diff --git a/.gitignore b/.gitignore index f2440b4f3dbdb548da0e5d9b336cdae1793a5505..4d3c44ec40e5b461853f5f108164fc2a470c0659 100644 --- a/.gitignore +++ b/.gitignore @@ -181,6 +181,8 @@ obproxy-tmp* src/.DS_Store unittest/.DS_Store ob_proxy_parser.output +.vscode/* +rpm/.dep_create deps/3rd/home deps/3rd/var deps/3rd/usr diff --git a/.secignore b/.secignore index 44c80e24eced26044eb36f85a4243b052434eabe..ebe3fd7830b880ea5b1093d14787e4367a313d63 100644 --- a/.secignore +++ b/.secignore @@ -42,7 +42,8 @@ http://www.quicklz.com/) http://www.goof.com/pcg/marc/liblzf.html) http://www.fastlz.org/ - http://stackoverflow.com/a/32095106/646947 + http://stackoverflow.com/* + https://stackoverflow.com/* http://fastcompression.blogspot.com/p/lz4.html https://groups.google.com/forum/# https://github.com/mcmilk/zstdmt diff --git a/build.sh b/build.sh index f1a82755cc9deccac824569dab33c73cacbf94e5..e5201ad28d612b83a9c0df88fe5f575189e6025b 100755 --- a/build.sh +++ b/build.sh @@ -73,14 +73,19 @@ function do_config() echo -e "\033[31m ===build debug version=== \033[0m" ;; xgcov) - # configure for release + # configure for gcov ./configure --with-gcc-version=9.3.0 --with-coverage=yes --enable-buildtime=no --enable-strip-ut=no --enable-silent-rules --enable-dlink-observer=no echo -e "\033[31m ===build gcov version=== \033[0m" ;; - xperf) - # configure for release - ./configure --with-gcc-version=9.3.0 --with-coverage=no --enable-buildtime=no --enable-strip-ut=no --enable-silent-rules --enable-dlink-observer=no --with-release --with-perf - echo -e "\033[31m ===build perf version=== \033[0m" + xasan) + # configure for asan + ./configure --with-gcc-version=9.3.0 --with-coverage=no --enable-buildtime=no --enable-strip-ut=no --enable-silent-rules --enable-dlink-observer=no --with-asan + echo -e "\033[31m ===build asan version=== \033[0m" + ;; + xso) + # configure for obproxy_so + ./configure --with-gcc-version=9.3.0 --with-coverage=no --enable-buildtime=no --enable-strip-ut=no --enable-silent-rules --enable-dlink-observer=no --with-release --with-so + echo -e "\033[31m ===build so version=== \033[0m" ;; *) # configure for release @@ -116,7 +121,7 @@ function do_rpm() cd ${TMP_DIR}/BUILD echo "[BUILD] make rpms..._prefix=${PREFIX} spec_file=${SPEC_FILE}" - rpmbuild --define "_topdir ${TMP_DIR}" --define "NAME ${PACKAGE}" --define "VERSION ${VERSION}" --define "_prefix ${PREFIX}" --define "RELEASE ${RELEASE}" -ba ${TOPDIR}/deps/3rd/${SPEC_FILE} || exit 2 + rpmbuild --define "_topdir ${TMP_DIR}" --define "NAME ${PACKAGE}" --define "VERSION ${VERSION}" --define "_prefix ${PREFIX}" --define "RELEASE ${RELEASE}" --define "rpm_path ${TOPDIR}" -ba ${TOPDIR}/deps/3rd/${SPEC_FILE} || exit 2 echo "[BUILD] make rpms done." cd ${TOPDIR} diff --git a/configure.ac b/configure.ac index 8fa3eee0ca15b227c155a963b1e171653083026a..8c3530a6e457882c5db279c624caf72f7b520155 100644 --- a/configure.ac +++ b/configure.ac @@ -1,10 +1,10 @@ AC_INIT([OceanBase], - [3.2.3.5], + [4.1.0.0], [wgs13579@gmail.com], [obproxy-ce], [http://oceanbase.taobao.org/]) - obapi_version="3.2.3.5" + obapi_version="4.1.0.0" AC_SUBST(obapi_version) AC_DISABLE_STATIC @@ -26,12 +26,12 @@ if test "$withval" = "yes"; then case "$host_cpu" in *aarch64* ) - AM_CXXFLAGS="-g -O2 -D_OB_VERSION=1000 -D_NO_EXCEPTION -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -DNDEBUG -D__USE_LARGEFILE64 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -Wall -Wextra -Wno-unused-parameter -Wformat -Wno-conversion -Wno-deprecated -Wno-invalid-offsetof -Wno-unused-result -Wno-format-security -finline-functions -fno-strict-aliasing -mtune=generic -Wno-psabi -Wno-sign-compare -Wno-class-memaccess -Wno-deprecated-copy -Wno-ignored-qualifiers -Wno-aligned-new -Wno-format-truncation -Wno-literal-suffix -Wno-format-overflow -Wno-stringop-truncation -Wno-memset-elt-size -Wno-cast-function-type -Wno-address-of-packed-member -fuse-ld=lld -ffunction-sections -Wl,--no-warn-symbol-ordering,--symbol-ordering-file,${ac_abs_confdir}/hotfuncs.txt" - AM_CFLAGS="-g -O2 -D_OB_VERSION=1000 -DCOMPATIBLE -D__USE_LARGEFILE64 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -DNDEBUG -finline-functions -fno-strict-aliasing -Wall -mtune=generic -Wno-psabi -Wno-sign-compare -fuse-ld=lld -ffunction-sections -Wl,--no-warn-symbol-ordering,--symbol-ordering-file,${ac_abs_confdir}/hotfuncs.txt" + AM_CXXFLAGS="-g -O2 -D_OB_VERSION=1000 -D_NO_EXCEPTION -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -DNDEBUG -D__USE_LARGEFILE64 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -Wall -Wextra -Wno-unused-parameter -Wformat -Wno-conversion -Wno-deprecated -Wno-invalid-offsetof -Wno-unused-result -Wno-format-security -finline-functions -fno-strict-aliasing -mtune=generic -march=armv8-a+crc -Wno-psabi -Wno-sign-compare -Wno-class-memaccess -Wno-deprecated-copy -Wno-ignored-qualifiers -Wno-aligned-new -Wno-format-truncation -Wno-literal-suffix -Wno-format-overflow -Wno-stringop-truncation -Wno-memset-elt-size -Wno-cast-function-type -Wno-address-of-packed-member -fno-omit-frame-pointer" + AM_CFLAGS="-g -O2 -D_OB_VERSION=1000 -DCOMPATIBLE -D__USE_LARGEFILE64 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -DNDEBUG -finline-functions -fno-strict-aliasing -Wall -mtune=generic -Wno-psabi -Wno-sign-compare" ;; * ) - AM_CXXFLAGS="-g -O2 -D_OB_VERSION=1000 -D_NO_EXCEPTION -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -DNDEBUG -D__USE_LARGEFILE64 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -Wall -Wextra -Wno-unused-parameter -Wformat -Wno-conversion -Wno-deprecated -Wno-invalid-offsetof -Wno-unused-result -Wno-format-security -finline-functions -fno-strict-aliasing -mtune=core2 -Wno-psabi -Wno-sign-compare -Wno-class-memaccess -Wno-deprecated-copy -Wno-ignored-qualifiers -Wno-aligned-new -Wno-format-truncation -Wno-literal-suffix -Wno-format-overflow -Wno-stringop-truncation -Wno-memset-elt-size -Wno-cast-function-type -Wno-address-of-packed-member -fuse-ld=lld -ffunction-sections -Wl,--no-warn-symbol-ordering,--symbol-ordering-file,${ac_abs_confdir}/hotfuncs.txt" - AM_CFLAGS="-g -O2 -D_OB_VERSION=1000 -DCOMPATIBLE -D__USE_LARGEFILE64 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -DNDEBUG -finline-functions -fno-strict-aliasing -Wall -mtune=core2 -Wno-psabi -Wno-sign-compare -fuse-ld=lld -ffunction-sections -Wl,--no-warn-symbol-ordering,--symbol-ordering-file,${ac_abs_confdir}/hotfuncs.txt" + AM_CXXFLAGS="-g -O2 -D_OB_VERSION=1000 -D_NO_EXCEPTION -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -DNDEBUG -D__USE_LARGEFILE64 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -Wall -Wextra -Wno-unused-parameter -Wformat -Wno-conversion -Wno-deprecated -Wno-invalid-offsetof -Wno-unused-result -Wno-format-security -finline-functions -fno-strict-aliasing -mtune=core2 -Wno-psabi -Wno-sign-compare -Wno-class-memaccess -Wno-deprecated-copy -Wno-ignored-qualifiers -Wno-aligned-new -Wno-format-truncation -Wno-literal-suffix -Wno-format-overflow -Wno-stringop-truncation -Wno-memset-elt-size -Wno-cast-function-type -Wno-address-of-packed-member -fno-omit-frame-pointer" + AM_CFLAGS="-g -O2 -D_OB_VERSION=1000 -DCOMPATIBLE -D__USE_LARGEFILE64 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -DNDEBUG -finline-functions -fno-strict-aliasing -Wall -mtune=core2 -Wno-psabi -Wno-sign-compare" ;; esac fi @@ -41,6 +41,26 @@ ] ) + AC_ARG_WITH([so], + AS_HELP_STRING([--with-so], + [with so support (default is NO)]), + [ + if test "$withval" = "yes"; then + support_so=yes + AM_CXXFLAGS="${AM_CXXFLAGS} -fPIC" + AM_CFLAGS="${AM_CFLAGS} -fPIC" + fi + ], + [support_so=no] + ) + + AM_CONDITIONAL([HAVE_SO], test x$support_so = xyes ) + + if test "$support_so" == "no"; then + AM_CXXFLAGS="${AM_CXXFLAGS} -fuse-ld=lld -ffunction-sections -Wl,--no-warn-symbol-ordering,--symbol-ordering-file,${ac_abs_confdir}/hotfuncs.txt" + AM_CFLAGS="${AM_CFLAGS} -fuse-ld=lld -ffunction-sections -Wl,--no-warn-symbol-ordering,--symbol-ordering-file,${ac_abs_confdir}/hotfuncs.txt" + fi + #check gcc version, add -Wno-ignored-qualifiers flag for gcc version greater than 4.3.0 GCC_VERSION=`$CC -dumpfullversion -dumpversion` if test $? -eq 0; then @@ -101,21 +121,16 @@ ], []) - AC_ARG_WITH([perf], - AS_HELP_STRING([--with-perf], - [with perf (default is NO)]), + AC_ARG_WITH([asan], + AS_HELP_STRING([--with-asan], + [with asan (default is NO)]), [ if test "$withval" = "yes"; then - # The following parameters are options for using gperftools, - # currently not using tcmalloc - # test_perf=yes - # AM_CXXFLAGS="${AM_CXXFLAGS} -D__NEED_PERF__" - # AM_LDFLAGS="${AM_LDFLAGS} -lprofiler" - AM_CXXFLAGS="${AM_CXXFLAGS} -fno-omit-frame-pointer" - AM_CFLAGS="${AM_CFLAGS} -fno-omit-frame-pointer" + AM_CXXFLAGS="${AM_CXXFLAGS} -fsanitize=address -fstack-protector-strong -fno-optimize-sibling-calls -fno-omit-frame-pointer -static-libasan -fno-var-tracking-assignments -fno-optimize-sibling-calls -fno-inline -DUSING_ASAN" + AM_CFLAGS="${AM_CFLAGS} -fsanitize=address -fstack-protector-strong -fno-optimize-sibling-calls -fno-omit-frame-pointer -static-libasan -fno-var-tracking-assignments -fno-optimize-sibling-calls -fno-inline -DUSING_ASAN" fi ], - [with_perf=no] + [with_asan=no] ) AC_ARG_WITH([5u-support], diff --git a/deps/3rd/obproxy.spec b/deps/3rd/obproxy.spec index 2fccee9d654062cb3170316d71ba64701b7ea286..03169a2ea7d038a9c02d3e8d75381c3ab761aec1 100644 --- a/deps/3rd/obproxy.spec +++ b/deps/3rd/obproxy.spec @@ -34,16 +34,29 @@ OceanBase Database Proxy %setup %build -./configure CXX=${CXX} CC=${CC} --with-gcc-version=9.3.0 RELEASEID=%{RELEASE} --prefix=%{_prefix} --with-test-case=no --with-release=yes --with-tblib-root=/opt/csr/common --with-easy-root=/usr --with-easy-lib-path=/usr/lib64 --with-svnfile --enable-shared=default --enable-silent-rules -mkdir -p unittest +mkdir -p lib +cp ${TOOLS_DIR}/lib64/libstdc++.so.6.0.28 lib/libstdc++.so.6 + +#./configure CXX=${CXX} CC=${CC} --with-gcc-version=9.3.0 --with-so --prefix=%{_prefix} --with-test-case=no --with-release=yes --with-tblib-root=/opt/csr/common --with-easy-root=/usr --with-easy-lib-path=/usr/lib64 --with-svnfile --enable-shared=default --enable-silent-rules CPU_CORES=`grep -c ^processor /proc/cpuinfo` MAKE_ARGS="-j $CPU_CORES" +#make $MAKE_ARGS +#cp src/obproxy/.libs/libobproxy_so.so.0.0.0 lib/libobproxy_so.so + +#make distclean >/dev/null 2>&1 +#find . -path ./tools/codestyle/astyle/build -prune -o -path ./doc -prune -o -name Makefile -exec rm -f {} \; +#find . -name .deps -prune -exec rm -rf {} \; + +./configure CXX=${CXX} CC=${CC} --with-gcc-version=9.3.0 RELEASEID=%{RELEASE} --prefix=%{_prefix} --with-test-case=no --with-release=yes --with-tblib-root=/opt/csr/common --with-easy-root=/usr --with-easy-lib-path=/usr/lib64 --with-svnfile --enable-shared=default --enable-silent-rules +mkdir -p unittest make $MAKE_ARGS %install make DESTDIR=$RPM_BUILD_ROOT install mkdir -p $RPM_BUILD_ROOT%{install_dir}/bin +mkdir -p $RPM_BUILD_ROOT%{install_dir}/lib cp src/obproxy/obproxy $RPM_BUILD_ROOT%{install_dir}/bin +cp -r lib/* $RPM_BUILD_ROOT%{install_dir}/lib cp script/deploy/obproxyd.sh $RPM_BUILD_ROOT%{install_dir}/bin %clean @@ -54,12 +67,19 @@ rm -rf $RPM_BUILD_ROOT %dir %{install_dir}/bin %{install_dir}/bin/obproxy %{install_dir}/bin/obproxyd.sh +%{install_dir}/lib/libstdc++.so.6 %pre rm -rf %{install_dir}/log rm -rf %{install_dir}/bin rm -rf %{install_dir}/etc rm -rf %{install_dir}/.conf +rm -rf /u01/obproxy/lib +mkdir -p /u01/obproxy/lib %post chown -R admin:admin %{install_dir} +ln -s %{install_dir}/lib/libobproxy_so.so /u01/obproxy/lib/libobproxy_so.so.0 +ln -s %{install_dir}/lib/libobproxy_so.so /u01/obproxy/lib/libobproxy_so.so +ln -s %{install_dir}/lib/libprotobuf.so.18 /u01/obproxy/lib/libprotobuf.so.18 +ln -s %{install_dir}/lib/libstdc++.so.6 /u01/obproxy/lib/libstdc++.so.6 diff --git a/deps/easy/src/io/easy_ssl.c b/deps/easy/src/io/easy_ssl.c index f7bfa8de593cf3e313f5a9819e1c82c8221f909e..e8e246c38a13f5ef70791b7e92d6836cb64e60f6 100644 --- a/deps/easy/src/io/easy_ssl.c +++ b/deps/easy/src/io/easy_ssl.c @@ -1601,14 +1601,6 @@ static int easy_ssl_dhparam(easy_ssl_ctx_t *ssl, char *file) DH *dh; BIO *bio; - /* - * -----BEGIN DH PARAMETERS----- - * MIGHAoGBALu8LcrYRnSQfEP89YDpz9vZWKP1aLQtSwju1OsPs1BMbAMCducQgAxc - * y7qokiYUxb7spWWl/fHSh6K8BJvmd4Bg6RqSp1fjBI9osHb302zI8pul34HcLKcl - * 7OZicMyaUDXYzs7vnqAnSmOrHlj6/UmI0PZdFGdX2gcd8EXP4WubAgEC - * -----END DH PARAMETERS----- - */ - static unsigned char dh1024_p[] = { 0xBB, 0xBC, 0x2D, 0xCA, 0xD8, 0x46, 0x74, 0x90, 0x7C, 0x43, 0xFC, 0xF5, 0x80, 0xE9, 0xCF, 0xDB, 0xD9, 0x58, 0xA3, 0xF5, 0x68, 0xB4, 0x2D, 0x4B, @@ -1677,19 +1669,6 @@ static int easy_ssl_dhparam_mysql(easy_ssl_ctx_t *ssl) { DH *dh; - /* - Diffie-Hellman key. - Generated using: >openssl dhparam -5 -C 2048 - - -----BEGIN DH PARAMETERS----- - MIIBCAKCAQEAil36wGZ2TmH6ysA3V1xtP4MKofXx5n88xq/aiybmGnReZMviCPEJ - 46+7VCktl/RZ5iaDH1XNG1dVQmznt9pu2G3usU+k1/VB4bQL4ZgW4u0Wzxh9PyXD - glm99I9Xyj4Z5PVE4MyAsxCRGA1kWQpD9/zKAegUBPLNqSo886Uqg9hmn8ksyU9E - BV5eAEciCuawh6V0O+Sj/C3cSfLhgA0GcXp3OqlmcDu6jS5gWjn3LdP1U0duVxMB - h/neTSCSvtce4CAMYMjKNVh9P1nu+2d9ZH2Od2xhRIqMTfAS1KTqF3VmSWzPFCjG - mjxx/bg6bOOjpgZapvB6ABWlWmRmAAWFtwIBBQ== - -----END DH PARAMETERS----- - */ static unsigned char dh2048_p[]= { 0x8A, 0x5D, 0xFA, 0xC0, 0x66, 0x76, 0x4E, 0x61, 0xFA, 0xCA, 0xC0, 0x37, diff --git a/rpm/obproxy-ce-VER.txt b/rpm/obproxy-ce-VER.txt index 281b514e00c9ebdf907e27efb45c908fbb136de3..16f4c78fd6a617adc9031d905fa2cbba5bdc1a29 100644 --- a/rpm/obproxy-ce-VER.txt +++ b/rpm/obproxy-ce-VER.txt @@ -1 +1 @@ -3.2.3.5 +4.1.0.0 diff --git a/script/deploy/obproxyd.sh b/script/deploy/obproxyd.sh index 9c7c47ffa5be1e8ecaf74792798b49d6984fae73..75d45dacf153ad77ea5cd00c735e714c7787c48f 100755 --- a/script/deploy/obproxyd.sh +++ b/script/deploy/obproxyd.sh @@ -147,7 +147,7 @@ function check_opt() OBPROXY_OPT_LOCAL="${OBPROXY_OPT_LOCAL},$OBPROXY_EXTRA_OPT" fi - OBPROXY_OPT_LOCAL=",enable_cached_server=true,enable_get_rslist_remote=true,monitor_stat_dump_interval=1s,enable_qos=true,enable_standby=false,query_digest_time_threshold=2ms,monitor_cost_ms_unit=true,enable_strict_kernel_release=false,enable_proxy_scramble=true,work_thread_num=$WORK_THREAD_NUM,proxy_mem_limited='2G',log_dir_size_threshold=10G${OBPROXY_OPT_LOCAL}" + OBPROXY_OPT_LOCAL=",server_detect_mode=0,enable_primary_zone=false,enable_cached_server=true,enable_get_rslist_remote=true,monitor_stat_dump_interval=1s,enable_qos=true,enable_standby=false,query_digest_time_threshold=2ms,monitor_cost_ms_unit=true,enable_strict_kernel_release=false,enable_proxy_scramble=true,work_thread_num=$WORK_THREAD_NUM,proxy_mem_limited='2G',log_dir_size_threshold=10G${OBPROXY_OPT_LOCAL}" } # change to the path where this script locates. diff --git a/src/common/cache/ob_kv_storecache.h b/src/common/cache/ob_kv_storecache.h index a8fd09e9d811c1741c9c92103b0ca1b3c0985ec8..dc19d62c9a3cd9136026c16740c3130eb6630da0 100644 --- a/src/common/cache/ob_kv_storecache.h +++ b/src/common/cache/ob_kv_storecache.h @@ -131,8 +131,10 @@ enum ObKVCachePolicy struct ObKVCacheConfig { public: - ObKVCacheConfig(); - void reset(); + /* this function is defined for c driver client compile */ + ObKVCacheConfig() {}; + /* this function is defined for c driver client compile */ + void reset() {}; bool is_valid_; int64_t priority_; char cache_name_[MAX_CACHE_NAME_LENGTH]; @@ -267,9 +269,12 @@ class ObKVCacheInstMap; class ObKVCacheInstHandle { public: - ObKVCacheInstHandle(); - virtual ~ObKVCacheInstHandle(); - void reset(); + /* this function is defined for c driver client compile */ + ObKVCacheInstHandle() {}; + /* this function is defined for c driver client compile */ + virtual ~ObKVCacheInstHandle() {}; + /* this function is defined for c driver client compile */ + void reset() {}; inline ObKVCacheInst *get_inst() { return inst_; } private: friend class ObKVCacheInstMap; @@ -291,8 +296,10 @@ struct ObKVCacheInfo class ObKVCacheInstMap { public: - ObKVCacheInstMap(); - virtual ~ObKVCacheInstMap(); + /* this function is defined for c driver client compile */ + ObKVCacheInstMap() {}; + /* this function is defined for c driver client compile */ + virtual ~ObKVCacheInstMap() {}; int init(const int64_t max_entry_cnt, const ObKVCacheConfig *configs); void destroy(); int get_cache_inst( @@ -319,8 +326,10 @@ private: class ObKVCacheStore { public: - ObKVCacheStore(); - virtual ~ObKVCacheStore(); + /* this function is defined for c driver client compile */ + ObKVCacheStore() {}; + /* this function is defined for c driver client compile */ + virtual ~ObKVCacheStore() {}; int init(ObKVCacheInstMap &insts, const int64_t max_cache_size, const int64_t block_size); void destroy(); int set_priority(const int64_t cache_id, const int64_t old_priority, const int64_t new_priority); @@ -394,8 +403,10 @@ private: class ObKVCacheMap { public: - ObKVCacheMap(); - virtual ~ObKVCacheMap(); + /* this function is defined for c driver client compile */ + ObKVCacheMap() {}; + /* this function is defined for c driver client compile */ + virtual ~ObKVCacheMap() {}; int init(const int64_t bucket_num, ObKVCacheStore *store); void destroy(); int erase_all(); @@ -452,19 +463,23 @@ class ObKVCacheHandle; class ObKVGlobalCache { public: - static ObKVGlobalCache &get_instance(); + /* this function is defined for c driver client compile */ + static ObKVGlobalCache &get_instance() {return *(new ObKVGlobalCache());}; int init(const int64_t bucket_num = DEFAULT_BUCKET_NUM, const int64_t max_cache_size = DEFAULT_MAX_CACHE_SIZE, const int64_t block_size = common::OB_MALLOC_BIG_BLOCK_SIZE); void destroy(); - void reload_priority(); + /* this function is defined for c driver client compile */ + void reload_priority() {}; int get_tenant_cache_info(const uint64_t tenant_id, ObIArray &infos); int get_all_cache_info(ObIArray &infos); private: template friend class ObKVCache; friend class ObKVCacheHandle; - ObKVGlobalCache(); - virtual ~ObKVGlobalCache(); + /* this function is defined for c driver client compile */ + ObKVGlobalCache() {} + /* this function is defined for c driver client compile */ + virtual ~ObKVGlobalCache() {} int register_cache(const char *cache_name, const int64_t priority, int64_t &cache_id); void deregister_cache(const int64_t cache_id); int set_priority(const int64_t cache_id, const int64_t priority); @@ -482,7 +497,8 @@ private: ObKVMemBlockHandle *&mb_handle); int erase(const int64_t cache_id, const ObIKVCacheKey &key); void revert(ObKVMemBlockHandle *mb_handle); - void wash(); + /* this function is defined for c driver client compile */ + void wash() {}; private: static const int64_t DEFAULT_BUCKET_NUM = 10000000L; static const int64_t DEFAULT_MAX_CACHE_SIZE = 1024L * 1024L * 1024L * 1024L; //1T diff --git a/src/common/mysql_proxy/ob_isql_client.h b/src/common/mysql_proxy/ob_isql_client.h index cd1293fec362622dd2f100250479cbe496068628..65dc7be30cd76f7ba4ae399e1dcdc039158ad799 100644 --- a/src/common/mysql_proxy/ob_isql_client.h +++ b/src/common/mysql_proxy/ob_isql_client.h @@ -58,10 +58,13 @@ public: public: friend class ObISQLClient; - ReadResult(); - virtual ~ReadResult(); + /* this function is defined for c driver client compile */ + ReadResult() {} + /* this function is defined for c driver client compile */ + virtual ~ReadResult() {} - sqlclient::ObMySQLResult *mysql_result(); + /* this function is defined for c driver client compile */ + sqlclient::ObMySQLResult *mysql_result() {return nullptr;} // FIXME : remove sqlclient::ObMySQLResult *get_result() { return mysql_result(); } diff --git a/src/common/ob_obj_cast.cpp b/src/common/ob_obj_cast.cpp index 1c29b365956736460ca48cf67059420836ec3ec4..684d180f817ab579ba51edc1506e37f725ca2d5c 100644 --- a/src/common/ob_obj_cast.cpp +++ b/src/common/ob_obj_cast.cpp @@ -1563,7 +1563,7 @@ static int double_float(const ObObjType expect_type, ObObjCastParams ¶ms, ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); - } else if (CAST_FAIL(real_range_check(expect_type, in.get_double(), value))) { + } else if (!lib::is_oracle_mode() && CAST_FAIL(real_range_check(expect_type, in.get_double(), value))) { } else { out.set_float(expect_type, value); } @@ -2975,17 +2975,30 @@ static int string_datetime(const ObObjType expect_type, ObObjCastParams ¶ms, { int ret = OB_SUCCESS; ObScale res_scale = -1; + ObString utf8_string; + if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) || ObDateTimeTC != ob_obj_type_class(expect_type))) { - ret = OB_ERR_UNEXPECTED; - LOG_ERROR("invalid input type", - K(ret), K(in), K(expect_type)); + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("invalid input type", + K(ret), K(in), K(expect_type)); + } else if (lib::is_oracle_mode() && in.is_blob()) { + ret = OB_NOT_SUPPORTED; + LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type)); + LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type"); + } else if (OB_FAIL(convert_string_collation(in.get_string(), in.get_collation_type(), utf8_string, ObCharset::get_system_collation(), params))) { + LOG_WARN("convert_string_collation", K(ret)); } else { - const ObTimeZoneInfo *tz_info = (ObTimestampType == expect_type) ? params.dtc_params_.tz_info_ : NULL; int64_t value = 0; - if (CAST_FAIL(ObTimeConverter::str_to_datetime(in.get_string(), tz_info, value, &res_scale))) { + ObTimeConvertCtx cvrt_ctx(params.dtc_params_.tz_info_, ObTimestampType == expect_type); + if (lib::is_oracle_mode()) { + cvrt_ctx.oracle_nls_format_ = params.dtc_params_.get_nls_format(ObDateTimeType); + CAST_FAIL(ObTimeConverter::str_to_date_oracle(utf8_string, cvrt_ctx, value)); } else { + CAST_FAIL(ObTimeConverter::str_to_datetime(utf8_string, cvrt_ctx.tz_info_, value, &res_scale)); + } + if(OB_SUCC(ret)) { SET_RES_DATETIME(out); } } @@ -3067,29 +3080,56 @@ static int string_string(const ObObjType expect_type, ObObjCastParams ¶ms, ObString str; in.get_string(str); if (0 != str.length() - && CS_TYPE_BINARY != in.get_collation_type() - && CS_TYPE_BINARY != params.dest_collation_ + // in mysql mode if charset is binary then not convert + // in oracle mode if charset is binary then convert + && ((CS_TYPE_BINARY != in.get_collation_type() && CS_TYPE_BINARY != params.dest_collation_) + || lib::is_oracle_mode()) && CS_TYPE_INVALID != in.get_collation_type() && CS_TYPE_INVALID != params.dest_collation_ && (ObCharset::charset_type_by_coll(in.get_collation_type()) != ObCharset::charset_type_by_coll(params.dest_collation_))) { char *buf = NULL; - // buf_len is related to the encoding length, gbk uses 2 bytes to encode a character, utf8mb4 uses 1 to 4 bytes - // CharConvertFactorNum is a multiple of the requested memory size - const int32_t CharConvertFactorNum = 2; + const int32_t CharConvertFactorNum = 4; int32_t buf_len = str.length() * CharConvertFactorNum; uint32_t result_len = 0; if (OB_UNLIKELY(NULL == (buf = static_cast(params.alloc(buf_len))))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("alloc memory failed", K(ret)); - } else if (OB_FAIL(ObCharset::charset_convert(in.get_collation_type(), - str.ptr(), - str.length(), - params.dest_collation_, - buf, - buf_len, - result_len))) { - LOG_WARN("charset convert failed", K(ret), K(in.get_collation_type()), K(params.dest_collation_)); + } else { + ret = ObCharset::charset_convert(in.get_collation_type(), + str.ptr(), + str.length(), + params.dest_collation_, + buf, + buf_len, + result_len); + if (OB_SUCCESS != ret) { + int32_t str_offset = 0; + int32_t buf_offset = 0; + ObString question_mark("?"); + while (str_offset < str.length() && buf_offset + question_mark.length() <= buf_len) { + int64_t offset = ObCharset::charpos(in.get_collation_type(), str.ptr() + str_offset, + str.length() - str_offset, 1); + ret = ObCharset::charset_convert(in.get_collation_type(), str.ptr() + str_offset, + static_cast(offset), params.dest_collation_, buf + buf_offset, buf_len - buf_offset, result_len); + str_offset += static_cast(offset); + if (OB_SUCCESS == ret && result_len > 0) { + buf_offset += result_len; + } else { + MEMCPY(buf + buf_offset, question_mark.ptr(), question_mark.length()); + buf_offset += question_mark.length(); + } + } + if (str_offset < str.length()) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("size overflow", K(ret), K(str)); + } else { + // The log is printed here to remind that there are characters that fail to convert and are replaced by '?' + LOG_DEBUG("charset convert failed", K(ret), K(in.get_collation_type()), K(params.dest_collation_)); + result_len = static_cast(buf_offset); + ret = OB_SUCCESS; + } + } } LOG_DEBUG("convert result", K(str), "result", ObHexEscapeSqlStr(ObString(result_len, buf))); @@ -4125,9 +4165,17 @@ int obj_accuracy_check(ObCastCtx &cast_ctx, const ObObj *&res_obj) { int ret = OB_SUCCESS; + bool valid_accuracy = true; + ObObjType type = obj.get_type(); + if (ob_is_number_tc(type) || ob_is_double_tc(type) || ob_is_float_tc(type)) { + if (accuracy.precision_ == -1 || accuracy.scale_ == -1) { + valid_accuracy = false; // invalid accuracy + } + } - if (accuracy.is_valid()) { - LOG_DEBUG("obj_accuracy_check before", K(obj), K(accuracy), K(cs_type)); + LOG_DEBUG("obj_accuracy_check before", K(obj), K(accuracy), K(cs_type), K(valid_accuracy)); + + if (valid_accuracy && accuracy.is_valid()) { switch (obj.get_type_class()) { case ObFloatTC: { ret = float_range_check(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_); diff --git a/src/common/ob_obj_type.h b/src/common/ob_obj_type.h index 625e4bba80bc3d16da38d442fa7e2d8466c3d60f..4e034eb648fd9b9f94435a4aec03f7c08b5fe005 100644 --- a/src/common/ob_obj_type.h +++ b/src/common/ob_obj_type.h @@ -90,6 +90,8 @@ enum ObObjType ObNCharType = 44, // nchar ObURowIDType = 45, // UROWID ObLobType = 46, // Oracle Lob + ObJsonType = 47, // Json Type + ObGeometryType = 48, // Geometry type ObMaxType // invalid type, or count of obj type }; @@ -295,7 +297,7 @@ inline bool ob_is_blob(const ObObjType type, const ObCollationType cs_type) inline bool is_obj_type_supported(ObObjType type) { return (type > ObNullType && type < ObUnknownType) - || ob_is_otimestamp_type(type); + || ob_is_otimestamp_type(type) || ob_is_number_tc(type); } // to_string adapter diff --git a/src/common/ob_object.cpp b/src/common/ob_object.cpp index 33b29d482f78d3bb1c4f27332c56ca498f9004d9..774296abd56a275b6d0305010d091cf1767e7a07 100644 --- a/src/common/ob_object.cpp +++ b/src/common/ob_object.cpp @@ -249,7 +249,7 @@ int64_t ObObj::get_deep_copy_size() const int64_t ret = 0; if (is_string_type()) { ret += val_len_; - } else if (ObNumberType == meta_.get_type() || ObUNumberType == meta_.get_type()) { + } else if (ob_is_number_tc(get_type())) { ret += (sizeof(uint32_t) * nmb_desc_.len_); } return ret; @@ -443,7 +443,7 @@ ObObjTypeFuncs OBJ_FUNCS[ObMaxType] = DEF_FUNC_ENTRY(ObRawType), // 39, raw DEF_FUNC_ENTRY(ObNullType), // 40 DEF_FUNC_ENTRY(ObNullType), // 41 - DEF_FUNC_ENTRY(ObNullType), // 42 + DEF_FUNC_ENTRY(ObNumberFloatType), // 42 DEF_FUNC_ENTRY(ObNVarchar2Type), // 43, nvarchar2 DEF_FUNC_ENTRY(ObNCharType), // 44, nchar }; diff --git a/src/common/ob_object.h b/src/common/ob_object.h index 8db10adb4d769215931aa6bfdc00b068592ccc57..f29788d33c3d651a69d5fc03ecf830c7b30d2ae3 100644 --- a/src/common/ob_object.h +++ b/src/common/ob_object.h @@ -383,6 +383,13 @@ public: void set_time_value(const int64_t value); void set_year_value(const uint8_t value); + void set_timestamp_tz(const int64_t time_us, const uint32_t time_ctx_desc) { set_otimestamp_value(ObTimestampTZType, time_us, time_ctx_desc); } + void set_timestamp_ltz(const int64_t time_us, const uint16_t time_desc) { set_otimestamp_value(ObTimestampLTZType, time_us, time_desc); } + void set_timestamp_nano(const int64_t time_us, const uint16_t time_desc) { set_otimestamp_value(ObTimestampNanoType, time_us, time_desc); } + void set_timestamp_tz(const ObOTimestampData &value) { set_otimestamp_value(ObTimestampTZType, value); } + void set_timestamp_ltz(const ObOTimestampData &value) { set_otimestamp_value(ObTimestampLTZType, value); } + void set_timestamp_nano(const ObOTimestampData &value) { set_otimestamp_value(ObTimestampNanoType, value); } + void set_string(const ObObjType type, const char *ptr, const ObString::obstr_size_t size); void set_string(const ObObjType type, const ObString &value); void set_varchar(const ObString &value); diff --git a/src/common/ob_partition_key.h b/src/common/ob_partition_key.h index 426dc9575e122e99bd560d2c90e04b9596474c57..0947578e0677eec752de2d2fccfcd0bbbbf84a8c 100644 --- a/src/common/ob_partition_key.h +++ b/src/common/ob_partition_key.h @@ -49,8 +49,10 @@ public: int init(const uint64_t table_id, const int32_t partition_idx, const int32_t partition_cnt); int parse(const char* str); - void reset(); - bool is_valid() const; + /* this function is defined for c driver client compile */ + void reset() {}; + /* this function is defined for c driver client compile */ + bool is_valid() const {return true;}; uint64_t hash() const; uint64_t inner_hash() const; int compare(const ObPartitionKey &other) const; diff --git a/src/common/ob_queue_thread.h b/src/common/ob_queue_thread.h index 243fd6e1a377e0c299e58f41506c82a8b02e78ac..22618a17c25405af5bb2ca7d583fe0ae4dfdf957 100644 --- a/src/common/ob_queue_thread.h +++ b/src/common/ob_queue_thread.h @@ -40,11 +40,19 @@ class ObCond static const int64_t SPIN_WAIT_NUM = 0; static const int64_t BUSY_INTERVAL = 1000; public: - explicit ObCond(const int64_t spin_wait_num = SPIN_WAIT_NUM); - ~ObCond(); + /* this function is defined for c driver client compile */ + explicit ObCond(const int64_t spin_wait_num = SPIN_WAIT_NUM) :spin_wait_num_(spin_wait_num) {} + /* this function is defined for c driver client compile */ + ~ObCond() {} public: - void signal(); - int timedwait(const int64_t time_us); + /* this function is defined for c driver client compile */ + void signal() {} + /* this function is defined for c driver client compile */ + int timedwait(const int64_t time_us) + { + UNUSED(time_us); + return OB_NOT_IMPLEMENT; + } int wait(); private: const int64_t spin_wait_num_; diff --git a/src/common/ob_range2.h b/src/common/ob_range2.h index f208a81b9a1cf36821a81e580cabd7e52ab63999..c41c12f0299e44138a3e5b20b91793dbfb7d48da 100644 --- a/src/common/ob_range2.h +++ b/src/common/ob_range2.h @@ -19,6 +19,8 @@ #include "common/ob_range.h" #include "lib/utility/utility.h" #include "lib/regex/ob_regex.h" +#include "lib/allocator/ob_allocator.h" +#include "obproxy/opsql/expr_parser/ob_expr_parse_result.h" namespace oceanbase @@ -100,6 +102,45 @@ public: return ret; } + int build_row_key(int64_t columns_num, ObIAllocator &allocator) { + // build row key like (min, min, min : max, max, max) + int ret = OB_SUCCESS; + if (columns_num < 0 || columns_num > OBPROXY_MAX_PART_LEVEL) { + ret = OB_INVALID_ARGUMENT; + COMMON_LOG(WARN, "invalid", K(columns_num)); + } else { + void *start_objs_buf = NULL; + void *end_objs_buf = NULL; + if (OB_ISNULL((start_objs_buf = allocator.alloc(sizeof(ObObj) * columns_num))) && columns_num != 0) { + ret = OB_ALLOCATE_MEMORY_FAILED; + COMMON_LOG(WARN, "fail to alloc new obj", K(ret), K(columns_num)); + } else if (OB_ISNULL(end_objs_buf = allocator.alloc(sizeof(ObObj) * columns_num)) && columns_num !=0) { + ret = OB_ALLOCATE_MEMORY_FAILED; + COMMON_LOG(WARN, "fail to alloc new obj", K(ret), K(columns_num)); + } else { + for (int i = 0; OB_SUCC(ret) && i < columns_num; i++) { + ObObj *start = NULL; + ObObj *end = NULL; + if (OB_ISNULL(start = new (reinterpret_cast(start_objs_buf) + i) ObObj())) { + ret = OB_ERR_UNEXPECTED; + COMMON_LOG(WARN, "failed to do placement new", K(start_objs_buf), K(ret)); + } else if (OB_ISNULL(end = new (reinterpret_cast(end_objs_buf) + i) ObObj())) { + ret = OB_ERR_UNEXPECTED; + COMMON_LOG(WARN, "failed to do placement new", K(end_objs_buf), K(ret)); + } else { + start->set_min_value(); + end->set_max_value(); + } + } + if (OB_SUCC(ret)) { + start_key_.assign(reinterpret_cast(start_objs_buf), columns_num); + end_key_.assign(reinterpret_cast(end_objs_buf), columns_num); + } + } + } + return ret; + } + // new compare func for tablet.range and scan_param.range inline int compare_with_endkey2(const ObNewRange &r) const { diff --git a/src/common/obsm_utils.cpp b/src/common/obsm_utils.cpp index db2a841c2e7e6cedabe81ab099c764ad2c3138b3..6ecb0e8de77fac220e4a200a428f0a6d9b54d539 100644 --- a/src/common/obsm_utils.cpp +++ b/src/common/obsm_utils.cpp @@ -307,6 +307,15 @@ int ObSMUtils::get_ob_type(ObObjType &ob_type, EMySQLFieldType mysql_type) case OB_MYSQL_TYPE_COMPLEX: ob_type = ObExtendType; break; + case OB_MYSQL_TYPE_OB_UROWID: + ob_type = ObURowIDType; + break; + case OB_MYSQL_TYPE_JSON: + ob_type = ObJsonType; + break; + case OB_MYSQL_TYPE_GEOMETRY: + ob_type = ObGeometryType; + break; default: _OB_LOG(WARN, "unsupport MySQL type %d", mysql_type); ret = OB_OBJ_TYPE_ERROR; diff --git a/src/lib/Makemodule.am b/src/lib/Makemodule.am index fab2bb59f4fe7ad0ae6fd7eb5b4b9d33b3fc637f..a828a2be8e2f2fa2652c55e7eaaaa1f132fb8b10 100644 --- a/src/lib/Makemodule.am +++ b/src/lib/Makemodule.am @@ -40,9 +40,16 @@ lib/charset/ob_charset.cpp\ lib/charset/ob_ctype.h\ lib/charset/ob_ctype.c\ lib/charset/ob_ctype_utf8.c\ +lib/charset/ob_ctype_gb18030.cc\ +lib/charset/ob_ctype_gbk.c\ +lib/charset/ob_ctype_utf16.c\ +lib/charset/ob_ctype_uca.c\ lib/charset/ob_ctype_mb.c\ lib/charset/ob_ctype_bin.c\ +lib/charset/ob_ctype_simple.c\ +lib/charset/ob_ctype_latin1.c\ lib/charset/ob_mysql_global.h\ +lib/charset/ob_config.h\ lib/charset/ob_dtoa.h\ lib/charset/ob_dtoa.c\ lib/charset/ob_uctype.h\ @@ -151,6 +158,7 @@ lib/oblog/ob_trace_log.h\ lib/oblog/ob_trace_log.cpp\ lib/oblog/ob_warning_buffer.h\ lib/oblog/ob_warning_buffer.cpp\ +lib/oblog/ob_simple_trace.h\ lib/queue/ob_dedup_queue.h\ lib/queue/ob_dedup_queue.cpp\ lib/queue/ob_fixed_queue.h\ @@ -207,6 +215,10 @@ lib/utility/ob_template_utils.h\ lib/utility/serialization.h\ lib/utility/ob_unify_serialize.h\ lib/utility/ob_serialization_helper.h\ +lib/utility/ob_2_0_full_link_trace_util.h\ +lib/utility/ob_2_0_full_link_trace_util.cpp\ +lib/utility/ob_2_0_full_link_trace_info.h\ +lib/utility/ob_2_0_full_link_trace_info.cpp\ lib/net/ob_addr.h\ lib/net/ob_addr.cpp\ lib/net/tbnetutil.cpp\ @@ -226,6 +238,9 @@ lib/stat/ob_stat_template.h\ lib/stat/ob_di_list.h\ lib/stat/ob_di_tls.h\ lib/trace/ob_trace_event.h\ +lib/trace/ob_trace.h\ +lib/trace/ob_trace.cpp\ +lib/trace/ob_trace_def.h\ lib/profile/ob_trace_id.h\ lib/wait_event/ob_wait_class.h\ lib/wait_event/ob_wait_event.h\ diff --git a/src/lib/alloc/malloc_hook.cpp b/src/lib/alloc/malloc_hook.cpp index 18a9949625fcdc00b029acf15ebdc7ab102dfae1..b7574b533a22debda86f106ba92f046e14166fc9 100644 --- a/src/lib/alloc/malloc_hook.cpp +++ b/src/lib/alloc/malloc_hook.cpp @@ -28,6 +28,8 @@ using namespace oceanbase::lib; EXTERN_C_BEGIN +#ifndef USING_ASAN + extern void *__libc_malloc(size_t size); extern void __libc_free(void *ptr); extern void *__libc_realloc(void *ptr, size_t size); @@ -290,4 +292,6 @@ int posix_memalign(void **memptr, size_t alignment, size_t size) return err; } +#endif + EXTERN_C_END diff --git a/src/lib/allocator/ob_concurrent_fifo_allocator.h b/src/lib/allocator/ob_concurrent_fifo_allocator.h index 10c0cdd33c2e218aff91ef6cf1dca8c768f05fd0..496d747a23637bb0b2fadd050109af7b17ed508b 100644 --- a/src/lib/allocator/ob_concurrent_fifo_allocator.h +++ b/src/lib/allocator/ob_concurrent_fifo_allocator.h @@ -21,17 +21,36 @@ namespace common class ObConcurrentFIFOAllocator : public common::ObIAllocator { public: - ObConcurrentFIFOAllocator(); - virtual ~ObConcurrentFIFOAllocator(); + /* this function is defined for c driver client compile */ + ObConcurrentFIFOAllocator() {}; + /* this function is defined for c driver client compile */ + virtual ~ObConcurrentFIFOAllocator() {}; public: + /* this function is defined for c driver client compile */ int init(const int64_t total_limit, const int64_t hold_limit, - const int64_t page_size); - void destroy(); + const int64_t page_size) + { + UNUSED(total_limit); + UNUSED(hold_limit); + UNUSED(page_size); + return OB_NOT_IMPLEMENT; + } + /* this function is defined for c driver client compile */ + void destroy() {}; public: void set_mod_id(const int64_t mod_id); - void *alloc(const int64_t size); - void free(void *ptr); + /* this function is defined for c driver client compile */ + void *alloc(const int64_t size) + { + UNUSED(size); + return nullptr; + } + /* this function is defined for c driver client compile */ + void free(void *ptr) + { + UNUSED(ptr); + } int64_t allocated(); int64_t hold() const {return 0;} int64_t get_direct_alloc_count(); diff --git a/src/lib/allocator/ob_fifo_allocator.h b/src/lib/allocator/ob_fifo_allocator.h index 2db3b588ba8b77f7d06011f7a78ccd6da65a75df..c57b38df2ef65f6aecf0b2ad3b97809c75dd7b42 100644 --- a/src/lib/allocator/ob_fifo_allocator.h +++ b/src/lib/allocator/ob_fifo_allocator.h @@ -89,16 +89,26 @@ private: static const int64_t ALREADY_FREE = 0xf5eebef0; static const int64_t SPECIAL_FLAG = -1; public: - ObFIFOAllocator(); - ~ObFIFOAllocator(); - + /* this function is defined for c driver client compile */ + ObFIFOAllocator() {}; + /* this function is defined for c driver client compile */ + ~ObFIFOAllocator() {}; + + /* this function is defined for c driver client compile */ int init(ObIAllocator *allocator, const int64_t page_size, - const int64_t page_hold_limit = 32); - void reset(); + const int64_t page_hold_limit = 32) + { + UNUSED(allocator); + UNUSED(page_size); + UNUSED(page_hold_limit); + return OB_NOT_IMPLEMENT; + } + /* this function is defined for c driver client compile */ + void reset() { /* not support */ } void reuse() { /* not support */ } - void *alloc(const int64_t size); + void *alloc(const int64_t size) { UNUSED(size); return NULL; } void *alloc_align(const int64_t size, const int64_t align); - void free(void *p); + void free(void *p) { UNUSED(p); } void set_mod_id(int64_t mod_id); inline int64_t used() const diff --git a/src/lib/allocator/ob_lf_fifo_allocator.h b/src/lib/allocator/ob_lf_fifo_allocator.h index 477ef1c4395001eccce5d06af98222de8f3b4199..d8b78cdf7b0296fa23ad335564942b371b58a1c7 100644 --- a/src/lib/allocator/ob_lf_fifo_allocator.h +++ b/src/lib/allocator/ob_lf_fifo_allocator.h @@ -54,8 +54,10 @@ private: class ObLfFIFOAllocator : public common::ObIAllocator { public: - ObLfFIFOAllocator(); - virtual ~ObLfFIFOAllocator(); + /* this function is defined for c driver client compile */ + ObLfFIFOAllocator() {} + /* this function is defined for c driver client compile */ + virtual ~ObLfFIFOAllocator() {} public: int init(const int64_t page_size, const int64_t mod_id, @@ -64,8 +66,9 @@ public: const int64_t total_limit = INT64_MAX); void destroy(); public: - void *alloc(const int64_t size); - void free(void *ptr); + /* this function is defined for c driver client compile */ + void *alloc(const int64_t size) { UNUSED(size); return NULL; } + void free(void *ptr) { UNUSED(ptr); } bool is_fragment(void *ptr); int64_t allocated() { return allocated_size_; } void set_mod_id(const int64_t mod_id) { mem_attr_.mod_id_ = mod_id; } diff --git a/src/lib/allocator/ob_malloc.cpp b/src/lib/allocator/ob_malloc.cpp index b5f32cd12c93ad04131f97769d45f66e9d1e5cd0..87b52a3ccaaaff58bd9ea3460a08568699596bcf 100644 --- a/src/lib/allocator/ob_malloc.cpp +++ b/src/lib/allocator/ob_malloc.cpp @@ -15,6 +15,7 @@ #include "lib/thread_local/ob_tsi_factory.h" #include "lib/utility/utility.h" #include +#include "obutils/ob_proxy_config.h" #ifdef __OB_MTRACE__ #include #endif diff --git a/src/lib/allocator/ob_mod_define.h b/src/lib/allocator/ob_mod_define.h index 9be908f848173e1ebe0f2c8ef524f9304e6ff1c0..9ff075be7bd8a9ab9a270124b17dc6243a7f4509 100644 --- a/src/lib/allocator/ob_mod_define.h +++ b/src/lib/allocator/ob_mod_define.h @@ -235,6 +235,7 @@ MOD_ITEM_DEF(OB_PROXY_QOS) MOD_ITEM_DEF(OB_PROXY_SSL_RELATED) MOD_ITEM_DEF(OB_PROXY_CONFIG_TABLE) MOD_ITEM_DEF(OB_PROMETHEUS_RELATED) +MOD_ITEM_DEF(OB_PROXY_SESS_SYNC) //mergeservermodules MOD_ITEM_DEF(OB_MS_CELL_ARRAY) diff --git a/src/lib/charset/ob_charset.cpp b/src/lib/charset/ob_charset.cpp index 9bef8250320a78660fc0fc0ca770ebdac7eefa2b..2f786eba4128ed10818cc52754fc093df5ea522a 100644 --- a/src/lib/charset/ob_charset.cpp +++ b/src/lib/charset/ob_charset.cpp @@ -22,7 +22,11 @@ namespace common const ObCharsetWrapper ObCharset::charset_wrap_arr_[CHARSET_WRAPPER_COUNT] = { {CHARSET_BINARY, "Binary pseudo charset", CS_TYPE_BINARY, 1}, - {CHARSET_UTF8MB4, "UTF-8 Unicode", CS_TYPE_UTF8MB4_GENERAL_CI, 4} + {CHARSET_UTF8MB4, "UTF-8 Unicode", CS_TYPE_UTF8MB4_GENERAL_CI, 4}, + {CHARSET_GBK, "GBK charset", CS_TYPE_GBK_CHINESE_CI, 2}, + {CHARSET_UTF16, "UTF-16 Unicode", CS_TYPE_UTF16_GENERAL_CI, 2}, + {CHARSET_GB18030, "GB18030 charset", CS_TYPE_GB18030_CHINESE_CI, 4}, + {CHARSET_LATIN1, "cp1252 West European", CS_TYPE_LATIN1_SWEDISH_CI, 1} }; const ObCollationWrapper ObCharset::collation_wrap_arr_[COLLATION_WRAPPER_COUNT] = @@ -30,21 +34,63 @@ const ObCollationWrapper ObCharset::collation_wrap_arr_[COLLATION_WRAPPER_COUNT] {CS_TYPE_UTF8MB4_GENERAL_CI, CHARSET_UTF8MB4, CS_TYPE_UTF8MB4_GENERAL_CI, true, true, 1}, {CS_TYPE_UTF8MB4_BIN, CHARSET_UTF8MB4, CS_TYPE_UTF8MB4_BIN, false, true, 1}, {CS_TYPE_BINARY, CHARSET_BINARY, CS_TYPE_BINARY, true, true, 1}, + {CS_TYPE_GBK_CHINESE_CI, CHARSET_GBK, CS_TYPE_GBK_CHINESE_CI, true, true, 1}, + {CS_TYPE_GBK_BIN, CHARSET_GBK, CS_TYPE_GBK_BIN, false, true, 1}, + {CS_TYPE_UTF16_GENERAL_CI, CHARSET_UTF16, CS_TYPE_UTF16_GENERAL_CI, true, true, 1}, + {CS_TYPE_UTF16_BIN, CHARSET_UTF16, CS_TYPE_UTF16_BIN, false, true, 1}, + {CS_TYPE_INVALID, CHARSET_INVALID, CS_TYPE_INVALID, false, false, 1}, + {CS_TYPE_INVALID, CHARSET_INVALID, CS_TYPE_INVALID, false, false, 1}, + {CS_TYPE_GB18030_CHINESE_CI, CHARSET_GB18030, CS_TYPE_GB18030_CHINESE_CI, true, true, 1}, + {CS_TYPE_GB18030_BIN, CHARSET_GB18030, CS_TYPE_GB18030_BIN, false, true, 1}, + {CS_TYPE_LATIN1_SWEDISH_CI, CHARSET_LATIN1, CS_TYPE_LATIN1_SWEDISH_CI,true, true, 1}, + {CS_TYPE_LATIN1_BIN, CHARSET_LATIN1, CS_TYPE_LATIN1_BIN,false, true, 1} }; void *ObCharset::charset_arr[CS_TYPE_MAX] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0 ~ 7 - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 8 + &ob_charset_latin1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 8 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 16 - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 24 + NULL, NULL, NULL, NULL, &ob_charset_gbk_chinese_ci, // 24 + NULL, NULL, NULL, // 29 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 32 NULL, NULL, NULL, NULL, NULL, // 40 &ob_charset_utf8mb4_general_ci, // 45 &ob_charset_utf8mb4_bin, // 46 - NULL, // 47 - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 48 + &ob_charset_latin1_bin, // 47 + NULL, NULL, NULL, NULL, NULL, NULL, // 48 + &ob_charset_utf16_general_ci,// 54 + &ob_charset_utf16_bin, // 55 NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 56 &ob_charset_bin, // 63 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 64 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 72 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 80 + &ob_charset_gbk_bin, // 87 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 88 + NULL, NULL, NULL, NULL, NULL, // 96 + NULL, // 101 + NULL, NULL, // 102 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 104 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 112 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 120 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 128 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 136 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 144 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 152 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 160 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 168 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 176 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 184 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 192 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 200 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 208 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 216 + NULL, // 224 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 225 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 233 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 241 + &ob_charset_gb18030_chinese_ci, // 248 + &ob_charset_gb18030_bin, // 249 }; double ObCharset::strntod(const char *str, @@ -55,7 +101,7 @@ double ObCharset::strntod(const char *str, ObCharsetInfo *cs = &ob_charset_bin; double result = 0.0; if (is_argument_valid(cs, str, str_len)) { - result = cs->cset->strntod(const_cast(str), str_len, endptr, err); + result = cs->cset->strntod(cs, const_cast(str), str_len, endptr, err); } return result; } @@ -70,7 +116,7 @@ int64_t ObCharset::strntoll(const char *str, *end_ptr = const_cast(str); int64_t result = 0; if (is_argument_valid(cs, str, str_len)) { - result = cs->cset->strntoll(str, str_len, base, end_ptr, err); + result = cs->cset->strntoll(cs, str, str_len, base, end_ptr, err); } return result; } @@ -85,7 +131,8 @@ uint64_t ObCharset::strntoull(const char *str, *end_ptr = const_cast(str); uint64_t result = 0; if (is_argument_valid(cs, str, str_len)) { - result = cs->cset->strntoull(str, + result = cs->cset->strntoull(cs, + str, str_len, base, end_ptr, @@ -102,7 +149,7 @@ int64_t ObCharset::strntoll(const char *str, char *end_ptr = NULL; int64_t result = 0; if (is_argument_valid(cs, str, str_len)) { - result = cs->cset->strntoll(str, str_len, base, &end_ptr, err); + result = cs->cset->strntoll(cs, str, str_len, base, &end_ptr, err); } return result; } @@ -116,7 +163,8 @@ uint64_t ObCharset::strntoull(const char *str, char *end_ptr = NULL; uint64_t result = 0; if (is_argument_valid(cs, str, str_len)) { - result = cs->cset->strntoull(str, + result = cs->cset->strntoull(cs, + str, str_len, base, &end_ptr, @@ -133,7 +181,8 @@ uint64_t ObCharset::strntoullrnd(const char *str, ObCharsetInfo *cs = &ob_charset_bin; uint64_t result = 0; if (is_argument_valid(cs, str, str_len)) { - result = cs->cset->strntoull10rnd(str, + result = cs->cset->strntoull10rnd(cs, + str, str_len, unsigned_fl, endptr, @@ -150,7 +199,7 @@ size_t ObCharset::scan_str(const char *str, if (OB_ISNULL(str) || OB_ISNULL(end) || OB_ISNULL(cs)) { BACKTRACE(ERROR, true, "invalid argument. str = %p, end = %p, cs = %p", str, end, cs); } else { - result = cs->cset->scan(str, end, sq); + result = cs->cset->scan(cs, str, end, sq); } return result; } @@ -163,9 +212,9 @@ uint32_t ObCharset::instr(ObCollationType collation_type, uint32_t result = 0; if (is_argument_valid(collation_type, str1, str1_len, str2, str2_len)) { ObCharsetInfo *cs = static_cast(ObCharset::charset_arr[collation_type]); - ob_match_info m_match_t[2]; - unsigned int nmatch = 1; - unsigned int m_ret = cs->coll->instr(cs, str1, str1_len, str2, str2_len, m_match_t, nmatch); + ob_match_t m_match_t[2]; + uint nmatch = 1; + uint m_ret = cs->coll->instr(cs, str1, str1_len, str2, str2_len, m_match_t, nmatch); if (0 == m_ret ) { result = 0; } else { @@ -190,13 +239,16 @@ uint32_t ObCharset::locate(ObCollationType collation_type, if (OB_UNLIKELY(start < 0 || start > str1_len)) { result = 0; } else { - start = static_cast(charpos(collation_type, str1, str1_len, start)); - if (static_cast(start) + str2_len > str1_len) { + int ret = OB_SUCCESS; + start = static_cast(charpos(collation_type, str1, str1_len, start, &ret)); + if (OB_FAIL(ret)) { + result = 0; + } else if (static_cast(start) + str2_len > str1_len) { result = 0; } else if (0 == str2_len) { result = static_cast(start) + 1; } else { - ob_match_info match_t; + ob_match_t match_t; uint32_t nmatch = 1; uint32_t m_ret = cs->coll->instr(cs, str1 + start, str1_len - start, str2, str2_len, &match_t, nmatch); if (0 == m_ret) { @@ -219,11 +271,12 @@ int ObCharset::strcmp(ObCollationType collation_type, int result = 0; if (is_argument_valid(collation_type, str1, str1_len, str2, str2_len)) { ObCharsetInfo *cs = static_cast(ObCharset::charset_arr[collation_type]); + const bool t_is_prefix = false; result = cs->coll->strnncoll(cs, - reinterpret_cast(str1), + reinterpret_cast(str1), str1_len, - reinterpret_cast(str2), - str2_len); + reinterpret_cast(str2), + str2_len, t_is_prefix); } return result; } @@ -238,17 +291,12 @@ int ObCharset::strcmpsp(ObCollationType collation_type, int result = 0; if (is_argument_valid(collation_type, str1, str1_len, str2, str2_len)) { ObCharsetInfo *cs = static_cast(ObCharset::charset_arr[collation_type]); - result = cmp_endspace ? - cs->coll->strnncoll(cs, - reinterpret_cast(str1), - str1_len, - reinterpret_cast(str2), - str2_len) - : cs->coll->strnncollsp(cs, - reinterpret_cast(str1), + result = cs->coll->strnncollsp(cs, + reinterpret_cast(str1), str1_len, - reinterpret_cast(str2), - str2_len); + reinterpret_cast(str2), + str2_len, + cmp_endspace); } return result; } @@ -284,16 +332,17 @@ size_t ObCharset::sortkey(ObCollationType collation_type, bool &is_valid_unicode) { size_t result = 0; - int is_valid_unicode_tmp = 0; + bool is_valid_unicode_tmp = 0; if (is_argument_valid(collation_type, str, str_len, key, key_len)) { ObCharsetInfo *cs = static_cast(ObCharset::charset_arr[collation_type]); result = cs->coll->strnxfrm(cs, - reinterpret_cast(key), + reinterpret_cast(key), key_len, OB_MAX_WEIGHT, - reinterpret_cast(str), + reinterpret_cast(str), str_len, + 0, &is_valid_unicode_tmp); is_valid_unicode = is_valid_unicode_tmp; } @@ -318,7 +367,7 @@ uint64_t ObCharset::hash(ObCollationType collation_type, LOG_ERROR("unexpected error. invalid argument(s)", K(cs), K(cs->coll)); } else { seed = 0xc6a4a7935bd1e995; - cs->coll->hash_sort(cs, reinterpret_cast(str), str_len, + cs->coll->hash_sort(cs, reinterpret_cast(str), str_len, &ret, &seed, calc_end_space, hash_algo); } } @@ -386,7 +435,7 @@ size_t ObCharset::strlen_char(const ObCollationType collation_type, if (OB_ISNULL(cs->cset)) { LOG_ERROR("unexpected error. invalid argument(s)", K(cs), K(cs->cset)); } else { - ret = cs->cset->numchars(cs, str, str_len); + ret = cs->cset->numchars(cs, str, str + str_len); } } return ret; @@ -406,7 +455,7 @@ size_t ObCharset::strlen_byte_no_sp(const ObCollationType collation_type, if (OB_ISNULL(cs->cset)) { LOG_ERROR("unexpected error. invalid argument(s)", K(cs), K(cs->cset)); } else { - ret = cs->cset->lengthsp(str, str_len); + ret = cs->cset->lengthsp(cs, str, str_len); } } return ret; @@ -432,11 +481,11 @@ int ObCharset::well_formed_len(ObCollationType collation_type, const char *str, LOG_ERROR("unexpected error. invalid argument(s)", K(cs), K(cs->cset)); } else { int32_t error = 0; - well_formed_len = cs->cset->well_formed_len(str, str_len, UINT64_MAX, &error); + well_formed_len = cs->cset->well_formed_len(cs, str, str + str_len, UINT64_MAX, &error); if (0 != error) { ret = OB_ERR_INCORRECT_STRING_VALUE; LOG_WARN("well_formed_len failed. invalid char found", - K(ret), "str", ObString(str_len, str)); + K(ret), K(error), "str", ObString(str_len, str)); } } } else { @@ -465,17 +514,20 @@ int ObCharset::well_formed_len(ObCollationType collation_type, const char *str, ret = OB_ERR_UNEXPECTED; LOG_ERROR("unexpected error. invalid argument(s)", K(cs), K(cs->cset)); } else { - well_formed_len = cs->cset->well_formed_len(str, str_len, UINT64_MAX, &well_formed_error); + well_formed_len = cs->cset->well_formed_len(cs, str, str + str_len, UINT64_MAX, &well_formed_error); } } return ret; } + +// Be careful with this function. The return value may be out of range. size_t ObCharset::charpos(const ObCollationType collation_type, - const char *str, - const int64_t str_len, - const int64_t length) + const char *str, + const int64_t str_len, + const int64_t length, + int *ret) { - size_t ret = 0; + size_t res_pos = 0; if (OB_UNLIKELY(collation_type <= CS_TYPE_INVALID || collation_type >= CS_TYPE_MAX) || OB_ISNULL(ObCharset::charset_arr[collation_type])) { @@ -485,10 +537,16 @@ size_t ObCharset::charpos(const ObCollationType collation_type, if (OB_ISNULL(cs->cset)) { LOG_ERROR("unexpected error. invalid argument(s)", K(cs), K(cs->cset)); } else { - ret = cs->cset->charpos(cs, str, str_len, length); + res_pos = cs->cset->charpos(cs, str, str + str_len, length); + if (res_pos > str_len) { + res_pos = str_len; + if (OB_NOT_NULL(ret)) { + *ret = OB_ERROR_OUT_OF_RANGE; + } + } } } - return ret; + return res_pos; } bool ObCharset::wildcmp(ObCollationType collation_type, @@ -535,20 +593,18 @@ int ObCharset::mb_wc(ObCollationType collation_type, K(ret), K(collation_type), K(ObCharset::charset_arr[collation_type])); } else { ObCharsetInfo *cs = static_cast(ObCharset::charset_arr[collation_type]); - ob_wc_t res_wc; + ob_wc_t my_wc; if (OB_ISNULL(cs->cset)) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("unexpected error. invalid argument(s)", K(cs), K(cs->cset)); } else { - int tmp = cs->cset->mb_wc( - reinterpret_cast(mb), - reinterpret_cast(mb + mb_size), - &res_wc); + int tmp = cs->cset->mb_wc(cs, &my_wc, reinterpret_cast(mb), + reinterpret_cast(mb + mb_size)); if (tmp <= 0) { ret = OB_ERROR; } else { ret = OB_SUCCESS; - wc = static_cast(res_wc); + wc = static_cast(my_wc); length = static_cast(tmp); } } @@ -569,10 +625,10 @@ int ObCharset::wc_mb(ObCollationType collation_type, int32_t wc, char *buff, int ret = OB_ERR_UNEXPECTED; LOG_ERROR("unexpected error. invalid argument(s)", K(cs), K(ret)); } else { - int tmp = cs->cset->wc_mb(wc, reinterpret_cast(buff), - reinterpret_cast(buff + buff_len)); + int tmp = cs->cset->wc_mb(cs, wc, reinterpret_cast(buff), + reinterpret_cast(buff + buff_len)); if (tmp <= 0) { - ret = OB_ERROR; + ret = OB_ERR_INCORRECT_STRING_VALUE; } else { ret = OB_SUCCESS; length = tmp; @@ -594,6 +650,22 @@ const char *ObCharset::charset_name(ObCharsetType charset_type) ret_name = "utf8mb4"; break; } + case CHARSET_GBK: { + ret_name = "gbk"; + break; + } + case CHARSET_UTF16: { + ret_name = "utf16"; + break; + } + case CHARSET_GB18030: { + ret_name = "gb18030"; + break; + } + case CHARSET_LATIN1: { + ret_name = "latin1"; + break; + } default: { break; } @@ -684,6 +756,16 @@ ObCharsetType ObCharset::charset_type(const ObString &cs_name) charset_type = CHARSET_UTF8MB4; } else if (0 == cs_name.case_compare(ob_charset_bin.csname)) { charset_type = CHARSET_BINARY; + } else if (0 == cs_name.case_compare(ob_charset_gb18030_chinese_ci.csname)) { + charset_type = CHARSET_GB18030; + } else if (0 == cs_name.case_compare(ob_charset_gbk_chinese_ci.csname)) { + charset_type = CHARSET_GBK; + } else if (0 == cs_name.case_compare(ob_charset_utf16_general_ci.csname)) { + charset_type = CHARSET_UTF16; + } else if (0 == cs_name.case_compare(ob_charset_latin1.csname)) { + charset_type = CHARSET_LATIN1; + } else if (0 == cs_name.case_compare(ob_charset_latin1_bin.csname)) { + charset_type = CHARSET_LATIN1; } return charset_type; } @@ -714,6 +796,22 @@ ObCollationType ObCharset::collation_type(const ObString &cs_name) collation_type = CS_TYPE_UTF8MB4_GENERAL_CI; } else if (0 == cs_name.case_compare(ob_charset_bin.name)) { collation_type = CS_TYPE_BINARY; + } else if (0 == cs_name.case_compare(ob_charset_gb18030_bin.name)) { + collation_type = CS_TYPE_GB18030_BIN; + } else if (0 == cs_name.case_compare(ob_charset_gb18030_chinese_ci.name)) { + collation_type = CS_TYPE_GB18030_CHINESE_CI; + } else if (0 == cs_name.case_compare(ob_charset_gbk_bin.name)) { + collation_type = CS_TYPE_GBK_BIN; + } else if (0 == cs_name.case_compare(ob_charset_gbk_chinese_ci.name)) { + collation_type = CS_TYPE_GBK_CHINESE_CI; + } else if (0 == cs_name.case_compare(ob_charset_utf16_bin.name)) { + collation_type = CS_TYPE_UTF16_BIN; + } else if (0 == cs_name.case_compare(ob_charset_utf16_general_ci.name)) { + collation_type = CS_TYPE_UTF16_GENERAL_CI; + } else if (0 == cs_name.case_compare(ob_charset_latin1.name)) { + collation_type = CS_TYPE_LATIN1_SWEDISH_CI; + } else if (0 == cs_name.case_compare(ob_charset_latin1_bin.name)) { + collation_type = CS_TYPE_LATIN1_BIN; } return collation_type; } @@ -735,6 +833,26 @@ bool ObCharset::is_valid_collation(ObCharsetType charset_type, ObCollationType c } else if (CHARSET_BINARY == charset_type && CS_TYPE_BINARY == collation_type) { ret = true; + } else if (CHARSET_GB18030 == charset_type) { + if (CS_TYPE_GB18030_BIN == collation_type + || CS_TYPE_GB18030_CHINESE_CI == collation_type) { + ret = true; + } + } else if (CHARSET_GBK == charset_type) { + if (CS_TYPE_GBK_BIN == collation_type + || CS_TYPE_GBK_CHINESE_CI == collation_type) { + ret = true; + } + } else if (CHARSET_UTF16 == charset_type) { + if (CS_TYPE_UTF16_BIN == collation_type + || CS_TYPE_UTF16_GENERAL_CI == collation_type) { + ret = true; + } + } else if (CHARSET_LATIN1 == charset_type) { + if (CS_TYPE_LATIN1_BIN == collation_type + || CS_TYPE_LATIN1_SWEDISH_CI == collation_type) { + ret = true; + } } return ret; } @@ -744,14 +862,26 @@ bool ObCharset::is_valid_collation(int64_t collation_type_int) ObCollationType collation_type = static_cast(collation_type_int); return CS_TYPE_UTF8MB4_GENERAL_CI == collation_type || CS_TYPE_UTF8MB4_BIN == collation_type - || CS_TYPE_BINARY == collation_type; + || CS_TYPE_BINARY == collation_type + || CS_TYPE_GB18030_BIN == collation_type + || CS_TYPE_GB18030_CHINESE_CI == collation_type + || CS_TYPE_GBK_BIN == collation_type + || CS_TYPE_GBK_CHINESE_CI == collation_type + || CS_TYPE_UTF16_BIN == collation_type + || CS_TYPE_UTF16_GENERAL_CI == collation_type + || CS_TYPE_LATIN1_BIN == collation_type + || CS_TYPE_LATIN1_SWEDISH_CI == collation_type; } bool ObCharset::is_valid_charset(int64_t cs_type_int) { ObCharsetType charset_type = static_cast(cs_type_int); return CHARSET_BINARY == charset_type - || CHARSET_UTF8MB4 == charset_type; + || CHARSET_UTF8MB4 == charset_type + || CHARSET_GBK == charset_type + || CHARSET_UTF16 == charset_type + || CHARSET_GB18030 == charset_type + || CHARSET_LATIN1 == charset_type; } ObCharsetType ObCharset::charset_type_by_coll(ObCollationType collation_type) @@ -768,6 +898,26 @@ ObCharsetType ObCharset::charset_type_by_coll(ObCollationType collation_type) charset_type = CHARSET_BINARY; break; } + case CS_TYPE_GB18030_BIN: + case CS_TYPE_GB18030_CHINESE_CI: { + charset_type = CHARSET_GB18030; + break; + } + case CS_TYPE_GBK_BIN: + case CS_TYPE_GBK_CHINESE_CI: { + charset_type = CHARSET_GBK; + break; + } + case CS_TYPE_UTF16_BIN: + case CS_TYPE_UTF16_GENERAL_CI: { + charset_type = CHARSET_UTF16; + break; + } + case CS_TYPE_LATIN1_SWEDISH_CI: + case CS_TYPE_LATIN1_BIN: { + charset_type = CHARSET_LATIN1; + break; + } default: { break; } @@ -982,6 +1132,22 @@ ObCollationType ObCharset::get_default_collation(ObCharsetType charset_type) collation_type = CS_TYPE_BINARY; break; } + case CHARSET_GB18030: { + collation_type = CS_TYPE_GB18030_CHINESE_CI; + break; + } + case CHARSET_GBK: { + collation_type = CS_TYPE_GBK_CHINESE_CI; + break; + } + case CHARSET_UTF16: { + collation_type = CS_TYPE_UTF16_GENERAL_CI; + break; + } + case CHARSET_LATIN1: { + collation_type = CS_TYPE_LATIN1_SWEDISH_CI; + break; + } default: { break; } @@ -1001,6 +1167,22 @@ ObCollationType ObCharset::get_default_collation_oracle(ObCharsetType charset_ty collation_type = CS_TYPE_BINARY; break; } + case CHARSET_GB18030: { + collation_type = CS_TYPE_GB18030_BIN; + break; + } + case CHARSET_GBK: { + collation_type = CS_TYPE_GBK_BIN; + break; + } + case CHARSET_UTF16: { + collation_type = CS_TYPE_UTF16_BIN; + break; + } + case CHARSET_LATIN1: { + collation_type = CS_TYPE_LATIN1_BIN; + break; + } default: { break; } @@ -1020,6 +1202,22 @@ int ObCharset::get_default_collation(ObCharsetType charset_type, ObCollationType collation_type = CS_TYPE_BINARY; break; } + case CHARSET_GB18030: { + collation_type = CS_TYPE_GB18030_CHINESE_CI; + break; + } + case CHARSET_GBK: { + collation_type = CS_TYPE_GBK_CHINESE_CI; + break; + } + case CHARSET_UTF16: { + collation_type = CS_TYPE_UTF16_GENERAL_CI; + break; + } + case CHARSET_LATIN1: { + collation_type = CS_TYPE_LATIN1_SWEDISH_CI; + break; + } default: { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid charset type", K(ret), K(charset_type)); @@ -1041,6 +1239,22 @@ ObCollationType ObCharset::get_bin_collation(ObCharsetType charset_type) collation_type = CS_TYPE_BINARY; break; } + case CHARSET_GB18030: { + collation_type = CS_TYPE_GB18030_BIN; + break; + } + case CHARSET_GBK: { + collation_type = CS_TYPE_GBK_BIN; + break; + } + case CHARSET_UTF16: { + collation_type = CS_TYPE_UTF16_BIN; + break; + } + case CHARSET_LATIN1: { + collation_type = CS_TYPE_LATIN1_BIN; + break; + } default: { break; } @@ -1095,7 +1309,7 @@ int ObCharset::first_valid_char( ret = OB_ERR_UNEXPECTED; LOG_ERROR("unexpected error. invalid argument(s)", K(cs), K(cs->cset)); } else { - len = static_cast(cs->cset->well_formed_len(buf, buf_size, 1, &error)); + len = static_cast(cs->cset->well_formed_len(cs, buf, buf + buf_size, 1, &error)); if (OB_LIKELY(0 == error)) { char_len = len; } else { @@ -1127,7 +1341,7 @@ int ObCharset::last_valid_char( for (len = cs->mbminlen; len <= cs->mbmaxlen; ++len) { int error = 0; int real_len = - static_cast(cs->cset->well_formed_len(buf + buf_size - len, len, len, &error)); + cs->cset->well_formed_len(cs, buf + buf_size - len, buf + buf_size, len, &error); if (0 == error && real_len == len) { char_len = len; break; @@ -1166,7 +1380,10 @@ bool ObCharset::is_default_collation(ObCollationType collation_type) bool ret = false; switch (collation_type) { case CS_TYPE_UTF8MB4_GENERAL_CI: - case CS_TYPE_BINARY: { + case CS_TYPE_BINARY: + case CS_TYPE_GB18030_CHINESE_CI: + case CS_TYPE_GBK_CHINESE_CI: + case CS_TYPE_UTF16_GENERAL_CI: { ret = true; break; } @@ -1268,7 +1485,8 @@ bool ObCharset::is_space(const ObCollationType collation_type, char c) LOG_ERROR("unexpected error. invalid argument(s)", K(ret), K(collation_type), K(ObCharset::charset_arr[collation_type])); } else { - ret = (' ' == c); + ObCharsetInfo *cs = static_cast(ObCharset::charset_arr[collation_type]); + ret = ob_isspace(cs, c); } return ret; } @@ -1283,7 +1501,7 @@ bool ObCharset::is_graph(const ObCollationType collation_type, char c) K(ret), K(collation_type), K(ObCharset::charset_arr[collation_type])); } else { ObCharsetInfo *cs = static_cast(ObCharset::charset_arr[collation_type]); - ret = !!(((cs)->ctype+1)[(unsigned char) (c)] & (_MY_PNT | _MY_U | _MY_L | _MY_NMR)); + ret = ob_isgraph(cs, c); } return ret; } @@ -1298,7 +1516,7 @@ bool ObCharset::usemb(const ObCollationType collation_type) K(ret), K(collation_type), K(ObCharset::charset_arr[collation_type])); } else { ObCharsetInfo *cs = static_cast(ObCharset::charset_arr[collation_type]); - ret = (NULL != cs->cset->ismbchar); + ret = use_mb(cs); } return ret; } @@ -1313,9 +1531,7 @@ int ObCharset::is_mbchar(const ObCollationType collation_type, const char *str, K(ret), K(collation_type), K(ObCharset::charset_arr[collation_type])); } else { ObCharsetInfo *cs = static_cast(ObCharset::charset_arr[collation_type]); - if (NULL != cs->cset->ismbchar) { - ret = cs->cset->ismbchar(str, end - str); - } + ret = ob_ismbchar(cs, str, end); } return ret; } @@ -1393,7 +1609,7 @@ int ObCharset::fit_string(const ObCollationType collation_type, int64_t char_len = 0; int error = 0; while(buf_start < buf_end) { - char_len = static_cast(cs->cset->well_formed_len(buf_start, buf_end - buf_start, 1, &error)); + char_len = static_cast(cs->cset->well_formed_len(cs, buf_start, buf_end, 1, &error)); if (OB_UNLIKELY(0 != error || char_len <= 0)) { ret = OB_INVALID_ARGUMENT; break; @@ -1481,11 +1697,16 @@ int ObCharset::charset_convert(const ObCollationType from_type, ObCharsetInfo *from_cs = static_cast(ObCharset::charset_arr[from_type]); ObCharsetInfo *to_cs = static_cast(ObCharset::charset_arr[to_type]); unsigned int errors; - result_len = ob_convert(to_str, to_len, to_cs, from_str, from_len, from_cs, &errors); - if (errors != 0) { - ret = OB_ERR_INCORRECT_STRING_VALUE; - LOG_WARN("ob_convert failed", K(ret), K(errors), - K(from_type), K(to_type), K(ObString(from_len, from_str)), K(to_len)); + if (NULL == from_cs || NULL == to_cs || NULL == from_str || NULL == to_str) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid arugment", K(from_cs), K(to_cs), K(from_str), K(to_str)); + } else { + result_len = ob_convert(to_str, to_len, to_cs, from_str, from_len, from_cs, &errors); + if (errors != 0) { + ret = OB_ERR_INCORRECT_STRING_VALUE; + LOG_WARN("ob_convert failed", K(ret), K(errors), + K(from_type), K(to_type), K(ObString(from_len, from_str)), K(to_len)); + } } } diff --git a/src/lib/charset/ob_charset.h b/src/lib/charset/ob_charset.h index 641b24c2e9113e631e9f83142a640e99e357d87a..b209c97c3d04f20746793e574ad181c8004a784b 100644 --- a/src/lib/charset/ob_charset.h +++ b/src/lib/charset/ob_charset.h @@ -27,15 +27,29 @@ enum ObCharsetType CHARSET_INVALID = 0, CHARSET_BINARY = 1, CHARSET_UTF8MB4 = 2, + CHARSET_GBK = 3, + CHARSET_UTF16 = 4, + CHARSET_GB18030 = 5, + CHARSET_LATIN1 = 6, CHARSET_MAX, }; enum ObCollationType { CS_TYPE_INVALID = 0, + CS_TYPE_LATIN1_SWEDISH_CI = 8, + CS_TYPE_GBK_CHINESE_CI = 28, CS_TYPE_UTF8MB4_GENERAL_CI = 45, CS_TYPE_UTF8MB4_BIN = 46, + CS_TYPE_LATIN1_BIN = 47, + CS_TYPE_UTF16_GENERAL_CI = 54, + CS_TYPE_UTF16_BIN = 55, CS_TYPE_BINARY = 63, + CS_TYPE_GBK_BIN = 87, + CS_TYPE_UTF16_UNICODE_CI = 101, + CS_TYPE_UTF8MB4_UNICODE_CI = 224, + CS_TYPE_GB18030_CHINESE_CI = 248, + CS_TYPE_GB18030_BIN = 249, CS_TYPE_MAX, }; /* @@ -89,8 +103,8 @@ private: virtual ~ObCharset() {}; public: - static const int64_t CHARSET_WRAPPER_COUNT = 2; - static const int64_t COLLATION_WRAPPER_COUNT = 3; + static const int64_t CHARSET_WRAPPER_COUNT = 6; + static const int64_t COLLATION_WRAPPER_COUNT = 13; static double strntod(const char *str, size_t str_len, @@ -190,7 +204,8 @@ public: static size_t charpos(ObCollationType collation_type, const char *str, const int64_t str_len, - const int64_t length); + const int64_t length, + int *ret = NULL); // match like pattern static bool wildcmp(ObCollationType collation_type, const ObString &str, diff --git a/src/lib/charset/ob_config.h b/src/lib/charset/ob_config.h new file mode 100644 index 0000000000000000000000000000000000000000..a93a7fc9a69d83d4fdb59149865106987b551ea2 --- /dev/null +++ b/src/lib/charset/ob_config.h @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef OB_CONFIG_H +#define OB_CONFIG_H + +#define _GNU_SOURCE 1 + + +#define SIZEOF_SIZE_T 8 +#define SIZEOF_CHARP 8 +#define SIZEOF_VOIDP 8 +#define SIZEOF_LONG 8 + +#define SIZEOF_CHAR 1 +#define HAS_CHAR 1 +#define HAS_LONG 1 + +#define HAS_CHARP 1 +#define SIZEOF_SHORT 2 +#define HAS_SHORT 1 +#define SIZEOF_INT 4 +#define HAS_INT 1 +#define SIZEOF_LONG_LONG 8 +#define HAS_LONG_LONG 1 +#define SIZEOF_OFF_T 8 +#define HAS_OFF_T 1 +#define SIZEOF_SIGSET_T 128 +#define HAS_SIGSET_T 1 +#define HAS_SIZE_T 1 +#define SIZEOF_UINT 4 +#define HAS_UINT 1 +#define SIZEOF_ULONG 8 +#define HAS_ULONG 1 +#define HAS_U_INT32_T 1 +#define SIZEOF_U_INT32_T 4 +#define HAS_MBSTATE_T +#define MAX_INDEXES 64U +#define QSORT_TYPE_IS_VOID 1 +#define SIGNAL_RETURN_TYPE_IS_VOID 1 +#define VOID_SIGHANDLER 1 +#define RETSIGTYPE void +#define RETQSORTTYPE void +#define STRUCT_RLIMIT struct rlimit +#define SOCKET_SIZE_TYPE socklen_t + + +#endif diff --git a/src/lib/charset/ob_ctype.c b/src/lib/charset/ob_ctype.c index a559a5ff47eb7e0dd05ce0bc70a7bbf8874e35c8..8c475310a863b13c4d217954f24b0128528f30c1 100644 --- a/src/lib/charset/ob_ctype.c +++ b/src/lib/charset/ob_ctype.c @@ -12,85 +12,93 @@ #include "lib/charset/ob_ctype.h" -static uint32_t -ob_convert_internal(char *to, uint32_t to_length, +static uint32 +ob_convert_internal(char *to, uint32 to_length, const ObCharsetInfo *to_cs, - const char *from, uint32_t from_length, - const ObCharsetInfo *from_cs, uint32_t *errors) + const char *from, uint32 from_length, + const ObCharsetInfo *from_cs, uint *errors) { - int res; + unsigned int error_num= 0; + int cnvres; ob_wc_t wc; - const unsigned char *from_end = (const unsigned char*) from + from_length; + const unsigned char *from_end= (const unsigned char*) from + from_length; char *to_start= to; unsigned char *to_end= (unsigned char*) to + to_length; - ob_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc; ob_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb; - uint32_t error_count= 0; - - while (1) { - if ((res = (*mb_wc)((unsigned char *) from, from_end, &wc)) > 0) { - from+= res; - } else if (res == OB_CS_ERR_ILLEGAL_SEQUENCE) { - error_count++; + ob_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc; + pbool conitnue = TRUE; + while (conitnue) { + if ((cnvres= (*mb_wc)(from_cs, &wc, (unsigned char*) from, from_end)) > 0) { + from+= cnvres; + } else if (cnvres == OB_CS_ILSEQ) { from++; wc= '?'; - } else if (res > OB_CS_ERR_TOOSMALL) { - /* - A correct multibyte sequence detected - But it doesn't have Unicode mapping. - */ - error_count++; - from+= (-res); + error_num++; + } else if (cnvres > OB_CS_TOOSMALL) { + from+= (-cnvres); wc= '?'; + error_num++; } else { - break; // Not enough characters + break; } -outp: - if ((res= (*wc_mb)(wc, (unsigned char*) to, to_end)) > 0) { - to+= res; - } else if (res == OB_CS_ERR_ILLEGAL_UNICODE && wc != '?') { - error_count++; - wc= '?'; - goto outp; - } else { - break; + pbool go = TRUE; + while (go) { + go = FALSE; + if ((cnvres= (*wc_mb)(to_cs, wc, (unsigned char*) to, to_end)) > 0) + to+= cnvres; + else if (cnvres == OB_CS_ILUNI && wc != '?') { + error_num++; + wc= '?'; + go = TRUE; + } else { + conitnue = FALSE; + } } } - *errors= error_count; - return (uint32_t) (to - to_start); + *errors= error_num; + return (uint32) (to - to_start); } -uint32_t -ob_convert(char *to, uint32_t to_length, const ObCharsetInfo *to_cs, - const char *from, uint32_t from_length, - const ObCharsetInfo *from_cs, uint32_t *errors) { - uint32_t length, length2; - /* - If any of the character sets is not ASCII compatible, - immediately switch to slow mb_wc->wc_mb method. - */ + +uint32 +ob_convert(char *to, uint32 to_length, const ObCharsetInfo *to_cs, + const char *from, uint32 from_length, + const ObCharsetInfo *from_cs, uint *errors) +{ + uint32 length, length2; + if ((to_cs->state | from_cs->state) & OB_CS_NONASCII) { - return ob_convert_internal(to, to_length, to_cs, - from, from_length, from_cs, errors); + return ob_convert_internal(to, to_length, to_cs, from, from_length, from_cs, errors); + } else { + length= length2= OB_MIN(to_length, from_length); } - length= length2= to_length < from_length ? to_length : from_length; +#if defined(__i386__) + while (length >= 4) { + if ((*(uint32*)from) & 0x80808080) break; + *((uint32*) to) = *((const uint32*) from); + from += 4; + to += 4; + length -= 4; + } +#endif /* __i386__ */ - for (; ; *to++= *from++, length--) { + while (TRUE) { if (!length) { *errors= 0; return length2; - } - if (*((unsigned char*) from) > 0x7F) { /* A non-ASCII character */ - uint32_t copied_length= length2 - length; + } else if (*((unsigned char*) from) > 0x7F) { + uint32 copied_length= length2 - length; to_length-= copied_length; from_length-= copied_length; return copied_length + ob_convert_internal(to, to_length, to_cs, from, from_length, from_cs, errors); } + *to++= *from++; + length--; } - return 0; + return 0; } diff --git a/src/lib/charset/ob_ctype.h b/src/lib/charset/ob_ctype.h index 62221ffe45e2fd82dc3a3e0426bfdf38ced1bedb..b11d946727ccd7689b43265b8588a3d1c83c08ac 100644 --- a/src/lib/charset/ob_ctype.h +++ b/src/lib/charset/ob_ctype.h @@ -13,7 +13,7 @@ #ifndef OCEANBASE_LIB_OBMYSQL_OB_CTYPE_ #define OCEANBASE_LIB_OBMYSQL_OB_CTYPE_ -//#include "lib/charset/ob_mysql_global.h" +#include "lib/charset/ob_mysql_global.h" #include #include #include @@ -22,7 +22,6 @@ extern "C" { #endif -#define OB_CS_SUCC(value) (OB_LIKELY(OB_CS_SUCCESS == (value))) #define OB_UTF8MB4 "utf8mb4" @@ -37,44 +36,80 @@ extern "C" { #define OB_UTF16_BIN OB_UTF16 "_bin" #define OB_UTF16_UNICODE_CI OB_UTF16 "_unicode_ci" -/* My charsets_list flags */ -#define OB_CS_COMPILED 1 /* compiled-in sets */ -#define OB_CS_CONFIG 2 /* sets that have a *.conf file */ -#define OB_CS_INDEX 4 /* sets listed in the Index file */ -#define OB_CS_LOADED 8 /* sets that are currently loaded */ -#define OB_CS_BINSORT 16 /* if binary sort order */ -#define OB_CS_PRIMARY 32 /* if primary collation */ -#define OB_CS_STRNXFRM 64 /* if strnxfrm is used for sort */ -#define OB_CS_UNICODE 128 /* is a charset is BMP Unicode */ -#define OB_CS_READY 256 /* if a charset is initialized */ -#define OB_CS_AVAILABLE 512 /* If either compiled-in or loaded*/ -#define OB_CS_CSSORT 1024 /* if case sensitive sort order */ -#define OB_CS_HIDDEN 2048 /* don't display in SHOW */ -#define OB_CS_PUREASCII 4096 /* if a charset is pure ascii */ -#define OB_CS_NONASCII 8192 /* if not ASCII-compatible */ -#define OB_CS_UNICODE_SUPPLEMENT 16384 /* Non-BMP Unicode characters */ -#define OB_CS_LOWER_SORT 32768 /* If use lower case as weight */ -#define OB_CHARSET_UNDEFINED 0 +#define OB_LATIN1 "latin1" +#define OB_LATIN1_SWEDISH_CI OB_LATIN1 "_swedish_ci" +#define OB_LATIN1_BIN OB_LATIN1 "_bin" +/* wm_wc and wc_mb return codes */ +#define OB_CS_ILSEQ 0 // mb_wc wrong sequence +#define OB_CS_ILUNI 0 // wc_mb fail to encode Unicode to charset +#define OB_CS_TOOSMALL -101 /* Need at least one byte: wc_mb and mb_wc */ +#define OB_CS_TOOSMALL2 -102 /* Need at least two bytes: wc_mb and mb_wc */ +#define OB_CS_TOOSMALL3 -103 /* Need at least three bytes: wc_mb and mb_wc */ +/* These following three are currently not really used */ +#define OB_CS_TOOSMALL4 -104 /* Need at least 4 bytes: wc_mb and mb_wc */ +#define OB_CS_TOOSMALL5 -105 /* Need at least 5 bytes: wc_mb and mb_wc */ +#define OB_CS_TOOSMALL6 -106 /* Need at least 6 bytes: wc_mb and mb_wc */ +/* A helper macros for "need at least n bytes" */ +#define OB_CS_TOOSMALLN(n) (-100-(n)) #define OB_SEQ_INTTAIL 1 #define OB_SEQ_SPACES 2 +#define OB_CS_COMPILED 1 +#define OB_CS_CONFIG 2 +#define OB_CS_INDEX 4 +#define OB_CS_LOADED 8 +#define OB_CS_BINSORT 16 +#define OB_CS_PRIMARY 32 +#define OB_CS_STRNXFRM 64 +#define OB_CS_UNICODE 128 +#define OB_CS_READY 256 +#define OB_CS_AVAILABLE 512 +#define OB_CS_CSSORT 1024 +#define OB_CS_HIDDEN 2048 +#define OB_CS_PUREASCII 4096 +#define OB_CS_NONASCII 8192 +#define OB_CS_UNICODE_SUPPLEMENT 16384 +#define OB_CS_LOWER_SORT 32768 +#define OB_CHARSET_UNDEFINED 0 -/* wm_wc and wc_mb return codes */ -#define OB_CS_SUCCESS 0 -#define OB_CS_ERR_ILLEGAL_SEQUENCE -1 /* Wrong by sequence: wb_wc */ -#define OB_CS_ERR_ILLEGAL_UNICODE -2 /* Cannot encode Unicode to charset: wc_mb */ -#define OB_CS_ERR_NUM_OUT_OF_RANGE -3 -#define OB_CS_ERR_TOOSMALL -101 /* Need at least one byte: wc_mb and mb_wc */ -#define OB_CS_ERR_TOOSMALL2 -102 /* Need at least two bytes: wc_mb and mb_wc */ -#define OB_CS_ERR_TOOSMALL3 -103 /* Need at least three bytes: wc_mb and mb_wc */ -/* These following three are currently not really used */ -#define OB_CS_ERR_TOOSMALL4 -104 /* Need at least 4 bytes: wc_mb and mb_wc */ -#define OB_CS_ERR_TOOSMALL5 -105 /* Need at least 5 bytes: wc_mb and mb_wc */ -#define OB_CS_ERR_TOOSMALL6 -106 /* Need at least 6 bytes: wc_mb and mb_wc */ -/* A helper macros for "need at least n bytes" */ -#define OB_CS_ERR_TOOSMALLN(n) (-100-(n)) +/* Character repertoire flags */ +#define OB_REPERTOIRE_ASCII 1 +#define OB_REPERTOIRE_EXTENDED 2 +#define OB_REPERTOIRE_UNICODE30 3 + +/* Flags for strxfrm */ +#define OB_STRXFRM_LEVEL1 0x00000001 +#define OB_STRXFRM_LEVEL2 0x00000002 +#define OB_STRXFRM_LEVEL3 0x00000004 +#define OB_STRXFRM_LEVEL4 0x00000008 +#define OB_STRXFRM_LEVEL5 0x00000010 +#define OB_STRXFRM_LEVEL6 0x00000020 +#define OB_STRXFRM_LEVEL_ALL 0x0000003F +#define OB_STRXFRM_NLEVELS 6 + +#define OB_STRXFRM_PAD_WITH_SPACE 0x00000040 +#define OB_STRXFRM_PAD_TO_MAXLEN 0x00000080 + +#define OB_STRXFRM_DESC_LEVEL1 0x00000100 +#define OB_STRXFRM_DESC_LEVEL2 0x00000200 +#define OB_STRXFRM_DESC_LEVEL3 0x00000300 +#define OB_STRXFRM_DESC_LEVEL4 0x00000800 +#define OB_STRXFRM_DESC_LEVEL5 0x00001000 +#define OB_STRXFRM_DESC_LEVEL6 0x00002000 +#define OB_STRXFRM_DESC_SHIFT 8 + +#define OB_STRXFRM_UNUSED_00004000 0x00004000 +#define OB_STRXFRM_UNUSED_00008000 0x00008000 + +#define OB_STRXFRM_REVERSE_LEVEL1 0x00010000 +#define OB_STRXFRM_REVERSE_LEVEL2 0x00020000 +#define OB_STRXFRM_REVERSE_LEVEL3 0x00040000 +#define OB_STRXFRM_REVERSE_LEVEL4 0x00080000 +#define OB_STRXFRM_REVERSE_LEVEL5 0x00100000 +#define OB_STRXFRM_REVERSE_LEVEL6 0x00200000 +#define OB_STRXFRM_REVERSE_SHIFT 16 #define _MY_U 01 /* Upper case */ #define _MY_L 02 /* Lower case */ @@ -85,24 +120,6 @@ extern "C" { #define _MY_B 0100 /* Blank */ #define _MY_X 0200 /* heXadecimal digit */ -#define ob_isascii(c) (0 == ((c) & ~0177)) -#define ob_toascii(c) ((c) & 0177) -#define ob_tocntrl(c) ((c) & 31) -#define ob_toprint(c) ((c) | 64) -#define ob_toupper(s,c) (char) ((s)->to_upper[(uchar) (c)]) -#define ob_tolower(s,c) (char) ((s)->to_lower[(uchar) (c)]) -#define ob_isalpha(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & (_MY_U | _MY_L) : 0) -#define ob_isupper(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & _MY_U : 0) -#define ob_islower(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & _MY_L : 0) -#define ob_isdigit(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & _MY_NMR : 0) -#define ob_isxdigit(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & _MY_X : 0) -#define ob_isalnum(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & (_MY_U | _MY_L | _MY_NMR) : 0) -#define ob_isspace(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & _MY_SPC : 0) -#define ob_ispunct(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & _MY_PNT : 0) -#define ob_isprint(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & (_MY_PNT | _MY_U | _MY_L | _MY_NMR | _MY_B) : 0) -#define ob_isgraph(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & (_MY_PNT | _MY_U | _MY_L | _MY_NMR) : 0) -#define ob_iscntrl(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & _MY_CTR : 0) - #define ob_charset_assert(condition) \ if (!(condition)) {\ while(1) {\ @@ -112,96 +129,162 @@ extern "C" { struct ObCharsetInfo; -#define ob_wc_t unsigned long +typedef char ob_bool; /* Small bool */ +#define ob_wc_t ulong #define OB_CS_REPLACEMENT_CHARACTER 0xFFFD -#define MY_ERRNO_EDOM 33 -#define MY_ERRNO_ERANGE 34 +/* Internal error numbers (for assembler functions) */ +#define OB_ERRNO_EDOM 33 +#define OB_ERRNO_ERANGE 34 +/* Some typedef to make it easy for C++ to make function pointers */ +typedef int (*ob_charset_conv_mb_wc)(const struct ObCharsetInfo *, + ob_wc_t *, const uchar *, const uchar *); +typedef int (*ob_charset_conv_wc_mb)(const struct ObCharsetInfo *, ob_wc_t, + uchar *, uchar *); +typedef size_t (*ob_charset_conv_case)(const struct ObCharsetInfo *, + char *, size_t, char *, size_t); + +#define OB_UCA_MAX_CONTRACTION 6 +#define OB_UCA_MAX_WEIGHT_SIZE 8 +#define OB_UCA_WEIGHT_LEVELS 1 + +typedef struct ob_contraction_t +{ + ob_wc_t ch[OB_UCA_MAX_CONTRACTION]; /* Character sequence */ + uint16 weight[OB_UCA_MAX_WEIGHT_SIZE];/* Its weight string, 0-terminated */ + ob_bool with_context; +} ObContraction; -typedef int (*ob_charset_conv_mb_wc)(const unsigned char *str, const unsigned char *end, ob_wc_t *wchar); -typedef int (*ob_charset_conv_wc_mb)(ob_wc_t wchar, unsigned char *str, unsigned char *end); -typedef size_t (*ob_charset_conv_case)(const struct ObCharsetInfo *cs, - char *src, size_t src_len, char *dst, size_t dst_len); +typedef struct ob_contraction_list_t +{ + size_t nitems; /* Number of items in the list */ + ObContraction *item; /* List of contractions */ + char *flags; /* Character flags, e.g. "is contraction head") */ +} ObContractions; + +typedef struct ob_uca_level_info_st +{ + ob_wc_t maxchar; + uchar *lengths; + uint16 **weights; + ObContractions contractions; +} ObUCAWeightLevel; + +typedef struct uca_info_st +{ + ObUCAWeightLevel level[OB_UCA_WEIGHT_LEVELS]; + /* Logical positions */ + ob_wc_t first_non_ignorable; + ob_wc_t last_non_ignorable; + ob_wc_t first_primary_ignorable; + ob_wc_t last_primary_ignorable; + ob_wc_t first_secondary_ignorable; + ob_wc_t last_secondary_ignorable; + ob_wc_t first_tertiary_ignorable; + ob_wc_t last_tertiary_ignorable; + ob_wc_t first_trailing; + ob_wc_t last_trailing; + ob_wc_t first_variable; + ob_wc_t last_variable; +} ObUCAInfo; + +extern ObUCAInfo ob_uca_v400; +extern uchar uca520_length[4352]; +extern uint16 *uca520_weight[4352]; +extern uchar uca_length[256]; +extern uint16 *uca_weight[256]; typedef struct { - unsigned int beg; - unsigned int end; - unsigned int mb_len; -} ob_match_info; + uint beg; + uint end; + uint mb_len; +} ob_match_t; -typedef struct ObUnicasePages +typedef struct ObUnicaseInfoChar { - uint32_t **upper_pages; - uint32_t **lower_pages; - uint32_t **sort_pages; -} ObUnicasePages; + uint32 toupper; + uint32 tolower; + uint32 sort; +} ObUnicaseInfoChar; + + +typedef struct ObUnicaseInfo +{ + ob_wc_t maxchar; + const ObUnicaseInfoChar **page; +} ObUnicaseInfo; typedef struct ObCharsetHandler { - // ismbchar() - detects whether the given string is a multi-byte sequence - uint32_t (*ismbchar)(const char *str, size_t len); - // numchars() - returns number of characters in the given string, e.g. in SQL function CHAR_LENGTH(). - size_t (*numchars)(const struct ObCharsetInfo *cs, const char *str, size_t len); - // charpos() - calculates the offset of the given position in the string. - // Used in SQL functions LEFT(), RIGHT(), SUBSTRING(), - size_t (*charpos)(const struct ObCharsetInfo *cs, const char *str, size_t len, size_t pos); - - // max_bytes_charpos() - calculates the offset of the given byte position in the string. - size_t (*max_bytes_charpos)(const struct ObCharsetInfo *cs, const char *str, - size_t str_len, size_t max_bytes, size_t *char_len); - // well_formed_len() - // - returns length of a given multi-byte string in bytes - // Used in INSERTs to shorten the given string so it - // a) is "well formed" according to the given character set - // b) can fit into the given data type - size_t (*well_formed_len)(const char *str, size_t len, size_t nchars, int *error); - - // lengthsp() - returns the length of the given string without trailing spaces. - size_t (*lengthsp)(const char *str, size_t len); - - // mb_wc - converts the left multi-byte sequence into its Unicode code. + //ob_bool (*init)(struct ObCharsetInfo *, MY_CHARSET_LOADER *loader); + /* Multibyte routines */ + uint (*ismbchar)(const struct ObCharsetInfo *, const char *, + const char *); + uint (*mbcharlen)(const struct ObCharsetInfo *, uint c); + size_t (*numchars)(const struct ObCharsetInfo *, const char *b, + const char *e); + size_t (*charpos)(const struct ObCharsetInfo *, const char *b, + const char *e, size_t pos); + size_t (*max_bytes_charpos)(const struct ObCharsetInfo *, const char *b, + const char *e, size_t max_bytes, size_t *char_len); + size_t (*well_formed_len)(const struct ObCharsetInfo *, + const char *b,const char *e, + size_t nchars, int *error); + size_t (*lengthsp)(const struct ObCharsetInfo *, const char *ptr, + size_t length); + /*size_t (*numcells)(const struct ObCharsetInfo *, const char *b, + const char *e);*/ + + /* Unicode conversion */ ob_charset_conv_mb_wc mb_wc; - // wc_mb - converts the given Unicode code into multi-byte sequence. ob_charset_conv_wc_mb wc_mb; + + /* CTYPE scanner */ int (*ctype)(const struct ObCharsetInfo *cs, int *ctype, - const unsigned char *s, const unsigned char *e); + const uchar *s, const uchar *e); + + /* Functions for case and sort conversion */ + /*size_t (*caseup_str)(const struct ObCharsetInfo *, char *); + size_t (*casedn_str)(const struct ObCharsetInfo *, char *);*/ - // caseup - converts the given string to lowercase using length ob_charset_conv_case caseup; - // casedn - converts the given string to lowercase using length ob_charset_conv_case casedn; - // fill() - writes the given Unicode value into the given string - // with the given length. Used to pad the string, usually - // with space character, according to the given charset. - void (*fill)(const struct ObCharsetInfo *, char *str, size_t len, int fill); - // String-to-number conversion routines - int64_t (*strntoll)(const char *str, size_t len, int base, char **endptr, int *err); - uint64_t (*strntoull)(const char *str, size_t len, int base, char **endptr, int *err); - double (*strntod)(char *str, size_t len, char **end, int *err); - uint64_t (*strntoull10rnd)(const char *str, size_t len, - int unsigned_flag, char **endptr, int *error); - // scan() - to skip leading spaces in the given string. - // Used when a string value is inserted into a numeric field. - size_t (*scan)(const char *b, const char *e, int sq); + + /* Charset dependant snprintf() */ + /*size_t (*snprintf)(const struct ObCharsetInfo *, char *to, size_t n, + const char *fmt, + ...) __attribute__((format(printf, 4, 5))); + size_t (*long10_to_str)(const struct ObCharsetInfo *, char *to, size_t n, + int radix, long int val); + size_t (*longlong10_to_str)(const struct ObCharsetInfo *, char *to, + size_t n, int radix, longlong val);*/ + + void (*fill)(const struct ObCharsetInfo *, char *to, size_t len, int fill); + + /* String-to-number conversion routines */ + long (*strntol)(const struct ObCharsetInfo *, const char *s, + size_t l, int base, char **e, int *err); + ulong (*strntoul)(const struct ObCharsetInfo *, const char *s, + size_t l, int base, char **e, int *err); + longlong (*strntoll)(const struct ObCharsetInfo *, const char *s, + size_t l, int base, char **e, int *err); + ulonglong (*strntoull)(const struct ObCharsetInfo *, const char *s, + size_t l, int base, char **e, int *err); + double (*strntod)(const struct ObCharsetInfo *, char *s, + size_t l, char **e, int *err); + /*longlong (*strtoll10)(const struct ObCharsetInfo *cs, + const char *nptr, char **endptr, int *error);*/ + ulonglong (*strntoull10rnd)(const struct ObCharsetInfo *cs, + const char *str, size_t length, + int unsigned_fl, + char **endptr, int *error); + size_t (*scan)(const struct ObCharsetInfo *, const char *b, + const char *e, int sq); } ObCharsetHandler; -// OB_COLLATION_HANDLER -// ==================== -// strnncoll() - compares two strings according to the given collation -// strnncollsp() - like the above but ignores trailing spaces for PAD SPACE -// collations. For NO PAD collations, identical to strnncoll. -// strnxfrm() - makes a sort key suitable for memcmp() corresponding -// to the given string -// like_range() - creates a LIKE range, for optimizer -// wildcmp() - wildcard comparison, for LIKE -// strcasecmp() - 0-terminated string comparison -// instr() - finds the first substring appearance in the string -// hash_sort() - calculates hash value taking into account -// the collation rules, e.g. case-insensitivity, -// accent sensitivity, etc. static const int HASH_BUFFER_LENGTH = 128; @@ -209,154 +292,267 @@ typedef uint64_t (*hash_algo)(const void* input, uint64_t length, uint64_t seed) typedef struct ObCollationHandler { - // strnncoll() - compares two strings according to the given collation - int (*strnncoll)(const struct ObCharsetInfo *cs, - const unsigned char *src, size_t src_len, - const unsigned char *dst, size_t dst_len); - // strnncollsp() - like the above but ignores trailing spaces for PAD SPACE - // collations. For NO PAD collations, identical to strnncoll. - int (*strnncollsp)(const struct ObCharsetInfo *cs, - const unsigned char *src, size_t src_len, - const unsigned char *dst, size_t dst_len); - // strnxfrm() - makes a sort key suitable for memcmp() corresponding - // to the given string - size_t (*strnxfrm)(const struct ObCharsetInfo *, - unsigned char *dst, size_t dst_len, uint32_t nweights, - const unsigned char *src, size_t srclen, int *is_valid_unicode); - - // like_range() - creates a LIKE range, for optimizer - int (*like_range)(const struct ObCharsetInfo *cs, const char *str, size_t str_len, - int w_prefix, int w_one, int w_many, size_t res_length, - char *min_str, char *max_str, - size_t *min_len, size_t *max_len); - // wildcmp() - wildcard comparison, for LIKE - int (*wildcmp)(const struct ObCharsetInfo *cs, const char *str,const char *strend, - const char *wildstr,const char *wildend, - int escape,int w_one, int w_many); - - // instr() - finds the first substring appearance in the string - uint32_t (*instr)(const struct ObCharsetInfo *cs, const char *base, size_t base_len, - const char *str, size_t str_len, ob_match_info *match, uint32_t nmatch); - - // hash_sort() - calculates hash value taking into account - // the collation rules, e.g. case-insensitivity, - // accent sensitivity, etc. - void (*hash_sort)(const struct ObCharsetInfo *cs, const unsigned char *s, size_t slen, - uint64_t *nr1, uint64_t *nr2, const int calc_end_space, hash_algo hash_algo); + //bool (*init)(ObCharsetInfo *, ObCharsetLoader *); + /* Collation routines */ + // Functions that do string comparisons + int (*strnncoll)(const struct ObCharsetInfo *, + const uchar *, size_t, const uchar *, size_t, bool); + // Ignore trailing spaces when comparing strings + int (*strnncollsp)(const struct ObCharsetInfo *, + const uchar *, size_t, const uchar *, size_t, + bool diff_if_only_endspace_difference); + // makes a sort key suitable for memcmp() corresponding to the given string + size_t (*strnxfrm)(const struct ObCharsetInfo *, + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags, bool *is_valid_unicode); + //size_t (*strnxfrmlen)(const struct ObCharsetInfo *, size_t); + + // creates a LIKE range, for optimizer, the query range module is used + bool (*like_range)(const struct ObCharsetInfo *, + const char *s, size_t s_length, + pchar w_prefix, pchar w_one, pchar w_many, + size_t res_length, + char *min_str, char *max_str, + size_t *min_len, size_t *max_len); + // wildcard comparison, for LIKE + int (*wildcmp)(const struct ObCharsetInfo *, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape,int w_one, int w_many); + + /*int (*strcasecmp)(const struct ObCharsetInfo *, const char *, + const char *);*/ + + // finds the first substring appearance in the string + uint (*instr)(const struct ObCharsetInfo *, + const char *b, size_t b_length, + const char *s, size_t s_length, + ob_match_t *match, uint nmatch); + + /* Hash calculation */ + // calculates hash value taking into account the collation rules, e.g. case-insensitivity + void (*hash_sort)(const struct ObCharsetInfo *cs, const uchar *key, size_t len, ulong *nr1, + ulong *nr2, const bool calc_end_space, hash_algo hash_algo); + bool (*propagate)(const struct ObCharsetInfo *cs, const uchar *str, + size_t len); } ObCollationHandler; typedef struct ObCharsetInfo { - uint32_t number; - uint32_t primary_number; - uint32_t binary_number; - uint32_t state; - const char *csname; - const char *name; - const char *comment; - const char *tailoring; - unsigned char *ctype; - unsigned char *to_lower; - unsigned char *to_upper; - unsigned char *sort_order; - ObUnicasePages *caseinfo; - unsigned char *state_map; - unsigned char *ident_map; - uint32_t strxfrm_multiply; - uint32_t caseup_multiply; - uint32_t casedn_multiply; - uint32_t mbminlen; - uint32_t mbmaxlen; - uint32_t min_sort_char; - uint32_t max_sort_char; /* For LIKE optimization */ - unsigned char pad_char; - int escape_with_backslash_is_dangerous; - unsigned char levels_for_compare; - unsigned char levels_for_order; + uint number; + uint primary_number; + uint binary_number; + uint state; + const char *csname; + const char *name; + const char *comment; + const char *tailoring; + uchar *ctype; + uchar *to_lower; + uchar *to_upper; + uchar *sort_order; + ObUCAInfo *uca; + //uint16 *tab_to_uni; + //MY_UNI_IDX *tab_from_uni; + ObUnicaseInfo *caseinfo; + uchar *state_map; + uchar *ident_map; + uint strxfrm_multiply; + uchar caseup_multiply; + uchar casedn_multiply; + uint mbminlen; + uint mbmaxlen; + ob_wc_t min_sort_char; + ob_wc_t max_sort_char; /* For LIKE optimization */ + uchar pad_char; + bool escape_with_backslash_is_dangerous; + uchar levels_for_compare; + uchar levels_for_order; ObCharsetHandler *cset; ObCollationHandler *coll; } ObCharsetInfo; +#define ob_isascii(c) (0 == ((c) & ~0177)) +#define ob_toascii(c) ((c) & 0177) +#define ob_tocntrl(c) ((c) & 31) +#define ob_toprint(c) ((c) | 64) +#define ob_toupper(s,c) (char) ((s)->to_upper[(uchar) (c)]) +#define ob_tolower(s,c) (char) ((s)->to_lower[(uchar) (c)]) +#define ob_sort_order(s,c) (char)((s)->sort_order[(uchar)(c)]) +#define ob_isalpha(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & (_MY_U | _MY_L) : 0) +#define ob_isupper(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & _MY_U : 0) +#define ob_islower(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & _MY_L : 0) +#define ob_isdigit(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & _MY_NMR : 0) +#define ob_isxdigit(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & _MY_X : 0) +#define ob_isalnum(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & (_MY_U | _MY_L | _MY_NMR) : 0) +#define ob_isspace(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & _MY_SPC : 0) +#define ob_ispunct(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & _MY_PNT : 0) +#define ob_isprint(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & (_MY_PNT | _MY_U | _MY_L | _MY_NMR | _MY_B) : 0) +#define ob_isgraph(s, c) ((s)->ctype != NULL ? ((s)->ctype+1)[(uchar) (c)] & (_MY_PNT | _MY_U | _MY_L | _MY_NMR) : 0) + +#define use_mb(s) ((s)->cset->ismbchar != NULL) +static inline uint ob_ismbchar(const ObCharsetInfo *cs, const char *str, + const char *strend) +{ + return cs->cset->ismbchar(cs, str, strend); +} + typedef struct ob_uni_ctype { - unsigned char pctype; - unsigned char *ctype; + uchar pctype; + uchar *ctype; } ObUniCtype; extern ObUniCtype ob_uni_ctype[256]; +//============================================================================= + +extern ObUnicaseInfo ob_unicase_default; + +//============================================================================= + extern ObCharsetInfo ob_charset_bin; extern ObCharsetInfo ob_charset_utf8mb4_bin; extern ObCharsetInfo ob_charset_utf8mb4_general_ci; +extern ObCharsetInfo ob_charset_latin1; +extern ObCharsetInfo ob_charset_latin1_bin; +extern ObCharsetInfo ob_charset_gbk_chinese_ci; +extern ObCharsetInfo ob_charset_gbk_bin; +extern ObCharsetInfo ob_charset_utf16_general_ci; +extern ObCharsetInfo ob_charset_utf16_bin; +extern ObCharsetInfo ob_charset_gb18030_chinese_ci; +extern ObCharsetInfo ob_charset_gb18030_bin; + +extern ObCollationHandler ob_collation_mb_bin_handler; extern ObCharsetHandler ob_charset_utf8mb4_handler; +extern ObCharsetHandler ob_charset_utf16_handler; +extern ObCollationHandler ob_collation_binary_handler; +extern ObCollationHandler ob_collation_8bit_simple_ci_handler; //============================================================================= -void ob_fill_8bit(const ObCharsetInfo *cs, char* str, size_t len, int fill); -int64_t ob_strntoll_8bit(const char *str, size_t len, int base, char **e, int *err); -uint64_t ob_strntoull_8bit(const char *str, size_t len, int base, char **e, int *err); -double ob_strntod_8bit(char *s, size_t len, char **e, int *err); -uint64_t ob_strntoull10rnd_8bit(const char *str, size_t len, int +void ob_fill_8bit(const ObCharsetInfo *cs, char* to, size_t l, int fill); + +long ob_strntol_8bit(const ObCharsetInfo *, const char *s, size_t l, + int base, char **e, int *err); +ulong ob_strntoul_8bit(const ObCharsetInfo *, const char *s, size_t l, + int base, char **e, int *err); +longlong ob_strntoll_8bit(const ObCharsetInfo *, const char *s, size_t l, + int base, char **e, int *err); +ulonglong ob_strntoull_8bit(const ObCharsetInfo *, const char *s, size_t l, + int base, char **e, int *err); +double ob_strntod_8bit(const ObCharsetInfo *, char *s, size_t l, char **e, + int *err); +/*size_t ob_long10_to_str_8bit(const ObCharsetInfo *, char *to, size_t l, + int radix, long int val); +size_t ob_longlong10_to_str_8bit(const ObCharsetInfo *, char *to, size_t l, + int radix, longlong val); + +longlong ob_strtoll10_8bit(const ObCharsetInfo *cs, + const char *nptr, char **endptr, int *error);*/ + +ulonglong ob_strntoull10rnd_8bit(const ObCharsetInfo *cs, + const char *str, size_t length, int unsigned_fl, char **endptr, int *error); -size_t ob_scan_8bit(const char *str, const char *end, int sq); + +size_t ob_scan_8bit(const ObCharsetInfo *cs, const char *b, const char *e, + int sq); //====================================================================== /* For 8-bit character set */ -int ob_like_range_simple(const ObCharsetInfo *cs, - const char *str, size_t str_len, - int escape, int w_one, int w_many, - size_t res_length, - char *min_str, char *max_str, - size_t *min_length, size_t *max_length); - -int64_t ob_strntoll(const char *str, size_t str_len, int base, char **end, int *err); -int64_t ob_strntoull(const char *str, size_t str_len, int base, char **end, int *err); - -int ob_like_range_mb(const ObCharsetInfo *cs, - const char *str, size_t str_len, - int escape, int w_one, int w_many, - size_t res_length, - char *min_str, char *max_str, - size_t *min_length, size_t *max_length); +bool ob_like_range_simple(const ObCharsetInfo *cs, + const char *ptr, size_t ptr_length, + pbool escape, pbool w_one, pbool w_many, + size_t res_length, + char *min_str, char *max_str, + size_t *min_length, size_t *max_length); + +bool ob_propagate_simple(const ObCharsetInfo *cs, const uchar *str, + size_t len); +bool ob_propagate_complex(const ObCharsetInfo *cs, const uchar *str, + size_t len); + +void ob_strxfrm_desc_and_reverse(uchar *str, uchar *strend, + uint flags, uint level); + +size_t ob_strxfrm_pad_desc_and_reverse(const ObCharsetInfo *cs, + uchar *str, uchar *frmend, uchar *strend, + uint nweights, uint flags, uint level); +int64_t ob_strntoll(const char *ptr, size_t len, int base, char **end, int *err); +int64_t ob_strntoull(const char *ptr, size_t len, int base, char **end, int *err); + +bool ob_like_range_mb(const ObCharsetInfo *cs, + const char *ptr,size_t ptr_length, + pbool escape, pbool w_one, pbool w_many, + size_t res_length, + char *min_str,char *max_str, + size_t *min_length,size_t *max_length); int ob_wildcmp_mb(const ObCharsetInfo *cs, - const char *str_ptr, const char *str_end_ptr, - const char *wild_str_ptr,const char *wild_end_ptr, - int escape_char, int w_one_char, int w_many_char); + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many); int ob_wildcmp_mb_impl(const ObCharsetInfo *cs, - const char *str_ptr, const char *str_end_ptr, - const char *wild_str_ptr,const char *wild_end_ptr, - int escape_char, int w_one_char, int w_many_char); + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many, int recurse_level); + +uint ob_instr_mb(const ObCharsetInfo *cs, + const char *b, size_t b_length, + const char *s, size_t s_length, + ob_match_t *match, uint nmatch); + +void ob_hash_sort_simple(const ObCharsetInfo *cs, + const uchar *key, size_t len, + ulong *nr1, ulong *nr2, + const bool calc_end_space, hash_algo hash_algo); -unsigned int ob_instr_mb(const ObCharsetInfo *cs, - const char *base, size_t base_len, - const char *str, size_t str_len, - ob_match_info *match, uint32_t nmatch); +const uchar *skip_trailing_space(const uchar *ptr,size_t len); -const unsigned char *skip_trailing_space(const unsigned char *str, size_t len); +size_t ob_numchars_mb(const ObCharsetInfo *cs __attribute__((unused)), const char *pos, const char *end); -size_t ob_numchars_mb(const ObCharsetInfo *cs, const char *str, size_t len); +size_t ob_charpos_mb(const ObCharsetInfo *cs __attribute__((unused)), const char *pos, const char *end, size_t length); -size_t ob_charpos_mb(const ObCharsetInfo *cs, const char *str, size_t len, size_t pos); +size_t ob_max_bytes_charpos_mb(const ObCharsetInfo *cs __attribute__((unused)), const char *pos, const char *end, size_t max_bytes, size_t *char_len); -size_t ob_max_bytes_charpos_mb(const ObCharsetInfo *cs, const char *str, - size_t str_len, size_t max_bytes, size_t *char_len); int ob_mb_ctype_mb(const ObCharsetInfo *cs __attribute__((unused)), int *ctype, - const unsigned char *s, const unsigned char *e); + const uchar *s, const uchar *e); + +size_t ob_caseup_mb(const ObCharsetInfo *, char *src, size_t srclen, + char *dst, size_t dstlen); + +size_t ob_casedn_mb(const ObCharsetInfo *, char *src, size_t srclen, + char *dst, size_t dstlen); + +const ObContractions *ob_charset_get_contractions(const ObCharsetInfo *cs, + int level); -size_t ob_lengthsp_8bit(const char *str, size_t str_len); +bool ob_uca_can_be_contraction_head(const ObContractions *c, ob_wc_t wc); + +bool ob_uca_can_be_contraction_tail(const ObContractions *c, ob_wc_t wc); + +uint16 *ob_uca_contraction2_weight(const ObContractions *list, ob_wc_t wc1, ob_wc_t wc2); + +size_t ob_lengthsp_8bit(const ObCharsetInfo *cs __attribute__((unused)), + const char *ptr, size_t length); int ob_strnncoll_mb_bin(const ObCharsetInfo *cs __attribute__((unused)), - const unsigned char *str1, size_t str1_len, - const unsigned char *str2, size_t str2_len); + const uchar *s, size_t slen, + const uchar *t, size_t tlen, + bool t_is_prefix); int ob_strnncollsp_mb_bin(const ObCharsetInfo *cs __attribute__((unused)), - const unsigned char *str1, size_t str1_len, - const unsigned char *str2, size_t str2_len); + const uchar *a, size_t a_length, + const uchar *b, size_t b_length, + bool diff_if_only_endspace_difference); + +size_t ob_strnxfrm_mb(const ObCharsetInfo *, + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags, bool *is_valid_unicode); int ob_wildcmp_mb_bin(const ObCharsetInfo *cs, const char *str,const char *str_end, @@ -364,27 +560,72 @@ int ob_wildcmp_mb_bin(const ObCharsetInfo *cs, int escape, int w_one, int w_many); void ob_hash_sort_mb_bin(const ObCharsetInfo *cs __attribute__((unused)), - const unsigned char *key, size_t len, uint64_t *nr1, uint64_t *nr2, - const int calc_end_space, hash_algo hash_algo); + const uchar *key, size_t len, ulong *nr1, ulong *nr2, + const bool calc_end_space, hash_algo hash_algo); -uint32_t ob_convert(char *to, uint32_t to_length, const ObCharsetInfo *to_cs, - const char *from, uint32_t from_length, - const ObCharsetInfo *from_cs, uint32_t *errors); +uint32 ob_convert(char *to, uint32 to_length, const ObCharsetInfo *to_cs, + const char *from, uint32 from_length, + const ObCharsetInfo *from_cs, uint *errors); size_t ob_strnxfrm_unicode_full_bin(const ObCharsetInfo *cs, - unsigned char *dst, size_t dstlen, uint32_t nweights, - const unsigned char *src, size_t srclen, - int *is_valid_unicode); + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags, bool *is_valid_unicode); + +bool ob_like_range_generic(const ObCharsetInfo *cs, const char *ptr, + size_t ptr_length, char escape, char w_one, + char w_many, size_t res_length, char *min_str, + char *max_str, size_t *min_length, + size_t *max_length); size_t ob_strnxfrm_unicode(const ObCharsetInfo *cs, - unsigned char *dst, size_t dstlen, uint32_t nweights, - const unsigned char *src, size_t src_len, int *is_valid_unicode); + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags, bool *is_valid_unicode); int ob_wildcmp_unicode(const ObCharsetInfo *cs, - const char *str, const char *str_end, - const char *wildstr, const char *wildend, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, int escape, int w_one, int w_many, - uint32_t **weights); + ObUnicaseInfo *weights); + +size_t ob_strxfrm_pad(const ObCharsetInfo *cs, uchar *str, uchar *frmend, + uchar *strend, uint nweights, uint flags); + +uint ob_mbcharlen_8bit(const ObCharsetInfo *cs __attribute__((unused)), + uint c __attribute__((unused))); + +size_t ob_numchars_8bit(const ObCharsetInfo *cs __attribute__((unused)), + const char *b, const char *e); + +size_t ob_charpos_8bit(const ObCharsetInfo *cs __attribute__((unused)), + const char *b __attribute__((unused)), + const char *e __attribute__((unused)), + size_t pos); + + +size_t ob_max_bytes_charpos_8bit(const ObCharsetInfo *cs __attribute__((unused)), + const char *b __attribute__((unused)), + const char *e __attribute__((unused)), + size_t max_bytes, + size_t *char_len); + +size_t ob_well_formed_len_8bit(const ObCharsetInfo *cs __attribute__((unused)), + const char *start, const char *end, + size_t nchars, int *error); + +size_t ob_lengthsp_binary(const ObCharsetInfo *cs __attribute__((unused)), + const char *ptr __attribute__((unused)), + size_t length); + +int ob_mb_ctype_8bit(const ObCharsetInfo *cs, int *ctype, + const uchar *s, const uchar *e); + +size_t ob_caseup_8bit(const ObCharsetInfo *cs __attribute__((unused)), + char* src __attribute__((unused)), size_t srclen __attribute__((unused)), + char* dst __attribute__((unused)), size_t dstlen __attribute__((unused))); + +size_t ob_casedn_8bit(const ObCharsetInfo *cs __attribute__((unused)), + char* src __attribute__((unused)), size_t srclen __attribute__((unused)), + char* dst __attribute__((unused)), size_t dstlen __attribute__((unused))); #ifdef __cplusplus } diff --git a/src/lib/charset/ob_ctype_bin.c b/src/lib/charset/ob_ctype_bin.c index 047a22828b4164214de53943192767cbc51d4f7c..00c0706221ddaff6cdf9418f6df224b5c2713284 100644 --- a/src/lib/charset/ob_ctype_bin.c +++ b/src/lib/charset/ob_ctype_bin.c @@ -14,366 +14,316 @@ static unsigned char ctype_bin[]= { - 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x28, 0x28, 0x28, 0x28, 0x28, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x48, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x10, 0x10, 0x10, 0x10, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16, + 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16, + 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32, + 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, 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, 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, }; -/* Dummy array for toupper / tolower / sortorder */ - static unsigned char bin_char_array[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, - 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 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, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 }; + +unsigned int ob_mbcharlen_8bit(const ObCharsetInfo *cs __attribute__((unused)), + unsigned int c __attribute__((unused))) +{ + return 1; +} + size_t ob_numchars_8bit(const ObCharsetInfo *cs __attribute__((unused)), - const char *str __attribute__((unused)), size_t len) + const char *begin, const char *end) { - return len; + return (size_t) (end - begin); } size_t ob_charpos_8bit(const ObCharsetInfo *cs __attribute__((unused)), - const char *str __attribute__((unused)), - size_t len __attribute__((unused)), - size_t pos) + const char *begin __attribute__((unused)), + const char *end __attribute__((unused)), + size_t pos) { return pos; } size_t ob_max_bytes_charpos_8bit(const ObCharsetInfo *cs __attribute__((unused)), - const char *str __attribute__((unused)), - size_t len __attribute__((unused)), - size_t max_bytes, - size_t *char_len) + const char *begin __attribute__((unused)), + const char *end __attribute__((unused)), + size_t max_bytes, + size_t *char_len) { *char_len = max_bytes; return max_bytes; } -size_t ob_well_formed_len_8bit(const char *str, size_t len, size_t nchars, int *error) +size_t ob_well_formed_len_8bit(const ObCharsetInfo *cs __attribute__((unused)), + const char *start, const char *end, + size_t nchars, int *error) { - size_t nbytes= len; + size_t nbytes= (size_t) (end-start); *error= 0; - return nbytes < nchars ? nbytes : nchars; + return OB_MIN(nbytes, nchars); } -size_t ob_lengthsp_binary(const char *str __attribute__((unused)), - size_t len) +size_t ob_lengthsp_binary(const ObCharsetInfo *cs __attribute__((unused)), + const char *ptr __attribute__((unused)), + size_t length) { - return len; + return length; } -static int ob_mb_wc_bin(const unsigned char *str, - const unsigned char *end __attribute__((unused)), - ob_wc_t *wc) +static int ob_mb_wc_bin(const ObCharsetInfo *cs __attribute__((unused)), + ob_wc_t *wc, + const unsigned char *str, + const unsigned char *end __attribute__((unused))) { if (str >= end) { - return OB_CS_ERR_TOOSMALL; + return OB_CS_TOOSMALL; + } else { + *wc=str[0]; } - - *wc=str[0]; return 1; } -static int ob_wc_mb_bin(ob_wc_t wc, unsigned char *s, - unsigned char *e __attribute__((unused))) -{ - if (s >= e) { - return OB_CS_ERR_TOOSMALL; - } - if (wc < 256) { - s[0]= (char) wc; +static int ob_wc_mb_bin(const ObCharsetInfo *cs __attribute__((unused)), + ob_wc_t wc, + unsigned char *str, + unsigned char *end __attribute__((unused))) +{ + if (str >= end) { + return OB_CS_TOOSMALL; + } else if (wc < 256) { + str[0] = (char) wc; return 1; } - return OB_CS_ERR_ILLEGAL_UNICODE; + return OB_CS_ILUNI; } -static int ob_mb_ctype_8bit(const ObCharsetInfo *cs, int *ctype, - const unsigned char *s, const unsigned char *e) +int ob_mb_ctype_8bit(const ObCharsetInfo *cs, int *ctype, + const unsigned char *str, const unsigned char *end) { - if (s >= e) { + if (str >= end) { *ctype= 0; - return OB_CS_ERR_TOOSMALL; + return OB_CS_TOOSMALL; } - *ctype= cs->ctype[*s + 1]; + *ctype= cs->ctype[*str + 1]; return 1; } static size_t ob_case_bin(const ObCharsetInfo *cs __attribute__((unused)), - char *src __attribute__((unused)), size_t srclen, - char *dst __attribute__((unused)), - size_t dstlen __attribute__((unused))) + char *src __attribute__((unused)), + size_t srclen, + char *dst __attribute__((unused)), + size_t dstlen __attribute__((unused))) { return srclen; } -//======================================================================== + static int ob_strnncoll_binary(const ObCharsetInfo *cs __attribute__((unused)), - const unsigned char *s, size_t slen, - const unsigned char *t, size_t tlen) + const unsigned char *str, size_t s_len, + const unsigned char *t, size_t t_len, + bool t_is_prefix) { - size_t len= slen < tlen ? slen : tlen; - int cmp= memcmp(s,t,len); - return cmp ? cmp : (int)(slen - tlen); + size_t len = OB_MIN(s_len,t_len); + int cmp = memcmp(str,t,len); + return cmp ? cmp : (int)((t_is_prefix ? len : s_len) - t_len); } -/* - Compare two strings. Result is sign(first_argument - second_argument) - - SYNOPSIS - ob_strnncollsp_binary() - cs Chararacter set - s String to compare - slen Length of 's' - t String to compare - tlen Length of 't' - - NOTE - This function is used for real binary strings, i.e. for - BLOB, BINARY(N) and VARBINARY(N). - It compares trailing spaces as spaces. - - RETURN - < 0 s < t - 0 s == t - > 0 s > t -*/ - static int ob_strnncollsp_binary(const ObCharsetInfo *cs __attribute__((unused)), - const unsigned char *s, size_t slen, - const unsigned char *t, size_t tlen) + const unsigned char *str, size_t s_len, + const unsigned char *t, size_t t_len, + bool diff_if_only_endspace_difference + __attribute__((unused))) { - return ob_strnncoll_binary(cs,s,slen,t,tlen); + return ob_strnncoll_binary(cs,str,s_len,t,t_len,0); } static size_t ob_strnxfrm_8bit_bin(const ObCharsetInfo *cs, - unsigned char * dst, size_t dstlen, uint32_t nweights, - const unsigned char *src, size_t srclen, - int *is_valid_unicode) + unsigned char * dst, size_t dstlen, unsigned int nweights, + const unsigned char *src, size_t srclen, unsigned int flags, + bool *is_valid_unicode __attribute__((unused))) { - *is_valid_unicode = 1; - srclen = (srclen < dstlen ? srclen : dstlen); - srclen = (srclen < nweights ? srclen : nweights); - if (dst != src && srclen > 0) { + set_if_smaller(srclen, dstlen); + set_if_smaller(srclen, nweights); + if (dst != src) { memcpy(dst, src, srclen); } - return srclen; + return ob_strxfrm_pad_desc_and_reverse(cs, dst, dst + srclen, dst + dstlen, + nweights - srclen, flags, 0); } -#define likeconv(s,A) (A) +#define likeconv(str,A) (A) #define INC_PTR(cs,A,B) (A)++ static int ob_wildcmp_bin_impl(const ObCharsetInfo *cs, - const char *str_ptr,const char *str_end_ptr, + const char *str,const char *str_end, const char *wild_str,const char *wild_end, - int escape_char, int w_one_char, int w_many_char, int recurse_level) + int escape_char, int w_one, int w_many, int recurse_level) { - int cmp_result= -1; + int result= -1; while (wild_str != wild_end) { - while (*wild_str != w_many_char && *wild_str != w_one_char) { + while (*wild_str != w_many && *wild_str != w_one) { if (*wild_str == escape_char && wild_str+1 != wild_end) { - wild_str++; - } - if (str_ptr == str_end_ptr || likeconv(cs,*wild_str++) != likeconv(cs,*str_ptr++)) { - return 1; + wild_str++; } - if (wild_str == wild_end) { - return str_ptr != str_end_ptr; + if (str == str_end || likeconv(cs,*wild_str++) != likeconv(cs,*str++)) { + return(1); + } else if (wild_str == wild_end) { + return(str != str_end); + } else { + result=1; } - cmp_result=1; } - if (*wild_str == w_one_char) { + if (*wild_str == w_one) { do { - if (str_ptr == str_end_ptr) { - return(cmp_result); + if (str == str_end) { + return(result); + } else { + INC_PTR(cs,str,str_end); } - INC_PTR(cs,str_ptr,str_end_ptr); - } while (++wild_str < wild_end && *wild_str == w_one_char); - if (wild_str == wild_end) { - break; - } + } while (++wild_str < wild_end && *wild_str == w_one); + if (wild_str == wild_end) break; } - if (*wild_str == w_many_char) { - unsigned char cmp = 0; - wild_str++; + if (*wild_str == w_many) { + unsigned char cmp; + wild_str++; for (; wild_str != wild_end ; wild_str++) { - if (*wild_str == w_many_char) { + if (*wild_str == w_many) { continue; - } - if (*wild_str == w_one_char) { - if (str_ptr == str_end_ptr) { + } else if (*wild_str == w_one) { + if (str == str_end) { return(-1); + } else { + INC_PTR(cs,str,str_end); + continue; } - INC_PTR(cs,str_ptr,str_end_ptr); - continue; } - break; + break; } if (wild_str == wild_end) { - return(0); - } - if (str_ptr == str_end_ptr) { - return(-1); - } - - if ((cmp= *wild_str) == escape_char && wild_str+1 != wild_end) { - cmp= *++wild_str; + return(0); + } else if (str == str_end) { + return(-1); + } else if ((cmp= *wild_str) == escape_char && wild_str+1 != wild_end) { + cmp= *++wild_str; } - INC_PTR(cs,wild_str,wild_end); + INC_PTR(cs,wild_str,wild_end); cmp=likeconv(cs,cmp); do { - while (str_ptr != str_end_ptr && (unsigned char) likeconv(cs,*str_ptr) != cmp) { - str_ptr++; + while (str != str_end && (unsigned char) likeconv(cs,*str) != cmp) { + str++; } - if (str_ptr++ == str_end_ptr) { - return -1; + if (str++ == str_end) { + return(-1); } - do { - int tmp=ob_wildcmp_bin_impl(cs,str_ptr,str_end_ptr, - wild_str,wild_end,escape_char, - w_one_char, w_many_char, recurse_level + 1); - if (tmp <= 0) { - return tmp; - } - } while (0); - } while (str_ptr != str_end_ptr && wild_str[0] != w_many_char); - return -1; + { + int tmp=ob_wildcmp_bin_impl(cs,str,str_end, + wild_str,wild_end,escape_char, + w_one, w_many, recurse_level + 1); + if (tmp <= 0) + return(tmp); + } + } while (str != str_end && wild_str[0] != w_many); + return(-1); } } - return str_ptr != str_end_ptr ? 1 : 0; + return(str != str_end ? 1 : 0); } int ob_wildcmp_bin(const ObCharsetInfo *cs, const char *str,const char *str_end, - const char *wildstr,const char *wildend, - int escape, int w_one, int w_many) + const char *wild_str,const char *wild_end, + int escape_char, int w_one, int w_many) { return ob_wildcmp_bin_impl(cs, str, str_end, - wildstr, wildend, - escape, w_one, w_many, 1); + wild_str, wild_end, + escape_char, w_one, w_many, 1); } static -uint32_t ob_instr_bin(const ObCharsetInfo *cs __attribute__((unused)), - const char *b, size_t b_length, +unsigned int ob_instr_bin(const ObCharsetInfo *cs __attribute__((unused)), + const char *begin, size_t b_length, const char *s, size_t s_length, - ob_match_info *match, uint32_t nmatch) + ob_match_t *match, unsigned int nmatch) { - register const unsigned char *str, *search, *end, *search_end; - - if (s_length <= b_length) - { - if (!s_length) - { - if (nmatch) - { + const unsigned char *str, *search, *end, *search_end; + + if (s_length <= b_length) { + if (!s_length) { + if (nmatch) { match->beg= 0; match->end= 0; match->mb_len= 0; } - return 1; /* Empty string is always found */ + return 1; } - str= (const unsigned char*) b; + str= (const unsigned char*) begin; search= (const unsigned char*) s; - end= (const unsigned char*) b+b_length-s_length+1; + end= (const unsigned char*) begin+b_length-s_length+1; search_end= (const unsigned char*) s + s_length; -skip: - while (str != end) - { - if ( (*str++) == (*search)) - { - register const unsigned char *i,*j; - - i= str; - j= search+1; - - while (j != search_end) - if ((*i++) != (*j++)) - goto skip; - - if (nmatch > 0) - { - match[0].beg= 0; - match[0].end= (size_t) (str- (const unsigned char*)b-1); - match[0].mb_len= match[0].end; - - if (nmatch > 1) - { - match[1].beg= match[0].end; - match[1].end= match[0].end+s_length; - match[1].mb_len= match[1].end-match[1].beg; - } - } - return 2; +loop: + while (str != end) { + if ( (*str++) == (*search)) { + const unsigned char *i, *j; + i= str; + j= search+1; + + while (j != search_end) { + if ((*i++) != (*j++)) { + goto loop; + } + } + + if (nmatch > 0) { + match[0].beg= 0; + match[0].end= (size_t) (str- (const unsigned char*)begin-1); + match[0].mb_len= match[0].end; + + if (nmatch > 1) { + match[1].beg= match[0].end; + match[1].end= match[0].end+s_length; + match[1].mb_len= match[1].end-match[1].beg; + } + } + return 2; } } } @@ -381,30 +331,30 @@ skip: } void ob_hash_sort_bin(const ObCharsetInfo *cs __attribute__((unused)), - const unsigned char *key, size_t len,uint64_t *nr1, uint64_t *nr2, - const int calc_end_space __attribute__((unused)), hash_algo hash_algo) + const unsigned char *key, size_t len, unsigned long int *nr1, unsigned long int *nr2, + const bool calc_end_space, + hash_algo hash_algo) { const unsigned char *pos = key; - key+= len; - if (NULL == hash_algo) - { - for (; pos < (unsigned char*) key ; pos++) - { - nr1[0]^=(uint64_t) ((((uint64_t) nr1[0] & 63)+nr2[0]) * - ((uint32_t)*pos)) + (nr1[0] << 8); + if (NULL == hash_algo) { + while (pos < (unsigned char*) key) { + nr1[0]^=(unsigned long int) ((((unsigned int) nr1[0] & 63)+nr2[0]) * + ((unsigned int)*pos)) + (nr1[0] << 8); nr2[0]+=3; + pos++; } } else { nr1[0] = hash_algo((void*)pos, (int)(key - pos), nr1[0]); } } -//======================================================================== + static ObCharsetHandler ob_charset_handler= { - NULL, + NULL, + ob_mbcharlen_8bit, ob_numchars_8bit, ob_charpos_8bit, ob_max_bytes_charpos_8bit, @@ -416,6 +366,8 @@ static ObCharsetHandler ob_charset_handler= ob_case_bin, ob_case_bin, ob_fill_8bit, + ob_strntol_8bit, + ob_strntoul_8bit, ob_strntoll_8bit, ob_strntoull_8bit, ob_strntod_8bit, @@ -423,7 +375,7 @@ static ObCharsetHandler ob_charset_handler= ob_scan_8bit }; -static ObCollationHandler ob_collation_binary_handler = +ObCollationHandler ob_collation_binary_handler = { ob_strnncoll_binary, ob_strnncollsp_binary, @@ -432,34 +384,36 @@ static ObCollationHandler ob_collation_binary_handler = ob_wildcmp_bin, ob_instr_bin, ob_hash_sort_bin, + ob_propagate_simple }; ObCharsetInfo ob_charset_bin = { - 63,0,0, /* number */ - OB_CS_COMPILED|OB_CS_BINSORT|OB_CS_PRIMARY,/* state */ - "binary", /* cs name */ - "binary", /* name */ - "", /* comment */ - NULL, /* tailoring */ - ctype_bin, /* ctype */ - bin_char_array, /* to_lower */ - bin_char_array, /* to_upper */ - NULL, /* sort_order */ - NULL, /* caseinfo */ - NULL, /* state_map */ - NULL, /* ident_map */ - 1, /* strxfrm_multiply */ - 1, /* caseup_multiply */ - 1, /* casedn_multiply */ - 1, /* mbminlen */ - 1, /* mbmaxlen */ - 0, /* min_sort_char */ - 255, /* max_sort_char */ - 0, /* pad char */ - 0, /* escape_with_backslash_is_dangerous */ - 1, /* levels_for_compare */ - 1, /* levels_for_order */ + 63,0,0, + OB_CS_COMPILED|OB_CS_BINSORT|OB_CS_PRIMARY, + "binary", + "binary", + "", + NULL, + ctype_bin, + bin_char_array, + bin_char_array, + NULL, + NULL, + &ob_unicase_default, + NULL, + NULL, + 1, + 1, + 1, + 1, + 1, + 0, + 255, + 0, + 0, + 1, + 1, &ob_charset_handler, &ob_collation_binary_handler }; diff --git a/src/lib/charset/ob_ctype_gb18030.cc b/src/lib/charset/ob_ctype_gb18030.cc new file mode 100644 index 0000000000000000000000000000000000000000..48bcdcc5366cd1e2a0c36b679caf25d2390c9f4b --- /dev/null +++ b/src/lib/charset/ob_ctype_gb18030.cc @@ -0,0 +1,19889 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#include "lib/charset/ob_ctype.h" + +#define is_mb_1(c) ((unsigned char)(c) <= 0x7F) +#define is_mb_odd(c) (0x81 <= (unsigned char)(c) && (unsigned char)(c) <= 0xFE) +#define is_mb_even_2(c) \ + ((0x40 <= (unsigned char)(c) && (unsigned char)(c) <= 0x7E) || \ + (0x80 <= (unsigned char)(c) && (unsigned char)(c) <= 0xFE)) +#define is_mb_even_4(c) (0x30 <= (unsigned char)(c) && (unsigned char)(c) <= 0x39) + +static const unsigned int MIN_MB_ODD_BYTE = 0x81; +static const unsigned int MIN_MB_EVEN_BYTE_2 = 0x40; +static const unsigned int MIN_MB_EVEN_BYTE_4 = 0x30; + +static const unsigned int MAX_GB18030_DIFF = 0x18398F; + + +static const unsigned int UNI2_TO_GB4_DIFF = 7456; + +static const unsigned int UNICASE_4_BYTE_OFFSET = 0x80; + +static const unsigned int MIN_2_BYTE_UNICASE = 0xA000; +static const unsigned int MAX_2_BYTE_UNICASE = 0xDFFF; + +static const unsigned int MIN_3_BYTE_FROM_UNI = 0x2E600; +static const unsigned int MAX_3_BYTE_FROM_UNI = 0x2E6FF; + +static const unsigned int PINYIN_2_BYTE_START = 0x8140; +static const unsigned int PINYIN_2_BYTE_END = 0xFE9F; + +static const unsigned int PINYIN_4_BYTE_1_START = 0x8138FD38; +static const unsigned int PINYIN_4_BYTE_1_END = 0x82359232; +static const unsigned int PINYIN_4_1_DIFF = 11328; + +static const unsigned int PINYIN_4_BYTE_2_START = 0x95328236; +static const unsigned int PINYIN_4_BYTE_2_END = 0x98399836; +static const unsigned int PINYIN_4_2_DIFF = 254536; + +static const unsigned int PINYIN_WEIGHT_BASE = 0xFFA00000; +static const unsigned int COMMON_WEIGHT_BASE = 0xFF000000; + +static unsigned char ctype_gb18030[257] = { + 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 16, 16, 16, 16, 16, 16, + 16, 129, 129, 129, 129, 129, 129, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16, + 16, 130, 130, 130, 130, 130, 130, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0}; + +static unsigned char to_lower_gb18030[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, ' ', '!', '"', '#', + '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', + '<', '=', '>', '?', '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\', ']', '^', '_', + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', '{', '|', '}', '~', 0x7F, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, + 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, + 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, + 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, + 0xFC, 0xFD, 0xFE, 0xFF}; + +static unsigned char to_upper_gb18030[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, ' ', '!', '"', '#', + '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', + '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', + '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '{', '|', '}', '~', 0x7F, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, + 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, + 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, + 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, + 0xFC, 0xFD, 0xFE, 0xFF}; + +static uchar sort_order_gb18030_ci[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, ' ', '!', '"', '#', + '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', + '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', + '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '{', '|', '}', '~', 0x7F, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, + 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, + 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, + 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, + 0xFC, 0xFD, 0xFE, 0xFF}; + +static ObUnicaseInfoChar plane00[] = { + {0x0000, 0x0000, 0x0000}, {0x0001, 0x0001, 0x0001}, + {0x0002, 0x0002, 0x0002}, {0x0003, 0x0003, 0x0003}, + {0x0004, 0x0004, 0x0004}, {0x0005, 0x0005, 0x0005}, + {0x0006, 0x0006, 0x0006}, {0x0007, 0x0007, 0x0007}, + {0x0008, 0x0008, 0x0008}, {0x0009, 0x0009, 0x0009}, + {0x000A, 0x000A, 0x000A}, {0x000B, 0x000B, 0x000B}, + {0x000C, 0x000C, 0x000C}, {0x000D, 0x000D, 0x000D}, + {0x000E, 0x000E, 0x000E}, {0x000F, 0x000F, 0x000F}, + {0x0010, 0x0010, 0x0010}, {0x0011, 0x0011, 0x0011}, + {0x0012, 0x0012, 0x0012}, {0x0013, 0x0013, 0x0013}, + {0x0014, 0x0014, 0x0014}, {0x0015, 0x0015, 0x0015}, + {0x0016, 0x0016, 0x0016}, {0x0017, 0x0017, 0x0017}, + {0x0018, 0x0018, 0x0018}, {0x0019, 0x0019, 0x0019}, + {0x001A, 0x001A, 0x001A}, {0x001B, 0x001B, 0x001B}, + {0x001C, 0x001C, 0x001C}, {0x001D, 0x001D, 0x001D}, + {0x001E, 0x001E, 0x001E}, {0x001F, 0x001F, 0x001F}, + {0x0020, 0x0020, 0x0020}, {0x0021, 0x0021, 0x0021}, + {0x0022, 0x0022, 0x0022}, {0x0023, 0x0023, 0x0023}, + {0x0024, 0x0024, 0x0024}, {0x0025, 0x0025, 0x0025}, + {0x0026, 0x0026, 0x0026}, {0x0027, 0x0027, 0x0027}, + {0x0028, 0x0028, 0x0028}, {0x0029, 0x0029, 0x0029}, + {0x002A, 0x002A, 0x002A}, {0x002B, 0x002B, 0x002B}, + {0x002C, 0x002C, 0x002C}, {0x002D, 0x002D, 0x002D}, + {0x002E, 0x002E, 0x002E}, {0x002F, 0x002F, 0x002F}, + {0x0030, 0x0030, 0x0030}, {0x0031, 0x0031, 0x0031}, + {0x0032, 0x0032, 0x0032}, {0x0033, 0x0033, 0x0033}, + {0x0034, 0x0034, 0x0034}, {0x0035, 0x0035, 0x0035}, + {0x0036, 0x0036, 0x0036}, {0x0037, 0x0037, 0x0037}, + {0x0038, 0x0038, 0x0038}, {0x0039, 0x0039, 0x0039}, + {0x003A, 0x003A, 0x003A}, {0x003B, 0x003B, 0x003B}, + {0x003C, 0x003C, 0x003C}, {0x003D, 0x003D, 0x003D}, + {0x003E, 0x003E, 0x003E}, {0x003F, 0x003F, 0x003F}, + {0x0040, 0x0040, 0x0040}, {0x0041, 0x0061, 0x0041}, + {0x0042, 0x0062, 0x0042}, {0x0043, 0x0063, 0x0043}, + {0x0044, 0x0064, 0x0044}, {0x0045, 0x0065, 0x0045}, + {0x0046, 0x0066, 0x0046}, {0x0047, 0x0067, 0x0047}, + {0x0048, 0x0068, 0x0048}, {0x0049, 0x0069, 0x0049}, + {0x004A, 0x006A, 0x004A}, {0x004B, 0x006B, 0x004B}, + {0x004C, 0x006C, 0x004C}, {0x004D, 0x006D, 0x004D}, + {0x004E, 0x006E, 0x004E}, {0x004F, 0x006F, 0x004F}, + {0x0050, 0x0070, 0x0050}, {0x0051, 0x0071, 0x0051}, + {0x0052, 0x0072, 0x0052}, {0x0053, 0x0073, 0x0053}, + {0x0054, 0x0074, 0x0054}, {0x0055, 0x0075, 0x0055}, + {0x0056, 0x0076, 0x0056}, {0x0057, 0x0077, 0x0057}, + {0x0058, 0x0078, 0x0058}, {0x0059, 0x0079, 0x0059}, + {0x005A, 0x007A, 0x005A}, {0x005B, 0x005B, 0x005B}, + {0x005C, 0x005C, 0x005C}, {0x005D, 0x005D, 0x005D}, + {0x005E, 0x005E, 0x005E}, {0x005F, 0x005F, 0x005F}, + {0x0060, 0x0060, 0x0060}, {0x0041, 0x0061, 0x0041}, + {0x0042, 0x0062, 0x0042}, {0x0043, 0x0063, 0x0043}, + {0x0044, 0x0064, 0x0044}, {0x0045, 0x0065, 0x0045}, + {0x0046, 0x0066, 0x0046}, {0x0047, 0x0067, 0x0047}, + {0x0048, 0x0068, 0x0048}, {0x0049, 0x0069, 0x0049}, + {0x004A, 0x006A, 0x004A}, {0x004B, 0x006B, 0x004B}, + {0x004C, 0x006C, 0x004C}, {0x004D, 0x006D, 0x004D}, + {0x004E, 0x006E, 0x004E}, {0x004F, 0x006F, 0x004F}, + {0x0050, 0x0070, 0x0050}, {0x0051, 0x0071, 0x0051}, + {0x0052, 0x0072, 0x0052}, {0x0053, 0x0073, 0x0053}, + {0x0054, 0x0074, 0x0054}, {0x0055, 0x0075, 0x0055}, + {0x0056, 0x0076, 0x0056}, {0x0057, 0x0077, 0x0057}, + {0x0058, 0x0078, 0x0058}, {0x0059, 0x0079, 0x0059}, + {0x005A, 0x007A, 0x005A}, {0x007B, 0x007B, 0x007B}, + {0x007C, 0x007C, 0x007C}, {0x007D, 0x007D, 0x007D}, + {0x007E, 0x007E, 0x007E}, {0x007F, 0x007F, 0x007F}, + {0x0080, 0x0080, 0x0080}, {0x0081, 0x0081, 0x0081}, + {0x0082, 0x0082, 0x0082}, {0x0083, 0x0083, 0x0083}, + {0x0084, 0x0084, 0x0084}, {0x0085, 0x0085, 0x0085}, + {0x0086, 0x0086, 0x0086}, {0x0087, 0x0087, 0x0087}, + {0x0088, 0x0088, 0x0088}, {0x0089, 0x0089, 0x0089}, + {0x008A, 0x008A, 0x008A}, {0x008B, 0x008B, 0x008B}, + {0x008C, 0x008C, 0x008C}, {0x008D, 0x008D, 0x008D}, + {0x008E, 0x008E, 0x008E}, {0x008F, 0x008F, 0x008F}, + {0x0090, 0x0090, 0x0090}, {0x0091, 0x0091, 0x0091}, + {0x0092, 0x0092, 0x0092}, {0x0093, 0x0093, 0x0093}, + {0x0094, 0x0094, 0x0094}, {0x0095, 0x0095, 0x0095}, + {0x0096, 0x0096, 0x0096}, {0x0097, 0x0097, 0x0097}, + {0x0098, 0x0098, 0x0098}, {0x0099, 0x0099, 0x0099}, + {0x009A, 0x009A, 0x009A}, {0x009B, 0x009B, 0x009B}, + {0x009C, 0x009C, 0x009C}, {0x009D, 0x009D, 0x009D}, + {0x009E, 0x009E, 0x009E}, {0x009F, 0x009F, 0x009F}, + {0x00A0, 0x00A0, 0x00A0}, {0x00A1, 0x00A1, 0x00A1}, + {0x00A2, 0x00A2, 0x00A2}, {0x00A3, 0x00A3, 0x00A3}, + {0x00A4, 0x00A4, 0x00A4}, {0x00A5, 0x00A5, 0x00A5}, + {0x00A6, 0x00A6, 0x00A6}, {0x00A7, 0x00A7, 0x00A7}, + {0x00A8, 0x00A8, 0x00A8}, {0x00A9, 0x00A9, 0x00A9}, + {0x00AA, 0x00AA, 0x00AA}, {0x00AB, 0x00AB, 0x00AB}, + {0x00AC, 0x00AC, 0x00AC}, {0x00AD, 0x00AD, 0x00AD}, + {0x00AE, 0x00AE, 0x00AE}, {0x00AF, 0x00AF, 0x00AF}, + {0x00B0, 0xA6CC, 0x00B5}, {0x00B1, 0x00B1, 0x00B1}, + {0x00B2, 0x00B2, 0x00B2}, {0x00B3, 0x00B3, 0x00B3}, + {0x00B4, 0x00B4, 0x00B4}, {0x00B5, 0x00B5, 0x00B5}, + {0x00B6, 0x00B6, 0x00B6}, {0x00B7, 0x00B7, 0x00B7}, + {0x00B8, 0x00B8, 0x00B8}, {0x00B9, 0x00B9, 0x00B9}, + {0x00BA, 0xA8A4, 0x00C0}, {0x00BB, 0xA8A2, 0x00C1}, + {0x00BC, 0x00D9, 0x00C2}, {0x00BD, 0x00DA, 0x00C3}, + {0x00BE, 0x00DB, 0x00C4}, {0x00BF, 0x00DC, 0x00C5}, + {0x00C0, 0x00DD, 0x00C6}, {0x00C1, 0x00DE, 0x00C7}, + {0x00C2, 0xA8A8, 0x00C8}, {0x00C3, 0xA8A6, 0x00C9}, + {0x00C4, 0xA8BA, 0x00CA}, {0x00C5, 0x00DF, 0x00CB}, + {0x00C6, 0xA8AC, 0x00CC}, {0x00C7, 0xA8AA, 0x00CD}, + {0x00C8, 0x00E0, 0x00CE}, {0x00C9, 0x00E1, 0x00CF}, + {0x00CA, 0x00E2, 0x00D0}, {0x00CB, 0x00E3, 0x00D1}, + {0x00CC, 0xA8B0, 0x00D2}, {0x00CD, 0xA8AE, 0x00D3}, + {0x00CE, 0x00E4, 0x00D4}, {0x00CF, 0x00E5, 0x00D5}, + {0x00D0, 0x00E6, 0x00D6}, {0x00D1, 0x00E7, 0x00D8}, + {0x00D2, 0xA8B4, 0x00D9}, {0x00D3, 0xA8B2, 0x00DA}, + {0x00D4, 0x00E8, 0x00DB}, {0x00D5, 0xA8B9, 0x00DC}, + {0x00D6, 0x00E9, 0x00DD}, {0x00D7, 0x00EA, 0x00DE}, + {0x00D8, 0x00D8, 0x00DF}, {0x00BC, 0x00D9, 0x00C2}, + {0x00BD, 0x00DA, 0x00C3}, {0x00BE, 0x00DB, 0x00C4}, + {0x00BF, 0x00DC, 0x00C5}, {0x00C0, 0x00DD, 0x00C6}, + {0x00C1, 0x00DE, 0x00C7}, {0x00C5, 0x00DF, 0x00CB}, + {0x00C8, 0x00E0, 0x00CE}, {0x00C9, 0x00E1, 0x00CF}, + {0x00CA, 0x00E2, 0x00D0}, {0x00CB, 0x00E3, 0x00D1}, + {0x00CE, 0x00E4, 0x00D4}, {0x00CF, 0x00E5, 0x00D5}, + {0x00D0, 0x00E6, 0x00D6}, {0x00D1, 0x00E7, 0x00D8}, + {0x00D4, 0x00E8, 0x00DB}, {0x00D6, 0x00E9, 0x00DD}, + {0x00D7, 0x00EA, 0x00DE}, {0x015C, 0x00EB, 0x0178}, + {0x00EC, 0xA8A1, 0x0100}, {0x00ED, 0x00EE, 0x0102}, + {0x00ED, 0x00EE, 0x0102}, {0x00EF, 0x00F0, 0x0104}, + {0x00EF, 0x00F0, 0x0104}, {0x00F1, 0x00F2, 0x0106}, + {0x00F1, 0x00F2, 0x0106}, {0x00F3, 0x00F4, 0x0108}, + {0x00F3, 0x00F4, 0x0108}, {0x00F5, 0x00F6, 0x010A}, + {0x00F5, 0x00F6, 0x010A}, {0x00F7, 0x00F8, 0x010C}, + {0x00F7, 0x00F8, 0x010C}, {0x00F9, 0x00FA, 0x010E}, + {0x00F9, 0x00FA, 0x010E}, {0x00FB, 0x00FC, 0x0110}, + {0x00FB, 0x00FC, 0x0110}, {0x00FD, 0xA8A5, 0x0112}, + {0x00FE, 0x00FF, 0x0114}, {0x00FE, 0x00FF, 0x0114}}; + +static ObUnicaseInfoChar plane01[] = { + {0x0100, 0x0101, 0x0116}, {0x0100, 0x0101, 0x0116}, + {0x0102, 0x0103, 0x0118}, {0x0102, 0x0103, 0x0118}, + {0x0104, 0xA8A7, 0x011A}, {0x0105, 0x0106, 0x011C}, + {0x0105, 0x0106, 0x011C}, {0x0107, 0x0108, 0x011E}, + {0x0107, 0x0108, 0x011E}, {0x0109, 0x010A, 0x0120}, + {0x0109, 0x010A, 0x0120}, {0x010B, 0x010C, 0x0122}, + {0x010B, 0x010C, 0x0122}, {0x010D, 0x010E, 0x0124}, + {0x010D, 0x010E, 0x0124}, {0x010F, 0x0110, 0x0126}, + {0x010F, 0x0110, 0x0126}, {0x0111, 0x0112, 0x0128}, + {0x0111, 0x0112, 0x0128}, {0x0113, 0xA8A9, 0x012A}, + {0x0114, 0x0115, 0x012C}, {0x0114, 0x0115, 0x012C}, + {0x0116, 0x0117, 0x012E}, {0x0116, 0x0117, 0x012E}, + {0x0118, 0x0069, 0x0130}, {0x0049, 0x0119, 0x0049}, + {0x011A, 0x011B, 0x0132}, {0x011A, 0x011B, 0x0132}, + {0x011C, 0x011D, 0x0134}, {0x011C, 0x011D, 0x0134}, + {0x011E, 0x011F, 0x0136}, {0x011E, 0x011F, 0x0136}, + {0x0120, 0x0120, 0x0138}, {0x0121, 0x0122, 0x0139}, + {0x0121, 0x0122, 0x0139}, {0x0123, 0x0124, 0x013B}, + {0x0123, 0x0124, 0x013B}, {0x0125, 0x0126, 0x013D}, + {0x0125, 0x0126, 0x013D}, {0x0127, 0x0128, 0x013F}, + {0x0127, 0x0128, 0x013F}, {0x0129, 0x012A, 0x0141}, + {0x0129, 0x012A, 0x0141}, {0x012B, 0xA8BD, 0x0143}, + {0x012C, 0x012D, 0x0145}, {0x012C, 0x012D, 0x0145}, + {0x012E, 0xA8BE, 0x0147}, {0x012F, 0x012F, 0x0149}, + {0x0130, 0x0131, 0x014A}, {0x0130, 0x0131, 0x014A}, + {0x0132, 0xA8AD, 0x014C}, {0x0133, 0x0134, 0x014E}, + {0x0133, 0x0134, 0x014E}, {0x0135, 0x0136, 0x0150}, + {0x0135, 0x0136, 0x0150}, {0x0137, 0x0138, 0x0152}, + {0x0137, 0x0138, 0x0152}, {0x0139, 0x013A, 0x0154}, + {0x0139, 0x013A, 0x0154}, {0x013B, 0x013C, 0x0156}, + {0x013B, 0x013C, 0x0156}, {0x013D, 0x013E, 0x0158}, + {0x013D, 0x013E, 0x0158}, {0x013F, 0x0140, 0x015A}, + {0x013F, 0x0140, 0x015A}, {0x0141, 0x0142, 0x015C}, + {0x0141, 0x0142, 0x015C}, {0x0143, 0x0144, 0x015E}, + {0x0143, 0x0144, 0x015E}, {0x0145, 0x0146, 0x0160}, + {0x0145, 0x0146, 0x0160}, {0x0147, 0x0148, 0x0162}, + {0x0147, 0x0148, 0x0162}, {0x0149, 0x014A, 0x0164}, + {0x0149, 0x014A, 0x0164}, {0x014B, 0x014C, 0x0166}, + {0x014B, 0x014C, 0x0166}, {0x014D, 0x014E, 0x0168}, + {0x014D, 0x014E, 0x0168}, {0x014F, 0xA8B1, 0x016A}, + {0x0150, 0x0151, 0x016C}, {0x0150, 0x0151, 0x016C}, + {0x0152, 0x0153, 0x016E}, {0x0152, 0x0153, 0x016E}, + {0x0154, 0x0155, 0x0170}, {0x0154, 0x0155, 0x0170}, + {0x0156, 0x0157, 0x0172}, {0x0156, 0x0157, 0x0172}, + {0x0158, 0x0159, 0x0174}, {0x0158, 0x0159, 0x0174}, + {0x015A, 0x015B, 0x0176}, {0x015A, 0x015B, 0x0176}, + {0x015C, 0x00EB, 0x0178}, {0x015D, 0x015E, 0x0179}, + {0x015D, 0x015E, 0x0179}, {0x015F, 0x0160, 0x017B}, + {0x015F, 0x0160, 0x017B}, {0x0161, 0x0162, 0x017D}, + {0x0161, 0x0162, 0x017D}, {0x0053, 0x0163, 0x017F}, + {0x021E, 0x0164, 0x0243}, {0x0165, 0x022D, 0x0181}, + {0x0166, 0x0167, 0x0182}, {0x0166, 0x0167, 0x0182}, + {0x0168, 0x0169, 0x0184}, {0x0168, 0x0169, 0x0184}, + {0x016A, 0x022E, 0x0186}, {0x016B, 0x016C, 0x0187}, + {0x016B, 0x016C, 0x0187}, {0x016D, 0x0230, 0x0189}, + {0x016E, 0x0231, 0x018A}, {0x016F, 0x0170, 0x018B}, + {0x016F, 0x0170, 0x018B}, {0x0171, 0x0171, 0x018D}, + {0x0172, 0x01B9, 0x018E}, {0x0173, 0x0233, 0x018F}, + {0x0174, 0x0235, 0x0190}, {0x0175, 0x0176, 0x0191}, + {0x0175, 0x0176, 0x0191}, {0x0177, 0x023A, 0x0193}, + {0x0178, 0x023C, 0x0194}, {0x01D2, 0x0179, 0x01F6}, + {0x017A, 0x0242, 0x0196}, {0x017B, 0x0241, 0x0197}, + {0x017C, 0x017D, 0x0198}, {0x017C, 0x017D, 0x0198}, + {0x0218, 0x017E, 0x023D}, {0x017F, 0x017F, 0x019B}, + {0x0180, 0x0248, 0x019C}, {0x0181, 0x024B, 0x019D}, + {0x01FB, 0x0182, 0x0220}, {0x0183, 0x024E, 0x019F}, + {0x0184, 0x0185, 0x01A0}, {0x0184, 0x0185, 0x01A0}, + {0x0186, 0x0187, 0x01A2}, {0x0186, 0x0187, 0x01A2}, + {0x0188, 0x0189, 0x01A4}, {0x0188, 0x0189, 0x01A4}, + {0x018A, 0x0259, 0x01A6}, {0x018B, 0x018C, 0x01A7}, + {0x018B, 0x018C, 0x01A7}, {0x018D, 0x025C, 0x01A9}, + {0x018E, 0x018E, 0x01AA}, {0x018F, 0x018F, 0x01AB}, + {0x0190, 0x0191, 0x01AC}, {0x0190, 0x0191, 0x01AC}, + {0x0192, 0x0261, 0x01AE}, {0x0193, 0x0194, 0x01AF}, + {0x0193, 0x0194, 0x01AF}, {0x0195, 0x0263, 0x01B1}, + {0x0196, 0x0264, 0x01B2}, {0x0197, 0x0198, 0x01B3}, + {0x0197, 0x0198, 0x01B3}, {0x0199, 0x019A, 0x01B5}, + {0x0199, 0x019A, 0x01B5}, {0x019B, 0x026B, 0x01B7}, + {0x019C, 0x019D, 0x01B8}, {0x019C, 0x019D, 0x01B8}, + {0x019E, 0x019E, 0x01BA}, {0x019F, 0x019F, 0x01BB}, + {0x01A0, 0x01A1, 0x01BC}, {0x01A0, 0x01A1, 0x01BC}, + {0x01A2, 0x01A2, 0x01BE}, {0x01D3, 0x01A3, 0x01F7}, + {0x01A4, 0x01A4, 0x01C0}, {0x01A5, 0x01A5, 0x01C1}, + {0x01A6, 0x01A6, 0x01C2}, {0x01A7, 0x01A7, 0x01C3}, + {0x01A8, 0x01AA, 0x01C4}, {0x01A9, 0x01AA, 0x01C5}, + {0x01A8, 0x01AA, 0x01C4}, {0x01AB, 0x01AD, 0x01C7}, + {0x01AC, 0x01AD, 0x01C8}, {0x01AB, 0x01AD, 0x01C7}, + {0x01AE, 0x01B0, 0x01CA}, {0x01AF, 0x01B0, 0x01CB}, + {0x01AE, 0x01B0, 0x01CA}, {0x01B1, 0xA8A3, 0x01CD}, + {0x01B2, 0xA8AB, 0x01CF}, {0x01B3, 0xA8AF, 0x01D1}, + {0x01B4, 0xA8B3, 0x01D3}, {0x01B5, 0xA8B5, 0x01D5}, + {0x01B6, 0xA8B6, 0x01D7}, {0x01B7, 0xA8B7, 0x01D9}, + {0x01B8, 0xA8B8, 0x01DB}, {0x0172, 0x01B9, 0x018E}, + {0x01BA, 0x01BB, 0x01DE}, {0x01BA, 0x01BB, 0x01DE}, + {0x01BC, 0x01BD, 0x01E0}, {0x01BC, 0x01BD, 0x01E0}, + {0x01BE, 0x01BF, 0x01E2}, {0x01BE, 0x01BF, 0x01E2}, + {0x01C0, 0x01C1, 0x01E4}, {0x01C0, 0x01C1, 0x01E4}, + {0x01C2, 0x01C3, 0x01E6}, {0x01C2, 0x01C3, 0x01E6}, + {0x01C4, 0x01C5, 0x01E8}, {0x01C4, 0x01C5, 0x01E8}, + {0x01C6, 0x01C7, 0x01EA}, {0x01C6, 0x01C7, 0x01EA}, + {0x01C8, 0x01C9, 0x01EC}, {0x01C8, 0x01C9, 0x01EC}, + {0x01CA, 0x01CB, 0x01EE}, {0x01CA, 0x01CB, 0x01EE}, + {0x01CC, 0x01CC, 0x01F0}, {0x01CD, 0x01CF, 0x01F1}, + {0x01CE, 0x01CF, 0x01F2}, {0x01CD, 0x01CF, 0x01F1}, + {0x01D0, 0x01D1, 0x01F4}, {0x01D0, 0x01D1, 0x01F4}, + {0x01D2, 0x0179, 0x01F6}, {0x01D3, 0x01A3, 0x01F7}, + {0x01D4, 0xA8BF, 0x01F8}, {0x01D5, 0x01D6, 0x01FA}, + {0x01D5, 0x01D6, 0x01FA}, {0x01D7, 0x01D8, 0x01FC}, + {0x01D7, 0x01D8, 0x01FC}, {0x01D9, 0x01DA, 0x01FE}, + {0x01D9, 0x01DA, 0x01FE}, {0x01DB, 0x01DC, 0x0200}, + {0x01DB, 0x01DC, 0x0200}, {0x01DD, 0x01DE, 0x0202}, + {0x01DD, 0x01DE, 0x0202}, {0x01DF, 0x01E0, 0x0204}, + {0x01DF, 0x01E0, 0x0204}, {0x01E1, 0x01E2, 0x0206}, + {0x01E1, 0x01E2, 0x0206}, {0x01E3, 0x01E4, 0x0208}, + {0x01E3, 0x01E4, 0x0208}, {0x01E5, 0x01E6, 0x020A}, + {0x01E5, 0x01E6, 0x020A}, {0x01E7, 0x01E8, 0x020C}, + {0x01E7, 0x01E8, 0x020C}, {0x01E9, 0x01EA, 0x020E}, + {0x01E9, 0x01EA, 0x020E}, {0x01EB, 0x01EC, 0x0210}, + {0x01EB, 0x01EC, 0x0210}, {0x01ED, 0x01EE, 0x0212}, + {0x01ED, 0x01EE, 0x0212}, {0x01EF, 0x01F0, 0x0214}, + {0x01EF, 0x01F0, 0x0214}, {0x01F1, 0x01F2, 0x0216}, + {0x01F1, 0x01F2, 0x0216}, {0x01F3, 0x01F4, 0x0218}, + {0x01F3, 0x01F4, 0x0218}, {0x01F5, 0x01F6, 0x021A}, + {0x01F5, 0x01F6, 0x021A}, {0x01F7, 0x01F8, 0x021C}, + {0x01F7, 0x01F8, 0x021C}, {0x01F9, 0x01FA, 0x021E}, + {0x01F9, 0x01FA, 0x021E}, {0x01FB, 0x0182, 0x0220}, + {0x01FC, 0x01FC, 0x0221}, {0x01FD, 0x01FE, 0x0222}, + {0x01FD, 0x01FE, 0x0222}, {0x01FF, 0x0200, 0x0224}}; + +static ObUnicaseInfoChar plane02[] = { + {0x01FF, 0x0200, 0x0224}, {0x0201, 0x0202, 0x0226}, + {0x0201, 0x0202, 0x0226}, {0x0203, 0x0204, 0x0228}, + {0x0203, 0x0204, 0x0228}, {0x0205, 0x0206, 0x022A}, + {0x0205, 0x0206, 0x022A}, {0x0207, 0x0208, 0x022C}, + {0x0207, 0x0208, 0x022C}, {0x0209, 0x020A, 0x022E}, + {0x0209, 0x020A, 0x022E}, {0x020B, 0x020C, 0x0230}, + {0x020B, 0x020C, 0x0230}, {0x020D, 0x020E, 0x0232}, + {0x020D, 0x020E, 0x0232}, {0x020F, 0x020F, 0x0234}, + {0x0210, 0x0210, 0x0235}, {0x0211, 0x0211, 0x0236}, + {0x0212, 0x0212, 0x0237}, {0x0213, 0x0213, 0x0238}, + {0x0214, 0x0214, 0x0239}, {0x0215, 0x2AA5, 0x023A}, + {0x0216, 0x0217, 0x023B}, {0x0216, 0x0217, 0x023B}, + {0x0218, 0x017E, 0x023D}, {0x0219, 0x2AA6, 0x023E}, + {0x2ABE, 0x021A, 0x2C7E}, {0x2ABF, 0x021B, 0x2C7F}, + {0x021C, 0x021D, 0x0241}, {0x021C, 0x021D, 0x0241}, + {0x021E, 0x0164, 0x0243}, {0x021F, 0x0262, 0x0244}, + {0x0220, 0x0265, 0x0245}, {0x0221, 0x0222, 0x0246}, + {0x0221, 0x0222, 0x0246}, {0x0223, 0x0224, 0x0248}, + {0x0223, 0x0224, 0x0248}, {0x0225, 0x0226, 0x024A}, + {0x0225, 0x0226, 0x024A}, {0x0227, 0x0228, 0x024C}, + {0x0227, 0x0228, 0x024C}, {0x0229, 0x022A, 0x024E}, + {0x0229, 0x022A, 0x024E}, {0x2AAF, 0x022B, 0x2C6F}, + {0x2AB0, 0x022C, 0x2C70}, {0x0165, 0x022D, 0x0181}, + {0x016A, 0x022E, 0x0186}, {0x022F, 0x022F, 0x0255}, + {0x016D, 0x0230, 0x0189}, {0x016E, 0x0231, 0x018A}, + {0x0232, 0x0232, 0x0258}, {0x0173, 0x0233, 0x018F}, + {0x0234, 0x0234, 0x025A}, {0x0174, 0x0235, 0x0190}, + {0x0236, 0x0236, 0x025C}, {0x0237, 0x0237, 0x025D}, + {0x0238, 0x0238, 0x025E}, {0x0239, 0x0239, 0x025F}, + {0x0177, 0x023A, 0x0193}, {0x023B, 0x023B, 0x0262}, + {0x0178, 0x023C, 0x0194}, {0x023D, 0x023D, 0x0264}, + {0x023E, 0x023E, 0x0265}, {0x023F, 0x023F, 0x0266}, + {0x0240, 0x0240, 0x0267}, {0x017B, 0x0241, 0x0197}, + {0x017A, 0x0242, 0x0196}, {0x0243, 0x0243, 0x026A}, + {0x2AA2, 0x0244, 0x2C62}, {0x0245, 0x0245, 0x026C}, + {0x0246, 0x0246, 0x026D}, {0x0247, 0x0247, 0x026E}, + {0x0180, 0x0248, 0x019C}, {0x0249, 0x0249, 0x0270}, + {0x2AAE, 0x024A, 0x2C6E}, {0x0181, 0x024B, 0x019D}, + {0x024C, 0x024C, 0x0273}, {0x024D, 0x024D, 0x0274}, + {0x0183, 0x024E, 0x019F}, {0x024F, 0x024F, 0x0276}, + {0x0250, 0x0250, 0x0277}, {0x0251, 0x0251, 0x0278}, + {0x0252, 0x0252, 0x0279}, {0x0253, 0x0253, 0x027A}, + {0x0254, 0x0254, 0x027B}, {0x0255, 0x0255, 0x027C}, + {0x2AA4, 0x0256, 0x2C64}, {0x0257, 0x0257, 0x027E}, + {0x0258, 0x0258, 0x027F}, {0x018A, 0x0259, 0x01A6}, + {0x025A, 0x025A, 0x0281}, {0x025B, 0x025B, 0x0282}, + {0x018D, 0x025C, 0x01A9}, {0x025D, 0x025D, 0x0284}, + {0x025E, 0x025E, 0x0285}, {0x025F, 0x025F, 0x0286}, + {0x0260, 0x0260, 0x0287}, {0x0192, 0x0261, 0x01AE}, + {0x021F, 0x0262, 0x0244}, {0x0195, 0x0263, 0x01B1}, + {0x0196, 0x0264, 0x01B2}, {0x0220, 0x0265, 0x0245}, + {0x0266, 0x0266, 0x028D}, {0x0267, 0x0267, 0x028E}, + {0x0268, 0x0268, 0x028F}, {0x0269, 0x0269, 0x0290}, + {0x026A, 0x026A, 0x0291}, {0x019B, 0x026B, 0x01B7}, + {0x026C, 0x026C, 0x0293}, {0x026D, 0x026D, 0x0294}, + {0x026E, 0x026E, 0x0295}, {0x026F, 0x026F, 0x0296}, + {0x0270, 0x0270, 0x0297}, {0x0271, 0x0271, 0x0298}, + {0x0272, 0x0272, 0x0299}, {0x0273, 0x0273, 0x029A}, + {0x0274, 0x0274, 0x029B}, {0x0275, 0x0275, 0x029C}, + {0x0276, 0x0276, 0x029D}, {0x0277, 0x0277, 0x029E}, + {0x0278, 0x0278, 0x029F}, {0x0279, 0x0279, 0x02A0}, + {0x027A, 0x027A, 0x02A1}, {0x027B, 0x027B, 0x02A2}, + {0x027C, 0x027C, 0x02A3}, {0x027D, 0x027D, 0x02A4}, + {0x027E, 0x027E, 0x02A5}, {0x027F, 0x027F, 0x02A6}, + {0x0280, 0x0280, 0x02A7}, {0x0281, 0x0281, 0x02A8}, + {0x0282, 0x0282, 0x02A9}, {0x0283, 0x0283, 0x02AA}, + {0x0284, 0x0284, 0x02AB}, {0x0285, 0x0285, 0x02AC}, + {0x0286, 0x0286, 0x02AD}, {0x0287, 0x0287, 0x02AE}, + {0x0288, 0x0288, 0x02AF}, {0x0289, 0x0289, 0x02B0}, + {0x028A, 0x028A, 0x02B1}, {0x028B, 0x028B, 0x02B2}, + {0x028C, 0x028C, 0x02B3}, {0x028D, 0x028D, 0x02B4}, + {0x028E, 0x028E, 0x02B5}, {0x028F, 0x028F, 0x02B6}, + {0x0290, 0x0290, 0x02B7}, {0x0291, 0x0291, 0x02B8}, + {0x0292, 0x0292, 0x02B9}, {0x0293, 0x0293, 0x02BA}, + {0x0294, 0x0294, 0x02BB}, {0x0295, 0x0295, 0x02BC}, + {0x0296, 0x0296, 0x02BD}, {0x0297, 0x0297, 0x02BE}, + {0x0298, 0x0298, 0x02BF}, {0x0299, 0x0299, 0x02C0}, + {0x029A, 0x029A, 0x02C1}, {0x029B, 0x029B, 0x02C2}, + {0x029C, 0x029C, 0x02C3}, {0x029D, 0x029D, 0x02C4}, + {0x029E, 0x029E, 0x02C5}, {0x029F, 0x029F, 0x02C6}, + {0x02A0, 0x02A0, 0x02C8}, {0x02A1, 0x02A1, 0x02CC}, + {0x02A2, 0x02A2, 0x02CD}, {0x02A3, 0x02A3, 0x02CE}, + {0x02A4, 0x02A4, 0x02CF}, {0x02A5, 0x02A5, 0x02D0}, + {0x02A6, 0x02A6, 0x02D1}, {0x02A7, 0x02A7, 0x02D2}, + {0x02A8, 0x02A8, 0x02D3}, {0x02A9, 0x02A9, 0x02D4}, + {0x02AA, 0x02AA, 0x02D5}, {0x02AB, 0x02AB, 0x02D6}, + {0x02AC, 0x02AC, 0x02D7}, {0x02AD, 0x02AD, 0x02D8}, + {0x02AE, 0x02AE, 0x02DA}, {0x02AF, 0x02AF, 0x02DB}, + {0x02B0, 0x02B0, 0x02DC}, {0x02B1, 0x02B1, 0x02DD}, + {0x02B2, 0x02B2, 0x02DE}, {0x02B3, 0x02B3, 0x02DF}, + {0x02B4, 0x02B4, 0x02E0}, {0x02B5, 0x02B5, 0x02E1}, + {0x02B6, 0x02B6, 0x02E2}, {0x02B7, 0x02B7, 0x02E3}, + {0x02B8, 0x02B8, 0x02E4}, {0x02B9, 0x02B9, 0x02E5}, + {0x02BA, 0x02BA, 0x02E6}, {0x02BB, 0x02BB, 0x02E7}, + {0x02BC, 0x02BC, 0x02E8}, {0x02BD, 0x02BD, 0x02E9}, + {0x02BE, 0x02BE, 0x02EA}, {0x02BF, 0x02BF, 0x02EB}, + {0x02C0, 0x02C0, 0x02EC}, {0x02C1, 0x02C1, 0x02ED}, + {0x02C2, 0x02C2, 0x02EE}, {0x02C3, 0x02C3, 0x02EF}, + {0x02C4, 0x02C4, 0x02F0}, {0x02C5, 0x02C5, 0x02F1}, + {0x02C6, 0x02C6, 0x02F2}, {0x02C7, 0x02C7, 0x02F3}, + {0x02C8, 0x02C8, 0x02F4}, {0x02C9, 0x02C9, 0x02F5}, + {0x02CA, 0x02CA, 0x02F6}, {0x02CB, 0x02CB, 0x02F7}, + {0x02CC, 0x02CC, 0x02F8}, {0x02CD, 0x02CD, 0x02F9}, + {0x02CE, 0x02CE, 0x02FA}, {0x02CF, 0x02CF, 0x02FB}, + {0x02D0, 0x02D0, 0x02FC}, {0x02D1, 0x02D1, 0x02FD}, + {0x02D2, 0x02D2, 0x02FE}, {0x02D3, 0x02D3, 0x02FF}, + {0x02D4, 0x02D4, 0x0300}, {0x02D5, 0x02D5, 0x0301}, + {0x02D6, 0x02D6, 0x0302}, {0x02D7, 0x02D7, 0x0303}, + {0x02D8, 0x02D8, 0x0304}, {0x02D9, 0x02D9, 0x0305}, + {0x02DA, 0x02DA, 0x0306}, {0x02DB, 0x02DB, 0x0307}, + {0x02DC, 0x02DC, 0x0308}, {0x02DD, 0x02DD, 0x0309}, + {0x02DE, 0x02DE, 0x030A}, {0x02DF, 0x02DF, 0x030B}, + {0x02E0, 0x02E0, 0x030C}, {0x02E1, 0x02E1, 0x030D}, + {0x02E2, 0x02E2, 0x030E}, {0x02E3, 0x02E3, 0x030F}, + {0x02E4, 0x02E4, 0x0310}, {0x02E5, 0x02E5, 0x0311}, + {0x02E6, 0x02E6, 0x0312}, {0x02E7, 0x02E7, 0x0313}, + {0x02E8, 0x02E8, 0x0314}, {0x02E9, 0x02E9, 0x0315}, + {0x02EA, 0x02EA, 0x0316}, {0x02EB, 0x02EB, 0x0317}, + {0x02EC, 0x02EC, 0x0318}, {0x02ED, 0x02ED, 0x0319}, + {0x02EE, 0x02EE, 0x031A}, {0x02EF, 0x02EF, 0x031B}, + {0x02F0, 0x02F0, 0x031C}, {0x02F1, 0x02F1, 0x031D}, + {0x02F2, 0x02F2, 0x031E}, {0x02F3, 0x02F3, 0x031F}, + {0x02F4, 0x02F4, 0x0320}, {0x02F5, 0x02F5, 0x0321}, + {0x02F6, 0x02F6, 0x0322}, {0x02F7, 0x02F7, 0x0323}, + {0x02F8, 0x02F8, 0x0324}, {0x02F9, 0x02F9, 0x0325}, + {0x02FA, 0x02FA, 0x0326}, {0x02FB, 0x02FB, 0x0327}, + {0x02FC, 0x02FC, 0x0328}, {0x02FD, 0x02FD, 0x0329}, + {0x02FE, 0x02FE, 0x032A}, {0x02FF, 0x02FF, 0x032B}}; + +static ObUnicaseInfoChar plane03[] = { + {0x0300, 0x0300, 0x032C}, {0x0301, 0x0301, 0x032D}, + {0x0302, 0x0302, 0x032E}, {0x0303, 0x0303, 0x032F}, + {0x0304, 0x0304, 0x0330}, {0x0305, 0x0305, 0x0331}, + {0x0306, 0x0306, 0x0332}, {0x0307, 0x0307, 0x0333}, + {0x0308, 0x0308, 0x0334}, {0x0309, 0x0309, 0x0335}, + {0x030A, 0x030A, 0x0336}, {0x030B, 0x030B, 0x0337}, + {0x030C, 0x030C, 0x0338}, {0x030D, 0x030D, 0x0339}, + {0x030E, 0x030E, 0x033A}, {0x030F, 0x030F, 0x033B}, + {0x0310, 0x0310, 0x033C}, {0x0311, 0x0311, 0x033D}, + {0x0312, 0x0312, 0x033E}, {0x0313, 0x0313, 0x033F}, + {0x0314, 0x0314, 0x0340}, {0x0315, 0x0315, 0x0341}, + {0x0316, 0x0316, 0x0342}, {0x0317, 0x0317, 0x0343}, + {0x0318, 0x0318, 0x0344}, {0xA6A9, 0x0319, 0x0345}, + {0x031A, 0x031A, 0x0346}, {0x031B, 0x031B, 0x0347}, + {0x031C, 0x031C, 0x0348}, {0x031D, 0x031D, 0x0349}, + {0x031E, 0x031E, 0x034A}, {0x031F, 0x031F, 0x034B}, + {0x0320, 0x0320, 0x034C}, {0x0321, 0x0321, 0x034D}, + {0x0322, 0x0322, 0x034E}, {0x0323, 0x0323, 0x034F}, + {0x0324, 0x0324, 0x0350}, {0x0325, 0x0325, 0x0351}, + {0x0326, 0x0326, 0x0352}, {0x0327, 0x0327, 0x0353}, + {0x0328, 0x0328, 0x0354}, {0x0329, 0x0329, 0x0355}, + {0x032A, 0x032A, 0x0356}, {0x032B, 0x032B, 0x0357}, + {0x032C, 0x032C, 0x0358}, {0x032D, 0x032D, 0x0359}, + {0x032E, 0x032E, 0x035A}, {0x032F, 0x032F, 0x035B}, + {0x0330, 0x0330, 0x035C}, {0x0331, 0x0331, 0x035D}, + {0x0332, 0x0332, 0x035E}, {0x0333, 0x0333, 0x035F}, + {0x0334, 0x0334, 0x0360}, {0x0335, 0x0335, 0x0361}, + {0x0336, 0x0336, 0x0362}, {0x0337, 0x0337, 0x0363}, + {0x0338, 0x0338, 0x0364}, {0x0339, 0x0339, 0x0365}, + {0x033A, 0x033A, 0x0366}, {0x033B, 0x033B, 0x0367}, + {0x033C, 0x033C, 0x0368}, {0x033D, 0x033D, 0x0369}, + {0x033E, 0x033E, 0x036A}, {0x033F, 0x033F, 0x036B}, + {0x0340, 0x0340, 0x036C}, {0x0341, 0x0341, 0x036D}, + {0x0342, 0x0342, 0x036E}, {0x0343, 0x0343, 0x036F}, + {0x0344, 0x0345, 0x0370}, {0x0344, 0x0345, 0x0370}, + {0x0346, 0x0347, 0x0372}, {0x0346, 0x0347, 0x0372}, + {0x0348, 0x0348, 0x0374}, {0x0349, 0x0349, 0x0375}, + {0x034A, 0x034B, 0x0376}, {0x034A, 0x034B, 0x0376}, + {0x034C, 0x034C, 0x0378}, {0x034D, 0x034D, 0x0379}, + {0x034E, 0x034E, 0x037A}, {0x03A1, 0x034F, 0x03FD}, + {0x03A2, 0x0350, 0x03FE}, {0x03A3, 0x0351, 0x03FF}, + {0x0352, 0x0352, 0x037E}, {0x0353, 0x0353, 0x037F}, + {0x0354, 0x0354, 0x0380}, {0x0355, 0x0355, 0x0381}, + {0x0356, 0x0356, 0x0382}, {0x0357, 0x0357, 0x0383}, + {0x0358, 0x0358, 0x0384}, {0x0359, 0x0359, 0x0385}, + {0x035A, 0x0368, 0x0386}, {0x035B, 0x035B, 0x0387}, + {0x035C, 0x0369, 0x0388}, {0x035D, 0x036A, 0x0389}, + {0x035E, 0x036B, 0x038A}, {0x035F, 0x035F, 0x038B}, + {0x0360, 0x0370, 0x038C}, {0x0361, 0x0361, 0x038D}, + {0x0362, 0x0371, 0x038E}, {0x0363, 0x0372, 0x038F}, + {0x0364, 0x0364, 0x0390}, {0x0365, 0x0365, 0x03A2}, + {0x0366, 0x036E, 0x03AA}, {0x0367, 0x036F, 0x03AB}, + {0x035A, 0x0368, 0x0386}, {0x035C, 0x0369, 0x0388}, + {0x035D, 0x036A, 0x0389}, {0x035E, 0x036B, 0x038A}, + {0x036C, 0x036C, 0x03B0}, {0x036D, 0xA6D2, 0x03C2}, + {0x0366, 0x036E, 0x03AA}, {0x0367, 0x036F, 0x03AB}, + {0x0360, 0x0370, 0x038C}, {0x0362, 0x0371, 0x038E}, + {0x0363, 0x0372, 0x038F}, {0x0373, 0x037B, 0x03CF}, + {0x0374, 0xA6C2, 0x03D0}, {0x0375, 0xA6C8, 0x03D1}, + {0x0376, 0x0376, 0x03D2}, {0x0377, 0x0377, 0x03D3}, + {0x0378, 0x0378, 0x03D4}, {0x0379, 0xA6D5, 0x03D5}, + {0x037A, 0xA6D0, 0x03D6}, {0x0373, 0x037B, 0x03CF}, + {0x037C, 0x037D, 0x03D8}, {0x037C, 0x037D, 0x03D8}, + {0x037E, 0x037F, 0x03DA}, {0x037E, 0x037F, 0x03DA}, + {0x0380, 0x0381, 0x03DC}, {0x0380, 0x0381, 0x03DC}, + {0x0382, 0x0383, 0x03DE}, {0x0382, 0x0383, 0x03DE}, + {0x0384, 0x0385, 0x03E0}, {0x0384, 0x0385, 0x03E0}, + {0x0386, 0x0387, 0x03E2}, {0x0386, 0x0387, 0x03E2}, + {0x0388, 0x0389, 0x03E4}, {0x0388, 0x0389, 0x03E4}, + {0x038A, 0x038B, 0x03E6}, {0x038A, 0x038B, 0x03E6}, + {0x038C, 0x038D, 0x03E8}, {0x038C, 0x038D, 0x03E8}, + {0x038E, 0x038F, 0x03EA}, {0x038E, 0x038F, 0x03EA}, + {0x0390, 0x0391, 0x03EC}, {0x0390, 0x0391, 0x03EC}, + {0x0392, 0x0393, 0x03EE}, {0x0392, 0x0393, 0x03EE}, + {0x0394, 0xA6CA, 0x03F0}, {0x0395, 0xA6D1, 0x03F1}, + {0x039D, 0x0396, 0x03F9}, {0x0397, 0x0397, 0x03F3}, + {0x0398, 0xA6C8, 0x03F4}, {0x0399, 0xA6C5, 0x03F5}, + {0x039A, 0x039A, 0x03F6}, {0x039B, 0x039C, 0x03F7}, + {0x039B, 0x039C, 0x03F7}, {0x039D, 0x0396, 0x03F9}, + {0x039E, 0x039F, 0x03FA}, {0x039E, 0x039F, 0x03FA}, + {0x03A0, 0x03A0, 0x03FC}, {0x03A1, 0x034F, 0x03FD}, + {0x03A2, 0x0350, 0x03FE}, {0x03A3, 0x0351, 0x03FF}, + {0x03A4, 0x03B3, 0x0400}, {0x03A5, 0x03B4, 0x0402}, + {0x03A6, 0x03B5, 0x0403}, {0x03A7, 0x03B6, 0x0404}, + {0x03A8, 0x03B7, 0x0405}, {0x03A9, 0x03B8, 0x0406}, + {0x03AA, 0x03B9, 0x0407}, {0x03AB, 0x03BA, 0x0408}, + {0x03AC, 0x03BB, 0x0409}, {0x03AD, 0x03BC, 0x040A}, + {0x03AE, 0x03BD, 0x040B}, {0x03AF, 0x03BE, 0x040C}, + {0x03B0, 0x03BF, 0x040D}, {0x03B1, 0x03C0, 0x040E}, + {0x03B2, 0x03C1, 0x040F}, {0x03A4, 0x03B3, 0x0400}, + {0x03A5, 0x03B4, 0x0402}, {0x03A6, 0x03B5, 0x0403}, + {0x03A7, 0x03B6, 0x0404}, {0x03A8, 0x03B7, 0x0405}, + {0x03A9, 0x03B8, 0x0406}, {0x03AA, 0x03B9, 0x0407}, + {0x03AB, 0x03BA, 0x0408}, {0x03AC, 0x03BB, 0x0409}, + {0x03AD, 0x03BC, 0x040A}, {0x03AE, 0x03BD, 0x040B}, + {0x03AF, 0x03BE, 0x040C}, {0x03B0, 0x03BF, 0x040D}, + {0x03B1, 0x03C0, 0x040E}, {0x03B2, 0x03C1, 0x040F}, + {0x03C2, 0x03C3, 0x0460}, {0x03C2, 0x03C3, 0x0460}, + {0x03C4, 0x03C5, 0x0462}, {0x03C4, 0x03C5, 0x0462}, + {0x03C6, 0x03C7, 0x0464}, {0x03C6, 0x03C7, 0x0464}, + {0x03C8, 0x03C9, 0x0466}, {0x03C8, 0x03C9, 0x0466}, + {0x03CA, 0x03CB, 0x0468}, {0x03CA, 0x03CB, 0x0468}, + {0x03CC, 0x03CD, 0x046A}, {0x03CC, 0x03CD, 0x046A}, + {0x03CE, 0x03CF, 0x046C}, {0x03CE, 0x03CF, 0x046C}, + {0x03D0, 0x03D1, 0x046E}, {0x03D0, 0x03D1, 0x046E}, + {0x03D2, 0x03D3, 0x0470}, {0x03D2, 0x03D3, 0x0470}, + {0x03D4, 0x03D5, 0x0472}, {0x03D4, 0x03D5, 0x0472}, + {0x03D6, 0x03D7, 0x0474}, {0x03D6, 0x03D7, 0x0474}, + {0x03D8, 0x03D9, 0x0476}, {0x03D8, 0x03D9, 0x0476}, + {0x03DA, 0x03DB, 0x0478}, {0x03DA, 0x03DB, 0x0478}, + {0x03DC, 0x03DD, 0x047A}, {0x03DC, 0x03DD, 0x047A}, + {0x03DE, 0x03DF, 0x047C}, {0x03DE, 0x03DF, 0x047C}, + {0x03E0, 0x03E1, 0x047E}, {0x03E0, 0x03E1, 0x047E}, + {0x03E2, 0x03E3, 0x0480}, {0x03E2, 0x03E3, 0x0480}, + {0x03E4, 0x03E4, 0x0482}, {0x03E5, 0x03E5, 0x0483}, + {0x03E6, 0x03E6, 0x0484}, {0x03E7, 0x03E7, 0x0485}, + {0x03E8, 0x03E8, 0x0486}, {0x03E9, 0x03E9, 0x0487}, + {0x03EA, 0x03EA, 0x0488}, {0x03EB, 0x03EB, 0x0489}, + {0x03EC, 0x03ED, 0x048A}, {0x03EC, 0x03ED, 0x048A}, + {0x03EE, 0x03EF, 0x048C}, {0x03EE, 0x03EF, 0x048C}, + {0x03F0, 0x03F1, 0x048E}, {0x03F0, 0x03F1, 0x048E}, + {0x03F2, 0x03F3, 0x0490}, {0x03F2, 0x03F3, 0x0490}, + {0x03F4, 0x03F5, 0x0492}, {0x03F4, 0x03F5, 0x0492}, + {0x03F6, 0x03F7, 0x0494}, {0x03F6, 0x03F7, 0x0494}, + {0x03F8, 0x03F9, 0x0496}, {0x03F8, 0x03F9, 0x0496}, + {0x03FA, 0x03FB, 0x0498}, {0x03FA, 0x03FB, 0x0498}, + {0x03FC, 0x03FD, 0x049A}, {0x03FC, 0x03FD, 0x049A}, + {0x03FE, 0x03FF, 0x049C}, {0x03FE, 0x03FF, 0x049C}}; + +static ObUnicaseInfoChar plane04[] = { + {0x0400, 0x0401, 0x049E}, {0x0400, 0x0401, 0x049E}, + {0x0402, 0x0403, 0x04A0}, {0x0402, 0x0403, 0x04A0}, + {0x0404, 0x0405, 0x04A2}, {0x0404, 0x0405, 0x04A2}, + {0x0406, 0x0407, 0x04A4}, {0x0406, 0x0407, 0x04A4}, + {0x0408, 0x0409, 0x04A6}, {0x0408, 0x0409, 0x04A6}, + {0x040A, 0x040B, 0x04A8}, {0x040A, 0x040B, 0x04A8}, + {0x040C, 0x040D, 0x04AA}, {0x040C, 0x040D, 0x04AA}, + {0x040E, 0x040F, 0x04AC}, {0x040E, 0x040F, 0x04AC}, + {0x0410, 0x0411, 0x04AE}, {0x0410, 0x0411, 0x04AE}, + {0x0412, 0x0413, 0x04B0}, {0x0412, 0x0413, 0x04B0}, + {0x0414, 0x0415, 0x04B2}, {0x0414, 0x0415, 0x04B2}, + {0x0416, 0x0417, 0x04B4}, {0x0416, 0x0417, 0x04B4}, + {0x0418, 0x0419, 0x04B6}, {0x0418, 0x0419, 0x04B6}, + {0x041A, 0x041B, 0x04B8}, {0x041A, 0x041B, 0x04B8}, + {0x041C, 0x041D, 0x04BA}, {0x041C, 0x041D, 0x04BA}, + {0x041E, 0x041F, 0x04BC}, {0x041E, 0x041F, 0x04BC}, + {0x0420, 0x0421, 0x04BE}, {0x0420, 0x0421, 0x04BE}, + {0x0422, 0x0431, 0x04C0}, {0x0423, 0x0424, 0x04C1}, + {0x0423, 0x0424, 0x04C1}, {0x0425, 0x0426, 0x04C3}, + {0x0425, 0x0426, 0x04C3}, {0x0427, 0x0428, 0x04C5}, + {0x0427, 0x0428, 0x04C5}, {0x0429, 0x042A, 0x04C7}, + {0x0429, 0x042A, 0x04C7}, {0x042B, 0x042C, 0x04C9}, + {0x042B, 0x042C, 0x04C9}, {0x042D, 0x042E, 0x04CB}, + {0x042D, 0x042E, 0x04CB}, {0x042F, 0x0430, 0x04CD}, + {0x042F, 0x0430, 0x04CD}, {0x0422, 0x0431, 0x04C0}, + {0x0432, 0x0433, 0x04D0}, {0x0432, 0x0433, 0x04D0}, + {0x0434, 0x0435, 0x04D2}, {0x0434, 0x0435, 0x04D2}, + {0x0436, 0x0437, 0x04D4}, {0x0436, 0x0437, 0x04D4}, + {0x0438, 0x0439, 0x04D6}, {0x0438, 0x0439, 0x04D6}, + {0x043A, 0x043B, 0x04D8}, {0x043A, 0x043B, 0x04D8}, + {0x043C, 0x043D, 0x04DA}, {0x043C, 0x043D, 0x04DA}, + {0x043E, 0x043F, 0x04DC}, {0x043E, 0x043F, 0x04DC}, + {0x0440, 0x0441, 0x04DE}, {0x0440, 0x0441, 0x04DE}, + {0x0442, 0x0443, 0x04E0}, {0x0442, 0x0443, 0x04E0}, + {0x0444, 0x0445, 0x04E2}, {0x0444, 0x0445, 0x04E2}, + {0x0446, 0x0447, 0x04E4}, {0x0446, 0x0447, 0x04E4}, + {0x0448, 0x0449, 0x04E6}, {0x0448, 0x0449, 0x04E6}, + {0x044A, 0x044B, 0x04E8}, {0x044A, 0x044B, 0x04E8}, + {0x044C, 0x044D, 0x04EA}, {0x044C, 0x044D, 0x04EA}, + {0x044E, 0x044F, 0x04EC}, {0x044E, 0x044F, 0x04EC}, + {0x0450, 0x0451, 0x04EE}, {0x0450, 0x0451, 0x04EE}, + {0x0452, 0x0453, 0x04F0}, {0x0452, 0x0453, 0x04F0}, + {0x0454, 0x0455, 0x04F2}, {0x0454, 0x0455, 0x04F2}, + {0x0456, 0x0457, 0x04F4}, {0x0456, 0x0457, 0x04F4}, + {0x0458, 0x0459, 0x04F6}, {0x0458, 0x0459, 0x04F6}, + {0x045A, 0x045B, 0x04F8}, {0x045A, 0x045B, 0x04F8}, + {0x045C, 0x045D, 0x04FA}, {0x045C, 0x045D, 0x04FA}, + {0x045E, 0x045F, 0x04FC}, {0x045E, 0x045F, 0x04FC}, + {0x0460, 0x0461, 0x04FE}, {0x0460, 0x0461, 0x04FE}, + {0x0462, 0x0463, 0x0500}, {0x0462, 0x0463, 0x0500}, + {0x0464, 0x0465, 0x0502}, {0x0464, 0x0465, 0x0502}, + {0x0466, 0x0467, 0x0504}, {0x0466, 0x0467, 0x0504}, + {0x0468, 0x0469, 0x0506}, {0x0468, 0x0469, 0x0506}, + {0x046A, 0x046B, 0x0508}, {0x046A, 0x046B, 0x0508}, + {0x046C, 0x046D, 0x050A}, {0x046C, 0x046D, 0x050A}, + {0x046E, 0x046F, 0x050C}, {0x046E, 0x046F, 0x050C}, + {0x0470, 0x0471, 0x050E}, {0x0470, 0x0471, 0x050E}, + {0x0472, 0x0473, 0x0510}, {0x0472, 0x0473, 0x0510}, + {0x0474, 0x0475, 0x0512}, {0x0474, 0x0475, 0x0512}, + {0x0476, 0x0477, 0x0514}, {0x0476, 0x0477, 0x0514}, + {0x0478, 0x0479, 0x0516}, {0x0478, 0x0479, 0x0516}, + {0x047A, 0x047B, 0x0518}, {0x047A, 0x047B, 0x0518}, + {0x047C, 0x047D, 0x051A}, {0x047C, 0x047D, 0x051A}, + {0x047E, 0x047F, 0x051C}, {0x047E, 0x047F, 0x051C}, + {0x0480, 0x0481, 0x051E}, {0x0480, 0x0481, 0x051E}, + {0x0482, 0x0483, 0x0520}, {0x0482, 0x0483, 0x0520}, + {0x0484, 0x0485, 0x0522}, {0x0484, 0x0485, 0x0522}, + {0x0486, 0x0487, 0x0524}, {0x0486, 0x0487, 0x0524}, + {0x0488, 0x0488, 0x0526}, {0x0489, 0x0489, 0x0527}, + {0x048A, 0x048A, 0x0528}, {0x048B, 0x048B, 0x0529}, + {0x048C, 0x048C, 0x052A}, {0x048D, 0x048D, 0x052B}, + {0x048E, 0x048E, 0x052C}, {0x048F, 0x048F, 0x052D}, + {0x0490, 0x0490, 0x052E}, {0x0491, 0x0491, 0x052F}, + {0x0492, 0x0492, 0x0530}, {0x0493, 0x04C3, 0x0531}, + {0x0494, 0x04C4, 0x0532}, {0x0495, 0x04C5, 0x0533}, + {0x0496, 0x04C6, 0x0534}, {0x0497, 0x04C7, 0x0535}, + {0x0498, 0x04C8, 0x0536}, {0x0499, 0x04C9, 0x0537}, + {0x049A, 0x04CA, 0x0538}, {0x049B, 0x04CB, 0x0539}, + {0x049C, 0x04CC, 0x053A}, {0x049D, 0x04CD, 0x053B}, + {0x049E, 0x04CE, 0x053C}, {0x049F, 0x04CF, 0x053D}, + {0x04A0, 0x04D0, 0x053E}, {0x04A1, 0x04D1, 0x053F}, + {0x04A2, 0x04D2, 0x0540}, {0x04A3, 0x04D3, 0x0541}, + {0x04A4, 0x04D4, 0x0542}, {0x04A5, 0x04D5, 0x0543}, + {0x04A6, 0x04D6, 0x0544}, {0x04A7, 0x04D7, 0x0545}, + {0x04A8, 0x04D8, 0x0546}, {0x04A9, 0x04D9, 0x0547}, + {0x04AA, 0x04DA, 0x0548}, {0x04AB, 0x04DB, 0x0549}, + {0x04AC, 0x04DC, 0x054A}, {0x04AD, 0x04DD, 0x054B}, + {0x04AE, 0x04DE, 0x054C}, {0x04AF, 0x04DF, 0x054D}, + {0x04B0, 0x04E0, 0x054E}, {0x04B1, 0x04E1, 0x054F}, + {0x04B2, 0x04E2, 0x0550}, {0x04B3, 0x04E3, 0x0551}, + {0x04B4, 0x04E4, 0x0552}, {0x04B5, 0x04E5, 0x0553}, + {0x04B6, 0x04E6, 0x0554}, {0x04B7, 0x04E7, 0x0555}, + {0x04B8, 0x04E8, 0x0556}, {0x04B9, 0x04B9, 0x0557}, + {0x04BA, 0x04BA, 0x0558}, {0x04BB, 0x04BB, 0x0559}, + {0x04BC, 0x04BC, 0x055A}, {0x04BD, 0x04BD, 0x055B}, + {0x04BE, 0x04BE, 0x055C}, {0x04BF, 0x04BF, 0x055D}, + {0x04C0, 0x04C0, 0x055E}, {0x04C1, 0x04C1, 0x055F}, + {0x04C2, 0x04C2, 0x0560}, {0x0493, 0x04C3, 0x0531}, + {0x0494, 0x04C4, 0x0532}, {0x0495, 0x04C5, 0x0533}, + {0x0496, 0x04C6, 0x0534}, {0x0497, 0x04C7, 0x0535}, + {0x0498, 0x04C8, 0x0536}, {0x0499, 0x04C9, 0x0537}, + {0x049A, 0x04CA, 0x0538}, {0x049B, 0x04CB, 0x0539}, + {0x049C, 0x04CC, 0x053A}, {0x049D, 0x04CD, 0x053B}, + {0x049E, 0x04CE, 0x053C}, {0x049F, 0x04CF, 0x053D}, + {0x04A0, 0x04D0, 0x053E}, {0x04A1, 0x04D1, 0x053F}, + {0x04A2, 0x04D2, 0x0540}, {0x04A3, 0x04D3, 0x0541}, + {0x04A4, 0x04D4, 0x0542}, {0x04A5, 0x04D5, 0x0543}, + {0x04A6, 0x04D6, 0x0544}, {0x04A7, 0x04D7, 0x0545}, + {0x04A8, 0x04D8, 0x0546}, {0x04A9, 0x04D9, 0x0547}, + {0x04AA, 0x04DA, 0x0548}, {0x04AB, 0x04DB, 0x0549}, + {0x04AC, 0x04DC, 0x054A}, {0x04AD, 0x04DD, 0x054B}, + {0x04AE, 0x04DE, 0x054C}, {0x04AF, 0x04DF, 0x054D}, + {0x04B0, 0x04E0, 0x054E}, {0x04B1, 0x04E1, 0x054F}, + {0x04B2, 0x04E2, 0x0550}, {0x04B3, 0x04E3, 0x0551}, + {0x04B4, 0x04E4, 0x0552}, {0x04B5, 0x04E5, 0x0553}, + {0x04B6, 0x04E6, 0x0554}, {0x04B7, 0x04E7, 0x0555}, + {0x04B8, 0x04E8, 0x0556}, {0x04E9, 0x04E9, 0x0587}, + {0x04EA, 0x04EA, 0x0588}, {0x04EB, 0x04EB, 0x0589}, + {0x04EC, 0x04EC, 0x058A}, {0x04ED, 0x04ED, 0x058B}, + {0x04EE, 0x04EE, 0x058C}, {0x04EF, 0x04EF, 0x058D}, + {0x04F0, 0x04F0, 0x058E}, {0x04F1, 0x04F1, 0x058F}, + {0x04F2, 0x04F2, 0x0590}, {0x04F3, 0x04F3, 0x0591}, + {0x04F4, 0x04F4, 0x0592}, {0x04F5, 0x04F5, 0x0593}, + {0x04F6, 0x04F6, 0x0594}, {0x04F7, 0x04F7, 0x0595}, + {0x04F8, 0x04F8, 0x0596}, {0x04F9, 0x04F9, 0x0597}, + {0x04FA, 0x04FA, 0x0598}, {0x04FB, 0x04FB, 0x0599}, + {0x04FC, 0x04FC, 0x059A}, {0x04FD, 0x04FD, 0x059B}, + {0x04FE, 0x04FE, 0x059C}, {0x04FF, 0x04FF, 0x059D}}; + +static ObUnicaseInfoChar plane10[] = { + {0x1000, 0x1000, 0x109E}, {0x1001, 0x1001, 0x109F}, + {0x1002, 0x2B40, 0x10A0}, {0x1003, 0x2B41, 0x10A1}, + {0x1004, 0x2B42, 0x10A2}, {0x1005, 0x2B43, 0x10A3}, + {0x1006, 0x2B44, 0x10A4}, {0x1007, 0x2B45, 0x10A5}, + {0x1008, 0x2B46, 0x10A6}, {0x1009, 0x2B47, 0x10A7}, + {0x100A, 0x2B48, 0x10A8}, {0x100B, 0x2B49, 0x10A9}, + {0x100C, 0x2B4A, 0x10AA}, {0x100D, 0x2B4B, 0x10AB}, + {0x100E, 0x2B4C, 0x10AC}, {0x100F, 0x2B4D, 0x10AD}, + {0x1010, 0x2B4E, 0x10AE}, {0x1011, 0x2B4F, 0x10AF}, + {0x1012, 0x2B50, 0x10B0}, {0x1013, 0x2B51, 0x10B1}, + {0x1014, 0x2B52, 0x10B2}, {0x1015, 0x2B53, 0x10B3}, + {0x1016, 0x2B54, 0x10B4}, {0x1017, 0x2B55, 0x10B5}, + {0x1018, 0x2B56, 0x10B6}, {0x1019, 0x2B57, 0x10B7}, + {0x101A, 0x2B58, 0x10B8}, {0x101B, 0x2B59, 0x10B9}, + {0x101C, 0x2B5A, 0x10BA}, {0x101D, 0x2B5B, 0x10BB}, + {0x101E, 0x2B5C, 0x10BC}, {0x101F, 0x2B5D, 0x10BD}, + {0x1020, 0x2B5E, 0x10BE}, {0x1021, 0x2B5F, 0x10BF}, + {0x1022, 0x2B60, 0x10C0}, {0x1023, 0x2B61, 0x10C1}, + {0x1024, 0x2B62, 0x10C2}, {0x1025, 0x2B63, 0x10C3}, + {0x1026, 0x2B64, 0x10C4}, {0x1027, 0x2B65, 0x10C5}, + {0x1028, 0x1028, 0x10C6}, {0x1029, 0x1029, 0x10C7}, + {0x102A, 0x102A, 0x10C8}, {0x102B, 0x102B, 0x10C9}, + {0x102C, 0x102C, 0x10CA}, {0x102D, 0x102D, 0x10CB}, + {0x102E, 0x102E, 0x10CC}, {0x102F, 0x102F, 0x10CD}, + {0x1030, 0x1030, 0x10CE}, {0x1031, 0x1031, 0x10CF}, + {0x1032, 0x1032, 0x10D0}, {0x1033, 0x1033, 0x10D1}, + {0x1034, 0x1034, 0x10D2}, {0x1035, 0x1035, 0x10D3}, + {0x1036, 0x1036, 0x10D4}, {0x1037, 0x1037, 0x10D5}, + {0x1038, 0x1038, 0x10D6}, {0x1039, 0x1039, 0x10D7}, + {0x103A, 0x103A, 0x10D8}, {0x103B, 0x103B, 0x10D9}, + {0x103C, 0x103C, 0x10DA}, {0x103D, 0x103D, 0x10DB}, + {0x103E, 0x103E, 0x10DC}, {0x103F, 0x103F, 0x10DD}, + {0x1040, 0x1040, 0x10DE}, {0x1041, 0x1041, 0x10DF}, + {0x1042, 0x1042, 0x10E0}, {0x1043, 0x1043, 0x10E1}, + {0x1044, 0x1044, 0x10E2}, {0x1045, 0x1045, 0x10E3}, + {0x1046, 0x1046, 0x10E4}, {0x1047, 0x1047, 0x10E5}, + {0x1048, 0x1048, 0x10E6}, {0x1049, 0x1049, 0x10E7}, + {0x104A, 0x104A, 0x10E8}, {0x104B, 0x104B, 0x10E9}, + {0x104C, 0x104C, 0x10EA}, {0x104D, 0x104D, 0x10EB}, + {0x104E, 0x104E, 0x10EC}, {0x104F, 0x104F, 0x10ED}, + {0x1050, 0x1050, 0x10EE}, {0x1051, 0x1051, 0x10EF}, + {0x1052, 0x1052, 0x10F0}, {0x1053, 0x1053, 0x10F1}, + {0x1054, 0x1054, 0x10F2}, {0x1055, 0x1055, 0x10F3}, + {0x1056, 0x1056, 0x10F4}, {0x1057, 0x1057, 0x10F5}, + {0x1058, 0x1058, 0x10F6}, {0x1059, 0x1059, 0x10F7}, + {0x105A, 0x105A, 0x10F8}, {0x105B, 0x105B, 0x10F9}, + {0x105C, 0x105C, 0x10FA}, {0x105D, 0x105D, 0x10FB}, + {0x105E, 0x105E, 0x10FC}, {0x105F, 0x105F, 0x10FD}, + {0x1060, 0x1060, 0x10FE}, {0x1061, 0x1061, 0x10FF}, + {0x1062, 0x1062, 0x1100}, {0x1063, 0x1063, 0x1101}, + {0x1064, 0x1064, 0x1102}, {0x1065, 0x1065, 0x1103}, + {0x1066, 0x1066, 0x1104}, {0x1067, 0x1067, 0x1105}, + {0x1068, 0x1068, 0x1106}, {0x1069, 0x1069, 0x1107}, + {0x106A, 0x106A, 0x1108}, {0x106B, 0x106B, 0x1109}, + {0x106C, 0x106C, 0x110A}, {0x106D, 0x106D, 0x110B}, + {0x106E, 0x106E, 0x110C}, {0x106F, 0x106F, 0x110D}, + {0x1070, 0x1070, 0x110E}, {0x1071, 0x1071, 0x110F}, + {0x1072, 0x1072, 0x1110}, {0x1073, 0x1073, 0x1111}, + {0x1074, 0x1074, 0x1112}, {0x1075, 0x1075, 0x1113}, + {0x1076, 0x1076, 0x1114}, {0x1077, 0x1077, 0x1115}, + {0x1078, 0x1078, 0x1116}, {0x1079, 0x1079, 0x1117}, + {0x107A, 0x107A, 0x1118}, {0x107B, 0x107B, 0x1119}, + {0x107C, 0x107C, 0x111A}, {0x107D, 0x107D, 0x111B}, + {0x107E, 0x107E, 0x111C}, {0x107F, 0x107F, 0x111D}, + {0x1080, 0x1080, 0x111E}, {0x1081, 0x1081, 0x111F}, + {0x1082, 0x1082, 0x1120}, {0x1083, 0x1083, 0x1121}, + {0x1084, 0x1084, 0x1122}, {0x1085, 0x1085, 0x1123}, + {0x1086, 0x1086, 0x1124}, {0x1087, 0x1087, 0x1125}, + {0x1088, 0x1088, 0x1126}, {0x1089, 0x1089, 0x1127}, + {0x108A, 0x108A, 0x1128}, {0x108B, 0x108B, 0x1129}, + {0x108C, 0x108C, 0x112A}, {0x108D, 0x108D, 0x112B}, + {0x108E, 0x108E, 0x112C}, {0x108F, 0x108F, 0x112D}, + {0x1090, 0x1090, 0x112E}, {0x1091, 0x1091, 0x112F}, + {0x1092, 0x1092, 0x1130}, {0x1093, 0x1093, 0x1131}, + {0x1094, 0x1094, 0x1132}, {0x1095, 0x1095, 0x1133}, + {0x1096, 0x1096, 0x1134}, {0x1097, 0x1097, 0x1135}, + {0x1098, 0x1098, 0x1136}, {0x1099, 0x1099, 0x1137}, + {0x109A, 0x109A, 0x1138}, {0x109B, 0x109B, 0x1139}, + {0x109C, 0x109C, 0x113A}, {0x109D, 0x109D, 0x113B}, + {0x109E, 0x109E, 0x113C}, {0x109F, 0x109F, 0x113D}, + {0x10A0, 0x10A0, 0x113E}, {0x10A1, 0x10A1, 0x113F}, + {0x10A2, 0x10A2, 0x1140}, {0x10A3, 0x10A3, 0x1141}, + {0x10A4, 0x10A4, 0x1142}, {0x10A5, 0x10A5, 0x1143}, + {0x10A6, 0x10A6, 0x1144}, {0x10A7, 0x10A7, 0x1145}, + {0x10A8, 0x10A8, 0x1146}, {0x10A9, 0x10A9, 0x1147}, + {0x10AA, 0x10AA, 0x1148}, {0x10AB, 0x10AB, 0x1149}, + {0x10AC, 0x10AC, 0x114A}, {0x10AD, 0x10AD, 0x114B}, + {0x10AE, 0x10AE, 0x114C}, {0x10AF, 0x10AF, 0x114D}, + {0x10B0, 0x10B0, 0x114E}, {0x10B1, 0x10B1, 0x114F}, + {0x10B2, 0x10B2, 0x1150}, {0x10B3, 0x10B3, 0x1151}, + {0x10B4, 0x10B4, 0x1152}, {0x10B5, 0x10B5, 0x1153}, + {0x10B6, 0x10B6, 0x1154}, {0x10B7, 0x10B7, 0x1155}, + {0x10B8, 0x10B8, 0x1156}, {0x10B9, 0x10B9, 0x1157}, + {0x10BA, 0x10BA, 0x1158}, {0x10BB, 0x10BB, 0x1159}, + {0x10BC, 0x10BC, 0x115A}, {0x10BD, 0x10BD, 0x115B}, + {0x10BE, 0x10BE, 0x115C}, {0x10BF, 0x10BF, 0x115D}, + {0x10C0, 0x10C0, 0x115E}, {0x10C1, 0x10C1, 0x115F}, + {0x10C2, 0x10C2, 0x1160}, {0x10C3, 0x10C3, 0x1161}, + {0x10C4, 0x10C4, 0x1162}, {0x10C5, 0x10C5, 0x1163}, + {0x10C6, 0x10C6, 0x1164}, {0x10C7, 0x10C7, 0x1165}, + {0x10C8, 0x10C8, 0x1166}, {0x10C9, 0x10C9, 0x1167}, + {0x10CA, 0x10CA, 0x1168}, {0x10CB, 0x10CB, 0x1169}, + {0x10CC, 0x10CC, 0x116A}, {0x10CD, 0x10CD, 0x116B}, + {0x10CE, 0x10CE, 0x116C}, {0x10CF, 0x10CF, 0x116D}, + {0x10D0, 0x10D0, 0x116E}, {0x10D1, 0x10D1, 0x116F}, + {0x10D2, 0x10D2, 0x1170}, {0x10D3, 0x10D3, 0x1171}, + {0x10D4, 0x10D4, 0x1172}, {0x10D5, 0x10D5, 0x1173}, + {0x10D6, 0x10D6, 0x1174}, {0x10D7, 0x10D7, 0x1175}, + {0x10D8, 0x10D8, 0x1176}, {0x10D9, 0x10D9, 0x1177}, + {0x10DA, 0x10DA, 0x1178}, {0x10DB, 0x10DB, 0x1179}, + {0x10DC, 0x10DC, 0x117A}, {0x10DD, 0x10DD, 0x117B}, + {0x10DE, 0x10DE, 0x117C}, {0x10DF, 0x10DF, 0x117D}, + {0x10E0, 0x10E0, 0x117E}, {0x10E1, 0x10E1, 0x117F}, + {0x10E2, 0x10E2, 0x1180}, {0x10E3, 0x10E3, 0x1181}, + {0x10E4, 0x10E4, 0x1182}, {0x10E5, 0x10E5, 0x1183}, + {0x10E6, 0x10E6, 0x1184}, {0x10E7, 0x10E7, 0x1185}, + {0x10E8, 0x10E8, 0x1186}, {0x10E9, 0x10E9, 0x1187}, + {0x10EA, 0x10EA, 0x1188}, {0x10EB, 0x10EB, 0x1189}, + {0x10EC, 0x10EC, 0x118A}, {0x10ED, 0x10ED, 0x118B}, + {0x10EE, 0x10EE, 0x118C}, {0x10EF, 0x10EF, 0x118D}, + {0x10F0, 0x10F0, 0x118E}, {0x10F1, 0x10F1, 0x118F}, + {0x10F2, 0x10F2, 0x1190}, {0x10F3, 0x10F3, 0x1191}, + {0x10F4, 0x10F4, 0x1192}, {0x10F5, 0x10F5, 0x1193}, + {0x10F6, 0x10F6, 0x1194}, {0x10F7, 0x10F7, 0x1195}, + {0x10F8, 0x10F8, 0x1196}, {0x10F9, 0x10F9, 0x1197}, + {0x10FA, 0x10FA, 0x1198}, {0x10FB, 0x10FB, 0x1199}, + {0x10FC, 0x10FC, 0x119A}, {0x10FD, 0x10FD, 0x119B}, + {0x10FE, 0x10FE, 0x119C}, {0x10FF, 0x10FF, 0x119D}}; + +static ObUnicaseInfoChar plane1D[] = { + {0x1D00, 0x1D00, 0x1D9E}, {0x1D01, 0x1D01, 0x1D9F}, + {0x1D02, 0x1D02, 0x1DA0}, {0x1D03, 0x1D03, 0x1DA1}, + {0x1D04, 0x1D04, 0x1DA2}, {0x1D05, 0x1D05, 0x1DA3}, + {0x1D06, 0x1D06, 0x1DA4}, {0x1D07, 0x1D07, 0x1DA5}, + {0x1D08, 0x1D08, 0x1DA6}, {0x1D09, 0x1D09, 0x1DA7}, + {0x1D0A, 0x1D0A, 0x1DA8}, {0x1D0B, 0x1D0B, 0x1DA9}, + {0x1D0C, 0x1D0C, 0x1DAA}, {0x1D0D, 0x1D0D, 0x1DAB}, + {0x1D0E, 0x1D0E, 0x1DAC}, {0x1D0F, 0x1D0F, 0x1DAD}, + {0x1D10, 0x1D10, 0x1DAE}, {0x1D11, 0x1D11, 0x1DAF}, + {0x1D12, 0x1D12, 0x1DB0}, {0x1D13, 0x1D13, 0x1DB1}, + {0x1D14, 0x1D14, 0x1DB2}, {0x1D15, 0x1D15, 0x1DB3}, + {0x1D16, 0x1D16, 0x1DB4}, {0x1D17, 0x1D17, 0x1DB5}, + {0x1D18, 0x1D18, 0x1DB6}, {0x1D19, 0x1D19, 0x1DB7}, + {0x1D1A, 0x1D1A, 0x1DB8}, {0x1D1B, 0x1D1B, 0x1DB9}, + {0x1D1C, 0x1D1C, 0x1DBA}, {0x1D1D, 0x1D1D, 0x1DBB}, + {0x1D1E, 0x1D1E, 0x1DBC}, {0x1D1F, 0x1D1F, 0x1DBD}, + {0x1D20, 0x1D20, 0x1DBE}, {0x1D21, 0x1D21, 0x1DBF}, + {0x1D22, 0x1D22, 0x1DC0}, {0x1D23, 0x1D23, 0x1DC1}, + {0x1D24, 0x1D24, 0x1DC2}, {0x1D25, 0x1D25, 0x1DC3}, + {0x1D26, 0x1D26, 0x1DC4}, {0x1D27, 0x1D27, 0x1DC5}, + {0x1D28, 0x1D28, 0x1DC6}, {0x1D29, 0x1D29, 0x1DC7}, + {0x1D2A, 0x1D2A, 0x1DC8}, {0x1D2B, 0x1D2B, 0x1DC9}, + {0x1D2C, 0x1D2C, 0x1DCA}, {0x1D2D, 0x1D2D, 0x1DCB}, + {0x1D2E, 0x1D2E, 0x1DCC}, {0x1D2F, 0x1D2F, 0x1DCD}, + {0x1D30, 0x1D30, 0x1DCE}, {0x1D31, 0x1D31, 0x1DCF}, + {0x1D32, 0x1D32, 0x1DD0}, {0x1D33, 0x1D33, 0x1DD1}, + {0x1D34, 0x1D34, 0x1DD2}, {0x1D35, 0x1D35, 0x1DD3}, + {0x1D36, 0x1D36, 0x1DD4}, {0x1D37, 0x1D37, 0x1DD5}, + {0x1D38, 0x1D38, 0x1DD6}, {0x1D39, 0x1D39, 0x1DD7}, + {0x1D3A, 0x1D3A, 0x1DD8}, {0x1D3B, 0x1D3B, 0x1DD9}, + {0x1D3C, 0x1D3C, 0x1DDA}, {0x1D3D, 0x1D3D, 0x1DDB}, + {0x1D3E, 0x1D3E, 0x1DDC}, {0x1D3F, 0x1D3F, 0x1DDD}, + {0x1D40, 0x1D40, 0x1DDE}, {0x1D41, 0x1D41, 0x1DDF}, + {0x1D42, 0x1D42, 0x1DE0}, {0x1D43, 0x1D43, 0x1DE1}, + {0x1D44, 0x1D44, 0x1DE2}, {0x1D45, 0x1D45, 0x1DE3}, + {0x1D46, 0x1D46, 0x1DE4}, {0x1D47, 0x1D47, 0x1DE5}, + {0x1D48, 0x1D48, 0x1DE6}, {0x1D49, 0x1D49, 0x1DE7}, + {0x1D4A, 0x1D4A, 0x1DE8}, {0x1D4B, 0x1D4B, 0x1DE9}, + {0x1D4C, 0x1D4C, 0x1DEA}, {0x1D4D, 0x1D4D, 0x1DEB}, + {0x1D4E, 0x1D4E, 0x1DEC}, {0x1D4F, 0x1D4F, 0x1DED}, + {0x1D50, 0x1D50, 0x1DEE}, {0x1D51, 0x1D51, 0x1DEF}, + {0x1D52, 0x1D52, 0x1DF0}, {0x1D53, 0x1D53, 0x1DF1}, + {0x1D54, 0x1D54, 0x1DF2}, {0x1D55, 0x1D55, 0x1DF3}, + {0x1D56, 0x1D56, 0x1DF4}, {0x1D57, 0x1D57, 0x1DF5}, + {0x1D58, 0x1D58, 0x1DF6}, {0x1D59, 0x1D59, 0x1DF7}, + {0x1D5A, 0x1D5A, 0x1DF8}, {0x1D5B, 0x1D5B, 0x1DF9}, + {0x1D5C, 0x1D5C, 0x1DFA}, {0x1D5D, 0x1D5D, 0x1DFB}, + {0x1D5E, 0x1D5E, 0x1DFC}, {0x1D5F, 0x1D5F, 0x1DFD}, + {0x1D60, 0x1D60, 0x1DFE}, {0x1D61, 0x1D61, 0x1DFF}, + {0x1D62, 0x1D63, 0x1E00}, {0x1D62, 0x1D63, 0x1E00}, + {0x1D64, 0x1D65, 0x1E02}, {0x1D64, 0x1D65, 0x1E02}, + {0x1D66, 0x1D67, 0x1E04}, {0x1D66, 0x1D67, 0x1E04}, + {0x1D68, 0x1D69, 0x1E06}, {0x1D68, 0x1D69, 0x1E06}, + {0x1D6A, 0x1D6B, 0x1E08}, {0x1D6A, 0x1D6B, 0x1E08}, + {0x1D6C, 0x1D6D, 0x1E0A}, {0x1D6C, 0x1D6D, 0x1E0A}, + {0x1D6E, 0x1D6F, 0x1E0C}, {0x1D6E, 0x1D6F, 0x1E0C}, + {0x1D70, 0x1D71, 0x1E0E}, {0x1D70, 0x1D71, 0x1E0E}, + {0x1D72, 0x1D73, 0x1E10}, {0x1D72, 0x1D73, 0x1E10}, + {0x1D74, 0x1D75, 0x1E12}, {0x1D74, 0x1D75, 0x1E12}, + {0x1D76, 0x1D77, 0x1E14}, {0x1D76, 0x1D77, 0x1E14}, + {0x1D78, 0x1D79, 0x1E16}, {0x1D78, 0x1D79, 0x1E16}, + {0x1D7A, 0x1D7B, 0x1E18}, {0x1D7A, 0x1D7B, 0x1E18}, + {0x1D7C, 0x1D7D, 0x1E1A}, {0x1D7C, 0x1D7D, 0x1E1A}, + {0x1D7E, 0x1D7F, 0x1E1C}, {0x1D7E, 0x1D7F, 0x1E1C}, + {0x1D80, 0x1D81, 0x1E1E}, {0x1D80, 0x1D81, 0x1E1E}, + {0x1D82, 0x1D83, 0x1E20}, {0x1D82, 0x1D83, 0x1E20}, + {0x1D84, 0x1D85, 0x1E22}, {0x1D84, 0x1D85, 0x1E22}, + {0x1D86, 0x1D87, 0x1E24}, {0x1D86, 0x1D87, 0x1E24}, + {0x1D88, 0x1D89, 0x1E26}, {0x1D88, 0x1D89, 0x1E26}, + {0x1D8A, 0x1D8B, 0x1E28}, {0x1D8A, 0x1D8B, 0x1E28}, + {0x1D8C, 0x1D8D, 0x1E2A}, {0x1D8C, 0x1D8D, 0x1E2A}, + {0x1D8E, 0x1D8F, 0x1E2C}, {0x1D8E, 0x1D8F, 0x1E2C}, + {0x1D90, 0x1D91, 0x1E2E}, {0x1D90, 0x1D91, 0x1E2E}, + {0x1D92, 0x1D93, 0x1E30}, {0x1D92, 0x1D93, 0x1E30}, + {0x1D94, 0x1D95, 0x1E32}, {0x1D94, 0x1D95, 0x1E32}, + {0x1D96, 0x1D97, 0x1E34}, {0x1D96, 0x1D97, 0x1E34}, + {0x1D98, 0x1D99, 0x1E36}, {0x1D98, 0x1D99, 0x1E36}, + {0x1D9A, 0x1D9B, 0x1E38}, {0x1D9A, 0x1D9B, 0x1E38}, + {0x1D9C, 0x1D9D, 0x1E3A}, {0x1D9C, 0x1D9D, 0x1E3A}, + {0x1D9E, 0x1D9F, 0x1E3C}, {0x1D9E, 0x1D9F, 0x1E3C}, + {0x1DA0, 0xA8BC, 0x1E3E}, {0x1DA1, 0x1DA1, 0xE7C7}, + {0x1DA2, 0x1DA3, 0x1E40}, {0x1DA2, 0x1DA3, 0x1E40}, + {0x1DA4, 0x1DA5, 0x1E42}, {0x1DA4, 0x1DA5, 0x1E42}, + {0x1DA6, 0x1DA7, 0x1E44}, {0x1DA6, 0x1DA7, 0x1E44}, + {0x1DA8, 0x1DA9, 0x1E46}, {0x1DA8, 0x1DA9, 0x1E46}, + {0x1DAA, 0x1DAB, 0x1E48}, {0x1DAA, 0x1DAB, 0x1E48}, + {0x1DAC, 0x1DAD, 0x1E4A}, {0x1DAC, 0x1DAD, 0x1E4A}, + {0x1DAE, 0x1DAF, 0x1E4C}, {0x1DAE, 0x1DAF, 0x1E4C}, + {0x1DB0, 0x1DB1, 0x1E4E}, {0x1DB0, 0x1DB1, 0x1E4E}, + {0x1DB2, 0x1DB3, 0x1E50}, {0x1DB2, 0x1DB3, 0x1E50}, + {0x1DB4, 0x1DB5, 0x1E52}, {0x1DB4, 0x1DB5, 0x1E52}, + {0x1DB6, 0x1DB7, 0x1E54}, {0x1DB6, 0x1DB7, 0x1E54}, + {0x1DB8, 0x1DB9, 0x1E56}, {0x1DB8, 0x1DB9, 0x1E56}, + {0x1DBA, 0x1DBB, 0x1E58}, {0x1DBA, 0x1DBB, 0x1E58}, + {0x1DBC, 0x1DBD, 0x1E5A}, {0x1DBC, 0x1DBD, 0x1E5A}, + {0x1DBE, 0x1DBF, 0x1E5C}, {0x1DBE, 0x1DBF, 0x1E5C}, + {0x1DC0, 0x1DC1, 0x1E5E}, {0x1DC0, 0x1DC1, 0x1E5E}, + {0x1DC2, 0x1DC3, 0x1E60}, {0x1DC2, 0x1DC3, 0x1E60}, + {0x1DC4, 0x1DC5, 0x1E62}, {0x1DC4, 0x1DC5, 0x1E62}, + {0x1DC6, 0x1DC7, 0x1E64}, {0x1DC6, 0x1DC7, 0x1E64}, + {0x1DC8, 0x1DC9, 0x1E66}, {0x1DC8, 0x1DC9, 0x1E66}, + {0x1DCA, 0x1DCB, 0x1E68}, {0x1DCA, 0x1DCB, 0x1E68}, + {0x1DCC, 0x1DCD, 0x1E6A}, {0x1DCC, 0x1DCD, 0x1E6A}, + {0x1DCE, 0x1DCF, 0x1E6C}, {0x1DCE, 0x1DCF, 0x1E6C}, + {0x1DD0, 0x1DD1, 0x1E6E}, {0x1DD0, 0x1DD1, 0x1E6E}, + {0x1DD2, 0x1DD3, 0x1E70}, {0x1DD2, 0x1DD3, 0x1E70}, + {0x1DD4, 0x1DD5, 0x1E72}, {0x1DD4, 0x1DD5, 0x1E72}, + {0x1DD6, 0x1DD7, 0x1E74}, {0x1DD6, 0x1DD7, 0x1E74}, + {0x1DD8, 0x1DD9, 0x1E76}, {0x1DD8, 0x1DD9, 0x1E76}, + {0x1DDA, 0x1DDB, 0x1E78}, {0x1DDA, 0x1DDB, 0x1E78}, + {0x1DDC, 0x1DDD, 0x1E7A}, {0x1DDC, 0x1DDD, 0x1E7A}, + {0x1DDE, 0x1DDF, 0x1E7C}, {0x1DDE, 0x1DDF, 0x1E7C}, + {0x1DE0, 0x1DE1, 0x1E7E}, {0x1DE0, 0x1DE1, 0x1E7E}, + {0x1DE2, 0x1DE3, 0x1E80}, {0x1DE2, 0x1DE3, 0x1E80}, + {0x1DE4, 0x1DE5, 0x1E82}, {0x1DE4, 0x1DE5, 0x1E82}, + {0x1DE6, 0x1DE7, 0x1E84}, {0x1DE6, 0x1DE7, 0x1E84}, + {0x1DE8, 0x1DE9, 0x1E86}, {0x1DE8, 0x1DE9, 0x1E86}, + {0x1DEA, 0x1DEB, 0x1E88}, {0x1DEA, 0x1DEB, 0x1E88}, + {0x1DEC, 0x1DED, 0x1E8A}, {0x1DEC, 0x1DED, 0x1E8A}, + {0x1DEE, 0x1DEF, 0x1E8C}, {0x1DEE, 0x1DEF, 0x1E8C}, + {0x1DF0, 0x1DF1, 0x1E8E}, {0x1DF0, 0x1DF1, 0x1E8E}, + {0x1DF2, 0x1DF3, 0x1E90}, {0x1DF2, 0x1DF3, 0x1E90}, + {0x1DF4, 0x1DF5, 0x1E92}, {0x1DF4, 0x1DF5, 0x1E92}, + {0x1DF6, 0x1DF7, 0x1E94}, {0x1DF6, 0x1DF7, 0x1E94}, + {0x1DF8, 0x1DF8, 0x1E96}, {0x1DF9, 0x1DF9, 0x1E97}, + {0x1DFA, 0x1DFA, 0x1E98}, {0x1DFB, 0x1DFB, 0x1E99}, + {0x1DFC, 0x1DFC, 0x1E9A}, {0x1DFD, 0x1DC3, 0x1E9B}, + {0x1DFE, 0x1DFE, 0x1E9C}, {0x1DFF, 0x1DFF, 0x1E9D}}; + +static ObUnicaseInfoChar plane1E[] = { + {0x1E00, 0x00D8, 0x1E9E}, {0x1E01, 0x1E01, 0x1E9F}, + {0x1E02, 0x1E03, 0x1EA0}, {0x1E02, 0x1E03, 0x1EA0}, + {0x1E04, 0x1E05, 0x1EA2}, {0x1E04, 0x1E05, 0x1EA2}, + {0x1E06, 0x1E07, 0x1EA4}, {0x1E06, 0x1E07, 0x1EA4}, + {0x1E08, 0x1E09, 0x1EA6}, {0x1E08, 0x1E09, 0x1EA6}, + {0x1E0A, 0x1E0B, 0x1EA8}, {0x1E0A, 0x1E0B, 0x1EA8}, + {0x1E0C, 0x1E0D, 0x1EAA}, {0x1E0C, 0x1E0D, 0x1EAA}, + {0x1E0E, 0x1E0F, 0x1EAC}, {0x1E0E, 0x1E0F, 0x1EAC}, + {0x1E10, 0x1E11, 0x1EAE}, {0x1E10, 0x1E11, 0x1EAE}, + {0x1E12, 0x1E13, 0x1EB0}, {0x1E12, 0x1E13, 0x1EB0}, + {0x1E14, 0x1E15, 0x1EB2}, {0x1E14, 0x1E15, 0x1EB2}, + {0x1E16, 0x1E17, 0x1EB4}, {0x1E16, 0x1E17, 0x1EB4}, + {0x1E18, 0x1E19, 0x1EB6}, {0x1E18, 0x1E19, 0x1EB6}, + {0x1E1A, 0x1E1B, 0x1EB8}, {0x1E1A, 0x1E1B, 0x1EB8}, + {0x1E1C, 0x1E1D, 0x1EBA}, {0x1E1C, 0x1E1D, 0x1EBA}, + {0x1E1E, 0x1E1F, 0x1EBC}, {0x1E1E, 0x1E1F, 0x1EBC}, + {0x1E20, 0x1E21, 0x1EBE}, {0x1E20, 0x1E21, 0x1EBE}, + {0x1E22, 0x1E23, 0x1EC0}, {0x1E22, 0x1E23, 0x1EC0}, + {0x1E24, 0x1E25, 0x1EC2}, {0x1E24, 0x1E25, 0x1EC2}, + {0x1E26, 0x1E27, 0x1EC4}, {0x1E26, 0x1E27, 0x1EC4}, + {0x1E28, 0x1E29, 0x1EC6}, {0x1E28, 0x1E29, 0x1EC6}, + {0x1E2A, 0x1E2B, 0x1EC8}, {0x1E2A, 0x1E2B, 0x1EC8}, + {0x1E2C, 0x1E2D, 0x1ECA}, {0x1E2C, 0x1E2D, 0x1ECA}, + {0x1E2E, 0x1E2F, 0x1ECC}, {0x1E2E, 0x1E2F, 0x1ECC}, + {0x1E30, 0x1E31, 0x1ECE}, {0x1E30, 0x1E31, 0x1ECE}, + {0x1E32, 0x1E33, 0x1ED0}, {0x1E32, 0x1E33, 0x1ED0}, + {0x1E34, 0x1E35, 0x1ED2}, {0x1E34, 0x1E35, 0x1ED2}, + {0x1E36, 0x1E37, 0x1ED4}, {0x1E36, 0x1E37, 0x1ED4}, + {0x1E38, 0x1E39, 0x1ED6}, {0x1E38, 0x1E39, 0x1ED6}, + {0x1E3A, 0x1E3B, 0x1ED8}, {0x1E3A, 0x1E3B, 0x1ED8}, + {0x1E3C, 0x1E3D, 0x1EDA}, {0x1E3C, 0x1E3D, 0x1EDA}, + {0x1E3E, 0x1E3F, 0x1EDC}, {0x1E3E, 0x1E3F, 0x1EDC}, + {0x1E40, 0x1E41, 0x1EDE}, {0x1E40, 0x1E41, 0x1EDE}, + {0x1E42, 0x1E43, 0x1EE0}, {0x1E42, 0x1E43, 0x1EE0}, + {0x1E44, 0x1E45, 0x1EE2}, {0x1E44, 0x1E45, 0x1EE2}, + {0x1E46, 0x1E47, 0x1EE4}, {0x1E46, 0x1E47, 0x1EE4}, + {0x1E48, 0x1E49, 0x1EE6}, {0x1E48, 0x1E49, 0x1EE6}, + {0x1E4A, 0x1E4B, 0x1EE8}, {0x1E4A, 0x1E4B, 0x1EE8}, + {0x1E4C, 0x1E4D, 0x1EEA}, {0x1E4C, 0x1E4D, 0x1EEA}, + {0x1E4E, 0x1E4F, 0x1EEC}, {0x1E4E, 0x1E4F, 0x1EEC}, + {0x1E50, 0x1E51, 0x1EEE}, {0x1E50, 0x1E51, 0x1EEE}, + {0x1E52, 0x1E53, 0x1EF0}, {0x1E52, 0x1E53, 0x1EF0}, + {0x1E54, 0x1E55, 0x1EF2}, {0x1E54, 0x1E55, 0x1EF2}, + {0x1E56, 0x1E57, 0x1EF4}, {0x1E56, 0x1E57, 0x1EF4}, + {0x1E58, 0x1E59, 0x1EF6}, {0x1E58, 0x1E59, 0x1EF6}, + {0x1E5A, 0x1E5B, 0x1EF8}, {0x1E5A, 0x1E5B, 0x1EF8}, + {0x1E5C, 0x1E5D, 0x1EFA}, {0x1E5C, 0x1E5D, 0x1EFA}, + {0x1E5E, 0x1E5F, 0x1EFC}, {0x1E5E, 0x1E5F, 0x1EFC}, + {0x1E60, 0x1E61, 0x1EFE}, {0x1E60, 0x1E61, 0x1EFE}, + {0x1E6A, 0x1E62, 0x1F08}, {0x1E6B, 0x1E63, 0x1F09}, + {0x1E6C, 0x1E64, 0x1F0A}, {0x1E6D, 0x1E65, 0x1F0B}, + {0x1E6E, 0x1E66, 0x1F0C}, {0x1E6F, 0x1E67, 0x1F0D}, + {0x1E70, 0x1E68, 0x1F0E}, {0x1E71, 0x1E69, 0x1F0F}, + {0x1E6A, 0x1E62, 0x1F08}, {0x1E6B, 0x1E63, 0x1F09}, + {0x1E6C, 0x1E64, 0x1F0A}, {0x1E6D, 0x1E65, 0x1F0B}, + {0x1E6E, 0x1E66, 0x1F0C}, {0x1E6F, 0x1E67, 0x1F0D}, + {0x1E70, 0x1E68, 0x1F0E}, {0x1E71, 0x1E69, 0x1F0F}, + {0x1E7A, 0x1E72, 0x1F18}, {0x1E7B, 0x1E73, 0x1F19}, + {0x1E7C, 0x1E74, 0x1F1A}, {0x1E7D, 0x1E75, 0x1F1B}, + {0x1E7E, 0x1E76, 0x1F1C}, {0x1E7F, 0x1E77, 0x1F1D}, + {0x1E78, 0x1E78, 0x1F16}, {0x1E79, 0x1E79, 0x1F17}, + {0x1E7A, 0x1E72, 0x1F18}, {0x1E7B, 0x1E73, 0x1F19}, + {0x1E7C, 0x1E74, 0x1F1A}, {0x1E7D, 0x1E75, 0x1F1B}, + {0x1E7E, 0x1E76, 0x1F1C}, {0x1E7F, 0x1E77, 0x1F1D}, + {0x1E80, 0x1E80, 0x1F1E}, {0x1E81, 0x1E81, 0x1F1F}, + {0x1E8A, 0x1E82, 0x1F28}, {0x1E8B, 0x1E83, 0x1F29}, + {0x1E8C, 0x1E84, 0x1F2A}, {0x1E8D, 0x1E85, 0x1F2B}, + {0x1E8E, 0x1E86, 0x1F2C}, {0x1E8F, 0x1E87, 0x1F2D}, + {0x1E90, 0x1E88, 0x1F2E}, {0x1E91, 0x1E89, 0x1F2F}, + {0x1E8A, 0x1E82, 0x1F28}, {0x1E8B, 0x1E83, 0x1F29}, + {0x1E8C, 0x1E84, 0x1F2A}, {0x1E8D, 0x1E85, 0x1F2B}, + {0x1E8E, 0x1E86, 0x1F2C}, {0x1E8F, 0x1E87, 0x1F2D}, + {0x1E90, 0x1E88, 0x1F2E}, {0x1E91, 0x1E89, 0x1F2F}, + {0x1E9A, 0x1E92, 0x1F38}, {0x1E9B, 0x1E93, 0x1F39}, + {0x1E9C, 0x1E94, 0x1F3A}, {0x1E9D, 0x1E95, 0x1F3B}, + {0x1E9E, 0x1E96, 0x1F3C}, {0x1E9F, 0x1E97, 0x1F3D}, + {0x1EA0, 0x1E98, 0x1F3E}, {0x1EA1, 0x1E99, 0x1F3F}, + {0x1E9A, 0x1E92, 0x1F38}, {0x1E9B, 0x1E93, 0x1F39}, + {0x1E9C, 0x1E94, 0x1F3A}, {0x1E9D, 0x1E95, 0x1F3B}, + {0x1E9E, 0x1E96, 0x1F3C}, {0x1E9F, 0x1E97, 0x1F3D}, + {0x1EA0, 0x1E98, 0x1F3E}, {0x1EA1, 0x1E99, 0x1F3F}, + {0x1EAA, 0x1EA2, 0x1F48}, {0x1EAB, 0x1EA3, 0x1F49}, + {0x1EAC, 0x1EA4, 0x1F4A}, {0x1EAD, 0x1EA5, 0x1F4B}, + {0x1EAE, 0x1EA6, 0x1F4C}, {0x1EAF, 0x1EA7, 0x1F4D}, + {0x1EA8, 0x1EA8, 0x1F46}, {0x1EA9, 0x1EA9, 0x1F47}, + {0x1EAA, 0x1EA2, 0x1F48}, {0x1EAB, 0x1EA3, 0x1F49}, + {0x1EAC, 0x1EA4, 0x1F4A}, {0x1EAD, 0x1EA5, 0x1F4B}, + {0x1EAE, 0x1EA6, 0x1F4C}, {0x1EAF, 0x1EA7, 0x1F4D}, + {0x1EB0, 0x1EB0, 0x1F4E}, {0x1EB1, 0x1EB1, 0x1F4F}, + {0x1EB2, 0x1EB2, 0x1F50}, {0x1EBB, 0x1EB3, 0x1F59}, + {0x1EB4, 0x1EB4, 0x1F52}, {0x1EBD, 0x1EB5, 0x1F5B}, + {0x1EB6, 0x1EB6, 0x1F54}, {0x1EBF, 0x1EB7, 0x1F5D}, + {0x1EB8, 0x1EB8, 0x1F56}, {0x1EC1, 0x1EB9, 0x1F5F}, + {0x1EBA, 0x1EBA, 0x1F58}, {0x1EBB, 0x1EB3, 0x1F59}, + {0x1EBC, 0x1EBC, 0x1F5A}, {0x1EBD, 0x1EB5, 0x1F5B}, + {0x1EBE, 0x1EBE, 0x1F5C}, {0x1EBF, 0x1EB7, 0x1F5D}, + {0x1EC0, 0x1EC0, 0x1F5E}, {0x1EC1, 0x1EB9, 0x1F5F}, + {0x1ECA, 0x1EC2, 0x1F68}, {0x1ECB, 0x1EC3, 0x1F69}, + {0x1ECC, 0x1EC4, 0x1F6A}, {0x1ECD, 0x1EC5, 0x1F6B}, + {0x1ECE, 0x1EC6, 0x1F6C}, {0x1ECF, 0x1EC7, 0x1F6D}, + {0x1ED0, 0x1EC8, 0x1F6E}, {0x1ED1, 0x1EC9, 0x1F6F}, + {0x1ECA, 0x1EC2, 0x1F68}, {0x1ECB, 0x1EC3, 0x1F69}, + {0x1ECC, 0x1EC4, 0x1F6A}, {0x1ECD, 0x1EC5, 0x1F6B}, + {0x1ECE, 0x1EC6, 0x1F6C}, {0x1ECF, 0x1EC7, 0x1F6D}, + {0x1ED0, 0x1EC8, 0x1F6E}, {0x1ED1, 0x1EC9, 0x1F6F}, + {0x1F1C, 0x1ED2, 0x1FBA}, {0x1F1D, 0x1ED3, 0x1FBB}, + {0x1F2A, 0x1ED4, 0x1FC8}, {0x1F2B, 0x1ED5, 0x1FC9}, + {0x1F2C, 0x1ED6, 0x1FCA}, {0x1F2D, 0x1ED7, 0x1FCB}, + {0x1F3C, 0x1ED8, 0x1FDA}, {0x1F3D, 0x1ED9, 0x1FDB}, + {0x1F5A, 0x1EDA, 0x1FF8}, {0x1F5B, 0x1EDB, 0x1FF9}, + {0x1F4C, 0x1EDC, 0x1FEA}, {0x1F4D, 0x1EDD, 0x1FEB}, + {0x1F5C, 0x1EDE, 0x1FFA}, {0x1F5D, 0x1EDF, 0x1FFB}, + {0x1EE0, 0x1EE0, 0x1F7E}, {0x1EE1, 0x1EE1, 0x1F7F}, + {0x1EEA, 0x1EE2, 0x1F88}, {0x1EEB, 0x1EE3, 0x1F89}, + {0x1EEC, 0x1EE4, 0x1F8A}, {0x1EED, 0x1EE5, 0x1F8B}, + {0x1EEE, 0x1EE6, 0x1F8C}, {0x1EEF, 0x1EE7, 0x1F8D}, + {0x1EF0, 0x1EE8, 0x1F8E}, {0x1EF1, 0x1EE9, 0x1F8F}, + {0x1EEA, 0x1EE2, 0x1F88}, {0x1EEB, 0x1EE3, 0x1F89}, + {0x1EEC, 0x1EE4, 0x1F8A}, {0x1EED, 0x1EE5, 0x1F8B}, + {0x1EEE, 0x1EE6, 0x1F8C}, {0x1EEF, 0x1EE7, 0x1F8D}, + {0x1EF0, 0x1EE8, 0x1F8E}, {0x1EF1, 0x1EE9, 0x1F8F}, + {0x1EFA, 0x1EF2, 0x1F98}, {0x1EFB, 0x1EF3, 0x1F99}, + {0x1EFC, 0x1EF4, 0x1F9A}, {0x1EFD, 0x1EF5, 0x1F9B}, + {0x1EFE, 0x1EF6, 0x1F9C}, {0x1EFF, 0x1EF7, 0x1F9D}, + {0x1F00, 0x1EF8, 0x1F9E}, {0x1F01, 0x1EF9, 0x1F9F}, + {0x1EFA, 0x1EF2, 0x1F98}, {0x1EFB, 0x1EF3, 0x1F99}, + {0x1EFC, 0x1EF4, 0x1F9A}, {0x1EFD, 0x1EF5, 0x1F9B}, + {0x1EFE, 0x1EF6, 0x1F9C}, {0x1EFF, 0x1EF7, 0x1F9D}}; + +static ObUnicaseInfoChar plane1F[] = { + {0x1F00, 0x1EF8, 0x1F9E}, {0x1F01, 0x1EF9, 0x1F9F}, + {0x1F0A, 0x1F02, 0x1FA8}, {0x1F0B, 0x1F03, 0x1FA9}, + {0x1F0C, 0x1F04, 0x1FAA}, {0x1F0D, 0x1F05, 0x1FAB}, + {0x1F0E, 0x1F06, 0x1FAC}, {0x1F0F, 0x1F07, 0x1FAD}, + {0x1F10, 0x1F08, 0x1FAE}, {0x1F11, 0x1F09, 0x1FAF}, + {0x1F0A, 0x1F02, 0x1FA8}, {0x1F0B, 0x1F03, 0x1FA9}, + {0x1F0C, 0x1F04, 0x1FAA}, {0x1F0D, 0x1F05, 0x1FAB}, + {0x1F0E, 0x1F06, 0x1FAC}, {0x1F0F, 0x1F07, 0x1FAD}, + {0x1F10, 0x1F08, 0x1FAE}, {0x1F11, 0x1F09, 0x1FAF}, + {0x1F1A, 0x1F12, 0x1FB8}, {0x1F1B, 0x1F13, 0x1FB9}, + {0x1F14, 0x1F14, 0x1FB2}, {0x1F1E, 0x1F15, 0x1FBC}, + {0x1F16, 0x1F16, 0x1FB4}, {0x1F17, 0x1F17, 0x1FB5}, + {0x1F18, 0x1F18, 0x1FB6}, {0x1F19, 0x1F19, 0x1FB7}, + {0x1F1A, 0x1F12, 0x1FB8}, {0x1F1B, 0x1F13, 0x1FB9}, + {0x1F1C, 0x1ED2, 0x1FBA}, {0x1F1D, 0x1ED3, 0x1FBB}, + {0x1F1E, 0x1F15, 0x1FBC}, {0x1F1F, 0x1F1F, 0x1FBD}, + {0x1F20, 0xA6C9, 0x1FBE}, {0x1F21, 0x1F21, 0x1FBF}, + {0x1F22, 0x1F22, 0x1FC0}, {0x1F23, 0x1F23, 0x1FC1}, + {0x1F24, 0x1F24, 0x1FC2}, {0x1F2E, 0x1F25, 0x1FCC}, + {0x1F26, 0x1F26, 0x1FC4}, {0x1F27, 0x1F27, 0x1FC5}, + {0x1F28, 0x1F28, 0x1FC6}, {0x1F29, 0x1F29, 0x1FC7}, + {0x1F2A, 0x1ED4, 0x1FC8}, {0x1F2B, 0x1ED5, 0x1FC9}, + {0x1F2C, 0x1ED6, 0x1FCA}, {0x1F2D, 0x1ED7, 0x1FCB}, + {0x1F2E, 0x1F25, 0x1FCC}, {0x1F2F, 0x1F2F, 0x1FCD}, + {0x1F30, 0x1F30, 0x1FCE}, {0x1F31, 0x1F31, 0x1FCF}, + {0x1F3A, 0x1F32, 0x1FD8}, {0x1F3B, 0x1F33, 0x1FD9}, + {0x1F34, 0x1F34, 0x1FD2}, {0x1F35, 0x1F35, 0x1FD3}, + {0x1F36, 0x1F36, 0x1FD4}, {0x1F37, 0x1F37, 0x1FD5}, + {0x1F38, 0x1F38, 0x1FD6}, {0x1F39, 0x1F39, 0x1FD7}, + {0x1F3A, 0x1F32, 0x1FD8}, {0x1F3B, 0x1F33, 0x1FD9}, + {0x1F3C, 0x1ED8, 0x1FDA}, {0x1F3D, 0x1ED9, 0x1FDB}, + {0x1F3E, 0x1F3E, 0x1FDC}, {0x1F3F, 0x1F3F, 0x1FDD}, + {0x1F40, 0x1F40, 0x1FDE}, {0x1F41, 0x1F41, 0x1FDF}, + {0x1F4A, 0x1F42, 0x1FE8}, {0x1F4B, 0x1F43, 0x1FE9}, + {0x1F44, 0x1F44, 0x1FE2}, {0x1F45, 0x1F45, 0x1FE3}, + {0x1F46, 0x1F46, 0x1FE4}, {0x1F4E, 0x1F47, 0x1FEC}, + {0x1F48, 0x1F48, 0x1FE6}, {0x1F49, 0x1F49, 0x1FE7}, + {0x1F4A, 0x1F42, 0x1FE8}, {0x1F4B, 0x1F43, 0x1FE9}, + {0x1F4C, 0x1EDC, 0x1FEA}, {0x1F4D, 0x1EDD, 0x1FEB}, + {0x1F4E, 0x1F47, 0x1FEC}, {0x1F4F, 0x1F4F, 0x1FED}, + {0x1F50, 0x1F50, 0x1FEE}, {0x1F51, 0x1F51, 0x1FEF}, + {0x1F52, 0x1F52, 0x1FF0}, {0x1F53, 0x1F53, 0x1FF1}, + {0x1F54, 0x1F54, 0x1FF2}, {0x1F5E, 0x1F55, 0x1FFC}, + {0x1F56, 0x1F56, 0x1FF4}, {0x1F57, 0x1F57, 0x1FF5}, + {0x1F58, 0x1F58, 0x1FF6}, {0x1F59, 0x1F59, 0x1FF7}, + {0x1F5A, 0x1EDA, 0x1FF8}, {0x1F5B, 0x1EDB, 0x1FF9}, + {0x1F5C, 0x1EDE, 0x1FFA}, {0x1F5D, 0x1EDF, 0x1FFB}, + {0x1F5E, 0x1F55, 0x1FFC}, {0x1F5F, 0x1F5F, 0x1FFD}, + {0x1F60, 0x1F60, 0x1FFE}, {0x1F61, 0x1F61, 0x1FFF}, + {0x1F62, 0x1F62, 0x2000}, {0x1F63, 0x1F63, 0x2001}, + {0x1F64, 0x1F64, 0x2002}, {0x1F65, 0x1F65, 0x2003}, + {0x1F66, 0x1F66, 0x2004}, {0x1F67, 0x1F67, 0x2005}, + {0x1F68, 0x1F68, 0x2006}, {0x1F69, 0x1F69, 0x2007}, + {0x1F6A, 0x1F6A, 0x2008}, {0x1F6B, 0x1F6B, 0x2009}, + {0x1F6C, 0x1F6C, 0x200A}, {0x1F6D, 0x1F6D, 0x200B}, + {0x1F6E, 0x1F6E, 0x200C}, {0x1F6F, 0x1F6F, 0x200D}, + {0x1F70, 0x1F70, 0x200E}, {0x1F71, 0x1F71, 0x200F}, + {0x1F72, 0x1F72, 0x2011}, {0x1F73, 0x1F73, 0x2012}, + {0x1F74, 0x1F74, 0x2017}, {0x1F75, 0x1F75, 0x201A}, + {0x1F76, 0x1F76, 0x201B}, {0x1F77, 0x1F77, 0x201E}, + {0x1F78, 0x1F78, 0x201F}, {0x1F79, 0x1F79, 0x2020}, + {0x1F7A, 0x1F7A, 0x2021}, {0x1F7B, 0x1F7B, 0x2022}, + {0x1F7C, 0x1F7C, 0x2023}, {0x1F7D, 0x1F7D, 0x2024}, + {0x1F7E, 0x1F7E, 0x2027}, {0x1F7F, 0x1F7F, 0x2028}, + {0x1F80, 0x1F80, 0x2029}, {0x1F81, 0x1F81, 0x202A}, + {0x1F82, 0x1F82, 0x202B}, {0x1F83, 0x1F83, 0x202C}, + {0x1F84, 0x1F84, 0x202D}, {0x1F85, 0x1F85, 0x202E}, + {0x1F86, 0x1F86, 0x202F}, {0x1F87, 0x1F87, 0x2031}, + {0x1F88, 0x1F88, 0x2034}, {0x1F89, 0x1F89, 0x2036}, + {0x1F8A, 0x1F8A, 0x2037}, {0x1F8B, 0x1F8B, 0x2038}, + {0x1F8C, 0x1F8C, 0x2039}, {0x1F8D, 0x1F8D, 0x203A}, + {0x1F8E, 0x1F8E, 0x203C}, {0x1F8F, 0x1F8F, 0x203D}, + {0x1F90, 0x1F90, 0x203E}, {0x1F91, 0x1F91, 0x203F}, + {0x1F92, 0x1F92, 0x2040}, {0x1F93, 0x1F93, 0x2041}, + {0x1F94, 0x1F94, 0x2042}, {0x1F95, 0x1F95, 0x2043}, + {0x1F96, 0x1F96, 0x2044}, {0x1F97, 0x1F97, 0x2045}, + {0x1F98, 0x1F98, 0x2046}, {0x1F99, 0x1F99, 0x2047}, + {0x1F9A, 0x1F9A, 0x2048}, {0x1F9B, 0x1F9B, 0x2049}, + {0x1F9C, 0x1F9C, 0x204A}, {0x1F9D, 0x1F9D, 0x204B}, + {0x1F9E, 0x1F9E, 0x204C}, {0x1F9F, 0x1F9F, 0x204D}, + {0x1FA0, 0x1FA0, 0x204E}, {0x1FA1, 0x1FA1, 0x204F}, + {0x1FA2, 0x1FA2, 0x2050}, {0x1FA3, 0x1FA3, 0x2051}, + {0x1FA4, 0x1FA4, 0x2052}, {0x1FA5, 0x1FA5, 0x2053}, + {0x1FA6, 0x1FA6, 0x2054}, {0x1FA7, 0x1FA7, 0x2055}, + {0x1FA8, 0x1FA8, 0x2056}, {0x1FA9, 0x1FA9, 0x2057}, + {0x1FAA, 0x1FAA, 0x2058}, {0x1FAB, 0x1FAB, 0x2059}, + {0x1FAC, 0x1FAC, 0x205A}, {0x1FAD, 0x1FAD, 0x205B}, + {0x1FAE, 0x1FAE, 0x205C}, {0x1FAF, 0x1FAF, 0x205D}, + {0x1FB0, 0x1FB0, 0x205E}, {0x1FB1, 0x1FB1, 0x205F}, + {0x1FB2, 0x1FB2, 0x2060}, {0x1FB3, 0x1FB3, 0x2061}, + {0x1FB4, 0x1FB4, 0x2062}, {0x1FB5, 0x1FB5, 0x2063}, + {0x1FB6, 0x1FB6, 0x2064}, {0x1FB7, 0x1FB7, 0x2065}, + {0x1FB8, 0x1FB8, 0x2066}, {0x1FB9, 0x1FB9, 0x2067}, + {0x1FBA, 0x1FBA, 0x2068}, {0x1FBB, 0x1FBB, 0x2069}, + {0x1FBC, 0x1FBC, 0x206A}, {0x1FBD, 0x1FBD, 0x206B}, + {0x1FBE, 0x1FBE, 0x206C}, {0x1FBF, 0x1FBF, 0x206D}, + {0x1FC0, 0x1FC0, 0x206E}, {0x1FC1, 0x1FC1, 0x206F}, + {0x1FC2, 0x1FC2, 0x2070}, {0x1FC3, 0x1FC3, 0x2071}, + {0x1FC4, 0x1FC4, 0x2072}, {0x1FC5, 0x1FC5, 0x2073}, + {0x1FC6, 0x1FC6, 0x2074}, {0x1FC7, 0x1FC7, 0x2075}, + {0x1FC8, 0x1FC8, 0x2076}, {0x1FC9, 0x1FC9, 0x2077}, + {0x1FCA, 0x1FCA, 0x2078}, {0x1FCB, 0x1FCB, 0x2079}, + {0x1FCC, 0x1FCC, 0x207A}, {0x1FCD, 0x1FCD, 0x207B}, + {0x1FCE, 0x1FCE, 0x207C}, {0x1FCF, 0x1FCF, 0x207D}, + {0x1FD0, 0x1FD0, 0x207E}, {0x1FD1, 0x1FD1, 0x207F}, + {0x1FD2, 0x1FD2, 0x2080}, {0x1FD3, 0x1FD3, 0x2081}, + {0x1FD4, 0x1FD4, 0x2082}, {0x1FD5, 0x1FD5, 0x2083}, + {0x1FD6, 0x1FD6, 0x2084}, {0x1FD7, 0x1FD7, 0x2085}, + {0x1FD8, 0x1FD8, 0x2086}, {0x1FD9, 0x1FD9, 0x2087}, + {0x1FDA, 0x1FDA, 0x2088}, {0x1FDB, 0x1FDB, 0x2089}, + {0x1FDC, 0x1FDC, 0x208A}, {0x1FDD, 0x1FDD, 0x208B}, + {0x1FDE, 0x1FDE, 0x208C}, {0x1FDF, 0x1FDF, 0x208D}, + {0x1FE0, 0x1FE0, 0x208E}, {0x1FE1, 0x1FE1, 0x208F}, + {0x1FE2, 0x1FE2, 0x2090}, {0x1FE3, 0x1FE3, 0x2091}, + {0x1FE4, 0x1FE4, 0x2092}, {0x1FE5, 0x1FE5, 0x2093}, + {0x1FE6, 0x1FE6, 0x2094}, {0x1FE7, 0x1FE7, 0x2095}, + {0x1FE8, 0x1FE8, 0x2096}, {0x1FE9, 0x1FE9, 0x2097}, + {0x1FEA, 0x1FEA, 0x2098}, {0x1FEB, 0x1FEB, 0x2099}, + {0x1FEC, 0x1FEC, 0x209A}, {0x1FED, 0x1FED, 0x209B}, + {0x1FEE, 0x1FEE, 0x209C}, {0x1FEF, 0x1FEF, 0x209D}, + {0x1FF0, 0x1FF0, 0x209E}, {0x1FF1, 0x1FF1, 0x209F}, + {0x1FF2, 0x1FF2, 0x20A0}, {0x1FF3, 0x1FF3, 0x20A1}, + {0x1FF4, 0x1FF4, 0x20A2}, {0x1FF5, 0x1FF5, 0x20A3}, + {0x1FF6, 0x1FF6, 0x20A4}, {0x1FF7, 0x1FF7, 0x20A5}, + {0x1FF8, 0x1FF8, 0x20A6}, {0x1FF9, 0x1FF9, 0x20A7}, + {0x1FFA, 0x1FFA, 0x20A8}, {0x1FFB, 0x1FFB, 0x20A9}, + {0x1FFC, 0x1FFC, 0x20AA}, {0x1FFD, 0x1FFD, 0x20AB}, + {0x1FFE, 0x1FFE, 0x20AD}, {0x1FFF, 0x1FFF, 0x20AE}}; + +static ObUnicaseInfoChar plane20[] = { + {0x2000, 0x2000, 0x20AF}, {0x2001, 0x2001, 0x20B0}, + {0x2002, 0x2002, 0x20B1}, {0x2003, 0x2003, 0x20B2}, + {0x2004, 0x2004, 0x20B3}, {0x2005, 0x2005, 0x20B4}, + {0x2006, 0x2006, 0x20B5}, {0x2007, 0x2007, 0x20B6}, + {0x2008, 0x2008, 0x20B7}, {0x2009, 0x2009, 0x20B8}, + {0x200A, 0x200A, 0x20B9}, {0x200B, 0x200B, 0x20BA}, + {0x200C, 0x200C, 0x20BB}, {0x200D, 0x200D, 0x20BC}, + {0x200E, 0x200E, 0x20BD}, {0x200F, 0x200F, 0x20BE}, + {0x2010, 0x2010, 0x20BF}, {0x2011, 0x2011, 0x20C0}, + {0x2012, 0x2012, 0x20C1}, {0x2013, 0x2013, 0x20C2}, + {0x2014, 0x2014, 0x20C3}, {0x2015, 0x2015, 0x20C4}, + {0x2016, 0x2016, 0x20C5}, {0x2017, 0x2017, 0x20C6}, + {0x2018, 0x2018, 0x20C7}, {0x2019, 0x2019, 0x20C8}, + {0x201A, 0x201A, 0x20C9}, {0x201B, 0x201B, 0x20CA}, + {0x201C, 0x201C, 0x20CB}, {0x201D, 0x201D, 0x20CC}, + {0x201E, 0x201E, 0x20CD}, {0x201F, 0x201F, 0x20CE}, + {0x2020, 0x2020, 0x20CF}, {0x2021, 0x2021, 0x20D0}, + {0x2022, 0x2022, 0x20D1}, {0x2023, 0x2023, 0x20D2}, + {0x2024, 0x2024, 0x20D3}, {0x2025, 0x2025, 0x20D4}, + {0x2026, 0x2026, 0x20D5}, {0x2027, 0x2027, 0x20D6}, + {0x2028, 0x2028, 0x20D7}, {0x2029, 0x2029, 0x20D8}, + {0x202A, 0x202A, 0x20D9}, {0x202B, 0x202B, 0x20DA}, + {0x202C, 0x202C, 0x20DB}, {0x202D, 0x202D, 0x20DC}, + {0x202E, 0x202E, 0x20DD}, {0x202F, 0x202F, 0x20DE}, + {0x2030, 0x2030, 0x20DF}, {0x2031, 0x2031, 0x20E0}, + {0x2032, 0x2032, 0x20E1}, {0x2033, 0x2033, 0x20E2}, + {0x2034, 0x2034, 0x20E3}, {0x2035, 0x2035, 0x20E4}, + {0x2036, 0x2036, 0x20E5}, {0x2037, 0x2037, 0x20E6}, + {0x2038, 0x2038, 0x20E7}, {0x2039, 0x2039, 0x20E8}, + {0x203A, 0x203A, 0x20E9}, {0x203B, 0x203B, 0x20EA}, + {0x203C, 0x203C, 0x20EB}, {0x203D, 0x203D, 0x20EC}, + {0x203E, 0x203E, 0x20ED}, {0x203F, 0x203F, 0x20EE}, + {0x2040, 0x2040, 0x20EF}, {0x2041, 0x2041, 0x20F0}, + {0x2042, 0x2042, 0x20F1}, {0x2043, 0x2043, 0x20F2}, + {0x2044, 0x2044, 0x20F3}, {0x2045, 0x2045, 0x20F4}, + {0x2046, 0x2046, 0x20F5}, {0x2047, 0x2047, 0x20F6}, + {0x2048, 0x2048, 0x20F7}, {0x2049, 0x2049, 0x20F8}, + {0x204A, 0x204A, 0x20F9}, {0x204B, 0x204B, 0x20FA}, + {0x204C, 0x204C, 0x20FB}, {0x204D, 0x204D, 0x20FC}, + {0x204E, 0x204E, 0x20FD}, {0x204F, 0x204F, 0x20FE}, + {0x2050, 0x2050, 0x20FF}, {0x2051, 0x2051, 0x2100}, + {0x2052, 0x2052, 0x2101}, {0x2053, 0x2053, 0x2102}, + {0x2054, 0x2054, 0x2104}, {0x2055, 0x2055, 0x2106}, + {0x2056, 0x2056, 0x2107}, {0x2057, 0x2057, 0x2108}, + {0x2058, 0x2058, 0x210A}, {0x2059, 0x2059, 0x210B}, + {0x205A, 0x205A, 0x210C}, {0x205B, 0x205B, 0x210D}, + {0x205C, 0x205C, 0x210E}, {0x205D, 0x205D, 0x210F}, + {0x205E, 0x205E, 0x2110}, {0x205F, 0x205F, 0x2111}, + {0x2060, 0x2060, 0x2112}, {0x2061, 0x2061, 0x2113}, + {0x2062, 0x2062, 0x2114}, {0x2063, 0x2063, 0x2115}, + {0x2064, 0x2064, 0x2117}, {0x2065, 0x2065, 0x2118}, + {0x2066, 0x2066, 0x2119}, {0x2067, 0x2067, 0x211A}, + {0x2068, 0x2068, 0x211B}, {0x2069, 0x2069, 0x211C}, + {0x206A, 0x206A, 0x211D}, {0x206B, 0x206B, 0x211E}, + {0x206C, 0x206C, 0x211F}, {0x206D, 0x206D, 0x2120}, + {0x206E, 0x206E, 0x2122}, {0x206F, 0x206F, 0x2123}, + {0x2070, 0x2070, 0x2124}, {0x2071, 0x2071, 0x2125}, + {0x2072, 0xA6D8, 0x2126}, {0x2073, 0x2073, 0x2127}, + {0x2074, 0x2074, 0x2128}, {0x2075, 0x2075, 0x2129}, + {0x2076, 0x006B, 0x212A}, {0x2077, 0x00DC, 0x212B}, + {0x2078, 0x2078, 0x212C}, {0x2079, 0x2079, 0x212D}, + {0x207A, 0x207A, 0x212E}, {0x207B, 0x207B, 0x212F}, + {0x207C, 0x207C, 0x2130}, {0x207D, 0x207D, 0x2131}, + {0x207E, 0x209A, 0x2132}, {0x207F, 0x207F, 0x2133}, + {0x2080, 0x2080, 0x2134}, {0x2081, 0x2081, 0x2135}, + {0x2082, 0x2082, 0x2136}, {0x2083, 0x2083, 0x2137}, + {0x2084, 0x2084, 0x2138}, {0x2085, 0x2085, 0x2139}, + {0x2086, 0x2086, 0x213A}, {0x2087, 0x2087, 0x213B}, + {0x2088, 0x2088, 0x213C}, {0x2089, 0x2089, 0x213D}, + {0x208A, 0x208A, 0x213E}, {0x208B, 0x208B, 0x213F}, + {0x208C, 0x208C, 0x2140}, {0x208D, 0x208D, 0x2141}, + {0x208E, 0x208E, 0x2142}, {0x208F, 0x208F, 0x2143}, + {0x2090, 0x2090, 0x2144}, {0x2091, 0x2091, 0x2145}, + {0x2092, 0x2092, 0x2146}, {0x2093, 0x2093, 0x2147}, + {0x2094, 0x2094, 0x2148}, {0x2095, 0x2095, 0x2149}, + {0x2096, 0x2096, 0x214A}, {0x2097, 0x2097, 0x214B}, + {0x2098, 0x2098, 0x214C}, {0x2099, 0x2099, 0x214D}, + {0x207E, 0x209A, 0x2132}, {0x209B, 0x209B, 0x214F}, + {0x209C, 0x209C, 0x2150}, {0x209D, 0x209D, 0x2151}, + {0x209E, 0x209E, 0x2152}, {0x209F, 0x209F, 0x2153}, + {0x20A0, 0x20A0, 0x2154}, {0x20A1, 0x20A1, 0x2155}, + {0x20A2, 0x20A2, 0x2156}, {0x20A3, 0x20A3, 0x2157}, + {0x20A4, 0x20A4, 0x2158}, {0x20A5, 0x20A5, 0x2159}, + {0x20A6, 0x20A6, 0x215A}, {0x20A7, 0x20A7, 0x215B}, + {0x20A8, 0x20A8, 0x215C}, {0x20A9, 0x20A9, 0x215D}, + {0x20AA, 0x20AA, 0x215E}, {0x20AB, 0x20AB, 0x215F}, + {0x20AC, 0x20B2, 0x216C}, {0x20AD, 0x20B3, 0x216D}, + {0x20AE, 0x20B4, 0x216E}, {0x20AF, 0x20B5, 0x216F}, + {0xA2FB, 0x20B0, 0x216A}, {0xA2FC, 0x20B1, 0x216B}, + {0x20AC, 0x20B2, 0x216C}, {0x20AD, 0x20B3, 0x216D}, + {0x20AE, 0x20B4, 0x216E}, {0x20AF, 0x20B5, 0x216F}, + {0x20B6, 0x20B6, 0x2180}, {0x20B7, 0x20B7, 0x2181}, + {0x20B8, 0x20B8, 0x2182}, {0x20B9, 0x20BA, 0x2183}, + {0x20B9, 0x20BA, 0x2183}, {0x20BB, 0x20BB, 0x2185}, + {0x20BC, 0x20BC, 0x2186}, {0x20BD, 0x20BD, 0x2187}, + {0x20BE, 0x20BE, 0x2188}, {0x20BF, 0x20BF, 0x2189}, + {0x20C0, 0x20C0, 0x218A}, {0x20C1, 0x20C1, 0x218B}, + {0x20C2, 0x20C2, 0x218C}, {0x20C3, 0x20C3, 0x218D}, + {0x20C4, 0x20C4, 0x218E}, {0x20C5, 0x20C5, 0x218F}, + {0x20C6, 0x20C6, 0x2194}, {0x20C7, 0x20C7, 0x2195}, + {0x20C8, 0x20C8, 0x219A}, {0x20C9, 0x20C9, 0x219B}, + {0x20CA, 0x20CA, 0x219C}, {0x20CB, 0x20CB, 0x219D}, + {0x20CC, 0x20CC, 0x219E}, {0x20CD, 0x20CD, 0x219F}, + {0x20CE, 0x20CE, 0x21A0}, {0x20CF, 0x20CF, 0x21A1}, + {0x20D0, 0x20D0, 0x21A2}, {0x20D1, 0x20D1, 0x21A3}, + {0x20D2, 0x20D2, 0x21A4}, {0x20D3, 0x20D3, 0x21A5}, + {0x20D4, 0x20D4, 0x21A6}, {0x20D5, 0x20D5, 0x21A7}, + {0x20D6, 0x20D6, 0x21A8}, {0x20D7, 0x20D7, 0x21A9}, + {0x20D8, 0x20D8, 0x21AA}, {0x20D9, 0x20D9, 0x21AB}, + {0x20DA, 0x20DA, 0x21AC}, {0x20DB, 0x20DB, 0x21AD}, + {0x20DC, 0x20DC, 0x21AE}, {0x20DD, 0x20DD, 0x21AF}, + {0x20DE, 0x20DE, 0x21B0}, {0x20DF, 0x20DF, 0x21B1}, + {0x20E0, 0x20E0, 0x21B2}, {0x20E1, 0x20E1, 0x21B3}, + {0x20E2, 0x20E2, 0x21B4}, {0x20E3, 0x20E3, 0x21B5}, + {0x20E4, 0x20E4, 0x21B6}, {0x20E5, 0x20E5, 0x21B7}, + {0x20E6, 0x20E6, 0x21B8}, {0x20E7, 0x20E7, 0x21B9}, + {0x20E8, 0x20E8, 0x21BA}, {0x20E9, 0x20E9, 0x21BB}, + {0x20EA, 0x20EA, 0x21BC}, {0x20EB, 0x20EB, 0x21BD}, + {0x20EC, 0x20EC, 0x21BE}, {0x20ED, 0x20ED, 0x21BF}, + {0x20EE, 0x20EE, 0x21C0}, {0x20EF, 0x20EF, 0x21C1}, + {0x20F0, 0x20F0, 0x21C2}, {0x20F1, 0x20F1, 0x21C3}, + {0x20F2, 0x20F2, 0x21C4}, {0x20F3, 0x20F3, 0x21C5}, + {0x20F4, 0x20F4, 0x21C6}, {0x20F5, 0x20F5, 0x21C7}, + {0x20F6, 0x20F6, 0x21C8}, {0x20F7, 0x20F7, 0x21C9}, + {0x20F8, 0x20F8, 0x21CA}, {0x20F9, 0x20F9, 0x21CB}, + {0x20FA, 0x20FA, 0x21CC}, {0x20FB, 0x20FB, 0x21CD}, + {0x20FC, 0x20FC, 0x21CE}, {0x20FD, 0x20FD, 0x21CF}, + {0x20FE, 0x20FE, 0x21D0}, {0x20FF, 0x20FF, 0x21D1}}; + +static ObUnicaseInfoChar plane23[] = { + {0x2300, 0x2300, 0x23F8}, {0x2301, 0x2301, 0x23F9}, + {0x2302, 0x2302, 0x23FA}, {0x2303, 0x2303, 0x23FB}, + {0x2304, 0x2304, 0x23FC}, {0x2305, 0x2305, 0x23FD}, + {0x2306, 0x2306, 0x23FE}, {0x2307, 0x2307, 0x23FF}, + {0x2308, 0x2308, 0x2400}, {0x2309, 0x2309, 0x2401}, + {0x230A, 0x230A, 0x2402}, {0x230B, 0x230B, 0x2403}, + {0x230C, 0x230C, 0x2404}, {0x230D, 0x230D, 0x2405}, + {0x230E, 0x230E, 0x2406}, {0x230F, 0x230F, 0x2407}, + {0x2310, 0x2310, 0x2408}, {0x2311, 0x2311, 0x2409}, + {0x2312, 0x2312, 0x240A}, {0x2313, 0x2313, 0x240B}, + {0x2314, 0x2314, 0x240C}, {0x2315, 0x2315, 0x240D}, + {0x2316, 0x2316, 0x240E}, {0x2317, 0x2317, 0x240F}, + {0x2318, 0x2318, 0x2410}, {0x2319, 0x2319, 0x2411}, + {0x231A, 0x231A, 0x2412}, {0x231B, 0x231B, 0x2413}, + {0x231C, 0x231C, 0x2414}, {0x231D, 0x231D, 0x2415}, + {0x231E, 0x231E, 0x2416}, {0x231F, 0x231F, 0x2417}, + {0x2320, 0x2320, 0x2418}, {0x2321, 0x2321, 0x2419}, + {0x2322, 0x2322, 0x241A}, {0x2323, 0x2323, 0x241B}, + {0x2324, 0x2324, 0x241C}, {0x2325, 0x2325, 0x241D}, + {0x2326, 0x2326, 0x241E}, {0x2327, 0x2327, 0x241F}, + {0x2328, 0x2328, 0x2420}, {0x2329, 0x2329, 0x2421}, + {0x232A, 0x232A, 0x2422}, {0x232B, 0x232B, 0x2423}, + {0x232C, 0x232C, 0x2424}, {0x232D, 0x232D, 0x2425}, + {0x232E, 0x232E, 0x2426}, {0x232F, 0x232F, 0x2427}, + {0x2330, 0x2330, 0x2428}, {0x2331, 0x2331, 0x2429}, + {0x2332, 0x2332, 0x242A}, {0x2333, 0x2333, 0x242B}, + {0x2334, 0x2334, 0x242C}, {0x2335, 0x2335, 0x242D}, + {0x2336, 0x2336, 0x242E}, {0x2337, 0x2337, 0x242F}, + {0x2338, 0x2338, 0x2430}, {0x2339, 0x2339, 0x2431}, + {0x233A, 0x233A, 0x2432}, {0x233B, 0x233B, 0x2433}, + {0x233C, 0x233C, 0x2434}, {0x233D, 0x233D, 0x2435}, + {0x233E, 0x233E, 0x2436}, {0x233F, 0x233F, 0x2437}, + {0x2340, 0x2340, 0x2438}, {0x2341, 0x2341, 0x2439}, + {0x2342, 0x2342, 0x243A}, {0x2343, 0x2343, 0x243B}, + {0x2344, 0x2344, 0x243C}, {0x2345, 0x2345, 0x243D}, + {0x2346, 0x2346, 0x243E}, {0x2347, 0x2347, 0x243F}, + {0x2348, 0x2348, 0x2440}, {0x2349, 0x2349, 0x2441}, + {0x234A, 0x234A, 0x2442}, {0x234B, 0x234B, 0x2443}, + {0x234C, 0x234C, 0x2444}, {0x234D, 0x234D, 0x2445}, + {0x234E, 0x234E, 0x2446}, {0x234F, 0x234F, 0x2447}, + {0x2350, 0x2350, 0x2448}, {0x2351, 0x2351, 0x2449}, + {0x2352, 0x2352, 0x244A}, {0x2353, 0x2353, 0x244B}, + {0x2354, 0x2354, 0x244C}, {0x2355, 0x2355, 0x244D}, + {0x2356, 0x2356, 0x244E}, {0x2357, 0x2357, 0x244F}, + {0x2358, 0x2358, 0x2450}, {0x2359, 0x2359, 0x2451}, + {0x235A, 0x235A, 0x2452}, {0x235B, 0x235B, 0x2453}, + {0x235C, 0x235C, 0x2454}, {0x235D, 0x235D, 0x2455}, + {0x235E, 0x235E, 0x2456}, {0x235F, 0x235F, 0x2457}, + {0x2360, 0x2360, 0x2458}, {0x2361, 0x2361, 0x2459}, + {0x2362, 0x2362, 0x245A}, {0x2363, 0x2363, 0x245B}, + {0x2364, 0x2364, 0x245C}, {0x2365, 0x2365, 0x245D}, + {0x2366, 0x2366, 0x245E}, {0x2367, 0x2367, 0x245F}, + {0x2368, 0x2368, 0x246A}, {0x2369, 0x2369, 0x246B}, + {0x236A, 0x236A, 0x246C}, {0x236B, 0x236B, 0x246D}, + {0x236C, 0x236C, 0x246E}, {0x236D, 0x236D, 0x246F}, + {0x236E, 0x236E, 0x2470}, {0x236F, 0x236F, 0x2471}, + {0x2370, 0x2370, 0x2472}, {0x2371, 0x2371, 0x2473}, + {0x2372, 0x2372, 0x249C}, {0x2373, 0x2373, 0x249D}, + {0x2374, 0x2374, 0x249E}, {0x2375, 0x2375, 0x249F}, + {0x2376, 0x2376, 0x24A0}, {0x2377, 0x2377, 0x24A1}, + {0x2378, 0x2378, 0x24A2}, {0x2379, 0x2379, 0x24A3}, + {0x237A, 0x237A, 0x24A4}, {0x237B, 0x237B, 0x24A5}, + {0x237C, 0x237C, 0x24A6}, {0x237D, 0x237D, 0x24A7}, + {0x237E, 0x237E, 0x24A8}, {0x237F, 0x237F, 0x24A9}, + {0x2380, 0x2380, 0x24AA}, {0x2381, 0x2381, 0x24AB}, + {0x2382, 0x2382, 0x24AC}, {0x2383, 0x2383, 0x24AD}, + {0x2384, 0x2384, 0x24AE}, {0x2385, 0x2385, 0x24AF}, + {0x2386, 0x2386, 0x24B0}, {0x2387, 0x2387, 0x24B1}, + {0x2388, 0x2388, 0x24B2}, {0x2389, 0x2389, 0x24B3}, + {0x238A, 0x238A, 0x24B4}, {0x238B, 0x238B, 0x24B5}, + {0x238C, 0x23A6, 0x24B6}, {0x238D, 0x23A7, 0x24B7}, + {0x238E, 0x23A8, 0x24B8}, {0x238F, 0x23A9, 0x24B9}, + {0x2390, 0x23AA, 0x24BA}, {0x2391, 0x23AB, 0x24BB}, + {0x2392, 0x23AC, 0x24BC}, {0x2393, 0x23AD, 0x24BD}, + {0x2394, 0x23AE, 0x24BE}, {0x2395, 0x23AF, 0x24BF}, + {0x2396, 0x23B0, 0x24C0}, {0x2397, 0x23B1, 0x24C1}, + {0x2398, 0x23B2, 0x24C2}, {0x2399, 0x23B3, 0x24C3}, + {0x239A, 0x23B4, 0x24C4}, {0x239B, 0x23B5, 0x24C5}, + {0x239C, 0x23B6, 0x24C6}, {0x239D, 0x23B7, 0x24C7}, + {0x239E, 0x23B8, 0x24C8}, {0x239F, 0x23B9, 0x24C9}, + {0x23A0, 0x23BA, 0x24CA}, {0x23A1, 0x23BB, 0x24CB}, + {0x23A2, 0x23BC, 0x24CC}, {0x23A3, 0x23BD, 0x24CD}, + {0x23A4, 0x23BE, 0x24CE}, {0x23A5, 0x23BF, 0x24CF}, + {0x238C, 0x23A6, 0x24B6}, {0x238D, 0x23A7, 0x24B7}, + {0x238E, 0x23A8, 0x24B8}, {0x238F, 0x23A9, 0x24B9}, + {0x2390, 0x23AA, 0x24BA}, {0x2391, 0x23AB, 0x24BB}, + {0x2392, 0x23AC, 0x24BC}, {0x2393, 0x23AD, 0x24BD}, + {0x2394, 0x23AE, 0x24BE}, {0x2395, 0x23AF, 0x24BF}, + {0x2396, 0x23B0, 0x24C0}, {0x2397, 0x23B1, 0x24C1}, + {0x2398, 0x23B2, 0x24C2}, {0x2399, 0x23B3, 0x24C3}, + {0x239A, 0x23B4, 0x24C4}, {0x239B, 0x23B5, 0x24C5}, + {0x239C, 0x23B6, 0x24C6}, {0x239D, 0x23B7, 0x24C7}, + {0x239E, 0x23B8, 0x24C8}, {0x239F, 0x23B9, 0x24C9}, + {0x23A0, 0x23BA, 0x24CA}, {0x23A1, 0x23BB, 0x24CB}, + {0x23A2, 0x23BC, 0x24CC}, {0x23A3, 0x23BD, 0x24CD}, + {0x23A4, 0x23BE, 0x24CE}, {0x23A5, 0x23BF, 0x24CF}, + {0x23C0, 0x23C0, 0x24EA}, {0x23C1, 0x23C1, 0x24EB}, + {0x23C2, 0x23C2, 0x24EC}, {0x23C3, 0x23C3, 0x24ED}, + {0x23C4, 0x23C4, 0x24EE}, {0x23C5, 0x23C5, 0x24EF}, + {0x23C6, 0x23C6, 0x24F0}, {0x23C7, 0x23C7, 0x24F1}, + {0x23C8, 0x23C8, 0x24F2}, {0x23C9, 0x23C9, 0x24F3}, + {0x23CA, 0x23CA, 0x24F4}, {0x23CB, 0x23CB, 0x24F5}, + {0x23CC, 0x23CC, 0x24F6}, {0x23CD, 0x23CD, 0x24F7}, + {0x23CE, 0x23CE, 0x24F8}, {0x23CF, 0x23CF, 0x24F9}, + {0x23D0, 0x23D0, 0x24FA}, {0x23D1, 0x23D1, 0x24FB}, + {0x23D2, 0x23D2, 0x24FC}, {0x23D3, 0x23D3, 0x24FD}, + {0x23D4, 0x23D4, 0x24FE}, {0x23D5, 0x23D5, 0x24FF}, + {0x23D6, 0x23D6, 0x254C}, {0x23D7, 0x23D7, 0x254D}, + {0x23D8, 0x23D8, 0x254E}, {0x23D9, 0x23D9, 0x254F}, + {0x23DA, 0x23DA, 0x2574}, {0x23DB, 0x23DB, 0x2575}, + {0x23DC, 0x23DC, 0x2576}, {0x23DD, 0x23DD, 0x2577}, + {0x23DE, 0x23DE, 0x2578}, {0x23DF, 0x23DF, 0x2579}, + {0x23E0, 0x23E0, 0x257A}, {0x23E1, 0x23E1, 0x257B}, + {0x23E2, 0x23E2, 0x257C}, {0x23E3, 0x23E3, 0x257D}, + {0x23E4, 0x23E4, 0x257E}, {0x23E5, 0x23E5, 0x257F}, + {0x23E6, 0x23E6, 0x2580}, {0x23E7, 0x23E7, 0x2590}, + {0x23E8, 0x23E8, 0x2591}, {0x23E9, 0x23E9, 0x2592}, + {0x23EA, 0x23EA, 0x2596}, {0x23EB, 0x23EB, 0x2597}, + {0x23EC, 0x23EC, 0x2598}, {0x23ED, 0x23ED, 0x2599}, + {0x23EE, 0x23EE, 0x259A}, {0x23EF, 0x23EF, 0x259B}, + {0x23F0, 0x23F0, 0x259C}, {0x23F1, 0x23F1, 0x259D}, + {0x23F2, 0x23F2, 0x259E}, {0x23F3, 0x23F3, 0x259F}, + {0x23F4, 0x23F4, 0x25A2}, {0x23F5, 0x23F5, 0x25A3}, + {0x23F6, 0x23F6, 0x25A4}, {0x23F7, 0x23F7, 0x25A5}, + {0x23F8, 0x23F8, 0x25A6}, {0x23F9, 0x23F9, 0x25A7}, + {0x23FA, 0x23FA, 0x25A8}, {0x23FB, 0x23FB, 0x25A9}, + {0x23FC, 0x23FC, 0x25AA}, {0x23FD, 0x23FD, 0x25AB}, + {0x23FE, 0x23FE, 0x25AC}, {0x23FF, 0x23FF, 0x25AD}}; + +static ObUnicaseInfoChar plane2A[] = { + {0x2A00, 0x2A00, 0x2BC0}, {0x2A01, 0x2A01, 0x2BC1}, + {0x2A02, 0x2A02, 0x2BC2}, {0x2A03, 0x2A03, 0x2BC3}, + {0x2A04, 0x2A04, 0x2BC4}, {0x2A05, 0x2A05, 0x2BC5}, + {0x2A06, 0x2A06, 0x2BC6}, {0x2A07, 0x2A07, 0x2BC7}, + {0x2A08, 0x2A08, 0x2BC8}, {0x2A09, 0x2A09, 0x2BC9}, + {0x2A0A, 0x2A0A, 0x2BCA}, {0x2A0B, 0x2A0B, 0x2BCB}, + {0x2A0C, 0x2A0C, 0x2BCC}, {0x2A0D, 0x2A0D, 0x2BCD}, + {0x2A0E, 0x2A0E, 0x2BCE}, {0x2A0F, 0x2A0F, 0x2BCF}, + {0x2A10, 0x2A10, 0x2BD0}, {0x2A11, 0x2A11, 0x2BD1}, + {0x2A12, 0x2A12, 0x2BD2}, {0x2A13, 0x2A13, 0x2BD3}, + {0x2A14, 0x2A14, 0x2BD4}, {0x2A15, 0x2A15, 0x2BD5}, + {0x2A16, 0x2A16, 0x2BD6}, {0x2A17, 0x2A17, 0x2BD7}, + {0x2A18, 0x2A18, 0x2BD8}, {0x2A19, 0x2A19, 0x2BD9}, + {0x2A1A, 0x2A1A, 0x2BDA}, {0x2A1B, 0x2A1B, 0x2BDB}, + {0x2A1C, 0x2A1C, 0x2BDC}, {0x2A1D, 0x2A1D, 0x2BDD}, + {0x2A1E, 0x2A1E, 0x2BDE}, {0x2A1F, 0x2A1F, 0x2BDF}, + {0x2A20, 0x2A20, 0x2BE0}, {0x2A21, 0x2A21, 0x2BE1}, + {0x2A22, 0x2A22, 0x2BE2}, {0x2A23, 0x2A23, 0x2BE3}, + {0x2A24, 0x2A24, 0x2BE4}, {0x2A25, 0x2A25, 0x2BE5}, + {0x2A26, 0x2A26, 0x2BE6}, {0x2A27, 0x2A27, 0x2BE7}, + {0x2A28, 0x2A28, 0x2BE8}, {0x2A29, 0x2A29, 0x2BE9}, + {0x2A2A, 0x2A2A, 0x2BEA}, {0x2A2B, 0x2A2B, 0x2BEB}, + {0x2A2C, 0x2A2C, 0x2BEC}, {0x2A2D, 0x2A2D, 0x2BED}, + {0x2A2E, 0x2A2E, 0x2BEE}, {0x2A2F, 0x2A2F, 0x2BEF}, + {0x2A30, 0x2A30, 0x2BF0}, {0x2A31, 0x2A31, 0x2BF1}, + {0x2A32, 0x2A32, 0x2BF2}, {0x2A33, 0x2A33, 0x2BF3}, + {0x2A34, 0x2A34, 0x2BF4}, {0x2A35, 0x2A35, 0x2BF5}, + {0x2A36, 0x2A36, 0x2BF6}, {0x2A37, 0x2A37, 0x2BF7}, + {0x2A38, 0x2A38, 0x2BF8}, {0x2A39, 0x2A39, 0x2BF9}, + {0x2A3A, 0x2A3A, 0x2BFA}, {0x2A3B, 0x2A3B, 0x2BFB}, + {0x2A3C, 0x2A3C, 0x2BFC}, {0x2A3D, 0x2A3D, 0x2BFD}, + {0x2A3E, 0x2A3E, 0x2BFE}, {0x2A3F, 0x2A3F, 0x2BFF}, + {0x2A40, 0x2A70, 0x2C00}, {0x2A41, 0x2A71, 0x2C01}, + {0x2A42, 0x2A72, 0x2C02}, {0x2A43, 0x2A73, 0x2C03}, + {0x2A44, 0x2A74, 0x2C04}, {0x2A45, 0x2A75, 0x2C05}, + {0x2A46, 0x2A76, 0x2C06}, {0x2A47, 0x2A77, 0x2C07}, + {0x2A48, 0x2A78, 0x2C08}, {0x2A49, 0x2A79, 0x2C09}, + {0x2A4A, 0x2A7A, 0x2C0A}, {0x2A4B, 0x2A7B, 0x2C0B}, + {0x2A4C, 0x2A7C, 0x2C0C}, {0x2A4D, 0x2A7D, 0x2C0D}, + {0x2A4E, 0x2A7E, 0x2C0E}, {0x2A4F, 0x2A7F, 0x2C0F}, + {0x2A50, 0x2A80, 0x2C10}, {0x2A51, 0x2A81, 0x2C11}, + {0x2A52, 0x2A82, 0x2C12}, {0x2A53, 0x2A83, 0x2C13}, + {0x2A54, 0x2A84, 0x2C14}, {0x2A55, 0x2A85, 0x2C15}, + {0x2A56, 0x2A86, 0x2C16}, {0x2A57, 0x2A87, 0x2C17}, + {0x2A58, 0x2A88, 0x2C18}, {0x2A59, 0x2A89, 0x2C19}, + {0x2A5A, 0x2A8A, 0x2C1A}, {0x2A5B, 0x2A8B, 0x2C1B}, + {0x2A5C, 0x2A8C, 0x2C1C}, {0x2A5D, 0x2A8D, 0x2C1D}, + {0x2A5E, 0x2A8E, 0x2C1E}, {0x2A5F, 0x2A8F, 0x2C1F}, + {0x2A60, 0x2A90, 0x2C20}, {0x2A61, 0x2A91, 0x2C21}, + {0x2A62, 0x2A92, 0x2C22}, {0x2A63, 0x2A93, 0x2C23}, + {0x2A64, 0x2A94, 0x2C24}, {0x2A65, 0x2A95, 0x2C25}, + {0x2A66, 0x2A96, 0x2C26}, {0x2A67, 0x2A97, 0x2C27}, + {0x2A68, 0x2A98, 0x2C28}, {0x2A69, 0x2A99, 0x2C29}, + {0x2A6A, 0x2A9A, 0x2C2A}, {0x2A6B, 0x2A9B, 0x2C2B}, + {0x2A6C, 0x2A9C, 0x2C2C}, {0x2A6D, 0x2A9D, 0x2C2D}, + {0x2A6E, 0x2A9E, 0x2C2E}, {0x2A6F, 0x2A6F, 0x2C2F}, + {0x2A40, 0x2A70, 0x2C00}, {0x2A41, 0x2A71, 0x2C01}, + {0x2A42, 0x2A72, 0x2C02}, {0x2A43, 0x2A73, 0x2C03}, + {0x2A44, 0x2A74, 0x2C04}, {0x2A45, 0x2A75, 0x2C05}, + {0x2A46, 0x2A76, 0x2C06}, {0x2A47, 0x2A77, 0x2C07}, + {0x2A48, 0x2A78, 0x2C08}, {0x2A49, 0x2A79, 0x2C09}, + {0x2A4A, 0x2A7A, 0x2C0A}, {0x2A4B, 0x2A7B, 0x2C0B}, + {0x2A4C, 0x2A7C, 0x2C0C}, {0x2A4D, 0x2A7D, 0x2C0D}, + {0x2A4E, 0x2A7E, 0x2C0E}, {0x2A4F, 0x2A7F, 0x2C0F}, + {0x2A50, 0x2A80, 0x2C10}, {0x2A51, 0x2A81, 0x2C11}, + {0x2A52, 0x2A82, 0x2C12}, {0x2A53, 0x2A83, 0x2C13}, + {0x2A54, 0x2A84, 0x2C14}, {0x2A55, 0x2A85, 0x2C15}, + {0x2A56, 0x2A86, 0x2C16}, {0x2A57, 0x2A87, 0x2C17}, + {0x2A58, 0x2A88, 0x2C18}, {0x2A59, 0x2A89, 0x2C19}, + {0x2A5A, 0x2A8A, 0x2C1A}, {0x2A5B, 0x2A8B, 0x2C1B}, + {0x2A5C, 0x2A8C, 0x2C1C}, {0x2A5D, 0x2A8D, 0x2C1D}, + {0x2A5E, 0x2A8E, 0x2C1E}, {0x2A5F, 0x2A8F, 0x2C1F}, + {0x2A60, 0x2A90, 0x2C20}, {0x2A61, 0x2A91, 0x2C21}, + {0x2A62, 0x2A92, 0x2C22}, {0x2A63, 0x2A93, 0x2C23}, + {0x2A64, 0x2A94, 0x2C24}, {0x2A65, 0x2A95, 0x2C25}, + {0x2A66, 0x2A96, 0x2C26}, {0x2A67, 0x2A97, 0x2C27}, + {0x2A68, 0x2A98, 0x2C28}, {0x2A69, 0x2A99, 0x2C29}, + {0x2A6A, 0x2A9A, 0x2C2A}, {0x2A6B, 0x2A9B, 0x2C2B}, + {0x2A6C, 0x2A9C, 0x2C2C}, {0x2A6D, 0x2A9D, 0x2C2D}, + {0x2A6E, 0x2A9E, 0x2C2E}, {0x2A9F, 0x2A9F, 0x2C5F}, + {0x2AA0, 0x2AA1, 0x2C60}, {0x2AA0, 0x2AA1, 0x2C60}, + {0x2AA2, 0x0244, 0x2C62}, {0x2AA3, 0x1CDF, 0x2C63}, + {0x2AA4, 0x0256, 0x2C64}, {0x0215, 0x2AA5, 0x023A}, + {0x0219, 0x2AA6, 0x023E}, {0x2AA7, 0x2AA8, 0x2C67}, + {0x2AA7, 0x2AA8, 0x2C67}, {0x2AA9, 0x2AAA, 0x2C69}, + {0x2AA9, 0x2AAA, 0x2C69}, {0x2AAB, 0x2AAC, 0x2C6B}, + {0x2AAB, 0x2AAC, 0x2C6B}, {0x2AAD, 0xA8BB, 0x2C6D}, + {0x2AAE, 0x024A, 0x2C6E}, {0x2AAF, 0x022B, 0x2C6F}, + {0x2AB0, 0x022C, 0x2C70}, {0x2AB1, 0x2AB1, 0x2C71}, + {0x2AB2, 0x2AB3, 0x2C72}, {0x2AB2, 0x2AB3, 0x2C72}, + {0x2AB4, 0x2AB4, 0x2C74}, {0x2AB5, 0x2AB6, 0x2C75}, + {0x2AB5, 0x2AB6, 0x2C75}, {0x2AB7, 0x2AB7, 0x2C77}, + {0x2AB8, 0x2AB8, 0x2C78}, {0x2AB9, 0x2AB9, 0x2C79}, + {0x2ABA, 0x2ABA, 0x2C7A}, {0x2ABB, 0x2ABB, 0x2C7B}, + {0x2ABC, 0x2ABC, 0x2C7C}, {0x2ABD, 0x2ABD, 0x2C7D}, + {0x2ABE, 0x021A, 0x2C7E}, {0x2ABF, 0x021B, 0x2C7F}, + {0x2AC0, 0x2AC1, 0x2C80}, {0x2AC0, 0x2AC1, 0x2C80}, + {0x2AC2, 0x2AC3, 0x2C82}, {0x2AC2, 0x2AC3, 0x2C82}, + {0x2AC4, 0x2AC5, 0x2C84}, {0x2AC4, 0x2AC5, 0x2C84}, + {0x2AC6, 0x2AC7, 0x2C86}, {0x2AC6, 0x2AC7, 0x2C86}, + {0x2AC8, 0x2AC9, 0x2C88}, {0x2AC8, 0x2AC9, 0x2C88}, + {0x2ACA, 0x2ACB, 0x2C8A}, {0x2ACA, 0x2ACB, 0x2C8A}, + {0x2ACC, 0x2ACD, 0x2C8C}, {0x2ACC, 0x2ACD, 0x2C8C}, + {0x2ACE, 0x2ACF, 0x2C8E}, {0x2ACE, 0x2ACF, 0x2C8E}, + {0x2AD0, 0x2AD1, 0x2C90}, {0x2AD0, 0x2AD1, 0x2C90}, + {0x2AD2, 0x2AD3, 0x2C92}, {0x2AD2, 0x2AD3, 0x2C92}, + {0x2AD4, 0x2AD5, 0x2C94}, {0x2AD4, 0x2AD5, 0x2C94}, + {0x2AD6, 0x2AD7, 0x2C96}, {0x2AD6, 0x2AD7, 0x2C96}, + {0x2AD8, 0x2AD9, 0x2C98}, {0x2AD8, 0x2AD9, 0x2C98}, + {0x2ADA, 0x2ADB, 0x2C9A}, {0x2ADA, 0x2ADB, 0x2C9A}, + {0x2ADC, 0x2ADD, 0x2C9C}, {0x2ADC, 0x2ADD, 0x2C9C}, + {0x2ADE, 0x2ADF, 0x2C9E}, {0x2ADE, 0x2ADF, 0x2C9E}, + {0x2AE0, 0x2AE1, 0x2CA0}, {0x2AE0, 0x2AE1, 0x2CA0}, + {0x2AE2, 0x2AE3, 0x2CA2}, {0x2AE2, 0x2AE3, 0x2CA2}, + {0x2AE4, 0x2AE5, 0x2CA4}, {0x2AE4, 0x2AE5, 0x2CA4}, + {0x2AE6, 0x2AE7, 0x2CA6}, {0x2AE6, 0x2AE7, 0x2CA6}, + {0x2AE8, 0x2AE9, 0x2CA8}, {0x2AE8, 0x2AE9, 0x2CA8}, + {0x2AEA, 0x2AEB, 0x2CAA}, {0x2AEA, 0x2AEB, 0x2CAA}, + {0x2AEC, 0x2AED, 0x2CAC}, {0x2AEC, 0x2AED, 0x2CAC}, + {0x2AEE, 0x2AEF, 0x2CAE}, {0x2AEE, 0x2AEF, 0x2CAE}, + {0x2AF0, 0x2AF1, 0x2CB0}, {0x2AF0, 0x2AF1, 0x2CB0}, + {0x2AF2, 0x2AF3, 0x2CB2}, {0x2AF2, 0x2AF3, 0x2CB2}, + {0x2AF4, 0x2AF5, 0x2CB4}, {0x2AF4, 0x2AF5, 0x2CB4}, + {0x2AF6, 0x2AF7, 0x2CB6}, {0x2AF6, 0x2AF7, 0x2CB6}, + {0x2AF8, 0x2AF9, 0x2CB8}, {0x2AF8, 0x2AF9, 0x2CB8}, + {0x2AFA, 0x2AFB, 0x2CBA}, {0x2AFA, 0x2AFB, 0x2CBA}, + {0x2AFC, 0x2AFD, 0x2CBC}, {0x2AFC, 0x2AFD, 0x2CBC}, + {0x2AFE, 0x2AFF, 0x2CBE}, {0x2AFE, 0x2AFF, 0x2CBE}}; + +static ObUnicaseInfoChar plane2B[] = { + {0x2B00, 0x2B01, 0x2CC0}, {0x2B00, 0x2B01, 0x2CC0}, + {0x2B02, 0x2B03, 0x2CC2}, {0x2B02, 0x2B03, 0x2CC2}, + {0x2B04, 0x2B05, 0x2CC4}, {0x2B04, 0x2B05, 0x2CC4}, + {0x2B06, 0x2B07, 0x2CC6}, {0x2B06, 0x2B07, 0x2CC6}, + {0x2B08, 0x2B09, 0x2CC8}, {0x2B08, 0x2B09, 0x2CC8}, + {0x2B0A, 0x2B0B, 0x2CCA}, {0x2B0A, 0x2B0B, 0x2CCA}, + {0x2B0C, 0x2B0D, 0x2CCC}, {0x2B0C, 0x2B0D, 0x2CCC}, + {0x2B0E, 0x2B0F, 0x2CCE}, {0x2B0E, 0x2B0F, 0x2CCE}, + {0x2B10, 0x2B11, 0x2CD0}, {0x2B10, 0x2B11, 0x2CD0}, + {0x2B12, 0x2B13, 0x2CD2}, {0x2B12, 0x2B13, 0x2CD2}, + {0x2B14, 0x2B15, 0x2CD4}, {0x2B14, 0x2B15, 0x2CD4}, + {0x2B16, 0x2B17, 0x2CD6}, {0x2B16, 0x2B17, 0x2CD6}, + {0x2B18, 0x2B19, 0x2CD8}, {0x2B18, 0x2B19, 0x2CD8}, + {0x2B1A, 0x2B1B, 0x2CDA}, {0x2B1A, 0x2B1B, 0x2CDA}, + {0x2B1C, 0x2B1D, 0x2CDC}, {0x2B1C, 0x2B1D, 0x2CDC}, + {0x2B1E, 0x2B1F, 0x2CDE}, {0x2B1E, 0x2B1F, 0x2CDE}, + {0x2B20, 0x2B21, 0x2CE0}, {0x2B20, 0x2B21, 0x2CE0}, + {0x2B22, 0x2B23, 0x2CE2}, {0x2B22, 0x2B23, 0x2CE2}, + {0x2B24, 0x2B24, 0x2CE4}, {0x2B25, 0x2B25, 0x2CE5}, + {0x2B26, 0x2B26, 0x2CE6}, {0x2B27, 0x2B27, 0x2CE7}, + {0x2B28, 0x2B28, 0x2CE8}, {0x2B29, 0x2B29, 0x2CE9}, + {0x2B2A, 0x2B2A, 0x2CEA}, {0x2B2B, 0x2B2C, 0x2CEB}, + {0x2B2B, 0x2B2C, 0x2CEB}, {0x2B2D, 0x2B2E, 0x2CED}, + {0x2B2D, 0x2B2E, 0x2CED}, {0x2B2F, 0x2B2F, 0x2CEF}, + {0x2B30, 0x2B30, 0x2CF0}, {0x2B31, 0x2B31, 0x2CF1}, + {0x2B32, 0x2B32, 0x2CF2}, {0x2B33, 0x2B33, 0x2CF3}, + {0x2B34, 0x2B34, 0x2CF4}, {0x2B35, 0x2B35, 0x2CF5}, + {0x2B36, 0x2B36, 0x2CF6}, {0x2B37, 0x2B37, 0x2CF7}, + {0x2B38, 0x2B38, 0x2CF8}, {0x2B39, 0x2B39, 0x2CF9}, + {0x2B3A, 0x2B3A, 0x2CFA}, {0x2B3B, 0x2B3B, 0x2CFB}, + {0x2B3C, 0x2B3C, 0x2CFC}, {0x2B3D, 0x2B3D, 0x2CFD}, + {0x2B3E, 0x2B3E, 0x2CFE}, {0x2B3F, 0x2B3F, 0x2CFF}, + {0x1002, 0x2B40, 0x10A0}, {0x1003, 0x2B41, 0x10A1}, + {0x1004, 0x2B42, 0x10A2}, {0x1005, 0x2B43, 0x10A3}, + {0x1006, 0x2B44, 0x10A4}, {0x1007, 0x2B45, 0x10A5}, + {0x1008, 0x2B46, 0x10A6}, {0x1009, 0x2B47, 0x10A7}, + {0x100A, 0x2B48, 0x10A8}, {0x100B, 0x2B49, 0x10A9}, + {0x100C, 0x2B4A, 0x10AA}, {0x100D, 0x2B4B, 0x10AB}, + {0x100E, 0x2B4C, 0x10AC}, {0x100F, 0x2B4D, 0x10AD}, + {0x1010, 0x2B4E, 0x10AE}, {0x1011, 0x2B4F, 0x10AF}, + {0x1012, 0x2B50, 0x10B0}, {0x1013, 0x2B51, 0x10B1}, + {0x1014, 0x2B52, 0x10B2}, {0x1015, 0x2B53, 0x10B3}, + {0x1016, 0x2B54, 0x10B4}, {0x1017, 0x2B55, 0x10B5}, + {0x1018, 0x2B56, 0x10B6}, {0x1019, 0x2B57, 0x10B7}, + {0x101A, 0x2B58, 0x10B8}, {0x101B, 0x2B59, 0x10B9}, + {0x101C, 0x2B5A, 0x10BA}, {0x101D, 0x2B5B, 0x10BB}, + {0x101E, 0x2B5C, 0x10BC}, {0x101F, 0x2B5D, 0x10BD}, + {0x1020, 0x2B5E, 0x10BE}, {0x1021, 0x2B5F, 0x10BF}, + {0x1022, 0x2B60, 0x10C0}, {0x1023, 0x2B61, 0x10C1}, + {0x1024, 0x2B62, 0x10C2}, {0x1025, 0x2B63, 0x10C3}, + {0x1026, 0x2B64, 0x10C4}, {0x1027, 0x2B65, 0x10C5}, + {0x2B66, 0x2B66, 0x2D26}, {0x2B67, 0x2B67, 0x2D27}, + {0x2B68, 0x2B68, 0x2D28}, {0x2B69, 0x2B69, 0x2D29}, + {0x2B6A, 0x2B6A, 0x2D2A}, {0x2B6B, 0x2B6B, 0x2D2B}, + {0x2B6C, 0x2B6C, 0x2D2C}, {0x2B6D, 0x2B6D, 0x2D2D}, + {0x2B6E, 0x2B6E, 0x2D2E}, {0x2B6F, 0x2B6F, 0x2D2F}, + {0x2B70, 0x2B70, 0x2D30}, {0x2B71, 0x2B71, 0x2D31}, + {0x2B72, 0x2B72, 0x2D32}, {0x2B73, 0x2B73, 0x2D33}, + {0x2B74, 0x2B74, 0x2D34}, {0x2B75, 0x2B75, 0x2D35}, + {0x2B76, 0x2B76, 0x2D36}, {0x2B77, 0x2B77, 0x2D37}, + {0x2B78, 0x2B78, 0x2D38}, {0x2B79, 0x2B79, 0x2D39}, + {0x2B7A, 0x2B7A, 0x2D3A}, {0x2B7B, 0x2B7B, 0x2D3B}, + {0x2B7C, 0x2B7C, 0x2D3C}, {0x2B7D, 0x2B7D, 0x2D3D}, + {0x2B7E, 0x2B7E, 0x2D3E}, {0x2B7F, 0x2B7F, 0x2D3F}, + {0x2B80, 0x2B80, 0x2D40}, {0x2B81, 0x2B81, 0x2D41}, + {0x2B82, 0x2B82, 0x2D42}, {0x2B83, 0x2B83, 0x2D43}, + {0x2B84, 0x2B84, 0x2D44}, {0x2B85, 0x2B85, 0x2D45}, + {0x2B86, 0x2B86, 0x2D46}, {0x2B87, 0x2B87, 0x2D47}, + {0x2B88, 0x2B88, 0x2D48}, {0x2B89, 0x2B89, 0x2D49}, + {0x2B8A, 0x2B8A, 0x2D4A}, {0x2B8B, 0x2B8B, 0x2D4B}, + {0x2B8C, 0x2B8C, 0x2D4C}, {0x2B8D, 0x2B8D, 0x2D4D}, + {0x2B8E, 0x2B8E, 0x2D4E}, {0x2B8F, 0x2B8F, 0x2D4F}, + {0x2B90, 0x2B90, 0x2D50}, {0x2B91, 0x2B91, 0x2D51}, + {0x2B92, 0x2B92, 0x2D52}, {0x2B93, 0x2B93, 0x2D53}, + {0x2B94, 0x2B94, 0x2D54}, {0x2B95, 0x2B95, 0x2D55}, + {0x2B96, 0x2B96, 0x2D56}, {0x2B97, 0x2B97, 0x2D57}, + {0x2B98, 0x2B98, 0x2D58}, {0x2B99, 0x2B99, 0x2D59}, + {0x2B9A, 0x2B9A, 0x2D5A}, {0x2B9B, 0x2B9B, 0x2D5B}, + {0x2B9C, 0x2B9C, 0x2D5C}, {0x2B9D, 0x2B9D, 0x2D5D}, + {0x2B9E, 0x2B9E, 0x2D5E}, {0x2B9F, 0x2B9F, 0x2D5F}, + {0x2BA0, 0x2BA0, 0x2D60}, {0x2BA1, 0x2BA1, 0x2D61}, + {0x2BA2, 0x2BA2, 0x2D62}, {0x2BA3, 0x2BA3, 0x2D63}, + {0x2BA4, 0x2BA4, 0x2D64}, {0x2BA5, 0x2BA5, 0x2D65}, + {0x2BA6, 0x2BA6, 0x2D66}, {0x2BA7, 0x2BA7, 0x2D67}, + {0x2BA8, 0x2BA8, 0x2D68}, {0x2BA9, 0x2BA9, 0x2D69}, + {0x2BAA, 0x2BAA, 0x2D6A}, {0x2BAB, 0x2BAB, 0x2D6B}, + {0x2BAC, 0x2BAC, 0x2D6C}, {0x2BAD, 0x2BAD, 0x2D6D}, + {0x2BAE, 0x2BAE, 0x2D6E}, {0x2BAF, 0x2BAF, 0x2D6F}, + {0x2BB0, 0x2BB0, 0x2D70}, {0x2BB1, 0x2BB1, 0x2D71}, + {0x2BB2, 0x2BB2, 0x2D72}, {0x2BB3, 0x2BB3, 0x2D73}, + {0x2BB4, 0x2BB4, 0x2D74}, {0x2BB5, 0x2BB5, 0x2D75}, + {0x2BB6, 0x2BB6, 0x2D76}, {0x2BB7, 0x2BB7, 0x2D77}, + {0x2BB8, 0x2BB8, 0x2D78}, {0x2BB9, 0x2BB9, 0x2D79}, + {0x2BBA, 0x2BBA, 0x2D7A}, {0x2BBB, 0x2BBB, 0x2D7B}, + {0x2BBC, 0x2BBC, 0x2D7C}, {0x2BBD, 0x2BBD, 0x2D7D}, + {0x2BBE, 0x2BBE, 0x2D7E}, {0x2BBF, 0x2BBF, 0x2D7F}, + {0x2BC0, 0x2BC0, 0x2D80}, {0x2BC1, 0x2BC1, 0x2D81}, + {0x2BC2, 0x2BC2, 0x2D82}, {0x2BC3, 0x2BC3, 0x2D83}, + {0x2BC4, 0x2BC4, 0x2D84}, {0x2BC5, 0x2BC5, 0x2D85}, + {0x2BC6, 0x2BC6, 0x2D86}, {0x2BC7, 0x2BC7, 0x2D87}, + {0x2BC8, 0x2BC8, 0x2D88}, {0x2BC9, 0x2BC9, 0x2D89}, + {0x2BCA, 0x2BCA, 0x2D8A}, {0x2BCB, 0x2BCB, 0x2D8B}, + {0x2BCC, 0x2BCC, 0x2D8C}, {0x2BCD, 0x2BCD, 0x2D8D}, + {0x2BCE, 0x2BCE, 0x2D8E}, {0x2BCF, 0x2BCF, 0x2D8F}, + {0x2BD0, 0x2BD0, 0x2D90}, {0x2BD1, 0x2BD1, 0x2D91}, + {0x2BD2, 0x2BD2, 0x2D92}, {0x2BD3, 0x2BD3, 0x2D93}, + {0x2BD4, 0x2BD4, 0x2D94}, {0x2BD5, 0x2BD5, 0x2D95}, + {0x2BD6, 0x2BD6, 0x2D96}, {0x2BD7, 0x2BD7, 0x2D97}, + {0x2BD8, 0x2BD8, 0x2D98}, {0x2BD9, 0x2BD9, 0x2D99}, + {0x2BDA, 0x2BDA, 0x2D9A}, {0x2BDB, 0x2BDB, 0x2D9B}, + {0x2BDC, 0x2BDC, 0x2D9C}, {0x2BDD, 0x2BDD, 0x2D9D}, + {0x2BDE, 0x2BDE, 0x2D9E}, {0x2BDF, 0x2BDF, 0x2D9F}, + {0x2BE0, 0x2BE0, 0x2DA0}, {0x2BE1, 0x2BE1, 0x2DA1}, + {0x2BE2, 0x2BE2, 0x2DA2}, {0x2BE3, 0x2BE3, 0x2DA3}, + {0x2BE4, 0x2BE4, 0x2DA4}, {0x2BE5, 0x2BE5, 0x2DA5}, + {0x2BE6, 0x2BE6, 0x2DA6}, {0x2BE7, 0x2BE7, 0x2DA7}, + {0x2BE8, 0x2BE8, 0x2DA8}, {0x2BE9, 0x2BE9, 0x2DA9}, + {0x2BEA, 0x2BEA, 0x2DAA}, {0x2BEB, 0x2BEB, 0x2DAB}, + {0x2BEC, 0x2BEC, 0x2DAC}, {0x2BED, 0x2BED, 0x2DAD}, + {0x2BEE, 0x2BEE, 0x2DAE}, {0x2BEF, 0x2BEF, 0x2DAF}, + {0x2BF0, 0x2BF0, 0x2DB0}, {0x2BF1, 0x2BF1, 0x2DB1}, + {0x2BF2, 0x2BF2, 0x2DB2}, {0x2BF3, 0x2BF3, 0x2DB3}, + {0x2BF4, 0x2BF4, 0x2DB4}, {0x2BF5, 0x2BF5, 0x2DB5}, + {0x2BF6, 0x2BF6, 0x2DB6}, {0x2BF7, 0x2BF7, 0x2DB7}, + {0x2BF8, 0x2BF8, 0x2DB8}, {0x2BF9, 0x2BF9, 0x2DB9}, + {0x2BFA, 0x2BFA, 0x2DBA}, {0x2BFB, 0x2BFB, 0x2DBB}, + {0x2BFC, 0x2BFC, 0x2DBC}, {0x2BFD, 0x2BFD, 0x2DBD}, + {0x2BFE, 0x2BFE, 0x2DBE}, {0x2BFF, 0x2BFF, 0x2DBF}}; + +static ObUnicaseInfoChar plane51[] = { + {0x5100, 0x5100, 0xA5C3}, {0x5101, 0x5101, 0xA5C4}, + {0x5102, 0x5102, 0xA5C5}, {0x5103, 0x5103, 0xA5C6}, + {0x5104, 0x5104, 0xA5C7}, {0x5105, 0x5105, 0xA5C8}, + {0x5106, 0x5106, 0xA5C9}, {0x5107, 0x5107, 0xA5CA}, + {0x5108, 0x5108, 0xA5CB}, {0x5109, 0x5109, 0xA5CC}, + {0x510A, 0x510A, 0xA5CD}, {0x510B, 0x510B, 0xA5CE}, + {0x510C, 0x510C, 0xA5CF}, {0x510D, 0x510D, 0xA5D0}, + {0x510E, 0x510E, 0xA5D1}, {0x510F, 0x510F, 0xA5D2}, + {0x5110, 0x5110, 0xA5D3}, {0x5111, 0x5111, 0xA5D4}, + {0x5112, 0x5112, 0xA5D5}, {0x5113, 0x5113, 0xA5D6}, + {0x5114, 0x5114, 0xA5D7}, {0x5115, 0x5115, 0xA5D8}, + {0x5116, 0x5116, 0xA5D9}, {0x5117, 0x5117, 0xA5DA}, + {0x5118, 0x5118, 0xA5DB}, {0x5119, 0x5119, 0xA5DC}, + {0x511A, 0x511A, 0xA5DD}, {0x511B, 0x511B, 0xA5DE}, + {0x511C, 0x511C, 0xA5DF}, {0x511D, 0x511D, 0xA5E0}, + {0x511E, 0x511E, 0xA5E1}, {0x511F, 0x511F, 0xA5E2}, + {0x5120, 0x5120, 0xA5E3}, {0x5121, 0x5121, 0xA5E4}, + {0x5122, 0x5122, 0xA5E5}, {0x5123, 0x5123, 0xA5E6}, + {0x5124, 0x5124, 0xA5E7}, {0x5125, 0x5125, 0xA5E8}, + {0x5126, 0x5126, 0xA5E9}, {0x5127, 0x5127, 0xA5EA}, + {0x5128, 0x5128, 0xA5EB}, {0x5129, 0x5129, 0xA5EC}, + {0x512A, 0x512A, 0xA5ED}, {0x512B, 0x512B, 0xA5EE}, + {0x512C, 0x512C, 0xA5EF}, {0x512D, 0x512D, 0xA5F0}, + {0x512E, 0x512E, 0xA5F1}, {0x512F, 0x512F, 0xA5F2}, + {0x5130, 0x5130, 0xA5F3}, {0x5131, 0x5131, 0xA5F4}, + {0x5132, 0x5132, 0xA5F5}, {0x5133, 0x5133, 0xA5F6}, + {0x5134, 0x5134, 0xA5F7}, {0x5135, 0x5135, 0xA5F8}, + {0x5136, 0x5136, 0xA5F9}, {0x5137, 0x5137, 0xA5FA}, + {0x5138, 0x5138, 0xA5FB}, {0x5139, 0x5139, 0xA5FC}, + {0x513A, 0x513A, 0xA5FD}, {0x513B, 0x513B, 0xA5FE}, + {0x513C, 0x513C, 0xA5FF}, {0x513D, 0x513D, 0xA600}, + {0x513E, 0x513E, 0xA601}, {0x513F, 0x513F, 0xA602}, + {0x5140, 0x5140, 0xA603}, {0x5141, 0x5141, 0xA604}, + {0x5142, 0x5142, 0xA605}, {0x5143, 0x5143, 0xA606}, + {0x5144, 0x5144, 0xA607}, {0x5145, 0x5145, 0xA608}, + {0x5146, 0x5146, 0xA609}, {0x5147, 0x5147, 0xA60A}, + {0x5148, 0x5148, 0xA60B}, {0x5149, 0x5149, 0xA60C}, + {0x514A, 0x514A, 0xA60D}, {0x514B, 0x514B, 0xA60E}, + {0x514C, 0x514C, 0xA60F}, {0x514D, 0x514D, 0xA610}, + {0x514E, 0x514E, 0xA611}, {0x514F, 0x514F, 0xA612}, + {0x5150, 0x5150, 0xA613}, {0x5151, 0x5151, 0xA614}, + {0x5152, 0x5152, 0xA615}, {0x5153, 0x5153, 0xA616}, + {0x5154, 0x5154, 0xA617}, {0x5155, 0x5155, 0xA618}, + {0x5156, 0x5156, 0xA619}, {0x5157, 0x5157, 0xA61A}, + {0x5158, 0x5158, 0xA61B}, {0x5159, 0x5159, 0xA61C}, + {0x515A, 0x515A, 0xA61D}, {0x515B, 0x515B, 0xA61E}, + {0x515C, 0x515C, 0xA61F}, {0x515D, 0x515D, 0xA620}, + {0x515E, 0x515E, 0xA621}, {0x515F, 0x515F, 0xA622}, + {0x5160, 0x5160, 0xA623}, {0x5161, 0x5161, 0xA624}, + {0x5162, 0x5162, 0xA625}, {0x5163, 0x5163, 0xA626}, + {0x5164, 0x5164, 0xA627}, {0x5165, 0x5165, 0xA628}, + {0x5166, 0x5166, 0xA629}, {0x5167, 0x5167, 0xA62A}, + {0x5168, 0x5168, 0xA62B}, {0x5169, 0x5169, 0xA62C}, + {0x516A, 0x516A, 0xA62D}, {0x516B, 0x516B, 0xA62E}, + {0x516C, 0x516C, 0xA62F}, {0x516D, 0x516D, 0xA630}, + {0x516E, 0x516E, 0xA631}, {0x516F, 0x516F, 0xA632}, + {0x5170, 0x5170, 0xA633}, {0x5171, 0x5171, 0xA634}, + {0x5172, 0x5172, 0xA635}, {0x5173, 0x5173, 0xA636}, + {0x5174, 0x5174, 0xA637}, {0x5175, 0x5175, 0xA638}, + {0x5176, 0x5176, 0xA639}, {0x5177, 0x5177, 0xA63A}, + {0x5178, 0x5178, 0xA63B}, {0x5179, 0x5179, 0xA63C}, + {0x517A, 0x517A, 0xA63D}, {0x517B, 0x517B, 0xA63E}, + {0x517C, 0x517C, 0xA63F}, {0x517D, 0x517E, 0xA640}, + {0x517D, 0x517E, 0xA640}, {0x517F, 0x5180, 0xA642}, + {0x517F, 0x5180, 0xA642}, {0x5181, 0x5182, 0xA644}, + {0x5181, 0x5182, 0xA644}, {0x5183, 0x5184, 0xA646}, + {0x5183, 0x5184, 0xA646}, {0x5185, 0x5186, 0xA648}, + {0x5185, 0x5186, 0xA648}, {0x5187, 0x5188, 0xA64A}, + {0x5187, 0x5188, 0xA64A}, {0x5189, 0x518A, 0xA64C}, + {0x5189, 0x518A, 0xA64C}, {0x518B, 0x518C, 0xA64E}, + {0x518B, 0x518C, 0xA64E}, {0x518D, 0x518E, 0xA650}, + {0x518D, 0x518E, 0xA650}, {0x518F, 0x5190, 0xA652}, + {0x518F, 0x5190, 0xA652}, {0x5191, 0x5192, 0xA654}, + {0x5191, 0x5192, 0xA654}, {0x5193, 0x5194, 0xA656}, + {0x5193, 0x5194, 0xA656}, {0x5195, 0x5196, 0xA658}, + {0x5195, 0x5196, 0xA658}, {0x5197, 0x5198, 0xA65A}, + {0x5197, 0x5198, 0xA65A}, {0x5199, 0x519A, 0xA65C}, + {0x5199, 0x519A, 0xA65C}, {0x519B, 0x519C, 0xA65E}, + {0x519B, 0x519C, 0xA65E}, {0x519D, 0x519D, 0xA660}, + {0x519E, 0x519E, 0xA661}, {0x519F, 0x51A0, 0xA662}, + {0x519F, 0x51A0, 0xA662}, {0x51A1, 0x51A2, 0xA664}, + {0x51A1, 0x51A2, 0xA664}, {0x51A3, 0x51A4, 0xA666}, + {0x51A3, 0x51A4, 0xA666}, {0x51A5, 0x51A6, 0xA668}, + {0x51A5, 0x51A6, 0xA668}, {0x51A7, 0x51A8, 0xA66A}, + {0x51A7, 0x51A8, 0xA66A}, {0x51A9, 0x51AA, 0xA66C}, + {0x51A9, 0x51AA, 0xA66C}, {0x51AB, 0x51AB, 0xA66E}, + {0x51AC, 0x51AC, 0xA66F}, {0x51AD, 0x51AD, 0xA670}, + {0x51AE, 0x51AE, 0xA671}, {0x51AF, 0x51AF, 0xA672}, + {0x51B0, 0x51B0, 0xA673}, {0x51B1, 0x51B1, 0xA674}, + {0x51B2, 0x51B2, 0xA675}, {0x51B3, 0x51B3, 0xA676}, + {0x51B4, 0x51B4, 0xA677}, {0x51B5, 0x51B5, 0xA678}, + {0x51B6, 0x51B6, 0xA679}, {0x51B7, 0x51B7, 0xA67A}, + {0x51B8, 0x51B8, 0xA67B}, {0x51B9, 0x51B9, 0xA67C}, + {0x51BA, 0x51BA, 0xA67D}, {0x51BB, 0x51BB, 0xA67E}, + {0x51BC, 0x51BC, 0xA67F}, {0x51BD, 0x51BE, 0xA680}, + {0x51BD, 0x51BE, 0xA680}, {0x51BF, 0x51C0, 0xA682}, + {0x51BF, 0x51C0, 0xA682}, {0x51C1, 0x51C2, 0xA684}, + {0x51C1, 0x51C2, 0xA684}, {0x51C3, 0x51C4, 0xA686}, + {0x51C3, 0x51C4, 0xA686}, {0x51C5, 0x51C6, 0xA688}, + {0x51C5, 0x51C6, 0xA688}, {0x51C7, 0x51C8, 0xA68A}, + {0x51C7, 0x51C8, 0xA68A}, {0x51C9, 0x51CA, 0xA68C}, + {0x51C9, 0x51CA, 0xA68C}, {0x51CB, 0x51CC, 0xA68E}, + {0x51CB, 0x51CC, 0xA68E}, {0x51CD, 0x51CE, 0xA690}, + {0x51CD, 0x51CE, 0xA690}, {0x51CF, 0x51D0, 0xA692}, + {0x51CF, 0x51D0, 0xA692}, {0x51D1, 0x51D2, 0xA694}, + {0x51D1, 0x51D2, 0xA694}, {0x51D3, 0x51D4, 0xA696}, + {0x51D3, 0x51D4, 0xA696}, {0x51D5, 0x51D5, 0xA698}, + {0x51D6, 0x51D6, 0xA699}, {0x51D7, 0x51D7, 0xA69A}, + {0x51D8, 0x51D8, 0xA69B}, {0x51D9, 0x51D9, 0xA69C}, + {0x51DA, 0x51DA, 0xA69D}, {0x51DB, 0x51DB, 0xA69E}, + {0x51DC, 0x51DC, 0xA69F}, {0x51DD, 0x51DD, 0xA6A0}, + {0x51DE, 0x51DE, 0xA6A1}, {0x51DF, 0x51DF, 0xA6A2}, + {0x51E0, 0x51E0, 0xA6A3}, {0x51E1, 0x51E1, 0xA6A4}, + {0x51E2, 0x51E2, 0xA6A5}, {0x51E3, 0x51E3, 0xA6A6}, + {0x51E4, 0x51E4, 0xA6A7}, {0x51E5, 0x51E5, 0xA6A8}, + {0x51E6, 0x51E6, 0xA6A9}, {0x51E7, 0x51E7, 0xA6AA}, + {0x51E8, 0x51E8, 0xA6AB}, {0x51E9, 0x51E9, 0xA6AC}, + {0x51EA, 0x51EA, 0xA6AD}, {0x51EB, 0x51EB, 0xA6AE}, + {0x51EC, 0x51EC, 0xA6AF}, {0x51ED, 0x51ED, 0xA6B0}, + {0x51EE, 0x51EE, 0xA6B1}, {0x51EF, 0x51EF, 0xA6B2}, + {0x51F0, 0x51F0, 0xA6B3}, {0x51F1, 0x51F1, 0xA6B4}, + {0x51F2, 0x51F2, 0xA6B5}, {0x51F3, 0x51F3, 0xA6B6}, + {0x51F4, 0x51F4, 0xA6B7}, {0x51F5, 0x51F5, 0xA6B8}, + {0x51F6, 0x51F6, 0xA6B9}, {0x51F7, 0x51F7, 0xA6BA}, + {0x51F8, 0x51F8, 0xA6BB}, {0x51F9, 0x51F9, 0xA6BC}, + {0x51FA, 0x51FA, 0xA6BD}, {0x51FB, 0x51FB, 0xA6BE}, + {0x51FC, 0x51FC, 0xA6BF}, {0x51FD, 0x51FD, 0xA6C0}, + {0x51FE, 0x51FE, 0xA6C1}, {0x51FF, 0x51FF, 0xA6C2}}; + +static ObUnicaseInfoChar plane52[] = { + {0x5200, 0x5200, 0xA6C3}, {0x5201, 0x5201, 0xA6C4}, + {0x5202, 0x5202, 0xA6C5}, {0x5203, 0x5203, 0xA6C6}, + {0x5204, 0x5204, 0xA6C7}, {0x5205, 0x5205, 0xA6C8}, + {0x5206, 0x5206, 0xA6C9}, {0x5207, 0x5207, 0xA6CA}, + {0x5208, 0x5208, 0xA6CB}, {0x5209, 0x5209, 0xA6CC}, + {0x520A, 0x520A, 0xA6CD}, {0x520B, 0x520B, 0xA6CE}, + {0x520C, 0x520C, 0xA6CF}, {0x520D, 0x520D, 0xA6D0}, + {0x520E, 0x520E, 0xA6D1}, {0x520F, 0x520F, 0xA6D2}, + {0x5210, 0x5210, 0xA6D3}, {0x5211, 0x5211, 0xA6D4}, + {0x5212, 0x5212, 0xA6D5}, {0x5213, 0x5213, 0xA6D6}, + {0x5214, 0x5214, 0xA6D7}, {0x5215, 0x5215, 0xA6D8}, + {0x5216, 0x5216, 0xA6D9}, {0x5217, 0x5217, 0xA6DA}, + {0x5218, 0x5218, 0xA6DB}, {0x5219, 0x5219, 0xA6DC}, + {0x521A, 0x521A, 0xA6DD}, {0x521B, 0x521B, 0xA6DE}, + {0x521C, 0x521C, 0xA6DF}, {0x521D, 0x521D, 0xA6E0}, + {0x521E, 0x521E, 0xA6E1}, {0x521F, 0x521F, 0xA6E2}, + {0x5220, 0x5220, 0xA6E3}, {0x5221, 0x5221, 0xA6E4}, + {0x5222, 0x5222, 0xA6E5}, {0x5223, 0x5223, 0xA6E6}, + {0x5224, 0x5224, 0xA6E7}, {0x5225, 0x5225, 0xA6E8}, + {0x5226, 0x5226, 0xA6E9}, {0x5227, 0x5227, 0xA6EA}, + {0x5228, 0x5228, 0xA6EB}, {0x5229, 0x5229, 0xA6EC}, + {0x522A, 0x522A, 0xA6ED}, {0x522B, 0x522B, 0xA6EE}, + {0x522C, 0x522C, 0xA6EF}, {0x522D, 0x522D, 0xA6F0}, + {0x522E, 0x522E, 0xA6F1}, {0x522F, 0x522F, 0xA6F2}, + {0x5230, 0x5230, 0xA6F3}, {0x5231, 0x5231, 0xA6F4}, + {0x5232, 0x5232, 0xA6F5}, {0x5233, 0x5233, 0xA6F6}, + {0x5234, 0x5234, 0xA6F7}, {0x5235, 0x5235, 0xA6F8}, + {0x5236, 0x5236, 0xA6F9}, {0x5237, 0x5237, 0xA6FA}, + {0x5238, 0x5238, 0xA6FB}, {0x5239, 0x5239, 0xA6FC}, + {0x523A, 0x523A, 0xA6FD}, {0x523B, 0x523B, 0xA6FE}, + {0x523C, 0x523C, 0xA6FF}, {0x523D, 0x523D, 0xA700}, + {0x523E, 0x523E, 0xA701}, {0x523F, 0x523F, 0xA702}, + {0x5240, 0x5240, 0xA703}, {0x5241, 0x5241, 0xA704}, + {0x5242, 0x5242, 0xA705}, {0x5243, 0x5243, 0xA706}, + {0x5244, 0x5244, 0xA707}, {0x5245, 0x5245, 0xA708}, + {0x5246, 0x5246, 0xA709}, {0x5247, 0x5247, 0xA70A}, + {0x5248, 0x5248, 0xA70B}, {0x5249, 0x5249, 0xA70C}, + {0x524A, 0x524A, 0xA70D}, {0x524B, 0x524B, 0xA70E}, + {0x524C, 0x524C, 0xA70F}, {0x524D, 0x524D, 0xA710}, + {0x524E, 0x524E, 0xA711}, {0x524F, 0x524F, 0xA712}, + {0x5250, 0x5250, 0xA713}, {0x5251, 0x5251, 0xA714}, + {0x5252, 0x5252, 0xA715}, {0x5253, 0x5253, 0xA716}, + {0x5254, 0x5254, 0xA717}, {0x5255, 0x5255, 0xA718}, + {0x5256, 0x5256, 0xA719}, {0x5257, 0x5257, 0xA71A}, + {0x5258, 0x5258, 0xA71B}, {0x5259, 0x5259, 0xA71C}, + {0x525A, 0x525A, 0xA71D}, {0x525B, 0x525B, 0xA71E}, + {0x525C, 0x525C, 0xA71F}, {0x525D, 0x525D, 0xA720}, + {0x525E, 0x525E, 0xA721}, {0x525F, 0x5260, 0xA722}, + {0x525F, 0x5260, 0xA722}, {0x5261, 0x5262, 0xA724}, + {0x5261, 0x5262, 0xA724}, {0x5263, 0x5264, 0xA726}, + {0x5263, 0x5264, 0xA726}, {0x5265, 0x5266, 0xA728}, + {0x5265, 0x5266, 0xA728}, {0x5267, 0x5268, 0xA72A}, + {0x5267, 0x5268, 0xA72A}, {0x5269, 0x526A, 0xA72C}, + {0x5269, 0x526A, 0xA72C}, {0x526B, 0x526C, 0xA72E}, + {0x526B, 0x526C, 0xA72E}, {0x526D, 0x526D, 0xA730}, + {0x526E, 0x526E, 0xA731}, {0x526F, 0x5270, 0xA732}, + {0x526F, 0x5270, 0xA732}, {0x5271, 0x5272, 0xA734}, + {0x5271, 0x5272, 0xA734}, {0x5273, 0x5274, 0xA736}, + {0x5273, 0x5274, 0xA736}, {0x5275, 0x5276, 0xA738}, + {0x5275, 0x5276, 0xA738}, {0x5277, 0x5278, 0xA73A}, + {0x5277, 0x5278, 0xA73A}, {0x5279, 0x527A, 0xA73C}, + {0x5279, 0x527A, 0xA73C}, {0x527B, 0x527C, 0xA73E}, + {0x527B, 0x527C, 0xA73E}, {0x527D, 0x527E, 0xA740}, + {0x527D, 0x527E, 0xA740}, {0x527F, 0x5280, 0xA742}, + {0x527F, 0x5280, 0xA742}, {0x5281, 0x5282, 0xA744}, + {0x5281, 0x5282, 0xA744}, {0x5283, 0x5284, 0xA746}, + {0x5283, 0x5284, 0xA746}, {0x5285, 0x5286, 0xA748}, + {0x5285, 0x5286, 0xA748}, {0x5287, 0x5288, 0xA74A}, + {0x5287, 0x5288, 0xA74A}, {0x5289, 0x528A, 0xA74C}, + {0x5289, 0x528A, 0xA74C}, {0x528B, 0x528C, 0xA74E}, + {0x528B, 0x528C, 0xA74E}, {0x528D, 0x528E, 0xA750}, + {0x528D, 0x528E, 0xA750}, {0x528F, 0x5290, 0xA752}, + {0x528F, 0x5290, 0xA752}, {0x5291, 0x5292, 0xA754}, + {0x5291, 0x5292, 0xA754}, {0x5293, 0x5294, 0xA756}, + {0x5293, 0x5294, 0xA756}, {0x5295, 0x5296, 0xA758}, + {0x5295, 0x5296, 0xA758}, {0x5297, 0x5298, 0xA75A}, + {0x5297, 0x5298, 0xA75A}, {0x5299, 0x529A, 0xA75C}, + {0x5299, 0x529A, 0xA75C}, {0x529B, 0x529C, 0xA75E}, + {0x529B, 0x529C, 0xA75E}, {0x529D, 0x529E, 0xA760}, + {0x529D, 0x529E, 0xA760}, {0x529F, 0x52A0, 0xA762}, + {0x529F, 0x52A0, 0xA762}, {0x52A1, 0x52A2, 0xA764}, + {0x52A1, 0x52A2, 0xA764}, {0x52A3, 0x52A4, 0xA766}, + {0x52A3, 0x52A4, 0xA766}, {0x52A5, 0x52A6, 0xA768}, + {0x52A5, 0x52A6, 0xA768}, {0x52A7, 0x52A8, 0xA76A}, + {0x52A7, 0x52A8, 0xA76A}, {0x52A9, 0x52AA, 0xA76C}, + {0x52A9, 0x52AA, 0xA76C}, {0x52AB, 0x52AC, 0xA76E}, + {0x52AB, 0x52AC, 0xA76E}, {0x52AD, 0x52AD, 0xA770}, + {0x52AE, 0x52AE, 0xA771}, {0x52AF, 0x52AF, 0xA772}, + {0x52B0, 0x52B0, 0xA773}, {0x52B1, 0x52B1, 0xA774}, + {0x52B2, 0x52B2, 0xA775}, {0x52B3, 0x52B3, 0xA776}, + {0x52B4, 0x52B4, 0xA777}, {0x52B5, 0x52B5, 0xA778}, + {0x52B6, 0x52B7, 0xA779}, {0x52B6, 0x52B7, 0xA779}, + {0x52B8, 0x52B9, 0xA77B}, {0x52B8, 0x52B9, 0xA77B}, + {0x52BA, 0x1CDB, 0xA77D}, {0x52BB, 0x52BC, 0xA77E}, + {0x52BB, 0x52BC, 0xA77E}, {0x52BD, 0x52BE, 0xA780}, + {0x52BD, 0x52BE, 0xA780}, {0x52BF, 0x52C0, 0xA782}, + {0x52BF, 0x52C0, 0xA782}, {0x52C1, 0x52C2, 0xA784}, + {0x52C1, 0x52C2, 0xA784}, {0x52C3, 0x52C4, 0xA786}, + {0x52C3, 0x52C4, 0xA786}, {0x52C5, 0x52C5, 0xA788}, + {0x52C6, 0x52C6, 0xA789}, {0x52C7, 0x52C7, 0xA78A}, + {0x52C8, 0x52C9, 0xA78B}, {0x52C8, 0x52C9, 0xA78B}, + {0x52CA, 0x52CA, 0xA78D}, {0x52CB, 0x52CB, 0xA78E}, + {0x52CC, 0x52CC, 0xA78F}, {0x52CD, 0x52CD, 0xA790}, + {0x52CE, 0x52CE, 0xA791}, {0x52CF, 0x52CF, 0xA792}, + {0x52D0, 0x52D0, 0xA793}, {0x52D1, 0x52D1, 0xA794}, + {0x52D2, 0x52D2, 0xA795}, {0x52D3, 0x52D3, 0xA796}, + {0x52D4, 0x52D4, 0xA797}, {0x52D5, 0x52D5, 0xA798}, + {0x52D6, 0x52D6, 0xA799}, {0x52D7, 0x52D7, 0xA79A}, + {0x52D8, 0x52D8, 0xA79B}, {0x52D9, 0x52D9, 0xA79C}, + {0x52DA, 0x52DA, 0xA79D}, {0x52DB, 0x52DB, 0xA79E}, + {0x52DC, 0x52DC, 0xA79F}, {0x52DD, 0x52DD, 0xA7A0}, + {0x52DE, 0x52DE, 0xA7A1}, {0x52DF, 0x52DF, 0xA7A2}, + {0x52E0, 0x52E0, 0xA7A3}, {0x52E1, 0x52E1, 0xA7A4}, + {0x52E2, 0x52E2, 0xA7A5}, {0x52E3, 0x52E3, 0xA7A6}, + {0x52E4, 0x52E4, 0xA7A7}, {0x52E5, 0x52E5, 0xA7A8}, + {0x52E6, 0x52E6, 0xA7A9}, {0x52E7, 0x52E7, 0xA7AA}, + {0x52E8, 0x52E8, 0xA7AB}, {0x52E9, 0x52E9, 0xA7AC}, + {0x52EA, 0x52EA, 0xA7AD}, {0x52EB, 0x52EB, 0xA7AE}, + {0x52EC, 0x52EC, 0xA7AF}, {0x52ED, 0x52ED, 0xA7B0}, + {0x52EE, 0x52EE, 0xA7B1}, {0x52EF, 0x52EF, 0xA7B2}, + {0x52F0, 0x52F0, 0xA7B3}, {0x52F1, 0x52F1, 0xA7B4}, + {0x52F2, 0x52F2, 0xA7B5}, {0x52F3, 0x52F3, 0xA7B6}, + {0x52F4, 0x52F4, 0xA7B7}, {0x52F5, 0x52F5, 0xA7B8}, + {0x52F6, 0x52F6, 0xA7B9}, {0x52F7, 0x52F7, 0xA7BA}, + {0x52F8, 0x52F8, 0xA7BB}, {0x52F9, 0x52F9, 0xA7BC}, + {0x52FA, 0x52FA, 0xA7BD}, {0x52FB, 0x52FB, 0xA7BE}, + {0x52FC, 0x52FC, 0xA7BF}, {0x52FD, 0x52FD, 0xA7C0}, + {0x52FE, 0x52FE, 0xA7C1}, {0x52FF, 0x52FF, 0xA7C2}}; + +static ObUnicaseInfoChar planeA2[] = { + {0xA200, 0xA200, 0x003F}, {0xA201, 0xA201, 0x003F}, + {0xA202, 0xA202, 0x003F}, {0xA203, 0xA203, 0x003F}, + {0xA204, 0xA204, 0x003F}, {0xA205, 0xA205, 0x003F}, + {0xA206, 0xA206, 0x003F}, {0xA207, 0xA207, 0x003F}, + {0xA208, 0xA208, 0x003F}, {0xA209, 0xA209, 0x003F}, + {0xA20A, 0xA20A, 0x003F}, {0xA20B, 0xA20B, 0x003F}, + {0xA20C, 0xA20C, 0x003F}, {0xA20D, 0xA20D, 0x003F}, + {0xA20E, 0xA20E, 0x003F}, {0xA20F, 0xA20F, 0x003F}, + {0xA210, 0xA210, 0x003F}, {0xA211, 0xA211, 0x003F}, + {0xA212, 0xA212, 0x003F}, {0xA213, 0xA213, 0x003F}, + {0xA214, 0xA214, 0x003F}, {0xA215, 0xA215, 0x003F}, + {0xA216, 0xA216, 0x003F}, {0xA217, 0xA217, 0x003F}, + {0xA218, 0xA218, 0x003F}, {0xA219, 0xA219, 0x003F}, + {0xA21A, 0xA21A, 0x003F}, {0xA21B, 0xA21B, 0x003F}, + {0xA21C, 0xA21C, 0x003F}, {0xA21D, 0xA21D, 0x003F}, + {0xA21E, 0xA21E, 0x003F}, {0xA21F, 0xA21F, 0x003F}, + {0xA220, 0xA220, 0x003F}, {0xA221, 0xA221, 0x003F}, + {0xA222, 0xA222, 0x003F}, {0xA223, 0xA223, 0x003F}, + {0xA224, 0xA224, 0x003F}, {0xA225, 0xA225, 0x003F}, + {0xA226, 0xA226, 0x003F}, {0xA227, 0xA227, 0x003F}, + {0xA228, 0xA228, 0x003F}, {0xA229, 0xA229, 0x003F}, + {0xA22A, 0xA22A, 0x003F}, {0xA22B, 0xA22B, 0x003F}, + {0xA22C, 0xA22C, 0x003F}, {0xA22D, 0xA22D, 0x003F}, + {0xA22E, 0xA22E, 0x003F}, {0xA22F, 0xA22F, 0x003F}, + {0xA230, 0xA230, 0x003F}, {0xA231, 0xA231, 0x003F}, + {0xA232, 0xA232, 0x003F}, {0xA233, 0xA233, 0x003F}, + {0xA234, 0xA234, 0x003F}, {0xA235, 0xA235, 0x003F}, + {0xA236, 0xA236, 0x003F}, {0xA237, 0xA237, 0x003F}, + {0xA238, 0xA238, 0x003F}, {0xA239, 0xA239, 0x003F}, + {0xA23A, 0xA23A, 0x003F}, {0xA23B, 0xA23B, 0x003F}, + {0xA23C, 0xA23C, 0x003F}, {0xA23D, 0xA23D, 0x003F}, + {0xA23E, 0xA23E, 0x003F}, {0xA23F, 0xA23F, 0x003F}, + {0xA240, 0xA240, 0xE526}, {0xA241, 0xA241, 0xE527}, + {0xA242, 0xA242, 0xE528}, {0xA243, 0xA243, 0xE529}, + {0xA244, 0xA244, 0xE52A}, {0xA245, 0xA245, 0xE52B}, + {0xA246, 0xA246, 0xE52C}, {0xA247, 0xA247, 0xE52D}, + {0xA248, 0xA248, 0xE52E}, {0xA249, 0xA249, 0xE52F}, + {0xA24A, 0xA24A, 0xE530}, {0xA24B, 0xA24B, 0xE531}, + {0xA24C, 0xA24C, 0xE532}, {0xA24D, 0xA24D, 0xE533}, + {0xA24E, 0xA24E, 0xE534}, {0xA24F, 0xA24F, 0xE535}, + {0xA250, 0xA250, 0xE536}, {0xA251, 0xA251, 0xE537}, + {0xA252, 0xA252, 0xE538}, {0xA253, 0xA253, 0xE539}, + {0xA254, 0xA254, 0xE53A}, {0xA255, 0xA255, 0xE53B}, + {0xA256, 0xA256, 0xE53C}, {0xA257, 0xA257, 0xE53D}, + {0xA258, 0xA258, 0xE53E}, {0xA259, 0xA259, 0xE53F}, + {0xA25A, 0xA25A, 0xE540}, {0xA25B, 0xA25B, 0xE541}, + {0xA25C, 0xA25C, 0xE542}, {0xA25D, 0xA25D, 0xE543}, + {0xA25E, 0xA25E, 0xE544}, {0xA25F, 0xA25F, 0xE545}, + {0xA260, 0xA260, 0xE546}, {0xA261, 0xA261, 0xE547}, + {0xA262, 0xA262, 0xE548}, {0xA263, 0xA263, 0xE549}, + {0xA264, 0xA264, 0xE54A}, {0xA265, 0xA265, 0xE54B}, + {0xA266, 0xA266, 0xE54C}, {0xA267, 0xA267, 0xE54D}, + {0xA268, 0xA268, 0xE54E}, {0xA269, 0xA269, 0xE54F}, + {0xA26A, 0xA26A, 0xE550}, {0xA26B, 0xA26B, 0xE551}, + {0xA26C, 0xA26C, 0xE552}, {0xA26D, 0xA26D, 0xE553}, + {0xA26E, 0xA26E, 0xE554}, {0xA26F, 0xA26F, 0xE555}, + {0xA270, 0xA270, 0xE556}, {0xA271, 0xA271, 0xE557}, + {0xA272, 0xA272, 0xE558}, {0xA273, 0xA273, 0xE559}, + {0xA274, 0xA274, 0xE55A}, {0xA275, 0xA275, 0xE55B}, + {0xA276, 0xA276, 0xE55C}, {0xA277, 0xA277, 0xE55D}, + {0xA278, 0xA278, 0xE55E}, {0xA279, 0xA279, 0xE55F}, + {0xA27A, 0xA27A, 0xE560}, {0xA27B, 0xA27B, 0xE561}, + {0xA27C, 0xA27C, 0xE562}, {0xA27D, 0xA27D, 0xE563}, + {0xA27E, 0xA27E, 0xE564}, {0xA27F, 0xA27F, 0x003F}, + {0xA280, 0xA280, 0xE565}, {0xA281, 0xA281, 0xE566}, + {0xA282, 0xA282, 0xE567}, {0xA283, 0xA283, 0xE568}, + {0xA284, 0xA284, 0xE569}, {0xA285, 0xA285, 0xE56A}, + {0xA286, 0xA286, 0xE56B}, {0xA287, 0xA287, 0xE56C}, + {0xA288, 0xA288, 0xE56D}, {0xA289, 0xA289, 0xE56E}, + {0xA28A, 0xA28A, 0xE56F}, {0xA28B, 0xA28B, 0xE570}, + {0xA28C, 0xA28C, 0xE571}, {0xA28D, 0xA28D, 0xE572}, + {0xA28E, 0xA28E, 0xE573}, {0xA28F, 0xA28F, 0xE574}, + {0xA290, 0xA290, 0xE575}, {0xA291, 0xA291, 0xE576}, + {0xA292, 0xA292, 0xE577}, {0xA293, 0xA293, 0xE578}, + {0xA294, 0xA294, 0xE579}, {0xA295, 0xA295, 0xE57A}, + {0xA296, 0xA296, 0xE57B}, {0xA297, 0xA297, 0xE57C}, + {0xA298, 0xA298, 0xE57D}, {0xA299, 0xA299, 0xE57E}, + {0xA29A, 0xA29A, 0xE57F}, {0xA29B, 0xA29B, 0xE580}, + {0xA29C, 0xA29C, 0xE581}, {0xA29D, 0xA29D, 0xE582}, + {0xA29E, 0xA29E, 0xE583}, {0xA29F, 0xA29F, 0xE584}, + {0xA2A0, 0xA2A0, 0xE585}, {0xA2F1, 0xA2A1, 0x2160}, + {0xA2F2, 0xA2A2, 0x2161}, {0xA2F3, 0xA2A3, 0x2162}, + {0xA2F4, 0xA2A4, 0x2163}, {0xA2F5, 0xA2A5, 0x2164}, + {0xA2F6, 0xA2A6, 0x2165}, {0xA2F7, 0xA2A7, 0x2166}, + {0xA2F8, 0xA2A8, 0x2167}, {0xA2F9, 0xA2A9, 0x2168}, + {0xA2FA, 0xA2AA, 0x2169}, {0xA2AB, 0xA2AB, 0xE766}, + {0xA2AC, 0xA2AC, 0xE767}, {0xA2AD, 0xA2AD, 0xE768}, + {0xA2AE, 0xA2AE, 0xE769}, {0xA2AF, 0xA2AF, 0xE76A}, + {0xA2B0, 0xA2B0, 0xE76B}, {0xA2B1, 0xA2B1, 0x2488}, + {0xA2B2, 0xA2B2, 0x2489}, {0xA2B3, 0xA2B3, 0x248A}, + {0xA2B4, 0xA2B4, 0x248B}, {0xA2B5, 0xA2B5, 0x248C}, + {0xA2B6, 0xA2B6, 0x248D}, {0xA2B7, 0xA2B7, 0x248E}, + {0xA2B8, 0xA2B8, 0x248F}, {0xA2B9, 0xA2B9, 0x2490}, + {0xA2BA, 0xA2BA, 0x2491}, {0xA2BB, 0xA2BB, 0x2492}, + {0xA2BC, 0xA2BC, 0x2493}, {0xA2BD, 0xA2BD, 0x2494}, + {0xA2BE, 0xA2BE, 0x2495}, {0xA2BF, 0xA2BF, 0x2496}, + {0xA2C0, 0xA2C0, 0x2497}, {0xA2C1, 0xA2C1, 0x2498}, + {0xA2C2, 0xA2C2, 0x2499}, {0xA2C3, 0xA2C3, 0x249A}, + {0xA2C4, 0xA2C4, 0x249B}, {0xA2C5, 0xA2C5, 0x2474}, + {0xA2C6, 0xA2C6, 0x2475}, {0xA2C7, 0xA2C7, 0x2476}, + {0xA2C8, 0xA2C8, 0x2477}, {0xA2C9, 0xA2C9, 0x2478}, + {0xA2CA, 0xA2CA, 0x2479}, {0xA2CB, 0xA2CB, 0x247A}, + {0xA2CC, 0xA2CC, 0x247B}, {0xA2CD, 0xA2CD, 0x247C}, + {0xA2CE, 0xA2CE, 0x247D}, {0xA2CF, 0xA2CF, 0x247E}, + {0xA2D0, 0xA2D0, 0x247F}, {0xA2D1, 0xA2D1, 0x2480}, + {0xA2D2, 0xA2D2, 0x2481}, {0xA2D3, 0xA2D3, 0x2482}, + {0xA2D4, 0xA2D4, 0x2483}, {0xA2D5, 0xA2D5, 0x2484}, + {0xA2D6, 0xA2D6, 0x2485}, {0xA2D7, 0xA2D7, 0x2486}, + {0xA2D8, 0xA2D8, 0x2487}, {0xA2D9, 0xA2D9, 0x2460}, + {0xA2DA, 0xA2DA, 0x2461}, {0xA2DB, 0xA2DB, 0x2462}, + {0xA2DC, 0xA2DC, 0x2463}, {0xA2DD, 0xA2DD, 0x2464}, + {0xA2DE, 0xA2DE, 0x2465}, {0xA2DF, 0xA2DF, 0x2466}, + {0xA2E0, 0xA2E0, 0x2467}, {0xA2E1, 0xA2E1, 0x2468}, + {0xA2E2, 0xA2E2, 0x2469}, {0xA2E3, 0xA2E3, 0x20AC}, + {0xA2E4, 0xA2E4, 0xE76D}, {0xA2E5, 0xA2E5, 0x3220}, + {0xA2E6, 0xA2E6, 0x3221}, {0xA2E7, 0xA2E7, 0x3222}, + {0xA2E8, 0xA2E8, 0x3223}, {0xA2E9, 0xA2E9, 0x3224}, + {0xA2EA, 0xA2EA, 0x3225}, {0xA2EB, 0xA2EB, 0x3226}, + {0xA2EC, 0xA2EC, 0x3227}, {0xA2ED, 0xA2ED, 0x3228}, + {0xA2EE, 0xA2EE, 0x3229}, {0xA2EF, 0xA2EF, 0xE76E}, + {0xA2F0, 0xA2F0, 0xE76F}, {0xA2F1, 0xA2A1, 0x2160}, + {0xA2F2, 0xA2A2, 0x2161}, {0xA2F3, 0xA2A3, 0x2162}, + {0xA2F4, 0xA2A4, 0x2163}, {0xA2F5, 0xA2A5, 0x2164}, + {0xA2F6, 0xA2A6, 0x2165}, {0xA2F7, 0xA2A7, 0x2166}, + {0xA2F8, 0xA2A8, 0x2167}, {0xA2F9, 0xA2A9, 0x2168}, + {0xA2FA, 0xA2AA, 0x2169}, {0xA2FB, 0x20B0, 0x216A}, + {0xA2FC, 0x20B1, 0x216B}, {0xA2FD, 0xA2FD, 0xE770}, + {0xA2FE, 0xA2FE, 0xE771}, {0xA2FF, 0xA2FF, 0x003F}}; + +static ObUnicaseInfoChar planeA3[] = { + {0xA300, 0xA300, 0x003F}, {0xA301, 0xA301, 0x003F}, + {0xA302, 0xA302, 0x003F}, {0xA303, 0xA303, 0x003F}, + {0xA304, 0xA304, 0x003F}, {0xA305, 0xA305, 0x003F}, + {0xA306, 0xA306, 0x003F}, {0xA307, 0xA307, 0x003F}, + {0xA308, 0xA308, 0x003F}, {0xA309, 0xA309, 0x003F}, + {0xA30A, 0xA30A, 0x003F}, {0xA30B, 0xA30B, 0x003F}, + {0xA30C, 0xA30C, 0x003F}, {0xA30D, 0xA30D, 0x003F}, + {0xA30E, 0xA30E, 0x003F}, {0xA30F, 0xA30F, 0x003F}, + {0xA310, 0xA310, 0x003F}, {0xA311, 0xA311, 0x003F}, + {0xA312, 0xA312, 0x003F}, {0xA313, 0xA313, 0x003F}, + {0xA314, 0xA314, 0x003F}, {0xA315, 0xA315, 0x003F}, + {0xA316, 0xA316, 0x003F}, {0xA317, 0xA317, 0x003F}, + {0xA318, 0xA318, 0x003F}, {0xA319, 0xA319, 0x003F}, + {0xA31A, 0xA31A, 0x003F}, {0xA31B, 0xA31B, 0x003F}, + {0xA31C, 0xA31C, 0x003F}, {0xA31D, 0xA31D, 0x003F}, + {0xA31E, 0xA31E, 0x003F}, {0xA31F, 0xA31F, 0x003F}, + {0xA320, 0xA320, 0x003F}, {0xA321, 0xA321, 0x003F}, + {0xA322, 0xA322, 0x003F}, {0xA323, 0xA323, 0x003F}, + {0xA324, 0xA324, 0x003F}, {0xA325, 0xA325, 0x003F}, + {0xA326, 0xA326, 0x003F}, {0xA327, 0xA327, 0x003F}, + {0xA328, 0xA328, 0x003F}, {0xA329, 0xA329, 0x003F}, + {0xA32A, 0xA32A, 0x003F}, {0xA32B, 0xA32B, 0x003F}, + {0xA32C, 0xA32C, 0x003F}, {0xA32D, 0xA32D, 0x003F}, + {0xA32E, 0xA32E, 0x003F}, {0xA32F, 0xA32F, 0x003F}, + {0xA330, 0xA330, 0x003F}, {0xA331, 0xA331, 0x003F}, + {0xA332, 0xA332, 0x003F}, {0xA333, 0xA333, 0x003F}, + {0xA334, 0xA334, 0x003F}, {0xA335, 0xA335, 0x003F}, + {0xA336, 0xA336, 0x003F}, {0xA337, 0xA337, 0x003F}, + {0xA338, 0xA338, 0x003F}, {0xA339, 0xA339, 0x003F}, + {0xA33A, 0xA33A, 0x003F}, {0xA33B, 0xA33B, 0x003F}, + {0xA33C, 0xA33C, 0x003F}, {0xA33D, 0xA33D, 0x003F}, + {0xA33E, 0xA33E, 0x003F}, {0xA33F, 0xA33F, 0x003F}, + {0xA340, 0xA340, 0xE586}, {0xA341, 0xA341, 0xE587}, + {0xA342, 0xA342, 0xE588}, {0xA343, 0xA343, 0xE589}, + {0xA344, 0xA344, 0xE58A}, {0xA345, 0xA345, 0xE58B}, + {0xA346, 0xA346, 0xE58C}, {0xA347, 0xA347, 0xE58D}, + {0xA348, 0xA348, 0xE58E}, {0xA349, 0xA349, 0xE58F}, + {0xA34A, 0xA34A, 0xE590}, {0xA34B, 0xA34B, 0xE591}, + {0xA34C, 0xA34C, 0xE592}, {0xA34D, 0xA34D, 0xE593}, + {0xA34E, 0xA34E, 0xE594}, {0xA34F, 0xA34F, 0xE595}, + {0xA350, 0xA350, 0xE596}, {0xA351, 0xA351, 0xE597}, + {0xA352, 0xA352, 0xE598}, {0xA353, 0xA353, 0xE599}, + {0xA354, 0xA354, 0xE59A}, {0xA355, 0xA355, 0xE59B}, + {0xA356, 0xA356, 0xE59C}, {0xA357, 0xA357, 0xE59D}, + {0xA358, 0xA358, 0xE59E}, {0xA359, 0xA359, 0xE59F}, + {0xA35A, 0xA35A, 0xE5A0}, {0xA35B, 0xA35B, 0xE5A1}, + {0xA35C, 0xA35C, 0xE5A2}, {0xA35D, 0xA35D, 0xE5A3}, + {0xA35E, 0xA35E, 0xE5A4}, {0xA35F, 0xA35F, 0xE5A5}, + {0xA360, 0xA360, 0xE5A6}, {0xA361, 0xA361, 0xE5A7}, + {0xA362, 0xA362, 0xE5A8}, {0xA363, 0xA363, 0xE5A9}, + {0xA364, 0xA364, 0xE5AA}, {0xA365, 0xA365, 0xE5AB}, + {0xA366, 0xA366, 0xE5AC}, {0xA367, 0xA367, 0xE5AD}, + {0xA368, 0xA368, 0xE5AE}, {0xA369, 0xA369, 0xE5AF}, + {0xA36A, 0xA36A, 0xE5B0}, {0xA36B, 0xA36B, 0xE5B1}, + {0xA36C, 0xA36C, 0xE5B2}, {0xA36D, 0xA36D, 0xE5B3}, + {0xA36E, 0xA36E, 0xE5B4}, {0xA36F, 0xA36F, 0xE5B5}, + {0xA370, 0xA370, 0xE5B6}, {0xA371, 0xA371, 0xE5B7}, + {0xA372, 0xA372, 0xE5B8}, {0xA373, 0xA373, 0xE5B9}, + {0xA374, 0xA374, 0xE5BA}, {0xA375, 0xA375, 0xE5BB}, + {0xA376, 0xA376, 0xE5BC}, {0xA377, 0xA377, 0xE5BD}, + {0xA378, 0xA378, 0xE5BE}, {0xA379, 0xA379, 0xE5BF}, + {0xA37A, 0xA37A, 0xE5C0}, {0xA37B, 0xA37B, 0xE5C1}, + {0xA37C, 0xA37C, 0xE5C2}, {0xA37D, 0xA37D, 0xE5C3}, + {0xA37E, 0xA37E, 0xE5C4}, {0xA37F, 0xA37F, 0x003F}, + {0xA380, 0xA380, 0xE5C5}, {0xA381, 0xA381, 0xE5C6}, + {0xA382, 0xA382, 0xE5C7}, {0xA383, 0xA383, 0xE5C8}, + {0xA384, 0xA384, 0xE5C9}, {0xA385, 0xA385, 0xE5CA}, + {0xA386, 0xA386, 0xE5CB}, {0xA387, 0xA387, 0xE5CC}, + {0xA388, 0xA388, 0xE5CD}, {0xA389, 0xA389, 0xE5CE}, + {0xA38A, 0xA38A, 0xE5CF}, {0xA38B, 0xA38B, 0xE5D0}, + {0xA38C, 0xA38C, 0xE5D1}, {0xA38D, 0xA38D, 0xE5D2}, + {0xA38E, 0xA38E, 0xE5D3}, {0xA38F, 0xA38F, 0xE5D4}, + {0xA390, 0xA390, 0xE5D5}, {0xA391, 0xA391, 0xE5D6}, + {0xA392, 0xA392, 0xE5D7}, {0xA393, 0xA393, 0xE5D8}, + {0xA394, 0xA394, 0xE5D9}, {0xA395, 0xA395, 0xE5DA}, + {0xA396, 0xA396, 0xE5DB}, {0xA397, 0xA397, 0xE5DC}, + {0xA398, 0xA398, 0xE5DD}, {0xA399, 0xA399, 0xE5DE}, + {0xA39A, 0xA39A, 0xE5DF}, {0xA39B, 0xA39B, 0xE5E0}, + {0xA39C, 0xA39C, 0xE5E1}, {0xA39D, 0xA39D, 0xE5E2}, + {0xA39E, 0xA39E, 0xE5E3}, {0xA39F, 0xA39F, 0xE5E4}, + {0xA3A0, 0xA3A0, 0xE5E5}, {0xA3A1, 0xA3A1, 0xFF01}, + {0xA3A2, 0xA3A2, 0xFF02}, {0xA3A3, 0xA3A3, 0xFF03}, + {0xA3A4, 0xA3A4, 0xFFE5}, {0xA3A5, 0xA3A5, 0xFF05}, + {0xA3A6, 0xA3A6, 0xFF06}, {0xA3A7, 0xA3A7, 0xFF07}, + {0xA3A8, 0xA3A8, 0xFF08}, {0xA3A9, 0xA3A9, 0xFF09}, + {0xA3AA, 0xA3AA, 0xFF0A}, {0xA3AB, 0xA3AB, 0xFF0B}, + {0xA3AC, 0xA3AC, 0xFF0C}, {0xA3AD, 0xA3AD, 0xFF0D}, + {0xA3AE, 0xA3AE, 0xFF0E}, {0xA3AF, 0xA3AF, 0xFF0F}, + {0xA3B0, 0xA3B0, 0xFF10}, {0xA3B1, 0xA3B1, 0xFF11}, + {0xA3B2, 0xA3B2, 0xFF12}, {0xA3B3, 0xA3B3, 0xFF13}, + {0xA3B4, 0xA3B4, 0xFF14}, {0xA3B5, 0xA3B5, 0xFF15}, + {0xA3B6, 0xA3B6, 0xFF16}, {0xA3B7, 0xA3B7, 0xFF17}, + {0xA3B8, 0xA3B8, 0xFF18}, {0xA3B9, 0xA3B9, 0xFF19}, + {0xA3BA, 0xA3BA, 0xFF1A}, {0xA3BB, 0xA3BB, 0xFF1B}, + {0xA3BC, 0xA3BC, 0xFF1C}, {0xA3BD, 0xA3BD, 0xFF1D}, + {0xA3BE, 0xA3BE, 0xFF1E}, {0xA3BF, 0xA3BF, 0xFF1F}, + {0xA3C0, 0xA3C0, 0xFF20}, {0xA3C1, 0xA3E1, 0xFF21}, + {0xA3C2, 0xA3E2, 0xFF22}, {0xA3C3, 0xA3E3, 0xFF23}, + {0xA3C4, 0xA3E4, 0xFF24}, {0xA3C5, 0xA3E5, 0xFF25}, + {0xA3C6, 0xA3E6, 0xFF26}, {0xA3C7, 0xA3E7, 0xFF27}, + {0xA3C8, 0xA3E8, 0xFF28}, {0xA3C9, 0xA3E9, 0xFF29}, + {0xA3CA, 0xA3EA, 0xFF2A}, {0xA3CB, 0xA3EB, 0xFF2B}, + {0xA3CC, 0xA3EC, 0xFF2C}, {0xA3CD, 0xA3ED, 0xFF2D}, + {0xA3CE, 0xA3EE, 0xFF2E}, {0xA3CF, 0xA3EF, 0xFF2F}, + {0xA3D0, 0xA3F0, 0xFF30}, {0xA3D1, 0xA3F1, 0xFF31}, + {0xA3D2, 0xA3F2, 0xFF32}, {0xA3D3, 0xA3F3, 0xFF33}, + {0xA3D4, 0xA3F4, 0xFF34}, {0xA3D5, 0xA3F5, 0xFF35}, + {0xA3D6, 0xA3F6, 0xFF36}, {0xA3D7, 0xA3F7, 0xFF37}, + {0xA3D8, 0xA3F8, 0xFF38}, {0xA3D9, 0xA3F9, 0xFF39}, + {0xA3DA, 0xA3FA, 0xFF3A}, {0xA3DB, 0xA3DB, 0xFF3B}, + {0xA3DC, 0xA3DC, 0xFF3C}, {0xA3DD, 0xA3DD, 0xFF3D}, + {0xA3DE, 0xA3DE, 0xFF3E}, {0xA3DF, 0xA3DF, 0xFF3F}, + {0xA3E0, 0xA3E0, 0xFF40}, {0xA3C1, 0xA3E1, 0xFF21}, + {0xA3C2, 0xA3E2, 0xFF22}, {0xA3C3, 0xA3E3, 0xFF23}, + {0xA3C4, 0xA3E4, 0xFF24}, {0xA3C5, 0xA3E5, 0xFF25}, + {0xA3C6, 0xA3E6, 0xFF26}, {0xA3C7, 0xA3E7, 0xFF27}, + {0xA3C8, 0xA3E8, 0xFF28}, {0xA3C9, 0xA3E9, 0xFF29}, + {0xA3CA, 0xA3EA, 0xFF2A}, {0xA3CB, 0xA3EB, 0xFF2B}, + {0xA3CC, 0xA3EC, 0xFF2C}, {0xA3CD, 0xA3ED, 0xFF2D}, + {0xA3CE, 0xA3EE, 0xFF2E}, {0xA3CF, 0xA3EF, 0xFF2F}, + {0xA3D0, 0xA3F0, 0xFF30}, {0xA3D1, 0xA3F1, 0xFF31}, + {0xA3D2, 0xA3F2, 0xFF32}, {0xA3D3, 0xA3F3, 0xFF33}, + {0xA3D4, 0xA3F4, 0xFF34}, {0xA3D5, 0xA3F5, 0xFF35}, + {0xA3D6, 0xA3F6, 0xFF36}, {0xA3D7, 0xA3F7, 0xFF37}, + {0xA3D8, 0xA3F8, 0xFF38}, {0xA3D9, 0xA3F9, 0xFF39}, + {0xA3DA, 0xA3FA, 0xFF3A}, {0xA3FB, 0xA3FB, 0xFF5B}, + {0xA3FC, 0xA3FC, 0xFF5C}, {0xA3FD, 0xA3FD, 0xFF5D}, + {0xA3FE, 0xA3FE, 0xFFE3}, {0xA3FF, 0xA3FF, 0x003F}}; + +static ObUnicaseInfoChar planeA6[] = { + {0xA600, 0xA600, 0x003F}, {0xA601, 0xA601, 0x003F}, + {0xA602, 0xA602, 0x003F}, {0xA603, 0xA603, 0x003F}, + {0xA604, 0xA604, 0x003F}, {0xA605, 0xA605, 0x003F}, + {0xA606, 0xA606, 0x003F}, {0xA607, 0xA607, 0x003F}, + {0xA608, 0xA608, 0x003F}, {0xA609, 0xA609, 0x003F}, + {0xA60A, 0xA60A, 0x003F}, {0xA60B, 0xA60B, 0x003F}, + {0xA60C, 0xA60C, 0x003F}, {0xA60D, 0xA60D, 0x003F}, + {0xA60E, 0xA60E, 0x003F}, {0xA60F, 0xA60F, 0x003F}, + {0xA610, 0xA610, 0x003F}, {0xA611, 0xA611, 0x003F}, + {0xA612, 0xA612, 0x003F}, {0xA613, 0xA613, 0x003F}, + {0xA614, 0xA614, 0x003F}, {0xA615, 0xA615, 0x003F}, + {0xA616, 0xA616, 0x003F}, {0xA617, 0xA617, 0x003F}, + {0xA618, 0xA618, 0x003F}, {0xA619, 0xA619, 0x003F}, + {0xA61A, 0xA61A, 0x003F}, {0xA61B, 0xA61B, 0x003F}, + {0xA61C, 0xA61C, 0x003F}, {0xA61D, 0xA61D, 0x003F}, + {0xA61E, 0xA61E, 0x003F}, {0xA61F, 0xA61F, 0x003F}, + {0xA620, 0xA620, 0x003F}, {0xA621, 0xA621, 0x003F}, + {0xA622, 0xA622, 0x003F}, {0xA623, 0xA623, 0x003F}, + {0xA624, 0xA624, 0x003F}, {0xA625, 0xA625, 0x003F}, + {0xA626, 0xA626, 0x003F}, {0xA627, 0xA627, 0x003F}, + {0xA628, 0xA628, 0x003F}, {0xA629, 0xA629, 0x003F}, + {0xA62A, 0xA62A, 0x003F}, {0xA62B, 0xA62B, 0x003F}, + {0xA62C, 0xA62C, 0x003F}, {0xA62D, 0xA62D, 0x003F}, + {0xA62E, 0xA62E, 0x003F}, {0xA62F, 0xA62F, 0x003F}, + {0xA630, 0xA630, 0x003F}, {0xA631, 0xA631, 0x003F}, + {0xA632, 0xA632, 0x003F}, {0xA633, 0xA633, 0x003F}, + {0xA634, 0xA634, 0x003F}, {0xA635, 0xA635, 0x003F}, + {0xA636, 0xA636, 0x003F}, {0xA637, 0xA637, 0x003F}, + {0xA638, 0xA638, 0x003F}, {0xA639, 0xA639, 0x003F}, + {0xA63A, 0xA63A, 0x003F}, {0xA63B, 0xA63B, 0x003F}, + {0xA63C, 0xA63C, 0x003F}, {0xA63D, 0xA63D, 0x003F}, + {0xA63E, 0xA63E, 0x003F}, {0xA63F, 0xA63F, 0x003F}, + {0xA640, 0xA640, 0xE6A6}, {0xA641, 0xA641, 0xE6A7}, + {0xA642, 0xA642, 0xE6A8}, {0xA643, 0xA643, 0xE6A9}, + {0xA644, 0xA644, 0xE6AA}, {0xA645, 0xA645, 0xE6AB}, + {0xA646, 0xA646, 0xE6AC}, {0xA647, 0xA647, 0xE6AD}, + {0xA648, 0xA648, 0xE6AE}, {0xA649, 0xA649, 0xE6AF}, + {0xA64A, 0xA64A, 0xE6B0}, {0xA64B, 0xA64B, 0xE6B1}, + {0xA64C, 0xA64C, 0xE6B2}, {0xA64D, 0xA64D, 0xE6B3}, + {0xA64E, 0xA64E, 0xE6B4}, {0xA64F, 0xA64F, 0xE6B5}, + {0xA650, 0xA650, 0xE6B6}, {0xA651, 0xA651, 0xE6B7}, + {0xA652, 0xA652, 0xE6B8}, {0xA653, 0xA653, 0xE6B9}, + {0xA654, 0xA654, 0xE6BA}, {0xA655, 0xA655, 0xE6BB}, + {0xA656, 0xA656, 0xE6BC}, {0xA657, 0xA657, 0xE6BD}, + {0xA658, 0xA658, 0xE6BE}, {0xA659, 0xA659, 0xE6BF}, + {0xA65A, 0xA65A, 0xE6C0}, {0xA65B, 0xA65B, 0xE6C1}, + {0xA65C, 0xA65C, 0xE6C2}, {0xA65D, 0xA65D, 0xE6C3}, + {0xA65E, 0xA65E, 0xE6C4}, {0xA65F, 0xA65F, 0xE6C5}, + {0xA660, 0xA660, 0xE6C6}, {0xA661, 0xA661, 0xE6C7}, + {0xA662, 0xA662, 0xE6C8}, {0xA663, 0xA663, 0xE6C9}, + {0xA664, 0xA664, 0xE6CA}, {0xA665, 0xA665, 0xE6CB}, + {0xA666, 0xA666, 0xE6CC}, {0xA667, 0xA667, 0xE6CD}, + {0xA668, 0xA668, 0xE6CE}, {0xA669, 0xA669, 0xE6CF}, + {0xA66A, 0xA66A, 0xE6D0}, {0xA66B, 0xA66B, 0xE6D1}, + {0xA66C, 0xA66C, 0xE6D2}, {0xA66D, 0xA66D, 0xE6D3}, + {0xA66E, 0xA66E, 0xE6D4}, {0xA66F, 0xA66F, 0xE6D5}, + {0xA670, 0xA670, 0xE6D6}, {0xA671, 0xA671, 0xE6D7}, + {0xA672, 0xA672, 0xE6D8}, {0xA673, 0xA673, 0xE6D9}, + {0xA674, 0xA674, 0xE6DA}, {0xA675, 0xA675, 0xE6DB}, + {0xA676, 0xA676, 0xE6DC}, {0xA677, 0xA677, 0xE6DD}, + {0xA678, 0xA678, 0xE6DE}, {0xA679, 0xA679, 0xE6DF}, + {0xA67A, 0xA67A, 0xE6E0}, {0xA67B, 0xA67B, 0xE6E1}, + {0xA67C, 0xA67C, 0xE6E2}, {0xA67D, 0xA67D, 0xE6E3}, + {0xA67E, 0xA67E, 0xE6E4}, {0xA67F, 0xA67F, 0x003F}, + {0xA680, 0xA680, 0xE6E5}, {0xA681, 0xA681, 0xE6E6}, + {0xA682, 0xA682, 0xE6E7}, {0xA683, 0xA683, 0xE6E8}, + {0xA684, 0xA684, 0xE6E9}, {0xA685, 0xA685, 0xE6EA}, + {0xA686, 0xA686, 0xE6EB}, {0xA687, 0xA687, 0xE6EC}, + {0xA688, 0xA688, 0xE6ED}, {0xA689, 0xA689, 0xE6EE}, + {0xA68A, 0xA68A, 0xE6EF}, {0xA68B, 0xA68B, 0xE6F0}, + {0xA68C, 0xA68C, 0xE6F1}, {0xA68D, 0xA68D, 0xE6F2}, + {0xA68E, 0xA68E, 0xE6F3}, {0xA68F, 0xA68F, 0xE6F4}, + {0xA690, 0xA690, 0xE6F5}, {0xA691, 0xA691, 0xE6F6}, + {0xA692, 0xA692, 0xE6F7}, {0xA693, 0xA693, 0xE6F8}, + {0xA694, 0xA694, 0xE6F9}, {0xA695, 0xA695, 0xE6FA}, + {0xA696, 0xA696, 0xE6FB}, {0xA697, 0xA697, 0xE6FC}, + {0xA698, 0xA698, 0xE6FD}, {0xA699, 0xA699, 0xE6FE}, + {0xA69A, 0xA69A, 0xE6FF}, {0xA69B, 0xA69B, 0xE700}, + {0xA69C, 0xA69C, 0xE701}, {0xA69D, 0xA69D, 0xE702}, + {0xA69E, 0xA69E, 0xE703}, {0xA69F, 0xA69F, 0xE704}, + {0xA6A0, 0xA6A0, 0xE705}, {0xA6A1, 0xA6C1, 0x0391}, + {0xA6A2, 0xA6C2, 0x0392}, {0xA6A3, 0xA6C3, 0x0393}, + {0xA6A4, 0xA6C4, 0x0394}, {0xA6A5, 0xA6C5, 0x0395}, + {0xA6A6, 0xA6C6, 0x0396}, {0xA6A7, 0xA6C7, 0x0397}, + {0xA6A8, 0xA6C8, 0x0398}, {0xA6A9, 0xA6C9, 0x0399}, + {0xA6AA, 0xA6CA, 0x039A}, {0xA6AB, 0xA6CB, 0x039B}, + {0xA6AC, 0xA6CC, 0x039C}, {0xA6AD, 0xA6CD, 0x039D}, + {0xA6AE, 0xA6CE, 0x039E}, {0xA6AF, 0xA6CF, 0x039F}, + {0xA6B0, 0xA6D0, 0x03A0}, {0xA6B1, 0xA6D1, 0x03A1}, + {0xA6B2, 0xA6D2, 0x03A3}, {0xA6B3, 0xA6D3, 0x03A4}, + {0xA6B4, 0xA6D4, 0x03A5}, {0xA6B5, 0xA6D5, 0x03A6}, + {0xA6B6, 0xA6D6, 0x03A7}, {0xA6B7, 0xA6D7, 0x03A8}, + {0xA6B8, 0xA6D8, 0x03A9}, {0xA6B9, 0xA6B9, 0xE785}, + {0xA6BA, 0xA6BA, 0xE786}, {0xA6BB, 0xA6BB, 0xE787}, + {0xA6BC, 0xA6BC, 0xE788}, {0xA6BD, 0xA6BD, 0xE789}, + {0xA6BE, 0xA6BE, 0xE78A}, {0xA6BF, 0xA6BF, 0xE78B}, + {0xA6C0, 0xA6C0, 0xE78C}, {0xA6A1, 0xA6C1, 0x0391}, + {0xA6A2, 0xA6C2, 0x03D0}, {0xA6A3, 0xA6C3, 0x0393}, + {0xA6A4, 0xA6C4, 0x0394}, {0xA6A5, 0xA6C5, 0x03F5}, + {0xA6A6, 0xA6C6, 0x0396}, {0xA6A7, 0xA6C7, 0x0397}, + {0xA6A8, 0xA6C8, 0x03D1}, {0xA6A9, 0xA6C9, 0x0345}, + {0xA6AA, 0xA6CA, 0x03F0}, {0xA6AB, 0xA6CB, 0x039B}, + {0xA6AC, 0xA6CC, 0x00B5}, {0xA6AD, 0xA6CD, 0x039D}, + {0xA6AE, 0xA6CE, 0x039E}, {0xA6AF, 0xA6CF, 0x039F}, + {0xA6B0, 0xA6D0, 0x03D6}, {0xA6B1, 0xA6D1, 0x03F1}, + {0xA6B2, 0xA6D2, 0x03C2}, {0xA6B3, 0xA6D3, 0x03A4}, + {0xA6B4, 0xA6D4, 0x03A5}, {0xA6B5, 0xA6D5, 0x03D5}, + {0xA6B6, 0xA6D6, 0x03A7}, {0xA6B7, 0xA6D7, 0x03A8}, + {0xA6B8, 0xA6D8, 0x2126}, {0xA6D9, 0xA6D9, 0xE78D}, + {0xA6DA, 0xA6DA, 0xE78E}, {0xA6DB, 0xA6DB, 0xE78F}, + {0xA6DC, 0xA6DC, 0xE790}, {0xA6DD, 0xA6DD, 0xE791}, + {0xA6DE, 0xA6DE, 0xE792}, {0xA6DF, 0xA6DF, 0xE793}, + {0xA6E0, 0xA6E0, 0xFE35}, {0xA6E1, 0xA6E1, 0xFE36}, + {0xA6E2, 0xA6E2, 0xFE39}, {0xA6E3, 0xA6E3, 0xFE3A}, + {0xA6E4, 0xA6E4, 0xFE3F}, {0xA6E5, 0xA6E5, 0xFE40}, + {0xA6E6, 0xA6E6, 0xFE3D}, {0xA6E7, 0xA6E7, 0xFE3E}, + {0xA6E8, 0xA6E8, 0xFE41}, {0xA6E9, 0xA6E9, 0xFE42}, + {0xA6EA, 0xA6EA, 0xFE43}, {0xA6EB, 0xA6EB, 0xFE44}, + {0xA6EC, 0xA6EC, 0xE794}, {0xA6ED, 0xA6ED, 0xE795}, + {0xA6EE, 0xA6EE, 0xFE3B}, {0xA6EF, 0xA6EF, 0xFE3C}, + {0xA6F0, 0xA6F0, 0xFE37}, {0xA6F1, 0xA6F1, 0xFE38}, + {0xA6F2, 0xA6F2, 0xFE31}, {0xA6F3, 0xA6F3, 0xE796}, + {0xA6F4, 0xA6F4, 0xFE33}, {0xA6F5, 0xA6F5, 0xFE34}, + {0xA6F6, 0xA6F6, 0xE797}, {0xA6F7, 0xA6F7, 0xE798}, + {0xA6F8, 0xA6F8, 0xE799}, {0xA6F9, 0xA6F9, 0xE79A}, + {0xA6FA, 0xA6FA, 0xE79B}, {0xA6FB, 0xA6FB, 0xE79C}, + {0xA6FC, 0xA6FC, 0xE79D}, {0xA6FD, 0xA6FD, 0xE79E}, + {0xA6FE, 0xA6FE, 0xE79F}, {0xA6FF, 0xA6FF, 0x003F}}; + +static ObUnicaseInfoChar planeA7[] = { + {0xA700, 0xA700, 0x003F}, {0xA701, 0xA701, 0x003F}, + {0xA702, 0xA702, 0x003F}, {0xA703, 0xA703, 0x003F}, + {0xA704, 0xA704, 0x003F}, {0xA705, 0xA705, 0x003F}, + {0xA706, 0xA706, 0x003F}, {0xA707, 0xA707, 0x003F}, + {0xA708, 0xA708, 0x003F}, {0xA709, 0xA709, 0x003F}, + {0xA70A, 0xA70A, 0x003F}, {0xA70B, 0xA70B, 0x003F}, + {0xA70C, 0xA70C, 0x003F}, {0xA70D, 0xA70D, 0x003F}, + {0xA70E, 0xA70E, 0x003F}, {0xA70F, 0xA70F, 0x003F}, + {0xA710, 0xA710, 0x003F}, {0xA711, 0xA711, 0x003F}, + {0xA712, 0xA712, 0x003F}, {0xA713, 0xA713, 0x003F}, + {0xA714, 0xA714, 0x003F}, {0xA715, 0xA715, 0x003F}, + {0xA716, 0xA716, 0x003F}, {0xA717, 0xA717, 0x003F}, + {0xA718, 0xA718, 0x003F}, {0xA719, 0xA719, 0x003F}, + {0xA71A, 0xA71A, 0x003F}, {0xA71B, 0xA71B, 0x003F}, + {0xA71C, 0xA71C, 0x003F}, {0xA71D, 0xA71D, 0x003F}, + {0xA71E, 0xA71E, 0x003F}, {0xA71F, 0xA71F, 0x003F}, + {0xA720, 0xA720, 0x003F}, {0xA721, 0xA721, 0x003F}, + {0xA722, 0xA722, 0x003F}, {0xA723, 0xA723, 0x003F}, + {0xA724, 0xA724, 0x003F}, {0xA725, 0xA725, 0x003F}, + {0xA726, 0xA726, 0x003F}, {0xA727, 0xA727, 0x003F}, + {0xA728, 0xA728, 0x003F}, {0xA729, 0xA729, 0x003F}, + {0xA72A, 0xA72A, 0x003F}, {0xA72B, 0xA72B, 0x003F}, + {0xA72C, 0xA72C, 0x003F}, {0xA72D, 0xA72D, 0x003F}, + {0xA72E, 0xA72E, 0x003F}, {0xA72F, 0xA72F, 0x003F}, + {0xA730, 0xA730, 0x003F}, {0xA731, 0xA731, 0x003F}, + {0xA732, 0xA732, 0x003F}, {0xA733, 0xA733, 0x003F}, + {0xA734, 0xA734, 0x003F}, {0xA735, 0xA735, 0x003F}, + {0xA736, 0xA736, 0x003F}, {0xA737, 0xA737, 0x003F}, + {0xA738, 0xA738, 0x003F}, {0xA739, 0xA739, 0x003F}, + {0xA73A, 0xA73A, 0x003F}, {0xA73B, 0xA73B, 0x003F}, + {0xA73C, 0xA73C, 0x003F}, {0xA73D, 0xA73D, 0x003F}, + {0xA73E, 0xA73E, 0x003F}, {0xA73F, 0xA73F, 0x003F}, + {0xA740, 0xA740, 0xE706}, {0xA741, 0xA741, 0xE707}, + {0xA742, 0xA742, 0xE708}, {0xA743, 0xA743, 0xE709}, + {0xA744, 0xA744, 0xE70A}, {0xA745, 0xA745, 0xE70B}, + {0xA746, 0xA746, 0xE70C}, {0xA747, 0xA747, 0xE70D}, + {0xA748, 0xA748, 0xE70E}, {0xA749, 0xA749, 0xE70F}, + {0xA74A, 0xA74A, 0xE710}, {0xA74B, 0xA74B, 0xE711}, + {0xA74C, 0xA74C, 0xE712}, {0xA74D, 0xA74D, 0xE713}, + {0xA74E, 0xA74E, 0xE714}, {0xA74F, 0xA74F, 0xE715}, + {0xA750, 0xA750, 0xE716}, {0xA751, 0xA751, 0xE717}, + {0xA752, 0xA752, 0xE718}, {0xA753, 0xA753, 0xE719}, + {0xA754, 0xA754, 0xE71A}, {0xA755, 0xA755, 0xE71B}, + {0xA756, 0xA756, 0xE71C}, {0xA757, 0xA757, 0xE71D}, + {0xA758, 0xA758, 0xE71E}, {0xA759, 0xA759, 0xE71F}, + {0xA75A, 0xA75A, 0xE720}, {0xA75B, 0xA75B, 0xE721}, + {0xA75C, 0xA75C, 0xE722}, {0xA75D, 0xA75D, 0xE723}, + {0xA75E, 0xA75E, 0xE724}, {0xA75F, 0xA75F, 0xE725}, + {0xA760, 0xA760, 0xE726}, {0xA761, 0xA761, 0xE727}, + {0xA762, 0xA762, 0xE728}, {0xA763, 0xA763, 0xE729}, + {0xA764, 0xA764, 0xE72A}, {0xA765, 0xA765, 0xE72B}, + {0xA766, 0xA766, 0xE72C}, {0xA767, 0xA767, 0xE72D}, + {0xA768, 0xA768, 0xE72E}, {0xA769, 0xA769, 0xE72F}, + {0xA76A, 0xA76A, 0xE730}, {0xA76B, 0xA76B, 0xE731}, + {0xA76C, 0xA76C, 0xE732}, {0xA76D, 0xA76D, 0xE733}, + {0xA76E, 0xA76E, 0xE734}, {0xA76F, 0xA76F, 0xE735}, + {0xA770, 0xA770, 0xE736}, {0xA771, 0xA771, 0xE737}, + {0xA772, 0xA772, 0xE738}, {0xA773, 0xA773, 0xE739}, + {0xA774, 0xA774, 0xE73A}, {0xA775, 0xA775, 0xE73B}, + {0xA776, 0xA776, 0xE73C}, {0xA777, 0xA777, 0xE73D}, + {0xA778, 0xA778, 0xE73E}, {0xA779, 0xA779, 0xE73F}, + {0xA77A, 0xA77A, 0xE740}, {0xA77B, 0xA77B, 0xE741}, + {0xA77C, 0xA77C, 0xE742}, {0xA77D, 0xA77D, 0xE743}, + {0xA77E, 0xA77E, 0xE744}, {0xA77F, 0xA77F, 0x003F}, + {0xA780, 0xA780, 0xE745}, {0xA781, 0xA781, 0xE746}, + {0xA782, 0xA782, 0xE747}, {0xA783, 0xA783, 0xE748}, + {0xA784, 0xA784, 0xE749}, {0xA785, 0xA785, 0xE74A}, + {0xA786, 0xA786, 0xE74B}, {0xA787, 0xA787, 0xE74C}, + {0xA788, 0xA788, 0xE74D}, {0xA789, 0xA789, 0xE74E}, + {0xA78A, 0xA78A, 0xE74F}, {0xA78B, 0xA78B, 0xE750}, + {0xA78C, 0xA78C, 0xE751}, {0xA78D, 0xA78D, 0xE752}, + {0xA78E, 0xA78E, 0xE753}, {0xA78F, 0xA78F, 0xE754}, + {0xA790, 0xA790, 0xE755}, {0xA791, 0xA791, 0xE756}, + {0xA792, 0xA792, 0xE757}, {0xA793, 0xA793, 0xE758}, + {0xA794, 0xA794, 0xE759}, {0xA795, 0xA795, 0xE75A}, + {0xA796, 0xA796, 0xE75B}, {0xA797, 0xA797, 0xE75C}, + {0xA798, 0xA798, 0xE75D}, {0xA799, 0xA799, 0xE75E}, + {0xA79A, 0xA79A, 0xE75F}, {0xA79B, 0xA79B, 0xE760}, + {0xA79C, 0xA79C, 0xE761}, {0xA79D, 0xA79D, 0xE762}, + {0xA79E, 0xA79E, 0xE763}, {0xA79F, 0xA79F, 0xE764}, + {0xA7A0, 0xA7A0, 0xE765}, {0xA7A1, 0xA7D1, 0x0410}, + {0xA7A2, 0xA7D2, 0x0411}, {0xA7A3, 0xA7D3, 0x0412}, + {0xA7A4, 0xA7D4, 0x0413}, {0xA7A5, 0xA7D5, 0x0414}, + {0xA7A6, 0xA7D6, 0x0415}, {0xA7A7, 0xA7D7, 0x0401}, + {0xA7A8, 0xA7D8, 0x0416}, {0xA7A9, 0xA7D9, 0x0417}, + {0xA7AA, 0xA7DA, 0x0418}, {0xA7AB, 0xA7DB, 0x0419}, + {0xA7AC, 0xA7DC, 0x041A}, {0xA7AD, 0xA7DD, 0x041B}, + {0xA7AE, 0xA7DE, 0x041C}, {0xA7AF, 0xA7DF, 0x041D}, + {0xA7B0, 0xA7E0, 0x041E}, {0xA7B1, 0xA7E1, 0x041F}, + {0xA7B2, 0xA7E2, 0x0420}, {0xA7B3, 0xA7E3, 0x0421}, + {0xA7B4, 0xA7E4, 0x0422}, {0xA7B5, 0xA7E5, 0x0423}, + {0xA7B6, 0xA7E6, 0x0424}, {0xA7B7, 0xA7E7, 0x0425}, + {0xA7B8, 0xA7E8, 0x0426}, {0xA7B9, 0xA7E9, 0x0427}, + {0xA7BA, 0xA7EA, 0x0428}, {0xA7BB, 0xA7EB, 0x0429}, + {0xA7BC, 0xA7EC, 0x042A}, {0xA7BD, 0xA7ED, 0x042B}, + {0xA7BE, 0xA7EE, 0x042C}, {0xA7BF, 0xA7EF, 0x042D}, + {0xA7C0, 0xA7F0, 0x042E}, {0xA7C1, 0xA7F1, 0x042F}, + {0xA7C2, 0xA7C2, 0xE7A0}, {0xA7C3, 0xA7C3, 0xE7A1}, + {0xA7C4, 0xA7C4, 0xE7A2}, {0xA7C5, 0xA7C5, 0xE7A3}, + {0xA7C6, 0xA7C6, 0xE7A4}, {0xA7C7, 0xA7C7, 0xE7A5}, + {0xA7C8, 0xA7C8, 0xE7A6}, {0xA7C9, 0xA7C9, 0xE7A7}, + {0xA7CA, 0xA7CA, 0xE7A8}, {0xA7CB, 0xA7CB, 0xE7A9}, + {0xA7CC, 0xA7CC, 0xE7AA}, {0xA7CD, 0xA7CD, 0xE7AB}, + {0xA7CE, 0xA7CE, 0xE7AC}, {0xA7CF, 0xA7CF, 0xE7AD}, + {0xA7D0, 0xA7D0, 0xE7AE}, {0xA7A1, 0xA7D1, 0x0410}, + {0xA7A2, 0xA7D2, 0x0411}, {0xA7A3, 0xA7D3, 0x0412}, + {0xA7A4, 0xA7D4, 0x0413}, {0xA7A5, 0xA7D5, 0x0414}, + {0xA7A6, 0xA7D6, 0x0415}, {0xA7A7, 0xA7D7, 0x0401}, + {0xA7A8, 0xA7D8, 0x0416}, {0xA7A9, 0xA7D9, 0x0417}, + {0xA7AA, 0xA7DA, 0x0418}, {0xA7AB, 0xA7DB, 0x0419}, + {0xA7AC, 0xA7DC, 0x041A}, {0xA7AD, 0xA7DD, 0x041B}, + {0xA7AE, 0xA7DE, 0x041C}, {0xA7AF, 0xA7DF, 0x041D}, + {0xA7B0, 0xA7E0, 0x041E}, {0xA7B1, 0xA7E1, 0x041F}, + {0xA7B2, 0xA7E2, 0x0420}, {0xA7B3, 0xA7E3, 0x0421}, + {0xA7B4, 0xA7E4, 0x0422}, {0xA7B5, 0xA7E5, 0x0423}, + {0xA7B6, 0xA7E6, 0x0424}, {0xA7B7, 0xA7E7, 0x0425}, + {0xA7B8, 0xA7E8, 0x0426}, {0xA7B9, 0xA7E9, 0x0427}, + {0xA7BA, 0xA7EA, 0x0428}, {0xA7BB, 0xA7EB, 0x0429}, + {0xA7BC, 0xA7EC, 0x042A}, {0xA7BD, 0xA7ED, 0x042B}, + {0xA7BE, 0xA7EE, 0x042C}, {0xA7BF, 0xA7EF, 0x042D}, + {0xA7C0, 0xA7F0, 0x042E}, {0xA7C1, 0xA7F1, 0x042F}, + {0xA7F2, 0xA7F2, 0xE7AF}, {0xA7F3, 0xA7F3, 0xE7B0}, + {0xA7F4, 0xA7F4, 0xE7B1}, {0xA7F5, 0xA7F5, 0xE7B2}, + {0xA7F6, 0xA7F6, 0xE7B3}, {0xA7F7, 0xA7F7, 0xE7B4}, + {0xA7F8, 0xA7F8, 0xE7B5}, {0xA7F9, 0xA7F9, 0xE7B6}, + {0xA7FA, 0xA7FA, 0xE7B7}, {0xA7FB, 0xA7FB, 0xE7B8}, + {0xA7FC, 0xA7FC, 0xE7B9}, {0xA7FD, 0xA7FD, 0xE7BA}, + {0xA7FE, 0xA7FE, 0xE7BB}, {0xA7FF, 0xA7FF, 0x003F}}; + +static ObUnicaseInfoChar planeA8[] = { + {0xA800, 0xA800, 0x003F}, {0xA801, 0xA801, 0x003F}, + {0xA802, 0xA802, 0x003F}, {0xA803, 0xA803, 0x003F}, + {0xA804, 0xA804, 0x003F}, {0xA805, 0xA805, 0x003F}, + {0xA806, 0xA806, 0x003F}, {0xA807, 0xA807, 0x003F}, + {0xA808, 0xA808, 0x003F}, {0xA809, 0xA809, 0x003F}, + {0xA80A, 0xA80A, 0x003F}, {0xA80B, 0xA80B, 0x003F}, + {0xA80C, 0xA80C, 0x003F}, {0xA80D, 0xA80D, 0x003F}, + {0xA80E, 0xA80E, 0x003F}, {0xA80F, 0xA80F, 0x003F}, + {0xA810, 0xA810, 0x003F}, {0xA811, 0xA811, 0x003F}, + {0xA812, 0xA812, 0x003F}, {0xA813, 0xA813, 0x003F}, + {0xA814, 0xA814, 0x003F}, {0xA815, 0xA815, 0x003F}, + {0xA816, 0xA816, 0x003F}, {0xA817, 0xA817, 0x003F}, + {0xA818, 0xA818, 0x003F}, {0xA819, 0xA819, 0x003F}, + {0xA81A, 0xA81A, 0x003F}, {0xA81B, 0xA81B, 0x003F}, + {0xA81C, 0xA81C, 0x003F}, {0xA81D, 0xA81D, 0x003F}, + {0xA81E, 0xA81E, 0x003F}, {0xA81F, 0xA81F, 0x003F}, + {0xA820, 0xA820, 0x003F}, {0xA821, 0xA821, 0x003F}, + {0xA822, 0xA822, 0x003F}, {0xA823, 0xA823, 0x003F}, + {0xA824, 0xA824, 0x003F}, {0xA825, 0xA825, 0x003F}, + {0xA826, 0xA826, 0x003F}, {0xA827, 0xA827, 0x003F}, + {0xA828, 0xA828, 0x003F}, {0xA829, 0xA829, 0x003F}, + {0xA82A, 0xA82A, 0x003F}, {0xA82B, 0xA82B, 0x003F}, + {0xA82C, 0xA82C, 0x003F}, {0xA82D, 0xA82D, 0x003F}, + {0xA82E, 0xA82E, 0x003F}, {0xA82F, 0xA82F, 0x003F}, + {0xA830, 0xA830, 0x003F}, {0xA831, 0xA831, 0x003F}, + {0xA832, 0xA832, 0x003F}, {0xA833, 0xA833, 0x003F}, + {0xA834, 0xA834, 0x003F}, {0xA835, 0xA835, 0x003F}, + {0xA836, 0xA836, 0x003F}, {0xA837, 0xA837, 0x003F}, + {0xA838, 0xA838, 0x003F}, {0xA839, 0xA839, 0x003F}, + {0xA83A, 0xA83A, 0x003F}, {0xA83B, 0xA83B, 0x003F}, + {0xA83C, 0xA83C, 0x003F}, {0xA83D, 0xA83D, 0x003F}, + {0xA83E, 0xA83E, 0x003F}, {0xA83F, 0xA83F, 0x003F}, + {0xA840, 0xA840, 0x02CA}, {0xA841, 0xA841, 0x02CB}, + {0xA842, 0xA842, 0x02D9}, {0xA843, 0xA843, 0x2013}, + {0xA844, 0xA844, 0x2015}, {0xA845, 0xA845, 0x2025}, + {0xA846, 0xA846, 0x2035}, {0xA847, 0xA847, 0x2105}, + {0xA848, 0xA848, 0x2109}, {0xA849, 0xA849, 0x2196}, + {0xA84A, 0xA84A, 0x2197}, {0xA84B, 0xA84B, 0x2198}, + {0xA84C, 0xA84C, 0x2199}, {0xA84D, 0xA84D, 0x2215}, + {0xA84E, 0xA84E, 0x221F}, {0xA84F, 0xA84F, 0x2223}, + {0xA850, 0xA850, 0x2252}, {0xA851, 0xA851, 0x2266}, + {0xA852, 0xA852, 0x2267}, {0xA853, 0xA853, 0x22BF}, + {0xA854, 0xA854, 0x2550}, {0xA855, 0xA855, 0x2551}, + {0xA856, 0xA856, 0x2552}, {0xA857, 0xA857, 0x2553}, + {0xA858, 0xA858, 0x2554}, {0xA859, 0xA859, 0x2555}, + {0xA85A, 0xA85A, 0x2556}, {0xA85B, 0xA85B, 0x2557}, + {0xA85C, 0xA85C, 0x2558}, {0xA85D, 0xA85D, 0x2559}, + {0xA85E, 0xA85E, 0x255A}, {0xA85F, 0xA85F, 0x255B}, + {0xA860, 0xA860, 0x255C}, {0xA861, 0xA861, 0x255D}, + {0xA862, 0xA862, 0x255E}, {0xA863, 0xA863, 0x255F}, + {0xA864, 0xA864, 0x2560}, {0xA865, 0xA865, 0x2561}, + {0xA866, 0xA866, 0x2562}, {0xA867, 0xA867, 0x2563}, + {0xA868, 0xA868, 0x2564}, {0xA869, 0xA869, 0x2565}, + {0xA86A, 0xA86A, 0x2566}, {0xA86B, 0xA86B, 0x2567}, + {0xA86C, 0xA86C, 0x2568}, {0xA86D, 0xA86D, 0x2569}, + {0xA86E, 0xA86E, 0x256A}, {0xA86F, 0xA86F, 0x256B}, + {0xA870, 0xA870, 0x256C}, {0xA871, 0xA871, 0x256D}, + {0xA872, 0xA872, 0x256E}, {0xA873, 0xA873, 0x256F}, + {0xA874, 0xA874, 0x2570}, {0xA875, 0xA875, 0x2571}, + {0xA876, 0xA876, 0x2572}, {0xA877, 0xA877, 0x2573}, + {0xA878, 0xA878, 0x2581}, {0xA879, 0xA879, 0x2582}, + {0xA87A, 0xA87A, 0x2583}, {0xA87B, 0xA87B, 0x2584}, + {0xA87C, 0xA87C, 0x2585}, {0xA87D, 0xA87D, 0x2586}, + {0xA87E, 0xA87E, 0x2587}, {0xA87F, 0xA87F, 0x003F}, + {0xA880, 0xA880, 0x2588}, {0xA881, 0xA881, 0x2589}, + {0xA882, 0xA882, 0x258A}, {0xA883, 0xA883, 0x258B}, + {0xA884, 0xA884, 0x258C}, {0xA885, 0xA885, 0x258D}, + {0xA886, 0xA886, 0x258E}, {0xA887, 0xA887, 0x258F}, + {0xA888, 0xA888, 0x2593}, {0xA889, 0xA889, 0x2594}, + {0xA88A, 0xA88A, 0x2595}, {0xA88B, 0xA88B, 0x25BC}, + {0xA88C, 0xA88C, 0x25BD}, {0xA88D, 0xA88D, 0x25E2}, + {0xA88E, 0xA88E, 0x25E3}, {0xA88F, 0xA88F, 0x25E4}, + {0xA890, 0xA890, 0x25E5}, {0xA891, 0xA891, 0x2609}, + {0xA892, 0xA892, 0x2295}, {0xA893, 0xA893, 0x3012}, + {0xA894, 0xA894, 0x301D}, {0xA895, 0xA895, 0x301E}, + {0xA896, 0xA896, 0xE7BC}, {0xA897, 0xA897, 0xE7BD}, + {0xA898, 0xA898, 0xE7BE}, {0xA899, 0xA899, 0xE7BF}, + {0xA89A, 0xA89A, 0xE7C0}, {0xA89B, 0xA89B, 0xE7C1}, + {0xA89C, 0xA89C, 0xE7C2}, {0xA89D, 0xA89D, 0xE7C3}, + {0xA89E, 0xA89E, 0xE7C4}, {0xA89F, 0xA89F, 0xE7C5}, + {0xA8A0, 0xA8A0, 0xE7C6}, {0x00EC, 0xA8A1, 0x0100}, + {0x00BB, 0xA8A2, 0x00C1}, {0x01B1, 0xA8A3, 0x01CD}, + {0x00BA, 0xA8A4, 0x00C0}, {0x00FD, 0xA8A5, 0x0112}, + {0x00C3, 0xA8A6, 0x00C9}, {0x0104, 0xA8A7, 0x011A}, + {0x00C2, 0xA8A8, 0x00C8}, {0x0113, 0xA8A9, 0x012A}, + {0x00C7, 0xA8AA, 0x00CD}, {0x01B2, 0xA8AB, 0x01CF}, + {0x00C6, 0xA8AC, 0x00CC}, {0x0132, 0xA8AD, 0x014C}, + {0x00CD, 0xA8AE, 0x00D3}, {0x01B3, 0xA8AF, 0x01D1}, + {0x00CC, 0xA8B0, 0x00D2}, {0x014F, 0xA8B1, 0x016A}, + {0x00D3, 0xA8B2, 0x00DA}, {0x01B4, 0xA8B3, 0x01D3}, + {0x00D2, 0xA8B4, 0x00D9}, {0x01B5, 0xA8B5, 0x01D5}, + {0x01B6, 0xA8B6, 0x01D7}, {0x01B7, 0xA8B7, 0x01D9}, + {0x01B8, 0xA8B8, 0x01DB}, {0x00D5, 0xA8B9, 0x00DC}, + {0x00C4, 0xA8BA, 0x00CA}, {0x2AAD, 0xA8BB, 0x2C6D}, + {0x1DA0, 0xA8BC, 0x1E3E}, {0x012B, 0xA8BD, 0x0143}, + {0x012E, 0xA8BE, 0x0147}, {0x01D4, 0xA8BF, 0x01F8}, + {0xA8C0, 0xA8C0, 0x0261}, {0xA8C1, 0xA8C1, 0xE7C9}, + {0xA8C2, 0xA8C2, 0xE7CA}, {0xA8C3, 0xA8C3, 0xE7CB}, + {0xA8C4, 0xA8C4, 0xE7CC}, {0xA8C5, 0xA8C5, 0x3105}, + {0xA8C6, 0xA8C6, 0x3106}, {0xA8C7, 0xA8C7, 0x3107}, + {0xA8C8, 0xA8C8, 0x3108}, {0xA8C9, 0xA8C9, 0x3109}, + {0xA8CA, 0xA8CA, 0x310A}, {0xA8CB, 0xA8CB, 0x310B}, + {0xA8CC, 0xA8CC, 0x310C}, {0xA8CD, 0xA8CD, 0x310D}, + {0xA8CE, 0xA8CE, 0x310E}, {0xA8CF, 0xA8CF, 0x310F}, + {0xA8D0, 0xA8D0, 0x3110}, {0xA8D1, 0xA8D1, 0x3111}, + {0xA8D2, 0xA8D2, 0x3112}, {0xA8D3, 0xA8D3, 0x3113}, + {0xA8D4, 0xA8D4, 0x3114}, {0xA8D5, 0xA8D5, 0x3115}, + {0xA8D6, 0xA8D6, 0x3116}, {0xA8D7, 0xA8D7, 0x3117}, + {0xA8D8, 0xA8D8, 0x3118}, {0xA8D9, 0xA8D9, 0x3119}, + {0xA8DA, 0xA8DA, 0x311A}, {0xA8DB, 0xA8DB, 0x311B}, + {0xA8DC, 0xA8DC, 0x311C}, {0xA8DD, 0xA8DD, 0x311D}, + {0xA8DE, 0xA8DE, 0x311E}, {0xA8DF, 0xA8DF, 0x311F}, + {0xA8E0, 0xA8E0, 0x3120}, {0xA8E1, 0xA8E1, 0x3121}, + {0xA8E2, 0xA8E2, 0x3122}, {0xA8E3, 0xA8E3, 0x3123}, + {0xA8E4, 0xA8E4, 0x3124}, {0xA8E5, 0xA8E5, 0x3125}, + {0xA8E6, 0xA8E6, 0x3126}, {0xA8E7, 0xA8E7, 0x3127}, + {0xA8E8, 0xA8E8, 0x3128}, {0xA8E9, 0xA8E9, 0x3129}, + {0xA8EA, 0xA8EA, 0xE7CD}, {0xA8EB, 0xA8EB, 0xE7CE}, + {0xA8EC, 0xA8EC, 0xE7CF}, {0xA8ED, 0xA8ED, 0xE7D0}, + {0xA8EE, 0xA8EE, 0xE7D1}, {0xA8EF, 0xA8EF, 0xE7D2}, + {0xA8F0, 0xA8F0, 0xE7D3}, {0xA8F1, 0xA8F1, 0xE7D4}, + {0xA8F2, 0xA8F2, 0xE7D5}, {0xA8F3, 0xA8F3, 0xE7D6}, + {0xA8F4, 0xA8F4, 0xE7D7}, {0xA8F5, 0xA8F5, 0xE7D8}, + {0xA8F6, 0xA8F6, 0xE7D9}, {0xA8F7, 0xA8F7, 0xE7DA}, + {0xA8F8, 0xA8F8, 0xE7DB}, {0xA8F9, 0xA8F9, 0xE7DC}, + {0xA8FA, 0xA8FA, 0xE7DD}, {0xA8FB, 0xA8FB, 0xE7DE}, + {0xA8FC, 0xA8FC, 0xE7DF}, {0xA8FD, 0xA8FD, 0xE7E0}, + {0xA8FE, 0xA8FE, 0xE7E1}, {0xA8FF, 0xA8FF, 0x003F}}; + +static ObUnicaseInfoChar planeE6[] = { + {0xE600, 0xE600, 0x103B8}, {0xE601, 0xE601, 0x103B9}, + {0xE602, 0xE602, 0x103BA}, {0xE603, 0xE603, 0x103BB}, + {0xE604, 0xE604, 0x103BC}, {0xE605, 0xE605, 0x103BD}, + {0xE606, 0xE606, 0x103BE}, {0xE607, 0xE607, 0x103BF}, + {0xE608, 0xE608, 0x103C0}, {0xE609, 0xE609, 0x103C1}, + {0xE60A, 0xE60A, 0x103C2}, {0xE60B, 0xE60B, 0x103C3}, + {0xE60C, 0xE60C, 0x103C4}, {0xE60D, 0xE60D, 0x103C5}, + {0xE60E, 0xE60E, 0x103C6}, {0xE60F, 0xE60F, 0x103C7}, + {0xE610, 0xE610, 0x103C8}, {0xE611, 0xE611, 0x103C9}, + {0xE612, 0xE612, 0x103CA}, {0xE613, 0xE613, 0x103CB}, + {0xE614, 0xE614, 0x103CC}, {0xE615, 0xE615, 0x103CD}, + {0xE616, 0xE616, 0x103CE}, {0xE617, 0xE617, 0x103CF}, + {0xE618, 0xE618, 0x103D0}, {0xE619, 0xE619, 0x103D1}, + {0xE61A, 0xE61A, 0x103D2}, {0xE61B, 0xE61B, 0x103D3}, + {0xE61C, 0xE61C, 0x103D4}, {0xE61D, 0xE61D, 0x103D5}, + {0xE61E, 0xE61E, 0x103D6}, {0xE61F, 0xE61F, 0x103D7}, + {0xE620, 0xE620, 0x103D8}, {0xE621, 0xE621, 0x103D9}, + {0xE622, 0xE622, 0x103DA}, {0xE623, 0xE623, 0x103DB}, + {0xE624, 0xE624, 0x103DC}, {0xE625, 0xE625, 0x103DD}, + {0xE626, 0xE626, 0x103DE}, {0xE627, 0xE627, 0x103DF}, + {0xE628, 0xE628, 0x103E0}, {0xE629, 0xE629, 0x103E1}, + {0xE62A, 0xE62A, 0x103E2}, {0xE62B, 0xE62B, 0x103E3}, + {0xE62C, 0xE62C, 0x103E4}, {0xE62D, 0xE62D, 0x103E5}, + {0xE62E, 0xE62E, 0x103E6}, {0xE62F, 0xE62F, 0x103E7}, + {0xE630, 0xE630, 0x103E8}, {0xE631, 0xE631, 0x103E9}, + {0xE632, 0xE632, 0x103EA}, {0xE633, 0xE633, 0x103EB}, + {0xE634, 0xE634, 0x103EC}, {0xE635, 0xE635, 0x103ED}, + {0xE636, 0xE636, 0x103EE}, {0xE637, 0xE637, 0x103EF}, + {0xE638, 0xE638, 0x103F0}, {0xE639, 0xE639, 0x103F1}, + {0xE63A, 0xE63A, 0x103F2}, {0xE63B, 0xE63B, 0x103F3}, + {0xE63C, 0xE63C, 0x103F4}, {0xE63D, 0xE63D, 0x103F5}, + {0xE63E, 0xE63E, 0x103F6}, {0xE63F, 0xE63F, 0x103F7}, + {0xE640, 0xE640, 0x103F8}, {0xE641, 0xE641, 0x103F9}, + {0xE642, 0xE642, 0x103FA}, {0xE643, 0xE643, 0x103FB}, + {0xE644, 0xE644, 0x103FC}, {0xE645, 0xE645, 0x103FD}, + {0xE646, 0xE646, 0x103FE}, {0xE647, 0xE647, 0x103FF}, + {0xE648, 0xE670, 0x10400}, {0xE649, 0xE671, 0x10401}, + {0xE64A, 0xE672, 0x10402}, {0xE64B, 0xE673, 0x10403}, + {0xE64C, 0xE674, 0x10404}, {0xE64D, 0xE675, 0x10405}, + {0xE64E, 0xE676, 0x10406}, {0xE64F, 0xE677, 0x10407}, + {0xE650, 0xE678, 0x10408}, {0xE651, 0xE679, 0x10409}, + {0xE652, 0xE67A, 0x1040A}, {0xE653, 0xE67B, 0x1040B}, + {0xE654, 0xE67C, 0x1040C}, {0xE655, 0xE67D, 0x1040D}, + {0xE656, 0xE67E, 0x1040E}, {0xE657, 0xE67F, 0x1040F}, + {0xE658, 0xE680, 0x10410}, {0xE659, 0xE681, 0x10411}, + {0xE65A, 0xE682, 0x10412}, {0xE65B, 0xE683, 0x10413}, + {0xE65C, 0xE684, 0x10414}, {0xE65D, 0xE685, 0x10415}, + {0xE65E, 0xE686, 0x10416}, {0xE65F, 0xE687, 0x10417}, + {0xE660, 0xE688, 0x10418}, {0xE661, 0xE689, 0x10419}, + {0xE662, 0xE68A, 0x1041A}, {0xE663, 0xE68B, 0x1041B}, + {0xE664, 0xE68C, 0x1041C}, {0xE665, 0xE68D, 0x1041D}, + {0xE666, 0xE68E, 0x1041E}, {0xE667, 0xE68F, 0x1041F}, + {0xE668, 0xE690, 0x10420}, {0xE669, 0xE691, 0x10421}, + {0xE66A, 0xE692, 0x10422}, {0xE66B, 0xE693, 0x10423}, + {0xE66C, 0xE694, 0x10424}, {0xE66D, 0xE695, 0x10425}, + {0xE66E, 0xE696, 0x10426}, {0xE66F, 0xE697, 0x10427}, + {0xE648, 0xE670, 0x10400}, {0xE649, 0xE671, 0x10401}, + {0xE64A, 0xE672, 0x10402}, {0xE64B, 0xE673, 0x10403}, + {0xE64C, 0xE674, 0x10404}, {0xE64D, 0xE675, 0x10405}, + {0xE64E, 0xE676, 0x10406}, {0xE64F, 0xE677, 0x10407}, + {0xE650, 0xE678, 0x10408}, {0xE651, 0xE679, 0x10409}, + {0xE652, 0xE67A, 0x1040A}, {0xE653, 0xE67B, 0x1040B}, + {0xE654, 0xE67C, 0x1040C}, {0xE655, 0xE67D, 0x1040D}, + {0xE656, 0xE67E, 0x1040E}, {0xE657, 0xE67F, 0x1040F}, + {0xE658, 0xE680, 0x10410}, {0xE659, 0xE681, 0x10411}, + {0xE65A, 0xE682, 0x10412}, {0xE65B, 0xE683, 0x10413}, + {0xE65C, 0xE684, 0x10414}, {0xE65D, 0xE685, 0x10415}, + {0xE65E, 0xE686, 0x10416}, {0xE65F, 0xE687, 0x10417}, + {0xE660, 0xE688, 0x10418}, {0xE661, 0xE689, 0x10419}, + {0xE662, 0xE68A, 0x1041A}, {0xE663, 0xE68B, 0x1041B}, + {0xE664, 0xE68C, 0x1041C}, {0xE665, 0xE68D, 0x1041D}, + {0xE666, 0xE68E, 0x1041E}, {0xE667, 0xE68F, 0x1041F}, + {0xE668, 0xE690, 0x10420}, {0xE669, 0xE691, 0x10421}, + {0xE66A, 0xE692, 0x10422}, {0xE66B, 0xE693, 0x10423}, + {0xE66C, 0xE694, 0x10424}, {0xE66D, 0xE695, 0x10425}, + {0xE66E, 0xE696, 0x10426}, {0xE66F, 0xE697, 0x10427}, + {0xE698, 0xE698, 0x10450}, {0xE699, 0xE699, 0x10451}, + {0xE69A, 0xE69A, 0x10452}, {0xE69B, 0xE69B, 0x10453}, + {0xE69C, 0xE69C, 0x10454}, {0xE69D, 0xE69D, 0x10455}, + {0xE69E, 0xE69E, 0x10456}, {0xE69F, 0xE69F, 0x10457}, + {0xE6A0, 0xE6A0, 0x10458}, {0xE6A1, 0xE6A1, 0x10459}, + {0xE6A2, 0xE6A2, 0x1045A}, {0xE6A3, 0xE6A3, 0x1045B}, + {0xE6A4, 0xE6A4, 0x1045C}, {0xE6A5, 0xE6A5, 0x1045D}, + {0xE6A6, 0xE6A6, 0x1045E}, {0xE6A7, 0xE6A7, 0x1045F}, + {0xE6A8, 0xE6A8, 0x10460}, {0xE6A9, 0xE6A9, 0x10461}, + {0xE6AA, 0xE6AA, 0x10462}, {0xE6AB, 0xE6AB, 0x10463}, + {0xE6AC, 0xE6AC, 0x10464}, {0xE6AD, 0xE6AD, 0x10465}, + {0xE6AE, 0xE6AE, 0x10466}, {0xE6AF, 0xE6AF, 0x10467}, + {0xE6B0, 0xE6B0, 0x10468}, {0xE6B1, 0xE6B1, 0x10469}, + {0xE6B2, 0xE6B2, 0x1046A}, {0xE6B3, 0xE6B3, 0x1046B}, + {0xE6B4, 0xE6B4, 0x1046C}, {0xE6B5, 0xE6B5, 0x1046D}, + {0xE6B6, 0xE6B6, 0x1046E}, {0xE6B7, 0xE6B7, 0x1046F}, + {0xE6B8, 0xE6B8, 0x10470}, {0xE6B9, 0xE6B9, 0x10471}, + {0xE6BA, 0xE6BA, 0x10472}, {0xE6BB, 0xE6BB, 0x10473}, + {0xE6BC, 0xE6BC, 0x10474}, {0xE6BD, 0xE6BD, 0x10475}, + {0xE6BE, 0xE6BE, 0x10476}, {0xE6BF, 0xE6BF, 0x10477}, + {0xE6C0, 0xE6C0, 0x10478}, {0xE6C1, 0xE6C1, 0x10479}, + {0xE6C2, 0xE6C2, 0x1047A}, {0xE6C3, 0xE6C3, 0x1047B}, + {0xE6C4, 0xE6C4, 0x1047C}, {0xE6C5, 0xE6C5, 0x1047D}, + {0xE6C6, 0xE6C6, 0x1047E}, {0xE6C7, 0xE6C7, 0x1047F}, + {0xE6C8, 0xE6C8, 0x10480}, {0xE6C9, 0xE6C9, 0x10481}, + {0xE6CA, 0xE6CA, 0x10482}, {0xE6CB, 0xE6CB, 0x10483}, + {0xE6CC, 0xE6CC, 0x10484}, {0xE6CD, 0xE6CD, 0x10485}, + {0xE6CE, 0xE6CE, 0x10486}, {0xE6CF, 0xE6CF, 0x10487}, + {0xE6D0, 0xE6D0, 0x10488}, {0xE6D1, 0xE6D1, 0x10489}, + {0xE6D2, 0xE6D2, 0x1048A}, {0xE6D3, 0xE6D3, 0x1048B}, + {0xE6D4, 0xE6D4, 0x1048C}, {0xE6D5, 0xE6D5, 0x1048D}, + {0xE6D6, 0xE6D6, 0x1048E}, {0xE6D7, 0xE6D7, 0x1048F}, + {0xE6D8, 0xE6D8, 0x10490}, {0xE6D9, 0xE6D9, 0x10491}, + {0xE6DA, 0xE6DA, 0x10492}, {0xE6DB, 0xE6DB, 0x10493}, + {0xE6DC, 0xE6DC, 0x10494}, {0xE6DD, 0xE6DD, 0x10495}, + {0xE6DE, 0xE6DE, 0x10496}, {0xE6DF, 0xE6DF, 0x10497}, + {0xE6E0, 0xE6E0, 0x10498}, {0xE6E1, 0xE6E1, 0x10499}, + {0xE6E2, 0xE6E2, 0x1049A}, {0xE6E3, 0xE6E3, 0x1049B}, + {0xE6E4, 0xE6E4, 0x1049C}, {0xE6E5, 0xE6E5, 0x1049D}, + {0xE6E6, 0xE6E6, 0x1049E}, {0xE6E7, 0xE6E7, 0x1049F}, + {0xE6E8, 0xE6E8, 0x104A0}, {0xE6E9, 0xE6E9, 0x104A1}, + {0xE6EA, 0xE6EA, 0x104A2}, {0xE6EB, 0xE6EB, 0x104A3}, + {0xE6EC, 0xE6EC, 0x104A4}, {0xE6ED, 0xE6ED, 0x104A5}, + {0xE6EE, 0xE6EE, 0x104A6}, {0xE6EF, 0xE6EF, 0x104A7}, + {0xE6F0, 0xE6F0, 0x104A8}, {0xE6F1, 0xE6F1, 0x104A9}, + {0xE6F2, 0xE6F2, 0x104AA}, {0xE6F3, 0xE6F3, 0x104AB}, + {0xE6F4, 0xE6F4, 0x104AC}, {0xE6F5, 0xE6F5, 0x104AD}, + {0xE6F6, 0xE6F6, 0x104AE}, {0xE6F7, 0xE6F7, 0x104AF}, + {0xE6F8, 0xE6F8, 0x104B0}, {0xE6F9, 0xE6F9, 0x104B1}, + {0xE6FA, 0xE6FA, 0x104B2}, {0xE6FB, 0xE6FB, 0x104B3}, + {0xE6FC, 0xE6FC, 0x104B4}, {0xE6FD, 0xE6FD, 0x104B5}, + {0xE6FE, 0xE6FE, 0x104B6}, {0xE6FF, 0xE6FF, 0x104B7}}; + +const static ObUnicaseInfoChar *ob_caseinfo_pages_gb18030[256] = { + plane00, plane01, plane02, plane03, plane04, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + plane10, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, plane1D, plane1E, plane1F, + plane20, NULL, NULL, plane23, NULL, NULL, NULL, NULL, + NULL, NULL, plane2A, plane2B, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, plane51, plane52, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, planeA2, planeA3, NULL, NULL, planeA6, planeA7, + planeA8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, planeE6, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; + +static ObUnicaseInfo ob_caseinfo_gb18030 = {0xFFFF, + ob_caseinfo_pages_gb18030}; + +static const uint16_t tab_gb18030_2_uni[] = { + 0x4E02, 0x4E04, 0x4E05, 0x4E06, 0x4E0F, 0x4E12, 0x4E17, 0x4E1F, 0x4E20, + 0x4E21, 0x4E23, 0x4E26, 0x4E29, 0x4E2E, 0x4E2F, 0x4E31, 0x4E33, 0x4E35, + 0x4E37, 0x4E3C, 0x4E40, 0x4E41, 0x4E42, 0x4E44, 0x4E46, 0x4E4A, 0x4E51, + 0x4E55, 0x4E57, 0x4E5A, 0x4E5B, 0x4E62, 0x4E63, 0x4E64, 0x4E65, 0x4E67, + 0x4E68, 0x4E6A, 0x4E6B, 0x4E6C, 0x4E6D, 0x4E6E, 0x4E6F, 0x4E72, 0x4E74, + 0x4E75, 0x4E76, 0x4E77, 0x4E78, 0x4E79, 0x4E7A, 0x4E7B, 0x4E7C, 0x4E7D, + 0x4E7F, 0x4E80, 0x4E81, 0x4E82, 0x4E83, 0x4E84, 0x4E85, 0x4E87, 0x4E8A, + 0, 0x4E90, 0x4E96, 0x4E97, 0x4E99, 0x4E9C, 0x4E9D, 0x4E9E, 0x4EA3, + 0x4EAA, 0x4EAF, 0x4EB0, 0x4EB1, 0x4EB4, 0x4EB6, 0x4EB7, 0x4EB8, 0x4EB9, + 0x4EBC, 0x4EBD, 0x4EBE, 0x4EC8, 0x4ECC, 0x4ECF, 0x4ED0, 0x4ED2, 0x4EDA, + 0x4EDB, 0x4EDC, 0x4EE0, 0x4EE2, 0x4EE6, 0x4EE7, 0x4EE9, 0x4EED, 0x4EEE, + 0x4EEF, 0x4EF1, 0x4EF4, 0x4EF8, 0x4EF9, 0x4EFA, 0x4EFC, 0x4EFE, 0x4F00, + 0x4F02, 0x4F03, 0x4F04, 0x4F05, 0x4F06, 0x4F07, 0x4F08, 0x4F0B, 0x4F0C, + 0x4F12, 0x4F13, 0x4F14, 0x4F15, 0x4F16, 0x4F1C, 0x4F1D, 0x4F21, 0x4F23, + 0x4F28, 0x4F29, 0x4F2C, 0x4F2D, 0x4F2E, 0x4F31, 0x4F33, 0x4F35, 0x4F37, + 0x4F39, 0x4F3B, 0x4F3E, 0x4F3F, 0x4F40, 0x4F41, 0x4F42, 0x4F44, 0x4F45, + 0x4F47, 0x4F48, 0x4F49, 0x4F4A, 0x4F4B, 0x4F4C, 0x4F52, 0x4F54, 0x4F56, + 0x4F61, 0x4F62, 0x4F66, 0x4F68, 0x4F6A, 0x4F6B, 0x4F6D, 0x4F6E, 0x4F71, + 0x4F72, 0x4F75, 0x4F77, 0x4F78, 0x4F79, 0x4F7A, 0x4F7D, 0x4F80, 0x4F81, + 0x4F82, 0x4F85, 0x4F86, 0x4F87, 0x4F8A, 0x4F8C, 0x4F8E, 0x4F90, 0x4F92, + 0x4F93, 0x4F95, 0x4F96, 0x4F98, 0x4F99, 0x4F9A, 0x4F9C, 0x4F9E, 0x4F9F, + 0x4FA1, 0x4FA2, 0, 0x4FA4, 0x4FAB, 0x4FAD, 0x4FB0, 0x4FB1, 0x4FB2, + 0x4FB3, 0x4FB4, 0x4FB6, 0x4FB7, 0x4FB8, 0x4FB9, 0x4FBA, 0x4FBB, 0x4FBC, + 0x4FBD, 0x4FBE, 0x4FC0, 0x4FC1, 0x4FC2, 0x4FC6, 0x4FC7, 0x4FC8, 0x4FC9, + 0x4FCB, 0x4FCC, 0x4FCD, 0x4FD2, 0x4FD3, 0x4FD4, 0x4FD5, 0x4FD6, 0x4FD9, + 0x4FDB, 0x4FE0, 0x4FE2, 0x4FE4, 0x4FE5, 0x4FE7, 0x4FEB, 0x4FEC, 0x4FF0, + 0x4FF2, 0x4FF4, 0x4FF5, 0x4FF6, 0x4FF7, 0x4FF9, 0x4FFB, 0x4FFC, 0x4FFD, + 0x4FFF, 0x5000, 0x5001, 0x5002, 0x5003, 0x5004, 0x5005, 0x5006, 0x5007, + 0x5008, 0x5009, 0x500A, 0, 0x500B, 0x500E, 0x5010, 0x5011, 0x5013, + 0x5015, 0x5016, 0x5017, 0x501B, 0x501D, 0x501E, 0x5020, 0x5022, 0x5023, + 0x5024, 0x5027, 0x502B, 0x502F, 0x5030, 0x5031, 0x5032, 0x5033, 0x5034, + 0x5035, 0x5036, 0x5037, 0x5038, 0x5039, 0x503B, 0x503D, 0x503F, 0x5040, + 0x5041, 0x5042, 0x5044, 0x5045, 0x5046, 0x5049, 0x504A, 0x504B, 0x504D, + 0x5050, 0x5051, 0x5052, 0x5053, 0x5054, 0x5056, 0x5057, 0x5058, 0x5059, + 0x505B, 0x505D, 0x505E, 0x505F, 0x5060, 0x5061, 0x5062, 0x5063, 0x5064, + 0x5066, 0x5067, 0x5068, 0x5069, 0x506A, 0x506B, 0x506D, 0x506E, 0x506F, + 0x5070, 0x5071, 0x5072, 0x5073, 0x5074, 0x5075, 0x5078, 0x5079, 0x507A, + 0x507C, 0x507D, 0x5081, 0x5082, 0x5083, 0x5084, 0x5086, 0x5087, 0x5089, + 0x508A, 0x508B, 0x508C, 0x508E, 0x508F, 0x5090, 0x5091, 0x5092, 0x5093, + 0x5094, 0x5095, 0x5096, 0x5097, 0x5098, 0x5099, 0x509A, 0x509B, 0x509C, + 0x509D, 0x509E, 0x509F, 0x50A0, 0x50A1, 0x50A2, 0x50A4, 0x50A6, 0x50AA, + 0x50AB, 0x50AD, 0x50AE, 0x50AF, 0x50B0, 0x50B1, 0x50B3, 0x50B4, 0x50B5, + 0x50B6, 0x50B7, 0x50B8, 0x50B9, 0x50BC, 0, 0x50BD, 0x50BE, 0x50BF, + 0x50C0, 0x50C1, 0x50C2, 0x50C3, 0x50C4, 0x50C5, 0x50C6, 0x50C7, 0x50C8, + 0x50C9, 0x50CA, 0x50CB, 0x50CC, 0x50CD, 0x50CE, 0x50D0, 0x50D1, 0x50D2, + 0x50D3, 0x50D4, 0x50D5, 0x50D7, 0x50D8, 0x50D9, 0x50DB, 0x50DC, 0x50DD, + 0x50DE, 0x50DF, 0x50E0, 0x50E1, 0x50E2, 0x50E3, 0x50E4, 0x50E5, 0x50E8, + 0x50E9, 0x50EA, 0x50EB, 0x50EF, 0x50F0, 0x50F1, 0x50F2, 0x50F4, 0x50F6, + 0x50F7, 0x50F8, 0x50F9, 0x50FA, 0x50FC, 0x50FD, 0x50FE, 0x50FF, 0x5100, + 0x5101, 0x5102, 0x5103, 0x5104, 0x5105, 0x5108, 0, 0x5109, 0x510A, + 0x510C, 0x510D, 0x510E, 0x510F, 0x5110, 0x5111, 0x5113, 0x5114, 0x5115, + 0x5116, 0x5117, 0x5118, 0x5119, 0x511A, 0x511B, 0x511C, 0x511D, 0x511E, + 0x511F, 0x5120, 0x5122, 0x5123, 0x5124, 0x5125, 0x5126, 0x5127, 0x5128, + 0x5129, 0x512A, 0x512B, 0x512C, 0x512D, 0x512E, 0x512F, 0x5130, 0x5131, + 0x5132, 0x5133, 0x5134, 0x5135, 0x5136, 0x5137, 0x5138, 0x5139, 0x513A, + 0x513B, 0x513C, 0x513D, 0x513E, 0x5142, 0x5147, 0x514A, 0x514C, 0x514E, + 0x514F, 0x5150, 0x5152, 0x5153, 0x5157, 0x5158, 0x5159, 0x515B, 0x515D, + 0x515E, 0x515F, 0x5160, 0x5161, 0x5163, 0x5164, 0x5166, 0x5167, 0x5169, + 0x516A, 0x516F, 0x5172, 0x517A, 0x517E, 0x517F, 0x5183, 0x5184, 0x5186, + 0x5187, 0x518A, 0x518B, 0x518E, 0x518F, 0x5190, 0x5191, 0x5193, 0x5194, + 0x5198, 0x519A, 0x519D, 0x519E, 0x519F, 0x51A1, 0x51A3, 0x51A6, 0x51A7, + 0x51A8, 0x51A9, 0x51AA, 0x51AD, 0x51AE, 0x51B4, 0x51B8, 0x51B9, 0x51BA, + 0x51BE, 0x51BF, 0x51C1, 0x51C2, 0x51C3, 0x51C5, 0x51C8, 0x51CA, 0x51CD, + 0x51CE, 0x51D0, 0x51D2, 0x51D3, 0x51D4, 0x51D5, 0x51D6, 0x51D7, 0, + 0x51D8, 0x51D9, 0x51DA, 0x51DC, 0x51DE, 0x51DF, 0x51E2, 0x51E3, 0x51E5, + 0x51E6, 0x51E7, 0x51E8, 0x51E9, 0x51EA, 0x51EC, 0x51EE, 0x51F1, 0x51F2, + 0x51F4, 0x51F7, 0x51FE, 0x5204, 0x5205, 0x5209, 0x520B, 0x520C, 0x520F, + 0x5210, 0x5213, 0x5214, 0x5215, 0x521C, 0x521E, 0x521F, 0x5221, 0x5222, + 0x5223, 0x5225, 0x5226, 0x5227, 0x522A, 0x522C, 0x522F, 0x5231, 0x5232, + 0x5234, 0x5235, 0x523C, 0x523E, 0x5244, 0x5245, 0x5246, 0x5247, 0x5248, + 0x5249, 0x524B, 0x524E, 0x524F, 0x5252, 0x5253, 0x5255, 0x5257, 0x5258, + 0, 0x5259, 0x525A, 0x525B, 0x525D, 0x525F, 0x5260, 0x5262, 0x5263, + 0x5264, 0x5266, 0x5268, 0x526B, 0x526C, 0x526D, 0x526E, 0x5270, 0x5271, + 0x5273, 0x5274, 0x5275, 0x5276, 0x5277, 0x5278, 0x5279, 0x527A, 0x527B, + 0x527C, 0x527E, 0x5280, 0x5283, 0x5284, 0x5285, 0x5286, 0x5287, 0x5289, + 0x528A, 0x528B, 0x528C, 0x528D, 0x528E, 0x528F, 0x5291, 0x5292, 0x5294, + 0x5295, 0x5296, 0x5297, 0x5298, 0x5299, 0x529A, 0x529C, 0x52A4, 0x52A5, + 0x52A6, 0x52A7, 0x52AE, 0x52AF, 0x52B0, 0x52B4, 0x52B5, 0x52B6, 0x52B7, + 0x52B8, 0x52B9, 0x52BA, 0x52BB, 0x52BC, 0x52BD, 0x52C0, 0x52C1, 0x52C2, + 0x52C4, 0x52C5, 0x52C6, 0x52C8, 0x52CA, 0x52CC, 0x52CD, 0x52CE, 0x52CF, + 0x52D1, 0x52D3, 0x52D4, 0x52D5, 0x52D7, 0x52D9, 0x52DA, 0x52DB, 0x52DC, + 0x52DD, 0x52DE, 0x52E0, 0x52E1, 0x52E2, 0x52E3, 0x52E5, 0x52E6, 0x52E7, + 0x52E8, 0x52E9, 0x52EA, 0x52EB, 0x52EC, 0x52ED, 0x52EE, 0x52EF, 0x52F1, + 0x52F2, 0x52F3, 0x52F4, 0x52F5, 0x52F6, 0x52F7, 0x52F8, 0x52FB, 0x52FC, + 0x52FD, 0x5301, 0x5302, 0x5303, 0x5304, 0x5307, 0x5309, 0x530A, 0x530B, + 0x530C, 0x530E, 0, 0x5311, 0x5312, 0x5313, 0x5314, 0x5318, 0x531B, + 0x531C, 0x531E, 0x531F, 0x5322, 0x5324, 0x5325, 0x5327, 0x5328, 0x5329, + 0x532B, 0x532C, 0x532D, 0x532F, 0x5330, 0x5331, 0x5332, 0x5333, 0x5334, + 0x5335, 0x5336, 0x5337, 0x5338, 0x533C, 0x533D, 0x5340, 0x5342, 0x5344, + 0x5346, 0x534B, 0x534C, 0x534D, 0x5350, 0x5354, 0x5358, 0x5359, 0x535B, + 0x535D, 0x5365, 0x5368, 0x536A, 0x536C, 0x536D, 0x5372, 0x5376, 0x5379, + 0x537B, 0x537C, 0x537D, 0x537E, 0x5380, 0x5381, 0x5383, 0x5387, 0x5388, + 0x538A, 0x538E, 0x538F, 0, 0x5390, 0x5391, 0x5392, 0x5393, 0x5394, + 0x5396, 0x5397, 0x5399, 0x539B, 0x539C, 0x539E, 0x53A0, 0x53A1, 0x53A4, + 0x53A7, 0x53AA, 0x53AB, 0x53AC, 0x53AD, 0x53AF, 0x53B0, 0x53B1, 0x53B2, + 0x53B3, 0x53B4, 0x53B5, 0x53B7, 0x53B8, 0x53B9, 0x53BA, 0x53BC, 0x53BD, + 0x53BE, 0x53C0, 0x53C3, 0x53C4, 0x53C5, 0x53C6, 0x53C7, 0x53CE, 0x53CF, + 0x53D0, 0x53D2, 0x53D3, 0x53D5, 0x53DA, 0x53DC, 0x53DD, 0x53DE, 0x53E1, + 0x53E2, 0x53E7, 0x53F4, 0x53FA, 0x53FE, 0x53FF, 0x5400, 0x5402, 0x5405, + 0x5407, 0x540B, 0x5414, 0x5418, 0x5419, 0x541A, 0x541C, 0x5422, 0x5424, + 0x5425, 0x542A, 0x5430, 0x5433, 0x5436, 0x5437, 0x543A, 0x543D, 0x543F, + 0x5441, 0x5442, 0x5444, 0x5445, 0x5447, 0x5449, 0x544C, 0x544D, 0x544E, + 0x544F, 0x5451, 0x545A, 0x545D, 0x545E, 0x545F, 0x5460, 0x5461, 0x5463, + 0x5465, 0x5467, 0x5469, 0x546A, 0x546B, 0x546C, 0x546D, 0x546E, 0x546F, + 0x5470, 0x5474, 0x5479, 0x547A, 0x547E, 0x547F, 0x5481, 0x5483, 0x5485, + 0x5487, 0x5488, 0x5489, 0x548A, 0x548D, 0x5491, 0x5493, 0x5497, 0x5498, + 0x549C, 0x549E, 0x549F, 0x54A0, 0x54A1, 0, 0x54A2, 0x54A5, 0x54AE, + 0x54B0, 0x54B2, 0x54B5, 0x54B6, 0x54B7, 0x54B9, 0x54BA, 0x54BC, 0x54BE, + 0x54C3, 0x54C5, 0x54CA, 0x54CB, 0x54D6, 0x54D8, 0x54DB, 0x54E0, 0x54E1, + 0x54E2, 0x54E3, 0x54E4, 0x54EB, 0x54EC, 0x54EF, 0x54F0, 0x54F1, 0x54F4, + 0x54F5, 0x54F6, 0x54F7, 0x54F8, 0x54F9, 0x54FB, 0x54FE, 0x5500, 0x5502, + 0x5503, 0x5504, 0x5505, 0x5508, 0x550A, 0x550B, 0x550C, 0x550D, 0x550E, + 0x5512, 0x5513, 0x5515, 0x5516, 0x5517, 0x5518, 0x5519, 0x551A, 0x551C, + 0x551D, 0x551E, 0x551F, 0x5521, 0x5525, 0x5526, 0, 0x5528, 0x5529, + 0x552B, 0x552D, 0x5532, 0x5534, 0x5535, 0x5536, 0x5538, 0x5539, 0x553A, + 0x553B, 0x553D, 0x5540, 0x5542, 0x5545, 0x5547, 0x5548, 0x554B, 0x554C, + 0x554D, 0x554E, 0x554F, 0x5551, 0x5552, 0x5553, 0x5554, 0x5557, 0x5558, + 0x5559, 0x555A, 0x555B, 0x555D, 0x555E, 0x555F, 0x5560, 0x5562, 0x5563, + 0x5568, 0x5569, 0x556B, 0x556F, 0x5570, 0x5571, 0x5572, 0x5573, 0x5574, + 0x5579, 0x557A, 0x557D, 0x557F, 0x5585, 0x5586, 0x558C, 0x558D, 0x558E, + 0x5590, 0x5592, 0x5593, 0x5595, 0x5596, 0x5597, 0x559A, 0x559B, 0x559E, + 0x55A0, 0x55A1, 0x55A2, 0x55A3, 0x55A4, 0x55A5, 0x55A6, 0x55A8, 0x55A9, + 0x55AA, 0x55AB, 0x55AC, 0x55AD, 0x55AE, 0x55AF, 0x55B0, 0x55B2, 0x55B4, + 0x55B6, 0x55B8, 0x55BA, 0x55BC, 0x55BF, 0x55C0, 0x55C1, 0x55C2, 0x55C3, + 0x55C6, 0x55C7, 0x55C8, 0x55CA, 0x55CB, 0x55CE, 0x55CF, 0x55D0, 0x55D5, + 0x55D7, 0x55D8, 0x55D9, 0x55DA, 0x55DB, 0x55DE, 0x55E0, 0x55E2, 0x55E7, + 0x55E9, 0x55ED, 0x55EE, 0x55F0, 0x55F1, 0x55F4, 0x55F6, 0x55F8, 0x55F9, + 0x55FA, 0x55FB, 0x55FC, 0x55FF, 0x5602, 0x5603, 0x5604, 0x5605, 0, + 0x5606, 0x5607, 0x560A, 0x560B, 0x560D, 0x5610, 0x5611, 0x5612, 0x5613, + 0x5614, 0x5615, 0x5616, 0x5617, 0x5619, 0x561A, 0x561C, 0x561D, 0x5620, + 0x5621, 0x5622, 0x5625, 0x5626, 0x5628, 0x5629, 0x562A, 0x562B, 0x562E, + 0x562F, 0x5630, 0x5633, 0x5635, 0x5637, 0x5638, 0x563A, 0x563C, 0x563D, + 0x563E, 0x5640, 0x5641, 0x5642, 0x5643, 0x5644, 0x5645, 0x5646, 0x5647, + 0x5648, 0x5649, 0x564A, 0x564B, 0x564F, 0x5650, 0x5651, 0x5652, 0x5653, + 0x5655, 0x5656, 0x565A, 0x565B, 0x565D, 0x565E, 0x565F, 0x5660, 0x5661, + 0, 0x5663, 0x5665, 0x5666, 0x5667, 0x566D, 0x566E, 0x566F, 0x5670, + 0x5672, 0x5673, 0x5674, 0x5675, 0x5677, 0x5678, 0x5679, 0x567A, 0x567D, + 0x567E, 0x567F, 0x5680, 0x5681, 0x5682, 0x5683, 0x5684, 0x5687, 0x5688, + 0x5689, 0x568A, 0x568B, 0x568C, 0x568D, 0x5690, 0x5691, 0x5692, 0x5694, + 0x5695, 0x5696, 0x5697, 0x5698, 0x5699, 0x569A, 0x569B, 0x569C, 0x569D, + 0x569E, 0x569F, 0x56A0, 0x56A1, 0x56A2, 0x56A4, 0x56A5, 0x56A6, 0x56A7, + 0x56A8, 0x56A9, 0x56AA, 0x56AB, 0x56AC, 0x56AD, 0x56AE, 0x56B0, 0x56B1, + 0x56B2, 0x56B3, 0x56B4, 0x56B5, 0x56B6, 0x56B8, 0x56B9, 0x56BA, 0x56BB, + 0x56BD, 0x56BE, 0x56BF, 0x56C0, 0x56C1, 0x56C2, 0x56C3, 0x56C4, 0x56C5, + 0x56C6, 0x56C7, 0x56C8, 0x56C9, 0x56CB, 0x56CC, 0x56CD, 0x56CE, 0x56CF, + 0x56D0, 0x56D1, 0x56D2, 0x56D3, 0x56D5, 0x56D6, 0x56D8, 0x56D9, 0x56DC, + 0x56E3, 0x56E5, 0x56E6, 0x56E7, 0x56E8, 0x56E9, 0x56EA, 0x56EC, 0x56EE, + 0x56EF, 0x56F2, 0x56F3, 0x56F6, 0x56F7, 0x56F8, 0x56FB, 0x56FC, 0x5700, + 0x5701, 0x5702, 0x5705, 0x5707, 0x570B, 0x570C, 0x570D, 0x570E, 0x570F, + 0x5710, 0x5711, 0, 0x5712, 0x5713, 0x5714, 0x5715, 0x5716, 0x5717, + 0x5718, 0x5719, 0x571A, 0x571B, 0x571D, 0x571E, 0x5720, 0x5721, 0x5722, + 0x5724, 0x5725, 0x5726, 0x5727, 0x572B, 0x5731, 0x5732, 0x5734, 0x5735, + 0x5736, 0x5737, 0x5738, 0x573C, 0x573D, 0x573F, 0x5741, 0x5743, 0x5744, + 0x5745, 0x5746, 0x5748, 0x5749, 0x574B, 0x5752, 0x5753, 0x5754, 0x5755, + 0x5756, 0x5758, 0x5759, 0x5762, 0x5763, 0x5765, 0x5767, 0x576C, 0x576E, + 0x5770, 0x5771, 0x5772, 0x5774, 0x5775, 0x5778, 0x5779, 0x577A, 0x577D, + 0x577E, 0x577F, 0x5780, 0, 0x5781, 0x5787, 0x5788, 0x5789, 0x578A, + 0x578D, 0x578E, 0x578F, 0x5790, 0x5791, 0x5794, 0x5795, 0x5796, 0x5797, + 0x5798, 0x5799, 0x579A, 0x579C, 0x579D, 0x579E, 0x579F, 0x57A5, 0x57A8, + 0x57AA, 0x57AC, 0x57AF, 0x57B0, 0x57B1, 0x57B3, 0x57B5, 0x57B6, 0x57B7, + 0x57B9, 0x57BA, 0x57BB, 0x57BC, 0x57BD, 0x57BE, 0x57BF, 0x57C0, 0x57C1, + 0x57C4, 0x57C5, 0x57C6, 0x57C7, 0x57C8, 0x57C9, 0x57CA, 0x57CC, 0x57CD, + 0x57D0, 0x57D1, 0x57D3, 0x57D6, 0x57D7, 0x57DB, 0x57DC, 0x57DE, 0x57E1, + 0x57E2, 0x57E3, 0x57E5, 0x57E6, 0x57E7, 0x57E8, 0x57E9, 0x57EA, 0x57EB, + 0x57EC, 0x57EE, 0x57F0, 0x57F1, 0x57F2, 0x57F3, 0x57F5, 0x57F6, 0x57F7, + 0x57FB, 0x57FC, 0x57FE, 0x57FF, 0x5801, 0x5803, 0x5804, 0x5805, 0x5808, + 0x5809, 0x580A, 0x580C, 0x580E, 0x580F, 0x5810, 0x5812, 0x5813, 0x5814, + 0x5816, 0x5817, 0x5818, 0x581A, 0x581B, 0x581C, 0x581D, 0x581F, 0x5822, + 0x5823, 0x5825, 0x5826, 0x5827, 0x5828, 0x5829, 0x582B, 0x582C, 0x582D, + 0x582E, 0x582F, 0x5831, 0x5832, 0x5833, 0x5834, 0x5836, 0x5837, 0x5838, + 0x5839, 0x583A, 0x583B, 0x583C, 0x583D, 0, 0x583E, 0x583F, 0x5840, + 0x5841, 0x5842, 0x5843, 0x5845, 0x5846, 0x5847, 0x5848, 0x5849, 0x584A, + 0x584B, 0x584E, 0x584F, 0x5850, 0x5852, 0x5853, 0x5855, 0x5856, 0x5857, + 0x5859, 0x585A, 0x585B, 0x585C, 0x585D, 0x585F, 0x5860, 0x5861, 0x5862, + 0x5863, 0x5864, 0x5866, 0x5867, 0x5868, 0x5869, 0x586A, 0x586D, 0x586E, + 0x586F, 0x5870, 0x5871, 0x5872, 0x5873, 0x5874, 0x5875, 0x5876, 0x5877, + 0x5878, 0x5879, 0x587A, 0x587B, 0x587C, 0x587D, 0x587F, 0x5882, 0x5884, + 0x5886, 0x5887, 0x5888, 0x588A, 0x588B, 0x588C, 0, 0x588D, 0x588E, + 0x588F, 0x5890, 0x5891, 0x5894, 0x5895, 0x5896, 0x5897, 0x5898, 0x589B, + 0x589C, 0x589D, 0x58A0, 0x58A1, 0x58A2, 0x58A3, 0x58A4, 0x58A5, 0x58A6, + 0x58A7, 0x58AA, 0x58AB, 0x58AC, 0x58AD, 0x58AE, 0x58AF, 0x58B0, 0x58B1, + 0x58B2, 0x58B3, 0x58B4, 0x58B5, 0x58B6, 0x58B7, 0x58B8, 0x58B9, 0x58BA, + 0x58BB, 0x58BD, 0x58BE, 0x58BF, 0x58C0, 0x58C2, 0x58C3, 0x58C4, 0x58C6, + 0x58C7, 0x58C8, 0x58C9, 0x58CA, 0x58CB, 0x58CC, 0x58CD, 0x58CE, 0x58CF, + 0x58D0, 0x58D2, 0x58D3, 0x58D4, 0x58D6, 0x58D7, 0x58D8, 0x58D9, 0x58DA, + 0x58DB, 0x58DC, 0x58DD, 0x58DE, 0x58DF, 0x58E0, 0x58E1, 0x58E2, 0x58E3, + 0x58E5, 0x58E6, 0x58E7, 0x58E8, 0x58E9, 0x58EA, 0x58ED, 0x58EF, 0x58F1, + 0x58F2, 0x58F4, 0x58F5, 0x58F7, 0x58F8, 0x58FA, 0x58FB, 0x58FC, 0x58FD, + 0x58FE, 0x58FF, 0x5900, 0x5901, 0x5903, 0x5905, 0x5906, 0x5908, 0x5909, + 0x590A, 0x590B, 0x590C, 0x590E, 0x5910, 0x5911, 0x5912, 0x5913, 0x5917, + 0x5918, 0x591B, 0x591D, 0x591E, 0x5920, 0x5921, 0x5922, 0x5923, 0x5926, + 0x5928, 0x592C, 0x5930, 0x5932, 0x5933, 0x5935, 0x5936, 0x593B, 0, + 0x593D, 0x593E, 0x593F, 0x5940, 0x5943, 0x5945, 0x5946, 0x594A, 0x594C, + 0x594D, 0x5950, 0x5952, 0x5953, 0x5959, 0x595B, 0x595C, 0x595D, 0x595E, + 0x595F, 0x5961, 0x5963, 0x5964, 0x5966, 0x5967, 0x5968, 0x5969, 0x596A, + 0x596B, 0x596C, 0x596D, 0x596E, 0x596F, 0x5970, 0x5971, 0x5972, 0x5975, + 0x5977, 0x597A, 0x597B, 0x597C, 0x597E, 0x597F, 0x5980, 0x5985, 0x5989, + 0x598B, 0x598C, 0x598E, 0x598F, 0x5990, 0x5991, 0x5994, 0x5995, 0x5998, + 0x599A, 0x599B, 0x599C, 0x599D, 0x599F, 0x59A0, 0x59A1, 0x59A2, 0x59A6, + 0, 0x59A7, 0x59AC, 0x59AD, 0x59B0, 0x59B1, 0x59B3, 0x59B4, 0x59B5, + 0x59B6, 0x59B7, 0x59B8, 0x59BA, 0x59BC, 0x59BD, 0x59BF, 0x59C0, 0x59C1, + 0x59C2, 0x59C3, 0x59C4, 0x59C5, 0x59C7, 0x59C8, 0x59C9, 0x59CC, 0x59CD, + 0x59CE, 0x59CF, 0x59D5, 0x59D6, 0x59D9, 0x59DB, 0x59DE, 0x59DF, 0x59E0, + 0x59E1, 0x59E2, 0x59E4, 0x59E6, 0x59E7, 0x59E9, 0x59EA, 0x59EB, 0x59ED, + 0x59EE, 0x59EF, 0x59F0, 0x59F1, 0x59F2, 0x59F3, 0x59F4, 0x59F5, 0x59F6, + 0x59F7, 0x59F8, 0x59FA, 0x59FC, 0x59FD, 0x59FE, 0x5A00, 0x5A02, 0x5A0A, + 0x5A0B, 0x5A0D, 0x5A0E, 0x5A0F, 0x5A10, 0x5A12, 0x5A14, 0x5A15, 0x5A16, + 0x5A17, 0x5A19, 0x5A1A, 0x5A1B, 0x5A1D, 0x5A1E, 0x5A21, 0x5A22, 0x5A24, + 0x5A26, 0x5A27, 0x5A28, 0x5A2A, 0x5A2B, 0x5A2C, 0x5A2D, 0x5A2E, 0x5A2F, + 0x5A30, 0x5A33, 0x5A35, 0x5A37, 0x5A38, 0x5A39, 0x5A3A, 0x5A3B, 0x5A3D, + 0x5A3E, 0x5A3F, 0x5A41, 0x5A42, 0x5A43, 0x5A44, 0x5A45, 0x5A47, 0x5A48, + 0x5A4B, 0x5A4C, 0x5A4D, 0x5A4E, 0x5A4F, 0x5A50, 0x5A51, 0x5A52, 0x5A53, + 0x5A54, 0x5A56, 0x5A57, 0x5A58, 0x5A59, 0x5A5B, 0x5A5C, 0x5A5D, 0x5A5E, + 0x5A5F, 0x5A60, 0, 0x5A61, 0x5A63, 0x5A64, 0x5A65, 0x5A66, 0x5A68, + 0x5A69, 0x5A6B, 0x5A6C, 0x5A6D, 0x5A6E, 0x5A6F, 0x5A70, 0x5A71, 0x5A72, + 0x5A73, 0x5A78, 0x5A79, 0x5A7B, 0x5A7C, 0x5A7D, 0x5A7E, 0x5A80, 0x5A81, + 0x5A82, 0x5A83, 0x5A84, 0x5A85, 0x5A86, 0x5A87, 0x5A88, 0x5A89, 0x5A8A, + 0x5A8B, 0x5A8C, 0x5A8D, 0x5A8E, 0x5A8F, 0x5A90, 0x5A91, 0x5A93, 0x5A94, + 0x5A95, 0x5A96, 0x5A97, 0x5A98, 0x5A99, 0x5A9C, 0x5A9D, 0x5A9E, 0x5A9F, + 0x5AA0, 0x5AA1, 0x5AA2, 0x5AA3, 0x5AA4, 0x5AA5, 0x5AA6, 0x5AA7, 0x5AA8, + 0x5AA9, 0x5AAB, 0x5AAC, 0, 0x5AAD, 0x5AAE, 0x5AAF, 0x5AB0, 0x5AB1, + 0x5AB4, 0x5AB6, 0x5AB7, 0x5AB9, 0x5ABA, 0x5ABB, 0x5ABC, 0x5ABD, 0x5ABF, + 0x5AC0, 0x5AC3, 0x5AC4, 0x5AC5, 0x5AC6, 0x5AC7, 0x5AC8, 0x5ACA, 0x5ACB, + 0x5ACD, 0x5ACE, 0x5ACF, 0x5AD0, 0x5AD1, 0x5AD3, 0x5AD5, 0x5AD7, 0x5AD9, + 0x5ADA, 0x5ADB, 0x5ADD, 0x5ADE, 0x5ADF, 0x5AE2, 0x5AE4, 0x5AE5, 0x5AE7, + 0x5AE8, 0x5AEA, 0x5AEC, 0x5AED, 0x5AEE, 0x5AEF, 0x5AF0, 0x5AF2, 0x5AF3, + 0x5AF4, 0x5AF5, 0x5AF6, 0x5AF7, 0x5AF8, 0x5AF9, 0x5AFA, 0x5AFB, 0x5AFC, + 0x5AFD, 0x5AFE, 0x5AFF, 0x5B00, 0x5B01, 0x5B02, 0x5B03, 0x5B04, 0x5B05, + 0x5B06, 0x5B07, 0x5B08, 0x5B0A, 0x5B0B, 0x5B0C, 0x5B0D, 0x5B0E, 0x5B0F, + 0x5B10, 0x5B11, 0x5B12, 0x5B13, 0x5B14, 0x5B15, 0x5B18, 0x5B19, 0x5B1A, + 0x5B1B, 0x5B1C, 0x5B1D, 0x5B1E, 0x5B1F, 0x5B20, 0x5B21, 0x5B22, 0x5B23, + 0x5B24, 0x5B25, 0x5B26, 0x5B27, 0x5B28, 0x5B29, 0x5B2A, 0x5B2B, 0x5B2C, + 0x5B2D, 0x5B2E, 0x5B2F, 0x5B30, 0x5B31, 0x5B33, 0x5B35, 0x5B36, 0x5B38, + 0x5B39, 0x5B3A, 0x5B3B, 0x5B3C, 0x5B3D, 0x5B3E, 0x5B3F, 0x5B41, 0x5B42, + 0x5B43, 0x5B44, 0x5B45, 0x5B46, 0x5B47, 0, 0x5B48, 0x5B49, 0x5B4A, + 0x5B4B, 0x5B4C, 0x5B4D, 0x5B4E, 0x5B4F, 0x5B52, 0x5B56, 0x5B5E, 0x5B60, + 0x5B61, 0x5B67, 0x5B68, 0x5B6B, 0x5B6D, 0x5B6E, 0x5B6F, 0x5B72, 0x5B74, + 0x5B76, 0x5B77, 0x5B78, 0x5B79, 0x5B7B, 0x5B7C, 0x5B7E, 0x5B7F, 0x5B82, + 0x5B86, 0x5B8A, 0x5B8D, 0x5B8E, 0x5B90, 0x5B91, 0x5B92, 0x5B94, 0x5B96, + 0x5B9F, 0x5BA7, 0x5BA8, 0x5BA9, 0x5BAC, 0x5BAD, 0x5BAE, 0x5BAF, 0x5BB1, + 0x5BB2, 0x5BB7, 0x5BBA, 0x5BBB, 0x5BBC, 0x5BC0, 0x5BC1, 0x5BC3, 0x5BC8, + 0x5BC9, 0x5BCA, 0x5BCB, 0x5BCD, 0x5BCE, 0x5BCF, 0, 0x5BD1, 0x5BD4, + 0x5BD5, 0x5BD6, 0x5BD7, 0x5BD8, 0x5BD9, 0x5BDA, 0x5BDB, 0x5BDC, 0x5BE0, + 0x5BE2, 0x5BE3, 0x5BE6, 0x5BE7, 0x5BE9, 0x5BEA, 0x5BEB, 0x5BEC, 0x5BED, + 0x5BEF, 0x5BF1, 0x5BF2, 0x5BF3, 0x5BF4, 0x5BF5, 0x5BF6, 0x5BF7, 0x5BFD, + 0x5BFE, 0x5C00, 0x5C02, 0x5C03, 0x5C05, 0x5C07, 0x5C08, 0x5C0B, 0x5C0C, + 0x5C0D, 0x5C0E, 0x5C10, 0x5C12, 0x5C13, 0x5C17, 0x5C19, 0x5C1B, 0x5C1E, + 0x5C1F, 0x5C20, 0x5C21, 0x5C23, 0x5C26, 0x5C28, 0x5C29, 0x5C2A, 0x5C2B, + 0x5C2D, 0x5C2E, 0x5C2F, 0x5C30, 0x5C32, 0x5C33, 0x5C35, 0x5C36, 0x5C37, + 0x5C43, 0x5C44, 0x5C46, 0x5C47, 0x5C4C, 0x5C4D, 0x5C52, 0x5C53, 0x5C54, + 0x5C56, 0x5C57, 0x5C58, 0x5C5A, 0x5C5B, 0x5C5C, 0x5C5D, 0x5C5F, 0x5C62, + 0x5C64, 0x5C67, 0x5C68, 0x5C69, 0x5C6A, 0x5C6B, 0x5C6C, 0x5C6D, 0x5C70, + 0x5C72, 0x5C73, 0x5C74, 0x5C75, 0x5C76, 0x5C77, 0x5C78, 0x5C7B, 0x5C7C, + 0x5C7D, 0x5C7E, 0x5C80, 0x5C83, 0x5C84, 0x5C85, 0x5C86, 0x5C87, 0x5C89, + 0x5C8A, 0x5C8B, 0x5C8E, 0x5C8F, 0x5C92, 0x5C93, 0x5C95, 0x5C9D, 0x5C9E, + 0x5C9F, 0x5CA0, 0x5CA1, 0x5CA4, 0x5CA5, 0x5CA6, 0x5CA7, 0x5CA8, 0, + 0x5CAA, 0x5CAE, 0x5CAF, 0x5CB0, 0x5CB2, 0x5CB4, 0x5CB6, 0x5CB9, 0x5CBA, + 0x5CBB, 0x5CBC, 0x5CBE, 0x5CC0, 0x5CC2, 0x5CC3, 0x5CC5, 0x5CC6, 0x5CC7, + 0x5CC8, 0x5CC9, 0x5CCA, 0x5CCC, 0x5CCD, 0x5CCE, 0x5CCF, 0x5CD0, 0x5CD1, + 0x5CD3, 0x5CD4, 0x5CD5, 0x5CD6, 0x5CD7, 0x5CD8, 0x5CDA, 0x5CDB, 0x5CDC, + 0x5CDD, 0x5CDE, 0x5CDF, 0x5CE0, 0x5CE2, 0x5CE3, 0x5CE7, 0x5CE9, 0x5CEB, + 0x5CEC, 0x5CEE, 0x5CEF, 0x5CF1, 0x5CF2, 0x5CF3, 0x5CF4, 0x5CF5, 0x5CF6, + 0x5CF7, 0x5CF8, 0x5CF9, 0x5CFA, 0x5CFC, 0x5CFD, 0x5CFE, 0x5CFF, 0x5D00, + 0, 0x5D01, 0x5D04, 0x5D05, 0x5D08, 0x5D09, 0x5D0A, 0x5D0B, 0x5D0C, + 0x5D0D, 0x5D0F, 0x5D10, 0x5D11, 0x5D12, 0x5D13, 0x5D15, 0x5D17, 0x5D18, + 0x5D19, 0x5D1A, 0x5D1C, 0x5D1D, 0x5D1F, 0x5D20, 0x5D21, 0x5D22, 0x5D23, + 0x5D25, 0x5D28, 0x5D2A, 0x5D2B, 0x5D2C, 0x5D2F, 0x5D30, 0x5D31, 0x5D32, + 0x5D33, 0x5D35, 0x5D36, 0x5D37, 0x5D38, 0x5D39, 0x5D3A, 0x5D3B, 0x5D3C, + 0x5D3F, 0x5D40, 0x5D41, 0x5D42, 0x5D43, 0x5D44, 0x5D45, 0x5D46, 0x5D48, + 0x5D49, 0x5D4D, 0x5D4E, 0x5D4F, 0x5D50, 0x5D51, 0x5D52, 0x5D53, 0x5D54, + 0x5D55, 0x5D56, 0x5D57, 0x5D59, 0x5D5A, 0x5D5C, 0x5D5E, 0x5D5F, 0x5D60, + 0x5D61, 0x5D62, 0x5D63, 0x5D64, 0x5D65, 0x5D66, 0x5D67, 0x5D68, 0x5D6A, + 0x5D6D, 0x5D6E, 0x5D70, 0x5D71, 0x5D72, 0x5D73, 0x5D75, 0x5D76, 0x5D77, + 0x5D78, 0x5D79, 0x5D7A, 0x5D7B, 0x5D7C, 0x5D7D, 0x5D7E, 0x5D7F, 0x5D80, + 0x5D81, 0x5D83, 0x5D84, 0x5D85, 0x5D86, 0x5D87, 0x5D88, 0x5D89, 0x5D8A, + 0x5D8B, 0x5D8C, 0x5D8D, 0x5D8E, 0x5D8F, 0x5D90, 0x5D91, 0x5D92, 0x5D93, + 0x5D94, 0x5D95, 0x5D96, 0x5D97, 0x5D98, 0x5D9A, 0x5D9B, 0x5D9C, 0x5D9E, + 0x5D9F, 0x5DA0, 0, 0x5DA1, 0x5DA2, 0x5DA3, 0x5DA4, 0x5DA5, 0x5DA6, + 0x5DA7, 0x5DA8, 0x5DA9, 0x5DAA, 0x5DAB, 0x5DAC, 0x5DAD, 0x5DAE, 0x5DAF, + 0x5DB0, 0x5DB1, 0x5DB2, 0x5DB3, 0x5DB4, 0x5DB5, 0x5DB6, 0x5DB8, 0x5DB9, + 0x5DBA, 0x5DBB, 0x5DBC, 0x5DBD, 0x5DBE, 0x5DBF, 0x5DC0, 0x5DC1, 0x5DC2, + 0x5DC3, 0x5DC4, 0x5DC6, 0x5DC7, 0x5DC8, 0x5DC9, 0x5DCA, 0x5DCB, 0x5DCC, + 0x5DCE, 0x5DCF, 0x5DD0, 0x5DD1, 0x5DD2, 0x5DD3, 0x5DD4, 0x5DD5, 0x5DD6, + 0x5DD7, 0x5DD8, 0x5DD9, 0x5DDA, 0x5DDC, 0x5DDF, 0x5DE0, 0x5DE3, 0x5DE4, + 0x5DEA, 0x5DEC, 0x5DED, 0, 0x5DF0, 0x5DF5, 0x5DF6, 0x5DF8, 0x5DF9, + 0x5DFA, 0x5DFB, 0x5DFC, 0x5DFF, 0x5E00, 0x5E04, 0x5E07, 0x5E09, 0x5E0A, + 0x5E0B, 0x5E0D, 0x5E0E, 0x5E12, 0x5E13, 0x5E17, 0x5E1E, 0x5E1F, 0x5E20, + 0x5E21, 0x5E22, 0x5E23, 0x5E24, 0x5E25, 0x5E28, 0x5E29, 0x5E2A, 0x5E2B, + 0x5E2C, 0x5E2F, 0x5E30, 0x5E32, 0x5E33, 0x5E34, 0x5E35, 0x5E36, 0x5E39, + 0x5E3A, 0x5E3E, 0x5E3F, 0x5E40, 0x5E41, 0x5E43, 0x5E46, 0x5E47, 0x5E48, + 0x5E49, 0x5E4A, 0x5E4B, 0x5E4D, 0x5E4E, 0x5E4F, 0x5E50, 0x5E51, 0x5E52, + 0x5E53, 0x5E56, 0x5E57, 0x5E58, 0x5E59, 0x5E5A, 0x5E5C, 0x5E5D, 0x5E5F, + 0x5E60, 0x5E63, 0x5E64, 0x5E65, 0x5E66, 0x5E67, 0x5E68, 0x5E69, 0x5E6A, + 0x5E6B, 0x5E6C, 0x5E6D, 0x5E6E, 0x5E6F, 0x5E70, 0x5E71, 0x5E75, 0x5E77, + 0x5E79, 0x5E7E, 0x5E81, 0x5E82, 0x5E83, 0x5E85, 0x5E88, 0x5E89, 0x5E8C, + 0x5E8D, 0x5E8E, 0x5E92, 0x5E98, 0x5E9B, 0x5E9D, 0x5EA1, 0x5EA2, 0x5EA3, + 0x5EA4, 0x5EA8, 0x5EA9, 0x5EAA, 0x5EAB, 0x5EAC, 0x5EAE, 0x5EAF, 0x5EB0, + 0x5EB1, 0x5EB2, 0x5EB4, 0x5EBA, 0x5EBB, 0x5EBC, 0x5EBD, 0x5EBF, 0x5EC0, + 0x5EC1, 0x5EC2, 0x5EC3, 0x5EC4, 0x5EC5, 0, 0x5EC6, 0x5EC7, 0x5EC8, + 0x5ECB, 0x5ECC, 0x5ECD, 0x5ECE, 0x5ECF, 0x5ED0, 0x5ED4, 0x5ED5, 0x5ED7, + 0x5ED8, 0x5ED9, 0x5EDA, 0x5EDC, 0x5EDD, 0x5EDE, 0x5EDF, 0x5EE0, 0x5EE1, + 0x5EE2, 0x5EE3, 0x5EE4, 0x5EE5, 0x5EE6, 0x5EE7, 0x5EE9, 0x5EEB, 0x5EEC, + 0x5EED, 0x5EEE, 0x5EEF, 0x5EF0, 0x5EF1, 0x5EF2, 0x5EF3, 0x5EF5, 0x5EF8, + 0x5EF9, 0x5EFB, 0x5EFC, 0x5EFD, 0x5F05, 0x5F06, 0x5F07, 0x5F09, 0x5F0C, + 0x5F0D, 0x5F0E, 0x5F10, 0x5F12, 0x5F14, 0x5F16, 0x5F19, 0x5F1A, 0x5F1C, + 0x5F1D, 0x5F1E, 0x5F21, 0x5F22, 0x5F23, 0x5F24, 0, 0x5F28, 0x5F2B, + 0x5F2C, 0x5F2E, 0x5F30, 0x5F32, 0x5F33, 0x5F34, 0x5F35, 0x5F36, 0x5F37, + 0x5F38, 0x5F3B, 0x5F3D, 0x5F3E, 0x5F3F, 0x5F41, 0x5F42, 0x5F43, 0x5F44, + 0x5F45, 0x5F46, 0x5F47, 0x5F48, 0x5F49, 0x5F4A, 0x5F4B, 0x5F4C, 0x5F4D, + 0x5F4E, 0x5F4F, 0x5F51, 0x5F54, 0x5F59, 0x5F5A, 0x5F5B, 0x5F5C, 0x5F5E, + 0x5F5F, 0x5F60, 0x5F63, 0x5F65, 0x5F67, 0x5F68, 0x5F6B, 0x5F6E, 0x5F6F, + 0x5F72, 0x5F74, 0x5F75, 0x5F76, 0x5F78, 0x5F7A, 0x5F7D, 0x5F7E, 0x5F7F, + 0x5F83, 0x5F86, 0x5F8D, 0x5F8E, 0x5F8F, 0x5F91, 0x5F93, 0x5F94, 0x5F96, + 0x5F9A, 0x5F9B, 0x5F9D, 0x5F9E, 0x5F9F, 0x5FA0, 0x5FA2, 0x5FA3, 0x5FA4, + 0x5FA5, 0x5FA6, 0x5FA7, 0x5FA9, 0x5FAB, 0x5FAC, 0x5FAF, 0x5FB0, 0x5FB1, + 0x5FB2, 0x5FB3, 0x5FB4, 0x5FB6, 0x5FB8, 0x5FB9, 0x5FBA, 0x5FBB, 0x5FBE, + 0x5FBF, 0x5FC0, 0x5FC1, 0x5FC2, 0x5FC7, 0x5FC8, 0x5FCA, 0x5FCB, 0x5FCE, + 0x5FD3, 0x5FD4, 0x5FD5, 0x5FDA, 0x5FDB, 0x5FDC, 0x5FDE, 0x5FDF, 0x5FE2, + 0x5FE3, 0x5FE5, 0x5FE6, 0x5FE8, 0x5FE9, 0x5FEC, 0x5FEF, 0x5FF0, 0x5FF2, + 0x5FF3, 0x5FF4, 0x5FF6, 0x5FF7, 0x5FF9, 0x5FFA, 0x5FFC, 0x6007, 0, + 0x6008, 0x6009, 0x600B, 0x600C, 0x6010, 0x6011, 0x6013, 0x6017, 0x6018, + 0x601A, 0x601E, 0x601F, 0x6022, 0x6023, 0x6024, 0x602C, 0x602D, 0x602E, + 0x6030, 0x6031, 0x6032, 0x6033, 0x6034, 0x6036, 0x6037, 0x6038, 0x6039, + 0x603A, 0x603D, 0x603E, 0x6040, 0x6044, 0x6045, 0x6046, 0x6047, 0x6048, + 0x6049, 0x604A, 0x604C, 0x604E, 0x604F, 0x6051, 0x6053, 0x6054, 0x6056, + 0x6057, 0x6058, 0x605B, 0x605C, 0x605E, 0x605F, 0x6060, 0x6061, 0x6065, + 0x6066, 0x606E, 0x6071, 0x6072, 0x6074, 0x6075, 0x6077, 0x607E, 0x6080, + 0, 0x6081, 0x6082, 0x6085, 0x6086, 0x6087, 0x6088, 0x608A, 0x608B, + 0x608E, 0x608F, 0x6090, 0x6091, 0x6093, 0x6095, 0x6097, 0x6098, 0x6099, + 0x609C, 0x609E, 0x60A1, 0x60A2, 0x60A4, 0x60A5, 0x60A7, 0x60A9, 0x60AA, + 0x60AE, 0x60B0, 0x60B3, 0x60B5, 0x60B6, 0x60B7, 0x60B9, 0x60BA, 0x60BD, + 0x60BE, 0x60BF, 0x60C0, 0x60C1, 0x60C2, 0x60C3, 0x60C4, 0x60C7, 0x60C8, + 0x60C9, 0x60CC, 0x60CD, 0x60CE, 0x60CF, 0x60D0, 0x60D2, 0x60D3, 0x60D4, + 0x60D6, 0x60D7, 0x60D9, 0x60DB, 0x60DE, 0x60E1, 0x60E2, 0x60E3, 0x60E4, + 0x60E5, 0x60EA, 0x60F1, 0x60F2, 0x60F5, 0x60F7, 0x60F8, 0x60FB, 0x60FC, + 0x60FD, 0x60FE, 0x60FF, 0x6102, 0x6103, 0x6104, 0x6105, 0x6107, 0x610A, + 0x610B, 0x610C, 0x6110, 0x6111, 0x6112, 0x6113, 0x6114, 0x6116, 0x6117, + 0x6118, 0x6119, 0x611B, 0x611C, 0x611D, 0x611E, 0x6121, 0x6122, 0x6125, + 0x6128, 0x6129, 0x612A, 0x612C, 0x612D, 0x612E, 0x612F, 0x6130, 0x6131, + 0x6132, 0x6133, 0x6134, 0x6135, 0x6136, 0x6137, 0x6138, 0x6139, 0x613A, + 0x613B, 0x613C, 0x613D, 0x613E, 0x6140, 0x6141, 0x6142, 0x6143, 0x6144, + 0x6145, 0x6146, 0, 0x6147, 0x6149, 0x614B, 0x614D, 0x614F, 0x6150, + 0x6152, 0x6153, 0x6154, 0x6156, 0x6157, 0x6158, 0x6159, 0x615A, 0x615B, + 0x615C, 0x615E, 0x615F, 0x6160, 0x6161, 0x6163, 0x6164, 0x6165, 0x6166, + 0x6169, 0x616A, 0x616B, 0x616C, 0x616D, 0x616E, 0x616F, 0x6171, 0x6172, + 0x6173, 0x6174, 0x6176, 0x6178, 0x6179, 0x617A, 0x617B, 0x617C, 0x617D, + 0x617E, 0x617F, 0x6180, 0x6181, 0x6182, 0x6183, 0x6184, 0x6185, 0x6186, + 0x6187, 0x6188, 0x6189, 0x618A, 0x618C, 0x618D, 0x618F, 0x6190, 0x6191, + 0x6192, 0x6193, 0x6195, 0, 0x6196, 0x6197, 0x6198, 0x6199, 0x619A, + 0x619B, 0x619C, 0x619E, 0x619F, 0x61A0, 0x61A1, 0x61A2, 0x61A3, 0x61A4, + 0x61A5, 0x61A6, 0x61AA, 0x61AB, 0x61AD, 0x61AE, 0x61AF, 0x61B0, 0x61B1, + 0x61B2, 0x61B3, 0x61B4, 0x61B5, 0x61B6, 0x61B8, 0x61B9, 0x61BA, 0x61BB, + 0x61BC, 0x61BD, 0x61BF, 0x61C0, 0x61C1, 0x61C3, 0x61C4, 0x61C5, 0x61C6, + 0x61C7, 0x61C9, 0x61CC, 0x61CD, 0x61CE, 0x61CF, 0x61D0, 0x61D3, 0x61D5, + 0x61D6, 0x61D7, 0x61D8, 0x61D9, 0x61DA, 0x61DB, 0x61DC, 0x61DD, 0x61DE, + 0x61DF, 0x61E0, 0x61E1, 0x61E2, 0x61E3, 0x61E4, 0x61E5, 0x61E7, 0x61E8, + 0x61E9, 0x61EA, 0x61EB, 0x61EC, 0x61ED, 0x61EE, 0x61EF, 0x61F0, 0x61F1, + 0x61F2, 0x61F3, 0x61F4, 0x61F6, 0x61F7, 0x61F8, 0x61F9, 0x61FA, 0x61FB, + 0x61FC, 0x61FD, 0x61FE, 0x6200, 0x6201, 0x6202, 0x6203, 0x6204, 0x6205, + 0x6207, 0x6209, 0x6213, 0x6214, 0x6219, 0x621C, 0x621D, 0x621E, 0x6220, + 0x6223, 0x6226, 0x6227, 0x6228, 0x6229, 0x622B, 0x622D, 0x622F, 0x6230, + 0x6231, 0x6232, 0x6235, 0x6236, 0x6238, 0x6239, 0x623A, 0x623B, 0x623C, + 0x6242, 0x6244, 0x6245, 0x6246, 0x624A, 0, 0x624F, 0x6250, 0x6255, + 0x6256, 0x6257, 0x6259, 0x625A, 0x625C, 0x625D, 0x625E, 0x625F, 0x6260, + 0x6261, 0x6262, 0x6264, 0x6265, 0x6268, 0x6271, 0x6272, 0x6274, 0x6275, + 0x6277, 0x6278, 0x627A, 0x627B, 0x627D, 0x6281, 0x6282, 0x6283, 0x6285, + 0x6286, 0x6287, 0x6288, 0x628B, 0x628C, 0x628D, 0x628E, 0x628F, 0x6290, + 0x6294, 0x6299, 0x629C, 0x629D, 0x629E, 0x62A3, 0x62A6, 0x62A7, 0x62A9, + 0x62AA, 0x62AD, 0x62AE, 0x62AF, 0x62B0, 0x62B2, 0x62B3, 0x62B4, 0x62B6, + 0x62B7, 0x62B8, 0x62BA, 0x62BE, 0x62C0, 0x62C1, 0, 0x62C3, 0x62CB, + 0x62CF, 0x62D1, 0x62D5, 0x62DD, 0x62DE, 0x62E0, 0x62E1, 0x62E4, 0x62EA, + 0x62EB, 0x62F0, 0x62F2, 0x62F5, 0x62F8, 0x62F9, 0x62FA, 0x62FB, 0x6300, + 0x6303, 0x6304, 0x6305, 0x6306, 0x630A, 0x630B, 0x630C, 0x630D, 0x630F, + 0x6310, 0x6312, 0x6313, 0x6314, 0x6315, 0x6317, 0x6318, 0x6319, 0x631C, + 0x6326, 0x6327, 0x6329, 0x632C, 0x632D, 0x632E, 0x6330, 0x6331, 0x6333, + 0x6334, 0x6335, 0x6336, 0x6337, 0x6338, 0x633B, 0x633C, 0x633E, 0x633F, + 0x6340, 0x6341, 0x6344, 0x6347, 0x6348, 0x634A, 0x6351, 0x6352, 0x6353, + 0x6354, 0x6356, 0x6357, 0x6358, 0x6359, 0x635A, 0x635B, 0x635C, 0x635D, + 0x6360, 0x6364, 0x6365, 0x6366, 0x6368, 0x636A, 0x636B, 0x636C, 0x636F, + 0x6370, 0x6372, 0x6373, 0x6374, 0x6375, 0x6378, 0x6379, 0x637C, 0x637D, + 0x637E, 0x637F, 0x6381, 0x6383, 0x6384, 0x6385, 0x6386, 0x638B, 0x638D, + 0x6391, 0x6393, 0x6394, 0x6395, 0x6397, 0x6399, 0x639A, 0x639B, 0x639C, + 0x639D, 0x639E, 0x639F, 0x63A1, 0x63A4, 0x63A6, 0x63AB, 0x63AF, 0x63B1, + 0x63B2, 0x63B5, 0x63B6, 0x63B9, 0x63BB, 0x63BD, 0x63BF, 0x63C0, 0, + 0x63C1, 0x63C2, 0x63C3, 0x63C5, 0x63C7, 0x63C8, 0x63CA, 0x63CB, 0x63CC, + 0x63D1, 0x63D3, 0x63D4, 0x63D5, 0x63D7, 0x63D8, 0x63D9, 0x63DA, 0x63DB, + 0x63DC, 0x63DD, 0x63DF, 0x63E2, 0x63E4, 0x63E5, 0x63E6, 0x63E7, 0x63E8, + 0x63EB, 0x63EC, 0x63EE, 0x63EF, 0x63F0, 0x63F1, 0x63F3, 0x63F5, 0x63F7, + 0x63F9, 0x63FA, 0x63FB, 0x63FC, 0x63FE, 0x6403, 0x6404, 0x6406, 0x6407, + 0x6408, 0x6409, 0x640A, 0x640D, 0x640E, 0x6411, 0x6412, 0x6415, 0x6416, + 0x6417, 0x6418, 0x6419, 0x641A, 0x641D, 0x641F, 0x6422, 0x6423, 0x6424, + 0, 0x6425, 0x6427, 0x6428, 0x6429, 0x642B, 0x642E, 0x642F, 0x6430, + 0x6431, 0x6432, 0x6433, 0x6435, 0x6436, 0x6437, 0x6438, 0x6439, 0x643B, + 0x643C, 0x643E, 0x6440, 0x6442, 0x6443, 0x6449, 0x644B, 0x644C, 0x644D, + 0x644E, 0x644F, 0x6450, 0x6451, 0x6453, 0x6455, 0x6456, 0x6457, 0x6459, + 0x645A, 0x645B, 0x645C, 0x645D, 0x645F, 0x6460, 0x6461, 0x6462, 0x6463, + 0x6464, 0x6465, 0x6466, 0x6468, 0x646A, 0x646B, 0x646C, 0x646E, 0x646F, + 0x6470, 0x6471, 0x6472, 0x6473, 0x6474, 0x6475, 0x6476, 0x6477, 0x647B, + 0x647C, 0x647D, 0x647E, 0x647F, 0x6480, 0x6481, 0x6483, 0x6486, 0x6488, + 0x6489, 0x648A, 0x648B, 0x648C, 0x648D, 0x648E, 0x648F, 0x6490, 0x6493, + 0x6494, 0x6497, 0x6498, 0x649A, 0x649B, 0x649C, 0x649D, 0x649F, 0x64A0, + 0x64A1, 0x64A2, 0x64A3, 0x64A5, 0x64A6, 0x64A7, 0x64A8, 0x64AA, 0x64AB, + 0x64AF, 0x64B1, 0x64B2, 0x64B3, 0x64B4, 0x64B6, 0x64B9, 0x64BB, 0x64BD, + 0x64BE, 0x64BF, 0x64C1, 0x64C3, 0x64C4, 0x64C6, 0x64C7, 0x64C8, 0x64C9, + 0x64CA, 0x64CB, 0x64CC, 0x64CF, 0x64D1, 0x64D3, 0x64D4, 0x64D5, 0x64D6, + 0x64D9, 0x64DA, 0, 0x64DB, 0x64DC, 0x64DD, 0x64DF, 0x64E0, 0x64E1, + 0x64E3, 0x64E5, 0x64E7, 0x64E8, 0x64E9, 0x64EA, 0x64EB, 0x64EC, 0x64ED, + 0x64EE, 0x64EF, 0x64F0, 0x64F1, 0x64F2, 0x64F3, 0x64F4, 0x64F5, 0x64F6, + 0x64F7, 0x64F8, 0x64F9, 0x64FA, 0x64FB, 0x64FC, 0x64FD, 0x64FE, 0x64FF, + 0x6501, 0x6502, 0x6503, 0x6504, 0x6505, 0x6506, 0x6507, 0x6508, 0x650A, + 0x650B, 0x650C, 0x650D, 0x650E, 0x650F, 0x6510, 0x6511, 0x6513, 0x6514, + 0x6515, 0x6516, 0x6517, 0x6519, 0x651A, 0x651B, 0x651C, 0x651D, 0x651E, + 0x651F, 0x6520, 0x6521, 0, 0x6522, 0x6523, 0x6524, 0x6526, 0x6527, + 0x6528, 0x6529, 0x652A, 0x652C, 0x652D, 0x6530, 0x6531, 0x6532, 0x6533, + 0x6537, 0x653A, 0x653C, 0x653D, 0x6540, 0x6541, 0x6542, 0x6543, 0x6544, + 0x6546, 0x6547, 0x654A, 0x654B, 0x654D, 0x654E, 0x6550, 0x6552, 0x6553, + 0x6554, 0x6557, 0x6558, 0x655A, 0x655C, 0x655F, 0x6560, 0x6561, 0x6564, + 0x6565, 0x6567, 0x6568, 0x6569, 0x656A, 0x656D, 0x656E, 0x656F, 0x6571, + 0x6573, 0x6575, 0x6576, 0x6578, 0x6579, 0x657A, 0x657B, 0x657C, 0x657D, + 0x657E, 0x657F, 0x6580, 0x6581, 0x6582, 0x6583, 0x6584, 0x6585, 0x6586, + 0x6588, 0x6589, 0x658A, 0x658D, 0x658E, 0x658F, 0x6592, 0x6594, 0x6595, + 0x6596, 0x6598, 0x659A, 0x659D, 0x659E, 0x65A0, 0x65A2, 0x65A3, 0x65A6, + 0x65A8, 0x65AA, 0x65AC, 0x65AE, 0x65B1, 0x65B2, 0x65B3, 0x65B4, 0x65B5, + 0x65B6, 0x65B7, 0x65B8, 0x65BA, 0x65BB, 0x65BE, 0x65BF, 0x65C0, 0x65C2, + 0x65C7, 0x65C8, 0x65C9, 0x65CA, 0x65CD, 0x65D0, 0x65D1, 0x65D3, 0x65D4, + 0x65D5, 0x65D8, 0x65D9, 0x65DA, 0x65DB, 0x65DC, 0x65DD, 0x65DE, 0x65DF, + 0x65E1, 0x65E3, 0x65E4, 0x65EA, 0x65EB, 0, 0x65F2, 0x65F3, 0x65F4, + 0x65F5, 0x65F8, 0x65F9, 0x65FB, 0x65FC, 0x65FD, 0x65FE, 0x65FF, 0x6601, + 0x6604, 0x6605, 0x6607, 0x6608, 0x6609, 0x660B, 0x660D, 0x6610, 0x6611, + 0x6612, 0x6616, 0x6617, 0x6618, 0x661A, 0x661B, 0x661C, 0x661E, 0x6621, + 0x6622, 0x6623, 0x6624, 0x6626, 0x6629, 0x662A, 0x662B, 0x662C, 0x662E, + 0x6630, 0x6632, 0x6633, 0x6637, 0x6638, 0x6639, 0x663A, 0x663B, 0x663D, + 0x663F, 0x6640, 0x6642, 0x6644, 0x6645, 0x6646, 0x6647, 0x6648, 0x6649, + 0x664A, 0x664D, 0x664E, 0x6650, 0x6651, 0x6658, 0, 0x6659, 0x665B, + 0x665C, 0x665D, 0x665E, 0x6660, 0x6662, 0x6663, 0x6665, 0x6667, 0x6669, + 0x666A, 0x666B, 0x666C, 0x666D, 0x6671, 0x6672, 0x6673, 0x6675, 0x6678, + 0x6679, 0x667B, 0x667C, 0x667D, 0x667F, 0x6680, 0x6681, 0x6683, 0x6685, + 0x6686, 0x6688, 0x6689, 0x668A, 0x668B, 0x668D, 0x668E, 0x668F, 0x6690, + 0x6692, 0x6693, 0x6694, 0x6695, 0x6698, 0x6699, 0x669A, 0x669B, 0x669C, + 0x669E, 0x669F, 0x66A0, 0x66A1, 0x66A2, 0x66A3, 0x66A4, 0x66A5, 0x66A6, + 0x66A9, 0x66AA, 0x66AB, 0x66AC, 0x66AD, 0x66AF, 0x66B0, 0x66B1, 0x66B2, + 0x66B3, 0x66B5, 0x66B6, 0x66B7, 0x66B8, 0x66BA, 0x66BB, 0x66BC, 0x66BD, + 0x66BF, 0x66C0, 0x66C1, 0x66C2, 0x66C3, 0x66C4, 0x66C5, 0x66C6, 0x66C7, + 0x66C8, 0x66C9, 0x66CA, 0x66CB, 0x66CC, 0x66CD, 0x66CE, 0x66CF, 0x66D0, + 0x66D1, 0x66D2, 0x66D3, 0x66D4, 0x66D5, 0x66D6, 0x66D7, 0x66D8, 0x66DA, + 0x66DE, 0x66DF, 0x66E0, 0x66E1, 0x66E2, 0x66E3, 0x66E4, 0x66E5, 0x66E7, + 0x66E8, 0x66EA, 0x66EB, 0x66EC, 0x66ED, 0x66EE, 0x66EF, 0x66F1, 0x66F5, + 0x66F6, 0x66F8, 0x66FA, 0x66FB, 0x66FD, 0x6701, 0x6702, 0x6703, 0, + 0x6704, 0x6705, 0x6706, 0x6707, 0x670C, 0x670E, 0x670F, 0x6711, 0x6712, + 0x6713, 0x6716, 0x6718, 0x6719, 0x671A, 0x671C, 0x671E, 0x6720, 0x6721, + 0x6722, 0x6723, 0x6724, 0x6725, 0x6727, 0x6729, 0x672E, 0x6730, 0x6732, + 0x6733, 0x6736, 0x6737, 0x6738, 0x6739, 0x673B, 0x673C, 0x673E, 0x673F, + 0x6741, 0x6744, 0x6745, 0x6747, 0x674A, 0x674B, 0x674D, 0x6752, 0x6754, + 0x6755, 0x6757, 0x6758, 0x6759, 0x675A, 0x675B, 0x675D, 0x6762, 0x6763, + 0x6764, 0x6766, 0x6767, 0x676B, 0x676C, 0x676E, 0x6771, 0x6774, 0x6776, + 0, 0x6778, 0x6779, 0x677A, 0x677B, 0x677D, 0x6780, 0x6782, 0x6783, + 0x6785, 0x6786, 0x6788, 0x678A, 0x678C, 0x678D, 0x678E, 0x678F, 0x6791, + 0x6792, 0x6793, 0x6794, 0x6796, 0x6799, 0x679B, 0x679F, 0x67A0, 0x67A1, + 0x67A4, 0x67A6, 0x67A9, 0x67AC, 0x67AE, 0x67B1, 0x67B2, 0x67B4, 0x67B9, + 0x67BA, 0x67BB, 0x67BC, 0x67BD, 0x67BE, 0x67BF, 0x67C0, 0x67C2, 0x67C5, + 0x67C6, 0x67C7, 0x67C8, 0x67C9, 0x67CA, 0x67CB, 0x67CC, 0x67CD, 0x67CE, + 0x67D5, 0x67D6, 0x67D7, 0x67DB, 0x67DF, 0x67E1, 0x67E3, 0x67E4, 0x67E6, + 0x67E7, 0x67E8, 0x67EA, 0x67EB, 0x67ED, 0x67EE, 0x67F2, 0x67F5, 0x67F6, + 0x67F7, 0x67F8, 0x67F9, 0x67FA, 0x67FB, 0x67FC, 0x67FE, 0x6801, 0x6802, + 0x6803, 0x6804, 0x6806, 0x680D, 0x6810, 0x6812, 0x6814, 0x6815, 0x6818, + 0x6819, 0x681A, 0x681B, 0x681C, 0x681E, 0x681F, 0x6820, 0x6822, 0x6823, + 0x6824, 0x6825, 0x6826, 0x6827, 0x6828, 0x682B, 0x682C, 0x682D, 0x682E, + 0x682F, 0x6830, 0x6831, 0x6834, 0x6835, 0x6836, 0x683A, 0x683B, 0x683F, + 0x6847, 0x684B, 0x684D, 0x684F, 0x6852, 0x6856, 0x6857, 0x6858, 0x6859, + 0x685A, 0x685B, 0, 0x685C, 0x685D, 0x685E, 0x685F, 0x686A, 0x686C, + 0x686D, 0x686E, 0x686F, 0x6870, 0x6871, 0x6872, 0x6873, 0x6875, 0x6878, + 0x6879, 0x687A, 0x687B, 0x687C, 0x687D, 0x687E, 0x687F, 0x6880, 0x6882, + 0x6884, 0x6887, 0x6888, 0x6889, 0x688A, 0x688B, 0x688C, 0x688D, 0x688E, + 0x6890, 0x6891, 0x6892, 0x6894, 0x6895, 0x6896, 0x6898, 0x6899, 0x689A, + 0x689B, 0x689C, 0x689D, 0x689E, 0x689F, 0x68A0, 0x68A1, 0x68A3, 0x68A4, + 0x68A5, 0x68A9, 0x68AA, 0x68AB, 0x68AC, 0x68AE, 0x68B1, 0x68B2, 0x68B4, + 0x68B6, 0x68B7, 0x68B8, 0, 0x68B9, 0x68BA, 0x68BB, 0x68BC, 0x68BD, + 0x68BE, 0x68BF, 0x68C1, 0x68C3, 0x68C4, 0x68C5, 0x68C6, 0x68C7, 0x68C8, + 0x68CA, 0x68CC, 0x68CE, 0x68CF, 0x68D0, 0x68D1, 0x68D3, 0x68D4, 0x68D6, + 0x68D7, 0x68D9, 0x68DB, 0x68DC, 0x68DD, 0x68DE, 0x68DF, 0x68E1, 0x68E2, + 0x68E4, 0x68E5, 0x68E6, 0x68E7, 0x68E8, 0x68E9, 0x68EA, 0x68EB, 0x68EC, + 0x68ED, 0x68EF, 0x68F2, 0x68F3, 0x68F4, 0x68F6, 0x68F7, 0x68F8, 0x68FB, + 0x68FD, 0x68FE, 0x68FF, 0x6900, 0x6902, 0x6903, 0x6904, 0x6906, 0x6907, + 0x6908, 0x6909, 0x690A, 0x690C, 0x690F, 0x6911, 0x6913, 0x6914, 0x6915, + 0x6916, 0x6917, 0x6918, 0x6919, 0x691A, 0x691B, 0x691C, 0x691D, 0x691E, + 0x6921, 0x6922, 0x6923, 0x6925, 0x6926, 0x6927, 0x6928, 0x6929, 0x692A, + 0x692B, 0x692C, 0x692E, 0x692F, 0x6931, 0x6932, 0x6933, 0x6935, 0x6936, + 0x6937, 0x6938, 0x693A, 0x693B, 0x693C, 0x693E, 0x6940, 0x6941, 0x6943, + 0x6944, 0x6945, 0x6946, 0x6947, 0x6948, 0x6949, 0x694A, 0x694B, 0x694C, + 0x694D, 0x694E, 0x694F, 0x6950, 0x6951, 0x6952, 0x6953, 0x6955, 0x6956, + 0x6958, 0x6959, 0x695B, 0x695C, 0x695F, 0, 0x6961, 0x6962, 0x6964, + 0x6965, 0x6967, 0x6968, 0x6969, 0x696A, 0x696C, 0x696D, 0x696F, 0x6970, + 0x6972, 0x6973, 0x6974, 0x6975, 0x6976, 0x697A, 0x697B, 0x697D, 0x697E, + 0x697F, 0x6981, 0x6983, 0x6985, 0x698A, 0x698B, 0x698C, 0x698E, 0x698F, + 0x6990, 0x6991, 0x6992, 0x6993, 0x6996, 0x6997, 0x6999, 0x699A, 0x699D, + 0x699E, 0x699F, 0x69A0, 0x69A1, 0x69A2, 0x69A3, 0x69A4, 0x69A5, 0x69A6, + 0x69A9, 0x69AA, 0x69AC, 0x69AE, 0x69AF, 0x69B0, 0x69B2, 0x69B3, 0x69B5, + 0x69B6, 0x69B8, 0x69B9, 0x69BA, 0x69BC, 0x69BD, 0, 0x69BE, 0x69BF, + 0x69C0, 0x69C2, 0x69C3, 0x69C4, 0x69C5, 0x69C6, 0x69C7, 0x69C8, 0x69C9, + 0x69CB, 0x69CD, 0x69CF, 0x69D1, 0x69D2, 0x69D3, 0x69D5, 0x69D6, 0x69D7, + 0x69D8, 0x69D9, 0x69DA, 0x69DC, 0x69DD, 0x69DE, 0x69E1, 0x69E2, 0x69E3, + 0x69E4, 0x69E5, 0x69E6, 0x69E7, 0x69E8, 0x69E9, 0x69EA, 0x69EB, 0x69EC, + 0x69EE, 0x69EF, 0x69F0, 0x69F1, 0x69F3, 0x69F4, 0x69F5, 0x69F6, 0x69F7, + 0x69F8, 0x69F9, 0x69FA, 0x69FB, 0x69FC, 0x69FE, 0x6A00, 0x6A01, 0x6A02, + 0x6A03, 0x6A04, 0x6A05, 0x6A06, 0x6A07, 0x6A08, 0x6A09, 0x6A0B, 0x6A0C, + 0x6A0D, 0x6A0E, 0x6A0F, 0x6A10, 0x6A11, 0x6A12, 0x6A13, 0x6A14, 0x6A15, + 0x6A16, 0x6A19, 0x6A1A, 0x6A1B, 0x6A1C, 0x6A1D, 0x6A1E, 0x6A20, 0x6A22, + 0x6A23, 0x6A24, 0x6A25, 0x6A26, 0x6A27, 0x6A29, 0x6A2B, 0x6A2C, 0x6A2D, + 0x6A2E, 0x6A30, 0x6A32, 0x6A33, 0x6A34, 0x6A36, 0x6A37, 0x6A38, 0x6A39, + 0x6A3A, 0x6A3B, 0x6A3C, 0x6A3F, 0x6A40, 0x6A41, 0x6A42, 0x6A43, 0x6A45, + 0x6A46, 0x6A48, 0x6A49, 0x6A4A, 0x6A4B, 0x6A4C, 0x6A4D, 0x6A4E, 0x6A4F, + 0x6A51, 0x6A52, 0x6A53, 0x6A54, 0x6A55, 0x6A56, 0x6A57, 0x6A5A, 0, + 0x6A5C, 0x6A5D, 0x6A5E, 0x6A5F, 0x6A60, 0x6A62, 0x6A63, 0x6A64, 0x6A66, + 0x6A67, 0x6A68, 0x6A69, 0x6A6A, 0x6A6B, 0x6A6C, 0x6A6D, 0x6A6E, 0x6A6F, + 0x6A70, 0x6A72, 0x6A73, 0x6A74, 0x6A75, 0x6A76, 0x6A77, 0x6A78, 0x6A7A, + 0x6A7B, 0x6A7D, 0x6A7E, 0x6A7F, 0x6A81, 0x6A82, 0x6A83, 0x6A85, 0x6A86, + 0x6A87, 0x6A88, 0x6A89, 0x6A8A, 0x6A8B, 0x6A8C, 0x6A8D, 0x6A8F, 0x6A92, + 0x6A93, 0x6A94, 0x6A95, 0x6A96, 0x6A98, 0x6A99, 0x6A9A, 0x6A9B, 0x6A9C, + 0x6A9D, 0x6A9E, 0x6A9F, 0x6AA1, 0x6AA2, 0x6AA3, 0x6AA4, 0x6AA5, 0x6AA6, + 0, 0x6AA7, 0x6AA8, 0x6AAA, 0x6AAD, 0x6AAE, 0x6AAF, 0x6AB0, 0x6AB1, + 0x6AB2, 0x6AB3, 0x6AB4, 0x6AB5, 0x6AB6, 0x6AB7, 0x6AB8, 0x6AB9, 0x6ABA, + 0x6ABB, 0x6ABC, 0x6ABD, 0x6ABE, 0x6ABF, 0x6AC0, 0x6AC1, 0x6AC2, 0x6AC3, + 0x6AC4, 0x6AC5, 0x6AC6, 0x6AC7, 0x6AC8, 0x6AC9, 0x6ACA, 0x6ACB, 0x6ACC, + 0x6ACD, 0x6ACE, 0x6ACF, 0x6AD0, 0x6AD1, 0x6AD2, 0x6AD3, 0x6AD4, 0x6AD5, + 0x6AD6, 0x6AD7, 0x6AD8, 0x6AD9, 0x6ADA, 0x6ADB, 0x6ADC, 0x6ADD, 0x6ADE, + 0x6ADF, 0x6AE0, 0x6AE1, 0x6AE2, 0x6AE3, 0x6AE4, 0x6AE5, 0x6AE6, 0x6AE7, + 0x6AE8, 0x6AE9, 0x6AEA, 0x6AEB, 0x6AEC, 0x6AED, 0x6AEE, 0x6AEF, 0x6AF0, + 0x6AF1, 0x6AF2, 0x6AF3, 0x6AF4, 0x6AF5, 0x6AF6, 0x6AF7, 0x6AF8, 0x6AF9, + 0x6AFA, 0x6AFB, 0x6AFC, 0x6AFD, 0x6AFE, 0x6AFF, 0x6B00, 0x6B01, 0x6B02, + 0x6B03, 0x6B04, 0x6B05, 0x6B06, 0x6B07, 0x6B08, 0x6B09, 0x6B0A, 0x6B0B, + 0x6B0C, 0x6B0D, 0x6B0E, 0x6B0F, 0x6B10, 0x6B11, 0x6B12, 0x6B13, 0x6B14, + 0x6B15, 0x6B16, 0x6B17, 0x6B18, 0x6B19, 0x6B1A, 0x6B1B, 0x6B1C, 0x6B1D, + 0x6B1E, 0x6B1F, 0x6B25, 0x6B26, 0x6B28, 0x6B29, 0x6B2A, 0x6B2B, 0x6B2C, + 0x6B2D, 0x6B2E, 0, 0x6B2F, 0x6B30, 0x6B31, 0x6B33, 0x6B34, 0x6B35, + 0x6B36, 0x6B38, 0x6B3B, 0x6B3C, 0x6B3D, 0x6B3F, 0x6B40, 0x6B41, 0x6B42, + 0x6B44, 0x6B45, 0x6B48, 0x6B4A, 0x6B4B, 0x6B4D, 0x6B4E, 0x6B4F, 0x6B50, + 0x6B51, 0x6B52, 0x6B53, 0x6B54, 0x6B55, 0x6B56, 0x6B57, 0x6B58, 0x6B5A, + 0x6B5B, 0x6B5C, 0x6B5D, 0x6B5E, 0x6B5F, 0x6B60, 0x6B61, 0x6B68, 0x6B69, + 0x6B6B, 0x6B6C, 0x6B6D, 0x6B6E, 0x6B6F, 0x6B70, 0x6B71, 0x6B72, 0x6B73, + 0x6B74, 0x6B75, 0x6B76, 0x6B77, 0x6B78, 0x6B7A, 0x6B7D, 0x6B7E, 0x6B7F, + 0x6B80, 0x6B85, 0x6B88, 0, 0x6B8C, 0x6B8E, 0x6B8F, 0x6B90, 0x6B91, + 0x6B94, 0x6B95, 0x6B97, 0x6B98, 0x6B99, 0x6B9C, 0x6B9D, 0x6B9E, 0x6B9F, + 0x6BA0, 0x6BA2, 0x6BA3, 0x6BA4, 0x6BA5, 0x6BA6, 0x6BA7, 0x6BA8, 0x6BA9, + 0x6BAB, 0x6BAC, 0x6BAD, 0x6BAE, 0x6BAF, 0x6BB0, 0x6BB1, 0x6BB2, 0x6BB6, + 0x6BB8, 0x6BB9, 0x6BBA, 0x6BBB, 0x6BBC, 0x6BBD, 0x6BBE, 0x6BC0, 0x6BC3, + 0x6BC4, 0x6BC6, 0x6BC7, 0x6BC8, 0x6BC9, 0x6BCA, 0x6BCC, 0x6BCE, 0x6BD0, + 0x6BD1, 0x6BD8, 0x6BDA, 0x6BDC, 0x6BDD, 0x6BDE, 0x6BDF, 0x6BE0, 0x6BE2, + 0x6BE3, 0x6BE4, 0x6BE5, 0x6BE6, 0x6BE7, 0x6BE8, 0x6BE9, 0x6BEC, 0x6BED, + 0x6BEE, 0x6BF0, 0x6BF1, 0x6BF2, 0x6BF4, 0x6BF6, 0x6BF7, 0x6BF8, 0x6BFA, + 0x6BFB, 0x6BFC, 0x6BFE, 0x6BFF, 0x6C00, 0x6C01, 0x6C02, 0x6C03, 0x6C04, + 0x6C08, 0x6C09, 0x6C0A, 0x6C0B, 0x6C0C, 0x6C0E, 0x6C12, 0x6C17, 0x6C1C, + 0x6C1D, 0x6C1E, 0x6C20, 0x6C23, 0x6C25, 0x6C2B, 0x6C2C, 0x6C2D, 0x6C31, + 0x6C33, 0x6C36, 0x6C37, 0x6C39, 0x6C3A, 0x6C3B, 0x6C3C, 0x6C3E, 0x6C3F, + 0x6C43, 0x6C44, 0x6C45, 0x6C48, 0x6C4B, 0x6C4C, 0x6C4D, 0x6C4E, 0x6C4F, + 0x6C51, 0x6C52, 0x6C53, 0x6C56, 0x6C58, 0, 0x6C59, 0x6C5A, 0x6C62, + 0x6C63, 0x6C65, 0x6C66, 0x6C67, 0x6C6B, 0x6C6C, 0x6C6D, 0x6C6E, 0x6C6F, + 0x6C71, 0x6C73, 0x6C75, 0x6C77, 0x6C78, 0x6C7A, 0x6C7B, 0x6C7C, 0x6C7F, + 0x6C80, 0x6C84, 0x6C87, 0x6C8A, 0x6C8B, 0x6C8D, 0x6C8E, 0x6C91, 0x6C92, + 0x6C95, 0x6C96, 0x6C97, 0x6C98, 0x6C9A, 0x6C9C, 0x6C9D, 0x6C9E, 0x6CA0, + 0x6CA2, 0x6CA8, 0x6CAC, 0x6CAF, 0x6CB0, 0x6CB4, 0x6CB5, 0x6CB6, 0x6CB7, + 0x6CBA, 0x6CC0, 0x6CC1, 0x6CC2, 0x6CC3, 0x6CC6, 0x6CC7, 0x6CC8, 0x6CCB, + 0x6CCD, 0x6CCE, 0x6CCF, 0x6CD1, 0x6CD2, 0x6CD8, 0, 0x6CD9, 0x6CDA, + 0x6CDC, 0x6CDD, 0x6CDF, 0x6CE4, 0x6CE6, 0x6CE7, 0x6CE9, 0x6CEC, 0x6CED, + 0x6CF2, 0x6CF4, 0x6CF9, 0x6CFF, 0x6D00, 0x6D02, 0x6D03, 0x6D05, 0x6D06, + 0x6D08, 0x6D09, 0x6D0A, 0x6D0D, 0x6D0F, 0x6D10, 0x6D11, 0x6D13, 0x6D14, + 0x6D15, 0x6D16, 0x6D18, 0x6D1C, 0x6D1D, 0x6D1F, 0x6D20, 0x6D21, 0x6D22, + 0x6D23, 0x6D24, 0x6D26, 0x6D28, 0x6D29, 0x6D2C, 0x6D2D, 0x6D2F, 0x6D30, + 0x6D34, 0x6D36, 0x6D37, 0x6D38, 0x6D3A, 0x6D3F, 0x6D40, 0x6D42, 0x6D44, + 0x6D49, 0x6D4C, 0x6D50, 0x6D55, 0x6D56, 0x6D57, 0x6D58, 0x6D5B, 0x6D5D, + 0x6D5F, 0x6D61, 0x6D62, 0x6D64, 0x6D65, 0x6D67, 0x6D68, 0x6D6B, 0x6D6C, + 0x6D6D, 0x6D70, 0x6D71, 0x6D72, 0x6D73, 0x6D75, 0x6D76, 0x6D79, 0x6D7A, + 0x6D7B, 0x6D7D, 0x6D7E, 0x6D7F, 0x6D80, 0x6D81, 0x6D83, 0x6D84, 0x6D86, + 0x6D87, 0x6D8A, 0x6D8B, 0x6D8D, 0x6D8F, 0x6D90, 0x6D92, 0x6D96, 0x6D97, + 0x6D98, 0x6D99, 0x6D9A, 0x6D9C, 0x6DA2, 0x6DA5, 0x6DAC, 0x6DAD, 0x6DB0, + 0x6DB1, 0x6DB3, 0x6DB4, 0x6DB6, 0x6DB7, 0x6DB9, 0x6DBA, 0x6DBB, 0x6DBC, + 0x6DBD, 0x6DBE, 0x6DC1, 0x6DC2, 0x6DC3, 0x6DC8, 0x6DC9, 0x6DCA, 0, + 0x6DCD, 0x6DCE, 0x6DCF, 0x6DD0, 0x6DD2, 0x6DD3, 0x6DD4, 0x6DD5, 0x6DD7, + 0x6DDA, 0x6DDB, 0x6DDC, 0x6DDF, 0x6DE2, 0x6DE3, 0x6DE5, 0x6DE7, 0x6DE8, + 0x6DE9, 0x6DEA, 0x6DED, 0x6DEF, 0x6DF0, 0x6DF2, 0x6DF4, 0x6DF5, 0x6DF6, + 0x6DF8, 0x6DFA, 0x6DFD, 0x6DFE, 0x6DFF, 0x6E00, 0x6E01, 0x6E02, 0x6E03, + 0x6E04, 0x6E06, 0x6E07, 0x6E08, 0x6E09, 0x6E0B, 0x6E0F, 0x6E12, 0x6E13, + 0x6E15, 0x6E18, 0x6E19, 0x6E1B, 0x6E1C, 0x6E1E, 0x6E1F, 0x6E22, 0x6E26, + 0x6E27, 0x6E28, 0x6E2A, 0x6E2C, 0x6E2E, 0x6E30, 0x6E31, 0x6E33, 0x6E35, + 0, 0x6E36, 0x6E37, 0x6E39, 0x6E3B, 0x6E3C, 0x6E3D, 0x6E3E, 0x6E3F, + 0x6E40, 0x6E41, 0x6E42, 0x6E45, 0x6E46, 0x6E47, 0x6E48, 0x6E49, 0x6E4A, + 0x6E4B, 0x6E4C, 0x6E4F, 0x6E50, 0x6E51, 0x6E52, 0x6E55, 0x6E57, 0x6E59, + 0x6E5A, 0x6E5C, 0x6E5D, 0x6E5E, 0x6E60, 0x6E61, 0x6E62, 0x6E63, 0x6E64, + 0x6E65, 0x6E66, 0x6E67, 0x6E68, 0x6E69, 0x6E6A, 0x6E6C, 0x6E6D, 0x6E6F, + 0x6E70, 0x6E71, 0x6E72, 0x6E73, 0x6E74, 0x6E75, 0x6E76, 0x6E77, 0x6E78, + 0x6E79, 0x6E7A, 0x6E7B, 0x6E7C, 0x6E7D, 0x6E80, 0x6E81, 0x6E82, 0x6E84, + 0x6E87, 0x6E88, 0x6E8A, 0x6E8B, 0x6E8C, 0x6E8D, 0x6E8E, 0x6E91, 0x6E92, + 0x6E93, 0x6E94, 0x6E95, 0x6E96, 0x6E97, 0x6E99, 0x6E9A, 0x6E9B, 0x6E9D, + 0x6E9E, 0x6EA0, 0x6EA1, 0x6EA3, 0x6EA4, 0x6EA6, 0x6EA8, 0x6EA9, 0x6EAB, + 0x6EAC, 0x6EAD, 0x6EAE, 0x6EB0, 0x6EB3, 0x6EB5, 0x6EB8, 0x6EB9, 0x6EBC, + 0x6EBE, 0x6EBF, 0x6EC0, 0x6EC3, 0x6EC4, 0x6EC5, 0x6EC6, 0x6EC8, 0x6EC9, + 0x6ECA, 0x6ECC, 0x6ECD, 0x6ECE, 0x6ED0, 0x6ED2, 0x6ED6, 0x6ED8, 0x6ED9, + 0x6EDB, 0x6EDC, 0x6EDD, 0x6EE3, 0x6EE7, 0x6EEA, 0x6EEB, 0x6EEC, 0x6EED, + 0x6EEE, 0x6EEF, 0, 0x6EF0, 0x6EF1, 0x6EF2, 0x6EF3, 0x6EF5, 0x6EF6, + 0x6EF7, 0x6EF8, 0x6EFA, 0x6EFB, 0x6EFC, 0x6EFD, 0x6EFE, 0x6EFF, 0x6F00, + 0x6F01, 0x6F03, 0x6F04, 0x6F05, 0x6F07, 0x6F08, 0x6F0A, 0x6F0B, 0x6F0C, + 0x6F0D, 0x6F0E, 0x6F10, 0x6F11, 0x6F12, 0x6F16, 0x6F17, 0x6F18, 0x6F19, + 0x6F1A, 0x6F1B, 0x6F1C, 0x6F1D, 0x6F1E, 0x6F1F, 0x6F21, 0x6F22, 0x6F23, + 0x6F25, 0x6F26, 0x6F27, 0x6F28, 0x6F2C, 0x6F2E, 0x6F30, 0x6F32, 0x6F34, + 0x6F35, 0x6F37, 0x6F38, 0x6F39, 0x6F3A, 0x6F3B, 0x6F3C, 0x6F3D, 0x6F3F, + 0x6F40, 0x6F41, 0x6F42, 0, 0x6F43, 0x6F44, 0x6F45, 0x6F48, 0x6F49, + 0x6F4A, 0x6F4C, 0x6F4E, 0x6F4F, 0x6F50, 0x6F51, 0x6F52, 0x6F53, 0x6F54, + 0x6F55, 0x6F56, 0x6F57, 0x6F59, 0x6F5A, 0x6F5B, 0x6F5D, 0x6F5F, 0x6F60, + 0x6F61, 0x6F63, 0x6F64, 0x6F65, 0x6F67, 0x6F68, 0x6F69, 0x6F6A, 0x6F6B, + 0x6F6C, 0x6F6F, 0x6F70, 0x6F71, 0x6F73, 0x6F75, 0x6F76, 0x6F77, 0x6F79, + 0x6F7B, 0x6F7D, 0x6F7E, 0x6F7F, 0x6F80, 0x6F81, 0x6F82, 0x6F83, 0x6F85, + 0x6F86, 0x6F87, 0x6F8A, 0x6F8B, 0x6F8F, 0x6F90, 0x6F91, 0x6F92, 0x6F93, + 0x6F94, 0x6F95, 0x6F96, 0x6F97, 0x6F98, 0x6F99, 0x6F9A, 0x6F9B, 0x6F9D, + 0x6F9E, 0x6F9F, 0x6FA0, 0x6FA2, 0x6FA3, 0x6FA4, 0x6FA5, 0x6FA6, 0x6FA8, + 0x6FA9, 0x6FAA, 0x6FAB, 0x6FAC, 0x6FAD, 0x6FAE, 0x6FAF, 0x6FB0, 0x6FB1, + 0x6FB2, 0x6FB4, 0x6FB5, 0x6FB7, 0x6FB8, 0x6FBA, 0x6FBB, 0x6FBC, 0x6FBD, + 0x6FBE, 0x6FBF, 0x6FC1, 0x6FC3, 0x6FC4, 0x6FC5, 0x6FC6, 0x6FC7, 0x6FC8, + 0x6FCA, 0x6FCB, 0x6FCC, 0x6FCD, 0x6FCE, 0x6FCF, 0x6FD0, 0x6FD3, 0x6FD4, + 0x6FD5, 0x6FD6, 0x6FD7, 0x6FD8, 0x6FD9, 0x6FDA, 0x6FDB, 0x6FDC, 0x6FDD, + 0x6FDF, 0x6FE2, 0x6FE3, 0x6FE4, 0x6FE5, 0, 0x6FE6, 0x6FE7, 0x6FE8, + 0x6FE9, 0x6FEA, 0x6FEB, 0x6FEC, 0x6FED, 0x6FF0, 0x6FF1, 0x6FF2, 0x6FF3, + 0x6FF4, 0x6FF5, 0x6FF6, 0x6FF7, 0x6FF8, 0x6FF9, 0x6FFA, 0x6FFB, 0x6FFC, + 0x6FFD, 0x6FFE, 0x6FFF, 0x7000, 0x7001, 0x7002, 0x7003, 0x7004, 0x7005, + 0x7006, 0x7007, 0x7008, 0x7009, 0x700A, 0x700B, 0x700C, 0x700D, 0x700E, + 0x700F, 0x7010, 0x7012, 0x7013, 0x7014, 0x7015, 0x7016, 0x7017, 0x7018, + 0x7019, 0x701C, 0x701D, 0x701E, 0x701F, 0x7020, 0x7021, 0x7022, 0x7024, + 0x7025, 0x7026, 0x7027, 0x7028, 0x7029, 0x702A, 0, 0x702B, 0x702C, + 0x702D, 0x702E, 0x702F, 0x7030, 0x7031, 0x7032, 0x7033, 0x7034, 0x7036, + 0x7037, 0x7038, 0x703A, 0x703B, 0x703C, 0x703D, 0x703E, 0x703F, 0x7040, + 0x7041, 0x7042, 0x7043, 0x7044, 0x7045, 0x7046, 0x7047, 0x7048, 0x7049, + 0x704A, 0x704B, 0x704D, 0x704E, 0x7050, 0x7051, 0x7052, 0x7053, 0x7054, + 0x7055, 0x7056, 0x7057, 0x7058, 0x7059, 0x705A, 0x705B, 0x705C, 0x705D, + 0x705F, 0x7060, 0x7061, 0x7062, 0x7063, 0x7064, 0x7065, 0x7066, 0x7067, + 0x7068, 0x7069, 0x706A, 0x706E, 0x7071, 0x7072, 0x7073, 0x7074, 0x7077, + 0x7079, 0x707A, 0x707B, 0x707D, 0x7081, 0x7082, 0x7083, 0x7084, 0x7086, + 0x7087, 0x7088, 0x708B, 0x708C, 0x708D, 0x708F, 0x7090, 0x7091, 0x7093, + 0x7097, 0x7098, 0x709A, 0x709B, 0x709E, 0x709F, 0x70A0, 0x70A1, 0x70A2, + 0x70A3, 0x70A4, 0x70A5, 0x70A6, 0x70A7, 0x70A8, 0x70A9, 0x70AA, 0x70B0, + 0x70B2, 0x70B4, 0x70B5, 0x70B6, 0x70BA, 0x70BE, 0x70BF, 0x70C4, 0x70C5, + 0x70C6, 0x70C7, 0x70C9, 0x70CB, 0x70CC, 0x70CD, 0x70CE, 0x70CF, 0x70D0, + 0x70D1, 0x70D2, 0x70D3, 0x70D4, 0x70D5, 0x70D6, 0x70D7, 0x70DA, 0, + 0x70DC, 0x70DD, 0x70DE, 0x70E0, 0x70E1, 0x70E2, 0x70E3, 0x70E5, 0x70EA, + 0x70EE, 0x70F0, 0x70F1, 0x70F2, 0x70F3, 0x70F4, 0x70F5, 0x70F6, 0x70F8, + 0x70FA, 0x70FB, 0x70FC, 0x70FE, 0x70FF, 0x7100, 0x7101, 0x7102, 0x7103, + 0x7104, 0x7105, 0x7106, 0x7107, 0x7108, 0x710B, 0x710C, 0x710D, 0x710E, + 0x710F, 0x7111, 0x7112, 0x7114, 0x7117, 0x711B, 0x711C, 0x711D, 0x711E, + 0x711F, 0x7120, 0x7121, 0x7122, 0x7123, 0x7124, 0x7125, 0x7127, 0x7128, + 0x7129, 0x712A, 0x712B, 0x712C, 0x712D, 0x712E, 0x7132, 0x7133, 0x7134, + 0, 0x7135, 0x7137, 0x7138, 0x7139, 0x713A, 0x713B, 0x713C, 0x713D, + 0x713E, 0x713F, 0x7140, 0x7141, 0x7142, 0x7143, 0x7144, 0x7146, 0x7147, + 0x7148, 0x7149, 0x714B, 0x714D, 0x714F, 0x7150, 0x7151, 0x7152, 0x7153, + 0x7154, 0x7155, 0x7156, 0x7157, 0x7158, 0x7159, 0x715A, 0x715B, 0x715D, + 0x715F, 0x7160, 0x7161, 0x7162, 0x7163, 0x7165, 0x7169, 0x716A, 0x716B, + 0x716C, 0x716D, 0x716F, 0x7170, 0x7171, 0x7174, 0x7175, 0x7176, 0x7177, + 0x7179, 0x717B, 0x717C, 0x717E, 0x717F, 0x7180, 0x7181, 0x7182, 0x7183, + 0x7185, 0x7186, 0x7187, 0x7188, 0x7189, 0x718B, 0x718C, 0x718D, 0x718E, + 0x7190, 0x7191, 0x7192, 0x7193, 0x7195, 0x7196, 0x7197, 0x719A, 0x719B, + 0x719C, 0x719D, 0x719E, 0x71A1, 0x71A2, 0x71A3, 0x71A4, 0x71A5, 0x71A6, + 0x71A7, 0x71A9, 0x71AA, 0x71AB, 0x71AD, 0x71AE, 0x71AF, 0x71B0, 0x71B1, + 0x71B2, 0x71B4, 0x71B6, 0x71B7, 0x71B8, 0x71BA, 0x71BB, 0x71BC, 0x71BD, + 0x71BE, 0x71BF, 0x71C0, 0x71C1, 0x71C2, 0x71C4, 0x71C5, 0x71C6, 0x71C7, + 0x71C8, 0x71C9, 0x71CA, 0x71CB, 0x71CC, 0x71CD, 0x71CF, 0x71D0, 0x71D1, + 0x71D2, 0x71D3, 0, 0x71D6, 0x71D7, 0x71D8, 0x71D9, 0x71DA, 0x71DB, + 0x71DC, 0x71DD, 0x71DE, 0x71DF, 0x71E1, 0x71E2, 0x71E3, 0x71E4, 0x71E6, + 0x71E8, 0x71E9, 0x71EA, 0x71EB, 0x71EC, 0x71ED, 0x71EF, 0x71F0, 0x71F1, + 0x71F2, 0x71F3, 0x71F4, 0x71F5, 0x71F6, 0x71F7, 0x71F8, 0x71FA, 0x71FB, + 0x71FC, 0x71FD, 0x71FE, 0x71FF, 0x7200, 0x7201, 0x7202, 0x7203, 0x7204, + 0x7205, 0x7207, 0x7208, 0x7209, 0x720A, 0x720B, 0x720C, 0x720D, 0x720E, + 0x720F, 0x7210, 0x7211, 0x7212, 0x7213, 0x7214, 0x7215, 0x7216, 0x7217, + 0x7218, 0x7219, 0x721A, 0, 0x721B, 0x721C, 0x721E, 0x721F, 0x7220, + 0x7221, 0x7222, 0x7223, 0x7224, 0x7225, 0x7226, 0x7227, 0x7229, 0x722B, + 0x722D, 0x722E, 0x722F, 0x7232, 0x7233, 0x7234, 0x723A, 0x723C, 0x723E, + 0x7240, 0x7241, 0x7242, 0x7243, 0x7244, 0x7245, 0x7246, 0x7249, 0x724A, + 0x724B, 0x724E, 0x724F, 0x7250, 0x7251, 0x7253, 0x7254, 0x7255, 0x7257, + 0x7258, 0x725A, 0x725C, 0x725E, 0x7260, 0x7263, 0x7264, 0x7265, 0x7268, + 0x726A, 0x726B, 0x726C, 0x726D, 0x7270, 0x7271, 0x7273, 0x7274, 0x7276, + 0x7277, 0x7278, 0x727B, 0x727C, 0x727D, 0x7282, 0x7283, 0x7285, 0x7286, + 0x7287, 0x7288, 0x7289, 0x728C, 0x728E, 0x7290, 0x7291, 0x7293, 0x7294, + 0x7295, 0x7296, 0x7297, 0x7298, 0x7299, 0x729A, 0x729B, 0x729C, 0x729D, + 0x729E, 0x72A0, 0x72A1, 0x72A2, 0x72A3, 0x72A4, 0x72A5, 0x72A6, 0x72A7, + 0x72A8, 0x72A9, 0x72AA, 0x72AB, 0x72AE, 0x72B1, 0x72B2, 0x72B3, 0x72B5, + 0x72BA, 0x72BB, 0x72BC, 0x72BD, 0x72BE, 0x72BF, 0x72C0, 0x72C5, 0x72C6, + 0x72C7, 0x72C9, 0x72CA, 0x72CB, 0x72CC, 0x72CF, 0x72D1, 0x72D3, 0x72D4, + 0x72D5, 0x72D6, 0x72D8, 0x72DA, 0x72DB, 0, 0xE4C6, 0xE4C7, 0xE4C8, + 0xE4C9, 0xE4CA, 0xE4CB, 0xE4CC, 0xE4CD, 0xE4CE, 0xE4CF, 0xE4D0, 0xE4D1, + 0xE4D2, 0xE4D3, 0xE4D4, 0xE4D5, 0xE4D6, 0xE4D7, 0xE4D8, 0xE4D9, 0xE4DA, + 0xE4DB, 0xE4DC, 0xE4DD, 0xE4DE, 0xE4DF, 0xE4E0, 0xE4E1, 0xE4E2, 0xE4E3, + 0xE4E4, 0xE4E5, 0xE4E6, 0xE4E7, 0xE4E8, 0xE4E9, 0xE4EA, 0xE4EB, 0xE4EC, + 0xE4ED, 0xE4EE, 0xE4EF, 0xE4F0, 0xE4F1, 0xE4F2, 0xE4F3, 0xE4F4, 0xE4F5, + 0xE4F6, 0xE4F7, 0xE4F8, 0xE4F9, 0xE4FA, 0xE4FB, 0xE4FC, 0xE4FD, 0xE4FE, + 0xE4FF, 0xE500, 0xE501, 0xE502, 0xE503, 0xE504, 0, 0xE505, 0xE506, + 0xE507, 0xE508, 0xE509, 0xE50A, 0xE50B, 0xE50C, 0xE50D, 0xE50E, 0xE50F, + 0xE510, 0xE511, 0xE512, 0xE513, 0xE514, 0xE515, 0xE516, 0xE517, 0xE518, + 0xE519, 0xE51A, 0xE51B, 0xE51C, 0xE51D, 0xE51E, 0xE51F, 0xE520, 0xE521, + 0xE522, 0xE523, 0xE524, 0xE525, 0x3000, 0x3001, 0x3002, 0x00B7, 0x02C9, + 0x02C7, 0x00A8, 0x3003, 0x3005, 0x2014, 0xFF5E, 0x2016, 0x2026, 0x2018, + 0x2019, 0x201C, 0x201D, 0x3014, 0x3015, 0x3008, 0x3009, 0x300A, 0x300B, + 0x300C, 0x300D, 0x300E, 0x300F, 0x3016, 0x3017, 0x3010, 0x3011, 0x00B1, + 0x00D7, 0x00F7, 0x2236, 0x2227, 0x2228, 0x2211, 0x220F, 0x222A, 0x2229, + 0x2208, 0x2237, 0x221A, 0x22A5, 0x2225, 0x2220, 0x2312, 0x2299, 0x222B, + 0x222E, 0x2261, 0x224C, 0x2248, 0x223D, 0x221D, 0x2260, 0x226E, 0x226F, + 0x2264, 0x2265, 0x221E, 0x2235, 0x2234, 0x2642, 0x2640, 0x00B0, 0x2032, + 0x2033, 0x2103, 0xFF04, 0x00A4, 0xFFE0, 0xFFE1, 0x2030, 0x00A7, 0x2116, + 0x2606, 0x2605, 0x25CB, 0x25CF, 0x25CE, 0x25C7, 0x25C6, 0x25A1, 0x25A0, + 0x25B3, 0x25B2, 0x203B, 0x2192, 0x2190, 0x2191, 0x2193, 0x3013, 0, + 0xE526, 0xE527, 0xE528, 0xE529, 0xE52A, 0xE52B, 0xE52C, 0xE52D, 0xE52E, + 0xE52F, 0xE530, 0xE531, 0xE532, 0xE533, 0xE534, 0xE535, 0xE536, 0xE537, + 0xE538, 0xE539, 0xE53A, 0xE53B, 0xE53C, 0xE53D, 0xE53E, 0xE53F, 0xE540, + 0xE541, 0xE542, 0xE543, 0xE544, 0xE545, 0xE546, 0xE547, 0xE548, 0xE549, + 0xE54A, 0xE54B, 0xE54C, 0xE54D, 0xE54E, 0xE54F, 0xE550, 0xE551, 0xE552, + 0xE553, 0xE554, 0xE555, 0xE556, 0xE557, 0xE558, 0xE559, 0xE55A, 0xE55B, + 0xE55C, 0xE55D, 0xE55E, 0xE55F, 0xE560, 0xE561, 0xE562, 0xE563, 0xE564, + 0, 0xE565, 0xE566, 0xE567, 0xE568, 0xE569, 0xE56A, 0xE56B, 0xE56C, + 0xE56D, 0xE56E, 0xE56F, 0xE570, 0xE571, 0xE572, 0xE573, 0xE574, 0xE575, + 0xE576, 0xE577, 0xE578, 0xE579, 0xE57A, 0xE57B, 0xE57C, 0xE57D, 0xE57E, + 0xE57F, 0xE580, 0xE581, 0xE582, 0xE583, 0xE584, 0xE585, 0x2170, 0x2171, + 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0xE766, + 0xE767, 0xE768, 0xE769, 0xE76A, 0xE76B, 0x2488, 0x2489, 0x248A, 0x248B, + 0x248C, 0x248D, 0x248E, 0x248F, 0x2490, 0x2491, 0x2492, 0x2493, 0x2494, + 0x2495, 0x2496, 0x2497, 0x2498, 0x2499, 0x249A, 0x249B, 0x2474, 0x2475, + 0x2476, 0x2477, 0x2478, 0x2479, 0x247A, 0x247B, 0x247C, 0x247D, 0x247E, + 0x247F, 0x2480, 0x2481, 0x2482, 0x2483, 0x2484, 0x2485, 0x2486, 0x2487, + 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, 0x2468, + 0x2469, 0x20AC, 0xE76D, 0x3220, 0x3221, 0x3222, 0x3223, 0x3224, 0x3225, + 0x3226, 0x3227, 0x3228, 0x3229, 0xE76E, 0xE76F, 0x2160, 0x2161, 0x2162, + 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, + 0xE770, 0xE771, 0, 0xE586, 0xE587, 0xE588, 0xE589, 0xE58A, 0xE58B, + 0xE58C, 0xE58D, 0xE58E, 0xE58F, 0xE590, 0xE591, 0xE592, 0xE593, 0xE594, + 0xE595, 0xE596, 0xE597, 0xE598, 0xE599, 0xE59A, 0xE59B, 0xE59C, 0xE59D, + 0xE59E, 0xE59F, 0xE5A0, 0xE5A1, 0xE5A2, 0xE5A3, 0xE5A4, 0xE5A5, 0xE5A6, + 0xE5A7, 0xE5A8, 0xE5A9, 0xE5AA, 0xE5AB, 0xE5AC, 0xE5AD, 0xE5AE, 0xE5AF, + 0xE5B0, 0xE5B1, 0xE5B2, 0xE5B3, 0xE5B4, 0xE5B5, 0xE5B6, 0xE5B7, 0xE5B8, + 0xE5B9, 0xE5BA, 0xE5BB, 0xE5BC, 0xE5BD, 0xE5BE, 0xE5BF, 0xE5C0, 0xE5C1, + 0xE5C2, 0xE5C3, 0xE5C4, 0, 0xE5C5, 0xE5C6, 0xE5C7, 0xE5C8, 0xE5C9, + 0xE5CA, 0xE5CB, 0xE5CC, 0xE5CD, 0xE5CE, 0xE5CF, 0xE5D0, 0xE5D1, 0xE5D2, + 0xE5D3, 0xE5D4, 0xE5D5, 0xE5D6, 0xE5D7, 0xE5D8, 0xE5D9, 0xE5DA, 0xE5DB, + 0xE5DC, 0xE5DD, 0xE5DE, 0xE5DF, 0xE5E0, 0xE5E1, 0xE5E2, 0xE5E3, 0xE5E4, + 0xE5E5, 0xFF01, 0xFF02, 0xFF03, 0xFFE5, 0xFF05, 0xFF06, 0xFF07, 0xFF08, + 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F, 0xFF10, 0xFF11, + 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17, 0xFF18, 0xFF19, 0xFF1A, + 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F, 0xFF20, 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, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, + 0xFF3F, 0xFF40, 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, 0xFF5B, 0xFF5C, 0xFF5D, 0xFFE3, 0, 0xE5E6, 0xE5E7, 0xE5E8, + 0xE5E9, 0xE5EA, 0xE5EB, 0xE5EC, 0xE5ED, 0xE5EE, 0xE5EF, 0xE5F0, 0xE5F1, + 0xE5F2, 0xE5F3, 0xE5F4, 0xE5F5, 0xE5F6, 0xE5F7, 0xE5F8, 0xE5F9, 0xE5FA, + 0xE5FB, 0xE5FC, 0xE5FD, 0xE5FE, 0xE5FF, 0xE600, 0xE601, 0xE602, 0xE603, + 0xE604, 0xE605, 0xE606, 0xE607, 0xE608, 0xE609, 0xE60A, 0xE60B, 0xE60C, + 0xE60D, 0xE60E, 0xE60F, 0xE610, 0xE611, 0xE612, 0xE613, 0xE614, 0xE615, + 0xE616, 0xE617, 0xE618, 0xE619, 0xE61A, 0xE61B, 0xE61C, 0xE61D, 0xE61E, + 0xE61F, 0xE620, 0xE621, 0xE622, 0xE623, 0xE624, 0, 0xE625, 0xE626, + 0xE627, 0xE628, 0xE629, 0xE62A, 0xE62B, 0xE62C, 0xE62D, 0xE62E, 0xE62F, + 0xE630, 0xE631, 0xE632, 0xE633, 0xE634, 0xE635, 0xE636, 0xE637, 0xE638, + 0xE639, 0xE63A, 0xE63B, 0xE63C, 0xE63D, 0xE63E, 0xE63F, 0xE640, 0xE641, + 0xE642, 0xE643, 0xE644, 0xE645, 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, + 0x3046, 0x3047, 0x3048, 0x3049, 0x304A, 0x304B, 0x304C, 0x304D, 0x304E, + 0x304F, 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057, + 0x3058, 0x3059, 0x305A, 0x305B, 0x305C, 0x305D, 0x305E, 0x305F, 0x3060, + 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066, 0x3067, 0x3068, 0x3069, + 0x306A, 0x306B, 0x306C, 0x306D, 0x306E, 0x306F, 0x3070, 0x3071, 0x3072, + 0x3073, 0x3074, 0x3075, 0x3076, 0x3077, 0x3078, 0x3079, 0x307A, 0x307B, + 0x307C, 0x307D, 0x307E, 0x307F, 0x3080, 0x3081, 0x3082, 0x3083, 0x3084, + 0x3085, 0x3086, 0x3087, 0x3088, 0x3089, 0x308A, 0x308B, 0x308C, 0x308D, + 0x308E, 0x308F, 0x3090, 0x3091, 0x3092, 0x3093, 0xE772, 0xE773, 0xE774, + 0xE775, 0xE776, 0xE777, 0xE778, 0xE779, 0xE77A, 0xE77B, 0xE77C, 0, + 0xE646, 0xE647, 0xE648, 0xE649, 0xE64A, 0xE64B, 0xE64C, 0xE64D, 0xE64E, + 0xE64F, 0xE650, 0xE651, 0xE652, 0xE653, 0xE654, 0xE655, 0xE656, 0xE657, + 0xE658, 0xE659, 0xE65A, 0xE65B, 0xE65C, 0xE65D, 0xE65E, 0xE65F, 0xE660, + 0xE661, 0xE662, 0xE663, 0xE664, 0xE665, 0xE666, 0xE667, 0xE668, 0xE669, + 0xE66A, 0xE66B, 0xE66C, 0xE66D, 0xE66E, 0xE66F, 0xE670, 0xE671, 0xE672, + 0xE673, 0xE674, 0xE675, 0xE676, 0xE677, 0xE678, 0xE679, 0xE67A, 0xE67B, + 0xE67C, 0xE67D, 0xE67E, 0xE67F, 0xE680, 0xE681, 0xE682, 0xE683, 0xE684, + 0, 0xE685, 0xE686, 0xE687, 0xE688, 0xE689, 0xE68A, 0xE68B, 0xE68C, + 0xE68D, 0xE68E, 0xE68F, 0xE690, 0xE691, 0xE692, 0xE693, 0xE694, 0xE695, + 0xE696, 0xE697, 0xE698, 0xE699, 0xE69A, 0xE69B, 0xE69C, 0xE69D, 0xE69E, + 0xE69F, 0xE6A0, 0xE6A1, 0xE6A2, 0xE6A3, 0xE6A4, 0xE6A5, 0x30A1, 0x30A2, + 0x30A3, 0x30A4, 0x30A5, 0x30A6, 0x30A7, 0x30A8, 0x30A9, 0x30AA, 0x30AB, + 0x30AC, 0x30AD, 0x30AE, 0x30AF, 0x30B0, 0x30B1, 0x30B2, 0x30B3, 0x30B4, + 0x30B5, 0x30B6, 0x30B7, 0x30B8, 0x30B9, 0x30BA, 0x30BB, 0x30BC, 0x30BD, + 0x30BE, 0x30BF, 0x30C0, 0x30C1, 0x30C2, 0x30C3, 0x30C4, 0x30C5, 0x30C6, + 0x30C7, 0x30C8, 0x30C9, 0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF, + 0x30D0, 0x30D1, 0x30D2, 0x30D3, 0x30D4, 0x30D5, 0x30D6, 0x30D7, 0x30D8, + 0x30D9, 0x30DA, 0x30DB, 0x30DC, 0x30DD, 0x30DE, 0x30DF, 0x30E0, 0x30E1, + 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7, 0x30E8, 0x30E9, 0x30EA, + 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x30EF, 0x30F0, 0x30F1, 0x30F2, 0x30F3, + 0x30F4, 0x30F5, 0x30F6, 0xE77D, 0xE77E, 0xE77F, 0xE780, 0xE781, 0xE782, + 0xE783, 0xE784, 0, 0xE6A6, 0xE6A7, 0xE6A8, 0xE6A9, 0xE6AA, 0xE6AB, + 0xE6AC, 0xE6AD, 0xE6AE, 0xE6AF, 0xE6B0, 0xE6B1, 0xE6B2, 0xE6B3, 0xE6B4, + 0xE6B5, 0xE6B6, 0xE6B7, 0xE6B8, 0xE6B9, 0xE6BA, 0xE6BB, 0xE6BC, 0xE6BD, + 0xE6BE, 0xE6BF, 0xE6C0, 0xE6C1, 0xE6C2, 0xE6C3, 0xE6C4, 0xE6C5, 0xE6C6, + 0xE6C7, 0xE6C8, 0xE6C9, 0xE6CA, 0xE6CB, 0xE6CC, 0xE6CD, 0xE6CE, 0xE6CF, + 0xE6D0, 0xE6D1, 0xE6D2, 0xE6D3, 0xE6D4, 0xE6D5, 0xE6D6, 0xE6D7, 0xE6D8, + 0xE6D9, 0xE6DA, 0xE6DB, 0xE6DC, 0xE6DD, 0xE6DE, 0xE6DF, 0xE6E0, 0xE6E1, + 0xE6E2, 0xE6E3, 0xE6E4, 0, 0xE6E5, 0xE6E6, 0xE6E7, 0xE6E8, 0xE6E9, + 0xE6EA, 0xE6EB, 0xE6EC, 0xE6ED, 0xE6EE, 0xE6EF, 0xE6F0, 0xE6F1, 0xE6F2, + 0xE6F3, 0xE6F4, 0xE6F5, 0xE6F6, 0xE6F7, 0xE6F8, 0xE6F9, 0xE6FA, 0xE6FB, + 0xE6FC, 0xE6FD, 0xE6FE, 0xE6FF, 0xE700, 0xE701, 0xE702, 0xE703, 0xE704, + 0xE705, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, + 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, 0x03A1, + 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0xE785, 0xE786, + 0xE787, 0xE788, 0xE789, 0xE78A, 0xE78B, 0xE78C, 0x03B1, 0x03B2, 0x03B3, + 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, + 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03C6, + 0x03C7, 0x03C8, 0x03C9, 0xE78D, 0xE78E, 0xE78F, 0xE790, 0xE791, 0xE792, + 0xE793, 0xFE35, 0xFE36, 0xFE39, 0xFE3A, 0xFE3F, 0xFE40, 0xFE3D, 0xFE3E, + 0xFE41, 0xFE42, 0xFE43, 0xFE44, 0xE794, 0xE795, 0xFE3B, 0xFE3C, 0xFE37, + 0xFE38, 0xFE31, 0xE796, 0xFE33, 0xFE34, 0xE797, 0xE798, 0xE799, 0xE79A, + 0xE79B, 0xE79C, 0xE79D, 0xE79E, 0xE79F, 0, 0xE706, 0xE707, 0xE708, + 0xE709, 0xE70A, 0xE70B, 0xE70C, 0xE70D, 0xE70E, 0xE70F, 0xE710, 0xE711, + 0xE712, 0xE713, 0xE714, 0xE715, 0xE716, 0xE717, 0xE718, 0xE719, 0xE71A, + 0xE71B, 0xE71C, 0xE71D, 0xE71E, 0xE71F, 0xE720, 0xE721, 0xE722, 0xE723, + 0xE724, 0xE725, 0xE726, 0xE727, 0xE728, 0xE729, 0xE72A, 0xE72B, 0xE72C, + 0xE72D, 0xE72E, 0xE72F, 0xE730, 0xE731, 0xE732, 0xE733, 0xE734, 0xE735, + 0xE736, 0xE737, 0xE738, 0xE739, 0xE73A, 0xE73B, 0xE73C, 0xE73D, 0xE73E, + 0xE73F, 0xE740, 0xE741, 0xE742, 0xE743, 0xE744, 0, 0xE745, 0xE746, + 0xE747, 0xE748, 0xE749, 0xE74A, 0xE74B, 0xE74C, 0xE74D, 0xE74E, 0xE74F, + 0xE750, 0xE751, 0xE752, 0xE753, 0xE754, 0xE755, 0xE756, 0xE757, 0xE758, + 0xE759, 0xE75A, 0xE75B, 0xE75C, 0xE75D, 0xE75E, 0xE75F, 0xE760, 0xE761, + 0xE762, 0xE763, 0xE764, 0xE765, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, + 0x0415, 0x0401, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, + 0x041D, 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, + 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, + 0x042F, 0xE7A0, 0xE7A1, 0xE7A2, 0xE7A3, 0xE7A4, 0xE7A5, 0xE7A6, 0xE7A7, + 0xE7A8, 0xE7A9, 0xE7AA, 0xE7AB, 0xE7AC, 0xE7AD, 0xE7AE, 0x0430, 0x0431, + 0x0432, 0x0433, 0x0434, 0x0435, 0x0451, 0x0436, 0x0437, 0x0438, 0x0439, + 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, + 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, + 0x044C, 0x044D, 0x044E, 0x044F, 0xE7AF, 0xE7B0, 0xE7B1, 0xE7B2, 0xE7B3, + 0xE7B4, 0xE7B5, 0xE7B6, 0xE7B7, 0xE7B8, 0xE7B9, 0xE7BA, 0xE7BB, 0, + 0x02CA, 0x02CB, 0x02D9, 0x2013, 0x2015, 0x2025, 0x2035, 0x2105, 0x2109, + 0x2196, 0x2197, 0x2198, 0x2199, 0x2215, 0x221F, 0x2223, 0x2252, 0x2266, + 0x2267, 0x22BF, 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, 0x2556, + 0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E, 0x255F, + 0x2560, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567, 0x2568, + 0x2569, 0x256A, 0x256B, 0x256C, 0x256D, 0x256E, 0x256F, 0x2570, 0x2571, + 0x2572, 0x2573, 0x2581, 0x2582, 0x2583, 0x2584, 0x2585, 0x2586, 0x2587, + 0, 0x2588, 0x2589, 0x258A, 0x258B, 0x258C, 0x258D, 0x258E, 0x258F, + 0x2593, 0x2594, 0x2595, 0x25BC, 0x25BD, 0x25E2, 0x25E3, 0x25E4, 0x25E5, + 0x2609, 0x2295, 0x3012, 0x301D, 0x301E, 0xE7BC, 0xE7BD, 0xE7BE, 0xE7BF, + 0xE7C0, 0xE7C1, 0xE7C2, 0xE7C3, 0xE7C4, 0xE7C5, 0xE7C6, 0x0101, 0x00E1, + 0x01CE, 0x00E0, 0x0113, 0x00E9, 0x011B, 0x00E8, 0x012B, 0x00ED, 0x01D0, + 0x00EC, 0x014D, 0x00F3, 0x01D2, 0x00F2, 0x016B, 0x00FA, 0x01D4, 0x00F9, + 0x01D6, 0x01D8, 0x01DA, 0x01DC, 0x00FC, 0x00EA, 0x0251, 0x1E3F, 0x0144, + 0x0148, 0x01F9, 0x0261, 0xE7C9, 0xE7CA, 0xE7CB, 0xE7CC, 0x3105, 0x3106, + 0x3107, 0x3108, 0x3109, 0x310A, 0x310B, 0x310C, 0x310D, 0x310E, 0x310F, + 0x3110, 0x3111, 0x3112, 0x3113, 0x3114, 0x3115, 0x3116, 0x3117, 0x3118, + 0x3119, 0x311A, 0x311B, 0x311C, 0x311D, 0x311E, 0x311F, 0x3120, 0x3121, + 0x3122, 0x3123, 0x3124, 0x3125, 0x3126, 0x3127, 0x3128, 0x3129, 0xE7CD, + 0xE7CE, 0xE7CF, 0xE7D0, 0xE7D1, 0xE7D2, 0xE7D3, 0xE7D4, 0xE7D5, 0xE7D6, + 0xE7D7, 0xE7D8, 0xE7D9, 0xE7DA, 0xE7DB, 0xE7DC, 0xE7DD, 0xE7DE, 0xE7DF, + 0xE7E0, 0xE7E1, 0, 0x3021, 0x3022, 0x3023, 0x3024, 0x3025, 0x3026, + 0x3027, 0x3028, 0x3029, 0x32A3, 0x338E, 0x338F, 0x339C, 0x339D, 0x339E, + 0x33A1, 0x33C4, 0x33CE, 0x33D1, 0x33D2, 0x33D5, 0xFE30, 0xFFE2, 0xFFE4, + 0xE7E2, 0x2121, 0x3231, 0xE7E3, 0x2010, 0xE7E4, 0xE7E5, 0xE7E6, 0x30FC, + 0x309B, 0x309C, 0x30FD, 0x30FE, 0x3006, 0x309D, 0x309E, 0xFE49, 0xFE4A, + 0xFE4B, 0xFE4C, 0xFE4D, 0xFE4E, 0xFE4F, 0xFE50, 0xFE51, 0xFE52, 0xFE54, + 0xFE55, 0xFE56, 0xFE57, 0xFE59, 0xFE5A, 0xFE5B, 0xFE5C, 0xFE5D, 0xFE5E, + 0xFE5F, 0xFE60, 0xFE61, 0, 0xFE62, 0xFE63, 0xFE64, 0xFE65, 0xFE66, + 0xFE68, 0xFE69, 0xFE6A, 0xFE6B, 0x303E, 0x2FF0, 0x2FF1, 0x2FF2, 0x2FF3, + 0x2FF4, 0x2FF5, 0x2FF6, 0x2FF7, 0x2FF8, 0x2FF9, 0x2FFA, 0x2FFB, 0x3007, + 0xE7F4, 0xE7F5, 0xE7F6, 0xE7F7, 0xE7F8, 0xE7F9, 0xE7FA, 0xE7FB, 0xE7FC, + 0xE7FD, 0xE7FE, 0xE7FF, 0xE800, 0x2500, 0x2501, 0x2502, 0x2503, 0x2504, + 0x2505, 0x2506, 0x2507, 0x2508, 0x2509, 0x250A, 0x250B, 0x250C, 0x250D, + 0x250E, 0x250F, 0x2510, 0x2511, 0x2512, 0x2513, 0x2514, 0x2515, 0x2516, + 0x2517, 0x2518, 0x2519, 0x251A, 0x251B, 0x251C, 0x251D, 0x251E, 0x251F, + 0x2520, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527, 0x2528, + 0x2529, 0x252A, 0x252B, 0x252C, 0x252D, 0x252E, 0x252F, 0x2530, 0x2531, + 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537, 0x2538, 0x2539, 0x253A, + 0x253B, 0x253C, 0x253D, 0x253E, 0x253F, 0x2540, 0x2541, 0x2542, 0x2543, + 0x2544, 0x2545, 0x2546, 0x2547, 0x2548, 0x2549, 0x254A, 0x254B, 0xE801, + 0xE802, 0xE803, 0xE804, 0xE805, 0xE806, 0xE807, 0xE808, 0xE809, 0xE80A, + 0xE80B, 0xE80C, 0xE80D, 0xE80E, 0xE80F, 0, 0x72DC, 0x72DD, 0x72DF, + 0x72E2, 0x72E3, 0x72E4, 0x72E5, 0x72E6, 0x72E7, 0x72EA, 0x72EB, 0x72F5, + 0x72F6, 0x72F9, 0x72FD, 0x72FE, 0x72FF, 0x7300, 0x7302, 0x7304, 0x7305, + 0x7306, 0x7307, 0x7308, 0x7309, 0x730B, 0x730C, 0x730D, 0x730F, 0x7310, + 0x7311, 0x7312, 0x7314, 0x7318, 0x7319, 0x731A, 0x731F, 0x7320, 0x7323, + 0x7324, 0x7326, 0x7327, 0x7328, 0x732D, 0x732F, 0x7330, 0x7332, 0x7333, + 0x7335, 0x7336, 0x733A, 0x733B, 0x733C, 0x733D, 0x7340, 0x7341, 0x7342, + 0x7343, 0x7344, 0x7345, 0x7346, 0x7347, 0x7348, 0, 0x7349, 0x734A, + 0x734B, 0x734C, 0x734E, 0x734F, 0x7351, 0x7353, 0x7354, 0x7355, 0x7356, + 0x7358, 0x7359, 0x735A, 0x735B, 0x735C, 0x735D, 0x735E, 0x735F, 0x7361, + 0x7362, 0x7363, 0x7364, 0x7365, 0x7366, 0x7367, 0x7368, 0x7369, 0x736A, + 0x736B, 0x736E, 0x7370, 0x7371, 0xE000, 0xE001, 0xE002, 0xE003, 0xE004, + 0xE005, 0xE006, 0xE007, 0xE008, 0xE009, 0xE00A, 0xE00B, 0xE00C, 0xE00D, + 0xE00E, 0xE00F, 0xE010, 0xE011, 0xE012, 0xE013, 0xE014, 0xE015, 0xE016, + 0xE017, 0xE018, 0xE019, 0xE01A, 0xE01B, 0xE01C, 0xE01D, 0xE01E, 0xE01F, + 0xE020, 0xE021, 0xE022, 0xE023, 0xE024, 0xE025, 0xE026, 0xE027, 0xE028, + 0xE029, 0xE02A, 0xE02B, 0xE02C, 0xE02D, 0xE02E, 0xE02F, 0xE030, 0xE031, + 0xE032, 0xE033, 0xE034, 0xE035, 0xE036, 0xE037, 0xE038, 0xE039, 0xE03A, + 0xE03B, 0xE03C, 0xE03D, 0xE03E, 0xE03F, 0xE040, 0xE041, 0xE042, 0xE043, + 0xE044, 0xE045, 0xE046, 0xE047, 0xE048, 0xE049, 0xE04A, 0xE04B, 0xE04C, + 0xE04D, 0xE04E, 0xE04F, 0xE050, 0xE051, 0xE052, 0xE053, 0xE054, 0xE055, + 0xE056, 0xE057, 0xE058, 0xE059, 0xE05A, 0xE05B, 0xE05C, 0xE05D, 0, + 0x7372, 0x7373, 0x7374, 0x7375, 0x7376, 0x7377, 0x7378, 0x7379, 0x737A, + 0x737B, 0x737C, 0x737D, 0x737F, 0x7380, 0x7381, 0x7382, 0x7383, 0x7385, + 0x7386, 0x7388, 0x738A, 0x738C, 0x738D, 0x738F, 0x7390, 0x7392, 0x7393, + 0x7394, 0x7395, 0x7397, 0x7398, 0x7399, 0x739A, 0x739C, 0x739D, 0x739E, + 0x73A0, 0x73A1, 0x73A3, 0x73A4, 0x73A5, 0x73A6, 0x73A7, 0x73A8, 0x73AA, + 0x73AC, 0x73AD, 0x73B1, 0x73B4, 0x73B5, 0x73B6, 0x73B8, 0x73B9, 0x73BC, + 0x73BD, 0x73BE, 0x73BF, 0x73C1, 0x73C3, 0x73C4, 0x73C5, 0x73C6, 0x73C7, + 0, 0x73CB, 0x73CC, 0x73CE, 0x73D2, 0x73D3, 0x73D4, 0x73D5, 0x73D6, + 0x73D7, 0x73D8, 0x73DA, 0x73DB, 0x73DC, 0x73DD, 0x73DF, 0x73E1, 0x73E2, + 0x73E3, 0x73E4, 0x73E6, 0x73E8, 0x73EA, 0x73EB, 0x73EC, 0x73EE, 0x73EF, + 0x73F0, 0x73F1, 0x73F3, 0x73F4, 0x73F5, 0x73F6, 0x73F7, 0xE05E, 0xE05F, + 0xE060, 0xE061, 0xE062, 0xE063, 0xE064, 0xE065, 0xE066, 0xE067, 0xE068, + 0xE069, 0xE06A, 0xE06B, 0xE06C, 0xE06D, 0xE06E, 0xE06F, 0xE070, 0xE071, + 0xE072, 0xE073, 0xE074, 0xE075, 0xE076, 0xE077, 0xE078, 0xE079, 0xE07A, + 0xE07B, 0xE07C, 0xE07D, 0xE07E, 0xE07F, 0xE080, 0xE081, 0xE082, 0xE083, + 0xE084, 0xE085, 0xE086, 0xE087, 0xE088, 0xE089, 0xE08A, 0xE08B, 0xE08C, + 0xE08D, 0xE08E, 0xE08F, 0xE090, 0xE091, 0xE092, 0xE093, 0xE094, 0xE095, + 0xE096, 0xE097, 0xE098, 0xE099, 0xE09A, 0xE09B, 0xE09C, 0xE09D, 0xE09E, + 0xE09F, 0xE0A0, 0xE0A1, 0xE0A2, 0xE0A3, 0xE0A4, 0xE0A5, 0xE0A6, 0xE0A7, + 0xE0A8, 0xE0A9, 0xE0AA, 0xE0AB, 0xE0AC, 0xE0AD, 0xE0AE, 0xE0AF, 0xE0B0, + 0xE0B1, 0xE0B2, 0xE0B3, 0xE0B4, 0xE0B5, 0xE0B6, 0xE0B7, 0xE0B8, 0xE0B9, + 0xE0BA, 0xE0BB, 0, 0x73F8, 0x73F9, 0x73FA, 0x73FB, 0x73FC, 0x73FD, + 0x73FE, 0x73FF, 0x7400, 0x7401, 0x7402, 0x7404, 0x7407, 0x7408, 0x740B, + 0x740C, 0x740D, 0x740E, 0x7411, 0x7412, 0x7413, 0x7414, 0x7415, 0x7416, + 0x7417, 0x7418, 0x7419, 0x741C, 0x741D, 0x741E, 0x741F, 0x7420, 0x7421, + 0x7423, 0x7424, 0x7427, 0x7429, 0x742B, 0x742D, 0x742F, 0x7431, 0x7432, + 0x7437, 0x7438, 0x7439, 0x743A, 0x743B, 0x743D, 0x743E, 0x743F, 0x7440, + 0x7442, 0x7443, 0x7444, 0x7445, 0x7446, 0x7447, 0x7448, 0x7449, 0x744A, + 0x744B, 0x744C, 0x744D, 0, 0x744E, 0x744F, 0x7450, 0x7451, 0x7452, + 0x7453, 0x7454, 0x7456, 0x7458, 0x745D, 0x7460, 0x7461, 0x7462, 0x7463, + 0x7464, 0x7465, 0x7466, 0x7467, 0x7468, 0x7469, 0x746A, 0x746B, 0x746C, + 0x746E, 0x746F, 0x7471, 0x7472, 0x7473, 0x7474, 0x7475, 0x7478, 0x7479, + 0x747A, 0xE0BC, 0xE0BD, 0xE0BE, 0xE0BF, 0xE0C0, 0xE0C1, 0xE0C2, 0xE0C3, + 0xE0C4, 0xE0C5, 0xE0C6, 0xE0C7, 0xE0C8, 0xE0C9, 0xE0CA, 0xE0CB, 0xE0CC, + 0xE0CD, 0xE0CE, 0xE0CF, 0xE0D0, 0xE0D1, 0xE0D2, 0xE0D3, 0xE0D4, 0xE0D5, + 0xE0D6, 0xE0D7, 0xE0D8, 0xE0D9, 0xE0DA, 0xE0DB, 0xE0DC, 0xE0DD, 0xE0DE, + 0xE0DF, 0xE0E0, 0xE0E1, 0xE0E2, 0xE0E3, 0xE0E4, 0xE0E5, 0xE0E6, 0xE0E7, + 0xE0E8, 0xE0E9, 0xE0EA, 0xE0EB, 0xE0EC, 0xE0ED, 0xE0EE, 0xE0EF, 0xE0F0, + 0xE0F1, 0xE0F2, 0xE0F3, 0xE0F4, 0xE0F5, 0xE0F6, 0xE0F7, 0xE0F8, 0xE0F9, + 0xE0FA, 0xE0FB, 0xE0FC, 0xE0FD, 0xE0FE, 0xE0FF, 0xE100, 0xE101, 0xE102, + 0xE103, 0xE104, 0xE105, 0xE106, 0xE107, 0xE108, 0xE109, 0xE10A, 0xE10B, + 0xE10C, 0xE10D, 0xE10E, 0xE10F, 0xE110, 0xE111, 0xE112, 0xE113, 0xE114, + 0xE115, 0xE116, 0xE117, 0xE118, 0xE119, 0, 0x747B, 0x747C, 0x747D, + 0x747F, 0x7482, 0x7484, 0x7485, 0x7486, 0x7488, 0x7489, 0x748A, 0x748C, + 0x748D, 0x748F, 0x7491, 0x7492, 0x7493, 0x7494, 0x7495, 0x7496, 0x7497, + 0x7498, 0x7499, 0x749A, 0x749B, 0x749D, 0x749F, 0x74A0, 0x74A1, 0x74A2, + 0x74A3, 0x74A4, 0x74A5, 0x74A6, 0x74AA, 0x74AB, 0x74AC, 0x74AD, 0x74AE, + 0x74AF, 0x74B0, 0x74B1, 0x74B2, 0x74B3, 0x74B4, 0x74B5, 0x74B6, 0x74B7, + 0x74B8, 0x74B9, 0x74BB, 0x74BC, 0x74BD, 0x74BE, 0x74BF, 0x74C0, 0x74C1, + 0x74C2, 0x74C3, 0x74C4, 0x74C5, 0x74C6, 0x74C7, 0, 0x74C8, 0x74C9, + 0x74CA, 0x74CB, 0x74CC, 0x74CD, 0x74CE, 0x74CF, 0x74D0, 0x74D1, 0x74D3, + 0x74D4, 0x74D5, 0x74D6, 0x74D7, 0x74D8, 0x74D9, 0x74DA, 0x74DB, 0x74DD, + 0x74DF, 0x74E1, 0x74E5, 0x74E7, 0x74E8, 0x74E9, 0x74EA, 0x74EB, 0x74EC, + 0x74ED, 0x74F0, 0x74F1, 0x74F2, 0xE11A, 0xE11B, 0xE11C, 0xE11D, 0xE11E, + 0xE11F, 0xE120, 0xE121, 0xE122, 0xE123, 0xE124, 0xE125, 0xE126, 0xE127, + 0xE128, 0xE129, 0xE12A, 0xE12B, 0xE12C, 0xE12D, 0xE12E, 0xE12F, 0xE130, + 0xE131, 0xE132, 0xE133, 0xE134, 0xE135, 0xE136, 0xE137, 0xE138, 0xE139, + 0xE13A, 0xE13B, 0xE13C, 0xE13D, 0xE13E, 0xE13F, 0xE140, 0xE141, 0xE142, + 0xE143, 0xE144, 0xE145, 0xE146, 0xE147, 0xE148, 0xE149, 0xE14A, 0xE14B, + 0xE14C, 0xE14D, 0xE14E, 0xE14F, 0xE150, 0xE151, 0xE152, 0xE153, 0xE154, + 0xE155, 0xE156, 0xE157, 0xE158, 0xE159, 0xE15A, 0xE15B, 0xE15C, 0xE15D, + 0xE15E, 0xE15F, 0xE160, 0xE161, 0xE162, 0xE163, 0xE164, 0xE165, 0xE166, + 0xE167, 0xE168, 0xE169, 0xE16A, 0xE16B, 0xE16C, 0xE16D, 0xE16E, 0xE16F, + 0xE170, 0xE171, 0xE172, 0xE173, 0xE174, 0xE175, 0xE176, 0xE177, 0, + 0x74F3, 0x74F5, 0x74F8, 0x74F9, 0x74FA, 0x74FB, 0x74FC, 0x74FD, 0x74FE, + 0x7500, 0x7501, 0x7502, 0x7503, 0x7505, 0x7506, 0x7507, 0x7508, 0x7509, + 0x750A, 0x750B, 0x750C, 0x750E, 0x7510, 0x7512, 0x7514, 0x7515, 0x7516, + 0x7517, 0x751B, 0x751D, 0x751E, 0x7520, 0x7521, 0x7522, 0x7523, 0x7524, + 0x7526, 0x7527, 0x752A, 0x752E, 0x7534, 0x7536, 0x7539, 0x753C, 0x753D, + 0x753F, 0x7541, 0x7542, 0x7543, 0x7544, 0x7546, 0x7547, 0x7549, 0x754A, + 0x754D, 0x7550, 0x7551, 0x7552, 0x7553, 0x7555, 0x7556, 0x7557, 0x7558, + 0, 0x755D, 0x755E, 0x755F, 0x7560, 0x7561, 0x7562, 0x7563, 0x7564, + 0x7567, 0x7568, 0x7569, 0x756B, 0x756C, 0x756D, 0x756E, 0x756F, 0x7570, + 0x7571, 0x7573, 0x7575, 0x7576, 0x7577, 0x757A, 0x757B, 0x757C, 0x757D, + 0x757E, 0x7580, 0x7581, 0x7582, 0x7584, 0x7585, 0x7587, 0xE178, 0xE179, + 0xE17A, 0xE17B, 0xE17C, 0xE17D, 0xE17E, 0xE17F, 0xE180, 0xE181, 0xE182, + 0xE183, 0xE184, 0xE185, 0xE186, 0xE187, 0xE188, 0xE189, 0xE18A, 0xE18B, + 0xE18C, 0xE18D, 0xE18E, 0xE18F, 0xE190, 0xE191, 0xE192, 0xE193, 0xE194, + 0xE195, 0xE196, 0xE197, 0xE198, 0xE199, 0xE19A, 0xE19B, 0xE19C, 0xE19D, + 0xE19E, 0xE19F, 0xE1A0, 0xE1A1, 0xE1A2, 0xE1A3, 0xE1A4, 0xE1A5, 0xE1A6, + 0xE1A7, 0xE1A8, 0xE1A9, 0xE1AA, 0xE1AB, 0xE1AC, 0xE1AD, 0xE1AE, 0xE1AF, + 0xE1B0, 0xE1B1, 0xE1B2, 0xE1B3, 0xE1B4, 0xE1B5, 0xE1B6, 0xE1B7, 0xE1B8, + 0xE1B9, 0xE1BA, 0xE1BB, 0xE1BC, 0xE1BD, 0xE1BE, 0xE1BF, 0xE1C0, 0xE1C1, + 0xE1C2, 0xE1C3, 0xE1C4, 0xE1C5, 0xE1C6, 0xE1C7, 0xE1C8, 0xE1C9, 0xE1CA, + 0xE1CB, 0xE1CC, 0xE1CD, 0xE1CE, 0xE1CF, 0xE1D0, 0xE1D1, 0xE1D2, 0xE1D3, + 0xE1D4, 0xE1D5, 0, 0x7588, 0x7589, 0x758A, 0x758C, 0x758D, 0x758E, + 0x7590, 0x7593, 0x7595, 0x7598, 0x759B, 0x759C, 0x759E, 0x75A2, 0x75A6, + 0x75A7, 0x75A8, 0x75A9, 0x75AA, 0x75AD, 0x75B6, 0x75B7, 0x75BA, 0x75BB, + 0x75BF, 0x75C0, 0x75C1, 0x75C6, 0x75CB, 0x75CC, 0x75CE, 0x75CF, 0x75D0, + 0x75D1, 0x75D3, 0x75D7, 0x75D9, 0x75DA, 0x75DC, 0x75DD, 0x75DF, 0x75E0, + 0x75E1, 0x75E5, 0x75E9, 0x75EC, 0x75ED, 0x75EE, 0x75EF, 0x75F2, 0x75F3, + 0x75F5, 0x75F6, 0x75F7, 0x75F8, 0x75FA, 0x75FB, 0x75FD, 0x75FE, 0x7602, + 0x7604, 0x7606, 0x7607, 0, 0x7608, 0x7609, 0x760B, 0x760D, 0x760E, + 0x760F, 0x7611, 0x7612, 0x7613, 0x7614, 0x7616, 0x761A, 0x761C, 0x761D, + 0x761E, 0x7621, 0x7623, 0x7627, 0x7628, 0x762C, 0x762E, 0x762F, 0x7631, + 0x7632, 0x7636, 0x7637, 0x7639, 0x763A, 0x763B, 0x763D, 0x7641, 0x7642, + 0x7644, 0xE1D6, 0xE1D7, 0xE1D8, 0xE1D9, 0xE1DA, 0xE1DB, 0xE1DC, 0xE1DD, + 0xE1DE, 0xE1DF, 0xE1E0, 0xE1E1, 0xE1E2, 0xE1E3, 0xE1E4, 0xE1E5, 0xE1E6, + 0xE1E7, 0xE1E8, 0xE1E9, 0xE1EA, 0xE1EB, 0xE1EC, 0xE1ED, 0xE1EE, 0xE1EF, + 0xE1F0, 0xE1F1, 0xE1F2, 0xE1F3, 0xE1F4, 0xE1F5, 0xE1F6, 0xE1F7, 0xE1F8, + 0xE1F9, 0xE1FA, 0xE1FB, 0xE1FC, 0xE1FD, 0xE1FE, 0xE1FF, 0xE200, 0xE201, + 0xE202, 0xE203, 0xE204, 0xE205, 0xE206, 0xE207, 0xE208, 0xE209, 0xE20A, + 0xE20B, 0xE20C, 0xE20D, 0xE20E, 0xE20F, 0xE210, 0xE211, 0xE212, 0xE213, + 0xE214, 0xE215, 0xE216, 0xE217, 0xE218, 0xE219, 0xE21A, 0xE21B, 0xE21C, + 0xE21D, 0xE21E, 0xE21F, 0xE220, 0xE221, 0xE222, 0xE223, 0xE224, 0xE225, + 0xE226, 0xE227, 0xE228, 0xE229, 0xE22A, 0xE22B, 0xE22C, 0xE22D, 0xE22E, + 0xE22F, 0xE230, 0xE231, 0xE232, 0xE233, 0, 0x7645, 0x7646, 0x7647, + 0x7648, 0x7649, 0x764A, 0x764B, 0x764E, 0x764F, 0x7650, 0x7651, 0x7652, + 0x7653, 0x7655, 0x7657, 0x7658, 0x7659, 0x765A, 0x765B, 0x765D, 0x765F, + 0x7660, 0x7661, 0x7662, 0x7664, 0x7665, 0x7666, 0x7667, 0x7668, 0x7669, + 0x766A, 0x766C, 0x766D, 0x766E, 0x7670, 0x7671, 0x7672, 0x7673, 0x7674, + 0x7675, 0x7676, 0x7677, 0x7679, 0x767A, 0x767C, 0x767F, 0x7680, 0x7681, + 0x7683, 0x7685, 0x7689, 0x768A, 0x768C, 0x768D, 0x768F, 0x7690, 0x7692, + 0x7694, 0x7695, 0x7697, 0x7698, 0x769A, 0x769B, 0, 0x769C, 0x769D, + 0x769E, 0x769F, 0x76A0, 0x76A1, 0x76A2, 0x76A3, 0x76A5, 0x76A6, 0x76A7, + 0x76A8, 0x76A9, 0x76AA, 0x76AB, 0x76AC, 0x76AD, 0x76AF, 0x76B0, 0x76B3, + 0x76B5, 0x76B6, 0x76B7, 0x76B8, 0x76B9, 0x76BA, 0x76BB, 0x76BC, 0x76BD, + 0x76BE, 0x76C0, 0x76C1, 0x76C3, 0x554A, 0x963F, 0x57C3, 0x6328, 0x54CE, + 0x5509, 0x54C0, 0x7691, 0x764C, 0x853C, 0x77EE, 0x827E, 0x788D, 0x7231, + 0x9698, 0x978D, 0x6C28, 0x5B89, 0x4FFA, 0x6309, 0x6697, 0x5CB8, 0x80FA, + 0x6848, 0x80AE, 0x6602, 0x76CE, 0x51F9, 0x6556, 0x71AC, 0x7FF1, 0x8884, + 0x50B2, 0x5965, 0x61CA, 0x6FB3, 0x82AD, 0x634C, 0x6252, 0x53ED, 0x5427, + 0x7B06, 0x516B, 0x75A4, 0x5DF4, 0x62D4, 0x8DCB, 0x9776, 0x628A, 0x8019, + 0x575D, 0x9738, 0x7F62, 0x7238, 0x767D, 0x67CF, 0x767E, 0x6446, 0x4F70, + 0x8D25, 0x62DC, 0x7A17, 0x6591, 0x73ED, 0x642C, 0x6273, 0x822C, 0x9881, + 0x677F, 0x7248, 0x626E, 0x62CC, 0x4F34, 0x74E3, 0x534A, 0x529E, 0x7ECA, + 0x90A6, 0x5E2E, 0x6886, 0x699C, 0x8180, 0x7ED1, 0x68D2, 0x78C5, 0x868C, + 0x9551, 0x508D, 0x8C24, 0x82DE, 0x80DE, 0x5305, 0x8912, 0x5265, 0, + 0x76C4, 0x76C7, 0x76C9, 0x76CB, 0x76CC, 0x76D3, 0x76D5, 0x76D9, 0x76DA, + 0x76DC, 0x76DD, 0x76DE, 0x76E0, 0x76E1, 0x76E2, 0x76E3, 0x76E4, 0x76E6, + 0x76E7, 0x76E8, 0x76E9, 0x76EA, 0x76EB, 0x76EC, 0x76ED, 0x76F0, 0x76F3, + 0x76F5, 0x76F6, 0x76F7, 0x76FA, 0x76FB, 0x76FD, 0x76FF, 0x7700, 0x7702, + 0x7703, 0x7705, 0x7706, 0x770A, 0x770C, 0x770E, 0x770F, 0x7710, 0x7711, + 0x7712, 0x7713, 0x7714, 0x7715, 0x7716, 0x7717, 0x7718, 0x771B, 0x771C, + 0x771D, 0x771E, 0x7721, 0x7723, 0x7724, 0x7725, 0x7727, 0x772A, 0x772B, + 0, 0x772C, 0x772E, 0x7730, 0x7731, 0x7732, 0x7733, 0x7734, 0x7739, + 0x773B, 0x773D, 0x773E, 0x773F, 0x7742, 0x7744, 0x7745, 0x7746, 0x7748, + 0x7749, 0x774A, 0x774B, 0x774C, 0x774D, 0x774E, 0x774F, 0x7752, 0x7753, + 0x7754, 0x7755, 0x7756, 0x7757, 0x7758, 0x7759, 0x775C, 0x8584, 0x96F9, + 0x4FDD, 0x5821, 0x9971, 0x5B9D, 0x62B1, 0x62A5, 0x66B4, 0x8C79, 0x9C8D, + 0x7206, 0x676F, 0x7891, 0x60B2, 0x5351, 0x5317, 0x8F88, 0x80CC, 0x8D1D, + 0x94A1, 0x500D, 0x72C8, 0x5907, 0x60EB, 0x7119, 0x88AB, 0x5954, 0x82EF, + 0x672C, 0x7B28, 0x5D29, 0x7EF7, 0x752D, 0x6CF5, 0x8E66, 0x8FF8, 0x903C, + 0x9F3B, 0x6BD4, 0x9119, 0x7B14, 0x5F7C, 0x78A7, 0x84D6, 0x853D, 0x6BD5, + 0x6BD9, 0x6BD6, 0x5E01, 0x5E87, 0x75F9, 0x95ED, 0x655D, 0x5F0A, 0x5FC5, + 0x8F9F, 0x58C1, 0x81C2, 0x907F, 0x965B, 0x97AD, 0x8FB9, 0x7F16, 0x8D2C, + 0x6241, 0x4FBF, 0x53D8, 0x535E, 0x8FA8, 0x8FA9, 0x8FAB, 0x904D, 0x6807, + 0x5F6A, 0x8198, 0x8868, 0x9CD6, 0x618B, 0x522B, 0x762A, 0x5F6C, 0x658C, + 0x6FD2, 0x6EE8, 0x5BBE, 0x6448, 0x5175, 0x51B0, 0x67C4, 0x4E19, 0x79C9, + 0x997C, 0x70B3, 0, 0x775D, 0x775E, 0x775F, 0x7760, 0x7764, 0x7767, + 0x7769, 0x776A, 0x776D, 0x776E, 0x776F, 0x7770, 0x7771, 0x7772, 0x7773, + 0x7774, 0x7775, 0x7776, 0x7777, 0x7778, 0x777A, 0x777B, 0x777C, 0x7781, + 0x7782, 0x7783, 0x7786, 0x7787, 0x7788, 0x7789, 0x778A, 0x778B, 0x778F, + 0x7790, 0x7793, 0x7794, 0x7795, 0x7796, 0x7797, 0x7798, 0x7799, 0x779A, + 0x779B, 0x779C, 0x779D, 0x779E, 0x77A1, 0x77A3, 0x77A4, 0x77A6, 0x77A8, + 0x77AB, 0x77AD, 0x77AE, 0x77AF, 0x77B1, 0x77B2, 0x77B4, 0x77B6, 0x77B7, + 0x77B8, 0x77B9, 0x77BA, 0, 0x77BC, 0x77BE, 0x77C0, 0x77C1, 0x77C2, + 0x77C3, 0x77C4, 0x77C5, 0x77C6, 0x77C7, 0x77C8, 0x77C9, 0x77CA, 0x77CB, + 0x77CC, 0x77CE, 0x77CF, 0x77D0, 0x77D1, 0x77D2, 0x77D3, 0x77D4, 0x77D5, + 0x77D6, 0x77D8, 0x77D9, 0x77DA, 0x77DD, 0x77DE, 0x77DF, 0x77E0, 0x77E1, + 0x77E4, 0x75C5, 0x5E76, 0x73BB, 0x83E0, 0x64AD, 0x62E8, 0x94B5, 0x6CE2, + 0x535A, 0x52C3, 0x640F, 0x94C2, 0x7B94, 0x4F2F, 0x5E1B, 0x8236, 0x8116, + 0x818A, 0x6E24, 0x6CCA, 0x9A73, 0x6355, 0x535C, 0x54FA, 0x8865, 0x57E0, + 0x4E0D, 0x5E03, 0x6B65, 0x7C3F, 0x90E8, 0x6016, 0x64E6, 0x731C, 0x88C1, + 0x6750, 0x624D, 0x8D22, 0x776C, 0x8E29, 0x91C7, 0x5F69, 0x83DC, 0x8521, + 0x9910, 0x53C2, 0x8695, 0x6B8B, 0x60ED, 0x60E8, 0x707F, 0x82CD, 0x8231, + 0x4ED3, 0x6CA7, 0x85CF, 0x64CD, 0x7CD9, 0x69FD, 0x66F9, 0x8349, 0x5395, + 0x7B56, 0x4FA7, 0x518C, 0x6D4B, 0x5C42, 0x8E6D, 0x63D2, 0x53C9, 0x832C, + 0x8336, 0x67E5, 0x78B4, 0x643D, 0x5BDF, 0x5C94, 0x5DEE, 0x8BE7, 0x62C6, + 0x67F4, 0x8C7A, 0x6400, 0x63BA, 0x8749, 0x998B, 0x8C17, 0x7F20, 0x94F2, + 0x4EA7, 0x9610, 0x98A4, 0x660C, 0x7316, 0, 0x77E6, 0x77E8, 0x77EA, + 0x77EF, 0x77F0, 0x77F1, 0x77F2, 0x77F4, 0x77F5, 0x77F7, 0x77F9, 0x77FA, + 0x77FB, 0x77FC, 0x7803, 0x7804, 0x7805, 0x7806, 0x7807, 0x7808, 0x780A, + 0x780B, 0x780E, 0x780F, 0x7810, 0x7813, 0x7815, 0x7819, 0x781B, 0x781E, + 0x7820, 0x7821, 0x7822, 0x7824, 0x7828, 0x782A, 0x782B, 0x782E, 0x782F, + 0x7831, 0x7832, 0x7833, 0x7835, 0x7836, 0x783D, 0x783F, 0x7841, 0x7842, + 0x7843, 0x7844, 0x7846, 0x7848, 0x7849, 0x784A, 0x784B, 0x784D, 0x784F, + 0x7851, 0x7853, 0x7854, 0x7858, 0x7859, 0x785A, 0, 0x785B, 0x785C, + 0x785E, 0x785F, 0x7860, 0x7861, 0x7862, 0x7863, 0x7864, 0x7865, 0x7866, + 0x7867, 0x7868, 0x7869, 0x786F, 0x7870, 0x7871, 0x7872, 0x7873, 0x7874, + 0x7875, 0x7876, 0x7878, 0x7879, 0x787A, 0x787B, 0x787D, 0x787E, 0x787F, + 0x7880, 0x7881, 0x7882, 0x7883, 0x573A, 0x5C1D, 0x5E38, 0x957F, 0x507F, + 0x80A0, 0x5382, 0x655E, 0x7545, 0x5531, 0x5021, 0x8D85, 0x6284, 0x949E, + 0x671D, 0x5632, 0x6F6E, 0x5DE2, 0x5435, 0x7092, 0x8F66, 0x626F, 0x64A4, + 0x63A3, 0x5F7B, 0x6F88, 0x90F4, 0x81E3, 0x8FB0, 0x5C18, 0x6668, 0x5FF1, + 0x6C89, 0x9648, 0x8D81, 0x886C, 0x6491, 0x79F0, 0x57CE, 0x6A59, 0x6210, + 0x5448, 0x4E58, 0x7A0B, 0x60E9, 0x6F84, 0x8BDA, 0x627F, 0x901E, 0x9A8B, + 0x79E4, 0x5403, 0x75F4, 0x6301, 0x5319, 0x6C60, 0x8FDF, 0x5F1B, 0x9A70, + 0x803B, 0x9F7F, 0x4F88, 0x5C3A, 0x8D64, 0x7FC5, 0x65A5, 0x70BD, 0x5145, + 0x51B2, 0x866B, 0x5D07, 0x5BA0, 0x62BD, 0x916C, 0x7574, 0x8E0C, 0x7A20, + 0x6101, 0x7B79, 0x4EC7, 0x7EF8, 0x7785, 0x4E11, 0x81ED, 0x521D, 0x51FA, + 0x6A71, 0x53A8, 0x8E87, 0x9504, 0x96CF, 0x6EC1, 0x9664, 0x695A, 0, + 0x7884, 0x7885, 0x7886, 0x7888, 0x788A, 0x788B, 0x788F, 0x7890, 0x7892, + 0x7894, 0x7895, 0x7896, 0x7899, 0x789D, 0x789E, 0x78A0, 0x78A2, 0x78A4, + 0x78A6, 0x78A8, 0x78A9, 0x78AA, 0x78AB, 0x78AC, 0x78AD, 0x78AE, 0x78AF, + 0x78B5, 0x78B6, 0x78B7, 0x78B8, 0x78BA, 0x78BB, 0x78BC, 0x78BD, 0x78BF, + 0x78C0, 0x78C2, 0x78C3, 0x78C4, 0x78C6, 0x78C7, 0x78C8, 0x78CC, 0x78CD, + 0x78CE, 0x78CF, 0x78D1, 0x78D2, 0x78D3, 0x78D6, 0x78D7, 0x78D8, 0x78DA, + 0x78DB, 0x78DC, 0x78DD, 0x78DE, 0x78DF, 0x78E0, 0x78E1, 0x78E2, 0x78E3, + 0, 0x78E4, 0x78E5, 0x78E6, 0x78E7, 0x78E9, 0x78EA, 0x78EB, 0x78ED, + 0x78EE, 0x78EF, 0x78F0, 0x78F1, 0x78F3, 0x78F5, 0x78F6, 0x78F8, 0x78F9, + 0x78FB, 0x78FC, 0x78FD, 0x78FE, 0x78FF, 0x7900, 0x7902, 0x7903, 0x7904, + 0x7906, 0x7907, 0x7908, 0x7909, 0x790A, 0x790B, 0x790C, 0x7840, 0x50A8, + 0x77D7, 0x6410, 0x89E6, 0x5904, 0x63E3, 0x5DDD, 0x7A7F, 0x693D, 0x4F20, + 0x8239, 0x5598, 0x4E32, 0x75AE, 0x7A97, 0x5E62, 0x5E8A, 0x95EF, 0x521B, + 0x5439, 0x708A, 0x6376, 0x9524, 0x5782, 0x6625, 0x693F, 0x9187, 0x5507, + 0x6DF3, 0x7EAF, 0x8822, 0x6233, 0x7EF0, 0x75B5, 0x8328, 0x78C1, 0x96CC, + 0x8F9E, 0x6148, 0x74F7, 0x8BCD, 0x6B64, 0x523A, 0x8D50, 0x6B21, 0x806A, + 0x8471, 0x56F1, 0x5306, 0x4ECE, 0x4E1B, 0x51D1, 0x7C97, 0x918B, 0x7C07, + 0x4FC3, 0x8E7F, 0x7BE1, 0x7A9C, 0x6467, 0x5D14, 0x50AC, 0x8106, 0x7601, + 0x7CB9, 0x6DEC, 0x7FE0, 0x6751, 0x5B58, 0x5BF8, 0x78CB, 0x64AE, 0x6413, + 0x63AA, 0x632B, 0x9519, 0x642D, 0x8FBE, 0x7B54, 0x7629, 0x6253, 0x5927, + 0x5446, 0x6B79, 0x50A3, 0x6234, 0x5E26, 0x6B86, 0x4EE3, 0x8D37, 0x888B, + 0x5F85, 0x902E, 0, 0x790D, 0x790E, 0x790F, 0x7910, 0x7911, 0x7912, + 0x7914, 0x7915, 0x7916, 0x7917, 0x7918, 0x7919, 0x791A, 0x791B, 0x791C, + 0x791D, 0x791F, 0x7920, 0x7921, 0x7922, 0x7923, 0x7925, 0x7926, 0x7927, + 0x7928, 0x7929, 0x792A, 0x792B, 0x792C, 0x792D, 0x792E, 0x792F, 0x7930, + 0x7931, 0x7932, 0x7933, 0x7935, 0x7936, 0x7937, 0x7938, 0x7939, 0x793D, + 0x793F, 0x7942, 0x7943, 0x7944, 0x7945, 0x7947, 0x794A, 0x794B, 0x794C, + 0x794D, 0x794E, 0x794F, 0x7950, 0x7951, 0x7952, 0x7954, 0x7955, 0x7958, + 0x7959, 0x7961, 0x7963, 0, 0x7964, 0x7966, 0x7969, 0x796A, 0x796B, + 0x796C, 0x796E, 0x7970, 0x7971, 0x7972, 0x7973, 0x7974, 0x7975, 0x7976, + 0x7979, 0x797B, 0x797C, 0x797D, 0x797E, 0x797F, 0x7982, 0x7983, 0x7986, + 0x7987, 0x7988, 0x7989, 0x798B, 0x798C, 0x798D, 0x798E, 0x7990, 0x7991, + 0x7992, 0x6020, 0x803D, 0x62C5, 0x4E39, 0x5355, 0x90F8, 0x63B8, 0x80C6, + 0x65E6, 0x6C2E, 0x4F46, 0x60EE, 0x6DE1, 0x8BDE, 0x5F39, 0x86CB, 0x5F53, + 0x6321, 0x515A, 0x8361, 0x6863, 0x5200, 0x6363, 0x8E48, 0x5012, 0x5C9B, + 0x7977, 0x5BFC, 0x5230, 0x7A3B, 0x60BC, 0x9053, 0x76D7, 0x5FB7, 0x5F97, + 0x7684, 0x8E6C, 0x706F, 0x767B, 0x7B49, 0x77AA, 0x51F3, 0x9093, 0x5824, + 0x4F4E, 0x6EF4, 0x8FEA, 0x654C, 0x7B1B, 0x72C4, 0x6DA4, 0x7FDF, 0x5AE1, + 0x62B5, 0x5E95, 0x5730, 0x8482, 0x7B2C, 0x5E1D, 0x5F1F, 0x9012, 0x7F14, + 0x98A0, 0x6382, 0x6EC7, 0x7898, 0x70B9, 0x5178, 0x975B, 0x57AB, 0x7535, + 0x4F43, 0x7538, 0x5E97, 0x60E6, 0x5960, 0x6DC0, 0x6BBF, 0x7889, 0x53FC, + 0x96D5, 0x51CB, 0x5201, 0x6389, 0x540A, 0x9493, 0x8C03, 0x8DCC, 0x7239, + 0x789F, 0x8776, 0x8FED, 0x8C0D, 0x53E0, 0, 0x7993, 0x7994, 0x7995, + 0x7996, 0x7997, 0x7998, 0x7999, 0x799B, 0x799C, 0x799D, 0x799E, 0x799F, + 0x79A0, 0x79A1, 0x79A2, 0x79A3, 0x79A4, 0x79A5, 0x79A6, 0x79A8, 0x79A9, + 0x79AA, 0x79AB, 0x79AC, 0x79AD, 0x79AE, 0x79AF, 0x79B0, 0x79B1, 0x79B2, + 0x79B4, 0x79B5, 0x79B6, 0x79B7, 0x79B8, 0x79BC, 0x79BF, 0x79C2, 0x79C4, + 0x79C5, 0x79C7, 0x79C8, 0x79CA, 0x79CC, 0x79CE, 0x79CF, 0x79D0, 0x79D3, + 0x79D4, 0x79D6, 0x79D7, 0x79D9, 0x79DA, 0x79DB, 0x79DC, 0x79DD, 0x79DE, + 0x79E0, 0x79E1, 0x79E2, 0x79E5, 0x79E8, 0x79EA, 0, 0x79EC, 0x79EE, + 0x79F1, 0x79F2, 0x79F3, 0x79F4, 0x79F5, 0x79F6, 0x79F7, 0x79F9, 0x79FA, + 0x79FC, 0x79FE, 0x79FF, 0x7A01, 0x7A04, 0x7A05, 0x7A07, 0x7A08, 0x7A09, + 0x7A0A, 0x7A0C, 0x7A0F, 0x7A10, 0x7A11, 0x7A12, 0x7A13, 0x7A15, 0x7A16, + 0x7A18, 0x7A19, 0x7A1B, 0x7A1C, 0x4E01, 0x76EF, 0x53EE, 0x9489, 0x9876, + 0x9F0E, 0x952D, 0x5B9A, 0x8BA2, 0x4E22, 0x4E1C, 0x51AC, 0x8463, 0x61C2, + 0x52A8, 0x680B, 0x4F97, 0x606B, 0x51BB, 0x6D1E, 0x515C, 0x6296, 0x6597, + 0x9661, 0x8C46, 0x9017, 0x75D8, 0x90FD, 0x7763, 0x6BD2, 0x728A, 0x72EC, + 0x8BFB, 0x5835, 0x7779, 0x8D4C, 0x675C, 0x9540, 0x809A, 0x5EA6, 0x6E21, + 0x5992, 0x7AEF, 0x77ED, 0x953B, 0x6BB5, 0x65AD, 0x7F0E, 0x5806, 0x5151, + 0x961F, 0x5BF9, 0x58A9, 0x5428, 0x8E72, 0x6566, 0x987F, 0x56E4, 0x949D, + 0x76FE, 0x9041, 0x6387, 0x54C6, 0x591A, 0x593A, 0x579B, 0x8EB2, 0x6735, + 0x8DFA, 0x8235, 0x5241, 0x60F0, 0x5815, 0x86FE, 0x5CE8, 0x9E45, 0x4FC4, + 0x989D, 0x8BB9, 0x5A25, 0x6076, 0x5384, 0x627C, 0x904F, 0x9102, 0x997F, + 0x6069, 0x800C, 0x513F, 0x8033, 0x5C14, 0x9975, 0x6D31, 0x4E8C, 0, + 0x7A1D, 0x7A1F, 0x7A21, 0x7A22, 0x7A24, 0x7A25, 0x7A26, 0x7A27, 0x7A28, + 0x7A29, 0x7A2A, 0x7A2B, 0x7A2C, 0x7A2D, 0x7A2E, 0x7A2F, 0x7A30, 0x7A31, + 0x7A32, 0x7A34, 0x7A35, 0x7A36, 0x7A38, 0x7A3A, 0x7A3E, 0x7A40, 0x7A41, + 0x7A42, 0x7A43, 0x7A44, 0x7A45, 0x7A47, 0x7A48, 0x7A49, 0x7A4A, 0x7A4B, + 0x7A4C, 0x7A4D, 0x7A4E, 0x7A4F, 0x7A50, 0x7A52, 0x7A53, 0x7A54, 0x7A55, + 0x7A56, 0x7A58, 0x7A59, 0x7A5A, 0x7A5B, 0x7A5C, 0x7A5D, 0x7A5E, 0x7A5F, + 0x7A60, 0x7A61, 0x7A62, 0x7A63, 0x7A64, 0x7A65, 0x7A66, 0x7A67, 0x7A68, + 0, 0x7A69, 0x7A6A, 0x7A6B, 0x7A6C, 0x7A6D, 0x7A6E, 0x7A6F, 0x7A71, + 0x7A72, 0x7A73, 0x7A75, 0x7A7B, 0x7A7C, 0x7A7D, 0x7A7E, 0x7A82, 0x7A85, + 0x7A87, 0x7A89, 0x7A8A, 0x7A8B, 0x7A8C, 0x7A8E, 0x7A8F, 0x7A90, 0x7A93, + 0x7A94, 0x7A99, 0x7A9A, 0x7A9B, 0x7A9E, 0x7AA1, 0x7AA2, 0x8D30, 0x53D1, + 0x7F5A, 0x7B4F, 0x4F10, 0x4E4F, 0x9600, 0x6CD5, 0x73D0, 0x85E9, 0x5E06, + 0x756A, 0x7FFB, 0x6A0A, 0x77FE, 0x9492, 0x7E41, 0x51E1, 0x70E6, 0x53CD, + 0x8FD4, 0x8303, 0x8D29, 0x72AF, 0x996D, 0x6CDB, 0x574A, 0x82B3, 0x65B9, + 0x80AA, 0x623F, 0x9632, 0x59A8, 0x4EFF, 0x8BBF, 0x7EBA, 0x653E, 0x83F2, + 0x975E, 0x5561, 0x98DE, 0x80A5, 0x532A, 0x8BFD, 0x5420, 0x80BA, 0x5E9F, + 0x6CB8, 0x8D39, 0x82AC, 0x915A, 0x5429, 0x6C1B, 0x5206, 0x7EB7, 0x575F, + 0x711A, 0x6C7E, 0x7C89, 0x594B, 0x4EFD, 0x5FFF, 0x6124, 0x7CAA, 0x4E30, + 0x5C01, 0x67AB, 0x8702, 0x5CF0, 0x950B, 0x98CE, 0x75AF, 0x70FD, 0x9022, + 0x51AF, 0x7F1D, 0x8BBD, 0x5949, 0x51E4, 0x4F5B, 0x5426, 0x592B, 0x6577, + 0x80A4, 0x5B75, 0x6276, 0x62C2, 0x8F90, 0x5E45, 0x6C1F, 0x7B26, 0x4F0F, + 0x4FD8, 0x670D, 0, 0x7AA3, 0x7AA4, 0x7AA7, 0x7AA9, 0x7AAA, 0x7AAB, + 0x7AAE, 0x7AAF, 0x7AB0, 0x7AB1, 0x7AB2, 0x7AB4, 0x7AB5, 0x7AB6, 0x7AB7, + 0x7AB8, 0x7AB9, 0x7ABA, 0x7ABB, 0x7ABC, 0x7ABD, 0x7ABE, 0x7AC0, 0x7AC1, + 0x7AC2, 0x7AC3, 0x7AC4, 0x7AC5, 0x7AC6, 0x7AC7, 0x7AC8, 0x7AC9, 0x7ACA, + 0x7ACC, 0x7ACD, 0x7ACE, 0x7ACF, 0x7AD0, 0x7AD1, 0x7AD2, 0x7AD3, 0x7AD4, + 0x7AD5, 0x7AD7, 0x7AD8, 0x7ADA, 0x7ADB, 0x7ADC, 0x7ADD, 0x7AE1, 0x7AE2, + 0x7AE4, 0x7AE7, 0x7AE8, 0x7AE9, 0x7AEA, 0x7AEB, 0x7AEC, 0x7AEE, 0x7AF0, + 0x7AF1, 0x7AF2, 0x7AF3, 0, 0x7AF4, 0x7AF5, 0x7AF6, 0x7AF7, 0x7AF8, + 0x7AFB, 0x7AFC, 0x7AFE, 0x7B00, 0x7B01, 0x7B02, 0x7B05, 0x7B07, 0x7B09, + 0x7B0C, 0x7B0D, 0x7B0E, 0x7B10, 0x7B12, 0x7B13, 0x7B16, 0x7B17, 0x7B18, + 0x7B1A, 0x7B1C, 0x7B1D, 0x7B1F, 0x7B21, 0x7B22, 0x7B23, 0x7B27, 0x7B29, + 0x7B2D, 0x6D6E, 0x6DAA, 0x798F, 0x88B1, 0x5F17, 0x752B, 0x629A, 0x8F85, + 0x4FEF, 0x91DC, 0x65A7, 0x812F, 0x8151, 0x5E9C, 0x8150, 0x8D74, 0x526F, + 0x8986, 0x8D4B, 0x590D, 0x5085, 0x4ED8, 0x961C, 0x7236, 0x8179, 0x8D1F, + 0x5BCC, 0x8BA3, 0x9644, 0x5987, 0x7F1A, 0x5490, 0x5676, 0x560E, 0x8BE5, + 0x6539, 0x6982, 0x9499, 0x76D6, 0x6E89, 0x5E72, 0x7518, 0x6746, 0x67D1, + 0x7AFF, 0x809D, 0x8D76, 0x611F, 0x79C6, 0x6562, 0x8D63, 0x5188, 0x521A, + 0x94A2, 0x7F38, 0x809B, 0x7EB2, 0x5C97, 0x6E2F, 0x6760, 0x7BD9, 0x768B, + 0x9AD8, 0x818F, 0x7F94, 0x7CD5, 0x641E, 0x9550, 0x7A3F, 0x544A, 0x54E5, + 0x6B4C, 0x6401, 0x6208, 0x9E3D, 0x80F3, 0x7599, 0x5272, 0x9769, 0x845B, + 0x683C, 0x86E4, 0x9601, 0x9694, 0x94EC, 0x4E2A, 0x5404, 0x7ED9, 0x6839, + 0x8DDF, 0x8015, 0x66F4, 0x5E9A, 0x7FB9, 0, 0x7B2F, 0x7B30, 0x7B32, + 0x7B34, 0x7B35, 0x7B36, 0x7B37, 0x7B39, 0x7B3B, 0x7B3D, 0x7B3F, 0x7B40, + 0x7B41, 0x7B42, 0x7B43, 0x7B44, 0x7B46, 0x7B48, 0x7B4A, 0x7B4D, 0x7B4E, + 0x7B53, 0x7B55, 0x7B57, 0x7B59, 0x7B5C, 0x7B5E, 0x7B5F, 0x7B61, 0x7B63, + 0x7B64, 0x7B65, 0x7B66, 0x7B67, 0x7B68, 0x7B69, 0x7B6A, 0x7B6B, 0x7B6C, + 0x7B6D, 0x7B6F, 0x7B70, 0x7B73, 0x7B74, 0x7B76, 0x7B78, 0x7B7A, 0x7B7C, + 0x7B7D, 0x7B7F, 0x7B81, 0x7B82, 0x7B83, 0x7B84, 0x7B86, 0x7B87, 0x7B88, + 0x7B89, 0x7B8A, 0x7B8B, 0x7B8C, 0x7B8E, 0x7B8F, 0, 0x7B91, 0x7B92, + 0x7B93, 0x7B96, 0x7B98, 0x7B99, 0x7B9A, 0x7B9B, 0x7B9E, 0x7B9F, 0x7BA0, + 0x7BA3, 0x7BA4, 0x7BA5, 0x7BAE, 0x7BAF, 0x7BB0, 0x7BB2, 0x7BB3, 0x7BB5, + 0x7BB6, 0x7BB7, 0x7BB9, 0x7BBA, 0x7BBB, 0x7BBC, 0x7BBD, 0x7BBE, 0x7BBF, + 0x7BC0, 0x7BC2, 0x7BC3, 0x7BC4, 0x57C2, 0x803F, 0x6897, 0x5DE5, 0x653B, + 0x529F, 0x606D, 0x9F9A, 0x4F9B, 0x8EAC, 0x516C, 0x5BAB, 0x5F13, 0x5DE9, + 0x6C5E, 0x62F1, 0x8D21, 0x5171, 0x94A9, 0x52FE, 0x6C9F, 0x82DF, 0x72D7, + 0x57A2, 0x6784, 0x8D2D, 0x591F, 0x8F9C, 0x83C7, 0x5495, 0x7B8D, 0x4F30, + 0x6CBD, 0x5B64, 0x59D1, 0x9F13, 0x53E4, 0x86CA, 0x9AA8, 0x8C37, 0x80A1, + 0x6545, 0x987E, 0x56FA, 0x96C7, 0x522E, 0x74DC, 0x5250, 0x5BE1, 0x6302, + 0x8902, 0x4E56, 0x62D0, 0x602A, 0x68FA, 0x5173, 0x5B98, 0x51A0, 0x89C2, + 0x7BA1, 0x9986, 0x7F50, 0x60EF, 0x704C, 0x8D2F, 0x5149, 0x5E7F, 0x901B, + 0x7470, 0x89C4, 0x572D, 0x7845, 0x5F52, 0x9F9F, 0x95FA, 0x8F68, 0x9B3C, + 0x8BE1, 0x7678, 0x6842, 0x67DC, 0x8DEA, 0x8D35, 0x523D, 0x8F8A, 0x6EDA, + 0x68CD, 0x9505, 0x90ED, 0x56FD, 0x679C, 0x88F9, 0x8FC7, 0x54C8, 0, + 0x7BC5, 0x7BC8, 0x7BC9, 0x7BCA, 0x7BCB, 0x7BCD, 0x7BCE, 0x7BCF, 0x7BD0, + 0x7BD2, 0x7BD4, 0x7BD5, 0x7BD6, 0x7BD7, 0x7BD8, 0x7BDB, 0x7BDC, 0x7BDE, + 0x7BDF, 0x7BE0, 0x7BE2, 0x7BE3, 0x7BE4, 0x7BE7, 0x7BE8, 0x7BE9, 0x7BEB, + 0x7BEC, 0x7BED, 0x7BEF, 0x7BF0, 0x7BF2, 0x7BF3, 0x7BF4, 0x7BF5, 0x7BF6, + 0x7BF8, 0x7BF9, 0x7BFA, 0x7BFB, 0x7BFD, 0x7BFF, 0x7C00, 0x7C01, 0x7C02, + 0x7C03, 0x7C04, 0x7C05, 0x7C06, 0x7C08, 0x7C09, 0x7C0A, 0x7C0D, 0x7C0E, + 0x7C10, 0x7C11, 0x7C12, 0x7C13, 0x7C14, 0x7C15, 0x7C17, 0x7C18, 0x7C19, + 0, 0x7C1A, 0x7C1B, 0x7C1C, 0x7C1D, 0x7C1E, 0x7C20, 0x7C21, 0x7C22, + 0x7C23, 0x7C24, 0x7C25, 0x7C28, 0x7C29, 0x7C2B, 0x7C2C, 0x7C2D, 0x7C2E, + 0x7C2F, 0x7C30, 0x7C31, 0x7C32, 0x7C33, 0x7C34, 0x7C35, 0x7C36, 0x7C37, + 0x7C39, 0x7C3A, 0x7C3B, 0x7C3C, 0x7C3D, 0x7C3E, 0x7C42, 0x9AB8, 0x5B69, + 0x6D77, 0x6C26, 0x4EA5, 0x5BB3, 0x9A87, 0x9163, 0x61A8, 0x90AF, 0x97E9, + 0x542B, 0x6DB5, 0x5BD2, 0x51FD, 0x558A, 0x7F55, 0x7FF0, 0x64BC, 0x634D, + 0x65F1, 0x61BE, 0x608D, 0x710A, 0x6C57, 0x6C49, 0x592F, 0x676D, 0x822A, + 0x58D5, 0x568E, 0x8C6A, 0x6BEB, 0x90DD, 0x597D, 0x8017, 0x53F7, 0x6D69, + 0x5475, 0x559D, 0x8377, 0x83CF, 0x6838, 0x79BE, 0x548C, 0x4F55, 0x5408, + 0x76D2, 0x8C89, 0x9602, 0x6CB3, 0x6DB8, 0x8D6B, 0x8910, 0x9E64, 0x8D3A, + 0x563F, 0x9ED1, 0x75D5, 0x5F88, 0x72E0, 0x6068, 0x54FC, 0x4EA8, 0x6A2A, + 0x8861, 0x6052, 0x8F70, 0x54C4, 0x70D8, 0x8679, 0x9E3F, 0x6D2A, 0x5B8F, + 0x5F18, 0x7EA2, 0x5589, 0x4FAF, 0x7334, 0x543C, 0x539A, 0x5019, 0x540E, + 0x547C, 0x4E4E, 0x5FFD, 0x745A, 0x58F6, 0x846B, 0x80E1, 0x8774, 0x72D0, + 0x7CCA, 0x6E56, 0, 0x7C43, 0x7C44, 0x7C45, 0x7C46, 0x7C47, 0x7C48, + 0x7C49, 0x7C4A, 0x7C4B, 0x7C4C, 0x7C4E, 0x7C4F, 0x7C50, 0x7C51, 0x7C52, + 0x7C53, 0x7C54, 0x7C55, 0x7C56, 0x7C57, 0x7C58, 0x7C59, 0x7C5A, 0x7C5B, + 0x7C5C, 0x7C5D, 0x7C5E, 0x7C5F, 0x7C60, 0x7C61, 0x7C62, 0x7C63, 0x7C64, + 0x7C65, 0x7C66, 0x7C67, 0x7C68, 0x7C69, 0x7C6A, 0x7C6B, 0x7C6C, 0x7C6D, + 0x7C6E, 0x7C6F, 0x7C70, 0x7C71, 0x7C72, 0x7C75, 0x7C76, 0x7C77, 0x7C78, + 0x7C79, 0x7C7A, 0x7C7E, 0x7C7F, 0x7C80, 0x7C81, 0x7C82, 0x7C83, 0x7C84, + 0x7C85, 0x7C86, 0x7C87, 0, 0x7C88, 0x7C8A, 0x7C8B, 0x7C8C, 0x7C8D, + 0x7C8E, 0x7C8F, 0x7C90, 0x7C93, 0x7C94, 0x7C96, 0x7C99, 0x7C9A, 0x7C9B, + 0x7CA0, 0x7CA1, 0x7CA3, 0x7CA6, 0x7CA7, 0x7CA8, 0x7CA9, 0x7CAB, 0x7CAC, + 0x7CAD, 0x7CAF, 0x7CB0, 0x7CB4, 0x7CB5, 0x7CB6, 0x7CB7, 0x7CB8, 0x7CBA, + 0x7CBB, 0x5F27, 0x864E, 0x552C, 0x62A4, 0x4E92, 0x6CAA, 0x6237, 0x82B1, + 0x54D7, 0x534E, 0x733E, 0x6ED1, 0x753B, 0x5212, 0x5316, 0x8BDD, 0x69D0, + 0x5F8A, 0x6000, 0x6DEE, 0x574F, 0x6B22, 0x73AF, 0x6853, 0x8FD8, 0x7F13, + 0x6362, 0x60A3, 0x5524, 0x75EA, 0x8C62, 0x7115, 0x6DA3, 0x5BA6, 0x5E7B, + 0x8352, 0x614C, 0x9EC4, 0x78FA, 0x8757, 0x7C27, 0x7687, 0x51F0, 0x60F6, + 0x714C, 0x6643, 0x5E4C, 0x604D, 0x8C0E, 0x7070, 0x6325, 0x8F89, 0x5FBD, + 0x6062, 0x86D4, 0x56DE, 0x6BC1, 0x6094, 0x6167, 0x5349, 0x60E0, 0x6666, + 0x8D3F, 0x79FD, 0x4F1A, 0x70E9, 0x6C47, 0x8BB3, 0x8BF2, 0x7ED8, 0x8364, + 0x660F, 0x5A5A, 0x9B42, 0x6D51, 0x6DF7, 0x8C41, 0x6D3B, 0x4F19, 0x706B, + 0x83B7, 0x6216, 0x60D1, 0x970D, 0x8D27, 0x7978, 0x51FB, 0x573E, 0x57FA, + 0x673A, 0x7578, 0x7A3D, 0x79EF, 0x7B95, 0, 0x7CBF, 0x7CC0, 0x7CC2, + 0x7CC3, 0x7CC4, 0x7CC6, 0x7CC9, 0x7CCB, 0x7CCE, 0x7CCF, 0x7CD0, 0x7CD1, + 0x7CD2, 0x7CD3, 0x7CD4, 0x7CD8, 0x7CDA, 0x7CDB, 0x7CDD, 0x7CDE, 0x7CE1, + 0x7CE2, 0x7CE3, 0x7CE4, 0x7CE5, 0x7CE6, 0x7CE7, 0x7CE9, 0x7CEA, 0x7CEB, + 0x7CEC, 0x7CED, 0x7CEE, 0x7CF0, 0x7CF1, 0x7CF2, 0x7CF3, 0x7CF4, 0x7CF5, + 0x7CF6, 0x7CF7, 0x7CF9, 0x7CFA, 0x7CFC, 0x7CFD, 0x7CFE, 0x7CFF, 0x7D00, + 0x7D01, 0x7D02, 0x7D03, 0x7D04, 0x7D05, 0x7D06, 0x7D07, 0x7D08, 0x7D09, + 0x7D0B, 0x7D0C, 0x7D0D, 0x7D0E, 0x7D0F, 0x7D10, 0, 0x7D11, 0x7D12, + 0x7D13, 0x7D14, 0x7D15, 0x7D16, 0x7D17, 0x7D18, 0x7D19, 0x7D1A, 0x7D1B, + 0x7D1C, 0x7D1D, 0x7D1E, 0x7D1F, 0x7D21, 0x7D23, 0x7D24, 0x7D25, 0x7D26, + 0x7D28, 0x7D29, 0x7D2A, 0x7D2C, 0x7D2D, 0x7D2E, 0x7D30, 0x7D31, 0x7D32, + 0x7D33, 0x7D34, 0x7D35, 0x7D36, 0x808C, 0x9965, 0x8FF9, 0x6FC0, 0x8BA5, + 0x9E21, 0x59EC, 0x7EE9, 0x7F09, 0x5409, 0x6781, 0x68D8, 0x8F91, 0x7C4D, + 0x96C6, 0x53CA, 0x6025, 0x75BE, 0x6C72, 0x5373, 0x5AC9, 0x7EA7, 0x6324, + 0x51E0, 0x810A, 0x5DF1, 0x84DF, 0x6280, 0x5180, 0x5B63, 0x4F0E, 0x796D, + 0x5242, 0x60B8, 0x6D4E, 0x5BC4, 0x5BC2, 0x8BA1, 0x8BB0, 0x65E2, 0x5FCC, + 0x9645, 0x5993, 0x7EE7, 0x7EAA, 0x5609, 0x67B7, 0x5939, 0x4F73, 0x5BB6, + 0x52A0, 0x835A, 0x988A, 0x8D3E, 0x7532, 0x94BE, 0x5047, 0x7A3C, 0x4EF7, + 0x67B6, 0x9A7E, 0x5AC1, 0x6B7C, 0x76D1, 0x575A, 0x5C16, 0x7B3A, 0x95F4, + 0x714E, 0x517C, 0x80A9, 0x8270, 0x5978, 0x7F04, 0x8327, 0x68C0, 0x67EC, + 0x78B1, 0x7877, 0x62E3, 0x6361, 0x7B80, 0x4FED, 0x526A, 0x51CF, 0x8350, + 0x69DB, 0x9274, 0x8DF5, 0x8D31, 0x89C1, 0x952E, 0x7BAD, 0x4EF6, 0, + 0x7D37, 0x7D38, 0x7D39, 0x7D3A, 0x7D3B, 0x7D3C, 0x7D3D, 0x7D3E, 0x7D3F, + 0x7D40, 0x7D41, 0x7D42, 0x7D43, 0x7D44, 0x7D45, 0x7D46, 0x7D47, 0x7D48, + 0x7D49, 0x7D4A, 0x7D4B, 0x7D4C, 0x7D4D, 0x7D4E, 0x7D4F, 0x7D50, 0x7D51, + 0x7D52, 0x7D53, 0x7D54, 0x7D55, 0x7D56, 0x7D57, 0x7D58, 0x7D59, 0x7D5A, + 0x7D5B, 0x7D5C, 0x7D5D, 0x7D5E, 0x7D5F, 0x7D60, 0x7D61, 0x7D62, 0x7D63, + 0x7D64, 0x7D65, 0x7D66, 0x7D67, 0x7D68, 0x7D69, 0x7D6A, 0x7D6B, 0x7D6C, + 0x7D6D, 0x7D6F, 0x7D70, 0x7D71, 0x7D72, 0x7D73, 0x7D74, 0x7D75, 0x7D76, + 0, 0x7D78, 0x7D79, 0x7D7A, 0x7D7B, 0x7D7C, 0x7D7D, 0x7D7E, 0x7D7F, + 0x7D80, 0x7D81, 0x7D82, 0x7D83, 0x7D84, 0x7D85, 0x7D86, 0x7D87, 0x7D88, + 0x7D89, 0x7D8A, 0x7D8B, 0x7D8C, 0x7D8D, 0x7D8E, 0x7D8F, 0x7D90, 0x7D91, + 0x7D92, 0x7D93, 0x7D94, 0x7D95, 0x7D96, 0x7D97, 0x7D98, 0x5065, 0x8230, + 0x5251, 0x996F, 0x6E10, 0x6E85, 0x6DA7, 0x5EFA, 0x50F5, 0x59DC, 0x5C06, + 0x6D46, 0x6C5F, 0x7586, 0x848B, 0x6868, 0x5956, 0x8BB2, 0x5320, 0x9171, + 0x964D, 0x8549, 0x6912, 0x7901, 0x7126, 0x80F6, 0x4EA4, 0x90CA, 0x6D47, + 0x9A84, 0x5A07, 0x56BC, 0x6405, 0x94F0, 0x77EB, 0x4FA5, 0x811A, 0x72E1, + 0x89D2, 0x997A, 0x7F34, 0x7EDE, 0x527F, 0x6559, 0x9175, 0x8F7F, 0x8F83, + 0x53EB, 0x7A96, 0x63ED, 0x63A5, 0x7686, 0x79F8, 0x8857, 0x9636, 0x622A, + 0x52AB, 0x8282, 0x6854, 0x6770, 0x6377, 0x776B, 0x7AED, 0x6D01, 0x7ED3, + 0x89E3, 0x59D0, 0x6212, 0x85C9, 0x82A5, 0x754C, 0x501F, 0x4ECB, 0x75A5, + 0x8BEB, 0x5C4A, 0x5DFE, 0x7B4B, 0x65A4, 0x91D1, 0x4ECA, 0x6D25, 0x895F, + 0x7D27, 0x9526, 0x4EC5, 0x8C28, 0x8FDB, 0x9773, 0x664B, 0x7981, 0x8FD1, + 0x70EC, 0x6D78, 0, 0x7D99, 0x7D9A, 0x7D9B, 0x7D9C, 0x7D9D, 0x7D9E, + 0x7D9F, 0x7DA0, 0x7DA1, 0x7DA2, 0x7DA3, 0x7DA4, 0x7DA5, 0x7DA7, 0x7DA8, + 0x7DA9, 0x7DAA, 0x7DAB, 0x7DAC, 0x7DAD, 0x7DAF, 0x7DB0, 0x7DB1, 0x7DB2, + 0x7DB3, 0x7DB4, 0x7DB5, 0x7DB6, 0x7DB7, 0x7DB8, 0x7DB9, 0x7DBA, 0x7DBB, + 0x7DBC, 0x7DBD, 0x7DBE, 0x7DBF, 0x7DC0, 0x7DC1, 0x7DC2, 0x7DC3, 0x7DC4, + 0x7DC5, 0x7DC6, 0x7DC7, 0x7DC8, 0x7DC9, 0x7DCA, 0x7DCB, 0x7DCC, 0x7DCD, + 0x7DCE, 0x7DCF, 0x7DD0, 0x7DD1, 0x7DD2, 0x7DD3, 0x7DD4, 0x7DD5, 0x7DD6, + 0x7DD7, 0x7DD8, 0x7DD9, 0, 0x7DDA, 0x7DDB, 0x7DDC, 0x7DDD, 0x7DDE, + 0x7DDF, 0x7DE0, 0x7DE1, 0x7DE2, 0x7DE3, 0x7DE4, 0x7DE5, 0x7DE6, 0x7DE7, + 0x7DE8, 0x7DE9, 0x7DEA, 0x7DEB, 0x7DEC, 0x7DED, 0x7DEE, 0x7DEF, 0x7DF0, + 0x7DF1, 0x7DF2, 0x7DF3, 0x7DF4, 0x7DF5, 0x7DF6, 0x7DF7, 0x7DF8, 0x7DF9, + 0x7DFA, 0x5C3D, 0x52B2, 0x8346, 0x5162, 0x830E, 0x775B, 0x6676, 0x9CB8, + 0x4EAC, 0x60CA, 0x7CBE, 0x7CB3, 0x7ECF, 0x4E95, 0x8B66, 0x666F, 0x9888, + 0x9759, 0x5883, 0x656C, 0x955C, 0x5F84, 0x75C9, 0x9756, 0x7ADF, 0x7ADE, + 0x51C0, 0x70AF, 0x7A98, 0x63EA, 0x7A76, 0x7EA0, 0x7396, 0x97ED, 0x4E45, + 0x7078, 0x4E5D, 0x9152, 0x53A9, 0x6551, 0x65E7, 0x81FC, 0x8205, 0x548E, + 0x5C31, 0x759A, 0x97A0, 0x62D8, 0x72D9, 0x75BD, 0x5C45, 0x9A79, 0x83CA, + 0x5C40, 0x5480, 0x77E9, 0x4E3E, 0x6CAE, 0x805A, 0x62D2, 0x636E, 0x5DE8, + 0x5177, 0x8DDD, 0x8E1E, 0x952F, 0x4FF1, 0x53E5, 0x60E7, 0x70AC, 0x5267, + 0x6350, 0x9E43, 0x5A1F, 0x5026, 0x7737, 0x5377, 0x7EE2, 0x6485, 0x652B, + 0x6289, 0x6398, 0x5014, 0x7235, 0x89C9, 0x51B3, 0x8BC0, 0x7EDD, 0x5747, + 0x83CC, 0x94A7, 0x519B, 0x541B, 0x5CFB, 0, 0x7DFB, 0x7DFC, 0x7DFD, + 0x7DFE, 0x7DFF, 0x7E00, 0x7E01, 0x7E02, 0x7E03, 0x7E04, 0x7E05, 0x7E06, + 0x7E07, 0x7E08, 0x7E09, 0x7E0A, 0x7E0B, 0x7E0C, 0x7E0D, 0x7E0E, 0x7E0F, + 0x7E10, 0x7E11, 0x7E12, 0x7E13, 0x7E14, 0x7E15, 0x7E16, 0x7E17, 0x7E18, + 0x7E19, 0x7E1A, 0x7E1B, 0x7E1C, 0x7E1D, 0x7E1E, 0x7E1F, 0x7E20, 0x7E21, + 0x7E22, 0x7E23, 0x7E24, 0x7E25, 0x7E26, 0x7E27, 0x7E28, 0x7E29, 0x7E2A, + 0x7E2B, 0x7E2C, 0x7E2D, 0x7E2E, 0x7E2F, 0x7E30, 0x7E31, 0x7E32, 0x7E33, + 0x7E34, 0x7E35, 0x7E36, 0x7E37, 0x7E38, 0x7E39, 0, 0x7E3A, 0x7E3C, + 0x7E3D, 0x7E3E, 0x7E3F, 0x7E40, 0x7E42, 0x7E43, 0x7E44, 0x7E45, 0x7E46, + 0x7E48, 0x7E49, 0x7E4A, 0x7E4B, 0x7E4C, 0x7E4D, 0x7E4E, 0x7E4F, 0x7E50, + 0x7E51, 0x7E52, 0x7E53, 0x7E54, 0x7E55, 0x7E56, 0x7E57, 0x7E58, 0x7E59, + 0x7E5A, 0x7E5B, 0x7E5C, 0x7E5D, 0x4FCA, 0x7AE3, 0x6D5A, 0x90E1, 0x9A8F, + 0x5580, 0x5496, 0x5361, 0x54AF, 0x5F00, 0x63E9, 0x6977, 0x51EF, 0x6168, + 0x520A, 0x582A, 0x52D8, 0x574E, 0x780D, 0x770B, 0x5EB7, 0x6177, 0x7CE0, + 0x625B, 0x6297, 0x4EA2, 0x7095, 0x8003, 0x62F7, 0x70E4, 0x9760, 0x5777, + 0x82DB, 0x67EF, 0x68F5, 0x78D5, 0x9897, 0x79D1, 0x58F3, 0x54B3, 0x53EF, + 0x6E34, 0x514B, 0x523B, 0x5BA2, 0x8BFE, 0x80AF, 0x5543, 0x57A6, 0x6073, + 0x5751, 0x542D, 0x7A7A, 0x6050, 0x5B54, 0x63A7, 0x62A0, 0x53E3, 0x6263, + 0x5BC7, 0x67AF, 0x54ED, 0x7A9F, 0x82E6, 0x9177, 0x5E93, 0x88E4, 0x5938, + 0x57AE, 0x630E, 0x8DE8, 0x80EF, 0x5757, 0x7B77, 0x4FA9, 0x5FEB, 0x5BBD, + 0x6B3E, 0x5321, 0x7B50, 0x72C2, 0x6846, 0x77FF, 0x7736, 0x65F7, 0x51B5, + 0x4E8F, 0x76D4, 0x5CBF, 0x7AA5, 0x8475, 0x594E, 0x9B41, 0x5080, 0, + 0x7E5E, 0x7E5F, 0x7E60, 0x7E61, 0x7E62, 0x7E63, 0x7E64, 0x7E65, 0x7E66, + 0x7E67, 0x7E68, 0x7E69, 0x7E6A, 0x7E6B, 0x7E6C, 0x7E6D, 0x7E6E, 0x7E6F, + 0x7E70, 0x7E71, 0x7E72, 0x7E73, 0x7E74, 0x7E75, 0x7E76, 0x7E77, 0x7E78, + 0x7E79, 0x7E7A, 0x7E7B, 0x7E7C, 0x7E7D, 0x7E7E, 0x7E7F, 0x7E80, 0x7E81, + 0x7E83, 0x7E84, 0x7E85, 0x7E86, 0x7E87, 0x7E88, 0x7E89, 0x7E8A, 0x7E8B, + 0x7E8C, 0x7E8D, 0x7E8E, 0x7E8F, 0x7E90, 0x7E91, 0x7E92, 0x7E93, 0x7E94, + 0x7E95, 0x7E96, 0x7E97, 0x7E98, 0x7E99, 0x7E9A, 0x7E9C, 0x7E9D, 0x7E9E, + 0, 0x7EAE, 0x7EB4, 0x7EBB, 0x7EBC, 0x7ED6, 0x7EE4, 0x7EEC, 0x7EF9, + 0x7F0A, 0x7F10, 0x7F1E, 0x7F37, 0x7F39, 0x7F3B, 0x7F3C, 0x7F3D, 0x7F3E, + 0x7F3F, 0x7F40, 0x7F41, 0x7F43, 0x7F46, 0x7F47, 0x7F48, 0x7F49, 0x7F4A, + 0x7F4B, 0x7F4C, 0x7F4D, 0x7F4E, 0x7F4F, 0x7F52, 0x7F53, 0x9988, 0x6127, + 0x6E83, 0x5764, 0x6606, 0x6346, 0x56F0, 0x62EC, 0x6269, 0x5ED3, 0x9614, + 0x5783, 0x62C9, 0x5587, 0x8721, 0x814A, 0x8FA3, 0x5566, 0x83B1, 0x6765, + 0x8D56, 0x84DD, 0x5A6A, 0x680F, 0x62E6, 0x7BEE, 0x9611, 0x5170, 0x6F9C, + 0x8C30, 0x63FD, 0x89C8, 0x61D2, 0x7F06, 0x70C2, 0x6EE5, 0x7405, 0x6994, + 0x72FC, 0x5ECA, 0x90CE, 0x6717, 0x6D6A, 0x635E, 0x52B3, 0x7262, 0x8001, + 0x4F6C, 0x59E5, 0x916A, 0x70D9, 0x6D9D, 0x52D2, 0x4E50, 0x96F7, 0x956D, + 0x857E, 0x78CA, 0x7D2F, 0x5121, 0x5792, 0x64C2, 0x808B, 0x7C7B, 0x6CEA, + 0x68F1, 0x695E, 0x51B7, 0x5398, 0x68A8, 0x7281, 0x9ECE, 0x7BF1, 0x72F8, + 0x79BB, 0x6F13, 0x7406, 0x674E, 0x91CC, 0x9CA4, 0x793C, 0x8389, 0x8354, + 0x540F, 0x6817, 0x4E3D, 0x5389, 0x52B1, 0x783E, 0x5386, 0x5229, 0x5088, + 0x4F8B, 0x4FD0, 0, 0x7F56, 0x7F59, 0x7F5B, 0x7F5C, 0x7F5D, 0x7F5E, + 0x7F60, 0x7F63, 0x7F64, 0x7F65, 0x7F66, 0x7F67, 0x7F6B, 0x7F6C, 0x7F6D, + 0x7F6F, 0x7F70, 0x7F73, 0x7F75, 0x7F76, 0x7F77, 0x7F78, 0x7F7A, 0x7F7B, + 0x7F7C, 0x7F7D, 0x7F7F, 0x7F80, 0x7F82, 0x7F83, 0x7F84, 0x7F85, 0x7F86, + 0x7F87, 0x7F88, 0x7F89, 0x7F8B, 0x7F8D, 0x7F8F, 0x7F90, 0x7F91, 0x7F92, + 0x7F93, 0x7F95, 0x7F96, 0x7F97, 0x7F98, 0x7F99, 0x7F9B, 0x7F9C, 0x7FA0, + 0x7FA2, 0x7FA3, 0x7FA5, 0x7FA6, 0x7FA8, 0x7FA9, 0x7FAA, 0x7FAB, 0x7FAC, + 0x7FAD, 0x7FAE, 0x7FB1, 0, 0x7FB3, 0x7FB4, 0x7FB5, 0x7FB6, 0x7FB7, + 0x7FBA, 0x7FBB, 0x7FBE, 0x7FC0, 0x7FC2, 0x7FC3, 0x7FC4, 0x7FC6, 0x7FC7, + 0x7FC8, 0x7FC9, 0x7FCB, 0x7FCD, 0x7FCF, 0x7FD0, 0x7FD1, 0x7FD2, 0x7FD3, + 0x7FD6, 0x7FD7, 0x7FD9, 0x7FDA, 0x7FDB, 0x7FDC, 0x7FDD, 0x7FDE, 0x7FE2, + 0x7FE3, 0x75E2, 0x7ACB, 0x7C92, 0x6CA5, 0x96B6, 0x529B, 0x7483, 0x54E9, + 0x4FE9, 0x8054, 0x83B2, 0x8FDE, 0x9570, 0x5EC9, 0x601C, 0x6D9F, 0x5E18, + 0x655B, 0x8138, 0x94FE, 0x604B, 0x70BC, 0x7EC3, 0x7CAE, 0x51C9, 0x6881, + 0x7CB1, 0x826F, 0x4E24, 0x8F86, 0x91CF, 0x667E, 0x4EAE, 0x8C05, 0x64A9, + 0x804A, 0x50DA, 0x7597, 0x71CE, 0x5BE5, 0x8FBD, 0x6F66, 0x4E86, 0x6482, + 0x9563, 0x5ED6, 0x6599, 0x5217, 0x88C2, 0x70C8, 0x52A3, 0x730E, 0x7433, + 0x6797, 0x78F7, 0x9716, 0x4E34, 0x90BB, 0x9CDE, 0x6DCB, 0x51DB, 0x8D41, + 0x541D, 0x62CE, 0x73B2, 0x83F1, 0x96F6, 0x9F84, 0x94C3, 0x4F36, 0x7F9A, + 0x51CC, 0x7075, 0x9675, 0x5CAD, 0x9886, 0x53E6, 0x4EE4, 0x6E9C, 0x7409, + 0x69B4, 0x786B, 0x998F, 0x7559, 0x5218, 0x7624, 0x6D41, 0x67F3, 0x516D, + 0x9F99, 0x804B, 0x5499, 0x7B3C, 0x7ABF, 0, 0x7FE4, 0x7FE7, 0x7FE8, + 0x7FEA, 0x7FEB, 0x7FEC, 0x7FED, 0x7FEF, 0x7FF2, 0x7FF4, 0x7FF5, 0x7FF6, + 0x7FF7, 0x7FF8, 0x7FF9, 0x7FFA, 0x7FFD, 0x7FFE, 0x7FFF, 0x8002, 0x8007, + 0x8008, 0x8009, 0x800A, 0x800E, 0x800F, 0x8011, 0x8013, 0x801A, 0x801B, + 0x801D, 0x801E, 0x801F, 0x8021, 0x8023, 0x8024, 0x802B, 0x802C, 0x802D, + 0x802E, 0x802F, 0x8030, 0x8032, 0x8034, 0x8039, 0x803A, 0x803C, 0x803E, + 0x8040, 0x8041, 0x8044, 0x8045, 0x8047, 0x8048, 0x8049, 0x804E, 0x804F, + 0x8050, 0x8051, 0x8053, 0x8055, 0x8056, 0x8057, 0, 0x8059, 0x805B, + 0x805C, 0x805D, 0x805E, 0x805F, 0x8060, 0x8061, 0x8062, 0x8063, 0x8064, + 0x8065, 0x8066, 0x8067, 0x8068, 0x806B, 0x806C, 0x806D, 0x806E, 0x806F, + 0x8070, 0x8072, 0x8073, 0x8074, 0x8075, 0x8076, 0x8077, 0x8078, 0x8079, + 0x807A, 0x807B, 0x807C, 0x807D, 0x9686, 0x5784, 0x62E2, 0x9647, 0x697C, + 0x5A04, 0x6402, 0x7BD3, 0x6F0F, 0x964B, 0x82A6, 0x5362, 0x9885, 0x5E90, + 0x7089, 0x63B3, 0x5364, 0x864F, 0x9C81, 0x9E93, 0x788C, 0x9732, 0x8DEF, + 0x8D42, 0x9E7F, 0x6F5E, 0x7984, 0x5F55, 0x9646, 0x622E, 0x9A74, 0x5415, + 0x94DD, 0x4FA3, 0x65C5, 0x5C65, 0x5C61, 0x7F15, 0x8651, 0x6C2F, 0x5F8B, + 0x7387, 0x6EE4, 0x7EFF, 0x5CE6, 0x631B, 0x5B6A, 0x6EE6, 0x5375, 0x4E71, + 0x63A0, 0x7565, 0x62A1, 0x8F6E, 0x4F26, 0x4ED1, 0x6CA6, 0x7EB6, 0x8BBA, + 0x841D, 0x87BA, 0x7F57, 0x903B, 0x9523, 0x7BA9, 0x9AA1, 0x88F8, 0x843D, + 0x6D1B, 0x9A86, 0x7EDC, 0x5988, 0x9EBB, 0x739B, 0x7801, 0x8682, 0x9A6C, + 0x9A82, 0x561B, 0x5417, 0x57CB, 0x4E70, 0x9EA6, 0x5356, 0x8FC8, 0x8109, + 0x7792, 0x9992, 0x86EE, 0x6EE1, 0x8513, 0x66FC, 0x6162, 0x6F2B, 0, + 0x807E, 0x8081, 0x8082, 0x8085, 0x8088, 0x808A, 0x808D, 0x808E, 0x808F, + 0x8090, 0x8091, 0x8092, 0x8094, 0x8095, 0x8097, 0x8099, 0x809E, 0x80A3, + 0x80A6, 0x80A7, 0x80A8, 0x80AC, 0x80B0, 0x80B3, 0x80B5, 0x80B6, 0x80B8, + 0x80B9, 0x80BB, 0x80C5, 0x80C7, 0x80C8, 0x80C9, 0x80CA, 0x80CB, 0x80CF, + 0x80D0, 0x80D1, 0x80D2, 0x80D3, 0x80D4, 0x80D5, 0x80D8, 0x80DF, 0x80E0, + 0x80E2, 0x80E3, 0x80E6, 0x80EE, 0x80F5, 0x80F7, 0x80F9, 0x80FB, 0x80FE, + 0x80FF, 0x8100, 0x8101, 0x8103, 0x8104, 0x8105, 0x8107, 0x8108, 0x810B, + 0, 0x810C, 0x8115, 0x8117, 0x8119, 0x811B, 0x811C, 0x811D, 0x811F, + 0x8120, 0x8121, 0x8122, 0x8123, 0x8124, 0x8125, 0x8126, 0x8127, 0x8128, + 0x8129, 0x812A, 0x812B, 0x812D, 0x812E, 0x8130, 0x8133, 0x8134, 0x8135, + 0x8137, 0x8139, 0x813A, 0x813B, 0x813C, 0x813D, 0x813F, 0x8C29, 0x8292, + 0x832B, 0x76F2, 0x6C13, 0x5FD9, 0x83BD, 0x732B, 0x8305, 0x951A, 0x6BDB, + 0x77DB, 0x94C6, 0x536F, 0x8302, 0x5192, 0x5E3D, 0x8C8C, 0x8D38, 0x4E48, + 0x73AB, 0x679A, 0x6885, 0x9176, 0x9709, 0x7164, 0x6CA1, 0x7709, 0x5A92, + 0x9541, 0x6BCF, 0x7F8E, 0x6627, 0x5BD0, 0x59B9, 0x5A9A, 0x95E8, 0x95F7, + 0x4EEC, 0x840C, 0x8499, 0x6AAC, 0x76DF, 0x9530, 0x731B, 0x68A6, 0x5B5F, + 0x772F, 0x919A, 0x9761, 0x7CDC, 0x8FF7, 0x8C1C, 0x5F25, 0x7C73, 0x79D8, + 0x89C5, 0x6CCC, 0x871C, 0x5BC6, 0x5E42, 0x68C9, 0x7720, 0x7EF5, 0x5195, + 0x514D, 0x52C9, 0x5A29, 0x7F05, 0x9762, 0x82D7, 0x63CF, 0x7784, 0x85D0, + 0x79D2, 0x6E3A, 0x5E99, 0x5999, 0x8511, 0x706D, 0x6C11, 0x62BF, 0x76BF, + 0x654F, 0x60AF, 0x95FD, 0x660E, 0x879F, 0x9E23, 0x94ED, 0x540D, 0x547D, + 0x8C2C, 0x6478, 0, 0x8140, 0x8141, 0x8142, 0x8143, 0x8144, 0x8145, + 0x8147, 0x8149, 0x814D, 0x814E, 0x814F, 0x8152, 0x8156, 0x8157, 0x8158, + 0x815B, 0x815C, 0x815D, 0x815E, 0x815F, 0x8161, 0x8162, 0x8163, 0x8164, + 0x8166, 0x8168, 0x816A, 0x816B, 0x816C, 0x816F, 0x8172, 0x8173, 0x8175, + 0x8176, 0x8177, 0x8178, 0x8181, 0x8183, 0x8184, 0x8185, 0x8186, 0x8187, + 0x8189, 0x818B, 0x818C, 0x818D, 0x818E, 0x8190, 0x8192, 0x8193, 0x8194, + 0x8195, 0x8196, 0x8197, 0x8199, 0x819A, 0x819E, 0x819F, 0x81A0, 0x81A1, + 0x81A2, 0x81A4, 0x81A5, 0, 0x81A7, 0x81A9, 0x81AB, 0x81AC, 0x81AD, + 0x81AE, 0x81AF, 0x81B0, 0x81B1, 0x81B2, 0x81B4, 0x81B5, 0x81B6, 0x81B7, + 0x81B8, 0x81B9, 0x81BC, 0x81BD, 0x81BE, 0x81BF, 0x81C4, 0x81C5, 0x81C7, + 0x81C8, 0x81C9, 0x81CB, 0x81CD, 0x81CE, 0x81CF, 0x81D0, 0x81D1, 0x81D2, + 0x81D3, 0x6479, 0x8611, 0x6A21, 0x819C, 0x78E8, 0x6469, 0x9B54, 0x62B9, + 0x672B, 0x83AB, 0x58A8, 0x9ED8, 0x6CAB, 0x6F20, 0x5BDE, 0x964C, 0x8C0B, + 0x725F, 0x67D0, 0x62C7, 0x7261, 0x4EA9, 0x59C6, 0x6BCD, 0x5893, 0x66AE, + 0x5E55, 0x52DF, 0x6155, 0x6728, 0x76EE, 0x7766, 0x7267, 0x7A46, 0x62FF, + 0x54EA, 0x5450, 0x94A0, 0x90A3, 0x5A1C, 0x7EB3, 0x6C16, 0x4E43, 0x5976, + 0x8010, 0x5948, 0x5357, 0x7537, 0x96BE, 0x56CA, 0x6320, 0x8111, 0x607C, + 0x95F9, 0x6DD6, 0x5462, 0x9981, 0x5185, 0x5AE9, 0x80FD, 0x59AE, 0x9713, + 0x502A, 0x6CE5, 0x5C3C, 0x62DF, 0x4F60, 0x533F, 0x817B, 0x9006, 0x6EBA, + 0x852B, 0x62C8, 0x5E74, 0x78BE, 0x64B5, 0x637B, 0x5FF5, 0x5A18, 0x917F, + 0x9E1F, 0x5C3F, 0x634F, 0x8042, 0x5B7D, 0x556E, 0x954A, 0x954D, 0x6D85, + 0x60A8, 0x67E0, 0x72DE, 0x51DD, 0x5B81, 0, 0x81D4, 0x81D5, 0x81D6, + 0x81D7, 0x81D8, 0x81D9, 0x81DA, 0x81DB, 0x81DC, 0x81DD, 0x81DE, 0x81DF, + 0x81E0, 0x81E1, 0x81E2, 0x81E4, 0x81E5, 0x81E6, 0x81E8, 0x81E9, 0x81EB, + 0x81EE, 0x81EF, 0x81F0, 0x81F1, 0x81F2, 0x81F5, 0x81F6, 0x81F7, 0x81F8, + 0x81F9, 0x81FA, 0x81FD, 0x81FF, 0x8203, 0x8207, 0x8208, 0x8209, 0x820A, + 0x820B, 0x820E, 0x820F, 0x8211, 0x8213, 0x8215, 0x8216, 0x8217, 0x8218, + 0x8219, 0x821A, 0x821D, 0x8220, 0x8224, 0x8225, 0x8226, 0x8227, 0x8229, + 0x822E, 0x8232, 0x823A, 0x823C, 0x823D, 0x823F, 0, 0x8240, 0x8241, + 0x8242, 0x8243, 0x8245, 0x8246, 0x8248, 0x824A, 0x824C, 0x824D, 0x824E, + 0x8250, 0x8251, 0x8252, 0x8253, 0x8254, 0x8255, 0x8256, 0x8257, 0x8259, + 0x825B, 0x825C, 0x825D, 0x825E, 0x8260, 0x8261, 0x8262, 0x8263, 0x8264, + 0x8265, 0x8266, 0x8267, 0x8269, 0x62E7, 0x6CDE, 0x725B, 0x626D, 0x94AE, + 0x7EBD, 0x8113, 0x6D53, 0x519C, 0x5F04, 0x5974, 0x52AA, 0x6012, 0x5973, + 0x6696, 0x8650, 0x759F, 0x632A, 0x61E6, 0x7CEF, 0x8BFA, 0x54E6, 0x6B27, + 0x9E25, 0x6BB4, 0x85D5, 0x5455, 0x5076, 0x6CA4, 0x556A, 0x8DB4, 0x722C, + 0x5E15, 0x6015, 0x7436, 0x62CD, 0x6392, 0x724C, 0x5F98, 0x6E43, 0x6D3E, + 0x6500, 0x6F58, 0x76D8, 0x78D0, 0x76FC, 0x7554, 0x5224, 0x53DB, 0x4E53, + 0x5E9E, 0x65C1, 0x802A, 0x80D6, 0x629B, 0x5486, 0x5228, 0x70AE, 0x888D, + 0x8DD1, 0x6CE1, 0x5478, 0x80DA, 0x57F9, 0x88F4, 0x8D54, 0x966A, 0x914D, + 0x4F69, 0x6C9B, 0x55B7, 0x76C6, 0x7830, 0x62A8, 0x70F9, 0x6F8E, 0x5F6D, + 0x84EC, 0x68DA, 0x787C, 0x7BF7, 0x81A8, 0x670B, 0x9E4F, 0x6367, 0x78B0, + 0x576F, 0x7812, 0x9739, 0x6279, 0x62AB, 0x5288, 0x7435, 0x6BD7, 0, + 0x826A, 0x826B, 0x826C, 0x826D, 0x8271, 0x8275, 0x8276, 0x8277, 0x8278, + 0x827B, 0x827C, 0x8280, 0x8281, 0x8283, 0x8285, 0x8286, 0x8287, 0x8289, + 0x828C, 0x8290, 0x8293, 0x8294, 0x8295, 0x8296, 0x829A, 0x829B, 0x829E, + 0x82A0, 0x82A2, 0x82A3, 0x82A7, 0x82B2, 0x82B5, 0x82B6, 0x82BA, 0x82BB, + 0x82BC, 0x82BF, 0x82C0, 0x82C2, 0x82C3, 0x82C5, 0x82C6, 0x82C9, 0x82D0, + 0x82D6, 0x82D9, 0x82DA, 0x82DD, 0x82E2, 0x82E7, 0x82E8, 0x82E9, 0x82EA, + 0x82EC, 0x82ED, 0x82EE, 0x82F0, 0x82F2, 0x82F3, 0x82F5, 0x82F6, 0x82F8, + 0, 0x82FA, 0x82FC, 0x82FD, 0x82FE, 0x82FF, 0x8300, 0x830A, 0x830B, + 0x830D, 0x8310, 0x8312, 0x8313, 0x8316, 0x8318, 0x8319, 0x831D, 0x831E, + 0x831F, 0x8320, 0x8321, 0x8322, 0x8323, 0x8324, 0x8325, 0x8326, 0x8329, + 0x832A, 0x832E, 0x8330, 0x8332, 0x8337, 0x833B, 0x833D, 0x5564, 0x813E, + 0x75B2, 0x76AE, 0x5339, 0x75DE, 0x50FB, 0x5C41, 0x8B6C, 0x7BC7, 0x504F, + 0x7247, 0x9A97, 0x98D8, 0x6F02, 0x74E2, 0x7968, 0x6487, 0x77A5, 0x62FC, + 0x9891, 0x8D2B, 0x54C1, 0x8058, 0x4E52, 0x576A, 0x82F9, 0x840D, 0x5E73, + 0x51ED, 0x74F6, 0x8BC4, 0x5C4F, 0x5761, 0x6CFC, 0x9887, 0x5A46, 0x7834, + 0x9B44, 0x8FEB, 0x7C95, 0x5256, 0x6251, 0x94FA, 0x4EC6, 0x8386, 0x8461, + 0x83E9, 0x84B2, 0x57D4, 0x6734, 0x5703, 0x666E, 0x6D66, 0x8C31, 0x66DD, + 0x7011, 0x671F, 0x6B3A, 0x6816, 0x621A, 0x59BB, 0x4E03, 0x51C4, 0x6F06, + 0x67D2, 0x6C8F, 0x5176, 0x68CB, 0x5947, 0x6B67, 0x7566, 0x5D0E, 0x8110, + 0x9F50, 0x65D7, 0x7948, 0x7941, 0x9A91, 0x8D77, 0x5C82, 0x4E5E, 0x4F01, + 0x542F, 0x5951, 0x780C, 0x5668, 0x6C14, 0x8FC4, 0x5F03, 0x6C7D, 0x6CE3, + 0x8BAB, 0x6390, 0, 0x833E, 0x833F, 0x8341, 0x8342, 0x8344, 0x8345, + 0x8348, 0x834A, 0x834B, 0x834C, 0x834D, 0x834E, 0x8353, 0x8355, 0x8356, + 0x8357, 0x8358, 0x8359, 0x835D, 0x8362, 0x8370, 0x8371, 0x8372, 0x8373, + 0x8374, 0x8375, 0x8376, 0x8379, 0x837A, 0x837E, 0x837F, 0x8380, 0x8381, + 0x8382, 0x8383, 0x8384, 0x8387, 0x8388, 0x838A, 0x838B, 0x838C, 0x838D, + 0x838F, 0x8390, 0x8391, 0x8394, 0x8395, 0x8396, 0x8397, 0x8399, 0x839A, + 0x839D, 0x839F, 0x83A1, 0x83A2, 0x83A3, 0x83A4, 0x83A5, 0x83A6, 0x83A7, + 0x83AC, 0x83AD, 0x83AE, 0, 0x83AF, 0x83B5, 0x83BB, 0x83BE, 0x83BF, + 0x83C2, 0x83C3, 0x83C4, 0x83C6, 0x83C8, 0x83C9, 0x83CB, 0x83CD, 0x83CE, + 0x83D0, 0x83D1, 0x83D2, 0x83D3, 0x83D5, 0x83D7, 0x83D9, 0x83DA, 0x83DB, + 0x83DE, 0x83E2, 0x83E3, 0x83E4, 0x83E6, 0x83E7, 0x83E8, 0x83EB, 0x83EC, + 0x83ED, 0x6070, 0x6D3D, 0x7275, 0x6266, 0x948E, 0x94C5, 0x5343, 0x8FC1, + 0x7B7E, 0x4EDF, 0x8C26, 0x4E7E, 0x9ED4, 0x94B1, 0x94B3, 0x524D, 0x6F5C, + 0x9063, 0x6D45, 0x8C34, 0x5811, 0x5D4C, 0x6B20, 0x6B49, 0x67AA, 0x545B, + 0x8154, 0x7F8C, 0x5899, 0x8537, 0x5F3A, 0x62A2, 0x6A47, 0x9539, 0x6572, + 0x6084, 0x6865, 0x77A7, 0x4E54, 0x4FA8, 0x5DE7, 0x9798, 0x64AC, 0x7FD8, + 0x5CED, 0x4FCF, 0x7A8D, 0x5207, 0x8304, 0x4E14, 0x602F, 0x7A83, 0x94A6, + 0x4FB5, 0x4EB2, 0x79E6, 0x7434, 0x52E4, 0x82B9, 0x64D2, 0x79BD, 0x5BDD, + 0x6C81, 0x9752, 0x8F7B, 0x6C22, 0x503E, 0x537F, 0x6E05, 0x64CE, 0x6674, + 0x6C30, 0x60C5, 0x9877, 0x8BF7, 0x5E86, 0x743C, 0x7A77, 0x79CB, 0x4E18, + 0x90B1, 0x7403, 0x6C42, 0x56DA, 0x914B, 0x6CC5, 0x8D8B, 0x533A, 0x86C6, + 0x66F2, 0x8EAF, 0x5C48, 0x9A71, 0x6E20, 0, 0x83EE, 0x83EF, 0x83F3, + 0x83F4, 0x83F5, 0x83F6, 0x83F7, 0x83FA, 0x83FB, 0x83FC, 0x83FE, 0x83FF, + 0x8400, 0x8402, 0x8405, 0x8407, 0x8408, 0x8409, 0x840A, 0x8410, 0x8412, + 0x8413, 0x8414, 0x8415, 0x8416, 0x8417, 0x8419, 0x841A, 0x841B, 0x841E, + 0x841F, 0x8420, 0x8421, 0x8422, 0x8423, 0x8429, 0x842A, 0x842B, 0x842C, + 0x842D, 0x842E, 0x842F, 0x8430, 0x8432, 0x8433, 0x8434, 0x8435, 0x8436, + 0x8437, 0x8439, 0x843A, 0x843B, 0x843E, 0x843F, 0x8440, 0x8441, 0x8442, + 0x8443, 0x8444, 0x8445, 0x8447, 0x8448, 0x8449, 0, 0x844A, 0x844B, + 0x844C, 0x844D, 0x844E, 0x844F, 0x8450, 0x8452, 0x8453, 0x8454, 0x8455, + 0x8456, 0x8458, 0x845D, 0x845E, 0x845F, 0x8460, 0x8462, 0x8464, 0x8465, + 0x8466, 0x8467, 0x8468, 0x846A, 0x846E, 0x846F, 0x8470, 0x8472, 0x8474, + 0x8477, 0x8479, 0x847B, 0x847C, 0x53D6, 0x5A36, 0x9F8B, 0x8DA3, 0x53BB, + 0x5708, 0x98A7, 0x6743, 0x919B, 0x6CC9, 0x5168, 0x75CA, 0x62F3, 0x72AC, + 0x5238, 0x529D, 0x7F3A, 0x7094, 0x7638, 0x5374, 0x9E4A, 0x69B7, 0x786E, + 0x96C0, 0x88D9, 0x7FA4, 0x7136, 0x71C3, 0x5189, 0x67D3, 0x74E4, 0x58E4, + 0x6518, 0x56B7, 0x8BA9, 0x9976, 0x6270, 0x7ED5, 0x60F9, 0x70ED, 0x58EC, + 0x4EC1, 0x4EBA, 0x5FCD, 0x97E7, 0x4EFB, 0x8BA4, 0x5203, 0x598A, 0x7EAB, + 0x6254, 0x4ECD, 0x65E5, 0x620E, 0x8338, 0x84C9, 0x8363, 0x878D, 0x7194, + 0x6EB6, 0x5BB9, 0x7ED2, 0x5197, 0x63C9, 0x67D4, 0x8089, 0x8339, 0x8815, + 0x5112, 0x5B7A, 0x5982, 0x8FB1, 0x4E73, 0x6C5D, 0x5165, 0x8925, 0x8F6F, + 0x962E, 0x854A, 0x745E, 0x9510, 0x95F0, 0x6DA6, 0x82E5, 0x5F31, 0x6492, + 0x6D12, 0x8428, 0x816E, 0x9CC3, 0x585E, 0x8D5B, 0x4E09, 0x53C1, 0, + 0x847D, 0x847E, 0x847F, 0x8480, 0x8481, 0x8483, 0x8484, 0x8485, 0x8486, + 0x848A, 0x848D, 0x848F, 0x8490, 0x8491, 0x8492, 0x8493, 0x8494, 0x8495, + 0x8496, 0x8498, 0x849A, 0x849B, 0x849D, 0x849E, 0x849F, 0x84A0, 0x84A2, + 0x84A3, 0x84A4, 0x84A5, 0x84A6, 0x84A7, 0x84A8, 0x84A9, 0x84AA, 0x84AB, + 0x84AC, 0x84AD, 0x84AE, 0x84B0, 0x84B1, 0x84B3, 0x84B5, 0x84B6, 0x84B7, + 0x84BB, 0x84BC, 0x84BE, 0x84C0, 0x84C2, 0x84C3, 0x84C5, 0x84C6, 0x84C7, + 0x84C8, 0x84CB, 0x84CC, 0x84CE, 0x84CF, 0x84D2, 0x84D4, 0x84D5, 0x84D7, + 0, 0x84D8, 0x84D9, 0x84DA, 0x84DB, 0x84DC, 0x84DE, 0x84E1, 0x84E2, + 0x84E4, 0x84E7, 0x84E8, 0x84E9, 0x84EA, 0x84EB, 0x84ED, 0x84EE, 0x84EF, + 0x84F1, 0x84F2, 0x84F3, 0x84F4, 0x84F5, 0x84F6, 0x84F7, 0x84F8, 0x84F9, + 0x84FA, 0x84FB, 0x84FD, 0x84FE, 0x8500, 0x8501, 0x8502, 0x4F1E, 0x6563, + 0x6851, 0x55D3, 0x4E27, 0x6414, 0x9A9A, 0x626B, 0x5AC2, 0x745F, 0x8272, + 0x6DA9, 0x68EE, 0x50E7, 0x838E, 0x7802, 0x6740, 0x5239, 0x6C99, 0x7EB1, + 0x50BB, 0x5565, 0x715E, 0x7B5B, 0x6652, 0x73CA, 0x82EB, 0x6749, 0x5C71, + 0x5220, 0x717D, 0x886B, 0x95EA, 0x9655, 0x64C5, 0x8D61, 0x81B3, 0x5584, + 0x6C55, 0x6247, 0x7F2E, 0x5892, 0x4F24, 0x5546, 0x8D4F, 0x664C, 0x4E0A, + 0x5C1A, 0x88F3, 0x68A2, 0x634E, 0x7A0D, 0x70E7, 0x828D, 0x52FA, 0x97F6, + 0x5C11, 0x54E8, 0x90B5, 0x7ECD, 0x5962, 0x8D4A, 0x86C7, 0x820C, 0x820D, + 0x8D66, 0x6444, 0x5C04, 0x6151, 0x6D89, 0x793E, 0x8BBE, 0x7837, 0x7533, + 0x547B, 0x4F38, 0x8EAB, 0x6DF1, 0x5A20, 0x7EC5, 0x795E, 0x6C88, 0x5BA1, + 0x5A76, 0x751A, 0x80BE, 0x614E, 0x6E17, 0x58F0, 0x751F, 0x7525, 0x7272, + 0x5347, 0x7EF3, 0, 0x8503, 0x8504, 0x8505, 0x8506, 0x8507, 0x8508, + 0x8509, 0x850A, 0x850B, 0x850D, 0x850E, 0x850F, 0x8510, 0x8512, 0x8514, + 0x8515, 0x8516, 0x8518, 0x8519, 0x851B, 0x851C, 0x851D, 0x851E, 0x8520, + 0x8522, 0x8523, 0x8524, 0x8525, 0x8526, 0x8527, 0x8528, 0x8529, 0x852A, + 0x852D, 0x852E, 0x852F, 0x8530, 0x8531, 0x8532, 0x8533, 0x8534, 0x8535, + 0x8536, 0x853E, 0x853F, 0x8540, 0x8541, 0x8542, 0x8544, 0x8545, 0x8546, + 0x8547, 0x854B, 0x854C, 0x854D, 0x854E, 0x854F, 0x8550, 0x8551, 0x8552, + 0x8553, 0x8554, 0x8555, 0, 0x8557, 0x8558, 0x855A, 0x855B, 0x855C, + 0x855D, 0x855F, 0x8560, 0x8561, 0x8562, 0x8563, 0x8565, 0x8566, 0x8567, + 0x8569, 0x856A, 0x856B, 0x856C, 0x856D, 0x856E, 0x856F, 0x8570, 0x8571, + 0x8573, 0x8575, 0x8576, 0x8577, 0x8578, 0x857C, 0x857D, 0x857F, 0x8580, + 0x8581, 0x7701, 0x76DB, 0x5269, 0x80DC, 0x5723, 0x5E08, 0x5931, 0x72EE, + 0x65BD, 0x6E7F, 0x8BD7, 0x5C38, 0x8671, 0x5341, 0x77F3, 0x62FE, 0x65F6, + 0x4EC0, 0x98DF, 0x8680, 0x5B9E, 0x8BC6, 0x53F2, 0x77E2, 0x4F7F, 0x5C4E, + 0x9A76, 0x59CB, 0x5F0F, 0x793A, 0x58EB, 0x4E16, 0x67FF, 0x4E8B, 0x62ED, + 0x8A93, 0x901D, 0x52BF, 0x662F, 0x55DC, 0x566C, 0x9002, 0x4ED5, 0x4F8D, + 0x91CA, 0x9970, 0x6C0F, 0x5E02, 0x6043, 0x5BA4, 0x89C6, 0x8BD5, 0x6536, + 0x624B, 0x9996, 0x5B88, 0x5BFF, 0x6388, 0x552E, 0x53D7, 0x7626, 0x517D, + 0x852C, 0x67A2, 0x68B3, 0x6B8A, 0x6292, 0x8F93, 0x53D4, 0x8212, 0x6DD1, + 0x758F, 0x4E66, 0x8D4E, 0x5B70, 0x719F, 0x85AF, 0x6691, 0x66D9, 0x7F72, + 0x8700, 0x9ECD, 0x9F20, 0x5C5E, 0x672F, 0x8FF0, 0x6811, 0x675F, 0x620D, + 0x7AD6, 0x5885, 0x5EB6, 0x6570, 0x6F31, 0, 0x8582, 0x8583, 0x8586, + 0x8588, 0x8589, 0x858A, 0x858B, 0x858C, 0x858D, 0x858E, 0x8590, 0x8591, + 0x8592, 0x8593, 0x8594, 0x8595, 0x8596, 0x8597, 0x8598, 0x8599, 0x859A, + 0x859D, 0x859E, 0x859F, 0x85A0, 0x85A1, 0x85A2, 0x85A3, 0x85A5, 0x85A6, + 0x85A7, 0x85A9, 0x85AB, 0x85AC, 0x85AD, 0x85B1, 0x85B2, 0x85B3, 0x85B4, + 0x85B5, 0x85B6, 0x85B8, 0x85BA, 0x85BB, 0x85BC, 0x85BD, 0x85BE, 0x85BF, + 0x85C0, 0x85C2, 0x85C3, 0x85C4, 0x85C5, 0x85C6, 0x85C7, 0x85C8, 0x85CA, + 0x85CB, 0x85CC, 0x85CD, 0x85CE, 0x85D1, 0x85D2, 0, 0x85D4, 0x85D6, + 0x85D7, 0x85D8, 0x85D9, 0x85DA, 0x85DB, 0x85DD, 0x85DE, 0x85DF, 0x85E0, + 0x85E1, 0x85E2, 0x85E3, 0x85E5, 0x85E6, 0x85E7, 0x85E8, 0x85EA, 0x85EB, + 0x85EC, 0x85ED, 0x85EE, 0x85EF, 0x85F0, 0x85F1, 0x85F2, 0x85F3, 0x85F4, + 0x85F5, 0x85F6, 0x85F7, 0x85F8, 0x6055, 0x5237, 0x800D, 0x6454, 0x8870, + 0x7529, 0x5E05, 0x6813, 0x62F4, 0x971C, 0x53CC, 0x723D, 0x8C01, 0x6C34, + 0x7761, 0x7A0E, 0x542E, 0x77AC, 0x987A, 0x821C, 0x8BF4, 0x7855, 0x6714, + 0x70C1, 0x65AF, 0x6495, 0x5636, 0x601D, 0x79C1, 0x53F8, 0x4E1D, 0x6B7B, + 0x8086, 0x5BFA, 0x55E3, 0x56DB, 0x4F3A, 0x4F3C, 0x9972, 0x5DF3, 0x677E, + 0x8038, 0x6002, 0x9882, 0x9001, 0x5B8B, 0x8BBC, 0x8BF5, 0x641C, 0x8258, + 0x64DE, 0x55FD, 0x82CF, 0x9165, 0x4FD7, 0x7D20, 0x901F, 0x7C9F, 0x50F3, + 0x5851, 0x6EAF, 0x5BBF, 0x8BC9, 0x8083, 0x9178, 0x849C, 0x7B97, 0x867D, + 0x968B, 0x968F, 0x7EE5, 0x9AD3, 0x788E, 0x5C81, 0x7A57, 0x9042, 0x96A7, + 0x795F, 0x5B59, 0x635F, 0x7B0B, 0x84D1, 0x68AD, 0x5506, 0x7F29, 0x7410, + 0x7D22, 0x9501, 0x6240, 0x584C, 0x4ED6, 0x5B83, 0x5979, 0x5854, 0, + 0x85F9, 0x85FA, 0x85FC, 0x85FD, 0x85FE, 0x8600, 0x8601, 0x8602, 0x8603, + 0x8604, 0x8606, 0x8607, 0x8608, 0x8609, 0x860A, 0x860B, 0x860C, 0x860D, + 0x860E, 0x860F, 0x8610, 0x8612, 0x8613, 0x8614, 0x8615, 0x8617, 0x8618, + 0x8619, 0x861A, 0x861B, 0x861C, 0x861D, 0x861E, 0x861F, 0x8620, 0x8621, + 0x8622, 0x8623, 0x8624, 0x8625, 0x8626, 0x8628, 0x862A, 0x862B, 0x862C, + 0x862D, 0x862E, 0x862F, 0x8630, 0x8631, 0x8632, 0x8633, 0x8634, 0x8635, + 0x8636, 0x8637, 0x8639, 0x863A, 0x863B, 0x863D, 0x863E, 0x863F, 0x8640, + 0, 0x8641, 0x8642, 0x8643, 0x8644, 0x8645, 0x8646, 0x8647, 0x8648, + 0x8649, 0x864A, 0x864B, 0x864C, 0x8652, 0x8653, 0x8655, 0x8656, 0x8657, + 0x8658, 0x8659, 0x865B, 0x865C, 0x865D, 0x865F, 0x8660, 0x8661, 0x8663, + 0x8664, 0x8665, 0x8666, 0x8667, 0x8668, 0x8669, 0x866A, 0x736D, 0x631E, + 0x8E4B, 0x8E0F, 0x80CE, 0x82D4, 0x62AC, 0x53F0, 0x6CF0, 0x915E, 0x592A, + 0x6001, 0x6C70, 0x574D, 0x644A, 0x8D2A, 0x762B, 0x6EE9, 0x575B, 0x6A80, + 0x75F0, 0x6F6D, 0x8C2D, 0x8C08, 0x5766, 0x6BEF, 0x8892, 0x78B3, 0x63A2, + 0x53F9, 0x70AD, 0x6C64, 0x5858, 0x642A, 0x5802, 0x68E0, 0x819B, 0x5510, + 0x7CD6, 0x5018, 0x8EBA, 0x6DCC, 0x8D9F, 0x70EB, 0x638F, 0x6D9B, 0x6ED4, + 0x7EE6, 0x8404, 0x6843, 0x9003, 0x6DD8, 0x9676, 0x8BA8, 0x5957, 0x7279, + 0x85E4, 0x817E, 0x75BC, 0x8A8A, 0x68AF, 0x5254, 0x8E22, 0x9511, 0x63D0, + 0x9898, 0x8E44, 0x557C, 0x4F53, 0x66FF, 0x568F, 0x60D5, 0x6D95, 0x5243, + 0x5C49, 0x5929, 0x6DFB, 0x586B, 0x7530, 0x751C, 0x606C, 0x8214, 0x8146, + 0x6311, 0x6761, 0x8FE2, 0x773A, 0x8DF3, 0x8D34, 0x94C1, 0x5E16, 0x5385, + 0x542C, 0x70C3, 0, 0x866D, 0x866F, 0x8670, 0x8672, 0x8673, 0x8674, + 0x8675, 0x8676, 0x8677, 0x8678, 0x8683, 0x8684, 0x8685, 0x8686, 0x8687, + 0x8688, 0x8689, 0x868E, 0x868F, 0x8690, 0x8691, 0x8692, 0x8694, 0x8696, + 0x8697, 0x8698, 0x8699, 0x869A, 0x869B, 0x869E, 0x869F, 0x86A0, 0x86A1, + 0x86A2, 0x86A5, 0x86A6, 0x86AB, 0x86AD, 0x86AE, 0x86B2, 0x86B3, 0x86B7, + 0x86B8, 0x86B9, 0x86BB, 0x86BC, 0x86BD, 0x86BE, 0x86BF, 0x86C1, 0x86C2, + 0x86C3, 0x86C5, 0x86C8, 0x86CC, 0x86CD, 0x86D2, 0x86D3, 0x86D5, 0x86D6, + 0x86D7, 0x86DA, 0x86DC, 0, 0x86DD, 0x86E0, 0x86E1, 0x86E2, 0x86E3, + 0x86E5, 0x86E6, 0x86E7, 0x86E8, 0x86EA, 0x86EB, 0x86EC, 0x86EF, 0x86F5, + 0x86F6, 0x86F7, 0x86FA, 0x86FB, 0x86FC, 0x86FD, 0x86FF, 0x8701, 0x8704, + 0x8705, 0x8706, 0x870B, 0x870C, 0x870E, 0x870F, 0x8710, 0x8711, 0x8714, + 0x8716, 0x6C40, 0x5EF7, 0x505C, 0x4EAD, 0x5EAD, 0x633A, 0x8247, 0x901A, + 0x6850, 0x916E, 0x77B3, 0x540C, 0x94DC, 0x5F64, 0x7AE5, 0x6876, 0x6345, + 0x7B52, 0x7EDF, 0x75DB, 0x5077, 0x6295, 0x5934, 0x900F, 0x51F8, 0x79C3, + 0x7A81, 0x56FE, 0x5F92, 0x9014, 0x6D82, 0x5C60, 0x571F, 0x5410, 0x5154, + 0x6E4D, 0x56E2, 0x63A8, 0x9893, 0x817F, 0x8715, 0x892A, 0x9000, 0x541E, + 0x5C6F, 0x81C0, 0x62D6, 0x6258, 0x8131, 0x9E35, 0x9640, 0x9A6E, 0x9A7C, + 0x692D, 0x59A5, 0x62D3, 0x553E, 0x6316, 0x54C7, 0x86D9, 0x6D3C, 0x5A03, + 0x74E6, 0x889C, 0x6B6A, 0x5916, 0x8C4C, 0x5F2F, 0x6E7E, 0x73A9, 0x987D, + 0x4E38, 0x70F7, 0x5B8C, 0x7897, 0x633D, 0x665A, 0x7696, 0x60CB, 0x5B9B, + 0x5A49, 0x4E07, 0x8155, 0x6C6A, 0x738B, 0x4EA1, 0x6789, 0x7F51, 0x5F80, + 0x65FA, 0x671B, 0x5FD8, 0x5984, 0x5A01, 0, 0x8719, 0x871B, 0x871D, + 0x871F, 0x8720, 0x8724, 0x8726, 0x8727, 0x8728, 0x872A, 0x872B, 0x872C, + 0x872D, 0x872F, 0x8730, 0x8732, 0x8733, 0x8735, 0x8736, 0x8738, 0x8739, + 0x873A, 0x873C, 0x873D, 0x8740, 0x8741, 0x8742, 0x8743, 0x8744, 0x8745, + 0x8746, 0x874A, 0x874B, 0x874D, 0x874F, 0x8750, 0x8751, 0x8752, 0x8754, + 0x8755, 0x8756, 0x8758, 0x875A, 0x875B, 0x875C, 0x875D, 0x875E, 0x875F, + 0x8761, 0x8762, 0x8766, 0x8767, 0x8768, 0x8769, 0x876A, 0x876B, 0x876C, + 0x876D, 0x876F, 0x8771, 0x8772, 0x8773, 0x8775, 0, 0x8777, 0x8778, + 0x8779, 0x877A, 0x877F, 0x8780, 0x8781, 0x8784, 0x8786, 0x8787, 0x8789, + 0x878A, 0x878C, 0x878E, 0x878F, 0x8790, 0x8791, 0x8792, 0x8794, 0x8795, + 0x8796, 0x8798, 0x8799, 0x879A, 0x879B, 0x879C, 0x879D, 0x879E, 0x87A0, + 0x87A1, 0x87A2, 0x87A3, 0x87A4, 0x5DCD, 0x5FAE, 0x5371, 0x97E6, 0x8FDD, + 0x6845, 0x56F4, 0x552F, 0x60DF, 0x4E3A, 0x6F4D, 0x7EF4, 0x82C7, 0x840E, + 0x59D4, 0x4F1F, 0x4F2A, 0x5C3E, 0x7EAC, 0x672A, 0x851A, 0x5473, 0x754F, + 0x80C3, 0x5582, 0x9B4F, 0x4F4D, 0x6E2D, 0x8C13, 0x5C09, 0x6170, 0x536B, + 0x761F, 0x6E29, 0x868A, 0x6587, 0x95FB, 0x7EB9, 0x543B, 0x7A33, 0x7D0A, + 0x95EE, 0x55E1, 0x7FC1, 0x74EE, 0x631D, 0x8717, 0x6DA1, 0x7A9D, 0x6211, + 0x65A1, 0x5367, 0x63E1, 0x6C83, 0x5DEB, 0x545C, 0x94A8, 0x4E4C, 0x6C61, + 0x8BEC, 0x5C4B, 0x65E0, 0x829C, 0x68A7, 0x543E, 0x5434, 0x6BCB, 0x6B66, + 0x4E94, 0x6342, 0x5348, 0x821E, 0x4F0D, 0x4FAE, 0x575E, 0x620A, 0x96FE, + 0x6664, 0x7269, 0x52FF, 0x52A1, 0x609F, 0x8BEF, 0x6614, 0x7199, 0x6790, + 0x897F, 0x7852, 0x77FD, 0x6670, 0x563B, 0x5438, 0x9521, 0x727A, 0, + 0x87A5, 0x87A6, 0x87A7, 0x87A9, 0x87AA, 0x87AE, 0x87B0, 0x87B1, 0x87B2, + 0x87B4, 0x87B6, 0x87B7, 0x87B8, 0x87B9, 0x87BB, 0x87BC, 0x87BE, 0x87BF, + 0x87C1, 0x87C2, 0x87C3, 0x87C4, 0x87C5, 0x87C7, 0x87C8, 0x87C9, 0x87CC, + 0x87CD, 0x87CE, 0x87CF, 0x87D0, 0x87D4, 0x87D5, 0x87D6, 0x87D7, 0x87D8, + 0x87D9, 0x87DA, 0x87DC, 0x87DD, 0x87DE, 0x87DF, 0x87E1, 0x87E2, 0x87E3, + 0x87E4, 0x87E6, 0x87E7, 0x87E8, 0x87E9, 0x87EB, 0x87EC, 0x87ED, 0x87EF, + 0x87F0, 0x87F1, 0x87F2, 0x87F3, 0x87F4, 0x87F5, 0x87F6, 0x87F7, 0x87F8, + 0, 0x87FA, 0x87FB, 0x87FC, 0x87FD, 0x87FF, 0x8800, 0x8801, 0x8802, + 0x8804, 0x8805, 0x8806, 0x8807, 0x8808, 0x8809, 0x880B, 0x880C, 0x880D, + 0x880E, 0x880F, 0x8810, 0x8811, 0x8812, 0x8814, 0x8817, 0x8818, 0x8819, + 0x881A, 0x881C, 0x881D, 0x881E, 0x881F, 0x8820, 0x8823, 0x7A00, 0x606F, + 0x5E0C, 0x6089, 0x819D, 0x5915, 0x60DC, 0x7184, 0x70EF, 0x6EAA, 0x6C50, + 0x7280, 0x6A84, 0x88AD, 0x5E2D, 0x4E60, 0x5AB3, 0x559C, 0x94E3, 0x6D17, + 0x7CFB, 0x9699, 0x620F, 0x7EC6, 0x778E, 0x867E, 0x5323, 0x971E, 0x8F96, + 0x6687, 0x5CE1, 0x4FA0, 0x72ED, 0x4E0B, 0x53A6, 0x590F, 0x5413, 0x6380, + 0x9528, 0x5148, 0x4ED9, 0x9C9C, 0x7EA4, 0x54B8, 0x8D24, 0x8854, 0x8237, + 0x95F2, 0x6D8E, 0x5F26, 0x5ACC, 0x663E, 0x9669, 0x73B0, 0x732E, 0x53BF, + 0x817A, 0x9985, 0x7FA1, 0x5BAA, 0x9677, 0x9650, 0x7EBF, 0x76F8, 0x53A2, + 0x9576, 0x9999, 0x7BB1, 0x8944, 0x6E58, 0x4E61, 0x7FD4, 0x7965, 0x8BE6, + 0x60F3, 0x54CD, 0x4EAB, 0x9879, 0x5DF7, 0x6A61, 0x50CF, 0x5411, 0x8C61, + 0x8427, 0x785D, 0x9704, 0x524A, 0x54EE, 0x56A3, 0x9500, 0x6D88, 0x5BB5, + 0x6DC6, 0x6653, 0, 0x8824, 0x8825, 0x8826, 0x8827, 0x8828, 0x8829, + 0x882A, 0x882B, 0x882C, 0x882D, 0x882E, 0x882F, 0x8830, 0x8831, 0x8833, + 0x8834, 0x8835, 0x8836, 0x8837, 0x8838, 0x883A, 0x883B, 0x883D, 0x883E, + 0x883F, 0x8841, 0x8842, 0x8843, 0x8846, 0x8847, 0x8848, 0x8849, 0x884A, + 0x884B, 0x884E, 0x884F, 0x8850, 0x8851, 0x8852, 0x8853, 0x8855, 0x8856, + 0x8858, 0x885A, 0x885B, 0x885C, 0x885D, 0x885E, 0x885F, 0x8860, 0x8866, + 0x8867, 0x886A, 0x886D, 0x886F, 0x8871, 0x8873, 0x8874, 0x8875, 0x8876, + 0x8878, 0x8879, 0x887A, 0, 0x887B, 0x887C, 0x8880, 0x8883, 0x8886, + 0x8887, 0x8889, 0x888A, 0x888C, 0x888E, 0x888F, 0x8890, 0x8891, 0x8893, + 0x8894, 0x8895, 0x8897, 0x8898, 0x8899, 0x889A, 0x889B, 0x889D, 0x889E, + 0x889F, 0x88A0, 0x88A1, 0x88A3, 0x88A5, 0x88A6, 0x88A7, 0x88A8, 0x88A9, + 0x88AA, 0x5C0F, 0x5B5D, 0x6821, 0x8096, 0x5578, 0x7B11, 0x6548, 0x6954, + 0x4E9B, 0x6B47, 0x874E, 0x978B, 0x534F, 0x631F, 0x643A, 0x90AA, 0x659C, + 0x80C1, 0x8C10, 0x5199, 0x68B0, 0x5378, 0x87F9, 0x61C8, 0x6CC4, 0x6CFB, + 0x8C22, 0x5C51, 0x85AA, 0x82AF, 0x950C, 0x6B23, 0x8F9B, 0x65B0, 0x5FFB, + 0x5FC3, 0x4FE1, 0x8845, 0x661F, 0x8165, 0x7329, 0x60FA, 0x5174, 0x5211, + 0x578B, 0x5F62, 0x90A2, 0x884C, 0x9192, 0x5E78, 0x674F, 0x6027, 0x59D3, + 0x5144, 0x51F6, 0x80F8, 0x5308, 0x6C79, 0x96C4, 0x718A, 0x4F11, 0x4FEE, + 0x7F9E, 0x673D, 0x55C5, 0x9508, 0x79C0, 0x8896, 0x7EE3, 0x589F, 0x620C, + 0x9700, 0x865A, 0x5618, 0x987B, 0x5F90, 0x8BB8, 0x84C4, 0x9157, 0x53D9, + 0x65ED, 0x5E8F, 0x755C, 0x6064, 0x7D6E, 0x5A7F, 0x7EEA, 0x7EED, 0x8F69, + 0x55A7, 0x5BA3, 0x60AC, 0x65CB, 0x7384, 0, 0x88AC, 0x88AE, 0x88AF, + 0x88B0, 0x88B2, 0x88B3, 0x88B4, 0x88B5, 0x88B6, 0x88B8, 0x88B9, 0x88BA, + 0x88BB, 0x88BD, 0x88BE, 0x88BF, 0x88C0, 0x88C3, 0x88C4, 0x88C7, 0x88C8, + 0x88CA, 0x88CB, 0x88CC, 0x88CD, 0x88CF, 0x88D0, 0x88D1, 0x88D3, 0x88D6, + 0x88D7, 0x88DA, 0x88DB, 0x88DC, 0x88DD, 0x88DE, 0x88E0, 0x88E1, 0x88E6, + 0x88E7, 0x88E9, 0x88EA, 0x88EB, 0x88EC, 0x88ED, 0x88EE, 0x88EF, 0x88F2, + 0x88F5, 0x88F6, 0x88F7, 0x88FA, 0x88FB, 0x88FD, 0x88FF, 0x8900, 0x8901, + 0x8903, 0x8904, 0x8905, 0x8906, 0x8907, 0x8908, 0, 0x8909, 0x890B, + 0x890C, 0x890D, 0x890E, 0x890F, 0x8911, 0x8914, 0x8915, 0x8916, 0x8917, + 0x8918, 0x891C, 0x891D, 0x891E, 0x891F, 0x8920, 0x8922, 0x8923, 0x8924, + 0x8926, 0x8927, 0x8928, 0x8929, 0x892C, 0x892D, 0x892E, 0x892F, 0x8931, + 0x8932, 0x8933, 0x8935, 0x8937, 0x9009, 0x7663, 0x7729, 0x7EDA, 0x9774, + 0x859B, 0x5B66, 0x7A74, 0x96EA, 0x8840, 0x52CB, 0x718F, 0x5FAA, 0x65EC, + 0x8BE2, 0x5BFB, 0x9A6F, 0x5DE1, 0x6B89, 0x6C5B, 0x8BAD, 0x8BAF, 0x900A, + 0x8FC5, 0x538B, 0x62BC, 0x9E26, 0x9E2D, 0x5440, 0x4E2B, 0x82BD, 0x7259, + 0x869C, 0x5D16, 0x8859, 0x6DAF, 0x96C5, 0x54D1, 0x4E9A, 0x8BB6, 0x7109, + 0x54BD, 0x9609, 0x70DF, 0x6DF9, 0x76D0, 0x4E25, 0x7814, 0x8712, 0x5CA9, + 0x5EF6, 0x8A00, 0x989C, 0x960E, 0x708E, 0x6CBF, 0x5944, 0x63A9, 0x773C, + 0x884D, 0x6F14, 0x8273, 0x5830, 0x71D5, 0x538C, 0x781A, 0x96C1, 0x5501, + 0x5F66, 0x7130, 0x5BB4, 0x8C1A, 0x9A8C, 0x6B83, 0x592E, 0x9E2F, 0x79E7, + 0x6768, 0x626C, 0x4F6F, 0x75A1, 0x7F8A, 0x6D0B, 0x9633, 0x6C27, 0x4EF0, + 0x75D2, 0x517B, 0x6837, 0x6F3E, 0x9080, 0x8170, 0x5996, 0x7476, 0, + 0x8938, 0x8939, 0x893A, 0x893B, 0x893C, 0x893D, 0x893E, 0x893F, 0x8940, + 0x8942, 0x8943, 0x8945, 0x8946, 0x8947, 0x8948, 0x8949, 0x894A, 0x894B, + 0x894C, 0x894D, 0x894E, 0x894F, 0x8950, 0x8951, 0x8952, 0x8953, 0x8954, + 0x8955, 0x8956, 0x8957, 0x8958, 0x8959, 0x895A, 0x895B, 0x895C, 0x895D, + 0x8960, 0x8961, 0x8962, 0x8963, 0x8964, 0x8965, 0x8967, 0x8968, 0x8969, + 0x896A, 0x896B, 0x896C, 0x896D, 0x896E, 0x896F, 0x8970, 0x8971, 0x8972, + 0x8973, 0x8974, 0x8975, 0x8976, 0x8977, 0x8978, 0x8979, 0x897A, 0x897C, + 0, 0x897D, 0x897E, 0x8980, 0x8982, 0x8984, 0x8985, 0x8987, 0x8988, + 0x8989, 0x898A, 0x898B, 0x898C, 0x898D, 0x898E, 0x898F, 0x8990, 0x8991, + 0x8992, 0x8993, 0x8994, 0x8995, 0x8996, 0x8997, 0x8998, 0x8999, 0x899A, + 0x899B, 0x899C, 0x899D, 0x899E, 0x899F, 0x89A0, 0x89A1, 0x6447, 0x5C27, + 0x9065, 0x7A91, 0x8C23, 0x59DA, 0x54AC, 0x8200, 0x836F, 0x8981, 0x8000, + 0x6930, 0x564E, 0x8036, 0x7237, 0x91CE, 0x51B6, 0x4E5F, 0x9875, 0x6396, + 0x4E1A, 0x53F6, 0x66F3, 0x814B, 0x591C, 0x6DB2, 0x4E00, 0x58F9, 0x533B, + 0x63D6, 0x94F1, 0x4F9D, 0x4F0A, 0x8863, 0x9890, 0x5937, 0x9057, 0x79FB, + 0x4EEA, 0x80F0, 0x7591, 0x6C82, 0x5B9C, 0x59E8, 0x5F5D, 0x6905, 0x8681, + 0x501A, 0x5DF2, 0x4E59, 0x77E3, 0x4EE5, 0x827A, 0x6291, 0x6613, 0x9091, + 0x5C79, 0x4EBF, 0x5F79, 0x81C6, 0x9038, 0x8084, 0x75AB, 0x4EA6, 0x88D4, + 0x610F, 0x6BC5, 0x5FC6, 0x4E49, 0x76CA, 0x6EA2, 0x8BE3, 0x8BAE, 0x8C0A, + 0x8BD1, 0x5F02, 0x7FFC, 0x7FCC, 0x7ECE, 0x8335, 0x836B, 0x56E0, 0x6BB7, + 0x97F3, 0x9634, 0x59FB, 0x541F, 0x94F6, 0x6DEB, 0x5BC5, 0x996E, 0x5C39, + 0x5F15, 0x9690, 0, 0x89A2, 0x89A3, 0x89A4, 0x89A5, 0x89A6, 0x89A7, + 0x89A8, 0x89A9, 0x89AA, 0x89AB, 0x89AC, 0x89AD, 0x89AE, 0x89AF, 0x89B0, + 0x89B1, 0x89B2, 0x89B3, 0x89B4, 0x89B5, 0x89B6, 0x89B7, 0x89B8, 0x89B9, + 0x89BA, 0x89BB, 0x89BC, 0x89BD, 0x89BE, 0x89BF, 0x89C0, 0x89C3, 0x89CD, + 0x89D3, 0x89D4, 0x89D5, 0x89D7, 0x89D8, 0x89D9, 0x89DB, 0x89DD, 0x89DF, + 0x89E0, 0x89E1, 0x89E2, 0x89E4, 0x89E7, 0x89E8, 0x89E9, 0x89EA, 0x89EC, + 0x89ED, 0x89EE, 0x89F0, 0x89F1, 0x89F2, 0x89F4, 0x89F5, 0x89F6, 0x89F7, + 0x89F8, 0x89F9, 0x89FA, 0, 0x89FB, 0x89FC, 0x89FD, 0x89FE, 0x89FF, + 0x8A01, 0x8A02, 0x8A03, 0x8A04, 0x8A05, 0x8A06, 0x8A08, 0x8A09, 0x8A0A, + 0x8A0B, 0x8A0C, 0x8A0D, 0x8A0E, 0x8A0F, 0x8A10, 0x8A11, 0x8A12, 0x8A13, + 0x8A14, 0x8A15, 0x8A16, 0x8A17, 0x8A18, 0x8A19, 0x8A1A, 0x8A1B, 0x8A1C, + 0x8A1D, 0x5370, 0x82F1, 0x6A31, 0x5A74, 0x9E70, 0x5E94, 0x7F28, 0x83B9, + 0x8424, 0x8425, 0x8367, 0x8747, 0x8FCE, 0x8D62, 0x76C8, 0x5F71, 0x9896, + 0x786C, 0x6620, 0x54DF, 0x62E5, 0x4F63, 0x81C3, 0x75C8, 0x5EB8, 0x96CD, + 0x8E0A, 0x86F9, 0x548F, 0x6CF3, 0x6D8C, 0x6C38, 0x607F, 0x52C7, 0x7528, + 0x5E7D, 0x4F18, 0x60A0, 0x5FE7, 0x5C24, 0x7531, 0x90AE, 0x94C0, 0x72B9, + 0x6CB9, 0x6E38, 0x9149, 0x6709, 0x53CB, 0x53F3, 0x4F51, 0x91C9, 0x8BF1, + 0x53C8, 0x5E7C, 0x8FC2, 0x6DE4, 0x4E8E, 0x76C2, 0x6986, 0x865E, 0x611A, + 0x8206, 0x4F59, 0x4FDE, 0x903E, 0x9C7C, 0x6109, 0x6E1D, 0x6E14, 0x9685, + 0x4E88, 0x5A31, 0x96E8, 0x4E0E, 0x5C7F, 0x79B9, 0x5B87, 0x8BED, 0x7FBD, + 0x7389, 0x57DF, 0x828B, 0x90C1, 0x5401, 0x9047, 0x55BB, 0x5CEA, 0x5FA1, + 0x6108, 0x6B32, 0x72F1, 0x80B2, 0x8A89, 0, 0x8A1E, 0x8A1F, 0x8A20, + 0x8A21, 0x8A22, 0x8A23, 0x8A24, 0x8A25, 0x8A26, 0x8A27, 0x8A28, 0x8A29, + 0x8A2A, 0x8A2B, 0x8A2C, 0x8A2D, 0x8A2E, 0x8A2F, 0x8A30, 0x8A31, 0x8A32, + 0x8A33, 0x8A34, 0x8A35, 0x8A36, 0x8A37, 0x8A38, 0x8A39, 0x8A3A, 0x8A3B, + 0x8A3C, 0x8A3D, 0x8A3F, 0x8A40, 0x8A41, 0x8A42, 0x8A43, 0x8A44, 0x8A45, + 0x8A46, 0x8A47, 0x8A49, 0x8A4A, 0x8A4B, 0x8A4C, 0x8A4D, 0x8A4E, 0x8A4F, + 0x8A50, 0x8A51, 0x8A52, 0x8A53, 0x8A54, 0x8A55, 0x8A56, 0x8A57, 0x8A58, + 0x8A59, 0x8A5A, 0x8A5B, 0x8A5C, 0x8A5D, 0x8A5E, 0, 0x8A5F, 0x8A60, + 0x8A61, 0x8A62, 0x8A63, 0x8A64, 0x8A65, 0x8A66, 0x8A67, 0x8A68, 0x8A69, + 0x8A6A, 0x8A6B, 0x8A6C, 0x8A6D, 0x8A6E, 0x8A6F, 0x8A70, 0x8A71, 0x8A72, + 0x8A73, 0x8A74, 0x8A75, 0x8A76, 0x8A77, 0x8A78, 0x8A7A, 0x8A7B, 0x8A7C, + 0x8A7D, 0x8A7E, 0x8A7F, 0x8A80, 0x6D74, 0x5BD3, 0x88D5, 0x9884, 0x8C6B, + 0x9A6D, 0x9E33, 0x6E0A, 0x51A4, 0x5143, 0x57A3, 0x8881, 0x539F, 0x63F4, + 0x8F95, 0x56ED, 0x5458, 0x5706, 0x733F, 0x6E90, 0x7F18, 0x8FDC, 0x82D1, + 0x613F, 0x6028, 0x9662, 0x66F0, 0x7EA6, 0x8D8A, 0x8DC3, 0x94A5, 0x5CB3, + 0x7CA4, 0x6708, 0x60A6, 0x9605, 0x8018, 0x4E91, 0x90E7, 0x5300, 0x9668, + 0x5141, 0x8FD0, 0x8574, 0x915D, 0x6655, 0x97F5, 0x5B55, 0x531D, 0x7838, + 0x6742, 0x683D, 0x54C9, 0x707E, 0x5BB0, 0x8F7D, 0x518D, 0x5728, 0x54B1, + 0x6512, 0x6682, 0x8D5E, 0x8D43, 0x810F, 0x846C, 0x906D, 0x7CDF, 0x51FF, + 0x85FB, 0x67A3, 0x65E9, 0x6FA1, 0x86A4, 0x8E81, 0x566A, 0x9020, 0x7682, + 0x7076, 0x71E5, 0x8D23, 0x62E9, 0x5219, 0x6CFD, 0x8D3C, 0x600E, 0x589E, + 0x618E, 0x66FE, 0x8D60, 0x624E, 0x55B3, 0x6E23, 0x672D, 0x8F67, 0, + 0x8A81, 0x8A82, 0x8A83, 0x8A84, 0x8A85, 0x8A86, 0x8A87, 0x8A88, 0x8A8B, + 0x8A8C, 0x8A8D, 0x8A8E, 0x8A8F, 0x8A90, 0x8A91, 0x8A92, 0x8A94, 0x8A95, + 0x8A96, 0x8A97, 0x8A98, 0x8A99, 0x8A9A, 0x8A9B, 0x8A9C, 0x8A9D, 0x8A9E, + 0x8A9F, 0x8AA0, 0x8AA1, 0x8AA2, 0x8AA3, 0x8AA4, 0x8AA5, 0x8AA6, 0x8AA7, + 0x8AA8, 0x8AA9, 0x8AAA, 0x8AAB, 0x8AAC, 0x8AAD, 0x8AAE, 0x8AAF, 0x8AB0, + 0x8AB1, 0x8AB2, 0x8AB3, 0x8AB4, 0x8AB5, 0x8AB6, 0x8AB7, 0x8AB8, 0x8AB9, + 0x8ABA, 0x8ABB, 0x8ABC, 0x8ABD, 0x8ABE, 0x8ABF, 0x8AC0, 0x8AC1, 0x8AC2, + 0, 0x8AC3, 0x8AC4, 0x8AC5, 0x8AC6, 0x8AC7, 0x8AC8, 0x8AC9, 0x8ACA, + 0x8ACB, 0x8ACC, 0x8ACD, 0x8ACE, 0x8ACF, 0x8AD0, 0x8AD1, 0x8AD2, 0x8AD3, + 0x8AD4, 0x8AD5, 0x8AD6, 0x8AD7, 0x8AD8, 0x8AD9, 0x8ADA, 0x8ADB, 0x8ADC, + 0x8ADD, 0x8ADE, 0x8ADF, 0x8AE0, 0x8AE1, 0x8AE2, 0x8AE3, 0x94E1, 0x95F8, + 0x7728, 0x6805, 0x69A8, 0x548B, 0x4E4D, 0x70B8, 0x8BC8, 0x6458, 0x658B, + 0x5B85, 0x7A84, 0x503A, 0x5BE8, 0x77BB, 0x6BE1, 0x8A79, 0x7C98, 0x6CBE, + 0x76CF, 0x65A9, 0x8F97, 0x5D2D, 0x5C55, 0x8638, 0x6808, 0x5360, 0x6218, + 0x7AD9, 0x6E5B, 0x7EFD, 0x6A1F, 0x7AE0, 0x5F70, 0x6F33, 0x5F20, 0x638C, + 0x6DA8, 0x6756, 0x4E08, 0x5E10, 0x8D26, 0x4ED7, 0x80C0, 0x7634, 0x969C, + 0x62DB, 0x662D, 0x627E, 0x6CBC, 0x8D75, 0x7167, 0x7F69, 0x5146, 0x8087, + 0x53EC, 0x906E, 0x6298, 0x54F2, 0x86F0, 0x8F99, 0x8005, 0x9517, 0x8517, + 0x8FD9, 0x6D59, 0x73CD, 0x659F, 0x771F, 0x7504, 0x7827, 0x81FB, 0x8D1E, + 0x9488, 0x4FA6, 0x6795, 0x75B9, 0x8BCA, 0x9707, 0x632F, 0x9547, 0x9635, + 0x84B8, 0x6323, 0x7741, 0x5F81, 0x72F0, 0x4E89, 0x6014, 0x6574, 0x62EF, + 0x6B63, 0x653F, 0, 0x8AE4, 0x8AE5, 0x8AE6, 0x8AE7, 0x8AE8, 0x8AE9, + 0x8AEA, 0x8AEB, 0x8AEC, 0x8AED, 0x8AEE, 0x8AEF, 0x8AF0, 0x8AF1, 0x8AF2, + 0x8AF3, 0x8AF4, 0x8AF5, 0x8AF6, 0x8AF7, 0x8AF8, 0x8AF9, 0x8AFA, 0x8AFB, + 0x8AFC, 0x8AFD, 0x8AFE, 0x8AFF, 0x8B00, 0x8B01, 0x8B02, 0x8B03, 0x8B04, + 0x8B05, 0x8B06, 0x8B08, 0x8B09, 0x8B0A, 0x8B0B, 0x8B0C, 0x8B0D, 0x8B0E, + 0x8B0F, 0x8B10, 0x8B11, 0x8B12, 0x8B13, 0x8B14, 0x8B15, 0x8B16, 0x8B17, + 0x8B18, 0x8B19, 0x8B1A, 0x8B1B, 0x8B1C, 0x8B1D, 0x8B1E, 0x8B1F, 0x8B20, + 0x8B21, 0x8B22, 0x8B23, 0, 0x8B24, 0x8B25, 0x8B27, 0x8B28, 0x8B29, + 0x8B2A, 0x8B2B, 0x8B2C, 0x8B2D, 0x8B2E, 0x8B2F, 0x8B30, 0x8B31, 0x8B32, + 0x8B33, 0x8B34, 0x8B35, 0x8B36, 0x8B37, 0x8B38, 0x8B39, 0x8B3A, 0x8B3B, + 0x8B3C, 0x8B3D, 0x8B3E, 0x8B3F, 0x8B40, 0x8B41, 0x8B42, 0x8B43, 0x8B44, + 0x8B45, 0x5E27, 0x75C7, 0x90D1, 0x8BC1, 0x829D, 0x679D, 0x652F, 0x5431, + 0x8718, 0x77E5, 0x80A2, 0x8102, 0x6C41, 0x4E4B, 0x7EC7, 0x804C, 0x76F4, + 0x690D, 0x6B96, 0x6267, 0x503C, 0x4F84, 0x5740, 0x6307, 0x6B62, 0x8DBE, + 0x53EA, 0x65E8, 0x7EB8, 0x5FD7, 0x631A, 0x63B7, 0x81F3, 0x81F4, 0x7F6E, + 0x5E1C, 0x5CD9, 0x5236, 0x667A, 0x79E9, 0x7A1A, 0x8D28, 0x7099, 0x75D4, + 0x6EDE, 0x6CBB, 0x7A92, 0x4E2D, 0x76C5, 0x5FE0, 0x949F, 0x8877, 0x7EC8, + 0x79CD, 0x80BF, 0x91CD, 0x4EF2, 0x4F17, 0x821F, 0x5468, 0x5DDE, 0x6D32, + 0x8BCC, 0x7CA5, 0x8F74, 0x8098, 0x5E1A, 0x5492, 0x76B1, 0x5B99, 0x663C, + 0x9AA4, 0x73E0, 0x682A, 0x86DB, 0x6731, 0x732A, 0x8BF8, 0x8BDB, 0x9010, + 0x7AF9, 0x70DB, 0x716E, 0x62C4, 0x77A9, 0x5631, 0x4E3B, 0x8457, 0x67F1, + 0x52A9, 0x86C0, 0x8D2E, 0x94F8, 0x7B51, 0, 0x8B46, 0x8B47, 0x8B48, + 0x8B49, 0x8B4A, 0x8B4B, 0x8B4C, 0x8B4D, 0x8B4E, 0x8B4F, 0x8B50, 0x8B51, + 0x8B52, 0x8B53, 0x8B54, 0x8B55, 0x8B56, 0x8B57, 0x8B58, 0x8B59, 0x8B5A, + 0x8B5B, 0x8B5C, 0x8B5D, 0x8B5E, 0x8B5F, 0x8B60, 0x8B61, 0x8B62, 0x8B63, + 0x8B64, 0x8B65, 0x8B67, 0x8B68, 0x8B69, 0x8B6A, 0x8B6B, 0x8B6D, 0x8B6E, + 0x8B6F, 0x8B70, 0x8B71, 0x8B72, 0x8B73, 0x8B74, 0x8B75, 0x8B76, 0x8B77, + 0x8B78, 0x8B79, 0x8B7A, 0x8B7B, 0x8B7C, 0x8B7D, 0x8B7E, 0x8B7F, 0x8B80, + 0x8B81, 0x8B82, 0x8B83, 0x8B84, 0x8B85, 0x8B86, 0, 0x8B87, 0x8B88, + 0x8B89, 0x8B8A, 0x8B8B, 0x8B8C, 0x8B8D, 0x8B8E, 0x8B8F, 0x8B90, 0x8B91, + 0x8B92, 0x8B93, 0x8B94, 0x8B95, 0x8B96, 0x8B97, 0x8B98, 0x8B99, 0x8B9A, + 0x8B9B, 0x8B9C, 0x8B9D, 0x8B9E, 0x8B9F, 0x8BAC, 0x8BB1, 0x8BBB, 0x8BC7, + 0x8BD0, 0x8BEA, 0x8C09, 0x8C1E, 0x4F4F, 0x6CE8, 0x795D, 0x9A7B, 0x6293, + 0x722A, 0x62FD, 0x4E13, 0x7816, 0x8F6C, 0x64B0, 0x8D5A, 0x7BC6, 0x6869, + 0x5E84, 0x88C5, 0x5986, 0x649E, 0x58EE, 0x72B6, 0x690E, 0x9525, 0x8FFD, + 0x8D58, 0x5760, 0x7F00, 0x8C06, 0x51C6, 0x6349, 0x62D9, 0x5353, 0x684C, + 0x7422, 0x8301, 0x914C, 0x5544, 0x7740, 0x707C, 0x6D4A, 0x5179, 0x54A8, + 0x8D44, 0x59FF, 0x6ECB, 0x6DC4, 0x5B5C, 0x7D2B, 0x4ED4, 0x7C7D, 0x6ED3, + 0x5B50, 0x81EA, 0x6E0D, 0x5B57, 0x9B03, 0x68D5, 0x8E2A, 0x5B97, 0x7EFC, + 0x603B, 0x7EB5, 0x90B9, 0x8D70, 0x594F, 0x63CD, 0x79DF, 0x8DB3, 0x5352, + 0x65CF, 0x7956, 0x8BC5, 0x963B, 0x7EC4, 0x94BB, 0x7E82, 0x5634, 0x9189, + 0x6700, 0x7F6A, 0x5C0A, 0x9075, 0x6628, 0x5DE6, 0x4F50, 0x67DE, 0x505A, + 0x4F5C, 0x5750, 0x5EA7, 0xE810, 0xE811, 0xE812, 0xE813, 0xE814, 0, + 0x8C38, 0x8C39, 0x8C3A, 0x8C3B, 0x8C3C, 0x8C3D, 0x8C3E, 0x8C3F, 0x8C40, + 0x8C42, 0x8C43, 0x8C44, 0x8C45, 0x8C48, 0x8C4A, 0x8C4B, 0x8C4D, 0x8C4E, + 0x8C4F, 0x8C50, 0x8C51, 0x8C52, 0x8C53, 0x8C54, 0x8C56, 0x8C57, 0x8C58, + 0x8C59, 0x8C5B, 0x8C5C, 0x8C5D, 0x8C5E, 0x8C5F, 0x8C60, 0x8C63, 0x8C64, + 0x8C65, 0x8C66, 0x8C67, 0x8C68, 0x8C69, 0x8C6C, 0x8C6D, 0x8C6E, 0x8C6F, + 0x8C70, 0x8C71, 0x8C72, 0x8C74, 0x8C75, 0x8C76, 0x8C77, 0x8C7B, 0x8C7C, + 0x8C7D, 0x8C7E, 0x8C7F, 0x8C80, 0x8C81, 0x8C83, 0x8C84, 0x8C86, 0x8C87, + 0, 0x8C88, 0x8C8B, 0x8C8D, 0x8C8E, 0x8C8F, 0x8C90, 0x8C91, 0x8C92, + 0x8C93, 0x8C95, 0x8C96, 0x8C97, 0x8C99, 0x8C9A, 0x8C9B, 0x8C9C, 0x8C9D, + 0x8C9E, 0x8C9F, 0x8CA0, 0x8CA1, 0x8CA2, 0x8CA3, 0x8CA4, 0x8CA5, 0x8CA6, + 0x8CA7, 0x8CA8, 0x8CA9, 0x8CAA, 0x8CAB, 0x8CAC, 0x8CAD, 0x4E8D, 0x4E0C, + 0x5140, 0x4E10, 0x5EFF, 0x5345, 0x4E15, 0x4E98, 0x4E1E, 0x9B32, 0x5B6C, + 0x5669, 0x4E28, 0x79BA, 0x4E3F, 0x5315, 0x4E47, 0x592D, 0x723B, 0x536E, + 0x6C10, 0x56DF, 0x80E4, 0x9997, 0x6BD3, 0x777E, 0x9F17, 0x4E36, 0x4E9F, + 0x9F10, 0x4E5C, 0x4E69, 0x4E93, 0x8288, 0x5B5B, 0x556C, 0x560F, 0x4EC4, + 0x538D, 0x539D, 0x53A3, 0x53A5, 0x53AE, 0x9765, 0x8D5D, 0x531A, 0x53F5, + 0x5326, 0x532E, 0x533E, 0x8D5C, 0x5366, 0x5363, 0x5202, 0x5208, 0x520E, + 0x522D, 0x5233, 0x523F, 0x5240, 0x524C, 0x525E, 0x5261, 0x525C, 0x84AF, + 0x527D, 0x5282, 0x5281, 0x5290, 0x5293, 0x5182, 0x7F54, 0x4EBB, 0x4EC3, + 0x4EC9, 0x4EC2, 0x4EE8, 0x4EE1, 0x4EEB, 0x4EDE, 0x4F1B, 0x4EF3, 0x4F22, + 0x4F64, 0x4EF5, 0x4F25, 0x4F27, 0x4F09, 0x4F2B, 0x4F5E, 0x4F67, 0x6538, + 0x4F5A, 0x4F5D, 0, 0x8CAE, 0x8CAF, 0x8CB0, 0x8CB1, 0x8CB2, 0x8CB3, + 0x8CB4, 0x8CB5, 0x8CB6, 0x8CB7, 0x8CB8, 0x8CB9, 0x8CBA, 0x8CBB, 0x8CBC, + 0x8CBD, 0x8CBE, 0x8CBF, 0x8CC0, 0x8CC1, 0x8CC2, 0x8CC3, 0x8CC4, 0x8CC5, + 0x8CC6, 0x8CC7, 0x8CC8, 0x8CC9, 0x8CCA, 0x8CCB, 0x8CCC, 0x8CCD, 0x8CCE, + 0x8CCF, 0x8CD0, 0x8CD1, 0x8CD2, 0x8CD3, 0x8CD4, 0x8CD5, 0x8CD6, 0x8CD7, + 0x8CD8, 0x8CD9, 0x8CDA, 0x8CDB, 0x8CDC, 0x8CDD, 0x8CDE, 0x8CDF, 0x8CE0, + 0x8CE1, 0x8CE2, 0x8CE3, 0x8CE4, 0x8CE5, 0x8CE6, 0x8CE7, 0x8CE8, 0x8CE9, + 0x8CEA, 0x8CEB, 0x8CEC, 0, 0x8CED, 0x8CEE, 0x8CEF, 0x8CF0, 0x8CF1, + 0x8CF2, 0x8CF3, 0x8CF4, 0x8CF5, 0x8CF6, 0x8CF7, 0x8CF8, 0x8CF9, 0x8CFA, + 0x8CFB, 0x8CFC, 0x8CFD, 0x8CFE, 0x8CFF, 0x8D00, 0x8D01, 0x8D02, 0x8D03, + 0x8D04, 0x8D05, 0x8D06, 0x8D07, 0x8D08, 0x8D09, 0x8D0A, 0x8D0B, 0x8D0C, + 0x8D0D, 0x4F5F, 0x4F57, 0x4F32, 0x4F3D, 0x4F76, 0x4F74, 0x4F91, 0x4F89, + 0x4F83, 0x4F8F, 0x4F7E, 0x4F7B, 0x4FAA, 0x4F7C, 0x4FAC, 0x4F94, 0x4FE6, + 0x4FE8, 0x4FEA, 0x4FC5, 0x4FDA, 0x4FE3, 0x4FDC, 0x4FD1, 0x4FDF, 0x4FF8, + 0x5029, 0x504C, 0x4FF3, 0x502C, 0x500F, 0x502E, 0x502D, 0x4FFE, 0x501C, + 0x500C, 0x5025, 0x5028, 0x507E, 0x5043, 0x5055, 0x5048, 0x504E, 0x506C, + 0x507B, 0x50A5, 0x50A7, 0x50A9, 0x50BA, 0x50D6, 0x5106, 0x50ED, 0x50EC, + 0x50E6, 0x50EE, 0x5107, 0x510B, 0x4EDD, 0x6C3D, 0x4F58, 0x4F65, 0x4FCE, + 0x9FA0, 0x6C46, 0x7C74, 0x516E, 0x5DFD, 0x9EC9, 0x9998, 0x5181, 0x5914, + 0x52F9, 0x530D, 0x8A07, 0x5310, 0x51EB, 0x5919, 0x5155, 0x4EA0, 0x5156, + 0x4EB3, 0x886E, 0x88A4, 0x4EB5, 0x8114, 0x88D2, 0x7980, 0x5B34, 0x8803, + 0x7FB8, 0x51AB, 0x51B1, 0x51BD, 0x51BC, 0, 0x8D0E, 0x8D0F, 0x8D10, + 0x8D11, 0x8D12, 0x8D13, 0x8D14, 0x8D15, 0x8D16, 0x8D17, 0x8D18, 0x8D19, + 0x8D1A, 0x8D1B, 0x8D1C, 0x8D20, 0x8D51, 0x8D52, 0x8D57, 0x8D5F, 0x8D65, + 0x8D68, 0x8D69, 0x8D6A, 0x8D6C, 0x8D6E, 0x8D6F, 0x8D71, 0x8D72, 0x8D78, + 0x8D79, 0x8D7A, 0x8D7B, 0x8D7C, 0x8D7D, 0x8D7E, 0x8D7F, 0x8D80, 0x8D82, + 0x8D83, 0x8D86, 0x8D87, 0x8D88, 0x8D89, 0x8D8C, 0x8D8D, 0x8D8E, 0x8D8F, + 0x8D90, 0x8D92, 0x8D93, 0x8D95, 0x8D96, 0x8D97, 0x8D98, 0x8D99, 0x8D9A, + 0x8D9B, 0x8D9C, 0x8D9D, 0x8D9E, 0x8DA0, 0x8DA1, 0, 0x8DA2, 0x8DA4, + 0x8DA5, 0x8DA6, 0x8DA7, 0x8DA8, 0x8DA9, 0x8DAA, 0x8DAB, 0x8DAC, 0x8DAD, + 0x8DAE, 0x8DAF, 0x8DB0, 0x8DB2, 0x8DB6, 0x8DB7, 0x8DB9, 0x8DBB, 0x8DBD, + 0x8DC0, 0x8DC1, 0x8DC2, 0x8DC5, 0x8DC7, 0x8DC8, 0x8DC9, 0x8DCA, 0x8DCD, + 0x8DD0, 0x8DD2, 0x8DD3, 0x8DD4, 0x51C7, 0x5196, 0x51A2, 0x51A5, 0x8BA0, + 0x8BA6, 0x8BA7, 0x8BAA, 0x8BB4, 0x8BB5, 0x8BB7, 0x8BC2, 0x8BC3, 0x8BCB, + 0x8BCF, 0x8BCE, 0x8BD2, 0x8BD3, 0x8BD4, 0x8BD6, 0x8BD8, 0x8BD9, 0x8BDC, + 0x8BDF, 0x8BE0, 0x8BE4, 0x8BE8, 0x8BE9, 0x8BEE, 0x8BF0, 0x8BF3, 0x8BF6, + 0x8BF9, 0x8BFC, 0x8BFF, 0x8C00, 0x8C02, 0x8C04, 0x8C07, 0x8C0C, 0x8C0F, + 0x8C11, 0x8C12, 0x8C14, 0x8C15, 0x8C16, 0x8C19, 0x8C1B, 0x8C18, 0x8C1D, + 0x8C1F, 0x8C20, 0x8C21, 0x8C25, 0x8C27, 0x8C2A, 0x8C2B, 0x8C2E, 0x8C2F, + 0x8C32, 0x8C33, 0x8C35, 0x8C36, 0x5369, 0x537A, 0x961D, 0x9622, 0x9621, + 0x9631, 0x962A, 0x963D, 0x963C, 0x9642, 0x9649, 0x9654, 0x965F, 0x9667, + 0x966C, 0x9672, 0x9674, 0x9688, 0x968D, 0x9697, 0x96B0, 0x9097, 0x909B, + 0x909D, 0x9099, 0x90AC, 0x90A1, 0x90B4, 0x90B3, 0x90B6, 0x90BA, 0, + 0x8DD5, 0x8DD8, 0x8DD9, 0x8DDC, 0x8DE0, 0x8DE1, 0x8DE2, 0x8DE5, 0x8DE6, + 0x8DE7, 0x8DE9, 0x8DED, 0x8DEE, 0x8DF0, 0x8DF1, 0x8DF2, 0x8DF4, 0x8DF6, + 0x8DFC, 0x8DFE, 0x8DFF, 0x8E00, 0x8E01, 0x8E02, 0x8E03, 0x8E04, 0x8E06, + 0x8E07, 0x8E08, 0x8E0B, 0x8E0D, 0x8E0E, 0x8E10, 0x8E11, 0x8E12, 0x8E13, + 0x8E15, 0x8E16, 0x8E17, 0x8E18, 0x8E19, 0x8E1A, 0x8E1B, 0x8E1C, 0x8E20, + 0x8E21, 0x8E24, 0x8E25, 0x8E26, 0x8E27, 0x8E28, 0x8E2B, 0x8E2D, 0x8E30, + 0x8E32, 0x8E33, 0x8E34, 0x8E36, 0x8E37, 0x8E38, 0x8E3B, 0x8E3C, 0x8E3E, + 0, 0x8E3F, 0x8E43, 0x8E45, 0x8E46, 0x8E4C, 0x8E4D, 0x8E4E, 0x8E4F, + 0x8E50, 0x8E53, 0x8E54, 0x8E55, 0x8E56, 0x8E57, 0x8E58, 0x8E5A, 0x8E5B, + 0x8E5C, 0x8E5D, 0x8E5E, 0x8E5F, 0x8E60, 0x8E61, 0x8E62, 0x8E63, 0x8E64, + 0x8E65, 0x8E67, 0x8E68, 0x8E6A, 0x8E6B, 0x8E6E, 0x8E71, 0x90B8, 0x90B0, + 0x90CF, 0x90C5, 0x90BE, 0x90D0, 0x90C4, 0x90C7, 0x90D3, 0x90E6, 0x90E2, + 0x90DC, 0x90D7, 0x90DB, 0x90EB, 0x90EF, 0x90FE, 0x9104, 0x9122, 0x911E, + 0x9123, 0x9131, 0x912F, 0x9139, 0x9143, 0x9146, 0x520D, 0x5942, 0x52A2, + 0x52AC, 0x52AD, 0x52BE, 0x54FF, 0x52D0, 0x52D6, 0x52F0, 0x53DF, 0x71EE, + 0x77CD, 0x5EF4, 0x51F5, 0x51FC, 0x9B2F, 0x53B6, 0x5F01, 0x755A, 0x5DEF, + 0x574C, 0x57A9, 0x57A1, 0x587E, 0x58BC, 0x58C5, 0x58D1, 0x5729, 0x572C, + 0x572A, 0x5733, 0x5739, 0x572E, 0x572F, 0x575C, 0x573B, 0x5742, 0x5769, + 0x5785, 0x576B, 0x5786, 0x577C, 0x577B, 0x5768, 0x576D, 0x5776, 0x5773, + 0x57AD, 0x57A4, 0x578C, 0x57B2, 0x57CF, 0x57A7, 0x57B4, 0x5793, 0x57A0, + 0x57D5, 0x57D8, 0x57DA, 0x57D9, 0x57D2, 0x57B8, 0x57F4, 0x57EF, 0x57F8, + 0x57E4, 0x57DD, 0, 0x8E73, 0x8E75, 0x8E77, 0x8E78, 0x8E79, 0x8E7A, + 0x8E7B, 0x8E7D, 0x8E7E, 0x8E80, 0x8E82, 0x8E83, 0x8E84, 0x8E86, 0x8E88, + 0x8E89, 0x8E8A, 0x8E8B, 0x8E8C, 0x8E8D, 0x8E8E, 0x8E91, 0x8E92, 0x8E93, + 0x8E95, 0x8E96, 0x8E97, 0x8E98, 0x8E99, 0x8E9A, 0x8E9B, 0x8E9D, 0x8E9F, + 0x8EA0, 0x8EA1, 0x8EA2, 0x8EA3, 0x8EA4, 0x8EA5, 0x8EA6, 0x8EA7, 0x8EA8, + 0x8EA9, 0x8EAA, 0x8EAD, 0x8EAE, 0x8EB0, 0x8EB1, 0x8EB3, 0x8EB4, 0x8EB5, + 0x8EB6, 0x8EB7, 0x8EB8, 0x8EB9, 0x8EBB, 0x8EBC, 0x8EBD, 0x8EBE, 0x8EBF, + 0x8EC0, 0x8EC1, 0x8EC2, 0, 0x8EC3, 0x8EC4, 0x8EC5, 0x8EC6, 0x8EC7, + 0x8EC8, 0x8EC9, 0x8ECA, 0x8ECB, 0x8ECC, 0x8ECD, 0x8ECF, 0x8ED0, 0x8ED1, + 0x8ED2, 0x8ED3, 0x8ED4, 0x8ED5, 0x8ED6, 0x8ED7, 0x8ED8, 0x8ED9, 0x8EDA, + 0x8EDB, 0x8EDC, 0x8EDD, 0x8EDE, 0x8EDF, 0x8EE0, 0x8EE1, 0x8EE2, 0x8EE3, + 0x8EE4, 0x580B, 0x580D, 0x57FD, 0x57ED, 0x5800, 0x581E, 0x5819, 0x5844, + 0x5820, 0x5865, 0x586C, 0x5881, 0x5889, 0x589A, 0x5880, 0x99A8, 0x9F19, + 0x61FF, 0x8279, 0x827D, 0x827F, 0x828F, 0x828A, 0x82A8, 0x8284, 0x828E, + 0x8291, 0x8297, 0x8299, 0x82AB, 0x82B8, 0x82BE, 0x82B0, 0x82C8, 0x82CA, + 0x82E3, 0x8298, 0x82B7, 0x82AE, 0x82CB, 0x82CC, 0x82C1, 0x82A9, 0x82B4, + 0x82A1, 0x82AA, 0x829F, 0x82C4, 0x82CE, 0x82A4, 0x82E1, 0x8309, 0x82F7, + 0x82E4, 0x830F, 0x8307, 0x82DC, 0x82F4, 0x82D2, 0x82D8, 0x830C, 0x82FB, + 0x82D3, 0x8311, 0x831A, 0x8306, 0x8314, 0x8315, 0x82E0, 0x82D5, 0x831C, + 0x8351, 0x835B, 0x835C, 0x8308, 0x8392, 0x833C, 0x8334, 0x8331, 0x839B, + 0x835E, 0x832F, 0x834F, 0x8347, 0x8343, 0x835F, 0x8340, 0x8317, 0x8360, + 0x832D, 0x833A, 0x8333, 0x8366, 0x8365, 0, 0x8EE5, 0x8EE6, 0x8EE7, + 0x8EE8, 0x8EE9, 0x8EEA, 0x8EEB, 0x8EEC, 0x8EED, 0x8EEE, 0x8EEF, 0x8EF0, + 0x8EF1, 0x8EF2, 0x8EF3, 0x8EF4, 0x8EF5, 0x8EF6, 0x8EF7, 0x8EF8, 0x8EF9, + 0x8EFA, 0x8EFB, 0x8EFC, 0x8EFD, 0x8EFE, 0x8EFF, 0x8F00, 0x8F01, 0x8F02, + 0x8F03, 0x8F04, 0x8F05, 0x8F06, 0x8F07, 0x8F08, 0x8F09, 0x8F0A, 0x8F0B, + 0x8F0C, 0x8F0D, 0x8F0E, 0x8F0F, 0x8F10, 0x8F11, 0x8F12, 0x8F13, 0x8F14, + 0x8F15, 0x8F16, 0x8F17, 0x8F18, 0x8F19, 0x8F1A, 0x8F1B, 0x8F1C, 0x8F1D, + 0x8F1E, 0x8F1F, 0x8F20, 0x8F21, 0x8F22, 0x8F23, 0, 0x8F24, 0x8F25, + 0x8F26, 0x8F27, 0x8F28, 0x8F29, 0x8F2A, 0x8F2B, 0x8F2C, 0x8F2D, 0x8F2E, + 0x8F2F, 0x8F30, 0x8F31, 0x8F32, 0x8F33, 0x8F34, 0x8F35, 0x8F36, 0x8F37, + 0x8F38, 0x8F39, 0x8F3A, 0x8F3B, 0x8F3C, 0x8F3D, 0x8F3E, 0x8F3F, 0x8F40, + 0x8F41, 0x8F42, 0x8F43, 0x8F44, 0x8368, 0x831B, 0x8369, 0x836C, 0x836A, + 0x836D, 0x836E, 0x83B0, 0x8378, 0x83B3, 0x83B4, 0x83A0, 0x83AA, 0x8393, + 0x839C, 0x8385, 0x837C, 0x83B6, 0x83A9, 0x837D, 0x83B8, 0x837B, 0x8398, + 0x839E, 0x83A8, 0x83BA, 0x83BC, 0x83C1, 0x8401, 0x83E5, 0x83D8, 0x5807, + 0x8418, 0x840B, 0x83DD, 0x83FD, 0x83D6, 0x841C, 0x8438, 0x8411, 0x8406, + 0x83D4, 0x83DF, 0x840F, 0x8403, 0x83F8, 0x83F9, 0x83EA, 0x83C5, 0x83C0, + 0x8426, 0x83F0, 0x83E1, 0x845C, 0x8451, 0x845A, 0x8459, 0x8473, 0x8487, + 0x8488, 0x847A, 0x8489, 0x8478, 0x843C, 0x8446, 0x8469, 0x8476, 0x848C, + 0x848E, 0x8431, 0x846D, 0x84C1, 0x84CD, 0x84D0, 0x84E6, 0x84BD, 0x84D3, + 0x84CA, 0x84BF, 0x84BA, 0x84E0, 0x84A1, 0x84B9, 0x84B4, 0x8497, 0x84E5, + 0x84E3, 0x850C, 0x750D, 0x8538, 0x84F0, 0x8539, 0x851F, 0x853A, 0, + 0x8F45, 0x8F46, 0x8F47, 0x8F48, 0x8F49, 0x8F4A, 0x8F4B, 0x8F4C, 0x8F4D, + 0x8F4E, 0x8F4F, 0x8F50, 0x8F51, 0x8F52, 0x8F53, 0x8F54, 0x8F55, 0x8F56, + 0x8F57, 0x8F58, 0x8F59, 0x8F5A, 0x8F5B, 0x8F5C, 0x8F5D, 0x8F5E, 0x8F5F, + 0x8F60, 0x8F61, 0x8F62, 0x8F63, 0x8F64, 0x8F65, 0x8F6A, 0x8F80, 0x8F8C, + 0x8F92, 0x8F9D, 0x8FA0, 0x8FA1, 0x8FA2, 0x8FA4, 0x8FA5, 0x8FA6, 0x8FA7, + 0x8FAA, 0x8FAC, 0x8FAD, 0x8FAE, 0x8FAF, 0x8FB2, 0x8FB3, 0x8FB4, 0x8FB5, + 0x8FB7, 0x8FB8, 0x8FBA, 0x8FBB, 0x8FBC, 0x8FBF, 0x8FC0, 0x8FC3, 0x8FC6, + 0, 0x8FC9, 0x8FCA, 0x8FCB, 0x8FCC, 0x8FCD, 0x8FCF, 0x8FD2, 0x8FD6, + 0x8FD7, 0x8FDA, 0x8FE0, 0x8FE1, 0x8FE3, 0x8FE7, 0x8FEC, 0x8FEF, 0x8FF1, + 0x8FF2, 0x8FF4, 0x8FF5, 0x8FF6, 0x8FFA, 0x8FFB, 0x8FFC, 0x8FFE, 0x8FFF, + 0x9007, 0x9008, 0x900C, 0x900E, 0x9013, 0x9015, 0x9018, 0x8556, 0x853B, + 0x84FF, 0x84FC, 0x8559, 0x8548, 0x8568, 0x8564, 0x855E, 0x857A, 0x77A2, + 0x8543, 0x8572, 0x857B, 0x85A4, 0x85A8, 0x8587, 0x858F, 0x8579, 0x85AE, + 0x859C, 0x8585, 0x85B9, 0x85B7, 0x85B0, 0x85D3, 0x85C1, 0x85DC, 0x85FF, + 0x8627, 0x8605, 0x8629, 0x8616, 0x863C, 0x5EFE, 0x5F08, 0x593C, 0x5941, + 0x8037, 0x5955, 0x595A, 0x5958, 0x530F, 0x5C22, 0x5C25, 0x5C2C, 0x5C34, + 0x624C, 0x626A, 0x629F, 0x62BB, 0x62CA, 0x62DA, 0x62D7, 0x62EE, 0x6322, + 0x62F6, 0x6339, 0x634B, 0x6343, 0x63AD, 0x63F6, 0x6371, 0x637A, 0x638E, + 0x63B4, 0x636D, 0x63AC, 0x638A, 0x6369, 0x63AE, 0x63BC, 0x63F2, 0x63F8, + 0x63E0, 0x63FF, 0x63C4, 0x63DE, 0x63CE, 0x6452, 0x63C6, 0x63BE, 0x6445, + 0x6441, 0x640B, 0x641B, 0x6420, 0x640C, 0x6426, 0x6421, 0x645E, 0x6484, + 0x646D, 0x6496, 0, 0x9019, 0x901C, 0x9023, 0x9024, 0x9025, 0x9027, + 0x9028, 0x9029, 0x902A, 0x902B, 0x902C, 0x9030, 0x9031, 0x9032, 0x9033, + 0x9034, 0x9037, 0x9039, 0x903A, 0x903D, 0x903F, 0x9040, 0x9043, 0x9045, + 0x9046, 0x9048, 0x9049, 0x904A, 0x904B, 0x904C, 0x904E, 0x9054, 0x9055, + 0x9056, 0x9059, 0x905A, 0x905C, 0x905D, 0x905E, 0x905F, 0x9060, 0x9061, + 0x9064, 0x9066, 0x9067, 0x9069, 0x906A, 0x906B, 0x906C, 0x906F, 0x9070, + 0x9071, 0x9072, 0x9073, 0x9076, 0x9077, 0x9078, 0x9079, 0x907A, 0x907B, + 0x907C, 0x907E, 0x9081, 0, 0x9084, 0x9085, 0x9086, 0x9087, 0x9089, + 0x908A, 0x908C, 0x908D, 0x908E, 0x908F, 0x9090, 0x9092, 0x9094, 0x9096, + 0x9098, 0x909A, 0x909C, 0x909E, 0x909F, 0x90A0, 0x90A4, 0x90A5, 0x90A7, + 0x90A8, 0x90A9, 0x90AB, 0x90AD, 0x90B2, 0x90B7, 0x90BC, 0x90BD, 0x90BF, + 0x90C0, 0x647A, 0x64B7, 0x64B8, 0x6499, 0x64BA, 0x64C0, 0x64D0, 0x64D7, + 0x64E4, 0x64E2, 0x6509, 0x6525, 0x652E, 0x5F0B, 0x5FD2, 0x7519, 0x5F11, + 0x535F, 0x53F1, 0x53FD, 0x53E9, 0x53E8, 0x53FB, 0x5412, 0x5416, 0x5406, + 0x544B, 0x5452, 0x5453, 0x5454, 0x5456, 0x5443, 0x5421, 0x5457, 0x5459, + 0x5423, 0x5432, 0x5482, 0x5494, 0x5477, 0x5471, 0x5464, 0x549A, 0x549B, + 0x5484, 0x5476, 0x5466, 0x549D, 0x54D0, 0x54AD, 0x54C2, 0x54B4, 0x54D2, + 0x54A7, 0x54A6, 0x54D3, 0x54D4, 0x5472, 0x54A3, 0x54D5, 0x54BB, 0x54BF, + 0x54CC, 0x54D9, 0x54DA, 0x54DC, 0x54A9, 0x54AA, 0x54A4, 0x54DD, 0x54CF, + 0x54DE, 0x551B, 0x54E7, 0x5520, 0x54FD, 0x5514, 0x54F3, 0x5522, 0x5523, + 0x550F, 0x5511, 0x5527, 0x552A, 0x5567, 0x558F, 0x55B5, 0x5549, 0x556D, + 0x5541, 0x5555, 0x553F, 0x5550, 0x553C, 0, 0x90C2, 0x90C3, 0x90C6, + 0x90C8, 0x90C9, 0x90CB, 0x90CC, 0x90CD, 0x90D2, 0x90D4, 0x90D5, 0x90D6, + 0x90D8, 0x90D9, 0x90DA, 0x90DE, 0x90DF, 0x90E0, 0x90E3, 0x90E4, 0x90E5, + 0x90E9, 0x90EA, 0x90EC, 0x90EE, 0x90F0, 0x90F1, 0x90F2, 0x90F3, 0x90F5, + 0x90F6, 0x90F7, 0x90F9, 0x90FA, 0x90FB, 0x90FC, 0x90FF, 0x9100, 0x9101, + 0x9103, 0x9105, 0x9106, 0x9107, 0x9108, 0x9109, 0x910A, 0x910B, 0x910C, + 0x910D, 0x910E, 0x910F, 0x9110, 0x9111, 0x9112, 0x9113, 0x9114, 0x9115, + 0x9116, 0x9117, 0x9118, 0x911A, 0x911B, 0x911C, 0, 0x911D, 0x911F, + 0x9120, 0x9121, 0x9124, 0x9125, 0x9126, 0x9127, 0x9128, 0x9129, 0x912A, + 0x912B, 0x912C, 0x912D, 0x912E, 0x9130, 0x9132, 0x9133, 0x9134, 0x9135, + 0x9136, 0x9137, 0x9138, 0x913A, 0x913B, 0x913C, 0x913D, 0x913E, 0x913F, + 0x9140, 0x9141, 0x9142, 0x9144, 0x5537, 0x5556, 0x5575, 0x5576, 0x5577, + 0x5533, 0x5530, 0x555C, 0x558B, 0x55D2, 0x5583, 0x55B1, 0x55B9, 0x5588, + 0x5581, 0x559F, 0x557E, 0x55D6, 0x5591, 0x557B, 0x55DF, 0x55BD, 0x55BE, + 0x5594, 0x5599, 0x55EA, 0x55F7, 0x55C9, 0x561F, 0x55D1, 0x55EB, 0x55EC, + 0x55D4, 0x55E6, 0x55DD, 0x55C4, 0x55EF, 0x55E5, 0x55F2, 0x55F3, 0x55CC, + 0x55CD, 0x55E8, 0x55F5, 0x55E4, 0x8F94, 0x561E, 0x5608, 0x560C, 0x5601, + 0x5624, 0x5623, 0x55FE, 0x5600, 0x5627, 0x562D, 0x5658, 0x5639, 0x5657, + 0x562C, 0x564D, 0x5662, 0x5659, 0x565C, 0x564C, 0x5654, 0x5686, 0x5664, + 0x5671, 0x566B, 0x567B, 0x567C, 0x5685, 0x5693, 0x56AF, 0x56D4, 0x56D7, + 0x56DD, 0x56E1, 0x56F5, 0x56EB, 0x56F9, 0x56FF, 0x5704, 0x570A, 0x5709, + 0x571C, 0x5E0F, 0x5E19, 0x5E14, 0x5E11, 0x5E31, 0x5E3B, 0x5E3C, 0, + 0x9145, 0x9147, 0x9148, 0x9151, 0x9153, 0x9154, 0x9155, 0x9156, 0x9158, + 0x9159, 0x915B, 0x915C, 0x915F, 0x9160, 0x9166, 0x9167, 0x9168, 0x916B, + 0x916D, 0x9173, 0x917A, 0x917B, 0x917C, 0x9180, 0x9181, 0x9182, 0x9183, + 0x9184, 0x9186, 0x9188, 0x918A, 0x918E, 0x918F, 0x9193, 0x9194, 0x9195, + 0x9196, 0x9197, 0x9198, 0x9199, 0x919C, 0x919D, 0x919E, 0x919F, 0x91A0, + 0x91A1, 0x91A4, 0x91A5, 0x91A6, 0x91A7, 0x91A8, 0x91A9, 0x91AB, 0x91AC, + 0x91B0, 0x91B1, 0x91B2, 0x91B3, 0x91B6, 0x91B7, 0x91B8, 0x91B9, 0x91BB, + 0, 0x91BC, 0x91BD, 0x91BE, 0x91BF, 0x91C0, 0x91C1, 0x91C2, 0x91C3, + 0x91C4, 0x91C5, 0x91C6, 0x91C8, 0x91CB, 0x91D0, 0x91D2, 0x91D3, 0x91D4, + 0x91D5, 0x91D6, 0x91D7, 0x91D8, 0x91D9, 0x91DA, 0x91DB, 0x91DD, 0x91DE, + 0x91DF, 0x91E0, 0x91E1, 0x91E2, 0x91E3, 0x91E4, 0x91E5, 0x5E37, 0x5E44, + 0x5E54, 0x5E5B, 0x5E5E, 0x5E61, 0x5C8C, 0x5C7A, 0x5C8D, 0x5C90, 0x5C96, + 0x5C88, 0x5C98, 0x5C99, 0x5C91, 0x5C9A, 0x5C9C, 0x5CB5, 0x5CA2, 0x5CBD, + 0x5CAC, 0x5CAB, 0x5CB1, 0x5CA3, 0x5CC1, 0x5CB7, 0x5CC4, 0x5CD2, 0x5CE4, + 0x5CCB, 0x5CE5, 0x5D02, 0x5D03, 0x5D27, 0x5D26, 0x5D2E, 0x5D24, 0x5D1E, + 0x5D06, 0x5D1B, 0x5D58, 0x5D3E, 0x5D34, 0x5D3D, 0x5D6C, 0x5D5B, 0x5D6F, + 0x5D5D, 0x5D6B, 0x5D4B, 0x5D4A, 0x5D69, 0x5D74, 0x5D82, 0x5D99, 0x5D9D, + 0x8C73, 0x5DB7, 0x5DC5, 0x5F73, 0x5F77, 0x5F82, 0x5F87, 0x5F89, 0x5F8C, + 0x5F95, 0x5F99, 0x5F9C, 0x5FA8, 0x5FAD, 0x5FB5, 0x5FBC, 0x8862, 0x5F61, + 0x72AD, 0x72B0, 0x72B4, 0x72B7, 0x72B8, 0x72C3, 0x72C1, 0x72CE, 0x72CD, + 0x72D2, 0x72E8, 0x72EF, 0x72E9, 0x72F2, 0x72F4, 0x72F7, 0x7301, 0x72F3, + 0x7303, 0x72FA, 0, 0x91E6, 0x91E7, 0x91E8, 0x91E9, 0x91EA, 0x91EB, + 0x91EC, 0x91ED, 0x91EE, 0x91EF, 0x91F0, 0x91F1, 0x91F2, 0x91F3, 0x91F4, + 0x91F5, 0x91F6, 0x91F7, 0x91F8, 0x91F9, 0x91FA, 0x91FB, 0x91FC, 0x91FD, + 0x91FE, 0x91FF, 0x9200, 0x9201, 0x9202, 0x9203, 0x9204, 0x9205, 0x9206, + 0x9207, 0x9208, 0x9209, 0x920A, 0x920B, 0x920C, 0x920D, 0x920E, 0x920F, + 0x9210, 0x9211, 0x9212, 0x9213, 0x9214, 0x9215, 0x9216, 0x9217, 0x9218, + 0x9219, 0x921A, 0x921B, 0x921C, 0x921D, 0x921E, 0x921F, 0x9220, 0x9221, + 0x9222, 0x9223, 0x9224, 0, 0x9225, 0x9226, 0x9227, 0x9228, 0x9229, + 0x922A, 0x922B, 0x922C, 0x922D, 0x922E, 0x922F, 0x9230, 0x9231, 0x9232, + 0x9233, 0x9234, 0x9235, 0x9236, 0x9237, 0x9238, 0x9239, 0x923A, 0x923B, + 0x923C, 0x923D, 0x923E, 0x923F, 0x9240, 0x9241, 0x9242, 0x9243, 0x9244, + 0x9245, 0x72FB, 0x7317, 0x7313, 0x7321, 0x730A, 0x731E, 0x731D, 0x7315, + 0x7322, 0x7339, 0x7325, 0x732C, 0x7338, 0x7331, 0x7350, 0x734D, 0x7357, + 0x7360, 0x736C, 0x736F, 0x737E, 0x821B, 0x5925, 0x98E7, 0x5924, 0x5902, + 0x9963, 0x9967, 0x9968, 0x9969, 0x996A, 0x996B, 0x996C, 0x9974, 0x9977, + 0x997D, 0x9980, 0x9984, 0x9987, 0x998A, 0x998D, 0x9990, 0x9991, 0x9993, + 0x9994, 0x9995, 0x5E80, 0x5E91, 0x5E8B, 0x5E96, 0x5EA5, 0x5EA0, 0x5EB9, + 0x5EB5, 0x5EBE, 0x5EB3, 0x8D53, 0x5ED2, 0x5ED1, 0x5EDB, 0x5EE8, 0x5EEA, + 0x81BA, 0x5FC4, 0x5FC9, 0x5FD6, 0x5FCF, 0x6003, 0x5FEE, 0x6004, 0x5FE1, + 0x5FE4, 0x5FFE, 0x6005, 0x6006, 0x5FEA, 0x5FED, 0x5FF8, 0x6019, 0x6035, + 0x6026, 0x601B, 0x600F, 0x600D, 0x6029, 0x602B, 0x600A, 0x603F, 0x6021, + 0x6078, 0x6079, 0x607B, 0x607A, 0x6042, 0, 0x9246, 0x9247, 0x9248, + 0x9249, 0x924A, 0x924B, 0x924C, 0x924D, 0x924E, 0x924F, 0x9250, 0x9251, + 0x9252, 0x9253, 0x9254, 0x9255, 0x9256, 0x9257, 0x9258, 0x9259, 0x925A, + 0x925B, 0x925C, 0x925D, 0x925E, 0x925F, 0x9260, 0x9261, 0x9262, 0x9263, + 0x9264, 0x9265, 0x9266, 0x9267, 0x9268, 0x9269, 0x926A, 0x926B, 0x926C, + 0x926D, 0x926E, 0x926F, 0x9270, 0x9271, 0x9272, 0x9273, 0x9275, 0x9276, + 0x9277, 0x9278, 0x9279, 0x927A, 0x927B, 0x927C, 0x927D, 0x927E, 0x927F, + 0x9280, 0x9281, 0x9282, 0x9283, 0x9284, 0x9285, 0, 0x9286, 0x9287, + 0x9288, 0x9289, 0x928A, 0x928B, 0x928C, 0x928D, 0x928F, 0x9290, 0x9291, + 0x9292, 0x9293, 0x9294, 0x9295, 0x9296, 0x9297, 0x9298, 0x9299, 0x929A, + 0x929B, 0x929C, 0x929D, 0x929E, 0x929F, 0x92A0, 0x92A1, 0x92A2, 0x92A3, + 0x92A4, 0x92A5, 0x92A6, 0x92A7, 0x606A, 0x607D, 0x6096, 0x609A, 0x60AD, + 0x609D, 0x6083, 0x6092, 0x608C, 0x609B, 0x60EC, 0x60BB, 0x60B1, 0x60DD, + 0x60D8, 0x60C6, 0x60DA, 0x60B4, 0x6120, 0x6126, 0x6115, 0x6123, 0x60F4, + 0x6100, 0x610E, 0x612B, 0x614A, 0x6175, 0x61AC, 0x6194, 0x61A7, 0x61B7, + 0x61D4, 0x61F5, 0x5FDD, 0x96B3, 0x95E9, 0x95EB, 0x95F1, 0x95F3, 0x95F5, + 0x95F6, 0x95FC, 0x95FE, 0x9603, 0x9604, 0x9606, 0x9608, 0x960A, 0x960B, + 0x960C, 0x960D, 0x960F, 0x9612, 0x9615, 0x9616, 0x9617, 0x9619, 0x961A, + 0x4E2C, 0x723F, 0x6215, 0x6C35, 0x6C54, 0x6C5C, 0x6C4A, 0x6CA3, 0x6C85, + 0x6C90, 0x6C94, 0x6C8C, 0x6C68, 0x6C69, 0x6C74, 0x6C76, 0x6C86, 0x6CA9, + 0x6CD0, 0x6CD4, 0x6CAD, 0x6CF7, 0x6CF8, 0x6CF1, 0x6CD7, 0x6CB2, 0x6CE0, + 0x6CD6, 0x6CFA, 0x6CEB, 0x6CEE, 0x6CB1, 0x6CD3, 0x6CEF, 0x6CFE, 0, + 0x92A8, 0x92A9, 0x92AA, 0x92AB, 0x92AC, 0x92AD, 0x92AF, 0x92B0, 0x92B1, + 0x92B2, 0x92B3, 0x92B4, 0x92B5, 0x92B6, 0x92B7, 0x92B8, 0x92B9, 0x92BA, + 0x92BB, 0x92BC, 0x92BD, 0x92BE, 0x92BF, 0x92C0, 0x92C1, 0x92C2, 0x92C3, + 0x92C4, 0x92C5, 0x92C6, 0x92C7, 0x92C9, 0x92CA, 0x92CB, 0x92CC, 0x92CD, + 0x92CE, 0x92CF, 0x92D0, 0x92D1, 0x92D2, 0x92D3, 0x92D4, 0x92D5, 0x92D6, + 0x92D7, 0x92D8, 0x92D9, 0x92DA, 0x92DB, 0x92DC, 0x92DD, 0x92DE, 0x92DF, + 0x92E0, 0x92E1, 0x92E2, 0x92E3, 0x92E4, 0x92E5, 0x92E6, 0x92E7, 0x92E8, + 0, 0x92E9, 0x92EA, 0x92EB, 0x92EC, 0x92ED, 0x92EE, 0x92EF, 0x92F0, + 0x92F1, 0x92F2, 0x92F3, 0x92F4, 0x92F5, 0x92F6, 0x92F7, 0x92F8, 0x92F9, + 0x92FA, 0x92FB, 0x92FC, 0x92FD, 0x92FE, 0x92FF, 0x9300, 0x9301, 0x9302, + 0x9303, 0x9304, 0x9305, 0x9306, 0x9307, 0x9308, 0x9309, 0x6D39, 0x6D27, + 0x6D0C, 0x6D43, 0x6D48, 0x6D07, 0x6D04, 0x6D19, 0x6D0E, 0x6D2B, 0x6D4D, + 0x6D2E, 0x6D35, 0x6D1A, 0x6D4F, 0x6D52, 0x6D54, 0x6D33, 0x6D91, 0x6D6F, + 0x6D9E, 0x6DA0, 0x6D5E, 0x6D93, 0x6D94, 0x6D5C, 0x6D60, 0x6D7C, 0x6D63, + 0x6E1A, 0x6DC7, 0x6DC5, 0x6DDE, 0x6E0E, 0x6DBF, 0x6DE0, 0x6E11, 0x6DE6, + 0x6DDD, 0x6DD9, 0x6E16, 0x6DAB, 0x6E0C, 0x6DAE, 0x6E2B, 0x6E6E, 0x6E4E, + 0x6E6B, 0x6EB2, 0x6E5F, 0x6E86, 0x6E53, 0x6E54, 0x6E32, 0x6E25, 0x6E44, + 0x6EDF, 0x6EB1, 0x6E98, 0x6EE0, 0x6F2D, 0x6EE2, 0x6EA5, 0x6EA7, 0x6EBD, + 0x6EBB, 0x6EB7, 0x6ED7, 0x6EB4, 0x6ECF, 0x6E8F, 0x6EC2, 0x6E9F, 0x6F62, + 0x6F46, 0x6F47, 0x6F24, 0x6F15, 0x6EF9, 0x6F2F, 0x6F36, 0x6F4B, 0x6F74, + 0x6F2A, 0x6F09, 0x6F29, 0x6F89, 0x6F8D, 0x6F8C, 0x6F78, 0x6F72, 0x6F7C, + 0x6F7A, 0x6FD1, 0, 0x930A, 0x930B, 0x930C, 0x930D, 0x930E, 0x930F, + 0x9310, 0x9311, 0x9312, 0x9313, 0x9314, 0x9315, 0x9316, 0x9317, 0x9318, + 0x9319, 0x931A, 0x931B, 0x931C, 0x931D, 0x931E, 0x931F, 0x9320, 0x9321, + 0x9322, 0x9323, 0x9324, 0x9325, 0x9326, 0x9327, 0x9328, 0x9329, 0x932A, + 0x932B, 0x932C, 0x932D, 0x932E, 0x932F, 0x9330, 0x9331, 0x9332, 0x9333, + 0x9334, 0x9335, 0x9336, 0x9337, 0x9338, 0x9339, 0x933A, 0x933B, 0x933C, + 0x933D, 0x933F, 0x9340, 0x9341, 0x9342, 0x9343, 0x9344, 0x9345, 0x9346, + 0x9347, 0x9348, 0x9349, 0, 0x934A, 0x934B, 0x934C, 0x934D, 0x934E, + 0x934F, 0x9350, 0x9351, 0x9352, 0x9353, 0x9354, 0x9355, 0x9356, 0x9357, + 0x9358, 0x9359, 0x935A, 0x935B, 0x935C, 0x935D, 0x935E, 0x935F, 0x9360, + 0x9361, 0x9362, 0x9363, 0x9364, 0x9365, 0x9366, 0x9367, 0x9368, 0x9369, + 0x936B, 0x6FC9, 0x6FA7, 0x6FB9, 0x6FB6, 0x6FC2, 0x6FE1, 0x6FEE, 0x6FDE, + 0x6FE0, 0x6FEF, 0x701A, 0x7023, 0x701B, 0x7039, 0x7035, 0x704F, 0x705E, + 0x5B80, 0x5B84, 0x5B95, 0x5B93, 0x5BA5, 0x5BB8, 0x752F, 0x9A9E, 0x6434, + 0x5BE4, 0x5BEE, 0x8930, 0x5BF0, 0x8E47, 0x8B07, 0x8FB6, 0x8FD3, 0x8FD5, + 0x8FE5, 0x8FEE, 0x8FE4, 0x8FE9, 0x8FE6, 0x8FF3, 0x8FE8, 0x9005, 0x9004, + 0x900B, 0x9026, 0x9011, 0x900D, 0x9016, 0x9021, 0x9035, 0x9036, 0x902D, + 0x902F, 0x9044, 0x9051, 0x9052, 0x9050, 0x9068, 0x9058, 0x9062, 0x905B, + 0x66B9, 0x9074, 0x907D, 0x9082, 0x9088, 0x9083, 0x908B, 0x5F50, 0x5F57, + 0x5F56, 0x5F58, 0x5C3B, 0x54AB, 0x5C50, 0x5C59, 0x5B71, 0x5C63, 0x5C66, + 0x7FBC, 0x5F2A, 0x5F29, 0x5F2D, 0x8274, 0x5F3C, 0x9B3B, 0x5C6E, 0x5981, + 0x5983, 0x598D, 0x59A9, 0x59AA, 0x59A3, 0, 0x936C, 0x936D, 0x936E, + 0x936F, 0x9370, 0x9371, 0x9372, 0x9373, 0x9374, 0x9375, 0x9376, 0x9377, + 0x9378, 0x9379, 0x937A, 0x937B, 0x937C, 0x937D, 0x937E, 0x937F, 0x9380, + 0x9381, 0x9382, 0x9383, 0x9384, 0x9385, 0x9386, 0x9387, 0x9388, 0x9389, + 0x938A, 0x938B, 0x938C, 0x938D, 0x938E, 0x9390, 0x9391, 0x9392, 0x9393, + 0x9394, 0x9395, 0x9396, 0x9397, 0x9398, 0x9399, 0x939A, 0x939B, 0x939C, + 0x939D, 0x939E, 0x939F, 0x93A0, 0x93A1, 0x93A2, 0x93A3, 0x93A4, 0x93A5, + 0x93A6, 0x93A7, 0x93A8, 0x93A9, 0x93AA, 0x93AB, 0, 0x93AC, 0x93AD, + 0x93AE, 0x93AF, 0x93B0, 0x93B1, 0x93B2, 0x93B3, 0x93B4, 0x93B5, 0x93B6, + 0x93B7, 0x93B8, 0x93B9, 0x93BA, 0x93BB, 0x93BC, 0x93BD, 0x93BE, 0x93BF, + 0x93C0, 0x93C1, 0x93C2, 0x93C3, 0x93C4, 0x93C5, 0x93C6, 0x93C7, 0x93C8, + 0x93C9, 0x93CB, 0x93CC, 0x93CD, 0x5997, 0x59CA, 0x59AB, 0x599E, 0x59A4, + 0x59D2, 0x59B2, 0x59AF, 0x59D7, 0x59BE, 0x5A05, 0x5A06, 0x59DD, 0x5A08, + 0x59E3, 0x59D8, 0x59F9, 0x5A0C, 0x5A09, 0x5A32, 0x5A34, 0x5A11, 0x5A23, + 0x5A13, 0x5A40, 0x5A67, 0x5A4A, 0x5A55, 0x5A3C, 0x5A62, 0x5A75, 0x80EC, + 0x5AAA, 0x5A9B, 0x5A77, 0x5A7A, 0x5ABE, 0x5AEB, 0x5AB2, 0x5AD2, 0x5AD4, + 0x5AB8, 0x5AE0, 0x5AE3, 0x5AF1, 0x5AD6, 0x5AE6, 0x5AD8, 0x5ADC, 0x5B09, + 0x5B17, 0x5B16, 0x5B32, 0x5B37, 0x5B40, 0x5C15, 0x5C1C, 0x5B5A, 0x5B65, + 0x5B73, 0x5B51, 0x5B53, 0x5B62, 0x9A75, 0x9A77, 0x9A78, 0x9A7A, 0x9A7F, + 0x9A7D, 0x9A80, 0x9A81, 0x9A85, 0x9A88, 0x9A8A, 0x9A90, 0x9A92, 0x9A93, + 0x9A96, 0x9A98, 0x9A9B, 0x9A9C, 0x9A9D, 0x9A9F, 0x9AA0, 0x9AA2, 0x9AA3, + 0x9AA5, 0x9AA7, 0x7E9F, 0x7EA1, 0x7EA3, 0x7EA5, 0x7EA8, 0x7EA9, 0, + 0x93CE, 0x93CF, 0x93D0, 0x93D1, 0x93D2, 0x93D3, 0x93D4, 0x93D5, 0x93D7, + 0x93D8, 0x93D9, 0x93DA, 0x93DB, 0x93DC, 0x93DD, 0x93DE, 0x93DF, 0x93E0, + 0x93E1, 0x93E2, 0x93E3, 0x93E4, 0x93E5, 0x93E6, 0x93E7, 0x93E8, 0x93E9, + 0x93EA, 0x93EB, 0x93EC, 0x93ED, 0x93EE, 0x93EF, 0x93F0, 0x93F1, 0x93F2, + 0x93F3, 0x93F4, 0x93F5, 0x93F6, 0x93F7, 0x93F8, 0x93F9, 0x93FA, 0x93FB, + 0x93FC, 0x93FD, 0x93FE, 0x93FF, 0x9400, 0x9401, 0x9402, 0x9403, 0x9404, + 0x9405, 0x9406, 0x9407, 0x9408, 0x9409, 0x940A, 0x940B, 0x940C, 0x940D, + 0, 0x940E, 0x940F, 0x9410, 0x9411, 0x9412, 0x9413, 0x9414, 0x9415, + 0x9416, 0x9417, 0x9418, 0x9419, 0x941A, 0x941B, 0x941C, 0x941D, 0x941E, + 0x941F, 0x9420, 0x9421, 0x9422, 0x9423, 0x9424, 0x9425, 0x9426, 0x9427, + 0x9428, 0x9429, 0x942A, 0x942B, 0x942C, 0x942D, 0x942E, 0x7EAD, 0x7EB0, + 0x7EBE, 0x7EC0, 0x7EC1, 0x7EC2, 0x7EC9, 0x7ECB, 0x7ECC, 0x7ED0, 0x7ED4, + 0x7ED7, 0x7EDB, 0x7EE0, 0x7EE1, 0x7EE8, 0x7EEB, 0x7EEE, 0x7EEF, 0x7EF1, + 0x7EF2, 0x7F0D, 0x7EF6, 0x7EFA, 0x7EFB, 0x7EFE, 0x7F01, 0x7F02, 0x7F03, + 0x7F07, 0x7F08, 0x7F0B, 0x7F0C, 0x7F0F, 0x7F11, 0x7F12, 0x7F17, 0x7F19, + 0x7F1C, 0x7F1B, 0x7F1F, 0x7F21, 0x7F22, 0x7F23, 0x7F24, 0x7F25, 0x7F26, + 0x7F27, 0x7F2A, 0x7F2B, 0x7F2C, 0x7F2D, 0x7F2F, 0x7F30, 0x7F31, 0x7F32, + 0x7F33, 0x7F35, 0x5E7A, 0x757F, 0x5DDB, 0x753E, 0x9095, 0x738E, 0x7391, + 0x73AE, 0x73A2, 0x739F, 0x73CF, 0x73C2, 0x73D1, 0x73B7, 0x73B3, 0x73C0, + 0x73C9, 0x73C8, 0x73E5, 0x73D9, 0x987C, 0x740A, 0x73E9, 0x73E7, 0x73DE, + 0x73BA, 0x73F2, 0x740F, 0x742A, 0x745B, 0x7426, 0x7425, 0x7428, 0x7430, + 0x742E, 0x742C, 0, 0x942F, 0x9430, 0x9431, 0x9432, 0x9433, 0x9434, + 0x9435, 0x9436, 0x9437, 0x9438, 0x9439, 0x943A, 0x943B, 0x943C, 0x943D, + 0x943F, 0x9440, 0x9441, 0x9442, 0x9443, 0x9444, 0x9445, 0x9446, 0x9447, + 0x9448, 0x9449, 0x944A, 0x944B, 0x944C, 0x944D, 0x944E, 0x944F, 0x9450, + 0x9451, 0x9452, 0x9453, 0x9454, 0x9455, 0x9456, 0x9457, 0x9458, 0x9459, + 0x945A, 0x945B, 0x945C, 0x945D, 0x945E, 0x945F, 0x9460, 0x9461, 0x9462, + 0x9463, 0x9464, 0x9465, 0x9466, 0x9467, 0x9468, 0x9469, 0x946A, 0x946C, + 0x946D, 0x946E, 0x946F, 0, 0x9470, 0x9471, 0x9472, 0x9473, 0x9474, + 0x9475, 0x9476, 0x9477, 0x9478, 0x9479, 0x947A, 0x947B, 0x947C, 0x947D, + 0x947E, 0x947F, 0x9480, 0x9481, 0x9482, 0x9483, 0x9484, 0x9491, 0x9496, + 0x9498, 0x94C7, 0x94CF, 0x94D3, 0x94D4, 0x94DA, 0x94E6, 0x94FB, 0x951C, + 0x9520, 0x741B, 0x741A, 0x7441, 0x745C, 0x7457, 0x7455, 0x7459, 0x7477, + 0x746D, 0x747E, 0x749C, 0x748E, 0x7480, 0x7481, 0x7487, 0x748B, 0x749E, + 0x74A8, 0x74A9, 0x7490, 0x74A7, 0x74D2, 0x74BA, 0x97EA, 0x97EB, 0x97EC, + 0x674C, 0x6753, 0x675E, 0x6748, 0x6769, 0x67A5, 0x6787, 0x676A, 0x6773, + 0x6798, 0x67A7, 0x6775, 0x67A8, 0x679E, 0x67AD, 0x678B, 0x6777, 0x677C, + 0x67F0, 0x6809, 0x67D8, 0x680A, 0x67E9, 0x67B0, 0x680C, 0x67D9, 0x67B5, + 0x67DA, 0x67B3, 0x67DD, 0x6800, 0x67C3, 0x67B8, 0x67E2, 0x680E, 0x67C1, + 0x67FD, 0x6832, 0x6833, 0x6860, 0x6861, 0x684E, 0x6862, 0x6844, 0x6864, + 0x6883, 0x681D, 0x6855, 0x6866, 0x6841, 0x6867, 0x6840, 0x683E, 0x684A, + 0x6849, 0x6829, 0x68B5, 0x688F, 0x6874, 0x6877, 0x6893, 0x686B, 0x68C2, + 0x696E, 0x68FC, 0x691F, 0x6920, 0x68F9, 0, 0x9527, 0x9533, 0x953D, + 0x9543, 0x9548, 0x954B, 0x9555, 0x955A, 0x9560, 0x956E, 0x9574, 0x9575, + 0x9577, 0x9578, 0x9579, 0x957A, 0x957B, 0x957C, 0x957D, 0x957E, 0x9580, + 0x9581, 0x9582, 0x9583, 0x9584, 0x9585, 0x9586, 0x9587, 0x9588, 0x9589, + 0x958A, 0x958B, 0x958C, 0x958D, 0x958E, 0x958F, 0x9590, 0x9591, 0x9592, + 0x9593, 0x9594, 0x9595, 0x9596, 0x9597, 0x9598, 0x9599, 0x959A, 0x959B, + 0x959C, 0x959D, 0x959E, 0x959F, 0x95A0, 0x95A1, 0x95A2, 0x95A3, 0x95A4, + 0x95A5, 0x95A6, 0x95A7, 0x95A8, 0x95A9, 0x95AA, 0, 0x95AB, 0x95AC, + 0x95AD, 0x95AE, 0x95AF, 0x95B0, 0x95B1, 0x95B2, 0x95B3, 0x95B4, 0x95B5, + 0x95B6, 0x95B7, 0x95B8, 0x95B9, 0x95BA, 0x95BB, 0x95BC, 0x95BD, 0x95BE, + 0x95BF, 0x95C0, 0x95C1, 0x95C2, 0x95C3, 0x95C4, 0x95C5, 0x95C6, 0x95C7, + 0x95C8, 0x95C9, 0x95CA, 0x95CB, 0x6924, 0x68F0, 0x690B, 0x6901, 0x6957, + 0x68E3, 0x6910, 0x6971, 0x6939, 0x6960, 0x6942, 0x695D, 0x6984, 0x696B, + 0x6980, 0x6998, 0x6978, 0x6934, 0x69CC, 0x6987, 0x6988, 0x69CE, 0x6989, + 0x6966, 0x6963, 0x6979, 0x699B, 0x69A7, 0x69BB, 0x69AB, 0x69AD, 0x69D4, + 0x69B1, 0x69C1, 0x69CA, 0x69DF, 0x6995, 0x69E0, 0x698D, 0x69FF, 0x6A2F, + 0x69ED, 0x6A17, 0x6A18, 0x6A65, 0x69F2, 0x6A44, 0x6A3E, 0x6AA0, 0x6A50, + 0x6A5B, 0x6A35, 0x6A8E, 0x6A79, 0x6A3D, 0x6A28, 0x6A58, 0x6A7C, 0x6A91, + 0x6A90, 0x6AA9, 0x6A97, 0x6AAB, 0x7337, 0x7352, 0x6B81, 0x6B82, 0x6B87, + 0x6B84, 0x6B92, 0x6B93, 0x6B8D, 0x6B9A, 0x6B9B, 0x6BA1, 0x6BAA, 0x8F6B, + 0x8F6D, 0x8F71, 0x8F72, 0x8F73, 0x8F75, 0x8F76, 0x8F78, 0x8F77, 0x8F79, + 0x8F7A, 0x8F7C, 0x8F7E, 0x8F81, 0x8F82, 0x8F84, 0x8F87, 0x8F8B, 0, + 0x95CC, 0x95CD, 0x95CE, 0x95CF, 0x95D0, 0x95D1, 0x95D2, 0x95D3, 0x95D4, + 0x95D5, 0x95D6, 0x95D7, 0x95D8, 0x95D9, 0x95DA, 0x95DB, 0x95DC, 0x95DD, + 0x95DE, 0x95DF, 0x95E0, 0x95E1, 0x95E2, 0x95E3, 0x95E4, 0x95E5, 0x95E6, + 0x95E7, 0x95EC, 0x95FF, 0x9607, 0x9613, 0x9618, 0x961B, 0x961E, 0x9620, + 0x9623, 0x9624, 0x9625, 0x9626, 0x9627, 0x9628, 0x9629, 0x962B, 0x962C, + 0x962D, 0x962F, 0x9630, 0x9637, 0x9638, 0x9639, 0x963A, 0x963E, 0x9641, + 0x9643, 0x964A, 0x964E, 0x964F, 0x9651, 0x9652, 0x9653, 0x9656, 0x9657, + 0, 0x9658, 0x9659, 0x965A, 0x965C, 0x965D, 0x965E, 0x9660, 0x9663, + 0x9665, 0x9666, 0x966B, 0x966D, 0x966E, 0x966F, 0x9670, 0x9671, 0x9673, + 0x9678, 0x9679, 0x967A, 0x967B, 0x967C, 0x967D, 0x967E, 0x967F, 0x9680, + 0x9681, 0x9682, 0x9683, 0x9684, 0x9687, 0x9689, 0x968A, 0x8F8D, 0x8F8E, + 0x8F8F, 0x8F98, 0x8F9A, 0x8ECE, 0x620B, 0x6217, 0x621B, 0x621F, 0x6222, + 0x6221, 0x6225, 0x6224, 0x622C, 0x81E7, 0x74EF, 0x74F4, 0x74FF, 0x750F, + 0x7511, 0x7513, 0x6534, 0x65EE, 0x65EF, 0x65F0, 0x660A, 0x6619, 0x6772, + 0x6603, 0x6615, 0x6600, 0x7085, 0x66F7, 0x661D, 0x6634, 0x6631, 0x6636, + 0x6635, 0x8006, 0x665F, 0x6654, 0x6641, 0x664F, 0x6656, 0x6661, 0x6657, + 0x6677, 0x6684, 0x668C, 0x66A7, 0x669D, 0x66BE, 0x66DB, 0x66DC, 0x66E6, + 0x66E9, 0x8D32, 0x8D33, 0x8D36, 0x8D3B, 0x8D3D, 0x8D40, 0x8D45, 0x8D46, + 0x8D48, 0x8D49, 0x8D47, 0x8D4D, 0x8D55, 0x8D59, 0x89C7, 0x89CA, 0x89CB, + 0x89CC, 0x89CE, 0x89CF, 0x89D0, 0x89D1, 0x726E, 0x729F, 0x725D, 0x7266, + 0x726F, 0x727E, 0x727F, 0x7284, 0x728B, 0x728D, 0x728F, 0x7292, 0x6308, + 0x6332, 0x63B0, 0, 0x968C, 0x968E, 0x9691, 0x9692, 0x9693, 0x9695, + 0x9696, 0x969A, 0x969B, 0x969D, 0x969E, 0x969F, 0x96A0, 0x96A1, 0x96A2, + 0x96A3, 0x96A4, 0x96A5, 0x96A6, 0x96A8, 0x96A9, 0x96AA, 0x96AB, 0x96AC, + 0x96AD, 0x96AE, 0x96AF, 0x96B1, 0x96B2, 0x96B4, 0x96B5, 0x96B7, 0x96B8, + 0x96BA, 0x96BB, 0x96BF, 0x96C2, 0x96C3, 0x96C8, 0x96CA, 0x96CB, 0x96D0, + 0x96D1, 0x96D3, 0x96D4, 0x96D6, 0x96D7, 0x96D8, 0x96D9, 0x96DA, 0x96DB, + 0x96DC, 0x96DD, 0x96DE, 0x96DF, 0x96E1, 0x96E2, 0x96E3, 0x96E4, 0x96E5, + 0x96E6, 0x96E7, 0x96EB, 0, 0x96EC, 0x96ED, 0x96EE, 0x96F0, 0x96F1, + 0x96F2, 0x96F4, 0x96F5, 0x96F8, 0x96FA, 0x96FB, 0x96FC, 0x96FD, 0x96FF, + 0x9702, 0x9703, 0x9705, 0x970A, 0x970B, 0x970C, 0x9710, 0x9711, 0x9712, + 0x9714, 0x9715, 0x9717, 0x9718, 0x9719, 0x971A, 0x971B, 0x971D, 0x971F, + 0x9720, 0x643F, 0x64D8, 0x8004, 0x6BEA, 0x6BF3, 0x6BFD, 0x6BF5, 0x6BF9, + 0x6C05, 0x6C07, 0x6C06, 0x6C0D, 0x6C15, 0x6C18, 0x6C19, 0x6C1A, 0x6C21, + 0x6C29, 0x6C24, 0x6C2A, 0x6C32, 0x6535, 0x6555, 0x656B, 0x724D, 0x7252, + 0x7256, 0x7230, 0x8662, 0x5216, 0x809F, 0x809C, 0x8093, 0x80BC, 0x670A, + 0x80BD, 0x80B1, 0x80AB, 0x80AD, 0x80B4, 0x80B7, 0x80E7, 0x80E8, 0x80E9, + 0x80EA, 0x80DB, 0x80C2, 0x80C4, 0x80D9, 0x80CD, 0x80D7, 0x6710, 0x80DD, + 0x80EB, 0x80F1, 0x80F4, 0x80ED, 0x810D, 0x810E, 0x80F2, 0x80FC, 0x6715, + 0x8112, 0x8C5A, 0x8136, 0x811E, 0x812C, 0x8118, 0x8132, 0x8148, 0x814C, + 0x8153, 0x8174, 0x8159, 0x815A, 0x8171, 0x8160, 0x8169, 0x817C, 0x817D, + 0x816D, 0x8167, 0x584D, 0x5AB5, 0x8188, 0x8182, 0x8191, 0x6ED5, 0x81A3, + 0x81AA, 0x81CC, 0x6726, 0x81CA, 0x81BB, 0, 0x9721, 0x9722, 0x9723, + 0x9724, 0x9725, 0x9726, 0x9727, 0x9728, 0x9729, 0x972B, 0x972C, 0x972E, + 0x972F, 0x9731, 0x9733, 0x9734, 0x9735, 0x9736, 0x9737, 0x973A, 0x973B, + 0x973C, 0x973D, 0x973F, 0x9740, 0x9741, 0x9742, 0x9743, 0x9744, 0x9745, + 0x9746, 0x9747, 0x9748, 0x9749, 0x974A, 0x974B, 0x974C, 0x974D, 0x974E, + 0x974F, 0x9750, 0x9751, 0x9754, 0x9755, 0x9757, 0x9758, 0x975A, 0x975C, + 0x975D, 0x975F, 0x9763, 0x9764, 0x9766, 0x9767, 0x9768, 0x976A, 0x976B, + 0x976C, 0x976D, 0x976E, 0x976F, 0x9770, 0x9771, 0, 0x9772, 0x9775, + 0x9777, 0x9778, 0x9779, 0x977A, 0x977B, 0x977D, 0x977E, 0x977F, 0x9780, + 0x9781, 0x9782, 0x9783, 0x9784, 0x9786, 0x9787, 0x9788, 0x9789, 0x978A, + 0x978C, 0x978E, 0x978F, 0x9790, 0x9793, 0x9795, 0x9796, 0x9797, 0x9799, + 0x979A, 0x979B, 0x979C, 0x979D, 0x81C1, 0x81A6, 0x6B24, 0x6B37, 0x6B39, + 0x6B43, 0x6B46, 0x6B59, 0x98D1, 0x98D2, 0x98D3, 0x98D5, 0x98D9, 0x98DA, + 0x6BB3, 0x5F40, 0x6BC2, 0x89F3, 0x6590, 0x9F51, 0x6593, 0x65BC, 0x65C6, + 0x65C4, 0x65C3, 0x65CC, 0x65CE, 0x65D2, 0x65D6, 0x7080, 0x709C, 0x7096, + 0x709D, 0x70BB, 0x70C0, 0x70B7, 0x70AB, 0x70B1, 0x70E8, 0x70CA, 0x7110, + 0x7113, 0x7116, 0x712F, 0x7131, 0x7173, 0x715C, 0x7168, 0x7145, 0x7172, + 0x714A, 0x7178, 0x717A, 0x7198, 0x71B3, 0x71B5, 0x71A8, 0x71A0, 0x71E0, + 0x71D4, 0x71E7, 0x71F9, 0x721D, 0x7228, 0x706C, 0x7118, 0x7166, 0x71B9, + 0x623E, 0x623D, 0x6243, 0x6248, 0x6249, 0x793B, 0x7940, 0x7946, 0x7949, + 0x795B, 0x795C, 0x7953, 0x795A, 0x7962, 0x7957, 0x7960, 0x796F, 0x7967, + 0x797A, 0x7985, 0x798A, 0x799A, 0x79A7, 0x79B3, 0x5FD1, 0x5FD0, 0, + 0x979E, 0x979F, 0x97A1, 0x97A2, 0x97A4, 0x97A5, 0x97A6, 0x97A7, 0x97A8, + 0x97A9, 0x97AA, 0x97AC, 0x97AE, 0x97B0, 0x97B1, 0x97B3, 0x97B5, 0x97B6, + 0x97B7, 0x97B8, 0x97B9, 0x97BA, 0x97BB, 0x97BC, 0x97BD, 0x97BE, 0x97BF, + 0x97C0, 0x97C1, 0x97C2, 0x97C3, 0x97C4, 0x97C5, 0x97C6, 0x97C7, 0x97C8, + 0x97C9, 0x97CA, 0x97CB, 0x97CC, 0x97CD, 0x97CE, 0x97CF, 0x97D0, 0x97D1, + 0x97D2, 0x97D3, 0x97D4, 0x97D5, 0x97D6, 0x97D7, 0x97D8, 0x97D9, 0x97DA, + 0x97DB, 0x97DC, 0x97DD, 0x97DE, 0x97DF, 0x97E0, 0x97E1, 0x97E2, 0x97E3, + 0, 0x97E4, 0x97E5, 0x97E8, 0x97EE, 0x97EF, 0x97F0, 0x97F1, 0x97F2, + 0x97F4, 0x97F7, 0x97F8, 0x97F9, 0x97FA, 0x97FB, 0x97FC, 0x97FD, 0x97FE, + 0x97FF, 0x9800, 0x9801, 0x9802, 0x9803, 0x9804, 0x9805, 0x9806, 0x9807, + 0x9808, 0x9809, 0x980A, 0x980B, 0x980C, 0x980D, 0x980E, 0x603C, 0x605D, + 0x605A, 0x6067, 0x6041, 0x6059, 0x6063, 0x60AB, 0x6106, 0x610D, 0x615D, + 0x61A9, 0x619D, 0x61CB, 0x61D1, 0x6206, 0x8080, 0x807F, 0x6C93, 0x6CF6, + 0x6DFC, 0x77F6, 0x77F8, 0x7800, 0x7809, 0x7817, 0x7818, 0x7811, 0x65AB, + 0x782D, 0x781C, 0x781D, 0x7839, 0x783A, 0x783B, 0x781F, 0x783C, 0x7825, + 0x782C, 0x7823, 0x7829, 0x784E, 0x786D, 0x7856, 0x7857, 0x7826, 0x7850, + 0x7847, 0x784C, 0x786A, 0x789B, 0x7893, 0x789A, 0x7887, 0x789C, 0x78A1, + 0x78A3, 0x78B2, 0x78B9, 0x78A5, 0x78D4, 0x78D9, 0x78C9, 0x78EC, 0x78F2, + 0x7905, 0x78F4, 0x7913, 0x7924, 0x791E, 0x7934, 0x9F9B, 0x9EF9, 0x9EFB, + 0x9EFC, 0x76F1, 0x7704, 0x770D, 0x76F9, 0x7707, 0x7708, 0x771A, 0x7722, + 0x7719, 0x772D, 0x7726, 0x7735, 0x7738, 0x7750, 0x7751, 0x7747, 0x7743, + 0x775A, 0x7768, 0, 0x980F, 0x9810, 0x9811, 0x9812, 0x9813, 0x9814, + 0x9815, 0x9816, 0x9817, 0x9818, 0x9819, 0x981A, 0x981B, 0x981C, 0x981D, + 0x981E, 0x981F, 0x9820, 0x9821, 0x9822, 0x9823, 0x9824, 0x9825, 0x9826, + 0x9827, 0x9828, 0x9829, 0x982A, 0x982B, 0x982C, 0x982D, 0x982E, 0x982F, + 0x9830, 0x9831, 0x9832, 0x9833, 0x9834, 0x9835, 0x9836, 0x9837, 0x9838, + 0x9839, 0x983A, 0x983B, 0x983C, 0x983D, 0x983E, 0x983F, 0x9840, 0x9841, + 0x9842, 0x9843, 0x9844, 0x9845, 0x9846, 0x9847, 0x9848, 0x9849, 0x984A, + 0x984B, 0x984C, 0x984D, 0, 0x984E, 0x984F, 0x9850, 0x9851, 0x9852, + 0x9853, 0x9854, 0x9855, 0x9856, 0x9857, 0x9858, 0x9859, 0x985A, 0x985B, + 0x985C, 0x985D, 0x985E, 0x985F, 0x9860, 0x9861, 0x9862, 0x9863, 0x9864, + 0x9865, 0x9866, 0x9867, 0x9868, 0x9869, 0x986A, 0x986B, 0x986C, 0x986D, + 0x986E, 0x7762, 0x7765, 0x777F, 0x778D, 0x777D, 0x7780, 0x778C, 0x7791, + 0x779F, 0x77A0, 0x77B0, 0x77B5, 0x77BD, 0x753A, 0x7540, 0x754E, 0x754B, + 0x7548, 0x755B, 0x7572, 0x7579, 0x7583, 0x7F58, 0x7F61, 0x7F5F, 0x8A48, + 0x7F68, 0x7F74, 0x7F71, 0x7F79, 0x7F81, 0x7F7E, 0x76CD, 0x76E5, 0x8832, + 0x9485, 0x9486, 0x9487, 0x948B, 0x948A, 0x948C, 0x948D, 0x948F, 0x9490, + 0x9494, 0x9497, 0x9495, 0x949A, 0x949B, 0x949C, 0x94A3, 0x94A4, 0x94AB, + 0x94AA, 0x94AD, 0x94AC, 0x94AF, 0x94B0, 0x94B2, 0x94B4, 0x94B6, 0x94B7, + 0x94B8, 0x94B9, 0x94BA, 0x94BC, 0x94BD, 0x94BF, 0x94C4, 0x94C8, 0x94C9, + 0x94CA, 0x94CB, 0x94CC, 0x94CD, 0x94CE, 0x94D0, 0x94D1, 0x94D2, 0x94D5, + 0x94D6, 0x94D7, 0x94D9, 0x94D8, 0x94DB, 0x94DE, 0x94DF, 0x94E0, 0x94E2, + 0x94E4, 0x94E5, 0x94E7, 0x94E8, 0x94EA, 0, 0x986F, 0x9870, 0x9871, + 0x9872, 0x9873, 0x9874, 0x988B, 0x988E, 0x9892, 0x9895, 0x9899, 0x98A3, + 0x98A8, 0x98A9, 0x98AA, 0x98AB, 0x98AC, 0x98AD, 0x98AE, 0x98AF, 0x98B0, + 0x98B1, 0x98B2, 0x98B3, 0x98B4, 0x98B5, 0x98B6, 0x98B7, 0x98B8, 0x98B9, + 0x98BA, 0x98BB, 0x98BC, 0x98BD, 0x98BE, 0x98BF, 0x98C0, 0x98C1, 0x98C2, + 0x98C3, 0x98C4, 0x98C5, 0x98C6, 0x98C7, 0x98C8, 0x98C9, 0x98CA, 0x98CB, + 0x98CC, 0x98CD, 0x98CF, 0x98D0, 0x98D4, 0x98D6, 0x98D7, 0x98DB, 0x98DC, + 0x98DD, 0x98E0, 0x98E1, 0x98E2, 0x98E3, 0x98E4, 0, 0x98E5, 0x98E6, + 0x98E9, 0x98EA, 0x98EB, 0x98EC, 0x98ED, 0x98EE, 0x98EF, 0x98F0, 0x98F1, + 0x98F2, 0x98F3, 0x98F4, 0x98F5, 0x98F6, 0x98F7, 0x98F8, 0x98F9, 0x98FA, + 0x98FB, 0x98FC, 0x98FD, 0x98FE, 0x98FF, 0x9900, 0x9901, 0x9902, 0x9903, + 0x9904, 0x9905, 0x9906, 0x9907, 0x94E9, 0x94EB, 0x94EE, 0x94EF, 0x94F3, + 0x94F4, 0x94F5, 0x94F7, 0x94F9, 0x94FC, 0x94FD, 0x94FF, 0x9503, 0x9502, + 0x9506, 0x9507, 0x9509, 0x950A, 0x950D, 0x950E, 0x950F, 0x9512, 0x9513, + 0x9514, 0x9515, 0x9516, 0x9518, 0x951B, 0x951D, 0x951E, 0x951F, 0x9522, + 0x952A, 0x952B, 0x9529, 0x952C, 0x9531, 0x9532, 0x9534, 0x9536, 0x9537, + 0x9538, 0x953C, 0x953E, 0x953F, 0x9542, 0x9535, 0x9544, 0x9545, 0x9546, + 0x9549, 0x954C, 0x954E, 0x954F, 0x9552, 0x9553, 0x9554, 0x9556, 0x9557, + 0x9558, 0x9559, 0x955B, 0x955E, 0x955F, 0x955D, 0x9561, 0x9562, 0x9564, + 0x9565, 0x9566, 0x9567, 0x9568, 0x9569, 0x956A, 0x956B, 0x956C, 0x956F, + 0x9571, 0x9572, 0x9573, 0x953A, 0x77E7, 0x77EC, 0x96C9, 0x79D5, 0x79ED, + 0x79E3, 0x79EB, 0x7A06, 0x5D47, 0x7A03, 0x7A02, 0x7A1E, 0x7A14, 0, + 0x9908, 0x9909, 0x990A, 0x990B, 0x990C, 0x990E, 0x990F, 0x9911, 0x9912, + 0x9913, 0x9914, 0x9915, 0x9916, 0x9917, 0x9918, 0x9919, 0x991A, 0x991B, + 0x991C, 0x991D, 0x991E, 0x991F, 0x9920, 0x9921, 0x9922, 0x9923, 0x9924, + 0x9925, 0x9926, 0x9927, 0x9928, 0x9929, 0x992A, 0x992B, 0x992C, 0x992D, + 0x992F, 0x9930, 0x9931, 0x9932, 0x9933, 0x9934, 0x9935, 0x9936, 0x9937, + 0x9938, 0x9939, 0x993A, 0x993B, 0x993C, 0x993D, 0x993E, 0x993F, 0x9940, + 0x9941, 0x9942, 0x9943, 0x9944, 0x9945, 0x9946, 0x9947, 0x9948, 0x9949, + 0, 0x994A, 0x994B, 0x994C, 0x994D, 0x994E, 0x994F, 0x9950, 0x9951, + 0x9952, 0x9953, 0x9956, 0x9957, 0x9958, 0x9959, 0x995A, 0x995B, 0x995C, + 0x995D, 0x995E, 0x995F, 0x9960, 0x9961, 0x9962, 0x9964, 0x9966, 0x9973, + 0x9978, 0x9979, 0x997B, 0x997E, 0x9982, 0x9983, 0x9989, 0x7A39, 0x7A37, + 0x7A51, 0x9ECF, 0x99A5, 0x7A70, 0x7688, 0x768E, 0x7693, 0x7699, 0x76A4, + 0x74DE, 0x74E0, 0x752C, 0x9E20, 0x9E22, 0x9E28, 0x9E29, 0x9E2A, 0x9E2B, + 0x9E2C, 0x9E32, 0x9E31, 0x9E36, 0x9E38, 0x9E37, 0x9E39, 0x9E3A, 0x9E3E, + 0x9E41, 0x9E42, 0x9E44, 0x9E46, 0x9E47, 0x9E48, 0x9E49, 0x9E4B, 0x9E4C, + 0x9E4E, 0x9E51, 0x9E55, 0x9E57, 0x9E5A, 0x9E5B, 0x9E5C, 0x9E5E, 0x9E63, + 0x9E66, 0x9E67, 0x9E68, 0x9E69, 0x9E6A, 0x9E6B, 0x9E6C, 0x9E71, 0x9E6D, + 0x9E73, 0x7592, 0x7594, 0x7596, 0x75A0, 0x759D, 0x75AC, 0x75A3, 0x75B3, + 0x75B4, 0x75B8, 0x75C4, 0x75B1, 0x75B0, 0x75C3, 0x75C2, 0x75D6, 0x75CD, + 0x75E3, 0x75E8, 0x75E6, 0x75E4, 0x75EB, 0x75E7, 0x7603, 0x75F1, 0x75FC, + 0x75FF, 0x7610, 0x7600, 0x7605, 0x760C, 0x7617, 0x760A, 0x7625, 0x7618, + 0x7615, 0x7619, 0, 0x998C, 0x998E, 0x999A, 0x999B, 0x999C, 0x999D, + 0x999E, 0x999F, 0x99A0, 0x99A1, 0x99A2, 0x99A3, 0x99A4, 0x99A6, 0x99A7, + 0x99A9, 0x99AA, 0x99AB, 0x99AC, 0x99AD, 0x99AE, 0x99AF, 0x99B0, 0x99B1, + 0x99B2, 0x99B3, 0x99B4, 0x99B5, 0x99B6, 0x99B7, 0x99B8, 0x99B9, 0x99BA, + 0x99BB, 0x99BC, 0x99BD, 0x99BE, 0x99BF, 0x99C0, 0x99C1, 0x99C2, 0x99C3, + 0x99C4, 0x99C5, 0x99C6, 0x99C7, 0x99C8, 0x99C9, 0x99CA, 0x99CB, 0x99CC, + 0x99CD, 0x99CE, 0x99CF, 0x99D0, 0x99D1, 0x99D2, 0x99D3, 0x99D4, 0x99D5, + 0x99D6, 0x99D7, 0x99D8, 0, 0x99D9, 0x99DA, 0x99DB, 0x99DC, 0x99DD, + 0x99DE, 0x99DF, 0x99E0, 0x99E1, 0x99E2, 0x99E3, 0x99E4, 0x99E5, 0x99E6, + 0x99E7, 0x99E8, 0x99E9, 0x99EA, 0x99EB, 0x99EC, 0x99ED, 0x99EE, 0x99EF, + 0x99F0, 0x99F1, 0x99F2, 0x99F3, 0x99F4, 0x99F5, 0x99F6, 0x99F7, 0x99F8, + 0x99F9, 0x761B, 0x763C, 0x7622, 0x7620, 0x7640, 0x762D, 0x7630, 0x763F, + 0x7635, 0x7643, 0x763E, 0x7633, 0x764D, 0x765E, 0x7654, 0x765C, 0x7656, + 0x766B, 0x766F, 0x7FCA, 0x7AE6, 0x7A78, 0x7A79, 0x7A80, 0x7A86, 0x7A88, + 0x7A95, 0x7AA6, 0x7AA0, 0x7AAC, 0x7AA8, 0x7AAD, 0x7AB3, 0x8864, 0x8869, + 0x8872, 0x887D, 0x887F, 0x8882, 0x88A2, 0x88C6, 0x88B7, 0x88BC, 0x88C9, + 0x88E2, 0x88CE, 0x88E3, 0x88E5, 0x88F1, 0x891A, 0x88FC, 0x88E8, 0x88FE, + 0x88F0, 0x8921, 0x8919, 0x8913, 0x891B, 0x890A, 0x8934, 0x892B, 0x8936, + 0x8941, 0x8966, 0x897B, 0x758B, 0x80E5, 0x76B2, 0x76B4, 0x77DC, 0x8012, + 0x8014, 0x8016, 0x801C, 0x8020, 0x8022, 0x8025, 0x8026, 0x8027, 0x8029, + 0x8028, 0x8031, 0x800B, 0x8035, 0x8043, 0x8046, 0x804D, 0x8052, 0x8069, + 0x8071, 0x8983, 0x9878, 0x9880, 0x9883, 0, 0x99FA, 0x99FB, 0x99FC, + 0x99FD, 0x99FE, 0x99FF, 0x9A00, 0x9A01, 0x9A02, 0x9A03, 0x9A04, 0x9A05, + 0x9A06, 0x9A07, 0x9A08, 0x9A09, 0x9A0A, 0x9A0B, 0x9A0C, 0x9A0D, 0x9A0E, + 0x9A0F, 0x9A10, 0x9A11, 0x9A12, 0x9A13, 0x9A14, 0x9A15, 0x9A16, 0x9A17, + 0x9A18, 0x9A19, 0x9A1A, 0x9A1B, 0x9A1C, 0x9A1D, 0x9A1E, 0x9A1F, 0x9A20, + 0x9A21, 0x9A22, 0x9A23, 0x9A24, 0x9A25, 0x9A26, 0x9A27, 0x9A28, 0x9A29, + 0x9A2A, 0x9A2B, 0x9A2C, 0x9A2D, 0x9A2E, 0x9A2F, 0x9A30, 0x9A31, 0x9A32, + 0x9A33, 0x9A34, 0x9A35, 0x9A36, 0x9A37, 0x9A38, 0, 0x9A39, 0x9A3A, + 0x9A3B, 0x9A3C, 0x9A3D, 0x9A3E, 0x9A3F, 0x9A40, 0x9A41, 0x9A42, 0x9A43, + 0x9A44, 0x9A45, 0x9A46, 0x9A47, 0x9A48, 0x9A49, 0x9A4A, 0x9A4B, 0x9A4C, + 0x9A4D, 0x9A4E, 0x9A4F, 0x9A50, 0x9A51, 0x9A52, 0x9A53, 0x9A54, 0x9A55, + 0x9A56, 0x9A57, 0x9A58, 0x9A59, 0x9889, 0x988C, 0x988D, 0x988F, 0x9894, + 0x989A, 0x989B, 0x989E, 0x989F, 0x98A1, 0x98A2, 0x98A5, 0x98A6, 0x864D, + 0x8654, 0x866C, 0x866E, 0x867F, 0x867A, 0x867C, 0x867B, 0x86A8, 0x868D, + 0x868B, 0x86AC, 0x869D, 0x86A7, 0x86A3, 0x86AA, 0x8693, 0x86A9, 0x86B6, + 0x86C4, 0x86B5, 0x86CE, 0x86B0, 0x86BA, 0x86B1, 0x86AF, 0x86C9, 0x86CF, + 0x86B4, 0x86E9, 0x86F1, 0x86F2, 0x86ED, 0x86F3, 0x86D0, 0x8713, 0x86DE, + 0x86F4, 0x86DF, 0x86D8, 0x86D1, 0x8703, 0x8707, 0x86F8, 0x8708, 0x870A, + 0x870D, 0x8709, 0x8723, 0x873B, 0x871E, 0x8725, 0x872E, 0x871A, 0x873E, + 0x8748, 0x8734, 0x8731, 0x8729, 0x8737, 0x873F, 0x8782, 0x8722, 0x877D, + 0x877E, 0x877B, 0x8760, 0x8770, 0x874C, 0x876E, 0x878B, 0x8753, 0x8763, + 0x877C, 0x8764, 0x8759, 0x8765, 0x8793, 0x87AF, 0x87A8, 0x87D2, 0, + 0x9A5A, 0x9A5B, 0x9A5C, 0x9A5D, 0x9A5E, 0x9A5F, 0x9A60, 0x9A61, 0x9A62, + 0x9A63, 0x9A64, 0x9A65, 0x9A66, 0x9A67, 0x9A68, 0x9A69, 0x9A6A, 0x9A6B, + 0x9A72, 0x9A83, 0x9A89, 0x9A8D, 0x9A8E, 0x9A94, 0x9A95, 0x9A99, 0x9AA6, + 0x9AA9, 0x9AAA, 0x9AAB, 0x9AAC, 0x9AAD, 0x9AAE, 0x9AAF, 0x9AB2, 0x9AB3, + 0x9AB4, 0x9AB5, 0x9AB9, 0x9ABB, 0x9ABD, 0x9ABE, 0x9ABF, 0x9AC3, 0x9AC4, + 0x9AC6, 0x9AC7, 0x9AC8, 0x9AC9, 0x9ACA, 0x9ACD, 0x9ACE, 0x9ACF, 0x9AD0, + 0x9AD2, 0x9AD4, 0x9AD5, 0x9AD6, 0x9AD7, 0x9AD9, 0x9ADA, 0x9ADB, 0x9ADC, + 0, 0x9ADD, 0x9ADE, 0x9AE0, 0x9AE2, 0x9AE3, 0x9AE4, 0x9AE5, 0x9AE7, + 0x9AE8, 0x9AE9, 0x9AEA, 0x9AEC, 0x9AEE, 0x9AF0, 0x9AF1, 0x9AF2, 0x9AF3, + 0x9AF4, 0x9AF5, 0x9AF6, 0x9AF7, 0x9AF8, 0x9AFA, 0x9AFC, 0x9AFD, 0x9AFE, + 0x9AFF, 0x9B00, 0x9B01, 0x9B02, 0x9B04, 0x9B05, 0x9B06, 0x87C6, 0x8788, + 0x8785, 0x87AD, 0x8797, 0x8783, 0x87AB, 0x87E5, 0x87AC, 0x87B5, 0x87B3, + 0x87CB, 0x87D3, 0x87BD, 0x87D1, 0x87C0, 0x87CA, 0x87DB, 0x87EA, 0x87E0, + 0x87EE, 0x8816, 0x8813, 0x87FE, 0x880A, 0x881B, 0x8821, 0x8839, 0x883C, + 0x7F36, 0x7F42, 0x7F44, 0x7F45, 0x8210, 0x7AFA, 0x7AFD, 0x7B08, 0x7B03, + 0x7B04, 0x7B15, 0x7B0A, 0x7B2B, 0x7B0F, 0x7B47, 0x7B38, 0x7B2A, 0x7B19, + 0x7B2E, 0x7B31, 0x7B20, 0x7B25, 0x7B24, 0x7B33, 0x7B3E, 0x7B1E, 0x7B58, + 0x7B5A, 0x7B45, 0x7B75, 0x7B4C, 0x7B5D, 0x7B60, 0x7B6E, 0x7B7B, 0x7B62, + 0x7B72, 0x7B71, 0x7B90, 0x7BA6, 0x7BA7, 0x7BB8, 0x7BAC, 0x7B9D, 0x7BA8, + 0x7B85, 0x7BAA, 0x7B9C, 0x7BA2, 0x7BAB, 0x7BB4, 0x7BD1, 0x7BC1, 0x7BCC, + 0x7BDD, 0x7BDA, 0x7BE5, 0x7BE6, 0x7BEA, 0x7C0C, 0x7BFE, 0x7BFC, 0x7C0F, + 0x7C16, 0x7C0B, 0, 0x9B07, 0x9B09, 0x9B0A, 0x9B0B, 0x9B0C, 0x9B0D, + 0x9B0E, 0x9B10, 0x9B11, 0x9B12, 0x9B14, 0x9B15, 0x9B16, 0x9B17, 0x9B18, + 0x9B19, 0x9B1A, 0x9B1B, 0x9B1C, 0x9B1D, 0x9B1E, 0x9B20, 0x9B21, 0x9B22, + 0x9B24, 0x9B25, 0x9B26, 0x9B27, 0x9B28, 0x9B29, 0x9B2A, 0x9B2B, 0x9B2C, + 0x9B2D, 0x9B2E, 0x9B30, 0x9B31, 0x9B33, 0x9B34, 0x9B35, 0x9B36, 0x9B37, + 0x9B38, 0x9B39, 0x9B3A, 0x9B3D, 0x9B3E, 0x9B3F, 0x9B40, 0x9B46, 0x9B4A, + 0x9B4B, 0x9B4C, 0x9B4E, 0x9B50, 0x9B52, 0x9B53, 0x9B55, 0x9B56, 0x9B57, + 0x9B58, 0x9B59, 0x9B5A, 0, 0x9B5B, 0x9B5C, 0x9B5D, 0x9B5E, 0x9B5F, + 0x9B60, 0x9B61, 0x9B62, 0x9B63, 0x9B64, 0x9B65, 0x9B66, 0x9B67, 0x9B68, + 0x9B69, 0x9B6A, 0x9B6B, 0x9B6C, 0x9B6D, 0x9B6E, 0x9B6F, 0x9B70, 0x9B71, + 0x9B72, 0x9B73, 0x9B74, 0x9B75, 0x9B76, 0x9B77, 0x9B78, 0x9B79, 0x9B7A, + 0x9B7B, 0x7C1F, 0x7C2A, 0x7C26, 0x7C38, 0x7C41, 0x7C40, 0x81FE, 0x8201, + 0x8202, 0x8204, 0x81EC, 0x8844, 0x8221, 0x8222, 0x8223, 0x822D, 0x822F, + 0x8228, 0x822B, 0x8238, 0x823B, 0x8233, 0x8234, 0x823E, 0x8244, 0x8249, + 0x824B, 0x824F, 0x825A, 0x825F, 0x8268, 0x887E, 0x8885, 0x8888, 0x88D8, + 0x88DF, 0x895E, 0x7F9D, 0x7F9F, 0x7FA7, 0x7FAF, 0x7FB0, 0x7FB2, 0x7C7C, + 0x6549, 0x7C91, 0x7C9D, 0x7C9C, 0x7C9E, 0x7CA2, 0x7CB2, 0x7CBC, 0x7CBD, + 0x7CC1, 0x7CC7, 0x7CCC, 0x7CCD, 0x7CC8, 0x7CC5, 0x7CD7, 0x7CE8, 0x826E, + 0x66A8, 0x7FBF, 0x7FCE, 0x7FD5, 0x7FE5, 0x7FE1, 0x7FE6, 0x7FE9, 0x7FEE, + 0x7FF3, 0x7CF8, 0x7D77, 0x7DA6, 0x7DAE, 0x7E47, 0x7E9B, 0x9EB8, 0x9EB4, + 0x8D73, 0x8D84, 0x8D94, 0x8D91, 0x8DB1, 0x8D67, 0x8D6D, 0x8C47, 0x8C49, + 0x914A, 0x9150, 0x914E, 0x914F, 0x9164, 0, 0x9B7C, 0x9B7D, 0x9B7E, + 0x9B7F, 0x9B80, 0x9B81, 0x9B82, 0x9B83, 0x9B84, 0x9B85, 0x9B86, 0x9B87, + 0x9B88, 0x9B89, 0x9B8A, 0x9B8B, 0x9B8C, 0x9B8D, 0x9B8E, 0x9B8F, 0x9B90, + 0x9B91, 0x9B92, 0x9B93, 0x9B94, 0x9B95, 0x9B96, 0x9B97, 0x9B98, 0x9B99, + 0x9B9A, 0x9B9B, 0x9B9C, 0x9B9D, 0x9B9E, 0x9B9F, 0x9BA0, 0x9BA1, 0x9BA2, + 0x9BA3, 0x9BA4, 0x9BA5, 0x9BA6, 0x9BA7, 0x9BA8, 0x9BA9, 0x9BAA, 0x9BAB, + 0x9BAC, 0x9BAD, 0x9BAE, 0x9BAF, 0x9BB0, 0x9BB1, 0x9BB2, 0x9BB3, 0x9BB4, + 0x9BB5, 0x9BB6, 0x9BB7, 0x9BB8, 0x9BB9, 0x9BBA, 0, 0x9BBB, 0x9BBC, + 0x9BBD, 0x9BBE, 0x9BBF, 0x9BC0, 0x9BC1, 0x9BC2, 0x9BC3, 0x9BC4, 0x9BC5, + 0x9BC6, 0x9BC7, 0x9BC8, 0x9BC9, 0x9BCA, 0x9BCB, 0x9BCC, 0x9BCD, 0x9BCE, + 0x9BCF, 0x9BD0, 0x9BD1, 0x9BD2, 0x9BD3, 0x9BD4, 0x9BD5, 0x9BD6, 0x9BD7, + 0x9BD8, 0x9BD9, 0x9BDA, 0x9BDB, 0x9162, 0x9161, 0x9170, 0x9169, 0x916F, + 0x917D, 0x917E, 0x9172, 0x9174, 0x9179, 0x918C, 0x9185, 0x9190, 0x918D, + 0x9191, 0x91A2, 0x91A3, 0x91AA, 0x91AD, 0x91AE, 0x91AF, 0x91B5, 0x91B4, + 0x91BA, 0x8C55, 0x9E7E, 0x8DB8, 0x8DEB, 0x8E05, 0x8E59, 0x8E69, 0x8DB5, + 0x8DBF, 0x8DBC, 0x8DBA, 0x8DC4, 0x8DD6, 0x8DD7, 0x8DDA, 0x8DDE, 0x8DCE, + 0x8DCF, 0x8DDB, 0x8DC6, 0x8DEC, 0x8DF7, 0x8DF8, 0x8DE3, 0x8DF9, 0x8DFB, + 0x8DE4, 0x8E09, 0x8DFD, 0x8E14, 0x8E1D, 0x8E1F, 0x8E2C, 0x8E2E, 0x8E23, + 0x8E2F, 0x8E3A, 0x8E40, 0x8E39, 0x8E35, 0x8E3D, 0x8E31, 0x8E49, 0x8E41, + 0x8E42, 0x8E51, 0x8E52, 0x8E4A, 0x8E70, 0x8E76, 0x8E7C, 0x8E6F, 0x8E74, + 0x8E85, 0x8E8F, 0x8E94, 0x8E90, 0x8E9C, 0x8E9E, 0x8C78, 0x8C82, 0x8C8A, + 0x8C85, 0x8C98, 0x8C94, 0x659B, 0x89D6, 0x89DE, 0x89DA, 0x89DC, 0, + 0x9BDC, 0x9BDD, 0x9BDE, 0x9BDF, 0x9BE0, 0x9BE1, 0x9BE2, 0x9BE3, 0x9BE4, + 0x9BE5, 0x9BE6, 0x9BE7, 0x9BE8, 0x9BE9, 0x9BEA, 0x9BEB, 0x9BEC, 0x9BED, + 0x9BEE, 0x9BEF, 0x9BF0, 0x9BF1, 0x9BF2, 0x9BF3, 0x9BF4, 0x9BF5, 0x9BF6, + 0x9BF7, 0x9BF8, 0x9BF9, 0x9BFA, 0x9BFB, 0x9BFC, 0x9BFD, 0x9BFE, 0x9BFF, + 0x9C00, 0x9C01, 0x9C02, 0x9C03, 0x9C04, 0x9C05, 0x9C06, 0x9C07, 0x9C08, + 0x9C09, 0x9C0A, 0x9C0B, 0x9C0C, 0x9C0D, 0x9C0E, 0x9C0F, 0x9C10, 0x9C11, + 0x9C12, 0x9C13, 0x9C14, 0x9C15, 0x9C16, 0x9C17, 0x9C18, 0x9C19, 0x9C1A, + 0, 0x9C1B, 0x9C1C, 0x9C1D, 0x9C1E, 0x9C1F, 0x9C20, 0x9C21, 0x9C22, + 0x9C23, 0x9C24, 0x9C25, 0x9C26, 0x9C27, 0x9C28, 0x9C29, 0x9C2A, 0x9C2B, + 0x9C2C, 0x9C2D, 0x9C2E, 0x9C2F, 0x9C30, 0x9C31, 0x9C32, 0x9C33, 0x9C34, + 0x9C35, 0x9C36, 0x9C37, 0x9C38, 0x9C39, 0x9C3A, 0x9C3B, 0x89E5, 0x89EB, + 0x89EF, 0x8A3E, 0x8B26, 0x9753, 0x96E9, 0x96F3, 0x96EF, 0x9706, 0x9701, + 0x9708, 0x970F, 0x970E, 0x972A, 0x972D, 0x9730, 0x973E, 0x9F80, 0x9F83, + 0x9F85, 0x9F86, 0x9F87, 0x9F88, 0x9F89, 0x9F8A, 0x9F8C, 0x9EFE, 0x9F0B, + 0x9F0D, 0x96B9, 0x96BC, 0x96BD, 0x96CE, 0x96D2, 0x77BF, 0x96E0, 0x928E, + 0x92AE, 0x92C8, 0x933E, 0x936A, 0x93CA, 0x938F, 0x943E, 0x946B, 0x9C7F, + 0x9C82, 0x9C85, 0x9C86, 0x9C87, 0x9C88, 0x7A23, 0x9C8B, 0x9C8E, 0x9C90, + 0x9C91, 0x9C92, 0x9C94, 0x9C95, 0x9C9A, 0x9C9B, 0x9C9E, 0x9C9F, 0x9CA0, + 0x9CA1, 0x9CA2, 0x9CA3, 0x9CA5, 0x9CA6, 0x9CA7, 0x9CA8, 0x9CA9, 0x9CAB, + 0x9CAD, 0x9CAE, 0x9CB0, 0x9CB1, 0x9CB2, 0x9CB3, 0x9CB4, 0x9CB5, 0x9CB6, + 0x9CB7, 0x9CBA, 0x9CBB, 0x9CBC, 0x9CBD, 0x9CC4, 0x9CC5, 0x9CC6, 0x9CC7, + 0x9CCA, 0x9CCB, 0, 0x9C3C, 0x9C3D, 0x9C3E, 0x9C3F, 0x9C40, 0x9C41, + 0x9C42, 0x9C43, 0x9C44, 0x9C45, 0x9C46, 0x9C47, 0x9C48, 0x9C49, 0x9C4A, + 0x9C4B, 0x9C4C, 0x9C4D, 0x9C4E, 0x9C4F, 0x9C50, 0x9C51, 0x9C52, 0x9C53, + 0x9C54, 0x9C55, 0x9C56, 0x9C57, 0x9C58, 0x9C59, 0x9C5A, 0x9C5B, 0x9C5C, + 0x9C5D, 0x9C5E, 0x9C5F, 0x9C60, 0x9C61, 0x9C62, 0x9C63, 0x9C64, 0x9C65, + 0x9C66, 0x9C67, 0x9C68, 0x9C69, 0x9C6A, 0x9C6B, 0x9C6C, 0x9C6D, 0x9C6E, + 0x9C6F, 0x9C70, 0x9C71, 0x9C72, 0x9C73, 0x9C74, 0x9C75, 0x9C76, 0x9C77, + 0x9C78, 0x9C79, 0x9C7A, 0, 0x9C7B, 0x9C7D, 0x9C7E, 0x9C80, 0x9C83, + 0x9C84, 0x9C89, 0x9C8A, 0x9C8C, 0x9C8F, 0x9C93, 0x9C96, 0x9C97, 0x9C98, + 0x9C99, 0x9C9D, 0x9CAA, 0x9CAC, 0x9CAF, 0x9CB9, 0x9CBE, 0x9CBF, 0x9CC0, + 0x9CC1, 0x9CC2, 0x9CC8, 0x9CC9, 0x9CD1, 0x9CD2, 0x9CDA, 0x9CDB, 0x9CE0, + 0x9CE1, 0x9CCC, 0x9CCD, 0x9CCE, 0x9CCF, 0x9CD0, 0x9CD3, 0x9CD4, 0x9CD5, + 0x9CD7, 0x9CD8, 0x9CD9, 0x9CDC, 0x9CDD, 0x9CDF, 0x9CE2, 0x977C, 0x9785, + 0x9791, 0x9792, 0x9794, 0x97AF, 0x97AB, 0x97A3, 0x97B2, 0x97B4, 0x9AB1, + 0x9AB0, 0x9AB7, 0x9E58, 0x9AB6, 0x9ABA, 0x9ABC, 0x9AC1, 0x9AC0, 0x9AC5, + 0x9AC2, 0x9ACB, 0x9ACC, 0x9AD1, 0x9B45, 0x9B43, 0x9B47, 0x9B49, 0x9B48, + 0x9B4D, 0x9B51, 0x98E8, 0x990D, 0x992E, 0x9955, 0x9954, 0x9ADF, 0x9AE1, + 0x9AE6, 0x9AEF, 0x9AEB, 0x9AFB, 0x9AED, 0x9AF9, 0x9B08, 0x9B0F, 0x9B13, + 0x9B1F, 0x9B23, 0x9EBD, 0x9EBE, 0x7E3B, 0x9E82, 0x9E87, 0x9E88, 0x9E8B, + 0x9E92, 0x93D6, 0x9E9D, 0x9E9F, 0x9EDB, 0x9EDC, 0x9EDD, 0x9EE0, 0x9EDF, + 0x9EE2, 0x9EE9, 0x9EE7, 0x9EE5, 0x9EEA, 0x9EEF, 0x9F22, 0x9F2C, 0x9F2F, + 0x9F39, 0x9F37, 0x9F3D, 0x9F3E, 0x9F44, 0, 0x9CE3, 0x9CE4, 0x9CE5, + 0x9CE6, 0x9CE7, 0x9CE8, 0x9CE9, 0x9CEA, 0x9CEB, 0x9CEC, 0x9CED, 0x9CEE, + 0x9CEF, 0x9CF0, 0x9CF1, 0x9CF2, 0x9CF3, 0x9CF4, 0x9CF5, 0x9CF6, 0x9CF7, + 0x9CF8, 0x9CF9, 0x9CFA, 0x9CFB, 0x9CFC, 0x9CFD, 0x9CFE, 0x9CFF, 0x9D00, + 0x9D01, 0x9D02, 0x9D03, 0x9D04, 0x9D05, 0x9D06, 0x9D07, 0x9D08, 0x9D09, + 0x9D0A, 0x9D0B, 0x9D0C, 0x9D0D, 0x9D0E, 0x9D0F, 0x9D10, 0x9D11, 0x9D12, + 0x9D13, 0x9D14, 0x9D15, 0x9D16, 0x9D17, 0x9D18, 0x9D19, 0x9D1A, 0x9D1B, + 0x9D1C, 0x9D1D, 0x9D1E, 0x9D1F, 0x9D20, 0x9D21, 0, 0x9D22, 0x9D23, + 0x9D24, 0x9D25, 0x9D26, 0x9D27, 0x9D28, 0x9D29, 0x9D2A, 0x9D2B, 0x9D2C, + 0x9D2D, 0x9D2E, 0x9D2F, 0x9D30, 0x9D31, 0x9D32, 0x9D33, 0x9D34, 0x9D35, + 0x9D36, 0x9D37, 0x9D38, 0x9D39, 0x9D3A, 0x9D3B, 0x9D3C, 0x9D3D, 0x9D3E, + 0x9D3F, 0x9D40, 0x9D41, 0x9D42, 0xE234, 0xE235, 0xE236, 0xE237, 0xE238, + 0xE239, 0xE23A, 0xE23B, 0xE23C, 0xE23D, 0xE23E, 0xE23F, 0xE240, 0xE241, + 0xE242, 0xE243, 0xE244, 0xE245, 0xE246, 0xE247, 0xE248, 0xE249, 0xE24A, + 0xE24B, 0xE24C, 0xE24D, 0xE24E, 0xE24F, 0xE250, 0xE251, 0xE252, 0xE253, + 0xE254, 0xE255, 0xE256, 0xE257, 0xE258, 0xE259, 0xE25A, 0xE25B, 0xE25C, + 0xE25D, 0xE25E, 0xE25F, 0xE260, 0xE261, 0xE262, 0xE263, 0xE264, 0xE265, + 0xE266, 0xE267, 0xE268, 0xE269, 0xE26A, 0xE26B, 0xE26C, 0xE26D, 0xE26E, + 0xE26F, 0xE270, 0xE271, 0xE272, 0xE273, 0xE274, 0xE275, 0xE276, 0xE277, + 0xE278, 0xE279, 0xE27A, 0xE27B, 0xE27C, 0xE27D, 0xE27E, 0xE27F, 0xE280, + 0xE281, 0xE282, 0xE283, 0xE284, 0xE285, 0xE286, 0xE287, 0xE288, 0xE289, + 0xE28A, 0xE28B, 0xE28C, 0xE28D, 0xE28E, 0xE28F, 0xE290, 0xE291, 0, + 0x9D43, 0x9D44, 0x9D45, 0x9D46, 0x9D47, 0x9D48, 0x9D49, 0x9D4A, 0x9D4B, + 0x9D4C, 0x9D4D, 0x9D4E, 0x9D4F, 0x9D50, 0x9D51, 0x9D52, 0x9D53, 0x9D54, + 0x9D55, 0x9D56, 0x9D57, 0x9D58, 0x9D59, 0x9D5A, 0x9D5B, 0x9D5C, 0x9D5D, + 0x9D5E, 0x9D5F, 0x9D60, 0x9D61, 0x9D62, 0x9D63, 0x9D64, 0x9D65, 0x9D66, + 0x9D67, 0x9D68, 0x9D69, 0x9D6A, 0x9D6B, 0x9D6C, 0x9D6D, 0x9D6E, 0x9D6F, + 0x9D70, 0x9D71, 0x9D72, 0x9D73, 0x9D74, 0x9D75, 0x9D76, 0x9D77, 0x9D78, + 0x9D79, 0x9D7A, 0x9D7B, 0x9D7C, 0x9D7D, 0x9D7E, 0x9D7F, 0x9D80, 0x9D81, + 0, 0x9D82, 0x9D83, 0x9D84, 0x9D85, 0x9D86, 0x9D87, 0x9D88, 0x9D89, + 0x9D8A, 0x9D8B, 0x9D8C, 0x9D8D, 0x9D8E, 0x9D8F, 0x9D90, 0x9D91, 0x9D92, + 0x9D93, 0x9D94, 0x9D95, 0x9D96, 0x9D97, 0x9D98, 0x9D99, 0x9D9A, 0x9D9B, + 0x9D9C, 0x9D9D, 0x9D9E, 0x9D9F, 0x9DA0, 0x9DA1, 0x9DA2, 0xE292, 0xE293, + 0xE294, 0xE295, 0xE296, 0xE297, 0xE298, 0xE299, 0xE29A, 0xE29B, 0xE29C, + 0xE29D, 0xE29E, 0xE29F, 0xE2A0, 0xE2A1, 0xE2A2, 0xE2A3, 0xE2A4, 0xE2A5, + 0xE2A6, 0xE2A7, 0xE2A8, 0xE2A9, 0xE2AA, 0xE2AB, 0xE2AC, 0xE2AD, 0xE2AE, + 0xE2AF, 0xE2B0, 0xE2B1, 0xE2B2, 0xE2B3, 0xE2B4, 0xE2B5, 0xE2B6, 0xE2B7, + 0xE2B8, 0xE2B9, 0xE2BA, 0xE2BB, 0xE2BC, 0xE2BD, 0xE2BE, 0xE2BF, 0xE2C0, + 0xE2C1, 0xE2C2, 0xE2C3, 0xE2C4, 0xE2C5, 0xE2C6, 0xE2C7, 0xE2C8, 0xE2C9, + 0xE2CA, 0xE2CB, 0xE2CC, 0xE2CD, 0xE2CE, 0xE2CF, 0xE2D0, 0xE2D1, 0xE2D2, + 0xE2D3, 0xE2D4, 0xE2D5, 0xE2D6, 0xE2D7, 0xE2D8, 0xE2D9, 0xE2DA, 0xE2DB, + 0xE2DC, 0xE2DD, 0xE2DE, 0xE2DF, 0xE2E0, 0xE2E1, 0xE2E2, 0xE2E3, 0xE2E4, + 0xE2E5, 0xE2E6, 0xE2E7, 0xE2E8, 0xE2E9, 0xE2EA, 0xE2EB, 0xE2EC, 0xE2ED, + 0xE2EE, 0xE2EF, 0, 0x9DA3, 0x9DA4, 0x9DA5, 0x9DA6, 0x9DA7, 0x9DA8, + 0x9DA9, 0x9DAA, 0x9DAB, 0x9DAC, 0x9DAD, 0x9DAE, 0x9DAF, 0x9DB0, 0x9DB1, + 0x9DB2, 0x9DB3, 0x9DB4, 0x9DB5, 0x9DB6, 0x9DB7, 0x9DB8, 0x9DB9, 0x9DBA, + 0x9DBB, 0x9DBC, 0x9DBD, 0x9DBE, 0x9DBF, 0x9DC0, 0x9DC1, 0x9DC2, 0x9DC3, + 0x9DC4, 0x9DC5, 0x9DC6, 0x9DC7, 0x9DC8, 0x9DC9, 0x9DCA, 0x9DCB, 0x9DCC, + 0x9DCD, 0x9DCE, 0x9DCF, 0x9DD0, 0x9DD1, 0x9DD2, 0x9DD3, 0x9DD4, 0x9DD5, + 0x9DD6, 0x9DD7, 0x9DD8, 0x9DD9, 0x9DDA, 0x9DDB, 0x9DDC, 0x9DDD, 0x9DDE, + 0x9DDF, 0x9DE0, 0x9DE1, 0, 0x9DE2, 0x9DE3, 0x9DE4, 0x9DE5, 0x9DE6, + 0x9DE7, 0x9DE8, 0x9DE9, 0x9DEA, 0x9DEB, 0x9DEC, 0x9DED, 0x9DEE, 0x9DEF, + 0x9DF0, 0x9DF1, 0x9DF2, 0x9DF3, 0x9DF4, 0x9DF5, 0x9DF6, 0x9DF7, 0x9DF8, + 0x9DF9, 0x9DFA, 0x9DFB, 0x9DFC, 0x9DFD, 0x9DFE, 0x9DFF, 0x9E00, 0x9E01, + 0x9E02, 0xE2F0, 0xE2F1, 0xE2F2, 0xE2F3, 0xE2F4, 0xE2F5, 0xE2F6, 0xE2F7, + 0xE2F8, 0xE2F9, 0xE2FA, 0xE2FB, 0xE2FC, 0xE2FD, 0xE2FE, 0xE2FF, 0xE300, + 0xE301, 0xE302, 0xE303, 0xE304, 0xE305, 0xE306, 0xE307, 0xE308, 0xE309, + 0xE30A, 0xE30B, 0xE30C, 0xE30D, 0xE30E, 0xE30F, 0xE310, 0xE311, 0xE312, + 0xE313, 0xE314, 0xE315, 0xE316, 0xE317, 0xE318, 0xE319, 0xE31A, 0xE31B, + 0xE31C, 0xE31D, 0xE31E, 0xE31F, 0xE320, 0xE321, 0xE322, 0xE323, 0xE324, + 0xE325, 0xE326, 0xE327, 0xE328, 0xE329, 0xE32A, 0xE32B, 0xE32C, 0xE32D, + 0xE32E, 0xE32F, 0xE330, 0xE331, 0xE332, 0xE333, 0xE334, 0xE335, 0xE336, + 0xE337, 0xE338, 0xE339, 0xE33A, 0xE33B, 0xE33C, 0xE33D, 0xE33E, 0xE33F, + 0xE340, 0xE341, 0xE342, 0xE343, 0xE344, 0xE345, 0xE346, 0xE347, 0xE348, + 0xE349, 0xE34A, 0xE34B, 0xE34C, 0xE34D, 0, 0x9E03, 0x9E04, 0x9E05, + 0x9E06, 0x9E07, 0x9E08, 0x9E09, 0x9E0A, 0x9E0B, 0x9E0C, 0x9E0D, 0x9E0E, + 0x9E0F, 0x9E10, 0x9E11, 0x9E12, 0x9E13, 0x9E14, 0x9E15, 0x9E16, 0x9E17, + 0x9E18, 0x9E19, 0x9E1A, 0x9E1B, 0x9E1C, 0x9E1D, 0x9E1E, 0x9E24, 0x9E27, + 0x9E2E, 0x9E30, 0x9E34, 0x9E3B, 0x9E3C, 0x9E40, 0x9E4D, 0x9E50, 0x9E52, + 0x9E53, 0x9E54, 0x9E56, 0x9E59, 0x9E5D, 0x9E5F, 0x9E60, 0x9E61, 0x9E62, + 0x9E65, 0x9E6E, 0x9E6F, 0x9E72, 0x9E74, 0x9E75, 0x9E76, 0x9E77, 0x9E78, + 0x9E79, 0x9E7A, 0x9E7B, 0x9E7C, 0x9E7D, 0x9E80, 0, 0x9E81, 0x9E83, + 0x9E84, 0x9E85, 0x9E86, 0x9E89, 0x9E8A, 0x9E8C, 0x9E8D, 0x9E8E, 0x9E8F, + 0x9E90, 0x9E91, 0x9E94, 0x9E95, 0x9E96, 0x9E97, 0x9E98, 0x9E99, 0x9E9A, + 0x9E9B, 0x9E9C, 0x9E9E, 0x9EA0, 0x9EA1, 0x9EA2, 0x9EA3, 0x9EA4, 0x9EA5, + 0x9EA7, 0x9EA8, 0x9EA9, 0x9EAA, 0xE34E, 0xE34F, 0xE350, 0xE351, 0xE352, + 0xE353, 0xE354, 0xE355, 0xE356, 0xE357, 0xE358, 0xE359, 0xE35A, 0xE35B, + 0xE35C, 0xE35D, 0xE35E, 0xE35F, 0xE360, 0xE361, 0xE362, 0xE363, 0xE364, + 0xE365, 0xE366, 0xE367, 0xE368, 0xE369, 0xE36A, 0xE36B, 0xE36C, 0xE36D, + 0xE36E, 0xE36F, 0xE370, 0xE371, 0xE372, 0xE373, 0xE374, 0xE375, 0xE376, + 0xE377, 0xE378, 0xE379, 0xE37A, 0xE37B, 0xE37C, 0xE37D, 0xE37E, 0xE37F, + 0xE380, 0xE381, 0xE382, 0xE383, 0xE384, 0xE385, 0xE386, 0xE387, 0xE388, + 0xE389, 0xE38A, 0xE38B, 0xE38C, 0xE38D, 0xE38E, 0xE38F, 0xE390, 0xE391, + 0xE392, 0xE393, 0xE394, 0xE395, 0xE396, 0xE397, 0xE398, 0xE399, 0xE39A, + 0xE39B, 0xE39C, 0xE39D, 0xE39E, 0xE39F, 0xE3A0, 0xE3A1, 0xE3A2, 0xE3A3, + 0xE3A4, 0xE3A5, 0xE3A6, 0xE3A7, 0xE3A8, 0xE3A9, 0xE3AA, 0xE3AB, 0, + 0x9EAB, 0x9EAC, 0x9EAD, 0x9EAE, 0x9EAF, 0x9EB0, 0x9EB1, 0x9EB2, 0x9EB3, + 0x9EB5, 0x9EB6, 0x9EB7, 0x9EB9, 0x9EBA, 0x9EBC, 0x9EBF, 0x9EC0, 0x9EC1, + 0x9EC2, 0x9EC3, 0x9EC5, 0x9EC6, 0x9EC7, 0x9EC8, 0x9ECA, 0x9ECB, 0x9ECC, + 0x9ED0, 0x9ED2, 0x9ED3, 0x9ED5, 0x9ED6, 0x9ED7, 0x9ED9, 0x9EDA, 0x9EDE, + 0x9EE1, 0x9EE3, 0x9EE4, 0x9EE6, 0x9EE8, 0x9EEB, 0x9EEC, 0x9EED, 0x9EEE, + 0x9EF0, 0x9EF1, 0x9EF2, 0x9EF3, 0x9EF4, 0x9EF5, 0x9EF6, 0x9EF7, 0x9EF8, + 0x9EFA, 0x9EFD, 0x9EFF, 0x9F00, 0x9F01, 0x9F02, 0x9F03, 0x9F04, 0x9F05, + 0, 0x9F06, 0x9F07, 0x9F08, 0x9F09, 0x9F0A, 0x9F0C, 0x9F0F, 0x9F11, + 0x9F12, 0x9F14, 0x9F15, 0x9F16, 0x9F18, 0x9F1A, 0x9F1B, 0x9F1C, 0x9F1D, + 0x9F1E, 0x9F1F, 0x9F21, 0x9F23, 0x9F24, 0x9F25, 0x9F26, 0x9F27, 0x9F28, + 0x9F29, 0x9F2A, 0x9F2B, 0x9F2D, 0x9F2E, 0x9F30, 0x9F31, 0xE3AC, 0xE3AD, + 0xE3AE, 0xE3AF, 0xE3B0, 0xE3B1, 0xE3B2, 0xE3B3, 0xE3B4, 0xE3B5, 0xE3B6, + 0xE3B7, 0xE3B8, 0xE3B9, 0xE3BA, 0xE3BB, 0xE3BC, 0xE3BD, 0xE3BE, 0xE3BF, + 0xE3C0, 0xE3C1, 0xE3C2, 0xE3C3, 0xE3C4, 0xE3C5, 0xE3C6, 0xE3C7, 0xE3C8, + 0xE3C9, 0xE3CA, 0xE3CB, 0xE3CC, 0xE3CD, 0xE3CE, 0xE3CF, 0xE3D0, 0xE3D1, + 0xE3D2, 0xE3D3, 0xE3D4, 0xE3D5, 0xE3D6, 0xE3D7, 0xE3D8, 0xE3D9, 0xE3DA, + 0xE3DB, 0xE3DC, 0xE3DD, 0xE3DE, 0xE3DF, 0xE3E0, 0xE3E1, 0xE3E2, 0xE3E3, + 0xE3E4, 0xE3E5, 0xE3E6, 0xE3E7, 0xE3E8, 0xE3E9, 0xE3EA, 0xE3EB, 0xE3EC, + 0xE3ED, 0xE3EE, 0xE3EF, 0xE3F0, 0xE3F1, 0xE3F2, 0xE3F3, 0xE3F4, 0xE3F5, + 0xE3F6, 0xE3F7, 0xE3F8, 0xE3F9, 0xE3FA, 0xE3FB, 0xE3FC, 0xE3FD, 0xE3FE, + 0xE3FF, 0xE400, 0xE401, 0xE402, 0xE403, 0xE404, 0xE405, 0xE406, 0xE407, + 0xE408, 0xE409, 0, 0x9F32, 0x9F33, 0x9F34, 0x9F35, 0x9F36, 0x9F38, + 0x9F3A, 0x9F3C, 0x9F3F, 0x9F40, 0x9F41, 0x9F42, 0x9F43, 0x9F45, 0x9F46, + 0x9F47, 0x9F48, 0x9F49, 0x9F4A, 0x9F4B, 0x9F4C, 0x9F4D, 0x9F4E, 0x9F4F, + 0x9F52, 0x9F53, 0x9F54, 0x9F55, 0x9F56, 0x9F57, 0x9F58, 0x9F59, 0x9F5A, + 0x9F5B, 0x9F5C, 0x9F5D, 0x9F5E, 0x9F5F, 0x9F60, 0x9F61, 0x9F62, 0x9F63, + 0x9F64, 0x9F65, 0x9F66, 0x9F67, 0x9F68, 0x9F69, 0x9F6A, 0x9F6B, 0x9F6C, + 0x9F6D, 0x9F6E, 0x9F6F, 0x9F70, 0x9F71, 0x9F72, 0x9F73, 0x9F74, 0x9F75, + 0x9F76, 0x9F77, 0x9F78, 0, 0x9F79, 0x9F7A, 0x9F7B, 0x9F7C, 0x9F7D, + 0x9F7E, 0x9F81, 0x9F82, 0x9F8D, 0x9F8E, 0x9F8F, 0x9F90, 0x9F91, 0x9F92, + 0x9F93, 0x9F94, 0x9F95, 0x9F96, 0x9F97, 0x9F98, 0x9F9C, 0x9F9D, 0x9F9E, + 0x9FA1, 0x9FA2, 0x9FA3, 0x9FA4, 0x9FA5, 0xF92C, 0xF979, 0xF995, 0xF9E7, + 0xF9F1, 0xE40A, 0xE40B, 0xE40C, 0xE40D, 0xE40E, 0xE40F, 0xE410, 0xE411, + 0xE412, 0xE413, 0xE414, 0xE415, 0xE416, 0xE417, 0xE418, 0xE419, 0xE41A, + 0xE41B, 0xE41C, 0xE41D, 0xE41E, 0xE41F, 0xE420, 0xE421, 0xE422, 0xE423, + 0xE424, 0xE425, 0xE426, 0xE427, 0xE428, 0xE429, 0xE42A, 0xE42B, 0xE42C, + 0xE42D, 0xE42E, 0xE42F, 0xE430, 0xE431, 0xE432, 0xE433, 0xE434, 0xE435, + 0xE436, 0xE437, 0xE438, 0xE439, 0xE43A, 0xE43B, 0xE43C, 0xE43D, 0xE43E, + 0xE43F, 0xE440, 0xE441, 0xE442, 0xE443, 0xE444, 0xE445, 0xE446, 0xE447, + 0xE448, 0xE449, 0xE44A, 0xE44B, 0xE44C, 0xE44D, 0xE44E, 0xE44F, 0xE450, + 0xE451, 0xE452, 0xE453, 0xE454, 0xE455, 0xE456, 0xE457, 0xE458, 0xE459, + 0xE45A, 0xE45B, 0xE45C, 0xE45D, 0xE45E, 0xE45F, 0xE460, 0xE461, 0xE462, + 0xE463, 0xE464, 0xE465, 0xE466, 0xE467, 0, 0xFA0C, 0xFA0D, 0xFA0E, + 0xFA0F, 0xFA11, 0xFA13, 0xFA14, 0xFA18, 0xFA1F, 0xFA20, 0xFA21, 0xFA23, + 0xFA24, 0xFA27, 0xFA28, 0xFA29, 0x2E81, 0xE816, 0xE817, 0xE818, 0x2E84, + 0x3473, 0x3447, 0x2E88, 0x2E8B, 0xE81E, 0x359E, 0x361A, 0x360E, 0x2E8C, + 0x2E97, 0x396E, 0x3918, 0xE826, 0x39CF, 0x39DF, 0x3A73, 0x39D0, 0xE82B, + 0xE82C, 0x3B4E, 0x3C6E, 0x3CE0, 0x2EA7, 0xE831, 0xE832, 0x2EAA, 0x4056, + 0x415F, 0x2EAE, 0x4337, 0x2EB3, 0x2EB6, 0x2EB7, 0xE83B, 0x43B1, 0x43AC, + 0x2EBB, 0x43DD, 0x44D6, 0x4661, 0x464C, 0xE843, 0, 0x4723, 0x4729, + 0x477C, 0x478D, 0x2ECA, 0x4947, 0x497A, 0x497D, 0x4982, 0x4983, 0x4985, + 0x4986, 0x499F, 0x499B, 0x49B7, 0x49B6, 0xE854, 0xE855, 0x4CA3, 0x4C9F, + 0x4CA0, 0x4CA1, 0x4C77, 0x4CA2, 0x4D13, 0x4D14, 0x4D15, 0x4D16, 0x4D17, + 0x4D18, 0x4D19, 0x4DAE, 0xE864, 0xE468, 0xE469, 0xE46A, 0xE46B, 0xE46C, + 0xE46D, 0xE46E, 0xE46F, 0xE470, 0xE471, 0xE472, 0xE473, 0xE474, 0xE475, + 0xE476, 0xE477, 0xE478, 0xE479, 0xE47A, 0xE47B, 0xE47C, 0xE47D, 0xE47E, + 0xE47F, 0xE480, 0xE481, 0xE482, 0xE483, 0xE484, 0xE485, 0xE486, 0xE487, + 0xE488, 0xE489, 0xE48A, 0xE48B, 0xE48C, 0xE48D, 0xE48E, 0xE48F, 0xE490, + 0xE491, 0xE492, 0xE493, 0xE494, 0xE495, 0xE496, 0xE497, 0xE498, 0xE499, + 0xE49A, 0xE49B, 0xE49C, 0xE49D, 0xE49E, 0xE49F, 0xE4A0, 0xE4A1, 0xE4A2, + 0xE4A3, 0xE4A4, 0xE4A5, 0xE4A6, 0xE4A7, 0xE4A8, 0xE4A9, 0xE4AA, 0xE4AB, + 0xE4AC, 0xE4AD, 0xE4AE, 0xE4AF, 0xE4B0, 0xE4B1, 0xE4B2, 0xE4B3, 0xE4B4, + 0xE4B5, 0xE4B6, 0xE4B7, 0xE4B8, 0xE4B9, 0xE4BA, 0xE4BB, 0xE4BC, 0xE4BD, + 0xE4BE, 0xE4BF, 0xE4C0, 0xE4C1, 0xE4C2, 0xE4C3, 0xE4C4, 0xE4C5, 0}; + +static const uint16_t tab_gb18030_4_uni[] = { + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, + 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, 0x0090, 0x0091, + 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, + 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x00A1, 0x00A2, 0x00A3, + 0x00A5, 0x00A6, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B8, 0x00B9, 0x00BA, 0x00BB, + 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, + 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, + 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E2, + 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00EB, 0x00EE, 0x00EF, 0x00F0, + 0x00F1, 0x00F4, 0x00F5, 0x00F6, 0x00F8, 0x00FB, 0x00FD, 0x00FE, 0x00FF, + 0x0100, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, + 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, 0x010F, 0x0110, 0x0111, 0x0112, + 0x0114, 0x0115, 0x0116, 0x0117, 0x0118, 0x0119, 0x011A, 0x011C, 0x011D, + 0x011E, 0x011F, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126, + 0x0127, 0x0128, 0x0129, 0x012A, 0x012C, 0x012D, 0x012E, 0x012F, 0x0130, + 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136, 0x0137, 0x0138, 0x0139, + 0x013A, 0x013B, 0x013C, 0x013D, 0x013E, 0x013F, 0x0140, 0x0141, 0x0142, + 0x0143, 0x0145, 0x0146, 0x0147, 0x0149, 0x014A, 0x014B, 0x014C, 0x014E, + 0x014F, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155, 0x0156, 0x0157, + 0x0158, 0x0159, 0x015A, 0x015B, 0x015C, 0x015D, 0x015E, 0x015F, 0x0160, + 0x0161, 0x0162, 0x0163, 0x0164, 0x0165, 0x0166, 0x0167, 0x0168, 0x0169, + 0x016A, 0x016C, 0x016D, 0x016E, 0x016F, 0x0170, 0x0171, 0x0172, 0x0173, + 0x0174, 0x0175, 0x0176, 0x0177, 0x0178, 0x0179, 0x017A, 0x017B, 0x017C, + 0x017D, 0x017E, 0x017F, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185, + 0x0186, 0x0187, 0x0188, 0x0189, 0x018A, 0x018B, 0x018C, 0x018D, 0x018E, + 0x018F, 0x0190, 0x0191, 0x0192, 0x0193, 0x0194, 0x0195, 0x0196, 0x0197, + 0x0198, 0x0199, 0x019A, 0x019B, 0x019C, 0x019D, 0x019E, 0x019F, 0x01A0, + 0x01A1, 0x01A2, 0x01A3, 0x01A4, 0x01A5, 0x01A6, 0x01A7, 0x01A8, 0x01A9, + 0x01AA, 0x01AB, 0x01AC, 0x01AD, 0x01AE, 0x01AF, 0x01B0, 0x01B1, 0x01B2, + 0x01B3, 0x01B4, 0x01B5, 0x01B6, 0x01B7, 0x01B8, 0x01B9, 0x01BA, 0x01BB, + 0x01BC, 0x01BD, 0x01BE, 0x01BF, 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, + 0x01C5, 0x01C6, 0x01C7, 0x01C8, 0x01C9, 0x01CA, 0x01CB, 0x01CC, 0x01CD, + 0x01CF, 0x01D1, 0x01D3, 0x01D5, 0x01D7, 0x01D9, 0x01DB, 0x01DD, 0x01DE, + 0x01DF, 0x01E0, 0x01E1, 0x01E2, 0x01E3, 0x01E4, 0x01E5, 0x01E6, 0x01E7, + 0x01E8, 0x01E9, 0x01EA, 0x01EB, 0x01EC, 0x01ED, 0x01EE, 0x01EF, 0x01F0, + 0x01F1, 0x01F2, 0x01F3, 0x01F4, 0x01F5, 0x01F6, 0x01F7, 0x01F8, 0x01FA, + 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF, 0x0200, 0x0201, 0x0202, 0x0203, + 0x0204, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209, 0x020A, 0x020B, 0x020C, + 0x020D, 0x020E, 0x020F, 0x0210, 0x0211, 0x0212, 0x0213, 0x0214, 0x0215, + 0x0216, 0x0217, 0x0218, 0x0219, 0x021A, 0x021B, 0x021C, 0x021D, 0x021E, + 0x021F, 0x0220, 0x0221, 0x0222, 0x0223, 0x0224, 0x0225, 0x0226, 0x0227, + 0x0228, 0x0229, 0x022A, 0x022B, 0x022C, 0x022D, 0x022E, 0x022F, 0x0230, + 0x0231, 0x0232, 0x0233, 0x0234, 0x0235, 0x0236, 0x0237, 0x0238, 0x0239, + 0x023A, 0x023B, 0x023C, 0x023D, 0x023E, 0x023F, 0x0240, 0x0241, 0x0242, + 0x0243, 0x0244, 0x0245, 0x0246, 0x0247, 0x0248, 0x0249, 0x024A, 0x024B, + 0x024C, 0x024D, 0x024E, 0x024F, 0x0250, 0x0252, 0x0253, 0x0254, 0x0255, + 0x0256, 0x0257, 0x0258, 0x0259, 0x025A, 0x025B, 0x025C, 0x025D, 0x025E, + 0x025F, 0x0260, 0x0262, 0x0263, 0x0264, 0x0265, 0x0266, 0x0267, 0x0268, + 0x0269, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x026F, 0x0270, 0x0271, + 0x0272, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277, 0x0278, 0x0279, 0x027A, + 0x027B, 0x027C, 0x027D, 0x027E, 0x027F, 0x0280, 0x0281, 0x0282, 0x0283, + 0x0284, 0x0285, 0x0286, 0x0287, 0x0288, 0x0289, 0x028A, 0x028B, 0x028C, + 0x028D, 0x028E, 0x028F, 0x0290, 0x0291, 0x0292, 0x0293, 0x0294, 0x0295, + 0x0296, 0x0297, 0x0298, 0x0299, 0x029A, 0x029B, 0x029C, 0x029D, 0x029E, + 0x029F, 0x02A0, 0x02A1, 0x02A2, 0x02A3, 0x02A4, 0x02A5, 0x02A6, 0x02A7, + 0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x02AC, 0x02AD, 0x02AE, 0x02AF, 0x02B0, + 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6, 0x02B7, 0x02B8, 0x02B9, + 0x02BA, 0x02BB, 0x02BC, 0x02BD, 0x02BE, 0x02BF, 0x02C0, 0x02C1, 0x02C2, + 0x02C3, 0x02C4, 0x02C5, 0x02C6, 0x02C8, 0x02CC, 0x02CD, 0x02CE, 0x02CF, + 0x02D0, 0x02D1, 0x02D2, 0x02D3, 0x02D4, 0x02D5, 0x02D6, 0x02D7, 0x02D8, + 0x02DA, 0x02DB, 0x02DC, 0x02DD, 0x02DE, 0x02DF, 0x02E0, 0x02E1, 0x02E2, + 0x02E3, 0x02E4, 0x02E5, 0x02E6, 0x02E7, 0x02E8, 0x02E9, 0x02EA, 0x02EB, + 0x02EC, 0x02ED, 0x02EE, 0x02EF, 0x02F0, 0x02F1, 0x02F2, 0x02F3, 0x02F4, + 0x02F5, 0x02F6, 0x02F7, 0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, 0x02FD, + 0x02FE, 0x02FF, 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, + 0x0307, 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F, + 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, 0x0318, + 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F, 0x0320, 0x0321, + 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, 0x0328, 0x0329, 0x032A, + 0x032B, 0x032C, 0x032D, 0x032E, 0x032F, 0x0330, 0x0331, 0x0332, 0x0333, + 0x0334, 0x0335, 0x0336, 0x0337, 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, + 0x033D, 0x033E, 0x033F, 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, + 0x0346, 0x0347, 0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, + 0x034F, 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, + 0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F, 0x0360, + 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, 0x0368, 0x0369, + 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F, 0x0370, 0x0371, 0x0372, + 0x0373, 0x0374, 0x0375, 0x0376, 0x0377, 0x0378, 0x0379, 0x037A, 0x037B, + 0x037C, 0x037D, 0x037E, 0x037F, 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, + 0x0385, 0x0386, 0x0387, 0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, + 0x038E, 0x038F, 0x0390, 0x03A2, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, + 0x03AF, 0x03B0, 0x03C2, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03CF, + 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7, 0x03D8, + 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF, 0x03E0, 0x03E1, + 0x03E2, 0x03E3, 0x03E4, 0x03E5, 0x03E6, 0x03E7, 0x03E8, 0x03E9, 0x03EA, + 0x03EB, 0x03EC, 0x03ED, 0x03EE, 0x03EF, 0x03F0, 0x03F1, 0x03F2, 0x03F3, + 0x03F4, 0x03F5, 0x03F6, 0x03F7, 0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, + 0x03FD, 0x03FE, 0x03FF, 0x0400, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, + 0x0407, 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040D, 0x040E, 0x040F, + 0x0450, 0xE7C7, 0x1E40, 0x1E41, 0x1E42, 0x1E43, 0x1E44, 0x1E45, 0x1E46, + 0x1E47, 0x1E48, 0x1E49, 0x1E4A, 0x1E4B, 0x1E4C, 0x1E4D, 0x1E4E, 0x1E4F, + 0x1E50, 0x1E51, 0x1E52, 0x1E53, 0x1E54, 0x1E55, 0x1E56, 0x1E57, 0x1E58, + 0x1E59, 0x1E5A, 0x1E5B, 0x1E5C, 0x1E5D, 0x1E5E, 0x1E5F, 0x1E60, 0x1E61, + 0x1E62, 0x1E63, 0x1E64, 0x1E65, 0x1E66, 0x1E67, 0x1E68, 0x1E69, 0x1E6A, + 0x1E6B, 0x1E6C, 0x1E6D, 0x1E6E, 0x1E6F, 0x1E70, 0x1E71, 0x1E72, 0x1E73, + 0x1E74, 0x1E75, 0x1E76, 0x1E77, 0x1E78, 0x1E79, 0x1E7A, 0x1E7B, 0x1E7C, + 0x1E7D, 0x1E7E, 0x1E7F, 0x1E80, 0x1E81, 0x1E82, 0x1E83, 0x1E84, 0x1E85, + 0x1E86, 0x1E87, 0x1E88, 0x1E89, 0x1E8A, 0x1E8B, 0x1E8C, 0x1E8D, 0x1E8E, + 0x1E8F, 0x1E90, 0x1E91, 0x1E92, 0x1E93, 0x1E94, 0x1E95, 0x1E96, 0x1E97, + 0x1E98, 0x1E99, 0x1E9A, 0x1E9B, 0x1E9C, 0x1E9D, 0x1E9E, 0x1E9F, 0x1EA0, + 0x1EA1, 0x1EA2, 0x1EA3, 0x1EA4, 0x1EA5, 0x1EA6, 0x1EA7, 0x1EA8, 0x1EA9, + 0x1EAA, 0x1EAB, 0x1EAC, 0x1EAD, 0x1EAE, 0x1EAF, 0x1EB0, 0x1EB1, 0x1EB2, + 0x1EB3, 0x1EB4, 0x1EB5, 0x1EB6, 0x1EB7, 0x1EB8, 0x1EB9, 0x1EBA, 0x1EBB, + 0x1EBC, 0x1EBD, 0x1EBE, 0x1EBF, 0x1EC0, 0x1EC1, 0x1EC2, 0x1EC3, 0x1EC4, + 0x1EC5, 0x1EC6, 0x1EC7, 0x1EC8, 0x1EC9, 0x1ECA, 0x1ECB, 0x1ECC, 0x1ECD, + 0x1ECE, 0x1ECF, 0x1ED0, 0x1ED1, 0x1ED2, 0x1ED3, 0x1ED4, 0x1ED5, 0x1ED6, + 0x1ED7, 0x1ED8, 0x1ED9, 0x1EDA, 0x1EDB, 0x1EDC, 0x1EDD, 0x1EDE, 0x1EDF, + 0x1EE0, 0x1EE1, 0x1EE2, 0x1EE3, 0x1EE4, 0x1EE5, 0x1EE6, 0x1EE7, 0x1EE8, + 0x1EE9, 0x1EEA, 0x1EEB, 0x1EEC, 0x1EED, 0x1EEE, 0x1EEF, 0x1EF0, 0x1EF1, + 0x1EF2, 0x1EF3, 0x1EF4, 0x1EF5, 0x1EF6, 0x1EF7, 0x1EF8, 0x1EF9, 0x1EFA, + 0x1EFB, 0x1EFC, 0x1EFD, 0x1EFE, 0x1EFF, 0x1F00, 0x1F01, 0x1F02, 0x1F03, + 0x1F04, 0x1F05, 0x1F06, 0x1F07, 0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, + 0x1F0D, 0x1F0E, 0x1F0F, 0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, + 0x1F16, 0x1F17, 0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x1F1E, + 0x1F1F, 0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27, + 0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F, 0x1F30, + 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37, 0x1F38, 0x1F39, + 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F, 0x1F40, 0x1F41, 0x1F42, + 0x1F43, 0x1F44, 0x1F45, 0x1F46, 0x1F47, 0x1F48, 0x1F49, 0x1F4A, 0x1F4B, + 0x1F4C, 0x1F4D, 0x1F4E, 0x1F4F, 0x1F50, 0x1F51, 0x1F52, 0x1F53, 0x1F54, + 0x1F55, 0x1F56, 0x1F57, 0x1F58, 0x1F59, 0x1F5A, 0x1F5B, 0x1F5C, 0x1F5D, + 0x1F5E, 0x1F5F, 0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, + 0x1F67, 0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F, + 0x1F70, 0x1F71, 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1F76, 0x1F77, 0x1F78, + 0x1F79, 0x1F7A, 0x1F7B, 0x1F7C, 0x1F7D, 0x1F7E, 0x1F7F, 0x1F80, 0x1F81, + 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87, 0x1F88, 0x1F89, 0x1F8A, + 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F, 0x1F90, 0x1F91, 0x1F92, 0x1F93, + 0x1F94, 0x1F95, 0x1F96, 0x1F97, 0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, + 0x1F9D, 0x1F9E, 0x1F9F, 0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, + 0x1FA6, 0x1FA7, 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, + 0x1FAF, 0x1FB0, 0x1FB1, 0x1FB2, 0x1FB3, 0x1FB4, 0x1FB5, 0x1FB6, 0x1FB7, + 0x1FB8, 0x1FB9, 0x1FBA, 0x1FBB, 0x1FBC, 0x1FBD, 0x1FBE, 0x1FBF, 0x1FC0, + 0x1FC1, 0x1FC2, 0x1FC3, 0x1FC4, 0x1FC5, 0x1FC6, 0x1FC7, 0x1FC8, 0x1FC9, + 0x1FCA, 0x1FCB, 0x1FCC, 0x1FCD, 0x1FCE, 0x1FCF, 0x1FD0, 0x1FD1, 0x1FD2, + 0x1FD3, 0x1FD4, 0x1FD5, 0x1FD6, 0x1FD7, 0x1FD8, 0x1FD9, 0x1FDA, 0x1FDB, + 0x1FDC, 0x1FDD, 0x1FDE, 0x1FDF, 0x1FE0, 0x1FE1, 0x1FE2, 0x1FE3, 0x1FE4, + 0x1FE5, 0x1FE6, 0x1FE7, 0x1FE8, 0x1FE9, 0x1FEA, 0x1FEB, 0x1FEC, 0x1FED, + 0x1FEE, 0x1FEF, 0x1FF0, 0x1FF1, 0x1FF2, 0x1FF3, 0x1FF4, 0x1FF5, 0x1FF6, + 0x1FF7, 0x1FF8, 0x1FF9, 0x1FFA, 0x1FFB, 0x1FFC, 0x1FFD, 0x1FFE, 0x1FFF, + 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, + 0x2009, 0x200A, 0x200B, 0x200C, 0x200D, 0x200E, 0x200F, 0x2011, 0x2012, + 0x2017, 0x201A, 0x201B, 0x201E, 0x201F, 0x2020, 0x2021, 0x2022, 0x2023, + 0x2024, 0x2027, 0x2028, 0x2029, 0x202A, 0x202B, 0x202C, 0x202D, 0x202E, + 0x202F, 0x2031, 0x2034, 0x2036, 0x2037, 0x2038, 0x2039, 0x203A, 0x203C, + 0x203D, 0x203E, 0x203F, 0x2040, 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, + 0x2046, 0x2047, 0x2048, 0x2049, 0x204A, 0x204B, 0x204C, 0x204D, 0x204E, + 0x204F, 0x2050, 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057, + 0x2058, 0x2059, 0x205A, 0x205B, 0x205C, 0x205D, 0x205E, 0x205F, 0x2060, + 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067, 0x2068, 0x2069, + 0x206A, 0x206B, 0x206C, 0x206D, 0x206E, 0x206F, 0x2070, 0x2071, 0x2072, + 0x2073, 0x2074, 0x2075, 0x2076, 0x2077, 0x2078, 0x2079, 0x207A, 0x207B, + 0x207C, 0x207D, 0x207E, 0x207F, 0x2080, 0x2081, 0x2082, 0x2083, 0x2084, + 0x2085, 0x2086, 0x2087, 0x2088, 0x2089, 0x208A, 0x208B, 0x208C, 0x208D, + 0x208E, 0x208F, 0x2090, 0x2091, 0x2092, 0x2093, 0x2094, 0x2095, 0x2096, + 0x2097, 0x2098, 0x2099, 0x209A, 0x209B, 0x209C, 0x209D, 0x209E, 0x209F, + 0x20A0, 0x20A1, 0x20A2, 0x20A3, 0x20A4, 0x20A5, 0x20A6, 0x20A7, 0x20A8, + 0x20A9, 0x20AA, 0x20AB, 0x20AD, 0x20AE, 0x20AF, 0x20B0, 0x20B1, 0x20B2, + 0x20B3, 0x20B4, 0x20B5, 0x20B6, 0x20B7, 0x20B8, 0x20B9, 0x20BA, 0x20BB, + 0x20BC, 0x20BD, 0x20BE, 0x20BF, 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, + 0x20C5, 0x20C6, 0x20C7, 0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, + 0x20CE, 0x20CF, 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, + 0x20D7, 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x20DF, + 0x20E0, 0x20E1, 0x20E2, 0x20E3, 0x20E4, 0x20E5, 0x20E6, 0x20E7, 0x20E8, + 0x20E9, 0x20EA, 0x20EB, 0x20EC, 0x20ED, 0x20EE, 0x20EF, 0x20F0, 0x20F1, + 0x20F2, 0x20F3, 0x20F4, 0x20F5, 0x20F6, 0x20F7, 0x20F8, 0x20F9, 0x20FA, + 0x20FB, 0x20FC, 0x20FD, 0x20FE, 0x20FF, 0x2100, 0x2101, 0x2102, 0x2104, + 0x2106, 0x2107, 0x2108, 0x210A, 0x210B, 0x210C, 0x210D, 0x210E, 0x210F, + 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2117, 0x2118, 0x2119, + 0x211A, 0x211B, 0x211C, 0x211D, 0x211E, 0x211F, 0x2120, 0x2122, 0x2123, + 0x2124, 0x2125, 0x2126, 0x2127, 0x2128, 0x2129, 0x212A, 0x212B, 0x212C, + 0x212D, 0x212E, 0x212F, 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, + 0x2136, 0x2137, 0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, + 0x213F, 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147, + 0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F, 0x2150, + 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, + 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F, 0x216C, 0x216D, 0x216E, + 0x216F, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0x2180, 0x2181, + 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187, 0x2188, 0x2189, 0x218A, + 0x218B, 0x218C, 0x218D, 0x218E, 0x218F, 0x2194, 0x2195, 0x219A, 0x219B, + 0x219C, 0x219D, 0x219E, 0x219F, 0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, + 0x21A5, 0x21A6, 0x21A7, 0x21A8, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, + 0x21AE, 0x21AF, 0x21B0, 0x21B1, 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, + 0x21B7, 0x21B8, 0x21B9, 0x21BA, 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF, + 0x21C0, 0x21C1, 0x21C2, 0x21C3, 0x21C4, 0x21C5, 0x21C6, 0x21C7, 0x21C8, + 0x21C9, 0x21CA, 0x21CB, 0x21CC, 0x21CD, 0x21CE, 0x21CF, 0x21D0, 0x21D1, + 0x21D2, 0x21D3, 0x21D4, 0x21D5, 0x21D6, 0x21D7, 0x21D8, 0x21D9, 0x21DA, + 0x21DB, 0x21DC, 0x21DD, 0x21DE, 0x21DF, 0x21E0, 0x21E1, 0x21E2, 0x21E3, + 0x21E4, 0x21E5, 0x21E6, 0x21E7, 0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, + 0x21ED, 0x21EE, 0x21EF, 0x21F0, 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, + 0x21F6, 0x21F7, 0x21F8, 0x21F9, 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, + 0x21FF, 0x2200, 0x2201, 0x2202, 0x2203, 0x2204, 0x2205, 0x2206, 0x2207, + 0x2209, 0x220A, 0x220B, 0x220C, 0x220D, 0x220E, 0x2210, 0x2212, 0x2213, + 0x2214, 0x2216, 0x2217, 0x2218, 0x2219, 0x221B, 0x221C, 0x2221, 0x2222, + 0x2224, 0x2226, 0x222C, 0x222D, 0x222F, 0x2230, 0x2231, 0x2232, 0x2233, + 0x2238, 0x2239, 0x223A, 0x223B, 0x223C, 0x223E, 0x223F, 0x2240, 0x2241, + 0x2242, 0x2243, 0x2244, 0x2245, 0x2246, 0x2247, 0x2249, 0x224A, 0x224B, + 0x224D, 0x224E, 0x224F, 0x2250, 0x2251, 0x2253, 0x2254, 0x2255, 0x2256, + 0x2257, 0x2258, 0x2259, 0x225A, 0x225B, 0x225C, 0x225D, 0x225E, 0x225F, + 0x2262, 0x2263, 0x2268, 0x2269, 0x226A, 0x226B, 0x226C, 0x226D, 0x2270, + 0x2271, 0x2272, 0x2273, 0x2274, 0x2275, 0x2276, 0x2277, 0x2278, 0x2279, + 0x227A, 0x227B, 0x227C, 0x227D, 0x227E, 0x227F, 0x2280, 0x2281, 0x2282, + 0x2283, 0x2284, 0x2285, 0x2286, 0x2287, 0x2288, 0x2289, 0x228A, 0x228B, + 0x228C, 0x228D, 0x228E, 0x228F, 0x2290, 0x2291, 0x2292, 0x2293, 0x2294, + 0x2296, 0x2297, 0x2298, 0x229A, 0x229B, 0x229C, 0x229D, 0x229E, 0x229F, + 0x22A0, 0x22A1, 0x22A2, 0x22A3, 0x22A4, 0x22A6, 0x22A7, 0x22A8, 0x22A9, + 0x22AA, 0x22AB, 0x22AC, 0x22AD, 0x22AE, 0x22AF, 0x22B0, 0x22B1, 0x22B2, + 0x22B3, 0x22B4, 0x22B5, 0x22B6, 0x22B7, 0x22B8, 0x22B9, 0x22BA, 0x22BB, + 0x22BC, 0x22BD, 0x22BE, 0x22C0, 0x22C1, 0x22C2, 0x22C3, 0x22C4, 0x22C5, + 0x22C6, 0x22C7, 0x22C8, 0x22C9, 0x22CA, 0x22CB, 0x22CC, 0x22CD, 0x22CE, + 0x22CF, 0x22D0, 0x22D1, 0x22D2, 0x22D3, 0x22D4, 0x22D5, 0x22D6, 0x22D7, + 0x22D8, 0x22D9, 0x22DA, 0x22DB, 0x22DC, 0x22DD, 0x22DE, 0x22DF, 0x22E0, + 0x22E1, 0x22E2, 0x22E3, 0x22E4, 0x22E5, 0x22E6, 0x22E7, 0x22E8, 0x22E9, + 0x22EA, 0x22EB, 0x22EC, 0x22ED, 0x22EE, 0x22EF, 0x22F0, 0x22F1, 0x22F2, + 0x22F3, 0x22F4, 0x22F5, 0x22F6, 0x22F7, 0x22F8, 0x22F9, 0x22FA, 0x22FB, + 0x22FC, 0x22FD, 0x22FE, 0x22FF, 0x2300, 0x2301, 0x2302, 0x2303, 0x2304, + 0x2305, 0x2306, 0x2307, 0x2308, 0x2309, 0x230A, 0x230B, 0x230C, 0x230D, + 0x230E, 0x230F, 0x2310, 0x2311, 0x2313, 0x2314, 0x2315, 0x2316, 0x2317, + 0x2318, 0x2319, 0x231A, 0x231B, 0x231C, 0x231D, 0x231E, 0x231F, 0x2320, + 0x2321, 0x2322, 0x2323, 0x2324, 0x2325, 0x2326, 0x2327, 0x2328, 0x2329, + 0x232A, 0x232B, 0x232C, 0x232D, 0x232E, 0x232F, 0x2330, 0x2331, 0x2332, + 0x2333, 0x2334, 0x2335, 0x2336, 0x2337, 0x2338, 0x2339, 0x233A, 0x233B, + 0x233C, 0x233D, 0x233E, 0x233F, 0x2340, 0x2341, 0x2342, 0x2343, 0x2344, + 0x2345, 0x2346, 0x2347, 0x2348, 0x2349, 0x234A, 0x234B, 0x234C, 0x234D, + 0x234E, 0x234F, 0x2350, 0x2351, 0x2352, 0x2353, 0x2354, 0x2355, 0x2356, + 0x2357, 0x2358, 0x2359, 0x235A, 0x235B, 0x235C, 0x235D, 0x235E, 0x235F, + 0x2360, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367, 0x2368, + 0x2369, 0x236A, 0x236B, 0x236C, 0x236D, 0x236E, 0x236F, 0x2370, 0x2371, + 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377, 0x2378, 0x2379, 0x237A, + 0x237B, 0x237C, 0x237D, 0x237E, 0x237F, 0x2380, 0x2381, 0x2382, 0x2383, + 0x2384, 0x2385, 0x2386, 0x2387, 0x2388, 0x2389, 0x238A, 0x238B, 0x238C, + 0x238D, 0x238E, 0x238F, 0x2390, 0x2391, 0x2392, 0x2393, 0x2394, 0x2395, + 0x2396, 0x2397, 0x2398, 0x2399, 0x239A, 0x239B, 0x239C, 0x239D, 0x239E, + 0x239F, 0x23A0, 0x23A1, 0x23A2, 0x23A3, 0x23A4, 0x23A5, 0x23A6, 0x23A7, + 0x23A8, 0x23A9, 0x23AA, 0x23AB, 0x23AC, 0x23AD, 0x23AE, 0x23AF, 0x23B0, + 0x23B1, 0x23B2, 0x23B3, 0x23B4, 0x23B5, 0x23B6, 0x23B7, 0x23B8, 0x23B9, + 0x23BA, 0x23BB, 0x23BC, 0x23BD, 0x23BE, 0x23BF, 0x23C0, 0x23C1, 0x23C2, + 0x23C3, 0x23C4, 0x23C5, 0x23C6, 0x23C7, 0x23C8, 0x23C9, 0x23CA, 0x23CB, + 0x23CC, 0x23CD, 0x23CE, 0x23CF, 0x23D0, 0x23D1, 0x23D2, 0x23D3, 0x23D4, + 0x23D5, 0x23D6, 0x23D7, 0x23D8, 0x23D9, 0x23DA, 0x23DB, 0x23DC, 0x23DD, + 0x23DE, 0x23DF, 0x23E0, 0x23E1, 0x23E2, 0x23E3, 0x23E4, 0x23E5, 0x23E6, + 0x23E7, 0x23E8, 0x23E9, 0x23EA, 0x23EB, 0x23EC, 0x23ED, 0x23EE, 0x23EF, + 0x23F0, 0x23F1, 0x23F2, 0x23F3, 0x23F4, 0x23F5, 0x23F6, 0x23F7, 0x23F8, + 0x23F9, 0x23FA, 0x23FB, 0x23FC, 0x23FD, 0x23FE, 0x23FF, 0x2400, 0x2401, + 0x2402, 0x2403, 0x2404, 0x2405, 0x2406, 0x2407, 0x2408, 0x2409, 0x240A, + 0x240B, 0x240C, 0x240D, 0x240E, 0x240F, 0x2410, 0x2411, 0x2412, 0x2413, + 0x2414, 0x2415, 0x2416, 0x2417, 0x2418, 0x2419, 0x241A, 0x241B, 0x241C, + 0x241D, 0x241E, 0x241F, 0x2420, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, + 0x2426, 0x2427, 0x2428, 0x2429, 0x242A, 0x242B, 0x242C, 0x242D, 0x242E, + 0x242F, 0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437, + 0x2438, 0x2439, 0x243A, 0x243B, 0x243C, 0x243D, 0x243E, 0x243F, 0x2440, + 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447, 0x2448, 0x2449, + 0x244A, 0x244B, 0x244C, 0x244D, 0x244E, 0x244F, 0x2450, 0x2451, 0x2452, + 0x2453, 0x2454, 0x2455, 0x2456, 0x2457, 0x2458, 0x2459, 0x245A, 0x245B, + 0x245C, 0x245D, 0x245E, 0x245F, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, + 0x246F, 0x2470, 0x2471, 0x2472, 0x2473, 0x249C, 0x249D, 0x249E, 0x249F, + 0x24A0, 0x24A1, 0x24A2, 0x24A3, 0x24A4, 0x24A5, 0x24A6, 0x24A7, 0x24A8, + 0x24A9, 0x24AA, 0x24AB, 0x24AC, 0x24AD, 0x24AE, 0x24AF, 0x24B0, 0x24B1, + 0x24B2, 0x24B3, 0x24B4, 0x24B5, 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, 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, 0x24EA, 0x24EB, 0x24EC, 0x24ED, 0x24EE, 0x24EF, 0x24F0, + 0x24F1, 0x24F2, 0x24F3, 0x24F4, 0x24F5, 0x24F6, 0x24F7, 0x24F8, 0x24F9, + 0x24FA, 0x24FB, 0x24FC, 0x24FD, 0x24FE, 0x24FF, 0x254C, 0x254D, 0x254E, + 0x254F, 0x2574, 0x2575, 0x2576, 0x2577, 0x2578, 0x2579, 0x257A, 0x257B, + 0x257C, 0x257D, 0x257E, 0x257F, 0x2580, 0x2590, 0x2591, 0x2592, 0x2596, + 0x2597, 0x2598, 0x2599, 0x259A, 0x259B, 0x259C, 0x259D, 0x259E, 0x259F, + 0x25A2, 0x25A3, 0x25A4, 0x25A5, 0x25A6, 0x25A7, 0x25A8, 0x25A9, 0x25AA, + 0x25AB, 0x25AC, 0x25AD, 0x25AE, 0x25AF, 0x25B0, 0x25B1, 0x25B4, 0x25B5, + 0x25B6, 0x25B7, 0x25B8, 0x25B9, 0x25BA, 0x25BB, 0x25BE, 0x25BF, 0x25C0, + 0x25C1, 0x25C2, 0x25C3, 0x25C4, 0x25C5, 0x25C8, 0x25C9, 0x25CA, 0x25CC, + 0x25CD, 0x25D0, 0x25D1, 0x25D2, 0x25D3, 0x25D4, 0x25D5, 0x25D6, 0x25D7, + 0x25D8, 0x25D9, 0x25DA, 0x25DB, 0x25DC, 0x25DD, 0x25DE, 0x25DF, 0x25E0, + 0x25E1, 0x25E6, 0x25E7, 0x25E8, 0x25E9, 0x25EA, 0x25EB, 0x25EC, 0x25ED, + 0x25EE, 0x25EF, 0x25F0, 0x25F1, 0x25F2, 0x25F3, 0x25F4, 0x25F5, 0x25F6, + 0x25F7, 0x25F8, 0x25F9, 0x25FA, 0x25FB, 0x25FC, 0x25FD, 0x25FE, 0x25FF, + 0x2600, 0x2601, 0x2602, 0x2603, 0x2604, 0x2607, 0x2608, 0x260A, 0x260B, + 0x260C, 0x260D, 0x260E, 0x260F, 0x2610, 0x2611, 0x2612, 0x2613, 0x2614, + 0x2615, 0x2616, 0x2617, 0x2618, 0x2619, 0x261A, 0x261B, 0x261C, 0x261D, + 0x261E, 0x261F, 0x2620, 0x2621, 0x2622, 0x2623, 0x2624, 0x2625, 0x2626, + 0x2627, 0x2628, 0x2629, 0x262A, 0x262B, 0x262C, 0x262D, 0x262E, 0x262F, + 0x2630, 0x2631, 0x2632, 0x2633, 0x2634, 0x2635, 0x2636, 0x2637, 0x2638, + 0x2639, 0x263A, 0x263B, 0x263C, 0x263D, 0x263E, 0x263F, 0x2641, 0x2E82, + 0x2E83, 0x2E85, 0x2E86, 0x2E87, 0x2E89, 0x2E8A, 0x2E8D, 0x2E8E, 0x2E8F, + 0x2E90, 0x2E91, 0x2E92, 0x2E93, 0x2E94, 0x2E95, 0x2E96, 0x2E98, 0x2E99, + 0x2E9A, 0x2E9B, 0x2E9C, 0x2E9D, 0x2E9E, 0x2E9F, 0x2EA0, 0x2EA1, 0x2EA2, + 0x2EA3, 0x2EA4, 0x2EA5, 0x2EA6, 0x2EA8, 0x2EA9, 0x2EAB, 0x2EAC, 0x2EAD, + 0x2EAF, 0x2EB0, 0x2EB1, 0x2EB2, 0x2EB4, 0x2EB5, 0x2EB8, 0x2EB9, 0x2EBA, + 0x2EBC, 0x2EBD, 0x2EBE, 0x2EBF, 0x2EC0, 0x2EC1, 0x2EC2, 0x2EC3, 0x2EC4, + 0x2EC5, 0x2EC6, 0x2EC7, 0x2EC8, 0x2EC9, 0x2ECB, 0x2ECC, 0x2ECD, 0x2ECE, + 0x2ECF, 0x2ED0, 0x2ED1, 0x2ED2, 0x2ED3, 0x2ED4, 0x2ED5, 0x2ED6, 0x2ED7, + 0x2ED8, 0x2ED9, 0x2EDA, 0x2EDB, 0x2EDC, 0x2EDD, 0x2EDE, 0x2EDF, 0x2EE0, + 0x2EE1, 0x2EE2, 0x2EE3, 0x2EE4, 0x2EE5, 0x2EE6, 0x2EE7, 0x2EE8, 0x2EE9, + 0x2EEA, 0x2EEB, 0x2EEC, 0x2EED, 0x2EEE, 0x2EEF, 0x2EF0, 0x2EF1, 0x2EF2, + 0x2EF3, 0x2EF4, 0x2EF5, 0x2EF6, 0x2EF7, 0x2EF8, 0x2EF9, 0x2EFA, 0x2EFB, + 0x2EFC, 0x2EFD, 0x2EFE, 0x2EFF, 0x2F00, 0x2F01, 0x2F02, 0x2F03, 0x2F04, + 0x2F05, 0x2F06, 0x2F07, 0x2F08, 0x2F09, 0x2F0A, 0x2F0B, 0x2F0C, 0x2F0D, + 0x2F0E, 0x2F0F, 0x2F10, 0x2F11, 0x2F12, 0x2F13, 0x2F14, 0x2F15, 0x2F16, + 0x2F17, 0x2F18, 0x2F19, 0x2F1A, 0x2F1B, 0x2F1C, 0x2F1D, 0x2F1E, 0x2F1F, + 0x2F20, 0x2F21, 0x2F22, 0x2F23, 0x2F24, 0x2F25, 0x2F26, 0x2F27, 0x2F28, + 0x2F29, 0x2F2A, 0x2F2B, 0x2F2C, 0x2F2D, 0x2F2E, 0x2F2F, 0x2F30, 0x2F31, + 0x2F32, 0x2F33, 0x2F34, 0x2F35, 0x2F36, 0x2F37, 0x2F38, 0x2F39, 0x2F3A, + 0x2F3B, 0x2F3C, 0x2F3D, 0x2F3E, 0x2F3F, 0x2F40, 0x2F41, 0x2F42, 0x2F43, + 0x2F44, 0x2F45, 0x2F46, 0x2F47, 0x2F48, 0x2F49, 0x2F4A, 0x2F4B, 0x2F4C, + 0x2F4D, 0x2F4E, 0x2F4F, 0x2F50, 0x2F51, 0x2F52, 0x2F53, 0x2F54, 0x2F55, + 0x2F56, 0x2F57, 0x2F58, 0x2F59, 0x2F5A, 0x2F5B, 0x2F5C, 0x2F5D, 0x2F5E, + 0x2F5F, 0x2F60, 0x2F61, 0x2F62, 0x2F63, 0x2F64, 0x2F65, 0x2F66, 0x2F67, + 0x2F68, 0x2F69, 0x2F6A, 0x2F6B, 0x2F6C, 0x2F6D, 0x2F6E, 0x2F6F, 0x2F70, + 0x2F71, 0x2F72, 0x2F73, 0x2F74, 0x2F75, 0x2F76, 0x2F77, 0x2F78, 0x2F79, + 0x2F7A, 0x2F7B, 0x2F7C, 0x2F7D, 0x2F7E, 0x2F7F, 0x2F80, 0x2F81, 0x2F82, + 0x2F83, 0x2F84, 0x2F85, 0x2F86, 0x2F87, 0x2F88, 0x2F89, 0x2F8A, 0x2F8B, + 0x2F8C, 0x2F8D, 0x2F8E, 0x2F8F, 0x2F90, 0x2F91, 0x2F92, 0x2F93, 0x2F94, + 0x2F95, 0x2F96, 0x2F97, 0x2F98, 0x2F99, 0x2F9A, 0x2F9B, 0x2F9C, 0x2F9D, + 0x2F9E, 0x2F9F, 0x2FA0, 0x2FA1, 0x2FA2, 0x2FA3, 0x2FA4, 0x2FA5, 0x2FA6, + 0x2FA7, 0x2FA8, 0x2FA9, 0x2FAA, 0x2FAB, 0x2FAC, 0x2FAD, 0x2FAE, 0x2FAF, + 0x2FB0, 0x2FB1, 0x2FB2, 0x2FB3, 0x2FB4, 0x2FB5, 0x2FB6, 0x2FB7, 0x2FB8, + 0x2FB9, 0x2FBA, 0x2FBB, 0x2FBC, 0x2FBD, 0x2FBE, 0x2FBF, 0x2FC0, 0x2FC1, + 0x2FC2, 0x2FC3, 0x2FC4, 0x2FC5, 0x2FC6, 0x2FC7, 0x2FC8, 0x2FC9, 0x2FCA, + 0x2FCB, 0x2FCC, 0x2FCD, 0x2FCE, 0x2FCF, 0x2FD0, 0x2FD1, 0x2FD2, 0x2FD3, + 0x2FD4, 0x2FD5, 0x2FD6, 0x2FD7, 0x2FD8, 0x2FD9, 0x2FDA, 0x2FDB, 0x2FDC, + 0x2FDD, 0x2FDE, 0x2FDF, 0x2FE0, 0x2FE1, 0x2FE2, 0x2FE3, 0x2FE4, 0x2FE5, + 0x2FE6, 0x2FE7, 0x2FE8, 0x2FE9, 0x2FEA, 0x2FEB, 0x2FEC, 0x2FED, 0x2FEE, + 0x2FEF, 0x2FFC, 0x2FFD, 0x2FFE, 0x2FFF, 0x3004, 0x3018, 0x3019, 0x301A, + 0x301B, 0x301C, 0x301F, 0x3020, 0x302A, 0x302B, 0x302C, 0x302D, 0x302E, + 0x302F, 0x3030, 0x3031, 0x3032, 0x3033, 0x3034, 0x3035, 0x3036, 0x3037, + 0x3038, 0x3039, 0x303A, 0x303B, 0x303C, 0x303D, 0x303F, 0x3040, 0x3094, + 0x3095, 0x3096, 0x3097, 0x3098, 0x3099, 0x309A, 0x309F, 0x30A0, 0x30F7, + 0x30F8, 0x30F9, 0x30FA, 0x30FB, 0x30FF, 0x3100, 0x3101, 0x3102, 0x3103, + 0x3104, 0x312A, 0x312B, 0x312C, 0x312D, 0x312E, 0x312F, 0x3130, 0x3131, + 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137, 0x3138, 0x3139, 0x313A, + 0x313B, 0x313C, 0x313D, 0x313E, 0x313F, 0x3140, 0x3141, 0x3142, 0x3143, + 0x3144, 0x3145, 0x3146, 0x3147, 0x3148, 0x3149, 0x314A, 0x314B, 0x314C, + 0x314D, 0x314E, 0x314F, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0x3155, + 0x3156, 0x3157, 0x3158, 0x3159, 0x315A, 0x315B, 0x315C, 0x315D, 0x315E, + 0x315F, 0x3160, 0x3161, 0x3162, 0x3163, 0x3164, 0x3165, 0x3166, 0x3167, + 0x3168, 0x3169, 0x316A, 0x316B, 0x316C, 0x316D, 0x316E, 0x316F, 0x3170, + 0x3171, 0x3172, 0x3173, 0x3174, 0x3175, 0x3176, 0x3177, 0x3178, 0x3179, + 0x317A, 0x317B, 0x317C, 0x317D, 0x317E, 0x317F, 0x3180, 0x3181, 0x3182, + 0x3183, 0x3184, 0x3185, 0x3186, 0x3187, 0x3188, 0x3189, 0x318A, 0x318B, + 0x318C, 0x318D, 0x318E, 0x318F, 0x3190, 0x3191, 0x3192, 0x3193, 0x3194, + 0x3195, 0x3196, 0x3197, 0x3198, 0x3199, 0x319A, 0x319B, 0x319C, 0x319D, + 0x319E, 0x319F, 0x31A0, 0x31A1, 0x31A2, 0x31A3, 0x31A4, 0x31A5, 0x31A6, + 0x31A7, 0x31A8, 0x31A9, 0x31AA, 0x31AB, 0x31AC, 0x31AD, 0x31AE, 0x31AF, + 0x31B0, 0x31B1, 0x31B2, 0x31B3, 0x31B4, 0x31B5, 0x31B6, 0x31B7, 0x31B8, + 0x31B9, 0x31BA, 0x31BB, 0x31BC, 0x31BD, 0x31BE, 0x31BF, 0x31C0, 0x31C1, + 0x31C2, 0x31C3, 0x31C4, 0x31C5, 0x31C6, 0x31C7, 0x31C8, 0x31C9, 0x31CA, + 0x31CB, 0x31CC, 0x31CD, 0x31CE, 0x31CF, 0x31D0, 0x31D1, 0x31D2, 0x31D3, + 0x31D4, 0x31D5, 0x31D6, 0x31D7, 0x31D8, 0x31D9, 0x31DA, 0x31DB, 0x31DC, + 0x31DD, 0x31DE, 0x31DF, 0x31E0, 0x31E1, 0x31E2, 0x31E3, 0x31E4, 0x31E5, + 0x31E6, 0x31E7, 0x31E8, 0x31E9, 0x31EA, 0x31EB, 0x31EC, 0x31ED, 0x31EE, + 0x31EF, 0x31F0, 0x31F1, 0x31F2, 0x31F3, 0x31F4, 0x31F5, 0x31F6, 0x31F7, + 0x31F8, 0x31F9, 0x31FA, 0x31FB, 0x31FC, 0x31FD, 0x31FE, 0x31FF, 0x3200, + 0x3201, 0x3202, 0x3203, 0x3204, 0x3205, 0x3206, 0x3207, 0x3208, 0x3209, + 0x320A, 0x320B, 0x320C, 0x320D, 0x320E, 0x320F, 0x3210, 0x3211, 0x3212, + 0x3213, 0x3214, 0x3215, 0x3216, 0x3217, 0x3218, 0x3219, 0x321A, 0x321B, + 0x321C, 0x321D, 0x321E, 0x321F, 0x322A, 0x322B, 0x322C, 0x322D, 0x322E, + 0x322F, 0x3230, 0x3232, 0x3233, 0x3234, 0x3235, 0x3236, 0x3237, 0x3238, + 0x3239, 0x323A, 0x323B, 0x323C, 0x323D, 0x323E, 0x323F, 0x3240, 0x3241, + 0x3242, 0x3243, 0x3244, 0x3245, 0x3246, 0x3247, 0x3248, 0x3249, 0x324A, + 0x324B, 0x324C, 0x324D, 0x324E, 0x324F, 0x3250, 0x3251, 0x3252, 0x3253, + 0x3254, 0x3255, 0x3256, 0x3257, 0x3258, 0x3259, 0x325A, 0x325B, 0x325C, + 0x325D, 0x325E, 0x325F, 0x3260, 0x3261, 0x3262, 0x3263, 0x3264, 0x3265, + 0x3266, 0x3267, 0x3268, 0x3269, 0x326A, 0x326B, 0x326C, 0x326D, 0x326E, + 0x326F, 0x3270, 0x3271, 0x3272, 0x3273, 0x3274, 0x3275, 0x3276, 0x3277, + 0x3278, 0x3279, 0x327A, 0x327B, 0x327C, 0x327D, 0x327E, 0x327F, 0x3280, + 0x3281, 0x3282, 0x3283, 0x3284, 0x3285, 0x3286, 0x3287, 0x3288, 0x3289, + 0x328A, 0x328B, 0x328C, 0x328D, 0x328E, 0x328F, 0x3290, 0x3291, 0x3292, + 0x3293, 0x3294, 0x3295, 0x3296, 0x3297, 0x3298, 0x3299, 0x329A, 0x329B, + 0x329C, 0x329D, 0x329E, 0x329F, 0x32A0, 0x32A1, 0x32A2, 0x32A4, 0x32A5, + 0x32A6, 0x32A7, 0x32A8, 0x32A9, 0x32AA, 0x32AB, 0x32AC, 0x32AD, 0x32AE, + 0x32AF, 0x32B0, 0x32B1, 0x32B2, 0x32B3, 0x32B4, 0x32B5, 0x32B6, 0x32B7, + 0x32B8, 0x32B9, 0x32BA, 0x32BB, 0x32BC, 0x32BD, 0x32BE, 0x32BF, 0x32C0, + 0x32C1, 0x32C2, 0x32C3, 0x32C4, 0x32C5, 0x32C6, 0x32C7, 0x32C8, 0x32C9, + 0x32CA, 0x32CB, 0x32CC, 0x32CD, 0x32CE, 0x32CF, 0x32D0, 0x32D1, 0x32D2, + 0x32D3, 0x32D4, 0x32D5, 0x32D6, 0x32D7, 0x32D8, 0x32D9, 0x32DA, 0x32DB, + 0x32DC, 0x32DD, 0x32DE, 0x32DF, 0x32E0, 0x32E1, 0x32E2, 0x32E3, 0x32E4, + 0x32E5, 0x32E6, 0x32E7, 0x32E8, 0x32E9, 0x32EA, 0x32EB, 0x32EC, 0x32ED, + 0x32EE, 0x32EF, 0x32F0, 0x32F1, 0x32F2, 0x32F3, 0x32F4, 0x32F5, 0x32F6, + 0x32F7, 0x32F8, 0x32F9, 0x32FA, 0x32FB, 0x32FC, 0x32FD, 0x32FE, 0x32FF, + 0x3300, 0x3301, 0x3302, 0x3303, 0x3304, 0x3305, 0x3306, 0x3307, 0x3308, + 0x3309, 0x330A, 0x330B, 0x330C, 0x330D, 0x330E, 0x330F, 0x3310, 0x3311, + 0x3312, 0x3313, 0x3314, 0x3315, 0x3316, 0x3317, 0x3318, 0x3319, 0x331A, + 0x331B, 0x331C, 0x331D, 0x331E, 0x331F, 0x3320, 0x3321, 0x3322, 0x3323, + 0x3324, 0x3325, 0x3326, 0x3327, 0x3328, 0x3329, 0x332A, 0x332B, 0x332C, + 0x332D, 0x332E, 0x332F, 0x3330, 0x3331, 0x3332, 0x3333, 0x3334, 0x3335, + 0x3336, 0x3337, 0x3338, 0x3339, 0x333A, 0x333B, 0x333C, 0x333D, 0x333E, + 0x333F, 0x3340, 0x3341, 0x3342, 0x3343, 0x3344, 0x3345, 0x3346, 0x3347, + 0x3348, 0x3349, 0x334A, 0x334B, 0x334C, 0x334D, 0x334E, 0x334F, 0x3350, + 0x3351, 0x3352, 0x3353, 0x3354, 0x3355, 0x3356, 0x3357, 0x3358, 0x3359, + 0x335A, 0x335B, 0x335C, 0x335D, 0x335E, 0x335F, 0x3360, 0x3361, 0x3362, + 0x3363, 0x3364, 0x3365, 0x3366, 0x3367, 0x3368, 0x3369, 0x336A, 0x336B, + 0x336C, 0x336D, 0x336E, 0x336F, 0x3370, 0x3371, 0x3372, 0x3373, 0x3374, + 0x3375, 0x3376, 0x3377, 0x3378, 0x3379, 0x337A, 0x337B, 0x337C, 0x337D, + 0x337E, 0x337F, 0x3380, 0x3381, 0x3382, 0x3383, 0x3384, 0x3385, 0x3386, + 0x3387, 0x3388, 0x3389, 0x338A, 0x338B, 0x338C, 0x338D, 0x3390, 0x3391, + 0x3392, 0x3393, 0x3394, 0x3395, 0x3396, 0x3397, 0x3398, 0x3399, 0x339A, + 0x339B, 0x339F, 0x33A0, 0x33A2, 0x33A3, 0x33A4, 0x33A5, 0x33A6, 0x33A7, + 0x33A8, 0x33A9, 0x33AA, 0x33AB, 0x33AC, 0x33AD, 0x33AE, 0x33AF, 0x33B0, + 0x33B1, 0x33B2, 0x33B3, 0x33B4, 0x33B5, 0x33B6, 0x33B7, 0x33B8, 0x33B9, + 0x33BA, 0x33BB, 0x33BC, 0x33BD, 0x33BE, 0x33BF, 0x33C0, 0x33C1, 0x33C2, + 0x33C3, 0x33C5, 0x33C6, 0x33C7, 0x33C8, 0x33C9, 0x33CA, 0x33CB, 0x33CC, + 0x33CD, 0x33CF, 0x33D0, 0x33D3, 0x33D4, 0x33D6, 0x33D7, 0x33D8, 0x33D9, + 0x33DA, 0x33DB, 0x33DC, 0x33DD, 0x33DE, 0x33DF, 0x33E0, 0x33E1, 0x33E2, + 0x33E3, 0x33E4, 0x33E5, 0x33E6, 0x33E7, 0x33E8, 0x33E9, 0x33EA, 0x33EB, + 0x33EC, 0x33ED, 0x33EE, 0x33EF, 0x33F0, 0x33F1, 0x33F2, 0x33F3, 0x33F4, + 0x33F5, 0x33F6, 0x33F7, 0x33F8, 0x33F9, 0x33FA, 0x33FB, 0x33FC, 0x33FD, + 0x33FE, 0x33FF, 0x3400, 0x3401, 0x3402, 0x3403, 0x3404, 0x3405, 0x3406, + 0x3407, 0x3408, 0x3409, 0x340A, 0x340B, 0x340C, 0x340D, 0x340E, 0x340F, + 0x3410, 0x3411, 0x3412, 0x3413, 0x3414, 0x3415, 0x3416, 0x3417, 0x3418, + 0x3419, 0x341A, 0x341B, 0x341C, 0x341D, 0x341E, 0x341F, 0x3420, 0x3421, + 0x3422, 0x3423, 0x3424, 0x3425, 0x3426, 0x3427, 0x3428, 0x3429, 0x342A, + 0x342B, 0x342C, 0x342D, 0x342E, 0x342F, 0x3430, 0x3431, 0x3432, 0x3433, + 0x3434, 0x3435, 0x3436, 0x3437, 0x3438, 0x3439, 0x343A, 0x343B, 0x343C, + 0x343D, 0x343E, 0x343F, 0x3440, 0x3441, 0x3442, 0x3443, 0x3444, 0x3445, + 0x3446, 0x3448, 0x3449, 0x344A, 0x344B, 0x344C, 0x344D, 0x344E, 0x344F, + 0x3450, 0x3451, 0x3452, 0x3453, 0x3454, 0x3455, 0x3456, 0x3457, 0x3458, + 0x3459, 0x345A, 0x345B, 0x345C, 0x345D, 0x345E, 0x345F, 0x3460, 0x3461, + 0x3462, 0x3463, 0x3464, 0x3465, 0x3466, 0x3467, 0x3468, 0x3469, 0x346A, + 0x346B, 0x346C, 0x346D, 0x346E, 0x346F, 0x3470, 0x3471, 0x3472, 0x3474, + 0x3475, 0x3476, 0x3477, 0x3478, 0x3479, 0x347A, 0x347B, 0x347C, 0x347D, + 0x347E, 0x347F, 0x3480, 0x3481, 0x3482, 0x3483, 0x3484, 0x3485, 0x3486, + 0x3487, 0x3488, 0x3489, 0x348A, 0x348B, 0x348C, 0x348D, 0x348E, 0x348F, + 0x3490, 0x3491, 0x3492, 0x3493, 0x3494, 0x3495, 0x3496, 0x3497, 0x3498, + 0x3499, 0x349A, 0x349B, 0x349C, 0x349D, 0x349E, 0x349F, 0x34A0, 0x34A1, + 0x34A2, 0x34A3, 0x34A4, 0x34A5, 0x34A6, 0x34A7, 0x34A8, 0x34A9, 0x34AA, + 0x34AB, 0x34AC, 0x34AD, 0x34AE, 0x34AF, 0x34B0, 0x34B1, 0x34B2, 0x34B3, + 0x34B4, 0x34B5, 0x34B6, 0x34B7, 0x34B8, 0x34B9, 0x34BA, 0x34BB, 0x34BC, + 0x34BD, 0x34BE, 0x34BF, 0x34C0, 0x34C1, 0x34C2, 0x34C3, 0x34C4, 0x34C5, + 0x34C6, 0x34C7, 0x34C8, 0x34C9, 0x34CA, 0x34CB, 0x34CC, 0x34CD, 0x34CE, + 0x34CF, 0x34D0, 0x34D1, 0x34D2, 0x34D3, 0x34D4, 0x34D5, 0x34D6, 0x34D7, + 0x34D8, 0x34D9, 0x34DA, 0x34DB, 0x34DC, 0x34DD, 0x34DE, 0x34DF, 0x34E0, + 0x34E1, 0x34E2, 0x34E3, 0x34E4, 0x34E5, 0x34E6, 0x34E7, 0x34E8, 0x34E9, + 0x34EA, 0x34EB, 0x34EC, 0x34ED, 0x34EE, 0x34EF, 0x34F0, 0x34F1, 0x34F2, + 0x34F3, 0x34F4, 0x34F5, 0x34F6, 0x34F7, 0x34F8, 0x34F9, 0x34FA, 0x34FB, + 0x34FC, 0x34FD, 0x34FE, 0x34FF, 0x3500, 0x3501, 0x3502, 0x3503, 0x3504, + 0x3505, 0x3506, 0x3507, 0x3508, 0x3509, 0x350A, 0x350B, 0x350C, 0x350D, + 0x350E, 0x350F, 0x3510, 0x3511, 0x3512, 0x3513, 0x3514, 0x3515, 0x3516, + 0x3517, 0x3518, 0x3519, 0x351A, 0x351B, 0x351C, 0x351D, 0x351E, 0x351F, + 0x3520, 0x3521, 0x3522, 0x3523, 0x3524, 0x3525, 0x3526, 0x3527, 0x3528, + 0x3529, 0x352A, 0x352B, 0x352C, 0x352D, 0x352E, 0x352F, 0x3530, 0x3531, + 0x3532, 0x3533, 0x3534, 0x3535, 0x3536, 0x3537, 0x3538, 0x3539, 0x353A, + 0x353B, 0x353C, 0x353D, 0x353E, 0x353F, 0x3540, 0x3541, 0x3542, 0x3543, + 0x3544, 0x3545, 0x3546, 0x3547, 0x3548, 0x3549, 0x354A, 0x354B, 0x354C, + 0x354D, 0x354E, 0x354F, 0x3550, 0x3551, 0x3552, 0x3553, 0x3554, 0x3555, + 0x3556, 0x3557, 0x3558, 0x3559, 0x355A, 0x355B, 0x355C, 0x355D, 0x355E, + 0x355F, 0x3560, 0x3561, 0x3562, 0x3563, 0x3564, 0x3565, 0x3566, 0x3567, + 0x3568, 0x3569, 0x356A, 0x356B, 0x356C, 0x356D, 0x356E, 0x356F, 0x3570, + 0x3571, 0x3572, 0x3573, 0x3574, 0x3575, 0x3576, 0x3577, 0x3578, 0x3579, + 0x357A, 0x357B, 0x357C, 0x357D, 0x357E, 0x357F, 0x3580, 0x3581, 0x3582, + 0x3583, 0x3584, 0x3585, 0x3586, 0x3587, 0x3588, 0x3589, 0x358A, 0x358B, + 0x358C, 0x358D, 0x358E, 0x358F, 0x3590, 0x3591, 0x3592, 0x3593, 0x3594, + 0x3595, 0x3596, 0x3597, 0x3598, 0x3599, 0x359A, 0x359B, 0x359C, 0x359D, + 0x359F, 0x35A0, 0x35A1, 0x35A2, 0x35A3, 0x35A4, 0x35A5, 0x35A6, 0x35A7, + 0x35A8, 0x35A9, 0x35AA, 0x35AB, 0x35AC, 0x35AD, 0x35AE, 0x35AF, 0x35B0, + 0x35B1, 0x35B2, 0x35B3, 0x35B4, 0x35B5, 0x35B6, 0x35B7, 0x35B8, 0x35B9, + 0x35BA, 0x35BB, 0x35BC, 0x35BD, 0x35BE, 0x35BF, 0x35C0, 0x35C1, 0x35C2, + 0x35C3, 0x35C4, 0x35C5, 0x35C6, 0x35C7, 0x35C8, 0x35C9, 0x35CA, 0x35CB, + 0x35CC, 0x35CD, 0x35CE, 0x35CF, 0x35D0, 0x35D1, 0x35D2, 0x35D3, 0x35D4, + 0x35D5, 0x35D6, 0x35D7, 0x35D8, 0x35D9, 0x35DA, 0x35DB, 0x35DC, 0x35DD, + 0x35DE, 0x35DF, 0x35E0, 0x35E1, 0x35E2, 0x35E3, 0x35E4, 0x35E5, 0x35E6, + 0x35E7, 0x35E8, 0x35E9, 0x35EA, 0x35EB, 0x35EC, 0x35ED, 0x35EE, 0x35EF, + 0x35F0, 0x35F1, 0x35F2, 0x35F3, 0x35F4, 0x35F5, 0x35F6, 0x35F7, 0x35F8, + 0x35F9, 0x35FA, 0x35FB, 0x35FC, 0x35FD, 0x35FE, 0x35FF, 0x3600, 0x3601, + 0x3602, 0x3603, 0x3604, 0x3605, 0x3606, 0x3607, 0x3608, 0x3609, 0x360A, + 0x360B, 0x360C, 0x360D, 0x360F, 0x3610, 0x3611, 0x3612, 0x3613, 0x3614, + 0x3615, 0x3616, 0x3617, 0x3618, 0x3619, 0x361B, 0x361C, 0x361D, 0x361E, + 0x361F, 0x3620, 0x3621, 0x3622, 0x3623, 0x3624, 0x3625, 0x3626, 0x3627, + 0x3628, 0x3629, 0x362A, 0x362B, 0x362C, 0x362D, 0x362E, 0x362F, 0x3630, + 0x3631, 0x3632, 0x3633, 0x3634, 0x3635, 0x3636, 0x3637, 0x3638, 0x3639, + 0x363A, 0x363B, 0x363C, 0x363D, 0x363E, 0x363F, 0x3640, 0x3641, 0x3642, + 0x3643, 0x3644, 0x3645, 0x3646, 0x3647, 0x3648, 0x3649, 0x364A, 0x364B, + 0x364C, 0x364D, 0x364E, 0x364F, 0x3650, 0x3651, 0x3652, 0x3653, 0x3654, + 0x3655, 0x3656, 0x3657, 0x3658, 0x3659, 0x365A, 0x365B, 0x365C, 0x365D, + 0x365E, 0x365F, 0x3660, 0x3661, 0x3662, 0x3663, 0x3664, 0x3665, 0x3666, + 0x3667, 0x3668, 0x3669, 0x366A, 0x366B, 0x366C, 0x366D, 0x366E, 0x366F, + 0x3670, 0x3671, 0x3672, 0x3673, 0x3674, 0x3675, 0x3676, 0x3677, 0x3678, + 0x3679, 0x367A, 0x367B, 0x367C, 0x367D, 0x367E, 0x367F, 0x3680, 0x3681, + 0x3682, 0x3683, 0x3684, 0x3685, 0x3686, 0x3687, 0x3688, 0x3689, 0x368A, + 0x368B, 0x368C, 0x368D, 0x368E, 0x368F, 0x3690, 0x3691, 0x3692, 0x3693, + 0x3694, 0x3695, 0x3696, 0x3697, 0x3698, 0x3699, 0x369A, 0x369B, 0x369C, + 0x369D, 0x369E, 0x369F, 0x36A0, 0x36A1, 0x36A2, 0x36A3, 0x36A4, 0x36A5, + 0x36A6, 0x36A7, 0x36A8, 0x36A9, 0x36AA, 0x36AB, 0x36AC, 0x36AD, 0x36AE, + 0x36AF, 0x36B0, 0x36B1, 0x36B2, 0x36B3, 0x36B4, 0x36B5, 0x36B6, 0x36B7, + 0x36B8, 0x36B9, 0x36BA, 0x36BB, 0x36BC, 0x36BD, 0x36BE, 0x36BF, 0x36C0, + 0x36C1, 0x36C2, 0x36C3, 0x36C4, 0x36C5, 0x36C6, 0x36C7, 0x36C8, 0x36C9, + 0x36CA, 0x36CB, 0x36CC, 0x36CD, 0x36CE, 0x36CF, 0x36D0, 0x36D1, 0x36D2, + 0x36D3, 0x36D4, 0x36D5, 0x36D6, 0x36D7, 0x36D8, 0x36D9, 0x36DA, 0x36DB, + 0x36DC, 0x36DD, 0x36DE, 0x36DF, 0x36E0, 0x36E1, 0x36E2, 0x36E3, 0x36E4, + 0x36E5, 0x36E6, 0x36E7, 0x36E8, 0x36E9, 0x36EA, 0x36EB, 0x36EC, 0x36ED, + 0x36EE, 0x36EF, 0x36F0, 0x36F1, 0x36F2, 0x36F3, 0x36F4, 0x36F5, 0x36F6, + 0x36F7, 0x36F8, 0x36F9, 0x36FA, 0x36FB, 0x36FC, 0x36FD, 0x36FE, 0x36FF, + 0x3700, 0x3701, 0x3702, 0x3703, 0x3704, 0x3705, 0x3706, 0x3707, 0x3708, + 0x3709, 0x370A, 0x370B, 0x370C, 0x370D, 0x370E, 0x370F, 0x3710, 0x3711, + 0x3712, 0x3713, 0x3714, 0x3715, 0x3716, 0x3717, 0x3718, 0x3719, 0x371A, + 0x371B, 0x371C, 0x371D, 0x371E, 0x371F, 0x3720, 0x3721, 0x3722, 0x3723, + 0x3724, 0x3725, 0x3726, 0x3727, 0x3728, 0x3729, 0x372A, 0x372B, 0x372C, + 0x372D, 0x372E, 0x372F, 0x3730, 0x3731, 0x3732, 0x3733, 0x3734, 0x3735, + 0x3736, 0x3737, 0x3738, 0x3739, 0x373A, 0x373B, 0x373C, 0x373D, 0x373E, + 0x373F, 0x3740, 0x3741, 0x3742, 0x3743, 0x3744, 0x3745, 0x3746, 0x3747, + 0x3748, 0x3749, 0x374A, 0x374B, 0x374C, 0x374D, 0x374E, 0x374F, 0x3750, + 0x3751, 0x3752, 0x3753, 0x3754, 0x3755, 0x3756, 0x3757, 0x3758, 0x3759, + 0x375A, 0x375B, 0x375C, 0x375D, 0x375E, 0x375F, 0x3760, 0x3761, 0x3762, + 0x3763, 0x3764, 0x3765, 0x3766, 0x3767, 0x3768, 0x3769, 0x376A, 0x376B, + 0x376C, 0x376D, 0x376E, 0x376F, 0x3770, 0x3771, 0x3772, 0x3773, 0x3774, + 0x3775, 0x3776, 0x3777, 0x3778, 0x3779, 0x377A, 0x377B, 0x377C, 0x377D, + 0x377E, 0x377F, 0x3780, 0x3781, 0x3782, 0x3783, 0x3784, 0x3785, 0x3786, + 0x3787, 0x3788, 0x3789, 0x378A, 0x378B, 0x378C, 0x378D, 0x378E, 0x378F, + 0x3790, 0x3791, 0x3792, 0x3793, 0x3794, 0x3795, 0x3796, 0x3797, 0x3798, + 0x3799, 0x379A, 0x379B, 0x379C, 0x379D, 0x379E, 0x379F, 0x37A0, 0x37A1, + 0x37A2, 0x37A3, 0x37A4, 0x37A5, 0x37A6, 0x37A7, 0x37A8, 0x37A9, 0x37AA, + 0x37AB, 0x37AC, 0x37AD, 0x37AE, 0x37AF, 0x37B0, 0x37B1, 0x37B2, 0x37B3, + 0x37B4, 0x37B5, 0x37B6, 0x37B7, 0x37B8, 0x37B9, 0x37BA, 0x37BB, 0x37BC, + 0x37BD, 0x37BE, 0x37BF, 0x37C0, 0x37C1, 0x37C2, 0x37C3, 0x37C4, 0x37C5, + 0x37C6, 0x37C7, 0x37C8, 0x37C9, 0x37CA, 0x37CB, 0x37CC, 0x37CD, 0x37CE, + 0x37CF, 0x37D0, 0x37D1, 0x37D2, 0x37D3, 0x37D4, 0x37D5, 0x37D6, 0x37D7, + 0x37D8, 0x37D9, 0x37DA, 0x37DB, 0x37DC, 0x37DD, 0x37DE, 0x37DF, 0x37E0, + 0x37E1, 0x37E2, 0x37E3, 0x37E4, 0x37E5, 0x37E6, 0x37E7, 0x37E8, 0x37E9, + 0x37EA, 0x37EB, 0x37EC, 0x37ED, 0x37EE, 0x37EF, 0x37F0, 0x37F1, 0x37F2, + 0x37F3, 0x37F4, 0x37F5, 0x37F6, 0x37F7, 0x37F8, 0x37F9, 0x37FA, 0x37FB, + 0x37FC, 0x37FD, 0x37FE, 0x37FF, 0x3800, 0x3801, 0x3802, 0x3803, 0x3804, + 0x3805, 0x3806, 0x3807, 0x3808, 0x3809, 0x380A, 0x380B, 0x380C, 0x380D, + 0x380E, 0x380F, 0x3810, 0x3811, 0x3812, 0x3813, 0x3814, 0x3815, 0x3816, + 0x3817, 0x3818, 0x3819, 0x381A, 0x381B, 0x381C, 0x381D, 0x381E, 0x381F, + 0x3820, 0x3821, 0x3822, 0x3823, 0x3824, 0x3825, 0x3826, 0x3827, 0x3828, + 0x3829, 0x382A, 0x382B, 0x382C, 0x382D, 0x382E, 0x382F, 0x3830, 0x3831, + 0x3832, 0x3833, 0x3834, 0x3835, 0x3836, 0x3837, 0x3838, 0x3839, 0x383A, + 0x383B, 0x383C, 0x383D, 0x383E, 0x383F, 0x3840, 0x3841, 0x3842, 0x3843, + 0x3844, 0x3845, 0x3846, 0x3847, 0x3848, 0x3849, 0x384A, 0x384B, 0x384C, + 0x384D, 0x384E, 0x384F, 0x3850, 0x3851, 0x3852, 0x3853, 0x3854, 0x3855, + 0x3856, 0x3857, 0x3858, 0x3859, 0x385A, 0x385B, 0x385C, 0x385D, 0x385E, + 0x385F, 0x3860, 0x3861, 0x3862, 0x3863, 0x3864, 0x3865, 0x3866, 0x3867, + 0x3868, 0x3869, 0x386A, 0x386B, 0x386C, 0x386D, 0x386E, 0x386F, 0x3870, + 0x3871, 0x3872, 0x3873, 0x3874, 0x3875, 0x3876, 0x3877, 0x3878, 0x3879, + 0x387A, 0x387B, 0x387C, 0x387D, 0x387E, 0x387F, 0x3880, 0x3881, 0x3882, + 0x3883, 0x3884, 0x3885, 0x3886, 0x3887, 0x3888, 0x3889, 0x388A, 0x388B, + 0x388C, 0x388D, 0x388E, 0x388F, 0x3890, 0x3891, 0x3892, 0x3893, 0x3894, + 0x3895, 0x3896, 0x3897, 0x3898, 0x3899, 0x389A, 0x389B, 0x389C, 0x389D, + 0x389E, 0x389F, 0x38A0, 0x38A1, 0x38A2, 0x38A3, 0x38A4, 0x38A5, 0x38A6, + 0x38A7, 0x38A8, 0x38A9, 0x38AA, 0x38AB, 0x38AC, 0x38AD, 0x38AE, 0x38AF, + 0x38B0, 0x38B1, 0x38B2, 0x38B3, 0x38B4, 0x38B5, 0x38B6, 0x38B7, 0x38B8, + 0x38B9, 0x38BA, 0x38BB, 0x38BC, 0x38BD, 0x38BE, 0x38BF, 0x38C0, 0x38C1, + 0x38C2, 0x38C3, 0x38C4, 0x38C5, 0x38C6, 0x38C7, 0x38C8, 0x38C9, 0x38CA, + 0x38CB, 0x38CC, 0x38CD, 0x38CE, 0x38CF, 0x38D0, 0x38D1, 0x38D2, 0x38D3, + 0x38D4, 0x38D5, 0x38D6, 0x38D7, 0x38D8, 0x38D9, 0x38DA, 0x38DB, 0x38DC, + 0x38DD, 0x38DE, 0x38DF, 0x38E0, 0x38E1, 0x38E2, 0x38E3, 0x38E4, 0x38E5, + 0x38E6, 0x38E7, 0x38E8, 0x38E9, 0x38EA, 0x38EB, 0x38EC, 0x38ED, 0x38EE, + 0x38EF, 0x38F0, 0x38F1, 0x38F2, 0x38F3, 0x38F4, 0x38F5, 0x38F6, 0x38F7, + 0x38F8, 0x38F9, 0x38FA, 0x38FB, 0x38FC, 0x38FD, 0x38FE, 0x38FF, 0x3900, + 0x3901, 0x3902, 0x3903, 0x3904, 0x3905, 0x3906, 0x3907, 0x3908, 0x3909, + 0x390A, 0x390B, 0x390C, 0x390D, 0x390E, 0x390F, 0x3910, 0x3911, 0x3912, + 0x3913, 0x3914, 0x3915, 0x3916, 0x3917, 0x3919, 0x391A, 0x391B, 0x391C, + 0x391D, 0x391E, 0x391F, 0x3920, 0x3921, 0x3922, 0x3923, 0x3924, 0x3925, + 0x3926, 0x3927, 0x3928, 0x3929, 0x392A, 0x392B, 0x392C, 0x392D, 0x392E, + 0x392F, 0x3930, 0x3931, 0x3932, 0x3933, 0x3934, 0x3935, 0x3936, 0x3937, + 0x3938, 0x3939, 0x393A, 0x393B, 0x393C, 0x393D, 0x393E, 0x393F, 0x3940, + 0x3941, 0x3942, 0x3943, 0x3944, 0x3945, 0x3946, 0x3947, 0x3948, 0x3949, + 0x394A, 0x394B, 0x394C, 0x394D, 0x394E, 0x394F, 0x3950, 0x3951, 0x3952, + 0x3953, 0x3954, 0x3955, 0x3956, 0x3957, 0x3958, 0x3959, 0x395A, 0x395B, + 0x395C, 0x395D, 0x395E, 0x395F, 0x3960, 0x3961, 0x3962, 0x3963, 0x3964, + 0x3965, 0x3966, 0x3967, 0x3968, 0x3969, 0x396A, 0x396B, 0x396C, 0x396D, + 0x396F, 0x3970, 0x3971, 0x3972, 0x3973, 0x3974, 0x3975, 0x3976, 0x3977, + 0x3978, 0x3979, 0x397A, 0x397B, 0x397C, 0x397D, 0x397E, 0x397F, 0x3980, + 0x3981, 0x3982, 0x3983, 0x3984, 0x3985, 0x3986, 0x3987, 0x3988, 0x3989, + 0x398A, 0x398B, 0x398C, 0x398D, 0x398E, 0x398F, 0x3990, 0x3991, 0x3992, + 0x3993, 0x3994, 0x3995, 0x3996, 0x3997, 0x3998, 0x3999, 0x399A, 0x399B, + 0x399C, 0x399D, 0x399E, 0x399F, 0x39A0, 0x39A1, 0x39A2, 0x39A3, 0x39A4, + 0x39A5, 0x39A6, 0x39A7, 0x39A8, 0x39A9, 0x39AA, 0x39AB, 0x39AC, 0x39AD, + 0x39AE, 0x39AF, 0x39B0, 0x39B1, 0x39B2, 0x39B3, 0x39B4, 0x39B5, 0x39B6, + 0x39B7, 0x39B8, 0x39B9, 0x39BA, 0x39BB, 0x39BC, 0x39BD, 0x39BE, 0x39BF, + 0x39C0, 0x39C1, 0x39C2, 0x39C3, 0x39C4, 0x39C5, 0x39C6, 0x39C7, 0x39C8, + 0x39C9, 0x39CA, 0x39CB, 0x39CC, 0x39CD, 0x39CE, 0x39D1, 0x39D2, 0x39D3, + 0x39D4, 0x39D5, 0x39D6, 0x39D7, 0x39D8, 0x39D9, 0x39DA, 0x39DB, 0x39DC, + 0x39DD, 0x39DE, 0x39E0, 0x39E1, 0x39E2, 0x39E3, 0x39E4, 0x39E5, 0x39E6, + 0x39E7, 0x39E8, 0x39E9, 0x39EA, 0x39EB, 0x39EC, 0x39ED, 0x39EE, 0x39EF, + 0x39F0, 0x39F1, 0x39F2, 0x39F3, 0x39F4, 0x39F5, 0x39F6, 0x39F7, 0x39F8, + 0x39F9, 0x39FA, 0x39FB, 0x39FC, 0x39FD, 0x39FE, 0x39FF, 0x3A00, 0x3A01, + 0x3A02, 0x3A03, 0x3A04, 0x3A05, 0x3A06, 0x3A07, 0x3A08, 0x3A09, 0x3A0A, + 0x3A0B, 0x3A0C, 0x3A0D, 0x3A0E, 0x3A0F, 0x3A10, 0x3A11, 0x3A12, 0x3A13, + 0x3A14, 0x3A15, 0x3A16, 0x3A17, 0x3A18, 0x3A19, 0x3A1A, 0x3A1B, 0x3A1C, + 0x3A1D, 0x3A1E, 0x3A1F, 0x3A20, 0x3A21, 0x3A22, 0x3A23, 0x3A24, 0x3A25, + 0x3A26, 0x3A27, 0x3A28, 0x3A29, 0x3A2A, 0x3A2B, 0x3A2C, 0x3A2D, 0x3A2E, + 0x3A2F, 0x3A30, 0x3A31, 0x3A32, 0x3A33, 0x3A34, 0x3A35, 0x3A36, 0x3A37, + 0x3A38, 0x3A39, 0x3A3A, 0x3A3B, 0x3A3C, 0x3A3D, 0x3A3E, 0x3A3F, 0x3A40, + 0x3A41, 0x3A42, 0x3A43, 0x3A44, 0x3A45, 0x3A46, 0x3A47, 0x3A48, 0x3A49, + 0x3A4A, 0x3A4B, 0x3A4C, 0x3A4D, 0x3A4E, 0x3A4F, 0x3A50, 0x3A51, 0x3A52, + 0x3A53, 0x3A54, 0x3A55, 0x3A56, 0x3A57, 0x3A58, 0x3A59, 0x3A5A, 0x3A5B, + 0x3A5C, 0x3A5D, 0x3A5E, 0x3A5F, 0x3A60, 0x3A61, 0x3A62, 0x3A63, 0x3A64, + 0x3A65, 0x3A66, 0x3A67, 0x3A68, 0x3A69, 0x3A6A, 0x3A6B, 0x3A6C, 0x3A6D, + 0x3A6E, 0x3A6F, 0x3A70, 0x3A71, 0x3A72, 0x3A74, 0x3A75, 0x3A76, 0x3A77, + 0x3A78, 0x3A79, 0x3A7A, 0x3A7B, 0x3A7C, 0x3A7D, 0x3A7E, 0x3A7F, 0x3A80, + 0x3A81, 0x3A82, 0x3A83, 0x3A84, 0x3A85, 0x3A86, 0x3A87, 0x3A88, 0x3A89, + 0x3A8A, 0x3A8B, 0x3A8C, 0x3A8D, 0x3A8E, 0x3A8F, 0x3A90, 0x3A91, 0x3A92, + 0x3A93, 0x3A94, 0x3A95, 0x3A96, 0x3A97, 0x3A98, 0x3A99, 0x3A9A, 0x3A9B, + 0x3A9C, 0x3A9D, 0x3A9E, 0x3A9F, 0x3AA0, 0x3AA1, 0x3AA2, 0x3AA3, 0x3AA4, + 0x3AA5, 0x3AA6, 0x3AA7, 0x3AA8, 0x3AA9, 0x3AAA, 0x3AAB, 0x3AAC, 0x3AAD, + 0x3AAE, 0x3AAF, 0x3AB0, 0x3AB1, 0x3AB2, 0x3AB3, 0x3AB4, 0x3AB5, 0x3AB6, + 0x3AB7, 0x3AB8, 0x3AB9, 0x3ABA, 0x3ABB, 0x3ABC, 0x3ABD, 0x3ABE, 0x3ABF, + 0x3AC0, 0x3AC1, 0x3AC2, 0x3AC3, 0x3AC4, 0x3AC5, 0x3AC6, 0x3AC7, 0x3AC8, + 0x3AC9, 0x3ACA, 0x3ACB, 0x3ACC, 0x3ACD, 0x3ACE, 0x3ACF, 0x3AD0, 0x3AD1, + 0x3AD2, 0x3AD3, 0x3AD4, 0x3AD5, 0x3AD6, 0x3AD7, 0x3AD8, 0x3AD9, 0x3ADA, + 0x3ADB, 0x3ADC, 0x3ADD, 0x3ADE, 0x3ADF, 0x3AE0, 0x3AE1, 0x3AE2, 0x3AE3, + 0x3AE4, 0x3AE5, 0x3AE6, 0x3AE7, 0x3AE8, 0x3AE9, 0x3AEA, 0x3AEB, 0x3AEC, + 0x3AED, 0x3AEE, 0x3AEF, 0x3AF0, 0x3AF1, 0x3AF2, 0x3AF3, 0x3AF4, 0x3AF5, + 0x3AF6, 0x3AF7, 0x3AF8, 0x3AF9, 0x3AFA, 0x3AFB, 0x3AFC, 0x3AFD, 0x3AFE, + 0x3AFF, 0x3B00, 0x3B01, 0x3B02, 0x3B03, 0x3B04, 0x3B05, 0x3B06, 0x3B07, + 0x3B08, 0x3B09, 0x3B0A, 0x3B0B, 0x3B0C, 0x3B0D, 0x3B0E, 0x3B0F, 0x3B10, + 0x3B11, 0x3B12, 0x3B13, 0x3B14, 0x3B15, 0x3B16, 0x3B17, 0x3B18, 0x3B19, + 0x3B1A, 0x3B1B, 0x3B1C, 0x3B1D, 0x3B1E, 0x3B1F, 0x3B20, 0x3B21, 0x3B22, + 0x3B23, 0x3B24, 0x3B25, 0x3B26, 0x3B27, 0x3B28, 0x3B29, 0x3B2A, 0x3B2B, + 0x3B2C, 0x3B2D, 0x3B2E, 0x3B2F, 0x3B30, 0x3B31, 0x3B32, 0x3B33, 0x3B34, + 0x3B35, 0x3B36, 0x3B37, 0x3B38, 0x3B39, 0x3B3A, 0x3B3B, 0x3B3C, 0x3B3D, + 0x3B3E, 0x3B3F, 0x3B40, 0x3B41, 0x3B42, 0x3B43, 0x3B44, 0x3B45, 0x3B46, + 0x3B47, 0x3B48, 0x3B49, 0x3B4A, 0x3B4B, 0x3B4C, 0x3B4D, 0x3B4F, 0x3B50, + 0x3B51, 0x3B52, 0x3B53, 0x3B54, 0x3B55, 0x3B56, 0x3B57, 0x3B58, 0x3B59, + 0x3B5A, 0x3B5B, 0x3B5C, 0x3B5D, 0x3B5E, 0x3B5F, 0x3B60, 0x3B61, 0x3B62, + 0x3B63, 0x3B64, 0x3B65, 0x3B66, 0x3B67, 0x3B68, 0x3B69, 0x3B6A, 0x3B6B, + 0x3B6C, 0x3B6D, 0x3B6E, 0x3B6F, 0x3B70, 0x3B71, 0x3B72, 0x3B73, 0x3B74, + 0x3B75, 0x3B76, 0x3B77, 0x3B78, 0x3B79, 0x3B7A, 0x3B7B, 0x3B7C, 0x3B7D, + 0x3B7E, 0x3B7F, 0x3B80, 0x3B81, 0x3B82, 0x3B83, 0x3B84, 0x3B85, 0x3B86, + 0x3B87, 0x3B88, 0x3B89, 0x3B8A, 0x3B8B, 0x3B8C, 0x3B8D, 0x3B8E, 0x3B8F, + 0x3B90, 0x3B91, 0x3B92, 0x3B93, 0x3B94, 0x3B95, 0x3B96, 0x3B97, 0x3B98, + 0x3B99, 0x3B9A, 0x3B9B, 0x3B9C, 0x3B9D, 0x3B9E, 0x3B9F, 0x3BA0, 0x3BA1, + 0x3BA2, 0x3BA3, 0x3BA4, 0x3BA5, 0x3BA6, 0x3BA7, 0x3BA8, 0x3BA9, 0x3BAA, + 0x3BAB, 0x3BAC, 0x3BAD, 0x3BAE, 0x3BAF, 0x3BB0, 0x3BB1, 0x3BB2, 0x3BB3, + 0x3BB4, 0x3BB5, 0x3BB6, 0x3BB7, 0x3BB8, 0x3BB9, 0x3BBA, 0x3BBB, 0x3BBC, + 0x3BBD, 0x3BBE, 0x3BBF, 0x3BC0, 0x3BC1, 0x3BC2, 0x3BC3, 0x3BC4, 0x3BC5, + 0x3BC6, 0x3BC7, 0x3BC8, 0x3BC9, 0x3BCA, 0x3BCB, 0x3BCC, 0x3BCD, 0x3BCE, + 0x3BCF, 0x3BD0, 0x3BD1, 0x3BD2, 0x3BD3, 0x3BD4, 0x3BD5, 0x3BD6, 0x3BD7, + 0x3BD8, 0x3BD9, 0x3BDA, 0x3BDB, 0x3BDC, 0x3BDD, 0x3BDE, 0x3BDF, 0x3BE0, + 0x3BE1, 0x3BE2, 0x3BE3, 0x3BE4, 0x3BE5, 0x3BE6, 0x3BE7, 0x3BE8, 0x3BE9, + 0x3BEA, 0x3BEB, 0x3BEC, 0x3BED, 0x3BEE, 0x3BEF, 0x3BF0, 0x3BF1, 0x3BF2, + 0x3BF3, 0x3BF4, 0x3BF5, 0x3BF6, 0x3BF7, 0x3BF8, 0x3BF9, 0x3BFA, 0x3BFB, + 0x3BFC, 0x3BFD, 0x3BFE, 0x3BFF, 0x3C00, 0x3C01, 0x3C02, 0x3C03, 0x3C04, + 0x3C05, 0x3C06, 0x3C07, 0x3C08, 0x3C09, 0x3C0A, 0x3C0B, 0x3C0C, 0x3C0D, + 0x3C0E, 0x3C0F, 0x3C10, 0x3C11, 0x3C12, 0x3C13, 0x3C14, 0x3C15, 0x3C16, + 0x3C17, 0x3C18, 0x3C19, 0x3C1A, 0x3C1B, 0x3C1C, 0x3C1D, 0x3C1E, 0x3C1F, + 0x3C20, 0x3C21, 0x3C22, 0x3C23, 0x3C24, 0x3C25, 0x3C26, 0x3C27, 0x3C28, + 0x3C29, 0x3C2A, 0x3C2B, 0x3C2C, 0x3C2D, 0x3C2E, 0x3C2F, 0x3C30, 0x3C31, + 0x3C32, 0x3C33, 0x3C34, 0x3C35, 0x3C36, 0x3C37, 0x3C38, 0x3C39, 0x3C3A, + 0x3C3B, 0x3C3C, 0x3C3D, 0x3C3E, 0x3C3F, 0x3C40, 0x3C41, 0x3C42, 0x3C43, + 0x3C44, 0x3C45, 0x3C46, 0x3C47, 0x3C48, 0x3C49, 0x3C4A, 0x3C4B, 0x3C4C, + 0x3C4D, 0x3C4E, 0x3C4F, 0x3C50, 0x3C51, 0x3C52, 0x3C53, 0x3C54, 0x3C55, + 0x3C56, 0x3C57, 0x3C58, 0x3C59, 0x3C5A, 0x3C5B, 0x3C5C, 0x3C5D, 0x3C5E, + 0x3C5F, 0x3C60, 0x3C61, 0x3C62, 0x3C63, 0x3C64, 0x3C65, 0x3C66, 0x3C67, + 0x3C68, 0x3C69, 0x3C6A, 0x3C6B, 0x3C6C, 0x3C6D, 0x3C6F, 0x3C70, 0x3C71, + 0x3C72, 0x3C73, 0x3C74, 0x3C75, 0x3C76, 0x3C77, 0x3C78, 0x3C79, 0x3C7A, + 0x3C7B, 0x3C7C, 0x3C7D, 0x3C7E, 0x3C7F, 0x3C80, 0x3C81, 0x3C82, 0x3C83, + 0x3C84, 0x3C85, 0x3C86, 0x3C87, 0x3C88, 0x3C89, 0x3C8A, 0x3C8B, 0x3C8C, + 0x3C8D, 0x3C8E, 0x3C8F, 0x3C90, 0x3C91, 0x3C92, 0x3C93, 0x3C94, 0x3C95, + 0x3C96, 0x3C97, 0x3C98, 0x3C99, 0x3C9A, 0x3C9B, 0x3C9C, 0x3C9D, 0x3C9E, + 0x3C9F, 0x3CA0, 0x3CA1, 0x3CA2, 0x3CA3, 0x3CA4, 0x3CA5, 0x3CA6, 0x3CA7, + 0x3CA8, 0x3CA9, 0x3CAA, 0x3CAB, 0x3CAC, 0x3CAD, 0x3CAE, 0x3CAF, 0x3CB0, + 0x3CB1, 0x3CB2, 0x3CB3, 0x3CB4, 0x3CB5, 0x3CB6, 0x3CB7, 0x3CB8, 0x3CB9, + 0x3CBA, 0x3CBB, 0x3CBC, 0x3CBD, 0x3CBE, 0x3CBF, 0x3CC0, 0x3CC1, 0x3CC2, + 0x3CC3, 0x3CC4, 0x3CC5, 0x3CC6, 0x3CC7, 0x3CC8, 0x3CC9, 0x3CCA, 0x3CCB, + 0x3CCC, 0x3CCD, 0x3CCE, 0x3CCF, 0x3CD0, 0x3CD1, 0x3CD2, 0x3CD3, 0x3CD4, + 0x3CD5, 0x3CD6, 0x3CD7, 0x3CD8, 0x3CD9, 0x3CDA, 0x3CDB, 0x3CDC, 0x3CDD, + 0x3CDE, 0x3CDF, 0x3CE1, 0x3CE2, 0x3CE3, 0x3CE4, 0x3CE5, 0x3CE6, 0x3CE7, + 0x3CE8, 0x3CE9, 0x3CEA, 0x3CEB, 0x3CEC, 0x3CED, 0x3CEE, 0x3CEF, 0x3CF0, + 0x3CF1, 0x3CF2, 0x3CF3, 0x3CF4, 0x3CF5, 0x3CF6, 0x3CF7, 0x3CF8, 0x3CF9, + 0x3CFA, 0x3CFB, 0x3CFC, 0x3CFD, 0x3CFE, 0x3CFF, 0x3D00, 0x3D01, 0x3D02, + 0x3D03, 0x3D04, 0x3D05, 0x3D06, 0x3D07, 0x3D08, 0x3D09, 0x3D0A, 0x3D0B, + 0x3D0C, 0x3D0D, 0x3D0E, 0x3D0F, 0x3D10, 0x3D11, 0x3D12, 0x3D13, 0x3D14, + 0x3D15, 0x3D16, 0x3D17, 0x3D18, 0x3D19, 0x3D1A, 0x3D1B, 0x3D1C, 0x3D1D, + 0x3D1E, 0x3D1F, 0x3D20, 0x3D21, 0x3D22, 0x3D23, 0x3D24, 0x3D25, 0x3D26, + 0x3D27, 0x3D28, 0x3D29, 0x3D2A, 0x3D2B, 0x3D2C, 0x3D2D, 0x3D2E, 0x3D2F, + 0x3D30, 0x3D31, 0x3D32, 0x3D33, 0x3D34, 0x3D35, 0x3D36, 0x3D37, 0x3D38, + 0x3D39, 0x3D3A, 0x3D3B, 0x3D3C, 0x3D3D, 0x3D3E, 0x3D3F, 0x3D40, 0x3D41, + 0x3D42, 0x3D43, 0x3D44, 0x3D45, 0x3D46, 0x3D47, 0x3D48, 0x3D49, 0x3D4A, + 0x3D4B, 0x3D4C, 0x3D4D, 0x3D4E, 0x3D4F, 0x3D50, 0x3D51, 0x3D52, 0x3D53, + 0x3D54, 0x3D55, 0x3D56, 0x3D57, 0x3D58, 0x3D59, 0x3D5A, 0x3D5B, 0x3D5C, + 0x3D5D, 0x3D5E, 0x3D5F, 0x3D60, 0x3D61, 0x3D62, 0x3D63, 0x3D64, 0x3D65, + 0x3D66, 0x3D67, 0x3D68, 0x3D69, 0x3D6A, 0x3D6B, 0x3D6C, 0x3D6D, 0x3D6E, + 0x3D6F, 0x3D70, 0x3D71, 0x3D72, 0x3D73, 0x3D74, 0x3D75, 0x3D76, 0x3D77, + 0x3D78, 0x3D79, 0x3D7A, 0x3D7B, 0x3D7C, 0x3D7D, 0x3D7E, 0x3D7F, 0x3D80, + 0x3D81, 0x3D82, 0x3D83, 0x3D84, 0x3D85, 0x3D86, 0x3D87, 0x3D88, 0x3D89, + 0x3D8A, 0x3D8B, 0x3D8C, 0x3D8D, 0x3D8E, 0x3D8F, 0x3D90, 0x3D91, 0x3D92, + 0x3D93, 0x3D94, 0x3D95, 0x3D96, 0x3D97, 0x3D98, 0x3D99, 0x3D9A, 0x3D9B, + 0x3D9C, 0x3D9D, 0x3D9E, 0x3D9F, 0x3DA0, 0x3DA1, 0x3DA2, 0x3DA3, 0x3DA4, + 0x3DA5, 0x3DA6, 0x3DA7, 0x3DA8, 0x3DA9, 0x3DAA, 0x3DAB, 0x3DAC, 0x3DAD, + 0x3DAE, 0x3DAF, 0x3DB0, 0x3DB1, 0x3DB2, 0x3DB3, 0x3DB4, 0x3DB5, 0x3DB6, + 0x3DB7, 0x3DB8, 0x3DB9, 0x3DBA, 0x3DBB, 0x3DBC, 0x3DBD, 0x3DBE, 0x3DBF, + 0x3DC0, 0x3DC1, 0x3DC2, 0x3DC3, 0x3DC4, 0x3DC5, 0x3DC6, 0x3DC7, 0x3DC8, + 0x3DC9, 0x3DCA, 0x3DCB, 0x3DCC, 0x3DCD, 0x3DCE, 0x3DCF, 0x3DD0, 0x3DD1, + 0x3DD2, 0x3DD3, 0x3DD4, 0x3DD5, 0x3DD6, 0x3DD7, 0x3DD8, 0x3DD9, 0x3DDA, + 0x3DDB, 0x3DDC, 0x3DDD, 0x3DDE, 0x3DDF, 0x3DE0, 0x3DE1, 0x3DE2, 0x3DE3, + 0x3DE4, 0x3DE5, 0x3DE6, 0x3DE7, 0x3DE8, 0x3DE9, 0x3DEA, 0x3DEB, 0x3DEC, + 0x3DED, 0x3DEE, 0x3DEF, 0x3DF0, 0x3DF1, 0x3DF2, 0x3DF3, 0x3DF4, 0x3DF5, + 0x3DF6, 0x3DF7, 0x3DF8, 0x3DF9, 0x3DFA, 0x3DFB, 0x3DFC, 0x3DFD, 0x3DFE, + 0x3DFF, 0x3E00, 0x3E01, 0x3E02, 0x3E03, 0x3E04, 0x3E05, 0x3E06, 0x3E07, + 0x3E08, 0x3E09, 0x3E0A, 0x3E0B, 0x3E0C, 0x3E0D, 0x3E0E, 0x3E0F, 0x3E10, + 0x3E11, 0x3E12, 0x3E13, 0x3E14, 0x3E15, 0x3E16, 0x3E17, 0x3E18, 0x3E19, + 0x3E1A, 0x3E1B, 0x3E1C, 0x3E1D, 0x3E1E, 0x3E1F, 0x3E20, 0x3E21, 0x3E22, + 0x3E23, 0x3E24, 0x3E25, 0x3E26, 0x3E27, 0x3E28, 0x3E29, 0x3E2A, 0x3E2B, + 0x3E2C, 0x3E2D, 0x3E2E, 0x3E2F, 0x3E30, 0x3E31, 0x3E32, 0x3E33, 0x3E34, + 0x3E35, 0x3E36, 0x3E37, 0x3E38, 0x3E39, 0x3E3A, 0x3E3B, 0x3E3C, 0x3E3D, + 0x3E3E, 0x3E3F, 0x3E40, 0x3E41, 0x3E42, 0x3E43, 0x3E44, 0x3E45, 0x3E46, + 0x3E47, 0x3E48, 0x3E49, 0x3E4A, 0x3E4B, 0x3E4C, 0x3E4D, 0x3E4E, 0x3E4F, + 0x3E50, 0x3E51, 0x3E52, 0x3E53, 0x3E54, 0x3E55, 0x3E56, 0x3E57, 0x3E58, + 0x3E59, 0x3E5A, 0x3E5B, 0x3E5C, 0x3E5D, 0x3E5E, 0x3E5F, 0x3E60, 0x3E61, + 0x3E62, 0x3E63, 0x3E64, 0x3E65, 0x3E66, 0x3E67, 0x3E68, 0x3E69, 0x3E6A, + 0x3E6B, 0x3E6C, 0x3E6D, 0x3E6E, 0x3E6F, 0x3E70, 0x3E71, 0x3E72, 0x3E73, + 0x3E74, 0x3E75, 0x3E76, 0x3E77, 0x3E78, 0x3E79, 0x3E7A, 0x3E7B, 0x3E7C, + 0x3E7D, 0x3E7E, 0x3E7F, 0x3E80, 0x3E81, 0x3E82, 0x3E83, 0x3E84, 0x3E85, + 0x3E86, 0x3E87, 0x3E88, 0x3E89, 0x3E8A, 0x3E8B, 0x3E8C, 0x3E8D, 0x3E8E, + 0x3E8F, 0x3E90, 0x3E91, 0x3E92, 0x3E93, 0x3E94, 0x3E95, 0x3E96, 0x3E97, + 0x3E98, 0x3E99, 0x3E9A, 0x3E9B, 0x3E9C, 0x3E9D, 0x3E9E, 0x3E9F, 0x3EA0, + 0x3EA1, 0x3EA2, 0x3EA3, 0x3EA4, 0x3EA5, 0x3EA6, 0x3EA7, 0x3EA8, 0x3EA9, + 0x3EAA, 0x3EAB, 0x3EAC, 0x3EAD, 0x3EAE, 0x3EAF, 0x3EB0, 0x3EB1, 0x3EB2, + 0x3EB3, 0x3EB4, 0x3EB5, 0x3EB6, 0x3EB7, 0x3EB8, 0x3EB9, 0x3EBA, 0x3EBB, + 0x3EBC, 0x3EBD, 0x3EBE, 0x3EBF, 0x3EC0, 0x3EC1, 0x3EC2, 0x3EC3, 0x3EC4, + 0x3EC5, 0x3EC6, 0x3EC7, 0x3EC8, 0x3EC9, 0x3ECA, 0x3ECB, 0x3ECC, 0x3ECD, + 0x3ECE, 0x3ECF, 0x3ED0, 0x3ED1, 0x3ED2, 0x3ED3, 0x3ED4, 0x3ED5, 0x3ED6, + 0x3ED7, 0x3ED8, 0x3ED9, 0x3EDA, 0x3EDB, 0x3EDC, 0x3EDD, 0x3EDE, 0x3EDF, + 0x3EE0, 0x3EE1, 0x3EE2, 0x3EE3, 0x3EE4, 0x3EE5, 0x3EE6, 0x3EE7, 0x3EE8, + 0x3EE9, 0x3EEA, 0x3EEB, 0x3EEC, 0x3EED, 0x3EEE, 0x3EEF, 0x3EF0, 0x3EF1, + 0x3EF2, 0x3EF3, 0x3EF4, 0x3EF5, 0x3EF6, 0x3EF7, 0x3EF8, 0x3EF9, 0x3EFA, + 0x3EFB, 0x3EFC, 0x3EFD, 0x3EFE, 0x3EFF, 0x3F00, 0x3F01, 0x3F02, 0x3F03, + 0x3F04, 0x3F05, 0x3F06, 0x3F07, 0x3F08, 0x3F09, 0x3F0A, 0x3F0B, 0x3F0C, + 0x3F0D, 0x3F0E, 0x3F0F, 0x3F10, 0x3F11, 0x3F12, 0x3F13, 0x3F14, 0x3F15, + 0x3F16, 0x3F17, 0x3F18, 0x3F19, 0x3F1A, 0x3F1B, 0x3F1C, 0x3F1D, 0x3F1E, + 0x3F1F, 0x3F20, 0x3F21, 0x3F22, 0x3F23, 0x3F24, 0x3F25, 0x3F26, 0x3F27, + 0x3F28, 0x3F29, 0x3F2A, 0x3F2B, 0x3F2C, 0x3F2D, 0x3F2E, 0x3F2F, 0x3F30, + 0x3F31, 0x3F32, 0x3F33, 0x3F34, 0x3F35, 0x3F36, 0x3F37, 0x3F38, 0x3F39, + 0x3F3A, 0x3F3B, 0x3F3C, 0x3F3D, 0x3F3E, 0x3F3F, 0x3F40, 0x3F41, 0x3F42, + 0x3F43, 0x3F44, 0x3F45, 0x3F46, 0x3F47, 0x3F48, 0x3F49, 0x3F4A, 0x3F4B, + 0x3F4C, 0x3F4D, 0x3F4E, 0x3F4F, 0x3F50, 0x3F51, 0x3F52, 0x3F53, 0x3F54, + 0x3F55, 0x3F56, 0x3F57, 0x3F58, 0x3F59, 0x3F5A, 0x3F5B, 0x3F5C, 0x3F5D, + 0x3F5E, 0x3F5F, 0x3F60, 0x3F61, 0x3F62, 0x3F63, 0x3F64, 0x3F65, 0x3F66, + 0x3F67, 0x3F68, 0x3F69, 0x3F6A, 0x3F6B, 0x3F6C, 0x3F6D, 0x3F6E, 0x3F6F, + 0x3F70, 0x3F71, 0x3F72, 0x3F73, 0x3F74, 0x3F75, 0x3F76, 0x3F77, 0x3F78, + 0x3F79, 0x3F7A, 0x3F7B, 0x3F7C, 0x3F7D, 0x3F7E, 0x3F7F, 0x3F80, 0x3F81, + 0x3F82, 0x3F83, 0x3F84, 0x3F85, 0x3F86, 0x3F87, 0x3F88, 0x3F89, 0x3F8A, + 0x3F8B, 0x3F8C, 0x3F8D, 0x3F8E, 0x3F8F, 0x3F90, 0x3F91, 0x3F92, 0x3F93, + 0x3F94, 0x3F95, 0x3F96, 0x3F97, 0x3F98, 0x3F99, 0x3F9A, 0x3F9B, 0x3F9C, + 0x3F9D, 0x3F9E, 0x3F9F, 0x3FA0, 0x3FA1, 0x3FA2, 0x3FA3, 0x3FA4, 0x3FA5, + 0x3FA6, 0x3FA7, 0x3FA8, 0x3FA9, 0x3FAA, 0x3FAB, 0x3FAC, 0x3FAD, 0x3FAE, + 0x3FAF, 0x3FB0, 0x3FB1, 0x3FB2, 0x3FB3, 0x3FB4, 0x3FB5, 0x3FB6, 0x3FB7, + 0x3FB8, 0x3FB9, 0x3FBA, 0x3FBB, 0x3FBC, 0x3FBD, 0x3FBE, 0x3FBF, 0x3FC0, + 0x3FC1, 0x3FC2, 0x3FC3, 0x3FC4, 0x3FC5, 0x3FC6, 0x3FC7, 0x3FC8, 0x3FC9, + 0x3FCA, 0x3FCB, 0x3FCC, 0x3FCD, 0x3FCE, 0x3FCF, 0x3FD0, 0x3FD1, 0x3FD2, + 0x3FD3, 0x3FD4, 0x3FD5, 0x3FD6, 0x3FD7, 0x3FD8, 0x3FD9, 0x3FDA, 0x3FDB, + 0x3FDC, 0x3FDD, 0x3FDE, 0x3FDF, 0x3FE0, 0x3FE1, 0x3FE2, 0x3FE3, 0x3FE4, + 0x3FE5, 0x3FE6, 0x3FE7, 0x3FE8, 0x3FE9, 0x3FEA, 0x3FEB, 0x3FEC, 0x3FED, + 0x3FEE, 0x3FEF, 0x3FF0, 0x3FF1, 0x3FF2, 0x3FF3, 0x3FF4, 0x3FF5, 0x3FF6, + 0x3FF7, 0x3FF8, 0x3FF9, 0x3FFA, 0x3FFB, 0x3FFC, 0x3FFD, 0x3FFE, 0x3FFF, + 0x4000, 0x4001, 0x4002, 0x4003, 0x4004, 0x4005, 0x4006, 0x4007, 0x4008, + 0x4009, 0x400A, 0x400B, 0x400C, 0x400D, 0x400E, 0x400F, 0x4010, 0x4011, + 0x4012, 0x4013, 0x4014, 0x4015, 0x4016, 0x4017, 0x4018, 0x4019, 0x401A, + 0x401B, 0x401C, 0x401D, 0x401E, 0x401F, 0x4020, 0x4021, 0x4022, 0x4023, + 0x4024, 0x4025, 0x4026, 0x4027, 0x4028, 0x4029, 0x402A, 0x402B, 0x402C, + 0x402D, 0x402E, 0x402F, 0x4030, 0x4031, 0x4032, 0x4033, 0x4034, 0x4035, + 0x4036, 0x4037, 0x4038, 0x4039, 0x403A, 0x403B, 0x403C, 0x403D, 0x403E, + 0x403F, 0x4040, 0x4041, 0x4042, 0x4043, 0x4044, 0x4045, 0x4046, 0x4047, + 0x4048, 0x4049, 0x404A, 0x404B, 0x404C, 0x404D, 0x404E, 0x404F, 0x4050, + 0x4051, 0x4052, 0x4053, 0x4054, 0x4055, 0x4057, 0x4058, 0x4059, 0x405A, + 0x405B, 0x405C, 0x405D, 0x405E, 0x405F, 0x4060, 0x4061, 0x4062, 0x4063, + 0x4064, 0x4065, 0x4066, 0x4067, 0x4068, 0x4069, 0x406A, 0x406B, 0x406C, + 0x406D, 0x406E, 0x406F, 0x4070, 0x4071, 0x4072, 0x4073, 0x4074, 0x4075, + 0x4076, 0x4077, 0x4078, 0x4079, 0x407A, 0x407B, 0x407C, 0x407D, 0x407E, + 0x407F, 0x4080, 0x4081, 0x4082, 0x4083, 0x4084, 0x4085, 0x4086, 0x4087, + 0x4088, 0x4089, 0x408A, 0x408B, 0x408C, 0x408D, 0x408E, 0x408F, 0x4090, + 0x4091, 0x4092, 0x4093, 0x4094, 0x4095, 0x4096, 0x4097, 0x4098, 0x4099, + 0x409A, 0x409B, 0x409C, 0x409D, 0x409E, 0x409F, 0x40A0, 0x40A1, 0x40A2, + 0x40A3, 0x40A4, 0x40A5, 0x40A6, 0x40A7, 0x40A8, 0x40A9, 0x40AA, 0x40AB, + 0x40AC, 0x40AD, 0x40AE, 0x40AF, 0x40B0, 0x40B1, 0x40B2, 0x40B3, 0x40B4, + 0x40B5, 0x40B6, 0x40B7, 0x40B8, 0x40B9, 0x40BA, 0x40BB, 0x40BC, 0x40BD, + 0x40BE, 0x40BF, 0x40C0, 0x40C1, 0x40C2, 0x40C3, 0x40C4, 0x40C5, 0x40C6, + 0x40C7, 0x40C8, 0x40C9, 0x40CA, 0x40CB, 0x40CC, 0x40CD, 0x40CE, 0x40CF, + 0x40D0, 0x40D1, 0x40D2, 0x40D3, 0x40D4, 0x40D5, 0x40D6, 0x40D7, 0x40D8, + 0x40D9, 0x40DA, 0x40DB, 0x40DC, 0x40DD, 0x40DE, 0x40DF, 0x40E0, 0x40E1, + 0x40E2, 0x40E3, 0x40E4, 0x40E5, 0x40E6, 0x40E7, 0x40E8, 0x40E9, 0x40EA, + 0x40EB, 0x40EC, 0x40ED, 0x40EE, 0x40EF, 0x40F0, 0x40F1, 0x40F2, 0x40F3, + 0x40F4, 0x40F5, 0x40F6, 0x40F7, 0x40F8, 0x40F9, 0x40FA, 0x40FB, 0x40FC, + 0x40FD, 0x40FE, 0x40FF, 0x4100, 0x4101, 0x4102, 0x4103, 0x4104, 0x4105, + 0x4106, 0x4107, 0x4108, 0x4109, 0x410A, 0x410B, 0x410C, 0x410D, 0x410E, + 0x410F, 0x4110, 0x4111, 0x4112, 0x4113, 0x4114, 0x4115, 0x4116, 0x4117, + 0x4118, 0x4119, 0x411A, 0x411B, 0x411C, 0x411D, 0x411E, 0x411F, 0x4120, + 0x4121, 0x4122, 0x4123, 0x4124, 0x4125, 0x4126, 0x4127, 0x4128, 0x4129, + 0x412A, 0x412B, 0x412C, 0x412D, 0x412E, 0x412F, 0x4130, 0x4131, 0x4132, + 0x4133, 0x4134, 0x4135, 0x4136, 0x4137, 0x4138, 0x4139, 0x413A, 0x413B, + 0x413C, 0x413D, 0x413E, 0x413F, 0x4140, 0x4141, 0x4142, 0x4143, 0x4144, + 0x4145, 0x4146, 0x4147, 0x4148, 0x4149, 0x414A, 0x414B, 0x414C, 0x414D, + 0x414E, 0x414F, 0x4150, 0x4151, 0x4152, 0x4153, 0x4154, 0x4155, 0x4156, + 0x4157, 0x4158, 0x4159, 0x415A, 0x415B, 0x415C, 0x415D, 0x415E, 0x4160, + 0x4161, 0x4162, 0x4163, 0x4164, 0x4165, 0x4166, 0x4167, 0x4168, 0x4169, + 0x416A, 0x416B, 0x416C, 0x416D, 0x416E, 0x416F, 0x4170, 0x4171, 0x4172, + 0x4173, 0x4174, 0x4175, 0x4176, 0x4177, 0x4178, 0x4179, 0x417A, 0x417B, + 0x417C, 0x417D, 0x417E, 0x417F, 0x4180, 0x4181, 0x4182, 0x4183, 0x4184, + 0x4185, 0x4186, 0x4187, 0x4188, 0x4189, 0x418A, 0x418B, 0x418C, 0x418D, + 0x418E, 0x418F, 0x4190, 0x4191, 0x4192, 0x4193, 0x4194, 0x4195, 0x4196, + 0x4197, 0x4198, 0x4199, 0x419A, 0x419B, 0x419C, 0x419D, 0x419E, 0x419F, + 0x41A0, 0x41A1, 0x41A2, 0x41A3, 0x41A4, 0x41A5, 0x41A6, 0x41A7, 0x41A8, + 0x41A9, 0x41AA, 0x41AB, 0x41AC, 0x41AD, 0x41AE, 0x41AF, 0x41B0, 0x41B1, + 0x41B2, 0x41B3, 0x41B4, 0x41B5, 0x41B6, 0x41B7, 0x41B8, 0x41B9, 0x41BA, + 0x41BB, 0x41BC, 0x41BD, 0x41BE, 0x41BF, 0x41C0, 0x41C1, 0x41C2, 0x41C3, + 0x41C4, 0x41C5, 0x41C6, 0x41C7, 0x41C8, 0x41C9, 0x41CA, 0x41CB, 0x41CC, + 0x41CD, 0x41CE, 0x41CF, 0x41D0, 0x41D1, 0x41D2, 0x41D3, 0x41D4, 0x41D5, + 0x41D6, 0x41D7, 0x41D8, 0x41D9, 0x41DA, 0x41DB, 0x41DC, 0x41DD, 0x41DE, + 0x41DF, 0x41E0, 0x41E1, 0x41E2, 0x41E3, 0x41E4, 0x41E5, 0x41E6, 0x41E7, + 0x41E8, 0x41E9, 0x41EA, 0x41EB, 0x41EC, 0x41ED, 0x41EE, 0x41EF, 0x41F0, + 0x41F1, 0x41F2, 0x41F3, 0x41F4, 0x41F5, 0x41F6, 0x41F7, 0x41F8, 0x41F9, + 0x41FA, 0x41FB, 0x41FC, 0x41FD, 0x41FE, 0x41FF, 0x4200, 0x4201, 0x4202, + 0x4203, 0x4204, 0x4205, 0x4206, 0x4207, 0x4208, 0x4209, 0x420A, 0x420B, + 0x420C, 0x420D, 0x420E, 0x420F, 0x4210, 0x4211, 0x4212, 0x4213, 0x4214, + 0x4215, 0x4216, 0x4217, 0x4218, 0x4219, 0x421A, 0x421B, 0x421C, 0x421D, + 0x421E, 0x421F, 0x4220, 0x4221, 0x4222, 0x4223, 0x4224, 0x4225, 0x4226, + 0x4227, 0x4228, 0x4229, 0x422A, 0x422B, 0x422C, 0x422D, 0x422E, 0x422F, + 0x4230, 0x4231, 0x4232, 0x4233, 0x4234, 0x4235, 0x4236, 0x4237, 0x4238, + 0x4239, 0x423A, 0x423B, 0x423C, 0x423D, 0x423E, 0x423F, 0x4240, 0x4241, + 0x4242, 0x4243, 0x4244, 0x4245, 0x4246, 0x4247, 0x4248, 0x4249, 0x424A, + 0x424B, 0x424C, 0x424D, 0x424E, 0x424F, 0x4250, 0x4251, 0x4252, 0x4253, + 0x4254, 0x4255, 0x4256, 0x4257, 0x4258, 0x4259, 0x425A, 0x425B, 0x425C, + 0x425D, 0x425E, 0x425F, 0x4260, 0x4261, 0x4262, 0x4263, 0x4264, 0x4265, + 0x4266, 0x4267, 0x4268, 0x4269, 0x426A, 0x426B, 0x426C, 0x426D, 0x426E, + 0x426F, 0x4270, 0x4271, 0x4272, 0x4273, 0x4274, 0x4275, 0x4276, 0x4277, + 0x4278, 0x4279, 0x427A, 0x427B, 0x427C, 0x427D, 0x427E, 0x427F, 0x4280, + 0x4281, 0x4282, 0x4283, 0x4284, 0x4285, 0x4286, 0x4287, 0x4288, 0x4289, + 0x428A, 0x428B, 0x428C, 0x428D, 0x428E, 0x428F, 0x4290, 0x4291, 0x4292, + 0x4293, 0x4294, 0x4295, 0x4296, 0x4297, 0x4298, 0x4299, 0x429A, 0x429B, + 0x429C, 0x429D, 0x429E, 0x429F, 0x42A0, 0x42A1, 0x42A2, 0x42A3, 0x42A4, + 0x42A5, 0x42A6, 0x42A7, 0x42A8, 0x42A9, 0x42AA, 0x42AB, 0x42AC, 0x42AD, + 0x42AE, 0x42AF, 0x42B0, 0x42B1, 0x42B2, 0x42B3, 0x42B4, 0x42B5, 0x42B6, + 0x42B7, 0x42B8, 0x42B9, 0x42BA, 0x42BB, 0x42BC, 0x42BD, 0x42BE, 0x42BF, + 0x42C0, 0x42C1, 0x42C2, 0x42C3, 0x42C4, 0x42C5, 0x42C6, 0x42C7, 0x42C8, + 0x42C9, 0x42CA, 0x42CB, 0x42CC, 0x42CD, 0x42CE, 0x42CF, 0x42D0, 0x42D1, + 0x42D2, 0x42D3, 0x42D4, 0x42D5, 0x42D6, 0x42D7, 0x42D8, 0x42D9, 0x42DA, + 0x42DB, 0x42DC, 0x42DD, 0x42DE, 0x42DF, 0x42E0, 0x42E1, 0x42E2, 0x42E3, + 0x42E4, 0x42E5, 0x42E6, 0x42E7, 0x42E8, 0x42E9, 0x42EA, 0x42EB, 0x42EC, + 0x42ED, 0x42EE, 0x42EF, 0x42F0, 0x42F1, 0x42F2, 0x42F3, 0x42F4, 0x42F5, + 0x42F6, 0x42F7, 0x42F8, 0x42F9, 0x42FA, 0x42FB, 0x42FC, 0x42FD, 0x42FE, + 0x42FF, 0x4300, 0x4301, 0x4302, 0x4303, 0x4304, 0x4305, 0x4306, 0x4307, + 0x4308, 0x4309, 0x430A, 0x430B, 0x430C, 0x430D, 0x430E, 0x430F, 0x4310, + 0x4311, 0x4312, 0x4313, 0x4314, 0x4315, 0x4316, 0x4317, 0x4318, 0x4319, + 0x431A, 0x431B, 0x431C, 0x431D, 0x431E, 0x431F, 0x4320, 0x4321, 0x4322, + 0x4323, 0x4324, 0x4325, 0x4326, 0x4327, 0x4328, 0x4329, 0x432A, 0x432B, + 0x432C, 0x432D, 0x432E, 0x432F, 0x4330, 0x4331, 0x4332, 0x4333, 0x4334, + 0x4335, 0x4336, 0x4338, 0x4339, 0x433A, 0x433B, 0x433C, 0x433D, 0x433E, + 0x433F, 0x4340, 0x4341, 0x4342, 0x4343, 0x4344, 0x4345, 0x4346, 0x4347, + 0x4348, 0x4349, 0x434A, 0x434B, 0x434C, 0x434D, 0x434E, 0x434F, 0x4350, + 0x4351, 0x4352, 0x4353, 0x4354, 0x4355, 0x4356, 0x4357, 0x4358, 0x4359, + 0x435A, 0x435B, 0x435C, 0x435D, 0x435E, 0x435F, 0x4360, 0x4361, 0x4362, + 0x4363, 0x4364, 0x4365, 0x4366, 0x4367, 0x4368, 0x4369, 0x436A, 0x436B, + 0x436C, 0x436D, 0x436E, 0x436F, 0x4370, 0x4371, 0x4372, 0x4373, 0x4374, + 0x4375, 0x4376, 0x4377, 0x4378, 0x4379, 0x437A, 0x437B, 0x437C, 0x437D, + 0x437E, 0x437F, 0x4380, 0x4381, 0x4382, 0x4383, 0x4384, 0x4385, 0x4386, + 0x4387, 0x4388, 0x4389, 0x438A, 0x438B, 0x438C, 0x438D, 0x438E, 0x438F, + 0x4390, 0x4391, 0x4392, 0x4393, 0x4394, 0x4395, 0x4396, 0x4397, 0x4398, + 0x4399, 0x439A, 0x439B, 0x439C, 0x439D, 0x439E, 0x439F, 0x43A0, 0x43A1, + 0x43A2, 0x43A3, 0x43A4, 0x43A5, 0x43A6, 0x43A7, 0x43A8, 0x43A9, 0x43AA, + 0x43AB, 0x43AD, 0x43AE, 0x43AF, 0x43B0, 0x43B2, 0x43B3, 0x43B4, 0x43B5, + 0x43B6, 0x43B7, 0x43B8, 0x43B9, 0x43BA, 0x43BB, 0x43BC, 0x43BD, 0x43BE, + 0x43BF, 0x43C0, 0x43C1, 0x43C2, 0x43C3, 0x43C4, 0x43C5, 0x43C6, 0x43C7, + 0x43C8, 0x43C9, 0x43CA, 0x43CB, 0x43CC, 0x43CD, 0x43CE, 0x43CF, 0x43D0, + 0x43D1, 0x43D2, 0x43D3, 0x43D4, 0x43D5, 0x43D6, 0x43D7, 0x43D8, 0x43D9, + 0x43DA, 0x43DB, 0x43DC, 0x43DE, 0x43DF, 0x43E0, 0x43E1, 0x43E2, 0x43E3, + 0x43E4, 0x43E5, 0x43E6, 0x43E7, 0x43E8, 0x43E9, 0x43EA, 0x43EB, 0x43EC, + 0x43ED, 0x43EE, 0x43EF, 0x43F0, 0x43F1, 0x43F2, 0x43F3, 0x43F4, 0x43F5, + 0x43F6, 0x43F7, 0x43F8, 0x43F9, 0x43FA, 0x43FB, 0x43FC, 0x43FD, 0x43FE, + 0x43FF, 0x4400, 0x4401, 0x4402, 0x4403, 0x4404, 0x4405, 0x4406, 0x4407, + 0x4408, 0x4409, 0x440A, 0x440B, 0x440C, 0x440D, 0x440E, 0x440F, 0x4410, + 0x4411, 0x4412, 0x4413, 0x4414, 0x4415, 0x4416, 0x4417, 0x4418, 0x4419, + 0x441A, 0x441B, 0x441C, 0x441D, 0x441E, 0x441F, 0x4420, 0x4421, 0x4422, + 0x4423, 0x4424, 0x4425, 0x4426, 0x4427, 0x4428, 0x4429, 0x442A, 0x442B, + 0x442C, 0x442D, 0x442E, 0x442F, 0x4430, 0x4431, 0x4432, 0x4433, 0x4434, + 0x4435, 0x4436, 0x4437, 0x4438, 0x4439, 0x443A, 0x443B, 0x443C, 0x443D, + 0x443E, 0x443F, 0x4440, 0x4441, 0x4442, 0x4443, 0x4444, 0x4445, 0x4446, + 0x4447, 0x4448, 0x4449, 0x444A, 0x444B, 0x444C, 0x444D, 0x444E, 0x444F, + 0x4450, 0x4451, 0x4452, 0x4453, 0x4454, 0x4455, 0x4456, 0x4457, 0x4458, + 0x4459, 0x445A, 0x445B, 0x445C, 0x445D, 0x445E, 0x445F, 0x4460, 0x4461, + 0x4462, 0x4463, 0x4464, 0x4465, 0x4466, 0x4467, 0x4468, 0x4469, 0x446A, + 0x446B, 0x446C, 0x446D, 0x446E, 0x446F, 0x4470, 0x4471, 0x4472, 0x4473, + 0x4474, 0x4475, 0x4476, 0x4477, 0x4478, 0x4479, 0x447A, 0x447B, 0x447C, + 0x447D, 0x447E, 0x447F, 0x4480, 0x4481, 0x4482, 0x4483, 0x4484, 0x4485, + 0x4486, 0x4487, 0x4488, 0x4489, 0x448A, 0x448B, 0x448C, 0x448D, 0x448E, + 0x448F, 0x4490, 0x4491, 0x4492, 0x4493, 0x4494, 0x4495, 0x4496, 0x4497, + 0x4498, 0x4499, 0x449A, 0x449B, 0x449C, 0x449D, 0x449E, 0x449F, 0x44A0, + 0x44A1, 0x44A2, 0x44A3, 0x44A4, 0x44A5, 0x44A6, 0x44A7, 0x44A8, 0x44A9, + 0x44AA, 0x44AB, 0x44AC, 0x44AD, 0x44AE, 0x44AF, 0x44B0, 0x44B1, 0x44B2, + 0x44B3, 0x44B4, 0x44B5, 0x44B6, 0x44B7, 0x44B8, 0x44B9, 0x44BA, 0x44BB, + 0x44BC, 0x44BD, 0x44BE, 0x44BF, 0x44C0, 0x44C1, 0x44C2, 0x44C3, 0x44C4, + 0x44C5, 0x44C6, 0x44C7, 0x44C8, 0x44C9, 0x44CA, 0x44CB, 0x44CC, 0x44CD, + 0x44CE, 0x44CF, 0x44D0, 0x44D1, 0x44D2, 0x44D3, 0x44D4, 0x44D5, 0x44D7, + 0x44D8, 0x44D9, 0x44DA, 0x44DB, 0x44DC, 0x44DD, 0x44DE, 0x44DF, 0x44E0, + 0x44E1, 0x44E2, 0x44E3, 0x44E4, 0x44E5, 0x44E6, 0x44E7, 0x44E8, 0x44E9, + 0x44EA, 0x44EB, 0x44EC, 0x44ED, 0x44EE, 0x44EF, 0x44F0, 0x44F1, 0x44F2, + 0x44F3, 0x44F4, 0x44F5, 0x44F6, 0x44F7, 0x44F8, 0x44F9, 0x44FA, 0x44FB, + 0x44FC, 0x44FD, 0x44FE, 0x44FF, 0x4500, 0x4501, 0x4502, 0x4503, 0x4504, + 0x4505, 0x4506, 0x4507, 0x4508, 0x4509, 0x450A, 0x450B, 0x450C, 0x450D, + 0x450E, 0x450F, 0x4510, 0x4511, 0x4512, 0x4513, 0x4514, 0x4515, 0x4516, + 0x4517, 0x4518, 0x4519, 0x451A, 0x451B, 0x451C, 0x451D, 0x451E, 0x451F, + 0x4520, 0x4521, 0x4522, 0x4523, 0x4524, 0x4525, 0x4526, 0x4527, 0x4528, + 0x4529, 0x452A, 0x452B, 0x452C, 0x452D, 0x452E, 0x452F, 0x4530, 0x4531, + 0x4532, 0x4533, 0x4534, 0x4535, 0x4536, 0x4537, 0x4538, 0x4539, 0x453A, + 0x453B, 0x453C, 0x453D, 0x453E, 0x453F, 0x4540, 0x4541, 0x4542, 0x4543, + 0x4544, 0x4545, 0x4546, 0x4547, 0x4548, 0x4549, 0x454A, 0x454B, 0x454C, + 0x454D, 0x454E, 0x454F, 0x4550, 0x4551, 0x4552, 0x4553, 0x4554, 0x4555, + 0x4556, 0x4557, 0x4558, 0x4559, 0x455A, 0x455B, 0x455C, 0x455D, 0x455E, + 0x455F, 0x4560, 0x4561, 0x4562, 0x4563, 0x4564, 0x4565, 0x4566, 0x4567, + 0x4568, 0x4569, 0x456A, 0x456B, 0x456C, 0x456D, 0x456E, 0x456F, 0x4570, + 0x4571, 0x4572, 0x4573, 0x4574, 0x4575, 0x4576, 0x4577, 0x4578, 0x4579, + 0x457A, 0x457B, 0x457C, 0x457D, 0x457E, 0x457F, 0x4580, 0x4581, 0x4582, + 0x4583, 0x4584, 0x4585, 0x4586, 0x4587, 0x4588, 0x4589, 0x458A, 0x458B, + 0x458C, 0x458D, 0x458E, 0x458F, 0x4590, 0x4591, 0x4592, 0x4593, 0x4594, + 0x4595, 0x4596, 0x4597, 0x4598, 0x4599, 0x459A, 0x459B, 0x459C, 0x459D, + 0x459E, 0x459F, 0x45A0, 0x45A1, 0x45A2, 0x45A3, 0x45A4, 0x45A5, 0x45A6, + 0x45A7, 0x45A8, 0x45A9, 0x45AA, 0x45AB, 0x45AC, 0x45AD, 0x45AE, 0x45AF, + 0x45B0, 0x45B1, 0x45B2, 0x45B3, 0x45B4, 0x45B5, 0x45B6, 0x45B7, 0x45B8, + 0x45B9, 0x45BA, 0x45BB, 0x45BC, 0x45BD, 0x45BE, 0x45BF, 0x45C0, 0x45C1, + 0x45C2, 0x45C3, 0x45C4, 0x45C5, 0x45C6, 0x45C7, 0x45C8, 0x45C9, 0x45CA, + 0x45CB, 0x45CC, 0x45CD, 0x45CE, 0x45CF, 0x45D0, 0x45D1, 0x45D2, 0x45D3, + 0x45D4, 0x45D5, 0x45D6, 0x45D7, 0x45D8, 0x45D9, 0x45DA, 0x45DB, 0x45DC, + 0x45DD, 0x45DE, 0x45DF, 0x45E0, 0x45E1, 0x45E2, 0x45E3, 0x45E4, 0x45E5, + 0x45E6, 0x45E7, 0x45E8, 0x45E9, 0x45EA, 0x45EB, 0x45EC, 0x45ED, 0x45EE, + 0x45EF, 0x45F0, 0x45F1, 0x45F2, 0x45F3, 0x45F4, 0x45F5, 0x45F6, 0x45F7, + 0x45F8, 0x45F9, 0x45FA, 0x45FB, 0x45FC, 0x45FD, 0x45FE, 0x45FF, 0x4600, + 0x4601, 0x4602, 0x4603, 0x4604, 0x4605, 0x4606, 0x4607, 0x4608, 0x4609, + 0x460A, 0x460B, 0x460C, 0x460D, 0x460E, 0x460F, 0x4610, 0x4611, 0x4612, + 0x4613, 0x4614, 0x4615, 0x4616, 0x4617, 0x4618, 0x4619, 0x461A, 0x461B, + 0x461C, 0x461D, 0x461E, 0x461F, 0x4620, 0x4621, 0x4622, 0x4623, 0x4624, + 0x4625, 0x4626, 0x4627, 0x4628, 0x4629, 0x462A, 0x462B, 0x462C, 0x462D, + 0x462E, 0x462F, 0x4630, 0x4631, 0x4632, 0x4633, 0x4634, 0x4635, 0x4636, + 0x4637, 0x4638, 0x4639, 0x463A, 0x463B, 0x463C, 0x463D, 0x463E, 0x463F, + 0x4640, 0x4641, 0x4642, 0x4643, 0x4644, 0x4645, 0x4646, 0x4647, 0x4648, + 0x4649, 0x464A, 0x464B, 0x464D, 0x464E, 0x464F, 0x4650, 0x4651, 0x4652, + 0x4653, 0x4654, 0x4655, 0x4656, 0x4657, 0x4658, 0x4659, 0x465A, 0x465B, + 0x465C, 0x465D, 0x465E, 0x465F, 0x4660, 0x4662, 0x4663, 0x4664, 0x4665, + 0x4666, 0x4667, 0x4668, 0x4669, 0x466A, 0x466B, 0x466C, 0x466D, 0x466E, + 0x466F, 0x4670, 0x4671, 0x4672, 0x4673, 0x4674, 0x4675, 0x4676, 0x4677, + 0x4678, 0x4679, 0x467A, 0x467B, 0x467C, 0x467D, 0x467E, 0x467F, 0x4680, + 0x4681, 0x4682, 0x4683, 0x4684, 0x4685, 0x4686, 0x4687, 0x4688, 0x4689, + 0x468A, 0x468B, 0x468C, 0x468D, 0x468E, 0x468F, 0x4690, 0x4691, 0x4692, + 0x4693, 0x4694, 0x4695, 0x4696, 0x4697, 0x4698, 0x4699, 0x469A, 0x469B, + 0x469C, 0x469D, 0x469E, 0x469F, 0x46A0, 0x46A1, 0x46A2, 0x46A3, 0x46A4, + 0x46A5, 0x46A6, 0x46A7, 0x46A8, 0x46A9, 0x46AA, 0x46AB, 0x46AC, 0x46AD, + 0x46AE, 0x46AF, 0x46B0, 0x46B1, 0x46B2, 0x46B3, 0x46B4, 0x46B5, 0x46B6, + 0x46B7, 0x46B8, 0x46B9, 0x46BA, 0x46BB, 0x46BC, 0x46BD, 0x46BE, 0x46BF, + 0x46C0, 0x46C1, 0x46C2, 0x46C3, 0x46C4, 0x46C5, 0x46C6, 0x46C7, 0x46C8, + 0x46C9, 0x46CA, 0x46CB, 0x46CC, 0x46CD, 0x46CE, 0x46CF, 0x46D0, 0x46D1, + 0x46D2, 0x46D3, 0x46D4, 0x46D5, 0x46D6, 0x46D7, 0x46D8, 0x46D9, 0x46DA, + 0x46DB, 0x46DC, 0x46DD, 0x46DE, 0x46DF, 0x46E0, 0x46E1, 0x46E2, 0x46E3, + 0x46E4, 0x46E5, 0x46E6, 0x46E7, 0x46E8, 0x46E9, 0x46EA, 0x46EB, 0x46EC, + 0x46ED, 0x46EE, 0x46EF, 0x46F0, 0x46F1, 0x46F2, 0x46F3, 0x46F4, 0x46F5, + 0x46F6, 0x46F7, 0x46F8, 0x46F9, 0x46FA, 0x46FB, 0x46FC, 0x46FD, 0x46FE, + 0x46FF, 0x4700, 0x4701, 0x4702, 0x4703, 0x4704, 0x4705, 0x4706, 0x4707, + 0x4708, 0x4709, 0x470A, 0x470B, 0x470C, 0x470D, 0x470E, 0x470F, 0x4710, + 0x4711, 0x4712, 0x4713, 0x4714, 0x4715, 0x4716, 0x4717, 0x4718, 0x4719, + 0x471A, 0x471B, 0x471C, 0x471D, 0x471E, 0x471F, 0x4720, 0x4721, 0x4722, + 0x4724, 0x4725, 0x4726, 0x4727, 0x4728, 0x472A, 0x472B, 0x472C, 0x472D, + 0x472E, 0x472F, 0x4730, 0x4731, 0x4732, 0x4733, 0x4734, 0x4735, 0x4736, + 0x4737, 0x4738, 0x4739, 0x473A, 0x473B, 0x473C, 0x473D, 0x473E, 0x473F, + 0x4740, 0x4741, 0x4742, 0x4743, 0x4744, 0x4745, 0x4746, 0x4747, 0x4748, + 0x4749, 0x474A, 0x474B, 0x474C, 0x474D, 0x474E, 0x474F, 0x4750, 0x4751, + 0x4752, 0x4753, 0x4754, 0x4755, 0x4756, 0x4757, 0x4758, 0x4759, 0x475A, + 0x475B, 0x475C, 0x475D, 0x475E, 0x475F, 0x4760, 0x4761, 0x4762, 0x4763, + 0x4764, 0x4765, 0x4766, 0x4767, 0x4768, 0x4769, 0x476A, 0x476B, 0x476C, + 0x476D, 0x476E, 0x476F, 0x4770, 0x4771, 0x4772, 0x4773, 0x4774, 0x4775, + 0x4776, 0x4777, 0x4778, 0x4779, 0x477A, 0x477B, 0x477D, 0x477E, 0x477F, + 0x4780, 0x4781, 0x4782, 0x4783, 0x4784, 0x4785, 0x4786, 0x4787, 0x4788, + 0x4789, 0x478A, 0x478B, 0x478C, 0x478E, 0x478F, 0x4790, 0x4791, 0x4792, + 0x4793, 0x4794, 0x4795, 0x4796, 0x4797, 0x4798, 0x4799, 0x479A, 0x479B, + 0x479C, 0x479D, 0x479E, 0x479F, 0x47A0, 0x47A1, 0x47A2, 0x47A3, 0x47A4, + 0x47A5, 0x47A6, 0x47A7, 0x47A8, 0x47A9, 0x47AA, 0x47AB, 0x47AC, 0x47AD, + 0x47AE, 0x47AF, 0x47B0, 0x47B1, 0x47B2, 0x47B3, 0x47B4, 0x47B5, 0x47B6, + 0x47B7, 0x47B8, 0x47B9, 0x47BA, 0x47BB, 0x47BC, 0x47BD, 0x47BE, 0x47BF, + 0x47C0, 0x47C1, 0x47C2, 0x47C3, 0x47C4, 0x47C5, 0x47C6, 0x47C7, 0x47C8, + 0x47C9, 0x47CA, 0x47CB, 0x47CC, 0x47CD, 0x47CE, 0x47CF, 0x47D0, 0x47D1, + 0x47D2, 0x47D3, 0x47D4, 0x47D5, 0x47D6, 0x47D7, 0x47D8, 0x47D9, 0x47DA, + 0x47DB, 0x47DC, 0x47DD, 0x47DE, 0x47DF, 0x47E0, 0x47E1, 0x47E2, 0x47E3, + 0x47E4, 0x47E5, 0x47E6, 0x47E7, 0x47E8, 0x47E9, 0x47EA, 0x47EB, 0x47EC, + 0x47ED, 0x47EE, 0x47EF, 0x47F0, 0x47F1, 0x47F2, 0x47F3, 0x47F4, 0x47F5, + 0x47F6, 0x47F7, 0x47F8, 0x47F9, 0x47FA, 0x47FB, 0x47FC, 0x47FD, 0x47FE, + 0x47FF, 0x4800, 0x4801, 0x4802, 0x4803, 0x4804, 0x4805, 0x4806, 0x4807, + 0x4808, 0x4809, 0x480A, 0x480B, 0x480C, 0x480D, 0x480E, 0x480F, 0x4810, + 0x4811, 0x4812, 0x4813, 0x4814, 0x4815, 0x4816, 0x4817, 0x4818, 0x4819, + 0x481A, 0x481B, 0x481C, 0x481D, 0x481E, 0x481F, 0x4820, 0x4821, 0x4822, + 0x4823, 0x4824, 0x4825, 0x4826, 0x4827, 0x4828, 0x4829, 0x482A, 0x482B, + 0x482C, 0x482D, 0x482E, 0x482F, 0x4830, 0x4831, 0x4832, 0x4833, 0x4834, + 0x4835, 0x4836, 0x4837, 0x4838, 0x4839, 0x483A, 0x483B, 0x483C, 0x483D, + 0x483E, 0x483F, 0x4840, 0x4841, 0x4842, 0x4843, 0x4844, 0x4845, 0x4846, + 0x4847, 0x4848, 0x4849, 0x484A, 0x484B, 0x484C, 0x484D, 0x484E, 0x484F, + 0x4850, 0x4851, 0x4852, 0x4853, 0x4854, 0x4855, 0x4856, 0x4857, 0x4858, + 0x4859, 0x485A, 0x485B, 0x485C, 0x485D, 0x485E, 0x485F, 0x4860, 0x4861, + 0x4862, 0x4863, 0x4864, 0x4865, 0x4866, 0x4867, 0x4868, 0x4869, 0x486A, + 0x486B, 0x486C, 0x486D, 0x486E, 0x486F, 0x4870, 0x4871, 0x4872, 0x4873, + 0x4874, 0x4875, 0x4876, 0x4877, 0x4878, 0x4879, 0x487A, 0x487B, 0x487C, + 0x487D, 0x487E, 0x487F, 0x4880, 0x4881, 0x4882, 0x4883, 0x4884, 0x4885, + 0x4886, 0x4887, 0x4888, 0x4889, 0x488A, 0x488B, 0x488C, 0x488D, 0x488E, + 0x488F, 0x4890, 0x4891, 0x4892, 0x4893, 0x4894, 0x4895, 0x4896, 0x4897, + 0x4898, 0x4899, 0x489A, 0x489B, 0x489C, 0x489D, 0x489E, 0x489F, 0x48A0, + 0x48A1, 0x48A2, 0x48A3, 0x48A4, 0x48A5, 0x48A6, 0x48A7, 0x48A8, 0x48A9, + 0x48AA, 0x48AB, 0x48AC, 0x48AD, 0x48AE, 0x48AF, 0x48B0, 0x48B1, 0x48B2, + 0x48B3, 0x48B4, 0x48B5, 0x48B6, 0x48B7, 0x48B8, 0x48B9, 0x48BA, 0x48BB, + 0x48BC, 0x48BD, 0x48BE, 0x48BF, 0x48C0, 0x48C1, 0x48C2, 0x48C3, 0x48C4, + 0x48C5, 0x48C6, 0x48C7, 0x48C8, 0x48C9, 0x48CA, 0x48CB, 0x48CC, 0x48CD, + 0x48CE, 0x48CF, 0x48D0, 0x48D1, 0x48D2, 0x48D3, 0x48D4, 0x48D5, 0x48D6, + 0x48D7, 0x48D8, 0x48D9, 0x48DA, 0x48DB, 0x48DC, 0x48DD, 0x48DE, 0x48DF, + 0x48E0, 0x48E1, 0x48E2, 0x48E3, 0x48E4, 0x48E5, 0x48E6, 0x48E7, 0x48E8, + 0x48E9, 0x48EA, 0x48EB, 0x48EC, 0x48ED, 0x48EE, 0x48EF, 0x48F0, 0x48F1, + 0x48F2, 0x48F3, 0x48F4, 0x48F5, 0x48F6, 0x48F7, 0x48F8, 0x48F9, 0x48FA, + 0x48FB, 0x48FC, 0x48FD, 0x48FE, 0x48FF, 0x4900, 0x4901, 0x4902, 0x4903, + 0x4904, 0x4905, 0x4906, 0x4907, 0x4908, 0x4909, 0x490A, 0x490B, 0x490C, + 0x490D, 0x490E, 0x490F, 0x4910, 0x4911, 0x4912, 0x4913, 0x4914, 0x4915, + 0x4916, 0x4917, 0x4918, 0x4919, 0x491A, 0x491B, 0x491C, 0x491D, 0x491E, + 0x491F, 0x4920, 0x4921, 0x4922, 0x4923, 0x4924, 0x4925, 0x4926, 0x4927, + 0x4928, 0x4929, 0x492A, 0x492B, 0x492C, 0x492D, 0x492E, 0x492F, 0x4930, + 0x4931, 0x4932, 0x4933, 0x4934, 0x4935, 0x4936, 0x4937, 0x4938, 0x4939, + 0x493A, 0x493B, 0x493C, 0x493D, 0x493E, 0x493F, 0x4940, 0x4941, 0x4942, + 0x4943, 0x4944, 0x4945, 0x4946, 0x4948, 0x4949, 0x494A, 0x494B, 0x494C, + 0x494D, 0x494E, 0x494F, 0x4950, 0x4951, 0x4952, 0x4953, 0x4954, 0x4955, + 0x4956, 0x4957, 0x4958, 0x4959, 0x495A, 0x495B, 0x495C, 0x495D, 0x495E, + 0x495F, 0x4960, 0x4961, 0x4962, 0x4963, 0x4964, 0x4965, 0x4966, 0x4967, + 0x4968, 0x4969, 0x496A, 0x496B, 0x496C, 0x496D, 0x496E, 0x496F, 0x4970, + 0x4971, 0x4972, 0x4973, 0x4974, 0x4975, 0x4976, 0x4977, 0x4978, 0x4979, + 0x497B, 0x497C, 0x497E, 0x497F, 0x4980, 0x4981, 0x4984, 0x4987, 0x4988, + 0x4989, 0x498A, 0x498B, 0x498C, 0x498D, 0x498E, 0x498F, 0x4990, 0x4991, + 0x4992, 0x4993, 0x4994, 0x4995, 0x4996, 0x4997, 0x4998, 0x4999, 0x499A, + 0x499C, 0x499D, 0x499E, 0x49A0, 0x49A1, 0x49A2, 0x49A3, 0x49A4, 0x49A5, + 0x49A6, 0x49A7, 0x49A8, 0x49A9, 0x49AA, 0x49AB, 0x49AC, 0x49AD, 0x49AE, + 0x49AF, 0x49B0, 0x49B1, 0x49B2, 0x49B3, 0x49B4, 0x49B5, 0x49B8, 0x49B9, + 0x49BA, 0x49BB, 0x49BC, 0x49BD, 0x49BE, 0x49BF, 0x49C0, 0x49C1, 0x49C2, + 0x49C3, 0x49C4, 0x49C5, 0x49C6, 0x49C7, 0x49C8, 0x49C9, 0x49CA, 0x49CB, + 0x49CC, 0x49CD, 0x49CE, 0x49CF, 0x49D0, 0x49D1, 0x49D2, 0x49D3, 0x49D4, + 0x49D5, 0x49D6, 0x49D7, 0x49D8, 0x49D9, 0x49DA, 0x49DB, 0x49DC, 0x49DD, + 0x49DE, 0x49DF, 0x49E0, 0x49E1, 0x49E2, 0x49E3, 0x49E4, 0x49E5, 0x49E6, + 0x49E7, 0x49E8, 0x49E9, 0x49EA, 0x49EB, 0x49EC, 0x49ED, 0x49EE, 0x49EF, + 0x49F0, 0x49F1, 0x49F2, 0x49F3, 0x49F4, 0x49F5, 0x49F6, 0x49F7, 0x49F8, + 0x49F9, 0x49FA, 0x49FB, 0x49FC, 0x49FD, 0x49FE, 0x49FF, 0x4A00, 0x4A01, + 0x4A02, 0x4A03, 0x4A04, 0x4A05, 0x4A06, 0x4A07, 0x4A08, 0x4A09, 0x4A0A, + 0x4A0B, 0x4A0C, 0x4A0D, 0x4A0E, 0x4A0F, 0x4A10, 0x4A11, 0x4A12, 0x4A13, + 0x4A14, 0x4A15, 0x4A16, 0x4A17, 0x4A18, 0x4A19, 0x4A1A, 0x4A1B, 0x4A1C, + 0x4A1D, 0x4A1E, 0x4A1F, 0x4A20, 0x4A21, 0x4A22, 0x4A23, 0x4A24, 0x4A25, + 0x4A26, 0x4A27, 0x4A28, 0x4A29, 0x4A2A, 0x4A2B, 0x4A2C, 0x4A2D, 0x4A2E, + 0x4A2F, 0x4A30, 0x4A31, 0x4A32, 0x4A33, 0x4A34, 0x4A35, 0x4A36, 0x4A37, + 0x4A38, 0x4A39, 0x4A3A, 0x4A3B, 0x4A3C, 0x4A3D, 0x4A3E, 0x4A3F, 0x4A40, + 0x4A41, 0x4A42, 0x4A43, 0x4A44, 0x4A45, 0x4A46, 0x4A47, 0x4A48, 0x4A49, + 0x4A4A, 0x4A4B, 0x4A4C, 0x4A4D, 0x4A4E, 0x4A4F, 0x4A50, 0x4A51, 0x4A52, + 0x4A53, 0x4A54, 0x4A55, 0x4A56, 0x4A57, 0x4A58, 0x4A59, 0x4A5A, 0x4A5B, + 0x4A5C, 0x4A5D, 0x4A5E, 0x4A5F, 0x4A60, 0x4A61, 0x4A62, 0x4A63, 0x4A64, + 0x4A65, 0x4A66, 0x4A67, 0x4A68, 0x4A69, 0x4A6A, 0x4A6B, 0x4A6C, 0x4A6D, + 0x4A6E, 0x4A6F, 0x4A70, 0x4A71, 0x4A72, 0x4A73, 0x4A74, 0x4A75, 0x4A76, + 0x4A77, 0x4A78, 0x4A79, 0x4A7A, 0x4A7B, 0x4A7C, 0x4A7D, 0x4A7E, 0x4A7F, + 0x4A80, 0x4A81, 0x4A82, 0x4A83, 0x4A84, 0x4A85, 0x4A86, 0x4A87, 0x4A88, + 0x4A89, 0x4A8A, 0x4A8B, 0x4A8C, 0x4A8D, 0x4A8E, 0x4A8F, 0x4A90, 0x4A91, + 0x4A92, 0x4A93, 0x4A94, 0x4A95, 0x4A96, 0x4A97, 0x4A98, 0x4A99, 0x4A9A, + 0x4A9B, 0x4A9C, 0x4A9D, 0x4A9E, 0x4A9F, 0x4AA0, 0x4AA1, 0x4AA2, 0x4AA3, + 0x4AA4, 0x4AA5, 0x4AA6, 0x4AA7, 0x4AA8, 0x4AA9, 0x4AAA, 0x4AAB, 0x4AAC, + 0x4AAD, 0x4AAE, 0x4AAF, 0x4AB0, 0x4AB1, 0x4AB2, 0x4AB3, 0x4AB4, 0x4AB5, + 0x4AB6, 0x4AB7, 0x4AB8, 0x4AB9, 0x4ABA, 0x4ABB, 0x4ABC, 0x4ABD, 0x4ABE, + 0x4ABF, 0x4AC0, 0x4AC1, 0x4AC2, 0x4AC3, 0x4AC4, 0x4AC5, 0x4AC6, 0x4AC7, + 0x4AC8, 0x4AC9, 0x4ACA, 0x4ACB, 0x4ACC, 0x4ACD, 0x4ACE, 0x4ACF, 0x4AD0, + 0x4AD1, 0x4AD2, 0x4AD3, 0x4AD4, 0x4AD5, 0x4AD6, 0x4AD7, 0x4AD8, 0x4AD9, + 0x4ADA, 0x4ADB, 0x4ADC, 0x4ADD, 0x4ADE, 0x4ADF, 0x4AE0, 0x4AE1, 0x4AE2, + 0x4AE3, 0x4AE4, 0x4AE5, 0x4AE6, 0x4AE7, 0x4AE8, 0x4AE9, 0x4AEA, 0x4AEB, + 0x4AEC, 0x4AED, 0x4AEE, 0x4AEF, 0x4AF0, 0x4AF1, 0x4AF2, 0x4AF3, 0x4AF4, + 0x4AF5, 0x4AF6, 0x4AF7, 0x4AF8, 0x4AF9, 0x4AFA, 0x4AFB, 0x4AFC, 0x4AFD, + 0x4AFE, 0x4AFF, 0x4B00, 0x4B01, 0x4B02, 0x4B03, 0x4B04, 0x4B05, 0x4B06, + 0x4B07, 0x4B08, 0x4B09, 0x4B0A, 0x4B0B, 0x4B0C, 0x4B0D, 0x4B0E, 0x4B0F, + 0x4B10, 0x4B11, 0x4B12, 0x4B13, 0x4B14, 0x4B15, 0x4B16, 0x4B17, 0x4B18, + 0x4B19, 0x4B1A, 0x4B1B, 0x4B1C, 0x4B1D, 0x4B1E, 0x4B1F, 0x4B20, 0x4B21, + 0x4B22, 0x4B23, 0x4B24, 0x4B25, 0x4B26, 0x4B27, 0x4B28, 0x4B29, 0x4B2A, + 0x4B2B, 0x4B2C, 0x4B2D, 0x4B2E, 0x4B2F, 0x4B30, 0x4B31, 0x4B32, 0x4B33, + 0x4B34, 0x4B35, 0x4B36, 0x4B37, 0x4B38, 0x4B39, 0x4B3A, 0x4B3B, 0x4B3C, + 0x4B3D, 0x4B3E, 0x4B3F, 0x4B40, 0x4B41, 0x4B42, 0x4B43, 0x4B44, 0x4B45, + 0x4B46, 0x4B47, 0x4B48, 0x4B49, 0x4B4A, 0x4B4B, 0x4B4C, 0x4B4D, 0x4B4E, + 0x4B4F, 0x4B50, 0x4B51, 0x4B52, 0x4B53, 0x4B54, 0x4B55, 0x4B56, 0x4B57, + 0x4B58, 0x4B59, 0x4B5A, 0x4B5B, 0x4B5C, 0x4B5D, 0x4B5E, 0x4B5F, 0x4B60, + 0x4B61, 0x4B62, 0x4B63, 0x4B64, 0x4B65, 0x4B66, 0x4B67, 0x4B68, 0x4B69, + 0x4B6A, 0x4B6B, 0x4B6C, 0x4B6D, 0x4B6E, 0x4B6F, 0x4B70, 0x4B71, 0x4B72, + 0x4B73, 0x4B74, 0x4B75, 0x4B76, 0x4B77, 0x4B78, 0x4B79, 0x4B7A, 0x4B7B, + 0x4B7C, 0x4B7D, 0x4B7E, 0x4B7F, 0x4B80, 0x4B81, 0x4B82, 0x4B83, 0x4B84, + 0x4B85, 0x4B86, 0x4B87, 0x4B88, 0x4B89, 0x4B8A, 0x4B8B, 0x4B8C, 0x4B8D, + 0x4B8E, 0x4B8F, 0x4B90, 0x4B91, 0x4B92, 0x4B93, 0x4B94, 0x4B95, 0x4B96, + 0x4B97, 0x4B98, 0x4B99, 0x4B9A, 0x4B9B, 0x4B9C, 0x4B9D, 0x4B9E, 0x4B9F, + 0x4BA0, 0x4BA1, 0x4BA2, 0x4BA3, 0x4BA4, 0x4BA5, 0x4BA6, 0x4BA7, 0x4BA8, + 0x4BA9, 0x4BAA, 0x4BAB, 0x4BAC, 0x4BAD, 0x4BAE, 0x4BAF, 0x4BB0, 0x4BB1, + 0x4BB2, 0x4BB3, 0x4BB4, 0x4BB5, 0x4BB6, 0x4BB7, 0x4BB8, 0x4BB9, 0x4BBA, + 0x4BBB, 0x4BBC, 0x4BBD, 0x4BBE, 0x4BBF, 0x4BC0, 0x4BC1, 0x4BC2, 0x4BC3, + 0x4BC4, 0x4BC5, 0x4BC6, 0x4BC7, 0x4BC8, 0x4BC9, 0x4BCA, 0x4BCB, 0x4BCC, + 0x4BCD, 0x4BCE, 0x4BCF, 0x4BD0, 0x4BD1, 0x4BD2, 0x4BD3, 0x4BD4, 0x4BD5, + 0x4BD6, 0x4BD7, 0x4BD8, 0x4BD9, 0x4BDA, 0x4BDB, 0x4BDC, 0x4BDD, 0x4BDE, + 0x4BDF, 0x4BE0, 0x4BE1, 0x4BE2, 0x4BE3, 0x4BE4, 0x4BE5, 0x4BE6, 0x4BE7, + 0x4BE8, 0x4BE9, 0x4BEA, 0x4BEB, 0x4BEC, 0x4BED, 0x4BEE, 0x4BEF, 0x4BF0, + 0x4BF1, 0x4BF2, 0x4BF3, 0x4BF4, 0x4BF5, 0x4BF6, 0x4BF7, 0x4BF8, 0x4BF9, + 0x4BFA, 0x4BFB, 0x4BFC, 0x4BFD, 0x4BFE, 0x4BFF, 0x4C00, 0x4C01, 0x4C02, + 0x4C03, 0x4C04, 0x4C05, 0x4C06, 0x4C07, 0x4C08, 0x4C09, 0x4C0A, 0x4C0B, + 0x4C0C, 0x4C0D, 0x4C0E, 0x4C0F, 0x4C10, 0x4C11, 0x4C12, 0x4C13, 0x4C14, + 0x4C15, 0x4C16, 0x4C17, 0x4C18, 0x4C19, 0x4C1A, 0x4C1B, 0x4C1C, 0x4C1D, + 0x4C1E, 0x4C1F, 0x4C20, 0x4C21, 0x4C22, 0x4C23, 0x4C24, 0x4C25, 0x4C26, + 0x4C27, 0x4C28, 0x4C29, 0x4C2A, 0x4C2B, 0x4C2C, 0x4C2D, 0x4C2E, 0x4C2F, + 0x4C30, 0x4C31, 0x4C32, 0x4C33, 0x4C34, 0x4C35, 0x4C36, 0x4C37, 0x4C38, + 0x4C39, 0x4C3A, 0x4C3B, 0x4C3C, 0x4C3D, 0x4C3E, 0x4C3F, 0x4C40, 0x4C41, + 0x4C42, 0x4C43, 0x4C44, 0x4C45, 0x4C46, 0x4C47, 0x4C48, 0x4C49, 0x4C4A, + 0x4C4B, 0x4C4C, 0x4C4D, 0x4C4E, 0x4C4F, 0x4C50, 0x4C51, 0x4C52, 0x4C53, + 0x4C54, 0x4C55, 0x4C56, 0x4C57, 0x4C58, 0x4C59, 0x4C5A, 0x4C5B, 0x4C5C, + 0x4C5D, 0x4C5E, 0x4C5F, 0x4C60, 0x4C61, 0x4C62, 0x4C63, 0x4C64, 0x4C65, + 0x4C66, 0x4C67, 0x4C68, 0x4C69, 0x4C6A, 0x4C6B, 0x4C6C, 0x4C6D, 0x4C6E, + 0x4C6F, 0x4C70, 0x4C71, 0x4C72, 0x4C73, 0x4C74, 0x4C75, 0x4C76, 0x4C78, + 0x4C79, 0x4C7A, 0x4C7B, 0x4C7C, 0x4C7D, 0x4C7E, 0x4C7F, 0x4C80, 0x4C81, + 0x4C82, 0x4C83, 0x4C84, 0x4C85, 0x4C86, 0x4C87, 0x4C88, 0x4C89, 0x4C8A, + 0x4C8B, 0x4C8C, 0x4C8D, 0x4C8E, 0x4C8F, 0x4C90, 0x4C91, 0x4C92, 0x4C93, + 0x4C94, 0x4C95, 0x4C96, 0x4C97, 0x4C98, 0x4C99, 0x4C9A, 0x4C9B, 0x4C9C, + 0x4C9D, 0x4C9E, 0x4CA4, 0x4CA5, 0x4CA6, 0x4CA7, 0x4CA8, 0x4CA9, 0x4CAA, + 0x4CAB, 0x4CAC, 0x4CAD, 0x4CAE, 0x4CAF, 0x4CB0, 0x4CB1, 0x4CB2, 0x4CB3, + 0x4CB4, 0x4CB5, 0x4CB6, 0x4CB7, 0x4CB8, 0x4CB9, 0x4CBA, 0x4CBB, 0x4CBC, + 0x4CBD, 0x4CBE, 0x4CBF, 0x4CC0, 0x4CC1, 0x4CC2, 0x4CC3, 0x4CC4, 0x4CC5, + 0x4CC6, 0x4CC7, 0x4CC8, 0x4CC9, 0x4CCA, 0x4CCB, 0x4CCC, 0x4CCD, 0x4CCE, + 0x4CCF, 0x4CD0, 0x4CD1, 0x4CD2, 0x4CD3, 0x4CD4, 0x4CD5, 0x4CD6, 0x4CD7, + 0x4CD8, 0x4CD9, 0x4CDA, 0x4CDB, 0x4CDC, 0x4CDD, 0x4CDE, 0x4CDF, 0x4CE0, + 0x4CE1, 0x4CE2, 0x4CE3, 0x4CE4, 0x4CE5, 0x4CE6, 0x4CE7, 0x4CE8, 0x4CE9, + 0x4CEA, 0x4CEB, 0x4CEC, 0x4CED, 0x4CEE, 0x4CEF, 0x4CF0, 0x4CF1, 0x4CF2, + 0x4CF3, 0x4CF4, 0x4CF5, 0x4CF6, 0x4CF7, 0x4CF8, 0x4CF9, 0x4CFA, 0x4CFB, + 0x4CFC, 0x4CFD, 0x4CFE, 0x4CFF, 0x4D00, 0x4D01, 0x4D02, 0x4D03, 0x4D04, + 0x4D05, 0x4D06, 0x4D07, 0x4D08, 0x4D09, 0x4D0A, 0x4D0B, 0x4D0C, 0x4D0D, + 0x4D0E, 0x4D0F, 0x4D10, 0x4D11, 0x4D12, 0x4D1A, 0x4D1B, 0x4D1C, 0x4D1D, + 0x4D1E, 0x4D1F, 0x4D20, 0x4D21, 0x4D22, 0x4D23, 0x4D24, 0x4D25, 0x4D26, + 0x4D27, 0x4D28, 0x4D29, 0x4D2A, 0x4D2B, 0x4D2C, 0x4D2D, 0x4D2E, 0x4D2F, + 0x4D30, 0x4D31, 0x4D32, 0x4D33, 0x4D34, 0x4D35, 0x4D36, 0x4D37, 0x4D38, + 0x4D39, 0x4D3A, 0x4D3B, 0x4D3C, 0x4D3D, 0x4D3E, 0x4D3F, 0x4D40, 0x4D41, + 0x4D42, 0x4D43, 0x4D44, 0x4D45, 0x4D46, 0x4D47, 0x4D48, 0x4D49, 0x4D4A, + 0x4D4B, 0x4D4C, 0x4D4D, 0x4D4E, 0x4D4F, 0x4D50, 0x4D51, 0x4D52, 0x4D53, + 0x4D54, 0x4D55, 0x4D56, 0x4D57, 0x4D58, 0x4D59, 0x4D5A, 0x4D5B, 0x4D5C, + 0x4D5D, 0x4D5E, 0x4D5F, 0x4D60, 0x4D61, 0x4D62, 0x4D63, 0x4D64, 0x4D65, + 0x4D66, 0x4D67, 0x4D68, 0x4D69, 0x4D6A, 0x4D6B, 0x4D6C, 0x4D6D, 0x4D6E, + 0x4D6F, 0x4D70, 0x4D71, 0x4D72, 0x4D73, 0x4D74, 0x4D75, 0x4D76, 0x4D77, + 0x4D78, 0x4D79, 0x4D7A, 0x4D7B, 0x4D7C, 0x4D7D, 0x4D7E, 0x4D7F, 0x4D80, + 0x4D81, 0x4D82, 0x4D83, 0x4D84, 0x4D85, 0x4D86, 0x4D87, 0x4D88, 0x4D89, + 0x4D8A, 0x4D8B, 0x4D8C, 0x4D8D, 0x4D8E, 0x4D8F, 0x4D90, 0x4D91, 0x4D92, + 0x4D93, 0x4D94, 0x4D95, 0x4D96, 0x4D97, 0x4D98, 0x4D99, 0x4D9A, 0x4D9B, + 0x4D9C, 0x4D9D, 0x4D9E, 0x4D9F, 0x4DA0, 0x4DA1, 0x4DA2, 0x4DA3, 0x4DA4, + 0x4DA5, 0x4DA6, 0x4DA7, 0x4DA8, 0x4DA9, 0x4DAA, 0x4DAB, 0x4DAC, 0x4DAD, + 0x4DAF, 0x4DB0, 0x4DB1, 0x4DB2, 0x4DB3, 0x4DB4, 0x4DB5, 0x4DB6, 0x4DB7, + 0x4DB8, 0x4DB9, 0x4DBA, 0x4DBB, 0x4DBC, 0x4DBD, 0x4DBE, 0x4DBF, 0x4DC0, + 0x4DC1, 0x4DC2, 0x4DC3, 0x4DC4, 0x4DC5, 0x4DC6, 0x4DC7, 0x4DC8, 0x4DC9, + 0x4DCA, 0x4DCB, 0x4DCC, 0x4DCD, 0x4DCE, 0x4DCF, 0x4DD0, 0x4DD1, 0x4DD2, + 0x4DD3, 0x4DD4, 0x4DD5, 0x4DD6, 0x4DD7, 0x4DD8, 0x4DD9, 0x4DDA, 0x4DDB, + 0x4DDC, 0x4DDD, 0x4DDE, 0x4DDF, 0x4DE0, 0x4DE1, 0x4DE2, 0x4DE3, 0x4DE4, + 0x4DE5, 0x4DE6, 0x4DE7, 0x4DE8, 0x4DE9, 0x4DEA, 0x4DEB, 0x4DEC, 0x4DED, + 0x4DEE, 0x4DEF, 0x4DF0, 0x4DF1, 0x4DF2, 0x4DF3, 0x4DF4, 0x4DF5, 0x4DF6, + 0x4DF7, 0x4DF8, 0x4DF9, 0x4DFA, 0x4DFB, 0x4DFC, 0x4DFD, 0x4DFE, 0x4DFF, + 0xE76C, 0xE7C8, 0xE7E7, 0xE7E8, 0xE7E9, 0xE7EA, 0xE7EB, 0xE7EC, 0xE7ED, + 0xE7EE, 0xE7EF, 0xE7F0, 0xE7F1, 0xE7F2, 0xE7F3, 0xE815, 0xE819, 0xE81A, + 0xE81B, 0xE81C, 0xE81D, 0xE81F, 0xE820, 0xE821, 0xE822, 0xE823, 0xE824, + 0xE825, 0xE827, 0xE828, 0xE829, 0xE82A, 0xE82D, 0xE82E, 0xE82F, 0xE830, + 0xE833, 0xE834, 0xE835, 0xE836, 0xE837, 0xE838, 0xE839, 0xE83A, 0xE83C, + 0xE83D, 0xE83E, 0xE83F, 0xE840, 0xE841, 0xE842, 0xE844, 0xE845, 0xE846, + 0xE847, 0xE848, 0xE849, 0xE84A, 0xE84B, 0xE84C, 0xE84D, 0xE84E, 0xE84F, + 0xE850, 0xE851, 0xE852, 0xE853, 0xE856, 0xE857, 0xE858, 0xE859, 0xE85A, + 0xE85B, 0xE85C, 0xE85D, 0xE85E, 0xE85F, 0xE860, 0xE861, 0xE862, 0xE863, + 0xF92D, 0xF92E, 0xF92F, 0xF930, 0xF931, 0xF932, 0xF933, 0xF934, 0xF935, + 0xF936, 0xF937, 0xF938, 0xF939, 0xF93A, 0xF93B, 0xF93C, 0xF93D, 0xF93E, + 0xF93F, 0xF940, 0xF941, 0xF942, 0xF943, 0xF944, 0xF945, 0xF946, 0xF947, + 0xF948, 0xF949, 0xF94A, 0xF94B, 0xF94C, 0xF94D, 0xF94E, 0xF94F, 0xF950, + 0xF951, 0xF952, 0xF953, 0xF954, 0xF955, 0xF956, 0xF957, 0xF958, 0xF959, + 0xF95A, 0xF95B, 0xF95C, 0xF95D, 0xF95E, 0xF95F, 0xF960, 0xF961, 0xF962, + 0xF963, 0xF964, 0xF965, 0xF966, 0xF967, 0xF968, 0xF969, 0xF96A, 0xF96B, + 0xF96C, 0xF96D, 0xF96E, 0xF96F, 0xF970, 0xF971, 0xF972, 0xF973, 0xF974, + 0xF975, 0xF976, 0xF977, 0xF978, 0xF97A, 0xF97B, 0xF97C, 0xF97D, 0xF97E, + 0xF97F, 0xF980, 0xF981, 0xF982, 0xF983, 0xF984, 0xF985, 0xF986, 0xF987, + 0xF988, 0xF989, 0xF98A, 0xF98B, 0xF98C, 0xF98D, 0xF98E, 0xF98F, 0xF990, + 0xF991, 0xF992, 0xF993, 0xF994, 0xF996, 0xF997, 0xF998, 0xF999, 0xF99A, + 0xF99B, 0xF99C, 0xF99D, 0xF99E, 0xF99F, 0xF9A0, 0xF9A1, 0xF9A2, 0xF9A3, + 0xF9A4, 0xF9A5, 0xF9A6, 0xF9A7, 0xF9A8, 0xF9A9, 0xF9AA, 0xF9AB, 0xF9AC, + 0xF9AD, 0xF9AE, 0xF9AF, 0xF9B0, 0xF9B1, 0xF9B2, 0xF9B3, 0xF9B4, 0xF9B5, + 0xF9B6, 0xF9B7, 0xF9B8, 0xF9B9, 0xF9BA, 0xF9BB, 0xF9BC, 0xF9BD, 0xF9BE, + 0xF9BF, 0xF9C0, 0xF9C1, 0xF9C2, 0xF9C3, 0xF9C4, 0xF9C5, 0xF9C6, 0xF9C7, + 0xF9C8, 0xF9C9, 0xF9CA, 0xF9CB, 0xF9CC, 0xF9CD, 0xF9CE, 0xF9CF, 0xF9D0, + 0xF9D1, 0xF9D2, 0xF9D3, 0xF9D4, 0xF9D5, 0xF9D6, 0xF9D7, 0xF9D8, 0xF9D9, + 0xF9DA, 0xF9DB, 0xF9DC, 0xF9DD, 0xF9DE, 0xF9DF, 0xF9E0, 0xF9E1, 0xF9E2, + 0xF9E3, 0xF9E4, 0xF9E5, 0xF9E6, 0xF9E8, 0xF9E9, 0xF9EA, 0xF9EB, 0xF9EC, + 0xF9ED, 0xF9EE, 0xF9EF, 0xF9F0, 0xF9F2, 0xF9F3, 0xF9F4, 0xF9F5, 0xF9F6, + 0xF9F7, 0xF9F8, 0xF9F9, 0xF9FA, 0xF9FB, 0xF9FC, 0xF9FD, 0xF9FE, 0xF9FF, + 0xFA00, 0xFA01, 0xFA02, 0xFA03, 0xFA04, 0xFA05, 0xFA06, 0xFA07, 0xFA08, + 0xFA09, 0xFA0A, 0xFA0B, 0xFA10, 0xFA12, 0xFA15, 0xFA16, 0xFA17, 0xFA19, + 0xFA1A, 0xFA1B, 0xFA1C, 0xFA1D, 0xFA1E, 0xFA22, 0xFA25, 0xFA26, 0xFE32, + 0xFE45, 0xFE46, 0xFE47, 0xFE48, 0xFE53, 0xFE58, 0xFE67, 0xFE6C, 0xFE6D, + 0xFE6E, 0xFE6F, 0xFE70, 0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE75, 0xFE76, + 0xFE77, 0xFE78, 0xFE79, 0xFE7A, 0xFE7B, 0xFE7C, 0xFE7D, 0xFE7E, 0xFE7F, + 0xFE80, 0xFE81, 0xFE82, 0xFE83, 0xFE84, 0xFE85, 0xFE86, 0xFE87, 0xFE88, + 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, 0xFE8D, 0xFE8E, 0xFE8F, 0xFE90, 0xFE91, + 0xFE92, 0xFE93, 0xFE94, 0xFE95, 0xFE96, 0xFE97, 0xFE98, 0xFE99, 0xFE9A, + 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, + 0xFEA4, 0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, + 0xFEAD, 0xFEAE, 0xFEAF, 0xFEB0, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, + 0xFEB6, 0xFEB7, 0xFEB8, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, + 0xFEBF, 0xFEC0, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7, + 0xFEC8, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, 0xFECD, 0xFECE, 0xFECF, 0xFED0, + 0xFED1, 0xFED2, 0xFED3, 0xFED4, 0xFED5, 0xFED6, 0xFED7, 0xFED8, 0xFED9, + 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0, 0xFEE1, 0xFEE2, + 0xFEE3, 0xFEE4, 0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, + 0xFEEC, 0xFEED, 0xFEEE, 0xFEEF, 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, + 0xFEF5, 0xFEF6, 0xFEF7, 0xFEF8, 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, + 0xFEFE, 0xFEFF, 0xFF00, 0xFF5F, 0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, + 0xFF65, 0xFF66, 0xFF67, 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, + 0xFF6E, 0xFF6F, 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, + 0xFF77, 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, + 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, 0xFF88, + 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, 0xFF90, 0xFF91, + 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, 0xFF98, 0xFF99, 0xFF9A, + 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, + 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7, 0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, + 0xFFAD, 0xFFAE, 0xFFAF, 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, + 0xFFB6, 0xFFB7, 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, + 0xFFBF, 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7, + 0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF, 0xFFD0, + 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7, 0xFFD8, 0xFFD9, + 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF, 0xFFE6, 0xFFE7, 0xFFE8, + 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF, 0xFFF0, 0xFFF1, + 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7, 0xFFF8, 0xFFF9, 0xFFFA, + 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF}; + +static const uint16_t tab_uni_gb18030_p1[] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, + 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, + 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, + 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, + 0xA1E8, 0x0024, 0x0025, 0xA1EC, 0xA1A7, 0x0026, 0x0027, 0x0028, 0x0029, + 0x002A, 0x002B, 0x002C, 0xA1E3, 0xA1C0, 0x002D, 0x002E, 0x002F, 0x0030, + 0x0031, 0xA1A4, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, + 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, + 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, + 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0xA1C1, 0x0051, 0x0052, + 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0xA8A4, 0xA8A2, 0x0059, + 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0xA8A8, 0xA8A6, 0xA8BA, 0x005F, + 0xA8AC, 0xA8AA, 0x0060, 0x0061, 0x0062, 0x0063, 0xA8B0, 0xA8AE, 0x0064, + 0x0065, 0x0066, 0xA1C2, 0x0067, 0xA8B4, 0xA8B2, 0x0068, 0xA8B9, 0x0069, + 0x006A, 0x006B, 0x006C, 0xA8A1, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, + 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, + 0x007B, 0x007C, 0x007D, 0xA8A5, 0x007E, 0x007F, 0x0080, 0x0081, 0x0082, + 0x0083, 0x0084, 0xA8A7, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, + 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, 0x0090, 0x0091, 0x0092, 0x0093, + 0xA8A9, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, + 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, + 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0xA8BD, 0x00AC, + 0x00AD, 0x00AE, 0xA8BE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0xA8AD, 0x00B3, + 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, + 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, + 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, + 0x00CF, 0xA8B1, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, + 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, + 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, + 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, + 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, 0x0100, 0x0101, 0x0102, 0x0103, + 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x010A, 0x010B, 0x010C, + 0x010D, 0x010E, 0x010F, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, + 0x0116, 0x0117, 0x0118, 0x0119, 0x011A, 0x011B, 0x011C, 0x011D, 0x011E, + 0x011F, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126, 0x0127, + 0x0128, 0x0129, 0x012A, 0x012B, 0x012C, 0x012D, 0x012E, 0x012F, 0x0130, + 0x0131, 0xA8A3, 0x0132, 0xA8AB, 0x0133, 0xA8AF, 0x0134, 0xA8B3, 0x0135, + 0xA8B5, 0x0136, 0xA8B6, 0x0137, 0xA8B7, 0x0138, 0xA8B8, 0x0139, 0x013A, + 0x013B, 0x013C, 0x013D, 0x013E, 0x013F, 0x0140, 0x0141, 0x0142, 0x0143, + 0x0144, 0x0145, 0x0146, 0x0147, 0x0148, 0x0149, 0x014A, 0x014B, 0x014C, + 0x014D, 0x014E, 0x014F, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0xA8BF, + 0x0155, 0x0156, 0x0157, 0x0158, 0x0159, 0x015A, 0x015B, 0x015C, 0x015D, + 0x015E, 0x015F, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165, 0x0166, + 0x0167, 0x0168, 0x0169, 0x016A, 0x016B, 0x016C, 0x016D, 0x016E, 0x016F, + 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175, 0x0176, 0x0177, 0x0178, + 0x0179, 0x017A, 0x017B, 0x017C, 0x017D, 0x017E, 0x017F, 0x0180, 0x0181, + 0x0182, 0x0183, 0x0184, 0x0185, 0x0186, 0x0187, 0x0188, 0x0189, 0x018A, + 0x018B, 0x018C, 0x018D, 0x018E, 0x018F, 0x0190, 0x0191, 0x0192, 0x0193, + 0x0194, 0x0195, 0x0196, 0x0197, 0x0198, 0x0199, 0x019A, 0x019B, 0x019C, + 0x019D, 0x019E, 0x019F, 0x01A0, 0x01A1, 0x01A2, 0x01A3, 0x01A4, 0x01A5, + 0x01A6, 0x01A7, 0x01A8, 0x01A9, 0x01AA, 0x01AB, 0xA8BB, 0x01AC, 0x01AD, + 0x01AE, 0x01AF, 0x01B0, 0x01B1, 0x01B2, 0x01B3, 0x01B4, 0x01B5, 0x01B6, + 0x01B7, 0x01B8, 0x01B9, 0x01BA, 0xA8C0, 0x01BB, 0x01BC, 0x01BD, 0x01BE, + 0x01BF, 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C5, 0x01C6, 0x01C7, + 0x01C8, 0x01C9, 0x01CA, 0x01CB, 0x01CC, 0x01CD, 0x01CE, 0x01CF, 0x01D0, + 0x01D1, 0x01D2, 0x01D3, 0x01D4, 0x01D5, 0x01D6, 0x01D7, 0x01D8, 0x01D9, + 0x01DA, 0x01DB, 0x01DC, 0x01DD, 0x01DE, 0x01DF, 0x01E0, 0x01E1, 0x01E2, + 0x01E3, 0x01E4, 0x01E5, 0x01E6, 0x01E7, 0x01E8, 0x01E9, 0x01EA, 0x01EB, + 0x01EC, 0x01ED, 0x01EE, 0x01EF, 0x01F0, 0x01F1, 0x01F2, 0x01F3, 0x01F4, + 0x01F5, 0x01F6, 0x01F7, 0x01F8, 0x01F9, 0x01FA, 0x01FB, 0x01FC, 0x01FD, + 0x01FE, 0x01FF, 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, 0x0206, + 0x0207, 0x0208, 0x0209, 0x020A, 0x020B, 0x020C, 0x020D, 0x020E, 0x020F, + 0x0210, 0x0211, 0x0212, 0x0213, 0x0214, 0x0215, 0x0216, 0x0217, 0x0218, + 0x0219, 0x021A, 0x021B, 0x021C, 0x021D, 0x021E, 0x021F, 0xA1A6, 0x0220, + 0xA1A5, 0xA840, 0xA841, 0x0221, 0x0222, 0x0223, 0x0224, 0x0225, 0x0226, + 0x0227, 0x0228, 0x0229, 0x022A, 0x022B, 0x022C, 0x022D, 0xA842, 0x022E, + 0x022F, 0x0230, 0x0231, 0x0232, 0x0233, 0x0234, 0x0235, 0x0236, 0x0237, + 0x0238, 0x0239, 0x023A, 0x023B, 0x023C, 0x023D, 0x023E, 0x023F, 0x0240, + 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247, 0x0248, 0x0249, + 0x024A, 0x024B, 0x024C, 0x024D, 0x024E, 0x024F, 0x0250, 0x0251, 0x0252, + 0x0253, 0x0254, 0x0255, 0x0256, 0x0257, 0x0258, 0x0259, 0x025A, 0x025B, + 0x025C, 0x025D, 0x025E, 0x025F, 0x0260, 0x0261, 0x0262, 0x0263, 0x0264, + 0x0265, 0x0266, 0x0267, 0x0268, 0x0269, 0x026A, 0x026B, 0x026C, 0x026D, + 0x026E, 0x026F, 0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0275, 0x0276, + 0x0277, 0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F, + 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0286, 0x0287, 0x0288, + 0x0289, 0x028A, 0x028B, 0x028C, 0x028D, 0x028E, 0x028F, 0x0290, 0x0291, + 0x0292, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297, 0x0298, 0x0299, 0x029A, + 0x029B, 0x029C, 0x029D, 0x029E, 0x029F, 0x02A0, 0x02A1, 0x02A2, 0x02A3, + 0x02A4, 0x02A5, 0x02A6, 0x02A7, 0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x02AC, + 0x02AD, 0x02AE, 0x02AF, 0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, + 0x02B6, 0x02B7, 0x02B8, 0x02B9, 0x02BA, 0x02BB, 0x02BC, 0x02BD, 0x02BE, + 0x02BF, 0x02C0, 0x02C1, 0x02C2, 0x02C3, 0x02C4, 0x02C5, 0x02C6, 0x02C7, + 0x02C8, 0x02C9, 0x02CA, 0x02CB, 0x02CC, 0x02CD, 0x02CE, 0x02CF, 0x02D0, + 0x02D1, 0x02D2, 0x02D3, 0x02D4, 0x02D5, 0x02D6, 0x02D7, 0x02D8, 0x02D9, + 0x02DA, 0x02DB, 0x02DC, 0x02DD, 0x02DE, 0x02DF, 0x02E0, 0x02E1, 0x02E2, + 0x02E3, 0x02E4, 0xA6A1, 0xA6A2, 0xA6A3, 0xA6A4, 0xA6A5, 0xA6A6, 0xA6A7, + 0xA6A8, 0xA6A9, 0xA6AA, 0xA6AB, 0xA6AC, 0xA6AD, 0xA6AE, 0xA6AF, 0xA6B0, + 0xA6B1, 0x02E5, 0xA6B2, 0xA6B3, 0xA6B4, 0xA6B5, 0xA6B6, 0xA6B7, 0xA6B8, + 0x02E6, 0x02E7, 0x02E8, 0x02E9, 0x02EA, 0x02EB, 0x02EC, 0xA6C1, 0xA6C2, + 0xA6C3, 0xA6C4, 0xA6C5, 0xA6C6, 0xA6C7, 0xA6C8, 0xA6C9, 0xA6CA, 0xA6CB, + 0xA6CC, 0xA6CD, 0xA6CE, 0xA6CF, 0xA6D0, 0xA6D1, 0x02ED, 0xA6D2, 0xA6D3, + 0xA6D4, 0xA6D5, 0xA6D6, 0xA6D7, 0xA6D8, 0x02EE, 0x02EF, 0x02F0, 0x02F1, + 0x02F2, 0x02F3, 0x02F4, 0x02F5, 0x02F6, 0x02F7, 0x02F8, 0x02F9, 0x02FA, + 0x02FB, 0x02FC, 0x02FD, 0x02FE, 0x02FF, 0x0300, 0x0301, 0x0302, 0x0303, + 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, + 0x030D, 0x030E, 0x030F, 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, + 0x0316, 0x0317, 0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, + 0x031F, 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0xA7A7, 0x0325, 0x0326, + 0x0327, 0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F, + 0x0330, 0x0331, 0x0332, 0xA7A1, 0xA7A2, 0xA7A3, 0xA7A4, 0xA7A5, 0xA7A6, + 0xA7A8, 0xA7A9, 0xA7AA, 0xA7AB, 0xA7AC, 0xA7AD, 0xA7AE, 0xA7AF, 0xA7B0, + 0xA7B1, 0xA7B2, 0xA7B3, 0xA7B4, 0xA7B5, 0xA7B6, 0xA7B7, 0xA7B8, 0xA7B9, + 0xA7BA, 0xA7BB, 0xA7BC, 0xA7BD, 0xA7BE, 0xA7BF, 0xA7C0, 0xA7C1, 0xA7D1, + 0xA7D2, 0xA7D3, 0xA7D4, 0xA7D5, 0xA7D6, 0xA7D8, 0xA7D9, 0xA7DA, 0xA7DB, + 0xA7DC, 0xA7DD, 0xA7DE, 0xA7DF, 0xA7E0, 0xA7E1, 0xA7E2, 0xA7E3, 0xA7E4, + 0xA7E5, 0xA7E6, 0xA7E7, 0xA7E8, 0xA7E9, 0xA7EA, 0xA7EB, 0xA7EC, 0xA7ED, + 0xA7EE, 0xA7EF, 0xA7F0, 0xA7F1, 0x0333, 0xA7D7, 0x0334, 0x0335, 0x0336, + 0x0337, 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F, + 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347, 0x0348, + 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F, 0x0350, 0x0351, + 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, 0x0358, 0x0359, 0x035A, + 0x035B, 0x035C, 0x035D, 0x035E, 0x035F, 0x0360, 0x0361, 0x0362, 0x0363, + 0x0364, 0x0365, 0x0366, 0x0367, 0x0368, 0x0369, 0x036A, 0x036B, 0x036C, + 0x036D, 0x036E, 0x036F, 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, + 0x0376, 0x0377, 0x0378, 0x0379, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, + 0x037F, 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387, + 0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F, 0x0390, + 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, + 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, 0x03A1, 0x03A2, + 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03AA, 0x03AB, + 0x03AC, 0x03AD, 0x03AE, 0x03AF, 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, + 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, + 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, + 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03CF, + 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7, 0x03D8, + 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF, 0x03E0, 0x03E1, + 0x03E2, 0x03E3, 0x03E4, 0x03E5, 0x03E6, 0x03E7, 0x03E8, 0x03E9, 0x03EA, + 0x03EB, 0x03EC, 0x03ED, 0x03EE, 0x03EF, 0x03F0, 0x03F1, 0x03F2, 0x03F3, + 0x03F4, 0x03F5, 0x03F6, 0x03F7, 0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, + 0x03FD, 0x03FE, 0x03FF, 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, + 0x0406, 0x0407, 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040D, 0x040E, + 0x040F, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0420, + 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, + 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, 0x0430, 0x0431, 0x0432, + 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, + 0x043C, 0x043D, 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, + 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, + 0x044E, 0x044F, 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, + 0x0457, 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F, + 0x0460, 0x0461, 0x0462, 0x0463, 0x0464, 0x0465, 0x0466, 0x0467, 0x0468, + 0x0469, 0x046A, 0x046B, 0x046C, 0x046D, 0x046E, 0x046F, 0x0470, 0x0471, + 0x0472, 0x0473, 0x0474, 0x0475, 0x0476, 0x0477, 0x0478, 0x0479, 0x047A, + 0x047B, 0x047C, 0x047D, 0x047E, 0x047F, 0x0480, 0x0481, 0x0482, 0x0483, + 0x0484, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489, 0x048A, 0x048B, 0x048C, + 0x048D, 0x048E, 0x048F, 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, + 0x0496, 0x0497, 0x0498, 0x0499, 0x049A, 0x049B, 0x049C, 0x049D, 0x049E, + 0x049F, 0x04A0, 0x04A1, 0x04A2, 0x04A3, 0x04A4, 0x04A5, 0x04A6, 0x04A7, + 0x04A8, 0x04A9, 0x04AA, 0x04AB, 0x04AC, 0x04AD, 0x04AE, 0x04AF, 0x04B0, + 0x04B1, 0x04B2, 0x04B3, 0x04B4, 0x04B5, 0x04B6, 0x04B7, 0x04B8, 0x04B9, + 0x04BA, 0x04BB, 0x04BC, 0x04BD, 0x04BE, 0x04BF, 0x04C0, 0x04C1, 0x04C2, + 0x04C3, 0x04C4, 0x04C5, 0x04C6, 0x04C7, 0x04C8, 0x04C9, 0x04CA, 0x04CB, + 0x04CC, 0x04CD, 0x04CE, 0x04CF, 0x04D0, 0x04D1, 0x04D2, 0x04D3, 0x04D4, + 0x04D5, 0x04D6, 0x04D7, 0x04D8, 0x04D9, 0x04DA, 0x04DB, 0x04DC, 0x04DD, + 0x04DE, 0x04DF, 0x04E0, 0x04E1, 0x04E2, 0x04E3, 0x04E4, 0x04E5, 0x04E6, + 0x04E7, 0x04E8, 0x04E9, 0x04EA, 0x04EB, 0x04EC, 0x04ED, 0x04EE, 0x04EF, + 0x04F0, 0x04F1, 0x04F2, 0x04F3, 0x04F4, 0x04F5, 0x04F6, 0x04F7, 0x04F8, + 0x04F9, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF, 0x0500, 0x0501, + 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509, 0x050A, + 0x050B, 0x050C, 0x050D, 0x050E, 0x050F, 0x0510, 0x0511, 0x0512, 0x0513, + 0x0514, 0x0515, 0x0516, 0x0517, 0x0518, 0x0519, 0x051A, 0x051B, 0x051C, + 0x051D, 0x051E, 0x051F, 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, + 0x0526, 0x0527, 0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, + 0x052F, 0x0530, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537, + 0x0538, 0x0539, 0x053A, 0x053B, 0x053C, 0x053D, 0x053E, 0x053F, 0x0540, + 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547, 0x0548, 0x0549, + 0x054A, 0x054B, 0x054C, 0x054D, 0x054E, 0x054F, 0x0550, 0x0551, 0x0552, + 0x0553, 0x0554, 0x0555, 0x0556, 0x0557, 0x0558, 0x0559, 0x055A, 0x055B, + 0x055C, 0x055D, 0x055E, 0x055F, 0x0560, 0x0561, 0x0562, 0x0563, 0x0564, + 0x0565, 0x0566, 0x0567, 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, + 0x056E, 0x056F, 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, + 0x0577, 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F, + 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587, 0x0588, + 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F, 0x0590, 0x0591, + 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597, 0x0598, 0x0599, 0x059A, + 0x059B, 0x059C, 0x059D, 0x059E, 0x059F, 0x05A0, 0x05A1, 0x05A2, 0x05A3, + 0x05A4, 0x05A5, 0x05A6, 0x05A7, 0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, + 0x05AD, 0x05AE, 0x05AF, 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, + 0x05B6, 0x05B7, 0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, + 0x05BF, 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x05C5, 0x05C6, 0x05C7, + 0x05C8, 0x05C9, 0x05CA, 0x05CB, 0x05CC, 0x05CD, 0x05CE, 0x05CF, 0x05D0, + 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, + 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1, 0x05E2, + 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x05EB, + 0x05EC, 0x05ED, 0x05EE, 0x05EF, 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, + 0x05F5, 0x05F6, 0x05F7, 0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, + 0x05FE, 0x05FF, 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, 0x0606, + 0x0607, 0x0608, 0x0609, 0x060A, 0x060B, 0x060C, 0x060D, 0x060E, 0x060F, + 0x0610, 0x0611, 0x0612, 0x0613, 0x0614, 0x0615, 0x0616, 0x0617, 0x0618, + 0x0619, 0x061A, 0x061B, 0x061C, 0x061D, 0x061E, 0x061F, 0x0620, 0x0621, + 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, + 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, + 0x0634, 0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x063B, 0x063C, + 0x063D, 0x063E, 0x063F, 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, + 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, 0x064B, 0x064C, 0x064D, 0x064E, + 0x064F, 0x0650, 0x0651, 0x0652, 0x0653, 0x0654, 0x0655, 0x0656, 0x0657, + 0x0658, 0x0659, 0x065A, 0x065B, 0x065C, 0x065D, 0x065E, 0x065F, 0x0660, + 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668, 0x0669, + 0x066A, 0x066B, 0x066C, 0x066D, 0x066E, 0x066F, 0x0670, 0x0671, 0x0672, + 0x0673, 0x0674, 0x0675, 0x0676, 0x0677, 0x0678, 0x0679, 0x067A, 0x067B, + 0x067C, 0x067D, 0x067E, 0x067F, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, + 0x0685, 0x0686, 0x0687, 0x0688, 0x0689, 0x068A, 0x068B, 0x068C, 0x068D, + 0x068E, 0x068F, 0x0690, 0x0691, 0x0692, 0x0693, 0x0694, 0x0695, 0x0696, + 0x0697, 0x0698, 0x0699, 0x069A, 0x069B, 0x069C, 0x069D, 0x069E, 0x069F, + 0x06A0, 0x06A1, 0x06A2, 0x06A3, 0x06A4, 0x06A5, 0x06A6, 0x06A7, 0x06A8, + 0x06A9, 0x06AA, 0x06AB, 0x06AC, 0x06AD, 0x06AE, 0x06AF, 0x06B0, 0x06B1, + 0x06B2, 0x06B3, 0x06B4, 0x06B5, 0x06B6, 0x06B7, 0x06B8, 0x06B9, 0x06BA, + 0x06BB, 0x06BC, 0x06BD, 0x06BE, 0x06BF, 0x06C0, 0x06C1, 0x06C2, 0x06C3, + 0x06C4, 0x06C5, 0x06C6, 0x06C7, 0x06C8, 0x06C9, 0x06CA, 0x06CB, 0x06CC, + 0x06CD, 0x06CE, 0x06CF, 0x06D0, 0x06D1, 0x06D2, 0x06D3, 0x06D4, 0x06D5, + 0x06D6, 0x06D7, 0x06D8, 0x06D9, 0x06DA, 0x06DB, 0x06DC, 0x06DD, 0x06DE, + 0x06DF, 0x06E0, 0x06E1, 0x06E2, 0x06E3, 0x06E4, 0x06E5, 0x06E6, 0x06E7, + 0x06E8, 0x06E9, 0x06EA, 0x06EB, 0x06EC, 0x06ED, 0x06EE, 0x06EF, 0x06F0, + 0x06F1, 0x06F2, 0x06F3, 0x06F4, 0x06F5, 0x06F6, 0x06F7, 0x06F8, 0x06F9, + 0x06FA, 0x06FB, 0x06FC, 0x06FD, 0x06FE, 0x06FF, 0x0700, 0x0701, 0x0702, + 0x0703, 0x0704, 0x0705, 0x0706, 0x0707, 0x0708, 0x0709, 0x070A, 0x070B, + 0x070C, 0x070D, 0x070E, 0x070F, 0x0710, 0x0711, 0x0712, 0x0713, 0x0714, + 0x0715, 0x0716, 0x0717, 0x0718, 0x0719, 0x071A, 0x071B, 0x071C, 0x071D, + 0x071E, 0x071F, 0x0720, 0x0721, 0x0722, 0x0723, 0x0724, 0x0725, 0x0726, + 0x0727, 0x0728, 0x0729, 0x072A, 0x072B, 0x072C, 0x072D, 0x072E, 0x072F, + 0x0730, 0x0731, 0x0732, 0x0733, 0x0734, 0x0735, 0x0736, 0x0737, 0x0738, + 0x0739, 0x073A, 0x073B, 0x073C, 0x073D, 0x073E, 0x073F, 0x0740, 0x0741, + 0x0742, 0x0743, 0x0744, 0x0745, 0x0746, 0x0747, 0x0748, 0x0749, 0x074A, + 0x074B, 0x074C, 0x074D, 0x074E, 0x074F, 0x0750, 0x0751, 0x0752, 0x0753, + 0x0754, 0x0755, 0x0756, 0x0757, 0x0758, 0x0759, 0x075A, 0x075B, 0x075C, + 0x075D, 0x075E, 0x075F, 0x0760, 0x0761, 0x0762, 0x0763, 0x0764, 0x0765, + 0x0766, 0x0767, 0x0768, 0x0769, 0x076A, 0x076B, 0x076C, 0x076D, 0x076E, + 0x076F, 0x0770, 0x0771, 0x0772, 0x0773, 0x0774, 0x0775, 0x0776, 0x0777, + 0x0778, 0x0779, 0x077A, 0x077B, 0x077C, 0x077D, 0x077E, 0x077F, 0x0780, + 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0786, 0x0787, 0x0788, 0x0789, + 0x078A, 0x078B, 0x078C, 0x078D, 0x078E, 0x078F, 0x0790, 0x0791, 0x0792, + 0x0793, 0x0794, 0x0795, 0x0796, 0x0797, 0x0798, 0x0799, 0x079A, 0x079B, + 0x079C, 0x079D, 0x079E, 0x079F, 0x07A0, 0x07A1, 0x07A2, 0x07A3, 0x07A4, + 0x07A5, 0x07A6, 0x07A7, 0x07A8, 0x07A9, 0x07AA, 0x07AB, 0x07AC, 0x07AD, + 0x07AE, 0x07AF, 0x07B0, 0x07B1, 0x07B2, 0x07B3, 0x07B4, 0x07B5, 0x07B6, + 0x07B7, 0x07B8, 0x07B9, 0x07BA, 0x07BB, 0x07BC, 0x07BD, 0x07BE, 0x07BF, + 0x07C0, 0x07C1, 0x07C2, 0x07C3, 0x07C4, 0x07C5, 0x07C6, 0x07C7, 0x07C8, + 0x07C9, 0x07CA, 0x07CB, 0x07CC, 0x07CD, 0x07CE, 0x07CF, 0x07D0, 0x07D1, + 0x07D2, 0x07D3, 0x07D4, 0x07D5, 0x07D6, 0x07D7, 0x07D8, 0x07D9, 0x07DA, + 0x07DB, 0x07DC, 0x07DD, 0x07DE, 0x07DF, 0x07E0, 0x07E1, 0x07E2, 0x07E3, + 0x07E4, 0x07E5, 0x07E6, 0x07E7, 0x07E8, 0x07E9, 0x07EA, 0x07EB, 0x07EC, + 0x07ED, 0x07EE, 0x07EF, 0x07F0, 0x07F1, 0x07F2, 0x07F3, 0x07F4, 0x07F5, + 0x07F6, 0x07F7, 0x07F8, 0x07F9, 0x07FA, 0x07FB, 0x07FC, 0x07FD, 0x07FE, + 0x07FF, 0x0800, 0x0801, 0x0802, 0x0803, 0x0804, 0x0805, 0x0806, 0x0807, + 0x0808, 0x0809, 0x080A, 0x080B, 0x080C, 0x080D, 0x080E, 0x080F, 0x0810, + 0x0811, 0x0812, 0x0813, 0x0814, 0x0815, 0x0816, 0x0817, 0x0818, 0x0819, + 0x081A, 0x081B, 0x081C, 0x081D, 0x081E, 0x081F, 0x0820, 0x0821, 0x0822, + 0x0823, 0x0824, 0x0825, 0x0826, 0x0827, 0x0828, 0x0829, 0x082A, 0x082B, + 0x082C, 0x082D, 0x082E, 0x082F, 0x0830, 0x0831, 0x0832, 0x0833, 0x0834, + 0x0835, 0x0836, 0x0837, 0x0838, 0x0839, 0x083A, 0x083B, 0x083C, 0x083D, + 0x083E, 0x083F, 0x0840, 0x0841, 0x0842, 0x0843, 0x0844, 0x0845, 0x0846, + 0x0847, 0x0848, 0x0849, 0x084A, 0x084B, 0x084C, 0x084D, 0x084E, 0x084F, + 0x0850, 0x0851, 0x0852, 0x0853, 0x0854, 0x0855, 0x0856, 0x0857, 0x0858, + 0x0859, 0x085A, 0x085B, 0x085C, 0x085D, 0x085E, 0x085F, 0x0860, 0x0861, + 0x0862, 0x0863, 0x0864, 0x0865, 0x0866, 0x0867, 0x0868, 0x0869, 0x086A, + 0x086B, 0x086C, 0x086D, 0x086E, 0x086F, 0x0870, 0x0871, 0x0872, 0x0873, + 0x0874, 0x0875, 0x0876, 0x0877, 0x0878, 0x0879, 0x087A, 0x087B, 0x087C, + 0x087D, 0x087E, 0x087F, 0x0880, 0x0881, 0x0882, 0x0883, 0x0884, 0x0885, + 0x0886, 0x0887, 0x0888, 0x0889, 0x088A, 0x088B, 0x088C, 0x088D, 0x088E, + 0x088F, 0x0890, 0x0891, 0x0892, 0x0893, 0x0894, 0x0895, 0x0896, 0x0897, + 0x0898, 0x0899, 0x089A, 0x089B, 0x089C, 0x089D, 0x089E, 0x089F, 0x08A0, + 0x08A1, 0x08A2, 0x08A3, 0x08A4, 0x08A5, 0x08A6, 0x08A7, 0x08A8, 0x08A9, + 0x08AA, 0x08AB, 0x08AC, 0x08AD, 0x08AE, 0x08AF, 0x08B0, 0x08B1, 0x08B2, + 0x08B3, 0x08B4, 0x08B5, 0x08B6, 0x08B7, 0x08B8, 0x08B9, 0x08BA, 0x08BB, + 0x08BC, 0x08BD, 0x08BE, 0x08BF, 0x08C0, 0x08C1, 0x08C2, 0x08C3, 0x08C4, + 0x08C5, 0x08C6, 0x08C7, 0x08C8, 0x08C9, 0x08CA, 0x08CB, 0x08CC, 0x08CD, + 0x08CE, 0x08CF, 0x08D0, 0x08D1, 0x08D2, 0x08D3, 0x08D4, 0x08D5, 0x08D6, + 0x08D7, 0x08D8, 0x08D9, 0x08DA, 0x08DB, 0x08DC, 0x08DD, 0x08DE, 0x08DF, + 0x08E0, 0x08E1, 0x08E2, 0x08E3, 0x08E4, 0x08E5, 0x08E6, 0x08E7, 0x08E8, + 0x08E9, 0x08EA, 0x08EB, 0x08EC, 0x08ED, 0x08EE, 0x08EF, 0x08F0, 0x08F1, + 0x08F2, 0x08F3, 0x08F4, 0x08F5, 0x08F6, 0x08F7, 0x08F8, 0x08F9, 0x08FA, + 0x08FB, 0x08FC, 0x08FD, 0x08FE, 0x08FF, 0x0900, 0x0901, 0x0902, 0x0903, + 0x0904, 0x0905, 0x0906, 0x0907, 0x0908, 0x0909, 0x090A, 0x090B, 0x090C, + 0x090D, 0x090E, 0x090F, 0x0910, 0x0911, 0x0912, 0x0913, 0x0914, 0x0915, + 0x0916, 0x0917, 0x0918, 0x0919, 0x091A, 0x091B, 0x091C, 0x091D, 0x091E, + 0x091F, 0x0920, 0x0921, 0x0922, 0x0923, 0x0924, 0x0925, 0x0926, 0x0927, + 0x0928, 0x0929, 0x092A, 0x092B, 0x092C, 0x092D, 0x092E, 0x092F, 0x0930, + 0x0931, 0x0932, 0x0933, 0x0934, 0x0935, 0x0936, 0x0937, 0x0938, 0x0939, + 0x093A, 0x093B, 0x093C, 0x093D, 0x093E, 0x093F, 0x0940, 0x0941, 0x0942, + 0x0943, 0x0944, 0x0945, 0x0946, 0x0947, 0x0948, 0x0949, 0x094A, 0x094B, + 0x094C, 0x094D, 0x094E, 0x094F, 0x0950, 0x0951, 0x0952, 0x0953, 0x0954, + 0x0955, 0x0956, 0x0957, 0x0958, 0x0959, 0x095A, 0x095B, 0x095C, 0x095D, + 0x095E, 0x095F, 0x0960, 0x0961, 0x0962, 0x0963, 0x0964, 0x0965, 0x0966, + 0x0967, 0x0968, 0x0969, 0x096A, 0x096B, 0x096C, 0x096D, 0x096E, 0x096F, + 0x0970, 0x0971, 0x0972, 0x0973, 0x0974, 0x0975, 0x0976, 0x0977, 0x0978, + 0x0979, 0x097A, 0x097B, 0x097C, 0x097D, 0x097E, 0x097F, 0x0980, 0x0981, + 0x0982, 0x0983, 0x0984, 0x0985, 0x0986, 0x0987, 0x0988, 0x0989, 0x098A, + 0x098B, 0x098C, 0x098D, 0x098E, 0x098F, 0x0990, 0x0991, 0x0992, 0x0993, + 0x0994, 0x0995, 0x0996, 0x0997, 0x0998, 0x0999, 0x099A, 0x099B, 0x099C, + 0x099D, 0x099E, 0x099F, 0x09A0, 0x09A1, 0x09A2, 0x09A3, 0x09A4, 0x09A5, + 0x09A6, 0x09A7, 0x09A8, 0x09A9, 0x09AA, 0x09AB, 0x09AC, 0x09AD, 0x09AE, + 0x09AF, 0x09B0, 0x09B1, 0x09B2, 0x09B3, 0x09B4, 0x09B5, 0x09B6, 0x09B7, + 0x09B8, 0x09B9, 0x09BA, 0x09BB, 0x09BC, 0x09BD, 0x09BE, 0x09BF, 0x09C0, + 0x09C1, 0x09C2, 0x09C3, 0x09C4, 0x09C5, 0x09C6, 0x09C7, 0x09C8, 0x09C9, + 0x09CA, 0x09CB, 0x09CC, 0x09CD, 0x09CE, 0x09CF, 0x09D0, 0x09D1, 0x09D2, + 0x09D3, 0x09D4, 0x09D5, 0x09D6, 0x09D7, 0x09D8, 0x09D9, 0x09DA, 0x09DB, + 0x09DC, 0x09DD, 0x09DE, 0x09DF, 0x09E0, 0x09E1, 0x09E2, 0x09E3, 0x09E4, + 0x09E5, 0x09E6, 0x09E7, 0x09E8, 0x09E9, 0x09EA, 0x09EB, 0x09EC, 0x09ED, + 0x09EE, 0x09EF, 0x09F0, 0x09F1, 0x09F2, 0x09F3, 0x09F4, 0x09F5, 0x09F6, + 0x09F7, 0x09F8, 0x09F9, 0x09FA, 0x09FB, 0x09FC, 0x09FD, 0x09FE, 0x09FF, + 0x0A00, 0x0A01, 0x0A02, 0x0A03, 0x0A04, 0x0A05, 0x0A06, 0x0A07, 0x0A08, + 0x0A09, 0x0A0A, 0x0A0B, 0x0A0C, 0x0A0D, 0x0A0E, 0x0A0F, 0x0A10, 0x0A11, + 0x0A12, 0x0A13, 0x0A14, 0x0A15, 0x0A16, 0x0A17, 0x0A18, 0x0A19, 0x0A1A, + 0x0A1B, 0x0A1C, 0x0A1D, 0x0A1E, 0x0A1F, 0x0A20, 0x0A21, 0x0A22, 0x0A23, + 0x0A24, 0x0A25, 0x0A26, 0x0A27, 0x0A28, 0x0A29, 0x0A2A, 0x0A2B, 0x0A2C, + 0x0A2D, 0x0A2E, 0x0A2F, 0x0A30, 0x0A31, 0x0A32, 0x0A33, 0x0A34, 0x0A35, + 0x0A36, 0x0A37, 0x0A38, 0x0A39, 0x0A3A, 0x0A3B, 0x0A3C, 0x0A3D, 0x0A3E, + 0x0A3F, 0x0A40, 0x0A41, 0x0A42, 0x0A43, 0x0A44, 0x0A45, 0x0A46, 0x0A47, + 0x0A48, 0x0A49, 0x0A4A, 0x0A4B, 0x0A4C, 0x0A4D, 0x0A4E, 0x0A4F, 0x0A50, + 0x0A51, 0x0A52, 0x0A53, 0x0A54, 0x0A55, 0x0A56, 0x0A57, 0x0A58, 0x0A59, + 0x0A5A, 0x0A5B, 0x0A5C, 0x0A5D, 0x0A5E, 0x0A5F, 0x0A60, 0x0A61, 0x0A62, + 0x0A63, 0x0A64, 0x0A65, 0x0A66, 0x0A67, 0x0A68, 0x0A69, 0x0A6A, 0x0A6B, + 0x0A6C, 0x0A6D, 0x0A6E, 0x0A6F, 0x0A70, 0x0A71, 0x0A72, 0x0A73, 0x0A74, + 0x0A75, 0x0A76, 0x0A77, 0x0A78, 0x0A79, 0x0A7A, 0x0A7B, 0x0A7C, 0x0A7D, + 0x0A7E, 0x0A7F, 0x0A80, 0x0A81, 0x0A82, 0x0A83, 0x0A84, 0x0A85, 0x0A86, + 0x0A87, 0x0A88, 0x0A89, 0x0A8A, 0x0A8B, 0x0A8C, 0x0A8D, 0x0A8E, 0x0A8F, + 0x0A90, 0x0A91, 0x0A92, 0x0A93, 0x0A94, 0x0A95, 0x0A96, 0x0A97, 0x0A98, + 0x0A99, 0x0A9A, 0x0A9B, 0x0A9C, 0x0A9D, 0x0A9E, 0x0A9F, 0x0AA0, 0x0AA1, + 0x0AA2, 0x0AA3, 0x0AA4, 0x0AA5, 0x0AA6, 0x0AA7, 0x0AA8, 0x0AA9, 0x0AAA, + 0x0AAB, 0x0AAC, 0x0AAD, 0x0AAE, 0x0AAF, 0x0AB0, 0x0AB1, 0x0AB2, 0x0AB3, + 0x0AB4, 0x0AB5, 0x0AB6, 0x0AB7, 0x0AB8, 0x0AB9, 0x0ABA, 0x0ABB, 0x0ABC, + 0x0ABD, 0x0ABE, 0x0ABF, 0x0AC0, 0x0AC1, 0x0AC2, 0x0AC3, 0x0AC4, 0x0AC5, + 0x0AC6, 0x0AC7, 0x0AC8, 0x0AC9, 0x0ACA, 0x0ACB, 0x0ACC, 0x0ACD, 0x0ACE, + 0x0ACF, 0x0AD0, 0x0AD1, 0x0AD2, 0x0AD3, 0x0AD4, 0x0AD5, 0x0AD6, 0x0AD7, + 0x0AD8, 0x0AD9, 0x0ADA, 0x0ADB, 0x0ADC, 0x0ADD, 0x0ADE, 0x0ADF, 0x0AE0, + 0x0AE1, 0x0AE2, 0x0AE3, 0x0AE4, 0x0AE5, 0x0AE6, 0x0AE7, 0x0AE8, 0x0AE9, + 0x0AEA, 0x0AEB, 0x0AEC, 0x0AED, 0x0AEE, 0x0AEF, 0x0AF0, 0x0AF1, 0x0AF2, + 0x0AF3, 0x0AF4, 0x0AF5, 0x0AF6, 0x0AF7, 0x0AF8, 0x0AF9, 0x0AFA, 0x0AFB, + 0x0AFC, 0x0AFD, 0x0AFE, 0x0AFF, 0x0B00, 0x0B01, 0x0B02, 0x0B03, 0x0B04, + 0x0B05, 0x0B06, 0x0B07, 0x0B08, 0x0B09, 0x0B0A, 0x0B0B, 0x0B0C, 0x0B0D, + 0x0B0E, 0x0B0F, 0x0B10, 0x0B11, 0x0B12, 0x0B13, 0x0B14, 0x0B15, 0x0B16, + 0x0B17, 0x0B18, 0x0B19, 0x0B1A, 0x0B1B, 0x0B1C, 0x0B1D, 0x0B1E, 0x0B1F, + 0x0B20, 0x0B21, 0x0B22, 0x0B23, 0x0B24, 0x0B25, 0x0B26, 0x0B27, 0x0B28, + 0x0B29, 0x0B2A, 0x0B2B, 0x0B2C, 0x0B2D, 0x0B2E, 0x0B2F, 0x0B30, 0x0B31, + 0x0B32, 0x0B33, 0x0B34, 0x0B35, 0x0B36, 0x0B37, 0x0B38, 0x0B39, 0x0B3A, + 0x0B3B, 0x0B3C, 0x0B3D, 0x0B3E, 0x0B3F, 0x0B40, 0x0B41, 0x0B42, 0x0B43, + 0x0B44, 0x0B45, 0x0B46, 0x0B47, 0x0B48, 0x0B49, 0x0B4A, 0x0B4B, 0x0B4C, + 0x0B4D, 0x0B4E, 0x0B4F, 0x0B50, 0x0B51, 0x0B52, 0x0B53, 0x0B54, 0x0B55, + 0x0B56, 0x0B57, 0x0B58, 0x0B59, 0x0B5A, 0x0B5B, 0x0B5C, 0x0B5D, 0x0B5E, + 0x0B5F, 0x0B60, 0x0B61, 0x0B62, 0x0B63, 0x0B64, 0x0B65, 0x0B66, 0x0B67, + 0x0B68, 0x0B69, 0x0B6A, 0x0B6B, 0x0B6C, 0x0B6D, 0x0B6E, 0x0B6F, 0x0B70, + 0x0B71, 0x0B72, 0x0B73, 0x0B74, 0x0B75, 0x0B76, 0x0B77, 0x0B78, 0x0B79, + 0x0B7A, 0x0B7B, 0x0B7C, 0x0B7D, 0x0B7E, 0x0B7F, 0x0B80, 0x0B81, 0x0B82, + 0x0B83, 0x0B84, 0x0B85, 0x0B86, 0x0B87, 0x0B88, 0x0B89, 0x0B8A, 0x0B8B, + 0x0B8C, 0x0B8D, 0x0B8E, 0x0B8F, 0x0B90, 0x0B91, 0x0B92, 0x0B93, 0x0B94, + 0x0B95, 0x0B96, 0x0B97, 0x0B98, 0x0B99, 0x0B9A, 0x0B9B, 0x0B9C, 0x0B9D, + 0x0B9E, 0x0B9F, 0x0BA0, 0x0BA1, 0x0BA2, 0x0BA3, 0x0BA4, 0x0BA5, 0x0BA6, + 0x0BA7, 0x0BA8, 0x0BA9, 0x0BAA, 0x0BAB, 0x0BAC, 0x0BAD, 0x0BAE, 0x0BAF, + 0x0BB0, 0x0BB1, 0x0BB2, 0x0BB3, 0x0BB4, 0x0BB5, 0x0BB6, 0x0BB7, 0x0BB8, + 0x0BB9, 0x0BBA, 0x0BBB, 0x0BBC, 0x0BBD, 0x0BBE, 0x0BBF, 0x0BC0, 0x0BC1, + 0x0BC2, 0x0BC3, 0x0BC4, 0x0BC5, 0x0BC6, 0x0BC7, 0x0BC8, 0x0BC9, 0x0BCA, + 0x0BCB, 0x0BCC, 0x0BCD, 0x0BCE, 0x0BCF, 0x0BD0, 0x0BD1, 0x0BD2, 0x0BD3, + 0x0BD4, 0x0BD5, 0x0BD6, 0x0BD7, 0x0BD8, 0x0BD9, 0x0BDA, 0x0BDB, 0x0BDC, + 0x0BDD, 0x0BDE, 0x0BDF, 0x0BE0, 0x0BE1, 0x0BE2, 0x0BE3, 0x0BE4, 0x0BE5, + 0x0BE6, 0x0BE7, 0x0BE8, 0x0BE9, 0x0BEA, 0x0BEB, 0x0BEC, 0x0BED, 0x0BEE, + 0x0BEF, 0x0BF0, 0x0BF1, 0x0BF2, 0x0BF3, 0x0BF4, 0x0BF5, 0x0BF6, 0x0BF7, + 0x0BF8, 0x0BF9, 0x0BFA, 0x0BFB, 0x0BFC, 0x0BFD, 0x0BFE, 0x0BFF, 0x0C00, + 0x0C01, 0x0C02, 0x0C03, 0x0C04, 0x0C05, 0x0C06, 0x0C07, 0x0C08, 0x0C09, + 0x0C0A, 0x0C0B, 0x0C0C, 0x0C0D, 0x0C0E, 0x0C0F, 0x0C10, 0x0C11, 0x0C12, + 0x0C13, 0x0C14, 0x0C15, 0x0C16, 0x0C17, 0x0C18, 0x0C19, 0x0C1A, 0x0C1B, + 0x0C1C, 0x0C1D, 0x0C1E, 0x0C1F, 0x0C20, 0x0C21, 0x0C22, 0x0C23, 0x0C24, + 0x0C25, 0x0C26, 0x0C27, 0x0C28, 0x0C29, 0x0C2A, 0x0C2B, 0x0C2C, 0x0C2D, + 0x0C2E, 0x0C2F, 0x0C30, 0x0C31, 0x0C32, 0x0C33, 0x0C34, 0x0C35, 0x0C36, + 0x0C37, 0x0C38, 0x0C39, 0x0C3A, 0x0C3B, 0x0C3C, 0x0C3D, 0x0C3E, 0x0C3F, + 0x0C40, 0x0C41, 0x0C42, 0x0C43, 0x0C44, 0x0C45, 0x0C46, 0x0C47, 0x0C48, + 0x0C49, 0x0C4A, 0x0C4B, 0x0C4C, 0x0C4D, 0x0C4E, 0x0C4F, 0x0C50, 0x0C51, + 0x0C52, 0x0C53, 0x0C54, 0x0C55, 0x0C56, 0x0C57, 0x0C58, 0x0C59, 0x0C5A, + 0x0C5B, 0x0C5C, 0x0C5D, 0x0C5E, 0x0C5F, 0x0C60, 0x0C61, 0x0C62, 0x0C63, + 0x0C64, 0x0C65, 0x0C66, 0x0C67, 0x0C68, 0x0C69, 0x0C6A, 0x0C6B, 0x0C6C, + 0x0C6D, 0x0C6E, 0x0C6F, 0x0C70, 0x0C71, 0x0C72, 0x0C73, 0x0C74, 0x0C75, + 0x0C76, 0x0C77, 0x0C78, 0x0C79, 0x0C7A, 0x0C7B, 0x0C7C, 0x0C7D, 0x0C7E, + 0x0C7F, 0x0C80, 0x0C81, 0x0C82, 0x0C83, 0x0C84, 0x0C85, 0x0C86, 0x0C87, + 0x0C88, 0x0C89, 0x0C8A, 0x0C8B, 0x0C8C, 0x0C8D, 0x0C8E, 0x0C8F, 0x0C90, + 0x0C91, 0x0C92, 0x0C93, 0x0C94, 0x0C95, 0x0C96, 0x0C97, 0x0C98, 0x0C99, + 0x0C9A, 0x0C9B, 0x0C9C, 0x0C9D, 0x0C9E, 0x0C9F, 0x0CA0, 0x0CA1, 0x0CA2, + 0x0CA3, 0x0CA4, 0x0CA5, 0x0CA6, 0x0CA7, 0x0CA8, 0x0CA9, 0x0CAA, 0x0CAB, + 0x0CAC, 0x0CAD, 0x0CAE, 0x0CAF, 0x0CB0, 0x0CB1, 0x0CB2, 0x0CB3, 0x0CB4, + 0x0CB5, 0x0CB6, 0x0CB7, 0x0CB8, 0x0CB9, 0x0CBA, 0x0CBB, 0x0CBC, 0x0CBD, + 0x0CBE, 0x0CBF, 0x0CC0, 0x0CC1, 0x0CC2, 0x0CC3, 0x0CC4, 0x0CC5, 0x0CC6, + 0x0CC7, 0x0CC8, 0x0CC9, 0x0CCA, 0x0CCB, 0x0CCC, 0x0CCD, 0x0CCE, 0x0CCF, + 0x0CD0, 0x0CD1, 0x0CD2, 0x0CD3, 0x0CD4, 0x0CD5, 0x0CD6, 0x0CD7, 0x0CD8, + 0x0CD9, 0x0CDA, 0x0CDB, 0x0CDC, 0x0CDD, 0x0CDE, 0x0CDF, 0x0CE0, 0x0CE1, + 0x0CE2, 0x0CE3, 0x0CE4, 0x0CE5, 0x0CE6, 0x0CE7, 0x0CE8, 0x0CE9, 0x0CEA, + 0x0CEB, 0x0CEC, 0x0CED, 0x0CEE, 0x0CEF, 0x0CF0, 0x0CF1, 0x0CF2, 0x0CF3, + 0x0CF4, 0x0CF5, 0x0CF6, 0x0CF7, 0x0CF8, 0x0CF9, 0x0CFA, 0x0CFB, 0x0CFC, + 0x0CFD, 0x0CFE, 0x0CFF, 0x0D00, 0x0D01, 0x0D02, 0x0D03, 0x0D04, 0x0D05, + 0x0D06, 0x0D07, 0x0D08, 0x0D09, 0x0D0A, 0x0D0B, 0x0D0C, 0x0D0D, 0x0D0E, + 0x0D0F, 0x0D10, 0x0D11, 0x0D12, 0x0D13, 0x0D14, 0x0D15, 0x0D16, 0x0D17, + 0x0D18, 0x0D19, 0x0D1A, 0x0D1B, 0x0D1C, 0x0D1D, 0x0D1E, 0x0D1F, 0x0D20, + 0x0D21, 0x0D22, 0x0D23, 0x0D24, 0x0D25, 0x0D26, 0x0D27, 0x0D28, 0x0D29, + 0x0D2A, 0x0D2B, 0x0D2C, 0x0D2D, 0x0D2E, 0x0D2F, 0x0D30, 0x0D31, 0x0D32, + 0x0D33, 0x0D34, 0x0D35, 0x0D36, 0x0D37, 0x0D38, 0x0D39, 0x0D3A, 0x0D3B, + 0x0D3C, 0x0D3D, 0x0D3E, 0x0D3F, 0x0D40, 0x0D41, 0x0D42, 0x0D43, 0x0D44, + 0x0D45, 0x0D46, 0x0D47, 0x0D48, 0x0D49, 0x0D4A, 0x0D4B, 0x0D4C, 0x0D4D, + 0x0D4E, 0x0D4F, 0x0D50, 0x0D51, 0x0D52, 0x0D53, 0x0D54, 0x0D55, 0x0D56, + 0x0D57, 0x0D58, 0x0D59, 0x0D5A, 0x0D5B, 0x0D5C, 0x0D5D, 0x0D5E, 0x0D5F, + 0x0D60, 0x0D61, 0x0D62, 0x0D63, 0x0D64, 0x0D65, 0x0D66, 0x0D67, 0x0D68, + 0x0D69, 0x0D6A, 0x0D6B, 0x0D6C, 0x0D6D, 0x0D6E, 0x0D6F, 0x0D70, 0x0D71, + 0x0D72, 0x0D73, 0x0D74, 0x0D75, 0x0D76, 0x0D77, 0x0D78, 0x0D79, 0x0D7A, + 0x0D7B, 0x0D7C, 0x0D7D, 0x0D7E, 0x0D7F, 0x0D80, 0x0D81, 0x0D82, 0x0D83, + 0x0D84, 0x0D85, 0x0D86, 0x0D87, 0x0D88, 0x0D89, 0x0D8A, 0x0D8B, 0x0D8C, + 0x0D8D, 0x0D8E, 0x0D8F, 0x0D90, 0x0D91, 0x0D92, 0x0D93, 0x0D94, 0x0D95, + 0x0D96, 0x0D97, 0x0D98, 0x0D99, 0x0D9A, 0x0D9B, 0x0D9C, 0x0D9D, 0x0D9E, + 0x0D9F, 0x0DA0, 0x0DA1, 0x0DA2, 0x0DA3, 0x0DA4, 0x0DA5, 0x0DA6, 0x0DA7, + 0x0DA8, 0x0DA9, 0x0DAA, 0x0DAB, 0x0DAC, 0x0DAD, 0x0DAE, 0x0DAF, 0x0DB0, + 0x0DB1, 0x0DB2, 0x0DB3, 0x0DB4, 0x0DB5, 0x0DB6, 0x0DB7, 0x0DB8, 0x0DB9, + 0x0DBA, 0x0DBB, 0x0DBC, 0x0DBD, 0x0DBE, 0x0DBF, 0x0DC0, 0x0DC1, 0x0DC2, + 0x0DC3, 0x0DC4, 0x0DC5, 0x0DC6, 0x0DC7, 0x0DC8, 0x0DC9, 0x0DCA, 0x0DCB, + 0x0DCC, 0x0DCD, 0x0DCE, 0x0DCF, 0x0DD0, 0x0DD1, 0x0DD2, 0x0DD3, 0x0DD4, + 0x0DD5, 0x0DD6, 0x0DD7, 0x0DD8, 0x0DD9, 0x0DDA, 0x0DDB, 0x0DDC, 0x0DDD, + 0x0DDE, 0x0DDF, 0x0DE0, 0x0DE1, 0x0DE2, 0x0DE3, 0x0DE4, 0x0DE5, 0x0DE6, + 0x0DE7, 0x0DE8, 0x0DE9, 0x0DEA, 0x0DEB, 0x0DEC, 0x0DED, 0x0DEE, 0x0DEF, + 0x0DF0, 0x0DF1, 0x0DF2, 0x0DF3, 0x0DF4, 0x0DF5, 0x0DF6, 0x0DF7, 0x0DF8, + 0x0DF9, 0x0DFA, 0x0DFB, 0x0DFC, 0x0DFD, 0x0DFE, 0x0DFF, 0x0E00, 0x0E01, + 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09, 0x0E0A, + 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, 0x0E10, 0x0E11, 0x0E12, 0x0E13, + 0x0E14, 0x0E15, 0x0E16, 0x0E17, 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, + 0x0E1D, 0x0E1E, 0x0E1F, 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, + 0x0E26, 0x0E27, 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, + 0x0E2F, 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, + 0x0E38, 0x0E39, 0x0E3A, 0x0E3B, 0x0E3C, 0x0E3D, 0x0E3E, 0x0E3F, 0x0E40, + 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, 0x0E48, 0x0E49, + 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, 0x0E50, 0x0E51, 0x0E52, + 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, + 0x0E5C, 0x0E5D, 0x0E5E, 0x0E5F, 0x0E60, 0x0E61, 0x0E62, 0x0E63, 0x0E64, + 0x0E65, 0x0E66, 0x0E67, 0x0E68, 0x0E69, 0x0E6A, 0x0E6B, 0x0E6C, 0x0E6D, + 0x0E6E, 0x0E6F, 0x0E70, 0x0E71, 0x0E72, 0x0E73, 0x0E74, 0x0E75, 0x0E76, + 0x0E77, 0x0E78, 0x0E79, 0x0E7A, 0x0E7B, 0x0E7C, 0x0E7D, 0x0E7E, 0x0E7F, + 0x0E80, 0x0E81, 0x0E82, 0x0E83, 0x0E84, 0x0E85, 0x0E86, 0x0E87, 0x0E88, + 0x0E89, 0x0E8A, 0x0E8B, 0x0E8C, 0x0E8D, 0x0E8E, 0x0E8F, 0x0E90, 0x0E91, + 0x0E92, 0x0E93, 0x0E94, 0x0E95, 0x0E96, 0x0E97, 0x0E98, 0x0E99, 0x0E9A, + 0x0E9B, 0x0E9C, 0x0E9D, 0x0E9E, 0x0E9F, 0x0EA0, 0x0EA1, 0x0EA2, 0x0EA3, + 0x0EA4, 0x0EA5, 0x0EA6, 0x0EA7, 0x0EA8, 0x0EA9, 0x0EAA, 0x0EAB, 0x0EAC, + 0x0EAD, 0x0EAE, 0x0EAF, 0x0EB0, 0x0EB1, 0x0EB2, 0x0EB3, 0x0EB4, 0x0EB5, + 0x0EB6, 0x0EB7, 0x0EB8, 0x0EB9, 0x0EBA, 0x0EBB, 0x0EBC, 0x0EBD, 0x0EBE, + 0x0EBF, 0x0EC0, 0x0EC1, 0x0EC2, 0x0EC3, 0x0EC4, 0x0EC5, 0x0EC6, 0x0EC7, + 0x0EC8, 0x0EC9, 0x0ECA, 0x0ECB, 0x0ECC, 0x0ECD, 0x0ECE, 0x0ECF, 0x0ED0, + 0x0ED1, 0x0ED2, 0x0ED3, 0x0ED4, 0x0ED5, 0x0ED6, 0x0ED7, 0x0ED8, 0x0ED9, + 0x0EDA, 0x0EDB, 0x0EDC, 0x0EDD, 0x0EDE, 0x0EDF, 0x0EE0, 0x0EE1, 0x0EE2, + 0x0EE3, 0x0EE4, 0x0EE5, 0x0EE6, 0x0EE7, 0x0EE8, 0x0EE9, 0x0EEA, 0x0EEB, + 0x0EEC, 0x0EED, 0x0EEE, 0x0EEF, 0x0EF0, 0x0EF1, 0x0EF2, 0x0EF3, 0x0EF4, + 0x0EF5, 0x0EF6, 0x0EF7, 0x0EF8, 0x0EF9, 0x0EFA, 0x0EFB, 0x0EFC, 0x0EFD, + 0x0EFE, 0x0EFF, 0x0F00, 0x0F01, 0x0F02, 0x0F03, 0x0F04, 0x0F05, 0x0F06, + 0x0F07, 0x0F08, 0x0F09, 0x0F0A, 0x0F0B, 0x0F0C, 0x0F0D, 0x0F0E, 0x0F0F, + 0x0F10, 0x0F11, 0x0F12, 0x0F13, 0x0F14, 0x0F15, 0x0F16, 0x0F17, 0x0F18, + 0x0F19, 0x0F1A, 0x0F1B, 0x0F1C, 0x0F1D, 0x0F1E, 0x0F1F, 0x0F20, 0x0F21, + 0x0F22, 0x0F23, 0x0F24, 0x0F25, 0x0F26, 0x0F27, 0x0F28, 0x0F29, 0x0F2A, + 0x0F2B, 0x0F2C, 0x0F2D, 0x0F2E, 0x0F2F, 0x0F30, 0x0F31, 0x0F32, 0x0F33, + 0x0F34, 0x0F35, 0x0F36, 0x0F37, 0x0F38, 0x0F39, 0x0F3A, 0x0F3B, 0x0F3C, + 0x0F3D, 0x0F3E, 0x0F3F, 0x0F40, 0x0F41, 0x0F42, 0x0F43, 0x0F44, 0x0F45, + 0x0F46, 0x0F47, 0x0F48, 0x0F49, 0x0F4A, 0x0F4B, 0x0F4C, 0x0F4D, 0x0F4E, + 0x0F4F, 0x0F50, 0x0F51, 0x0F52, 0x0F53, 0x0F54, 0x0F55, 0x0F56, 0x0F57, + 0x0F58, 0x0F59, 0x0F5A, 0x0F5B, 0x0F5C, 0x0F5D, 0x0F5E, 0x0F5F, 0x0F60, + 0x0F61, 0x0F62, 0x0F63, 0x0F64, 0x0F65, 0x0F66, 0x0F67, 0x0F68, 0x0F69, + 0x0F6A, 0x0F6B, 0x0F6C, 0x0F6D, 0x0F6E, 0x0F6F, 0x0F70, 0x0F71, 0x0F72, + 0x0F73, 0x0F74, 0x0F75, 0x0F76, 0x0F77, 0x0F78, 0x0F79, 0x0F7A, 0x0F7B, + 0x0F7C, 0x0F7D, 0x0F7E, 0x0F7F, 0x0F80, 0x0F81, 0x0F82, 0x0F83, 0x0F84, + 0x0F85, 0x0F86, 0x0F87, 0x0F88, 0x0F89, 0x0F8A, 0x0F8B, 0x0F8C, 0x0F8D, + 0x0F8E, 0x0F8F, 0x0F90, 0x0F91, 0x0F92, 0x0F93, 0x0F94, 0x0F95, 0x0F96, + 0x0F97, 0x0F98, 0x0F99, 0x0F9A, 0x0F9B, 0x0F9C, 0x0F9D, 0x0F9E, 0x0F9F, + 0x0FA0, 0x0FA1, 0x0FA2, 0x0FA3, 0x0FA4, 0x0FA5, 0x0FA6, 0x0FA7, 0x0FA8, + 0x0FA9, 0x0FAA, 0x0FAB, 0x0FAC, 0x0FAD, 0x0FAE, 0x0FAF, 0x0FB0, 0x0FB1, + 0x0FB2, 0x0FB3, 0x0FB4, 0x0FB5, 0x0FB6, 0x0FB7, 0x0FB8, 0x0FB9, 0x0FBA, + 0x0FBB, 0x0FBC, 0x0FBD, 0x0FBE, 0x0FBF, 0x0FC0, 0x0FC1, 0x0FC2, 0x0FC3, + 0x0FC4, 0x0FC5, 0x0FC6, 0x0FC7, 0x0FC8, 0x0FC9, 0x0FCA, 0x0FCB, 0x0FCC, + 0x0FCD, 0x0FCE, 0x0FCF, 0x0FD0, 0x0FD1, 0x0FD2, 0x0FD3, 0x0FD4, 0x0FD5, + 0x0FD6, 0x0FD7, 0x0FD8, 0x0FD9, 0x0FDA, 0x0FDB, 0x0FDC, 0x0FDD, 0x0FDE, + 0x0FDF, 0x0FE0, 0x0FE1, 0x0FE2, 0x0FE3, 0x0FE4, 0x0FE5, 0x0FE6, 0x0FE7, + 0x0FE8, 0x0FE9, 0x0FEA, 0x0FEB, 0x0FEC, 0x0FED, 0x0FEE, 0x0FEF, 0x0FF0, + 0x0FF1, 0x0FF2, 0x0FF3, 0x0FF4, 0x0FF5, 0x0FF6, 0x0FF7, 0x0FF8, 0x0FF9, + 0x0FFA, 0x0FFB, 0x0FFC, 0x0FFD, 0x0FFE, 0x0FFF, 0x1000, 0x1001, 0x1002, + 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1008, 0x1009, 0x100A, 0x100B, + 0x100C, 0x100D, 0x100E, 0x100F, 0x1010, 0x1011, 0x1012, 0x1013, 0x1014, + 0x1015, 0x1016, 0x1017, 0x1018, 0x1019, 0x101A, 0x101B, 0x101C, 0x101D, + 0x101E, 0x101F, 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, + 0x1027, 0x1028, 0x1029, 0x102A, 0x102B, 0x102C, 0x102D, 0x102E, 0x102F, + 0x1030, 0x1031, 0x1032, 0x1033, 0x1034, 0x1035, 0x1036, 0x1037, 0x1038, + 0x1039, 0x103A, 0x103B, 0x103C, 0x103D, 0x103E, 0x103F, 0x1040, 0x1041, + 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047, 0x1048, 0x1049, 0x104A, + 0x104B, 0x104C, 0x104D, 0x104E, 0x104F, 0x1050, 0x1051, 0x1052, 0x1053, + 0x1054, 0x1055, 0x1056, 0x1057, 0x1058, 0x1059, 0x105A, 0x105B, 0x105C, + 0x105D, 0x105E, 0x105F, 0x1060, 0x1061, 0x1062, 0x1063, 0x1064, 0x1065, + 0x1066, 0x1067, 0x1068, 0x1069, 0x106A, 0x106B, 0x106C, 0x106D, 0x106E, + 0x106F, 0x1070, 0x1071, 0x1072, 0x1073, 0x1074, 0x1075, 0x1076, 0x1077, + 0x1078, 0x1079, 0x107A, 0x107B, 0x107C, 0x107D, 0x107E, 0x107F, 0x1080, + 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087, 0x1088, 0x1089, + 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F, 0x1090, 0x1091, 0x1092, + 0x1093, 0x1094, 0x1095, 0x1096, 0x1097, 0x1098, 0x1099, 0x109A, 0x109B, + 0x109C, 0x109D, 0x109E, 0x109F, 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, 0x10C6, 0x10C7, 0x10C8, + 0x10C9, 0x10CA, 0x10CB, 0x10CC, 0x10CD, 0x10CE, 0x10CF, 0x10D0, 0x10D1, + 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7, 0x10D8, 0x10D9, 0x10DA, + 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF, 0x10E0, 0x10E1, 0x10E2, 0x10E3, + 0x10E4, 0x10E5, 0x10E6, 0x10E7, 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, + 0x10ED, 0x10EE, 0x10EF, 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, + 0x10F6, 0x10F7, 0x10F8, 0x10F9, 0x10FA, 0x10FB, 0x10FC, 0x10FD, 0x10FE, + 0x10FF, 0x1100, 0x1101, 0x1102, 0x1103, 0x1104, 0x1105, 0x1106, 0x1107, + 0x1108, 0x1109, 0x110A, 0x110B, 0x110C, 0x110D, 0x110E, 0x110F, 0x1110, + 0x1111, 0x1112, 0x1113, 0x1114, 0x1115, 0x1116, 0x1117, 0x1118, 0x1119, + 0x111A, 0x111B, 0x111C, 0x111D, 0x111E, 0x111F, 0x1120, 0x1121, 0x1122, + 0x1123, 0x1124, 0x1125, 0x1126, 0x1127, 0x1128, 0x1129, 0x112A, 0x112B, + 0x112C, 0x112D, 0x112E, 0x112F, 0x1130, 0x1131, 0x1132, 0x1133, 0x1134, + 0x1135, 0x1136, 0x1137, 0x1138, 0x1139, 0x113A, 0x113B, 0x113C, 0x113D, + 0x113E, 0x113F, 0x1140, 0x1141, 0x1142, 0x1143, 0x1144, 0x1145, 0x1146, + 0x1147, 0x1148, 0x1149, 0x114A, 0x114B, 0x114C, 0x114D, 0x114E, 0x114F, + 0x1150, 0x1151, 0x1152, 0x1153, 0x1154, 0x1155, 0x1156, 0x1157, 0x1158, + 0x1159, 0x115A, 0x115B, 0x115C, 0x115D, 0x115E, 0x115F, 0x1160, 0x1161, + 0x1162, 0x1163, 0x1164, 0x1165, 0x1166, 0x1167, 0x1168, 0x1169, 0x116A, + 0x116B, 0x116C, 0x116D, 0x116E, 0x116F, 0x1170, 0x1171, 0x1172, 0x1173, + 0x1174, 0x1175, 0x1176, 0x1177, 0x1178, 0x1179, 0x117A, 0x117B, 0x117C, + 0x117D, 0x117E, 0x117F, 0x1180, 0x1181, 0x1182, 0x1183, 0x1184, 0x1185, + 0x1186, 0x1187, 0x1188, 0x1189, 0x118A, 0x118B, 0x118C, 0x118D, 0x118E, + 0x118F, 0x1190, 0x1191, 0x1192, 0x1193, 0x1194, 0x1195, 0x1196, 0x1197, + 0x1198, 0x1199, 0x119A, 0x119B, 0x119C, 0x119D, 0x119E, 0x119F, 0x11A0, + 0x11A1, 0x11A2, 0x11A3, 0x11A4, 0x11A5, 0x11A6, 0x11A7, 0x11A8, 0x11A9, + 0x11AA, 0x11AB, 0x11AC, 0x11AD, 0x11AE, 0x11AF, 0x11B0, 0x11B1, 0x11B2, + 0x11B3, 0x11B4, 0x11B5, 0x11B6, 0x11B7, 0x11B8, 0x11B9, 0x11BA, 0x11BB, + 0x11BC, 0x11BD, 0x11BE, 0x11BF, 0x11C0, 0x11C1, 0x11C2, 0x11C3, 0x11C4, + 0x11C5, 0x11C6, 0x11C7, 0x11C8, 0x11C9, 0x11CA, 0x11CB, 0x11CC, 0x11CD, + 0x11CE, 0x11CF, 0x11D0, 0x11D1, 0x11D2, 0x11D3, 0x11D4, 0x11D5, 0x11D6, + 0x11D7, 0x11D8, 0x11D9, 0x11DA, 0x11DB, 0x11DC, 0x11DD, 0x11DE, 0x11DF, + 0x11E0, 0x11E1, 0x11E2, 0x11E3, 0x11E4, 0x11E5, 0x11E6, 0x11E7, 0x11E8, + 0x11E9, 0x11EA, 0x11EB, 0x11EC, 0x11ED, 0x11EE, 0x11EF, 0x11F0, 0x11F1, + 0x11F2, 0x11F3, 0x11F4, 0x11F5, 0x11F6, 0x11F7, 0x11F8, 0x11F9, 0x11FA, + 0x11FB, 0x11FC, 0x11FD, 0x11FE, 0x11FF, 0x1200, 0x1201, 0x1202, 0x1203, + 0x1204, 0x1205, 0x1206, 0x1207, 0x1208, 0x1209, 0x120A, 0x120B, 0x120C, + 0x120D, 0x120E, 0x120F, 0x1210, 0x1211, 0x1212, 0x1213, 0x1214, 0x1215, + 0x1216, 0x1217, 0x1218, 0x1219, 0x121A, 0x121B, 0x121C, 0x121D, 0x121E, + 0x121F, 0x1220, 0x1221, 0x1222, 0x1223, 0x1224, 0x1225, 0x1226, 0x1227, + 0x1228, 0x1229, 0x122A, 0x122B, 0x122C, 0x122D, 0x122E, 0x122F, 0x1230, + 0x1231, 0x1232, 0x1233, 0x1234, 0x1235, 0x1236, 0x1237, 0x1238, 0x1239, + 0x123A, 0x123B, 0x123C, 0x123D, 0x123E, 0x123F, 0x1240, 0x1241, 0x1242, + 0x1243, 0x1244, 0x1245, 0x1246, 0x1247, 0x1248, 0x1249, 0x124A, 0x124B, + 0x124C, 0x124D, 0x124E, 0x124F, 0x1250, 0x1251, 0x1252, 0x1253, 0x1254, + 0x1255, 0x1256, 0x1257, 0x1258, 0x1259, 0x125A, 0x125B, 0x125C, 0x125D, + 0x125E, 0x125F, 0x1260, 0x1261, 0x1262, 0x1263, 0x1264, 0x1265, 0x1266, + 0x1267, 0x1268, 0x1269, 0x126A, 0x126B, 0x126C, 0x126D, 0x126E, 0x126F, + 0x1270, 0x1271, 0x1272, 0x1273, 0x1274, 0x1275, 0x1276, 0x1277, 0x1278, + 0x1279, 0x127A, 0x127B, 0x127C, 0x127D, 0x127E, 0x127F, 0x1280, 0x1281, + 0x1282, 0x1283, 0x1284, 0x1285, 0x1286, 0x1287, 0x1288, 0x1289, 0x128A, + 0x128B, 0x128C, 0x128D, 0x128E, 0x128F, 0x1290, 0x1291, 0x1292, 0x1293, + 0x1294, 0x1295, 0x1296, 0x1297, 0x1298, 0x1299, 0x129A, 0x129B, 0x129C, + 0x129D, 0x129E, 0x129F, 0x12A0, 0x12A1, 0x12A2, 0x12A3, 0x12A4, 0x12A5, + 0x12A6, 0x12A7, 0x12A8, 0x12A9, 0x12AA, 0x12AB, 0x12AC, 0x12AD, 0x12AE, + 0x12AF, 0x12B0, 0x12B1, 0x12B2, 0x12B3, 0x12B4, 0x12B5, 0x12B6, 0x12B7, + 0x12B8, 0x12B9, 0x12BA, 0x12BB, 0x12BC, 0x12BD, 0x12BE, 0x12BF, 0x12C0, + 0x12C1, 0x12C2, 0x12C3, 0x12C4, 0x12C5, 0x12C6, 0x12C7, 0x12C8, 0x12C9, + 0x12CA, 0x12CB, 0x12CC, 0x12CD, 0x12CE, 0x12CF, 0x12D0, 0x12D1, 0x12D2, + 0x12D3, 0x12D4, 0x12D5, 0x12D6, 0x12D7, 0x12D8, 0x12D9, 0x12DA, 0x12DB, + 0x12DC, 0x12DD, 0x12DE, 0x12DF, 0x12E0, 0x12E1, 0x12E2, 0x12E3, 0x12E4, + 0x12E5, 0x12E6, 0x12E7, 0x12E8, 0x12E9, 0x12EA, 0x12EB, 0x12EC, 0x12ED, + 0x12EE, 0x12EF, 0x12F0, 0x12F1, 0x12F2, 0x12F3, 0x12F4, 0x12F5, 0x12F6, + 0x12F7, 0x12F8, 0x12F9, 0x12FA, 0x12FB, 0x12FC, 0x12FD, 0x12FE, 0x12FF, + 0x1300, 0x1301, 0x1302, 0x1303, 0x1304, 0x1305, 0x1306, 0x1307, 0x1308, + 0x1309, 0x130A, 0x130B, 0x130C, 0x130D, 0x130E, 0x130F, 0x1310, 0x1311, + 0x1312, 0x1313, 0x1314, 0x1315, 0x1316, 0x1317, 0x1318, 0x1319, 0x131A, + 0x131B, 0x131C, 0x131D, 0x131E, 0x131F, 0x1320, 0x1321, 0x1322, 0x1323, + 0x1324, 0x1325, 0x1326, 0x1327, 0x1328, 0x1329, 0x132A, 0x132B, 0x132C, + 0x132D, 0x132E, 0x132F, 0x1330, 0x1331, 0x1332, 0x1333, 0x1334, 0x1335, + 0x1336, 0x1337, 0x1338, 0x1339, 0x133A, 0x133B, 0x133C, 0x133D, 0x133E, + 0x133F, 0x1340, 0x1341, 0x1342, 0x1343, 0x1344, 0x1345, 0x1346, 0x1347, + 0x1348, 0x1349, 0x134A, 0x134B, 0x134C, 0x134D, 0x134E, 0x134F, 0x1350, + 0x1351, 0x1352, 0x1353, 0x1354, 0x1355, 0x1356, 0x1357, 0x1358, 0x1359, + 0x135A, 0x135B, 0x135C, 0x135D, 0x135E, 0x135F, 0x1360, 0x1361, 0x1362, + 0x1363, 0x1364, 0x1365, 0x1366, 0x1367, 0x1368, 0x1369, 0x136A, 0x136B, + 0x136C, 0x136D, 0x136E, 0x136F, 0x1370, 0x1371, 0x1372, 0x1373, 0x1374, + 0x1375, 0x1376, 0x1377, 0x1378, 0x1379, 0x137A, 0x137B, 0x137C, 0x137D, + 0x137E, 0x137F, 0x1380, 0x1381, 0x1382, 0x1383, 0x1384, 0x1385, 0x1386, + 0x1387, 0x1388, 0x1389, 0x138A, 0x138B, 0x138C, 0x138D, 0x138E, 0x138F, + 0x1390, 0x1391, 0x1392, 0x1393, 0x1394, 0x1395, 0x1396, 0x1397, 0x1398, + 0x1399, 0x139A, 0x139B, 0x139C, 0x139D, 0x139E, 0x139F, 0x13A0, 0x13A1, + 0x13A2, 0x13A3, 0x13A4, 0x13A5, 0x13A6, 0x13A7, 0x13A8, 0x13A9, 0x13AA, + 0x13AB, 0x13AC, 0x13AD, 0x13AE, 0x13AF, 0x13B0, 0x13B1, 0x13B2, 0x13B3, + 0x13B4, 0x13B5, 0x13B6, 0x13B7, 0x13B8, 0x13B9, 0x13BA, 0x13BB, 0x13BC, + 0x13BD, 0x13BE, 0x13BF, 0x13C0, 0x13C1, 0x13C2, 0x13C3, 0x13C4, 0x13C5, + 0x13C6, 0x13C7, 0x13C8, 0x13C9, 0x13CA, 0x13CB, 0x13CC, 0x13CD, 0x13CE, + 0x13CF, 0x13D0, 0x13D1, 0x13D2, 0x13D3, 0x13D4, 0x13D5, 0x13D6, 0x13D7, + 0x13D8, 0x13D9, 0x13DA, 0x13DB, 0x13DC, 0x13DD, 0x13DE, 0x13DF, 0x13E0, + 0x13E1, 0x13E2, 0x13E3, 0x13E4, 0x13E5, 0x13E6, 0x13E7, 0x13E8, 0x13E9, + 0x13EA, 0x13EB, 0x13EC, 0x13ED, 0x13EE, 0x13EF, 0x13F0, 0x13F1, 0x13F2, + 0x13F3, 0x13F4, 0x13F5, 0x13F6, 0x13F7, 0x13F8, 0x13F9, 0x13FA, 0x13FB, + 0x13FC, 0x13FD, 0x13FE, 0x13FF, 0x1400, 0x1401, 0x1402, 0x1403, 0x1404, + 0x1405, 0x1406, 0x1407, 0x1408, 0x1409, 0x140A, 0x140B, 0x140C, 0x140D, + 0x140E, 0x140F, 0x1410, 0x1411, 0x1412, 0x1413, 0x1414, 0x1415, 0x1416, + 0x1417, 0x1418, 0x1419, 0x141A, 0x141B, 0x141C, 0x141D, 0x141E, 0x141F, + 0x1420, 0x1421, 0x1422, 0x1423, 0x1424, 0x1425, 0x1426, 0x1427, 0x1428, + 0x1429, 0x142A, 0x142B, 0x142C, 0x142D, 0x142E, 0x142F, 0x1430, 0x1431, + 0x1432, 0x1433, 0x1434, 0x1435, 0x1436, 0x1437, 0x1438, 0x1439, 0x143A, + 0x143B, 0x143C, 0x143D, 0x143E, 0x143F, 0x1440, 0x1441, 0x1442, 0x1443, + 0x1444, 0x1445, 0x1446, 0x1447, 0x1448, 0x1449, 0x144A, 0x144B, 0x144C, + 0x144D, 0x144E, 0x144F, 0x1450, 0x1451, 0x1452, 0x1453, 0x1454, 0x1455, + 0x1456, 0x1457, 0x1458, 0x1459, 0x145A, 0x145B, 0x145C, 0x145D, 0x145E, + 0x145F, 0x1460, 0x1461, 0x1462, 0x1463, 0x1464, 0x1465, 0x1466, 0x1467, + 0x1468, 0x1469, 0x146A, 0x146B, 0x146C, 0x146D, 0x146E, 0x146F, 0x1470, + 0x1471, 0x1472, 0x1473, 0x1474, 0x1475, 0x1476, 0x1477, 0x1478, 0x1479, + 0x147A, 0x147B, 0x147C, 0x147D, 0x147E, 0x147F, 0x1480, 0x1481, 0x1482, + 0x1483, 0x1484, 0x1485, 0x1486, 0x1487, 0x1488, 0x1489, 0x148A, 0x148B, + 0x148C, 0x148D, 0x148E, 0x148F, 0x1490, 0x1491, 0x1492, 0x1493, 0x1494, + 0x1495, 0x1496, 0x1497, 0x1498, 0x1499, 0x149A, 0x149B, 0x149C, 0x149D, + 0x149E, 0x149F, 0x14A0, 0x14A1, 0x14A2, 0x14A3, 0x14A4, 0x14A5, 0x14A6, + 0x14A7, 0x14A8, 0x14A9, 0x14AA, 0x14AB, 0x14AC, 0x14AD, 0x14AE, 0x14AF, + 0x14B0, 0x14B1, 0x14B2, 0x14B3, 0x14B4, 0x14B5, 0x14B6, 0x14B7, 0x14B8, + 0x14B9, 0x14BA, 0x14BB, 0x14BC, 0x14BD, 0x14BE, 0x14BF, 0x14C0, 0x14C1, + 0x14C2, 0x14C3, 0x14C4, 0x14C5, 0x14C6, 0x14C7, 0x14C8, 0x14C9, 0x14CA, + 0x14CB, 0x14CC, 0x14CD, 0x14CE, 0x14CF, 0x14D0, 0x14D1, 0x14D2, 0x14D3, + 0x14D4, 0x14D5, 0x14D6, 0x14D7, 0x14D8, 0x14D9, 0x14DA, 0x14DB, 0x14DC, + 0x14DD, 0x14DE, 0x14DF, 0x14E0, 0x14E1, 0x14E2, 0x14E3, 0x14E4, 0x14E5, + 0x14E6, 0x14E7, 0x14E8, 0x14E9, 0x14EA, 0x14EB, 0x14EC, 0x14ED, 0x14EE, + 0x14EF, 0x14F0, 0x14F1, 0x14F2, 0x14F3, 0x14F4, 0x14F5, 0x14F6, 0x14F7, + 0x14F8, 0x14F9, 0x14FA, 0x14FB, 0x14FC, 0x14FD, 0x14FE, 0x14FF, 0x1500, + 0x1501, 0x1502, 0x1503, 0x1504, 0x1505, 0x1506, 0x1507, 0x1508, 0x1509, + 0x150A, 0x150B, 0x150C, 0x150D, 0x150E, 0x150F, 0x1510, 0x1511, 0x1512, + 0x1513, 0x1514, 0x1515, 0x1516, 0x1517, 0x1518, 0x1519, 0x151A, 0x151B, + 0x151C, 0x151D, 0x151E, 0x151F, 0x1520, 0x1521, 0x1522, 0x1523, 0x1524, + 0x1525, 0x1526, 0x1527, 0x1528, 0x1529, 0x152A, 0x152B, 0x152C, 0x152D, + 0x152E, 0x152F, 0x1530, 0x1531, 0x1532, 0x1533, 0x1534, 0x1535, 0x1536, + 0x1537, 0x1538, 0x1539, 0x153A, 0x153B, 0x153C, 0x153D, 0x153E, 0x153F, + 0x1540, 0x1541, 0x1542, 0x1543, 0x1544, 0x1545, 0x1546, 0x1547, 0x1548, + 0x1549, 0x154A, 0x154B, 0x154C, 0x154D, 0x154E, 0x154F, 0x1550, 0x1551, + 0x1552, 0x1553, 0x1554, 0x1555, 0x1556, 0x1557, 0x1558, 0x1559, 0x155A, + 0x155B, 0x155C, 0x155D, 0x155E, 0x155F, 0x1560, 0x1561, 0x1562, 0x1563, + 0x1564, 0x1565, 0x1566, 0x1567, 0x1568, 0x1569, 0x156A, 0x156B, 0x156C, + 0x156D, 0x156E, 0x156F, 0x1570, 0x1571, 0x1572, 0x1573, 0x1574, 0x1575, + 0x1576, 0x1577, 0x1578, 0x1579, 0x157A, 0x157B, 0x157C, 0x157D, 0x157E, + 0x157F, 0x1580, 0x1581, 0x1582, 0x1583, 0x1584, 0x1585, 0x1586, 0x1587, + 0x1588, 0x1589, 0x158A, 0x158B, 0x158C, 0x158D, 0x158E, 0x158F, 0x1590, + 0x1591, 0x1592, 0x1593, 0x1594, 0x1595, 0x1596, 0x1597, 0x1598, 0x1599, + 0x159A, 0x159B, 0x159C, 0x159D, 0x159E, 0x159F, 0x15A0, 0x15A1, 0x15A2, + 0x15A3, 0x15A4, 0x15A5, 0x15A6, 0x15A7, 0x15A8, 0x15A9, 0x15AA, 0x15AB, + 0x15AC, 0x15AD, 0x15AE, 0x15AF, 0x15B0, 0x15B1, 0x15B2, 0x15B3, 0x15B4, + 0x15B5, 0x15B6, 0x15B7, 0x15B8, 0x15B9, 0x15BA, 0x15BB, 0x15BC, 0x15BD, + 0x15BE, 0x15BF, 0x15C0, 0x15C1, 0x15C2, 0x15C3, 0x15C4, 0x15C5, 0x15C6, + 0x15C7, 0x15C8, 0x15C9, 0x15CA, 0x15CB, 0x15CC, 0x15CD, 0x15CE, 0x15CF, + 0x15D0, 0x15D1, 0x15D2, 0x15D3, 0x15D4, 0x15D5, 0x15D6, 0x15D7, 0x15D8, + 0x15D9, 0x15DA, 0x15DB, 0x15DC, 0x15DD, 0x15DE, 0x15DF, 0x15E0, 0x15E1, + 0x15E2, 0x15E3, 0x15E4, 0x15E5, 0x15E6, 0x15E7, 0x15E8, 0x15E9, 0x15EA, + 0x15EB, 0x15EC, 0x15ED, 0x15EE, 0x15EF, 0x15F0, 0x15F1, 0x15F2, 0x15F3, + 0x15F4, 0x15F5, 0x15F6, 0x15F7, 0x15F8, 0x15F9, 0x15FA, 0x15FB, 0x15FC, + 0x15FD, 0x15FE, 0x15FF, 0x1600, 0x1601, 0x1602, 0x1603, 0x1604, 0x1605, + 0x1606, 0x1607, 0x1608, 0x1609, 0x160A, 0x160B, 0x160C, 0x160D, 0x160E, + 0x160F, 0x1610, 0x1611, 0x1612, 0x1613, 0x1614, 0x1615, 0x1616, 0x1617, + 0x1618, 0x1619, 0x161A, 0x161B, 0x161C, 0x161D, 0x161E, 0x161F, 0x1620, + 0x1621, 0x1622, 0x1623, 0x1624, 0x1625, 0x1626, 0x1627, 0x1628, 0x1629, + 0x162A, 0x162B, 0x162C, 0x162D, 0x162E, 0x162F, 0x1630, 0x1631, 0x1632, + 0x1633, 0x1634, 0x1635, 0x1636, 0x1637, 0x1638, 0x1639, 0x163A, 0x163B, + 0x163C, 0x163D, 0x163E, 0x163F, 0x1640, 0x1641, 0x1642, 0x1643, 0x1644, + 0x1645, 0x1646, 0x1647, 0x1648, 0x1649, 0x164A, 0x164B, 0x164C, 0x164D, + 0x164E, 0x164F, 0x1650, 0x1651, 0x1652, 0x1653, 0x1654, 0x1655, 0x1656, + 0x1657, 0x1658, 0x1659, 0x165A, 0x165B, 0x165C, 0x165D, 0x165E, 0x165F, + 0x1660, 0x1661, 0x1662, 0x1663, 0x1664, 0x1665, 0x1666, 0x1667, 0x1668, + 0x1669, 0x166A, 0x166B, 0x166C, 0x166D, 0x166E, 0x166F, 0x1670, 0x1671, + 0x1672, 0x1673, 0x1674, 0x1675, 0x1676, 0x1677, 0x1678, 0x1679, 0x167A, + 0x167B, 0x167C, 0x167D, 0x167E, 0x167F, 0x1680, 0x1681, 0x1682, 0x1683, + 0x1684, 0x1685, 0x1686, 0x1687, 0x1688, 0x1689, 0x168A, 0x168B, 0x168C, + 0x168D, 0x168E, 0x168F, 0x1690, 0x1691, 0x1692, 0x1693, 0x1694, 0x1695, + 0x1696, 0x1697, 0x1698, 0x1699, 0x169A, 0x169B, 0x169C, 0x169D, 0x169E, + 0x169F, 0x16A0, 0x16A1, 0x16A2, 0x16A3, 0x16A4, 0x16A5, 0x16A6, 0x16A7, + 0x16A8, 0x16A9, 0x16AA, 0x16AB, 0x16AC, 0x16AD, 0x16AE, 0x16AF, 0x16B0, + 0x16B1, 0x16B2, 0x16B3, 0x16B4, 0x16B5, 0x16B6, 0x16B7, 0x16B8, 0x16B9, + 0x16BA, 0x16BB, 0x16BC, 0x16BD, 0x16BE, 0x16BF, 0x16C0, 0x16C1, 0x16C2, + 0x16C3, 0x16C4, 0x16C5, 0x16C6, 0x16C7, 0x16C8, 0x16C9, 0x16CA, 0x16CB, + 0x16CC, 0x16CD, 0x16CE, 0x16CF, 0x16D0, 0x16D1, 0x16D2, 0x16D3, 0x16D4, + 0x16D5, 0x16D6, 0x16D7, 0x16D8, 0x16D9, 0x16DA, 0x16DB, 0x16DC, 0x16DD, + 0x16DE, 0x16DF, 0x16E0, 0x16E1, 0x16E2, 0x16E3, 0x16E4, 0x16E5, 0x16E6, + 0x16E7, 0x16E8, 0x16E9, 0x16EA, 0x16EB, 0x16EC, 0x16ED, 0x16EE, 0x16EF, + 0x16F0, 0x16F1, 0x16F2, 0x16F3, 0x16F4, 0x16F5, 0x16F6, 0x16F7, 0x16F8, + 0x16F9, 0x16FA, 0x16FB, 0x16FC, 0x16FD, 0x16FE, 0x16FF, 0x1700, 0x1701, + 0x1702, 0x1703, 0x1704, 0x1705, 0x1706, 0x1707, 0x1708, 0x1709, 0x170A, + 0x170B, 0x170C, 0x170D, 0x170E, 0x170F, 0x1710, 0x1711, 0x1712, 0x1713, + 0x1714, 0x1715, 0x1716, 0x1717, 0x1718, 0x1719, 0x171A, 0x171B, 0x171C, + 0x171D, 0x171E, 0x171F, 0x1720, 0x1721, 0x1722, 0x1723, 0x1724, 0x1725, + 0x1726, 0x1727, 0x1728, 0x1729, 0x172A, 0x172B, 0x172C, 0x172D, 0x172E, + 0x172F, 0x1730, 0x1731, 0x1732, 0x1733, 0x1734, 0x1735, 0x1736, 0x1737, + 0x1738, 0x1739, 0x173A, 0x173B, 0x173C, 0x173D, 0x173E, 0x173F, 0x1740, + 0x1741, 0x1742, 0x1743, 0x1744, 0x1745, 0x1746, 0x1747, 0x1748, 0x1749, + 0x174A, 0x174B, 0x174C, 0x174D, 0x174E, 0x174F, 0x1750, 0x1751, 0x1752, + 0x1753, 0x1754, 0x1755, 0x1756, 0x1757, 0x1758, 0x1759, 0x175A, 0x175B, + 0x175C, 0x175D, 0x175E, 0x175F, 0x1760, 0x1761, 0x1762, 0x1763, 0x1764, + 0x1765, 0x1766, 0x1767, 0x1768, 0x1769, 0x176A, 0x176B, 0x176C, 0x176D, + 0x176E, 0x176F, 0x1770, 0x1771, 0x1772, 0x1773, 0x1774, 0x1775, 0x1776, + 0x1777, 0x1778, 0x1779, 0x177A, 0x177B, 0x177C, 0x177D, 0x177E, 0x177F, + 0x1780, 0x1781, 0x1782, 0x1783, 0x1784, 0x1785, 0x1786, 0x1787, 0x1788, + 0x1789, 0x178A, 0x178B, 0x178C, 0x178D, 0x178E, 0x178F, 0x1790, 0x1791, + 0x1792, 0x1793, 0x1794, 0x1795, 0x1796, 0x1797, 0x1798, 0x1799, 0x179A, + 0x179B, 0x179C, 0x179D, 0x179E, 0x179F, 0x17A0, 0x17A1, 0x17A2, 0x17A3, + 0x17A4, 0x17A5, 0x17A6, 0x17A7, 0x17A8, 0x17A9, 0x17AA, 0x17AB, 0x17AC, + 0x17AD, 0x17AE, 0x17AF, 0x17B0, 0x17B1, 0x17B2, 0x17B3, 0x17B4, 0x17B5, + 0x17B6, 0x17B7, 0x17B8, 0x17B9, 0x17BA, 0x17BB, 0x17BC, 0x17BD, 0x17BE, + 0x17BF, 0x17C0, 0x17C1, 0x17C2, 0x17C3, 0x17C4, 0x17C5, 0x17C6, 0x17C7, + 0x17C8, 0x17C9, 0x17CA, 0x17CB, 0x17CC, 0x17CD, 0x17CE, 0x17CF, 0x17D0, + 0x17D1, 0x17D2, 0x17D3, 0x17D4, 0x17D5, 0x17D6, 0x17D7, 0x17D8, 0x17D9, + 0x17DA, 0x17DB, 0x17DC, 0x17DD, 0x17DE, 0x17DF, 0x17E0, 0x17E1, 0x17E2, + 0x17E3, 0x17E4, 0x17E5, 0x17E6, 0x17E7, 0x17E8, 0x17E9, 0x17EA, 0x17EB, + 0x17EC, 0x17ED, 0x17EE, 0x17EF, 0x17F0, 0x17F1, 0x17F2, 0x17F3, 0x17F4, + 0x17F5, 0x17F6, 0x17F7, 0x17F8, 0x17F9, 0x17FA, 0x17FB, 0x17FC, 0x17FD, + 0x17FE, 0x17FF, 0x1800, 0x1801, 0x1802, 0x1803, 0x1804, 0x1805, 0x1806, + 0x1807, 0x1808, 0x1809, 0x180A, 0x180B, 0x180C, 0x180D, 0x180E, 0x180F, + 0x1810, 0x1811, 0x1812, 0x1813, 0x1814, 0x1815, 0x1816, 0x1817, 0x1818, + 0x1819, 0x181A, 0x181B, 0x181C, 0x181D, 0x181E, 0x181F, 0x1820, 0x1821, + 0x1822, 0x1823, 0x1824, 0x1825, 0x1826, 0x1827, 0x1828, 0x1829, 0x182A, + 0x182B, 0x182C, 0x182D, 0x182E, 0x182F, 0x1830, 0x1831, 0x1832, 0x1833, + 0x1834, 0x1835, 0x1836, 0x1837, 0x1838, 0x1839, 0x183A, 0x183B, 0x183C, + 0x183D, 0x183E, 0x183F, 0x1840, 0x1841, 0x1842, 0x1843, 0x1844, 0x1845, + 0x1846, 0x1847, 0x1848, 0x1849, 0x184A, 0x184B, 0x184C, 0x184D, 0x184E, + 0x184F, 0x1850, 0x1851, 0x1852, 0x1853, 0x1854, 0x1855, 0x1856, 0x1857, + 0x1858, 0x1859, 0x185A, 0x185B, 0x185C, 0x185D, 0x185E, 0x185F, 0x1860, + 0x1861, 0x1862, 0x1863, 0x1864, 0x1865, 0x1866, 0x1867, 0x1868, 0x1869, + 0x186A, 0x186B, 0x186C, 0x186D, 0x186E, 0x186F, 0x1870, 0x1871, 0x1872, + 0x1873, 0x1874, 0x1875, 0x1876, 0x1877, 0x1878, 0x1879, 0x187A, 0x187B, + 0x187C, 0x187D, 0x187E, 0x187F, 0x1880, 0x1881, 0x1882, 0x1883, 0x1884, + 0x1885, 0x1886, 0x1887, 0x1888, 0x1889, 0x188A, 0x188B, 0x188C, 0x188D, + 0x188E, 0x188F, 0x1890, 0x1891, 0x1892, 0x1893, 0x1894, 0x1895, 0x1896, + 0x1897, 0x1898, 0x1899, 0x189A, 0x189B, 0x189C, 0x189D, 0x189E, 0x189F, + 0x18A0, 0x18A1, 0x18A2, 0x18A3, 0x18A4, 0x18A5, 0x18A6, 0x18A7, 0x18A8, + 0x18A9, 0x18AA, 0x18AB, 0x18AC, 0x18AD, 0x18AE, 0x18AF, 0x18B0, 0x18B1, + 0x18B2, 0x18B3, 0x18B4, 0x18B5, 0x18B6, 0x18B7, 0x18B8, 0x18B9, 0x18BA, + 0x18BB, 0x18BC, 0x18BD, 0x18BE, 0x18BF, 0x18C0, 0x18C1, 0x18C2, 0x18C3, + 0x18C4, 0x18C5, 0x18C6, 0x18C7, 0x18C8, 0x18C9, 0x18CA, 0x18CB, 0x18CC, + 0x18CD, 0x18CE, 0x18CF, 0x18D0, 0x18D1, 0x18D2, 0x18D3, 0x18D4, 0x18D5, + 0x18D6, 0x18D7, 0x18D8, 0x18D9, 0x18DA, 0x18DB, 0x18DC, 0x18DD, 0x18DE, + 0x18DF, 0x18E0, 0x18E1, 0x18E2, 0x18E3, 0x18E4, 0x18E5, 0x18E6, 0x18E7, + 0x18E8, 0x18E9, 0x18EA, 0x18EB, 0x18EC, 0x18ED, 0x18EE, 0x18EF, 0x18F0, + 0x18F1, 0x18F2, 0x18F3, 0x18F4, 0x18F5, 0x18F6, 0x18F7, 0x18F8, 0x18F9, + 0x18FA, 0x18FB, 0x18FC, 0x18FD, 0x18FE, 0x18FF, 0x1900, 0x1901, 0x1902, + 0x1903, 0x1904, 0x1905, 0x1906, 0x1907, 0x1908, 0x1909, 0x190A, 0x190B, + 0x190C, 0x190D, 0x190E, 0x190F, 0x1910, 0x1911, 0x1912, 0x1913, 0x1914, + 0x1915, 0x1916, 0x1917, 0x1918, 0x1919, 0x191A, 0x191B, 0x191C, 0x191D, + 0x191E, 0x191F, 0x1920, 0x1921, 0x1922, 0x1923, 0x1924, 0x1925, 0x1926, + 0x1927, 0x1928, 0x1929, 0x192A, 0x192B, 0x192C, 0x192D, 0x192E, 0x192F, + 0x1930, 0x1931, 0x1932, 0x1933, 0x1934, 0x1935, 0x1936, 0x1937, 0x1938, + 0x1939, 0x193A, 0x193B, 0x193C, 0x193D, 0x193E, 0x193F, 0x1940, 0x1941, + 0x1942, 0x1943, 0x1944, 0x1945, 0x1946, 0x1947, 0x1948, 0x1949, 0x194A, + 0x194B, 0x194C, 0x194D, 0x194E, 0x194F, 0x1950, 0x1951, 0x1952, 0x1953, + 0x1954, 0x1955, 0x1956, 0x1957, 0x1958, 0x1959, 0x195A, 0x195B, 0x195C, + 0x195D, 0x195E, 0x195F, 0x1960, 0x1961, 0x1962, 0x1963, 0x1964, 0x1965, + 0x1966, 0x1967, 0x1968, 0x1969, 0x196A, 0x196B, 0x196C, 0x196D, 0x196E, + 0x196F, 0x1970, 0x1971, 0x1972, 0x1973, 0x1974, 0x1975, 0x1976, 0x1977, + 0x1978, 0x1979, 0x197A, 0x197B, 0x197C, 0x197D, 0x197E, 0x197F, 0x1980, + 0x1981, 0x1982, 0x1983, 0x1984, 0x1985, 0x1986, 0x1987, 0x1988, 0x1989, + 0x198A, 0x198B, 0x198C, 0x198D, 0x198E, 0x198F, 0x1990, 0x1991, 0x1992, + 0x1993, 0x1994, 0x1995, 0x1996, 0x1997, 0x1998, 0x1999, 0x199A, 0x199B, + 0x199C, 0x199D, 0x199E, 0x199F, 0x19A0, 0x19A1, 0x19A2, 0x19A3, 0x19A4, + 0x19A5, 0x19A6, 0x19A7, 0x19A8, 0x19A9, 0x19AA, 0x19AB, 0x19AC, 0x19AD, + 0x19AE, 0x19AF, 0x19B0, 0x19B1, 0x19B2, 0x19B3, 0x19B4, 0x19B5, 0x19B6, + 0x19B7, 0x19B8, 0x19B9, 0x19BA, 0x19BB, 0x19BC, 0x19BD, 0x19BE, 0x19BF, + 0x19C0, 0x19C1, 0x19C2, 0x19C3, 0x19C4, 0x19C5, 0x19C6, 0x19C7, 0x19C8, + 0x19C9, 0x19CA, 0x19CB, 0x19CC, 0x19CD, 0x19CE, 0x19CF, 0x19D0, 0x19D1, + 0x19D2, 0x19D3, 0x19D4, 0x19D5, 0x19D6, 0x19D7, 0x19D8, 0x19D9, 0x19DA, + 0x19DB, 0x19DC, 0x19DD, 0x19DE, 0x19DF, 0x19E0, 0x19E1, 0x19E2, 0x19E3, + 0x19E4, 0x19E5, 0x19E6, 0x19E7, 0x19E8, 0x19E9, 0x19EA, 0x19EB, 0x19EC, + 0x19ED, 0x19EE, 0x19EF, 0x19F0, 0x19F1, 0x19F2, 0x19F3, 0x19F4, 0x19F5, + 0x19F6, 0x19F7, 0x19F8, 0x19F9, 0x19FA, 0x19FB, 0x19FC, 0x19FD, 0x19FE, + 0x19FF, 0x1A00, 0x1A01, 0x1A02, 0x1A03, 0x1A04, 0x1A05, 0x1A06, 0x1A07, + 0x1A08, 0x1A09, 0x1A0A, 0x1A0B, 0x1A0C, 0x1A0D, 0x1A0E, 0x1A0F, 0x1A10, + 0x1A11, 0x1A12, 0x1A13, 0x1A14, 0x1A15, 0x1A16, 0x1A17, 0x1A18, 0x1A19, + 0x1A1A, 0x1A1B, 0x1A1C, 0x1A1D, 0x1A1E, 0x1A1F, 0x1A20, 0x1A21, 0x1A22, + 0x1A23, 0x1A24, 0x1A25, 0x1A26, 0x1A27, 0x1A28, 0x1A29, 0x1A2A, 0x1A2B, + 0x1A2C, 0x1A2D, 0x1A2E, 0x1A2F, 0x1A30, 0x1A31, 0x1A32, 0x1A33, 0x1A34, + 0x1A35, 0x1A36, 0x1A37, 0x1A38, 0x1A39, 0x1A3A, 0x1A3B, 0x1A3C, 0x1A3D, + 0x1A3E, 0x1A3F, 0x1A40, 0x1A41, 0x1A42, 0x1A43, 0x1A44, 0x1A45, 0x1A46, + 0x1A47, 0x1A48, 0x1A49, 0x1A4A, 0x1A4B, 0x1A4C, 0x1A4D, 0x1A4E, 0x1A4F, + 0x1A50, 0x1A51, 0x1A52, 0x1A53, 0x1A54, 0x1A55, 0x1A56, 0x1A57, 0x1A58, + 0x1A59, 0x1A5A, 0x1A5B, 0x1A5C, 0x1A5D, 0x1A5E, 0x1A5F, 0x1A60, 0x1A61, + 0x1A62, 0x1A63, 0x1A64, 0x1A65, 0x1A66, 0x1A67, 0x1A68, 0x1A69, 0x1A6A, + 0x1A6B, 0x1A6C, 0x1A6D, 0x1A6E, 0x1A6F, 0x1A70, 0x1A71, 0x1A72, 0x1A73, + 0x1A74, 0x1A75, 0x1A76, 0x1A77, 0x1A78, 0x1A79, 0x1A7A, 0x1A7B, 0x1A7C, + 0x1A7D, 0x1A7E, 0x1A7F, 0x1A80, 0x1A81, 0x1A82, 0x1A83, 0x1A84, 0x1A85, + 0x1A86, 0x1A87, 0x1A88, 0x1A89, 0x1A8A, 0x1A8B, 0x1A8C, 0x1A8D, 0x1A8E, + 0x1A8F, 0x1A90, 0x1A91, 0x1A92, 0x1A93, 0x1A94, 0x1A95, 0x1A96, 0x1A97, + 0x1A98, 0x1A99, 0x1A9A, 0x1A9B, 0x1A9C, 0x1A9D, 0x1A9E, 0x1A9F, 0x1AA0, + 0x1AA1, 0x1AA2, 0x1AA3, 0x1AA4, 0x1AA5, 0x1AA6, 0x1AA7, 0x1AA8, 0x1AA9, + 0x1AAA, 0x1AAB, 0x1AAC, 0x1AAD, 0x1AAE, 0x1AAF, 0x1AB0, 0x1AB1, 0x1AB2, + 0x1AB3, 0x1AB4, 0x1AB5, 0x1AB6, 0x1AB7, 0x1AB8, 0x1AB9, 0x1ABA, 0x1ABB, + 0x1ABC, 0x1ABD, 0x1ABE, 0x1ABF, 0x1AC0, 0x1AC1, 0x1AC2, 0x1AC3, 0x1AC4, + 0x1AC5, 0x1AC6, 0x1AC7, 0x1AC8, 0x1AC9, 0x1ACA, 0x1ACB, 0x1ACC, 0x1ACD, + 0x1ACE, 0x1ACF, 0x1AD0, 0x1AD1, 0x1AD2, 0x1AD3, 0x1AD4, 0x1AD5, 0x1AD6, + 0x1AD7, 0x1AD8, 0x1AD9, 0x1ADA, 0x1ADB, 0x1ADC, 0x1ADD, 0x1ADE, 0x1ADF, + 0x1AE0, 0x1AE1, 0x1AE2, 0x1AE3, 0x1AE4, 0x1AE5, 0x1AE6, 0x1AE7, 0x1AE8, + 0x1AE9, 0x1AEA, 0x1AEB, 0x1AEC, 0x1AED, 0x1AEE, 0x1AEF, 0x1AF0, 0x1AF1, + 0x1AF2, 0x1AF3, 0x1AF4, 0x1AF5, 0x1AF6, 0x1AF7, 0x1AF8, 0x1AF9, 0x1AFA, + 0x1AFB, 0x1AFC, 0x1AFD, 0x1AFE, 0x1AFF, 0x1B00, 0x1B01, 0x1B02, 0x1B03, + 0x1B04, 0x1B05, 0x1B06, 0x1B07, 0x1B08, 0x1B09, 0x1B0A, 0x1B0B, 0x1B0C, + 0x1B0D, 0x1B0E, 0x1B0F, 0x1B10, 0x1B11, 0x1B12, 0x1B13, 0x1B14, 0x1B15, + 0x1B16, 0x1B17, 0x1B18, 0x1B19, 0x1B1A, 0x1B1B, 0x1B1C, 0x1B1D, 0x1B1E, + 0x1B1F, 0x1B20, 0x1B21, 0x1B22, 0x1B23, 0x1B24, 0x1B25, 0x1B26, 0x1B27, + 0x1B28, 0x1B29, 0x1B2A, 0x1B2B, 0x1B2C, 0x1B2D, 0x1B2E, 0x1B2F, 0x1B30, + 0x1B31, 0x1B32, 0x1B33, 0x1B34, 0x1B35, 0x1B36, 0x1B37, 0x1B38, 0x1B39, + 0x1B3A, 0x1B3B, 0x1B3C, 0x1B3D, 0x1B3E, 0x1B3F, 0x1B40, 0x1B41, 0x1B42, + 0x1B43, 0x1B44, 0x1B45, 0x1B46, 0x1B47, 0x1B48, 0x1B49, 0x1B4A, 0x1B4B, + 0x1B4C, 0x1B4D, 0x1B4E, 0x1B4F, 0x1B50, 0x1B51, 0x1B52, 0x1B53, 0x1B54, + 0x1B55, 0x1B56, 0x1B57, 0x1B58, 0x1B59, 0x1B5A, 0x1B5B, 0x1B5C, 0x1B5D, + 0x1B5E, 0x1B5F, 0x1B60, 0x1B61, 0x1B62, 0x1B63, 0x1B64, 0x1B65, 0x1B66, + 0x1B67, 0x1B68, 0x1B69, 0x1B6A, 0x1B6B, 0x1B6C, 0x1B6D, 0x1B6E, 0x1B6F, + 0x1B70, 0x1B71, 0x1B72, 0x1B73, 0x1B74, 0x1B75, 0x1B76, 0x1B77, 0x1B78, + 0x1B79, 0x1B7A, 0x1B7B, 0x1B7C, 0x1B7D, 0x1B7E, 0x1B7F, 0x1B80, 0x1B81, + 0x1B82, 0x1B83, 0x1B84, 0x1B85, 0x1B86, 0x1B87, 0x1B88, 0x1B89, 0x1B8A, + 0x1B8B, 0x1B8C, 0x1B8D, 0x1B8E, 0x1B8F, 0x1B90, 0x1B91, 0x1B92, 0x1B93, + 0x1B94, 0x1B95, 0x1B96, 0x1B97, 0x1B98, 0x1B99, 0x1B9A, 0x1B9B, 0x1B9C, + 0x1B9D, 0x1B9E, 0x1B9F, 0x1BA0, 0x1BA1, 0x1BA2, 0x1BA3, 0x1BA4, 0x1BA5, + 0x1BA6, 0x1BA7, 0x1BA8, 0x1BA9, 0x1BAA, 0x1BAB, 0x1BAC, 0x1BAD, 0x1BAE, + 0x1BAF, 0x1BB0, 0x1BB1, 0x1BB2, 0x1BB3, 0x1BB4, 0x1BB5, 0x1BB6, 0x1BB7, + 0x1BB8, 0x1BB9, 0x1BBA, 0x1BBB, 0x1BBC, 0x1BBD, 0x1BBE, 0x1BBF, 0x1BC0, + 0x1BC1, 0x1BC2, 0x1BC3, 0x1BC4, 0x1BC5, 0x1BC6, 0x1BC7, 0x1BC8, 0x1BC9, + 0x1BCA, 0x1BCB, 0x1BCC, 0x1BCD, 0x1BCE, 0x1BCF, 0x1BD0, 0x1BD1, 0x1BD2, + 0x1BD3, 0x1BD4, 0x1BD5, 0x1BD6, 0x1BD7, 0x1BD8, 0x1BD9, 0x1BDA, 0x1BDB, + 0x1BDC, 0x1BDD, 0x1BDE, 0x1BDF, 0x1BE0, 0x1BE1, 0x1BE2, 0x1BE3, 0x1BE4, + 0x1BE5, 0x1BE6, 0x1BE7, 0x1BE8, 0x1BE9, 0x1BEA, 0x1BEB, 0x1BEC, 0x1BED, + 0x1BEE, 0x1BEF, 0x1BF0, 0x1BF1, 0x1BF2, 0x1BF3, 0x1BF4, 0x1BF5, 0x1BF6, + 0x1BF7, 0x1BF8, 0x1BF9, 0x1BFA, 0x1BFB, 0x1BFC, 0x1BFD, 0x1BFE, 0x1BFF, + 0x1C00, 0x1C01, 0x1C02, 0x1C03, 0x1C04, 0x1C05, 0x1C06, 0x1C07, 0x1C08, + 0x1C09, 0x1C0A, 0x1C0B, 0x1C0C, 0x1C0D, 0x1C0E, 0x1C0F, 0x1C10, 0x1C11, + 0x1C12, 0x1C13, 0x1C14, 0x1C15, 0x1C16, 0x1C17, 0x1C18, 0x1C19, 0x1C1A, + 0x1C1B, 0x1C1C, 0x1C1D, 0x1C1E, 0x1C1F, 0x1C20, 0x1C21, 0x1C22, 0x1C23, + 0x1C24, 0x1C25, 0x1C26, 0x1C27, 0x1C28, 0x1C29, 0x1C2A, 0x1C2B, 0x1C2C, + 0x1C2D, 0x1C2E, 0x1C2F, 0x1C30, 0x1C31, 0x1C32, 0x1C33, 0x1C34, 0x1C35, + 0x1C36, 0x1C37, 0x1C38, 0x1C39, 0x1C3A, 0x1C3B, 0x1C3C, 0x1C3D, 0x1C3E, + 0x1C3F, 0x1C40, 0x1C41, 0x1C42, 0x1C43, 0x1C44, 0x1C45, 0x1C46, 0x1C47, + 0x1C48, 0x1C49, 0x1C4A, 0x1C4B, 0x1C4C, 0x1C4D, 0x1C4E, 0x1C4F, 0x1C50, + 0x1C51, 0x1C52, 0x1C53, 0x1C54, 0x1C55, 0x1C56, 0x1C57, 0x1C58, 0x1C59, + 0x1C5A, 0x1C5B, 0x1C5C, 0x1C5D, 0x1C5E, 0x1C5F, 0x1C60, 0x1C61, 0x1C62, + 0x1C63, 0x1C64, 0x1C65, 0x1C66, 0x1C67, 0x1C68, 0x1C69, 0x1C6A, 0x1C6B, + 0x1C6C, 0x1C6D, 0x1C6E, 0x1C6F, 0x1C70, 0x1C71, 0x1C72, 0x1C73, 0x1C74, + 0x1C75, 0x1C76, 0x1C77, 0x1C78, 0x1C79, 0x1C7A, 0x1C7B, 0x1C7C, 0x1C7D, + 0x1C7E, 0x1C7F, 0x1C80, 0x1C81, 0x1C82, 0x1C83, 0x1C84, 0x1C85, 0x1C86, + 0x1C87, 0x1C88, 0x1C89, 0x1C8A, 0x1C8B, 0x1C8C, 0x1C8D, 0x1C8E, 0x1C8F, + 0x1C90, 0x1C91, 0x1C92, 0x1C93, 0x1C94, 0x1C95, 0x1C96, 0x1C97, 0x1C98, + 0x1C99, 0x1C9A, 0x1C9B, 0x1C9C, 0x1C9D, 0x1C9E, 0x1C9F, 0x1CA0, 0x1CA1, + 0x1CA2, 0x1CA3, 0x1CA4, 0x1CA5, 0x1CA6, 0x1CA7, 0x1CA8, 0x1CA9, 0x1CAA, + 0x1CAB, 0x1CAC, 0x1CAD, 0x1CAE, 0x1CAF, 0x1CB0, 0x1CB1, 0x1CB2, 0x1CB3, + 0x1CB4, 0x1CB5, 0x1CB6, 0x1CB7, 0x1CB8, 0x1CB9, 0x1CBA, 0x1CBB, 0x1CBC, + 0x1CBD, 0x1CBE, 0x1CBF, 0x1CC0, 0x1CC1, 0x1CC2, 0x1CC3, 0x1CC4, 0x1CC5, + 0x1CC6, 0x1CC7, 0x1CC8, 0x1CC9, 0x1CCA, 0x1CCB, 0x1CCC, 0x1CCD, 0x1CCE, + 0x1CCF, 0x1CD0, 0x1CD1, 0x1CD2, 0x1CD3, 0x1CD4, 0x1CD5, 0x1CD6, 0x1CD7, + 0x1CD8, 0x1CD9, 0x1CDA, 0x1CDB, 0x1CDC, 0x1CDD, 0x1CDE, 0x1CDF, 0x1CE0, + 0x1CE1, 0x1CE2, 0x1CE3, 0x1CE4, 0x1CE5, 0x1CE6, 0x1CE7, 0x1CE8, 0x1CE9, + 0x1CEA, 0x1CEB, 0x1CEC, 0x1CED, 0x1CEE, 0x1CEF, 0x1CF0, 0x1CF1, 0x1CF2, + 0x1CF3, 0x1CF4, 0x1CF5, 0x1CF6, 0x1CF7, 0x1CF8, 0x1CF9, 0x1CFA, 0x1CFB, + 0x1CFC, 0x1CFD, 0x1CFE, 0x1CFF, 0x1D00, 0x1D01, 0x1D02, 0x1D03, 0x1D04, + 0x1D05, 0x1D06, 0x1D07, 0x1D08, 0x1D09, 0x1D0A, 0x1D0B, 0x1D0C, 0x1D0D, + 0x1D0E, 0x1D0F, 0x1D10, 0x1D11, 0x1D12, 0x1D13, 0x1D14, 0x1D15, 0x1D16, + 0x1D17, 0x1D18, 0x1D19, 0x1D1A, 0x1D1B, 0x1D1C, 0x1D1D, 0x1D1E, 0x1D1F, + 0x1D20, 0xA8BC, 0x1D22, 0x1D23, 0x1D24, 0x1D25, 0x1D26, 0x1D27, 0x1D28, + 0x1D29, 0x1D2A, 0x1D2B, 0x1D2C, 0x1D2D, 0x1D2E, 0x1D2F, 0x1D30, 0x1D31, + 0x1D32, 0x1D33, 0x1D34, 0x1D35, 0x1D36, 0x1D37, 0x1D38, 0x1D39, 0x1D3A, + 0x1D3B, 0x1D3C, 0x1D3D, 0x1D3E, 0x1D3F, 0x1D40, 0x1D41, 0x1D42, 0x1D43, + 0x1D44, 0x1D45, 0x1D46, 0x1D47, 0x1D48, 0x1D49, 0x1D4A, 0x1D4B, 0x1D4C, + 0x1D4D, 0x1D4E, 0x1D4F, 0x1D50, 0x1D51, 0x1D52, 0x1D53, 0x1D54, 0x1D55, + 0x1D56, 0x1D57, 0x1D58, 0x1D59, 0x1D5A, 0x1D5B, 0x1D5C, 0x1D5D, 0x1D5E, + 0x1D5F, 0x1D60, 0x1D61, 0x1D62, 0x1D63, 0x1D64, 0x1D65, 0x1D66, 0x1D67, + 0x1D68, 0x1D69, 0x1D6A, 0x1D6B, 0x1D6C, 0x1D6D, 0x1D6E, 0x1D6F, 0x1D70, + 0x1D71, 0x1D72, 0x1D73, 0x1D74, 0x1D75, 0x1D76, 0x1D77, 0x1D78, 0x1D79, + 0x1D7A, 0x1D7B, 0x1D7C, 0x1D7D, 0x1D7E, 0x1D7F, 0x1D80, 0x1D81, 0x1D82, + 0x1D83, 0x1D84, 0x1D85, 0x1D86, 0x1D87, 0x1D88, 0x1D89, 0x1D8A, 0x1D8B, + 0x1D8C, 0x1D8D, 0x1D8E, 0x1D8F, 0x1D90, 0x1D91, 0x1D92, 0x1D93, 0x1D94, + 0x1D95, 0x1D96, 0x1D97, 0x1D98, 0x1D99, 0x1D9A, 0x1D9B, 0x1D9C, 0x1D9D, + 0x1D9E, 0x1D9F, 0x1DA0, 0x1DA1, 0x1DA2, 0x1DA3, 0x1DA4, 0x1DA5, 0x1DA6, + 0x1DA7, 0x1DA8, 0x1DA9, 0x1DAA, 0x1DAB, 0x1DAC, 0x1DAD, 0x1DAE, 0x1DAF, + 0x1DB0, 0x1DB1, 0x1DB2, 0x1DB3, 0x1DB4, 0x1DB5, 0x1DB6, 0x1DB7, 0x1DB8, + 0x1DB9, 0x1DBA, 0x1DBB, 0x1DBC, 0x1DBD, 0x1DBE, 0x1DBF, 0x1DC0, 0x1DC1, + 0x1DC2, 0x1DC3, 0x1DC4, 0x1DC5, 0x1DC6, 0x1DC7, 0x1DC8, 0x1DC9, 0x1DCA, + 0x1DCB, 0x1DCC, 0x1DCD, 0x1DCE, 0x1DCF, 0x1DD0, 0x1DD1, 0x1DD2, 0x1DD3, + 0x1DD4, 0x1DD5, 0x1DD6, 0x1DD7, 0x1DD8, 0x1DD9, 0x1DDA, 0x1DDB, 0x1DDC, + 0x1DDD, 0x1DDE, 0x1DDF, 0x1DE0, 0x1DE1, 0x1DE2, 0x1DE3, 0x1DE4, 0x1DE5, + 0x1DE6, 0x1DE7, 0x1DE8, 0x1DE9, 0x1DEA, 0x1DEB, 0x1DEC, 0x1DED, 0x1DEE, + 0x1DEF, 0x1DF0, 0x1DF1, 0x1DF2, 0x1DF3, 0x1DF4, 0x1DF5, 0x1DF6, 0x1DF7, + 0x1DF8, 0x1DF9, 0x1DFA, 0x1DFB, 0x1DFC, 0x1DFD, 0x1DFE, 0x1DFF, 0x1E00, + 0x1E01, 0x1E02, 0x1E03, 0x1E04, 0x1E05, 0x1E06, 0x1E07, 0x1E08, 0x1E09, + 0x1E0A, 0x1E0B, 0x1E0C, 0x1E0D, 0x1E0E, 0x1E0F, 0x1E10, 0x1E11, 0x1E12, + 0x1E13, 0x1E14, 0x1E15, 0x1E16, 0x1E17, 0x1E18, 0x1E19, 0x1E1A, 0x1E1B, + 0x1E1C, 0x1E1D, 0x1E1E, 0x1E1F, 0x1E20, 0x1E21, 0x1E22, 0x1E23, 0x1E24, + 0x1E25, 0x1E26, 0x1E27, 0x1E28, 0x1E29, 0x1E2A, 0x1E2B, 0x1E2C, 0x1E2D, + 0x1E2E, 0x1E2F, 0x1E30, 0x1E31, 0x1E32, 0x1E33, 0x1E34, 0x1E35, 0x1E36, + 0x1E37, 0x1E38, 0x1E39, 0x1E3A, 0x1E3B, 0x1E3C, 0x1E3D, 0x1E3E, 0x1E3F, + 0x1E40, 0x1E41, 0x1E42, 0x1E43, 0x1E44, 0x1E45, 0x1E46, 0x1E47, 0x1E48, + 0x1E49, 0x1E4A, 0x1E4B, 0x1E4C, 0x1E4D, 0x1E4E, 0x1E4F, 0x1E50, 0x1E51, + 0x1E52, 0x1E53, 0x1E54, 0x1E55, 0x1E56, 0x1E57, 0x1E58, 0x1E59, 0x1E5A, + 0x1E5B, 0x1E5C, 0x1E5D, 0x1E5E, 0x1E5F, 0x1E60, 0x1E61, 0x1E62, 0x1E63, + 0x1E64, 0x1E65, 0x1E66, 0x1E67, 0x1E68, 0x1E69, 0x1E6A, 0x1E6B, 0x1E6C, + 0x1E6D, 0x1E6E, 0x1E6F, 0x1E70, 0x1E71, 0x1E72, 0x1E73, 0x1E74, 0x1E75, + 0x1E76, 0x1E77, 0x1E78, 0x1E79, 0x1E7A, 0x1E7B, 0x1E7C, 0x1E7D, 0x1E7E, + 0x1E7F, 0x1E80, 0x1E81, 0x1E82, 0x1E83, 0x1E84, 0x1E85, 0x1E86, 0x1E87, + 0x1E88, 0x1E89, 0x1E8A, 0x1E8B, 0x1E8C, 0x1E8D, 0x1E8E, 0x1E8F, 0x1E90, + 0x1E91, 0x1E92, 0x1E93, 0x1E94, 0x1E95, 0x1E96, 0x1E97, 0x1E98, 0x1E99, + 0x1E9A, 0x1E9B, 0x1E9C, 0x1E9D, 0x1E9E, 0x1E9F, 0x1EA0, 0x1EA1, 0x1EA2, + 0x1EA3, 0x1EA4, 0x1EA5, 0x1EA6, 0x1EA7, 0x1EA8, 0x1EA9, 0x1EAA, 0x1EAB, + 0x1EAC, 0x1EAD, 0x1EAE, 0x1EAF, 0x1EB0, 0x1EB1, 0x1EB2, 0x1EB3, 0x1EB4, + 0x1EB5, 0x1EB6, 0x1EB7, 0x1EB8, 0x1EB9, 0x1EBA, 0x1EBB, 0x1EBC, 0x1EBD, + 0x1EBE, 0x1EBF, 0x1EC0, 0x1EC1, 0x1EC2, 0x1EC3, 0x1EC4, 0x1EC5, 0x1EC6, + 0x1EC7, 0x1EC8, 0x1EC9, 0x1ECA, 0x1ECB, 0x1ECC, 0x1ECD, 0x1ECE, 0x1ECF, + 0x1ED0, 0x1ED1, 0x1ED2, 0x1ED3, 0x1ED4, 0x1ED5, 0x1ED6, 0x1ED7, 0x1ED8, + 0x1ED9, 0x1EDA, 0x1EDB, 0x1EDC, 0x1EDD, 0x1EDE, 0x1EDF, 0x1EE0, 0x1EE1, + 0x1EE2, 0x1EE3, 0x1EE4, 0x1EE5, 0x1EE6, 0x1EE7, 0x1EE8, 0x1EE9, 0x1EEA, + 0x1EEB, 0x1EEC, 0x1EED, 0x1EEE, 0x1EEF, 0x1EF0, 0x1EF1, 0xA95C, 0x1EF2, + 0x1EF3, 0xA843, 0xA1AA, 0xA844, 0xA1AC, 0x1EF4, 0xA1AE, 0xA1AF, 0x1EF5, + 0x1EF6, 0xA1B0, 0xA1B1, 0x1EF7, 0x1EF8, 0x1EF9, 0x1EFA, 0x1EFB, 0x1EFC, + 0x1EFD, 0xA845, 0xA1AD, 0x1EFE, 0x1EFF, 0x1F00, 0x1F01, 0x1F02, 0x1F03, + 0x1F04, 0x1F05, 0x1F06, 0xA1EB, 0x1F07, 0xA1E4, 0xA1E5, 0x1F08, 0xA846, + 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0xA1F9, 0x1F0E, 0x1F0F, 0x1F10, + 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x1F16, 0x1F17, 0x1F18, 0x1F19, + 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x1F1E, 0x1F1F, 0x1F20, 0x1F21, 0x1F22, + 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27, 0x1F28, 0x1F29, 0x1F2A, 0x1F2B, + 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F, 0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, + 0x1F35, 0x1F36, 0x1F37, 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, + 0x1F3E, 0x1F3F, 0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x1F46, + 0x1F47, 0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x1F4E, 0x1F4F, + 0x1F50, 0x1F51, 0x1F52, 0x1F53, 0x1F54, 0x1F55, 0x1F56, 0x1F57, 0x1F58, + 0x1F59, 0x1F5A, 0x1F5B, 0x1F5C, 0x1F5D, 0x1F5E, 0x1F5F, 0x1F60, 0x1F61, + 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67, 0x1F68, 0x1F69, 0x1F6A, + 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F, 0x1F70, 0x1F71, 0x1F72, 0x1F73, + 0x1F74, 0x1F75, 0x1F76, 0x1F77, 0x1F78, 0x1F79, 0x1F7A, 0x1F7B, 0x1F7C, + 0x1F7D, 0xA2E3, 0x1F7E, 0x1F7F, 0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, + 0x1F85, 0x1F86, 0x1F87, 0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, + 0x1F8E, 0x1F8F, 0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, + 0x1F97, 0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F, + 0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7, 0x1FA8, + 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF, 0x1FB0, 0x1FB1, + 0x1FB2, 0x1FB3, 0x1FB4, 0x1FB5, 0x1FB6, 0x1FB7, 0x1FB8, 0x1FB9, 0x1FBA, + 0x1FBB, 0x1FBC, 0x1FBD, 0x1FBE, 0x1FBF, 0x1FC0, 0x1FC1, 0x1FC2, 0x1FC3, + 0x1FC4, 0x1FC5, 0x1FC6, 0x1FC7, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FCC, + 0x1FCD, 0x1FCE, 0x1FCF, 0x1FD0, 0x1FD1, 0x1FD2, 0x1FD3, 0xA1E6, 0x1FD4, + 0xA847, 0x1FD5, 0x1FD6, 0x1FD7, 0xA848, 0x1FD8, 0x1FD9, 0x1FDA, 0x1FDB, + 0x1FDC, 0x1FDD, 0x1FDE, 0x1FDF, 0x1FE0, 0x1FE1, 0x1FE2, 0x1FE3, 0xA1ED, + 0x1FE4, 0x1FE5, 0x1FE6, 0x1FE7, 0x1FE8, 0x1FE9, 0x1FEA, 0x1FEB, 0x1FEC, + 0x1FED, 0xA959, 0x1FEE, 0x1FEF, 0x1FF0, 0x1FF1, 0x1FF2, 0x1FF3, 0x1FF4, + 0x1FF5, 0x1FF6, 0x1FF7, 0x1FF8, 0x1FF9, 0x1FFA, 0x1FFB, 0x1FFC, 0x1FFD, + 0x1FFE, 0x1FFF, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, + 0x2007, 0x2008, 0x2009, 0x200A, 0x200B, 0x200C, 0x200D, 0x200E, 0x200F, + 0x2010, 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017, 0x2018, + 0x2019, 0x201A, 0x201B, 0x201C, 0x201D, 0x201E, 0x201F, 0x2020, 0x2021, + 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027, 0x2028, 0x2029, 0x202A, + 0x202B, 0xA2F1, 0xA2F2, 0xA2F3, 0xA2F4, 0xA2F5, 0xA2F6, 0xA2F7, 0xA2F8, + 0xA2F9, 0xA2FA, 0xA2FB, 0xA2FC, 0x202C, 0x202D, 0x202E, 0x202F, 0xA2A1, + 0xA2A2, 0xA2A3, 0xA2A4, 0xA2A5, 0xA2A6, 0xA2A7, 0xA2A8, 0xA2A9, 0xA2AA, + 0x2030, 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037, 0x2038, + 0x2039, 0x203A, 0x203B, 0x203C, 0x203D, 0x203E, 0x203F, 0x2040, 0x2041, + 0x2042, 0x2043, 0x2044, 0x2045, 0xA1FB, 0xA1FC, 0xA1FA, 0xA1FD, 0x2046, + 0x2047, 0xA849, 0xA84A, 0xA84B, 0xA84C, 0x2048, 0x2049, 0x204A, 0x204B, + 0x204C, 0x204D, 0x204E, 0x204F, 0x2050, 0x2051, 0x2052, 0x2053, 0x2054, + 0x2055, 0x2056, 0x2057, 0x2058, 0x2059, 0x205A, 0x205B, 0x205C, 0x205D, + 0x205E, 0x205F, 0x2060, 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, + 0x2067, 0x2068, 0x2069, 0x206A, 0x206B, 0x206C, 0x206D, 0x206E, 0x206F, + 0x2070, 0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077, 0x2078, + 0x2079, 0x207A, 0x207B, 0x207C, 0x207D, 0x207E, 0x207F, 0x2080, 0x2081, + 0x2082, 0x2083, 0x2084, 0x2085, 0x2086, 0x2087, 0x2088, 0x2089, 0x208A, + 0x208B, 0x208C, 0x208D, 0x208E, 0x208F, 0x2090, 0x2091, 0x2092, 0x2093, + 0x2094, 0x2095, 0x2096, 0x2097, 0x2098, 0x2099, 0x209A, 0x209B, 0x209C, + 0x209D, 0x209E, 0x209F, 0x20A0, 0x20A1, 0x20A2, 0x20A3, 0x20A4, 0x20A5, + 0x20A6, 0x20A7, 0x20A8, 0x20A9, 0x20AA, 0x20AB, 0x20AC, 0x20AD, 0x20AE, + 0x20AF, 0x20B0, 0x20B1, 0x20B2, 0x20B3, 0x20B4, 0x20B5, 0xA1CA, 0x20B6, + 0x20B7, 0x20B8, 0x20B9, 0x20BA, 0x20BB, 0xA1C7, 0x20BC, 0xA1C6, 0x20BD, + 0x20BE, 0x20BF, 0xA84D, 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0xA1CC, 0x20C4, + 0x20C5, 0xA1D8, 0xA1DE, 0xA84E, 0xA1CF, 0x20C6, 0x20C7, 0xA84F, 0x20C8, + 0xA1CE, 0x20C9, 0xA1C4, 0xA1C5, 0xA1C9, 0xA1C8, 0xA1D2, 0x20CA, 0x20CB, + 0xA1D3, 0x20CC, 0x20CD, 0x20CE, 0x20CF, 0x20D0, 0xA1E0, 0xA1DF, 0xA1C3, + 0xA1CB, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0xA1D7, 0x20D6, 0x20D7, + 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x20DF, 0xA1D6, + 0x20E0, 0x20E1, 0x20E2, 0xA1D5, 0x20E3, 0x20E4, 0x20E5, 0x20E6, 0x20E7, + 0xA850, 0x20E8, 0x20E9, 0x20EA, 0x20EB, 0x20EC, 0x20ED, 0x20EE, 0x20EF, + 0x20F0, 0x20F1, 0x20F2, 0x20F3, 0x20F4, 0xA1D9, 0xA1D4, 0x20F5, 0x20F6, + 0xA1DC, 0xA1DD, 0xA851, 0xA852, 0x20F7, 0x20F8, 0x20F9, 0x20FA, 0x20FB, + 0x20FC, 0xA1DA, 0xA1DB, 0x20FD, 0x20FE, 0x20FF, 0x2100, 0x2101, 0x2102, + 0x2103, 0x2104, 0x2105, 0x2106, 0x2107, 0x2108, 0x2109, 0x210A, 0x210B, + 0x210C, 0x210D, 0x210E, 0x210F, 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, + 0x2115, 0x2116, 0x2117, 0x2118, 0x2119, 0x211A, 0x211B, 0x211C, 0x211D, + 0x211E, 0x211F, 0x2120, 0x2121, 0xA892, 0x2122, 0x2123, 0x2124, 0xA1D1, + 0x2125, 0x2126, 0x2127, 0x2128, 0x2129, 0x212A, 0x212B, 0x212C, 0x212D, + 0x212E, 0x212F, 0xA1CD, 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, + 0x2136, 0x2137, 0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, + 0x213F, 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147, + 0x2148, 0xA853, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F, + 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, + 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F, 0x2160, 0x2161, + 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, + 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0x2170, 0x2171, 0x2172, 0x2173, + 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, + 0x217D, 0x217E, 0x217F, 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, + 0x2186, 0x2187, 0x2188, 0x2189, 0x218A, 0x218B, 0x218C, 0x218D, 0x218E, + 0x218F, 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197, + 0x2198, 0x2199, 0x219A, 0xA1D0, 0x219B, 0x219C, 0x219D, 0x219E, 0x219F, + 0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, 0x21A5, 0x21A6, 0x21A7, 0x21A8, + 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21AE, 0x21AF, 0x21B0, 0x21B1, + 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, 0x21B7, 0x21B8, 0x21B9, 0x21BA, + 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF, 0x21C0, 0x21C1, 0x21C2, 0x21C3, + 0x21C4, 0x21C5, 0x21C6, 0x21C7, 0x21C8, 0x21C9, 0x21CA, 0x21CB, 0x21CC, + 0x21CD, 0x21CE, 0x21CF, 0x21D0, 0x21D1, 0x21D2, 0x21D3, 0x21D4, 0x21D5, + 0x21D6, 0x21D7, 0x21D8, 0x21D9, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21DE, + 0x21DF, 0x21E0, 0x21E1, 0x21E2, 0x21E3, 0x21E4, 0x21E5, 0x21E6, 0x21E7, + 0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, 0x21ED, 0x21EE, 0x21EF, 0x21F0, + 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, 0x21F6, 0x21F7, 0x21F8, 0x21F9, + 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, 0x21FF, 0x2200, 0x2201, 0x2202, + 0x2203, 0x2204, 0x2205, 0x2206, 0x2207, 0x2208, 0x2209, 0x220A, 0x220B, + 0x220C, 0x220D, 0x220E, 0x220F, 0x2210, 0x2211, 0x2212, 0x2213, 0x2214, + 0x2215, 0x2216, 0x2217, 0x2218, 0x2219, 0x221A, 0x221B, 0x221C, 0x221D, + 0x221E, 0x221F, 0x2220, 0x2221, 0x2222, 0x2223, 0x2224, 0x2225, 0x2226, + 0x2227, 0x2228, 0x2229, 0x222A, 0x222B, 0x222C, 0x222D, 0x222E, 0x222F, + 0x2230, 0x2231, 0x2232, 0x2233, 0x2234, 0x2235, 0x2236, 0x2237, 0x2238, + 0x2239, 0x223A, 0x223B, 0x223C, 0x223D, 0x223E, 0x223F, 0x2240, 0x2241, + 0x2242, 0x2243, 0x2244, 0x2245, 0x2246, 0x2247, 0x2248, 0x2249, 0x224A, + 0x224B, 0x224C, 0x224D, 0x224E, 0x224F, 0x2250, 0x2251, 0x2252, 0x2253, + 0x2254, 0x2255, 0x2256, 0x2257, 0x2258, 0x2259, 0x225A, 0x225B, 0x225C, + 0x225D, 0x225E, 0x225F, 0x2260, 0x2261, 0x2262, 0x2263, 0x2264, 0x2265, + 0x2266, 0x2267, 0x2268, 0x2269, 0x226A, 0x226B, 0x226C, 0x226D, 0x226E, + 0x226F, 0x2270, 0x2271, 0x2272, 0x2273, 0x2274, 0x2275, 0x2276, 0x2277, + 0x2278, 0x2279, 0x227A, 0x227B, 0x227C, 0x227D, 0x227E, 0x227F, 0x2280, + 0x2281, 0x2282, 0x2283, 0x2284, 0x2285, 0x2286, 0x2287, 0x2288, 0x2289, + 0x228A, 0x228B, 0x228C, 0x228D, 0x228E, 0x228F, 0x2290, 0x2291, 0x2292, + 0x2293, 0x2294, 0x2295, 0x2296, 0x2297, 0x2298, 0x2299, 0x229A, 0x229B, + 0x229C, 0x229D, 0x229E, 0x229F, 0x22A0, 0x22A1, 0x22A2, 0x22A3, 0x22A4, + 0x22A5, 0x22A6, 0x22A7, 0x22A8, 0x22A9, 0x22AA, 0x22AB, 0x22AC, 0x22AD, + 0x22AE, 0x22AF, 0x22B0, 0x22B1, 0x22B2, 0x22B3, 0x22B4, 0x22B5, 0x22B6, + 0x22B7, 0x22B8, 0x22B9, 0x22BA, 0x22BB, 0x22BC, 0x22BD, 0x22BE, 0x22BF, + 0x22C0, 0x22C1, 0x22C2, 0x22C3, 0x22C4, 0x22C5, 0x22C6, 0x22C7, 0x22C8, + 0x22C9, 0x22CA, 0x22CB, 0x22CC, 0x22CD, 0x22CE, 0x22CF, 0x22D0, 0x22D1, + 0x22D2, 0x22D3, 0x22D4, 0x22D5, 0x22D6, 0x22D7, 0x22D8, 0x22D9, 0x22DA, + 0x22DB, 0x22DC, 0x22DD, 0x22DE, 0x22DF, 0x22E0, 0x22E1, 0x22E2, 0x22E3, + 0x22E4, 0x22E5, 0x22E6, 0x22E7, 0xA2D9, 0xA2DA, 0xA2DB, 0xA2DC, 0xA2DD, + 0xA2DE, 0xA2DF, 0xA2E0, 0xA2E1, 0xA2E2, 0x22E8, 0x22E9, 0x22EA, 0x22EB, + 0x22EC, 0x22ED, 0x22EE, 0x22EF, 0x22F0, 0x22F1, 0xA2C5, 0xA2C6, 0xA2C7, + 0xA2C8, 0xA2C9, 0xA2CA, 0xA2CB, 0xA2CC, 0xA2CD, 0xA2CE, 0xA2CF, 0xA2D0, + 0xA2D1, 0xA2D2, 0xA2D3, 0xA2D4, 0xA2D5, 0xA2D6, 0xA2D7, 0xA2D8, 0xA2B1, + 0xA2B2, 0xA2B3, 0xA2B4, 0xA2B5, 0xA2B6, 0xA2B7, 0xA2B8, 0xA2B9, 0xA2BA, + 0xA2BB, 0xA2BC, 0xA2BD, 0xA2BE, 0xA2BF, 0xA2C0, 0xA2C1, 0xA2C2, 0xA2C3, + 0xA2C4, 0x22F2, 0x22F3, 0x22F4, 0x22F5, 0x22F6, 0x22F7, 0x22F8, 0x22F9, + 0x22FA, 0x22FB, 0x22FC, 0x22FD, 0x22FE, 0x22FF, 0x2300, 0x2301, 0x2302, + 0x2303, 0x2304, 0x2305, 0x2306, 0x2307, 0x2308, 0x2309, 0x230A, 0x230B, + 0x230C, 0x230D, 0x230E, 0x230F, 0x2310, 0x2311, 0x2312, 0x2313, 0x2314, + 0x2315, 0x2316, 0x2317, 0x2318, 0x2319, 0x231A, 0x231B, 0x231C, 0x231D, + 0x231E, 0x231F, 0x2320, 0x2321, 0x2322, 0x2323, 0x2324, 0x2325, 0x2326, + 0x2327, 0x2328, 0x2329, 0x232A, 0x232B, 0x232C, 0x232D, 0x232E, 0x232F, + 0x2330, 0x2331, 0x2332, 0x2333, 0x2334, 0x2335, 0x2336, 0x2337, 0x2338, + 0x2339, 0x233A, 0x233B, 0x233C, 0x233D, 0x233E, 0x233F, 0x2340, 0x2341, + 0x2342, 0x2343, 0x2344, 0x2345, 0x2346, 0x2347, 0x2348, 0x2349, 0x234A, + 0x234B, 0x234C, 0x234D, 0x234E, 0x234F, 0x2350, 0x2351, 0x2352, 0x2353, + 0x2354, 0x2355, 0xA9A4, 0xA9A5, 0xA9A6, 0xA9A7, 0xA9A8, 0xA9A9, 0xA9AA, + 0xA9AB, 0xA9AC, 0xA9AD, 0xA9AE, 0xA9AF, 0xA9B0, 0xA9B1, 0xA9B2, 0xA9B3, + 0xA9B4, 0xA9B5, 0xA9B6, 0xA9B7, 0xA9B8, 0xA9B9, 0xA9BA, 0xA9BB, 0xA9BC, + 0xA9BD, 0xA9BE, 0xA9BF, 0xA9C0, 0xA9C1, 0xA9C2, 0xA9C3, 0xA9C4, 0xA9C5, + 0xA9C6, 0xA9C7, 0xA9C8, 0xA9C9, 0xA9CA, 0xA9CB, 0xA9CC, 0xA9CD, 0xA9CE, + 0xA9CF, 0xA9D0, 0xA9D1, 0xA9D2, 0xA9D3, 0xA9D4, 0xA9D5, 0xA9D6, 0xA9D7, + 0xA9D8, 0xA9D9, 0xA9DA, 0xA9DB, 0xA9DC, 0xA9DD, 0xA9DE, 0xA9DF, 0xA9E0, + 0xA9E1, 0xA9E2, 0xA9E3, 0xA9E4, 0xA9E5, 0xA9E6, 0xA9E7, 0xA9E8, 0xA9E9, + 0xA9EA, 0xA9EB, 0xA9EC, 0xA9ED, 0xA9EE, 0xA9EF, 0x2356, 0x2357, 0x2358, + 0x2359, 0xA854, 0xA855, 0xA856, 0xA857, 0xA858, 0xA859, 0xA85A, 0xA85B, + 0xA85C, 0xA85D, 0xA85E, 0xA85F, 0xA860, 0xA861, 0xA862, 0xA863, 0xA864, + 0xA865, 0xA866, 0xA867, 0xA868, 0xA869, 0xA86A, 0xA86B, 0xA86C, 0xA86D, + 0xA86E, 0xA86F, 0xA870, 0xA871, 0xA872, 0xA873, 0xA874, 0xA875, 0xA876, + 0xA877, 0x235A, 0x235B, 0x235C, 0x235D, 0x235E, 0x235F, 0x2360, 0x2361, + 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0xA878, 0xA879, 0xA87A, 0xA87B, + 0xA87C, 0xA87D, 0xA87E, 0xA880, 0xA881, 0xA882, 0xA883, 0xA884, 0xA885, + 0xA886, 0xA887, 0x2367, 0x2368, 0x2369, 0xA888, 0xA889, 0xA88A, 0x236A, + 0x236B, 0x236C, 0x236D, 0x236E, 0x236F, 0x2370, 0x2371, 0x2372, 0x2373, + 0xA1F6, 0xA1F5, 0x2374, 0x2375, 0x2376, 0x2377, 0x2378, 0x2379, 0x237A, + 0x237B, 0x237C, 0x237D, 0x237E, 0x237F, 0x2380, 0x2381, 0x2382, 0x2383, + 0xA1F8, 0xA1F7, 0x2384, 0x2385, 0x2386, 0x2387, 0x2388, 0x2389, 0x238A, + 0x238B, 0xA88B, 0xA88C, 0x238C, 0x238D, 0x238E, 0x238F, 0x2390, 0x2391, + 0x2392, 0x2393, 0xA1F4, 0xA1F3, 0x2394, 0x2395, 0x2396, 0xA1F0, 0x2397, + 0x2398, 0xA1F2, 0xA1F1, 0x2399, 0x239A, 0x239B, 0x239C, 0x239D, 0x239E, + 0x239F, 0x23A0, 0x23A1, 0x23A2, 0x23A3, 0x23A4, 0x23A5, 0x23A6, 0x23A7, + 0x23A8, 0x23A9, 0x23AA, 0xA88D, 0xA88E, 0xA88F, 0xA890, 0x23AB, 0x23AC, + 0x23AD, 0x23AE, 0x23AF, 0x23B0, 0x23B1, 0x23B2, 0x23B3, 0x23B4, 0x23B5, + 0x23B6, 0x23B7, 0x23B8, 0x23B9, 0x23BA, 0x23BB, 0x23BC, 0x23BD, 0x23BE, + 0x23BF, 0x23C0, 0x23C1, 0x23C2, 0x23C3, 0x23C4, 0x23C5, 0x23C6, 0x23C7, + 0x23C8, 0x23C9, 0xA1EF, 0xA1EE, 0x23CA, 0x23CB, 0xA891, 0x23CC, 0x23CD, + 0x23CE, 0x23CF, 0x23D0, 0x23D1, 0x23D2, 0x23D3, 0x23D4, 0x23D5, 0x23D6, + 0x23D7, 0x23D8, 0x23D9, 0x23DA, 0x23DB, 0x23DC, 0x23DD, 0x23DE, 0x23DF, + 0x23E0, 0x23E1, 0x23E2, 0x23E3, 0x23E4, 0x23E5, 0x23E6, 0x23E7, 0x23E8, + 0x23E9, 0x23EA, 0x23EB, 0x23EC, 0x23ED, 0x23EE, 0x23EF, 0x23F0, 0x23F1, + 0x23F2, 0x23F3, 0x23F4, 0x23F5, 0x23F6, 0x23F7, 0x23F8, 0x23F9, 0x23FA, + 0x23FB, 0x23FC, 0x23FD, 0x23FE, 0x23FF, 0x2400, 0x2401, 0xA1E2, 0x2402, + 0xA1E1, 0x2403, 0x2404, 0x2405, 0x2406, 0x2407, 0x2408, 0x2409, 0x240A, + 0x240B, 0x240C, 0x240D, 0x240E, 0x240F, 0x2410, 0x2411, 0x2412, 0x2413, + 0x2414, 0x2415, 0x2416, 0x2417, 0x2418, 0x2419, 0x241A, 0x241B, 0x241C, + 0x241D, 0x241E, 0x241F, 0x2420, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, + 0x2426, 0x2427, 0x2428, 0x2429, 0x242A, 0x242B, 0x242C, 0x242D, 0x242E, + 0x242F, 0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437, + 0x2438, 0x2439, 0x243A, 0x243B, 0x243C, 0x243D, 0x243E, 0x243F, 0x2440, + 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447, 0x2448, 0x2449, + 0x244A, 0x244B, 0x244C, 0x244D, 0x244E, 0x244F, 0x2450, 0x2451, 0x2452, + 0x2453, 0x2454, 0x2455, 0x2456, 0x2457, 0x2458, 0x2459, 0x245A, 0x245B, + 0x245C, 0x245D, 0x245E, 0x245F, 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, + 0x2465, 0x2466, 0x2467, 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, + 0x246E, 0x246F, 0x2470, 0x2471, 0x2472, 0x2473, 0x2474, 0x2475, 0x2476, + 0x2477, 0x2478, 0x2479, 0x247A, 0x247B, 0x247C, 0x247D, 0x247E, 0x247F, + 0x2480, 0x2481, 0x2482, 0x2483, 0x2484, 0x2485, 0x2486, 0x2487, 0x2488, + 0x2489, 0x248A, 0x248B, 0x248C, 0x248D, 0x248E, 0x248F, 0x2490, 0x2491, + 0x2492, 0x2493, 0x2494, 0x2495, 0x2496, 0x2497, 0x2498, 0x2499, 0x249A, + 0x249B, 0x249C, 0x249D, 0x249E, 0x249F, 0x24A0, 0x24A1, 0x24A2, 0x24A3, + 0x24A4, 0x24A5, 0x24A6, 0x24A7, 0x24A8, 0x24A9, 0x24AA, 0x24AB, 0x24AC, + 0x24AD, 0x24AE, 0x24AF, 0x24B0, 0x24B1, 0x24B2, 0x24B3, 0x24B4, 0x24B5, + 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, 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, 0x24EA, 0x24EB, + 0x24EC, 0x24ED, 0x24EE, 0x24EF, 0x24F0, 0x24F1, 0x24F2, 0x24F3, 0x24F4, + 0x24F5, 0x24F6, 0x24F7, 0x24F8, 0x24F9, 0x24FA, 0x24FB, 0x24FC, 0x24FD, + 0x24FE, 0x24FF, 0x2500, 0x2501, 0x2502, 0x2503, 0x2504, 0x2505, 0x2506, + 0x2507, 0x2508, 0x2509, 0x250A, 0x250B, 0x250C, 0x250D, 0x250E, 0x250F, + 0x2510, 0x2511, 0x2512, 0x2513, 0x2514, 0x2515, 0x2516, 0x2517, 0x2518, + 0x2519, 0x251A, 0x251B, 0x251C, 0x251D, 0x251E, 0x251F, 0x2520, 0x2521, + 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527, 0x2528, 0x2529, 0x252A, + 0x252B, 0x252C, 0x252D, 0x252E, 0x252F, 0x2530, 0x2531, 0x2532, 0x2533, + 0x2534, 0x2535, 0x2536, 0x2537, 0x2538, 0x2539, 0x253A, 0x253B, 0x253C, + 0x253D, 0x253E, 0x253F, 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, + 0x2546, 0x2547, 0x2548, 0x2549, 0x254A, 0x254B, 0x254C, 0x254D, 0x254E, + 0x254F, 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, 0x2556, 0x2557, + 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E, 0x255F, 0x2560, + 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567, 0x2568, 0x2569, + 0x256A, 0x256B, 0x256C, 0x256D, 0x256E, 0x256F, 0x2570, 0x2571, 0x2572, + 0x2573, 0x2574, 0x2575, 0x2576, 0x2577, 0x2578, 0x2579, 0x257A, 0x257B, + 0x257C, 0x257D, 0x257E, 0x257F, 0x2580, 0x2581, 0x2582, 0x2583, 0x2584, + 0x2585, 0x2586, 0x2587, 0x2588, 0x2589, 0x258A, 0x258B, 0x258C, 0x258D, + 0x258E, 0x258F, 0x2590, 0x2591, 0x2592, 0x2593, 0x2594, 0x2595, 0x2596, + 0x2597, 0x2598, 0x2599, 0x259A, 0x259B, 0x259C, 0x259D, 0x259E, 0x259F, + 0x25A0, 0x25A1, 0x25A2, 0x25A3, 0x25A4, 0x25A5, 0x25A6, 0x25A7, 0x25A8, + 0x25A9, 0x25AA, 0x25AB, 0x25AC, 0x25AD, 0x25AE, 0x25AF, 0x25B0, 0x25B1, + 0x25B2, 0x25B3, 0x25B4, 0x25B5, 0x25B6, 0x25B7, 0x25B8, 0x25B9, 0x25BA, + 0x25BB, 0x25BC, 0x25BD, 0x25BE, 0x25BF, 0x25C0, 0x25C1, 0x25C2, 0x25C3, + 0x25C4, 0x25C5, 0x25C6, 0x25C7, 0x25C8, 0x25C9, 0x25CA, 0x25CB, 0x25CC, + 0x25CD, 0x25CE, 0x25CF, 0x25D0, 0x25D1, 0x25D2, 0x25D3, 0x25D4, 0x25D5, + 0x25D6, 0x25D7, 0x25D8, 0x25D9, 0x25DA, 0x25DB, 0x25DC, 0x25DD, 0x25DE, + 0x25DF, 0x25E0, 0x25E1, 0x25E2, 0x25E3, 0x25E4, 0x25E5, 0x25E6, 0x25E7, + 0x25E8, 0x25E9, 0x25EA, 0x25EB, 0x25EC, 0x25ED, 0x25EE, 0x25EF, 0x25F0, + 0x25F1, 0x25F2, 0x25F3, 0x25F4, 0x25F5, 0x25F6, 0x25F7, 0x25F8, 0x25F9, + 0x25FA, 0x25FB, 0x25FC, 0x25FD, 0x25FE, 0x25FF, 0x2600, 0x2601, 0x2602, + 0x2603, 0x2604, 0x2605, 0x2606, 0x2607, 0x2608, 0x2609, 0x260A, 0x260B, + 0x260C, 0x260D, 0x260E, 0x260F, 0x2610, 0x2611, 0x2612, 0x2613, 0x2614, + 0x2615, 0x2616, 0x2617, 0x2618, 0x2619, 0x261A, 0x261B, 0x261C, 0x261D, + 0x261E, 0x261F, 0x2620, 0x2621, 0x2622, 0x2623, 0x2624, 0x2625, 0x2626, + 0x2627, 0x2628, 0x2629, 0x262A, 0x262B, 0x262C, 0x262D, 0x262E, 0x262F, + 0x2630, 0x2631, 0x2632, 0x2633, 0x2634, 0x2635, 0x2636, 0x2637, 0x2638, + 0x2639, 0x263A, 0x263B, 0x263C, 0x263D, 0x263E, 0x263F, 0x2640, 0x2641, + 0x2642, 0x2643, 0x2644, 0x2645, 0x2646, 0x2647, 0x2648, 0x2649, 0x264A, + 0x264B, 0x264C, 0x264D, 0x264E, 0x264F, 0x2650, 0x2651, 0x2652, 0x2653, + 0x2654, 0x2655, 0x2656, 0x2657, 0x2658, 0x2659, 0x265A, 0x265B, 0x265C, + 0x265D, 0x265E, 0x265F, 0x2660, 0x2661, 0x2662, 0x2663, 0x2664, 0x2665, + 0x2666, 0x2667, 0x2668, 0x2669, 0x266A, 0x266B, 0x266C, 0x266D, 0x266E, + 0x266F, 0x2670, 0x2671, 0x2672, 0x2673, 0x2674, 0x2675, 0x2676, 0x2677, + 0x2678, 0x2679, 0x267A, 0x267B, 0x267C, 0x267D, 0x267E, 0x267F, 0x2680, + 0x2681, 0x2682, 0x2683, 0x2684, 0x2685, 0x2686, 0x2687, 0x2688, 0x2689, + 0x268A, 0x268B, 0x268C, 0x268D, 0x268E, 0x268F, 0x2690, 0x2691, 0x2692, + 0x2693, 0x2694, 0x2695, 0x2696, 0x2697, 0x2698, 0x2699, 0x269A, 0x269B, + 0x269C, 0x269D, 0x269E, 0x269F, 0x26A0, 0x26A1, 0x26A2, 0x26A3, 0x26A4, + 0x26A5, 0x26A6, 0x26A7, 0x26A8, 0x26A9, 0x26AA, 0x26AB, 0x26AC, 0x26AD, + 0x26AE, 0x26AF, 0x26B0, 0x26B1, 0x26B2, 0x26B3, 0x26B4, 0x26B5, 0x26B6, + 0x26B7, 0x26B8, 0x26B9, 0x26BA, 0x26BB, 0x26BC, 0x26BD, 0x26BE, 0x26BF, + 0x26C0, 0x26C1, 0x26C2, 0x26C3, 0x26C4, 0x26C5, 0x26C6, 0x26C7, 0x26C8, + 0x26C9, 0x26CA, 0x26CB, 0x26CC, 0x26CD, 0x26CE, 0x26CF, 0x26D0, 0x26D1, + 0x26D2, 0x26D3, 0x26D4, 0x26D5, 0x26D6, 0x26D7, 0x26D8, 0x26D9, 0x26DA, + 0x26DB, 0x26DC, 0x26DD, 0x26DE, 0x26DF, 0x26E0, 0x26E1, 0x26E2, 0x26E3, + 0x26E4, 0x26E5, 0x26E6, 0x26E7, 0x26E8, 0x26E9, 0x26EA, 0x26EB, 0x26EC, + 0x26ED, 0x26EE, 0x26EF, 0x26F0, 0x26F1, 0x26F2, 0x26F3, 0x26F4, 0x26F5, + 0x26F6, 0x26F7, 0x26F8, 0x26F9, 0x26FA, 0x26FB, 0x26FC, 0x26FD, 0x26FE, + 0x26FF, 0x2700, 0x2701, 0x2702, 0x2703, 0x2704, 0x2705, 0x2706, 0x2707, + 0x2708, 0x2709, 0x270A, 0x270B, 0x270C, 0x270D, 0x270E, 0x270F, 0x2710, + 0x2711, 0x2712, 0x2713, 0x2714, 0x2715, 0x2716, 0x2717, 0x2718, 0x2719, + 0x271A, 0x271B, 0x271C, 0x271D, 0x271E, 0x271F, 0x2720, 0x2721, 0x2722, + 0x2723, 0x2724, 0x2725, 0x2726, 0x2727, 0x2728, 0x2729, 0x272A, 0x272B, + 0x272C, 0x272D, 0x272E, 0x272F, 0x2730, 0x2731, 0x2732, 0x2733, 0x2734, + 0x2735, 0x2736, 0x2737, 0x2738, 0x2739, 0x273A, 0x273B, 0x273C, 0x273D, + 0x273E, 0x273F, 0x2740, 0x2741, 0x2742, 0x2743, 0x2744, 0x2745, 0x2746, + 0x2747, 0x2748, 0x2749, 0x274A, 0x274B, 0x274C, 0x274D, 0x274E, 0x274F, + 0x2750, 0x2751, 0x2752, 0x2753, 0x2754, 0x2755, 0x2756, 0x2757, 0x2758, + 0x2759, 0x275A, 0x275B, 0x275C, 0x275D, 0x275E, 0x275F, 0x2760, 0x2761, + 0x2762, 0x2763, 0x2764, 0x2765, 0x2766, 0x2767, 0x2768, 0x2769, 0x276A, + 0x276B, 0x276C, 0x276D, 0x276E, 0x276F, 0x2770, 0x2771, 0x2772, 0x2773, + 0x2774, 0x2775, 0x2776, 0x2777, 0x2778, 0x2779, 0x277A, 0x277B, 0x277C, + 0x277D, 0x277E, 0x277F, 0x2780, 0x2781, 0x2782, 0x2783, 0x2784, 0x2785, + 0x2786, 0x2787, 0x2788, 0x2789, 0x278A, 0x278B, 0x278C, 0x278D, 0x278E, + 0x278F, 0x2790, 0x2791, 0x2792, 0x2793, 0x2794, 0x2795, 0x2796, 0x2797, + 0x2798, 0x2799, 0x279A, 0x279B, 0x279C, 0x279D, 0x279E, 0x279F, 0x27A0, + 0x27A1, 0x27A2, 0x27A3, 0x27A4, 0x27A5, 0x27A6, 0x27A7, 0x27A8, 0x27A9, + 0x27AA, 0x27AB, 0x27AC, 0x27AD, 0x27AE, 0x27AF, 0x27B0, 0x27B1, 0x27B2, + 0x27B3, 0x27B4, 0x27B5, 0x27B6, 0x27B7, 0x27B8, 0x27B9, 0x27BA, 0x27BB, + 0x27BC, 0x27BD, 0x27BE, 0x27BF, 0x27C0, 0x27C1, 0x27C2, 0x27C3, 0x27C4, + 0x27C5, 0x27C6, 0x27C7, 0x27C8, 0x27C9, 0x27CA, 0x27CB, 0x27CC, 0x27CD, + 0x27CE, 0x27CF, 0x27D0, 0x27D1, 0x27D2, 0x27D3, 0x27D4, 0x27D5, 0x27D6, + 0x27D7, 0x27D8, 0x27D9, 0x27DA, 0x27DB, 0x27DC, 0x27DD, 0x27DE, 0x27DF, + 0x27E0, 0x27E1, 0x27E2, 0x27E3, 0x27E4, 0x27E5, 0x27E6, 0x27E7, 0x27E8, + 0x27E9, 0x27EA, 0x27EB, 0x27EC, 0x27ED, 0x27EE, 0x27EF, 0x27F0, 0x27F1, + 0x27F2, 0x27F3, 0x27F4, 0x27F5, 0x27F6, 0x27F7, 0x27F8, 0x27F9, 0x27FA, + 0x27FB, 0x27FC, 0x27FD, 0x27FE, 0x27FF, 0x2800, 0x2801, 0x2802, 0x2803, + 0x2804, 0x2805, 0x2806, 0x2807, 0x2808, 0x2809, 0x280A, 0x280B, 0x280C, + 0x280D, 0x280E, 0x280F, 0x2810, 0x2811, 0x2812, 0x2813, 0x2814, 0x2815, + 0x2816, 0x2817, 0x2818, 0x2819, 0x281A, 0x281B, 0x281C, 0x281D, 0x281E, + 0x281F, 0x2820, 0x2821, 0x2822, 0x2823, 0x2824, 0x2825, 0x2826, 0x2827, + 0x2828, 0x2829, 0x282A, 0x282B, 0x282C, 0x282D, 0x282E, 0x282F, 0x2830, + 0x2831, 0x2832, 0x2833, 0x2834, 0x2835, 0x2836, 0x2837, 0x2838, 0x2839, + 0x283A, 0x283B, 0x283C, 0x283D, 0x283E, 0x283F, 0x2840, 0x2841, 0x2842, + 0x2843, 0x2844, 0x2845, 0x2846, 0x2847, 0x2848, 0x2849, 0x284A, 0x284B, + 0x284C, 0x284D, 0x284E, 0x284F, 0x2850, 0x2851, 0x2852, 0x2853, 0x2854, + 0x2855, 0x2856, 0x2857, 0x2858, 0x2859, 0x285A, 0x285B, 0x285C, 0x285D, + 0x285E, 0x285F, 0x2860, 0x2861, 0x2862, 0x2863, 0x2864, 0x2865, 0x2866, + 0x2867, 0x2868, 0x2869, 0x286A, 0x286B, 0x286C, 0x286D, 0x286E, 0x286F, + 0x2870, 0x2871, 0x2872, 0x2873, 0x2874, 0x2875, 0x2876, 0x2877, 0x2878, + 0x2879, 0x287A, 0x287B, 0x287C, 0x287D, 0x287E, 0x287F, 0x2880, 0x2881, + 0x2882, 0x2883, 0x2884, 0x2885, 0x2886, 0x2887, 0x2888, 0x2889, 0x288A, + 0x288B, 0x288C, 0x288D, 0x288E, 0x288F, 0x2890, 0x2891, 0x2892, 0x2893, + 0x2894, 0x2895, 0x2896, 0x2897, 0x2898, 0x2899, 0x289A, 0x289B, 0x289C, + 0x289D, 0x289E, 0x289F, 0x28A0, 0x28A1, 0x28A2, 0x28A3, 0x28A4, 0x28A5, + 0x28A6, 0x28A7, 0x28A8, 0x28A9, 0x28AA, 0x28AB, 0x28AC, 0x28AD, 0x28AE, + 0x28AF, 0x28B0, 0x28B1, 0x28B2, 0x28B3, 0x28B4, 0x28B5, 0x28B6, 0x28B7, + 0x28B8, 0x28B9, 0x28BA, 0x28BB, 0x28BC, 0x28BD, 0x28BE, 0x28BF, 0x28C0, + 0x28C1, 0x28C2, 0x28C3, 0x28C4, 0x28C5, 0x28C6, 0x28C7, 0x28C8, 0x28C9, + 0x28CA, 0x28CB, 0x28CC, 0x28CD, 0x28CE, 0x28CF, 0x28D0, 0x28D1, 0x28D2, + 0x28D3, 0x28D4, 0x28D5, 0x28D6, 0x28D7, 0x28D8, 0x28D9, 0x28DA, 0x28DB, + 0x28DC, 0x28DD, 0x28DE, 0x28DF, 0x28E0, 0x28E1, 0x28E2, 0x28E3, 0x28E4, + 0x28E5, 0x28E6, 0x28E7, 0x28E8, 0x28E9, 0x28EA, 0x28EB, 0x28EC, 0x28ED, + 0x28EE, 0x28EF, 0x28F0, 0x28F1, 0x28F2, 0x28F3, 0x28F4, 0x28F5, 0x28F6, + 0x28F7, 0x28F8, 0x28F9, 0x28FA, 0x28FB, 0x28FC, 0x28FD, 0x28FE, 0x28FF, + 0x2900, 0x2901, 0x2902, 0x2903, 0x2904, 0x2905, 0x2906, 0x2907, 0x2908, + 0x2909, 0x290A, 0x290B, 0x290C, 0x290D, 0x290E, 0x290F, 0x2910, 0x2911, + 0x2912, 0x2913, 0x2914, 0x2915, 0x2916, 0x2917, 0x2918, 0x2919, 0x291A, + 0x291B, 0x291C, 0x291D, 0x291E, 0x291F, 0x2920, 0x2921, 0x2922, 0x2923, + 0x2924, 0x2925, 0x2926, 0x2927, 0x2928, 0x2929, 0x292A, 0x292B, 0x292C, + 0x292D, 0x292E, 0x292F, 0x2930, 0x2931, 0x2932, 0x2933, 0x2934, 0x2935, + 0x2936, 0x2937, 0x2938, 0x2939, 0x293A, 0x293B, 0x293C, 0x293D, 0x293E, + 0x293F, 0x2940, 0x2941, 0x2942, 0x2943, 0x2944, 0x2945, 0x2946, 0x2947, + 0x2948, 0x2949, 0x294A, 0x294B, 0x294C, 0x294D, 0x294E, 0x294F, 0x2950, + 0x2951, 0x2952, 0x2953, 0x2954, 0x2955, 0x2956, 0x2957, 0x2958, 0x2959, + 0x295A, 0x295B, 0x295C, 0x295D, 0x295E, 0x295F, 0x2960, 0x2961, 0x2962, + 0x2963, 0x2964, 0x2965, 0x2966, 0x2967, 0x2968, 0x2969, 0x296A, 0x296B, + 0x296C, 0x296D, 0x296E, 0x296F, 0x2970, 0x2971, 0x2972, 0x2973, 0x2974, + 0x2975, 0x2976, 0x2977, 0x2978, 0x2979, 0x297A, 0x297B, 0x297C, 0x297D, + 0x297E, 0x297F, 0x2980, 0x2981, 0x2982, 0x2983, 0x2984, 0x2985, 0x2986, + 0x2987, 0x2988, 0x2989, 0x298A, 0x298B, 0x298C, 0x298D, 0x298E, 0x298F, + 0x2990, 0x2991, 0x2992, 0x2993, 0x2994, 0x2995, 0x2996, 0x2997, 0x2998, + 0x2999, 0x299A, 0x299B, 0x299C, 0x299D, 0x299E, 0x299F, 0x29A0, 0x29A1, + 0x29A2, 0x29A3, 0x29A4, 0x29A5, 0x29A6, 0x29A7, 0x29A8, 0x29A9, 0x29AA, + 0x29AB, 0x29AC, 0x29AD, 0x29AE, 0x29AF, 0x29B0, 0x29B1, 0x29B2, 0x29B3, + 0x29B4, 0x29B5, 0x29B6, 0x29B7, 0x29B8, 0x29B9, 0x29BA, 0x29BB, 0x29BC, + 0x29BD, 0x29BE, 0x29BF, 0x29C0, 0x29C1, 0x29C2, 0x29C3, 0x29C4, 0x29C5, + 0x29C6, 0x29C7, 0x29C8, 0x29C9, 0x29CA, 0x29CB, 0x29CC, 0x29CD, 0x29CE, + 0x29CF, 0x29D0, 0x29D1, 0x29D2, 0x29D3, 0x29D4, 0x29D5, 0x29D6, 0x29D7, + 0x29D8, 0x29D9, 0x29DA, 0x29DB, 0x29DC, 0x29DD, 0x29DE, 0x29DF, 0x29E0, + 0x29E1, 0x29E2, 0x29E3, 0x29E4, 0x29E5, 0x29E6, 0x29E7, 0x29E8, 0x29E9, + 0x29EA, 0x29EB, 0x29EC, 0x29ED, 0x29EE, 0x29EF, 0x29F0, 0x29F1, 0x29F2, + 0x29F3, 0x29F4, 0x29F5, 0x29F6, 0x29F7, 0x29F8, 0x29F9, 0x29FA, 0x29FB, + 0x29FC, 0x29FD, 0x29FE, 0x29FF, 0x2A00, 0x2A01, 0x2A02, 0x2A03, 0x2A04, + 0x2A05, 0x2A06, 0x2A07, 0x2A08, 0x2A09, 0x2A0A, 0x2A0B, 0x2A0C, 0x2A0D, + 0x2A0E, 0x2A0F, 0x2A10, 0x2A11, 0x2A12, 0x2A13, 0x2A14, 0x2A15, 0x2A16, + 0x2A17, 0x2A18, 0x2A19, 0x2A1A, 0x2A1B, 0x2A1C, 0x2A1D, 0x2A1E, 0x2A1F, + 0x2A20, 0x2A21, 0x2A22, 0x2A23, 0x2A24, 0x2A25, 0x2A26, 0x2A27, 0x2A28, + 0x2A29, 0x2A2A, 0x2A2B, 0x2A2C, 0x2A2D, 0x2A2E, 0x2A2F, 0x2A30, 0x2A31, + 0x2A32, 0x2A33, 0x2A34, 0x2A35, 0x2A36, 0x2A37, 0x2A38, 0x2A39, 0x2A3A, + 0x2A3B, 0x2A3C, 0x2A3D, 0x2A3E, 0x2A3F, 0x2A40, 0x2A41, 0x2A42, 0x2A43, + 0x2A44, 0x2A45, 0x2A46, 0x2A47, 0x2A48, 0x2A49, 0x2A4A, 0x2A4B, 0x2A4C, + 0x2A4D, 0x2A4E, 0x2A4F, 0x2A50, 0x2A51, 0x2A52, 0x2A53, 0x2A54, 0x2A55, + 0x2A56, 0x2A57, 0x2A58, 0x2A59, 0x2A5A, 0x2A5B, 0x2A5C, 0x2A5D, 0x2A5E, + 0x2A5F, 0x2A60, 0x2A61, 0x2A62, 0x2A63, 0x2A64, 0x2A65, 0x2A66, 0x2A67, + 0x2A68, 0x2A69, 0x2A6A, 0x2A6B, 0x2A6C, 0x2A6D, 0x2A6E, 0x2A6F, 0x2A70, + 0x2A71, 0x2A72, 0x2A73, 0x2A74, 0x2A75, 0x2A76, 0x2A77, 0x2A78, 0x2A79, + 0x2A7A, 0x2A7B, 0x2A7C, 0x2A7D, 0x2A7E, 0x2A7F, 0x2A80, 0x2A81, 0x2A82, + 0x2A83, 0x2A84, 0x2A85, 0x2A86, 0x2A87, 0x2A88, 0x2A89, 0x2A8A, 0x2A8B, + 0x2A8C, 0x2A8D, 0x2A8E, 0x2A8F, 0x2A90, 0x2A91, 0x2A92, 0x2A93, 0x2A94, + 0x2A95, 0x2A96, 0x2A97, 0x2A98, 0x2A99, 0x2A9A, 0x2A9B, 0x2A9C, 0x2A9D, + 0x2A9E, 0x2A9F, 0x2AA0, 0x2AA1, 0x2AA2, 0x2AA3, 0x2AA4, 0x2AA5, 0x2AA6, + 0x2AA7, 0x2AA8, 0x2AA9, 0x2AAA, 0x2AAB, 0x2AAC, 0x2AAD, 0x2AAE, 0x2AAF, + 0x2AB0, 0x2AB1, 0x2AB2, 0x2AB3, 0x2AB4, 0x2AB5, 0x2AB6, 0x2AB7, 0x2AB8, + 0x2AB9, 0x2ABA, 0x2ABB, 0x2ABC, 0x2ABD, 0x2ABE, 0x2ABF, 0x2AC0, 0x2AC1, + 0x2AC2, 0x2AC3, 0x2AC4, 0x2AC5, 0x2AC6, 0x2AC7, 0x2AC8, 0x2AC9, 0x2ACA, + 0x2ACB, 0x2ACC, 0x2ACD, 0x2ACE, 0x2ACF, 0x2AD0, 0x2AD1, 0x2AD2, 0x2AD3, + 0x2AD4, 0x2AD5, 0x2AD6, 0x2AD7, 0x2AD8, 0x2AD9, 0x2ADA, 0x2ADB, 0x2ADC, + 0x2ADD, 0x2ADE, 0x2ADF, 0x2AE0, 0x2AE1, 0x2AE2, 0x2AE3, 0x2AE4, 0x2AE5, + 0x2AE6, 0x2AE7, 0x2AE8, 0x2AE9, 0x2AEA, 0x2AEB, 0x2AEC, 0x2AED, 0x2AEE, + 0x2AEF, 0x2AF0, 0x2AF1, 0x2AF2, 0x2AF3, 0x2AF4, 0x2AF5, 0x2AF6, 0x2AF7, + 0x2AF8, 0x2AF9, 0x2AFA, 0x2AFB, 0x2AFC, 0x2AFD, 0x2AFE, 0x2AFF, 0x2B00, + 0x2B01, 0x2B02, 0x2B03, 0x2B04, 0x2B05, 0x2B06, 0x2B07, 0x2B08, 0x2B09, + 0x2B0A, 0x2B0B, 0x2B0C, 0x2B0D, 0x2B0E, 0x2B0F, 0x2B10, 0x2B11, 0x2B12, + 0x2B13, 0x2B14, 0x2B15, 0x2B16, 0x2B17, 0x2B18, 0x2B19, 0x2B1A, 0x2B1B, + 0x2B1C, 0x2B1D, 0x2B1E, 0x2B1F, 0x2B20, 0x2B21, 0x2B22, 0x2B23, 0x2B24, + 0x2B25, 0x2B26, 0x2B27, 0x2B28, 0x2B29, 0x2B2A, 0x2B2B, 0x2B2C, 0x2B2D, + 0x2B2E, 0x2B2F, 0x2B30, 0x2B31, 0x2B32, 0x2B33, 0x2B34, 0x2B35, 0x2B36, + 0x2B37, 0x2B38, 0x2B39, 0x2B3A, 0x2B3B, 0x2B3C, 0x2B3D, 0x2B3E, 0x2B3F, + 0x2B40, 0x2B41, 0x2B42, 0x2B43, 0x2B44, 0x2B45, 0x2B46, 0x2B47, 0x2B48, + 0x2B49, 0x2B4A, 0x2B4B, 0x2B4C, 0x2B4D, 0x2B4E, 0x2B4F, 0x2B50, 0x2B51, + 0x2B52, 0x2B53, 0x2B54, 0x2B55, 0x2B56, 0x2B57, 0x2B58, 0x2B59, 0x2B5A, + 0x2B5B, 0x2B5C, 0x2B5D, 0x2B5E, 0x2B5F, 0x2B60, 0x2B61, 0x2B62, 0x2B63, + 0x2B64, 0x2B65, 0x2B66, 0x2B67, 0x2B68, 0x2B69, 0x2B6A, 0x2B6B, 0x2B6C, + 0x2B6D, 0x2B6E, 0x2B6F, 0x2B70, 0x2B71, 0x2B72, 0x2B73, 0x2B74, 0x2B75, + 0x2B76, 0x2B77, 0x2B78, 0x2B79, 0x2B7A, 0x2B7B, 0x2B7C, 0x2B7D, 0x2B7E, + 0x2B7F, 0x2B80, 0x2B81, 0x2B82, 0x2B83, 0x2B84, 0x2B85, 0x2B86, 0x2B87, + 0x2B88, 0x2B89, 0x2B8A, 0x2B8B, 0x2B8C, 0x2B8D, 0x2B8E, 0x2B8F, 0x2B90, + 0x2B91, 0x2B92, 0x2B93, 0x2B94, 0x2B95, 0x2B96, 0x2B97, 0x2B98, 0x2B99, + 0x2B9A, 0x2B9B, 0x2B9C, 0x2B9D, 0x2B9E, 0x2B9F, 0x2BA0, 0x2BA1, 0x2BA2, + 0x2BA3, 0x2BA4, 0x2BA5, 0x2BA6, 0x2BA7, 0x2BA8, 0x2BA9, 0x2BAA, 0x2BAB, + 0x2BAC, 0x2BAD, 0x2BAE, 0x2BAF, 0x2BB0, 0x2BB1, 0x2BB2, 0x2BB3, 0x2BB4, + 0x2BB5, 0x2BB6, 0x2BB7, 0x2BB8, 0x2BB9, 0x2BBA, 0x2BBB, 0x2BBC, 0x2BBD, + 0x2BBE, 0x2BBF, 0x2BC0, 0x2BC1, 0x2BC2, 0x2BC3, 0x2BC4, 0x2BC5, 0x2BC6, + 0x2BC7, 0x2BC8, 0x2BC9, 0x2BCA, 0x2BCB, 0x2BCC, 0x2BCD, 0x2BCE, 0x2BCF, + 0x2BD0, 0x2BD1, 0x2BD2, 0x2BD3, 0x2BD4, 0x2BD5, 0x2BD6, 0x2BD7, 0x2BD8, + 0x2BD9, 0x2BDA, 0x2BDB, 0x2BDC, 0x2BDD, 0x2BDE, 0x2BDF, 0x2BE0, 0x2BE1, + 0x2BE2, 0x2BE3, 0x2BE4, 0x2BE5, 0x2BE6, 0x2BE7, 0x2BE8, 0x2BE9, 0x2BEA, + 0x2BEB, 0x2BEC, 0x2BED, 0x2BEE, 0x2BEF, 0x2BF0, 0x2BF1, 0x2BF2, 0x2BF3, + 0x2BF4, 0x2BF5, 0x2BF6, 0x2BF7, 0x2BF8, 0x2BF9, 0x2BFA, 0x2BFB, 0x2BFC, + 0x2BFD, 0x2BFE, 0x2BFF, 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, 0x2C2F, 0x2C30, 0x2C31, 0x2C32, + 0x2C33, 0x2C34, 0x2C35, 0x2C36, 0x2C37, 0x2C38, 0x2C39, 0x2C3A, 0x2C3B, + 0x2C3C, 0x2C3D, 0x2C3E, 0x2C3F, 0x2C40, 0xFE50, 0x2C41, 0x2C42, 0xFE54, + 0x2C43, 0x2C44, 0x2C45, 0xFE57, 0x2C46, 0x2C47, 0xFE58, 0xFE5D, 0x2C48, + 0x2C49, 0x2C4A, 0x2C4B, 0x2C4C, 0x2C4D, 0x2C4E, 0x2C4F, 0x2C50, 0x2C51, + 0xFE5E, 0x2C52, 0x2C53, 0x2C54, 0x2C55, 0x2C56, 0x2C57, 0x2C58, 0x2C59, + 0x2C5A, 0x2C5B, 0x2C5C, 0x2C5D, 0x2C5E, 0x2C5F, 0x2C60, 0xFE6B, 0x2C61, + 0x2C62, 0xFE6E, 0x2C63, 0x2C64, 0x2C65, 0xFE71, 0x2C66, 0x2C67, 0x2C68, + 0x2C69, 0xFE73, 0x2C6A, 0x2C6B, 0xFE74, 0xFE75, 0x2C6C, 0x2C6D, 0x2C6E, + 0xFE79, 0x2C6F, 0x2C70, 0x2C71, 0x2C72, 0x2C73, 0x2C74, 0x2C75, 0x2C76, + 0x2C77, 0x2C78, 0x2C79, 0x2C7A, 0x2C7B, 0x2C7C, 0xFE84, 0x2C7D, 0x2C7E, + 0x2C7F, 0x2C80, 0x2C81, 0x2C82, 0x2C83, 0x2C84, 0x2C85, 0x2C86, 0x2C87, + 0x2C88, 0x2C89, 0x2C8A, 0x2C8B, 0x2C8C, 0x2C8D, 0x2C8E, 0x2C8F, 0x2C90, + 0x2C91, 0x2C92, 0x2C93, 0x2C94, 0x2C95, 0x2C96, 0x2C97, 0x2C98, 0x2C99, + 0x2C9A, 0x2C9B, 0x2C9C, 0x2C9D, 0x2C9E, 0x2C9F, 0x2CA0, 0x2CA1, 0x2CA2, + 0x2CA3, 0x2CA4, 0x2CA5, 0x2CA6, 0x2CA7, 0x2CA8, 0x2CA9, 0x2CAA, 0x2CAB, + 0x2CAC, 0x2CAD, 0x2CAE, 0x2CAF, 0x2CB0, 0x2CB1, 0x2CB2, 0x2CB3, 0x2CB4, + 0x2CB5, 0x2CB6, 0x2CB7, 0x2CB8, 0x2CB9, 0x2CBA, 0x2CBB, 0x2CBC, 0x2CBD, + 0x2CBE, 0x2CBF, 0x2CC0, 0x2CC1, 0x2CC2, 0x2CC3, 0x2CC4, 0x2CC5, 0x2CC6, + 0x2CC7, 0x2CC8, 0x2CC9, 0x2CCA, 0x2CCB, 0x2CCC, 0x2CCD, 0x2CCE, 0x2CCF, + 0x2CD0, 0x2CD1, 0x2CD2, 0x2CD3, 0x2CD4, 0x2CD5, 0x2CD6, 0x2CD7, 0x2CD8, + 0x2CD9, 0x2CDA, 0x2CDB, 0x2CDC, 0x2CDD, 0x2CDE, 0x2CDF, 0x2CE0, 0x2CE1, + 0x2CE2, 0x2CE3, 0x2CE4, 0x2CE5, 0x2CE6, 0x2CE7, 0x2CE8, 0x2CE9, 0x2CEA, + 0x2CEB, 0x2CEC, 0x2CED, 0x2CEE, 0x2CEF, 0x2CF0, 0x2CF1, 0x2CF2, 0x2CF3, + 0x2CF4, 0x2CF5, 0x2CF6, 0x2CF7, 0x2CF8, 0x2CF9, 0x2CFA, 0x2CFB, 0x2CFC, + 0x2CFD, 0x2CFE, 0x2CFF, 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, 0x2D26, 0x2D27, 0x2D28, 0x2D29, + 0x2D2A, 0x2D2B, 0x2D2C, 0x2D2D, 0x2D2E, 0x2D2F, 0x2D30, 0x2D31, 0x2D32, + 0x2D33, 0x2D34, 0x2D35, 0x2D36, 0x2D37, 0x2D38, 0x2D39, 0x2D3A, 0x2D3B, + 0x2D3C, 0x2D3D, 0x2D3E, 0x2D3F, 0x2D40, 0x2D41, 0x2D42, 0x2D43, 0x2D44, + 0x2D45, 0x2D46, 0x2D47, 0x2D48, 0x2D49, 0x2D4A, 0x2D4B, 0x2D4C, 0x2D4D, + 0x2D4E, 0x2D4F, 0x2D50, 0x2D51, 0x2D52, 0x2D53, 0x2D54, 0x2D55, 0x2D56, + 0x2D57, 0x2D58, 0x2D59, 0x2D5A, 0x2D5B, 0x2D5C, 0x2D5D, 0x2D5E, 0x2D5F, + 0x2D60, 0x2D61, 0x2D62, 0x2D63, 0x2D64, 0x2D65, 0x2D66, 0x2D67, 0x2D68, + 0x2D69, 0x2D6A, 0x2D6B, 0x2D6C, 0x2D6D, 0x2D6E, 0x2D6F, 0x2D70, 0x2D71, + 0x2D72, 0x2D73, 0x2D74, 0x2D75, 0x2D76, 0x2D77, 0x2D78, 0x2D79, 0x2D7A, + 0x2D7B, 0x2D7C, 0x2D7D, 0x2D7E, 0x2D7F, 0x2D80, 0x2D81, 0x2D82, 0x2D83, + 0x2D84, 0x2D85, 0x2D86, 0x2D87, 0x2D88, 0x2D89, 0x2D8A, 0x2D8B, 0x2D8C, + 0x2D8D, 0x2D8E, 0x2D8F, 0x2D90, 0x2D91, 0x2D92, 0x2D93, 0x2D94, 0x2D95, + 0x2D96, 0x2D97, 0x2D98, 0x2D99, 0x2D9A, 0x2D9B, 0x2D9C, 0x2D9D, 0x2D9E, + 0x2D9F, 0x2DA0, 0x2DA1, 0xA98A, 0xA98B, 0xA98C, 0xA98D, 0xA98E, 0xA98F, + 0xA990, 0xA991, 0xA992, 0xA993, 0xA994, 0xA995, 0x2DA2, 0x2DA3, 0x2DA4, + 0x2DA5, 0xA1A1, 0xA1A2, 0xA1A3, 0xA1A8, 0x2DA6, 0xA1A9, 0xA965, 0xA996, + 0xA1B4, 0xA1B5, 0xA1B6, 0xA1B7, 0xA1B8, 0xA1B9, 0xA1BA, 0xA1BB, 0xA1BE, + 0xA1BF, 0xA893, 0xA1FE, 0xA1B2, 0xA1B3, 0xA1BC, 0xA1BD, 0x2DA7, 0x2DA8, + 0x2DA9, 0x2DAA, 0x2DAB, 0xA894, 0xA895, 0x2DAC, 0x2DAD, 0xA940, 0xA941, + 0xA942, 0xA943, 0xA944, 0xA945, 0xA946, 0xA947, 0xA948, 0x2DAE, 0x2DAF, + 0x2DB0, 0x2DB1, 0x2DB2, 0x2DB3, 0x2DB4, 0x2DB5, 0x2DB6, 0x2DB7, 0x2DB8, + 0x2DB9, 0x2DBA, 0x2DBB, 0x2DBC, 0x2DBD, 0x2DBE, 0x2DBF, 0x2DC0, 0x2DC1, + 0xA989, 0x2DC2, 0x2DC3, 0xA4A1, 0xA4A2, 0xA4A3, 0xA4A4, 0xA4A5, 0xA4A6, + 0xA4A7, 0xA4A8, 0xA4A9, 0xA4AA, 0xA4AB, 0xA4AC, 0xA4AD, 0xA4AE, 0xA4AF, + 0xA4B0, 0xA4B1, 0xA4B2, 0xA4B3, 0xA4B4, 0xA4B5, 0xA4B6, 0xA4B7, 0xA4B8, + 0xA4B9, 0xA4BA, 0xA4BB, 0xA4BC, 0xA4BD, 0xA4BE, 0xA4BF, 0xA4C0, 0xA4C1, + 0xA4C2, 0xA4C3, 0xA4C4, 0xA4C5, 0xA4C6, 0xA4C7, 0xA4C8, 0xA4C9, 0xA4CA, + 0xA4CB, 0xA4CC, 0xA4CD, 0xA4CE, 0xA4CF, 0xA4D0, 0xA4D1, 0xA4D2, 0xA4D3, + 0xA4D4, 0xA4D5, 0xA4D6, 0xA4D7, 0xA4D8, 0xA4D9, 0xA4DA, 0xA4DB, 0xA4DC, + 0xA4DD, 0xA4DE, 0xA4DF, 0xA4E0, 0xA4E1, 0xA4E2, 0xA4E3, 0xA4E4, 0xA4E5, + 0xA4E6, 0xA4E7, 0xA4E8, 0xA4E9, 0xA4EA, 0xA4EB, 0xA4EC, 0xA4ED, 0xA4EE, + 0xA4EF, 0xA4F0, 0xA4F1, 0xA4F2, 0xA4F3, 0x2DC4, 0x2DC5, 0x2DC6, 0x2DC7, + 0x2DC8, 0x2DC9, 0x2DCA, 0xA961, 0xA962, 0xA966, 0xA967, 0x2DCB, 0x2DCC, + 0xA5A1, 0xA5A2, 0xA5A3, 0xA5A4, 0xA5A5, 0xA5A6, 0xA5A7, 0xA5A8, 0xA5A9, + 0xA5AA, 0xA5AB, 0xA5AC, 0xA5AD, 0xA5AE, 0xA5AF, 0xA5B0, 0xA5B1, 0xA5B2, + 0xA5B3, 0xA5B4, 0xA5B5, 0xA5B6, 0xA5B7, 0xA5B8, 0xA5B9, 0xA5BA, 0xA5BB, + 0xA5BC, 0xA5BD, 0xA5BE, 0xA5BF, 0xA5C0, 0xA5C1, 0xA5C2, 0xA5C3, 0xA5C4, + 0xA5C5, 0xA5C6, 0xA5C7, 0xA5C8, 0xA5C9, 0xA5CA, 0xA5CB, 0xA5CC, 0xA5CD, + 0xA5CE, 0xA5CF, 0xA5D0, 0xA5D1, 0xA5D2, 0xA5D3, 0xA5D4, 0xA5D5, 0xA5D6, + 0xA5D7, 0xA5D8, 0xA5D9, 0xA5DA, 0xA5DB, 0xA5DC, 0xA5DD, 0xA5DE, 0xA5DF, + 0xA5E0, 0xA5E1, 0xA5E2, 0xA5E3, 0xA5E4, 0xA5E5, 0xA5E6, 0xA5E7, 0xA5E8, + 0xA5E9, 0xA5EA, 0xA5EB, 0xA5EC, 0xA5ED, 0xA5EE, 0xA5EF, 0xA5F0, 0xA5F1, + 0xA5F2, 0xA5F3, 0xA5F4, 0xA5F5, 0xA5F6, 0x2DCD, 0x2DCE, 0x2DCF, 0x2DD0, + 0x2DD1, 0xA960, 0xA963, 0xA964, 0x2DD2, 0x2DD3, 0x2DD4, 0x2DD5, 0x2DD6, + 0x2DD7, 0xA8C5, 0xA8C6, 0xA8C7, 0xA8C8, 0xA8C9, 0xA8CA, 0xA8CB, 0xA8CC, + 0xA8CD, 0xA8CE, 0xA8CF, 0xA8D0, 0xA8D1, 0xA8D2, 0xA8D3, 0xA8D4, 0xA8D5, + 0xA8D6, 0xA8D7, 0xA8D8, 0xA8D9, 0xA8DA, 0xA8DB, 0xA8DC, 0xA8DD, 0xA8DE, + 0xA8DF, 0xA8E0, 0xA8E1, 0xA8E2, 0xA8E3, 0xA8E4, 0xA8E5, 0xA8E6, 0xA8E7, + 0xA8E8, 0xA8E9, 0x2DD8, 0x2DD9, 0x2DDA, 0x2DDB, 0x2DDC, 0x2DDD, 0x2DDE, + 0x2DDF, 0x2DE0, 0x2DE1, 0x2DE2, 0x2DE3, 0x2DE4, 0x2DE5, 0x2DE6, 0x2DE7, + 0x2DE8, 0x2DE9, 0x2DEA, 0x2DEB, 0x2DEC, 0x2DED, 0x2DEE, 0x2DEF, 0x2DF0, + 0x2DF1, 0x2DF2, 0x2DF3, 0x2DF4, 0x2DF5, 0x2DF6, 0x2DF7, 0x2DF8, 0x2DF9, + 0x2DFA, 0x2DFB, 0x2DFC, 0x2DFD, 0x2DFE, 0x2DFF, 0x2E00, 0x2E01, 0x2E02, + 0x2E03, 0x2E04, 0x2E05, 0x2E06, 0x2E07, 0x2E08, 0x2E09, 0x2E0A, 0x2E0B, + 0x2E0C, 0x2E0D, 0x2E0E, 0x2E0F, 0x2E10, 0x2E11, 0x2E12, 0x2E13, 0x2E14, + 0x2E15, 0x2E16, 0x2E17, 0x2E18, 0x2E19, 0x2E1A, 0x2E1B, 0x2E1C, 0x2E1D, + 0x2E1E, 0x2E1F, 0x2E20, 0x2E21, 0x2E22, 0x2E23, 0x2E24, 0x2E25, 0x2E26, + 0x2E27, 0x2E28, 0x2E29, 0x2E2A, 0x2E2B, 0x2E2C, 0x2E2D, 0x2E2E, 0x2E2F, + 0x2E30, 0x2E31, 0x2E32, 0x2E33, 0x2E34, 0x2E35, 0x2E36, 0x2E37, 0x2E38, + 0x2E39, 0x2E3A, 0x2E3B, 0x2E3C, 0x2E3D, 0x2E3E, 0x2E3F, 0x2E40, 0x2E41, + 0x2E42, 0x2E43, 0x2E44, 0x2E45, 0x2E46, 0x2E47, 0x2E48, 0x2E49, 0x2E4A, + 0x2E4B, 0x2E4C, 0x2E4D, 0x2E4E, 0x2E4F, 0x2E50, 0x2E51, 0x2E52, 0x2E53, + 0x2E54, 0x2E55, 0x2E56, 0x2E57, 0x2E58, 0x2E59, 0x2E5A, 0x2E5B, 0x2E5C, + 0x2E5D, 0x2E5E, 0x2E5F, 0x2E60, 0x2E61, 0x2E62, 0x2E63, 0x2E64, 0x2E65, + 0x2E66, 0x2E67, 0x2E68, 0x2E69, 0x2E6A, 0x2E6B, 0x2E6C, 0x2E6D, 0x2E6E, + 0x2E6F, 0x2E70, 0x2E71, 0x2E72, 0x2E73, 0x2E74, 0x2E75, 0x2E76, 0x2E77, + 0x2E78, 0x2E79, 0x2E7A, 0x2E7B, 0x2E7C, 0x2E7D, 0x2E7E, 0x2E7F, 0x2E80, + 0x2E81, 0x2E82, 0x2E83, 0x2E84, 0x2E85, 0x2E86, 0x2E87, 0x2E88, 0x2E89, + 0x2E8A, 0x2E8B, 0x2E8C, 0x2E8D, 0x2E8E, 0x2E8F, 0x2E90, 0x2E91, 0x2E92, + 0x2E93, 0x2E94, 0x2E95, 0x2E96, 0x2E97, 0x2E98, 0x2E99, 0x2E9A, 0x2E9B, + 0x2E9C, 0x2E9D, 0x2E9E, 0x2E9F, 0x2EA0, 0x2EA1, 0x2EA2, 0x2EA3, 0x2EA4, + 0x2EA5, 0x2EA6, 0x2EA7, 0x2EA8, 0x2EA9, 0x2EAA, 0x2EAB, 0x2EAC, 0x2EAD, + 0x2EAE, 0x2EAF, 0x2EB0, 0x2EB1, 0x2EB2, 0x2EB3, 0x2EB4, 0x2EB5, 0x2EB6, + 0x2EB7, 0x2EB8, 0x2EB9, 0x2EBA, 0x2EBB, 0x2EBC, 0x2EBD, 0x2EBE, 0x2EBF, + 0x2EC0, 0x2EC1, 0x2EC2, 0x2EC3, 0x2EC4, 0x2EC5, 0x2EC6, 0x2EC7, 0x2EC8, + 0x2EC9, 0x2ECA, 0x2ECB, 0x2ECC, 0x2ECD, 0xA2E5, 0xA2E6, 0xA2E7, 0xA2E8, + 0xA2E9, 0xA2EA, 0xA2EB, 0xA2EC, 0xA2ED, 0xA2EE, 0x2ECE, 0x2ECF, 0x2ED0, + 0x2ED1, 0x2ED2, 0x2ED3, 0x2ED4, 0xA95A, 0x2ED5, 0x2ED6, 0x2ED7, 0x2ED8, + 0x2ED9, 0x2EDA, 0x2EDB, 0x2EDC, 0x2EDD, 0x2EDE, 0x2EDF, 0x2EE0, 0x2EE1, + 0x2EE2, 0x2EE3, 0x2EE4, 0x2EE5, 0x2EE6, 0x2EE7, 0x2EE8, 0x2EE9, 0x2EEA, + 0x2EEB, 0x2EEC, 0x2EED, 0x2EEE, 0x2EEF, 0x2EF0, 0x2EF1, 0x2EF2, 0x2EF3, + 0x2EF4, 0x2EF5, 0x2EF6, 0x2EF7, 0x2EF8, 0x2EF9, 0x2EFA, 0x2EFB, 0x2EFC, + 0x2EFD, 0x2EFE, 0x2EFF, 0x2F00, 0x2F01, 0x2F02, 0x2F03, 0x2F04, 0x2F05, + 0x2F06, 0x2F07, 0x2F08, 0x2F09, 0x2F0A, 0x2F0B, 0x2F0C, 0x2F0D, 0x2F0E, + 0x2F0F, 0x2F10, 0x2F11, 0x2F12, 0x2F13, 0x2F14, 0x2F15, 0x2F16, 0x2F17, + 0x2F18, 0x2F19, 0x2F1A, 0x2F1B, 0x2F1C, 0x2F1D, 0x2F1E, 0x2F1F, 0x2F20, + 0x2F21, 0x2F22, 0x2F23, 0x2F24, 0x2F25, 0x2F26, 0x2F27, 0x2F28, 0x2F29, + 0x2F2A, 0x2F2B, 0x2F2C, 0x2F2D, 0x2F2E, 0x2F2F, 0x2F30, 0x2F31, 0x2F32, + 0x2F33, 0x2F34, 0x2F35, 0x2F36, 0x2F37, 0x2F38, 0x2F39, 0x2F3A, 0x2F3B, + 0x2F3C, 0x2F3D, 0x2F3E, 0x2F3F, 0x2F40, 0x2F41, 0x2F42, 0x2F43, 0x2F44, + 0x2F45, 0xA949, 0x2F46, 0x2F47, 0x2F48, 0x2F49, 0x2F4A, 0x2F4B, 0x2F4C, + 0x2F4D, 0x2F4E, 0x2F4F, 0x2F50, 0x2F51, 0x2F52, 0x2F53, 0x2F54, 0x2F55, + 0x2F56, 0x2F57, 0x2F58, 0x2F59, 0x2F5A, 0x2F5B, 0x2F5C, 0x2F5D, 0x2F5E, + 0x2F5F, 0x2F60, 0x2F61, 0x2F62, 0x2F63, 0x2F64, 0x2F65, 0x2F66, 0x2F67, + 0x2F68, 0x2F69, 0x2F6A, 0x2F6B, 0x2F6C, 0x2F6D, 0x2F6E, 0x2F6F, 0x2F70, + 0x2F71, 0x2F72, 0x2F73, 0x2F74, 0x2F75, 0x2F76, 0x2F77, 0x2F78, 0x2F79, + 0x2F7A, 0x2F7B, 0x2F7C, 0x2F7D, 0x2F7E, 0x2F7F, 0x2F80, 0x2F81, 0x2F82, + 0x2F83, 0x2F84, 0x2F85, 0x2F86, 0x2F87, 0x2F88, 0x2F89, 0x2F8A, 0x2F8B, + 0x2F8C, 0x2F8D, 0x2F8E, 0x2F8F, 0x2F90, 0x2F91, 0x2F92, 0x2F93, 0x2F94, + 0x2F95, 0x2F96, 0x2F97, 0x2F98, 0x2F99, 0x2F9A, 0x2F9B, 0x2F9C, 0x2F9D, + 0x2F9E, 0x2F9F, 0x2FA0, 0x2FA1, 0x2FA2, 0x2FA3, 0x2FA4, 0x2FA5, 0x2FA6, + 0x2FA7, 0x2FA8, 0x2FA9, 0x2FAA, 0x2FAB, 0x2FAC, 0x2FAD, 0x2FAE, 0x2FAF, + 0x2FB0, 0x2FB1, 0x2FB2, 0x2FB3, 0x2FB4, 0x2FB5, 0x2FB6, 0x2FB7, 0x2FB8, + 0x2FB9, 0x2FBA, 0x2FBB, 0x2FBC, 0x2FBD, 0x2FBE, 0x2FBF, 0x2FC0, 0x2FC1, + 0x2FC2, 0x2FC3, 0x2FC4, 0x2FC5, 0x2FC6, 0x2FC7, 0x2FC8, 0x2FC9, 0x2FCA, + 0x2FCB, 0x2FCC, 0x2FCD, 0x2FCE, 0x2FCF, 0x2FD0, 0x2FD1, 0x2FD2, 0x2FD3, + 0x2FD4, 0x2FD5, 0x2FD6, 0x2FD7, 0x2FD8, 0x2FD9, 0x2FDA, 0x2FDB, 0x2FDC, + 0x2FDD, 0x2FDE, 0x2FDF, 0x2FE0, 0x2FE1, 0x2FE2, 0x2FE3, 0x2FE4, 0x2FE5, + 0x2FE6, 0x2FE7, 0x2FE8, 0x2FE9, 0x2FEA, 0x2FEB, 0x2FEC, 0x2FED, 0x2FEE, + 0x2FEF, 0x2FF0, 0x2FF1, 0x2FF2, 0x2FF3, 0x2FF4, 0x2FF5, 0x2FF6, 0x2FF7, + 0x2FF8, 0x2FF9, 0x2FFA, 0x2FFB, 0x2FFC, 0x2FFD, 0x2FFE, 0x2FFF, 0x3000, + 0x3001, 0x3002, 0x3003, 0x3004, 0x3005, 0x3006, 0x3007, 0x3008, 0x3009, + 0x300A, 0x300B, 0x300C, 0x300D, 0x300E, 0x300F, 0x3010, 0x3011, 0x3012, + 0x3013, 0x3014, 0x3015, 0x3016, 0x3017, 0x3018, 0x3019, 0x301A, 0x301B, + 0x301C, 0x301D, 0x301E, 0x301F, 0x3020, 0x3021, 0x3022, 0x3023, 0x3024, + 0x3025, 0x3026, 0x3027, 0x3028, 0x3029, 0x302A, 0x302B, 0x302C, 0x302D, + 0x302E, 0x302F, 0xA94A, 0xA94B, 0x3030, 0x3031, 0x3032, 0x3033, 0x3034, + 0x3035, 0x3036, 0x3037, 0x3038, 0x3039, 0x303A, 0x303B, 0xA94C, 0xA94D, + 0xA94E, 0x303C, 0x303D, 0xA94F, 0x303E, 0x303F, 0x3040, 0x3041, 0x3042, + 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049, 0x304A, 0x304B, + 0x304C, 0x304D, 0x304E, 0x304F, 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, + 0x3055, 0x3056, 0x3057, 0x3058, 0x3059, 0x305A, 0x305B, 0x305C, 0x305D, + 0x305E, 0x305F, 0xA950, 0x3060, 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, + 0x3066, 0x3067, 0x3068, 0xA951, 0x3069, 0x306A, 0xA952, 0xA953, 0x306B, + 0x306C, 0xA954, 0x306D, 0x306E, 0x306F, 0x3070, 0x3071, 0x3072, 0x3073, + 0x3074, 0x3075, 0x3076, 0x3077, 0x3078, 0x3079, 0x307A, 0x307B, 0x307C, + 0x307D, 0x307E, 0x307F, 0x3080, 0x3081, 0x3082, 0x3083, 0x3084, 0x3085, + 0x3086, 0x3087, 0x3088, 0x3089, 0x308A, 0x308B, 0x308C, 0x308D, 0x308E, + 0x308F, 0x3090, 0x3091, 0x3092, 0x3093, 0x3094, 0x3095, 0x3096, 0x3097, + 0x3098, 0x3099, 0x309A, 0x309B, 0x309C, 0x309D, 0x309E, 0x309F, 0x30A0, + 0x30A1, 0x30A2, 0x30A3, 0x30A4, 0x30A5, 0x30A6, 0x30A7, 0x30A8, 0x30A9, + 0x30AA, 0x30AB, 0x30AC, 0x30AD, 0x30AE, 0x30AF, 0x30B0, 0x30B1, 0x30B2, + 0x30B3, 0x30B4, 0x30B5, 0x30B6, 0x30B7, 0x30B8, 0x30B9, 0x30BA, 0x30BB, + 0x30BC, 0x30BD, 0x30BE, 0x30BF, 0x30C0, 0x30C1, 0x30C2, 0x30C3, 0x30C4, + 0x30C5, 0x30C6, 0x30C7, 0x30C8, 0x30C9, 0x30CA, 0x30CB, 0x30CC, 0x30CD, + 0x30CE, 0x30CF, 0x30D0, 0x30D1, 0x30D2, 0x30D3, 0x30D4, 0x30D5, 0x30D6, + 0x30D7, 0x30D8, 0x30D9, 0x30DA, 0x30DB, 0x30DC, 0x30DD, 0xFE56, 0x30DE, + 0x30DF, 0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7, + 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x30EF, 0x30F0, + 0x30F1, 0x30F2, 0x30F3, 0x30F4, 0x30F5, 0x30F6, 0x30F7, 0x30F8, 0x30F9, + 0x30FA, 0x30FB, 0x30FC, 0x30FD, 0x30FE, 0x30FF, 0x3100, 0x3101, 0x3102, + 0x3103, 0x3104, 0x3105, 0x3106, 0x3107, 0x3108, 0xFE55, 0x3109, 0x310A, + 0x310B, 0x310C, 0x310D, 0x310E, 0x310F, 0x3110, 0x3111, 0x3112, 0x3113, + 0x3114, 0x3115, 0x3116, 0x3117, 0x3118, 0x3119, 0x311A, 0x311B, 0x311C, + 0x311D, 0x311E, 0x311F, 0x3120, 0x3121, 0x3122, 0x3123, 0x3124, 0x3125, + 0x3126, 0x3127, 0x3128, 0x3129, 0x312A, 0x312B, 0x312C, 0x312D, 0x312E, + 0x312F, 0x3130, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137, + 0x3138, 0x3139, 0x313A, 0x313B, 0x313C, 0x313D, 0x313E, 0x313F, 0x3140, + 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147, 0x3148, 0x3149, + 0x314A, 0x314B, 0x314C, 0x314D, 0x314E, 0x314F, 0x3150, 0x3151, 0x3152, + 0x3153, 0x3154, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315A, 0x315B, + 0x315C, 0x315D, 0x315E, 0x315F, 0x3160, 0x3161, 0x3162, 0x3163, 0x3164, + 0x3165, 0x3166, 0x3167, 0x3168, 0x3169, 0x316A, 0x316B, 0x316C, 0x316D, + 0x316E, 0x316F, 0x3170, 0x3171, 0x3172, 0x3173, 0x3174, 0x3175, 0x3176, + 0x3177, 0x3178, 0x3179, 0x317A, 0x317B, 0x317C, 0x317D, 0x317E, 0x317F, + 0x3180, 0x3181, 0x3182, 0x3183, 0x3184, 0x3185, 0x3186, 0x3187, 0x3188, + 0x3189, 0x318A, 0x318B, 0x318C, 0x318D, 0x318E, 0x318F, 0x3190, 0x3191, + 0x3192, 0x3193, 0x3194, 0x3195, 0x3196, 0x3197, 0x3198, 0x3199, 0x319A, + 0x319B, 0x319C, 0x319D, 0x319E, 0x319F, 0x31A0, 0x31A1, 0x31A2, 0x31A3, + 0x31A4, 0x31A5, 0x31A6, 0x31A7, 0x31A8, 0x31A9, 0x31AA, 0x31AB, 0x31AC, + 0x31AD, 0x31AE, 0x31AF, 0x31B0, 0x31B1, 0x31B2, 0x31B3, 0x31B4, 0x31B5, + 0x31B6, 0x31B7, 0x31B8, 0x31B9, 0x31BA, 0x31BB, 0x31BC, 0x31BD, 0x31BE, + 0x31BF, 0x31C0, 0x31C1, 0x31C2, 0x31C3, 0x31C4, 0x31C5, 0x31C6, 0x31C7, + 0x31C8, 0x31C9, 0x31CA, 0x31CB, 0x31CC, 0x31CD, 0x31CE, 0x31CF, 0x31D0, + 0x31D1, 0x31D2, 0x31D3, 0x31D4, 0x31D5, 0x31D6, 0x31D7, 0x31D8, 0x31D9, + 0x31DA, 0x31DB, 0x31DC, 0x31DD, 0x31DE, 0x31DF, 0x31E0, 0x31E1, 0x31E2, + 0x31E3, 0x31E4, 0x31E5, 0x31E6, 0x31E7, 0x31E8, 0x31E9, 0x31EA, 0x31EB, + 0x31EC, 0x31ED, 0x31EE, 0x31EF, 0x31F0, 0x31F1, 0x31F2, 0x31F3, 0x31F4, + 0x31F5, 0x31F6, 0x31F7, 0x31F8, 0x31F9, 0x31FA, 0x31FB, 0x31FC, 0x31FD, + 0x31FE, 0x31FF, 0x3200, 0x3201, 0x3202, 0x3203, 0x3204, 0x3205, 0x3206, + 0x3207, 0x3208, 0x3209, 0x320A, 0x320B, 0x320C, 0x320D, 0x320E, 0x320F, + 0x3210, 0x3211, 0x3212, 0x3213, 0x3214, 0x3215, 0x3216, 0x3217, 0x3218, + 0x3219, 0x321A, 0x321B, 0x321C, 0x321D, 0x321E, 0x321F, 0x3220, 0x3221, + 0x3222, 0x3223, 0x3224, 0x3225, 0x3226, 0x3227, 0x3228, 0x3229, 0x322A, + 0x322B, 0x322C, 0x322D, 0x322E, 0x322F, 0x3230, 0x3231, 0x3232, 0xFE5A, + 0x3233, 0x3234, 0x3235, 0x3236, 0x3237, 0x3238, 0x3239, 0x323A, 0x323B, + 0x323C, 0x323D, 0x323E, 0x323F, 0x3240, 0x3241, 0x3242, 0x3243, 0x3244, + 0x3245, 0x3246, 0x3247, 0x3248, 0x3249, 0x324A, 0x324B, 0x324C, 0x324D, + 0x324E, 0x324F, 0x3250, 0x3251, 0x3252, 0x3253, 0x3254, 0x3255, 0x3256, + 0x3257, 0x3258, 0x3259, 0x325A, 0x325B, 0x325C, 0x325D, 0x325E, 0x325F, + 0x3260, 0x3261, 0x3262, 0x3263, 0x3264, 0x3265, 0x3266, 0x3267, 0x3268, + 0x3269, 0x326A, 0x326B, 0x326C, 0x326D, 0x326E, 0x326F, 0x3270, 0x3271, + 0x3272, 0x3273, 0x3274, 0x3275, 0x3276, 0x3277, 0x3278, 0x3279, 0x327A, + 0x327B, 0x327C, 0x327D, 0x327E, 0x327F, 0x3280, 0x3281, 0x3282, 0x3283, + 0x3284, 0x3285, 0x3286, 0x3287, 0x3288, 0x3289, 0x328A, 0x328B, 0x328C, + 0x328D, 0x328E, 0x328F, 0x3290, 0x3291, 0x3292, 0x3293, 0x3294, 0x3295, + 0x3296, 0x3297, 0x3298, 0x3299, 0x329A, 0x329B, 0x329C, 0x329D, 0x329E, + 0x329F, 0x32A0, 0x32A1, 0xFE5C, 0x32A2, 0x32A3, 0x32A4, 0x32A5, 0x32A6, + 0x32A7, 0x32A8, 0x32A9, 0x32AA, 0x32AB, 0x32AC, 0xFE5B, 0x32AD, 0x32AE, + 0x32AF, 0x32B0, 0x32B1, 0x32B2, 0x32B3, 0x32B4, 0x32B5, 0x32B6, 0x32B7, + 0x32B8, 0x32B9, 0x32BA, 0x32BB, 0x32BC, 0x32BD, 0x32BE, 0x32BF, 0x32C0, + 0x32C1, 0x32C2, 0x32C3, 0x32C4, 0x32C5, 0x32C6, 0x32C7, 0x32C8, 0x32C9, + 0x32CA, 0x32CB, 0x32CC, 0x32CD, 0x32CE, 0x32CF, 0x32D0, 0x32D1, 0x32D2, + 0x32D3, 0x32D4, 0x32D5, 0x32D6, 0x32D7, 0x32D8, 0x32D9, 0x32DA, 0x32DB, + 0x32DC, 0x32DD, 0x32DE, 0x32DF, 0x32E0, 0x32E1, 0x32E2, 0x32E3, 0x32E4, + 0x32E5, 0x32E6, 0x32E7, 0x32E8, 0x32E9, 0x32EA, 0x32EB, 0x32EC, 0x32ED, + 0x32EE, 0x32EF, 0x32F0, 0x32F1, 0x32F2, 0x32F3, 0x32F4, 0x32F5, 0x32F6, + 0x32F7, 0x32F8, 0x32F9, 0x32FA, 0x32FB, 0x32FC, 0x32FD, 0x32FE, 0x32FF, + 0x3300, 0x3301, 0x3302, 0x3303, 0x3304, 0x3305, 0x3306, 0x3307, 0x3308, + 0x3309, 0x330A, 0x330B, 0x330C, 0x330D, 0x330E, 0x330F, 0x3310, 0x3311, + 0x3312, 0x3313, 0x3314, 0x3315, 0x3316, 0x3317, 0x3318, 0x3319, 0x331A, + 0x331B, 0x331C, 0x331D, 0x331E, 0x331F, 0x3320, 0x3321, 0x3322, 0x3323, + 0x3324, 0x3325, 0x3326, 0x3327, 0x3328, 0x3329, 0x332A, 0x332B, 0x332C, + 0x332D, 0x332E, 0x332F, 0x3330, 0x3331, 0x3332, 0x3333, 0x3334, 0x3335, + 0x3336, 0x3337, 0x3338, 0x3339, 0x333A, 0x333B, 0x333C, 0x333D, 0x333E, + 0x333F, 0x3340, 0x3341, 0x3342, 0x3343, 0x3344, 0x3345, 0x3346, 0x3347, + 0x3348, 0x3349, 0x334A, 0x334B, 0x334C, 0x334D, 0x334E, 0x334F, 0x3350, + 0x3351, 0x3352, 0x3353, 0x3354, 0x3355, 0x3356, 0x3357, 0x3358, 0x3359, + 0x335A, 0x335B, 0x335C, 0x335D, 0x335E, 0x335F, 0x3360, 0x3361, 0x3362, + 0x3363, 0x3364, 0x3365, 0x3366, 0x3367, 0x3368, 0x3369, 0x336A, 0x336B, + 0x336C, 0x336D, 0x336E, 0x336F, 0x3370, 0x3371, 0x3372, 0x3373, 0x3374, + 0x3375, 0x3376, 0x3377, 0x3378, 0x3379, 0x337A, 0x337B, 0x337C, 0x337D, + 0x337E, 0x337F, 0x3380, 0x3381, 0x3382, 0x3383, 0x3384, 0x3385, 0x3386, + 0x3387, 0x3388, 0x3389, 0x338A, 0x338B, 0x338C, 0x338D, 0x338E, 0x338F, + 0x3390, 0x3391, 0x3392, 0x3393, 0x3394, 0x3395, 0x3396, 0x3397, 0x3398, + 0x3399, 0x339A, 0x339B, 0x339C, 0x339D, 0x339E, 0x339F, 0x33A0, 0x33A1, + 0x33A2, 0x33A3, 0x33A4, 0x33A5, 0x33A6, 0x33A7, 0x33A8, 0x33A9, 0x33AA, + 0x33AB, 0x33AC, 0x33AD, 0x33AE, 0x33AF, 0x33B0, 0x33B1, 0x33B2, 0x33B3, + 0x33B4, 0x33B5, 0x33B6, 0x33B7, 0x33B8, 0x33B9, 0x33BA, 0x33BB, 0x33BC, + 0x33BD, 0x33BE, 0x33BF, 0x33C0, 0x33C1, 0x33C2, 0x33C3, 0x33C4, 0x33C5, + 0x33C6, 0x33C7, 0x33C8, 0x33C9, 0x33CA, 0x33CB, 0x33CC, 0x33CD, 0x33CE, + 0x33CF, 0x33D0, 0x33D1, 0x33D2, 0x33D3, 0x33D4, 0x33D5, 0x33D6, 0x33D7, + 0x33D8, 0x33D9, 0x33DA, 0x33DB, 0x33DC, 0x33DD, 0x33DE, 0x33DF, 0x33E0, + 0x33E1, 0x33E2, 0x33E3, 0x33E4, 0x33E5, 0x33E6, 0x33E7, 0x33E8, 0x33E9, + 0x33EA, 0x33EB, 0x33EC, 0x33ED, 0x33EE, 0x33EF, 0x33F0, 0x33F1, 0x33F2, + 0x33F3, 0x33F4, 0x33F5, 0x33F6, 0x33F7, 0x33F8, 0x33F9, 0x33FA, 0x33FB, + 0x33FC, 0x33FD, 0x33FE, 0x33FF, 0x3400, 0x3401, 0x3402, 0x3403, 0x3404, + 0x3405, 0x3406, 0x3407, 0x3408, 0x3409, 0x340A, 0x340B, 0x340C, 0x340D, + 0x340E, 0x340F, 0x3410, 0x3411, 0x3412, 0x3413, 0x3414, 0x3415, 0x3416, + 0x3417, 0x3418, 0x3419, 0x341A, 0x341B, 0x341C, 0x341D, 0x341E, 0x341F, + 0x3420, 0x3421, 0x3422, 0x3423, 0x3424, 0x3425, 0x3426, 0x3427, 0x3428, + 0x3429, 0x342A, 0x342B, 0x342C, 0x342D, 0x342E, 0x342F, 0x3430, 0x3431, + 0x3432, 0x3433, 0x3434, 0x3435, 0x3436, 0x3437, 0x3438, 0x3439, 0x343A, + 0x343B, 0x343C, 0x343D, 0x343E, 0x343F, 0x3440, 0x3441, 0x3442, 0x3443, + 0x3444, 0x3445, 0x3446, 0x3447, 0x3448, 0x3449, 0x344A, 0x344B, 0x344C, + 0x344D, 0x344E, 0x344F, 0x3450, 0x3451, 0x3452, 0x3453, 0x3454, 0x3455, + 0x3456, 0x3457, 0x3458, 0x3459, 0x345A, 0x345B, 0x345C, 0x345D, 0x345E, + 0x345F, 0x3460, 0x3461, 0x3462, 0x3463, 0x3464, 0x3465, 0x3466, 0x3467, + 0x3468, 0x3469, 0x346A, 0x346B, 0x346C, 0x346D, 0x346E, 0x346F, 0x3470, + 0x3471, 0x3472, 0x3473, 0x3474, 0x3475, 0x3476, 0x3477, 0x3478, 0x3479, + 0x347A, 0x347B, 0x347C, 0x347D, 0x347E, 0x347F, 0x3480, 0x3481, 0x3482, + 0x3483, 0x3484, 0x3485, 0x3486, 0x3487, 0x3488, 0x3489, 0x348A, 0x348B, + 0x348C, 0x348D, 0x348E, 0x348F, 0x3490, 0x3491, 0x3492, 0x3493, 0x3494, + 0x3495, 0x3496, 0x3497, 0x3498, 0x3499, 0x349A, 0x349B, 0x349C, 0x349D, + 0x349E, 0x349F, 0x34A0, 0x34A1, 0x34A2, 0x34A3, 0x34A4, 0x34A5, 0x34A6, + 0x34A7, 0x34A8, 0x34A9, 0x34AA, 0x34AB, 0x34AC, 0x34AD, 0x34AE, 0x34AF, + 0x34B0, 0x34B1, 0x34B2, 0x34B3, 0x34B4, 0x34B5, 0x34B6, 0x34B7, 0x34B8, + 0x34B9, 0x34BA, 0x34BB, 0x34BC, 0x34BD, 0x34BE, 0x34BF, 0x34C0, 0x34C1, + 0x34C2, 0x34C3, 0x34C4, 0x34C5, 0x34C6, 0x34C7, 0x34C8, 0x34C9, 0x34CA, + 0x34CB, 0x34CC, 0x34CD, 0x34CE, 0x34CF, 0x34D0, 0x34D1, 0x34D2, 0x34D3, + 0x34D4, 0x34D5, 0x34D6, 0x34D7, 0x34D8, 0x34D9, 0x34DA, 0x34DB, 0x34DC, + 0x34DD, 0x34DE, 0x34DF, 0x34E0, 0x34E1, 0x34E2, 0x34E3, 0x34E4, 0x34E5, + 0x34E6, 0x34E7, 0x34E8, 0x34E9, 0x34EA, 0x34EB, 0x34EC, 0x34ED, 0x34EE, + 0x34EF, 0x34F0, 0x34F1, 0x34F2, 0x34F3, 0x34F4, 0x34F5, 0x34F6, 0x34F7, + 0x34F8, 0x34F9, 0x34FA, 0x34FB, 0x34FC, 0x34FD, 0x34FE, 0x34FF, 0x3500, + 0x3501, 0x3502, 0x3503, 0x3504, 0x3505, 0x3506, 0x3507, 0x3508, 0x3509, + 0x350A, 0x350B, 0x350C, 0x350D, 0x350E, 0x350F, 0x3510, 0x3511, 0x3512, + 0x3513, 0x3514, 0x3515, 0x3516, 0x3517, 0x3518, 0x3519, 0x351A, 0x351B, + 0x351C, 0x351D, 0x351E, 0x351F, 0x3520, 0x3521, 0x3522, 0x3523, 0x3524, + 0x3525, 0x3526, 0x3527, 0x3528, 0x3529, 0x352A, 0x352B, 0x352C, 0x352D, + 0x352E, 0x352F, 0x3530, 0x3531, 0x3532, 0x3533, 0x3534, 0x3535, 0x3536, + 0x3537, 0x3538, 0x3539, 0x353A, 0x353B, 0x353C, 0x353D, 0x353E, 0x353F, + 0x3540, 0x3541, 0x3542, 0x3543, 0x3544, 0x3545, 0x3546, 0x3547, 0x3548, + 0x3549, 0x354A, 0x354B, 0x354C, 0x354D, 0x354E, 0x354F, 0x3550, 0x3551, + 0x3552, 0x3553, 0x3554, 0x3555, 0x3556, 0x3557, 0x3558, 0x3559, 0x355A, + 0x355B, 0x355C, 0x355D, 0x355E, 0x355F, 0x3560, 0x3561, 0x3562, 0x3563, + 0x3564, 0x3565, 0x3566, 0x3567, 0x3568, 0x3569, 0x356A, 0x356B, 0x356C, + 0x356D, 0x356E, 0x356F, 0x3570, 0x3571, 0x3572, 0x3573, 0x3574, 0x3575, + 0x3576, 0x3577, 0x3578, 0x3579, 0x357A, 0x357B, 0x357C, 0x357D, 0x357E, + 0x357F, 0x3580, 0x3581, 0x3582, 0x3583, 0x3584, 0x3585, 0x3586, 0x3587, + 0x3588, 0x3589, 0x358A, 0x358B, 0x358C, 0x358D, 0x358E, 0x358F, 0x3590, + 0x3591, 0x3592, 0x3593, 0x3594, 0x3595, 0x3596, 0x3597, 0x3598, 0x3599, + 0x359A, 0x359B, 0x359C, 0x359D, 0x359E, 0x359F, 0x35A0, 0x35A1, 0x35A2, + 0x35A3, 0x35A4, 0x35A5, 0x35A6, 0x35A7, 0x35A8, 0x35A9, 0xFE60, 0x35AA, + 0x35AB, 0x35AC, 0x35AD, 0x35AE, 0x35AF, 0x35B0, 0x35B1, 0x35B2, 0x35B3, + 0x35B4, 0x35B5, 0x35B6, 0x35B7, 0x35B8, 0x35B9, 0x35BA, 0x35BB, 0x35BC, + 0x35BD, 0x35BE, 0x35BF, 0x35C0, 0x35C1, 0x35C2, 0x35C3, 0x35C4, 0x35C5, + 0x35C6, 0x35C7, 0x35C8, 0x35C9, 0x35CA, 0x35CB, 0x35CC, 0x35CD, 0x35CE, + 0x35CF, 0x35D0, 0x35D1, 0x35D2, 0x35D3, 0x35D4, 0x35D5, 0x35D6, 0x35D7, + 0x35D8, 0x35D9, 0x35DA, 0x35DB, 0x35DC, 0x35DD, 0x35DE, 0x35DF, 0x35E0, + 0x35E1, 0x35E2, 0x35E3, 0x35E4, 0x35E5, 0x35E6, 0x35E7, 0x35E8, 0x35E9, + 0x35EA, 0x35EB, 0x35EC, 0x35ED, 0x35EE, 0x35EF, 0x35F0, 0x35F1, 0x35F2, + 0x35F3, 0x35F4, 0x35F5, 0x35F6, 0x35F7, 0x35F8, 0x35F9, 0x35FA, 0x35FB, + 0x35FC, 0x35FD, 0x35FE, 0xFE5F, 0x35FF, 0x3600, 0x3601, 0x3602, 0x3603, + 0x3604, 0x3605, 0x3606, 0x3607, 0x3608, 0x3609, 0x360A, 0x360B, 0x360C, + 0x360D, 0x360E, 0x360F, 0x3610, 0x3611, 0x3612, 0x3613, 0x3614, 0x3615, + 0x3616, 0x3617, 0x3618, 0x3619, 0x361A, 0x361B, 0x361C, 0x361D, 0x361E, + 0x361F, 0x3620, 0x3621, 0x3622, 0x3623, 0x3624, 0x3625, 0x3626, 0x3627, + 0x3628, 0x3629, 0x362A, 0x362B, 0x362C, 0x362D, 0x362E, 0x362F, 0x3630, + 0x3631, 0x3632, 0x3633, 0x3634, 0x3635, 0x3636, 0x3637, 0x3638, 0x3639, + 0x363A, 0x363B, 0x363C, 0x363D, 0x363E, 0x363F, 0x3640, 0x3641, 0x3642, + 0x3643, 0x3644, 0x3645, 0x3646, 0x3647, 0x3648, 0x3649, 0x364A, 0x364B, + 0x364C, 0x364D, 0x364E, 0x364F, 0x3650, 0x3651, 0x3652, 0x3653, 0x3654, + 0x3655, 0x3656, 0x3657, 0x3658, 0x3659, 0x365A, 0x365B, 0x365C, 0x365D, + 0x365E, 0xFE62, 0xFE65, 0x365F, 0x3660, 0x3661, 0x3662, 0x3663, 0x3664, + 0x3665, 0x3666, 0x3667, 0x3668, 0x3669, 0x366A, 0x366B, 0x366C, 0xFE63, + 0x366D, 0x366E, 0x366F, 0x3670, 0x3671, 0x3672, 0x3673, 0x3674, 0x3675, + 0x3676, 0x3677, 0x3678, 0x3679, 0x367A, 0x367B, 0x367C, 0x367D, 0x367E, + 0x367F, 0x3680, 0x3681, 0x3682, 0x3683, 0x3684, 0x3685, 0x3686, 0x3687, + 0x3688, 0x3689, 0x368A, 0x368B, 0x368C, 0x368D, 0x368E, 0x368F, 0x3690, + 0x3691, 0x3692, 0x3693, 0x3694, 0x3695, 0x3696, 0x3697, 0x3698, 0x3699, + 0x369A, 0x369B, 0x369C, 0x369D, 0x369E, 0x369F, 0x36A0, 0x36A1, 0x36A2, + 0x36A3, 0x36A4, 0x36A5, 0x36A6, 0x36A7, 0x36A8, 0x36A9, 0x36AA, 0x36AB, + 0x36AC, 0x36AD, 0x36AE, 0x36AF, 0x36B0, 0x36B1, 0x36B2, 0x36B3, 0x36B4, + 0x36B5, 0x36B6, 0x36B7, 0x36B8, 0x36B9, 0x36BA, 0x36BB, 0x36BC, 0x36BD, + 0x36BE, 0x36BF, 0x36C0, 0x36C1, 0x36C2, 0x36C3, 0x36C4, 0x36C5, 0x36C6, + 0x36C7, 0x36C8, 0x36C9, 0x36CA, 0x36CB, 0x36CC, 0x36CD, 0x36CE, 0x36CF, + 0x36D0, 0x36D1, 0x36D2, 0x36D3, 0x36D4, 0x36D5, 0x36D6, 0x36D7, 0x36D8, + 0x36D9, 0x36DA, 0x36DB, 0x36DC, 0x36DD, 0x36DE, 0x36DF, 0x36E0, 0x36E1, + 0x36E2, 0x36E3, 0x36E4, 0x36E5, 0x36E6, 0x36E7, 0x36E8, 0x36E9, 0x36EA, + 0x36EB, 0x36EC, 0x36ED, 0x36EE, 0x36EF, 0x36F0, 0x36F1, 0x36F2, 0x36F3, + 0x36F4, 0x36F5, 0x36F6, 0x36F7, 0x36F8, 0x36F9, 0x36FA, 0x36FB, 0x36FC, + 0x36FD, 0x36FE, 0x36FF, 0xFE64, 0x3700, 0x3701, 0x3702, 0x3703, 0x3704, + 0x3705, 0x3706, 0x3707, 0x3708, 0x3709, 0x370A, 0x370B, 0x370C, 0x370D, + 0x370E, 0x370F, 0x3710, 0x3711, 0x3712, 0x3713, 0x3714, 0x3715, 0x3716, + 0x3717, 0x3718, 0x3719, 0x371A, 0x371B, 0x371C, 0x371D, 0x371E, 0x371F, + 0x3720, 0x3721, 0x3722, 0x3723, 0x3724, 0x3725, 0x3726, 0x3727, 0x3728, + 0x3729, 0x372A, 0x372B, 0x372C, 0x372D, 0x372E, 0x372F, 0x3730, 0x3731, + 0x3732, 0x3733, 0x3734, 0x3735, 0x3736, 0x3737, 0x3738, 0x3739, 0x373A, + 0x373B, 0x373C, 0x373D, 0x373E, 0x373F, 0x3740, 0x3741, 0x3742, 0x3743, + 0x3744, 0x3745, 0x3746, 0x3747, 0x3748, 0x3749, 0x374A, 0x374B, 0x374C, + 0x374D, 0x374E, 0x374F, 0x3750, 0x3751, 0x3752, 0x3753, 0x3754, 0x3755, + 0x3756, 0x3757, 0x3758, 0x3759, 0x375A, 0x375B, 0x375C, 0x375D, 0x375E, + 0x375F, 0x3760, 0x3761, 0x3762, 0x3763, 0x3764, 0x3765, 0x3766, 0x3767, + 0x3768, 0x3769, 0x376A, 0x376B, 0x376C, 0x376D, 0x376E, 0x376F, 0x3770, + 0x3771, 0x3772, 0x3773, 0x3774, 0x3775, 0x3776, 0x3777, 0x3778, 0x3779, + 0x377A, 0x377B, 0x377C, 0x377D, 0x377E, 0x377F, 0x3780, 0x3781, 0x3782, + 0x3783, 0x3784, 0x3785, 0x3786, 0x3787, 0x3788, 0x3789, 0x378A, 0x378B, + 0x378C, 0x378D, 0x378E, 0x378F, 0x3790, 0x3791, 0x3792, 0x3793, 0x3794, + 0x3795, 0x3796, 0x3797, 0x3798, 0x3799, 0x379A, 0x379B, 0x379C, 0x379D, + 0x379E, 0x379F, 0x37A0, 0x37A1, 0x37A2, 0x37A3, 0x37A4, 0x37A5, 0x37A6, + 0x37A7, 0x37A8, 0x37A9, 0x37AA, 0x37AB, 0x37AC, 0x37AD, 0x37AE, 0x37AF, + 0x37B0, 0x37B1, 0x37B2, 0x37B3, 0x37B4, 0x37B5, 0x37B6, 0x37B7, 0x37B8, + 0x37B9, 0x37BA, 0x37BB, 0x37BC, 0x37BD, 0x37BE, 0x37BF, 0x37C0, 0x37C1, + 0x37C2, 0x37C3, 0x37C4, 0x37C5, 0x37C6, 0x37C7, 0x37C8, 0x37C9, 0x37CA, + 0x37CB, 0x37CC, 0x37CD, 0x37CE, 0x37CF, 0x37D0, 0x37D1, 0x37D2, 0x37D3, + 0x37D4, 0x37D5, 0x37D6, 0x37D7, 0x37D8, 0x37D9, 0xFE68, 0x37DA, 0x37DB, + 0x37DC, 0x37DD, 0x37DE, 0x37DF, 0x37E0, 0x37E1, 0x37E2, 0x37E3, 0x37E4, + 0x37E5, 0x37E6, 0x37E7, 0x37E8, 0x37E9, 0x37EA, 0x37EB, 0x37EC, 0x37ED, + 0x37EE, 0x37EF, 0x37F0, 0x37F1, 0x37F2, 0x37F3, 0x37F4, 0x37F5, 0x37F6, + 0x37F7, 0x37F8, 0x37F9, 0x37FA, 0x37FB, 0x37FC, 0x37FD, 0x37FE, 0x37FF, + 0x3800, 0x3801, 0x3802, 0x3803, 0x3804, 0x3805, 0x3806, 0x3807, 0x3808, + 0x3809, 0x380A, 0x380B, 0x380C, 0x380D, 0x380E, 0x380F, 0x3810, 0x3811, + 0x3812, 0x3813, 0x3814, 0x3815, 0x3816, 0x3817, 0x3818, 0x3819, 0x381A, + 0x381B, 0x381C, 0x381D, 0x381E, 0x381F, 0x3820, 0x3821, 0x3822, 0x3823, + 0x3824, 0x3825, 0x3826, 0x3827, 0x3828, 0x3829, 0x382A, 0x382B, 0x382C, + 0x382D, 0x382E, 0x382F, 0x3830, 0x3831, 0x3832, 0x3833, 0x3834, 0x3835, + 0x3836, 0x3837, 0x3838, 0x3839, 0x383A, 0x383B, 0x383C, 0x383D, 0x383E, + 0x383F, 0x3840, 0x3841, 0x3842, 0x3843, 0x3844, 0x3845, 0x3846, 0x3847, + 0x3848, 0x3849, 0x384A, 0x384B, 0x384C, 0x384D, 0x384E, 0x384F, 0x3850, + 0x3851, 0x3852, 0x3853, 0x3854, 0x3855, 0x3856, 0x3857, 0x3858, 0x3859, + 0x385A, 0x385B, 0x385C, 0x385D, 0x385E, 0x385F, 0x3860, 0x3861, 0x3862, + 0x3863, 0x3864, 0x3865, 0x3866, 0x3867, 0x3868, 0x3869, 0x386A, 0x386B, + 0x386C, 0x386D, 0x386E, 0x386F, 0x3870, 0x3871, 0x3872, 0x3873, 0x3874, + 0x3875, 0x3876, 0x3877, 0x3878, 0x3879, 0x387A, 0x387B, 0x387C, 0x387D, + 0x387E, 0x387F, 0x3880, 0x3881, 0x3882, 0x3883, 0x3884, 0x3885, 0x3886, + 0x3887, 0x3888, 0x3889, 0x388A, 0x388B, 0x388C, 0x388D, 0x388E, 0x388F, + 0x3890, 0x3891, 0x3892, 0x3893, 0x3894, 0x3895, 0x3896, 0x3897, 0x3898, + 0x3899, 0x389A, 0x389B, 0x389C, 0x389D, 0x389E, 0x389F, 0x38A0, 0x38A1, + 0x38A2, 0x38A3, 0x38A4, 0x38A5, 0x38A6, 0x38A7, 0x38A8, 0x38A9, 0x38AA, + 0x38AB, 0x38AC, 0x38AD, 0x38AE, 0x38AF, 0x38B0, 0x38B1, 0x38B2, 0x38B3, + 0x38B4, 0x38B5, 0x38B6, 0x38B7, 0x38B8, 0x38B9, 0x38BA, 0x38BB, 0x38BC, + 0x38BD, 0x38BE, 0x38BF, 0x38C0, 0x38C1, 0x38C2, 0x38C3, 0x38C4, 0x38C5, + 0x38C6, 0x38C7, 0x38C8, 0x38C9, 0x38CA, 0x38CB, 0x38CC, 0x38CD, 0x38CE, + 0x38CF, 0x38D0, 0x38D1, 0x38D2, 0x38D3, 0x38D4, 0x38D5, 0x38D6, 0x38D7, + 0x38D8, 0x38D9, 0x38DA, 0x38DB, 0x38DC, 0x38DD, 0x38DE, 0x38DF, 0x38E0, + 0x38E1, 0x38E2, 0x38E3, 0x38E4, 0x38E5, 0x38E6, 0x38E7, 0x38E8, 0x38E9, + 0x38EA, 0x38EB, 0x38EC, 0x38ED, 0x38EE, 0x38EF, 0x38F0, 0x38F1, 0x38F2, + 0x38F3, 0x38F4, 0x38F5, 0x38F6, 0x38F7, 0x38F8, 0xFE69, 0x38F9, 0x38FA, + 0x38FB, 0x38FC, 0x38FD, 0x38FE, 0x38FF, 0x3900, 0x3901, 0x3902, 0x3903, + 0x3904, 0x3905, 0x3906, 0x3907, 0x3908, 0x3909, 0x390A, 0x390B, 0x390C, + 0x390D, 0x390E, 0x390F, 0x3910, 0x3911, 0x3912, 0x3913, 0x3914, 0x3915, + 0x3916, 0x3917, 0x3918, 0x3919, 0x391A, 0x391B, 0x391C, 0x391D, 0x391E, + 0x391F, 0x3920, 0x3921, 0x3922, 0x3923, 0x3924, 0x3925, 0x3926, 0x3927, + 0x3928, 0x3929, 0x392A, 0x392B, 0x392C, 0x392D, 0x392E, 0x392F, 0x3930, + 0x3931, 0x3932, 0x3933, 0x3934, 0x3935, 0x3936, 0x3937, 0x3938, 0x3939, + 0x393A, 0x393B, 0x393C, 0x393D, 0x393E, 0x393F, 0x3940, 0x3941, 0x3942, + 0x3943, 0x3944, 0x3945, 0x3946, 0x3947, 0x3948, 0x3949, 0x394A, 0x394B, + 0x394C, 0x394D, 0x394E, 0x394F, 0x3950, 0x3951, 0x3952, 0x3953, 0x3954, + 0x3955, 0x3956, 0x3957, 0x3958, 0x3959, 0x395A, 0x395B, 0x395C, 0x395D, + 0x395E, 0x395F, 0x3960, 0x3961, 0x3962, 0x3963, 0x3964, 0x3965, 0x3966, + 0x3967, 0x3968, 0x3969, 0xFE6A, 0x396A, 0x396B, 0x396C, 0x396D, 0x396E, + 0x396F, 0x3970, 0x3971, 0x3972, 0x3973, 0x3974, 0x3975, 0x3976, 0x3977, + 0x3978, 0x3979, 0x397A, 0x397B, 0x397C, 0x397D, 0x397E, 0x397F, 0x3980, + 0x3981, 0x3982, 0x3983, 0x3984, 0x3985, 0x3986, 0x3987, 0x3988, 0x3989, + 0x398A, 0x398B, 0x398C, 0x398D, 0x398E, 0x398F, 0x3990, 0x3991, 0x3992, + 0x3993, 0x3994, 0x3995, 0x3996, 0x3997, 0x3998, 0x3999, 0x399A, 0x399B, + 0x399C, 0x399D, 0x399E, 0x399F, 0x39A0, 0x39A1, 0x39A2, 0x39A3, 0x39A4, + 0x39A5, 0x39A6, 0x39A7, 0x39A8, 0x39A9, 0x39AA, 0x39AB, 0x39AC, 0x39AD, + 0x39AE, 0x39AF, 0x39B0, 0x39B1, 0x39B2, 0x39B3, 0x39B4, 0x39B5, 0x39B6, + 0x39B7, 0x39B8, 0x39B9, 0x39BA, 0x39BB, 0x39BC, 0x39BD, 0x39BE, 0x39BF, + 0x39C0, 0x39C1, 0x39C2, 0x39C3, 0x39C4, 0x39C5, 0x39C6, 0x39C7, 0x39C8, + 0x39C9, 0x39CA, 0x39CB, 0x39CC, 0x39CD, 0x39CE, 0x39CF, 0x39D0, 0x39D1, + 0x39D2, 0x39D3, 0x39D4, 0x39D5, 0x39D6, 0x39D7, 0x39D8, 0x39D9, 0x39DA, + 0x39DB, 0x39DC, 0x39DD, 0x39DE, 0x39DF, 0x39E0, 0x39E1, 0x39E2, 0x39E3, + 0x39E4, 0x39E5, 0x39E6, 0x39E7, 0x39E8, 0x39E9, 0x39EA, 0x39EB, 0x39EC, + 0x39ED, 0x39EE, 0x39EF, 0x39F0, 0x39F1, 0x39F2, 0x39F3, 0x39F4, 0x39F5, + 0x39F6, 0x39F7, 0x39F8, 0x39F9, 0x39FA, 0x39FB, 0x39FC, 0x39FD, 0x39FE, + 0x39FF, 0x3A00, 0x3A01, 0x3A02, 0x3A03, 0x3A04, 0x3A05, 0x3A06, 0x3A07, + 0x3A08, 0x3A09, 0x3A0A, 0x3A0B, 0x3A0C, 0x3A0D, 0x3A0E, 0x3A0F, 0x3A10, + 0x3A11, 0x3A12, 0x3A13, 0x3A14, 0x3A15, 0x3A16, 0x3A17, 0x3A18, 0x3A19, + 0x3A1A, 0x3A1B, 0x3A1C, 0x3A1D, 0x3A1E, 0x3A1F, 0x3A20, 0x3A21, 0x3A22, + 0x3A23, 0x3A24, 0x3A25, 0x3A26, 0x3A27, 0x3A28, 0x3A29, 0x3A2A, 0x3A2B, + 0x3A2C, 0x3A2D, 0x3A2E, 0x3A2F, 0x3A30, 0x3A31, 0x3A32, 0x3A33, 0x3A34, + 0x3A35, 0x3A36, 0x3A37, 0x3A38, 0x3A39, 0x3A3A, 0x3A3B, 0x3A3C, 0x3A3D, + 0x3A3E, 0x3A3F, 0x3A40, 0x3A41, 0x3A42, 0x3A43, 0x3A44, 0x3A45, 0x3A46, + 0x3A47, 0x3A48, 0x3A49, 0x3A4A, 0x3A4B, 0x3A4C, 0x3A4D, 0x3A4E, 0x3A4F, + 0x3A50, 0x3A51, 0x3A52, 0x3A53, 0x3A54, 0x3A55, 0x3A56, 0x3A57, 0x3A58, + 0x3A59, 0x3A5A, 0x3A5B, 0x3A5C, 0x3A5D, 0x3A5E, 0x3A5F, 0x3A60, 0x3A61, + 0x3A62, 0x3A63, 0x3A64, 0x3A65, 0x3A66, 0x3A67, 0x3A68, 0x3A69, 0x3A6A, + 0x3A6B, 0x3A6C, 0x3A6D, 0x3A6E, 0x3A6F, 0x3A70, 0x3A71, 0x3A72, 0x3A73, + 0x3A74, 0x3A75, 0x3A76, 0x3A77, 0x3A78, 0x3A79, 0x3A7A, 0x3A7B, 0x3A7C, + 0x3A7D, 0x3A7E, 0x3A7F, 0x3A80, 0x3A81, 0x3A82, 0x3A83, 0x3A84, 0x3A85, + 0x3A86, 0x3A87, 0x3A88, 0x3A89, 0x3A8A, 0x3A8B, 0x3A8C, 0x3A8D, 0x3A8E, + 0x3A8F, 0x3A90, 0x3A91, 0x3A92, 0x3A93, 0x3A94, 0x3A95, 0x3A96, 0x3A97, + 0x3A98, 0x3A99, 0x3A9A, 0x3A9B, 0x3A9C, 0x3A9D, 0x3A9E, 0x3A9F, 0x3AA0, + 0x3AA1, 0x3AA2, 0x3AA3, 0x3AA4, 0x3AA5, 0x3AA6, 0x3AA7, 0x3AA8, 0x3AA9, + 0x3AAA, 0x3AAB, 0x3AAC, 0x3AAD, 0x3AAE, 0x3AAF, 0x3AB0, 0x3AB1, 0x3AB2, + 0x3AB3, 0x3AB4, 0x3AB5, 0x3AB6, 0x3AB7, 0x3AB8, 0x3AB9, 0x3ABA, 0x3ABB, + 0x3ABC, 0x3ABD, 0x3ABE, 0x3ABF, 0x3AC0, 0x3AC1, 0x3AC2, 0x3AC3, 0x3AC4, + 0x3AC5, 0x3AC6, 0x3AC7, 0x3AC8, 0x3AC9, 0x3ACA, 0x3ACB, 0x3ACC, 0x3ACD, + 0x3ACE, 0x3ACF, 0x3AD0, 0x3AD1, 0x3AD2, 0x3AD3, 0x3AD4, 0x3AD5, 0x3AD6, + 0x3AD7, 0x3AD8, 0x3AD9, 0x3ADA, 0x3ADB, 0x3ADC, 0x3ADD, 0x3ADE, 0x3ADF, + 0x3AE0, 0x3AE1, 0x3AE2, 0x3AE3, 0x3AE4, 0x3AE5, 0x3AE6, 0x3AE7, 0x3AE8, + 0x3AE9, 0x3AEA, 0x3AEB, 0x3AEC, 0x3AED, 0x3AEE, 0x3AEF, 0x3AF0, 0x3AF1, + 0x3AF2, 0x3AF3, 0x3AF4, 0x3AF5, 0x3AF6, 0x3AF7, 0x3AF8, 0x3AF9, 0x3AFA, + 0x3AFB, 0x3AFC, 0x3AFD, 0x3AFE, 0x3AFF, 0x3B00, 0x3B01, 0x3B02, 0x3B03, + 0x3B04, 0x3B05, 0x3B06, 0x3B07, 0x3B08, 0x3B09, 0x3B0A, 0x3B0B, 0x3B0C, + 0x3B0D, 0x3B0E, 0x3B0F, 0x3B10, 0x3B11, 0x3B12, 0x3B13, 0x3B14, 0x3B15, + 0x3B16, 0x3B17, 0x3B18, 0x3B19, 0x3B1A, 0x3B1B, 0x3B1C, 0x3B1D, 0x3B1E, + 0x3B1F, 0x3B20, 0x3B21, 0x3B22, 0x3B23, 0x3B24, 0x3B25, 0x3B26, 0x3B27, + 0x3B28, 0x3B29, 0x3B2A, 0x3B2B, 0x3B2C, 0x3B2D, 0x3B2E, 0x3B2F, 0x3B30, + 0x3B31, 0x3B32, 0x3B33, 0x3B34, 0x3B35, 0x3B36, 0x3B37, 0x3B38, 0x3B39, + 0x3B3A, 0x3B3B, 0x3B3C, 0x3B3D, 0x3B3E, 0x3B3F, 0x3B40, 0x3B41, 0x3B42, + 0x3B43, 0x3B44, 0x3B45, 0x3B46, 0x3B47, 0x3B48, 0x3B49, 0x3B4A, 0x3B4B, + 0x3B4C, 0x3B4D, 0x3B4E, 0x3B4F, 0x3B50, 0x3B51, 0x3B52, 0x3B53, 0x3B54, + 0x3B55, 0x3B56, 0x3B57, 0x3B58, 0x3B59, 0x3B5A, 0x3B5B, 0x3B5C, 0x3B5D, + 0x3B5E, 0x3B5F, 0x3B60, 0x3B61, 0x3B62, 0x3B63, 0x3B64, 0x3B65, 0x3B66, + 0x3B67, 0x3B68, 0x3B69, 0x3B6A, 0x3B6B, 0x3B6C, 0x3B6D, 0x3B6E, 0x3B6F, + 0x3B70, 0x3B71, 0x3B72, 0x3B73, 0x3B74, 0x3B75, 0x3B76, 0x3B77, 0x3B78, + 0x3B79, 0x3B7A, 0x3B7B, 0x3B7C, 0x3B7D, 0x3B7E, 0x3B7F, 0x3B80, 0x3B81, + 0x3B82, 0x3B83, 0x3B84, 0x3B85, 0x3B86, 0x3B87, 0x3B88, 0x3B89, 0x3B8A, + 0x3B8B, 0x3B8C, 0x3B8D, 0x3B8E, 0x3B8F, 0x3B90, 0x3B91, 0x3B92, 0x3B93, + 0x3B94, 0x3B95, 0x3B96, 0x3B97, 0x3B98, 0x3B99, 0x3B9A, 0x3B9B, 0x3B9C, + 0x3B9D, 0x3B9E, 0x3B9F, 0x3BA0, 0x3BA1, 0x3BA2, 0x3BA3, 0x3BA4, 0x3BA5, + 0x3BA6, 0x3BA7, 0x3BA8, 0x3BA9, 0x3BAA, 0x3BAB, 0x3BAC, 0x3BAD, 0x3BAE, + 0x3BAF, 0x3BB0, 0x3BB1, 0x3BB2, 0x3BB3, 0x3BB4, 0x3BB5, 0x3BB6, 0x3BB7, + 0x3BB8, 0x3BB9, 0x3BBA, 0x3BBB, 0x3BBC, 0x3BBD, 0x3BBE, 0x3BBF, 0x3BC0, + 0x3BC1, 0x3BC2, 0x3BC3, 0x3BC4, 0x3BC5, 0x3BC6, 0x3BC7, 0x3BC8, 0x3BC9, + 0x3BCA, 0x3BCB, 0x3BCC, 0x3BCD, 0x3BCE, 0x3BCF, 0x3BD0, 0x3BD1, 0x3BD2, + 0x3BD3, 0x3BD4, 0x3BD5, 0x3BD6, 0x3BD7, 0x3BD8, 0x3BD9, 0x3BDA, 0x3BDB, + 0x3BDC, 0x3BDD, 0x3BDE, 0x3BDF, 0x3BE0, 0x3BE1, 0x3BE2, 0x3BE3, 0x3BE4, + 0x3BE5, 0x3BE6, 0x3BE7, 0x3BE8, 0x3BE9, 0x3BEA, 0x3BEB, 0x3BEC, 0x3BED, + 0x3BEE, 0x3BEF, 0x3BF0, 0x3BF1, 0x3BF2, 0x3BF3, 0x3BF4, 0x3BF5, 0x3BF6, + 0x3BF7, 0x3BF8, 0x3BF9, 0x3BFA, 0x3BFB, 0x3BFC, 0x3BFD, 0x3BFE, 0x3BFF, + 0x3C00, 0x3C01, 0x3C02, 0x3C03, 0x3C04, 0x3C05, 0x3C06, 0x3C07, 0x3C08, + 0x3C09, 0x3C0A, 0x3C0B, 0x3C0C, 0x3C0D, 0x3C0E, 0x3C0F, 0x3C10, 0x3C11, + 0x3C12, 0x3C13, 0x3C14, 0x3C15, 0x3C16, 0x3C17, 0x3C18, 0x3C19, 0x3C1A, + 0x3C1B, 0x3C1C, 0x3C1D, 0x3C1E, 0x3C1F, 0x3C20, 0x3C21, 0x3C22, 0x3C23, + 0x3C24, 0x3C25, 0x3C26, 0x3C27, 0x3C28, 0x3C29, 0x3C2A, 0x3C2B, 0x3C2C, + 0x3C2D, 0x3C2E, 0x3C2F, 0x3C30, 0x3C31, 0x3C32, 0x3C33, 0x3C34, 0x3C35, + 0x3C36, 0x3C37, 0x3C38, 0x3C39, 0x3C3A, 0x3C3B, 0x3C3C, 0x3C3D, 0x3C3E, + 0x3C3F, 0x3C40, 0x3C41, 0x3C42, 0x3C43, 0x3C44, 0x3C45, 0x3C46, 0x3C47, + 0x3C48, 0x3C49, 0x3C4A, 0x3C4B, 0x3C4C, 0x3C4D, 0x3C4E, 0x3C4F, 0x3C50, + 0x3C51, 0x3C52, 0x3C53, 0x3C54, 0x3C55, 0x3C56, 0x3C57, 0x3C58, 0x3C59, + 0x3C5A, 0x3C5B, 0x3C5C, 0x3C5D, 0x3C5E, 0x3C5F, 0x3C60, 0x3C61, 0x3C62, + 0x3C63, 0x3C64, 0x3C65, 0x3C66, 0x3C67, 0x3C68, 0x3C69, 0x3C6A, 0x3C6B, + 0x3C6C, 0x3C6D, 0x3C6E, 0x3C6F, 0x3C70, 0x3C71, 0x3C72, 0x3C73, 0x3C74, + 0x3C75, 0x3C76, 0x3C77, 0x3C78, 0x3C79, 0x3C7A, 0x3C7B, 0x3C7C, 0x3C7D, + 0x3C7E, 0x3C7F, 0x3C80, 0x3C81, 0x3C82, 0x3C83, 0x3C84, 0x3C85, 0x3C86, + 0x3C87, 0x3C88, 0x3C89, 0x3C8A, 0x3C8B, 0x3C8C, 0x3C8D, 0x3C8E, 0x3C8F, + 0x3C90, 0x3C91, 0x3C92, 0x3C93, 0x3C94, 0x3C95, 0x3C96, 0x3C97, 0x3C98, + 0x3C99, 0x3C9A, 0x3C9B, 0x3C9C, 0x3C9D, 0x3C9E, 0x3C9F, 0x3CA0, 0x3CA1, + 0x3CA2, 0x3CA3, 0x3CA4, 0x3CA5, 0x3CA6, 0x3CA7, 0x3CA8, 0x3CA9, 0x3CAA, + 0x3CAB, 0x3CAC, 0x3CAD, 0x3CAE, 0x3CAF, 0x3CB0, 0x3CB1, 0x3CB2, 0x3CB3, + 0x3CB4, 0x3CB5, 0x3CB6, 0x3CB7, 0x3CB8, 0x3CB9, 0x3CBA, 0x3CBB, 0x3CBC, + 0x3CBD, 0x3CBE, 0x3CBF, 0x3CC0, 0x3CC1, 0x3CC2, 0x3CC3, 0x3CC4, 0x3CC5, + 0x3CC6, 0x3CC7, 0x3CC8, 0x3CC9, 0x3CCA, 0x3CCB, 0x3CCC, 0x3CCD, 0x3CCE, + 0x3CCF, 0x3CD0, 0x3CD1, 0x3CD2, 0x3CD3, 0x3CD4, 0x3CD5, 0x3CD6, 0x3CD7, + 0x3CD8, 0x3CD9, 0x3CDA, 0x3CDB, 0x3CDC, 0x3CDD, 0x3CDE, 0xFE6F, 0x3CDF, + 0x3CE0, 0x3CE1, 0x3CE2, 0x3CE3, 0x3CE4, 0x3CE5, 0x3CE6, 0x3CE7, 0x3CE8, + 0x3CE9, 0x3CEA, 0x3CEB, 0x3CEC, 0x3CED, 0x3CEE, 0x3CEF, 0x3CF0, 0x3CF1, + 0x3CF2, 0x3CF3, 0x3CF4, 0x3CF5, 0x3CF6, 0x3CF7, 0x3CF8, 0x3CF9, 0x3CFA, + 0x3CFB, 0x3CFC, 0x3CFD, 0x3CFE, 0x3CFF, 0x3D00, 0x3D01, 0x3D02, 0x3D03, + 0x3D04, 0x3D05, 0x3D06, 0x3D07, 0x3D08, 0x3D09, 0x3D0A, 0x3D0B, 0x3D0C, + 0x3D0D, 0x3D0E, 0x3D0F, 0x3D10, 0x3D11, 0x3D12, 0x3D13, 0x3D14, 0x3D15, + 0x3D16, 0x3D17, 0x3D18, 0x3D19, 0x3D1A, 0x3D1B, 0x3D1C, 0x3D1D, 0x3D1E, + 0x3D1F, 0x3D20, 0x3D21, 0x3D22, 0x3D23, 0x3D24, 0x3D25, 0x3D26, 0x3D27, + 0x3D28, 0x3D29, 0x3D2A, 0x3D2B, 0x3D2C, 0x3D2D, 0x3D2E, 0x3D2F, 0x3D30, + 0x3D31, 0x3D32, 0x3D33, 0x3D34, 0x3D35, 0x3D36, 0x3D37, 0x3D38, 0x3D39, + 0x3D3A, 0x3D3B, 0x3D3C, 0x3D3D, 0x3D3E, 0x3D3F, 0x3D40, 0x3D41, 0x3D42, + 0x3D43, 0x3D44, 0x3D45, 0x3D46, 0x3D47, 0x3D48, 0x3D49, 0x3D4A, 0x3D4B, + 0x3D4C, 0x3D4D, 0x3D4E, 0x3D4F, 0x3D50, 0x3D51, 0x3D52, 0x3D53, 0x3D54, + 0x3D55, 0x3D56, 0x3D57, 0x3D58, 0x3D59, 0x3D5A, 0x3D5B, 0x3D5C, 0x3D5D, + 0x3D5E, 0x3D5F, 0x3D60, 0x3D61, 0x3D62, 0x3D63, 0x3D64, 0x3D65, 0x3D66, + 0x3D67, 0x3D68, 0x3D69, 0x3D6A, 0x3D6B, 0x3D6C, 0x3D6D, 0x3D6E, 0x3D6F, + 0x3D70, 0x3D71, 0x3D72, 0x3D73, 0x3D74, 0x3D75, 0x3D76, 0x3D77, 0x3D78, + 0x3D79, 0x3D7A, 0x3D7B, 0x3D7C, 0x3D7D, 0x3D7E, 0x3D7F, 0x3D80, 0x3D81, + 0x3D82, 0x3D83, 0x3D84, 0x3D85, 0x3D86, 0x3D87, 0x3D88, 0x3D89, 0x3D8A, + 0x3D8B, 0x3D8C, 0x3D8D, 0x3D8E, 0x3D8F, 0x3D90, 0x3D91, 0x3D92, 0x3D93, + 0x3D94, 0x3D95, 0x3D96, 0x3D97, 0x3D98, 0x3D99, 0x3D9A, 0x3D9B, 0x3D9C, + 0x3D9D, 0x3D9E, 0x3D9F, 0x3DA0, 0x3DA1, 0x3DA2, 0x3DA3, 0x3DA4, 0x3DA5, + 0x3DA6, 0x3DA7, 0x3DA8, 0x3DA9, 0x3DAA, 0x3DAB, 0x3DAC, 0x3DAD, 0x3DAE, + 0x3DAF, 0x3DB0, 0x3DB1, 0x3DB2, 0x3DB3, 0x3DB4, 0x3DB5, 0x3DB6, 0x3DB7, + 0x3DB8, 0x3DB9, 0x3DBA, 0x3DBB, 0x3DBC, 0x3DBD, 0x3DBE, 0x3DBF, 0x3DC0, + 0x3DC1, 0x3DC2, 0x3DC3, 0x3DC4, 0x3DC5, 0x3DC6, 0x3DC7, 0x3DC8, 0x3DC9, + 0x3DCA, 0x3DCB, 0x3DCC, 0x3DCD, 0x3DCE, 0x3DCF, 0x3DD0, 0x3DD1, 0x3DD2, + 0x3DD3, 0x3DD4, 0x3DD5, 0x3DD6, 0x3DD7, 0x3DD8, 0x3DD9, 0x3DDA, 0x3DDB, + 0x3DDC, 0x3DDD, 0x3DDE, 0x3DDF, 0x3DE0, 0x3DE1, 0x3DE2, 0x3DE3, 0x3DE4, + 0x3DE5, 0x3DE6, 0xFE70, 0x3DE7, 0x3DE8, 0x3DE9, 0x3DEA, 0x3DEB, 0x3DEC, + 0x3DED, 0x3DEE, 0x3DEF, 0x3DF0, 0x3DF1, 0x3DF2, 0x3DF3, 0x3DF4, 0x3DF5, + 0x3DF6, 0x3DF7, 0x3DF8, 0x3DF9, 0x3DFA, 0x3DFB, 0x3DFC, 0x3DFD, 0x3DFE, + 0x3DFF, 0x3E00, 0x3E01, 0x3E02, 0x3E03, 0x3E04, 0x3E05, 0x3E06, 0x3E07, + 0x3E08, 0x3E09, 0x3E0A, 0x3E0B, 0x3E0C, 0x3E0D, 0x3E0E, 0x3E0F, 0x3E10, + 0x3E11, 0x3E12, 0x3E13, 0x3E14, 0x3E15, 0x3E16, 0x3E17, 0x3E18, 0x3E19, + 0x3E1A, 0x3E1B, 0x3E1C, 0x3E1D, 0x3E1E, 0x3E1F, 0x3E20, 0x3E21, 0x3E22, + 0x3E23, 0x3E24, 0x3E25, 0x3E26, 0x3E27, 0x3E28, 0x3E29, 0x3E2A, 0x3E2B, + 0x3E2C, 0x3E2D, 0x3E2E, 0x3E2F, 0x3E30, 0x3E31, 0x3E32, 0x3E33, 0x3E34, + 0x3E35, 0x3E36, 0x3E37, 0x3E38, 0x3E39, 0x3E3A, 0x3E3B, 0x3E3C, 0x3E3D, + 0x3E3E, 0x3E3F, 0x3E40, 0x3E41, 0x3E42, 0x3E43, 0x3E44, 0x3E45, 0x3E46, + 0x3E47, 0x3E48, 0x3E49, 0x3E4A, 0x3E4B, 0x3E4C, 0x3E4D, 0x3E4E, 0x3E4F, + 0x3E50, 0x3E51, 0x3E52, 0x3E53, 0x3E54, 0x3E55, 0x3E56, 0x3E57, 0x3E58, + 0x3E59, 0x3E5A, 0x3E5B, 0x3E5C, 0x3E5D, 0x3E5E, 0x3E5F, 0x3E60, 0x3E61, + 0x3E62, 0x3E63, 0x3E64, 0x3E65, 0x3E66, 0x3E67, 0x3E68, 0x3E69, 0x3E6A, + 0x3E6B, 0x3E6C, 0x3E6D, 0x3E6E, 0x3E6F, 0x3E70, 0x3E71, 0x3E72, 0x3E73, + 0x3E74, 0x3E75, 0x3E76, 0x3E77, 0x3E78, 0x3E79, 0x3E7A, 0x3E7B, 0x3E7C, + 0x3E7D, 0x3E7E, 0x3E7F, 0x3E80, 0x3E81, 0x3E82, 0x3E83, 0x3E84, 0x3E85, + 0x3E86, 0x3E87, 0x3E88, 0x3E89, 0x3E8A, 0x3E8B, 0x3E8C, 0x3E8D, 0x3E8E, + 0x3E8F, 0x3E90, 0x3E91, 0x3E92, 0x3E93, 0x3E94, 0x3E95, 0x3E96, 0x3E97, + 0x3E98, 0x3E99, 0x3E9A, 0x3E9B, 0x3E9C, 0x3E9D, 0x3E9E, 0x3E9F, 0x3EA0, + 0x3EA1, 0x3EA2, 0x3EA3, 0x3EA4, 0x3EA5, 0x3EA6, 0x3EA7, 0x3EA8, 0x3EA9, + 0x3EAA, 0x3EAB, 0x3EAC, 0x3EAD, 0x3EAE, 0x3EAF, 0x3EB0, 0x3EB1, 0x3EB2, + 0x3EB3, 0x3EB4, 0x3EB5, 0x3EB6, 0x3EB7, 0x3EB8, 0x3EB9, 0x3EBA, 0x3EBB, + 0x3EBC, 0x3EBD, 0x3EBE, 0x3EBF, 0x3EC0, 0x3EC1, 0x3EC2, 0x3EC3, 0x3EC4, + 0x3EC5, 0x3EC6, 0x3EC7, 0x3EC8, 0x3EC9, 0x3ECA, 0x3ECB, 0x3ECC, 0x3ECD, + 0x3ECE, 0x3ECF, 0x3ED0, 0x3ED1, 0x3ED2, 0x3ED3, 0x3ED4, 0x3ED5, 0x3ED6, + 0x3ED7, 0x3ED8, 0x3ED9, 0x3EDA, 0x3EDB, 0x3EDC, 0x3EDD, 0x3EDE, 0x3EDF, + 0x3EE0, 0x3EE1, 0x3EE2, 0x3EE3, 0x3EE4, 0x3EE5, 0x3EE6, 0x3EE7, 0x3EE8, + 0x3EE9, 0x3EEA, 0x3EEB, 0x3EEC, 0x3EED, 0x3EEE, 0x3EEF, 0x3EF0, 0x3EF1, + 0x3EF2, 0x3EF3, 0x3EF4, 0x3EF5, 0x3EF6, 0x3EF7, 0x3EF8, 0x3EF9, 0x3EFA, + 0x3EFB, 0x3EFC, 0x3EFD, 0x3EFE, 0x3EFF, 0x3F00, 0x3F01, 0x3F02, 0x3F03, + 0x3F04, 0x3F05, 0x3F06, 0x3F07, 0x3F08, 0x3F09, 0x3F0A, 0x3F0B, 0x3F0C, + 0x3F0D, 0x3F0E, 0x3F0F, 0x3F10, 0x3F11, 0x3F12, 0x3F13, 0x3F14, 0x3F15, + 0x3F16, 0x3F17, 0x3F18, 0x3F19, 0x3F1A, 0x3F1B, 0x3F1C, 0x3F1D, 0x3F1E, + 0x3F1F, 0x3F20, 0x3F21, 0x3F22, 0x3F23, 0x3F24, 0x3F25, 0x3F26, 0x3F27, + 0x3F28, 0x3F29, 0x3F2A, 0x3F2B, 0x3F2C, 0x3F2D, 0x3F2E, 0x3F2F, 0x3F30, + 0x3F31, 0x3F32, 0x3F33, 0x3F34, 0x3F35, 0x3F36, 0x3F37, 0x3F38, 0x3F39, + 0x3F3A, 0x3F3B, 0x3F3C, 0x3F3D, 0x3F3E, 0x3F3F, 0x3F40, 0x3F41, 0x3F42, + 0x3F43, 0x3F44, 0x3F45, 0x3F46, 0x3F47, 0x3F48, 0x3F49, 0x3F4A, 0x3F4B, + 0x3F4C, 0x3F4D, 0x3F4E, 0x3F4F, 0x3F50, 0x3F51, 0x3F52, 0x3F53, 0x3F54, + 0x3F55, 0x3F56, 0x3F57, 0x3F58, 0x3F59, 0x3F5A, 0x3F5B, 0x3F5C, 0x3F5D, + 0x3F5E, 0x3F5F, 0x3F60, 0x3F61, 0x3F62, 0x3F63, 0x3F64, 0x3F65, 0x3F66, + 0x3F67, 0x3F68, 0x3F69, 0x3F6A, 0x3F6B, 0x3F6C, 0x3F6D, 0x3F6E, 0x3F6F, + 0x3F70, 0x3F71, 0x3F72, 0x3F73, 0x3F74, 0x3F75, 0x3F76, 0x3F77, 0x3F78, + 0x3F79, 0x3F7A, 0x3F7B, 0x3F7C, 0x3F7D, 0x3F7E, 0x3F7F, 0x3F80, 0x3F81, + 0x3F82, 0x3F83, 0x3F84, 0x3F85, 0x3F86, 0x3F87, 0x3F88, 0x3F89, 0x3F8A, + 0x3F8B, 0x3F8C, 0x3F8D, 0x3F8E, 0x3F8F, 0x3F90, 0x3F91, 0x3F92, 0x3F93, + 0x3F94, 0x3F95, 0x3F96, 0x3F97, 0x3F98, 0x3F99, 0x3F9A, 0x3F9B, 0x3F9C, + 0x3F9D, 0x3F9E, 0x3F9F, 0x3FA0, 0x3FA1, 0x3FA2, 0x3FA3, 0x3FA4, 0x3FA5, + 0x3FA6, 0x3FA7, 0x3FA8, 0x3FA9, 0x3FAA, 0x3FAB, 0x3FAC, 0x3FAD, 0x3FAE, + 0x3FAF, 0x3FB0, 0x3FB1, 0x3FB2, 0x3FB3, 0x3FB4, 0x3FB5, 0x3FB6, 0x3FB7, + 0x3FB8, 0x3FB9, 0x3FBA, 0x3FBB, 0x3FBC, 0x3FBD, 0xFE72, 0x3FBE, 0x3FBF, + 0x3FC0, 0x3FC1, 0x3FC2, 0x3FC3, 0x3FC4, 0x3FC5, 0x3FC6, 0x3FC7, 0x3FC8, + 0x3FC9, 0x3FCA, 0x3FCB, 0x3FCC, 0x3FCD, 0x3FCE, 0x3FCF, 0x3FD0, 0x3FD1, + 0x3FD2, 0x3FD3, 0x3FD4, 0x3FD5, 0x3FD6, 0x3FD7, 0x3FD8, 0x3FD9, 0x3FDA, + 0x3FDB, 0x3FDC, 0x3FDD, 0x3FDE, 0x3FDF, 0x3FE0, 0x3FE1, 0x3FE2, 0x3FE3, + 0x3FE4, 0x3FE5, 0x3FE6, 0x3FE7, 0x3FE8, 0x3FE9, 0x3FEA, 0x3FEB, 0x3FEC, + 0x3FED, 0x3FEE, 0x3FEF, 0x3FF0, 0x3FF1, 0x3FF2, 0x3FF3, 0x3FF4, 0x3FF5, + 0x3FF6, 0x3FF7, 0x3FF8, 0x3FF9, 0x3FFA, 0x3FFB, 0x3FFC, 0x3FFD, 0x3FFE, + 0x3FFF, 0x4000, 0x4001, 0x4002, 0x4003, 0x4004, 0x4005, 0x4006, 0x4007, + 0x4008, 0x4009, 0x400A, 0x400B, 0x400C, 0x400D, 0x400E, 0x400F, 0x4010, + 0x4011, 0x4012, 0x4013, 0x4014, 0x4015, 0x4016, 0x4017, 0x4018, 0x4019, + 0x401A, 0x401B, 0x401C, 0x401D, 0x401E, 0x401F, 0x4020, 0x4021, 0x4022, + 0x4023, 0x4024, 0x4025, 0x4026, 0x4027, 0x4028, 0x4029, 0x402A, 0x402B, + 0x402C, 0x402D, 0x402E, 0x402F, 0x4030, 0x4031, 0xFE78, 0x4032, 0x4033, + 0x4034, 0x4035, 0xFE77, 0x4036, 0x4037, 0x4038, 0x4039, 0x403A, 0x403B, + 0x403C, 0x403D, 0x403E, 0x403F, 0x4040, 0x4041, 0x4042, 0x4043, 0x4044, + 0x4045, 0x4046, 0x4047, 0x4048, 0x4049, 0x404A, 0x404B, 0x404C, 0x404D, + 0x404E, 0x404F, 0x4050, 0x4051, 0x4052, 0x4053, 0x4054, 0x4055, 0x4056, + 0x4057, 0x4058, 0x4059, 0x405A, 0x405B, 0x405C, 0x405D, 0x405E, 0x405F, + 0x4060, 0xFE7A, 0x4061, 0x4062, 0x4063, 0x4064, 0x4065, 0x4066, 0x4067, + 0x4068, 0x4069, 0x406A, 0x406B, 0x406C, 0x406D, 0x406E, 0x406F, 0x4070, + 0x4071, 0x4072, 0x4073, 0x4074, 0x4075, 0x4076, 0x4077, 0x4078, 0x4079, + 0x407A, 0x407B, 0x407C, 0x407D, 0x407E, 0x407F, 0x4080, 0x4081, 0x4082, + 0x4083, 0x4084, 0x4085, 0x4086, 0x4087, 0x4088, 0x4089, 0x408A, 0x408B, + 0x408C, 0x408D, 0x408E, 0x408F, 0x4090, 0x4091, 0x4092, 0x4093, 0x4094, + 0x4095, 0x4096, 0x4097, 0x4098, 0x4099, 0x409A, 0x409B, 0x409C, 0x409D, + 0x409E, 0x409F, 0x40A0, 0x40A1, 0x40A2, 0x40A3, 0x40A4, 0x40A5, 0x40A6, + 0x40A7, 0x40A8, 0x40A9, 0x40AA, 0x40AB, 0x40AC, 0x40AD, 0x40AE, 0x40AF, + 0x40B0, 0x40B1, 0x40B2, 0x40B3, 0x40B4, 0x40B5, 0x40B6, 0x40B7, 0x40B8, + 0x40B9, 0x40BA, 0x40BB, 0x40BC, 0x40BD, 0x40BE, 0x40BF, 0x40C0, 0x40C1, + 0x40C2, 0x40C3, 0x40C4, 0x40C5, 0x40C6, 0x40C7, 0x40C8, 0x40C9, 0x40CA, + 0x40CB, 0x40CC, 0x40CD, 0x40CE, 0x40CF, 0x40D0, 0x40D1, 0x40D2, 0x40D3, + 0x40D4, 0x40D5, 0x40D6, 0x40D7, 0x40D8, 0x40D9, 0x40DA, 0x40DB, 0x40DC, + 0x40DD, 0x40DE, 0x40DF, 0x40E0, 0x40E1, 0x40E2, 0x40E3, 0x40E4, 0x40E5, + 0x40E6, 0x40E7, 0x40E8, 0x40E9, 0x40EA, 0x40EB, 0x40EC, 0x40ED, 0x40EE, + 0x40EF, 0x40F0, 0x40F1, 0x40F2, 0x40F3, 0x40F4, 0x40F5, 0x40F6, 0x40F7, + 0x40F8, 0x40F9, 0x40FA, 0x40FB, 0x40FC, 0x40FD, 0x40FE, 0x40FF, 0x4100, + 0x4101, 0x4102, 0x4103, 0x4104, 0x4105, 0x4106, 0x4107, 0x4108, 0x4109, + 0x410A, 0x410B, 0x410C, 0x410D, 0x410E, 0x410F, 0x4110, 0x4111, 0x4112, + 0x4113, 0x4114, 0x4115, 0x4116, 0x4117, 0x4118, 0x4119, 0x411A, 0x411B, + 0x411C, 0x411D, 0x411E, 0x411F, 0x4120, 0x4121, 0x4122, 0x4123, 0x4124, + 0x4125, 0x4126, 0x4127, 0x4128, 0x4129, 0x412A, 0x412B, 0x412C, 0x412D, + 0x412E, 0x412F, 0x4130, 0x4131, 0x4132, 0x4133, 0x4134, 0x4135, 0x4136, + 0x4137, 0x4138, 0x4139, 0x413A, 0x413B, 0x413C, 0x413D, 0x413E, 0x413F, + 0x4140, 0x4141, 0x4142, 0x4143, 0x4144, 0x4145, 0x4146, 0x4147, 0x4148, + 0x4149, 0x414A, 0x414B, 0x414C, 0x414D, 0x414E, 0x414F, 0x4150, 0x4151, + 0x4152, 0x4153, 0x4154, 0x4155, 0x4156, 0x4157, 0x4158, 0xFE7B, 0x4159, + 0x415A, 0x415B, 0x415C, 0x415D, 0x415E, 0x415F, 0x4160, 0x4161, 0x4162, + 0x4163, 0x4164, 0x4165, 0x4166, 0x4167, 0x4168, 0x4169, 0x416A, 0x416B, + 0x416C, 0x416D, 0x416E, 0x416F, 0x4170, 0x4171, 0x4172, 0x4173, 0x4174, + 0x4175, 0x4176, 0x4177, 0x4178, 0x4179, 0x417A, 0x417B, 0x417C, 0x417D, + 0x417E, 0x417F, 0x4180, 0x4181, 0x4182, 0x4183, 0x4184, 0x4185, 0x4186, + 0x4187, 0x4188, 0x4189, 0x418A, 0x418B, 0x418C, 0x418D, 0x418E, 0x418F, + 0x4190, 0x4191, 0x4192, 0x4193, 0x4194, 0x4195, 0x4196, 0x4197, 0x4198, + 0x4199, 0x419A, 0x419B, 0x419C, 0x419D, 0x419E, 0x419F, 0x41A0, 0x41A1, + 0x41A2, 0x41A3, 0x41A4, 0x41A5, 0x41A6, 0x41A7, 0x41A8, 0x41A9, 0x41AA, + 0x41AB, 0x41AC, 0x41AD, 0x41AE, 0x41AF, 0x41B0, 0x41B1, 0x41B2, 0x41B3, + 0x41B4, 0x41B5, 0x41B6, 0x41B7, 0x41B8, 0x41B9, 0x41BA, 0x41BB, 0x41BC, + 0x41BD, 0x41BE, 0x41BF, 0x41C0, 0x41C1, 0x41C2, 0x41C3, 0x41C4, 0x41C5, + 0x41C6, 0x41C7, 0x41C8, 0x41C9, 0x41CA, 0x41CB, 0x41CC, 0x41CD, 0x41CE, + 0x41CF, 0x41D0, 0x41D1, 0x41D2, 0x41D3, 0x41D4, 0x41D5, 0x41D6, 0x41D7, + 0x41D8, 0x41D9, 0x41DA, 0x41DB, 0x41DC, 0x41DD, 0x41DE, 0x41DF, 0x41E0, + 0x41E1, 0x41E2, 0x41E3, 0x41E4, 0x41E5, 0x41E6, 0x41E7, 0x41E8, 0x41E9, + 0x41EA, 0x41EB, 0x41EC, 0x41ED, 0x41EE, 0x41EF, 0x41F0, 0x41F1, 0x41F2, + 0x41F3, 0x41F4, 0x41F5, 0x41F6, 0x41F7, 0x41F8, 0x41F9, 0x41FA, 0x41FB, + 0x41FC, 0x41FD, 0x41FE, 0x41FF, 0x4200, 0x4201, 0x4202, 0x4203, 0x4204, + 0x4205, 0x4206, 0x4207, 0x4208, 0x4209, 0x420A, 0x420B, 0x420C, 0x420D, + 0x420E, 0x420F, 0x4210, 0x4211, 0x4212, 0x4213, 0x4214, 0x4215, 0x4216, + 0x4217, 0x4218, 0x4219, 0x421A, 0x421B, 0x421C, 0x421D, 0x421E, 0x421F, + 0x4220, 0x4221, 0x4222, 0x4223, 0x4224, 0x4225, 0x4226, 0x4227, 0x4228, + 0x4229, 0x422A, 0x422B, 0x422C, 0x422D, 0x422E, 0x422F, 0x4230, 0x4231, + 0x4232, 0x4233, 0x4234, 0x4235, 0x4236, 0x4237, 0x4238, 0x4239, 0x423A, + 0x423B, 0x423C, 0x423D, 0x423E, 0x423F, 0x4240, 0x4241, 0x4242, 0x4243, + 0x4244, 0x4245, 0x4246, 0x4247, 0x4248, 0x4249, 0x424A, 0x424B, 0x424C, + 0x424D, 0x424E, 0x424F, 0x4250, 0x4251, 0x4252, 0x4253, 0x4254, 0x4255, + 0x4256, 0x4257, 0x4258, 0x4259, 0x425A, 0x425B, 0x425C, 0x425D, 0x425E, + 0x425F, 0x4260, 0x4261, 0x4262, 0x4263, 0x4264, 0x4265, 0x4266, 0x4267, + 0x4268, 0x4269, 0x426A, 0x426B, 0x426C, 0x426D, 0x426E, 0x426F, 0x4270, + 0x4271, 0x4272, 0x4273, 0x4274, 0x4275, 0x4276, 0x4277, 0x4278, 0x4279, + 0x427A, 0x427B, 0x427C, 0x427D, 0x427E, 0x427F, 0x4280, 0x4281, 0x4282, + 0x4283, 0x4284, 0x4285, 0x4286, 0x4287, 0x4288, 0x4289, 0x428A, 0x428B, + 0x428C, 0x428D, 0x428E, 0x428F, 0x4290, 0x4291, 0x4292, 0x4293, 0x4294, + 0x4295, 0x4296, 0x4297, 0x4298, 0x4299, 0x429A, 0x429B, 0x429C, 0x429D, + 0x429E, 0x429F, 0x42A0, 0x42A1, 0x42A2, 0x42A3, 0x42A4, 0x42A5, 0x42A6, + 0x42A7, 0x42A8, 0x42A9, 0x42AA, 0x42AB, 0x42AC, 0x42AD, 0x42AE, 0x42AF, + 0x42B0, 0x42B1, 0x42B2, 0x42B3, 0x42B4, 0x42B5, 0x42B6, 0x42B7, 0x42B8, + 0x42B9, 0x42BA, 0x42BB, 0x42BC, 0x42BD, 0x42BE, 0x42BF, 0x42C0, 0x42C1, + 0x42C2, 0x42C3, 0x42C4, 0x42C5, 0x42C6, 0x42C7, 0x42C8, 0x42C9, 0x42CA, + 0x42CB, 0x42CC, 0x42CD, 0xFE7D, 0x42CE, 0x42CF, 0x42D0, 0x42D1, 0x42D2, + 0x42D3, 0x42D4, 0x42D5, 0x42D6, 0x42D7, 0x42D8, 0x42D9, 0x42DA, 0x42DB, + 0x42DC, 0x42DD, 0x42DE, 0x42DF, 0x42E0, 0x42E1, 0xFE7C, 0x42E2, 0x42E3, + 0x42E4, 0x42E5, 0x42E6, 0x42E7, 0x42E8, 0x42E9, 0x42EA, 0x42EB, 0x42EC, + 0x42ED, 0x42EE, 0x42EF, 0x42F0, 0x42F1, 0x42F2, 0x42F3, 0x42F4, 0x42F5, + 0x42F6, 0x42F7, 0x42F8, 0x42F9, 0x42FA, 0x42FB, 0x42FC, 0x42FD, 0x42FE, + 0x42FF, 0x4300, 0x4301, 0x4302, 0x4303, 0x4304, 0x4305, 0x4306, 0x4307, + 0x4308, 0x4309, 0x430A, 0x430B, 0x430C, 0x430D, 0x430E, 0x430F, 0x4310, + 0x4311, 0x4312, 0x4313, 0x4314, 0x4315, 0x4316, 0x4317, 0x4318, 0x4319, + 0x431A, 0x431B, 0x431C, 0x431D, 0x431E, 0x431F, 0x4320, 0x4321, 0x4322, + 0x4323, 0x4324, 0x4325, 0x4326, 0x4327, 0x4328, 0x4329, 0x432A, 0x432B, + 0x432C, 0x432D, 0x432E, 0x432F, 0x4330, 0x4331, 0x4332, 0x4333, 0x4334, + 0x4335, 0x4336, 0x4337, 0x4338, 0x4339, 0x433A, 0x433B, 0x433C, 0x433D, + 0x433E, 0x433F, 0x4340, 0x4341, 0x4342, 0x4343, 0x4344, 0x4345, 0x4346, + 0x4347, 0x4348, 0x4349, 0x434A, 0x434B, 0x434C, 0x434D, 0x434E, 0x434F, + 0x4350, 0x4351, 0x4352, 0x4353, 0x4354, 0x4355, 0x4356, 0x4357, 0x4358, + 0x4359, 0x435A, 0x435B, 0x435C, 0x435D, 0x435E, 0x435F, 0x4360, 0x4361, + 0x4362, 0x4363, 0x4364, 0x4365, 0x4366, 0x4367, 0x4368, 0x4369, 0x436A, + 0x436B, 0x436C, 0x436D, 0x436E, 0x436F, 0x4370, 0x4371, 0x4372, 0x4373, + 0x4374, 0x4375, 0x4376, 0x4377, 0x4378, 0x4379, 0x437A, 0x437B, 0x437C, + 0x437D, 0x437E, 0x437F, 0x4380, 0x4381, 0x4382, 0x4383, 0x4384, 0x4385, + 0x4386, 0x4387, 0x4388, 0x4389, 0x438A, 0x438B, 0x438C, 0x438D, 0x438E, + 0x438F, 0x4390, 0x4391, 0x4392, 0x4393, 0x4394, 0x4395, 0x4396, 0x4397, + 0x4398, 0x4399, 0x439A, 0x439B, 0x439C, 0x439D, 0x439E, 0x439F, 0x43A0, + 0x43A1, 0x43A2, 0xFE80, 0x43A3, 0x43A4, 0x43A5, 0x43A6, 0x43A7, 0xFE81, + 0x43A8, 0x43A9, 0x43AA, 0x43AB, 0x43AC, 0x43AD, 0x43AE, 0x43AF, 0x43B0, + 0x43B1, 0x43B2, 0x43B3, 0x43B4, 0x43B5, 0x43B6, 0x43B7, 0x43B8, 0x43B9, + 0x43BA, 0x43BB, 0x43BC, 0x43BD, 0x43BE, 0x43BF, 0x43C0, 0x43C1, 0x43C2, + 0x43C3, 0x43C4, 0x43C5, 0x43C6, 0x43C7, 0x43C8, 0x43C9, 0x43CA, 0x43CB, + 0x43CC, 0x43CD, 0x43CE, 0x43CF, 0x43D0, 0x43D1, 0x43D2, 0x43D3, 0x43D4, + 0x43D5, 0x43D6, 0x43D7, 0x43D8, 0x43D9, 0x43DA, 0x43DB, 0x43DC, 0x43DD, + 0x43DE, 0x43DF, 0x43E0, 0x43E1, 0x43E2, 0x43E3, 0x43E4, 0x43E5, 0x43E6, + 0x43E7, 0x43E8, 0x43E9, 0x43EA, 0x43EB, 0x43EC, 0x43ED, 0x43EE, 0x43EF, + 0x43F0, 0x43F1, 0x43F2, 0x43F3, 0x43F4, 0x43F5, 0x43F6, 0x43F7, 0x43F8, + 0x43F9, 0xFE82, 0x43FA, 0x43FB, 0x43FC, 0x43FD, 0x43FE, 0x43FF, 0x4400, + 0x4401, 0x4402, 0x4403, 0x4404, 0x4405, 0x4406, 0x4407, 0x4408, 0x4409, + 0xFE83, 0x440A, 0x440B, 0x440C, 0x440D, 0x440E, 0x440F, 0x4410, 0x4411, + 0x4412, 0x4413, 0x4414, 0x4415, 0x4416, 0x4417, 0x4418, 0x4419, 0x441A, + 0x441B, 0x441C, 0x441D, 0x441E, 0x441F, 0x4420, 0x4421, 0x4422, 0x4423, + 0x4424, 0x4425, 0x4426, 0x4427, 0x4428, 0x4429, 0x442A, 0x442B, 0x442C, + 0x442D, 0x442E, 0x442F, 0x4430, 0x4431, 0x4432, 0x4433, 0x4434, 0x4435, + 0x4436, 0x4437, 0x4438, 0x4439, 0x443A, 0x443B, 0x443C, 0x443D, 0x443E, + 0x443F, 0x4440, 0x4441, 0x4442, 0x4443, 0x4444, 0x4445, 0x4446, 0x4447, + 0x4448, 0x4449, 0x444A, 0x444B, 0x444C, 0x444D, 0x444E, 0x444F, 0x4450, + 0x4451, 0x4452, 0x4453, 0x4454, 0x4455, 0x4456, 0x4457, 0x4458, 0x4459, + 0x445A, 0x445B, 0x445C, 0x445D, 0x445E, 0x445F, 0x4460, 0x4461, 0x4462, + 0x4463, 0x4464, 0x4465, 0x4466, 0x4467, 0x4468, 0x4469, 0x446A, 0x446B, + 0x446C, 0x446D, 0x446E, 0x446F, 0x4470, 0x4471, 0x4472, 0x4473, 0x4474, + 0x4475, 0x4476, 0x4477, 0x4478, 0x4479, 0x447A, 0x447B, 0x447C, 0x447D, + 0x447E, 0x447F, 0x4480, 0x4481, 0x4482, 0x4483, 0x4484, 0x4485, 0x4486, + 0x4487, 0x4488, 0x4489, 0x448A, 0x448B, 0x448C, 0x448D, 0x448E, 0x448F, + 0x4490, 0x4491, 0x4492, 0x4493, 0x4494, 0x4495, 0x4496, 0x4497, 0x4498, + 0x4499, 0x449A, 0x449B, 0x449C, 0x449D, 0x449E, 0x449F, 0x44A0, 0x44A1, + 0x44A2, 0x44A3, 0x44A4, 0x44A5, 0x44A6, 0x44A7, 0x44A8, 0x44A9, 0x44AA, + 0x44AB, 0x44AC, 0x44AD, 0x44AE, 0x44AF, 0x44B0, 0x44B1, 0x44B2, 0x44B3, + 0x44B4, 0x44B5, 0x44B6, 0x44B7, 0x44B8, 0x44B9, 0x44BA, 0x44BB, 0x44BC, + 0x44BD, 0x44BE, 0x44BF, 0x44C0, 0x44C1, 0x44C2, 0x44C3, 0x44C4, 0x44C5, + 0x44C6, 0x44C7, 0x44C8, 0x44C9, 0x44CA, 0x44CB, 0x44CC, 0x44CD, 0x44CE, + 0x44CF, 0x44D0, 0x44D1, 0x44D2, 0x44D3, 0x44D4, 0x44D5, 0x44D6, 0x44D7, + 0x44D8, 0x44D9, 0x44DA, 0x44DB, 0x44DC, 0x44DD, 0x44DE, 0x44DF, 0x44E0, + 0x44E1, 0x44E2, 0x44E3, 0x44E4, 0x44E5, 0x44E6, 0x44E7, 0x44E8, 0x44E9, + 0x44EA, 0x44EB, 0x44EC, 0x44ED, 0x44EE, 0x44EF, 0x44F0, 0x44F1, 0x44F2, + 0x44F3, 0x44F4, 0x44F5, 0x44F6, 0x44F7, 0x44F8, 0x44F9, 0x44FA, 0x44FB, + 0x44FC, 0x44FD, 0x44FE, 0x44FF, 0x4500, 0x4501, 0x4502, 0x4503, 0x4504, + 0x4505, 0x4506, 0x4507, 0x4508, 0x4509, 0x450A, 0x450B, 0x450C, 0x450D, + 0x450E, 0x450F, 0x4510, 0x4511, 0x4512, 0x4513, 0x4514, 0x4515, 0x4516, + 0x4517, 0x4518, 0x4519, 0x451A, 0x451B, 0x451C, 0x451D, 0x451E, 0x451F, + 0x4520, 0x4521, 0x4522, 0x4523, 0x4524, 0x4525, 0x4526, 0x4527, 0x4528, + 0x4529, 0x452A, 0x452B, 0x452C, 0x452D, 0x452E, 0x452F, 0x4530, 0x4531, + 0x4532, 0x4533, 0x4534, 0x4535, 0x4536, 0x4537, 0x4538, 0x4539, 0x453A, + 0x453B, 0x453C, 0x453D, 0x453E, 0x453F, 0x4540, 0x4541, 0x4542, 0x4543, + 0x4544, 0x4545, 0x4546, 0x4547, 0x4548, 0x4549, 0x454A, 0x454B, 0x454C, + 0x454D, 0x454E, 0x454F, 0x4550, 0x4551, 0x4552, 0x4553, 0x4554, 0x4555, + 0x4556, 0x4557, 0x4558, 0x4559, 0x455A, 0x455B, 0x455C, 0x455D, 0x455E, + 0x455F, 0x4560, 0x4561, 0x4562, 0x4563, 0x4564, 0x4565, 0x4566, 0x4567, + 0x4568, 0x4569, 0x456A, 0x456B, 0x456C, 0x456D, 0x456E, 0x456F, 0x4570, + 0x4571, 0x4572, 0x4573, 0x4574, 0x4575, 0x4576, 0x4577, 0x4578, 0x4579, + 0x457A, 0x457B, 0x457C, 0x457D, 0x457E, 0x457F, 0x4580, 0x4581, 0x4582, + 0x4583, 0x4584, 0x4585, 0x4586, 0x4587, 0x4588, 0x4589, 0x458A, 0x458B, + 0x458C, 0x458D, 0x458E, 0x458F, 0x4590, 0x4591, 0x4592, 0x4593, 0x4594, + 0x4595, 0x4596, 0x4597, 0x4598, 0x4599, 0x459A, 0x459B, 0x459C, 0x459D, + 0x459E, 0x459F, 0x45A0, 0x45A1, 0x45A2, 0x45A3, 0x45A4, 0x45A5, 0x45A6, + 0x45A7, 0x45A8, 0x45A9, 0x45AA, 0x45AB, 0x45AC, 0x45AD, 0x45AE, 0x45AF, + 0x45B0, 0x45B1, 0x45B2, 0x45B3, 0x45B4, 0x45B5, 0x45B6, 0x45B7, 0x45B8, + 0x45B9, 0x45BA, 0x45BB, 0x45BC, 0x45BD, 0x45BE, 0x45BF, 0x45C0, 0x45C1, + 0x45C2, 0xFE85, 0x45C3, 0x45C4, 0x45C5, 0x45C6, 0x45C7, 0x45C8, 0x45C9, + 0x45CA, 0x45CB, 0x45CC, 0x45CD, 0x45CE, 0x45CF, 0x45D0, 0x45D1, 0x45D2, + 0x45D3, 0x45D4, 0x45D5, 0x45D6, 0x45D7, 0x45D8, 0x45D9, 0x45DA, 0x45DB, + 0x45DC, 0x45DD, 0x45DE, 0x45DF, 0x45E0, 0x45E1, 0x45E2, 0x45E3, 0x45E4, + 0x45E5, 0x45E6, 0x45E7, 0x45E8, 0x45E9, 0x45EA, 0x45EB, 0x45EC, 0x45ED, + 0x45EE, 0x45EF, 0x45F0, 0x45F1, 0x45F2, 0x45F3, 0x45F4, 0xFE86, 0x45F5, + 0x45F6, 0xFE87, 0x45F7, 0x45F8, 0x45F9, 0x45FA, 0xFE88, 0xFE89, 0x45FB, + 0xFE8A, 0xFE8B, 0x45FC, 0x45FD, 0x45FE, 0x45FF, 0x4600, 0x4601, 0x4602, + 0x4603, 0x4604, 0x4605, 0x4606, 0x4607, 0x4608, 0x4609, 0x460A, 0x460B, + 0x460C, 0x460D, 0x460E, 0x460F, 0xFE8D, 0x4610, 0x4611, 0x4612, 0xFE8C, + 0x4613, 0x4614, 0x4615, 0x4616, 0x4617, 0x4618, 0x4619, 0x461A, 0x461B, + 0x461C, 0x461D, 0x461E, 0x461F, 0x4620, 0x4621, 0x4622, 0x4623, 0x4624, + 0x4625, 0x4626, 0x4627, 0x4628, 0xFE8F, 0xFE8E, 0x4629, 0x462A, 0x462B, + 0x462C, 0x462D, 0x462E, 0x462F, 0x4630, 0x4631, 0x4632, 0x4633, 0x4634, + 0x4635, 0x4636, 0x4637, 0x4638, 0x4639, 0x463A, 0x463B, 0x463C, 0x463D, + 0x463E, 0x463F, 0x4640, 0x4641, 0x4642, 0x4643, 0x4644, 0x4645, 0x4646, + 0x4647, 0x4648, 0x4649, 0x464A, 0x464B, 0x464C, 0x464D, 0x464E, 0x464F, + 0x4650, 0x4651, 0x4652, 0x4653, 0x4654, 0x4655, 0x4656, 0x4657, 0x4658, + 0x4659, 0x465A, 0x465B, 0x465C, 0x465D, 0x465E, 0x465F, 0x4660, 0x4661, + 0x4662, 0x4663, 0x4664, 0x4665, 0x4666, 0x4667, 0x4668, 0x4669, 0x466A, + 0x466B, 0x466C, 0x466D, 0x466E, 0x466F, 0x4670, 0x4671, 0x4672, 0x4673, + 0x4674, 0x4675, 0x4676, 0x4677, 0x4678, 0x4679, 0x467A, 0x467B, 0x467C, + 0x467D, 0x467E, 0x467F, 0x4680, 0x4681, 0x4682, 0x4683, 0x4684, 0x4685, + 0x4686, 0x4687, 0x4688, 0x4689, 0x468A, 0x468B, 0x468C, 0x468D, 0x468E, + 0x468F, 0x4690, 0x4691, 0x4692, 0x4693, 0x4694, 0x4695, 0x4696, 0x4697, + 0x4698, 0x4699, 0x469A, 0x469B, 0x469C, 0x469D, 0x469E, 0x469F, 0x46A0, + 0x46A1, 0x46A2, 0x46A3, 0x46A4, 0x46A5, 0x46A6, 0x46A7, 0x46A8, 0x46A9, + 0x46AA, 0x46AB, 0x46AC, 0x46AD, 0x46AE, 0x46AF, 0x46B0, 0x46B1, 0x46B2, + 0x46B3, 0x46B4, 0x46B5, 0x46B6, 0x46B7, 0x46B8, 0x46B9, 0x46BA, 0x46BB, + 0x46BC, 0x46BD, 0x46BE, 0x46BF, 0x46C0, 0x46C1, 0x46C2, 0x46C3, 0x46C4, + 0x46C5, 0x46C6, 0x46C7, 0x46C8, 0x46C9, 0x46CA, 0x46CB, 0x46CC, 0x46CD, + 0x46CE, 0x46CF, 0x46D0, 0x46D1, 0x46D2, 0x46D3, 0x46D4, 0x46D5, 0x46D6, + 0x46D7, 0x46D8, 0x46D9, 0x46DA, 0x46DB, 0x46DC, 0x46DD, 0x46DE, 0x46DF, + 0x46E0, 0x46E1, 0x46E2, 0x46E3, 0x46E4, 0x46E5, 0x46E6, 0x46E7, 0x46E8, + 0x46E9, 0x46EA, 0x46EB, 0x46EC, 0x46ED, 0x46EE, 0x46EF, 0x46F0, 0x46F1, + 0x46F2, 0x46F3, 0x46F4, 0x46F5, 0x46F6, 0x46F7, 0x46F8, 0x46F9, 0x46FA, + 0x46FB, 0x46FC, 0x46FD, 0x46FE, 0x46FF, 0x4700, 0x4701, 0x4702, 0x4703, + 0x4704, 0x4705, 0x4706, 0x4707, 0x4708, 0x4709, 0x470A, 0x470B, 0x470C, + 0x470D, 0x470E, 0x470F, 0x4710, 0x4711, 0x4712, 0x4713, 0x4714, 0x4715, + 0x4716, 0x4717, 0x4718, 0x4719, 0x471A, 0x471B, 0x471C, 0x471D, 0x471E, + 0x471F, 0x4720, 0x4721, 0x4722, 0x4723, 0x4724, 0x4725, 0x4726, 0x4727, + 0x4728, 0x4729, 0x472A, 0x472B, 0x472C, 0x472D, 0x472E, 0x472F, 0x4730, + 0x4731, 0x4732, 0x4733, 0x4734, 0x4735, 0x4736, 0x4737, 0x4738, 0x4739, + 0x473A, 0x473B, 0x473C, 0x473D, 0x473E, 0x473F, 0x4740, 0x4741, 0x4742, + 0x4743, 0x4744, 0x4745, 0x4746, 0x4747, 0x4748, 0x4749, 0x474A, 0x474B, + 0x474C, 0x474D, 0x474E, 0x474F, 0x4750, 0x4751, 0x4752, 0x4753, 0x4754, + 0x4755, 0x4756, 0x4757, 0x4758, 0x4759, 0x475A, 0x475B, 0x475C, 0x475D, + 0x475E, 0x475F, 0x4760, 0x4761, 0x4762, 0x4763, 0x4764, 0x4765, 0x4766, + 0x4767, 0x4768, 0x4769, 0x476A, 0x476B, 0x476C, 0x476D, 0x476E, 0x476F, + 0x4770, 0x4771, 0x4772, 0x4773, 0x4774, 0x4775, 0x4776, 0x4777, 0x4778, + 0x4779, 0x477A, 0x477B, 0x477C, 0x477D, 0x477E, 0x477F, 0x4780, 0x4781, + 0x4782, 0x4783, 0x4784, 0x4785, 0x4786, 0x4787, 0x4788, 0x4789, 0x478A, + 0x478B, 0x478C, 0x478D, 0x478E, 0x478F, 0x4790, 0x4791, 0x4792, 0x4793, + 0x4794, 0x4795, 0x4796, 0x4797, 0x4798, 0x4799, 0x479A, 0x479B, 0x479C, + 0x479D, 0x479E, 0x479F, 0x47A0, 0x47A1, 0x47A2, 0x47A3, 0x47A4, 0x47A5, + 0x47A6, 0x47A7, 0x47A8, 0x47A9, 0x47AA, 0x47AB, 0x47AC, 0x47AD, 0x47AE, + 0x47AF, 0x47B0, 0x47B1, 0x47B2, 0x47B3, 0x47B4, 0x47B5, 0x47B6, 0x47B7, + 0x47B8, 0x47B9, 0x47BA, 0x47BB, 0x47BC, 0x47BD, 0x47BE, 0x47BF, 0x47C0, + 0x47C1, 0x47C2, 0x47C3, 0x47C4, 0x47C5, 0x47C6, 0x47C7, 0x47C8, 0x47C9, + 0x47CA, 0x47CB, 0x47CC, 0x47CD, 0x47CE, 0x47CF, 0x47D0, 0x47D1, 0x47D2, + 0x47D3, 0x47D4, 0x47D5, 0x47D6, 0x47D7, 0x47D8, 0x47D9, 0x47DA, 0x47DB, + 0x47DC, 0x47DD, 0x47DE, 0x47DF, 0x47E0, 0x47E1, 0x47E2, 0x47E3, 0x47E4, + 0x47E5, 0x47E6, 0x47E7, 0x47E8, 0x47E9, 0x47EA, 0x47EB, 0x47EC, 0x47ED, + 0x47EE, 0x47EF, 0x47F0, 0x47F1, 0x47F2, 0x47F3, 0x47F4, 0x47F5, 0x47F6, + 0x47F7, 0x47F8, 0x47F9, 0x47FA, 0x47FB, 0x47FC, 0x47FD, 0x47FE, 0x47FF, + 0x4800, 0x4801, 0x4802, 0x4803, 0x4804, 0x4805, 0x4806, 0x4807, 0x4808, + 0x4809, 0x480A, 0x480B, 0x480C, 0x480D, 0x480E, 0x480F, 0x4810, 0x4811, + 0x4812, 0x4813, 0x4814, 0x4815, 0x4816, 0x4817, 0x4818, 0x4819, 0x481A, + 0x481B, 0x481C, 0x481D, 0x481E, 0x481F, 0x4820, 0x4821, 0x4822, 0x4823, + 0x4824, 0x4825, 0x4826, 0x4827, 0x4828, 0x4829, 0x482A, 0x482B, 0x482C, + 0x482D, 0x482E, 0x482F, 0x4830, 0x4831, 0x4832, 0x4833, 0x4834, 0x4835, + 0x4836, 0x4837, 0x4838, 0x4839, 0x483A, 0x483B, 0x483C, 0x483D, 0x483E, + 0x483F, 0x4840, 0x4841, 0x4842, 0x4843, 0x4844, 0x4845, 0x4846, 0x4847, + 0x4848, 0x4849, 0x484A, 0x484B, 0x484C, 0x484D, 0x484E, 0x484F, 0x4850, + 0x4851, 0x4852, 0x4853, 0x4854, 0x4855, 0x4856, 0x4857, 0x4858, 0x4859, + 0x485A, 0x485B, 0x485C, 0x485D, 0x485E, 0x485F, 0x4860, 0x4861, 0x4862, + 0x4863, 0x4864, 0x4865, 0x4866, 0x4867, 0x4868, 0x4869, 0x486A, 0x486B, + 0x486C, 0x486D, 0x486E, 0x486F, 0x4870, 0x4871, 0x4872, 0x4873, 0x4874, + 0x4875, 0x4876, 0x4877, 0x4878, 0x4879, 0x487A, 0x487B, 0x487C, 0x487D, + 0x487E, 0x487F, 0x4880, 0x4881, 0x4882, 0x4883, 0x4884, 0x4885, 0x4886, + 0x4887, 0x4888, 0x4889, 0x488A, 0x488B, 0x488C, 0x488D, 0x488E, 0x488F, + 0x4890, 0x4891, 0x4892, 0x4893, 0x4894, 0x4895, 0x4896, 0x4897, 0x4898, + 0x4899, 0x489A, 0x489B, 0x489C, 0x489D, 0x489E, 0x489F, 0x48A0, 0x48A1, + 0x48A2, 0x48A3, 0x48A4, 0x48A5, 0x48A6, 0x48A7, 0x48A8, 0x48A9, 0x48AA, + 0x48AB, 0x48AC, 0x48AD, 0x48AE, 0x48AF, 0x48B0, 0x48B1, 0x48B2, 0x48B3, + 0x48B4, 0x48B5, 0x48B6, 0x48B7, 0x48B8, 0x48B9, 0x48BA, 0x48BB, 0x48BC, + 0x48BD, 0x48BE, 0x48BF, 0x48C0, 0x48C1, 0x48C2, 0x48C3, 0x48C4, 0x48C5, + 0x48C6, 0x48C7, 0x48C8, 0x48C9, 0x48CA, 0x48CB, 0x48CC, 0x48CD, 0x48CE, + 0x48CF, 0x48D0, 0x48D1, 0x48D2, 0x48D3, 0x48D4, 0x48D5, 0x48D6, 0x48D7, + 0x48D8, 0x48D9, 0x48DA, 0x48DB, 0x48DC, 0x48DD, 0x48DE, 0x48DF, 0x48E0, + 0x48E1, 0x48E2, 0x48E3, 0x48E4, 0x48E5, 0x48E6, 0x48E7, 0xFE96, 0x48E8, + 0x48E9, 0x48EA, 0x48EB, 0x48EC, 0x48ED, 0x48EE, 0x48EF, 0x48F0, 0x48F1, + 0x48F2, 0x48F3, 0x48F4, 0x48F5, 0x48F6, 0x48F7, 0x48F8, 0x48F9, 0x48FA, + 0x48FB, 0x48FC, 0x48FD, 0x48FE, 0x48FF, 0x4900, 0x4901, 0x4902, 0x4903, + 0x4904, 0x4905, 0x4906, 0x4907, 0x4908, 0x4909, 0x490A, 0x490B, 0x490C, + 0x490D, 0x490E, 0xFE93, 0xFE94, 0xFE95, 0xFE97, 0xFE92, 0x490F, 0x4910, + 0x4911, 0x4912, 0x4913, 0x4914, 0x4915, 0x4916, 0x4917, 0x4918, 0x4919, + 0x491A, 0x491B, 0x491C, 0x491D, 0x491E, 0x491F, 0x4920, 0x4921, 0x4922, + 0x4923, 0x4924, 0x4925, 0x4926, 0x4927, 0x4928, 0x4929, 0x492A, 0x492B, + 0x492C, 0x492D, 0x492E, 0x492F, 0x4930, 0x4931, 0x4932, 0x4933, 0x4934, + 0x4935, 0x4936, 0x4937, 0x4938, 0x4939, 0x493A, 0x493B, 0x493C, 0x493D, + 0x493E, 0x493F, 0x4940, 0x4941, 0x4942, 0x4943, 0x4944, 0x4945, 0x4946, + 0x4947, 0x4948, 0x4949, 0x494A, 0x494B, 0x494C, 0x494D, 0x494E, 0x494F, + 0x4950, 0x4951, 0x4952, 0x4953, 0x4954, 0x4955, 0x4956, 0x4957, 0x4958, + 0x4959, 0x495A, 0x495B, 0x495C, 0x495D, 0x495E, 0x495F, 0x4960, 0x4961, + 0x4962, 0x4963, 0x4964, 0x4965, 0x4966, 0x4967, 0x4968, 0x4969, 0x496A, + 0x496B, 0x496C, 0x496D, 0x496E, 0x496F, 0x4970, 0x4971, 0x4972, 0x4973, + 0x4974, 0x4975, 0x4976, 0x4977, 0x4978, 0x4979, 0x497A, 0x497B, 0x497C, + 0x497D, 0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E, 0x497E, + 0x497F, 0x4980, 0x4981, 0x4982, 0x4983, 0x4984, 0x4985, 0x4986, 0x4987, + 0x4988, 0x4989, 0x498A, 0x498B, 0x498C, 0x498D, 0x498E, 0x498F, 0x4990, + 0x4991, 0x4992, 0x4993, 0x4994, 0x4995, 0x4996, 0x4997, 0x4998, 0x4999, + 0x499A, 0x499B, 0x499C, 0x499D, 0x499E, 0x499F, 0x49A0, 0x49A1, 0x49A2, + 0x49A3, 0x49A4, 0x49A5, 0x49A6, 0x49A7, 0x49A8, 0x49A9, 0x49AA, 0x49AB, + 0x49AC, 0x49AD, 0x49AE, 0x49AF, 0x49B0, 0x49B1, 0x49B2, 0x49B3, 0x49B4, + 0x49B5, 0x49B6, 0x49B7, 0x49B8, 0x49B9, 0x49BA, 0x49BB, 0x49BC, 0x49BD, + 0x49BE, 0x49BF, 0x49C0, 0x49C1, 0x49C2, 0x49C3, 0x49C4, 0x49C5, 0x49C6, + 0x49C7, 0x49C8, 0x49C9, 0x49CA, 0x49CB, 0x49CC, 0x49CD, 0x49CE, 0x49CF, + 0x49D0, 0x49D1, 0x49D2, 0x49D3, 0x49D4, 0x49D5, 0x49D6, 0x49D7, 0x49D8, + 0x49D9, 0x49DA, 0x49DB, 0x49DC, 0x49DD, 0x49DE, 0x49DF, 0x49E0, 0x49E1, + 0x49E2, 0x49E3, 0x49E4, 0x49E5, 0x49E6, 0x49E7, 0x49E8, 0x49E9, 0x49EA, + 0x49EB, 0x49EC, 0x49ED, 0x49EE, 0x49EF, 0x49F0, 0x49F1, 0x49F2, 0x49F3, + 0x49F4, 0x49F5, 0x49F6, 0x49F7, 0x49F8, 0x49F9, 0x49FA, 0x49FB, 0x49FC, + 0x49FD, 0x49FE, 0x49FF, 0x4A00, 0x4A01, 0x4A02, 0x4A03, 0x4A04, 0x4A05, + 0x4A06, 0x4A07, 0x4A08, 0x4A09, 0x4A0A, 0x4A0B, 0x4A0C, 0x4A0D, 0x4A0E, + 0x4A0F, 0x4A10, 0x4A11, 0xFE9F, 0x4A12, 0x4A13, 0x4A14, 0x4A15, 0x4A16, + 0x4A17, 0x4A18, 0x4A19, 0x4A1A, 0x4A1B, 0x4A1C, 0x4A1D, 0x4A1E, 0x4A1F, + 0x4A20, 0x4A21, 0x4A22, 0x4A23, 0x4A24, 0x4A25, 0x4A26, 0x4A27, 0x4A28, + 0x4A29, 0x4A2A, 0x4A2B, 0x4A2C, 0x4A2D, 0x4A2E, 0x4A2F, 0x4A30, 0x4A31, + 0x4A32, 0x4A33, 0x4A34, 0x4A35, 0x4A36, 0x4A37, 0x4A38, 0x4A39, 0x4A3A, + 0x4A3B, 0x4A3C, 0x4A3D, 0x4A3E, 0x4A3F, 0x4A40, 0x4A41, 0x4A42, 0x4A43, + 0x4A44, 0x4A45, 0x4A46, 0x4A47, 0x4A48, 0x4A49, 0x4A4A, 0x4A4B, 0x4A4C, + 0x4A4D, 0x4A4E, 0x4A4F, 0x4A50, 0x4A51, 0x4A52, 0x4A53, 0x4A54, 0x4A55, + 0x4A56, 0x4A57, 0x4A58, 0x4A59, 0x4A5A, 0x4A5B, 0x4A5C, 0x4A5D, 0x4A5E, + 0x4A5F, 0x4A60, 0x4A61, 0x4A62, 0xD2BB, 0xB6A1, 0x8140, 0xC6DF, 0x8141, + 0x8142, 0x8143, 0xCDF2, 0xD5C9, 0xC8FD, 0xC9CF, 0xCFC2, 0xD8A2, 0xB2BB, + 0xD3EB, 0x8144, 0xD8A4, 0xB3F3, 0x8145, 0xD7A8, 0xC7D2, 0xD8A7, 0xCAC0, + 0x8146, 0xC7F0, 0xB1FB, 0xD2B5, 0xB4D4, 0xB6AB, 0xCBBF, 0xD8A9, 0x8147, + 0x8148, 0x8149, 0xB6AA, 0x814A, 0xC1BD, 0xD1CF, 0x814B, 0xC9A5, 0xD8AD, + 0x814C, 0xB8F6, 0xD1BE, 0xE3DC, 0xD6D0, 0x814D, 0x814E, 0xB7E1, 0x814F, + 0xB4AE, 0x8150, 0xC1D9, 0x8151, 0xD8BC, 0x8152, 0xCDE8, 0xB5A4, 0xCEAA, + 0xD6F7, 0x8153, 0xC0F6, 0xBED9, 0xD8AF, 0x8154, 0x8155, 0x8156, 0xC4CB, + 0x8157, 0xBEC3, 0x8158, 0xD8B1, 0xC3B4, 0xD2E5, 0x8159, 0xD6AE, 0xCEDA, + 0xD5A7, 0xBAF5, 0xB7A6, 0xC0D6, 0x815A, 0xC6B9, 0xC5D2, 0xC7C7, 0x815B, + 0xB9D4, 0x815C, 0xB3CB, 0xD2D2, 0x815D, 0x815E, 0xD8BF, 0xBEC5, 0xC6F2, + 0xD2B2, 0xCFB0, 0xCFE7, 0x815F, 0x8160, 0x8161, 0x8162, 0xCAE9, 0x8163, + 0x8164, 0xD8C0, 0x8165, 0x8166, 0x8167, 0x8168, 0x8169, 0x816A, 0xC2F2, + 0xC2D2, 0x816B, 0xC8E9, 0x816C, 0x816D, 0x816E, 0x816F, 0x8170, 0x8171, + 0x8172, 0x8173, 0x8174, 0x8175, 0xC7AC, 0x8176, 0x8177, 0x8178, 0x8179, + 0x817A, 0x817B, 0x817C, 0xC1CB, 0x817D, 0xD3E8, 0xD5F9, 0x817E, 0xCAC2, + 0xB6FE, 0xD8A1, 0xD3DA, 0xBFF7, 0x8180, 0xD4C6, 0xBBA5, 0xD8C1, 0xCEE5, + 0xBEAE, 0x8181, 0x8182, 0xD8A8, 0x8183, 0xD1C7, 0xD0A9, 0x8184, 0x8185, + 0x8186, 0xD8BD, 0xD9EF, 0xCDF6, 0xBFBA, 0x8187, 0xBDBB, 0xBAA5, 0xD2E0, + 0xB2FA, 0xBAE0, 0xC4B6, 0x8188, 0xCFED, 0xBEA9, 0xCDA4, 0xC1C1, 0x8189, + 0x818A, 0x818B, 0xC7D7, 0xD9F1, 0x818C, 0xD9F4, 0x818D, 0x818E, 0x818F, + 0x8190, 0xC8CB, 0xD8E9, 0x8191, 0x8192, 0x8193, 0xD2DA, 0xCAB2, 0xC8CA, + 0xD8EC, 0xD8EA, 0xD8C6, 0xBDF6, 0xC6CD, 0xB3F0, 0x8194, 0xD8EB, 0xBDF1, + 0xBDE9, 0x8195, 0xC8D4, 0xB4D3, 0x8196, 0x8197, 0xC2D8, 0x8198, 0xB2D6, + 0xD7D0, 0xCACB, 0xCBFB, 0xD5CC, 0xB8B6, 0xCFC9, 0x8199, 0x819A, 0x819B, + 0xD9DA, 0xD8F0, 0xC7AA, 0x819C, 0xD8EE, 0x819D, 0xB4FA, 0xC1EE, 0xD2D4, + 0x819E, 0x819F, 0xD8ED, 0x81A0, 0xD2C7, 0xD8EF, 0xC3C7, 0x81A1, 0x81A2, + 0x81A3, 0xD1F6, 0x81A4, 0xD6D9, 0xD8F2, 0x81A5, 0xD8F5, 0xBCFE, 0xBCDB, + 0x81A6, 0x81A7, 0x81A8, 0xC8CE, 0x81A9, 0xB7DD, 0x81AA, 0xB7C2, 0x81AB, + 0xC6F3, 0x81AC, 0x81AD, 0x81AE, 0x81AF, 0x81B0, 0x81B1, 0x81B2, 0xD8F8, + 0xD2C1, 0x81B3, 0x81B4, 0xCEE9, 0xBCBF, 0xB7FC, 0xB7A5, 0xD0DD, 0x81B5, + 0x81B6, 0x81B7, 0x81B8, 0x81B9, 0xD6DA, 0xD3C5, 0xBBEF, 0xBBE1, 0xD8F1, + 0x81BA, 0x81BB, 0xC9A1, 0xCEB0, 0xB4AB, 0x81BC, 0xD8F3, 0x81BD, 0xC9CB, + 0xD8F6, 0xC2D7, 0xD8F7, 0x81BE, 0x81BF, 0xCEB1, 0xD8F9, 0x81C0, 0x81C1, + 0x81C2, 0xB2AE, 0xB9C0, 0x81C3, 0xD9A3, 0x81C4, 0xB0E9, 0x81C5, 0xC1E6, + 0x81C6, 0xC9EC, 0x81C7, 0xCBC5, 0x81C8, 0xCBC6, 0xD9A4, 0x81C9, 0x81CA, + 0x81CB, 0x81CC, 0x81CD, 0xB5E8, 0x81CE, 0x81CF, 0xB5AB, 0x81D0, 0x81D1, + 0x81D2, 0x81D3, 0x81D4, 0x81D5, 0xCEBB, 0xB5CD, 0xD7A1, 0xD7F4, 0xD3D3, + 0x81D6, 0xCCE5, 0x81D7, 0xBACE, 0x81D8, 0xD9A2, 0xD9DC, 0xD3E0, 0xD8FD, + 0xB7F0, 0xD7F7, 0xD8FE, 0xD8FA, 0xD9A1, 0xC4E3, 0x81D9, 0x81DA, 0xD3B6, + 0xD8F4, 0xD9DD, 0x81DB, 0xD8FB, 0x81DC, 0xC5E5, 0x81DD, 0x81DE, 0xC0D0, + 0x81DF, 0x81E0, 0xD1F0, 0xB0DB, 0x81E1, 0x81E2, 0xBCD1, 0xD9A6, 0x81E3, + 0xD9A5, 0x81E4, 0x81E5, 0x81E6, 0x81E7, 0xD9AC, 0xD9AE, 0x81E8, 0xD9AB, + 0xCAB9, 0x81E9, 0x81EA, 0x81EB, 0xD9A9, 0xD6B6, 0x81EC, 0x81ED, 0x81EE, + 0xB3DE, 0xD9A8, 0x81EF, 0xC0FD, 0x81F0, 0xCACC, 0x81F1, 0xD9AA, 0x81F2, + 0xD9A7, 0x81F3, 0x81F4, 0xD9B0, 0x81F5, 0x81F6, 0xB6B1, 0x81F7, 0x81F8, + 0x81F9, 0xB9A9, 0x81FA, 0xD2C0, 0x81FB, 0x81FC, 0xCFC0, 0x81FD, 0x81FE, + 0xC2C2, 0x8240, 0xBDC4, 0xD5EC, 0xB2E0, 0xC7C8, 0xBFEB, 0xD9AD, 0x8241, + 0xD9AF, 0x8242, 0xCEEA, 0xBAEE, 0x8243, 0x8244, 0x8245, 0x8246, 0x8247, + 0xC7D6, 0x8248, 0x8249, 0x824A, 0x824B, 0x824C, 0x824D, 0x824E, 0x824F, + 0x8250, 0xB1E3, 0x8251, 0x8252, 0x8253, 0xB4D9, 0xB6ED, 0xD9B4, 0x8254, + 0x8255, 0x8256, 0x8257, 0xBFA1, 0x8258, 0x8259, 0x825A, 0xD9DE, 0xC7CE, + 0xC0FE, 0xD9B8, 0x825B, 0x825C, 0x825D, 0x825E, 0x825F, 0xCBD7, 0xB7FD, + 0x8260, 0xD9B5, 0x8261, 0xD9B7, 0xB1A3, 0xD3E1, 0xD9B9, 0x8262, 0xD0C5, + 0x8263, 0xD9B6, 0x8264, 0x8265, 0xD9B1, 0x8266, 0xD9B2, 0xC1A9, 0xD9B3, + 0x8267, 0x8268, 0xBCF3, 0xD0DE, 0xB8A9, 0x8269, 0xBEE3, 0x826A, 0xD9BD, + 0x826B, 0x826C, 0x826D, 0x826E, 0xD9BA, 0x826F, 0xB0B3, 0x8270, 0x8271, + 0x8272, 0xD9C2, 0x8273, 0x8274, 0x8275, 0x8276, 0x8277, 0x8278, 0x8279, + 0x827A, 0x827B, 0x827C, 0x827D, 0x827E, 0x8280, 0xD9C4, 0xB1B6, 0x8281, + 0xD9BF, 0x8282, 0x8283, 0xB5B9, 0x8284, 0xBEF3, 0x8285, 0x8286, 0x8287, + 0xCCC8, 0xBAF2, 0xD2D0, 0x8288, 0xD9C3, 0x8289, 0x828A, 0xBDE8, 0x828B, + 0xB3AB, 0x828C, 0x828D, 0x828E, 0xD9C5, 0xBEEB, 0x828F, 0xD9C6, 0xD9BB, + 0xC4DF, 0x8290, 0xD9BE, 0xD9C1, 0xD9C0, 0x8291, 0x8292, 0x8293, 0x8294, + 0x8295, 0x8296, 0x8297, 0x8298, 0x8299, 0x829A, 0x829B, 0xD5AE, 0x829C, + 0xD6B5, 0x829D, 0xC7E3, 0x829E, 0x829F, 0x82A0, 0x82A1, 0xD9C8, 0x82A2, + 0x82A3, 0x82A4, 0xBCD9, 0xD9CA, 0x82A5, 0x82A6, 0x82A7, 0xD9BC, 0x82A8, + 0xD9CB, 0xC6AB, 0x82A9, 0x82AA, 0x82AB, 0x82AC, 0x82AD, 0xD9C9, 0x82AE, + 0x82AF, 0x82B0, 0x82B1, 0xD7F6, 0x82B2, 0xCDA3, 0x82B3, 0x82B4, 0x82B5, + 0x82B6, 0x82B7, 0x82B8, 0x82B9, 0x82BA, 0xBDA1, 0x82BB, 0x82BC, 0x82BD, + 0x82BE, 0x82BF, 0x82C0, 0xD9CC, 0x82C1, 0x82C2, 0x82C3, 0x82C4, 0x82C5, + 0x82C6, 0x82C7, 0x82C8, 0x82C9, 0xC5BC, 0xCDB5, 0x82CA, 0x82CB, 0x82CC, + 0xD9CD, 0x82CD, 0x82CE, 0xD9C7, 0xB3A5, 0xBFFE, 0x82CF, 0x82D0, 0x82D1, + 0x82D2, 0xB8B5, 0x82D3, 0x82D4, 0xC0FC, 0x82D5, 0x82D6, 0x82D7, 0x82D8, + 0xB0F8, 0x82D9, 0x82DA, 0x82DB, 0x82DC, 0x82DD, 0x82DE, 0x82DF, 0x82E0, + 0x82E1, 0x82E2, 0x82E3, 0x82E4, 0x82E5, 0x82E6, 0x82E7, 0x82E8, 0x82E9, + 0x82EA, 0x82EB, 0x82EC, 0x82ED, 0xB4F6, 0x82EE, 0xD9CE, 0x82EF, 0xD9CF, + 0xB4A2, 0xD9D0, 0x82F0, 0x82F1, 0xB4DF, 0x82F2, 0x82F3, 0x82F4, 0x82F5, + 0x82F6, 0xB0C1, 0x82F7, 0x82F8, 0x82F9, 0x82FA, 0x82FB, 0x82FC, 0x82FD, + 0xD9D1, 0xC9B5, 0x82FE, 0x8340, 0x8341, 0x8342, 0x8343, 0x8344, 0x8345, + 0x8346, 0x8347, 0x8348, 0x8349, 0x834A, 0x834B, 0x834C, 0x834D, 0x834E, + 0x834F, 0x8350, 0x8351, 0xCFF1, 0x8352, 0x8353, 0x8354, 0x8355, 0x8356, + 0x8357, 0xD9D2, 0x8358, 0x8359, 0x835A, 0xC1C5, 0x835B, 0x835C, 0x835D, + 0x835E, 0x835F, 0x8360, 0x8361, 0x8362, 0x8363, 0x8364, 0x8365, 0xD9D6, + 0xC9AE, 0x8366, 0x8367, 0x8368, 0x8369, 0xD9D5, 0xD9D4, 0xD9D7, 0x836A, + 0x836B, 0x836C, 0x836D, 0xCBDB, 0x836E, 0xBDA9, 0x836F, 0x8370, 0x8371, + 0x8372, 0x8373, 0xC6A7, 0x8374, 0x8375, 0x8376, 0x8377, 0x8378, 0x8379, + 0x837A, 0x837B, 0x837C, 0x837D, 0xD9D3, 0xD9D8, 0x837E, 0x8380, 0x8381, + 0xD9D9, 0x8382, 0x8383, 0x8384, 0x8385, 0x8386, 0x8387, 0xC8E5, 0x8388, + 0x8389, 0x838A, 0x838B, 0x838C, 0x838D, 0x838E, 0x838F, 0x8390, 0x8391, + 0x8392, 0x8393, 0x8394, 0x8395, 0xC0DC, 0x8396, 0x8397, 0x8398, 0x8399, + 0x839A, 0x839B, 0x839C, 0x839D, 0x839E, 0x839F, 0x83A0, 0x83A1, 0x83A2, + 0x83A3, 0x83A4, 0x83A5, 0x83A6, 0x83A7, 0x83A8, 0x83A9, 0x83AA, 0x83AB, + 0x83AC, 0x83AD, 0x83AE, 0x83AF, 0x83B0, 0x83B1, 0x83B2, 0xB6F9, 0xD8A3, + 0xD4CA, 0x83B3, 0xD4AA, 0xD0D6, 0xB3E4, 0xD5D7, 0x83B4, 0xCFC8, 0xB9E2, + 0x83B5, 0xBFCB, 0x83B6, 0xC3E2, 0x83B7, 0x83B8, 0x83B9, 0xB6D2, 0x83BA, + 0x83BB, 0xCDC3, 0xD9EE, 0xD9F0, 0x83BC, 0x83BD, 0x83BE, 0xB5B3, 0x83BF, + 0xB6B5, 0x83C0, 0x83C1, 0x83C2, 0x83C3, 0x83C4, 0xBEA4, 0x83C5, 0x83C6, + 0xC8EB, 0x83C7, 0x83C8, 0xC8AB, 0x83C9, 0x83CA, 0xB0CB, 0xB9AB, 0xC1F9, + 0xD9E2, 0x83CB, 0xC0BC, 0xB9B2, 0x83CC, 0xB9D8, 0xD0CB, 0xB1F8, 0xC6E4, + 0xBEDF, 0xB5E4, 0xD7C8, 0x83CD, 0xD1F8, 0xBCE6, 0xCADE, 0x83CE, 0x83CF, + 0xBCBD, 0xD9E6, 0xD8E7, 0x83D0, 0x83D1, 0xC4DA, 0x83D2, 0x83D3, 0xB8D4, + 0xC8BD, 0x83D4, 0x83D5, 0xB2E1, 0xD4D9, 0x83D6, 0x83D7, 0x83D8, 0x83D9, + 0xC3B0, 0x83DA, 0x83DB, 0xC3E1, 0xDAA2, 0xC8DF, 0x83DC, 0xD0B4, 0x83DD, + 0xBEFC, 0xC5A9, 0x83DE, 0x83DF, 0x83E0, 0xB9DA, 0x83E1, 0xDAA3, 0x83E2, + 0xD4A9, 0xDAA4, 0x83E3, 0x83E4, 0x83E5, 0x83E6, 0x83E7, 0xD9FB, 0xB6AC, + 0x83E8, 0x83E9, 0xB7EB, 0xB1F9, 0xD9FC, 0xB3E5, 0xBEF6, 0x83EA, 0xBFF6, + 0xD2B1, 0xC0E4, 0x83EB, 0x83EC, 0x83ED, 0xB6B3, 0xD9FE, 0xD9FD, 0x83EE, + 0x83EF, 0xBEBB, 0x83F0, 0x83F1, 0x83F2, 0xC6E0, 0x83F3, 0xD7BC, 0xDAA1, + 0x83F4, 0xC1B9, 0x83F5, 0xB5F2, 0xC1E8, 0x83F6, 0x83F7, 0xBCF5, 0x83F8, + 0xB4D5, 0x83F9, 0x83FA, 0x83FB, 0x83FC, 0x83FD, 0x83FE, 0x8440, 0x8441, + 0x8442, 0xC1DD, 0x8443, 0xC4FD, 0x8444, 0x8445, 0xBCB8, 0xB7B2, 0x8446, + 0x8447, 0xB7EF, 0x8448, 0x8449, 0x844A, 0x844B, 0x844C, 0x844D, 0xD9EC, + 0x844E, 0xC6BE, 0x844F, 0xBFAD, 0xBBCB, 0x8450, 0x8451, 0xB5CA, 0x8452, + 0xDBC9, 0xD0D7, 0x8453, 0xCDB9, 0xB0BC, 0xB3F6, 0xBBF7, 0xDBCA, 0xBAAF, + 0x8454, 0xD4E4, 0xB5B6, 0xB5F3, 0xD8D6, 0xC8D0, 0x8455, 0x8456, 0xB7D6, + 0xC7D0, 0xD8D7, 0x8457, 0xBFAF, 0x8458, 0x8459, 0xDBBB, 0xD8D8, 0x845A, + 0x845B, 0xD0CC, 0xBBAE, 0x845C, 0x845D, 0x845E, 0xEBBE, 0xC1D0, 0xC1F5, + 0xD4F2, 0xB8D5, 0xB4B4, 0x845F, 0xB3F5, 0x8460, 0x8461, 0xC9BE, 0x8462, + 0x8463, 0x8464, 0xC5D0, 0x8465, 0x8466, 0x8467, 0xC5D9, 0xC0FB, 0x8468, + 0xB1F0, 0x8469, 0xD8D9, 0xB9CE, 0x846A, 0xB5BD, 0x846B, 0x846C, 0xD8DA, + 0x846D, 0x846E, 0xD6C6, 0xCBA2, 0xC8AF, 0xC9B2, 0xB4CC, 0xBFCC, 0x846F, + 0xB9F4, 0x8470, 0xD8DB, 0xD8DC, 0xB6E7, 0xBCC1, 0xCCEA, 0x8471, 0x8472, + 0x8473, 0x8474, 0x8475, 0x8476, 0xCFF7, 0x8477, 0xD8DD, 0xC7B0, 0x8478, + 0x8479, 0xB9D0, 0xBDA3, 0x847A, 0x847B, 0xCCDE, 0x847C, 0xC6CA, 0x847D, + 0x847E, 0x8480, 0x8481, 0x8482, 0xD8E0, 0x8483, 0xD8DE, 0x8484, 0x8485, + 0xD8DF, 0x8486, 0x8487, 0x8488, 0xB0FE, 0x8489, 0xBEE7, 0x848A, 0xCAA3, + 0xBCF4, 0x848B, 0x848C, 0x848D, 0x848E, 0xB8B1, 0x848F, 0x8490, 0xB8EE, + 0x8491, 0x8492, 0x8493, 0x8494, 0x8495, 0x8496, 0x8497, 0x8498, 0x8499, + 0x849A, 0xD8E2, 0x849B, 0xBDCB, 0x849C, 0xD8E4, 0xD8E3, 0x849D, 0x849E, + 0x849F, 0x84A0, 0x84A1, 0xC5FC, 0x84A2, 0x84A3, 0x84A4, 0x84A5, 0x84A6, + 0x84A7, 0x84A8, 0xD8E5, 0x84A9, 0x84AA, 0xD8E6, 0x84AB, 0x84AC, 0x84AD, + 0x84AE, 0x84AF, 0x84B0, 0x84B1, 0xC1A6, 0x84B2, 0xC8B0, 0xB0EC, 0xB9A6, + 0xBCD3, 0xCEF1, 0xDBBD, 0xC1D3, 0x84B3, 0x84B4, 0x84B5, 0x84B6, 0xB6AF, + 0xD6FA, 0xC5AC, 0xBDD9, 0xDBBE, 0xDBBF, 0x84B7, 0x84B8, 0x84B9, 0xC0F8, + 0xBEA2, 0xC0CD, 0x84BA, 0x84BB, 0x84BC, 0x84BD, 0x84BE, 0x84BF, 0x84C0, + 0x84C1, 0x84C2, 0x84C3, 0xDBC0, 0xCAC6, 0x84C4, 0x84C5, 0x84C6, 0xB2AA, + 0x84C7, 0x84C8, 0x84C9, 0xD3C2, 0x84CA, 0xC3E3, 0x84CB, 0xD1AB, 0x84CC, + 0x84CD, 0x84CE, 0x84CF, 0xDBC2, 0x84D0, 0xC0D5, 0x84D1, 0x84D2, 0x84D3, + 0xDBC3, 0x84D4, 0xBFB1, 0x84D5, 0x84D6, 0x84D7, 0x84D8, 0x84D9, 0x84DA, + 0xC4BC, 0x84DB, 0x84DC, 0x84DD, 0x84DE, 0xC7DA, 0x84DF, 0x84E0, 0x84E1, + 0x84E2, 0x84E3, 0x84E4, 0x84E5, 0x84E6, 0x84E7, 0x84E8, 0x84E9, 0xDBC4, + 0x84EA, 0x84EB, 0x84EC, 0x84ED, 0x84EE, 0x84EF, 0x84F0, 0x84F1, 0xD9E8, + 0xC9D7, 0x84F2, 0x84F3, 0x84F4, 0xB9B4, 0xCEF0, 0xD4C8, 0x84F5, 0x84F6, + 0x84F7, 0x84F8, 0xB0FC, 0xB4D2, 0x84F9, 0xD0D9, 0x84FA, 0x84FB, 0x84FC, + 0x84FD, 0xD9E9, 0x84FE, 0xDECB, 0xD9EB, 0x8540, 0x8541, 0x8542, 0x8543, + 0xD8B0, 0xBBAF, 0xB1B1, 0x8544, 0xB3D7, 0xD8CE, 0x8545, 0x8546, 0xD4D1, + 0x8547, 0x8548, 0xBDB3, 0xBFEF, 0x8549, 0xCFBB, 0x854A, 0x854B, 0xD8D0, + 0x854C, 0x854D, 0x854E, 0xB7CB, 0x854F, 0x8550, 0x8551, 0xD8D1, 0x8552, + 0x8553, 0x8554, 0x8555, 0x8556, 0x8557, 0x8558, 0x8559, 0x855A, 0x855B, + 0xC6A5, 0xC7F8, 0xD2BD, 0x855C, 0x855D, 0xD8D2, 0xC4E4, 0x855E, 0xCAAE, + 0x855F, 0xC7A7, 0x8560, 0xD8A6, 0x8561, 0xC9FD, 0xCEE7, 0xBBDC, 0xB0EB, + 0x8562, 0x8563, 0x8564, 0xBBAA, 0xD0AD, 0x8565, 0xB1B0, 0xD7E4, 0xD7BF, + 0x8566, 0xB5A5, 0xC2F4, 0xC4CF, 0x8567, 0x8568, 0xB2A9, 0x8569, 0xB2B7, + 0x856A, 0xB1E5, 0xDFB2, 0xD5BC, 0xBFA8, 0xC2AC, 0xD8D5, 0xC2B1, 0x856B, + 0xD8D4, 0xCED4, 0x856C, 0xDAE0, 0x856D, 0xCEC0, 0x856E, 0x856F, 0xD8B4, + 0xC3AE, 0xD3A1, 0xCEA3, 0x8570, 0xBCB4, 0xC8B4, 0xC2D1, 0x8571, 0xBEED, + 0xD0B6, 0x8572, 0xDAE1, 0x8573, 0x8574, 0x8575, 0x8576, 0xC7E4, 0x8577, + 0x8578, 0xB3A7, 0x8579, 0xB6F2, 0xCCFC, 0xC0FA, 0x857A, 0x857B, 0xC0F7, + 0x857C, 0xD1B9, 0xD1E1, 0xD8C7, 0x857D, 0x857E, 0x8580, 0x8581, 0x8582, + 0x8583, 0x8584, 0xB2DE, 0x8585, 0x8586, 0xC0E5, 0x8587, 0xBAF1, 0x8588, + 0x8589, 0xD8C8, 0x858A, 0xD4AD, 0x858B, 0x858C, 0xCFE1, 0xD8C9, 0x858D, + 0xD8CA, 0xCFC3, 0x858E, 0xB3F8, 0xBEC7, 0x858F, 0x8590, 0x8591, 0x8592, + 0xD8CB, 0x8593, 0x8594, 0x8595, 0x8596, 0x8597, 0x8598, 0x8599, 0xDBCC, + 0x859A, 0x859B, 0x859C, 0x859D, 0xC8A5, 0x859E, 0x859F, 0x85A0, 0xCFD8, + 0x85A1, 0xC8FE, 0xB2CE, 0x85A2, 0x85A3, 0x85A4, 0x85A5, 0x85A6, 0xD3D6, + 0xB2E6, 0xBCB0, 0xD3D1, 0xCBAB, 0xB7B4, 0x85A7, 0x85A8, 0x85A9, 0xB7A2, + 0x85AA, 0x85AB, 0xCAE5, 0x85AC, 0xC8A1, 0xCADC, 0xB1E4, 0xD0F0, 0x85AD, + 0xC5D1, 0x85AE, 0x85AF, 0x85B0, 0xDBC5, 0xB5FE, 0x85B1, 0x85B2, 0xBFDA, + 0xB9C5, 0xBEE4, 0xC1ED, 0x85B3, 0xDFB6, 0xDFB5, 0xD6BB, 0xBDD0, 0xD5D9, + 0xB0C8, 0xB6A3, 0xBFC9, 0xCCA8, 0xDFB3, 0xCAB7, 0xD3D2, 0x85B4, 0xD8CF, + 0xD2B6, 0xBAC5, 0xCBBE, 0xCCBE, 0x85B5, 0xDFB7, 0xB5F0, 0xDFB4, 0x85B6, + 0x85B7, 0x85B8, 0xD3F5, 0x85B9, 0xB3D4, 0xB8F7, 0x85BA, 0xDFBA, 0x85BB, + 0xBACF, 0xBCAA, 0xB5F5, 0x85BC, 0xCDAC, 0xC3FB, 0xBAF3, 0xC0F4, 0xCDC2, + 0xCFF2, 0xDFB8, 0xCFC5, 0x85BD, 0xC2C0, 0xDFB9, 0xC2F0, 0x85BE, 0x85BF, + 0x85C0, 0xBEFD, 0x85C1, 0xC1DF, 0xCDCC, 0xD2F7, 0xB7CD, 0xDFC1, 0x85C2, + 0xDFC4, 0x85C3, 0x85C4, 0xB7F1, 0xB0C9, 0xB6D6, 0xB7D4, 0x85C5, 0xBAAC, + 0xCCFD, 0xBFD4, 0xCBB1, 0xC6F4, 0x85C6, 0xD6A8, 0xDFC5, 0x85C7, 0xCEE2, + 0xB3B3, 0x85C8, 0x85C9, 0xCEFC, 0xB4B5, 0x85CA, 0xCEC7, 0xBAF0, 0x85CB, + 0xCEE1, 0x85CC, 0xD1BD, 0x85CD, 0x85CE, 0xDFC0, 0x85CF, 0x85D0, 0xB4F4, + 0x85D1, 0xB3CA, 0x85D2, 0xB8E6, 0xDFBB, 0x85D3, 0x85D4, 0x85D5, 0x85D6, + 0xC4C5, 0x85D7, 0xDFBC, 0xDFBD, 0xDFBE, 0xC5BB, 0xDFBF, 0xDFC2, 0xD4B1, + 0xDFC3, 0x85D8, 0xC7BA, 0xCED8, 0x85D9, 0x85DA, 0x85DB, 0x85DC, 0x85DD, + 0xC4D8, 0x85DE, 0xDFCA, 0x85DF, 0xDFCF, 0x85E0, 0xD6DC, 0x85E1, 0x85E2, + 0x85E3, 0x85E4, 0x85E5, 0x85E6, 0x85E7, 0x85E8, 0xDFC9, 0xDFDA, 0xCEB6, + 0x85E9, 0xBAC7, 0xDFCE, 0xDFC8, 0xC5DE, 0x85EA, 0x85EB, 0xC9EB, 0xBAF4, + 0xC3FC, 0x85EC, 0x85ED, 0xBED7, 0x85EE, 0xDFC6, 0x85EF, 0xDFCD, 0x85F0, + 0xC5D8, 0x85F1, 0x85F2, 0x85F3, 0x85F4, 0xD5A6, 0xBACD, 0x85F5, 0xBECC, + 0xD3BD, 0xB8C0, 0x85F6, 0xD6E4, 0x85F7, 0xDFC7, 0xB9BE, 0xBFA7, 0x85F8, + 0x85F9, 0xC1FC, 0xDFCB, 0xDFCC, 0x85FA, 0xDFD0, 0x85FB, 0x85FC, 0x85FD, + 0x85FE, 0x8640, 0xDFDB, 0xDFE5, 0x8641, 0xDFD7, 0xDFD6, 0xD7C9, 0xDFE3, + 0xDFE4, 0xE5EB, 0xD2A7, 0xDFD2, 0x8642, 0xBFA9, 0x8643, 0xD4DB, 0x8644, + 0xBFC8, 0xDFD4, 0x8645, 0x8646, 0x8647, 0xCFCC, 0x8648, 0x8649, 0xDFDD, + 0x864A, 0xD1CA, 0x864B, 0xDFDE, 0xB0A7, 0xC6B7, 0xDFD3, 0x864C, 0xBAE5, + 0x864D, 0xB6DF, 0xCDDB, 0xB9FE, 0xD4D5, 0x864E, 0x864F, 0xDFDF, 0xCFEC, + 0xB0A5, 0xDFE7, 0xDFD1, 0xD1C6, 0xDFD5, 0xDFD8, 0xDFD9, 0xDFDC, 0x8650, + 0xBBA9, 0x8651, 0xDFE0, 0xDFE1, 0x8652, 0xDFE2, 0xDFE6, 0xDFE8, 0xD3B4, + 0x8653, 0x8654, 0x8655, 0x8656, 0x8657, 0xB8E7, 0xC5B6, 0xDFEA, 0xC9DA, + 0xC1A8, 0xC4C4, 0x8658, 0x8659, 0xBFDE, 0xCFF8, 0x865A, 0x865B, 0x865C, + 0xD5DC, 0xDFEE, 0x865D, 0x865E, 0x865F, 0x8660, 0x8661, 0x8662, 0xB2B8, + 0x8663, 0xBADF, 0xDFEC, 0x8664, 0xDBC1, 0x8665, 0xD1E4, 0x8666, 0x8667, + 0x8668, 0x8669, 0xCBF4, 0xB4BD, 0x866A, 0xB0A6, 0x866B, 0x866C, 0x866D, + 0x866E, 0x866F, 0xDFF1, 0xCCC6, 0xDFF2, 0x8670, 0x8671, 0xDFED, 0x8672, + 0x8673, 0x8674, 0x8675, 0x8676, 0x8677, 0xDFE9, 0x8678, 0x8679, 0x867A, + 0x867B, 0xDFEB, 0x867C, 0xDFEF, 0xDFF0, 0xBBBD, 0x867D, 0x867E, 0xDFF3, + 0x8680, 0x8681, 0xDFF4, 0x8682, 0xBBA3, 0x8683, 0xCADB, 0xCEA8, 0xE0A7, + 0xB3AA, 0x8684, 0xE0A6, 0x8685, 0x8686, 0x8687, 0xE0A1, 0x8688, 0x8689, + 0x868A, 0x868B, 0xDFFE, 0x868C, 0xCDD9, 0xDFFC, 0x868D, 0xDFFA, 0x868E, + 0xBFD0, 0xD7C4, 0x868F, 0xC9CC, 0x8690, 0x8691, 0xDFF8, 0xB0A1, 0x8692, + 0x8693, 0x8694, 0x8695, 0x8696, 0xDFFD, 0x8697, 0x8698, 0x8699, 0x869A, + 0xDFFB, 0xE0A2, 0x869B, 0x869C, 0x869D, 0x869E, 0x869F, 0xE0A8, 0x86A0, + 0x86A1, 0x86A2, 0x86A3, 0xB7C8, 0x86A4, 0x86A5, 0xC6A1, 0xC9B6, 0xC0B2, + 0xDFF5, 0x86A6, 0x86A7, 0xC5BE, 0x86A8, 0xD8C4, 0xDFF9, 0xC4F6, 0x86A9, + 0x86AA, 0x86AB, 0x86AC, 0x86AD, 0x86AE, 0xE0A3, 0xE0A4, 0xE0A5, 0xD0A5, + 0x86AF, 0x86B0, 0xE0B4, 0xCCE4, 0x86B1, 0xE0B1, 0x86B2, 0xBFA6, 0xE0AF, + 0xCEB9, 0xE0AB, 0xC9C6, 0x86B3, 0x86B4, 0xC0AE, 0xE0AE, 0xBAED, 0xBAB0, + 0xE0A9, 0x86B5, 0x86B6, 0x86B7, 0xDFF6, 0x86B8, 0xE0B3, 0x86B9, 0x86BA, + 0xE0B8, 0x86BB, 0x86BC, 0x86BD, 0xB4AD, 0xE0B9, 0x86BE, 0x86BF, 0xCFB2, + 0xBAC8, 0x86C0, 0xE0B0, 0x86C1, 0x86C2, 0x86C3, 0x86C4, 0x86C5, 0x86C6, + 0x86C7, 0xD0FA, 0x86C8, 0x86C9, 0x86CA, 0x86CB, 0x86CC, 0x86CD, 0x86CE, + 0x86CF, 0x86D0, 0xE0AC, 0x86D1, 0xD4FB, 0x86D2, 0xDFF7, 0x86D3, 0xC5E7, + 0x86D4, 0xE0AD, 0x86D5, 0xD3F7, 0x86D6, 0xE0B6, 0xE0B7, 0x86D7, 0x86D8, + 0x86D9, 0x86DA, 0x86DB, 0xE0C4, 0xD0E1, 0x86DC, 0x86DD, 0x86DE, 0xE0BC, + 0x86DF, 0x86E0, 0xE0C9, 0xE0CA, 0x86E1, 0x86E2, 0x86E3, 0xE0BE, 0xE0AA, + 0xC9A4, 0xE0C1, 0x86E4, 0xE0B2, 0x86E5, 0x86E6, 0x86E7, 0x86E8, 0x86E9, + 0xCAC8, 0xE0C3, 0x86EA, 0xE0B5, 0x86EB, 0xCECB, 0x86EC, 0xCBC3, 0xE0CD, + 0xE0C6, 0xE0C2, 0x86ED, 0xE0CB, 0x86EE, 0xE0BA, 0xE0BF, 0xE0C0, 0x86EF, + 0x86F0, 0xE0C5, 0x86F1, 0x86F2, 0xE0C7, 0xE0C8, 0x86F3, 0xE0CC, 0x86F4, + 0xE0BB, 0x86F5, 0x86F6, 0x86F7, 0x86F8, 0x86F9, 0xCBD4, 0xE0D5, 0x86FA, + 0xE0D6, 0xE0D2, 0x86FB, 0x86FC, 0x86FD, 0x86FE, 0x8740, 0x8741, 0xE0D0, + 0xBCCE, 0x8742, 0x8743, 0xE0D1, 0x8744, 0xB8C2, 0xD8C5, 0x8745, 0x8746, + 0x8747, 0x8748, 0x8749, 0x874A, 0x874B, 0x874C, 0xD0EA, 0x874D, 0x874E, + 0xC2EF, 0x874F, 0x8750, 0xE0CF, 0xE0BD, 0x8751, 0x8752, 0x8753, 0xE0D4, + 0xE0D3, 0x8754, 0x8755, 0xE0D7, 0x8756, 0x8757, 0x8758, 0x8759, 0xE0DC, + 0xE0D8, 0x875A, 0x875B, 0x875C, 0xD6F6, 0xB3B0, 0x875D, 0xD7EC, 0x875E, + 0xCBBB, 0x875F, 0x8760, 0xE0DA, 0x8761, 0xCEFB, 0x8762, 0x8763, 0x8764, + 0xBAD9, 0x8765, 0x8766, 0x8767, 0x8768, 0x8769, 0x876A, 0x876B, 0x876C, + 0x876D, 0x876E, 0x876F, 0x8770, 0xE0E1, 0xE0DD, 0xD2AD, 0x8771, 0x8772, + 0x8773, 0x8774, 0x8775, 0xE0E2, 0x8776, 0x8777, 0xE0DB, 0xE0D9, 0xE0DF, + 0x8778, 0x8779, 0xE0E0, 0x877A, 0x877B, 0x877C, 0x877D, 0x877E, 0xE0DE, + 0x8780, 0xE0E4, 0x8781, 0x8782, 0x8783, 0xC6F7, 0xD8AC, 0xD4EB, 0xE0E6, + 0xCAC9, 0x8784, 0x8785, 0x8786, 0x8787, 0xE0E5, 0x8788, 0x8789, 0x878A, + 0x878B, 0xB8C1, 0x878C, 0x878D, 0x878E, 0x878F, 0xE0E7, 0xE0E8, 0x8790, + 0x8791, 0x8792, 0x8793, 0x8794, 0x8795, 0x8796, 0x8797, 0xE0E9, 0xE0E3, + 0x8798, 0x8799, 0x879A, 0x879B, 0x879C, 0x879D, 0x879E, 0xBABF, 0xCCE7, + 0x879F, 0x87A0, 0x87A1, 0xE0EA, 0x87A2, 0x87A3, 0x87A4, 0x87A5, 0x87A6, + 0x87A7, 0x87A8, 0x87A9, 0x87AA, 0x87AB, 0x87AC, 0x87AD, 0x87AE, 0x87AF, + 0x87B0, 0xCFF9, 0x87B1, 0x87B2, 0x87B3, 0x87B4, 0x87B5, 0x87B6, 0x87B7, + 0x87B8, 0x87B9, 0x87BA, 0x87BB, 0xE0EB, 0x87BC, 0x87BD, 0x87BE, 0x87BF, + 0x87C0, 0x87C1, 0x87C2, 0xC8C2, 0x87C3, 0x87C4, 0x87C5, 0x87C6, 0xBDC0, + 0x87C7, 0x87C8, 0x87C9, 0x87CA, 0x87CB, 0x87CC, 0x87CD, 0x87CE, 0x87CF, + 0x87D0, 0x87D1, 0x87D2, 0x87D3, 0xC4D2, 0x87D4, 0x87D5, 0x87D6, 0x87D7, + 0x87D8, 0x87D9, 0x87DA, 0x87DB, 0x87DC, 0xE0EC, 0x87DD, 0x87DE, 0xE0ED, + 0x87DF, 0x87E0, 0xC7F4, 0xCBC4, 0x87E1, 0xE0EE, 0xBBD8, 0xD8B6, 0xD2F2, + 0xE0EF, 0xCDC5, 0x87E2, 0xB6DA, 0x87E3, 0x87E4, 0x87E5, 0x87E6, 0x87E7, + 0x87E8, 0xE0F1, 0x87E9, 0xD4B0, 0x87EA, 0x87EB, 0xC0A7, 0xB4D1, 0x87EC, + 0x87ED, 0xCEA7, 0xE0F0, 0x87EE, 0x87EF, 0x87F0, 0xE0F2, 0xB9CC, 0x87F1, + 0x87F2, 0xB9FA, 0xCDBC, 0xE0F3, 0x87F3, 0x87F4, 0x87F5, 0xC6D4, 0xE0F4, + 0x87F6, 0xD4B2, 0x87F7, 0xC8A6, 0xE0F6, 0xE0F5, 0x87F8, 0x87F9, 0x87FA, + 0x87FB, 0x87FC, 0x87FD, 0x87FE, 0x8840, 0x8841, 0x8842, 0x8843, 0x8844, + 0x8845, 0x8846, 0x8847, 0x8848, 0x8849, 0xE0F7, 0x884A, 0x884B, 0xCDC1, + 0x884C, 0x884D, 0x884E, 0xCAA5, 0x884F, 0x8850, 0x8851, 0x8852, 0xD4DA, + 0xDBD7, 0xDBD9, 0x8853, 0xDBD8, 0xB9E7, 0xDBDC, 0xDBDD, 0xB5D8, 0x8854, + 0x8855, 0xDBDA, 0x8856, 0x8857, 0x8858, 0x8859, 0x885A, 0xDBDB, 0xB3A1, + 0xDBDF, 0x885B, 0x885C, 0xBBF8, 0x885D, 0xD6B7, 0x885E, 0xDBE0, 0x885F, + 0x8860, 0x8861, 0x8862, 0xBEF9, 0x8863, 0x8864, 0xB7BB, 0x8865, 0xDBD0, + 0xCCAE, 0xBFB2, 0xBBB5, 0xD7F8, 0xBFD3, 0x8866, 0x8867, 0x8868, 0x8869, + 0x886A, 0xBFE9, 0x886B, 0x886C, 0xBCE1, 0xCCB3, 0xDBDE, 0xB0D3, 0xCEEB, + 0xB7D8, 0xD7B9, 0xC6C2, 0x886D, 0x886E, 0xC0A4, 0x886F, 0xCCB9, 0x8870, + 0xDBE7, 0xDBE1, 0xC6BA, 0xDBE3, 0x8871, 0xDBE8, 0x8872, 0xC5F7, 0x8873, + 0x8874, 0x8875, 0xDBEA, 0x8876, 0x8877, 0xDBE9, 0xBFC0, 0x8878, 0x8879, + 0x887A, 0xDBE6, 0xDBE5, 0x887B, 0x887C, 0x887D, 0x887E, 0x8880, 0xB4B9, + 0xC0AC, 0xC2A2, 0xDBE2, 0xDBE4, 0x8881, 0x8882, 0x8883, 0x8884, 0xD0CD, + 0xDBED, 0x8885, 0x8886, 0x8887, 0x8888, 0x8889, 0xC0DD, 0xDBF2, 0x888A, + 0x888B, 0x888C, 0x888D, 0x888E, 0x888F, 0x8890, 0xB6E2, 0x8891, 0x8892, + 0x8893, 0x8894, 0xDBF3, 0xDBD2, 0xB9B8, 0xD4AB, 0xDBEC, 0x8895, 0xBFD1, + 0xDBF0, 0x8896, 0xDBD1, 0x8897, 0xB5E6, 0x8898, 0xDBEB, 0xBFE5, 0x8899, + 0x889A, 0x889B, 0xDBEE, 0x889C, 0xDBF1, 0x889D, 0x889E, 0x889F, 0xDBF9, + 0x88A0, 0x88A1, 0x88A2, 0x88A3, 0x88A4, 0x88A5, 0x88A6, 0x88A7, 0x88A8, + 0xB9A1, 0xB0A3, 0x88A9, 0x88AA, 0x88AB, 0x88AC, 0x88AD, 0x88AE, 0x88AF, + 0xC2F1, 0x88B0, 0x88B1, 0xB3C7, 0xDBEF, 0x88B2, 0x88B3, 0xDBF8, 0x88B4, + 0xC6D2, 0xDBF4, 0x88B5, 0x88B6, 0xDBF5, 0xDBF7, 0xDBF6, 0x88B7, 0x88B8, + 0xDBFE, 0x88B9, 0xD3F2, 0xB2BA, 0x88BA, 0x88BB, 0x88BC, 0xDBFD, 0x88BD, + 0x88BE, 0x88BF, 0x88C0, 0x88C1, 0x88C2, 0x88C3, 0x88C4, 0xDCA4, 0x88C5, + 0xDBFB, 0x88C6, 0x88C7, 0x88C8, 0x88C9, 0xDBFA, 0x88CA, 0x88CB, 0x88CC, + 0xDBFC, 0xC5E0, 0xBBF9, 0x88CD, 0x88CE, 0xDCA3, 0x88CF, 0x88D0, 0xDCA5, + 0x88D1, 0xCCC3, 0x88D2, 0x88D3, 0x88D4, 0xB6D1, 0xDDC0, 0x88D5, 0x88D6, + 0x88D7, 0xDCA1, 0x88D8, 0xDCA2, 0x88D9, 0x88DA, 0x88DB, 0xC7B5, 0x88DC, + 0x88DD, 0x88DE, 0xB6E9, 0x88DF, 0x88E0, 0x88E1, 0xDCA7, 0x88E2, 0x88E3, + 0x88E4, 0x88E5, 0xDCA6, 0x88E6, 0xDCA9, 0xB1A4, 0x88E7, 0x88E8, 0xB5CC, + 0x88E9, 0x88EA, 0x88EB, 0x88EC, 0x88ED, 0xBFB0, 0x88EE, 0x88EF, 0x88F0, + 0x88F1, 0x88F2, 0xD1DF, 0x88F3, 0x88F4, 0x88F5, 0x88F6, 0xB6C2, 0x88F7, + 0x88F8, 0x88F9, 0x88FA, 0x88FB, 0x88FC, 0x88FD, 0x88FE, 0x8940, 0x8941, + 0x8942, 0x8943, 0x8944, 0x8945, 0xDCA8, 0x8946, 0x8947, 0x8948, 0x8949, + 0x894A, 0x894B, 0x894C, 0xCBFA, 0xEBF3, 0x894D, 0x894E, 0x894F, 0xCBDC, + 0x8950, 0x8951, 0xCBFE, 0x8952, 0x8953, 0x8954, 0xCCC1, 0x8955, 0x8956, + 0x8957, 0x8958, 0x8959, 0xC8FB, 0x895A, 0x895B, 0x895C, 0x895D, 0x895E, + 0x895F, 0xDCAA, 0x8960, 0x8961, 0x8962, 0x8963, 0x8964, 0xCCEE, 0xDCAB, + 0x8965, 0x8966, 0x8967, 0x8968, 0x8969, 0x896A, 0x896B, 0x896C, 0x896D, + 0x896E, 0x896F, 0x8970, 0x8971, 0x8972, 0x8973, 0x8974, 0x8975, 0xDBD3, + 0x8976, 0xDCAF, 0xDCAC, 0x8977, 0xBEB3, 0x8978, 0xCAFB, 0x8979, 0x897A, + 0x897B, 0xDCAD, 0x897C, 0x897D, 0x897E, 0x8980, 0x8981, 0x8982, 0x8983, + 0x8984, 0xC9CA, 0xC4B9, 0x8985, 0x8986, 0x8987, 0x8988, 0x8989, 0xC7BD, + 0xDCAE, 0x898A, 0x898B, 0x898C, 0xD4F6, 0xD0E6, 0x898D, 0x898E, 0x898F, + 0x8990, 0x8991, 0x8992, 0x8993, 0x8994, 0xC4AB, 0xB6D5, 0x8995, 0x8996, + 0x8997, 0x8998, 0x8999, 0x899A, 0x899B, 0x899C, 0x899D, 0x899E, 0x899F, + 0x89A0, 0x89A1, 0x89A2, 0x89A3, 0x89A4, 0x89A5, 0x89A6, 0xDBD4, 0x89A7, + 0x89A8, 0x89A9, 0x89AA, 0xB1DA, 0x89AB, 0x89AC, 0x89AD, 0xDBD5, 0x89AE, + 0x89AF, 0x89B0, 0x89B1, 0x89B2, 0x89B3, 0x89B4, 0x89B5, 0x89B6, 0x89B7, + 0x89B8, 0xDBD6, 0x89B9, 0x89BA, 0x89BB, 0xBABE, 0x89BC, 0x89BD, 0x89BE, + 0x89BF, 0x89C0, 0x89C1, 0x89C2, 0x89C3, 0x89C4, 0x89C5, 0x89C6, 0x89C7, + 0x89C8, 0x89C9, 0xC8C0, 0x89CA, 0x89CB, 0x89CC, 0x89CD, 0x89CE, 0x89CF, + 0xCABF, 0xC8C9, 0x89D0, 0xD7B3, 0x89D1, 0xC9F9, 0x89D2, 0x89D3, 0xBFC7, + 0x89D4, 0x89D5, 0xBAF8, 0x89D6, 0x89D7, 0xD2BC, 0x89D8, 0x89D9, 0x89DA, + 0x89DB, 0x89DC, 0x89DD, 0x89DE, 0x89DF, 0xE2BA, 0x89E0, 0xB4A6, 0x89E1, + 0x89E2, 0xB1B8, 0x89E3, 0x89E4, 0x89E5, 0x89E6, 0x89E7, 0xB8B4, 0x89E8, + 0xCFC4, 0x89E9, 0x89EA, 0x89EB, 0x89EC, 0xD9E7, 0xCFA6, 0xCDE2, 0x89ED, + 0x89EE, 0xD9ED, 0xB6E0, 0x89EF, 0xD2B9, 0x89F0, 0x89F1, 0xB9BB, 0x89F2, + 0x89F3, 0x89F4, 0x89F5, 0xE2B9, 0xE2B7, 0x89F6, 0xB4F3, 0x89F7, 0xCCEC, + 0xCCAB, 0xB7F2, 0x89F8, 0xD8B2, 0xD1EB, 0xBABB, 0x89F9, 0xCAA7, 0x89FA, + 0x89FB, 0xCDB7, 0x89FC, 0x89FD, 0xD2C4, 0xBFE4, 0xBCD0, 0xB6E1, 0x89FE, + 0xDEC5, 0x8A40, 0x8A41, 0x8A42, 0x8A43, 0xDEC6, 0xDBBC, 0x8A44, 0xD1D9, + 0x8A45, 0x8A46, 0xC6E6, 0xC4CE, 0xB7EE, 0x8A47, 0xB7DC, 0x8A48, 0x8A49, + 0xBFFC, 0xD7E0, 0x8A4A, 0xC6F5, 0x8A4B, 0x8A4C, 0xB1BC, 0xDEC8, 0xBDB1, + 0xCCD7, 0xDECA, 0x8A4D, 0xDEC9, 0x8A4E, 0x8A4F, 0x8A50, 0x8A51, 0x8A52, + 0xB5EC, 0x8A53, 0xC9DD, 0x8A54, 0x8A55, 0xB0C2, 0x8A56, 0x8A57, 0x8A58, + 0x8A59, 0x8A5A, 0x8A5B, 0x8A5C, 0x8A5D, 0x8A5E, 0x8A5F, 0x8A60, 0x8A61, + 0x8A62, 0xC5AE, 0xC5AB, 0x8A63, 0xC4CC, 0x8A64, 0xBCE9, 0xCBFD, 0x8A65, + 0x8A66, 0x8A67, 0xBAC3, 0x8A68, 0x8A69, 0x8A6A, 0xE5F9, 0xC8E7, 0xE5FA, + 0xCDFD, 0x8A6B, 0xD7B1, 0xB8BE, 0xC2E8, 0x8A6C, 0xC8D1, 0x8A6D, 0x8A6E, + 0xE5FB, 0x8A6F, 0x8A70, 0x8A71, 0x8A72, 0xB6CA, 0xBCCB, 0x8A73, 0x8A74, + 0xD1FD, 0xE6A1, 0x8A75, 0xC3EE, 0x8A76, 0x8A77, 0x8A78, 0x8A79, 0xE6A4, + 0x8A7A, 0x8A7B, 0x8A7C, 0x8A7D, 0xE5FE, 0xE6A5, 0xCDD7, 0x8A7E, 0x8A80, + 0xB7C1, 0xE5FC, 0xE5FD, 0xE6A3, 0x8A81, 0x8A82, 0xC4DD, 0xE6A8, 0x8A83, + 0x8A84, 0xE6A7, 0x8A85, 0x8A86, 0x8A87, 0x8A88, 0x8A89, 0x8A8A, 0xC3C3, + 0x8A8B, 0xC6DE, 0x8A8C, 0x8A8D, 0xE6AA, 0x8A8E, 0x8A8F, 0x8A90, 0x8A91, + 0x8A92, 0x8A93, 0x8A94, 0xC4B7, 0x8A95, 0x8A96, 0x8A97, 0xE6A2, 0xCABC, + 0x8A98, 0x8A99, 0x8A9A, 0x8A9B, 0xBDE3, 0xB9C3, 0xE6A6, 0xD0D5, 0xCEAF, + 0x8A9C, 0x8A9D, 0xE6A9, 0xE6B0, 0x8A9E, 0xD2A6, 0x8A9F, 0xBDAA, 0xE6AD, + 0x8AA0, 0x8AA1, 0x8AA2, 0x8AA3, 0x8AA4, 0xE6AF, 0x8AA5, 0xC0D1, 0x8AA6, + 0x8AA7, 0xD2CC, 0x8AA8, 0x8AA9, 0x8AAA, 0xBCA7, 0x8AAB, 0x8AAC, 0x8AAD, + 0x8AAE, 0x8AAF, 0x8AB0, 0x8AB1, 0x8AB2, 0x8AB3, 0x8AB4, 0x8AB5, 0x8AB6, + 0xE6B1, 0x8AB7, 0xD2F6, 0x8AB8, 0x8AB9, 0x8ABA, 0xD7CB, 0x8ABB, 0xCDFE, + 0x8ABC, 0xCDDE, 0xC2A6, 0xE6AB, 0xE6AC, 0xBDBF, 0xE6AE, 0xE6B3, 0x8ABD, + 0x8ABE, 0xE6B2, 0x8ABF, 0x8AC0, 0x8AC1, 0x8AC2, 0xE6B6, 0x8AC3, 0xE6B8, + 0x8AC4, 0x8AC5, 0x8AC6, 0x8AC7, 0xC4EF, 0x8AC8, 0x8AC9, 0x8ACA, 0xC4C8, + 0x8ACB, 0x8ACC, 0xBEEA, 0xC9EF, 0x8ACD, 0x8ACE, 0xE6B7, 0x8ACF, 0xB6F0, + 0x8AD0, 0x8AD1, 0x8AD2, 0xC3E4, 0x8AD3, 0x8AD4, 0x8AD5, 0x8AD6, 0x8AD7, + 0x8AD8, 0x8AD9, 0xD3E9, 0xE6B4, 0x8ADA, 0xE6B5, 0x8ADB, 0xC8A2, 0x8ADC, + 0x8ADD, 0x8ADE, 0x8ADF, 0x8AE0, 0xE6BD, 0x8AE1, 0x8AE2, 0x8AE3, 0xE6B9, + 0x8AE4, 0x8AE5, 0x8AE6, 0x8AE7, 0x8AE8, 0xC6C5, 0x8AE9, 0x8AEA, 0xCDF1, + 0xE6BB, 0x8AEB, 0x8AEC, 0x8AED, 0x8AEE, 0x8AEF, 0x8AF0, 0x8AF1, 0x8AF2, + 0x8AF3, 0x8AF4, 0xE6BC, 0x8AF5, 0x8AF6, 0x8AF7, 0x8AF8, 0xBBE9, 0x8AF9, + 0x8AFA, 0x8AFB, 0x8AFC, 0x8AFD, 0x8AFE, 0x8B40, 0xE6BE, 0x8B41, 0x8B42, + 0x8B43, 0x8B44, 0xE6BA, 0x8B45, 0x8B46, 0xC0B7, 0x8B47, 0x8B48, 0x8B49, + 0x8B4A, 0x8B4B, 0x8B4C, 0x8B4D, 0x8B4E, 0x8B4F, 0xD3A4, 0xE6BF, 0xC9F4, + 0xE6C3, 0x8B50, 0x8B51, 0xE6C4, 0x8B52, 0x8B53, 0x8B54, 0x8B55, 0xD0F6, + 0x8B56, 0x8B57, 0x8B58, 0x8B59, 0x8B5A, 0x8B5B, 0x8B5C, 0x8B5D, 0x8B5E, + 0x8B5F, 0x8B60, 0x8B61, 0x8B62, 0x8B63, 0x8B64, 0x8B65, 0x8B66, 0x8B67, + 0xC3BD, 0x8B68, 0x8B69, 0x8B6A, 0x8B6B, 0x8B6C, 0x8B6D, 0x8B6E, 0xC3C4, + 0xE6C2, 0x8B6F, 0x8B70, 0x8B71, 0x8B72, 0x8B73, 0x8B74, 0x8B75, 0x8B76, + 0x8B77, 0x8B78, 0x8B79, 0x8B7A, 0x8B7B, 0x8B7C, 0xE6C1, 0x8B7D, 0x8B7E, + 0x8B80, 0x8B81, 0x8B82, 0x8B83, 0x8B84, 0xE6C7, 0xCFB1, 0x8B85, 0xEBF4, + 0x8B86, 0x8B87, 0xE6CA, 0x8B88, 0x8B89, 0x8B8A, 0x8B8B, 0x8B8C, 0xE6C5, + 0x8B8D, 0x8B8E, 0xBCDE, 0xC9A9, 0x8B8F, 0x8B90, 0x8B91, 0x8B92, 0x8B93, + 0x8B94, 0xBCB5, 0x8B95, 0x8B96, 0xCFD3, 0x8B97, 0x8B98, 0x8B99, 0x8B9A, + 0x8B9B, 0xE6C8, 0x8B9C, 0xE6C9, 0x8B9D, 0xE6CE, 0x8B9E, 0xE6D0, 0x8B9F, + 0x8BA0, 0x8BA1, 0xE6D1, 0x8BA2, 0x8BA3, 0x8BA4, 0xE6CB, 0xB5D5, 0x8BA5, + 0xE6CC, 0x8BA6, 0x8BA7, 0xE6CF, 0x8BA8, 0x8BA9, 0xC4DB, 0x8BAA, 0xE6C6, + 0x8BAB, 0x8BAC, 0x8BAD, 0x8BAE, 0x8BAF, 0xE6CD, 0x8BB0, 0x8BB1, 0x8BB2, + 0x8BB3, 0x8BB4, 0x8BB5, 0x8BB6, 0x8BB7, 0x8BB8, 0x8BB9, 0x8BBA, 0x8BBB, + 0x8BBC, 0x8BBD, 0x8BBE, 0x8BBF, 0x8BC0, 0x8BC1, 0x8BC2, 0x8BC3, 0x8BC4, + 0x8BC5, 0x8BC6, 0xE6D2, 0x8BC7, 0x8BC8, 0x8BC9, 0x8BCA, 0x8BCB, 0x8BCC, + 0x8BCD, 0x8BCE, 0x8BCF, 0x8BD0, 0x8BD1, 0x8BD2, 0xE6D4, 0xE6D3, 0x8BD3, + 0x8BD4, 0x8BD5, 0x8BD6, 0x8BD7, 0x8BD8, 0x8BD9, 0x8BDA, 0x8BDB, 0x8BDC, + 0x8BDD, 0x8BDE, 0x8BDF, 0x8BE0, 0x8BE1, 0x8BE2, 0x8BE3, 0x8BE4, 0x8BE5, + 0x8BE6, 0x8BE7, 0x8BE8, 0x8BE9, 0x8BEA, 0x8BEB, 0x8BEC, 0xE6D5, 0x8BED, + 0xD9F8, 0x8BEE, 0x8BEF, 0xE6D6, 0x8BF0, 0x8BF1, 0x8BF2, 0x8BF3, 0x8BF4, + 0x8BF5, 0x8BF6, 0x8BF7, 0xE6D7, 0x8BF8, 0x8BF9, 0x8BFA, 0x8BFB, 0x8BFC, + 0x8BFD, 0x8BFE, 0x8C40, 0x8C41, 0x8C42, 0x8C43, 0x8C44, 0x8C45, 0x8C46, + 0x8C47, 0xD7D3, 0xE6DD, 0x8C48, 0xE6DE, 0xBFD7, 0xD4D0, 0x8C49, 0xD7D6, + 0xB4E6, 0xCBEF, 0xE6DA, 0xD8C3, 0xD7CE, 0xD0A2, 0x8C4A, 0xC3CF, 0x8C4B, + 0x8C4C, 0xE6DF, 0xBCBE, 0xB9C2, 0xE6DB, 0xD1A7, 0x8C4D, 0x8C4E, 0xBAA2, + 0xC2CF, 0x8C4F, 0xD8AB, 0x8C50, 0x8C51, 0x8C52, 0xCAEB, 0xE5EE, 0x8C53, + 0xE6DC, 0x8C54, 0xB7F5, 0x8C55, 0x8C56, 0x8C57, 0x8C58, 0xC8E6, 0x8C59, + 0x8C5A, 0xC4F5, 0x8C5B, 0x8C5C, 0xE5B2, 0xC4FE, 0x8C5D, 0xCBFC, 0xE5B3, + 0xD5AC, 0x8C5E, 0xD3EE, 0xCAD8, 0xB0B2, 0x8C5F, 0xCBCE, 0xCDEA, 0x8C60, + 0x8C61, 0xBAEA, 0x8C62, 0x8C63, 0x8C64, 0xE5B5, 0x8C65, 0xE5B4, 0x8C66, + 0xD7DA, 0xB9D9, 0xD6E6, 0xB6A8, 0xCDF0, 0xD2CB, 0xB1A6, 0xCAB5, 0x8C67, + 0xB3E8, 0xC9F3, 0xBFCD, 0xD0FB, 0xCAD2, 0xE5B6, 0xBBC2, 0x8C68, 0x8C69, + 0x8C6A, 0xCFDC, 0xB9AC, 0x8C6B, 0x8C6C, 0x8C6D, 0x8C6E, 0xD4D7, 0x8C6F, + 0x8C70, 0xBAA6, 0xD1E7, 0xCFFC, 0xBCD2, 0x8C71, 0xE5B7, 0xC8DD, 0x8C72, + 0x8C73, 0x8C74, 0xBFED, 0xB1F6, 0xCBDE, 0x8C75, 0x8C76, 0xBCC5, 0x8C77, + 0xBCC4, 0xD2FA, 0xC3DC, 0xBFDC, 0x8C78, 0x8C79, 0x8C7A, 0x8C7B, 0xB8BB, + 0x8C7C, 0x8C7D, 0x8C7E, 0xC3C2, 0x8C80, 0xBAAE, 0xD4A2, 0x8C81, 0x8C82, + 0x8C83, 0x8C84, 0x8C85, 0x8C86, 0x8C87, 0x8C88, 0x8C89, 0xC7DE, 0xC4AF, + 0xB2EC, 0x8C8A, 0xB9D1, 0x8C8B, 0x8C8C, 0xE5BB, 0xC1C8, 0x8C8D, 0x8C8E, + 0xD5AF, 0x8C8F, 0x8C90, 0x8C91, 0x8C92, 0x8C93, 0xE5BC, 0x8C94, 0xE5BE, + 0x8C95, 0x8C96, 0x8C97, 0x8C98, 0x8C99, 0x8C9A, 0x8C9B, 0xB4E7, 0xB6D4, + 0xCBC2, 0xD1B0, 0xB5BC, 0x8C9C, 0x8C9D, 0xCAD9, 0x8C9E, 0xB7E2, 0x8C9F, + 0x8CA0, 0xC9E4, 0x8CA1, 0xBDAB, 0x8CA2, 0x8CA3, 0xCEBE, 0xD7F0, 0x8CA4, + 0x8CA5, 0x8CA6, 0x8CA7, 0xD0A1, 0x8CA8, 0xC9D9, 0x8CA9, 0x8CAA, 0xB6FB, + 0xE6D8, 0xBCE2, 0x8CAB, 0xB3BE, 0x8CAC, 0xC9D0, 0x8CAD, 0xE6D9, 0xB3A2, + 0x8CAE, 0x8CAF, 0x8CB0, 0x8CB1, 0xDECC, 0x8CB2, 0xD3C8, 0xDECD, 0x8CB3, + 0xD2A2, 0x8CB4, 0x8CB5, 0x8CB6, 0x8CB7, 0xDECE, 0x8CB8, 0x8CB9, 0x8CBA, + 0x8CBB, 0xBECD, 0x8CBC, 0x8CBD, 0xDECF, 0x8CBE, 0x8CBF, 0x8CC0, 0xCAAC, + 0xD2FC, 0xB3DF, 0xE5EA, 0xC4E1, 0xBEA1, 0xCEB2, 0xC4F2, 0xBED6, 0xC6A8, + 0xB2E3, 0x8CC1, 0x8CC2, 0xBED3, 0x8CC3, 0x8CC4, 0xC7FC, 0xCCEB, 0xBDEC, + 0xCEDD, 0x8CC5, 0x8CC6, 0xCABA, 0xC6C1, 0xE5EC, 0xD0BC, 0x8CC7, 0x8CC8, + 0x8CC9, 0xD5B9, 0x8CCA, 0x8CCB, 0x8CCC, 0xE5ED, 0x8CCD, 0x8CCE, 0x8CCF, + 0x8CD0, 0xCAF4, 0x8CD1, 0xCDC0, 0xC2C5, 0x8CD2, 0xE5EF, 0x8CD3, 0xC2C4, + 0xE5F0, 0x8CD4, 0x8CD5, 0x8CD6, 0x8CD7, 0x8CD8, 0x8CD9, 0x8CDA, 0xE5F8, + 0xCDCD, 0x8CDB, 0xC9BD, 0x8CDC, 0x8CDD, 0x8CDE, 0x8CDF, 0x8CE0, 0x8CE1, + 0x8CE2, 0xD2D9, 0xE1A8, 0x8CE3, 0x8CE4, 0x8CE5, 0x8CE6, 0xD3EC, 0x8CE7, + 0xCBEA, 0xC6F1, 0x8CE8, 0x8CE9, 0x8CEA, 0x8CEB, 0x8CEC, 0xE1AC, 0x8CED, + 0x8CEE, 0x8CEF, 0xE1A7, 0xE1A9, 0x8CF0, 0x8CF1, 0xE1AA, 0xE1AF, 0x8CF2, + 0x8CF3, 0xB2ED, 0x8CF4, 0xE1AB, 0xB8DA, 0xE1AD, 0xE1AE, 0xE1B0, 0xB5BA, + 0xE1B1, 0x8CF5, 0x8CF6, 0x8CF7, 0x8CF8, 0x8CF9, 0xE1B3, 0xE1B8, 0x8CFA, + 0x8CFB, 0x8CFC, 0x8CFD, 0x8CFE, 0xD1D2, 0x8D40, 0xE1B6, 0xE1B5, 0xC1EB, + 0x8D41, 0x8D42, 0x8D43, 0xE1B7, 0x8D44, 0xD4C0, 0x8D45, 0xE1B2, 0x8D46, + 0xE1BA, 0xB0B6, 0x8D47, 0x8D48, 0x8D49, 0x8D4A, 0xE1B4, 0x8D4B, 0xBFF9, + 0x8D4C, 0xE1B9, 0x8D4D, 0x8D4E, 0xE1BB, 0x8D4F, 0x8D50, 0x8D51, 0x8D52, + 0x8D53, 0x8D54, 0xE1BE, 0x8D55, 0x8D56, 0x8D57, 0x8D58, 0x8D59, 0x8D5A, + 0xE1BC, 0x8D5B, 0x8D5C, 0x8D5D, 0x8D5E, 0x8D5F, 0x8D60, 0xD6C5, 0x8D61, + 0x8D62, 0x8D63, 0x8D64, 0x8D65, 0x8D66, 0x8D67, 0xCFBF, 0x8D68, 0x8D69, + 0xE1BD, 0xE1BF, 0xC2CD, 0x8D6A, 0xB6EB, 0x8D6B, 0xD3F8, 0x8D6C, 0x8D6D, + 0xC7CD, 0x8D6E, 0x8D6F, 0xB7E5, 0x8D70, 0x8D71, 0x8D72, 0x8D73, 0x8D74, + 0x8D75, 0x8D76, 0x8D77, 0x8D78, 0x8D79, 0xBEFE, 0x8D7A, 0x8D7B, 0x8D7C, + 0x8D7D, 0x8D7E, 0x8D80, 0xE1C0, 0xE1C1, 0x8D81, 0x8D82, 0xE1C7, 0xB3E7, + 0x8D83, 0x8D84, 0x8D85, 0x8D86, 0x8D87, 0x8D88, 0xC6E9, 0x8D89, 0x8D8A, + 0x8D8B, 0x8D8C, 0x8D8D, 0xB4DE, 0x8D8E, 0xD1C2, 0x8D8F, 0x8D90, 0x8D91, + 0x8D92, 0xE1C8, 0x8D93, 0x8D94, 0xE1C6, 0x8D95, 0x8D96, 0x8D97, 0x8D98, + 0x8D99, 0xE1C5, 0x8D9A, 0xE1C3, 0xE1C2, 0x8D9B, 0xB1C0, 0x8D9C, 0x8D9D, + 0x8D9E, 0xD5B8, 0xE1C4, 0x8D9F, 0x8DA0, 0x8DA1, 0x8DA2, 0x8DA3, 0xE1CB, + 0x8DA4, 0x8DA5, 0x8DA6, 0x8DA7, 0x8DA8, 0x8DA9, 0x8DAA, 0x8DAB, 0xE1CC, + 0xE1CA, 0x8DAC, 0x8DAD, 0x8DAE, 0x8DAF, 0x8DB0, 0x8DB1, 0x8DB2, 0x8DB3, + 0xEFFA, 0x8DB4, 0x8DB5, 0xE1D3, 0xE1D2, 0xC7B6, 0x8DB6, 0x8DB7, 0x8DB8, + 0x8DB9, 0x8DBA, 0x8DBB, 0x8DBC, 0x8DBD, 0x8DBE, 0x8DBF, 0x8DC0, 0xE1C9, + 0x8DC1, 0x8DC2, 0xE1CE, 0x8DC3, 0xE1D0, 0x8DC4, 0x8DC5, 0x8DC6, 0x8DC7, + 0x8DC8, 0x8DC9, 0x8DCA, 0x8DCB, 0x8DCC, 0x8DCD, 0x8DCE, 0xE1D4, 0x8DCF, + 0xE1D1, 0xE1CD, 0x8DD0, 0x8DD1, 0xE1CF, 0x8DD2, 0x8DD3, 0x8DD4, 0x8DD5, + 0xE1D5, 0x8DD6, 0x8DD7, 0x8DD8, 0x8DD9, 0x8DDA, 0x8DDB, 0x8DDC, 0x8DDD, + 0x8DDE, 0x8DDF, 0x8DE0, 0x8DE1, 0x8DE2, 0xE1D6, 0x8DE3, 0x8DE4, 0x8DE5, + 0x8DE6, 0x8DE7, 0x8DE8, 0x8DE9, 0x8DEA, 0x8DEB, 0x8DEC, 0x8DED, 0x8DEE, + 0x8DEF, 0x8DF0, 0x8DF1, 0x8DF2, 0x8DF3, 0x8DF4, 0x8DF5, 0x8DF6, 0x8DF7, + 0x8DF8, 0xE1D7, 0x8DF9, 0x8DFA, 0x8DFB, 0xE1D8, 0x8DFC, 0x8DFD, 0x8DFE, + 0x8E40, 0x8E41, 0x8E42, 0x8E43, 0x8E44, 0x8E45, 0x8E46, 0x8E47, 0x8E48, + 0x8E49, 0x8E4A, 0x8E4B, 0x8E4C, 0x8E4D, 0x8E4E, 0x8E4F, 0x8E50, 0x8E51, + 0x8E52, 0x8E53, 0x8E54, 0x8E55, 0xE1DA, 0x8E56, 0x8E57, 0x8E58, 0x8E59, + 0x8E5A, 0x8E5B, 0x8E5C, 0x8E5D, 0x8E5E, 0x8E5F, 0x8E60, 0x8E61, 0x8E62, + 0xE1DB, 0x8E63, 0x8E64, 0x8E65, 0x8E66, 0x8E67, 0x8E68, 0x8E69, 0xCEA1, + 0x8E6A, 0x8E6B, 0x8E6C, 0x8E6D, 0x8E6E, 0x8E6F, 0x8E70, 0x8E71, 0x8E72, + 0x8E73, 0x8E74, 0x8E75, 0x8E76, 0xE7DD, 0x8E77, 0xB4A8, 0xD6DD, 0x8E78, + 0x8E79, 0xD1B2, 0xB3B2, 0x8E7A, 0x8E7B, 0xB9A4, 0xD7F3, 0xC7C9, 0xBEDE, + 0xB9AE, 0x8E7C, 0xCED7, 0x8E7D, 0x8E7E, 0xB2EE, 0xDBCF, 0x8E80, 0xBCBA, + 0xD2D1, 0xCBC8, 0xB0CD, 0x8E81, 0x8E82, 0xCFEF, 0x8E83, 0x8E84, 0x8E85, + 0x8E86, 0x8E87, 0xD9E3, 0xBDED, 0x8E88, 0x8E89, 0xB1D2, 0xCAD0, 0xB2BC, + 0x8E8A, 0xCBA7, 0xB7AB, 0x8E8B, 0xCAA6, 0x8E8C, 0x8E8D, 0x8E8E, 0xCFA3, + 0x8E8F, 0x8E90, 0xE0F8, 0xD5CA, 0xE0FB, 0x8E91, 0x8E92, 0xE0FA, 0xC5C1, + 0xCCFB, 0x8E93, 0xC1B1, 0xE0F9, 0xD6E3, 0xB2AF, 0xD6C4, 0xB5DB, 0x8E94, + 0x8E95, 0x8E96, 0x8E97, 0x8E98, 0x8E99, 0x8E9A, 0x8E9B, 0xB4F8, 0xD6A1, + 0x8E9C, 0x8E9D, 0x8E9E, 0x8E9F, 0x8EA0, 0xCFAF, 0xB0EF, 0x8EA1, 0x8EA2, + 0xE0FC, 0x8EA3, 0x8EA4, 0x8EA5, 0x8EA6, 0x8EA7, 0xE1A1, 0xB3A3, 0x8EA8, + 0x8EA9, 0xE0FD, 0xE0FE, 0xC3B1, 0x8EAA, 0x8EAB, 0x8EAC, 0x8EAD, 0xC3DD, + 0x8EAE, 0xE1A2, 0xB7F9, 0x8EAF, 0x8EB0, 0x8EB1, 0x8EB2, 0x8EB3, 0x8EB4, + 0xBBCF, 0x8EB5, 0x8EB6, 0x8EB7, 0x8EB8, 0x8EB9, 0x8EBA, 0x8EBB, 0xE1A3, + 0xC4BB, 0x8EBC, 0x8EBD, 0x8EBE, 0x8EBF, 0x8EC0, 0xE1A4, 0x8EC1, 0x8EC2, + 0xE1A5, 0x8EC3, 0x8EC4, 0xE1A6, 0xB4B1, 0x8EC5, 0x8EC6, 0x8EC7, 0x8EC8, + 0x8EC9, 0x8ECA, 0x8ECB, 0x8ECC, 0x8ECD, 0x8ECE, 0x8ECF, 0x8ED0, 0x8ED1, + 0x8ED2, 0x8ED3, 0xB8C9, 0xC6BD, 0xC4EA, 0x8ED4, 0xB2A2, 0x8ED5, 0xD0D2, + 0x8ED6, 0xE7DB, 0xBBC3, 0xD3D7, 0xD3C4, 0x8ED7, 0xB9E3, 0xE2CF, 0x8ED8, + 0x8ED9, 0x8EDA, 0xD7AF, 0x8EDB, 0xC7EC, 0xB1D3, 0x8EDC, 0x8EDD, 0xB4B2, + 0xE2D1, 0x8EDE, 0x8EDF, 0x8EE0, 0xD0F2, 0xC2AE, 0xE2D0, 0x8EE1, 0xBFE2, + 0xD3A6, 0xB5D7, 0xE2D2, 0xB5EA, 0x8EE2, 0xC3ED, 0xB8FD, 0x8EE3, 0xB8AE, + 0x8EE4, 0xC5D3, 0xB7CF, 0xE2D4, 0x8EE5, 0x8EE6, 0x8EE7, 0x8EE8, 0xE2D3, + 0xB6C8, 0xD7F9, 0x8EE9, 0x8EEA, 0x8EEB, 0x8EEC, 0x8EED, 0xCDA5, 0x8EEE, + 0x8EEF, 0x8EF0, 0x8EF1, 0x8EF2, 0xE2D8, 0x8EF3, 0xE2D6, 0xCAFC, 0xBFB5, + 0xD3B9, 0xE2D5, 0x8EF4, 0x8EF5, 0x8EF6, 0x8EF7, 0xE2D7, 0x8EF8, 0x8EF9, + 0x8EFA, 0x8EFB, 0x8EFC, 0x8EFD, 0x8EFE, 0x8F40, 0x8F41, 0x8F42, 0xC1AE, + 0xC0C8, 0x8F43, 0x8F44, 0x8F45, 0x8F46, 0x8F47, 0x8F48, 0xE2DB, 0xE2DA, + 0xC0AA, 0x8F49, 0x8F4A, 0xC1CE, 0x8F4B, 0x8F4C, 0x8F4D, 0x8F4E, 0xE2DC, + 0x8F4F, 0x8F50, 0x8F51, 0x8F52, 0x8F53, 0x8F54, 0x8F55, 0x8F56, 0x8F57, + 0x8F58, 0x8F59, 0x8F5A, 0xE2DD, 0x8F5B, 0xE2DE, 0x8F5C, 0x8F5D, 0x8F5E, + 0x8F5F, 0x8F60, 0x8F61, 0x8F62, 0x8F63, 0x8F64, 0xDBC8, 0x8F65, 0xD1D3, + 0xCDA2, 0x8F66, 0x8F67, 0xBDA8, 0x8F68, 0x8F69, 0x8F6A, 0xDEC3, 0xD8A5, + 0xBFAA, 0xDBCD, 0xD2EC, 0xC6FA, 0xC5AA, 0x8F6B, 0x8F6C, 0x8F6D, 0xDEC4, + 0x8F6E, 0xB1D7, 0xDFAE, 0x8F6F, 0x8F70, 0x8F71, 0xCABD, 0x8F72, 0xDFB1, + 0x8F73, 0xB9AD, 0x8F74, 0xD2FD, 0x8F75, 0xB8A5, 0xBAEB, 0x8F76, 0x8F77, + 0xB3DA, 0x8F78, 0x8F79, 0x8F7A, 0xB5DC, 0xD5C5, 0x8F7B, 0x8F7C, 0x8F7D, + 0x8F7E, 0xC3D6, 0xCFD2, 0xBBA1, 0x8F80, 0xE5F3, 0xE5F2, 0x8F81, 0x8F82, + 0xE5F4, 0x8F83, 0xCDE4, 0x8F84, 0xC8F5, 0x8F85, 0x8F86, 0x8F87, 0x8F88, + 0x8F89, 0x8F8A, 0x8F8B, 0xB5AF, 0xC7BF, 0x8F8C, 0xE5F6, 0x8F8D, 0x8F8E, + 0x8F8F, 0xECB0, 0x8F90, 0x8F91, 0x8F92, 0x8F93, 0x8F94, 0x8F95, 0x8F96, + 0x8F97, 0x8F98, 0x8F99, 0x8F9A, 0x8F9B, 0x8F9C, 0x8F9D, 0x8F9E, 0xE5E6, + 0x8F9F, 0xB9E9, 0xB5B1, 0x8FA0, 0xC2BC, 0xE5E8, 0xE5E7, 0xE5E9, 0x8FA1, + 0x8FA2, 0x8FA3, 0x8FA4, 0xD2CD, 0x8FA5, 0x8FA6, 0x8FA7, 0xE1EA, 0xD0CE, + 0x8FA8, 0xCDAE, 0x8FA9, 0xD1E5, 0x8FAA, 0x8FAB, 0xB2CA, 0xB1EB, 0x8FAC, + 0xB1F2, 0xC5ED, 0x8FAD, 0x8FAE, 0xD5C3, 0xD3B0, 0x8FAF, 0xE1DC, 0x8FB0, + 0x8FB1, 0x8FB2, 0xE1DD, 0x8FB3, 0xD2DB, 0x8FB4, 0xB3B9, 0xB1CB, 0x8FB5, + 0x8FB6, 0x8FB7, 0xCDF9, 0xD5F7, 0xE1DE, 0x8FB8, 0xBEB6, 0xB4FD, 0x8FB9, + 0xE1DF, 0xBADC, 0xE1E0, 0xBBB2, 0xC2C9, 0xE1E1, 0x8FBA, 0x8FBB, 0x8FBC, + 0xD0EC, 0x8FBD, 0xCDBD, 0x8FBE, 0x8FBF, 0xE1E2, 0x8FC0, 0xB5C3, 0xC5C7, + 0xE1E3, 0x8FC1, 0x8FC2, 0xE1E4, 0x8FC3, 0x8FC4, 0x8FC5, 0x8FC6, 0xD3F9, + 0x8FC7, 0x8FC8, 0x8FC9, 0x8FCA, 0x8FCB, 0x8FCC, 0xE1E5, 0x8FCD, 0xD1AD, + 0x8FCE, 0x8FCF, 0xE1E6, 0xCEA2, 0x8FD0, 0x8FD1, 0x8FD2, 0x8FD3, 0x8FD4, + 0x8FD5, 0xE1E7, 0x8FD6, 0xB5C2, 0x8FD7, 0x8FD8, 0x8FD9, 0x8FDA, 0xE1E8, + 0xBBD5, 0x8FDB, 0x8FDC, 0x8FDD, 0x8FDE, 0x8FDF, 0xD0C4, 0xE2E0, 0xB1D8, + 0xD2E4, 0x8FE0, 0x8FE1, 0xE2E1, 0x8FE2, 0x8FE3, 0xBCC9, 0xC8CC, 0x8FE4, + 0xE2E3, 0xECFE, 0xECFD, 0xDFAF, 0x8FE5, 0x8FE6, 0x8FE7, 0xE2E2, 0xD6BE, + 0xCDFC, 0xC3A6, 0x8FE8, 0x8FE9, 0x8FEA, 0xE3C3, 0x8FEB, 0x8FEC, 0xD6D2, + 0xE2E7, 0x8FED, 0x8FEE, 0xE2E8, 0x8FEF, 0x8FF0, 0xD3C7, 0x8FF1, 0x8FF2, + 0xE2EC, 0xBFEC, 0x8FF3, 0xE2ED, 0xE2E5, 0x8FF4, 0x8FF5, 0xB3C0, 0x8FF6, + 0x8FF7, 0x8FF8, 0xC4EE, 0x8FF9, 0x8FFA, 0xE2EE, 0x8FFB, 0x8FFC, 0xD0C3, + 0x8FFD, 0xBAF6, 0xE2E9, 0xB7DE, 0xBBB3, 0xCCAC, 0xCBCB, 0xE2E4, 0xE2E6, + 0xE2EA, 0xE2EB, 0x8FFE, 0x9040, 0x9041, 0xE2F7, 0x9042, 0x9043, 0xE2F4, + 0xD4F5, 0xE2F3, 0x9044, 0x9045, 0xC5AD, 0x9046, 0xD5FA, 0xC5C2, 0xB2C0, + 0x9047, 0x9048, 0xE2EF, 0x9049, 0xE2F2, 0xC1AF, 0xCBBC, 0x904A, 0x904B, + 0xB5A1, 0xE2F9, 0x904C, 0x904D, 0x904E, 0xBCB1, 0xE2F1, 0xD0D4, 0xD4B9, + 0xE2F5, 0xB9D6, 0xE2F6, 0x904F, 0x9050, 0x9051, 0xC7D3, 0x9052, 0x9053, + 0x9054, 0x9055, 0x9056, 0xE2F0, 0x9057, 0x9058, 0x9059, 0x905A, 0x905B, + 0xD7DC, 0xEDA1, 0x905C, 0x905D, 0xE2F8, 0x905E, 0xEDA5, 0xE2FE, 0xCAD1, + 0x905F, 0x9060, 0x9061, 0x9062, 0x9063, 0x9064, 0x9065, 0xC1B5, 0x9066, + 0xBBD0, 0x9067, 0x9068, 0xBFD6, 0x9069, 0xBAE3, 0x906A, 0x906B, 0xCBA1, + 0x906C, 0x906D, 0x906E, 0xEDA6, 0xEDA3, 0x906F, 0x9070, 0xEDA2, 0x9071, + 0x9072, 0x9073, 0x9074, 0xBBD6, 0xEDA7, 0xD0F4, 0x9075, 0x9076, 0xEDA4, + 0xBADE, 0xB6F7, 0xE3A1, 0xB6B2, 0xCCF1, 0xB9A7, 0x9077, 0xCFA2, 0xC7A1, + 0x9078, 0x9079, 0xBFD2, 0x907A, 0x907B, 0xB6F1, 0x907C, 0xE2FA, 0xE2FB, + 0xE2FD, 0xE2FC, 0xC4D5, 0xE3A2, 0x907D, 0xD3C1, 0x907E, 0x9080, 0x9081, + 0xE3A7, 0xC7C4, 0x9082, 0x9083, 0x9084, 0x9085, 0xCFA4, 0x9086, 0x9087, + 0xE3A9, 0xBAB7, 0x9088, 0x9089, 0x908A, 0x908B, 0xE3A8, 0x908C, 0xBBDA, + 0x908D, 0xE3A3, 0x908E, 0x908F, 0x9090, 0xE3A4, 0xE3AA, 0x9091, 0xE3A6, + 0x9092, 0xCEF2, 0xD3C6, 0x9093, 0x9094, 0xBBBC, 0x9095, 0x9096, 0xD4C3, + 0x9097, 0xC4FA, 0x9098, 0x9099, 0xEDA8, 0xD0FC, 0xE3A5, 0x909A, 0xC3F5, + 0x909B, 0xE3AD, 0xB1AF, 0x909C, 0xE3B2, 0x909D, 0x909E, 0x909F, 0xBCC2, + 0x90A0, 0x90A1, 0xE3AC, 0xB5BF, 0x90A2, 0x90A3, 0x90A4, 0x90A5, 0x90A6, + 0x90A7, 0x90A8, 0x90A9, 0xC7E9, 0xE3B0, 0x90AA, 0x90AB, 0x90AC, 0xBEAA, + 0xCDEF, 0x90AD, 0x90AE, 0x90AF, 0x90B0, 0x90B1, 0xBBF3, 0x90B2, 0x90B3, + 0x90B4, 0xCCE8, 0x90B5, 0x90B6, 0xE3AF, 0x90B7, 0xE3B1, 0x90B8, 0xCFA7, + 0xE3AE, 0x90B9, 0xCEA9, 0xBBDD, 0x90BA, 0x90BB, 0x90BC, 0x90BD, 0x90BE, + 0xB5EB, 0xBEE5, 0xB2D2, 0xB3CD, 0x90BF, 0xB1B9, 0xE3AB, 0xB2D1, 0xB5AC, + 0xB9DF, 0xB6E8, 0x90C0, 0x90C1, 0xCFEB, 0xE3B7, 0x90C2, 0xBBCC, 0x90C3, + 0x90C4, 0xC8C7, 0xD0CA, 0x90C5, 0x90C6, 0x90C7, 0x90C8, 0x90C9, 0xE3B8, + 0xB3EE, 0x90CA, 0x90CB, 0x90CC, 0x90CD, 0xEDA9, 0x90CE, 0xD3FA, 0xD3E4, + 0x90CF, 0x90D0, 0x90D1, 0xEDAA, 0xE3B9, 0xD2E2, 0x90D2, 0x90D3, 0x90D4, + 0x90D5, 0x90D6, 0xE3B5, 0x90D7, 0x90D8, 0x90D9, 0x90DA, 0xD3DE, 0x90DB, + 0x90DC, 0x90DD, 0x90DE, 0xB8D0, 0xE3B3, 0x90DF, 0x90E0, 0xE3B6, 0xB7DF, + 0x90E1, 0xE3B4, 0xC0A2, 0x90E2, 0x90E3, 0x90E4, 0xE3BA, 0x90E5, 0x90E6, + 0x90E7, 0x90E8, 0x90E9, 0x90EA, 0x90EB, 0x90EC, 0x90ED, 0x90EE, 0x90EF, + 0x90F0, 0x90F1, 0x90F2, 0x90F3, 0x90F4, 0x90F5, 0x90F6, 0x90F7, 0xD4B8, + 0x90F8, 0x90F9, 0x90FA, 0x90FB, 0x90FC, 0x90FD, 0x90FE, 0x9140, 0xB4C8, + 0x9141, 0xE3BB, 0x9142, 0xBBC5, 0x9143, 0xC9F7, 0x9144, 0x9145, 0xC9E5, + 0x9146, 0x9147, 0x9148, 0xC4BD, 0x9149, 0x914A, 0x914B, 0x914C, 0x914D, + 0x914E, 0x914F, 0xEDAB, 0x9150, 0x9151, 0x9152, 0x9153, 0xC2FD, 0x9154, + 0x9155, 0x9156, 0x9157, 0xBBDB, 0xBFAE, 0x9158, 0x9159, 0x915A, 0x915B, + 0x915C, 0x915D, 0x915E, 0xCEBF, 0x915F, 0x9160, 0x9161, 0x9162, 0xE3BC, + 0x9163, 0xBFB6, 0x9164, 0x9165, 0x9166, 0x9167, 0x9168, 0x9169, 0x916A, + 0x916B, 0x916C, 0x916D, 0x916E, 0x916F, 0x9170, 0x9171, 0x9172, 0x9173, + 0x9174, 0x9175, 0x9176, 0xB1EF, 0x9177, 0x9178, 0xD4F7, 0x9179, 0x917A, + 0x917B, 0x917C, 0x917D, 0xE3BE, 0x917E, 0x9180, 0x9181, 0x9182, 0x9183, + 0x9184, 0x9185, 0x9186, 0xEDAD, 0x9187, 0x9188, 0x9189, 0x918A, 0x918B, + 0x918C, 0x918D, 0x918E, 0x918F, 0xE3BF, 0xBAA9, 0xEDAC, 0x9190, 0x9191, + 0xE3BD, 0x9192, 0x9193, 0x9194, 0x9195, 0x9196, 0x9197, 0x9198, 0x9199, + 0x919A, 0x919B, 0xE3C0, 0x919C, 0x919D, 0x919E, 0x919F, 0x91A0, 0x91A1, + 0xBAB6, 0x91A2, 0x91A3, 0x91A4, 0xB6AE, 0x91A5, 0x91A6, 0x91A7, 0x91A8, + 0x91A9, 0xD0B8, 0x91AA, 0xB0C3, 0xEDAE, 0x91AB, 0x91AC, 0x91AD, 0x91AE, + 0x91AF, 0xEDAF, 0xC0C1, 0x91B0, 0xE3C1, 0x91B1, 0x91B2, 0x91B3, 0x91B4, + 0x91B5, 0x91B6, 0x91B7, 0x91B8, 0x91B9, 0x91BA, 0x91BB, 0x91BC, 0x91BD, + 0x91BE, 0x91BF, 0x91C0, 0x91C1, 0xC5B3, 0x91C2, 0x91C3, 0x91C4, 0x91C5, + 0x91C6, 0x91C7, 0x91C8, 0x91C9, 0x91CA, 0x91CB, 0x91CC, 0x91CD, 0x91CE, + 0x91CF, 0xE3C2, 0x91D0, 0x91D1, 0x91D2, 0x91D3, 0x91D4, 0x91D5, 0x91D6, + 0x91D7, 0x91D8, 0xDCB2, 0x91D9, 0x91DA, 0x91DB, 0x91DC, 0x91DD, 0x91DE, + 0xEDB0, 0x91DF, 0xB8EA, 0x91E0, 0xCEEC, 0xEAA7, 0xD0E7, 0xCAF9, 0xC8D6, + 0xCFB7, 0xB3C9, 0xCED2, 0xBDE4, 0x91E1, 0x91E2, 0xE3DE, 0xBBF2, 0xEAA8, + 0xD5BD, 0x91E3, 0xC6DD, 0xEAA9, 0x91E4, 0x91E5, 0x91E6, 0xEAAA, 0x91E7, + 0xEAAC, 0xEAAB, 0x91E8, 0xEAAE, 0xEAAD, 0x91E9, 0x91EA, 0x91EB, 0x91EC, + 0xBDD8, 0x91ED, 0xEAAF, 0x91EE, 0xC2BE, 0x91EF, 0x91F0, 0x91F1, 0x91F2, + 0xB4C1, 0xB4F7, 0x91F3, 0x91F4, 0xBBA7, 0x91F5, 0x91F6, 0x91F7, 0x91F8, + 0x91F9, 0xECE6, 0xECE5, 0xB7BF, 0xCBF9, 0xB1E2, 0x91FA, 0xECE7, 0x91FB, + 0x91FC, 0x91FD, 0xC9C8, 0xECE8, 0xECE9, 0x91FE, 0xCAD6, 0xDED0, 0xB2C5, + 0xD4FA, 0x9240, 0x9241, 0xC6CB, 0xB0C7, 0xB4F2, 0xC8D3, 0x9242, 0x9243, + 0x9244, 0xCDD0, 0x9245, 0x9246, 0xBFB8, 0x9247, 0x9248, 0x9249, 0x924A, + 0x924B, 0x924C, 0x924D, 0xBFDB, 0x924E, 0x924F, 0xC7A4, 0xD6B4, 0x9250, + 0xC0A9, 0xDED1, 0xC9A8, 0xD1EF, 0xC5A4, 0xB0E7, 0xB3B6, 0xC8C5, 0x9251, + 0x9252, 0xB0E2, 0x9253, 0x9254, 0xB7F6, 0x9255, 0x9256, 0xC5FA, 0x9257, + 0x9258, 0xB6F3, 0x9259, 0xD5D2, 0xB3D0, 0xBCBC, 0x925A, 0x925B, 0x925C, + 0xB3AD, 0x925D, 0x925E, 0x925F, 0x9260, 0xBEF1, 0xB0D1, 0x9261, 0x9262, + 0x9263, 0x9264, 0x9265, 0x9266, 0xD2D6, 0xCAE3, 0xD7A5, 0x9267, 0xCDB6, + 0xB6B6, 0xBFB9, 0xD5DB, 0x9268, 0xB8A7, 0xC5D7, 0x9269, 0x926A, 0x926B, + 0xDED2, 0xBFD9, 0xC2D5, 0xC7C0, 0x926C, 0xBBA4, 0xB1A8, 0x926D, 0x926E, + 0xC5EA, 0x926F, 0x9270, 0xC5FB, 0xCCA7, 0x9271, 0x9272, 0x9273, 0x9274, + 0xB1A7, 0x9275, 0x9276, 0x9277, 0xB5D6, 0x9278, 0x9279, 0x927A, 0xC4A8, + 0x927B, 0xDED3, 0xD1BA, 0xB3E9, 0x927C, 0xC3F2, 0x927D, 0x927E, 0xB7F7, + 0x9280, 0xD6F4, 0xB5A3, 0xB2F0, 0xC4B4, 0xC4E9, 0xC0AD, 0xDED4, 0x9281, + 0xB0E8, 0xC5C4, 0xC1E0, 0x9282, 0xB9D5, 0x9283, 0xBEDC, 0xCDD8, 0xB0CE, + 0x9284, 0xCDCF, 0xDED6, 0xBED0, 0xD7BE, 0xDED5, 0xD5D0, 0xB0DD, 0x9285, + 0x9286, 0xC4E2, 0x9287, 0x9288, 0xC2A3, 0xBCF0, 0x9289, 0xD3B5, 0xC0B9, + 0xC5A1, 0xB2A6, 0xD4F1, 0x928A, 0x928B, 0xC0A8, 0xCAC3, 0xDED7, 0xD5FC, + 0x928C, 0xB9B0, 0x928D, 0xC8AD, 0xCBA9, 0x928E, 0xDED9, 0xBFBD, 0x928F, + 0x9290, 0x9291, 0x9292, 0xC6B4, 0xD7A7, 0xCAB0, 0xC4C3, 0x9293, 0xB3D6, + 0xB9D2, 0x9294, 0x9295, 0x9296, 0x9297, 0xD6B8, 0xEAFC, 0xB0B4, 0x9298, + 0x9299, 0x929A, 0x929B, 0xBFE6, 0x929C, 0x929D, 0xCCF4, 0x929E, 0x929F, + 0x92A0, 0x92A1, 0xCDDA, 0x92A2, 0x92A3, 0x92A4, 0xD6BF, 0xC2CE, 0x92A5, + 0xCECE, 0xCCA2, 0xD0AE, 0xC4D3, 0xB5B2, 0xDED8, 0xD5F5, 0xBCB7, 0xBBD3, + 0x92A6, 0x92A7, 0xB0A4, 0x92A8, 0xC5B2, 0xB4EC, 0x92A9, 0x92AA, 0x92AB, + 0xD5F1, 0x92AC, 0x92AD, 0xEAFD, 0x92AE, 0x92AF, 0x92B0, 0x92B1, 0x92B2, + 0x92B3, 0xDEDA, 0xCDA6, 0x92B4, 0x92B5, 0xCDEC, 0x92B6, 0x92B7, 0x92B8, + 0x92B9, 0xCEE6, 0xDEDC, 0x92BA, 0xCDB1, 0xC0A6, 0x92BB, 0x92BC, 0xD7BD, + 0x92BD, 0xDEDB, 0xB0C6, 0xBAB4, 0xC9D3, 0xC4F3, 0xBEE8, 0x92BE, 0x92BF, + 0x92C0, 0x92C1, 0xB2B6, 0x92C2, 0x92C3, 0x92C4, 0x92C5, 0x92C6, 0x92C7, + 0x92C8, 0x92C9, 0xC0CC, 0xCBF0, 0x92CA, 0xBCF1, 0xBBBB, 0xB5B7, 0x92CB, + 0x92CC, 0x92CD, 0xC5F5, 0x92CE, 0xDEE6, 0x92CF, 0x92D0, 0x92D1, 0xDEE3, + 0xBEDD, 0x92D2, 0x92D3, 0xDEDF, 0x92D4, 0x92D5, 0x92D6, 0x92D7, 0xB4B7, + 0xBDDD, 0x92D8, 0x92D9, 0xDEE0, 0xC4ED, 0x92DA, 0x92DB, 0x92DC, 0x92DD, + 0xCFC6, 0x92DE, 0xB5E0, 0x92DF, 0x92E0, 0x92E1, 0x92E2, 0xB6DE, 0xCADA, + 0xB5F4, 0xDEE5, 0x92E3, 0xD5C6, 0x92E4, 0xDEE1, 0xCCCD, 0xC6FE, 0x92E5, + 0xC5C5, 0x92E6, 0x92E7, 0x92E8, 0xD2B4, 0x92E9, 0xBEF2, 0x92EA, 0x92EB, + 0x92EC, 0x92ED, 0x92EE, 0x92EF, 0x92F0, 0xC2D3, 0x92F1, 0xCCBD, 0xB3B8, + 0x92F2, 0xBDD3, 0x92F3, 0xBFD8, 0xCDC6, 0xD1DA, 0xB4EB, 0x92F4, 0xDEE4, + 0xDEDD, 0xDEE7, 0x92F5, 0xEAFE, 0x92F6, 0x92F7, 0xC2B0, 0xDEE2, 0x92F8, + 0x92F9, 0xD6C0, 0xB5A7, 0x92FA, 0xB2F4, 0x92FB, 0xDEE8, 0x92FC, 0xDEF2, + 0x92FD, 0x92FE, 0x9340, 0x9341, 0x9342, 0xDEED, 0x9343, 0xDEF1, 0x9344, + 0x9345, 0xC8E0, 0x9346, 0x9347, 0x9348, 0xD7E1, 0xDEEF, 0xC3E8, 0xCCE1, + 0x9349, 0xB2E5, 0x934A, 0x934B, 0x934C, 0xD2BE, 0x934D, 0x934E, 0x934F, + 0x9350, 0x9351, 0x9352, 0x9353, 0xDEEE, 0x9354, 0xDEEB, 0xCED5, 0x9355, + 0xB4A7, 0x9356, 0x9357, 0x9358, 0x9359, 0x935A, 0xBFAB, 0xBEBE, 0x935B, + 0x935C, 0xBDD2, 0x935D, 0x935E, 0x935F, 0x9360, 0xDEE9, 0x9361, 0xD4AE, + 0x9362, 0xDEDE, 0x9363, 0xDEEA, 0x9364, 0x9365, 0x9366, 0x9367, 0xC0BF, + 0x9368, 0xDEEC, 0xB2F3, 0xB8E9, 0xC2A7, 0x9369, 0x936A, 0xBDC1, 0x936B, + 0x936C, 0x936D, 0x936E, 0x936F, 0xDEF5, 0xDEF8, 0x9370, 0x9371, 0xB2AB, + 0xB4A4, 0x9372, 0x9373, 0xB4EA, 0xC9A6, 0x9374, 0x9375, 0x9376, 0x9377, + 0x9378, 0x9379, 0xDEF6, 0xCBD1, 0x937A, 0xB8E3, 0x937B, 0xDEF7, 0xDEFA, + 0x937C, 0x937D, 0x937E, 0x9380, 0xDEF9, 0x9381, 0x9382, 0x9383, 0xCCC2, + 0x9384, 0xB0E1, 0xB4EE, 0x9385, 0x9386, 0x9387, 0x9388, 0x9389, 0x938A, + 0xE5BA, 0x938B, 0x938C, 0x938D, 0x938E, 0x938F, 0xD0AF, 0x9390, 0x9391, + 0xB2EB, 0x9392, 0xEBA1, 0x9393, 0xDEF4, 0x9394, 0x9395, 0xC9E3, 0xDEF3, + 0xB0DA, 0xD2A1, 0xB1F7, 0x9396, 0xCCAF, 0x9397, 0x9398, 0x9399, 0x939A, + 0x939B, 0x939C, 0x939D, 0xDEF0, 0x939E, 0xCBA4, 0x939F, 0x93A0, 0x93A1, + 0xD5AA, 0x93A2, 0x93A3, 0x93A4, 0x93A5, 0x93A6, 0xDEFB, 0x93A7, 0x93A8, + 0x93A9, 0x93AA, 0x93AB, 0x93AC, 0x93AD, 0x93AE, 0xB4DD, 0x93AF, 0xC4A6, + 0x93B0, 0x93B1, 0x93B2, 0xDEFD, 0x93B3, 0x93B4, 0x93B5, 0x93B6, 0x93B7, + 0x93B8, 0x93B9, 0x93BA, 0x93BB, 0x93BC, 0xC3FE, 0xC4A1, 0xDFA1, 0x93BD, + 0x93BE, 0x93BF, 0x93C0, 0x93C1, 0x93C2, 0x93C3, 0xC1CC, 0x93C4, 0xDEFC, + 0xBEEF, 0x93C5, 0xC6B2, 0x93C6, 0x93C7, 0x93C8, 0x93C9, 0x93CA, 0x93CB, + 0x93CC, 0x93CD, 0x93CE, 0xB3C5, 0xC8F6, 0x93CF, 0x93D0, 0xCBBA, 0xDEFE, + 0x93D1, 0x93D2, 0xDFA4, 0x93D3, 0x93D4, 0x93D5, 0x93D6, 0xD7B2, 0x93D7, + 0x93D8, 0x93D9, 0x93DA, 0x93DB, 0xB3B7, 0x93DC, 0x93DD, 0x93DE, 0x93DF, + 0xC1C3, 0x93E0, 0x93E1, 0xC7CB, 0xB2A5, 0xB4E9, 0x93E2, 0xD7AB, 0x93E3, + 0x93E4, 0x93E5, 0x93E6, 0xC4EC, 0x93E7, 0xDFA2, 0xDFA3, 0x93E8, 0xDFA5, + 0x93E9, 0xBAB3, 0x93EA, 0x93EB, 0x93EC, 0xDFA6, 0x93ED, 0xC0DE, 0x93EE, + 0x93EF, 0xC9C3, 0x93F0, 0x93F1, 0x93F2, 0x93F3, 0x93F4, 0x93F5, 0x93F6, + 0xB2D9, 0xC7E6, 0x93F7, 0xDFA7, 0x93F8, 0xC7DC, 0x93F9, 0x93FA, 0x93FB, + 0x93FC, 0xDFA8, 0xEBA2, 0x93FD, 0x93FE, 0x9440, 0x9441, 0x9442, 0xCBD3, + 0x9443, 0x9444, 0x9445, 0xDFAA, 0x9446, 0xDFA9, 0x9447, 0xB2C1, 0x9448, + 0x9449, 0x944A, 0x944B, 0x944C, 0x944D, 0x944E, 0x944F, 0x9450, 0x9451, + 0x9452, 0x9453, 0x9454, 0x9455, 0x9456, 0x9457, 0x9458, 0x9459, 0x945A, + 0x945B, 0x945C, 0x945D, 0x945E, 0x945F, 0x9460, 0xC5CA, 0x9461, 0x9462, + 0x9463, 0x9464, 0x9465, 0x9466, 0x9467, 0x9468, 0xDFAB, 0x9469, 0x946A, + 0x946B, 0x946C, 0x946D, 0x946E, 0x946F, 0x9470, 0xD4DC, 0x9471, 0x9472, + 0x9473, 0x9474, 0x9475, 0xC8C1, 0x9476, 0x9477, 0x9478, 0x9479, 0x947A, + 0x947B, 0x947C, 0x947D, 0x947E, 0x9480, 0x9481, 0x9482, 0xDFAC, 0x9483, + 0x9484, 0x9485, 0x9486, 0x9487, 0xBEF0, 0x9488, 0x9489, 0xDFAD, 0xD6A7, + 0x948A, 0x948B, 0x948C, 0x948D, 0xEAB7, 0xEBB6, 0xCAD5, 0x948E, 0xD8FC, + 0xB8C4, 0x948F, 0xB9A5, 0x9490, 0x9491, 0xB7C5, 0xD5FE, 0x9492, 0x9493, + 0x9494, 0x9495, 0x9496, 0xB9CA, 0x9497, 0x9498, 0xD0A7, 0xF4CD, 0x9499, + 0x949A, 0xB5D0, 0x949B, 0x949C, 0xC3F4, 0x949D, 0xBEC8, 0x949E, 0x949F, + 0x94A0, 0xEBB7, 0xB0BD, 0x94A1, 0x94A2, 0xBDCC, 0x94A3, 0xC1B2, 0x94A4, + 0xB1D6, 0xB3A8, 0x94A5, 0x94A6, 0x94A7, 0xB8D2, 0xC9A2, 0x94A8, 0x94A9, + 0xB6D8, 0x94AA, 0x94AB, 0x94AC, 0x94AD, 0xEBB8, 0xBEB4, 0x94AE, 0x94AF, + 0x94B0, 0xCAFD, 0x94B1, 0xC7C3, 0x94B2, 0xD5FB, 0x94B3, 0x94B4, 0xB7F3, + 0x94B5, 0x94B6, 0x94B7, 0x94B8, 0x94B9, 0x94BA, 0x94BB, 0x94BC, 0x94BD, + 0x94BE, 0x94BF, 0x94C0, 0x94C1, 0x94C2, 0x94C3, 0xCEC4, 0x94C4, 0x94C5, + 0x94C6, 0xD5AB, 0xB1F3, 0x94C7, 0x94C8, 0x94C9, 0xECB3, 0xB0DF, 0x94CA, + 0xECB5, 0x94CB, 0x94CC, 0x94CD, 0xB6B7, 0x94CE, 0xC1CF, 0x94CF, 0xF5FA, + 0xD0B1, 0x94D0, 0x94D1, 0xD5E5, 0x94D2, 0xCED3, 0x94D3, 0x94D4, 0xBDEF, + 0xB3E2, 0x94D5, 0xB8AB, 0x94D6, 0xD5B6, 0x94D7, 0xEDBD, 0x94D8, 0xB6CF, + 0x94D9, 0xCBB9, 0xD0C2, 0x94DA, 0x94DB, 0x94DC, 0x94DD, 0x94DE, 0x94DF, + 0x94E0, 0x94E1, 0xB7BD, 0x94E2, 0x94E3, 0xECB6, 0xCAA9, 0x94E4, 0x94E5, + 0x94E6, 0xC5D4, 0x94E7, 0xECB9, 0xECB8, 0xC2C3, 0xECB7, 0x94E8, 0x94E9, + 0x94EA, 0x94EB, 0xD0FD, 0xECBA, 0x94EC, 0xECBB, 0xD7E5, 0x94ED, 0x94EE, + 0xECBC, 0x94EF, 0x94F0, 0x94F1, 0xECBD, 0xC6EC, 0x94F2, 0x94F3, 0x94F4, + 0x94F5, 0x94F6, 0x94F7, 0x94F8, 0x94F9, 0xCEDE, 0x94FA, 0xBCC8, 0x94FB, + 0x94FC, 0xC8D5, 0xB5A9, 0xBEC9, 0xD6BC, 0xD4E7, 0x94FD, 0x94FE, 0xD1AE, + 0xD0F1, 0xEAB8, 0xEAB9, 0xEABA, 0xBAB5, 0x9540, 0x9541, 0x9542, 0x9543, + 0xCAB1, 0xBFF5, 0x9544, 0x9545, 0xCDFA, 0x9546, 0x9547, 0x9548, 0x9549, + 0x954A, 0xEAC0, 0x954B, 0xB0BA, 0xEABE, 0x954C, 0x954D, 0xC0A5, 0x954E, + 0x954F, 0x9550, 0xEABB, 0x9551, 0xB2FD, 0x9552, 0xC3F7, 0xBBE8, 0x9553, + 0x9554, 0x9555, 0xD2D7, 0xCEF4, 0xEABF, 0x9556, 0x9557, 0x9558, 0xEABC, + 0x9559, 0x955A, 0x955B, 0xEAC3, 0x955C, 0xD0C7, 0xD3B3, 0x955D, 0x955E, + 0x955F, 0x9560, 0xB4BA, 0x9561, 0xC3C1, 0xD7F2, 0x9562, 0x9563, 0x9564, + 0x9565, 0xD5D1, 0x9566, 0xCAC7, 0x9567, 0xEAC5, 0x9568, 0x9569, 0xEAC4, + 0xEAC7, 0xEAC6, 0x956A, 0x956B, 0x956C, 0x956D, 0x956E, 0xD6E7, 0x956F, + 0xCFD4, 0x9570, 0x9571, 0xEACB, 0x9572, 0xBBCE, 0x9573, 0x9574, 0x9575, + 0x9576, 0x9577, 0x9578, 0x9579, 0xBDFA, 0xC9CE, 0x957A, 0x957B, 0xEACC, + 0x957C, 0x957D, 0xC9B9, 0xCFFE, 0xEACA, 0xD4CE, 0xEACD, 0xEACF, 0x957E, + 0x9580, 0xCDED, 0x9581, 0x9582, 0x9583, 0x9584, 0xEAC9, 0x9585, 0xEACE, + 0x9586, 0x9587, 0xCEEE, 0x9588, 0xBBDE, 0x9589, 0xB3BF, 0x958A, 0x958B, + 0x958C, 0x958D, 0x958E, 0xC6D5, 0xBEB0, 0xCEFA, 0x958F, 0x9590, 0x9591, + 0xC7E7, 0x9592, 0xBEA7, 0xEAD0, 0x9593, 0x9594, 0xD6C7, 0x9595, 0x9596, + 0x9597, 0xC1C0, 0x9598, 0x9599, 0x959A, 0xD4DD, 0x959B, 0xEAD1, 0x959C, + 0x959D, 0xCFBE, 0x959E, 0x959F, 0x95A0, 0x95A1, 0xEAD2, 0x95A2, 0x95A3, + 0x95A4, 0x95A5, 0xCAEE, 0x95A6, 0x95A7, 0x95A8, 0x95A9, 0xC5AF, 0xB0B5, + 0x95AA, 0x95AB, 0x95AC, 0x95AD, 0x95AE, 0xEAD4, 0x95AF, 0x95B0, 0x95B1, + 0x95B2, 0x95B3, 0x95B4, 0x95B5, 0x95B6, 0x95B7, 0xEAD3, 0xF4DF, 0x95B8, + 0x95B9, 0x95BA, 0x95BB, 0x95BC, 0xC4BA, 0x95BD, 0x95BE, 0x95BF, 0x95C0, + 0x95C1, 0xB1A9, 0x95C2, 0x95C3, 0x95C4, 0x95C5, 0xE5DF, 0x95C6, 0x95C7, + 0x95C8, 0x95C9, 0xEAD5, 0x95CA, 0x95CB, 0x95CC, 0x95CD, 0x95CE, 0x95CF, + 0x95D0, 0x95D1, 0x95D2, 0x95D3, 0x95D4, 0x95D5, 0x95D6, 0x95D7, 0x95D8, + 0x95D9, 0x95DA, 0x95DB, 0x95DC, 0x95DD, 0x95DE, 0x95DF, 0x95E0, 0x95E1, + 0x95E2, 0x95E3, 0xCAEF, 0x95E4, 0xEAD6, 0xEAD7, 0xC6D8, 0x95E5, 0x95E6, + 0x95E7, 0x95E8, 0x95E9, 0x95EA, 0x95EB, 0x95EC, 0xEAD8, 0x95ED, 0x95EE, + 0xEAD9, 0x95EF, 0x95F0, 0x95F1, 0x95F2, 0x95F3, 0x95F4, 0xD4BB, 0x95F5, + 0xC7FA, 0xD2B7, 0xB8FC, 0x95F6, 0x95F7, 0xEAC2, 0x95F8, 0xB2DC, 0x95F9, + 0x95FA, 0xC2FC, 0x95FB, 0xD4F8, 0xCCE6, 0xD7EE, 0x95FC, 0x95FD, 0x95FE, + 0x9640, 0x9641, 0x9642, 0x9643, 0xD4C2, 0xD3D0, 0xEBC3, 0xC5F3, 0x9644, + 0xB7FE, 0x9645, 0x9646, 0xEBD4, 0x9647, 0x9648, 0x9649, 0xCBB7, 0xEBDE, + 0x964A, 0xC0CA, 0x964B, 0x964C, 0x964D, 0xCDFB, 0x964E, 0xB3AF, 0x964F, + 0xC6DA, 0x9650, 0x9651, 0x9652, 0x9653, 0x9654, 0x9655, 0xEBFC, 0x9656, + 0xC4BE, 0x9657, 0xCEB4, 0xC4A9, 0xB1BE, 0xD4FD, 0x9658, 0xCAF5, 0x9659, + 0xD6EC, 0x965A, 0x965B, 0xC6D3, 0xB6E4, 0x965C, 0x965D, 0x965E, 0x965F, + 0xBBFA, 0x9660, 0x9661, 0xD0E0, 0x9662, 0x9663, 0xC9B1, 0x9664, 0xD4D3, + 0xC8A8, 0x9665, 0x9666, 0xB8CB, 0x9667, 0xE8BE, 0xC9BC, 0x9668, 0x9669, + 0xE8BB, 0x966A, 0xC0EE, 0xD0D3, 0xB2C4, 0xB4E5, 0x966B, 0xE8BC, 0x966C, + 0x966D, 0xD5C8, 0x966E, 0x966F, 0x9670, 0x9671, 0x9672, 0xB6C5, 0x9673, + 0xE8BD, 0xCAF8, 0xB8DC, 0xCCF5, 0x9674, 0x9675, 0x9676, 0xC0B4, 0x9677, + 0x9678, 0xD1EE, 0xE8BF, 0xE8C2, 0x9679, 0x967A, 0xBABC, 0x967B, 0xB1AD, + 0xBDDC, 0x967C, 0xEABD, 0xE8C3, 0x967D, 0xE8C6, 0x967E, 0xE8CB, 0x9680, + 0x9681, 0x9682, 0x9683, 0xE8CC, 0x9684, 0xCBC9, 0xB0E5, 0x9685, 0xBCAB, + 0x9686, 0x9687, 0xB9B9, 0x9688, 0x9689, 0xE8C1, 0x968A, 0xCDF7, 0x968B, + 0xE8CA, 0x968C, 0x968D, 0x968E, 0x968F, 0xCEF6, 0x9690, 0x9691, 0x9692, + 0x9693, 0xD5ED, 0x9694, 0xC1D6, 0xE8C4, 0x9695, 0xC3B6, 0x9696, 0xB9FB, + 0xD6A6, 0xE8C8, 0x9697, 0x9698, 0x9699, 0xCAE0, 0xD4E6, 0x969A, 0xE8C0, + 0x969B, 0xE8C5, 0xE8C7, 0x969C, 0xC7B9, 0xB7E3, 0x969D, 0xE8C9, 0x969E, + 0xBFDD, 0xE8D2, 0x969F, 0x96A0, 0xE8D7, 0x96A1, 0xE8D5, 0xBCDC, 0xBCCF, + 0xE8DB, 0x96A2, 0x96A3, 0x96A4, 0x96A5, 0x96A6, 0x96A7, 0x96A8, 0x96A9, + 0xE8DE, 0x96AA, 0xE8DA, 0xB1FA, 0x96AB, 0x96AC, 0x96AD, 0x96AE, 0x96AF, + 0x96B0, 0x96B1, 0x96B2, 0x96B3, 0x96B4, 0xB0D8, 0xC4B3, 0xB8CC, 0xC6E2, + 0xC8BE, 0xC8E1, 0x96B5, 0x96B6, 0x96B7, 0xE8CF, 0xE8D4, 0xE8D6, 0x96B8, + 0xB9F1, 0xE8D8, 0xD7F5, 0x96B9, 0xC4FB, 0x96BA, 0xE8DC, 0x96BB, 0x96BC, + 0xB2E9, 0x96BD, 0x96BE, 0x96BF, 0xE8D1, 0x96C0, 0x96C1, 0xBCED, 0x96C2, + 0x96C3, 0xBFC2, 0xE8CD, 0xD6F9, 0x96C4, 0xC1F8, 0xB2F1, 0x96C5, 0x96C6, + 0x96C7, 0x96C8, 0x96C9, 0x96CA, 0x96CB, 0x96CC, 0xE8DF, 0x96CD, 0xCAC1, + 0xE8D9, 0x96CE, 0x96CF, 0x96D0, 0x96D1, 0xD5A4, 0x96D2, 0xB1EA, 0xD5BB, + 0xE8CE, 0xE8D0, 0xB6B0, 0xE8D3, 0x96D3, 0xE8DD, 0xC0B8, 0x96D4, 0xCAF7, + 0x96D5, 0xCBA8, 0x96D6, 0x96D7, 0xC6DC, 0xC0F5, 0x96D8, 0x96D9, 0x96DA, + 0x96DB, 0x96DC, 0xE8E9, 0x96DD, 0x96DE, 0x96DF, 0xD0A3, 0x96E0, 0x96E1, + 0x96E2, 0x96E3, 0x96E4, 0x96E5, 0x96E6, 0xE8F2, 0xD6EA, 0x96E7, 0x96E8, + 0x96E9, 0x96EA, 0x96EB, 0x96EC, 0x96ED, 0xE8E0, 0xE8E1, 0x96EE, 0x96EF, + 0x96F0, 0xD1F9, 0xBACB, 0xB8F9, 0x96F1, 0x96F2, 0xB8F1, 0xD4D4, 0xE8EF, + 0x96F3, 0xE8EE, 0xE8EC, 0xB9F0, 0xCCD2, 0xE8E6, 0xCEA6, 0xBFF2, 0x96F4, + 0xB0B8, 0xE8F1, 0xE8F0, 0x96F5, 0xD7C0, 0x96F6, 0xE8E4, 0x96F7, 0xCDA9, + 0xC9A3, 0x96F8, 0xBBB8, 0xBDDB, 0xE8EA, 0x96F9, 0x96FA, 0x96FB, 0x96FC, + 0x96FD, 0x96FE, 0x9740, 0x9741, 0x9742, 0x9743, 0xE8E2, 0xE8E3, 0xE8E5, + 0xB5B5, 0xE8E7, 0xC7C5, 0xE8EB, 0xE8ED, 0xBDB0, 0xD7AE, 0x9744, 0xE8F8, + 0x9745, 0x9746, 0x9747, 0x9748, 0x9749, 0x974A, 0x974B, 0x974C, 0xE8F5, + 0x974D, 0xCDB0, 0xE8F6, 0x974E, 0x974F, 0x9750, 0x9751, 0x9752, 0x9753, + 0x9754, 0x9755, 0x9756, 0xC1BA, 0x9757, 0xE8E8, 0x9758, 0xC3B7, 0xB0F0, + 0x9759, 0x975A, 0x975B, 0x975C, 0x975D, 0x975E, 0x975F, 0x9760, 0xE8F4, + 0x9761, 0x9762, 0x9763, 0xE8F7, 0x9764, 0x9765, 0x9766, 0xB9A3, 0x9767, + 0x9768, 0x9769, 0x976A, 0x976B, 0x976C, 0x976D, 0x976E, 0x976F, 0x9770, + 0xC9D2, 0x9771, 0x9772, 0x9773, 0xC3CE, 0xCEE0, 0xC0E6, 0x9774, 0x9775, + 0x9776, 0x9777, 0xCBF3, 0x9778, 0xCCDD, 0xD0B5, 0x9779, 0x977A, 0xCAE1, + 0x977B, 0xE8F3, 0x977C, 0x977D, 0x977E, 0x9780, 0x9781, 0x9782, 0x9783, + 0x9784, 0x9785, 0x9786, 0xBCEC, 0x9787, 0xE8F9, 0x9788, 0x9789, 0x978A, + 0x978B, 0x978C, 0x978D, 0xC3DE, 0x978E, 0xC6E5, 0x978F, 0xB9F7, 0x9790, + 0x9791, 0x9792, 0x9793, 0xB0F4, 0x9794, 0x9795, 0xD7D8, 0x9796, 0x9797, + 0xBCAC, 0x9798, 0xC5EF, 0x9799, 0x979A, 0x979B, 0x979C, 0x979D, 0xCCC4, + 0x979E, 0x979F, 0xE9A6, 0x97A0, 0x97A1, 0x97A2, 0x97A3, 0x97A4, 0x97A5, + 0x97A6, 0x97A7, 0x97A8, 0x97A9, 0xC9AD, 0x97AA, 0xE9A2, 0xC0E2, 0x97AB, + 0x97AC, 0x97AD, 0xBFC3, 0x97AE, 0x97AF, 0x97B0, 0xE8FE, 0xB9D7, 0x97B1, + 0xE8FB, 0x97B2, 0x97B3, 0x97B4, 0x97B5, 0xE9A4, 0x97B6, 0x97B7, 0x97B8, + 0xD2CE, 0x97B9, 0x97BA, 0x97BB, 0x97BC, 0x97BD, 0xE9A3, 0x97BE, 0xD6B2, + 0xD7B5, 0x97BF, 0xE9A7, 0x97C0, 0xBDB7, 0x97C1, 0x97C2, 0x97C3, 0x97C4, + 0x97C5, 0x97C6, 0x97C7, 0x97C8, 0x97C9, 0x97CA, 0x97CB, 0x97CC, 0xE8FC, + 0xE8FD, 0x97CD, 0x97CE, 0x97CF, 0xE9A1, 0x97D0, 0x97D1, 0x97D2, 0x97D3, + 0x97D4, 0x97D5, 0x97D6, 0x97D7, 0xCDD6, 0x97D8, 0x97D9, 0xD2AC, 0x97DA, + 0x97DB, 0x97DC, 0xE9B2, 0x97DD, 0x97DE, 0x97DF, 0x97E0, 0xE9A9, 0x97E1, + 0x97E2, 0x97E3, 0xB4AA, 0x97E4, 0xB4BB, 0x97E5, 0x97E6, 0xE9AB, 0x97E7, + 0x97E8, 0x97E9, 0x97EA, 0x97EB, 0x97EC, 0x97ED, 0x97EE, 0x97EF, 0x97F0, + 0x97F1, 0x97F2, 0x97F3, 0x97F4, 0x97F5, 0x97F6, 0x97F7, 0xD0A8, 0x97F8, + 0x97F9, 0xE9A5, 0x97FA, 0x97FB, 0xB3FE, 0x97FC, 0x97FD, 0xE9AC, 0xC0E3, + 0x97FE, 0xE9AA, 0x9840, 0x9841, 0xE9B9, 0x9842, 0x9843, 0xE9B8, 0x9844, + 0x9845, 0x9846, 0x9847, 0xE9AE, 0x9848, 0x9849, 0xE8FA, 0x984A, 0x984B, + 0xE9A8, 0x984C, 0x984D, 0x984E, 0x984F, 0x9850, 0xBFAC, 0xE9B1, 0xE9BA, + 0x9851, 0x9852, 0xC2A5, 0x9853, 0x9854, 0x9855, 0xE9AF, 0x9856, 0xB8C5, + 0x9857, 0xE9AD, 0x9858, 0xD3DC, 0xE9B4, 0xE9B5, 0xE9B7, 0x9859, 0x985A, + 0x985B, 0xE9C7, 0x985C, 0x985D, 0x985E, 0x985F, 0x9860, 0x9861, 0xC0C6, + 0xE9C5, 0x9862, 0x9863, 0xE9B0, 0x9864, 0x9865, 0xE9BB, 0xB0F1, 0x9866, + 0x9867, 0x9868, 0x9869, 0x986A, 0x986B, 0x986C, 0x986D, 0x986E, 0x986F, + 0xE9BC, 0xD5A5, 0x9870, 0x9871, 0xE9BE, 0x9872, 0xE9BF, 0x9873, 0x9874, + 0x9875, 0xE9C1, 0x9876, 0x9877, 0xC1F1, 0x9878, 0x9879, 0xC8B6, 0x987A, + 0x987B, 0x987C, 0xE9BD, 0x987D, 0x987E, 0x9880, 0x9881, 0x9882, 0xE9C2, + 0x9883, 0x9884, 0x9885, 0x9886, 0x9887, 0x9888, 0x9889, 0x988A, 0xE9C3, + 0x988B, 0xE9B3, 0x988C, 0xE9B6, 0x988D, 0xBBB1, 0x988E, 0x988F, 0x9890, + 0xE9C0, 0x9891, 0x9892, 0x9893, 0x9894, 0x9895, 0x9896, 0xBCF7, 0x9897, + 0x9898, 0x9899, 0xE9C4, 0xE9C6, 0x989A, 0x989B, 0x989C, 0x989D, 0x989E, + 0x989F, 0x98A0, 0x98A1, 0x98A2, 0x98A3, 0x98A4, 0x98A5, 0xE9CA, 0x98A6, + 0x98A7, 0x98A8, 0x98A9, 0xE9CE, 0x98AA, 0x98AB, 0x98AC, 0x98AD, 0x98AE, + 0x98AF, 0x98B0, 0x98B1, 0x98B2, 0x98B3, 0xB2DB, 0x98B4, 0xE9C8, 0x98B5, + 0x98B6, 0x98B7, 0x98B8, 0x98B9, 0x98BA, 0x98BB, 0x98BC, 0x98BD, 0x98BE, + 0xB7AE, 0x98BF, 0x98C0, 0x98C1, 0x98C2, 0x98C3, 0x98C4, 0x98C5, 0x98C6, + 0x98C7, 0x98C8, 0x98C9, 0x98CA, 0xE9CB, 0xE9CC, 0x98CB, 0x98CC, 0x98CD, + 0x98CE, 0x98CF, 0x98D0, 0xD5C1, 0x98D1, 0xC4A3, 0x98D2, 0x98D3, 0x98D4, + 0x98D5, 0x98D6, 0x98D7, 0xE9D8, 0x98D8, 0xBAE1, 0x98D9, 0x98DA, 0x98DB, + 0x98DC, 0xE9C9, 0x98DD, 0xD3A3, 0x98DE, 0x98DF, 0x98E0, 0xE9D4, 0x98E1, + 0x98E2, 0x98E3, 0x98E4, 0x98E5, 0x98E6, 0x98E7, 0xE9D7, 0xE9D0, 0x98E8, + 0x98E9, 0x98EA, 0x98EB, 0x98EC, 0xE9CF, 0x98ED, 0x98EE, 0xC7C1, 0x98EF, + 0x98F0, 0x98F1, 0x98F2, 0x98F3, 0x98F4, 0x98F5, 0x98F6, 0xE9D2, 0x98F7, + 0x98F8, 0x98F9, 0x98FA, 0x98FB, 0x98FC, 0x98FD, 0xE9D9, 0xB3C8, 0x98FE, + 0xE9D3, 0x9940, 0x9941, 0x9942, 0x9943, 0x9944, 0xCFF0, 0x9945, 0x9946, + 0x9947, 0xE9CD, 0x9948, 0x9949, 0x994A, 0x994B, 0x994C, 0x994D, 0x994E, + 0x994F, 0x9950, 0x9951, 0x9952, 0xB3F7, 0x9953, 0x9954, 0x9955, 0x9956, + 0x9957, 0x9958, 0x9959, 0xE9D6, 0x995A, 0x995B, 0xE9DA, 0x995C, 0x995D, + 0x995E, 0xCCB4, 0x995F, 0x9960, 0x9961, 0xCFAD, 0x9962, 0x9963, 0x9964, + 0x9965, 0x9966, 0x9967, 0x9968, 0x9969, 0x996A, 0xE9D5, 0x996B, 0xE9DC, + 0xE9DB, 0x996C, 0x996D, 0x996E, 0x996F, 0x9970, 0xE9DE, 0x9971, 0x9972, + 0x9973, 0x9974, 0x9975, 0x9976, 0x9977, 0x9978, 0xE9D1, 0x9979, 0x997A, + 0x997B, 0x997C, 0x997D, 0x997E, 0x9980, 0x9981, 0xE9DD, 0x9982, 0xE9DF, + 0xC3CA, 0x9983, 0x9984, 0x9985, 0x9986, 0x9987, 0x9988, 0x9989, 0x998A, + 0x998B, 0x998C, 0x998D, 0x998E, 0x998F, 0x9990, 0x9991, 0x9992, 0x9993, + 0x9994, 0x9995, 0x9996, 0x9997, 0x9998, 0x9999, 0x999A, 0x999B, 0x999C, + 0x999D, 0x999E, 0x999F, 0x99A0, 0x99A1, 0x99A2, 0x99A3, 0x99A4, 0x99A5, + 0x99A6, 0x99A7, 0x99A8, 0x99A9, 0x99AA, 0x99AB, 0x99AC, 0x99AD, 0x99AE, + 0x99AF, 0x99B0, 0x99B1, 0x99B2, 0x99B3, 0x99B4, 0x99B5, 0x99B6, 0x99B7, + 0x99B8, 0x99B9, 0x99BA, 0x99BB, 0x99BC, 0x99BD, 0x99BE, 0x99BF, 0x99C0, + 0x99C1, 0x99C2, 0x99C3, 0x99C4, 0x99C5, 0x99C6, 0x99C7, 0x99C8, 0x99C9, + 0x99CA, 0x99CB, 0x99CC, 0x99CD, 0x99CE, 0x99CF, 0x99D0, 0x99D1, 0x99D2, + 0x99D3, 0x99D4, 0x99D5, 0x99D6, 0x99D7, 0x99D8, 0x99D9, 0x99DA, 0x99DB, + 0x99DC, 0x99DD, 0x99DE, 0x99DF, 0x99E0, 0x99E1, 0x99E2, 0x99E3, 0x99E4, + 0x99E5, 0x99E6, 0x99E7, 0x99E8, 0x99E9, 0x99EA, 0x99EB, 0x99EC, 0x99ED, + 0x99EE, 0x99EF, 0x99F0, 0x99F1, 0x99F2, 0x99F3, 0x99F4, 0x99F5, 0xC7B7, + 0xB4CE, 0xBBB6, 0xD0C0, 0xECA3, 0x99F6, 0x99F7, 0xC5B7, 0x99F8, 0x99F9, + 0x99FA, 0x99FB, 0x99FC, 0x99FD, 0x99FE, 0x9A40, 0x9A41, 0x9A42, 0xD3FB, + 0x9A43, 0x9A44, 0x9A45, 0x9A46, 0xECA4, 0x9A47, 0xECA5, 0xC6DB, 0x9A48, + 0x9A49, 0x9A4A, 0xBFEE, 0x9A4B, 0x9A4C, 0x9A4D, 0x9A4E, 0xECA6, 0x9A4F, + 0x9A50, 0xECA7, 0xD0AA, 0x9A51, 0xC7B8, 0x9A52, 0x9A53, 0xB8E8, 0x9A54, + 0x9A55, 0x9A56, 0x9A57, 0x9A58, 0x9A59, 0x9A5A, 0x9A5B, 0x9A5C, 0x9A5D, + 0x9A5E, 0x9A5F, 0xECA8, 0x9A60, 0x9A61, 0x9A62, 0x9A63, 0x9A64, 0x9A65, + 0x9A66, 0x9A67, 0xD6B9, 0xD5FD, 0xB4CB, 0xB2BD, 0xCEE4, 0xC6E7, 0x9A68, + 0x9A69, 0xCDE1, 0x9A6A, 0x9A6B, 0x9A6C, 0x9A6D, 0x9A6E, 0x9A6F, 0x9A70, + 0x9A71, 0x9A72, 0x9A73, 0x9A74, 0x9A75, 0x9A76, 0x9A77, 0xB4F5, 0x9A78, + 0xCBC0, 0xBCDF, 0x9A79, 0x9A7A, 0x9A7B, 0x9A7C, 0xE9E2, 0xE9E3, 0xD1EA, + 0xE9E5, 0x9A7D, 0xB4F9, 0xE9E4, 0x9A7E, 0xD1B3, 0xCAE2, 0xB2D0, 0x9A80, + 0xE9E8, 0x9A81, 0x9A82, 0x9A83, 0x9A84, 0xE9E6, 0xE9E7, 0x9A85, 0x9A86, + 0xD6B3, 0x9A87, 0x9A88, 0x9A89, 0xE9E9, 0xE9EA, 0x9A8A, 0x9A8B, 0x9A8C, + 0x9A8D, 0x9A8E, 0xE9EB, 0x9A8F, 0x9A90, 0x9A91, 0x9A92, 0x9A93, 0x9A94, + 0x9A95, 0x9A96, 0xE9EC, 0x9A97, 0x9A98, 0x9A99, 0x9A9A, 0x9A9B, 0x9A9C, + 0x9A9D, 0x9A9E, 0xECAF, 0xC5B9, 0xB6CE, 0x9A9F, 0xD2F3, 0x9AA0, 0x9AA1, + 0x9AA2, 0x9AA3, 0x9AA4, 0x9AA5, 0x9AA6, 0xB5EE, 0x9AA7, 0xBBD9, 0xECB1, + 0x9AA8, 0x9AA9, 0xD2E3, 0x9AAA, 0x9AAB, 0x9AAC, 0x9AAD, 0x9AAE, 0xCEE3, + 0x9AAF, 0xC4B8, 0x9AB0, 0xC3BF, 0x9AB1, 0x9AB2, 0xB6BE, 0xD8B9, 0xB1C8, + 0xB1CF, 0xB1D1, 0xC5FE, 0x9AB3, 0xB1D0, 0x9AB4, 0xC3AB, 0x9AB5, 0x9AB6, + 0x9AB7, 0x9AB8, 0x9AB9, 0xD5B1, 0x9ABA, 0x9ABB, 0x9ABC, 0x9ABD, 0x9ABE, + 0x9ABF, 0x9AC0, 0x9AC1, 0xEBA4, 0xBAC1, 0x9AC2, 0x9AC3, 0x9AC4, 0xCCBA, + 0x9AC5, 0x9AC6, 0x9AC7, 0xEBA5, 0x9AC8, 0xEBA7, 0x9AC9, 0x9ACA, 0x9ACB, + 0xEBA8, 0x9ACC, 0x9ACD, 0x9ACE, 0xEBA6, 0x9ACF, 0x9AD0, 0x9AD1, 0x9AD2, + 0x9AD3, 0x9AD4, 0x9AD5, 0xEBA9, 0xEBAB, 0xEBAA, 0x9AD6, 0x9AD7, 0x9AD8, + 0x9AD9, 0x9ADA, 0xEBAC, 0x9ADB, 0xCACF, 0xD8B5, 0xC3F1, 0x9ADC, 0xC3A5, + 0xC6F8, 0xEBAD, 0xC4CA, 0x9ADD, 0xEBAE, 0xEBAF, 0xEBB0, 0xB7D5, 0x9ADE, + 0x9ADF, 0x9AE0, 0xB7FA, 0x9AE1, 0xEBB1, 0xC7E2, 0x9AE2, 0xEBB3, 0x9AE3, + 0xBAA4, 0xD1F5, 0xB0B1, 0xEBB2, 0xEBB4, 0x9AE4, 0x9AE5, 0x9AE6, 0xB5AA, + 0xC2C8, 0xC7E8, 0x9AE7, 0xEBB5, 0x9AE8, 0xCBAE, 0xE3DF, 0x9AE9, 0x9AEA, + 0xD3C0, 0x9AEB, 0x9AEC, 0x9AED, 0x9AEE, 0xD9DB, 0x9AEF, 0x9AF0, 0xCDA1, + 0xD6AD, 0xC7F3, 0x9AF1, 0x9AF2, 0x9AF3, 0xD9E0, 0xBBE3, 0x9AF4, 0xBABA, + 0xE3E2, 0x9AF5, 0x9AF6, 0x9AF7, 0x9AF8, 0x9AF9, 0xCFAB, 0x9AFA, 0x9AFB, + 0x9AFC, 0xE3E0, 0xC9C7, 0x9AFD, 0xBAB9, 0x9AFE, 0x9B40, 0x9B41, 0xD1B4, + 0xE3E1, 0xC8EA, 0xB9AF, 0xBDAD, 0xB3D8, 0xCEDB, 0x9B42, 0x9B43, 0xCCC0, + 0x9B44, 0x9B45, 0x9B46, 0xE3E8, 0xE3E9, 0xCDF4, 0x9B47, 0x9B48, 0x9B49, + 0x9B4A, 0x9B4B, 0xCCAD, 0x9B4C, 0xBCB3, 0x9B4D, 0xE3EA, 0x9B4E, 0xE3EB, + 0x9B4F, 0x9B50, 0xD0DA, 0x9B51, 0x9B52, 0x9B53, 0xC6FB, 0xB7DA, 0x9B54, + 0x9B55, 0xC7DF, 0xD2CA, 0xCED6, 0x9B56, 0xE3E4, 0xE3EC, 0x9B57, 0xC9F2, + 0xB3C1, 0x9B58, 0x9B59, 0xE3E7, 0x9B5A, 0x9B5B, 0xC6E3, 0xE3E5, 0x9B5C, + 0x9B5D, 0xEDB3, 0xE3E6, 0x9B5E, 0x9B5F, 0x9B60, 0x9B61, 0xC9B3, 0x9B62, + 0xC5E6, 0x9B63, 0x9B64, 0x9B65, 0xB9B5, 0x9B66, 0xC3BB, 0x9B67, 0xE3E3, + 0xC5BD, 0xC1A4, 0xC2D9, 0xB2D7, 0x9B68, 0xE3ED, 0xBBA6, 0xC4AD, 0x9B69, + 0xE3F0, 0xBEDA, 0x9B6A, 0x9B6B, 0xE3FB, 0xE3F5, 0xBAD3, 0x9B6C, 0x9B6D, + 0x9B6E, 0x9B6F, 0xB7D0, 0xD3CD, 0x9B70, 0xD6CE, 0xD5D3, 0xB9C1, 0xD5B4, + 0xD1D8, 0x9B71, 0x9B72, 0x9B73, 0x9B74, 0xD0B9, 0xC7F6, 0x9B75, 0x9B76, + 0x9B77, 0xC8AA, 0xB2B4, 0x9B78, 0xC3DA, 0x9B79, 0x9B7A, 0x9B7B, 0xE3EE, + 0x9B7C, 0x9B7D, 0xE3FC, 0xE3EF, 0xB7A8, 0xE3F7, 0xE3F4, 0x9B7E, 0x9B80, + 0x9B81, 0xB7BA, 0x9B82, 0x9B83, 0xC5A2, 0x9B84, 0xE3F6, 0xC5DD, 0xB2A8, + 0xC6FC, 0x9B85, 0xC4E0, 0x9B86, 0x9B87, 0xD7A2, 0x9B88, 0xC0E1, 0xE3F9, + 0x9B89, 0x9B8A, 0xE3FA, 0xE3FD, 0xCCA9, 0xE3F3, 0x9B8B, 0xD3BE, 0x9B8C, + 0xB1C3, 0xEDB4, 0xE3F1, 0xE3F2, 0x9B8D, 0xE3F8, 0xD0BA, 0xC6C3, 0xD4F3, + 0xE3FE, 0x9B8E, 0x9B8F, 0xBDE0, 0x9B90, 0x9B91, 0xE4A7, 0x9B92, 0x9B93, + 0xE4A6, 0x9B94, 0x9B95, 0x9B96, 0xD1F3, 0xE4A3, 0x9B97, 0xE4A9, 0x9B98, + 0x9B99, 0x9B9A, 0xC8F7, 0x9B9B, 0x9B9C, 0x9B9D, 0x9B9E, 0xCFB4, 0x9B9F, + 0xE4A8, 0xE4AE, 0xC2E5, 0x9BA0, 0x9BA1, 0xB6B4, 0x9BA2, 0x9BA3, 0x9BA4, + 0x9BA5, 0x9BA6, 0x9BA7, 0xBDF2, 0x9BA8, 0xE4A2, 0x9BA9, 0x9BAA, 0xBAE9, + 0xE4AA, 0x9BAB, 0x9BAC, 0xE4AC, 0x9BAD, 0x9BAE, 0xB6FD, 0xD6DE, 0xE4B2, + 0x9BAF, 0xE4AD, 0x9BB0, 0x9BB1, 0x9BB2, 0xE4A1, 0x9BB3, 0xBBEE, 0xCDDD, + 0xC7A2, 0xC5C9, 0x9BB4, 0x9BB5, 0xC1F7, 0x9BB6, 0xE4A4, 0x9BB7, 0xC7B3, + 0xBDAC, 0xBDBD, 0xE4A5, 0x9BB8, 0xD7C7, 0xB2E2, 0x9BB9, 0xE4AB, 0xBCC3, + 0xE4AF, 0x9BBA, 0xBBEB, 0xE4B0, 0xC5A8, 0xE4B1, 0x9BBB, 0x9BBC, 0x9BBD, + 0x9BBE, 0xD5E3, 0xBFA3, 0x9BBF, 0xE4BA, 0x9BC0, 0xE4B7, 0x9BC1, 0xE4BB, + 0x9BC2, 0x9BC3, 0xE4BD, 0x9BC4, 0x9BC5, 0xC6D6, 0x9BC6, 0x9BC7, 0xBAC6, + 0xC0CB, 0x9BC8, 0x9BC9, 0x9BCA, 0xB8A1, 0xE4B4, 0x9BCB, 0x9BCC, 0x9BCD, + 0x9BCE, 0xD4A1, 0x9BCF, 0x9BD0, 0xBAA3, 0xBDFE, 0x9BD1, 0x9BD2, 0x9BD3, + 0xE4BC, 0x9BD4, 0x9BD5, 0x9BD6, 0x9BD7, 0x9BD8, 0xCDBF, 0x9BD9, 0x9BDA, + 0xC4F9, 0x9BDB, 0x9BDC, 0xCFFB, 0xC9E6, 0x9BDD, 0x9BDE, 0xD3BF, 0x9BDF, + 0xCFD1, 0x9BE0, 0x9BE1, 0xE4B3, 0x9BE2, 0xE4B8, 0xE4B9, 0xCCE9, 0x9BE3, + 0x9BE4, 0x9BE5, 0x9BE6, 0x9BE7, 0xCCCE, 0x9BE8, 0xC0D4, 0xE4B5, 0xC1B0, + 0xE4B6, 0xCED0, 0x9BE9, 0xBBC1, 0xB5D3, 0x9BEA, 0xC8F3, 0xBDA7, 0xD5C7, + 0xC9AC, 0xB8A2, 0xE4CA, 0x9BEB, 0x9BEC, 0xE4CC, 0xD1C4, 0x9BED, 0x9BEE, + 0xD2BA, 0x9BEF, 0x9BF0, 0xBAAD, 0x9BF1, 0x9BF2, 0xBAD4, 0x9BF3, 0x9BF4, + 0x9BF5, 0x9BF6, 0x9BF7, 0x9BF8, 0xE4C3, 0xB5ED, 0x9BF9, 0x9BFA, 0x9BFB, + 0xD7CD, 0xE4C0, 0xCFFD, 0xE4BF, 0x9BFC, 0x9BFD, 0x9BFE, 0xC1DC, 0xCCCA, + 0x9C40, 0x9C41, 0x9C42, 0x9C43, 0xCAE7, 0x9C44, 0x9C45, 0x9C46, 0x9C47, + 0xC4D7, 0x9C48, 0xCCD4, 0xE4C8, 0x9C49, 0x9C4A, 0x9C4B, 0xE4C7, 0xE4C1, + 0x9C4C, 0xE4C4, 0xB5AD, 0x9C4D, 0x9C4E, 0xD3D9, 0x9C4F, 0xE4C6, 0x9C50, + 0x9C51, 0x9C52, 0x9C53, 0xD2F9, 0xB4E3, 0x9C54, 0xBBB4, 0x9C55, 0x9C56, + 0xC9EE, 0x9C57, 0xB4BE, 0x9C58, 0x9C59, 0x9C5A, 0xBBEC, 0x9C5B, 0xD1CD, + 0x9C5C, 0xCCED, 0xEDB5, 0x9C5D, 0x9C5E, 0x9C5F, 0x9C60, 0x9C61, 0x9C62, + 0x9C63, 0x9C64, 0xC7E5, 0x9C65, 0x9C66, 0x9C67, 0x9C68, 0xD4A8, 0x9C69, + 0xE4CB, 0xD7D5, 0xE4C2, 0x9C6A, 0xBDA5, 0xE4C5, 0x9C6B, 0x9C6C, 0xD3E6, + 0x9C6D, 0xE4C9, 0xC9F8, 0x9C6E, 0x9C6F, 0xE4BE, 0x9C70, 0x9C71, 0xD3E5, + 0x9C72, 0x9C73, 0xC7FE, 0xB6C9, 0x9C74, 0xD4FC, 0xB2B3, 0xE4D7, 0x9C75, + 0x9C76, 0x9C77, 0xCEC2, 0x9C78, 0xE4CD, 0x9C79, 0xCEBC, 0x9C7A, 0xB8DB, + 0x9C7B, 0x9C7C, 0xE4D6, 0x9C7D, 0xBFCA, 0x9C7E, 0x9C80, 0x9C81, 0xD3CE, + 0x9C82, 0xC3EC, 0x9C83, 0x9C84, 0x9C85, 0x9C86, 0x9C87, 0x9C88, 0x9C89, + 0x9C8A, 0xC5C8, 0xE4D8, 0x9C8B, 0x9C8C, 0x9C8D, 0x9C8E, 0x9C8F, 0x9C90, + 0x9C91, 0x9C92, 0xCDC4, 0xE4CF, 0x9C93, 0x9C94, 0x9C95, 0x9C96, 0xE4D4, + 0xE4D5, 0x9C97, 0xBAFE, 0x9C98, 0xCFE6, 0x9C99, 0x9C9A, 0xD5BF, 0x9C9B, + 0x9C9C, 0x9C9D, 0xE4D2, 0x9C9E, 0x9C9F, 0x9CA0, 0x9CA1, 0x9CA2, 0x9CA3, + 0x9CA4, 0x9CA5, 0x9CA6, 0x9CA7, 0x9CA8, 0xE4D0, 0x9CA9, 0x9CAA, 0xE4CE, + 0x9CAB, 0x9CAC, 0x9CAD, 0x9CAE, 0x9CAF, 0x9CB0, 0x9CB1, 0x9CB2, 0x9CB3, + 0x9CB4, 0x9CB5, 0x9CB6, 0x9CB7, 0x9CB8, 0x9CB9, 0xCDE5, 0xCAAA, 0x9CBA, + 0x9CBB, 0x9CBC, 0xC0A3, 0x9CBD, 0xBDA6, 0xE4D3, 0x9CBE, 0x9CBF, 0xB8C8, + 0x9CC0, 0x9CC1, 0x9CC2, 0x9CC3, 0x9CC4, 0xE4E7, 0xD4B4, 0x9CC5, 0x9CC6, + 0x9CC7, 0x9CC8, 0x9CC9, 0x9CCA, 0x9CCB, 0xE4DB, 0x9CCC, 0x9CCD, 0x9CCE, + 0xC1EF, 0x9CCF, 0x9CD0, 0xE4E9, 0x9CD1, 0x9CD2, 0xD2E7, 0x9CD3, 0x9CD4, + 0xE4DF, 0x9CD5, 0xE4E0, 0x9CD6, 0x9CD7, 0xCFAA, 0x9CD8, 0x9CD9, 0x9CDA, + 0x9CDB, 0xCBDD, 0x9CDC, 0xE4DA, 0xE4D1, 0x9CDD, 0xE4E5, 0x9CDE, 0xC8DC, + 0xE4E3, 0x9CDF, 0x9CE0, 0xC4E7, 0xE4E2, 0x9CE1, 0xE4E1, 0x9CE2, 0x9CE3, + 0x9CE4, 0xB3FC, 0xE4E8, 0x9CE5, 0x9CE6, 0x9CE7, 0x9CE8, 0xB5E1, 0x9CE9, + 0x9CEA, 0x9CEB, 0xD7CC, 0x9CEC, 0x9CED, 0x9CEE, 0xE4E6, 0x9CEF, 0xBBAC, + 0x9CF0, 0xD7D2, 0xCCCF, 0xEBF8, 0x9CF1, 0xE4E4, 0x9CF2, 0x9CF3, 0xB9F6, + 0x9CF4, 0x9CF5, 0x9CF6, 0xD6CD, 0xE4D9, 0xE4DC, 0xC2FA, 0xE4DE, 0x9CF7, + 0xC2CB, 0xC0C4, 0xC2D0, 0x9CF8, 0xB1F5, 0xCCB2, 0x9CF9, 0x9CFA, 0x9CFB, + 0x9CFC, 0x9CFD, 0x9CFE, 0x9D40, 0x9D41, 0x9D42, 0x9D43, 0xB5CE, 0x9D44, + 0x9D45, 0x9D46, 0x9D47, 0xE4EF, 0x9D48, 0x9D49, 0x9D4A, 0x9D4B, 0x9D4C, + 0x9D4D, 0x9D4E, 0x9D4F, 0xC6AF, 0x9D50, 0x9D51, 0x9D52, 0xC6E1, 0x9D53, + 0x9D54, 0xE4F5, 0x9D55, 0x9D56, 0x9D57, 0x9D58, 0x9D59, 0xC2A9, 0x9D5A, + 0x9D5B, 0x9D5C, 0xC0EC, 0xD1DD, 0xE4EE, 0x9D5D, 0x9D5E, 0x9D5F, 0x9D60, + 0x9D61, 0x9D62, 0x9D63, 0x9D64, 0x9D65, 0x9D66, 0xC4AE, 0x9D67, 0x9D68, + 0x9D69, 0xE4ED, 0x9D6A, 0x9D6B, 0x9D6C, 0x9D6D, 0xE4F6, 0xE4F4, 0xC2FE, + 0x9D6E, 0xE4DD, 0x9D6F, 0xE4F0, 0x9D70, 0xCAFE, 0x9D71, 0xD5C4, 0x9D72, + 0x9D73, 0xE4F1, 0x9D74, 0x9D75, 0x9D76, 0x9D77, 0x9D78, 0x9D79, 0x9D7A, + 0xD1FA, 0x9D7B, 0x9D7C, 0x9D7D, 0x9D7E, 0x9D80, 0x9D81, 0x9D82, 0xE4EB, + 0xE4EC, 0x9D83, 0x9D84, 0x9D85, 0xE4F2, 0x9D86, 0xCEAB, 0x9D87, 0x9D88, + 0x9D89, 0x9D8A, 0x9D8B, 0x9D8C, 0x9D8D, 0x9D8E, 0x9D8F, 0x9D90, 0xC5CB, + 0x9D91, 0x9D92, 0x9D93, 0xC7B1, 0x9D94, 0xC2BA, 0x9D95, 0x9D96, 0x9D97, + 0xE4EA, 0x9D98, 0x9D99, 0x9D9A, 0xC1CA, 0x9D9B, 0x9D9C, 0x9D9D, 0x9D9E, + 0x9D9F, 0x9DA0, 0xCCB6, 0xB3B1, 0x9DA1, 0x9DA2, 0x9DA3, 0xE4FB, 0x9DA4, + 0xE4F3, 0x9DA5, 0x9DA6, 0x9DA7, 0xE4FA, 0x9DA8, 0xE4FD, 0x9DA9, 0xE4FC, + 0x9DAA, 0x9DAB, 0x9DAC, 0x9DAD, 0x9DAE, 0x9DAF, 0x9DB0, 0xB3CE, 0x9DB1, + 0x9DB2, 0x9DB3, 0xB3BA, 0xE4F7, 0x9DB4, 0x9DB5, 0xE4F9, 0xE4F8, 0xC5EC, + 0x9DB6, 0x9DB7, 0x9DB8, 0x9DB9, 0x9DBA, 0x9DBB, 0x9DBC, 0x9DBD, 0x9DBE, + 0x9DBF, 0x9DC0, 0x9DC1, 0x9DC2, 0xC0BD, 0x9DC3, 0x9DC4, 0x9DC5, 0x9DC6, + 0xD4E8, 0x9DC7, 0x9DC8, 0x9DC9, 0x9DCA, 0x9DCB, 0xE5A2, 0x9DCC, 0x9DCD, + 0x9DCE, 0x9DCF, 0x9DD0, 0x9DD1, 0x9DD2, 0x9DD3, 0x9DD4, 0x9DD5, 0x9DD6, + 0xB0C4, 0x9DD7, 0x9DD8, 0xE5A4, 0x9DD9, 0x9DDA, 0xE5A3, 0x9DDB, 0x9DDC, + 0x9DDD, 0x9DDE, 0x9DDF, 0x9DE0, 0xBCA4, 0x9DE1, 0xE5A5, 0x9DE2, 0x9DE3, + 0x9DE4, 0x9DE5, 0x9DE6, 0x9DE7, 0xE5A1, 0x9DE8, 0x9DE9, 0x9DEA, 0x9DEB, + 0x9DEC, 0x9DED, 0x9DEE, 0xE4FE, 0xB1F4, 0x9DEF, 0x9DF0, 0x9DF1, 0x9DF2, + 0x9DF3, 0x9DF4, 0x9DF5, 0x9DF6, 0x9DF7, 0x9DF8, 0x9DF9, 0xE5A8, 0x9DFA, + 0xE5A9, 0xE5A6, 0x9DFB, 0x9DFC, 0x9DFD, 0x9DFE, 0x9E40, 0x9E41, 0x9E42, + 0x9E43, 0x9E44, 0x9E45, 0x9E46, 0x9E47, 0xE5A7, 0xE5AA, 0x9E48, 0x9E49, + 0x9E4A, 0x9E4B, 0x9E4C, 0x9E4D, 0x9E4E, 0x9E4F, 0x9E50, 0x9E51, 0x9E52, + 0x9E53, 0x9E54, 0x9E55, 0x9E56, 0x9E57, 0x9E58, 0x9E59, 0x9E5A, 0x9E5B, + 0x9E5C, 0x9E5D, 0x9E5E, 0x9E5F, 0x9E60, 0x9E61, 0x9E62, 0x9E63, 0x9E64, + 0x9E65, 0x9E66, 0x9E67, 0x9E68, 0xC6D9, 0x9E69, 0x9E6A, 0x9E6B, 0x9E6C, + 0x9E6D, 0x9E6E, 0x9E6F, 0x9E70, 0xE5AB, 0xE5AD, 0x9E71, 0x9E72, 0x9E73, + 0x9E74, 0x9E75, 0x9E76, 0x9E77, 0xE5AC, 0x9E78, 0x9E79, 0x9E7A, 0x9E7B, + 0x9E7C, 0x9E7D, 0x9E7E, 0x9E80, 0x9E81, 0x9E82, 0x9E83, 0x9E84, 0x9E85, + 0x9E86, 0x9E87, 0x9E88, 0x9E89, 0xE5AF, 0x9E8A, 0x9E8B, 0x9E8C, 0xE5AE, + 0x9E8D, 0x9E8E, 0x9E8F, 0x9E90, 0x9E91, 0x9E92, 0x9E93, 0x9E94, 0x9E95, + 0x9E96, 0x9E97, 0x9E98, 0x9E99, 0x9E9A, 0x9E9B, 0x9E9C, 0x9E9D, 0x9E9E, + 0xB9E0, 0x9E9F, 0x9EA0, 0xE5B0, 0x9EA1, 0x9EA2, 0x9EA3, 0x9EA4, 0x9EA5, + 0x9EA6, 0x9EA7, 0x9EA8, 0x9EA9, 0x9EAA, 0x9EAB, 0x9EAC, 0x9EAD, 0x9EAE, + 0xE5B1, 0x9EAF, 0x9EB0, 0x9EB1, 0x9EB2, 0x9EB3, 0x9EB4, 0x9EB5, 0x9EB6, + 0x9EB7, 0x9EB8, 0x9EB9, 0x9EBA, 0xBBF0, 0xECE1, 0xC3F0, 0x9EBB, 0xB5C6, + 0xBBD2, 0x9EBC, 0x9EBD, 0x9EBE, 0x9EBF, 0xC1E9, 0xD4EE, 0x9EC0, 0xBEC4, + 0x9EC1, 0x9EC2, 0x9EC3, 0xD7C6, 0x9EC4, 0xD4D6, 0xB2D3, 0xECBE, 0x9EC5, + 0x9EC6, 0x9EC7, 0x9EC8, 0xEAC1, 0x9EC9, 0x9ECA, 0x9ECB, 0xC2AF, 0xB4B6, + 0x9ECC, 0x9ECD, 0x9ECE, 0xD1D7, 0x9ECF, 0x9ED0, 0x9ED1, 0xB3B4, 0x9ED2, + 0xC8B2, 0xBFBB, 0xECC0, 0x9ED3, 0x9ED4, 0xD6CB, 0x9ED5, 0x9ED6, 0xECBF, + 0xECC1, 0x9ED7, 0x9ED8, 0x9ED9, 0x9EDA, 0x9EDB, 0x9EDC, 0x9EDD, 0x9EDE, + 0x9EDF, 0x9EE0, 0x9EE1, 0x9EE2, 0x9EE3, 0xECC5, 0xBEE6, 0xCCBF, 0xC5DA, + 0xBEBC, 0x9EE4, 0xECC6, 0x9EE5, 0xB1FE, 0x9EE6, 0x9EE7, 0x9EE8, 0xECC4, + 0xD5A8, 0xB5E3, 0x9EE9, 0xECC2, 0xC1B6, 0xB3E3, 0x9EEA, 0x9EEB, 0xECC3, + 0xCBB8, 0xC0C3, 0xCCFE, 0x9EEC, 0x9EED, 0x9EEE, 0x9EEF, 0xC1D2, 0x9EF0, + 0xECC8, 0x9EF1, 0x9EF2, 0x9EF3, 0x9EF4, 0x9EF5, 0x9EF6, 0x9EF7, 0x9EF8, + 0x9EF9, 0x9EFA, 0x9EFB, 0x9EFC, 0x9EFD, 0xBAE6, 0xC0D3, 0x9EFE, 0xD6F2, + 0x9F40, 0x9F41, 0x9F42, 0xD1CC, 0x9F43, 0x9F44, 0x9F45, 0x9F46, 0xBFBE, + 0x9F47, 0xB7B3, 0xC9D5, 0xECC7, 0xBBE2, 0x9F48, 0xCCCC, 0xBDFD, 0xC8C8, + 0x9F49, 0xCFA9, 0x9F4A, 0x9F4B, 0x9F4C, 0x9F4D, 0x9F4E, 0x9F4F, 0x9F50, + 0xCDE9, 0x9F51, 0xC5EB, 0x9F52, 0x9F53, 0x9F54, 0xB7E9, 0x9F55, 0x9F56, + 0x9F57, 0x9F58, 0x9F59, 0x9F5A, 0x9F5B, 0x9F5C, 0x9F5D, 0x9F5E, 0x9F5F, + 0xD1C9, 0xBAB8, 0x9F60, 0x9F61, 0x9F62, 0x9F63, 0x9F64, 0xECC9, 0x9F65, + 0x9F66, 0xECCA, 0x9F67, 0xBBC0, 0xECCB, 0x9F68, 0xECE2, 0xB1BA, 0xB7D9, + 0x9F69, 0x9F6A, 0x9F6B, 0x9F6C, 0x9F6D, 0x9F6E, 0x9F6F, 0x9F70, 0x9F71, + 0x9F72, 0x9F73, 0xBDB9, 0x9F74, 0x9F75, 0x9F76, 0x9F77, 0x9F78, 0x9F79, + 0x9F7A, 0x9F7B, 0xECCC, 0xD1E6, 0xECCD, 0x9F7C, 0x9F7D, 0x9F7E, 0x9F80, + 0xC8BB, 0x9F81, 0x9F82, 0x9F83, 0x9F84, 0x9F85, 0x9F86, 0x9F87, 0x9F88, + 0x9F89, 0x9F8A, 0x9F8B, 0x9F8C, 0x9F8D, 0x9F8E, 0xECD1, 0x9F8F, 0x9F90, + 0x9F91, 0x9F92, 0xECD3, 0x9F93, 0xBBCD, 0x9F94, 0xBCE5, 0x9F95, 0x9F96, + 0x9F97, 0x9F98, 0x9F99, 0x9F9A, 0x9F9B, 0x9F9C, 0x9F9D, 0x9F9E, 0x9F9F, + 0x9FA0, 0x9FA1, 0xECCF, 0x9FA2, 0xC9B7, 0x9FA3, 0x9FA4, 0x9FA5, 0x9FA6, + 0x9FA7, 0xC3BA, 0x9FA8, 0xECE3, 0xD5D5, 0xECD0, 0x9FA9, 0x9FAA, 0x9FAB, + 0x9FAC, 0x9FAD, 0xD6F3, 0x9FAE, 0x9FAF, 0x9FB0, 0xECD2, 0xECCE, 0x9FB1, + 0x9FB2, 0x9FB3, 0x9FB4, 0xECD4, 0x9FB5, 0xECD5, 0x9FB6, 0x9FB7, 0xC9BF, + 0x9FB8, 0x9FB9, 0x9FBA, 0x9FBB, 0x9FBC, 0x9FBD, 0xCFA8, 0x9FBE, 0x9FBF, + 0x9FC0, 0x9FC1, 0x9FC2, 0xD0DC, 0x9FC3, 0x9FC4, 0x9FC5, 0x9FC6, 0xD1AC, + 0x9FC7, 0x9FC8, 0x9FC9, 0x9FCA, 0xC8DB, 0x9FCB, 0x9FCC, 0x9FCD, 0xECD6, + 0xCEF5, 0x9FCE, 0x9FCF, 0x9FD0, 0x9FD1, 0x9FD2, 0xCAEC, 0xECDA, 0x9FD3, + 0x9FD4, 0x9FD5, 0x9FD6, 0x9FD7, 0x9FD8, 0x9FD9, 0xECD9, 0x9FDA, 0x9FDB, + 0x9FDC, 0xB0BE, 0x9FDD, 0x9FDE, 0x9FDF, 0x9FE0, 0x9FE1, 0x9FE2, 0xECD7, + 0x9FE3, 0xECD8, 0x9FE4, 0x9FE5, 0x9FE6, 0xECE4, 0x9FE7, 0x9FE8, 0x9FE9, + 0x9FEA, 0x9FEB, 0x9FEC, 0x9FED, 0x9FEE, 0x9FEF, 0xC8BC, 0x9FF0, 0x9FF1, + 0x9FF2, 0x9FF3, 0x9FF4, 0x9FF5, 0x9FF6, 0x9FF7, 0x9FF8, 0x9FF9, 0xC1C7, + 0x9FFA, 0x9FFB, 0x9FFC, 0x9FFD, 0x9FFE, 0xECDC, 0xD1E0, 0xA040, 0xA041, + 0xA042, 0xA043, 0xA044, 0xA045, 0xA046, 0xA047, 0xA048, 0xA049, 0xECDB, + 0xA04A, 0xA04B, 0xA04C, 0xA04D, 0xD4EF, 0xA04E, 0xECDD, 0xA04F, 0xA050, + 0xA051, 0xA052, 0xA053, 0xA054, 0xDBC6, 0xA055, 0xA056, 0xA057, 0xA058, + 0xA059, 0xA05A, 0xA05B, 0xA05C, 0xA05D, 0xA05E, 0xECDE, 0xA05F, 0xA060, + 0xA061, 0xA062, 0xA063, 0xA064, 0xA065, 0xA066, 0xA067, 0xA068, 0xA069, + 0xA06A, 0xB1AC, 0xA06B, 0xA06C, 0xA06D, 0xA06E, 0xA06F, 0xA070, 0xA071, + 0xA072, 0xA073, 0xA074, 0xA075, 0xA076, 0xA077, 0xA078, 0xA079, 0xA07A, + 0xA07B, 0xA07C, 0xA07D, 0xA07E, 0xA080, 0xA081, 0xECDF, 0xA082, 0xA083, + 0xA084, 0xA085, 0xA086, 0xA087, 0xA088, 0xA089, 0xA08A, 0xA08B, 0xECE0, + 0xA08C, 0xD7A6, 0xA08D, 0xC5C0, 0xA08E, 0xA08F, 0xA090, 0xEBBC, 0xB0AE, + 0xA091, 0xA092, 0xA093, 0xBEF4, 0xB8B8, 0xD2AF, 0xB0D6, 0xB5F9, 0xA094, + 0xD8B3, 0xA095, 0xCBAC, 0xA096, 0xE3DD, 0xA097, 0xA098, 0xA099, 0xA09A, + 0xA09B, 0xA09C, 0xA09D, 0xC6AC, 0xB0E6, 0xA09E, 0xA09F, 0xA0A0, 0xC5C6, + 0xEBB9, 0xA0A1, 0xA0A2, 0xA0A3, 0xA0A4, 0xEBBA, 0xA0A5, 0xA0A6, 0xA0A7, + 0xEBBB, 0xA0A8, 0xA0A9, 0xD1C0, 0xA0AA, 0xC5A3, 0xA0AB, 0xEAF2, 0xA0AC, + 0xC4B2, 0xA0AD, 0xC4B5, 0xC0CE, 0xA0AE, 0xA0AF, 0xA0B0, 0xEAF3, 0xC4C1, + 0xA0B1, 0xCEEF, 0xA0B2, 0xA0B3, 0xA0B4, 0xA0B5, 0xEAF0, 0xEAF4, 0xA0B6, + 0xA0B7, 0xC9FC, 0xA0B8, 0xA0B9, 0xC7A3, 0xA0BA, 0xA0BB, 0xA0BC, 0xCCD8, + 0xCEFE, 0xA0BD, 0xA0BE, 0xA0BF, 0xEAF5, 0xEAF6, 0xCFAC, 0xC0E7, 0xA0C0, + 0xA0C1, 0xEAF7, 0xA0C2, 0xA0C3, 0xA0C4, 0xA0C5, 0xA0C6, 0xB6BF, 0xEAF8, + 0xA0C7, 0xEAF9, 0xA0C8, 0xEAFA, 0xA0C9, 0xA0CA, 0xEAFB, 0xA0CB, 0xA0CC, + 0xA0CD, 0xA0CE, 0xA0CF, 0xA0D0, 0xA0D1, 0xA0D2, 0xA0D3, 0xA0D4, 0xA0D5, + 0xA0D6, 0xEAF1, 0xA0D7, 0xA0D8, 0xA0D9, 0xA0DA, 0xA0DB, 0xA0DC, 0xA0DD, + 0xA0DE, 0xA0DF, 0xA0E0, 0xA0E1, 0xA0E2, 0xC8AE, 0xE1EB, 0xA0E3, 0xB7B8, + 0xE1EC, 0xA0E4, 0xA0E5, 0xA0E6, 0xE1ED, 0xA0E7, 0xD7B4, 0xE1EE, 0xE1EF, + 0xD3CC, 0xA0E8, 0xA0E9, 0xA0EA, 0xA0EB, 0xA0EC, 0xA0ED, 0xA0EE, 0xE1F1, + 0xBFF1, 0xE1F0, 0xB5D2, 0xA0EF, 0xA0F0, 0xA0F1, 0xB1B7, 0xA0F2, 0xA0F3, + 0xA0F4, 0xA0F5, 0xE1F3, 0xE1F2, 0xA0F6, 0xBAFC, 0xA0F7, 0xE1F4, 0xA0F8, + 0xA0F9, 0xA0FA, 0xA0FB, 0xB9B7, 0xA0FC, 0xBED1, 0xA0FD, 0xA0FE, 0xAA40, + 0xAA41, 0xC4FC, 0xAA42, 0xBADD, 0xBDC6, 0xAA43, 0xAA44, 0xAA45, 0xAA46, + 0xAA47, 0xAA48, 0xE1F5, 0xE1F7, 0xAA49, 0xAA4A, 0xB6C0, 0xCFC1, 0xCAA8, + 0xE1F6, 0xD5F8, 0xD3FC, 0xE1F8, 0xE1FC, 0xE1F9, 0xAA4B, 0xAA4C, 0xE1FA, + 0xC0EA, 0xAA4D, 0xE1FE, 0xE2A1, 0xC0C7, 0xAA4E, 0xAA4F, 0xAA50, 0xAA51, + 0xE1FB, 0xAA52, 0xE1FD, 0xAA53, 0xAA54, 0xAA55, 0xAA56, 0xAA57, 0xAA58, + 0xE2A5, 0xAA59, 0xAA5A, 0xAA5B, 0xC1D4, 0xAA5C, 0xAA5D, 0xAA5E, 0xAA5F, + 0xE2A3, 0xAA60, 0xE2A8, 0xB2FE, 0xE2A2, 0xAA61, 0xAA62, 0xAA63, 0xC3CD, + 0xB2C2, 0xE2A7, 0xE2A6, 0xAA64, 0xAA65, 0xE2A4, 0xE2A9, 0xAA66, 0xAA67, + 0xE2AB, 0xAA68, 0xAA69, 0xAA6A, 0xD0C9, 0xD6ED, 0xC3A8, 0xE2AC, 0xAA6B, + 0xCFD7, 0xAA6C, 0xAA6D, 0xE2AE, 0xAA6E, 0xAA6F, 0xBAEF, 0xAA70, 0xAA71, + 0xE9E0, 0xE2AD, 0xE2AA, 0xAA72, 0xAA73, 0xAA74, 0xAA75, 0xBBAB, 0xD4B3, + 0xAA76, 0xAA77, 0xAA78, 0xAA79, 0xAA7A, 0xAA7B, 0xAA7C, 0xAA7D, 0xAA7E, + 0xAA80, 0xAA81, 0xAA82, 0xAA83, 0xE2B0, 0xAA84, 0xAA85, 0xE2AF, 0xAA86, + 0xE9E1, 0xAA87, 0xAA88, 0xAA89, 0xAA8A, 0xE2B1, 0xAA8B, 0xAA8C, 0xAA8D, + 0xAA8E, 0xAA8F, 0xAA90, 0xAA91, 0xAA92, 0xE2B2, 0xAA93, 0xAA94, 0xAA95, + 0xAA96, 0xAA97, 0xAA98, 0xAA99, 0xAA9A, 0xAA9B, 0xAA9C, 0xAA9D, 0xE2B3, + 0xCCA1, 0xAA9E, 0xE2B4, 0xAA9F, 0xAAA0, 0xAB40, 0xAB41, 0xAB42, 0xAB43, + 0xAB44, 0xAB45, 0xAB46, 0xAB47, 0xAB48, 0xAB49, 0xAB4A, 0xAB4B, 0xE2B5, + 0xAB4C, 0xAB4D, 0xAB4E, 0xAB4F, 0xAB50, 0xD0FE, 0xAB51, 0xAB52, 0xC2CA, + 0xAB53, 0xD3F1, 0xAB54, 0xCDF5, 0xAB55, 0xAB56, 0xE7E0, 0xAB57, 0xAB58, + 0xE7E1, 0xAB59, 0xAB5A, 0xAB5B, 0xAB5C, 0xBEC1, 0xAB5D, 0xAB5E, 0xAB5F, + 0xAB60, 0xC2EA, 0xAB61, 0xAB62, 0xAB63, 0xE7E4, 0xAB64, 0xAB65, 0xE7E3, + 0xAB66, 0xAB67, 0xAB68, 0xAB69, 0xAB6A, 0xAB6B, 0xCDE6, 0xAB6C, 0xC3B5, + 0xAB6D, 0xAB6E, 0xE7E2, 0xBBB7, 0xCFD6, 0xAB6F, 0xC1E1, 0xE7E9, 0xAB70, + 0xAB71, 0xAB72, 0xE7E8, 0xAB73, 0xAB74, 0xE7F4, 0xB2A3, 0xAB75, 0xAB76, + 0xAB77, 0xAB78, 0xE7EA, 0xAB79, 0xE7E6, 0xAB7A, 0xAB7B, 0xAB7C, 0xAB7D, + 0xAB7E, 0xE7EC, 0xE7EB, 0xC9BA, 0xAB80, 0xAB81, 0xD5E4, 0xAB82, 0xE7E5, + 0xB7A9, 0xE7E7, 0xAB83, 0xAB84, 0xAB85, 0xAB86, 0xAB87, 0xAB88, 0xAB89, + 0xE7EE, 0xAB8A, 0xAB8B, 0xAB8C, 0xAB8D, 0xE7F3, 0xAB8E, 0xD6E9, 0xAB8F, + 0xAB90, 0xAB91, 0xAB92, 0xE7ED, 0xAB93, 0xE7F2, 0xAB94, 0xE7F1, 0xAB95, + 0xAB96, 0xAB97, 0xB0E0, 0xAB98, 0xAB99, 0xAB9A, 0xAB9B, 0xE7F5, 0xAB9C, + 0xAB9D, 0xAB9E, 0xAB9F, 0xABA0, 0xAC40, 0xAC41, 0xAC42, 0xAC43, 0xAC44, + 0xAC45, 0xAC46, 0xAC47, 0xAC48, 0xAC49, 0xAC4A, 0xC7F2, 0xAC4B, 0xC0C5, + 0xC0ED, 0xAC4C, 0xAC4D, 0xC1F0, 0xE7F0, 0xAC4E, 0xAC4F, 0xAC50, 0xAC51, + 0xE7F6, 0xCBF6, 0xAC52, 0xAC53, 0xAC54, 0xAC55, 0xAC56, 0xAC57, 0xAC58, + 0xAC59, 0xAC5A, 0xE8A2, 0xE8A1, 0xAC5B, 0xAC5C, 0xAC5D, 0xAC5E, 0xAC5F, + 0xAC60, 0xD7C1, 0xAC61, 0xAC62, 0xE7FA, 0xE7F9, 0xAC63, 0xE7FB, 0xAC64, + 0xE7F7, 0xAC65, 0xE7FE, 0xAC66, 0xE7FD, 0xAC67, 0xE7FC, 0xAC68, 0xAC69, + 0xC1D5, 0xC7D9, 0xC5FD, 0xC5C3, 0xAC6A, 0xAC6B, 0xAC6C, 0xAC6D, 0xAC6E, + 0xC7ED, 0xAC6F, 0xAC70, 0xAC71, 0xAC72, 0xE8A3, 0xAC73, 0xAC74, 0xAC75, + 0xAC76, 0xAC77, 0xAC78, 0xAC79, 0xAC7A, 0xAC7B, 0xAC7C, 0xAC7D, 0xAC7E, + 0xAC80, 0xAC81, 0xAC82, 0xAC83, 0xAC84, 0xAC85, 0xAC86, 0xE8A6, 0xAC87, + 0xE8A5, 0xAC88, 0xE8A7, 0xBAF7, 0xE7F8, 0xE8A4, 0xAC89, 0xC8F0, 0xC9AA, + 0xAC8A, 0xAC8B, 0xAC8C, 0xAC8D, 0xAC8E, 0xAC8F, 0xAC90, 0xAC91, 0xAC92, + 0xAC93, 0xAC94, 0xAC95, 0xAC96, 0xE8A9, 0xAC97, 0xAC98, 0xB9E5, 0xAC99, + 0xAC9A, 0xAC9B, 0xAC9C, 0xAC9D, 0xD1FE, 0xE8A8, 0xAC9E, 0xAC9F, 0xACA0, + 0xAD40, 0xAD41, 0xAD42, 0xE8AA, 0xAD43, 0xE8AD, 0xE8AE, 0xAD44, 0xC1A7, + 0xAD45, 0xAD46, 0xAD47, 0xE8AF, 0xAD48, 0xAD49, 0xAD4A, 0xE8B0, 0xAD4B, + 0xAD4C, 0xE8AC, 0xAD4D, 0xE8B4, 0xAD4E, 0xAD4F, 0xAD50, 0xAD51, 0xAD52, + 0xAD53, 0xAD54, 0xAD55, 0xAD56, 0xAD57, 0xAD58, 0xE8AB, 0xAD59, 0xE8B1, + 0xAD5A, 0xAD5B, 0xAD5C, 0xAD5D, 0xAD5E, 0xAD5F, 0xAD60, 0xAD61, 0xE8B5, + 0xE8B2, 0xE8B3, 0xAD62, 0xAD63, 0xAD64, 0xAD65, 0xAD66, 0xAD67, 0xAD68, + 0xAD69, 0xAD6A, 0xAD6B, 0xAD6C, 0xAD6D, 0xAD6E, 0xAD6F, 0xAD70, 0xAD71, + 0xE8B7, 0xAD72, 0xAD73, 0xAD74, 0xAD75, 0xAD76, 0xAD77, 0xAD78, 0xAD79, + 0xAD7A, 0xAD7B, 0xAD7C, 0xAD7D, 0xAD7E, 0xAD80, 0xAD81, 0xAD82, 0xAD83, + 0xAD84, 0xAD85, 0xAD86, 0xAD87, 0xAD88, 0xAD89, 0xE8B6, 0xAD8A, 0xAD8B, + 0xAD8C, 0xAD8D, 0xAD8E, 0xAD8F, 0xAD90, 0xAD91, 0xAD92, 0xB9CF, 0xAD93, + 0xF0AC, 0xAD94, 0xF0AD, 0xAD95, 0xC6B0, 0xB0EA, 0xC8BF, 0xAD96, 0xCDDF, + 0xAD97, 0xAD98, 0xAD99, 0xAD9A, 0xAD9B, 0xAD9C, 0xAD9D, 0xCECD, 0xEAB1, + 0xAD9E, 0xAD9F, 0xADA0, 0xAE40, 0xEAB2, 0xAE41, 0xC6BF, 0xB4C9, 0xAE42, + 0xAE43, 0xAE44, 0xAE45, 0xAE46, 0xAE47, 0xAE48, 0xEAB3, 0xAE49, 0xAE4A, + 0xAE4B, 0xAE4C, 0xD5E7, 0xAE4D, 0xAE4E, 0xAE4F, 0xAE50, 0xAE51, 0xAE52, + 0xAE53, 0xAE54, 0xDDF9, 0xAE55, 0xEAB4, 0xAE56, 0xEAB5, 0xAE57, 0xEAB6, + 0xAE58, 0xAE59, 0xAE5A, 0xAE5B, 0xB8CA, 0xDFB0, 0xC9F5, 0xAE5C, 0xCCF0, + 0xAE5D, 0xAE5E, 0xC9FA, 0xAE5F, 0xAE60, 0xAE61, 0xAE62, 0xAE63, 0xC9FB, + 0xAE64, 0xAE65, 0xD3C3, 0xCBA6, 0xAE66, 0xB8A6, 0xF0AE, 0xB1C2, 0xAE67, + 0xE5B8, 0xCCEF, 0xD3C9, 0xBCD7, 0xC9EA, 0xAE68, 0xB5E7, 0xAE69, 0xC4D0, + 0xB5E9, 0xAE6A, 0xEEAE, 0xBBAD, 0xAE6B, 0xAE6C, 0xE7DE, 0xAE6D, 0xEEAF, + 0xAE6E, 0xAE6F, 0xAE70, 0xAE71, 0xB3A9, 0xAE72, 0xAE73, 0xEEB2, 0xAE74, + 0xAE75, 0xEEB1, 0xBDE7, 0xAE76, 0xEEB0, 0xCEB7, 0xAE77, 0xAE78, 0xAE79, + 0xAE7A, 0xC5CF, 0xAE7B, 0xAE7C, 0xAE7D, 0xAE7E, 0xC1F4, 0xDBCE, 0xEEB3, + 0xD0F3, 0xAE80, 0xAE81, 0xAE82, 0xAE83, 0xAE84, 0xAE85, 0xAE86, 0xAE87, + 0xC2D4, 0xC6E8, 0xAE88, 0xAE89, 0xAE8A, 0xB7AC, 0xAE8B, 0xAE8C, 0xAE8D, + 0xAE8E, 0xAE8F, 0xAE90, 0xAE91, 0xEEB4, 0xAE92, 0xB3EB, 0xAE93, 0xAE94, + 0xAE95, 0xBBFB, 0xEEB5, 0xAE96, 0xAE97, 0xAE98, 0xAE99, 0xAE9A, 0xE7DC, + 0xAE9B, 0xAE9C, 0xAE9D, 0xEEB6, 0xAE9E, 0xAE9F, 0xBDAE, 0xAEA0, 0xAF40, + 0xAF41, 0xAF42, 0xF1E2, 0xAF43, 0xAF44, 0xAF45, 0xCAE8, 0xAF46, 0xD2C9, + 0xF0DA, 0xAF47, 0xF0DB, 0xAF48, 0xF0DC, 0xC1C6, 0xAF49, 0xB8ED, 0xBECE, + 0xAF4A, 0xAF4B, 0xF0DE, 0xAF4C, 0xC5B1, 0xF0DD, 0xD1F1, 0xAF4D, 0xF0E0, + 0xB0CC, 0xBDEA, 0xAF4E, 0xAF4F, 0xAF50, 0xAF51, 0xAF52, 0xD2DF, 0xF0DF, + 0xAF53, 0xB4AF, 0xB7E8, 0xF0E6, 0xF0E5, 0xC6A3, 0xF0E1, 0xF0E2, 0xB4C3, + 0xAF54, 0xAF55, 0xF0E3, 0xD5EE, 0xAF56, 0xAF57, 0xCCDB, 0xBED2, 0xBCB2, + 0xAF58, 0xAF59, 0xAF5A, 0xF0E8, 0xF0E7, 0xF0E4, 0xB2A1, 0xAF5B, 0xD6A2, + 0xD3B8, 0xBEB7, 0xC8AC, 0xAF5C, 0xAF5D, 0xF0EA, 0xAF5E, 0xAF5F, 0xAF60, + 0xAF61, 0xD1F7, 0xAF62, 0xD6CC, 0xBADB, 0xF0E9, 0xAF63, 0xB6BB, 0xAF64, + 0xAF65, 0xCDB4, 0xAF66, 0xAF67, 0xC6A6, 0xAF68, 0xAF69, 0xAF6A, 0xC1A1, + 0xF0EB, 0xF0EE, 0xAF6B, 0xF0ED, 0xF0F0, 0xF0EC, 0xAF6C, 0xBBBE, 0xF0EF, + 0xAF6D, 0xAF6E, 0xAF6F, 0xAF70, 0xCCB5, 0xF0F2, 0xAF71, 0xAF72, 0xB3D5, + 0xAF73, 0xAF74, 0xAF75, 0xAF76, 0xB1D4, 0xAF77, 0xAF78, 0xF0F3, 0xAF79, + 0xAF7A, 0xF0F4, 0xF0F6, 0xB4E1, 0xAF7B, 0xF0F1, 0xAF7C, 0xF0F7, 0xAF7D, + 0xAF7E, 0xAF80, 0xAF81, 0xF0FA, 0xAF82, 0xF0F8, 0xAF83, 0xAF84, 0xAF85, + 0xF0F5, 0xAF86, 0xAF87, 0xAF88, 0xAF89, 0xF0FD, 0xAF8A, 0xF0F9, 0xF0FC, + 0xF0FE, 0xAF8B, 0xF1A1, 0xAF8C, 0xAF8D, 0xAF8E, 0xCEC1, 0xF1A4, 0xAF8F, + 0xF1A3, 0xAF90, 0xC1F6, 0xF0FB, 0xCADD, 0xAF91, 0xAF92, 0xB4F1, 0xB1F1, + 0xCCB1, 0xAF93, 0xF1A6, 0xAF94, 0xAF95, 0xF1A7, 0xAF96, 0xAF97, 0xF1AC, + 0xD5CE, 0xF1A9, 0xAF98, 0xAF99, 0xC8B3, 0xAF9A, 0xAF9B, 0xAF9C, 0xF1A2, + 0xAF9D, 0xF1AB, 0xF1A8, 0xF1A5, 0xAF9E, 0xAF9F, 0xF1AA, 0xAFA0, 0xB040, + 0xB041, 0xB042, 0xB043, 0xB044, 0xB045, 0xB046, 0xB0A9, 0xF1AD, 0xB047, + 0xB048, 0xB049, 0xB04A, 0xB04B, 0xB04C, 0xF1AF, 0xB04D, 0xF1B1, 0xB04E, + 0xB04F, 0xB050, 0xB051, 0xB052, 0xF1B0, 0xB053, 0xF1AE, 0xB054, 0xB055, + 0xB056, 0xB057, 0xD1A2, 0xB058, 0xB059, 0xB05A, 0xB05B, 0xB05C, 0xB05D, + 0xB05E, 0xF1B2, 0xB05F, 0xB060, 0xB061, 0xF1B3, 0xB062, 0xB063, 0xB064, + 0xB065, 0xB066, 0xB067, 0xB068, 0xB069, 0xB9EF, 0xB06A, 0xB06B, 0xB5C7, + 0xB06C, 0xB0D7, 0xB0D9, 0xB06D, 0xB06E, 0xB06F, 0xD4ED, 0xB070, 0xB5C4, + 0xB071, 0xBDD4, 0xBBCA, 0xF0A7, 0xB072, 0xB073, 0xB8DE, 0xB074, 0xB075, + 0xF0A8, 0xB076, 0xB077, 0xB0A8, 0xB078, 0xF0A9, 0xB079, 0xB07A, 0xCDEE, + 0xB07B, 0xB07C, 0xF0AA, 0xB07D, 0xB07E, 0xB080, 0xB081, 0xB082, 0xB083, + 0xB084, 0xB085, 0xB086, 0xB087, 0xF0AB, 0xB088, 0xB089, 0xB08A, 0xB08B, + 0xB08C, 0xB08D, 0xB08E, 0xB08F, 0xB090, 0xC6A4, 0xB091, 0xB092, 0xD6E5, + 0xF1E4, 0xB093, 0xF1E5, 0xB094, 0xB095, 0xB096, 0xB097, 0xB098, 0xB099, + 0xB09A, 0xB09B, 0xB09C, 0xB09D, 0xC3F3, 0xB09E, 0xB09F, 0xD3DB, 0xB0A0, + 0xB140, 0xD6D1, 0xC5E8, 0xB141, 0xD3AF, 0xB142, 0xD2E6, 0xB143, 0xB144, + 0xEEC1, 0xB0BB, 0xD5B5, 0xD1CE, 0xBCE0, 0xBAD0, 0xB145, 0xBFF8, 0xB146, + 0xB8C7, 0xB5C1, 0xC5CC, 0xB147, 0xB148, 0xCAA2, 0xB149, 0xB14A, 0xB14B, + 0xC3CB, 0xB14C, 0xB14D, 0xB14E, 0xB14F, 0xB150, 0xEEC2, 0xB151, 0xB152, + 0xB153, 0xB154, 0xB155, 0xB156, 0xB157, 0xB158, 0xC4BF, 0xB6A2, 0xB159, + 0xEDEC, 0xC3A4, 0xB15A, 0xD6B1, 0xB15B, 0xB15C, 0xB15D, 0xCFE0, 0xEDEF, + 0xB15E, 0xB15F, 0xC5CE, 0xB160, 0xB6DC, 0xB161, 0xB162, 0xCAA1, 0xB163, + 0xB164, 0xEDED, 0xB165, 0xB166, 0xEDF0, 0xEDF1, 0xC3BC, 0xB167, 0xBFB4, + 0xB168, 0xEDEE, 0xB169, 0xB16A, 0xB16B, 0xB16C, 0xB16D, 0xB16E, 0xB16F, + 0xB170, 0xB171, 0xB172, 0xB173, 0xEDF4, 0xEDF2, 0xB174, 0xB175, 0xB176, + 0xB177, 0xD5E6, 0xC3DF, 0xB178, 0xEDF3, 0xB179, 0xB17A, 0xB17B, 0xEDF6, + 0xB17C, 0xD5A3, 0xD1A3, 0xB17D, 0xB17E, 0xB180, 0xEDF5, 0xB181, 0xC3D0, + 0xB182, 0xB183, 0xB184, 0xB185, 0xB186, 0xEDF7, 0xBFF4, 0xBEEC, 0xEDF8, + 0xB187, 0xCCF7, 0xB188, 0xD1DB, 0xB189, 0xB18A, 0xB18B, 0xD7C5, 0xD5F6, + 0xB18C, 0xEDFC, 0xB18D, 0xB18E, 0xB18F, 0xEDFB, 0xB190, 0xB191, 0xB192, + 0xB193, 0xB194, 0xB195, 0xB196, 0xB197, 0xEDF9, 0xEDFA, 0xB198, 0xB199, + 0xB19A, 0xB19B, 0xB19C, 0xB19D, 0xB19E, 0xB19F, 0xEDFD, 0xBEA6, 0xB1A0, + 0xB240, 0xB241, 0xB242, 0xB243, 0xCBAF, 0xEEA1, 0xB6BD, 0xB244, 0xEEA2, + 0xC4C0, 0xB245, 0xEDFE, 0xB246, 0xB247, 0xBDDE, 0xB2C7, 0xB248, 0xB249, + 0xB24A, 0xB24B, 0xB24C, 0xB24D, 0xB24E, 0xB24F, 0xB250, 0xB251, 0xB252, + 0xB253, 0xB6C3, 0xB254, 0xB255, 0xB256, 0xEEA5, 0xD8BA, 0xEEA3, 0xEEA6, + 0xB257, 0xB258, 0xB259, 0xC3E9, 0xB3F2, 0xB25A, 0xB25B, 0xB25C, 0xB25D, + 0xB25E, 0xB25F, 0xEEA7, 0xEEA4, 0xCFB9, 0xB260, 0xB261, 0xEEA8, 0xC2F7, + 0xB262, 0xB263, 0xB264, 0xB265, 0xB266, 0xB267, 0xB268, 0xB269, 0xB26A, + 0xB26B, 0xB26C, 0xB26D, 0xEEA9, 0xEEAA, 0xB26E, 0xDEAB, 0xB26F, 0xB270, + 0xC6B3, 0xB271, 0xC7C6, 0xB272, 0xD6F5, 0xB5C9, 0xB273, 0xCBB2, 0xB274, + 0xB275, 0xB276, 0xEEAB, 0xB277, 0xB278, 0xCDAB, 0xB279, 0xEEAC, 0xB27A, + 0xB27B, 0xB27C, 0xB27D, 0xB27E, 0xD5B0, 0xB280, 0xEEAD, 0xB281, 0xF6C4, + 0xB282, 0xB283, 0xB284, 0xB285, 0xB286, 0xB287, 0xB288, 0xB289, 0xB28A, + 0xB28B, 0xB28C, 0xB28D, 0xB28E, 0xDBC7, 0xB28F, 0xB290, 0xB291, 0xB292, + 0xB293, 0xB294, 0xB295, 0xB296, 0xB297, 0xB4A3, 0xB298, 0xB299, 0xB29A, + 0xC3AC, 0xF1E6, 0xB29B, 0xB29C, 0xB29D, 0xB29E, 0xB29F, 0xCAB8, 0xD2D3, + 0xB2A0, 0xD6AA, 0xB340, 0xEFF2, 0xB341, 0xBED8, 0xB342, 0xBDC3, 0xEFF3, + 0xB6CC, 0xB0AB, 0xB343, 0xB344, 0xB345, 0xB346, 0xCAAF, 0xB347, 0xB348, + 0xEDB6, 0xB349, 0xEDB7, 0xB34A, 0xB34B, 0xB34C, 0xB34D, 0xCEF9, 0xB7AF, + 0xBFF3, 0xEDB8, 0xC2EB, 0xC9B0, 0xB34E, 0xB34F, 0xB350, 0xB351, 0xB352, + 0xB353, 0xEDB9, 0xB354, 0xB355, 0xC6F6, 0xBFB3, 0xB356, 0xB357, 0xB358, + 0xEDBC, 0xC5F8, 0xB359, 0xD1D0, 0xB35A, 0xD7A9, 0xEDBA, 0xEDBB, 0xB35B, + 0xD1E2, 0xB35C, 0xEDBF, 0xEDC0, 0xB35D, 0xEDC4, 0xB35E, 0xB35F, 0xB360, + 0xEDC8, 0xB361, 0xEDC6, 0xEDCE, 0xD5E8, 0xB362, 0xEDC9, 0xB363, 0xB364, + 0xEDC7, 0xEDBE, 0xB365, 0xB366, 0xC5E9, 0xB367, 0xB368, 0xB369, 0xC6C6, + 0xB36A, 0xB36B, 0xC9E9, 0xD4D2, 0xEDC1, 0xEDC2, 0xEDC3, 0xEDC5, 0xB36C, + 0xC0F9, 0xB36D, 0xB4A1, 0xB36E, 0xB36F, 0xB370, 0xB371, 0xB9E8, 0xB372, + 0xEDD0, 0xB373, 0xB374, 0xB375, 0xB376, 0xEDD1, 0xB377, 0xEDCA, 0xB378, + 0xEDCF, 0xB379, 0xCEF8, 0xB37A, 0xB37B, 0xCBB6, 0xEDCC, 0xEDCD, 0xB37C, + 0xB37D, 0xB37E, 0xB380, 0xB381, 0xCFF5, 0xB382, 0xB383, 0xB384, 0xB385, + 0xB386, 0xB387, 0xB388, 0xB389, 0xB38A, 0xB38B, 0xB38C, 0xB38D, 0xEDD2, + 0xC1F2, 0xD3B2, 0xEDCB, 0xC8B7, 0xB38E, 0xB38F, 0xB390, 0xB391, 0xB392, + 0xB393, 0xB394, 0xB395, 0xBCEF, 0xB396, 0xB397, 0xB398, 0xB399, 0xC5F0, + 0xB39A, 0xB39B, 0xB39C, 0xB39D, 0xB39E, 0xB39F, 0xB3A0, 0xB440, 0xB441, + 0xB442, 0xEDD6, 0xB443, 0xB5EF, 0xB444, 0xB445, 0xC2B5, 0xB0AD, 0xCBE9, + 0xB446, 0xB447, 0xB1AE, 0xB448, 0xEDD4, 0xB449, 0xB44A, 0xB44B, 0xCDEB, + 0xB5E2, 0xB44C, 0xEDD5, 0xEDD3, 0xEDD7, 0xB44D, 0xB44E, 0xB5FA, 0xB44F, + 0xEDD8, 0xB450, 0xEDD9, 0xB451, 0xEDDC, 0xB452, 0xB1CC, 0xB453, 0xB454, + 0xB455, 0xB456, 0xB457, 0xB458, 0xB459, 0xB45A, 0xC5F6, 0xBCEE, 0xEDDA, + 0xCCBC, 0xB2EA, 0xB45B, 0xB45C, 0xB45D, 0xB45E, 0xEDDB, 0xB45F, 0xB460, + 0xB461, 0xB462, 0xC4EB, 0xB463, 0xB464, 0xB4C5, 0xB465, 0xB466, 0xB467, + 0xB0F5, 0xB468, 0xB469, 0xB46A, 0xEDDF, 0xC0DA, 0xB4E8, 0xB46B, 0xB46C, + 0xB46D, 0xB46E, 0xC5CD, 0xB46F, 0xB470, 0xB471, 0xEDDD, 0xBFC4, 0xB472, + 0xB473, 0xB474, 0xEDDE, 0xB475, 0xB476, 0xB477, 0xB478, 0xB479, 0xB47A, + 0xB47B, 0xB47C, 0xB47D, 0xB47E, 0xB480, 0xB481, 0xB482, 0xB483, 0xC4A5, + 0xB484, 0xB485, 0xB486, 0xEDE0, 0xB487, 0xB488, 0xB489, 0xB48A, 0xB48B, + 0xEDE1, 0xB48C, 0xEDE3, 0xB48D, 0xB48E, 0xC1D7, 0xB48F, 0xB490, 0xBBC7, + 0xB491, 0xB492, 0xB493, 0xB494, 0xB495, 0xB496, 0xBDB8, 0xB497, 0xB498, + 0xB499, 0xEDE2, 0xB49A, 0xB49B, 0xB49C, 0xB49D, 0xB49E, 0xB49F, 0xB4A0, + 0xB540, 0xB541, 0xB542, 0xB543, 0xB544, 0xB545, 0xEDE4, 0xB546, 0xB547, + 0xB548, 0xB549, 0xB54A, 0xB54B, 0xB54C, 0xB54D, 0xB54E, 0xB54F, 0xEDE6, + 0xB550, 0xB551, 0xB552, 0xB553, 0xB554, 0xEDE5, 0xB555, 0xB556, 0xB557, + 0xB558, 0xB559, 0xB55A, 0xB55B, 0xB55C, 0xB55D, 0xB55E, 0xB55F, 0xB560, + 0xB561, 0xB562, 0xB563, 0xEDE7, 0xB564, 0xB565, 0xB566, 0xB567, 0xB568, + 0xCABE, 0xECEA, 0xC0F1, 0xB569, 0xC9E7, 0xB56A, 0xECEB, 0xC6EE, 0xB56B, + 0xB56C, 0xB56D, 0xB56E, 0xECEC, 0xB56F, 0xC6ED, 0xECED, 0xB570, 0xB571, + 0xB572, 0xB573, 0xB574, 0xB575, 0xB576, 0xB577, 0xB578, 0xECF0, 0xB579, + 0xB57A, 0xD7E6, 0xECF3, 0xB57B, 0xB57C, 0xECF1, 0xECEE, 0xECEF, 0xD7A3, + 0xC9F1, 0xCBEE, 0xECF4, 0xB57D, 0xECF2, 0xB57E, 0xB580, 0xCFE9, 0xB581, + 0xECF6, 0xC6B1, 0xB582, 0xB583, 0xB584, 0xB585, 0xBCC0, 0xB586, 0xECF5, + 0xB587, 0xB588, 0xB589, 0xB58A, 0xB58B, 0xB58C, 0xB58D, 0xB5BB, 0xBBF6, + 0xB58E, 0xECF7, 0xB58F, 0xB590, 0xB591, 0xB592, 0xB593, 0xD9F7, 0xBDFB, + 0xB594, 0xB595, 0xC2BB, 0xECF8, 0xB596, 0xB597, 0xB598, 0xB599, 0xECF9, + 0xB59A, 0xB59B, 0xB59C, 0xB59D, 0xB8A3, 0xB59E, 0xB59F, 0xB5A0, 0xB640, + 0xB641, 0xB642, 0xB643, 0xB644, 0xB645, 0xB646, 0xECFA, 0xB647, 0xB648, + 0xB649, 0xB64A, 0xB64B, 0xB64C, 0xB64D, 0xB64E, 0xB64F, 0xB650, 0xB651, + 0xB652, 0xECFB, 0xB653, 0xB654, 0xB655, 0xB656, 0xB657, 0xB658, 0xB659, + 0xB65A, 0xB65B, 0xB65C, 0xB65D, 0xECFC, 0xB65E, 0xB65F, 0xB660, 0xB661, + 0xB662, 0xD3ED, 0xD8AE, 0xC0EB, 0xB663, 0xC7DD, 0xBACC, 0xB664, 0xD0E3, + 0xCBBD, 0xB665, 0xCDBA, 0xB666, 0xB667, 0xB8D1, 0xB668, 0xB669, 0xB1FC, + 0xB66A, 0xC7EF, 0xB66B, 0xD6D6, 0xB66C, 0xB66D, 0xB66E, 0xBFC6, 0xC3EB, + 0xB66F, 0xB670, 0xEFF5, 0xB671, 0xB672, 0xC3D8, 0xB673, 0xB674, 0xB675, + 0xB676, 0xB677, 0xB678, 0xD7E2, 0xB679, 0xB67A, 0xB67B, 0xEFF7, 0xB3D3, + 0xB67C, 0xC7D8, 0xD1ED, 0xB67D, 0xD6C8, 0xB67E, 0xEFF8, 0xB680, 0xEFF6, + 0xB681, 0xBBFD, 0xB3C6, 0xB682, 0xB683, 0xB684, 0xB685, 0xB686, 0xB687, + 0xB688, 0xBDD5, 0xB689, 0xB68A, 0xD2C6, 0xB68B, 0xBBE0, 0xB68C, 0xB68D, + 0xCFA1, 0xB68E, 0xEFFC, 0xEFFB, 0xB68F, 0xB690, 0xEFF9, 0xB691, 0xB692, + 0xB693, 0xB694, 0xB3CC, 0xB695, 0xC9D4, 0xCBB0, 0xB696, 0xB697, 0xB698, + 0xB699, 0xB69A, 0xEFFE, 0xB69B, 0xB69C, 0xB0DE, 0xB69D, 0xB69E, 0xD6C9, + 0xB69F, 0xB6A0, 0xB740, 0xEFFD, 0xB741, 0xB3ED, 0xB742, 0xB743, 0xF6D5, + 0xB744, 0xB745, 0xB746, 0xB747, 0xB748, 0xB749, 0xB74A, 0xB74B, 0xB74C, + 0xB74D, 0xB74E, 0xB74F, 0xB750, 0xB751, 0xB752, 0xCEC8, 0xB753, 0xB754, + 0xB755, 0xF0A2, 0xB756, 0xF0A1, 0xB757, 0xB5BE, 0xBCDA, 0xBBFC, 0xB758, + 0xB8E5, 0xB759, 0xB75A, 0xB75B, 0xB75C, 0xB75D, 0xB75E, 0xC4C2, 0xB75F, + 0xB760, 0xB761, 0xB762, 0xB763, 0xB764, 0xB765, 0xB766, 0xB767, 0xB768, + 0xF0A3, 0xB769, 0xB76A, 0xB76B, 0xB76C, 0xB76D, 0xCBEB, 0xB76E, 0xB76F, + 0xB770, 0xB771, 0xB772, 0xB773, 0xB774, 0xB775, 0xB776, 0xB777, 0xB778, + 0xB779, 0xB77A, 0xB77B, 0xB77C, 0xB77D, 0xB77E, 0xB780, 0xB781, 0xB782, + 0xB783, 0xB784, 0xB785, 0xB786, 0xF0A6, 0xB787, 0xB788, 0xB789, 0xD1A8, + 0xB78A, 0xBEBF, 0xC7EE, 0xF1B6, 0xF1B7, 0xBFD5, 0xB78B, 0xB78C, 0xB78D, + 0xB78E, 0xB4A9, 0xF1B8, 0xCDBB, 0xB78F, 0xC7D4, 0xD5AD, 0xB790, 0xF1B9, + 0xB791, 0xF1BA, 0xB792, 0xB793, 0xB794, 0xB795, 0xC7CF, 0xB796, 0xB797, + 0xB798, 0xD2A4, 0xD6CF, 0xB799, 0xB79A, 0xF1BB, 0xBDD1, 0xB4B0, 0xBEBD, + 0xB79B, 0xB79C, 0xB79D, 0xB4DC, 0xCED1, 0xB79E, 0xBFDF, 0xF1BD, 0xB79F, + 0xB7A0, 0xB840, 0xB841, 0xBFFA, 0xF1BC, 0xB842, 0xF1BF, 0xB843, 0xB844, + 0xB845, 0xF1BE, 0xF1C0, 0xB846, 0xB847, 0xB848, 0xB849, 0xB84A, 0xF1C1, + 0xB84B, 0xB84C, 0xB84D, 0xB84E, 0xB84F, 0xB850, 0xB851, 0xB852, 0xB853, + 0xB854, 0xB855, 0xC1FE, 0xB856, 0xB857, 0xB858, 0xB859, 0xB85A, 0xB85B, + 0xB85C, 0xB85D, 0xB85E, 0xB85F, 0xB860, 0xC1A2, 0xB861, 0xB862, 0xB863, + 0xB864, 0xB865, 0xB866, 0xB867, 0xB868, 0xB869, 0xB86A, 0xCAFA, 0xB86B, + 0xB86C, 0xD5BE, 0xB86D, 0xB86E, 0xB86F, 0xB870, 0xBEBA, 0xBEB9, 0xD5C2, + 0xB871, 0xB872, 0xBFA2, 0xB873, 0xCDAF, 0xF1B5, 0xB874, 0xB875, 0xB876, + 0xB877, 0xB878, 0xB879, 0xBDDF, 0xB87A, 0xB6CB, 0xB87B, 0xB87C, 0xB87D, + 0xB87E, 0xB880, 0xB881, 0xB882, 0xB883, 0xB884, 0xD6F1, 0xF3C3, 0xB885, + 0xB886, 0xF3C4, 0xB887, 0xB8CD, 0xB888, 0xB889, 0xB88A, 0xF3C6, 0xF3C7, + 0xB88B, 0xB0CA, 0xB88C, 0xF3C5, 0xB88D, 0xF3C9, 0xCBF1, 0xB88E, 0xB88F, + 0xB890, 0xF3CB, 0xB891, 0xD0A6, 0xB892, 0xB893, 0xB1CA, 0xF3C8, 0xB894, + 0xB895, 0xB896, 0xF3CF, 0xB897, 0xB5D1, 0xB898, 0xB899, 0xF3D7, 0xB89A, + 0xF3D2, 0xB89B, 0xB89C, 0xB89D, 0xF3D4, 0xF3D3, 0xB7FB, 0xB89E, 0xB1BF, + 0xB89F, 0xF3CE, 0xF3CA, 0xB5DA, 0xB8A0, 0xF3D0, 0xB940, 0xB941, 0xF3D1, + 0xB942, 0xF3D5, 0xB943, 0xB944, 0xB945, 0xB946, 0xF3CD, 0xB947, 0xBCE3, + 0xB948, 0xC1FD, 0xB949, 0xF3D6, 0xB94A, 0xB94B, 0xB94C, 0xB94D, 0xB94E, + 0xB94F, 0xF3DA, 0xB950, 0xF3CC, 0xB951, 0xB5C8, 0xB952, 0xBDEE, 0xF3DC, + 0xB953, 0xB954, 0xB7A4, 0xBFF0, 0xD6FE, 0xCDB2, 0xB955, 0xB4F0, 0xB956, + 0xB2DF, 0xB957, 0xF3D8, 0xB958, 0xF3D9, 0xC9B8, 0xB959, 0xF3DD, 0xB95A, + 0xB95B, 0xF3DE, 0xB95C, 0xF3E1, 0xB95D, 0xB95E, 0xB95F, 0xB960, 0xB961, + 0xB962, 0xB963, 0xB964, 0xB965, 0xB966, 0xB967, 0xF3DF, 0xB968, 0xB969, + 0xF3E3, 0xF3E2, 0xB96A, 0xB96B, 0xF3DB, 0xB96C, 0xBFEA, 0xB96D, 0xB3EF, + 0xB96E, 0xF3E0, 0xB96F, 0xB970, 0xC7A9, 0xB971, 0xBCF2, 0xB972, 0xB973, + 0xB974, 0xB975, 0xF3EB, 0xB976, 0xB977, 0xB978, 0xB979, 0xB97A, 0xB97B, + 0xB97C, 0xB9BF, 0xB97D, 0xB97E, 0xF3E4, 0xB980, 0xB981, 0xB982, 0xB2AD, + 0xBBFE, 0xB983, 0xCBE3, 0xB984, 0xB985, 0xB986, 0xB987, 0xF3ED, 0xF3E9, + 0xB988, 0xB989, 0xB98A, 0xB9DC, 0xF3EE, 0xB98B, 0xB98C, 0xB98D, 0xF3E5, + 0xF3E6, 0xF3EA, 0xC2E1, 0xF3EC, 0xF3EF, 0xF3E8, 0xBCFD, 0xB98E, 0xB98F, + 0xB990, 0xCFE4, 0xB991, 0xB992, 0xF3F0, 0xB993, 0xB994, 0xB995, 0xF3E7, + 0xB996, 0xB997, 0xB998, 0xB999, 0xB99A, 0xB99B, 0xB99C, 0xB99D, 0xF3F2, + 0xB99E, 0xB99F, 0xB9A0, 0xBA40, 0xD7AD, 0xC6AA, 0xBA41, 0xBA42, 0xBA43, + 0xBA44, 0xF3F3, 0xBA45, 0xBA46, 0xBA47, 0xBA48, 0xF3F1, 0xBA49, 0xC2A8, + 0xBA4A, 0xBA4B, 0xBA4C, 0xBA4D, 0xBA4E, 0xB8DD, 0xF3F5, 0xBA4F, 0xBA50, + 0xF3F4, 0xBA51, 0xBA52, 0xBA53, 0xB4DB, 0xBA54, 0xBA55, 0xBA56, 0xF3F6, + 0xF3F7, 0xBA57, 0xBA58, 0xBA59, 0xF3F8, 0xBA5A, 0xBA5B, 0xBA5C, 0xC0BA, + 0xBA5D, 0xBA5E, 0xC0E9, 0xBA5F, 0xBA60, 0xBA61, 0xBA62, 0xBA63, 0xC5F1, + 0xBA64, 0xBA65, 0xBA66, 0xBA67, 0xF3FB, 0xBA68, 0xF3FA, 0xBA69, 0xBA6A, + 0xBA6B, 0xBA6C, 0xBA6D, 0xBA6E, 0xBA6F, 0xBA70, 0xB4D8, 0xBA71, 0xBA72, + 0xBA73, 0xF3FE, 0xF3F9, 0xBA74, 0xBA75, 0xF3FC, 0xBA76, 0xBA77, 0xBA78, + 0xBA79, 0xBA7A, 0xBA7B, 0xF3FD, 0xBA7C, 0xBA7D, 0xBA7E, 0xBA80, 0xBA81, + 0xBA82, 0xBA83, 0xBA84, 0xF4A1, 0xBA85, 0xBA86, 0xBA87, 0xBA88, 0xBA89, + 0xBA8A, 0xF4A3, 0xBBC9, 0xBA8B, 0xBA8C, 0xF4A2, 0xBA8D, 0xBA8E, 0xBA8F, + 0xBA90, 0xBA91, 0xBA92, 0xBA93, 0xBA94, 0xBA95, 0xBA96, 0xBA97, 0xBA98, + 0xBA99, 0xF4A4, 0xBA9A, 0xBA9B, 0xBA9C, 0xBA9D, 0xBA9E, 0xBA9F, 0xB2BE, + 0xF4A6, 0xF4A5, 0xBAA0, 0xBB40, 0xBB41, 0xBB42, 0xBB43, 0xBB44, 0xBB45, + 0xBB46, 0xBB47, 0xBB48, 0xBB49, 0xBCAE, 0xBB4A, 0xBB4B, 0xBB4C, 0xBB4D, + 0xBB4E, 0xBB4F, 0xBB50, 0xBB51, 0xBB52, 0xBB53, 0xBB54, 0xBB55, 0xBB56, + 0xBB57, 0xBB58, 0xBB59, 0xBB5A, 0xBB5B, 0xBB5C, 0xBB5D, 0xBB5E, 0xBB5F, + 0xBB60, 0xBB61, 0xBB62, 0xBB63, 0xBB64, 0xBB65, 0xBB66, 0xBB67, 0xBB68, + 0xBB69, 0xBB6A, 0xBB6B, 0xBB6C, 0xBB6D, 0xBB6E, 0xC3D7, 0xD9E1, 0xBB6F, + 0xBB70, 0xBB71, 0xBB72, 0xBB73, 0xBB74, 0xC0E0, 0xF4CC, 0xD7D1, 0xBB75, + 0xBB76, 0xBB77, 0xBB78, 0xBB79, 0xBB7A, 0xBB7B, 0xBB7C, 0xBB7D, 0xBB7E, + 0xBB80, 0xB7DB, 0xBB81, 0xBB82, 0xBB83, 0xBB84, 0xBB85, 0xBB86, 0xBB87, + 0xF4CE, 0xC1A3, 0xBB88, 0xBB89, 0xC6C9, 0xBB8A, 0xB4D6, 0xD5B3, 0xBB8B, + 0xBB8C, 0xBB8D, 0xF4D0, 0xF4CF, 0xF4D1, 0xCBDA, 0xBB8E, 0xBB8F, 0xF4D2, + 0xBB90, 0xD4C1, 0xD6E0, 0xBB91, 0xBB92, 0xBB93, 0xBB94, 0xB7E0, 0xBB95, + 0xBB96, 0xBB97, 0xC1B8, 0xBB98, 0xBB99, 0xC1BB, 0xF4D3, 0xBEAC, 0xBB9A, + 0xBB9B, 0xBB9C, 0xBB9D, 0xBB9E, 0xB4E2, 0xBB9F, 0xBBA0, 0xF4D4, 0xF4D5, + 0xBEAB, 0xBC40, 0xBC41, 0xF4D6, 0xBC42, 0xBC43, 0xBC44, 0xF4DB, 0xBC45, + 0xF4D7, 0xF4DA, 0xBC46, 0xBAFD, 0xBC47, 0xF4D8, 0xF4D9, 0xBC48, 0xBC49, + 0xBC4A, 0xBC4B, 0xBC4C, 0xBC4D, 0xBC4E, 0xB8E2, 0xCCC7, 0xF4DC, 0xBC4F, + 0xB2DA, 0xBC50, 0xBC51, 0xC3D3, 0xBC52, 0xBC53, 0xD4E3, 0xBFB7, 0xBC54, + 0xBC55, 0xBC56, 0xBC57, 0xBC58, 0xBC59, 0xBC5A, 0xF4DD, 0xBC5B, 0xBC5C, + 0xBC5D, 0xBC5E, 0xBC5F, 0xBC60, 0xC5B4, 0xBC61, 0xBC62, 0xBC63, 0xBC64, + 0xBC65, 0xBC66, 0xBC67, 0xBC68, 0xF4E9, 0xBC69, 0xBC6A, 0xCFB5, 0xBC6B, + 0xBC6C, 0xBC6D, 0xBC6E, 0xBC6F, 0xBC70, 0xBC71, 0xBC72, 0xBC73, 0xBC74, + 0xBC75, 0xBC76, 0xBC77, 0xBC78, 0xCEC9, 0xBC79, 0xBC7A, 0xBC7B, 0xBC7C, + 0xBC7D, 0xBC7E, 0xBC80, 0xBC81, 0xBC82, 0xBC83, 0xBC84, 0xBC85, 0xBC86, + 0xBC87, 0xBC88, 0xBC89, 0xBC8A, 0xBC8B, 0xBC8C, 0xBC8D, 0xBC8E, 0xCBD8, + 0xBC8F, 0xCBF7, 0xBC90, 0xBC91, 0xBC92, 0xBC93, 0xBDF4, 0xBC94, 0xBC95, + 0xBC96, 0xD7CF, 0xBC97, 0xBC98, 0xBC99, 0xC0DB, 0xBC9A, 0xBC9B, 0xBC9C, + 0xBC9D, 0xBC9E, 0xBC9F, 0xBCA0, 0xBD40, 0xBD41, 0xBD42, 0xBD43, 0xBD44, + 0xBD45, 0xBD46, 0xBD47, 0xBD48, 0xBD49, 0xBD4A, 0xBD4B, 0xBD4C, 0xBD4D, + 0xBD4E, 0xBD4F, 0xBD50, 0xBD51, 0xBD52, 0xBD53, 0xBD54, 0xBD55, 0xBD56, + 0xBD57, 0xBD58, 0xBD59, 0xBD5A, 0xBD5B, 0xBD5C, 0xBD5D, 0xBD5E, 0xBD5F, + 0xBD60, 0xBD61, 0xBD62, 0xBD63, 0xBD64, 0xBD65, 0xBD66, 0xBD67, 0xBD68, + 0xBD69, 0xBD6A, 0xBD6B, 0xBD6C, 0xBD6D, 0xBD6E, 0xBD6F, 0xBD70, 0xBD71, + 0xBD72, 0xBD73, 0xBD74, 0xBD75, 0xBD76, 0xD0F5, 0xBD77, 0xBD78, 0xBD79, + 0xBD7A, 0xBD7B, 0xBD7C, 0xBD7D, 0xBD7E, 0xF4EA, 0xBD80, 0xBD81, 0xBD82, + 0xBD83, 0xBD84, 0xBD85, 0xBD86, 0xBD87, 0xBD88, 0xBD89, 0xBD8A, 0xBD8B, + 0xBD8C, 0xBD8D, 0xBD8E, 0xBD8F, 0xBD90, 0xBD91, 0xBD92, 0xBD93, 0xBD94, + 0xBD95, 0xBD96, 0xBD97, 0xBD98, 0xBD99, 0xBD9A, 0xBD9B, 0xBD9C, 0xBD9D, + 0xBD9E, 0xBD9F, 0xBDA0, 0xBE40, 0xBE41, 0xBE42, 0xBE43, 0xBE44, 0xBE45, + 0xBE46, 0xBE47, 0xBE48, 0xBE49, 0xBE4A, 0xBE4B, 0xBE4C, 0xF4EB, 0xBE4D, + 0xBE4E, 0xBE4F, 0xBE50, 0xBE51, 0xBE52, 0xBE53, 0xF4EC, 0xBE54, 0xBE55, + 0xBE56, 0xBE57, 0xBE58, 0xBE59, 0xBE5A, 0xBE5B, 0xBE5C, 0xBE5D, 0xBE5E, + 0xBE5F, 0xBE60, 0xBE61, 0xBE62, 0xBE63, 0xBE64, 0xBE65, 0xBE66, 0xBE67, + 0xBE68, 0xBE69, 0xBE6A, 0xBE6B, 0xBE6C, 0xBE6D, 0xBE6E, 0xBE6F, 0xBE70, + 0xBE71, 0xBE72, 0xBE73, 0xBE74, 0xBE75, 0xBE76, 0xBE77, 0xBE78, 0xBE79, + 0xBE7A, 0xBE7B, 0xBE7C, 0xBE7D, 0xBE7E, 0xBE80, 0xBE81, 0xBE82, 0xBE83, + 0xBE84, 0xBE85, 0xBE86, 0xBE87, 0xBE88, 0xBE89, 0xBE8A, 0xBE8B, 0xBE8C, + 0xBE8D, 0xBE8E, 0xBE8F, 0xBE90, 0xBE91, 0xBE92, 0xBE93, 0xBE94, 0xBE95, + 0xBE96, 0xBE97, 0xBE98, 0xBE99, 0xBE9A, 0xBE9B, 0xBE9C, 0xBE9D, 0xBE9E, + 0xBE9F, 0xBEA0, 0xBF40, 0xBF41, 0xBF42, 0xBF43, 0xBF44, 0xBF45, 0xBF46, + 0xBF47, 0xBF48, 0xBF49, 0xBF4A, 0xBF4B, 0xBF4C, 0xBF4D, 0xBF4E, 0xBF4F, + 0xBF50, 0xBF51, 0xBF52, 0xBF53, 0xBF54, 0xBF55, 0xBF56, 0xBF57, 0xBF58, + 0xBF59, 0xBF5A, 0xBF5B, 0xBF5C, 0xBF5D, 0xBF5E, 0xBF5F, 0xBF60, 0xBF61, + 0xBF62, 0xBF63, 0xBF64, 0xBF65, 0xBF66, 0xBF67, 0xBF68, 0xBF69, 0xBF6A, + 0xBF6B, 0xBF6C, 0xBF6D, 0xBF6E, 0xBF6F, 0xBF70, 0xBF71, 0xBF72, 0xBF73, + 0xBF74, 0xBF75, 0xBF76, 0xBF77, 0xBF78, 0xBF79, 0xBF7A, 0xBF7B, 0xBF7C, + 0xBF7D, 0xBF7E, 0xBF80, 0xF7E3, 0xBF81, 0xBF82, 0xBF83, 0xBF84, 0xBF85, + 0xB7B1, 0xBF86, 0xBF87, 0xBF88, 0xBF89, 0xBF8A, 0xF4ED, 0xBF8B, 0xBF8C, + 0xBF8D, 0xBF8E, 0xBF8F, 0xBF90, 0xBF91, 0xBF92, 0xBF93, 0xBF94, 0xBF95, + 0xBF96, 0xBF97, 0xBF98, 0xBF99, 0xBF9A, 0xBF9B, 0xBF9C, 0xBF9D, 0xBF9E, + 0xBF9F, 0xBFA0, 0xC040, 0xC041, 0xC042, 0xC043, 0xC044, 0xC045, 0xC046, + 0xC047, 0xC048, 0xC049, 0xC04A, 0xC04B, 0xC04C, 0xC04D, 0xC04E, 0xC04F, + 0xC050, 0xC051, 0xC052, 0xC053, 0xC054, 0xC055, 0xC056, 0xC057, 0xC058, + 0xC059, 0xC05A, 0xC05B, 0xC05C, 0xC05D, 0xC05E, 0xC05F, 0xC060, 0xC061, + 0xC062, 0xC063, 0xD7EB, 0xC064, 0xC065, 0xC066, 0xC067, 0xC068, 0xC069, + 0xC06A, 0xC06B, 0xC06C, 0xC06D, 0xC06E, 0xC06F, 0xC070, 0xC071, 0xC072, + 0xC073, 0xC074, 0xC075, 0xC076, 0xC077, 0xC078, 0xC079, 0xC07A, 0xC07B, + 0xF4EE, 0xC07C, 0xC07D, 0xC07E, 0xE6F9, 0xBEC0, 0xE6FA, 0xBAEC, 0xE6FB, + 0xCFCB, 0xE6FC, 0xD4BC, 0xBCB6, 0xE6FD, 0xE6FE, 0xBCCD, 0xC8D2, 0xCEB3, + 0xE7A1, 0xC080, 0xB4BF, 0xE7A2, 0xC9B4, 0xB8D9, 0xC4C9, 0xC081, 0xD7DD, + 0xC2DA, 0xB7D7, 0xD6BD, 0xCEC6, 0xB7C4, 0xC082, 0xC083, 0xC5A6, 0xE7A3, + 0xCFDF, 0xE7A4, 0xE7A5, 0xE7A6, 0xC1B7, 0xD7E9, 0xC9F0, 0xCFB8, 0xD6AF, + 0xD6D5, 0xE7A7, 0xB0ED, 0xE7A8, 0xE7A9, 0xC9DC, 0xD2EF, 0xBEAD, 0xE7AA, + 0xB0F3, 0xC8DE, 0xBDE1, 0xE7AB, 0xC8C6, 0xC084, 0xE7AC, 0xBBE6, 0xB8F8, + 0xD1A4, 0xE7AD, 0xC2E7, 0xBEF8, 0xBDCA, 0xCDB3, 0xE7AE, 0xE7AF, 0xBEEE, + 0xD0E5, 0xC085, 0xCBE7, 0xCCD0, 0xBCCC, 0xE7B0, 0xBCA8, 0xD0F7, 0xE7B1, + 0xC086, 0xD0F8, 0xE7B2, 0xE7B3, 0xB4C2, 0xE7B4, 0xE7B5, 0xC9FE, 0xCEAC, + 0xC3E0, 0xE7B7, 0xB1C1, 0xB3F1, 0xC087, 0xE7B8, 0xE7B9, 0xD7DB, 0xD5C0, + 0xE7BA, 0xC2CC, 0xD7BA, 0xE7BB, 0xE7BC, 0xE7BD, 0xBCEA, 0xC3E5, 0xC0C2, + 0xE7BE, 0xE7BF, 0xBCA9, 0xC088, 0xE7C0, 0xE7C1, 0xE7B6, 0xB6D0, 0xE7C2, + 0xC089, 0xE7C3, 0xE7C4, 0xBBBA, 0xB5DE, 0xC2C6, 0xB1E0, 0xE7C5, 0xD4B5, + 0xE7C6, 0xB8BF, 0xE7C8, 0xE7C7, 0xB7EC, 0xC08A, 0xE7C9, 0xB2F8, 0xE7CA, + 0xE7CB, 0xE7CC, 0xE7CD, 0xE7CE, 0xE7CF, 0xE7D0, 0xD3A7, 0xCBF5, 0xE7D1, + 0xE7D2, 0xE7D3, 0xE7D4, 0xC9C9, 0xE7D5, 0xE7D6, 0xE7D7, 0xE7D8, 0xE7D9, + 0xBDC9, 0xE7DA, 0xF3BE, 0xC08B, 0xB8D7, 0xC08C, 0xC8B1, 0xC08D, 0xC08E, + 0xC08F, 0xC090, 0xC091, 0xC092, 0xC093, 0xF3BF, 0xC094, 0xF3C0, 0xF3C1, + 0xC095, 0xC096, 0xC097, 0xC098, 0xC099, 0xC09A, 0xC09B, 0xC09C, 0xC09D, + 0xC09E, 0xB9DE, 0xCDF8, 0xC09F, 0xC0A0, 0xD8E8, 0xBAB1, 0xC140, 0xC2DE, + 0xEEB7, 0xC141, 0xB7A3, 0xC142, 0xC143, 0xC144, 0xC145, 0xEEB9, 0xC146, + 0xEEB8, 0xB0D5, 0xC147, 0xC148, 0xC149, 0xC14A, 0xC14B, 0xEEBB, 0xD5D6, + 0xD7EF, 0xC14C, 0xC14D, 0xC14E, 0xD6C3, 0xC14F, 0xC150, 0xEEBD, 0xCAF0, + 0xC151, 0xEEBC, 0xC152, 0xC153, 0xC154, 0xC155, 0xEEBE, 0xC156, 0xC157, + 0xC158, 0xC159, 0xEEC0, 0xC15A, 0xC15B, 0xEEBF, 0xC15C, 0xC15D, 0xC15E, + 0xC15F, 0xC160, 0xC161, 0xC162, 0xC163, 0xD1F2, 0xC164, 0xC7BC, 0xC165, + 0xC3C0, 0xC166, 0xC167, 0xC168, 0xC169, 0xC16A, 0xB8E1, 0xC16B, 0xC16C, + 0xC16D, 0xC16E, 0xC16F, 0xC1E7, 0xC170, 0xC171, 0xF4C6, 0xD0DF, 0xF4C7, + 0xC172, 0xCFDB, 0xC173, 0xC174, 0xC8BA, 0xC175, 0xC176, 0xF4C8, 0xC177, + 0xC178, 0xC179, 0xC17A, 0xC17B, 0xC17C, 0xC17D, 0xF4C9, 0xF4CA, 0xC17E, + 0xF4CB, 0xC180, 0xC181, 0xC182, 0xC183, 0xC184, 0xD9FA, 0xB8FE, 0xC185, + 0xC186, 0xE5F1, 0xD3F0, 0xC187, 0xF4E0, 0xC188, 0xCECC, 0xC189, 0xC18A, + 0xC18B, 0xB3E1, 0xC18C, 0xC18D, 0xC18E, 0xC18F, 0xF1B4, 0xC190, 0xD2EE, + 0xC191, 0xF4E1, 0xC192, 0xC193, 0xC194, 0xC195, 0xC196, 0xCFE8, 0xF4E2, + 0xC197, 0xC198, 0xC7CC, 0xC199, 0xC19A, 0xC19B, 0xC19C, 0xC19D, 0xC19E, + 0xB5D4, 0xB4E4, 0xF4E4, 0xC19F, 0xC1A0, 0xC240, 0xF4E3, 0xF4E5, 0xC241, + 0xC242, 0xF4E6, 0xC243, 0xC244, 0xC245, 0xC246, 0xF4E7, 0xC247, 0xBAB2, + 0xB0BF, 0xC248, 0xF4E8, 0xC249, 0xC24A, 0xC24B, 0xC24C, 0xC24D, 0xC24E, + 0xC24F, 0xB7AD, 0xD2ED, 0xC250, 0xC251, 0xC252, 0xD2AB, 0xC0CF, 0xC253, + 0xBFBC, 0xEBA3, 0xD5DF, 0xEAC8, 0xC254, 0xC255, 0xC256, 0xC257, 0xF1F3, + 0xB6F8, 0xCBA3, 0xC258, 0xC259, 0xC4CD, 0xC25A, 0xF1E7, 0xC25B, 0xF1E8, + 0xB8FB, 0xF1E9, 0xBAC4, 0xD4C5, 0xB0D2, 0xC25C, 0xC25D, 0xF1EA, 0xC25E, + 0xC25F, 0xC260, 0xF1EB, 0xC261, 0xF1EC, 0xC262, 0xC263, 0xF1ED, 0xF1EE, + 0xF1EF, 0xF1F1, 0xF1F0, 0xC5D5, 0xC264, 0xC265, 0xC266, 0xC267, 0xC268, + 0xC269, 0xF1F2, 0xC26A, 0xB6FA, 0xC26B, 0xF1F4, 0xD2AE, 0xDEC7, 0xCBCA, + 0xC26C, 0xC26D, 0xB3DC, 0xC26E, 0xB5A2, 0xC26F, 0xB9A2, 0xC270, 0xC271, + 0xC4F4, 0xF1F5, 0xC272, 0xC273, 0xF1F6, 0xC274, 0xC275, 0xC276, 0xC1C4, + 0xC1FB, 0xD6B0, 0xF1F7, 0xC277, 0xC278, 0xC279, 0xC27A, 0xF1F8, 0xC27B, + 0xC1AA, 0xC27C, 0xC27D, 0xC27E, 0xC6B8, 0xC280, 0xBEDB, 0xC281, 0xC282, + 0xC283, 0xC284, 0xC285, 0xC286, 0xC287, 0xC288, 0xC289, 0xC28A, 0xC28B, + 0xC28C, 0xC28D, 0xC28E, 0xF1F9, 0xB4CF, 0xC28F, 0xC290, 0xC291, 0xC292, + 0xC293, 0xC294, 0xF1FA, 0xC295, 0xC296, 0xC297, 0xC298, 0xC299, 0xC29A, + 0xC29B, 0xC29C, 0xC29D, 0xC29E, 0xC29F, 0xC2A0, 0xC340, 0xEDB2, 0xEDB1, + 0xC341, 0xC342, 0xCBE0, 0xD2DE, 0xC343, 0xCBC1, 0xD5D8, 0xC344, 0xC8E2, + 0xC345, 0xC0DF, 0xBCA1, 0xC346, 0xC347, 0xC348, 0xC349, 0xC34A, 0xC34B, + 0xEBC1, 0xC34C, 0xC34D, 0xD0A4, 0xC34E, 0xD6E2, 0xC34F, 0xB6C7, 0xB8D8, + 0xEBC0, 0xB8CE, 0xC350, 0xEBBF, 0xB3A6, 0xB9C9, 0xD6AB, 0xC351, 0xB7F4, + 0xB7CA, 0xC352, 0xC353, 0xC354, 0xBCE7, 0xB7BE, 0xEBC6, 0xC355, 0xEBC7, + 0xB0B9, 0xBFCF, 0xC356, 0xEBC5, 0xD3FD, 0xC357, 0xEBC8, 0xC358, 0xC359, + 0xEBC9, 0xC35A, 0xC35B, 0xB7CE, 0xC35C, 0xEBC2, 0xEBC4, 0xC9F6, 0xD6D7, + 0xD5CD, 0xD0B2, 0xEBCF, 0xCEB8, 0xEBD0, 0xC35D, 0xB5A8, 0xC35E, 0xC35F, + 0xC360, 0xC361, 0xC362, 0xB1B3, 0xEBD2, 0xCCA5, 0xC363, 0xC364, 0xC365, + 0xC366, 0xC367, 0xC368, 0xC369, 0xC5D6, 0xEBD3, 0xC36A, 0xEBD1, 0xC5DF, + 0xEBCE, 0xCAA4, 0xEBD5, 0xB0FB, 0xC36B, 0xC36C, 0xBAFA, 0xC36D, 0xC36E, + 0xD8B7, 0xF1E3, 0xC36F, 0xEBCA, 0xEBCB, 0xEBCC, 0xEBCD, 0xEBD6, 0xE6C0, + 0xEBD9, 0xC370, 0xBFE8, 0xD2C8, 0xEBD7, 0xEBDC, 0xB8EC, 0xEBD8, 0xC371, + 0xBDBA, 0xC372, 0xD0D8, 0xC373, 0xB0B7, 0xC374, 0xEBDD, 0xC4DC, 0xC375, + 0xC376, 0xC377, 0xC378, 0xD6AC, 0xC379, 0xC37A, 0xC37B, 0xB4E0, 0xC37C, + 0xC37D, 0xC2F6, 0xBCB9, 0xC37E, 0xC380, 0xEBDA, 0xEBDB, 0xD4E0, 0xC6EA, + 0xC4D4, 0xEBDF, 0xC5A7, 0xD9F5, 0xC381, 0xB2B1, 0xC382, 0xEBE4, 0xC383, + 0xBDC5, 0xC384, 0xC385, 0xC386, 0xEBE2, 0xC387, 0xC388, 0xC389, 0xC38A, + 0xC38B, 0xC38C, 0xC38D, 0xC38E, 0xC38F, 0xC390, 0xC391, 0xC392, 0xC393, + 0xEBE3, 0xC394, 0xC395, 0xB8AC, 0xC396, 0xCDD1, 0xEBE5, 0xC397, 0xC398, + 0xC399, 0xEBE1, 0xC39A, 0xC1B3, 0xC39B, 0xC39C, 0xC39D, 0xC39E, 0xC39F, + 0xC6A2, 0xC3A0, 0xC440, 0xC441, 0xC442, 0xC443, 0xC444, 0xC445, 0xCCF3, + 0xC446, 0xEBE6, 0xC447, 0xC0B0, 0xD2B8, 0xEBE7, 0xC448, 0xC449, 0xC44A, + 0xB8AF, 0xB8AD, 0xC44B, 0xEBE8, 0xC7BB, 0xCDF3, 0xC44C, 0xC44D, 0xC44E, + 0xEBEA, 0xEBEB, 0xC44F, 0xC450, 0xC451, 0xC452, 0xC453, 0xEBED, 0xC454, + 0xC455, 0xC456, 0xC457, 0xD0C8, 0xC458, 0xEBF2, 0xC459, 0xEBEE, 0xC45A, + 0xC45B, 0xC45C, 0xEBF1, 0xC8F9, 0xC45D, 0xD1FC, 0xEBEC, 0xC45E, 0xC45F, + 0xEBE9, 0xC460, 0xC461, 0xC462, 0xC463, 0xB8B9, 0xCFD9, 0xC4E5, 0xEBEF, + 0xEBF0, 0xCCDA, 0xCDC8, 0xB0F2, 0xC464, 0xEBF6, 0xC465, 0xC466, 0xC467, + 0xC468, 0xC469, 0xEBF5, 0xC46A, 0xB2B2, 0xC46B, 0xC46C, 0xC46D, 0xC46E, + 0xB8E0, 0xC46F, 0xEBF7, 0xC470, 0xC471, 0xC472, 0xC473, 0xC474, 0xC475, + 0xB1EC, 0xC476, 0xC477, 0xCCC5, 0xC4A4, 0xCFA5, 0xC478, 0xC479, 0xC47A, + 0xC47B, 0xC47C, 0xEBF9, 0xC47D, 0xC47E, 0xECA2, 0xC480, 0xC5F2, 0xC481, + 0xEBFA, 0xC482, 0xC483, 0xC484, 0xC485, 0xC486, 0xC487, 0xC488, 0xC489, + 0xC9C5, 0xC48A, 0xC48B, 0xC48C, 0xC48D, 0xC48E, 0xC48F, 0xE2DF, 0xEBFE, + 0xC490, 0xC491, 0xC492, 0xC493, 0xCDCE, 0xECA1, 0xB1DB, 0xD3B7, 0xC494, + 0xC495, 0xD2DC, 0xC496, 0xC497, 0xC498, 0xEBFD, 0xC499, 0xEBFB, 0xC49A, + 0xC49B, 0xC49C, 0xC49D, 0xC49E, 0xC49F, 0xC4A0, 0xC540, 0xC541, 0xC542, + 0xC543, 0xC544, 0xC545, 0xC546, 0xC547, 0xC548, 0xC549, 0xC54A, 0xC54B, + 0xC54C, 0xC54D, 0xC54E, 0xB3BC, 0xC54F, 0xC550, 0xC551, 0xEAB0, 0xC552, + 0xC553, 0xD7D4, 0xC554, 0xF4AB, 0xB3F4, 0xC555, 0xC556, 0xC557, 0xC558, + 0xC559, 0xD6C1, 0xD6C2, 0xC55A, 0xC55B, 0xC55C, 0xC55D, 0xC55E, 0xC55F, + 0xD5E9, 0xBECA, 0xC560, 0xF4A7, 0xC561, 0xD2A8, 0xF4A8, 0xF4A9, 0xC562, + 0xF4AA, 0xBECB, 0xD3DF, 0xC563, 0xC564, 0xC565, 0xC566, 0xC567, 0xC9E0, + 0xC9E1, 0xC568, 0xC569, 0xF3C2, 0xC56A, 0xCAE6, 0xC56B, 0xCCF2, 0xC56C, + 0xC56D, 0xC56E, 0xC56F, 0xC570, 0xC571, 0xE2B6, 0xCBB4, 0xC572, 0xCEE8, + 0xD6DB, 0xC573, 0xF4AD, 0xF4AE, 0xF4AF, 0xC574, 0xC575, 0xC576, 0xC577, + 0xF4B2, 0xC578, 0xBABD, 0xF4B3, 0xB0E3, 0xF4B0, 0xC579, 0xF4B1, 0xBDA2, + 0xB2D5, 0xC57A, 0xF4B6, 0xF4B7, 0xB6E6, 0xB2B0, 0xCFCF, 0xF4B4, 0xB4AC, + 0xC57B, 0xF4B5, 0xC57C, 0xC57D, 0xF4B8, 0xC57E, 0xC580, 0xC581, 0xC582, + 0xC583, 0xF4B9, 0xC584, 0xC585, 0xCDA7, 0xC586, 0xF4BA, 0xC587, 0xF4BB, + 0xC588, 0xC589, 0xC58A, 0xF4BC, 0xC58B, 0xC58C, 0xC58D, 0xC58E, 0xC58F, + 0xC590, 0xC591, 0xC592, 0xCBD2, 0xC593, 0xF4BD, 0xC594, 0xC595, 0xC596, + 0xC597, 0xF4BE, 0xC598, 0xC599, 0xC59A, 0xC59B, 0xC59C, 0xC59D, 0xC59E, + 0xC59F, 0xF4BF, 0xC5A0, 0xC640, 0xC641, 0xC642, 0xC643, 0xF4DE, 0xC1BC, + 0xBCE8, 0xC644, 0xC9AB, 0xD1DE, 0xE5F5, 0xC645, 0xC646, 0xC647, 0xC648, + 0xDCB3, 0xD2D5, 0xC649, 0xC64A, 0xDCB4, 0xB0AC, 0xDCB5, 0xC64B, 0xC64C, + 0xBDDA, 0xC64D, 0xDCB9, 0xC64E, 0xC64F, 0xC650, 0xD8C2, 0xC651, 0xDCB7, + 0xD3F3, 0xC652, 0xC9D6, 0xDCBA, 0xDCB6, 0xC653, 0xDCBB, 0xC3A2, 0xC654, + 0xC655, 0xC656, 0xC657, 0xDCBC, 0xDCC5, 0xDCBD, 0xC658, 0xC659, 0xCEDF, + 0xD6A5, 0xC65A, 0xDCCF, 0xC65B, 0xDCCD, 0xC65C, 0xC65D, 0xDCD2, 0xBDE6, + 0xC2AB, 0xC65E, 0xDCB8, 0xDCCB, 0xDCCE, 0xDCBE, 0xB7D2, 0xB0C5, 0xDCC7, + 0xD0BE, 0xDCC1, 0xBBA8, 0xC65F, 0xB7BC, 0xDCCC, 0xC660, 0xC661, 0xDCC6, + 0xDCBF, 0xC7DB, 0xC662, 0xC663, 0xC664, 0xD1BF, 0xDCC0, 0xC665, 0xC666, + 0xDCCA, 0xC667, 0xC668, 0xDCD0, 0xC669, 0xC66A, 0xCEAD, 0xDCC2, 0xC66B, + 0xDCC3, 0xDCC8, 0xDCC9, 0xB2D4, 0xDCD1, 0xCBD5, 0xC66C, 0xD4B7, 0xDCDB, + 0xDCDF, 0xCCA6, 0xDCE6, 0xC66D, 0xC3E7, 0xDCDC, 0xC66E, 0xC66F, 0xBFC1, + 0xDCD9, 0xC670, 0xB0FA, 0xB9B6, 0xDCE5, 0xDCD3, 0xC671, 0xDCC4, 0xDCD6, + 0xC8F4, 0xBFE0, 0xC672, 0xC673, 0xC674, 0xC675, 0xC9BB, 0xC676, 0xC677, + 0xC678, 0xB1BD, 0xC679, 0xD3A2, 0xC67A, 0xC67B, 0xDCDA, 0xC67C, 0xC67D, + 0xDCD5, 0xC67E, 0xC6BB, 0xC680, 0xDCDE, 0xC681, 0xC682, 0xC683, 0xC684, + 0xC685, 0xD7C2, 0xC3AF, 0xB7B6, 0xC7D1, 0xC3A9, 0xDCE2, 0xDCD8, 0xDCEB, + 0xDCD4, 0xC686, 0xC687, 0xDCDD, 0xC688, 0xBEA5, 0xDCD7, 0xC689, 0xDCE0, + 0xC68A, 0xC68B, 0xDCE3, 0xDCE4, 0xC68C, 0xDCF8, 0xC68D, 0xC68E, 0xDCE1, + 0xDDA2, 0xDCE7, 0xC68F, 0xC690, 0xC691, 0xC692, 0xC693, 0xC694, 0xC695, + 0xC696, 0xC697, 0xC698, 0xBCEB, 0xB4C4, 0xC699, 0xC69A, 0xC3A3, 0xB2E7, + 0xDCFA, 0xC69B, 0xDCF2, 0xC69C, 0xDCEF, 0xC69D, 0xDCFC, 0xDCEE, 0xD2F0, + 0xB2E8, 0xC69E, 0xC8D7, 0xC8E3, 0xDCFB, 0xC69F, 0xDCED, 0xC6A0, 0xC740, + 0xC741, 0xDCF7, 0xC742, 0xC743, 0xDCF5, 0xC744, 0xC745, 0xBEA3, 0xDCF4, + 0xC746, 0xB2DD, 0xC747, 0xC748, 0xC749, 0xC74A, 0xC74B, 0xDCF3, 0xBCF6, + 0xDCE8, 0xBBC4, 0xC74C, 0xC0F3, 0xC74D, 0xC74E, 0xC74F, 0xC750, 0xC751, + 0xBCD4, 0xDCE9, 0xDCEA, 0xC752, 0xDCF1, 0xDCF6, 0xDCF9, 0xB5B4, 0xC753, + 0xC8D9, 0xBBE7, 0xDCFE, 0xDCFD, 0xD3AB, 0xDDA1, 0xDDA3, 0xDDA5, 0xD2F1, + 0xDDA4, 0xDDA6, 0xDDA7, 0xD2A9, 0xC754, 0xC755, 0xC756, 0xC757, 0xC758, + 0xC759, 0xC75A, 0xBAC9, 0xDDA9, 0xC75B, 0xC75C, 0xDDB6, 0xDDB1, 0xDDB4, + 0xC75D, 0xC75E, 0xC75F, 0xC760, 0xC761, 0xC762, 0xC763, 0xDDB0, 0xC6CE, + 0xC764, 0xC765, 0xC0F2, 0xC766, 0xC767, 0xC768, 0xC769, 0xC9AF, 0xC76A, + 0xC76B, 0xC76C, 0xDCEC, 0xDDAE, 0xC76D, 0xC76E, 0xC76F, 0xC770, 0xDDB7, + 0xC771, 0xC772, 0xDCF0, 0xDDAF, 0xC773, 0xDDB8, 0xC774, 0xDDAC, 0xC775, + 0xC776, 0xC777, 0xC778, 0xC779, 0xC77A, 0xC77B, 0xDDB9, 0xDDB3, 0xDDAD, + 0xC4AA, 0xC77C, 0xC77D, 0xC77E, 0xC780, 0xDDA8, 0xC0B3, 0xC1AB, 0xDDAA, + 0xDDAB, 0xC781, 0xDDB2, 0xBBF1, 0xDDB5, 0xD3A8, 0xDDBA, 0xC782, 0xDDBB, + 0xC3A7, 0xC783, 0xC784, 0xDDD2, 0xDDBC, 0xC785, 0xC786, 0xC787, 0xDDD1, + 0xC788, 0xB9BD, 0xC789, 0xC78A, 0xBED5, 0xC78B, 0xBEFA, 0xC78C, 0xC78D, + 0xBACA, 0xC78E, 0xC78F, 0xC790, 0xC791, 0xDDCA, 0xC792, 0xDDC5, 0xC793, + 0xDDBF, 0xC794, 0xC795, 0xC796, 0xB2CB, 0xDDC3, 0xC797, 0xDDCB, 0xB2A4, + 0xDDD5, 0xC798, 0xC799, 0xC79A, 0xDDBE, 0xC79B, 0xC79C, 0xC79D, 0xC6D0, + 0xDDD0, 0xC79E, 0xC79F, 0xC7A0, 0xC840, 0xC841, 0xDDD4, 0xC1E2, 0xB7C6, + 0xC842, 0xC843, 0xC844, 0xC845, 0xC846, 0xDDCE, 0xDDCF, 0xC847, 0xC848, + 0xC849, 0xDDC4, 0xC84A, 0xC84B, 0xC84C, 0xDDBD, 0xC84D, 0xDDCD, 0xCCD1, + 0xC84E, 0xDDC9, 0xC84F, 0xC850, 0xC851, 0xC852, 0xDDC2, 0xC3C8, 0xC6BC, + 0xCEAE, 0xDDCC, 0xC853, 0xDDC8, 0xC854, 0xC855, 0xC856, 0xC857, 0xC858, + 0xC859, 0xDDC1, 0xC85A, 0xC85B, 0xC85C, 0xDDC6, 0xC2DC, 0xC85D, 0xC85E, + 0xC85F, 0xC860, 0xC861, 0xC862, 0xD3A9, 0xD3AA, 0xDDD3, 0xCFF4, 0xC8F8, + 0xC863, 0xC864, 0xC865, 0xC866, 0xC867, 0xC868, 0xC869, 0xC86A, 0xDDE6, + 0xC86B, 0xC86C, 0xC86D, 0xC86E, 0xC86F, 0xC870, 0xDDC7, 0xC871, 0xC872, + 0xC873, 0xDDE0, 0xC2E4, 0xC874, 0xC875, 0xC876, 0xC877, 0xC878, 0xC879, + 0xC87A, 0xC87B, 0xDDE1, 0xC87C, 0xC87D, 0xC87E, 0xC880, 0xC881, 0xC882, + 0xC883, 0xC884, 0xC885, 0xC886, 0xDDD7, 0xC887, 0xC888, 0xC889, 0xC88A, + 0xC88B, 0xD6F8, 0xC88C, 0xDDD9, 0xDDD8, 0xB8F0, 0xDDD6, 0xC88D, 0xC88E, + 0xC88F, 0xC890, 0xC6CF, 0xC891, 0xB6AD, 0xC892, 0xC893, 0xC894, 0xC895, + 0xC896, 0xDDE2, 0xC897, 0xBAF9, 0xD4E1, 0xDDE7, 0xC898, 0xC899, 0xC89A, + 0xB4D0, 0xC89B, 0xDDDA, 0xC89C, 0xBFFB, 0xDDE3, 0xC89D, 0xDDDF, 0xC89E, + 0xDDDD, 0xC89F, 0xC8A0, 0xC940, 0xC941, 0xC942, 0xC943, 0xC944, 0xB5D9, + 0xC945, 0xC946, 0xC947, 0xC948, 0xDDDB, 0xDDDC, 0xDDDE, 0xC949, 0xBDAF, + 0xDDE4, 0xC94A, 0xDDE5, 0xC94B, 0xC94C, 0xC94D, 0xC94E, 0xC94F, 0xC950, + 0xC951, 0xC952, 0xDDF5, 0xC953, 0xC3C9, 0xC954, 0xC955, 0xCBE2, 0xC956, + 0xC957, 0xC958, 0xC959, 0xDDF2, 0xC95A, 0xC95B, 0xC95C, 0xC95D, 0xC95E, + 0xC95F, 0xC960, 0xC961, 0xC962, 0xC963, 0xC964, 0xC965, 0xC966, 0xD8E1, + 0xC967, 0xC968, 0xC6D1, 0xC969, 0xDDF4, 0xC96A, 0xC96B, 0xC96C, 0xD5F4, + 0xDDF3, 0xDDF0, 0xC96D, 0xC96E, 0xDDEC, 0xC96F, 0xDDEF, 0xC970, 0xDDE8, + 0xC971, 0xC972, 0xD0EE, 0xC973, 0xC974, 0xC975, 0xC976, 0xC8D8, 0xDDEE, + 0xC977, 0xC978, 0xDDE9, 0xC979, 0xC97A, 0xDDEA, 0xCBF2, 0xC97B, 0xDDED, + 0xC97C, 0xC97D, 0xB1CD, 0xC97E, 0xC980, 0xC981, 0xC982, 0xC983, 0xC984, + 0xC0B6, 0xC985, 0xBCBB, 0xDDF1, 0xC986, 0xC987, 0xDDF7, 0xC988, 0xDDF6, + 0xDDEB, 0xC989, 0xC98A, 0xC98B, 0xC98C, 0xC98D, 0xC5EE, 0xC98E, 0xC98F, + 0xC990, 0xDDFB, 0xC991, 0xC992, 0xC993, 0xC994, 0xC995, 0xC996, 0xC997, + 0xC998, 0xC999, 0xC99A, 0xC99B, 0xDEA4, 0xC99C, 0xC99D, 0xDEA3, 0xC99E, + 0xC99F, 0xC9A0, 0xCA40, 0xCA41, 0xCA42, 0xCA43, 0xCA44, 0xCA45, 0xCA46, + 0xCA47, 0xCA48, 0xDDF8, 0xCA49, 0xCA4A, 0xCA4B, 0xCA4C, 0xC3EF, 0xCA4D, + 0xC2FB, 0xCA4E, 0xCA4F, 0xCA50, 0xD5E1, 0xCA51, 0xCA52, 0xCEB5, 0xCA53, + 0xCA54, 0xCA55, 0xCA56, 0xDDFD, 0xCA57, 0xB2CC, 0xCA58, 0xCA59, 0xCA5A, + 0xCA5B, 0xCA5C, 0xCA5D, 0xCA5E, 0xCA5F, 0xCA60, 0xC4E8, 0xCADF, 0xCA61, + 0xCA62, 0xCA63, 0xCA64, 0xCA65, 0xCA66, 0xCA67, 0xCA68, 0xCA69, 0xCA6A, + 0xC7BE, 0xDDFA, 0xDDFC, 0xDDFE, 0xDEA2, 0xB0AA, 0xB1CE, 0xCA6B, 0xCA6C, + 0xCA6D, 0xCA6E, 0xCA6F, 0xDEAC, 0xCA70, 0xCA71, 0xCA72, 0xCA73, 0xDEA6, + 0xBDB6, 0xC8EF, 0xCA74, 0xCA75, 0xCA76, 0xCA77, 0xCA78, 0xCA79, 0xCA7A, + 0xCA7B, 0xCA7C, 0xCA7D, 0xCA7E, 0xDEA1, 0xCA80, 0xCA81, 0xDEA5, 0xCA82, + 0xCA83, 0xCA84, 0xCA85, 0xDEA9, 0xCA86, 0xCA87, 0xCA88, 0xCA89, 0xCA8A, + 0xDEA8, 0xCA8B, 0xCA8C, 0xCA8D, 0xDEA7, 0xCA8E, 0xCA8F, 0xCA90, 0xCA91, + 0xCA92, 0xCA93, 0xCA94, 0xCA95, 0xCA96, 0xDEAD, 0xCA97, 0xD4CC, 0xCA98, + 0xCA99, 0xCA9A, 0xCA9B, 0xDEB3, 0xDEAA, 0xDEAE, 0xCA9C, 0xCA9D, 0xC0D9, + 0xCA9E, 0xCA9F, 0xCAA0, 0xCB40, 0xCB41, 0xB1A1, 0xDEB6, 0xCB42, 0xDEB1, + 0xCB43, 0xCB44, 0xCB45, 0xCB46, 0xCB47, 0xCB48, 0xCB49, 0xDEB2, 0xCB4A, + 0xCB4B, 0xCB4C, 0xCB4D, 0xCB4E, 0xCB4F, 0xCB50, 0xCB51, 0xCB52, 0xCB53, + 0xCB54, 0xD1A6, 0xDEB5, 0xCB55, 0xCB56, 0xCB57, 0xCB58, 0xCB59, 0xCB5A, + 0xCB5B, 0xDEAF, 0xCB5C, 0xCB5D, 0xCB5E, 0xDEB0, 0xCB5F, 0xD0BD, 0xCB60, + 0xCB61, 0xCB62, 0xDEB4, 0xCAED, 0xDEB9, 0xCB63, 0xCB64, 0xCB65, 0xCB66, + 0xCB67, 0xCB68, 0xDEB8, 0xCB69, 0xDEB7, 0xCB6A, 0xCB6B, 0xCB6C, 0xCB6D, + 0xCB6E, 0xCB6F, 0xCB70, 0xDEBB, 0xCB71, 0xCB72, 0xCB73, 0xCB74, 0xCB75, + 0xCB76, 0xCB77, 0xBDE5, 0xCB78, 0xCB79, 0xCB7A, 0xCB7B, 0xCB7C, 0xB2D8, + 0xC3EA, 0xCB7D, 0xCB7E, 0xDEBA, 0xCB80, 0xC5BA, 0xCB81, 0xCB82, 0xCB83, + 0xCB84, 0xCB85, 0xCB86, 0xDEBC, 0xCB87, 0xCB88, 0xCB89, 0xCB8A, 0xCB8B, + 0xCB8C, 0xCB8D, 0xCCD9, 0xCB8E, 0xCB8F, 0xCB90, 0xCB91, 0xB7AA, 0xCB92, + 0xCB93, 0xCB94, 0xCB95, 0xCB96, 0xCB97, 0xCB98, 0xCB99, 0xCB9A, 0xCB9B, + 0xCB9C, 0xCB9D, 0xCB9E, 0xCB9F, 0xCBA0, 0xCC40, 0xCC41, 0xD4E5, 0xCC42, + 0xCC43, 0xCC44, 0xDEBD, 0xCC45, 0xCC46, 0xCC47, 0xCC48, 0xCC49, 0xDEBF, + 0xCC4A, 0xCC4B, 0xCC4C, 0xCC4D, 0xCC4E, 0xCC4F, 0xCC50, 0xCC51, 0xCC52, + 0xCC53, 0xCC54, 0xC4A2, 0xCC55, 0xCC56, 0xCC57, 0xCC58, 0xDEC1, 0xCC59, + 0xCC5A, 0xCC5B, 0xCC5C, 0xCC5D, 0xCC5E, 0xCC5F, 0xCC60, 0xCC61, 0xCC62, + 0xCC63, 0xCC64, 0xCC65, 0xCC66, 0xCC67, 0xCC68, 0xDEBE, 0xCC69, 0xDEC0, + 0xCC6A, 0xCC6B, 0xCC6C, 0xCC6D, 0xCC6E, 0xCC6F, 0xCC70, 0xCC71, 0xCC72, + 0xCC73, 0xCC74, 0xCC75, 0xCC76, 0xCC77, 0xD5BA, 0xCC78, 0xCC79, 0xCC7A, + 0xDEC2, 0xCC7B, 0xCC7C, 0xCC7D, 0xCC7E, 0xCC80, 0xCC81, 0xCC82, 0xCC83, + 0xCC84, 0xCC85, 0xCC86, 0xCC87, 0xCC88, 0xCC89, 0xCC8A, 0xCC8B, 0xF2AE, + 0xBBA2, 0xC2B2, 0xC5B0, 0xC2C7, 0xCC8C, 0xCC8D, 0xF2AF, 0xCC8E, 0xCC8F, + 0xCC90, 0xCC91, 0xCC92, 0xD0E9, 0xCC93, 0xCC94, 0xCC95, 0xD3DD, 0xCC96, + 0xCC97, 0xCC98, 0xEBBD, 0xCC99, 0xCC9A, 0xCC9B, 0xCC9C, 0xCC9D, 0xCC9E, + 0xCC9F, 0xCCA0, 0xB3E6, 0xF2B0, 0xCD40, 0xF2B1, 0xCD41, 0xCD42, 0xCAAD, + 0xCD43, 0xCD44, 0xCD45, 0xCD46, 0xCD47, 0xCD48, 0xCD49, 0xBAE7, 0xF2B3, + 0xF2B5, 0xF2B4, 0xCBE4, 0xCFBA, 0xF2B2, 0xCAB4, 0xD2CF, 0xC2EC, 0xCD4A, + 0xCD4B, 0xCD4C, 0xCD4D, 0xCD4E, 0xCD4F, 0xCD50, 0xCEC3, 0xF2B8, 0xB0F6, + 0xF2B7, 0xCD51, 0xCD52, 0xCD53, 0xCD54, 0xCD55, 0xF2BE, 0xCD56, 0xB2CF, + 0xCD57, 0xCD58, 0xCD59, 0xCD5A, 0xCD5B, 0xCD5C, 0xD1C1, 0xF2BA, 0xCD5D, + 0xCD5E, 0xCD5F, 0xCD60, 0xCD61, 0xF2BC, 0xD4E9, 0xCD62, 0xCD63, 0xF2BB, + 0xF2B6, 0xF2BF, 0xF2BD, 0xCD64, 0xF2B9, 0xCD65, 0xCD66, 0xF2C7, 0xF2C4, + 0xF2C6, 0xCD67, 0xCD68, 0xF2CA, 0xF2C2, 0xF2C0, 0xCD69, 0xCD6A, 0xCD6B, + 0xF2C5, 0xCD6C, 0xCD6D, 0xCD6E, 0xCD6F, 0xCD70, 0xD6FB, 0xCD71, 0xCD72, + 0xCD73, 0xF2C1, 0xCD74, 0xC7F9, 0xC9DF, 0xCD75, 0xF2C8, 0xB9C6, 0xB5B0, + 0xCD76, 0xCD77, 0xF2C3, 0xF2C9, 0xF2D0, 0xF2D6, 0xCD78, 0xCD79, 0xBBD7, + 0xCD7A, 0xCD7B, 0xCD7C, 0xF2D5, 0xCDDC, 0xCD7D, 0xD6EB, 0xCD7E, 0xCD80, + 0xF2D2, 0xF2D4, 0xCD81, 0xCD82, 0xCD83, 0xCD84, 0xB8F2, 0xCD85, 0xCD86, + 0xCD87, 0xCD88, 0xF2CB, 0xCD89, 0xCD8A, 0xCD8B, 0xF2CE, 0xC2F9, 0xCD8C, + 0xD5DD, 0xF2CC, 0xF2CD, 0xF2CF, 0xF2D3, 0xCD8D, 0xCD8E, 0xCD8F, 0xF2D9, + 0xD3BC, 0xCD90, 0xCD91, 0xCD92, 0xCD93, 0xB6EA, 0xCD94, 0xCAF1, 0xCD95, + 0xB7E4, 0xF2D7, 0xCD96, 0xCD97, 0xCD98, 0xF2D8, 0xF2DA, 0xF2DD, 0xF2DB, + 0xCD99, 0xCD9A, 0xF2DC, 0xCD9B, 0xCD9C, 0xCD9D, 0xCD9E, 0xD1D1, 0xF2D1, + 0xCD9F, 0xCDC9, 0xCDA0, 0xCECF, 0xD6A9, 0xCE40, 0xF2E3, 0xCE41, 0xC3DB, + 0xCE42, 0xF2E0, 0xCE43, 0xCE44, 0xC0AF, 0xF2EC, 0xF2DE, 0xCE45, 0xF2E1, + 0xCE46, 0xCE47, 0xCE48, 0xF2E8, 0xCE49, 0xCE4A, 0xCE4B, 0xCE4C, 0xF2E2, + 0xCE4D, 0xCE4E, 0xF2E7, 0xCE4F, 0xCE50, 0xF2E6, 0xCE51, 0xCE52, 0xF2E9, + 0xCE53, 0xCE54, 0xCE55, 0xF2DF, 0xCE56, 0xCE57, 0xF2E4, 0xF2EA, 0xCE58, + 0xCE59, 0xCE5A, 0xCE5B, 0xCE5C, 0xCE5D, 0xCE5E, 0xD3AC, 0xF2E5, 0xB2F5, + 0xCE5F, 0xCE60, 0xF2F2, 0xCE61, 0xD0AB, 0xCE62, 0xCE63, 0xCE64, 0xCE65, + 0xF2F5, 0xCE66, 0xCE67, 0xCE68, 0xBBC8, 0xCE69, 0xF2F9, 0xCE6A, 0xCE6B, + 0xCE6C, 0xCE6D, 0xCE6E, 0xCE6F, 0xF2F0, 0xCE70, 0xCE71, 0xF2F6, 0xF2F8, + 0xF2FA, 0xCE72, 0xCE73, 0xCE74, 0xCE75, 0xCE76, 0xCE77, 0xCE78, 0xCE79, + 0xF2F3, 0xCE7A, 0xF2F1, 0xCE7B, 0xCE7C, 0xCE7D, 0xBAFB, 0xCE7E, 0xB5FB, + 0xCE80, 0xCE81, 0xCE82, 0xCE83, 0xF2EF, 0xF2F7, 0xF2ED, 0xF2EE, 0xCE84, + 0xCE85, 0xCE86, 0xF2EB, 0xF3A6, 0xCE87, 0xF3A3, 0xCE88, 0xCE89, 0xF3A2, + 0xCE8A, 0xCE8B, 0xF2F4, 0xCE8C, 0xC8DA, 0xCE8D, 0xCE8E, 0xCE8F, 0xCE90, + 0xCE91, 0xF2FB, 0xCE92, 0xCE93, 0xCE94, 0xF3A5, 0xCE95, 0xCE96, 0xCE97, + 0xCE98, 0xCE99, 0xCE9A, 0xCE9B, 0xC3F8, 0xCE9C, 0xCE9D, 0xCE9E, 0xCE9F, + 0xCEA0, 0xCF40, 0xCF41, 0xCF42, 0xF2FD, 0xCF43, 0xCF44, 0xF3A7, 0xF3A9, + 0xF3A4, 0xCF45, 0xF2FC, 0xCF46, 0xCF47, 0xCF48, 0xF3AB, 0xCF49, 0xF3AA, + 0xCF4A, 0xCF4B, 0xCF4C, 0xCF4D, 0xC2DD, 0xCF4E, 0xCF4F, 0xF3AE, 0xCF50, + 0xCF51, 0xF3B0, 0xCF52, 0xCF53, 0xCF54, 0xCF55, 0xCF56, 0xF3A1, 0xCF57, + 0xCF58, 0xCF59, 0xF3B1, 0xF3AC, 0xCF5A, 0xCF5B, 0xCF5C, 0xCF5D, 0xCF5E, + 0xF3AF, 0xF2FE, 0xF3AD, 0xCF5F, 0xCF60, 0xCF61, 0xCF62, 0xCF63, 0xCF64, + 0xCF65, 0xF3B2, 0xCF66, 0xCF67, 0xCF68, 0xCF69, 0xF3B4, 0xCF6A, 0xCF6B, + 0xCF6C, 0xCF6D, 0xF3A8, 0xCF6E, 0xCF6F, 0xCF70, 0xCF71, 0xF3B3, 0xCF72, + 0xCF73, 0xCF74, 0xF3B5, 0xCF75, 0xCF76, 0xCF77, 0xCF78, 0xCF79, 0xCF7A, + 0xCF7B, 0xCF7C, 0xCF7D, 0xCF7E, 0xD0B7, 0xCF80, 0xCF81, 0xCF82, 0xCF83, + 0xF3B8, 0xCF84, 0xCF85, 0xCF86, 0xCF87, 0xD9F9, 0xCF88, 0xCF89, 0xCF8A, + 0xCF8B, 0xCF8C, 0xCF8D, 0xF3B9, 0xCF8E, 0xCF8F, 0xCF90, 0xCF91, 0xCF92, + 0xCF93, 0xCF94, 0xCF95, 0xF3B7, 0xCF96, 0xC8E4, 0xF3B6, 0xCF97, 0xCF98, + 0xCF99, 0xCF9A, 0xF3BA, 0xCF9B, 0xCF9C, 0xCF9D, 0xCF9E, 0xCF9F, 0xF3BB, + 0xB4C0, 0xCFA0, 0xD040, 0xD041, 0xD042, 0xD043, 0xD044, 0xD045, 0xD046, + 0xD047, 0xD048, 0xD049, 0xD04A, 0xD04B, 0xD04C, 0xD04D, 0xEEC3, 0xD04E, + 0xD04F, 0xD050, 0xD051, 0xD052, 0xD053, 0xF3BC, 0xD054, 0xD055, 0xF3BD, + 0xD056, 0xD057, 0xD058, 0xD1AA, 0xD059, 0xD05A, 0xD05B, 0xF4AC, 0xD0C6, + 0xD05C, 0xD05D, 0xD05E, 0xD05F, 0xD060, 0xD061, 0xD0D0, 0xD1DC, 0xD062, + 0xD063, 0xD064, 0xD065, 0xD066, 0xD067, 0xCFCE, 0xD068, 0xD069, 0xBDD6, + 0xD06A, 0xD1C3, 0xD06B, 0xD06C, 0xD06D, 0xD06E, 0xD06F, 0xD070, 0xD071, + 0xBAE2, 0xE1E9, 0xD2C2, 0xF1C2, 0xB2B9, 0xD072, 0xD073, 0xB1ED, 0xF1C3, + 0xD074, 0xC9C0, 0xB3C4, 0xD075, 0xD9F2, 0xD076, 0xCBA5, 0xD077, 0xF1C4, + 0xD078, 0xD079, 0xD07A, 0xD07B, 0xD6D4, 0xD07C, 0xD07D, 0xD07E, 0xD080, + 0xD081, 0xF1C5, 0xF4C0, 0xF1C6, 0xD082, 0xD4AC, 0xF1C7, 0xD083, 0xB0C0, + 0xF4C1, 0xD084, 0xD085, 0xF4C2, 0xD086, 0xD087, 0xB4FC, 0xD088, 0xC5DB, + 0xD089, 0xD08A, 0xD08B, 0xD08C, 0xCCBB, 0xD08D, 0xD08E, 0xD08F, 0xD0E4, + 0xD090, 0xD091, 0xD092, 0xD093, 0xD094, 0xCDE0, 0xD095, 0xD096, 0xD097, + 0xD098, 0xD099, 0xF1C8, 0xD09A, 0xD9F3, 0xD09B, 0xD09C, 0xD09D, 0xD09E, + 0xD09F, 0xD0A0, 0xB1BB, 0xD140, 0xCFAE, 0xD141, 0xD142, 0xD143, 0xB8A4, + 0xD144, 0xD145, 0xD146, 0xD147, 0xD148, 0xF1CA, 0xD149, 0xD14A, 0xD14B, + 0xD14C, 0xF1CB, 0xD14D, 0xD14E, 0xD14F, 0xD150, 0xB2C3, 0xC1D1, 0xD151, + 0xD152, 0xD7B0, 0xF1C9, 0xD153, 0xD154, 0xF1CC, 0xD155, 0xD156, 0xD157, + 0xD158, 0xF1CE, 0xD159, 0xD15A, 0xD15B, 0xD9F6, 0xD15C, 0xD2E1, 0xD4A3, + 0xD15D, 0xD15E, 0xF4C3, 0xC8B9, 0xD15F, 0xD160, 0xD161, 0xD162, 0xD163, + 0xF4C4, 0xD164, 0xD165, 0xF1CD, 0xF1CF, 0xBFE3, 0xF1D0, 0xD166, 0xD167, + 0xF1D4, 0xD168, 0xD169, 0xD16A, 0xD16B, 0xD16C, 0xD16D, 0xD16E, 0xF1D6, + 0xF1D1, 0xD16F, 0xC9D1, 0xC5E1, 0xD170, 0xD171, 0xD172, 0xC2E3, 0xB9FC, + 0xD173, 0xD174, 0xF1D3, 0xD175, 0xF1D5, 0xD176, 0xD177, 0xD178, 0xB9D3, + 0xD179, 0xD17A, 0xD17B, 0xD17C, 0xD17D, 0xD17E, 0xD180, 0xF1DB, 0xD181, + 0xD182, 0xD183, 0xD184, 0xD185, 0xBAD6, 0xD186, 0xB0FD, 0xF1D9, 0xD187, + 0xD188, 0xD189, 0xD18A, 0xD18B, 0xF1D8, 0xF1D2, 0xF1DA, 0xD18C, 0xD18D, + 0xD18E, 0xD18F, 0xD190, 0xF1D7, 0xD191, 0xD192, 0xD193, 0xC8EC, 0xD194, + 0xD195, 0xD196, 0xD197, 0xCDCA, 0xF1DD, 0xD198, 0xD199, 0xD19A, 0xD19B, + 0xE5BD, 0xD19C, 0xD19D, 0xD19E, 0xF1DC, 0xD19F, 0xF1DE, 0xD1A0, 0xD240, + 0xD241, 0xD242, 0xD243, 0xD244, 0xD245, 0xD246, 0xD247, 0xD248, 0xF1DF, + 0xD249, 0xD24A, 0xCFE5, 0xD24B, 0xD24C, 0xD24D, 0xD24E, 0xD24F, 0xD250, + 0xD251, 0xD252, 0xD253, 0xD254, 0xD255, 0xD256, 0xD257, 0xD258, 0xD259, + 0xD25A, 0xD25B, 0xD25C, 0xD25D, 0xD25E, 0xD25F, 0xD260, 0xD261, 0xD262, + 0xD263, 0xF4C5, 0xBDF3, 0xD264, 0xD265, 0xD266, 0xD267, 0xD268, 0xD269, + 0xF1E0, 0xD26A, 0xD26B, 0xD26C, 0xD26D, 0xD26E, 0xD26F, 0xD270, 0xD271, + 0xD272, 0xD273, 0xD274, 0xD275, 0xD276, 0xD277, 0xD278, 0xD279, 0xD27A, + 0xD27B, 0xD27C, 0xD27D, 0xF1E1, 0xD27E, 0xD280, 0xD281, 0xCEF7, 0xD282, + 0xD2AA, 0xD283, 0xF1FB, 0xD284, 0xD285, 0xB8B2, 0xD286, 0xD287, 0xD288, + 0xD289, 0xD28A, 0xD28B, 0xD28C, 0xD28D, 0xD28E, 0xD28F, 0xD290, 0xD291, + 0xD292, 0xD293, 0xD294, 0xD295, 0xD296, 0xD297, 0xD298, 0xD299, 0xD29A, + 0xD29B, 0xD29C, 0xD29D, 0xD29E, 0xD29F, 0xD2A0, 0xD340, 0xD341, 0xD342, + 0xD343, 0xD344, 0xD345, 0xD346, 0xD347, 0xD348, 0xD349, 0xD34A, 0xD34B, + 0xD34C, 0xD34D, 0xD34E, 0xD34F, 0xD350, 0xD351, 0xD352, 0xD353, 0xD354, + 0xD355, 0xD356, 0xD357, 0xD358, 0xD359, 0xD35A, 0xD35B, 0xD35C, 0xD35D, + 0xD35E, 0xBCFB, 0xB9DB, 0xD35F, 0xB9E6, 0xC3D9, 0xCAD3, 0xEAE8, 0xC0C0, + 0xBEF5, 0xEAE9, 0xEAEA, 0xEAEB, 0xD360, 0xEAEC, 0xEAED, 0xEAEE, 0xEAEF, + 0xBDC7, 0xD361, 0xD362, 0xD363, 0xF5FB, 0xD364, 0xD365, 0xD366, 0xF5FD, + 0xD367, 0xF5FE, 0xD368, 0xF5FC, 0xD369, 0xD36A, 0xD36B, 0xD36C, 0xBDE2, + 0xD36D, 0xF6A1, 0xB4A5, 0xD36E, 0xD36F, 0xD370, 0xD371, 0xF6A2, 0xD372, + 0xD373, 0xD374, 0xF6A3, 0xD375, 0xD376, 0xD377, 0xECB2, 0xD378, 0xD379, + 0xD37A, 0xD37B, 0xD37C, 0xD37D, 0xD37E, 0xD380, 0xD381, 0xD382, 0xD383, + 0xD384, 0xD1D4, 0xD385, 0xD386, 0xD387, 0xD388, 0xD389, 0xD38A, 0xD9EA, + 0xD38B, 0xD38C, 0xD38D, 0xD38E, 0xD38F, 0xD390, 0xD391, 0xD392, 0xD393, + 0xD394, 0xD395, 0xD396, 0xD397, 0xD398, 0xD399, 0xD39A, 0xD39B, 0xD39C, + 0xD39D, 0xD39E, 0xD39F, 0xD3A0, 0xD440, 0xD441, 0xD442, 0xD443, 0xD444, + 0xD445, 0xD446, 0xD447, 0xD448, 0xD449, 0xD44A, 0xD44B, 0xD44C, 0xD44D, + 0xD44E, 0xD44F, 0xD450, 0xD451, 0xD452, 0xD453, 0xD454, 0xD455, 0xD456, + 0xD457, 0xD458, 0xD459, 0xD45A, 0xD45B, 0xD45C, 0xD45D, 0xD45E, 0xD45F, + 0xF6A4, 0xD460, 0xD461, 0xD462, 0xD463, 0xD464, 0xD465, 0xD466, 0xD467, + 0xD468, 0xEEBA, 0xD469, 0xD46A, 0xD46B, 0xD46C, 0xD46D, 0xD46E, 0xD46F, + 0xD470, 0xD471, 0xD472, 0xD473, 0xD474, 0xD475, 0xD476, 0xD477, 0xD478, + 0xD479, 0xD47A, 0xD47B, 0xD47C, 0xD47D, 0xD47E, 0xD480, 0xD481, 0xD482, + 0xD483, 0xD484, 0xD485, 0xD486, 0xD487, 0xD488, 0xD489, 0xD48A, 0xD48B, + 0xD48C, 0xD48D, 0xD48E, 0xD48F, 0xD490, 0xD491, 0xD492, 0xD493, 0xD494, + 0xD495, 0xD496, 0xD497, 0xD498, 0xD499, 0xD5B2, 0xD49A, 0xD49B, 0xD49C, + 0xD49D, 0xD49E, 0xD49F, 0xD4A0, 0xD540, 0xD541, 0xD542, 0xD543, 0xD544, + 0xD545, 0xD546, 0xD547, 0xD3FE, 0xCCDC, 0xD548, 0xD549, 0xD54A, 0xD54B, + 0xD54C, 0xD54D, 0xD54E, 0xD54F, 0xCAC4, 0xD550, 0xD551, 0xD552, 0xD553, + 0xD554, 0xD555, 0xD556, 0xD557, 0xD558, 0xD559, 0xD55A, 0xD55B, 0xD55C, + 0xD55D, 0xD55E, 0xD55F, 0xD560, 0xD561, 0xD562, 0xD563, 0xD564, 0xD565, + 0xD566, 0xD567, 0xD568, 0xD569, 0xD56A, 0xD56B, 0xD56C, 0xD56D, 0xD56E, + 0xD56F, 0xD570, 0xD571, 0xD572, 0xD573, 0xD574, 0xD575, 0xD576, 0xD577, + 0xD578, 0xD579, 0xD57A, 0xD57B, 0xD57C, 0xD57D, 0xD57E, 0xD580, 0xD581, + 0xD582, 0xD583, 0xD584, 0xD585, 0xD586, 0xD587, 0xD588, 0xD589, 0xD58A, + 0xD58B, 0xD58C, 0xD58D, 0xD58E, 0xD58F, 0xD590, 0xD591, 0xD592, 0xD593, + 0xD594, 0xD595, 0xD596, 0xD597, 0xD598, 0xD599, 0xD59A, 0xD59B, 0xD59C, + 0xD59D, 0xD59E, 0xD59F, 0xD5A0, 0xD640, 0xD641, 0xD642, 0xD643, 0xD644, + 0xD645, 0xD646, 0xD647, 0xD648, 0xD649, 0xD64A, 0xD64B, 0xD64C, 0xD64D, + 0xD64E, 0xD64F, 0xD650, 0xD651, 0xD652, 0xD653, 0xD654, 0xD655, 0xD656, + 0xD657, 0xD658, 0xD659, 0xD65A, 0xD65B, 0xD65C, 0xD65D, 0xD65E, 0xD65F, + 0xD660, 0xD661, 0xD662, 0xE5C0, 0xD663, 0xD664, 0xD665, 0xD666, 0xD667, + 0xD668, 0xD669, 0xD66A, 0xD66B, 0xD66C, 0xD66D, 0xD66E, 0xD66F, 0xD670, + 0xD671, 0xD672, 0xD673, 0xD674, 0xD675, 0xD676, 0xD677, 0xD678, 0xD679, + 0xD67A, 0xD67B, 0xD67C, 0xD67D, 0xD67E, 0xD680, 0xD681, 0xF6A5, 0xD682, + 0xD683, 0xD684, 0xD685, 0xD686, 0xD687, 0xD688, 0xD689, 0xD68A, 0xD68B, + 0xD68C, 0xD68D, 0xD68E, 0xD68F, 0xD690, 0xD691, 0xD692, 0xD693, 0xD694, + 0xD695, 0xD696, 0xD697, 0xD698, 0xD699, 0xD69A, 0xD69B, 0xD69C, 0xD69D, + 0xD69E, 0xD69F, 0xD6A0, 0xD740, 0xD741, 0xD742, 0xD743, 0xD744, 0xD745, + 0xD746, 0xD747, 0xD748, 0xD749, 0xD74A, 0xD74B, 0xD74C, 0xD74D, 0xD74E, + 0xD74F, 0xD750, 0xD751, 0xD752, 0xD753, 0xD754, 0xD755, 0xD756, 0xD757, + 0xD758, 0xD759, 0xD75A, 0xD75B, 0xD75C, 0xD75D, 0xD75E, 0xD75F, 0xBEAF, + 0xD760, 0xD761, 0xD762, 0xD763, 0xD764, 0xC6A9, 0xD765, 0xD766, 0xD767, + 0xD768, 0xD769, 0xD76A, 0xD76B, 0xD76C, 0xD76D, 0xD76E, 0xD76F, 0xD770, + 0xD771, 0xD772, 0xD773, 0xD774, 0xD775, 0xD776, 0xD777, 0xD778, 0xD779, + 0xD77A, 0xD77B, 0xD77C, 0xD77D, 0xD77E, 0xD780, 0xD781, 0xD782, 0xD783, + 0xD784, 0xD785, 0xD786, 0xD787, 0xD788, 0xD789, 0xD78A, 0xD78B, 0xD78C, + 0xD78D, 0xD78E, 0xD78F, 0xD790, 0xD791, 0xD792, 0xD793, 0xD794, 0xD795, + 0xD796, 0xD797, 0xD798, 0xDAA5, 0xBCC6, 0xB6A9, 0xB8BC, 0xC8CF, 0xBCA5, + 0xDAA6, 0xDAA7, 0xCCD6, 0xC8C3, 0xDAA8, 0xC6FD, 0xD799, 0xD1B5, 0xD2E9, + 0xD1B6, 0xBCC7, 0xD79A, 0xBDB2, 0xBBE4, 0xDAA9, 0xDAAA, 0xD1C8, 0xDAAB, + 0xD0ED, 0xB6EF, 0xC2DB, 0xD79B, 0xCBCF, 0xB7ED, 0xC9E8, 0xB7C3, 0xBEF7, + 0xD6A4, 0xDAAC, 0xDAAD, 0xC6C0, 0xD7E7, 0xCAB6, 0xD79C, 0xD5A9, 0xCBDF, + 0xD5EF, 0xDAAE, 0xD6DF, 0xB4CA, 0xDAB0, 0xDAAF, 0xD79D, 0xD2EB, 0xDAB1, + 0xDAB2, 0xDAB3, 0xCAD4, 0xDAB4, 0xCAAB, 0xDAB5, 0xDAB6, 0xB3CF, 0xD6EF, + 0xDAB7, 0xBBB0, 0xB5AE, 0xDAB8, 0xDAB9, 0xB9EE, 0xD1AF, 0xD2E8, 0xDABA, + 0xB8C3, 0xCFEA, 0xB2EF, 0xDABB, 0xDABC, 0xD79E, 0xBDEB, 0xCEDC, 0xD3EF, + 0xDABD, 0xCEF3, 0xDABE, 0xD3D5, 0xBBE5, 0xDABF, 0xCBB5, 0xCBD0, 0xDAC0, + 0xC7EB, 0xD6EE, 0xDAC1, 0xC5B5, 0xB6C1, 0xDAC2, 0xB7CC, 0xBFCE, 0xDAC3, + 0xDAC4, 0xCBAD, 0xDAC5, 0xB5F7, 0xDAC6, 0xC1C2, 0xD7BB, 0xDAC7, 0xCCB8, + 0xD79F, 0xD2EA, 0xC4B1, 0xDAC8, 0xB5FD, 0xBBD1, 0xDAC9, 0xD0B3, 0xDACA, + 0xDACB, 0xCEBD, 0xDACC, 0xDACD, 0xDACE, 0xB2F7, 0xDAD1, 0xDACF, 0xD1E8, + 0xDAD0, 0xC3D5, 0xDAD2, 0xD7A0, 0xDAD3, 0xDAD4, 0xDAD5, 0xD0BB, 0xD2A5, + 0xB0F9, 0xDAD6, 0xC7AB, 0xDAD7, 0xBDF7, 0xC3A1, 0xDAD8, 0xDAD9, 0xC3FD, + 0xCCB7, 0xDADA, 0xDADB, 0xC0BE, 0xC6D7, 0xDADC, 0xDADD, 0xC7B4, 0xDADE, + 0xDADF, 0xB9C8, 0xD840, 0xD841, 0xD842, 0xD843, 0xD844, 0xD845, 0xD846, + 0xD847, 0xD848, 0xBBED, 0xD849, 0xD84A, 0xD84B, 0xD84C, 0xB6B9, 0xF4F8, + 0xD84D, 0xF4F9, 0xD84E, 0xD84F, 0xCDE3, 0xD850, 0xD851, 0xD852, 0xD853, + 0xD854, 0xD855, 0xD856, 0xD857, 0xF5B9, 0xD858, 0xD859, 0xD85A, 0xD85B, + 0xEBE0, 0xD85C, 0xD85D, 0xD85E, 0xD85F, 0xD860, 0xD861, 0xCFF3, 0xBBBF, + 0xD862, 0xD863, 0xD864, 0xD865, 0xD866, 0xD867, 0xD868, 0xBAC0, 0xD4A5, + 0xD869, 0xD86A, 0xD86B, 0xD86C, 0xD86D, 0xD86E, 0xD86F, 0xE1D9, 0xD870, + 0xD871, 0xD872, 0xD873, 0xF5F4, 0xB1AA, 0xB2F2, 0xD874, 0xD875, 0xD876, + 0xD877, 0xD878, 0xD879, 0xD87A, 0xF5F5, 0xD87B, 0xD87C, 0xF5F7, 0xD87D, + 0xD87E, 0xD880, 0xBAD1, 0xF5F6, 0xD881, 0xC3B2, 0xD882, 0xD883, 0xD884, + 0xD885, 0xD886, 0xD887, 0xD888, 0xF5F9, 0xD889, 0xD88A, 0xD88B, 0xF5F8, + 0xD88C, 0xD88D, 0xD88E, 0xD88F, 0xD890, 0xD891, 0xD892, 0xD893, 0xD894, + 0xD895, 0xD896, 0xD897, 0xD898, 0xD899, 0xD89A, 0xD89B, 0xD89C, 0xD89D, + 0xD89E, 0xD89F, 0xD8A0, 0xD940, 0xD941, 0xD942, 0xD943, 0xD944, 0xD945, + 0xD946, 0xD947, 0xD948, 0xD949, 0xD94A, 0xD94B, 0xD94C, 0xD94D, 0xD94E, + 0xD94F, 0xD950, 0xD951, 0xD952, 0xD953, 0xD954, 0xD955, 0xD956, 0xD957, + 0xD958, 0xD959, 0xD95A, 0xD95B, 0xD95C, 0xD95D, 0xD95E, 0xD95F, 0xD960, + 0xD961, 0xD962, 0xD963, 0xD964, 0xD965, 0xD966, 0xD967, 0xD968, 0xD969, + 0xD96A, 0xD96B, 0xD96C, 0xD96D, 0xD96E, 0xD96F, 0xD970, 0xD971, 0xD972, + 0xD973, 0xD974, 0xD975, 0xD976, 0xD977, 0xD978, 0xD979, 0xD97A, 0xD97B, + 0xD97C, 0xD97D, 0xD97E, 0xD980, 0xD981, 0xD982, 0xD983, 0xD984, 0xD985, + 0xD986, 0xD987, 0xD988, 0xD989, 0xD98A, 0xD98B, 0xD98C, 0xD98D, 0xD98E, + 0xD98F, 0xD990, 0xD991, 0xD992, 0xD993, 0xD994, 0xD995, 0xD996, 0xD997, + 0xD998, 0xD999, 0xD99A, 0xD99B, 0xD99C, 0xD99D, 0xD99E, 0xD99F, 0xD9A0, + 0xDA40, 0xDA41, 0xDA42, 0xDA43, 0xDA44, 0xDA45, 0xDA46, 0xDA47, 0xDA48, + 0xDA49, 0xDA4A, 0xDA4B, 0xDA4C, 0xDA4D, 0xDA4E, 0xB1B4, 0xD5EA, 0xB8BA, + 0xDA4F, 0xB9B1, 0xB2C6, 0xD4F0, 0xCFCD, 0xB0DC, 0xD5CB, 0xBBF5, 0xD6CA, + 0xB7B7, 0xCCB0, 0xC6B6, 0xB1E1, 0xB9BA, 0xD6FC, 0xB9E1, 0xB7A1, 0xBCFA, + 0xEADA, 0xEADB, 0xCCF9, 0xB9F3, 0xEADC, 0xB4FB, 0xC3B3, 0xB7D1, 0xBAD8, + 0xEADD, 0xD4F4, 0xEADE, 0xBCD6, 0xBBDF, 0xEADF, 0xC1DE, 0xC2B8, 0xD4DF, + 0xD7CA, 0xEAE0, 0xEAE1, 0xEAE4, 0xEAE2, 0xEAE3, 0xC9DE, 0xB8B3, 0xB6C4, + 0xEAE5, 0xCAEA, 0xC9CD, 0xB4CD, 0xDA50, 0xDA51, 0xE2D9, 0xC5E2, 0xEAE6, + 0xC0B5, 0xDA52, 0xD7B8, 0xEAE7, 0xD7AC, 0xC8FC, 0xD8D3, 0xD8CD, 0xD4DE, + 0xDA53, 0xD4F9, 0xC9C4, 0xD3AE, 0xB8D3, 0xB3E0, 0xDA54, 0xC9E2, 0xF4F6, + 0xDA55, 0xDA56, 0xDA57, 0xBAD5, 0xDA58, 0xF4F7, 0xDA59, 0xDA5A, 0xD7DF, + 0xDA5B, 0xDA5C, 0xF4F1, 0xB8B0, 0xD5D4, 0xB8CF, 0xC6F0, 0xDA5D, 0xDA5E, + 0xDA5F, 0xDA60, 0xDA61, 0xDA62, 0xDA63, 0xDA64, 0xDA65, 0xB3C3, 0xDA66, + 0xDA67, 0xF4F2, 0xB3AC, 0xDA68, 0xDA69, 0xDA6A, 0xDA6B, 0xD4BD, 0xC7F7, + 0xDA6C, 0xDA6D, 0xDA6E, 0xDA6F, 0xDA70, 0xF4F4, 0xDA71, 0xDA72, 0xF4F3, + 0xDA73, 0xDA74, 0xDA75, 0xDA76, 0xDA77, 0xDA78, 0xDA79, 0xDA7A, 0xDA7B, + 0xDA7C, 0xCCCB, 0xDA7D, 0xDA7E, 0xDA80, 0xC8A4, 0xDA81, 0xDA82, 0xDA83, + 0xDA84, 0xDA85, 0xDA86, 0xDA87, 0xDA88, 0xDA89, 0xDA8A, 0xDA8B, 0xDA8C, + 0xDA8D, 0xF4F5, 0xDA8E, 0xD7E3, 0xC5BF, 0xF5C0, 0xDA8F, 0xDA90, 0xF5BB, + 0xDA91, 0xF5C3, 0xDA92, 0xF5C2, 0xDA93, 0xD6BA, 0xF5C1, 0xDA94, 0xDA95, + 0xDA96, 0xD4BE, 0xF5C4, 0xDA97, 0xF5CC, 0xDA98, 0xDA99, 0xDA9A, 0xDA9B, + 0xB0CF, 0xB5F8, 0xDA9C, 0xF5C9, 0xF5CA, 0xDA9D, 0xC5DC, 0xDA9E, 0xDA9F, + 0xDAA0, 0xDB40, 0xF5C5, 0xF5C6, 0xDB41, 0xDB42, 0xF5C7, 0xF5CB, 0xDB43, + 0xBEE0, 0xF5C8, 0xB8FA, 0xDB44, 0xDB45, 0xDB46, 0xF5D0, 0xF5D3, 0xDB47, + 0xDB48, 0xDB49, 0xBFE7, 0xDB4A, 0xB9F2, 0xF5BC, 0xF5CD, 0xDB4B, 0xDB4C, + 0xC2B7, 0xDB4D, 0xDB4E, 0xDB4F, 0xCCF8, 0xDB50, 0xBCF9, 0xDB51, 0xF5CE, + 0xF5CF, 0xF5D1, 0xB6E5, 0xF5D2, 0xDB52, 0xF5D5, 0xDB53, 0xDB54, 0xDB55, + 0xDB56, 0xDB57, 0xDB58, 0xDB59, 0xF5BD, 0xDB5A, 0xDB5B, 0xDB5C, 0xF5D4, + 0xD3BB, 0xDB5D, 0xB3EC, 0xDB5E, 0xDB5F, 0xCCA4, 0xDB60, 0xDB61, 0xDB62, + 0xDB63, 0xF5D6, 0xDB64, 0xDB65, 0xDB66, 0xDB67, 0xDB68, 0xDB69, 0xDB6A, + 0xDB6B, 0xF5D7, 0xBEE1, 0xF5D8, 0xDB6C, 0xDB6D, 0xCCDF, 0xF5DB, 0xDB6E, + 0xDB6F, 0xDB70, 0xDB71, 0xDB72, 0xB2C8, 0xD7D9, 0xDB73, 0xF5D9, 0xDB74, + 0xF5DA, 0xF5DC, 0xDB75, 0xF5E2, 0xDB76, 0xDB77, 0xDB78, 0xF5E0, 0xDB79, + 0xDB7A, 0xDB7B, 0xF5DF, 0xF5DD, 0xDB7C, 0xDB7D, 0xF5E1, 0xDB7E, 0xDB80, + 0xF5DE, 0xF5E4, 0xF5E5, 0xDB81, 0xCCE3, 0xDB82, 0xDB83, 0xE5BF, 0xB5B8, + 0xF5E3, 0xF5E8, 0xCCA3, 0xDB84, 0xDB85, 0xDB86, 0xDB87, 0xDB88, 0xF5E6, + 0xF5E7, 0xDB89, 0xDB8A, 0xDB8B, 0xDB8C, 0xDB8D, 0xDB8E, 0xF5BE, 0xDB8F, + 0xDB90, 0xDB91, 0xDB92, 0xDB93, 0xDB94, 0xDB95, 0xDB96, 0xDB97, 0xDB98, + 0xDB99, 0xDB9A, 0xB1C4, 0xDB9B, 0xDB9C, 0xF5BF, 0xDB9D, 0xDB9E, 0xB5C5, + 0xB2E4, 0xDB9F, 0xF5EC, 0xF5E9, 0xDBA0, 0xB6D7, 0xDC40, 0xF5ED, 0xDC41, + 0xF5EA, 0xDC42, 0xDC43, 0xDC44, 0xDC45, 0xDC46, 0xF5EB, 0xDC47, 0xDC48, + 0xB4DA, 0xDC49, 0xD4EA, 0xDC4A, 0xDC4B, 0xDC4C, 0xF5EE, 0xDC4D, 0xB3F9, + 0xDC4E, 0xDC4F, 0xDC50, 0xDC51, 0xDC52, 0xDC53, 0xDC54, 0xF5EF, 0xF5F1, + 0xDC55, 0xDC56, 0xDC57, 0xF5F0, 0xDC58, 0xDC59, 0xDC5A, 0xDC5B, 0xDC5C, + 0xDC5D, 0xDC5E, 0xF5F2, 0xDC5F, 0xF5F3, 0xDC60, 0xDC61, 0xDC62, 0xDC63, + 0xDC64, 0xDC65, 0xDC66, 0xDC67, 0xDC68, 0xDC69, 0xDC6A, 0xDC6B, 0xC9ED, + 0xB9AA, 0xDC6C, 0xDC6D, 0xC7FB, 0xDC6E, 0xDC6F, 0xB6E3, 0xDC70, 0xDC71, + 0xDC72, 0xDC73, 0xDC74, 0xDC75, 0xDC76, 0xCCC9, 0xDC77, 0xDC78, 0xDC79, + 0xDC7A, 0xDC7B, 0xDC7C, 0xDC7D, 0xDC7E, 0xDC80, 0xDC81, 0xDC82, 0xDC83, + 0xDC84, 0xDC85, 0xDC86, 0xDC87, 0xDC88, 0xDC89, 0xDC8A, 0xEAA6, 0xDC8B, + 0xDC8C, 0xDC8D, 0xDC8E, 0xDC8F, 0xDC90, 0xDC91, 0xDC92, 0xDC93, 0xDC94, + 0xDC95, 0xDC96, 0xDC97, 0xDC98, 0xDC99, 0xDC9A, 0xDC9B, 0xDC9C, 0xDC9D, + 0xDC9E, 0xDC9F, 0xDCA0, 0xDD40, 0xDD41, 0xDD42, 0xDD43, 0xDD44, 0xDD45, + 0xDD46, 0xDD47, 0xDD48, 0xDD49, 0xDD4A, 0xDD4B, 0xDD4C, 0xDD4D, 0xDD4E, + 0xDD4F, 0xDD50, 0xDD51, 0xDD52, 0xDD53, 0xDD54, 0xDD55, 0xDD56, 0xDD57, + 0xDD58, 0xDD59, 0xDD5A, 0xDD5B, 0xDD5C, 0xDD5D, 0xDD5E, 0xDD5F, 0xDD60, + 0xDD61, 0xDD62, 0xDD63, 0xDD64, 0xDD65, 0xDD66, 0xDD67, 0xDD68, 0xDD69, + 0xDD6A, 0xDD6B, 0xDD6C, 0xDD6D, 0xDD6E, 0xDD6F, 0xDD70, 0xDD71, 0xDD72, + 0xDD73, 0xDD74, 0xDD75, 0xDD76, 0xDD77, 0xDD78, 0xDD79, 0xDD7A, 0xDD7B, + 0xDD7C, 0xDD7D, 0xDD7E, 0xDD80, 0xDD81, 0xDD82, 0xDD83, 0xDD84, 0xDD85, + 0xDD86, 0xDD87, 0xDD88, 0xDD89, 0xDD8A, 0xDD8B, 0xDD8C, 0xDD8D, 0xDD8E, + 0xDD8F, 0xDD90, 0xDD91, 0xDD92, 0xDD93, 0xDD94, 0xDD95, 0xDD96, 0xDD97, + 0xDD98, 0xDD99, 0xDD9A, 0xDD9B, 0xDD9C, 0xDD9D, 0xDD9E, 0xDD9F, 0xDDA0, + 0xDE40, 0xDE41, 0xDE42, 0xDE43, 0xDE44, 0xDE45, 0xDE46, 0xDE47, 0xDE48, + 0xDE49, 0xDE4A, 0xDE4B, 0xDE4C, 0xDE4D, 0xDE4E, 0xDE4F, 0xDE50, 0xDE51, + 0xDE52, 0xDE53, 0xDE54, 0xDE55, 0xDE56, 0xDE57, 0xDE58, 0xDE59, 0xDE5A, + 0xDE5B, 0xDE5C, 0xDE5D, 0xDE5E, 0xDE5F, 0xDE60, 0xB3B5, 0xD4FE, 0xB9EC, + 0xD0F9, 0xDE61, 0xE9ED, 0xD7AA, 0xE9EE, 0xC2D6, 0xC8ED, 0xBAE4, 0xE9EF, + 0xE9F0, 0xE9F1, 0xD6E1, 0xE9F2, 0xE9F3, 0xE9F5, 0xE9F4, 0xE9F6, 0xE9F7, + 0xC7E1, 0xE9F8, 0xD4D8, 0xE9F9, 0xBDCE, 0xDE62, 0xE9FA, 0xE9FB, 0xBDCF, + 0xE9FC, 0xB8A8, 0xC1BE, 0xE9FD, 0xB1B2, 0xBBD4, 0xB9F5, 0xE9FE, 0xDE63, + 0xEAA1, 0xEAA2, 0xEAA3, 0xB7F8, 0xBCAD, 0xDE64, 0xCAE4, 0xE0CE, 0xD4AF, + 0xCFBD, 0xD5B7, 0xEAA4, 0xD5DE, 0xEAA5, 0xD0C1, 0xB9BC, 0xDE65, 0xB4C7, + 0xB1D9, 0xDE66, 0xDE67, 0xDE68, 0xC0B1, 0xDE69, 0xDE6A, 0xDE6B, 0xDE6C, + 0xB1E6, 0xB1E7, 0xDE6D, 0xB1E8, 0xDE6E, 0xDE6F, 0xDE70, 0xDE71, 0xB3BD, + 0xC8E8, 0xDE72, 0xDE73, 0xDE74, 0xDE75, 0xE5C1, 0xDE76, 0xDE77, 0xB1DF, + 0xDE78, 0xDE79, 0xDE7A, 0xC1C9, 0xB4EF, 0xDE7B, 0xDE7C, 0xC7A8, 0xD3D8, + 0xDE7D, 0xC6F9, 0xD1B8, 0xDE7E, 0xB9FD, 0xC2F5, 0xDE80, 0xDE81, 0xDE82, + 0xDE83, 0xDE84, 0xD3AD, 0xDE85, 0xD4CB, 0xBDFC, 0xDE86, 0xE5C2, 0xB7B5, + 0xE5C3, 0xDE87, 0xDE88, 0xBBB9, 0xD5E2, 0xDE89, 0xBDF8, 0xD4B6, 0xCEA5, + 0xC1AC, 0xB3D9, 0xDE8A, 0xDE8B, 0xCCF6, 0xDE8C, 0xE5C6, 0xE5C4, 0xE5C8, + 0xDE8D, 0xE5CA, 0xE5C7, 0xB5CF, 0xC6C8, 0xDE8E, 0xB5FC, 0xE5C5, 0xDE8F, + 0xCAF6, 0xDE90, 0xDE91, 0xE5C9, 0xDE92, 0xDE93, 0xDE94, 0xC3D4, 0xB1C5, + 0xBCA3, 0xDE95, 0xDE96, 0xDE97, 0xD7B7, 0xDE98, 0xDE99, 0xCDCB, 0xCBCD, + 0xCACA, 0xCCD3, 0xE5CC, 0xE5CB, 0xC4E6, 0xDE9A, 0xDE9B, 0xD1A1, 0xD1B7, + 0xE5CD, 0xDE9C, 0xE5D0, 0xDE9D, 0xCDB8, 0xD6F0, 0xE5CF, 0xB5DD, 0xDE9E, + 0xCDBE, 0xDE9F, 0xE5D1, 0xB6BA, 0xDEA0, 0xDF40, 0xCDA8, 0xB9E4, 0xDF41, + 0xCAC5, 0xB3D1, 0xCBD9, 0xD4EC, 0xE5D2, 0xB7EA, 0xDF42, 0xDF43, 0xDF44, + 0xE5CE, 0xDF45, 0xDF46, 0xDF47, 0xDF48, 0xDF49, 0xDF4A, 0xE5D5, 0xB4FE, + 0xE5D6, 0xDF4B, 0xDF4C, 0xDF4D, 0xDF4E, 0xDF4F, 0xE5D3, 0xE5D4, 0xDF50, + 0xD2DD, 0xDF51, 0xDF52, 0xC2DF, 0xB1C6, 0xDF53, 0xD3E2, 0xDF54, 0xDF55, + 0xB6DD, 0xCBEC, 0xDF56, 0xE5D7, 0xDF57, 0xDF58, 0xD3F6, 0xDF59, 0xDF5A, + 0xDF5B, 0xDF5C, 0xDF5D, 0xB1E9, 0xDF5E, 0xB6F4, 0xE5DA, 0xE5D8, 0xE5D9, + 0xB5C0, 0xDF5F, 0xDF60, 0xDF61, 0xD2C5, 0xE5DC, 0xDF62, 0xDF63, 0xE5DE, + 0xDF64, 0xDF65, 0xDF66, 0xDF67, 0xDF68, 0xDF69, 0xE5DD, 0xC7B2, 0xDF6A, + 0xD2A3, 0xDF6B, 0xDF6C, 0xE5DB, 0xDF6D, 0xDF6E, 0xDF6F, 0xDF70, 0xD4E2, + 0xD5DA, 0xDF71, 0xDF72, 0xDF73, 0xDF74, 0xDF75, 0xE5E0, 0xD7F1, 0xDF76, + 0xDF77, 0xDF78, 0xDF79, 0xDF7A, 0xDF7B, 0xDF7C, 0xE5E1, 0xDF7D, 0xB1DC, + 0xD1FB, 0xDF7E, 0xE5E2, 0xE5E4, 0xDF80, 0xDF81, 0xDF82, 0xDF83, 0xE5E3, + 0xDF84, 0xDF85, 0xE5E5, 0xDF86, 0xDF87, 0xDF88, 0xDF89, 0xDF8A, 0xD2D8, + 0xDF8B, 0xB5CB, 0xDF8C, 0xE7DF, 0xDF8D, 0xDAF5, 0xDF8E, 0xDAF8, 0xDF8F, + 0xDAF6, 0xDF90, 0xDAF7, 0xDF91, 0xDF92, 0xDF93, 0xDAFA, 0xD0CF, 0xC4C7, + 0xDF94, 0xDF95, 0xB0EE, 0xDF96, 0xDF97, 0xDF98, 0xD0B0, 0xDF99, 0xDAF9, + 0xDF9A, 0xD3CA, 0xBAAA, 0xDBA2, 0xC7F1, 0xDF9B, 0xDAFC, 0xDAFB, 0xC9DB, + 0xDAFD, 0xDF9C, 0xDBA1, 0xD7DE, 0xDAFE, 0xC1DA, 0xDF9D, 0xDF9E, 0xDBA5, + 0xDF9F, 0xDFA0, 0xD3F4, 0xE040, 0xE041, 0xDBA7, 0xDBA4, 0xE042, 0xDBA8, + 0xE043, 0xE044, 0xBDBC, 0xE045, 0xE046, 0xE047, 0xC0C9, 0xDBA3, 0xDBA6, + 0xD6A3, 0xE048, 0xDBA9, 0xE049, 0xE04A, 0xE04B, 0xDBAD, 0xE04C, 0xE04D, + 0xE04E, 0xDBAE, 0xDBAC, 0xBAC2, 0xE04F, 0xE050, 0xE051, 0xBFA4, 0xDBAB, + 0xE052, 0xE053, 0xE054, 0xDBAA, 0xD4C7, 0xB2BF, 0xE055, 0xE056, 0xDBAF, + 0xE057, 0xB9F9, 0xE058, 0xDBB0, 0xE059, 0xE05A, 0xE05B, 0xE05C, 0xB3BB, + 0xE05D, 0xE05E, 0xE05F, 0xB5A6, 0xE060, 0xE061, 0xE062, 0xE063, 0xB6BC, + 0xDBB1, 0xE064, 0xE065, 0xE066, 0xB6F5, 0xE067, 0xDBB2, 0xE068, 0xE069, + 0xE06A, 0xE06B, 0xE06C, 0xE06D, 0xE06E, 0xE06F, 0xE070, 0xE071, 0xE072, + 0xE073, 0xE074, 0xE075, 0xE076, 0xE077, 0xE078, 0xE079, 0xE07A, 0xE07B, + 0xB1C9, 0xE07C, 0xE07D, 0xE07E, 0xE080, 0xDBB4, 0xE081, 0xE082, 0xE083, + 0xDBB3, 0xDBB5, 0xE084, 0xE085, 0xE086, 0xE087, 0xE088, 0xE089, 0xE08A, + 0xE08B, 0xE08C, 0xE08D, 0xE08E, 0xDBB7, 0xE08F, 0xDBB6, 0xE090, 0xE091, + 0xE092, 0xE093, 0xE094, 0xE095, 0xE096, 0xDBB8, 0xE097, 0xE098, 0xE099, + 0xE09A, 0xE09B, 0xE09C, 0xE09D, 0xE09E, 0xE09F, 0xDBB9, 0xE0A0, 0xE140, + 0xDBBA, 0xE141, 0xE142, 0xD3CF, 0xF4FA, 0xC7F5, 0xD7C3, 0xC5E4, 0xF4FC, + 0xF4FD, 0xF4FB, 0xE143, 0xBEC6, 0xE144, 0xE145, 0xE146, 0xE147, 0xD0EF, + 0xE148, 0xE149, 0xB7D3, 0xE14A, 0xE14B, 0xD4CD, 0xCCAA, 0xE14C, 0xE14D, + 0xF5A2, 0xF5A1, 0xBAA8, 0xF4FE, 0xCBD6, 0xE14E, 0xE14F, 0xE150, 0xF5A4, + 0xC0D2, 0xE151, 0xB3EA, 0xE152, 0xCDAA, 0xF5A5, 0xF5A3, 0xBDB4, 0xF5A8, + 0xE153, 0xF5A9, 0xBDCD, 0xC3B8, 0xBFE1, 0xCBE1, 0xF5AA, 0xE154, 0xE155, + 0xE156, 0xF5A6, 0xF5A7, 0xC4F0, 0xE157, 0xE158, 0xE159, 0xE15A, 0xE15B, + 0xF5AC, 0xE15C, 0xB4BC, 0xE15D, 0xD7ED, 0xE15E, 0xB4D7, 0xF5AB, 0xF5AE, + 0xE15F, 0xE160, 0xF5AD, 0xF5AF, 0xD0D1, 0xE161, 0xE162, 0xE163, 0xE164, + 0xE165, 0xE166, 0xE167, 0xC3D1, 0xC8A9, 0xE168, 0xE169, 0xE16A, 0xE16B, + 0xE16C, 0xE16D, 0xF5B0, 0xF5B1, 0xE16E, 0xE16F, 0xE170, 0xE171, 0xE172, + 0xE173, 0xF5B2, 0xE174, 0xE175, 0xF5B3, 0xF5B4, 0xF5B5, 0xE176, 0xE177, + 0xE178, 0xE179, 0xF5B7, 0xF5B6, 0xE17A, 0xE17B, 0xE17C, 0xE17D, 0xF5B8, + 0xE17E, 0xE180, 0xE181, 0xE182, 0xE183, 0xE184, 0xE185, 0xE186, 0xE187, + 0xE188, 0xE189, 0xE18A, 0xB2C9, 0xE18B, 0xD3D4, 0xCACD, 0xE18C, 0xC0EF, + 0xD6D8, 0xD2B0, 0xC1BF, 0xE18D, 0xBDF0, 0xE18E, 0xE18F, 0xE190, 0xE191, + 0xE192, 0xE193, 0xE194, 0xE195, 0xE196, 0xE197, 0xB8AA, 0xE198, 0xE199, + 0xE19A, 0xE19B, 0xE19C, 0xE19D, 0xE19E, 0xE19F, 0xE1A0, 0xE240, 0xE241, + 0xE242, 0xE243, 0xE244, 0xE245, 0xE246, 0xE247, 0xE248, 0xE249, 0xE24A, + 0xE24B, 0xE24C, 0xE24D, 0xE24E, 0xE24F, 0xE250, 0xE251, 0xE252, 0xE253, + 0xE254, 0xE255, 0xE256, 0xE257, 0xE258, 0xE259, 0xE25A, 0xE25B, 0xE25C, + 0xE25D, 0xE25E, 0xE25F, 0xE260, 0xE261, 0xE262, 0xE263, 0xE264, 0xE265, + 0xE266, 0xE267, 0xE268, 0xE269, 0xE26A, 0xE26B, 0xE26C, 0xE26D, 0xE26E, + 0xE26F, 0xE270, 0xE271, 0xE272, 0xE273, 0xE274, 0xE275, 0xE276, 0xE277, + 0xE278, 0xE279, 0xE27A, 0xE27B, 0xE27C, 0xE27D, 0xE27E, 0xE280, 0xE281, + 0xE282, 0xE283, 0xE284, 0xE285, 0xE286, 0xE287, 0xE288, 0xE289, 0xE28A, + 0xE28B, 0xE28C, 0xE28D, 0xE28E, 0xE28F, 0xE290, 0xE291, 0xE292, 0xE293, + 0xE294, 0xE295, 0xE296, 0xE297, 0xE298, 0xE299, 0xE29A, 0xE29B, 0xE29C, + 0xE29D, 0xE29E, 0xE29F, 0xE2A0, 0xE340, 0xE341, 0xE342, 0xE343, 0xE344, + 0xE345, 0xE346, 0xE347, 0xE348, 0xE349, 0xE34A, 0xE34B, 0xE34C, 0xE34D, + 0xE34E, 0xE34F, 0xE350, 0xE351, 0xE352, 0xE353, 0xE354, 0xE355, 0xE356, + 0xE357, 0xE358, 0xE359, 0xE35A, 0xE35B, 0xE35C, 0xE35D, 0xE35E, 0xE35F, + 0xE360, 0xE361, 0xE362, 0xE363, 0xE364, 0xE365, 0xE366, 0xE367, 0xE368, + 0xE369, 0xE36A, 0xE36B, 0xE36C, 0xE36D, 0xBCF8, 0xE36E, 0xE36F, 0xE370, + 0xE371, 0xE372, 0xE373, 0xE374, 0xE375, 0xE376, 0xE377, 0xE378, 0xE379, + 0xE37A, 0xE37B, 0xE37C, 0xE37D, 0xE37E, 0xE380, 0xE381, 0xE382, 0xE383, + 0xE384, 0xE385, 0xE386, 0xE387, 0xF6C6, 0xE388, 0xE389, 0xE38A, 0xE38B, + 0xE38C, 0xE38D, 0xE38E, 0xE38F, 0xE390, 0xE391, 0xE392, 0xE393, 0xE394, + 0xE395, 0xE396, 0xE397, 0xE398, 0xE399, 0xE39A, 0xE39B, 0xE39C, 0xE39D, + 0xE39E, 0xE39F, 0xE3A0, 0xE440, 0xE441, 0xE442, 0xE443, 0xE444, 0xE445, + 0xF6C7, 0xE446, 0xE447, 0xE448, 0xE449, 0xE44A, 0xE44B, 0xE44C, 0xE44D, + 0xE44E, 0xE44F, 0xE450, 0xE451, 0xE452, 0xE453, 0xE454, 0xE455, 0xE456, + 0xE457, 0xE458, 0xE459, 0xE45A, 0xE45B, 0xE45C, 0xE45D, 0xE45E, 0xF6C8, + 0xE45F, 0xE460, 0xE461, 0xE462, 0xE463, 0xE464, 0xE465, 0xE466, 0xE467, + 0xE468, 0xE469, 0xE46A, 0xE46B, 0xE46C, 0xE46D, 0xE46E, 0xE46F, 0xE470, + 0xE471, 0xE472, 0xE473, 0xE474, 0xE475, 0xE476, 0xE477, 0xE478, 0xE479, + 0xE47A, 0xE47B, 0xE47C, 0xE47D, 0xE47E, 0xE480, 0xE481, 0xE482, 0xE483, + 0xE484, 0xE485, 0xE486, 0xE487, 0xE488, 0xE489, 0xE48A, 0xE48B, 0xE48C, + 0xE48D, 0xE48E, 0xE48F, 0xE490, 0xE491, 0xE492, 0xE493, 0xE494, 0xE495, + 0xE496, 0xE497, 0xE498, 0xE499, 0xE49A, 0xE49B, 0xE49C, 0xE49D, 0xE49E, + 0xE49F, 0xE4A0, 0xE540, 0xE541, 0xE542, 0xE543, 0xE544, 0xE545, 0xE546, + 0xE547, 0xE548, 0xE549, 0xE54A, 0xE54B, 0xE54C, 0xE54D, 0xE54E, 0xE54F, + 0xE550, 0xE551, 0xE552, 0xE553, 0xE554, 0xE555, 0xE556, 0xE557, 0xE558, + 0xE559, 0xE55A, 0xE55B, 0xE55C, 0xE55D, 0xE55E, 0xE55F, 0xE560, 0xE561, + 0xE562, 0xE563, 0xE564, 0xE565, 0xE566, 0xE567, 0xE568, 0xE569, 0xE56A, + 0xE56B, 0xE56C, 0xE56D, 0xE56E, 0xE56F, 0xE570, 0xE571, 0xE572, 0xE573, + 0xF6C9, 0xE574, 0xE575, 0xE576, 0xE577, 0xE578, 0xE579, 0xE57A, 0xE57B, + 0xE57C, 0xE57D, 0xE57E, 0xE580, 0xE581, 0xE582, 0xE583, 0xE584, 0xE585, + 0xE586, 0xE587, 0xE588, 0xE589, 0xE58A, 0xE58B, 0xE58C, 0xE58D, 0xE58E, + 0xE58F, 0xE590, 0xE591, 0xE592, 0xE593, 0xE594, 0xE595, 0xE596, 0xE597, + 0xE598, 0xE599, 0xE59A, 0xE59B, 0xE59C, 0xE59D, 0xE59E, 0xE59F, 0xF6CA, + 0xE5A0, 0xE640, 0xE641, 0xE642, 0xE643, 0xE644, 0xE645, 0xE646, 0xE647, + 0xE648, 0xE649, 0xE64A, 0xE64B, 0xE64C, 0xE64D, 0xE64E, 0xE64F, 0xE650, + 0xE651, 0xE652, 0xE653, 0xE654, 0xE655, 0xE656, 0xE657, 0xE658, 0xE659, + 0xE65A, 0xE65B, 0xE65C, 0xE65D, 0xE65E, 0xE65F, 0xE660, 0xE661, 0xE662, + 0xF6CC, 0xE663, 0xE664, 0xE665, 0xE666, 0xE667, 0xE668, 0xE669, 0xE66A, + 0xE66B, 0xE66C, 0xE66D, 0xE66E, 0xE66F, 0xE670, 0xE671, 0xE672, 0xE673, + 0xE674, 0xE675, 0xE676, 0xE677, 0xE678, 0xE679, 0xE67A, 0xE67B, 0xE67C, + 0xE67D, 0xE67E, 0xE680, 0xE681, 0xE682, 0xE683, 0xE684, 0xE685, 0xE686, + 0xE687, 0xE688, 0xE689, 0xE68A, 0xE68B, 0xE68C, 0xE68D, 0xE68E, 0xE68F, + 0xE690, 0xE691, 0xE692, 0xE693, 0xE694, 0xE695, 0xE696, 0xE697, 0xE698, + 0xE699, 0xE69A, 0xE69B, 0xE69C, 0xE69D, 0xF6CB, 0xE69E, 0xE69F, 0xE6A0, + 0xE740, 0xE741, 0xE742, 0xE743, 0xE744, 0xE745, 0xE746, 0xE747, 0xF7E9, + 0xE748, 0xE749, 0xE74A, 0xE74B, 0xE74C, 0xE74D, 0xE74E, 0xE74F, 0xE750, + 0xE751, 0xE752, 0xE753, 0xE754, 0xE755, 0xE756, 0xE757, 0xE758, 0xE759, + 0xE75A, 0xE75B, 0xE75C, 0xE75D, 0xE75E, 0xE75F, 0xE760, 0xE761, 0xE762, + 0xE763, 0xE764, 0xE765, 0xE766, 0xE767, 0xE768, 0xE769, 0xE76A, 0xE76B, + 0xE76C, 0xE76D, 0xE76E, 0xE76F, 0xE770, 0xE771, 0xE772, 0xE773, 0xE774, + 0xE775, 0xE776, 0xE777, 0xE778, 0xE779, 0xE77A, 0xE77B, 0xE77C, 0xE77D, + 0xE77E, 0xE780, 0xE781, 0xE782, 0xE783, 0xE784, 0xE785, 0xE786, 0xE787, + 0xE788, 0xE789, 0xE78A, 0xE78B, 0xE78C, 0xE78D, 0xE78E, 0xE78F, 0xE790, + 0xE791, 0xE792, 0xE793, 0xE794, 0xE795, 0xE796, 0xE797, 0xE798, 0xE799, + 0xE79A, 0xE79B, 0xE79C, 0xE79D, 0xE79E, 0xE79F, 0xE7A0, 0xE840, 0xE841, + 0xE842, 0xE843, 0xE844, 0xE845, 0xE846, 0xE847, 0xE848, 0xE849, 0xE84A, + 0xE84B, 0xE84C, 0xE84D, 0xE84E, 0xF6CD, 0xE84F, 0xE850, 0xE851, 0xE852, + 0xE853, 0xE854, 0xE855, 0xE856, 0xE857, 0xE858, 0xE859, 0xE85A, 0xE85B, + 0xE85C, 0xE85D, 0xE85E, 0xE85F, 0xE860, 0xE861, 0xE862, 0xE863, 0xE864, + 0xE865, 0xE866, 0xE867, 0xE868, 0xE869, 0xE86A, 0xE86B, 0xE86C, 0xE86D, + 0xE86E, 0xE86F, 0xE870, 0xE871, 0xE872, 0xE873, 0xE874, 0xE875, 0xE876, + 0xE877, 0xE878, 0xE879, 0xE87A, 0xF6CE, 0xE87B, 0xE87C, 0xE87D, 0xE87E, + 0xE880, 0xE881, 0xE882, 0xE883, 0xE884, 0xE885, 0xE886, 0xE887, 0xE888, + 0xE889, 0xE88A, 0xE88B, 0xE88C, 0xE88D, 0xE88E, 0xE88F, 0xE890, 0xE891, + 0xE892, 0xE893, 0xE894, 0xEEC4, 0xEEC5, 0xEEC6, 0xD5EB, 0xB6A4, 0xEEC8, + 0xEEC7, 0xEEC9, 0xEECA, 0xC7A5, 0xEECB, 0xEECC, 0xE895, 0xB7B0, 0xB5F6, + 0xEECD, 0xEECF, 0xE896, 0xEECE, 0xE897, 0xB8C6, 0xEED0, 0xEED1, 0xEED2, + 0xB6DB, 0xB3AE, 0xD6D3, 0xC4C6, 0xB1B5, 0xB8D6, 0xEED3, 0xEED4, 0xD4BF, + 0xC7D5, 0xBEFB, 0xCED9, 0xB9B3, 0xEED6, 0xEED5, 0xEED8, 0xEED7, 0xC5A5, + 0xEED9, 0xEEDA, 0xC7AE, 0xEEDB, 0xC7AF, 0xEEDC, 0xB2A7, 0xEEDD, 0xEEDE, + 0xEEDF, 0xEEE0, 0xEEE1, 0xD7EA, 0xEEE2, 0xEEE3, 0xBCD8, 0xEEE4, 0xD3CB, + 0xCCFA, 0xB2AC, 0xC1E5, 0xEEE5, 0xC7A6, 0xC3AD, 0xE898, 0xEEE6, 0xEEE7, + 0xEEE8, 0xEEE9, 0xEEEA, 0xEEEB, 0xEEEC, 0xE899, 0xEEED, 0xEEEE, 0xEEEF, + 0xE89A, 0xE89B, 0xEEF0, 0xEEF1, 0xEEF2, 0xEEF4, 0xEEF3, 0xE89C, 0xEEF5, + 0xCDAD, 0xC2C1, 0xEEF6, 0xEEF7, 0xEEF8, 0xD5A1, 0xEEF9, 0xCFB3, 0xEEFA, + 0xEEFB, 0xE89D, 0xEEFC, 0xEEFD, 0xEFA1, 0xEEFE, 0xEFA2, 0xB8F5, 0xC3FA, + 0xEFA3, 0xEFA4, 0xBDC2, 0xD2BF, 0xB2F9, 0xEFA5, 0xEFA6, 0xEFA7, 0xD2F8, + 0xEFA8, 0xD6FD, 0xEFA9, 0xC6CC, 0xE89E, 0xEFAA, 0xEFAB, 0xC1B4, 0xEFAC, + 0xCFFA, 0xCBF8, 0xEFAE, 0xEFAD, 0xB3FA, 0xB9F8, 0xEFAF, 0xEFB0, 0xD0E2, + 0xEFB1, 0xEFB2, 0xB7E6, 0xD0BF, 0xEFB3, 0xEFB4, 0xEFB5, 0xC8F1, 0xCCE0, + 0xEFB6, 0xEFB7, 0xEFB8, 0xEFB9, 0xEFBA, 0xD5E0, 0xEFBB, 0xB4ED, 0xC3AA, + 0xEFBC, 0xE89F, 0xEFBD, 0xEFBE, 0xEFBF, 0xE8A0, 0xCEFD, 0xEFC0, 0xC2E0, + 0xB4B8, 0xD7B6, 0xBDF5, 0xE940, 0xCFC7, 0xEFC3, 0xEFC1, 0xEFC2, 0xEFC4, + 0xB6A7, 0xBCFC, 0xBEE2, 0xC3CC, 0xEFC5, 0xEFC6, 0xE941, 0xEFC7, 0xEFCF, + 0xEFC8, 0xEFC9, 0xEFCA, 0xC7C2, 0xEFF1, 0xB6CD, 0xEFCB, 0xE942, 0xEFCC, + 0xEFCD, 0xB6C6, 0xC3BE, 0xEFCE, 0xE943, 0xEFD0, 0xEFD1, 0xEFD2, 0xD5F2, + 0xE944, 0xEFD3, 0xC4F7, 0xE945, 0xEFD4, 0xC4F8, 0xEFD5, 0xEFD6, 0xB8E4, + 0xB0F7, 0xEFD7, 0xEFD8, 0xEFD9, 0xE946, 0xEFDA, 0xEFDB, 0xEFDC, 0xEFDD, + 0xE947, 0xEFDE, 0xBEB5, 0xEFE1, 0xEFDF, 0xEFE0, 0xE948, 0xEFE2, 0xEFE3, + 0xC1CD, 0xEFE4, 0xEFE5, 0xEFE6, 0xEFE7, 0xEFE8, 0xEFE9, 0xEFEA, 0xEFEB, + 0xEFEC, 0xC0D8, 0xE949, 0xEFED, 0xC1AD, 0xEFEE, 0xEFEF, 0xEFF0, 0xE94A, + 0xE94B, 0xCFE2, 0xE94C, 0xE94D, 0xE94E, 0xE94F, 0xE950, 0xE951, 0xE952, + 0xE953, 0xB3A4, 0xE954, 0xE955, 0xE956, 0xE957, 0xE958, 0xE959, 0xE95A, + 0xE95B, 0xE95C, 0xE95D, 0xE95E, 0xE95F, 0xE960, 0xE961, 0xE962, 0xE963, + 0xE964, 0xE965, 0xE966, 0xE967, 0xE968, 0xE969, 0xE96A, 0xE96B, 0xE96C, + 0xE96D, 0xE96E, 0xE96F, 0xE970, 0xE971, 0xE972, 0xE973, 0xE974, 0xE975, + 0xE976, 0xE977, 0xE978, 0xE979, 0xE97A, 0xE97B, 0xE97C, 0xE97D, 0xE97E, + 0xE980, 0xE981, 0xE982, 0xE983, 0xE984, 0xE985, 0xE986, 0xE987, 0xE988, + 0xE989, 0xE98A, 0xE98B, 0xE98C, 0xE98D, 0xE98E, 0xE98F, 0xE990, 0xE991, + 0xE992, 0xE993, 0xE994, 0xE995, 0xE996, 0xE997, 0xE998, 0xE999, 0xE99A, + 0xE99B, 0xE99C, 0xE99D, 0xE99E, 0xE99F, 0xE9A0, 0xEA40, 0xEA41, 0xEA42, + 0xEA43, 0xEA44, 0xEA45, 0xEA46, 0xEA47, 0xEA48, 0xEA49, 0xEA4A, 0xEA4B, + 0xEA4C, 0xEA4D, 0xEA4E, 0xEA4F, 0xEA50, 0xEA51, 0xEA52, 0xEA53, 0xEA54, + 0xEA55, 0xEA56, 0xEA57, 0xEA58, 0xEA59, 0xEA5A, 0xEA5B, 0xC3C5, 0xE3C5, + 0xC9C1, 0xE3C6, 0xEA5C, 0xB1D5, 0xCECA, 0xB4B3, 0xC8F2, 0xE3C7, 0xCFD0, + 0xE3C8, 0xBCE4, 0xE3C9, 0xE3CA, 0xC3C6, 0xD5A2, 0xC4D6, 0xB9EB, 0xCEC5, + 0xE3CB, 0xC3F6, 0xE3CC, 0xEA5D, 0xB7A7, 0xB8F3, 0xBAD2, 0xE3CD, 0xE3CE, + 0xD4C4, 0xE3CF, 0xEA5E, 0xE3D0, 0xD1CB, 0xE3D1, 0xE3D2, 0xE3D3, 0xE3D4, + 0xD1D6, 0xE3D5, 0xB2FB, 0xC0BB, 0xE3D6, 0xEA5F, 0xC0AB, 0xE3D7, 0xE3D8, + 0xE3D9, 0xEA60, 0xE3DA, 0xE3DB, 0xEA61, 0xB8B7, 0xDAE2, 0xEA62, 0xB6D3, + 0xEA63, 0xDAE4, 0xDAE3, 0xEA64, 0xEA65, 0xEA66, 0xEA67, 0xEA68, 0xEA69, + 0xEA6A, 0xDAE6, 0xEA6B, 0xEA6C, 0xEA6D, 0xC8EE, 0xEA6E, 0xEA6F, 0xDAE5, + 0xB7C0, 0xD1F4, 0xD2F5, 0xD5F3, 0xBDD7, 0xEA70, 0xEA71, 0xEA72, 0xEA73, + 0xD7E8, 0xDAE8, 0xDAE7, 0xEA74, 0xB0A2, 0xCDD3, 0xEA75, 0xDAE9, 0xEA76, + 0xB8BD, 0xBCCA, 0xC2BD, 0xC2A4, 0xB3C2, 0xDAEA, 0xEA77, 0xC2AA, 0xC4B0, + 0xBDB5, 0xEA78, 0xEA79, 0xCFDE, 0xEA7A, 0xEA7B, 0xEA7C, 0xDAEB, 0xC9C2, + 0xEA7D, 0xEA7E, 0xEA80, 0xEA81, 0xEA82, 0xB1DD, 0xEA83, 0xEA84, 0xEA85, + 0xDAEC, 0xEA86, 0xB6B8, 0xD4BA, 0xEA87, 0xB3FD, 0xEA88, 0xEA89, 0xDAED, + 0xD4C9, 0xCFD5, 0xC5E3, 0xEA8A, 0xDAEE, 0xEA8B, 0xEA8C, 0xEA8D, 0xEA8E, + 0xEA8F, 0xDAEF, 0xEA90, 0xDAF0, 0xC1EA, 0xCCD5, 0xCFDD, 0xEA91, 0xEA92, + 0xEA93, 0xEA94, 0xEA95, 0xEA96, 0xEA97, 0xEA98, 0xEA99, 0xEA9A, 0xEA9B, + 0xEA9C, 0xEA9D, 0xD3E7, 0xC2A1, 0xEA9E, 0xDAF1, 0xEA9F, 0xEAA0, 0xCBE5, + 0xEB40, 0xDAF2, 0xEB41, 0xCBE6, 0xD2FE, 0xEB42, 0xEB43, 0xEB44, 0xB8F4, + 0xEB45, 0xEB46, 0xDAF3, 0xB0AF, 0xCFB6, 0xEB47, 0xEB48, 0xD5CF, 0xEB49, + 0xEB4A, 0xEB4B, 0xEB4C, 0xEB4D, 0xEB4E, 0xEB4F, 0xEB50, 0xEB51, 0xEB52, + 0xCBED, 0xEB53, 0xEB54, 0xEB55, 0xEB56, 0xEB57, 0xEB58, 0xEB59, 0xEB5A, + 0xDAF4, 0xEB5B, 0xEB5C, 0xE3C4, 0xEB5D, 0xEB5E, 0xC1A5, 0xEB5F, 0xEB60, + 0xF6BF, 0xEB61, 0xEB62, 0xF6C0, 0xF6C1, 0xC4D1, 0xEB63, 0xC8B8, 0xD1E3, + 0xEB64, 0xEB65, 0xD0DB, 0xD1C5, 0xBCAF, 0xB9CD, 0xEB66, 0xEFF4, 0xEB67, + 0xEB68, 0xB4C6, 0xD3BA, 0xF6C2, 0xB3FB, 0xEB69, 0xEB6A, 0xF6C3, 0xEB6B, + 0xEB6C, 0xB5F1, 0xEB6D, 0xEB6E, 0xEB6F, 0xEB70, 0xEB71, 0xEB72, 0xEB73, + 0xEB74, 0xEB75, 0xEB76, 0xF6C5, 0xEB77, 0xEB78, 0xEB79, 0xEB7A, 0xEB7B, + 0xEB7C, 0xEB7D, 0xD3EA, 0xF6A7, 0xD1A9, 0xEB7E, 0xEB80, 0xEB81, 0xEB82, + 0xF6A9, 0xEB83, 0xEB84, 0xEB85, 0xF6A8, 0xEB86, 0xEB87, 0xC1E3, 0xC0D7, + 0xEB88, 0xB1A2, 0xEB89, 0xEB8A, 0xEB8B, 0xEB8C, 0xCEED, 0xEB8D, 0xD0E8, + 0xF6AB, 0xEB8E, 0xEB8F, 0xCFF6, 0xEB90, 0xF6AA, 0xD5F0, 0xF6AC, 0xC3B9, + 0xEB91, 0xEB92, 0xEB93, 0xBBF4, 0xF6AE, 0xF6AD, 0xEB94, 0xEB95, 0xEB96, + 0xC4DE, 0xEB97, 0xEB98, 0xC1D8, 0xEB99, 0xEB9A, 0xEB9B, 0xEB9C, 0xEB9D, + 0xCBAA, 0xEB9E, 0xCFBC, 0xEB9F, 0xEBA0, 0xEC40, 0xEC41, 0xEC42, 0xEC43, + 0xEC44, 0xEC45, 0xEC46, 0xEC47, 0xEC48, 0xF6AF, 0xEC49, 0xEC4A, 0xF6B0, + 0xEC4B, 0xEC4C, 0xF6B1, 0xEC4D, 0xC2B6, 0xEC4E, 0xEC4F, 0xEC50, 0xEC51, + 0xEC52, 0xB0D4, 0xC5F9, 0xEC53, 0xEC54, 0xEC55, 0xEC56, 0xF6B2, 0xEC57, + 0xEC58, 0xEC59, 0xEC5A, 0xEC5B, 0xEC5C, 0xEC5D, 0xEC5E, 0xEC5F, 0xEC60, + 0xEC61, 0xEC62, 0xEC63, 0xEC64, 0xEC65, 0xEC66, 0xEC67, 0xEC68, 0xEC69, + 0xC7E0, 0xF6A6, 0xEC6A, 0xEC6B, 0xBEB8, 0xEC6C, 0xEC6D, 0xBEB2, 0xEC6E, + 0xB5E5, 0xEC6F, 0xEC70, 0xB7C7, 0xEC71, 0xBFBF, 0xC3D2, 0xC3E6, 0xEC72, + 0xEC73, 0xD8CC, 0xEC74, 0xEC75, 0xEC76, 0xB8EF, 0xEC77, 0xEC78, 0xEC79, + 0xEC7A, 0xEC7B, 0xEC7C, 0xEC7D, 0xEC7E, 0xEC80, 0xBDF9, 0xD1A5, 0xEC81, + 0xB0D0, 0xEC82, 0xEC83, 0xEC84, 0xEC85, 0xEC86, 0xF7B0, 0xEC87, 0xEC88, + 0xEC89, 0xEC8A, 0xEC8B, 0xEC8C, 0xEC8D, 0xEC8E, 0xF7B1, 0xEC8F, 0xEC90, + 0xEC91, 0xEC92, 0xEC93, 0xD0AC, 0xEC94, 0xB0B0, 0xEC95, 0xEC96, 0xEC97, + 0xF7B2, 0xF7B3, 0xEC98, 0xF7B4, 0xEC99, 0xEC9A, 0xEC9B, 0xC7CA, 0xEC9C, + 0xEC9D, 0xEC9E, 0xEC9F, 0xECA0, 0xED40, 0xED41, 0xBECF, 0xED42, 0xED43, + 0xF7B7, 0xED44, 0xED45, 0xED46, 0xED47, 0xED48, 0xED49, 0xED4A, 0xF7B6, + 0xED4B, 0xB1DE, 0xED4C, 0xF7B5, 0xED4D, 0xED4E, 0xF7B8, 0xED4F, 0xF7B9, + 0xED50, 0xED51, 0xED52, 0xED53, 0xED54, 0xED55, 0xED56, 0xED57, 0xED58, + 0xED59, 0xED5A, 0xED5B, 0xED5C, 0xED5D, 0xED5E, 0xED5F, 0xED60, 0xED61, + 0xED62, 0xED63, 0xED64, 0xED65, 0xED66, 0xED67, 0xED68, 0xED69, 0xED6A, + 0xED6B, 0xED6C, 0xED6D, 0xED6E, 0xED6F, 0xED70, 0xED71, 0xED72, 0xED73, + 0xED74, 0xED75, 0xED76, 0xED77, 0xED78, 0xED79, 0xED7A, 0xED7B, 0xED7C, + 0xED7D, 0xED7E, 0xED80, 0xED81, 0xCEA4, 0xC8CD, 0xED82, 0xBAAB, 0xE8B8, + 0xE8B9, 0xE8BA, 0xBEC2, 0xED83, 0xED84, 0xED85, 0xED86, 0xED87, 0xD2F4, + 0xED88, 0xD4CF, 0xC9D8, 0xED89, 0xED8A, 0xED8B, 0xED8C, 0xED8D, 0xED8E, + 0xED8F, 0xED90, 0xED91, 0xED92, 0xED93, 0xED94, 0xED95, 0xED96, 0xED97, + 0xED98, 0xED99, 0xED9A, 0xED9B, 0xED9C, 0xED9D, 0xED9E, 0xED9F, 0xEDA0, + 0xEE40, 0xEE41, 0xEE42, 0xEE43, 0xEE44, 0xEE45, 0xEE46, 0xEE47, 0xEE48, + 0xEE49, 0xEE4A, 0xEE4B, 0xEE4C, 0xEE4D, 0xEE4E, 0xEE4F, 0xEE50, 0xEE51, + 0xEE52, 0xEE53, 0xEE54, 0xEE55, 0xEE56, 0xEE57, 0xEE58, 0xEE59, 0xEE5A, + 0xEE5B, 0xEE5C, 0xEE5D, 0xEE5E, 0xEE5F, 0xEE60, 0xEE61, 0xEE62, 0xEE63, + 0xEE64, 0xEE65, 0xEE66, 0xEE67, 0xEE68, 0xEE69, 0xEE6A, 0xEE6B, 0xEE6C, + 0xEE6D, 0xEE6E, 0xEE6F, 0xEE70, 0xEE71, 0xEE72, 0xEE73, 0xEE74, 0xEE75, + 0xEE76, 0xEE77, 0xEE78, 0xEE79, 0xEE7A, 0xEE7B, 0xEE7C, 0xEE7D, 0xEE7E, + 0xEE80, 0xEE81, 0xEE82, 0xEE83, 0xEE84, 0xEE85, 0xEE86, 0xEE87, 0xEE88, + 0xEE89, 0xEE8A, 0xEE8B, 0xEE8C, 0xEE8D, 0xEE8E, 0xEE8F, 0xEE90, 0xEE91, + 0xEE92, 0xEE93, 0xEE94, 0xEE95, 0xEE96, 0xEE97, 0xEE98, 0xEE99, 0xEE9A, + 0xEE9B, 0xEE9C, 0xEE9D, 0xEE9E, 0xEE9F, 0xEEA0, 0xEF40, 0xEF41, 0xEF42, + 0xEF43, 0xEF44, 0xEF45, 0xD2B3, 0xB6A5, 0xC7EA, 0xF1FC, 0xCFEE, 0xCBB3, + 0xD0EB, 0xE7EF, 0xCDE7, 0xB9CB, 0xB6D9, 0xF1FD, 0xB0E4, 0xCBCC, 0xF1FE, + 0xD4A4, 0xC2AD, 0xC1EC, 0xC6C4, 0xBEB1, 0xF2A1, 0xBCD5, 0xEF46, 0xF2A2, + 0xF2A3, 0xEF47, 0xF2A4, 0xD2C3, 0xC6B5, 0xEF48, 0xCDC7, 0xF2A5, 0xEF49, + 0xD3B1, 0xBFC5, 0xCCE2, 0xEF4A, 0xF2A6, 0xF2A7, 0xD1D5, 0xB6EE, 0xF2A8, + 0xF2A9, 0xB5DF, 0xF2AA, 0xF2AB, 0xEF4B, 0xB2FC, 0xF2AC, 0xF2AD, 0xC8A7, + 0xEF4C, 0xEF4D, 0xEF4E, 0xEF4F, 0xEF50, 0xEF51, 0xEF52, 0xEF53, 0xEF54, + 0xEF55, 0xEF56, 0xEF57, 0xEF58, 0xEF59, 0xEF5A, 0xEF5B, 0xEF5C, 0xEF5D, + 0xEF5E, 0xEF5F, 0xEF60, 0xEF61, 0xEF62, 0xEF63, 0xEF64, 0xEF65, 0xEF66, + 0xEF67, 0xEF68, 0xEF69, 0xEF6A, 0xEF6B, 0xEF6C, 0xEF6D, 0xEF6E, 0xEF6F, + 0xEF70, 0xEF71, 0xB7E7, 0xEF72, 0xEF73, 0xECA9, 0xECAA, 0xECAB, 0xEF74, + 0xECAC, 0xEF75, 0xEF76, 0xC6AE, 0xECAD, 0xECAE, 0xEF77, 0xEF78, 0xEF79, + 0xB7C9, 0xCAB3, 0xEF7A, 0xEF7B, 0xEF7C, 0xEF7D, 0xEF7E, 0xEF80, 0xEF81, + 0xE2B8, 0xF7CF, 0xEF82, 0xEF83, 0xEF84, 0xEF85, 0xEF86, 0xEF87, 0xEF88, + 0xEF89, 0xEF8A, 0xEF8B, 0xEF8C, 0xEF8D, 0xEF8E, 0xEF8F, 0xEF90, 0xEF91, + 0xEF92, 0xEF93, 0xEF94, 0xEF95, 0xEF96, 0xEF97, 0xEF98, 0xEF99, 0xEF9A, + 0xEF9B, 0xEF9C, 0xEF9D, 0xEF9E, 0xEF9F, 0xEFA0, 0xF040, 0xF041, 0xF042, + 0xF043, 0xF044, 0xF7D0, 0xF045, 0xF046, 0xB2CD, 0xF047, 0xF048, 0xF049, + 0xF04A, 0xF04B, 0xF04C, 0xF04D, 0xF04E, 0xF04F, 0xF050, 0xF051, 0xF052, + 0xF053, 0xF054, 0xF055, 0xF056, 0xF057, 0xF058, 0xF059, 0xF05A, 0xF05B, + 0xF05C, 0xF05D, 0xF05E, 0xF05F, 0xF060, 0xF061, 0xF062, 0xF063, 0xF7D1, + 0xF064, 0xF065, 0xF066, 0xF067, 0xF068, 0xF069, 0xF06A, 0xF06B, 0xF06C, + 0xF06D, 0xF06E, 0xF06F, 0xF070, 0xF071, 0xF072, 0xF073, 0xF074, 0xF075, + 0xF076, 0xF077, 0xF078, 0xF079, 0xF07A, 0xF07B, 0xF07C, 0xF07D, 0xF07E, + 0xF080, 0xF081, 0xF082, 0xF083, 0xF084, 0xF085, 0xF086, 0xF087, 0xF088, + 0xF089, 0xF7D3, 0xF7D2, 0xF08A, 0xF08B, 0xF08C, 0xF08D, 0xF08E, 0xF08F, + 0xF090, 0xF091, 0xF092, 0xF093, 0xF094, 0xF095, 0xF096, 0xE2BB, 0xF097, + 0xBCA2, 0xF098, 0xE2BC, 0xE2BD, 0xE2BE, 0xE2BF, 0xE2C0, 0xE2C1, 0xB7B9, + 0xD2FB, 0xBDA4, 0xCACE, 0xB1A5, 0xCBC7, 0xF099, 0xE2C2, 0xB6FC, 0xC8C4, + 0xE2C3, 0xF09A, 0xF09B, 0xBDC8, 0xF09C, 0xB1FD, 0xE2C4, 0xF09D, 0xB6F6, + 0xE2C5, 0xC4D9, 0xF09E, 0xF09F, 0xE2C6, 0xCFDA, 0xB9DD, 0xE2C7, 0xC0A1, + 0xF0A0, 0xE2C8, 0xB2F6, 0xF140, 0xE2C9, 0xF141, 0xC1F3, 0xE2CA, 0xE2CB, + 0xC2F8, 0xE2CC, 0xE2CD, 0xE2CE, 0xCAD7, 0xD8B8, 0xD9E5, 0xCFE3, 0xF142, + 0xF143, 0xF144, 0xF145, 0xF146, 0xF147, 0xF148, 0xF149, 0xF14A, 0xF14B, + 0xF14C, 0xF0A5, 0xF14D, 0xF14E, 0xDCB0, 0xF14F, 0xF150, 0xF151, 0xF152, + 0xF153, 0xF154, 0xF155, 0xF156, 0xF157, 0xF158, 0xF159, 0xF15A, 0xF15B, + 0xF15C, 0xF15D, 0xF15E, 0xF15F, 0xF160, 0xF161, 0xF162, 0xF163, 0xF164, + 0xF165, 0xF166, 0xF167, 0xF168, 0xF169, 0xF16A, 0xF16B, 0xF16C, 0xF16D, + 0xF16E, 0xF16F, 0xF170, 0xF171, 0xF172, 0xF173, 0xF174, 0xF175, 0xF176, + 0xF177, 0xF178, 0xF179, 0xF17A, 0xF17B, 0xF17C, 0xF17D, 0xF17E, 0xF180, + 0xF181, 0xF182, 0xF183, 0xF184, 0xF185, 0xF186, 0xF187, 0xF188, 0xF189, + 0xF18A, 0xF18B, 0xF18C, 0xF18D, 0xF18E, 0xF18F, 0xF190, 0xF191, 0xF192, + 0xF193, 0xF194, 0xF195, 0xF196, 0xF197, 0xF198, 0xF199, 0xF19A, 0xF19B, + 0xF19C, 0xF19D, 0xF19E, 0xF19F, 0xF1A0, 0xF240, 0xF241, 0xF242, 0xF243, + 0xF244, 0xF245, 0xF246, 0xF247, 0xF248, 0xF249, 0xF24A, 0xF24B, 0xF24C, + 0xF24D, 0xF24E, 0xF24F, 0xF250, 0xF251, 0xF252, 0xF253, 0xF254, 0xF255, + 0xF256, 0xF257, 0xF258, 0xF259, 0xF25A, 0xF25B, 0xF25C, 0xF25D, 0xF25E, + 0xF25F, 0xF260, 0xF261, 0xF262, 0xF263, 0xF264, 0xF265, 0xF266, 0xF267, + 0xF268, 0xF269, 0xF26A, 0xF26B, 0xF26C, 0xF26D, 0xF26E, 0xF26F, 0xF270, + 0xF271, 0xF272, 0xF273, 0xF274, 0xF275, 0xF276, 0xF277, 0xF278, 0xF279, + 0xF27A, 0xF27B, 0xF27C, 0xF27D, 0xF27E, 0xF280, 0xF281, 0xF282, 0xF283, + 0xF284, 0xF285, 0xF286, 0xF287, 0xF288, 0xF289, 0xF28A, 0xF28B, 0xF28C, + 0xF28D, 0xF28E, 0xF28F, 0xF290, 0xF291, 0xF292, 0xF293, 0xF294, 0xF295, + 0xF296, 0xF297, 0xF298, 0xF299, 0xF29A, 0xF29B, 0xF29C, 0xF29D, 0xF29E, + 0xF29F, 0xF2A0, 0xF340, 0xF341, 0xF342, 0xF343, 0xF344, 0xF345, 0xF346, + 0xF347, 0xF348, 0xF349, 0xF34A, 0xF34B, 0xF34C, 0xF34D, 0xF34E, 0xF34F, + 0xF350, 0xF351, 0xC2ED, 0xD4A6, 0xCDD4, 0xD1B1, 0xB3DB, 0xC7FD, 0xF352, + 0xB2B5, 0xC2BF, 0xE6E0, 0xCABB, 0xE6E1, 0xE6E2, 0xBED4, 0xE6E3, 0xD7A4, + 0xCDD5, 0xE6E5, 0xBCDD, 0xE6E4, 0xE6E6, 0xE6E7, 0xC2EE, 0xF353, 0xBDBE, + 0xE6E8, 0xC2E6, 0xBAA7, 0xE6E9, 0xF354, 0xE6EA, 0xB3D2, 0xD1E9, 0xF355, + 0xF356, 0xBFA5, 0xE6EB, 0xC6EF, 0xE6EC, 0xE6ED, 0xF357, 0xF358, 0xE6EE, + 0xC6AD, 0xE6EF, 0xF359, 0xC9A7, 0xE6F0, 0xE6F1, 0xE6F2, 0xE5B9, 0xE6F3, + 0xE6F4, 0xC2E2, 0xE6F5, 0xE6F6, 0xD6E8, 0xE6F7, 0xF35A, 0xE6F8, 0xB9C7, + 0xF35B, 0xF35C, 0xF35D, 0xF35E, 0xF35F, 0xF360, 0xF361, 0xF7BB, 0xF7BA, + 0xF362, 0xF363, 0xF364, 0xF365, 0xF7BE, 0xF7BC, 0xBAA1, 0xF366, 0xF7BF, + 0xF367, 0xF7C0, 0xF368, 0xF369, 0xF36A, 0xF7C2, 0xF7C1, 0xF7C4, 0xF36B, + 0xF36C, 0xF7C3, 0xF36D, 0xF36E, 0xF36F, 0xF370, 0xF371, 0xF7C5, 0xF7C6, + 0xF372, 0xF373, 0xF374, 0xF375, 0xF7C7, 0xF376, 0xCBE8, 0xF377, 0xF378, + 0xF379, 0xF37A, 0xB8DF, 0xF37B, 0xF37C, 0xF37D, 0xF37E, 0xF380, 0xF381, + 0xF7D4, 0xF382, 0xF7D5, 0xF383, 0xF384, 0xF385, 0xF386, 0xF7D6, 0xF387, + 0xF388, 0xF389, 0xF38A, 0xF7D8, 0xF38B, 0xF7DA, 0xF38C, 0xF7D7, 0xF38D, + 0xF38E, 0xF38F, 0xF390, 0xF391, 0xF392, 0xF393, 0xF394, 0xF395, 0xF7DB, + 0xF396, 0xF7D9, 0xF397, 0xF398, 0xF399, 0xF39A, 0xF39B, 0xF39C, 0xF39D, + 0xD7D7, 0xF39E, 0xF39F, 0xF3A0, 0xF440, 0xF7DC, 0xF441, 0xF442, 0xF443, + 0xF444, 0xF445, 0xF446, 0xF7DD, 0xF447, 0xF448, 0xF449, 0xF7DE, 0xF44A, + 0xF44B, 0xF44C, 0xF44D, 0xF44E, 0xF44F, 0xF450, 0xF451, 0xF452, 0xF453, + 0xF454, 0xF7DF, 0xF455, 0xF456, 0xF457, 0xF7E0, 0xF458, 0xF459, 0xF45A, + 0xF45B, 0xF45C, 0xF45D, 0xF45E, 0xF45F, 0xF460, 0xF461, 0xF462, 0xDBCB, + 0xF463, 0xF464, 0xD8AA, 0xF465, 0xF466, 0xF467, 0xF468, 0xF469, 0xF46A, + 0xF46B, 0xF46C, 0xE5F7, 0xB9ED, 0xF46D, 0xF46E, 0xF46F, 0xF470, 0xBFFD, + 0xBBEA, 0xF7C9, 0xC6C7, 0xF7C8, 0xF471, 0xF7CA, 0xF7CC, 0xF7CB, 0xF472, + 0xF473, 0xF474, 0xF7CD, 0xF475, 0xCEBA, 0xF476, 0xF7CE, 0xF477, 0xF478, + 0xC4A7, 0xF479, 0xF47A, 0xF47B, 0xF47C, 0xF47D, 0xF47E, 0xF480, 0xF481, + 0xF482, 0xF483, 0xF484, 0xF485, 0xF486, 0xF487, 0xF488, 0xF489, 0xF48A, + 0xF48B, 0xF48C, 0xF48D, 0xF48E, 0xF48F, 0xF490, 0xF491, 0xF492, 0xF493, + 0xF494, 0xF495, 0xF496, 0xF497, 0xF498, 0xF499, 0xF49A, 0xF49B, 0xF49C, + 0xF49D, 0xF49E, 0xF49F, 0xF4A0, 0xF540, 0xF541, 0xF542, 0xF543, 0xF544, + 0xF545, 0xF546, 0xF547, 0xF548, 0xF549, 0xF54A, 0xF54B, 0xF54C, 0xF54D, + 0xF54E, 0xF54F, 0xF550, 0xF551, 0xF552, 0xF553, 0xF554, 0xF555, 0xF556, + 0xF557, 0xF558, 0xF559, 0xF55A, 0xF55B, 0xF55C, 0xF55D, 0xF55E, 0xF55F, + 0xF560, 0xF561, 0xF562, 0xF563, 0xF564, 0xF565, 0xF566, 0xF567, 0xF568, + 0xF569, 0xF56A, 0xF56B, 0xF56C, 0xF56D, 0xF56E, 0xF56F, 0xF570, 0xF571, + 0xF572, 0xF573, 0xF574, 0xF575, 0xF576, 0xF577, 0xF578, 0xF579, 0xF57A, + 0xF57B, 0xF57C, 0xF57D, 0xF57E, 0xF580, 0xF581, 0xF582, 0xF583, 0xF584, + 0xF585, 0xF586, 0xF587, 0xF588, 0xF589, 0xF58A, 0xF58B, 0xF58C, 0xF58D, + 0xF58E, 0xF58F, 0xF590, 0xF591, 0xF592, 0xF593, 0xF594, 0xF595, 0xF596, + 0xF597, 0xF598, 0xF599, 0xF59A, 0xF59B, 0xF59C, 0xF59D, 0xF59E, 0xF59F, + 0xF5A0, 0xF640, 0xF641, 0xF642, 0xF643, 0xF644, 0xF645, 0xF646, 0xF647, + 0xF648, 0xF649, 0xF64A, 0xF64B, 0xF64C, 0xF64D, 0xF64E, 0xF64F, 0xF650, + 0xF651, 0xF652, 0xF653, 0xF654, 0xF655, 0xF656, 0xF657, 0xF658, 0xF659, + 0xF65A, 0xF65B, 0xF65C, 0xF65D, 0xF65E, 0xF65F, 0xF660, 0xF661, 0xF662, + 0xF663, 0xF664, 0xF665, 0xF666, 0xF667, 0xF668, 0xF669, 0xF66A, 0xF66B, + 0xF66C, 0xF66D, 0xF66E, 0xF66F, 0xF670, 0xF671, 0xF672, 0xF673, 0xF674, + 0xF675, 0xF676, 0xF677, 0xF678, 0xF679, 0xF67A, 0xF67B, 0xF67C, 0xF67D, + 0xF67E, 0xF680, 0xF681, 0xF682, 0xF683, 0xF684, 0xF685, 0xF686, 0xF687, + 0xF688, 0xF689, 0xF68A, 0xF68B, 0xF68C, 0xF68D, 0xF68E, 0xF68F, 0xF690, + 0xF691, 0xF692, 0xF693, 0xF694, 0xF695, 0xF696, 0xF697, 0xF698, 0xF699, + 0xF69A, 0xF69B, 0xF69C, 0xF69D, 0xF69E, 0xF69F, 0xF6A0, 0xF740, 0xF741, + 0xF742, 0xF743, 0xF744, 0xF745, 0xF746, 0xF747, 0xF748, 0xF749, 0xF74A, + 0xF74B, 0xF74C, 0xF74D, 0xF74E, 0xF74F, 0xF750, 0xF751, 0xF752, 0xF753, + 0xF754, 0xF755, 0xF756, 0xF757, 0xF758, 0xF759, 0xF75A, 0xF75B, 0xF75C, + 0xF75D, 0xF75E, 0xF75F, 0xF760, 0xF761, 0xF762, 0xF763, 0xF764, 0xF765, + 0xF766, 0xF767, 0xF768, 0xF769, 0xF76A, 0xF76B, 0xF76C, 0xF76D, 0xF76E, + 0xF76F, 0xF770, 0xF771, 0xF772, 0xF773, 0xF774, 0xF775, 0xF776, 0xF777, + 0xF778, 0xF779, 0xF77A, 0xF77B, 0xF77C, 0xF77D, 0xF77E, 0xF780, 0xD3E3, + 0xF781, 0xF782, 0xF6CF, 0xF783, 0xC2B3, 0xF6D0, 0xF784, 0xF785, 0xF6D1, + 0xF6D2, 0xF6D3, 0xF6D4, 0xF786, 0xF787, 0xF6D6, 0xF788, 0xB1AB, 0xF6D7, + 0xF789, 0xF6D8, 0xF6D9, 0xF6DA, 0xF78A, 0xF6DB, 0xF6DC, 0xF78B, 0xF78C, + 0xF78D, 0xF78E, 0xF6DD, 0xF6DE, 0xCFCA, 0xF78F, 0xF6DF, 0xF6E0, 0xF6E1, + 0xF6E2, 0xF6E3, 0xF6E4, 0xC0F0, 0xF6E5, 0xF6E6, 0xF6E7, 0xF6E8, 0xF6E9, + 0xF790, 0xF6EA, 0xF791, 0xF6EB, 0xF6EC, 0xF792, 0xF6ED, 0xF6EE, 0xF6EF, + 0xF6F0, 0xF6F1, 0xF6F2, 0xF6F3, 0xF6F4, 0xBEA8, 0xF793, 0xF6F5, 0xF6F6, + 0xF6F7, 0xF6F8, 0xF794, 0xF795, 0xF796, 0xF797, 0xF798, 0xC8FA, 0xF6F9, + 0xF6FA, 0xF6FB, 0xF6FC, 0xF799, 0xF79A, 0xF6FD, 0xF6FE, 0xF7A1, 0xF7A2, + 0xF7A3, 0xF7A4, 0xF7A5, 0xF79B, 0xF79C, 0xF7A6, 0xF7A7, 0xF7A8, 0xB1EE, + 0xF7A9, 0xF7AA, 0xF7AB, 0xF79D, 0xF79E, 0xF7AC, 0xF7AD, 0xC1DB, 0xF7AE, + 0xF79F, 0xF7A0, 0xF7AF, 0xF840, 0xF841, 0xF842, 0xF843, 0xF844, 0xF845, + 0xF846, 0xF847, 0xF848, 0xF849, 0xF84A, 0xF84B, 0xF84C, 0xF84D, 0xF84E, + 0xF84F, 0xF850, 0xF851, 0xF852, 0xF853, 0xF854, 0xF855, 0xF856, 0xF857, + 0xF858, 0xF859, 0xF85A, 0xF85B, 0xF85C, 0xF85D, 0xF85E, 0xF85F, 0xF860, + 0xF861, 0xF862, 0xF863, 0xF864, 0xF865, 0xF866, 0xF867, 0xF868, 0xF869, + 0xF86A, 0xF86B, 0xF86C, 0xF86D, 0xF86E, 0xF86F, 0xF870, 0xF871, 0xF872, + 0xF873, 0xF874, 0xF875, 0xF876, 0xF877, 0xF878, 0xF879, 0xF87A, 0xF87B, + 0xF87C, 0xF87D, 0xF87E, 0xF880, 0xF881, 0xF882, 0xF883, 0xF884, 0xF885, + 0xF886, 0xF887, 0xF888, 0xF889, 0xF88A, 0xF88B, 0xF88C, 0xF88D, 0xF88E, + 0xF88F, 0xF890, 0xF891, 0xF892, 0xF893, 0xF894, 0xF895, 0xF896, 0xF897, + 0xF898, 0xF899, 0xF89A, 0xF89B, 0xF89C, 0xF89D, 0xF89E, 0xF89F, 0xF8A0, + 0xF940, 0xF941, 0xF942, 0xF943, 0xF944, 0xF945, 0xF946, 0xF947, 0xF948, + 0xF949, 0xF94A, 0xF94B, 0xF94C, 0xF94D, 0xF94E, 0xF94F, 0xF950, 0xF951, + 0xF952, 0xF953, 0xF954, 0xF955, 0xF956, 0xF957, 0xF958, 0xF959, 0xF95A, + 0xF95B, 0xF95C, 0xF95D, 0xF95E, 0xF95F, 0xF960, 0xF961, 0xF962, 0xF963, + 0xF964, 0xF965, 0xF966, 0xF967, 0xF968, 0xF969, 0xF96A, 0xF96B, 0xF96C, + 0xF96D, 0xF96E, 0xF96F, 0xF970, 0xF971, 0xF972, 0xF973, 0xF974, 0xF975, + 0xF976, 0xF977, 0xF978, 0xF979, 0xF97A, 0xF97B, 0xF97C, 0xF97D, 0xF97E, + 0xF980, 0xF981, 0xF982, 0xF983, 0xF984, 0xF985, 0xF986, 0xF987, 0xF988, + 0xF989, 0xF98A, 0xF98B, 0xF98C, 0xF98D, 0xF98E, 0xF98F, 0xF990, 0xF991, + 0xF992, 0xF993, 0xF994, 0xF995, 0xF996, 0xF997, 0xF998, 0xF999, 0xF99A, + 0xF99B, 0xF99C, 0xF99D, 0xF99E, 0xF99F, 0xF9A0, 0xFA40, 0xFA41, 0xFA42, + 0xFA43, 0xFA44, 0xFA45, 0xFA46, 0xFA47, 0xFA48, 0xFA49, 0xFA4A, 0xFA4B, + 0xFA4C, 0xFA4D, 0xFA4E, 0xFA4F, 0xFA50, 0xFA51, 0xFA52, 0xFA53, 0xFA54, + 0xFA55, 0xFA56, 0xFA57, 0xFA58, 0xFA59, 0xFA5A, 0xFA5B, 0xFA5C, 0xFA5D, + 0xFA5E, 0xFA5F, 0xFA60, 0xFA61, 0xFA62, 0xFA63, 0xFA64, 0xFA65, 0xFA66, + 0xFA67, 0xFA68, 0xFA69, 0xFA6A, 0xFA6B, 0xFA6C, 0xFA6D, 0xFA6E, 0xFA6F, + 0xFA70, 0xFA71, 0xFA72, 0xFA73, 0xFA74, 0xFA75, 0xFA76, 0xFA77, 0xFA78, + 0xFA79, 0xFA7A, 0xFA7B, 0xFA7C, 0xFA7D, 0xFA7E, 0xFA80, 0xFA81, 0xFA82, + 0xFA83, 0xFA84, 0xFA85, 0xFA86, 0xFA87, 0xFA88, 0xFA89, 0xFA8A, 0xFA8B, + 0xFA8C, 0xFA8D, 0xFA8E, 0xFA8F, 0xFA90, 0xFA91, 0xFA92, 0xFA93, 0xFA94, + 0xFA95, 0xFA96, 0xFA97, 0xFA98, 0xFA99, 0xFA9A, 0xFA9B, 0xFA9C, 0xFA9D, + 0xFA9E, 0xFA9F, 0xFAA0, 0xFB40, 0xFB41, 0xFB42, 0xFB43, 0xFB44, 0xFB45, + 0xFB46, 0xFB47, 0xFB48, 0xFB49, 0xFB4A, 0xFB4B, 0xFB4C, 0xFB4D, 0xFB4E, + 0xFB4F, 0xFB50, 0xFB51, 0xFB52, 0xFB53, 0xFB54, 0xFB55, 0xFB56, 0xFB57, + 0xFB58, 0xFB59, 0xFB5A, 0xFB5B, 0xC4F1, 0xF0AF, 0xBCA6, 0xF0B0, 0xC3F9, + 0xFB5C, 0xC5B8, 0xD1BB, 0xFB5D, 0xF0B1, 0xF0B2, 0xF0B3, 0xF0B4, 0xF0B5, + 0xD1BC, 0xFB5E, 0xD1EC, 0xFB5F, 0xF0B7, 0xF0B6, 0xD4A7, 0xFB60, 0xCDD2, + 0xF0B8, 0xF0BA, 0xF0B9, 0xF0BB, 0xF0BC, 0xFB61, 0xFB62, 0xB8EB, 0xF0BD, + 0xBAE8, 0xFB63, 0xF0BE, 0xF0BF, 0xBEE9, 0xF0C0, 0xB6EC, 0xF0C1, 0xF0C2, + 0xF0C3, 0xF0C4, 0xC8B5, 0xF0C5, 0xF0C6, 0xFB64, 0xF0C7, 0xC5F4, 0xFB65, + 0xF0C8, 0xFB66, 0xFB67, 0xFB68, 0xF0C9, 0xFB69, 0xF0CA, 0xF7BD, 0xFB6A, + 0xF0CB, 0xF0CC, 0xF0CD, 0xFB6B, 0xF0CE, 0xFB6C, 0xFB6D, 0xFB6E, 0xFB6F, + 0xF0CF, 0xBAD7, 0xFB70, 0xF0D0, 0xF0D1, 0xF0D2, 0xF0D3, 0xF0D4, 0xF0D5, + 0xF0D6, 0xF0D8, 0xFB71, 0xFB72, 0xD3A5, 0xF0D7, 0xFB73, 0xF0D9, 0xFB74, + 0xFB75, 0xFB76, 0xFB77, 0xFB78, 0xFB79, 0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D, + 0xF5BA, 0xC2B9, 0xFB7E, 0xFB80, 0xF7E4, 0xFB81, 0xFB82, 0xFB83, 0xFB84, + 0xF7E5, 0xF7E6, 0xFB85, 0xFB86, 0xF7E7, 0xFB87, 0xFB88, 0xFB89, 0xFB8A, + 0xFB8B, 0xFB8C, 0xF7E8, 0xC2B4, 0xFB8D, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91, + 0xFB92, 0xFB93, 0xFB94, 0xFB95, 0xF7EA, 0xFB96, 0xF7EB, 0xFB97, 0xFB98, + 0xFB99, 0xFB9A, 0xFB9B, 0xFB9C, 0xC2F3, 0xFB9D, 0xFB9E, 0xFB9F, 0xFBA0, + 0xFC40, 0xFC41, 0xFC42, 0xFC43, 0xFC44, 0xFC45, 0xFC46, 0xFC47, 0xFC48, + 0xF4F0, 0xFC49, 0xFC4A, 0xFC4B, 0xF4EF, 0xFC4C, 0xFC4D, 0xC2E9, 0xFC4E, + 0xF7E1, 0xF7E2, 0xFC4F, 0xFC50, 0xFC51, 0xFC52, 0xFC53, 0xBBC6, 0xFC54, + 0xFC55, 0xFC56, 0xFC57, 0xD9E4, 0xFC58, 0xFC59, 0xFC5A, 0xCAF2, 0xC0E8, + 0xF0A4, 0xFC5B, 0xBADA, 0xFC5C, 0xFC5D, 0xC7AD, 0xFC5E, 0xFC5F, 0xFC60, + 0xC4AC, 0xFC61, 0xFC62, 0xF7EC, 0xF7ED, 0xF7EE, 0xFC63, 0xF7F0, 0xF7EF, + 0xFC64, 0xF7F1, 0xFC65, 0xFC66, 0xF7F4, 0xFC67, 0xF7F3, 0xFC68, 0xF7F2, + 0xF7F5, 0xFC69, 0xFC6A, 0xFC6B, 0xFC6C, 0xF7F6, 0xFC6D, 0xFC6E, 0xFC6F, + 0xFC70, 0xFC71, 0xFC72, 0xFC73, 0xFC74, 0xFC75, 0xEDE9, 0xFC76, 0xEDEA, + 0xEDEB, 0xFC77, 0xF6BC, 0xFC78, 0xFC79, 0xFC7A, 0xFC7B, 0xFC7C, 0xFC7D, + 0xFC7E, 0xFC80, 0xFC81, 0xFC82, 0xFC83, 0xFC84, 0xF6BD, 0xFC85, 0xF6BE, + 0xB6A6, 0xFC86, 0xD8BE, 0xFC87, 0xFC88, 0xB9C4, 0xFC89, 0xFC8A, 0xFC8B, + 0xD8BB, 0xFC8C, 0xDCB1, 0xFC8D, 0xFC8E, 0xFC8F, 0xFC90, 0xFC91, 0xFC92, + 0xCAF3, 0xFC93, 0xF7F7, 0xFC94, 0xFC95, 0xFC96, 0xFC97, 0xFC98, 0xFC99, + 0xFC9A, 0xFC9B, 0xFC9C, 0xF7F8, 0xFC9D, 0xFC9E, 0xF7F9, 0xFC9F, 0xFCA0, + 0xFD40, 0xFD41, 0xFD42, 0xFD43, 0xFD44, 0xF7FB, 0xFD45, 0xF7FA, 0xFD46, + 0xB1C7, 0xFD47, 0xF7FC, 0xF7FD, 0xFD48, 0xFD49, 0xFD4A, 0xFD4B, 0xFD4C, + 0xF7FE, 0xFD4D, 0xFD4E, 0xFD4F, 0xFD50, 0xFD51, 0xFD52, 0xFD53, 0xFD54, + 0xFD55, 0xFD56, 0xFD57, 0xC6EB, 0xECB4, 0xFD58, 0xFD59, 0xFD5A, 0xFD5B, + 0xFD5C, 0xFD5D, 0xFD5E, 0xFD5F, 0xFD60, 0xFD61, 0xFD62, 0xFD63, 0xFD64, + 0xFD65, 0xFD66, 0xFD67, 0xFD68, 0xFD69, 0xFD6A, 0xFD6B, 0xFD6C, 0xFD6D, + 0xFD6E, 0xFD6F, 0xFD70, 0xFD71, 0xFD72, 0xFD73, 0xFD74, 0xFD75, 0xFD76, + 0xFD77, 0xFD78, 0xFD79, 0xFD7A, 0xFD7B, 0xFD7C, 0xFD7D, 0xFD7E, 0xFD80, + 0xFD81, 0xFD82, 0xFD83, 0xFD84, 0xFD85, 0xB3DD, 0xF6B3, 0xFD86, 0xFD87, + 0xF6B4, 0xC1E4, 0xF6B5, 0xF6B6, 0xF6B7, 0xF6B8, 0xF6B9, 0xF6BA, 0xC8A3, + 0xF6BB, 0xFD88, 0xFD89, 0xFD8A, 0xFD8B, 0xFD8C, 0xFD8D, 0xFD8E, 0xFD8F, + 0xFD90, 0xFD91, 0xFD92, 0xFD93, 0xC1FA, 0xB9A8, 0xEDE8, 0xFD94, 0xFD95, + 0xFD96, 0xB9EA, 0xD9DF, 0xFD97, 0xFD98, 0xFD99, 0xFD9A, 0xFD9B}; + +static const uint16_t tab_uni_gb18030_p2[] = { + 0xAAA1, 0xAAA2, 0xAAA3, 0xAAA4, 0xAAA5, 0xAAA6, 0xAAA7, 0xAAA8, 0xAAA9, + 0xAAAA, 0xAAAB, 0xAAAC, 0xAAAD, 0xAAAE, 0xAAAF, 0xAAB0, 0xAAB1, 0xAAB2, + 0xAAB3, 0xAAB4, 0xAAB5, 0xAAB6, 0xAAB7, 0xAAB8, 0xAAB9, 0xAABA, 0xAABB, + 0xAABC, 0xAABD, 0xAABE, 0xAABF, 0xAAC0, 0xAAC1, 0xAAC2, 0xAAC3, 0xAAC4, + 0xAAC5, 0xAAC6, 0xAAC7, 0xAAC8, 0xAAC9, 0xAACA, 0xAACB, 0xAACC, 0xAACD, + 0xAACE, 0xAACF, 0xAAD0, 0xAAD1, 0xAAD2, 0xAAD3, 0xAAD4, 0xAAD5, 0xAAD6, + 0xAAD7, 0xAAD8, 0xAAD9, 0xAADA, 0xAADB, 0xAADC, 0xAADD, 0xAADE, 0xAADF, + 0xAAE0, 0xAAE1, 0xAAE2, 0xAAE3, 0xAAE4, 0xAAE5, 0xAAE6, 0xAAE7, 0xAAE8, + 0xAAE9, 0xAAEA, 0xAAEB, 0xAAEC, 0xAAED, 0xAAEE, 0xAAEF, 0xAAF0, 0xAAF1, + 0xAAF2, 0xAAF3, 0xAAF4, 0xAAF5, 0xAAF6, 0xAAF7, 0xAAF8, 0xAAF9, 0xAAFA, + 0xAAFB, 0xAAFC, 0xAAFD, 0xAAFE, 0xABA1, 0xABA2, 0xABA3, 0xABA4, 0xABA5, + 0xABA6, 0xABA7, 0xABA8, 0xABA9, 0xABAA, 0xABAB, 0xABAC, 0xABAD, 0xABAE, + 0xABAF, 0xABB0, 0xABB1, 0xABB2, 0xABB3, 0xABB4, 0xABB5, 0xABB6, 0xABB7, + 0xABB8, 0xABB9, 0xABBA, 0xABBB, 0xABBC, 0xABBD, 0xABBE, 0xABBF, 0xABC0, + 0xABC1, 0xABC2, 0xABC3, 0xABC4, 0xABC5, 0xABC6, 0xABC7, 0xABC8, 0xABC9, + 0xABCA, 0xABCB, 0xABCC, 0xABCD, 0xABCE, 0xABCF, 0xABD0, 0xABD1, 0xABD2, + 0xABD3, 0xABD4, 0xABD5, 0xABD6, 0xABD7, 0xABD8, 0xABD9, 0xABDA, 0xABDB, + 0xABDC, 0xABDD, 0xABDE, 0xABDF, 0xABE0, 0xABE1, 0xABE2, 0xABE3, 0xABE4, + 0xABE5, 0xABE6, 0xABE7, 0xABE8, 0xABE9, 0xABEA, 0xABEB, 0xABEC, 0xABED, + 0xABEE, 0xABEF, 0xABF0, 0xABF1, 0xABF2, 0xABF3, 0xABF4, 0xABF5, 0xABF6, + 0xABF7, 0xABF8, 0xABF9, 0xABFA, 0xABFB, 0xABFC, 0xABFD, 0xABFE, 0xACA1, + 0xACA2, 0xACA3, 0xACA4, 0xACA5, 0xACA6, 0xACA7, 0xACA8, 0xACA9, 0xACAA, + 0xACAB, 0xACAC, 0xACAD, 0xACAE, 0xACAF, 0xACB0, 0xACB1, 0xACB2, 0xACB3, + 0xACB4, 0xACB5, 0xACB6, 0xACB7, 0xACB8, 0xACB9, 0xACBA, 0xACBB, 0xACBC, + 0xACBD, 0xACBE, 0xACBF, 0xACC0, 0xACC1, 0xACC2, 0xACC3, 0xACC4, 0xACC5, + 0xACC6, 0xACC7, 0xACC8, 0xACC9, 0xACCA, 0xACCB, 0xACCC, 0xACCD, 0xACCE, + 0xACCF, 0xACD0, 0xACD1, 0xACD2, 0xACD3, 0xACD4, 0xACD5, 0xACD6, 0xACD7, + 0xACD8, 0xACD9, 0xACDA, 0xACDB, 0xACDC, 0xACDD, 0xACDE, 0xACDF, 0xACE0, + 0xACE1, 0xACE2, 0xACE3, 0xACE4, 0xACE5, 0xACE6, 0xACE7, 0xACE8, 0xACE9, + 0xACEA, 0xACEB, 0xACEC, 0xACED, 0xACEE, 0xACEF, 0xACF0, 0xACF1, 0xACF2, + 0xACF3, 0xACF4, 0xACF5, 0xACF6, 0xACF7, 0xACF8, 0xACF9, 0xACFA, 0xACFB, + 0xACFC, 0xACFD, 0xACFE, 0xADA1, 0xADA2, 0xADA3, 0xADA4, 0xADA5, 0xADA6, + 0xADA7, 0xADA8, 0xADA9, 0xADAA, 0xADAB, 0xADAC, 0xADAD, 0xADAE, 0xADAF, + 0xADB0, 0xADB1, 0xADB2, 0xADB3, 0xADB4, 0xADB5, 0xADB6, 0xADB7, 0xADB8, + 0xADB9, 0xADBA, 0xADBB, 0xADBC, 0xADBD, 0xADBE, 0xADBF, 0xADC0, 0xADC1, + 0xADC2, 0xADC3, 0xADC4, 0xADC5, 0xADC6, 0xADC7, 0xADC8, 0xADC9, 0xADCA, + 0xADCB, 0xADCC, 0xADCD, 0xADCE, 0xADCF, 0xADD0, 0xADD1, 0xADD2, 0xADD3, + 0xADD4, 0xADD5, 0xADD6, 0xADD7, 0xADD8, 0xADD9, 0xADDA, 0xADDB, 0xADDC, + 0xADDD, 0xADDE, 0xADDF, 0xADE0, 0xADE1, 0xADE2, 0xADE3, 0xADE4, 0xADE5, + 0xADE6, 0xADE7, 0xADE8, 0xADE9, 0xADEA, 0xADEB, 0xADEC, 0xADED, 0xADEE, + 0xADEF, 0xADF0, 0xADF1, 0xADF2, 0xADF3, 0xADF4, 0xADF5, 0xADF6, 0xADF7, + 0xADF8, 0xADF9, 0xADFA, 0xADFB, 0xADFC, 0xADFD, 0xADFE, 0xAEA1, 0xAEA2, + 0xAEA3, 0xAEA4, 0xAEA5, 0xAEA6, 0xAEA7, 0xAEA8, 0xAEA9, 0xAEAA, 0xAEAB, + 0xAEAC, 0xAEAD, 0xAEAE, 0xAEAF, 0xAEB0, 0xAEB1, 0xAEB2, 0xAEB3, 0xAEB4, + 0xAEB5, 0xAEB6, 0xAEB7, 0xAEB8, 0xAEB9, 0xAEBA, 0xAEBB, 0xAEBC, 0xAEBD, + 0xAEBE, 0xAEBF, 0xAEC0, 0xAEC1, 0xAEC2, 0xAEC3, 0xAEC4, 0xAEC5, 0xAEC6, + 0xAEC7, 0xAEC8, 0xAEC9, 0xAECA, 0xAECB, 0xAECC, 0xAECD, 0xAECE, 0xAECF, + 0xAED0, 0xAED1, 0xAED2, 0xAED3, 0xAED4, 0xAED5, 0xAED6, 0xAED7, 0xAED8, + 0xAED9, 0xAEDA, 0xAEDB, 0xAEDC, 0xAEDD, 0xAEDE, 0xAEDF, 0xAEE0, 0xAEE1, + 0xAEE2, 0xAEE3, 0xAEE4, 0xAEE5, 0xAEE6, 0xAEE7, 0xAEE8, 0xAEE9, 0xAEEA, + 0xAEEB, 0xAEEC, 0xAEED, 0xAEEE, 0xAEEF, 0xAEF0, 0xAEF1, 0xAEF2, 0xAEF3, + 0xAEF4, 0xAEF5, 0xAEF6, 0xAEF7, 0xAEF8, 0xAEF9, 0xAEFA, 0xAEFB, 0xAEFC, + 0xAEFD, 0xAEFE, 0xAFA1, 0xAFA2, 0xAFA3, 0xAFA4, 0xAFA5, 0xAFA6, 0xAFA7, + 0xAFA8, 0xAFA9, 0xAFAA, 0xAFAB, 0xAFAC, 0xAFAD, 0xAFAE, 0xAFAF, 0xAFB0, + 0xAFB1, 0xAFB2, 0xAFB3, 0xAFB4, 0xAFB5, 0xAFB6, 0xAFB7, 0xAFB8, 0xAFB9, + 0xAFBA, 0xAFBB, 0xAFBC, 0xAFBD, 0xAFBE, 0xAFBF, 0xAFC0, 0xAFC1, 0xAFC2, + 0xAFC3, 0xAFC4, 0xAFC5, 0xAFC6, 0xAFC7, 0xAFC8, 0xAFC9, 0xAFCA, 0xAFCB, + 0xAFCC, 0xAFCD, 0xAFCE, 0xAFCF, 0xAFD0, 0xAFD1, 0xAFD2, 0xAFD3, 0xAFD4, + 0xAFD5, 0xAFD6, 0xAFD7, 0xAFD8, 0xAFD9, 0xAFDA, 0xAFDB, 0xAFDC, 0xAFDD, + 0xAFDE, 0xAFDF, 0xAFE0, 0xAFE1, 0xAFE2, 0xAFE3, 0xAFE4, 0xAFE5, 0xAFE6, + 0xAFE7, 0xAFE8, 0xAFE9, 0xAFEA, 0xAFEB, 0xAFEC, 0xAFED, 0xAFEE, 0xAFEF, + 0xAFF0, 0xAFF1, 0xAFF2, 0xAFF3, 0xAFF4, 0xAFF5, 0xAFF6, 0xAFF7, 0xAFF8, + 0xAFF9, 0xAFFA, 0xAFFB, 0xAFFC, 0xAFFD, 0xAFFE, 0xF8A1, 0xF8A2, 0xF8A3, + 0xF8A4, 0xF8A5, 0xF8A6, 0xF8A7, 0xF8A8, 0xF8A9, 0xF8AA, 0xF8AB, 0xF8AC, + 0xF8AD, 0xF8AE, 0xF8AF, 0xF8B0, 0xF8B1, 0xF8B2, 0xF8B3, 0xF8B4, 0xF8B5, + 0xF8B6, 0xF8B7, 0xF8B8, 0xF8B9, 0xF8BA, 0xF8BB, 0xF8BC, 0xF8BD, 0xF8BE, + 0xF8BF, 0xF8C0, 0xF8C1, 0xF8C2, 0xF8C3, 0xF8C4, 0xF8C5, 0xF8C6, 0xF8C7, + 0xF8C8, 0xF8C9, 0xF8CA, 0xF8CB, 0xF8CC, 0xF8CD, 0xF8CE, 0xF8CF, 0xF8D0, + 0xF8D1, 0xF8D2, 0xF8D3, 0xF8D4, 0xF8D5, 0xF8D6, 0xF8D7, 0xF8D8, 0xF8D9, + 0xF8DA, 0xF8DB, 0xF8DC, 0xF8DD, 0xF8DE, 0xF8DF, 0xF8E0, 0xF8E1, 0xF8E2, + 0xF8E3, 0xF8E4, 0xF8E5, 0xF8E6, 0xF8E7, 0xF8E8, 0xF8E9, 0xF8EA, 0xF8EB, + 0xF8EC, 0xF8ED, 0xF8EE, 0xF8EF, 0xF8F0, 0xF8F1, 0xF8F2, 0xF8F3, 0xF8F4, + 0xF8F5, 0xF8F6, 0xF8F7, 0xF8F8, 0xF8F9, 0xF8FA, 0xF8FB, 0xF8FC, 0xF8FD, + 0xF8FE, 0xF9A1, 0xF9A2, 0xF9A3, 0xF9A4, 0xF9A5, 0xF9A6, 0xF9A7, 0xF9A8, + 0xF9A9, 0xF9AA, 0xF9AB, 0xF9AC, 0xF9AD, 0xF9AE, 0xF9AF, 0xF9B0, 0xF9B1, + 0xF9B2, 0xF9B3, 0xF9B4, 0xF9B5, 0xF9B6, 0xF9B7, 0xF9B8, 0xF9B9, 0xF9BA, + 0xF9BB, 0xF9BC, 0xF9BD, 0xF9BE, 0xF9BF, 0xF9C0, 0xF9C1, 0xF9C2, 0xF9C3, + 0xF9C4, 0xF9C5, 0xF9C6, 0xF9C7, 0xF9C8, 0xF9C9, 0xF9CA, 0xF9CB, 0xF9CC, + 0xF9CD, 0xF9CE, 0xF9CF, 0xF9D0, 0xF9D1, 0xF9D2, 0xF9D3, 0xF9D4, 0xF9D5, + 0xF9D6, 0xF9D7, 0xF9D8, 0xF9D9, 0xF9DA, 0xF9DB, 0xF9DC, 0xF9DD, 0xF9DE, + 0xF9DF, 0xF9E0, 0xF9E1, 0xF9E2, 0xF9E3, 0xF9E4, 0xF9E5, 0xF9E6, 0xF9E7, + 0xF9E8, 0xF9E9, 0xF9EA, 0xF9EB, 0xF9EC, 0xF9ED, 0xF9EE, 0xF9EF, 0xF9F0, + 0xF9F1, 0xF9F2, 0xF9F3, 0xF9F4, 0xF9F5, 0xF9F6, 0xF9F7, 0xF9F8, 0xF9F9, + 0xF9FA, 0xF9FB, 0xF9FC, 0xF9FD, 0xF9FE, 0xFAA1, 0xFAA2, 0xFAA3, 0xFAA4, + 0xFAA5, 0xFAA6, 0xFAA7, 0xFAA8, 0xFAA9, 0xFAAA, 0xFAAB, 0xFAAC, 0xFAAD, + 0xFAAE, 0xFAAF, 0xFAB0, 0xFAB1, 0xFAB2, 0xFAB3, 0xFAB4, 0xFAB5, 0xFAB6, + 0xFAB7, 0xFAB8, 0xFAB9, 0xFABA, 0xFABB, 0xFABC, 0xFABD, 0xFABE, 0xFABF, + 0xFAC0, 0xFAC1, 0xFAC2, 0xFAC3, 0xFAC4, 0xFAC5, 0xFAC6, 0xFAC7, 0xFAC8, + 0xFAC9, 0xFACA, 0xFACB, 0xFACC, 0xFACD, 0xFACE, 0xFACF, 0xFAD0, 0xFAD1, + 0xFAD2, 0xFAD3, 0xFAD4, 0xFAD5, 0xFAD6, 0xFAD7, 0xFAD8, 0xFAD9, 0xFADA, + 0xFADB, 0xFADC, 0xFADD, 0xFADE, 0xFADF, 0xFAE0, 0xFAE1, 0xFAE2, 0xFAE3, + 0xFAE4, 0xFAE5, 0xFAE6, 0xFAE7, 0xFAE8, 0xFAE9, 0xFAEA, 0xFAEB, 0xFAEC, + 0xFAED, 0xFAEE, 0xFAEF, 0xFAF0, 0xFAF1, 0xFAF2, 0xFAF3, 0xFAF4, 0xFAF5, + 0xFAF6, 0xFAF7, 0xFAF8, 0xFAF9, 0xFAFA, 0xFAFB, 0xFAFC, 0xFAFD, 0xFAFE, + 0xFBA1, 0xFBA2, 0xFBA3, 0xFBA4, 0xFBA5, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9, + 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD, 0xFBAE, 0xFBAF, 0xFBB0, 0xFBB1, 0xFBB2, + 0xFBB3, 0xFBB4, 0xFBB5, 0xFBB6, 0xFBB7, 0xFBB8, 0xFBB9, 0xFBBA, 0xFBBB, + 0xFBBC, 0xFBBD, 0xFBBE, 0xFBBF, 0xFBC0, 0xFBC1, 0xFBC2, 0xFBC3, 0xFBC4, + 0xFBC5, 0xFBC6, 0xFBC7, 0xFBC8, 0xFBC9, 0xFBCA, 0xFBCB, 0xFBCC, 0xFBCD, + 0xFBCE, 0xFBCF, 0xFBD0, 0xFBD1, 0xFBD2, 0xFBD3, 0xFBD4, 0xFBD5, 0xFBD6, + 0xFBD7, 0xFBD8, 0xFBD9, 0xFBDA, 0xFBDB, 0xFBDC, 0xFBDD, 0xFBDE, 0xFBDF, + 0xFBE0, 0xFBE1, 0xFBE2, 0xFBE3, 0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7, 0xFBE8, + 0xFBE9, 0xFBEA, 0xFBEB, 0xFBEC, 0xFBED, 0xFBEE, 0xFBEF, 0xFBF0, 0xFBF1, + 0xFBF2, 0xFBF3, 0xFBF4, 0xFBF5, 0xFBF6, 0xFBF7, 0xFBF8, 0xFBF9, 0xFBFA, + 0xFBFB, 0xFBFC, 0xFBFD, 0xFBFE, 0xFCA1, 0xFCA2, 0xFCA3, 0xFCA4, 0xFCA5, + 0xFCA6, 0xFCA7, 0xFCA8, 0xFCA9, 0xFCAA, 0xFCAB, 0xFCAC, 0xFCAD, 0xFCAE, + 0xFCAF, 0xFCB0, 0xFCB1, 0xFCB2, 0xFCB3, 0xFCB4, 0xFCB5, 0xFCB6, 0xFCB7, + 0xFCB8, 0xFCB9, 0xFCBA, 0xFCBB, 0xFCBC, 0xFCBD, 0xFCBE, 0xFCBF, 0xFCC0, + 0xFCC1, 0xFCC2, 0xFCC3, 0xFCC4, 0xFCC5, 0xFCC6, 0xFCC7, 0xFCC8, 0xFCC9, + 0xFCCA, 0xFCCB, 0xFCCC, 0xFCCD, 0xFCCE, 0xFCCF, 0xFCD0, 0xFCD1, 0xFCD2, + 0xFCD3, 0xFCD4, 0xFCD5, 0xFCD6, 0xFCD7, 0xFCD8, 0xFCD9, 0xFCDA, 0xFCDB, + 0xFCDC, 0xFCDD, 0xFCDE, 0xFCDF, 0xFCE0, 0xFCE1, 0xFCE2, 0xFCE3, 0xFCE4, + 0xFCE5, 0xFCE6, 0xFCE7, 0xFCE8, 0xFCE9, 0xFCEA, 0xFCEB, 0xFCEC, 0xFCED, + 0xFCEE, 0xFCEF, 0xFCF0, 0xFCF1, 0xFCF2, 0xFCF3, 0xFCF4, 0xFCF5, 0xFCF6, + 0xFCF7, 0xFCF8, 0xFCF9, 0xFCFA, 0xFCFB, 0xFCFC, 0xFCFD, 0xFCFE, 0xFDA1, + 0xFDA2, 0xFDA3, 0xFDA4, 0xFDA5, 0xFDA6, 0xFDA7, 0xFDA8, 0xFDA9, 0xFDAA, + 0xFDAB, 0xFDAC, 0xFDAD, 0xFDAE, 0xFDAF, 0xFDB0, 0xFDB1, 0xFDB2, 0xFDB3, + 0xFDB4, 0xFDB5, 0xFDB6, 0xFDB7, 0xFDB8, 0xFDB9, 0xFDBA, 0xFDBB, 0xFDBC, + 0xFDBD, 0xFDBE, 0xFDBF, 0xFDC0, 0xFDC1, 0xFDC2, 0xFDC3, 0xFDC4, 0xFDC5, + 0xFDC6, 0xFDC7, 0xFDC8, 0xFDC9, 0xFDCA, 0xFDCB, 0xFDCC, 0xFDCD, 0xFDCE, + 0xFDCF, 0xFDD0, 0xFDD1, 0xFDD2, 0xFDD3, 0xFDD4, 0xFDD5, 0xFDD6, 0xFDD7, + 0xFDD8, 0xFDD9, 0xFDDA, 0xFDDB, 0xFDDC, 0xFDDD, 0xFDDE, 0xFDDF, 0xFDE0, + 0xFDE1, 0xFDE2, 0xFDE3, 0xFDE4, 0xFDE5, 0xFDE6, 0xFDE7, 0xFDE8, 0xFDE9, + 0xFDEA, 0xFDEB, 0xFDEC, 0xFDED, 0xFDEE, 0xFDEF, 0xFDF0, 0xFDF1, 0xFDF2, + 0xFDF3, 0xFDF4, 0xFDF5, 0xFDF6, 0xFDF7, 0xFDF8, 0xFDF9, 0xFDFA, 0xFDFB, + 0xFDFC, 0xFDFD, 0xFDFE, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, 0xFEA6, + 0xFEA7, 0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, 0xFEAE, 0xFEAF, + 0xFEB0, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8, + 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0, 0xFEC1, + 0xFEC2, 0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8, 0xFEC9, 0xFECA, + 0xFECB, 0xFECC, 0xFECD, 0xFECE, 0xFECF, 0xFED0, 0xFED1, 0xFED2, 0xFED3, + 0xFED4, 0xFED5, 0xFED6, 0xFED7, 0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, + 0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, + 0xFEE6, 0xFEE7, 0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, 0xFEEE, + 0xFEEF, 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7, + 0xFEF8, 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0xA140, 0xA141, + 0xA142, 0xA143, 0xA144, 0xA145, 0xA146, 0xA147, 0xA148, 0xA149, 0xA14A, + 0xA14B, 0xA14C, 0xA14D, 0xA14E, 0xA14F, 0xA150, 0xA151, 0xA152, 0xA153, + 0xA154, 0xA155, 0xA156, 0xA157, 0xA158, 0xA159, 0xA15A, 0xA15B, 0xA15C, + 0xA15D, 0xA15E, 0xA15F, 0xA160, 0xA161, 0xA162, 0xA163, 0xA164, 0xA165, + 0xA166, 0xA167, 0xA168, 0xA169, 0xA16A, 0xA16B, 0xA16C, 0xA16D, 0xA16E, + 0xA16F, 0xA170, 0xA171, 0xA172, 0xA173, 0xA174, 0xA175, 0xA176, 0xA177, + 0xA178, 0xA179, 0xA17A, 0xA17B, 0xA17C, 0xA17D, 0xA17E, 0xA180, 0xA181, + 0xA182, 0xA183, 0xA184, 0xA185, 0xA186, 0xA187, 0xA188, 0xA189, 0xA18A, + 0xA18B, 0xA18C, 0xA18D, 0xA18E, 0xA18F, 0xA190, 0xA191, 0xA192, 0xA193, + 0xA194, 0xA195, 0xA196, 0xA197, 0xA198, 0xA199, 0xA19A, 0xA19B, 0xA19C, + 0xA19D, 0xA19E, 0xA19F, 0xA1A0, 0xA240, 0xA241, 0xA242, 0xA243, 0xA244, + 0xA245, 0xA246, 0xA247, 0xA248, 0xA249, 0xA24A, 0xA24B, 0xA24C, 0xA24D, + 0xA24E, 0xA24F, 0xA250, 0xA251, 0xA252, 0xA253, 0xA254, 0xA255, 0xA256, + 0xA257, 0xA258, 0xA259, 0xA25A, 0xA25B, 0xA25C, 0xA25D, 0xA25E, 0xA25F, + 0xA260, 0xA261, 0xA262, 0xA263, 0xA264, 0xA265, 0xA266, 0xA267, 0xA268, + 0xA269, 0xA26A, 0xA26B, 0xA26C, 0xA26D, 0xA26E, 0xA26F, 0xA270, 0xA271, + 0xA272, 0xA273, 0xA274, 0xA275, 0xA276, 0xA277, 0xA278, 0xA279, 0xA27A, + 0xA27B, 0xA27C, 0xA27D, 0xA27E, 0xA280, 0xA281, 0xA282, 0xA283, 0xA284, + 0xA285, 0xA286, 0xA287, 0xA288, 0xA289, 0xA28A, 0xA28B, 0xA28C, 0xA28D, + 0xA28E, 0xA28F, 0xA290, 0xA291, 0xA292, 0xA293, 0xA294, 0xA295, 0xA296, + 0xA297, 0xA298, 0xA299, 0xA29A, 0xA29B, 0xA29C, 0xA29D, 0xA29E, 0xA29F, + 0xA2A0, 0xA340, 0xA341, 0xA342, 0xA343, 0xA344, 0xA345, 0xA346, 0xA347, + 0xA348, 0xA349, 0xA34A, 0xA34B, 0xA34C, 0xA34D, 0xA34E, 0xA34F, 0xA350, + 0xA351, 0xA352, 0xA353, 0xA354, 0xA355, 0xA356, 0xA357, 0xA358, 0xA359, + 0xA35A, 0xA35B, 0xA35C, 0xA35D, 0xA35E, 0xA35F, 0xA360, 0xA361, 0xA362, + 0xA363, 0xA364, 0xA365, 0xA366, 0xA367, 0xA368, 0xA369, 0xA36A, 0xA36B, + 0xA36C, 0xA36D, 0xA36E, 0xA36F, 0xA370, 0xA371, 0xA372, 0xA373, 0xA374, + 0xA375, 0xA376, 0xA377, 0xA378, 0xA379, 0xA37A, 0xA37B, 0xA37C, 0xA37D, + 0xA37E, 0xA380, 0xA381, 0xA382, 0xA383, 0xA384, 0xA385, 0xA386, 0xA387, + 0xA388, 0xA389, 0xA38A, 0xA38B, 0xA38C, 0xA38D, 0xA38E, 0xA38F, 0xA390, + 0xA391, 0xA392, 0xA393, 0xA394, 0xA395, 0xA396, 0xA397, 0xA398, 0xA399, + 0xA39A, 0xA39B, 0xA39C, 0xA39D, 0xA39E, 0xA39F, 0xA3A0, 0xA440, 0xA441, + 0xA442, 0xA443, 0xA444, 0xA445, 0xA446, 0xA447, 0xA448, 0xA449, 0xA44A, + 0xA44B, 0xA44C, 0xA44D, 0xA44E, 0xA44F, 0xA450, 0xA451, 0xA452, 0xA453, + 0xA454, 0xA455, 0xA456, 0xA457, 0xA458, 0xA459, 0xA45A, 0xA45B, 0xA45C, + 0xA45D, 0xA45E, 0xA45F, 0xA460, 0xA461, 0xA462, 0xA463, 0xA464, 0xA465, + 0xA466, 0xA467, 0xA468, 0xA469, 0xA46A, 0xA46B, 0xA46C, 0xA46D, 0xA46E, + 0xA46F, 0xA470, 0xA471, 0xA472, 0xA473, 0xA474, 0xA475, 0xA476, 0xA477, + 0xA478, 0xA479, 0xA47A, 0xA47B, 0xA47C, 0xA47D, 0xA47E, 0xA480, 0xA481, + 0xA482, 0xA483, 0xA484, 0xA485, 0xA486, 0xA487, 0xA488, 0xA489, 0xA48A, + 0xA48B, 0xA48C, 0xA48D, 0xA48E, 0xA48F, 0xA490, 0xA491, 0xA492, 0xA493, + 0xA494, 0xA495, 0xA496, 0xA497, 0xA498, 0xA499, 0xA49A, 0xA49B, 0xA49C, + 0xA49D, 0xA49E, 0xA49F, 0xA4A0, 0xA540, 0xA541, 0xA542, 0xA543, 0xA544, + 0xA545, 0xA546, 0xA547, 0xA548, 0xA549, 0xA54A, 0xA54B, 0xA54C, 0xA54D, + 0xA54E, 0xA54F, 0xA550, 0xA551, 0xA552, 0xA553, 0xA554, 0xA555, 0xA556, + 0xA557, 0xA558, 0xA559, 0xA55A, 0xA55B, 0xA55C, 0xA55D, 0xA55E, 0xA55F, + 0xA560, 0xA561, 0xA562, 0xA563, 0xA564, 0xA565, 0xA566, 0xA567, 0xA568, + 0xA569, 0xA56A, 0xA56B, 0xA56C, 0xA56D, 0xA56E, 0xA56F, 0xA570, 0xA571, + 0xA572, 0xA573, 0xA574, 0xA575, 0xA576, 0xA577, 0xA578, 0xA579, 0xA57A, + 0xA57B, 0xA57C, 0xA57D, 0xA57E, 0xA580, 0xA581, 0xA582, 0xA583, 0xA584, + 0xA585, 0xA586, 0xA587, 0xA588, 0xA589, 0xA58A, 0xA58B, 0xA58C, 0xA58D, + 0xA58E, 0xA58F, 0xA590, 0xA591, 0xA592, 0xA593, 0xA594, 0xA595, 0xA596, + 0xA597, 0xA598, 0xA599, 0xA59A, 0xA59B, 0xA59C, 0xA59D, 0xA59E, 0xA59F, + 0xA5A0, 0xA640, 0xA641, 0xA642, 0xA643, 0xA644, 0xA645, 0xA646, 0xA647, + 0xA648, 0xA649, 0xA64A, 0xA64B, 0xA64C, 0xA64D, 0xA64E, 0xA64F, 0xA650, + 0xA651, 0xA652, 0xA653, 0xA654, 0xA655, 0xA656, 0xA657, 0xA658, 0xA659, + 0xA65A, 0xA65B, 0xA65C, 0xA65D, 0xA65E, 0xA65F, 0xA660, 0xA661, 0xA662, + 0xA663, 0xA664, 0xA665, 0xA666, 0xA667, 0xA668, 0xA669, 0xA66A, 0xA66B, + 0xA66C, 0xA66D, 0xA66E, 0xA66F, 0xA670, 0xA671, 0xA672, 0xA673, 0xA674, + 0xA675, 0xA676, 0xA677, 0xA678, 0xA679, 0xA67A, 0xA67B, 0xA67C, 0xA67D, + 0xA67E, 0xA680, 0xA681, 0xA682, 0xA683, 0xA684, 0xA685, 0xA686, 0xA687, + 0xA688, 0xA689, 0xA68A, 0xA68B, 0xA68C, 0xA68D, 0xA68E, 0xA68F, 0xA690, + 0xA691, 0xA692, 0xA693, 0xA694, 0xA695, 0xA696, 0xA697, 0xA698, 0xA699, + 0xA69A, 0xA69B, 0xA69C, 0xA69D, 0xA69E, 0xA69F, 0xA6A0, 0xA740, 0xA741, + 0xA742, 0xA743, 0xA744, 0xA745, 0xA746, 0xA747, 0xA748, 0xA749, 0xA74A, + 0xA74B, 0xA74C, 0xA74D, 0xA74E, 0xA74F, 0xA750, 0xA751, 0xA752, 0xA753, + 0xA754, 0xA755, 0xA756, 0xA757, 0xA758, 0xA759, 0xA75A, 0xA75B, 0xA75C, + 0xA75D, 0xA75E, 0xA75F, 0xA760, 0xA761, 0xA762, 0xA763, 0xA764, 0xA765, + 0xA766, 0xA767, 0xA768, 0xA769, 0xA76A, 0xA76B, 0xA76C, 0xA76D, 0xA76E, + 0xA76F, 0xA770, 0xA771, 0xA772, 0xA773, 0xA774, 0xA775, 0xA776, 0xA777, + 0xA778, 0xA779, 0xA77A, 0xA77B, 0xA77C, 0xA77D, 0xA77E, 0xA780, 0xA781, + 0xA782, 0xA783, 0xA784, 0xA785, 0xA786, 0xA787, 0xA788, 0xA789, 0xA78A, + 0xA78B, 0xA78C, 0xA78D, 0xA78E, 0xA78F, 0xA790, 0xA791, 0xA792, 0xA793, + 0xA794, 0xA795, 0xA796, 0xA797, 0xA798, 0xA799, 0xA79A, 0xA79B, 0xA79C, + 0xA79D, 0xA79E, 0xA79F, 0xA7A0, 0xA2AB, 0xA2AC, 0xA2AD, 0xA2AE, 0xA2AF, + 0xA2B0, 0x659D, 0xA2E4, 0xA2EF, 0xA2F0, 0xA2FD, 0xA2FE, 0xA4F4, 0xA4F5, + 0xA4F6, 0xA4F7, 0xA4F8, 0xA4F9, 0xA4FA, 0xA4FB, 0xA4FC, 0xA4FD, 0xA4FE, + 0xA5F7, 0xA5F8, 0xA5F9, 0xA5FA, 0xA5FB, 0xA5FC, 0xA5FD, 0xA5FE, 0xA6B9, + 0xA6BA, 0xA6BB, 0xA6BC, 0xA6BD, 0xA6BE, 0xA6BF, 0xA6C0, 0xA6D9, 0xA6DA, + 0xA6DB, 0xA6DC, 0xA6DD, 0xA6DE, 0xA6DF, 0xA6EC, 0xA6ED, 0xA6F3, 0xA6F6, + 0xA6F7, 0xA6F8, 0xA6F9, 0xA6FA, 0xA6FB, 0xA6FC, 0xA6FD, 0xA6FE, 0xA7C2, + 0xA7C3, 0xA7C4, 0xA7C5, 0xA7C6, 0xA7C7, 0xA7C8, 0xA7C9, 0xA7CA, 0xA7CB, + 0xA7CC, 0xA7CD, 0xA7CE, 0xA7CF, 0xA7D0, 0xA7F2, 0xA7F3, 0xA7F4, 0xA7F5, + 0xA7F6, 0xA7F7, 0xA7F8, 0xA7F9, 0xA7FA, 0xA7FB, 0xA7FC, 0xA7FD, 0xA7FE, + 0xA896, 0xA897, 0xA898, 0xA899, 0xA89A, 0xA89B, 0xA89C, 0xA89D, 0xA89E, + 0xA89F, 0xA8A0, 0x0001, 0x659E, 0xA8C1, 0xA8C2, 0xA8C3, 0xA8C4, 0xA8EA, + 0xA8EB, 0xA8EC, 0xA8ED, 0xA8EE, 0xA8EF, 0xA8F0, 0xA8F1, 0xA8F2, 0xA8F3, + 0xA8F4, 0xA8F5, 0xA8F6, 0xA8F7, 0xA8F8, 0xA8F9, 0xA8FA, 0xA8FB, 0xA8FC, + 0xA8FD, 0xA8FE, 0xA958, 0xA95B, 0xA95D, 0xA95E, 0xA95F, 0x659F, 0x65A0, + 0x65A1, 0x65A2, 0x65A3, 0x65A4, 0x65A5, 0x65A6, 0x65A7, 0x65A8, 0x65A9, + 0x65AA, 0x65AB, 0xA997, 0xA998, 0xA999, 0xA99A, 0xA99B, 0xA99C, 0xA99D, + 0xA99E, 0xA99F, 0xA9A0, 0xA9A1, 0xA9A2, 0xA9A3, 0xA9F0, 0xA9F1, 0xA9F2, + 0xA9F3, 0xA9F4, 0xA9F5, 0xA9F6, 0xA9F7, 0xA9F8, 0xA9F9, 0xA9FA, 0xA9FB, + 0xA9FC, 0xA9FD, 0xA9FE, 0xD7FA, 0xD7FB, 0xD7FC, 0xD7FD, 0xD7FE, 0x65AC, + 0xFE51, 0xFE52, 0xFE53, 0x65AD, 0x65AE, 0x65AF, 0x65B0, 0x65B1, 0xFE59, + 0x65B2, 0x65B3, 0x65B4, 0x65B5, 0x65B6, 0x65B7, 0x65B8, 0xFE61, 0x65B9, + 0x65BA, 0x65BB, 0x65BC, 0xFE66, 0xFE67, 0x65BD, 0x65BE, 0x65BF, 0x65C0, + 0xFE6C, 0xFE6D, 0x65C1, 0x65C2, 0x65C3, 0x65C4, 0x65C5, 0x65C6, 0x65C7, + 0x65C8, 0xFE76, 0x65C9, 0x65CA, 0x65CB, 0x65CC, 0x65CD, 0x65CE, 0x65CF, + 0xFE7E, 0x65D0, 0x65D1, 0x65D2, 0x65D3, 0x65D4, 0x65D5, 0x65D6, 0x65D7, + 0x65D8, 0x65D9, 0x65DA, 0x65DB, 0x65DC, 0x65DD, 0x65DE, 0x65DF, 0xFE90, + 0xFE91, 0x65E0, 0x65E1, 0x65E2, 0x65E3, 0x65E4, 0x65E5, 0x65E6, 0x65E7, + 0x65E8, 0x65E9, 0x65EA, 0x65EB, 0x65EC, 0x65ED, 0xFEA0, 0xFD9C, 0x76B5, + 0x76B6, 0x76B7, 0x76B8, 0x76B9, 0x76BA, 0x76BB, 0x76BC, 0x76BD, 0x76BE, + 0x76BF, 0x76C0, 0x76C1, 0x76C2, 0x76C3, 0x76C4, 0x76C5, 0x76C6, 0x76C7, + 0x76C8, 0x76C9, 0x76CA, 0x76CB, 0x76CC, 0x76CD, 0x76CE, 0x76CF, 0x76D0, + 0x76D1, 0x76D2, 0x76D3, 0x76D4, 0x76D5, 0x76D6, 0x76D7, 0x76D8, 0x76D9, + 0x76DA, 0x76DB, 0x76DC, 0x76DD, 0x76DE, 0x76DF, 0x76E0, 0x76E1, 0x76E2, + 0x76E3, 0x76E4, 0x76E5, 0x76E6, 0x76E7, 0x76E8, 0x76E9, 0x76EA, 0x76EB, + 0x76EC, 0x76ED, 0x76EE, 0x76EF, 0x76F0, 0x76F1, 0x76F2, 0x76F3, 0x76F4, + 0x76F5, 0x76F6, 0x76F7, 0x76F8, 0x76F9, 0x76FA, 0x76FB, 0x76FC, 0x76FD, + 0x76FE, 0x76FF, 0x7700, 0xFD9D, 0x7701, 0x7702, 0x7703, 0x7704, 0x7705, + 0x7706, 0x7707, 0x7708, 0x7709, 0x770A, 0x770B, 0x770C, 0x770D, 0x770E, + 0x770F, 0x7710, 0x7711, 0x7712, 0x7713, 0x7714, 0x7715, 0x7716, 0x7717, + 0x7718, 0x7719, 0x771A, 0x771B, 0xFD9E, 0x771C, 0x771D, 0x771E, 0x771F, + 0x7720, 0x7721, 0x7722, 0x7723, 0x7724, 0x7725, 0x7726, 0x7727, 0x7728, + 0x7729, 0x772A, 0x772B, 0x772C, 0x772D, 0x772E, 0x772F, 0x7730, 0x7731, + 0x7732, 0x7733, 0x7734, 0x7735, 0x7736, 0x7737, 0x7738, 0x7739, 0x773A, + 0x773B, 0x773C, 0x773D, 0x773E, 0x773F, 0x7740, 0x7741, 0x7742, 0x7743, + 0x7744, 0x7745, 0x7746, 0x7747, 0x7748, 0x7749, 0x774A, 0x774B, 0x774C, + 0x774D, 0x774E, 0x774F, 0x7750, 0x7751, 0x7752, 0x7753, 0x7754, 0x7755, + 0x7756, 0x7757, 0x7758, 0x7759, 0x775A, 0x775B, 0x775C, 0x775D, 0x775E, + 0x775F, 0x7760, 0x7761, 0x7762, 0x7763, 0x7764, 0x7765, 0x7766, 0x7767, + 0x7768, 0x7769, 0x776A, 0x776B, 0x776C, 0xFD9F, 0x776D, 0x776E, 0x776F, + 0x7770, 0x7771, 0x7772, 0x7773, 0x7774, 0x7775, 0xFDA0, 0x7776, 0x7777, + 0x7778, 0x7779, 0x777A, 0x777B, 0x777C, 0x777D, 0x777E, 0x777F, 0x7780, + 0x7781, 0x7782, 0x7783, 0x7784, 0x7785, 0x7786, 0x7787, 0x7788, 0x7789, + 0x778A, 0x778B, 0x778C, 0x778D, 0x778E, 0x778F, 0xFE40, 0xFE41, 0xFE42, + 0xFE43, 0x7790, 0xFE44, 0x7791, 0xFE45, 0xFE46, 0x7792, 0x7793, 0x7794, + 0xFE47, 0x7795, 0x7796, 0x7797, 0x7798, 0x7799, 0x779A, 0xFE48, 0xFE49, + 0xFE4A, 0x779B, 0xFE4B, 0xFE4C, 0x779C, 0x779D, 0xFE4D, 0xFE4E, 0xFE4F, + 0x779E, 0x779F, 0x77A0, 0x77A1, 0x77A2, 0x77A3, 0x77A4, 0x77A5, 0x77A6, + 0x77A7, 0x77A8, 0x77A9, 0x77AA, 0x77AB, 0x77AC, 0x77AD, 0x77AE, 0x77AF, + 0x77B0, 0x77B1, 0x77B2, 0x77B3, 0x77B4, 0x77B5, 0x77B6, 0x77B7, 0x77B8, + 0x77B9, 0x77BA, 0x77BB, 0x77BC, 0x77BD, 0x77BE, 0x77BF, 0x77C0, 0x77C1, + 0x77C2, 0x77C3, 0x77C4, 0x77C5, 0x77C6, 0x77C7, 0x77C8, 0x77C9, 0x77CA, + 0x77CB, 0x77CC, 0x77CD, 0x77CE, 0x77CF, 0x77D0, 0x77D1, 0x77D2, 0x77D3, + 0x77D4, 0x77D5, 0x77D6, 0x77D7, 0x77D8, 0x77D9, 0x77DA, 0x77DB, 0x77DC, + 0x77DD, 0x77DE, 0x77DF, 0x77E0, 0x77E1, 0x77E2, 0x77E3, 0x77E4, 0x77E5, + 0x77E6, 0x77E7, 0x77E8, 0x77E9, 0x77EA, 0x77EB, 0x77EC, 0x77ED, 0x77EE, + 0x77EF, 0x77F0, 0x77F1, 0x77F2, 0x77F3, 0x77F4, 0x77F5, 0x77F6, 0x77F7, + 0x77F8, 0x77F9, 0x77FA, 0x77FB, 0x77FC, 0x77FD, 0x77FE, 0x77FF, 0x7800, + 0x7801, 0x7802, 0x7803, 0x7804, 0x7805, 0x7806, 0x7807, 0x7808, 0x7809, + 0x780A, 0x780B, 0x780C, 0x780D, 0x780E, 0x780F, 0x7810, 0x7811, 0x7812, + 0x7813, 0x7814, 0x7815, 0x7816, 0x7817, 0x7818, 0x7819, 0x781A, 0x781B, + 0x781C, 0x781D, 0x781E, 0x781F, 0x7820, 0x7821, 0x7822, 0x7823, 0x7824, + 0x7825, 0x7826, 0x7827, 0x7828, 0x7829, 0x782A, 0x782B, 0x782C, 0x782D, + 0x782E, 0x782F, 0x7830, 0x7831, 0x7832, 0x7833, 0x7834, 0x7835, 0x7836, + 0x7837, 0x7838, 0x7839, 0x783A, 0x783B, 0x783C, 0x783D, 0x783E, 0x783F, + 0x7840, 0x7841, 0x7842, 0x7843, 0x7844, 0x7845, 0x7846, 0x7847, 0x7848, + 0x7849, 0x784A, 0x784B, 0x784C, 0x784D, 0x784E, 0x784F, 0x7850, 0x7851, + 0x7852, 0x7853, 0x7854, 0x7855, 0x7856, 0x7857, 0x7858, 0x7859, 0x785A, + 0x785B, 0x785C, 0x785D, 0x785E, 0x785F, 0x7860, 0x7861, 0x7862, 0x7863, + 0x7864, 0x7865, 0x7866, 0x7867, 0x7868, 0x7869, 0x786A, 0x786B, 0x786C, + 0x786D, 0x786E, 0x786F, 0x7870, 0x7871, 0x7872, 0x7873, 0x7874, 0x7875, + 0x7876, 0x7877, 0x7878, 0x7879, 0x787A, 0x787B, 0x787C, 0x787D, 0x787E, + 0x787F, 0x7880, 0x7881, 0x7882, 0x7883, 0x7884, 0x7885, 0x7886, 0x7887, + 0x7888, 0x7889, 0x788A, 0x788B, 0x788C, 0x788D, 0x788E, 0x788F, 0x7890, + 0x7891, 0x7892, 0x7893, 0x7894, 0x7895, 0x7896, 0x7897, 0x7898, 0x7899, + 0x789A, 0x789B, 0x789C, 0x789D, 0x789E, 0x789F, 0x78A0, 0x78A1, 0x78A2, + 0x78A3, 0x78A4, 0x78A5, 0x78A6, 0x78A7, 0x78A8, 0x78A9, 0x78AA, 0x78AB, + 0x78AC, 0x78AD, 0x78AE, 0x78AF, 0x78B0, 0x78B1, 0x78B2, 0x78B3, 0x78B4, + 0x78B5, 0x78B6, 0x78B7, 0x78B8, 0x78B9, 0x78BA, 0x78BB, 0x78BC, 0x78BD, + 0x78BE, 0x78BF, 0x78C0, 0x78C1, 0x78C2, 0x78C3, 0x78C4, 0x78C5, 0x78C6, + 0x78C7, 0x78C8, 0x78C9, 0x78CA, 0x78CB, 0x78CC, 0x78CD, 0x78CE, 0x78CF, + 0x78D0, 0x78D1, 0x78D2, 0x78D3, 0x78D4, 0x78D5, 0x78D6, 0x78D7, 0x78D8, + 0x78D9, 0x78DA, 0x78DB, 0x78DC, 0x78DD, 0x78DE, 0x78DF, 0x78E0, 0x78E1, + 0x78E2, 0x78E3, 0x78E4, 0x78E5, 0x78E6, 0x78E7, 0x78E8, 0x78E9, 0x78EA, + 0x78EB, 0x78EC, 0x78ED, 0x78EE, 0x78EF, 0x78F0, 0x78F1, 0x78F2, 0x78F3, + 0x78F4, 0x78F5, 0x78F6, 0x78F7, 0x78F8, 0x78F9, 0x78FA, 0x78FB, 0x78FC, + 0x78FD, 0x78FE, 0x78FF, 0x7900, 0x7901, 0x7902, 0x7903, 0x7904, 0x7905, + 0x7906, 0x7907, 0x7908, 0x7909, 0x790A, 0x790B, 0x790C, 0x790D, 0x790E, + 0x790F, 0x7910, 0x7911, 0x7912, 0x7913, 0x7914, 0x7915, 0x7916, 0x7917, + 0x7918, 0x7919, 0x791A, 0x791B, 0x791C, 0x791D, 0x791E, 0x791F, 0x7920, + 0x7921, 0x7922, 0x7923, 0x7924, 0x7925, 0x7926, 0x7927, 0x7928, 0x7929, + 0x792A, 0x792B, 0x792C, 0x792D, 0x792E, 0x792F, 0x7930, 0x7931, 0x7932, + 0x7933, 0x7934, 0x7935, 0x7936, 0x7937, 0x7938, 0x7939, 0x793A, 0x793B, + 0x793C, 0x793D, 0x793E, 0x793F, 0x7940, 0x7941, 0x7942, 0x7943, 0x7944, + 0x7945, 0x7946, 0x7947, 0x7948, 0x7949, 0x794A, 0x794B, 0x794C, 0x794D, + 0x794E, 0x794F, 0x7950, 0x7951, 0x7952, 0x7953, 0x7954, 0x7955, 0x7956, + 0x7957, 0x7958, 0x7959, 0x795A, 0x795B, 0x795C, 0x795D, 0x795E, 0x795F, + 0x7960, 0x7961, 0x7962, 0x7963, 0x7964, 0x7965, 0x7966, 0x7967, 0x7968, + 0x7969, 0x796A, 0x796B, 0x796C, 0x796D, 0x796E, 0x796F, 0x7970, 0x7971, + 0x7972, 0x7973, 0x7974, 0x7975, 0x7976, 0x7977, 0x7978, 0x7979, 0x797A, + 0x797B, 0x797C, 0x797D, 0x797E, 0x797F, 0x7980, 0x7981, 0x7982, 0x7983, + 0x7984, 0x7985, 0x7986, 0x7987, 0x7988, 0x7989, 0x798A, 0x798B, 0x798C, + 0x798D, 0x798E, 0x798F, 0x7990, 0x7991, 0x7992, 0x7993, 0x7994, 0x7995, + 0x7996, 0x7997, 0x7998, 0x7999, 0x799A, 0x799B, 0x799C, 0x799D, 0x799E, + 0x799F, 0x79A0, 0x79A1, 0x79A2, 0x79A3, 0x79A4, 0x79A5, 0x79A6, 0x79A7, + 0x79A8, 0x79A9, 0x79AA, 0x79AB, 0x79AC, 0x79AD, 0x79AE, 0x79AF, 0x79B0, + 0x79B1, 0x79B2, 0x79B3, 0x79B4, 0x79B5, 0x79B6, 0x79B7, 0x79B8, 0x79B9, + 0x79BA, 0x79BB, 0x79BC, 0x79BD, 0x79BE, 0x79BF, 0x79C0, 0x79C1, 0x79C2, + 0x79C3, 0x79C4, 0x79C5, 0x79C6, 0x79C7, 0x79C8, 0x79C9, 0x79CA, 0x79CB, + 0x79CC, 0x79CD, 0x79CE, 0x79CF, 0x79D0, 0x79D1, 0x79D2, 0x79D3, 0x79D4, + 0x79D5, 0x79D6, 0x79D7, 0x79D8, 0x79D9, 0x79DA, 0x79DB, 0x79DC, 0x79DD, + 0x79DE, 0x79DF, 0x79E0, 0x79E1, 0x79E2, 0x79E3, 0x79E4, 0x79E5, 0x79E6, + 0x79E7, 0x79E8, 0x79E9, 0x79EA, 0x79EB, 0x79EC, 0x79ED, 0x79EE, 0x79EF, + 0x79F0, 0x79F1, 0x79F2, 0x79F3, 0x79F4, 0x79F5, 0x79F6, 0x79F7, 0x79F8, + 0x79F9, 0x79FA, 0x79FB, 0x79FC, 0x79FD, 0x79FE, 0x79FF, 0x7A00, 0x7A01, + 0x7A02, 0x7A03, 0x7A04, 0x7A05, 0x7A06, 0x7A07, 0x7A08, 0x7A09, 0x7A0A, + 0x7A0B, 0x7A0C, 0x7A0D, 0x7A0E, 0x7A0F, 0x7A10, 0x7A11, 0x7A12, 0x7A13, + 0x7A14, 0x7A15, 0x7A16, 0x7A17, 0x7A18, 0x7A19, 0x7A1A, 0x7A1B, 0x7A1C, + 0x7A1D, 0x7A1E, 0x7A1F, 0x7A20, 0x7A21, 0x7A22, 0x7A23, 0x7A24, 0x7A25, + 0x7A26, 0x7A27, 0x7A28, 0x7A29, 0x7A2A, 0x7A2B, 0x7A2C, 0x7A2D, 0x7A2E, + 0x7A2F, 0x7A30, 0x7A31, 0x7A32, 0x7A33, 0x7A34, 0x7A35, 0x7A36, 0x7A37, + 0x7A38, 0x7A39, 0x7A3A, 0x7A3B, 0x7A3C, 0x7A3D, 0x7A3E, 0x7A3F, 0x7A40, + 0x7A41, 0x7A42, 0x7A43, 0x7A44, 0x7A45, 0x7A46, 0x7A47, 0x7A48, 0x7A49, + 0x7A4A, 0x7A4B, 0x7A4C, 0x7A4D, 0x7A4E, 0x7A4F, 0x7A50, 0x7A51, 0x7A52, + 0x7A53, 0x7A54, 0x7A55, 0x7A56, 0x7A57, 0x7A58, 0x7A59, 0x7A5A, 0x7A5B, + 0x7A5C, 0x7A5D, 0x7A5E, 0x7A5F, 0x7A60, 0x7A61, 0x7A62, 0x7A63, 0x7A64, + 0x7A65, 0x7A66, 0x7A67, 0x7A68, 0x7A69, 0x7A6A, 0x7A6B, 0x7A6C, 0x7A6D, + 0x7A6E, 0x7A6F, 0x7A70, 0x7A71, 0x7A72, 0x7A73, 0x7A74, 0x7A75, 0x7A76, + 0x7A77, 0x7A78, 0x7A79, 0x7A7A, 0x7A7B, 0x7A7C, 0x7A7D, 0x7A7E, 0x7A7F, + 0x7A80, 0x7A81, 0x7A82, 0x7A83, 0x7A84, 0x7A85, 0x7A86, 0x7A87, 0x7A88, + 0x7A89, 0x7A8A, 0x7A8B, 0x7A8C, 0x7A8D, 0x7A8E, 0x7A8F, 0x7A90, 0x7A91, + 0x7A92, 0x7A93, 0x7A94, 0x7A95, 0x7A96, 0x7A97, 0x7A98, 0x7A99, 0x7A9A, + 0x7A9B, 0x7A9C, 0x7A9D, 0x7A9E, 0x7A9F, 0x7AA0, 0x7AA1, 0x7AA2, 0x7AA3, + 0x7AA4, 0x7AA5, 0x7AA6, 0x7AA7, 0x7AA8, 0x7AA9, 0x7AAA, 0x7AAB, 0x7AAC, + 0x7AAD, 0x7AAE, 0x7AAF, 0x7AB0, 0x7AB1, 0x7AB2, 0x7AB3, 0x7AB4, 0x7AB5, + 0x7AB6, 0x7AB7, 0x7AB8, 0x7AB9, 0x7ABA, 0x7ABB, 0x7ABC, 0x7ABD, 0x7ABE, + 0x7ABF, 0x7AC0, 0x7AC1, 0x7AC2, 0x7AC3, 0x7AC4, 0x7AC5, 0x7AC6, 0x7AC7, + 0x7AC8, 0x7AC9, 0x7ACA, 0x7ACB, 0x7ACC, 0x7ACD, 0x7ACE, 0x7ACF, 0x7AD0, + 0x7AD1, 0x7AD2, 0x7AD3, 0x7AD4, 0x7AD5, 0x7AD6, 0x7AD7, 0x7AD8, 0x7AD9, + 0x7ADA, 0x7ADB, 0x7ADC, 0x7ADD, 0x7ADE, 0x7ADF, 0x7AE0, 0x7AE1, 0x7AE2, + 0x7AE3, 0x7AE4, 0x7AE5, 0x7AE6, 0x7AE7, 0x7AE8, 0x7AE9, 0x7AEA, 0x7AEB, + 0x7AEC, 0x7AED, 0x7AEE, 0x7AEF, 0x7AF0, 0x7AF1, 0x7AF2, 0x7AF3, 0x7AF4, + 0x7AF5, 0x7AF6, 0x7AF7, 0x7AF8, 0x7AF9, 0x7AFA, 0x7AFB, 0x7AFC, 0x7AFD, + 0x7AFE, 0x7AFF, 0x7B00, 0x7B01, 0x7B02, 0x7B03, 0x7B04, 0x7B05, 0x7B06, + 0x7B07, 0x7B08, 0x7B09, 0x7B0A, 0x7B0B, 0x7B0C, 0x7B0D, 0x7B0E, 0x7B0F, + 0x7B10, 0x7B11, 0x7B12, 0x7B13, 0x7B14, 0x7B15, 0x7B16, 0x7B17, 0x7B18, + 0x7B19, 0x7B1A, 0x7B1B, 0x7B1C, 0x7B1D, 0x7B1E, 0x7B1F, 0x7B20, 0x7B21, + 0x7B22, 0x7B23, 0x7B24, 0x7B25, 0x7B26, 0x7B27, 0x7B28, 0x7B29, 0x7B2A, + 0x7B2B, 0x7B2C, 0x7B2D, 0x7B2E, 0x7B2F, 0x7B30, 0x7B31, 0x7B32, 0x7B33, + 0x7B34, 0x7B35, 0x7B36, 0x7B37, 0x7B38, 0x7B39, 0x7B3A, 0x7B3B, 0x7B3C, + 0x7B3D, 0x7B3E, 0x7B3F, 0x7B40, 0x7B41, 0x7B42, 0x7B43, 0x7B44, 0x7B45, + 0x7B46, 0x7B47, 0x7B48, 0x7B49, 0x7B4A, 0x7B4B, 0x7B4C, 0x7B4D, 0x7B4E, + 0x7B4F, 0x7B50, 0x7B51, 0x7B52, 0x7B53, 0x7B54, 0x7B55, 0x7B56, 0x7B57, + 0x7B58, 0x7B59, 0x7B5A, 0x7B5B, 0x7B5C, 0x7B5D, 0x7B5E, 0x7B5F, 0x7B60, + 0x7B61, 0x7B62, 0x7B63, 0x7B64, 0x7B65, 0x7B66, 0x7B67, 0x7B68, 0x7B69, + 0x7B6A, 0x7B6B, 0x7B6C, 0x7B6D, 0x7B6E, 0x7B6F, 0x7B70, 0x7B71, 0x7B72, + 0x7B73, 0x7B74, 0x7B75, 0x7B76, 0x7B77, 0x7B78, 0x7B79, 0x7B7A, 0x7B7B, + 0x7B7C, 0x7B7D, 0x7B7E, 0x7B7F, 0x7B80, 0x7B81, 0x7B82, 0x7B83, 0x7B84, + 0x7B85, 0x7B86, 0x7B87, 0x7B88, 0x7B89, 0x7B8A, 0x7B8B, 0x7B8C, 0x7B8D, + 0x7B8E, 0x7B8F, 0x7B90, 0x7B91, 0x7B92, 0x7B93, 0x7B94, 0x7B95, 0x7B96, + 0x7B97, 0x7B98, 0x7B99, 0x7B9A, 0x7B9B, 0x7B9C, 0x7B9D, 0x7B9E, 0x7B9F, + 0x7BA0, 0x7BA1, 0x7BA2, 0x7BA3, 0xA955, 0xA6F2, 0x7BA4, 0xA6F4, 0xA6F5, + 0xA6E0, 0xA6E1, 0xA6F0, 0xA6F1, 0xA6E2, 0xA6E3, 0xA6EE, 0xA6EF, 0xA6E6, + 0xA6E7, 0xA6E4, 0xA6E5, 0xA6E8, 0xA6E9, 0xA6EA, 0xA6EB, 0x7BA5, 0x7BA6, + 0x7BA7, 0x7BA8, 0xA968, 0xA969, 0xA96A, 0xA96B, 0xA96C, 0xA96D, 0xA96E, + 0xA96F, 0xA970, 0xA971, 0x7BA9, 0xA972, 0xA973, 0xA974, 0xA975, 0x7BAA, + 0xA976, 0xA977, 0xA978, 0xA979, 0xA97A, 0xA97B, 0xA97C, 0xA97D, 0xA97E, + 0xA980, 0xA981, 0xA982, 0xA983, 0xA984, 0x7BAB, 0xA985, 0xA986, 0xA987, + 0xA988, 0x7BAC, 0x7BAD, 0x7BAE, 0x7BAF, 0x7BB0, 0x7BB1, 0x7BB2, 0x7BB3, + 0x7BB4, 0x7BB5, 0x7BB6, 0x7BB7, 0x7BB8, 0x7BB9, 0x7BBA, 0x7BBB, 0x7BBC, + 0x7BBD, 0x7BBE, 0x7BBF, 0x7BC0, 0x7BC1, 0x7BC2, 0x7BC3, 0x7BC4, 0x7BC5, + 0x7BC6, 0x7BC7, 0x7BC8, 0x7BC9, 0x7BCA, 0x7BCB, 0x7BCC, 0x7BCD, 0x7BCE, + 0x7BCF, 0x7BD0, 0x7BD1, 0x7BD2, 0x7BD3, 0x7BD4, 0x7BD5, 0x7BD6, 0x7BD7, + 0x7BD8, 0x7BD9, 0x7BDA, 0x7BDB, 0x7BDC, 0x7BDD, 0x7BDE, 0x7BDF, 0x7BE0, + 0x7BE1, 0x7BE2, 0x7BE3, 0x7BE4, 0x7BE5, 0x7BE6, 0x7BE7, 0x7BE8, 0x7BE9, + 0x7BEA, 0x7BEB, 0x7BEC, 0x7BED, 0x7BEE, 0x7BEF, 0x7BF0, 0x7BF1, 0x7BF2, + 0x7BF3, 0x7BF4, 0x7BF5, 0x7BF6, 0x7BF7, 0x7BF8, 0x7BF9, 0x7BFA, 0x7BFB, + 0x7BFC, 0x7BFD, 0x7BFE, 0x7BFF, 0x7C00, 0x7C01, 0x7C02, 0x7C03, 0x7C04, + 0x7C05, 0x7C06, 0x7C07, 0x7C08, 0x7C09, 0x7C0A, 0x7C0B, 0x7C0C, 0x7C0D, + 0x7C0E, 0x7C0F, 0x7C10, 0x7C11, 0x7C12, 0x7C13, 0x7C14, 0x7C15, 0x7C16, + 0x7C17, 0x7C18, 0x7C19, 0x7C1A, 0x7C1B, 0x7C1C, 0x7C1D, 0x7C1E, 0x7C1F, + 0x7C20, 0x7C21, 0x7C22, 0x7C23, 0x7C24, 0x7C25, 0x7C26, 0x7C27, 0x7C28, + 0x7C29, 0x7C2A, 0x7C2B, 0x7C2C, 0x7C2D, 0x7C2E, 0x7C2F, 0x7C30, 0x7C31, + 0x7C32, 0x7C33, 0x7C34, 0x7C35, 0x7C36, 0x7C37, 0x7C38, 0x7C39, 0x7C3A, + 0x7C3B, 0x7C3C, 0x7C3D, 0x7C3E, 0x7C3F, 0x7C40, 0xA3A1, 0xA3A2, 0xA3A3, + 0xA1E7, 0xA3A5, 0xA3A6, 0xA3A7, 0xA3A8, 0xA3A9, 0xA3AA, 0xA3AB, 0xA3AC, + 0xA3AD, 0xA3AE, 0xA3AF, 0xA3B0, 0xA3B1, 0xA3B2, 0xA3B3, 0xA3B4, 0xA3B5, + 0xA3B6, 0xA3B7, 0xA3B8, 0xA3B9, 0xA3BA, 0xA3BB, 0xA3BC, 0xA3BD, 0xA3BE, + 0xA3BF, 0xA3C0, 0xA3C1, 0xA3C2, 0xA3C3, 0xA3C4, 0xA3C5, 0xA3C6, 0xA3C7, + 0xA3C8, 0xA3C9, 0xA3CA, 0xA3CB, 0xA3CC, 0xA3CD, 0xA3CE, 0xA3CF, 0xA3D0, + 0xA3D1, 0xA3D2, 0xA3D3, 0xA3D4, 0xA3D5, 0xA3D6, 0xA3D7, 0xA3D8, 0xA3D9, + 0xA3DA, 0xA3DB, 0xA3DC, 0xA3DD, 0xA3DE, 0xA3DF, 0xA3E0, 0xA3E1, 0xA3E2, + 0xA3E3, 0xA3E4, 0xA3E5, 0xA3E6, 0xA3E7, 0xA3E8, 0xA3E9, 0xA3EA, 0xA3EB, + 0xA3EC, 0xA3ED, 0xA3EE, 0xA3EF, 0xA3F0, 0xA3F1, 0xA3F2, 0xA3F3, 0xA3F4, + 0xA3F5, 0xA3F6, 0xA3F7, 0xA3F8, 0xA3F9, 0xA3FA, 0xA3FB, 0xA3FC, 0xA3FD, + 0xA1AB, 0x7C41, 0x7C42, 0x7C43, 0x7C44, 0x7C45, 0x7C46, 0x7C47, 0x7C48, + 0x7C49, 0x7C4A, 0x7C4B, 0x7C4C, 0x7C4D, 0x7C4E, 0x7C4F, 0x7C50, 0x7C51, + 0x7C52, 0x7C53, 0x7C54, 0x7C55, 0x7C56, 0x7C57, 0x7C58, 0x7C59, 0x7C5A, + 0x7C5B, 0x7C5C, 0x7C5D, 0x7C5E, 0x7C5F, 0x7C60, 0x7C61, 0x7C62, 0x7C63, + 0x7C64, 0x7C65, 0x7C66, 0x7C67, 0x7C68, 0x7C69, 0x7C6A, 0x7C6B, 0x7C6C, + 0x7C6D, 0x7C6E, 0x7C6F, 0x7C70, 0x7C71, 0x7C72, 0x7C73, 0x7C74, 0x7C75, + 0x7C76, 0x7C77, 0x7C78, 0x7C79, 0x7C7A, 0x7C7B, 0x7C7C, 0x7C7D, 0x7C7E, + 0x7C7F, 0x7C80, 0x7C81, 0x7C82, 0x7C83, 0x7C84, 0x7C85, 0x7C86, 0x7C87, + 0x7C88, 0x7C89, 0x7C8A, 0x7C8B, 0x7C8C, 0x7C8D, 0x7C8E, 0x7C8F, 0x7C90, + 0x7C91, 0x7C92, 0x7C93, 0x7C94, 0x7C95, 0x7C96, 0x7C97, 0x7C98, 0x7C99, + 0x7C9A, 0x7C9B, 0x7C9C, 0x7C9D, 0x7C9E, 0x7C9F, 0x7CA0, 0x7CA1, 0x7CA2, + 0x7CA3, 0x7CA4, 0x7CA5, 0x7CA6, 0x7CA7, 0x7CA8, 0x7CA9, 0x7CAA, 0x7CAB, + 0x7CAC, 0x7CAD, 0x7CAE, 0x7CAF, 0x7CB0, 0x7CB1, 0x7CB2, 0x7CB3, 0x7CB4, + 0x7CB5, 0x7CB6, 0x7CB7, 0x7CB8, 0x7CB9, 0x7CBA, 0x7CBB, 0x7CBC, 0x7CBD, + 0x7CBE, 0x7CBF, 0x7CC0, 0x7CC1, 0xA1E9, 0xA1EA, 0xA956, 0xA3FE, 0xA957, + 0xA3A4, 0x7CC2, 0x7CC3, 0x7CC4, 0x7CC5, 0x7CC6, 0x7CC7, 0x7CC8, 0x7CC9, + 0x7CCA, 0x7CCB, 0x7CCC, 0x7CCD, 0x7CCE, 0x7CCF, 0x7CD0, 0x7CD1, 0x7CD2, + 0x7CD3, 0x7CD4, 0x7CD5, 0x7CD6, 0x7CD7, 0x7CD8, 0x7CD9, 0x7CDA, 0x7CDB}; + +static const uint16_t gb18030_2_weight_py[] = { + 15308, 26403, 32018, 10022, 20221, 3853, 26996, 6117, 24523, 17600, 36813, + 1796, 14235, 12424, 13777, 9402, 2763, 40603, 9858, 14080, 7905, 35363, + 35610, 31400, 14287, 35292, 36111, 11015, 3298, 36190, 34284, 8336, 14288, + 32020, 11032, 6317, 26965, 21034, 12685, 14582, 26905, 19601, 10824, 40703, + 33915, 34465, 8093, 26086, 20856, 8385, 28328, 36968, 4806, 39018, 39657, + 9512, 8396, 19021, 17937, 35820, 14815, 19318, 27011, 36944, 27705, 28174, + 8788, 34234, 23228, 34238, 28437, 35289, 32493, 14027, 35178, 36898, 5148, + 17412, 6746, 19824, 12251, 12677, 30443, 390, 1744, 7812, 25865, 1745, + 32053, 30025, 10612, 8417, 1875, 3032, 2888, 26413, 25300, 12799, 3033, + 23732, 31078, 35007, 7689, 2319, 30446, 5510, 39874, 22268, 36947, 5891, + 6633, 31310, 35627, 33157, 12254, 67, 13926, 22418, 5132, 7834, 28854, + 4747, 4087, 3046, 32312, 34098, 33161, 38316, 32145, 21796, 21264, 32938, + 33589, 40060, 24677, 999, 22419, 35641, 27710, 35547, 39233, 9928, 19345, + 40270, 2093, 24678, 1114, 38824, 4422, 34815, 38692, 1160, 32059, 24761, + 27141, 836, 11661, 10459, 32470, 8674, 7190, 20501, 1797, 10524, 11958, + 9570, 24923, 4440, 33251, 26579, 30035, 8302, 16241, 35382, 9450, 36052, + 20077, 33597, 140, 18699, 7066, 19055, 2584, 3402, 34101, 39979, 25542, + 4817, 27715, 38038, 28542, 21673, 13890, 14207, 3378, 39183, 41281, 3859, + 18877, 14460, 27346, 29530, 26697, 29946, 1888, 20980, 32580, 29935, 37138, + 31785, 33547, 9484, 15682, 31258, 35693, 8099, 17572, 11918, 14121, 23841, + 25892, 22266, 31436, 8100, 31944, 33371, 5650, 3048, 39870, 16242, 27774, + 11989, 32748, 13106, 1606, 3984, 7498, 34245, 892, 37237, 33118, 11019, + 2865, 39391, 1800, 14322, 34927, 4752, 17397, 30330, 16243, 2324, 40974, + 8769, 29294, 27227, 19842, 28650, 4193, 33295, 22346, 23147, 8458, 14127, + 28121, 13647, 7399, 39458, 40890, 19058, 27784, 16841, 11919, 6133, 40859, + 981, 31260, 14609, 20943, 2192, 12988, 35117, 26144, 24201, 36306, 3251, + 12864, 25646, 39954, 4283, 30676, 37153, 1804, 29069, 34605, 7709, 28857, + 31088, 6915, 3060, 26776, 15205, 5660, 2503, 899, 32964, 11480, 35028, + 38698, 3861, 34294, 36756, 33565, 38377, 4353, 8174, 1080, 39658, 20235, + 12296, 35570, 32965, 34050, 2170, 6474, 2413, 39078, 29675, 900, 37977, + 13654, 30677, 27914, 39690, 27992, 31923, 37642, 25474, 21810, 37910, 13267, + 19294, 5732, 28791, 10270, 13665, 31492, 26308, 23848, 14880, 2326, 3998, + 25868, 910, 32756, 36634, 34937, 28747, 28298, 34830, 7157, 1806, 12717, + 38043, 9244, 2230, 16740, 36548, 38154, 40955, 1018, 27823, 4095, 37171, + 38561, 41057, 26371, 4167, 14150, 10086, 38748, 24358, 34624, 5683, 32990, + 18505, 912, 22744, 13898, 17528, 18736, 19379, 23669, 32093, 28750, 36413, + 6207, 40425, 26313, 24049, 14225, 29940, 41219, 23073, 16559, 2936, 9462, + 23170, 3260, 2692, 30711, 12159, 1857, 11768, 4114, 29438, 5197, 13449, + 7664, 32371, 14494, 6966, 17963, 1938, 9233, 32428, 32372, 20448, 35207, + 13977, 12839, 24105, 7728, 40097, 96, 25844, 35489, 15081, 21727, 2699, + 35875, 5310, 15768, 13028, 4020, 13456, 26138, 38048, 2316, 1704, 185, + 28574, 3820, 2629, 16345, 21283, 13914, 23864, 19866, 31291, 21644, 24493, + 21284, 2916, 17815, 18908, 15848, 822, 37378, 1557, 38076, 39503, 27769, + 36698, 10228, 3225, 3227, 17246, 29023, 30738, 18461, 3959, 2720, 25200, + 27273, 11844, 17313, 19124, 38080, 21863, 28868, 34569, 16714, 21054, 38053, + 33319, 6551, 6552, 29838, 2890, 7065, 7067, 13846, 34472, 26974, 0, + 23649, 7572, 19563, 26609, 6229, 0, 17047, 11541, 30444, 21183, 17604, + 36970, 10145, 29227, 7568, 12554, 35821, 19615, 25171, 37528, 19598, 2403, + 14185, 9284, 14200, 19620, 40068, 9040, 33561, 36109, 15198, 35373, 19994, + 27028, 19847, 14611, 15599, 17874, 8176, 32930, 20155, 28550, 8488, 11044, + 22093, 7913, 20422, 23584, 12852, 27347, 19750, 29765, 9217, 14128, 24418, + 6198, 8459, 36067, 35449, 17155, 4180, 20506, 40564, 4710, 27647, 6702, + 13978, 17940, 31579, 6367, 7229, 7230, 14373, 3945, 39357, 7690, 20833, + 39869, 7691, 7696, 15145, 8397, 22878, 15749, 9965, 25297, 4133, 12085, + 23837, 4822, 12089, 5134, 30299, 14823, 16847, 7914, 24880, 14374, 20423, + 17997, 39877, 1644, 13618, 13619, 26205, 2759, 8796, 4177, 15897, 6757, + 7135, 13627, 4442, 14090, 18494, 19155, 38233, 37478, 4870, 15425, 26088, + 4178, 4872, 16853, 7499, 2768, 23246, 4179, 40860, 8502, 1837, 6673, + 24377, 6323, 13109, 12513, 34289, 11946, 6690, 6475, 31153, 9292, 26797, + 13114, 4938, 15146, 4181, 4081, 2782, 29863, 18737, 16879, 22405, 26228, + 15582, 9267, 11220, 38387, 40699, 17429, 14650, 18240, 9647, 13457, 9648, + 13144, 13145, 28772, 12601, 13158, 13159, 39808, 2721, 13072, 20556, 16996, + 40262, 34225, 13927, 15504, 32818, 39529, 35643, 40128, 20576, 16544, 14751, + 15591, 34755, 30179, 32746, 20705, 15810, 13629, 17765, 15426, 13936, 8603, + 20428, 3578, 16464, 36621, 15427, 14754, 24378, 18708, 2110, 3586, 15171, + 20237, 6201, 33629, 31403, 35752, 33996, 31013, 26802, 16555, 18738, 22745, + 27083, 12145, 13303, 2982, 25018, 32543, 35854, 14907, 7209, 14717, 29619, + 14651, 5115, 19356, 34002, 34004, 18945, 17208, 3111, 25201, 25022, 37819, + 14241, 790, 30908, 1391, 8337, 8338, 36037, 22312, 14376, 28930, 8675, + 6908, 8900, 4939, 14327, 24441, 21109, 14307, 35366, 13288, 15292, 10825, + 24679, 1460, 24142, 38120, 15813, 10842, 37155, 9591, 11753, 5109, 9646, + 17421, 17430, 28106, 6369, 14362, 14973, 31770, 15338, 34473, 24700, 34096, + 21418, 41041, 27005, 31771, 30389, 30390, 32824, 5088, 12297, 27454, 15850, + 31426, 32955, 13608, 248, 24442, 26466, 3518, 33599, 25043, 31327, 12278, + 6917, 31516, 25907, 30656, 38918, 10023, 34211, 5605, 38456, 22136, 34182, + 10334, 34187, 39617, 22139, 29064, 26524, 29466, 41140, 7500, 2414, 37551, + 17158, 5733, 13899, 291, 9608, 34632, 17171, 2937, 16341, 17187, 34408, + 34555, 37614, 8872, 17870, 25503, 24877, 7102, 16728, 6319, 40375, 2223, + 2224, 2227, 90, 5059, 27155, 9330, 430, 25736, 27012, 40597, 12802, + 27910, 8604, 30784, 25713, 4574, 9285, 24567, 3513, 17710, 10568, 20319, + 19474, 33724, 40812, 4825, 35152, 21946, 11945, 35297, 3854, 24319, 13780, + 2094, 6820, 10616, 31184, 21164, 33950, 6223, 10569, 8601, 15050, 18875, + 8672, 19687, 23401, 31187, 13504, 10570, 3516, 26733, 29964, 30989, 6893, + 26828, 14729, 22307, 30951, 19245, 25136, 5610, 27019, 40061, 29447, 31778, + 35668, 23457, 22842, 40826, 33557, 35669, 32577, 4925, 24881, 9962, 30036, + 23030, 1646, 7920, 34722, 10335, 9862, 4896, 30217, 41308, 2096, 28543, + 32316, 11986, 23464, 7136, 6898, 31786, 40069, 27348, 32747, 15722, 11270, + 28932, 6899, 33825, 9736, 16592, 29584, 33326, 36879, 6040, 21434, 33313, + 7566, 10258, 37543, 18475, 23031, 19492, 41047, 10357, 32333, 16548, 1839, + 17622, 411, 20321, 17777, 28122, 7957, 10056, 27572, 36891, 9086, 9144, + 956, 9974, 35726, 12759, 29731, 32153, 30331, 17122, 24594, 3050, 38199, + 34214, 6226, 23410, 5552, 24326, 20599, 8969, 6259, 24886, 17606, 16539, + 26091, 41268, 31042, 13950, 23483, 7079, 23979, 191, 38235, 21423, 36930, + 29299, 16290, 31468, 30, 21770, 40611, 5661, 10533, 2193, 32438, 29967, + 31263, 30979, 26146, 9149, 23414, 23415, 5179, 35187, 40840, 1132, 4761, + 10369, 34216, 23418, 38948, 17607, 32172, 36309, 9303, 39019, 9851, 19096, + 34296, 5662, 24937, 2770, 14470, 28793, 182, 5187, 37269, 38956, 40001, + 2623, 30249, 37248, 37980, 34897, 20240, 10921, 37876, 11405, 11406, 12129, + 39927, 30595, 26153, 33638, 11485, 6693, 21523, 17626, 37270, 25935, 3415, + 24048, 34613, 5102, 22309, 2228, 36541, 30526, 36401, 2076, 31810, 13666, + 38209, 11089, 29086, 34946, 10469, 23903, 26007, 36549, 10707, 32857, 19320, + 2507, 9910, 25612, 30190, 12146, 22158, 31159, 23816, 40729, 19206, 30234, + 0, 28344, 39480, 25841, 8773, 20850, 23985, 1249, 294, 17414, 41146, + 38912, 20626, 28724, 13525, 3688, 13357, 15147, 28752, 26236, 35, 32627, + 18581, 32628, 10865, 11769, 9750, 21953, 32094, 38252, 2906, 22935, 5422, + 19301, 10940, 8289, 28770, 35159, 25848, 13526, 32766, 11145, 19339, 25152, + 16562, 32770, 12168, 16004, 32639, 10222, 8127, 24052, 4021, 2792, 5202, + 34128, 6875, 41221, 7210, 3430, 11633, 38073, 4154, 4649, 5198, 37341, + 29970, 31560, 23519, 10216, 17431, 33509, 11636, 36166, 34071, 21549, 27655, + 34538, 36516, 4911, 38602, 40103, 21730, 11795, 33018, 13537, 37656, 26, + 36566, 15772, 37189, 22298, 5396, 10567, 6613, 5249, 33202, 22585, 36103, + 41168, 21648, 5579, 16444, 28413, 11951, 32036, 35241, 6684, 22623, 3824, + 12616, 13995, 2917, 34145, 19683, 29212, 18674, 11826, 1988, 36701, 21571, + 36175, 11115, 19685, 10601, 38996, 16950, 18265, 9927, 21035, 20545, 34675, + 17268, 18612, 18397, 20550, 5230, 3229, 22799, 22590, 32558, 20551, 31887, + 6753, 15705, 34420, 2727, 36364, 5784, 16239, 28523, 32678, 4338, 11294, + 12062, 40447, 21589, 32679, 2167, 16978, 2827, 2644, 17328, 36000, 19099, + 37998, 27959, 31762, 38335, 12967, 37999, 40263, 16387, 21601, 16433, 18354, + 11657, 36046, 21617, 29859, 15294, 37475, 14202, 22646, 37822, 4475, 11660, + 6821, 9771, 29559, 29762, 9773, 25112, 25376, 9774, 28544, 9777, 36129, + 11920, 9975, 19061, 9779, 4093, 30596, 37552, 24909, 15648, 8197, 37562, + 37563, 34270, 29787, 29802, 29803, 29864, 19036, 11782, 35905, 18981, 18999, + 34227, 29833, 29525, 23104, 18694, 15784, 34147, 37215, 23625, 23626, 40589, + 5289, 23583, 32049, 26363, 21497, 20577, 12748, 39535, 33991, 35645, 24291, + 19688, 25465, 29982, 978, 1164, 14085, 5641, 14019, 12478, 5606, 14020, + 625, 28766, 24685, 39370, 9300, 28554, 14187, 34816, 7813, 18700, 24526, + 9033, 33952, 433, 18000, 40277, 8152, 10829, 39618, 355, 5015, 22180, + 20465, 12495, 10461, 18919, 4372, 3521, 36053, 10801, 6522, 38862, 7940, + 9454, 34922, 6717, 9576, 2533, 34759, 32827, 27167, 1824, 10630, 4988, + 15120, 5293, 10191, 188, 33206, 32334, 653, 7853, 471, 35728, 36257, + 10057, 33616, 4194, 24241, 1035, 7381, 25044, 36624, 15056, 12703, 5653, + 16522, 14732, 13854, 38936, 17779, 11244, 2112, 14189, 35156, 5623, 34164, + 24938, 28186, 24352, 30335, 14620, 19082, 39241, 15543, 3740, 6135, 28745, + 2209, 3991, 1036, 15207, 6722, 35753, 39463, 40558, 23260, 14621, 21226, + 15440, 16040, 21323, 12865, 8507, 37251, 6918, 9220, 16842, 7413, 34194, + 16110, 219, 26725, 21113, 29742, 3325, 11893, 1226, 17529, 9742, 40418, + 766, 37002, 19569, 13574, 25630, 35190, 8855, 40896, 37003, 11486, 6934, + 34939, 806, 4379, 19707, 2934, 30094, 36264, 7763, 39956, 13812, 13858, + 10564, 8515, 4227, 12999, 22902, 16821, 32537, 11465, 6496, 30279, 33737, + 12543, 12325, 15762, 36414, 36641, 15150, 28000, 26935, 20135, 31015, 3340, + 29788, 25060, 39930, 17173, 39931, 699, 38147, 6528, 29268, 31356, 39336, + 33998, 39200, 82, 8904, 34387, 15213, 30887, 32991, 18329, 9926, 16513, + 2907, 22356, 1060, 3181, 18748, 18659, 21918, 23857, 19723, 20627, 40385, + 27498, 18548, 1539, 2432, 39741, 38752, 15237, 5815, 3204, 39486, 31830, + 9746, 23971, 13969, 5693, 4713, 34633, 28424, 38337, 23766, 30881, 40525, + 24012, 26317, 26318, 455, 23076, 15769, 6169, 7256, 25076, 6609, 41205, + 5694, 26809, 6788, 6791, 28670, 5488, 20748, 7618, 11500, 28671, 4991, + 35197, 40361, 13213, 370, 23951, 24017, 15493, 35906, 22541, 5822, 13244, + 35162, 33931, 28678, 16412, 14660, 11274, 5319, 25217, 23872, 34007, 32396, + 31755, 99, 34176, 5367, 25637, 14017, 16753, 15875, 18613, 34421, 28696, + 30748, 11276, 18463, 18464, 25718, 17269, 17919, 2862, 34018, 34438, 16715, + 493, 30291, 25905, 40471, 35299, 19346, 40285, 40475, 10912, 16083, 10922, + 33640, 16089, 27191, 19530, 41206, 27192, 35337, 9127, 13289, 7758, 38572, + 1474, 28115, 25111, 18001, 4874, 33357, 33104, 21094, 32045, 37628, 19600, + 6668, 24374, 30263, 9042, 23492, 19970, 19972, 3206, 38296, 9329, 8573, + 28885, 28590, 34458, 1112, 11198, 37867, 12688, 396, 7047, 5513, 22207, + 14750, 32828, 5764, 34876, 11388, 15123, 38372, 972, 11560, 7464, 5856, + 34115, 1008, 360, 31014, 9857, 31357, 362, 13270, 17422, 6701, 37807, + 13271, 27106, 7667, 12027, 1347, 18982, 6755, 6068, 23627, 14289, 21831, + 2580, 32056, 7309, 12429, 10614, 5082, 7837, 14116, 9898, 30974, 39879, + 21976, 15508, 39945, 37823, 7823, 3666, 37693, 40453, 34589, 20867, 33108, + 7593, 7692, 30393, 6429, 434, 40598, 38827, 20940, 37631, 29700, 32149, + 39454, 6808, 20579, 1173, 26581, 6809, 10338, 33558, 7164, 39234, 20372, + 627, 7839, 18002, 40817, 25174, 26208, 34723, 19374, 40710, 14587, 25322, + 6188, 12280, 8307, 32526, 11157, 14701, 9038, 12858, 12859, 21422, 39457, + 12108, 32325, 10539, 9455, 15024, 15712, 34594, 20502, 17768, 22277, 6903, + 36881, 34359, 26588, 26919, 9577, 24927, 27780, 10631, 32335, 26472, 3300, + 32957, 19493, 7854, 19698, 15434, 4311, 4312, 29532, 33261, 20983, 36982, + 23012, 21172, 39639, 9976, 40456, 22788, 29948, 32336, 31191, 34360, 31265, + 15, 34366, 36983, 27725, 17391, 14398, 40512, 23153, 32160, 40612, 6136, + 18714, 50, 6811, 18499, 20191, 4552, 23032, 14471, 2171, 18031, 32600, + 27283, 23416, 11608, 7328, 31065, 25676, 28653, 7420, 7554, 29232, 21227, + 24940, 14124, 14034, 23657, 5798, 33299, 11077, 30276, 16249, 36078, 3764, + 21143, 8178, 19062, 220, 16041, 36137, 34249, 14399, 17140, 5769, 32161, + 11245, 11209, 5298, 35030, 21028, 4313, 12810, 29676, 37272, 30597, 5674, + 25508, 19755, 5103, 25649, 24214, 11609, 31093, 23754, 4228, 20282, 8182, + 13771, 6476, 35466, 39957, 11487, 20193, 152, 36311, 33738, 13575, 30529, + 39265, 24535, 27069, 32980, 30142, 17531, 19644, 25186, 27635, 22649, 30791, + 30188, 14330, 10923, 24202, 767, 33481, 29677, 9522, 3909, 34947, 37565, + 25400, 25613, 18227, 19759, 22062, 340, 19248, 15995, 24256, 39087, 37566, + 13576, 25408, 20482, 36321, 28004, 21454, 28903, 22144, 16473, 21118, 741, + 22608, 35856, 37317, 33804, 19372, 35328, 15260, 36556, 21332, 9532, 13902, + 40386, 38253, 9942, 16620, 38913, 11095, 11096, 363, 21199, 19323, 22770, + 9109, 31280, 24053, 30148, 38664, 19576, 32188, 32189, 20645, 17666, 17432, + 11228, 9538, 5459, 39494, 33511, 35333, 11214, 31561, 16005, 25236, 34640, + 2700, 13362, 19763, 7348, 7211, 32106, 35907, 11797, 13538, 8233, 27116, + 28205, 23952, 17508, 11338, 33142, 21461, 6170, 35908, 2232, 100, 21436, + 21649, 19250, 29415, 3825, 13996, 4404, 37071, 22795, 25439, 25575, 20948, + 34329, 28579, 36350, 2267, 37749, 20203, 1395, 26688, 33311, 21354, 6372, + 18320, 37518, 16420, 34676, 18118, 13491, 21437, 16422, 23714, 36365, 27479, + 11848, 24979, 20101, 16988, 18983, 34439, 40224, 16428, 14818, 19247, 33165, + 27718, 28545, 36917, 40401, 28264, 20322, 4553, 23658, 34165, 21279, 40743, + 16904, 33932, 2043, 20932, 21576, 36366, 18984, 25463, 24444, 29724, 25538, + 35009, 35375, 14086, 40548, 40236, 10624, 26914, 35420, 29404, 26975, 3301, + 25121, 8893, 32586, 38493, 760, 26664, 11558, 20120, 15600, 2194, 38067, + 37485, 24353, 25050, 39083, 13124, 21634, 1807, 11322, 24299, 26931, 21635, + 13960, 21637, 39720, 37172, 769, 15787, 21638, 14640, 24305, 10866, 26941, + 21640, 26676, 30718, 32932, 15788, 11783, 15089, 35936, 35509, 782, 24229, + 3747, 784, 7742, 18917, 6555, 22949, 40378, 7855, 15435, 13230, 40381, + 34054, 27369, 6570, 5364, 13610, 7103, 7104, 27213, 26405, 20698, 17741, + 32264, 32265, 16111, 30430, 17735, 19480, 30435, 30432, 30433, 34918, 6763, + 15990, 39928, 8398, 9156, 29914, 8411, 8412, 31774, 1078, 13791, 29248, + 5885, 26833, 39139, 32959, 21221, 31453, 30671, 19418, 18563, 22860, 29223, + 7506, 32981, 18899, 2474, 33019, 14674, 14813, 17688, 14963, 27332, 31901, + 21306, 30244, 32054, 17076, 6883, 5418, 11860, 18356, 25304, 31311, 10048, + 26574, 3881, 25305, 37694, 604, 35010, 249, 31315, 13623, 6886, 7594, + 30306, 23733, 23225, 13784, 41278, 41279, 34817, 14588, 8494, 33917, 22909, + 17093, 29367, 24688, 7922, 30070, 22489, 356, 15856, 24689, 22963, 29368, + 18003, 3459, 22901, 10054, 33432, 29578, 33918, 1521, 10345, 406, 19187, + 6904, 8161, 5942, 18703, 7055, 7070, 8308, 24902, 35402, 20759, 26920, + 141, 30580, 11313, 20118, 17025, 12498, 29585, 30581, 36883, 9242, 17026, + 34924, 13336, 6827, 32829, 2055, 25114, 7705, 21073, 17029, 36746, 32337, + 10644, 5353, 26596, 3302, 29767, 8827, 10259, 31952, 36131, 37149, 16523, + 15236, 32249, 25045, 3721, 28451, 17878, 11205, 14402, 16250, 20386, 16042, + 16043, 41050, 9221, 34195, 8527, 19063, 19064, 16826, 6676, 39254, 36139, + 6137, 9981, 39255, 30678, 22511, 13657, 41051, 15646, 6138, 36140, 40885, + 38311, 11488, 37004, 34777, 7717, 24622, 34778, 29072, 35574, 39695, 27070, + 6936, 40313, 15190, 18926, 34493, 19756, 9991, 12132, 11407, 29496, 31348, + 37005, 40898, 16333, 15410, 34377, 34378, 30686, 40899, 2544, 28190, 15479, + 24215, 29225, 29789, 6530, 31521, 31017, 2328, 5302, 25409, 13680, 15151, + 18228, 31358, 23998, 1019, 5734, 23817, 36642, 21535, 4846, 27147, 25758, + 27828, 40912, 13306, 17657, 15262, 2787, 5988, 2450, 6076, 29748, 18550, + 38655, 38656, 295, 2366, 24719, 23908, 4715, 41159, 5361, 5362, 31688, + 37318, 22291, 18381, 32546, 2475, 1859, 24222, 13363, 34531, 16565, 38714, + 17668, 17669, 13864, 6789, 41207, 13533, 9649, 34970, 13364, 34971, 14919, + 38603, 35909, 33933, 21087, 35228, 35229, 35501, 21560, 32277, 12353, 33030, + 15415, 31564, 5709, 371, 41166, 30884, 25440, 5368, 18186, 37990, 37190, + 37753, 36230, 25628, 13738, 17230, 9548, 18399, 18400, 25451, 31637, 14531, + 2728, 36497, 15914, 34423, 21098, 24980, 3030, 4690, 18985, 5754, 5755, + 21616, 34441, 34440, 34576, 15966, 34577, 15748, 11448, 14021, 2992, 17811, + 14585, 23135, 23136, 24641, 39365, 38828, 35422, 13892, 34102, 14752, 412, + 7907, 37951, 6051, 21494, 7559, 22002, 39536, 11050, 5170, 5017, 20580, + 1830, 20591, 35697, 35698, 22849, 23588, 14730, 25545, 27442, 27530, 24092, + 39067, 26840, 25122, 5032, 9506, 22861, 38806, 25893, 30277, 5038, 26148, + 23265, 6411, 10752, 39334, 33482, 30599, 35787, 663, 22866, 6045, 8905, + 22063, 28905, 20138, 12837, 29008, 11624, 39904, 26237, 1540, 9785, 38254, + 20811, 666, 14100, 2793, 39763, 10874, 1273, 1393, 38820, 20162, 24018, + 2668, 7619, 19876, 671, 3826, 20343, 3932, 13721, 32287, 16369, 12848, + 1798, 8467, 12447, 29458, 38298, 9474, 20696, 24233, 6636, 34212, 536, + 13787, 40490, 34152, 4444, 29580, 35559, 39628, 29351, 39629, 32590, 29768, + 9587, 15684, 19495, 36827, 2056, 1799, 3383, 16251, 12299, 27787, 27362, + 24403, 37275, 20314, 27862, 2419, 32441, 7509, 14332, 6954, 9523, 18330, + 26155, 27863, 39721, 23035, 24406, 14343, 14333, 18512, 36271, 5055, 18750, + 35857, 3922, 29804, 27657, 33138, 20316, 2938, 31281, 7522, 9476, 15699, + 15774, 1316, 23953, 17942, 17689, 18615, 12681, 36498, 32125, 29482, 36588, + 16990, 29484, 34025, 5545, 22026, 11662, 20941, 11665, 7651, 14546, 34475, + 38144, 35293, 7132, 25852, 7133, 27085, 5890, 11035, 31138, 29902, 13290, + 468, 26658, 14830, 28888, 8096, 5612, 2972, 39135, 35423, 24903, 26415, + 33731, 14130, 5857, 38746, 13295, 23940, 22349, 1227, 26532, 5188, 13013, + 8775, 7160, 1250, 15584, 13212, 1676, 32650, 5203, 9751, 13308, 10691, + 20028, 9762, 30290, 14987, 12469, 18701, 11757, 11758, 35502, 35503, 35521, + 37679, 37681, 30910, 34595, 37240, 3406, 5858, 36643, 22732, 3448, 40590, + 30134, 12260, 39881, 30447, 5515, 18005, 7925, 30462, 31439, 30465, 3379, + 39641, 14131, 4551, 39871, 4555, 6144, 12531, 39662, 4556, 39992, 16252, + 32967, 13806, 13116, 27073, 12811, 1484, 8184, 30687, 22146, 31524, 39272, + 22747, 29105, 5438, 39279, 1658, 3690, 3096, 13459, 11798, 19735, 18486, + 32457, 829, 24831, 16646, 25266, 6087, 8324, 25269, 8368, 23445, 27007, + 31415, 7233, 36304, 20374, 30949, 31323, 12261, 31779, 12749, 30394, 4481, + 37224, 23226, 4748, 28591, 29983, 23735, 11887, 33322, 15835, 32060, 15250, + 14589, 35674, 755, 20375, 22232, 14597, 628, 21066, 29429, 11064, 14598, + 3783, 5648, 29728, 36739, 7844, 31780, 1177, 36683, 33847, 4484, 1761, + 11553, 33600, 1178, 27350, 31440, 28619, 36673, 20697, 39545, 27033, 31792, + 16594, 10540, 15815, 20707, 39551, 32832, 29353, 5944, 10260, 9578, 31441, + 13415, 27775, 10837, 24530, 11666, 3581, 35405, 33327, 9334, 17958, 3525, + 26407, 24904, 37702, 22316, 5426, 11733, 32793, 19488, 36625, 37482, 22441, + 37706, 37254, 29770, 13804, 38949, 17959, 10261, 24148, 29173, 2113, 23845, + 31454, 19375, 35314, 10532, 3380, 31336, 16859, 17623, 4486, 35757, 17124, + 21107, 6919, 31338, 4557, 6694, 2953, 19833, 25895, 9412, 9407, 23155, + 15546, 29302, 19065, 31493, 15209, 9696, 21328, 6604, 9819, 38586, 37493, + 13857, 12544, 16331, 37256, 10387, 24941, 28654, 29178, 21515, 4314, 11872, + 33125, 6938, 28339, 40951, 12866, 36635, 5431, 21116, 37913, 5969, 4287, + 24465, 2420, 1439, 20438, 40901, 29073, 920, 33740, 30531, 8693, 30688, + 1229, 33741, 11408, 20242, 36636, 15172, 5299, 36080, 3171, 19653, 23604, + 15452, 84, 24160, 34495, 21883, 40952, 25825, 36531, 25068, 8906, 37847, + 28018, 23292, 34951, 27824, 11574, 12327, 9158, 14641, 4183, 21333, 32859, + 15152, 39317, 36644, 2391, 34125, 26709, 1928, 15175, 31823, 11930, 36648, + 34834, 17175, 25941, 28906, 36089, 33657, 28606, 37917, 20508, 8984, 4562, + 22700, 20812, 9787, 3627, 2282, 2259, 2254, 4717, 20449, 38756, 29671, + 364, 27499, 9419, 25077, 38210, 14347, 17417, 21967, 27830, 24263, 36280, + 18937, 26374, 29865, 19382, 23679, 26545, 24427, 5703, 39495, 18513, 14785, + 23182, 23174, 37344, 22881, 17659, 4589, 36695, 3691, 39765, 29672, 3261, + 23520, 24720, 22366, 941, 24494, 13365, 3617, 17435, 22886, 16006, 11785, + 3355, 36285, 36286, 31747, 31581, 5204, 28673, 6737, 6573, 28028, 14939, + 2439, 32641, 7213, 7666, 16569, 16621, 32190, 20450, 17722, 31282, 2285, + 14920, 4650, 32388, 28727, 26769, 22476, 35911, 32107, 21088, 5206, 28730, + 14102, 27801, 13471, 30822, 33766, 24280, 24271, 14661, 2393, 15496, 36351, + 35912, 17944, 26026, 15090, 11257, 101, 34334, 16147, 32037, 3650, 37191, + 36292, 4999, 19954, 108, 19877, 6584, 23342, 20566, 16351, 19840, 3827, + 39809, 21900, 34330, 34842, 1989, 39828, 15878, 15849, 36860, 7897, 18266, + 20344, 3370, 11864, 2844, 16421, 11261, 33819, 25229, 2848, 12636, 14693, + 11295, 26564, 17564, 21024, 20056, 28870, 14989, 8536, 40489, 37687, 8631, + 12854, 6199, 5961, 38319, 12767, 39407, 15939, 38708, 23909, 8655, 13022, + 37319, 34532, 10875, 38719, 31853, 31862, 24834, 11036, 11038, 6884, 27014, + 29161, 19603, 5793, 26394, 35424, 35566, 34496, 24569, 16647, 7297, 25624, + 38037, 38799, 5883, 36921, 15628, 8418, 26575, 2492, 30028, 9130, 31313, + 5450, 25307, 31416, 23737, 12750, 36953, 353, 31423, 39539, 39612, 5451, + 34462, 15836, 1463, 14375, 30950, 10895, 37695, 24322, 5136, 39308, 37868, + 30308, 21156, 23016, 23017, 432, 334, 38226, 37949, 1762, 39546, 28614, + 2102, 35014, 39132, 38371, 34724, 10310, 21268, 35175, 3575, 22428, 12689, + 19771, 24690, 3976, 12693, 38457, 22170, 20840, 23738, 30038, 537, 5614, + 14599, 16116, 23578, 23646, 10519, 21623, 8943, 4819, 35406, 32833, 2408, + 11594, 510, 39630, 16118, 6720, 6721, 21753, 39184, 8677, 13508, 6192, + 20844, 17769, 38373, 18878, 5945, 14845, 17866, 14552, 34243, 32154, 37471, + 30042, 1898, 8829, 29151, 3310, 25761, 15513, 19752, 18481, 14388, 22344, + 12989, 26215, 25629, 32837, 2500, 7760, 13421, 14324, 11990, 29771, 23019, + 38307, 27357, 35131, 14857, 30312, 2114, 41227, 35733, 38516, 18879, 27858, + 30043, 657, 30878, 30396, 24247, 26518, 20387, 19813, 8109, 5350, 31066, + 14734, 37714, 40950, 3122, 29738, 983, 25735, 41243, 31089, 31476, 3315, + 25968, 19049, 24419, 8508, 5624, 11922, 23266, 27236, 23665, 18034, 34254, + 39256, 17608, 9304, 35758, 12001, 26305, 39312, 2197, 1752, 29175, 39994, + 15500, 21994, 13566, 20519, 8867, 19989, 25939, 22408, 21879, 13000, 39266, + 14265, 13001, 34388, 21011, 10578, 22603, 30532, 25826, 21486, 27075, 40953, + 39201, 34056, 36603, 1401, 34779, 11409, 34497, 38069, 33485, 15398, 12288, + 29181, 16175, 16189, 3172, 14270, 29783, 11610, 8794, 3752, 32619, 32800, + 23749, 2511, 847, 34940, 30533, 1077, 30982, 40954, 8807, 9052, 24333, + 25410, 25061, 3770, 28280, 28266, 25402, 701, 15363, 34952, 5358, 39415, + 21811, 16164, 24663, 32266, 13962, 20334, 6956, 4199, 26229, 28462, 38463, + 22066, 17176, 28907, 10926, 39723, 30193, 11169, 30983, 23967, 29270, 39089, + 6957, 21889, 24958, 38502, 31271, 26537, 15284, 27871, 25788, 2789, 28309, + 14272, 3689, 4139, 9321, 7766, 5695, 23511, 27878, 17505, 3262, 3420, + 9420, 18753, 18551, 40960, 8346, 11099, 38389, 4170, 28879, 11222, 20930, + 13236, 9533, 36478, 304, 39767, 21550, 19445, 2840, 15585, 3889, 26546, + 29866, 13450, 2302, 15524, 1541, 13307, 36090, 9063, 23682, 12354, 22760, + 16542, 6614, 32381, 25634, 9651, 38074, 35880, 32191, 3268, 21085, 10725, + 9491, 4914, 21402, 17941, 39318, 11634, 13460, 12456, 2355, 5150, 5151, + 1860, 3063, 14811, 8128, 993, 8129, 40637, 30712, 23047, 24337, 6611, + 11170, 13461, 28486, 24110, 31053, 13035, 36569, 21047, 18669, 40638, 38269, + 23050, 4331, 12201, 5274, 26027, 24386, 13592, 15745, 5117, 32878, 15114, + 377, 14662, 35219, 7043, 19990, 20029, 12458, 28580, 5369, 16418, 14572, + 35145, 25603, 35252, 35245, 21289, 31114, 12382, 1732, 21650, 8666, 39810, + 39791, 16141, 20547, 13174, 32904, 17830, 28640, 533, 27928, 18676, 19045, + 25249, 29055, 34843, 16806, 2158, 27274, 38077, 21409, 32288, 15101, 17274, + 16210, 11378, 36443, 18616, 18466, 23709, 23710, 23715, 16371, 32126, 36367, + 19741, 2672, 36534, 4684, 32914, 26565, 19130, 15108, 20057, 16979, 38081, + 18988, 28642, 17331, 5756, 30208, 5278, 13498, 16430, 17359, 9620, 9580, + 23160, 34077, 15309, 35550, 8371, 569, 22966, 5728, 15597, 20429, 31330, + 10360, 2411, 3986, 8683, 33627, 13517, 3166, 26605, 6691, 37159, 544, + 33628, 6692, 21526, 5773, 6679, 35790, 15412, 34616, 12134, 29706, 32757, + 6696, 34785, 31975, 20399, 36, 37, 5572, 39206, 27392, 17672, 24731, + 33359, 35592, 13472, 26366, 13473, 40661, 35937, 17509, 1332, 16964, 32785, + 32786, 33914, 23233, 23249, 14867, 38520, 16476, 580, 37203, 16379, 30770, + 26735, 12805, 12812, 37164, 13527, 29413, 6301, 36119, 23890, 24764, 38643, + 4884, 40622, 40639, 24267, 17901, 40662, 4030, 6512, 40264, 2764, 10159, + 22279, 36740, 19774, 23250, 22448, 18215, 7857, 7400, 14038, 38872, 35575, + 26426, 13125, 37030, 39792, 7215, 22707, 7216, 38617, 15778, 28237, 37098, + 12470, 12534, 12007, 32820, 29347, 28552, 5643, 33459, 2762, 34750, 26915, + 20376, 20377, 30019, 4222, 31252, 883, 605, 13626, 26736, 11060, 7394, + 9623, 33726, 7563, 24292, 10833, 34354, 38304, 7395, 26698, 14600, 34763, + 1766, 33851, 22967, 39136, 18010, 10256, 20592, 1475, 33608, 11866, 40972, + 27037, 7495, 5946, 30885, 6130, 49, 1767, 251, 18362, 15860, 29405, + 26926, 11559, 33828, 15921, 33472, 13422, 13941, 39645, 29591, 10704, 8310, + 32496, 10070, 15063, 32344, 16044, 40080, 31477, 26796, 38950, 38951, 10071, + 10266, 30348, 29306, 40623, 41177, 40052, 26272, 21276, 31495, 23422, 39313, + 35791, 225, 30349, 17881, 2871, 30476, 32726, 7555, 8858, 35468, 37802, + 11617, 33569, 20445, 35120, 36509, 27310, 30700, 24385, 19655, 20992, 13014, + 34786, 4229, 34959, 28348, 13972, 13451, 15155, 8583, 31019, 2958, 23512, + 10281, 34634, 17189, 12592, 19836, 38091, 33020, 10284, 20640, 4508, 21340, + 38762, 11786, 10108, 33807, 4098, 17676, 5207, 14103, 22761, 17902, 31751, + 35913, 12603, 11579, 5060, 35209, 35210, 17212, 28679, 29633, 32733, 7527, + 26682, 38895, 10291, 35938, 32510, 33233, 26643, 13477, 824, 14165, 34664, + 111, 35246, 25582, 19884, 17253, 3195, 15879, 6018, 17727, 34684, 12063, + 18623, 25454, 18411, 19179, 18989, 26199, 28871, 34578, 40226, 37666, 35170, + 10834, 27228, 2360, 26819, 2468, 2280, 33643, 11761, 36219, 24169, 7585, + 22556, 7597, 18011, 7460, 29165, 21823, 29406, 16509, 41142, 20475, 11462, + 29968, 12137, 36317, 40908, 30508, 29634, 16521, 16637, 18412, 5476, 27336, + 20785, 25267, 394, 6712, 5341, 17081, 9567, 14244, 1113, 3290, 4436, + 25626, 23635, 36955, 31146, 34030, 7234, 40819, 25313, 30033, 5644, 19481, + 3569, 35653, 8342, 8880, 16849, 13325, 26364, 30427, 14370, 19482, 27719, + 37536, 7491, 6128, 32062, 4223, 27220, 11201, 33114, 3856, 3857, 27779, + 31083, 13933, 12103, 19555, 1181, 265, 7598, 35678, 7930, 20978, 11061, + 34154, 6254, 33151, 34888, 6870, 38861, 37902, 41202, 6255, 6806, 18851, + 27856, 20979, 32069, 28558, 31722, 9325, 725, 20593, 35705, 35180, 35184, + 27038, 21501, 1121, 35407, 21272, 16160, 10348, 632, 7235, 39890, 5027, + 4374, 34821, 7845, 19625, 26445, 27783, 26589, 20982, 36626, 39631, 38374, + 5176, 9084, 2107, 276, 7942, 407, 6765, 1188, 26216, 27727, 3980, + 22235, 27021, 9326, 38375, 35020, 14319, 18302, 19695, 17389, 25387, 38224, + 26741, 36622, 34043, 23476, 39068, 35425, 32477, 39192, 17126, 25997, 15186, + 962, 25287, 526, 25288, 1801, 40715, 3788, 35734, 4447, 13110, 41172, + 7077, 7111, 36828, 7174, 8945, 38581, 17782, 36063, 35735, 27047, 7962, + 25547, 35426, 15643, 24450, 25909, 33958, 6768, 40510, 36985, 38066, 0, + 36307, 13836, 18353, 38696, 34044, 26099, 39079, 845, 29472, 16121, 14136, + 23009, 984, 25677, 31478, 16477, 18306, 7710, 23156, 30954, 15030, 8427, + 27985, 24611, 36832, 18483, 22324, 40459, 5664, 33734, 29777, 38207, 277, + 1213, 5556, 9984, 39402, 25331, 903, 12995, 11400, 30341, 21853, 12709, + 29374, 12535, 32601, 18887, 11891, 2456, 7606, 27789, 16863, 6280, 24296, + 36469, 14406, 16084, 40616, 2656, 30679, 14137, 16864, 1689, 32050, 7816, + 28942, 39665, 16253, 17406, 40574, 16874, 23497, 1809, 19068, 4491, 23850, + 23283, 2211, 2682, 5432, 7468, 22015, 697, 11877, 3328, 38182, 17160, + 37279, 37280, 9226, 15069, 6203, 8512, 30477, 4885, 7246, 3246, 38705, + 23423, 37499, 34500, 37281, 24911, 35792, 25292, 23162, 40577, 7997, 16260, + 41001, 41002, 7573, 26611, 24382, 21234, 30350, 18730, 10211, 13579, 3799, + 14555, 14481, 3329, 41245, 23900, 34168, 848, 40624, 40733, 1692, 22353, + 6099, 3949, 2967, 19843, 11246, 13002, 9524, 31812, 5420, 9690, 5840, + 39408, 25025, 20514, 8281, 8868, 22409, 38647, 36042, 26070, 6733, 8198, + 30701, 30541, 12813, 40909, 12889, 35469, 31683, 34625, 34513, 12890, 37173, + 10397, 31101, 22666, 1085, 34902, 12008, 33497, 25744, 34787, 16190, 34389, + 975, 11618, 15941, 13813, 15942, 27641, 7722, 30145, 39666, 20813, 19656, + 11087, 10934, 29503, 37033, 36771, 27827, 33869, 34831, 39091, 22667, 35199, + 13683, 35200, 6653, 37012, 30542, 19717, 29185, 12317, 13684, 25533, 11496, + 16657, 25026, 32571, 27148, 28660, 30891, 26726, 4043, 22645, 12818, 35858, + 38657, 8032, 21891, 20147, 9175, 13140, 28409, 35040, 26116, 37577, 40848, + 20488, 28019, 12838, 34960, 13701, 11578, 8469, 23767, 19303, 37578, 25417, + 26942, 39423, 37853, 29504, 25411, 28807, 38525, 27649, 26810, 15370, 31542, + 9166, 23176, 8584, 28270, 22067, 28909, 8713, 34061, 5738, 21778, 12338, + 9057, 23910, 23819, 19724, 33669, 8534, 40640, 30107, 24122, 34862, 5739, + 12819, 41183, 5421, 18489, 25938, 31694, 12170, 17425, 11787, 36562, 23866, + 9825, 8355, 8360, 29868, 11230, 26071, 4721, 22361, 36850, 13275, 11103, + 11429, 9652, 21551, 35881, 8556, 15266, 9539, 9540, 19453, 5536, 40465, + 16659, 16517, 3182, 4509, 16908, 33393, 24387, 27501, 29665, 9423, 38260, + 28030, 16744, 18665, 17587, 20156, 18520, 3002, 28031, 15377, 1547, 18769, + 14274, 39038, 38395, 27264, 19384, 21460, 34869, 29388, 22362, 40335, 26119, + 24968, 12903, 4510, 12679, 34717, 33988, 7151, 34078, 39500, 41150, 4570, + 23115, 27397, 11223, 16015, 39112, 26326, 31586, 4234, 5824, 7187, 20539, + 31293, 25238, 17968, 18251, 24060, 32390, 25732, 7261, 38666, 16606, 37859, + 27565, 6615, 3273, 28825, 19868, 28056, 14942, 5825, 11800, 12184, 21872, + 30151, 21667, 25688, 29635, 38343, 7626, 24496, 25193, 10551, 23780, 9111, + 18317, 16624, 8558, 31907, 26820, 40886, 25908, 12371, 6243, 14181, 13214, + 4044, 28494, 27270, 13249, 17948, 21734, 36227, 28224, 26248, 41192, 33813, + 3277, 8474, 14513, 41196, 35939, 23118, 7733, 11702, 5321, 12619, 28216, + 22890, 3362, 3960, 40365, 9662, 12373, 13776, 12824, 38544, 13040, 23956, + 5402, 35597, 1601, 27805, 26495, 17394, 36176, 28964, 28583, 20208, 23352, + 29876, 1710, 12036, 12629, 23706, 21292, 21653, 35345, 8597, 15227, 36297, + 21782, 24413, 34547, 23353, 20175, 38900, 9668, 4241, 12213, 15954, 22942, + 5496, 3933, 8776, 20210, 36705, 39839, 11571, 23711, 16762, 16696, 25812, + 18681, 17254, 4689, 18953, 20350, 11837, 21934, 18609, 39811, 8565, 6376, + 37603, 17275, 7540, 40669, 27930, 17456, 13326, 3938, 24438, 40176, 18624, + 34430, 17293, 40175, 3231, 13741, 7020, 27956, 11264, 21585, 37415, 18414, + 16314, 13560, 32291, 9556, 14575, 32676, 18125, 36373, 12958, 36242, 36811, + 36450, 32461, 21744, 2011, 2736, 16380, 14577, 27481, 26568, 30650, 4582, + 24984, 24835, 2353, 14372, 37437, 19135, 17349, 4692, 18990, 5282, 14996, + 34719, 16434, 16391, 40227, 16721, 17066, 496, 21043, 37449, 18156, 9496, + 35679, 23641, 33468, 2974, 3981, 23488, 15169, 35736, 14858, 31800, 33618, + 10316, 15993, 16470, 15793, 27582, 17, 4047, 3539, 24216, 15210, 15796, + 15214, 4113, 9261, 36085, 37035, 32630, 35211, 31162, 28756, 13983, 21924, + 10876, 29191, 11286, 33514, 22300, 31752, 32772, 4049, 26327, 9951, 4031, + 35940, 7010, 37082, 4337, 11447, 2103, 2104, 14601, 23743, 3467, 26005, + 3540, 26011, 39933, 28195, 28196, 17190, 4890, 37057, 17214, 9549, 6885, + 38926, 20582, 20583, 34889, 26743, 33619, 14869, 23598, 24612, 27986, 24380, + 35793, 7829, 35193, 2251, 11879, 5983, 39102, 37881, 30892, 3876, 29193, + 13984, 26379, 36169, 5869, 14353, 11801, 4696, 5118, 6463, 13250, 17552, + 1734, 6377, 13216, 12959, 40288, 24420, 35759, 26093, 24096, 15399, 32709, + 34119, 11691, 24008, 12163, 21925, 11697, 6509, 35346, 32686, 9401, 19748, + 48, 13770, 22498, 2710, 10206, 2189, 22493, 17864, 12700, 25824, 20795, + 30159, 34046, 7112, 25395, 32253, 14467, 24613, 6281, 26101, 22251, 14482, + 6680, 1081, 25906, 19658, 25828, 36935, 30166, 10398, 28474, 25859, 18863, + 20747, 19581, 29636, 25489, 38612, 25982, 38613, 19887, 18682, 6033, 14825, + 23447, 34756, 21187, 1741, 26590, 23477, 31456, 24354, 34264, 6145, 34835, + 37806, 39307, 1746, 5287, 27551, 16648, 21308, 7306, 9566, 1679, 38299, + 20222, 5846, 40592, 4117, 30301, 7310, 4980, 30030, 19477, 24573, 22817, + 23629, 31139, 31140, 29846, 14369, 39366, 39540, 23636, 14087, 14088, 25695, + 15021, 10620, 24999, 1464, 8455, 39876, 7362, 14832, 11016, 21684, 33593, + 33602, 37824, 34463, 5172, 36726, 11052, 11982, 21819, 19689, 20111, 3671, + 22119, 1118, 39541, 22095, 40507, 37954, 18209, 38227, 7695, 19772, 38065, + 30040, 17096, 20078, 35385, 7154, 29250, 27623, 15858, 14204, 14382, 35681, + 12694, 39885, 11720, 959, 38229, 40186, 36684, 9082, 10835, 22845, 4425, + 39373, 27968, 3242, 27713, 14459, 25781, 26737, 14840, 7931, 12432, 9406, + 5242, 36126, 22058, 35707, 11596, 38040, 3303, 30582, 10803, 13101, 27732, + 7072, 33256, 7945, 25996, 39554, 36255, 31195, 15314, 19194, 211, 29166, + 20708, 16785, 35309, 20082, 24930, 22968, 32696, 32953, 27971, 15817, 24150, + 14591, 22851, 33328, 39633, 9456, 20470, 31148, 24692, 35708, 14125, 26838, + 7168, 2766, 13937, 17783, 24601, 30673, 9979, 19497, 36748, 1899, 6274, + 10645, 35737, 36466, 16402, 10027, 17030, 8799, 17525, 4253, 7761, 35738, + 29594, 16554, 12705, 3676, 14212, 28124, 3247, 22282, 32341, 26700, 16104, + 22824, 10062, 14032, 21391, 29735, 32752, 29534, 6828, 29966, 17128, 27531, + 27733, 16788, 27532, 6343, 37837, 10565, 33301, 27186, 4315, 38807, 15547, + 31090, 30048, 6141, 31043, 14407, 26528, 17575, 11873, 28455, 24155, 5429, + 14763, 9151, 9820, 34299, 39995, 22402, 10268, 2867, 23157, 7368, 39468, + 18718, 14474, 16792, 39032, 22862, 29303, 37259, 21228, 18719, 20125, 14138, + 18036, 19066, 24772, 37260, 21393, 1531, 10849, 37494, 16254, 24355, 23809, + 39558, 36210, 20126, 985, 37487, 30980, 25742, 7421, 37488, 15409, 12537, + 26529, 26066, 23562, 22601, 31906, 37490, 25510, 11410, 13003, 21832, 24625, + 29497, 7247, 31044, 5676, 30535, 25558, 2421, 10373, 34501, 10661, 20089, + 19565, 36312, 34502, 10579, 26781, 19757, 38018, 11894, 20962, 9599, 3600, + 6940, 17534, 23499, 23500, 19711, 29264, 4598, 30600, 2229, 11746, 20621, + 33486, 12320, 12997, 7792, 35796, 36266, 26933, 13580, 3256, 28749, 37014, + 1233, 20440, 26847, 29744, 26753, 36637, 14483, 6204, 29893, 13444, 24626, + 28768, 18378, 12009, 37554, 21012, 635, 36838, 24952, 40460, 17629, 2683, + 34379, 4262, 21528, 40735, 19421, 36409, 16235, 7808, 18501, 30601, 32051, + 36410, 22920, 13964, 34627, 28349, 37570, 17418, 35036, 19971, 40559, 3342, + 28605, 28421, 30194, 9001, 25943, 38498, 26937, 19089, 19277, 30543, 2185, + 31360, 30893, 23901, 38247, 26855, 33, 37849, 36086, 28008, 28390, 26856, + 21, 22109, 4008, 30998, 2329, 20335, 8707, 10274, 11576, 31824, 5561, + 39725, 33273, 13685, 8653, 28132, 13522, 11763, 36152, 8549, 18379, 4264, + 32794, 37303, 33426, 11100, 1253, 1542, 39751, 13305, 15611, 26719, 26375, + 20148, 297, 18662, 11028, 36694, 2790, 7346, 36559, 9707, 19426, 24407, + 37047, 12575, 34202, 2999, 31743, 12576, 18515, 18382, 13904, 9789, 4563, + 39496, 8358, 23949, 13528, 4501, 4267, 29867, 21920, 29012, 35160, 31689, + 20149, 28809, 26376, 10099, 17419, 30196, 3492, 8405, 7767, 40878, 15264, + 22333, 38787, 40483, 33670, 11976, 13141, 34318, 27500, 17660, 4733, 29106, + 13241, 4564, 36483, 10681, 34062, 27387, 9421, 40993, 16112, 33671, 39752, + 22614, 37346, 13535, 23010, 5308, 11788, 13710, 31284, 21998, 12355, 30614, + 28044, 23772, 31566, 31843, 34129, 6659, 20451, 25730, 28032, 39109, 4565, + 35860, 39039, 30284, 26319, 34073, 16007, 35122, 29805, 25772, 10513, 1301, + 2702, 27316, 23048, 17895, 30615, 26038, 26019, 3356, 14232, 11231, 13366, + 16622, 4814, 10726, 10005, 37856, 18334, 10727, 8044, 10285, 10399, 32192, + 13147, 26245, 31844, 37473, 18854, 21680, 37073, 17946, 20256, 5250, 11434, + 38270, 33035, 37365, 27117, 33934, 18092, 30410, 40773, 36570, 11802, 2306, + 17547, 5826, 35232, 11340, 39113, 19458, 5154, 35919, 28206, 22621, 14663, + 28487, 24274, 40653, 21731, 9752, 13991, 7622, 26029, 12356, 11803, 3957, + 28502, 27803, 6079, 26067, 40255, 17447, 20097, 26881, 27398, 20163, 21677, + 36433, 36434, 19878, 13999, 23343, 12620, 4789, 31118, 28920, 36231, 36232, + 6580, 4406, 12028, 14169, 16446, 15096, 60, 30624, 1706, 9195, 23787, + 36435, 1742, 16142, 7535, 2351, 19684, 13176, 30739, 19226, 38098, 18951, + 17231, 36703, 34871, 18677, 27770, 39793, 36441, 6374, 30494, 11646, 33056, + 22080, 26690, 1564, 2716, 20665, 18269, 12939, 26042, 3367, 9201, 1716, + 12052, 32408, 18617, 24339, 25452, 17276, 14170, 32669, 36446, 28167, 30750, + 11262, 33980, 40170, 18403, 16309, 6588, 7279, 10999, 16310, 27418, 18201, + 36447, 20048, 12644, 17558, 13183, 36451, 17920, 35990, 12953, 2731, 5075, + 25203, 13068, 16372, 7280, 27514, 37523, 40682, 7744, 26566, 16769, 16373, + 4579, 24832, 36589, 23792, 7195, 25101, 34705, 36536, 25774, 38109, 18992, + 34690, 16980, 20103, 26356, 28643, 5279, 13499, 2828, 36537, 10306, 40225, + 16431, 16388, 21052, 30294, 19000, 34095, 32309, 34708, 8484, 34713, 37462, + 9449, 32573, 32574, 11861, 10571, 40415, 38484, 32940, 3570, 38009, 23460, + 39886, 7599, 21697, 30913, 22964, 35682, 22432, 15167, 22098, 15168, 22163, + 20791, 17737, 9451, 33116, 9495, 9452, 1522, 4930, 31948, 39245, 40190, + 15407, 38865, 7946, 439, 32954, 6766, 18191, 40569, 22184, 28560, 34822, + 29560, 9930, 30781, 11557, 40124, 13423, 33620, 10543, 25002, 11396, 33378, + 33379, 32255, 36120, 31152, 39987, 34929, 27048, 30519, 29595, 20327, 38015, + 15170, 31956, 33829, 39248, 22972, 11671, 9459, 3079, 11602, 3238, 0, + 17867, 7978, 14213, 32970, 23109, 29473, 40606, 29536, 9888, 16510, 34601, + 33630, 3592, 25396, 10915, 31482, 27239, 10466, 33995, 15689, 14708, 32603, + 31483, 40478, 15064, 5665, 32971, 12302, 34302, 18966, 34609, 14475, 17961, + 16049, 11924, 29969, 31499, 4767, 31204, 10580, 3022, 8113, 31098, 4492, + 7793, 22867, 24467, 25743, 31500, 24468, 33178, 35797, 14887, 37283, 8532, + 22520, 33354, 30514, 26754, 2954, 26423, 33346, 21394, 8808, 30879, 3178, + 10471, 15977, 39935, 31925, 11619, 7794, 17539, 33215, 13445, 1254, 36318, + 40248, 30703, 29851, 26277, 31544, 21835, 21836, 2689, 34313, 14216, 14226, + 19790, 30803, 38428, 33179, 24479, 25512, 11419, 7251, 24635, 28197, 34788, + 17803, 13585, 8615, 9262, 37804, 31926, 27149, 17639, 9058, 28810, 3024, + 7053, 1941, 11565, 32871, 31831, 31367, 37921, 10413, 10473, 31546, 37854, + 20927, 26280, 24519, 35083, 20150, 17426, 36420, 31277, 8911, 34716, 23980, + 1276, 1548, 4511, 18771, 12907, 18521, 22363, 28138, 35884, 28999, 14922, + 40921, 11104, 35492, 39770, 30814, 18314, 10109, 21926, 25258, 14230, 16113, + 4697, 38344, 12923, 31588, 31589, 35885, 32774, 3639, 11509, 2802, 35212, + 28680, 34656, 32202, 24023, 15092, 5461, 6661, 26636, 13373, 7627, 27669, + 37367, 17903, 29637, 26434, 7587, 34079, 16443, 19765, 28881, 35921, 14104, + 19838, 14182, 13474, 36429, 35941, 33935, 16352, 28608, 2310, 31605, 25089, + 4522, 17457, 11703, 40214, 18103, 30560, 35942, 32894, 38897, 11817, 4992, + 21735, 16353, 25583, 15323, 34013, 14003, 3836, 5405, 35096, 10494, 16447, + 1569, 25447, 17256, 20673, 25753, 18954, 16211, 283, 34136, 15880, 27605, + 17754, 17296, 18626, 14965, 17731, 34685, 31645, 33069, 18415, 35255, 2317, + 25222, 37770, 16452, 4583, 3737, 9435, 14699, 3115, 20061, 28873, 16457, + 40228, 16461, 18157, 37465, 38906, 39238, 22185, 3244, 30798, 10146, 14923, + 35290, 41096, 7119, 4151, 15345, 38122, 5984, 23911, 36606, 23957, 22102, + 2989, 12880, 4138, 37037, 38429, 1406, 682, 1942, 4141, 36919, 6379, + 3257, 21718, 14246, 28400, 25314, 19469, 7365, 8496, 34592, 8634, 886, + 27728, 36886, 8639, 20760, 5619, 25016, 24934, 40864, 19499, 15516, 23660, + 16877, 23034, 8513, 39474, 964, 24953, 4263, 12727, 7723, 15364, 14488, + 3918, 31833, 928, 19212, 13817, 19257, 25860, 30815, 19582, 6616, 29638, + 24123, 31908, 17257, 6380, 17839, 22024, 22711, 2003, 31646, 3779, 30644, + 15969, 3781, 431, 12430, 2178, 40593, 8628, 15296, 1879, 10789, 34235, + 36116, 11283, 40474, 24343, 39946, 20789, 22433, 14462, 35386, 26738, 30073, + 18007, 22495, 21269, 35016, 36877, 33955, 5173, 1884, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 17995, 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, 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, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 15674, 32244, 11315, 10350, 38866, 12283, 34105, 26217, 28444, + 29588, 16596, 19498, 31459, 31957, 897, 39648, 34362, 26094, 10063, 14039, + 22014, 7427, 32604, 545, 23270, 1534, 36267, 16255, 12868, 23894, 16045, + 34309, 40976, 39668, 39258, 34198, 17868, 5771, 40904, 9635, 7718, 31046, + 37555, 4082, 29850, 34265, 32801, 12720, 1402, 36765, 34954, 28267, 1930, + 20484, 27866, 19298, 37572, 4998, 37321, 26857, 10214, 23986, 35829, 39093, + 2330, 10225, 19447, 13276, 20631, 2693, 298, 10218, 4720, 994, 1302, + 1279, 11502, 23077, 17896, 33683, 29631, 35087, 27592, 32643, 27208, 6612, + 13539, 8720, 14792, 6362, 11804, 15775, 32278, 32281, 21651, 22796, 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, 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, 0, + 0, 0, 0, 0, 0, 12030, 21781, 19955, 17834, 21135, 9478, + 27202, 18618, 28432, 32414, 20049, 25204, 21140, 19132, 32298, 23382, 14991, + 20311, 40717, 18598, 27965, 24571, 8297, 16651, 395, 10621, 5645, 4119, + 8374, 36959, 23404, 36960, 2947, 8882, 31256, 7841, 13795, 34189, 1472, + 689, 37700, 14841, 19809, 14842, 12855, 5138, 22786, 23892, 35710, 180, + 22852, 7947, 33793, 4426, 9020, 12803, 26447, 4369, 25182, 26746, 26591, + 35412, 41097, 18303, 1192, 39063, 13855, 13511, 13112, 17130, 9487, 32073, + 39988, 34292, 33434, 34770, 33563, 27976, 24242, 36133, 34047, 763, 32533, + 31958, 9509, 3677, 33622, 22283, 16632, 5245, 36530, 30921, 6830, 3316, + 5666, 31270, 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, 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, 0, 0, 0, 0, 0, 0, 31202, 3312, 15065, + 19703, 905, 29537, 32346, 3993, 9988, 33801, 34372, 33861, 33438, 7979, + 31484, 18038, 16866, 13954, 28395, 7807, 30315, 5805, 22790, 38648, 26006, + 20395, 37284, 16261, 30923, 26806, 30602, 29307, 4000, 1039, 3248, 6959, + 2872, 1040, 18731, 9385, 5861, 915, 25052, 40625, 24250, 7198, 14016, + 6413, 13814, 11897, 37174, 19720, 4231, 33749, 29093, 33216, 5053, 25513, + 20400, 12892, 30704, 25651, 11420, 32863, 4084, 13015, 40423, 2955, 17541, + 24959, 6503, 34199, 11499, 18238, 26863, 25423, 28353, 34963, 30894, 31278, + 39103, 13973, 36421, 19279, 28910, 18241, 17191, 16482, 39208, 23912, 4831, + 14912, 38855, 1699, 27259, 2912, 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, 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, 0, 0, 0, 0, 0, 0, + 16064, 40388, 4512, 35339, 23324, 36484, 28357, 24646, 307, 17506, 19818, + 36171, 11249, 30823, 31222, 5462, 33444, 38346, 34081, 24794, 5322, 17904, + 17678, 24497, 28058, 9542, 14105, 7263, 13985, 18252, 12187, 11863, 14106, + 113, 38188, 5254, 13478, 9730, 28735, 11818, 11347, 26040, 28219, 29283, + 4045, 37084, 14004, 18619, 1712, 27297, 41169, 16360, 31760, 40788, 33816, + 25666, 31119, 8364, 16697, 6381, 17279, 39840, 25525, 16967, 38102, 24507, + 29213, 9554, 28160, 16217, 18416, 18627, 17299, 16453, 36375, 20058, 32462, + 24516, 9436, 5416, 38112, 11367, 1885, 1900, 39483, 17361, 0, 32469, + 23637, 608, 22301, 7396, 5139, 0, 0, 30245, 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, 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, 0, 0, 0, + 0, 0, 0, 10901, 35413, 528, 14709, 2900, 3412, 0, 5300, + 19947, 40516, 22869, 1407, 40089, 0, 4392, 36329, 23513, 32186, 18553, + 5705, 21928, 40389, 17970, 31294, 5121, 31034, 36356, 34562, 29261, 9998, + 2904, 24375, 26598, 2773, 2774, 25678, 27942, 26628, 18695, 7790, 38412, + 7911, 22820, 29529, 39181, 19844, 23235, 18323, 34031, 18210, 20761, 37829, + 7948, 8798, 13798, 7949, 29256, 20762, 6671, 13227, 30185, 4936, 20984, + 20764, 20765, 2412, 29259, 8313, 1202, 4941, 39669, 19024, 22047, 36040, + 11212, 26489, 37015, 20769, 15071, 35763, 18220, 5974, 11215, 5248, 40520, + 13235, 3347, 2959, 30016, 16681, 2520, 18253, 6046, 17974, 13254, 3840, + 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, + 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, + 0, 0, 0, 0, 0, 0, 22635, 6019, 6024, 13633, 5177, + 27245, 39753, 20938, 1119, 8497, 40045, 32024, 33465, 3216, 14847, 23243, + 31915, 4751, 1193, 40973, 33903, 39395, 7169, 39559, 7501, 14390, 26221, + 21509, 29007, 29562, 13568, 30680, 11675, 28625, 3593, 19785, 14147, 32608, + 29745, 19504, 32609, 28096, 7864, 6697, 27189, 35831, 1020, 38810, 9387, + 19253, 17885, 12557, 29313, 156, 3609, 1257, 20401, 6532, 6817, 34219, + 4640, 26712, 39937, 3619, 37322, 7726, 34793, 3183, 29794, 9748, 30927, + 11426, 15697, 36091, 14925, 31571, 9361, 35886, 4142, 11775, 21845, 5740, + 38816, 26723, 4657, 35922, 40985, 27937, 26031, 5918, 18573, 18574, 24275, + 8068, 17683, 24063, 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, 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, 0, 0, 0, 0, 0, 0, 18260, 16573, + 32212, 7531, 5122, 36282, 10488, 32213, 9365, 9670, 21755, 37399, 30629, + 36579, 16759, 17236, 27324, 5228, 17950, 17951, 1672, 12637, 3444, 34844, + 13596, 39303, 19686, 17314, 12068, 16316, 12682, 33843, 36503, 36244, 36597, + 28644, 5759, 19181, 19006, 19010, 1827, 1834, 440, 7155, 7158, 24128, + 12267, 38196, 19618, 21980, 4427, 18022, 20600, 12285, 22403, 8543, 6835, + 10082, 1234, 3806, 23854, 40, 32732, 10286, 11580, 10287, 38273, 4744, + 10294, 32737, 35220, 10297, 13481, 121, 33239, 11584, 17300, 22739, 10449, + 13553, 8421, 22212, 24627, 25063, 38391, 9178, 15035, 15036, 40098, 38399, + 9196, 38846, 6384, 23405, 36395, 841, 8, 1, 14, 16, 10, + 12, 11, 32, 42, 56, 52, 66, 86, 75, 79, 165, + 145, 137, 189, 210, 227, 209, 216, 214, 244, 250, 267, + 274, 288, 305, 313, 337, 359, 361, 373, 374, 400, 413, + 392, 500, 501, 504, 389, 409, 499, 436, 449, 465, 461, + 472, 467, 491, 506, 469, 516, 525, 523, 531, 524, 540, + 542, 549, 576, 572, 579, 568, 573, 574, 606, 607, 649, + 629, 623, 646, 622, 621, 630, 651, 654, 658, 681, 683, + 677, 696, 708, 691, 709, 695, 698, 724, 726, 719, 733, + 1838, 38831, 10351, 10362, 1840, 30334, 36932, 7331, 8115, 24628, 5387, + 18741, 38652, 16910, 13905, 33673, 12901, 22069, 167, 18606, 33583, 40026, + 5323, 171, 9202, 17301, 8456, 30503, 23461, 37616, 29257, 33117, 31795, + 7700, 20382, 20471, 27042, 37830, 22045, 7398, 19628, 32328, 27051, 34730, + 39249, 35022, 26599, 11991, 4982, 39142, 15863, 14391, 26701, 19781, 20602, + 40299, 39070, 27052, 5957, 21320, 40867, 3019, 1773, 20085, 18367, 29599, + 6043, 5667, 21158, 20476, 33862, 39197, 34774, 20611, 39955, 20603, 19713, + 26477, 10084, 11412, 3387, 4848, 14770, 6836, 19422, 32354, 31503, 16106, + 26279, 29314, 9726, 30358, 16844, 27086, 24480, 17804, 39274, 747, 743, + 757, 765, 756, 753, 793, 792, 817, 800, 811, 828, 840, + 856, 846, 839, 867, 917, 889, 873, 891, 893, 876, 880, + 913, 914, 898, 958, 971, 969, 986, 1009, 1037, 1031, 1053, + 1070, 1054, 1082, 1105, 1110, 1139, 1128, 1120, 1281, 1261, 1285, + 1157, 1199, 1191, 1153, 1166, 1256, 1159, 1212, 1274, 1154, 22612, + 1314, 1339, 1328, 1196, 1419, 1396, 1403, 1429, 1431, 1473, 1469, + 1458, 1505, 1506, 1510, 1490, 1526, 1533, 1549, 1592, 1636, 1628, + 1645, 1671, 1688, 1691, 1705, 1694, 1687, 1728, 1749, 1747, 1768, + 1757, 1763, 1770, 1769, 16885, 16293, 28198, 14778, 1258, 11882, 18742, + 35833, 40053, 37049, 11883, 19299, 32034, 33282, 11629, 9729, 38021, 4291, + 12893, 19791, 10767, 33754, 29342, 33674, 7183, 31108, 16003, 19993, 31023, + 15616, 5314, 3137, 24488, 20650, 27542, 38274, 38818, 35923, 5871, 15586, + 20651, 27566, 4523, 18492, 3432, 19388, 9613, 11446, 25721, 31608, 23085, + 26687, 17726, 3112, 32214, 35221, 33700, 20725, 9663, 13168, 35250, 122, + 11829, 13049, 38901, 19738, 3867, 25987, 21670, 34016, 35103, 12044, 19896, + 20211, 22800, 20212, 17281, 15882, 33777, 20215, 12069, 18633, 19911, 18418, + 9438, 19435, 31767, 28875, 15246, 40267, 17875, 37285, 27586, 38249, 14998, + 26660, 1802, 1794, 1836, 1848, 1861, 1832, 1844, 1833, 1919, 1889, + 1929, 1906, 1944, 1877, 1882, 1915, 1914, 2053, 1922, 22910, 1881, + 2075, 2050, 2074, 2073, 2121, 2091, 2092, 2095, 2150, 2118, 2101, + 2157, 2172, 2184, 2180, 2175, 2182, 2203, 2207, 2191, 2195, 2210, + 2212, 2233, 2221, 2248, 2246, 2250, 2279, 2294, 2322, 2325, 2318, + 2321, 2343, 2356, 2357, 2373, 2362, 2390, 2406, 2423, 2405, 2404, + 2410, 2471, 2488, 2510, 2489, 2535, 2536, 2534, 2555, 2545, 2553, + 2583, 2587, 2585, 2608, 2619, 2620, 2661, 2297, 2695, 2686, 2680, + 2690, 2777, 2758, 2778, 2846, 2864, 2868, 10744, 36464, 39996, 13480, + 38348, 37678, 487, 6090, 23453, 40823, 31325, 38928, 15637, 8498, 5090, + 14849, 17110, 7847, 20383, 6872, 15252, 39555, 13800, 1685, 6896, 38930, + 28181, 22046, 14015, 20604, 14392, 37243, 15352, 30086, 6910, 20767, 40300, + 21803, 22825, 18023, 22213, 16655, 1841, 22975, 36674, 15893, 15515, 24946, + 40142, 15822, 6922, 23602, 18722, 30681, 77, 32347, 34373, 22326, 16633, + 10654, 24437, 30593, 24046, 35764, 15519, 25057, 2837, 16484, 10582, 37016, + 32612, 31971, 19527, 19201, 36638, 3054, 3089, 34620, 26107, 16086, 37286, + 3602, 11247, 18655, 3202, 21844, 27795, 40631, 15523, 34314, 40521, 15551, + 3318, 23294, 40977, 24422, 2929, 2895, 2898, 38781, 2896, 2892, 2928, + 2966, 2948, 2952, 2949, 2980, 2969, 2975, 2993, 3000, 3003, 2991, + 3014, 3016, 3045, 3059, 3097, 3087, 3071, 3098, 3121, 3146, 3152, + 3145, 3239, 3149, 3151, 3153, 3220, 3215, 3269, 3249, 3299, 3361, + 3289, 3291, 3306, 3334, 3326, 3357, 3296, 3294, 3381, 3382, 3392, + 3400, 3422, 3462, 27146, 3451, 3457, 3450, 3453, 3530, 3520, 3517, + 3512, 3572, 3589, 3566, 3582, 3668, 3669, 3716, 3720, 3739, 3762, + 3879, 3800, 3815, 3807, 3804, 3808, 3782, 3796, 3863, 3852, 3872, + 3882, 3880, 3927, 3902, 3936, 3907, 3916, 3903, 3899, 4042, 17886, + 15034, 1855, 20402, 12894, 10472, 25065, 16830, 36154, 31273, 23295, 19084, + 21081, 25656, 34395, 6104, 30103, 36323, 15459, 30808, 27593, 39105, 6506, + 31983, 5309, 29098, 21126, 29345, 23514, 6666, 7727, 25080, 25081, 19280, + 8915, 28036, 6844, 18244, 27661, 28819, 11171, 22467, 30714, 29277, 31987, + 31573, 17439, 30616, 37886, 6535, 16176, 40390, 24428, 40393, 2707, 23533, + 310, 22339, 18336, 18671, 15242, 4173, 3207, 36223, 16748, 1551, 23534, + 23535, 4724, 40929, 4333, 19093, 12202, 26335, 16574, 38349, 13169, 31865, + 6111, 28687, 22075, 37991, 24028, 5540, 17237, 13215, 31909, 38791, 24066, + 13050, 37385, 40538, 10434, 15472, 38282, 16693, 3948, 3951, 4040, 4007, + 4014, 3969, 4058, 4076, 4080, 4096, 4088, 4092, 4111, 4118, 4135, + 4137, 4155, 4150, 4166, 4175, 4186, 4187, 4196, 4205, 4191, 4224, + 4230, 4271, 4252, 4257, 4250, 4296, 4301, 4316, 4349, 4378, 4394, + 4395, 4393, 4391, 4380, 4367, 4421, 4441, 4455, 4437, 4517, 4494, + 4476, 4474, 4542, 4543, 4597, 4616, 4656, 4660, 4631, 4683, 4698, + 4694, 4718, 4708, 4709, 4759, 4770, 4775, 4763, 4777, 4809, 4816, + 4824, 4834, 4835, 4829, 4881, 4878, 4889, 4904, 4923, 4948, 4990, + 4976, 4978, 4994, 5001, 5004, 5066, 5024, 5028, 5009, 5031, 5043, + 5025, 5003, 15417, 3963, 35256, 25094, 5325, 35599, 22479, 22480, 37400, + 22778, 7016, 127, 15391, 12945, 37401, 25671, 22224, 4412, 1992, 34878, + 19314, 32228, 15883, 16704, 16767, 39850, 17282, 17303, 7282, 25102, 22227, + 36376, 17317, 18419, 18420, 20683, 27482, 9439, 16384, 38083, 34444, 25358, + 37696, 28401, 19290, 32946, 34890, 23236, 1004, 6557, 39948, 25323, 35302, + 26922, 36888, 39636, 29373, 8162, 20119, 28107, 19778, 2621, 18888, 37151, + 31203, 40301, 9590, 31959, 39396, 8611, 8612, 27535, 13955, 26704, 8315, + 16085, 5668, 28948, 9227, 9413, 41178, 18052, 18733, 5357, 39475, 851, + 39020, 11621, 36843, 36087, 40746, 12010, 39095, 37650, 31208, 32268, 5026, + 5094, 5086, 5081, 5085, 5096, 5146, 5142, 5167, 5189, 5169, 5181, + 5184, 5174, 5180, 5186, 5244, 5268, 5269, 5294, 5295, 5336, 5354, + 5370, 5379, 5352, 5356, 5351, 5376, 5397, 5383, 5388, 5385, 5439, + 5448, 5446, 5472, 5453, 5454, 5478, 5493, 5484, 5482, 5527, 5511, + 5533, 5551, 5553, 5558, 5546, 5554, 5567, 5565, 5613, 5611, 5445, + 5681, 5669, 5651, 5642, 5658, 5679, 5742, 5730, 5735, 5776, 5765, + 5763, 5827, 5792, 5785, 5786, 5726, 5790, 5799, 5803, 5801, 5807, + 5863, 5845, 5872, 5852, 5841, 5900, 5892, 5893, 5899, 5932, 5931, + 5993, 6000, 5938, 5963, 5982, 34789, 39418, 35326, 19721, 27644, 5686, + 957, 39106, 36651, 12342, 8617, 28813, 27650, 19304, 28476, 8283, 33758, + 23326, 37386, 12189, 27760, 2708, 5210, 9664, 28220, 17052, 21736, 20037, + 5372, 17259, 37771, 29146, 38113, 16818, 25504, 32972, 29726, 25270, 40824, + 2532, 35686, 32065, 21371, 24532, 7658, 10257, 37832, 39383, 14028, 39384, + 37235, 15685, 634, 22443, 21223, 17133, 36749, 22444, 1902, 18024, 21375, + 41241, 39397, 14605, 11961, 29601, 39676, 11963, 10377, 36071, 40723, 39677, + 25290, 6440, 40143, 21725, 8186, 15317, 34120, 27536, 16087, 8429, 14044, + 29079, 29786, 34272, 19085, 18744, 9230, 41250, 40563, 702, 12150, 39419, + 16090, 16831, 6048, 6056, 6050, 6057, 6069, 6074, 6103, 6091, 6086, + 6118, 6123, 6124, 6168, 6171, 6182, 6193, 6185, 6191, 6184, 6194, + 6228, 6253, 6268, 6258, 6269, 6277, 6285, 6227, 6330, 6340, 6353, + 6341, 6346, 6410, 6419, 6416, 6426, 6456, 6428, 6434, 6446, 6425, + 6479, 6487, 6507, 6491, 6493, 6498, 6525, 6553, 6549, 6550, 6608, + 6603, 6623, 6605, 6646, 6635, 6643, 6639, 6650, 6677, 6670, 6667, + 6685, 6716, 6736, 6805, 6785, 6777, 6758, 6778, 6771, 6843, 6826, + 6841, 6823, 6847, 6819, 6825, 6909, 6880, 6889, 6951, 6927, 6914, + 7048, 7064, 7063, 7106, 7105, 7110, 7109, 7130, 22358, 1781, 41179, + 37306, 19031, 32448, 35331, 31835, 1443, 12580, 8034, 22616, 21892, 13590, + 39938, 40916, 33575, 3263, 5393, 32193, 40756, 37348, 33687, 39772, 8588, + 9186, 25424, 28208, 25502, 12605, 15273, 2286, 19731, 39814, 12581, 18795, + 27949, 12190, 36486, 30968, 24546, 10483, 35925, 11519, 24179, 12459, 32656, + 23087, 13378, 40582, 39942, 41203, 18909, 28230, 21738, 26044, 11830, 25199, + 21903, 37402, 22780, 12638, 29927, 30970, 3279, 12045, 15884, 18912, 1574, + 26068, 40587, 17002, 4693, 30178, 36925, 26592, 14093, 35065, 16547, 35024, + 738, 1774, 30186, 40196, 13512, 5896, 31155, 9519, 4136, 35073, 32613, + 3320, 15606, 5194, 40632, 33498, 7138, 7153, 7171, 7178, 7163, 7162, + 7173, 7191, 7196, 7220, 7205, 7207, 7218, 7257, 7236, 7239, 7269, + 7228, 7240, 7296, 7299, 7321, 7322, 7307, 7314, 7313, 7412, 7363, + 7360, 7380, 7379, 7376, 7377, 7387, 7388, 7393, 7409, 7423, 7417, + 7419, 7415, 7449, 7462, 7463, 7487, 7494, 7489, 7492, 7497, 7562, + 7576, 7558, 7565, 7556, 7561, 7592, 7613, 7595, 7645, 7654, 7650, + 7655, 7660, 7661, 7686, 7698, 7697, 7724, 7706, 7721, 7687, 7699, + 7711, 7762, 7757, 7795, 7778, 7788, 7787, 7912, 7822, 8275, 7879, + 7842, 7876, 7917, 7927, 8023, 7995, 7944, 7980, 7909, 7939, 7929, + 27946, 9358, 40701, 31051, 30197, 34275, 24489, 34973, 34974, 29414, 3004, + 29278, 5919, 14665, 17748, 31591, 31377, 15906, 4145, 38841, 15806, 15802, + 3278, 4790, 22722, 38218, 4701, 24116, 24508, 6310, 38223, 18467, 24197, + 3973, 27142, 8156, 23881, 3982, 10636, 23244, 10307, 26818, 7684, 20312, + 24864, 40302, 18026, 18369, 1803, 563, 27745, 10663, 14148, 5911, 35836, + 27380, 14140, 24870, 22832, 26451, 40406, 2481, 5464, 4815, 30253, 14176, + 15229, 14178, 16653, 22345, 3463, 19489, 40191, 30428, 32698, 28108, 24295, + 34192, 40511, 37545, 10164, 2455, 1206, 35567, 6142, 26225, 4900, 40199, + 20890, 9091, 24157, 20437, 727, 2415, 22285, 18039, 7963, 7977, 8014, + 8278, 7908, 8276, 8091, 8112, 8105, 8107, 8098, 23067, 8117, 8095, + 8124, 8165, 8177, 8255, 8192, 8160, 8280, 8146, 8157, 8144, 8201, + 8148, 8183, 8145, 8151, 8147, 8200, 8277, 8292, 8288, 8303, 8326, + 8354, 8344, 8345, 8347, 8453, 8366, 8372, 8387, 8388, 8375, 8425, + 8430, 8422, 8426, 8479, 8486, 8489, 8501, 8500, 8493, 8492, 8524, + 8529, 8491, 8559, 8539, 8542, 8552, 8540, 8560, 8580, 8591, 8589, + 8602, 8640, 8656, 8649, 8624, 8645, 8641, 8635, 8646, 8680, 8698, + 8686, 9855, 8679, 8702, 8771, 8765, 8766, 8777, 8780, 8781, 8801, + 8851, 8797, 8818, 21793, 7981, 7243, 8428, 7332, 26982, 19612, 29224, + 24460, 20466, 19202, 9638, 24710, 3475, 36081, 35076, 1137, 16125, 32710, + 28278, 25559, 12140, 10173, 39960, 16263, 5247, 2429, 7871, 29795, 16886, + 16488, 14557, 9388, 13016, 9999, 29611, 31979, 39729, 3335, 28109, 40326, + 41251, 29499, 2430, 8616, 8400, 15895, 37851, 21909, 32729, 23023, 16270, + 41006, 1142, 1283, 8774, 28568, 9328, 36938, 12902, 5394, 3490, 39281, + 26164, 40054, 18759, 17890, 15082, 8036, 38433, 9107, 23685, 15083, 4206, + 2436, 41062, 2035, 33760, 1408, 28286, 32274, 22883, 33226, 10954, 35493, + 37676, 4232, 18939, 31167, 6172, 27597, 12360, 13689, 33227, 19796, 7349, + 8826, 8833, 8836, 8869, 8879, 8874, 8894, 8899, 8881, 8895, 8871, + 8887, 8870, 8935, 8938, 8941, 8966, 8965, 8990, 8985, 8988, 9017, + 9016, 9037, 9034, 9036, 9041, 9100, 9245, 9241, 9106, 9075, 9081, + 9080, 9079, 9171, 9128, 9154, 9143, 9134, 9136, 9216, 9219, 9215, + 9228, 9250, 9247, 9290, 9294, 9302, 9309, 9313, 9324, 9331, 9355, + 9344, 9346, 9347, 9345, 9389, 9384, 9442, 9408, 9434, 9405, 9448, + 9473, 9488, 9528, 9501, 9498, 9517, 9497, 9500, 9505, 9568, 9585, + 9573, 9581, 9631, 9624, 9645, 9629, 9621, 9702, 9703, 9724, 9745, + 9741, 9775, 9815, 9829, 9842, 9852, 4101, 7729, 40212, 11512, 24176, + 24543, 20301, 23867, 9246, 27150, 37860, 10424, 28826, 37751, 3775, 25751, + 39290, 21561, 23871, 32734, 18460, 22371, 6423, 40655, 3924, 26184, 40342, + 23917, 18391, 12925, 2141, 11820, 1323, 5576, 4530, 34331, 2288, 40435, + 22545, 22735, 37403, 29872, 38280, 26185, 9666, 35511, 11110, 2803, 15620, + 22891, 38216, 12203, 18558, 2445, 21407, 28316, 4699, 5930, 28320, 16661, + 17640, 32657, 1994, 20176, 26186, 5326, 17691, 5126, 8136, 13052, 20456, + 16020, 5072, 13388, 28288, 16577, 32670, 18831, 27131, 38058, 23566, 22021, + 23567, 22022, 8443, 14681, 6469, 18819, 34425, 5260, 25846, 40367, 18405, + 23712, 17474, 27152, 9876, 9871, 9885, 9904, 9895, 9903, 9902, 9940, + 9948, 9960, 9997, 9959, 9985, 9990, 9961, 10028, 10024, 10117, 10114, + 10060, 10053, 10113, 10059, 10073, 10051, 10046, 10147, 10160, 10166, 10231, + 10230, 10219, 10210, 10245, 10243, 10265, 10247, 10263, 2, 10318, 10366, + 10381, 10361, 10329, 10336, 10332, 10331, 10375, 10215, 10355, 10340, 10372, + 10478, 10475, 10481, 10463, 10511, 10510, 10521, 10525, 10526, 10529, 10531, + 10530, 10550, 10552, 10541, 10572, 10573, 10575, 10641, 10660, 10634, 10617, + 10613, 10615, 10748, 10742, 10755, 10788, 10800, 10823, 10797, 10828, 11132, + 10831, 10937, 10904, 10931, 10903, 10955, 10899, 11135, 10927, 16374, 16026, + 37099, 37762, 10240, 39121, 28584, 29215, 21586, 3842, 36044, 23568, 29029, + 40448, 40116, 7224, 27934, 40115, 23884, 40688, 29034, 18845, 18634, 13077, + 30175, 36458, 37443, 16319, 18426, 24203, 17489, 16389, 23726, 37776, 39922, + 24839, 17490, 1428, 6517, 41133, 17003, 27697, 19143, 36463, 37788, 40697, + 37463, 7237, 26584, 38932, 26593, 21817, 10353, 21219, 4826, 38819, 23648, + 38573, 1129, 611, 31340, 26095, 15253, 25531, 1207, 4755, 36301, 38944, + 3528, 28611, 11133, 8395, 14615, 20614, 40081, 16867, 27990, 10664, 29606, + 2416, 17884, 40461, 529, 16635, 7084, 24711, 10507, 32364, 8016, 17038, + 37731, 18760, 14496, 23311, 553, 38759, 10897, 11017, 11134, 11051, 11033, + 11053, 11037, 11139, 11141, 11154, 11168, 11167, 11202, 11196, 11195, 11203, + 11254, 11252, 11251, 11253, 11269, 11445, 11308, 11317, 9870, 11372, 11393, + 11399, 11391, 11411, 11423, 11401, 11395, 11389, 11382, 11458, 11466, 11484, + 11518, 11515, 11526, 11478, 11481, 11490, 11497, 11585, 11562, 11556, 11561, + 11587, 11595, 11614, 11641, 11593, 11676, 11658, 11692, 11686, 11784, 11714, + 11744, 11739, 11736, 11740, 11717, 11734, 11716, 11718, 11730, 11727, 11867, + 11865, 11870, 11899, 11888, 11923, 11953, 11960, 11971, 11970, 11993, 11984, + 12005, 12033, 11985, 12003, 12084, 12091, 12122, 12092, 12149, 12172, 12116, + 12165, 9826, 11248, 25875, 28821, 1446, 20270, 40981, 13151, 16920, 33037, + 7888, 21897, 944, 9192, 33428, 12843, 40466, 28832, 25878, 7674, 13311, + 20543, 25880, 25881, 21902, 31620, 17594, 15779, 2045, 11355, 27419, 40991, + 32416, 29880, 21596, 17304, 41305, 5596, 21597, 29426, 16460, 27616, 14252, + 8883, 39310, 14255, 36878, 12504, 2589, 40072, 34040, 37669, 10638, 36927, + 10354, 30311, 25324, 30918, 24603, 20884, 40718, 29702, 21704, 7818, 12520, + 27232, 4254, 22445, 39193, 26096, 10647, 39561, 12287, 7569, 37839, 25327, + 5145, 13856, 7401, 4756, 14300, 37958, 505, 7861, 39679, 4428, 3795, + 10655, 37959, 31805, 7982, 32973, 26608, 1846, 40308, 24702, 12096, 12087, + 12110, 12186, 12083, 12100, 12113, 12124, 12141, 12257, 12266, 12316, 12678, + 12406, 12323, 12252, 12282, 12289, 12262, 12265, 12326, 12263, 12437, 12422, + 12290, 12423, 12562, 12482, 12600, 12489, 12473, 12538, 12488, 12533, 12502, + 12528, 12527, 12471, 12472, 12500, 12480, 12487, 12479, 12521, 12477, 12731, + 12698, 12686, 12690, 12704, 12683, 12756, 12772, 12807, 12798, 12808, 12809, + 12842, 12827, 12829, 12828, 12836, 12850, 12863, 12849, 12847, 12869, 12851, + 12891, 12861, 12856, 12857, 12846, 12882, 12987, 12996, 12984, 13026, 13005, + 12978, 12990, 13017, 12981, 12994, 12993, 13104, 15217, 13136, 13132, 13105, + 13095, 13137, 13149, 13096, 18040, 40309, 26475, 8463, 34826, 7983, 30092, + 39146, 5039, 3994, 26842, 39899, 32167, 41101, 14191, 636, 24774, 20615, + 27363, 41174, 15894, 14040, 25337, 10174, 32985, 13675, 40148, 3802, 9307, + 530, 14890, 15867, 10929, 4451, 11324, 8809, 28900, 13676, 15693, 13438, + 24955, 8331, 19203, 33867, 1015, 32355, 8003, 8778, 6205, 25405, 29420, + 36082, 16737, 32986, 14772, 8316, 5975, 29661, 27637, 13300, 32482, 11748, + 14891, 13018, 14779, 3424, 20246, 39156, 18895, 3336, 24637, 27254, 680, + 29662, 32622, 11328, 24219, 8841, 33427, 29094, 29719, 32864, 10674, 31826, + 8017, 29475, 28134, 6569, 16091, 7872, 14050, 11091, 39420, 34384, 14222, + 7768, 13108, 13113, 13100, 13099, 13117, 13128, 13111, 13098, 13239, 13222, + 13223, 13226, 13217, 13256, 13268, 13265, 13263, 13262, 13324, 13302, 13291, + 13368, 13347, 13377, 13348, 13343, 13329, 13333, 13337, 13341, 13335, 14974, + 13433, 13430, 13428, 13413, 13429, 13418, 13411, 13420, 13475, 13419, 13441, + 13518, 13529, 13515, 13516, 13501, 13520, 13577, 13565, 13564, 13569, 13583, + 13562, 13699, 13620, 13613, 14466, 13631, 13659, 13686, 13704, 13640, 13644, + 13772, 13835, 13788, 12387, 13789, 13797, 13803, 13778, 13799, 13802, 13792, + 13837, 13859, 13839, 13847, 13838, 13848, 13877, 13894, 13901, 13887, 13900, + 13932, 13968, 13942, 13965, 13931, 13945, 13943, 12560, 33722, 25350, 40917, + 3132, 6738, 17192, 18934, 17584, 3814, 25010, 26479, 23312, 40560, 23314, + 30362, 23861, 32374, 27194, 30609, 28952, 30363, 8518, 30488, 1026, 40547, + 2205, 9827, 4776, 19074, 18312, 23432, 38711, 1284, 4326, 18078, 20197, + 23178, 24172, 29274, 40918, 9708, 41007, 31550, 40757, 33305, 17613, 13906, + 7433, 25680, 20409, 37327, 40962, 7255, 18935, 33675, 36332, 26411, 23564, + 33688, 32452, 12910, 15463, 32383, 25659, 20198, 12174, 6508, 3727, 5706, + 20412, 20286, 37582, 33023, 775, 27664, 24544, 1409, 11374, 8812, 4515, + 20252, 30818, 8219, 30723, 29690, 9005, 20302, 32879, 17545, 40923, 1499, + 37925, 36094, 29108, 9270, 13888, 13928, 14029, 14051, 14026, 14180, 14042, + 14058, 14023, 14036, 14054, 14049, 14025, 14079, 14110, 14096, 14095, 14158, + 14154, 14146, 14167, 14119, 14132, 14153, 14143, 14133, 14117, 14209, 14217, + 14266, 14251, 14243, 14294, 14298, 14286, 14293, 14285, 14301, 14328, 14329, + 14309, 14312, 14339, 14314, 14331, 14315, 14442, 14381, 14383, 14389, 14379, + 14386, 14478, 14456, 14545, 14698, 14549, 14547, 14646, 14590, 14623, 14580, + 14595, 14627, 14658, 14638, 14607, 14581, 14622, 14602, 14612, 14706, 14716, + 14705, 14753, 14765, 14728, 14760, 14810, 14990, 14831, 14866, 14855, 14948, + 14853, 14822, 14827, 14850, 15019, 15032, 15027, 15016, 15018, 15057, 39797, + 37926, 3270, 2704, 5062, 31989, 37583, 40963, 33517, 36533, 30882, 8813, + 33761, 36430, 13993, 35927, 40529, 21344, 670, 9188, 22073, 40106, 12926, + 4357, 24971, 27504, 37811, 31993, 4725, 31593, 25427, 28917, 8234, 37861, + 3140, 8592, 25620, 10972, 38051, 29018, 32392, 28047, 39166, 40986, 28918, + 11586, 2213, 1324, 7803, 4661, 16931, 28321, 34542, 31756, 40988, 16690, + 14796, 23873, 19460, 39506, 18910, 20825, 22736, 17449, 33886, 40965, 12204, + 26249, 28231, 18947, 1048, 35343, 25953, 20726, 23973, 11905, 32429, 12621, + 26179, 33449, 25162, 33887, 28240, 24032, 38351, 41272, 39439, 26341, 25882, + 17912, 37404, 7217, 17692, 4336, 41212, 13177, 15051, 15072, 15059, 15053, + 15061, 15112, 15111, 15116, 8636, 15122, 15127, 15153, 15138, 15148, 15184, + 15189, 15187, 15199, 15202, 15234, 15254, 15263, 15275, 15283, 15295, 15290, + 15297, 15310, 15312, 15316, 15332, 15402, 15340, 15343, 15356, 15379, 15375, + 15347, 15397, 9863, 15401, 15413, 15420, 15421, 15430, 15438, 15483, 15489, + 15485, 15488, 15507, 15506, 15540, 15567, 15561, 15570, 15577, 15588, 15595, + 15603, 15639, 15642, 15653, 15675, 15698, 15681, 15695, 15708, 15723, 15731, + 15734, 15732, 15750, 15766, 15753, 15751, 15785, 15795, 15808, 15823, 15837, + 15820, 15859, 15866, 15855, 15854, 15896, 15901, 15898, 15903, 15933, 15919, + 15944, 9513, 25253, 2808, 25691, 33451, 11831, 11237, 41125, 31621, 23975, + 37950, 4993, 26771, 11839, 31883, 26048, 13056, 13257, 11356, 38191, 4535, + 33072, 13485, 1364, 5231, 35976, 21750, 28241, 35977, 26189, 33538, 12646, + 1718, 23832, 16375, 23096, 34019, 23371, 22388, 35107, 20685, 16814, 32916, + 41131, 15885, 36713, 33713, 16706, 32130, 2737, 13561, 18635, 2741, 36384, + 2188, 25227, 32139, 41155, 41134, 19241, 17008, 16437, 16726, 17568, 10622, + 25315, 40274, 39178, 5947, 31801, 36313, 28945, 37800, 32356, 4711, 32948, + 7826, 7827, 23560, 1847, 22870, 32538, 38907, 8519, 36341, 9429, 41213, + 28693, 2352, 23551, 31035, 36369, 16707, 28708, 18636, 30456, 8487, 16001, + 15997, 15998, 16037, 16038, 16081, 16101, 16117, 16115, 16130, 16129, 16157, + 16159, 16177, 16197, 16188, 16200, 16234, 16247, 16240, 16294, 16338, 16330, + 16328, 16326, 16347, 16336, 16323, 16342, 16340, 16404, 16400, 16414, 16405, + 16439, 16442, 16479, 16481, 16471, 16474, 16465, 16508, 16524, 16541, 16543, + 16545, 16589, 16590, 16593, 16619, 16616, 16615, 16670, 16644, 16671, 16695, + 16749, 16745, 16794, 16750, 16733, 16683, 16639, 16786, 16784, 16828, 16829, + 16840, 16850, 16862, 16865, 16925, 16929, 17392, 16855, 16881, 17034, 17388, + 17022, 17046, 17018, 17136, 17112, 17079, 17125, 17082, 17074, 17085, 17132, + 17072, 17083, 17154, 17091, 17101, 19100, 19997, 9088, 40240, 14393, 19562, + 20385, 9305, 29081, 14773, 8004, 26714, 9308, 40633, 37307, 199, 7184, + 27651, 19309, 18315, 508, 7186, 3007, 30824, 1306, 12622, 3699, 18321, + 14799, 20177, 38902, 19121, 22553, 12239, 12248, 18996, 20079, 4932, 34765, + 36830, 36826, 7603, 415, 34853, 9147, 23893, 38123, 8541, 35767, 40311, + 35453, 25406, 25125, 23970, 11329, 32366, 35839, 34877, 23913, 23777, 37060, + 8814, 37590, 7276, 26253, 7633, 26255, 17516, 21764, 23983, 8968, 3679, + 7570, 10648, 3588, 4757, 7984, 31961, 974, 16161, 22449, 18327, 39680, + 24775, 31677, 32855, 31815, 15400, 11750, 11613, 32614, 26159, 10675, 13238, + 5395, 26165, 17161, 17078, 17148, 17088, 17100, 17070, 16909, 17390, 17396, + 17410, 17404, 17399, 17470, 17416, 17402, 17403, 17401, 17498, 17500, 17536, + 17524, 17523, 17522, 17581, 17573, 17574, 17582, 17571, 17601, 17625, 17632, + 17628, 17621, 17624, 17641, 17650, 17654, 17645, 17677, 17656, 17643, 16604, + 16667, 17744, 17750, 17743, 17738, 17758, 17800, 17784, 17759, 17793, 17883, + 17872, 17908, 17906, 17873, 17871, 17923, 17880, 17939, 17960, 17954, 17869, + 18015, 18047, 18069, 18073, 18027, 18198, 18043, 18018, 17998, 18028, 18181, + 18184, 18189, 18188, 18203, 18216, 18237, 18222, 18235, 18214, 18207, 18242, + 18213, 18301, 18322, 18355, 18374, 18357, 18373, 18490, 3621, 33762, 3633, + 40924, 30323, 11637, 10772, 10484, 22708, 17450, 10778, 388, 17913, 22308, + 24117, 319, 11840, 33778, 5413, 16588, 9021, 9024, 9022, 6042, 25643, + 20953, 6473, 29465, 22450, 35446, 24887, 12713, 14617, 3911, 19086, 12344, + 38443, 18527, 12216, 16626, 12055, 36714, 11266, 35659, 24244, 37841, 5093, + 10650, 39460, 22105, 39147, 3085, 39261, 36833, 30232, 29359, 7086, 34266, + 29432, 33721, 10275, 26807, 17805, 14055, 1143, 5631, 9790, 30929, 33677, + 22828, 4503, 6116, 21244, 29510, 14568, 4516, 15905, 17570, 17440, 31024, + 16010, 17452, 17460, 4531, 26764, 27831, 29478, 16021, 21572, 39509, 5128, + 21658, 24133, 21295, 29481, 29483, 18377, 18455, 18457, 18454, 18507, 18495, + 18546, 18554, 18567, 18561, 18587, 18584, 18602, 18586, 18590, 18653, 18650, + 18652, 18656, 18838, 18743, 18843, 18747, 18710, 18726, 18790, 18732, 18702, + 18698, 18768, 18856, 18874, 18892, 18876, 18885, 18903, 18893, 18896, 18922, + 18928, 18920, 18923, 18931, 18924, 18969, 18970, 18968, 18975, 19014, 19016, + 6920, 6921, 19048, 19056, 19051, 19050, 19053, 19054, 19088, 19105, 19116, + 19094, 19106, 19110, 19111, 19112, 19164, 19205, 19188, 19191, 19189, 19246, + 19252, 19272, 19273, 19275, 19270, 19292, 19322, 19319, 19325, 19336, 19347, + 19348, 19344, 19349, 19385, 19383, 19378, 19423, 19450, 19437, 19444, 19446, + 18428, 38870, 27734, 28012, 38887, 35622, 24575, 15481, 2395, 8632, 1880, + 11384, 35553, 25316, 25595, 37630, 2496, 9963, 7602, 22233, 22164, 36737, + 25138, 30952, 23238, 22496, 31433, 31434, 15484, 5948, 7496, 441, 1892, + 24766, 29258, 40825, 15641, 39386, 21316, 22853, 40874, 8102, 32156, 20763, + 24695, 15349, 3523, 34729, 22120, 3409, 33330, 7078, 10544, 40875, 9510, + 3313, 29408, 4758, 19699, 32841, 32842, 19351, 33103, 21624, 30398, 30956, + 33384, 14141, 36834, 10535, 17796, 26222, 29538, 19704, 4258, 26705, 23810, + 5449, 14711, 4636, 33382, 33175, 30049, 3321, 21174, 6282, 21151, 22573, + 9153, 17150, 38808, 4768, 13582, 17610, 27518, 1535, 19380, 19478, 19490, + 19485, 19483, 19476, 19525, 19549, 19558, 19575, 19552, 19553, 19611, 19599, + 19622, 19623, 19645, 19666, 19629, 19681, 19693, 19691, 19702, 19725, 19730, + 19718, 19690, 19696, 19708, 19762, 19749, 19751, 19775, 19784, 19770, 19783, + 19807, 19829, 19841, 19850, 19861, 19886, 19857, 19950, 19943, 19969, 19967, + 19992, 20027, 20041, 20030, 20000, 20007, 19996, 20075, 20122, 20117, 20115, + 20152, 20123, 20130, 20194, 20190, 20192, 20236, 20223, 20230, 20232, 20244, + 20267, 20279, 20283, 20284, 20304, 20294, 20297, 20310, 20309, 20338, 20325, + 20371, 20426, 20421, 20436, 20434, 20432, 20468, 20493, 20469, 20478, 20467, + 20512, 20521, 20523, 19070, 22664, 16738, 15999, 4203, 5190, 21176, 20925, + 25338, 26706, 4321, 14411, 6206, 22523, 9783, 31103, 19760, 21242, 40424, + 3610, 19108, 21952, 5687, 158, 21122, 27465, 37918, 39936, 25539, 29796, + 30707, 13447, 12729, 6504, 1260, 2905, 23820, 30237, 27935, 28814, 28023, + 40524, 35865, 17661, 12345, 22533, 32872, 18906, 21942, 2913, 18775, 9793, + 22128, 4062, 13280, 7881, 40391, 18940, 13367, 36514, 18865, 33987, 4239, + 29639, 21350, 17679, 4787, 9543, 32651, 29000, 7265, 39501, 13376, 10882, + 4782, 25733, 32453, 28168, 7672, 40366, 5158, 15776, 21737, 14950, 4032, + 14742, 16204, 17511, 30010, 23356, 4798, 1735, 34014, 21149, 31120, 38151, + 20532, 20552, 20533, 20535, 20542, 20537, 20555, 20564, 20574, 20609, 20656, + 20664, 20585, 20630, 20628, 20589, 20712, 20703, 20735, 20834, 20754, 20753, + 20756, 20752, 20808, 20817, 20810, 20802, 20816, 20782, 20786, 20814, 20792, + 20822, 20843, 20858, 21165, 20881, 20865, 20877, 20868, 20937, 20934, 20935, + 20954, 20950, 20981, 20977, 20987, 21039, 21070, 21108, 21104, 21141, 21144, + 21166, 21173, 21184, 21198, 21202, 21210, 21252, 21220, 21216, 21211, 21266, + 21265, 21318, 21336, 21317, 21334, 21368, 21366, 21369, 21404, 21403, 21392, + 21421, 21444, 21439, 21445, 21480, 21485, 21510, 21577, 21512, 21555, 21556, + 21508, 21619, 21631, 21628, 21645, 21625, 32410, 1570, 33312, 15790, 16213, + 34337, 18628, 12065, 37968, 19174, 24840, 38152, 18998, 21263, 37973, 23643, + 31085, 9490, 17909, 9479, 13410, 12550, 8548, 3874, 20199, 21562, 8697, + 13130, 5977, 39410, 33388, 28569, 32322, 2499, 31816, 37177, 33308, 14570, + 14357, 33196, 26571, 14297, 28626, 27099, 28754, 23128, 23129, 9394, 11238, + 29344, 31980, 5343, 7358, 21984, 28597, 7242, 4091, 18852, 18046, 31962, + 24471, 22142, 15738, 8018, 38211, 7769, 16889, 37042, 16489, 37308, 1945, + 21430, 14426, 11514, 15464, 1500, 20819, 5999, 6318, 712, 2519, 35929, + 2333, 18528, 5068, 33989, 35098, 5508, 5262, 23958, 18683, 35601, 12400, + 13191, 12056, 23372, 21627, 21674, 21683, 21692, 21703, 21694, 21724, 21722, + 21719, 21752, 21789, 21797, 21807, 21815, 21834, 21841, 21839, 21852, 21899, + 21904, 21875, 21908, 21912, 21915, 21913, 21964, 21947, 21950, 21911, 21985, + 21982, 21993, 22003, 22004, 21995, 22007, 22013, 22016, 22012, 22035, 22031, + 22054, 22049, 22059, 22072, 22103, 22104, 22094, 22101, 22118, 22137, 22141, + 22159, 22165, 22169, 22179, 22178, 22210, 22187, 22204, 22209, 22230, 22236, + 22248, 22256, 22253, 22247, 22284, 22274, 22273, 22297, 22302, 22320, 22315, + 22325, 22338, 22351, 22359, 22352, 22357, 22416, 22372, 22343, 22360, 22401, + 22410, 22424, 22439, 22482, 22421, 22427, 22466, 22521, 22497, 18687, 18637, + 2745, 27488, 12928, 22829, 34677, 34702, 2389, 16649, 29460, 29364, 13328, + 22342, 35640, 2607, 20188, 8369, 37221, 11046, 40855, 11728, 28117, 39609, + 29985, 30661, 23455, 30912, 25271, 7919, 33594, 11140, 14834, 9014, 335, + 3900, 19619, 25369, 10157, 36117, 36817, 35661, 24200, 22570, 29063, 5550, + 17099, 36665, 887, 35557, 21629, 21270, 1886, 1764, 33421, 35017, 32066, + 10627, 38458, 6129, 5937, 21487, 10836, 19694, 26740, 9083, 1183, 30779, + 7938, 40707, 5616, 12505, 4593, 37558, 33919, 8678, 17111, 25390, 2631, + 3157, 37236, 10193, 40858, 17774, 31198, 12506, 9504, 4446, 9039, 9457, + 13340, 36981, 40714, 7172, 19529, 39950, 22508, 22522, 22504, 22484, 22560, + 22575, 22618, 22595, 22636, 22654, 22647, 22690, 22693, 22704, 22748, 22720, + 22743, 22757, 22762, 22773, 22793, 22787, 22812, 22818, 22819, 22843, 22846, + 22864, 22839, 22841, 22858, 22840, 22848, 22907, 23008, 22918, 22932, 22974, + 22990, 22965, 22978, 23011, 23039, 23126, 23037, 23066, 23070, 23068, 23072, + 2111, 23105, 23107, 23110, 23108, 23112, 23134, 23133, 23161, 23163, 23150, + 23561, 23144, 23139, 23148, 23177, 23146, 23142, 23229, 23284, 23230, 23234, + 23271, 23263, 23253, 23222, 23309, 23237, 23220, 23282, 23413, 23398, 23392, + 23396, 23400, 23465, 23470, 23527, 23443, 23450, 23451, 23452, 23459, 23444, + 23572, 23638, 40193, 11316, 7850, 8309, 4899, 4110, 14030, 7076, 212, + 24042, 3465, 22855, 13851, 16597, 27355, 40455, 4934, 38234, 37472, 6438, + 30674, 16856, 6276, 7856, 25289, 36134, 2116, 37873, 28126, 3304, 3162, + 31199, 1650, 31464, 8834, 40304, 20608, 40458, 41242, 30044, 24604, 28297, + 3163, 22347, 19849, 33298, 14033, 3052, 15028, 34365, 4879, 10064, 4880, + 12762, 30449, 27979, 21705, 26418, 32342, 30978, 13652, 20986, 20798, 29848, + 8975, 19526, 4449, 5671, 24768, 6143, 41000, 16162, 18724, 30787, 21521, + 16046, 23069, 38016, 8578, 9822, 19067, 3797, 4197, 38703, 19814, 16868, + 803, 24329, 14735, 24245, 5625, 13570, 13896, 24047, 28561, 23589, 23590, + 23647, 23628, 23645, 23656, 23622, 23632, 23674, 23623, 23666, 8392, 23783, + 23746, 23747, 23740, 23773, 23818, 23802, 23823, 23846, 23849, 23836, 23860, + 23891, 23886, 23902, 23887, 23944, 23947, 23943, 23964, 24021, 24010, 24006, + 23989, 24044, 24065, 24039, 24040, 24077, 24113, 24108, 24099, 24091, 24088, + 24093, 24136, 12696, 24135, 24139, 24144, 24209, 24207, 24206, 24243, 24249, + 24254, 24235, 24266, 24251, 24302, 24323, 24345, 24347, 24346, 24348, 24349, + 24356, 24390, 24381, 24383, 24379, 24399, 24401, 24417, 24469, 24445, 24531, + 24522, 24524, 24616, 24576, 24568, 24592, 24579, 24716, 24674, 24707, 24675, + 24708, 24686, 24684, 24773, 8804, 11162, 24248, 149, 30475, 1038, 40049, + 12871, 17935, 28718, 29263, 5386, 11022, 10382, 4226, 2901, 11319, 7507, + 16256, 26151, 34487, 35447, 29378, 23273, 30345, 2417, 39230, 30162, 14262, + 1392, 36041, 19851, 2052, 22228, 6115, 24536, 15358, 32539, 30403, 37168, + 37019, 8189, 17535, 33746, 21013, 2427, 31047, 4285, 32615, 1440, 19650, + 154, 36412, 16126, 16127, 13234, 20245, 41296, 41297, 41038, 25511, 31734, + 35195, 155, 24778, 12884, 8007, 18930, 14047, 22305, 10665, 10666, 10756, + 34621, 29746, 40739, 24384, 20092, 11492, 26617, 8348, 40085, 13131, 30694, + 1924, 30537, 12551, 6499, 35077, 28130, 24957, 39084, 11881, 26849, 16335, + 40906, 24862, 24865, 24873, 24890, 24878, 24907, 24991, 24922, 24972, 24929, + 24921, 24944, 24933, 24998, 25015, 25014, 25029, 9626, 25038, 25040, 25109, + 25071, 25058, 25053, 25124, 25126, 25148, 25156, 25172, 25181, 25208, 25219, + 25220, 25218, 25228, 25234, 25243, 25251, 25254, 25256, 25264, 25263, 25261, + 25283, 25318, 25302, 25298, 25296, 25311, 25308, 25352, 25353, 25371, 25384, + 25383, 25414, 25391, 25433, 25421, 25413, 25392, 25389, 25462, 25509, 25505, + 25537, 25546, 25586, 25570, 25576, 25541, 25598, 25596, 25594, 25607, 25619, + 25642, 25638, 25686, 25706, 25704, 25724, 25725, 25738, 25740, 25763, 25766, + 25786, 25829, 25833, 25827, 25843, 25849, 25853, 34900, 37496, 19715, 37801, + 27364, 40419, 9356, 25198, 33904, 11147, 30695, 36918, 27867, 36273, 26858, + 4266, 26939, 37805, 39097, 25562, 17181, 25031, 37573, 17182, 14562, 31531, + 3905, 33552, 29798, 18232, 12016, 5777, 23855, 41039, 22988, 4850, 37501, + 3912, 37309, 22065, 23071, 20908, 31684, 7614, 37852, 25745, 2331, 20012, + 28268, 20486, 27868, 18233, 31685, 9161, 16480, 8356, 4888, 28804, 19163, + 33751, 35037, 9643, 40958, 9705, 41309, 29379, 2431, 22295, 5211, 26621, + 16515, 18199, 5912, 29383, 19614, 29565, 4013, 160, 17420, 4505, 22871, + 24540, 13907, 4268, 13706, 30610, 29899, 2369, 37349, 35867, 40809, 1262, + 18663, 2132, 38760, 16677, 25866, 25898, 25910, 25919, 25934, 25942, 25944, + 25967, 25970, 26008, 25994, 25998, 26069, 26076, 26098, 26089, 26080, 26087, + 26082, 26085, 26137, 26147, 26110, 26181, 26190, 26218, 26211, 26206, 26200, + 26204, 26238, 26212, 26260, 26263, 26324, 26337, 26330, 26309, 26293, 26301, + 26321, 26373, 26367, 26369, 26396, 26395, 26404, 26406, 26414, 26420, 26416, + 26424, 26417, 26443, 26442, 26452, 26454, 26471, 26467, 26468, 26485, 26488, + 26505, 26499, 26516, 26531, 26538, 26525, 26536, 26526, 26523, 26521, 26600, + 26573, 26580, 26576, 26578, 26607, 26595, 26585, 26653, 3150, 26659, 26669, + 26652, 26696, 26710, 26703, 26734, 26729, 26755, 26745, 26728, 26767, 23950, + 19449, 34396, 18079, 12552, 1543, 9711, 10030, 5569, 18763, 26550, 26378, + 5570, 34001, 1946, 5698, 4853, 26629, 33875, 10945, 299, 20094, 18517, + 39905, 22937, 13273, 20151, 4506, 21457, 11777, 14787, 36162, 13142, 36088, + 9791, 3179, 11102, 26112, 15614, 23863, 19255, 38130, 38317, 16921, 30725, + 12363, 23778, 26811, 19870, 21960, 2798, 5780, 25687, 16746, 37063, 24057, + 3920, 11177, 12913, 19341, 37857, 732, 36788, 18797, 25237, 6984, 29109, + 7477, 14927, 7200, 25568, 7623, 16011, 27564, 34223, 33518, 8222, 5317, + 31218, 6173, 27666, 32652, 31848, 18384, 30898, 26484, 12914, 28271, 18093, + 37369, 31990, 27767, 21733, 33767, 37931, 37350, 26774, 26799, 26801, 26795, + 26793, 26824, 26823, 26839, 26837, 26848, 26830, 26821, 26829, 26898, 26902, + 27144, 26909, 26651, 26924, 26923, 26913, 27143, 26962, 26964, 26969, 26976, + 26973, 26970, 27006, 27002, 26993, 26997, 27039, 27016, 27035, 27100, 27058, + 27018, 27036, 27084, 27115, 27045, 26999, 27017, 27081, 27027, 26994, 27000, + 27034, 27030, 27024, 27025, 27157, 27163, 27169, 27165, 27176, 27184, 27182, + 27177, 27193, 27180, 27265, 27221, 27237, 27229, 27215, 27256, 27219, 27249, + 27238, 27246, 27211, 27286, 27284, 27290, 27320, 27309, 27322, 27313, 27314, + 27312, 27315, 27308, 27337, 27345, 27351, 27340, 27338, 27353, 27383, 27361, + 27378, 27386, 31698, 10295, 105, 11806, 11807, 12609, 4407, 32450, 30413, + 20340, 16836, 13247, 2308, 26639, 23955, 17453, 15374, 37591, 4960, 29201, + 28778, 38605, 28272, 32108, 7266, 6081, 33038, 9193, 27319, 13162, 10200, + 25804, 34005, 35090, 565, 6581, 22797, 30732, 21652, 3832, 19330, 22723, + 12624, 38189, 3192, 39117, 7124, 21290, 36436, 4572, 32658, 23344, 7188, + 13042, 33695, 15955, 1452, 5923, 20170, 16354, 14002, 24503, 24182, 17706, + 32219, 28064, 18869, 35960, 33705, 32934, 35961, 16179, 16760, 13541, 5581, + 39597, 862, 35099, 20670, 11439, 1567, 27929, 28695, 29901, 24512, 24068, + 30843, 18270, 11822, 21974, 8598, 37937, 837, 17285, 27327, 3935, 27356, + 27424, 27427, 27435, 27433, 27440, 27441, 27458, 27456, 27474, 27472, 27496, + 27517, 27521, 27540, 27537, 27555, 27568, 27557, 27561, 27571, 27584, 27579, + 27576, 27636, 27659, 27654, 27626, 27619, 27614, 27612, 27702, 27749, 27708, + 27748, 27706, 4438, 27003, 27722, 27704, 27778, 27820, 27817, 27844, 27842, + 27839, 27838, 27841, 27864, 27884, 27923, 27939, 27940, 27944, 27961, 27978, + 27980, 27995, 28015, 28001, 28007, 27984, 28092, 27969, 28100, 28110, 28111, + 28120, 28153, 28154, 28152, 28173, 28199, 28175, 28228, 28193, 28204, 28184, + 28261, 28275, 28276, 28308, 28300, 28294, 28311, 28336, 28333, 28340, 28327, + 28407, 28397, 28398, 28399, 28420, 63, 17981, 33779, 24340, 16313, 30171, + 31394, 25692, 25693, 23362, 18620, 27954, 29928, 19909, 37944, 22894, 37208, + 34017, 12639, 14198, 33780, 24673, 27955, 14199, 7810, 2047, 25205, 35992, + 32293, 37106, 14532, 17559, 17518, 36239, 23959, 36370, 18406, 29713, 30762, + 37766, 18122, 35000, 19742, 10136, 15915, 16376, 12649, 5329, 19468, 16817, + 16708, 11653, 7745, 39444, 30855, 15963, 11267, 16982, 12657, 16773, 11281, + 19133, 12240, 15967, 18848, 12968, 25821, 29043, 16719, 25012, 32688, 36026, + 19001, 19827, 1642, 27629, 32597, 3995, 10851, 33477, 4844, 7991, 33492, + 18658, 11026, 10277, 13360, 14636, 820, 34409, 38721, 38722, 15908, 1707, + 31875, 27417, 28428, 28442, 28504, 28490, 28546, 28557, 28556, 28551, 28596, + 28601, 28589, 28593, 28592, 28612, 28631, 28617, 28636, 28632, 28645, 28684, + 28662, 28674, 28666, 28651, 28713, 28720, 28716, 28753, 28746, 28741, 28743, + 28764, 28799, 28801, 28790, 28795, 28822, 28788, 28827, 28856, 28864, 28858, + 28880, 28877, 28897, 28895, 28908, 28896, 28946, 28936, 28935, 28943, 28938, + 28972, 28977, 28984, 29025, 29009, 29006, 29010, 29045, 29044, 29053, 29049, + 29074, 29114, 29120, 29071, 29149, 29182, 29204, 29174, 29169, 29164, 29222, + 29226, 29233, 29269, 29247, 29262, 29252, 29316, 29309, 29354, 29365, 29370, + 29417, 29422, 29430, 29436, 29428, 29457, 29462, 29467, 5849, 24582, 6060, + 31912, 14852, 38933, 26501, 36928, 9973, 40831, 32528, 7370, 6913, 416, + 3531, 23653, 30919, 37709, 37710, 15029, 23255, 29598, 23256, 37546, 14861, + 11672, 24246, 23257, 39953, 20799, 30450, 7604, 7605, 10167, 8170, 25144, + 804, 21231, 28988, 22865, 3471, 14618, 17151, 8179, 38421, 9025, 22513, + 22514, 32169, 5860, 1652, 1777, 38584, 29437, 9155, 36405, 8699, 4453, + 11677, 19509, 8190, 17799, 35324, 32177, 17165, 35807, 22872, 23166, 26509, + 35454, 30482, 20622, 24162, 9602, 24474, 16636, 33218, 13815, 24638, 12775, + 29953, 3055, 551, 10090, 33803, 26717, 8120, 32368, 16490, 1263, 37502, + 36844, 13692, 5191, 5812, 11678, 29459, 29486, 29494, 29489, 29490, 29533, + 29543, 29561, 29592, 29616, 29641, 29574, 29603, 29576, 29605, 29659, 29657, + 29660, 29655, 29668, 29674, 29683, 29682, 29714, 29723, 29727, 29730, 29764, + 29769, 29773, 29847, 29776, 29832, 29835, 29840, 29849, 29858, 29896, 29908, + 29939, 29954, 29957, 29947, 29963, 29979, 30008, 30039, 30027, 30050, 30089, + 30067, 30065, 30176, 30143, 30135, 28439, 30160, 30181, 30246, 30191, 30182, + 30210, 30214, 30229, 30247, 30260, 30285, 30273, 30280, 30309, 30313, 30298, + 30314, 30304, 30359, 30332, 30340, 30353, 30338, 30327, 30336, 30388, 30404, + 30434, 30445, 30442, 30513, 30458, 30461, 30502, 30505, 30499, 30498, 30516, + 27798, 14427, 23318, 37332, 15085, 27652, 19076, 17194, 5995, 28953, 16061, + 10003, 10102, 706, 7456, 30548, 6607, 37510, 28392, 23821, 25708, 21246, + 30810, 17615, 6152, 6969, 616, 5699, 30490, 2256, 34836, 6106, 16198, + 13693, 29511, 19673, 33519, 20200, 13593, 26944, 33764, 34535, 25519, 30553, + 8223, 37584, 19797, 30883, 25569, 32881, 31932, 36336, 26872, 3728, 28775, + 40159, 40925, 29110, 37585, 19871, 16203, 6361, 24545, 17202, 31054, 37809, + 24871, 36425, 13243, 650, 27670, 4463, 31598, 31006, 17454, 592, 25434, + 12377, 31169, 33448, 10119, 35504, 1096, 11178, 35594, 6462, 20971, 10428, + 10976, 9541, 19282, 35931, 30936, 36432, 28994, 39909, 30564, 30540, 30515, + 30572, 30578, 30586, 30574, 30589, 30591, 30773, 30608, 30594, 30662, 30522, + 30663, 30657, 30658, 30659, 30660, 30774, 30809, 30777, 30782, 30783, 30789, + 30840, 30775, 30796, 30788, 30786, 30812, 30772, 30896, 30888, 30920, 30909, + 30916, 30911, 30948, 30964, 30953, 30972, 30996, 30993, 31030, 31038, 31052, + 31040, 31050, 31059, 31105, 31082, 31095, 31079, 31145, 31144, 31151, 31134, + 31141, 31150, 31147, 31181, 31188, 31200, 31186, 31185, 31182, 31254, 31242, + 31262, 31243, 31279, 31402, 31257, 31314, 31308, 31363, 31342, 31324, 31305, + 31401, 31337, 31335, 31427, 31547, 31428, 31904, 31486, 31782, 31494, 31559, + 31413, 31535, 31458, 2334, 25992, 23565, 29427, 26384, 5715, 18813, 30836, + 39817, 3189, 24802, 22546, 37087, 13170, 18529, 24309, 36234, 13252, 30940, + 32659, 30416, 38993, 39044, 19261, 9764, 18261, 4533, 16945, 19432, 32660, + 2968, 20671, 41153, 27678, 24554, 28996, 39510, 22380, 13483, 24814, 1633, + 17694, 9617, 31758, 12461, 40395, 7457, 16578, 14959, 14960, 36177, 2717, + 13390, 21093, 32671, 31232, 3731, 34088, 27679, 4046, 3280, 5263, 17058, + 26346, 35602, 14109, 4964, 23552, 4364, 32513, 26559, 24283, 36535, 2641, + 17261, 38325, 33781, 40217, 38287, 32813, 19538, 33076, 23373, 25457, 13069, + 10241, 40685, 13756, 22802, 10325, 7287, 16709, 13753, 16226, 20461, 17305, + 31504, 31905, 31421, 31473, 31574, 31405, 31474, 31545, 31481, 31526, 31417, + 31501, 31700, 31678, 31672, 31668, 31682, 31731, 31730, 31723, 31775, 31820, + 31772, 31783, 31931, 31917, 31938, 32003, 31985, 31976, 31946, 31940, 31950, + 32019, 26152, 32025, 32021, 32076, 32091, 32055, 32427, 32099, 32058, 32152, + 32151, 32170, 32168, 32148, 32155, 32150, 32182, 32246, 32248, 32320, 32359, + 32314, 32367, 32351, 32357, 32326, 32343, 32323, 32321, 32434, 32437, 32464, + 32435, 32451, 32454, 32442, 32431, 32483, 32478, 32472, 32501, 32494, 32492, + 32530, 32527, 32551, 32542, 32523, 32536, 32606, 32611, 32648, 33901, 32585, + 32663, 32616, 32593, 32587, 32705, 32724, 24563, 21598, 18638, 6470, 32683, + 40183, 18430, 17323, 18431, 7747, 35129, 1075, 21040, 9209, 36385, 27420, + 31660, 2276, 24850, 24990, 2277, 19415, 13767, 40231, 40588, 11459, 21714, + 22237, 39961, 19354, 7143, 15113, 20360, 31902, 15235, 37639, 24900, 18049, + 33864, 27365, 29670, 32540, 32184, 10957, 30821, 5398, 3694, 30826, 5403, + 40556, 8423, 36966, 35389, 7851, 7567, 13636, 39893, 5143, 35718, 39951, + 13801, 39556, 32844, 25140, 39389, 15025, 2635, 11599, 25141, 30088, 18183, + 805, 35072, 41290, 1208, 26473, 14619, 10465, 33921, 39145, 35437, 22005, + 1842, 5521, 8171, 9698, 39653, 39685, 25145, 35747, 30045, 20887, 8994, + 33857, 38945, 24698, 32721, 32742, 32751, 32745, 32754, 32753, 32750, 32804, + 32795, 32805, 32808, 32882, 32819, 32834, 32861, 32821, 32848, 32825, 32851, + 32927, 32968, 32949, 33075, 33034, 32944, 32945, 32987, 32958, 33145, 33110, + 33133, 33115, 33111, 33134, 33109, 33105, 33169, 33176, 33205, 33217, 33210, + 33209, 33288, 33244, 33253, 33248, 33246, 33245, 33284, 33291, 33289, 33292, + 33290, 33317, 33316, 33331, 33320, 33323, 33342, 33344, 33369, 33372, 33380, + 33422, 33441, 33439, 33430, 33436, 33435, 33501, 33458, 33505, 33478, 33500, + 33471, 33548, 33554, 33663, 33636, 33605, 33588, 33592, 3988, 33607, 33648, + 33641, 33631, 33632, 33725, 33736, 33729, 33799, 33800, 33789, 9699, 21365, + 1904, 1849, 3542, 3537, 15690, 25333, 13297, 13119, 1917, 13661, 7082, + 25555, 40144, 9520, 36072, 15121, 33314, 33493, 16047, 21455, 27374, 12770, + 16088, 17041, 14715, 26618, 8701, 39149, 18224, 12563, 35845, 2079, 40463, + 27538, 25127, 17393, 7820, 2664, 16056, 28951, 37653, 18065, 3546, 2874, + 3810, 17611, 22257, 7431, 37503, 34517, 6357, 39757, 35581, 12564, 39478, + 15502, 23563, 29189, 29100, 8210, 3725, 33016, 5996, 16062, 6480, 33445, + 33446, 37654, 8211, 37054, 29894, 34530, 11630, 22229, 5111, 37882, 28412, + 9006, 11255, 25429, 37655, 20970, 14233, 28355, 593, 25925, 21463, 36342, + 13821, 11258, 15700, 17441, 16922, 26878, 33827, 33841, 33855, 33854, 33906, + 33908, 33916, 33913, 33944, 33948, 33993, 33999, 34055, 34027, 34032, 34026, + 34029, 34028, 34110, 34099, 34143, 34097, 34107, 34100, 34148, 34153, 34157, + 34162, 34285, 34146, 34186, 34180, 34193, 34196, 34201, 34197, 34218, 34213, + 34230, 34233, 34301, 34593, 34306, 34290, 34300, 34368, 34346, 34364, 34385, + 34353, 34345, 34350, 34406, 34376, 34357, 34356, 34467, 34483, 34486, 34478, + 34522, 34602, 34614, 34657, 34587, 34597, 34623, 34598, 34596, 34618, 34599, + 34611, 34604, 34728, 34720, 34732, 34731, 34751, 34746, 34754, 34757, 34747, + 34764, 34749, 34823, 34814, 34825, 34819, 34850, 34864, 34910, 34903, 34885, + 34964, 18907, 35932, 5935, 33049, 32112, 30837, 1599, 2379, 12195, 26072, + 734, 1394, 8070, 13043, 40437, 13044, 4792, 12388, 5123, 37992, 7270, + 1983, 32557, 33154, 1660, 25239, 19429, 16355, 345, 38283, 9671, 2398, + 28233, 21739, 2670, 17513, 5259, 27329, 28736, 1367, 16364, 23095, 39599, + 6518, 27331, 30241, 27136, 534, 32912, 2015, 3233, 16318, 18423, 31714, + 32134, 16385, 39025, 5077, 14700, 38115, 26894, 13084, 36020, 16462, 34232, + 31418, 7780, 8282, 7811, 484, 10443, 12242, 12250, 13097, 9348, 1480, + 34603, 9521, 14872, 22685, 19643, 20128, 20129, 20331, 27062, 27746, 2662, + 19109, 14893, 20144, 29421, 17427, 35084, 39758, 15037, 31691, 34953, 34917, + 34956, 34933, 34943, 34923, 35018, 35026, 35067, 35068, 35106, 35119, 35121, + 35130, 35288, 35157, 35153, 35150, 35167, 35118, 35164, 35165, 35166, 35194, + 35173, 35188, 35291, 35319, 35296, 35321, 35318, 35301, 35294, 35295, 35478, + 35369, 35460, 35444, 35365, 35435, 35482, 35377, 36039, 35398, 35520, 35576, + 35563, 35565, 35542, 35541, 35552, 35543, 35617, 35652, 35677, 35663, 35630, + 35613, 35650, 35946, 35778, 35840, 35711, 35625, 35844, 35825, 35882, 35616, + 35612, 35740, 35828, 35689, 35623, 35748, 35662, 35633, 35945, 35769, 35687, + 36059, 36060, 36047, 36064, 36061, 36049, 36055, 36114, 36145, 36142, 36138, + 36198, 36193, 36194, 36209, 26285, 30555, 31849, 29321, 37075, 16415, 6997, + 6421, 24223, 22161, 12625, 20495, 36437, 9070, 24744, 38726, 14006, 9366, + 5470, 13186, 19122, 24897, 12947, 30641, 14977, 24750, 19125, 16426, 26693, + 5597, 9378, 34591, 29310, 24588, 13853, 4617, 39686, 3038, 12293, 5192, + 5628, 11216, 24961, 8710, 27088, 9605, 13773, 11933, 24642, 33224, 21249, + 12175, 18778, 38397, 1327, 33235, 26385, 8927, 39844, 33940, 4037, 31629, + 35530, 17343, 14983, 31656, 34694, 31663, 34715, 6093, 8163, 24589, 24590, + 13509, 12508, 7206, 34111, 5898, 10716, 2636, 28974, 33475, 13653, 35438, + 25328, 34144, 36135, 26303, 23480, 30046, 12524, 34112, 36136, 6832, 7574, + 34258, 36251, 36305, 36338, 36310, 36358, 36303, 36333, 36400, 36402, 36403, + 36399, 36532, 36396, 36439, 36398, 36482, 36477, 36510, 36506, 36539, 36543, + 36542, 36576, 36544, 36546, 36554, 36650, 36646, 36617, 36618, 36627, 36614, + 36629, 36620, 36662, 36685, 36676, 36687, 36679, 36719, 36720, 36731, 36755, + 36727, 36735, 36764, 36818, 36812, 36916, 36868, 36871, 36901, 36889, 36866, + 36870, 36923, 36931, 36945, 36963, 37034, 37043, 37028, 37053, 36950, 36969, + 37021, 36967, 37010, 37013, 36993, 36998, 37129, 36984, 37137, 37128, 37132, + 37143, 37131, 37144, 37134, 37212, 37250, 37220, 37230, 33456, 37294, 37271, + 37239, 37276, 37301, 37258, 37234, 37229, 37313, 34895, 27846, 26672, 36143, + 33127, 14874, 32707, 21159, 3168, 36759, 39569, 33332, 7403, 33177, 2976, + 26530, 32081, 25767, 40561, 33566, 35772, 35773, 28093, 3417, 10319, 26619, + 10390, 33651, 39151, 40317, 39335, 9044, 40846, 38588, 9162, 8191, 13008, + 5978, 18053, 5629, 34855, 21080, 22108, 40087, 8465, 35810, 14626, 35078, + 38500, 35456, 35457, 24869, 38875, 22873, 1238, 33355, 24715, 446, 4949, + 41103, 28902, 40249, 4388, 38959, 36639, 33571, 34064, 35846, 11563, 10402, + 27089, 2552, 32764, 26860, 10527, 2594, 9053, 9606, 24962, 11765, 13694, + 11217, 8318, 32485, 30546, 26622, 40090, 29614, 20017, 20515, 6962, 11623, + 34393, 33335, 9310, 7145, 37241, 37273, 37291, 37246, 37351, 37213, 37484, + 37489, 37480, 37527, 37538, 37548, 37542, 37553, 37581, 37533, 37532, 37544, + 37571, 37569, 37556, 37615, 37633, 37652, 37634, 37635, 37665, 37668, 37727, + 37717, 35069, 37699, 37726, 37684, 37707, 37713, 37840, 37818, 37833, 37820, + 37872, 37865, 37899, 37927, 37909, 37798, 37920, 37897, 37952, 37976, 37974, + 38014, 38012, 38010, 38025, 38042, 38035, 38036, 38063, 38078, 38086, 38093, + 38124, 38146, 38148, 38158, 38163, 38170, 38192, 38174, 38173, 38184, 38179, + 38222, 38215, 38205, 38197, 38195, 38217, 38231, 38228, 38225, 38230, 38318, + 38331, 38339, 38341, 2472, 38361, 38368, 38379, 38382, 38411, 34229, 1810, + 29410, 35472, 16741, 40154, 15826, 15715, 31214, 12585, 39760, 25345, 4647, + 16518, 6845, 15843, 7046, 29548, 5195, 931, 2696, 36907, 15525, 24103, + 24220, 27432, 161, 37182, 32767, 3345, 13818, 32375, 31165, 31368, 8619, + 27853, 2061, 11778, 14156, 27573, 39209, 27574, 6359, 11250, 2962, 27519, + 13716, 15466, 24733, 4566, 32716, 28210, 30491, 32195, 7478, 3433, 28489, + 35891, 21345, 36173, 5916, 22580, 40646, 2799, 3138, 40555, 12597, 23188, + 28676, 40530, 30726, 14502, 24409, 6174, 39338, 38265, 41008, 23691, 40647, + 17636, 13152, 4023, 10226, 19091, 26679, 1596, 11273, 22675, 37066, 6005, + 33524, 22689, 27119, 33769, 27120, 11937, 11232, 38423, 38418, 38459, 38491, + 38504, 38004, 38483, 38492, 38485, 38524, 38517, 38540, 38548, 38556, 38563, + 38614, 38578, 38594, 38583, 38576, 38641, 38638, 21399, 38642, 38640, 38737, + 38694, 38691, 38693, 38697, 38706, 38702, 38763, 38747, 38754, 38757, 38744, + 38786, 38785, 38801, 38796, 38800, 38805, 38797, 38804, 38817, 38811, 38829, + 38830, 38850, 38852, 38867, 38879, 38881, 38859, 38886, 38858, 38914, 38921, + 38934, 38958, 38986, 39017, 39021, 39051, 39026, 39029, 39062, 39090, 39071, + 39094, 39073, 39116, 39054, 39056, 39057, 39133, 39141, 39130, 39215, 39190, + 39214, 39176, 39273, 39244, 39259, 39236, 39246, 39232, 39237, 39321, 39311, + 39323, 39329, 6998, 39968, 5710, 32889, 8059, 23114, 29512, 13163, 23439, + 37371, 40776, 40394, 31754, 11809, 36097, 168, 32207, 20999, 3190, 7783, + 40163, 34796, 34658, 11520, 33770, 8733, 21895, 23193, 20724, 35235, 30827, + 33315, 29021, 40027, 26336, 22941, 16017, 11570, 12038, 8667, 36438, 20026, + 32736, 20172, 31757, 23921, 3142, 33977, 29124, 28069, 714, 3501, 23700, + 27125, 13284, 37595, 33051, 10491, 28921, 34984, 34985, 39872, 37092, 1568, + 4592, 16946, 20544, 20667, 26386, 39000, 20522, 13058, 38284, 13597, 17463, + 18531, 2312, 21935, 9731, 31703, 40672, 317, 318, 13921, 39001, 35523, + 10889, 13319, 19399, 3013, 10131, 11184, 2816, 33536, 38354, 26057, 39328, + 39331, 39327, 39325, 39362, 39371, 39359, 39363, 39426, 39374, 39377, 39399, + 39361, 39358, 39376, 39470, 39456, 39472, 39473, 39451, 39459, 39453, 39534, + 39552, 39526, 39570, 39527, 39532, 39542, 39610, 39644, 39664, 39608, 39651, + 39731, 39620, 39627, 39616, 39700, 39650, 39728, 39623, 39622, 39670, 39702, + 39621, 39678, 39873, 39892, 39883, 39894, 39897, 39888, 39924, 39923, 39952, + 39943, 39944, 39977, 39981, 39976, 39984, 39978, 40003, 40040, 40044, 40123, + 40062, 40078, 40063, 40071, 40110, 40138, 40137, 40150, 40127, 40140, 40139, + 40130, 40197, 40184, 40194, 40247, 40238, 40258, 40254, 40234, 39050, 40287, + 40272, 40312, 40282, 40323, 40315, 31630, 38402, 6589, 39350, 21095, 16365, + 6860, 36371, 14967, 12225, 41225, 13488, 2046, 11843, 40442, 31236, 38333, + 38449, 27153, 24118, 28699, 38334, 23120, 26772, 33783, 38220, 28704, 5275, + 28246, 32295, 12230, 13548, 38732, 21038, 35353, 130, 38622, 11711, 11242, + 35993, 35994, 26347, 25230, 21785, 23833, 40543, 28530, 11120, 40034, 10242, + 131, 36378, 13197, 37427, 13078, 11854, 6392, 39006, 33896, 38110, 16774, + 26694, 30865, 2829, 17352, 35533, 1518, 39012, 34695, 7033, 3847, 30869, + 3848, 35115, 2750, 25231, 36246, 16392, 3236, 32924, 21606, 11302, 38117, + 36030, 5285, 38637, 34709, 6408, 30026, 25301, 33321, 33347, 1168, 39985, + 26667, 33480, 40271, 40280, 40291, 40284, 40362, 38848, 40371, 40374, 40380, + 40400, 40429, 40427, 40431, 40457, 40452, 40462, 40451, 40484, 40470, 40472, + 4202, 40498, 40492, 40527, 40509, 40546, 40552, 40557, 40571, 40568, 40567, + 40572, 41246, 40599, 40608, 40610, 39049, 40594, 40602, 40708, 40709, 40720, + 40711, 40736, 40722, 40704, 40843, 40811, 40829, 40845, 40884, 40853, 40866, + 40852, 40938, 40903, 40927, 40888, 40892, 40948, 40971, 40995, 41023, 41027, + 41028, 41037, 41043, 41044, 41052, 41098, 41092, 41093, 41094, 41116, 41130, + 41164, 41189, 41176, 41180, 41204, 41208, 41239, 41264, 41265, 38490, 41291, + 41274, 41275, 41287, 0, 0, 0, 0, 0, 23654, 10656, 31922, + 12306, 10676, 9945, 10592, 31610, 31611, 17695, 10037, 6393, 18434, 23412, + 17042, 5455, 1093, 27396, 32398, 7736, 39853, 39867, 34710, 34712, 3979, + 11607, 29991, 35774, 35775, 12872, 421, 10809, 6948, 3906, 12897, 15490, + 8319, 14637, 7877, 31554, 1700, 40164, 12738, 7629, 31612, 1984, 30899, + 11349, 5587, 40935, 7635, 35982, 218, 22515, 20894, 22451, 9029, 20899, + 36900, 20623, 27751, 11330, 16057, 10404, 10104, 16913, 21250, 1146, 37195, + 12739, 29853, 19551, 31613, 7004, 14679, 3893, 28700, 11303, 15003, 878, + 39065, 37541, 8164, 2183, 8970, 28985, 35439, 10172, 30400, 22789, 12004, + 7336, 28627, 9411, 38244, 39471, 3968, 12081, 31304, 8335, 21419, 25777, + 22417, 8787, 3288, 8688, 21063, 6995, 9691, 36974, 22766, 1109, 30024, + 34880, 34915, 39360, 5509, 33162, 36256, 15929, 37320, 8551, 28968, 40233, + 12268, 20968, 20318, 12088, 23216, 20076, 875, 26000, 9173, 38297, 26520, + 4873, 34482, 14881, 27648, 35226, 34660, 7359, 22947, 9571, 15992, 1433, + 38266, 9299, 36814, 5337, 35615, 30947, 14083, 15632, 9622, 15139, 16173, + 12111, 26298, 30274, 15743, 22699, 14905, 24005, 11949, 35903, 14184, 30463, + 25262, 6049, 38779, 16641, 25759, 8625, 20783, 25299, 37130, 22563, 34181, + 30215, 31244, 2863, 2320, 15291, 40269, 21672, 15117, 36680, 35642, 8986, + 7142, 40319, 27079, 1239, 40751, 7144, 9639, 22688, 1437, 19338, 5049, + 26804, 15868, 7513, 29434, 35459, 3477, 19651, 10468, 1240, 18746, 17962, + 11766, 8320, 22669, 40752, 12816, 33666, 38320, 13448, 8357, 38126, 13135, + 36337, 34126, 39210, 26492, 1701, 1702, 24643, 26493, 4126, 38131, 40017, + 16297, 38092, 4464, 3139, 26397, 29323, 22263, 8815, 32196, 19360, 13153, + 28212, 8226, 28757, 4567, 4568, 39779, 12177, 38815, 6422, 13994, 33338, + 4292, 37890, 778, 38022, 16300, 7804, 2350, 12208, 26815, 35949, 40438, + 8244, 9071, 25845, 38285, 17696, 35964, 559, 3211, 30419, 39833, 40539, + 1571, 37815, 38363, 5232, 38103, 34678, 23138, 26348, 29575, 30066, 21309, + 12687, 12269, 7134, 36874, 15721, 15200, 40129, 35665, 29348, 2616, 13412, + 21720, 20704, 3785, 34471, 17102, 24584, 17024, 37139, 22821, 36619, 23240, + 7791, 23843, 25739, 22011, 40570, 27226, 19156, 31039, 1127, 29167, 9349, + 15542, 14608, 7659, 34481, 32845, 12525, 30520, 40949, 18498, 28859, 1690, + 21854, 3606, 31536, 14098, 13138, 13356, 14341, 29618, 33755, 5114, 29573, + 30011, 26500, 23633, 41095, 37755, 4678, 5548, 31406, 34118, 10694, 9800, + 2806, 15962, 718, 23062, 10574, 7972, 7910, 27966, 27711, 29681, 34466, + 1895, 9694, 19642, 32976, 18973, 23021, 1780, 36427, 19172, 16698, 1743, + 11043, 17763, 32243, 30422, 36453, 14009, 8478, 32234, 38136, 1379, 6394, + 27300, 34691, 26401, 33898, 18488, 8482, 38138, 37530, 1241, 40006, 7796, + 37812, 31489, 29615, 31828, 3259, 3275, 31995, 28835, 41022, 17115, 26304, + 24462, 36206, 32262, 4351, 14875, 24298, 3472, 4352, 3221, 5979, 5528, + 31819, 38589, 14894, 12337, 3487, 3914, 9266, 33972, 29386, 6734, 8433, + 28313, 4648, 31692, 38889, 28026, 36224, 14504, 13154, 25082, 4328, 4738, + 18780, 5318, 24548, 40777, 29119, 24741, 3652, 11535, 24069, 24033, 13543, + 38221, 29217, 7128, 38084, 15686, 15353, 14876, 3200, 7410, 37716, 475, + 23276, 30164, 35812, 21395, 18055, 19786, 15650, 4355, 23580, 40320, 14417, + 27785, 20107, 39926, 20473, 34344, 13614, 10714, 26291, 21910, 14586, 21153, + 9133, 10309, 5607, 38860, 24682, 35379, 15811, 16731, 9301, 12274, 11590, + 26586, 9035, 24925, 39239, 11917, 33559, 24089, 8606, 15838, 7045, 40997, + 40607, 30675, 36988, 26666, 2769, 28185, 3169, 13121, 33965, 35189, 6925, + 37266, 33735, 150, 5672, 40726, 22686, 20524, 5271, 27996, 27078, 20134, + 38963, 13019, 38332, 24050, 14915, 34644, 38600, 3230, 13607, 13891, 8143, + 31309, 23624, 14082, 601, 5788, 41276, 838, 33249, 8305, 39637, 21503, + 40999, 4195, 22507, 30525, 11483, 15926, 31699, 9956, 24443, 15851, 19473, + 31143, 7361, 1759, 22423, 879, 35172, 5774, 22061, 14631, 21238, 35474, + 12154, 6783, 6784, 40155, 24963, 40372, 32487, 3611, 22670, 39736, 12776, + 2204, 28469, 14499, 27261, 29808, 4018, 14157, 21547, 32636, 2136, 4813, + 20776, 27262, 13452, 24009, 20717, 13155, 23331, 31055, 30727, 13717, 12365, + 21554, 14431, 14432, 19078, 18782, 16845, 30372, 24970, 41065, 24177, 35588, + 4655, 40926, 22411, 39276, 37077, 6662, 4116, 36656, 5711, 38473, 3208, + 9271, 28831, 8061, 41068, 21896, 2576, 29942, 23922, 21408, 5744, 29125, + 12391, 18205, 38101, 1341, 3705, 18824, 17697, 28781, 5074, 28074, 31759, + 15985, 12220, 39511, 23927, 5588, 22082, 40936, 17464, 38165, 21412, 29929, + 14527, 32122, 39916, 5608, 28553, 12755, 39626, 40131, 15754, 24141, 11310, + 37903, 17118, 36465, 8607, 31447, 7955, 22506, 28652, 34489, 14767, 34316, + 36156, 38750, 22938, 26315, 41010, 18116, 7740, 3897, 11383, 19343, 24762, + 26464, 10333, 8762, 19942, 33626, 32875, 27911, 33046, 14976, 36192, 23798, + 5288, 2951, 27610, 1459, 973, 24623, 979, 6902, 7167, 27287, 12182, + 36567, 10487, 30573, 31136, 8627, 39175, 15852, 22564, 35368, 17087, 23223, + 602, 8376, 18456, 5789, 18588, 3072, 3458, 30069, 21213, 20755, 354, + 34156, 5941, 6187, 15141, 26214, 26393, 21102, 8306, 36124, 3308, 26925, + 9740, 33994, 17778, 37636, 39462, 192, 35754, 22510, 21424, 1869, 4667, + 14970, 17983, 28419, 24034, 14814, 17642, 6624, 15881, 4969, 1374, 1375, + 14687, 24120, 6632, 3844, 12235, 31303, 37772, 21414, 39520, 17345, 39861, + 3943, 6516, 30866, 18435, 17990, 32135, 30871, 16393, 25213, 25775, 21607, + 28539, 24854, 13833, 4685, 4867, 31768, 15971, 15005, 17992, 5100, 7685, + 29153, 6735, 8909, 16493, 25351, 19167, 59, 12178, 14505, 15575, 16623, + 34540, 19806, 15278, 24746, 18535, 16629, 6752, 39514, 34718, 29158, 5415, + 36538, 37453, 3047, 34241, 9583, 15026, 37711, 33174, 5034, 33733, 7327, + 25330, 26223, 15840, 27243, 29993, 3170, 5044, 6926, 20896, 23278, 19567, + 25648, 25334, 23750, 40403, 10576, 10857, 22348, 29841, 25975, 5037, 15645, + 5965, 36077, 16827, 10808, 8706, 37564, 19441, 36555, 17583, 3491, 33146, + 22557, 36013, 2400, 13327, 20936, 6424, 23631, 12097, 30303, 24439, 23399, + 32432, 7918, 34349, 37826, 7488, 12485, 17090, 6890, 14592, 22488, 39543, + 25696, 32318, 2893, 4478, 24234, 31319, 23839, 23227, 26207, 1466, 40275, + 15579, 35554, 20587, 8383, 22767, 18359, 437, 20793, 14384, 25175, 24398, + 3461, 7937, 18008, 21447, 36254, 19559, 36397, 24448, 20378, 26444, 23842, + 29065, 25233, 1195, 4377, 14551, 29590, 11668, 40135, 29491, 24043, 7954, + 25286, 33294, 24931, 11729, 34041, 20472, 12507, 13339, 3675, 13225, 19190, + 33258, 24782, 15869, 5630, 18057, 5050, 278, 39153, 7339, 15829, 34833, + 22330, 916, 9098, 9099, 22191, 40322, 25480, 6949, 450, 40042, 39576, + 34944, 15360, 35813, 39714, 27092, 22876, 7087, 8954, 14493, 13524, 9463, + 10406, 15154, 24964, 40010, 38046, 39737, 26491, 17634, 37335, 26430, 36782, + 30408, 36220, 38970, 30367, 8126, 24362, 40019, 21251, 16834, 38978, 38717, + 17637, 40769, 11639, 30492, 4329, 9830, 15220, 35589, 22369, 23869, 9715, + 21405, 22884, 9392, 937, 19079, 22018, 17590, 25664, 25521, 12680, 34797, + 32208, 4104, 4607, 4238, 8734, 36793, 10598, 27268, 8236, 40778, 8062, + 30900, 998, 38672, 37088, 30901, 28922, 9198, 39119, 32001, 34042, 8792, + 13938, 19337, 28263, 10640, 40074, 15204, 1104, 26928, 31041, 36831, 6829, + 19700, 36752, 17135, 29772, 32075, 7968, 28125, 36753, 5555, 26602, 9382, + 16525, 36308, 4255, 14041, 23272, 31488, 27791, 13895, 20958, 23159, 444, + 27242, 2869, 29431, 36995, 11320, 1221, 7990, 29781, 5185, 4764, 34304, + 14408, 5297, 12870, 30344, 36404, 9094, 10075, 23574, 7720, 25339, 32445, + 30538, 2780, 15149, 23501, 16000, 31735, 6944, 768, 21987, 29500, 18503, + 22037, 33745, 12721, 39098, 26859, 25616, 20632, 7052, 923, 31018, 10196, + 12335, 16890, 703, 12896, 27588, 16529, 36418, 37310, 28024, 19863, 6237, + 31745, 17507, 4645, 17965, 37596, 18825, 13391, 3011, 40410, 30844, 11906, + 33990, 39004, 13544, 38728, 2067, 16611, 7636, 7221, 17918, 8745, 26055, + 15230, 11359, 35604, 12408, 40544, 7100, 37428, 13198, 10608, 16713, 22294, + 17346, 17357, 18640, 17993, 5013, 39990, 17580, 30895, 4389, 41181, 1496, + 16199, 4400, 33909, 643, 1504, 33910, 596, 4415, 1515, 1517, 21726, + 21729, 2818, 4308, 36036, 25356, 1397, 26903, 25625, 2651, 8370, 36924, + 35372, 23141, 37955, 30501, 29839, 40549, 29163, 10158, 4924, 6822, 39974, + 3074, 21312, 39624, 3155, 40283, 28931, 30075, 24899, 11669, 6196, 36890, + 20942, 35417, 13645, 17775, 34106, 6642, 14210, 36686, 24605, 5659, 14134, + 35568, 24789, 15615, 33723, 17721, 11791, 34130, 14928, 25681, 41188, 12364, + 19869, 7214, 23329, 10692, 33039, 10597, 30557, 35930, 31033, 27926, 1326, + 10199, 28582, 25578, 34010, 32282, 8595, 16953, 12057, 24824, 10560, 7283, + 21587, 20059, 8934, 35701, 15847, 17398, 4898, 35696, 31450, 38143, 22189, + 36718, 17734, 8298, 8399, 27207, 19808, 29860, 3117, 8097, 22096, 336, + 13639, 13416, 37957, 35732, 18884, 15058, 29338, 35134, 31, 20889, 12443, + 9318, 527, 14405, 23020, 17788, 23748, 9409, 5970, 38381, 34262, 24330, + 37011, 195, 33742, 1779, 15932, 37646, 27252, 7058, 4059, 12888, 27587, + 38651, 21886, 25920, 19210, 36327, 39488, 10096, 39031, 31341, 17405, 28388, + 11673, 9243, 16257, 988, 4882, 14879, 1055, 36761, 39998, 13956, 37267, + 4299, 29176, 4945, 37619, 21881, 5301, 28155, 34508, 3478, 29082, 26934, + 39085, 36768, 37916, 6950, 9846, 4950, 30603, 21032, 34955, 3875, 34124, + 28470, 5690, 3488, 37622, 28013, 19321, 9422, 38761, 27102, 2165, 3623, + 28027, 6657, 5700, 18518, 3496, 4833, 25252, 23692, 33836, 37355, 35495, + 31374, 17675, 27121, 19361, 9877, 38607, 29016, 7125, 1414, 1418, 16957, + 37604, 35003, 19134, 17062, 29485, 23394, 26202, 36946, 25540, 30426, 7835, + 15293, 1680, 33107, 26657, 37531, 4808, 11973, 662, 14593, 1169, 30216, + 15812, 9502, 26831, 15638, 38966, 32876, 18583, 41222, 4680, 8437, 11433, + 22583, 33285, 40660, 11955, 41138, 21051, 35614, 28981, 5018, 27072, 2069, + 3563, 12086, 15594, 5338, 16645, 38369, 34149, 34883, 7836, 8089, 35644, + 4995, 17086, 6888, 1116, 955, 9735, 24320, 36197, 37956, 15110, 8287, + 9077, 18190, 6125, 21626, 6669, 21065, 36682, 27620, 15814, 12105, 26661, + 11591, 4897, 17865, 35397, 32581, 1185, 4346, 9453, 11723, 33373, 35303, + 22030, 15756, 6715, 12494, 20320, 19991, 38489, 21721, 8782, 20701, 19293, + 3405, 16549, 8825, 31190, 38376, 28330, 38200, 31449, 41285, 12112, 7781, + 38236, 21878, 20278, 17876, 40417, 38834, 28939, 10844, 4760, 26145, 8304, + 10343, 12275, 10799, 33252, 31669, 9531, 21850, 16540, 34358, 3297, 6270, + 18857, 8103, 31189, 16466, 12757, 8824, 1893, 31796, 890, 32701, 23152, + 24350, 39991, 40998, 22847, 16248, 21224, 36754, 2138, 32436, 14479, 36573, + 23994, 35317, 19705, 25741, 908, 27244, 37161, 37908, 10746, 15925, 32439, + 32440, 27860, 28796, 20481, 31513, 25599, 4006, 40741, 41004, 35196, 31158, + 32446, 37844, 10273, 36553, 19652, 2994, 7875, 17719, 40384, 11092, 24001, + 19440, 24002, 33576, 5486, 1358, 34068, 1286, 38338, 30611, 39340, 19668, + 17892, 5112, 19872, 35225, 2396, 15771, 7730, 19873, 15873, 17512, 38097, + 2712, 36700, 12210, 34668, 2724, 4860, 11293, 36540, 5178, 2051, 6096, + 16463, 17139, 27426, 4065, 5964, 4902, 20990, 16872, 15930, 13572, 36602, + 15994, 14264, 27861, 36076, 3597, 13573, 18580, 15691, 21906, 11742, 24255, + 293, 27999, 6329, 15362, 21532, 10320, 3129, 28396, 8704, 7, 20835, + 10213, 5724, 22, 81, 28306, 9867, 29563, 3418, 22288, 16822, 2364, + 22746, 23172, 36326, 1023, 27920, 5564, 20146, 22335, 14809, 17664, 23046, + 4066, 13531, 21907, 24265, 18582, 2469, 5458, 10198, 13988, 14938, 35335, + 25830, 22471, 25574, 2156, 12050, 21033, 30571, 12977, 20974, 19052, 10894, + 17999, 36880, 37148, 24351, 37156, 11337, 30575, 39619, 22275, 28855, 3786, + 38239, 9780, 31648, 38107, 17324, 36991, 34490, 41175, 19568, 39199, 6284, + 39082, 37663, 8279, 29237, 23581, 7159, 3811, 38047, 4325, 36904, 36278, + 23074, 41185, 9890, 30618, 18787, 16411, 34326, 28956, 38665, 28677, 40531, + 32209, 6331, 28734, 24653, 4274, 37933, 22995, 15387, 27891, 3865, 4838, + 37935, 36671, 273, 38514, 13312, 22737, 3212, 37408, 16947, 38166, 35350, + 13317, 28702, 7161, 21742, 35995, 34686, 35996, 21440, 25590, 3845, 34697, + 18138, 20068, 20069, 21442, 33200, 13557, 26187, 20074, 34706, 1468, 27067, + 27137, 16958, 14014, 24593, 35564, 17718, 5344, 38833, 6062, 22977, 24609, + 417, 39076, 39461, 418, 19020, 8108, 20944, 5904, 26307, 24081, 30590, + 31094, 19443, 38814, 8043, 7212, 12259, 23397, 23634, 23224, 24680, 34183, + 32317, 352, 2452, 16325, 397, 11057, 15404, 6127, 12800, 33431, 5016, + 9015, 19605, 20373, 35671, 6189, 13507, 34034, 39242, 16551, 16244, 27786, + 34297, 9222, 32703, 9743, 15544, 14864, 25401, 35031, 30257, 38027, 30598, + 37006, 4845, 18545, 40731, 19709, 26805, 27794, 12452, 38813, 17894, 5489, + 1708, 35510, 5746, 3562, 7391, 4623, 34104, 34762, 10802, 16245, 31726, + 2899, 11489, 34950, 39288, 13470, 24851, 26201, 25024, 24570, 206, 9475, + 19288, 21693, 37869, 31943, 22183, 7493, 25388, 15757, 27179, 28262, 1201, + 14758, 17129, 36986, 32256, 36132, 15605, 4122, 40839, 7303, 11163, 11164, + 10076, 8510, 23279, 19502, 25379, 5673, 27743, 31807, 35779, 2611, 26843, + 29837, 31491, 21818, 23662, 24672, 13122, 22605, 35137, 13860, 464, 7371, + 3176, 33271, 6263, 37729, 23667, 7868, 22452, 20900, 33132, 6839, 14896, + 6652, 8998, 36211, 23757, 615, 25787, 25273, 2981, 21707, 7577, 37878, + 12451, 24252, 22453, 9744, 10669, 36150, 15033, 26853, 35815, 39901, 31736, + 8349, 25380, 11975, 28603, 15300, 37664, 18853, 6952, 30990, 6698, 40761, + 21280, 29800, 27093, 20404, 9105, 15367, 18066, 1782, 27752, 9170, 1934, + 22460, 37314, 27753, 41252, 2060, 36776, 29272, 12817, 39099, 26986, 27094, + 39485, 14633, 28095, 35315, 9821, 19103, 21229, 26486, 4635, 20004, 10928, + 2546, 30692, 30880, 19712, 21078, 38758, 14155, 14924, 17673, 33036, 34008, + 11296, 4107, 11978, 28265, 36160, 39525, 26899, 28786, 29986, 31776, 25319, + 37225, 3573, 35391, 32495, 1845, 36992, 11892, 2512, 27869, 20528, 33391, + 13908, 25876, 40432, 21042, 22561, 31248, 9569, 22182, 33375, 32474, 30140, + 147, 37157, 1211, 8810, 296, 13903, 2701, 33032, 17943, 36352, 33201, + 5339, 4823, 2835, 31250, 39611, 21965, 3670, 31249, 15166, 2945, 4176, + 27777, 1462, 21691, 11058, 3975, 22314, 4927, 34848, 41280, 21215, 7926, + 2973, 35675, 35384, 29667, 34288, 2407, 15142, 34036, 2665, 26861, 26862, + 33871, 38836, 810, 10407, 1267, 26759, 3915, 26940, 1935, 40327, 3612, + 37961, 22922, 29617, 23765, 8024, 38552, 18310, 23676, 8025, 17184, 37733, + 22461, 34735, 639, 1856, 13696, 9002, 27382, 39277, 20774, 31737, 31738, + 5691, 12730, 20815, 28722, 11332, 35577, 27645, 15871, 15119, 871, 29624, + 33274, 10684, 13454, 3550, 7148, 19213, 1783, 27103, 20718, 12732, 36163, + 15038, 40015, 3755, 32507, 29625, 20641, 16799, 12167, 37336, 33679, 25276, + 41229, 39761, 26311, 3624, 32273, 33275, 24967, 22464, 29439, 40160, 32548, + 20489, 15725, 34966, 32097, 32187, 33397, 15039, 2517, 16603, 12348, 22579, + 25565, 20095, 35332, 36093, 9465, 15431, 37904, 896, 27819, 23650, 15900, + 16080, 35731, 29168, 24906, 24154, 33300, 7465, 2933, 30471, 3792, 10846, + 4762, 37914, 15996, 6939, 16843, 40514, 24083, 1230, 28005, 23852, 36558, + 14101, 24056, 3692, 4026, 17945, 19957, 29292, 11642, 27455, 34588, 30579, + 10623, 20425, 15251, 28447, 18858, 16082, 14260, 16472, 37268, 2870, 31808, + 30922, 11875, 6928, 24888, 25059, 10408, 29273, 25032, 10031, 23937, 22056, + 23888, 27550, 23448, 27709, 2582, 7694, 37535, 20788, 20224, 6637, 20110, + 9132, 1465, 30975, 10184, 30576, 16652, 8379, 27343, 18358, 18589, 34725, + 27720, 30072, 18006, 19607, 19184, 33848, 22097, 30071, 10626, 20427, 14024, + 200, 6122, 36848, 26012, 15331, 23771, 27776, 24, 5913, 10111, 25711, + 27110, 15528, 24649, 32646, 38979, 33447, 38150, 29112, 4892, 9272, 10729, + 39908, 29679, 18902, 19729, 16497, 30373, 33139, 37858, 938, 28038, 37358, + 2698, 6107, 1959, 10112, 12783, 10690, 4681, 7731, 2667, 30374, 39784, + 27667, 33765, 11179, 37185, 29391, 8957, 40650, 19038, 33278, 24307, 26722, + 10007, 19039, 35141, 3926, 38359, 14434, 32385, 29440, 19512, 23130, 16923, + 22112, 25712, 3353, 8620, 17044, 28993, 1826, 40338, 39231, 29757, 18316, + 41194, 14669, 2941, 37624, 13164, 8521, 5920, 28960, 2915, 19080, 9832, + 18094, 861, 18799, 16936, 23919, 23025, 14743, 20413, 11314, 30668, 17770, + 12701, 39061, 36058, 11667, 40133, 12501, 33610, 11726, 28933, 34038, 13293, + 18211, 11018, 34039, 25609, 27975, 31196, 16246, 30587, 40605, 14707, 2454, + 659, 31457, 19753, 11394, 40242, 23269, 31480, 27790, 6347, 40575, 22600, + 20238, 8461, 7450, 4558, 26670, 9410, 18720, 27464, 32983, 34308, 20243, + 13435, 27865, 11491, 33645, 22304, 12879, 33866, 31097, 19710, 34628, 24258, + 15453, 26540, 19531, 36416, 23111, 17178, 25614, 28410, 11927, 1252, 33442, + 8118, 28802, 22126, 20483, 11501, 36419, 32631, 16409, 2367, 10868, 19211, + 11424, 17542, 40158, 35330, 18755, 33805, 8432, 27393, 27660, 26244, 26482, + 29630, 2703, 16299, 41195, 22373, 232, 22472, 32394, 34173, 40500, 16803, + 15385, 15557, 28500, 16066, 6366, 21192, 4209, 40780, 39286, 966, 21563, + 40987, 4275, 28682, 6109, 23338, 23782, 40534, 12196, 37373, 13915, 9395, + 19588, 2878, 29326, 31599, 17551, 28961, 9236, 4893, 27402, 39118, 18800, + 19956, 18801, 11148, 1600, 8294, 16278, 15495, 7414, 31404, 20972, 30414, + 11136, 5443, 32109, 22657, 11952, 17638, 7204, 19820, 15161, 36345, 5541, + 17553, 9760, 32283, 6465, 29822, 30626, 40933, 8245, 25523, 12393, 7005, + 15043, 3210, 29126, 38444, 11114, 34800, 6511, 32002, 37089, 15533, 33237, + 11528, 30745, 8246, 38843, 2523, 24183, 26883, 10603, 15956, 29327, 24030, + 28141, 17048, 5209, 2706, 17446, 25577, 23084, 1336, 10234, 40664, 10134, + 33067, 36445, 37765, 7681, 10302, 494, 20187, 9564, 5291, 20113, 36882, + 3159, 21636, 23677, 23681, 31365, 17667, 23695, 11339, 13047, 13046, 4306, + 34237, 31320, 14206, 38232, 35390, 7108, 12697, 14120, 5021, 10804, 22140, + 2057, 17031, 24606, 32598, 29171, 25115, 15924, 30523, 11404, 18725, 4094, + 11493, 24632, 31973, 300, 9055, 28471, 18234, 32102, 17899, 14668, 33041, + 20305, 28234, 16169, 12468, 11738, 29892, 39697, 15304, 39549, 12114, 6813, + 2299, 31740, 14652, 2851, 14118, 21799, 20080, 7988, 1228, 37441, 3069, + 27575, 7416, 34347, 31247, 37222, 1117, 24031, 10780, 29680, 4534, 11351, + 35251, 20415, 13171, 6482, 13165, 27809, 15957, 10985, 33772, 6747, 13733, + 39120, 1415, 39912, 40785, 33407, 35144, 19767, 22042, 27, 13830, 23882, + 19737, 28369, 4965, 715, 32005, 17469, 28373, 15181, 34994, 35258, 21783, + 31007, 25450, 28842, 28374, 23929, 17264, 27603, 4210, 1995, 22083, 4919, + 1099, 25928, 8522, 40787, 31174, 36442, 11583, 29397, 18273, 15162, 28289, + 26129, 27896, 30420, 10299, 39224, 39225, 16500, 35966, 37602, 28867, 21573, + 31704, 12742, 8669, 19284, 14723, 27857, 41114, 28375, 32043, 7809, 30991, + 20854, 18685, 28376, 21936, 41083, 29879, 33412, 9433, 33894, 17555, 27203, + 19434, 20672, 19123, 13930, 40818, 9499, 21681, 36951, 27712, 4926, 40038, + 26209, 24138, 34242, 25232, 27224, 18967, 13334, 22772, 2586, 17028, 22823, + 30184, 32157, 28296, 5654, 30670, 6812, 14135, 1593, 13655, 2866, 1210, + 2679, 21804, 339, 37643, 29495, 31347, 9047, 20526, 22607, 83, 22791, + 3419, 16903, 34317, 23945, 22719, 2908, 16673, 38753, 31562, 26322, 1315, + 21465, 19251, 27476, 8296, 8291, 7915, 21790, 40730, 13609, 14819, 722, + 38140, 27723, 8158, 40996, 35690, 21792, 5022, 32584, 11159, 22660, 16858, + 23281, 15445, 40494, 2226, 39716, 31355, 365, 18236, 26312, 1545, 4507, + 2801, 12642, 32458, 27611, 36922, 40058, 8629, 30302, 15853, 1359, 30847, + 18280, 5593, 25883, 40969, 35525, 18832, 15537, 23933, 4732, 23207, 2921, + 28782, 19464, 36584, 2819, 7737, 14175, 1572, 27413, 18578, 33452, 4538, + 18407, 38104, 13188, 2385, 16969, 32046, 31632, 15280, 27516, 1073, 38821, + 23883, 3283, 18842, 11188, 12409, 23097, 11846, 23976, 22930, 17921, 26056, + 33453, 25886, 3284, 16029, 27684, 18346, 21097, 11537, 22768, 28248, 7285, + 24071, 24917, 34807, 28783, 32563, 14978, 13394, 41214, 17703, 24194, 16584, + 6592, 33155, 38060, 12231, 13071, 39917, 5499, 34179, 36526, 6543, 14979, + 21784, 38061, 23122, 29443, 7286, 38822, 6085, 26349, 15137, 12956, 7544, + 28253, 18688, 14726, 11850, 37429, 17486, 37825, 22422, 27216, 8457, 32947, + 7933, 40066, 7934, 3978, 5020, 15683, 10162, 13294, 8832, 32596, 29068, + 18041, 23419, 7422, 26409, 9697, 6723, 27188, 18307, 25005, 30342, 40724, + 15450, 32444, 29080, 20298, 11749, 27638, 1488, 8997, 40517, 20396, 13966, + 39157, 25615, 8582, 16888, 35838, 12895, 1696, 22701, 19448, 16676, 20716, + 25949, 32880, 17674, 38342, 13245, 23826, 24025, 11341, 41128, 34879, 12171, + 4075, 38011, 36545, 6054, 12094, 30667, 1683, 30914, 14846, 15346, 18364, + 5795, 5029, 22969, 20381, 12702, 7113, 8946, 33476, 34191, 10163, 34930, + 19195, 31725, 11603, 17499, 23286, 36319, 23285, 11025, 16050, 34504, 4559, + 30352, 40678, 24036, 13201, 40687, 16710, 1380, 29444, 11361, 35270, 6710, + 9835, 5334, 14695, 7638, 4971, 36005, 132, 40945, 34141, 5927, 40359, + 10563, 40545, 12241, 21599, 10451, 12070, 24368, 1720, 36383, 16032, 21662, + 33543, 13203, 13204, 23885, 2579, 39865, 20363, 16999, 16716, 12243, 41139, + 15889, 26402, 22398, 16231, 6400, 27608, 4342, 18964, 1585, 834, 18690, + 32430, 15807, 18440, 7037, 18641, 13206, 16458, 2027, 12971, 35116, 2751, + 32467, 13208, 31665, 9444, 2347, 21609, 16779, 4686, 24856, 22116, 19146, + 41122, 19005, 38172, 21612, 15007, 28876, 27335, 16398, 12276, 34758, 33259, + 802, 33266, 19503, 34260, 39688, 32082, 31206, 23299, 2875, 3124, 14410, + 19660, 37039, 37649, 31978, 21121, 94, 28812, 13912, 11510, 36339, 4736, + 4513, 33808, 38765, 23081, 2311, 24812, 18803, 1351, 38105, 30988, 30709, + 37919, 28912, 31317, 1525, 23403, 2494, 19289, 17095, 22492, 20292, 35015, + 25697, 12979, 3947, 3295, 4482, 32579, 7364, 21992, 40279, 20952, 39632, + 39027, 18363, 14318, 22850, 18594, 31947, 32582, 36885, 39553, 30157, 39379, + 18012, 9019, 5618, 17107, 6764, 3243, 15315, 16598, 34159, 25235, 39646, + 39069, 9458, 23151, 29535, 9255, 14325, 11206, 10542, 9632, 13651, 18971, + 14757, 144, 33562, 7329, 9224, 7975, 14868, 40836, 28299, 18035, 3952, + 7610, 6350, 23851, 38873, 39738, 36324, 11508, 40762, 1960, 28865, 25430, + 1066, 18259, 11353, 16221, 2744, 38784, 2894, 14302, 338, 5980, 24734, + 17730, 20053, 19811, 19291, 27457, 26270, 11994, 19812, 34375, 1223, 10077, + 1224, 26365, 15130, 15301, 1017, 10670, 25727, 25900, 32178, 32179, 12886, + 20442, 31924, 27552, 6288, 38430, 21146, 38596, 22332, 32017, 18068, 1495, + 1268, 25728, 95, 9360, 8715, 8716, 7185, 4019, 10724, 9535, 20447, + 25993, 16096, 16534, 18861, 29508, 26171, 14500, 37746, 37747, 2800, 24891, + 17973, 2879, 26194, 16097, 34328, 30937, 34410, 7000, 11885, 37374, 30938, + 32560, 735, 10731, 24896, 35054, 30941, 620, 233, 30627, 36104, 16144, + 25093, 19107, 4201, 17578, 9824, 13126, 5675, 14409, 41029, 26711, 20993, + 38384, 17538, 16407, 12329, 22814, 14560, 24538, 6500, 4204, 3222, 18859, + 2550, 14559, 33870, 19716, 36415, 39101, 7473, 28472, 28282, 33003, 8550, + 4719, 8585, 27590, 1698, 25416, 40157, 33002, 13910, 23948, 23184, 3891, + 28816, 40162, 10952, 8435, 37750, 24391, 30116, 14941, 24059, 24273, 18670, + 41209, 31584, 14509, 37589, 16688, 34411, 17949, 2044, 2567, 36772, 306, + 20584, 4624, 26368, 29293, 37875, 17527, 22730, 5104, 12318, 1729, 35916, + 25317, 6897, 9085, 15350, 18596, 39557, 35720, 39138, 10841, 17117, 34926, + 27057, 39656, 24936, 18711, 38954, 21397, 30483, 16357, 6334, 25027, 7735, + 29286, 21574, 28514, 15163, 10437, 25095, 4174, 9368, 6307, 23442, 15911, + 28846, 9370, 22725, 15244, 31890, 11847, 2823, 22638, 5330, 11362, 28525, + 30945, 28417, 10052, 15143, 6326, 11751, 4953, 11345, 16643, 33160, 8339, + 39605, 36048, 34748, 6251, 6887, 26731, 22243, 15505, 37866, 39533, 22486, + 3240, 6891, 24683, 5609, 18180, 30068, 1760, 6759, 27223, 6760, 7068, + 9574, 36926, 15055, 24090, 33260, 4251, 8172, 31951, 26268, 26747, 23042, + 39188, 32332, 5419, 7504, 35750, 6564, 19059, 36066, 14396, 3165, 18712, + 26750, 32261, 36074, 40241, 34776, 25366, 31966, 3722, 34612, 36075, 27367, + 5526, 30524, 21522, 6565, 4322, 40740, 4602, 18786, 17905, 30785, 12845, + 23889, 12763, 12450, 12314, 15192, 5479, 8352, 13023, 38129, 21914, 18016, + 2124, 1063, 38360, 22625, 23038, 8286, 16172, 8454, 10254, 28649, 8576, + 38303, 33113, 37828, 14205, 10347, 38064, 19609, 37233, 2931, 21315, 23252, + 3311, 35183, 2990, 34600, 11601, 2058, 9983, 9598, 33747, 15940, 93, + 20487, 29972, 34012, 35095, 31641, 21049, 961, 27044, 15862, 35416, 39655, + 40719, 8312, 13949, 39198, 16291, 24617, 12142, 5147, 8212, 2655, 12523, + 31679, 5559, 37044, 9062, 13987, 24889, 13103, 13310, 22816, 19557, 9139, + 31267, 9225, 12138, 14629, 12881, 22652, 15329, 24149, 25762, 512, 194, + 13571, 8350, 34509, 11615, 37879, 31353, 28806, 12568, 5359, 292, 31829, + 36215, 25823, 25245, 17893, 29913, 5487, 13468, 28157, 369, 32275, 7617, + 21286, 7092, 12197, 5366, 36229, 6849, 18462, 31633, 17220, 17242, 10909, + 39401, 35780, 24253, 23668, 11325, 9056, 14775, 10872, 37986, 37067, 3823, + 28144, 10132, 31121, 27475, 9431, 3937, 37993, 36582, 12222, 31622, 18345, + 16959, 21002, 33942, 38002, 12420, 12421, 20860, 7831, 26004, 20807, 7579, + 22125, 37845, 3613, 34736, 183, 31362, 5813, 5306, 11094, 5914, 20820, + 3188, 38511, 18086, 23194, 40024, 10693, 38608, 36100, 40343, 30007, 18200, + 6215, 36347, 31385, 18106, 18107, 10696, 36105, 8712, 515, 19635, 20744, + 4766, 13127, 25856, 27253, 2940, 18855, 23116, 24836, 22754, 5342, 32061, + 4079, 6131, 34247, 36065, 15443, 37803, 28116, 3591, 13443, 6352, 5985, + 36853, 37539, 9795, 37688, 31081, 25386, 11453, 14089, 25640, 28594, 8884, + 40550, 20874, 34920, 23803, 18365, 6195, 15118, 18595, 12804, 26699, 40073, + 41284, 9253, 39064, 24765, 39387, 14126, 9460, 6200, 34293, 15760, 25785, + 9887, 22661, 39191, 20086, 29992, 19104, 4868, 22172, 30343, 21483, 14046, + 34311, 7451, 37017, 40905, 6100, 13129, 4600, 21015, 20247, 30236, 6960, + 27381, 3339, 36512, 8714, 18900, 1730, 29013, 39775, 4070, 9197, 19885, + 25954, 26251, 19362, 19363, 37891, 18342, 19979, 1717, 31392, 30848, 16149, + 31705, 35983, 5234, 29042, 37430, 18408, 5076, 12410, 22134, 34810, 30648, + 7746, 31898, 12658, 19926, 19927, 16717, 17367, 12076, 65, 7553, 5079, + 18441, 18139, 135, 7751, 17380, 787, 10508, 10504, 10506, 1823, 24344, + 29238, 39100, 3266, 24426, 14163, 14168, 29245, 7429, 20264, 813, 29328, + 11852, 35278, 6063, 2549, 23760, 25340, 5560, 6448, 31354, 25341, 24260, + 21711, 36216, 25768, 20911, 20642, 41105, 640, 35871, 35085, 28954, 934, + 12780, 10685, 22193, 1825, 36096, 8726, 28958, 13719, 164, 10523, 8958, + 23621, 29477, 36519, 28143, 29392, 33884, 15574, 1050, 28506, 26412, 17461, + 17971, 36956, 31479, 35322, 26157, 33135, 26556, 1527, 25784, 14634, 27875, + 1555, 1556, 27212, 9050, 9168, 10982, 7467, 12180, 16346, 36961, 22281, + 19560, 38580, 14037, 21275, 18229, 35583, 34752, 30666, 6638, 23978, 26921, + 10839, 40289, 33853, 28559, 35185, 34768, 31344, 9987, 19831, 2978, 34619, + 10936, 37304, 30544, 6502, 730, 33748, 1405, 29952, 18204, 19454, 26380, + 37923, 35883, 37368, 7262, 28218, 32285, 14982, 4706, 1524, 5384, 33658, + 31587, 17094, 11059, 14188, 11078, 7425, 26995, 27714, 32064, 39548, 24694, + 11065, 7951, 41283, 19999, 39382, 4376, 39074, 29355, 23287, 2684, 31825, + 40641, 31753, 25207, 28980, 28712, 1789, 16145, 16237, 33061, 674, 7062, + 24555, 24556, 10438, 32779, 20829, 12933, 5542, 30903, 28925, 28515, 32910, + 22084, 8746, 1368, 16151, 28784, 18538, 9682, 24073, 33911, 12236, 12964, + 13260, 2854, 4972, 11124, 32306, 23728, 6402, 30242, 12973, 16399, 30583, + 25342, 8038, 19793, 25020, 8727, 30728, 24114, 10015, 2964, 16154, 25534, + 37939, 26560, 30755, 8743, 561, 28926, 9012, 37942, 8623, 1369, 30761, + 28257, 6397, 30243, 6403, 7956, 14306, 32105, 33044, 32113, 12228, 37985, + 16658, 22374, 11536, 36354, 37945, 22392, 176, 36108, 32517, 11125, 35182, + 6071, 24404, 15928, 32541, 27562, 9941, 33495, 35477, 33499, 6874, 27848, + 15980, 23302, 6561, 12760, 11732, 21822, 21194, 34849, 40861, 25051, 23671, + 20443, 28991, 23529, 6575, 19677, 19839, 8537, 37211, 37219, 4929, 33920, + 20296, 12099, 8382, 5292, 11987, 3049, 6640, 34244, 40601, 1399, 7701, + 7176, 76, 17131, 18368, 38460, 29597, 5622, 16174, 30085, 7964, 33265, + 19501, 31960, 23992, 38558, 6202, 21075, 8770, 31099, 23506, 6566, 922, + 6102, 3203, 6356, 13702, 5697, 33874, 1442, 38975, 9714, 25924, 24429, + 24800, 6619, 5494, 13255, 2163, 19897, 2017, 15188, 39578, 8072, 8140, + 33466, 20231, 15581, 6629, 20293, 5089, 26775, 37483, 35432, 28129, 40868, + 3413, 20711, 16292, 13004, 5678, 28303, 34200, 21335, 10177, 37315, 30320, + 582, 6655, 5571, 5113, 22111, 22924, 18185, 3095, 14099, 16800, 10421, + 24015, 6992, 6846, 30729, 32883, 16136, 26680, 35507, 26685, 9874, 6548, + 37186, 22835, 16801, 8130, 12784, 29692, 11813, 15952, 12790, 19097, 29553, + 3276, 36488, 37813, 10979, 10120, 14107, 29919, 29920, 22794, 16301, 29921, + 40794, 40793, 4211, 6112, 16302, 28688, 10129, 23705, 15388, 4793, 33839, + 24226, 35516, 25834, 29135, 6853, 7013, 34417, 30986, 15228, 36609, 40396, + 34418, 32286, 33193, 35603, 37660, 25931, 5747, 5748, 13285, 15909, 16810, + 16585, 22740, 30268, 19405, 4670, 35004, 10303, 24074, 9239, 34139, 34573, + 11855, 2855, 25591, 19931, 1722, 28133, 22611, 25709, 27922, 15945, 19664, + 15378, 20491, 22733, 3274, 15241, 17907, 9203, 29463, 1182, 25001, 29255, + 7323, 39140, 26490, 30357, 29889, 7953, 8505, 9146, 17166, 34516, 22532, + 16410, 16933, 12205, 38350, 10363, 9427, 14727, 13841, 8290, 35546, 22904, + 38825, 17715, 29836, 4121, 26213, 19810, 2610, 21816, 2109, 28595, 14606, + 610, 23741, 7367, 15298, 29701, 11974, 462, 37245, 39253, 9148, 6814, + 22953, 2119, 1905, 37712, 20800, 28717, 5797, 27581, 27059, 33858, 28404, + 1209, 21225, 22447, 6689, 15326, 16600, 7114, 36835, 3323, 12766, 21076, + 35135, 5333, 5905, 36073, 15144, 40145, 6097, 6121, 11165, 24948, 9853, + 32307, 22809, 18643, 16435, 21611, 24995, 29546, 14218, 11767, 36476, 36607, + 16808, 7702, 1536, 9311, 8028, 31927, 38662, 1544, 25792, 452, 28570, + 17813, 9274, 33885, 26436, 14676, 1562, 27680, 30756, 34806, 34997, 27900, + 15164, 27901, 7222, 18281, 31710, 18347, 22712, 22713, 18287, 1579, 1580, + 1581, 17707, 1615, 26062, 7752, 33420, 34753, 38639, 27646, 34967, 18239, + 7418, 7226, 7447, 26918, 2225, 12120, 6095, 27735, 30051, 38585, 29997, + 25343, 37295, 14783, 3605, 36217, 7342, 7343, 28269, 36212, 29707, 35479, + 41299, 1270, 13774, 28913, 18311, 4401, 29450, 27754, 770, 27096, 6787, + 9913, 25346, 29320, 13455, 12781, 1784, 34968, 29626, 26104, 5906, 39263, + 26003, 3751, 28767, 193, 25556, 16558, 16264, 28990, 15522, 38358, 17037, + 8613, 6840, 4887, 19029, 18309, 15129, 13009, 16487, 24301, 14418, 4, + 23907, 21888, 965, 5436, 15455, 16058, 9232, 11948, 22254, 14737, 28663, + 40755, 24174, 15157, 27653, 6972, 2518, 27881, 11334, 25, 18570, 23914, + 7520, 19726, 20652, 8725, 14721, 20852, 18247, 35894, 12736, 1703, 1554, + 28779, 19459, 19114, 36574, 41070, 33882, 5539, 2713, 14952, 23090, 18673, + 6583, 16356, 23119, 4682, 23924, 5495, 12047, 40674, 35967, 2578, 1575, + 39906, 26663, 4849, 39739, 1124, 40827, 20606, 27282, 18890, 12133, 7866, + 16485, 15365, 25293, 4402, 32508, 34837, 14789, 7121, 16669, 31558, 1863, + 21177, 6994, 2139, 15091, 6299, 28039, 37068, 27112, 34981, 11904, 9833, + 27113, 13166, 40535, 1786, 32395, 2144, 35240, 28683, 7439, 38767, 30831, + 9396, 7001, 21837, 37936, 10987, 11530, 11825, 12934, 10782, 116, 28838, + 7588, 30839, 9199, 2524, 27855, 28844, 1996, 8564, 31878, 16019, 18343, + 27897, 28965, 35262, 37862, 20549, 28848, 19402, 1360, 37419, 33413, 13924, + 25890, 16030, 40446, 26351, 3656, 5235, 35998, 12232, 25241, 3286, 30862, + 32519, 38627, 7589, 9925, 19928, 34698, 20561, 2752, 32520, 19148, 38118, + 21046, 6088, 30031, 6761, 10356, 16668, 31448, 6278, 15060, 9823, 9164, + 39162, 12594, 26032, 21381, 8256, 25210, 9503, 13426, 10271, 31529, 22940, + 5956, 11079, 36616, 14253, 37477, 758, 39189, 9090, 6134, 18597, 24769, + 3411, 27631, 7083, 39689, 9260, 33385, 18972, 1926, 16878, 9165, 37297, + 32180, 29085, 31274, 20285, 159, 858, 4297, 10951, 6975, 4397, 19727, + 31369, 35088, 12919, 36349, 39042, 18338, 17687, 13385, 14360, 37397, 11117, + 18828, 9440, 21152, 6055, 13563, 17097, 26297, 17109, 36742, 8389, 15351, + 5144, 38494, 22211, 40297, 33796, 12706, 34217, 35443, 39706, 16557, 31351, + 4847, 32175, 26106, 40203, 7516, 9229, 30705, 37175, 36937, 5107, 16194, + 35862, 10766, 2638, 18568, 12820, 25980, 35205, 1937, 7616, 1950, 21282, + 1290, 1975, 29821, 9950, 7440, 12935, 170, 125, 32123, 37814, 7640, + 22783, 33149, 19276, 37296, 7765, 10092, 5562, 30105, 38964, 3489, 34066, + 40328, 39430, 22290, 33187, 25381, 25789, 37884, 30930, 39493, 5200, 18862, + 36783, 1951, 773, 14917, 30113, 35872, 24728, 23137, 24735, 14195, 22958, + 38840, 37513, 22264, 40102, 14649, 40339, 21794, 14436, 22468, 38141, 12840, + 18087, 39163, 28573, 8228, 34840, 26988, 1312, 30177, 30115, 27762, 18248, + 19311, 22681, 28963, 39804, 25436, 29019, 6213, 34006, 24914, 26641, 14196, + 7123, 9917, 1976, 40167, 36102, 19221, 40125, 5214, 33052, 18264, 14517, + 27832, 24227, 19517, 3629, 20649, 585, 12358, 11517, 1550, 19168, 36485, + 38565, 18390, 36228, 3774, 595, 16306, 35956, 5830, 22588, 5753, 24842, + 35768, 27821, 31432, 24447, 40551, 1432, 35025, 29409, 6290, 15366, 37052, + 34000, 14645, 37184, 36038, 2572, 20880, 25325, 13852, 19779, 22106, 5246, + 12765, 8643, 15501, 17411, 3337, 17504, 13007, 1594, 3953, 29186, 1264, + 14423, 6681, 4910, 930, 771, 18901, 1444, 16343, 3551, 39023, 23974, + 25584, 22115, 22562, 33469, 15031, 4810, 13849, 16729, 40830, 3035, 27742, + 11947, 16618, 28771, 21959, 18522, 13279, 21780, 20688, 5976, 6058, 5098, + 18045, 21633, 9263, 16009, 314, 28659, 9931, 23258, 10169, 16502, 10130, + 29824, 33773, 29962, 15097, 6879, 3389, 33238, 44, 18826, 40502, 40031, + 26561, 22683, 16070, 28966, 16279, 40937, 15473, 23358, 23359, 34671, 7441, + 25958, 34552, 8748, 35057, 31396, 22695, 4539, 22696, 23789, 7442, 11538, + 23786, 11956, 37103, 29140, 24978, 32011, 40939, 15959, 25526, 27683, 9280, + 30126, 9553, 27904, 23717, 3373, 39847, 18283, 22396, 29028, 31711, 2394, + 6389, 34687, 37606, 41017, 25960, 26352, 16984, 39857, 27480, 18844, 31712, + 19126, 38774, 20680, 384, 2242, 1582, 4541, 24753, 1377, 39858, 37440, + 33542, 11190, 1871, 28088, 32684, 17925, 38738, 6627, 18293, 30129, 2485, + 5839, 13401, 29446, 34699, 19139, 38629, 13677, 10393, 36474, 15361, 10091, + 6993, 40392, 21564, 19373, 25926, 10300, 25587, 22803, 10826, 23745, 24577, + 12435, 2634, 11597, 8767, 19846, 7969, 22505, 25699, 32259, 10209, 13805, + 8983, 6261, 36203, 3410, 9936, 9095, 10383, 17152, 36758, 25147, 38497, + 24534, 18048, 3253, 36897, 24473, 12769, 21079, 39712, 27639, 24713, 29501, + 16128, 23288, 13351, 34782, 20715, 26716, 38911, 26429, 31213, 16892, 3913, + 8020, 23906, 24361, 23319, 31552, 37333, 7434, 9828, 9753, 35868, 22534, + 29389, 24966, 30283, 16492, 19953, 4233, 25428, 21021, 8049, 15948, 15382, + 8224, 27886, 37064, 36789, 18523, 24648, 1410, 19584, 24278, 315, 19428, + 19536, 14076, 36021, 35279, 30062, 22784, 40121, 34707, 18448, 18873, 29040, + 32468, 12673, 27493, 14542, 31720, 11304, 17015, 1588, 25375, 36062, 1528, + 33207, 24212, 40895, 27991, 15937, 27478, 30682, 30697, 30698, 37024, 8466, + 35819, 246, 815, 935, 4358, 29155, 24016, 15736, 29943, 8848, 22677, + 37095, 28170, 2009, 32675, 685, 2010, 4362, 20554, 17705, 18541, 32681, + 38137, 29160, 1739, 15792, 18644, 8546, 24104, 15306, 24086, 16586, 25990, + 16055, 5563, 7405, 33398, 25151, 5201, 16063, 1731, 7199, 22469, 7201, + 29197, 818, 1313, 19586, 8053, 7093, 25437, 24738, 8923, 16139, 22377, + 40368, 26439, 28322, 29211, 17245, 1733, 5589, 22386, 27812, 19324, 37592, + 31597, 3435, 28830, 22151, 27123, 11527, 2383, 22709, 28833, 31609, 32559, + 39911, 38769, 27451, 19589, 22381, 11833, 22081, 26342, 12058, 19961, 2722, + 17476, 20359, 16983, 6472, 24855, 7821, 36334, 24432, 32038, 27056, 40187, + 36976, 12286, 6409, 12118, 12992, 38869, 40835, 11074, 24461, 22955, 4944, + 26751, 38242, 9023, 17147, 27739, 29377, 12711, 1400, 3414, 15607, 1236, + 32263, 34383, 24954, 39268, 37850, 27087, 8533, 21996, 26427, 32728, 24425, + 38258, 24171, 40330, 25747, 23769, 30168, 1282, 5110, 15555, 37506, 32634, + 39110, 16008, 11511, 10770, 9007, 7480, 17215, 1322, 3497, 28060, 20348, + 6244, 18804, 6510, 9614, 39292, 40940, 27569, 13063, 30155, 11002, 16215, + 23376, 17484, 39170, 22397, 19315, 25863, 19407, 19408, 26078, 33544, 17853, + 23722, 23721, 21041, 16153, 21665, 1740, 25215, 6279, 6298, 21147, 10734, + 31879, 6311, 10041, 6314, 6313, 14283, 37454, 37458, 34662, 8135, 24284, + 9551, 40942, 18348, 9555, 26389, 19787, 12569, 23305, 8301, 33508, 37395, + 29925, 23199, 17620, 8414, 22714, 1371, 12465, 33540, 3871, 34579, 38630, + 37001, 5346, 25275, 13697, 507, 10686, 30054, 5915, 12455, 33691, 6848, + 6974, 26121, 10179, 30003, 20655, 13824, 26681, 619, 37586, 22538, 18666, + 30933, 10963, 18605, 37965, 7383, 7624, 20916, 36790, 22697, 20699, 10431, + 31997, 5831, 38057, 5467, 2037, 16311, 40113, 36965, 36980, 3681, 31817, + 21511, 21826, 4090, 26219, 35562, 1130, 39896, 612, 7402, 8763, 18599, + 40200, 38243, 31509, 26428, 30708, 19952, 27173, 2382, 3703, 19907, 24211, + 21452, 12715, 24639, 26114, 1366, 5524, 23966, 28307, 13713, 28774, 31594, + 32071, 20083, 414, 17149, 29419, 31505, 40738, 2301, 17891, 40979, 25873, + 10771, 38055, 4399, 33577, 25518, 24665, 13316, 8783, 12571, 35714, 18044, + 31506, 40331, 7474, 13033, 22655, 10426, 35944, 20109, 39476, 23313, 23431, + 34982, 5417, 7863, 24748, 14256, 14416, 17806, 40753, 38082, 21010, 39022, + 13229, 27065, 6061, 8391, 40079, 35569, 9101, 24739, 10012, 22474, 18097, + 30121, 1868, 24656, 22889, 8067, 1330, 4434, 30832, 14439, 5873, 483, + 36797, 9720, 22475, 21379, 33232, 28576, 821, 8240, 38476, 14659, 9115, + 27151, 6221, 5080, 28509, 13734, 27271, 10817, 32514, 7095, 235, 30628, + 38899, 40168, 36289, 17824, 19223, 29642, 29156, 35953, 1816, 30746, 13381, + 15668, 9545, 32115, 8740, 11682, 16638, 8284, 15333, 33455, 6708, 15044, + 29136, 20259, 26441, 38477, 28323, 24228, 37096, 21180, 39002, 9723, 8850, + 28094, 31233, 24659, 26252, 23056, 11441, 29396, 17056, 26130, 26131, 15336, + 19903, 3399, 17395, 41036, 31910, 36658, 21256, 40797, 23364, 39302, 32515, + 21181, 4279, 12643, 5878, 4639, 30102, 32090, 20509, 39582, 34638, 26182, + 3352, 29809, 16798, 16065, 22241, 10978, 29121, 33582, 9893, 28837, 16579, + 2068, 13546, 31631, 14688, 17059, 34022, 26968, 4858, 6630, 24482, 33930, + 4663, 1665, 801, 28403, 12998, 7862, 23898, 39479, 7867, 26227, 17167, + 30098, 12723, 2034, 28562, 15979, 24000, 1265, 32270, 32089, 12155, 13354, + 17585, 12586, 4300, 11256, 3495, 39780, 5781, 1958, 39498, 13156, 6006, + 4071, 39940, 14571, 6705, 4837, 22679, 25520, 21567, 22076, 23197, 3940, + 14969, 23121, 7278, 4666, 40220, 17985, 2743, 17851, 41120, 33095, 39614, + 5862, 20633, 33390, 20668, 22547, 10914, 14873, 26370, 9097, 40748, 24192, + 9238, 40057, 6162, 16280, 7542, 21258, 35985, 16071, 18835, 14364, 2883, + 14067, 19081, 18117, 41015, 16970, 19962, 40943, 39849, 21382, 11138, 37474, + 5723, 26886, 26646, 11915, 29142, 10784, 33241, 40178, 16222, 40944, 38324, + 1420, 1421, 11442, 24981, 38328, 30565, 30566, 37107, 4242, 25528, 6021, + 11543, 17561, 34563, 24557, 24558, 13064, 1102, 7022, 34809, 8264, 25836, + 8445, 31937, 30156, 11005, 27154, 25754, 33899, 30905, 23876, 10304, 31176, + 7386, 25963, 18290, 19285, 26955, 26890, 9373, 40801, 29032, 28435, 35005, + 6868, 36612, 23794, 23378, 30906, 25756, 26727, 17487, 327, 16666, 11654, + 20462, 12659, 29403, 24756, 12965, 26648, 19412, 8908, 28025, 39776, 40750, + 24435, 14149, 37000, 17169, 30924, 29509, 12588, 22292, 7437, 26174, 36182, + 64, 25888, 19335, 3218, 14563, 731, 29387, 40764, 15491, 37187, 4330, + 31123, 20229, 37561, 30127, 40491, 28277, 14761, 14424, 19214, 24818, 3839, + 24486, 18977, 31375, 38094, 20727, 380, 18272, 953, 33148, 36769, 7382, + 479, 22877, 21376, 18603, 27945, 8202, 10811, 28566, 9537, 13707, 30717, + 7090, 12589, 13361, 32509, 34070, 8847, 16924, 17443, 12917, 26948, 29394, + 9716, 26123, 11432, 12599, 24364, 18098, 41012, 7438, 16067, 2880, 9237, + 21253, 21380, 5874, 26880, 40783, 7676, 6011, 7008, 24553, 8248, 11531, + 1417, 25956, 31715, 24661, 1614, 12660, 12652, 40222, 13261, 33418, 40398, + 36595, 38775, 15282, 33947, 1639, 37445, 24757, 32567, 1873, 13500, 34093, + 28089, 11549, 41216, 26359, 26360, 7227, 9687, 17926, 34094, 20291, 31766, + 38367, 32572, 7683, 9379, 10821, 15783, 38329, 25965, 38632, 8450, 9689, + 36528, 17065, 2925, 16823, 27421, 136, 25593, 12671, 33719, 11129, 27422, + 17374, 17863, 17379, 20368, 39123, 32521, 7041, 18646, 9445, 17016, 32142, + 5345, 12445, 29998, 426, 10409, 36777, 38464, 480, 22529, 15322, 29627, + 38321, 10814, 15767, 38468, 15040, 36653, 23340, 26642, 1098, 2919, 29128, + 30902, 30562, 24975, 13253, 22153, 12943, 30850, 31707, 11122, 8447, 320, + 23360, 28431, 9369, 34995, 16664, 1613, 33946, 19404, 20460, 36585, 9680, + 26353, 41215, 17061, 4955, 34738, 4961, 24058, 19395, 12942, 14445, 25524, + 9011, 950, 13816, 29689, 15659, 9182, 5632, 10776, 8729, 15390, 1345, + 18536, 23613, 15791, 1737, 6399, 19795, 454, 34537, 17617, 32653, 30495, + 3445, 32500, 34649, 29454, 28929, 36594, 1530, 16059, 19580, 25155, 29393, + 12615, 40782, 33404, 24977, 14279, 1738, 11366, 17861, 20536, 11640, 20032, + 12454, 15041, 40257, 20035, 23370, 321, 26567, 17928, 5071, 4034, 36859, + 32009, 35352, 24749, 6390, 16977, 24394, 2292, 242, 7631, 36911, 31238, + 34580, 31658, 24657, 9952, 38408, 38628, 9399, 21453, 35578, 8030, 17185, + 14271, 2065, 34631, 8104, 5864, 12158, 7797, 25627, 8406, 26868, 7799, + 20490, 774, 37508, 39434, 11106, 24269, 7884, 587, 30934, 12918, 26875, + 37362, 7833, 34907, 14936, 14937, 22582, 11288, 39220, 777, 34650, 34171, + 39346, 7374, 7800, 30935, 21929, 5065, 8662, 25573, 18099, 20341, 8054, + 30122, 20414, 17227, 1448, 39806, 8663, 37514, 4411, 24806, 32654, 3438, + 5216, 14440, 35051, 9116, 6156, 37376, 34743, 25501, 34175, 29442, 37377, + 29346, 36348, 6539, 31171, 7096, 9278, 106, 39437, 34667, 10557, 32662, + 12792, 17825, 40169, 34801, 29129, 10697, 19224, 25581, 20729, 8668, 25279, + 13382, 33409, 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, 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, 0, 0, 0, 0, 0, 0, 40029, 39438, 19225, + 10566, 21435, 7044, 18979, 12793, 12634, 29826, 11292, 30153, 2085, 31234, + 14724, 37412, 1998, 15099, 34135, 1097, 31624, 15100, 14523, 29759, 14066, + 29137, 6856, 6857, 15846, 10996, 31301, 26645, 16307, 13559, 22117, 18836, + 22550, 27277, 8081, 175, 40680, 22394, 24285, 23713, 863, 5879, 18837, + 25110, 12949, 14530, 29845, 34178, 37520, 23367, 16971, 35267, 40504, 15559, + 6800, 16072, 26766, 23368, 14068, 35986, 35987, 14069, 40798, 16281, 6163, + 23208, 4298, 8819, 14448, 14971, 36043, 41234, 12229, 27414, 36362, 3657, + 20289, 25529, 177, 24560, 29143, 11006, 29144, 7024, 13602, 19593, 8083, + 4244, 29828, 34564, 10448, 37608, 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, 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, 0, 0, 0, 0, 0, 0, + 22659, 16075, 19743, 11007, 36363, 4132, 31398, 14533, 6222, 2338, 7408, + 10501, 36379, 37609, 32131, 31011, 26891, 10502, 3941, 28852, 32013, 25757, + 18291, 12415, 9126, 12963, 28290, 10141, 4416, 4417, 36010, 35108, 34689, + 12237, 17326, 29289, 15623, 29059, 29060, 36011, 29830, 19286, 13399, 8570, + 29290, 3199, 12416, 29883, 39048, 328, 35059, 35358, 21939, 3660, 39863, + 18350, 36596, 18872, 1381, 27484, 40690, 37117, 31240, 14995, 36187, 29148, + 27691, 13402, 36022, 11192, 1384, 36387, 28090, 11550, 7292, 13403, 17709, + 34700, 8572, 14368, 32237, 32238, 29831, 19342, 41217, 37447, 36389, 18849, + 29884, 32239, 33943, 36028, 22640, 3966, 19142, 31662, 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, 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, 0, 0, 0, + 0, 0, 0, 35537, 12249, 38294, 37124, 38633, 35282, 34813, 22641, + 21666, 11130, 20073, 36392, 19938, 5601, 37787, 37448, 16781, 835, 18647, + 10505, 18449, 27494, 37792, 36393, 9446, 24860, 17017, 19012, 26832, 2323, + 32599, 18029, 33922, 10547, 40000, 31207, 16060, 23678, 8811, 37505, 28014, + 10416, 24541, 35900, 31004, 18250, 12368, 35901, 35342, 11354, 38616, 19904, + 27485, 18654, 13868, 18100, 13065, 32232, 4863, 13075, 13088, 34445, 36693, + 4619, 22196, 4620, 22198, 40345, 12936, 20034, 37204, 18276, 3194, 15045, + 17915, 21261, 14365, 15046, 14072, 17290, 32460, 32233, 12744, 20051, 17327, + 38777, 14077, 23387, 18161, 34452, 4621, 19353, 10417, 3027, 7886, 20271, + 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, + 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, + 0, 0, 0, 0, 0, 0, 20255, 7892, 22222, 24895, 24742, + 20730, 7896, 32406, 16282, 20277, 3667, 7754, 24736, 20274, 19682, 20700, + 41016, 21847, 7642, 11495, 13869, 9467, 29242, 29710, 11236, 15876, 10701, + 3449, 10509, 35902, 5156, 31861, 29975, 20648, 23785, 5783, 34553, 19769, + 34565, 37769, 5276, 34340, 34436, 34570, 5164, 39173, 5078, 2293, 35360, + 19747, 38689, 34586, 6407, 18648, 7649, 20249, 37598, 4665, 24898, 3012, + 30206, 40179, 39445, 19935, 330, 1640, 30133, 1389, 2995, 20154, 6078, + 40770, 9172, 6161, 7634, 37524, 2887, 8571, 23556, 37525, 28785, 29004, + 27305, 7534, 30943, 459, 5877, 30125, 39914, 24823, 26765, 26951, 26954, + 29519, 21433, 14075, 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, 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, 0, 0, 0, 0, 0, 0, 11912, 14540, + 34575, 29760, 27694, 32423, 16727, 35053, 31389, 31393, 10739, 33091, 7036, + 33454, 31036, 38409, 21756, 21062, 23322, 38528, 12635, 40799, 12238, 12246, + 3553, 3224, 3226, 10441, 34205, 36183, 33078, 736, 38291, 33083, 2630, + 3446, 34566, 14576, 29401, 18123, 18108, 3895, 24985, 33087, 15498, 21591, + 14367, 35058, 4340, 16100, 37209, 3965, 35608, 21262, 38293, 41020, 24876, + 37896, 34584, 21943, 7039, 31132, 36032, 4365, 41021, 5760, 3967, 14013, + 34282, 10385, 36151, 18392, 22154, 8928, 22155, 34567, 18425, 18468, 8932, + 15196, 4974, 18176, 4975, 9547, 24565, 1643, 4220, 10453, 15000, 32926, + 37452, 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, 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, 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, 2943, 0, 0, 0, 34283, + 40083, 40059, 5335, 13769, 0, 30248, 10042, 10036, 32719, 33204, 40088, + 40064, 0, 8490, 15739, 27837, 27816, 0, 0, 8495, 15765, 28443, + 21682, 0, 0, 0, 18491, 2281, 27009, 3767, 0, 25309, 25349, + 0, 490, 481, 37470, 40377, 24481, 16023, 16013, 0, 33128, 34696, + 14161, 24389, 0, 26344, 35138, 22923, 26345, 40586, 26350, 15008, 30967, + 39341, 4069, 39342, 0, 0, 37116, 36290, 4243, 24559, 37115, 29033, + 26876, 13384, 17826, 14071, 14534, 29061, 22643, 34568}; + +static const uint16_t gb18030_4_weight_py_p1[] = { + 36865, 34286, 36250, 25280, 14183, 0, 5349, 2049, 32720, 31179, 30440, + 30441, 31180, 27773, 34914, 12676, 12467, 33203, 27209, 28151, 0, 25382, + 25370, 37683, 5007, 0, 20420, 27553, 27554, 1590, 38908, 38905, 23963, + 25028, 0, 20832, 27001, 27140, 27700, 27701, 8523, 30497, 30496, 0, + 0, 0, 37469, 25536, 14543, 2399, 2401, 2402, 11031, 36045, 31667, + 31911, 13211, 0, 0, 34455, 954, 3057, 4305, 4307, 4344, 8141, + 13886, 2926, 2927, 38795, 19828, 0, 8142, 37136, 24373, 30655, 35287, + 7756, 7448, 26958, 0, 26959, 26960, 0, 19287, 9142, 9618, 37127, + 21479, 18693, 19371, 11552, 20260, 23390, 23391, 3560, 3561, 18452, 18453, + 9563, 9562, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, + 24521, 29334, 0, 0, 15728, 31241, 36195, 0, 0, 0, 0, + 0, 35364, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 32822, 0, 0, 0, 0, 0, 3784, 0, 0, 0, 0, + 21876, 0, 0, 5101, 0, 0, 0, 33596, 33250, 0, 33318, + 18208, 17932, 32447, 36575, 33159, 39126, 5008, 31306, 22044, 0, 0, + 19271, 23838, 35626, 36112, 21185, 3391, 7688, 0, 0, 0, 40566, + 7389, 331, 31246, 41273, 0, 6183, 27967, 35664, 24446, 15809, 16783, + 21101, 40276, 27217, 0, 0, 0, 33556, 0, 0, 26587, 13796, + 5939, 21851, 27970, 35692, 18472, 36505, 1032, 0, 0, 0, 16329, + 20281, 35724, 17119, 12512, 37146, 19102, 2618, 0, 0, 0, 11890, + 33564, 11737, 25244, 0, 0, 10079, 31809, 28602, 34936, 11741, 15068, + 19296, 19030, 28797, 34945, 38877, 38522, 37170, 40635, 7147, 25190, 23428, + 3615, 31275, 10093, 28860, 26009, 0, 24484, 16672, 25790, 0, 0, + 15981, 23075, 28485, 27288, 34740, 21957, 28571, 0, 20201, 36284, 5917, + 37188, 20342, 15095, 21468, 33053, 36804, 0, 0, 3114, 7739, 16764, + 17312, 0, 19178, 0, 12474, 0, 0, 0, 0, 24920, 0, + 2177, 17602, 9131, 19616, 0, 9288, 28180, 0, 0, 19637, 19377, + 24908, 27082, 16987, 0, 30455, 15596, 6442, 39213, 29456, 0, 0, + 1795, 11983, 6186, 8967, 3241, 0, 24208, 14208, 18707, 33296, 0, + 20988, 32977, 0, 1247, 13698, 27982, 0, 8873, 0, 36867, 33243, + 23582, 22487, 5787, 8094, 19183, 23585, 23586, 28765, 509, 8386, 4370, + 33727, 16507, 0, 0, 26502, 0, 16852, 11204, 29685, 22648, 5522, + 25647, 6916, 24152, 35782, 40576, 25702, 12874, 0, 3607, 3724, 31537, + 0, 19034, 5456, 17887, 14904, 28016, 32765, 38088, 0, 0, 40251, + 38663, 12920, 41030, 4048, 33045, 17228, 0, 3655, 31708, 12976, 0, + 12256, 0, 7486, 3971, 1002, 13628, 0, 438, 17605, 15759, 0, + 31919, 1618, 14906, 16686, 33192, 556, 34841, 18949, 901, 6930, 18657, + 0, 0, 3081, 21864, 33791, 10537, 37154, 0, 9603, 35822, 33832, + 8982, 18560, 29048, 16642, 27004, 0, 28279, 35062, 32052, 41026, 0, + 25041, 36113, 31410, 39530, 12747, 11047, 16155, 35555, 15424, 7843, 24240, + 73, 0, 15446, 3908, 32931, 3917, 30550, 0, 0, 11381, 27973, + 36893, 0, 15088, 38847, 33587, 26966, 0, 27425, 15989, 27473, 10410, + 8359, 34456, 24566, 26572, 11197, 31412, 7308, 22162, 5135, 7390, 8878, + 275, 8088, 21154, 33949, 36722, 11155, 0, 3147, 9770, 20836, 11199, + 17092, 7165, 32576, 23029, 0, 27716, 0, 0, 16654, 17956, 35694, + 10790, 0, 33606, 24763, 7069, 0, 0, 34033, 0, 0, 0, + 0, 21504, 30669, 32956, 29066, 10643, 30012, 21505, 21506, 36128, 39066, + 0, 0, 0, 0, 0, 27181, 21877, 35186, 23259, 29715, 9980, + 15062, 6166, 11869, 18713, 14397, 11996, 18030, 0, 29298, 19060, 0, + 0, 0, 0, 0, 0, 8689, 34307, 26930, 33926, 22296, 4284, + 21686, 6725, 38245, 6932, 32852, 36688, 6933, 26778, 30958, 15647, 10920, + 8691, 31968, 19438, 19028, 12309, 10747, 39691, 0, 0, 30250, 0, + 564, 80, 40497, 23670, 9046, 5193, 852, 1927, 3888, 17172, 32763, + 33440, 0, 0, 0, 0, 0, 10680, 29187, 4641, 16133, 16560, + 39740, 32807, 31539, 0, 24167, 38388, 31540, 0, 0, 4561, 12349, + 12022, 28425, 34399, 33682, 22926, 25838, 0, 0, 0, 9757, 35227, + 32511, 33907, 10422, 41301, 35904, 4403, 0, 16824, 32211, 28587, 25438, + 35935, 39825, 31615, 32218, 14677, 12395, 0, 22223, 17267, 0, 16368, + 25840, 10040, 34431, 24752, 0, 34443, 15197, 3559, 21492, 11979, 0, + 1172, 31941, 31012, 33794, 30282, 36805, 24230, 33590, 21496, 1163, 10248, + 14084, 350, 351, 0, 0, 39055, 28613, 14457, 0, 41277, 2097, + 13637, 72, 38142, 4371, 7166, 0, 0, 0, 0, 21507, 18325, + 19697, 6562, 656, 1197, 759, 0, 3990, 32027, 29300, 2897, 0, + 0, 6674, 30527, 8181, 6726, 37162, 35158, 15931, 30683, 15761, 0, + 30528, 34898, 18458, 33213, 40382, 3480, 32858, 21533, 16512, 35327, 40911, + 19381, 38812, 32033, 9727, 32868, 0, 12590, 17665, 35876, 12350, 36167, + 0, 4912, 35877, 33029, 10289, 36654, 15221, 2841, 28575, 28824, 39505, + 823, 19881, 15953, 2715, 16752, 0, 31881, 0, 31636, 24121, 21055, + 37799, 0, 18361, 8159, 40889, 0, 9135, 15124, 5866, 11221, 15984, + 0, 8574, 28976, 0, 26261, 16285, 21498, 7921, 8575, 24130, 626, + 12691, 15541, 31787, 37252, 40493, 26668, 4317, 32618, 12457, 21788, 32693, + 35629, 36948, 35370, 34459, 26656, 25173, 10249, 25779, 15020, 36724, 0, + 33150, 22231, 24528, 2652, 0, 2098, 6126, 27717, 7107, 0, 19604, + 37900, 12101, 0, 24079, 33324, 22181, 3898, 22313, 21867, 13638, 35306, + 7137, 6762, 0, 0, 0, 6718, 0, 0, 24146, 18881, 24595, + 27912, 2296, 6272, 31452, 7703, 35729, 28295, 24125, 22971, 33120, 29656, + 33172, 36745, 895, 18476, 0, 0, 0, 0, 37836, 16854, 28450, + 16403, 19420, 23965, 40041, 34606, 31471, 18715, 31472, 25969, 7337, 0, + 30684, 7197, 35784, 21114, 3254, 28748, 12131, 27368, 22663, 151, 15714, + 2508, 0, 32173, 39694, 0, 0, 7716, 17530, 34053, 33655, 20136, + 11755, 20809, 36550, 38650, 35823, 21775, 28800, 31519, 37846, 27377, 8010, + 35824, 4952, 0, 17423, 2365, 2231, 14639, 18749, 28017, 21197, 366, + 198, 23858, 0, 4714, 4498, 0, 25153, 21401, 19327, 33153, 37744, + 20929, 375, 26635, 19310, 0, 0, 16445, 31603, 37756, 39827, 31026, + 11259, 19980, 21470, 30387, 20046, 21583, 24828, 38108, 17567, 39523, 40813, + 9869, 33591, 10252, 33728, 39640, 20233, 4260, 9048, 0, 4272, 18997, + 40268, 27164, 17711, 14310, 32928, 6089, 13783, 25385, 19479, 0, 15429, + 35019, 21630, 35399, 16467, 36600, 36130, 34367, 27983, 0, 17877, 34166, + 19564, 20474, 41173, 37163, 35785, 9049, 20093, 15076, 30962, 0, 15261, + 5816, 18380, 0, 33283, 4778, 24054, 20207, 19982, 24314, 0, 30305, + 5423, 74, 0, 1478, 21759, 17424, 13909, 36920, 4190, 41266, 2032, + 11592, 35064, 29936, 12529, 146, 19197, 12441, 30685, 1850, 37960, 33656, + 21385, 37898, 0, 460, 38925, 14378, 30664, 32951, 23466, 35400, 32952, + 4373, 24596, 6325, 21482, 23493, 12446, 29898, 0, 27814, 5818, 16564, + 38678, 0, 0, 36110, 2451, 12425, 11715, 40815, 16324, 21064, 14584, + 24318, 5011, 0, 13616, 33555, 4477, 36663, 6252, 3455, 0, 20424, + 11476, 28176, 15403, 41045, 10253, 3293, 33953, 21214, 3574, 17400, 208, + 20757, 27621, 32473, 34760, 11158, 4875, 24597, 16550, 7959, 6563, 19494, + 16468, 30137, 9977, 19524, 1897, 25113, 23247, 9978, 0, 18478, 0, + 29375, 38237, 23261, 38085, 20003, 22249, 38699, 32534, 8526, 0, 23262, + 0, 18716, 0, 37912, 6935, 6477, 20392, 30530, 24950, 27918, 20393, + 29743, 0, 20507, 35034, 14897, 17174, 15763, 8530, 37567, 4989, 0, + 16561, 18510, 23859, 302, 1595, 36557, 19532, 5360, 0, 303, 0, + 31687, 8042, 5116, 14346, 25729, 29629, 24729, 6977, 23181, 12351, 12352, + 11174, 13532, 41190, 1597, 19875, 555, 30730, 35591, 376, 37199, 10232, + 6579, 31117, 21355, 4687, 0, 16951, 18614, 21471, 11260, 17272, 0, + 18958, 7743, 20102, 37455, 0, 14579, 0, 0, 38646, 22337, 35545, + 0, 12530, 1111, 0, 25306, 11449, 7232, 8673, 15680, 13786, 26081, + 0, 27617, 29579, 37476, 40706, 1174, 15724, 17103, 11457, 34035, 21868, + 0, 38940, 30977, 32162, 23597, 35133, 19638, 0, 0, 27370, 0, + 23997, 40553, 16048, 31349, 36316, 4153, 29087, 17415, 1084, 8999, 19508, + 33000, 7798, 18511, 38156, 39343, 3921, 19456, 18389, 0, 36291, 22776, + 39352, 12952, 18986, 21490, 35789, 0, 12570, 12370, 38541, 37133, 14291, + 11307, 39537, 16158, 18004, 39544, 970, 38487, 14380, 5171, 17736, 35700, + 38864, 32327, 3580, 4445, 3522, 34474, 16469, 6273, 18479, 2678, 0, + 29904, 2541, 51, 3534, 0, 36470, 38957, 29687, 0, 29907, 2554, + 35039, 40959, 0, 22048, 24107, 17433, 24270, 18668, 34652, 15303, 27951, + 35988, 2650, 14203, 13272, 0, 14164, 0, 6190, 0, 14747, 10050, + 5640, 0, 0, 10619, 0, 3460, 5847, 1176, 0, 34103, 18591, + 0, 32831, 1186, 0, 1198, 0, 32163, 25700, 1674, 7115, 14769, + 0, 39204, 919, 6955, 37181, 24793, 38090, 20052, 35673, 27763, 0, + 0, 0, 26295, 28555, 20801, 14145, 1483, 25415, 2487, 2305, 6052, + 0, 0, 0, 0, 5547, 29654, 28441, 33255, 27781, 6687, 31791, + 28889, 0, 29067, 26300, 13115, 39661, 30521, 36259, 0, 0, 11371, + 39929, 23494, 40900, 0, 32993, 33001, 38255, 30607, 0, 0, 28492, + 38604, 21676, 0, 0, 0, 35635, 25282, 27339, 2581, 40591, 0, + 20227, 12270, 7378, 22271, 71, 7312, 333, 24321, 23569, 32744, 7560, + 8378, 23987, 8637, 29582, 2653, 36875, 8538, 980, 8154, 3974, 40278, + 0, 0, 10161, 21618, 14844, 3672, 2588, 15566, 17780, 17104, 37232, + 0, 36971, 9900, 17105, 10743, 8940, 15436, 37638, 5425, 11725, 0, + 9489, 14211, 41293, 8167, 24153, 868, 3077, 4383, 19496, 9932, 31797, + 24599, 11555, 0, 0, 3787, 25894, 34298, 39467, 5430, 28986, 19830, + 18033, 27183, 29949, 2249, 5968, 3082, 22350, 35320, 14473, 12532, 16259, + 29301, 37645, 0, 2196, 23154, 37255, 17409, 4490, 0, 0, 0, + 37008, 12313, 30794, 20088, 28191, 32853, 33483, 3598, 24624, 11759, 0, + 37009, 24163, 27559, 27539, 6728, 18500, 0, 22147, 28604, 36218, 25946, + 7469, 3131, 37568, 35467, 11925, 26010, 35208, 20446, 7647, 10395, 0, + 36274, 2433, 21339, 372, 7770, 17434, 2911, 2788, 19256, 5933, 10867, + 18752, 0, 35878, 11175, 38393, 10880, 6978, 12023, 28284, 21342, 32379, + 16915, 32380, 34653, 18386, 19835, 13870, 12200, 0, 1453, 37202, 12035, + 20306, 3833, 19331, 0, 16662, 13739, 30853, 35989, 33776, 31882, 2289, + 16370, 36241, 33081, 37971, 19177, 18153, 23736, 11981, 12853, 31060, 0, + 0, 8682, 40136, 5953, 36630, 12449, 34784, 25617, 31693, 27512, 37380, + 35376, 23801, 12271, 24882, 29253, 27156, 23799, 20784, 13843, 19602, 36196, + 8341, 22903, 33824, 19617, 7392, 34184, 11589, 37227, 9252, 9332, 18300, + 6895, 40822, 40857, 1180, 30219, 0, 17766, 0, 0, 0, 9901, + 36056, 40132, 3748, 32245, 33850, 0, 24586, 22278, 9579, 7071, 8942, + 24452, 10838, 16595, 17106, 3217, 25867, 40698, 31063, 23018, 15512, 30020, + 22318, 28987, 28453, 40614, 1607, 9223, 10847, 0, 1776, 39663, 6167, + 6545, 39993, 21189, 17934, 22933, 12442, 20394, 30689, 3061, 9051, 665, + 25557, 28628, 2077, 40902, 15902, 16556, 10081, 36408, 39699, 13667, 33281, + 32860, 34059, 26275, 23763, 32803, 28006, 9868, 20140, 11895, 22457, 0, + 11760, 20902, 27825, 990, 3769, 13681, 11575, 16406, 0, 11098, 6235, + 12018, 9706, 34958, 2434, 9609, 13139, 13024, 5363, 13970, 19302, 11772, + 20250, 2260, 19037, 22613, 34861, 14642, 14643, 25070, 0, 23689, 26183, + 0, 14348, 12024, 37885, 4956, 33757, 32642, 7523, 2440, 35218, 0, + 5452, 0, 24272, 11701, 30006, 0, 23954, 31696, 21285, 25831, 19883, + 29871, 16417, 10233, 4467, 38567, 281, 19170, 20349, 0, 7893, 0, + 32902, 1990, 11828, 24412, 32903, 0, 0, 2001, 23790, 22944, 13492, + 14981, 16099, 14535, 7032, 21600, 23725, 6029, 6030, 0, 23149, 39393, + 23267, 40515, 15630, 36954, 24236, 15635, 10346, 7941, 0, 5617, 32339, + 9630, 10359, 25123, 10069, 29658, 1907, 26271, 1135, 18727, 35192, 21233, + 4061, 25896, 5908, 18728, 29705, 17502, 15411, 25897, 39154, 4064, 17537, + 19654, 0, 23683, 15177, 26459, 32629, 1296, 38394, 36281, 31582, 26325, + 28041, 25799, 25716, 4302, 18622, 18124, 2531, 0, 11416, 0, 0, + 12753, 631, 10905, 6262, 0, 18552, 14441, 14803, 15406, 28329, 19192, + 38942, 6073, 6505, 40334, 34461, 22138, 2540, 0, 0, 0, 0, + 35571, 0, 0, 36762, 11635, 35044, 35008, 39531, 8937, 23402, 8790, + 0, 0, 10798, 20114, 7928, 10832, 9485, 28715, 5517, 0, 34361, + 0, 0, 24883, 0, 2930, 20503, 28894, 798, 143, 0, 0, + 32251, 0, 0, 0, 19639, 16526, 21009, 902, 3167, 0, 7426, + 40051, 12135, 13578, 27371, 0, 16105, 5971, 18729, 0, 0, 0, + 0, 37032, 28563, 2839, 19439, 20444, 11417, 30890, 21833, 11418, 10757, + 14151, 1939, 32272, 17188, 13971, 0, 19534, 22749, 10223, 34795, 0, + 32389, 28042, 30731, 3102, 31583, 13990, 2477, 10482, 7584, 26195, 18101, + 0, 6585, 23201, 23132, 37757, 1991, 0, 11836, 6017, 34683, 14696, + 13552, 21030, 17859, 36949, 29198, 29243, 31253, 10705, 32697, 10267, 0, + 29358, 39269, 0, 11472, 8218, 0, 0, 29974, 0, 25357, 13405, + 0, 33166, 0, 0, 37632, 14839, 11156, 0, 688, 20706, 0, + 30665, 0, 19776, 27726, 1476, 18593, 24691, 0, 0, 8685, 38943, + 18886, 22032, 25393, 24600, 17781, 8944, 32252, 31799, 33123, 0, 21451, + 0, 0, 0, 32849, 17791, 7858, 4843, 40615, 420, 41294, 38952, + 41143, 10371, 12301, 0, 12867, 0, 0, 0, 29784, 32174, 34499, + 28794, 28459, 5627, 14886, 254, 9992, 32708, 14480, 30534, 678, 40495, + 21527, 29340, 20960, 0, 0, 36842, 20195, 0, 0, 20964, 26782, + 2513, 34312, 8795, 3754, 25650, 12773, 24257, 19571, 6958, 17177, 3482, + 38125, 10396, 13682, 21398, 0, 9416, 10758, 8353, 0, 991, 28352, + 31161, 12572, 31541, 24485, 10412, 31000, 32185, 13700, 11900, 22530, 26627, + 3771, 39207, 0, 38597, 27589, 12162, 27850, 39585, 977, 0, 0, + 0, 16519, 1297, 33879, 22260, 5061, 0, 39431, 22535, 2794, 1298, + 28029, 12025, 10522, 14229, 4099, 13274, 21200, 9183, 7407, 0, 0, + 28493, 4784, 31585, 5442, 32200, 15801, 38981, 28414, 10967, 4785, 18788, + 14790, 18789, 23865, 22219, 39222, 0, 17213, 2375, 23333, 0, 0, + 29199, 18102, 24810, 17510, 18672, 27296, 8979, 38989, 22174, 13997, 24392, + 0, 0, 40930, 23091, 13918, 1603, 13175, 9721, 0, 0, 38168, + 17837, 16965, 19171, 26691, 20209, 13182, 5592, 949, 0, 17514, 0, + 32227, 22801, 25099, 18413, 41200, 0, 14975, 26256, 33939, 0, 33084, + 0, 16423, 23381, 35532, 21866, 16997, 37775, 0, 35551, 3401, 12491, + 10149, 32943, 15509, 40712, 10313, 31793, 24884, 9864, 31913, 9865, 9508, + 2657, 34045, 33473, 26702, 15604, 31920, 26149, 36933, 34263, 23033, 41054, + 36836, 40863, 17503, 32085, 32031, 35579, 26156, 34626, 13521, 31543, 3547, + 27097, 15267, 36222, 10514, 35915, 31604, 26037, 13998, 35247, 36706, 25100, + 35149, 18991, 16078, 39324, 0, 0, 0, 0, 32797, 0, 4765, + 33394, 236, 33423, 2244, 4108, 38415, 0, 35706, 22434, 15640, 26749, + 16478, 29938, 31496, 18051, 23164, 31096, 17533, 6351, 19834, 16441, 30702, + 6501, 38, 38029, 11773, 35859, 20646, 40879, 7668, 22370, 0, 1334, + 17295, 18625, 19235, 9861, 39134, 8311, 25046, 39081, 15549, 3330, 14335, + 14898, 12573, 18091, 0, 26453, 25088, 25717, 4310, 21209, 39372, 18493, + 22171, 0, 0, 796, 25394, 32077, 16790, 32602, 7859, 24771, 0, + 26100, 39574, 28656, 25479, 27941, 36475, 19572, 20965, 1493, 0, 27436, + 28808, 10097, 25979, 25418, 0, 5460, 23079, 13372, 28731, 0, 25159, + 21654, 17838, 6032, 5955, 39947, 0, 18938, 5208, 31408, 9565, 12255, + 21307, 35621, 21420, 37135, 30457, 9843, 38302, 34348, 4749, 32147, 13407, + 29699, 8150, 22272, 0, 36681, 24529, 34155, 2105, 1470, 27022, 38417, + 35680, 1471, 0, 6556, 16327, 35308, 2633, 3673, 33852, 33609, 36972, + 33376, 0, 0, 0, 9739, 0, 0, 0, 18482, 32961, 3078, + 12991, 28620, 22598, 38068, 33795, 32158, 21481, 0, 0, 0, 0, + 0, 20124, 12536, 21774, 10848, 11144, 30472, 36757, 38240, 1232, 20087, + 23896, 32969, 7330, 35760, 28624, 16791, 36631, 0, 13953, 26533, 36260, + 12444, 0, 27987, 0, 0, 0, 30478, 20268, 27994, 35795, 26180, + 31498, 12319, 19200, 36691, 19649, 38462, 28192, 39701, 1486, 16876, 0, + 0, 0, 0, 0, 0, 0, 24100, 9415, 31525, 39205, 36552, + 21536, 15077, 32995, 35035, 32996, 39416, 21204, 0, 27642, 18459, 3177, + 20142, 25062, 5106, 26276, 0, 0, 0, 28020, 33005, 1940, 6077, + 41061, 0, 27385, 26513, 10098, 28633, 8586, 0, 0, 0, 20914, + 20157, 34072, 19837, 13146, 4735, 14921, 10479, 7524, 26945, 3065, 26721, + 21829, 22882, 19457, 0, 0, 0, 0, 35917, 3821, 0, 15665, + 746, 16685, 15416, 26172, 1319, 28158, 8730, 22624, 35918, 32201, 21348, + 36428, 40256, 4273, 7774, 33699, 22734, 31296, 17682, 2342, 41032, 41237, + 1507, 35093, 11346, 22041, 33405, 0, 16757, 24434, 32777, 13387, 9802, + 0, 0, 34424, 33938, 40177, 10559, 36444, 31627, 0, 0, 17481, + 32292, 11358, 36107, 0, 17557, 26288, 2345, 952, 13073, 27416, 7357, + 5836, 0, 492, 37119, 0, 0, 21050, 16778, 36033, 5012, 0, + 2677, 3015, 8373, 13934, 21193, 0, 0, 0, 17717, 20595, 36825, + 0, 18324, 9971, 0, 36666, 13944, 3526, 25326, 21723, 0, 0, + 10717, 29339, 0, 18, 9259, 1532, 1909, 24458, 0, 27372, 4215, + 11690, 3021, 8185, 11611, 6941, 30797, 7612, 28657, 0, 19069, 10470, + 36645, 11693, 0, 37036, 40956, 34629, 24634, 38878, 14221, 28564, 0, + 0, 0, 0, 0, 0, 29956, 17889, 14227, 38465, 33219, 11101, + 0, 33672, 0, 0, 0, 4774, 24408, 20647, 0, 38161, 1062, + 3431, 0, 0, 34654, 8731, 20657, 942, 14740, 6003, 38896, 0, + 31221, 34655, 0, 14947, 32111, 28581, 10035, 0, 5782, 12630, 13744, + 0, 41126, 0, 33068, 16315, 7281, 12064, 31892, 21595, 20060, 25166, + 4705, 36121, 20116, 0, 14911, 24693, 29596, 30397, 38910, 17023, 26446, + 15571, 32063, 38927, 39394, 29407, 27230, 927, 35249, 22694, 2850, 11039, + 15499, 14245, 139, 4248, 23739, 885, 403, 7600, 15339, 30078, 30079, + 41240, 18014, 0, 9589, 34291, 27050, 10793, 17792, 26103, 27737, 0, + 904, 25332, 6348, 1910, 17579, 23814, 7510, 12577, 40957, 11620, 10400, + 16882, 37579, 37735, 33395, 2795, 5574, 16680, 13911, 3726, 27766, 23117, + 35050, 13251, 11291, 11435, 28923, 25622, 31027, 36454, 25242, 36122, 27015, + 36115, 14833, 29984, 33792, 12695, 39887, 24140, 40281, 5848, 0, 36876, + 0, 0, 35410, 26977, 35709, 20596, 0, 0, 25047, 32594, 31197, + 8800, 36467, 29492, 26979, 21222, 8803, 28456, 31045, 14476, 2772, 22731, + 40618, 10850, 21117, 34380, 9027, 37166, 10754, 0, 27643, 3421, 11090, + 34857, 30999, 32360, 22792, 25422, 18516, 16602, 26239, 32632, 38257, 9916, + 7258, 10033, 2666, 38715, 0, 28427, 40341, 21732, 10124, 37083, 40666, + 36910, 17278, 12053, 31647, 32128, 2732, 17482, 0, 27615, 14311, 23060, + 24574, 8939, 40820, 36958, 0, 0, 25364, 21698, 19692, 404, 14284, + 0, 33611, 22856, 1477, 19626, 0, 0, 0, 0, 35431, 36987, + 0, 22857, 24697, 762, 11735, 0, 0, 0, 2122, 19500, 16184, + 29780, 31201, 17142, 18037, 0, 12545, 15070, 41003, 6729, 14888, 5048, + 921, 0, 0, 0, 0, 0, 16192, 1695, 28156, 29793, 33905, + 0, 0, 0, 0, 0, 6790, 0, 0, 28202, 1303, 29754, + 26021, 2304, 29810, 20251, 13865, 18904, 0, 0, 38720, 1147, 12374, + 38330, 33771, 17232, 0, 0, 28225, 36577, 27323, 0, 0, 6851, + 0, 0, 0, 0, 24515, 19136, 39185, 29987, 9087, 37150, 16735, + 1911, 21175, 22672, 17543, 28861, 17436, 30897, 5256, 17375, 29487, 30220, + 40065, 8499, 33257, 266, 7324, 22407, 1901, 30083, 27240, 35442, 1912, + 24156, 29703, 8948, 29604, 9993, 3332, 13671, 11421, 33302, 5809, 2613, + 6208, 22526, 25653, 17809, 26784, 21954, 5696, 37048, 4097, 25425, 15268, + 28818, 4571, 22721, 4172, 18791, 29640, 39347, 17234, 25808, 22050, 27671, + 0, 5257, 10991, 35974, 32409, 33088, 19140, 18351, 0, 28661, 8471, + 0, 28686, 0, 0, 0, 36728, 20976, 0, 8525, 15052, 3583, + 8992, 30333, 17143, 18218, 17797, 31970, 854, 197, 37305, 14489, 25516, + 34074, 40765, 4855, 2307, 38357, 36578, 8250, 25669, 0, 31718, 27379, + 13408, 13409, 33464, 38803, 0, 0, 27529, 3156, 7300, 12284, 39380, + 0, 9218, 31339, 0, 24151, 27358, 9866, 30084, 6344, 40833, 25143, + 20796, 8168, 18021, 12303, 33383, 33830, 20924, 34167, 13808, 17144, 4942, + 25552, 37495, 18894, 26673, 17036, 17630, 8839, 33180, 32802, 24300, 24161, + 3088, 36766, 2125, 15841, 25055, 85, 24218, 23904, 4009, 22287, 16131, + 35325, 9319, 26785, 22653, 0, 40092, 11503, 11627, 10943, 929, 0, + 0, 38390, 12579, 9185, 31570, 8587, 2627, 19307, 40336, 29941, 40528, + 32103, 16495, 0, 0, 0, 39796, 102, 32279, 9758, 31697, 0, + 29944, 2287, 25986, 32117, 13831, 7677, 25133, 0, 35101, 5373, 12794, + 16766, 34433, 18631, 29931, 36457, 22639, 19237, 17362, 1673, 0, 19627, + 519, 11573, 0, 35081, 10322, 4290, 10418, 21675, 3841, 17315, 28874, + 11309, 1194, 410, 3080, 34851, 4943, 290, 33928, 0, 40745, 4909, + 25191, 668, 4856, 30375, 28511, 750, 8381, 34363, 31443, 40298, 34215, + 7325, 36894, 148, 29906, 19856, 26542, 13975, 9191, 12604, 24064, 13484, + 34434, 31895, 15248, 20225, 33845, 26210, 31084, 23642, 11387, 25320, 39186, + 29230, 14848, 32835, 23468, 252, 19777, 9140, 0, 28892, 7241, 14614, + 2836, 27558, 1204, 19633, 27580, 9145, 10706, 11211, 19199, 10170, 12764, + 24945, 8314, 11464, 2078, 9159, 7719, 20804, 78, 36471, 27560, 17631, + 13672, 3601, 13673, 3768, 22900, 3125, 34381, 6414, 5677, 0, 17633, + 32361, 1538, 33303, 19949, 35201, 20143, 23504, 23505, 31107, 33006, 37324, + 23608, 3348, 35041, 36330, 34794, 12340, 40913, 33753, 20407, 15159, 35045, + 34534, 28285, 9654, 11581, 36423, 26786, 2561, 17438, 0, 33810, 4103, + 3105, 21349, 24892, 20287, 12031, 37074, 38667, 10980, 2480, 1558, 23784, + 31607, 13281, 15587, 19329, 19537, 38673, 1454, 12214, 14956, 21036, 1352, + 27130, 27606, 20676, 17842, 20356, 20682, 31652, 2740, 24843, 13555, 12077, + 32141, 33604, 21700, 29600, 10769, 37383, 0, 3697, 2014, 41132, 5853, + 40573, 12115, 23601, 0, 33304, 11776, 26906, 15631, 0, 6521, 34925, + 36973, 690, 13641, 39028, 12707, 26980, 5621, 6165, 4381, 8169, 20384, + 39072, 39144, 0, 34610, 24080, 10151, 8949, 23991, 19025, 9339, 16187, + 25703, 7194, 4869, 34382, 8901, 13674, 9320, 9784, 28350, 31069, 39337, + 21537, 5910, 16286, 28466, 4771, 34170, 9704, 0, 0, 5530, 0, + 20196, 13589, 20408, 14565, 37050, 39104, 38884, 38505, 33220, 0, 586, + 10419, 9065, 10689, 16567, 31371, 1862, 15530, 18794, 4658, 17448, 35340, + 24112, 27292, 0, 33881, 13873, 24225, 11704, 28059, 4158, 6618, 18393, + 0, 21092, 28689, 5161, 30751, 8441, 4963, 17258, 2159, 32415, 22086, + 16219, 40182, 21474, 11265, 36455, 32419, 16456, 20560, 497, 0, 9582, + 1123, 7848, 11988, 35742, 18326, 0, 36070, 14766, 11962, 3333, 6286, + 6837, 0, 34515, 40522, 38503, 23426, 37041, 25019, 11965, 21538, 11505, + 14566, 26548, 0, 0, 22367, 20492, 2377, 18525, 16927, 4143, 0, + 4728, 26340, 5125, 23361, 0, 16317, 18163, 17713, 25361, 36964, 35685, + 5884, 23406, 35388, 21370, 7849, 12986, 34190, 7366, 25698, 32070, 0, + 0, 1205, 26927, 22976, 21374, 39675, 28944, 29304, 29305, 25611, 35765, + 17794, 222, 10376, 24459, 17146, 9518, 40869, 27989, 37640, 34257, 2542, + 30354, 14714, 29542, 36840, 11747, 13006, 25679, 19506, 14556, 40747, 14420, + 157, 28200, 16267, 11928, 25007, 2873, 6781, 15552, 21160, 29099, 33574, + 14344, 11506, 23516, 13703, 19577, 34320, 0, 39588, 29912, 0, 97, + 22149, 2349, 28820, 7057, 11934, 23327, 3923, 28360, 40644, 21779, 29817, + 26637, 18556, 1552, 16928, 19390, 33144, 2462, 11525, 19766, 8563, 17467, + 5407, 38674, 40789, 0, 0, 39851, 488, 4805, 24562, 0, 18421, + 32133, 7549, 9814, 3292, 14317, 6907, 3674, 37705, 10635, 35023, 34161, + 34931, 29602, 38496, 36896, 33963, 35029, 15444, 11403, 16486, 37725, 3173, + 0, 0, 26713, 0, 21639, 20485, 10589, 4140, 37887, 33759, 13986, + 40654, 36942, 28638, 15274, 24498, 0, 3366, 14276, 33979, 39293, 3698, + 22053, 24115, 0, 24819, 16363, 35975, 25455, 27687, 23630, 27721, 0, + 7170, 0, 19848, 11207, 0, 0, 9907, 24098, 4003, 25066, 6567, + 17180, 476, 13826, 33527, 19227, 0, 37871, 39895, 11073, 36201, 0, + 39560, 23805, 0, 8394, 13118, 40305, 40306, 15676, 21517, 25701, 38241, + 260, 39708, 8973, 35801, 3416, 12139, 40147, 16601, 25335, 25403, 39267, + 20897, 2422, 0, 0, 35471, 14900, 1655, 3343, 15079, 6291, 30706, + 35837, 38960, 34391, 0, 25857, 19073, 22879, 38856, 10000, 37325, 5057, + 38885, 7455, 26163, 18076, 28477, 24721, 19511, 35222, 745, 9655, 9295, + 21019, 8722, 0, 26946, 15380, 28361, 4398, 40099, 28572, 15770, 24338, + 33516, 6420, 2441, 11373, 4514, 25839, 39344, 23775, 13866, 40922, 30720, + 0, 0, 31855, 20918, 23082, 27888, 14666, 39115, 26435, 28916, 590, + 28496, 23870, 31005, 25431, 19220, 10981, 27927, 39910, 23088, 20347, 13874, + 26437, 20167, 27406, 18104, 16751, 13282, 16837, 39815, 5888, 0, 25879, + 9119, 7353, 19801, 28239, 13051, 28840, 33071, 15669, 31231, 7273, 19228, + 2236, 2483, 18109, 35347, 4575, 37863, 19898, 37416, 39841, 35600, 5163, + 12054, 30637, 28697, 26047, 33058, 27931, 27835, 23718, 18285, 36003, 0, + 16813, 16981, 7546, 17845, 17988, 32420, 32790, 21938, 20062, 32137, 25212, + 40449, 27487, 34447, 1520, 18168, 10637, 23251, 17739, 613, 1215, 10916, + 10917, 0, 2425, 22286, 24470, 20479, 14337, 2129, 19722, 25871, 30804, + 0, 0, 16911, 25009, 0, 11901, 32505, 0, 27107, 36424, 0, + 21020, 11513, 14349, 34323, 0, 25800, 29873, 33047, 38990, 19821, 31866, + 19397, 0, 11532, 28690, 32778, 35257, 1354, 19117, 7274, 17283, 4745, + 4051, 5411, 5595, 15886, 3942, 32138, 2857, 20071, 23879, 24580, 39187, + 0, 0, 0, 11075, 8390, 3529, 9337, 20797, 1903, 11208, 8830, + 34932, 19634, 30468, 0, 0, 0, 25554, 33924, 39260, 20389, 13266, + 0, 38701, 41244, 37715, 17795, 0, 40082, 1216, 25336, 37287, 0, + 4320, 7116, 35802, 20091, 24421, 0, 30479, 12559, 2080, 0, 1623, + 7252, 37732, 16887, 7253, 24788, 8123, 7089, 6818, 39282, 29240, 37326, + 13976, 23430, 14497, 16271, 3064, 872, 21716, 35888, 33578, 20720, 34075, + 8045, 0, 21622, 29476, 1046, 38469, 30551, 15381, 34904, 21970, 32644, + 8845, 28828, 9659, 11805, 28415, 0, 34979, 4916, 23541, 13917, 19041, + 20168, 20169, 12927, 18806, 7268, 21931, 20031, 13746, 8137, 1677, 11582, + 27950, 34991, 21579, 13878, 17515, 2005, 12946, 29157, 18113, 41129, 26887, + 36243, 5412, 3843, 2161, 20361, 34571, 16427, 3738, 13400, 27486, 24918, + 21604, 19238, 0, 26895, 19240, 40230, 0, 14759, 14214, 7117, 35804, + 25707, 2206, 25277, 8046, 16348, 28245, 36977, 36750, 5772, 18042, 40310, + 28457, 22863, 38549, 13350, 4207, 2134, 15619, 4827, 0, 10025, 10026, + 20736, 11066, 8889, 5520, 7966, 33856, 20006, 19714, 16527, 9231, 38880, + 28467, 37329, 40980, 16932, 18796, 31227, 16694, 12463, 17321, 17004, 0, + 22914, 34824, 30231, 30093, 22327, 0, 38874, 9601, 0, 33551, 20928, + 25074, 30715, 39283, 6151, 30724, 1968, 0, 11436, 33888, 38059, 17337, + 34480, 11479, 33964, 10918, 764, 25185, 32605, 22979, 17740, 40005, 35805, + 33649, 19204, 15327, 4011, 0, 20907, 10001, 3025, 18761, 38659, 28478, + 7889, 10596, 38352, 24067, 28072, 22781, 9437, 0, 11880, 3904, 0, + 7074, 7075, 25645, 23409, 27741, 14491, 0, 34527, 705, 35215, 40758, + 21161, 4185, 2358, 29206, 10126, 41257, 38922, 30228, 8802, 1217, 7141, + 40316, 31361, 30925, 39756, 40094, 18762, 30928, 9710, 24647, 16202, 38032, + 27924, 20202, 5635, 23542, 2381, 22750, 17468, 26888, 18427, 28011, 23449, + 37629, 7759, 33460, 14843, 5656, 22692, 9381, 21699, 25321, 39182, 8343, + 22597, 28714, 3017, 4281, 10311, 20598, 1648, 23471, 27043, 1125, 14851, + 27730, 0, 9257, 20885, 11687, 31461, 7140, 33381, 20709, 0, 31673, + 39681, 25726, 14477, 5962, 39034, 26476, 19945, 1218, 10074, 36994, 32348, + 22122, 21203, 2252, 2126, 0, 23424, 12548, 40626, 18735, 15073, 32358, + 31507, 2201, 30961, 39477, 40876, 16052, 4493, 29308, 4012, 5531, 4289, + 24539, 38961, 38385, 25514, 1726, 12334, 31530, 40153, 14901, 8709, 12151, + 4907, 3134, 28391, 25748, 32506, 11566, 23336, 40332, 28283, 2614, 31021, + 15373, 15330, 9180, 8321, 7347, 4518, 2374, 39774, 2796, 16682, 33399, + 38564, 38977, 37061, 9656, 8919, 38056, 5119, 12032, 27889, 28758, 9112, + 31859, 19392, 6707, 378, 22626, 31381, 62, 19899, 22633, 19900, 34845, + 39842, 2006, 36452, 30640, 25223, 16381, 34339, 2825, 24987, 39148, 23093, + 0, 28565, 7503, 27307, 0, 5316, 4857, 28622, 29260, 3536, 28488, + 12821, 27567, 11545, 17716, 0, 0, 3119, 13948, 6912, 8995, 7986, + 6776, 0, 6943, 1016, 28901, 5680, 0, 5688, 2131, 30364, 38888, + 19075, 23315, 20818, 23862, 0, 40919, 27883, 0, 36785, 40022, 28499, + 0, 28062, 2145, 31701, 13283, 2397, 8243, 29020, 3113, 8252, 7536, + 31302, 31446, 34827, 20516, 22160, 19539, 26077, 19930, 2388, 29369, 15140, + 539, 32723, 33171, 23473, 0, 0, 26456, 11397, 21685, 32700, 3161, + 5095, 7708, 36202, 253, 25183, 25378, 19376, 7334, 24705, 26983, 10380, + 1481, 5041, 20618, 5477, 0, 0, 15824, 0, 2593, 6731, 36841, + 10272, 0, 9264, 33966, 16795, 13897, 23425, 24712, 30481, 35323, 17651, + 0, 0, 34392, 35841, 36155, 23296, 38962, 31827, 35842, 35139, 31212, + 39421, 39733, 10029, 4324, 7874, 4265, 22875, 15741, 3809, 0, 30149, + 4504, 8553, 15718, 24723, 24724, 39424, 19973, 17193, 40014, 28482, 39425, + 9234, 17614, 10871, 16196, 5779, 4460, 36335, 0, 0, 23317, 0, + 2595, 19672, 6360, 36095, 2628, 25710, 10528, 25660, 7882, 16295, 33306, + 12912, 35889, 19764, 0, 19515, 12607, 28317, 10118, 0, 17218, 40849, + 41108, 34980, 8660, 16934, 23438, 8978, 17219, 1753, 28318, 0, 0, + 28063, 3878, 12929, 32896, 946, 33584, 14171, 23089, 18105, 32491, 41302, + 5922, 4277, 24411, 21000, 38527, 18948, 35514, 26461, 37085, 11182, 16943, + 21991, 0, 0, 16944, 0, 0, 27507, 0, 35947, 21678, 27676, + 15704, 8253, 35348, 5468, 25163, 2447, 0, 29132, 24282, 1604, 28242, + 30630, 6622, 26045, 123, 23546, 41223, 15803, 7482, 0, 36299, 0, + 25973, 6308, 11841, 33073, 38286, 28698, 28845, 39843, 35979, 8078, 6858, + 0, 15102, 12743, 2569, 32229, 19466, 0, 1373, 18121, 13755, 16027, + 12795, 0, 3282, 16538, 33242, 7547, 18871, 38479, 10450, 12234, 21297, + 36459, 32791, 29036, 16612, 38292, 15965, 0, 23795, 14536, 22726, 7289, + 29696, 17952, 20064, 40692, 32920, 11127, 20065, 13604, 38001, 4587, 17369, + 25168, 40229, 36188, 10144, 0, 36035, 19008, 37794, 25170, 18171, 21443, + 37467, 21840, 0, 35744, 21842, 35745, 23744, 31963, 3950, 36148, 20132, + 31532, 20909, 15215, 41104, 31981, 34403, 29818, 29056, 31172, 28372, 36181, + 3717, 40047, 19523, 37540, 21824, 20280, 38180, 30346, 16869, 24706, 20893, + 26929, 1222, 40725, 694, 0, 14774, 32499, 15934, 22038, 15825, 34057, + 38499, 34942, 16053, 11622, 31533, 6842, 34790, 29384, 36775, 14902, 16891, + 0, 16912, 3264, 12583, 11029, 38712, 8125, 2909, 9390, 14498, 19865, + 2876, 28755, 20721, 33231, 17043, 34325, 27885, 26871, 35890, 1813, 4519, + 10774, 30365, 5707, 12194, 8732, 10010, 1969, 33402, 18257, 2263, 2264, + 35948, 33814, 34416, 38190, 10127, 36608, 40932, 0, 15276, 37086, 23196, + 39043, 19263, 0, 0, 27508, 14005, 9432, 23094, 17977, 0, 29518, + 13258, 16214, 35980, 36583, 4470, 34559, 13752, 34020, 30856, 32294, 21659, + 8262, 8750, 0, 20686, 40355, 20933, 32299, 30946, 17340, 2273, 20366, + 12969, 21361, 2648, 30296, 33614, 21825, 19352, 41144, 15238, 15115, 10168, + 0, 0, 37370, 30857, 40189, 0, 0, 35717, 0, 5854, 7970, + 1131, 40244, 40838, 27366, 31965, 21232, 0, 13439, 34058, 3683, 21777, + 25407, 39713, 25911, 0, 26232, 37311, 0, 13863, 0, 18766, 9944, + 1625, 35869, 41184, 38713, 37334, 30366, 21247, 9391, 14914, 1044, 2257, + 0, 6793, 23523, 34906, 16012, 25636, 10775, 34076, 33024, 0, 0, + 32888, 1970, 15468, 4726, 33696, 532, 21932, 40966, 0, 29207, 3961, + 3500, 21466, 9430, 7775, 33048, 5469, 30631, 14961, 38362, 25814, 6750, + 18114, 19917, 0, 9839, 19918, 18422, 0, 36527, 0, 9443, 4676, + 17011, 6406, 0, 1529, 0, 31510, 0, 5427, 5428, 32349, 17408, + 0, 26478, 32856, 26850, 30799, 0, 0, 10476, 36781, 18777, 16296, + 36487, 26790, 14793, 23538, 13045, 37934, 0, 23547, 0, 17982, 12405, + 19333, 4161, 21411, 1719, 17376, 18173, 8509, 3344, 33752, 32269, 10947, + 1091, 41064, 5005, 5006, 11935, 25832, 3106, 29118, 0, 21901, 39818, + 18271, 7541, 13487, 9371, 31709, 17916, 33788, 25365, 28973, 22572, 33173, + 26302, 39687, 30233, 29704, 29235, 35316, 32974, 22574, 34934, 34935, 21827, + 10269, 21620, 36261, 7301, 20989, 34894, 30399, 37620, 31972, 40086, 37621, + 27077, 20269, 31511, 12553, 28949, 7512, 33968, 21236, 4387, 20133, 1489, + 0, 20851, 37312, 6961, 39581, 25274, 33664, 19032, 11764, 34123, 21084, + 10103, 12779, 6295, 11226, 29750, 22833, 4646, 31553, 27852, 20022, 33186, + 31373, 24490, 38766, 28955, 33307, 14351, 14657, 11936, 29111, 19386, 34642, + 12176, 27197, 16747, 30370, 3100, 2309, 13827, 36908, 11699, 38474, 28068, + 8737, 21133, 31868, 0, 6541, 3506, 30632, 38999, 9722, 2987, 3440, + 38164, 11842, 18980, 17699, 16581, 30060, 11650, 31395, 381, 26563, 28161, + 19366, 28763, 33197, 14112, 187, 28529, 2738, 30861, 29890, 12654, 3197, + 3116, 37438, 32304, 0, 0, 0, 21134, 0, 24591, 13228, 27822, + 15074, 17662, 14503, 0, 19433, 17849, 0, 3996, 3543, 32486, 24221, + 19761, 27389, 2632, 3554, 9123, 37076, 36098, 0, 18262, 16576, 27407, + 39007, 27490, 11606, 0, 0, 6947, 0, 26168, 40983, 14931, 15094, + 29852, 18533, 30638, 3706, 40356, 17850, 0, 39014, 38854, 0, 35776, + 3886, 21237, 1852, 28099, 35587, 10288, 34276, 11350, 19461, 19462, 24825, + 16610, 10239, 39915, 20391, 32171, 39202, 27311, 41247, 40318, 9045, 33868, + 35811, 39735, 32867, 13967, 2258, 0, 2135, 17589, 39432, 12598, 30371, + 9426, 14430, 98, 8225, 9657, 10816, 34659, 25663, 39799, 1610, 35515, + 28367, 6013, 9675, 26816, 34140, 3235, 26512, 0, 0, 4293, 10652, + 6209, 3265, 30716, 25589, 27306, 2169, 12295, 37979, 23274, 34305, 8180, + 37292, 8008, 22985, 39411, 28721, 41248, 3062, 24781, 36903, 10405, 10810, + 9607, 6963, 13301, 37883, 29720, 4812, 29752, 8213, 41254, 10948, 0, + 1957, 38839, 15013, 28776, 14933, 8227, 11521, 4236, 36655, 4216, 28368, + 3502, 23701, 2174, 32718, 19401, 2238, 23548, 13179, 1357, 12226, 39516, + 40219, 24826, 38682, 12413, 1426, 0, 17344, 17354, 37781, 24992, 3245, + 8166, 2592, 28878, 27066, 10187, 24159, 23275, 1918, 20895, 29717, 3901, + 4638, 37728, 39412, 3174, 4005, 1242, 19854, 448, 29265, 20397, 17757, + 7782, 3258, 24668, 29380, 8022, 16132, 13020, 0, 0, 0, 39211, + 24645, 41300, 3622, 15946, 17810, 933, 6455, 31286, 0, 40649, 18781, + 28777, 0, 3925, 17616, 29324, 16095, 2914, 14934, 29814, 11431, 7525, + 1310, 0, 31934, 31116, 12613, 24893, 15982, 10977, 24549, 28222, 2173, + 0, 24670, 22628, 22152, 30240, 34987, 25441, 34011, 4662, 6014, 3653, + 4859, 19977, 33842, 6751, 1666, 39045, 3939, 2849, 9679, 6515, 41034, + 5503, 16284, 29037, 37782, 24993, 40232, 18056, 3126, 39152, 8193, 26535, + 29411, 15716, 34, 0, 24491, 27401, 9882, 26287, 30267, 38683, 18469, + 14257, 17116, 0, 4225, 25398, 37718, 14877, 15286, 7302, 23277, 10657, + 7993, 18601, 10668, 30101, 20398, 29266, 14782, 23427, 39315, 24423, 8953, + 29275, 16494, 19667, 36277, 18784, 37511, 14506, 22620, 0, 32890, 1503, + 11884, 40166, 25444, 25927, 31170, 2599, 15532, 26338, 22383, 19463, 33411, + 0, 4536, 15536, 40409, 2723, 27681, 3707, 28247, 951, 15183, 0, + 39856, 30867, 20418, 18137, 41121, 21610, 18174, 23482, 37720, 0, 35892, + 31761, 3180, 0, 25487, 3196, 21741, 36729, 12486, 1887, 7397, 0, + 0, 4625, 5620, 13344, 36990, 10367, 33625, 37244, 24699, 0, 546, + 8806, 14215, 0, 34268, 27375, 36767, 27847, 35204, 2348, 34965, 27390, + 34397, 27449, 17745, 4520, 37354, 1971, 28159, 0, 34661, 16804, 17914, + 29057, 6383, 37783, 12427, 0, 37827, 0, 0, 14385, 14548, 3884, + 3158, 8892, 32545, 32247, 142, 9584, 37145, 16734, 0, 29774, 3164, + 33264, 24607, 10189, 0, 5270, 2199, 5626, 34488, 40728, 0, 36320, + 2685, 0, 16896, 28351, 19278, 19283, 0, 28815, 22259, 18519, 23180, + 4854, 29815, 6989, 2261, 13718, 35506, 12392, 5281, 14993, 1126, 16787, + 35749, 4256, 4259, 22980, 16870, 38026, 28600, 22986, 4627, 14632, 33667, + 7340, 0, 33668, 7146, 11967, 40156, 25188, 7182, 14718, 9947, 17591, + 39433, 20161, 36941, 0, 2461, 19734, 36099, 20257, 29819, 15951, 0, + 0, 20173, 25445, 37390, 23923, 20038, 14528, 22591, 13923, 30511, 12640, + 19925, 13200, 33984, 833, 8449, 2831, 17382, 17035, 24608, 6647, 36511, + 37877, 3175, 39577, 25189, 0, 19033, 15133, 9610, 37739, 11780, 22617, + 2556, 6740, 2705, 26120, 27108, 26555, 33277, 36426, 27109, 3634, 35236, + 10011, 7530, 35237, 34545, 41137, 27895, 13875, 6797, 32401, 9367, 28924, + 24189, 2810, 10018, 19978, 37758, 4664, 23874, 13922, 20780, 37519, 0, + 22341, 39351, 39845, 4278, 37205, 20732, 30423, 13320, 23206, 28079, 22769, + 29288, 15804, 4669, 28252, 0, 13601, 13194, 324, 13495, 35271, 0, + 35272, 18424, 38171, 751, 17485, 0, 11363, 18963, 30652, 32300, 29445, + 2020, 39355, 40223, 866, 19933, 32937, 21940, 36716, 0, 32740, 17365, + 38455, 20072, 0, 0, 0, 32929, 0, 0, 0, 0, 12542, + 13587, 0, 21458, 322, 3997, 31346, 9386, 32988, 29544, 33969, 5305, + 38595, 28723, 22334, 32874, 33680, 32377, 27756, 15735, 31219, 11950, 25731, + 6333, 11344, 16138, 8237, 4072, 32210, 24279, 24132, 16349, 0, 34277, + 36353, 25092, 10155, 4294, 39823, 0, 30763, 34435, 32565, 36006, 21301, + 0, 26904, 6053, 40816, 14836, 33595, 37549, 0, 0, 33560, 5377, + 29251, 8768, 35418, 10642, 35310, 0, 17033, 15644, 32260, 28127, 31803, + 33859, 0, 0, 5525, 16258, 39999, 21426, 3324, 13123, 1245, 40420, + 18059, 10279, 704, 28805, 3425, 19300, 32370, 27466, 36560, 24726, 0, + 23078, 11792, 30619, 35595, 35238, 0, 3108, 10236, 1709, 0, 32411, + 2735, 11943, 0, 10078, 4385, 39414, 23289, 15935, 25515, 0, 36325, + 33343, 0, 10960, 4739, 0, 25086, 5577, 31384, 24552, 0, 34679, + 17704, 1107, 0, 1721, 0, 37526, 21843, 739, 36473, 10678, 4396, + 23609, 29101, 37337, 16678, 744, 0, 12587, 8052, 32386, 2460, 10883, + 26035, 1029, 24363, 37200, 30203, 61, 10014, 5224, 8739, 5582, 12048, + 22130, 0, 40501, 18110, 19332, 19364, 17478, 32673, 33945, 39228, 23004, + 8263, 21767, 31897, 6599, 5240, 37894, 32425, 36248, 27281, 6602, 1076, + 11123, 7466, 7508, 37983, 939, 7444, 32092, 27095, 20248, 38660, 38661, + 38598, 11812, 8132, 30381, 20570, 24072, 17733, 0, 20367, 10860, 10671, + 37022, 23300, 6786, 256, 0, 477, 5692, 33877, 5701, 1287, 40095, + 22192, 29435, 35496, 0, 12789, 39801, 29820, 32892, 5213, 29395, 33043, + 2963, 37625, 9397, 17618, 1049, 0, 18816, 12402, 33889, 27410, 6337, + 27898, 10993, 37938, 2820, 675, 25453, 6862, 31008, 485, 7777, 36943, + 39046, 7639, 9398, 2086, 8753, 6626, 11546, 6396, 29159, 2022, 23877, + 17857, 18443, 30874, 38742, 16396, 28149, 20912, 1288, 30111, 40333, 5934, + 2083, 14516, 23000, 32006, 30754, 23002, 4922, 7225, 2674, 11128, 37984, + 0, 0, 0, 0, 0, 7288, 33093, 10672, 3479, 740, 36157, + 0, 14057, 1972, 25668, 3869, 36361, 35357, 8332, 16054, 37880, 39158, + 34221, 14428, 10813, 20411, 513, 8718, 1497, 40580, 10282, 39159, 26789, + 8784, 1311, 6745, 4276, 4057, 25901, 3363, 25157, 3209, 19676, 22265, + 30561, 22586, 8134, 40583, 23198, 17910, 35344, 19822, 31228, 23549, 6016, + 3213, 32007, 10439, 25929, 9279, 10783, 282, 8138, 24035, 11942, 22481, + 34428, 27682, 31706, 20498, 15986, 8747, 0, 382, 25889, 27511, 18540, + 39171, 11853, 2739, 0, 17986, 20855, 10142, 6398, 14012, 20218, 7293, + 7040, 2977, 10673, 10679, 37316, 33973, 22173, 1089, 2985, 36849, 35485, + 33975, 25791, 33690, 17204, 17221, 37657, 6577, 12034, 26175, 16838, 23015, + 10887, 9799, 2146, 25683, 30845, 27899, 238, 37094, 32455, 10558, 34805, + 32674, 34996, 0, 1376, 0, 10562, 28971, 18295, 0, 40346, 0, + 31821, 38087, 35818, 6293, 37576, 14340, 0, 1936, 29102, 36481, 0, + 35488, 21378, 26481, 992, 9003, 618, 20644, 8322, 7059, 26519, 0, + 39787, 34870, 13157, 37658, 27544, 29122, 30736, 34133, 39803, 35934, 25294, + 27127, 10986, 21163, 35125, 13180, 28169, 36495, 781, 10994, 10995, 35261, + 0, 34874, 17479, 31635, 7060, 6542, 38079, 40354, 36500, 36502, 13925, + 4164, 5238, 0, 15781, 36016, 35277, 13079, 7061, 21663, 4420, 23834, + 33985, 1874, 20106, 27549, 20563, 17598, 23436, 23437, 27174, 8080, 1949, + 1068, 1664, 35598, 30877, 11327, 7254, 23303, 19579, 772, 258, 261, + 8216, 23320, 25128, 30112, 35898, 1962, 22676, 457, 0, 33809, 0, + 0, 37375, 3499, 18607, 35508, 17222, 0, 21464, 31873, 31229, 0, + 16805, 23053, 40585, 41151, 40675, 2881, 239, 7097, 37411, 16846, 8257, + 38450, 11909, 4295, 27903, 1101, 1370, 38451, 0, 10447, 17309, 0, + 10137, 38033, 9125, 3375, 18542, 20687, 20181, 19368, 386, 39008, 40221, + 11548, 7291, 5505, 29650, 0, 6401, 31131, 30872, 12667, 3664, 17929, + 1586, 18447, 13093, 21613, 19151, 26650, 0, 9277, 21588, 35781, 15652, + 30321, 30199, 23611, 1963, 15305, 18088, 8472, 9276, 9878, 15832, 10554, + 15907, 38277, 29479, 16503, 1344, 11437, 22997, 35055, 30421, 29214, 28171, + 15720, 6591, 347, 13195, 20558, 16033, 15782, 243, 19317, 24405, 24004, + 0, 15324, 10305, 6756, 32084, 20926, 28314, 13820, 22465, 21990, 27800, + 2910, 21558, 19387, 27807, 4466, 32114, 16146, 0, 5583, 23026, 29398, + 41082, 31076, 7538, 2216, 22385, 25835, 0, 25527, 23363, 4862, 22087, + 2016, 19406, 40970, 4473, 16034, 12668, 16394, 0, 19937, 20220, 22091, + 18645, 41136, 0, 18289, 35584, 30932, 17206, 17223, 38364, 40265, 11902, + 26654, 3635, 33310, 30493, 6160, 12049, 22589, 10890, 19802, 3066, 19804, + 2988, 14539, 21786, 0, 36027, 25592, 18178, 34269, 0, 23518, 40763, + 0, 710, 8917, 38267, 13823, 37069, 24268, 940, 428, 30120, 34742, + 24062, 36857, 39805, 13829, 20661, 26770, 26332, 23339, 26333, 20098, 8961, + 35518, 8863, 8864, 29712, 7894, 33937, 35263, 29517, 29399, 20731, 18275, + 2239, 16960, 27276, 18834, 12061, 4894, 22025, 18282, 14684, 38729, 14529, + 39301, 41084, 32412, 39848, 0, 0, 16216, 0, 0, 16223, 33541, + 8865, 6865, 20751, 39973, 29141, 37607, 38624, 8866, 31010, 16506, 27908, + 38480, 9883, 11191, 38687, 0, 18543, 2856, 39862, 30868, 33822, 38194, + 20419, 9558, 27960, 0, 0, 27690, 6804, 2465, 15805, 29038, 21182, + 16587, 18692, 35535, 33097, 34581, 24396, 23058, 3849, 32240, 9400, 13765, + 16321, 19941, 35286, 0, 17226, 0, 0, 5058, 6458, 10687, 0, + 31841, 0, 23332, 0, 37587, 12367, 37928, 7406, 8918, 10180, 39219, + 25083, 0, 0, 13825, 22544, 8473, 33812, 26762, 26950, 24085, 4408, + 6007, 1977, 5875, 30376, 4409, 39594, 521, 31295, 780, 5215, 458, + 29643, 0, 8926, 14359, 9667, 4468, 36858, 37597, 16607, 14519, 8076, + 21575, 6854, 6855, 33287, 15243, 34673, 29825, 23036, 1052, 20499, 27547, + 34681, 23366, 37605, 1637, 0, 33785, 10785, 11544, 34913, 14801, 15961, + 7023, 12411, 20681, 3735, 785, 31399, 39229, 33715, 28532, 3659, 31653, + 4585, 19267, 15624, 34692, 2274, 0, 10503, 5475, 25167, 29652, 37446, + 32568, 21100, 27570, 7641, 23100, 18141, 349, 11368, 35536, 11369, 19939, + 36391, 16780, 34711, 788, 6038, 18179, 8531, 32666, 30255, 4074, 5602, + 11335, 35049, 17207, 20024, 10885, 26763, 12741, 36179, 30563, 0, 22727, + 18850, 18142, 35874, 2187, 26316, 10879, 27291, 30058, 20663, 11180, 29453, + 1791, 22387, 11908, 7895, 9838, 2152, 16972, 2847, 22554, 4864, 19929, + 28384, 23984, 39522, 15890, 1108, 329, 19940, 32387, 15706, 29694, 29854, + 30757, 32124, 0, 29857, 16614, 2833, 21346, 21352, 16937, 6179, 14691, + 23875, 2019, 26198, 38407, 28975, 23878, 21751, 35851, 14159, 8436, 5584, + 13039, 19800, 4962, 13059, 37413, 33062, 38052, 19520, 16973, 9733, 34021, + 28526, 39047, 34875, 29891, 26391, 31903, 24038, 30875, 36529, 4052, 24822, + 30205, 0, 39449, 29554, 9212, 26392, 2166, 8077, 29455, 28521, 28533, + 40659, 10016, 22893, 10445, 40506, 40119, 2025, 18294, 21830, 31625, 22225, + 5722, 10326, 29219, 30272, 29221, 23349, 12628, 3507, 486, 14008, 15476, + 17311, 14692, 24875, 16228, 9208, 23619, 23386, 32424, 13089, 26957, 12970, + 47, 11193, 38410, 38295, 35060, 38636, 12674, 2606, 34714, 12966, 0, + 0, 13396, 29649, 21004, 37773, 0, 3511, 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, 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, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 26273}; + +static const uint16_t gb18030_4_weight_py_p2[] = { + 10308, 23140, 0, 24134, 0, 9894, 0, 0, 0, 24520, 2354, + 0, 0, 26998, 0, 0, 0, 0, 0, 27613, 14821, 0, + 0, 0, 0, 0, 0, 37216, 0, 15539, 0, 0, 0, + 0, 40702, 0, 0, 0, 33247, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 20734, 0, 0, 0, 0, 0, + 12106, 35177, 15023, 0, 0, 23742, 18706, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3887, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27114, + 0, 0, 0, 0, 0, 0, 0, 0, 24193, 0, 0, + 0, 0, 8295, 0, 0, 0, 0, 0, 0, 0, 23239, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2786, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11285, 0, 35611, 41263, 13605, 0, 0, 0, 0, 0, 0, + 0, 0, 40994, 0, 0, 40810, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 13840, 0, 0, 22027, 0, 6519, + 4545, 0, 26695, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 11477, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 36191, 0, 9692, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 14237, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 26577, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 14321, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 35206, 0, 0, + 0, 6214, 0, 0, 14816, 13606, 0, 5880, 0, 14817, 4189, + 0, 0, 0, 17996, 0, 0, 0, 29471, 0, 0, 0, + 0, 0, 0, 0, 0, 8789, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 34239, 0, 0, 35392, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 30606, 0, 0, 13612, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 35381, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6041, 0, 0, 23245, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 728, 0, 0, 0, 0, 32979, 0, 0, 0, 0, + 0, 0, 0, 38809, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 36565, 0, 0, 0, 33692, 0, 0, 0, 0, 0, 0, + 0, 0, 6044, 0, 5124, 0, 0, 0, 30769, 0, 0, + 0, 9283, 0, 0, 0, 0, 0, 7305, 0, 0, 0, + 0, 20573, 0, 0, 31409, 34457, 0, 0, 21212, 5168, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5133, 0, 0, + 0, 28886, 0, 0, 8875, 0, 0, 0, 0, 15710, 3970, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 24879, 0, 20575, 0, 26825, 0, 8419, 0, 26732, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 30032, 0, 0, 0, + 27158, 0, 0, 0, 0, 21491, 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, 37901, 9289, + 0, 0, 0, 0, 0, 0, 32575, 16546, 0, 0, 5175, + 28291, 0, 0, 0, 19522, 35393, 0, 28983, 0, 1184, 0, + 0, 0, 0, 0, 0, 0, 28440, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 19186, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 31721, 11868, 4935, 0, 0, 14610, + 0, 6342, 0, 0, 190, 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, + 19780, 0, 0, 25142, 0, 28, 37238, 0, 0, 13107, 0, + 23475, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 20433, 0, 0, 0, 40075, 39638, 39925, 21105, 1805, 0, 40416, + 27359, 34114, 14863, 23807, 0, 0, 9293, 0, 29737, 0, 0, + 0, 36508, 39659, 0, 0, 0, 0, 0, 0, 15923, 0, + 0, 0, 0, 0, 0, 0, 3219, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17526, 34163, 0, 0, 0, 0, 9844, 20295, 26503, 37147, 0, + 27736, 27913, 0, 39660, 0, 0, 24126, 0, 8175, 0, 0, + 14469, 911, 0, 1225, 0, 0, 28337, 0, 0, 23812, 20505, + 2779, 0, 0, 25940, 12128, 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, 8971, 24463, 0, + 0, 0, 25500, 0, 0, 0, 27917, 27919, 34938, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3765, 0, 0, 27443, + 38909, 17170, 8351, 28131, 38590, 0, 40481, 0, 0, 0, 0, + 0, 0, 0, 0, 8196, 0, 0, 0, 0, 0, 12144, + 6233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 11752, 0, 0, + 13010, 34510, 39717, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 19758, 35079, 5529, 35463, 0, 0, 0, 1657, + 0, 0, 24785, 35853, 0, 34858, 0, 0, 0, 38431, 0, + 0, 0, 26160, 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, 16268, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 14903, 0, 23171, 0, + 0, 37045, 0, 0, 38028, 25793, 26013, 0, 0, 6658, 0, + 0, 0, 13775, 15376, 0, 0, 37674, 0, 0, 0, 13029, + 34969, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 32101, 0, 32769, 24011, 0, 0, 0, 37340, 24791, 0, 0, + 0, 0, 0, 32100, 19216, 0, 9477, 0, 0, 3267, 4171, + 35499, 0, 39320, 0, 40984, 6574, 0, 38554, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7479, 35500, 19874, 0, 0, 0, 0, 0, 0, 1413, 13728, + 27404, 17681, 1149, 27963, 0, 0, 0, 5713, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 945, 30985, 0, 0, 0, 0, 19893, 0, 2805, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5371, + 0, 0, 0, 0, 22798, 13060, 17978, 9673, 23203, 10606, 0, + 0, 0, 12404, 33063, 39300, 2813, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 34998, 2821, 0, 0, 0, 0, 0, + 0, 5751, 3760, 21169, 21170, 0, 0, 38570, 1423, 0, 2824, + 0, 0, 0, 0, 0, 0, 0, 0, 32685, 0, 0, + 0, 0, 4675, 33147, 14114, 23731, 0, 24372, 0, 0, 0, + 0, 9129, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 31322, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 37618, 1775, 0, 0, 0, 0, 30319, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 21459, 0, 0, 0, 0, 17544, 0, 0, 25247, 0, + 0, 0, 0, 0, 7351, 5578, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 11644, 35971, 32222, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 16386, 8272, 0, 33367, 0, + 0, 17599, 28883, 12253, 0, 0, 0, 13779, 38413, 26826, 0, + 0, 0, 0, 0, 23241, 1430, 0, 16401, 17933, 0, 0, + 0, 0, 0, 0, 0, 39718, 1246, 26808, 0, 0, 0, + 0, 26813, 0, 24286, 0, 0, 1523, 31407, 0, 0, 0, + 0, 0, 14749, 0, 12098, 0, 31419, 24290, 0, 0, 9899, + 0, 0, 0, 19057, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 37722, 0, 0, 0, 0, 0, 0, 0, + 17413, 0, 0, 0, 0, 0, 0, 583, 0, 0, 10548, + 0, 0, 0, 23200, 0, 0, 0, 23708, 39356, 19597, 0, + 0, 0, 0, 4544, 0, 0, 20864, 0, 0, 0, 0, + 0, 29524, 0, 40887, 0, 0, 0, 0, 0, 0, 0, + 0, 14186, 38851, 0, 0, 0, 0, 0, 0, 0, 0, + 21390, 3314, 0, 0, 23603, 0, 0, 37298, 13440, 0, 0, + 0, 0, 0, 38893, 0, 0, 0, 0, 0, 5544, 14238, + 0, 0, 0, 28165, 0, 0, 34881, 0, 0, 0, 30431, + 0, 0, 17644, 0, 29577, 0, 19966, 0, 0, 0, 0, + 36821, 0, 0, 0, 0, 0, 0, 0, 27632, 0, 0, + 0, 0, 0, 0, 0, 18564, 0, 0, 0, 36092, 0, + 0, 0, 0, 0, 3746, 0, 0, 0, 0, 0, 8448, + 14236, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24316, + 14201, 0, 32823, 0, 0, 0, 0, 0, 0, 0, 0, + 10460, 0, 0, 0, 28887, 0, 24585, 32826, 14122, 21387, 14123, + 0, 0, 12277, 0, 0, 0, 0, 0, 0, 0, 0, + 29295, 0, 4753, 5950, 0, 24400, 0, 0, 0, 0, 0, + 0, 0, 22899, 22859, 0, 5960, 18562, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17501, 9989, 22123, 28792, 0, 0, + 0, 35464, 33802, 28389, 18226, 27497, 26708, 0, 2128, 27870, 0, + 0, 24262, 26675, 0, 0, 0, 21754, 29551, 13240, 0, 0, + 0, 0, 0, 0, 0, 0, 31580, 39807, 0, 0, 0, + 0, 0, 0, 16303, 17247, 17248, 0, 0, 10442, 13542, 0, + 34437, 0, 27210, 0, 0, 26961, 0, 0, 0, 0, 0, + 0, 39127, 0, 36675, 0, 0, 0, 0, 0, 0, 28387, + 31183, 0, 0, 0, 0, 0, 2891, 4548, 0, 0, 0, + 14596, 0, 0, 0, 0, 0, 0, 0, 27218, 0, 0, + 0, 0, 0, 14323, 30584, 0, 0, 0, 0, 0, 0, + 0, 0, 11995, 0, 0, 0, 0, 0, 13584, 0, 0, + 0, 0, 0, 0, 0, 38183, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 21945, 0, 0, 0, 0, 0, 9286, + 0, 0, 0, 0, 0, 0, 10205, 17019, 39606, 32313, 0, + 0, 2054, 2944, 0, 0, 0, 0, 0, 0, 0, 0, + 37797, 10368, 0, 0, 0, 0, 0, 0, 0, 28914, 0, + 0, 0, 1573, 0, 0, 0, 0, 5842, 0, 7131, 14239, + 0, 0, 0, 0, 5637, 35618, 16035, 0, 38917, 0, 16114, + 39975, 14583, 0, 0, 0, 26292, 26140, 5844, 566, 12090, 0, + 0, 39875, 0, 0, 35367, 0, 15576, 31135, 0, 0, 0, + 8626, 393, 0, 0, 8987, 0, 0, 32146, 9248, 18299, 3515, + 9312, 4078, 0, 16848, 4629, 27423, 0, 0, 0, 0, 0, + 0, 1115, 0, 0, 0, 1758, 17084, 0, 0, 14295, 29349, + 6713, 0, 34287, 24901, 0, 0, 17764, 0, 15422, 0, 8779, + 39058, 0, 7596, 0, 0, 0, 0, 0, 0, 0, 0, + 35383, 0, 14313, 33598, 13414, 0, 0, 18918, 14296, 0, 3855, + 0, 0, 32319, 0, 15755, 6559, 0, 0, 0, 0, 19095, + 31437, 24324, 2106, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 23587, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 22440, 34158, 1005, 9817, 9254, 0, 0, + 0, 14464, 0, 0, 23570, 0, 14856, 0, 0, 0, 0, + 0, 17120, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 11142, 13342, 0, 0, 0, 0, 0, 0, 23591, + 0, 38419, 23571, 0, 38947, 2504, 36468, 0, 0, 34295, 0, + 3680, 0, 0, 0, 3533, 0, 30275, 0, 27859, 0, 0, + 0, 0, 0, 15206, 37550, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3790, 0, 28338, 29740, 0, 0, 38955, 29047, + 0, 31156, 0, 4901, 17156, 2506, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 25399, 8972, 25054, 0, 16871, 0, + 0, 0, 0, 28899, 0, 0, 0, 0, 0, 17157, 0, + 0, 20014, 0, 3608, 0, 0, 9725, 18506, 4168, 28343, 13442, + 13958, 0, 0, 0, 7179, 38523, 0, 0, 0, 0, 0, + 0, 0, 13959, 4769, 0, 0, 2486, 41220, 0, 38882, 0, + 0, 22755, 38654, 31538, 35082, 8122, 3687, 0, 0, 0, 0, + 0, 4773, 0, 0, 0, 9268, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 12160, 0, 0, 26014, 38599, + 18194, 26015, 35217, 0, 0, 0, 0, 0, 14429, 0, 0, + 0, 0, 0, 29753, 0, 0, 0, 25571, 38268, 11336, 0, + 0, 0, 0, 32276, 0, 23693, 38894, 0, 0, 0, 0, + 0, 0, 2265, 0, 0, 16140, 17229, 25522, 0, 0, 0, + 6368, 0, 0, 17816, 0, 0, 0, 0, 36355, 17249, 0, + 0, 6371, 0, 18112, 0, 0, 0, 0, 0, 0, 0, + 30289, 0, 0, 0, 0, 6028, 0, 0, 0, 14240, 0, + 17071, 15627, 15503, 0, 39129, 0, 0, 0, 0, 0, 0, + 10458, 0, 1161, 0, 22420, 0, 0, 0, 0, 0, 10148, + 0, 0, 0, 0, 0, 0, 40596, 6544, 0, 35666, 0, + 0, 0, 0, 0, 0, 0, 15423, 35667, 20590, 0, 0, + 2245, 0, 8823, 15428, 27029, 0, 0, 0, 0, 0, 0, + 0, 18019, 1006, 0, 0, 6492, 0, 0, 0, 0, 14704, + 21106, 40832, 0, 0, 40975, 0, 0, 0, 0, 0, 0, + 0, 28789, 0, 0, 31967, 10080, 0, 0, 0, 0, 19027, + 23752, 0, 0, 0, 0, 0, 20625, 21917, 10212, 0, 0, + 0, 38426, 14776, 4560, 0, 0, 0, 0, 17186, 38432, 36846, + 5814, 14908, 925, 0, 0, 0, 35038, 22756, 0, 0, 0, + 0, 0, 0, 13979, 15158, 26016, 34838, 13980, 0, 0, 0, + 15470, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2671, 0, 0, 21413, 0, 30424, 18965, 0, 0, 0, 0, + 0, 37821, 34882, 720, 0, 0, 15017, 33790, 0, 39980, 0, + 0, 0, 0, 0, 0, 0, 15988, 7789, 0, 0, 0, + 0, 0, 0, 0, 0, 24767, 26470, 28274, 0, 0, 0, + 6324, 0, 15740, 22214, 0, 0, 0, 0, 0, 0, 808, + 0, 0, 0, 8203, 14342, 25150, 0, 0, 0, 14437, 0, + 0, 0, 0, 0, 24501, 0, 0, 40033, 11194, 752, 0, + 0, 0, 0, 0, 35374, 0, 35394, 35395, 0, 0, 0, + 0, 19624, 0, 0, 0, 0, 0, 0, 0, 0, 25654, + 0, 0, 0, 0, 4414, 0, 0, 9957, 0, 4546, 0, + 0, 0, 31773, 0, 0, 0, 0, 24924, 29366, 0, 5894, + 0, 9966, 0, 0, 0, 0, 0, 0, 0, 0, 35155, + 0, 0, 0, 0, 0, 6810, 30588, 0, 2327, 5907, 0, + 0, 0, 6931, 5684, 0, 28105, 24965, 0, 0, 6976, 21922, + 33806, 0, 0, 0, 31292, 0, 0, 0, 35972, 0, 20733, + 0, 0, 0, 0, 0, 0, 0, 10827, 0, 0, 0, + 9967, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 26900, 0, 0, 0, 25778, 0, 0, 0, 0, 1156, 0, + 9958, 14115, 0, 0, 24317, 4842, 4435, 0, 567, 0, 0, + 0, 0, 6520, 0, 0, 0, 0, 31777, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 39392, 19017, 0, 10843, + 12298, 9316, 0, 0, 0, 0, 0, 22124, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40161, + 0, 0, 0, 0, 1150, 0, 37079, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 23393, 0, 0, 10330, 3946, + 0, 0, 26465, 3568, 1878, 0, 0, 0, 25362, 36732, 0, + 0, 0, 20939, 0, 0, 0, 0, 11722, 29371, 609, 0, + 0, 0, 0, 33467, 0, 0, 0, 36744, 3587, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10545, 0, 0, 0, + 30264, 0, 0, 32999, 0, 0, 0, 14918, 0, 28150, 24342, + 40414, 0, 0, 0, 0, 0, 0, 12475, 0, 0, 1162, + 0, 31438, 0, 0, 0, 0, 0, 12308, 0, 15075, 0, + 0, 17655, 36699, 0, 0, 0, 0, 0, 0, 14453, 0, + 0, 0, 0, 37685, 0, 0, 687, 0, 0, 22485, 0, + 0, 38300, 0, 0, 35628, 5604, 0, 0, 24137, 0, 28326, + 0, 4439, 0, 40273, 37690, 0, 0, 0, 0, 0, 13332, + 0, 0, 0, 0, 26911, 0, 0, 35396, 31945, 0, 0, + 0, 0, 0, 0, 0, 37537, 0, 0, 0, 0, 9776, + 0, 15432, 0, 0, 4754, 35725, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17121, 0, 5766, 0, 0, 31467, 0, + 0, 0, 0, 1248, 0, 0, 1434, 19701, 17138, 0, 0, + 27916, 0, 0, 0, 0, 0, 0, 0, 0, 18219, 9642, + 15451, 0, 0, 0, 0, 35465, 0, 31739, 36158, 0, 0, + 0, 0, 15456, 0, 0, 0, 26544, 0, 0, 0, 31070, + 0, 0, 0, 0, 0, 0, 22619, 0, 0, 0, 0, + 0, 0, 0, 37742, 10688, 0, 0, 17209, 8232, 0, 0, + 0, 0, 0, 0, 0, 14955, 32116, 0, 0, 0, 0, + 5752, 0, 0, 17348, 0, 0, 0, 0, 0, 0, 29722, + 0, 0, 0, 0, 12844, 0, 0, 522, 5638, 38782, 0, + 0, 0, 0, 0, 37214, 0, 0, 0, 0, 6554, 0, + 0, 0, 0, 2222, 29763, 0, 0, 0, 0, 0, 0, + 0, 28618, 12279, 23242, 26299, 21373, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9414, 0, 1138, 0, 0, + 33212, 0, 0, 0, 0, 0, 0, 0, 39165, 0, 0, + 0, 0, 0, 25765, 0, 20572, 0, 7906, 0, 0, 0, + 0, 28884, 686, 0, 0, 0, 0, 0, 0, 1605, 0, + 31411, 0, 13615, 0, 0, 0, 0, 0, 0, 0, 13929, + 0, 0, 0, 0, 0, 0, 0, 23640, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 27724, 14091, 0, 3524, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14094, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 28189, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 38383, 16880, 0, 0, 0, 40579, 0, 0, 0, 0, + 1492, 0, 0, 0, 0, 0, 30001, 0, 0, 0, 1292, + 0, 0, 7521, 0, 0, 0, 5441, 0, 40211, 0, 0, + 0, 0, 14446, 0, 0, 0, 0, 0, 0, 0, 35544, + 0, 0, 34226, 0, 0, 3564, 9287, 39528, 0, 0, 0, + 0, 0, 0, 25355, 0, 0, 36677, 0, 1876, 0, 12428, + 22811, 0, 0, 36302, 34721, 19546, 0, 0, 0, 0, 0, + 0, 0, 18471, 20837, 25822, 4077, 0, 4366, 31245, 25303, 0, + 0, 0, 5010, 12258, 0, 35548, 0, 25135, 0, 0, 11980, + 9249, 0, 38920, 22593, 0, 0, 37953, 624, 13621, 0, 0, + 10737, 0, 0, 32315, 11588, 0, 0, 0, 0, 0, 0, + 0, 0, 38370, 4996, 8630, 0, 22594, 0, 22691, 26907, 17603, + 37691, 11048, 1461, 0, 0, 25359, 0, 25360, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 35298, 39364, 0, 13844, + 30992, 2970, 0, 24525, 0, 40235, 0, 38414, 22948, 207, 0, + 10337, 0, 3883, 34352, 0, 0, 0, 27020, 11056, 6894, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 26912, 0, 0, 0, 0, 30037, 5014, 30261, 22906, 25466, 14377, + 0, 1829, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 37140, 6225, 0, 9575, 27178, + 0, 0, 28292, 21313, 39982, 18473, 1765, 41226, 35179, 25178, 0, + 18009, 25782, 0, 0, 16732, 6900, 0, 39949, 12436, 0, 0, + 6901, 0, 0, 0, 41282, 0, 0, 20876, 37870, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 32950, 41157, + 27349, 6119, 7203, 25285, 0, 652, 9968, 10629, 35304, 0, 35305, + 0, 0, 15341, 35695, 11663, 39240, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 14129, 0, 0, 8681, 0, 0, 21757, 24145, 0, 5951, + 0, 12514, 35727, 35419, 0, 7958, 27577, 27578, 36623, 15487, 11160, + 10715, 0, 0, 0, 10358, 0, 0, 10315, 23804, 23592, 0, + 27731, 0, 655, 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, 14031, 15433, 0, + 0, 0, 0, 0, 13, 18496, 0, 29732, 0, 0, 4152, + 0, 0, 27843, 3307, 0, 30517, 0, 0, 21801, 0, 14299, + 0, 0, 1686, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 32749, 26748, 10792, 0, 0, + 40296, 0, 9351, 12121, 0, 12526, 0, 31469, 0, 26527, 21951, + 10910, 28449, 32702, 0, 38206, 0, 0, 2039, 23484, 30187, 30047, + 5382, 0, 20888, 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, 38519, 0, 0, 34248, 0, 0, 31264, 39125, + 5447, 10317, 0, 245, 22509, 26001, 7646, 9258, 0, 0, 0, + 22954, 0, 0, 0, 33860, 9934, 8506, 419, 40891, 19968, 0, + 11997, 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, 5729, 31470, 0, + 0, 4983, 21053, 0, 0, 0, 5855, 19196, 15439, 0, 0, + 0, 0, 35783, 14882, 10386, 0, 12310, 0, 0, 10467, 21524, + 25723, 23753, 5046, 26422, 15447, 40201, 0, 26844, 18925, 12718, 22662, + 10807, 12130, 28458, 3798, 31048, 14144, 22919, 38521, 33130, 0, 0, + 1482, 0, 0, 33639, 0, 0, 0, 0, 9096, 13811, 0, + 0, 32181, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6834, 0, 1920, 22698, 0, 0, 0, 38005, 0, 22034, + 29741, 0, 36314, 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, + 32497, 0, 0, 21882, 8647, 1921, 32978, 0, 0, 0, 39086, + 37027, 21330, 0, 0, 0, 0, 0, 34121, 30235, 0, 268, + 10087, 10585, 5105, 0, 21857, 0, 2392, 12324, 21207, 36640, 32617, + 0, 4053, 35080, 0, 8705, 28798, 809, 2783, 0, 33654, 0, + 0, 9872, 0, 3803, 0, 13011, 41235, 0, 0, 0, 30802, + 4905, 22454, 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, 11414, + 0, 31517, 0, 22310, 18202, 20773, 20323, 16528, 29951, 578, 0, + 0, 8652, 0, 15696, 0, 0, 12725, 1854, 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, 11415, 0, 41058, 19207, 0, 0, + 0, 0, 0, 0, 16901, 0, 10411, 20529, 0, 27541, 26626, + 15288, 3616, 18074, 19165, 0, 0, 34519, 38883, 4055, 9174, 24304, + 0, 28665, 7665, 29801, 0, 0, 0, 0, 18075, 0, 0, + 16516, 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, 16339, 38089, 31364, 0, 0, 0, 0, 16902, 5, 19035, + 39583, 3812, 13304, 0, 12899, 0, 0, 0, 0, 19072, 35480, + 0, 26372, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 12161, 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, 35855, 21621, 0, 0, 0, 11781, + 0, 38392, 0, 0, 10032, 0, 36221, 1293, 163, 31929, 21248, + 0, 0, 0, 5535, 13030, 22068, 0, 0, 37342, 4067, 37964, + 0, 2558, 0, 38971, 26017, 0, 22299, 9108, 38972, 0, 0, + 0, 0, 0, 16914, 6239, 0, 3816, 0, 41163, 22991, 0, + 0, 26494, 18385, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 27391, 0, + 13981, 18084, 0, 0, 15265, 16201, 0, 33510, 13982, 0, 4085, + 0, 0, 0, 37743, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 19340, 33028, 14275, 12602, 0, 37748, 0, 0, 0, 12921, + 0, 10008, 0, 25797, 11796, 24109, 0, 26025, 41165, 0, 0, + 18667, 11234, 3892, 26286, 31113, 12369, 40651, 32198, 35336, 9796, 16014, + 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, 40020, + 0, 0, 18767, 0, 1864, 26949, 36517, 15662, 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, 39788, 32884, 0, 0, 35242, + 7002, 18946, 10122, 35243, 0, 0, 0, 0, 19222, 4334, 7352, + 39504, 36520, 30969, 30201, 107, 37080, 0, 0, 11149, 0, 17817, + 14059, 37989, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 38132, 6578, 0, + 12617, 0, 0, 0, 31057, 0, 12381, 31602, 0, 38723, 29870, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37081, + 0, 0, 0, 0, 17827, 0, 0, 39826, 26885, 0, 16609, + 16304, 30747, 22201, 3505, 36490, 6304, 0, 6305, 0, 827, 24184, + 27408, 0, 39508, 0, 0, 0, 0, 0, 17828, 0, 22379, + 0, 38915, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 21933, 0, 0, + 33054, 12396, 16305, 36440, 2470, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 16640, 0, + 0, 0, 0, 0, 0, 19092, 0, 0, 0, 18398, 31880, + 0, 0, 0, 17979, 0, 0, 9552, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 33240, 0, 0, 0, 16963, 4363, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 24414, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 12951, 5410, 13066, 24436, 33079, 36525, 0, 0, 0, + 0, 0, 0, 0, 0, 9856, 0, 39052, 26498, 20045, 11357, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4673, 25588, 25773, 12067, 35354, 0, 5543, 0, 19023, 0, + 35999, 0, 0, 0, 0, 0, 0, 2048, 22156, 28705, 6866, + 38135, 4578, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 38533, 0, 31763, 19544, 0, 16229, 37948, 0, 0, + 0, 0, 0, 0, 0, 7027, 0, 0, 0, 6023, 0, + 0, 0, 0, 0, 0, 0, 9374, 0, 0, 0, 11443, + 0, 0, 0, 27139, 13081, 0, 0, 38631, 12419, 11444, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 30425, 19180, 0, + 0, 0, 0, 0, 0, 0, 0, 6315, 0, 0, 0, + 0, 0, 17566, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 21493, 21006, 14308, 37686, 0, 0, + 34884, 4134, 0, 0, 0, 2278, 17020, 6634, 21007, 21008, 0, + 0, 0, 0, 0, 25372, 0, 0, 0, 0, 37692, 0, + 0, 36723, 0, 36050, 0, 9772, 0, 0, 0, 5290, 0, + 0, 0, 0, 0, 0, 0, 0, 39059, 19998, 5940, 0, + 0, 39060, 0, 0, 0, 15711, 0, 9969, 27840, 10344, 12107, + 38935, 0, 0, 0, 1771, 0, 30585, 29673, 0, 29766, 0, + 0, 8503, 18497, 24932, 11921, 40402, 25049, 0, 10653, 0, 5296, + 10370, 28599, 9317, 0, 37249, 0, 34261, 0, 0, 30278, 25116, + 0, 0, 0, 0, 14883, 21916, 0, 0, 24910, 39481, 0, + 0, 18060, 31160, 33182, 4951, 0, 37497, 37647, 0, 0, 0, + 20636, 0, 36778, 0, 0, 0, 0, 31276, 0, 38751, 0, + 0, 33756, 0, 0, 25246, 9713, 37343, 0, 0, 0, 0, + 0, 31998, 1449, 36799, 0, 36106, 0, 33817, 36806, 16701, 0, + 0, 0, 0, 0, 29523, 0, 0, 39053, 0, 0, 0, + 0, 38034, 8285, 16171, 0, 0, 25039, 0, 0, 0, 0, + 14454, 0, 4221, 4895, 29981, 9, 0, 0, 0, 40814, 0, + 0, 11475, 35646, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 791, 3454, 0, 0, 25373, 0, + 0, 0, 0, 0, 0, 18585, 0, 0, 13622, 27013, 0, + 41115, 0, 0, 0, 0, 0, 0, 35647, 0, 0, 7652, + 7653, 0, 0, 0, 20578, 0, 0, 0, 27341, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 287, 0, 22571, 22844, 22908, 12751, 40037, 0, 24527, 0, 0, + 0, 36819, 28648, 0, 0, 25467, 0, 20112, 0, 0, 0, + 0, 0, 0, 0, 0, 35670, 0, 25470, 0, 0, 17767, + 24449, 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, 11664, 12496, 0, 0, + 0, 0, 8605, 0, 0, 0, 0, 0, 0, 0, 36738, + 2497, 5424, 36054, 0, 37231, 894, 0, 1896, 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, + 23988, 0, 0, 0, 0, 0, 2574, 0, 33119, 0, 3466, + 0, 0, 0, 0, 38201, 15920, 0, 7505, 0, 0, 28405, + 9338, 0, 0, 6675, 0, 0, 0, 0, 9514, 0, 39464, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2771, 21110, 0, 0, 10911, 0, 28940, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 35755, 0, 0, 21525, 38559, 11321, 0, 6443, 0, 23491, 2418, + 0, 0, 4198, 0, 0, 0, 4903, 0, 0, 0, 39692, + 8856, 0, 0, 0, 31031, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 6444, 0, 0, 0, + 3474, 0, 0, 0, 223, 16124, 0, 31092, 0, 0, 0, + 36315, 0, 22687, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 38424, 40370, 0, + 28002, 0, 0, 0, 0, 21331, 0, 0, 0, 0, 0, + 0, 40202, 2687, 0, 0, 1056, 21241, 39482, 11754, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 32029, 0, + 39719, 31518, 0, 0, 13269, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6529, 7870, 0, 0, 13358, 2996, 552, + 0, 0, 0, 0, 0, 17807, 0, 0, 0, 0, 0, + 0, 301, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 38155, 4016, 0, 0, 30147, 0, + 0, 10217, 15259, 36159, 0, 32373, 0, 0, 0, 0, 0, + 0, 8204, 1627, 0, 15904, 0, 0, 0, 24175, 25794, 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, 4913, 35161, 0, 0, 0, 38788, 0, 17586, 0, + 6547, 0, 0, 0, 0, 16563, 34003, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 39762, 0, 15661, 0, 0, 0, + 28213, 31056, 0, 0, 0, 15663, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13034, 0, 0, 0, 0, + 0, 0, 13277, 0, 0, 0, 0, 40533, 0, 27502, 37070, + 0, 0, 25798, 0, 37363, 16413, 0, 0, 0, 0, 0, + 37379, 0, 23828, 14673, 0, 17818, 0, 0, 27295, 32397, 0, + 0, 8362, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 28578, 0, 0, 0, 0, 29329, 0, 0, 0, + 0, 0, 0, 0, 19976, 0, 5585, 0, 20206, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 11645, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6798, 0, 0, + 0, 17829, 0, 0, 0, 0, 16308, 36180, 16419, 0, 13392, + 0, 12051, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9766, 0, 0, 38730, 0, 0, 0, 0, 0, 0, + 20100, 0, 0, 15912, 0, 0, 0, 0, 0, 0, 6803, + 0, 0, 0, 0, 0, 0, 0, 36184, 0, 0, 0, + 0, 0, 0, 0, 16816, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8981, 0, 0, 0, + 0, 0, 29526, 34916, 0, 30459, 0, 0, 0, 0, 13648, + 0, 0, 0, 0, 33377, 0, 27360, 0, 0, 0, 0, + 0, 0, 30790, 0, 0, 37299, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 38611, 0, 0, 0, + 0, 0, 0, 0, 247, 0, 0, 0, 0, 0, 25933, + 3846, 0, 15729, 0, 0, 0, 14544, 9897, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 20226, 0, 0, 0, + 0, 10186, 0, 0, 3791, 0, 0, 0, 18061, 0, 40907, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 16036, 0, 0, 39878, 0, 38826, 0, 6039, 9018, + 37835, 5091, 21869, 0, 0, 0, 0, 0, 0, 1772, 0, + 25146, 2658, 0, 0, 0, 25475, 36068, 2659, 0, 0, 39693, + 0, 0, 9340, 21855, 26610, 0, 0, 28003, 0, 0, 31068, + 3545, 0, 0, 0, 0, 0, 0, 20337, 39487, 0, 0, + 23173, 0, 0, 9004, 0, 0, 0, 0, 18557, 0, 40784, + 0, 0, 0, 0, 5277, 0, 32308, 0, 25535, 0, 0, + 0, 0, 0, 22399, 0, 0, 0, 0, 0, 0, 31414, + 0, 0, 0, 15709, 0, 9619, 4247, 13781, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 13782, 31420, 0, + 15629, 0, 9078, 38486, 7315, 0, 0, 32941, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 11311, 0, 21448, 31788, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4612, 0, 9693, 0, 0, 0, + 31451, 0, 0, 0, 0, 0, 23579, 0, 0, 19470, 0, + 0, 38937, 0, 0, 14755, 0, 0, 0, 1616, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1617, 0, + 0, 0, 0, 24939, 0, 0, 0, 0, 0, 31811, 0, + 0, 13432, 0, 24949, 39571, 29236, 15125, 0, 0, 0, 0, + 25869, 0, 0, 40742, 0, 0, 0, 0, 0, 0, 0, + 13678, 0, 0, 0, 0, 0, 0, 1654, 0, 6294, 41147, + 0, 0, 0, 0, 0, 0, 0, 0, 34520, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1294, 0, 0, + 0, 15744, 0, 34651, 30620, 0, 11290, 0, 10290, 0, 0, + 0, 0, 8924, 0, 0, 19882, 0, 0, 16754, 0, 5719, + 0, 1793, 11298, 0, 0, 30207, 14986, 0, 0, 0, 0, + 0, 0, 0, 3565, 0, 0, 0, 0, 391, 14290, 0, + 0, 0, 0, 0, 0, 0, 0, 5639, 0, 38798, 0, + 4979, 26908, 10250, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 35168, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1165, 22568, 35012, 0, 0, + 5514, 2295, 22785, 37698, 24124, 22425, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 30136, 32942, 0, 0, 0, 0, 0, 0, + 35174, 0, 0, 7316, 9251, 11063, 25597, 0, 0, 0, 0, + 0, 25179, 7824, 11456, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 25544, 0, 0, 0, + 0, 0, 0, 0, 19608, 0, 0, 6523, 11724, 31789, 33374, + 0, 0, 25180, 35307, 0, 0, 38938, 0, 12515, 8608, 36892, + 0, 23043, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3985, 4613, + 38939, 21449, 0, 24147, 0, 0, 2537, 0, 21450, 28123, 0, + 0, 0, 0, 0, 2538, 3309, 34928, 6436, 30436, 0, 21425, + 20002, 0, 0, 0, 0, 0, 21771, 31804, 0, 34892, 0, + 2660, 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, 32966, 20330, 15538, 0, 4637, 0, 26779, 22107, 11086, 0, + 15448, 32353, 0, 10749, 24464, 40897, 0, 0, 7994, 20959, 0, + 21327, 0, 15677, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 21196, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8648, + 0, 0, 0, 10750, 0, 19, 0, 26845, 0, 0, 0, + 0, 0, 0, 0, 0, 33386, 4487, 13346, 0, 38425, 32607, + 17532, 24868, 0, 0, 26274, 32992, 0, 8974, 20332, 2624, 0, + 7051, 0, 0, 0, 6289, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 15608, 0, 0, 0, 29381, 26854, 0, 0, 0, 25912, + 0, 0, 9357, 0, 0, 0, 10283, 39742, 34867, 29568, 1271, + 0, 20530, 0, 8031, 0, 0, 0, 0, 0, 0, 23946, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 39743, 0, 0, + 27877, 0, 0, 21456, 14784, 0, 34859, 0, 11471, 0, 0, + 0, 1024, 20531, 2997, 0, 0, 0, 18898, 26433, 2081, 38340, + 27656, 0, 41186, 37675, 38054, 19015, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 24792, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 20300, 0, 0, 0, + 0, 0, 40428, 0, 0, 0, 0, 0, 0, 0, 5311, + 0, 37509, 0, 0, 0, 0, 0, 0, 0, 14569, 0, + 0, 11696, 23528, 0, 37929, 0, 19455, 0, 20565, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 22705, 0, 13989, 0, + 0, 0, 0, 0, 34908, 0, 0, 0, 0, 0, 0, + 3636, 21347, 27887, 0, 0, 0, 0, 0, 27405, 0, 0, + 22706, 0, 0, 0, 0, 0, 0, 0, 0, 10123, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34911, + 0, 21168, 0, 0, 0, 0, 0, 0, 0, 27128, 0, + 37516, 0, 2214, 13737, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 33055, 0, 0, 0, 34422, 32667, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 33064, 17270, + 0, 7355, 0, 0, 0, 0, 0, 0, 0, 0, 40350, + 0, 20921, 0, 40411, 0, 0, 15910, 0, 0, 0, 19128, + 0, 0, 0, 0, 0, 0, 0, 0, 23577, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 30292, 0, 0, + 0, 0, 0, 0, 27302, 0, 3390, 0, 35619, 0, 0, + 0, 0, 10244, 0, 13505, 0, 0, 11719, 0, 32743, 4368, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 12497, 0, 0, 0, 0, 0, 0, + 0, 21271, 0, 21274, 29150, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 14628, 0, 20513, 0, 0, + 0, 0, 16873, 0, 39958, 0, 33642, 0, 24476, 8011, 0, + 1727, 0, 0, 0, 12555, 0, 0, 23290, 31822, 0, 0, + 0, 0, 0, 5485, 7088, 0, 0, 0, 0, 0, 27289, + 29628, 32715, 0, 22542, 0, 0, 0, 0, 0, 0, 0, + 0, 5152, 0, 12397, 0, 0, 0, 0, 0, 0, 0, + 0, 32784, 0, 0, 0, 4581, 0, 0, 0, 1678, 25464, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 20261, 0, 0, 0, 0, 20262, + 0, 27214, 32694, 754, 30225, 0, 22208, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 8327, 0, 10830, 10538, 0, 40185, + 9314, 0, 0, 0, 9628, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5023, 0, 0, 1684, 11554, 0, + 0, 2539, 0, 0, 0, 32026, 14465, 0, 35021, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7643, 38202, 0, 0, 0, 7704, 0, 0, 0, 0, + 0, 0, 14400, 37253, 0, 0, 0, 0, 0, 11871, 0, + 0, 0, 0, 0, 0, 0, 0, 13656, 33352, 0, 20957, + 0, 0, 0, 0, 0, 21772, 0, 26780, 0, 37274, 0, + 0, 11323, 8838, 30347, 0, 30095, 23996, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 36265, 0, 12719, 0, 0, 0, 0, 0, 0, 28345, + 0, 13679, 31520, 31016, 0, 0, 0, 19507, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 34783, 0, + 34948, 0, 0, 0, 0, 19510, 21919, 0, 0, 184, 0, + 0, 0, 18566, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6967, 40847, 0, 0, 0, 0, 6968, 0, + 228, 0, 0, 0, 0, 12017, 0, 2473, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 33358, 12591, 0, 41255, 0, 23323, 0, 0, 0, 0, + 39287, 0, 0, 0, 0, 0, 12183, 23191, 14738, 21646, 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, 26041, 0, 0, 0, 0, 0, 10493, + 25494, 24310, 0, 0, 0, 0, 14447, 0, 0, 17271, 0, + 0, 0, 0, 0, 26952, 0, 0, 21357, 32226, 7902, 0, + 0, 25604, 0, 0, 0, 33366, 9681, 0, 12656, 0, 19964, + 7904, 0, 25847, 37436, 13551, 19985, 18439, 23936, 0, 20067, 0, + 0, 35538, 0, 0, 9955, 21363, 16631, 26079, 0, 0, 17953, + 0, 37217, 0, 0, 0, 0, 0, 0, 21848, 0, 0, + 0, 0, 0, 31328, 0, 0, 0, 1435, 0, 0, 1436, + 33739, 0, 12875, 0, 0, 1438, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5437, 0, 0, 0, 0, 40387, 0, + 0, 0, 25488, 0, 0, 0, 0, 27468, 0, 0, 0, + 0, 0, 0, 0, 12684, 0, 0, 11685, 0, 0, 38574, + 0, 0, 0, 535, 17762, 0, 32796, 0, 0, 0, 0, + 0, 0, 0, 12982, 27168, 0, 0, 0, 0, 15325, 0, + 0, 0, 9350, 19018, 0, 0, 0, 0, 0, 21773, 2932, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 17577, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 20963, 25600, 0, 0, 0, 39744, 0, 0, + 0, 0, 0, 0, 0, 2371, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17210, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 16358, 0, 0, 0, 2673, 0, 30429, + 0, 0, 17075, 0, 0, 31307, 22177, 36869, 0, 8367, 0, + 0, 0, 138, 33370, 27522, 25685, 0, 0, 0, 0, 0, + 603, 36725, 0, 0, 0, 0, 0, 0, 0, 0, 11959, + 0, 0, 11598, 0, 0, 41286, 32588, 0, 20189, 0, 0, + 0, 0, 8299, 37617, 0, 2040, 3037, 29937, 0, 2041, 0, + 0, 0, 0, 0, 8300, 0, 29356, 20846, 0, 0, 0, + 0, 10933, 21534, 0, 0, 0, 0, 11679, 18549, 0, 29096, + 0, 24106, 24055, 39939, 0, 0, 0, 5537, 0, 0, 0, + 17900, 0, 0, 24982, 40397, 0, 16711, 0, 32923, 0, 0, + 25265, 0, 0, 5243, 0, 6320, 21386, 0, 0, 0, 26967, + 0, 0, 32144, 0, 0, 0, 0, 0, 0, 39452, 0, + 0, 0, 68, 4345, 23061, 0, 26971, 0, 0, 0, 24687, + 27304, 5727, 0, 32722, 27525, 0, 11312, 0, 0, 0, 35401, + 14702, 0, 0, 39550, 0, 0, 0, 0, 0, 0, 0, + 38863, 0, 0, 0, 0, 0, 0, 33617, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 18477, 0, 40293, + 0, 28331, 0, 0, 0, 5952, 0, 0, 24770, 0, 15441, + 10845, 14401, 0, 24402, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1751, 0, 0, 0, 0, 0, + 0, 0, 29177, 0, 14884, 0, 0, 24621, 0, 0, 0, + 0, 0, 0, 0, 0, 13298, 0, 0, 0, 0, 0, + 0, 37911, 0, 0, 19789, 22455, 0, 24784, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 20137, 0, 0, + 29183, 0, 0, 15174, 0, 1140, 0, 24718, 0, 0, 0, + 0, 0, 0, 0, 0, 29363, 0, 4022, 0, 0, 0, + 0, 0, 0, 14501, 0, 31563, 0, 0, 0, 17967, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3557, 12223, 0, 0, 0, 0, 0, 18621, 0, + 0, 0, 17329, 0, 0, 0, 0, 0, 14820, 0, 0, + 0, 0, 0, 0, 40126, 18696, 0, 0, 0, 0, 0, + 0, 0, 21499, 0, 0, 0, 0, 0, 24928, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 34228, 0, 6881, 0, 11040, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 19475, 0, 0, + 0, 0, 0, 0, 0, 0, 31312, 0, 0, 2491, 0, + 0, 0, 0, 24204, 13617, 10618, 0, 5083, 7054, 38301, 11049, + 263, 13785, 8149, 36664, 0, 7693, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 20787, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 25995, 4549, 0, 0, + 0, 15249, 0, 0, 0, 0, 0, 0, 35061, 70, 723, + 0, 22950, 0, 26972, 7317, 0, 14458, 22490, 0, 30778, 15633, + 24131, 8377, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 15857, 28178, 1003, 12692, + 34240, 0, 0, 0, 15231, 21500, 0, 33254, 0, 31790, 0, + 17957, 6719, 0, 2765, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 27031, 0, 0, 6560, 0, 13224, 37141, 18704, 7056, 0, + 0, 9138, 0, 30672, 3051, 11392, 1649, 0, 0, 10058, 29903, + 20882, 23411, 0, 29684, 37481, 30448, 0, 31192, 8609, 0, 0, + 15511, 0, 35421, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 32589, 0, 9586, 34246, 28183, 27818, + 0, 40604, 0, 0, 29733, 32250, 0, 0, 0, 0, 38306, + 17123, 0, 0, 40294, 0, 13649, 0, 0, 29172, 0, 0, + 32846, 24457, 0, 34250, 14403, 0, 0, 36141, 39465, 0, 15208, + 40721, 0, 15354, 0, 21513, 23939, 30337, 38238, 0, 14404, 0, + 40865, 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, 34251, 0, 0, 17879, 0, 23264, 0, + 0, 0, 0, 11674, 0, 0, 0, 0, 23485, 0, 34772, + 28187, 0, 23417, 9515, 0, 0, 0, 0, 0, 0, 0, + 0, 24328, 6815, 0, 41292, 0, 0, 38308, 23486, 12311, 0, + 30096, 5966, 0, 11743, 19570, 0, 33567, 0, 0, 10751, 34494, + 32481, 4488, 10924, 0, 0, 224, 0, 1778, 0, 0, 0, + 0, 0, 0, 0, 0, 6727, 0, 0, 0, 0, 0, + 0, 0, 0, 40245, 5967, 36689, 23421, 26932, 33997, 36690, 15191, + 24082, 0, 0, 23899, 22303, 0, 0, 24951, 0, 36407, 0, + 0, 0, 0, 0, 26105, 0, 0, 0, 28904, 0, 10720, + 22577, 34949, 0, 0, 0, 0, 29790, 2625, 0, 32030, 23291, + 0, 24477, 0, 0, 13961, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 39088, 0, 0, 0, 40151, 0, 31522, + 0, 30997, 39932, 0, 0, 0, 28194, 0, 0, 15368, 16134, + 15289, 0, 0, 2998, 1272, 20637, 40329, 10094, 37180, 35481, 19254, + 0, 0, 23509, 9728, 19442, 17658, 17888, 41059, 16742, 11097, 4169, + 23510, 16674, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3426, 0, 22936, 5989, 0, + 0, 0, 0, 0, 16743, 0, 0, 0, 35586, 0, 0, + 0, 0, 5819, 0, 0, 6610, 8555, 10873, 0, 32640, 8293, + 22336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 26677, 0, 0, 0, 0, 30613, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6572, 3001, + 36226, 15773, 15664, 0, 41191, 9189, 0, 0, 37930, 39789, 0, + 0, 12618, 3272, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 33031, 0, 0, 0, 0, 41167, 186, 10201, + 0, 0, 22960, 0, 5580, 35244, 0, 0, 0, 21090, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 13729, 713, 16416, + 2340, 0, 1331, 0, 0, 0, 0, 38669, 23539, 0, 0, + 0, 0, 0, 21091, 0, 0, 18950, 0, 15877, 0, 20546, + 0, 16755, 22202, 0, 0, 0, 0, 0, 17250, 2482, 0, + 5324, 16756, 0, 0, 7014, 0, 1072, 14964, 0, 0, 0, + 0, 0, 0, 0, 0, 33818, 21578, 0, 9918, 0, 0, + 0, 0, 0, 32289, 0, 13067, 20047, 21584, 0, 0, 0, + 0, 0, 0, 0, 0, 2341, 27836, 38356, 36001, 0, 0, + 0, 3736, 0, 2344, 0, 0, 0, 0, 16771, 21865, 17330, + 0, 0, 16989, 19129, 0, 0, 0, 28869, 0, 0, 21602, + 21603, 0, 12247, 0, 16777, 0, 21056, 0, 0, 17930, 18151, + 0, 0, 32241, 37460, 0, 38006, 24997, 17760, 0, 0, 0, + 0, 0, 37223, 11451, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 21103, 0, 34108, 0, 14472, 11998, 0, 35786, 0, + 0, 0, 0, 0, 0, 0, 0, 31626, 26053, 13496, 36592, + 0, 0, 0, 0, 0, 0, 0, 26822, 14018, 30391, 35151, + 14242, 0, 0, 8936, 0, 0, 0, 0, 11600, 0, 0, + 0, 0, 0, 0, 0, 0, 7122, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10045, 0, 0, 0, 0, + 0, 0, 7960, 0, 0, 0, 7973, 40613, 12123, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 669, + 0, 0, 23219, 26963, 0, 5882, 22269, 32242, 25851, 0, 0, + 0, 0, 2889, 37667, 0, 8876, 0, 31137, 0, 7557, 0, + 0, 2760, 0, 21186, 14828, 0, 38849, 0, 23734, 0, 0, + 332, 0, 0, 0, 0, 30460, 39880, 0, 11452, 0, 2099, + 40237, 1175, 2971, 39235, 7923, 15580, 0, 41238, 33846, 0, 8153, + 0, 0, 0, 35013, 0, 0, 1831, 0, 881, 32830, 27032, + 35403, 0, 10632, 4750, 0, 35699, 40379, 0, 0, 0, 0, + 3579, 0, 0, 0, 0, 0, 0, 22911, 0, 0, 0, + 36125, 0, 0, 0, 0, 0, 0, 0, 0, 37637, 0, + 0, 0, 0, 14190, 0, 0, 19630, 23844, 0, 35730, 0, + 0, 0, 31193, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 844, 11999, 4554, 15545, 0, 0, 0, + 0, 28452, 0, 10067, 23847, 0, 0, 0, 39466, 0, 0, + 0, 0, 0, 26002, 0, 0, 23659, 9818, 0, 0, 9695, + 0, 0, 12876, 39900, 20241, 9597, 27071, 20713, 6937, 463, 16185, + 0, 0, 0, 40084, 0, 12312, 0, 0, 0, 0, 0, + 38181, 0, 0, 0, 38380, 35788, 0, 9026, 0, 0, 9527, + 36322, 26188, 10394, 700, 20629, 19855, 0, 0, 31359, 5051, 0, + 0, 14219, 0, 0, 0, 0, 10088, 0, 0, 29569, 15583, + 16905, 39745, 11770, 38071, 0, 5886, 4642, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 39746, 0, 15726, 0, 32549, 11229, + 17670, 4779, 24013, 13458, 0, 33512, 7149, 0, 30056, 28672, 39764, + 0, 0, 0, 0, 0, 0, 21128, 19670, 5702, 2476, 0, + 0, 13469, 17444, 0, 26124, 5205, 0, 0, 28214, 17445, 9848, + 0, 0, 1598, 0, 4465, 5823, 18942, 21287, 34541, 16350, 0, + 0, 8363, 3930, 0, 0, 0, 1348, 41077, 11827, 0, 16289, + 32221, 7678, 10497, 0, 0, 0, 0, 0, 0, 0, 0, + 35104, 38681, 0, 21171, 0, 19176, 0, 37611, 0, 21206, 0, + 0, 0, 0, 0, 0, 25281, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8692, 0, 13012, 22874, 0, 0, 0, 1675, 0, + 0, 13160, 0, 0, 1815, 0, 0, 0, 0, 0, 20108, + 11034, 0, 0, 0, 5881, 0, 36678, 34886, 1000, 0, 3148, + 12102, 0, 34887, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9352, 34607, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3556, 0, 26141, 34460, 35631, 35632, 3070, + 0, 0, 10049, 11450, 0, 0, 0, 0, 27528, 28177, 25268, + 28646, 39538, 0, 7311, 7779, 0, 0, 0, 0, 28647, 0, + 19995, 22491, 2100, 20871, 29249, 435, 35672, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 34468, 0, 29350, 0, 34919, 26662, + 15342, 29586, 0, 33826, 0, 0, 0, 0, 0, 0, 0, + 36884, 0, 541, 0, 0, 0, 31953, 18882, 16103, 38121, 24598, + 0, 0, 4632, 41141, 18544, 0, 31954, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 26597, 0, 0, 23064, 0, + 14035, 23895, 35756, 0, 21514, 6526, 0, 13658, 28188, 38700, 4594, + 0, 0, 1010, 9353, 26517, 0, 13951, 5663, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 5097, 0, 20945, 0, + 21758, 0, 12300, 34369, 0, 21776, 0, 6445, 30792, 22650, 0, + 0, 0, 10925, 0, 12832, 35191, 15049, 16334, 16186, 36079, 0, + 0, 0, 29905, 0, 0, 0, 0, 0, 0, 0, 21115, + 0, 0, 0, 0, 41102, 0, 0, 0, 0, 19297, 27640, + 39722, 0, 0, 11616, 40519, 0, 11756, 0, 0, 0, 0, + 0, 3910, 0, 3090, 0, 0, 33389, 16337, 0, 4499, 26718, + 20638, 35329, 34957, 31741, 41160, 1812, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 37046, 0, 18751, 0, 0, 0, + 0, 29915, 30719, 0, 7620, 26678, 0, 0, 0, 0, 0, + 0, 0, 0, 17671, 0, 0, 0, 0, 0, 0, 27317, + 5153, 14739, 37072, 33189, 34977, 27948, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 11968, 0, 23697, 0, 0, 0, 0, + 0, 19262, 0, 0, 15160, 0, 0, 0, 18675, 0, 36702, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32407, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31235, + 0, 36240, 31638, 0, 0, 38532, 33080, 0, 0, 0, 24829, + 0, 0, 0, 16991, 0, 0, 0, 0, 23724, 0, 0, + 0, 0, 0, 0, 18152, 19004, 0, 0, 0, 0, 2649, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 39330, 0, 34370, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 36252, 15918, 0, 0, 0, 24681, 0, 7916, 0, 37226, + 0, 0, 0, 0, 0, 23231, 0, 0, 0, 0, 23467, + 12499, 37479, 0, 0, 0, 0, 0, 8610, 14756, 0, 23248, + 0, 8328, 0, 25017, 0, 0, 0, 0, 30793, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39747, + 0, 0, 0, 13021, 0, 27755, 0, 0, 35910, 23694, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 17073, 0, + 0, 38119, 35648, 0, 2179, 35649, 8633, 0, 5943, 0, 39378, + 35702, 0, 38013, 5033, 0, 27993, 0, 0, 0, 0, 0, + 13730, 3228, 24830, 0, 10044, 32143, 0, 0, 0, 0, 0, + 0, 24919, 13611, 0, 0, 0, 14748, 0, 0, 0, 0, + 5166, 0, 0, 13842, 0, 0, 0, 0, 0, 0, 1748, + 10893, 0, 0, 0, 14829, 0, 36952, 0, 0, 0, 0, + 0, 0, 0, 17021, 23938, 27523, 15634, 0, 39131, 0, 0, + 0, 0, 7924, 26582, 0, 0, 0, 4192, 0, 0, 29587, + 0, 35703, 0, 34761, 0, 0, 30077, 39983, 12281, 0, 0, + 0, 0, 0, 34109, 0, 26665, 33732, 0, 0, 0, 0, + 0, 18212, 37486, 10913, 39332, 0, 0, 22323, 0, 0, 0, + 14865, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 39696, 22651, 37644, 0, 12877, 0, 0, 0, 22145, 0, 0, + 0, 40421, 0, 32183, 0, 1025, 0, 4500, 0, 20639, 0, + 0, 0, 9786, 0, 0, 0, 3354, 24014, 0, 0, 0, + 0, 0, 0, 1317, 0, 0, 23972, 0, 40021, 0, 0, + 0, 0, 0, 0, 7272, 1634, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2000, 25497, 0, 0, 0, 0, + 0, 6084, 24983, 14366, 35002, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 31939, 0, 0, 38175, 0, 0, 0, + 0, 0, 0, 5092, 0, 31266, 30090, 0, 10852, 0, 0, + 0, 0, 31523, 0, 0, 0, 0, 16269, 0, 7435, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 10998, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 32057, 0, 0, 26262, 0, 0, 0, 7490, 0, 0, 4876, + 0, 7961, 0, 3992, 0, 0, 0, 0, 0, 0, 0, + 0, 6120, 16440, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 31742, 0, 0, 0, 0, 0, 1546, 37364, 28215, + 31750, 0, 0, 0, 0, 23027, 0, 0, 0, 0, 0, + 0, 13502, 0, 35634, 0, 0, 30300, 12431, 0, 30307, 29945, + 0, 0, 0, 264, 0, 29228, 3456, 0, 0, 0, 25137, + 0, 25780, 36118, 22426, 4423, 29581, 36199, 0, 0, 8676, 29352, + 39243, 40070, 0, 35404, 15730, 27782, 0, 0, 0, 5652, 0, + 0, 0, 0, 32836, 0, 32591, 9486, 30138, 7707, 31194, 0, + 0, 33433, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 36747, 0, 18032, 34608, 0, 0, 6139, 23487, 28941, 9982, 0, + 3470, 27788, 0, 0, 0, 0, 0, 25004, 0, 0, 10068, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25532, + 23495, 15126, 37007, 2509, 3393, 37277, 0, 1808, 0, 4489, 40146, + 0, 37290, 0, 0, 0, 0, 14885, 18331, 25945, 37300, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 27444, 0, 0, 0, 0, 0, 37648, + 0, 0, 38749, 0, 0, 27445, 0, 3954, 38755, 25872, 32095, + 0, 4716, 19951, 5566, 0, 0, 0, 39748, 367, 0, 0, + 0, 0, 0, 0, 33392, 0, 22671, 0, 13534, 15798, 25795, + 32378, 38509, 5820, 0, 0, 0, 0, 0, 0, 0, 35490, + 0, 0, 11799, 26323, 0, 0, 0, 0, 0, 0, 0, + 0, 3729, 35505, 33033, 39790, 29424, 0, 22838, 32216, 0, 0, + 32110, 28070, 0, 4688, 0, 0, 0, 0, 0, 27833, 0, + 0, 0, 10516, 0, 32413, 0, 36807, 0, 37426, 0, 0, + 28585, 0, 14988, 21057, 0, 5725, 0, 35620, 1155, 0, 0, + 0, 0, 0, 0, 33457, 35636, 25608, 0, 8877, 0, 0, + 35637, 0, 0, 0, 0, 39607, 33106, 0, 12476, 0, 32022, + 0, 0, 0, 38823, 21155, 32939, 0, 0, 0, 35651, 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, 8090, 0, 26522, 0, 37534, 7298, + 0, 7838, 31316, 31422, 10702, 0, 0, 0, 12481, 2946, 0, + 0, 0, 0, 20581, 22276, 0, 0, 20743, 24578, 19621, 0, + 4928, 0, 31942, 26583, 28982, 10625, 1179, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 21267, 0, 24041, 0, 0, 0, 0, 0, 0, 0, 25639, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 13292, 2498, 20081, 0, 0, 35704, + 0, 28293, 0, 31329, 33730, 0, 0, 31670, 0, 35560, 0, + 0, 0, 0, 0, 0, 0, 0, 21069, 0, 0, 30780, + 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, 15233, 0, 0, 18480, 18883, 40469, 0, + 0, 0, 0, 0, 0, 39642, 0, 33297, 0, 8828, 13939, + 32338, 12516, 4877, 0, 16552, 7644, 14613, 0, 0, 0, 0, + 20313, 31955, 0, 0, 0, 0, 27974, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 39643, 0, 11071, 15601, + 0, 28332, 21319, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 28998, 40295, 0, 0, 0, 0, 0, 4940, + 0, 24610, 34252, 0, 32164, 0, 0, 21188, 0, 0, 0, + 39562, 1651, 0, 0, 0, 3741, 16332, 6140, 25117, 32535, 0, + 32704, 30339, 25610, 30504, 21324, 0, 511, 34253, 0, 0, 0, + 0, 0, 27633, 36204, 0, 37257, 0, 0, 0, 0, 0, + 16860, 12000, 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, 692, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 31475, 0, + 14261, 0, 0, 32982, 23664, 21884, 33280, 6695, 12448, 31269, 20745, + 34615, 23496, 20847, 3599, 10753, 0, 25977, 0, 21077, 0, 0, + 3384, 3385, 15976, 0, 12833, 29782, 0, 6349, 0, 0, 31969, + 39959, 12006, 3723, 4946, 0, 0, 19646, 35075, 0, 0, 0, + 0, 0, 14713, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 27074, 0, 0, 36146, 0, 0, + 0, 9157, 31350, 0, 0, 0, 9847, 29179, 0, 10577, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25255, + 0, 35450, 0, 30014, 0, 0, 0, 24478, 9911, 0, 23503, + 0, 0, 12012, 29184, 22456, 0, 0, 8840, 0, 32994, 0, + 20139, 8614, 28408, 32502, 0, 27251, 0, 0, 8012, 0, 0, + 0, 0, 0, 40383, 18332, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 36770, 0, 0, 0, 0, + 3388, 6531, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 16906, 34860, 16907, 0, 0, 18660, 20775, 28201, 91, + 0, 0, 15610, 0, 38965, 92, 29011, 0, 18933, 29910, 1088, + 0, 0, 0, 0, 0, 0, 0, 0, 11771, 11333, 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, 16135, 0, 33136, 0, 0, 0, 25978, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 27384, 25069, + 427, 29955, 0, 0, 0, 8217, 1629, 0, 28863, 0, 32550, + 0, 27658, 1952, 0, 19328, 5312, 0, 9650, 10512, 31565, 5313, + 35879, 0, 1090, 0, 9110, 4780, 26018, 0, 0, 0, 8719, + 37345, 20861, 0, 17195, 39766, 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, 38890, 0, 0, 0, 12169, 25657, 0, 0, 0, 3756, + 0, 0, 0, 0, 0, 0, 0, 0, 13708, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2960, 38973, 0, 0, + 0, 0, 28040, 36568, 0, 0, 23530, 40652, 0, 0, 15179, + 0, 35230, 0, 23531, 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, 33362, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 35338, 3864, 0, 0, 0, 29888, 109, 22777, 0, + 0, 17819, 20204, 110, 0, 20567, 30833, 36521, 21288, 0, 0, + 0, 1978, 0, 18339, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 25715, 0, 0, 0, 0, 0, 0, 0, 18867, 2566, 0, + 0, 4035, 0, 25985, 16952, 0, 27811, 0, 17251, 0, 0, + 0, 0, 31874, 0, 34335, 4839, 0, 18267, 0, 0, 0, + 0, 0, 0, 0, 19894, 0, 38725, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 40486, 0, 0, 20307, 0, 17273, + 0, 14573, 0, 0, 0, 33065, 33066, 18465, 18401, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 29027, 40348, 0, 0, 0, 0, 0, 0, 0, + 2729, 32290, 0, 0, 36449, 22293, 0, 0, 0, 0, 0, + 0, 0, 32913, 0, 13550, 0, 0, 0, 3708, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10327, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 30018, 0, 0, 0, 0, + 0, 0, 0, 10713, 0, 0, 19416, 0, 13885, 0, 24760, + 6250, 24572, 38007, 0, 26730, 38008, 0, 0, 35549, 0, 0, + 0, 0, 11200, 0, 0, 0, 0, 15185, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 37703, 21314, 27627, 0, 31061, 0, 0, 0, 2247, + 0, 12862, 0, 20326, 26448, 0, 25476, 8393, 0, 0, 0, + 0, 23941, 0, 27285, 40620, 0, 0, 0, 0, 0, 0, + 26846, 0, 29180, 0, 0, 0, 0, 38427, 38591, 0, 0, + 0, 0, 0, 7662, 20333, 0, 38313, 0, 0, 0, 39749, + 23680, 10095, 8711, 0, 0, 0, 0, 0, 0, 2255, 0, + 9788, 13359, 0, 36561, 308, 0, 0, 0, 0, 0, 0, + 38435, 0, 31842, 0, 0, 0, 33513, 31283, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 14940, 12181, + 0, 3637, 0, 30378, 0, 20345, 38322, 0, 0, 0, 0, + 13751, 26953, 0, 31639, 0, 7025, 0, 0, 0, 11041, 11045, + 0, 17080, 0, 0, 3972, 0, 0, 35300, 19606, 33462, 39884, + 0, 35676, 0, 0, 0, 0, 0, 0, 17647, 0, 0, + 0, 0, 12860, 12983, 14461, 0, 0, 40286, 0, 0, 0, + 31261, 0, 0, 0, 0, 0, 0, 15442, 15408, 17159, 1134, + 8694, 0, 33484, 26109, 18062, 15369, 0, 0, 0, 0, 0, + 1953, 1412, 27460, 23351, 26354, 0, 0, 0, 12082, 0, 24078, + 0, 0, 0, 0, 0, 35638, 14824, 38783, 0, 33163, 0, + 0, 0, 0, 30029, 9896, 32023, 0, 30064, 35371, 0, 0, + 0, 0, 0, 0, 4630, 0, 0, 0, 13219, 20975, 0, + 0, 22400, 0, 13624, 33900, 10896, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 36815, 21798, 35169, 0, 0, 36253, + 0, 15562, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 32578, 32433, 0, 0, 0, 0, 21067, 0, 38802, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 13630, 0, 0, 21800, 26296, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 12752, 0, 0, 0, 0, 40046, 25471, 0, 0, 18705, 25783, + 21808, 0, 1890, 38929, 0, 24293, 0, 4347, 41046, 0, 31062, + 31259, 0, 0, 21488, 0, 0, 0, 32068, 10633, 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, 29556, 13893, 0, 0, + 0, 0, 13650, 10464, 29734, 38941, 22774, 13940, 21026, 0, 0, + 0, 0, 6644, 0, 31455, 32960, 0, 31798, 16553, 6486, 12517, + 2501, 3763, 0, 8504, 0, 0, 0, 0, 0, 32476, 5355, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1479, + 32592, 33121, 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, 37158, 32165, 16861, 23808, 0, 0, + 19754, 0, 23990, 34255, 0, 23573, 24517, 0, 693, 39257, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 38309, 27463, 0, + 0, 25976, 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, 18717, 0, 0, 0, + 32847, 0, 8110, 38557, 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, 38312, + 0, 6497, 0, 5483, 37278, 0, 18927, 0, 30401, 33927, 13434, + 37682, 39698, 30690, 0, 8695, 14554, 0, 34498, 4883, 19647, 0, + 0, 0, 0, 0, 0, 0, 7996, 20, 0, 0, 33743, + 0, 8511, 153, 0, 0, 0, 0, 12315, 0, 0, 0, + 0, 0, 22517, 39572, 0, 0, 21856, 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, 22110, 0, 35451, + 0, 0, 13668, 0, 40732, 0, 12834, 30258, 0, 0, 12835, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2784, 0, 28346, 28347, + 12328, 27826, 0, 29050, 22458, 22934, 0, 0, 0, 0, 0, + 20141, 0, 0, 0, 0, 0, 35198, 0, 24334, 13963, 0, + 0, 14807, 0, 0, 37498, 25631, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 637, 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, + 1693, 0, 0, 0, 30807, 38212, 24168, 27879, 18661, 0, 0, + 0, 5990, 4060, 1275, 40205, 19249, 7517, 22758, 36275, 33873, 0, + 368, 40636, 41060, 0, 0, 1141, 0, 0, 0, 0, 0, + 16531, 0, 29188, 0, 0, 0, 0, 0, 29412, 12900, 0, + 0, 0, 0, 29664, 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, + 6682, 6210, 0, 0, 0, 1441, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 39768, 0, 7621, 0, 0, 0, 15285, 39769, 38526, + 1295, 15799, 0, 641, 14812, 24730, 0, 23183, 16679, 32877, 28773, + 0, 0, 0, 0, 0, 0, 0, 0, 27882, 0, 936, + 0, 0, 0, 0, 0, 0, 0, 0, 34868, 13031, 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, 38213, 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, 40373, + 0, 0, 7260, 0, 26514, 0, 24495, 0, 22992, 0, 29441, + 26125, 37988, 0, 0, 0, 21462, 9341, 4741, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24111, + 0, 6002, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 22775, 4405, 0, 711, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36293, + 0, 0, 0, 32280, 0, 0, 35596, 20303, 6489, 40107, 0, + 15558, 0, 0, 0, 0, 0, 0, 0, 0, 38768, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 18268, 0, 39596, 2807, + 6373, 37600, 0, 0, 28393, 13740, 17252, 8962, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 673, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 9801, 17690, 26689, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 21472, 0, 4702, + 30758, 0, 30059, 0, 0, 27952, 0, 18402, 0, 0, 0, + 0, 0, 32668, 34556, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 24415, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 31640, 0, 37105, 0, 39353, + 33082, 2615, 7680, 0, 9806, 0, 14111, 16449, 32127, 0, 0, + 18119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 16768, 0, 0, 0, 15105, + 32789, 0, 0, 0, 0, 0, 0, 0, 0, 37996, 0, + 0, 0, 0, 0, 0, 0, 9375, 24196, 19231, 35109, 18987, + 28535, 0, 0, 0, 0, 0, 0, 0, 19232, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 466, + 2858, 0, 40694, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 29416, 0, 0, 0, 30293, 18154, 0, 0, 0, 37461, + 23446, 0, 23232, 0, 0, 0, 0, 12490, 1883, 0, 26834, + 8101, 0, 9507, 0, 0, 5767, 0, 10194, 0, 8329, 0, + 23268, 0, 0, 0, 0, 0, 0, 0, 3327, 11745, 0, + 0, 31974, 26936, 39724, 23306, 0, 9914, 0, 0, 13462, 17211, + 0, 17724, 0, 24019, 0, 0, 0, 25806, 0, 23209, 26827, + 0, 0, 13625, 0, 0, 0, 0, 0, 0, 882, 1398, + 402, 15022, 22429, 0, 0, 5137, 0, 0, 28787, 15973, 15636, + 0, 15592, 0, 0, 0, 0, 0, 26835, 26836, 12109, 795, + 0, 0, 0, 15405, 15816, 0, 0, 0, 0, 20430, 0, + 0, 17648, 6905, 8684, 0, 0, 0, 30466, 6688, 0, 0, + 23593, 11161, 0, 10703, 0, 0, 22319, 0, 13510, 0, 0, + 0, 0, 24696, 40862, 40076, 15819, 0, 26092, 0, 12518, 30518, + 23044, 33923, 0, 26419, 0, 0, 0, 0, 0, 16475, 39563, + 29539, 0, 0, 4984, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 34773, 13952, 39564, 0, 0, + 40621, 0, 37978, 2681, 0, 0, 0, 0, 19648, 0, 0, + 0, 15548, 40002, 10853, 22329, 0, 0, 0, 14334, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4318, 20439, 0, + 0, 0, 0, 32758, 0, 6417, 30604, 0, 2253, 37029, 6449, + 15131, 22609, 0, 0, 3341, 0, 0, 0, 4288, 0, 26458, + 34511, 15764, 0, 37672, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23307, + 39280, 0, 15457, 23308, 39584, 18754, 0, 0, 0, 0, 22462, + 21890, 22206, 0, 0, 0, 0, 0, 0, 7472, 0, 0, + 0, 0, 30926, 0, 0, 19862, 0, 0, 0, 0, 0, + 26283, 0, 0, 0, 33360, 0, 6792, 1609, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 36696, 0, 19451, 0, + 17725, 0, 0, 32885, 19022, 24020, 5491, 0, 3359, 3360, 0, + 0, 0, 0, 0, 4332, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2442, 0, 0, 0, 0, 0, 0, + 0, 16687, 38670, 17051, 17455, 25132, 0, 0, 0, 0, 0, + 0, 0, 0, 3191, 0, 3364, 9118, 0, 40989, 3834, 4130, + 0, 0, 0, 0, 0, 0, 0, 16809, 27604, 18952, 0, + 0, 0, 0, 8082, 0, 17291, 0, 25904, 0, 0, 0, + 25862, 0, 0, 0, 25817, 0, 0, 0, 21592, 0, 0, + 41118, 17064, 0, 0, 0, 27334, 0, 0, 8085, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1187, 0, 0, + 0, 5380, 0, 0, 0, 0, 26841, 0, 0, 0, 8464, + 28751, 0, 0, 0, 0, 19452, 0, 0, 16916, 0, 0, + 1318, 0, 0, 0, 22079, 0, 36709, 0, 0, 0, 0, + 14248, 0, 9737, 17646, 0, 0, 31087, 23594, 6260, 0, 17789, + 0, 13424, 0, 17790, 0, 0, 0, 0, 0, 29360, 0, + 0, 9747, 0, 22127, 24007, 0, 5573, 37922, 0, 0, 0, + 0, 0, 0, 0, 16650, 0, 0, 0, 27622, 33112, 0, + 0, 0, 0, 33122, 32531, 19158, 0, 0, 0, 0, 0, + 1012, 29357, 0, 0, 0, 0, 0, 0, 32759, 0, 6234, + 0, 0, 0, 0, 5303, 29502, 40422, 0, 0, 0, 0, + 0, 21923, 0, 31111, 0, 0, 0, 0, 0, 0, 33143, + 25661, 0, 0, 40663, 5320, 0, 0, 0, 4794, 0, 0, + 0, 40676, 0, 0, 0, 0, 0, 4547, 2761, 0, 0, + 0, 0, 34820, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 34479, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 34484, 0, 39195, 0, 0, 0, 0, 0, 0, + 0, 21871, 34617, 0, 0, 0, 0, 0, 0, 7404, 0, + 0, 0, 34512, 37031, 0, 0, 29088, 8205, 976, 0, 34521, + 0, 11625, 0, 0, 0, 0, 0, 11569, 0, 0, 9658, + 34663, 0, 10989, 1563, 0, 0, 0, 0, 0, 0, 28258, + 0, 0, 0, 0, 0, 0, 40856, 12483, 6871, 12519, 15974, + 0, 17627, 0, 0, 0, 12013, 0, 30621, 40565, 0, 0, + 0, 29527, 0, 0, 0, 38023, 36872, 0, 0, 0, 0, + 25312, 0, 0, 0, 20263, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 20872, 0, 0, 29729, 0, + 5087, 0, 14838, 0, 0, 33463, 5516, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 32525, 0, 0, 0, 0, + 0, 0, 33349, 0, 0, 36822, 9291, 0, 0, 31442, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 10462, 0, 0, + 0, 0, 6070, 0, 0, 18592, 0, 33549, 0, 40077, 32340, + 11460, 2502, 26978, 8460, 21870, 213, 0, 0, 0, 32798, 0, + 0, 0, 0, 0, 0, 0, 10262, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 24213, 8835, 26224, 7974, 0, + 0, 0, 0, 0, 0, 0, 38310, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5182, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5770, 26606, + 0, 41100, 0, 0, 0, 0, 0, 0, 0, 0, 1619, + 0, 0, 0, 4200, 39036, 5047, 0, 0, 31067, 24466, 0, + 0, 0, 17882, 0, 11876, 12136, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2363, 0, 0, 0, 0, 20803, 0, 0, 5972, 30795, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1485, 29152, 0, 0, 0, + 29791, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 8859, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3481, 4599, + 29154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 12019, 23175, 25948, 25936, 33833, 270, 20967, 0, 34792, 27258, + 26115, 0, 0, 0, 0, 29547, 0, 0, 0, 0, 0, + 0, 0, 34274, 11564, 0, 0, 0, 1697, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 21968, 2372, 0, 309, 0, 19671, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 19867, 0, 29241, 0, 0, 0, 0, 0, 0, 25937, + 33693, 15240, 0, 0, 0, 0, 0, 0, 0, 16520, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1632, 4569, 0, 0, 32199, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 29973, 0, 0, 0, 0, 37381, + 5217, 36522, 0, 38844, 0, 23131, 0, 0, 0, 0, 0, + 0, 0, 0, 11815, 0, 0, 0, 0, 0, 117, 20569, + 0, 0, 14063, 16359, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 17836, 22738, 0, 2002, + 24513, 0, 0, 1361, 0, 0, 0, 0, 0, 36586, 0, + 0, 0, 0, 0, 17292, 0, 0, 0, 0, 0, 0, + 0, 21593, 0, 5444, 0, 0, 0, 11299, 0, 0, 0, + 37778, 0, 0, 4246, 0, 17368, 0, 38778, 18155, 4280, 0, + 0, 0, 0, 0, 0, 2409, 34037, 0, 0, 0, 14550, + 11862, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 29564, 0, 0, 0, 0, + 0, 0, 0, 21641, 14653, 0, 0, 0, 0, 0, 0, + 0, 2598, 0, 0, 0, 0, 0, 0, 38167, 0, 0, + 0, 0, 37456, 0, 0, 0, 15482, 0, 0, 0, 0, + 0, 0, 15861, 7461, 0, 0, 0, 0, 0, 0, 0, + 37907, 23806, 0, 0, 0, 24942, 0, 0, 0, 22981, 0, + 22267, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8860, + 35826, 19208, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 15789, 0, 33834, 21431, 0, 0, 0, 0, 0, 10966, + 14508, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 35253, 0, 0, 0, 0, 31642, 0, 0, + 37774, 28872, 22815, 6628, 874, 0, 0, 17712, 0, 0, 0, + 0, 0, 0, 0, 36615, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 34150, 0, 0, 13406, + 0, 0, 16102, 0, 39180, 27342, 0, 0, 26916, 0, 0, + 0, 36733, 22029, 32695, 12272, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 23145, 10339, 0, 0, 15563, 0, 0, 0, + 0, 0, 0, 0, 35176, 3576, 0, 0, 0, 0, 0, + 0, 15313, 37704, 0, 0, 30221, 21388, 0, 4375, 0, 35408, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 14371, 0, 0, 0, 0, 0, + 0, 34727, 16851, 0, 4997, 3718, 0, 0, 0, 0, 0, + 35427, 0, 0, 0, 0, 10061, 0, 0, 0, 0, 35311, + 0, 3749, 11072, 40369, 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, 24453, 6767, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 29593, 32072, 0, 0, 0, 0, 0, 7976, 0, 0, + 5800, 31676, 32799, 39196, 24095, 29739, 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, 0, 0, 0, 10072, 15865, + 28301, 0, 27185, 29376, 0, 0, 0, 39080, 0, 0, 21190, + 0, 23813, 36147, 0, 17609, 26154, 40870, 22518, 8547, 0, 0, + 13957, 36763, 0, 26310, 0, 20131, 21966, 0, 10854, 0, 0, + 0, 36899, 0, 19946, 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, 0, 0, 0, 0, 0, 0, 39573, + 0, 0, 1136, 0, 0, 0, 26612, 23498, 32083, 22060, 15287, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 27459, 22519, 0, 38017, 40246, 0, 27872, + 14220, 0, 0, 2688, 7250, 32711, 36214, 10759, 19657, 29792, 0, + 12556, 0, 0, 0, 35470, 0, 37302, 14192, 22217, 0, 32620, + 0, 9030, 0, 0, 9000, 28281, 32267, 40405, 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, 0, 0, 3805, + 0, 0, 0, 0, 0, 23999, 29089, 37848, 0, 0, 26230, + 17802, 0, 39579, 0, 0, 0, 22009, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 14487, 16265, 0, 0, 0, 40844, 0, 24786, + 9176, 14909, 39489, 271, 24336, 22531, 41148, 0, 23768, 0, 4851, + 0, 12339, 29097, 25563, 0, 9889, 34067, 0, 926, 39490, 0, + 6656, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5273, + 0, 0, 0, 0, 25367, 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, 8404, 0, 0, 8535, 28473, 0, + 30167, 34863, 15655, 39750, 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, 12904, 21343, 26631, + 707, 27447, 6240, 0, 23690, 10004, 23576, 8434, 0, 0, 4269, + 2559, 1299, 35334, 7880, 6876, 0, 16566, 10224, 16917, 0, 0, + 0, 0, 28992, 26632, 0, 36168, 0, 0, 12905, 0, 0, + 0, 2560, 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, 21552, 4603, 0, 0, + 35491, 0, 0, 0, 28817, 0, 0, 14788, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3628, + 9031, 0, 0, 13709, 38974, 10953, 19513, 0, 0, 0, 41009, + 27764, 0, 0, 7528, 40771, 40772, 0, 13722, 27668, 0, 4235, + 22220, 0, 0, 0, 35143, 5538, 0, 16684, 33522, 25572, 0, + 21999, 14791, 31854, 35231, 166, 0, 35914, 12922, 0, 0, 27804, + 31074, 0, 26028, 39592, 1095, 40433, 0, 0, 0, 13309, 10292, + 0, 3638, 6660, 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, 1964, + 12372, 4056, 0, 19219, 0, 0, 25689, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 10968, 0, 0, 0, 0, 0, 5218, 0, 0, 10034, + 25087, 26127, 38671, 38279, 4105, 23195, 6008, 0, 38513, 29721, 0, + 0, 4361, 25807, 0, 19115, 0, 0, 12383, 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, 19169, 24281, 0, 0, 0, 24502, 14794, 0, 0, 0, + 112, 13041, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 29205, 30939, 0, 0, 24027, 0, 0, 0, 22020, + 11907, 0, 0, 118, 0, 27601, 17465, 6586, 0, 28510, 13919, + 1349, 34548, 8621, 22724, 37398, 26558, 0, 0, 12938, 0, 10990, + 0, 0, 17831, 0, 1511, 28071, 13386, 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, 40540, + 0, 0, 0, 0, 9953, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6663, 0, 0, 0, 0, 0, 0, 0, + 0, 32935, 19905, 7898, 18829, 28761, 0, 0, 18278, 32119, 25930, + 0, 0, 4609, 40467, 0, 3143, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17556, 0, 0, 0, 16966, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 22413, 30154, 0, 0, 30172, 0, + 17701, 32787, 4219, 11277, 21473, 23716, 17294, 0, 0, 22175, 29400, + 18279, 31237, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 36499, 0, 38452, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 37111, 0, + 32296, 33820, 27461, 31649, 0, 0, 19745, 26074, 17562, 0, 14280, + 16630, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 32680, 41018, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 18292, 0, 38904, 0, + 39009, 0, 16772, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6490, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 13082, 27462, 41259, 24198, 0, 16613, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37442, + 36019, 21303, 0, 0, 2467, 0, 0, 0, 0, 0, 0, + 34701, 0, 25672, 0, 0, 0, 0, 0, 0, 34446, 6031, + 20219, 0, 0, 0, 0, 0, 0, 16722, 0, 30295, 0, + 0, 0, 0, 0, 0, 20863, 0, 0, 0, 0, 0, + 34450, 0, 0, 0, 16782, 0, 0, 26136, 10891, 0, 0, + 31424, 31425, 0, 36816, 9929, 0, 9860, 0, 30180, 33601, 22430, + 28615, 31429, 31430, 1682, 24205, 31431, 36962, 31781, 0, 4443, 23840, + 31914, 0, 0, 30211, 6906, 36823, 33293, 21217, 9970, 1189, 26742, + 0, 0, 38577, 5794, 37142, 0, 21949, 0, 9588, 30467, 23651, + 35428, 0, 0, 41048, 0, 23652, 6094, 15514, 0, 3987, 35312, + 0, 0, 9935, 15794, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5804, 31813, 40734, 18050, 40871, 0, + 37282, 11878, 0, 27703, 15211, 0, 0, 0, 0, 0, 0, + 0, 226, 0, 36837, 12330, 11926, 23575, 10760, 10761, 0, 5806, + 0, 0, 0, 0, 0, 32806, 0, 0, 0, 26539, 26158, + 0, 0, 0, 32869, 34961, 4986, 0, 33004, 3427, 36847, 10321, + 26161, 0, 0, 0, 0, 28567, 0, 40206, 0, 54, 0, + 0, 0, 25072, 38261, 0, 16165, 18571, 4068, 0, 36851, 0, + 0, 0, 0, 0, 0, 0, 29192, 0, 26877, 0, 0, + 0, 0, 0, 0, 0, 0, 32773, 31863, 0, 0, 0, + 0, 0, 12041, 3651, 35955, 0, 0, 0, 0, 27298, 37760, + 2730, 7021, 31643, 31650, 36501, 41088, 37969, 0, 0, 37972, 0, + 0, 0, 0, 0, 0, 0, 28438, 30392, 0, 0, 0, + 33167, 0, 0, 30500, 8092, 0, 0, 0, 0, 18651, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 12980, 0, 0, 34355, 0, 1190, 15486, 9404, 0, 0, + 40716, 0, 0, 0, 0, 0, 15975, 40048, 39647, 0, 0, + 29778, 0, 0, 0, 28454, 0, 3999, 3255, 3386, 40314, 0, + 4985, 0, 0, 0, 0, 0, 0, 0, 0, 1251, 0, + 12814, 0, 0, 35827, 0, 0, 37730, 8517, 0, 0, 0, + 0, 0, 8407, 0, 0, 0, 0, 0, 24022, 0, 0, + 0, 3928, 3931, 1333, 0, 0, 0, 9669, 0, 0, 9200, + 1792, 36298, 40542, 9206, 0, 17332, 0, 0, 0, 0, 0, + 6882, 5002, 0, 0, 0, 0, 0, 2243, 0, 0, 0, + 0, 0, 29162, 6427, 35654, 0, 0, 0, 5936, 0, 21695, + 0, 33954, 21157, 9625, 15311, 0, 0, 4109, 0, 0, 0, + 38416, 36734, 0, 538, 26917, 5791, 21978, 24587, 0, 0, 0, + 33956, 0, 20594, 15344, 36824, 13417, 1891, 0, 0, 0, 0, + 33424, 0, 0, 0, 0, 0, 20084, 19193, 0, 33959, 0, + 6769, 0, 7139, 26220, 0, 15991, 21142, 20234, 17127, 19019, 0, + 5954, 0, 23595, 16789, 0, 19640, 0, 10534, 3083, 39667, 0, + 9150, 4828, 0, 0, 0, 0, 31343, 28978, 0, 0, 31497, + 34899, 30691, 0, 41055, 19295, 37165, 22404, 35794, 24331, 37723, 15014, + 13299, 33644, 1013, 0, 0, 0, 0, 19160, 40496, 0, 0, + 0, 0, 0, 0, 6450, 32544, 0, 0, 11762, 0, 0, + 0, 9167, 15320, 0, 0, 33214, 11896, 1404, 0, 0, 0, + 15458, 15321, 0, 0, 4852, 0, 0, 0, 0, 0, 0, + 18770, 0, 41187, 38160, 13463, 9424, 0, 0, 0, 0, 34321, + 7091, 0, 24388, 0, 0, 5492, 27765, 28217, 17746, 0, 0, + 0, 0, 26328, 0, 1335, 30834, 35248, 0, 38568, 0, 35146, + 5926, 119, 0, 0, 13315, 0, 0, 27953, 0, 11278, 37424, + 0, 0, 25221, 0, 0, 5757, 41119, 570, 0, 24237, 0, + 0, 12699, 0, 22502, 0, 0, 29686, 0, 0, 0, 3793, + 0, 0, 0, 0, 9592, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 12147, 0, 0, 0, 0, 0, 0, + 0, 33970, 0, 5808, 0, 0, 1494, 38030, 29620, 0, 0, + 0, 0, 0, 0, 26284, 0, 9235, 25078, 0, 0, 0, + 0, 0, 0, 9190, 0, 0, 0, 0, 0, 0, 0, + 10969, 15746, 0, 0, 9068, 0, 28057, 0, 3835, 0, 15534, + 0, 6335, 0, 0, 0, 0, 35973, 0, 0, 5409, 23932, + 0, 0, 0, 0, 0, 18433, 0, 16998, 0, 17360, 24370, + 0, 30570, 0, 20702, 0, 0, 0, 0, 23458, 0, 13264, + 32838, 0, 0, 0, 0, 5052, 0, 18514, 0, 0, 0, + 0, 0, 0, 9403, 0, 0, 0, 22244, 0, 0, 22503, + 0, 14762, 0, 853, 14910, 14786, 27098, 0, 0, 0, 0, + 32933, 0, 0, 25684, 14177, 23007, 25850, 0, 0, 0, 0, + 12093, 0, 0, 0, 0, 0, 0, 0, 0, 7564, 884, + 13793, 25760, 0, 22431, 0, 0, 0, 0, 0, 5649, 19556, + 502, 503, 29372, 18013, 26744, 39137, 22435, 31331, 0, 38305, 797, + 0, 0, 0, 0, 0, 0, 18880, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10192, + 6256, 7943, 21218, 0, 0, 0, 8687, 0, 0, 25548, 32254, + 0, 0, 1200, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 19561, 0, 0, 0, 25477, 24614, 0, 0, 0, 1908, + 0, 10195, 21111, 34371, 0, 0, 0, 0, 0, 0, 0, + 22190, 28128, 0, 30161, 0, 24709, 16875, 5433, 0, 13669, 13670, + 9700, 12878, 1231, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 25899, 664, 4261, 0, + 0, 0, 20961, 679, 0, 0, 25412, 12726, 27873, 0, 0, + 0, 5434, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 32086, 38592, 19659, 0, 0, 40744, 0, + 12574, 23310, 0, 0, 0, 0, 25618, 28310, 25483, 31366, 25419, + 25420, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28475, + 0, 27880, 0, 0, 0, 0, 0, 0, 0, 16918, 0, + 0, 4734, 40920, 19817, 31748, 0, 19535, 21553, 0, 28137, 0, + 22261, 0, 0, 1300, 5704, 0, 0, 24799, 24061, 0, 7586, + 28043, 0, 0, 0, 0, 0, 0, 33523, 0, 0, 0, + 25490, 12185, 0, 0, 24811, 17820, 0, 0, 0, 0, 0, + 0, 0, 0, 25983, 0, 0, 16107, 0, 4795, 35254, 1817, + 0, 13742, 0, 24816, 24817, 0, 0, 0, 19895, 25160, 0, + 1711, 3009, 0, 0, 6378, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 25206, 32129, 0, 0, 28969, 24837, 21594, 0, + 0, 27278, 18689, 0, 16109, 0, 0, 0, 0, 0, 20379, + 20431, 0, 0, 0, 5183, 0, 0, 36276, 0, 0, 32776, + 0, 0, 0, 12484, 0, 0, 0, 0, 36057, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7580, 39962, 0, 0, + 0, 9184, 0, 0, 0, 0, 0, 2530, 0, 18206, 0, + 0, 2070, 0, 0, 0, 21975, 27707, 5340, 39128, 0, 0, + 26203, 0, 4063, 0, 14292, 0, 0, 0, 0, 0, 15419, + 3452, 0, 0, 0, 0, 0, 11054, 17089, 26083, 0, 0, + 22028, 30577, 31251, 0, 0, 0, 36394, 0, 0, 0, 0, + 26084, 5512, 0, 0, 5084, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 29725, 10341, 22951, 0, 39547, 21696, + 21311, 0, 0, 0, 0, 0, 25468, 9333, 0, 39455, 0, + 0, 12273, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7318, 0, 0, 13632, 9884, 0, 0, + 0, 38695, 0, 31794, 0, 0, 40713, 0, 0, 31671, 22742, + 0, 0, 960, 0, 12985, 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, 13102, 0, 0, 37975, 0, 0, 0, + 0, 0, 0, 0, 982, 19631, 0, 0, 38203, 40476, 0, + 15839, 0, 0, 1103, 0, 22033, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 19632, 28744, 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, 30013, 19157, 0, 0, 28621, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, + 0, 0, 0, 0, 0, 9986, 40198, 0, 6772, 6773, 8462, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 24518, 0, + 30473, 0, 20610, 39033, 30955, 40477, 0, 13567, 22215, 0, 0, + 0, 0, 0, 0, 0, 27988, 0, 0, 0, 0, 14624, + 0, 0, 23158, 2298, 0, 29861, 26102, 0, 30091, 0, 0, + 11210, 0, 35761, 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, 0, 0, 0, 0, 0, 0, 0, 0, + 20388, 39898, 0, 0, 0, 27583, 0, 0, 0, 35762, 30474, + 289, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 27964, 0, 0, 0, 0, 0, 0, 0, 9600, 30144, 11689, + 0, 0, 33646, 38070, 0, 40841, 1487, 0, 4947, 36069, 25006, + 0, 0, 11271, 20848, 37981, 0, 29075, 0, 0, 0, 0, + 0, 35452, 28629, 26508, 27585, 0, 33267, 0, 0, 36839, 0, + 0, 7611, 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, 15449, 0, 0, 0, 7998, 0, 0, + 0, 0, 0, 0, 20441, 0, 0, 0, 0, 0, 0, + 0, 22604, 0, 12321, 24101, 39934, 8468, 37500, 3483, 0, 0, + 0, 23853, 0, 41249, 0, 32862, 19573, 0, 10935, 0, 22610, + 34122, 0, 31977, 29090, 0, 0, 20903, 4054, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 31272, 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, 11468, 33971, 28979, 0, 24102, + 0, 0, 13352, 0, 0, 0, 0, 0, 0, 0, 0, + 5272, 547, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5307, 15612, 0, 14425, 26117, + 14052, 0, 0, 20534, 21761, 0, 27591, 0, 27388, 40464, 8033, + 0, 0, 38127, 32870, 16532, 29570, 0, 0, 0, 0, 0, + 0, 38967, 0, 0, 2303, 0, 37734, 0, 0, 40091, 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, 28634, 0, 0, 0, 34394, + 18756, 34523, 0, 0, 0, 0, 0, 38256, 27446, 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, 9755, 40208, 0, 25566, 25567, 0, + 0, 15219, 12593, 8557, 0, 0, 0, 33021, 0, 0, 21969, + 12906, 0, 0, 0, 39497, 38436, 0, 10708, 0, 15800, 0, + 1954, 0, 0, 26020, 230, 13148, 0, 29014, 0, 0, 27802, + 0, 19974, 36170, 28635, 9756, 0, 0, 25635, 30813, 0, 0, + 27759, 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, 23521, 0, 38789, 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, 6176, 8055, 26683, 28045, 35920, 17548, 0, 10423, 0, 39114, + 0, 38271, 0, 4742, 4743, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7801, 17049, 15617, 0, 0, 0, 32771, 36855, + 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, 10229, 0, 0, + 0, 0, 0, 10115, 15494, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 37366, 0, 0, 0, 0, 0, 11377, 28319, 0, 16206, + 0, 6302, 13167, 22928, 1450, 0, 0, 0, 0, 33978, 0, + 1508, 0, 0, 0, 0, 30835, 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, 5227, 13743, 560, 0, 21410, 32403, 26043, 0, + 0, 11186, 4050, 0, 0, 21971, 17832, 5586, 2215, 0, 38447, + 0, 18868, 0, 0, 0, 12042, 0, 0, 17255, 36491, 0, + 30749, 1350, 9803, 0, 22631, 0, 0, 1565, 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, + 34549, 0, 0, 0, 40439, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10698, 0, 0, 0, + 17980, 7015, 0, 36236, 16448, 0, 35100, 0, 0, 33892, 17277, + 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, 16450, 18120, 31644, 10607, 0, + 13493, 40681, 0, 0, 0, 39515, 0, 0, 2012, 29003, 204, + 0, 0, 34089, 16765, 38134, 11710, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 31891, 10700, 0, 7356, 13074, 4580, 37997, 0, 2160, 0, 36711, + 0, 0, 6596, 22055, 0, 0, 0, 0, 0, 0, 0, + 0, 28527, 0, 22114, 0, 0, 0, 7223, 31651, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 35110, 19131, 0, 0, + 1425, 0, 14010, 17333, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 34693, 6312, 0, 0, 19467, 0, + 8933, 25226, 2313, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 19826, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9214, 27471, 0, 0, 0, 0, 0, 34448, 1390, 0, 0, + 0, 0, 0, 0, 1589, 3377, 15987, 0, 11972, 0, 0, + 0, 0, 0, 0, 0, 0, 3571, 0, 31080, 0, 4596, + 39613, 0, 0, 0, 0, 0, 0, 27524, 0, 0, 9297, + 23040, 33603, 27624, 0, 31255, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7840, 0, 27023, 0, 0, + 11721, 11454, 21979, 0, 0, 0, 0, 0, 0, 40239, 0, + 35409, 0, 0, 0, 0, 17108, 26266, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 20380, 0, 8638, + 0, 10840, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7049, 7175, 0, 0, 33621, 35429, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 36507, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3468, 0, + 0, 0, 0, 35430, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5557, 11688, 10374, 0, 38461, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37842, + 32078, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32166, + 16617, 26474, 27060, 40617, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1620, 14304, 31049, 13436, 7999, 0, 32443, 15173, 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, 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, 21119, 0, 12014, 12331, 16191, 0, 0, 0, 0, + 7817, 26278, 17742, 20336, 3091, 0, 0, 20527, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 18508, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6779, 0, 0, 21120, 0, 12148, 0, 0, 40324, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 28009, 6780, 0, 0, 0, 14228, + 0, 0, 38031, 11694, 36479, 10941, 17964, 31020, 10100, 0, 0, + 0, 20995, 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, 31832, 0, 8470, 0, 0, 0, 0, 10474, + 12164, 32504, 26118, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 29958, 0, 38838, 27394, 0, + 36852, 12908, 0, 0, 0, 0, 0, 38214, 0, 0, 0, + 0, 0, 0, 0, 38764, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 25750, 0, 0, 0, + 0, 0, 0, 34322, 0, 0, 0, 0, 0, 0, 4781, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 12357, 26381, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6996, 16570, 28732, 0, 40340, 0, 0, 0, 0, 0, + 17947, 0, 38345, 0, 14741, 10881, 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, 26684, 12029, + 0, 0, 0, 16016, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4027, 40104, 0, 0, 0, 280, 0, 40665, 0, + 0, 0, 0, 33234, 0, 20346, 10886, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 28685, 0, 0, 0, 0, 1337, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6082, 0, 0, + 0, 0, 0, 15180, 0, 1566, 0, 0, 0, 0, 12043, + 17833, 4700, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 32404, 25259, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 37761, 0, 34015, 0, 17728, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 26133, 0, 0, 27134, 0, + 0, 0, 33070, 0, 0, 0, 0, 0, 0, 0, 0, + 32677, 0, 0, 0, 35147, 16424, 35991, 0, 0, 0, 0, + 0, 17517, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2013, 2359, 0, 0, 0, 0, 0, 0, 0, 35105, 0, + 0, 0, 0, 0, 0, 0, 0, 17563, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 28536, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 12662, 0, 0, 31657, 39864, + 0, 0, 0, 0, 31659, 0, 0, 37785, 0, 0, 0, + 0, 0, 0, 32310, 0, 40700, 0, 0, 0, 0, 0, + 0, 0, 0, 38780, 0, 0, 0, 0, 0, 41091, 0, + 20839, 0, 0, 0, 0, 0, 0, 5378, 17771, 20841, 0, + 0, 0, 0, 0, 0, 0, 0, 22186, 0, 14603, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 19161, 0, + 0, 27428, 26410, 0, 0, 19162, 0, 7581, 0, 0, 0, + 812, 0, 0, 0, 0, 17196, 0, 0, 33361, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5252, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3398, 0, 0, 0, + 38794, 0, 0, 27933, 0, 0, 26655, 0, 0, 0, 0, + 0, 0, 0, 8761, 0, 0, 0, 0, 0, 36936, 0, + 11626, 3103, 0, 13506, 40290, 27225, 0, 0, 32706, 0, 0, + 0, 21642, 0, 0, 0, 0, 0, 0, 13218, 0, 13220, + 0, 0, 0, 0, 0, 0, 0, 5895, 0, 0, 0, + 0, 0, 23942, 24615, 0, 7712, 0, 0, 0, 0, 0, + 38707, 15357, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5991, 38262, 0, 0, 9468, 26030, 7669, 0, 0, 13278, + 0, 34412, 39812, 0, 0, 0, 17297, 0, 0, 0, 18158, + 0, 0, 0, 35378, 0, 24863, 22057, 8989, 0, 12801, 10349, + 0, 22406, 0, 14604, 0, 3075, 0, 0, 17785, 27049, 22973, + 32532, 0, 22599, 19159, 4634, 0, 37160, 0, 0, 0, 15572, + 32984, 0, 0, 0, 0, 30351, 34503, 22252, 0, 0, 0, + 3331, 0, 0, 0, 0, 29091, 3092, 1255, 17540, 12815, 0, + 29505, 0, 0, 0, 29051, 0, 0, 0, 0, 0, 5998, + 0, 27395, 16919, 18864, 31930, 0, 4722, 0, 0, 0, 1865, + 29917, 23080, 0, 17969, 7670, 0, 1979, 2843, 0, 0, 5253, + 28588, 5406, 0, 0, 17298, 0, 34185, 34188, 38579, 0, 0, + 35441, 0, 23165, 0, 0, 0, 0, 0, 0, 0, 11042, + 0, 29461, 0, 15590, 0, 0, 4249, 36736, 7656, 0, 21849, + 29336, 13935, 22494, 3154, 22596, 0, 13794, 9572, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 40473, 0, 0, 10898, + 3858, 27344, 28890, 22499, 25472, 25473, 0, 10791, 22317, 0, 0, + 0, 0, 0, 0, 543, 0, 31949, 0, 0, 0, 24294, + 21273, 0, 28891, 24885, 0, 0, 32839, 0, 38868, 11143, 33124, + 0, 27159, 0, 0, 29779, 0, 17576, 1214, 3885, 0, 33208, + 0, 33126, 7860, 0, 0, 0, 0, 13807, 0, 0, 0, + 8111, 0, 0, 28989, 26534, 0, 0, 2979, 4188, 0, 0, + 0, 0, 0, 0, 25149, 10795, 1014, 0, 2200, 0, 0, + 0, 0, 20746, 0, 0, 0, 33487, 5973, 0, 0, 2785, + 37038, 39963, 0, 0, 0, 16883, 27162, 0, 0, 0, 0, + 0, 6354, 0, 19550, 11498, 0, 28950, 0, 6451, 29092, 26756, + 19719, 0, 0, 0, 39092, 24264, 22615, 28811, 2332, 34962, 0, + 33443, 667, 9177, 0, 0, 0, 2133, 0, 0, 0, 0, + 0, 0, 9059, 1943, 0, 0, 0, 30984, 0, 0, 12578, + 0, 0, 0, 0, 0, 16166, 0, 0, 4723, 20452, 4628, + 21927, 36563, 0, 0, 0, 0, 19583, 15460, 19471, 6080, 11287, + 6742, 13242, 28033, 0, 0, 0, 0, 2478, 28495, 0, 11516, + 14943, 34080, 0, 0, 33363, 0, 20164, 25131, 16571, 0, 0, + 39813, 30740, 0, 0, 0, 0, 26039, 0, 0, 0, 38133, + 0, 0, 0, 0, 0, 203, 30854, 0, 11279, 0, 0, + 38735, 0, 36374, 8670, 11849, 0, 24986, 0, 0, 0, 0, + 0, 17854, 14541, 495, 16723, 0, 19414, 18159, 0, 0, 17077, + 12426, 0, 0, 0, 11659, 33164, 27008, 38919, 0, 0, 1828, + 0, 0, 0, 2493, 0, 0, 0, 2495, 14022, 398, 877, + 0, 0, 34590, 0, 11055, 0, 36957, 0, 1167, 4089, 0, + 12433, 0, 0, 0, 20790, 0, 19554, 39882, 0, 35171, 6224, + 35154, 0, 0, 0, 25374, 36051, 0, 10255, 0, 20873, 29448, + 8155, 20758, 38024, 0, 10900, 0, 3118, 30074, 0, 0, 3977, + 7932, 0, 0, 0, 0, 0, 0, 0, 794, 0, 0, + 0, 0, 5615, 2190, 18697, 22952, 4931, 35181, 0, 35561, 0, + 0, 0, 32475, 1079, 40134, 0, 35411, 0, 18921, 0, 15818, + 0, 0, 39634, 0, 0, 0, 0, 30212, 5518, 27352, 17772, + 38177, 39635, 21071, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2617, 0, 0, 32595, 38145, 0, 0, 37242, 6275, 2591, + 32840, 34769, 0, 32257, 761, 0, 0, 0, 0, 0, 0, + 0, 0, 38518, 0, 24602, 0, 10906, 38041, 14859, 0, 9933, + 0, 0, 0, 0, 0, 0, 0, 0, 215, 38204, 0, + 0, 26150, 0, 32345, 3535, 34485, 0, 221, 0, 0, 0, + 38953, 14870, 0, 0, 17141, 0, 16656, 0, 0, 2198, 0, + 18721, 0, 12710, 0, 0, 32028, 32760, 34310, 33488, 0, 6648, + 36411, 11612, 29076, 21760, 31732, 0, 0, 29785, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 30251, 3123, + 0, 0, 0, 10581, 0, 29077, 33744, 37982, 0, 0, 0, + 0, 0, 0, 8696, 0, 0, 0, 18502, 2622, 22064, 12332, + 0, 28463, 0, 0, 31527, 0, 0, 32621, 0, 25947, 12728, + 28010, 11469, 0, 4830, 0, 28464, 27434, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 8013, 17179, 0, 26541, 0, 28803, + 0, 0, 0, 0, 0, 0, 5736, 0, 0, 0, 1277, + 0, 9060, 4643, 0, 23684, 0, 0, 16675, 28021, 0, 0, + 40978, 10197, 0, 0, 0, 0, 0, 0, 0, 3618, 2368, + 0, 0, 31106, 32633, 17808, 34319, 0, 0, 0, 0, 0, + 0, 1278, 0, 11425, 0, 31548, 3428, 33515, 21086, 34400, 0, + 33022, 38437, 0, 28207, 0, 31845, 1027, 25154, 27596, 584, 9653, + 15134, 3136, 0, 0, 33684, 0, 0, 0, 0, 0, 0, + 0, 6979, 17197, 31567, 11430, 28034, 0, 2939, 0, 0, 0, + 0, 0, 18772, 34401, 0, 0, 5251, 5155, 34741, 0, 38555, + 14664, 0, 6703, 25951, 16277, 28046, 0, 0, 0, 0, 0, + 0, 38272, 0, 0, 0, 1320, 0, 0, 36294, 0, 10202, + 0, 17821, 0, 0, 10235, 34798, 0, 0, 0, 0, 0, + 27602, 120, 24506, 0, 0, 16758, 32905, 0, 27129, 0, 0, + 0, 0, 0, 0, 18678, 0, 25097, 17472, 0, 0, 0, + 0, 0, 32781, 0, 36368, 0, 0, 32915, 0, 0, 0, + 0, 0, 0, 18127, 36715, 0, 0, 0, 0, 5280, 16432, + 32687, 0, 0, 0, 0, 0, 0, 0, 35861, 0, 0, + 0, 31142, 0, 35655, 30034, 2071, 0, 33168, 0, 0, 27618, + 13845, 0, 399, 7192, 0, 20586, 25737, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4981, 12492, + 0, 0, 0, 0, 27972, 24451, 408, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 29254, 36741, 0, 30080, 0, 30262, 36887, + 0, 6132, 0, 0, 31724, 15564, 0, 0, 0, 24454, 6524, + 6770, 0, 35739, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 31460, 24210, 27977, 0, 0, 18217, 0, + 30316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3053, 40141, + 0, 19641, 0, 0, 0, 0, 0, 0, 24943, 0, 0, + 0, 0, 0, 36934, 0, 35798, 20008, 0, 0, 16262, 39703, + 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, 21235, 0, + 577, 0, 0, 0, 6146, 0, 0, 0, 39704, 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, 35830, 0, 0, 18063, 37040, 4495, 5685, 39726, + 0, 0, 0, 25652, 0, 0, 13133, 0, 0, 0, 0, + 0, 30406, 0, 13974, 0, 22148, 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, 18757, 24787, 0, 31744, 4954, 0, 0, + 0, 0, 11105, 19166, 0, 16660, 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, 8956, 0, 0, 0, 0, 18195, 0, 0, 0, 0, + 0, 0, 16572, 0, 40434, 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, 38185, 10293, 32554, 0, + 0, 10296, 17233, 0, 0, 5828, 8736, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 11348, 0, 0, 0, 0, + 0, 0, 7003, 0, 31999, 0, 0, 0, 0, 12940, 23354, + 32004, 36861, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 39298, 0, + 0, 0, 0, 0, 0, 0, 0, 40441, 0, 0, 0, + 2845, 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, 33085, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 21099, 0, 0, 0, 0, + 0, 0, 0, 12663, 29291, 0, 0, 0, 0, 34585, 0, + 0, 0, 10246, 33156, 18160, 0, 571, 1033, 0, 0, 0, + 0, 8991, 18020, 0, 0, 16122, 23599, 13519, 0, 7050, 34941, + 6327, 0, 0, 0, 0, 0, 11977, 6418, 22239, 0, 0, + 0, 0, 0, 0, 0, 0, 37580, 0, 0, 18524, 33276, + 0, 0, 17437, 34972, 31568, 34978, 0, 31616, 0, 0, 18629, + 0, 34688, 0, 0, 24988, 0, 0, 0, 0, 25216, 30224, + 41042, 7319, 35683, 6430, 28179, 0, 22436, 0, 9972, 0, 33612, + 0, 8947, 0, 5655, 0, 20883, 0, 0, 0, 0, 0, + 0, 6774, 30189, 0, 0, 21516, 0, 0, 0, 0, 0, + 5901, 11463, 0, 0, 29078, 7338, 0, 0, 0, 31205, 255, + 0, 22868, 0, 0, 0, 0, 9994, 0, 8516, 16884, 0, + 6606, 8199, 20904, 0, 2449, 0, 0, 0, 0, 13588, 0, + 24424, 0, 36328, 32489, 0, 0, 0, 0, 10942, 0, 0, + 28022, 0, 0, 0, 0, 0, 0, 8658, 6980, 33685, 0, + 0, 0, 0, 0, 0, 0, 0, 31590, 0, 0, 0, + 15270, 9797, 13595, 4102, 16689, 10555, 41210, 0, 0, 0, 0, + 22771, 0, 0, 5466, 31617, 16692, 0, 26339, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 18630, 0, 6597, 15106, + 0, 0, 2852, 0, 32918, 30209, 39010, 0, 40399, 0, 0, + 0, 18352, 16725, 0, 0, 0, 5019, 8380, 0, 0, 0, + 0, 0, 0, 27040, 0, 0, 34514, 0, 0, 0, 0, + 8410, 0, 0, 0, 34432, 0, 0, 0, 0, 0, 28118, + 0, 0, 0, 39891, 0, 27041, 0, 0, 0, 0, 26798, + 0, 0, 0, 2775, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11524, + 36295, 0, 0, 19959, 0, 0, 0, 0, 0, 0, 25209, + 0, 0, 32471, 0, 0, 906, 0, 0, 0, 4100, 0, + 0, 0, 0, 23099, 0, 0, 0, 0, 0, 0, 0, + 15337, 16156, 0, 0, 25000, 0, 10185, 3577, 19484, 0, 0, + 0, 0, 38488, 0, 0, 0, 7657, 0, 3034, 0, 0, + 0, 0, 0, 0, 14092, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 17773, 0, + 20878, 20879, 29589, 0, 0, 0, 25139, 41099, 22442, 36829, 0, + 27231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17786, 27160, 29887, 0, 8577, 26449, 30082, 0, 20985, 0, 0, + 0, 30141, 8897, 5902, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 19944, 660, 0, 32850, 27738, 29540, 9633, 0, + 0, 8000, 9636, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9637, 0, 0, 0, 0, 0, 0, 0, 40250, + 0, 16266, 0, 19083, 29312, 25187, 0, 0, 6148, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14777, 34390, 0, 0, 25632, 5149, 0, 0, 19663, 0, 0, + 0, 0, 0, 18976, 0, 33686, 0, 31569, 0, 0, 0, + 0, 0, 0, 0, 19258, 23185, 0, 2596, 0, 0, 26383, + 10116, 22887, 0, 0, 0, 12188, 0, 0, 0, 0, 17235, + 0, 37382, 594, 0, 29001, 0, 0, 0, 0, 3828, 0, + 0, 3829, 0, 0, 0, 23202, 31618, 948, 0, 0, 0, + 35264, 0, 0, 9480, 0, 40349, 0, 0, 0, 16702, 16703, + 2527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9482, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6034, 0, 0, 0, 0, 0, 34210, 0, 0, + 0, 0, 21502, 27247, 0, 39705, 0, 0, 0, 39794, 0, + 0, 39795, 22587, 0, 14247, 14249, 35656, 36873, 0, 14250, 0, + 0, 0, 0, 11385, 0, 6431, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 28934, 24143, 24238, 33170, 2654, 12503, 0, + 24325, 0, 0, 0, 0, 0, 0, 0, 6435, 39381, 0, + 0, 21948, 0, 31332, 0, 30915, 0, 0, 0, 0, 0, + 1203, 0, 0, 842, 0, 20766, 13946, 28937, 17649, 0, 0, + 0, 0, 2361, 38420, 0, 0, 0, 0, 0, 3527, 34160, + 15922, 36258, 0, 0, 0, 0, 0, 0, 0, 0, 18372, + 23600, 0, 10150, 26408, 9906, 2505, 0, 13425, 16599, 0, 0, + 0, 0, 0, 0, 31485, 0, 0, 1913, 0, 0, 0, + 0, 0, 0, 0, 39565, 0, 30021, 8001, 0, 10855, 0, + 21529, 35799, 40480, 0, 0, 0, 2547, 0, 0, 0, 28097, + 0, 0, 37915, 0, 0, 0, 0, 0, 0, 6447, 0, + 31502, 4123, 33268, 13437, 26613, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 30437, 849, 7453, 13134, 24960, 35832, + 6149, 33659, 20905, 12333, 0, 0, 39155, 23293, 6533, 36153, 0, + 14338, 22527, 33183, 19071, 2202, 18192, 1622, 5390, 5435, 0, 0, + 0, 0, 0, 16236, 0, 31528, 14635, 0, 32712, 0, 14048, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 30265, 0, 21125, 32449, + 25073, 24170, 29749, 33573, 11774, 0, 0, 0, 20406, 30713, 0, + 36779, 29911, 5056, 0, 0, 0, 15414, 20913, 0, 8206, 37323, + 39586, 0, 9943, 23, 8207, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 34737, 0, 0, 26943, 0, 2694, 0, 0, + 0, 3630, 37924, 27437, 0, 28035, 25923, 0, 6981, 39319, 39, + 28358, 2137, 0, 25129, 35887, 34533, 0, 20915, 31285, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 17198, 17199, 0, + 31572, 14926, 26869, 0, 34222, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3186, 36422, 1321, 3104, 0, + 0, 38398, 30152, 11107, 29017, 36518, 1148, 21647, 17549, 33190, 37192, + 0, 0, 0, 0, 0, 0, 0, 943, 0, 20540, 6538, + 0, 5365, 23334, 0, 0, 0, 0, 0, 0, 0, 27438, + 0, 0, 32655, 39941, 40537, 0, 1509, 0, 30741, 31606, 0, + 5463, 0, 32811, 22051, 21565, 0, 0, 1661, 26557, 7532, 20454, + 23540, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 26334, 28366, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12384, + 0, 0, 5160, 14798, 18818, 0, 379, 0, 0, 0, 35957, + 27325, 28238, 30841, 30326, 3962, 0, 0, 0, 0, 31124, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1362, 0, 36237, + 11969, 0, 0, 15182, 21656, 0, 0, 0, 0, 126, 0, + 17280, 0, 38529, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 18840, 0, 0, 0, 0, 1514, 22085, 0, 0, + 0, 0, 0, 0, 0, 9678, 27957, 19920, 32297, 18487, 0, + 23553, 0, 0, 0, 0, 0, 2853, 36014, 10183, 0, 17520, + 9441, 0, 30768, 0, 0, 0, 0, 14992, 16718, 18995, 17363, + 0, 22559, 0, 0, 0, 0, 0, 11380, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 9516, 0, 0, + 0, 0, 14490, 0, 0, 5457, 0, 0, 0, 7529, 0, + 0, 0, 0, 0, 0, 39367, 0, 19773, 0, 11386, 0, + 0, 0, 21981, 1122, 0, 22912, 0, 0, 0, 0, 0, + 0, 7073, 0, 11390, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2950, 0, 19198, 7828, 0, + 0, 0, 0, 0, 0, 0, 0, 3801, 0, 41056, 20991, + 32727, 0, 0, 0, 0, 0, 548, 18739, 0, 19209, 0, + 0, 21427, 38248, 0, 0, 0, 40325, 10938, 0, 0, 11628, + 28862, 3813, 0, 0, 0, 0, 0, 0, 11504, 6236, 0, + 0, 0, 0, 0, 0, 0, 0, 20317, 0, 1965, 0, + 0, 5714, 0, 5480, 23051, 0, 27808, 3830, 0, 0, 0, + 0, 35102, 19960, 18404, 0, 0, 0, 0, 17473, 0, 0, + 1667, 0, 0, 0, 0, 18913, 0, 0, 0, 0, 26064, + 41260, 0, 0, 0, 4821, 18162, 39309, 22569, 737, 0, 0, + 25042, 0, 0, 22437, 21025, 22438, 2033, 888, 7156, 0, 20435, + 20601, 30226, 38832, 39649, 4614, 0, 0, 0, 0, 34051, 12304, + 9634, 0, 3317, 0, 0, 0, 10083, 32761, 25056, 0, 4319, + 0, 8114, 0, 0, 0, 0, 0, 24303, 18740, 25064, 5775, + 23672, 0, 0, 0, 0, 2935, 28465, 855, 0, 0, 6454, + 1043, 10812, 0, 0, 0, 0, 38466, 38467, 0, 0, 0, + 0, 25079, 19259, 10006, 0, 0, 18243, 18792, 0, 40774, 0, + 22584, 40105, 0, 38162, 0, 21712, 0, 0, 11819, 0, 0, + 33936, 0, 16208, 0, 0, 0, 0, 0, 21763, 34557, 25196, + 21137, 0, 16218, 9481, 6385, 0, 0, 18632, 0, 0, 0, + 13086, 33094, 23559, 0, 0, 32570, 0, 0, 9816, 13634, 19547, + 0, 0, 31916, 15899, 0, 0, 0, 0, 0, 0, 36667, + 0, 9886, 20121, 35070, 0, 0, 30886, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17145, 14764, 31154, 24045, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5909, 4001, + 0, 0, 28302, 0, 0, 3682, 0, 0, 24912, 26543, 0, + 0, 0, 0, 0, 0, 0, 0, 19948, 14644, 0, 0, + 0, 0, 0, 0, 0, 29811, 0, 0, 0, 0, 0, + 0, 21728, 20541, 0, 0, 0, 0, 0, 7671, 0, 0, + 0, 0, 0, 0, 0, 0, 312, 9759, 10970, 2268, 6617, + 9892, 13479, 0, 0, 0, 0, 0, 0, 0, 9117, 0, + 0, 0, 0, 13872, 0, 0, 34802, 0, 0, 0, 0, + 0, 0, 0, 2600, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 11652, 0, 0, 0, 0, 0, 0, + 0, 24838, 15394, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 24371, 36029, 0, 0, 15165, 13404, 0, 0, 3761, 2072, + 8791, 13331, 39368, 0, 0, 30976, 0, 1681, 0, 0, 0, + 33348, 7320, 0, 0, 35387, 4120, 35063, 0, 0, 34726, 6432, + 34469, 0, 19845, 0, 0, 0, 0, 0, 3403, 20794, 13338, + 0, 21821, 0, 9778, 33957, 0, 0, 7950, 33902, 7846, 22280, + 20597, 31444, 31086, 26267, 0, 0, 31445, 23469, 20265, 0, 0, + 0, 0, 0, 0, 0, 0, 5140, 0, 3860, 0, 0, + 0, 0, 0, 0, 0, 0, 7502, 20324, 0, 33960, 33623, + 27630, 14553, 19610, 799, 0, 35433, 9256, 21321, 0, 35434, 0, + 41288, 0, 0, 21802, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5796, 7326, 35741, 27053, 0, 0, + 4615, 39143, 0, 0, 0, 0, 0, 27061, 13427, 10805, 7080, + 0, 0, 0, 0, 16793, 33962, 8854, 0, 27161, 0, 14710, + 0, 0, 0, 0, 0, 0, 0, 13660, 30592, 0, 27171, + 14139, 0, 33550, 3750, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 13231, 20741, 0, 0, 37261, 0, 0, 14889, 0, + 0, 0, 0, 29557, 0, 0, 32610, 0, 6230, 0, 9782, + 19505, 30438, 33647, 30506, 28304, 14771, 37724, 0, 9995, 0, 26614, + 0, 32854, 18221, 25720, 0, 0, 0, 0, 0, 0, 0, + 1235, 0, 0, 21145, 0, 0, 0, 30402, 14336, 25030, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21329, + 0, 20009, 28305, 0, 23968, 0, 0, 10089, 40630, 20015, 33660, + 0, 16514, 13687, 6101, 2956, 39727, 7430, 12774, 15078, 12015, 23167, + 14419, 40554, 0, 5810, 13446, 34169, 0, 38653, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 39417, 0, 19355, 10861, + 32997, 26938, 9529, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 33661, 0, 0, 12341, 0, 4184, 0, 19665, + 25633, 33502, 11427, 26162, 14564, 0, 0, 0, 15872, 0, 10768, + 9359, 9269, 0, 20018, 5992, 1280, 17612, 16195, 26281, 18758, 31834, + 0, 0, 27921, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 21921, 0, 16832, 0, 0, 0, 0, + 0, 0, 0, 0, 15656, 9534, 0, 0, 31549, 22070, 26022, + 15015, 10728, 9425, 14654, 0, 20969, 11176, 8721, 17200, 9064, 29194, + 0, 19308, 29015, 4957, 0, 0, 0, 23186, 37347, 13464, 20339, + 8844, 19975, 30816, 0, 29107, 23325, 0, 0, 3187, 6241, 0, + 22071, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10110, 0, 0, 0, 20165, + 19260, 18793, 23192, 15529, 0, 6004, 23532, 13374, 15271, 24024, 20166, + 26246, 0, 0, 0, 0, 0, 0, 12909, 16926, 15467, 33694, + 0, 0, 0, 0, 0, 0, 19389, 7802, 2842, 11698, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 15618, 0, 0, 30742, 9428, + 12385, 41230, 12037, 32895, 0, 0, 0, 0, 28226, 0, 25665, + 0, 28995, 0, 0, 0, 39348, 16068, 32512, 20205, 0, 31864, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25764, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7011, 20351, 40260, 41014, 19958, 0, 31619, 0, 28839, 0, + 12841, 2920, 12398, 0, 0, 0, 0, 0, 0, 0, 0, + 40670, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10498, 2568, 23550, 20213, 39169, + 15670, 35265, 40032, 0, 12944, 0, 22113, 0, 0, 11649, 0, + 20497, 18344, 0, 0, 0, 0, 0, 0, 0, 27546, 0, + 19365, 16974, 0, 0, 27607, 35528, 0, 0, 0, 0, 17302, + 0, 0, 0, 32815, 28997, 33416, 0, 0, 33895, 17316, 19921, + 30645, 19922, 0, 0, 0, 0, 0, 0, 0, 0, 35111, + 16383, 18128, 36380, 36381, 17334, 13076, 9557, 0, 0, 0, 9376, + 33089, 0, 0, 26569, 0, 41154, 0, 0, 0, 0, 0, + 0, 0, 15247, 16724, 0, 0, 0, 0, 0, 1519, 0, + 0, 27303, 21820, 33613, 0, 0, 0, 10264, 0, 0, 0, + 0, 9593, 0, 38560, 16483, 4679, 39707, 7764, 24217, 0, 38246, + 20906, 21709, 35834, 0, 0, 4502, 26864, 13025, 40914, 34524, 36331, + 0, 0, 0, 25655, 0, 25426, 31846, 0, 9362, 15178, 0, + 31370, 0, 24276, 4524, 0, 38275, 33057, 0, 37384, 38096, 4147, + 17054, 17055, 33704, 20040, 33706, 25670, 0, 0, 9674, 25496, 0, + 0, 19594, 0, 24287, 4703, 4704, 4707, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 31149, 0, 7193, 443, 0, 0, + 0, 0, 0, 0, 23596, 39671, 29418, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 39672, 39469, 0, 11402, 3794, 0, + 39673, 0, 0, 0, 36472, 0, 0, 0, 31352, 850, 0, + 10662, 26674, 0, 14899, 16002, 0, 0, 35580, 34271, 0, 0, + 1086, 0, 0, 0, 15733, 23673, 0, 0, 38835, 0, 15156, + 26377, 0, 0, 229, 38968, 39754, 0, 0, 0, 0, 0, + 0, 39771, 0, 13465, 0, 0, 0, 0, 0, 0, 27672, + 23086, 21962, 0, 0, 0, 0, 0, 0, 0, 40671, 0, + 0, 0, 0, 0, 0, 36382, 0, 11301, 0, 34231, 0, + 0, 26910, 21977, 23106, 0, 0, 0, 19486, 2609, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 37831, 0, 0, 9141, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5141, 0, 21072, 0, 38931, 0, 10902, 0, 0, 0, + 0, 0, 15510, 0, 5958, 29470, 0, 0, 9335, 0, 0, + 24440, 26981, 12806, 357, 20859, 22813, 12761, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 39030, 2115, 31064, + 0, 2575, 0, 0, 0, 0, 21074, 15203, 0, 0, 0, + 6345, 9336, 24455, 0, 25397, 35572, 6527, 16736, 0, 39997, 15713, + 6816, 32079, 5802, 21880, 6923, 36547, 31345, 15517, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 39674, 0, 0, 0, 39566, 34052, 0, 0, + 39333, 0, 0, 34775, 0, 12002, 12305, 21112, 0, 0, 0, + 0, 34256, 18723, 0, 0, 7865, 25870, 4002, 30693, 0, 8116, + 15520, 27744, 15299, 0, 35800, 11213, 0, 0, 0, 0, 0, + 0, 0, 37167, 0, 0, 0, 0, 17162, 0, 0, 17936, + 6415, 6942, 0, 0, 0, 23969, 6355, 0, 0, 13688, 4323, + 32362, 0, 0, 0, 8581, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5391, 0, 0, 0, 10586, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 40915, 0, 0, + 23515, 30108, 10588, 22578, 8862, 0, 21544, 0, 0, 15554, 0, + 0, 39587, 0, 0, 0, 0, 0, 0, 32730, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 26547, 37051, 13237, 0, 0, 0, 0, 0, 23429, + 3205, 25921, 0, 28359, 23774, 11789, 0, 26320, 6982, 0, 0, + 0, 0, 0, 0, 0, 0, 24542, 0, 15461, 0, 0, + 31002, 40766, 12359, 0, 0, 0, 0, 4977, 0, 4891, 0, + 0, 0, 18555, 15272, 16137, 5575, 24127, 0, 20658, 0, 0, + 9831, 10595, 3006, 10515, 0, 0, 0, 0, 0, 0, 0, + 0, 2376, 38982, 0, 0, 9717, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 33526, 22375, 14949, 0, 0, 8439, 27673, + 0, 28227, 25090, 0, 31225, 34413, 22412, 32738, 22052, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1069, + 39168, 12399, 0, 0, 13920, 17466, 15497, 0, 40043, 0, 0, + 0, 0, 0, 0, 0, 38219, 0, 16663, 23204, 1820, 0, + 0, 0, 0, 0, 0, 0, 0, 36238, 22779, 0, 0, + 0, 0, 27932, 18955, 0, 5594, 6386, 17732, 40683, 0, 0, + 0, 0, 0, 0, 0, 0, 2942, 0, 0, 0, 0, + 0, 0, 0, 3232, 28528, 0, 0, 0, 0, 0, 25103, + 5414, 0, 0, 25224, 0, 23005, 0, 0, 0, 0, 0, + 0, 39920, 32816, 0, 0, 13259, 24844, 16776, 2168, 25037, 0, + 0, 0, 0, 0, 0, 32569, 16820, 0, 0, 0, 16459, + 0, 0, 0, 0, 16180, 0, 16181, 0, 0, 37466, 0, + 0, 0, 0, 0, 13503, 24231, 12095, 0, 0, 8420, 0, + 0, 35657, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 35684, 39375, 0, 0, 1591, 26739, 14316, + 0, 0, 0, 0, 10314, 7952, 0, 14387, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 41267, 35414, 0, 0, 0, 0, 32330, 35415, + 0, 27729, 0, 4217, 0, 0, 20605, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 38582, 0, 34048, 0, 0, 25549, 0, 11992, + 0, 0, 0, 26421, 0, 0, 0, 27187, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36895, + 37262, 0, 0, 15066, 0, 0, 0, 0, 0, 0, 40737, + 18734, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3541, 16051, 0, 0, 0, 0, + 40562, 0, 0, 0, 0, 0, 10762, 0, 0, 33570, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 40910, 36513, 0, + 0, 40152, 0, 0, 18333, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 21812, 0, 0, 0, 0, 0, + 0, 1304, 0, 3631, 0, 41106, 7772, 18773, 23113, 0, 0, + 0, 0, 0, 40430, 0, 38976, 26870, 37183, 18774, 17588, 0, + 0, 0, 14944, 17747, 1028, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 35943, 9364, 0, 0, 0, 0, 0, 0, 0, 343, 0, + 0, 9665, 20455, 0, 34550, 16361, 0, 0, 1993, 0, 0, + 38099, 36863, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 36002, 21296, 0, 0, 0, 0, 0, 21299, 9840, 15109, + 0, 26892, 0, 32302, 0, 23727, 25104, 15970, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 26507, 0, 12011, 0, 30407, + 0, 0, 0, 0, 0, 7545, 7552, 0, 37218, 0, 0, + 0, 39369, 9298, 0, 13635, 19487, 10342, 0, 36820, 0, 0, + 0, 0, 0, 0, 6433, 27625, 0, 17098, 0, 0, 13642, + 21701, 470, 36975, 0, 0, 0, 0, 0, 39385, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10352, 15348, 0, 0, + 0, 0, 6437, 12708, 0, 3120, 0, 4218, 10364, 38547, 0, + 0, 0, 0, 19782, 0, 0, 10365, 40834, 40195, 0, 0, + 30087, 0, 0, 0, 0, 0, 41228, 0, 25553, 6775, 13296, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10546, + 0, 1011, 20612, 0, 0, 0, 0, 41053, 0, 0, 1621, + 0, 15692, 12768, 0, 0, 0, 0, 40578, 0, 33387, 0, + 0, 0, 0, 0, 0, 10388, 0, 23993, 0, 0, 0, + 0, 0, 0, 0, 7470, 26757, 0, 0, 0, 40523, 15797, + 38314, 32087, 0, 1259, 35835, 0, 2957, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 19661, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 30360, 0, 0, 0, 0, 0, 0, 31163, 15657, 31071, + 33221, 15371, 0, 14273, 6478, 11428, 0, 0, 39755, 2435, 25517, + 12343, 0, 35213, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 14053, 34865, 0, 0, 0, 0, + 40961, 0, 0, 0, 0, 0, 0, 0, 2283, 0, 0, + 0, 0, 0, 0, 0, 27662, 17201, 9187, 2961, 0, 7476, + 18245, 0, 13711, 37808, 0, 0, 39773, 0, 0, 3817, 1630, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 12173, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 19113, 12924, 0, 4144, 27503, 0, 18943, + 15093, 13540, 0, 29200, 38400, 0, 0, 35924, 0, 4525, 21178, + 12737, 0, 0, 0, 0, 0, 12606, 0, 0, 0, 0, + 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 13036, 0, 0, 997, 0, 7267, 28229, 41231, + 0, 8562, 8594, 16575, 0, 40667, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 11109, 0, 0, 29922, 0, 0, + 0, 1338, 14514, 0, 0, 0, 0, 0, 0, 11181, 0, + 0, 0, 3365, 0, 0, 0, 15777, 5258, 8742, 32906, 0, + 13745, 0, 2235, 0, 0, 0, 0, 0, 0, 0, 0, + 41078, 0, 23092, 0, 0, 27326, 2084, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 21657, 34558, 40112, 0, 19906, + 0, 1455, 0, 32562, 0, 0, 0, 0, 18830, 16968, 0, + 0, 0, 12645, 0, 20357, 16811, 0, 39852, 36710, 1456, 0, + 0, 0, 0, 0, 0, 0, 20830, 25197, 0, 0, 0, + 0, 0, 0, 0, 0, 21475, 0, 0, 0, 0, 0, + 0, 0, 24989, 39011, 0, 0, 0, 0, 16819, 0, 0, + 0, 0, 0, 0, 5284, 14999, 0, 0, 0, 18146, 0, + 18164, 34451, 0, 0, 0, 35011, 39177, 23143, 69, 0, 21791, + 19521, 0, 0, 0, 0, 0, 0, 0, 15201, 0, 14254, + 34476, 20266, 0, 36127, 30310, 35066, 30183, 22500, 28182, 0, 0, + 0, 0, 0, 0, 0, 0, 15565, 0, 0, 10646, 0, + 20504, 18025, 35743, 26601, 0, 41289, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 29736, 0, 36668, 0, 30227, + 9594, 10718, 0, 0, 0, 27063, 0, 33353, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 3319, 0, 15518, 35766, 34852, + 29498, 6287, 2548, 18328, 0, 0, 0, 24629, 33831, 26615, 15786, + 29669, 0, 23815, 0, 3873, 0, 0, 0, 0, 30959, 0, + 18484, 196, 0, 0, 0, 0, 0, 0, 15212, 0, 35032, + 0, 8002, 0, 0, 0, 1057, 16408, 23606, 5811, 0, 0, + 13523, 9530, 0, 33356, 0, 0, 15454, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 32363, 31133, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8955, + 0, 0, 0, 21955, 15372, 0, 0, 0, 15658, 0, 0, + 0, 0, 0, 29279, 9066, 19281, 0, 18335, 0, 0, 0, + 30817, 30966, 0, 0, 0, 0, 0, 0, 8976, 0, 29812, + 21643, 0, 0, 20158, 0, 0, 0, 16496, 23825, 19391, 38983, + 0, 11235, 36571, 13992, 0, 19799, 0, 0, 8056, 0, 0, + 0, 24801, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 18340, 8241, 5219, 0, + 8960, 0, 4791, 0, 0, 33286, 0, 0, 0, 0, 0, + 0, 29758, 27200, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 24514, 0, 0, 0, 0, 0, 0, + 0, 0, 25456, 0, 0, 0, 0, 0, 0, 0, 17318, + 0, 0, 0, 12233, 30174, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 29653, 0, 0, 0, 0, 0, + 28710, 0, 18165, 0, 35658, 25641, 0, 22001, 0, 0, 0, + 2164, 0, 0, 0, 37708, 25048, 40303, 9905, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 7177, 9908, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2059, 22827, 17798, 0, 0, 0, 0, 0, 0, + 0, 15978, 8015, 29315, 31102, 0, 14421, 0, 0, 0, 0, + 0, 0, 0, 0, 39107, 0, 8035, 0, 0, 0, 0, + 0, 0, 0, 18383, 0, 0, 0, 31847, 29280, 0, 0, + 0, 12595, 0, 0, 0, 35094, 0, 4659, 0, 0, 22168, + 24180, 0, 0, 0, 0, 0, 18394, 12460, 0, 0, 0, + 0, 0, 29645, 35522, 0, 2882, 0, 0, 0, 0, 0, + 8929, 0, 0, 6219, 0, 0, 0, 0, 0, 0, 0, + 32466, 0, 0, 29531, 0, 40376, 35556, 35712, 40828, 23408, 0, + 0, 2573, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6641, 0, 0, 3678, 18709, 6645, 0, 7369, 27054, 29170, 12117, + 24533, 27527, 3160, 0, 0, 11572, 27145, 0, 0, 37838, 0, + 0, 0, 0, 0, 18370, 0, 19419, 8993, 0, 0, 0, + 32080, 20613, 0, 26671, 0, 22916, 35074, 24701, 25184, 0, 0, + 0, 14625, 0, 0, 36205, 520, 21518, 0, 3766, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 25404, 4112, 21530, 17163, + 13233, 15318, 2424, 3753, 40363, 40842, 34780, 0, 0, 0, 0, + 0, 0, 0, 30960, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 12546, 12547, 0, 0, + 0, 18932, 24636, 6654, 742, 2663, 0, 1931, 0, 3423, 39037, + 19548, 0, 12558, 20315, 37651, 0, 31209, 39730, 22830, 0, 0, + 3686, 0, 0, 0, 0, 0, 20016, 7454, 4832, 19858, 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, 36161, 19533, 5778, 5867, + 0, 23770, 0, 0, 10188, 39491, 14495, 21428, 0, 0, 0, + 20019, 9179, 0, 0, 0, 0, 0, 40364, 21545, 40642, 0, + 35214, 4590, 0, 33503, 0, 31836, 0, 0, 1858, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2284, 0, 0, 0, 0, 34525, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 13913, 0, + 0, 14567, 5315, 6459, 0, 35142, 14160, 15462, 19217, 30721, 29755, + 36784, 22040, 0, 22536, 6108, 0, 30722, 3099, 13150, 0, 27663, + 40645, 27936, 0, 25658, 0, 37058, 0, 0, 0, 0, 6983, + 0, 0, 15679, 0, 40337, 0, 0, 0, 0, 0, 31988, + 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, 8057, 28959, 31592, 3776, 8438, + 18866, 2443, 26329, 18254, 0, 31856, 12191, 35593, 28681, 0, 10971, + 0, 0, 4836, 8764, 0, 27118, 25952, 10730, 32391, 0, 0, + 31992, 0, 0, 0, 0, 20823, 28363, 0, 38566, 0, 7887, + 26033, 21795, 35926, 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, 24277, 24430, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 11821, 27505, 5157, + 21930, 20666, 23698, 3648, 22019, 14795, 0, 0, 3008, 17822, 1754, + 15621, 5220, 3831, 29571, 5221, 19431, 11111, 17684, 32215, 0, 2380, + 18805, 4129, 31226, 19396, 0, 0, 0, 40850, 0, 6464, 0, + 0, 27513, 8242, 14675, 40108, 0, 5921, 30509, 4148, 23699, 29961, + 0, 17458, 1559, 16938, 0, 0, 16939, 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, 1353, 8251, 4796, 6336, 0, 38100, 18395, 34085, 24509, 12215, + 23830, 0, 13053, 26440, 6799, 27275, 2148, 33532, 6178, 0, 25161, + 0, 34803, 25690, 17976, 13054, 5716, 7632, 5832, 41198, 0, 21668, + 0, 0, 0, 0, 28112, 29330, 237, 0, 0, 2446, 6113, + 26644, 6466, 29130, 13482, 41199, 38792, 13055, 5229, 5162, 27834, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 38675, 29515, + 39829, 0, 0, 36801, 22023, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17057, 0, 0, 23788, 0, 28243, 14574, + 128, 8744, 14682, 30009, 1363, 23615, 2004, 11838, 0, 13184, 0, + 0, 9010, 28114, 0, 0, 0, 0, 4413, 23982, 0, 0, + 0, 34426, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5834, 0, 0, 20354, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 23003, 18187, 13754, + 40351, 9207, 0, 0, 6485, 38903, 0, 26463, 24312, 20050, 0, + 22897, 4576, 3780, 0, 0, 25815, 0, 0, 0, 0, 0, + 0, 29331, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 18286, 18870, 18686, 41019, 0, 0, + 0, 18959, 11379, 0, 29402, 29932, 23977, 17984, 865, 22203, 38626, + 0, 17319, 0, 0, 0, 29145, 11008, 0, 0, 0, 0, + 0, 17846, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 11712, 24754, + 33844, 0, 14179, 6025, 28164, 0, 30863, 0, 34442, 34341, 647, + 0, 13287, 21300, 17335, 11011, 23554, 39921, 0, 0, 0, 0, + 0, 0, 0, 0, 1382, 0, 0, 37120, 6026, 17989, 17350, + 40691, 12664, 14451, 0, 7748, 0, 37444, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17855, 38000, 23796, 13603, 9377, 0, + 40695, 0, 0, 8273, 0, 0, 0, 0, 0, 0, 0, + 26065, 0, 0, 4677, 0, 0, 0, 0, 0, 0, 11713, + 0, 0, 0, 0, 5331, 18446, 36034, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 25776, 37793, 0, + 5603, 0, 0, 0, 0, 0, 0, 8452, 38062, 26362, 37464, + 2031, 0, 6092, 7238, 0, 37228, 0, 26594, 0, 0, 0, + 0, 0, 8888, 0, 20328, 29989, 0, 0, 17787, 0, 0, + 0, 0, 0, 0, 0, 0, 38378, 22238, 0, 20005, 0, + 20477, 7333, 0, 20891, 27740, 35445, 12712, 40307, 0, 0, 0, + 0, 0, 575, 37263, 0, 22956, 0, 0, 0, 11284, 2300, + 13349, 0, 0, 0, 28658, 0, 0, 0, 0, 0, 0, + 0, 0, 39709, 0, 20090, 15319, 0, 0, 0, 0, 34893, + 6568, 25008, 2130, 4010, 24084, 18230, 1932, 0, 15255, 7663, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5392, 0, 0, + 0, 6292, 8708, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 18077, 31690, 0, 21341, 40011, + 40012, 0, 0, 0, 0, 3772, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 21367, 12166, 0, 24722, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 15135, 0, 0, 32382, 0, 10420, + 0, 17897, 0, 40767, 0, 0, 0, 21958, 4651, 0, 0, + 0, 0, 2562, 0, 0, 0, 0, 0, 39964, 2066, 0, + 0, 0, 0, 0, 3777, 31857, 25801, 32203, 26034, 20272, 0, + 7264, 39435, 0, 4786, 0, 0, 0, 0, 0, 32035, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 21898, 16940, 41071, + 0, 4729, 38281, 0, 16941, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 23355, 0, 40584, 4797, 23055, 0, 7275, 28691, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 40790, 41109, 40030, 25448, + 17911, 28692, 0, 0, 0, 0, 0, 0, 0, 27135, 0, + 0, 0, 4746, 40796, 7899, 0, 0, 0, 0, 32782, 0, + 0, 0, 0, 0, 0, 7738, 0, 0, 0, 0, 0, + 0, 32417, 13190, 0, 7682, 0, 0, 0, 0, 17320, 20684, + 0, 0, 0, 0, 0, 0, 36712, 0, 0, 0, 0, + 0, 12072, 0, 24755, 0, 0, 0, 0, 21441, 0, 0, + 0, 20063, 0, 0, 23557, 0, 0, 10455, 0, 17565, 0, + 0, 0, 0, 0, 0, 41306, 0, 0, 18169, 0, 0, + 40188, 0, 21446, 0, 0, 12434, 25363, 13643, 8424, 0, 0, + 35713, 0, 0, 40039, 0, 31333, 0, 0, 0, 0, 8831, + 4633, 0, 20329, 0, 0, 0, 34049, 0, 39398, 32699, 0, + 0, 7965, 10907, 0, 0, 0, 5519, 0, 14860, 5897, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 27170, 0, 0, + 30469, 0, 0, 0, 0, 0, 0, 20892, 5523, 27064, 4384, + 27241, 0, 30230, 3084, 7244, 0, 9092, 37491, 0, 0, 9354, + 0, 0, 0, 0, 0, 0, 0, 0, 24158, 0, 38644, + 5040, 26487, 0, 0, 0, 0, 0, 0, 0, 40004, 32498, + 20480, 40872, 11467, 20010, 0, 31814, 39710, 22036, 6730, 0, 0, + 0, 4452, 20714, 0, 3039, 0, 35803, 8996, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 14045, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38336, + 22831, 35202, 13690, 0, 22459, 0, 0, 26111, 40482, 14223, 0, + 0, 18231, 37176, 0, 14422, 0, 0, 0, 0, 21887, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 19662, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3130, 0, 40426, 21429, 15573, 13591, 11224, + 0, 0, 33137, 41253, 34635, 14913, 0, 0, 0, 0, 10869, + 40093, 26549, 0, 34526, 0, 33007, 5994, 0, 0, 3133, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13027, 12582, 0, 0, 4327, + 10682, 0, 0, 0, 0, 0, 0, 0, 0, 4958, 0, + 0, 0, 15136, 33228, 11790, 13032, 40100, 38470, 8220, 3632, 1047, + 21893, 0, 0, 0, 12596, 23776, 0, 30411, 21941, 1305, 27598, + 0, 0, 0, 0, 0, 0, 0, 0, 14056, 35223, 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, + 7481, 0, 0, 16930, 0, 0, 17216, 22543, 0, 0, 0, + 0, 0, 0, 28221, 18255, 10425, 11914, 28733, 27599, 39798, 1966, + 0, 0, 0, 31858, 0, 0, 0, 22939, 25134, 0, 20824, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 36572, 0, 0, 0, 0, 5067, 0, 0, 0, + 0, 0, 0, 0, 23441, 5889, 21566, 27506, 0, 26438, 16098, + 28232, 0, 6245, 6009, 0, 0, 0, 0, 0, 0, 0, + 8925, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 40408, 9798, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33533, + 24820, 0, 0, 34086, 0, 0, 13389, 38997, 0, 5833, 25915, + 1030, 0, 28371, 23831, 0, 0, 0, 33534, 0, 34087, 0, + 0, 20669, 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, 28244, 16212, 40261, 40114, 0, 17284, 0, 5127, 14524, 0, + 37943, 2814, 19120, 0, 0, 26049, 0, 17475, 0, 41127, 0, + 0, 16312, 27510, 24191, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6247, 0, 0, 0, 0, 0, 31397, 19912, + 0, 12647, 0, 0, 3447, 0, 21294, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 34999, 0, 0, 16224, 0, 0, 18960, 0, 28255, + 7903, 0, 0, 16770, 30764, 0, 0, 0, 0, 0, 0, + 0, 0, 4540, 0, 0, 0, 0, 0, 17336, 0, 22804, + 0, 15048, 14578, 0, 16230, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 12665, 0, 0, 20365, 0, 35112, + 1427, 0, 0, 0, 4586, 27695, 0, 0, 27696, 0, 0, + 10456, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 21060, 0, 6035, 0, 0, 3073, 37905, 0, 33425, 27233, 0, + 2776, 20390, 17407, 36083, 33211, 30536, 9160, 29688, 28411, 7471, 4906, + 21539, 4644, 41271, 13712, 33880, 1967, 13871, 36233, 33528, 0, 36978, + 33350, 0, 23478, 843, 33262, 8950, 0, 0, 41158, 0, 0, + 0, 13581, 0, 15128, 0, 0, 33272, 857, 27255, 37328, 0, + 40055, 38658, 0, 0, 0, 0, 0, 0, 39907, 0, 0, + 0, 2563, 0, 4208, 18337, 0, 0, 0, 0, 28142, 0, + 40259, 0, 0, 0, 0, 0, 0, 0, 0, 1513, 0, + 0, 0, 33194, 0, 34279, 0, 0, 18133, 0, 0, 0, + 0, 34281, 0, 0, 0, 0, 29464, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5549, 0, 0, + 0, 0, 0, 0, 0, 22501, 11067, 2453, 0, 0, 0, + 0, 0, 0, 29231, 20737, 14731, 0, 20738, 0, 14616, 18304, + 0, 18182, 0, 0, 0, 18305, 11076, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 7967, 10908, + 0, 0, 6924, 8898, 9093, 0, 0, 0, 0, 9306, 0, + 0, 0, 0, 0, 0, 0, 19026, 0, 7245, 18929, 19852, + 8005, 18223, 0, 0, 0, 0, 0, 32865, 9103, 0, 32365, + 1933, 0, 12561, 0, 0, 0, 0, 0, 0, 0, 24913, + 18745, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27594, + 0, 0, 20740, 37330, 10101, 0, 0, 0, 0, 0, 37736, + 5199, 0, 0, 0, 0, 37059, 12911, 0, 0, 8520, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2378, + 26724, 18318, 0, 0, 0, 0, 13375, 0, 0, 28048, 28049, + 39967, 0, 0, 0, 0, 0, 0, 17749, 0, 33838, 18807, + 0, 12623, 0, 0, 34414, 0, 0, 0, 0, 18820, 0, + 20457, 29131, 0, 0, 0, 11438, 0, 0, 35958, 28737, 0, + 31300, 0, 0, 0, 12224, 0, 0, 0, 0, 0, 0, + 6387, 16074, 0, 15047, 0, 0, 0, 0, 26893, 21031, 23006, + 0, 0, 27280, 25023, 0, 0, 0, 0, 0, 0, 25310, + 0, 0, 7601, 0, 0, 28445, 29988, 0, 34766, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6678, 4350, 0, 9152, 7607, 0, 0, 25507, + 0, 0, 0, 8544, 32479, 0, 32480, 10794, 0, 28898, 26306, + 34781, 40873, 0, 37557, 0, 0, 0, 0, 0, 0, 0, + 27962, 0, 0, 4124, 32484, 0, 581, 0, 19424, 0, 8119, + 16178, 17039, 0, 13691, 36692, 0, 0, 0, 0, 37331, 0, + 3620, 0, 4125, 35863, 26240, 0, 0, 0, 12361, 34324, 0, + 0, 31372, 4270, 19514, 0, 0, 0, 0, 8047, 12734, 9067, + 9122, 12786, 0, 0, 0, 32204, 0, 14000, 40882, 18526, 0, + 0, 9069, 0, 0, 0, 25278, 0, 26250, 0, 0, 14957, + 29646, 36862, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 12941, 6382, 0, 11000, 0, 0, 0, 25959, + 37425, 0, 0, 0, 0, 0, 19367, 0, 39443, 34338, 8568, + 0, 11280, 0, 0, 0, 0, 0, 24994, 0, 0, 34847, + 0, 41156, 0, 0, 0, 32583, 35715, 34477, 10639, 36979, 0, + 0, 0, 3584, 0, 3464, 0, 0, 10165, 25999, 21983, 28448, + 7571, 3408, 0, 0, 10649, 33961, 0, 0, 0, 0, 0, + 0, 0, 0, 39567, 0, 0, 0, 0, 24776, 0, 0, + 0, 0, 31487, 7985, 0, 27248, 9909, 0, 22982, 0, 4429, + 0, 0, 0, 0, 0, 0, 0, 2637, 0, 0, 10583, + 0, 0, 0, 0, 22205, 26620, 32623, 0, 0, 33750, 4431, + 29506, 22987, 0, 0, 0, 0, 0, 0, 28479, 2516, 0, + 0, 41063, 12020, 33676, 34636, 2639, 0, 30106, 0, 0, 0, + 0, 0, 0, 32194, 33763, 10773, 11375, 8723, 3742, 1307, 10590, + 10591, 3493, 0, 2564, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 38471, 0, 38543, 28497, 0, 0, 22993, + 28498, 0, 36791, 8058, 4359, 4959, 28429, 0, 18256, 0, 0, + 4360, 0, 10602, 0, 10125, 16168, 0, 26882, 0, 0, 0, + 0, 29647, 11832, 10435, 22764, 37405, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 32120, 10038, 0, 22998, 0, 0, + 0, 0, 0, 0, 16225, 12073, 0, 0, 0, 0, 0, + 0, 0, 0, 28610, 0, 0, 0, 16591, 0, 27354, 0, + 0, 0, 5381, 5768, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 33364, 0, 0, 30512, 0, 3068, + 20951, 0, 14826, 0, 0, 7081, 7085, 21814, 21828, 0, 0, + 0, 0, 0, 0, 40407, 0, 0, 0, 0, 21905, 0, + 17761, 16730, 0, 405, 0, 0, 0, 0, 3252, 0, 0, + 9525, 24956, 8772, 0, 8951, 26480, 0, 0, 0, 0, 16272, + 39284, 35864, 9709, 30547, 19087, 0, 0, 0, 26947, 36340, 26787, + 29813, 1308, 0, 38263, 39965, 0, 25491, 23335, 8235, 2444, 0, + 0, 0, 0, 16942, 19398, 0, 17459, 1560, 0, 0, 0, + 4159, 35959, 0, 0, 0, 22043, 0, 0, 0, 0, 35978, + 15780, 0, 0, 1577, 0, 3663, 24848, 20695, 38923, 26142, 26143, + 0, 0, 0, 0, 0, 0, 34891, 8890, 20955, 0, 0, + 32962, 0, 0, 29337, 0, 0, 0, 0, 0, 0, 35132, + 0, 0, 26097, 0, 0, 0, 0, 0, 25974, 0, 0, + 5731, 33633, 0, 0, 0, 0, 0, 24777, 0, 0, 0, + 0, 0, 0, 10584, 26803, 29558, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6807, 0, 0, + 0, 0, 17653, 0, 10721, 17040, 0, 32503, 0, 0, 26715, + 0, 0, 7873, 0, 0, 0, 0, 0, 0, 0, 34528, + 30489, 23179, 6739, 0, 11225, 23686, 0, 33008, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4459, 26760, + 0, 0, 0, 7150, 0, 33229, 0, 29959, 34641, 0, 17812, + 0, 0, 20023, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 40982, 0, 40768, 0, 10973, 36431, 17451, 4917, + 29282, 29343, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 25432, 0, 104, 0, 0, 114, 38991, 9763, 18808, 38845, 20033, + 17685, 38992, 0, 0, 0, 24872, 4532, 0, 0, 29480, 0, + 28694, 38676, 10992, 0, 22765, 0, 4920, 25449, 0, 0, 0, + 0, 0, 21136, 0, 0, 0, 0, 21037, 5261, 13486, 0, + 0, 0, 0, 0, 14683, 7126, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 17338, 0, 9767, + 30271, 0, 0, 0, 0, 21495, 0, 13850, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 22565, 3567, 0, 0, 0, + 0, 0, 0, 0, 22566, 35639, 6321, 30218, 33992, 0, 23454, + 26294, 0, 0, 33461, 0, 0, 10312, 22099, 0, 22234, 0, + 33325, 0, 3519, 28616, 41171, 41124, 23462, 6322, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27526, + 0, 0, 20857, 31435, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3018, 35688, 0, 0, 39247, 0, 0, 14463, 5030, + 0, 25854, 0, 0, 40292, 30395, 0, 0, 25855, 633, 12830, + 19350, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 30158, 0, 23472, 0, 0, 0, 0, 40454, 30081, + 0, 0, 22854, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 22321, 15821, 35436, 0, 32963, 37670, 10520, 0, 10745, 39250, + 4282, 27055, 30222, 0, 32843, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 8853, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6911, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 15673, 20886, 0, 0, + 14394, 33863, 24703, 3086, 18891, 10378, 26800, 21027, 0, 10379, 2543, + 34303, 8837, 21519, 0, 9781, 34374, 9383, 0, 0, 39682, 16634, + 0, 0, 0, 0, 0, 0, 6412, 23489, 24704, 14871, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7713, 0, 33634, 29950, 0, 9996, 15649, 0, 0, + 26616, 39711, 0, 22166, 39270, 17164, 30355, 0, 7304, 33181, 0, + 0, 34267, 0, 0, 0, 0, 14412, 26707, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 19528, 0, 30015, 40627, 31508, 36268, 14043, 29994, 0, + 0, 8857, 12549, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 40404, 0, 0, 29433, 0, 39409, 0, 12322, + 0, 0, 0, 36417, 30805, 0, 11422, 29507, 2691, 0, 0, + 15943, 23607, 638, 2514, 30146, 21016, 13586, 0, 34315, 0, 29797, + 0, 30963, 0, 4496, 0, 0, 33662, 36272, 0, 0, 1058, + 0, 0, 0, 0, 18860, 0, 0, 0, 0, 38019, 4908, + 0, 0, 0, 21540, 14561, 10763, 0, 0, 0, 8861, 0, + 0, 0, 0, 0, 0, 0, 0, 10764, 15193, 8907, 0, + 11695, 33009, 0, 0, 31837, 10002, 20020, 0, 31022, 11931, 25950, + 33185, 38969, 12021, 0, 8912, 0, 0, 25842, 13861, 30198, 0, + 0, 0, 6546, 3429, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 31551, 0, 0, 0, 0, 20021, 38128, 25922, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 29999, 39732, 30965, 0, 0, 36172, 30017, 0, + 3693, 38264, 0, 32645, 20538, 4652, 0, 0, 1447, 33400, 0, + 0, 35494, 0, 0, 0, 0, 0, 0, 11568, 0, 38396, + 28315, 11903, 14655, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4653, 0, 0, 12192, 34082, 28287, + 2479, 0, 35928, 0, 0, 0, 0, 1553, 0, 0, 0, + 14945, 17217, 0, 0, 22221, 0, 0, 0, 0, 37966, 35233, + 0, 1325, 39040, 39041, 0, 14354, 38984, 0, 0, 27399, 0, + 0, 0, 31595, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 33580, 20947, 32205, 9718, 30825, 0, 0, + 12386, 25809, 0, 0, 6177, 21860, 6461, 39294, 15666, 0, 0, + 20494, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 748, 11816, 0, 0, 40931, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 25902, 0, + 29002, 35513, 0, 37387, 0, 0, 0, 35097, 21669, 0, 3837, + 11940, 0, 6587, 0, 23545, 36492, 1818, 21655, 11533, 0, 0, + 0, 0, 0, 0, 0, 0, 36493, 0, 0, 0, 749, + 0, 0, 0, 9492, 16763, 41224, 0, 0, 0, 0, 0, + 0, 0, 0, 2815, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 13061, 0, 0, 0, 19913, 0, 32788, 0, 0, + 0, 0, 0, 33195, 0, 16975, 0, 0, 0, 0, 0, + 0, 0, 0, 24087, 0, 0, 0, 0, 30766, 20923, 0, + 22135, 0, 16712, 0, 0, 19137, 0, 0, 0, 18993, 0, + 8821, 0, 18994, 0, 0, 24849, 0, 0, 0, 19144, 0, + 21044, 0, 0, 19145, 37791, 0, 0, 0, 0, 0, 27533, + 0, 0, 20127, 30452, 2426, 12883, 30480, 0, 0, 0, 0, + 0, 12735, 0, 0, 0, 0, 11360, 0, 0, 0, 17569, + 40854, 517, 27166, 0, 0, 30329, 0, 0, 0, 27234, 0, + 0, 0, 0, 9511, 31462, 0, 25550, 35071, 0, 0, 8545, + 0, 0, 0, 0, 0, 0, 37737, 0, 0, 36564, 30238, + 1955, 0, 0, 0, 0, 33191, 0, 0, 22627, 1980, 0, + 0, 9919, 38569, 31128, 0, 35266, 1372, 9923, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3585, 0, 0, + 39683, 0, 21230, 0, 0, 0, 31210, 55, 0, 0, 0, + 0, 0, 53, 37193, 3640, 0, 0, 14166, 39816, 39830, 39831, + 14455, 0, 0, 0, 0, 9964, 0, 0, 0, 22822, 0, + 0, 35027, 0, 0, 0, 0, 0, 36751, 22826, 0, 20616, + 0, 0, 0, 0, 0, 41295, 22983, 0, 33929, 15842, 35806, + 22984, 0, 0, 0, 0, 0, 0, 0, 0, 40526, 0, + 0, 0, 0, 0, 0, 0, 21245, 24664, 4604, 0, 0, + 0, 0, 0, 0, 35046, 0, 0, 0, 0, 7628, 0, + 0, 0, 31994, 0, 13246, 2521, 0, 0, 32775, 2522, 0, + 0, 0, 0, 0, 3368, 4799, 0, 0, 0, 24510, 0, + 37417, 0, 37100, 0, 0, 0, 30987, 0, 2528, 37207, 0, + 0, 0, 0, 0, 0, 41258, 5374, 0, 0, 14804, 5375, + 36390, 0, 7786, 0, 0, 0, 31037, 0, 0, 13947, 23479, + 0, 24327, 0, 16119, 0, 28623, 32074, 0, 29234, 0, 16123, + 0, 29341, 0, 10930, 40149, 38587, 28460, 0, 29239, 28468, 28480, + 11172, 34529, 29451, 0, 29452, 28481, 0, 0, 0, 0, 0, + 0, 11272, 0, 12787, 23536, 0, 28503, 0, 0, 28641, 11239, + 0, 0, 40443, 11153, 0, 0, 16390, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 41218, 35660, 7935, 31326, 0, 7936, + 0, 6059, 28446, 0, 0, 0, 0, 0, 0, 0, 3036, + 0, 0, 25377, 25003, 0, 8642, 0, 0, 0, 0, 7987, + 5670, 5859, 36632, 0, 12831, 0, 0, 18375, 0, 0, 36633, + 22512, 0, 11964, 24472, 0, 7248, 31211, 29607, 10175, 0, 0, + 28630, 0, 0, 0, 0, 0, 10536, 0, 0, 0, 0, + 0, 29361, 0, 0, 0, 40007, 0, 0, 554, 33010, 5347, + 0, 13862, 0, 0, 0, 0, 0, 10870, 859, 0, 6105, + 0, 0, 0, 21858, 30819, 37062, 0, 33230, 8048, 32384, 23522, + 29756, 0, 0, 12362, 0, 36515, 0, 5490, 30552, 31575, 0, + 22017, 0, 26768, 36854, 0, 41, 13161, 0, 9008, 25752, 0, + 0, 0, 8977, 0, 0, 26167, 28829, 0, 0, 0, 0, + 0, 0, 18809, 316, 0, 23543, 33406, 0, 5000, 0, 0, + 0, 7189, 30842, 0, 6664, 17693, 7219, 11534, 14958, 28512, 41232, + 25240, 2237, 29024, 0, 0, 11240, 33535, 0, 38615, 0, 0, + 0, 8442, 0, 0, 22389, 2240, 32812, 4968, 0, 0, 0, + 12648, 0, 0, 0, 0, 17060, 0, 0, 22088, 0, 0, + 0, 18429, 17339, 31713, 29035, 0, 0, 18134, 0, 0, 0, + 0, 17068, 25169, 18170, 0, 0, 0, 9701, 0, 0, 0, + 0, 0, 22917, 20617, 22008, 0, 0, 474, 0, 0, 0, + 0, 0, 0, 0, 23316, 0, 0, 34402, 0, 0, 0, + 0, 0, 30239, 262, 0, 20517, 20453, 34137, 19914, 0, 0, + 9323, 0, 0, 13330, 0, 0, 0, 0, 8325, 0, 0, + 0, 0, 0, 2181, 31318, 38924, 25284, 15578, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 38853, 39889, 24581, 9738, 8885, 23041, 11062, 20228, 0, 0, 29229, + 0, 0, 0, 0, 30464, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 40192, 4933, 33351, 20842, 0, 0, 14703, 0, + 0, 21389, 0, 0, 0, 0, 0, 0, 11068, 26090, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 39388, 0, 0, 28402, 0, + 27628, 0, 0, 0, 35716, 0, 0, 0, 0, 0, 0, + 0, 24456, 39652, 18889, 25551, 0, 23254, 37152, 39989, 34771, 32258, + 20710, 3789, 11604, 14258, 14326, 22729, 0, 0, 0, 0, 13513, + 0, 9315, 0, 20607, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 31463, 23065, 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, 12522, 0, 0, 0, 0, 0, 0, 30957, 907, 35573, + 7989, 27634, 14712, 12539, 0, 21325, 0, 987, 0, 0, 0, + 0, 33635, 0, 0, 24297, 1916, 0, 0, 30451, 39035, 0, + 31091, 26450, 38208, 34828, 0, 0, 27845, 21520, 0, 0, 0, + 0, 1219, 0, 0, 0, 0, 0, 0, 0, 4626, 23897, + 0, 0, 0, 0, 0, 32755, 39403, 26504, 0, 0, 39684, + 22328, 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, 5903, 0, + 0, 0, 0, 0, 0, 31100, 0, 39568, 1220, 0, 7608, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 661, 0, + 0, 0, 0, 24630, 21277, 1923, 6649, 0, 26984, 33489, 2902, + 33490, 35136, 20011, 0, 0, 0, 33131, 40628, 8187, 0, 0, + 22576, 33967, 0, 37288, 32176, 37289, 37018, 0, 14413, 28406, 15550, + 0, 0, 39271, 19853, 8514, 0, 0, 0, 0, 0, 20805, + 31733, 1237, 0, 8188, 0, 0, 0, 0, 0, 32762, 0, + 0, 0, 14267, 0, 0, 9028, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3476, 14268, 14269, 0, + 0, 26108, 0, 7428, 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, 0, 0, 0, 0, 0, 0, 0, + 8006, 0, 0, 0, 30405, 33491, 1851, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10276, 0, 32866, 22668, 37178, 0, 29271, 22528, 0, 26985, 15742, + 12152, 0, 0, 38386, 20966, 20739, 0, 8019, 6452, 0, 0, + 26783, 2551, 0, 3484, 9604, 20403, 28769, 550, 23905, 0, 40634, + 30806, 34063, 0, 20299, 38020, 36773, 0, 36902, 0, 26231, 10401, + 18897, 39484, 0, 0, 0, 14152, 39096, 0, 0, 19859, 36774, + 0, 31104, 451, 0, 0, 14780, 25561, 4601, 39422, 0, 0, + 0, 0, 0, 0, 0, 0, 10939, 34734, 0, 15080, 26510, + 15609, 0, 0, 23764, 0, 0, 19860, 0, 0, 0, 0, + 0, 29382, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 21541, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3485, 0, 33337, 0, 11932, 0, 0, + 5568, 16491, 0, 38157, 2437, 28354, 41110, 28136, 0, 31984, 0, + 33011, 0, 0, 13705, 36780, 0, 9061, 8843, 0, 0, 0, + 15084, 11567, 12346, 23013, 31164, 0, 35866, 0, 0, 20946, 0, + 25484, 20996, 0, 22880, 26314, 5868, 12347, 11146, 6571, 15568, 28483, + 0, 10723, 0, 27260, 0, 0, 0, 10549, 7648, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15613, + 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, 21377, 0, 0, 0, 3919, 0, + 0, 0, 0, 0, 0, 0, 0, 23981, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 31838, 10944, 27851, + 31109, 0, 9915, 25564, 19864, 0, 25874, 0, 31215, 0, 36786, + 0, 28637, 26633, 0, 0, 0, 23433, 0, 9794, 23610, 32104, + 0, 0, 0, 0, 28139, 18776, 0, 0, 23187, 5870, 0, + 0, 23328, 12782, 36787, 31695, 3005, 0, 0, 0, 0, 0, + 20159, 18572, 1145, 0, 0, 0, 0, 0, 0, 22262, 0, + 0, 0, 39111, 26634, 2797, 8221, 0, 0, 0, 0, 24732, + 27665, 0, 0, 41149, 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, 0, 0, 0, 0, 38891, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 22537, 0, 0, 4605, 0, 0, 0, + 0, 0, 8561, 6363, 0, 7890, 9363, 25971, 27925, 13037, 23024, + 0, 2262, 1064, 20742, 38842, 32717, 0, 14510, 27267, 13038, 16935, + 0, 4127, 16625, 0, 10485, 10974, 9113, 38790, 13723, 32555, 0, + 6332, 10009, 12788, 32556, 12375, 27318, 16535, 12193, 26247, 0, 0, + 28919, 40775, 27467, 0, 12376, 4028, 12608, 26638, 17972, 17680, 0, + 25877, 0, 201, 25662, 0, 29116, 5212, 0, 11342, 0, 25802, + 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, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 25682, 31168, + 14667, 11343, 16835, 18798, 0, 0, 28639, 38347, 0, 0, 0, + 23781, 0, 0, 0, 31596, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4433, 26515, 0, 0, 0, 0, 25803, 0, + 0, 19678, 24813, 0, 1981, 8440, 0, 24181, 14797, 5255, 2918, + 34799, 10432, 0, 12206, 0, 1788, 0, 19736, 0, 0, 0, + 6620, 344, 14060, 18810, 20275, 5829, 10489, 0, 12930, 0, 0, + 11183, 9009, 0, 0, 18811, 8069, 11705, 0, 38323, 0, 14001, + 27674, 25119, 0, 0, 0, 0, 0, 5222, 0, 30415, 1451, + 0, 0, 0, 0, 12791, 0, 0, 0, 0, 0, 0, + 5159, 14277, 32206, 1982, 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, 32000, 0, 1561, 0, 0, 0, 22996, 0, + 0, 25972, 947, 26176, 30743, 0, 2335, 18812, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 5223, 0, 9204, 37967, + 684, 8476, 0, 0, 2986, 12631, 17755, 0, 24511, 13178, 18821, + 6483, 28101, 34992, 36235, 0, 28513, 34993, 14064, 3934, 8073, 37601, + 26462, 0, 1819, 5327, 27132, 0, 0, 18610, 24185, 19118, 22999, + 0, 19901, 13747, 0, 0, 12217, 0, 0, 18822, 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, 0, 2965, + 20352, 19902, 13057, 0, 0, 2208, 0, 28073, 0, 0, 0, + 0, 0, 0, 0, 10495, 25813, 0, 40791, 15535, 8849, 27677, + 0, 0, 0, 0, 0, 29138, 38727, 33074, 27520, 3558, 36707, + 18684, 19981, 17840, 27771, 0, 0, 31628, 7277, 7900, 26692, 29139, + 2642, 37763, 0, 7901, 13185, 5720, 0, 0, 0, 32909, 5129, + 0, 0, 0, 39512, 0, 0, 0, 33707, 0, 0, 0, + 0, 21580, 7354, 19908, 20458, 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, 0, 0, 0, 0, 0, 0, + 18537, 6388, 0, 38731, 13192, 10135, 5233, 26073, 13193, 28703, 13494, + 22945, 0, 22898, 0, 40444, 0, 17702, 40883, 0, 40684, 0, + 11119, 0, 0, 0, 0, 31888, 0, 19915, 14685, 20358, 32230, + 0, 16028, 19916, 12954, 0, 0, 0, 21765, 0, 5721, 25961, + 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, 4038, 39518, 23793, 18914, 0, 40686, 0, + 0, 0, 41304, 10020, 28172, 9073, 0, 3870, 12653, 36004, 37112, + 0, 0, 0, 0, 0, 0, 0, 21766, 21298, 25755, 0, + 0, 0, 17924, 0, 0, 21660, 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, + 24075, 35006, 8270, 27483, 16031, 24841, 6181, 27333, 0, 0, 0, + 0, 0, 16992, 14537, 25694, 0, 0, 0, 38454, 0, 0, + 0, 32682, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19825, + 26956, 5758, 17351, 5506, 38114, 0, 19138, 2275, 0, 0, 286, + 0, 0, 13083, 0, 5928, 0, 0, 36460, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 36025, 5283, 21769, 0, + 37779, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 17067, 17009, + 11131, 0, 36914, 0, 0, 0, 0, 0, 0, 0, 21058, + 0, 0, 0, 0, 0, 0, 0, 3237, 0, 0, 0, + 0, 0, 0, 7753, 1641, 0, 0, 0, 0, 19436, 8485, + 12080, 0, 4622, 0, 36864, 0, 0, 36915, 0, 0, 0, + 33470, 0, 0, 0, 0, 33624, 11020, 18600, 0, 31964, 35770, + 0, 0, 0, 0, 0, 0, 0, 11023, 11080, 40837, 0, + 0, 0, 0, 0, 0, 8902, 29897, 31157, 18064, 9104, 39903, + 0, 0, 0, 0, 0, 0, 0, 18604, 0, 0, 0, + 41111, 0, 0, 0, 29621, 31928, 10414, 0, 0, 0, 0, + 37745, 0, 0, 0, 0, 0, 20998, 1956, 10877, 23537, 27293, + 23918, 40023, 35091, 9114, 0, 0, 0, 591, 15222, 0, 0, + 0, 0, 0, 0, 0, 10427, 12610, 10975, 34415, 0, 0, + 0, 0, 4240, 6083, 24551, 10779, 0, 0, 10298, 0, 0, + 41113, 0, 32220, 0, 0, 32041, 31884, 0, 0, 26050, 0, + 0, 0, 8749, 31889, 0, 0, 0, 8751, 0, 0, 18915, + 0, 8752, 15477, 0, 27205, 40360, 0, 29039, 34236, 21310, 0, + 0, 0, 0, 0, 0, 0, 19185, 28119, 0, 0, 2767, + 0, 0, 31334, 0, 36929, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 38178, 0, 35746, 31465, 10651, 24935, 30470, 3532, + 31802, 29296, 37874, 0, 35313, 12291, 11605, 7819, 0, 8106, 0, + 0, 12292, 33797, 0, 0, 28598, 0, 6439, 0, 0, 0, + 37547, 0, 0, 0, 5657, 0, 0, 40243, 28547, 0, 25478, + 33925, 37264, 7335, 869, 0, 24866, 0, 2123, 12714, 38422, 0, + 21805, 26506, 0, 0, 0, 17153, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9595, 9327, 0, 5042, 0, 0, 0, 0, 0, 0, + 0, 8317, 0, 0, 4454, 0, 34505, 27793, 27076, 0, 15694, + 39575, 29608, 24779, 6945, 0, 33269, 25560, 37020, 0, 0, 35808, + 35809, 33650, 7830, 8700, 0, 0, 0, 0, 10389, 36084, 0, + 10719, 0, 6732, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 33270, 7249, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 23168, 26113, 0, 6453, 5689, 16893, 35843, + 31686, 8842, 29612, 15328, 10722, 16092, 21542, 3486, 29095, 0, 29613, + 0, 0, 0, 0, 0, 16894, 20910, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 38593, 870, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 29385, 0, 37962, 6970, 27195, 15556, + 22364, 8208, 18764, 33012, 33013, 33396, 18765, 29317, 28484, 4461, 24725, + 0, 8209, 39427, 0, 33014, 41025, 7519, 20410, 33222, 0, 0, + 29622, 23297, 0, 22702, 0, 28203, 7120, 0, 0, 0, 11030, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 27799, 0, 1624, + 6067, 617, 26865, 33015, 32714, 7475, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4115, 27448, + 34905, 14929, 26788, 0, 36697, 7350, 0, 0, 15949, 5708, 0, + 19585, 13714, 0, 34404, 0, 0, 30554, 0, 0, 25913, 13715, + 37065, 30820, 6985, 24969, 14231, 7773, 18387, 6001, 22674, 0, 17546, + 10956, 18941, 0, 0, 0, 0, 0, 0, 0, 0, 5821, + 0, 0, 0, 4783, 20722, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30453, + 14719, 15383, 34405, 13466, 0, 0, 0, 0, 0, 0, 0, + 8920, 0, 25435, 28273, 26331, 0, 0, 3498, 0, 23337, 28364, + 0, 35234, 38186, 25035, 38668, 429, 41067, 28365, 38985, 31860, 0, + 3958, 13476, 41193, 8661, 31378, 0, 0, 19040, 12378, 0, 0, + 32886, 32887, 0, 0, 6267, 0, 0, 0, 0, 24547, 0, + 0, 0, 0, 0, 22888, 0, 18258, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 13724, 0, 11808, 0, 0, 0, 26173, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39507, + 115, 33701, 1340, 0, 35124, 21356, 40215, 0, 28065, 0, 32897, + 37388, 24740, 0, 0, 41072, 39436, 38770, 19042, 30744, 3700, 20171, + 0, 12207, 0, 28066, 35163, 31702, 29874, 17462, 33815, 0, 31382, + 0, 0, 0, 0, 0, 19590, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10695, 0, 0, 19043, + 6375, 4573, 2711, 18814, 28067, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 19044, 0, 0, 0, 0, 0, + 39913, 16954, 7537, 0, 14108, 16022, 35962, 11187, 4800, 0, 37406, + 1051, 29976, 27328, 5073, 31173, 4469, 21679, 5328, 41079, 10017, 0, + 22551, 4131, 0, 0, 6467, 22000, 0, 0, 40171, 0, 32907, + 38998, 24186, 33774, 0, 25988, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1355, 0, 8254, 0, 0, 0, 0, 0, + 17260, 0, 0, 0, 0, 0, 6859, 0, 35127, 27330, 0, + 26051, 0, 23205, 9849, 26052, 0, 8259, 19591, 0, 16699, 38618, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2643, + 0, 0, 0, 0, 30846, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 16700, 0, + 38326, 36359, 129, 32814, 0, 1365, 0, 0, 0, 0, 0, + 0, 2733, 0, 0, 22555, 4577, 17843, 23374, 0, 12650, 14073, + 6164, 7459, 35529, 29881, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 19963, 2271, 34206, + 0, 0, 0, 0, 0, 0, 0, 34846, 0, 29521, 0, + 0, 0, 39519, 0, 33086, 18961, 0, 17322, 0, 19595, 0, + 0, 32012, 0, 0, 27938, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27958, + 33983, 0, 0, 0, 0, 0, 17341, 37612, 0, 0, 38688, + 0, 28537, 33821, 30864, 35275, 22157, 19596, 29147, 22805, 0, 6471, + 24660, 35606, 0, 0, 0, 0, 30128, 2645, 0, 0, 14011, + 0, 0, 0, 0, 6869, 0, 0, 0, 0, 0, 0, + 2746, 36386, 18135, 0, 32303, 0, 23213, 0, 37777, 19047, 36461, + 24845, 0, 0, 0, 7484, 40805, 0, 0, 0, 0, 0, + 24369, 0, 0, 0, 21664, 30873, 27489, 0, 8274, 0, 0, + 20693, 20694, 30132, 2647, 38153, 0, 0, 0, 0, 0, 17005, + 17010, 0, 32016, 14746, 0, 21005, 20186, 0, 0, 11551, 0, + 27515, 0, 33586, 0, 0, 7485, 0, 33098, 0, 0, 0, + 0, 28541, 36661, 0, 38690, 0, 0, 0, 0, 0, 0, + 0, 23962, 21045, 0, 17994, 0, 0, 0, 19009, 32311, 8086, + 0, 18172, 0, 0, 0, 25966, 0, 11859, 0, 0, 0, + 0, 0, 29488, 0, 24376, 0, 11461, 0, 217, 0, 0, + 0, 0, 0, 0, 19425, 0, 21337, 0, 0, 0, 9792, + 21956, 0, 0, 32547, 0, 13867, 0, 0, 0, 0, 39291, + 0, 20838, 0, 0, 25903, 11112, 0, 41080, 11707, 0, 0, + 12218, 0, 0, 0, 35269, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 33263, 0, + 0, 16182, 37265, 14892, 0, 0, 0, 0, 0, 27373, 39275, + 0, 36647, 0, 8654, 0, 13143, 33188, 0, 0, 11638, 0, + 0, 27452, 0, 0, 3704, 10181, 0, 0, 0, 0, 17714, + 0, 0, 0, 0, 13221, 0, 8886, 0, 40600, 0, 0, + 0, 0, 0, 23407, 0, 0, 0, 0, 23644, 0, 6257, + 22913, 0, 0, 11069, 0, 0, 21702, 0, 23474, 5850, 5851, + 0, 17113, 0, 0, 33329, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 20845, 0, 39251, + 16183, 39654, 0, 6873, 1843, 22915, 33474, 36669, 4382, 17137, 0, + 0, 22188, 0, 0, 33437, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 23124, 0, 3058, 23490, 0, 0, + 35771, 0, 29070, 6724, 18376, 0, 13120, 0, 0, 0, 0, + 0, 38704, 37641, 0, 0, 0, 0, 0, 0, 0, 36996, + 0, 8805, 0, 10806, 0, 0, 0, 23420, 0, 20806, 11413, + 18485, 31818, 6838, 16511, 7511, 30356, 0, 4811, 0, 22354, 0, + 0, 0, 4886, 30994, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 8579, 0, + 0, 0, 4772, 0, 0, 23507, 16895, 24164, 23856, 15553, 1041, + 0, 27190, 0, 0, 0, 0, 0, 0, 0, 30545, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 26233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40759, 0, 0, 29190, 23687, 6358, 0, 0, 29806, 0, 0, + 30549, 0, 0, 0, 10946, 33223, 0, 26241, 39589, 0, 0, + 0, 0, 3548, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 40101, 31003, 3494, + 28362, 33025, 0, 15465, 0, 0, 26193, 26873, 27196, 0, 13822, + 0, 0, 0, 8590, 18905, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 33026, 0, 0, 0, 0, 0, 39590, 0, + 0, 0, 19393, 0, 27450, 15469, 0, 5887, 35341, 0, 28050, + 4146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4788, + 30169, 0, 0, 33040, 0, 0, 0, 0, 0, 0, 0, + 33811, 0, 0, 0, 0, 10490, 14951, 0, 0, 29208, 7533, + 0, 39595, 27124, 29923, 0, 0, 3701, 0, 29209, 38724, 10556, + 0, 24815, 30625, 0, 6621, 825, 0, 0, 0, 17686, 0, + 0, 0, 0, 0, 0, 0, 27675, 0, 0, 0, 0, + 0, 1602, 33050, 1662, 0, 4588, 0, 0, 0, 14678, 10436, + 0, 0, 0, 16024, 36580, 0, 0, 0, 0, 0, 0, + 0, 27409, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 21581, 0, 37101, 40677, 19910, 11001, 0, 0, + 17841, 0, 0, 0, 0, 0, 0, 0, 13600, 33345, 0, + 0, 0, 0, 34560, 0, 0, 0, 0, 0, 13757, 16220, + 27415, 13758, 16705, 0, 0, 41086, 0, 27138, 0, 0, 0, + 0, 0, 30646, 6339, 28082, 0, 0, 0, 0, 0, 0, + 0, 0, 32919, 25211, 0, 0, 0, 0, 0, 0, 0, + 19239, 0, 0, 0, 0, 23730, 0, 0, 0, 0, 0, + 0, 21059, 18166, 0, 0, 12675, 0, 0, 0, 20511, 0, + 0, 9137, 0, 0, 0, 0, 33798, 0, 0, 0, 33479, + 0, 0, 0, 0, 1947, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30558, 0, 0, 0, 0, 0, 15671, + 0, 0, 0, 30328, 0, 2590, 0, 19636, 15437, 0, 0, + 4450, 0, 0, 0, 32350, 20619, 0, 0, 0, 0, 0, + 0, 11874, 2838, 26851, 39150, 6946, 20013, 0, 26852, 24714, 27250, + 0, 4354, 34506, 0, 0, 10862, 23169, 39734, 11470, 0, 0, + 0, 0, 0, 0, 0, 39580, 0, 36845, 0, 0, 0, + 0, 0, 8618, 35042, 23014, 0, 0, 0, 0, 0, 0, + 0, 0, 35483, 3394, 12584, 0, 58, 0, 6211, 0, 28209, + 0, 14350, 0, 0, 0, 0, 0, 0, 23524, 17442, 33835, + 0, 17723, 0, 0, 0, 0, 37932, 33837, 4595, 22656, 0, + 15950, 0, 29117, 11376, 5120, 9660, 3141, 0, 26398, 12611, 0, + 0, 0, 0, 17550, 15195, 26812, 0, 6246, 36800, 23345, 0, + 32739, 0, 0, 0, 0, 0, 35963, 18530, 0, 0, 4149, + 0, 0, 0, 0, 16627, 8566, 0, 0, 0, 38353, 0, + 30642, 0, 0, 0, 12955, 0, 0, 0, 0, 36377, 7290, + 17342, 23719, 0, 0, 0, 35114, 0, 0, 0, 15917, 30653, + 0, 25107, 0, 0, 32741, 25108, 0, 0, 10892, 0, 0, + 0, 0, 6672, 3983, 0, 0, 26603, 0, 0, 40619, 6831, + 12540, 0, 0, 28655, 0, 21986, 0, 0, 0, 0, 0, + 0, 0, 13809, 24097, 0, 0, 0, 0, 23755, 14630, 0, + 0, 24631, 30097, 0, 0, 0, 21885, 27747, 0, 0, 0, + 35455, 0, 9169, 11929, 21997, 40749, 0, 13353, 0, 0, 31746, + 26460, 0, 35484, 39759, 0, 0, 0, 0, 0, 0, 0, + 19090, 0, 40016, 14930, 28675, 21894, 14656, 10958, 0, 39777, 0, + 0, 0, 0, 1092, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3641, 33768, 12379, 9296, 14511, 31115, 30117, 0, 24652, + 30559, 6481, 0, 27198, 0, 39167, 21162, 0, 0, 31867, 38994, + 39819, 0, 20853, 0, 0, 0, 0, 12931, 0, 0, 0, + 0, 0, 34983, 9804, 0, 0, 5636, 0, 12046, 14065, 0, + 0, 0, 0, 0, 0, 14966, 37764, 0, 0, 0, 0, + 0, 0, 12407, 0, 28078, 0, 12960, 0, 16076, 31129, 15887, + 1584, 14985, 0, 0, 1387, 0, 2749, 0, 40806, 17377, 0, + 0, 0, 7815, 23800, 34464, 0, 28742, 20588, 0, 0, 0, + 15602, 31466, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11081, 11082, 0, 7992, 0, 0, 34854, 9845, 0, 25272, 36262, + 7714, 15067, 0, 37843, 0, 0, 34116, 0, 31806, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31921, + 0, 0, 10171, 0, 0, 0, 0, 0, 0, 0, 0, + 11083, 0, 0, 10856, 23125, 7208, 0, 0, 0, 0, 12722, + 0, 0, 35458, 0, 0, 0, 0, 0, 30052, 20849, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 36149, 36269, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 12565, 30507, 27090, + 6534, 6782, 0, 30104, 30195, 17183, 0, 0, 0, 25257, 0, + 0, 4456, 33665, 40008, 40877, 0, 0, 0, 0, 0, 0, + 30485, 34220, 0, 12566, 3023, 0, 0, 0, 0, 0, 0, + 0, 0, 12336, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 26282, 29807, 0, 1659, 31839, 22463, 38506, 0, + 0, 11779, 0, 28312, 0, 10477, 0, 37673, 0, 31166, 0, + 18080, 0, 38507, 11173, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2697, 0, 0, 0, 0, 0, 0, + 0, 6971, 0, 3184, 0, 0, 0, 0, 0, 28211, 0, + 29322, 0, 0, 0, 0, 0, 0, 39778, 29195, 279, 40648, + 40880, 15384, 0, 26023, 29281, 18779, 0, 0, 0, 0, 26259, + 38472, 0, 0, 0, 3695, 0, 34643, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 20778, 10878, 0, + 0, 0, 0, 0, 0, 3434, 0, 0, 28037, 0, 0, + 0, 0, 0, 21130, 0, 0, 12380, 6704, 10815, 0, 4591, + 38401, 36174, 0, 32735, 0, 1502, 1065, 16205, 0, 3436, 0, + 23612, 0, 169, 26879, 0, 0, 3642, 0, 0, 0, 0, + 0, 0, 0, 0, 21813, 0, 12612, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 21961, 0, 31933, 0, + 0, 2640, 0, 43, 0, 0, 26814, 10433, 0, 12389, 3439, + 31869, 39295, 0, 0, 28416, 0, 19313, 0, 0, 22477, 0, + 0, 33529, 23829, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 32039, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 37389, 0, 0, 0, + 0, 0, 0, 13731, 32042, 18679, 0, 24187, 0, 2601, 0, + 0, 0, 34872, 12632, 26139, 18576, 0, 12219, 39832, 30510, 0, + 1356, 172, 35349, 173, 0, 0, 0, 0, 16955, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32118, + 0, 0, 0, 0, 14363, 28738, 0, 10301, 10499, 0, 0, + 38403, 38679, 35981, 31885, 0, 31886, 7202, 34427, 0, 0, 20779, + 0, 0, 0, 0, 0, 9120, 0, 0, 0, 0, 0, + 0, 0, 0, 37864, 0, 0, 0, 0, 0, 39972, 0, + 2817, 4163, 11845, 37995, 9732, 13070, 34207, 0, 0, 0, 32564, + 10500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 5236, 0, 0, 0, + 20216, 21661, 0, 19923, 0, 17847, 40117, 23057, 28549, 0, 0, + 0, 36456, 29030, 9809, 0, 0, 0, 0, 23960, 0, 18962, + 25820, 17848, 3510, 32936, 0, 0, 9812, 831, 19233, 14802, 0, + 0, 0, 7028, 0, 0, 0, 0, 0, 0, 0, 0, + 10452, 0, 19805, 0, 0, 33092, 22806, 0, 9954, 3234, 26358, + 11856, 0, 0, 0, 0, 0, 0, 0, 36388, 0, 13087, + 0, 0, 0, 0, 179, 0, 0, 0, 28538, 35361, 29934, + 0, 0, 0, 18297, 0, 41261, 0, 17014, 0, 22810, 33986, + 0, 21201, 6316, 0, 0, 16438, 0, 0, 0, 0, 0, + 38575, 14835, 39075, 12294, 23655, 0, 9937, 7609, 0, 9938, 10667, + 10403, 10765, 0, 0, 0, 38716, 3818, 28607, 23868, 0, 26554, + 36343, 0, 0, 24224, 0, 0, 12039, 0, 31870, 10492, 31876, + 31935, 10203, 16628, 0, 17286, 0, 0, 3281, 0, 0, 0, + 15107, 31664, 10043, 0, 0, 0, 0, 0, 6283, 0, 6231, + 30281, 0, 0, 6232, 38044, 14781, 0, 18547, 4017, 0, 39285, + 0, 0, 0, 23330, 15239, 12026, 16274, 0, 0, 0, 0, + 0, 0, 0, 8323, 0, 27201, 0, 6157, 0, 0, 0, + 0, 18532, 29855, 0, 0, 37093, 31383, 0, 29287, 0, 0, + 0, 0, 0, 0, 0, 9807, 0, 0, 0, 0, 0, + 28706, 23383, 0, 0, 0, 0, 0, 0, 17856, 17370, 0, + 34024, 0, 0, 0, 0, 8852, 29468, 10065, 3989, 0, 29990, + 0, 33341, 36760, 20620, 3538, 0, 11024, 6328, 0, 20770, 0, + 20898, 0, 18054, 0, 0, 0, 87, 32088, 0, 0, 0, + 15216, 27750, 25858, 0, 0, 0, 35847, 0, 0, 0, 0, + 35870, 32768, 0, 39428, 6296, 0, 0, 0, 0, 19359, 0, + 0, 0, 19077, 14932, 0, 0, 0, 23915, 18085, 0, 0, + 0, 0, 0, 0, 22678, 4606, 6796, 37194, 0, 0, 0, + 40581, 0, 31871, 11275, 20496, 28834, 0, 0, 0, 23052, 0, + 20178, 19400, 0, 9322, 0, 23707, 0, 17917, 20459, 30759, 2484, + 0, 11121, 28162, 0, 0, 14686, 26178, 19924, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 30651, 31661, 18197, 0, 0, + 1388, 30876, 0, 0, 0, 17114, 38946, 0, 36601, 10919, 30317, + 422, 12873, 0, 0, 0, 0, 41269, 38649, 1853, 24537, 34733, + 0, 0, 6147, 24780, 0, 0, 0, 0, 22524, 38550, 0, + 0, 26234, 9054, 1608, 35473, 8021, 0, 33184, 27091, 29566, 0, + 0, 6065, 0, 0, 29751, 32635, 31216, 22258, 11631, 0, 0, + 0, 0, 16273, 0, 0, 0, 27761, 4737, 26169, 40056, 38892, + 30617, 16275, 1309, 0, 0, 6175, 0, 0, 21131, 32810, 25248, + 29895, 30828, 36792, 19732, 37593, 39969, 0, 0, 0, 0, 0, + 0, 0, 27893, 0, 9124, 26483, 0, 38857, 22548, 0, 0, + 29572, 0, 3441, 22382, 2718, 36581, 27509, 0, 31298, 0, 22552, + 11440, 0, 8079, 0, 1611, 0, 0, 0, 0, 21096, 0, + 1612, 30858, 36587, 0, 21139, 9343, 0, 0, 0, 0, 0, + 17353, 0, 33199, 34449, 22970, 22245, 0, 0, 0, 0, 28334, + 0, 25329, 26269, 0, 0, 0, 0, 28335, 0, 0, 0, + 0, 0, 5099, 0, 19832, 0, 0, 0, 0, 0, 0, + 0, 0, 27172, 0, 0, 0, 0, 9043, 0, 9939, 27080, + 34832, 0, 9163, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 15359, 0, 0, 14414, 0, 22039, 2428, + 729, 33336, 2186, 0, 0, 17938, 88, 0, 0, 0, 20145, + 16287, 0, 0, 0, 32624, 0, 26511, 0, 0, 0, 0, + 0, 0, 0, 11966, 21338, 0, 0, 0, 0, 0, 0, + 0, 39339, 0, 17966, 38434, 0, 0, 37855, 0, 0, 33678, + 0, 0, 0, 0, 0, 0, 3349, 31072, 31555, 0, 0, + 932, 0, 0, 26382, 0, 0, 0, 37352, 20160, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6488, 0, 0, 2597, 0, 38276, 3396, 0, + 29513, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 35512, 0, 0, 0, 0, 0, 34909, 0, 0, 15667, 0, + 7630, 32898, 3397, 0, 0, 0, 0, 0, 0, 0, 0, + 16018, 0, 0, 0, 1713, 0, 18534, 0, 0, 0, 35965, + 20179, 33059, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9550, 0, 19119, 0, 0, 26343, 0, 0, 0, 0, 0, + 0, 0, 14525, 6338, 0, 0, 32121, 0, 0, 39600, 0, + 0, 1736, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 39601, 40445, 33941, 17560, 28249, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 16454, 14694, + 20217, 34138, 38736, 9734, 0, 0, 0, 0, 0, 0, 39860, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30870, + 25013, 2646, 0, 0, 0, 0, 0, 0, 0, 0, 25368, + 0, 37780, 0, 40807, 0, 0, 0, 19242, 9627, 0, 3322, + 0, 14415, 29311, 30412, 0, 0, 0, 39404, 0, 0, 21014, + 0, 0, 0, 0, 9946, 0, 0, 0, 0, 31576, 17898, + 0, 0, 34327, 33697, 0, 0, 0, 0, 11113, 8475, 33702, + 0, 31877, 0, 0, 0, 4802, 0, 0, 31893, 11009, 0, + 0, 0, 0, 0, 0, 34342, 0, 0, 0, 0, 0, + 0, 0, 0, 35719, 3469, 14862, 0, 41049, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13514, 35777, 0, 28719, 3594, + 445, 29716, 40893, 24618, 0, 0, 3595, 31728, 0, 0, 0, + 0, 0, 0, 0, 21326, 0, 4618, 0, 31268, 0, 4004, + 27943, 36604, 14558, 447, 0, 4430, 5682, 22092, 3603, 0, 24662, + 0, 34386, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 38551, 0, 0, 0, 0, 32369, 1059, 15827, 23508, 40009, 14492, + 24165, 20634, 37574, 0, 9644, 41145, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 24166, 0, 0, 0, 0, 0, 0, + 0, 0, 10949, 24644, 9873, 8214, 16533, 26166, 31556, 2062, 27101, + 36649, 9464, 0, 21546, 0, 0, 10796, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 20153, 0, 0, 0, 6986, + 32197, 37888, 33689, 24306, 6153, 16833, 23525, 16344, 8050, 23434, 3743, + 0, 0, 4654, 0, 0, 20659, 860, 0, 0, 0, 5399, + 0, 0, 0, 13725, 3758, 3643, 37372, 4727, 28051, 29202, 27400, + 38438, 8060, 0, 3107, 7814, 10777, 38439, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 13726, 38440, + 38606, 0, 0, 34543, 9880, 31297, 11185, 5743, 34986, 27894, 23702, + 12390, 33365, 23544, 15042, 0, 9881, 0, 0, 0, 0, 0, + 0, 0, 34551, 13748, 4730, 0, 29877, 38771, 22710, 18823, 39440, + 4036, 20180, 23926, 0, 17554, 0, 0, 0, 0, 0, 0, + 17262, 0, 0, 0, 6861, 28076, 14968, 0, 0, 14526, 28701, + 17700, 25861, 6217, 0, 37994, 39513, 0, 0, 0, 33893, 18115, + 0, 0, 5471, 0, 0, 38623, 33784, 24313, 13549, 22637, 0, + 0, 10039, 0, 0, 0, 0, 0, 37113, 9810, 0, 34090, + 0, 0, 34091, 2742, 13760, 14538, 34572, 6395, 0, 10736, 32421, + 34092, 0, 0, 0, 0, 18136, 13763, 36031, 24853, 8416, 7750, + 0, 15004, 24759, 0, 0, 0, 0, 14320, 0, 12509, 12438, + 0, 0, 0, 0, 0, 0, 31674, 22121, 0, 15864, 15687, + 0, 15688, 38495, 0, 0, 473, 0, 0, 3201, 11084, 21809, + 6833, 33333, 6631, 26752, 30318, 7575, 0, 0, 31490, 40727, 0, + 11085, 0, 0, 0, 0, 1653, 0, 30163, 614, 8690, 0, + 15355, 0, 0, 0, 0, 0, 0, 40518, 8009, 20624, 12771, + 30099, 37293, 0, 20771, 14895, 14484, 9265, 22957, 0, 0, 21278, + 0, 0, 0, 30223, 34507, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3862, 15828, 9912, + 0, 32488, 31534, 0, 4820, 29567, 25746, 0, 6700, 3093, 0, + 0, 0, 16796, 40754, 0, 39314, 41270, 0, 0, 15256, 38045, + 0, 37504, 24483, 0, 0, 0, 7180, 34065, 0, 12567, 0, + 2515, 0, 0, 0, 0, 0, 0, 0, 27263, 33876, 32873, + 29052, 10105, 32096, 26242, 30022, 10178, 16094, 2459, 6238, 21859, 34637, + 3350, 23045, 23517, 37738, 7878, 0, 0, 0, 0, 29550, 0, + 0, 0, 0, 0, 0, 0, 31073, 26761, 30150, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 28725, 0, 34224, 39781, 18783, 34536, + 14433, 0, 0, 5440, 0, 4024, 41107, 6987, 39499, 22368, 0, + 1631, 0, 5633, 0, 0, 0, 0, 0, 0, 0, 0, + 16276, 0, 35224, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 10227, 22074, 28759, 15269, 33525, 41031, 12614, 31379, 0, 0, + 4128, 0, 0, 22994, 34539, 30170, 0, 6364, 0, 22680, 3644, + 11938, 22836, 0, 4526, 38475, 0, 0, 0, 0, 30287, 0, + 0, 0, 0, 30259, 0, 0, 0, 6999, 30829, 514, 0, + 13248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2565, 0, 4033, 15737, 29022, 41013, 17238, 28505, 25810, 0, + 0, 22077, 22078, 0, 0, 0, 25984, 24029, 0, 0, 0, + 0, 0, 0, 0, 0, 41073, 0, 39820, 34544, 0, 13732, + 21205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 18978, 24745, 0, 5497, 17595, + 2809, 24188, 18577, 6015, 4731, 0, 0, 12462, 0, 0, 3010, + 27469, 41081, 0, 15277, 0, 0, 23928, 16956, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 27439, 37407, 38772, 16761, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 22943, 0, 0, 0, 0, 39003, + 32783, 0, 28739, 4803, 16366, 0, 33537, 27412, 38478, 2269, 0, + 0, 1151, 22414, 0, 0, 0, 0, 3371, 0, 0, 0, + 0, 0, 24070, 12227, 0, 0, 0, 0, 0, 38530, 0, + 16367, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29332, + 25816, 13879, 40352, 6801, 0, 2603, 14800, 28849, 1074, 0, 7284, + 17844, 38327, 28250, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 26054, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 39854, 29930, 0, 24367, 0, 4339, 0, + 0, 0, 28531, 1822, 30971, 0, 0, 22961, 0, 0, 0, + 0, 0, 0, 0, 20557, 2162, 0, 0, 15888, 0, 4865, + 25250, 832, 16320, 0, 0, 0, 0, 0, 0, 21417, 16993, + 0, 0, 0, 0, 0, 0, 13497, 18639, 17355, 18436, 9685, + 0, 0, 0, 2830, 0, 0, 0, 0, 0, 0, 32140, + 0, 2859, 0, 33096, 38740, 0, 0, 0, 0, 0, 27491, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 20105, 19002, 19243, 0, 0, 5761, 0, 0, 0, 0, 0, + 0, 0, 6036, 0, 30297, 37795, 19011, 0, 19013, 0, 0, + 0, 0, 16825, 0, 30256, 6047, 21195, 26457, 32975, 22516, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 19566, 0, + 36207, 0, 1925, 0, 40321, 0, 0, 3684, 0, 0, 0, + 0, 0, 0, 0, 20772, 30100, 0, 29663, 35140, 0, 0, + 0, 0, 0, 0, 11577, 0, 25344, 0, 35203, 0, 0, + 0, 0, 0, 30109, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 41117, 37353, 0, 0, 6, 0, 40018, 30286, + 0, 0, 0, 6743, 39970, 9854, 11522, 20273, 0, 0, 0, + 4237, 24178, 8921, 29514, 19733, 0, 0, 0, 28882, 0, 0, + 25442, 0, 0, 25443, 23346, 9805, 0, 0, 0, 32561, 29285, + 0, 0, 0, 0, 0, 0, 32672, 0, 0, 38619, 4804, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16382, + 0, 0, 0, 26647, 0, 16775, 17356, 0, 2675, 21608, 19003, + 0, 29469, 11731, 0, 0, 0, 0, 8896, 0, 0, 0, + 0, 0, 0, 0, 0, 23481, 36989, 0, 33129, 0, 0, + 0, 0, 37719, 423, 5045, 12125, 33865, 0, 0, 14878, 21706, + 0, 0, 0, 0, 0, 0, 0, 6441, 12307, 0, 0, + 0, 0, 0, 0, 21988, 8952, 989, 0, 15521, 34856, 18308, + 21239, 38501, 36270, 21396, 22216, 0, 8903, 2127, 10391, 25481, 9640, + 0, 0, 0, 1243, 31512, 14485, 11898, 1266, 0, 29362, 39316, + 0, 0, 35848, 4457, 0, 1811, 0, 0, 0, 0, 8910, + 0, 0, 7181, 0, 0, 34791, 33572, 0, 0, 10587, 0, + 0, 38149, 2626, 10683, 0, 29276, 0, 0, 0, 39429, 33225, + 33553, 0, 0, 39212, 0, 0, 30368, 0, 0, 0, 15086, + 0, 0, 0, 0, 31110, 0, 0, 18785, 0, 39289, 25485, + 3358, 8051, 0, 6988, 28915, 28823, 0, 14720, 3040, 28491, 5634, + 0, 40928, 0, 0, 15526, 29900, 0, 15527, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 25486, 37810, 10429, 40964, 4527, 24550, 0, 0, 0, 20826, 6706, + 33581, 15531, 32393, 0, 0, 0, 0, 0, 0, 0, 0, + 6365, 15223, 0, 36344, 0, 0, 0, 40779, 0, 0, 0, + 0, 11523, 0, 22376, 0, 17239, 0, 1985, 8738, 14515, 15386, + 0, 10983, 34988, 28836, 0, 24504, 25492, 18319, 11823, 12209, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 39821, 0, 28841, 39598, 15279, 0, 0, 0, 0, + 0, 0, 34873, 0, 28866, 10604, 0, 0, 0, 17596, 0, + 2384, 0, 0, 0, 20949, 40967, 0, 5498, 0, 13393, 22390, + 0, 9469, 7098, 13187, 13545, 21861, 38193, 0, 0, 0, 0, + 22395, 5264, 0, 24827, 17483, 20831, 16425, 0, 0, 0, 0, + 7637, 0, 0, 0, 11911, 0, 0, 0, 15834, 0, 36245, + 27470, 13199, 0, 0, 0, 0, 0, 0, 0, 19234, 0, + 18846, 0, 0, 0, 0, 0, 8757, 25225, 0, 0, 22807, + 0, 18437, 0, 0, 0, 39174, 32422, 0, 0, 17991, 17493, + 26258, 2026, 17364, 0, 0, 0, 0, 0, 0, 32925, 8759, + 20464, 17495, 0, 0, 15006, 40036, 0, 0, 0, 0, 15396, + 0, 6037, 0, 39015, 0, 27222, 12104, 18366, 9461, 38187, 32418, + 23639, 0, 26604, 0, 0, 36208, 13810, 0, 0, 26623, 26624, + 25769, 0, 0, 0, 0, 31840, 0, 0, 0, 0, 0, + 15702, 0, 24803, 0, 8735, 644, 0, 1342, 23703, 0, 0, + 0, 0, 0, 0, 1714, 645, 0, 41303, 22632, 0, 12059, + 0, 0, 0, 0, 0, 0, 0, 648, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 21740, 0, 3198, + 0, 22311, 0, 0, 8087, 29761, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 22567, 22962, 0, 0, 3514, 0, 0, + 33951, 23456, 31321, 0, 0, 39615, 5646, 4479, 36730, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4480, 0, 0, 5647, 40595, 0, 41024, 4550, 0, 0, 22100, + 34470, 23463, 25469, 12754, 0, 39625, 24583, 37701, 0, 27026, 0, + 0, 0, 10208, 0, 0, 0, 0, 0, 0, 0, 30041, + 0, 0, 1647, 0, 15232, 0, 0, 0, 4309, 0, 4424, + 0, 36200, 27046, 20956, 25644, 0, 34767, 3404, 0, 4348, 0, + 0, 8891, 20001, 0, 12439, 0, 0, 0, 0, 0, 0, + 0, 8793, 38198, 0, 0, 0, 1034, 0, 0, 0, 0, + 0, 33158, 16120, 0, 5959, 0, 0, 29493, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 27534, 0, + 0, 0, 5035, 0, 0, 0, 0, 0, 0, 0, 17032, + 0, 36628, 13345, 0, 0, 28418, 24867, 36144, 37492, 13662, 0, + 23661, 34896, 34259, 0, 0, 24357, 0, 0, 0, 0, 0, + 0, 0, 22250, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 12716, 0, 29718, 0, 29046, 0, 0, + 0, 0, 0, 6651, 2781, 12724, 3604, 12885, 27376, 0, 0, + 0, 0, 0, 0, 0, 0, 28461, 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, + 39413, 0, 37559, 0, 0, 10858, 0, 17801, 0, 0, 0, + 38250, 0, 4015, 0, 0, 0, 24669, 1021, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 11331, 15717, 26758, 0, 13695, 0, 30486, 0, + 0, 0, 10863, 0, 0, 0, 0, 0, 0, 38259, 38072, + 34866, 0, 3549, 14345, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 17663, 36939, 0, 0, 0, 0, 1445, 0, + 15844, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3877, + 34203, 40643, 0, 24173, 32376, 0, 37507, 31287, 13467, 32552, 26170, + 0, 39782, 0, 0, 3757, 0, 1411, 30556, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5401, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 37356, 29916, 0, 0, 3041, 0, 0, + 0, 11810, 23827, 0, 30733, 0, 0, 0, 0, 0, 0, + 0, 36794, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5712, 0, 4987, 0, 0, 36795, 14355, 29918, 38075, + 0, 0, 11824, 0, 26177, 0, 0, 12040, 0, 0, 0, + 0, 0, 0, 0, 34989, 0, 0, 0, 0, 32399, 0, + 0, 0, 0, 32400, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5717, 0, 14361, 0, 0, + 0, 11834, 0, 15334, 36802, 0, 0, 17287, 0, 0, 0, + 4106, 0, 3508, 0, 12060, 0, 36808, 0, 37767, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 28524, 38106, 0, 0, + 0, 21590, 40357, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 32305, 0, 0, 0, 0, 0, 0, + 0, 26901, 0, 15589, 23395, 29834, 7231, 4807, 0, 0, 29980, + 2490, 2176, 32522, 22270, 14081, 23221, 26455, 21690, 20866, 0, 24232, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1158, 0, 0, 0, 0, 0, 1170, + 721, 1467, 40705, 20869, 30776, 10207, 0, 0, 0, 0, 0, + 0, 0, 13889, 0, 39326, 0, 0, 0, 24129, 0, 0, + 0, 0, 0, 0, 10251, 29583, 38176, 26794, 4818, 11455, 25543, + 38039, 21372, 0, 0, 0, 0, 0, 0, 0, 32067, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 24926, 12493, 36123, + 17027, 19491, 26469, 10055, 4871, 15054, 12510, 2108, 18474, 7825, 36743, + 15758, 0, 0, 0, 0, 0, 32529, 0, 0, 0, 0, + 37834, 0, 24239, 11670, 23063, 0, 0, 0, 0, 0, 16857, + 22246, 27235, 14395, 35440, 39252, 3719, 0, 31675, 0, 11021, 25506, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11398, + 24094, 39400, 36406, 31729, 23995, 12541, 39262, 11482, 0, 36997, 41005, + 19706, 0, 0, 0, 26777, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 24947, 0, 0, 0, 0, + 0, 0, 13232, 10384, 0, 29609, 10392, 30889, 35814, 22143, 0, + 0, 30995, 23756, 17168, 35461, 4182, 33652, 30696, 0, 0, 0, + 0, 0, 8650, 0, 37169, 0, 0, 38562, 8401, 23675, 15257, + 16897, 26625, 9417, 0, 22718, 0, 0, 16898, 0, 11027, 0, + 0, 29799, 27563, 0, 11093, 16899, 0, 0, 18565, 0, 0, + 0, 5304, 0, 41298, 26235, 0, 26551, 0, 7771, 14647, 29623, + 13453, 24051, 8554, 40760, 11507, 26243, 0, 0, 28667, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 30053, 0, 18193, 0, 3351, + 31032, 41256, 37357, 0, 40209, 0, 25130, 31749, 24795, 0, 8724, + 0, 0, 0, 0, 0, 0, 23189, 33520, 0, 0, 0, + 0, 8361, 25084, 3822, 19879, 0, 0, 0, 0, 0, 0, + 26640, 24804, 0, 0, 24026, 2266, 0, 0, 17240, 0, 30417, + 16691, 33236, 16501, 0, 0, 27126, 39296, 7271, 0, 0, 0, + 0, 0, 39822, 0, 0, 0, 0, 36178, 0, 17263, 0, + 0, 0, 0, 20548, 30752, 0, 36360, 25202, 0, 0, 0, + 0, 0, 24916, 0, 0, 0, 0, 19175, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5036, 0, + 36263, 1133, 8644, 0, 30981, 34491, 20239, 0, 8528, 24619, 39405, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9102, 29610, 0, 18058, 29083, 4390, 35462, 7341, 22921, 1244, + 0, 807, 0, 0, 0, 0, 0, 0, 0, 0, 22331, + 0, 28098, 0, 0, 27796, 30605, 32713, 0, 0, 0, 0, + 0, 10278, 34518, 0, 0, 0, 0, 0, 0, 0, 0, + 35475, 38159, 36480, 21017, 0, 0, 0, 0, 0, 37963, 0, + 29318, 31557, 13530, 34398, 0, 0, 0, 0, 0, 0, 0, + 21167, 28728, 34645, 29325, 39783, 3773, 28957, 0, 0, 0, 0, + 38510, 0, 0, 0, 0, 0, 0, 20253, 0, 0, 31288, + 36225, 34646, 16605, 0, 0, 0, 0, 22927, 0, 11939, 9891, + 20749, 4528, 0, 0, 15703, 3778, 0, 36856, 0, 0, 0, + 40656, 0, 0, 27890, 0, 0, 0, 0, 0, 0, 36287, + 0, 0, 41197, 25914, 18341, 10128, 30838, 19888, 10984, 17241, 0, + 20174, 0, 672, 13048, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 25091, 0, 0, 0, 19889, 0, 20750, 10710, + 11116, 20039, 26196, 0, 0, 26387, 3043, 0, 40673, 0, 39441, + 21432, 0, 0, 0, 0, 0, 12633, 0, 0, 15392, 39299, + 0, 0, 0, 0, 0, 5130, 17729, 38680, 8963, 16582, 11151, + 4073, 0, 13062, 16025, 0, 0, 0, 0, 26497, 0, 0, + 0, 0, 0, 0, 3214, 28740, 0, 11004, 19919, 22226, 38684, + 2923, 0, 8444, 0, 0, 35997, 0, 28251, 0, 0, 0, + 33714, 12655, 16455, 0, 0, 0, 35531, 0, 0, 20183, 0, + 20362, 0, 0, 0, 4691, 0, 0, 16429, 0, 0, 34343, + 0, 0, 20070, 0, 0, 0, 36660, 2346, 13090, 0, 0, + 27909, 0, 0, 0, 0, 0, 0, 34453, 0, 0, 14768, + 0, 0, 0, 6990, 0, 0, 7673, 0, 7675, 0, 0, + 0, 0, 0, 0, 9493, 19326, 0, 17756, 0, 0, 0, + 0, 3685, 0, 16900, 0, 0, 0, 0, 0, 39502, 0, + 0, 33060, 0, 0, 3838, 0, 12414, 0, 0, 0, 22446, + 0, 0, 0, 0, 13663, 0, 0, 0, 0, 40050, 0, + 0, 0, 0, 0, 33334, 0, 0, 0, 15870, 0, 0, + 0, 0, 0, 0, 0, 14097, 0, 11088, 0, 0, 23758, + 0, 0, 0, 0, 2457, 0, 0, 23298, 30361, 19574, 0, + 6264, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15593, + 0, 5054, 0, 21082, 0, 10677, 0, 0, 0, 0, 0, + 0, 0, 16288, 6741, 23688, 0, 36164, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 18569, 11632, 0, 0, 0, 8215, 19578, 0, 40013, 0, 0, + 36605, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 16568, 12366, 35893, 18246, 4521, 0, 21022, 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, 29971, 32553, 0, 0, 0, 1501, 4156, 31376, + 0, 14435, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 32809, 22473, 40657, 25714, 0, 25981, 40881, 0, 39345, + 0, 0, 41069, 24737, 0, 3645, 0, 39800, 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, 25021, 23696, 34174, + 3042, 10430, 25602, 0, 0, 0, 14438, 31380, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3646, 15874, 0, 4608, + 25673, 16143, 3503, 41074, 13379, 0, 37090, 29823, 19890, 4918, 27600, + 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, 7734, 9032, + 6158, 2577, 19679, 2804, 1416, 37391, 0, 0, 30325, 41075, 0, + 40786, 0, 4086, 30379, 30202, 0, 24915, 0, 0, 30380, 0, + 32040, 0, 0, 0, 0, 0, 0, 36523, 13172, 0, 0, + 30753, 29133, 25957, 0, 23357, 26128, 37409, 12401, 6306, 2811, 29878, + 0, 0, 18274, 0, 40541, 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, 25674, + 0, 0, 34669, 9205, 0, 17265, 2525, 0, 0, 0, 5718, + 0, 38677, 22929, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 18579, 0, 39846, + 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, + 17477, 0, 0, 0, 19173, 0, 0, 0, 0, 0, 0, + 0, 6802, 0, 0, 14980, 17306, 16377, 0, 25675, 9121, 2734, + 33539, 0, 0, 39602, 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, 33982, 1870, + 3285, 0, 40353, 10517, 0, 0, 598, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 6020, 0, 0, 38685, 9811, 0, + 0, 1578, 16227, 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, + 13883, 0, 0, 0, 0, 0, 0, 0, 8334, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 19983, 0, 37439, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 31765, 0, 22716, 27688, 0, 0, 0, + 0, 0, 0, 5504, 0, 0, 0, 4303, 5599, 12244, 2747, + 0, 0, 0, 40693, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2217, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 13323, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29697, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17012, + 0, 0, 0, 0, 23880, 0, 0, 0, 4304, 0, 0, + 0, 0, 0, 0, 0, 0, 28540, 0, 5929, 0, 13092, + 0, 0, 0, 0, 0, 0, 0, 39604, 15001, 0, 20562, + 0, 19147, 0, 0, 0, 0, 0, 786, 0, 0, 0, + 0, 0, 0, 41135, 0, 0, 0, 0, 0, 0, 0, + 38916, 0, 0, 37126, 0, 0, 789, 0, 0, 19274, 31784, + 11070, 35721, 6824, 9089, 29775, 39077, 0, 24633, 27997, 17635, 24717, + 18067, 9418, 16498, 29678, 4915, 18575, 11529, 27199, 13380, 41211, 8333, + 30633, 0, 0, 16039, 6494, 27792, 23280, 34829, 0, 0, 0, + 27068, 0, 8330, 0, 0, 5389, 35033, 0, 0, 0, 23759, + 0, 26425, 2903, 20520, 0, 20525, 0, 0, 0, 21123, 0, + 0, 4497, 0, 21543, 38837, 2458, 0, 0, 27797, 21548, 4462, + 0, 0, 15087, 0, 26431, 0, 40210, 6744, 231, 1094, 0, + 0, 29196, 0, 22581, 31991, 24650, 26791, 0, 0, 0, 28780, + 0, 0, 0, 19394, 22658, 0, 29210, 25446, 0, 0, 0, + 0, 0, 0, 0, 4537, 0, 0, 12221, 7776, 31390, 13547, + 16583, 38355, 22391, 2290, 0, 21743, 0, 2822, 0, 0, 0, + 0, 0, 0, 0, 0, 19410, 9684, 21484, 3713, 2860, 0, + 0, 0, 21061, 0, 0, 31918, 14259, 12440, 39194, 0, 0, + 0, 0, 29541, 0, 0, 19815, 37721, 0, 39902, 29995, 25705, + 32989, 31514, 0, 29545, 21708, 0, 30484, 12887, 0, 7578, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1491, 0, 0, 0, 0, 35476, 0, 0, 5986, + 12156, 8431, 0, 0, 12898, 14193, 0, 0, 0, 0, 0, + 15132, 0, 0, 0, 25067, 0, 20994, 20719, 33681, 27829, 26720, + 15830, 25075, 30612, 0, 0, 0, 5997, 20997, 0, 25749, 8913, + 6297, 0, 21400, 0, 0, 2984, 10415, 34639, 0, 0, 0, + 0, 0, 29816, 2082, 0, 10959, 36652, 0, 26987, 4025, 0, + 0, 0, 0, 0, 0, 0, 0, 32647, 19819, 17045, 29113, + 0, 12915, 0, 0, 0, 39591, 9273, 9393, 0, 23526, 0, + 7436, 37196, 38987, 30734, 6877, 2669, 31600, 0, 9194, 0, 0, + 0, 0, 0, 0, 25085, 11811, 0, 32891, 36346, 0, 28501, + 30252, 8063, 13828, 22622, 0, 0, 0, 26792, 37091, 15719, 0, + 22629, 32899, 21846, 32402, 13173, 33703, 0, 1343, 0, 0, 0, + 21001, 0, 17592, 0, 22682, 0, 0, 0, 14172, 0, 0, + 0, 28430, 34670, 124, 0, 0, 32664, 23930, 31299, 28843, 0, + 15098, 0, 0, 0, 0, 0, 16148, 0, 0, 0, 0, + 0, 0, 16537, 0, 21208, 0, 0, 6309, 27299, 0, 13489, + 21582, 0, 37102, 0, 0, 0, 0, 0, 2448, 0, 13490, + 0, 11243, 30944, 35128, 6864, 9471, 11152, 13395, 0, 0, 0, + 0, 0, 0, 0, 16812, 0, 26388, 36672, 0, 5473, 9372, + 21689, 0, 28256, 32566, 0, 25818, 2886, 0, 0, 0, 0, + 0, 0, 25734, 0, 37816, 0, 7590, 13202, 33717, 0, 0, + 0, 31896, 27301, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 32921, 17366, 0, 0, 29698, 0, 0, 20104, + 2832, 11957, 0, 0, 40412, 37786, 0, 0, 0, 0, 0, + 0, 0, 0, 16397, 0, 34454, 5332, 32524, 37689, 29528, 1001, + 25891, 32331, 5949, 22606, 22665, 0, 28422, 0, 13369, 35123, 0, + 37768, 0, 25354, 24076, 23217, 5843, 23218, 0, 0, 10047, 37529, + 36721, 12264, 8340, 9859, 27010, 0, 24676, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 30973, 0, 0, 39179, 22905, 34351, + 9076, 14594, 29335, 0, 0, 0, 0, 0, 6892, 0, 0, + 34151, 17955, 1171, 0, 0, 0, 40821, 10628, 0, 6714, 0, + 6558, 33849, 0, 26264, 0, 26265, 34921, 25176, 0, 0, 0, + 0, 0, 0, 0, 30076, 0, 0, 1750, 33615, 29965, 3305, + 0, 6271, 35722, 0, 0, 0, 3076, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 14733, 12119, 0, 38871, 1007, 0, 29297, + 0, 0, 0, 0, 22322, 0, 0, 0, 0, 8173, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30139, 0, 32159, 21322, 18371, 0, 0, + 40609, 0, 39264, 27556, 40894, 7715, 6495, 22602, 34492, 27915, 24620, + 6929, 23751, 0, 23811, 0, 2154, 34117, 0, 0, 0, 0, + 0, 0, 40513, 0, 0, 19613, 13431, 0, 0, 0, 0, + 0, 38645, 22525, 31515, 34622, 7514, 21531, 0, 39715, 0, 28341, + 0, 35816, 0, 16739, 33653, 0, 35817, 0, 0, 30539, 0, + 0, 12143, 3127, 5981, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 37560, 0, 31680, 0, 18225, 28342, 0, + 0, 0, 0, 0, 0, 0, 0, 1022, 32032, 34630, 0, + 4712, 0, 15258, 0, 0, 24359, 18509, 1087, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 38709, 4695, 31217, + 33504, 3135, 10220, 14916, 0, 3223, 2557, 2791, 39492, 34069, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8717, 3185, 35216, 0, 0, 0, 0, 3956, 24796, + 33027, 0, 38718, 15492, 0, 14935, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 24797, 0, 19880, 35239, 41011, + 23083, 0, 27122, 0, 0, 0, 0, 27321, 2709, 0, 0, + 6370, 0, 9765, 18815, 34332, 0, 0, 0, 0, 21469, 1715, + 0, 0, 0, 0, 0, 0, 0, 29926, 0, 0, 0, + 0, 0, 0, 21358, 11297, 23791, 0, 0, 0, 0, 0, + 0, 32048, 0, 0, 18147, 0, 0, 0, 0, 17428, 0, + 35895, 0, 17203, 27768, 0, 0, 5069, 0, 0, 30859, 0, + 0, 4448, 0, 0, 0, 14303, 10658, 0, 36999, 0, 15927, + 0, 0, 0, 10176, 8651, 7411, 0, 0, 15936, 0, 0, + 9526, 3544, 0, 0, 14305, 0, 0, 28135, 0, 0, 5987, + 0, 0, 0, 0, 0, 0, 0, 28166, 0, 0, 0, + 24259, 0, 0, 0, 9536, 0, 0, 0, 0, 0, 0, + 40499, 0, 0, 29423, 0, 0, 37740, 0, 0, 0, 0, + 0, 41161, 0, 0, 0, 0, 0, 0, 0, 31220, 4740, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39785, + 0, 0, 0, 0, 27543, 0, 6154, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 30622, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3745, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 25722, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 12394, 0, 0, 0, 0, 0, 5876, 0, + 2336, 0, 15622, 0, 0, 30634, 0, 0, 0, 2270, 0, + 0, 19264, 21972, 0, 0, 0, 0, 0, 0, 25884, 0, + 0, 0, 30643, 0, 0, 0, 0, 0, 25887, 0, 0, + 13880, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 30647, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2218, 17000, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 37789, 0, 0, 0, 0, 37817, 0, + 0, 3250, 0, 0, 26226, 0, 0, 0, 0, 0, 0, + 0, 10859, 26191, 29996, 0, 7832, 0, 24332, 33494, 0, 0, + 0, 4083, 8194, 0, 0, 0, 35849, 6150, 8026, 8027, 38251, + 23127, 0, 18070, 0, 0, 0, 26192, 22218, 0, 0, 0, + 36165, 19215, 11227, 36279, 1061, 36940, 26552, 0, 33017, 3955, 0, + 0, 0, 0, 0, 0, 0, 0, 26553, 5817, 0, 0, + 0, 35896, 0, 3101, 8846, 18388, 22885, 37889, 34647, 20653, 0, + 28140, 0, 0, 0, 0, 0, 0, 0, 14162, 0, 27854, + 22150, 0, 34204, 26024, 6748, 0, 0, 4157, 33042, 0, 29869, + 8922, 33883, 0, 16167, 0, 18095, 0, 5064, 38441, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 36101, 27806, 0, + 37197, 30118, 30119, 0, 0, 482, 25195, 1986, 5070, 0, 38445, + 10781, 0, 0, 0, 11708, 0, 0, 0, 0, 0, 0, + 18608, 0, 0, 0, 0, 18196, 25579, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5225, 19891, 32044, 31025, 10019, 40792, + 39226, 26046, 4861, 17266, 0, 5745, 17471, 9072, 0, 0, 0, + 22384, 0, 0, 0, 36357, 0, 10818, 0, 6582, 31391, 0, + 0, 0, 0, 0, 0, 0, 22751, 10496, 0, 18396, 20674, + 7483, 18911, 38288, 2007, 5835, 19541, 0, 40487, 18833, 22132, 6590, + 2151, 0, 0, 0, 0, 3144, 19465, 0, 0, 0, 0, + 0, 0, 0, 0, 31634, 0, 0, 0, 0, 0, 0, + 205, 39918, 0, 21029, 30173, 10446, 0, 0, 6593, 30288, 39919, + 2463, 17307, 27477, 0, 0, 0, 2464, 0, 27685, 0, 6594, + 0, 11886, 0, 0, 0, 0, 0, 0, 0, 12961, 21745, + 5237, 8268, 12071, 11851, 4418, 0, 36659, 25819, 29522, 0, 0, + 0, 0, 0, 0, 0, 18349, 0, 0, 28102, 18129, 19411, + 5838, 0, 0, 0, 22176, 0, 18130, 0, 0, 17347, 0, + 21768, 0, 0, 0, 17852, 26289, 0, 7551, 0, 0, 0, + 0, 26290, 0, 0, 18140, 38741, 0, 1724, 17006, 0, 0, + 27698, 25214, 12972, 40696, 0, 0, 18143, 18144, 19986, 0, 27492, + 0, 0, 0, 0, 18148, 0, 0, 11944, 0, 0, 0, + 0, 0, 0, 18167, 12975, 24861, 0, 0, 0, 21749, 14142, + 3128, 0, 0, 0, 0, 0, 39108, 24431, 0, 24433, 7012, + 0, 0, 26058, 0, 0, 0, 0, 0, 909, 0, 7424, + 0, 0, 7515, 7452, 0, 0, 0, 0, 7372, 15678, 0, + 0, 0, 0, 37987, 11793, 0, 7458, 0, 0, 0, 6595, + 0, 0, 0, 0, 21989, 21710, 22167, 5196, 5108, 89, 0, + 29319, 3026, 342, 19792, 21018, 0, 0, 2042, 37338, 32098, 19357, + 0, 0, 22834, 0, 6536, 0, 5400, 0, 0, 33309, 21351, + 9949, 4029, 27429, 19430, 0, 0, 0, 0, 0, 30418, 35950, + 5924, 34333, 0, 31122, 28113, 0, 202, 16362, 21023, 0, 24667, + 20276, 21874, 2272, 2291, 0, 0, 0, 16451, 29333, 35273, 0, + 21415, 0, 27431, 0, 0, 0, 0, 4419, 0, 13085, 0, + 0, 8480, 0, 0, 0, 13209, 9813, 0, 38635, 0, 19182, + 0, 0, 12126, 9641, 0, 0, 0, 12777, 12453, 0, 0, + 33872, 0, 7725, 0, 0, 0, 1269, 23301, 0, 0, 37575, + 269, 5532, 0, 0, 6964, 7615, 0, 0, 14648, 21281, 30110, + 0, 26630, 8037, 31986, 24790, 22989, 30369, 18081, 19305, 40096, 814, + 0, 37339, 0, 0, 0, 0, 1045, 19358, 0, 12733, 0, + 34839, 0, 15727, 13536, 0, 1785, 0, 0, 0, 19218, 9612, + 6794, 39786, 0, 0, 0, 39216, 6991, 40165, 456, 0, 0, + 0, 39217, 7732, 6300, 21406, 2142, 6576, 26126, 26036, 1329, 0, + 0, 0, 39802, 38988, 2143, 0, 0, 0, 14946, 34132, 0, + 0, 0, 31872, 0, 40668, 557, 34990, 3866, 28507, 23704, 0, + 21148, 37392, 7006, 12932, 35951, 32661, 0, 21568, 0, 0, 1755, + 0, 0, 0, 0, 9834, 32900, 5925, 0, 0, 14443, 28370, + 6010, 8074, 20258, 27133, 33890, 29134, 37410, 0, 0, 32908, 8075, + 39834, 21293, 33891, 34804, 0, 7784, 40990, 40111, 33775, 0, 0, + 0, 40172, 0, 16238, 0, 36524, 8622, 16150, 0, 6852, 30635, + 19739, 0, 0, 0, 11263, 3868, 0, 28377, 28516, 28378, 28517, + 33981, 0, 8964, 12825, 0, 2008, 28518, 37627, 0, 0, 0, + 0, 0, 0, 28519, 0, 0, 0, 0, 4214, 0, 0, + 33340, 10444, 28324, 0, 0, 0, 0, 20677, 3734, 28146, 38289, + 18841, 38773, 19230, 33708, 12957, 26257, 0, 33709, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 13286, 0, 0, + 0, 830, 19334, 0, 29648, 31894, 0, 0, 25459, 0, 26773, + 40118, 0, 12962, 8269, 5501, 0, 0, 36593, 14450, 0, 36015, + 676, 0, 26059, 28259, 0, 6711, 33090, 0, 0, 0, 11364, + 0, 0, 0, 25606, 21302, 40120, 9686, 0, 19236, 0, 0, + 0, 0, 0, 0, 0, 39447, 33718, 0, 39448, 0, 14997, + 14452, 0, 0, 37613, 18642, 0, 0, 2029, 0, 0, 25461, + 33099, 0, 0, 0, 0, 0, 31769, 19149, 0, 0, 0, + 8760, 0, 0, 41123, 10085, 0, 13355, 25770, 24261, 25118, 22194, + 37741, 3094, 8039, 22240, 0, 0, 19794, 0, 0, 28911, 0, + 15480, 31850, 0, 0, 0, 0, 0, 6795, 0, 35897, 0, + 0, 28223, 0, 31996, 14722, 0, 30623, 0, 35933, 0, 37393, + 0, 558, 30124, 28508, 22199, 0, 0, 0, 1790, 0, 0, + 37940, 37941, 6513, 25667, 30636, 0, 0, 0, 0, 0, 30760, + 9676, 0, 4970, 32010, 0, 0, 11941, 14745, 28147, 0, 28254, + 0, 0, 18539, 562, 37431, 39354, 9683, 0, 15916, 8569, 5131, + 0, 0, 0, 32301, 38546, 26060, 0, 15395, 2088, 2023, 0, + 0, 28260, 0, 37450, 2089, 14281, 14282, 0, 14805, 15009, 0, + 20875, 38542, 28893, 30710, 31982, 32998, 0, 0, 0, 25811, 12211, + 0, 0, 33077, 0, 0, 6598, 40851, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 37623, 24335, 8040, 22365, 22195, + 0, 36283, 0, 10593, 41066, 0, 8916, 6212, 10324, 31112, 0, + 22129, 0, 0, 28052, 15224, 21569, 10237, 7805, 7007, 35259, 0, + 0, 29516, 6218, 39005, 25916, 0, 0, 0, 20678, 28080, 0, + 16665, 0, 23123, 6867, 40689, 35276, 0, 0, 0, 32465, 9494, + 25295, 18175, 0, 0, 358, 0, 0, 2612, 0, 6699, 24475, + 15651, 33496, 11326, 34901, 39203, 29549, 1042, 0, 0, 257, 0, + 15194, 0, 15654, 22255, 36905, 341, 19816, 20635, 0, 0, 0, + 0, 0, 8121, 24360, 16193, 6265, 28726, 0, 0, 23822, 35086, + 30811, 10950, 20643, 10323, 33878, 0, 1289, 22925, 0, 5534, 0, + 39160, 0, 26866, 15218, 2438, 0, 0, 33506, 39161, 0, 40252, + 0, 0, 0, 0, 11794, 3552, 0, 0, 10709, 21762, 21557, + 34648, 0, 3744, 8131, 9466, 23190, 0, 8785, 29552, 0, 0, + 0, 28729, 23824, 0, 0, 14352, 33521, 23435, 0, 39218, 0, + 0, 0, 24654, 0, 6878, 0, 0, 11814, 10732, 24410, 0, + 3056, 0, 0, 8238, 0, 10599, 31601, 31223, 19516, 0, 0, + 29054, 0, 0, 10600, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1973, 0, 24308, 8786, 0, 0, 8064, 15983, + 0, 0, 0, 0, 0, 1663, 14173, 15225, 9544, 0, 8596, + 33530, 234, 37754, 31386, 35517, 14061, 0, 18817, 24974, 29924, 0, + 12626, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 14234, 14954, 22763, 16069, 0, 0, 30266, 11835, 6665, 37626, + 13749, 0, 9672, 8599, 23001, 19823, 40440, 10190, 0, 0, 0, + 0, 0, 0, 0, 0, 36610, 24658, 0, 16807, 259, 22592, + 31009, 0, 0, 24341, 0, 24311, 20355, 6248, 20042, 38620, 0, + 24416, 35526, 0, 0, 0, 0, 0, 0, 0, 597, 0, + 0, 14725, 0, 38290, 33710, 16378, 19265, 19266, 21937, 864, 0, + 23028, 33711, 0, 0, 0, 383, 0, 0, 0, 0, 0, + 10711, 0, 0, 10712, 38686, 0, 26075, 8600, 0, 22946, 17751, + 0, 0, 0, 0, 30269, 33786, 0, 0, 0, 0, 0, + 15964, 0, 0, 7029, 10143, 26061, 0, 0, 5239, 0, 0, + 0, 0, 0, 33787, 0, 7034, 8365, 0, 5348, 0, 19965, + 35359, 21671, 0, 22808, 0, 0, 0, 2339, 0, 0, 0, + 0, 37662, 0, 7038, 21605, 0, 0, 36247, 0, 0, 24037, + 0, 10609, 18149, 0, 2676, 36504, 0, 0, 0, 0, 9380, + 0, 21477, 33507, 28668, 14007, 0, 0, 0, 22355, 0, 17652, + 0, 0, 918, 0, 0, 33152, 30000, 2983, 8402, 0, 10864, + 30487, 0, 0, 8029, 22289, 0, 21083, 34060, 33974, 0, 0, + 18313, 18082, 33976, 24727, 10221, 35486, 10106, 0, 8041, 453, 35487, + 0, 1948, 0, 0, 0, 10594, 17205, 0, 0, 0, 25796, + 31577, 0, 0, 0, 27111, 22703, 11233, 35497, 1961, 1974, 21179, + 24655, 0, 0, 30735, 3109, 36796, 0, 30830, 11700, 25805, 0, + 0, 0, 10733, 27892, 10121, 22197, 0, 7384, 0, 18263, 40109, + 22549, 0, 17243, 0, 0, 4212, 31614, 39297, 0, 1067, 39322, + 28235, 34546, 0, 0, 0, 0, 24365, 31387, 17619, 0, 38898, + 17593, 0, 0, 0, 13598, 0, 10605, 36704, 0, 16209, 10819, + 0, 37659, 10699, 35260, 0, 36494, 33840, 36803, 0, 0, 0, + 0, 24976, 0, 0, 0, 28847, 28379, 0, 17288, 27902, 17289, + 0, 0, 37418, 0, 0, 35984, 0, 0, 0, 0, 0, + 33417, 323, 29882, 28081, 27453, 0, 37432, 0, 7741, 0, 0, + 0, 28083, 29933, 37433, 39304, 39305, 0, 28970, 0, 0, 0, + 0, 18288, 0, 3374, 28163, 25964, 0, 0, 0, 0, 0, + 0, 9210, 7749, 17858, 22717, 0, 0, 0, 17371, 0, 18444, + 3896, 32689, 10610, 33100, 26570, 0, 0, 18451, 10741, 33823, 7755, + 0, 442, 1894, 28947, 27998, 38876, 1537, 27874, 29909, 28356, 32637, + 10553, 25955, 0, 7432, 0, 0, 0, 0, 21717, 19542, 0, + 0, 0, 0, 11365, 39450, 0, 0, 0, 35723, 0, 37247, + 0, 0, 35448, 37671, 3473, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 36213, 21715, 25482, 0, 0, 0, + 20901, 0, 0, 0, 0, 0, 0, 0, 29267, 0, 424, + 0, 0, 0, 0, 7118, 39278, 6965, 23022, 12157, 21243, 0, + 14224, 12778, 0, 0, 8403, 0, 0, 0, 18071, 0, 41182, + 0, 0, 924, 0, 0, 0, 0, 0, 0, 27257, 35582, + 22010, 0, 0, 0, 21127, 27104, 0, 19427, 27105, 0, 29103, + 0, 0, 0, 0, 0, 0, 8914, 0, 0, 0, 0, + 16802, 776, 37512, 41236, 16499, 33401, 0, 0, 38049, 3395, 12916, + 19674, 12785, 37359, 0, 0, 37360, 35498, 0, 0, 0, 19472, + 38050, 0, 40532, 29115, 0, 0, 31851, 14512, 38095, 18802, 28962, + 0, 0, 40536, 18096, 0, 14670, 0, 0, 12198, 14744, 0, + 0, 40781, 0, 37677, 6155, 0, 0, 0, 0, 21048, 0, + 0, 0, 3730, 0, 0, 0, 0, 0, 0, 0, 0, + 272, 0, 0, 0, 8816, 0, 1866, 6110, 30737, 0, 0, + 0, 0, 24973, 15389, 0, 0, 22630, 15226, 8071, 36657, 0, + 29875, 29711, 36909, 34912, 0, 35126, 0, 0, 34665, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 32217, 0, 29127, + 0, 28236, 0, 0, 0, 4410, 0, 0, 0, 33585, 31388, + 2234, 37394, 0, 0, 2812, 32008, 0, 15335, 2337, 2526, 24666, + 0, 0, 4921, 0, 28075, 0, 0, 11150, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 31175, 37517, 0, 0, 0, 0, 13321, 32516, 38531, 25885, 20553, + 0, 26399, 2386, 28145, 4162, 20043, 40218, 3732, 12641, 3733, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17480, 0, 0, 0, 0, 9920, 0, 0, 0, 0, + 0, 6625, 32518, 3287, 26400, 17308, 11542, 0, 0, 5500, 0, + 0, 17597, 0, 0, 0, 0, 0, 0, 37970, 0, 0, + 0, 12066, 17922, 0, 0, 6391, 10139, 36590, 37661, 9850, 18126, + 0, 17519, 0, 385, 5265, 36007, 21746, 26355, 0, 33198, 0, + 0, 4973, 37434, 2241, 31130, 2570, 2021, 0, 13080, 0, 0, + 0, 0, 0, 0, 19932, 30767, 20559, 0, 0, 0, 0, + 27548, 13761, 27609, 12074, 0, 0, 4343, 0, 18442, 11282, 0, + 30061, 0, 0, 37123, 0, 0, 2861, 36599, 12079, 0, 16436, + 0, 0, 0, 0, 20870, 401, 8384, 35558, 12758, 0, 4937, + 6098, 34113, 25291, 14736, 29862, 33568, 27849, 0, 2370, 3271, 0, + 6072, 0, 0, 0, 0, 0, 0, 0, 0, 9875, 0, + 0, 0, 0, 31289, 0, 0, 0, 0, 0, 0, 23440, + 0, 12212, 0, 0, 0, 0, 0, 15958, 30639, 0, 0, + 0, 0, 0, 0, 27175, 8084, 0, 29885, 0, 1656, 0, + 28664, 10153, 22759, 0, 0, 0, 37055, 28669, 0, 0, 0, + 0, 0, 0, 0, 32456, 0, 33414, 0, 0, 0, 0, + 31028, 9921, 22393, 0, 0, 0, 0, 0, 0, 0, 28707, + 0, 1669, 32463, 0, 0, 35607, 0, 0, 22728, 11318, 20768, + 425, 0, 7344, 0, 0, 0, 6064, 0, 0, 0, 0, + 0, 0, 0, 7582, 0, 0, 13819, 0, 0, 0, 28325, + 0, 0, 0, 0, 0, 30409, 8657, 0, 0, 7583, 0, + 30114, 0, 30931, 9275, 6683, 0, 38980, 4432, 35047, 0, 642, + 2140, 20654, 0, 22959, 0, 0, 8728, 0, 0, 18249, 0, + 0, 25192, 0, 0, 0, 0, 0, 0, 8408, 0, 10961, + 20723, 0, 0, 33403, 11473, 8065, 11681, 0, 24805, 13727, 30057, + 37078, 20660, 40025, 14356, 0, 27294, 15831, 24499, 17814, 8239, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 33698, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17975, + 0, 21570, 0, 22478, 0, 8247, 2147, 35952, 0, 0, 1987, + 0, 6850, 0, 0, 0, 0, 0, 38995, 0, 17244, 0, + 0, 29843, 4966, 0, 18827, 34336, 6159, 24190, 30382, 20510, 41152, + 8258, 24747, 967, 346, 23931, 0, 0, 0, 0, 25120, 0, + 0, 0, 0, 0, 0, 25096, 11189, 32405, 16108, 0, 0, + 0, 4801, 0, 0, 35524, 0, 0, 0, 3442, 40992, 21138, + 3372, 6484, 36611, 39024, 0, 28760, 34808, 32911, 33782, 0, 6514, + 27430, 32223, 32224, 0, 0, 6863, 0, 0, 0, 0, 0, + 0, 0, 0, 16170, 0, 0, 0, 0, 0, 30849, 36708, + 37104, 0, 0, 29058, 0, 13881, 0, 28850, 23375, 0, 5750, + 28927, 18956, 38733, 30904, 12651, 284, 21973, 23618, 0, 0, 0, + 26889, 28434, 0, 0, 20679, 0, 0, 0, 36809, 0, 0, + 0, 0, 0, 0, 0, 38453, 0, 0, 35001, 0, 0, + 0, 0, 0, 0, 0, 3709, 16985, 37114, 2826, 35355, 0, + 0, 3658, 0, 16986, 0, 0, 0, 0, 0, 0, 0, + 0, 29829, 0, 41087, 0, 0, 32235, 0, 0, 0, 0, + 31899, 0, 1670, 10021, 23384, 25917, 0, 7446, 0, 26357, 0, + 0, 0, 0, 0, 0, 0, 11300, 0, 0, 0, 0, + 0, 0, 0, 717, 37121, 37122, 0, 12418, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 15747, 40946, + 0, 0, 0, 0, 0, 0, 32426, 19936, 0, 0, 0, + 0, 0, 0, 0, 0, 17372, 39868, 7294, 17860, 2219, 6405, + 9472, 33368, 17013, 23558, 0, 0, 15002, 30063, 0, 14697, 32690, + 0, 0, 0, 0, 24858, 0, 0, 0, 40413, 0, 0, + 0, 0, 15010, 0, 0, 0, 0, 13790, 0, 40067, 32324, + 18360, 34818, 25177, 35691, 17776, 1835, 11889, 12511, 6197, 39986, 24905, + 13646, 0, 0, 0, 0, 14468, 0, 963, 0, 0, 1083, + 8703, 4286, 0, 23761, 27876, 30800, 3338, 18504, 37023, 16163, 23762, + 5737, 28423, 38710, 0, 7259, 17835, 29474, 12127, 23663, 10932, 0, + 0, 37025, 23502, 37026, 30192, 0, 478, 23304, 25771, 24003, 34273, + 32271, 0, 0, 0, 0, 0, 0, 4356, 7345, 0, 16093, + 9712, 25033, 6973, 24487, 0, 0, 19306, 15660, 35043, 0, 0, + 25034, 3890, 12822, 0, 40253, 0, 6537, 30213, 0, 21129, 0, + 0, 0, 34407, 29632, 0, 0, 0, 0, 0, 33279, 9719, + 22837, 0, 0, 0, 37198, 10486, 0, 40658, 0, 0, 26496, + 37201, 0, 0, 12627, 0, 23925, 27545, 4335, 41076, 16839, 21255, + 0, 30204, 38446, 0, 5226, 0, 0, 0, 0, 0, 0, + 6468, 1512, 13599, 23614, 10440, 3759, 34419, 0, 34672, 0, 0, + 0, 27815, 29026, 35056, 0, 15307, 0, 40503, 9677, 45, 9922, + 0, 0, 0, 0, 28380, 33712, 1576, 0, 7806, 24751, 19543, + 0, 9808, 0, 0, 0, 0, 0, 1378, 14984, 4165, 0, + 0, 23098, 0, 0, 0, 36008, 0, 0, 23720, 36017, 7030, + 18131, 0, 1383, 0, 0, 0, 0, 0, 12075, 20571, 0, + 0, 34023, 0, 0, 34703, 0, 0, 0, 17373, 0, 28711, + 0, 0, 0, 19007, 0, 15176, 19669, 32638, 0, 0, 0, + 0, 57, 0, 0, 28426, 0, 0, 19798, 0, 9761, 0, + 0, 0, 8593, 21089, 10238, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 25036, 0, 0, 0, 0, 2387, 25989, + 0, 0, 0, 0, 22558, 0, 0, 0, 0, 0, 0, + 32817, 32691, 14486, 0, 0, 0, 0, 3346, 21124, 0, 0, + 0, 0, 0, 21191, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 20777, 0, 26432, 0, 5741, 0, + 0, 18089, 0, 39164, 35048, 0, 8229, 23779, 24492, 14507, 1814, + 19587, 38512, 28548, 0, 0, 0, 3696, 0, 0, 0, 0, + 0, 0, 38553, 0, 26874, 36670, 0, 24500, 5404, 29203, 40508, + 0, 36288, 0, 21132, 1867, 15833, 39593, 6749, 4529, 779, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 16948, 0, 0, + 14518, 30942, 17823, 0, 0, 31075, 26991, 21467, 19518, 14278, 0, + 0, 0, 0, 33408, 0, 0, 0, 0, 31058, 0, 5408, + 0, 31623, 240, 4967, 40968, 10133, 4213, 1100, 0, 6216, 0, + 38793, 0, 0, 0, 34177, 0, 0, 5590, 11954, 0, 0, + 0, 20416, 0, 0, 8260, 0, 783, 15474, 19592, 25260, 40941, + 23616, 31936, 27905, 33415, 20919, 0, 0, 0, 19403, 0, 0, + 0, 0, 38404, 2725, 26562, 31077, 0, 0, 0, 0, 46, + 716, 10204, 0, 25962, 28381, 29216, 34278, 0, 1821, 25458, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 26134, 31029, + 0, 0, 325, 0, 40468, 0, 22752, 28148, 35356, 27906, 6249, + 27907, 19127, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7550, 41233, 0, 21150, 5474, 39521, 4840, 17708, 12466, 1872, 4584, + 3376, 2087, 0, 25864, 38111, 0, 0, 0, 0, 0, 13554, + 0, 0, 35113, 18691, 0, 2314, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 21304, 0, 0, 0, 0, 0, 0, + 0, 13764, 23102, 40488, 38116, 0, 0, 0, 0, 0, 0, + 17378, 0, 0, 16232, 0, 0, 3715, 0, 0, 38743, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1498, 31001, 0, + 0, 0, 0, 10735, 0, 0, 0, 22782, 0, 26063, 0, + 0, 0, 0, 21305, 7591, 33579, 0, 26989, 0, 14689, 0, + 0, 0, 14994, 0, 37457, 0, 9749, 9754, 0, 10962, 0, + 0, 17224, 32893, 7094, 37594, 9879, 0, 0, 14174, 0, 15471, + 0, 40934, 7539, 0, 22340, 8817, 0, 12948, 21257, 0, 32225, + 17310, 3028, 0, 7099, 8820, 37435, 11010, 7548, 326, 0, 0, + 0, 7129, 0, 0, 0, 0, 15478, 15707, 2024, 0, 0, + 35280, 13556, 0, 0, 0, 0, 0, 0, 0, 3031, 8822, + 25623, 0, 37790, 0, 17931, 0, 0, 0, 0, 37459, 37796, + 38537, 32692, 0, 0, 20370, 0, 0, 0, 9596, 14263, 0, + 30165, 0, 0, 31681, 30699, 40629, 30801, 15938, 0, 0, 19788, + 0, 10280, 10152, 7373, 21687, 36906, 11218, 0, 0, 16530, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 40204, 9611, 1291, 12823, 29390, 0, 18936, 15569, 41162, 18083, + 23321, 0, 40207, 0, 0, 0, 0, 9181, 41112, 0, 34739, + 27947, 0, 15947, 0, 2877, 0, 34975, 0, 0, 37361, 0, + 0, 0, 0, 0, 0, 27266, 16298, 35899, 6242, 0, 0, + 0, 31224, 36489, 8066, 40436, 8133, 0, 28053, 17050, 35092, 29960, + 0, 0, 0, 0, 0, 0, 0, 9661, 0, 0, 0, + 18944, 34666, 23347, 16536, 40216, 0, 9615, 10888, 0, 0, 0, + 0, 0, 0, 14062, 0, 0, 3555, 0, 0, 14521, 38448, + 0, 20288, 0, 0, 0, 0, 0, 0, 0, 40173, 8413, + 33339, 12403, 0, 0, 0, 26197, 19803, 37946, 0, 0, 0, + 27204, 0, 0, 18957, 36912, 13322, 21862, 0, 0, 0, 0, + 14690, 36913, 0, 0, 36009, 29031, 30649, 3067, 17987, 9240, 0, + 17325, 17752, 0, 0, 13398, 34811, 1583, 23377, 0, 0, 0, + 36018, 0, 0, 1723, 19934, 2605, 0, 8415, 0, 0, 0, + 24846, 5600, 16720, 0, 0, 0, 0, 18150, 0, 0, 0, + 11305, 24857, 0, 19150, 0, 15972, 0, 0, 0, 24640, 37179, + 11219, 0, 0, 0, 16797, 0, 25347, 32731, 27757, 0, 0, + 6457, 1626, 0, 0, 0, 0, 21688, 0, 10480, 22242, 0, + 7526, 20821, 0, 0, 7883, 0, 0, 10964, 30454, 26122, 0, + 13370, 31290, 0, 0, 0, 0, 0, 0, 0, 8230, 0, + 0, 0, 0, 0, 0, 0, 1787, 40344, 0, 40213, 3437, + 0, 26686, 10884, 2063, 0, 0, 0, 0, 25194, 0, 0, + 0, 0, 0, 0, 0, 20827, 0, 17225, 0, 0, 12740, + 0, 0, 19312, 0, 0, 19892, 20728, 40028, 32284, 11706, 9342, + 14358, 0, 20828, 0, 25621, 0, 31230, 0, 25580, 0, 38515, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 21873, 32901, 0, 13313, 0, 0, 0, + 0, 0, 0, 17053, 27272, 35968, 5591, 24393, 14522, 0, 0, + 39835, 0, 16504, 2149, 15845, 35969, 0, 1997, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3654, 0, + 0, 0, 0, 0, 13318, 0, 31125, 34134, 0, 0, 0, + 0, 29977, 19519, 0, 7385, 40679, 0, 23617, 0, 28433, 23365, + 0, 22415, 1635, 7679, 29844, 11241, 0, 0, 7017, 0, 0, + 0, 7018, 0, 0, 6114, 0, 25585, 0, 0, 0, 0, + 0, 7019, 0, 0, 0, 0, 0, 0, 0, 34680, 27772, + 0, 0, 0, 0, 0, 36448, 21259, 21260, 35527, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 20044, 0, 0, 0, 0, 35148, 22931, 4610, + 0, 30860, 0, 9924, 36372, 0, 29520, 39855, 7445, 36810, 0, + 0, 15960, 241, 489, 0, 10138, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 21003, 20973, 0, 0, + 14074, 0, 0, 30567, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4039, 0, 28383, 28928, 23379, 28851, 30765, + 8446, 0, 8754, 0, 10140, 0, 20922, 8755, 0, 0, 0, + 0, 39306, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 28436, 0, + 0, 0, 27686, 0, 21359, 25932, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 32917, 0, 0, 0, + 41089, 37118, 21360, 23210, 0, 0, 26649, 0, 0, 0, 0, + 0, 0, 2064, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 16077, 16994, 0, 9281, 0, + 0, 0, 0, 0, 0, 0, 34574, 2153, 13205, 0, 31239, + 2466, 17927, 40450, 0, 11655, 0, 29651, 38481, 0, 10518, 0, + 0, 9841, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14113, 0, 0, 0, 6027, 0, 36462, 0, 0, 0, 0, + 39866, 0, 0, 0, 0, 0, 30771, 0, 12669, 25499, 0, + 0, 387, 5266, 19141, 35281, 30569, 0, 0, 0, 0, 0, + 23961, 0, 0, 0, 0, 0, 0, 8758, 12670, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 41035, 0, + 35539, 0, 0, 38482, 0, 17862, 0, 0, 0, 0, 0, + 0, 35284, 0, 0, 0, 0, 0, 0, 0, 38634, 0, + 0, 0, 3851, 1587, 0, 0, 0, 0, 33720, 36717, 0, + 0, 0, 0, 0, 33101, 30654, 17381, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2030, 13094, 2753, 16079, + 0, 0, 24397, 0, 0, 0, 0, 0, 27495, 31666, 24859, + 0, 0, 0, 0, 0, 0, 19152, 0, 0, 5286, 21384, + 17069, 0, 498, 0, 6953, 7869, 8195, 11913, 38508, 162, 0, + 0, 24651, 3819, 20254, 34131, 29842, 21254, 11137, 27269, 0, 33531, + 39971, 15281, 0, 0, 0, 0, 0, 32625, 32626, 4458, 3614, + 0, 5865, 35850, 0, 6066, 0, 0, 10107, 30322, 0, 35585, + 816, 35873, 0, 0, 0, 0, 34127, 0, 0, 0, 0, + 32490, 0, 0, 0, 0, 0, 0, 1106, 0, 0, 13720, + 8659, 38315, 0, 39221, 10965, 31578, 33140, 32649, 8231, 39966, 0, + 19675, 33141, 23916, 0, 0, 0, 7625, 588, 11289, 0, 0, + 0, 0, 0, 0, 13371, 0, 819, 34172, 34976, 0, 0, + 0, 0, 0, 31852, 0, 14671, 0, 24894, 37752, 28577, 29708, + 20662, 38442, 24807, 0, 7891, 0, 24808, 3647, 0, 36798, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 29123, 0, + 0, 30200, 0, 0, 30123, 0, 3929, 0, 8664, 0, 0, + 0, 0, 0, 0, 37515, 8665, 24809, 0, 0, 0, 0, + 14672, 0, 0, 6012, 35519, 26884, 35954, 0, 9616, 13314, 0, + 27810, 24505, 0, 7009, 11474, 11683, 34083, 0, 0, 14520, 0, + 38545, 3649, 16608, 0, 23348, 33410, 0, 11643, 29644, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8249, + 0, 0, 34084, 13735, 20099, 37396, 0, 0, 0, 0, 0, + 0, 0, 40485, 13383, 39836, 3369, 0, 13750, 32665, 3193, 16961, + 37759, 0, 39837, 16580, 31126, 24821, 0, 30439, 0, 35351, 35970, + 16505, 0, 29693, 174, 14962, 34674, 0, 0, 0, 14680, 0, + 39227, 0, 39838, 19540, 0, 0, 0, 33450, 0, 0, 4160, + 3894, 0, 0, 0, 0, 0, 23934, 7443, 2922, 0, 20214, + 28077, 348, 0, 8139, 0, 0, 0, 30851, 39442, 20417, 2884, + 34429, 37420, 0, 8261, 28520, 12464, 0, 7543, 0, 0, 11003, + 14449, 0, 37206, 0, 0, 0, 0, 0, 23369, 19740, 0, + 0, 1638, 9836, 0, 0, 0, 20518, 0, 30383, 30384, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14070, 37421, 32231, 0, 0, 4245, 12412, 0, 32459, 22306, 8265, + 0, 0, 0, 18284, 0, 25837, 33912, 41033, 0, 13759, 0, + 0, 38625, 0, 37108, 37109, 19744, 20308, 19680, 6709, 8266, 0, + 0, 0, 0, 0, 0, 0, 13196, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 20290, 0, 285, 0, 0, + 0, 0, 15475, 0, 0, 0, 0, 0, 0, 0, 0, + 10786, 0, 0, 0, 9074, 0, 31654, 0, 25460, 8671, 22089, + 37610, 32047, 0, 0, 26135, 22483, 0, 24395, 36591, 24833, 0, + 8980, 0, 8756, 32132, 0, 28084, 0, 0, 0, 599, 23380, + 10820, 0, 0, 0, 31655, 0, 31177, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 23211, 11126, 9559, 0, 5598, 26390, 19369, 20463, 12661, 31716, 32136, + 12417, 2924, 15625, 3710, 0, 0, 0, 0, 0, 0, 38776, + 22741, 28086, 19046, 16995, 19984, 3711, 29246, 0, 18132, 0, 3661, + 0, 0, 0, 0, 0, 0, 0, 0, 3712, 0, 0, + 3662, 0, 0, 0, 21476, 0, 36613, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20184, + 0, 27279, 0, 31900, 0, 7035, 40804, 0, 0, 13762, 12245, + 10740, 26817, 17358, 0, 23214, 0, 40035, 27692, 24847, 0, 0, + 0, 0, 0, 0, 0, 0, 32922, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 27693, 0, 0, 0, + 33545, 0, 0, 0, 0, 8271, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 21747, 34280, + 18296, 12826, 9560, 15968, 3665, 2315, 3944, 0, 9768, 0, 5165, + 0, 0, 0, 13207, 0, 5267, 10822, 0, 15626, 0, 4041, + 23729, 134, 0, 22642, 0, 0, 0, 0, 0, 0, 34142, + 14078, 19987, 0, 1725, 16395, 9213, 3850, 0, 0, 36598, 9282, + 37125, 40122, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2220, 0, 18298, 2090, 19244, 13766, + 39124, 20369, 9483, 0, 12796, 0, 16233, 0, 0, 0, 0, + 0, 0, 27206, 0, 0, 9769, 0, 0, 19988, 23797, 16322, + 0, 10457, 29886, 0, 0, 0, 0, 0, 11656, 0, 0, + 0, 0, 0, 0, 10611, 0, 0, 0, 18916, 0, 0, + 12797, 0, 0, 0, 0, 0, 9561, 0, 0, 35362, 11306, + 0, 0, 0, 0, 0, 0, 19153, 0, 0, 0, 15011, + 0, 0, 0, 9447, 0, 0, 24996, 21478, 0, 0, 19417, + 0, 0, 37906, 30917, 3590, 3596, 39406, 0, 4386, 40479, 11166, + 13664, 24783, 29747, 20405, 19728, 37056, 311, 589, 0, 22470, 39122, + 18664, 3626, 29691, 0, 13594, 0, 38610, 0, 0, 0, 0, + 0, 13876, 18680, 0, 0, 13189, 28762, 2885, 0, 4471, 0, + 0, 30254, 4611, 15245, 0, 1516, 0, 0, 0, 0, 0, + 0, 30907, 0, 0, 23723, 0, 0, 0, 8481, 0, 0, + 11857, 0, 8451, 0, 12672, 8483, 0, 11268, 0, 0, 0, + 27758, 0, 0, 7885, 0, 0, 0, 0, 22539, 0, 2155, + 0, 0, 0, 0, 995, 0, 0, 0, 0, 0, 26990, + 0, 0, 11352, 0, 9546, 0, 0, 21963, 0, 0, 0, + 0, 0, 0, 0, 0, 22200, 0, 36496, 29555, 32780, 0, + 40347, 0, 37097, 0, 0, 0, 0, 0, 13181, 0, 0, + 24874, 30385, 16073, 40505, 0, 37422, 9837, 22895, 41170, 41085, 0, + 40180, 21838, 40181, 0, 0, 0, 0, 22715, 20054, 0, 0, + 0, 0, 1385, 28087, 0, 0, 0, 23101, 20066, 0, 0, + 0, 0, 0, 0, 0, 0, 35283, 37210, 0, 37451, 0, + 40266, 0, 0, 18145, 0, 0, 0, 0, 0, 0, 21787, + 0, 0, 0, 18072, 0, 17720, 0, 30055, 0, 1144, 20917, + 24798, 0, 22540, 6266, 21559, 30004, 0, 12179, 0, 18090, 0, + 0, 0, 15701, 28054, 0, 0, 0, 29709, 0, 0, 0, + 0, 0, 20931, 38278, 0, 0, 29666, 8741, 6540, 0, 0, + 13736, 0, 29284, 29425, 3504, 24743, 0, 26132, 0, 1999, 16962, + 0, 19229, 0, 17698, 27411, 5481, 0, 3443, 20353, 0, 28967, + 11910, 0, 21489, 0, 15103, 11118, 0, 18839, 35268, 0, 20675, + 3044, 0, 0, 0, 28394, 0, 15393, 8267, 0, 3029, 0, + 0, 28382, 0, 0, 24561, 0, 0, 0, 28085, 0, 37947, + 0, 28385, 15672, 2018, 0, 18559, 20689, 0, 17521, 33897, 28386, + 19413, 1386, 0, 0, 0, 0, 0, 0, 0, 29220, 0, + 17491, 28709, 26361, 0, 24852, 6404, 11370, 25991, 0, 0, 0, + 15891, 0, 0, 0, 21614, 0, 21615, 19154, 41262, 35751, 32352, + 3020, 29449, 0, 0, 0, 0, 0, 0, 27595, 0, 20096, + 0, 0, 20025, 0, 0, 0, 30377, 0, 996, 23920, 0, + 20568, 0, 0, 18277, 31127, 0, 19768, 0, 29695, 0, 0, + 20781, 0, 19746, 0, 0, 0, 0, 41307, 0, 30002, 15302, + 30005, 0, 0, 0, 3110, 39349, 0, 3702, 29244, 0, 39824, + 2714, 2719, 0, 0, 24366, 29978, 11709, 25098, 38621, 12950, 2726, + 0, 11539, 0, 11651, 3509, 0, 11540, 10561, 37892, 0, 29856, + 1422, 0, 11547, 37893, 0, 0, 0, 0, 20690, 8930, 0, + 8931, 0, 9688, 0, 2748, 0, 25105, 25719, 15892, 22753, 0, + 0, 25601, 0, 0, 0, 21713, 11108, 13916, 21353, 826, 0, + 21291, 0, 1346, 10988, 16949, 0, 0, 40174, 20862, 0, 25011, + 7785, 1152, 16976, 1668, 21383, 6180, 0, 0, 17488, 21362, 17492, + 19268, 39013, 0, 0, 0, 12746, 35540, 0, 18470, 0, 35852, + 0, 0, 0, 0, 5063, 6460, 0, 0, 0, 0, 35590, + 0, 28609, 10154, 27403, 0, 0, 0, 0, 30324, 0, 28055, + 35052, 7152, 0, 39223, 0, 0, 0, 0, 0, 0, 0, + 6303, 12937, 0, 0, 0, 22131, 11647, 0, 2602, 26254, 18611, + 0, 37414, 0, 34682, 30386, 24119, 19098, 37423, 0, 0, 29827, + 30852, 0, 30023, 0, 0, 11916, 968, 24195, 0, 13882, 16283, + 0, 39603, 37110, 0, 4472, 0, 0, 0, 0, 0, 0, + 35274, 6022, 2604, 5837, 19409, 0, 5502, 30568, 21416, 16815, 1756, + 31178, 0, 39172, 0, 0, 25530, 30270, 20182, 13832, 0, 10787, + 0, 38571, 25605, 40803, 22090, 0, 20691, 0, 20185, 0, 23212, + 20692, 0, 0, 39446, 600, 0, 20364, 0, 18847, 0, 23215, + 3714, 0, 17001, 36023, 0, 0, 5507, 4841, 0, 6600, 19316, + 34582, 0, 38365, 34583, 6601, 23059, 0, 0, 37784, 0, 0, + 0, 12078, 19370, 13091, 21748, 24288, 0, 24289, 0, 0, 35285, + 0, 28586, 0, 0, 0, 0, 12974, 0, 0, 2571, 0, + 5241, 29041, 17383, 0, 0, 21438, 2754, 38139, 0, 0, 0, + 0, 37468, 0, 41201, 1424, 0, 0, 3964, 0, 0, 0, + 0, 0, 0, 0, 25158, 0, 25164, 34744, 2036, 0, 0, + 0, 0, 4668, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 20055, 0, 15418, 0, 4674, 0, 0, 0, 0, + 0, 0, 31719, 0, 19269, 0, 26896, 5762, 0, 0, 26897, + 0, 0, 6075, 14194, 0, 37588, 8409, 0, 0, 0, 11858, + 12199, 0, 22378, 0, 5465, 0, 1071, 0, 0, 22133, 28522, + 0, 37521, 8567, 37522, 0, 0, 0, 0, 0, 12745, 0, + 0, 0, 15560, 0, 0, 6220, 0, 0, 32236, 23555, 0, + 25918, 0, 0, 0, 36300, 0, 0, 18445, 0, 0, 29005, + 18450, 0, 0, 25348, 0, 0, 36296, 22892, 23054, 37599, 25493, + 0, 7375, 0, 0, 0, 10156, 20036, 10997, 40795, 0, 18111, + 14197, 25495, 0, 0, 0, 22896, 9470, 7127, 0, 0, 0, + 0, 0, 0, 0, 0, 4671, 15104, 0, 0, 0, 0, + 0, 0, 0, 33429, 0, 7101, 29218, 0, 34812, 0, 133, + 11012, 31717, 0, 11013, 0, 27689, 17063, 0, 36024, 9211, 0, + 28853, 0, 0, 0, 0, 0, 0, 25106, 40947, 17007, 0, + 13558, 0, 0, 7295, 23103, 27699, 0, 13768, 18649, 17384, 2755, + 0, 35089, 0, 0, 0, 0, 11648, 0, 0, 0, 10738, + 5749, 24671, 14972, 0, 22634, 0, 0, 0, 15913, 0, 0, + 31764, 29062, 0, 0, 33716, 0, 0, 0, 0, 0, 1457, + 0, 0, 10328, 17494, 0, 0, 28091, 17753, 0, 0, 0, + 0, 13884, 0, 0, 0, 0, 17385, 2756, 0, 0, 23341, + 23350, 0, 0, 40800, 0, 40802, 0, 23385, 0, 23388, 40808, + 0, 38536, 38538, 22006, 0, 14444, 0, 0, 34554, 0, 0, + 10182, 20920, 0, 0, 0, 0, 0, 0, 34561, 0, 38734, + 26992, 39517, 0, 0, 0, 0, 38405, 0, 0, 0, 0, + 0, 0, 25498, 38406, 0, 36012, 20500, 34208, 0, 39859, 0, + 16152, 32014, 0, 22684, 28534, 0, 35605, 0, 0, 33419, 38534, + 0, 6754, 7026, 0, 0, 0, 36186, 0, 7031, 28103, 178, + 4866, 0, 30130, 0, 30131, 32015, 0, 0, 4341, 0, 28104, + 0, 0, 0, 0, 0, 0, 0, 12666, 23835, 41090, 38535, + 37895, 38739, 0, 35534, 0, 0, 0, 0, 0, 34209, 37680, + 0, 0, 0, 0, 0, 10454, 23620, 0, 0, 0, 2529, + 0, 0, 0, 0, 21944, 0, 0, 0, 0, 11014, 0, + 34704, 0, 24199, 2028, 23935, 13834, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 21364, 0, 0, 2834, 24315, + 0, 38169, 0, 0, 36249, 33102, 0, 23389, 13210, 0, 0, + 33546, 0, 38366, 0, 7042, 0, 0, 0, 41040, 35609, 0, + 0, 0, 0, 39524, 17386, 0, 0, 17387, 36189, 0, 0, + 17497, 0, 2757, 0, 15012, 0, 38003, 0, 0, 0, 0, + 0, 0, 38539, 22673, 0, 18409, 0, 18410, 0, 0, 0, + 0, 18417, 0, 0, 0, 0, 18432, 0, 0, 18438, 0, + 19545, 0, 0, 39016, 0, 0, 0, 0, 0, 0, 8477, + 9013, 25165, 4672, 13397, 0, 0, 0, 0, 0, 0, 2038, + 0, 40358, 24564, 34745, 0, 0, 0, 0, 32792, 0, 11684, + 24758, 0, 0, 0, 0, 18177, 0, 36185, 0, 0, 0, + 22644, 0, 0, 0, 17496, 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, 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, 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, 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, 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, 6686, 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, 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, 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, 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, 518, 0, 0, 0, 0, 0, 0, + 38601, 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, 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, 0, 0, 0, 0, 0, 0, 18974, 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, 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, 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, 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, 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, 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, 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, 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, 27813, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 14806, 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, 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, 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, 0, 36551, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 21806, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4483, 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, 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, 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, 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, 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, 32329, 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, 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, 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, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 17134, 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, 7518, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28061, + 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, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15598, 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, 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, 3407, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 34009, 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, 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, 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, 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, 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, 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, 23605, + 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, + 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, + 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, + 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, 8959, 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, 0, 0, 0, 12153, 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, 19101, 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, 0, 0, 0, 0, 35624, + 0, 0, 0, 0, 0, 35380, 0, 0, 21068, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 31727, 0, 32725, 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, 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, 14808, 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, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 37697, 0, 15752, 0, 0, 18017, + 0, 0, 0, 0, 0, 0, 21240, 0, 0, 2117, 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, 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, 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, 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, 10013, 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, 0, 0, 0, + 0, 7852, 0, 4485, 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, 14953, 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, 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, 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, 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, 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, 38745, 0, 0, + 0, 0, 0, 2120, 27981, 0, 0, 0, 0, 0, 0, + 11494, 0, 0, 0, 0, 0, 38609, 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, 14837, 0, 0, 0, 0, 0, 10066, 29, + 0, 0, 0, 29084, 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, 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, 0, 0, 0, 0, 0, 0, 0, + 33637, 10659, 0, 0, 0, 0, 0, 0, 0, 0, 7971, + 0, 11680, 26867, 0, 0, 0, 23049, 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, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 39390, 0, 0, 14854, 0, + 0, 0, 21632, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3625, 0, 29104}; + +enum CASESENSITIVITY { + INSENSITIVE = 0, + SENSITIVE = 1, +}; + + +static unsigned int diff_to_gb18030_4(unsigned char *dst, unsigned int dstlen, unsigned int diff) { + ob_charset_assert(dstlen >= 4); + + if (diff > MAX_GB18030_DIFF || dstlen < 4) return 0; + + dst[3] = (unsigned char)(diff % 10) + MIN_MB_EVEN_BYTE_4; + diff /= 10; + dst[2] = (unsigned char)(diff % 126) + MIN_MB_ODD_BYTE; + diff /= 126; + dst[1] = (unsigned char)(diff % 10) + MIN_MB_EVEN_BYTE_4; + dst[0] = (unsigned char)(diff / 10) + MIN_MB_ODD_BYTE; + + return 4; +} + +static unsigned int gb18030_4_code_to_diff(unsigned int code) { + unsigned int diff = 0; + + ob_charset_assert(is_mb_odd((code >> 24) & 0xFF)); + diff += ((code >> 24) & 0xFF) - MIN_MB_ODD_BYTE; + diff *= 10; + ob_charset_assert(is_mb_even_4((code >> 16) & 0xFF)); + diff += ((code >> 16) & 0xFF) - MIN_MB_EVEN_BYTE_4; + diff *= 126; + ob_charset_assert(is_mb_odd((code >> 8) & 0xFF)); + diff += ((code >> 8) & 0xFF) - MIN_MB_ODD_BYTE; + diff *= 10; + ob_charset_assert(is_mb_even_4(code & 0xFF)); + diff += (code & 0xFF) - MIN_MB_EVEN_BYTE_4; + + return diff; +} + +static unsigned int ob_ismbchar_gb18030(const ObCharsetInfo *cs __attribute__((unused)), + const char *p, const char *e) { + ob_charset_assert(e > p); + + if (e - p <= 1 || !is_mb_odd(p[0])) { + return 0; + } else if (is_mb_even_2(p[1])) { + return 2; + } else if (e - p > 3 && is_mb_even_4(p[1]) && is_mb_odd(p[2]) && + is_mb_even_4(p[3])) { + return 4; + } + + return 0; +} + +static inline unsigned int gb18030_chs_to_code(const unsigned char *src, size_t srclen) { + unsigned int r = 0; + + ob_charset_assert(srclen == 1 || srclen == 2 || srclen == 4); + + switch (srclen) { + case 1: + r = src[0]; + break; + case 2: + r = (src[0] << 8) + src[1]; + break; + case 4: + r = (src[0] << 24) + (src[1] << 16) + (src[2] << 8) + src[3]; + break; + default: + ob_charset_assert(0); + } + + return r; +} + +static size_t code_to_gb18030_chs(unsigned char *dst, size_t dstlen, unsigned int code) { + size_t i, len = 0; + unsigned char *dst_end = dst + dstlen; + unsigned char r[4]; + for (i = 0; code != 0; i++, code >>= 8) r[i] = (unsigned char)(code & 0xFF); + + ob_charset_assert(i == 1 || i == 2 || i == 4); + for (; i > 0 && dst < dst_end; --i, ++len) *dst++ = r[i - 1]; + + return len; +} + +static unsigned int ob_mbcharlen_gb18030(const ObCharsetInfo *cs __attribute__((unused)), + unsigned int c) { + if (c <= 0xFF) { + return !is_mb_odd(c); + } else if (c > 0xFFFF || !is_mb_odd((c >> 8) & 0xFF)) { + return 0; + } else if (is_mb_even_2((c & 0xFF))) { + return 2; + } else if (is_mb_even_4((c & 0xFF))) { + return 4; + } + return 0; +} + +static size_t ob_well_formed_len_gb18030( + const ObCharsetInfo *cs __attribute__((unused)), const char *b, const char *e, + size_t pos, int *error) { + const char *b0 = b; + const char *emb = e - 1; + + *error = 0; + + while (pos-- && b < e) { + if (is_mb_1((unsigned char)b[0])) { + ++b; + } else if (b < emb && is_mb_odd(b[0]) && is_mb_even_2(b[1])) { + b += 2; + } else if (b + 2 < emb && is_mb_odd(b[0]) && is_mb_even_4(b[1]) && + is_mb_odd(b[2]) && is_mb_even_4(b[3])) { + b += 4; + } else { + *error = 1; + break; + } + } + + return (size_t)(b - b0); +} + +static inline unsigned int gb18030_4_chs_to_diff(const unsigned char *src) { + return (src[0] - MIN_MB_ODD_BYTE) * 12600 + + (src[1] - MIN_MB_EVEN_BYTE_4) * 1260 + + (src[2] - MIN_MB_ODD_BYTE) * 10 + (src[3] - MIN_MB_EVEN_BYTE_4); +} + +static int ob_mb_wc_gb18030(const ObCharsetInfo *cs __attribute__((unused)), + ob_wc_t *pwc, const unsigned char *s, const unsigned char *e) { + unsigned int idx = 0; + unsigned int cp = 0; + + if (s >= e) { + return OB_CS_TOOSMALL; + } else if (is_mb_1(s[0])) { + *pwc = s[0]; + return 1; + } else if (!is_mb_odd(s[0])) { + return OB_CS_ILSEQ; + } else if (s + 2 > e) { + return OB_CS_TOOSMALL2; + } else if (is_mb_even_2(s[1])) { + idx = (s[0] - MIN_MB_ODD_BYTE) * 192 + (s[1] - MIN_MB_EVEN_BYTE_2); + *pwc = tab_gb18030_2_uni[idx]; + return (*pwc == 0) ? OB_CS_ILSEQ : 2; + } else if (is_mb_even_4(s[1])) { + if (s + 4 > e) return OB_CS_TOOSMALL4; + + if (!(is_mb_odd(s[2]) && is_mb_even_4(s[3]))) return OB_CS_ILSEQ; + + idx = gb18030_4_chs_to_diff(s); + + if (idx < 0x334) { + cp = tab_gb18030_4_uni[idx]; + } else if (idx <= 0x1D20) { + cp = idx + 0x11E; + } else if (idx < 0x2403) { + cp = tab_gb18030_4_uni[idx - 6637]; + } else if (idx <= 0x2C40) { + cp = idx + 0x240; + } else if (idx < 0x4A63) { + cp = tab_gb18030_4_uni[idx - 6637 - 2110]; + } else if (idx <= 0x82BC) { + cp = idx + 0x5543; + } else if (idx < 0x830E) { + cp = tab_gb18030_4_uni[idx - 6637 - 2110 - 14426]; + } else if (idx <= 0x93D4) { + cp = idx + 0x6557; + } else if (idx < 0x94BE) { + cp = tab_gb18030_4_uni[idx - 6637 - 2110 - 14426 - 4295]; + } else if (idx <= 0x98C3) { + cp = idx + 0x656C; + } else if (idx <= 0x99fb) { + cp = tab_gb18030_4_uni[idx - 6637 - 2110 - 14426 - 4295 - 1030]; + } else if (idx >= 0x2E248 && idx <= 0x12E247) { + cp = idx - 0x1E248; + } else if ((idx > 0x99fb && idx < 0x2E248) || + (idx > 0x12E247 && idx <= 0x18398F)) { + cp = 0x003F; + } else { + ob_charset_assert(0); + } + + *pwc = cp; + return 4; + } else + return OB_CS_ILSEQ; +} + +static int ob_wc_mb_gb18030_chs(const ObCharsetInfo *cs __attribute__((unused)), + ob_wc_t wc, unsigned char *s, unsigned char *e) { + unsigned int idx = 0; + unsigned int len = 2; + uint16_t cp = 0; + unsigned int err; + + if (s >= e) { + return OB_CS_TOOSMALL; + } else if (wc < 0x80) { + s[0] = (unsigned char)wc; + return 1; + } else if (wc < 0x9FA6) { + cp = tab_uni_gb18030_p1[wc - 0x80]; + if ((unsigned int)((cp >> 8) & 0xFF) < MIN_MB_ODD_BYTE) { + idx = cp; + len = 4; + } + } else if (wc <= 0xD7FF) { + idx = wc - 0x5543; + len = 4; + } else if (wc < 0xE000) { + return OB_CS_ILUNI; + } else if (wc < 0xE865) { + cp = tab_uni_gb18030_p2[wc - 0xE000]; + if ((unsigned int)((cp >> 8) & 0xFF) < MIN_MB_ODD_BYTE) { + idx = cp + UNI2_TO_GB4_DIFF; + len = 4; + } + } else if (wc <= 0xF92B) { + idx = wc - 0x6557; + len = 4; + } else if (wc <= 0XFFFF) { + cp = tab_uni_gb18030_p2[wc - 0xE000 - 4295]; + if ((unsigned int)((cp >> 8) & 0xFF) < MIN_MB_ODD_BYTE) { + idx = cp + UNI2_TO_GB4_DIFF; + len = 4; + } + } else if (wc <= 0x10FFFF) { + idx = wc + 0x1E248; + len = 4; + } else { + return OB_CS_ILUNI; + } + + switch (len) { + case 2: + if (s + 2 > e) return OB_CS_TOOSMALL2; + s[0] = (unsigned char)((cp >> 8) & 0xFF); + s[1] = (unsigned char)(cp & 0xFF); + return len; + case 4: + if (s + 4 > e) return OB_CS_TOOSMALL4; + err = diff_to_gb18030_4(s, 4, idx); + ob_charset_assert(err != 0); + return err != 0 ? len : OB_CS_ILUNI; + } + + ob_charset_assert(0); + return OB_CS_ILUNI; +} + +static const ObUnicaseInfoChar *get_case_info(const ObCharsetInfo *cs, + const unsigned char *src, + size_t srclen) { + const ObUnicaseInfoChar *p = NULL; + unsigned int diff, code; + + ob_charset_assert(cs != NULL); + + switch (srclen) { + case 1: + return &cs->caseinfo->page[0][(unsigned char)src[0]]; + case 2: + if (src[0] < ((MIN_2_BYTE_UNICASE >> 8) & 0xFF) || + src[0] > ((MAX_2_BYTE_UNICASE >> 8) & 0xFF)) + return NULL; + + p = cs->caseinfo->page[(unsigned char)src[0]]; + return p ? &p[(unsigned char)src[1]] : NULL; + case 4: + diff = gb18030_4_chs_to_diff(src); + code = 0; + + if (diff < MIN_2_BYTE_UNICASE - UNICASE_4_BYTE_OFFSET) + code = diff + UNICASE_4_BYTE_OFFSET; + else if (diff >= MIN_3_BYTE_FROM_UNI && diff <= MAX_3_BYTE_FROM_UNI) + code = (diff & 0xFFFF); + else + return NULL; + + p = cs->caseinfo->page[(code >> 8) & 0xFF]; + return p ? &p[code & 0xFF] : NULL; + } + + ob_charset_assert(0); + return NULL; +} + +static unsigned int case_info_code_to_gb18030(unsigned int code) { + if ((code >= MIN_2_BYTE_UNICASE && code <= MAX_2_BYTE_UNICASE) || + code < UNICASE_4_BYTE_OFFSET) + return code; + else { + unsigned int r; + unsigned char gbchs[4]; + + if (code >= UNICASE_4_BYTE_OFFSET && code < MIN_2_BYTE_UNICASE) + code -= UNICASE_4_BYTE_OFFSET; + else if (code >= (MIN_3_BYTE_FROM_UNI & 0xFFFF) && + code <= (MAX_3_BYTE_FROM_UNI & 0xFFFF)) + code += (MIN_3_BYTE_FROM_UNI & 0xFF0000); + else + ob_charset_assert(0); + + r = diff_to_gb18030_4(gbchs, 4, code); + ob_charset_assert(r == 4); + + return r == 4 ? gb18030_chs_to_code(gbchs, 4) : 0; + } +} + +static unsigned int get_casefolded_code(const ObCharsetInfo *cs, const unsigned char *src, + size_t srclen, size_t is_upper) { + const ObUnicaseInfoChar *ch = get_case_info(cs, src, srclen); + + ob_charset_assert(srclen == 1 || srclen == 2 || srclen == 4); + + return ch ? case_info_code_to_gb18030(is_upper ? ch->toupper : ch->tolower) + : 0; +} + +static size_t ob_casefold_gb18030(const ObCharsetInfo *cs, char *src, + size_t srclen, char *dst, size_t dstlen, + const unsigned char *map, bool is_upper) { + char *srcend = src + srclen; + char *dst0 = dst; + char *dst_end = dst + dstlen; + + while (src < srcend) { + unsigned int mblen = ob_ismbchar_gb18030(cs, src, srcend); + + ob_charset_assert(dst < dst_end); + if (mblen) { + unsigned int code = get_casefolded_code(cs, (unsigned char *)src, mblen, is_upper); + + if (code != 0) { + size_t mblen_dst = + code_to_gb18030_chs((unsigned char *)dst, dst_end - dst, code); + + ob_charset_assert(dst + mblen_dst <= dst_end); + src += mblen; + dst += mblen_dst; + } else { + ob_charset_assert(mblen == 2 || mblen == 4); + ob_charset_assert(dst + mblen <= dst_end); + + if (mblen == 4) { + *dst++ = *src++; + *dst++ = *src++; + } + + *dst++ = *src++; + *dst++ = *src++; + } + } else + *dst++ = (char)map[(unsigned char)(*src++)]; + } + + return (size_t)(dst - dst0); +} + +static size_t ob_caseup_gb18030(const ObCharsetInfo *cs, char *src, + size_t srclen, char *dst, size_t dstlen) { + ob_charset_assert(cs != NULL); + ob_charset_assert(src != dst || cs->caseup_multiply == 1); + ob_charset_assert(dstlen >= srclen * cs->caseup_multiply); + return ob_casefold_gb18030(cs, src, srclen, dst, dstlen, cs->to_upper, 1); +} + +static size_t ob_casedn_gb18030(const ObCharsetInfo *cs, char *src, + size_t srclen, char *dst, size_t dstlen) { + ob_charset_assert(cs != NULL); + ob_charset_assert(src != dst || cs->casedn_multiply == 1); + ob_charset_assert(dstlen >= srclen * cs->casedn_multiply); + return ob_casefold_gb18030(cs, src, srclen, dst, dstlen, cs->to_lower, 0); +} + +static unsigned int get_weight_if_chinese_character(unsigned int code) { + if (code >= PINYIN_2_BYTE_START && code <= PINYIN_2_BYTE_END) { + unsigned int idx = (((code >> 8) & 0xFF) - MIN_MB_ODD_BYTE) * 0xBE + (code & 0xFF) - + MIN_MB_EVEN_BYTE_2; + if ((code & 0xFF) > 0x7F) idx -= 0x01; + + return PINYIN_WEIGHT_BASE + gb18030_2_weight_py[idx]; + } else if (code >= PINYIN_4_BYTE_1_START && code <= PINYIN_4_BYTE_1_END) { + unsigned int idx = gb18030_4_code_to_diff(code) - PINYIN_4_1_DIFF; + return PINYIN_WEIGHT_BASE + gb18030_4_weight_py_p1[idx]; + } else if (code >= PINYIN_4_BYTE_2_START && code <= PINYIN_4_BYTE_2_END) { + unsigned int idx = gb18030_4_code_to_diff(code) - PINYIN_4_2_DIFF; + return PINYIN_WEIGHT_BASE + gb18030_4_weight_py_p2[idx]; + } + + return PINYIN_WEIGHT_BASE; +} + +template +static uint get_weight_for_mbchar(const ObCharsetInfo *cs, const uchar *src, + size_t mblen) { + unsigned int weight, caseup_code, code = gb18030_chs_to_code(src, mblen); + + ob_charset_assert(mblen == 2 || mblen == 4); + + + if (code == 0xFE39FE39) return 0xFFFFFFFF; + + weight = get_weight_if_chinese_character(code); + if (weight > PINYIN_WEIGHT_BASE) return weight; + if (CASESENSITIVE == INSENSITIVE) { + caseup_code = get_casefolded_code(cs, src, mblen, 1); + if (caseup_code == 0) caseup_code = code; + code = caseup_code; + } + weight = (code <= 0xFFFF) + ? code + : COMMON_WEIGHT_BASE + gb18030_4_code_to_diff(code); + + return weight; +} + +template +static int ob_strnncoll_gb18030_internal(const ObCharsetInfo *cs, + const unsigned char **s_res, size_t s_length, + const unsigned char **t_res, size_t t_length) { + const unsigned char *s = *s_res; + const unsigned char *t = *t_res; + const unsigned char *se = s + s_length; + const unsigned char *te = t + t_length; + + ob_charset_assert(cs != NULL); + + while (s < se && t < te) { + unsigned int mblen_s = ob_ismbchar_gb18030(cs, (char *)s, (char *)se); + unsigned int mblen_t = ob_ismbchar_gb18030(cs, (char *)t, (char *)te); + + if (mblen_s > 0 && mblen_t > 0) { + unsigned int code_s = get_weight_for_mbchar(cs, s, mblen_s); + unsigned int code_t = get_weight_for_mbchar(cs, t, mblen_t); + + if (code_s != code_t) return code_s > code_t ? 1 : -1; + + s += mblen_s; + t += mblen_t; + } else if (mblen_s == 0 && mblen_t == 0) { + unsigned char so = cs->sort_order[*s++], to = cs->sort_order[*t++]; + if (so != to) return (int)(so - to); + } else { + return mblen_s == 0 ? -1 : 1; + } + } + + *s_res = s; + *t_res = t; + return 0; +} + +template +static int ob_strnncoll_gb18030(const ObCharsetInfo *cs, const uchar *s, + size_t s_length, const uchar *t, + size_t t_length, bool t_is_prefix) { + int res = ob_strnncoll_gb18030_internal(cs, &s, s_length, &t, t_length); + + if (res != 0) { + return res; + } else if (t_is_prefix && s_length > t_length) { + return 0; + } + return (int)(s_length - t_length); +} + +template +static int ob_strnncollsp_gb18030(const ObCharsetInfo *cs, const uchar *s, + size_t s_length, const uchar *t, + size_t t_length, bool diff_if_only_endspace_difference) { + const unsigned char *se = s + s_length, *te = t + t_length; + int res = ob_strnncoll_gb18030_internal(cs, &s, s_length, &t, t_length); + + if (!res && (s != se || t != te)) { + int swap = 1; + if (diff_if_only_endspace_difference) { + return s_length < t_length ? -1 : 1; + } else if (s_length < t_length) { + s = t; + se = te; + swap = -1; + res = -res; + } + + for (; s < se; s++) { + if (*s != 0x20) return (*s < 0x20) ? -swap : swap; + } + } + + return res; +} + +template +static size_t ob_strnxfrm_gb18030(const ObCharsetInfo *cs, uchar *dst, + size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags, + bool *is_valid_unicode) { + unsigned char *ds = dst; + unsigned char *de = dst + dstlen; + const unsigned char *se = src + srclen; + const unsigned char *sort_order; + *is_valid_unicode = 1; + + ob_charset_assert(cs != NULL); + sort_order = cs->sort_order; + + for (; dst < de && src < se && nweights; nweights--) { + unsigned int mblen = cs->cset->ismbchar(cs, (const char *)src, (const char *)se); + + if (mblen > 0) { + unsigned int weight = get_weight_for_mbchar(cs, src, mblen); + dst += code_to_gb18030_chs(dst, de - dst, weight); + src += mblen; + } else { + *dst++ = sort_order ? sort_order[*src] : *src; + ++src; + } + } + return ob_strxfrm_pad(cs, ds, dst, de, nweights, flags); +} + +size_t ob_varlen_encoding_gb18030_for_memcmp(const struct ObCharsetInfo* cs, + uchar* dst, size_t dst_len, uint nweights, + const uchar *src, size_t src_len, + bool *is_valid_unicode) +{ + uchar *dst0 = dst; + uchar *de = dst + dst_len; + const uchar *se = src + src_len; + const uchar *sort_order; + *is_valid_unicode = 1; + ob_charset_assert(cs != NULL); + sort_order = cs->sort_order; + for (; dst < de && src < se && nweights; nweights--) { + uint mblen = cs->cset->ismbchar(cs, (const char *)src, (const char *)se); + uint weight = 0; + if (mblen > 0) { + weight = get_weight_for_mbchar(cs, src, mblen); + } else { + weight = sort_order ? sort_order[*src] : *src; + ++src; + } + if (weight == 0) { + dst += code_to_gb18030_chs(dst, de - dst, weight); + weight = 0x0000000000000001; + } + dst += code_to_gb18030_chs(dst, de - dst, weight); + src += mblen; + } + // adds 0x0000 0000 0000 0000, 0x0000 0000 0000 0000 + memset(dst, 0x00, 8); + dst += 8; + return dst - dst0; +} +uint16_t find_space_char_count_gb18030(const uchar* src, const uchar* se) +{ + int space_cnt = 1; + while (*(src+space_cnt) == 0x20 && (src+space_cnt)sort_order; + uint16_t space_cnt = 0xFFFF; + for (; dst < de && src < se && nweights; nweights--) { + // for reslovable multiple bytes, only space's first byte is 0x20, + // in gb18030 encoding scheme + if (*src == 0x20) { + space_cnt = find_space_char_count_gb18030(src, se); + if (space_cnt == 0) break; + memset(dst, 0x00, 8); + *(dst+3) = 0x20; + if (*(src+space_cnt) > 0x20){ + *(dst+7)=0x21; + // flip + uint16_t tmp_cnt = space_cnt ^ 0xFFFF; + *(dst+8)=*((uchar*)&tmp_cnt+1); + *(dst+9)=*(&tmp_cnt); + } else { + *(dst+7) = 0x19; + *(dst+8)=*((uchar*)&space_cnt+1); + *(dst+9)=*(&space_cnt); + } + dst += 10; + src += space_cnt; + } + uint mblen = cs->cset->ismbchar(cs, (const char *)src, (const char *)se); + uint weight = 0; + if (mblen > 0) { + weight = get_weight_for_mbchar(cs, src, mblen); + src += mblen; + } else { + weight = sort_order ? sort_order[*src] : *src; + ++src; + } + dst += code_to_gb18030_chs(dst, de - dst, weight); + } + // adds 0x20, 0x20 + memset(dst, 0x00, 8); + *(dst+3) = 0x20; + *(dst+7) = 0x20; + dst += 8; + return dst - dst0; +} + +size_t ob_strnxfrm_gb18030_varlen(const struct ObCharsetInfo* cs, + uchar* dst, size_t dst_len, uint nweights, + const uchar *src, size_t srclen, + bool is_memcmp, bool *is_valid_unicode) +{ + if (is_memcmp) { + return ob_varlen_encoding_gb18030_for_memcmp(cs, dst, dst_len, nweights, + src, srclen, is_valid_unicode); + } else { + return ob_varlen_encoding_gb18030_for_spacecmp(cs, dst, dst_len, nweights, + src, srclen, is_valid_unicode); + } +} + +static unsigned int unicode_to_gb18030_code(const ObCharsetInfo *cs, int unicode) { + unsigned char dst[4]; + unsigned int dst_len; + int res; + + ob_charset_assert(cs != NULL); + + res = cs->cset->wc_mb(cs, unicode, dst, dst + 4); + + ob_charset_assert(res == 1 || res == 2 || res == 4); + + dst_len = (unsigned int)res; + return gb18030_chs_to_code(dst, dst_len); +} + +static size_t get_code_and_length(const ObCharsetInfo *cs, const char *s, + const char *e, size_t *code) { + size_t len; + + if (s >= e) { + return 0; + } else if (is_mb_1(s[0])) { + *code = s[0]; + return 1; + } else if ((len = ob_ismbchar_gb18030(cs, s, e)) == 0) { + return 0; + } + + ob_charset_assert(len == 2 || len == 4); + *code = gb18030_chs_to_code((const unsigned char *)s, len); + return len; +} + +template +static unsigned int get_weight_for_gb18030_chs(const ObCharsetInfo *cs, const char *s, + size_t s_len) { + ob_charset_assert(s_len == 1 || s_len == 2 || s_len == 4); + + if (s_len == 1) { + ob_charset_assert(is_mb_1(*s)); + return cs->sort_order[(unsigned char)*s]; + } + + return get_weight_for_mbchar(cs, (const unsigned char *)s, s_len); +} + +template +static int ob_wildcmp_gb18030_impl(const ObCharsetInfo *cs, const char *str, + const char *str_end, const char *wild_str, + const char *wild_end, unsigned int escape_char, unsigned int w_one, + unsigned int w_many, int recurse_level) { + int result = -1; + size_t s_gb, w_gb; + size_t s_len = 0, w_len; + + + + while (wild_str != wild_end) { + while (TRUE) { + bool escaped = 0; + if ((w_len = get_code_and_length(cs, wild_str, wild_end, &w_gb)) == 0) + return 1; + + if (w_gb == w_many) { + result = 1; + break; + } + + wild_str += w_len; + if (w_gb == escape_char && wild_str < wild_end) { + if ((w_len = get_code_and_length(cs, wild_str, wild_end, &w_gb)) == 0) + return 1; + + wild_str += w_len; + escaped = 1; + } + + if ((s_len = get_code_and_length(cs, str, str_end, &s_gb)) == 0) return 1; + str += s_len; + + if (!escaped && w_gb == w_one) { + result = 1; + } else { + s_gb = get_weight_for_gb18030_chs(cs, str - s_len, s_len); + w_gb = get_weight_for_gb18030_chs(cs, wild_str - w_len, w_len); + if (s_gb != w_gb) return 1; /* No match */ + } + + if (wild_str == wild_end) + return (str != str_end); + } + + if (w_gb == w_many) { + + for (; wild_str != wild_end;) { + if ((w_len = get_code_and_length(cs, wild_str, wild_end, &w_gb)) == 0) { + return 1; + } else if (w_gb == w_many) { + wild_str += w_len; + continue; + } else if (w_gb == w_one) { + wild_str += w_len; + + if ((s_len = get_code_and_length(cs, str, str_end, &s_gb)) == 0) + return 1; + str += s_len; + continue; + } else + break; + } + + if (wild_str == wild_end) return 0; + else if (str == str_end) return -1; + else if ((w_len = get_code_and_length(cs, wild_str, wild_end, &w_gb)) == 0) + return 1; + else wild_str += w_len; + + if (w_gb == escape_char) { + if (wild_str < wild_end) { + if ((w_len = get_code_and_length(cs, wild_str, wild_end, &w_gb)) == 0) { + return 1; + } else { + wild_str += w_len; + } + } + } + + while (TRUE) { + while (str != str_end) { + if ((s_len = get_code_and_length(cs, str, str_end, &s_gb)) == 0) { + return 1; + } + + s_gb = get_weight_for_gb18030_chs(cs, str, s_len); + w_gb = get_weight_for_gb18030_chs(cs, wild_str - w_len, w_len); + if (s_gb == w_gb) { + break; + } else { + str += s_len; + } + } + + if (str == str_end) { + return -1; + } else { + str += s_len; + } + + result = ob_wildcmp_gb18030_impl(cs, str, str_end, wild_str, wild_end, escape_char, + w_one, w_many, recurse_level + 1); + if (result <= 0) return result; + } + } + } + + return (str != str_end ? 1 : 0); +} + +template +static int ob_wildcmp_gb18030(const ObCharsetInfo *cs, const char *str, + const char *str_end, const char *wild_str, + const char *wild_end, int escape_char, int w_one, + int w_many) { + unsigned int escape_gb, w_one_gb, w_many_gb; + + escape_gb = unicode_to_gb18030_code(cs, escape_char); + w_one_gb = unicode_to_gb18030_code(cs, w_one); + w_many_gb = unicode_to_gb18030_code(cs, w_many); + + return ob_wildcmp_gb18030_impl(cs, str, str_end, wild_str, wild_end, escape_gb, + w_one_gb, w_many_gb, 1); +} + +template +static void ob_hash_sort_gb18030(const ObCharsetInfo *cs, const uchar *s, + size_t slen, ulong *n1, ulong *n2, + const bool calc_end_space, hash_algo hash_algo) { + const unsigned char *e = s + slen; + unsigned long int tmp1, tmp2; + size_t len; + size_t s_gb; + unsigned int ch; + + int length = 0; + unsigned char data[HASH_BUFFER_LENGTH]; + + if (!calc_end_space) { + while (e > s && e[-1] == 0x20) e--; + } + + tmp1 = *n1; + tmp2 = *n2; + + if (NULL == hash_algo) { + while ((len = get_code_and_length(cs, (const char *)s, (const char *)e, + &s_gb)) != 0) { + s_gb = get_weight_for_gb18030_chs(cs, (const char *)s, len); + + ch = (s_gb & 0xFF); + tmp1 ^= (((tmp1 & 63) + tmp2) * ch) + (tmp1 << 8); + tmp2 += 3; + + ch = (s_gb >> 8) & 0xFF; + tmp1 ^= (((tmp1 & 63) + tmp2) * ch) + (tmp1 << 8); + tmp2 += 3; + + ch = (s_gb >> 16) & 0xFF; + tmp1 ^= (((tmp1 & 63) + tmp2) * ch) + (tmp1 << 8); + tmp2 += 3; + + ch = (s_gb >> 24) & 0xFF; + tmp1 ^= (((tmp1 & 63) + tmp2) * ch) + (tmp1 << 8); + tmp2 += 3; + + s += len; + } + } else { + while ((len = get_code_and_length(cs, (const char *)s, (const char *)e, + &s_gb)) != 0) { + s_gb = get_weight_for_gb18030_chs(cs, (const char *)s, len); + if (length > HASH_BUFFER_LENGTH - 4) { + tmp1 = hash_algo((void*) &data, length, tmp1); + length = 0; + } + memcpy(data+length, &s_gb, 4); + length += 4; + s+= len; + } + if (length > 0) { + tmp1 = hash_algo((void*) &data, length, tmp1); + } + } + + *n1 = tmp1; + *n2 = tmp2; +} + +static ObCollationHandler ob_collation_ci_handler = +{ + ob_strnncoll_gb18030, + ob_strnncollsp_gb18030, + ob_strnxfrm_gb18030, + ob_like_range_mb, + ob_wildcmp_gb18030, + ob_instr_mb, + ob_hash_sort_gb18030, + ob_propagate_simple +}; + +static ObCharsetHandler ob_charset_gb18030_handler = { + ob_ismbchar_gb18030, + ob_mbcharlen_gb18030, + ob_numchars_mb, + ob_charpos_mb, + ob_max_bytes_charpos_mb, + ob_well_formed_len_gb18030, + ob_lengthsp_8bit, + ob_mb_wc_gb18030, + ob_wc_mb_gb18030_chs, + ob_mb_ctype_mb, + ob_caseup_gb18030, + ob_casedn_gb18030, + ob_fill_8bit, + ob_strntol_8bit, + ob_strntoul_8bit, + ob_strntoll_8bit, + ob_strntoull_8bit, + ob_strntod_8bit, + ob_strntoull10rnd_8bit, + ob_scan_8bit}; + +ObCharsetInfo ob_charset_gb18030_chinese_ci = { + 248, + 0, + 0, /* number */ + OB_CS_COMPILED | OB_CS_PRIMARY | OB_CS_STRNXFRM, /* state */ + "gb18030", /* cs name */ + "gb18030_chinese_ci", /* name */ + "", /* comment */ + NULL, /* tailoring */ + ctype_gb18030, /* ctype */ + to_lower_gb18030, /* lower */ + to_upper_gb18030, /* UPPER */ + sort_order_gb18030_ci, /* sort */ + NULL, /* uca */ + &ob_caseinfo_gb18030, /* caseinfo */ + NULL, /* state_map */ + NULL, /* ident_map */ + 2, /* strxfrm_multiply */ + 2, /* caseup_multiply */ + 2, /* casedn_multiply */ + 1, /* mbminlen */ + 4, /* mbmaxlen */ + 0, /* min_sort_char */ + 0xFE39FE39, /* max_sort_char */ + ' ', /* pad char */ + 1, /* escape_with_backslash_is_dangerous */ + 1, /* levels_for_compare */ + 1, + &ob_charset_gb18030_handler, + &ob_collation_ci_handler}; + +ObCharsetInfo ob_charset_gb18030_bin = { + 249, + 0, + 0, + OB_CS_COMPILED | OB_CS_BINSORT, + "gb18030", + "gb18030_bin", + "", + NULL, + ctype_gb18030, + to_lower_gb18030, + to_upper_gb18030, + NULL, + NULL, + &ob_caseinfo_gb18030, + NULL, + NULL, + 1, + 2, + 2, + 1, + 4, + 0, + 0xFEFEFEFE, + ' ', + 1, + 1, + 1, + &ob_charset_gb18030_handler, + &ob_collation_mb_bin_handler}; diff --git a/src/lib/charset/ob_ctype_gbk.c b/src/lib/charset/ob_ctype_gbk.c new file mode 100644 index 0000000000000000000000000000000000000000..93501c42bb40127d3af0e6184ef594d91f7da376 --- /dev/null +++ b/src/lib/charset/ob_ctype_gbk.c @@ -0,0 +1,10927 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#include "lib/charset/ob_ctype.h" + +#define isgbkhead(c) (0x81<=(unsigned char)(c) && (unsigned char)(c)<=0xfe) +#define isgbktail(c) ((0x40<=(unsigned char)(c) && (unsigned char)(c)<=0x7e) || \ + (0x80<=(unsigned char)(c) && (unsigned char)(c)<=0xfe)) + +#define isgbkcode(c,d) (isgbkhead(c) && isgbktail(d)) +#define gbkcode(c,d) ((((unsigned int) (unsigned char) (c)) <<8) | (unsigned char)(d)) +#define gbkhead(e) ((unsigned char)(e>>8)) +#define gbktail(e) ((unsigned char)(e&0xff)) + +static unsigned char ctype_gbk[257] = +{ + 0, + 32,32,32,32,32,32,32,32,32,40,40,40,40,40,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 72,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 132,132,132,132,132,132,132,132,132,132,16,16,16,16,16,16, + 16,129,129,129,129,129,129,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,16,16,16,16,16, + 16,130,130,130,130,130,130,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,16,16,16,16,32, + 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,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0, +}; + +static unsigned char to_lower_gbk[]= +{ + '\000','\001','\002','\003','\004','\005','\006','\007', + '\010','\011','\012','\013','\014','\015','\016','\017', + '\020','\021','\022','\023','\024','\025','\026','\027', + '\030','\031','\032','\033','\034','\035','\036','\037', + ' ', '!', '"', '#', '$', '%', '&', '\'', + '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', ':', ';', '<', '=', '>', '?', + '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', '[', '\\', ']', '^', '_', + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', '{', '|', '}', '~', '\177', + (unsigned char) '\200',(unsigned char) '\201',(unsigned char) '\202',(unsigned char) '\203',(unsigned char) '\204',(unsigned char) '\205',(unsigned char) '\206',(unsigned char) '\207', + (unsigned char) '\210',(unsigned char) '\211',(unsigned char) '\212',(unsigned char) '\213',(unsigned char) '\214',(unsigned char) '\215',(unsigned char) '\216',(unsigned char) '\217', + (unsigned char) '\220',(unsigned char) '\221',(unsigned char) '\222',(unsigned char) '\223',(unsigned char) '\224',(unsigned char) '\225',(unsigned char) '\226',(unsigned char) '\227', + (unsigned char) '\230',(unsigned char) '\231',(unsigned char) '\232',(unsigned char) '\233',(unsigned char) '\234',(unsigned char) '\235',(unsigned char) '\236',(unsigned char) '\237', + (unsigned char) '\240',(unsigned char) '\241',(unsigned char) '\242',(unsigned char) '\243',(unsigned char) '\244',(unsigned char) '\245',(unsigned char) '\246',(unsigned char) '\247', + (unsigned char) '\250',(unsigned char) '\251',(unsigned char) '\252',(unsigned char) '\253',(unsigned char) '\254',(unsigned char) '\255',(unsigned char) '\256',(unsigned char) '\257', + (unsigned char) '\260',(unsigned char) '\261',(unsigned char) '\262',(unsigned char) '\263',(unsigned char) '\264',(unsigned char) '\265',(unsigned char) '\266',(unsigned char) '\267', + (unsigned char) '\270',(unsigned char) '\271',(unsigned char) '\272',(unsigned char) '\273',(unsigned char) '\274',(unsigned char) '\275',(unsigned char) '\276',(unsigned char) '\277', + (unsigned char) '\300',(unsigned char) '\301',(unsigned char) '\302',(unsigned char) '\303',(unsigned char) '\304',(unsigned char) '\305',(unsigned char) '\306',(unsigned char) '\307', + (unsigned char) '\310',(unsigned char) '\311',(unsigned char) '\312',(unsigned char) '\313',(unsigned char) '\314',(unsigned char) '\315',(unsigned char) '\316',(unsigned char) '\317', + (unsigned char) '\320',(unsigned char) '\321',(unsigned char) '\322',(unsigned char) '\323',(unsigned char) '\324',(unsigned char) '\325',(unsigned char) '\326',(unsigned char) '\327', + (unsigned char) '\330',(unsigned char) '\331',(unsigned char) '\332',(unsigned char) '\333',(unsigned char) '\334',(unsigned char) '\335',(unsigned char) '\336',(unsigned char) '\337', + (unsigned char) '\340',(unsigned char) '\341',(unsigned char) '\342',(unsigned char) '\343',(unsigned char) '\344',(unsigned char) '\345',(unsigned char) '\346',(unsigned char) '\347', + (unsigned char) '\350',(unsigned char) '\351',(unsigned char) '\352',(unsigned char) '\353',(unsigned char) '\354',(unsigned char) '\355',(unsigned char) '\356',(unsigned char) '\357', + (unsigned char) '\360',(unsigned char) '\361',(unsigned char) '\362',(unsigned char) '\363',(unsigned char) '\364',(unsigned char) '\365',(unsigned char) '\366',(unsigned char) '\367', + (unsigned char) '\370',(unsigned char) '\371',(unsigned char) '\372',(unsigned char) '\373',(unsigned char) '\374',(unsigned char) '\375',(unsigned char) '\376',(unsigned char) '\377', +}; + +static unsigned char to_upper_gbk[]= +{ + '\000','\001','\002','\003','\004','\005','\006','\007', + '\010','\011','\012','\013','\014','\015','\016','\017', + '\020','\021','\022','\023','\024','\025','\026','\027', + '\030','\031','\032','\033','\034','\035','\036','\037', + ' ', '!', '"', '#', '$', '%', '&', '\'', + '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', ':', ';', '<', '=', '>', '?', + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', + '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '{', '|', '}', '~', '\177', + (unsigned char) '\200',(unsigned char) '\201',(unsigned char) '\202',(unsigned char) '\203',(unsigned char) '\204',(unsigned char) '\205',(unsigned char) '\206',(unsigned char) '\207', + (unsigned char) '\210',(unsigned char) '\211',(unsigned char) '\212',(unsigned char) '\213',(unsigned char) '\214',(unsigned char) '\215',(unsigned char) '\216',(unsigned char) '\217', + (unsigned char) '\220',(unsigned char) '\221',(unsigned char) '\222',(unsigned char) '\223',(unsigned char) '\224',(unsigned char) '\225',(unsigned char) '\226',(unsigned char) '\227', + (unsigned char) '\230',(unsigned char) '\231',(unsigned char) '\232',(unsigned char) '\233',(unsigned char) '\234',(unsigned char) '\235',(unsigned char) '\236',(unsigned char) '\237', + (unsigned char) '\240',(unsigned char) '\241',(unsigned char) '\242',(unsigned char) '\243',(unsigned char) '\244',(unsigned char) '\245',(unsigned char) '\246',(unsigned char) '\247', + (unsigned char) '\250',(unsigned char) '\251',(unsigned char) '\252',(unsigned char) '\253',(unsigned char) '\254',(unsigned char) '\255',(unsigned char) '\256',(unsigned char) '\257', + (unsigned char) '\260',(unsigned char) '\261',(unsigned char) '\262',(unsigned char) '\263',(unsigned char) '\264',(unsigned char) '\265',(unsigned char) '\266',(unsigned char) '\267', + (unsigned char) '\270',(unsigned char) '\271',(unsigned char) '\272',(unsigned char) '\273',(unsigned char) '\274',(unsigned char) '\275',(unsigned char) '\276',(unsigned char) '\277', + (unsigned char) '\300',(unsigned char) '\301',(unsigned char) '\302',(unsigned char) '\303',(unsigned char) '\304',(unsigned char) '\305',(unsigned char) '\306',(unsigned char) '\307', + (unsigned char) '\310',(unsigned char) '\311',(unsigned char) '\312',(unsigned char) '\313',(unsigned char) '\314',(unsigned char) '\315',(unsigned char) '\316',(unsigned char) '\317', + (unsigned char) '\320',(unsigned char) '\321',(unsigned char) '\322',(unsigned char) '\323',(unsigned char) '\324',(unsigned char) '\325',(unsigned char) '\326',(unsigned char) '\327', + (unsigned char) '\330',(unsigned char) '\331',(unsigned char) '\332',(unsigned char) '\333',(unsigned char) '\334',(unsigned char) '\335',(unsigned char) '\336',(unsigned char) '\337', + (unsigned char) '\340',(unsigned char) '\341',(unsigned char) '\342',(unsigned char) '\343',(unsigned char) '\344',(unsigned char) '\345',(unsigned char) '\346',(unsigned char) '\347', + (unsigned char) '\350',(unsigned char) '\351',(unsigned char) '\352',(unsigned char) '\353',(unsigned char) '\354',(unsigned char) '\355',(unsigned char) '\356',(unsigned char) '\357', + (unsigned char) '\360',(unsigned char) '\361',(unsigned char) '\362',(unsigned char) '\363',(unsigned char) '\364',(unsigned char) '\365',(unsigned char) '\366',(unsigned char) '\367', + (unsigned char) '\370',(unsigned char) '\371',(unsigned char) '\372',(unsigned char) '\373',(unsigned char) '\374',(unsigned char) '\375',(unsigned char) '\376',(unsigned char) '\377', +}; + + +static ObUnicaseInfoChar cA2[256]= +{ + {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,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,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},{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,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}, + {0xA240,0xA240,0x003F}, + {0xA241,0xA241,0x003F}, + {0xA242,0xA242,0x003F}, + {0xA243,0xA243,0x003F}, + {0xA244,0xA244,0x003F}, + {0xA245,0xA245,0x003F}, + {0xA246,0xA246,0x003F}, + {0xA247,0xA247,0x003F}, + {0xA248,0xA248,0x003F}, + {0xA249,0xA249,0x003F}, + {0xA24A,0xA24A,0x003F}, + {0xA24B,0xA24B,0x003F}, + {0xA24C,0xA24C,0x003F}, + {0xA24D,0xA24D,0x003F}, + {0xA24E,0xA24E,0x003F}, + {0xA24F,0xA24F,0x003F}, + {0xA250,0xA250,0x003F}, + {0xA251,0xA251,0x003F}, + {0xA252,0xA252,0x003F}, + {0xA253,0xA253,0x003F}, + {0xA254,0xA254,0x003F}, + {0xA255,0xA255,0x003F}, + {0xA256,0xA256,0x003F}, + {0xA257,0xA257,0x003F}, + {0xA258,0xA258,0x003F}, + {0xA259,0xA259,0x003F}, + {0xA25A,0xA25A,0x003F}, + {0xA25B,0xA25B,0x003F}, + {0xA25C,0xA25C,0x003F}, + {0xA25D,0xA25D,0x003F}, + {0xA25E,0xA25E,0x003F}, + {0xA25F,0xA25F,0x003F}, + {0xA260,0xA260,0x003F}, + {0xA261,0xA261,0x003F}, + {0xA262,0xA262,0x003F}, + {0xA263,0xA263,0x003F}, + {0xA264,0xA264,0x003F}, + {0xA265,0xA265,0x003F}, + {0xA266,0xA266,0x003F}, + {0xA267,0xA267,0x003F}, + {0xA268,0xA268,0x003F}, + {0xA269,0xA269,0x003F}, + {0xA26A,0xA26A,0x003F}, + {0xA26B,0xA26B,0x003F}, + {0xA26C,0xA26C,0x003F}, + {0xA26D,0xA26D,0x003F}, + {0xA26E,0xA26E,0x003F}, + {0xA26F,0xA26F,0x003F}, + {0xA270,0xA270,0x003F}, + {0xA271,0xA271,0x003F}, + {0xA272,0xA272,0x003F}, + {0xA273,0xA273,0x003F}, + {0xA274,0xA274,0x003F}, + {0xA275,0xA275,0x003F}, + {0xA276,0xA276,0x003F}, + {0xA277,0xA277,0x003F}, + {0xA278,0xA278,0x003F}, + {0xA279,0xA279,0x003F}, + {0xA27A,0xA27A,0x003F}, + {0xA27B,0xA27B,0x003F}, + {0xA27C,0xA27C,0x003F}, + {0xA27D,0xA27D,0x003F}, + {0xA27E,0xA27E,0x003F}, + {0xA27F,0xA27F,0xA27F}, + {0xA280,0xA280,0x003F}, + {0xA281,0xA281,0x003F}, + {0xA282,0xA282,0x003F}, + {0xA283,0xA283,0x003F}, + {0xA284,0xA284,0x003F}, + {0xA285,0xA285,0x003F}, + {0xA286,0xA286,0x003F}, + {0xA287,0xA287,0x003F}, + {0xA288,0xA288,0x003F}, + {0xA289,0xA289,0x003F}, + {0xA28A,0xA28A,0x003F}, + {0xA28B,0xA28B,0x003F}, + {0xA28C,0xA28C,0x003F}, + {0xA28D,0xA28D,0x003F}, + {0xA28E,0xA28E,0x003F}, + {0xA28F,0xA28F,0x003F}, + {0xA290,0xA290,0x003F}, + {0xA291,0xA291,0x003F}, + {0xA292,0xA292,0x003F}, + {0xA293,0xA293,0x003F}, + {0xA294,0xA294,0x003F}, + {0xA295,0xA295,0x003F}, + {0xA296,0xA296,0x003F}, + {0xA297,0xA297,0x003F}, + {0xA298,0xA298,0x003F}, + {0xA299,0xA299,0x003F}, + {0xA29A,0xA29A,0x003F}, + {0xA29B,0xA29B,0x003F}, + {0xA29C,0xA29C,0x003F}, + {0xA29D,0xA29D,0x003F}, + {0xA29E,0xA29E,0x003F}, + {0xA29F,0xA29F,0x003F}, + {0xA2A0,0xA2A0,0x003F}, + {0xA2F1,0xA2A1,0x2170}, + {0xA2F2,0xA2A2,0x2171}, + {0xA2F3,0xA2A3,0x2172}, + {0xA2F4,0xA2A4,0x2173}, + {0xA2F5,0xA2A5,0x2174}, + {0xA2F6,0xA2A6,0x2175}, + {0xA2F7,0xA2A7,0x2176}, + {0xA2F8,0xA2A8,0x2177}, + {0xA2F9,0xA2A9,0x2178}, + {0xA2FA,0xA2AA,0x2179}, + {0xA2AB,0xA2AB,0x003F}, + {0xA2AC,0xA2AC,0x003F}, + {0xA2AD,0xA2AD,0x003F}, + {0xA2AE,0xA2AE,0x003F}, + {0xA2AF,0xA2AF,0x003F}, + {0xA2B0,0xA2B0,0x003F}, + {0xA2B1,0xA2B1,0x2488}, + {0xA2B2,0xA2B2,0x2489}, + {0xA2B3,0xA2B3,0x248A}, + {0xA2B4,0xA2B4,0x248B}, + {0xA2B5,0xA2B5,0x248C}, + {0xA2B6,0xA2B6,0x248D}, + {0xA2B7,0xA2B7,0x248E}, + {0xA2B8,0xA2B8,0x248F}, + {0xA2B9,0xA2B9,0x2490}, + {0xA2BA,0xA2BA,0x2491}, + {0xA2BB,0xA2BB,0x2492}, + {0xA2BC,0xA2BC,0x2493}, + {0xA2BD,0xA2BD,0x2494}, + {0xA2BE,0xA2BE,0x2495}, + {0xA2BF,0xA2BF,0x2496}, + {0xA2C0,0xA2C0,0x2497}, + {0xA2C1,0xA2C1,0x2498}, + {0xA2C2,0xA2C2,0x2499}, + {0xA2C3,0xA2C3,0x249A}, + {0xA2C4,0xA2C4,0x249B}, + {0xA2C5,0xA2C5,0x2474}, + {0xA2C6,0xA2C6,0x2475}, + {0xA2C7,0xA2C7,0x2476}, + {0xA2C8,0xA2C8,0x2477}, + {0xA2C9,0xA2C9,0x2478}, + {0xA2CA,0xA2CA,0x2479}, + {0xA2CB,0xA2CB,0x247A}, + {0xA2CC,0xA2CC,0x247B}, + {0xA2CD,0xA2CD,0x247C}, + {0xA2CE,0xA2CE,0x247D}, + {0xA2CF,0xA2CF,0x247E}, + {0xA2D0,0xA2D0,0x247F}, + {0xA2D1,0xA2D1,0x2480}, + {0xA2D2,0xA2D2,0x2481}, + {0xA2D3,0xA2D3,0x2482}, + {0xA2D4,0xA2D4,0x2483}, + {0xA2D5,0xA2D5,0x2484}, + {0xA2D6,0xA2D6,0x2485}, + {0xA2D7,0xA2D7,0x2486}, + {0xA2D8,0xA2D8,0x2487}, + {0xA2D9,0xA2D9,0x2460}, + {0xA2DA,0xA2DA,0x2461}, + {0xA2DB,0xA2DB,0x2462}, + {0xA2DC,0xA2DC,0x2463}, + {0xA2DD,0xA2DD,0x2464}, + {0xA2DE,0xA2DE,0x2465}, + {0xA2DF,0xA2DF,0x2466}, + {0xA2E0,0xA2E0,0x2467}, + {0xA2E1,0xA2E1,0x2468}, + {0xA2E2,0xA2E2,0x2469}, + {0xA2E3,0xA2E3,0x003F}, + {0xA2E4,0xA2E4,0x003F}, + {0xA2E5,0xA2E5,0x3220}, + {0xA2E6,0xA2E6,0x3221}, + {0xA2E7,0xA2E7,0x3222}, + {0xA2E8,0xA2E8,0x3223}, + {0xA2E9,0xA2E9,0x3224}, + {0xA2EA,0xA2EA,0x3225}, + {0xA2EB,0xA2EB,0x3226}, + {0xA2EC,0xA2EC,0x3227}, + {0xA2ED,0xA2ED,0x3228}, + {0xA2EE,0xA2EE,0x3229}, + {0xA2EF,0xA2EF,0x003F}, + {0xA2F0,0xA2F0,0x003F}, + {0xA2F1,0xA2A1,0x2160}, + {0xA2F2,0xA2A2,0x2161}, + {0xA2F3,0xA2A3,0x2162}, + {0xA2F4,0xA2A4,0x2163}, + {0xA2F5,0xA2A5,0x2164}, + {0xA2F6,0xA2A6,0x2165}, + {0xA2F7,0xA2A7,0x2166}, + {0xA2F8,0xA2A8,0x2167}, + {0xA2F9,0xA2A9,0x2168}, + {0xA2FA,0xA2AA,0x2169}, + {0xA2FB,0xA2FB,0x216A}, + {0xA2FC,0xA2FC,0x216B}, + {0xA2FD,0xA2FD,0x003F}, + {0xA2FE,0xA2FE,0x003F}, + {0xA2FF,0xA2FF,0xA2FF} +}; + +static ObUnicaseInfoChar cA3[256]= +{ + {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,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,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},{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,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}, + {0xA340,0xA340,0x003F}, + {0xA341,0xA341,0x003F}, + {0xA342,0xA342,0x003F}, + {0xA343,0xA343,0x003F}, + {0xA344,0xA344,0x003F}, + {0xA345,0xA345,0x003F}, + {0xA346,0xA346,0x003F}, + {0xA347,0xA347,0x003F}, + {0xA348,0xA348,0x003F}, + {0xA349,0xA349,0x003F}, + {0xA34A,0xA34A,0x003F}, + {0xA34B,0xA34B,0x003F}, + {0xA34C,0xA34C,0x003F}, + {0xA34D,0xA34D,0x003F}, + {0xA34E,0xA34E,0x003F}, + {0xA34F,0xA34F,0x003F}, + {0xA350,0xA350,0x003F}, + {0xA351,0xA351,0x003F}, + {0xA352,0xA352,0x003F}, + {0xA353,0xA353,0x003F}, + {0xA354,0xA354,0x003F}, + {0xA355,0xA355,0x003F}, + {0xA356,0xA356,0x003F}, + {0xA357,0xA357,0x003F}, + {0xA358,0xA358,0x003F}, + {0xA359,0xA359,0x003F}, + {0xA35A,0xA35A,0x003F}, + {0xA35B,0xA35B,0x003F}, + {0xA35C,0xA35C,0x003F}, + {0xA35D,0xA35D,0x003F}, + {0xA35E,0xA35E,0x003F}, + {0xA35F,0xA35F,0x003F}, + {0xA360,0xA360,0x003F}, + {0xA361,0xA361,0x003F}, + {0xA362,0xA362,0x003F}, + {0xA363,0xA363,0x003F}, + {0xA364,0xA364,0x003F}, + {0xA365,0xA365,0x003F}, + {0xA366,0xA366,0x003F}, + {0xA367,0xA367,0x003F}, + {0xA368,0xA368,0x003F}, + {0xA369,0xA369,0x003F}, + {0xA36A,0xA36A,0x003F}, + {0xA36B,0xA36B,0x003F}, + {0xA36C,0xA36C,0x003F}, + {0xA36D,0xA36D,0x003F}, + {0xA36E,0xA36E,0x003F}, + {0xA36F,0xA36F,0x003F}, + {0xA370,0xA370,0x003F}, + {0xA371,0xA371,0x003F}, + {0xA372,0xA372,0x003F}, + {0xA373,0xA373,0x003F}, + {0xA374,0xA374,0x003F}, + {0xA375,0xA375,0x003F}, + {0xA376,0xA376,0x003F}, + {0xA377,0xA377,0x003F}, + {0xA378,0xA378,0x003F}, + {0xA379,0xA379,0x003F}, + {0xA37A,0xA37A,0x003F}, + {0xA37B,0xA37B,0x003F}, + {0xA37C,0xA37C,0x003F}, + {0xA37D,0xA37D,0x003F}, + {0xA37E,0xA37E,0x003F}, + {0xA37F,0xA37F,0xA37F}, + {0xA380,0xA380,0x003F}, + {0xA381,0xA381,0x003F}, + {0xA382,0xA382,0x003F}, + {0xA383,0xA383,0x003F}, + {0xA384,0xA384,0x003F}, + {0xA385,0xA385,0x003F}, + {0xA386,0xA386,0x003F}, + {0xA387,0xA387,0x003F}, + {0xA388,0xA388,0x003F}, + {0xA389,0xA389,0x003F}, + {0xA38A,0xA38A,0x003F}, + {0xA38B,0xA38B,0x003F}, + {0xA38C,0xA38C,0x003F}, + {0xA38D,0xA38D,0x003F}, + {0xA38E,0xA38E,0x003F}, + {0xA38F,0xA38F,0x003F}, + {0xA390,0xA390,0x003F}, + {0xA391,0xA391,0x003F}, + {0xA392,0xA392,0x003F}, + {0xA393,0xA393,0x003F}, + {0xA394,0xA394,0x003F}, + {0xA395,0xA395,0x003F}, + {0xA396,0xA396,0x003F}, + {0xA397,0xA397,0x003F}, + {0xA398,0xA398,0x003F}, + {0xA399,0xA399,0x003F}, + {0xA39A,0xA39A,0x003F}, + {0xA39B,0xA39B,0x003F}, + {0xA39C,0xA39C,0x003F}, + {0xA39D,0xA39D,0x003F}, + {0xA39E,0xA39E,0x003F}, + {0xA39F,0xA39F,0x003F}, + {0xA3A0,0xA3A0,0x003F}, + {0xA3A1,0xA3A1,0xFF01}, + {0xA3A2,0xA3A2,0xFF02}, + {0xA3A3,0xA3A3,0xFF03}, + {0xA3A4,0xA3A4,0xFFE5}, + {0xA3A5,0xA3A5,0xFF05}, + {0xA3A6,0xA3A6,0xFF06}, + {0xA3A7,0xA3A7,0xFF07}, + {0xA3A8,0xA3A8,0xFF08}, + {0xA3A9,0xA3A9,0xFF09}, + {0xA3AA,0xA3AA,0xFF0A}, + {0xA3AB,0xA3AB,0xFF0B}, + {0xA3AC,0xA3AC,0xFF0C}, + {0xA3AD,0xA3AD,0xFF0D}, + {0xA3AE,0xA3AE,0xFF0E}, + {0xA3AF,0xA3AF,0xFF0F}, + {0xA3B0,0xA3B0,0xFF10}, + {0xA3B1,0xA3B1,0xFF11}, + {0xA3B2,0xA3B2,0xFF12}, + {0xA3B3,0xA3B3,0xFF13}, + {0xA3B4,0xA3B4,0xFF14}, + {0xA3B5,0xA3B5,0xFF15}, + {0xA3B6,0xA3B6,0xFF16}, + {0xA3B7,0xA3B7,0xFF17}, + {0xA3B8,0xA3B8,0xFF18}, + {0xA3B9,0xA3B9,0xFF19}, + {0xA3BA,0xA3BA,0xFF1A}, + {0xA3BB,0xA3BB,0xFF1B}, + {0xA3BC,0xA3BC,0xFF1C}, + {0xA3BD,0xA3BD,0xFF1D}, + {0xA3BE,0xA3BE,0xFF1E}, + {0xA3BF,0xA3BF,0xFF1F}, + {0xA3C0,0xA3C0,0xFF20}, + {0xA3C1,0xA3E1,0xFF21}, + {0xA3C2,0xA3E2,0xFF22}, + {0xA3C3,0xA3E3,0xFF23}, + {0xA3C4,0xA3E4,0xFF24}, + {0xA3C5,0xA3E5,0xFF25}, + {0xA3C6,0xA3E6,0xFF26}, + {0xA3C7,0xA3E7,0xFF27}, + {0xA3C8,0xA3E8,0xFF28}, + {0xA3C9,0xA3E9,0xFF29}, + {0xA3CA,0xA3EA,0xFF2A}, + {0xA3CB,0xA3EB,0xFF2B}, + {0xA3CC,0xA3EC,0xFF2C}, + {0xA3CD,0xA3ED,0xFF2D}, + {0xA3CE,0xA3EE,0xFF2E}, + {0xA3CF,0xA3EF,0xFF2F}, + {0xA3D0,0xA3F0,0xFF30}, + {0xA3D1,0xA3F1,0xFF31}, + {0xA3D2,0xA3F2,0xFF32}, + {0xA3D3,0xA3F3,0xFF33}, + {0xA3D4,0xA3F4,0xFF34}, + {0xA3D5,0xA3F5,0xFF35}, + {0xA3D6,0xA3F6,0xFF36}, + {0xA3D7,0xA3F7,0xFF37}, + {0xA3D8,0xA3F8,0xFF38}, + {0xA3D9,0xA3F9,0xFF39}, + {0xA3DA,0xA3FA,0xFF3A}, + {0xA3DB,0xA3DB,0xFF3B}, + {0xA3DC,0xA3DC,0xFF3C}, + {0xA3DD,0xA3DD,0xFF3D}, + {0xA3DE,0xA3DE,0xFF3E}, + {0xA3DF,0xA3DF,0xFF3F}, + {0xA3E0,0xA3E0,0xFF40}, + {0xA3C1,0xA3E1,0xFF41}, + {0xA3C2,0xA3E2,0xFF42}, + {0xA3C3,0xA3E3,0xFF43}, + {0xA3C4,0xA3E4,0xFF44}, + {0xA3C5,0xA3E5,0xFF45}, + {0xA3C6,0xA3E6,0xFF46}, + {0xA3C7,0xA3E7,0xFF47}, + {0xA3C8,0xA3E8,0xFF48}, + {0xA3C9,0xA3E9,0xFF49}, + {0xA3CA,0xA3EA,0xFF4A}, + {0xA3CB,0xA3EB,0xFF4B}, + {0xA3CC,0xA3EC,0xFF4C}, + {0xA3CD,0xA3ED,0xFF4D}, + {0xA3CE,0xA3EE,0xFF4E}, + {0xA3CF,0xA3EF,0xFF4F}, + {0xA3D0,0xA3F0,0xFF50}, + {0xA3D1,0xA3F1,0xFF51}, + {0xA3D2,0xA3F2,0xFF52}, + {0xA3D3,0xA3F3,0xFF53}, + {0xA3D4,0xA3F4,0xFF54}, + {0xA3D5,0xA3F5,0xFF55}, + {0xA3D6,0xA3F6,0xFF56}, + {0xA3D7,0xA3F7,0xFF57}, + {0xA3D8,0xA3F8,0xFF58}, + {0xA3D9,0xA3F9,0xFF59}, + {0xA3DA,0xA3FA,0xFF5A}, + {0xA3FB,0xA3FB,0xFF5B}, + {0xA3FC,0xA3FC,0xFF5C}, + {0xA3FD,0xA3FD,0xFF5D}, + {0xA3FE,0xA3FE,0xFFE3}, + {0xA3FF,0xA3FF,0xA3FF} +}; + + +static ObUnicaseInfoChar cA6[256]= +{ + {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,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,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},{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,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}, + {0xA640,0xA640,0x003F}, + {0xA641,0xA641,0x003F}, + {0xA642,0xA642,0x003F}, + {0xA643,0xA643,0x003F}, + {0xA644,0xA644,0x003F}, + {0xA645,0xA645,0x003F}, + {0xA646,0xA646,0x003F}, + {0xA647,0xA647,0x003F}, + {0xA648,0xA648,0x003F}, + {0xA649,0xA649,0x003F}, + {0xA64A,0xA64A,0x003F}, + {0xA64B,0xA64B,0x003F}, + {0xA64C,0xA64C,0x003F}, + {0xA64D,0xA64D,0x003F}, + {0xA64E,0xA64E,0x003F}, + {0xA64F,0xA64F,0x003F}, + {0xA650,0xA650,0x003F}, + {0xA651,0xA651,0x003F}, + {0xA652,0xA652,0x003F}, + {0xA653,0xA653,0x003F}, + {0xA654,0xA654,0x003F}, + {0xA655,0xA655,0x003F}, + {0xA656,0xA656,0x003F}, + {0xA657,0xA657,0x003F}, + {0xA658,0xA658,0x003F}, + {0xA659,0xA659,0x003F}, + {0xA65A,0xA65A,0x003F}, + {0xA65B,0xA65B,0x003F}, + {0xA65C,0xA65C,0x003F}, + {0xA65D,0xA65D,0x003F}, + {0xA65E,0xA65E,0x003F}, + {0xA65F,0xA65F,0x003F}, + {0xA660,0xA660,0x003F}, + {0xA661,0xA661,0x003F}, + {0xA662,0xA662,0x003F}, + {0xA663,0xA663,0x003F}, + {0xA664,0xA664,0x003F}, + {0xA665,0xA665,0x003F}, + {0xA666,0xA666,0x003F}, + {0xA667,0xA667,0x003F}, + {0xA668,0xA668,0x003F}, + {0xA669,0xA669,0x003F}, + {0xA66A,0xA66A,0x003F}, + {0xA66B,0xA66B,0x003F}, + {0xA66C,0xA66C,0x003F}, + {0xA66D,0xA66D,0x003F}, + {0xA66E,0xA66E,0x003F}, + {0xA66F,0xA66F,0x003F}, + {0xA670,0xA670,0x003F}, + {0xA671,0xA671,0x003F}, + {0xA672,0xA672,0x003F}, + {0xA673,0xA673,0x003F}, + {0xA674,0xA674,0x003F}, + {0xA675,0xA675,0x003F}, + {0xA676,0xA676,0x003F}, + {0xA677,0xA677,0x003F}, + {0xA678,0xA678,0x003F}, + {0xA679,0xA679,0x003F}, + {0xA67A,0xA67A,0x003F}, + {0xA67B,0xA67B,0x003F}, + {0xA67C,0xA67C,0x003F}, + {0xA67D,0xA67D,0x003F}, + {0xA67E,0xA67E,0x003F}, + {0xA67F,0xA67F,0xA67F}, + {0xA680,0xA680,0x003F}, + {0xA681,0xA681,0x003F}, + {0xA682,0xA682,0x003F}, + {0xA683,0xA683,0x003F}, + {0xA684,0xA684,0x003F}, + {0xA685,0xA685,0x003F}, + {0xA686,0xA686,0x003F}, + {0xA687,0xA687,0x003F}, + {0xA688,0xA688,0x003F}, + {0xA689,0xA689,0x003F}, + {0xA68A,0xA68A,0x003F}, + {0xA68B,0xA68B,0x003F}, + {0xA68C,0xA68C,0x003F}, + {0xA68D,0xA68D,0x003F}, + {0xA68E,0xA68E,0x003F}, + {0xA68F,0xA68F,0x003F}, + {0xA690,0xA690,0x003F}, + {0xA691,0xA691,0x003F}, + {0xA692,0xA692,0x003F}, + {0xA693,0xA693,0x003F}, + {0xA694,0xA694,0x003F}, + {0xA695,0xA695,0x003F}, + {0xA696,0xA696,0x003F}, + {0xA697,0xA697,0x003F}, + {0xA698,0xA698,0x003F}, + {0xA699,0xA699,0x003F}, + {0xA69A,0xA69A,0x003F}, + {0xA69B,0xA69B,0x003F}, + {0xA69C,0xA69C,0x003F}, + {0xA69D,0xA69D,0x003F}, + {0xA69E,0xA69E,0x003F}, + {0xA69F,0xA69F,0x003F}, + {0xA6A0,0xA6A0,0x003F}, + {0xA6A1,0xA6C1,0x0391}, + {0xA6A2,0xA6C2,0x0392}, + {0xA6A3,0xA6C3,0x0393}, + {0xA6A4,0xA6C4,0x0394}, + {0xA6A5,0xA6C5,0x0395}, + {0xA6A6,0xA6C6,0x0396}, + {0xA6A7,0xA6C7,0x0397}, + {0xA6A8,0xA6C8,0x0398}, + {0xA6A9,0xA6C9,0x0399}, + {0xA6AA,0xA6CA,0x039A}, + {0xA6AB,0xA6CB,0x039B}, + {0xA6AC,0xA6CC,0x039C}, + {0xA6AD,0xA6CD,0x039D}, + {0xA6AE,0xA6CE,0x039E}, + {0xA6AF,0xA6CF,0x039F}, + {0xA6B0,0xA6D0,0x03A0}, + {0xA6B1,0xA6D1,0x03A1}, + {0xA6B2,0xA6D2,0x03A3}, + {0xA6B3,0xA6D3,0x03A4}, + {0xA6B4,0xA6D4,0x03A5}, + {0xA6B5,0xA6D5,0x03A6}, + {0xA6B6,0xA6D6,0x03A7}, + {0xA6B7,0xA6D7,0x03A8}, + {0xA6B8,0xA6D8,0x03A9}, + {0xA6B9,0xA6B9,0x003F}, + {0xA6BA,0xA6BA,0x003F}, + {0xA6BB,0xA6BB,0x003F}, + {0xA6BC,0xA6BC,0x003F}, + {0xA6BD,0xA6BD,0x003F}, + {0xA6BE,0xA6BE,0x003F}, + {0xA6BF,0xA6BF,0x003F}, + {0xA6C0,0xA6C0,0x003F}, + {0xA6A1,0xA6C1,0x03B1}, + {0xA6A2,0xA6C2,0x03B2}, + {0xA6A3,0xA6C3,0x03B3}, + {0xA6A4,0xA6C4,0x03B4}, + {0xA6A5,0xA6C5,0x03B5}, + {0xA6A6,0xA6C6,0x03B6}, + {0xA6A7,0xA6C7,0x03B7}, + {0xA6A8,0xA6C8,0x03B8}, + {0xA6A9,0xA6C9,0x03B9}, + {0xA6AA,0xA6CA,0x03BA}, + {0xA6AB,0xA6CB,0x03BB}, + {0xA6AC,0xA6CC,0x03BC}, + {0xA6AD,0xA6CD,0x03BD}, + {0xA6AE,0xA6CE,0x03BE}, + {0xA6AF,0xA6CF,0x03BF}, + {0xA6B0,0xA6D0,0x03C0}, + {0xA6B1,0xA6D1,0x03C1}, + {0xA6B2,0xA6D2,0x03C3}, + {0xA6B3,0xA6D3,0x03C4}, + {0xA6B4,0xA6D4,0x03C5}, + {0xA6B5,0xA6D5,0x03C6}, + {0xA6B6,0xA6D6,0x03C7}, + {0xA6B7,0xA6D7,0x03C8}, + {0xA6B8,0xA6D8,0x03C9}, + {0xA6D9,0xA6D9,0x003F}, + {0xA6DA,0xA6DA,0x003F}, + {0xA6DB,0xA6DB,0x003F}, + {0xA6DC,0xA6DC,0x003F}, + {0xA6DD,0xA6DD,0x003F}, + {0xA6DE,0xA6DE,0x003F}, + {0xA6DF,0xA6DF,0x003F}, + {0xA6E0,0xA6E0,0xFE35}, + {0xA6E1,0xA6E1,0xFE36}, + {0xA6E2,0xA6E2,0xFE39}, + {0xA6E3,0xA6E3,0xFE3A}, + {0xA6E4,0xA6E4,0xFE3F}, + {0xA6E5,0xA6E5,0xFE40}, + {0xA6E6,0xA6E6,0xFE3D}, + {0xA6E7,0xA6E7,0xFE3E}, + {0xA6E8,0xA6E8,0xFE41}, + {0xA6E9,0xA6E9,0xFE42}, + {0xA6EA,0xA6EA,0xFE43}, + {0xA6EB,0xA6EB,0xFE44}, + {0xA6EC,0xA6EC,0x003F}, + {0xA6ED,0xA6ED,0x003F}, + {0xA6EE,0xA6EE,0xFE3B}, + {0xA6EF,0xA6EF,0xFE3C}, + {0xA6F0,0xA6F0,0xFE37}, + {0xA6F1,0xA6F1,0xFE38}, + {0xA6F2,0xA6F2,0xFE31}, + {0xA6F3,0xA6F3,0x003F}, + {0xA6F4,0xA6F4,0xFE33}, + {0xA6F5,0xA6F5,0xFE34}, + {0xA6F6,0xA6F6,0x003F}, + {0xA6F7,0xA6F7,0x003F}, + {0xA6F8,0xA6F8,0x003F}, + {0xA6F9,0xA6F9,0x003F}, + {0xA6FA,0xA6FA,0x003F}, + {0xA6FB,0xA6FB,0x003F}, + {0xA6FC,0xA6FC,0x003F}, + {0xA6FD,0xA6FD,0x003F}, + {0xA6FE,0xA6FE,0x003F}, + {0xA6FF,0xA6FF,0xA6FF} +}; + + +static ObUnicaseInfoChar cA7[256]= +{ + {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,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,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},{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,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}, + {0xA740,0xA740,0x003F}, + {0xA741,0xA741,0x003F}, + {0xA742,0xA742,0x003F}, + {0xA743,0xA743,0x003F}, + {0xA744,0xA744,0x003F}, + {0xA745,0xA745,0x003F}, + {0xA746,0xA746,0x003F}, + {0xA747,0xA747,0x003F}, + {0xA748,0xA748,0x003F}, + {0xA749,0xA749,0x003F}, + {0xA74A,0xA74A,0x003F}, + {0xA74B,0xA74B,0x003F}, + {0xA74C,0xA74C,0x003F}, + {0xA74D,0xA74D,0x003F}, + {0xA74E,0xA74E,0x003F}, + {0xA74F,0xA74F,0x003F}, + {0xA750,0xA750,0x003F}, + {0xA751,0xA751,0x003F}, + {0xA752,0xA752,0x003F}, + {0xA753,0xA753,0x003F}, + {0xA754,0xA754,0x003F}, + {0xA755,0xA755,0x003F}, + {0xA756,0xA756,0x003F}, + {0xA757,0xA757,0x003F}, + {0xA758,0xA758,0x003F}, + {0xA759,0xA759,0x003F}, + {0xA75A,0xA75A,0x003F}, + {0xA75B,0xA75B,0x003F}, + {0xA75C,0xA75C,0x003F}, + {0xA75D,0xA75D,0x003F}, + {0xA75E,0xA75E,0x003F}, + {0xA75F,0xA75F,0x003F}, + {0xA760,0xA760,0x003F}, + {0xA761,0xA761,0x003F}, + {0xA762,0xA762,0x003F}, + {0xA763,0xA763,0x003F}, + {0xA764,0xA764,0x003F}, + {0xA765,0xA765,0x003F}, + {0xA766,0xA766,0x003F}, + {0xA767,0xA767,0x003F}, + {0xA768,0xA768,0x003F}, + {0xA769,0xA769,0x003F}, + {0xA76A,0xA76A,0x003F}, + {0xA76B,0xA76B,0x003F}, + {0xA76C,0xA76C,0x003F}, + {0xA76D,0xA76D,0x003F}, + {0xA76E,0xA76E,0x003F}, + {0xA76F,0xA76F,0x003F}, + {0xA770,0xA770,0x003F}, + {0xA771,0xA771,0x003F}, + {0xA772,0xA772,0x003F}, + {0xA773,0xA773,0x003F}, + {0xA774,0xA774,0x003F}, + {0xA775,0xA775,0x003F}, + {0xA776,0xA776,0x003F}, + {0xA777,0xA777,0x003F}, + {0xA778,0xA778,0x003F}, + {0xA779,0xA779,0x003F}, + {0xA77A,0xA77A,0x003F}, + {0xA77B,0xA77B,0x003F}, + {0xA77C,0xA77C,0x003F}, + {0xA77D,0xA77D,0x003F}, + {0xA77E,0xA77E,0x003F}, + {0xA77F,0xA77F,0xA77F}, + {0xA780,0xA780,0x003F}, + {0xA781,0xA781,0x003F}, + {0xA782,0xA782,0x003F}, + {0xA783,0xA783,0x003F}, + {0xA784,0xA784,0x003F}, + {0xA785,0xA785,0x003F}, + {0xA786,0xA786,0x003F}, + {0xA787,0xA787,0x003F}, + {0xA788,0xA788,0x003F}, + {0xA789,0xA789,0x003F}, + {0xA78A,0xA78A,0x003F}, + {0xA78B,0xA78B,0x003F}, + {0xA78C,0xA78C,0x003F}, + {0xA78D,0xA78D,0x003F}, + {0xA78E,0xA78E,0x003F}, + {0xA78F,0xA78F,0x003F}, + {0xA790,0xA790,0x003F}, + {0xA791,0xA791,0x003F}, + {0xA792,0xA792,0x003F}, + {0xA793,0xA793,0x003F}, + {0xA794,0xA794,0x003F}, + {0xA795,0xA795,0x003F}, + {0xA796,0xA796,0x003F}, + {0xA797,0xA797,0x003F}, + {0xA798,0xA798,0x003F}, + {0xA799,0xA799,0x003F}, + {0xA79A,0xA79A,0x003F}, + {0xA79B,0xA79B,0x003F}, + {0xA79C,0xA79C,0x003F}, + {0xA79D,0xA79D,0x003F}, + {0xA79E,0xA79E,0x003F}, + {0xA79F,0xA79F,0x003F}, + {0xA7A0,0xA7A0,0x003F}, + {0xA7A1,0xA7D1,0x0410}, + {0xA7A2,0xA7D2,0x0411}, + {0xA7A3,0xA7D3,0x0412}, + {0xA7A4,0xA7D4,0x0413}, + {0xA7A5,0xA7D5,0x0414}, + {0xA7A6,0xA7D6,0x0415}, + {0xA7A7,0xA7D7,0x0401}, + {0xA7A8,0xA7D8,0x0416}, + {0xA7A9,0xA7D9,0x0417}, + {0xA7AA,0xA7DA,0x0418}, + {0xA7AB,0xA7DB,0x0419}, + {0xA7AC,0xA7DC,0x041A}, + {0xA7AD,0xA7DD,0x041B}, + {0xA7AE,0xA7DE,0x041C}, + {0xA7AF,0xA7DF,0x041D}, + {0xA7B0,0xA7E0,0x041E}, + {0xA7B1,0xA7E1,0x041F}, + {0xA7B2,0xA7E2,0x0420}, + {0xA7B3,0xA7E3,0x0421}, + {0xA7B4,0xA7E4,0x0422}, + {0xA7B5,0xA7E5,0x0423}, + {0xA7B6,0xA7E6,0x0424}, + {0xA7B7,0xA7E7,0x0425}, + {0xA7B8,0xA7E8,0x0426}, + {0xA7B9,0xA7E9,0x0427}, + {0xA7BA,0xA7EA,0x0428}, + {0xA7BB,0xA7EB,0x0429}, + {0xA7BC,0xA7EC,0x042A}, + {0xA7BD,0xA7ED,0x042B}, + {0xA7BE,0xA7EE,0x042C}, + {0xA7BF,0xA7EF,0x042D}, + {0xA7C0,0xA7F0,0x042E}, + {0xA7C1,0xA7F1,0x042F}, + {0xA7C2,0xA7C2,0x003F}, + {0xA7C3,0xA7C3,0x003F}, + {0xA7C4,0xA7C4,0x003F}, + {0xA7C5,0xA7C5,0x003F}, + {0xA7C6,0xA7C6,0x003F}, + {0xA7C7,0xA7C7,0x003F}, + {0xA7C8,0xA7C8,0x003F}, + {0xA7C9,0xA7C9,0x003F}, + {0xA7CA,0xA7CA,0x003F}, + {0xA7CB,0xA7CB,0x003F}, + {0xA7CC,0xA7CC,0x003F}, + {0xA7CD,0xA7CD,0x003F}, + {0xA7CE,0xA7CE,0x003F}, + {0xA7CF,0xA7CF,0x003F}, + {0xA7D0,0xA7D0,0x003F}, + {0xA7A1,0xA7D1,0x0430}, + {0xA7A2,0xA7D2,0x0431}, + {0xA7A3,0xA7D3,0x0432}, + {0xA7A4,0xA7D4,0x0433}, + {0xA7A5,0xA7D5,0x0434}, + {0xA7A6,0xA7D6,0x0435}, + {0xA7A7,0xA7D7,0x0451}, + {0xA7A8,0xA7D8,0x0436}, + {0xA7A9,0xA7D9,0x0437}, + {0xA7AA,0xA7DA,0x0438}, + {0xA7AB,0xA7DB,0x0439}, + {0xA7AC,0xA7DC,0x043A}, + {0xA7AD,0xA7DD,0x043B}, + {0xA7AE,0xA7DE,0x043C}, + {0xA7AF,0xA7DF,0x043D}, + {0xA7B0,0xA7E0,0x043E}, + {0xA7B1,0xA7E1,0x043F}, + {0xA7B2,0xA7E2,0x0440}, + {0xA7B3,0xA7E3,0x0441}, + {0xA7B4,0xA7E4,0x0442}, + {0xA7B5,0xA7E5,0x0443}, + {0xA7B6,0xA7E6,0x0444}, + {0xA7B7,0xA7E7,0x0445}, + {0xA7B8,0xA7E8,0x0446}, + {0xA7B9,0xA7E9,0x0447}, + {0xA7BA,0xA7EA,0x0448}, + {0xA7BB,0xA7EB,0x0449}, + {0xA7BC,0xA7EC,0x044A}, + {0xA7BD,0xA7ED,0x044B}, + {0xA7BE,0xA7EE,0x044C}, + {0xA7BF,0xA7EF,0x044D}, + {0xA7C0,0xA7F0,0x044E}, + {0xA7C1,0xA7F1,0x044F}, + {0xA7F2,0xA7F2,0x003F}, + {0xA7F3,0xA7F3,0x003F}, + {0xA7F4,0xA7F4,0x003F}, + {0xA7F5,0xA7F5,0x003F}, + {0xA7F6,0xA7F6,0x003F}, + {0xA7F7,0xA7F7,0x003F}, + {0xA7F8,0xA7F8,0x003F}, + {0xA7F9,0xA7F9,0x003F}, + {0xA7FA,0xA7FA,0x003F}, + {0xA7FB,0xA7FB,0x003F}, + {0xA7FC,0xA7FC,0x003F}, + {0xA7FD,0xA7FD,0x003F}, + {0xA7FE,0xA7FE,0x003F}, + {0xA7FF,0xA7FF,0xA7FF} +}; + + +static const ObUnicaseInfoChar *ob_caseinfo_pages_gbk[256]= +{ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, cA2, cA3, NULL, NULL, cA6, cA7, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + + +static ObUnicaseInfo ob_caseinfo_gbk= +{ + 0xFFFF, + ob_caseinfo_pages_gbk +}; + + +static unsigned char sort_order_gbk[]= +{ + '\000','\001','\002','\003','\004','\005','\006','\007', + '\010','\011','\012','\013','\014','\015','\016','\017', + '\020','\021','\022','\023','\024','\025','\026','\027', + '\030','\031','\032','\033','\034','\035','\036','\037', + ' ', '!', '"', '#', '$', '%', '&', '\'', + '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', ':', ';', '<', '=', '>', '?', + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '\\', ']', '[', '^', '_', + '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '{', '|', '}', 'Y', '\177', + (unsigned char) '\200',(unsigned char) '\201',(unsigned char) '\202',(unsigned char) '\203',(unsigned char) '\204',(unsigned char) '\205',(unsigned char) '\206',(unsigned char) '\207', + (unsigned char) '\210',(unsigned char) '\211',(unsigned char) '\212',(unsigned char) '\213',(unsigned char) '\214',(unsigned char) '\215',(unsigned char) '\216',(unsigned char) '\217', + (unsigned char) '\220',(unsigned char) '\221',(unsigned char) '\222',(unsigned char) '\223',(unsigned char) '\224',(unsigned char) '\225',(unsigned char) '\226',(unsigned char) '\227', + (unsigned char) '\230',(unsigned char) '\231',(unsigned char) '\232',(unsigned char) '\233',(unsigned char) '\234',(unsigned char) '\235',(unsigned char) '\236',(unsigned char) '\237', + (unsigned char) '\240',(unsigned char) '\241',(unsigned char) '\242',(unsigned char) '\243',(unsigned char) '\244',(unsigned char) '\245',(unsigned char) '\246',(unsigned char) '\247', + (unsigned char) '\250',(unsigned char) '\251',(unsigned char) '\252',(unsigned char) '\253',(unsigned char) '\254',(unsigned char) '\255',(unsigned char) '\256',(unsigned char) '\257', + (unsigned char) '\260',(unsigned char) '\261',(unsigned char) '\262',(unsigned char) '\263',(unsigned char) '\264',(unsigned char) '\265',(unsigned char) '\266',(unsigned char) '\267', + (unsigned char) '\270',(unsigned char) '\271',(unsigned char) '\272',(unsigned char) '\273',(unsigned char) '\274',(unsigned char) '\275',(unsigned char) '\276',(unsigned char) '\277', + (unsigned char) '\300',(unsigned char) '\301',(unsigned char) '\302',(unsigned char) '\303',(unsigned char) '\304',(unsigned char) '\305',(unsigned char) '\306',(unsigned char) '\307', + (unsigned char) '\310',(unsigned char) '\311',(unsigned char) '\312',(unsigned char) '\313',(unsigned char) '\314',(unsigned char) '\315',(unsigned char) '\316',(unsigned char) '\317', + (unsigned char) '\320',(unsigned char) '\321',(unsigned char) '\322',(unsigned char) '\323',(unsigned char) '\324',(unsigned char) '\325',(unsigned char) '\326',(unsigned char) '\327', + (unsigned char) '\330',(unsigned char) '\331',(unsigned char) '\332',(unsigned char) '\333',(unsigned char) '\334',(unsigned char) '\335',(unsigned char) '\336',(unsigned char) '\337', + (unsigned char) '\340',(unsigned char) '\341',(unsigned char) '\342',(unsigned char) '\343',(unsigned char) '\344',(unsigned char) '\345',(unsigned char) '\346',(unsigned char) '\347', + (unsigned char) '\350',(unsigned char) '\351',(unsigned char) '\352',(unsigned char) '\353',(unsigned char) '\354',(unsigned char) '\355',(unsigned char) '\356',(unsigned char) '\357', + (unsigned char) '\360',(unsigned char) '\361',(unsigned char) '\362',(unsigned char) '\363',(unsigned char) '\364',(unsigned char) '\365',(unsigned char) '\366',(unsigned char) '\367', + (unsigned char) '\370',(unsigned char) '\371',(unsigned char) '\372',(unsigned char) '\373',(unsigned char) '\374',(unsigned char) '\375',(unsigned char) '\376',(unsigned char) '\377', +}; + +static uint16_t gbk_order[]= +{ +8653,14277,17116,11482,11160,2751,14613,3913,13337,9827, +19496,1759,8105,7103,7836,5638,2223,21433,5878,8006, +4851,18766,18879,16728,8129,6200,19133,6389,2500,19084, +16228,5074,8130,5900,6201,3985,14597,11566,8588,8769, +15885,11411,11965,1961,18012,18303,12242,14118,11490,12911, +15015,4367,3184,2093,20937,5710,5108,10560,9993,18982, +8393,10697,14620,19558,14970,15193,5359,18189,12666,18192, +3310,18659,17358,7973,18673,19537,3404,9723,4221,16486, +7023,13648,16310,1049,1726,4799,15534,4366,17133,4192, +6219,5118,1804,2360,2279,14279,13740,4511,2361,12906, +16650,18590,4723,2001,16313,3594,21026,12146,19561,3800, +4161,16774,18892,17657,7025,892,7917,12245,3394,4813, +11902,3189,20002,2365,12964,18115,17660,20227,17182,11907, +11671,17562,17864,21131,13423,1361,12246,18897,14978,18848, +20727,5902,10726,21241,1906,13424,1408,20519,3038,18495, +20446,1431,17138,13464,14558,1221,6720,6137,17348,5268, +4448,11313,1760,6172,6870,5744,13541,3044,17701,14368, +16114,5051,9142,18776,5669,19089,11088,17867,925,10395, +4372,10578,2138,2554,18118,21087,13862,7461,14983,3322, +15305,11844,7924,8087,2542,20701,21772,2754,10490,8218, +14800,15869,14436,16119,1814,11543,17398,16069,19659,17020, +17844,5694,8833,16744,18925,4957,9812,6852,8036,12966, +14038,12145,16833,11165,17076,17756,3673,2367,20916,9143, +14927,6885,17486,7469,1661,2827,4627,18198,1307,19711, +17637,2595,2262,20807,1764,8150,18547,3192,9711,16262, +9144,2006,21629,5311,15743,14733,10991,15402,2916,17724, +12195,12622,5141,8039,15169,7780,4568,20835,21575,10580, +15022,9470,6853,3926,21563,1342,16745,8181,11526,1947, +7402,18641,14145,13149,19222,2468,12920,13916,21077,2968, +16438,19667,1768,15632,18374,4738,15517,16655,4309,2374, +14492,8602,3679,2103,1312,18681,6613,18604,20451,2755, +18218,19473,17854,20316,3003,4998,1391,20938,11169,7049, +18861,17577,18091,1937,4085,2059,20633,15948,1313,20138, +7785,16439,15081,20955,15117,17065,19924,13831,11913,20062, +7568,10703,3717,15480,6047,7790,16867,14223,12971,8429, +2008,2833,14026,1317,17493,19411,18551,15452,15257,18504, +4441,1769,7249,20128,5509,1970,9420,19365,20190,21617, +12202,15041,2871,19676,20388,21674,14258,2901,8058,5970, +20472,13257,18226,3694,17591,10279,1318,12409,7901,9794, +10416,10769,12876,17154,15455,19298,3970,21327,14228,13095, +8096,16072,21748,12581,9326,2311,5683,12641,3583,2184, +16464,6969,1795,6778,2880,15819,3433,7674,4713,17297, +8231,4333,9995,1841,5558,17155,17298,11283,18694,7946, +7311,13129,4753,21149,905,14010,18821,8532,11873,2190, +19006,3456,8874,7433,2841,7680,14143,20130,1993,1699, +976,15361,2736,2154,9202,11685,7951,12982,11008,16763, +11829,13327,11686,2299,9940,10507,8917,1277,19790,1636, +20143,21002,15011,19443,6026,13299,2455,9667,15612,16477, +10261,2811,2202,13674,14760,6818,9691,10624,20145,11940, +15524,18349,9437,11578,20132,17736,4121,4122,16023,2280, +4371,4373,7873,18307,14602,14695,13054,5410,6065,14389, +3979,1137,5411,6672,16311,11632,9829,19575,5901,15708, +12553,7165,18983,10860,13664,18242,10848,2049,8075,5579, +8083,10863,21136,5445,17851,19132,8597,18771,11054,14631, +10997,8292,8803,11246,4999,17559,11134,15369,5155,6407, +12054,4857,11265,12834,7322,15057,10937,15984,5544,8040, +13291,3961,5142,19101,869,9631,2009,11315,21404,3172, +14941,4204,7947,9997,16906,4035,4476,4477,8171,2818, +20725,4724,11453,20868,4725,4729,8565,5109,12490,8862, +5920,13737,2888,6930,12963,3223,6934,3395,16243,8397, +9475,4858,13515,3777,11266,10029,21028,1671,7765,7766, +14169,2221,5328,2907,8951,4225,4416,7770,3046,8014, +3975,10636,20236,19825,3248,8717,2140,2908,3249,9477, +4628,2225,12676,2909,21564,5167,1225,4186,13266,4017, +7471,7146,18214,6890,4195,16037,16688,5583,14497,7476, +3286,8566,2910,2862,2232,16038,10417,9492,12234,14190, +8793,5573,6486,20322,21455,9734,8317,10143,5781,7681, +5782,7500,7501,15466,7188,7511,7512,21003,2203,21693, +11350,9540,21212,18183,7918,8754,17511,20869,18899,21160, +11356,9315,8364,8798,18460,16189,17483,11415,8897,7771, +9917,8718,7926,5228,11270,2644,9269,19404,8719,8367, +13267,10400,1914,2157,8584,11171,3964,17881,16785,18951, +18052,16616,14500,9323,10418,12410,14661,6963,7570,7668, +13601,17386,18995,8437,4460,8346,15920,8318,3387,10734, +18057,18058,10525,9654,2390,13675,13603,20000,8106,1260, +10824,1426,5075,5076,18887,12175,8174,15558,5269,4304, +5380,3287,8156,5386,11605,8142,18768,7580,8641,6319, +13425,4478,13147,2019,8900,6331,19668,5756,6769,3381, +9009,9730,9735,15160,4036,8167,13489,17009,8667,18308, +13439,18112,11735,21667,14617,17010,16290,16291,17515,3368, +7050,14841,5636,16826,17573,7760,18493,13306,14312,2619, +17868,13609,8991,7038,4310,16881,14020,16422,20565,5941, +18174,3642,20346,12080,856,13144,18158,20908,10800,15630, +14340,15837,21707,4629,2060,19870,9632,3718,7902,994, +5762,18391,9647,2312,9199,9648,18281,18342,19911,5367, +9950,13834,13513,8771,9414,4057,21302,1963,1964,1967, +902,3349,14697,5602,1071,13959,14621,21428,7288,15079, +7039,16495,13949,3111,5580,13365,2615,4109,6202,11213, +10792,17918,21538,3226,18658,11985,6862,18734,2752,13232, +7838,1907,4252,6223,16703,11495,18037,3974,6301,5226, +8514,10487,5267,10892,12763,16706,7702,20003,2616,14457, +16083,16587,4296,14513,8355,12171,16590,10670,13651,3646, +14626,21132,15826,17015,18911,12792,12461,21545,17848,18912, +17396,3277,13516,5918,16115,12548,1673,4864,18438,6078, +5880,3263,16211,21784,1909,15296,17183,6884,12796,4417, +4299,17021,21137,14801,17484,8852,6512,15560,4300,17921, +5819,9342,15900,17742,19525,3869,11715,17703,12554,6040, +19865,10267,12549,10804,21670,6091,17277,9319,12531,9840, +1060,11215,10514,15170,4892,5904,14898,19534,5469,5470, +1128,5922,18937,7270,15971,17189,16263,9474,13382,2369, +20210,18177,3976,12767,3618,13236,10885,5397,15621,8770, +9830,9310,14121,21573,16634,19148,12803,4381,13051,956, +20237,3755,19551,15744,9169,16852,866,11893,21439,3680, +6197,17412,17324,16086,16747,16602,3834,5510,12770,12771, +3420,16198,21552,1421,3198,6097,18178,12772,20576,9831, +17200,19226,5584,20226,5822,10609,11641,3599,13550,15387, +5361,15481,952,3426,19731,20581,21103,2153,16223,19719, +20139,18533,11172,6356,20044,6584,6585,6954,21058,16397, +14150,17888,6618,4199,11775,9843,19732,14051,2564,13093, +18379,3377,12174,1968,19359,16350,19294,12243,1294,5362, +20214,6898,15645,18557,6146,13005,14084,19366,6272,17534, +10713,2104,5894,13900,16200,6964,12093,16692,12975,21496, +9358,16216,7314,15280,3056,14008,5363,11510,13001,1474, +997,9724,21709,20612,11383,15441,7715,2684,7622,8585, +15456,14192,872,17497,10281,17428,6338,6779,5831,11989, +17156,20245,2293,12512,3560,10705,6367,5040,15465,18663, +14003,7716,17498,6462,10721,13660,9327,17501,6973,9010, +17433,6024,10669,13098,2842,15393,3436,18133,4283,21749, +4461,2571,6707,1986,2900,3138,3434,19771,9090,16900, +12816,6022,9736,17830,6708,19167,18099,11781,14950,18337, +19249,3270,20404,21152,11875,6791,17596,7723,19933,884, +19376,8877,19687,12164,3544,17647,4150,3457,17648,12338, +19127,21715,11831,3635,9259,15329,6901,17127,18710,4191, +12352,21112,7195,7956,2300,18061,10887,15701,10319,6808, +1859,19445,11794,19170,6436,10969,6216,20594,9522,10157, +5898,11567,11326,18410,9674,10340,10229,11345,3447,2456, +12439,12340,17368,10889,17057,4224,8845,18285,2207,19263, +3872,9117,15331,17456,2995,6523,6919,21337,11803,17457, +1936,9533,2248,2161,9697,19072,10607,20163,15100,6199, +20287,7392,20107,21238,9225,11809,13650,10203,6717,19085, +11816,16035,8643,19823,8084,12359,20004,3059,6719,4253, +5838,15886,15982,5839,13638,13780,5840,15341,5842,19140, +6854,5923,10582,5843,2868,16398,19872,13534,8824,12598, +19879,19880,18208,16051,16004,16005,16039,10567,6783,19020, +10539,10550,18184,16018,15868,12573,10392,8863,8172,19697, +12845,12846,21424,3476,12833,17119,14167,11764,11357,7264, +20873,18048,18901,13220,4667,8756,16106,4705,1432,8009, +3665,7966,7128,2587,7967,12053,15477,13430,20832,5587, +15350,8076,18496,4801,10396,13339,5438,18013,1074,10032, +21247,4985,6322,20909,989,3323,12104,11235,7138,6138, +10512,3008,2621,19090,6306,4110,20541,4877,5674,18543, +4231,5748,2116,18465,17517,14702,1762,6233,3281,8548, +3479,6000,954,17677,17278,1186,4803,1097,18938,19207, +5954,17874,2917,13191,1374,4557,13610,19406,8518,7240, +3675,9306,8357,7882,20573,9913,6446,1915,8078,18661, +3600,18200,13551,15199,13252,16268,8298,10602,20739,8775, +2704,3928,15450,1948,2829,1375,8603,4214,18952,20841, +21403,12685,8299,11653,8726,9031,11701,7331,5169,19721, +4311,5546,9471,4548,18163,9032,972,14386,11607,15974, +2517,6540,1462,9789,5823,21324,1244,19595,10838,7744, +13909,18685,5360,21578,19596,6619,4318,18552,1268,3013, +10906,2309,16148,12551,4773,21079,7858,7887,6198,5174, +2935,8605,12479,9418,17729,6610,4093,16233,17928,17030, +7062,8871,19299,19417,8569,15122,14579,11123,16618,2526, +15997,13618,21060,9639,12203,1209,20185,4112,15728,16751, +20767,18053,20711,898,5381,18272,8607,16540,17592,10190, +5887,9300,2294,12204,1384,2426,10427,10374,11972,12978, +10920,11384,16040,14865,10301,1622,2072,20975,20512,8617, +3765,2439,20849,7172,5829,13045,7943,3700,3174,18392, +15307,20290,12928,16506,21383,13068,14230,14231,1088,12583, +8875,3942,4462,13626,4146,3217,3701,14505,4242,4245, +15413,3587,11432,4684,6631,15414,3271,18690,21282,7502, +1039,13032,13072,8748,19021,12316,3766,7551,18665,1852, +15419,9243,8322,6513,3492,13684,12987,18062,9260,16999, +906,18151,3529,13911,7957,9427,8940,10341,18286,15427, +16481,6514,10263,10264,13950,9675,9985,2208,18070,18291, +9406,1106,16240,14024,21355,18735,10727,21254,21358,6353, +9064,6357,17889,9070,14715,10820,4147,14718,18755,5496, +7582,4769,20373,1592,15166,13637,10033,3251,17753,17613, +11596,17130,19916,10850,4182,13264,11964,5447,12805,11003, +11047,2440,20269,5601,5209,15535,15370,18300,1406,6926, +20037,7229,1056,4359,3596,12118,8363,17518,3735,18497, +6573,8553,20360,1351,6662,4610,3780,18127,1363,1032, +16617,12536,16800,1037,7571,9731,4203,19993,7572,14677, +4715,6902,1527,10540,2376,3886,12847,8131,11926,2135, +17136,4517,7104,6221,3365,4816,8031,5875,16599,21029, +11997,5995,21069,20005,4807,2552,8400,21341,18361,11496, +17629,4669,4726,16292,4072,1075,21429,20521,11523,19918, +15958,17185,18913,4247,11358,1436,14370,4248,6080,17849, +4434,20728,11236,1173,4817,10034,21539,13666,14173,18439, +10741,21482,8275,13754,3952,7040,5056,17377,6456,8339, +5443,7327,7328,11738,20834,20673,17273,6182,5675,8491, +8847,18364,11314,9918,12150,4302,19527,18255,14375,14566, +5749,13543,15020,6234,17279,14316,2502,17574,10805,4827, +11443,8723,2979,2980,15870,17708,11546,19581,12503,11626, +20926,5924,21344,12472,16076,17280,16710,18256,16748,16841, +18260,19582,14989,9609,8190,21375,12628,17194,21440,3929, +10404,879,4249,10275,11146,3095,12550,8191,1949,10054, +17413,14766,12773,6692,5001,16647,16648,15405,4581,4582, +15709,11654,13552,8046,7979,12868,3756,17726,6421,16231, +9150,19109,21097,11614,5002,10583,973,9033,19149,18201, +8192,9622,3737,17195,6447,6480,3483,18605,11564,13964, +7294,15949,19734,16351,3689,13838,10941,3378,13918,13178, +6693,16657,12924,2936,11189,5005,7831,4086,18806,21080, +6620,11148,932,19228,17929,7745,16352,20747,13345,15635, +17584,16171,9790,10871,13670,14932,12361,16502,16199,3132, +6358,7791,1245,17817,15950,5715,21662,18558,19882,13796, +13901,10132,10944,12039,1026,10672,9002,13206,20689,19883, +7746,13800,11302,19235,15124,11752,15542,12085,9276,11609, +1235,12346,18996,19759,17966,10773,18749,8627,19370,11703, +5719,7905,21307,20246,5908,9361,20563,6426,6427,1034, +13922,10677,12423,5487,16758,13099,16174,20438,11193,17210, +17211,11392,9864,9712,6490,5723,3572,20852,17832,18753, +6482,16901,9011,13705,18396,2181,7625,10946,4534,4463, +17161,19022,6168,7724,4536,14680,15209,13033,9774,17945, +17649,11755,3943,19023,1971,907,11742,11832,10673,15800, +2738,7958,3028,19632,12437,13822,13876,11528,18236,15363, +19255,12988,19972,11154,1403,14431,17732,11711,4037,10186, +19849,9247,18411,10100,7696,11743,9249,17172,19264,14855, +6822,13579,11104,9538,10541,18292,21213,9251,8394,21477, +17662,14984,15342,19522,21318,15232,11216,3096,12869,18145, +11682,21506,9501,18022,1877,11517,11798,19265,10542,13830, +13303,7230,13858,18591,18772,8010,21395,21223,6229,14563, +18794,15793,14603,2503,13642,5375,17403,20364,3516,14419, +6659,11115,8804,1950,20141,19831,13343,6142,20637,7482, +11825,1770,6541,13226,14576,11826,7938,11847,20963,19677, +1247,8885,11827,8312,13229,6339,14584,11828,14425,16469, +17560,8886,6784,8533,19039,18830,1257,13187,2705,1258, +4762,10511,4124,12519,21303,4828,8724,7588,21305,18092, +14812,4131,3527,7762,4393,4394,14764,14280,11327,9907, +17242,17243,9046,16304,9904,10796,16305,16306,16307,18541, +4232,8998,21059,5110,5515,16061,5115,5116,17012,1390, +7844,15716,3798,14519,20669,17576,11649,16842,16843,10758, +10309,12474,15684,4631,17585,10500,2084,17597,8329,8391, +9883,8392,21237,17624,11692,16188,17134,9579,4288,3503, +6742,10206,13743,16775,5949,14364,2765,18725,19947,1157, +18592,981,16777,7768,4290,4670,16248,12907,12663,7839, +21769,21770,18498,8276,5161,18015,12501,9591,15773,13432, +4865,16137,12288,1030,8924,13433,12525,15774,10036,2589, +12463,2091,1185,15898,18016,1588,6083,8721,10649,4303, +4990,3826,10399,4363,4375,5057,13530,18786,11438,14567, +926,16386,6533,11113,9552,7139,3954,16387,19529,5502, +9919,18545,7610,4258,17519,1884,13639,4736,11585,9555, +19464,17281,13793,3517,14382,2504,15985,5349,5231,17082, +19141,19665,9307,8616,17234,13611,2695,15316,9955,6478, +8193,9151,11248,9034,9035,21671,5547,18164,5179,10584, +10585,10055,4187,20740,19151,3965,5926,20741,16440,12301, +7787,21672,8823,3930,19152,21490,20275,6621,19597,18474, +4742,13395,18475,15636,18862,20956,14654,4319,21271,8594, +10518,18318,10942,5932,6955,6586,15855,16795,19598,21579, +9193,8712,18267,18268,16447,21580,2121,15200,8679,13179, +12699,15998,4113,16882,16619,2010,15485,13801,7795,870, +10133,16801,13060,1368,3719,12950,19418,11778,3238,14580, +13968,15043,21588,7596,9858,8628,2233,3853,2076,3890, +15978,10302,20433,20434,998,2031,13447,13009,3175,21713, +3524,3525,16958,19760,12160,10221,17387,2085,1796,13182, +7626,18232,9328,20458,9866,9867,7890,4243,21738,7721, +8441,18574,7627,18575,8442,20405,19024,18023,11593,18705, +18706,18824,11788,17251,7074,17601,8707,5724,3710,1040, +21730,16369,13823,3530,10114,7818,19688,19975,19196,13859, +7823,9660,5732,10230,10231,19319,16937,8244,2209,19345, +8961,18287,11599,13580,2359,3159,10543,3729,3730,11805, +18293,18294,18354,8989,18295,8861,6605,7968,2341,9938, +8768,12561,12562,13406,20792,20522,18795,7897,15252,13598, +12240,4852,20087,3876,11763,4648,12010,20874,6409,3412, +3325,11359,4866,11367,18927,18928,12467,12835,8356,13863, +14839,14878,13123,20625,14523,13643,3336,5707,12475,20508, +7408,16232,3339,14148,12687,4061,6287,20780,17818,16400, +18969,1192,12480,3839,5382,12040,15543,11124,7309,15602, +6704,21044,14193,1623,5847,20247,11469,1193,8019,2236, +20985,6342,1492,1504,20496,11136,13073,2171,4685,11015, +1195,2739,11224,2793,7816,17258,9214,7318,1761,5147, +7112,15831,20270,5689,10886,13188,4163,18175,1124,7840, +21342,18140,3047,15899,18853,20918,15766,20919,17405,15986, +5754,8835,10998,19501,1885,1763,2547,9152,7051,15026, +14808,13284,19736,11210,15061,2064,17327,4633,8155,4327, +16448,10191,17124,15062,20964,1923,13258,8159,8160,10282, +19210,3348,10428,18997,2788,16006,14951,17645,11211,2313, +16759,4637,5691,8789,8878,1513,13034,9999,9884,10342, +7208,19346,17173,15845,19387,9539,15847,18074,3612,12524, +6721,11524,6722,4706,8251,18309,20183,18728,4413,14016, +4414,14663,3799,6402,16674,3664,7583,1095,14412,20469, +15536,4954,3649,2329,20674,18787,8365,14285,19827,8041, +3781,20470,7589,13024,12198,1463,14347,15407,7422,5256, +4428,1475,8794,7429,1682,17439,3437,5832,7552,6264, +11065,5836,16239,8476,7122,10397,6770,6771,18825,18826, +18836,19941,19942,16558,18365,19706,2556,3782,19419,12386, +2582,21425,16167,7028,21030,16314,3597,10037,4867,16320, +16834,16192,2543,20927,8042,3094,20798,3097,16984,7154, +20939,3065,21098,9153,17578,7857,7477,14656,7295,1595, +5007,16449,1210,16883,20750,12413,15649,3561,20754,1676, +2686,2387,18576,6792,10927,10271,17338,1280,13490,9371, +13717,3895,5069,13719,5093,18895,14619,16819,4457,19220, +11238,16588,16780,7029,17016,7841,16249,3061,19702,12664, +3190,15371,16092,12908,6842,17740,16318,17139,8623,8277, +18915,1238,11239,12128,8801,1174,11583,15810,5542,8283, +19457,3670,15969,19460,4821,17017,1437,19436,17979,3064, +1738,6656,18038,12251,14802,16835,15386,19400,11360,8772, +14633,17022,9344,6183,8902,11416,20884,17520,15767,3827, +6041,5750,12620,17485,14929,6328,13340,6723,2645,18788, +17743,5604,10010,2624,14282,13531,19953,12179,3554,6754, +17406,10801,19407,19828,12258,19955,19722,15988,7855,20577, +10011,6042,13150,15685,1916,12969,16845,10742,18954,6179, +2544,16786,9484,9295,3066,18955,9610,11603,4312,16788, +3098,3557,2322,10985,9623,5646,5641,12629,8777,15745, +10586,16868,8604,5796,11702,4142,5857,20398,19836,7885, +7161,9956,19723,6106,13553,15406,15689,11772,2981,6832, +17639,4282,15278,21613,7332,19412,3558,11608,20063,3840, +2970,13315,2065,1573,6835,21581,15637,1324,17930,16353, +5277,16450,1465,17931,6587,11173,19413,12806,14256,19110, +2421,10875,12840,8731,900,13156,18319,13919,21614,13998, +19229,13624,5383,20021,15132,12707,18560,15042,6665,7064, +5516,8313,2911,11704,17535,8570,20769,19420,2042,18131, +14446,1834,8586,17035,6859,19422,18507,9640,14053,15544, +19118,17896,15382,20067,11316,5407,3101,12414,11470,5848, +2665,1985,1980,1978,3176,11284,20476,15945,1035,14866, +5648,13627,20215,8161,9726,11995,15044,7944,19212,10523, +14260,16041,10744,12882,14352,13297,3707,20853,10283,8383, +12648,12643,19772,12491,9860,3115,19442,2687,20986,15946, +2474,12817,13449,12214,1335,13328,7628,2661,9737,12494, +9012,6786,2533,19214,19215,16992,16993,3438,15415,4244, +4177,15139,8454,2074,17434,4465,4714,9329,9362,17212, +11285,9868,16760,1987,8443,3139,17304,15442,14485,12280, +19025,17162,11876,3439,15443,8022,15032,6985,16515,6520, +13218,13213,8323,2043,8750,19256,19026,10001,14089,8534, +6504,908,18238,9098,17128,2669,19633,19217,3316,11048, +910,11016,4136,12731,11353,9205,10989,2740,21004,11955, +2792,18512,1860,21010,8942,8918,19446,4850,10158,11225, +2540,6809,2254,9248,6506,17972,13691,2256,7209,8336, +6524,14358,9808,11563,11076,15525,8477,21363,5186,19944, +5244,7323,3962,3835,1943,7276,20814,8973,20456,13010, +5259,7430,19761,18334,17044,20461,17050,17052,13492,6403, +6405,4289,14622,15676,10851,3752,14272,18796,18858,18320, +13367,9372,4512,13896,20126,20502,3797,19543,8815,5950, +14365,2095,16110,5497,16776,3566,13744,2096,12909,7265, +19564,1029,16825,20875,20905,3567,18301,8908,1583,8173, +16589,6347,19948,13234,14413,20763,20038,16250,11622,12542, +12543,1073,1020,20229,20006,1739,20880,11540,12559,18593, +20671,20312,18440,6068,11675,18672,2642,12253,7231,10952, +13434,2822,7233,20423,12100,11484,12910,16116,1125,3651, +8284,9079,12829,12861,6169,11818,5398,3221,2622,17521, +2054,6683,1109,20920,9081,4212,4213,11887,20702,5270, +7704,3956,11486,9920,20313,10367,3828,8407,9912,8256, +18196,17190,19661,16120,1820,5350,15671,2509,14122,8758, +10939,11888,8182,12193,7403,14178,13957,17523,2101,4770, +7655,8183,6886,15989,12544,20274,15038,18649,8414,16254, +1917,21752,18677,20375,10368,15058,16121,1188,16434,16294, +13198,14335,11249,10977,4962,3511,16649,8358,19962,21612, +15746,15973,1355,13958,21757,16656,12631,2512,14067,10572, +13292,5170,3655,6855,12688,14737,12872,10056,18202,20742, +9832,5590,11679,6891,18375,20766,1952,1731,15687,21643, +8751,12006,7737,11319,5333,10992,14052,12235,11944,7413, +20748,8118,7414,18273,11558,6209,12344,16354,13999,11761, +14657,21615,20712,18094,6624,1596,18476,6588,18321,21705, +17819,8705,7046,15690,9113,9121,2422,8120,15995,6694, +5325,2707,17426,17586,12922,2106,1289,18553,16355,3565, +16605,21616,5326,5451,13240,13802,13619,2711,15246,15234, +13803,12205,8685,18561,3522,20817,11914,9109,13419,17244, +7939,11219,4328,2922,14191,15318,20350,12042,9641,15545, +6359,20965,16202,17095,16606,13043,15730,20641,4329,11939, +13563,20368,16752,14349,8638,13804,13990,2234,15265,8122, +2685,2894,5849,4775,3702,12812,15070,9770,2475,2568, +5649,10429,10303,21619,5080,6428,20369,13046,15531,6487, +11516,7546,5720,19339,1004,20987,11782,10745,2253,8795, +2767,14353,16042,7675,2169,12884,1662,7594,18566,5458, +12885,6974,12417,9313,4151,17301,13910,5783,20142,19007, +17213,2477,11592,6276,5697,3272,11727,9998,20770,6709, +7682,7117,2025,15459,3406,1797,2375,8390,17435,1358, +4973,21451,16175,12569,13241,4148,6463,7683,15325,13131, +16643,7435,19378,11574,10380,21452,20254,12571,2992,6993, +3467,14090,13276,7756,8860,3388,17543,18699,1043,8324, +18700,4343,10993,11066,7118,15364,3531,9246,8267,18656, +13908,18715,18711,11688,6903,7819,1717,11833,5263,21005, +7817,9093,11343,7524,17550,9943,15396,1121,15086,10320, +10570,13706,21006,18513,9453,1932,14761,3157,11732,17259, +8542,9676,9130,6569,19320,10343,10265,12893,12894,12899, +9215,17174,19266,10930,2173,19321,3154,17554,14359,10645, +10933,11077,2580,20146,10544,15397,9698,3731,16207,3470, +7698,9252,9704,5767,5771,6957,18101,8654,18849,5096, +1140,12527,3715,8802,11271,16783,6092,2057,2828,5274, +17882,7710,2416,20634,4197,19671,1129,17883,4198,11776, +3738,4188,18970,8713,18381,6958,15960,17494,4200,18478, +17067,11280,873,874,3633,20715,14821,9870,13450,17754, +18870,7685,14235,7686,21462,19040,9775,1521,9528,17504, +17505,18011,12669,12677,8419,20377,20378,1147,19690,9221, +16487,14459,7291,7296,19678,7717,15962,4011,19137,12994, +13466,20429,21443,21447,21453,13211,9972,21463,2846,4106, +21215,7846,5998,12151,19461,11481,12678,12263,10127,4830, +4569,7982,20546,18863,14293,7483,4368,20996,4466,12391, +4467,20414,8881,15223,19646,7123,7156,6895,17513,15764, +15348,3667,17805,2222,18456,14564,11240,11241,16084,2931, +16740,1302,1158,7769,14460,6416,4564,5768,17920,4651, +13221,6324,18251,20273,4565,14437,8285,18467,1742,17981, +12528,20675,10041,6038,11368,1593,17872,6829,21627,14637, +4625,3870,16539,3924,878,1743,983,10210,8927,15794, +14574,6661,17923,8964,8848,7656,7929,20929,15903,6271, +5059,17362,5957,8521,17282,9030,21142,16846,14496,20578, +20579,5961,6045,16271,15748,21444,21722,21126,14210,11681, +16870,12775,20768,18971,961,16277,9958,2268,16325,17473, +4602,17975,18813,20068,6698,17857,11253,18643,19350,14773, +16456,13275,10876,11552,7423,18479,2937,18567,15281,12600, +7676,8573,5236,16622,2324,12813,6052,18393,9649,7183, +10986,20150,17598,6053,11393,3076,11708,20482,6787,5977, +17968,2874,9874,15444,8023,12418,9973,16994,19027,7189, +6675,3350,18695,18696,9655,15420,15927,17477,4639,14429, +20556,6027,19041,17388,17691,14198,7688,1278,8067,18405, +911,18712,13881,11019,9668,2434,8943,3863,3864,18635, +6920,10483,13827,10236,10646,10545,14163,15526,18355,21216, +19936,18904,6325,14734,2028,14470,20288,1984,17891,6772, +19191,13158,4664,12324,1141,10042,4606,13468,11921,15795, +9298,21708,11298,6609,16087,12635,19232,21586,16342,15928, +9305,9330,10237,12445,14794,15622,13718,1053,4209,3505, +9582,13370,8108,1407,2494,3042,13898,12854,19565,16680, +18079,4479,21541,13747,16113,3668,10797,2553,18905,5077, +5370,18773,7584,14171,16293,8133,10798,16977,19860,4621, +3922,17141,2932,14727,6475,17634,11859,2753,15018,19951, +7925,6942,10831,1438,984,4672,18918,4818,11541,6417, +18159,3988,17654,18530,4279,20540,20056,21718,14461,3671, +10325,15019,11542,17145,14990,16978,5598,4878,11369,18930, +18674,18679,14638,11766,1414,18789,11678,9105,6085,12036, +4480,21036,3332,3009,18518,4822,14731,14306,15021,14376, +11545,19408,20921,20314,3416,5467,12563,990,4879,1816, +4233,1400,20361,14991,21256,12130,14627,5599,2118,18599, +8149,10174,10898,9600,13786,20199,13996,19405,18087,12800, +20626,18797,17351,20707,9612,14076,8590,1730,13728,1115, +13729,1765,21485,2719,18941,3049,7472,21719,4379,4400, +19713,4440,5399,20394,9613,19097,18942,14643,4893,13865, +18798,8821,13311,14040,18042,4234,2918,11418,20093,11959, +19223,7782,10175,20449,18088,13977,20635,1287,15839,9083, +8048,1826,1356,13929,16855,9278,10177,4739,12632,16593, +8497,5125,15113,13389,19504,10268,12182,21359,3681,17925, +15994,20213,19535,1457,3622,5928,20813,13761,1314,7409, +6581,16272,11937,7244,15777,7157,17414,10492,8890,2079, +4675,15024,14993,4001,13223,19335,8195,9065,21441,2164, +16441,8049,9485,1732,17122,4802,15566,20941,9154,9720, +21415,9489,12807,1750,10589,3067,12973,12700,1958,2177, +20582,4613,12019,1206,6836,2519,20201,9633,19738,19739, +5551,5813,3967,5172,16326,3257,4489,2466,20454,12776, +19839,18322,19740,13535,18972,13732,12637,21417,4914,9159, +21645,21646,4658,2395,13272,11658,16278,10412,6019,7748, +2723,8257,8226,2520,21758,13002,18147,12304,21445,21499, +1690,12201,3903,2804,2269,10970,6448,7415,5716,17031, +3539,5774,3739,20815,13600,11483,4965,5335,12236,14225, +18807,14390,4216,5014,16457,16361,7297,21587,7347,18814, +16955,18388,18328,7348,19679,6110,16663,12369,1476,18535, +5825,17823,13967,18480,9122,18274,1353,6699,8975,7859, +8976,14937,4748,16173,7052,11471,10877,8831,6364,15860, +19611,19481,3070,17992,18505,20643,12370,18691,7796,18692, +14887,19602,16362,10915,15692,7058,7797,13854,6628,9380, +13564,17332,14606,15409,16542,14408,2779,12309,7300,18998, +20435,4929,11948,11127,5527,7497,15300,18609,14133,19889, +21557,11307,15133,7310,18568,7806,6674,5148,12929,10706, +19890,13809,14585,20820,16547,15861,13805,15490,20380,14943, +14506,8690,16890,5522,12644,5215,15238,12043,15547,5289, +2939,20652,11894,7070,5455,13011,12953,10921,17901,5184, +21420,16154,13096,18523,3721,7301,20976,3526,10222,14042, +16962,6975,9771,6788,19373,12983,5864,5087,5088,16043, +6488,14108,3179,12211,19513,7574,6431,6596,5784,11783, +19008,5199,8631,5725,5726,10747,20588,21351,9382,9302, +2427,3077,9502,17769,13277,14867,15892,5652,20250,15140, +9392,10377,9824,11135,10286,2347,15141,8693,1628,10435, +8123,20614,20325,14755,10748,11476,18525,15782,12212,21285, +14134,13572,7358,3078,6976,18233,18030,4423,18102,20856, +21710,3109,12603,14824,6489,9018,20659,14236,16908,2943, +3767,4430,11338,16764,13698,10016,10150,13104,17305,13956, +4494,20440,9353,20031,14892,4152,2480,15500,11009,15148, +8456,15421,6793,6986,11941,16176,11841,13935,15929,20295, +4689,13329,13672,6191,12935,5489,10184,9364,5200,16995, +14508,21558,14031,7083,3981,7995,7513,2845,3312,14758, +7555,10004,11581,19193,6801,14199,21731,17970,2484,5149, +8239,21734,19042,12606,4757,6738,3493,7196,15214,12496, +2537,2812,21294,6802,7084,7835,7303,14686,7436,13036, +3547,18872,1660,15033,14328,9661,19171,15580,15366,11155, +12734,16046,1734,6907,7202,12892,11690,11836,18759,5223, +7525,19218,11897,13288,18340,12735,11140,20559,5788,2945, +7000,8981,12517,3592,2794,5299,11156,19448,21012,6670, +12895,9430,9397,13995,10385,9669,3158,10527,11228,6814, +11979,10481,21007,5204,4039,19906,9677,4643,21465,15088, +9750,7602,2798,13302,21190,10348,18289,9683,21191,2458, +7824,4352,15099,6508,11800,19802,10238,9134,7646,17260, +5738,8268,17458,10103,19270,7384,19200,19492,19326,17341, +11884,1869,2211,9222,8270,14857,14362,21736,3113,13582, +13493,2022,8170,19809,10630,9701,3160,10546,3472,8481, +18296,9253,9228,21217,9411,9575,1108,11572,19816,10106, +5687,6517,12857,17808,2331,2825,12804,8582,18943,8415, +17025,17875,6069,9000,9273,8891,14905,862,17820,2629, +13239,8606,8893,8608,2873,5568,19113,19613,17429,18697, +16694,15460,7948,11973,6343,15695,6518,17833,12166,16996, +17502,17837,16910,9776,2847,19043,4350,19637,2994,6526, +1911,1912,8286,12915,2596,14082,2630,14086,21061,15203, +15204,9650,20251,19624,9656,5733,4287,20567,11361,11362, +18595,14464,17876,8421,12838,13390,15114,13269,18973,15961, +18686,1977,6837,3849,20653,20047,16543,2763,15696,7949, +14264,19168,3788,8162,9019,3165,3389,4080,7556,9803, +1719,4040,7378,7385,21257,13293,18956,14123,8704,13125, +18554,18129,6773,13628,6970,11974,6737,4103,18760,17463, +5637,10935,877,7830,12293,2197,10829,10830,12290,9911, +7237,13997,11460,16169,18089,4401,13794,17235,8221,13391, +4002,11963,12138,8227,4189,1392,14019,10878,14001,14749, +16184,6111,15323,14021,10479,11433,9507,15930,13816,20410, +14071,20411,11022,10386,3868,8398,12785,18461,11633,1712, +14377,12801,16847,13253,18205,3934,18508,20026,20762,1727, +3474,14876,9373,11693,4515,5741,1683,20271,11161,3776, +19946,2881,16244,4518,3320,16111,10794,13371,12447,12849, +16675,16676,16020,8132,20793,20876,12855,8011,8012,13939, +8490,6225,13589,1584,5137,21027,12072,8402,6390,11853, +17866,17869,20007,18302,3413,19454,6411,6881,11856,10893, +11109,2678,12073,1411,20877,12056,21372,20089,10122,20230, +4728,10953,20092,16118,9594,11089,18779,4425,15717,14926, +8925,8085,8177,18919,7234,21033,6746,1340,20232,21196, +19437,5466,6326,12178,3039,2590,15105,2462,14981,8217, +18039,14462,8404,4871,7106,5640,3414,19139,21089,18675, +6685,20127,2505,16388,6308,7465,14994,4376,17705,4881, +14075,20887,19205,16712,8657,10654,967,15679,11417,9442, +18739,11091,13545,12529,17465,17570,15107,8903,13152,8279, +12469,17744,20923,5676,11294,16683,13435,18931,8037,14521, +12239,2224,7927,9925,13383,16435,5925,10806,19465,1821, +3996,6240,18944,19334,9236,5943,9556,5331,9787,2951, +4771,18945,15905,9322,7242,2680,8090,15171,2467,12153, +17283,14440,9076,12453,5958,7977,11723,15972,17490,15872, +4259,16085,9614,14879,14995,9444,14880,4024,20015,6180, +17728,14711,2982,20493,8778,16273,16125,3931,16635,8196, +14343,9816,6833,15317,13154,3556,8372,5511,5858,5962, +21099,12232,6046,2264,12633,4546,2598,10405,8222,9445, +20611,12476,15747,19725,11655,10406,11118,8050,10058,10587, +13473,19726,11725,1619,6334,19837,9155,13254,12949,20890, +19184,1827,1343,19832,16603,13965,4583,19833,8711,7158, +14344,14079,12690,12343,16858,19835,13840,6589,7416,11927, +13397,15856,4743,16636,15639,16356,13868,2066,6099,18323, +6248,11097,10835,19230,18324,6210,14493,10943,20116,6845, +11533,5758,2653,4321,9791,12808,12809,10910,15727,3118, +16401,1969,6764,1831,17856,7060,7411,4788,18974,19208, +14577,7749,20638,15453,19603,1467,11277,14526,15975,14474, +19414,8228,3968,16054,7670,13398,15464,10220,6896,19874, +11559,1178,19508,13557,21347,9845,2178,17201,2956,6144, +21500,10759,19295,9119,4744,10277,16402,17092,19296,12506, +7940,5777,15282,19885,9727,18607,11004,21405,2527,15381, +3290,16203,5419,14055,20320,14581,10603,10688,16363,20117, +16802,16544,13006,20243,14529,871,20023,19114,15127,15290, +14530,863,12065,2837,16620,2011,11220,5286,6049,6673, +17036,3626,20966,19240,7798,5258,15176,7713,6775,19158, +5194,14849,2958,17495,19750,17782,6429,1478,1624,20977, +7595,8809,14451,14261,11128,1000,10375,6397,19441,2235, +4533,19372,5803,10762,13286,19619,7174,18171,2345,16989, +7175,10304,10223,7907,5850,3102,20854,5089,13030,7718, +3071,2961,16044,11996,15605,18664,16959,11129,15491,14262, +5975,9728,16204,2609,5113,12206,21572,8630,12187,20495, +2697,17902,6879,7499,18230,2902,9861,3185,15650,7549, +3103,19341,6258,17658,14820,5650,3104,9047,17903,20978, +12349,8444,7722,12508,3487,6789,7811,16761,12009,7075, +16410,15146,12956,17045,17046,15253,4178,11286,13955,15142, +20657,3105,18999,20988,16237,15394,18100,9013,18645,16007, +13982,6167,1505,2192,14780,12602,9969,16411,14095,14088, +2534,8099,6491,7629,9363,3218,6277,5938,20028,10192, +6278,4935,6054,6122,17214,7503,14197,17047,1038,10378, +11848,19634,10003,14486,3458,6599,20255,17604,19780,14681, +18024,10085,10782,21520,19379,6794,1994,9801,3768,18707, +6550,20660,10783,3407,19029,15210,12351,8325,15326,13215, +21459,11877,5833,7953,12165,14091,7085,16516,2810,15332, +15034,15884,14092,21234,9744,11102,14544,14825,11137,11849, +19312,19313,11017,7959,12732,7197,21716,16667,15553,19197, +19128,4133,3029,6904,13300,9261,8537,885,16413,1701, +5533,12941,19314,1702,9094,4642,2014,10888,7526,16478, +10666,20155,10454,9662,19447,18514,10384,15013,20997,19355, +4038,16334,6715,17614,12048,14432,1638,2200,11226,10159, +7375,14097,2539,5536,1706,6914,17311,10344,13242,13826, +9678,8070,17452,19323,15190,16484,6507,18047,21188,10232, +9181,4137,4537,6383,9182,14762,10097,19324,11103,7217, +9806,7528,19267,9986,19065,7382,2210,3359,13676,7450, +9216,4504,14870,19851,21470,4763,14360,9433,9217,3112, +13491,19388,12943,4452,8473,18429,19327,13983,20164,10547, +18419,9534,11105,14250,15398,3471,7699,2249,19329,6064, +21214,9266,9226,11577,16241,10551,18111,17265,18432,5152, +18436,19820,5668,17394,17395,6679,6203,21322,20357,17563, +2639,20109,12794,21034,4673,11860,16561,12560,18920,12254, +8580,12058,8581,12097,11457,9905,5670,17663,5671,5672, +1567,3282,17079,20734,21198,8710,20525,4882,1078,17571, +17572,10118,21411,12108,15354,18500,15887,14207,16389,6658, +21091,7657,17877,6186,13592,6579,17760,17761,17236,19142, +16686,21093,18548,14644,16345,15906,18043,20114,8583,17083, +17974,20736,12532,6727,5679,2381,6689,2412,6757,9927, +4902,8091,2382,12596,15840,21435,15874,5886,9299,14182, +17884,2650,13795,6355,16860,14740,6143,18051,8837,8422, +17415,16861,21360,8525,3682,17580,7053,16793,10493,18376, +8223,10013,9039,6857,16088,16871,3203,16719,6211,8304, +4966,16661,3068,4789,12481,13316,13966,16872,13317,17669, +18975,7618,19741,5182,12305,5517,16327,14475,5569,14290, +14291,11634,5336,16357,2424,6147,8993,21062,17068,6700, +4790,9796,17681,7671,1479,19233,21230,16458,16032,14211, +16885,11929,11930,2182,18227,8092,8097,10963,16505,20340, +7936,13322,13855,6591,4490,13402,15205,18481,9934,7752, +20216,5570,19990,11554,14664,9847,5456,15492,2357,4362, +1842,6667,17539,17041,16805,19992,6118,6149,16892,20027, +11515,14213,13323,18623,11130,9732,19304,16753,5408,18394, +13052,1494,1629,3079,10436,7359,10287,12213,15178,19011, +15893,8445,21592,6432,18822,20989,16509,10181,5978,11975, +13712,8098,9051,3163,20296,7366,16912,16913,19012,17503, +2668,6635,2240,18698,18103,18400,18104,13075,8536,3573, +4179,14399,7632,4690,14958,19781,9974,8100,14299,4691, +18105,9258,10947,15533,19030,8101,10987,8024,8025,19309, +19044,18025,9206,15383,1996,16919,13631,21622,9751,6739, +21208,10093,16371,19045,17549,20557,6803,3299,11934,1757, +13882,6156,18066,7961,2742,3549,18631,6157,9262,1641, +13824,9670,11406,13972,10528,9131,992,18071,8944,14917, +9891,9684,10349,8463,9900,18415,16939,17617,10239,18716, +1999,13688,19981,9263,3114,2702,5658,8338,2392,11075, +15527,9264,21218,9254,10107,19822,20533,20731,12109,2465, +16403,5936,8446,18652,21685,4404,2899,8671,20171,3850, +13012,19374,13037,12060,2338,7339,2893,19614,20341,1553, +1200,1843,2895,19515,4041,2471,11852,8109,15294,13748, +10790,4544,5162,18363,5246,1303,14992,19530,5248,11439, +3653,13599,13548,21566,10808,8760,12870,9490,12552,5173, +15593,1345,13558,2957,7254,4749,8686,8229,2786,17042, +1329,10661,7863,10679,14022,16510,9508,4153,15931,13105, +16920,9671,4042,9945,12024,12395,1866,16940,2714,16419, +13701,2715,1072,7105,2148,21426,5242,8645,1807,6302, +18190,19135,4458,21357,8910,21070,11455,12255,8219,18780, +17675,16139,10039,12256,11676,18596,19523,18040,3396,1811, +23007,23008,23009,23010,23011,23012,23013,23014,23015,23016, +23017,23018,23019,23020,23021,23022,23023,23024,23025,23026, +23027,23028,23029,23030,23031,23032,23033,23034,23035,23036, +23037,23038,23039,23040,23041,23042,23043,23044,23045,23046, +23047,23048,23049,23050,23051,23052,23053,23054,23055,23056, +23057,23058,23059,23060,23061,23062,23063,23064,23065,23066, +23067,23068,23069,23070,23071,23072,23073,23074,23075,23076, +23077,23078,23079,23080,23081,23082,23083,23084,23085,23086, +23087,23088,23089,23090,23091,23092,23093,23094,23095,23096, +23097,23098,23099,23100,23101,23102,11,34,37,328, +70,72,68,118,23934,6,66,74,330,75, +76,77,78,109,112,88,90,92,94,96, +98,100,102,114,115,104,106,131,132,133, +151,143,144,136,135,146,145,134,152,137, +165,142,140,167,124,147,148,158,155,154, +153,138,157,163,164,159,160,431,150,149, +339,338,327,79,80,443,18,323,321,322, +331,325,491,335,336,176,178,177,175,174, +169,168,171,170,332,185,189,183,187,334, +23103,23104,23105,23106,23107,23108,23109,23110,23111,23112, +23113,23114,23115,23116,23117,23118,23119,23120,23121,23122, +23123,23124,23125,23126,23127,23128,23129,23130,23131,23132, +23133,23134,23135,23136,23137,23138,23139,23140,23141,23142, +23143,23144,23145,23146,23147,23148,23149,23150,23151,23152, +23153,23154,23155,23156,23157,23158,23159,23160,23161,23162, +23163,23164,23165,23166,23167,23168,23169,23170,23171,23172, +23173,23174,23175,23176,23177,23178,23179,23180,23181,23182, +23183,23184,23185,23186,23187,23188,23189,23190,23191,23192, +23193,23194,23195,23196,23197,23198,345,352,359,366, +373,380,387,394,401,407,23679,23680,23681,23682, +23683,23684,344,351,358,365,372,379,386,393, +400,406,410,413,416,418,420,422,424,426, +428,430,343,350,357,364,371,378,385,392, +399,405,409,412,415,417,419,421,423,425, +427,429,342,349,356,363,370,377,384,391, +398,404,23685,23686,18727,4412,14015,14972,16730,10188, +12616,1048,8127,14553,23687,23688,346,353,360,367, +374,381,388,395,402,408,411,414,23689,23690, +23199,23200,23201,23202,23203,23204,23205,23206,23207,23208, +23209,23210,23211,23212,23213,23214,23215,23216,23217,23218, +23219,23220,23221,23222,23223,23224,23225,23226,23227,23228, +23229,23230,23231,23232,23233,23234,23235,23236,23237,23238, +23239,23240,23241,23242,23243,23244,23245,23246,23247,23248, +23249,23250,23251,23252,23253,23254,23255,23256,23257,23258, +23259,23260,23261,23262,23263,23264,23265,23266,23267,23268, +23269,23270,23271,23272,23273,23274,23275,23276,23277,23278, +23279,23280,23281,23282,23283,23284,23285,23286,23287,23288, +23289,23290,23291,23292,23293,23294,13,14,16,324, +20,22,1,24,27,30,121,32,3,36, +38,340,341,348,355,362,369,376,383,390, +397,40,43,126,128,130,45,47,432,439, +441,447,449,456,459,462,464,470,472,477, +481,487,492,498,500,502,504,506,509,520, +522,524,526,528,48,50,51,52,53,57, +433,440,442,448,450,457,460,463,465,471, +473,478,482,488,493,499,501,503,505,507, +510,521,523,525,527,529,60,62,64,69, +23295,23296,23297,23298,23299,23300,23301,23302,23303,23304, +23305,23306,23307,23308,23309,23310,23311,23312,23313,23314, +23315,23316,23317,23318,23319,23320,23321,23322,23323,23324, +23325,23326,23327,23328,23329,23330,23331,23332,23333,23334, +23335,23336,23337,23338,23339,23340,23341,23342,23343,23344, +23345,23346,23347,23348,23349,23350,23351,23352,23353,23354, +23355,23356,23357,23358,23359,23360,23361,23362,23363,23364, +23365,23366,23367,23368,23369,23370,23371,23372,23373,23374, +23375,23376,23377,23378,23379,23380,23381,23382,23383,23384, +23385,23386,23387,23388,23389,23390,645,647,649,651, +653,655,658,660,662,664,667,669,671,673, +675,677,680,682,684,686,688,690,692,694, +696,698,700,702,704,706,708,710,712,714, +716,718,720,722,724,726,728,730,732,734, +736,738,740,742,744,746,748,750,752,754, +756,758,760,762,764,766,768,770,772,774, +776,778,780,782,784,786,788,790,792,794, +796,798,800,802,804,806,808,810,812,23691, +23692,23693,23694,23695,23696,23697,23698,23699,23700,23701, +23391,23392,23393,23394,23395,23396,23397,23398,23399,23400, +23401,23402,23403,23404,23405,23406,23407,23408,23409,23410, +23411,23412,23413,23414,23415,23416,23417,23418,23419,23420, +23421,23422,23423,23424,23425,23426,23427,23428,23429,23430, +23431,23432,23433,23434,23435,23436,23437,23438,23439,23440, +23441,23442,23443,23444,23445,23446,23447,23448,23449,23450, +23451,23452,23453,23454,23455,23456,23457,23458,23459,23460, +23461,23462,23463,23464,23465,23466,23467,23468,23469,23470, +23471,23472,23473,23474,23475,23476,23477,23478,23479,23480, +23481,23482,23483,23484,23485,23486,644,646,648,650, +652,654,657,659,661,663,666,668,670,672, +674,676,679,681,683,685,687,689,691,693, +695,697,699,701,703,705,707,709,711,713, +715,717,719,721,723,725,727,729,731,733, +735,737,739,741,743,745,747,749,751,753, +755,757,759,761,763,765,767,769,771,773, +775,777,779,781,783,785,787,789,791,793, +795,797,799,801,803,805,807,809,811,656, +665,678,23702,23703,23704,23705,23706,23707,23708,23709, +23487,23488,23489,23490,23491,23492,23493,23494,23495,23496, +23497,23498,23499,23500,23501,23502,23503,23504,23505,23506, +23507,23508,23509,23510,23511,23512,23513,23514,23515,23516, +23517,23518,23519,23520,23521,23522,23523,23524,23525,23526, +23527,23528,23529,23530,23531,23532,23533,23534,23535,23536, +23537,23538,23539,23540,23541,23542,23543,23544,23545,23546, +23547,23548,23549,23550,23551,23552,23553,23554,23555,23556, +23557,23558,23559,23560,23561,23562,23563,23564,23565,23566, +23567,23568,23569,23570,23571,23572,23573,23574,23575,23576, +23577,23578,23579,23580,23581,23582,530,532,534,536, +538,540,542,544,546,548,550,552,554,556, +558,560,562,564,566,568,570,572,574,576, +23710,23711,23712,23713,23714,23715,23716,23717,531,533, +535,537,539,541,543,545,547,549,551,553, +555,557,559,561,563,565,567,569,571,573, +575,577,23718,23719,23720,23721,23722,23723,23724,25, +28,110,113,89,91,93,95,97,99,101, +103,23725,23726,105,107,61,65,8,23727,82, +87,23728,23729,23730,23731,23732,23733,23734,23735,23736, +23583,23584,23585,23586,23587,23588,23589,23590,23591,23592, +23593,23594,23595,23596,23597,23598,23599,23600,23601,23602, +23603,23604,23605,23606,23607,23608,23609,23610,23611,23612, +23613,23614,23615,23616,23617,23618,23619,23620,23621,23622, +23623,23624,23625,23626,23627,23628,23629,23630,23631,23632, +23633,23634,23635,23636,23637,23638,23639,23640,23641,23642, +23643,23644,23645,23646,23647,23648,23649,23650,23651,23652, +23653,23654,23655,23656,23657,23658,23659,23660,23661,23662, +23663,23664,23665,23666,23667,23668,23669,23670,23671,23672, +23673,23674,23675,23676,23677,23678,578,580,582,584, +586,588,590,592,594,596,598,600,602,604, +606,608,610,612,614,616,618,620,622,624, +626,628,630,632,634,636,638,640,642,23737, +23738,23739,23740,23741,23742,23743,23744,23745,23746,23747, +23748,23749,23750,23751,579,581,583,585,587,589, +591,593,595,597,599,601,603,605,607,609, +611,613,615,617,619,621,623,625,627,629, +631,633,635,637,639,641,643,23752,23753,23754, +23755,23756,23757,23758,23759,23760,23761,23762,23763,23764, +71,58,73,5,7,329,81,446,458,190, +184,186,188,123,139,141,156,161,162,166, +197,204,209,210,211,217,218,219,225,226, +227,233,234,235,245,246,247,256,257,258, +267,268,269,278,279,280,297,298,299,212, +220,236,228,300,301,302,303,307,309,311, +313,315,317,319,318,316,314,312,310,308, +304,320,305,306,172,173,179,180,181,182, +337,122,333,116,117,23765,23766,23767,23768,23769, +23770,23771,23772,23773,23774,23775,437,434,436,435, +455,451,454,452,469,466,468,467,497,494, +496,495,515,511,514,512,519,516,518,517, +513,453,438,23776,489,490,23777,461,23778,23779, +23780,23781,813,814,815,816,817,818,819,820, +821,822,823,824,825,826,827,828,829,830, +831,832,833,834,835,836,837,838,839,840, +841,842,843,844,845,846,847,848,849,23782, +23783,23784,23785,23786,23787,23788,23789,23790,23791,23792, +23793,23794,23795,23796,23797,23798,23799,23800,23801,23802, +347,354,361,368,375,382,389,396,403,20773, +484,474,486,445,475,483,444,476,479,480, +485,41,326,67,23803,508,21167,23804,4,23805, +23806,23807,23935,9,10,23936,23937,119,23938,23939, +83,84,85,86,54,55,56,31,33,35, +42,39,44,12,23,26,59,63,108,111, +15,21,29,120,2,125,129,127,49,17, +19,46,23808,23809,23810,23811,23812,23813,23814,23815, +23816,23817,23818,23819,23820,0,23821,23822,23823,23824, +23825,23826,23827,23828,23829,23830,23831,23832,23833,191, +192,198,199,193,194,200,201,195,196,202, +203,205,206,207,208,213,214,215,216,221, +222,223,224,229,230,231,232,237,238,239, +240,241,242,243,244,248,249,250,251,252, +253,254,255,259,260,261,262,263,264,265, +266,270,271,272,273,274,275,276,277,281, +282,283,284,285,286,287,288,289,290,291, +292,293,294,295,296,23834,23835,23836,23837,23838, +23839,23840,23841,23842,23843,23844,23845,23846,23847,23848, +8829,17231,6535,6086,20542,7042,18120,14179,15314,15901, +9317,10807,16850,17084,1310,20931,18257,14124,5959,7983, +12018,4587,17416,1130,12691,1620,19209,9156,7333,12998, +9036,18384,21630,20942,20743,18167,9930,2092,21583,5037, +4745,16637,19875,2869,16031,18206,17531,7250,1549,19478, +18563,15235,1836,11304,15065,10689,19887,3315,19763,14531, +6021,13003,18986,20644,2012,6025,10777,7575,11431,2185, +1002,5217,3180,1359,1506,1495,6633,1901,9970,17909, +15926,18626,14914,17436,14719,4149,7725,5316,8386,4033, +6795,8879,17252,17253,11834,1558,21785,21786,21787,21788, +21789,21790,21791,21792,21793,21794,21795,21796,21797,21798, +21799,21800,21801,21802,21803,21804,21805,21806,21807,21808, +21809,21810,21811,21812,21813,21814,21815,21816,21817,21818, +21819,21820,21821,21822,21823,21824,21825,21826,21827,21828, +21829,21830,21831,21832,21833,21834,21835,21836,21837,21838, +21839,21840,21841,21842,21843,21844,21845,21846,21847,21848, +21849,21850,21851,21852,21853,21854,21855,21856,21857,21858, +21859,21860,21861,21862,21863,21864,21865,21866,21867,21868, +21869,21870,21871,21872,21873,21874,21875,21876,21877,21878, +6905,11896,11018,9944,11594,5692,14720,10345,15311,17313, +11073,13677,11600,10627,17262,12754,8479,11208,21486,10333, +15102,13369,5048,9375,1054,6226,3669,2883,5098,19567, +12765,19568,2317,6231,16742,4819,7847,18193,10973,1202, +19952,8405,20040,8406,7324,3397,12430,12996,18932,951, +12470,4883,17960,3000,5431,7289,14307,3007,13669,14466, +14378,15344,21686,10176,1444,20623,7883,7706,7474,9616, +5680,17147,21094,18216,17786,18471,17853,15109,13192,19144, +18090,1242,17380,17085,5708,2681,17878,12154,9347,3452, +19224,16567,4261,2513,15633,16750,21879,21880,21881,21882, +21883,21884,21885,21886,21887,21888,21889,21890,21891,21892, +21893,21894,21895,21896,21897,21898,21899,21900,21901,21902, +21903,21904,21905,21906,21907,21908,21909,21910,21911,21912, +21913,21914,21915,21916,21917,21918,21919,21920,21921,21922, +21923,21924,21925,21926,21927,21928,21929,21930,21931,21932, +21933,21934,21935,21936,21937,21938,21939,21940,21941,21942, +21943,21944,21945,21946,21947,21948,21949,21950,21951,21952, +21953,21954,21955,21956,21957,21958,21959,21960,21961,21962, +21963,21964,21965,21966,21967,21968,21969,21970,21971,21972, +16716,2510,8526,10903,1315,15875,17286,2830,5964,17964, +18262,17987,17789,4903,16862,10059,9624,7886,15277,4741, +16257,3760,12433,20430,14083,11250,19742,9160,11251,14501, +16404,15749,2834,1377,2472,4330,2270,1378,10413,5626, +3784,1321,12999,21418,13200,4454,7888,4062,7860,6701, +19680,10917,2940,17937,15646,17682,3347,13842,11254,7350, +16459,13920,6592,17537,2863,7424,21326,2323,9797,13565, +4098,18168,6630,10141,14536,13811,15283,18569,16545,16756, +20654,7945,19306,10691,15548,10144,9651,9282,15761,13013, +3229,8438,20536,1694,14752,2296,21973,21974,21975,21976, +21977,21978,21979,21980,21981,21982,21983,21984,21985,21986, +21987,21988,21989,21990,21991,21992,21993,21994,21995,21996, +21997,21998,21999,22000,22001,22002,22003,22004,22005,22006, +22007,22008,22009,22010,22011,22012,22013,22014,22015,22016, +22017,22018,22019,22020,22021,22022,22023,22024,22025,22026, +22027,22028,22029,22030,22031,22032,22033,22034,22035,22036, +22037,22038,22039,22040,22041,22042,22043,22044,22045,22046, +22047,22048,22049,22050,22051,22052,22053,22054,22055,22056, +22057,22058,22059,22060,22061,22062,22063,22064,22065,22066, +9052,21308,3080,18756,12724,8021,20202,13409,1006,9772, +10979,19169,6464,16517,16723,3574,17793,20297,18106,13480, +3494,9975,9876,13330,15149,5727,8026,4496,7891,10151, +6988,6796,8027,912,20204,3459,7689,5816,15446,6804, +6553,14096,15216,15737,2813,19638,7962,10346,1705,14771, +21717,9211,17004,7203,17971,13927,16668,5090,9398,4043, +9679,21013,13850,9709,20158,13332,15702,5736,15188,9135, +10240,10350,9685,9265,19271,11078,17342,13335,5659,3552, +20166,6564,1812,1822,20848,9705,14696,17347,13055,1161, +12167,4566,3398,4797,11233,16212,22067,22068,22069,22070, +22071,22072,22073,22074,22075,22076,22077,22078,22079,22080, +22081,22082,22083,22084,22085,22086,22087,22088,22089,22090, +22091,22092,22093,22094,22095,22096,22097,22098,22099,22100, +22101,22102,22103,22104,22105,22106,22107,22108,22109,22110, +22111,22112,22113,22114,22115,22116,22117,22118,22119,22120, +22121,22122,22123,22124,22125,22126,22127,22128,22129,22130, +22131,22132,22133,22134,22135,22136,22137,22138,22139,22140, +22141,22142,22143,22144,22145,22146,22147,22148,22149,22150, +22151,22152,22153,22154,22155,22156,22157,22158,22159,22160, +6350,18790,1138,8373,2289,2560,10201,3484,11035,21378, +12482,1554,21148,10202,3018,19241,12814,17208,10305,3708, +11976,21309,10017,16765,3445,16627,19259,18343,15724,5934, +2291,13265,14383,2227,2228,13930,15091,14397,10393,4786, +20334,4856,12451,3878,13590,10995,1440,8146,15241,10123, +11440,20011,4884,5330,7849,4885,15720,11441,15587,7543, +16196,4895,11547,11444,11445,2058,15723,5061,1451,3266, +20943,10563,12032,18741,6481,19604,19605,11447,8527,18957, +10129,3842,6483,3455,21380,7592,2530,2325,16105,9393, +2111,10152,3859,10020,7559,2744,22161,22162,22163,22164, +22165,22166,22167,22168,22169,22170,22171,22172,22173,22174, +22175,22176,22177,22178,22179,22180,22181,22182,22183,22184, +22185,22186,22187,22188,22189,22190,22191,22192,22193,22194, +22195,22196,22197,22198,22199,22200,22201,22202,22203,22204, +22205,22206,22207,22208,22209,22210,22211,22212,22213,22214, +22215,22216,22217,22218,22219,22220,22221,22222,22223,22224, +22225,22226,22227,22228,22229,22230,22231,22232,22233,22234, +22235,22236,22237,22238,22239,22240,22241,22242,22243,22244, +22245,22246,22247,22248,22249,22250,22251,22252,22253,22254, +12354,3866,3867,7773,3417,14744,20979,11522,1412,5163, +21124,17120,17806,2446,18041,12674,17062,3191,1445,21628, +18004,20808,4436,20891,4630,8185,14183,11699,15601,15889, +7738,16442,6730,15388,2651,10960,8055,17418,15976,10812, +17419,15158,12565,4201,14713,18987,1369,20510,5627,10676, +9961,7166,15752,935,2656,1481,11255,4114,8681,18181, +3134,14449,21064,20980,19764,4751,18483,2428,15999,5830, +16571,6595,8842,19119,8448,16903,5616,19013,2896,6780, +11925,3722,20516,14453,3142,19031,21634,15089,14093,3815, +10313,10314,13216,4943,9879,13106,22255,22256,22257,22258, +22259,22260,22261,22262,22263,22264,22265,22266,22267,22268, +22269,22270,22271,22272,22273,22274,22275,22276,22277,22278, +22279,22280,22281,22282,22283,22284,22285,22286,22287,22288, +22289,22290,22291,22292,22293,22294,22295,22296,22297,22298, +22299,22300,22301,22302,22303,22304,22305,22306,22307,22308, +22309,22310,22311,22312,22313,22314,22315,22316,22317,22318, +22319,22320,22321,22322,22323,22324,22325,22326,22327,22328, +22329,22330,22331,22332,22333,22334,22335,22336,22337,22338, +22339,22340,22341,22342,22343,22344,22345,22346,22347,22348, +10154,9331,17220,4640,3390,19213,6155,17221,5617,16373, +11889,19795,16417,19383,9428,9663,14784,3446,10006,10007, +1681,7210,2577,18515,7757,20761,10891,9692,6922,9185, +7009,17978,19348,19201,19392,15399,3732,10647,10554,10555, +1775,1778,1079,4426,4427,13140,1389,20208,10861,11998, +3040,10047,11370,7043,12233,5191,4263,5968,1468,2727, +12976,875,17476,6055,6676,6056,20256,3188,6057,17480, +18701,6059,7691,916,17694,6671,9686,12406,6134,7731, +5119,12121,13399,13620,20323,5528,8503,8504,21150,20327, +20328,20443,4044,12766,19283,1286,852,851,860,861, +857,859,858,868,876,882,881,891,901,893, +896,941,928,924,955,966,974,965,970,969, +979,982,985,987,993,1005,1009,1023,1031,1033, +1042,1041,1058,1061,1052,1051,1055,1062,1047,1059, +1050,1076,1084,1093,1090,12005,1094,1105,1098,1096, +1111,1114,1112,1120,1113,1126,1127,1131,1145,1142, +1146,1139,1143,1144,1159,1160,1172,1175,1171,1183, +1170,1169,1176,1184,1187,1189,1199,1201,1197,1205, +1214,1203,1215,1204,1208,1223,1224,1220,1230,1780, +20526,6087,6094,1781,16266,19553,4527,4967,13400,3540, +10420,20432,9504,7908,17904,7356,12044,942,10339,17862, +21113,3495,947,5537,9687,5138,16340,12795,19913,15721, +17636,17023,4733,11245,11295,14640,20012,12031,4567,10866, +17275,14645,18444,20737,18600,14384,6887,3311,20680,8930, +8186,14441,10957,11371,21261,20628,14646,3832,11700,21568, +2356,1747,11093,10214,15909,3871,3683,11623,11299,17988, +20709,18472,11377,21078,11372,10912,13094,5969,6565,2548, +3240,8376,4264,10760,17289,16874,9077,14212,15753,5814, +16235,9473,14665,13324,9935,20751,1853,1236,1240,1243, +1239,1237,1262,1261,1273,1263,1270,1279,1285,1290, +1288,1284,1295,1323,1305,1297,1306,1308,1298,1301, +1319,1320,1311,1339,1350,1349,1357,1364,1365,1373, +1380,1387,1381,1393,1402,1405,1423,1417,1413,1496, +1483,1501,1429,1449,1443,1427,1433,1480,1430,1456, +1493,1428,1488,1511,1523,1519,1448,1563,1546,1550, +1568,1569,1590,1591,1580,1605,1606,1608,1598,1615, +1614,1630,1654,1666,1665,1672,1680,1687,1689,1700, +1691,1686,1713,1729,1728,1744,1735,1740,1746,1745, +9494,9172,15206,8380,12347,6839,10421,5195,21127,19620, +6840,10704,17125,17716,6705,5815,20118,2971,7351,10964, +6291,17939,15762,17905,4443,16666,5780,11053,16623,8812, +3489,2399,13325,11395,4702,20257,20518,19032,3789,8796, +11396,14893,3085,10290,2572,10750,5728,6600,14894,16921, +12586,14430,9909,2391,7518,18702,17913,11423,5785,7519, +18713,917,6810,7442,20560,10929,2758,14072,11842,18068, +18634,6910,11023,11157,12440,11158,9431,8945,17951,11159, +6923,10352,11028,10241,5660,10767,17006,15528,8622,21239, +13193,19743,14907,20244,8482,14416,1766,1758,1779,1791, +1798,1776,1785,1777,1829,1815,1835,1825,1844,1805, +1809,1828,1790,1845,1830,1810,1808,1898,1894,1897, +1896,1920,1904,1905,1908,1929,1919,1910,1931,1938, +1944,1940,1939,1941,1953,1956,1946,1951,1957,1959, +1972,1962,1975,1974,1976,1983,1991,2004,2007,2000, +2003,2021,2026,2027,2034,2029,2041,2052,2067,2051, +2050,2055,2083,2088,2105,2094,2119,2120,2117,2128, +2122,2127,2137,2142,2139,2145,2150,2152,2166,2165, +2186,2180,2175,2183,2229,2220,2230,2255,2261,2265, +6285,19332,21100,7690,20298,19940,1104,3897,12790,21542, +16782,20568,8817,5164,3370,8409,9603,4823,16562,4280, +8624,20888,7851,1685,4297,20569,15195,16213,7878,11373, +8187,19715,10638,16144,4306,11446,21225,11910,12454,10048, +12122,9378,1782,12534,19430,8931,8759,13555,21171,5682, +4313,12839,10408,16443,895,17287,18263,12184,9348,6244, +13270,16498,13091,2089,8761,13614,2252,9283,6212,19606, +17421,17093,1207,10269,19415,2371,2385,18385,14130,9067, +5518,2090,6449,10371,2437,11932,15030,21448,8763,18329, +21381,8779,2528,12708,21631,13294,2306,2285,2287,2278, +2286,2281,2305,2310,2318,2321,2319,2335,2328,2332, +2342,2346,2348,2340,2354,2355,2364,2373,2388,2384, +2378,2389,2394,2404,2407,2403,2417,2405,2406,2408, +2449,2445,2478,2447,2501,2536,2493,2495,2507,2521, +2518,2535,2498,2496,2545,2546,2550,2551,2569,2592, +2597,2585,2588,2584,2586,2625,2620,2618,2614,2640, +2648,2638,2646,2675,2676,2693,2694,2703,2709,2733, +2724,2735,2728,2726,2729,2716,2721,2756,2750,2760, +2766,2764,2791,2774,2796,2778,2785,2775,2772,2808, +9962,8501,1793,11256,7352,6148,13621,9465,19159,16754, +12709,10591,11591,13923,18276,3907,16152,19236,8734,16465, +14913,20655,4100,17099,3488,15648,11612,15732,12815,4175, +4752,13629,13069,10692,5387,15143,4269,10146,14954,15497, +6465,12273,8996,15734,17102,12649,9738,16511,20050,4115, +9114,12030,18577,21312,2195,12820,1008,12190,10193,10382, +8620,2903,2441,19121,9424,12390,12821,12822,3181,21599, +2993,10596,6994,14238,9332,20299,7520,17053,3911,3770, +1800,20104,13077,3608,9664,7521,16922,20497,13108,7443, +19791,21391,6128,8738,20260,9454,2803,2805,2851,2836, +2838,2819,2854,2859,2861,2872,2864,2867,2879,2882, +2890,2892,21361,2898,2444,2905,2912,2913,2920,2926, +2915,2933,2938,2963,2950,2954,2948,2974,2976,2983, +3001,3012,3021,3022,3019,3017,3014,3006,3037,3045, +3053,3043,3084,3069,2889,3058,3057,3093,3117,3123, +3141,3143,3130,3153,3164,3162,3177,3170,3171,3196, +3204,3205,3200,3207,3215,3220,3225,3231,3232,3228, +3255,3252,3260,3267,3274,3291,3295,3308,3309,3313, +3317,3318,3354,3329,3333,3319,3335,3342,3330,3344, +7820,2814,18717,13633,3496,18873,12281,12282,19642,12426, +12824,919,8701,7379,19796,13928,12125,3032,1861,18516, +10710,17224,8946,9400,9432,21017,9680,9688,4505,13636, +12126,19272,9693,10242,10243,11408,14858,5661,9223,1934, +18297,13775,19949,15295,10699,17566,18531,12671,1362,4125, +21071,21072,18737,14570,19531,20924,15776,4991,11114,15161, +10955,2151,10494,19666,16717,21262,5755,17086,20809,5232, +5233,14881,7934,14443,5062,9066,3684,15570,5552,5647, +21724,10070,10414,3520,20845,1469,2807,6702,19510,19115, +21507,6897,20646,19928,16720,17245,3331,3372,3367,3364, +3366,3373,3403,3399,3410,3427,3411,3422,3423,3415, +3421,3425,3451,3464,3465,3480,3481,3500,3518,3532, +3515,3513,3519,3512,3534,3545,3535,3541,3537,3562, +3555,3564,3579,3568,3569,3580,3589,3584,3582,3603, +3595,3606,3617,3619,3623,3613,3620,20383,3628,3650, +3648,3663,3693,3685,3674,3666,3677,3692,3723,3716, +3720,3740,3736,3734,3769,3751,3745,3746,3747,3750, +3757,3759,3758,3761,3786,3775,3790,3779,3774,3806, +3801,3802,3805,3821,3820,3854,3858,3824,3836,3848, +18482,20818,18748,10918,14938,3695,1326,20656,19424,7176, +5237,15494,14944,10707,15324,5018,17941,12725,19792,6989, +15008,2196,3441,5786,15217,9568,11879,11071,3533,9672, +19982,20829,20167,9459,13835,17581,15967,13720,21543,2115, +18921,17143,11714,13342,4709,6039,20013,20801,7974,20802, +19709,8836,1177,12259,11650,9619,19466,12260,1823,10049, +11716,21755,20810,8288,6872,15910,20945,6873,6101,19102, +21492,20946,13731,4075,21265,11871,5008,5212,20276,14882, +9068,5127,7987,15640,15996,18209,10599,10423,5555,21760, +21408,1211,6966,20967,9071,9466,3873,3880,3875,3881, +3887,3889,3906,3898,3894,3914,3918,3919,3941,3944, +3948,3957,3950,3955,3949,3958,3978,3987,3984,3990, +3994,3998,4005,3977,4020,4023,4029,4058,4025,4060, +4064,4063,4070,4078,4071,4073,4076,4069,4087,4090, +4101,4091,4092,4094,4111,4123,4119,4120,4145,4141, +4155,4143,4170,4162,4169,4166,4171,4196,4184,4181, +4193,4211,4219,4208,4240,4236,4226,4237,4235,4268, +4257,4267,4255,4273,4251,4256,4305,4286,4293,4326, +4316,4308,4360,4370,4369,4396,4395,4399,4398,4411, +12208,9994,21675,19752,10565,10566,18751,17043,1575,7177, +4930,1497,11949,7753,21065,21589,17827,2452,3542,9799, +21513,19773,17910,20990,5218,5529,13812,15211,13833,7190, +8632,1988,10980,21008,7178,10445,15095,6990,19343,16596, +13353,9102,19033,6642,13165,7119,17444,12587,7635,21421, +15934,21735,10508,15219,11881,14098,6811,13673,11957,19797, +12427,7211,16066,16597,2486,6911,8947,10510,1645,14100, +21422,9542,3161,18186,19547,14379,8015,18615,9318,18601, +1234,1748,16197,21202,7707,3803,16689,5712,2891,18619, +17422,2514,8807,3431,21449,17824,4418,4424,4437,4442, +4433,4432,4439,4449,4453,4469,4456,4459,4468,4492, +4481,4483,4499,4475,4485,4510,4514,4521,4522,4516, +4520,4519,4541,4542,4539,4556,4555,4553,4554,4560, +4561,4563,4575,4585,4578,4580,4576,4600,4608,4609, +4619,4624,4620,4622,4626,4650,4661,4647,4652,4646, +4649,4668,4680,4671,4701,4707,4704,4708,4711,4712, +4721,4731,4730,4750,4737,4747,4722,4732,4740,4772, +4768,4777,4780,4785,4784,4800,4806,4812,4843,4820, +4841,4860,4869,4924,4913,4880,4904,4854,4876,4870, +15094,5614,21419,16641,16205,18210,13326,18578,18579,15799, +2349,15735,3816,8326,9877,16914,16809,8957,2897,20531, +8894,8895,2485,3210,9880,20221,3168,13134,13333,4013, +20225,10266,13170,2820,14560,4986,12858,2826,6236,12675, +6016,14467,4654,11209,13505,21263,10050,10216,1767,1117, +15001,6249,8056,3810,18988,14815,8052,13509,12456,9505, +21320,2086,3575,3219,16224,8072,8612,8073,9377,12194, +2593,10802,21199,16252,7658,15162,13222,18161,21374,19867, +6002,2081,12295,18859,3932,14186,17088,21204,11505,5473, +13155,11275,1226,2061,12156,10060,4894,4901,4919,4912, +4853,4952,4951,4964,4959,4960,4956,4963,4968,4953, +4971,4994,5000,5034,5013,4989,5004,4980,4987,4978, +5016,4982,5006,4979,4983,4981,5015,4984,5045,5044, +5052,5070,5085,5078,5079,5081,5091,5092,5097,5103, +5104,5099,5123,5128,5120,5124,5150,5153,5156,5166, +5165,5160,5159,5158,5180,5181,5201,5187,5190,5198, +5188,5202,5213,5220,5219,5227,5250,5257,5255,5240, +5253,5251,5247,5254,5273,5279,5275,5281,5272,5283, +5313,5308,5309,5317,5319,5320,5332,5327,5329,5344, +11905,4905,4487,5126,4528,14605,10857,14651,13312,11276, +10656,5775,13442,2602,19111,18620,1422,9084,7665,15245, +13869,6960,6007,21081,9161,3454,2069,4838,16000,9495, +9286,8258,5628,7425,5935,15941,17098,20969,2522,15163, +21278,21761,15857,2070,5235,5112,8905,20024,11962,17475, +12547,9163,21648,12021,1499,5314,15358,5600,19556,7357, +20552,6398,20755,14154,21128,10431,9963,8529,4931,20324, +5486,12886,8530,2927,2073,21676,1875,17942,1555,15248, +17248,12492,17686,6371,14539,19939,2941,10524,16696,3945, +14915,7077,7800,17687,10967,4535,5348,5352,5354,5364, +5369,5368,5376,5379,5371,5378,5366,5374,5365,5394, +5395,5396,5404,5403,5415,5412,5414,5429,5428,5442, +5439,5441,5446,5481,5474,5462,5485,5461,5465,5464, +5463,5524,5495,5513,5504,5500,5501,5543,5545,5541, +5553,5564,5563,5582,5585,5589,5594,5596,5597,5603, +5612,5605,5607,5608,5606,5629,5625,5663,5642,5657, +5639,5667,5688,5695,5717,5702,5699,5711,5698,5701, +5706,5742,5753,5746,5751,5773,5769,5779,5772,5765, +5799,5800,5812,5828,5821,5841,5856,5868,5872,5879, +2875,4754,21288,6262,13163,13350,11202,12984,5488,14588, +20032,6124,15501,19974,2713,13971,20758,11789,12986,17478, +5388,12086,4067,21460,2789,14159,21289,13016,10227,7367, +1927,6805,1515,3634,3086,18237,14110,3166,12318,12404, +19798,16045,20258,14160,5787,18832,6434,2241,8813,12497, +20219,6995,10307,2075,11731,15268,3167,3793,15269,9383, +9810,17445,1862,11141,14161,3497,9885,3392,4975,7444, +11287,9022,3357,7639,15249,9333,17453,10460,14689,20135, +12781,12023,12736,12321,5133,8333,10461,10455,18288,3461, +14012,21296,5424,12896,9758,14690,5883,5882,5884,5893, +5890,5892,5891,5906,5910,5916,5933,5915,5929,5931, +5917,5944,5942,5983,5982,5956,5953,5981,5955,5963, +5951,5948,5993,5999,6003,6029,6028,6023,6018,6035, +6034,6044,6036,6043,6067,6070,6096,6102,6093,6074, +6079,6076,6075,6100,6114,6089,6081,6098,6151,6150, +6152,6139,6166,6165,6170,6173,6174,6176,6178,6177, +6190,6192,6184,6204,6205,6207,6239,6247,6235,6224, +6220,6222,6286,6284,6288,6300,6305,6310,6303,6321, +6318,6323,6366,6352,6363,6351,6373,6349,6372,6360, +9218,9024,19647,19977,6031,20667,15367,15704,11801,2745, +18839,12746,15615,21338,21157,4472,14789,21156,12944,21473, +15617,10469,10353,7389,16187,19328,19812,9187,10246,13171, +9764,9227,12904,19984,21054,13495,9765,1566,4108,21702, +9543,14550,10632,19331,19986,21475,19821,4482,14371,20570, +14380,11917,6088,11647,3227,20507,12863,20374,1418,1163, +16789,14125,8625,13837,1419,15197,19145,20574,11094,15377, +6420,5107,8294,11378,21145,2563,15115,6250,15913,2062, +9960,21348,1118,9312,4384,13443,6107,17294,4920,9561, +19968,10432,8232,12716,1132,20479,6348,6391,6393,6410, +6401,6412,6404,6444,6455,6454,6461,6460,6476,6474, +6473,6477,6501,6499,6498,6500,6511,6516,6531,6537, +6530,6566,6576,6580,6575,6590,6593,6582,6578,6574, +6570,6607,6611,6617,6641,6639,6644,6612,6614,6623, +6629,6660,6664,6657,6663,6678,6684,6696,6713,6682, +6731,6718,6774,6735,6785,6741,6763,6760,6758,6761, +6744,6756,6743,6745,6752,6749,6830,6828,6831,6846, +6843,6856,6867,6871,6875,6874,6888,6882,6894,6906, +6883,6892,6929,6935,6952,6936,6965,6978,6949,6971, +5865,6450,14029,15498,1577,11182,21633,7505,9509,17606, +4847,11952,1336,5531,17783,7259,21352,15505,14032,4717, +7598,11340,14033,14034,11956,2670,9826,8882,1880,6558, +14787,7212,17314,16048,11806,9689,21783,3638,11807,15809, +9267,14923,8111,5372,20764,8113,19524,7143,2143,21139, +18085,19938,6237,19549,5249,16253,13755,16564,13384,11502, +21487,15959,11862,4804,7147,14736,2952,12261,20708,14126, +6241,20892,7045,4656,20016,13758,3402,7884,4570,3193, +8138,20094,1064,4831,20948,12639,2710,6245,20095,17027, +4906,17582,14388,1788,21266,13507,6938,6932,6944,6987, +6928,6941,6947,6953,6961,7026,7033,7057,7069,7092, +7061,7024,7041,7047,7030,7032,7063,7031,7108,7101, +7109,7102,7168,7131,7187,7136,7126,7159,7135,7155, +7142,7153,7152,7124,7125,7140,7130,7134,7129,7148, +7127,7257,7236,7228,7232,7241,7227,7268,7278,7292, +7287,7293,7307,7312,7304,7306,7305,7308,7320,7330, +7319,7317,7334,7321,7349,7329,7325,7326,7316,7341, +7401,7410,7400,7432,7418,7397,7404,7426,7399,7407, +7406,7467,7498,7494,7491,7468,7458,7495,7504,7459, +10061,21267,14318,5144,18503,4907,16147,20682,3340,2831, +14524,21042,17196,21688,8079,1179,13475,11379,14809,21720, +8933,7984,13763,6008,17588,7792,21174,2725,5592,1119, +8431,8934,6362,3051,6542,5337,15540,17532,8840,7666, +13560,5071,10657,17991,1366,17290,4915,5318,15914,13798, +15804,19112,9419,17589,8377,5063,3843,15940,14934,7591, +17353,6765,8432,7427,8381,2570,16607,20713,10498,2523, +13403,14750,1198,15942,17427,6544,13180,5355,17781,15647, +17792,17538,6255,17038,4921,15841,15186,4130,9072,4839, +7991,6424,20819,18270,8095,4776,7470,7475,7464,7463, +7478,7486,7473,7462,7548,7539,7540,7542,7538,7561, +7569,7567,7566,7565,7581,7593,7585,7631,7616,7634, +7617,7615,7606,7607,7611,7614,7609,8468,7663,7662, +7660,7650,7661,7652,7648,7654,7687,7653,7667,7711, +7719,7708,7709,7701,7712,7747,7736,7735,7739,7751, +7733,7805,7767,7763,8220,7772,7788,7799,7808,7777, +7778,7832,7829,7842,7867,7843,7848,7854,7837,7850, +7853,7845,7869,7889,7871,7874,7870,7876,7894,7898, +7904,7895,7903,7923,7942,7930,7941,7922,7932,7931, +7167,17898,13734,21590,2398,4220,9652,10521,9822,2734, +13594,14319,12717,21406,12719,16283,12980,17299,14717,16407, +15572,16284,5175,16330,1371,21384,1955,5866,3206,10592, +10180,12779,20457,1500,2988,10080,11150,12647,13160,15733, +21591,5804,21649,16894,21514,17730,9835,7909,4590,13931, +11258,19765,21620,4491,10522,17906,19242,14284,12720,17911, +17335,7360,8735,17302,13924,11151,6979,4102,2699,3709, +11259,10841,19892,17599,1253,14955,13351,1556,6568,5340, +3082,11178,16512,5021,16470,15956,5421,11203,17544,9800, +21593,1601,5807,19122,15651,5574,7919,7920,7975,7992, +7972,7989,7986,7996,7969,7980,7993,7990,7971,8005, +8030,8017,8016,8064,8060,8054,8068,8034,8043,8059, +8051,8044,8032,8088,8093,8119,8110,8107,8135,8137, +8128,8134,8126,8139,8152,8153,8143,8144,8157,8145, +8154,8147,8213,8176,8178,8184,8175,8180,8224,8216, +8250,8254,8253,8252,8315,8278,8301,8273,8282,8303, +8320,8311,8290,8272,8300,8287,8293,8341,8345,8340, +8366,8374,8354,8370,8389,8478,8401,8418,8413,8458, +8412,8396,8399,8410,8489,8499,8494,8487,8488,8519, +20998,20073,2479,2194,3351,17103,19893,21621,17834,14484, +16366,5341,14114,19310,7954,19034,21386,11709,1194,5530, +12046,21153,7368,3004,13574,14868,20076,17105,3182,7191, +13817,15551,5027,20033,20693,5221,13907,6376,20131,15608, +17306,15147,20694,21635,15552,6668,1960,1516,4779,3144, +9516,15270,18339,17000,21637,9395,21332,12989,10785,20858, +10509,11400,12392,9745,18000,21623,6996,14200,15220,10526, +1372,18758,14058,11323,13047,6848,17166,7198,14144,17799, +13663,18001,15224,13080,20301,21765,20826,14241,14035,9981, +19799,4501,9886,2337,21741,7527,8515,8528,8522,8516, +8524,8545,8544,8546,10204,8552,8554,8571,8559,8567, +8589,8593,8591,8598,8600,8614,8626,8629,8633,8637, +8644,8639,8647,8655,8656,8659,8664,8668,8669,8670, +8680,8695,8692,8673,8702,8703,8708,8714,8715,8716, +8720,8725,8741,8745,8743,8744,8757,8755,8773,8786, +8785,8787,8790,8797,8800,8805,8819,8820,8826,8830, +8843,8832,8841,8846,8853,8855,8857,8856,8864,8872, +8866,8865,8884,8892,8896,8904,8909,8929,8926,8932, +8923,8922,8950,8954,8952,8955,8971,8963,8977,8992, +13709,2243,13936,17800,6812,6495,21698,16928,13049,20034, +3300,14487,6815,7213,14099,7445,7562,6559,13081,3089, +7868,7694,1531,2204,19057,11885,15225,19058,14141,13884, +7218,1708,12959,9219,12590,18072,12747,12225,18637,11409, +9457,17555,21701,8948,19449,17915,9401,17176,2212,7697, +10354,2213,19276,1945,13689,17180,21712,21703,10667,17007, +9255,9412,9809,6227,13749,21244,20700,3829,17026,19231, +15568,20065,17291,3173,17568,4808,4809,12626,1789,12483, +17382,20548,5176,19250,5654,21742,15425,2017,12825,16628, +19268,9402,15432,10355,14973,5154,9008,9004,9005,9028, +9029,9062,9075,9080,9078,9089,9088,9103,9104,9115, +9124,9120,9127,9106,9148,9141,9173,9196,9192,9191, +9190,9204,9195,9188,9200,9198,9237,9235,9244,9238, +9256,9257,9279,9281,9274,9277,9270,9296,9308,9311, +9314,9316,9340,9341,9343,9360,9357,9356,9379,9369, +9388,9396,9425,9422,9446,9426,9417,9451,9440,9443, +9441,9463,9464,9469,9476,9478,9486,9514,9515,9479, +9480,9493,9558,9549,9550,9566,9547,9482,9605,9581, +9611,9583,9578,9585,9618,9577,9584,9630,9590,9598, +13649,14373,5471,21226,8188,10999,11247,5591,15642,8378, +4916,14394,5593,21450,19753,962,4444,14945,10708,10182, +1101,4446,2350,16518,1507,7199,2690,10185,8387,11142, +20561,10621,12322,7014,7020,10548,11086,3283,18469,19502, +19500,4676,1065,18521,5506,12997,20172,5189,18958,21268, +18808,13799,13645,13044,6545,17295,18990,18509,13014,12933, +19625,5342,19899,4502,14203,4694,14204,9780,11891,13053, +5405,2682,4657,6242,2647,3194,4908,17089,12172,9107, +12264,10189,20949,13476,16951,17533,16878,8706,6767,6695, +17423,14153,6256,7547,3543,14155,9634,9580,9626,9588, +9597,9576,9503,9553,9710,9721,9718,9714,9757,9725, +9716,9717,9715,9766,9768,9793,9786,9785,9783,9819, +9813,9815,9820,9811,9828,9842,9846,9844,9839,9841, +9869,9855,9856,9854,9875,9857,9853,9352,9902,9908, +9881,9859,9906,9914,9933,9926,9915,9929,9959,9952, +9979,9977,9953,9951,9988,9957,9996,10012,10009,10027, +10044,10067,10078,10079,10051,10028,10063,10046,10030,10052, +10035,10112,10116,10115,10119,10128,10140,10130,10138,10126, +10121,10145,10125,10173,10187,10205,10218,10207,10217,10226, +2662,17943,2667,21594,16297,6710,6295,6153,12393,9746, +13485,1012,9982,12173,13135,1014,6816,17952,3550,9339, +5432,5435,5433,3833,13915,4377,4084,15836,12265,2599, +13519,7246,8295,2780,10600,7071,20259,10291,7001,9365, +6915,19450,6509,18906,13195,20018,3371,6243,20837,20838, +20683,2383,20745,19505,16215,15770,4385,18207,15813,14106, +6050,14504,9936,7994,1424,3660,5851,16572,17907,12484, +3072,3908,3909,15864,8264,3083,8956,9739,9740,16624, +9016,9747,9752,3087,14478,15045,15843,9023,11795,20859, +3393,11837,13142,7531,15844,15846,10219,10258,10260,10257, +10280,10273,10300,10306,10310,10308,10323,10321,10335,10322, +10327,10369,10365,10366,10372,10466,10422,10316,10425,10401, +10411,10444,10415,10398,10394,10434,10474,10486,10496,10488, +10491,10505,10497,10499,10515,10519,10513,10516,10419,10517, +10531,10532,10530,10536,10557,10558,10561,10562,10571,10579, +10574,10573,10576,10577,10601,10612,10620,10608,10613,10616, +10617,10618,10640,10658,10650,10653,10651,10671,10675,10684, +10685,10686,10682,10701,10714,10712,10715,10718,10728,10729, +10725,10730,10749,10746,10743,10761,10780,10768,10775,10776, +10247,20545,14996,15128,20554,18888,13372,8740,2045,5245, +3614,6572,2617,13750,13891,19917,2099,5919,4674,12129, +12074,19459,13652,16591,12673,12291,16831,16832,8742,3830, +1446,1080,1817,13469,15722,21544,4607,20803,11696,12180, +21570,4824,17192,11442,13437,8674,2623,18443,12075,2557, +17745,4380,6188,21571,5709,2511,15796,3195,10900,17524, +17525,10731,17526,11815,16604,16594,17764,8053,19506,6181, +9931,14184,15876,10904,2955,14444,7274,15592,8343,7054, +17763,17666,16126,2515,16070,4003,11606,12332,5512,9461, +20509,15201,7750,9833,14872,1621,10770,10795,10803,10799, +10994,10793,10817,10825,10833,10840,10827,10828,10856,10849, +10864,10865,10872,10881,10867,10890,10896,10895,10902,10922, +10926,10916,10894,10899,10907,10945,10936,10938,10954,10959, +10951,10958,10971,10983,10990,11001,11036,11021,11005,11037, +11034,11046,11045,11096,11064,11072,11067,11057,11060,11055, +11085,11116,11112,11111,11132,11117,11121,11149,11145,11147, +11170,11162,11166,11168,11175,11181,11188,11190,11191,11204, +11198,11200,11207,11206,11221,11217,11234,11268,11264,11274, +11273,11272,11292,11311,11293,11300,11291,11318,11321,11325, +10590,12368,5874,13561,2924,3428,11628,11514,13764,14445, +2985,8199,3969,12308,5846,16664,10919,13921,4173,2657, +10615,11988,3696,936,11611,14847,20069,21063,13843,16001, +16461,7672,7255,4099,1482,2292,12954,16218,14714,15495, +15134,21382,19001,9862,7072,12312,17540,10502,11977,2297, +10437,5853,12078,2853,7577,4844,21310,10438,7630,19353, +10480,18031,2077,15932,11710,9878,3209,5729,17440,15598, +4497,20857,7633,6344,3208,18724,17336,15189,4716,21295, +3409,8880,11880,8459,2848,8361,9129,9777,16103,12737, +3213,1720,18067,11618,16669,20188,11331,11346,11332,11333, +11339,11336,11349,11352,11355,11376,11391,11401,11364,11386, +11385,11366,11420,11413,11428,11437,11435,11434,11436,11429, +11467,11475,11468,11464,11474,11450,11452,11472,11458,11479, +11485,11491,11621,11501,11494,11499,11497,11521,11518,11519, +11531,11529,11544,11539,11549,11568,11584,11604,11602,11613, +11615,11625,11627,11493,11635,11636,11642,11665,11648,11646, +11643,11674,11673,11698,11707,11697,11705,18231,11712,11713, +11729,11728,11724,11737,11741,11744,11747,11758,11760,11769, +11799,11771,11786,11787,11768,11817,11823,11822,11830,11819, +17312,1642,17733,9056,9132,18239,10351,6921,20098,10644, +13496,20189,10549,11670,20099,12859,16654,5696,9980,5693, +7647,7162,5193,2761,11152,11790,5278,7488,3845,20816, +17766,15359,17271,2100,13616,19682,17688,8265,8163,17671, +14339,8136,15389,14673,15458,12611,12612,5631,6496,15763, +17100,3507,4484,12000,15378,4486,2866,10331,10066,17090, +13319,12084,8849,4922,20217,4778,9497,19616,9287,15880, +1846,11740,8205,6638,21595,1602,11477,3857,3983,1216, +2110,19035,2015,10292,3355,18032,18632,3577,3462,13039, +10387,18874,7091,7532,6916,12748,11821,11845,11851,11855, +11861,11858,11870,11869,11866,11886,11901,11908,11912,11915, +11928,11924,11923,11936,11954,11958,11942,11961,11968,11971, +11969,11992,11986,11987,11994,12001,11999,12004,12011,12012, +12007,12014,12017,12020,12016,12027,12026,12034,12033,12037, +12045,12061,12062,12055,12059,12071,12081,12083,12094,12098, +12099,12103,12102,12107,12110,12117,12119,12127,12131,12137, +12141,12139,12135,12155,12148,12147,12163,12168,12181,12177, +12183,12215,12199,12209,12200,12207,12217,12218,12192,12210, +12231,12237,12250,12257,12284,12247,12252,12272,12306,12292, +10389,10356,2216,14861,7370,12455,18412,18428,2040,9374, +15833,15771,7605,12191,18896,2097,11144,5094,19700,6408, +21561,6750,15167,20902,16093,16427,12791,16560,13721,4862, +21245,6445,8403,7133,1021,2773,10862,13776,5996,19136, +19498,18907,13139,12331,3672,3616,9596,19429,1304,18852, +21250,11677,1813,1741,17779,18597,17144,6232,20347,3923, +3823,11765,6327,10897,14463,5565,1441,16492,4875,21479, +20882,7144,3063,11749,18017,5271,9604,13789,2155,2410, +19710,6011,21562,9922,16714,4185,5705,3048,5444,5677, +7613,19579,21484,4438,10819,21073,12299,12307,12294,12285, +12327,12333,12350,12341,12355,12363,12360,12358,12381,12389, +12387,12399,12408,12416,12419,12425,12435,12431,12443,12449, +12450,12462,12464,12477,12458,12460,12473,12459,12466,12500, +12502,12505,12511,12533,12539,12526,12535,12540,12558,12566, +12555,12575,12578,12576,12580,12594,12592,12593,12597,12595, +12601,12614,12613,12636,12638,12624,12630,12619,12615,12623, +12646,12621,12618,12667,12701,12668,12670,12692,12686,12680, +12660,12715,12672,12659,12698,12769,12760,12756,12758,12762, +12797,12798,12818,12783,12787,12788,12789,12793,12784,12827, +12856,21200,6536,4825,5058,3284,2878,7976,4378,968, +13088,2594,12471,7879,9345,14805,21343,3285,2056,19580, +4074,16436,9481,3997,4829,13730,19146,1918,20042,15173, +2506,2413,16715,1674,16851,5353,21264,11375,21346,21756, +16122,13385,15256,2414,12196,11000,17725,7978,2370,8495, +18259,3253,5960,3254,7272,16315,19468,11863,14289,17284, +16601,7783,11548,11461,16026,11637,10818,3050,3686,13470, +3933,21644,9108,10409,16499,11773,9037,12577,20115,5211, +5860,10588,2722,2921,20453,10978,9487,1266,13237,8359, +13196,3656,7740,7900,13092,15355,12836,12837,12862,12848, +12860,12867,12842,12851,12878,12843,12873,12919,12937,12917, +12918,12912,12932,12952,12947,12957,12970,12972,12962,12979, +12995,12990,13004,12991,13026,13028,13025,13041,13074,13067, +13065,13056,13090,13107,13086,13087,13115,13132,13130,13126, +13122,13119,13124,13138,13141,13143,13146,13148,13174,13173, +13172,13194,13199,13204,13190,13210,13201,13228,13235,13245, +13247,13246,13248,13249,13255,13278,13271,13273,13268,13282, +13283,13290,13318,13308,13341,13336,13338,13392,13373,13366, +13381,13375,13446,13421,13440,13422,13441,13431,13429,13474, +5334,6458,13177,930,16324,1376,21125,7336,9992,15438, +15726,3538,6394,6103,2934,2290,6538,4632,9157,14149, +18315,18805,14308,7160,5611,2063,20684,16182,8116,1459, +18961,11002,1282,12123,3902,13346,8682,17383,16296,19673, +19674,5009,9792,17934,11560,2068,16638,2969,17424,1551, +11465,933,19297,9085,9086,7545,11176,21759,21780,21665, +13841,16985,18688,934,13477,7342,4917,10520,7343,12170, +6251,6252,6289,18386,15977,21503,13274,11098,6626,14391, +5082,21146,7489,16452,1832,16358,7163,4095,18621,15175, +13562,20639,6838,14528,9194,21585,13504,13506,13511,13522, +13514,13533,13585,13540,13575,13544,13539,13554,13547,13588, +13597,13596,13605,13604,13607,13608,13623,13625,13615,13613, +13644,13646,13658,13662,13665,13668,13680,13686,13687,13685, +13690,13695,13702,13707,13710,13711,13716,13715,13713,13726, +13752,13742,13738,13736,13746,13745,13772,13773,13778,13784, +13790,13807,13791,13818,13810,13806,13792,13788,13829,13839, +13836,13857,13864,13885,13873,13877,13861,13893,13892,13890, +13895,13906,13914,13912,13933,13944,13943,13951,13952,13960, +13962,13978,13979,13988,14002,14005,14000,14009,14014,14017, +18534,19838,10913,19989,14810,21325,5613,13671,18005,9007, +16453,19509,15066,19116,14532,2959,14582,19991,20647,13870, +9643,13606,19888,9644,8261,16887,2776,17846,16002,10135, +6899,3741,12977,21666,12537,3242,19840,2781,19754,12041, +12579,11511,16956,4681,20025,13969,2013,11061,15236,11305, +15067,10136,16957,5477,9280,5086,3259,15488,10639,17938, +18608,5778,21618,5801,21781,15779,2071,12157,9197,14395, +9301,10074,3811,15780,10858,15891,21207,938,9729,3073, +12485,13348,7910,2962,7809,16408,16057,2033,19774,19002, +8233,1484,10376,1924,20480,9391,14025,14027,14041,14043, +14050,14054,14056,14066,14068,14085,14074,14077,14107,14111, +14127,14120,14115,14119,14116,14117,14142,14147,14152,14158, +14162,14180,14218,14170,14164,14168,14194,14175,14205,14206, +14234,14240,14237,14224,14216,14220,14232,14259,14253,14255, +14274,14273,14278,14281,14270,14287,14286,14292,14288,14304, +14303,14309,14310,14315,14313,14314,14321,14323,14332,14329, +14334,14346,14350,14341,14348,14342,14338,14337,14385,14363, +14369,14366,14367,14387,14381,14372,14407,14414,14415,14422, +14438,14435,14447,14442,14458,14455,14476,14465,14454,14483, +13031,10779,18277,10081,7164,1625,5805,5945,3629,10433, +14354,14263,3630,18056,1883,3704,3243,14398,17996,6368, +1007,11100,10284,21045,12513,7573,11131,3074,11754,6781, +8384,19162,14195,19117,5852,2425,6430,14131,8810,12981, +10678,2020,20249,9510,16471,7078,12934,14507,11011,11991, +2237,3742,13934,9423,19626,13101,2787,6466,7361,10722, +20029,1229,19487,10446,13697,4337,15652,4616,8449,4638, +13872,4686,9017,14891,18182,17835,5022,3490,16722,3946, +14956,17441,17048,10224,20074,14298,7362,15239,10086,19783, +17104,15010,11878,17946,20077,19775,14490,14498,14499,14468, +14494,14512,14511,14522,14520,14527,14516,14510,14514,14552, +14556,14568,14559,14555,14572,14571,14562,14561,14595,14596, +14599,14604,14601,14600,14618,14616,14609,14612,14639,14623, +14635,14675,14649,14625,14636,14662,14679,14642,14614,14624, +14660,14630,14610,14615,14634,14632,14628,14629,14698,14699, +14703,14701,14705,14710,14709,14706,14716,14708,14756,14728, +14738,14735,14724,14751,14726,14746,14739,14745,14722,14768, +14767,14770,14782,14774,14783,14776,14779,14775,14777,21229, +14795,14799,14803,14797,14796,14804,14818,14807,14814,14819, +16964,6058,909,6797,6798,7192,3030,17333,16299,11222, +9468,7554,1995,14400,13035,9748,8691,19900,3297,15698, +15469,20407,15240,17163,4498,3892,17607,5532,14781,7514, +6015,13994,18059,18628,1134,4134,12438,16476,11835,2741, +10716,12400,12823,20205,2432,20662,4408,11689,19315,3110, +17446,12733,4447,7437,17912,8982,1579,3818,11138,9207, +7960,13331,13166,17249,17222,15151,10482,19052,17914,17561, +19053,9116,9429,7726,3636,20898,1292,18633,11403,6601, +1639,15087,15426,16058,13334,13109,16528,10160,6806,11980, +5224,20082,1256,9681,14785,21189,14806,14831,14833,14836, +14835,14837,14838,14845,14843,14851,14848,14864,14871,14875, +14885,14883,14886,14895,14888,14889,14897,14906,14903,14902, +14933,14952,14949,14928,14924,14922,14921,14968,15004,14974, +15003,14971,14976,14977,14986,14969,15017,15039,15036,15051, +15050,15048,15047,15049,15063,15072,15084,14911,15090,15092, +15101,15110,15111,15118,15131,15123,15126,15112,15104,15106, +15159,15164,15165,15168,15183,15184,15182,15192,15207,15194, +15218,15202,15208,15196,15229,15242,15243,15264,15260,15254, +15266,15276,15275,15279,15273,15299,15292,15293,7828,15306, +887,10021,17953,13243,9184,16186,16814,13937,13938,12741, +10347,15097,16067,10816,20085,12498,19692,18069,7214,8082, +17954,13359,15098,8104,4796,1882,13678,19066,17261,19804, +8245,9781,9782,19199,13040,19269,10233,15964,6453,19979, +10101,18587,10931,5991,8962,9220,7219,3498,10789,9458, +9403,6497,4764,20827,16533,8987,6510,9535,7221,9435, +6515,10628,7015,8988,10471,7393,14013,15618,9409,13595, +17464,19080,10552,10982,1669,14930,17409,2832,6335,17814, +3236,4911,17821,10373,6396,6051,7623,8309,1275,18279, +20462,20463,8958,1703,17054,14830,15308,15313,15333,15328, +15345,15352,15351,15347,15376,15379,15368,15373,15372,15384, +15391,15385,15395,15392,15400,15423,15410,15416,15412,15403, +15435,15439,15436,15457,15451,15448,15449,15462,15484,15486, +15479,15482,15499,15478,15502,15516,15521,15518,15532,15530, +15539,15537,15546,15538,15569,15563,15562,15567,15564,15584, +15585,15590,15613,15603,15600,15604,15624,15623,15626,15625, +15638,15654,15656,15634,15670,15691,15699,15686,15682,15678, +15677,15707,15710,15729,15715,15725,15718,15754,15750,15768, +15772,15775,15801,15807,15811,15816,15827,15830,15834,15838, +3778,13376,2463,14515,8411,20571,14331,19550,5921,21548, +17360,4547,4307,1066,2626,12865,16565,19957,19958,8496, +12681,15908,12682,19868,8416,6728,13197,12683,21076,11462, +16316,4677,4678,6004,4995,13655,12112,11657,3341,12478, +2600,8296,9628,5003,20338,5436,12302,1873,17198,3783, +1675,1749,20396,15817,5514,19293,5280,3052,6732,10813, +5010,9932,18747,17203,9635,18976,12486,7793,14333,18809, +16328,11381,13157,5759,13321,9350,17684,7861,13404,7279, +16078,2372,1328,5971,17965,20714,4970,17246,9288,1485, +19841,19511,7801,3429,3762,6733,15832,15849,15853,15850, +15851,15871,15878,15888,15904,15917,15933,15895,15911,15897, +15912,15938,15937,15939,15936,15944,15947,15954,15953,15965, +15966,15968,15970,15983,15987,15992,15990,15993,16017,16019, +16025,16030,16034,16056,16059,16071,16079,16080,16075,16082, +16091,16102,16117,16109,16127,16146,16134,16132,16141,16172, +16168,16179,16181,16193,16190,16201,16194,16191,16208,16214, +16222,16226,16238,16229,16234,16251,16255,16242,16256,16247, +16282,16264,16265,16280,16270,16261,16269,16289,16295,16308, +16312,16309,16321,16317,16319,16339,16341,16337,16336,16344, +15031,8206,12721,19766,8531,14946,10593,9653,3855,15573, +9048,5937,5976,1213,4604,16466,4144,19845,15291,12955, +13945,11661,16467,9836,3935,4334,1166,3705,16331,1979, +11099,2187,9125,7067,15865,10883,17836,11153,7755,14586, +17944,18335,13845,16367,5023,19894,10968,16513,13925,17546, +17071,19245,14540,2700,15468,21180,21596,15653,19895,11012, +9128,4032,13352,16963,16644,19994,13510,19307,7550,1150, +14959,3054,16917,16613,9749,1151,13819,7086,16697,17798, +5984,18827,1395,6467,18871,4079,11536,6126,6377,6736, +10693,19037,16577,19311,15609,21047,16374,16360,16343,16379, +16384,16391,16381,16393,16395,16378,16406,16396,16428,16444, +16429,16423,16424,16425,16426,16489,16507,16491,16493,16494, +16501,16527,16490,16503,16500,16497,16508,16488,16548,16541, +16566,16557,16563,16559,16586,16595,16592,16598,16611,16610, +16625,16630,16642,16632,16640,16646,16665,16653,16659,16651, +16681,16679,16685,16672,16677,16684,16682,16701,16707,16711, +16705,16704,16702,16741,16729,16746,16731,16757,16733,16743, +16734,16772,16803,16791,16781,16770,16771,16787,16784,16827, +16893,16828,16821,16863,16829,16869,16899,16823,16888,16849, +2016,15014,12728,15788,14266,3713,10452,16524,21009,2430, +13482,12319,19639,7522,10293,13231,19198,7557,16580,17447, +10786,20593,20616,10681,5837,10155,3088,9519,10765,17448, +2301,11404,21711,14961,13356,15597,20860,12222,7692,13486, +1678,9887,5764,17002,7120,21314,4605,9334,8461,8462, +19172,2201,7640,11595,17454,11427,2701,18108,14962,2795, +2487,3463,9570,14243,18875,8029,3301,12826,3033,17369, +14355,13219,19325,2160,9673,20280,17955,21209,20264,17510, +10823,17619,12749,13828,7451,6032,21471,7826,1709,6073, +4508,9434,7825,9138,11289,9690,16875,16844,16824,16853, +16904,16817,16854,16891,16859,16884,16820,16873,16966,16952, +16950,16948,16954,16983,16982,16979,17013,17034,17011,17018, +17070,17063,17073,17110,17101,17096,17077,17074,17080,17117, +17123,17121,17118,17149,17153,17135,17132,17158,17137,17188, +17187,17199,17197,17184,17191,17186,17206,17232,17233,17269, +17293,17266,17296,17288,17292,17274,17285,17272,17270,17320, +17323,17343,17321,17334,17337,17328,17318,17354,17352,17349, +17364,17359,17357,17379,17378,17389,17385,17376,17381,17417, +17420,17438,17399,17487,17451,17425,17407,17404,17468,17472, +13417,11808,10357,4082,17461,21194,10248,9537,10249,12092, +18646,12326,11569,5540,19277,14790,16944,1981,13498,13584, +1982,10757,7827,21219,21423,6608,11919,12132,21082,10733, +4420,8555,11230,17060,8615,19923,13471,10069,17989,14811, +15915,10270,17207,6374,16514,3546,2689,16519,3548,21401, +5121,19572,18781,4826,4655,7774,21038,3400,18935,21074, +7852,20805,17527,13653,20806,8492,2158,6687,13654,16145, +10111,1267,18618,21778,1452,14317,8297,6140,18019,20681, +18801,12013,1783,3598,4996,5798,20934,20950,13656,18947, +16123,11503,5416,17985,20575,13438,17471,17481,17489,17482, +17492,17491,17488,17507,17506,17508,17509,17547,17512,17522, +17536,17514,17529,17516,17530,17558,17579,17569,17618,17603, +17564,17565,17590,17575,17650,17631,17642,17635,17632,17643, +17630,17627,17664,17667,17676,17683,17680,17679,17674,17696, +17704,17699,17698,17697,17717,17721,17719,17722,17720,17735, +17734,17746,17737,17741,17749,17750,17755,17757,17762,17780, +17895,17790,17784,17788,17787,17831,17804,17828,17815,17826, +17811,17845,17847,17899,17887,17870,17863,17865,17879,17871, +17893,17890,17885,17886,17919,17927,17922,17962,17963,17959, +19727,11058,1784,1792,2631,2627,8838,13762,7590,7479, +11380,7789,4382,13866,21172,5713,19103,8550,17710,14105, +9038,11753,14813,7252,9069,9562,8344,14392,5282,20685, +10131,7169,18993,1899,21350,14884,13647,9559,17794,2168, +9042,15571,19930,10075,2632,2271,2730,9834,12142,4589, +5802,18331,4030,20981,12777,12710,5863,8753,12640,15694, +14674,4932,2698,17595,3856,9049,4088,17795,17796,19931, +5019,19623,16055,18333,6706,12115,3383,20048,15303,5422, +6502,13814,19932,11535,8102,2129,1152,14046,11756,19251, +7865,6505,8844,9741,9511,14542,17973,17977,17984,17983, +18006,18007,18014,18010,18029,18036,18049,18054,18093,18077, +18080,18075,18078,18076,18123,18116,18113,18114,18122,18117, +18138,18141,18142,18144,18139,18137,18157,18154,18162,18165, +18170,18166,18180,18176,18185,18188,18221,18212,18223,18215, +18220,18261,18245,18258,18271,18250,18243,18248,18278,18266, +18253,18252,18305,18313,18314,18310,18332,18371,18380,18401, +18360,18367,18387,18368,18366,18382,18369,18377,18373,18442, +18437,18446,18445,18457,18452,18459,18462,18453,18468,18455, +18501,18494,18502,18499,18520,18524,18538,18536,18529,18570, +10506,19038,3822,17611,17167,16525,1658,2035,7193,14109, +1232,1508,4944,7438,21333,7439,3211,7088,3391,20105, +4500,1857,17390,18107,1677,13699,10764,9208,1027,20261, +5789,2047,15221,11882,2172,9779,3460,14786,15447,1533, +9212,4947,20899,15340,14788,16219,14691,1122,17552,1870, +2459,9186,10244,16974,17178,9224,20600,3361,8271,20168, +14549,7456,19077,9231,18187,16822,4781,5011,4798,1103, +6132,7017,7022,7460,5609,1594,18372,5714,8423,12377, +10870,11119,11120,11218,14652,15002,2167,20686,8433,11125, +15805,9733,18624,20982,8505,16960,18562,18540,18565,18550, +18555,18544,18598,18603,18616,18617,18636,18642,18644,18648, +18647,18662,18660,18657,18669,18682,18666,18667,18668,18687, +18671,18683,18726,18744,18733,18745,18743,18736,18731,18732, +18818,18770,18812,18804,18767,18800,18820,18774,18777,18785, +18835,18864,18855,18857,18844,18843,18850,18845,18885,18903, +18917,18909,18893,18881,18902,19048,18966,18991,18933,18891, +18992,18984,19009,18884,18880,18946,18985,18923,18889,18948, +18908,18894,19047,18960,18922,19093,19094,19086,19098,19095, +19088,19091,19134,19155,19153,19150,19181,19178,19179,19183, +14214,16368,17049,15756,19635,9245,4344,4065,13183,12095, +7200,11312,19316,5459,13526,20464,7963,5618,3578,7529, +10622,13527,7380,16418,8470,13529,10625,9250,14433,3639, +5623,18362,15751,13378,7881,3124,20951,2363,7048,3430, +3657,6484,13566,5287,14667,5760,7833,6860,13407,17685, +11662,6980,10439,20326,1518,17692,14267,5390,21014,18026, +2850,16932,18840,10470,8475,16942,18422,16946,18249,3899, +4992,13379,13380,7705,7145,4524,18124,3804,6274,2102, +15586,17812,7784,3418,13759,18125,19147,14221,12802,16124, +7150,18126,19163,4262,4659,18203,19203,19221,19247,19227, +19261,19219,19243,19289,19290,19291,19288,19305,19284,19318, +19286,19340,19338,19351,19349,19357,19361,19360,19382,19362, +19364,19368,19423,19421,19399,19401,19409,19397,19410,19403, +19428,19438,19432,19439,19433,19452,19453,19456,19472,19455, +19458,19477,19499,19495,19494,19518,19520,19539,19532,19517, +19519,19545,19552,19557,19570,19612,19617,19610,19622,19562, +19574,19608,19573,19600,19554,19588,19592,19559,19583,19658, +19653,19656,19662,19655,19663,19657,19694,19720,19699,19705, +19696,19745,19733,19712,19737,19749,19724,19708,19704,19756, +18532,15052,14424,19154,17640,8425,17469,11624,2418,19475, +20893,17747,4572,17668,2333,14345,18264,13980,21407,17855, +18962,18963,15119,2565,6071,14393,6108,17894,20687,21273, +20781,5448,21556,20399,5519,5012,7420,3846,10071,3658, +18522,11590,12064,21147,5145,18977,8302,18622,20367,16149, +18810,13508,20549,12487,1471,17752,13445,1083,3292,21689, +15541,21232,3015,20584,19416,17858,18095,18994,6666,6112, +14668,2126,17496,14534,6175,2144,5452,5761,13567,6776, +7802,6485,5065,17355,16365,14396,2731,3971,11062,11320, +4332,6703,18275,17748,5595,4422,19714,19735,19744,19717, +19776,19695,19830,19834,19826,19854,19861,19869,19864,19873, +19891,19858,19857,19866,19886,19884,19876,19912,19919,19929, +19920,19921,19935,19937,19966,19964,19954,19950,19965,19943, +19956,19961,20017,19999,20014,20001,20041,20035,20055,20075, +20061,20059,20071,20054,20088,20101,20100,20113,20112,20110, +20120,20121,20124,20125,20137,20144,20149,20152,20173,20184, +20186,20191,20192,20195,20206,20198,20197,20203,20200,20224, +20218,20212,20209,20207,20220,20234,20231,20228,20233,20277, +20283,20292,20293,20289,20307,20332,20317,20319,20333,20335, +1772,15798,18815,9421,21176,8906,8850,16693,7179,20983, +13770,3136,9303,4270,8914,16896,15881,3432,1331,2188, +19541,8764,13127,13181,14834,939,19683,17499,2529,7864, +17300,16695,16806,5238,15054,1890,6782,8062,14899,20716, +14900,4031,6451,2326,14873,7813,8736,13451,3106,17470, +15212,16332,17215,4617,2573,15327,19014,11487,19164,3814, +12335,21456,2238,2400,21400,7185,12650,15417,21387,16472, +8207,13287,3947,20783,20252,21650,12887,21457,9849,7506, +2843,17126,10604,14426,1657,6492,12372,19628,3860,17838, +12380,14682,17947,14683,6861,6493,20339,20337,20348,20362, +20370,20311,20356,20363,20358,20379,20376,20382,20384,20386, +20389,20412,20392,20401,20395,20391,20427,20424,20436,20428, +20426,20466,20448,20445,20447,20450,20455,20452,20483,20471, +20475,20477,20468,20494,20492,20504,20500,20503,20506,20501, +20505,20517,20511,20523,20524,20534,20535,20543,20550,20551, +20538,20553,20537,20564,20566,20572,20583,20592,20602,20603, +20613,20607,20609,20622,20642,20629,20645,20630,20661,20618, +20619,20620,20672,20679,20670,20720,20705,20719,20699,20752, +20733,20744,20729,20735,20726,20730,20771,20765,20772,20778, +4345,21083,3711,17548,4939,12605,15866,7515,12780,19784, +21521,21313,16998,6799,19124,943,17217,11555,2431,4783, +21183,18484,18402,6643,17948,5296,11950,12652,11422,18708, +16520,17689,15611,21114,14239,12516,9020,6669,6908,5264, +19317,11063,17479,11139,17001,13038,2402,18046,15658,15152, +1217,2613,12890,14688,7578,19902,17612,17449,15554,18582, +18583,20824,19643,1640,3116,9520,11341,11342,14268,20595, +11324,7446,20262,21692,9755,10294,1998,11981,5817,16967, +21466,1013,1044,7915,20596,18837,6345,7603,10787,2353, +5988,6469,2245,17839,20302,14103,20777,20779,20776,20774, +20790,20794,20787,20791,20821,20795,20797,20811,20789,20786, +20796,20842,20833,20843,20844,20830,20836,20831,20872,20885, +20866,20894,20867,20870,20878,20903,20928,20940,20901,20933, +20970,20911,20917,20907,20958,20932,20968,20914,20913,20944, +20959,20912,20947,21025,21037,21032,21039,21041,21035,21056, +21055,21075,21067,21068,21085,21088,21084,21090,21086,21104, +21119,21122,21123,21133,21143,21134,21138,21154,21168,21166, +21175,21159,21170,21169,21162,21203,21195,21201,21231,21224, +21236,21233,21222,21269,21255,21243,21270,21251,21277,21272, +16933,20329,4138,20785,11597,9213,4278,19356,8464,7003, +21751,7695,1881,6817,21335,11347,20285,20345,14592,13110, +15428,20286,12608,14488,17956,20222,15431,3468,15227,17175, +7006,7730,9760,11892,18763,888,20415,6740,6819,19067, +19068,14244,13692,11900,12960,4140,15338,6438,21117,6033, +920,19273,7386,19805,7455,6826,4047,20599,17958,20165, +9436,14434,16535,2250,9702,18841,1611,20601,18423,4355, +2748,16537,2749,18639,2217,13693,19202,9229,2460,17556, +11810,6528,20169,19082,3473,20422,18433,4056,16108,13741, +17739,17751,1434,21092,14421,17816,21242,21249,21259,21253, +21293,21298,21299,21301,21304,21317,21329,21328,21330,21345, +21340,21349,21339,21362,21354,21356,21367,21368,21365,21385, +21373,21376,21399,21402,21413,21410,21409,21414,21446,21430, +21437,21438,21442,21427,21432,21480,21481,21489,21483,21501, +21491,21478,21553,21476,21536,21554,21537,21560,21567,21559, +21603,21582,21598,21574,21576,21610,21626,21638,21658,21660, +21661,21663,21668,21669,21673,21687,21681,21682,21683,21704, +21700,21714,21729,21723,21725,21737,21739,21754,21763,21764, +21773,21779,21766,21767,21777,23849,23850,23851,23852,23853, +12866,6246,17064,7055,6257,5909,6213,16924,16925,9888, +5946,4048,10251,12768,9563,3570,1394,14823,17309,4758, +21018,21024,18434,18435,2824,6691,16095,18964,18965,7337, +1068,6313,4323,2777,7355,8746,5066,8310,4842,16897, +1695,21184,7260,4692,16926,1858,16549,6554,3637,21600, +4696,19059,971,12303,11506,12266,5437,11508,19538,11382, +15005,6546,8747,6113,975,9506,11663,1425,19689,7261, +16033,10826,16927,19049,8332,2769,15429,6527,8484,1299, +20624,19863,4993,1942,5406,15591,18949,6006,16258,12432, +6893,4529,15390,5645,20242,20952,2817,6927,16768,5073, +11736,13984,12244,5322,2492,5276,11580,4342,5794,19576, +12420,1404,16107,18527,18539,20788,3641,17661,19206,8968, +19762,5197,15583,21221,7034,11534,11212,6933,12658,11087, +1806,14078,5526,20268,14336,3250,18312,8430,14942,18704, +18403,4538,12518,5745,8999,1571,20253,5586,19497,3501, +18883,16585,8008,8816,5766,8560,9118,6945,14219,16230, +8859,12385,8436,13064,6865,19019,8074,16322,13714,3874, +20491,9367,13976,18886,11451,13739,19654,12329,18155,16209, +16732,2260,2002,8640,21240,11843,8547,19434,18898,5413, +4419,21274,14659,1472,21509,4421,5776,12379,1572,10720, +3345,14502,8935,4634,15814,18811,2603,10873,6145,1346, +10424,10014,6777,5067,12371,21510,7298,17900,20278,7673, +5068,20174,7493,19246,18132,20717,14326,1696,1697,13408, +14327,2886,20176,21108,9174,20151,3055,2401,14275,15757, +12143,5343,17216,10735,7507,15213,5025,15461,3107,3108, +20993,6981,20515,4066,7955,11260,2972,20078,1255,20119, +9176,4795,2024,6998,14509,913,21334,5030,5460,14011, +20263,9889,19054,1135,2443,16301,21011,21392,1643,19998, +20308,3448,20159,18413,12589,14245,15896,16133,11672,5039, +7035,4415,19521,8851,8599,21161,18910,15765,2149,7649, +11867,11414,2717,18306,9599,13377,9551,19660,12452,19402, +14988,4787,12968,13961,12015,21412,14732,10637,16631,1416, +15680,5610,8774,8291,4710,18311,17528,7151,16346,21611, +10274,15519,1688,11938,2655,16889,8018,7496,7621,8158, +15919,17940,3386,15894,16104,14330,12852,21684,19976,3150, +3615,16818,18128,6267,5855,2242,8986,1219,12574,6206, +4899,4855,15103,14979,15952,18304,1819,5795,10869,17583, +10535,12546,1751,19308,10643,9399,1725,6406,9916,17230, +16303,19330,7964,5409,17225,20177,1540,4049,14772,18420, +18421,18003,10272,5151,20179,19855,1473,21105,4791,19995, +16865,15916,17039,2473,2482,17106,15507,21657,9606,14222, +13314,13224,17240,21495,8426,13225,2601,3002,2450,3847, +3604,17033,20400,8434,7068,2605,2783,5572,18045,15806, +4217,5130,15267,3137,16961,20555,15137,19192,8235,7508, +13630,2989,3187,10440,3491,13354,21522,15655,13456,2671, +6649,13111,13082,7727,20223,15706,4410,20148,16687,8677, +8427,2436,4549,19963,1099,12694,16183,18978,7490,10072, +10961,8825,3041,12830,21275,8201,15023,11106,21057,11297, +18241,7764,6273,14215,11967,8274,11620,5499,6066,3643, +20539,13427,18775,8898,9416,5588,7775,6680,14374,5440, +13542,20775,6851,17850,13120,5229,8911,16836,21640,21436, +16437,19585,14420,2226,15198,2419,7480,18044,18684,4314, +19728,17926,931,3687,21494,12378,11328,3466,15120,14658, +11122,20585,7428,20284,13097,8439,18397,20403,2457,7759, +7896,4977,16773,12844,8007,1155,3748,21768,1283,17700, +5054,20925,11767,21642,2919,12298,16349,6615,16445,16965, +5914,13307,8919,10791,16678,4540,1736,12249,1300,18670, +15815,12038,8306,11659,18816,7170,4238,4239,21177,13568, +21300,17356,2658,1383,20971,7280,1954,3294,8234,14753, +16008,2839,8063,11780,17432,1925,3222,11449,14754,7677, +13066,11051,7509,12727,16645,16473,7814,7080,11784,8208, +11785,10594,10441,9467,16286,13573,21677,13164,12651,3140, +21597,12238,20757,19636,4180,2973,19426,3712,20353,2442, +16156,15504,4940,21678,11951,2132,16073,13018,20441,3724, +15659,7089,10195,20156,1524,2692,10456,9890,15471,3358, +15153,17003,8997,7204,20861,13020,20862,12050,21601,9754, +20193,11733,16068,8242,17171,21052,3644,15349,7267,20915, +21163,8867,17019,6532,20057,9608,19333,5230,16837,4889, +12297,15404,18316,8375,18228,19160,20473,12514,14229,21651, +10098,4761,2771,6571,10724,13465,14311,6077,5306,11033, +17880,17541,15080,17610,8469,19177,12946,3475,2320,14919, +1581,1352,13396,1354,4301,4435,14769,6984,19377,6154, +16380,16673,5241,20698,8920,12330,18769,9587,12661,1156, +5100,10259,3749,10324,2379,3647,16136,11644,11456,988, +18194,3825,3951,8561,14177,14271,11601,5055,19138,2508, +14573,5820,18050,9924,19922,20840,957,18953,12300,11739, +1801,3148,8466,10022,15304,13083,13084,9852,4156,5634, +3303,1537,1538,8334,13137,4160,2746,7010,16767,19983, +11734,20864,9699,21021,2801,4107,16536,10252,10024,17179, +16538,9230,13682,17623,11811,15339,13500,7098,3155,21696, +17008,8990,8485,10025,3375,4660,15672,4218,5385,9291, +13735,10641,883,6982,8236,8781,8782,18338,10948,8634, +13458,10295,9366,4222,20863,18414,15674,3551,19279,19817, +2366,20336,5752,8493,19959,17665,3337,17924,4525,13760, +14185,8912,14742,16097,2420,3343,4315,11507,12695,10836, +13917,8913,12923,21319,6208,6336,12197,16027,14069,3338, +8822,3838,19108,9462,6312,5285,19881,10772,19369,9821, +2608,17651,12325,19076,2039,7604,11520,4068,12850,6939, +16246,17738,12761,17319,4861,18247,20009,4863,7132,9589, +4294,8280,12287,20879,13940,17268,2282,3060,13189,16779, +12965,12665,14172,1586,21246,8791,18851,11365,5102,12421, +10209,1077,11459,8179,13667,13281,2591,4874,10040,11748, +19204,10854,19285,13310,11243,14305,12967,18791,13694,1447, +3011,8255,15902,6725,21165,15852,13089,4888,13727,17723, +13546,6751,18086,11296,12799,7612,2679,7541,10652,19287, +13478,8936,3659,10073,3346,991,20688,4530,8907,18506, +12185,1322,5479,5480,12113,21276,13832,4324,1085,21120, +20895,18556,8683,18979,13256,14669,12488,4386,5401,8230, +7714,5684,10426,8572,13569,21106,20123,20972,14325,9848, +19768,14297,19485,6567,13641,20587,16285,4972,13260,21109, +11664,10082,20590,20459,9850,21518,6711,16333,2990,5869, +8609,18869,12216,12985,5808,11730,12493,5630,1333,10595, +12022,9825,13926,13847,7087,18485,17218,2876,3122,2944, +5297,19490,6215,14757,5028,21523,4941,16550,1360,20442, +19640,16551,8610,5492,20664,17108,12913,5324,7928,10719, +15231,6238,21141,8601,1401,14575,16633,19503,4260,10901, +19467,9620,15991,17148,4897,15172,19469,3621,17638,16267, +9275,19225,2953,7985,12693,16864,15028,7899,11532,12634, +1082,14741,2266,15812,19589,6539,1458,4910,16028,3424, +3201,18222,21664,3482,7335,16276,19292,5475,5965,12828, +4746,13765,17330,16359,2231,8568,12810,9006,16986,4322, +1246,12002,15858,10278,12028,17933,7251,20648,14533,13904, +11387,4361,1327,16621,6012,7066,9498,1212,7354,14910, +9309,19302,19755,15135,11007,3980,16990,9773,3135,10015, +19903,10457,7641,2351,21321,16529,6849,18033,20598,7728, +20465,1892,9355,4697,4470,9984,5302,14101,8613,6560, +18877,7093,21393,4392,19806,7533,6218,9405,12162,9700, +9703,10358,10026,3321,21095,9818,16546,3016,21726,1600, +9126,3025,18008,1182,1604,1607,1154,3034,1609,1610, +11872,11874,20695,2978,18729,13774,4513,14557,13897,2162, +5095,19546,18846,12617,20310,16338,16024,21396,3275,5997, +3276,4254,21031,2380,11694,2643,2409,21252,15559,16140, +13517,6726,3960,19533,11525,18793,7779,9923,18121,4168, +8089,19470,13386,3678,8045,18860,13479,8811,17917,9899, +6790,18134,8450,13932,21728,7079,11010,4493,12726,6265, +17608,6214,16370,19036,16626,15085,1517,6014,15365,13879, +18064,17254,5222,9523,6917,13488,6195,4506,11802,11079, +5393,18929,8916,9713,3265,18926,16840,20182,12111,19451, +9903,5049,5111,14700,10972,16036,2393,4955,1589,1022, +7776,7651,20091,18940,10605,8520,15760,18650,867,11504, +7110,5845,1116,8194,12545,9928,12921,5643,3841,20318, +18204,13238,19601,960,17932,1771,8970,19926,14747,4364, +2852,7346,14909,20431,11946,14044,10659,19239,20850,5974, +20610,16790,9719,15289,6729,5507,9158,1344,3256,8428, +1382,19476,21101,7935,19729,2984,15688,3289,19914,11945, +3485,15185,18326,2604,15643,14578,20640,19479,20066,4325, +5873,3293,16405,11551,18564,2762,18130,15319,3697,2606, +19915,15129,10690,5651,20481,14676,1935,2663,15138,4176, +3706,10285,2611,3230,13708,12888,17976,19777,18823,4338, +9873,14684,10736,6552,20408,15607,4409,1559,1562,9524, +19907,19493,10629,9573,15848,12757,14166,19560,13860,16260, +4814,8642,1684,17628,14411,19856,3214,6876,1191,8281, +1435,16210,8899,5703,14517,8818,20586,17542,10318,21750, +3151,5132,6598,12337,17718,21461,6868,21706,11576,18882, +15589,3326,14655,1895,2637,6931,8799,3502,9370,20309, +850,18528,4815,4950,18900,3314,9586,4292,1409,1123, +5818,13233,19180,20090,8543,17061,5581,10117,3920,11820, +4183,11582,19435,14925,8901,6943,14417,6681,3264,9910, +18784,17400,1442,2999,5673,6747,17758,18738,12025,8868, +4210,7137,11214,11052,20359,11868,5321,11412,10702,2555, +9320,5347,16709,20315,15274,20211,16839,21776,6946,4782, +20238,11943,11187,9954,21323,20528,15565,6332,3197,14146, +5053,6082,7036,6304,17702,16949,5718,11935,9289,18254, +2499,3995,10489,4958,16708,9272,7269,5346,1818,17024, +13518,17466,12627,13250,21096,21641,12465,9149,11651,19471, +1926,17322,8225,19380,13058,18742,10905,13963,1316,14743, +19672,20060,6311,8966,17325,17326,15059,15483,11301,16880, +13894,2835,21505,21647,18689,16691,17331,20019,13059,19367, +10874,2343,4840,9898,21306,6425,13062,10771,13063,17859, +3585,1529,18097,1502,20291,16409,20782,10882,9965,3384, +11013,18703,2046,8876,4755,11014,8939,9778,20154,2198, +19444,6999,18407,2206,20157,6522,19358,3419,1787,3901, +9268,9621,14832,2855,3837,3268,11550,9488,8969,7742, +19393,9001,8117,15060,19107,2652,7743,10276,8839,16639, +6762,13205,996,15121,4019,8730,11777,6072,2397,15262, +5284,855,11638,6020,3714,880,897,14908,5881,15890, +2566,12158,9460,2030,12411,12642,19238,1370,15082,3605, +11126,12188,8388,9863,12568,2856,7720,11960,13209,10317, +2082,3571,6013,7952,8453,18754,14004,12276,13875,1930, +6913,11565,16377,7396,11538,10575,6346,10031,19526,19664, +13251,19669,19897,16382,20910,12149,15515,2718,20239,5844, +16941,20162,9694,19586,18317,21721,10837,3376,4004,20636, +19871,4833,15711,12831,12507,2732,20129,2987,19540,19211, +12582,21727,5888,16412,10443,9242,18234,15575,20439,15418, +21388,17219,4021,15445,13412,2964,20079,4431,8698,15074, +2757,3234,20080,19431,986,20372,7599,12405,2244,19800, +9521,20194,18761,7601,15430,12509,11883,19069,18416,19070, +11745,13887,2747,18424,10104,11081,11082,11746,17673,7732, +14551,11084,18430,1587,14653,14692,9525,7875,5043,18856, +9897,3508,20527,3884,12504,13388,1081,20632,20839,1067, +10559,4961,11527,3807,14187,13116,16394,16658,10774,20514, +4934,4464,7027,12759,12853,12662,13426,18156,17267,1028, +2078,9189,1057,6413,8709,3921,7266,17785,3324,5427, +10852,11237,18914,3953,7703,18081,20732,9321,9145,15025, +18219,5548,17467,5824,8776,8417,13797,18606,16225,20122, +16399,19599,3237,10299,21498,10908,14503,15029,7114,20513, +9968,3588,1704,18831,3725,2636,4562,3128,18119,18466, +6307,9146,16981,2288,6622,18559,20756,7684,13499,14165, +13587,13368,964,5690,10683,11857,20039,17075,12106,4623, +13787,8869,14707,15230,1450,8369,9615,19584,17237,19143, +8806,2885,21551,4488,19590,16690,5966,5171,12696,10810, +13781,3688,15000,17028,18967,2147,14525,16022,16866,11918, +12871,13394,7481,12267,18653,19185,1092,4550,2423,17712, +3993,19967,12874,4837,1922,11509,17641,4265,8435,4172, +5418,19186,12925,1165,13989,13722,2336,11864,4662,20045, +18865,13202,12268,5827,6253,19156,8500,3809,18980,21043, +16987,5083,13782,6878,15380,8649,19877,10336,11639,16569, +4202,21515,11660,16003,14670,11257,5484,8689,10076,1752, +3020,5523,1837,12269,19757,15006,21762,1889,19483,3763, +7299,20649,14607,14671,15818,8307,15157,18740,5859,10610, +11656,14322,3131,11059,6361,2123,16451,16504,10911,11588, +20478,8061,8447,9871,17605,18063,6525,2877,6880,15233, +19161,20865,14554,15476,16094,17014,13753,19703,2641,18783, +17361,1786,19587,6844,2107,15068,11330,17768,7911,14030, +21331,11571,12328,16736,5743,12105,17759,17350,16170,929, +19670,1455,5338,999,7906,2191,17602,10000,19257,17626, +3504,3224,2251,16738,20904,11993,2677,16737,8579,2316, +2906,15016,1582,11854,6414,2821,12176,3279,18517,21771, +11645,4868,2330,18916,18778,15943,18213,2053,8562,18082, +12926,14535,15302,17994,20529,1269,6115,1489,14477,2784, +14583,1838,21279,2659,20096,12522,15918,12927,4925,20385, +10859,12879,4926,9645,19969,12270,18447,1180,1794,7803, +5420,14817,20753,11448,11683,11779,3698,7256,11473,15440, +14409,18866,14939,8937,8551,1296,15921,17713,6259,7678, +2633,4405,5315,1753,14587,11421,5877,19165,8506,21107, +2708,17365,15922,11389,9448,6972,19769,17908,13724,21753, +20984,14226,2664,16991,17714,13571,12271,15820,21181,6292, +11308,8854,18571,17157,17209,17770,8507,2108,9351,7073, +12334,13871,11101,18752,19120,5685,8722,20058,1309,15037, +12864,8953,9061,18939,15681,13532,13153,17727,4611,2308, +16323,2720,6333,3199,20064,9003,4320,9472,21377,13117, +1466,15125,12951,19371,8020,13100,2688,2844,10002,11041, +15741,6714,14842,18244,16385,6228,11267,8646,15315,10475, +9063,8115,9297,19730,2267,17029,16568,6834,4317,13520, +13617,6116,15731,13622,8618,21353,12035,12992,14874,12786, +14975,2136,4727,19859,11454,11163,4164,11108,5498,1585, +16600,6010,16383,9376,5101,14798,10208,10326,18441,14985, +4227,10038,10853,10648,17980,12057,16138,6230,11269,7970, +963,3917,19512,14087,8662,12931,14947,11640,3812,5979, +13947,14678,8765,13411,17437,20591,17797,20187,15627,3261, +5575,6279,19375,4009,10504,10925,9292,16298,17646,20030, +1334,15144,19778,2189,15882,1850,5980,7282,6263,8347, +4756,2170,16287,20995,14957,8348,6468,19685,15784,8938, +21458,10568,17715,13230,14452,5939,10569,18654,2790,20305, +8209,17303,4271,10814,12570,9512,12067,13948,2532,5239, +9565,15596,1733,21286,20718,15979,10183,21732,8328,2315, +19847,7369,5177,3817,15577,2298,10597,8737,10087,12277, +10447,9518,13017,12144,8362,11261,6534,16432,9921,7238, +20621,19092,6724,21164,7141,17873,6748,15561,18083,7586, +10124,6392,18084,13899,15108,16713,9147,16392,21434,8342, +2080,1190,16848,10940,6577,21228,12689,16857,15027,4026, +21416,12342,14482,5143,4601,3099,14423,5644,10407,14846, +17587,18224,11174,7664,15064,6625,17892,12169,7338,17990, +16660,10909,18389,13207,8732,14351,10821,19301,12599,9642, +13902,15301,6858,1477,17791,4969,15487,12077,11303,6632, +19303,17430,9240,2032,6340,10660,6594,9798,21179,18750, +10430,17967,5129,14822,14953,14196,14320,15925,2193,9175, +21733,12219,977,12278,17307,18149,21369,9452,854,8783, +15330,9054,4034,16521,2928,21524,20759,1348,11791,21636, +2965,15422,3910,12729,12936,21389,6991,19785,7914,5632, +10845,2273,15758,16918,9802,15578,5559,3262,14826,20663, +10448,11040,10449,6452,1659,5046,9164,8749,4551,16762, +11537,16300,6399,3563,17164,17165,6866,9851,4451,10981, +8575,18450,3609,9804,5835,17255,4081,16011,16414,16288, +5031,13848,7090,4348,8510,20665,15660,20344,6435,18486, +4105,17109,19641,8766,14479,6646,16479,5032,20532,2112, +13167,14545,6217,8983,11953,13078,15179,9567,3440,20406, +9743,13878,12585,1522,6030,21464,5990,17616,19322,19978, +4719,6061,1107,11143,5740,3477,11110,19528,2411,11846, +12880,12883,16804,9865,12889,6549,7441,7440,2977,18191, +16739,8086,20235,18782,4397,7235,8035,3328,6309,12082, +1886,9557,13387,17410,15683,13640,8965,16347,6583,10410, +2870,6627,13401,17094,1003,5453,15320,10137,17159,9971, +8327,17609,11205,15222,9110,7121,6759,16053,20957,8651, +20883,6948,4250,2176,16988,8319,2257,8033,11909,11090, +4909,1464,19811,2377,14901,4577,18246,16735,19701,1410, +13079,6297,15951,21624,6555,18714,11263,7523,4089,7516, +14960,8984,6381,17949,20606,7821,20666,1560,21050,21527, +17773,18655,10949,12029,865,5072,12938,10928,2113,3302, +1218,17111,9756,15284,8587,18584,18718,11898,16614,13825, +15510,15285,13021,5300,14916,2929,1863,12051,3273,1397, +14048,5178,21528,16699,19260,6677,15790,10162,8576,15250, +14138,15075,16302,5225,20722,20723,9293,19055,19905,15523, +11796,16968,7262,5266,10694,8350,15056,21691,15286,15287, +4759,16553,11489,10388,15288,11982,21680,16047,17777,5656, +18002,9805,14721,10766,11405,10623,7921,21540,5700,11850, +19563,14980,3278,21118,14174,13145,18195,13703,14730,9784, +7608,12424,2141,9554,12448,16195,17193,15255,3676,16433, +4281,8047,1655,7786,2263,1454,2174,11911,1024,19925, +15854,16794,5449,11329,12345,899,12434,2567,9500,18229, +13027,12412,2295,9389,20474,16902,14233,1512,11757,10674, +14853,5047,5042,4859,11903,21497,7761,8395,1222,20180, +14987,4988,21639,18924,11904,15343,17402,6457,12366,9483, +12697,8728,21366,1966,20962,16799,1036,10139,14227,1627, +3075,20460,7215,17339,14920,19544,21130,5243,16245,8921, +1534,16530,10165,3611,14036,21625,18838,10462,8767,13022, +3183,12656,2303,15472,10788,19385,2246,4760,8071,1644, +14827,10315,17801,3090,10234,20160,7530,2038,9529,17131, +16935,8635,14869,1388,20487,12897,2488,10467,6470,7094, +12591,6820,13023,12510,9987,14102,17802,17315,2489,9025, +14965,10167,11598,6651,12422,15226,4507,13112,13538,18489, +15473,17392,8471,7642,21744,9892,13169,9336,4139,17656, +20136,7007,7452,21053,3593,18153,19347,4118,8472,11899, +15705,12610,15822,15823,20499,3893,14246,8558,7453,4644, +15228,10390,8352,6823,19807,9762,20008,12248,14725,5140, +17567,4872,21135,4873,2823,3327,8834,6001,7587,5351, +17408,15631,10062,12774,4584,14283,5797,4215,14712,10178, +13593,16274,21493,8729,17329,15641,11201,6766,14935,1597, +5417,21379,11252,7937,20690,13903,5214,9496,18989,7353, +1692,12388,10778,9390,11322,14057,17545,9872,20294,7553, +12958,13076,6551,21699,18526,6977,2858,20111,19363,3877, +6937,16431,4653,11242,8408,8672,10212,3753,3334,12530, +11244,7239,4402,5400,17813,18160,6187,18549,10655,16980, +6690,9767,12703,19234,12702,6395,9040,18325,3100,16279, +21468,13085,12901,21472,9404,1541,15824,6562,17553,4207, +5871,2491,8337,4698,3304,19073,921,21609,18136,3819, +21292,6196,21394,7016,11691,6135,6924,13263,1710,19275, +9027,11838,17842,7534,7535,12961,2134,21023,11231,9541, +9407,7018,21695,8949,14276,12230,9139,4052,14918,2997, +10529,1652,1281,10391,17226,8888,10253,4356,10359,7536, +9232,1872,7394,18640,2218,17345,7537,16947,5664,2023, +11812,9438,3156,13502,12070,10633,21697,10553,20196,11814, +8486,15529,21220,9233,13985,18463,17706,1265,17711,10811, +18146,20953,17150,19675,12711,2272,2396,8198,10879,19615, +19927,17097,11610,904,15493,7913,6636,19248,3186,3081, +17969,20484,12584,1997,13484,10450,1528,20161,16609,16463, +20070,15549,16778,1613,12764,2098,10698,9593,12289,11196, +18594,13941,7398,2802,2497,3062,17397,4543,12003,21248, +11530,20922,20608,10211,8148,12468,10328,17078,17401,19462, +20886,16180,20799,10043,5430,3652,9601,16142,2464,8658, +9346,18143,13696,20930,20627,5678,12625,15873,9082,8151, +6479,6185,6755,7781,10533,8368,927,17852,4526,5549, +4900,8420,21550,15259,10057,2806,4679,4027,12974,20547, +20973,19237,6634,21516,1851,15522,13815,1386,10153,6556, +9136,2215,2283,2284,8140,1025,3852,8457,9901,11080, +10975,10700,14844,14209,6889,10976,18265,1460,5967,1461, +14188,8557,8650,1367,6254,13953,14039,17204,7492,7344, +11278,17066,14877,4006,20342,11616,20402,12186,17115,10077, +1599,1490,13954,6119,5615,5291,5260,4445,2840,6275, +5721,11282,14113,9073,9304,10477,15862,14156,8237,19970, +19971,2239,13523,10019,2274,14137,9074,18235,16578,18280, +4346,6841,19786,16579,6280,1231,6281,13525,18611,16581, +1168,944,16415,19129,9095,13632,10614,2923,9817,5862, +7484,3690,8197,3119,14448,11553,20321,9795,9239,7065, +12444,8260,13347,4096,2925,2451,10476,2125,8259,17993, +10914,19300,20651,4614,15322,15247,17594,5196,3178,5216, +14912,1693,13808,21178,17593,7912,13029,12645,2768,15496, +21182,6370,5131,19973,13279,16159,8455,13103,13214,10381, +21740,16907,8238,19898,9394,18282,10005,1879,2130,19482, +1001,11363,3129,14254,15742,20043,9788,12402,3379,7059, +1714,19028,13751,4298,5468,8675,10330,20889,18936,20677, +6330,9607,18546,14648,20936,13549,10402,20580,11726,16329, +9210,4022,13576,12241,15738,11797,15335,8577,6129,13634, +2904,5619,4012,12782,8959,15512,5621,12401,8621,17058, +6821,2247,12283,3499,6561,15337,16583,16584,5952,8563, +4018,6768,15321,6548,9368,17659,18890,20900,19087,18454, +3986,4291,14456,12134,5157,20036,20871,12286,2461,4295, +13428,3645,10110,16135,1737,4228,14729,4229,4374,5747, +19548,8517,13121,17707,2949,4997,17081,14208,14469,12564, +20703,17276,3514,12136,18950,4127,10581,19100,8189,2415, +10403,14471,17239,19105,21227,18473,13777,17091,2696,18378, +19106,19591,3602,16348,11774,4128,2986,21504,3121,10442, +9976,16496,7315,12993,7273,7113,7056,8595,3581,5084, +7431,20175,11970,10045,1921,1385,20306,12353,12556,5038, +9111,5136,6037,15401,5210,20272,17633,20010,5770,6084, +20140,10855,19707,2307,11695,12679,14495,18678,2339,18370, +6688,1888,5927,5757,17935,8974,903,11306,16089,18065, +18630,16938,11575,1341,14641,8928,18792,20935,21488,5060, +7933,20710,9170,13393,6962,15454,5020,2163,7149,16953, +3624,19618,5457,7950,13521,7466,7597,12446,10832,5503, +16749,5550,6959,8305,7340,12362,8661,13151,15258,1110, +959,7741,5064,18327,6697,20046,16797,15489,7171,3523, +995,17040,19188,13991,13704,9966,16060,3586,12314,15187, +19770,17250,4683,11687,4388,6992,3528,19195,20999,10262, +16936,9658,9665,6141,20812,18968,13203,12875,6543,5454, +8379,6341,20103,19629,2737,15181,5989,6909,14852,5655, +2797,20106,19384,7002,16929,10197,9526,11556,18027,20108, +7099,7100,11492,4810,14081,11466,4663,12076,20020,2660, +18448,953,11006,3764,3486,6337,3813,11478,2429,20343, +10083,12653,21110,6266,20409,19125,21290,16101,10088,3973, +19252,16810,10094,10095,6268,19130,5288,1878,10868,11430, +3202,7485,14018,14748,2314,10473,12604,13494,12415,3506, +17140,2860,3925,18199,19099,8727,20022,12557,2649,7669, +4028,3851,19514,19862,5854,19945,16652,13785,6606,8013, +13913,15374,5373,21397,11498,18542,12948,10213,3959,8549, +10329,7290,14439,21140,21775,5566,20676,13467,20804,8038, +5681,3963,18217,8870,13987,5885,12367,20706,11095,16096, +10611,3247,12101,16275,11759,7988,18225,4603,19607,21584, +3904,7487,3120,11561,11177,16217,4331,14816,2525,19352, +5290,10501,1715,15606,20991,20371,5534,11020,14059,14201, +10737,10738,20051,10196,11049,1707,16812,16531,9099,16969, +19060,3449,15620,19808,10235,3360,7095,12079,18491,16420, +16421,17059,7222,11050,11029,9408,9706,6925,890,4645, +3363,10254,10105,923,4765,9708,1259,6160,6161,6163, +1774,13244,15712,20650,2476,13296,8066,8069,15714,4588, +11180,1271,15759,6824,18721,3885,2124,7345,13766,3625, +4077,16798,13767,13208,11865,19189,13981,11512,11390,21690, +1181,19004,18625,15574,1133,7754,6260,12114,1754,19123, +5293,15576,7081,940,6171,5402,12832,15842,19354,15180, +15785,17998,8788,1379,15334,20498,9753,10018,19566,16856, +18746,14151,17644,16909,1616,13986,8308,15069,1634,1635, +14723,5450,5483,6380,4612,6983,9203,19569,12152,10834, +20393,7981,11680,10134,18868,18458,16430,4165,13050,14569, +6329,21258,17982,15353,18680,18470,16792,5930,10984,2334, +18383,6365,19751,16364,4097,1227,17936,1552,16077,10120, +10781,14265,20072,19010,19782,4495,15215,17256,8474,3169, +1612,3536,17897,16911,9592,6415,8077,6422,4586,14611, +14982,17142,20881,13436,6418,4886,21774,11056,20800,3010, +20631,15769,12704,2179,17037,21454,16997,13679,15588,15434, +1525,9096,9140,17615,1196,4365,13357,13358,6130,13136, +11480,7371,3610,11966,15555,15336,17551,12052,5303,1535, +9100,15474,10297,5791,13113,18009,7011,7390,7563,2258, +3305,6440,17263,12905,4053,16220,7395,9234,16390,13768, +4933,10965,13602,5294,16474,13133,5940,2327,9097,13856, +20083,14356,16482,5301,1136,15556,5426,20084,5205,1536, +16485,6825,4050,16221,4054,4890,8141,17160,17600,17168, +7004,20102,9381,12220,6650,19258,20086,12226,949,19131, +17372,6441,18676,3888,13285,8967,17384,14890,5907,17822, +18817,17825,5557,15053,8995,12712,4126,7271,6753,11920, +13757,18519,21565,13612,12877,11279,15595,12819,4132,10884, +10988,5185,11762,19698,3280,18018,11199,6940,5139,3478, +17809,2368,4167,18197,21431,1547,4734,4450,894,9617, +10215,20349,15907,3654,9112,16143,4896,17709,10809,17087, +13057,20387,3966,11586,5312,16662,12811,4129,1325,3905, +2438,21121,7807,3703,17995,1574,20589,5806,14045,13298, +13481,4154,3590,7560,1933,11024,1871,8592,20896,4946, +4976,17807,11167,8792,4158,11197,3369,14491,19829,18799, +15174,21569,2561,11419,9171,7417,3691,15261,18169,11706, +6009,19758,16259,1148,4174,3631,3385,12066,12538,10113, +2386,8065,9449,6123,13070,4339,4272,16475,7815,9091, +14427,18828,18829,8697,4116,1603,12457,9450,15808,7283, +15957,6800,8980,7284,10606,15883,2483,19344,19996,6379, +5985,8028,16062,16063,12436,9177,16064,21529,21530,2930, +3912,9178,15424,5986,12891,8699,3212,8103,13184,18833, +14006,15663,4275,4351,18283,16608,8611,19395,21315,18284, +17257,17672,18876,19934,14049,3726,3727,7579,8960,9456, +9337,12407,16227,10740,3149,18588,6062,13114,5562,18135, +18352,6827,2259,13888,11031,1711,15177,12348,13946,15083, +8978,10880,8694,11310,12403,2481,8619,9978,5538,15835, +1439,13591,15719,4523,20678,14324,16281,16052,4887,5168, +5505,9636,18330,12311,9241,9517,6997,20300,6095,5653, +8353,7872,5041,18847,12499,20520,9896,16021,2884,14176, +10974,2146,11916,1913,15375,8289,1162,12914,4545,8648, +3989,6877,1091,19716,20738,5508,8678,12520,1887,1824, +19960,11463,15437,3754,14904,14650,17986,15298,1453,11652, +12262,4194,8660,9349,4403,19507,2516,7275,11587,18651, +2470,3808,19104,8564,21173,15877,3915,6459,13556,5876, +17264,12442,10360,10008,11813,13586,15879,8094,12541,19337, +19394,9455,4735,3916,5571,4927,17069,20437,1626,13993, +1086,15360,9939,5576,17999,14300,8330,1637,14963,16483, +18488,18586,15077,8578,14061,4471,10166,16971,10198,12396, +12397,10169,1647,1648,1649,9894,1650,14104,4766,17778, +18464,20425,14940,18572,10142,4579,4473,4599,14565,1965, +6951,3900,14997,16128,20397,16098,13769,19746,8382,2654, +19190,4531,4532,15237,19187,21280,18819,21782,1491,7834, +15550,1248,3026,15828,15007,1249,14672,4241,5895,13771, +15755,7679,7281,1755,18573,15923,14128,15803,20746,14080, +2706,15463,958,13867,9325,9162,15594,8762,20304,9560, +5234,4266,3258,10564,10179,8556,7421,9285,13227,8202, +853,13008,11947,1347,3559,8733,9043,5556,6864,12140, +8360,15411,21512,13161,8574,14948,4335,2109,15071,6547, +864,10312,13015,4636,10923,11397,5292,8349,11488,10147, +19015,7258,1698,1633,15470,10784,10619,19381,21679,17997, +3607,2199,8460,12588,10383,4135,9209,12607,3152,13019, +3591,6912,21467,19056,2133,1646,21046,14418,3241,20974, +1415,21546,11374,14765,10495,6956,4835,9284,8687,13733, +3027,17366,18510,8385,4406,9387,16898,1799,11629,4341, +1891,8535,4010,15145,19630,16905,18580,6847,5870,14685, +7517,21390,1756,17308,1928,18709,3442,4594,20485,16522, +5633,4347,11931,20081,6382,6647,6807,7372,6298,914, +15509,4665,16526,5535,2114,15055,15511,1864,5203,17055, +9021,10163,15076,15581,18719,16554,11344,15513,10752,1530, +19803,17776,7916,14037,9026,21336,14247,2672,3450,19071, +7008,13700,2490,16534,17373,20416,4666,5899,11030,18425, +11351,2219,17374,10634,20170,11573,3896,16112,4230,6090, +9386,16838,3999,8523,5861,5520,20691,7184,14094,11721, +5035,13681,5704,7659,6048,16886,12515,3831,6423,19398, +8112,19824,1241,20704,5472,3927,10332,13472,2559,14931, +4383,20954,5567,17765,10534,1833,9491,5521,19748,17205, +15644,16755,11192,937,1291,2960,6369,4336,3023,10924, +16807,18627,7365,19254,20615,10194,9882,7638,8164,19794, +6437,10459,5662,11619,3879,7734,9595,14217,9602,19463, +5105,8676,3401,20365,12120,21260,17961,7243,18179,18803, +20960,9324,16796,3239,17202,14129,21206,4635,5554,16460, +19681,19555,3380,9123,19000,6290,2159,10311,7302,14070, +18693,1839,4682,1847,11684,1503,1854,16010,5911,4595, +7373,945,918,17170,19997,4699,12428,17653,10687,19747, +4774,5973,3699,16153,16129,2607,18096,21281,20822,12159, +17670,13783,13992,20049,16573,20851,3405,10478,19486,1848, +1251,8440,16155,19005,13448,12567,13452,8080,12523,20530, +19846,12189,21151,8316,21287,11906,8210,12274,20181,7313, +10084,20692,15346,5026,18511,14608,1509,16157,16158,15009, +10148,10709,12375,15579,21000,13820,15610,3972,18060,13536, +14401,8081,4407,5896,1855,21185,19126,10663,21111,3443, +5897,10156,8240,15046,13185,10815,2666,11394,1149,7076, +6640,1632,10642,19342,20390,10225,19194,2712,1153,9179, +19051,3771,12339,3728,13497,18959,15040,16830,13309,21398, +1570,18602,15797,4007,8688,19621,18055,8314,19684,18730, +2131,11500,13756,7880,10956,12063,3453,7248,5252,8752, +9722,2524,9769,7419,1656,2809,15693,1486,8203,4190, +3269,1330,1250,10503,1576,9201,2634,20605,13048,13883, +12069,18173,17810,8498,3216,7877,9415,21547,2362,14999, +6863,9359,15520,11990,10288,7576,11895,11410,3844,3882, +3374,10065,11824,5826,9015,1010,15408,5903,12684,6005, +9294,5987,16012,17950,16081,8538,4284,2549,17693,15012, +10458,21370,21116,14357,12376,9057,15582,9165,21602,8739, +12738,12739,18408,4596,14062,18409,5304,18612,16815,12383, +3091,12384,12942,4597,6652,12940,6869,19648,15666,13537, +17113,21604,8985,13851,14964,5578,16163,5735,15078,12900, +2541,21015,10168,12228,15614,16972,2044,4045,18417,19908, +21655,14063,14248,12751,21019,14856,10468,16973,10626,20488, +11407,1046,1973,1651,3092,13461,1542,21020,19810,17841, +6471,1802,15154,17462,9989,20467,4157,10172,16165,2087, +3773,7643,15825,18426,10635,20418,7794,6109,19336,8684, +5972,4340,21311,11792,10739,14047,6060,13886,12441,6320, +12916,13374,7107,2156,6686,5310,10996,4898,12296,13942, +17238,6017,7856,5377,3991,19182,2558,5905,5476,6104, +9629,19474,13657,20366,13344,10068,2469,19536,13320,7277, +11589,20961,14936,13444,15859,9087,12705,7619,18477,10839, +14450,20562,14296,16721,9499,2782,4923,13007,13259,12722, +16895,19767,4591,5867,5834,19003,12313,15783,13570,16236, +9290,11039,2942,13813,11562,4936,8979,8696,5024,15073, +19627,19488,10289,13410,1557,10843,13217,1011,10763,10822, +8003,19078,18722,16131,12429,21158,18431,10255,10485,15619, +17346,7226,14862,8249,16976,6529,9544,1653,13779,19096, +1617,17678,13176,21577,15116,8972,14854,16446,16454,16455, +19609,5146,18981,980,1272,1332,3005,15673,13071,8858, +16074,5357,12373,19644,15191,1867,17455,12096,1868,3235, +11348,9893,10298,17459,20178,15675,1723,8889,10361,5192, +13128,8652,13118,9338,14073,9041,3627,4573,17771,13659, +3435,9050,1716,4429,12275,4455,15697,1274,1510,10844, +4937,4389,13821,13454,5389,9092,12221,21297,14301,15271, +15700,9666,1718,15703,12224,15035,10680,19901,16916,2574, +15503,12087,14687,6645,2037,12394,15506,16923,17391,21049, +20486,14840,10846,12223,6813,12049,14242,6918,11042,2205, +9759,11229,9536,4083,13501,4805,19244,13301,17129,14647, +21197,19577,7044,4059,6950,7405,20544,21549,6419,13313, +12521,3288,14472,20240,5434,9625,14998,15778,7245,1548, +2562,8808,1470,17241,18269,13559,20749,8502,14666,5183, +12008,14294,17474,13295,20248,13159,21283,13970,12930,16185, +1498,3382,8780,19843,17431,20658,9014,6637,6293,5423, +4618,9657,1514,2612,15150,11227,3982,10451,4104,5763, +20760,21605,14896,7447,4223,6384,9133,12750,9761,20696, +12229,10711,14023,10754,10755,14112,17843,9947,12902,12903, +11570,9101,11839,1724,13683,4000,4008,11617,6282,17056, +4014,5947,4015,4016,8125,19818,19819,18404,4974,17655, +5734,21606,10199,5737,14269,10962,12713,12714,5050,17829, +19793,16065,12655,9838,5117,12398,1539,12752,17840,2759, +18356,20419,19594,3510,13723,7804,1070,6261,16130,3632, +7116,19631,4274,13162,14135,5994,16100,11398,7866,14428, +1167,19896,12315,10379,16574,6375,10338,20097,4559,4687, +11513,19489,12382,11337,6127,17107,3772,20134,3576,1876, +9183,21155,19571,19578,2683,17032,11770,11922,2865,14181, +18854,1420,21040,1164,4571,5307,10334,21205,20241,16879, +14295,16462,11038,14704,2036,2691,11026,13175,11750,7247, +13405,14132,1532,3601,13042,15263,7812,15467,16915,17146, +11092,1063,9627,15802,16876,21502,1992,9964,21632,14028, +6294,20133,3024,17860,13844,13420,7600,5323,7173,18934, +10064,16877,21284,4615,7434,12364,6125,19046,11107,20846, +12718,12778,18581,3553,4834,13459,8114,8200,9937,21511, +20147,11557,20604,7544,2628,3883,5106,21144,18802,5482, +13455,5912,12279,10089,16160,1102,13413,12495,4942,1520, +7201,16523,8211,3791,1856,19491,5810,12317,11718,17690, +15362,1276,5029,20354,8321,5490,14590,3936,3352,15309, +7822,14759,6316,17370,4390,946,16416,20558,21186,19216, +9941,10664,15935,18834,19050,1773,16480,7636,8828,5730, +17169,5298,6734,9354,4945,8665,17774,4206,8511,15664, +11179,14302,20355,15272,13186,19645,11630,20597,5811,5358, +15096,16725,13415,14202,12572,6602,15789,9569,14139,14140, +8666,11025,2538,9527,21659,16930,19427,14403,21531,12742, +13262,17371,11631,2966,7216,3795,3133,16151,17152,11317, +20897,18395,14537,2531,16009,9447,9053,12133,6378,15657, +17861,5889,15508,9335,1893,7729,16934,8335,9571,18073, +14598,3244,4159,13304,18021,3145,1679,1264,15297,7412, +4832,13000,20847,4836,14189,9637,16150,7253,1874,15356, +8994,13061,1487,17247,17151,6967,7620,9823,7180,2975, +6503,2610,20994,3743,1849,20855,7510,3861,2857,21066, +8266,4205,3233,12374,13846,11793,12047,12654,2799,8465, +12609,4503,3147,21210,10023,2214,9946,21694,17625,20906, +3785,11388,17767,11402,12320,6354,8424,14257,5478,21508, +13168,5561,21129,3938,9166,4598,11667,19061,9058,10463, +8165,2276,7998,10598,10099,21653,9530,11043,21607,21016, +11722,6400,19649,3662,14546,14405,6603,15667,6299,17695, +21193,9137,21608,7205,1564,1565,6604,13581,20281,16375, +16376,19650,2946,13852,3865,6653,9807,18344,13360,13361, +7448,1399,4353,18490,5036,14007,7383,17072,16178,6385, +14693,13973,17957,16555,7387,6063,16700,12091,14064,10170, +10696,14594,14547,5622,21534,15616,15312,18589,5305,19396, +12945,12753,16556,13974,14410,9763,1017,9385,6716,11290, +7223,15792,13462,7391,14406,10756,5384,15136,20992,21555, +13289,8057,19593,9638,16570,15863,7181,12161,4592,14157, +19173,889,17316,10717,2448,8262,1228,15781,21517,19166, +19686,2991,16670,11164,19878,16164,21364,15244,8371,8204, +10662,8331,2743,13305,10537,16808,20153,11424,1045,10161, +1338,17652,19480,4558,1100,12489,11717,10337,15093,5017, +6314,15357,5722,7810,16468,4387,7182,7624,17367,18098, +5356,9513,9742,7363,14589,15787,5809,14136,6597,7186, +13261,10090,21652,4593,9055,2275,5560,11666,11719,3792, +14543,21526,4718,3862,4349,13355,5033,6648,1561,14060, +16975,13418,1664,7224,7220,21211,7564,13363,21316,19390, +20489,8636,18035,1667,19813,13463,17393,1803,7700,18109, +15155,6654,21746,14251,14252,4474,5792,9991,18110,11195, +17005,20303,17344,4720,5624,6317,8883,20282,14065,20420, +5135,5793,14489,9574,2304,9410,14791,922,13889,7225, +17916,6442,14793,9707,9949,10668,11232,20668,17375,4358, +10362,5666,9545,17181,3509,7111,16099,1069,6117,19484, +20351,1840,12310,8663,15924,20279,6315,8873,20352,8508, +19425,12730,14402,1396,2302,15661,16552,16372,13577,7558, +12088,7377,16532,16970,6439,5134,1015,12740,15310,5620, +18585,9384,1663,18034,10753,11288,19386,5790,14249,21745, +9572,3296,18449,3298,13102,10751,7376,8214,13849,5425, +1337,7862,15955,8827,5493,3661,6296,5295,8700,1526, +10296,12841,8887,1721,4051,10966,1087,18336,9837,17442, +16335,2578,17363,18398,15829,15557,19389,1618,9044,10842, +13661,15786,7194,21525,17772,13578,8124,1722,6563,9948, +11335,6712,11068,7115,8509,21235,11070,12745,1016,14361, +9990,3356,2849,19516,17112,18762,13460,4046,9532,13280, +1989,978,4693,19542,16726,18357,16943,13414,5913,20330, +20417,5635,11751,18867,4928,9646,8121,1900,18390,4891, +3787,6968,4792,13905,5114,14538,4793,11309,1252,19844, +20823,6433,13212,4845,4688,16575,7364,14541,19779,4811, +18537,8451,8452,12336,6519,20721,1254,18399,18148,20784, +4552,4794,16576,11978,3353,5261,13874,10091,11223,4938, +16161,11262,9659,1578,21001,5262,19848,3031,13483,17443, +2575,3444,8212,18610,5491,21048,19787,18451,19788,18150, +15821,19789,15736,19253,4117,16698,4391,5577,915,20825, +18406,6193,17450,7285,9942,21187,18487,15662,6269,10453, +13880,11425,5265,13725,7637,17775,22349,22350,22351,22352, +22353,22354,22355,22356,22357,22358,22359,22360,22361,22362, +22363,22364,22365,22366,22367,22368,22369,22370,22371,22372, +22373,22374,22375,22376,22377,22378,22379,22380,22381,22382, +22383,22384,22385,22386,22387,22388,22389,22390,22391,22392, +22393,22394,22395,22396,22397,22398,22399,22400,22401,22402, +22403,22404,22405,22406,22407,22408,22409,22410,22411,22412, +22413,22414,22415,22416,22417,22418,22419,22420,22421,22422, +22423,22424,22425,22426,22427,22428,22429,22430,22431,22432, +22433,22434,22435,22436,22437,22438,22439,22440,22441,22442, +21115,2576,10665,6194,11720,4285,10538,7286,7206,16013, +6521,16177,1902,16724,8351,19801,1865,8539,8540,1398, +16931,8541,8241,15980,7997,15665,4276,4277,8915,5539, +16766,14404,9180,7693,12068,10464,12323,14763,4948,948, +21469,12227,13416,12898,1293,3796,10465,13635,7381,8243, +16029,18152,19850,12743,9531,18720,21371,8784,4246,9059, +14481,12744,7999,19062,19063,8000,21532,9167,3939,12657, +2967,5345,8215,8467,19064,21743,7005,14828,14829,2673, +11194,13853,950,13362,15668,6386,15669,4354,7758,10847, +4949,2947,16014,18345,6133,19909,22443,22444,22445,22446, +22447,22448,22449,22450,22451,22452,22453,22454,22455,22456, +22457,22458,22459,22460,22461,22462,22463,22464,22465,22466, +22467,22468,22469,22470,22471,22472,22473,22474,22475,22476, +22477,22478,22479,22480,22481,22482,22483,22484,22485,22486, +22487,22488,22489,22490,22491,22492,22493,22494,22495,22496, +22497,22498,22499,22500,22501,22502,22503,22504,22505,22506, +22507,22508,22509,22510,22511,22512,22513,22514,22515,22516, +22517,22518,22519,22520,22521,22522,22523,22524,22525,22526, +22527,22528,22529,22530,22531,22532,22533,22534,22535,22536, +12365,9060,10932,6387,19262,2887,16816,8246,3940,2018, +4574,6388,19274,19910,17177,16615,14548,6158,2800,15514, +17114,13975,10171,7096,5494,7388,15251,5992,3035,3036, +19074,18638,18418,7012,9695,15739,8814,15628,15629,19075, +16015,10695,17460,5206,15740,2435,7097,16049,20617,1018, +18614,18764,11983,2674,21022,10200,19391,10484,1543,14859, +21474,19651,16727,8480,19176,15433,14966,7644,19079,6472, +1544,19278,15156,6655,4509,7645,9895,18427,5208,8169, +17227,17228,16016,10723,21747,19814,19280,10472,16050,17229, +18028,19081,12356,14792,10631,16945,22537,22538,22539,22540, +22541,22542,22543,22544,22545,22546,22547,22548,22549,22550, +22551,22552,22553,22554,22555,22556,22557,22558,22559,22560, +22561,22562,22563,22564,22565,22566,22567,22568,22569,22570, +22571,22572,22573,22574,22575,22576,22577,22578,22579,22580, +22581,22582,22583,22584,22585,22586,22587,22588,22589,22590, +22591,22592,22593,22594,22595,22596,22597,22598,22599,22600, +22601,22602,22603,22604,22605,22606,22607,22608,22609,22610, +22611,22612,22613,22614,22615,22616,22617,22618,22619,22620, +22621,22622,22623,22624,22625,22626,22627,22628,22629,22630, +18842,7021,20267,19652,20421,18723,18492,12357,11840,6443, +11083,19281,11032,3640,19985,19815,9439,1903,10363,6162, +10256,14863,19988,19282,5665,13503,9546,10556,14518,2005, +17411,10053,18020,6189,21102,16718,9045,12881,5339,19842, +15130,6120,13349,19016,16612,10149,7082,19017,18757,6557, +20413,11027,14860,10370,7892,10092,7449,17223,3245,7454, +7457,18298,19440,3125,1631,3126,12116,21291,7374,11069, +19691,10164,2433,8512,9983,11668,8166,8513,8001,9682, +17340,18290,7263,11074,9696,20490,8004,12755,10108,18299, +3127,10732,6121,2358,4846,11183,22631,22632,22633,22634, +22635,22636,22637,22638,22639,22640,22641,22642,22643,22644, +22645,22646,22647,22648,22649,22650,22651,22652,22653,22654, +22655,22656,22657,22658,22659,22660,22661,22662,22663,22664, +22665,22666,22667,22668,22669,22670,22671,22672,22673,22674, +22675,22676,22677,22678,22679,22680,22681,22682,22683,22684, +22685,22686,22687,22688,22689,22690,22691,22692,22693,22694, +22695,22696,22697,22698,22699,22700,22701,22702,22703,22704, +22705,22706,22707,22708,22709,22710,22711,22712,22713,22714, +22715,22716,22717,22718,22719,22720,22721,22722,22723,22724, +11184,4848,12124,13524,13457,11426,4849,17310,9168,11186, +2581,4767,13453,11185,11334,11354,21654,11933,4700,6616, +7893,5686,15713,15963,6494,8941,6270,2583,6164,19018, +3408,17051,16090,11399,12939,3744,18341,10950,18346,19980, +3469,18240,18350,18351,20724,20697,3362,1990,18765,10934, +20444,18359,4055,10364,4703,11281,19904,3146,13528,2352, +16206,21192,20828,11044,1019,1668,16166,1545,2344,11133, +3891,21519,5525,3937,4695,19852,2277,5207,2048,19853, +15475,15599,14778,4641,16582,1089,3794,16162,21051,13487, +14480,14591,14593,15867,8247,8002,22725,22726,22727,22728, +22729,22730,22731,22732,22733,22734,22735,22736,22737,22738, +22739,22740,22741,22742,22743,22744,22745,22746,22747,22748, +22749,22750,22751,22752,22753,22754,22755,22756,22757,22758, +22759,22760,22761,22762,22763,22764,22765,22766,22767,22768, +22769,22770,22771,22772,22773,22774,22775,22776,22777,22778, +22779,22780,22781,22782,22783,22784,22785,22786,22787,22788, +22789,22790,22791,22792,22793,22794,22795,22796,22797,22798, +22799,22800,22801,22802,22803,22804,22805,22806,22807,22808, +22809,22810,22811,22812,22813,22814,22815,22816,22817,22818, +6850,8248,18353,15981,14967,17317,9413,18629,16811,16813, +6283,17622,6159,17803,16629,20331,11890,11579,12723,20381, +7207,21533,7013,7019,2635,2453,2454,6131,18172,19174, +17620,1233,20265,14694,21535,2579,18347,8269,15791,10102, +10096,2770,13583,17621,19175,11804,8168,18613,2996,20052, +19693,2815,18878,11669,20266,2998,13512,20053,18358,11984, +4357,16671,19083,3246,21656,3733,2816,7965,18211,6105, +19157,10228,12089,5391,12090,18348,10245,10250,5392,8596, +3306,10109,3307,5731,13364,1670,2914,6136,8483,17557, +19987,9271,9814,5122,9564,9967,22819,22820,22821,22822, +22823,22824,22825,22826,22827,22828,22829,22830,22831,22832, +22833,22834,22835,22836,22837,22838,22839,22840,22841,22842, +22843,22844,22845,22846,22847,22848,22849,22850,22851,22852, +22853,22854,22855,22856,22857,22858,22859,22860,22861,22862, +22863,22864,22865,22866,22867,22868,22869,22870,22871,22872, +22873,22874,22875,22876,22877,22878,22879,22880,22881,22882, +22883,22884,22885,22886,22887,22888,22889,22890,22891,22892, +22893,22894,22895,22896,22897,22898,22899,22900,22901,22902, +22903,22904,22905,22906,22907,22908,22909,22910,22911,22912, +16769,6900,14850,19718,12706,4918,8263,9548,886,5739, +14473,3992,7037,17500,17731,3521,23854,23855,23856,23857, +23858,23859,23860,23861,23862,23863,23864,23865,23866,23867, +23868,23869,23870,23871,23872,23873,23874,23875,23876,23877, +23878,23879,23880,23881,23882,23883,23884,23885,23886,23887, +23888,23889,23890,23891,23892,23893,23894,23895,23896,23897, +23898,23899,23900,23901,23902,23903,23904,23905,23906,23907, +23908,23909,23910,23911,23912,23913,23914,23915,23916,23917, +23918,23919,23920,23921,23922,23923,23924,23925,23926,23927, +23928,23929,23930,23931,23932,23933,22913,22914,22915,22916, +22917,22918,22919,22920,22921,22922,22923,22924,22925,22926, +22927,22928,22929,22930,22931,22932,22933,22934,22935,22936, +22937,22938,22939,22940,22941,22942,22943,22944,22945,22946, +22947,22948,22949,22950,22951,22952,22953,22954,22955,22956, +22957,22958,22959,22960,22961,22962,22963,22964,22965,22966, +22967,22968,22969,22970,22971,22972,22973,22974,22975,22976, +22977,22978,22979,22980,22981,22982,22983,22984,22985,22986, +22987,22988,22989,22990,22991,22992,22993,22994,22995,22996, +22997,22998,22999,23000,23001,23002,23003,23004,23005,23006 +}; + +static uint16_t gbksortorder(uint16_t i) +{ + unsigned int idx=gbktail(i); + if (idx>0x7f) idx-=0x41; + else idx-=0x40; + idx+=(gbkhead(i)-0x81)*0xbe; + return 0x8100+gbk_order[idx]; +} + + +int ob_strnncoll_gbk_internal(const unsigned char **a_res, const unsigned char **b_res, + size_t length) +{ + const unsigned char *a= *a_res, *b= *b_res; + unsigned int a_char,b_char; + + while (length--) + { + if ((length > 0) && isgbkcode(*a,*(a+1)) && isgbkcode(*b, *(b+1))) + { + a_char= gbkcode(*a,*(a+1)); + b_char= gbkcode(*b,*(b+1)); + if (a_char != b_char) + return ((int) gbksortorder((uint16_t) a_char) - + (int) gbksortorder((uint16_t) b_char)); + a+= 2; + b+= 2; + length--; + } + else if (sort_order_gbk[*a++] != sort_order_gbk[*b++]) + return ((int) sort_order_gbk[a[-1]] - + (int) sort_order_gbk[b[-1]]); + } + *a_res= a; + *b_res= b; + return 0; +} + + + +int ob_strnncoll_gbk(const ObCharsetInfo *cs __attribute__((unused)), + const unsigned char *a, size_t a_length, + const unsigned char *b, size_t b_length, + bool b_is_prefix) +{ + size_t length = OB_MIN(a_length, b_length); + int res= ob_strnncoll_gbk_internal(&a, &b, length); + return res ? res : (int) ((b_is_prefix ? length : a_length) - b_length); +} + + +static int ob_strnncollsp_gbk(const ObCharsetInfo * cs __attribute__((unused)), + const unsigned char *a, size_t a_length, + const unsigned char *b, size_t b_length, + bool diff_if_only_endspace_difference) +{ + size_t length = OB_MIN(a_length, b_length); + int res = ob_strnncoll_gbk_internal(&a, &b, length); + + if (!res && a_length != b_length) { + const unsigned char *end; + int swap= 1; + if (diff_if_only_endspace_difference) { + return a_length < b_length ? -1 : 1; + } else if (a_length < b_length) { + a_length = b_length; + a = b; + swap= -1; + res= -res; + } + for (end= a + a_length-length; a < end ; a++) { + if (*a != ' ') { + return (*a < ' ') ? -swap : swap; + } + } + } + return res; +} + + +static size_t +ob_strnxfrm_gbk(const ObCharsetInfo *cs, + unsigned char *dst, size_t dstlen, unsigned int nweights, + const unsigned char *src, size_t srclen, unsigned int flags, bool *is_valid_unicode) +{ + unsigned char *d0= dst; + unsigned char *de= dst + dstlen; + const unsigned char *se= src + srclen; + const unsigned char *sort_order= cs->sort_order; + *is_valid_unicode = 1; + + for (; dst < de && src < se && nweights; nweights--) { + if (cs->cset->ismbchar(cs, (const char*) src, (const char*) se)) { + uint16_t e= gbksortorder((uint16_t) gbkcode(*src, *(src + 1))); + *dst++= gbkhead(e); + if (dst < de) { + *dst++= gbktail(e); + } + src+= 2; + } else { + *dst++= sort_order ? sort_order[*src++] : *src++; + if (src < se) { + *is_valid_unicode = 0; + } + } + } + return ob_strxfrm_pad_desc_and_reverse(cs, d0, dst, de, nweights, flags, 0); +} + + +size_t ob_varlen_encoding_gbk_for_memcmp(const struct ObCharsetInfo* cs, + uchar* dst, size_t dst_len, uint nweights, + const uchar *src, size_t src_len, + bool *is_valid_unicode) +{ + uchar *d0= dst; + uchar *de= dst + dst_len; + const uchar *se= src + src_len; + const uchar *sort_order= cs->sort_order; + *is_valid_unicode = 1; + + for (; dst < de && src < se && nweights; nweights--) + { + if (isgbkhead(*(src)) && (se)-(src)>1 && isgbktail(*((src)+1))) + { + /* + Note, it is safe not to check (src < se) + in the code below, because ismbchar() would + not return TRUE if src was too short + */ + uint16_t e= gbksortorder((uint16) gbkcode(*src, *(src + 1))); + *dst++= gbkhead(e); + if (dst < de) + *dst++= gbktail(e); + src+= 2; + if (e == 0) { + *dst++ = 0x00; + *dst++ = 0x01; + } + } else { + uint16_t e = sort_order ? sort_order[*src++] : *src++; + *dst++ = gbkhead(e); + *dst++ = gbktail(e); + if (e == 0) { + *dst++ = 0x00; + *dst++ = 0x01; + } + if (src < se) { + *is_valid_unicode = 0; + } + } + } + *dst++ = 0x00; + *dst++ = 0x00; + *dst++ = 0x00; + *dst++ = 0x00; + + return dst - d0; +} + +size_t ob_varlen_encoding_gbk_for_spacecmp(const struct ObCharsetInfo* cs, + uchar* dst, size_t dst_len, uint nweights, + const uchar *src, size_t src_len, + bool *is_valid_unicode) +{ + uchar *d0= dst; + uchar *de= dst + dst_len; + const uchar *se= src + src_len; + const uchar *sort_order= cs->sort_order; + *is_valid_unicode = 1; + + // trim + while (*(se-1) == 0x20 && se>src) se--; + for (; dst < de && src < se && nweights; nweights--) + { + int16_t space_cnt = 0; + uint16_t e = 0; + while (*src == 0x20) + { + space_cnt++; + src++; + } + if (isgbkhead(*(src)) && (se)-(src)>1 && isgbktail(*((src)+1))) + { + /* + Note, it is safe not to check (src < se) + in the code below, because ismbchar() would + not return TRUE if src was too short + */ + e = gbksortorder((uint16) gbkcode(*src, *(src + 1))); + src+= 2; + } else { + e = sort_order ? sort_order[*src++] : *src++; + if (src < se) { + *is_valid_unicode = 0; + } + } + if (space_cnt != 0) { + *dst++ = 0x00; + *dst++ = 0x20; + if (e > 0x20) { + *dst++ = 0x00; + *dst++ = 0x21; + space_cnt = -space_cnt; + } else { + *dst++ = 0x00; + *dst++ = 0x19; + } + *dst++ = ((uchar)(space_cnt >> 8)); + *dst++ = ((uchar)(space_cnt & 0xff)); + } + *dst++ = gbkhead(e); + *dst++ = gbktail(e); + } + *dst++ = 0x00; + *dst++ = 0x20; + *dst++ = 0x00; + *dst++ = 0x20; + + return dst - d0; +} +size_t ob_strnxfrm_gbk_varlen(const struct ObCharsetInfo* cs, + uchar* dst, size_t dst_len, uint nweights, + const uchar *src, size_t srclen, + bool is_memcmp, bool *is_valid_unicode) +{ + if (is_memcmp) { + return ob_varlen_encoding_gbk_for_memcmp(cs, dst, dst_len, nweights, + src, srclen, is_valid_unicode); + } else { + return ob_varlen_encoding_gbk_for_spacecmp(cs, dst, dst_len, nweights, + src, srclen, is_valid_unicode); + } +} + + +static unsigned int ismbchar_gbk(const ObCharsetInfo *cs __attribute__((unused)), + const char* p, const char *e) +{ + return (isgbkhead(*(p)) && (e)-(p)>1 && isgbktail(*((p)+1))? 2: 0); +} + +static unsigned int mbcharlen_gbk(const ObCharsetInfo *cs __attribute__((unused)), + unsigned int c) +{ + return (isgbkhead(c)? 2 : 1); +} + + +static uint16_t tab_gbk_uni0[]={ +0x4E02,0x4E04,0x4E05,0x4E06,0x4E0F,0x4E12,0x4E17,0x4E1F, +0x4E20,0x4E21,0x4E23,0x4E26,0x4E29,0x4E2E,0x4E2F,0x4E31, +0x4E33,0x4E35,0x4E37,0x4E3C,0x4E40,0x4E41,0x4E42,0x4E44, +0x4E46,0x4E4A,0x4E51,0x4E55,0x4E57,0x4E5A,0x4E5B,0x4E62, +0x4E63,0x4E64,0x4E65,0x4E67,0x4E68,0x4E6A,0x4E6B,0x4E6C, +0x4E6D,0x4E6E,0x4E6F,0x4E72,0x4E74,0x4E75,0x4E76,0x4E77, +0x4E78,0x4E79,0x4E7A,0x4E7B,0x4E7C,0x4E7D,0x4E7F,0x4E80, +0x4E81,0x4E82,0x4E83,0x4E84,0x4E85,0x4E87,0x4E8A, 0, +0x4E90,0x4E96,0x4E97,0x4E99,0x4E9C,0x4E9D,0x4E9E,0x4EA3, +0x4EAA,0x4EAF,0x4EB0,0x4EB1,0x4EB4,0x4EB6,0x4EB7,0x4EB8, +0x4EB9,0x4EBC,0x4EBD,0x4EBE,0x4EC8,0x4ECC,0x4ECF,0x4ED0, +0x4ED2,0x4EDA,0x4EDB,0x4EDC,0x4EE0,0x4EE2,0x4EE6,0x4EE7, +0x4EE9,0x4EED,0x4EEE,0x4EEF,0x4EF1,0x4EF4,0x4EF8,0x4EF9, +0x4EFA,0x4EFC,0x4EFE,0x4F00,0x4F02,0x4F03,0x4F04,0x4F05, +0x4F06,0x4F07,0x4F08,0x4F0B,0x4F0C,0x4F12,0x4F13,0x4F14, +0x4F15,0x4F16,0x4F1C,0x4F1D,0x4F21,0x4F23,0x4F28,0x4F29, +0x4F2C,0x4F2D,0x4F2E,0x4F31,0x4F33,0x4F35,0x4F37,0x4F39, +0x4F3B,0x4F3E,0x4F3F,0x4F40,0x4F41,0x4F42,0x4F44,0x4F45, +0x4F47,0x4F48,0x4F49,0x4F4A,0x4F4B,0x4F4C,0x4F52,0x4F54, +0x4F56,0x4F61,0x4F62,0x4F66,0x4F68,0x4F6A,0x4F6B,0x4F6D, +0x4F6E,0x4F71,0x4F72,0x4F75,0x4F77,0x4F78,0x4F79,0x4F7A, +0x4F7D,0x4F80,0x4F81,0x4F82,0x4F85,0x4F86,0x4F87,0x4F8A, +0x4F8C,0x4F8E,0x4F90,0x4F92,0x4F93,0x4F95,0x4F96,0x4F98, +0x4F99,0x4F9A,0x4F9C,0x4F9E,0x4F9F,0x4FA1,0x4FA2, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x4FA4,0x4FAB,0x4FAD,0x4FB0,0x4FB1,0x4FB2,0x4FB3,0x4FB4, +0x4FB6,0x4FB7,0x4FB8,0x4FB9,0x4FBA,0x4FBB,0x4FBC,0x4FBD, +0x4FBE,0x4FC0,0x4FC1,0x4FC2,0x4FC6,0x4FC7,0x4FC8,0x4FC9, +0x4FCB,0x4FCC,0x4FCD,0x4FD2,0x4FD3,0x4FD4,0x4FD5,0x4FD6, +0x4FD9,0x4FDB,0x4FE0,0x4FE2,0x4FE4,0x4FE5,0x4FE7,0x4FEB, +0x4FEC,0x4FF0,0x4FF2,0x4FF4,0x4FF5,0x4FF6,0x4FF7,0x4FF9, +0x4FFB,0x4FFC,0x4FFD,0x4FFF,0x5000,0x5001,0x5002,0x5003, +0x5004,0x5005,0x5006,0x5007,0x5008,0x5009,0x500A, 0, +0x500B,0x500E,0x5010,0x5011,0x5013,0x5015,0x5016,0x5017, +0x501B,0x501D,0x501E,0x5020,0x5022,0x5023,0x5024,0x5027, +0x502B,0x502F,0x5030,0x5031,0x5032,0x5033,0x5034,0x5035, +0x5036,0x5037,0x5038,0x5039,0x503B,0x503D,0x503F,0x5040, +0x5041,0x5042,0x5044,0x5045,0x5046,0x5049,0x504A,0x504B, +0x504D,0x5050,0x5051,0x5052,0x5053,0x5054,0x5056,0x5057, +0x5058,0x5059,0x505B,0x505D,0x505E,0x505F,0x5060,0x5061, +0x5062,0x5063,0x5064,0x5066,0x5067,0x5068,0x5069,0x506A, +0x506B,0x506D,0x506E,0x506F,0x5070,0x5071,0x5072,0x5073, +0x5074,0x5075,0x5078,0x5079,0x507A,0x507C,0x507D,0x5081, +0x5082,0x5083,0x5084,0x5086,0x5087,0x5089,0x508A,0x508B, +0x508C,0x508E,0x508F,0x5090,0x5091,0x5092,0x5093,0x5094, +0x5095,0x5096,0x5097,0x5098,0x5099,0x509A,0x509B,0x509C, +0x509D,0x509E,0x509F,0x50A0,0x50A1,0x50A2,0x50A4,0x50A6, +0x50AA,0x50AB,0x50AD,0x50AE,0x50AF,0x50B0,0x50B1,0x50B3, +0x50B4,0x50B5,0x50B6,0x50B7,0x50B8,0x50B9,0x50BC, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x50BD,0x50BE,0x50BF,0x50C0,0x50C1,0x50C2,0x50C3,0x50C4, +0x50C5,0x50C6,0x50C7,0x50C8,0x50C9,0x50CA,0x50CB,0x50CC, +0x50CD,0x50CE,0x50D0,0x50D1,0x50D2,0x50D3,0x50D4,0x50D5, +0x50D7,0x50D8,0x50D9,0x50DB,0x50DC,0x50DD,0x50DE,0x50DF, +0x50E0,0x50E1,0x50E2,0x50E3,0x50E4,0x50E5,0x50E8,0x50E9, +0x50EA,0x50EB,0x50EF,0x50F0,0x50F1,0x50F2,0x50F4,0x50F6, +0x50F7,0x50F8,0x50F9,0x50FA,0x50FC,0x50FD,0x50FE,0x50FF, +0x5100,0x5101,0x5102,0x5103,0x5104,0x5105,0x5108, 0, +0x5109,0x510A,0x510C,0x510D,0x510E,0x510F,0x5110,0x5111, +0x5113,0x5114,0x5115,0x5116,0x5117,0x5118,0x5119,0x511A, +0x511B,0x511C,0x511D,0x511E,0x511F,0x5120,0x5122,0x5123, +0x5124,0x5125,0x5126,0x5127,0x5128,0x5129,0x512A,0x512B, +0x512C,0x512D,0x512E,0x512F,0x5130,0x5131,0x5132,0x5133, +0x5134,0x5135,0x5136,0x5137,0x5138,0x5139,0x513A,0x513B, +0x513C,0x513D,0x513E,0x5142,0x5147,0x514A,0x514C,0x514E, +0x514F,0x5150,0x5152,0x5153,0x5157,0x5158,0x5159,0x515B, +0x515D,0x515E,0x515F,0x5160,0x5161,0x5163,0x5164,0x5166, +0x5167,0x5169,0x516A,0x516F,0x5172,0x517A,0x517E,0x517F, +0x5183,0x5184,0x5186,0x5187,0x518A,0x518B,0x518E,0x518F, +0x5190,0x5191,0x5193,0x5194,0x5198,0x519A,0x519D,0x519E, +0x519F,0x51A1,0x51A3,0x51A6,0x51A7,0x51A8,0x51A9,0x51AA, +0x51AD,0x51AE,0x51B4,0x51B8,0x51B9,0x51BA,0x51BE,0x51BF, +0x51C1,0x51C2,0x51C3,0x51C5,0x51C8,0x51CA,0x51CD,0x51CE, +0x51D0,0x51D2,0x51D3,0x51D4,0x51D5,0x51D6,0x51D7, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x51D8,0x51D9,0x51DA,0x51DC,0x51DE,0x51DF,0x51E2,0x51E3, +0x51E5,0x51E6,0x51E7,0x51E8,0x51E9,0x51EA,0x51EC,0x51EE, +0x51F1,0x51F2,0x51F4,0x51F7,0x51FE,0x5204,0x5205,0x5209, +0x520B,0x520C,0x520F,0x5210,0x5213,0x5214,0x5215,0x521C, +0x521E,0x521F,0x5221,0x5222,0x5223,0x5225,0x5226,0x5227, +0x522A,0x522C,0x522F,0x5231,0x5232,0x5234,0x5235,0x523C, +0x523E,0x5244,0x5245,0x5246,0x5247,0x5248,0x5249,0x524B, +0x524E,0x524F,0x5252,0x5253,0x5255,0x5257,0x5258, 0, +0x5259,0x525A,0x525B,0x525D,0x525F,0x5260,0x5262,0x5263, +0x5264,0x5266,0x5268,0x526B,0x526C,0x526D,0x526E,0x5270, +0x5271,0x5273,0x5274,0x5275,0x5276,0x5277,0x5278,0x5279, +0x527A,0x527B,0x527C,0x527E,0x5280,0x5283,0x5284,0x5285, +0x5286,0x5287,0x5289,0x528A,0x528B,0x528C,0x528D,0x528E, +0x528F,0x5291,0x5292,0x5294,0x5295,0x5296,0x5297,0x5298, +0x5299,0x529A,0x529C,0x52A4,0x52A5,0x52A6,0x52A7,0x52AE, +0x52AF,0x52B0,0x52B4,0x52B5,0x52B6,0x52B7,0x52B8,0x52B9, +0x52BA,0x52BB,0x52BC,0x52BD,0x52C0,0x52C1,0x52C2,0x52C4, +0x52C5,0x52C6,0x52C8,0x52CA,0x52CC,0x52CD,0x52CE,0x52CF, +0x52D1,0x52D3,0x52D4,0x52D5,0x52D7,0x52D9,0x52DA,0x52DB, +0x52DC,0x52DD,0x52DE,0x52E0,0x52E1,0x52E2,0x52E3,0x52E5, +0x52E6,0x52E7,0x52E8,0x52E9,0x52EA,0x52EB,0x52EC,0x52ED, +0x52EE,0x52EF,0x52F1,0x52F2,0x52F3,0x52F4,0x52F5,0x52F6, +0x52F7,0x52F8,0x52FB,0x52FC,0x52FD,0x5301,0x5302,0x5303, +0x5304,0x5307,0x5309,0x530A,0x530B,0x530C,0x530E, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x5311,0x5312,0x5313,0x5314,0x5318,0x531B,0x531C,0x531E, +0x531F,0x5322,0x5324,0x5325,0x5327,0x5328,0x5329,0x532B, +0x532C,0x532D,0x532F,0x5330,0x5331,0x5332,0x5333,0x5334, +0x5335,0x5336,0x5337,0x5338,0x533C,0x533D,0x5340,0x5342, +0x5344,0x5346,0x534B,0x534C,0x534D,0x5350,0x5354,0x5358, +0x5359,0x535B,0x535D,0x5365,0x5368,0x536A,0x536C,0x536D, +0x5372,0x5376,0x5379,0x537B,0x537C,0x537D,0x537E,0x5380, +0x5381,0x5383,0x5387,0x5388,0x538A,0x538E,0x538F, 0, +0x5390,0x5391,0x5392,0x5393,0x5394,0x5396,0x5397,0x5399, +0x539B,0x539C,0x539E,0x53A0,0x53A1,0x53A4,0x53A7,0x53AA, +0x53AB,0x53AC,0x53AD,0x53AF,0x53B0,0x53B1,0x53B2,0x53B3, +0x53B4,0x53B5,0x53B7,0x53B8,0x53B9,0x53BA,0x53BC,0x53BD, +0x53BE,0x53C0,0x53C3,0x53C4,0x53C5,0x53C6,0x53C7,0x53CE, +0x53CF,0x53D0,0x53D2,0x53D3,0x53D5,0x53DA,0x53DC,0x53DD, +0x53DE,0x53E1,0x53E2,0x53E7,0x53F4,0x53FA,0x53FE,0x53FF, +0x5400,0x5402,0x5405,0x5407,0x540B,0x5414,0x5418,0x5419, +0x541A,0x541C,0x5422,0x5424,0x5425,0x542A,0x5430,0x5433, +0x5436,0x5437,0x543A,0x543D,0x543F,0x5441,0x5442,0x5444, +0x5445,0x5447,0x5449,0x544C,0x544D,0x544E,0x544F,0x5451, +0x545A,0x545D,0x545E,0x545F,0x5460,0x5461,0x5463,0x5465, +0x5467,0x5469,0x546A,0x546B,0x546C,0x546D,0x546E,0x546F, +0x5470,0x5474,0x5479,0x547A,0x547E,0x547F,0x5481,0x5483, +0x5485,0x5487,0x5488,0x5489,0x548A,0x548D,0x5491,0x5493, +0x5497,0x5498,0x549C,0x549E,0x549F,0x54A0,0x54A1, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x54A2,0x54A5,0x54AE,0x54B0,0x54B2,0x54B5,0x54B6,0x54B7, +0x54B9,0x54BA,0x54BC,0x54BE,0x54C3,0x54C5,0x54CA,0x54CB, +0x54D6,0x54D8,0x54DB,0x54E0,0x54E1,0x54E2,0x54E3,0x54E4, +0x54EB,0x54EC,0x54EF,0x54F0,0x54F1,0x54F4,0x54F5,0x54F6, +0x54F7,0x54F8,0x54F9,0x54FB,0x54FE,0x5500,0x5502,0x5503, +0x5504,0x5505,0x5508,0x550A,0x550B,0x550C,0x550D,0x550E, +0x5512,0x5513,0x5515,0x5516,0x5517,0x5518,0x5519,0x551A, +0x551C,0x551D,0x551E,0x551F,0x5521,0x5525,0x5526, 0, +0x5528,0x5529,0x552B,0x552D,0x5532,0x5534,0x5535,0x5536, +0x5538,0x5539,0x553A,0x553B,0x553D,0x5540,0x5542,0x5545, +0x5547,0x5548,0x554B,0x554C,0x554D,0x554E,0x554F,0x5551, +0x5552,0x5553,0x5554,0x5557,0x5558,0x5559,0x555A,0x555B, +0x555D,0x555E,0x555F,0x5560,0x5562,0x5563,0x5568,0x5569, +0x556B,0x556F,0x5570,0x5571,0x5572,0x5573,0x5574,0x5579, +0x557A,0x557D,0x557F,0x5585,0x5586,0x558C,0x558D,0x558E, +0x5590,0x5592,0x5593,0x5595,0x5596,0x5597,0x559A,0x559B, +0x559E,0x55A0,0x55A1,0x55A2,0x55A3,0x55A4,0x55A5,0x55A6, +0x55A8,0x55A9,0x55AA,0x55AB,0x55AC,0x55AD,0x55AE,0x55AF, +0x55B0,0x55B2,0x55B4,0x55B6,0x55B8,0x55BA,0x55BC,0x55BF, +0x55C0,0x55C1,0x55C2,0x55C3,0x55C6,0x55C7,0x55C8,0x55CA, +0x55CB,0x55CE,0x55CF,0x55D0,0x55D5,0x55D7,0x55D8,0x55D9, +0x55DA,0x55DB,0x55DE,0x55E0,0x55E2,0x55E7,0x55E9,0x55ED, +0x55EE,0x55F0,0x55F1,0x55F4,0x55F6,0x55F8,0x55F9,0x55FA, +0x55FB,0x55FC,0x55FF,0x5602,0x5603,0x5604,0x5605, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x5606,0x5607,0x560A,0x560B,0x560D,0x5610,0x5611,0x5612, +0x5613,0x5614,0x5615,0x5616,0x5617,0x5619,0x561A,0x561C, +0x561D,0x5620,0x5621,0x5622,0x5625,0x5626,0x5628,0x5629, +0x562A,0x562B,0x562E,0x562F,0x5630,0x5633,0x5635,0x5637, +0x5638,0x563A,0x563C,0x563D,0x563E,0x5640,0x5641,0x5642, +0x5643,0x5644,0x5645,0x5646,0x5647,0x5648,0x5649,0x564A, +0x564B,0x564F,0x5650,0x5651,0x5652,0x5653,0x5655,0x5656, +0x565A,0x565B,0x565D,0x565E,0x565F,0x5660,0x5661, 0, +0x5663,0x5665,0x5666,0x5667,0x566D,0x566E,0x566F,0x5670, +0x5672,0x5673,0x5674,0x5675,0x5677,0x5678,0x5679,0x567A, +0x567D,0x567E,0x567F,0x5680,0x5681,0x5682,0x5683,0x5684, +0x5687,0x5688,0x5689,0x568A,0x568B,0x568C,0x568D,0x5690, +0x5691,0x5692,0x5694,0x5695,0x5696,0x5697,0x5698,0x5699, +0x569A,0x569B,0x569C,0x569D,0x569E,0x569F,0x56A0,0x56A1, +0x56A2,0x56A4,0x56A5,0x56A6,0x56A7,0x56A8,0x56A9,0x56AA, +0x56AB,0x56AC,0x56AD,0x56AE,0x56B0,0x56B1,0x56B2,0x56B3, +0x56B4,0x56B5,0x56B6,0x56B8,0x56B9,0x56BA,0x56BB,0x56BD, +0x56BE,0x56BF,0x56C0,0x56C1,0x56C2,0x56C3,0x56C4,0x56C5, +0x56C6,0x56C7,0x56C8,0x56C9,0x56CB,0x56CC,0x56CD,0x56CE, +0x56CF,0x56D0,0x56D1,0x56D2,0x56D3,0x56D5,0x56D6,0x56D8, +0x56D9,0x56DC,0x56E3,0x56E5,0x56E6,0x56E7,0x56E8,0x56E9, +0x56EA,0x56EC,0x56EE,0x56EF,0x56F2,0x56F3,0x56F6,0x56F7, +0x56F8,0x56FB,0x56FC,0x5700,0x5701,0x5702,0x5705,0x5707, +0x570B,0x570C,0x570D,0x570E,0x570F,0x5710,0x5711, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x5712,0x5713,0x5714,0x5715,0x5716,0x5717,0x5718,0x5719, +0x571A,0x571B,0x571D,0x571E,0x5720,0x5721,0x5722,0x5724, +0x5725,0x5726,0x5727,0x572B,0x5731,0x5732,0x5734,0x5735, +0x5736,0x5737,0x5738,0x573C,0x573D,0x573F,0x5741,0x5743, +0x5744,0x5745,0x5746,0x5748,0x5749,0x574B,0x5752,0x5753, +0x5754,0x5755,0x5756,0x5758,0x5759,0x5762,0x5763,0x5765, +0x5767,0x576C,0x576E,0x5770,0x5771,0x5772,0x5774,0x5775, +0x5778,0x5779,0x577A,0x577D,0x577E,0x577F,0x5780, 0, +0x5781,0x5787,0x5788,0x5789,0x578A,0x578D,0x578E,0x578F, +0x5790,0x5791,0x5794,0x5795,0x5796,0x5797,0x5798,0x5799, +0x579A,0x579C,0x579D,0x579E,0x579F,0x57A5,0x57A8,0x57AA, +0x57AC,0x57AF,0x57B0,0x57B1,0x57B3,0x57B5,0x57B6,0x57B7, +0x57B9,0x57BA,0x57BB,0x57BC,0x57BD,0x57BE,0x57BF,0x57C0, +0x57C1,0x57C4,0x57C5,0x57C6,0x57C7,0x57C8,0x57C9,0x57CA, +0x57CC,0x57CD,0x57D0,0x57D1,0x57D3,0x57D6,0x57D7,0x57DB, +0x57DC,0x57DE,0x57E1,0x57E2,0x57E3,0x57E5,0x57E6,0x57E7, +0x57E8,0x57E9,0x57EA,0x57EB,0x57EC,0x57EE,0x57F0,0x57F1, +0x57F2,0x57F3,0x57F5,0x57F6,0x57F7,0x57FB,0x57FC,0x57FE, +0x57FF,0x5801,0x5803,0x5804,0x5805,0x5808,0x5809,0x580A, +0x580C,0x580E,0x580F,0x5810,0x5812,0x5813,0x5814,0x5816, +0x5817,0x5818,0x581A,0x581B,0x581C,0x581D,0x581F,0x5822, +0x5823,0x5825,0x5826,0x5827,0x5828,0x5829,0x582B,0x582C, +0x582D,0x582E,0x582F,0x5831,0x5832,0x5833,0x5834,0x5836, +0x5837,0x5838,0x5839,0x583A,0x583B,0x583C,0x583D, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x583E,0x583F,0x5840,0x5841,0x5842,0x5843,0x5845,0x5846, +0x5847,0x5848,0x5849,0x584A,0x584B,0x584E,0x584F,0x5850, +0x5852,0x5853,0x5855,0x5856,0x5857,0x5859,0x585A,0x585B, +0x585C,0x585D,0x585F,0x5860,0x5861,0x5862,0x5863,0x5864, +0x5866,0x5867,0x5868,0x5869,0x586A,0x586D,0x586E,0x586F, +0x5870,0x5871,0x5872,0x5873,0x5874,0x5875,0x5876,0x5877, +0x5878,0x5879,0x587A,0x587B,0x587C,0x587D,0x587F,0x5882, +0x5884,0x5886,0x5887,0x5888,0x588A,0x588B,0x588C, 0, +0x588D,0x588E,0x588F,0x5890,0x5891,0x5894,0x5895,0x5896, +0x5897,0x5898,0x589B,0x589C,0x589D,0x58A0,0x58A1,0x58A2, +0x58A3,0x58A4,0x58A5,0x58A6,0x58A7,0x58AA,0x58AB,0x58AC, +0x58AD,0x58AE,0x58AF,0x58B0,0x58B1,0x58B2,0x58B3,0x58B4, +0x58B5,0x58B6,0x58B7,0x58B8,0x58B9,0x58BA,0x58BB,0x58BD, +0x58BE,0x58BF,0x58C0,0x58C2,0x58C3,0x58C4,0x58C6,0x58C7, +0x58C8,0x58C9,0x58CA,0x58CB,0x58CC,0x58CD,0x58CE,0x58CF, +0x58D0,0x58D2,0x58D3,0x58D4,0x58D6,0x58D7,0x58D8,0x58D9, +0x58DA,0x58DB,0x58DC,0x58DD,0x58DE,0x58DF,0x58E0,0x58E1, +0x58E2,0x58E3,0x58E5,0x58E6,0x58E7,0x58E8,0x58E9,0x58EA, +0x58ED,0x58EF,0x58F1,0x58F2,0x58F4,0x58F5,0x58F7,0x58F8, +0x58FA,0x58FB,0x58FC,0x58FD,0x58FE,0x58FF,0x5900,0x5901, +0x5903,0x5905,0x5906,0x5908,0x5909,0x590A,0x590B,0x590C, +0x590E,0x5910,0x5911,0x5912,0x5913,0x5917,0x5918,0x591B, +0x591D,0x591E,0x5920,0x5921,0x5922,0x5923,0x5926,0x5928, +0x592C,0x5930,0x5932,0x5933,0x5935,0x5936,0x593B, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x593D,0x593E,0x593F,0x5940,0x5943,0x5945,0x5946,0x594A, +0x594C,0x594D,0x5950,0x5952,0x5953,0x5959,0x595B,0x595C, +0x595D,0x595E,0x595F,0x5961,0x5963,0x5964,0x5966,0x5967, +0x5968,0x5969,0x596A,0x596B,0x596C,0x596D,0x596E,0x596F, +0x5970,0x5971,0x5972,0x5975,0x5977,0x597A,0x597B,0x597C, +0x597E,0x597F,0x5980,0x5985,0x5989,0x598B,0x598C,0x598E, +0x598F,0x5990,0x5991,0x5994,0x5995,0x5998,0x599A,0x599B, +0x599C,0x599D,0x599F,0x59A0,0x59A1,0x59A2,0x59A6, 0, +0x59A7,0x59AC,0x59AD,0x59B0,0x59B1,0x59B3,0x59B4,0x59B5, +0x59B6,0x59B7,0x59B8,0x59BA,0x59BC,0x59BD,0x59BF,0x59C0, +0x59C1,0x59C2,0x59C3,0x59C4,0x59C5,0x59C7,0x59C8,0x59C9, +0x59CC,0x59CD,0x59CE,0x59CF,0x59D5,0x59D6,0x59D9,0x59DB, +0x59DE,0x59DF,0x59E0,0x59E1,0x59E2,0x59E4,0x59E6,0x59E7, +0x59E9,0x59EA,0x59EB,0x59ED,0x59EE,0x59EF,0x59F0,0x59F1, +0x59F2,0x59F3,0x59F4,0x59F5,0x59F6,0x59F7,0x59F8,0x59FA, +0x59FC,0x59FD,0x59FE,0x5A00,0x5A02,0x5A0A,0x5A0B,0x5A0D, +0x5A0E,0x5A0F,0x5A10,0x5A12,0x5A14,0x5A15,0x5A16,0x5A17, +0x5A19,0x5A1A,0x5A1B,0x5A1D,0x5A1E,0x5A21,0x5A22,0x5A24, +0x5A26,0x5A27,0x5A28,0x5A2A,0x5A2B,0x5A2C,0x5A2D,0x5A2E, +0x5A2F,0x5A30,0x5A33,0x5A35,0x5A37,0x5A38,0x5A39,0x5A3A, +0x5A3B,0x5A3D,0x5A3E,0x5A3F,0x5A41,0x5A42,0x5A43,0x5A44, +0x5A45,0x5A47,0x5A48,0x5A4B,0x5A4C,0x5A4D,0x5A4E,0x5A4F, +0x5A50,0x5A51,0x5A52,0x5A53,0x5A54,0x5A56,0x5A57,0x5A58, +0x5A59,0x5A5B,0x5A5C,0x5A5D,0x5A5E,0x5A5F,0x5A60, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x5A61,0x5A63,0x5A64,0x5A65,0x5A66,0x5A68,0x5A69,0x5A6B, +0x5A6C,0x5A6D,0x5A6E,0x5A6F,0x5A70,0x5A71,0x5A72,0x5A73, +0x5A78,0x5A79,0x5A7B,0x5A7C,0x5A7D,0x5A7E,0x5A80,0x5A81, +0x5A82,0x5A83,0x5A84,0x5A85,0x5A86,0x5A87,0x5A88,0x5A89, +0x5A8A,0x5A8B,0x5A8C,0x5A8D,0x5A8E,0x5A8F,0x5A90,0x5A91, +0x5A93,0x5A94,0x5A95,0x5A96,0x5A97,0x5A98,0x5A99,0x5A9C, +0x5A9D,0x5A9E,0x5A9F,0x5AA0,0x5AA1,0x5AA2,0x5AA3,0x5AA4, +0x5AA5,0x5AA6,0x5AA7,0x5AA8,0x5AA9,0x5AAB,0x5AAC, 0, +0x5AAD,0x5AAE,0x5AAF,0x5AB0,0x5AB1,0x5AB4,0x5AB6,0x5AB7, +0x5AB9,0x5ABA,0x5ABB,0x5ABC,0x5ABD,0x5ABF,0x5AC0,0x5AC3, +0x5AC4,0x5AC5,0x5AC6,0x5AC7,0x5AC8,0x5ACA,0x5ACB,0x5ACD, +0x5ACE,0x5ACF,0x5AD0,0x5AD1,0x5AD3,0x5AD5,0x5AD7,0x5AD9, +0x5ADA,0x5ADB,0x5ADD,0x5ADE,0x5ADF,0x5AE2,0x5AE4,0x5AE5, +0x5AE7,0x5AE8,0x5AEA,0x5AEC,0x5AED,0x5AEE,0x5AEF,0x5AF0, +0x5AF2,0x5AF3,0x5AF4,0x5AF5,0x5AF6,0x5AF7,0x5AF8,0x5AF9, +0x5AFA,0x5AFB,0x5AFC,0x5AFD,0x5AFE,0x5AFF,0x5B00,0x5B01, +0x5B02,0x5B03,0x5B04,0x5B05,0x5B06,0x5B07,0x5B08,0x5B0A, +0x5B0B,0x5B0C,0x5B0D,0x5B0E,0x5B0F,0x5B10,0x5B11,0x5B12, +0x5B13,0x5B14,0x5B15,0x5B18,0x5B19,0x5B1A,0x5B1B,0x5B1C, +0x5B1D,0x5B1E,0x5B1F,0x5B20,0x5B21,0x5B22,0x5B23,0x5B24, +0x5B25,0x5B26,0x5B27,0x5B28,0x5B29,0x5B2A,0x5B2B,0x5B2C, +0x5B2D,0x5B2E,0x5B2F,0x5B30,0x5B31,0x5B33,0x5B35,0x5B36, +0x5B38,0x5B39,0x5B3A,0x5B3B,0x5B3C,0x5B3D,0x5B3E,0x5B3F, +0x5B41,0x5B42,0x5B43,0x5B44,0x5B45,0x5B46,0x5B47, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x5B48,0x5B49,0x5B4A,0x5B4B,0x5B4C,0x5B4D,0x5B4E,0x5B4F, +0x5B52,0x5B56,0x5B5E,0x5B60,0x5B61,0x5B67,0x5B68,0x5B6B, +0x5B6D,0x5B6E,0x5B6F,0x5B72,0x5B74,0x5B76,0x5B77,0x5B78, +0x5B79,0x5B7B,0x5B7C,0x5B7E,0x5B7F,0x5B82,0x5B86,0x5B8A, +0x5B8D,0x5B8E,0x5B90,0x5B91,0x5B92,0x5B94,0x5B96,0x5B9F, +0x5BA7,0x5BA8,0x5BA9,0x5BAC,0x5BAD,0x5BAE,0x5BAF,0x5BB1, +0x5BB2,0x5BB7,0x5BBA,0x5BBB,0x5BBC,0x5BC0,0x5BC1,0x5BC3, +0x5BC8,0x5BC9,0x5BCA,0x5BCB,0x5BCD,0x5BCE,0x5BCF, 0, +0x5BD1,0x5BD4,0x5BD5,0x5BD6,0x5BD7,0x5BD8,0x5BD9,0x5BDA, +0x5BDB,0x5BDC,0x5BE0,0x5BE2,0x5BE3,0x5BE6,0x5BE7,0x5BE9, +0x5BEA,0x5BEB,0x5BEC,0x5BED,0x5BEF,0x5BF1,0x5BF2,0x5BF3, +0x5BF4,0x5BF5,0x5BF6,0x5BF7,0x5BFD,0x5BFE,0x5C00,0x5C02, +0x5C03,0x5C05,0x5C07,0x5C08,0x5C0B,0x5C0C,0x5C0D,0x5C0E, +0x5C10,0x5C12,0x5C13,0x5C17,0x5C19,0x5C1B,0x5C1E,0x5C1F, +0x5C20,0x5C21,0x5C23,0x5C26,0x5C28,0x5C29,0x5C2A,0x5C2B, +0x5C2D,0x5C2E,0x5C2F,0x5C30,0x5C32,0x5C33,0x5C35,0x5C36, +0x5C37,0x5C43,0x5C44,0x5C46,0x5C47,0x5C4C,0x5C4D,0x5C52, +0x5C53,0x5C54,0x5C56,0x5C57,0x5C58,0x5C5A,0x5C5B,0x5C5C, +0x5C5D,0x5C5F,0x5C62,0x5C64,0x5C67,0x5C68,0x5C69,0x5C6A, +0x5C6B,0x5C6C,0x5C6D,0x5C70,0x5C72,0x5C73,0x5C74,0x5C75, +0x5C76,0x5C77,0x5C78,0x5C7B,0x5C7C,0x5C7D,0x5C7E,0x5C80, +0x5C83,0x5C84,0x5C85,0x5C86,0x5C87,0x5C89,0x5C8A,0x5C8B, +0x5C8E,0x5C8F,0x5C92,0x5C93,0x5C95,0x5C9D,0x5C9E,0x5C9F, +0x5CA0,0x5CA1,0x5CA4,0x5CA5,0x5CA6,0x5CA7,0x5CA8, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x5CAA,0x5CAE,0x5CAF,0x5CB0,0x5CB2,0x5CB4,0x5CB6,0x5CB9, +0x5CBA,0x5CBB,0x5CBC,0x5CBE,0x5CC0,0x5CC2,0x5CC3,0x5CC5, +0x5CC6,0x5CC7,0x5CC8,0x5CC9,0x5CCA,0x5CCC,0x5CCD,0x5CCE, +0x5CCF,0x5CD0,0x5CD1,0x5CD3,0x5CD4,0x5CD5,0x5CD6,0x5CD7, +0x5CD8,0x5CDA,0x5CDB,0x5CDC,0x5CDD,0x5CDE,0x5CDF,0x5CE0, +0x5CE2,0x5CE3,0x5CE7,0x5CE9,0x5CEB,0x5CEC,0x5CEE,0x5CEF, +0x5CF1,0x5CF2,0x5CF3,0x5CF4,0x5CF5,0x5CF6,0x5CF7,0x5CF8, +0x5CF9,0x5CFA,0x5CFC,0x5CFD,0x5CFE,0x5CFF,0x5D00, 0, +0x5D01,0x5D04,0x5D05,0x5D08,0x5D09,0x5D0A,0x5D0B,0x5D0C, +0x5D0D,0x5D0F,0x5D10,0x5D11,0x5D12,0x5D13,0x5D15,0x5D17, +0x5D18,0x5D19,0x5D1A,0x5D1C,0x5D1D,0x5D1F,0x5D20,0x5D21, +0x5D22,0x5D23,0x5D25,0x5D28,0x5D2A,0x5D2B,0x5D2C,0x5D2F, +0x5D30,0x5D31,0x5D32,0x5D33,0x5D35,0x5D36,0x5D37,0x5D38, +0x5D39,0x5D3A,0x5D3B,0x5D3C,0x5D3F,0x5D40,0x5D41,0x5D42, +0x5D43,0x5D44,0x5D45,0x5D46,0x5D48,0x5D49,0x5D4D,0x5D4E, +0x5D4F,0x5D50,0x5D51,0x5D52,0x5D53,0x5D54,0x5D55,0x5D56, +0x5D57,0x5D59,0x5D5A,0x5D5C,0x5D5E,0x5D5F,0x5D60,0x5D61, +0x5D62,0x5D63,0x5D64,0x5D65,0x5D66,0x5D67,0x5D68,0x5D6A, +0x5D6D,0x5D6E,0x5D70,0x5D71,0x5D72,0x5D73,0x5D75,0x5D76, +0x5D77,0x5D78,0x5D79,0x5D7A,0x5D7B,0x5D7C,0x5D7D,0x5D7E, +0x5D7F,0x5D80,0x5D81,0x5D83,0x5D84,0x5D85,0x5D86,0x5D87, +0x5D88,0x5D89,0x5D8A,0x5D8B,0x5D8C,0x5D8D,0x5D8E,0x5D8F, +0x5D90,0x5D91,0x5D92,0x5D93,0x5D94,0x5D95,0x5D96,0x5D97, +0x5D98,0x5D9A,0x5D9B,0x5D9C,0x5D9E,0x5D9F,0x5DA0, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x5DA1,0x5DA2,0x5DA3,0x5DA4,0x5DA5,0x5DA6,0x5DA7,0x5DA8, +0x5DA9,0x5DAA,0x5DAB,0x5DAC,0x5DAD,0x5DAE,0x5DAF,0x5DB0, +0x5DB1,0x5DB2,0x5DB3,0x5DB4,0x5DB5,0x5DB6,0x5DB8,0x5DB9, +0x5DBA,0x5DBB,0x5DBC,0x5DBD,0x5DBE,0x5DBF,0x5DC0,0x5DC1, +0x5DC2,0x5DC3,0x5DC4,0x5DC6,0x5DC7,0x5DC8,0x5DC9,0x5DCA, +0x5DCB,0x5DCC,0x5DCE,0x5DCF,0x5DD0,0x5DD1,0x5DD2,0x5DD3, +0x5DD4,0x5DD5,0x5DD6,0x5DD7,0x5DD8,0x5DD9,0x5DDA,0x5DDC, +0x5DDF,0x5DE0,0x5DE3,0x5DE4,0x5DEA,0x5DEC,0x5DED, 0, +0x5DF0,0x5DF5,0x5DF6,0x5DF8,0x5DF9,0x5DFA,0x5DFB,0x5DFC, +0x5DFF,0x5E00,0x5E04,0x5E07,0x5E09,0x5E0A,0x5E0B,0x5E0D, +0x5E0E,0x5E12,0x5E13,0x5E17,0x5E1E,0x5E1F,0x5E20,0x5E21, +0x5E22,0x5E23,0x5E24,0x5E25,0x5E28,0x5E29,0x5E2A,0x5E2B, +0x5E2C,0x5E2F,0x5E30,0x5E32,0x5E33,0x5E34,0x5E35,0x5E36, +0x5E39,0x5E3A,0x5E3E,0x5E3F,0x5E40,0x5E41,0x5E43,0x5E46, +0x5E47,0x5E48,0x5E49,0x5E4A,0x5E4B,0x5E4D,0x5E4E,0x5E4F, +0x5E50,0x5E51,0x5E52,0x5E53,0x5E56,0x5E57,0x5E58,0x5E59, +0x5E5A,0x5E5C,0x5E5D,0x5E5F,0x5E60,0x5E63,0x5E64,0x5E65, +0x5E66,0x5E67,0x5E68,0x5E69,0x5E6A,0x5E6B,0x5E6C,0x5E6D, +0x5E6E,0x5E6F,0x5E70,0x5E71,0x5E75,0x5E77,0x5E79,0x5E7E, +0x5E81,0x5E82,0x5E83,0x5E85,0x5E88,0x5E89,0x5E8C,0x5E8D, +0x5E8E,0x5E92,0x5E98,0x5E9B,0x5E9D,0x5EA1,0x5EA2,0x5EA3, +0x5EA4,0x5EA8,0x5EA9,0x5EAA,0x5EAB,0x5EAC,0x5EAE,0x5EAF, +0x5EB0,0x5EB1,0x5EB2,0x5EB4,0x5EBA,0x5EBB,0x5EBC,0x5EBD, +0x5EBF,0x5EC0,0x5EC1,0x5EC2,0x5EC3,0x5EC4,0x5EC5, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x5EC6,0x5EC7,0x5EC8,0x5ECB,0x5ECC,0x5ECD,0x5ECE,0x5ECF, +0x5ED0,0x5ED4,0x5ED5,0x5ED7,0x5ED8,0x5ED9,0x5EDA,0x5EDC, +0x5EDD,0x5EDE,0x5EDF,0x5EE0,0x5EE1,0x5EE2,0x5EE3,0x5EE4, +0x5EE5,0x5EE6,0x5EE7,0x5EE9,0x5EEB,0x5EEC,0x5EED,0x5EEE, +0x5EEF,0x5EF0,0x5EF1,0x5EF2,0x5EF3,0x5EF5,0x5EF8,0x5EF9, +0x5EFB,0x5EFC,0x5EFD,0x5F05,0x5F06,0x5F07,0x5F09,0x5F0C, +0x5F0D,0x5F0E,0x5F10,0x5F12,0x5F14,0x5F16,0x5F19,0x5F1A, +0x5F1C,0x5F1D,0x5F1E,0x5F21,0x5F22,0x5F23,0x5F24, 0, +0x5F28,0x5F2B,0x5F2C,0x5F2E,0x5F30,0x5F32,0x5F33,0x5F34, +0x5F35,0x5F36,0x5F37,0x5F38,0x5F3B,0x5F3D,0x5F3E,0x5F3F, +0x5F41,0x5F42,0x5F43,0x5F44,0x5F45,0x5F46,0x5F47,0x5F48, +0x5F49,0x5F4A,0x5F4B,0x5F4C,0x5F4D,0x5F4E,0x5F4F,0x5F51, +0x5F54,0x5F59,0x5F5A,0x5F5B,0x5F5C,0x5F5E,0x5F5F,0x5F60, +0x5F63,0x5F65,0x5F67,0x5F68,0x5F6B,0x5F6E,0x5F6F,0x5F72, +0x5F74,0x5F75,0x5F76,0x5F78,0x5F7A,0x5F7D,0x5F7E,0x5F7F, +0x5F83,0x5F86,0x5F8D,0x5F8E,0x5F8F,0x5F91,0x5F93,0x5F94, +0x5F96,0x5F9A,0x5F9B,0x5F9D,0x5F9E,0x5F9F,0x5FA0,0x5FA2, +0x5FA3,0x5FA4,0x5FA5,0x5FA6,0x5FA7,0x5FA9,0x5FAB,0x5FAC, +0x5FAF,0x5FB0,0x5FB1,0x5FB2,0x5FB3,0x5FB4,0x5FB6,0x5FB8, +0x5FB9,0x5FBA,0x5FBB,0x5FBE,0x5FBF,0x5FC0,0x5FC1,0x5FC2, +0x5FC7,0x5FC8,0x5FCA,0x5FCB,0x5FCE,0x5FD3,0x5FD4,0x5FD5, +0x5FDA,0x5FDB,0x5FDC,0x5FDE,0x5FDF,0x5FE2,0x5FE3,0x5FE5, +0x5FE6,0x5FE8,0x5FE9,0x5FEC,0x5FEF,0x5FF0,0x5FF2,0x5FF3, +0x5FF4,0x5FF6,0x5FF7,0x5FF9,0x5FFA,0x5FFC,0x6007, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x6008,0x6009,0x600B,0x600C,0x6010,0x6011,0x6013,0x6017, +0x6018,0x601A,0x601E,0x601F,0x6022,0x6023,0x6024,0x602C, +0x602D,0x602E,0x6030,0x6031,0x6032,0x6033,0x6034,0x6036, +0x6037,0x6038,0x6039,0x603A,0x603D,0x603E,0x6040,0x6044, +0x6045,0x6046,0x6047,0x6048,0x6049,0x604A,0x604C,0x604E, +0x604F,0x6051,0x6053,0x6054,0x6056,0x6057,0x6058,0x605B, +0x605C,0x605E,0x605F,0x6060,0x6061,0x6065,0x6066,0x606E, +0x6071,0x6072,0x6074,0x6075,0x6077,0x607E,0x6080, 0, +0x6081,0x6082,0x6085,0x6086,0x6087,0x6088,0x608A,0x608B, +0x608E,0x608F,0x6090,0x6091,0x6093,0x6095,0x6097,0x6098, +0x6099,0x609C,0x609E,0x60A1,0x60A2,0x60A4,0x60A5,0x60A7, +0x60A9,0x60AA,0x60AE,0x60B0,0x60B3,0x60B5,0x60B6,0x60B7, +0x60B9,0x60BA,0x60BD,0x60BE,0x60BF,0x60C0,0x60C1,0x60C2, +0x60C3,0x60C4,0x60C7,0x60C8,0x60C9,0x60CC,0x60CD,0x60CE, +0x60CF,0x60D0,0x60D2,0x60D3,0x60D4,0x60D6,0x60D7,0x60D9, +0x60DB,0x60DE,0x60E1,0x60E2,0x60E3,0x60E4,0x60E5,0x60EA, +0x60F1,0x60F2,0x60F5,0x60F7,0x60F8,0x60FB,0x60FC,0x60FD, +0x60FE,0x60FF,0x6102,0x6103,0x6104,0x6105,0x6107,0x610A, +0x610B,0x610C,0x6110,0x6111,0x6112,0x6113,0x6114,0x6116, +0x6117,0x6118,0x6119,0x611B,0x611C,0x611D,0x611E,0x6121, +0x6122,0x6125,0x6128,0x6129,0x612A,0x612C,0x612D,0x612E, +0x612F,0x6130,0x6131,0x6132,0x6133,0x6134,0x6135,0x6136, +0x6137,0x6138,0x6139,0x613A,0x613B,0x613C,0x613D,0x613E, +0x6140,0x6141,0x6142,0x6143,0x6144,0x6145,0x6146, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x6147,0x6149,0x614B,0x614D,0x614F,0x6150,0x6152,0x6153, +0x6154,0x6156,0x6157,0x6158,0x6159,0x615A,0x615B,0x615C, +0x615E,0x615F,0x6160,0x6161,0x6163,0x6164,0x6165,0x6166, +0x6169,0x616A,0x616B,0x616C,0x616D,0x616E,0x616F,0x6171, +0x6172,0x6173,0x6174,0x6176,0x6178,0x6179,0x617A,0x617B, +0x617C,0x617D,0x617E,0x617F,0x6180,0x6181,0x6182,0x6183, +0x6184,0x6185,0x6186,0x6187,0x6188,0x6189,0x618A,0x618C, +0x618D,0x618F,0x6190,0x6191,0x6192,0x6193,0x6195, 0, +0x6196,0x6197,0x6198,0x6199,0x619A,0x619B,0x619C,0x619E, +0x619F,0x61A0,0x61A1,0x61A2,0x61A3,0x61A4,0x61A5,0x61A6, +0x61AA,0x61AB,0x61AD,0x61AE,0x61AF,0x61B0,0x61B1,0x61B2, +0x61B3,0x61B4,0x61B5,0x61B6,0x61B8,0x61B9,0x61BA,0x61BB, +0x61BC,0x61BD,0x61BF,0x61C0,0x61C1,0x61C3,0x61C4,0x61C5, +0x61C6,0x61C7,0x61C9,0x61CC,0x61CD,0x61CE,0x61CF,0x61D0, +0x61D3,0x61D5,0x61D6,0x61D7,0x61D8,0x61D9,0x61DA,0x61DB, +0x61DC,0x61DD,0x61DE,0x61DF,0x61E0,0x61E1,0x61E2,0x61E3, +0x61E4,0x61E5,0x61E7,0x61E8,0x61E9,0x61EA,0x61EB,0x61EC, +0x61ED,0x61EE,0x61EF,0x61F0,0x61F1,0x61F2,0x61F3,0x61F4, +0x61F6,0x61F7,0x61F8,0x61F9,0x61FA,0x61FB,0x61FC,0x61FD, +0x61FE,0x6200,0x6201,0x6202,0x6203,0x6204,0x6205,0x6207, +0x6209,0x6213,0x6214,0x6219,0x621C,0x621D,0x621E,0x6220, +0x6223,0x6226,0x6227,0x6228,0x6229,0x622B,0x622D,0x622F, +0x6230,0x6231,0x6232,0x6235,0x6236,0x6238,0x6239,0x623A, +0x623B,0x623C,0x6242,0x6244,0x6245,0x6246,0x624A, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x624F,0x6250,0x6255,0x6256,0x6257,0x6259,0x625A,0x625C, +0x625D,0x625E,0x625F,0x6260,0x6261,0x6262,0x6264,0x6265, +0x6268,0x6271,0x6272,0x6274,0x6275,0x6277,0x6278,0x627A, +0x627B,0x627D,0x6281,0x6282,0x6283,0x6285,0x6286,0x6287, +0x6288,0x628B,0x628C,0x628D,0x628E,0x628F,0x6290,0x6294, +0x6299,0x629C,0x629D,0x629E,0x62A3,0x62A6,0x62A7,0x62A9, +0x62AA,0x62AD,0x62AE,0x62AF,0x62B0,0x62B2,0x62B3,0x62B4, +0x62B6,0x62B7,0x62B8,0x62BA,0x62BE,0x62C0,0x62C1, 0, +0x62C3,0x62CB,0x62CF,0x62D1,0x62D5,0x62DD,0x62DE,0x62E0, +0x62E1,0x62E4,0x62EA,0x62EB,0x62F0,0x62F2,0x62F5,0x62F8, +0x62F9,0x62FA,0x62FB,0x6300,0x6303,0x6304,0x6305,0x6306, +0x630A,0x630B,0x630C,0x630D,0x630F,0x6310,0x6312,0x6313, +0x6314,0x6315,0x6317,0x6318,0x6319,0x631C,0x6326,0x6327, +0x6329,0x632C,0x632D,0x632E,0x6330,0x6331,0x6333,0x6334, +0x6335,0x6336,0x6337,0x6338,0x633B,0x633C,0x633E,0x633F, +0x6340,0x6341,0x6344,0x6347,0x6348,0x634A,0x6351,0x6352, +0x6353,0x6354,0x6356,0x6357,0x6358,0x6359,0x635A,0x635B, +0x635C,0x635D,0x6360,0x6364,0x6365,0x6366,0x6368,0x636A, +0x636B,0x636C,0x636F,0x6370,0x6372,0x6373,0x6374,0x6375, +0x6378,0x6379,0x637C,0x637D,0x637E,0x637F,0x6381,0x6383, +0x6384,0x6385,0x6386,0x638B,0x638D,0x6391,0x6393,0x6394, +0x6395,0x6397,0x6399,0x639A,0x639B,0x639C,0x639D,0x639E, +0x639F,0x63A1,0x63A4,0x63A6,0x63AB,0x63AF,0x63B1,0x63B2, +0x63B5,0x63B6,0x63B9,0x63BB,0x63BD,0x63BF,0x63C0, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x63C1,0x63C2,0x63C3,0x63C5,0x63C7,0x63C8,0x63CA,0x63CB, +0x63CC,0x63D1,0x63D3,0x63D4,0x63D5,0x63D7,0x63D8,0x63D9, +0x63DA,0x63DB,0x63DC,0x63DD,0x63DF,0x63E2,0x63E4,0x63E5, +0x63E6,0x63E7,0x63E8,0x63EB,0x63EC,0x63EE,0x63EF,0x63F0, +0x63F1,0x63F3,0x63F5,0x63F7,0x63F9,0x63FA,0x63FB,0x63FC, +0x63FE,0x6403,0x6404,0x6406,0x6407,0x6408,0x6409,0x640A, +0x640D,0x640E,0x6411,0x6412,0x6415,0x6416,0x6417,0x6418, +0x6419,0x641A,0x641D,0x641F,0x6422,0x6423,0x6424, 0, +0x6425,0x6427,0x6428,0x6429,0x642B,0x642E,0x642F,0x6430, +0x6431,0x6432,0x6433,0x6435,0x6436,0x6437,0x6438,0x6439, +0x643B,0x643C,0x643E,0x6440,0x6442,0x6443,0x6449,0x644B, +0x644C,0x644D,0x644E,0x644F,0x6450,0x6451,0x6453,0x6455, +0x6456,0x6457,0x6459,0x645A,0x645B,0x645C,0x645D,0x645F, +0x6460,0x6461,0x6462,0x6463,0x6464,0x6465,0x6466,0x6468, +0x646A,0x646B,0x646C,0x646E,0x646F,0x6470,0x6471,0x6472, +0x6473,0x6474,0x6475,0x6476,0x6477,0x647B,0x647C,0x647D, +0x647E,0x647F,0x6480,0x6481,0x6483,0x6486,0x6488,0x6489, +0x648A,0x648B,0x648C,0x648D,0x648E,0x648F,0x6490,0x6493, +0x6494,0x6497,0x6498,0x649A,0x649B,0x649C,0x649D,0x649F, +0x64A0,0x64A1,0x64A2,0x64A3,0x64A5,0x64A6,0x64A7,0x64A8, +0x64AA,0x64AB,0x64AF,0x64B1,0x64B2,0x64B3,0x64B4,0x64B6, +0x64B9,0x64BB,0x64BD,0x64BE,0x64BF,0x64C1,0x64C3,0x64C4, +0x64C6,0x64C7,0x64C8,0x64C9,0x64CA,0x64CB,0x64CC,0x64CF, +0x64D1,0x64D3,0x64D4,0x64D5,0x64D6,0x64D9,0x64DA, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x64DB,0x64DC,0x64DD,0x64DF,0x64E0,0x64E1,0x64E3,0x64E5, +0x64E7,0x64E8,0x64E9,0x64EA,0x64EB,0x64EC,0x64ED,0x64EE, +0x64EF,0x64F0,0x64F1,0x64F2,0x64F3,0x64F4,0x64F5,0x64F6, +0x64F7,0x64F8,0x64F9,0x64FA,0x64FB,0x64FC,0x64FD,0x64FE, +0x64FF,0x6501,0x6502,0x6503,0x6504,0x6505,0x6506,0x6507, +0x6508,0x650A,0x650B,0x650C,0x650D,0x650E,0x650F,0x6510, +0x6511,0x6513,0x6514,0x6515,0x6516,0x6517,0x6519,0x651A, +0x651B,0x651C,0x651D,0x651E,0x651F,0x6520,0x6521, 0, +0x6522,0x6523,0x6524,0x6526,0x6527,0x6528,0x6529,0x652A, +0x652C,0x652D,0x6530,0x6531,0x6532,0x6533,0x6537,0x653A, +0x653C,0x653D,0x6540,0x6541,0x6542,0x6543,0x6544,0x6546, +0x6547,0x654A,0x654B,0x654D,0x654E,0x6550,0x6552,0x6553, +0x6554,0x6557,0x6558,0x655A,0x655C,0x655F,0x6560,0x6561, +0x6564,0x6565,0x6567,0x6568,0x6569,0x656A,0x656D,0x656E, +0x656F,0x6571,0x6573,0x6575,0x6576,0x6578,0x6579,0x657A, +0x657B,0x657C,0x657D,0x657E,0x657F,0x6580,0x6581,0x6582, +0x6583,0x6584,0x6585,0x6586,0x6588,0x6589,0x658A,0x658D, +0x658E,0x658F,0x6592,0x6594,0x6595,0x6596,0x6598,0x659A, +0x659D,0x659E,0x65A0,0x65A2,0x65A3,0x65A6,0x65A8,0x65AA, +0x65AC,0x65AE,0x65B1,0x65B2,0x65B3,0x65B4,0x65B5,0x65B6, +0x65B7,0x65B8,0x65BA,0x65BB,0x65BE,0x65BF,0x65C0,0x65C2, +0x65C7,0x65C8,0x65C9,0x65CA,0x65CD,0x65D0,0x65D1,0x65D3, +0x65D4,0x65D5,0x65D8,0x65D9,0x65DA,0x65DB,0x65DC,0x65DD, +0x65DE,0x65DF,0x65E1,0x65E3,0x65E4,0x65EA,0x65EB, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x65F2,0x65F3,0x65F4,0x65F5,0x65F8,0x65F9,0x65FB,0x65FC, +0x65FD,0x65FE,0x65FF,0x6601,0x6604,0x6605,0x6607,0x6608, +0x6609,0x660B,0x660D,0x6610,0x6611,0x6612,0x6616,0x6617, +0x6618,0x661A,0x661B,0x661C,0x661E,0x6621,0x6622,0x6623, +0x6624,0x6626,0x6629,0x662A,0x662B,0x662C,0x662E,0x6630, +0x6632,0x6633,0x6637,0x6638,0x6639,0x663A,0x663B,0x663D, +0x663F,0x6640,0x6642,0x6644,0x6645,0x6646,0x6647,0x6648, +0x6649,0x664A,0x664D,0x664E,0x6650,0x6651,0x6658, 0, +0x6659,0x665B,0x665C,0x665D,0x665E,0x6660,0x6662,0x6663, +0x6665,0x6667,0x6669,0x666A,0x666B,0x666C,0x666D,0x6671, +0x6672,0x6673,0x6675,0x6678,0x6679,0x667B,0x667C,0x667D, +0x667F,0x6680,0x6681,0x6683,0x6685,0x6686,0x6688,0x6689, +0x668A,0x668B,0x668D,0x668E,0x668F,0x6690,0x6692,0x6693, +0x6694,0x6695,0x6698,0x6699,0x669A,0x669B,0x669C,0x669E, +0x669F,0x66A0,0x66A1,0x66A2,0x66A3,0x66A4,0x66A5,0x66A6, +0x66A9,0x66AA,0x66AB,0x66AC,0x66AD,0x66AF,0x66B0,0x66B1, +0x66B2,0x66B3,0x66B5,0x66B6,0x66B7,0x66B8,0x66BA,0x66BB, +0x66BC,0x66BD,0x66BF,0x66C0,0x66C1,0x66C2,0x66C3,0x66C4, +0x66C5,0x66C6,0x66C7,0x66C8,0x66C9,0x66CA,0x66CB,0x66CC, +0x66CD,0x66CE,0x66CF,0x66D0,0x66D1,0x66D2,0x66D3,0x66D4, +0x66D5,0x66D6,0x66D7,0x66D8,0x66DA,0x66DE,0x66DF,0x66E0, +0x66E1,0x66E2,0x66E3,0x66E4,0x66E5,0x66E7,0x66E8,0x66EA, +0x66EB,0x66EC,0x66ED,0x66EE,0x66EF,0x66F1,0x66F5,0x66F6, +0x66F8,0x66FA,0x66FB,0x66FD,0x6701,0x6702,0x6703, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x6704,0x6705,0x6706,0x6707,0x670C,0x670E,0x670F,0x6711, +0x6712,0x6713,0x6716,0x6718,0x6719,0x671A,0x671C,0x671E, +0x6720,0x6721,0x6722,0x6723,0x6724,0x6725,0x6727,0x6729, +0x672E,0x6730,0x6732,0x6733,0x6736,0x6737,0x6738,0x6739, +0x673B,0x673C,0x673E,0x673F,0x6741,0x6744,0x6745,0x6747, +0x674A,0x674B,0x674D,0x6752,0x6754,0x6755,0x6757,0x6758, +0x6759,0x675A,0x675B,0x675D,0x6762,0x6763,0x6764,0x6766, +0x6767,0x676B,0x676C,0x676E,0x6771,0x6774,0x6776, 0, +0x6778,0x6779,0x677A,0x677B,0x677D,0x6780,0x6782,0x6783, +0x6785,0x6786,0x6788,0x678A,0x678C,0x678D,0x678E,0x678F, +0x6791,0x6792,0x6793,0x6794,0x6796,0x6799,0x679B,0x679F, +0x67A0,0x67A1,0x67A4,0x67A6,0x67A9,0x67AC,0x67AE,0x67B1, +0x67B2,0x67B4,0x67B9,0x67BA,0x67BB,0x67BC,0x67BD,0x67BE, +0x67BF,0x67C0,0x67C2,0x67C5,0x67C6,0x67C7,0x67C8,0x67C9, +0x67CA,0x67CB,0x67CC,0x67CD,0x67CE,0x67D5,0x67D6,0x67D7, +0x67DB,0x67DF,0x67E1,0x67E3,0x67E4,0x67E6,0x67E7,0x67E8, +0x67EA,0x67EB,0x67ED,0x67EE,0x67F2,0x67F5,0x67F6,0x67F7, +0x67F8,0x67F9,0x67FA,0x67FB,0x67FC,0x67FE,0x6801,0x6802, +0x6803,0x6804,0x6806,0x680D,0x6810,0x6812,0x6814,0x6815, +0x6818,0x6819,0x681A,0x681B,0x681C,0x681E,0x681F,0x6820, +0x6822,0x6823,0x6824,0x6825,0x6826,0x6827,0x6828,0x682B, +0x682C,0x682D,0x682E,0x682F,0x6830,0x6831,0x6834,0x6835, +0x6836,0x683A,0x683B,0x683F,0x6847,0x684B,0x684D,0x684F, +0x6852,0x6856,0x6857,0x6858,0x6859,0x685A,0x685B, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x685C,0x685D,0x685E,0x685F,0x686A,0x686C,0x686D,0x686E, +0x686F,0x6870,0x6871,0x6872,0x6873,0x6875,0x6878,0x6879, +0x687A,0x687B,0x687C,0x687D,0x687E,0x687F,0x6880,0x6882, +0x6884,0x6887,0x6888,0x6889,0x688A,0x688B,0x688C,0x688D, +0x688E,0x6890,0x6891,0x6892,0x6894,0x6895,0x6896,0x6898, +0x6899,0x689A,0x689B,0x689C,0x689D,0x689E,0x689F,0x68A0, +0x68A1,0x68A3,0x68A4,0x68A5,0x68A9,0x68AA,0x68AB,0x68AC, +0x68AE,0x68B1,0x68B2,0x68B4,0x68B6,0x68B7,0x68B8, 0, +0x68B9,0x68BA,0x68BB,0x68BC,0x68BD,0x68BE,0x68BF,0x68C1, +0x68C3,0x68C4,0x68C5,0x68C6,0x68C7,0x68C8,0x68CA,0x68CC, +0x68CE,0x68CF,0x68D0,0x68D1,0x68D3,0x68D4,0x68D6,0x68D7, +0x68D9,0x68DB,0x68DC,0x68DD,0x68DE,0x68DF,0x68E1,0x68E2, +0x68E4,0x68E5,0x68E6,0x68E7,0x68E8,0x68E9,0x68EA,0x68EB, +0x68EC,0x68ED,0x68EF,0x68F2,0x68F3,0x68F4,0x68F6,0x68F7, +0x68F8,0x68FB,0x68FD,0x68FE,0x68FF,0x6900,0x6902,0x6903, +0x6904,0x6906,0x6907,0x6908,0x6909,0x690A,0x690C,0x690F, +0x6911,0x6913,0x6914,0x6915,0x6916,0x6917,0x6918,0x6919, +0x691A,0x691B,0x691C,0x691D,0x691E,0x6921,0x6922,0x6923, +0x6925,0x6926,0x6927,0x6928,0x6929,0x692A,0x692B,0x692C, +0x692E,0x692F,0x6931,0x6932,0x6933,0x6935,0x6936,0x6937, +0x6938,0x693A,0x693B,0x693C,0x693E,0x6940,0x6941,0x6943, +0x6944,0x6945,0x6946,0x6947,0x6948,0x6949,0x694A,0x694B, +0x694C,0x694D,0x694E,0x694F,0x6950,0x6951,0x6952,0x6953, +0x6955,0x6956,0x6958,0x6959,0x695B,0x695C,0x695F, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x6961,0x6962,0x6964,0x6965,0x6967,0x6968,0x6969,0x696A, +0x696C,0x696D,0x696F,0x6970,0x6972,0x6973,0x6974,0x6975, +0x6976,0x697A,0x697B,0x697D,0x697E,0x697F,0x6981,0x6983, +0x6985,0x698A,0x698B,0x698C,0x698E,0x698F,0x6990,0x6991, +0x6992,0x6993,0x6996,0x6997,0x6999,0x699A,0x699D,0x699E, +0x699F,0x69A0,0x69A1,0x69A2,0x69A3,0x69A4,0x69A5,0x69A6, +0x69A9,0x69AA,0x69AC,0x69AE,0x69AF,0x69B0,0x69B2,0x69B3, +0x69B5,0x69B6,0x69B8,0x69B9,0x69BA,0x69BC,0x69BD, 0, +0x69BE,0x69BF,0x69C0,0x69C2,0x69C3,0x69C4,0x69C5,0x69C6, +0x69C7,0x69C8,0x69C9,0x69CB,0x69CD,0x69CF,0x69D1,0x69D2, +0x69D3,0x69D5,0x69D6,0x69D7,0x69D8,0x69D9,0x69DA,0x69DC, +0x69DD,0x69DE,0x69E1,0x69E2,0x69E3,0x69E4,0x69E5,0x69E6, +0x69E7,0x69E8,0x69E9,0x69EA,0x69EB,0x69EC,0x69EE,0x69EF, +0x69F0,0x69F1,0x69F3,0x69F4,0x69F5,0x69F6,0x69F7,0x69F8, +0x69F9,0x69FA,0x69FB,0x69FC,0x69FE,0x6A00,0x6A01,0x6A02, +0x6A03,0x6A04,0x6A05,0x6A06,0x6A07,0x6A08,0x6A09,0x6A0B, +0x6A0C,0x6A0D,0x6A0E,0x6A0F,0x6A10,0x6A11,0x6A12,0x6A13, +0x6A14,0x6A15,0x6A16,0x6A19,0x6A1A,0x6A1B,0x6A1C,0x6A1D, +0x6A1E,0x6A20,0x6A22,0x6A23,0x6A24,0x6A25,0x6A26,0x6A27, +0x6A29,0x6A2B,0x6A2C,0x6A2D,0x6A2E,0x6A30,0x6A32,0x6A33, +0x6A34,0x6A36,0x6A37,0x6A38,0x6A39,0x6A3A,0x6A3B,0x6A3C, +0x6A3F,0x6A40,0x6A41,0x6A42,0x6A43,0x6A45,0x6A46,0x6A48, +0x6A49,0x6A4A,0x6A4B,0x6A4C,0x6A4D,0x6A4E,0x6A4F,0x6A51, +0x6A52,0x6A53,0x6A54,0x6A55,0x6A56,0x6A57,0x6A5A, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x6A5C,0x6A5D,0x6A5E,0x6A5F,0x6A60,0x6A62,0x6A63,0x6A64, +0x6A66,0x6A67,0x6A68,0x6A69,0x6A6A,0x6A6B,0x6A6C,0x6A6D, +0x6A6E,0x6A6F,0x6A70,0x6A72,0x6A73,0x6A74,0x6A75,0x6A76, +0x6A77,0x6A78,0x6A7A,0x6A7B,0x6A7D,0x6A7E,0x6A7F,0x6A81, +0x6A82,0x6A83,0x6A85,0x6A86,0x6A87,0x6A88,0x6A89,0x6A8A, +0x6A8B,0x6A8C,0x6A8D,0x6A8F,0x6A92,0x6A93,0x6A94,0x6A95, +0x6A96,0x6A98,0x6A99,0x6A9A,0x6A9B,0x6A9C,0x6A9D,0x6A9E, +0x6A9F,0x6AA1,0x6AA2,0x6AA3,0x6AA4,0x6AA5,0x6AA6, 0, +0x6AA7,0x6AA8,0x6AAA,0x6AAD,0x6AAE,0x6AAF,0x6AB0,0x6AB1, +0x6AB2,0x6AB3,0x6AB4,0x6AB5,0x6AB6,0x6AB7,0x6AB8,0x6AB9, +0x6ABA,0x6ABB,0x6ABC,0x6ABD,0x6ABE,0x6ABF,0x6AC0,0x6AC1, +0x6AC2,0x6AC3,0x6AC4,0x6AC5,0x6AC6,0x6AC7,0x6AC8,0x6AC9, +0x6ACA,0x6ACB,0x6ACC,0x6ACD,0x6ACE,0x6ACF,0x6AD0,0x6AD1, +0x6AD2,0x6AD3,0x6AD4,0x6AD5,0x6AD6,0x6AD7,0x6AD8,0x6AD9, +0x6ADA,0x6ADB,0x6ADC,0x6ADD,0x6ADE,0x6ADF,0x6AE0,0x6AE1, +0x6AE2,0x6AE3,0x6AE4,0x6AE5,0x6AE6,0x6AE7,0x6AE8,0x6AE9, +0x6AEA,0x6AEB,0x6AEC,0x6AED,0x6AEE,0x6AEF,0x6AF0,0x6AF1, +0x6AF2,0x6AF3,0x6AF4,0x6AF5,0x6AF6,0x6AF7,0x6AF8,0x6AF9, +0x6AFA,0x6AFB,0x6AFC,0x6AFD,0x6AFE,0x6AFF,0x6B00,0x6B01, +0x6B02,0x6B03,0x6B04,0x6B05,0x6B06,0x6B07,0x6B08,0x6B09, +0x6B0A,0x6B0B,0x6B0C,0x6B0D,0x6B0E,0x6B0F,0x6B10,0x6B11, +0x6B12,0x6B13,0x6B14,0x6B15,0x6B16,0x6B17,0x6B18,0x6B19, +0x6B1A,0x6B1B,0x6B1C,0x6B1D,0x6B1E,0x6B1F,0x6B25,0x6B26, +0x6B28,0x6B29,0x6B2A,0x6B2B,0x6B2C,0x6B2D,0x6B2E, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x6B2F,0x6B30,0x6B31,0x6B33,0x6B34,0x6B35,0x6B36,0x6B38, +0x6B3B,0x6B3C,0x6B3D,0x6B3F,0x6B40,0x6B41,0x6B42,0x6B44, +0x6B45,0x6B48,0x6B4A,0x6B4B,0x6B4D,0x6B4E,0x6B4F,0x6B50, +0x6B51,0x6B52,0x6B53,0x6B54,0x6B55,0x6B56,0x6B57,0x6B58, +0x6B5A,0x6B5B,0x6B5C,0x6B5D,0x6B5E,0x6B5F,0x6B60,0x6B61, +0x6B68,0x6B69,0x6B6B,0x6B6C,0x6B6D,0x6B6E,0x6B6F,0x6B70, +0x6B71,0x6B72,0x6B73,0x6B74,0x6B75,0x6B76,0x6B77,0x6B78, +0x6B7A,0x6B7D,0x6B7E,0x6B7F,0x6B80,0x6B85,0x6B88, 0, +0x6B8C,0x6B8E,0x6B8F,0x6B90,0x6B91,0x6B94,0x6B95,0x6B97, +0x6B98,0x6B99,0x6B9C,0x6B9D,0x6B9E,0x6B9F,0x6BA0,0x6BA2, +0x6BA3,0x6BA4,0x6BA5,0x6BA6,0x6BA7,0x6BA8,0x6BA9,0x6BAB, +0x6BAC,0x6BAD,0x6BAE,0x6BAF,0x6BB0,0x6BB1,0x6BB2,0x6BB6, +0x6BB8,0x6BB9,0x6BBA,0x6BBB,0x6BBC,0x6BBD,0x6BBE,0x6BC0, +0x6BC3,0x6BC4,0x6BC6,0x6BC7,0x6BC8,0x6BC9,0x6BCA,0x6BCC, +0x6BCE,0x6BD0,0x6BD1,0x6BD8,0x6BDA,0x6BDC,0x6BDD,0x6BDE, +0x6BDF,0x6BE0,0x6BE2,0x6BE3,0x6BE4,0x6BE5,0x6BE6,0x6BE7, +0x6BE8,0x6BE9,0x6BEC,0x6BED,0x6BEE,0x6BF0,0x6BF1,0x6BF2, +0x6BF4,0x6BF6,0x6BF7,0x6BF8,0x6BFA,0x6BFB,0x6BFC,0x6BFE, +0x6BFF,0x6C00,0x6C01,0x6C02,0x6C03,0x6C04,0x6C08,0x6C09, +0x6C0A,0x6C0B,0x6C0C,0x6C0E,0x6C12,0x6C17,0x6C1C,0x6C1D, +0x6C1E,0x6C20,0x6C23,0x6C25,0x6C2B,0x6C2C,0x6C2D,0x6C31, +0x6C33,0x6C36,0x6C37,0x6C39,0x6C3A,0x6C3B,0x6C3C,0x6C3E, +0x6C3F,0x6C43,0x6C44,0x6C45,0x6C48,0x6C4B,0x6C4C,0x6C4D, +0x6C4E,0x6C4F,0x6C51,0x6C52,0x6C53,0x6C56,0x6C58, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x6C59,0x6C5A,0x6C62,0x6C63,0x6C65,0x6C66,0x6C67,0x6C6B, +0x6C6C,0x6C6D,0x6C6E,0x6C6F,0x6C71,0x6C73,0x6C75,0x6C77, +0x6C78,0x6C7A,0x6C7B,0x6C7C,0x6C7F,0x6C80,0x6C84,0x6C87, +0x6C8A,0x6C8B,0x6C8D,0x6C8E,0x6C91,0x6C92,0x6C95,0x6C96, +0x6C97,0x6C98,0x6C9A,0x6C9C,0x6C9D,0x6C9E,0x6CA0,0x6CA2, +0x6CA8,0x6CAC,0x6CAF,0x6CB0,0x6CB4,0x6CB5,0x6CB6,0x6CB7, +0x6CBA,0x6CC0,0x6CC1,0x6CC2,0x6CC3,0x6CC6,0x6CC7,0x6CC8, +0x6CCB,0x6CCD,0x6CCE,0x6CCF,0x6CD1,0x6CD2,0x6CD8, 0, +0x6CD9,0x6CDA,0x6CDC,0x6CDD,0x6CDF,0x6CE4,0x6CE6,0x6CE7, +0x6CE9,0x6CEC,0x6CED,0x6CF2,0x6CF4,0x6CF9,0x6CFF,0x6D00, +0x6D02,0x6D03,0x6D05,0x6D06,0x6D08,0x6D09,0x6D0A,0x6D0D, +0x6D0F,0x6D10,0x6D11,0x6D13,0x6D14,0x6D15,0x6D16,0x6D18, +0x6D1C,0x6D1D,0x6D1F,0x6D20,0x6D21,0x6D22,0x6D23,0x6D24, +0x6D26,0x6D28,0x6D29,0x6D2C,0x6D2D,0x6D2F,0x6D30,0x6D34, +0x6D36,0x6D37,0x6D38,0x6D3A,0x6D3F,0x6D40,0x6D42,0x6D44, +0x6D49,0x6D4C,0x6D50,0x6D55,0x6D56,0x6D57,0x6D58,0x6D5B, +0x6D5D,0x6D5F,0x6D61,0x6D62,0x6D64,0x6D65,0x6D67,0x6D68, +0x6D6B,0x6D6C,0x6D6D,0x6D70,0x6D71,0x6D72,0x6D73,0x6D75, +0x6D76,0x6D79,0x6D7A,0x6D7B,0x6D7D,0x6D7E,0x6D7F,0x6D80, +0x6D81,0x6D83,0x6D84,0x6D86,0x6D87,0x6D8A,0x6D8B,0x6D8D, +0x6D8F,0x6D90,0x6D92,0x6D96,0x6D97,0x6D98,0x6D99,0x6D9A, +0x6D9C,0x6DA2,0x6DA5,0x6DAC,0x6DAD,0x6DB0,0x6DB1,0x6DB3, +0x6DB4,0x6DB6,0x6DB7,0x6DB9,0x6DBA,0x6DBB,0x6DBC,0x6DBD, +0x6DBE,0x6DC1,0x6DC2,0x6DC3,0x6DC8,0x6DC9,0x6DCA, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x6DCD,0x6DCE,0x6DCF,0x6DD0,0x6DD2,0x6DD3,0x6DD4,0x6DD5, +0x6DD7,0x6DDA,0x6DDB,0x6DDC,0x6DDF,0x6DE2,0x6DE3,0x6DE5, +0x6DE7,0x6DE8,0x6DE9,0x6DEA,0x6DED,0x6DEF,0x6DF0,0x6DF2, +0x6DF4,0x6DF5,0x6DF6,0x6DF8,0x6DFA,0x6DFD,0x6DFE,0x6DFF, +0x6E00,0x6E01,0x6E02,0x6E03,0x6E04,0x6E06,0x6E07,0x6E08, +0x6E09,0x6E0B,0x6E0F,0x6E12,0x6E13,0x6E15,0x6E18,0x6E19, +0x6E1B,0x6E1C,0x6E1E,0x6E1F,0x6E22,0x6E26,0x6E27,0x6E28, +0x6E2A,0x6E2C,0x6E2E,0x6E30,0x6E31,0x6E33,0x6E35, 0, +0x6E36,0x6E37,0x6E39,0x6E3B,0x6E3C,0x6E3D,0x6E3E,0x6E3F, +0x6E40,0x6E41,0x6E42,0x6E45,0x6E46,0x6E47,0x6E48,0x6E49, +0x6E4A,0x6E4B,0x6E4C,0x6E4F,0x6E50,0x6E51,0x6E52,0x6E55, +0x6E57,0x6E59,0x6E5A,0x6E5C,0x6E5D,0x6E5E,0x6E60,0x6E61, +0x6E62,0x6E63,0x6E64,0x6E65,0x6E66,0x6E67,0x6E68,0x6E69, +0x6E6A,0x6E6C,0x6E6D,0x6E6F,0x6E70,0x6E71,0x6E72,0x6E73, +0x6E74,0x6E75,0x6E76,0x6E77,0x6E78,0x6E79,0x6E7A,0x6E7B, +0x6E7C,0x6E7D,0x6E80,0x6E81,0x6E82,0x6E84,0x6E87,0x6E88, +0x6E8A,0x6E8B,0x6E8C,0x6E8D,0x6E8E,0x6E91,0x6E92,0x6E93, +0x6E94,0x6E95,0x6E96,0x6E97,0x6E99,0x6E9A,0x6E9B,0x6E9D, +0x6E9E,0x6EA0,0x6EA1,0x6EA3,0x6EA4,0x6EA6,0x6EA8,0x6EA9, +0x6EAB,0x6EAC,0x6EAD,0x6EAE,0x6EB0,0x6EB3,0x6EB5,0x6EB8, +0x6EB9,0x6EBC,0x6EBE,0x6EBF,0x6EC0,0x6EC3,0x6EC4,0x6EC5, +0x6EC6,0x6EC8,0x6EC9,0x6ECA,0x6ECC,0x6ECD,0x6ECE,0x6ED0, +0x6ED2,0x6ED6,0x6ED8,0x6ED9,0x6EDB,0x6EDC,0x6EDD,0x6EE3, +0x6EE7,0x6EEA,0x6EEB,0x6EEC,0x6EED,0x6EEE,0x6EEF, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x6EF0,0x6EF1,0x6EF2,0x6EF3,0x6EF5,0x6EF6,0x6EF7,0x6EF8, +0x6EFA,0x6EFB,0x6EFC,0x6EFD,0x6EFE,0x6EFF,0x6F00,0x6F01, +0x6F03,0x6F04,0x6F05,0x6F07,0x6F08,0x6F0A,0x6F0B,0x6F0C, +0x6F0D,0x6F0E,0x6F10,0x6F11,0x6F12,0x6F16,0x6F17,0x6F18, +0x6F19,0x6F1A,0x6F1B,0x6F1C,0x6F1D,0x6F1E,0x6F1F,0x6F21, +0x6F22,0x6F23,0x6F25,0x6F26,0x6F27,0x6F28,0x6F2C,0x6F2E, +0x6F30,0x6F32,0x6F34,0x6F35,0x6F37,0x6F38,0x6F39,0x6F3A, +0x6F3B,0x6F3C,0x6F3D,0x6F3F,0x6F40,0x6F41,0x6F42, 0, +0x6F43,0x6F44,0x6F45,0x6F48,0x6F49,0x6F4A,0x6F4C,0x6F4E, +0x6F4F,0x6F50,0x6F51,0x6F52,0x6F53,0x6F54,0x6F55,0x6F56, +0x6F57,0x6F59,0x6F5A,0x6F5B,0x6F5D,0x6F5F,0x6F60,0x6F61, +0x6F63,0x6F64,0x6F65,0x6F67,0x6F68,0x6F69,0x6F6A,0x6F6B, +0x6F6C,0x6F6F,0x6F70,0x6F71,0x6F73,0x6F75,0x6F76,0x6F77, +0x6F79,0x6F7B,0x6F7D,0x6F7E,0x6F7F,0x6F80,0x6F81,0x6F82, +0x6F83,0x6F85,0x6F86,0x6F87,0x6F8A,0x6F8B,0x6F8F,0x6F90, +0x6F91,0x6F92,0x6F93,0x6F94,0x6F95,0x6F96,0x6F97,0x6F98, +0x6F99,0x6F9A,0x6F9B,0x6F9D,0x6F9E,0x6F9F,0x6FA0,0x6FA2, +0x6FA3,0x6FA4,0x6FA5,0x6FA6,0x6FA8,0x6FA9,0x6FAA,0x6FAB, +0x6FAC,0x6FAD,0x6FAE,0x6FAF,0x6FB0,0x6FB1,0x6FB2,0x6FB4, +0x6FB5,0x6FB7,0x6FB8,0x6FBA,0x6FBB,0x6FBC,0x6FBD,0x6FBE, +0x6FBF,0x6FC1,0x6FC3,0x6FC4,0x6FC5,0x6FC6,0x6FC7,0x6FC8, +0x6FCA,0x6FCB,0x6FCC,0x6FCD,0x6FCE,0x6FCF,0x6FD0,0x6FD3, +0x6FD4,0x6FD5,0x6FD6,0x6FD7,0x6FD8,0x6FD9,0x6FDA,0x6FDB, +0x6FDC,0x6FDD,0x6FDF,0x6FE2,0x6FE3,0x6FE4,0x6FE5, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x6FE6,0x6FE7,0x6FE8,0x6FE9,0x6FEA,0x6FEB,0x6FEC,0x6FED, +0x6FF0,0x6FF1,0x6FF2,0x6FF3,0x6FF4,0x6FF5,0x6FF6,0x6FF7, +0x6FF8,0x6FF9,0x6FFA,0x6FFB,0x6FFC,0x6FFD,0x6FFE,0x6FFF, +0x7000,0x7001,0x7002,0x7003,0x7004,0x7005,0x7006,0x7007, +0x7008,0x7009,0x700A,0x700B,0x700C,0x700D,0x700E,0x700F, +0x7010,0x7012,0x7013,0x7014,0x7015,0x7016,0x7017,0x7018, +0x7019,0x701C,0x701D,0x701E,0x701F,0x7020,0x7021,0x7022, +0x7024,0x7025,0x7026,0x7027,0x7028,0x7029,0x702A, 0, +0x702B,0x702C,0x702D,0x702E,0x702F,0x7030,0x7031,0x7032, +0x7033,0x7034,0x7036,0x7037,0x7038,0x703A,0x703B,0x703C, +0x703D,0x703E,0x703F,0x7040,0x7041,0x7042,0x7043,0x7044, +0x7045,0x7046,0x7047,0x7048,0x7049,0x704A,0x704B,0x704D, +0x704E,0x7050,0x7051,0x7052,0x7053,0x7054,0x7055,0x7056, +0x7057,0x7058,0x7059,0x705A,0x705B,0x705C,0x705D,0x705F, +0x7060,0x7061,0x7062,0x7063,0x7064,0x7065,0x7066,0x7067, +0x7068,0x7069,0x706A,0x706E,0x7071,0x7072,0x7073,0x7074, +0x7077,0x7079,0x707A,0x707B,0x707D,0x7081,0x7082,0x7083, +0x7084,0x7086,0x7087,0x7088,0x708B,0x708C,0x708D,0x708F, +0x7090,0x7091,0x7093,0x7097,0x7098,0x709A,0x709B,0x709E, +0x709F,0x70A0,0x70A1,0x70A2,0x70A3,0x70A4,0x70A5,0x70A6, +0x70A7,0x70A8,0x70A9,0x70AA,0x70B0,0x70B2,0x70B4,0x70B5, +0x70B6,0x70BA,0x70BE,0x70BF,0x70C4,0x70C5,0x70C6,0x70C7, +0x70C9,0x70CB,0x70CC,0x70CD,0x70CE,0x70CF,0x70D0,0x70D1, +0x70D2,0x70D3,0x70D4,0x70D5,0x70D6,0x70D7,0x70DA, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x70DC,0x70DD,0x70DE,0x70E0,0x70E1,0x70E2,0x70E3,0x70E5, +0x70EA,0x70EE,0x70F0,0x70F1,0x70F2,0x70F3,0x70F4,0x70F5, +0x70F6,0x70F8,0x70FA,0x70FB,0x70FC,0x70FE,0x70FF,0x7100, +0x7101,0x7102,0x7103,0x7104,0x7105,0x7106,0x7107,0x7108, +0x710B,0x710C,0x710D,0x710E,0x710F,0x7111,0x7112,0x7114, +0x7117,0x711B,0x711C,0x711D,0x711E,0x711F,0x7120,0x7121, +0x7122,0x7123,0x7124,0x7125,0x7127,0x7128,0x7129,0x712A, +0x712B,0x712C,0x712D,0x712E,0x7132,0x7133,0x7134, 0, +0x7135,0x7137,0x7138,0x7139,0x713A,0x713B,0x713C,0x713D, +0x713E,0x713F,0x7140,0x7141,0x7142,0x7143,0x7144,0x7146, +0x7147,0x7148,0x7149,0x714B,0x714D,0x714F,0x7150,0x7151, +0x7152,0x7153,0x7154,0x7155,0x7156,0x7157,0x7158,0x7159, +0x715A,0x715B,0x715D,0x715F,0x7160,0x7161,0x7162,0x7163, +0x7165,0x7169,0x716A,0x716B,0x716C,0x716D,0x716F,0x7170, +0x7171,0x7174,0x7175,0x7176,0x7177,0x7179,0x717B,0x717C, +0x717E,0x717F,0x7180,0x7181,0x7182,0x7183,0x7185,0x7186, +0x7187,0x7188,0x7189,0x718B,0x718C,0x718D,0x718E,0x7190, +0x7191,0x7192,0x7193,0x7195,0x7196,0x7197,0x719A,0x719B, +0x719C,0x719D,0x719E,0x71A1,0x71A2,0x71A3,0x71A4,0x71A5, +0x71A6,0x71A7,0x71A9,0x71AA,0x71AB,0x71AD,0x71AE,0x71AF, +0x71B0,0x71B1,0x71B2,0x71B4,0x71B6,0x71B7,0x71B8,0x71BA, +0x71BB,0x71BC,0x71BD,0x71BE,0x71BF,0x71C0,0x71C1,0x71C2, +0x71C4,0x71C5,0x71C6,0x71C7,0x71C8,0x71C9,0x71CA,0x71CB, +0x71CC,0x71CD,0x71CF,0x71D0,0x71D1,0x71D2,0x71D3, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x71D6,0x71D7,0x71D8,0x71D9,0x71DA,0x71DB,0x71DC,0x71DD, +0x71DE,0x71DF,0x71E1,0x71E2,0x71E3,0x71E4,0x71E6,0x71E8, +0x71E9,0x71EA,0x71EB,0x71EC,0x71ED,0x71EF,0x71F0,0x71F1, +0x71F2,0x71F3,0x71F4,0x71F5,0x71F6,0x71F7,0x71F8,0x71FA, +0x71FB,0x71FC,0x71FD,0x71FE,0x71FF,0x7200,0x7201,0x7202, +0x7203,0x7204,0x7205,0x7207,0x7208,0x7209,0x720A,0x720B, +0x720C,0x720D,0x720E,0x720F,0x7210,0x7211,0x7212,0x7213, +0x7214,0x7215,0x7216,0x7217,0x7218,0x7219,0x721A, 0, +0x721B,0x721C,0x721E,0x721F,0x7220,0x7221,0x7222,0x7223, +0x7224,0x7225,0x7226,0x7227,0x7229,0x722B,0x722D,0x722E, +0x722F,0x7232,0x7233,0x7234,0x723A,0x723C,0x723E,0x7240, +0x7241,0x7242,0x7243,0x7244,0x7245,0x7246,0x7249,0x724A, +0x724B,0x724E,0x724F,0x7250,0x7251,0x7253,0x7254,0x7255, +0x7257,0x7258,0x725A,0x725C,0x725E,0x7260,0x7263,0x7264, +0x7265,0x7268,0x726A,0x726B,0x726C,0x726D,0x7270,0x7271, +0x7273,0x7274,0x7276,0x7277,0x7278,0x727B,0x727C,0x727D, +0x7282,0x7283,0x7285,0x7286,0x7287,0x7288,0x7289,0x728C, +0x728E,0x7290,0x7291,0x7293,0x7294,0x7295,0x7296,0x7297, +0x7298,0x7299,0x729A,0x729B,0x729C,0x729D,0x729E,0x72A0, +0x72A1,0x72A2,0x72A3,0x72A4,0x72A5,0x72A6,0x72A7,0x72A8, +0x72A9,0x72AA,0x72AB,0x72AE,0x72B1,0x72B2,0x72B3,0x72B5, +0x72BA,0x72BB,0x72BC,0x72BD,0x72BE,0x72BF,0x72C0,0x72C5, +0x72C6,0x72C7,0x72C9,0x72CA,0x72CB,0x72CC,0x72CF,0x72D1, +0x72D3,0x72D4,0x72D5,0x72D6,0x72D8,0x72DA,0x72DB, 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, 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, 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, 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,0x3000,0x3001,0x3002,0x00B7,0x02C9,0x02C7,0x00A8, +0x3003,0x3005,0x2014,0xFF5E,0x2016,0x2026,0x2018,0x2019, +0x201C,0x201D,0x3014,0x3015,0x3008,0x3009,0x300A,0x300B, +0x300C,0x300D,0x300E,0x300F,0x3016,0x3017,0x3010,0x3011, +0x00B1,0x00D7,0x00F7,0x2236,0x2227,0x2228,0x2211,0x220F, +0x222A,0x2229,0x2208,0x2237,0x221A,0x22A5,0x2225,0x2220, +0x2312,0x2299,0x222B,0x222E,0x2261,0x224C,0x2248,0x223D, +0x221D,0x2260,0x226E,0x226F,0x2264,0x2265,0x221E,0x2235, +0x2234,0x2642,0x2640,0x00B0,0x2032,0x2033,0x2103,0xFF04, +0x00A4,0xFFE0,0xFFE1,0x2030,0x00A7,0x2116,0x2606,0x2605, +0x25CB,0x25CF,0x25CE,0x25C7,0x25C6,0x25A1,0x25A0,0x25B3, +0x25B2,0x203B,0x2192,0x2190,0x2191,0x2193,0x3013, 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, 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, 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, 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,0x2170,0x2171,0x2172,0x2173,0x2174,0x2175,0x2176, +0x2177,0x2178,0x2179, 0, 0, 0, 0, 0, + 0,0x2488,0x2489,0x248A,0x248B,0x248C,0x248D,0x248E, +0x248F,0x2490,0x2491,0x2492,0x2493,0x2494,0x2495,0x2496, +0x2497,0x2498,0x2499,0x249A,0x249B,0x2474,0x2475,0x2476, +0x2477,0x2478,0x2479,0x247A,0x247B,0x247C,0x247D,0x247E, +0x247F,0x2480,0x2481,0x2482,0x2483,0x2484,0x2485,0x2486, +0x2487,0x2460,0x2461,0x2462,0x2463,0x2464,0x2465,0x2466, +0x2467,0x2468,0x2469, 0, 0,0x3220,0x3221,0x3222, +0x3223,0x3224,0x3225,0x3226,0x3227,0x3228,0x3229, 0, + 0,0x2160,0x2161,0x2162,0x2163,0x2164,0x2165,0x2166, +0x2167,0x2168,0x2169,0x216A,0x216B, 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, 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, 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, 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,0xFF01,0xFF02,0xFF03,0xFFE5,0xFF05,0xFF06,0xFF07, +0xFF08,0xFF09,0xFF0A,0xFF0B,0xFF0C,0xFF0D,0xFF0E,0xFF0F, +0xFF10,0xFF11,0xFF12,0xFF13,0xFF14,0xFF15,0xFF16,0xFF17, +0xFF18,0xFF19,0xFF1A,0xFF1B,0xFF1C,0xFF1D,0xFF1E,0xFF1F, +0xFF20,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,0xFF3B,0xFF3C,0xFF3D,0xFF3E,0xFF3F, +0xFF40,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,0xFF5B,0xFF5C,0xFF5D,0xFFE3, 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, 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, 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, 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,0x3041,0x3042,0x3043,0x3044,0x3045,0x3046,0x3047, +0x3048,0x3049,0x304A,0x304B,0x304C,0x304D,0x304E,0x304F, +0x3050,0x3051,0x3052,0x3053,0x3054,0x3055,0x3056,0x3057, +0x3058,0x3059,0x305A,0x305B,0x305C,0x305D,0x305E,0x305F, +0x3060,0x3061,0x3062,0x3063,0x3064,0x3065,0x3066,0x3067, +0x3068,0x3069,0x306A,0x306B,0x306C,0x306D,0x306E,0x306F, +0x3070,0x3071,0x3072,0x3073,0x3074,0x3075,0x3076,0x3077, +0x3078,0x3079,0x307A,0x307B,0x307C,0x307D,0x307E,0x307F, +0x3080,0x3081,0x3082,0x3083,0x3084,0x3085,0x3086,0x3087, +0x3088,0x3089,0x308A,0x308B,0x308C,0x308D,0x308E,0x308F, +0x3090,0x3091,0x3092,0x3093, 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, + 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, 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, + 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,0x30A1,0x30A2,0x30A3,0x30A4,0x30A5,0x30A6,0x30A7, +0x30A8,0x30A9,0x30AA,0x30AB,0x30AC,0x30AD,0x30AE,0x30AF, +0x30B0,0x30B1,0x30B2,0x30B3,0x30B4,0x30B5,0x30B6,0x30B7, +0x30B8,0x30B9,0x30BA,0x30BB,0x30BC,0x30BD,0x30BE,0x30BF, +0x30C0,0x30C1,0x30C2,0x30C3,0x30C4,0x30C5,0x30C6,0x30C7, +0x30C8,0x30C9,0x30CA,0x30CB,0x30CC,0x30CD,0x30CE,0x30CF, +0x30D0,0x30D1,0x30D2,0x30D3,0x30D4,0x30D5,0x30D6,0x30D7, +0x30D8,0x30D9,0x30DA,0x30DB,0x30DC,0x30DD,0x30DE,0x30DF, +0x30E0,0x30E1,0x30E2,0x30E3,0x30E4,0x30E5,0x30E6,0x30E7, +0x30E8,0x30E9,0x30EA,0x30EB,0x30EC,0x30ED,0x30EE,0x30EF, +0x30F0,0x30F1,0x30F2,0x30F3,0x30F4,0x30F5,0x30F6, 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, 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, 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, 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,0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397, +0x0398,0x0399,0x039A,0x039B,0x039C,0x039D,0x039E,0x039F, +0x03A0,0x03A1,0x03A3,0x03A4,0x03A5,0x03A6,0x03A7,0x03A8, +0x03A9, 0, 0, 0, 0, 0, 0, 0, + 0,0x03B1,0x03B2,0x03B3,0x03B4,0x03B5,0x03B6,0x03B7, +0x03B8,0x03B9,0x03BA,0x03BB,0x03BC,0x03BD,0x03BE,0x03BF, +0x03C0,0x03C1,0x03C3,0x03C4,0x03C5,0x03C6,0x03C7,0x03C8, +0x03C9, 0, 0, 0, 0, 0, 0, 0, +0xFE35,0xFE36,0xFE39,0xFE3A,0xFE3F,0xFE40,0xFE3D,0xFE3E, +0xFE41,0xFE42,0xFE43,0xFE44, 0, 0,0xFE3B,0xFE3C, +0xFE37,0xFE38,0xFE31, 0,0xFE33,0xFE34, 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, 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, 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, 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,0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0401, +0x0416,0x0417,0x0418,0x0419,0x041A,0x041B,0x041C,0x041D, +0x041E,0x041F,0x0420,0x0421,0x0422,0x0423,0x0424,0x0425, +0x0426,0x0427,0x0428,0x0429,0x042A,0x042B,0x042C,0x042D, +0x042E,0x042F, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0,0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0451, +0x0436,0x0437,0x0438,0x0439,0x043A,0x043B,0x043C,0x043D, +0x043E,0x043F,0x0440,0x0441,0x0442,0x0443,0x0444,0x0445, +0x0446,0x0447,0x0448,0x0449,0x044A,0x044B,0x044C,0x044D, +0x044E,0x044F, 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, 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, +0x02CA,0x02CB,0x02D9,0x2013,0x2015,0x2025,0x2035,0x2105, +0x2109,0x2196,0x2197,0x2198,0x2199,0x2215,0x221F,0x2223, +0x2252,0x2266,0x2267,0x22BF,0x2550,0x2551,0x2552,0x2553, +0x2554,0x2555,0x2556,0x2557,0x2558,0x2559,0x255A,0x255B, +0x255C,0x255D,0x255E,0x255F,0x2560,0x2561,0x2562,0x2563, +0x2564,0x2565,0x2566,0x2567,0x2568,0x2569,0x256A,0x256B, +0x256C,0x256D,0x256E,0x256F,0x2570,0x2571,0x2572,0x2573, +0x2581,0x2582,0x2583,0x2584,0x2585,0x2586,0x2587, 0, +0x2588,0x2589,0x258A,0x258B,0x258C,0x258D,0x258E,0x258F, +0x2593,0x2594,0x2595,0x25BC,0x25BD,0x25E2,0x25E3,0x25E4, +0x25E5,0x2609,0x2295,0x3012,0x301D,0x301E, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0,0x0101,0x00E1,0x01CE,0x00E0,0x0113,0x00E9,0x011B, +0x00E8,0x012B,0x00ED,0x01D0,0x00EC,0x014D,0x00F3,0x01D2, +0x00F2,0x016B,0x00FA,0x01D4,0x00F9,0x01D6,0x01D8,0x01DA, +0x01DC,0x00FC,0x00EA,0x0251, 0,0x0144,0x0148, 0, +0x0261, 0, 0, 0, 0,0x3105,0x3106,0x3107, +0x3108,0x3109,0x310A,0x310B,0x310C,0x310D,0x310E,0x310F, +0x3110,0x3111,0x3112,0x3113,0x3114,0x3115,0x3116,0x3117, +0x3118,0x3119,0x311A,0x311B,0x311C,0x311D,0x311E,0x311F, +0x3120,0x3121,0x3122,0x3123,0x3124,0x3125,0x3126,0x3127, +0x3128,0x3129, 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, 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, +0x3021,0x3022,0x3023,0x3024,0x3025,0x3026,0x3027,0x3028, +0x3029,0x32A3,0x338E,0x338F,0x339C,0x339D,0x339E,0x33A1, +0x33C4,0x33CE,0x33D1,0x33D2,0x33D5,0xFE30,0xFFE2,0xFFE4, + 0,0x2121,0x3231, 0,0x2010, 0, 0, 0, +0x30FC,0x309B,0x309C,0x30FD,0x30FE,0x3006,0x309D,0x309E, +0xFE49,0xFE4A,0xFE4B,0xFE4C,0xFE4D,0xFE4E,0xFE4F,0xFE50, +0xFE51,0xFE52,0xFE54,0xFE55,0xFE56,0xFE57,0xFE59,0xFE5A, +0xFE5B,0xFE5C,0xFE5D,0xFE5E,0xFE5F,0xFE60,0xFE61, 0, +0xFE62,0xFE63,0xFE64,0xFE65,0xFE66,0xFE68,0xFE69,0xFE6A, +0xFE6B, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,0x3007, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,0x2500,0x2501,0x2502,0x2503, +0x2504,0x2505,0x2506,0x2507,0x2508,0x2509,0x250A,0x250B, +0x250C,0x250D,0x250E,0x250F,0x2510,0x2511,0x2512,0x2513, +0x2514,0x2515,0x2516,0x2517,0x2518,0x2519,0x251A,0x251B, +0x251C,0x251D,0x251E,0x251F,0x2520,0x2521,0x2522,0x2523, +0x2524,0x2525,0x2526,0x2527,0x2528,0x2529,0x252A,0x252B, +0x252C,0x252D,0x252E,0x252F,0x2530,0x2531,0x2532,0x2533, +0x2534,0x2535,0x2536,0x2537,0x2538,0x2539,0x253A,0x253B, +0x253C,0x253D,0x253E,0x253F,0x2540,0x2541,0x2542,0x2543, +0x2544,0x2545,0x2546,0x2547,0x2548,0x2549,0x254A,0x254B, + 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, 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, +0x72DC,0x72DD,0x72DF,0x72E2,0x72E3,0x72E4,0x72E5,0x72E6, +0x72E7,0x72EA,0x72EB,0x72F5,0x72F6,0x72F9,0x72FD,0x72FE, +0x72FF,0x7300,0x7302,0x7304,0x7305,0x7306,0x7307,0x7308, +0x7309,0x730B,0x730C,0x730D,0x730F,0x7310,0x7311,0x7312, +0x7314,0x7318,0x7319,0x731A,0x731F,0x7320,0x7323,0x7324, +0x7326,0x7327,0x7328,0x732D,0x732F,0x7330,0x7332,0x7333, +0x7335,0x7336,0x733A,0x733B,0x733C,0x733D,0x7340,0x7341, +0x7342,0x7343,0x7344,0x7345,0x7346,0x7347,0x7348, 0, +0x7349,0x734A,0x734B,0x734C,0x734E,0x734F,0x7351,0x7353, +0x7354,0x7355,0x7356,0x7358,0x7359,0x735A,0x735B,0x735C, +0x735D,0x735E,0x735F,0x7361,0x7362,0x7363,0x7364,0x7365, +0x7366,0x7367,0x7368,0x7369,0x736A,0x736B,0x736E,0x7370, +0x7371, 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, 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, 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, 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, +0x7372,0x7373,0x7374,0x7375,0x7376,0x7377,0x7378,0x7379, +0x737A,0x737B,0x737C,0x737D,0x737F,0x7380,0x7381,0x7382, +0x7383,0x7385,0x7386,0x7388,0x738A,0x738C,0x738D,0x738F, +0x7390,0x7392,0x7393,0x7394,0x7395,0x7397,0x7398,0x7399, +0x739A,0x739C,0x739D,0x739E,0x73A0,0x73A1,0x73A3,0x73A4, +0x73A5,0x73A6,0x73A7,0x73A8,0x73AA,0x73AC,0x73AD,0x73B1, +0x73B4,0x73B5,0x73B6,0x73B8,0x73B9,0x73BC,0x73BD,0x73BE, +0x73BF,0x73C1,0x73C3,0x73C4,0x73C5,0x73C6,0x73C7, 0, +0x73CB,0x73CC,0x73CE,0x73D2,0x73D3,0x73D4,0x73D5,0x73D6, +0x73D7,0x73D8,0x73DA,0x73DB,0x73DC,0x73DD,0x73DF,0x73E1, +0x73E2,0x73E3,0x73E4,0x73E6,0x73E8,0x73EA,0x73EB,0x73EC, +0x73EE,0x73EF,0x73F0,0x73F1,0x73F3,0x73F4,0x73F5,0x73F6, +0x73F7, 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, 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, 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, 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, +0x73F8,0x73F9,0x73FA,0x73FB,0x73FC,0x73FD,0x73FE,0x73FF, +0x7400,0x7401,0x7402,0x7404,0x7407,0x7408,0x740B,0x740C, +0x740D,0x740E,0x7411,0x7412,0x7413,0x7414,0x7415,0x7416, +0x7417,0x7418,0x7419,0x741C,0x741D,0x741E,0x741F,0x7420, +0x7421,0x7423,0x7424,0x7427,0x7429,0x742B,0x742D,0x742F, +0x7431,0x7432,0x7437,0x7438,0x7439,0x743A,0x743B,0x743D, +0x743E,0x743F,0x7440,0x7442,0x7443,0x7444,0x7445,0x7446, +0x7447,0x7448,0x7449,0x744A,0x744B,0x744C,0x744D, 0, +0x744E,0x744F,0x7450,0x7451,0x7452,0x7453,0x7454,0x7456, +0x7458,0x745D,0x7460,0x7461,0x7462,0x7463,0x7464,0x7465, +0x7466,0x7467,0x7468,0x7469,0x746A,0x746B,0x746C,0x746E, +0x746F,0x7471,0x7472,0x7473,0x7474,0x7475,0x7478,0x7479, +0x747A, 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, 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, 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, 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, +0x747B,0x747C,0x747D,0x747F,0x7482,0x7484,0x7485,0x7486, +0x7488,0x7489,0x748A,0x748C,0x748D,0x748F,0x7491,0x7492, +0x7493,0x7494,0x7495,0x7496,0x7497,0x7498,0x7499,0x749A, +0x749B,0x749D,0x749F,0x74A0,0x74A1,0x74A2,0x74A3,0x74A4, +0x74A5,0x74A6,0x74AA,0x74AB,0x74AC,0x74AD,0x74AE,0x74AF, +0x74B0,0x74B1,0x74B2,0x74B3,0x74B4,0x74B5,0x74B6,0x74B7, +0x74B8,0x74B9,0x74BB,0x74BC,0x74BD,0x74BE,0x74BF,0x74C0, +0x74C1,0x74C2,0x74C3,0x74C4,0x74C5,0x74C6,0x74C7, 0, +0x74C8,0x74C9,0x74CA,0x74CB,0x74CC,0x74CD,0x74CE,0x74CF, +0x74D0,0x74D1,0x74D3,0x74D4,0x74D5,0x74D6,0x74D7,0x74D8, +0x74D9,0x74DA,0x74DB,0x74DD,0x74DF,0x74E1,0x74E5,0x74E7, +0x74E8,0x74E9,0x74EA,0x74EB,0x74EC,0x74ED,0x74F0,0x74F1, +0x74F2, 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, 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, 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, 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, +0x74F3,0x74F5,0x74F8,0x74F9,0x74FA,0x74FB,0x74FC,0x74FD, +0x74FE,0x7500,0x7501,0x7502,0x7503,0x7505,0x7506,0x7507, +0x7508,0x7509,0x750A,0x750B,0x750C,0x750E,0x7510,0x7512, +0x7514,0x7515,0x7516,0x7517,0x751B,0x751D,0x751E,0x7520, +0x7521,0x7522,0x7523,0x7524,0x7526,0x7527,0x752A,0x752E, +0x7534,0x7536,0x7539,0x753C,0x753D,0x753F,0x7541,0x7542, +0x7543,0x7544,0x7546,0x7547,0x7549,0x754A,0x754D,0x7550, +0x7551,0x7552,0x7553,0x7555,0x7556,0x7557,0x7558, 0, +0x755D,0x755E,0x755F,0x7560,0x7561,0x7562,0x7563,0x7564, +0x7567,0x7568,0x7569,0x756B,0x756C,0x756D,0x756E,0x756F, +0x7570,0x7571,0x7573,0x7575,0x7576,0x7577,0x757A,0x757B, +0x757C,0x757D,0x757E,0x7580,0x7581,0x7582,0x7584,0x7585, +0x7587, 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, 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, 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, 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, +0x7588,0x7589,0x758A,0x758C,0x758D,0x758E,0x7590,0x7593, +0x7595,0x7598,0x759B,0x759C,0x759E,0x75A2,0x75A6,0x75A7, +0x75A8,0x75A9,0x75AA,0x75AD,0x75B6,0x75B7,0x75BA,0x75BB, +0x75BF,0x75C0,0x75C1,0x75C6,0x75CB,0x75CC,0x75CE,0x75CF, +0x75D0,0x75D1,0x75D3,0x75D7,0x75D9,0x75DA,0x75DC,0x75DD, +0x75DF,0x75E0,0x75E1,0x75E5,0x75E9,0x75EC,0x75ED,0x75EE, +0x75EF,0x75F2,0x75F3,0x75F5,0x75F6,0x75F7,0x75F8,0x75FA, +0x75FB,0x75FD,0x75FE,0x7602,0x7604,0x7606,0x7607, 0, +0x7608,0x7609,0x760B,0x760D,0x760E,0x760F,0x7611,0x7612, +0x7613,0x7614,0x7616,0x761A,0x761C,0x761D,0x761E,0x7621, +0x7623,0x7627,0x7628,0x762C,0x762E,0x762F,0x7631,0x7632, +0x7636,0x7637,0x7639,0x763A,0x763B,0x763D,0x7641,0x7642, +0x7644, 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, 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, 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, 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, +0x7645,0x7646,0x7647,0x7648,0x7649,0x764A,0x764B,0x764E, +0x764F,0x7650,0x7651,0x7652,0x7653,0x7655,0x7657,0x7658, +0x7659,0x765A,0x765B,0x765D,0x765F,0x7660,0x7661,0x7662, +0x7664,0x7665,0x7666,0x7667,0x7668,0x7669,0x766A,0x766C, +0x766D,0x766E,0x7670,0x7671,0x7672,0x7673,0x7674,0x7675, +0x7676,0x7677,0x7679,0x767A,0x767C,0x767F,0x7680,0x7681, +0x7683,0x7685,0x7689,0x768A,0x768C,0x768D,0x768F,0x7690, +0x7692,0x7694,0x7695,0x7697,0x7698,0x769A,0x769B, 0, +0x769C,0x769D,0x769E,0x769F,0x76A0,0x76A1,0x76A2,0x76A3, +0x76A5,0x76A6,0x76A7,0x76A8,0x76A9,0x76AA,0x76AB,0x76AC, +0x76AD,0x76AF,0x76B0,0x76B3,0x76B5,0x76B6,0x76B7,0x76B8, +0x76B9,0x76BA,0x76BB,0x76BC,0x76BD,0x76BE,0x76C0,0x76C1, +0x76C3,0x554A,0x963F,0x57C3,0x6328,0x54CE,0x5509,0x54C0, +0x7691,0x764C,0x853C,0x77EE,0x827E,0x788D,0x7231,0x9698, +0x978D,0x6C28,0x5B89,0x4FFA,0x6309,0x6697,0x5CB8,0x80FA, +0x6848,0x80AE,0x6602,0x76CE,0x51F9,0x6556,0x71AC,0x7FF1, +0x8884,0x50B2,0x5965,0x61CA,0x6FB3,0x82AD,0x634C,0x6252, +0x53ED,0x5427,0x7B06,0x516B,0x75A4,0x5DF4,0x62D4,0x8DCB, +0x9776,0x628A,0x8019,0x575D,0x9738,0x7F62,0x7238,0x767D, +0x67CF,0x767E,0x6446,0x4F70,0x8D25,0x62DC,0x7A17,0x6591, +0x73ED,0x642C,0x6273,0x822C,0x9881,0x677F,0x7248,0x626E, +0x62CC,0x4F34,0x74E3,0x534A,0x529E,0x7ECA,0x90A6,0x5E2E, +0x6886,0x699C,0x8180,0x7ED1,0x68D2,0x78C5,0x868C,0x9551, +0x508D,0x8C24,0x82DE,0x80DE,0x5305,0x8912,0x5265, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x76C4,0x76C7,0x76C9,0x76CB,0x76CC,0x76D3,0x76D5,0x76D9, +0x76DA,0x76DC,0x76DD,0x76DE,0x76E0,0x76E1,0x76E2,0x76E3, +0x76E4,0x76E6,0x76E7,0x76E8,0x76E9,0x76EA,0x76EB,0x76EC, +0x76ED,0x76F0,0x76F3,0x76F5,0x76F6,0x76F7,0x76FA,0x76FB, +0x76FD,0x76FF,0x7700,0x7702,0x7703,0x7705,0x7706,0x770A, +0x770C,0x770E,0x770F,0x7710,0x7711,0x7712,0x7713,0x7714, +0x7715,0x7716,0x7717,0x7718,0x771B,0x771C,0x771D,0x771E, +0x7721,0x7723,0x7724,0x7725,0x7727,0x772A,0x772B, 0, +0x772C,0x772E,0x7730,0x7731,0x7732,0x7733,0x7734,0x7739, +0x773B,0x773D,0x773E,0x773F,0x7742,0x7744,0x7745,0x7746, +0x7748,0x7749,0x774A,0x774B,0x774C,0x774D,0x774E,0x774F, +0x7752,0x7753,0x7754,0x7755,0x7756,0x7757,0x7758,0x7759, +0x775C,0x8584,0x96F9,0x4FDD,0x5821,0x9971,0x5B9D,0x62B1, +0x62A5,0x66B4,0x8C79,0x9C8D,0x7206,0x676F,0x7891,0x60B2, +0x5351,0x5317,0x8F88,0x80CC,0x8D1D,0x94A1,0x500D,0x72C8, +0x5907,0x60EB,0x7119,0x88AB,0x5954,0x82EF,0x672C,0x7B28, +0x5D29,0x7EF7,0x752D,0x6CF5,0x8E66,0x8FF8,0x903C,0x9F3B, +0x6BD4,0x9119,0x7B14,0x5F7C,0x78A7,0x84D6,0x853D,0x6BD5, +0x6BD9,0x6BD6,0x5E01,0x5E87,0x75F9,0x95ED,0x655D,0x5F0A, +0x5FC5,0x8F9F,0x58C1,0x81C2,0x907F,0x965B,0x97AD,0x8FB9, +0x7F16,0x8D2C,0x6241,0x4FBF,0x53D8,0x535E,0x8FA8,0x8FA9, +0x8FAB,0x904D,0x6807,0x5F6A,0x8198,0x8868,0x9CD6,0x618B, +0x522B,0x762A,0x5F6C,0x658C,0x6FD2,0x6EE8,0x5BBE,0x6448, +0x5175,0x51B0,0x67C4,0x4E19,0x79C9,0x997C,0x70B3, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x775D,0x775E,0x775F,0x7760,0x7764,0x7767,0x7769,0x776A, +0x776D,0x776E,0x776F,0x7770,0x7771,0x7772,0x7773,0x7774, +0x7775,0x7776,0x7777,0x7778,0x777A,0x777B,0x777C,0x7781, +0x7782,0x7783,0x7786,0x7787,0x7788,0x7789,0x778A,0x778B, +0x778F,0x7790,0x7793,0x7794,0x7795,0x7796,0x7797,0x7798, +0x7799,0x779A,0x779B,0x779C,0x779D,0x779E,0x77A1,0x77A3, +0x77A4,0x77A6,0x77A8,0x77AB,0x77AD,0x77AE,0x77AF,0x77B1, +0x77B2,0x77B4,0x77B6,0x77B7,0x77B8,0x77B9,0x77BA, 0, +0x77BC,0x77BE,0x77C0,0x77C1,0x77C2,0x77C3,0x77C4,0x77C5, +0x77C6,0x77C7,0x77C8,0x77C9,0x77CA,0x77CB,0x77CC,0x77CE, +0x77CF,0x77D0,0x77D1,0x77D2,0x77D3,0x77D4,0x77D5,0x77D6, +0x77D8,0x77D9,0x77DA,0x77DD,0x77DE,0x77DF,0x77E0,0x77E1, +0x77E4,0x75C5,0x5E76,0x73BB,0x83E0,0x64AD,0x62E8,0x94B5, +0x6CE2,0x535A,0x52C3,0x640F,0x94C2,0x7B94,0x4F2F,0x5E1B, +0x8236,0x8116,0x818A,0x6E24,0x6CCA,0x9A73,0x6355,0x535C, +0x54FA,0x8865,0x57E0,0x4E0D,0x5E03,0x6B65,0x7C3F,0x90E8, +0x6016,0x64E6,0x731C,0x88C1,0x6750,0x624D,0x8D22,0x776C, +0x8E29,0x91C7,0x5F69,0x83DC,0x8521,0x9910,0x53C2,0x8695, +0x6B8B,0x60ED,0x60E8,0x707F,0x82CD,0x8231,0x4ED3,0x6CA7, +0x85CF,0x64CD,0x7CD9,0x69FD,0x66F9,0x8349,0x5395,0x7B56, +0x4FA7,0x518C,0x6D4B,0x5C42,0x8E6D,0x63D2,0x53C9,0x832C, +0x8336,0x67E5,0x78B4,0x643D,0x5BDF,0x5C94,0x5DEE,0x8BE7, +0x62C6,0x67F4,0x8C7A,0x6400,0x63BA,0x8749,0x998B,0x8C17, +0x7F20,0x94F2,0x4EA7,0x9610,0x98A4,0x660C,0x7316, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x77E6,0x77E8,0x77EA,0x77EF,0x77F0,0x77F1,0x77F2,0x77F4, +0x77F5,0x77F7,0x77F9,0x77FA,0x77FB,0x77FC,0x7803,0x7804, +0x7805,0x7806,0x7807,0x7808,0x780A,0x780B,0x780E,0x780F, +0x7810,0x7813,0x7815,0x7819,0x781B,0x781E,0x7820,0x7821, +0x7822,0x7824,0x7828,0x782A,0x782B,0x782E,0x782F,0x7831, +0x7832,0x7833,0x7835,0x7836,0x783D,0x783F,0x7841,0x7842, +0x7843,0x7844,0x7846,0x7848,0x7849,0x784A,0x784B,0x784D, +0x784F,0x7851,0x7853,0x7854,0x7858,0x7859,0x785A, 0, +0x785B,0x785C,0x785E,0x785F,0x7860,0x7861,0x7862,0x7863, +0x7864,0x7865,0x7866,0x7867,0x7868,0x7869,0x786F,0x7870, +0x7871,0x7872,0x7873,0x7874,0x7875,0x7876,0x7878,0x7879, +0x787A,0x787B,0x787D,0x787E,0x787F,0x7880,0x7881,0x7882, +0x7883,0x573A,0x5C1D,0x5E38,0x957F,0x507F,0x80A0,0x5382, +0x655E,0x7545,0x5531,0x5021,0x8D85,0x6284,0x949E,0x671D, +0x5632,0x6F6E,0x5DE2,0x5435,0x7092,0x8F66,0x626F,0x64A4, +0x63A3,0x5F7B,0x6F88,0x90F4,0x81E3,0x8FB0,0x5C18,0x6668, +0x5FF1,0x6C89,0x9648,0x8D81,0x886C,0x6491,0x79F0,0x57CE, +0x6A59,0x6210,0x5448,0x4E58,0x7A0B,0x60E9,0x6F84,0x8BDA, +0x627F,0x901E,0x9A8B,0x79E4,0x5403,0x75F4,0x6301,0x5319, +0x6C60,0x8FDF,0x5F1B,0x9A70,0x803B,0x9F7F,0x4F88,0x5C3A, +0x8D64,0x7FC5,0x65A5,0x70BD,0x5145,0x51B2,0x866B,0x5D07, +0x5BA0,0x62BD,0x916C,0x7574,0x8E0C,0x7A20,0x6101,0x7B79, +0x4EC7,0x7EF8,0x7785,0x4E11,0x81ED,0x521D,0x51FA,0x6A71, +0x53A8,0x8E87,0x9504,0x96CF,0x6EC1,0x9664,0x695A, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x7884,0x7885,0x7886,0x7888,0x788A,0x788B,0x788F,0x7890, +0x7892,0x7894,0x7895,0x7896,0x7899,0x789D,0x789E,0x78A0, +0x78A2,0x78A4,0x78A6,0x78A8,0x78A9,0x78AA,0x78AB,0x78AC, +0x78AD,0x78AE,0x78AF,0x78B5,0x78B6,0x78B7,0x78B8,0x78BA, +0x78BB,0x78BC,0x78BD,0x78BF,0x78C0,0x78C2,0x78C3,0x78C4, +0x78C6,0x78C7,0x78C8,0x78CC,0x78CD,0x78CE,0x78CF,0x78D1, +0x78D2,0x78D3,0x78D6,0x78D7,0x78D8,0x78DA,0x78DB,0x78DC, +0x78DD,0x78DE,0x78DF,0x78E0,0x78E1,0x78E2,0x78E3, 0, +0x78E4,0x78E5,0x78E6,0x78E7,0x78E9,0x78EA,0x78EB,0x78ED, +0x78EE,0x78EF,0x78F0,0x78F1,0x78F3,0x78F5,0x78F6,0x78F8, +0x78F9,0x78FB,0x78FC,0x78FD,0x78FE,0x78FF,0x7900,0x7902, +0x7903,0x7904,0x7906,0x7907,0x7908,0x7909,0x790A,0x790B, +0x790C,0x7840,0x50A8,0x77D7,0x6410,0x89E6,0x5904,0x63E3, +0x5DDD,0x7A7F,0x693D,0x4F20,0x8239,0x5598,0x4E32,0x75AE, +0x7A97,0x5E62,0x5E8A,0x95EF,0x521B,0x5439,0x708A,0x6376, +0x9524,0x5782,0x6625,0x693F,0x9187,0x5507,0x6DF3,0x7EAF, +0x8822,0x6233,0x7EF0,0x75B5,0x8328,0x78C1,0x96CC,0x8F9E, +0x6148,0x74F7,0x8BCD,0x6B64,0x523A,0x8D50,0x6B21,0x806A, +0x8471,0x56F1,0x5306,0x4ECE,0x4E1B,0x51D1,0x7C97,0x918B, +0x7C07,0x4FC3,0x8E7F,0x7BE1,0x7A9C,0x6467,0x5D14,0x50AC, +0x8106,0x7601,0x7CB9,0x6DEC,0x7FE0,0x6751,0x5B58,0x5BF8, +0x78CB,0x64AE,0x6413,0x63AA,0x632B,0x9519,0x642D,0x8FBE, +0x7B54,0x7629,0x6253,0x5927,0x5446,0x6B79,0x50A3,0x6234, +0x5E26,0x6B86,0x4EE3,0x8D37,0x888B,0x5F85,0x902E, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x790D,0x790E,0x790F,0x7910,0x7911,0x7912,0x7914,0x7915, +0x7916,0x7917,0x7918,0x7919,0x791A,0x791B,0x791C,0x791D, +0x791F,0x7920,0x7921,0x7922,0x7923,0x7925,0x7926,0x7927, +0x7928,0x7929,0x792A,0x792B,0x792C,0x792D,0x792E,0x792F, +0x7930,0x7931,0x7932,0x7933,0x7935,0x7936,0x7937,0x7938, +0x7939,0x793D,0x793F,0x7942,0x7943,0x7944,0x7945,0x7947, +0x794A,0x794B,0x794C,0x794D,0x794E,0x794F,0x7950,0x7951, +0x7952,0x7954,0x7955,0x7958,0x7959,0x7961,0x7963, 0, +0x7964,0x7966,0x7969,0x796A,0x796B,0x796C,0x796E,0x7970, +0x7971,0x7972,0x7973,0x7974,0x7975,0x7976,0x7979,0x797B, +0x797C,0x797D,0x797E,0x797F,0x7982,0x7983,0x7986,0x7987, +0x7988,0x7989,0x798B,0x798C,0x798D,0x798E,0x7990,0x7991, +0x7992,0x6020,0x803D,0x62C5,0x4E39,0x5355,0x90F8,0x63B8, +0x80C6,0x65E6,0x6C2E,0x4F46,0x60EE,0x6DE1,0x8BDE,0x5F39, +0x86CB,0x5F53,0x6321,0x515A,0x8361,0x6863,0x5200,0x6363, +0x8E48,0x5012,0x5C9B,0x7977,0x5BFC,0x5230,0x7A3B,0x60BC, +0x9053,0x76D7,0x5FB7,0x5F97,0x7684,0x8E6C,0x706F,0x767B, +0x7B49,0x77AA,0x51F3,0x9093,0x5824,0x4F4E,0x6EF4,0x8FEA, +0x654C,0x7B1B,0x72C4,0x6DA4,0x7FDF,0x5AE1,0x62B5,0x5E95, +0x5730,0x8482,0x7B2C,0x5E1D,0x5F1F,0x9012,0x7F14,0x98A0, +0x6382,0x6EC7,0x7898,0x70B9,0x5178,0x975B,0x57AB,0x7535, +0x4F43,0x7538,0x5E97,0x60E6,0x5960,0x6DC0,0x6BBF,0x7889, +0x53FC,0x96D5,0x51CB,0x5201,0x6389,0x540A,0x9493,0x8C03, +0x8DCC,0x7239,0x789F,0x8776,0x8FED,0x8C0D,0x53E0, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x7993,0x7994,0x7995,0x7996,0x7997,0x7998,0x7999,0x799B, +0x799C,0x799D,0x799E,0x799F,0x79A0,0x79A1,0x79A2,0x79A3, +0x79A4,0x79A5,0x79A6,0x79A8,0x79A9,0x79AA,0x79AB,0x79AC, +0x79AD,0x79AE,0x79AF,0x79B0,0x79B1,0x79B2,0x79B4,0x79B5, +0x79B6,0x79B7,0x79B8,0x79BC,0x79BF,0x79C2,0x79C4,0x79C5, +0x79C7,0x79C8,0x79CA,0x79CC,0x79CE,0x79CF,0x79D0,0x79D3, +0x79D4,0x79D6,0x79D7,0x79D9,0x79DA,0x79DB,0x79DC,0x79DD, +0x79DE,0x79E0,0x79E1,0x79E2,0x79E5,0x79E8,0x79EA, 0, +0x79EC,0x79EE,0x79F1,0x79F2,0x79F3,0x79F4,0x79F5,0x79F6, +0x79F7,0x79F9,0x79FA,0x79FC,0x79FE,0x79FF,0x7A01,0x7A04, +0x7A05,0x7A07,0x7A08,0x7A09,0x7A0A,0x7A0C,0x7A0F,0x7A10, +0x7A11,0x7A12,0x7A13,0x7A15,0x7A16,0x7A18,0x7A19,0x7A1B, +0x7A1C,0x4E01,0x76EF,0x53EE,0x9489,0x9876,0x9F0E,0x952D, +0x5B9A,0x8BA2,0x4E22,0x4E1C,0x51AC,0x8463,0x61C2,0x52A8, +0x680B,0x4F97,0x606B,0x51BB,0x6D1E,0x515C,0x6296,0x6597, +0x9661,0x8C46,0x9017,0x75D8,0x90FD,0x7763,0x6BD2,0x728A, +0x72EC,0x8BFB,0x5835,0x7779,0x8D4C,0x675C,0x9540,0x809A, +0x5EA6,0x6E21,0x5992,0x7AEF,0x77ED,0x953B,0x6BB5,0x65AD, +0x7F0E,0x5806,0x5151,0x961F,0x5BF9,0x58A9,0x5428,0x8E72, +0x6566,0x987F,0x56E4,0x949D,0x76FE,0x9041,0x6387,0x54C6, +0x591A,0x593A,0x579B,0x8EB2,0x6735,0x8DFA,0x8235,0x5241, +0x60F0,0x5815,0x86FE,0x5CE8,0x9E45,0x4FC4,0x989D,0x8BB9, +0x5A25,0x6076,0x5384,0x627C,0x904F,0x9102,0x997F,0x6069, +0x800C,0x513F,0x8033,0x5C14,0x9975,0x6D31,0x4E8C, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x7A1D,0x7A1F,0x7A21,0x7A22,0x7A24,0x7A25,0x7A26,0x7A27, +0x7A28,0x7A29,0x7A2A,0x7A2B,0x7A2C,0x7A2D,0x7A2E,0x7A2F, +0x7A30,0x7A31,0x7A32,0x7A34,0x7A35,0x7A36,0x7A38,0x7A3A, +0x7A3E,0x7A40,0x7A41,0x7A42,0x7A43,0x7A44,0x7A45,0x7A47, +0x7A48,0x7A49,0x7A4A,0x7A4B,0x7A4C,0x7A4D,0x7A4E,0x7A4F, +0x7A50,0x7A52,0x7A53,0x7A54,0x7A55,0x7A56,0x7A58,0x7A59, +0x7A5A,0x7A5B,0x7A5C,0x7A5D,0x7A5E,0x7A5F,0x7A60,0x7A61, +0x7A62,0x7A63,0x7A64,0x7A65,0x7A66,0x7A67,0x7A68, 0, +0x7A69,0x7A6A,0x7A6B,0x7A6C,0x7A6D,0x7A6E,0x7A6F,0x7A71, +0x7A72,0x7A73,0x7A75,0x7A7B,0x7A7C,0x7A7D,0x7A7E,0x7A82, +0x7A85,0x7A87,0x7A89,0x7A8A,0x7A8B,0x7A8C,0x7A8E,0x7A8F, +0x7A90,0x7A93,0x7A94,0x7A99,0x7A9A,0x7A9B,0x7A9E,0x7AA1, +0x7AA2,0x8D30,0x53D1,0x7F5A,0x7B4F,0x4F10,0x4E4F,0x9600, +0x6CD5,0x73D0,0x85E9,0x5E06,0x756A,0x7FFB,0x6A0A,0x77FE, +0x9492,0x7E41,0x51E1,0x70E6,0x53CD,0x8FD4,0x8303,0x8D29, +0x72AF,0x996D,0x6CDB,0x574A,0x82B3,0x65B9,0x80AA,0x623F, +0x9632,0x59A8,0x4EFF,0x8BBF,0x7EBA,0x653E,0x83F2,0x975E, +0x5561,0x98DE,0x80A5,0x532A,0x8BFD,0x5420,0x80BA,0x5E9F, +0x6CB8,0x8D39,0x82AC,0x915A,0x5429,0x6C1B,0x5206,0x7EB7, +0x575F,0x711A,0x6C7E,0x7C89,0x594B,0x4EFD,0x5FFF,0x6124, +0x7CAA,0x4E30,0x5C01,0x67AB,0x8702,0x5CF0,0x950B,0x98CE, +0x75AF,0x70FD,0x9022,0x51AF,0x7F1D,0x8BBD,0x5949,0x51E4, +0x4F5B,0x5426,0x592B,0x6577,0x80A4,0x5B75,0x6276,0x62C2, +0x8F90,0x5E45,0x6C1F,0x7B26,0x4F0F,0x4FD8,0x670D, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x7AA3,0x7AA4,0x7AA7,0x7AA9,0x7AAA,0x7AAB,0x7AAE,0x7AAF, +0x7AB0,0x7AB1,0x7AB2,0x7AB4,0x7AB5,0x7AB6,0x7AB7,0x7AB8, +0x7AB9,0x7ABA,0x7ABB,0x7ABC,0x7ABD,0x7ABE,0x7AC0,0x7AC1, +0x7AC2,0x7AC3,0x7AC4,0x7AC5,0x7AC6,0x7AC7,0x7AC8,0x7AC9, +0x7ACA,0x7ACC,0x7ACD,0x7ACE,0x7ACF,0x7AD0,0x7AD1,0x7AD2, +0x7AD3,0x7AD4,0x7AD5,0x7AD7,0x7AD8,0x7ADA,0x7ADB,0x7ADC, +0x7ADD,0x7AE1,0x7AE2,0x7AE4,0x7AE7,0x7AE8,0x7AE9,0x7AEA, +0x7AEB,0x7AEC,0x7AEE,0x7AF0,0x7AF1,0x7AF2,0x7AF3, 0, +0x7AF4,0x7AF5,0x7AF6,0x7AF7,0x7AF8,0x7AFB,0x7AFC,0x7AFE, +0x7B00,0x7B01,0x7B02,0x7B05,0x7B07,0x7B09,0x7B0C,0x7B0D, +0x7B0E,0x7B10,0x7B12,0x7B13,0x7B16,0x7B17,0x7B18,0x7B1A, +0x7B1C,0x7B1D,0x7B1F,0x7B21,0x7B22,0x7B23,0x7B27,0x7B29, +0x7B2D,0x6D6E,0x6DAA,0x798F,0x88B1,0x5F17,0x752B,0x629A, +0x8F85,0x4FEF,0x91DC,0x65A7,0x812F,0x8151,0x5E9C,0x8150, +0x8D74,0x526F,0x8986,0x8D4B,0x590D,0x5085,0x4ED8,0x961C, +0x7236,0x8179,0x8D1F,0x5BCC,0x8BA3,0x9644,0x5987,0x7F1A, +0x5490,0x5676,0x560E,0x8BE5,0x6539,0x6982,0x9499,0x76D6, +0x6E89,0x5E72,0x7518,0x6746,0x67D1,0x7AFF,0x809D,0x8D76, +0x611F,0x79C6,0x6562,0x8D63,0x5188,0x521A,0x94A2,0x7F38, +0x809B,0x7EB2,0x5C97,0x6E2F,0x6760,0x7BD9,0x768B,0x9AD8, +0x818F,0x7F94,0x7CD5,0x641E,0x9550,0x7A3F,0x544A,0x54E5, +0x6B4C,0x6401,0x6208,0x9E3D,0x80F3,0x7599,0x5272,0x9769, +0x845B,0x683C,0x86E4,0x9601,0x9694,0x94EC,0x4E2A,0x5404, +0x7ED9,0x6839,0x8DDF,0x8015,0x66F4,0x5E9A,0x7FB9, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x7B2F,0x7B30,0x7B32,0x7B34,0x7B35,0x7B36,0x7B37,0x7B39, +0x7B3B,0x7B3D,0x7B3F,0x7B40,0x7B41,0x7B42,0x7B43,0x7B44, +0x7B46,0x7B48,0x7B4A,0x7B4D,0x7B4E,0x7B53,0x7B55,0x7B57, +0x7B59,0x7B5C,0x7B5E,0x7B5F,0x7B61,0x7B63,0x7B64,0x7B65, +0x7B66,0x7B67,0x7B68,0x7B69,0x7B6A,0x7B6B,0x7B6C,0x7B6D, +0x7B6F,0x7B70,0x7B73,0x7B74,0x7B76,0x7B78,0x7B7A,0x7B7C, +0x7B7D,0x7B7F,0x7B81,0x7B82,0x7B83,0x7B84,0x7B86,0x7B87, +0x7B88,0x7B89,0x7B8A,0x7B8B,0x7B8C,0x7B8E,0x7B8F, 0, +0x7B91,0x7B92,0x7B93,0x7B96,0x7B98,0x7B99,0x7B9A,0x7B9B, +0x7B9E,0x7B9F,0x7BA0,0x7BA3,0x7BA4,0x7BA5,0x7BAE,0x7BAF, +0x7BB0,0x7BB2,0x7BB3,0x7BB5,0x7BB6,0x7BB7,0x7BB9,0x7BBA, +0x7BBB,0x7BBC,0x7BBD,0x7BBE,0x7BBF,0x7BC0,0x7BC2,0x7BC3, +0x7BC4,0x57C2,0x803F,0x6897,0x5DE5,0x653B,0x529F,0x606D, +0x9F9A,0x4F9B,0x8EAC,0x516C,0x5BAB,0x5F13,0x5DE9,0x6C5E, +0x62F1,0x8D21,0x5171,0x94A9,0x52FE,0x6C9F,0x82DF,0x72D7, +0x57A2,0x6784,0x8D2D,0x591F,0x8F9C,0x83C7,0x5495,0x7B8D, +0x4F30,0x6CBD,0x5B64,0x59D1,0x9F13,0x53E4,0x86CA,0x9AA8, +0x8C37,0x80A1,0x6545,0x987E,0x56FA,0x96C7,0x522E,0x74DC, +0x5250,0x5BE1,0x6302,0x8902,0x4E56,0x62D0,0x602A,0x68FA, +0x5173,0x5B98,0x51A0,0x89C2,0x7BA1,0x9986,0x7F50,0x60EF, +0x704C,0x8D2F,0x5149,0x5E7F,0x901B,0x7470,0x89C4,0x572D, +0x7845,0x5F52,0x9F9F,0x95FA,0x8F68,0x9B3C,0x8BE1,0x7678, +0x6842,0x67DC,0x8DEA,0x8D35,0x523D,0x8F8A,0x6EDA,0x68CD, +0x9505,0x90ED,0x56FD,0x679C,0x88F9,0x8FC7,0x54C8, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x7BC5,0x7BC8,0x7BC9,0x7BCA,0x7BCB,0x7BCD,0x7BCE,0x7BCF, +0x7BD0,0x7BD2,0x7BD4,0x7BD5,0x7BD6,0x7BD7,0x7BD8,0x7BDB, +0x7BDC,0x7BDE,0x7BDF,0x7BE0,0x7BE2,0x7BE3,0x7BE4,0x7BE7, +0x7BE8,0x7BE9,0x7BEB,0x7BEC,0x7BED,0x7BEF,0x7BF0,0x7BF2, +0x7BF3,0x7BF4,0x7BF5,0x7BF6,0x7BF8,0x7BF9,0x7BFA,0x7BFB, +0x7BFD,0x7BFF,0x7C00,0x7C01,0x7C02,0x7C03,0x7C04,0x7C05, +0x7C06,0x7C08,0x7C09,0x7C0A,0x7C0D,0x7C0E,0x7C10,0x7C11, +0x7C12,0x7C13,0x7C14,0x7C15,0x7C17,0x7C18,0x7C19, 0, +0x7C1A,0x7C1B,0x7C1C,0x7C1D,0x7C1E,0x7C20,0x7C21,0x7C22, +0x7C23,0x7C24,0x7C25,0x7C28,0x7C29,0x7C2B,0x7C2C,0x7C2D, +0x7C2E,0x7C2F,0x7C30,0x7C31,0x7C32,0x7C33,0x7C34,0x7C35, +0x7C36,0x7C37,0x7C39,0x7C3A,0x7C3B,0x7C3C,0x7C3D,0x7C3E, +0x7C42,0x9AB8,0x5B69,0x6D77,0x6C26,0x4EA5,0x5BB3,0x9A87, +0x9163,0x61A8,0x90AF,0x97E9,0x542B,0x6DB5,0x5BD2,0x51FD, +0x558A,0x7F55,0x7FF0,0x64BC,0x634D,0x65F1,0x61BE,0x608D, +0x710A,0x6C57,0x6C49,0x592F,0x676D,0x822A,0x58D5,0x568E, +0x8C6A,0x6BEB,0x90DD,0x597D,0x8017,0x53F7,0x6D69,0x5475, +0x559D,0x8377,0x83CF,0x6838,0x79BE,0x548C,0x4F55,0x5408, +0x76D2,0x8C89,0x9602,0x6CB3,0x6DB8,0x8D6B,0x8910,0x9E64, +0x8D3A,0x563F,0x9ED1,0x75D5,0x5F88,0x72E0,0x6068,0x54FC, +0x4EA8,0x6A2A,0x8861,0x6052,0x8F70,0x54C4,0x70D8,0x8679, +0x9E3F,0x6D2A,0x5B8F,0x5F18,0x7EA2,0x5589,0x4FAF,0x7334, +0x543C,0x539A,0x5019,0x540E,0x547C,0x4E4E,0x5FFD,0x745A, +0x58F6,0x846B,0x80E1,0x8774,0x72D0,0x7CCA,0x6E56, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x7C43,0x7C44,0x7C45,0x7C46,0x7C47,0x7C48,0x7C49,0x7C4A, +0x7C4B,0x7C4C,0x7C4E,0x7C4F,0x7C50,0x7C51,0x7C52,0x7C53, +0x7C54,0x7C55,0x7C56,0x7C57,0x7C58,0x7C59,0x7C5A,0x7C5B, +0x7C5C,0x7C5D,0x7C5E,0x7C5F,0x7C60,0x7C61,0x7C62,0x7C63, +0x7C64,0x7C65,0x7C66,0x7C67,0x7C68,0x7C69,0x7C6A,0x7C6B, +0x7C6C,0x7C6D,0x7C6E,0x7C6F,0x7C70,0x7C71,0x7C72,0x7C75, +0x7C76,0x7C77,0x7C78,0x7C79,0x7C7A,0x7C7E,0x7C7F,0x7C80, +0x7C81,0x7C82,0x7C83,0x7C84,0x7C85,0x7C86,0x7C87, 0, +0x7C88,0x7C8A,0x7C8B,0x7C8C,0x7C8D,0x7C8E,0x7C8F,0x7C90, +0x7C93,0x7C94,0x7C96,0x7C99,0x7C9A,0x7C9B,0x7CA0,0x7CA1, +0x7CA3,0x7CA6,0x7CA7,0x7CA8,0x7CA9,0x7CAB,0x7CAC,0x7CAD, +0x7CAF,0x7CB0,0x7CB4,0x7CB5,0x7CB6,0x7CB7,0x7CB8,0x7CBA, +0x7CBB,0x5F27,0x864E,0x552C,0x62A4,0x4E92,0x6CAA,0x6237, +0x82B1,0x54D7,0x534E,0x733E,0x6ED1,0x753B,0x5212,0x5316, +0x8BDD,0x69D0,0x5F8A,0x6000,0x6DEE,0x574F,0x6B22,0x73AF, +0x6853,0x8FD8,0x7F13,0x6362,0x60A3,0x5524,0x75EA,0x8C62, +0x7115,0x6DA3,0x5BA6,0x5E7B,0x8352,0x614C,0x9EC4,0x78FA, +0x8757,0x7C27,0x7687,0x51F0,0x60F6,0x714C,0x6643,0x5E4C, +0x604D,0x8C0E,0x7070,0x6325,0x8F89,0x5FBD,0x6062,0x86D4, +0x56DE,0x6BC1,0x6094,0x6167,0x5349,0x60E0,0x6666,0x8D3F, +0x79FD,0x4F1A,0x70E9,0x6C47,0x8BB3,0x8BF2,0x7ED8,0x8364, +0x660F,0x5A5A,0x9B42,0x6D51,0x6DF7,0x8C41,0x6D3B,0x4F19, +0x706B,0x83B7,0x6216,0x60D1,0x970D,0x8D27,0x7978,0x51FB, +0x573E,0x57FA,0x673A,0x7578,0x7A3D,0x79EF,0x7B95, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x7CBF,0x7CC0,0x7CC2,0x7CC3,0x7CC4,0x7CC6,0x7CC9,0x7CCB, +0x7CCE,0x7CCF,0x7CD0,0x7CD1,0x7CD2,0x7CD3,0x7CD4,0x7CD8, +0x7CDA,0x7CDB,0x7CDD,0x7CDE,0x7CE1,0x7CE2,0x7CE3,0x7CE4, +0x7CE5,0x7CE6,0x7CE7,0x7CE9,0x7CEA,0x7CEB,0x7CEC,0x7CED, +0x7CEE,0x7CF0,0x7CF1,0x7CF2,0x7CF3,0x7CF4,0x7CF5,0x7CF6, +0x7CF7,0x7CF9,0x7CFA,0x7CFC,0x7CFD,0x7CFE,0x7CFF,0x7D00, +0x7D01,0x7D02,0x7D03,0x7D04,0x7D05,0x7D06,0x7D07,0x7D08, +0x7D09,0x7D0B,0x7D0C,0x7D0D,0x7D0E,0x7D0F,0x7D10, 0, +0x7D11,0x7D12,0x7D13,0x7D14,0x7D15,0x7D16,0x7D17,0x7D18, +0x7D19,0x7D1A,0x7D1B,0x7D1C,0x7D1D,0x7D1E,0x7D1F,0x7D21, +0x7D23,0x7D24,0x7D25,0x7D26,0x7D28,0x7D29,0x7D2A,0x7D2C, +0x7D2D,0x7D2E,0x7D30,0x7D31,0x7D32,0x7D33,0x7D34,0x7D35, +0x7D36,0x808C,0x9965,0x8FF9,0x6FC0,0x8BA5,0x9E21,0x59EC, +0x7EE9,0x7F09,0x5409,0x6781,0x68D8,0x8F91,0x7C4D,0x96C6, +0x53CA,0x6025,0x75BE,0x6C72,0x5373,0x5AC9,0x7EA7,0x6324, +0x51E0,0x810A,0x5DF1,0x84DF,0x6280,0x5180,0x5B63,0x4F0E, +0x796D,0x5242,0x60B8,0x6D4E,0x5BC4,0x5BC2,0x8BA1,0x8BB0, +0x65E2,0x5FCC,0x9645,0x5993,0x7EE7,0x7EAA,0x5609,0x67B7, +0x5939,0x4F73,0x5BB6,0x52A0,0x835A,0x988A,0x8D3E,0x7532, +0x94BE,0x5047,0x7A3C,0x4EF7,0x67B6,0x9A7E,0x5AC1,0x6B7C, +0x76D1,0x575A,0x5C16,0x7B3A,0x95F4,0x714E,0x517C,0x80A9, +0x8270,0x5978,0x7F04,0x8327,0x68C0,0x67EC,0x78B1,0x7877, +0x62E3,0x6361,0x7B80,0x4FED,0x526A,0x51CF,0x8350,0x69DB, +0x9274,0x8DF5,0x8D31,0x89C1,0x952E,0x7BAD,0x4EF6, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x7D37,0x7D38,0x7D39,0x7D3A,0x7D3B,0x7D3C,0x7D3D,0x7D3E, +0x7D3F,0x7D40,0x7D41,0x7D42,0x7D43,0x7D44,0x7D45,0x7D46, +0x7D47,0x7D48,0x7D49,0x7D4A,0x7D4B,0x7D4C,0x7D4D,0x7D4E, +0x7D4F,0x7D50,0x7D51,0x7D52,0x7D53,0x7D54,0x7D55,0x7D56, +0x7D57,0x7D58,0x7D59,0x7D5A,0x7D5B,0x7D5C,0x7D5D,0x7D5E, +0x7D5F,0x7D60,0x7D61,0x7D62,0x7D63,0x7D64,0x7D65,0x7D66, +0x7D67,0x7D68,0x7D69,0x7D6A,0x7D6B,0x7D6C,0x7D6D,0x7D6F, +0x7D70,0x7D71,0x7D72,0x7D73,0x7D74,0x7D75,0x7D76, 0, +0x7D78,0x7D79,0x7D7A,0x7D7B,0x7D7C,0x7D7D,0x7D7E,0x7D7F, +0x7D80,0x7D81,0x7D82,0x7D83,0x7D84,0x7D85,0x7D86,0x7D87, +0x7D88,0x7D89,0x7D8A,0x7D8B,0x7D8C,0x7D8D,0x7D8E,0x7D8F, +0x7D90,0x7D91,0x7D92,0x7D93,0x7D94,0x7D95,0x7D96,0x7D97, +0x7D98,0x5065,0x8230,0x5251,0x996F,0x6E10,0x6E85,0x6DA7, +0x5EFA,0x50F5,0x59DC,0x5C06,0x6D46,0x6C5F,0x7586,0x848B, +0x6868,0x5956,0x8BB2,0x5320,0x9171,0x964D,0x8549,0x6912, +0x7901,0x7126,0x80F6,0x4EA4,0x90CA,0x6D47,0x9A84,0x5A07, +0x56BC,0x6405,0x94F0,0x77EB,0x4FA5,0x811A,0x72E1,0x89D2, +0x997A,0x7F34,0x7EDE,0x527F,0x6559,0x9175,0x8F7F,0x8F83, +0x53EB,0x7A96,0x63ED,0x63A5,0x7686,0x79F8,0x8857,0x9636, +0x622A,0x52AB,0x8282,0x6854,0x6770,0x6377,0x776B,0x7AED, +0x6D01,0x7ED3,0x89E3,0x59D0,0x6212,0x85C9,0x82A5,0x754C, +0x501F,0x4ECB,0x75A5,0x8BEB,0x5C4A,0x5DFE,0x7B4B,0x65A4, +0x91D1,0x4ECA,0x6D25,0x895F,0x7D27,0x9526,0x4EC5,0x8C28, +0x8FDB,0x9773,0x664B,0x7981,0x8FD1,0x70EC,0x6D78, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x7D99,0x7D9A,0x7D9B,0x7D9C,0x7D9D,0x7D9E,0x7D9F,0x7DA0, +0x7DA1,0x7DA2,0x7DA3,0x7DA4,0x7DA5,0x7DA7,0x7DA8,0x7DA9, +0x7DAA,0x7DAB,0x7DAC,0x7DAD,0x7DAF,0x7DB0,0x7DB1,0x7DB2, +0x7DB3,0x7DB4,0x7DB5,0x7DB6,0x7DB7,0x7DB8,0x7DB9,0x7DBA, +0x7DBB,0x7DBC,0x7DBD,0x7DBE,0x7DBF,0x7DC0,0x7DC1,0x7DC2, +0x7DC3,0x7DC4,0x7DC5,0x7DC6,0x7DC7,0x7DC8,0x7DC9,0x7DCA, +0x7DCB,0x7DCC,0x7DCD,0x7DCE,0x7DCF,0x7DD0,0x7DD1,0x7DD2, +0x7DD3,0x7DD4,0x7DD5,0x7DD6,0x7DD7,0x7DD8,0x7DD9, 0, +0x7DDA,0x7DDB,0x7DDC,0x7DDD,0x7DDE,0x7DDF,0x7DE0,0x7DE1, +0x7DE2,0x7DE3,0x7DE4,0x7DE5,0x7DE6,0x7DE7,0x7DE8,0x7DE9, +0x7DEA,0x7DEB,0x7DEC,0x7DED,0x7DEE,0x7DEF,0x7DF0,0x7DF1, +0x7DF2,0x7DF3,0x7DF4,0x7DF5,0x7DF6,0x7DF7,0x7DF8,0x7DF9, +0x7DFA,0x5C3D,0x52B2,0x8346,0x5162,0x830E,0x775B,0x6676, +0x9CB8,0x4EAC,0x60CA,0x7CBE,0x7CB3,0x7ECF,0x4E95,0x8B66, +0x666F,0x9888,0x9759,0x5883,0x656C,0x955C,0x5F84,0x75C9, +0x9756,0x7ADF,0x7ADE,0x51C0,0x70AF,0x7A98,0x63EA,0x7A76, +0x7EA0,0x7396,0x97ED,0x4E45,0x7078,0x4E5D,0x9152,0x53A9, +0x6551,0x65E7,0x81FC,0x8205,0x548E,0x5C31,0x759A,0x97A0, +0x62D8,0x72D9,0x75BD,0x5C45,0x9A79,0x83CA,0x5C40,0x5480, +0x77E9,0x4E3E,0x6CAE,0x805A,0x62D2,0x636E,0x5DE8,0x5177, +0x8DDD,0x8E1E,0x952F,0x4FF1,0x53E5,0x60E7,0x70AC,0x5267, +0x6350,0x9E43,0x5A1F,0x5026,0x7737,0x5377,0x7EE2,0x6485, +0x652B,0x6289,0x6398,0x5014,0x7235,0x89C9,0x51B3,0x8BC0, +0x7EDD,0x5747,0x83CC,0x94A7,0x519B,0x541B,0x5CFB, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x7DFB,0x7DFC,0x7DFD,0x7DFE,0x7DFF,0x7E00,0x7E01,0x7E02, +0x7E03,0x7E04,0x7E05,0x7E06,0x7E07,0x7E08,0x7E09,0x7E0A, +0x7E0B,0x7E0C,0x7E0D,0x7E0E,0x7E0F,0x7E10,0x7E11,0x7E12, +0x7E13,0x7E14,0x7E15,0x7E16,0x7E17,0x7E18,0x7E19,0x7E1A, +0x7E1B,0x7E1C,0x7E1D,0x7E1E,0x7E1F,0x7E20,0x7E21,0x7E22, +0x7E23,0x7E24,0x7E25,0x7E26,0x7E27,0x7E28,0x7E29,0x7E2A, +0x7E2B,0x7E2C,0x7E2D,0x7E2E,0x7E2F,0x7E30,0x7E31,0x7E32, +0x7E33,0x7E34,0x7E35,0x7E36,0x7E37,0x7E38,0x7E39, 0, +0x7E3A,0x7E3C,0x7E3D,0x7E3E,0x7E3F,0x7E40,0x7E42,0x7E43, +0x7E44,0x7E45,0x7E46,0x7E48,0x7E49,0x7E4A,0x7E4B,0x7E4C, +0x7E4D,0x7E4E,0x7E4F,0x7E50,0x7E51,0x7E52,0x7E53,0x7E54, +0x7E55,0x7E56,0x7E57,0x7E58,0x7E59,0x7E5A,0x7E5B,0x7E5C, +0x7E5D,0x4FCA,0x7AE3,0x6D5A,0x90E1,0x9A8F,0x5580,0x5496, +0x5361,0x54AF,0x5F00,0x63E9,0x6977,0x51EF,0x6168,0x520A, +0x582A,0x52D8,0x574E,0x780D,0x770B,0x5EB7,0x6177,0x7CE0, +0x625B,0x6297,0x4EA2,0x7095,0x8003,0x62F7,0x70E4,0x9760, +0x5777,0x82DB,0x67EF,0x68F5,0x78D5,0x9897,0x79D1,0x58F3, +0x54B3,0x53EF,0x6E34,0x514B,0x523B,0x5BA2,0x8BFE,0x80AF, +0x5543,0x57A6,0x6073,0x5751,0x542D,0x7A7A,0x6050,0x5B54, +0x63A7,0x62A0,0x53E3,0x6263,0x5BC7,0x67AF,0x54ED,0x7A9F, +0x82E6,0x9177,0x5E93,0x88E4,0x5938,0x57AE,0x630E,0x8DE8, +0x80EF,0x5757,0x7B77,0x4FA9,0x5FEB,0x5BBD,0x6B3E,0x5321, +0x7B50,0x72C2,0x6846,0x77FF,0x7736,0x65F7,0x51B5,0x4E8F, +0x76D4,0x5CBF,0x7AA5,0x8475,0x594E,0x9B41,0x5080, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x7E5E,0x7E5F,0x7E60,0x7E61,0x7E62,0x7E63,0x7E64,0x7E65, +0x7E66,0x7E67,0x7E68,0x7E69,0x7E6A,0x7E6B,0x7E6C,0x7E6D, +0x7E6E,0x7E6F,0x7E70,0x7E71,0x7E72,0x7E73,0x7E74,0x7E75, +0x7E76,0x7E77,0x7E78,0x7E79,0x7E7A,0x7E7B,0x7E7C,0x7E7D, +0x7E7E,0x7E7F,0x7E80,0x7E81,0x7E83,0x7E84,0x7E85,0x7E86, +0x7E87,0x7E88,0x7E89,0x7E8A,0x7E8B,0x7E8C,0x7E8D,0x7E8E, +0x7E8F,0x7E90,0x7E91,0x7E92,0x7E93,0x7E94,0x7E95,0x7E96, +0x7E97,0x7E98,0x7E99,0x7E9A,0x7E9C,0x7E9D,0x7E9E, 0, +0x7EAE,0x7EB4,0x7EBB,0x7EBC,0x7ED6,0x7EE4,0x7EEC,0x7EF9, +0x7F0A,0x7F10,0x7F1E,0x7F37,0x7F39,0x7F3B,0x7F3C,0x7F3D, +0x7F3E,0x7F3F,0x7F40,0x7F41,0x7F43,0x7F46,0x7F47,0x7F48, +0x7F49,0x7F4A,0x7F4B,0x7F4C,0x7F4D,0x7F4E,0x7F4F,0x7F52, +0x7F53,0x9988,0x6127,0x6E83,0x5764,0x6606,0x6346,0x56F0, +0x62EC,0x6269,0x5ED3,0x9614,0x5783,0x62C9,0x5587,0x8721, +0x814A,0x8FA3,0x5566,0x83B1,0x6765,0x8D56,0x84DD,0x5A6A, +0x680F,0x62E6,0x7BEE,0x9611,0x5170,0x6F9C,0x8C30,0x63FD, +0x89C8,0x61D2,0x7F06,0x70C2,0x6EE5,0x7405,0x6994,0x72FC, +0x5ECA,0x90CE,0x6717,0x6D6A,0x635E,0x52B3,0x7262,0x8001, +0x4F6C,0x59E5,0x916A,0x70D9,0x6D9D,0x52D2,0x4E50,0x96F7, +0x956D,0x857E,0x78CA,0x7D2F,0x5121,0x5792,0x64C2,0x808B, +0x7C7B,0x6CEA,0x68F1,0x695E,0x51B7,0x5398,0x68A8,0x7281, +0x9ECE,0x7BF1,0x72F8,0x79BB,0x6F13,0x7406,0x674E,0x91CC, +0x9CA4,0x793C,0x8389,0x8354,0x540F,0x6817,0x4E3D,0x5389, +0x52B1,0x783E,0x5386,0x5229,0x5088,0x4F8B,0x4FD0, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x7F56,0x7F59,0x7F5B,0x7F5C,0x7F5D,0x7F5E,0x7F60,0x7F63, +0x7F64,0x7F65,0x7F66,0x7F67,0x7F6B,0x7F6C,0x7F6D,0x7F6F, +0x7F70,0x7F73,0x7F75,0x7F76,0x7F77,0x7F78,0x7F7A,0x7F7B, +0x7F7C,0x7F7D,0x7F7F,0x7F80,0x7F82,0x7F83,0x7F84,0x7F85, +0x7F86,0x7F87,0x7F88,0x7F89,0x7F8B,0x7F8D,0x7F8F,0x7F90, +0x7F91,0x7F92,0x7F93,0x7F95,0x7F96,0x7F97,0x7F98,0x7F99, +0x7F9B,0x7F9C,0x7FA0,0x7FA2,0x7FA3,0x7FA5,0x7FA6,0x7FA8, +0x7FA9,0x7FAA,0x7FAB,0x7FAC,0x7FAD,0x7FAE,0x7FB1, 0, +0x7FB3,0x7FB4,0x7FB5,0x7FB6,0x7FB7,0x7FBA,0x7FBB,0x7FBE, +0x7FC0,0x7FC2,0x7FC3,0x7FC4,0x7FC6,0x7FC7,0x7FC8,0x7FC9, +0x7FCB,0x7FCD,0x7FCF,0x7FD0,0x7FD1,0x7FD2,0x7FD3,0x7FD6, +0x7FD7,0x7FD9,0x7FDA,0x7FDB,0x7FDC,0x7FDD,0x7FDE,0x7FE2, +0x7FE3,0x75E2,0x7ACB,0x7C92,0x6CA5,0x96B6,0x529B,0x7483, +0x54E9,0x4FE9,0x8054,0x83B2,0x8FDE,0x9570,0x5EC9,0x601C, +0x6D9F,0x5E18,0x655B,0x8138,0x94FE,0x604B,0x70BC,0x7EC3, +0x7CAE,0x51C9,0x6881,0x7CB1,0x826F,0x4E24,0x8F86,0x91CF, +0x667E,0x4EAE,0x8C05,0x64A9,0x804A,0x50DA,0x7597,0x71CE, +0x5BE5,0x8FBD,0x6F66,0x4E86,0x6482,0x9563,0x5ED6,0x6599, +0x5217,0x88C2,0x70C8,0x52A3,0x730E,0x7433,0x6797,0x78F7, +0x9716,0x4E34,0x90BB,0x9CDE,0x6DCB,0x51DB,0x8D41,0x541D, +0x62CE,0x73B2,0x83F1,0x96F6,0x9F84,0x94C3,0x4F36,0x7F9A, +0x51CC,0x7075,0x9675,0x5CAD,0x9886,0x53E6,0x4EE4,0x6E9C, +0x7409,0x69B4,0x786B,0x998F,0x7559,0x5218,0x7624,0x6D41, +0x67F3,0x516D,0x9F99,0x804B,0x5499,0x7B3C,0x7ABF, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x7FE4,0x7FE7,0x7FE8,0x7FEA,0x7FEB,0x7FEC,0x7FED,0x7FEF, +0x7FF2,0x7FF4,0x7FF5,0x7FF6,0x7FF7,0x7FF8,0x7FF9,0x7FFA, +0x7FFD,0x7FFE,0x7FFF,0x8002,0x8007,0x8008,0x8009,0x800A, +0x800E,0x800F,0x8011,0x8013,0x801A,0x801B,0x801D,0x801E, +0x801F,0x8021,0x8023,0x8024,0x802B,0x802C,0x802D,0x802E, +0x802F,0x8030,0x8032,0x8034,0x8039,0x803A,0x803C,0x803E, +0x8040,0x8041,0x8044,0x8045,0x8047,0x8048,0x8049,0x804E, +0x804F,0x8050,0x8051,0x8053,0x8055,0x8056,0x8057, 0, +0x8059,0x805B,0x805C,0x805D,0x805E,0x805F,0x8060,0x8061, +0x8062,0x8063,0x8064,0x8065,0x8066,0x8067,0x8068,0x806B, +0x806C,0x806D,0x806E,0x806F,0x8070,0x8072,0x8073,0x8074, +0x8075,0x8076,0x8077,0x8078,0x8079,0x807A,0x807B,0x807C, +0x807D,0x9686,0x5784,0x62E2,0x9647,0x697C,0x5A04,0x6402, +0x7BD3,0x6F0F,0x964B,0x82A6,0x5362,0x9885,0x5E90,0x7089, +0x63B3,0x5364,0x864F,0x9C81,0x9E93,0x788C,0x9732,0x8DEF, +0x8D42,0x9E7F,0x6F5E,0x7984,0x5F55,0x9646,0x622E,0x9A74, +0x5415,0x94DD,0x4FA3,0x65C5,0x5C65,0x5C61,0x7F15,0x8651, +0x6C2F,0x5F8B,0x7387,0x6EE4,0x7EFF,0x5CE6,0x631B,0x5B6A, +0x6EE6,0x5375,0x4E71,0x63A0,0x7565,0x62A1,0x8F6E,0x4F26, +0x4ED1,0x6CA6,0x7EB6,0x8BBA,0x841D,0x87BA,0x7F57,0x903B, +0x9523,0x7BA9,0x9AA1,0x88F8,0x843D,0x6D1B,0x9A86,0x7EDC, +0x5988,0x9EBB,0x739B,0x7801,0x8682,0x9A6C,0x9A82,0x561B, +0x5417,0x57CB,0x4E70,0x9EA6,0x5356,0x8FC8,0x8109,0x7792, +0x9992,0x86EE,0x6EE1,0x8513,0x66FC,0x6162,0x6F2B, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x807E,0x8081,0x8082,0x8085,0x8088,0x808A,0x808D,0x808E, +0x808F,0x8090,0x8091,0x8092,0x8094,0x8095,0x8097,0x8099, +0x809E,0x80A3,0x80A6,0x80A7,0x80A8,0x80AC,0x80B0,0x80B3, +0x80B5,0x80B6,0x80B8,0x80B9,0x80BB,0x80C5,0x80C7,0x80C8, +0x80C9,0x80CA,0x80CB,0x80CF,0x80D0,0x80D1,0x80D2,0x80D3, +0x80D4,0x80D5,0x80D8,0x80DF,0x80E0,0x80E2,0x80E3,0x80E6, +0x80EE,0x80F5,0x80F7,0x80F9,0x80FB,0x80FE,0x80FF,0x8100, +0x8101,0x8103,0x8104,0x8105,0x8107,0x8108,0x810B, 0, +0x810C,0x8115,0x8117,0x8119,0x811B,0x811C,0x811D,0x811F, +0x8120,0x8121,0x8122,0x8123,0x8124,0x8125,0x8126,0x8127, +0x8128,0x8129,0x812A,0x812B,0x812D,0x812E,0x8130,0x8133, +0x8134,0x8135,0x8137,0x8139,0x813A,0x813B,0x813C,0x813D, +0x813F,0x8C29,0x8292,0x832B,0x76F2,0x6C13,0x5FD9,0x83BD, +0x732B,0x8305,0x951A,0x6BDB,0x77DB,0x94C6,0x536F,0x8302, +0x5192,0x5E3D,0x8C8C,0x8D38,0x4E48,0x73AB,0x679A,0x6885, +0x9176,0x9709,0x7164,0x6CA1,0x7709,0x5A92,0x9541,0x6BCF, +0x7F8E,0x6627,0x5BD0,0x59B9,0x5A9A,0x95E8,0x95F7,0x4EEC, +0x840C,0x8499,0x6AAC,0x76DF,0x9530,0x731B,0x68A6,0x5B5F, +0x772F,0x919A,0x9761,0x7CDC,0x8FF7,0x8C1C,0x5F25,0x7C73, +0x79D8,0x89C5,0x6CCC,0x871C,0x5BC6,0x5E42,0x68C9,0x7720, +0x7EF5,0x5195,0x514D,0x52C9,0x5A29,0x7F05,0x9762,0x82D7, +0x63CF,0x7784,0x85D0,0x79D2,0x6E3A,0x5E99,0x5999,0x8511, +0x706D,0x6C11,0x62BF,0x76BF,0x654F,0x60AF,0x95FD,0x660E, +0x879F,0x9E23,0x94ED,0x540D,0x547D,0x8C2C,0x6478, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x8140,0x8141,0x8142,0x8143,0x8144,0x8145,0x8147,0x8149, +0x814D,0x814E,0x814F,0x8152,0x8156,0x8157,0x8158,0x815B, +0x815C,0x815D,0x815E,0x815F,0x8161,0x8162,0x8163,0x8164, +0x8166,0x8168,0x816A,0x816B,0x816C,0x816F,0x8172,0x8173, +0x8175,0x8176,0x8177,0x8178,0x8181,0x8183,0x8184,0x8185, +0x8186,0x8187,0x8189,0x818B,0x818C,0x818D,0x818E,0x8190, +0x8192,0x8193,0x8194,0x8195,0x8196,0x8197,0x8199,0x819A, +0x819E,0x819F,0x81A0,0x81A1,0x81A2,0x81A4,0x81A5, 0, +0x81A7,0x81A9,0x81AB,0x81AC,0x81AD,0x81AE,0x81AF,0x81B0, +0x81B1,0x81B2,0x81B4,0x81B5,0x81B6,0x81B7,0x81B8,0x81B9, +0x81BC,0x81BD,0x81BE,0x81BF,0x81C4,0x81C5,0x81C7,0x81C8, +0x81C9,0x81CB,0x81CD,0x81CE,0x81CF,0x81D0,0x81D1,0x81D2, +0x81D3,0x6479,0x8611,0x6A21,0x819C,0x78E8,0x6469,0x9B54, +0x62B9,0x672B,0x83AB,0x58A8,0x9ED8,0x6CAB,0x6F20,0x5BDE, +0x964C,0x8C0B,0x725F,0x67D0,0x62C7,0x7261,0x4EA9,0x59C6, +0x6BCD,0x5893,0x66AE,0x5E55,0x52DF,0x6155,0x6728,0x76EE, +0x7766,0x7267,0x7A46,0x62FF,0x54EA,0x5450,0x94A0,0x90A3, +0x5A1C,0x7EB3,0x6C16,0x4E43,0x5976,0x8010,0x5948,0x5357, +0x7537,0x96BE,0x56CA,0x6320,0x8111,0x607C,0x95F9,0x6DD6, +0x5462,0x9981,0x5185,0x5AE9,0x80FD,0x59AE,0x9713,0x502A, +0x6CE5,0x5C3C,0x62DF,0x4F60,0x533F,0x817B,0x9006,0x6EBA, +0x852B,0x62C8,0x5E74,0x78BE,0x64B5,0x637B,0x5FF5,0x5A18, +0x917F,0x9E1F,0x5C3F,0x634F,0x8042,0x5B7D,0x556E,0x954A, +0x954D,0x6D85,0x60A8,0x67E0,0x72DE,0x51DD,0x5B81, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x81D4,0x81D5,0x81D6,0x81D7,0x81D8,0x81D9,0x81DA,0x81DB, +0x81DC,0x81DD,0x81DE,0x81DF,0x81E0,0x81E1,0x81E2,0x81E4, +0x81E5,0x81E6,0x81E8,0x81E9,0x81EB,0x81EE,0x81EF,0x81F0, +0x81F1,0x81F2,0x81F5,0x81F6,0x81F7,0x81F8,0x81F9,0x81FA, +0x81FD,0x81FF,0x8203,0x8207,0x8208,0x8209,0x820A,0x820B, +0x820E,0x820F,0x8211,0x8213,0x8215,0x8216,0x8217,0x8218, +0x8219,0x821A,0x821D,0x8220,0x8224,0x8225,0x8226,0x8227, +0x8229,0x822E,0x8232,0x823A,0x823C,0x823D,0x823F, 0, +0x8240,0x8241,0x8242,0x8243,0x8245,0x8246,0x8248,0x824A, +0x824C,0x824D,0x824E,0x8250,0x8251,0x8252,0x8253,0x8254, +0x8255,0x8256,0x8257,0x8259,0x825B,0x825C,0x825D,0x825E, +0x8260,0x8261,0x8262,0x8263,0x8264,0x8265,0x8266,0x8267, +0x8269,0x62E7,0x6CDE,0x725B,0x626D,0x94AE,0x7EBD,0x8113, +0x6D53,0x519C,0x5F04,0x5974,0x52AA,0x6012,0x5973,0x6696, +0x8650,0x759F,0x632A,0x61E6,0x7CEF,0x8BFA,0x54E6,0x6B27, +0x9E25,0x6BB4,0x85D5,0x5455,0x5076,0x6CA4,0x556A,0x8DB4, +0x722C,0x5E15,0x6015,0x7436,0x62CD,0x6392,0x724C,0x5F98, +0x6E43,0x6D3E,0x6500,0x6F58,0x76D8,0x78D0,0x76FC,0x7554, +0x5224,0x53DB,0x4E53,0x5E9E,0x65C1,0x802A,0x80D6,0x629B, +0x5486,0x5228,0x70AE,0x888D,0x8DD1,0x6CE1,0x5478,0x80DA, +0x57F9,0x88F4,0x8D54,0x966A,0x914D,0x4F69,0x6C9B,0x55B7, +0x76C6,0x7830,0x62A8,0x70F9,0x6F8E,0x5F6D,0x84EC,0x68DA, +0x787C,0x7BF7,0x81A8,0x670B,0x9E4F,0x6367,0x78B0,0x576F, +0x7812,0x9739,0x6279,0x62AB,0x5288,0x7435,0x6BD7, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x826A,0x826B,0x826C,0x826D,0x8271,0x8275,0x8276,0x8277, +0x8278,0x827B,0x827C,0x8280,0x8281,0x8283,0x8285,0x8286, +0x8287,0x8289,0x828C,0x8290,0x8293,0x8294,0x8295,0x8296, +0x829A,0x829B,0x829E,0x82A0,0x82A2,0x82A3,0x82A7,0x82B2, +0x82B5,0x82B6,0x82BA,0x82BB,0x82BC,0x82BF,0x82C0,0x82C2, +0x82C3,0x82C5,0x82C6,0x82C9,0x82D0,0x82D6,0x82D9,0x82DA, +0x82DD,0x82E2,0x82E7,0x82E8,0x82E9,0x82EA,0x82EC,0x82ED, +0x82EE,0x82F0,0x82F2,0x82F3,0x82F5,0x82F6,0x82F8, 0, +0x82FA,0x82FC,0x82FD,0x82FE,0x82FF,0x8300,0x830A,0x830B, +0x830D,0x8310,0x8312,0x8313,0x8316,0x8318,0x8319,0x831D, +0x831E,0x831F,0x8320,0x8321,0x8322,0x8323,0x8324,0x8325, +0x8326,0x8329,0x832A,0x832E,0x8330,0x8332,0x8337,0x833B, +0x833D,0x5564,0x813E,0x75B2,0x76AE,0x5339,0x75DE,0x50FB, +0x5C41,0x8B6C,0x7BC7,0x504F,0x7247,0x9A97,0x98D8,0x6F02, +0x74E2,0x7968,0x6487,0x77A5,0x62FC,0x9891,0x8D2B,0x54C1, +0x8058,0x4E52,0x576A,0x82F9,0x840D,0x5E73,0x51ED,0x74F6, +0x8BC4,0x5C4F,0x5761,0x6CFC,0x9887,0x5A46,0x7834,0x9B44, +0x8FEB,0x7C95,0x5256,0x6251,0x94FA,0x4EC6,0x8386,0x8461, +0x83E9,0x84B2,0x57D4,0x6734,0x5703,0x666E,0x6D66,0x8C31, +0x66DD,0x7011,0x671F,0x6B3A,0x6816,0x621A,0x59BB,0x4E03, +0x51C4,0x6F06,0x67D2,0x6C8F,0x5176,0x68CB,0x5947,0x6B67, +0x7566,0x5D0E,0x8110,0x9F50,0x65D7,0x7948,0x7941,0x9A91, +0x8D77,0x5C82,0x4E5E,0x4F01,0x542F,0x5951,0x780C,0x5668, +0x6C14,0x8FC4,0x5F03,0x6C7D,0x6CE3,0x8BAB,0x6390, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x833E,0x833F,0x8341,0x8342,0x8344,0x8345,0x8348,0x834A, +0x834B,0x834C,0x834D,0x834E,0x8353,0x8355,0x8356,0x8357, +0x8358,0x8359,0x835D,0x8362,0x8370,0x8371,0x8372,0x8373, +0x8374,0x8375,0x8376,0x8379,0x837A,0x837E,0x837F,0x8380, +0x8381,0x8382,0x8383,0x8384,0x8387,0x8388,0x838A,0x838B, +0x838C,0x838D,0x838F,0x8390,0x8391,0x8394,0x8395,0x8396, +0x8397,0x8399,0x839A,0x839D,0x839F,0x83A1,0x83A2,0x83A3, +0x83A4,0x83A5,0x83A6,0x83A7,0x83AC,0x83AD,0x83AE, 0, +0x83AF,0x83B5,0x83BB,0x83BE,0x83BF,0x83C2,0x83C3,0x83C4, +0x83C6,0x83C8,0x83C9,0x83CB,0x83CD,0x83CE,0x83D0,0x83D1, +0x83D2,0x83D3,0x83D5,0x83D7,0x83D9,0x83DA,0x83DB,0x83DE, +0x83E2,0x83E3,0x83E4,0x83E6,0x83E7,0x83E8,0x83EB,0x83EC, +0x83ED,0x6070,0x6D3D,0x7275,0x6266,0x948E,0x94C5,0x5343, +0x8FC1,0x7B7E,0x4EDF,0x8C26,0x4E7E,0x9ED4,0x94B1,0x94B3, +0x524D,0x6F5C,0x9063,0x6D45,0x8C34,0x5811,0x5D4C,0x6B20, +0x6B49,0x67AA,0x545B,0x8154,0x7F8C,0x5899,0x8537,0x5F3A, +0x62A2,0x6A47,0x9539,0x6572,0x6084,0x6865,0x77A7,0x4E54, +0x4FA8,0x5DE7,0x9798,0x64AC,0x7FD8,0x5CED,0x4FCF,0x7A8D, +0x5207,0x8304,0x4E14,0x602F,0x7A83,0x94A6,0x4FB5,0x4EB2, +0x79E6,0x7434,0x52E4,0x82B9,0x64D2,0x79BD,0x5BDD,0x6C81, +0x9752,0x8F7B,0x6C22,0x503E,0x537F,0x6E05,0x64CE,0x6674, +0x6C30,0x60C5,0x9877,0x8BF7,0x5E86,0x743C,0x7A77,0x79CB, +0x4E18,0x90B1,0x7403,0x6C42,0x56DA,0x914B,0x6CC5,0x8D8B, +0x533A,0x86C6,0x66F2,0x8EAF,0x5C48,0x9A71,0x6E20, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x83EE,0x83EF,0x83F3,0x83F4,0x83F5,0x83F6,0x83F7,0x83FA, +0x83FB,0x83FC,0x83FE,0x83FF,0x8400,0x8402,0x8405,0x8407, +0x8408,0x8409,0x840A,0x8410,0x8412,0x8413,0x8414,0x8415, +0x8416,0x8417,0x8419,0x841A,0x841B,0x841E,0x841F,0x8420, +0x8421,0x8422,0x8423,0x8429,0x842A,0x842B,0x842C,0x842D, +0x842E,0x842F,0x8430,0x8432,0x8433,0x8434,0x8435,0x8436, +0x8437,0x8439,0x843A,0x843B,0x843E,0x843F,0x8440,0x8441, +0x8442,0x8443,0x8444,0x8445,0x8447,0x8448,0x8449, 0, +0x844A,0x844B,0x844C,0x844D,0x844E,0x844F,0x8450,0x8452, +0x8453,0x8454,0x8455,0x8456,0x8458,0x845D,0x845E,0x845F, +0x8460,0x8462,0x8464,0x8465,0x8466,0x8467,0x8468,0x846A, +0x846E,0x846F,0x8470,0x8472,0x8474,0x8477,0x8479,0x847B, +0x847C,0x53D6,0x5A36,0x9F8B,0x8DA3,0x53BB,0x5708,0x98A7, +0x6743,0x919B,0x6CC9,0x5168,0x75CA,0x62F3,0x72AC,0x5238, +0x529D,0x7F3A,0x7094,0x7638,0x5374,0x9E4A,0x69B7,0x786E, +0x96C0,0x88D9,0x7FA4,0x7136,0x71C3,0x5189,0x67D3,0x74E4, +0x58E4,0x6518,0x56B7,0x8BA9,0x9976,0x6270,0x7ED5,0x60F9, +0x70ED,0x58EC,0x4EC1,0x4EBA,0x5FCD,0x97E7,0x4EFB,0x8BA4, +0x5203,0x598A,0x7EAB,0x6254,0x4ECD,0x65E5,0x620E,0x8338, +0x84C9,0x8363,0x878D,0x7194,0x6EB6,0x5BB9,0x7ED2,0x5197, +0x63C9,0x67D4,0x8089,0x8339,0x8815,0x5112,0x5B7A,0x5982, +0x8FB1,0x4E73,0x6C5D,0x5165,0x8925,0x8F6F,0x962E,0x854A, +0x745E,0x9510,0x95F0,0x6DA6,0x82E5,0x5F31,0x6492,0x6D12, +0x8428,0x816E,0x9CC3,0x585E,0x8D5B,0x4E09,0x53C1, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x847D,0x847E,0x847F,0x8480,0x8481,0x8483,0x8484,0x8485, +0x8486,0x848A,0x848D,0x848F,0x8490,0x8491,0x8492,0x8493, +0x8494,0x8495,0x8496,0x8498,0x849A,0x849B,0x849D,0x849E, +0x849F,0x84A0,0x84A2,0x84A3,0x84A4,0x84A5,0x84A6,0x84A7, +0x84A8,0x84A9,0x84AA,0x84AB,0x84AC,0x84AD,0x84AE,0x84B0, +0x84B1,0x84B3,0x84B5,0x84B6,0x84B7,0x84BB,0x84BC,0x84BE, +0x84C0,0x84C2,0x84C3,0x84C5,0x84C6,0x84C7,0x84C8,0x84CB, +0x84CC,0x84CE,0x84CF,0x84D2,0x84D4,0x84D5,0x84D7, 0, +0x84D8,0x84D9,0x84DA,0x84DB,0x84DC,0x84DE,0x84E1,0x84E2, +0x84E4,0x84E7,0x84E8,0x84E9,0x84EA,0x84EB,0x84ED,0x84EE, +0x84EF,0x84F1,0x84F2,0x84F3,0x84F4,0x84F5,0x84F6,0x84F7, +0x84F8,0x84F9,0x84FA,0x84FB,0x84FD,0x84FE,0x8500,0x8501, +0x8502,0x4F1E,0x6563,0x6851,0x55D3,0x4E27,0x6414,0x9A9A, +0x626B,0x5AC2,0x745F,0x8272,0x6DA9,0x68EE,0x50E7,0x838E, +0x7802,0x6740,0x5239,0x6C99,0x7EB1,0x50BB,0x5565,0x715E, +0x7B5B,0x6652,0x73CA,0x82EB,0x6749,0x5C71,0x5220,0x717D, +0x886B,0x95EA,0x9655,0x64C5,0x8D61,0x81B3,0x5584,0x6C55, +0x6247,0x7F2E,0x5892,0x4F24,0x5546,0x8D4F,0x664C,0x4E0A, +0x5C1A,0x88F3,0x68A2,0x634E,0x7A0D,0x70E7,0x828D,0x52FA, +0x97F6,0x5C11,0x54E8,0x90B5,0x7ECD,0x5962,0x8D4A,0x86C7, +0x820C,0x820D,0x8D66,0x6444,0x5C04,0x6151,0x6D89,0x793E, +0x8BBE,0x7837,0x7533,0x547B,0x4F38,0x8EAB,0x6DF1,0x5A20, +0x7EC5,0x795E,0x6C88,0x5BA1,0x5A76,0x751A,0x80BE,0x614E, +0x6E17,0x58F0,0x751F,0x7525,0x7272,0x5347,0x7EF3, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x8503,0x8504,0x8505,0x8506,0x8507,0x8508,0x8509,0x850A, +0x850B,0x850D,0x850E,0x850F,0x8510,0x8512,0x8514,0x8515, +0x8516,0x8518,0x8519,0x851B,0x851C,0x851D,0x851E,0x8520, +0x8522,0x8523,0x8524,0x8525,0x8526,0x8527,0x8528,0x8529, +0x852A,0x852D,0x852E,0x852F,0x8530,0x8531,0x8532,0x8533, +0x8534,0x8535,0x8536,0x853E,0x853F,0x8540,0x8541,0x8542, +0x8544,0x8545,0x8546,0x8547,0x854B,0x854C,0x854D,0x854E, +0x854F,0x8550,0x8551,0x8552,0x8553,0x8554,0x8555, 0, +0x8557,0x8558,0x855A,0x855B,0x855C,0x855D,0x855F,0x8560, +0x8561,0x8562,0x8563,0x8565,0x8566,0x8567,0x8569,0x856A, +0x856B,0x856C,0x856D,0x856E,0x856F,0x8570,0x8571,0x8573, +0x8575,0x8576,0x8577,0x8578,0x857C,0x857D,0x857F,0x8580, +0x8581,0x7701,0x76DB,0x5269,0x80DC,0x5723,0x5E08,0x5931, +0x72EE,0x65BD,0x6E7F,0x8BD7,0x5C38,0x8671,0x5341,0x77F3, +0x62FE,0x65F6,0x4EC0,0x98DF,0x8680,0x5B9E,0x8BC6,0x53F2, +0x77E2,0x4F7F,0x5C4E,0x9A76,0x59CB,0x5F0F,0x793A,0x58EB, +0x4E16,0x67FF,0x4E8B,0x62ED,0x8A93,0x901D,0x52BF,0x662F, +0x55DC,0x566C,0x9002,0x4ED5,0x4F8D,0x91CA,0x9970,0x6C0F, +0x5E02,0x6043,0x5BA4,0x89C6,0x8BD5,0x6536,0x624B,0x9996, +0x5B88,0x5BFF,0x6388,0x552E,0x53D7,0x7626,0x517D,0x852C, +0x67A2,0x68B3,0x6B8A,0x6292,0x8F93,0x53D4,0x8212,0x6DD1, +0x758F,0x4E66,0x8D4E,0x5B70,0x719F,0x85AF,0x6691,0x66D9, +0x7F72,0x8700,0x9ECD,0x9F20,0x5C5E,0x672F,0x8FF0,0x6811, +0x675F,0x620D,0x7AD6,0x5885,0x5EB6,0x6570,0x6F31, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x8582,0x8583,0x8586,0x8588,0x8589,0x858A,0x858B,0x858C, +0x858D,0x858E,0x8590,0x8591,0x8592,0x8593,0x8594,0x8595, +0x8596,0x8597,0x8598,0x8599,0x859A,0x859D,0x859E,0x859F, +0x85A0,0x85A1,0x85A2,0x85A3,0x85A5,0x85A6,0x85A7,0x85A9, +0x85AB,0x85AC,0x85AD,0x85B1,0x85B2,0x85B3,0x85B4,0x85B5, +0x85B6,0x85B8,0x85BA,0x85BB,0x85BC,0x85BD,0x85BE,0x85BF, +0x85C0,0x85C2,0x85C3,0x85C4,0x85C5,0x85C6,0x85C7,0x85C8, +0x85CA,0x85CB,0x85CC,0x85CD,0x85CE,0x85D1,0x85D2, 0, +0x85D4,0x85D6,0x85D7,0x85D8,0x85D9,0x85DA,0x85DB,0x85DD, +0x85DE,0x85DF,0x85E0,0x85E1,0x85E2,0x85E3,0x85E5,0x85E6, +0x85E7,0x85E8,0x85EA,0x85EB,0x85EC,0x85ED,0x85EE,0x85EF, +0x85F0,0x85F1,0x85F2,0x85F3,0x85F4,0x85F5,0x85F6,0x85F7, +0x85F8,0x6055,0x5237,0x800D,0x6454,0x8870,0x7529,0x5E05, +0x6813,0x62F4,0x971C,0x53CC,0x723D,0x8C01,0x6C34,0x7761, +0x7A0E,0x542E,0x77AC,0x987A,0x821C,0x8BF4,0x7855,0x6714, +0x70C1,0x65AF,0x6495,0x5636,0x601D,0x79C1,0x53F8,0x4E1D, +0x6B7B,0x8086,0x5BFA,0x55E3,0x56DB,0x4F3A,0x4F3C,0x9972, +0x5DF3,0x677E,0x8038,0x6002,0x9882,0x9001,0x5B8B,0x8BBC, +0x8BF5,0x641C,0x8258,0x64DE,0x55FD,0x82CF,0x9165,0x4FD7, +0x7D20,0x901F,0x7C9F,0x50F3,0x5851,0x6EAF,0x5BBF,0x8BC9, +0x8083,0x9178,0x849C,0x7B97,0x867D,0x968B,0x968F,0x7EE5, +0x9AD3,0x788E,0x5C81,0x7A57,0x9042,0x96A7,0x795F,0x5B59, +0x635F,0x7B0B,0x84D1,0x68AD,0x5506,0x7F29,0x7410,0x7D22, +0x9501,0x6240,0x584C,0x4ED6,0x5B83,0x5979,0x5854, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x85F9,0x85FA,0x85FC,0x85FD,0x85FE,0x8600,0x8601,0x8602, +0x8603,0x8604,0x8606,0x8607,0x8608,0x8609,0x860A,0x860B, +0x860C,0x860D,0x860E,0x860F,0x8610,0x8612,0x8613,0x8614, +0x8615,0x8617,0x8618,0x8619,0x861A,0x861B,0x861C,0x861D, +0x861E,0x861F,0x8620,0x8621,0x8622,0x8623,0x8624,0x8625, +0x8626,0x8628,0x862A,0x862B,0x862C,0x862D,0x862E,0x862F, +0x8630,0x8631,0x8632,0x8633,0x8634,0x8635,0x8636,0x8637, +0x8639,0x863A,0x863B,0x863D,0x863E,0x863F,0x8640, 0, +0x8641,0x8642,0x8643,0x8644,0x8645,0x8646,0x8647,0x8648, +0x8649,0x864A,0x864B,0x864C,0x8652,0x8653,0x8655,0x8656, +0x8657,0x8658,0x8659,0x865B,0x865C,0x865D,0x865F,0x8660, +0x8661,0x8663,0x8664,0x8665,0x8666,0x8667,0x8668,0x8669, +0x866A,0x736D,0x631E,0x8E4B,0x8E0F,0x80CE,0x82D4,0x62AC, +0x53F0,0x6CF0,0x915E,0x592A,0x6001,0x6C70,0x574D,0x644A, +0x8D2A,0x762B,0x6EE9,0x575B,0x6A80,0x75F0,0x6F6D,0x8C2D, +0x8C08,0x5766,0x6BEF,0x8892,0x78B3,0x63A2,0x53F9,0x70AD, +0x6C64,0x5858,0x642A,0x5802,0x68E0,0x819B,0x5510,0x7CD6, +0x5018,0x8EBA,0x6DCC,0x8D9F,0x70EB,0x638F,0x6D9B,0x6ED4, +0x7EE6,0x8404,0x6843,0x9003,0x6DD8,0x9676,0x8BA8,0x5957, +0x7279,0x85E4,0x817E,0x75BC,0x8A8A,0x68AF,0x5254,0x8E22, +0x9511,0x63D0,0x9898,0x8E44,0x557C,0x4F53,0x66FF,0x568F, +0x60D5,0x6D95,0x5243,0x5C49,0x5929,0x6DFB,0x586B,0x7530, +0x751C,0x606C,0x8214,0x8146,0x6311,0x6761,0x8FE2,0x773A, +0x8DF3,0x8D34,0x94C1,0x5E16,0x5385,0x542C,0x70C3, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x866D,0x866F,0x8670,0x8672,0x8673,0x8674,0x8675,0x8676, +0x8677,0x8678,0x8683,0x8684,0x8685,0x8686,0x8687,0x8688, +0x8689,0x868E,0x868F,0x8690,0x8691,0x8692,0x8694,0x8696, +0x8697,0x8698,0x8699,0x869A,0x869B,0x869E,0x869F,0x86A0, +0x86A1,0x86A2,0x86A5,0x86A6,0x86AB,0x86AD,0x86AE,0x86B2, +0x86B3,0x86B7,0x86B8,0x86B9,0x86BB,0x86BC,0x86BD,0x86BE, +0x86BF,0x86C1,0x86C2,0x86C3,0x86C5,0x86C8,0x86CC,0x86CD, +0x86D2,0x86D3,0x86D5,0x86D6,0x86D7,0x86DA,0x86DC, 0, +0x86DD,0x86E0,0x86E1,0x86E2,0x86E3,0x86E5,0x86E6,0x86E7, +0x86E8,0x86EA,0x86EB,0x86EC,0x86EF,0x86F5,0x86F6,0x86F7, +0x86FA,0x86FB,0x86FC,0x86FD,0x86FF,0x8701,0x8704,0x8705, +0x8706,0x870B,0x870C,0x870E,0x870F,0x8710,0x8711,0x8714, +0x8716,0x6C40,0x5EF7,0x505C,0x4EAD,0x5EAD,0x633A,0x8247, +0x901A,0x6850,0x916E,0x77B3,0x540C,0x94DC,0x5F64,0x7AE5, +0x6876,0x6345,0x7B52,0x7EDF,0x75DB,0x5077,0x6295,0x5934, +0x900F,0x51F8,0x79C3,0x7A81,0x56FE,0x5F92,0x9014,0x6D82, +0x5C60,0x571F,0x5410,0x5154,0x6E4D,0x56E2,0x63A8,0x9893, +0x817F,0x8715,0x892A,0x9000,0x541E,0x5C6F,0x81C0,0x62D6, +0x6258,0x8131,0x9E35,0x9640,0x9A6E,0x9A7C,0x692D,0x59A5, +0x62D3,0x553E,0x6316,0x54C7,0x86D9,0x6D3C,0x5A03,0x74E6, +0x889C,0x6B6A,0x5916,0x8C4C,0x5F2F,0x6E7E,0x73A9,0x987D, +0x4E38,0x70F7,0x5B8C,0x7897,0x633D,0x665A,0x7696,0x60CB, +0x5B9B,0x5A49,0x4E07,0x8155,0x6C6A,0x738B,0x4EA1,0x6789, +0x7F51,0x5F80,0x65FA,0x671B,0x5FD8,0x5984,0x5A01, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x8719,0x871B,0x871D,0x871F,0x8720,0x8724,0x8726,0x8727, +0x8728,0x872A,0x872B,0x872C,0x872D,0x872F,0x8730,0x8732, +0x8733,0x8735,0x8736,0x8738,0x8739,0x873A,0x873C,0x873D, +0x8740,0x8741,0x8742,0x8743,0x8744,0x8745,0x8746,0x874A, +0x874B,0x874D,0x874F,0x8750,0x8751,0x8752,0x8754,0x8755, +0x8756,0x8758,0x875A,0x875B,0x875C,0x875D,0x875E,0x875F, +0x8761,0x8762,0x8766,0x8767,0x8768,0x8769,0x876A,0x876B, +0x876C,0x876D,0x876F,0x8771,0x8772,0x8773,0x8775, 0, +0x8777,0x8778,0x8779,0x877A,0x877F,0x8780,0x8781,0x8784, +0x8786,0x8787,0x8789,0x878A,0x878C,0x878E,0x878F,0x8790, +0x8791,0x8792,0x8794,0x8795,0x8796,0x8798,0x8799,0x879A, +0x879B,0x879C,0x879D,0x879E,0x87A0,0x87A1,0x87A2,0x87A3, +0x87A4,0x5DCD,0x5FAE,0x5371,0x97E6,0x8FDD,0x6845,0x56F4, +0x552F,0x60DF,0x4E3A,0x6F4D,0x7EF4,0x82C7,0x840E,0x59D4, +0x4F1F,0x4F2A,0x5C3E,0x7EAC,0x672A,0x851A,0x5473,0x754F, +0x80C3,0x5582,0x9B4F,0x4F4D,0x6E2D,0x8C13,0x5C09,0x6170, +0x536B,0x761F,0x6E29,0x868A,0x6587,0x95FB,0x7EB9,0x543B, +0x7A33,0x7D0A,0x95EE,0x55E1,0x7FC1,0x74EE,0x631D,0x8717, +0x6DA1,0x7A9D,0x6211,0x65A1,0x5367,0x63E1,0x6C83,0x5DEB, +0x545C,0x94A8,0x4E4C,0x6C61,0x8BEC,0x5C4B,0x65E0,0x829C, +0x68A7,0x543E,0x5434,0x6BCB,0x6B66,0x4E94,0x6342,0x5348, +0x821E,0x4F0D,0x4FAE,0x575E,0x620A,0x96FE,0x6664,0x7269, +0x52FF,0x52A1,0x609F,0x8BEF,0x6614,0x7199,0x6790,0x897F, +0x7852,0x77FD,0x6670,0x563B,0x5438,0x9521,0x727A, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x87A5,0x87A6,0x87A7,0x87A9,0x87AA,0x87AE,0x87B0,0x87B1, +0x87B2,0x87B4,0x87B6,0x87B7,0x87B8,0x87B9,0x87BB,0x87BC, +0x87BE,0x87BF,0x87C1,0x87C2,0x87C3,0x87C4,0x87C5,0x87C7, +0x87C8,0x87C9,0x87CC,0x87CD,0x87CE,0x87CF,0x87D0,0x87D4, +0x87D5,0x87D6,0x87D7,0x87D8,0x87D9,0x87DA,0x87DC,0x87DD, +0x87DE,0x87DF,0x87E1,0x87E2,0x87E3,0x87E4,0x87E6,0x87E7, +0x87E8,0x87E9,0x87EB,0x87EC,0x87ED,0x87EF,0x87F0,0x87F1, +0x87F2,0x87F3,0x87F4,0x87F5,0x87F6,0x87F7,0x87F8, 0, +0x87FA,0x87FB,0x87FC,0x87FD,0x87FF,0x8800,0x8801,0x8802, +0x8804,0x8805,0x8806,0x8807,0x8808,0x8809,0x880B,0x880C, +0x880D,0x880E,0x880F,0x8810,0x8811,0x8812,0x8814,0x8817, +0x8818,0x8819,0x881A,0x881C,0x881D,0x881E,0x881F,0x8820, +0x8823,0x7A00,0x606F,0x5E0C,0x6089,0x819D,0x5915,0x60DC, +0x7184,0x70EF,0x6EAA,0x6C50,0x7280,0x6A84,0x88AD,0x5E2D, +0x4E60,0x5AB3,0x559C,0x94E3,0x6D17,0x7CFB,0x9699,0x620F, +0x7EC6,0x778E,0x867E,0x5323,0x971E,0x8F96,0x6687,0x5CE1, +0x4FA0,0x72ED,0x4E0B,0x53A6,0x590F,0x5413,0x6380,0x9528, +0x5148,0x4ED9,0x9C9C,0x7EA4,0x54B8,0x8D24,0x8854,0x8237, +0x95F2,0x6D8E,0x5F26,0x5ACC,0x663E,0x9669,0x73B0,0x732E, +0x53BF,0x817A,0x9985,0x7FA1,0x5BAA,0x9677,0x9650,0x7EBF, +0x76F8,0x53A2,0x9576,0x9999,0x7BB1,0x8944,0x6E58,0x4E61, +0x7FD4,0x7965,0x8BE6,0x60F3,0x54CD,0x4EAB,0x9879,0x5DF7, +0x6A61,0x50CF,0x5411,0x8C61,0x8427,0x785D,0x9704,0x524A, +0x54EE,0x56A3,0x9500,0x6D88,0x5BB5,0x6DC6,0x6653, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x8824,0x8825,0x8826,0x8827,0x8828,0x8829,0x882A,0x882B, +0x882C,0x882D,0x882E,0x882F,0x8830,0x8831,0x8833,0x8834, +0x8835,0x8836,0x8837,0x8838,0x883A,0x883B,0x883D,0x883E, +0x883F,0x8841,0x8842,0x8843,0x8846,0x8847,0x8848,0x8849, +0x884A,0x884B,0x884E,0x884F,0x8850,0x8851,0x8852,0x8853, +0x8855,0x8856,0x8858,0x885A,0x885B,0x885C,0x885D,0x885E, +0x885F,0x8860,0x8866,0x8867,0x886A,0x886D,0x886F,0x8871, +0x8873,0x8874,0x8875,0x8876,0x8878,0x8879,0x887A, 0, +0x887B,0x887C,0x8880,0x8883,0x8886,0x8887,0x8889,0x888A, +0x888C,0x888E,0x888F,0x8890,0x8891,0x8893,0x8894,0x8895, +0x8897,0x8898,0x8899,0x889A,0x889B,0x889D,0x889E,0x889F, +0x88A0,0x88A1,0x88A3,0x88A5,0x88A6,0x88A7,0x88A8,0x88A9, +0x88AA,0x5C0F,0x5B5D,0x6821,0x8096,0x5578,0x7B11,0x6548, +0x6954,0x4E9B,0x6B47,0x874E,0x978B,0x534F,0x631F,0x643A, +0x90AA,0x659C,0x80C1,0x8C10,0x5199,0x68B0,0x5378,0x87F9, +0x61C8,0x6CC4,0x6CFB,0x8C22,0x5C51,0x85AA,0x82AF,0x950C, +0x6B23,0x8F9B,0x65B0,0x5FFB,0x5FC3,0x4FE1,0x8845,0x661F, +0x8165,0x7329,0x60FA,0x5174,0x5211,0x578B,0x5F62,0x90A2, +0x884C,0x9192,0x5E78,0x674F,0x6027,0x59D3,0x5144,0x51F6, +0x80F8,0x5308,0x6C79,0x96C4,0x718A,0x4F11,0x4FEE,0x7F9E, +0x673D,0x55C5,0x9508,0x79C0,0x8896,0x7EE3,0x589F,0x620C, +0x9700,0x865A,0x5618,0x987B,0x5F90,0x8BB8,0x84C4,0x9157, +0x53D9,0x65ED,0x5E8F,0x755C,0x6064,0x7D6E,0x5A7F,0x7EEA, +0x7EED,0x8F69,0x55A7,0x5BA3,0x60AC,0x65CB,0x7384, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x88AC,0x88AE,0x88AF,0x88B0,0x88B2,0x88B3,0x88B4,0x88B5, +0x88B6,0x88B8,0x88B9,0x88BA,0x88BB,0x88BD,0x88BE,0x88BF, +0x88C0,0x88C3,0x88C4,0x88C7,0x88C8,0x88CA,0x88CB,0x88CC, +0x88CD,0x88CF,0x88D0,0x88D1,0x88D3,0x88D6,0x88D7,0x88DA, +0x88DB,0x88DC,0x88DD,0x88DE,0x88E0,0x88E1,0x88E6,0x88E7, +0x88E9,0x88EA,0x88EB,0x88EC,0x88ED,0x88EE,0x88EF,0x88F2, +0x88F5,0x88F6,0x88F7,0x88FA,0x88FB,0x88FD,0x88FF,0x8900, +0x8901,0x8903,0x8904,0x8905,0x8906,0x8907,0x8908, 0, +0x8909,0x890B,0x890C,0x890D,0x890E,0x890F,0x8911,0x8914, +0x8915,0x8916,0x8917,0x8918,0x891C,0x891D,0x891E,0x891F, +0x8920,0x8922,0x8923,0x8924,0x8926,0x8927,0x8928,0x8929, +0x892C,0x892D,0x892E,0x892F,0x8931,0x8932,0x8933,0x8935, +0x8937,0x9009,0x7663,0x7729,0x7EDA,0x9774,0x859B,0x5B66, +0x7A74,0x96EA,0x8840,0x52CB,0x718F,0x5FAA,0x65EC,0x8BE2, +0x5BFB,0x9A6F,0x5DE1,0x6B89,0x6C5B,0x8BAD,0x8BAF,0x900A, +0x8FC5,0x538B,0x62BC,0x9E26,0x9E2D,0x5440,0x4E2B,0x82BD, +0x7259,0x869C,0x5D16,0x8859,0x6DAF,0x96C5,0x54D1,0x4E9A, +0x8BB6,0x7109,0x54BD,0x9609,0x70DF,0x6DF9,0x76D0,0x4E25, +0x7814,0x8712,0x5CA9,0x5EF6,0x8A00,0x989C,0x960E,0x708E, +0x6CBF,0x5944,0x63A9,0x773C,0x884D,0x6F14,0x8273,0x5830, +0x71D5,0x538C,0x781A,0x96C1,0x5501,0x5F66,0x7130,0x5BB4, +0x8C1A,0x9A8C,0x6B83,0x592E,0x9E2F,0x79E7,0x6768,0x626C, +0x4F6F,0x75A1,0x7F8A,0x6D0B,0x9633,0x6C27,0x4EF0,0x75D2, +0x517B,0x6837,0x6F3E,0x9080,0x8170,0x5996,0x7476, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x8938,0x8939,0x893A,0x893B,0x893C,0x893D,0x893E,0x893F, +0x8940,0x8942,0x8943,0x8945,0x8946,0x8947,0x8948,0x8949, +0x894A,0x894B,0x894C,0x894D,0x894E,0x894F,0x8950,0x8951, +0x8952,0x8953,0x8954,0x8955,0x8956,0x8957,0x8958,0x8959, +0x895A,0x895B,0x895C,0x895D,0x8960,0x8961,0x8962,0x8963, +0x8964,0x8965,0x8967,0x8968,0x8969,0x896A,0x896B,0x896C, +0x896D,0x896E,0x896F,0x8970,0x8971,0x8972,0x8973,0x8974, +0x8975,0x8976,0x8977,0x8978,0x8979,0x897A,0x897C, 0, +0x897D,0x897E,0x8980,0x8982,0x8984,0x8985,0x8987,0x8988, +0x8989,0x898A,0x898B,0x898C,0x898D,0x898E,0x898F,0x8990, +0x8991,0x8992,0x8993,0x8994,0x8995,0x8996,0x8997,0x8998, +0x8999,0x899A,0x899B,0x899C,0x899D,0x899E,0x899F,0x89A0, +0x89A1,0x6447,0x5C27,0x9065,0x7A91,0x8C23,0x59DA,0x54AC, +0x8200,0x836F,0x8981,0x8000,0x6930,0x564E,0x8036,0x7237, +0x91CE,0x51B6,0x4E5F,0x9875,0x6396,0x4E1A,0x53F6,0x66F3, +0x814B,0x591C,0x6DB2,0x4E00,0x58F9,0x533B,0x63D6,0x94F1, +0x4F9D,0x4F0A,0x8863,0x9890,0x5937,0x9057,0x79FB,0x4EEA, +0x80F0,0x7591,0x6C82,0x5B9C,0x59E8,0x5F5D,0x6905,0x8681, +0x501A,0x5DF2,0x4E59,0x77E3,0x4EE5,0x827A,0x6291,0x6613, +0x9091,0x5C79,0x4EBF,0x5F79,0x81C6,0x9038,0x8084,0x75AB, +0x4EA6,0x88D4,0x610F,0x6BC5,0x5FC6,0x4E49,0x76CA,0x6EA2, +0x8BE3,0x8BAE,0x8C0A,0x8BD1,0x5F02,0x7FFC,0x7FCC,0x7ECE, +0x8335,0x836B,0x56E0,0x6BB7,0x97F3,0x9634,0x59FB,0x541F, +0x94F6,0x6DEB,0x5BC5,0x996E,0x5C39,0x5F15,0x9690, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x89A2,0x89A3,0x89A4,0x89A5,0x89A6,0x89A7,0x89A8,0x89A9, +0x89AA,0x89AB,0x89AC,0x89AD,0x89AE,0x89AF,0x89B0,0x89B1, +0x89B2,0x89B3,0x89B4,0x89B5,0x89B6,0x89B7,0x89B8,0x89B9, +0x89BA,0x89BB,0x89BC,0x89BD,0x89BE,0x89BF,0x89C0,0x89C3, +0x89CD,0x89D3,0x89D4,0x89D5,0x89D7,0x89D8,0x89D9,0x89DB, +0x89DD,0x89DF,0x89E0,0x89E1,0x89E2,0x89E4,0x89E7,0x89E8, +0x89E9,0x89EA,0x89EC,0x89ED,0x89EE,0x89F0,0x89F1,0x89F2, +0x89F4,0x89F5,0x89F6,0x89F7,0x89F8,0x89F9,0x89FA, 0, +0x89FB,0x89FC,0x89FD,0x89FE,0x89FF,0x8A01,0x8A02,0x8A03, +0x8A04,0x8A05,0x8A06,0x8A08,0x8A09,0x8A0A,0x8A0B,0x8A0C, +0x8A0D,0x8A0E,0x8A0F,0x8A10,0x8A11,0x8A12,0x8A13,0x8A14, +0x8A15,0x8A16,0x8A17,0x8A18,0x8A19,0x8A1A,0x8A1B,0x8A1C, +0x8A1D,0x5370,0x82F1,0x6A31,0x5A74,0x9E70,0x5E94,0x7F28, +0x83B9,0x8424,0x8425,0x8367,0x8747,0x8FCE,0x8D62,0x76C8, +0x5F71,0x9896,0x786C,0x6620,0x54DF,0x62E5,0x4F63,0x81C3, +0x75C8,0x5EB8,0x96CD,0x8E0A,0x86F9,0x548F,0x6CF3,0x6D8C, +0x6C38,0x607F,0x52C7,0x7528,0x5E7D,0x4F18,0x60A0,0x5FE7, +0x5C24,0x7531,0x90AE,0x94C0,0x72B9,0x6CB9,0x6E38,0x9149, +0x6709,0x53CB,0x53F3,0x4F51,0x91C9,0x8BF1,0x53C8,0x5E7C, +0x8FC2,0x6DE4,0x4E8E,0x76C2,0x6986,0x865E,0x611A,0x8206, +0x4F59,0x4FDE,0x903E,0x9C7C,0x6109,0x6E1D,0x6E14,0x9685, +0x4E88,0x5A31,0x96E8,0x4E0E,0x5C7F,0x79B9,0x5B87,0x8BED, +0x7FBD,0x7389,0x57DF,0x828B,0x90C1,0x5401,0x9047,0x55BB, +0x5CEA,0x5FA1,0x6108,0x6B32,0x72F1,0x80B2,0x8A89, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x8A1E,0x8A1F,0x8A20,0x8A21,0x8A22,0x8A23,0x8A24,0x8A25, +0x8A26,0x8A27,0x8A28,0x8A29,0x8A2A,0x8A2B,0x8A2C,0x8A2D, +0x8A2E,0x8A2F,0x8A30,0x8A31,0x8A32,0x8A33,0x8A34,0x8A35, +0x8A36,0x8A37,0x8A38,0x8A39,0x8A3A,0x8A3B,0x8A3C,0x8A3D, +0x8A3F,0x8A40,0x8A41,0x8A42,0x8A43,0x8A44,0x8A45,0x8A46, +0x8A47,0x8A49,0x8A4A,0x8A4B,0x8A4C,0x8A4D,0x8A4E,0x8A4F, +0x8A50,0x8A51,0x8A52,0x8A53,0x8A54,0x8A55,0x8A56,0x8A57, +0x8A58,0x8A59,0x8A5A,0x8A5B,0x8A5C,0x8A5D,0x8A5E, 0, +0x8A5F,0x8A60,0x8A61,0x8A62,0x8A63,0x8A64,0x8A65,0x8A66, +0x8A67,0x8A68,0x8A69,0x8A6A,0x8A6B,0x8A6C,0x8A6D,0x8A6E, +0x8A6F,0x8A70,0x8A71,0x8A72,0x8A73,0x8A74,0x8A75,0x8A76, +0x8A77,0x8A78,0x8A7A,0x8A7B,0x8A7C,0x8A7D,0x8A7E,0x8A7F, +0x8A80,0x6D74,0x5BD3,0x88D5,0x9884,0x8C6B,0x9A6D,0x9E33, +0x6E0A,0x51A4,0x5143,0x57A3,0x8881,0x539F,0x63F4,0x8F95, +0x56ED,0x5458,0x5706,0x733F,0x6E90,0x7F18,0x8FDC,0x82D1, +0x613F,0x6028,0x9662,0x66F0,0x7EA6,0x8D8A,0x8DC3,0x94A5, +0x5CB3,0x7CA4,0x6708,0x60A6,0x9605,0x8018,0x4E91,0x90E7, +0x5300,0x9668,0x5141,0x8FD0,0x8574,0x915D,0x6655,0x97F5, +0x5B55,0x531D,0x7838,0x6742,0x683D,0x54C9,0x707E,0x5BB0, +0x8F7D,0x518D,0x5728,0x54B1,0x6512,0x6682,0x8D5E,0x8D43, +0x810F,0x846C,0x906D,0x7CDF,0x51FF,0x85FB,0x67A3,0x65E9, +0x6FA1,0x86A4,0x8E81,0x566A,0x9020,0x7682,0x7076,0x71E5, +0x8D23,0x62E9,0x5219,0x6CFD,0x8D3C,0x600E,0x589E,0x618E, +0x66FE,0x8D60,0x624E,0x55B3,0x6E23,0x672D,0x8F67, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x8A81,0x8A82,0x8A83,0x8A84,0x8A85,0x8A86,0x8A87,0x8A88, +0x8A8B,0x8A8C,0x8A8D,0x8A8E,0x8A8F,0x8A90,0x8A91,0x8A92, +0x8A94,0x8A95,0x8A96,0x8A97,0x8A98,0x8A99,0x8A9A,0x8A9B, +0x8A9C,0x8A9D,0x8A9E,0x8A9F,0x8AA0,0x8AA1,0x8AA2,0x8AA3, +0x8AA4,0x8AA5,0x8AA6,0x8AA7,0x8AA8,0x8AA9,0x8AAA,0x8AAB, +0x8AAC,0x8AAD,0x8AAE,0x8AAF,0x8AB0,0x8AB1,0x8AB2,0x8AB3, +0x8AB4,0x8AB5,0x8AB6,0x8AB7,0x8AB8,0x8AB9,0x8ABA,0x8ABB, +0x8ABC,0x8ABD,0x8ABE,0x8ABF,0x8AC0,0x8AC1,0x8AC2, 0, +0x8AC3,0x8AC4,0x8AC5,0x8AC6,0x8AC7,0x8AC8,0x8AC9,0x8ACA, +0x8ACB,0x8ACC,0x8ACD,0x8ACE,0x8ACF,0x8AD0,0x8AD1,0x8AD2, +0x8AD3,0x8AD4,0x8AD5,0x8AD6,0x8AD7,0x8AD8,0x8AD9,0x8ADA, +0x8ADB,0x8ADC,0x8ADD,0x8ADE,0x8ADF,0x8AE0,0x8AE1,0x8AE2, +0x8AE3,0x94E1,0x95F8,0x7728,0x6805,0x69A8,0x548B,0x4E4D, +0x70B8,0x8BC8,0x6458,0x658B,0x5B85,0x7A84,0x503A,0x5BE8, +0x77BB,0x6BE1,0x8A79,0x7C98,0x6CBE,0x76CF,0x65A9,0x8F97, +0x5D2D,0x5C55,0x8638,0x6808,0x5360,0x6218,0x7AD9,0x6E5B, +0x7EFD,0x6A1F,0x7AE0,0x5F70,0x6F33,0x5F20,0x638C,0x6DA8, +0x6756,0x4E08,0x5E10,0x8D26,0x4ED7,0x80C0,0x7634,0x969C, +0x62DB,0x662D,0x627E,0x6CBC,0x8D75,0x7167,0x7F69,0x5146, +0x8087,0x53EC,0x906E,0x6298,0x54F2,0x86F0,0x8F99,0x8005, +0x9517,0x8517,0x8FD9,0x6D59,0x73CD,0x659F,0x771F,0x7504, +0x7827,0x81FB,0x8D1E,0x9488,0x4FA6,0x6795,0x75B9,0x8BCA, +0x9707,0x632F,0x9547,0x9635,0x84B8,0x6323,0x7741,0x5F81, +0x72F0,0x4E89,0x6014,0x6574,0x62EF,0x6B63,0x653F, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x8AE4,0x8AE5,0x8AE6,0x8AE7,0x8AE8,0x8AE9,0x8AEA,0x8AEB, +0x8AEC,0x8AED,0x8AEE,0x8AEF,0x8AF0,0x8AF1,0x8AF2,0x8AF3, +0x8AF4,0x8AF5,0x8AF6,0x8AF7,0x8AF8,0x8AF9,0x8AFA,0x8AFB, +0x8AFC,0x8AFD,0x8AFE,0x8AFF,0x8B00,0x8B01,0x8B02,0x8B03, +0x8B04,0x8B05,0x8B06,0x8B08,0x8B09,0x8B0A,0x8B0B,0x8B0C, +0x8B0D,0x8B0E,0x8B0F,0x8B10,0x8B11,0x8B12,0x8B13,0x8B14, +0x8B15,0x8B16,0x8B17,0x8B18,0x8B19,0x8B1A,0x8B1B,0x8B1C, +0x8B1D,0x8B1E,0x8B1F,0x8B20,0x8B21,0x8B22,0x8B23, 0, +0x8B24,0x8B25,0x8B27,0x8B28,0x8B29,0x8B2A,0x8B2B,0x8B2C, +0x8B2D,0x8B2E,0x8B2F,0x8B30,0x8B31,0x8B32,0x8B33,0x8B34, +0x8B35,0x8B36,0x8B37,0x8B38,0x8B39,0x8B3A,0x8B3B,0x8B3C, +0x8B3D,0x8B3E,0x8B3F,0x8B40,0x8B41,0x8B42,0x8B43,0x8B44, +0x8B45,0x5E27,0x75C7,0x90D1,0x8BC1,0x829D,0x679D,0x652F, +0x5431,0x8718,0x77E5,0x80A2,0x8102,0x6C41,0x4E4B,0x7EC7, +0x804C,0x76F4,0x690D,0x6B96,0x6267,0x503C,0x4F84,0x5740, +0x6307,0x6B62,0x8DBE,0x53EA,0x65E8,0x7EB8,0x5FD7,0x631A, +0x63B7,0x81F3,0x81F4,0x7F6E,0x5E1C,0x5CD9,0x5236,0x667A, +0x79E9,0x7A1A,0x8D28,0x7099,0x75D4,0x6EDE,0x6CBB,0x7A92, +0x4E2D,0x76C5,0x5FE0,0x949F,0x8877,0x7EC8,0x79CD,0x80BF, +0x91CD,0x4EF2,0x4F17,0x821F,0x5468,0x5DDE,0x6D32,0x8BCC, +0x7CA5,0x8F74,0x8098,0x5E1A,0x5492,0x76B1,0x5B99,0x663C, +0x9AA4,0x73E0,0x682A,0x86DB,0x6731,0x732A,0x8BF8,0x8BDB, +0x9010,0x7AF9,0x70DB,0x716E,0x62C4,0x77A9,0x5631,0x4E3B, +0x8457,0x67F1,0x52A9,0x86C0,0x8D2E,0x94F8,0x7B51, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x8B46,0x8B47,0x8B48,0x8B49,0x8B4A,0x8B4B,0x8B4C,0x8B4D, +0x8B4E,0x8B4F,0x8B50,0x8B51,0x8B52,0x8B53,0x8B54,0x8B55, +0x8B56,0x8B57,0x8B58,0x8B59,0x8B5A,0x8B5B,0x8B5C,0x8B5D, +0x8B5E,0x8B5F,0x8B60,0x8B61,0x8B62,0x8B63,0x8B64,0x8B65, +0x8B67,0x8B68,0x8B69,0x8B6A,0x8B6B,0x8B6D,0x8B6E,0x8B6F, +0x8B70,0x8B71,0x8B72,0x8B73,0x8B74,0x8B75,0x8B76,0x8B77, +0x8B78,0x8B79,0x8B7A,0x8B7B,0x8B7C,0x8B7D,0x8B7E,0x8B7F, +0x8B80,0x8B81,0x8B82,0x8B83,0x8B84,0x8B85,0x8B86, 0, +0x8B87,0x8B88,0x8B89,0x8B8A,0x8B8B,0x8B8C,0x8B8D,0x8B8E, +0x8B8F,0x8B90,0x8B91,0x8B92,0x8B93,0x8B94,0x8B95,0x8B96, +0x8B97,0x8B98,0x8B99,0x8B9A,0x8B9B,0x8B9C,0x8B9D,0x8B9E, +0x8B9F,0x8BAC,0x8BB1,0x8BBB,0x8BC7,0x8BD0,0x8BEA,0x8C09, +0x8C1E,0x4F4F,0x6CE8,0x795D,0x9A7B,0x6293,0x722A,0x62FD, +0x4E13,0x7816,0x8F6C,0x64B0,0x8D5A,0x7BC6,0x6869,0x5E84, +0x88C5,0x5986,0x649E,0x58EE,0x72B6,0x690E,0x9525,0x8FFD, +0x8D58,0x5760,0x7F00,0x8C06,0x51C6,0x6349,0x62D9,0x5353, +0x684C,0x7422,0x8301,0x914C,0x5544,0x7740,0x707C,0x6D4A, +0x5179,0x54A8,0x8D44,0x59FF,0x6ECB,0x6DC4,0x5B5C,0x7D2B, +0x4ED4,0x7C7D,0x6ED3,0x5B50,0x81EA,0x6E0D,0x5B57,0x9B03, +0x68D5,0x8E2A,0x5B97,0x7EFC,0x603B,0x7EB5,0x90B9,0x8D70, +0x594F,0x63CD,0x79DF,0x8DB3,0x5352,0x65CF,0x7956,0x8BC5, +0x963B,0x7EC4,0x94BB,0x7E82,0x5634,0x9189,0x6700,0x7F6A, +0x5C0A,0x9075,0x6628,0x5DE6,0x4F50,0x67DE,0x505A,0x4F5C, +0x5750,0x5EA7, 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, 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, +0x8C38,0x8C39,0x8C3A,0x8C3B,0x8C3C,0x8C3D,0x8C3E,0x8C3F, +0x8C40,0x8C42,0x8C43,0x8C44,0x8C45,0x8C48,0x8C4A,0x8C4B, +0x8C4D,0x8C4E,0x8C4F,0x8C50,0x8C51,0x8C52,0x8C53,0x8C54, +0x8C56,0x8C57,0x8C58,0x8C59,0x8C5B,0x8C5C,0x8C5D,0x8C5E, +0x8C5F,0x8C60,0x8C63,0x8C64,0x8C65,0x8C66,0x8C67,0x8C68, +0x8C69,0x8C6C,0x8C6D,0x8C6E,0x8C6F,0x8C70,0x8C71,0x8C72, +0x8C74,0x8C75,0x8C76,0x8C77,0x8C7B,0x8C7C,0x8C7D,0x8C7E, +0x8C7F,0x8C80,0x8C81,0x8C83,0x8C84,0x8C86,0x8C87, 0, +0x8C88,0x8C8B,0x8C8D,0x8C8E,0x8C8F,0x8C90,0x8C91,0x8C92, +0x8C93,0x8C95,0x8C96,0x8C97,0x8C99,0x8C9A,0x8C9B,0x8C9C, +0x8C9D,0x8C9E,0x8C9F,0x8CA0,0x8CA1,0x8CA2,0x8CA3,0x8CA4, +0x8CA5,0x8CA6,0x8CA7,0x8CA8,0x8CA9,0x8CAA,0x8CAB,0x8CAC, +0x8CAD,0x4E8D,0x4E0C,0x5140,0x4E10,0x5EFF,0x5345,0x4E15, +0x4E98,0x4E1E,0x9B32,0x5B6C,0x5669,0x4E28,0x79BA,0x4E3F, +0x5315,0x4E47,0x592D,0x723B,0x536E,0x6C10,0x56DF,0x80E4, +0x9997,0x6BD3,0x777E,0x9F17,0x4E36,0x4E9F,0x9F10,0x4E5C, +0x4E69,0x4E93,0x8288,0x5B5B,0x556C,0x560F,0x4EC4,0x538D, +0x539D,0x53A3,0x53A5,0x53AE,0x9765,0x8D5D,0x531A,0x53F5, +0x5326,0x532E,0x533E,0x8D5C,0x5366,0x5363,0x5202,0x5208, +0x520E,0x522D,0x5233,0x523F,0x5240,0x524C,0x525E,0x5261, +0x525C,0x84AF,0x527D,0x5282,0x5281,0x5290,0x5293,0x5182, +0x7F54,0x4EBB,0x4EC3,0x4EC9,0x4EC2,0x4EE8,0x4EE1,0x4EEB, +0x4EDE,0x4F1B,0x4EF3,0x4F22,0x4F64,0x4EF5,0x4F25,0x4F27, +0x4F09,0x4F2B,0x4F5E,0x4F67,0x6538,0x4F5A,0x4F5D, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x8CAE,0x8CAF,0x8CB0,0x8CB1,0x8CB2,0x8CB3,0x8CB4,0x8CB5, +0x8CB6,0x8CB7,0x8CB8,0x8CB9,0x8CBA,0x8CBB,0x8CBC,0x8CBD, +0x8CBE,0x8CBF,0x8CC0,0x8CC1,0x8CC2,0x8CC3,0x8CC4,0x8CC5, +0x8CC6,0x8CC7,0x8CC8,0x8CC9,0x8CCA,0x8CCB,0x8CCC,0x8CCD, +0x8CCE,0x8CCF,0x8CD0,0x8CD1,0x8CD2,0x8CD3,0x8CD4,0x8CD5, +0x8CD6,0x8CD7,0x8CD8,0x8CD9,0x8CDA,0x8CDB,0x8CDC,0x8CDD, +0x8CDE,0x8CDF,0x8CE0,0x8CE1,0x8CE2,0x8CE3,0x8CE4,0x8CE5, +0x8CE6,0x8CE7,0x8CE8,0x8CE9,0x8CEA,0x8CEB,0x8CEC, 0, +0x8CED,0x8CEE,0x8CEF,0x8CF0,0x8CF1,0x8CF2,0x8CF3,0x8CF4, +0x8CF5,0x8CF6,0x8CF7,0x8CF8,0x8CF9,0x8CFA,0x8CFB,0x8CFC, +0x8CFD,0x8CFE,0x8CFF,0x8D00,0x8D01,0x8D02,0x8D03,0x8D04, +0x8D05,0x8D06,0x8D07,0x8D08,0x8D09,0x8D0A,0x8D0B,0x8D0C, +0x8D0D,0x4F5F,0x4F57,0x4F32,0x4F3D,0x4F76,0x4F74,0x4F91, +0x4F89,0x4F83,0x4F8F,0x4F7E,0x4F7B,0x4FAA,0x4F7C,0x4FAC, +0x4F94,0x4FE6,0x4FE8,0x4FEA,0x4FC5,0x4FDA,0x4FE3,0x4FDC, +0x4FD1,0x4FDF,0x4FF8,0x5029,0x504C,0x4FF3,0x502C,0x500F, +0x502E,0x502D,0x4FFE,0x501C,0x500C,0x5025,0x5028,0x507E, +0x5043,0x5055,0x5048,0x504E,0x506C,0x507B,0x50A5,0x50A7, +0x50A9,0x50BA,0x50D6,0x5106,0x50ED,0x50EC,0x50E6,0x50EE, +0x5107,0x510B,0x4EDD,0x6C3D,0x4F58,0x4F65,0x4FCE,0x9FA0, +0x6C46,0x7C74,0x516E,0x5DFD,0x9EC9,0x9998,0x5181,0x5914, +0x52F9,0x530D,0x8A07,0x5310,0x51EB,0x5919,0x5155,0x4EA0, +0x5156,0x4EB3,0x886E,0x88A4,0x4EB5,0x8114,0x88D2,0x7980, +0x5B34,0x8803,0x7FB8,0x51AB,0x51B1,0x51BD,0x51BC, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x8D0E,0x8D0F,0x8D10,0x8D11,0x8D12,0x8D13,0x8D14,0x8D15, +0x8D16,0x8D17,0x8D18,0x8D19,0x8D1A,0x8D1B,0x8D1C,0x8D20, +0x8D51,0x8D52,0x8D57,0x8D5F,0x8D65,0x8D68,0x8D69,0x8D6A, +0x8D6C,0x8D6E,0x8D6F,0x8D71,0x8D72,0x8D78,0x8D79,0x8D7A, +0x8D7B,0x8D7C,0x8D7D,0x8D7E,0x8D7F,0x8D80,0x8D82,0x8D83, +0x8D86,0x8D87,0x8D88,0x8D89,0x8D8C,0x8D8D,0x8D8E,0x8D8F, +0x8D90,0x8D92,0x8D93,0x8D95,0x8D96,0x8D97,0x8D98,0x8D99, +0x8D9A,0x8D9B,0x8D9C,0x8D9D,0x8D9E,0x8DA0,0x8DA1, 0, +0x8DA2,0x8DA4,0x8DA5,0x8DA6,0x8DA7,0x8DA8,0x8DA9,0x8DAA, +0x8DAB,0x8DAC,0x8DAD,0x8DAE,0x8DAF,0x8DB0,0x8DB2,0x8DB6, +0x8DB7,0x8DB9,0x8DBB,0x8DBD,0x8DC0,0x8DC1,0x8DC2,0x8DC5, +0x8DC7,0x8DC8,0x8DC9,0x8DCA,0x8DCD,0x8DD0,0x8DD2,0x8DD3, +0x8DD4,0x51C7,0x5196,0x51A2,0x51A5,0x8BA0,0x8BA6,0x8BA7, +0x8BAA,0x8BB4,0x8BB5,0x8BB7,0x8BC2,0x8BC3,0x8BCB,0x8BCF, +0x8BCE,0x8BD2,0x8BD3,0x8BD4,0x8BD6,0x8BD8,0x8BD9,0x8BDC, +0x8BDF,0x8BE0,0x8BE4,0x8BE8,0x8BE9,0x8BEE,0x8BF0,0x8BF3, +0x8BF6,0x8BF9,0x8BFC,0x8BFF,0x8C00,0x8C02,0x8C04,0x8C07, +0x8C0C,0x8C0F,0x8C11,0x8C12,0x8C14,0x8C15,0x8C16,0x8C19, +0x8C1B,0x8C18,0x8C1D,0x8C1F,0x8C20,0x8C21,0x8C25,0x8C27, +0x8C2A,0x8C2B,0x8C2E,0x8C2F,0x8C32,0x8C33,0x8C35,0x8C36, +0x5369,0x537A,0x961D,0x9622,0x9621,0x9631,0x962A,0x963D, +0x963C,0x9642,0x9649,0x9654,0x965F,0x9667,0x966C,0x9672, +0x9674,0x9688,0x968D,0x9697,0x96B0,0x9097,0x909B,0x909D, +0x9099,0x90AC,0x90A1,0x90B4,0x90B3,0x90B6,0x90BA, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x8DD5,0x8DD8,0x8DD9,0x8DDC,0x8DE0,0x8DE1,0x8DE2,0x8DE5, +0x8DE6,0x8DE7,0x8DE9,0x8DED,0x8DEE,0x8DF0,0x8DF1,0x8DF2, +0x8DF4,0x8DF6,0x8DFC,0x8DFE,0x8DFF,0x8E00,0x8E01,0x8E02, +0x8E03,0x8E04,0x8E06,0x8E07,0x8E08,0x8E0B,0x8E0D,0x8E0E, +0x8E10,0x8E11,0x8E12,0x8E13,0x8E15,0x8E16,0x8E17,0x8E18, +0x8E19,0x8E1A,0x8E1B,0x8E1C,0x8E20,0x8E21,0x8E24,0x8E25, +0x8E26,0x8E27,0x8E28,0x8E2B,0x8E2D,0x8E30,0x8E32,0x8E33, +0x8E34,0x8E36,0x8E37,0x8E38,0x8E3B,0x8E3C,0x8E3E, 0, +0x8E3F,0x8E43,0x8E45,0x8E46,0x8E4C,0x8E4D,0x8E4E,0x8E4F, +0x8E50,0x8E53,0x8E54,0x8E55,0x8E56,0x8E57,0x8E58,0x8E5A, +0x8E5B,0x8E5C,0x8E5D,0x8E5E,0x8E5F,0x8E60,0x8E61,0x8E62, +0x8E63,0x8E64,0x8E65,0x8E67,0x8E68,0x8E6A,0x8E6B,0x8E6E, +0x8E71,0x90B8,0x90B0,0x90CF,0x90C5,0x90BE,0x90D0,0x90C4, +0x90C7,0x90D3,0x90E6,0x90E2,0x90DC,0x90D7,0x90DB,0x90EB, +0x90EF,0x90FE,0x9104,0x9122,0x911E,0x9123,0x9131,0x912F, +0x9139,0x9143,0x9146,0x520D,0x5942,0x52A2,0x52AC,0x52AD, +0x52BE,0x54FF,0x52D0,0x52D6,0x52F0,0x53DF,0x71EE,0x77CD, +0x5EF4,0x51F5,0x51FC,0x9B2F,0x53B6,0x5F01,0x755A,0x5DEF, +0x574C,0x57A9,0x57A1,0x587E,0x58BC,0x58C5,0x58D1,0x5729, +0x572C,0x572A,0x5733,0x5739,0x572E,0x572F,0x575C,0x573B, +0x5742,0x5769,0x5785,0x576B,0x5786,0x577C,0x577B,0x5768, +0x576D,0x5776,0x5773,0x57AD,0x57A4,0x578C,0x57B2,0x57CF, +0x57A7,0x57B4,0x5793,0x57A0,0x57D5,0x57D8,0x57DA,0x57D9, +0x57D2,0x57B8,0x57F4,0x57EF,0x57F8,0x57E4,0x57DD, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x8E73,0x8E75,0x8E77,0x8E78,0x8E79,0x8E7A,0x8E7B,0x8E7D, +0x8E7E,0x8E80,0x8E82,0x8E83,0x8E84,0x8E86,0x8E88,0x8E89, +0x8E8A,0x8E8B,0x8E8C,0x8E8D,0x8E8E,0x8E91,0x8E92,0x8E93, +0x8E95,0x8E96,0x8E97,0x8E98,0x8E99,0x8E9A,0x8E9B,0x8E9D, +0x8E9F,0x8EA0,0x8EA1,0x8EA2,0x8EA3,0x8EA4,0x8EA5,0x8EA6, +0x8EA7,0x8EA8,0x8EA9,0x8EAA,0x8EAD,0x8EAE,0x8EB0,0x8EB1, +0x8EB3,0x8EB4,0x8EB5,0x8EB6,0x8EB7,0x8EB8,0x8EB9,0x8EBB, +0x8EBC,0x8EBD,0x8EBE,0x8EBF,0x8EC0,0x8EC1,0x8EC2, 0, +0x8EC3,0x8EC4,0x8EC5,0x8EC6,0x8EC7,0x8EC8,0x8EC9,0x8ECA, +0x8ECB,0x8ECC,0x8ECD,0x8ECF,0x8ED0,0x8ED1,0x8ED2,0x8ED3, +0x8ED4,0x8ED5,0x8ED6,0x8ED7,0x8ED8,0x8ED9,0x8EDA,0x8EDB, +0x8EDC,0x8EDD,0x8EDE,0x8EDF,0x8EE0,0x8EE1,0x8EE2,0x8EE3, +0x8EE4,0x580B,0x580D,0x57FD,0x57ED,0x5800,0x581E,0x5819, +0x5844,0x5820,0x5865,0x586C,0x5881,0x5889,0x589A,0x5880, +0x99A8,0x9F19,0x61FF,0x8279,0x827D,0x827F,0x828F,0x828A, +0x82A8,0x8284,0x828E,0x8291,0x8297,0x8299,0x82AB,0x82B8, +0x82BE,0x82B0,0x82C8,0x82CA,0x82E3,0x8298,0x82B7,0x82AE, +0x82CB,0x82CC,0x82C1,0x82A9,0x82B4,0x82A1,0x82AA,0x829F, +0x82C4,0x82CE,0x82A4,0x82E1,0x8309,0x82F7,0x82E4,0x830F, +0x8307,0x82DC,0x82F4,0x82D2,0x82D8,0x830C,0x82FB,0x82D3, +0x8311,0x831A,0x8306,0x8314,0x8315,0x82E0,0x82D5,0x831C, +0x8351,0x835B,0x835C,0x8308,0x8392,0x833C,0x8334,0x8331, +0x839B,0x835E,0x832F,0x834F,0x8347,0x8343,0x835F,0x8340, +0x8317,0x8360,0x832D,0x833A,0x8333,0x8366,0x8365, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x8EE5,0x8EE6,0x8EE7,0x8EE8,0x8EE9,0x8EEA,0x8EEB,0x8EEC, +0x8EED,0x8EEE,0x8EEF,0x8EF0,0x8EF1,0x8EF2,0x8EF3,0x8EF4, +0x8EF5,0x8EF6,0x8EF7,0x8EF8,0x8EF9,0x8EFA,0x8EFB,0x8EFC, +0x8EFD,0x8EFE,0x8EFF,0x8F00,0x8F01,0x8F02,0x8F03,0x8F04, +0x8F05,0x8F06,0x8F07,0x8F08,0x8F09,0x8F0A,0x8F0B,0x8F0C, +0x8F0D,0x8F0E,0x8F0F,0x8F10,0x8F11,0x8F12,0x8F13,0x8F14, +0x8F15,0x8F16,0x8F17,0x8F18,0x8F19,0x8F1A,0x8F1B,0x8F1C, +0x8F1D,0x8F1E,0x8F1F,0x8F20,0x8F21,0x8F22,0x8F23, 0, +0x8F24,0x8F25,0x8F26,0x8F27,0x8F28,0x8F29,0x8F2A,0x8F2B, +0x8F2C,0x8F2D,0x8F2E,0x8F2F,0x8F30,0x8F31,0x8F32,0x8F33, +0x8F34,0x8F35,0x8F36,0x8F37,0x8F38,0x8F39,0x8F3A,0x8F3B, +0x8F3C,0x8F3D,0x8F3E,0x8F3F,0x8F40,0x8F41,0x8F42,0x8F43, +0x8F44,0x8368,0x831B,0x8369,0x836C,0x836A,0x836D,0x836E, +0x83B0,0x8378,0x83B3,0x83B4,0x83A0,0x83AA,0x8393,0x839C, +0x8385,0x837C,0x83B6,0x83A9,0x837D,0x83B8,0x837B,0x8398, +0x839E,0x83A8,0x83BA,0x83BC,0x83C1,0x8401,0x83E5,0x83D8, +0x5807,0x8418,0x840B,0x83DD,0x83FD,0x83D6,0x841C,0x8438, +0x8411,0x8406,0x83D4,0x83DF,0x840F,0x8403,0x83F8,0x83F9, +0x83EA,0x83C5,0x83C0,0x8426,0x83F0,0x83E1,0x845C,0x8451, +0x845A,0x8459,0x8473,0x8487,0x8488,0x847A,0x8489,0x8478, +0x843C,0x8446,0x8469,0x8476,0x848C,0x848E,0x8431,0x846D, +0x84C1,0x84CD,0x84D0,0x84E6,0x84BD,0x84D3,0x84CA,0x84BF, +0x84BA,0x84E0,0x84A1,0x84B9,0x84B4,0x8497,0x84E5,0x84E3, +0x850C,0x750D,0x8538,0x84F0,0x8539,0x851F,0x853A, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x8F45,0x8F46,0x8F47,0x8F48,0x8F49,0x8F4A,0x8F4B,0x8F4C, +0x8F4D,0x8F4E,0x8F4F,0x8F50,0x8F51,0x8F52,0x8F53,0x8F54, +0x8F55,0x8F56,0x8F57,0x8F58,0x8F59,0x8F5A,0x8F5B,0x8F5C, +0x8F5D,0x8F5E,0x8F5F,0x8F60,0x8F61,0x8F62,0x8F63,0x8F64, +0x8F65,0x8F6A,0x8F80,0x8F8C,0x8F92,0x8F9D,0x8FA0,0x8FA1, +0x8FA2,0x8FA4,0x8FA5,0x8FA6,0x8FA7,0x8FAA,0x8FAC,0x8FAD, +0x8FAE,0x8FAF,0x8FB2,0x8FB3,0x8FB4,0x8FB5,0x8FB7,0x8FB8, +0x8FBA,0x8FBB,0x8FBC,0x8FBF,0x8FC0,0x8FC3,0x8FC6, 0, +0x8FC9,0x8FCA,0x8FCB,0x8FCC,0x8FCD,0x8FCF,0x8FD2,0x8FD6, +0x8FD7,0x8FDA,0x8FE0,0x8FE1,0x8FE3,0x8FE7,0x8FEC,0x8FEF, +0x8FF1,0x8FF2,0x8FF4,0x8FF5,0x8FF6,0x8FFA,0x8FFB,0x8FFC, +0x8FFE,0x8FFF,0x9007,0x9008,0x900C,0x900E,0x9013,0x9015, +0x9018,0x8556,0x853B,0x84FF,0x84FC,0x8559,0x8548,0x8568, +0x8564,0x855E,0x857A,0x77A2,0x8543,0x8572,0x857B,0x85A4, +0x85A8,0x8587,0x858F,0x8579,0x85AE,0x859C,0x8585,0x85B9, +0x85B7,0x85B0,0x85D3,0x85C1,0x85DC,0x85FF,0x8627,0x8605, +0x8629,0x8616,0x863C,0x5EFE,0x5F08,0x593C,0x5941,0x8037, +0x5955,0x595A,0x5958,0x530F,0x5C22,0x5C25,0x5C2C,0x5C34, +0x624C,0x626A,0x629F,0x62BB,0x62CA,0x62DA,0x62D7,0x62EE, +0x6322,0x62F6,0x6339,0x634B,0x6343,0x63AD,0x63F6,0x6371, +0x637A,0x638E,0x63B4,0x636D,0x63AC,0x638A,0x6369,0x63AE, +0x63BC,0x63F2,0x63F8,0x63E0,0x63FF,0x63C4,0x63DE,0x63CE, +0x6452,0x63C6,0x63BE,0x6445,0x6441,0x640B,0x641B,0x6420, +0x640C,0x6426,0x6421,0x645E,0x6484,0x646D,0x6496, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x9019,0x901C,0x9023,0x9024,0x9025,0x9027,0x9028,0x9029, +0x902A,0x902B,0x902C,0x9030,0x9031,0x9032,0x9033,0x9034, +0x9037,0x9039,0x903A,0x903D,0x903F,0x9040,0x9043,0x9045, +0x9046,0x9048,0x9049,0x904A,0x904B,0x904C,0x904E,0x9054, +0x9055,0x9056,0x9059,0x905A,0x905C,0x905D,0x905E,0x905F, +0x9060,0x9061,0x9064,0x9066,0x9067,0x9069,0x906A,0x906B, +0x906C,0x906F,0x9070,0x9071,0x9072,0x9073,0x9076,0x9077, +0x9078,0x9079,0x907A,0x907B,0x907C,0x907E,0x9081, 0, +0x9084,0x9085,0x9086,0x9087,0x9089,0x908A,0x908C,0x908D, +0x908E,0x908F,0x9090,0x9092,0x9094,0x9096,0x9098,0x909A, +0x909C,0x909E,0x909F,0x90A0,0x90A4,0x90A5,0x90A7,0x90A8, +0x90A9,0x90AB,0x90AD,0x90B2,0x90B7,0x90BC,0x90BD,0x90BF, +0x90C0,0x647A,0x64B7,0x64B8,0x6499,0x64BA,0x64C0,0x64D0, +0x64D7,0x64E4,0x64E2,0x6509,0x6525,0x652E,0x5F0B,0x5FD2, +0x7519,0x5F11,0x535F,0x53F1,0x53FD,0x53E9,0x53E8,0x53FB, +0x5412,0x5416,0x5406,0x544B,0x5452,0x5453,0x5454,0x5456, +0x5443,0x5421,0x5457,0x5459,0x5423,0x5432,0x5482,0x5494, +0x5477,0x5471,0x5464,0x549A,0x549B,0x5484,0x5476,0x5466, +0x549D,0x54D0,0x54AD,0x54C2,0x54B4,0x54D2,0x54A7,0x54A6, +0x54D3,0x54D4,0x5472,0x54A3,0x54D5,0x54BB,0x54BF,0x54CC, +0x54D9,0x54DA,0x54DC,0x54A9,0x54AA,0x54A4,0x54DD,0x54CF, +0x54DE,0x551B,0x54E7,0x5520,0x54FD,0x5514,0x54F3,0x5522, +0x5523,0x550F,0x5511,0x5527,0x552A,0x5567,0x558F,0x55B5, +0x5549,0x556D,0x5541,0x5555,0x553F,0x5550,0x553C, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x90C2,0x90C3,0x90C6,0x90C8,0x90C9,0x90CB,0x90CC,0x90CD, +0x90D2,0x90D4,0x90D5,0x90D6,0x90D8,0x90D9,0x90DA,0x90DE, +0x90DF,0x90E0,0x90E3,0x90E4,0x90E5,0x90E9,0x90EA,0x90EC, +0x90EE,0x90F0,0x90F1,0x90F2,0x90F3,0x90F5,0x90F6,0x90F7, +0x90F9,0x90FA,0x90FB,0x90FC,0x90FF,0x9100,0x9101,0x9103, +0x9105,0x9106,0x9107,0x9108,0x9109,0x910A,0x910B,0x910C, +0x910D,0x910E,0x910F,0x9110,0x9111,0x9112,0x9113,0x9114, +0x9115,0x9116,0x9117,0x9118,0x911A,0x911B,0x911C, 0, +0x911D,0x911F,0x9120,0x9121,0x9124,0x9125,0x9126,0x9127, +0x9128,0x9129,0x912A,0x912B,0x912C,0x912D,0x912E,0x9130, +0x9132,0x9133,0x9134,0x9135,0x9136,0x9137,0x9138,0x913A, +0x913B,0x913C,0x913D,0x913E,0x913F,0x9140,0x9141,0x9142, +0x9144,0x5537,0x5556,0x5575,0x5576,0x5577,0x5533,0x5530, +0x555C,0x558B,0x55D2,0x5583,0x55B1,0x55B9,0x5588,0x5581, +0x559F,0x557E,0x55D6,0x5591,0x557B,0x55DF,0x55BD,0x55BE, +0x5594,0x5599,0x55EA,0x55F7,0x55C9,0x561F,0x55D1,0x55EB, +0x55EC,0x55D4,0x55E6,0x55DD,0x55C4,0x55EF,0x55E5,0x55F2, +0x55F3,0x55CC,0x55CD,0x55E8,0x55F5,0x55E4,0x8F94,0x561E, +0x5608,0x560C,0x5601,0x5624,0x5623,0x55FE,0x5600,0x5627, +0x562D,0x5658,0x5639,0x5657,0x562C,0x564D,0x5662,0x5659, +0x565C,0x564C,0x5654,0x5686,0x5664,0x5671,0x566B,0x567B, +0x567C,0x5685,0x5693,0x56AF,0x56D4,0x56D7,0x56DD,0x56E1, +0x56F5,0x56EB,0x56F9,0x56FF,0x5704,0x570A,0x5709,0x571C, +0x5E0F,0x5E19,0x5E14,0x5E11,0x5E31,0x5E3B,0x5E3C, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x9145,0x9147,0x9148,0x9151,0x9153,0x9154,0x9155,0x9156, +0x9158,0x9159,0x915B,0x915C,0x915F,0x9160,0x9166,0x9167, +0x9168,0x916B,0x916D,0x9173,0x917A,0x917B,0x917C,0x9180, +0x9181,0x9182,0x9183,0x9184,0x9186,0x9188,0x918A,0x918E, +0x918F,0x9193,0x9194,0x9195,0x9196,0x9197,0x9198,0x9199, +0x919C,0x919D,0x919E,0x919F,0x91A0,0x91A1,0x91A4,0x91A5, +0x91A6,0x91A7,0x91A8,0x91A9,0x91AB,0x91AC,0x91B0,0x91B1, +0x91B2,0x91B3,0x91B6,0x91B7,0x91B8,0x91B9,0x91BB, 0, +0x91BC,0x91BD,0x91BE,0x91BF,0x91C0,0x91C1,0x91C2,0x91C3, +0x91C4,0x91C5,0x91C6,0x91C8,0x91CB,0x91D0,0x91D2,0x91D3, +0x91D4,0x91D5,0x91D6,0x91D7,0x91D8,0x91D9,0x91DA,0x91DB, +0x91DD,0x91DE,0x91DF,0x91E0,0x91E1,0x91E2,0x91E3,0x91E4, +0x91E5,0x5E37,0x5E44,0x5E54,0x5E5B,0x5E5E,0x5E61,0x5C8C, +0x5C7A,0x5C8D,0x5C90,0x5C96,0x5C88,0x5C98,0x5C99,0x5C91, +0x5C9A,0x5C9C,0x5CB5,0x5CA2,0x5CBD,0x5CAC,0x5CAB,0x5CB1, +0x5CA3,0x5CC1,0x5CB7,0x5CC4,0x5CD2,0x5CE4,0x5CCB,0x5CE5, +0x5D02,0x5D03,0x5D27,0x5D26,0x5D2E,0x5D24,0x5D1E,0x5D06, +0x5D1B,0x5D58,0x5D3E,0x5D34,0x5D3D,0x5D6C,0x5D5B,0x5D6F, +0x5D5D,0x5D6B,0x5D4B,0x5D4A,0x5D69,0x5D74,0x5D82,0x5D99, +0x5D9D,0x8C73,0x5DB7,0x5DC5,0x5F73,0x5F77,0x5F82,0x5F87, +0x5F89,0x5F8C,0x5F95,0x5F99,0x5F9C,0x5FA8,0x5FAD,0x5FB5, +0x5FBC,0x8862,0x5F61,0x72AD,0x72B0,0x72B4,0x72B7,0x72B8, +0x72C3,0x72C1,0x72CE,0x72CD,0x72D2,0x72E8,0x72EF,0x72E9, +0x72F2,0x72F4,0x72F7,0x7301,0x72F3,0x7303,0x72FA, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x91E6,0x91E7,0x91E8,0x91E9,0x91EA,0x91EB,0x91EC,0x91ED, +0x91EE,0x91EF,0x91F0,0x91F1,0x91F2,0x91F3,0x91F4,0x91F5, +0x91F6,0x91F7,0x91F8,0x91F9,0x91FA,0x91FB,0x91FC,0x91FD, +0x91FE,0x91FF,0x9200,0x9201,0x9202,0x9203,0x9204,0x9205, +0x9206,0x9207,0x9208,0x9209,0x920A,0x920B,0x920C,0x920D, +0x920E,0x920F,0x9210,0x9211,0x9212,0x9213,0x9214,0x9215, +0x9216,0x9217,0x9218,0x9219,0x921A,0x921B,0x921C,0x921D, +0x921E,0x921F,0x9220,0x9221,0x9222,0x9223,0x9224, 0, +0x9225,0x9226,0x9227,0x9228,0x9229,0x922A,0x922B,0x922C, +0x922D,0x922E,0x922F,0x9230,0x9231,0x9232,0x9233,0x9234, +0x9235,0x9236,0x9237,0x9238,0x9239,0x923A,0x923B,0x923C, +0x923D,0x923E,0x923F,0x9240,0x9241,0x9242,0x9243,0x9244, +0x9245,0x72FB,0x7317,0x7313,0x7321,0x730A,0x731E,0x731D, +0x7315,0x7322,0x7339,0x7325,0x732C,0x7338,0x7331,0x7350, +0x734D,0x7357,0x7360,0x736C,0x736F,0x737E,0x821B,0x5925, +0x98E7,0x5924,0x5902,0x9963,0x9967,0x9968,0x9969,0x996A, +0x996B,0x996C,0x9974,0x9977,0x997D,0x9980,0x9984,0x9987, +0x998A,0x998D,0x9990,0x9991,0x9993,0x9994,0x9995,0x5E80, +0x5E91,0x5E8B,0x5E96,0x5EA5,0x5EA0,0x5EB9,0x5EB5,0x5EBE, +0x5EB3,0x8D53,0x5ED2,0x5ED1,0x5EDB,0x5EE8,0x5EEA,0x81BA, +0x5FC4,0x5FC9,0x5FD6,0x5FCF,0x6003,0x5FEE,0x6004,0x5FE1, +0x5FE4,0x5FFE,0x6005,0x6006,0x5FEA,0x5FED,0x5FF8,0x6019, +0x6035,0x6026,0x601B,0x600F,0x600D,0x6029,0x602B,0x600A, +0x603F,0x6021,0x6078,0x6079,0x607B,0x607A,0x6042, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x9246,0x9247,0x9248,0x9249,0x924A,0x924B,0x924C,0x924D, +0x924E,0x924F,0x9250,0x9251,0x9252,0x9253,0x9254,0x9255, +0x9256,0x9257,0x9258,0x9259,0x925A,0x925B,0x925C,0x925D, +0x925E,0x925F,0x9260,0x9261,0x9262,0x9263,0x9264,0x9265, +0x9266,0x9267,0x9268,0x9269,0x926A,0x926B,0x926C,0x926D, +0x926E,0x926F,0x9270,0x9271,0x9272,0x9273,0x9275,0x9276, +0x9277,0x9278,0x9279,0x927A,0x927B,0x927C,0x927D,0x927E, +0x927F,0x9280,0x9281,0x9282,0x9283,0x9284,0x9285, 0, +0x9286,0x9287,0x9288,0x9289,0x928A,0x928B,0x928C,0x928D, +0x928F,0x9290,0x9291,0x9292,0x9293,0x9294,0x9295,0x9296, +0x9297,0x9298,0x9299,0x929A,0x929B,0x929C,0x929D,0x929E, +0x929F,0x92A0,0x92A1,0x92A2,0x92A3,0x92A4,0x92A5,0x92A6, +0x92A7,0x606A,0x607D,0x6096,0x609A,0x60AD,0x609D,0x6083, +0x6092,0x608C,0x609B,0x60EC,0x60BB,0x60B1,0x60DD,0x60D8, +0x60C6,0x60DA,0x60B4,0x6120,0x6126,0x6115,0x6123,0x60F4, +0x6100,0x610E,0x612B,0x614A,0x6175,0x61AC,0x6194,0x61A7, +0x61B7,0x61D4,0x61F5,0x5FDD,0x96B3,0x95E9,0x95EB,0x95F1, +0x95F3,0x95F5,0x95F6,0x95FC,0x95FE,0x9603,0x9604,0x9606, +0x9608,0x960A,0x960B,0x960C,0x960D,0x960F,0x9612,0x9615, +0x9616,0x9617,0x9619,0x961A,0x4E2C,0x723F,0x6215,0x6C35, +0x6C54,0x6C5C,0x6C4A,0x6CA3,0x6C85,0x6C90,0x6C94,0x6C8C, +0x6C68,0x6C69,0x6C74,0x6C76,0x6C86,0x6CA9,0x6CD0,0x6CD4, +0x6CAD,0x6CF7,0x6CF8,0x6CF1,0x6CD7,0x6CB2,0x6CE0,0x6CD6, +0x6CFA,0x6CEB,0x6CEE,0x6CB1,0x6CD3,0x6CEF,0x6CFE, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x92A8,0x92A9,0x92AA,0x92AB,0x92AC,0x92AD,0x92AF,0x92B0, +0x92B1,0x92B2,0x92B3,0x92B4,0x92B5,0x92B6,0x92B7,0x92B8, +0x92B9,0x92BA,0x92BB,0x92BC,0x92BD,0x92BE,0x92BF,0x92C0, +0x92C1,0x92C2,0x92C3,0x92C4,0x92C5,0x92C6,0x92C7,0x92C9, +0x92CA,0x92CB,0x92CC,0x92CD,0x92CE,0x92CF,0x92D0,0x92D1, +0x92D2,0x92D3,0x92D4,0x92D5,0x92D6,0x92D7,0x92D8,0x92D9, +0x92DA,0x92DB,0x92DC,0x92DD,0x92DE,0x92DF,0x92E0,0x92E1, +0x92E2,0x92E3,0x92E4,0x92E5,0x92E6,0x92E7,0x92E8, 0, +0x92E9,0x92EA,0x92EB,0x92EC,0x92ED,0x92EE,0x92EF,0x92F0, +0x92F1,0x92F2,0x92F3,0x92F4,0x92F5,0x92F6,0x92F7,0x92F8, +0x92F9,0x92FA,0x92FB,0x92FC,0x92FD,0x92FE,0x92FF,0x9300, +0x9301,0x9302,0x9303,0x9304,0x9305,0x9306,0x9307,0x9308, +0x9309,0x6D39,0x6D27,0x6D0C,0x6D43,0x6D48,0x6D07,0x6D04, +0x6D19,0x6D0E,0x6D2B,0x6D4D,0x6D2E,0x6D35,0x6D1A,0x6D4F, +0x6D52,0x6D54,0x6D33,0x6D91,0x6D6F,0x6D9E,0x6DA0,0x6D5E, +0x6D93,0x6D94,0x6D5C,0x6D60,0x6D7C,0x6D63,0x6E1A,0x6DC7, +0x6DC5,0x6DDE,0x6E0E,0x6DBF,0x6DE0,0x6E11,0x6DE6,0x6DDD, +0x6DD9,0x6E16,0x6DAB,0x6E0C,0x6DAE,0x6E2B,0x6E6E,0x6E4E, +0x6E6B,0x6EB2,0x6E5F,0x6E86,0x6E53,0x6E54,0x6E32,0x6E25, +0x6E44,0x6EDF,0x6EB1,0x6E98,0x6EE0,0x6F2D,0x6EE2,0x6EA5, +0x6EA7,0x6EBD,0x6EBB,0x6EB7,0x6ED7,0x6EB4,0x6ECF,0x6E8F, +0x6EC2,0x6E9F,0x6F62,0x6F46,0x6F47,0x6F24,0x6F15,0x6EF9, +0x6F2F,0x6F36,0x6F4B,0x6F74,0x6F2A,0x6F09,0x6F29,0x6F89, +0x6F8D,0x6F8C,0x6F78,0x6F72,0x6F7C,0x6F7A,0x6FD1, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x930A,0x930B,0x930C,0x930D,0x930E,0x930F,0x9310,0x9311, +0x9312,0x9313,0x9314,0x9315,0x9316,0x9317,0x9318,0x9319, +0x931A,0x931B,0x931C,0x931D,0x931E,0x931F,0x9320,0x9321, +0x9322,0x9323,0x9324,0x9325,0x9326,0x9327,0x9328,0x9329, +0x932A,0x932B,0x932C,0x932D,0x932E,0x932F,0x9330,0x9331, +0x9332,0x9333,0x9334,0x9335,0x9336,0x9337,0x9338,0x9339, +0x933A,0x933B,0x933C,0x933D,0x933F,0x9340,0x9341,0x9342, +0x9343,0x9344,0x9345,0x9346,0x9347,0x9348,0x9349, 0, +0x934A,0x934B,0x934C,0x934D,0x934E,0x934F,0x9350,0x9351, +0x9352,0x9353,0x9354,0x9355,0x9356,0x9357,0x9358,0x9359, +0x935A,0x935B,0x935C,0x935D,0x935E,0x935F,0x9360,0x9361, +0x9362,0x9363,0x9364,0x9365,0x9366,0x9367,0x9368,0x9369, +0x936B,0x6FC9,0x6FA7,0x6FB9,0x6FB6,0x6FC2,0x6FE1,0x6FEE, +0x6FDE,0x6FE0,0x6FEF,0x701A,0x7023,0x701B,0x7039,0x7035, +0x704F,0x705E,0x5B80,0x5B84,0x5B95,0x5B93,0x5BA5,0x5BB8, +0x752F,0x9A9E,0x6434,0x5BE4,0x5BEE,0x8930,0x5BF0,0x8E47, +0x8B07,0x8FB6,0x8FD3,0x8FD5,0x8FE5,0x8FEE,0x8FE4,0x8FE9, +0x8FE6,0x8FF3,0x8FE8,0x9005,0x9004,0x900B,0x9026,0x9011, +0x900D,0x9016,0x9021,0x9035,0x9036,0x902D,0x902F,0x9044, +0x9051,0x9052,0x9050,0x9068,0x9058,0x9062,0x905B,0x66B9, +0x9074,0x907D,0x9082,0x9088,0x9083,0x908B,0x5F50,0x5F57, +0x5F56,0x5F58,0x5C3B,0x54AB,0x5C50,0x5C59,0x5B71,0x5C63, +0x5C66,0x7FBC,0x5F2A,0x5F29,0x5F2D,0x8274,0x5F3C,0x9B3B, +0x5C6E,0x5981,0x5983,0x598D,0x59A9,0x59AA,0x59A3, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x936C,0x936D,0x936E,0x936F,0x9370,0x9371,0x9372,0x9373, +0x9374,0x9375,0x9376,0x9377,0x9378,0x9379,0x937A,0x937B, +0x937C,0x937D,0x937E,0x937F,0x9380,0x9381,0x9382,0x9383, +0x9384,0x9385,0x9386,0x9387,0x9388,0x9389,0x938A,0x938B, +0x938C,0x938D,0x938E,0x9390,0x9391,0x9392,0x9393,0x9394, +0x9395,0x9396,0x9397,0x9398,0x9399,0x939A,0x939B,0x939C, +0x939D,0x939E,0x939F,0x93A0,0x93A1,0x93A2,0x93A3,0x93A4, +0x93A5,0x93A6,0x93A7,0x93A8,0x93A9,0x93AA,0x93AB, 0, +0x93AC,0x93AD,0x93AE,0x93AF,0x93B0,0x93B1,0x93B2,0x93B3, +0x93B4,0x93B5,0x93B6,0x93B7,0x93B8,0x93B9,0x93BA,0x93BB, +0x93BC,0x93BD,0x93BE,0x93BF,0x93C0,0x93C1,0x93C2,0x93C3, +0x93C4,0x93C5,0x93C6,0x93C7,0x93C8,0x93C9,0x93CB,0x93CC, +0x93CD,0x5997,0x59CA,0x59AB,0x599E,0x59A4,0x59D2,0x59B2, +0x59AF,0x59D7,0x59BE,0x5A05,0x5A06,0x59DD,0x5A08,0x59E3, +0x59D8,0x59F9,0x5A0C,0x5A09,0x5A32,0x5A34,0x5A11,0x5A23, +0x5A13,0x5A40,0x5A67,0x5A4A,0x5A55,0x5A3C,0x5A62,0x5A75, +0x80EC,0x5AAA,0x5A9B,0x5A77,0x5A7A,0x5ABE,0x5AEB,0x5AB2, +0x5AD2,0x5AD4,0x5AB8,0x5AE0,0x5AE3,0x5AF1,0x5AD6,0x5AE6, +0x5AD8,0x5ADC,0x5B09,0x5B17,0x5B16,0x5B32,0x5B37,0x5B40, +0x5C15,0x5C1C,0x5B5A,0x5B65,0x5B73,0x5B51,0x5B53,0x5B62, +0x9A75,0x9A77,0x9A78,0x9A7A,0x9A7F,0x9A7D,0x9A80,0x9A81, +0x9A85,0x9A88,0x9A8A,0x9A90,0x9A92,0x9A93,0x9A96,0x9A98, +0x9A9B,0x9A9C,0x9A9D,0x9A9F,0x9AA0,0x9AA2,0x9AA3,0x9AA5, +0x9AA7,0x7E9F,0x7EA1,0x7EA3,0x7EA5,0x7EA8,0x7EA9, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x93CE,0x93CF,0x93D0,0x93D1,0x93D2,0x93D3,0x93D4,0x93D5, +0x93D7,0x93D8,0x93D9,0x93DA,0x93DB,0x93DC,0x93DD,0x93DE, +0x93DF,0x93E0,0x93E1,0x93E2,0x93E3,0x93E4,0x93E5,0x93E6, +0x93E7,0x93E8,0x93E9,0x93EA,0x93EB,0x93EC,0x93ED,0x93EE, +0x93EF,0x93F0,0x93F1,0x93F2,0x93F3,0x93F4,0x93F5,0x93F6, +0x93F7,0x93F8,0x93F9,0x93FA,0x93FB,0x93FC,0x93FD,0x93FE, +0x93FF,0x9400,0x9401,0x9402,0x9403,0x9404,0x9405,0x9406, +0x9407,0x9408,0x9409,0x940A,0x940B,0x940C,0x940D, 0, +0x940E,0x940F,0x9410,0x9411,0x9412,0x9413,0x9414,0x9415, +0x9416,0x9417,0x9418,0x9419,0x941A,0x941B,0x941C,0x941D, +0x941E,0x941F,0x9420,0x9421,0x9422,0x9423,0x9424,0x9425, +0x9426,0x9427,0x9428,0x9429,0x942A,0x942B,0x942C,0x942D, +0x942E,0x7EAD,0x7EB0,0x7EBE,0x7EC0,0x7EC1,0x7EC2,0x7EC9, +0x7ECB,0x7ECC,0x7ED0,0x7ED4,0x7ED7,0x7EDB,0x7EE0,0x7EE1, +0x7EE8,0x7EEB,0x7EEE,0x7EEF,0x7EF1,0x7EF2,0x7F0D,0x7EF6, +0x7EFA,0x7EFB,0x7EFE,0x7F01,0x7F02,0x7F03,0x7F07,0x7F08, +0x7F0B,0x7F0C,0x7F0F,0x7F11,0x7F12,0x7F17,0x7F19,0x7F1C, +0x7F1B,0x7F1F,0x7F21,0x7F22,0x7F23,0x7F24,0x7F25,0x7F26, +0x7F27,0x7F2A,0x7F2B,0x7F2C,0x7F2D,0x7F2F,0x7F30,0x7F31, +0x7F32,0x7F33,0x7F35,0x5E7A,0x757F,0x5DDB,0x753E,0x9095, +0x738E,0x7391,0x73AE,0x73A2,0x739F,0x73CF,0x73C2,0x73D1, +0x73B7,0x73B3,0x73C0,0x73C9,0x73C8,0x73E5,0x73D9,0x987C, +0x740A,0x73E9,0x73E7,0x73DE,0x73BA,0x73F2,0x740F,0x742A, +0x745B,0x7426,0x7425,0x7428,0x7430,0x742E,0x742C, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x942F,0x9430,0x9431,0x9432,0x9433,0x9434,0x9435,0x9436, +0x9437,0x9438,0x9439,0x943A,0x943B,0x943C,0x943D,0x943F, +0x9440,0x9441,0x9442,0x9443,0x9444,0x9445,0x9446,0x9447, +0x9448,0x9449,0x944A,0x944B,0x944C,0x944D,0x944E,0x944F, +0x9450,0x9451,0x9452,0x9453,0x9454,0x9455,0x9456,0x9457, +0x9458,0x9459,0x945A,0x945B,0x945C,0x945D,0x945E,0x945F, +0x9460,0x9461,0x9462,0x9463,0x9464,0x9465,0x9466,0x9467, +0x9468,0x9469,0x946A,0x946C,0x946D,0x946E,0x946F, 0, +0x9470,0x9471,0x9472,0x9473,0x9474,0x9475,0x9476,0x9477, +0x9478,0x9479,0x947A,0x947B,0x947C,0x947D,0x947E,0x947F, +0x9480,0x9481,0x9482,0x9483,0x9484,0x9491,0x9496,0x9498, +0x94C7,0x94CF,0x94D3,0x94D4,0x94DA,0x94E6,0x94FB,0x951C, +0x9520,0x741B,0x741A,0x7441,0x745C,0x7457,0x7455,0x7459, +0x7477,0x746D,0x747E,0x749C,0x748E,0x7480,0x7481,0x7487, +0x748B,0x749E,0x74A8,0x74A9,0x7490,0x74A7,0x74D2,0x74BA, +0x97EA,0x97EB,0x97EC,0x674C,0x6753,0x675E,0x6748,0x6769, +0x67A5,0x6787,0x676A,0x6773,0x6798,0x67A7,0x6775,0x67A8, +0x679E,0x67AD,0x678B,0x6777,0x677C,0x67F0,0x6809,0x67D8, +0x680A,0x67E9,0x67B0,0x680C,0x67D9,0x67B5,0x67DA,0x67B3, +0x67DD,0x6800,0x67C3,0x67B8,0x67E2,0x680E,0x67C1,0x67FD, +0x6832,0x6833,0x6860,0x6861,0x684E,0x6862,0x6844,0x6864, +0x6883,0x681D,0x6855,0x6866,0x6841,0x6867,0x6840,0x683E, +0x684A,0x6849,0x6829,0x68B5,0x688F,0x6874,0x6877,0x6893, +0x686B,0x68C2,0x696E,0x68FC,0x691F,0x6920,0x68F9, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x9527,0x9533,0x953D,0x9543,0x9548,0x954B,0x9555,0x955A, +0x9560,0x956E,0x9574,0x9575,0x9577,0x9578,0x9579,0x957A, +0x957B,0x957C,0x957D,0x957E,0x9580,0x9581,0x9582,0x9583, +0x9584,0x9585,0x9586,0x9587,0x9588,0x9589,0x958A,0x958B, +0x958C,0x958D,0x958E,0x958F,0x9590,0x9591,0x9592,0x9593, +0x9594,0x9595,0x9596,0x9597,0x9598,0x9599,0x959A,0x959B, +0x959C,0x959D,0x959E,0x959F,0x95A0,0x95A1,0x95A2,0x95A3, +0x95A4,0x95A5,0x95A6,0x95A7,0x95A8,0x95A9,0x95AA, 0, +0x95AB,0x95AC,0x95AD,0x95AE,0x95AF,0x95B0,0x95B1,0x95B2, +0x95B3,0x95B4,0x95B5,0x95B6,0x95B7,0x95B8,0x95B9,0x95BA, +0x95BB,0x95BC,0x95BD,0x95BE,0x95BF,0x95C0,0x95C1,0x95C2, +0x95C3,0x95C4,0x95C5,0x95C6,0x95C7,0x95C8,0x95C9,0x95CA, +0x95CB,0x6924,0x68F0,0x690B,0x6901,0x6957,0x68E3,0x6910, +0x6971,0x6939,0x6960,0x6942,0x695D,0x6984,0x696B,0x6980, +0x6998,0x6978,0x6934,0x69CC,0x6987,0x6988,0x69CE,0x6989, +0x6966,0x6963,0x6979,0x699B,0x69A7,0x69BB,0x69AB,0x69AD, +0x69D4,0x69B1,0x69C1,0x69CA,0x69DF,0x6995,0x69E0,0x698D, +0x69FF,0x6A2F,0x69ED,0x6A17,0x6A18,0x6A65,0x69F2,0x6A44, +0x6A3E,0x6AA0,0x6A50,0x6A5B,0x6A35,0x6A8E,0x6A79,0x6A3D, +0x6A28,0x6A58,0x6A7C,0x6A91,0x6A90,0x6AA9,0x6A97,0x6AAB, +0x7337,0x7352,0x6B81,0x6B82,0x6B87,0x6B84,0x6B92,0x6B93, +0x6B8D,0x6B9A,0x6B9B,0x6BA1,0x6BAA,0x8F6B,0x8F6D,0x8F71, +0x8F72,0x8F73,0x8F75,0x8F76,0x8F78,0x8F77,0x8F79,0x8F7A, +0x8F7C,0x8F7E,0x8F81,0x8F82,0x8F84,0x8F87,0x8F8B, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x95CC,0x95CD,0x95CE,0x95CF,0x95D0,0x95D1,0x95D2,0x95D3, +0x95D4,0x95D5,0x95D6,0x95D7,0x95D8,0x95D9,0x95DA,0x95DB, +0x95DC,0x95DD,0x95DE,0x95DF,0x95E0,0x95E1,0x95E2,0x95E3, +0x95E4,0x95E5,0x95E6,0x95E7,0x95EC,0x95FF,0x9607,0x9613, +0x9618,0x961B,0x961E,0x9620,0x9623,0x9624,0x9625,0x9626, +0x9627,0x9628,0x9629,0x962B,0x962C,0x962D,0x962F,0x9630, +0x9637,0x9638,0x9639,0x963A,0x963E,0x9641,0x9643,0x964A, +0x964E,0x964F,0x9651,0x9652,0x9653,0x9656,0x9657, 0, +0x9658,0x9659,0x965A,0x965C,0x965D,0x965E,0x9660,0x9663, +0x9665,0x9666,0x966B,0x966D,0x966E,0x966F,0x9670,0x9671, +0x9673,0x9678,0x9679,0x967A,0x967B,0x967C,0x967D,0x967E, +0x967F,0x9680,0x9681,0x9682,0x9683,0x9684,0x9687,0x9689, +0x968A,0x8F8D,0x8F8E,0x8F8F,0x8F98,0x8F9A,0x8ECE,0x620B, +0x6217,0x621B,0x621F,0x6222,0x6221,0x6225,0x6224,0x622C, +0x81E7,0x74EF,0x74F4,0x74FF,0x750F,0x7511,0x7513,0x6534, +0x65EE,0x65EF,0x65F0,0x660A,0x6619,0x6772,0x6603,0x6615, +0x6600,0x7085,0x66F7,0x661D,0x6634,0x6631,0x6636,0x6635, +0x8006,0x665F,0x6654,0x6641,0x664F,0x6656,0x6661,0x6657, +0x6677,0x6684,0x668C,0x66A7,0x669D,0x66BE,0x66DB,0x66DC, +0x66E6,0x66E9,0x8D32,0x8D33,0x8D36,0x8D3B,0x8D3D,0x8D40, +0x8D45,0x8D46,0x8D48,0x8D49,0x8D47,0x8D4D,0x8D55,0x8D59, +0x89C7,0x89CA,0x89CB,0x89CC,0x89CE,0x89CF,0x89D0,0x89D1, +0x726E,0x729F,0x725D,0x7266,0x726F,0x727E,0x727F,0x7284, +0x728B,0x728D,0x728F,0x7292,0x6308,0x6332,0x63B0, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x968C,0x968E,0x9691,0x9692,0x9693,0x9695,0x9696,0x969A, +0x969B,0x969D,0x969E,0x969F,0x96A0,0x96A1,0x96A2,0x96A3, +0x96A4,0x96A5,0x96A6,0x96A8,0x96A9,0x96AA,0x96AB,0x96AC, +0x96AD,0x96AE,0x96AF,0x96B1,0x96B2,0x96B4,0x96B5,0x96B7, +0x96B8,0x96BA,0x96BB,0x96BF,0x96C2,0x96C3,0x96C8,0x96CA, +0x96CB,0x96D0,0x96D1,0x96D3,0x96D4,0x96D6,0x96D7,0x96D8, +0x96D9,0x96DA,0x96DB,0x96DC,0x96DD,0x96DE,0x96DF,0x96E1, +0x96E2,0x96E3,0x96E4,0x96E5,0x96E6,0x96E7,0x96EB, 0, +0x96EC,0x96ED,0x96EE,0x96F0,0x96F1,0x96F2,0x96F4,0x96F5, +0x96F8,0x96FA,0x96FB,0x96FC,0x96FD,0x96FF,0x9702,0x9703, +0x9705,0x970A,0x970B,0x970C,0x9710,0x9711,0x9712,0x9714, +0x9715,0x9717,0x9718,0x9719,0x971A,0x971B,0x971D,0x971F, +0x9720,0x643F,0x64D8,0x8004,0x6BEA,0x6BF3,0x6BFD,0x6BF5, +0x6BF9,0x6C05,0x6C07,0x6C06,0x6C0D,0x6C15,0x6C18,0x6C19, +0x6C1A,0x6C21,0x6C29,0x6C24,0x6C2A,0x6C32,0x6535,0x6555, +0x656B,0x724D,0x7252,0x7256,0x7230,0x8662,0x5216,0x809F, +0x809C,0x8093,0x80BC,0x670A,0x80BD,0x80B1,0x80AB,0x80AD, +0x80B4,0x80B7,0x80E7,0x80E8,0x80E9,0x80EA,0x80DB,0x80C2, +0x80C4,0x80D9,0x80CD,0x80D7,0x6710,0x80DD,0x80EB,0x80F1, +0x80F4,0x80ED,0x810D,0x810E,0x80F2,0x80FC,0x6715,0x8112, +0x8C5A,0x8136,0x811E,0x812C,0x8118,0x8132,0x8148,0x814C, +0x8153,0x8174,0x8159,0x815A,0x8171,0x8160,0x8169,0x817C, +0x817D,0x816D,0x8167,0x584D,0x5AB5,0x8188,0x8182,0x8191, +0x6ED5,0x81A3,0x81AA,0x81CC,0x6726,0x81CA,0x81BB, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x9721,0x9722,0x9723,0x9724,0x9725,0x9726,0x9727,0x9728, +0x9729,0x972B,0x972C,0x972E,0x972F,0x9731,0x9733,0x9734, +0x9735,0x9736,0x9737,0x973A,0x973B,0x973C,0x973D,0x973F, +0x9740,0x9741,0x9742,0x9743,0x9744,0x9745,0x9746,0x9747, +0x9748,0x9749,0x974A,0x974B,0x974C,0x974D,0x974E,0x974F, +0x9750,0x9751,0x9754,0x9755,0x9757,0x9758,0x975A,0x975C, +0x975D,0x975F,0x9763,0x9764,0x9766,0x9767,0x9768,0x976A, +0x976B,0x976C,0x976D,0x976E,0x976F,0x9770,0x9771, 0, +0x9772,0x9775,0x9777,0x9778,0x9779,0x977A,0x977B,0x977D, +0x977E,0x977F,0x9780,0x9781,0x9782,0x9783,0x9784,0x9786, +0x9787,0x9788,0x9789,0x978A,0x978C,0x978E,0x978F,0x9790, +0x9793,0x9795,0x9796,0x9797,0x9799,0x979A,0x979B,0x979C, +0x979D,0x81C1,0x81A6,0x6B24,0x6B37,0x6B39,0x6B43,0x6B46, +0x6B59,0x98D1,0x98D2,0x98D3,0x98D5,0x98D9,0x98DA,0x6BB3, +0x5F40,0x6BC2,0x89F3,0x6590,0x9F51,0x6593,0x65BC,0x65C6, +0x65C4,0x65C3,0x65CC,0x65CE,0x65D2,0x65D6,0x7080,0x709C, +0x7096,0x709D,0x70BB,0x70C0,0x70B7,0x70AB,0x70B1,0x70E8, +0x70CA,0x7110,0x7113,0x7116,0x712F,0x7131,0x7173,0x715C, +0x7168,0x7145,0x7172,0x714A,0x7178,0x717A,0x7198,0x71B3, +0x71B5,0x71A8,0x71A0,0x71E0,0x71D4,0x71E7,0x71F9,0x721D, +0x7228,0x706C,0x7118,0x7166,0x71B9,0x623E,0x623D,0x6243, +0x6248,0x6249,0x793B,0x7940,0x7946,0x7949,0x795B,0x795C, +0x7953,0x795A,0x7962,0x7957,0x7960,0x796F,0x7967,0x797A, +0x7985,0x798A,0x799A,0x79A7,0x79B3,0x5FD1,0x5FD0, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x979E,0x979F,0x97A1,0x97A2,0x97A4,0x97A5,0x97A6,0x97A7, +0x97A8,0x97A9,0x97AA,0x97AC,0x97AE,0x97B0,0x97B1,0x97B3, +0x97B5,0x97B6,0x97B7,0x97B8,0x97B9,0x97BA,0x97BB,0x97BC, +0x97BD,0x97BE,0x97BF,0x97C0,0x97C1,0x97C2,0x97C3,0x97C4, +0x97C5,0x97C6,0x97C7,0x97C8,0x97C9,0x97CA,0x97CB,0x97CC, +0x97CD,0x97CE,0x97CF,0x97D0,0x97D1,0x97D2,0x97D3,0x97D4, +0x97D5,0x97D6,0x97D7,0x97D8,0x97D9,0x97DA,0x97DB,0x97DC, +0x97DD,0x97DE,0x97DF,0x97E0,0x97E1,0x97E2,0x97E3, 0, +0x97E4,0x97E5,0x97E8,0x97EE,0x97EF,0x97F0,0x97F1,0x97F2, +0x97F4,0x97F7,0x97F8,0x97F9,0x97FA,0x97FB,0x97FC,0x97FD, +0x97FE,0x97FF,0x9800,0x9801,0x9802,0x9803,0x9804,0x9805, +0x9806,0x9807,0x9808,0x9809,0x980A,0x980B,0x980C,0x980D, +0x980E,0x603C,0x605D,0x605A,0x6067,0x6041,0x6059,0x6063, +0x60AB,0x6106,0x610D,0x615D,0x61A9,0x619D,0x61CB,0x61D1, +0x6206,0x8080,0x807F,0x6C93,0x6CF6,0x6DFC,0x77F6,0x77F8, +0x7800,0x7809,0x7817,0x7818,0x7811,0x65AB,0x782D,0x781C, +0x781D,0x7839,0x783A,0x783B,0x781F,0x783C,0x7825,0x782C, +0x7823,0x7829,0x784E,0x786D,0x7856,0x7857,0x7826,0x7850, +0x7847,0x784C,0x786A,0x789B,0x7893,0x789A,0x7887,0x789C, +0x78A1,0x78A3,0x78B2,0x78B9,0x78A5,0x78D4,0x78D9,0x78C9, +0x78EC,0x78F2,0x7905,0x78F4,0x7913,0x7924,0x791E,0x7934, +0x9F9B,0x9EF9,0x9EFB,0x9EFC,0x76F1,0x7704,0x770D,0x76F9, +0x7707,0x7708,0x771A,0x7722,0x7719,0x772D,0x7726,0x7735, +0x7738,0x7750,0x7751,0x7747,0x7743,0x775A,0x7768, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x980F,0x9810,0x9811,0x9812,0x9813,0x9814,0x9815,0x9816, +0x9817,0x9818,0x9819,0x981A,0x981B,0x981C,0x981D,0x981E, +0x981F,0x9820,0x9821,0x9822,0x9823,0x9824,0x9825,0x9826, +0x9827,0x9828,0x9829,0x982A,0x982B,0x982C,0x982D,0x982E, +0x982F,0x9830,0x9831,0x9832,0x9833,0x9834,0x9835,0x9836, +0x9837,0x9838,0x9839,0x983A,0x983B,0x983C,0x983D,0x983E, +0x983F,0x9840,0x9841,0x9842,0x9843,0x9844,0x9845,0x9846, +0x9847,0x9848,0x9849,0x984A,0x984B,0x984C,0x984D, 0, +0x984E,0x984F,0x9850,0x9851,0x9852,0x9853,0x9854,0x9855, +0x9856,0x9857,0x9858,0x9859,0x985A,0x985B,0x985C,0x985D, +0x985E,0x985F,0x9860,0x9861,0x9862,0x9863,0x9864,0x9865, +0x9866,0x9867,0x9868,0x9869,0x986A,0x986B,0x986C,0x986D, +0x986E,0x7762,0x7765,0x777F,0x778D,0x777D,0x7780,0x778C, +0x7791,0x779F,0x77A0,0x77B0,0x77B5,0x77BD,0x753A,0x7540, +0x754E,0x754B,0x7548,0x755B,0x7572,0x7579,0x7583,0x7F58, +0x7F61,0x7F5F,0x8A48,0x7F68,0x7F74,0x7F71,0x7F79,0x7F81, +0x7F7E,0x76CD,0x76E5,0x8832,0x9485,0x9486,0x9487,0x948B, +0x948A,0x948C,0x948D,0x948F,0x9490,0x9494,0x9497,0x9495, +0x949A,0x949B,0x949C,0x94A3,0x94A4,0x94AB,0x94AA,0x94AD, +0x94AC,0x94AF,0x94B0,0x94B2,0x94B4,0x94B6,0x94B7,0x94B8, +0x94B9,0x94BA,0x94BC,0x94BD,0x94BF,0x94C4,0x94C8,0x94C9, +0x94CA,0x94CB,0x94CC,0x94CD,0x94CE,0x94D0,0x94D1,0x94D2, +0x94D5,0x94D6,0x94D7,0x94D9,0x94D8,0x94DB,0x94DE,0x94DF, +0x94E0,0x94E2,0x94E4,0x94E5,0x94E7,0x94E8,0x94EA, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x986F,0x9870,0x9871,0x9872,0x9873,0x9874,0x988B,0x988E, +0x9892,0x9895,0x9899,0x98A3,0x98A8,0x98A9,0x98AA,0x98AB, +0x98AC,0x98AD,0x98AE,0x98AF,0x98B0,0x98B1,0x98B2,0x98B3, +0x98B4,0x98B5,0x98B6,0x98B7,0x98B8,0x98B9,0x98BA,0x98BB, +0x98BC,0x98BD,0x98BE,0x98BF,0x98C0,0x98C1,0x98C2,0x98C3, +0x98C4,0x98C5,0x98C6,0x98C7,0x98C8,0x98C9,0x98CA,0x98CB, +0x98CC,0x98CD,0x98CF,0x98D0,0x98D4,0x98D6,0x98D7,0x98DB, +0x98DC,0x98DD,0x98E0,0x98E1,0x98E2,0x98E3,0x98E4, 0, +0x98E5,0x98E6,0x98E9,0x98EA,0x98EB,0x98EC,0x98ED,0x98EE, +0x98EF,0x98F0,0x98F1,0x98F2,0x98F3,0x98F4,0x98F5,0x98F6, +0x98F7,0x98F8,0x98F9,0x98FA,0x98FB,0x98FC,0x98FD,0x98FE, +0x98FF,0x9900,0x9901,0x9902,0x9903,0x9904,0x9905,0x9906, +0x9907,0x94E9,0x94EB,0x94EE,0x94EF,0x94F3,0x94F4,0x94F5, +0x94F7,0x94F9,0x94FC,0x94FD,0x94FF,0x9503,0x9502,0x9506, +0x9507,0x9509,0x950A,0x950D,0x950E,0x950F,0x9512,0x9513, +0x9514,0x9515,0x9516,0x9518,0x951B,0x951D,0x951E,0x951F, +0x9522,0x952A,0x952B,0x9529,0x952C,0x9531,0x9532,0x9534, +0x9536,0x9537,0x9538,0x953C,0x953E,0x953F,0x9542,0x9535, +0x9544,0x9545,0x9546,0x9549,0x954C,0x954E,0x954F,0x9552, +0x9553,0x9554,0x9556,0x9557,0x9558,0x9559,0x955B,0x955E, +0x955F,0x955D,0x9561,0x9562,0x9564,0x9565,0x9566,0x9567, +0x9568,0x9569,0x956A,0x956B,0x956C,0x956F,0x9571,0x9572, +0x9573,0x953A,0x77E7,0x77EC,0x96C9,0x79D5,0x79ED,0x79E3, +0x79EB,0x7A06,0x5D47,0x7A03,0x7A02,0x7A1E,0x7A14, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x9908,0x9909,0x990A,0x990B,0x990C,0x990E,0x990F,0x9911, +0x9912,0x9913,0x9914,0x9915,0x9916,0x9917,0x9918,0x9919, +0x991A,0x991B,0x991C,0x991D,0x991E,0x991F,0x9920,0x9921, +0x9922,0x9923,0x9924,0x9925,0x9926,0x9927,0x9928,0x9929, +0x992A,0x992B,0x992C,0x992D,0x992F,0x9930,0x9931,0x9932, +0x9933,0x9934,0x9935,0x9936,0x9937,0x9938,0x9939,0x993A, +0x993B,0x993C,0x993D,0x993E,0x993F,0x9940,0x9941,0x9942, +0x9943,0x9944,0x9945,0x9946,0x9947,0x9948,0x9949, 0, +0x994A,0x994B,0x994C,0x994D,0x994E,0x994F,0x9950,0x9951, +0x9952,0x9953,0x9956,0x9957,0x9958,0x9959,0x995A,0x995B, +0x995C,0x995D,0x995E,0x995F,0x9960,0x9961,0x9962,0x9964, +0x9966,0x9973,0x9978,0x9979,0x997B,0x997E,0x9982,0x9983, +0x9989,0x7A39,0x7A37,0x7A51,0x9ECF,0x99A5,0x7A70,0x7688, +0x768E,0x7693,0x7699,0x76A4,0x74DE,0x74E0,0x752C,0x9E20, +0x9E22,0x9E28,0x9E29,0x9E2A,0x9E2B,0x9E2C,0x9E32,0x9E31, +0x9E36,0x9E38,0x9E37,0x9E39,0x9E3A,0x9E3E,0x9E41,0x9E42, +0x9E44,0x9E46,0x9E47,0x9E48,0x9E49,0x9E4B,0x9E4C,0x9E4E, +0x9E51,0x9E55,0x9E57,0x9E5A,0x9E5B,0x9E5C,0x9E5E,0x9E63, +0x9E66,0x9E67,0x9E68,0x9E69,0x9E6A,0x9E6B,0x9E6C,0x9E71, +0x9E6D,0x9E73,0x7592,0x7594,0x7596,0x75A0,0x759D,0x75AC, +0x75A3,0x75B3,0x75B4,0x75B8,0x75C4,0x75B1,0x75B0,0x75C3, +0x75C2,0x75D6,0x75CD,0x75E3,0x75E8,0x75E6,0x75E4,0x75EB, +0x75E7,0x7603,0x75F1,0x75FC,0x75FF,0x7610,0x7600,0x7605, +0x760C,0x7617,0x760A,0x7625,0x7618,0x7615,0x7619, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x998C,0x998E,0x999A,0x999B,0x999C,0x999D,0x999E,0x999F, +0x99A0,0x99A1,0x99A2,0x99A3,0x99A4,0x99A6,0x99A7,0x99A9, +0x99AA,0x99AB,0x99AC,0x99AD,0x99AE,0x99AF,0x99B0,0x99B1, +0x99B2,0x99B3,0x99B4,0x99B5,0x99B6,0x99B7,0x99B8,0x99B9, +0x99BA,0x99BB,0x99BC,0x99BD,0x99BE,0x99BF,0x99C0,0x99C1, +0x99C2,0x99C3,0x99C4,0x99C5,0x99C6,0x99C7,0x99C8,0x99C9, +0x99CA,0x99CB,0x99CC,0x99CD,0x99CE,0x99CF,0x99D0,0x99D1, +0x99D2,0x99D3,0x99D4,0x99D5,0x99D6,0x99D7,0x99D8, 0, +0x99D9,0x99DA,0x99DB,0x99DC,0x99DD,0x99DE,0x99DF,0x99E0, +0x99E1,0x99E2,0x99E3,0x99E4,0x99E5,0x99E6,0x99E7,0x99E8, +0x99E9,0x99EA,0x99EB,0x99EC,0x99ED,0x99EE,0x99EF,0x99F0, +0x99F1,0x99F2,0x99F3,0x99F4,0x99F5,0x99F6,0x99F7,0x99F8, +0x99F9,0x761B,0x763C,0x7622,0x7620,0x7640,0x762D,0x7630, +0x763F,0x7635,0x7643,0x763E,0x7633,0x764D,0x765E,0x7654, +0x765C,0x7656,0x766B,0x766F,0x7FCA,0x7AE6,0x7A78,0x7A79, +0x7A80,0x7A86,0x7A88,0x7A95,0x7AA6,0x7AA0,0x7AAC,0x7AA8, +0x7AAD,0x7AB3,0x8864,0x8869,0x8872,0x887D,0x887F,0x8882, +0x88A2,0x88C6,0x88B7,0x88BC,0x88C9,0x88E2,0x88CE,0x88E3, +0x88E5,0x88F1,0x891A,0x88FC,0x88E8,0x88FE,0x88F0,0x8921, +0x8919,0x8913,0x891B,0x890A,0x8934,0x892B,0x8936,0x8941, +0x8966,0x897B,0x758B,0x80E5,0x76B2,0x76B4,0x77DC,0x8012, +0x8014,0x8016,0x801C,0x8020,0x8022,0x8025,0x8026,0x8027, +0x8029,0x8028,0x8031,0x800B,0x8035,0x8043,0x8046,0x804D, +0x8052,0x8069,0x8071,0x8983,0x9878,0x9880,0x9883, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x99FA,0x99FB,0x99FC,0x99FD,0x99FE,0x99FF,0x9A00,0x9A01, +0x9A02,0x9A03,0x9A04,0x9A05,0x9A06,0x9A07,0x9A08,0x9A09, +0x9A0A,0x9A0B,0x9A0C,0x9A0D,0x9A0E,0x9A0F,0x9A10,0x9A11, +0x9A12,0x9A13,0x9A14,0x9A15,0x9A16,0x9A17,0x9A18,0x9A19, +0x9A1A,0x9A1B,0x9A1C,0x9A1D,0x9A1E,0x9A1F,0x9A20,0x9A21, +0x9A22,0x9A23,0x9A24,0x9A25,0x9A26,0x9A27,0x9A28,0x9A29, +0x9A2A,0x9A2B,0x9A2C,0x9A2D,0x9A2E,0x9A2F,0x9A30,0x9A31, +0x9A32,0x9A33,0x9A34,0x9A35,0x9A36,0x9A37,0x9A38, 0, +0x9A39,0x9A3A,0x9A3B,0x9A3C,0x9A3D,0x9A3E,0x9A3F,0x9A40, +0x9A41,0x9A42,0x9A43,0x9A44,0x9A45,0x9A46,0x9A47,0x9A48, +0x9A49,0x9A4A,0x9A4B,0x9A4C,0x9A4D,0x9A4E,0x9A4F,0x9A50, +0x9A51,0x9A52,0x9A53,0x9A54,0x9A55,0x9A56,0x9A57,0x9A58, +0x9A59,0x9889,0x988C,0x988D,0x988F,0x9894,0x989A,0x989B, +0x989E,0x989F,0x98A1,0x98A2,0x98A5,0x98A6,0x864D,0x8654, +0x866C,0x866E,0x867F,0x867A,0x867C,0x867B,0x86A8,0x868D, +0x868B,0x86AC,0x869D,0x86A7,0x86A3,0x86AA,0x8693,0x86A9, +0x86B6,0x86C4,0x86B5,0x86CE,0x86B0,0x86BA,0x86B1,0x86AF, +0x86C9,0x86CF,0x86B4,0x86E9,0x86F1,0x86F2,0x86ED,0x86F3, +0x86D0,0x8713,0x86DE,0x86F4,0x86DF,0x86D8,0x86D1,0x8703, +0x8707,0x86F8,0x8708,0x870A,0x870D,0x8709,0x8723,0x873B, +0x871E,0x8725,0x872E,0x871A,0x873E,0x8748,0x8734,0x8731, +0x8729,0x8737,0x873F,0x8782,0x8722,0x877D,0x877E,0x877B, +0x8760,0x8770,0x874C,0x876E,0x878B,0x8753,0x8763,0x877C, +0x8764,0x8759,0x8765,0x8793,0x87AF,0x87A8,0x87D2, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x9A5A,0x9A5B,0x9A5C,0x9A5D,0x9A5E,0x9A5F,0x9A60,0x9A61, +0x9A62,0x9A63,0x9A64,0x9A65,0x9A66,0x9A67,0x9A68,0x9A69, +0x9A6A,0x9A6B,0x9A72,0x9A83,0x9A89,0x9A8D,0x9A8E,0x9A94, +0x9A95,0x9A99,0x9AA6,0x9AA9,0x9AAA,0x9AAB,0x9AAC,0x9AAD, +0x9AAE,0x9AAF,0x9AB2,0x9AB3,0x9AB4,0x9AB5,0x9AB9,0x9ABB, +0x9ABD,0x9ABE,0x9ABF,0x9AC3,0x9AC4,0x9AC6,0x9AC7,0x9AC8, +0x9AC9,0x9ACA,0x9ACD,0x9ACE,0x9ACF,0x9AD0,0x9AD2,0x9AD4, +0x9AD5,0x9AD6,0x9AD7,0x9AD9,0x9ADA,0x9ADB,0x9ADC, 0, +0x9ADD,0x9ADE,0x9AE0,0x9AE2,0x9AE3,0x9AE4,0x9AE5,0x9AE7, +0x9AE8,0x9AE9,0x9AEA,0x9AEC,0x9AEE,0x9AF0,0x9AF1,0x9AF2, +0x9AF3,0x9AF4,0x9AF5,0x9AF6,0x9AF7,0x9AF8,0x9AFA,0x9AFC, +0x9AFD,0x9AFE,0x9AFF,0x9B00,0x9B01,0x9B02,0x9B04,0x9B05, +0x9B06,0x87C6,0x8788,0x8785,0x87AD,0x8797,0x8783,0x87AB, +0x87E5,0x87AC,0x87B5,0x87B3,0x87CB,0x87D3,0x87BD,0x87D1, +0x87C0,0x87CA,0x87DB,0x87EA,0x87E0,0x87EE,0x8816,0x8813, +0x87FE,0x880A,0x881B,0x8821,0x8839,0x883C,0x7F36,0x7F42, +0x7F44,0x7F45,0x8210,0x7AFA,0x7AFD,0x7B08,0x7B03,0x7B04, +0x7B15,0x7B0A,0x7B2B,0x7B0F,0x7B47,0x7B38,0x7B2A,0x7B19, +0x7B2E,0x7B31,0x7B20,0x7B25,0x7B24,0x7B33,0x7B3E,0x7B1E, +0x7B58,0x7B5A,0x7B45,0x7B75,0x7B4C,0x7B5D,0x7B60,0x7B6E, +0x7B7B,0x7B62,0x7B72,0x7B71,0x7B90,0x7BA6,0x7BA7,0x7BB8, +0x7BAC,0x7B9D,0x7BA8,0x7B85,0x7BAA,0x7B9C,0x7BA2,0x7BAB, +0x7BB4,0x7BD1,0x7BC1,0x7BCC,0x7BDD,0x7BDA,0x7BE5,0x7BE6, +0x7BEA,0x7C0C,0x7BFE,0x7BFC,0x7C0F,0x7C16,0x7C0B, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x9B07,0x9B09,0x9B0A,0x9B0B,0x9B0C,0x9B0D,0x9B0E,0x9B10, +0x9B11,0x9B12,0x9B14,0x9B15,0x9B16,0x9B17,0x9B18,0x9B19, +0x9B1A,0x9B1B,0x9B1C,0x9B1D,0x9B1E,0x9B20,0x9B21,0x9B22, +0x9B24,0x9B25,0x9B26,0x9B27,0x9B28,0x9B29,0x9B2A,0x9B2B, +0x9B2C,0x9B2D,0x9B2E,0x9B30,0x9B31,0x9B33,0x9B34,0x9B35, +0x9B36,0x9B37,0x9B38,0x9B39,0x9B3A,0x9B3D,0x9B3E,0x9B3F, +0x9B40,0x9B46,0x9B4A,0x9B4B,0x9B4C,0x9B4E,0x9B50,0x9B52, +0x9B53,0x9B55,0x9B56,0x9B57,0x9B58,0x9B59,0x9B5A, 0, +0x9B5B,0x9B5C,0x9B5D,0x9B5E,0x9B5F,0x9B60,0x9B61,0x9B62, +0x9B63,0x9B64,0x9B65,0x9B66,0x9B67,0x9B68,0x9B69,0x9B6A, +0x9B6B,0x9B6C,0x9B6D,0x9B6E,0x9B6F,0x9B70,0x9B71,0x9B72, +0x9B73,0x9B74,0x9B75,0x9B76,0x9B77,0x9B78,0x9B79,0x9B7A, +0x9B7B,0x7C1F,0x7C2A,0x7C26,0x7C38,0x7C41,0x7C40,0x81FE, +0x8201,0x8202,0x8204,0x81EC,0x8844,0x8221,0x8222,0x8223, +0x822D,0x822F,0x8228,0x822B,0x8238,0x823B,0x8233,0x8234, +0x823E,0x8244,0x8249,0x824B,0x824F,0x825A,0x825F,0x8268, +0x887E,0x8885,0x8888,0x88D8,0x88DF,0x895E,0x7F9D,0x7F9F, +0x7FA7,0x7FAF,0x7FB0,0x7FB2,0x7C7C,0x6549,0x7C91,0x7C9D, +0x7C9C,0x7C9E,0x7CA2,0x7CB2,0x7CBC,0x7CBD,0x7CC1,0x7CC7, +0x7CCC,0x7CCD,0x7CC8,0x7CC5,0x7CD7,0x7CE8,0x826E,0x66A8, +0x7FBF,0x7FCE,0x7FD5,0x7FE5,0x7FE1,0x7FE6,0x7FE9,0x7FEE, +0x7FF3,0x7CF8,0x7D77,0x7DA6,0x7DAE,0x7E47,0x7E9B,0x9EB8, +0x9EB4,0x8D73,0x8D84,0x8D94,0x8D91,0x8DB1,0x8D67,0x8D6D, +0x8C47,0x8C49,0x914A,0x9150,0x914E,0x914F,0x9164, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x9B7C,0x9B7D,0x9B7E,0x9B7F,0x9B80,0x9B81,0x9B82,0x9B83, +0x9B84,0x9B85,0x9B86,0x9B87,0x9B88,0x9B89,0x9B8A,0x9B8B, +0x9B8C,0x9B8D,0x9B8E,0x9B8F,0x9B90,0x9B91,0x9B92,0x9B93, +0x9B94,0x9B95,0x9B96,0x9B97,0x9B98,0x9B99,0x9B9A,0x9B9B, +0x9B9C,0x9B9D,0x9B9E,0x9B9F,0x9BA0,0x9BA1,0x9BA2,0x9BA3, +0x9BA4,0x9BA5,0x9BA6,0x9BA7,0x9BA8,0x9BA9,0x9BAA,0x9BAB, +0x9BAC,0x9BAD,0x9BAE,0x9BAF,0x9BB0,0x9BB1,0x9BB2,0x9BB3, +0x9BB4,0x9BB5,0x9BB6,0x9BB7,0x9BB8,0x9BB9,0x9BBA, 0, +0x9BBB,0x9BBC,0x9BBD,0x9BBE,0x9BBF,0x9BC0,0x9BC1,0x9BC2, +0x9BC3,0x9BC4,0x9BC5,0x9BC6,0x9BC7,0x9BC8,0x9BC9,0x9BCA, +0x9BCB,0x9BCC,0x9BCD,0x9BCE,0x9BCF,0x9BD0,0x9BD1,0x9BD2, +0x9BD3,0x9BD4,0x9BD5,0x9BD6,0x9BD7,0x9BD8,0x9BD9,0x9BDA, +0x9BDB,0x9162,0x9161,0x9170,0x9169,0x916F,0x917D,0x917E, +0x9172,0x9174,0x9179,0x918C,0x9185,0x9190,0x918D,0x9191, +0x91A2,0x91A3,0x91AA,0x91AD,0x91AE,0x91AF,0x91B5,0x91B4, +0x91BA,0x8C55,0x9E7E,0x8DB8,0x8DEB,0x8E05,0x8E59,0x8E69, +0x8DB5,0x8DBF,0x8DBC,0x8DBA,0x8DC4,0x8DD6,0x8DD7,0x8DDA, +0x8DDE,0x8DCE,0x8DCF,0x8DDB,0x8DC6,0x8DEC,0x8DF7,0x8DF8, +0x8DE3,0x8DF9,0x8DFB,0x8DE4,0x8E09,0x8DFD,0x8E14,0x8E1D, +0x8E1F,0x8E2C,0x8E2E,0x8E23,0x8E2F,0x8E3A,0x8E40,0x8E39, +0x8E35,0x8E3D,0x8E31,0x8E49,0x8E41,0x8E42,0x8E51,0x8E52, +0x8E4A,0x8E70,0x8E76,0x8E7C,0x8E6F,0x8E74,0x8E85,0x8E8F, +0x8E94,0x8E90,0x8E9C,0x8E9E,0x8C78,0x8C82,0x8C8A,0x8C85, +0x8C98,0x8C94,0x659B,0x89D6,0x89DE,0x89DA,0x89DC, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x9BDC,0x9BDD,0x9BDE,0x9BDF,0x9BE0,0x9BE1,0x9BE2,0x9BE3, +0x9BE4,0x9BE5,0x9BE6,0x9BE7,0x9BE8,0x9BE9,0x9BEA,0x9BEB, +0x9BEC,0x9BED,0x9BEE,0x9BEF,0x9BF0,0x9BF1,0x9BF2,0x9BF3, +0x9BF4,0x9BF5,0x9BF6,0x9BF7,0x9BF8,0x9BF9,0x9BFA,0x9BFB, +0x9BFC,0x9BFD,0x9BFE,0x9BFF,0x9C00,0x9C01,0x9C02,0x9C03, +0x9C04,0x9C05,0x9C06,0x9C07,0x9C08,0x9C09,0x9C0A,0x9C0B, +0x9C0C,0x9C0D,0x9C0E,0x9C0F,0x9C10,0x9C11,0x9C12,0x9C13, +0x9C14,0x9C15,0x9C16,0x9C17,0x9C18,0x9C19,0x9C1A, 0, +0x9C1B,0x9C1C,0x9C1D,0x9C1E,0x9C1F,0x9C20,0x9C21,0x9C22, +0x9C23,0x9C24,0x9C25,0x9C26,0x9C27,0x9C28,0x9C29,0x9C2A, +0x9C2B,0x9C2C,0x9C2D,0x9C2E,0x9C2F,0x9C30,0x9C31,0x9C32, +0x9C33,0x9C34,0x9C35,0x9C36,0x9C37,0x9C38,0x9C39,0x9C3A, +0x9C3B,0x89E5,0x89EB,0x89EF,0x8A3E,0x8B26,0x9753,0x96E9, +0x96F3,0x96EF,0x9706,0x9701,0x9708,0x970F,0x970E,0x972A, +0x972D,0x9730,0x973E,0x9F80,0x9F83,0x9F85,0x9F86,0x9F87, +0x9F88,0x9F89,0x9F8A,0x9F8C,0x9EFE,0x9F0B,0x9F0D,0x96B9, +0x96BC,0x96BD,0x96CE,0x96D2,0x77BF,0x96E0,0x928E,0x92AE, +0x92C8,0x933E,0x936A,0x93CA,0x938F,0x943E,0x946B,0x9C7F, +0x9C82,0x9C85,0x9C86,0x9C87,0x9C88,0x7A23,0x9C8B,0x9C8E, +0x9C90,0x9C91,0x9C92,0x9C94,0x9C95,0x9C9A,0x9C9B,0x9C9E, +0x9C9F,0x9CA0,0x9CA1,0x9CA2,0x9CA3,0x9CA5,0x9CA6,0x9CA7, +0x9CA8,0x9CA9,0x9CAB,0x9CAD,0x9CAE,0x9CB0,0x9CB1,0x9CB2, +0x9CB3,0x9CB4,0x9CB5,0x9CB6,0x9CB7,0x9CBA,0x9CBB,0x9CBC, +0x9CBD,0x9CC4,0x9CC5,0x9CC6,0x9CC7,0x9CCA,0x9CCB, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x9C3C,0x9C3D,0x9C3E,0x9C3F,0x9C40,0x9C41,0x9C42,0x9C43, +0x9C44,0x9C45,0x9C46,0x9C47,0x9C48,0x9C49,0x9C4A,0x9C4B, +0x9C4C,0x9C4D,0x9C4E,0x9C4F,0x9C50,0x9C51,0x9C52,0x9C53, +0x9C54,0x9C55,0x9C56,0x9C57,0x9C58,0x9C59,0x9C5A,0x9C5B, +0x9C5C,0x9C5D,0x9C5E,0x9C5F,0x9C60,0x9C61,0x9C62,0x9C63, +0x9C64,0x9C65,0x9C66,0x9C67,0x9C68,0x9C69,0x9C6A,0x9C6B, +0x9C6C,0x9C6D,0x9C6E,0x9C6F,0x9C70,0x9C71,0x9C72,0x9C73, +0x9C74,0x9C75,0x9C76,0x9C77,0x9C78,0x9C79,0x9C7A, 0, +0x9C7B,0x9C7D,0x9C7E,0x9C80,0x9C83,0x9C84,0x9C89,0x9C8A, +0x9C8C,0x9C8F,0x9C93,0x9C96,0x9C97,0x9C98,0x9C99,0x9C9D, +0x9CAA,0x9CAC,0x9CAF,0x9CB9,0x9CBE,0x9CBF,0x9CC0,0x9CC1, +0x9CC2,0x9CC8,0x9CC9,0x9CD1,0x9CD2,0x9CDA,0x9CDB,0x9CE0, +0x9CE1,0x9CCC,0x9CCD,0x9CCE,0x9CCF,0x9CD0,0x9CD3,0x9CD4, +0x9CD5,0x9CD7,0x9CD8,0x9CD9,0x9CDC,0x9CDD,0x9CDF,0x9CE2, +0x977C,0x9785,0x9791,0x9792,0x9794,0x97AF,0x97AB,0x97A3, +0x97B2,0x97B4,0x9AB1,0x9AB0,0x9AB7,0x9E58,0x9AB6,0x9ABA, +0x9ABC,0x9AC1,0x9AC0,0x9AC5,0x9AC2,0x9ACB,0x9ACC,0x9AD1, +0x9B45,0x9B43,0x9B47,0x9B49,0x9B48,0x9B4D,0x9B51,0x98E8, +0x990D,0x992E,0x9955,0x9954,0x9ADF,0x9AE1,0x9AE6,0x9AEF, +0x9AEB,0x9AFB,0x9AED,0x9AF9,0x9B08,0x9B0F,0x9B13,0x9B1F, +0x9B23,0x9EBD,0x9EBE,0x7E3B,0x9E82,0x9E87,0x9E88,0x9E8B, +0x9E92,0x93D6,0x9E9D,0x9E9F,0x9EDB,0x9EDC,0x9EDD,0x9EE0, +0x9EDF,0x9EE2,0x9EE9,0x9EE7,0x9EE5,0x9EEA,0x9EEF,0x9F22, +0x9F2C,0x9F2F,0x9F39,0x9F37,0x9F3D,0x9F3E,0x9F44, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0x9CE3,0x9CE4,0x9CE5,0x9CE6,0x9CE7,0x9CE8,0x9CE9,0x9CEA, +0x9CEB,0x9CEC,0x9CED,0x9CEE,0x9CEF,0x9CF0,0x9CF1,0x9CF2, +0x9CF3,0x9CF4,0x9CF5,0x9CF6,0x9CF7,0x9CF8,0x9CF9,0x9CFA, +0x9CFB,0x9CFC,0x9CFD,0x9CFE,0x9CFF,0x9D00,0x9D01,0x9D02, +0x9D03,0x9D04,0x9D05,0x9D06,0x9D07,0x9D08,0x9D09,0x9D0A, +0x9D0B,0x9D0C,0x9D0D,0x9D0E,0x9D0F,0x9D10,0x9D11,0x9D12, +0x9D13,0x9D14,0x9D15,0x9D16,0x9D17,0x9D18,0x9D19,0x9D1A, +0x9D1B,0x9D1C,0x9D1D,0x9D1E,0x9D1F,0x9D20,0x9D21, 0, +0x9D22,0x9D23,0x9D24,0x9D25,0x9D26,0x9D27,0x9D28,0x9D29, +0x9D2A,0x9D2B,0x9D2C,0x9D2D,0x9D2E,0x9D2F,0x9D30,0x9D31, +0x9D32,0x9D33,0x9D34,0x9D35,0x9D36,0x9D37,0x9D38,0x9D39, +0x9D3A,0x9D3B,0x9D3C,0x9D3D,0x9D3E,0x9D3F,0x9D40,0x9D41, +0x9D42, 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, 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, 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, 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, +0x9D43,0x9D44,0x9D45,0x9D46,0x9D47,0x9D48,0x9D49,0x9D4A, +0x9D4B,0x9D4C,0x9D4D,0x9D4E,0x9D4F,0x9D50,0x9D51,0x9D52, +0x9D53,0x9D54,0x9D55,0x9D56,0x9D57,0x9D58,0x9D59,0x9D5A, +0x9D5B,0x9D5C,0x9D5D,0x9D5E,0x9D5F,0x9D60,0x9D61,0x9D62, +0x9D63,0x9D64,0x9D65,0x9D66,0x9D67,0x9D68,0x9D69,0x9D6A, +0x9D6B,0x9D6C,0x9D6D,0x9D6E,0x9D6F,0x9D70,0x9D71,0x9D72, +0x9D73,0x9D74,0x9D75,0x9D76,0x9D77,0x9D78,0x9D79,0x9D7A, +0x9D7B,0x9D7C,0x9D7D,0x9D7E,0x9D7F,0x9D80,0x9D81, 0, +0x9D82,0x9D83,0x9D84,0x9D85,0x9D86,0x9D87,0x9D88,0x9D89, +0x9D8A,0x9D8B,0x9D8C,0x9D8D,0x9D8E,0x9D8F,0x9D90,0x9D91, +0x9D92,0x9D93,0x9D94,0x9D95,0x9D96,0x9D97,0x9D98,0x9D99, +0x9D9A,0x9D9B,0x9D9C,0x9D9D,0x9D9E,0x9D9F,0x9DA0,0x9DA1, +0x9DA2, 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, 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, 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, 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, +0x9DA3,0x9DA4,0x9DA5,0x9DA6,0x9DA7,0x9DA8,0x9DA9,0x9DAA, +0x9DAB,0x9DAC,0x9DAD,0x9DAE,0x9DAF,0x9DB0,0x9DB1,0x9DB2, +0x9DB3,0x9DB4,0x9DB5,0x9DB6,0x9DB7,0x9DB8,0x9DB9,0x9DBA, +0x9DBB,0x9DBC,0x9DBD,0x9DBE,0x9DBF,0x9DC0,0x9DC1,0x9DC2, +0x9DC3,0x9DC4,0x9DC5,0x9DC6,0x9DC7,0x9DC8,0x9DC9,0x9DCA, +0x9DCB,0x9DCC,0x9DCD,0x9DCE,0x9DCF,0x9DD0,0x9DD1,0x9DD2, +0x9DD3,0x9DD4,0x9DD5,0x9DD6,0x9DD7,0x9DD8,0x9DD9,0x9DDA, +0x9DDB,0x9DDC,0x9DDD,0x9DDE,0x9DDF,0x9DE0,0x9DE1, 0, +0x9DE2,0x9DE3,0x9DE4,0x9DE5,0x9DE6,0x9DE7,0x9DE8,0x9DE9, +0x9DEA,0x9DEB,0x9DEC,0x9DED,0x9DEE,0x9DEF,0x9DF0,0x9DF1, +0x9DF2,0x9DF3,0x9DF4,0x9DF5,0x9DF6,0x9DF7,0x9DF8,0x9DF9, +0x9DFA,0x9DFB,0x9DFC,0x9DFD,0x9DFE,0x9DFF,0x9E00,0x9E01, +0x9E02, 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, 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, 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, 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, +0x9E03,0x9E04,0x9E05,0x9E06,0x9E07,0x9E08,0x9E09,0x9E0A, +0x9E0B,0x9E0C,0x9E0D,0x9E0E,0x9E0F,0x9E10,0x9E11,0x9E12, +0x9E13,0x9E14,0x9E15,0x9E16,0x9E17,0x9E18,0x9E19,0x9E1A, +0x9E1B,0x9E1C,0x9E1D,0x9E1E,0x9E24,0x9E27,0x9E2E,0x9E30, +0x9E34,0x9E3B,0x9E3C,0x9E40,0x9E4D,0x9E50,0x9E52,0x9E53, +0x9E54,0x9E56,0x9E59,0x9E5D,0x9E5F,0x9E60,0x9E61,0x9E62, +0x9E65,0x9E6E,0x9E6F,0x9E72,0x9E74,0x9E75,0x9E76,0x9E77, +0x9E78,0x9E79,0x9E7A,0x9E7B,0x9E7C,0x9E7D,0x9E80, 0, +0x9E81,0x9E83,0x9E84,0x9E85,0x9E86,0x9E89,0x9E8A,0x9E8C, +0x9E8D,0x9E8E,0x9E8F,0x9E90,0x9E91,0x9E94,0x9E95,0x9E96, +0x9E97,0x9E98,0x9E99,0x9E9A,0x9E9B,0x9E9C,0x9E9E,0x9EA0, +0x9EA1,0x9EA2,0x9EA3,0x9EA4,0x9EA5,0x9EA7,0x9EA8,0x9EA9, +0x9EAA, 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, 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, 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, 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, +0x9EAB,0x9EAC,0x9EAD,0x9EAE,0x9EAF,0x9EB0,0x9EB1,0x9EB2, +0x9EB3,0x9EB5,0x9EB6,0x9EB7,0x9EB9,0x9EBA,0x9EBC,0x9EBF, +0x9EC0,0x9EC1,0x9EC2,0x9EC3,0x9EC5,0x9EC6,0x9EC7,0x9EC8, +0x9ECA,0x9ECB,0x9ECC,0x9ED0,0x9ED2,0x9ED3,0x9ED5,0x9ED6, +0x9ED7,0x9ED9,0x9EDA,0x9EDE,0x9EE1,0x9EE3,0x9EE4,0x9EE6, +0x9EE8,0x9EEB,0x9EEC,0x9EED,0x9EEE,0x9EF0,0x9EF1,0x9EF2, +0x9EF3,0x9EF4,0x9EF5,0x9EF6,0x9EF7,0x9EF8,0x9EFA,0x9EFD, +0x9EFF,0x9F00,0x9F01,0x9F02,0x9F03,0x9F04,0x9F05, 0, +0x9F06,0x9F07,0x9F08,0x9F09,0x9F0A,0x9F0C,0x9F0F,0x9F11, +0x9F12,0x9F14,0x9F15,0x9F16,0x9F18,0x9F1A,0x9F1B,0x9F1C, +0x9F1D,0x9F1E,0x9F1F,0x9F21,0x9F23,0x9F24,0x9F25,0x9F26, +0x9F27,0x9F28,0x9F29,0x9F2A,0x9F2B,0x9F2D,0x9F2E,0x9F30, +0x9F31, 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, 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, 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, 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, +0x9F32,0x9F33,0x9F34,0x9F35,0x9F36,0x9F38,0x9F3A,0x9F3C, +0x9F3F,0x9F40,0x9F41,0x9F42,0x9F43,0x9F45,0x9F46,0x9F47, +0x9F48,0x9F49,0x9F4A,0x9F4B,0x9F4C,0x9F4D,0x9F4E,0x9F4F, +0x9F52,0x9F53,0x9F54,0x9F55,0x9F56,0x9F57,0x9F58,0x9F59, +0x9F5A,0x9F5B,0x9F5C,0x9F5D,0x9F5E,0x9F5F,0x9F60,0x9F61, +0x9F62,0x9F63,0x9F64,0x9F65,0x9F66,0x9F67,0x9F68,0x9F69, +0x9F6A,0x9F6B,0x9F6C,0x9F6D,0x9F6E,0x9F6F,0x9F70,0x9F71, +0x9F72,0x9F73,0x9F74,0x9F75,0x9F76,0x9F77,0x9F78, 0, +0x9F79,0x9F7A,0x9F7B,0x9F7C,0x9F7D,0x9F7E,0x9F81,0x9F82, +0x9F8D,0x9F8E,0x9F8F,0x9F90,0x9F91,0x9F92,0x9F93,0x9F94, +0x9F95,0x9F96,0x9F97,0x9F98,0x9F9C,0x9F9D,0x9F9E,0x9FA1, +0x9FA2,0x9FA3,0x9FA4,0x9FA5,0xF92C,0xF979,0xF995,0xF9E7, +0xF9F1, 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, 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, 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, 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, +0xFA0C,0xFA0D,0xFA0E,0xFA0F,0xFA11,0xFA13,0xFA14,0xFA18, +0xFA1F,0xFA20,0xFA21,0xFA23,0xFA24,0xFA27,0xFA28,0xFA29 +}; + +static int func_gbk_uni_onechar(int code){ + if ((code>=0x8140)&&(code<=0xFE4F)) + return(tab_gbk_uni0[code-0x8140]); + return(0); +} + + + + +static uint16_t tab_uni_gbk0[]={ +0xA1E8, 0, 0,0xA1EC,0xA1A7, 0, 0, 0, + 0, 0, 0, 0,0xA1E3,0xA1C0, 0, 0, + 0, 0, 0,0xA1A4, 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,0xA1C1, 0, 0, 0, 0, + 0, 0, 0, 0,0xA8A4,0xA8A2, 0, 0, + 0, 0, 0, 0,0xA8A8,0xA8A6,0xA8BA, 0, +0xA8AC,0xA8AA, 0, 0, 0, 0,0xA8B0,0xA8AE, + 0, 0, 0,0xA1C2, 0,0xA8B4,0xA8B2, 0, +0xA8B9, 0, 0, 0, 0,0xA8A1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,0xA8A5, + 0, 0, 0, 0, 0, 0, 0,0xA8A7, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,0xA8A9, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0xA8BD, 0, 0, 0,0xA8BE, 0, 0, 0, + 0,0xA8AD, 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,0xA8B1, + 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, 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, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,0xA8A3, 0,0xA8AB, 0,0xA8AF, 0, +0xA8B3, 0,0xA8B5, 0,0xA8B6, 0,0xA8B7, 0, +0xA8B8, 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, 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, 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,0xA8BB, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,0xA8C0, 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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,0xA1A6, 0,0xA1A5,0xA840,0xA841, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,0xA842, 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, 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, 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, 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, 0, 0, + 0, 0, 0, 0, 0,0xA6A1,0xA6A2,0xA6A3, +0xA6A4,0xA6A5,0xA6A6,0xA6A7,0xA6A8,0xA6A9,0xA6AA,0xA6AB, +0xA6AC,0xA6AD,0xA6AE,0xA6AF,0xA6B0,0xA6B1, 0,0xA6B2, +0xA6B3,0xA6B4,0xA6B5,0xA6B6,0xA6B7,0xA6B8, 0, 0, + 0, 0, 0, 0, 0,0xA6C1,0xA6C2,0xA6C3, +0xA6C4,0xA6C5,0xA6C6,0xA6C7,0xA6C8,0xA6C9,0xA6CA,0xA6CB, +0xA6CC,0xA6CD,0xA6CE,0xA6CF,0xA6D0,0xA6D1, 0,0xA6D2, +0xA6D3,0xA6D4,0xA6D5,0xA6D6,0xA6D7,0xA6D8, 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, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,0xA7A7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,0xA7A1,0xA7A2,0xA7A3,0xA7A4, +0xA7A5,0xA7A6,0xA7A8,0xA7A9,0xA7AA,0xA7AB,0xA7AC,0xA7AD, +0xA7AE,0xA7AF,0xA7B0,0xA7B1,0xA7B2,0xA7B3,0xA7B4,0xA7B5, +0xA7B6,0xA7B7,0xA7B8,0xA7B9,0xA7BA,0xA7BB,0xA7BC,0xA7BD, +0xA7BE,0xA7BF,0xA7C0,0xA7C1,0xA7D1,0xA7D2,0xA7D3,0xA7D4, +0xA7D5,0xA7D6,0xA7D8,0xA7D9,0xA7DA,0xA7DB,0xA7DC,0xA7DD, +0xA7DE,0xA7DF,0xA7E0,0xA7E1,0xA7E2,0xA7E3,0xA7E4,0xA7E5, +0xA7E6,0xA7E7,0xA7E8,0xA7E9,0xA7EA,0xA7EB,0xA7EC,0xA7ED, +0xA7EE,0xA7EF,0xA7F0,0xA7F1, 0,0xA7D7}; + + +static uint16_t tab_uni_gbk1[]={ +0xA95C, 0, 0,0xA843,0xA1AA,0xA844,0xA1AC, 0, +0xA1AE,0xA1AF, 0, 0,0xA1B0,0xA1B1, 0, 0, + 0, 0, 0, 0, 0,0xA845,0xA1AD, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0xA1EB, 0,0xA1E4,0xA1E5, 0,0xA846, 0, 0, + 0, 0, 0,0xA1F9, 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, + 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, 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, + 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, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,0xA1E6, 0,0xA847, 0, 0, + 0,0xA848, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,0xA1ED, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0,0xA959, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0xA2F1,0xA2F2,0xA2F3,0xA2F4,0xA2F5,0xA2F6,0xA2F7,0xA2F8, +0xA2F9,0xA2FA,0xA2FB,0xA2FC, 0, 0, 0, 0, +0xA2A1,0xA2A2,0xA2A3,0xA2A4,0xA2A5,0xA2A6,0xA2A7,0xA2A8, +0xA2A9,0xA2AA, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0xA1FB,0xA1FC,0xA1FA,0xA1FD, 0, 0,0xA849,0xA84A, +0xA84B,0xA84C, 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, 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, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0xA1CA, 0, 0, 0, 0, 0, 0,0xA1C7, + 0,0xA1C6, 0, 0, 0,0xA84D, 0, 0, + 0, 0,0xA1CC, 0, 0,0xA1D8,0xA1DE,0xA84E, +0xA1CF, 0, 0,0xA84F, 0,0xA1CE, 0,0xA1C4, +0xA1C5,0xA1C9,0xA1C8,0xA1D2, 0, 0,0xA1D3, 0, + 0, 0, 0, 0,0xA1E0,0xA1DF,0xA1C3,0xA1CB, + 0, 0, 0, 0, 0,0xA1D7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0xA1D6, 0, 0, 0,0xA1D5, 0, 0, 0, + 0, 0,0xA850, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0xA1D9,0xA1D4, 0, 0,0xA1DC,0xA1DD,0xA851,0xA852, + 0, 0, 0, 0, 0, 0,0xA1DA,0xA1DB, + 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,0xA892, 0, 0, + 0,0xA1D1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,0xA1CD, 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,0xA853, + 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, 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,0xA1D0}; + + +static uint16_t tab_uni_gbk2[]={ +0xA2D9,0xA2DA,0xA2DB,0xA2DC,0xA2DD,0xA2DE,0xA2DF,0xA2E0, +0xA2E1,0xA2E2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,0xA2C5,0xA2C6,0xA2C7,0xA2C8, +0xA2C9,0xA2CA,0xA2CB,0xA2CC,0xA2CD,0xA2CE,0xA2CF,0xA2D0, +0xA2D1,0xA2D2,0xA2D3,0xA2D4,0xA2D5,0xA2D6,0xA2D7,0xA2D8, +0xA2B1,0xA2B2,0xA2B3,0xA2B4,0xA2B5,0xA2B6,0xA2B7,0xA2B8, +0xA2B9,0xA2BA,0xA2BB,0xA2BC,0xA2BD,0xA2BE,0xA2BF,0xA2C0, +0xA2C1,0xA2C2,0xA2C3,0xA2C4, 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, + 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, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0xA9A4,0xA9A5,0xA9A6,0xA9A7,0xA9A8,0xA9A9,0xA9AA,0xA9AB, +0xA9AC,0xA9AD,0xA9AE,0xA9AF,0xA9B0,0xA9B1,0xA9B2,0xA9B3, +0xA9B4,0xA9B5,0xA9B6,0xA9B7,0xA9B8,0xA9B9,0xA9BA,0xA9BB, +0xA9BC,0xA9BD,0xA9BE,0xA9BF,0xA9C0,0xA9C1,0xA9C2,0xA9C3, +0xA9C4,0xA9C5,0xA9C6,0xA9C7,0xA9C8,0xA9C9,0xA9CA,0xA9CB, +0xA9CC,0xA9CD,0xA9CE,0xA9CF,0xA9D0,0xA9D1,0xA9D2,0xA9D3, +0xA9D4,0xA9D5,0xA9D6,0xA9D7,0xA9D8,0xA9D9,0xA9DA,0xA9DB, +0xA9DC,0xA9DD,0xA9DE,0xA9DF,0xA9E0,0xA9E1,0xA9E2,0xA9E3, +0xA9E4,0xA9E5,0xA9E6,0xA9E7,0xA9E8,0xA9E9,0xA9EA,0xA9EB, +0xA9EC,0xA9ED,0xA9EE,0xA9EF, 0, 0, 0, 0, +0xA854,0xA855,0xA856,0xA857,0xA858,0xA859,0xA85A,0xA85B, +0xA85C,0xA85D,0xA85E,0xA85F,0xA860,0xA861,0xA862,0xA863, +0xA864,0xA865,0xA866,0xA867,0xA868,0xA869,0xA86A,0xA86B, +0xA86C,0xA86D,0xA86E,0xA86F,0xA870,0xA871,0xA872,0xA873, +0xA874,0xA875,0xA876,0xA877, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0,0xA878,0xA879,0xA87A,0xA87B,0xA87C,0xA87D,0xA87E, +0xA880,0xA881,0xA882,0xA883,0xA884,0xA885,0xA886,0xA887, + 0, 0, 0,0xA888,0xA889,0xA88A, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0xA1F6,0xA1F5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,0xA1F8,0xA1F7, 0, 0, 0, 0, + 0, 0, 0, 0,0xA88B,0xA88C, 0, 0, + 0, 0, 0, 0, 0, 0,0xA1F4,0xA1F3, + 0, 0, 0,0xA1F0, 0, 0,0xA1F2,0xA1F1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,0xA88D,0xA88E,0xA88F,0xA890, 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,0xA1EF,0xA1EE, 0, + 0,0xA891, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0xA1E2, 0,0xA1E1}; + + +static uint16_t tab_uni_gbk3[]={ +0xA1A1,0xA1A2,0xA1A3,0xA1A8, 0,0xA1A9,0xA965,0xA996, +0xA1B4,0xA1B5,0xA1B6,0xA1B7,0xA1B8,0xA1B9,0xA1BA,0xA1BB, +0xA1BE,0xA1BF,0xA893,0xA1FE,0xA1B2,0xA1B3,0xA1BC,0xA1BD, + 0, 0, 0, 0, 0,0xA894,0xA895, 0, + 0,0xA940,0xA941,0xA942,0xA943,0xA944,0xA945,0xA946, +0xA947,0xA948, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0,0xA4A1,0xA4A2,0xA4A3,0xA4A4,0xA4A5,0xA4A6,0xA4A7, +0xA4A8,0xA4A9,0xA4AA,0xA4AB,0xA4AC,0xA4AD,0xA4AE,0xA4AF, +0xA4B0,0xA4B1,0xA4B2,0xA4B3,0xA4B4,0xA4B5,0xA4B6,0xA4B7, +0xA4B8,0xA4B9,0xA4BA,0xA4BB,0xA4BC,0xA4BD,0xA4BE,0xA4BF, +0xA4C0,0xA4C1,0xA4C2,0xA4C3,0xA4C4,0xA4C5,0xA4C6,0xA4C7, +0xA4C8,0xA4C9,0xA4CA,0xA4CB,0xA4CC,0xA4CD,0xA4CE,0xA4CF, +0xA4D0,0xA4D1,0xA4D2,0xA4D3,0xA4D4,0xA4D5,0xA4D6,0xA4D7, +0xA4D8,0xA4D9,0xA4DA,0xA4DB,0xA4DC,0xA4DD,0xA4DE,0xA4DF, +0xA4E0,0xA4E1,0xA4E2,0xA4E3,0xA4E4,0xA4E5,0xA4E6,0xA4E7, +0xA4E8,0xA4E9,0xA4EA,0xA4EB,0xA4EC,0xA4ED,0xA4EE,0xA4EF, +0xA4F0,0xA4F1,0xA4F2,0xA4F3, 0, 0, 0, 0, + 0, 0, 0,0xA961,0xA962,0xA966,0xA967, 0, + 0,0xA5A1,0xA5A2,0xA5A3,0xA5A4,0xA5A5,0xA5A6,0xA5A7, +0xA5A8,0xA5A9,0xA5AA,0xA5AB,0xA5AC,0xA5AD,0xA5AE,0xA5AF, +0xA5B0,0xA5B1,0xA5B2,0xA5B3,0xA5B4,0xA5B5,0xA5B6,0xA5B7, +0xA5B8,0xA5B9,0xA5BA,0xA5BB,0xA5BC,0xA5BD,0xA5BE,0xA5BF, +0xA5C0,0xA5C1,0xA5C2,0xA5C3,0xA5C4,0xA5C5,0xA5C6,0xA5C7, +0xA5C8,0xA5C9,0xA5CA,0xA5CB,0xA5CC,0xA5CD,0xA5CE,0xA5CF, +0xA5D0,0xA5D1,0xA5D2,0xA5D3,0xA5D4,0xA5D5,0xA5D6,0xA5D7, +0xA5D8,0xA5D9,0xA5DA,0xA5DB,0xA5DC,0xA5DD,0xA5DE,0xA5DF, +0xA5E0,0xA5E1,0xA5E2,0xA5E3,0xA5E4,0xA5E5,0xA5E6,0xA5E7, +0xA5E8,0xA5E9,0xA5EA,0xA5EB,0xA5EC,0xA5ED,0xA5EE,0xA5EF, +0xA5F0,0xA5F1,0xA5F2,0xA5F3,0xA5F4,0xA5F5,0xA5F6, 0, + 0, 0, 0, 0,0xA960,0xA963,0xA964, 0, + 0, 0, 0, 0, 0,0xA8C5,0xA8C6,0xA8C7, +0xA8C8,0xA8C9,0xA8CA,0xA8CB,0xA8CC,0xA8CD,0xA8CE,0xA8CF, +0xA8D0,0xA8D1,0xA8D2,0xA8D3,0xA8D4,0xA8D5,0xA8D6,0xA8D7, +0xA8D8,0xA8D9,0xA8DA,0xA8DB,0xA8DC,0xA8DD,0xA8DE,0xA8DF, +0xA8E0,0xA8E1,0xA8E2,0xA8E3,0xA8E4,0xA8E5,0xA8E6,0xA8E7, +0xA8E8,0xA8E9}; + + +static uint16_t tab_uni_gbk4[]={ +0xA2E5,0xA2E6,0xA2E7,0xA2E8,0xA2E9,0xA2EA,0xA2EB,0xA2EC, +0xA2ED,0xA2EE, 0, 0, 0, 0, 0, 0, + 0,0xA95A, 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, 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, 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,0xA949}; + + +static uint16_t tab_uni_gbk5[]={ +0xA94A,0xA94B, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,0xA94C,0xA94D, +0xA94E, 0, 0,0xA94F, 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,0xA950, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +0xA951, 0, 0,0xA952,0xA953, 0, 0,0xA954 +}; + + +static uint16_t tab_uni_gbk6[]={ +0xD2BB,0xB6A1,0x8140,0xC6DF,0x8141,0x8142,0x8143,0xCDF2, +0xD5C9,0xC8FD,0xC9CF,0xCFC2,0xD8A2,0xB2BB,0xD3EB,0x8144, +0xD8A4,0xB3F3,0x8145,0xD7A8,0xC7D2,0xD8A7,0xCAC0,0x8146, +0xC7F0,0xB1FB,0xD2B5,0xB4D4,0xB6AB,0xCBBF,0xD8A9,0x8147, +0x8148,0x8149,0xB6AA,0x814A,0xC1BD,0xD1CF,0x814B,0xC9A5, +0xD8AD,0x814C,0xB8F6,0xD1BE,0xE3DC,0xD6D0,0x814D,0x814E, +0xB7E1,0x814F,0xB4AE,0x8150,0xC1D9,0x8151,0xD8BC,0x8152, +0xCDE8,0xB5A4,0xCEAA,0xD6F7,0x8153,0xC0F6,0xBED9,0xD8AF, +0x8154,0x8155,0x8156,0xC4CB,0x8157,0xBEC3,0x8158,0xD8B1, +0xC3B4,0xD2E5,0x8159,0xD6AE,0xCEDA,0xD5A7,0xBAF5,0xB7A6, +0xC0D6,0x815A,0xC6B9,0xC5D2,0xC7C7,0x815B,0xB9D4,0x815C, +0xB3CB,0xD2D2,0x815D,0x815E,0xD8BF,0xBEC5,0xC6F2,0xD2B2, +0xCFB0,0xCFE7,0x815F,0x8160,0x8161,0x8162,0xCAE9,0x8163, +0x8164,0xD8C0,0x8165,0x8166,0x8167,0x8168,0x8169,0x816A, +0xC2F2,0xC2D2,0x816B,0xC8E9,0x816C,0x816D,0x816E,0x816F, +0x8170,0x8171,0x8172,0x8173,0x8174,0x8175,0xC7AC,0x8176, +0x8177,0x8178,0x8179,0x817A,0x817B,0x817C,0xC1CB,0x817D, +0xD3E8,0xD5F9,0x817E,0xCAC2,0xB6FE,0xD8A1,0xD3DA,0xBFF7, +0x8180,0xD4C6,0xBBA5,0xD8C1,0xCEE5,0xBEAE,0x8181,0x8182, +0xD8A8,0x8183,0xD1C7,0xD0A9,0x8184,0x8185,0x8186,0xD8BD, +0xD9EF,0xCDF6,0xBFBA,0x8187,0xBDBB,0xBAA5,0xD2E0,0xB2FA, +0xBAE0,0xC4B6,0x8188,0xCFED,0xBEA9,0xCDA4,0xC1C1,0x8189, +0x818A,0x818B,0xC7D7,0xD9F1,0x818C,0xD9F4,0x818D,0x818E, +0x818F,0x8190,0xC8CB,0xD8E9,0x8191,0x8192,0x8193,0xD2DA, +0xCAB2,0xC8CA,0xD8EC,0xD8EA,0xD8C6,0xBDF6,0xC6CD,0xB3F0, +0x8194,0xD8EB,0xBDF1,0xBDE9,0x8195,0xC8D4,0xB4D3,0x8196, +0x8197,0xC2D8,0x8198,0xB2D6,0xD7D0,0xCACB,0xCBFB,0xD5CC, +0xB8B6,0xCFC9,0x8199,0x819A,0x819B,0xD9DA,0xD8F0,0xC7AA, +0x819C,0xD8EE,0x819D,0xB4FA,0xC1EE,0xD2D4,0x819E,0x819F, +0xD8ED,0x81A0,0xD2C7,0xD8EF,0xC3C7,0x81A1,0x81A2,0x81A3, +0xD1F6,0x81A4,0xD6D9,0xD8F2,0x81A5,0xD8F5,0xBCFE,0xBCDB, +0x81A6,0x81A7,0x81A8,0xC8CE,0x81A9,0xB7DD,0x81AA,0xB7C2, +0x81AB,0xC6F3,0x81AC,0x81AD,0x81AE,0x81AF,0x81B0,0x81B1, +0x81B2,0xD8F8,0xD2C1,0x81B3,0x81B4,0xCEE9,0xBCBF,0xB7FC, +0xB7A5,0xD0DD,0x81B5,0x81B6,0x81B7,0x81B8,0x81B9,0xD6DA, +0xD3C5,0xBBEF,0xBBE1,0xD8F1,0x81BA,0x81BB,0xC9A1,0xCEB0, +0xB4AB,0x81BC,0xD8F3,0x81BD,0xC9CB,0xD8F6,0xC2D7,0xD8F7, +0x81BE,0x81BF,0xCEB1,0xD8F9,0x81C0,0x81C1,0x81C2,0xB2AE, +0xB9C0,0x81C3,0xD9A3,0x81C4,0xB0E9,0x81C5,0xC1E6,0x81C6, +0xC9EC,0x81C7,0xCBC5,0x81C8,0xCBC6,0xD9A4,0x81C9,0x81CA, +0x81CB,0x81CC,0x81CD,0xB5E8,0x81CE,0x81CF,0xB5AB,0x81D0, +0x81D1,0x81D2,0x81D3,0x81D4,0x81D5,0xCEBB,0xB5CD,0xD7A1, +0xD7F4,0xD3D3,0x81D6,0xCCE5,0x81D7,0xBACE,0x81D8,0xD9A2, +0xD9DC,0xD3E0,0xD8FD,0xB7F0,0xD7F7,0xD8FE,0xD8FA,0xD9A1, +0xC4E3,0x81D9,0x81DA,0xD3B6,0xD8F4,0xD9DD,0x81DB,0xD8FB, +0x81DC,0xC5E5,0x81DD,0x81DE,0xC0D0,0x81DF,0x81E0,0xD1F0, +0xB0DB,0x81E1,0x81E2,0xBCD1,0xD9A6,0x81E3,0xD9A5,0x81E4, +0x81E5,0x81E6,0x81E7,0xD9AC,0xD9AE,0x81E8,0xD9AB,0xCAB9, +0x81E9,0x81EA,0x81EB,0xD9A9,0xD6B6,0x81EC,0x81ED,0x81EE, +0xB3DE,0xD9A8,0x81EF,0xC0FD,0x81F0,0xCACC,0x81F1,0xD9AA, +0x81F2,0xD9A7,0x81F3,0x81F4,0xD9B0,0x81F5,0x81F6,0xB6B1, +0x81F7,0x81F8,0x81F9,0xB9A9,0x81FA,0xD2C0,0x81FB,0x81FC, +0xCFC0,0x81FD,0x81FE,0xC2C2,0x8240,0xBDC4,0xD5EC,0xB2E0, +0xC7C8,0xBFEB,0xD9AD,0x8241,0xD9AF,0x8242,0xCEEA,0xBAEE, +0x8243,0x8244,0x8245,0x8246,0x8247,0xC7D6,0x8248,0x8249, +0x824A,0x824B,0x824C,0x824D,0x824E,0x824F,0x8250,0xB1E3, +0x8251,0x8252,0x8253,0xB4D9,0xB6ED,0xD9B4,0x8254,0x8255, +0x8256,0x8257,0xBFA1,0x8258,0x8259,0x825A,0xD9DE,0xC7CE, +0xC0FE,0xD9B8,0x825B,0x825C,0x825D,0x825E,0x825F,0xCBD7, +0xB7FD,0x8260,0xD9B5,0x8261,0xD9B7,0xB1A3,0xD3E1,0xD9B9, +0x8262,0xD0C5,0x8263,0xD9B6,0x8264,0x8265,0xD9B1,0x8266, +0xD9B2,0xC1A9,0xD9B3,0x8267,0x8268,0xBCF3,0xD0DE,0xB8A9, +0x8269,0xBEE3,0x826A,0xD9BD,0x826B,0x826C,0x826D,0x826E, +0xD9BA,0x826F,0xB0B3,0x8270,0x8271,0x8272,0xD9C2,0x8273, +0x8274,0x8275,0x8276,0x8277,0x8278,0x8279,0x827A,0x827B, +0x827C,0x827D,0x827E,0x8280,0xD9C4,0xB1B6,0x8281,0xD9BF, +0x8282,0x8283,0xB5B9,0x8284,0xBEF3,0x8285,0x8286,0x8287, +0xCCC8,0xBAF2,0xD2D0,0x8288,0xD9C3,0x8289,0x828A,0xBDE8, +0x828B,0xB3AB,0x828C,0x828D,0x828E,0xD9C5,0xBEEB,0x828F, +0xD9C6,0xD9BB,0xC4DF,0x8290,0xD9BE,0xD9C1,0xD9C0,0x8291, +0x8292,0x8293,0x8294,0x8295,0x8296,0x8297,0x8298,0x8299, +0x829A,0x829B,0xD5AE,0x829C,0xD6B5,0x829D,0xC7E3,0x829E, +0x829F,0x82A0,0x82A1,0xD9C8,0x82A2,0x82A3,0x82A4,0xBCD9, +0xD9CA,0x82A5,0x82A6,0x82A7,0xD9BC,0x82A8,0xD9CB,0xC6AB, +0x82A9,0x82AA,0x82AB,0x82AC,0x82AD,0xD9C9,0x82AE,0x82AF, +0x82B0,0x82B1,0xD7F6,0x82B2,0xCDA3,0x82B3,0x82B4,0x82B5, +0x82B6,0x82B7,0x82B8,0x82B9,0x82BA,0xBDA1,0x82BB,0x82BC, +0x82BD,0x82BE,0x82BF,0x82C0,0xD9CC,0x82C1,0x82C2,0x82C3, +0x82C4,0x82C5,0x82C6,0x82C7,0x82C8,0x82C9,0xC5BC,0xCDB5, +0x82CA,0x82CB,0x82CC,0xD9CD,0x82CD,0x82CE,0xD9C7,0xB3A5, +0xBFFE,0x82CF,0x82D0,0x82D1,0x82D2,0xB8B5,0x82D3,0x82D4, +0xC0FC,0x82D5,0x82D6,0x82D7,0x82D8,0xB0F8,0x82D9,0x82DA, +0x82DB,0x82DC,0x82DD,0x82DE,0x82DF,0x82E0,0x82E1,0x82E2, +0x82E3,0x82E4,0x82E5,0x82E6,0x82E7,0x82E8,0x82E9,0x82EA, +0x82EB,0x82EC,0x82ED,0xB4F6,0x82EE,0xD9CE,0x82EF,0xD9CF, +0xB4A2,0xD9D0,0x82F0,0x82F1,0xB4DF,0x82F2,0x82F3,0x82F4, +0x82F5,0x82F6,0xB0C1,0x82F7,0x82F8,0x82F9,0x82FA,0x82FB, +0x82FC,0x82FD,0xD9D1,0xC9B5,0x82FE,0x8340,0x8341,0x8342, +0x8343,0x8344,0x8345,0x8346,0x8347,0x8348,0x8349,0x834A, +0x834B,0x834C,0x834D,0x834E,0x834F,0x8350,0x8351,0xCFF1, +0x8352,0x8353,0x8354,0x8355,0x8356,0x8357,0xD9D2,0x8358, +0x8359,0x835A,0xC1C5,0x835B,0x835C,0x835D,0x835E,0x835F, +0x8360,0x8361,0x8362,0x8363,0x8364,0x8365,0xD9D6,0xC9AE, +0x8366,0x8367,0x8368,0x8369,0xD9D5,0xD9D4,0xD9D7,0x836A, +0x836B,0x836C,0x836D,0xCBDB,0x836E,0xBDA9,0x836F,0x8370, +0x8371,0x8372,0x8373,0xC6A7,0x8374,0x8375,0x8376,0x8377, +0x8378,0x8379,0x837A,0x837B,0x837C,0x837D,0xD9D3,0xD9D8, +0x837E,0x8380,0x8381,0xD9D9,0x8382,0x8383,0x8384,0x8385, +0x8386,0x8387,0xC8E5,0x8388,0x8389,0x838A,0x838B,0x838C, +0x838D,0x838E,0x838F,0x8390,0x8391,0x8392,0x8393,0x8394, +0x8395,0xC0DC,0x8396,0x8397,0x8398,0x8399,0x839A,0x839B, +0x839C,0x839D,0x839E,0x839F,0x83A0,0x83A1,0x83A2,0x83A3, +0x83A4,0x83A5,0x83A6,0x83A7,0x83A8,0x83A9,0x83AA,0x83AB, +0x83AC,0x83AD,0x83AE,0x83AF,0x83B0,0x83B1,0x83B2,0xB6F9, +0xD8A3,0xD4CA,0x83B3,0xD4AA,0xD0D6,0xB3E4,0xD5D7,0x83B4, +0xCFC8,0xB9E2,0x83B5,0xBFCB,0x83B6,0xC3E2,0x83B7,0x83B8, +0x83B9,0xB6D2,0x83BA,0x83BB,0xCDC3,0xD9EE,0xD9F0,0x83BC, +0x83BD,0x83BE,0xB5B3,0x83BF,0xB6B5,0x83C0,0x83C1,0x83C2, +0x83C3,0x83C4,0xBEA4,0x83C5,0x83C6,0xC8EB,0x83C7,0x83C8, +0xC8AB,0x83C9,0x83CA,0xB0CB,0xB9AB,0xC1F9,0xD9E2,0x83CB, +0xC0BC,0xB9B2,0x83CC,0xB9D8,0xD0CB,0xB1F8,0xC6E4,0xBEDF, +0xB5E4,0xD7C8,0x83CD,0xD1F8,0xBCE6,0xCADE,0x83CE,0x83CF, +0xBCBD,0xD9E6,0xD8E7,0x83D0,0x83D1,0xC4DA,0x83D2,0x83D3, +0xB8D4,0xC8BD,0x83D4,0x83D5,0xB2E1,0xD4D9,0x83D6,0x83D7, +0x83D8,0x83D9,0xC3B0,0x83DA,0x83DB,0xC3E1,0xDAA2,0xC8DF, +0x83DC,0xD0B4,0x83DD,0xBEFC,0xC5A9,0x83DE,0x83DF,0x83E0, +0xB9DA,0x83E1,0xDAA3,0x83E2,0xD4A9,0xDAA4,0x83E3,0x83E4, +0x83E5,0x83E6,0x83E7,0xD9FB,0xB6AC,0x83E8,0x83E9,0xB7EB, +0xB1F9,0xD9FC,0xB3E5,0xBEF6,0x83EA,0xBFF6,0xD2B1,0xC0E4, +0x83EB,0x83EC,0x83ED,0xB6B3,0xD9FE,0xD9FD,0x83EE,0x83EF, +0xBEBB,0x83F0,0x83F1,0x83F2,0xC6E0,0x83F3,0xD7BC,0xDAA1, +0x83F4,0xC1B9,0x83F5,0xB5F2,0xC1E8,0x83F6,0x83F7,0xBCF5, +0x83F8,0xB4D5,0x83F9,0x83FA,0x83FB,0x83FC,0x83FD,0x83FE, +0x8440,0x8441,0x8442,0xC1DD,0x8443,0xC4FD,0x8444,0x8445, +0xBCB8,0xB7B2,0x8446,0x8447,0xB7EF,0x8448,0x8449,0x844A, +0x844B,0x844C,0x844D,0xD9EC,0x844E,0xC6BE,0x844F,0xBFAD, +0xBBCB,0x8450,0x8451,0xB5CA,0x8452,0xDBC9,0xD0D7,0x8453, +0xCDB9,0xB0BC,0xB3F6,0xBBF7,0xDBCA,0xBAAF,0x8454,0xD4E4, +0xB5B6,0xB5F3,0xD8D6,0xC8D0,0x8455,0x8456,0xB7D6,0xC7D0, +0xD8D7,0x8457,0xBFAF,0x8458,0x8459,0xDBBB,0xD8D8,0x845A, +0x845B,0xD0CC,0xBBAE,0x845C,0x845D,0x845E,0xEBBE,0xC1D0, +0xC1F5,0xD4F2,0xB8D5,0xB4B4,0x845F,0xB3F5,0x8460,0x8461, +0xC9BE,0x8462,0x8463,0x8464,0xC5D0,0x8465,0x8466,0x8467, +0xC5D9,0xC0FB,0x8468,0xB1F0,0x8469,0xD8D9,0xB9CE,0x846A, +0xB5BD,0x846B,0x846C,0xD8DA,0x846D,0x846E,0xD6C6,0xCBA2, +0xC8AF,0xC9B2,0xB4CC,0xBFCC,0x846F,0xB9F4,0x8470,0xD8DB, +0xD8DC,0xB6E7,0xBCC1,0xCCEA,0x8471,0x8472,0x8473,0x8474, +0x8475,0x8476,0xCFF7,0x8477,0xD8DD,0xC7B0,0x8478,0x8479, +0xB9D0,0xBDA3,0x847A,0x847B,0xCCDE,0x847C,0xC6CA,0x847D, +0x847E,0x8480,0x8481,0x8482,0xD8E0,0x8483,0xD8DE,0x8484, +0x8485,0xD8DF,0x8486,0x8487,0x8488,0xB0FE,0x8489,0xBEE7, +0x848A,0xCAA3,0xBCF4,0x848B,0x848C,0x848D,0x848E,0xB8B1, +0x848F,0x8490,0xB8EE,0x8491,0x8492,0x8493,0x8494,0x8495, +0x8496,0x8497,0x8498,0x8499,0x849A,0xD8E2,0x849B,0xBDCB, +0x849C,0xD8E4,0xD8E3,0x849D,0x849E,0x849F,0x84A0,0x84A1, +0xC5FC,0x84A2,0x84A3,0x84A4,0x84A5,0x84A6,0x84A7,0x84A8, +0xD8E5,0x84A9,0x84AA,0xD8E6,0x84AB,0x84AC,0x84AD,0x84AE, +0x84AF,0x84B0,0x84B1,0xC1A6,0x84B2,0xC8B0,0xB0EC,0xB9A6, +0xBCD3,0xCEF1,0xDBBD,0xC1D3,0x84B3,0x84B4,0x84B5,0x84B6, +0xB6AF,0xD6FA,0xC5AC,0xBDD9,0xDBBE,0xDBBF,0x84B7,0x84B8, +0x84B9,0xC0F8,0xBEA2,0xC0CD,0x84BA,0x84BB,0x84BC,0x84BD, +0x84BE,0x84BF,0x84C0,0x84C1,0x84C2,0x84C3,0xDBC0,0xCAC6, +0x84C4,0x84C5,0x84C6,0xB2AA,0x84C7,0x84C8,0x84C9,0xD3C2, +0x84CA,0xC3E3,0x84CB,0xD1AB,0x84CC,0x84CD,0x84CE,0x84CF, +0xDBC2,0x84D0,0xC0D5,0x84D1,0x84D2,0x84D3,0xDBC3,0x84D4, +0xBFB1,0x84D5,0x84D6,0x84D7,0x84D8,0x84D9,0x84DA,0xC4BC, +0x84DB,0x84DC,0x84DD,0x84DE,0xC7DA,0x84DF,0x84E0,0x84E1, +0x84E2,0x84E3,0x84E4,0x84E5,0x84E6,0x84E7,0x84E8,0x84E9, +0xDBC4,0x84EA,0x84EB,0x84EC,0x84ED,0x84EE,0x84EF,0x84F0, +0x84F1,0xD9E8,0xC9D7,0x84F2,0x84F3,0x84F4,0xB9B4,0xCEF0, +0xD4C8,0x84F5,0x84F6,0x84F7,0x84F8,0xB0FC,0xB4D2,0x84F9, +0xD0D9,0x84FA,0x84FB,0x84FC,0x84FD,0xD9E9,0x84FE,0xDECB, +0xD9EB,0x8540,0x8541,0x8542,0x8543,0xD8B0,0xBBAF,0xB1B1, +0x8544,0xB3D7,0xD8CE,0x8545,0x8546,0xD4D1,0x8547,0x8548, +0xBDB3,0xBFEF,0x8549,0xCFBB,0x854A,0x854B,0xD8D0,0x854C, +0x854D,0x854E,0xB7CB,0x854F,0x8550,0x8551,0xD8D1,0x8552, +0x8553,0x8554,0x8555,0x8556,0x8557,0x8558,0x8559,0x855A, +0x855B,0xC6A5,0xC7F8,0xD2BD,0x855C,0x855D,0xD8D2,0xC4E4, +0x855E,0xCAAE,0x855F,0xC7A7,0x8560,0xD8A6,0x8561,0xC9FD, +0xCEE7,0xBBDC,0xB0EB,0x8562,0x8563,0x8564,0xBBAA,0xD0AD, +0x8565,0xB1B0,0xD7E4,0xD7BF,0x8566,0xB5A5,0xC2F4,0xC4CF, +0x8567,0x8568,0xB2A9,0x8569,0xB2B7,0x856A,0xB1E5,0xDFB2, +0xD5BC,0xBFA8,0xC2AC,0xD8D5,0xC2B1,0x856B,0xD8D4,0xCED4, +0x856C,0xDAE0,0x856D,0xCEC0,0x856E,0x856F,0xD8B4,0xC3AE, +0xD3A1,0xCEA3,0x8570,0xBCB4,0xC8B4,0xC2D1,0x8571,0xBEED, +0xD0B6,0x8572,0xDAE1,0x8573,0x8574,0x8575,0x8576,0xC7E4, +0x8577,0x8578,0xB3A7,0x8579,0xB6F2,0xCCFC,0xC0FA,0x857A, +0x857B,0xC0F7,0x857C,0xD1B9,0xD1E1,0xD8C7,0x857D,0x857E, +0x8580,0x8581,0x8582,0x8583,0x8584,0xB2DE,0x8585,0x8586, +0xC0E5,0x8587,0xBAF1,0x8588,0x8589,0xD8C8,0x858A,0xD4AD, +0x858B,0x858C,0xCFE1,0xD8C9,0x858D,0xD8CA,0xCFC3,0x858E, +0xB3F8,0xBEC7,0x858F,0x8590,0x8591,0x8592,0xD8CB,0x8593, +0x8594,0x8595,0x8596,0x8597,0x8598,0x8599,0xDBCC,0x859A, +0x859B,0x859C,0x859D,0xC8A5,0x859E,0x859F,0x85A0,0xCFD8, +0x85A1,0xC8FE,0xB2CE,0x85A2,0x85A3,0x85A4,0x85A5,0x85A6, +0xD3D6,0xB2E6,0xBCB0,0xD3D1,0xCBAB,0xB7B4,0x85A7,0x85A8, +0x85A9,0xB7A2,0x85AA,0x85AB,0xCAE5,0x85AC,0xC8A1,0xCADC, +0xB1E4,0xD0F0,0x85AD,0xC5D1,0x85AE,0x85AF,0x85B0,0xDBC5, +0xB5FE,0x85B1,0x85B2,0xBFDA,0xB9C5,0xBEE4,0xC1ED,0x85B3, +0xDFB6,0xDFB5,0xD6BB,0xBDD0,0xD5D9,0xB0C8,0xB6A3,0xBFC9, +0xCCA8,0xDFB3,0xCAB7,0xD3D2,0x85B4,0xD8CF,0xD2B6,0xBAC5, +0xCBBE,0xCCBE,0x85B5,0xDFB7,0xB5F0,0xDFB4,0x85B6,0x85B7, +0x85B8,0xD3F5,0x85B9,0xB3D4,0xB8F7,0x85BA,0xDFBA,0x85BB, +0xBACF,0xBCAA,0xB5F5,0x85BC,0xCDAC,0xC3FB,0xBAF3,0xC0F4, +0xCDC2,0xCFF2,0xDFB8,0xCFC5,0x85BD,0xC2C0,0xDFB9,0xC2F0, +0x85BE,0x85BF,0x85C0,0xBEFD,0x85C1,0xC1DF,0xCDCC,0xD2F7, +0xB7CD,0xDFC1,0x85C2,0xDFC4,0x85C3,0x85C4,0xB7F1,0xB0C9, +0xB6D6,0xB7D4,0x85C5,0xBAAC,0xCCFD,0xBFD4,0xCBB1,0xC6F4, +0x85C6,0xD6A8,0xDFC5,0x85C7,0xCEE2,0xB3B3,0x85C8,0x85C9, +0xCEFC,0xB4B5,0x85CA,0xCEC7,0xBAF0,0x85CB,0xCEE1,0x85CC, +0xD1BD,0x85CD,0x85CE,0xDFC0,0x85CF,0x85D0,0xB4F4,0x85D1, +0xB3CA,0x85D2,0xB8E6,0xDFBB,0x85D3,0x85D4,0x85D5,0x85D6, +0xC4C5,0x85D7,0xDFBC,0xDFBD,0xDFBE,0xC5BB,0xDFBF,0xDFC2, +0xD4B1,0xDFC3,0x85D8,0xC7BA,0xCED8,0x85D9,0x85DA,0x85DB, +0x85DC,0x85DD,0xC4D8,0x85DE,0xDFCA,0x85DF,0xDFCF,0x85E0, +0xD6DC,0x85E1,0x85E2,0x85E3,0x85E4,0x85E5,0x85E6,0x85E7, +0x85E8,0xDFC9,0xDFDA,0xCEB6,0x85E9,0xBAC7,0xDFCE,0xDFC8, +0xC5DE,0x85EA,0x85EB,0xC9EB,0xBAF4,0xC3FC,0x85EC,0x85ED, +0xBED7,0x85EE,0xDFC6,0x85EF,0xDFCD,0x85F0,0xC5D8,0x85F1, +0x85F2,0x85F3,0x85F4,0xD5A6,0xBACD,0x85F5,0xBECC,0xD3BD, +0xB8C0,0x85F6,0xD6E4,0x85F7,0xDFC7,0xB9BE,0xBFA7,0x85F8, +0x85F9,0xC1FC,0xDFCB,0xDFCC,0x85FA,0xDFD0,0x85FB,0x85FC, +0x85FD,0x85FE,0x8640,0xDFDB,0xDFE5,0x8641,0xDFD7,0xDFD6, +0xD7C9,0xDFE3,0xDFE4,0xE5EB,0xD2A7,0xDFD2,0x8642,0xBFA9, +0x8643,0xD4DB,0x8644,0xBFC8,0xDFD4,0x8645,0x8646,0x8647, +0xCFCC,0x8648,0x8649,0xDFDD,0x864A,0xD1CA,0x864B,0xDFDE, +0xB0A7,0xC6B7,0xDFD3,0x864C,0xBAE5,0x864D,0xB6DF,0xCDDB, +0xB9FE,0xD4D5,0x864E,0x864F,0xDFDF,0xCFEC,0xB0A5,0xDFE7, +0xDFD1,0xD1C6,0xDFD5,0xDFD8,0xDFD9,0xDFDC,0x8650,0xBBA9, +0x8651,0xDFE0,0xDFE1,0x8652,0xDFE2,0xDFE6,0xDFE8,0xD3B4, +0x8653,0x8654,0x8655,0x8656,0x8657,0xB8E7,0xC5B6,0xDFEA, +0xC9DA,0xC1A8,0xC4C4,0x8658,0x8659,0xBFDE,0xCFF8,0x865A, +0x865B,0x865C,0xD5DC,0xDFEE,0x865D,0x865E,0x865F,0x8660, +0x8661,0x8662,0xB2B8,0x8663,0xBADF,0xDFEC,0x8664,0xDBC1, +0x8665,0xD1E4,0x8666,0x8667,0x8668,0x8669,0xCBF4,0xB4BD, +0x866A,0xB0A6,0x866B,0x866C,0x866D,0x866E,0x866F,0xDFF1, +0xCCC6,0xDFF2,0x8670,0x8671,0xDFED,0x8672,0x8673,0x8674, +0x8675,0x8676,0x8677,0xDFE9,0x8678,0x8679,0x867A,0x867B, +0xDFEB,0x867C,0xDFEF,0xDFF0,0xBBBD,0x867D,0x867E,0xDFF3, +0x8680,0x8681,0xDFF4,0x8682,0xBBA3,0x8683,0xCADB,0xCEA8, +0xE0A7,0xB3AA,0x8684,0xE0A6,0x8685,0x8686,0x8687,0xE0A1, +0x8688,0x8689,0x868A,0x868B,0xDFFE,0x868C,0xCDD9,0xDFFC, +0x868D,0xDFFA,0x868E,0xBFD0,0xD7C4,0x868F,0xC9CC,0x8690, +0x8691,0xDFF8,0xB0A1,0x8692,0x8693,0x8694,0x8695,0x8696, +0xDFFD,0x8697,0x8698,0x8699,0x869A,0xDFFB,0xE0A2,0x869B, +0x869C,0x869D,0x869E,0x869F,0xE0A8,0x86A0,0x86A1,0x86A2, +0x86A3,0xB7C8,0x86A4,0x86A5,0xC6A1,0xC9B6,0xC0B2,0xDFF5, +0x86A6,0x86A7,0xC5BE,0x86A8,0xD8C4,0xDFF9,0xC4F6,0x86A9, +0x86AA,0x86AB,0x86AC,0x86AD,0x86AE,0xE0A3,0xE0A4,0xE0A5, +0xD0A5,0x86AF,0x86B0,0xE0B4,0xCCE4,0x86B1,0xE0B1,0x86B2, +0xBFA6,0xE0AF,0xCEB9,0xE0AB,0xC9C6,0x86B3,0x86B4,0xC0AE, +0xE0AE,0xBAED,0xBAB0,0xE0A9,0x86B5,0x86B6,0x86B7,0xDFF6, +0x86B8,0xE0B3,0x86B9,0x86BA,0xE0B8,0x86BB,0x86BC,0x86BD, +0xB4AD,0xE0B9,0x86BE,0x86BF,0xCFB2,0xBAC8,0x86C0,0xE0B0, +0x86C1,0x86C2,0x86C3,0x86C4,0x86C5,0x86C6,0x86C7,0xD0FA, +0x86C8,0x86C9,0x86CA,0x86CB,0x86CC,0x86CD,0x86CE,0x86CF, +0x86D0,0xE0AC,0x86D1,0xD4FB,0x86D2,0xDFF7,0x86D3,0xC5E7, +0x86D4,0xE0AD,0x86D5,0xD3F7,0x86D6,0xE0B6,0xE0B7,0x86D7, +0x86D8,0x86D9,0x86DA,0x86DB,0xE0C4,0xD0E1,0x86DC,0x86DD, +0x86DE,0xE0BC,0x86DF,0x86E0,0xE0C9,0xE0CA,0x86E1,0x86E2, +0x86E3,0xE0BE,0xE0AA,0xC9A4,0xE0C1,0x86E4,0xE0B2,0x86E5, +0x86E6,0x86E7,0x86E8,0x86E9,0xCAC8,0xE0C3,0x86EA,0xE0B5, +0x86EB,0xCECB,0x86EC,0xCBC3,0xE0CD,0xE0C6,0xE0C2,0x86ED, +0xE0CB,0x86EE,0xE0BA,0xE0BF,0xE0C0,0x86EF,0x86F0,0xE0C5, +0x86F1,0x86F2,0xE0C7,0xE0C8,0x86F3,0xE0CC,0x86F4,0xE0BB, +0x86F5,0x86F6,0x86F7,0x86F8,0x86F9,0xCBD4,0xE0D5,0x86FA, +0xE0D6,0xE0D2,0x86FB,0x86FC,0x86FD,0x86FE,0x8740,0x8741, +0xE0D0,0xBCCE,0x8742,0x8743,0xE0D1,0x8744,0xB8C2,0xD8C5, +0x8745,0x8746,0x8747,0x8748,0x8749,0x874A,0x874B,0x874C, +0xD0EA,0x874D,0x874E,0xC2EF,0x874F,0x8750,0xE0CF,0xE0BD, +0x8751,0x8752,0x8753,0xE0D4,0xE0D3,0x8754,0x8755,0xE0D7, +0x8756,0x8757,0x8758,0x8759,0xE0DC,0xE0D8,0x875A,0x875B, +0x875C,0xD6F6,0xB3B0,0x875D,0xD7EC,0x875E,0xCBBB,0x875F, +0x8760,0xE0DA,0x8761,0xCEFB,0x8762,0x8763,0x8764,0xBAD9, +0x8765,0x8766,0x8767,0x8768,0x8769,0x876A,0x876B,0x876C, +0x876D,0x876E,0x876F,0x8770,0xE0E1,0xE0DD,0xD2AD,0x8771, +0x8772,0x8773,0x8774,0x8775,0xE0E2,0x8776,0x8777,0xE0DB, +0xE0D9,0xE0DF,0x8778,0x8779,0xE0E0,0x877A,0x877B,0x877C, +0x877D,0x877E,0xE0DE,0x8780,0xE0E4,0x8781,0x8782,0x8783, +0xC6F7,0xD8AC,0xD4EB,0xE0E6,0xCAC9,0x8784,0x8785,0x8786, +0x8787,0xE0E5,0x8788,0x8789,0x878A,0x878B,0xB8C1,0x878C, +0x878D,0x878E,0x878F,0xE0E7,0xE0E8,0x8790,0x8791,0x8792, +0x8793,0x8794,0x8795,0x8796,0x8797,0xE0E9,0xE0E3,0x8798, +0x8799,0x879A,0x879B,0x879C,0x879D,0x879E,0xBABF,0xCCE7, +0x879F,0x87A0,0x87A1,0xE0EA,0x87A2,0x87A3,0x87A4,0x87A5, +0x87A6,0x87A7,0x87A8,0x87A9,0x87AA,0x87AB,0x87AC,0x87AD, +0x87AE,0x87AF,0x87B0,0xCFF9,0x87B1,0x87B2,0x87B3,0x87B4, +0x87B5,0x87B6,0x87B7,0x87B8,0x87B9,0x87BA,0x87BB,0xE0EB, +0x87BC,0x87BD,0x87BE,0x87BF,0x87C0,0x87C1,0x87C2,0xC8C2, +0x87C3,0x87C4,0x87C5,0x87C6,0xBDC0,0x87C7,0x87C8,0x87C9, +0x87CA,0x87CB,0x87CC,0x87CD,0x87CE,0x87CF,0x87D0,0x87D1, +0x87D2,0x87D3,0xC4D2,0x87D4,0x87D5,0x87D6,0x87D7,0x87D8, +0x87D9,0x87DA,0x87DB,0x87DC,0xE0EC,0x87DD,0x87DE,0xE0ED, +0x87DF,0x87E0,0xC7F4,0xCBC4,0x87E1,0xE0EE,0xBBD8,0xD8B6, +0xD2F2,0xE0EF,0xCDC5,0x87E2,0xB6DA,0x87E3,0x87E4,0x87E5, +0x87E6,0x87E7,0x87E8,0xE0F1,0x87E9,0xD4B0,0x87EA,0x87EB, +0xC0A7,0xB4D1,0x87EC,0x87ED,0xCEA7,0xE0F0,0x87EE,0x87EF, +0x87F0,0xE0F2,0xB9CC,0x87F1,0x87F2,0xB9FA,0xCDBC,0xE0F3, +0x87F3,0x87F4,0x87F5,0xC6D4,0xE0F4,0x87F6,0xD4B2,0x87F7, +0xC8A6,0xE0F6,0xE0F5,0x87F8,0x87F9,0x87FA,0x87FB,0x87FC, +0x87FD,0x87FE,0x8840,0x8841,0x8842,0x8843,0x8844,0x8845, +0x8846,0x8847,0x8848,0x8849,0xE0F7,0x884A,0x884B,0xCDC1, +0x884C,0x884D,0x884E,0xCAA5,0x884F,0x8850,0x8851,0x8852, +0xD4DA,0xDBD7,0xDBD9,0x8853,0xDBD8,0xB9E7,0xDBDC,0xDBDD, +0xB5D8,0x8854,0x8855,0xDBDA,0x8856,0x8857,0x8858,0x8859, +0x885A,0xDBDB,0xB3A1,0xDBDF,0x885B,0x885C,0xBBF8,0x885D, +0xD6B7,0x885E,0xDBE0,0x885F,0x8860,0x8861,0x8862,0xBEF9, +0x8863,0x8864,0xB7BB,0x8865,0xDBD0,0xCCAE,0xBFB2,0xBBB5, +0xD7F8,0xBFD3,0x8866,0x8867,0x8868,0x8869,0x886A,0xBFE9, +0x886B,0x886C,0xBCE1,0xCCB3,0xDBDE,0xB0D3,0xCEEB,0xB7D8, +0xD7B9,0xC6C2,0x886D,0x886E,0xC0A4,0x886F,0xCCB9,0x8870, +0xDBE7,0xDBE1,0xC6BA,0xDBE3,0x8871,0xDBE8,0x8872,0xC5F7, +0x8873,0x8874,0x8875,0xDBEA,0x8876,0x8877,0xDBE9,0xBFC0, +0x8878,0x8879,0x887A,0xDBE6,0xDBE5,0x887B,0x887C,0x887D, +0x887E,0x8880,0xB4B9,0xC0AC,0xC2A2,0xDBE2,0xDBE4,0x8881, +0x8882,0x8883,0x8884,0xD0CD,0xDBED,0x8885,0x8886,0x8887, +0x8888,0x8889,0xC0DD,0xDBF2,0x888A,0x888B,0x888C,0x888D, +0x888E,0x888F,0x8890,0xB6E2,0x8891,0x8892,0x8893,0x8894, +0xDBF3,0xDBD2,0xB9B8,0xD4AB,0xDBEC,0x8895,0xBFD1,0xDBF0, +0x8896,0xDBD1,0x8897,0xB5E6,0x8898,0xDBEB,0xBFE5,0x8899, +0x889A,0x889B,0xDBEE,0x889C,0xDBF1,0x889D,0x889E,0x889F, +0xDBF9,0x88A0,0x88A1,0x88A2,0x88A3,0x88A4,0x88A5,0x88A6, +0x88A7,0x88A8,0xB9A1,0xB0A3,0x88A9,0x88AA,0x88AB,0x88AC, +0x88AD,0x88AE,0x88AF,0xC2F1,0x88B0,0x88B1,0xB3C7,0xDBEF, +0x88B2,0x88B3,0xDBF8,0x88B4,0xC6D2,0xDBF4,0x88B5,0x88B6, +0xDBF5,0xDBF7,0xDBF6,0x88B7,0x88B8,0xDBFE,0x88B9,0xD3F2, +0xB2BA,0x88BA,0x88BB,0x88BC,0xDBFD,0x88BD,0x88BE,0x88BF, +0x88C0,0x88C1,0x88C2,0x88C3,0x88C4,0xDCA4,0x88C5,0xDBFB, +0x88C6,0x88C7,0x88C8,0x88C9,0xDBFA,0x88CA,0x88CB,0x88CC, +0xDBFC,0xC5E0,0xBBF9,0x88CD,0x88CE,0xDCA3,0x88CF,0x88D0, +0xDCA5,0x88D1,0xCCC3,0x88D2,0x88D3,0x88D4,0xB6D1,0xDDC0, +0x88D5,0x88D6,0x88D7,0xDCA1,0x88D8,0xDCA2,0x88D9,0x88DA, +0x88DB,0xC7B5,0x88DC,0x88DD,0x88DE,0xB6E9,0x88DF,0x88E0, +0x88E1,0xDCA7,0x88E2,0x88E3,0x88E4,0x88E5,0xDCA6,0x88E6, +0xDCA9,0xB1A4,0x88E7,0x88E8,0xB5CC,0x88E9,0x88EA,0x88EB, +0x88EC,0x88ED,0xBFB0,0x88EE,0x88EF,0x88F0,0x88F1,0x88F2, +0xD1DF,0x88F3,0x88F4,0x88F5,0x88F6,0xB6C2,0x88F7,0x88F8, +0x88F9,0x88FA,0x88FB,0x88FC,0x88FD,0x88FE,0x8940,0x8941, +0x8942,0x8943,0x8944,0x8945,0xDCA8,0x8946,0x8947,0x8948, +0x8949,0x894A,0x894B,0x894C,0xCBFA,0xEBF3,0x894D,0x894E, +0x894F,0xCBDC,0x8950,0x8951,0xCBFE,0x8952,0x8953,0x8954, +0xCCC1,0x8955,0x8956,0x8957,0x8958,0x8959,0xC8FB,0x895A, +0x895B,0x895C,0x895D,0x895E,0x895F,0xDCAA,0x8960,0x8961, +0x8962,0x8963,0x8964,0xCCEE,0xDCAB,0x8965,0x8966,0x8967, +0x8968,0x8969,0x896A,0x896B,0x896C,0x896D,0x896E,0x896F, +0x8970,0x8971,0x8972,0x8973,0x8974,0x8975,0xDBD3,0x8976, +0xDCAF,0xDCAC,0x8977,0xBEB3,0x8978,0xCAFB,0x8979,0x897A, +0x897B,0xDCAD,0x897C,0x897D,0x897E,0x8980,0x8981,0x8982, +0x8983,0x8984,0xC9CA,0xC4B9,0x8985,0x8986,0x8987,0x8988, +0x8989,0xC7BD,0xDCAE,0x898A,0x898B,0x898C,0xD4F6,0xD0E6, +0x898D,0x898E,0x898F,0x8990,0x8991,0x8992,0x8993,0x8994, +0xC4AB,0xB6D5,0x8995,0x8996,0x8997,0x8998,0x8999,0x899A, +0x899B,0x899C,0x899D,0x899E,0x899F,0x89A0,0x89A1,0x89A2, +0x89A3,0x89A4,0x89A5,0x89A6,0xDBD4,0x89A7,0x89A8,0x89A9, +0x89AA,0xB1DA,0x89AB,0x89AC,0x89AD,0xDBD5,0x89AE,0x89AF, +0x89B0,0x89B1,0x89B2,0x89B3,0x89B4,0x89B5,0x89B6,0x89B7, +0x89B8,0xDBD6,0x89B9,0x89BA,0x89BB,0xBABE,0x89BC,0x89BD, +0x89BE,0x89BF,0x89C0,0x89C1,0x89C2,0x89C3,0x89C4,0x89C5, +0x89C6,0x89C7,0x89C8,0x89C9,0xC8C0,0x89CA,0x89CB,0x89CC, +0x89CD,0x89CE,0x89CF,0xCABF,0xC8C9,0x89D0,0xD7B3,0x89D1, +0xC9F9,0x89D2,0x89D3,0xBFC7,0x89D4,0x89D5,0xBAF8,0x89D6, +0x89D7,0xD2BC,0x89D8,0x89D9,0x89DA,0x89DB,0x89DC,0x89DD, +0x89DE,0x89DF,0xE2BA,0x89E0,0xB4A6,0x89E1,0x89E2,0xB1B8, +0x89E3,0x89E4,0x89E5,0x89E6,0x89E7,0xB8B4,0x89E8,0xCFC4, +0x89E9,0x89EA,0x89EB,0x89EC,0xD9E7,0xCFA6,0xCDE2,0x89ED, +0x89EE,0xD9ED,0xB6E0,0x89EF,0xD2B9,0x89F0,0x89F1,0xB9BB, +0x89F2,0x89F3,0x89F4,0x89F5,0xE2B9,0xE2B7,0x89F6,0xB4F3, +0x89F7,0xCCEC,0xCCAB,0xB7F2,0x89F8,0xD8B2,0xD1EB,0xBABB, +0x89F9,0xCAA7,0x89FA,0x89FB,0xCDB7,0x89FC,0x89FD,0xD2C4, +0xBFE4,0xBCD0,0xB6E1,0x89FE,0xDEC5,0x8A40,0x8A41,0x8A42, +0x8A43,0xDEC6,0xDBBC,0x8A44,0xD1D9,0x8A45,0x8A46,0xC6E6, +0xC4CE,0xB7EE,0x8A47,0xB7DC,0x8A48,0x8A49,0xBFFC,0xD7E0, +0x8A4A,0xC6F5,0x8A4B,0x8A4C,0xB1BC,0xDEC8,0xBDB1,0xCCD7, +0xDECA,0x8A4D,0xDEC9,0x8A4E,0x8A4F,0x8A50,0x8A51,0x8A52, +0xB5EC,0x8A53,0xC9DD,0x8A54,0x8A55,0xB0C2,0x8A56,0x8A57, +0x8A58,0x8A59,0x8A5A,0x8A5B,0x8A5C,0x8A5D,0x8A5E,0x8A5F, +0x8A60,0x8A61,0x8A62,0xC5AE,0xC5AB,0x8A63,0xC4CC,0x8A64, +0xBCE9,0xCBFD,0x8A65,0x8A66,0x8A67,0xBAC3,0x8A68,0x8A69, +0x8A6A,0xE5F9,0xC8E7,0xE5FA,0xCDFD,0x8A6B,0xD7B1,0xB8BE, +0xC2E8,0x8A6C,0xC8D1,0x8A6D,0x8A6E,0xE5FB,0x8A6F,0x8A70, +0x8A71,0x8A72,0xB6CA,0xBCCB,0x8A73,0x8A74,0xD1FD,0xE6A1, +0x8A75,0xC3EE,0x8A76,0x8A77,0x8A78,0x8A79,0xE6A4,0x8A7A, +0x8A7B,0x8A7C,0x8A7D,0xE5FE,0xE6A5,0xCDD7,0x8A7E,0x8A80, +0xB7C1,0xE5FC,0xE5FD,0xE6A3,0x8A81,0x8A82,0xC4DD,0xE6A8, +0x8A83,0x8A84,0xE6A7,0x8A85,0x8A86,0x8A87,0x8A88,0x8A89, +0x8A8A,0xC3C3,0x8A8B,0xC6DE,0x8A8C,0x8A8D,0xE6AA,0x8A8E, +0x8A8F,0x8A90,0x8A91,0x8A92,0x8A93,0x8A94,0xC4B7,0x8A95, +0x8A96,0x8A97,0xE6A2,0xCABC,0x8A98,0x8A99,0x8A9A,0x8A9B, +0xBDE3,0xB9C3,0xE6A6,0xD0D5,0xCEAF,0x8A9C,0x8A9D,0xE6A9, +0xE6B0,0x8A9E,0xD2A6,0x8A9F,0xBDAA,0xE6AD,0x8AA0,0x8AA1, +0x8AA2,0x8AA3,0x8AA4,0xE6AF,0x8AA5,0xC0D1,0x8AA6,0x8AA7, +0xD2CC,0x8AA8,0x8AA9,0x8AAA,0xBCA7,0x8AAB,0x8AAC,0x8AAD, +0x8AAE,0x8AAF,0x8AB0,0x8AB1,0x8AB2,0x8AB3,0x8AB4,0x8AB5, +0x8AB6,0xE6B1,0x8AB7,0xD2F6,0x8AB8,0x8AB9,0x8ABA,0xD7CB, +0x8ABB,0xCDFE,0x8ABC,0xCDDE,0xC2A6,0xE6AB,0xE6AC,0xBDBF, +0xE6AE,0xE6B3,0x8ABD,0x8ABE,0xE6B2,0x8ABF,0x8AC0,0x8AC1, +0x8AC2,0xE6B6,0x8AC3,0xE6B8,0x8AC4,0x8AC5,0x8AC6,0x8AC7, +0xC4EF,0x8AC8,0x8AC9,0x8ACA,0xC4C8,0x8ACB,0x8ACC,0xBEEA, +0xC9EF,0x8ACD,0x8ACE,0xE6B7,0x8ACF,0xB6F0,0x8AD0,0x8AD1, +0x8AD2,0xC3E4,0x8AD3,0x8AD4,0x8AD5,0x8AD6,0x8AD7,0x8AD8, +0x8AD9,0xD3E9,0xE6B4,0x8ADA,0xE6B5,0x8ADB,0xC8A2,0x8ADC, +0x8ADD,0x8ADE,0x8ADF,0x8AE0,0xE6BD,0x8AE1,0x8AE2,0x8AE3, +0xE6B9,0x8AE4,0x8AE5,0x8AE6,0x8AE7,0x8AE8,0xC6C5,0x8AE9, +0x8AEA,0xCDF1,0xE6BB,0x8AEB,0x8AEC,0x8AED,0x8AEE,0x8AEF, +0x8AF0,0x8AF1,0x8AF2,0x8AF3,0x8AF4,0xE6BC,0x8AF5,0x8AF6, +0x8AF7,0x8AF8,0xBBE9,0x8AF9,0x8AFA,0x8AFB,0x8AFC,0x8AFD, +0x8AFE,0x8B40,0xE6BE,0x8B41,0x8B42,0x8B43,0x8B44,0xE6BA, +0x8B45,0x8B46,0xC0B7,0x8B47,0x8B48,0x8B49,0x8B4A,0x8B4B, +0x8B4C,0x8B4D,0x8B4E,0x8B4F,0xD3A4,0xE6BF,0xC9F4,0xE6C3, +0x8B50,0x8B51,0xE6C4,0x8B52,0x8B53,0x8B54,0x8B55,0xD0F6, +0x8B56,0x8B57,0x8B58,0x8B59,0x8B5A,0x8B5B,0x8B5C,0x8B5D, +0x8B5E,0x8B5F,0x8B60,0x8B61,0x8B62,0x8B63,0x8B64,0x8B65, +0x8B66,0x8B67,0xC3BD,0x8B68,0x8B69,0x8B6A,0x8B6B,0x8B6C, +0x8B6D,0x8B6E,0xC3C4,0xE6C2,0x8B6F,0x8B70,0x8B71,0x8B72, +0x8B73,0x8B74,0x8B75,0x8B76,0x8B77,0x8B78,0x8B79,0x8B7A, +0x8B7B,0x8B7C,0xE6C1,0x8B7D,0x8B7E,0x8B80,0x8B81,0x8B82, +0x8B83,0x8B84,0xE6C7,0xCFB1,0x8B85,0xEBF4,0x8B86,0x8B87, +0xE6CA,0x8B88,0x8B89,0x8B8A,0x8B8B,0x8B8C,0xE6C5,0x8B8D, +0x8B8E,0xBCDE,0xC9A9,0x8B8F,0x8B90,0x8B91,0x8B92,0x8B93, +0x8B94,0xBCB5,0x8B95,0x8B96,0xCFD3,0x8B97,0x8B98,0x8B99, +0x8B9A,0x8B9B,0xE6C8,0x8B9C,0xE6C9,0x8B9D,0xE6CE,0x8B9E, +0xE6D0,0x8B9F,0x8BA0,0x8BA1,0xE6D1,0x8BA2,0x8BA3,0x8BA4, +0xE6CB,0xB5D5,0x8BA5,0xE6CC,0x8BA6,0x8BA7,0xE6CF,0x8BA8, +0x8BA9,0xC4DB,0x8BAA,0xE6C6,0x8BAB,0x8BAC,0x8BAD,0x8BAE, +0x8BAF,0xE6CD,0x8BB0,0x8BB1,0x8BB2,0x8BB3,0x8BB4,0x8BB5, +0x8BB6,0x8BB7,0x8BB8,0x8BB9,0x8BBA,0x8BBB,0x8BBC,0x8BBD, +0x8BBE,0x8BBF,0x8BC0,0x8BC1,0x8BC2,0x8BC3,0x8BC4,0x8BC5, +0x8BC6,0xE6D2,0x8BC7,0x8BC8,0x8BC9,0x8BCA,0x8BCB,0x8BCC, +0x8BCD,0x8BCE,0x8BCF,0x8BD0,0x8BD1,0x8BD2,0xE6D4,0xE6D3, +0x8BD3,0x8BD4,0x8BD5,0x8BD6,0x8BD7,0x8BD8,0x8BD9,0x8BDA, +0x8BDB,0x8BDC,0x8BDD,0x8BDE,0x8BDF,0x8BE0,0x8BE1,0x8BE2, +0x8BE3,0x8BE4,0x8BE5,0x8BE6,0x8BE7,0x8BE8,0x8BE9,0x8BEA, +0x8BEB,0x8BEC,0xE6D5,0x8BED,0xD9F8,0x8BEE,0x8BEF,0xE6D6, +0x8BF0,0x8BF1,0x8BF2,0x8BF3,0x8BF4,0x8BF5,0x8BF6,0x8BF7, +0xE6D7,0x8BF8,0x8BF9,0x8BFA,0x8BFB,0x8BFC,0x8BFD,0x8BFE, +0x8C40,0x8C41,0x8C42,0x8C43,0x8C44,0x8C45,0x8C46,0x8C47, +0xD7D3,0xE6DD,0x8C48,0xE6DE,0xBFD7,0xD4D0,0x8C49,0xD7D6, +0xB4E6,0xCBEF,0xE6DA,0xD8C3,0xD7CE,0xD0A2,0x8C4A,0xC3CF, +0x8C4B,0x8C4C,0xE6DF,0xBCBE,0xB9C2,0xE6DB,0xD1A7,0x8C4D, +0x8C4E,0xBAA2,0xC2CF,0x8C4F,0xD8AB,0x8C50,0x8C51,0x8C52, +0xCAEB,0xE5EE,0x8C53,0xE6DC,0x8C54,0xB7F5,0x8C55,0x8C56, +0x8C57,0x8C58,0xC8E6,0x8C59,0x8C5A,0xC4F5,0x8C5B,0x8C5C, +0xE5B2,0xC4FE,0x8C5D,0xCBFC,0xE5B3,0xD5AC,0x8C5E,0xD3EE, +0xCAD8,0xB0B2,0x8C5F,0xCBCE,0xCDEA,0x8C60,0x8C61,0xBAEA, +0x8C62,0x8C63,0x8C64,0xE5B5,0x8C65,0xE5B4,0x8C66,0xD7DA, +0xB9D9,0xD6E6,0xB6A8,0xCDF0,0xD2CB,0xB1A6,0xCAB5,0x8C67, +0xB3E8,0xC9F3,0xBFCD,0xD0FB,0xCAD2,0xE5B6,0xBBC2,0x8C68, +0x8C69,0x8C6A,0xCFDC,0xB9AC,0x8C6B,0x8C6C,0x8C6D,0x8C6E, +0xD4D7,0x8C6F,0x8C70,0xBAA6,0xD1E7,0xCFFC,0xBCD2,0x8C71, +0xE5B7,0xC8DD,0x8C72,0x8C73,0x8C74,0xBFED,0xB1F6,0xCBDE, +0x8C75,0x8C76,0xBCC5,0x8C77,0xBCC4,0xD2FA,0xC3DC,0xBFDC, +0x8C78,0x8C79,0x8C7A,0x8C7B,0xB8BB,0x8C7C,0x8C7D,0x8C7E, +0xC3C2,0x8C80,0xBAAE,0xD4A2,0x8C81,0x8C82,0x8C83,0x8C84, +0x8C85,0x8C86,0x8C87,0x8C88,0x8C89,0xC7DE,0xC4AF,0xB2EC, +0x8C8A,0xB9D1,0x8C8B,0x8C8C,0xE5BB,0xC1C8,0x8C8D,0x8C8E, +0xD5AF,0x8C8F,0x8C90,0x8C91,0x8C92,0x8C93,0xE5BC,0x8C94, +0xE5BE,0x8C95,0x8C96,0x8C97,0x8C98,0x8C99,0x8C9A,0x8C9B, +0xB4E7,0xB6D4,0xCBC2,0xD1B0,0xB5BC,0x8C9C,0x8C9D,0xCAD9, +0x8C9E,0xB7E2,0x8C9F,0x8CA0,0xC9E4,0x8CA1,0xBDAB,0x8CA2, +0x8CA3,0xCEBE,0xD7F0,0x8CA4,0x8CA5,0x8CA6,0x8CA7,0xD0A1, +0x8CA8,0xC9D9,0x8CA9,0x8CAA,0xB6FB,0xE6D8,0xBCE2,0x8CAB, +0xB3BE,0x8CAC,0xC9D0,0x8CAD,0xE6D9,0xB3A2,0x8CAE,0x8CAF, +0x8CB0,0x8CB1,0xDECC,0x8CB2,0xD3C8,0xDECD,0x8CB3,0xD2A2, +0x8CB4,0x8CB5,0x8CB6,0x8CB7,0xDECE,0x8CB8,0x8CB9,0x8CBA, +0x8CBB,0xBECD,0x8CBC,0x8CBD,0xDECF,0x8CBE,0x8CBF,0x8CC0, +0xCAAC,0xD2FC,0xB3DF,0xE5EA,0xC4E1,0xBEA1,0xCEB2,0xC4F2, +0xBED6,0xC6A8,0xB2E3,0x8CC1,0x8CC2,0xBED3,0x8CC3,0x8CC4, +0xC7FC,0xCCEB,0xBDEC,0xCEDD,0x8CC5,0x8CC6,0xCABA,0xC6C1, +0xE5EC,0xD0BC,0x8CC7,0x8CC8,0x8CC9,0xD5B9,0x8CCA,0x8CCB, +0x8CCC,0xE5ED,0x8CCD,0x8CCE,0x8CCF,0x8CD0,0xCAF4,0x8CD1, +0xCDC0,0xC2C5,0x8CD2,0xE5EF,0x8CD3,0xC2C4,0xE5F0,0x8CD4, +0x8CD5,0x8CD6,0x8CD7,0x8CD8,0x8CD9,0x8CDA,0xE5F8,0xCDCD, +0x8CDB,0xC9BD,0x8CDC,0x8CDD,0x8CDE,0x8CDF,0x8CE0,0x8CE1, +0x8CE2,0xD2D9,0xE1A8,0x8CE3,0x8CE4,0x8CE5,0x8CE6,0xD3EC, +0x8CE7,0xCBEA,0xC6F1,0x8CE8,0x8CE9,0x8CEA,0x8CEB,0x8CEC, +0xE1AC,0x8CED,0x8CEE,0x8CEF,0xE1A7,0xE1A9,0x8CF0,0x8CF1, +0xE1AA,0xE1AF,0x8CF2,0x8CF3,0xB2ED,0x8CF4,0xE1AB,0xB8DA, +0xE1AD,0xE1AE,0xE1B0,0xB5BA,0xE1B1,0x8CF5,0x8CF6,0x8CF7, +0x8CF8,0x8CF9,0xE1B3,0xE1B8,0x8CFA,0x8CFB,0x8CFC,0x8CFD, +0x8CFE,0xD1D2,0x8D40,0xE1B6,0xE1B5,0xC1EB,0x8D41,0x8D42, +0x8D43,0xE1B7,0x8D44,0xD4C0,0x8D45,0xE1B2,0x8D46,0xE1BA, +0xB0B6,0x8D47,0x8D48,0x8D49,0x8D4A,0xE1B4,0x8D4B,0xBFF9, +0x8D4C,0xE1B9,0x8D4D,0x8D4E,0xE1BB,0x8D4F,0x8D50,0x8D51, +0x8D52,0x8D53,0x8D54,0xE1BE,0x8D55,0x8D56,0x8D57,0x8D58, +0x8D59,0x8D5A,0xE1BC,0x8D5B,0x8D5C,0x8D5D,0x8D5E,0x8D5F, +0x8D60,0xD6C5,0x8D61,0x8D62,0x8D63,0x8D64,0x8D65,0x8D66, +0x8D67,0xCFBF,0x8D68,0x8D69,0xE1BD,0xE1BF,0xC2CD,0x8D6A, +0xB6EB,0x8D6B,0xD3F8,0x8D6C,0x8D6D,0xC7CD,0x8D6E,0x8D6F, +0xB7E5,0x8D70,0x8D71,0x8D72,0x8D73,0x8D74,0x8D75,0x8D76, +0x8D77,0x8D78,0x8D79,0xBEFE,0x8D7A,0x8D7B,0x8D7C,0x8D7D, +0x8D7E,0x8D80,0xE1C0,0xE1C1,0x8D81,0x8D82,0xE1C7,0xB3E7, +0x8D83,0x8D84,0x8D85,0x8D86,0x8D87,0x8D88,0xC6E9,0x8D89, +0x8D8A,0x8D8B,0x8D8C,0x8D8D,0xB4DE,0x8D8E,0xD1C2,0x8D8F, +0x8D90,0x8D91,0x8D92,0xE1C8,0x8D93,0x8D94,0xE1C6,0x8D95, +0x8D96,0x8D97,0x8D98,0x8D99,0xE1C5,0x8D9A,0xE1C3,0xE1C2, +0x8D9B,0xB1C0,0x8D9C,0x8D9D,0x8D9E,0xD5B8,0xE1C4,0x8D9F, +0x8DA0,0x8DA1,0x8DA2,0x8DA3,0xE1CB,0x8DA4,0x8DA5,0x8DA6, +0x8DA7,0x8DA8,0x8DA9,0x8DAA,0x8DAB,0xE1CC,0xE1CA,0x8DAC, +0x8DAD,0x8DAE,0x8DAF,0x8DB0,0x8DB1,0x8DB2,0x8DB3,0xEFFA, +0x8DB4,0x8DB5,0xE1D3,0xE1D2,0xC7B6,0x8DB6,0x8DB7,0x8DB8, +0x8DB9,0x8DBA,0x8DBB,0x8DBC,0x8DBD,0x8DBE,0x8DBF,0x8DC0, +0xE1C9,0x8DC1,0x8DC2,0xE1CE,0x8DC3,0xE1D0,0x8DC4,0x8DC5, +0x8DC6,0x8DC7,0x8DC8,0x8DC9,0x8DCA,0x8DCB,0x8DCC,0x8DCD, +0x8DCE,0xE1D4,0x8DCF,0xE1D1,0xE1CD,0x8DD0,0x8DD1,0xE1CF, +0x8DD2,0x8DD3,0x8DD4,0x8DD5,0xE1D5,0x8DD6,0x8DD7,0x8DD8, +0x8DD9,0x8DDA,0x8DDB,0x8DDC,0x8DDD,0x8DDE,0x8DDF,0x8DE0, +0x8DE1,0x8DE2,0xE1D6,0x8DE3,0x8DE4,0x8DE5,0x8DE6,0x8DE7, +0x8DE8,0x8DE9,0x8DEA,0x8DEB,0x8DEC,0x8DED,0x8DEE,0x8DEF, +0x8DF0,0x8DF1,0x8DF2,0x8DF3,0x8DF4,0x8DF5,0x8DF6,0x8DF7, +0x8DF8,0xE1D7,0x8DF9,0x8DFA,0x8DFB,0xE1D8,0x8DFC,0x8DFD, +0x8DFE,0x8E40,0x8E41,0x8E42,0x8E43,0x8E44,0x8E45,0x8E46, +0x8E47,0x8E48,0x8E49,0x8E4A,0x8E4B,0x8E4C,0x8E4D,0x8E4E, +0x8E4F,0x8E50,0x8E51,0x8E52,0x8E53,0x8E54,0x8E55,0xE1DA, +0x8E56,0x8E57,0x8E58,0x8E59,0x8E5A,0x8E5B,0x8E5C,0x8E5D, +0x8E5E,0x8E5F,0x8E60,0x8E61,0x8E62,0xE1DB,0x8E63,0x8E64, +0x8E65,0x8E66,0x8E67,0x8E68,0x8E69,0xCEA1,0x8E6A,0x8E6B, +0x8E6C,0x8E6D,0x8E6E,0x8E6F,0x8E70,0x8E71,0x8E72,0x8E73, +0x8E74,0x8E75,0x8E76,0xE7DD,0x8E77,0xB4A8,0xD6DD,0x8E78, +0x8E79,0xD1B2,0xB3B2,0x8E7A,0x8E7B,0xB9A4,0xD7F3,0xC7C9, +0xBEDE,0xB9AE,0x8E7C,0xCED7,0x8E7D,0x8E7E,0xB2EE,0xDBCF, +0x8E80,0xBCBA,0xD2D1,0xCBC8,0xB0CD,0x8E81,0x8E82,0xCFEF, +0x8E83,0x8E84,0x8E85,0x8E86,0x8E87,0xD9E3,0xBDED,0x8E88, +0x8E89,0xB1D2,0xCAD0,0xB2BC,0x8E8A,0xCBA7,0xB7AB,0x8E8B, +0xCAA6,0x8E8C,0x8E8D,0x8E8E,0xCFA3,0x8E8F,0x8E90,0xE0F8, +0xD5CA,0xE0FB,0x8E91,0x8E92,0xE0FA,0xC5C1,0xCCFB,0x8E93, +0xC1B1,0xE0F9,0xD6E3,0xB2AF,0xD6C4,0xB5DB,0x8E94,0x8E95, +0x8E96,0x8E97,0x8E98,0x8E99,0x8E9A,0x8E9B,0xB4F8,0xD6A1, +0x8E9C,0x8E9D,0x8E9E,0x8E9F,0x8EA0,0xCFAF,0xB0EF,0x8EA1, +0x8EA2,0xE0FC,0x8EA3,0x8EA4,0x8EA5,0x8EA6,0x8EA7,0xE1A1, +0xB3A3,0x8EA8,0x8EA9,0xE0FD,0xE0FE,0xC3B1,0x8EAA,0x8EAB, +0x8EAC,0x8EAD,0xC3DD,0x8EAE,0xE1A2,0xB7F9,0x8EAF,0x8EB0, +0x8EB1,0x8EB2,0x8EB3,0x8EB4,0xBBCF,0x8EB5,0x8EB6,0x8EB7, +0x8EB8,0x8EB9,0x8EBA,0x8EBB,0xE1A3,0xC4BB,0x8EBC,0x8EBD, +0x8EBE,0x8EBF,0x8EC0,0xE1A4,0x8EC1,0x8EC2,0xE1A5,0x8EC3, +0x8EC4,0xE1A6,0xB4B1,0x8EC5,0x8EC6,0x8EC7,0x8EC8,0x8EC9, +0x8ECA,0x8ECB,0x8ECC,0x8ECD,0x8ECE,0x8ECF,0x8ED0,0x8ED1, +0x8ED2,0x8ED3,0xB8C9,0xC6BD,0xC4EA,0x8ED4,0xB2A2,0x8ED5, +0xD0D2,0x8ED6,0xE7DB,0xBBC3,0xD3D7,0xD3C4,0x8ED7,0xB9E3, +0xE2CF,0x8ED8,0x8ED9,0x8EDA,0xD7AF,0x8EDB,0xC7EC,0xB1D3, +0x8EDC,0x8EDD,0xB4B2,0xE2D1,0x8EDE,0x8EDF,0x8EE0,0xD0F2, +0xC2AE,0xE2D0,0x8EE1,0xBFE2,0xD3A6,0xB5D7,0xE2D2,0xB5EA, +0x8EE2,0xC3ED,0xB8FD,0x8EE3,0xB8AE,0x8EE4,0xC5D3,0xB7CF, +0xE2D4,0x8EE5,0x8EE6,0x8EE7,0x8EE8,0xE2D3,0xB6C8,0xD7F9, +0x8EE9,0x8EEA,0x8EEB,0x8EEC,0x8EED,0xCDA5,0x8EEE,0x8EEF, +0x8EF0,0x8EF1,0x8EF2,0xE2D8,0x8EF3,0xE2D6,0xCAFC,0xBFB5, +0xD3B9,0xE2D5,0x8EF4,0x8EF5,0x8EF6,0x8EF7,0xE2D7,0x8EF8, +0x8EF9,0x8EFA,0x8EFB,0x8EFC,0x8EFD,0x8EFE,0x8F40,0x8F41, +0x8F42,0xC1AE,0xC0C8,0x8F43,0x8F44,0x8F45,0x8F46,0x8F47, +0x8F48,0xE2DB,0xE2DA,0xC0AA,0x8F49,0x8F4A,0xC1CE,0x8F4B, +0x8F4C,0x8F4D,0x8F4E,0xE2DC,0x8F4F,0x8F50,0x8F51,0x8F52, +0x8F53,0x8F54,0x8F55,0x8F56,0x8F57,0x8F58,0x8F59,0x8F5A, +0xE2DD,0x8F5B,0xE2DE,0x8F5C,0x8F5D,0x8F5E,0x8F5F,0x8F60, +0x8F61,0x8F62,0x8F63,0x8F64,0xDBC8,0x8F65,0xD1D3,0xCDA2, +0x8F66,0x8F67,0xBDA8,0x8F68,0x8F69,0x8F6A,0xDEC3,0xD8A5, +0xBFAA,0xDBCD,0xD2EC,0xC6FA,0xC5AA,0x8F6B,0x8F6C,0x8F6D, +0xDEC4,0x8F6E,0xB1D7,0xDFAE,0x8F6F,0x8F70,0x8F71,0xCABD, +0x8F72,0xDFB1,0x8F73,0xB9AD,0x8F74,0xD2FD,0x8F75,0xB8A5, +0xBAEB,0x8F76,0x8F77,0xB3DA,0x8F78,0x8F79,0x8F7A,0xB5DC, +0xD5C5,0x8F7B,0x8F7C,0x8F7D,0x8F7E,0xC3D6,0xCFD2,0xBBA1, +0x8F80,0xE5F3,0xE5F2,0x8F81,0x8F82,0xE5F4,0x8F83,0xCDE4, +0x8F84,0xC8F5,0x8F85,0x8F86,0x8F87,0x8F88,0x8F89,0x8F8A, +0x8F8B,0xB5AF,0xC7BF,0x8F8C,0xE5F6,0x8F8D,0x8F8E,0x8F8F, +0xECB0,0x8F90,0x8F91,0x8F92,0x8F93,0x8F94,0x8F95,0x8F96, +0x8F97,0x8F98,0x8F99,0x8F9A,0x8F9B,0x8F9C,0x8F9D,0x8F9E, +0xE5E6,0x8F9F,0xB9E9,0xB5B1,0x8FA0,0xC2BC,0xE5E8,0xE5E7, +0xE5E9,0x8FA1,0x8FA2,0x8FA3,0x8FA4,0xD2CD,0x8FA5,0x8FA6, +0x8FA7,0xE1EA,0xD0CE,0x8FA8,0xCDAE,0x8FA9,0xD1E5,0x8FAA, +0x8FAB,0xB2CA,0xB1EB,0x8FAC,0xB1F2,0xC5ED,0x8FAD,0x8FAE, +0xD5C3,0xD3B0,0x8FAF,0xE1DC,0x8FB0,0x8FB1,0x8FB2,0xE1DD, +0x8FB3,0xD2DB,0x8FB4,0xB3B9,0xB1CB,0x8FB5,0x8FB6,0x8FB7, +0xCDF9,0xD5F7,0xE1DE,0x8FB8,0xBEB6,0xB4FD,0x8FB9,0xE1DF, +0xBADC,0xE1E0,0xBBB2,0xC2C9,0xE1E1,0x8FBA,0x8FBB,0x8FBC, +0xD0EC,0x8FBD,0xCDBD,0x8FBE,0x8FBF,0xE1E2,0x8FC0,0xB5C3, +0xC5C7,0xE1E3,0x8FC1,0x8FC2,0xE1E4,0x8FC3,0x8FC4,0x8FC5, +0x8FC6,0xD3F9,0x8FC7,0x8FC8,0x8FC9,0x8FCA,0x8FCB,0x8FCC, +0xE1E5,0x8FCD,0xD1AD,0x8FCE,0x8FCF,0xE1E6,0xCEA2,0x8FD0, +0x8FD1,0x8FD2,0x8FD3,0x8FD4,0x8FD5,0xE1E7,0x8FD6,0xB5C2, +0x8FD7,0x8FD8,0x8FD9,0x8FDA,0xE1E8,0xBBD5,0x8FDB,0x8FDC, +0x8FDD,0x8FDE,0x8FDF,0xD0C4,0xE2E0,0xB1D8,0xD2E4,0x8FE0, +0x8FE1,0xE2E1,0x8FE2,0x8FE3,0xBCC9,0xC8CC,0x8FE4,0xE2E3, +0xECFE,0xECFD,0xDFAF,0x8FE5,0x8FE6,0x8FE7,0xE2E2,0xD6BE, +0xCDFC,0xC3A6,0x8FE8,0x8FE9,0x8FEA,0xE3C3,0x8FEB,0x8FEC, +0xD6D2,0xE2E7,0x8FED,0x8FEE,0xE2E8,0x8FEF,0x8FF0,0xD3C7, +0x8FF1,0x8FF2,0xE2EC,0xBFEC,0x8FF3,0xE2ED,0xE2E5,0x8FF4, +0x8FF5,0xB3C0,0x8FF6,0x8FF7,0x8FF8,0xC4EE,0x8FF9,0x8FFA, +0xE2EE,0x8FFB,0x8FFC,0xD0C3,0x8FFD,0xBAF6,0xE2E9,0xB7DE, +0xBBB3,0xCCAC,0xCBCB,0xE2E4,0xE2E6,0xE2EA,0xE2EB,0x8FFE, +0x9040,0x9041,0xE2F7,0x9042,0x9043,0xE2F4,0xD4F5,0xE2F3, +0x9044,0x9045,0xC5AD,0x9046,0xD5FA,0xC5C2,0xB2C0,0x9047, +0x9048,0xE2EF,0x9049,0xE2F2,0xC1AF,0xCBBC,0x904A,0x904B, +0xB5A1,0xE2F9,0x904C,0x904D,0x904E,0xBCB1,0xE2F1,0xD0D4, +0xD4B9,0xE2F5,0xB9D6,0xE2F6,0x904F,0x9050,0x9051,0xC7D3, +0x9052,0x9053,0x9054,0x9055,0x9056,0xE2F0,0x9057,0x9058, +0x9059,0x905A,0x905B,0xD7DC,0xEDA1,0x905C,0x905D,0xE2F8, +0x905E,0xEDA5,0xE2FE,0xCAD1,0x905F,0x9060,0x9061,0x9062, +0x9063,0x9064,0x9065,0xC1B5,0x9066,0xBBD0,0x9067,0x9068, +0xBFD6,0x9069,0xBAE3,0x906A,0x906B,0xCBA1,0x906C,0x906D, +0x906E,0xEDA6,0xEDA3,0x906F,0x9070,0xEDA2,0x9071,0x9072, +0x9073,0x9074,0xBBD6,0xEDA7,0xD0F4,0x9075,0x9076,0xEDA4, +0xBADE,0xB6F7,0xE3A1,0xB6B2,0xCCF1,0xB9A7,0x9077,0xCFA2, +0xC7A1,0x9078,0x9079,0xBFD2,0x907A,0x907B,0xB6F1,0x907C, +0xE2FA,0xE2FB,0xE2FD,0xE2FC,0xC4D5,0xE3A2,0x907D,0xD3C1, +0x907E,0x9080,0x9081,0xE3A7,0xC7C4,0x9082,0x9083,0x9084, +0x9085,0xCFA4,0x9086,0x9087,0xE3A9,0xBAB7,0x9088,0x9089, +0x908A,0x908B,0xE3A8,0x908C,0xBBDA,0x908D,0xE3A3,0x908E, +0x908F,0x9090,0xE3A4,0xE3AA,0x9091,0xE3A6,0x9092,0xCEF2, +0xD3C6,0x9093,0x9094,0xBBBC,0x9095,0x9096,0xD4C3,0x9097, +0xC4FA,0x9098,0x9099,0xEDA8,0xD0FC,0xE3A5,0x909A,0xC3F5, +0x909B,0xE3AD,0xB1AF,0x909C,0xE3B2,0x909D,0x909E,0x909F, +0xBCC2,0x90A0,0x90A1,0xE3AC,0xB5BF,0x90A2,0x90A3,0x90A4, +0x90A5,0x90A6,0x90A7,0x90A8,0x90A9,0xC7E9,0xE3B0,0x90AA, +0x90AB,0x90AC,0xBEAA,0xCDEF,0x90AD,0x90AE,0x90AF,0x90B0, +0x90B1,0xBBF3,0x90B2,0x90B3,0x90B4,0xCCE8,0x90B5,0x90B6, +0xE3AF,0x90B7,0xE3B1,0x90B8,0xCFA7,0xE3AE,0x90B9,0xCEA9, +0xBBDD,0x90BA,0x90BB,0x90BC,0x90BD,0x90BE,0xB5EB,0xBEE5, +0xB2D2,0xB3CD,0x90BF,0xB1B9,0xE3AB,0xB2D1,0xB5AC,0xB9DF, +0xB6E8,0x90C0,0x90C1,0xCFEB,0xE3B7,0x90C2,0xBBCC,0x90C3, +0x90C4,0xC8C7,0xD0CA,0x90C5,0x90C6,0x90C7,0x90C8,0x90C9, +0xE3B8,0xB3EE,0x90CA,0x90CB,0x90CC,0x90CD,0xEDA9,0x90CE, +0xD3FA,0xD3E4,0x90CF,0x90D0,0x90D1,0xEDAA,0xE3B9,0xD2E2, +0x90D2,0x90D3,0x90D4,0x90D5,0x90D6,0xE3B5,0x90D7,0x90D8, +0x90D9,0x90DA,0xD3DE,0x90DB,0x90DC,0x90DD,0x90DE,0xB8D0, +0xE3B3,0x90DF,0x90E0,0xE3B6,0xB7DF,0x90E1,0xE3B4,0xC0A2, +0x90E2,0x90E3,0x90E4,0xE3BA,0x90E5,0x90E6,0x90E7,0x90E8, +0x90E9,0x90EA,0x90EB,0x90EC,0x90ED,0x90EE,0x90EF,0x90F0, +0x90F1,0x90F2,0x90F3,0x90F4,0x90F5,0x90F6,0x90F7,0xD4B8, +0x90F8,0x90F9,0x90FA,0x90FB,0x90FC,0x90FD,0x90FE,0x9140, +0xB4C8,0x9141,0xE3BB,0x9142,0xBBC5,0x9143,0xC9F7,0x9144, +0x9145,0xC9E5,0x9146,0x9147,0x9148,0xC4BD,0x9149,0x914A, +0x914B,0x914C,0x914D,0x914E,0x914F,0xEDAB,0x9150,0x9151, +0x9152,0x9153,0xC2FD,0x9154,0x9155,0x9156,0x9157,0xBBDB, +0xBFAE,0x9158,0x9159,0x915A,0x915B,0x915C,0x915D,0x915E, +0xCEBF,0x915F,0x9160,0x9161,0x9162,0xE3BC,0x9163,0xBFB6, +0x9164,0x9165,0x9166,0x9167,0x9168,0x9169,0x916A,0x916B, +0x916C,0x916D,0x916E,0x916F,0x9170,0x9171,0x9172,0x9173, +0x9174,0x9175,0x9176,0xB1EF,0x9177,0x9178,0xD4F7,0x9179, +0x917A,0x917B,0x917C,0x917D,0xE3BE,0x917E,0x9180,0x9181, +0x9182,0x9183,0x9184,0x9185,0x9186,0xEDAD,0x9187,0x9188, +0x9189,0x918A,0x918B,0x918C,0x918D,0x918E,0x918F,0xE3BF, +0xBAA9,0xEDAC,0x9190,0x9191,0xE3BD,0x9192,0x9193,0x9194, +0x9195,0x9196,0x9197,0x9198,0x9199,0x919A,0x919B,0xE3C0, +0x919C,0x919D,0x919E,0x919F,0x91A0,0x91A1,0xBAB6,0x91A2, +0x91A3,0x91A4,0xB6AE,0x91A5,0x91A6,0x91A7,0x91A8,0x91A9, +0xD0B8,0x91AA,0xB0C3,0xEDAE,0x91AB,0x91AC,0x91AD,0x91AE, +0x91AF,0xEDAF,0xC0C1,0x91B0,0xE3C1,0x91B1,0x91B2,0x91B3, +0x91B4,0x91B5,0x91B6,0x91B7,0x91B8,0x91B9,0x91BA,0x91BB, +0x91BC,0x91BD,0x91BE,0x91BF,0x91C0,0x91C1,0xC5B3,0x91C2, +0x91C3,0x91C4,0x91C5,0x91C6,0x91C7,0x91C8,0x91C9,0x91CA, +0x91CB,0x91CC,0x91CD,0x91CE,0x91CF,0xE3C2,0x91D0,0x91D1, +0x91D2,0x91D3,0x91D4,0x91D5,0x91D6,0x91D7,0x91D8,0xDCB2, +0x91D9,0x91DA,0x91DB,0x91DC,0x91DD,0x91DE,0xEDB0,0x91DF, +0xB8EA,0x91E0,0xCEEC,0xEAA7,0xD0E7,0xCAF9,0xC8D6,0xCFB7, +0xB3C9,0xCED2,0xBDE4,0x91E1,0x91E2,0xE3DE,0xBBF2,0xEAA8, +0xD5BD,0x91E3,0xC6DD,0xEAA9,0x91E4,0x91E5,0x91E6,0xEAAA, +0x91E7,0xEAAC,0xEAAB,0x91E8,0xEAAE,0xEAAD,0x91E9,0x91EA, +0x91EB,0x91EC,0xBDD8,0x91ED,0xEAAF,0x91EE,0xC2BE,0x91EF, +0x91F0,0x91F1,0x91F2,0xB4C1,0xB4F7,0x91F3,0x91F4,0xBBA7, +0x91F5,0x91F6,0x91F7,0x91F8,0x91F9,0xECE6,0xECE5,0xB7BF, +0xCBF9,0xB1E2,0x91FA,0xECE7,0x91FB,0x91FC,0x91FD,0xC9C8, +0xECE8,0xECE9,0x91FE,0xCAD6,0xDED0,0xB2C5,0xD4FA,0x9240, +0x9241,0xC6CB,0xB0C7,0xB4F2,0xC8D3,0x9242,0x9243,0x9244, +0xCDD0,0x9245,0x9246,0xBFB8,0x9247,0x9248,0x9249,0x924A, +0x924B,0x924C,0x924D,0xBFDB,0x924E,0x924F,0xC7A4,0xD6B4, +0x9250,0xC0A9,0xDED1,0xC9A8,0xD1EF,0xC5A4,0xB0E7,0xB3B6, +0xC8C5,0x9251,0x9252,0xB0E2,0x9253,0x9254,0xB7F6,0x9255, +0x9256,0xC5FA,0x9257,0x9258,0xB6F3,0x9259,0xD5D2,0xB3D0, +0xBCBC,0x925A,0x925B,0x925C,0xB3AD,0x925D,0x925E,0x925F, +0x9260,0xBEF1,0xB0D1,0x9261,0x9262,0x9263,0x9264,0x9265, +0x9266,0xD2D6,0xCAE3,0xD7A5,0x9267,0xCDB6,0xB6B6,0xBFB9, +0xD5DB,0x9268,0xB8A7,0xC5D7,0x9269,0x926A,0x926B,0xDED2, +0xBFD9,0xC2D5,0xC7C0,0x926C,0xBBA4,0xB1A8,0x926D,0x926E, +0xC5EA,0x926F,0x9270,0xC5FB,0xCCA7,0x9271,0x9272,0x9273, +0x9274,0xB1A7,0x9275,0x9276,0x9277,0xB5D6,0x9278,0x9279, +0x927A,0xC4A8,0x927B,0xDED3,0xD1BA,0xB3E9,0x927C,0xC3F2, +0x927D,0x927E,0xB7F7,0x9280,0xD6F4,0xB5A3,0xB2F0,0xC4B4, +0xC4E9,0xC0AD,0xDED4,0x9281,0xB0E8,0xC5C4,0xC1E0,0x9282, +0xB9D5,0x9283,0xBEDC,0xCDD8,0xB0CE,0x9284,0xCDCF,0xDED6, +0xBED0,0xD7BE,0xDED5,0xD5D0,0xB0DD,0x9285,0x9286,0xC4E2, +0x9287,0x9288,0xC2A3,0xBCF0,0x9289,0xD3B5,0xC0B9,0xC5A1, +0xB2A6,0xD4F1,0x928A,0x928B,0xC0A8,0xCAC3,0xDED7,0xD5FC, +0x928C,0xB9B0,0x928D,0xC8AD,0xCBA9,0x928E,0xDED9,0xBFBD, +0x928F,0x9290,0x9291,0x9292,0xC6B4,0xD7A7,0xCAB0,0xC4C3, +0x9293,0xB3D6,0xB9D2,0x9294,0x9295,0x9296,0x9297,0xD6B8, +0xEAFC,0xB0B4,0x9298,0x9299,0x929A,0x929B,0xBFE6,0x929C, +0x929D,0xCCF4,0x929E,0x929F,0x92A0,0x92A1,0xCDDA,0x92A2, +0x92A3,0x92A4,0xD6BF,0xC2CE,0x92A5,0xCECE,0xCCA2,0xD0AE, +0xC4D3,0xB5B2,0xDED8,0xD5F5,0xBCB7,0xBBD3,0x92A6,0x92A7, +0xB0A4,0x92A8,0xC5B2,0xB4EC,0x92A9,0x92AA,0x92AB,0xD5F1, +0x92AC,0x92AD,0xEAFD,0x92AE,0x92AF,0x92B0,0x92B1,0x92B2, +0x92B3,0xDEDA,0xCDA6,0x92B4,0x92B5,0xCDEC,0x92B6,0x92B7, +0x92B8,0x92B9,0xCEE6,0xDEDC,0x92BA,0xCDB1,0xC0A6,0x92BB, +0x92BC,0xD7BD,0x92BD,0xDEDB,0xB0C6,0xBAB4,0xC9D3,0xC4F3, +0xBEE8,0x92BE,0x92BF,0x92C0,0x92C1,0xB2B6,0x92C2,0x92C3, +0x92C4,0x92C5,0x92C6,0x92C7,0x92C8,0x92C9,0xC0CC,0xCBF0, +0x92CA,0xBCF1,0xBBBB,0xB5B7,0x92CB,0x92CC,0x92CD,0xC5F5, +0x92CE,0xDEE6,0x92CF,0x92D0,0x92D1,0xDEE3,0xBEDD,0x92D2, +0x92D3,0xDEDF,0x92D4,0x92D5,0x92D6,0x92D7,0xB4B7,0xBDDD, +0x92D8,0x92D9,0xDEE0,0xC4ED,0x92DA,0x92DB,0x92DC,0x92DD, +0xCFC6,0x92DE,0xB5E0,0x92DF,0x92E0,0x92E1,0x92E2,0xB6DE, +0xCADA,0xB5F4,0xDEE5,0x92E3,0xD5C6,0x92E4,0xDEE1,0xCCCD, +0xC6FE,0x92E5,0xC5C5,0x92E6,0x92E7,0x92E8,0xD2B4,0x92E9, +0xBEF2,0x92EA,0x92EB,0x92EC,0x92ED,0x92EE,0x92EF,0x92F0, +0xC2D3,0x92F1,0xCCBD,0xB3B8,0x92F2,0xBDD3,0x92F3,0xBFD8, +0xCDC6,0xD1DA,0xB4EB,0x92F4,0xDEE4,0xDEDD,0xDEE7,0x92F5, +0xEAFE,0x92F6,0x92F7,0xC2B0,0xDEE2,0x92F8,0x92F9,0xD6C0, +0xB5A7,0x92FA,0xB2F4,0x92FB,0xDEE8,0x92FC,0xDEF2,0x92FD, +0x92FE,0x9340,0x9341,0x9342,0xDEED,0x9343,0xDEF1,0x9344, +0x9345,0xC8E0,0x9346,0x9347,0x9348,0xD7E1,0xDEEF,0xC3E8, +0xCCE1,0x9349,0xB2E5,0x934A,0x934B,0x934C,0xD2BE,0x934D, +0x934E,0x934F,0x9350,0x9351,0x9352,0x9353,0xDEEE,0x9354, +0xDEEB,0xCED5,0x9355,0xB4A7,0x9356,0x9357,0x9358,0x9359, +0x935A,0xBFAB,0xBEBE,0x935B,0x935C,0xBDD2,0x935D,0x935E, +0x935F,0x9360,0xDEE9,0x9361,0xD4AE,0x9362,0xDEDE,0x9363, +0xDEEA,0x9364,0x9365,0x9366,0x9367,0xC0BF,0x9368,0xDEEC, +0xB2F3,0xB8E9,0xC2A7,0x9369,0x936A,0xBDC1,0x936B,0x936C, +0x936D,0x936E,0x936F,0xDEF5,0xDEF8,0x9370,0x9371,0xB2AB, +0xB4A4,0x9372,0x9373,0xB4EA,0xC9A6,0x9374,0x9375,0x9376, +0x9377,0x9378,0x9379,0xDEF6,0xCBD1,0x937A,0xB8E3,0x937B, +0xDEF7,0xDEFA,0x937C,0x937D,0x937E,0x9380,0xDEF9,0x9381, +0x9382,0x9383,0xCCC2,0x9384,0xB0E1,0xB4EE,0x9385,0x9386, +0x9387,0x9388,0x9389,0x938A,0xE5BA,0x938B,0x938C,0x938D, +0x938E,0x938F,0xD0AF,0x9390,0x9391,0xB2EB,0x9392,0xEBA1, +0x9393,0xDEF4,0x9394,0x9395,0xC9E3,0xDEF3,0xB0DA,0xD2A1, +0xB1F7,0x9396,0xCCAF,0x9397,0x9398,0x9399,0x939A,0x939B, +0x939C,0x939D,0xDEF0,0x939E,0xCBA4,0x939F,0x93A0,0x93A1, +0xD5AA,0x93A2,0x93A3,0x93A4,0x93A5,0x93A6,0xDEFB,0x93A7, +0x93A8,0x93A9,0x93AA,0x93AB,0x93AC,0x93AD,0x93AE,0xB4DD, +0x93AF,0xC4A6,0x93B0,0x93B1,0x93B2,0xDEFD,0x93B3,0x93B4, +0x93B5,0x93B6,0x93B7,0x93B8,0x93B9,0x93BA,0x93BB,0x93BC, +0xC3FE,0xC4A1,0xDFA1,0x93BD,0x93BE,0x93BF,0x93C0,0x93C1, +0x93C2,0x93C3,0xC1CC,0x93C4,0xDEFC,0xBEEF,0x93C5,0xC6B2, +0x93C6,0x93C7,0x93C8,0x93C9,0x93CA,0x93CB,0x93CC,0x93CD, +0x93CE,0xB3C5,0xC8F6,0x93CF,0x93D0,0xCBBA,0xDEFE,0x93D1, +0x93D2,0xDFA4,0x93D3,0x93D4,0x93D5,0x93D6,0xD7B2,0x93D7, +0x93D8,0x93D9,0x93DA,0x93DB,0xB3B7,0x93DC,0x93DD,0x93DE, +0x93DF,0xC1C3,0x93E0,0x93E1,0xC7CB,0xB2A5,0xB4E9,0x93E2, +0xD7AB,0x93E3,0x93E4,0x93E5,0x93E6,0xC4EC,0x93E7,0xDFA2, +0xDFA3,0x93E8,0xDFA5,0x93E9,0xBAB3,0x93EA,0x93EB,0x93EC, +0xDFA6,0x93ED,0xC0DE,0x93EE,0x93EF,0xC9C3,0x93F0,0x93F1, +0x93F2,0x93F3,0x93F4,0x93F5,0x93F6,0xB2D9,0xC7E6,0x93F7, +0xDFA7,0x93F8,0xC7DC,0x93F9,0x93FA,0x93FB,0x93FC,0xDFA8, +0xEBA2,0x93FD,0x93FE,0x9440,0x9441,0x9442,0xCBD3,0x9443, +0x9444,0x9445,0xDFAA,0x9446,0xDFA9,0x9447,0xB2C1,0x9448, +0x9449,0x944A,0x944B,0x944C,0x944D,0x944E,0x944F,0x9450, +0x9451,0x9452,0x9453,0x9454,0x9455,0x9456,0x9457,0x9458, +0x9459,0x945A,0x945B,0x945C,0x945D,0x945E,0x945F,0x9460, +0xC5CA,0x9461,0x9462,0x9463,0x9464,0x9465,0x9466,0x9467, +0x9468,0xDFAB,0x9469,0x946A,0x946B,0x946C,0x946D,0x946E, +0x946F,0x9470,0xD4DC,0x9471,0x9472,0x9473,0x9474,0x9475, +0xC8C1,0x9476,0x9477,0x9478,0x9479,0x947A,0x947B,0x947C, +0x947D,0x947E,0x9480,0x9481,0x9482,0xDFAC,0x9483,0x9484, +0x9485,0x9486,0x9487,0xBEF0,0x9488,0x9489,0xDFAD,0xD6A7, +0x948A,0x948B,0x948C,0x948D,0xEAB7,0xEBB6,0xCAD5,0x948E, +0xD8FC,0xB8C4,0x948F,0xB9A5,0x9490,0x9491,0xB7C5,0xD5FE, +0x9492,0x9493,0x9494,0x9495,0x9496,0xB9CA,0x9497,0x9498, +0xD0A7,0xF4CD,0x9499,0x949A,0xB5D0,0x949B,0x949C,0xC3F4, +0x949D,0xBEC8,0x949E,0x949F,0x94A0,0xEBB7,0xB0BD,0x94A1, +0x94A2,0xBDCC,0x94A3,0xC1B2,0x94A4,0xB1D6,0xB3A8,0x94A5, +0x94A6,0x94A7,0xB8D2,0xC9A2,0x94A8,0x94A9,0xB6D8,0x94AA, +0x94AB,0x94AC,0x94AD,0xEBB8,0xBEB4,0x94AE,0x94AF,0x94B0, +0xCAFD,0x94B1,0xC7C3,0x94B2,0xD5FB,0x94B3,0x94B4,0xB7F3, +0x94B5,0x94B6,0x94B7,0x94B8,0x94B9,0x94BA,0x94BB,0x94BC, +0x94BD,0x94BE,0x94BF,0x94C0,0x94C1,0x94C2,0x94C3,0xCEC4, +0x94C4,0x94C5,0x94C6,0xD5AB,0xB1F3,0x94C7,0x94C8,0x94C9, +0xECB3,0xB0DF,0x94CA,0xECB5,0x94CB,0x94CC,0x94CD,0xB6B7, +0x94CE,0xC1CF,0x94CF,0xF5FA,0xD0B1,0x94D0,0x94D1,0xD5E5, +0x94D2,0xCED3,0x94D3,0x94D4,0xBDEF,0xB3E2,0x94D5,0xB8AB, +0x94D6,0xD5B6,0x94D7,0xEDBD,0x94D8,0xB6CF,0x94D9,0xCBB9, +0xD0C2,0x94DA,0x94DB,0x94DC,0x94DD,0x94DE,0x94DF,0x94E0, +0x94E1,0xB7BD,0x94E2,0x94E3,0xECB6,0xCAA9,0x94E4,0x94E5, +0x94E6,0xC5D4,0x94E7,0xECB9,0xECB8,0xC2C3,0xECB7,0x94E8, +0x94E9,0x94EA,0x94EB,0xD0FD,0xECBA,0x94EC,0xECBB,0xD7E5, +0x94ED,0x94EE,0xECBC,0x94EF,0x94F0,0x94F1,0xECBD,0xC6EC, +0x94F2,0x94F3,0x94F4,0x94F5,0x94F6,0x94F7,0x94F8,0x94F9, +0xCEDE,0x94FA,0xBCC8,0x94FB,0x94FC,0xC8D5,0xB5A9,0xBEC9, +0xD6BC,0xD4E7,0x94FD,0x94FE,0xD1AE,0xD0F1,0xEAB8,0xEAB9, +0xEABA,0xBAB5,0x9540,0x9541,0x9542,0x9543,0xCAB1,0xBFF5, +0x9544,0x9545,0xCDFA,0x9546,0x9547,0x9548,0x9549,0x954A, +0xEAC0,0x954B,0xB0BA,0xEABE,0x954C,0x954D,0xC0A5,0x954E, +0x954F,0x9550,0xEABB,0x9551,0xB2FD,0x9552,0xC3F7,0xBBE8, +0x9553,0x9554,0x9555,0xD2D7,0xCEF4,0xEABF,0x9556,0x9557, +0x9558,0xEABC,0x9559,0x955A,0x955B,0xEAC3,0x955C,0xD0C7, +0xD3B3,0x955D,0x955E,0x955F,0x9560,0xB4BA,0x9561,0xC3C1, +0xD7F2,0x9562,0x9563,0x9564,0x9565,0xD5D1,0x9566,0xCAC7, +0x9567,0xEAC5,0x9568,0x9569,0xEAC4,0xEAC7,0xEAC6,0x956A, +0x956B,0x956C,0x956D,0x956E,0xD6E7,0x956F,0xCFD4,0x9570, +0x9571,0xEACB,0x9572,0xBBCE,0x9573,0x9574,0x9575,0x9576, +0x9577,0x9578,0x9579,0xBDFA,0xC9CE,0x957A,0x957B,0xEACC, +0x957C,0x957D,0xC9B9,0xCFFE,0xEACA,0xD4CE,0xEACD,0xEACF, +0x957E,0x9580,0xCDED,0x9581,0x9582,0x9583,0x9584,0xEAC9, +0x9585,0xEACE,0x9586,0x9587,0xCEEE,0x9588,0xBBDE,0x9589, +0xB3BF,0x958A,0x958B,0x958C,0x958D,0x958E,0xC6D5,0xBEB0, +0xCEFA,0x958F,0x9590,0x9591,0xC7E7,0x9592,0xBEA7,0xEAD0, +0x9593,0x9594,0xD6C7,0x9595,0x9596,0x9597,0xC1C0,0x9598, +0x9599,0x959A,0xD4DD,0x959B,0xEAD1,0x959C,0x959D,0xCFBE, +0x959E,0x959F,0x95A0,0x95A1,0xEAD2,0x95A2,0x95A3,0x95A4, +0x95A5,0xCAEE,0x95A6,0x95A7,0x95A8,0x95A9,0xC5AF,0xB0B5, +0x95AA,0x95AB,0x95AC,0x95AD,0x95AE,0xEAD4,0x95AF,0x95B0, +0x95B1,0x95B2,0x95B3,0x95B4,0x95B5,0x95B6,0x95B7,0xEAD3, +0xF4DF,0x95B8,0x95B9,0x95BA,0x95BB,0x95BC,0xC4BA,0x95BD, +0x95BE,0x95BF,0x95C0,0x95C1,0xB1A9,0x95C2,0x95C3,0x95C4, +0x95C5,0xE5DF,0x95C6,0x95C7,0x95C8,0x95C9,0xEAD5,0x95CA, +0x95CB,0x95CC,0x95CD,0x95CE,0x95CF,0x95D0,0x95D1,0x95D2, +0x95D3,0x95D4,0x95D5,0x95D6,0x95D7,0x95D8,0x95D9,0x95DA, +0x95DB,0x95DC,0x95DD,0x95DE,0x95DF,0x95E0,0x95E1,0x95E2, +0x95E3,0xCAEF,0x95E4,0xEAD6,0xEAD7,0xC6D8,0x95E5,0x95E6, +0x95E7,0x95E8,0x95E9,0x95EA,0x95EB,0x95EC,0xEAD8,0x95ED, +0x95EE,0xEAD9,0x95EF,0x95F0,0x95F1,0x95F2,0x95F3,0x95F4, +0xD4BB,0x95F5,0xC7FA,0xD2B7,0xB8FC,0x95F6,0x95F7,0xEAC2, +0x95F8,0xB2DC,0x95F9,0x95FA,0xC2FC,0x95FB,0xD4F8,0xCCE6, +0xD7EE,0x95FC,0x95FD,0x95FE,0x9640,0x9641,0x9642,0x9643, +0xD4C2,0xD3D0,0xEBC3,0xC5F3,0x9644,0xB7FE,0x9645,0x9646, +0xEBD4,0x9647,0x9648,0x9649,0xCBB7,0xEBDE,0x964A,0xC0CA, +0x964B,0x964C,0x964D,0xCDFB,0x964E,0xB3AF,0x964F,0xC6DA, +0x9650,0x9651,0x9652,0x9653,0x9654,0x9655,0xEBFC,0x9656, +0xC4BE,0x9657,0xCEB4,0xC4A9,0xB1BE,0xD4FD,0x9658,0xCAF5, +0x9659,0xD6EC,0x965A,0x965B,0xC6D3,0xB6E4,0x965C,0x965D, +0x965E,0x965F,0xBBFA,0x9660,0x9661,0xD0E0,0x9662,0x9663, +0xC9B1,0x9664,0xD4D3,0xC8A8,0x9665,0x9666,0xB8CB,0x9667, +0xE8BE,0xC9BC,0x9668,0x9669,0xE8BB,0x966A,0xC0EE,0xD0D3, +0xB2C4,0xB4E5,0x966B,0xE8BC,0x966C,0x966D,0xD5C8,0x966E, +0x966F,0x9670,0x9671,0x9672,0xB6C5,0x9673,0xE8BD,0xCAF8, +0xB8DC,0xCCF5,0x9674,0x9675,0x9676,0xC0B4,0x9677,0x9678, +0xD1EE,0xE8BF,0xE8C2,0x9679,0x967A,0xBABC,0x967B,0xB1AD, +0xBDDC,0x967C,0xEABD,0xE8C3,0x967D,0xE8C6,0x967E,0xE8CB, +0x9680,0x9681,0x9682,0x9683,0xE8CC,0x9684,0xCBC9,0xB0E5, +0x9685,0xBCAB,0x9686,0x9687,0xB9B9,0x9688,0x9689,0xE8C1, +0x968A,0xCDF7,0x968B,0xE8CA,0x968C,0x968D,0x968E,0x968F, +0xCEF6,0x9690,0x9691,0x9692,0x9693,0xD5ED,0x9694,0xC1D6, +0xE8C4,0x9695,0xC3B6,0x9696,0xB9FB,0xD6A6,0xE8C8,0x9697, +0x9698,0x9699,0xCAE0,0xD4E6,0x969A,0xE8C0,0x969B,0xE8C5, +0xE8C7,0x969C,0xC7B9,0xB7E3,0x969D,0xE8C9,0x969E,0xBFDD, +0xE8D2,0x969F,0x96A0,0xE8D7,0x96A1,0xE8D5,0xBCDC,0xBCCF, +0xE8DB,0x96A2,0x96A3,0x96A4,0x96A5,0x96A6,0x96A7,0x96A8, +0x96A9,0xE8DE,0x96AA,0xE8DA,0xB1FA,0x96AB,0x96AC,0x96AD, +0x96AE,0x96AF,0x96B0,0x96B1,0x96B2,0x96B3,0x96B4,0xB0D8, +0xC4B3,0xB8CC,0xC6E2,0xC8BE,0xC8E1,0x96B5,0x96B6,0x96B7, +0xE8CF,0xE8D4,0xE8D6,0x96B8,0xB9F1,0xE8D8,0xD7F5,0x96B9, +0xC4FB,0x96BA,0xE8DC,0x96BB,0x96BC,0xB2E9,0x96BD,0x96BE, +0x96BF,0xE8D1,0x96C0,0x96C1,0xBCED,0x96C2,0x96C3,0xBFC2, +0xE8CD,0xD6F9,0x96C4,0xC1F8,0xB2F1,0x96C5,0x96C6,0x96C7, +0x96C8,0x96C9,0x96CA,0x96CB,0x96CC,0xE8DF,0x96CD,0xCAC1, +0xE8D9,0x96CE,0x96CF,0x96D0,0x96D1,0xD5A4,0x96D2,0xB1EA, +0xD5BB,0xE8CE,0xE8D0,0xB6B0,0xE8D3,0x96D3,0xE8DD,0xC0B8, +0x96D4,0xCAF7,0x96D5,0xCBA8,0x96D6,0x96D7,0xC6DC,0xC0F5, +0x96D8,0x96D9,0x96DA,0x96DB,0x96DC,0xE8E9,0x96DD,0x96DE, +0x96DF,0xD0A3,0x96E0,0x96E1,0x96E2,0x96E3,0x96E4,0x96E5, +0x96E6,0xE8F2,0xD6EA,0x96E7,0x96E8,0x96E9,0x96EA,0x96EB, +0x96EC,0x96ED,0xE8E0,0xE8E1,0x96EE,0x96EF,0x96F0,0xD1F9, +0xBACB,0xB8F9,0x96F1,0x96F2,0xB8F1,0xD4D4,0xE8EF,0x96F3, +0xE8EE,0xE8EC,0xB9F0,0xCCD2,0xE8E6,0xCEA6,0xBFF2,0x96F4, +0xB0B8,0xE8F1,0xE8F0,0x96F5,0xD7C0,0x96F6,0xE8E4,0x96F7, +0xCDA9,0xC9A3,0x96F8,0xBBB8,0xBDDB,0xE8EA,0x96F9,0x96FA, +0x96FB,0x96FC,0x96FD,0x96FE,0x9740,0x9741,0x9742,0x9743, +0xE8E2,0xE8E3,0xE8E5,0xB5B5,0xE8E7,0xC7C5,0xE8EB,0xE8ED, +0xBDB0,0xD7AE,0x9744,0xE8F8,0x9745,0x9746,0x9747,0x9748, +0x9749,0x974A,0x974B,0x974C,0xE8F5,0x974D,0xCDB0,0xE8F6, +0x974E,0x974F,0x9750,0x9751,0x9752,0x9753,0x9754,0x9755, +0x9756,0xC1BA,0x9757,0xE8E8,0x9758,0xC3B7,0xB0F0,0x9759, +0x975A,0x975B,0x975C,0x975D,0x975E,0x975F,0x9760,0xE8F4, +0x9761,0x9762,0x9763,0xE8F7,0x9764,0x9765,0x9766,0xB9A3, +0x9767,0x9768,0x9769,0x976A,0x976B,0x976C,0x976D,0x976E, +0x976F,0x9770,0xC9D2,0x9771,0x9772,0x9773,0xC3CE,0xCEE0, +0xC0E6,0x9774,0x9775,0x9776,0x9777,0xCBF3,0x9778,0xCCDD, +0xD0B5,0x9779,0x977A,0xCAE1,0x977B,0xE8F3,0x977C,0x977D, +0x977E,0x9780,0x9781,0x9782,0x9783,0x9784,0x9785,0x9786, +0xBCEC,0x9787,0xE8F9,0x9788,0x9789,0x978A,0x978B,0x978C, +0x978D,0xC3DE,0x978E,0xC6E5,0x978F,0xB9F7,0x9790,0x9791, +0x9792,0x9793,0xB0F4,0x9794,0x9795,0xD7D8,0x9796,0x9797, +0xBCAC,0x9798,0xC5EF,0x9799,0x979A,0x979B,0x979C,0x979D, +0xCCC4,0x979E,0x979F,0xE9A6,0x97A0,0x97A1,0x97A2,0x97A3, +0x97A4,0x97A5,0x97A6,0x97A7,0x97A8,0x97A9,0xC9AD,0x97AA, +0xE9A2,0xC0E2,0x97AB,0x97AC,0x97AD,0xBFC3,0x97AE,0x97AF, +0x97B0,0xE8FE,0xB9D7,0x97B1,0xE8FB,0x97B2,0x97B3,0x97B4, +0x97B5,0xE9A4,0x97B6,0x97B7,0x97B8,0xD2CE,0x97B9,0x97BA, +0x97BB,0x97BC,0x97BD,0xE9A3,0x97BE,0xD6B2,0xD7B5,0x97BF, +0xE9A7,0x97C0,0xBDB7,0x97C1,0x97C2,0x97C3,0x97C4,0x97C5, +0x97C6,0x97C7,0x97C8,0x97C9,0x97CA,0x97CB,0x97CC,0xE8FC, +0xE8FD,0x97CD,0x97CE,0x97CF,0xE9A1,0x97D0,0x97D1,0x97D2, +0x97D3,0x97D4,0x97D5,0x97D6,0x97D7,0xCDD6,0x97D8,0x97D9, +0xD2AC,0x97DA,0x97DB,0x97DC,0xE9B2,0x97DD,0x97DE,0x97DF, +0x97E0,0xE9A9,0x97E1,0x97E2,0x97E3,0xB4AA,0x97E4,0xB4BB, +0x97E5,0x97E6,0xE9AB,0x97E7,0x97E8,0x97E9,0x97EA,0x97EB, +0x97EC,0x97ED,0x97EE,0x97EF,0x97F0,0x97F1,0x97F2,0x97F3, +0x97F4,0x97F5,0x97F6,0x97F7,0xD0A8,0x97F8,0x97F9,0xE9A5, +0x97FA,0x97FB,0xB3FE,0x97FC,0x97FD,0xE9AC,0xC0E3,0x97FE, +0xE9AA,0x9840,0x9841,0xE9B9,0x9842,0x9843,0xE9B8,0x9844, +0x9845,0x9846,0x9847,0xE9AE,0x9848,0x9849,0xE8FA,0x984A, +0x984B,0xE9A8,0x984C,0x984D,0x984E,0x984F,0x9850,0xBFAC, +0xE9B1,0xE9BA,0x9851,0x9852,0xC2A5,0x9853,0x9854,0x9855, +0xE9AF,0x9856,0xB8C5,0x9857,0xE9AD,0x9858,0xD3DC,0xE9B4, +0xE9B5,0xE9B7,0x9859,0x985A,0x985B,0xE9C7,0x985C,0x985D, +0x985E,0x985F,0x9860,0x9861,0xC0C6,0xE9C5,0x9862,0x9863, +0xE9B0,0x9864,0x9865,0xE9BB,0xB0F1,0x9866,0x9867,0x9868, +0x9869,0x986A,0x986B,0x986C,0x986D,0x986E,0x986F,0xE9BC, +0xD5A5,0x9870,0x9871,0xE9BE,0x9872,0xE9BF,0x9873,0x9874, +0x9875,0xE9C1,0x9876,0x9877,0xC1F1,0x9878,0x9879,0xC8B6, +0x987A,0x987B,0x987C,0xE9BD,0x987D,0x987E,0x9880,0x9881, +0x9882,0xE9C2,0x9883,0x9884,0x9885,0x9886,0x9887,0x9888, +0x9889,0x988A,0xE9C3,0x988B,0xE9B3,0x988C,0xE9B6,0x988D, +0xBBB1,0x988E,0x988F,0x9890,0xE9C0,0x9891,0x9892,0x9893, +0x9894,0x9895,0x9896,0xBCF7,0x9897,0x9898,0x9899,0xE9C4, +0xE9C6,0x989A,0x989B,0x989C,0x989D,0x989E,0x989F,0x98A0, +0x98A1,0x98A2,0x98A3,0x98A4,0x98A5,0xE9CA,0x98A6,0x98A7, +0x98A8,0x98A9,0xE9CE,0x98AA,0x98AB,0x98AC,0x98AD,0x98AE, +0x98AF,0x98B0,0x98B1,0x98B2,0x98B3,0xB2DB,0x98B4,0xE9C8, +0x98B5,0x98B6,0x98B7,0x98B8,0x98B9,0x98BA,0x98BB,0x98BC, +0x98BD,0x98BE,0xB7AE,0x98BF,0x98C0,0x98C1,0x98C2,0x98C3, +0x98C4,0x98C5,0x98C6,0x98C7,0x98C8,0x98C9,0x98CA,0xE9CB, +0xE9CC,0x98CB,0x98CC,0x98CD,0x98CE,0x98CF,0x98D0,0xD5C1, +0x98D1,0xC4A3,0x98D2,0x98D3,0x98D4,0x98D5,0x98D6,0x98D7, +0xE9D8,0x98D8,0xBAE1,0x98D9,0x98DA,0x98DB,0x98DC,0xE9C9, +0x98DD,0xD3A3,0x98DE,0x98DF,0x98E0,0xE9D4,0x98E1,0x98E2, +0x98E3,0x98E4,0x98E5,0x98E6,0x98E7,0xE9D7,0xE9D0,0x98E8, +0x98E9,0x98EA,0x98EB,0x98EC,0xE9CF,0x98ED,0x98EE,0xC7C1, +0x98EF,0x98F0,0x98F1,0x98F2,0x98F3,0x98F4,0x98F5,0x98F6, +0xE9D2,0x98F7,0x98F8,0x98F9,0x98FA,0x98FB,0x98FC,0x98FD, +0xE9D9,0xB3C8,0x98FE,0xE9D3,0x9940,0x9941,0x9942,0x9943, +0x9944,0xCFF0,0x9945,0x9946,0x9947,0xE9CD,0x9948,0x9949, +0x994A,0x994B,0x994C,0x994D,0x994E,0x994F,0x9950,0x9951, +0x9952,0xB3F7,0x9953,0x9954,0x9955,0x9956,0x9957,0x9958, +0x9959,0xE9D6,0x995A,0x995B,0xE9DA,0x995C,0x995D,0x995E, +0xCCB4,0x995F,0x9960,0x9961,0xCFAD,0x9962,0x9963,0x9964, +0x9965,0x9966,0x9967,0x9968,0x9969,0x996A,0xE9D5,0x996B, +0xE9DC,0xE9DB,0x996C,0x996D,0x996E,0x996F,0x9970,0xE9DE, +0x9971,0x9972,0x9973,0x9974,0x9975,0x9976,0x9977,0x9978, +0xE9D1,0x9979,0x997A,0x997B,0x997C,0x997D,0x997E,0x9980, +0x9981,0xE9DD,0x9982,0xE9DF,0xC3CA,0x9983,0x9984,0x9985, +0x9986,0x9987,0x9988,0x9989,0x998A,0x998B,0x998C,0x998D, +0x998E,0x998F,0x9990,0x9991,0x9992,0x9993,0x9994,0x9995, +0x9996,0x9997,0x9998,0x9999,0x999A,0x999B,0x999C,0x999D, +0x999E,0x999F,0x99A0,0x99A1,0x99A2,0x99A3,0x99A4,0x99A5, +0x99A6,0x99A7,0x99A8,0x99A9,0x99AA,0x99AB,0x99AC,0x99AD, +0x99AE,0x99AF,0x99B0,0x99B1,0x99B2,0x99B3,0x99B4,0x99B5, +0x99B6,0x99B7,0x99B8,0x99B9,0x99BA,0x99BB,0x99BC,0x99BD, +0x99BE,0x99BF,0x99C0,0x99C1,0x99C2,0x99C3,0x99C4,0x99C5, +0x99C6,0x99C7,0x99C8,0x99C9,0x99CA,0x99CB,0x99CC,0x99CD, +0x99CE,0x99CF,0x99D0,0x99D1,0x99D2,0x99D3,0x99D4,0x99D5, +0x99D6,0x99D7,0x99D8,0x99D9,0x99DA,0x99DB,0x99DC,0x99DD, +0x99DE,0x99DF,0x99E0,0x99E1,0x99E2,0x99E3,0x99E4,0x99E5, +0x99E6,0x99E7,0x99E8,0x99E9,0x99EA,0x99EB,0x99EC,0x99ED, +0x99EE,0x99EF,0x99F0,0x99F1,0x99F2,0x99F3,0x99F4,0x99F5, +0xC7B7,0xB4CE,0xBBB6,0xD0C0,0xECA3,0x99F6,0x99F7,0xC5B7, +0x99F8,0x99F9,0x99FA,0x99FB,0x99FC,0x99FD,0x99FE,0x9A40, +0x9A41,0x9A42,0xD3FB,0x9A43,0x9A44,0x9A45,0x9A46,0xECA4, +0x9A47,0xECA5,0xC6DB,0x9A48,0x9A49,0x9A4A,0xBFEE,0x9A4B, +0x9A4C,0x9A4D,0x9A4E,0xECA6,0x9A4F,0x9A50,0xECA7,0xD0AA, +0x9A51,0xC7B8,0x9A52,0x9A53,0xB8E8,0x9A54,0x9A55,0x9A56, +0x9A57,0x9A58,0x9A59,0x9A5A,0x9A5B,0x9A5C,0x9A5D,0x9A5E, +0x9A5F,0xECA8,0x9A60,0x9A61,0x9A62,0x9A63,0x9A64,0x9A65, +0x9A66,0x9A67,0xD6B9,0xD5FD,0xB4CB,0xB2BD,0xCEE4,0xC6E7, +0x9A68,0x9A69,0xCDE1,0x9A6A,0x9A6B,0x9A6C,0x9A6D,0x9A6E, +0x9A6F,0x9A70,0x9A71,0x9A72,0x9A73,0x9A74,0x9A75,0x9A76, +0x9A77,0xB4F5,0x9A78,0xCBC0,0xBCDF,0x9A79,0x9A7A,0x9A7B, +0x9A7C,0xE9E2,0xE9E3,0xD1EA,0xE9E5,0x9A7D,0xB4F9,0xE9E4, +0x9A7E,0xD1B3,0xCAE2,0xB2D0,0x9A80,0xE9E8,0x9A81,0x9A82, +0x9A83,0x9A84,0xE9E6,0xE9E7,0x9A85,0x9A86,0xD6B3,0x9A87, +0x9A88,0x9A89,0xE9E9,0xE9EA,0x9A8A,0x9A8B,0x9A8C,0x9A8D, +0x9A8E,0xE9EB,0x9A8F,0x9A90,0x9A91,0x9A92,0x9A93,0x9A94, +0x9A95,0x9A96,0xE9EC,0x9A97,0x9A98,0x9A99,0x9A9A,0x9A9B, +0x9A9C,0x9A9D,0x9A9E,0xECAF,0xC5B9,0xB6CE,0x9A9F,0xD2F3, +0x9AA0,0x9AA1,0x9AA2,0x9AA3,0x9AA4,0x9AA5,0x9AA6,0xB5EE, +0x9AA7,0xBBD9,0xECB1,0x9AA8,0x9AA9,0xD2E3,0x9AAA,0x9AAB, +0x9AAC,0x9AAD,0x9AAE,0xCEE3,0x9AAF,0xC4B8,0x9AB0,0xC3BF, +0x9AB1,0x9AB2,0xB6BE,0xD8B9,0xB1C8,0xB1CF,0xB1D1,0xC5FE, +0x9AB3,0xB1D0,0x9AB4,0xC3AB,0x9AB5,0x9AB6,0x9AB7,0x9AB8, +0x9AB9,0xD5B1,0x9ABA,0x9ABB,0x9ABC,0x9ABD,0x9ABE,0x9ABF, +0x9AC0,0x9AC1,0xEBA4,0xBAC1,0x9AC2,0x9AC3,0x9AC4,0xCCBA, +0x9AC5,0x9AC6,0x9AC7,0xEBA5,0x9AC8,0xEBA7,0x9AC9,0x9ACA, +0x9ACB,0xEBA8,0x9ACC,0x9ACD,0x9ACE,0xEBA6,0x9ACF,0x9AD0, +0x9AD1,0x9AD2,0x9AD3,0x9AD4,0x9AD5,0xEBA9,0xEBAB,0xEBAA, +0x9AD6,0x9AD7,0x9AD8,0x9AD9,0x9ADA,0xEBAC,0x9ADB,0xCACF, +0xD8B5,0xC3F1,0x9ADC,0xC3A5,0xC6F8,0xEBAD,0xC4CA,0x9ADD, +0xEBAE,0xEBAF,0xEBB0,0xB7D5,0x9ADE,0x9ADF,0x9AE0,0xB7FA, +0x9AE1,0xEBB1,0xC7E2,0x9AE2,0xEBB3,0x9AE3,0xBAA4,0xD1F5, +0xB0B1,0xEBB2,0xEBB4,0x9AE4,0x9AE5,0x9AE6,0xB5AA,0xC2C8, +0xC7E8,0x9AE7,0xEBB5,0x9AE8,0xCBAE,0xE3DF,0x9AE9,0x9AEA, +0xD3C0,0x9AEB,0x9AEC,0x9AED,0x9AEE,0xD9DB,0x9AEF,0x9AF0, +0xCDA1,0xD6AD,0xC7F3,0x9AF1,0x9AF2,0x9AF3,0xD9E0,0xBBE3, +0x9AF4,0xBABA,0xE3E2,0x9AF5,0x9AF6,0x9AF7,0x9AF8,0x9AF9, +0xCFAB,0x9AFA,0x9AFB,0x9AFC,0xE3E0,0xC9C7,0x9AFD,0xBAB9, +0x9AFE,0x9B40,0x9B41,0xD1B4,0xE3E1,0xC8EA,0xB9AF,0xBDAD, +0xB3D8,0xCEDB,0x9B42,0x9B43,0xCCC0,0x9B44,0x9B45,0x9B46, +0xE3E8,0xE3E9,0xCDF4,0x9B47,0x9B48,0x9B49,0x9B4A,0x9B4B, +0xCCAD,0x9B4C,0xBCB3,0x9B4D,0xE3EA,0x9B4E,0xE3EB,0x9B4F, +0x9B50,0xD0DA,0x9B51,0x9B52,0x9B53,0xC6FB,0xB7DA,0x9B54, +0x9B55,0xC7DF,0xD2CA,0xCED6,0x9B56,0xE3E4,0xE3EC,0x9B57, +0xC9F2,0xB3C1,0x9B58,0x9B59,0xE3E7,0x9B5A,0x9B5B,0xC6E3, +0xE3E5,0x9B5C,0x9B5D,0xEDB3,0xE3E6,0x9B5E,0x9B5F,0x9B60, +0x9B61,0xC9B3,0x9B62,0xC5E6,0x9B63,0x9B64,0x9B65,0xB9B5, +0x9B66,0xC3BB,0x9B67,0xE3E3,0xC5BD,0xC1A4,0xC2D9,0xB2D7, +0x9B68,0xE3ED,0xBBA6,0xC4AD,0x9B69,0xE3F0,0xBEDA,0x9B6A, +0x9B6B,0xE3FB,0xE3F5,0xBAD3,0x9B6C,0x9B6D,0x9B6E,0x9B6F, +0xB7D0,0xD3CD,0x9B70,0xD6CE,0xD5D3,0xB9C1,0xD5B4,0xD1D8, +0x9B71,0x9B72,0x9B73,0x9B74,0xD0B9,0xC7F6,0x9B75,0x9B76, +0x9B77,0xC8AA,0xB2B4,0x9B78,0xC3DA,0x9B79,0x9B7A,0x9B7B, +0xE3EE,0x9B7C,0x9B7D,0xE3FC,0xE3EF,0xB7A8,0xE3F7,0xE3F4, +0x9B7E,0x9B80,0x9B81,0xB7BA,0x9B82,0x9B83,0xC5A2,0x9B84, +0xE3F6,0xC5DD,0xB2A8,0xC6FC,0x9B85,0xC4E0,0x9B86,0x9B87, +0xD7A2,0x9B88,0xC0E1,0xE3F9,0x9B89,0x9B8A,0xE3FA,0xE3FD, +0xCCA9,0xE3F3,0x9B8B,0xD3BE,0x9B8C,0xB1C3,0xEDB4,0xE3F1, +0xE3F2,0x9B8D,0xE3F8,0xD0BA,0xC6C3,0xD4F3,0xE3FE,0x9B8E, +0x9B8F,0xBDE0,0x9B90,0x9B91,0xE4A7,0x9B92,0x9B93,0xE4A6, +0x9B94,0x9B95,0x9B96,0xD1F3,0xE4A3,0x9B97,0xE4A9,0x9B98, +0x9B99,0x9B9A,0xC8F7,0x9B9B,0x9B9C,0x9B9D,0x9B9E,0xCFB4, +0x9B9F,0xE4A8,0xE4AE,0xC2E5,0x9BA0,0x9BA1,0xB6B4,0x9BA2, +0x9BA3,0x9BA4,0x9BA5,0x9BA6,0x9BA7,0xBDF2,0x9BA8,0xE4A2, +0x9BA9,0x9BAA,0xBAE9,0xE4AA,0x9BAB,0x9BAC,0xE4AC,0x9BAD, +0x9BAE,0xB6FD,0xD6DE,0xE4B2,0x9BAF,0xE4AD,0x9BB0,0x9BB1, +0x9BB2,0xE4A1,0x9BB3,0xBBEE,0xCDDD,0xC7A2,0xC5C9,0x9BB4, +0x9BB5,0xC1F7,0x9BB6,0xE4A4,0x9BB7,0xC7B3,0xBDAC,0xBDBD, +0xE4A5,0x9BB8,0xD7C7,0xB2E2,0x9BB9,0xE4AB,0xBCC3,0xE4AF, +0x9BBA,0xBBEB,0xE4B0,0xC5A8,0xE4B1,0x9BBB,0x9BBC,0x9BBD, +0x9BBE,0xD5E3,0xBFA3,0x9BBF,0xE4BA,0x9BC0,0xE4B7,0x9BC1, +0xE4BB,0x9BC2,0x9BC3,0xE4BD,0x9BC4,0x9BC5,0xC6D6,0x9BC6, +0x9BC7,0xBAC6,0xC0CB,0x9BC8,0x9BC9,0x9BCA,0xB8A1,0xE4B4, +0x9BCB,0x9BCC,0x9BCD,0x9BCE,0xD4A1,0x9BCF,0x9BD0,0xBAA3, +0xBDFE,0x9BD1,0x9BD2,0x9BD3,0xE4BC,0x9BD4,0x9BD5,0x9BD6, +0x9BD7,0x9BD8,0xCDBF,0x9BD9,0x9BDA,0xC4F9,0x9BDB,0x9BDC, +0xCFFB,0xC9E6,0x9BDD,0x9BDE,0xD3BF,0x9BDF,0xCFD1,0x9BE0, +0x9BE1,0xE4B3,0x9BE2,0xE4B8,0xE4B9,0xCCE9,0x9BE3,0x9BE4, +0x9BE5,0x9BE6,0x9BE7,0xCCCE,0x9BE8,0xC0D4,0xE4B5,0xC1B0, +0xE4B6,0xCED0,0x9BE9,0xBBC1,0xB5D3,0x9BEA,0xC8F3,0xBDA7, +0xD5C7,0xC9AC,0xB8A2,0xE4CA,0x9BEB,0x9BEC,0xE4CC,0xD1C4, +0x9BED,0x9BEE,0xD2BA,0x9BEF,0x9BF0,0xBAAD,0x9BF1,0x9BF2, +0xBAD4,0x9BF3,0x9BF4,0x9BF5,0x9BF6,0x9BF7,0x9BF8,0xE4C3, +0xB5ED,0x9BF9,0x9BFA,0x9BFB,0xD7CD,0xE4C0,0xCFFD,0xE4BF, +0x9BFC,0x9BFD,0x9BFE,0xC1DC,0xCCCA,0x9C40,0x9C41,0x9C42, +0x9C43,0xCAE7,0x9C44,0x9C45,0x9C46,0x9C47,0xC4D7,0x9C48, +0xCCD4,0xE4C8,0x9C49,0x9C4A,0x9C4B,0xE4C7,0xE4C1,0x9C4C, +0xE4C4,0xB5AD,0x9C4D,0x9C4E,0xD3D9,0x9C4F,0xE4C6,0x9C50, +0x9C51,0x9C52,0x9C53,0xD2F9,0xB4E3,0x9C54,0xBBB4,0x9C55, +0x9C56,0xC9EE,0x9C57,0xB4BE,0x9C58,0x9C59,0x9C5A,0xBBEC, +0x9C5B,0xD1CD,0x9C5C,0xCCED,0xEDB5,0x9C5D,0x9C5E,0x9C5F, +0x9C60,0x9C61,0x9C62,0x9C63,0x9C64,0xC7E5,0x9C65,0x9C66, +0x9C67,0x9C68,0xD4A8,0x9C69,0xE4CB,0xD7D5,0xE4C2,0x9C6A, +0xBDA5,0xE4C5,0x9C6B,0x9C6C,0xD3E6,0x9C6D,0xE4C9,0xC9F8, +0x9C6E,0x9C6F,0xE4BE,0x9C70,0x9C71,0xD3E5,0x9C72,0x9C73, +0xC7FE,0xB6C9,0x9C74,0xD4FC,0xB2B3,0xE4D7,0x9C75,0x9C76, +0x9C77,0xCEC2,0x9C78,0xE4CD,0x9C79,0xCEBC,0x9C7A,0xB8DB, +0x9C7B,0x9C7C,0xE4D6,0x9C7D,0xBFCA,0x9C7E,0x9C80,0x9C81, +0xD3CE,0x9C82,0xC3EC,0x9C83,0x9C84,0x9C85,0x9C86,0x9C87, +0x9C88,0x9C89,0x9C8A,0xC5C8,0xE4D8,0x9C8B,0x9C8C,0x9C8D, +0x9C8E,0x9C8F,0x9C90,0x9C91,0x9C92,0xCDC4,0xE4CF,0x9C93, +0x9C94,0x9C95,0x9C96,0xE4D4,0xE4D5,0x9C97,0xBAFE,0x9C98, +0xCFE6,0x9C99,0x9C9A,0xD5BF,0x9C9B,0x9C9C,0x9C9D,0xE4D2, +0x9C9E,0x9C9F,0x9CA0,0x9CA1,0x9CA2,0x9CA3,0x9CA4,0x9CA5, +0x9CA6,0x9CA7,0x9CA8,0xE4D0,0x9CA9,0x9CAA,0xE4CE,0x9CAB, +0x9CAC,0x9CAD,0x9CAE,0x9CAF,0x9CB0,0x9CB1,0x9CB2,0x9CB3, +0x9CB4,0x9CB5,0x9CB6,0x9CB7,0x9CB8,0x9CB9,0xCDE5,0xCAAA, +0x9CBA,0x9CBB,0x9CBC,0xC0A3,0x9CBD,0xBDA6,0xE4D3,0x9CBE, +0x9CBF,0xB8C8,0x9CC0,0x9CC1,0x9CC2,0x9CC3,0x9CC4,0xE4E7, +0xD4B4,0x9CC5,0x9CC6,0x9CC7,0x9CC8,0x9CC9,0x9CCA,0x9CCB, +0xE4DB,0x9CCC,0x9CCD,0x9CCE,0xC1EF,0x9CCF,0x9CD0,0xE4E9, +0x9CD1,0x9CD2,0xD2E7,0x9CD3,0x9CD4,0xE4DF,0x9CD5,0xE4E0, +0x9CD6,0x9CD7,0xCFAA,0x9CD8,0x9CD9,0x9CDA,0x9CDB,0xCBDD, +0x9CDC,0xE4DA,0xE4D1,0x9CDD,0xE4E5,0x9CDE,0xC8DC,0xE4E3, +0x9CDF,0x9CE0,0xC4E7,0xE4E2,0x9CE1,0xE4E1,0x9CE2,0x9CE3, +0x9CE4,0xB3FC,0xE4E8,0x9CE5,0x9CE6,0x9CE7,0x9CE8,0xB5E1, +0x9CE9,0x9CEA,0x9CEB,0xD7CC,0x9CEC,0x9CED,0x9CEE,0xE4E6, +0x9CEF,0xBBAC,0x9CF0,0xD7D2,0xCCCF,0xEBF8,0x9CF1,0xE4E4, +0x9CF2,0x9CF3,0xB9F6,0x9CF4,0x9CF5,0x9CF6,0xD6CD,0xE4D9, +0xE4DC,0xC2FA,0xE4DE,0x9CF7,0xC2CB,0xC0C4,0xC2D0,0x9CF8, +0xB1F5,0xCCB2,0x9CF9,0x9CFA,0x9CFB,0x9CFC,0x9CFD,0x9CFE, +0x9D40,0x9D41,0x9D42,0x9D43,0xB5CE,0x9D44,0x9D45,0x9D46, +0x9D47,0xE4EF,0x9D48,0x9D49,0x9D4A,0x9D4B,0x9D4C,0x9D4D, +0x9D4E,0x9D4F,0xC6AF,0x9D50,0x9D51,0x9D52,0xC6E1,0x9D53, +0x9D54,0xE4F5,0x9D55,0x9D56,0x9D57,0x9D58,0x9D59,0xC2A9, +0x9D5A,0x9D5B,0x9D5C,0xC0EC,0xD1DD,0xE4EE,0x9D5D,0x9D5E, +0x9D5F,0x9D60,0x9D61,0x9D62,0x9D63,0x9D64,0x9D65,0x9D66, +0xC4AE,0x9D67,0x9D68,0x9D69,0xE4ED,0x9D6A,0x9D6B,0x9D6C, +0x9D6D,0xE4F6,0xE4F4,0xC2FE,0x9D6E,0xE4DD,0x9D6F,0xE4F0, +0x9D70,0xCAFE,0x9D71,0xD5C4,0x9D72,0x9D73,0xE4F1,0x9D74, +0x9D75,0x9D76,0x9D77,0x9D78,0x9D79,0x9D7A,0xD1FA,0x9D7B, +0x9D7C,0x9D7D,0x9D7E,0x9D80,0x9D81,0x9D82,0xE4EB,0xE4EC, +0x9D83,0x9D84,0x9D85,0xE4F2,0x9D86,0xCEAB,0x9D87,0x9D88, +0x9D89,0x9D8A,0x9D8B,0x9D8C,0x9D8D,0x9D8E,0x9D8F,0x9D90, +0xC5CB,0x9D91,0x9D92,0x9D93,0xC7B1,0x9D94,0xC2BA,0x9D95, +0x9D96,0x9D97,0xE4EA,0x9D98,0x9D99,0x9D9A,0xC1CA,0x9D9B, +0x9D9C,0x9D9D,0x9D9E,0x9D9F,0x9DA0,0xCCB6,0xB3B1,0x9DA1, +0x9DA2,0x9DA3,0xE4FB,0x9DA4,0xE4F3,0x9DA5,0x9DA6,0x9DA7, +0xE4FA,0x9DA8,0xE4FD,0x9DA9,0xE4FC,0x9DAA,0x9DAB,0x9DAC, +0x9DAD,0x9DAE,0x9DAF,0x9DB0,0xB3CE,0x9DB1,0x9DB2,0x9DB3, +0xB3BA,0xE4F7,0x9DB4,0x9DB5,0xE4F9,0xE4F8,0xC5EC,0x9DB6, +0x9DB7,0x9DB8,0x9DB9,0x9DBA,0x9DBB,0x9DBC,0x9DBD,0x9DBE, +0x9DBF,0x9DC0,0x9DC1,0x9DC2,0xC0BD,0x9DC3,0x9DC4,0x9DC5, +0x9DC6,0xD4E8,0x9DC7,0x9DC8,0x9DC9,0x9DCA,0x9DCB,0xE5A2, +0x9DCC,0x9DCD,0x9DCE,0x9DCF,0x9DD0,0x9DD1,0x9DD2,0x9DD3, +0x9DD4,0x9DD5,0x9DD6,0xB0C4,0x9DD7,0x9DD8,0xE5A4,0x9DD9, +0x9DDA,0xE5A3,0x9DDB,0x9DDC,0x9DDD,0x9DDE,0x9DDF,0x9DE0, +0xBCA4,0x9DE1,0xE5A5,0x9DE2,0x9DE3,0x9DE4,0x9DE5,0x9DE6, +0x9DE7,0xE5A1,0x9DE8,0x9DE9,0x9DEA,0x9DEB,0x9DEC,0x9DED, +0x9DEE,0xE4FE,0xB1F4,0x9DEF,0x9DF0,0x9DF1,0x9DF2,0x9DF3, +0x9DF4,0x9DF5,0x9DF6,0x9DF7,0x9DF8,0x9DF9,0xE5A8,0x9DFA, +0xE5A9,0xE5A6,0x9DFB,0x9DFC,0x9DFD,0x9DFE,0x9E40,0x9E41, +0x9E42,0x9E43,0x9E44,0x9E45,0x9E46,0x9E47,0xE5A7,0xE5AA, +0x9E48,0x9E49,0x9E4A,0x9E4B,0x9E4C,0x9E4D,0x9E4E,0x9E4F, +0x9E50,0x9E51,0x9E52,0x9E53,0x9E54,0x9E55,0x9E56,0x9E57, +0x9E58,0x9E59,0x9E5A,0x9E5B,0x9E5C,0x9E5D,0x9E5E,0x9E5F, +0x9E60,0x9E61,0x9E62,0x9E63,0x9E64,0x9E65,0x9E66,0x9E67, +0x9E68,0xC6D9,0x9E69,0x9E6A,0x9E6B,0x9E6C,0x9E6D,0x9E6E, +0x9E6F,0x9E70,0xE5AB,0xE5AD,0x9E71,0x9E72,0x9E73,0x9E74, +0x9E75,0x9E76,0x9E77,0xE5AC,0x9E78,0x9E79,0x9E7A,0x9E7B, +0x9E7C,0x9E7D,0x9E7E,0x9E80,0x9E81,0x9E82,0x9E83,0x9E84, +0x9E85,0x9E86,0x9E87,0x9E88,0x9E89,0xE5AF,0x9E8A,0x9E8B, +0x9E8C,0xE5AE,0x9E8D,0x9E8E,0x9E8F,0x9E90,0x9E91,0x9E92, +0x9E93,0x9E94,0x9E95,0x9E96,0x9E97,0x9E98,0x9E99,0x9E9A, +0x9E9B,0x9E9C,0x9E9D,0x9E9E,0xB9E0,0x9E9F,0x9EA0,0xE5B0, +0x9EA1,0x9EA2,0x9EA3,0x9EA4,0x9EA5,0x9EA6,0x9EA7,0x9EA8, +0x9EA9,0x9EAA,0x9EAB,0x9EAC,0x9EAD,0x9EAE,0xE5B1,0x9EAF, +0x9EB0,0x9EB1,0x9EB2,0x9EB3,0x9EB4,0x9EB5,0x9EB6,0x9EB7, +0x9EB8,0x9EB9,0x9EBA,0xBBF0,0xECE1,0xC3F0,0x9EBB,0xB5C6, +0xBBD2,0x9EBC,0x9EBD,0x9EBE,0x9EBF,0xC1E9,0xD4EE,0x9EC0, +0xBEC4,0x9EC1,0x9EC2,0x9EC3,0xD7C6,0x9EC4,0xD4D6,0xB2D3, +0xECBE,0x9EC5,0x9EC6,0x9EC7,0x9EC8,0xEAC1,0x9EC9,0x9ECA, +0x9ECB,0xC2AF,0xB4B6,0x9ECC,0x9ECD,0x9ECE,0xD1D7,0x9ECF, +0x9ED0,0x9ED1,0xB3B4,0x9ED2,0xC8B2,0xBFBB,0xECC0,0x9ED3, +0x9ED4,0xD6CB,0x9ED5,0x9ED6,0xECBF,0xECC1,0x9ED7,0x9ED8, +0x9ED9,0x9EDA,0x9EDB,0x9EDC,0x9EDD,0x9EDE,0x9EDF,0x9EE0, +0x9EE1,0x9EE2,0x9EE3,0xECC5,0xBEE6,0xCCBF,0xC5DA,0xBEBC, +0x9EE4,0xECC6,0x9EE5,0xB1FE,0x9EE6,0x9EE7,0x9EE8,0xECC4, +0xD5A8,0xB5E3,0x9EE9,0xECC2,0xC1B6,0xB3E3,0x9EEA,0x9EEB, +0xECC3,0xCBB8,0xC0C3,0xCCFE,0x9EEC,0x9EED,0x9EEE,0x9EEF, +0xC1D2,0x9EF0,0xECC8,0x9EF1,0x9EF2,0x9EF3,0x9EF4,0x9EF5, +0x9EF6,0x9EF7,0x9EF8,0x9EF9,0x9EFA,0x9EFB,0x9EFC,0x9EFD, +0xBAE6,0xC0D3,0x9EFE,0xD6F2,0x9F40,0x9F41,0x9F42,0xD1CC, +0x9F43,0x9F44,0x9F45,0x9F46,0xBFBE,0x9F47,0xB7B3,0xC9D5, +0xECC7,0xBBE2,0x9F48,0xCCCC,0xBDFD,0xC8C8,0x9F49,0xCFA9, +0x9F4A,0x9F4B,0x9F4C,0x9F4D,0x9F4E,0x9F4F,0x9F50,0xCDE9, +0x9F51,0xC5EB,0x9F52,0x9F53,0x9F54,0xB7E9,0x9F55,0x9F56, +0x9F57,0x9F58,0x9F59,0x9F5A,0x9F5B,0x9F5C,0x9F5D,0x9F5E, +0x9F5F,0xD1C9,0xBAB8,0x9F60,0x9F61,0x9F62,0x9F63,0x9F64, +0xECC9,0x9F65,0x9F66,0xECCA,0x9F67,0xBBC0,0xECCB,0x9F68, +0xECE2,0xB1BA,0xB7D9,0x9F69,0x9F6A,0x9F6B,0x9F6C,0x9F6D, +0x9F6E,0x9F6F,0x9F70,0x9F71,0x9F72,0x9F73,0xBDB9,0x9F74, +0x9F75,0x9F76,0x9F77,0x9F78,0x9F79,0x9F7A,0x9F7B,0xECCC, +0xD1E6,0xECCD,0x9F7C,0x9F7D,0x9F7E,0x9F80,0xC8BB,0x9F81, +0x9F82,0x9F83,0x9F84,0x9F85,0x9F86,0x9F87,0x9F88,0x9F89, +0x9F8A,0x9F8B,0x9F8C,0x9F8D,0x9F8E,0xECD1,0x9F8F,0x9F90, +0x9F91,0x9F92,0xECD3,0x9F93,0xBBCD,0x9F94,0xBCE5,0x9F95, +0x9F96,0x9F97,0x9F98,0x9F99,0x9F9A,0x9F9B,0x9F9C,0x9F9D, +0x9F9E,0x9F9F,0x9FA0,0x9FA1,0xECCF,0x9FA2,0xC9B7,0x9FA3, +0x9FA4,0x9FA5,0x9FA6,0x9FA7,0xC3BA,0x9FA8,0xECE3,0xD5D5, +0xECD0,0x9FA9,0x9FAA,0x9FAB,0x9FAC,0x9FAD,0xD6F3,0x9FAE, +0x9FAF,0x9FB0,0xECD2,0xECCE,0x9FB1,0x9FB2,0x9FB3,0x9FB4, +0xECD4,0x9FB5,0xECD5,0x9FB6,0x9FB7,0xC9BF,0x9FB8,0x9FB9, +0x9FBA,0x9FBB,0x9FBC,0x9FBD,0xCFA8,0x9FBE,0x9FBF,0x9FC0, +0x9FC1,0x9FC2,0xD0DC,0x9FC3,0x9FC4,0x9FC5,0x9FC6,0xD1AC, +0x9FC7,0x9FC8,0x9FC9,0x9FCA,0xC8DB,0x9FCB,0x9FCC,0x9FCD, +0xECD6,0xCEF5,0x9FCE,0x9FCF,0x9FD0,0x9FD1,0x9FD2,0xCAEC, +0xECDA,0x9FD3,0x9FD4,0x9FD5,0x9FD6,0x9FD7,0x9FD8,0x9FD9, +0xECD9,0x9FDA,0x9FDB,0x9FDC,0xB0BE,0x9FDD,0x9FDE,0x9FDF, +0x9FE0,0x9FE1,0x9FE2,0xECD7,0x9FE3,0xECD8,0x9FE4,0x9FE5, +0x9FE6,0xECE4,0x9FE7,0x9FE8,0x9FE9,0x9FEA,0x9FEB,0x9FEC, +0x9FED,0x9FEE,0x9FEF,0xC8BC,0x9FF0,0x9FF1,0x9FF2,0x9FF3, +0x9FF4,0x9FF5,0x9FF6,0x9FF7,0x9FF8,0x9FF9,0xC1C7,0x9FFA, +0x9FFB,0x9FFC,0x9FFD,0x9FFE,0xECDC,0xD1E0,0xA040,0xA041, +0xA042,0xA043,0xA044,0xA045,0xA046,0xA047,0xA048,0xA049, +0xECDB,0xA04A,0xA04B,0xA04C,0xA04D,0xD4EF,0xA04E,0xECDD, +0xA04F,0xA050,0xA051,0xA052,0xA053,0xA054,0xDBC6,0xA055, +0xA056,0xA057,0xA058,0xA059,0xA05A,0xA05B,0xA05C,0xA05D, +0xA05E,0xECDE,0xA05F,0xA060,0xA061,0xA062,0xA063,0xA064, +0xA065,0xA066,0xA067,0xA068,0xA069,0xA06A,0xB1AC,0xA06B, +0xA06C,0xA06D,0xA06E,0xA06F,0xA070,0xA071,0xA072,0xA073, +0xA074,0xA075,0xA076,0xA077,0xA078,0xA079,0xA07A,0xA07B, +0xA07C,0xA07D,0xA07E,0xA080,0xA081,0xECDF,0xA082,0xA083, +0xA084,0xA085,0xA086,0xA087,0xA088,0xA089,0xA08A,0xA08B, +0xECE0,0xA08C,0xD7A6,0xA08D,0xC5C0,0xA08E,0xA08F,0xA090, +0xEBBC,0xB0AE,0xA091,0xA092,0xA093,0xBEF4,0xB8B8,0xD2AF, +0xB0D6,0xB5F9,0xA094,0xD8B3,0xA095,0xCBAC,0xA096,0xE3DD, +0xA097,0xA098,0xA099,0xA09A,0xA09B,0xA09C,0xA09D,0xC6AC, +0xB0E6,0xA09E,0xA09F,0xA0A0,0xC5C6,0xEBB9,0xA0A1,0xA0A2, +0xA0A3,0xA0A4,0xEBBA,0xA0A5,0xA0A6,0xA0A7,0xEBBB,0xA0A8, +0xA0A9,0xD1C0,0xA0AA,0xC5A3,0xA0AB,0xEAF2,0xA0AC,0xC4B2, +0xA0AD,0xC4B5,0xC0CE,0xA0AE,0xA0AF,0xA0B0,0xEAF3,0xC4C1, +0xA0B1,0xCEEF,0xA0B2,0xA0B3,0xA0B4,0xA0B5,0xEAF0,0xEAF4, +0xA0B6,0xA0B7,0xC9FC,0xA0B8,0xA0B9,0xC7A3,0xA0BA,0xA0BB, +0xA0BC,0xCCD8,0xCEFE,0xA0BD,0xA0BE,0xA0BF,0xEAF5,0xEAF6, +0xCFAC,0xC0E7,0xA0C0,0xA0C1,0xEAF7,0xA0C2,0xA0C3,0xA0C4, +0xA0C5,0xA0C6,0xB6BF,0xEAF8,0xA0C7,0xEAF9,0xA0C8,0xEAFA, +0xA0C9,0xA0CA,0xEAFB,0xA0CB,0xA0CC,0xA0CD,0xA0CE,0xA0CF, +0xA0D0,0xA0D1,0xA0D2,0xA0D3,0xA0D4,0xA0D5,0xA0D6,0xEAF1, +0xA0D7,0xA0D8,0xA0D9,0xA0DA,0xA0DB,0xA0DC,0xA0DD,0xA0DE, +0xA0DF,0xA0E0,0xA0E1,0xA0E2,0xC8AE,0xE1EB,0xA0E3,0xB7B8, +0xE1EC,0xA0E4,0xA0E5,0xA0E6,0xE1ED,0xA0E7,0xD7B4,0xE1EE, +0xE1EF,0xD3CC,0xA0E8,0xA0E9,0xA0EA,0xA0EB,0xA0EC,0xA0ED, +0xA0EE,0xE1F1,0xBFF1,0xE1F0,0xB5D2,0xA0EF,0xA0F0,0xA0F1, +0xB1B7,0xA0F2,0xA0F3,0xA0F4,0xA0F5,0xE1F3,0xE1F2,0xA0F6, +0xBAFC,0xA0F7,0xE1F4,0xA0F8,0xA0F9,0xA0FA,0xA0FB,0xB9B7, +0xA0FC,0xBED1,0xA0FD,0xA0FE,0xAA40,0xAA41,0xC4FC,0xAA42, +0xBADD,0xBDC6,0xAA43,0xAA44,0xAA45,0xAA46,0xAA47,0xAA48, +0xE1F5,0xE1F7,0xAA49,0xAA4A,0xB6C0,0xCFC1,0xCAA8,0xE1F6, +0xD5F8,0xD3FC,0xE1F8,0xE1FC,0xE1F9,0xAA4B,0xAA4C,0xE1FA, +0xC0EA,0xAA4D,0xE1FE,0xE2A1,0xC0C7,0xAA4E,0xAA4F,0xAA50, +0xAA51,0xE1FB,0xAA52,0xE1FD,0xAA53,0xAA54,0xAA55,0xAA56, +0xAA57,0xAA58,0xE2A5,0xAA59,0xAA5A,0xAA5B,0xC1D4,0xAA5C, +0xAA5D,0xAA5E,0xAA5F,0xE2A3,0xAA60,0xE2A8,0xB2FE,0xE2A2, +0xAA61,0xAA62,0xAA63,0xC3CD,0xB2C2,0xE2A7,0xE2A6,0xAA64, +0xAA65,0xE2A4,0xE2A9,0xAA66,0xAA67,0xE2AB,0xAA68,0xAA69, +0xAA6A,0xD0C9,0xD6ED,0xC3A8,0xE2AC,0xAA6B,0xCFD7,0xAA6C, +0xAA6D,0xE2AE,0xAA6E,0xAA6F,0xBAEF,0xAA70,0xAA71,0xE9E0, +0xE2AD,0xE2AA,0xAA72,0xAA73,0xAA74,0xAA75,0xBBAB,0xD4B3, +0xAA76,0xAA77,0xAA78,0xAA79,0xAA7A,0xAA7B,0xAA7C,0xAA7D, +0xAA7E,0xAA80,0xAA81,0xAA82,0xAA83,0xE2B0,0xAA84,0xAA85, +0xE2AF,0xAA86,0xE9E1,0xAA87,0xAA88,0xAA89,0xAA8A,0xE2B1, +0xAA8B,0xAA8C,0xAA8D,0xAA8E,0xAA8F,0xAA90,0xAA91,0xAA92, +0xE2B2,0xAA93,0xAA94,0xAA95,0xAA96,0xAA97,0xAA98,0xAA99, +0xAA9A,0xAA9B,0xAA9C,0xAA9D,0xE2B3,0xCCA1,0xAA9E,0xE2B4, +0xAA9F,0xAAA0,0xAB40,0xAB41,0xAB42,0xAB43,0xAB44,0xAB45, +0xAB46,0xAB47,0xAB48,0xAB49,0xAB4A,0xAB4B,0xE2B5,0xAB4C, +0xAB4D,0xAB4E,0xAB4F,0xAB50,0xD0FE,0xAB51,0xAB52,0xC2CA, +0xAB53,0xD3F1,0xAB54,0xCDF5,0xAB55,0xAB56,0xE7E0,0xAB57, +0xAB58,0xE7E1,0xAB59,0xAB5A,0xAB5B,0xAB5C,0xBEC1,0xAB5D, +0xAB5E,0xAB5F,0xAB60,0xC2EA,0xAB61,0xAB62,0xAB63,0xE7E4, +0xAB64,0xAB65,0xE7E3,0xAB66,0xAB67,0xAB68,0xAB69,0xAB6A, +0xAB6B,0xCDE6,0xAB6C,0xC3B5,0xAB6D,0xAB6E,0xE7E2,0xBBB7, +0xCFD6,0xAB6F,0xC1E1,0xE7E9,0xAB70,0xAB71,0xAB72,0xE7E8, +0xAB73,0xAB74,0xE7F4,0xB2A3,0xAB75,0xAB76,0xAB77,0xAB78, +0xE7EA,0xAB79,0xE7E6,0xAB7A,0xAB7B,0xAB7C,0xAB7D,0xAB7E, +0xE7EC,0xE7EB,0xC9BA,0xAB80,0xAB81,0xD5E4,0xAB82,0xE7E5, +0xB7A9,0xE7E7,0xAB83,0xAB84,0xAB85,0xAB86,0xAB87,0xAB88, +0xAB89,0xE7EE,0xAB8A,0xAB8B,0xAB8C,0xAB8D,0xE7F3,0xAB8E, +0xD6E9,0xAB8F,0xAB90,0xAB91,0xAB92,0xE7ED,0xAB93,0xE7F2, +0xAB94,0xE7F1,0xAB95,0xAB96,0xAB97,0xB0E0,0xAB98,0xAB99, +0xAB9A,0xAB9B,0xE7F5,0xAB9C,0xAB9D,0xAB9E,0xAB9F,0xABA0, +0xAC40,0xAC41,0xAC42,0xAC43,0xAC44,0xAC45,0xAC46,0xAC47, +0xAC48,0xAC49,0xAC4A,0xC7F2,0xAC4B,0xC0C5,0xC0ED,0xAC4C, +0xAC4D,0xC1F0,0xE7F0,0xAC4E,0xAC4F,0xAC50,0xAC51,0xE7F6, +0xCBF6,0xAC52,0xAC53,0xAC54,0xAC55,0xAC56,0xAC57,0xAC58, +0xAC59,0xAC5A,0xE8A2,0xE8A1,0xAC5B,0xAC5C,0xAC5D,0xAC5E, +0xAC5F,0xAC60,0xD7C1,0xAC61,0xAC62,0xE7FA,0xE7F9,0xAC63, +0xE7FB,0xAC64,0xE7F7,0xAC65,0xE7FE,0xAC66,0xE7FD,0xAC67, +0xE7FC,0xAC68,0xAC69,0xC1D5,0xC7D9,0xC5FD,0xC5C3,0xAC6A, +0xAC6B,0xAC6C,0xAC6D,0xAC6E,0xC7ED,0xAC6F,0xAC70,0xAC71, +0xAC72,0xE8A3,0xAC73,0xAC74,0xAC75,0xAC76,0xAC77,0xAC78, +0xAC79,0xAC7A,0xAC7B,0xAC7C,0xAC7D,0xAC7E,0xAC80,0xAC81, +0xAC82,0xAC83,0xAC84,0xAC85,0xAC86,0xE8A6,0xAC87,0xE8A5, +0xAC88,0xE8A7,0xBAF7,0xE7F8,0xE8A4,0xAC89,0xC8F0,0xC9AA, +0xAC8A,0xAC8B,0xAC8C,0xAC8D,0xAC8E,0xAC8F,0xAC90,0xAC91, +0xAC92,0xAC93,0xAC94,0xAC95,0xAC96,0xE8A9,0xAC97,0xAC98, +0xB9E5,0xAC99,0xAC9A,0xAC9B,0xAC9C,0xAC9D,0xD1FE,0xE8A8, +0xAC9E,0xAC9F,0xACA0,0xAD40,0xAD41,0xAD42,0xE8AA,0xAD43, +0xE8AD,0xE8AE,0xAD44,0xC1A7,0xAD45,0xAD46,0xAD47,0xE8AF, +0xAD48,0xAD49,0xAD4A,0xE8B0,0xAD4B,0xAD4C,0xE8AC,0xAD4D, +0xE8B4,0xAD4E,0xAD4F,0xAD50,0xAD51,0xAD52,0xAD53,0xAD54, +0xAD55,0xAD56,0xAD57,0xAD58,0xE8AB,0xAD59,0xE8B1,0xAD5A, +0xAD5B,0xAD5C,0xAD5D,0xAD5E,0xAD5F,0xAD60,0xAD61,0xE8B5, +0xE8B2,0xE8B3,0xAD62,0xAD63,0xAD64,0xAD65,0xAD66,0xAD67, +0xAD68,0xAD69,0xAD6A,0xAD6B,0xAD6C,0xAD6D,0xAD6E,0xAD6F, +0xAD70,0xAD71,0xE8B7,0xAD72,0xAD73,0xAD74,0xAD75,0xAD76, +0xAD77,0xAD78,0xAD79,0xAD7A,0xAD7B,0xAD7C,0xAD7D,0xAD7E, +0xAD80,0xAD81,0xAD82,0xAD83,0xAD84,0xAD85,0xAD86,0xAD87, +0xAD88,0xAD89,0xE8B6,0xAD8A,0xAD8B,0xAD8C,0xAD8D,0xAD8E, +0xAD8F,0xAD90,0xAD91,0xAD92,0xB9CF,0xAD93,0xF0AC,0xAD94, +0xF0AD,0xAD95,0xC6B0,0xB0EA,0xC8BF,0xAD96,0xCDDF,0xAD97, +0xAD98,0xAD99,0xAD9A,0xAD9B,0xAD9C,0xAD9D,0xCECD,0xEAB1, +0xAD9E,0xAD9F,0xADA0,0xAE40,0xEAB2,0xAE41,0xC6BF,0xB4C9, +0xAE42,0xAE43,0xAE44,0xAE45,0xAE46,0xAE47,0xAE48,0xEAB3, +0xAE49,0xAE4A,0xAE4B,0xAE4C,0xD5E7,0xAE4D,0xAE4E,0xAE4F, +0xAE50,0xAE51,0xAE52,0xAE53,0xAE54,0xDDF9,0xAE55,0xEAB4, +0xAE56,0xEAB5,0xAE57,0xEAB6,0xAE58,0xAE59,0xAE5A,0xAE5B, +0xB8CA,0xDFB0,0xC9F5,0xAE5C,0xCCF0,0xAE5D,0xAE5E,0xC9FA, +0xAE5F,0xAE60,0xAE61,0xAE62,0xAE63,0xC9FB,0xAE64,0xAE65, +0xD3C3,0xCBA6,0xAE66,0xB8A6,0xF0AE,0xB1C2,0xAE67,0xE5B8, +0xCCEF,0xD3C9,0xBCD7,0xC9EA,0xAE68,0xB5E7,0xAE69,0xC4D0, +0xB5E9,0xAE6A,0xEEAE,0xBBAD,0xAE6B,0xAE6C,0xE7DE,0xAE6D, +0xEEAF,0xAE6E,0xAE6F,0xAE70,0xAE71,0xB3A9,0xAE72,0xAE73, +0xEEB2,0xAE74,0xAE75,0xEEB1,0xBDE7,0xAE76,0xEEB0,0xCEB7, +0xAE77,0xAE78,0xAE79,0xAE7A,0xC5CF,0xAE7B,0xAE7C,0xAE7D, +0xAE7E,0xC1F4,0xDBCE,0xEEB3,0xD0F3,0xAE80,0xAE81,0xAE82, +0xAE83,0xAE84,0xAE85,0xAE86,0xAE87,0xC2D4,0xC6E8,0xAE88, +0xAE89,0xAE8A,0xB7AC,0xAE8B,0xAE8C,0xAE8D,0xAE8E,0xAE8F, +0xAE90,0xAE91,0xEEB4,0xAE92,0xB3EB,0xAE93,0xAE94,0xAE95, +0xBBFB,0xEEB5,0xAE96,0xAE97,0xAE98,0xAE99,0xAE9A,0xE7DC, +0xAE9B,0xAE9C,0xAE9D,0xEEB6,0xAE9E,0xAE9F,0xBDAE,0xAEA0, +0xAF40,0xAF41,0xAF42,0xF1E2,0xAF43,0xAF44,0xAF45,0xCAE8, +0xAF46,0xD2C9,0xF0DA,0xAF47,0xF0DB,0xAF48,0xF0DC,0xC1C6, +0xAF49,0xB8ED,0xBECE,0xAF4A,0xAF4B,0xF0DE,0xAF4C,0xC5B1, +0xF0DD,0xD1F1,0xAF4D,0xF0E0,0xB0CC,0xBDEA,0xAF4E,0xAF4F, +0xAF50,0xAF51,0xAF52,0xD2DF,0xF0DF,0xAF53,0xB4AF,0xB7E8, +0xF0E6,0xF0E5,0xC6A3,0xF0E1,0xF0E2,0xB4C3,0xAF54,0xAF55, +0xF0E3,0xD5EE,0xAF56,0xAF57,0xCCDB,0xBED2,0xBCB2,0xAF58, +0xAF59,0xAF5A,0xF0E8,0xF0E7,0xF0E4,0xB2A1,0xAF5B,0xD6A2, +0xD3B8,0xBEB7,0xC8AC,0xAF5C,0xAF5D,0xF0EA,0xAF5E,0xAF5F, +0xAF60,0xAF61,0xD1F7,0xAF62,0xD6CC,0xBADB,0xF0E9,0xAF63, +0xB6BB,0xAF64,0xAF65,0xCDB4,0xAF66,0xAF67,0xC6A6,0xAF68, +0xAF69,0xAF6A,0xC1A1,0xF0EB,0xF0EE,0xAF6B,0xF0ED,0xF0F0, +0xF0EC,0xAF6C,0xBBBE,0xF0EF,0xAF6D,0xAF6E,0xAF6F,0xAF70, +0xCCB5,0xF0F2,0xAF71,0xAF72,0xB3D5,0xAF73,0xAF74,0xAF75, +0xAF76,0xB1D4,0xAF77,0xAF78,0xF0F3,0xAF79,0xAF7A,0xF0F4, +0xF0F6,0xB4E1,0xAF7B,0xF0F1,0xAF7C,0xF0F7,0xAF7D,0xAF7E, +0xAF80,0xAF81,0xF0FA,0xAF82,0xF0F8,0xAF83,0xAF84,0xAF85, +0xF0F5,0xAF86,0xAF87,0xAF88,0xAF89,0xF0FD,0xAF8A,0xF0F9, +0xF0FC,0xF0FE,0xAF8B,0xF1A1,0xAF8C,0xAF8D,0xAF8E,0xCEC1, +0xF1A4,0xAF8F,0xF1A3,0xAF90,0xC1F6,0xF0FB,0xCADD,0xAF91, +0xAF92,0xB4F1,0xB1F1,0xCCB1,0xAF93,0xF1A6,0xAF94,0xAF95, +0xF1A7,0xAF96,0xAF97,0xF1AC,0xD5CE,0xF1A9,0xAF98,0xAF99, +0xC8B3,0xAF9A,0xAF9B,0xAF9C,0xF1A2,0xAF9D,0xF1AB,0xF1A8, +0xF1A5,0xAF9E,0xAF9F,0xF1AA,0xAFA0,0xB040,0xB041,0xB042, +0xB043,0xB044,0xB045,0xB046,0xB0A9,0xF1AD,0xB047,0xB048, +0xB049,0xB04A,0xB04B,0xB04C,0xF1AF,0xB04D,0xF1B1,0xB04E, +0xB04F,0xB050,0xB051,0xB052,0xF1B0,0xB053,0xF1AE,0xB054, +0xB055,0xB056,0xB057,0xD1A2,0xB058,0xB059,0xB05A,0xB05B, +0xB05C,0xB05D,0xB05E,0xF1B2,0xB05F,0xB060,0xB061,0xF1B3, +0xB062,0xB063,0xB064,0xB065,0xB066,0xB067,0xB068,0xB069, +0xB9EF,0xB06A,0xB06B,0xB5C7,0xB06C,0xB0D7,0xB0D9,0xB06D, +0xB06E,0xB06F,0xD4ED,0xB070,0xB5C4,0xB071,0xBDD4,0xBBCA, +0xF0A7,0xB072,0xB073,0xB8DE,0xB074,0xB075,0xF0A8,0xB076, +0xB077,0xB0A8,0xB078,0xF0A9,0xB079,0xB07A,0xCDEE,0xB07B, +0xB07C,0xF0AA,0xB07D,0xB07E,0xB080,0xB081,0xB082,0xB083, +0xB084,0xB085,0xB086,0xB087,0xF0AB,0xB088,0xB089,0xB08A, +0xB08B,0xB08C,0xB08D,0xB08E,0xB08F,0xB090,0xC6A4,0xB091, +0xB092,0xD6E5,0xF1E4,0xB093,0xF1E5,0xB094,0xB095,0xB096, +0xB097,0xB098,0xB099,0xB09A,0xB09B,0xB09C,0xB09D,0xC3F3, +0xB09E,0xB09F,0xD3DB,0xB0A0,0xB140,0xD6D1,0xC5E8,0xB141, +0xD3AF,0xB142,0xD2E6,0xB143,0xB144,0xEEC1,0xB0BB,0xD5B5, +0xD1CE,0xBCE0,0xBAD0,0xB145,0xBFF8,0xB146,0xB8C7,0xB5C1, +0xC5CC,0xB147,0xB148,0xCAA2,0xB149,0xB14A,0xB14B,0xC3CB, +0xB14C,0xB14D,0xB14E,0xB14F,0xB150,0xEEC2,0xB151,0xB152, +0xB153,0xB154,0xB155,0xB156,0xB157,0xB158,0xC4BF,0xB6A2, +0xB159,0xEDEC,0xC3A4,0xB15A,0xD6B1,0xB15B,0xB15C,0xB15D, +0xCFE0,0xEDEF,0xB15E,0xB15F,0xC5CE,0xB160,0xB6DC,0xB161, +0xB162,0xCAA1,0xB163,0xB164,0xEDED,0xB165,0xB166,0xEDF0, +0xEDF1,0xC3BC,0xB167,0xBFB4,0xB168,0xEDEE,0xB169,0xB16A, +0xB16B,0xB16C,0xB16D,0xB16E,0xB16F,0xB170,0xB171,0xB172, +0xB173,0xEDF4,0xEDF2,0xB174,0xB175,0xB176,0xB177,0xD5E6, +0xC3DF,0xB178,0xEDF3,0xB179,0xB17A,0xB17B,0xEDF6,0xB17C, +0xD5A3,0xD1A3,0xB17D,0xB17E,0xB180,0xEDF5,0xB181,0xC3D0, +0xB182,0xB183,0xB184,0xB185,0xB186,0xEDF7,0xBFF4,0xBEEC, +0xEDF8,0xB187,0xCCF7,0xB188,0xD1DB,0xB189,0xB18A,0xB18B, +0xD7C5,0xD5F6,0xB18C,0xEDFC,0xB18D,0xB18E,0xB18F,0xEDFB, +0xB190,0xB191,0xB192,0xB193,0xB194,0xB195,0xB196,0xB197, +0xEDF9,0xEDFA,0xB198,0xB199,0xB19A,0xB19B,0xB19C,0xB19D, +0xB19E,0xB19F,0xEDFD,0xBEA6,0xB1A0,0xB240,0xB241,0xB242, +0xB243,0xCBAF,0xEEA1,0xB6BD,0xB244,0xEEA2,0xC4C0,0xB245, +0xEDFE,0xB246,0xB247,0xBDDE,0xB2C7,0xB248,0xB249,0xB24A, +0xB24B,0xB24C,0xB24D,0xB24E,0xB24F,0xB250,0xB251,0xB252, +0xB253,0xB6C3,0xB254,0xB255,0xB256,0xEEA5,0xD8BA,0xEEA3, +0xEEA6,0xB257,0xB258,0xB259,0xC3E9,0xB3F2,0xB25A,0xB25B, +0xB25C,0xB25D,0xB25E,0xB25F,0xEEA7,0xEEA4,0xCFB9,0xB260, +0xB261,0xEEA8,0xC2F7,0xB262,0xB263,0xB264,0xB265,0xB266, +0xB267,0xB268,0xB269,0xB26A,0xB26B,0xB26C,0xB26D,0xEEA9, +0xEEAA,0xB26E,0xDEAB,0xB26F,0xB270,0xC6B3,0xB271,0xC7C6, +0xB272,0xD6F5,0xB5C9,0xB273,0xCBB2,0xB274,0xB275,0xB276, +0xEEAB,0xB277,0xB278,0xCDAB,0xB279,0xEEAC,0xB27A,0xB27B, +0xB27C,0xB27D,0xB27E,0xD5B0,0xB280,0xEEAD,0xB281,0xF6C4, +0xB282,0xB283,0xB284,0xB285,0xB286,0xB287,0xB288,0xB289, +0xB28A,0xB28B,0xB28C,0xB28D,0xB28E,0xDBC7,0xB28F,0xB290, +0xB291,0xB292,0xB293,0xB294,0xB295,0xB296,0xB297,0xB4A3, +0xB298,0xB299,0xB29A,0xC3AC,0xF1E6,0xB29B,0xB29C,0xB29D, +0xB29E,0xB29F,0xCAB8,0xD2D3,0xB2A0,0xD6AA,0xB340,0xEFF2, +0xB341,0xBED8,0xB342,0xBDC3,0xEFF3,0xB6CC,0xB0AB,0xB343, +0xB344,0xB345,0xB346,0xCAAF,0xB347,0xB348,0xEDB6,0xB349, +0xEDB7,0xB34A,0xB34B,0xB34C,0xB34D,0xCEF9,0xB7AF,0xBFF3, +0xEDB8,0xC2EB,0xC9B0,0xB34E,0xB34F,0xB350,0xB351,0xB352, +0xB353,0xEDB9,0xB354,0xB355,0xC6F6,0xBFB3,0xB356,0xB357, +0xB358,0xEDBC,0xC5F8,0xB359,0xD1D0,0xB35A,0xD7A9,0xEDBA, +0xEDBB,0xB35B,0xD1E2,0xB35C,0xEDBF,0xEDC0,0xB35D,0xEDC4, +0xB35E,0xB35F,0xB360,0xEDC8,0xB361,0xEDC6,0xEDCE,0xD5E8, +0xB362,0xEDC9,0xB363,0xB364,0xEDC7,0xEDBE,0xB365,0xB366, +0xC5E9,0xB367,0xB368,0xB369,0xC6C6,0xB36A,0xB36B,0xC9E9, +0xD4D2,0xEDC1,0xEDC2,0xEDC3,0xEDC5,0xB36C,0xC0F9,0xB36D, +0xB4A1,0xB36E,0xB36F,0xB370,0xB371,0xB9E8,0xB372,0xEDD0, +0xB373,0xB374,0xB375,0xB376,0xEDD1,0xB377,0xEDCA,0xB378, +0xEDCF,0xB379,0xCEF8,0xB37A,0xB37B,0xCBB6,0xEDCC,0xEDCD, +0xB37C,0xB37D,0xB37E,0xB380,0xB381,0xCFF5,0xB382,0xB383, +0xB384,0xB385,0xB386,0xB387,0xB388,0xB389,0xB38A,0xB38B, +0xB38C,0xB38D,0xEDD2,0xC1F2,0xD3B2,0xEDCB,0xC8B7,0xB38E, +0xB38F,0xB390,0xB391,0xB392,0xB393,0xB394,0xB395,0xBCEF, +0xB396,0xB397,0xB398,0xB399,0xC5F0,0xB39A,0xB39B,0xB39C, +0xB39D,0xB39E,0xB39F,0xB3A0,0xB440,0xB441,0xB442,0xEDD6, +0xB443,0xB5EF,0xB444,0xB445,0xC2B5,0xB0AD,0xCBE9,0xB446, +0xB447,0xB1AE,0xB448,0xEDD4,0xB449,0xB44A,0xB44B,0xCDEB, +0xB5E2,0xB44C,0xEDD5,0xEDD3,0xEDD7,0xB44D,0xB44E,0xB5FA, +0xB44F,0xEDD8,0xB450,0xEDD9,0xB451,0xEDDC,0xB452,0xB1CC, +0xB453,0xB454,0xB455,0xB456,0xB457,0xB458,0xB459,0xB45A, +0xC5F6,0xBCEE,0xEDDA,0xCCBC,0xB2EA,0xB45B,0xB45C,0xB45D, +0xB45E,0xEDDB,0xB45F,0xB460,0xB461,0xB462,0xC4EB,0xB463, +0xB464,0xB4C5,0xB465,0xB466,0xB467,0xB0F5,0xB468,0xB469, +0xB46A,0xEDDF,0xC0DA,0xB4E8,0xB46B,0xB46C,0xB46D,0xB46E, +0xC5CD,0xB46F,0xB470,0xB471,0xEDDD,0xBFC4,0xB472,0xB473, +0xB474,0xEDDE,0xB475,0xB476,0xB477,0xB478,0xB479,0xB47A, +0xB47B,0xB47C,0xB47D,0xB47E,0xB480,0xB481,0xB482,0xB483, +0xC4A5,0xB484,0xB485,0xB486,0xEDE0,0xB487,0xB488,0xB489, +0xB48A,0xB48B,0xEDE1,0xB48C,0xEDE3,0xB48D,0xB48E,0xC1D7, +0xB48F,0xB490,0xBBC7,0xB491,0xB492,0xB493,0xB494,0xB495, +0xB496,0xBDB8,0xB497,0xB498,0xB499,0xEDE2,0xB49A,0xB49B, +0xB49C,0xB49D,0xB49E,0xB49F,0xB4A0,0xB540,0xB541,0xB542, +0xB543,0xB544,0xB545,0xEDE4,0xB546,0xB547,0xB548,0xB549, +0xB54A,0xB54B,0xB54C,0xB54D,0xB54E,0xB54F,0xEDE6,0xB550, +0xB551,0xB552,0xB553,0xB554,0xEDE5,0xB555,0xB556,0xB557, +0xB558,0xB559,0xB55A,0xB55B,0xB55C,0xB55D,0xB55E,0xB55F, +0xB560,0xB561,0xB562,0xB563,0xEDE7,0xB564,0xB565,0xB566, +0xB567,0xB568,0xCABE,0xECEA,0xC0F1,0xB569,0xC9E7,0xB56A, +0xECEB,0xC6EE,0xB56B,0xB56C,0xB56D,0xB56E,0xECEC,0xB56F, +0xC6ED,0xECED,0xB570,0xB571,0xB572,0xB573,0xB574,0xB575, +0xB576,0xB577,0xB578,0xECF0,0xB579,0xB57A,0xD7E6,0xECF3, +0xB57B,0xB57C,0xECF1,0xECEE,0xECEF,0xD7A3,0xC9F1,0xCBEE, +0xECF4,0xB57D,0xECF2,0xB57E,0xB580,0xCFE9,0xB581,0xECF6, +0xC6B1,0xB582,0xB583,0xB584,0xB585,0xBCC0,0xB586,0xECF5, +0xB587,0xB588,0xB589,0xB58A,0xB58B,0xB58C,0xB58D,0xB5BB, +0xBBF6,0xB58E,0xECF7,0xB58F,0xB590,0xB591,0xB592,0xB593, +0xD9F7,0xBDFB,0xB594,0xB595,0xC2BB,0xECF8,0xB596,0xB597, +0xB598,0xB599,0xECF9,0xB59A,0xB59B,0xB59C,0xB59D,0xB8A3, +0xB59E,0xB59F,0xB5A0,0xB640,0xB641,0xB642,0xB643,0xB644, +0xB645,0xB646,0xECFA,0xB647,0xB648,0xB649,0xB64A,0xB64B, +0xB64C,0xB64D,0xB64E,0xB64F,0xB650,0xB651,0xB652,0xECFB, +0xB653,0xB654,0xB655,0xB656,0xB657,0xB658,0xB659,0xB65A, +0xB65B,0xB65C,0xB65D,0xECFC,0xB65E,0xB65F,0xB660,0xB661, +0xB662,0xD3ED,0xD8AE,0xC0EB,0xB663,0xC7DD,0xBACC,0xB664, +0xD0E3,0xCBBD,0xB665,0xCDBA,0xB666,0xB667,0xB8D1,0xB668, +0xB669,0xB1FC,0xB66A,0xC7EF,0xB66B,0xD6D6,0xB66C,0xB66D, +0xB66E,0xBFC6,0xC3EB,0xB66F,0xB670,0xEFF5,0xB671,0xB672, +0xC3D8,0xB673,0xB674,0xB675,0xB676,0xB677,0xB678,0xD7E2, +0xB679,0xB67A,0xB67B,0xEFF7,0xB3D3,0xB67C,0xC7D8,0xD1ED, +0xB67D,0xD6C8,0xB67E,0xEFF8,0xB680,0xEFF6,0xB681,0xBBFD, +0xB3C6,0xB682,0xB683,0xB684,0xB685,0xB686,0xB687,0xB688, +0xBDD5,0xB689,0xB68A,0xD2C6,0xB68B,0xBBE0,0xB68C,0xB68D, +0xCFA1,0xB68E,0xEFFC,0xEFFB,0xB68F,0xB690,0xEFF9,0xB691, +0xB692,0xB693,0xB694,0xB3CC,0xB695,0xC9D4,0xCBB0,0xB696, +0xB697,0xB698,0xB699,0xB69A,0xEFFE,0xB69B,0xB69C,0xB0DE, +0xB69D,0xB69E,0xD6C9,0xB69F,0xB6A0,0xB740,0xEFFD,0xB741, +0xB3ED,0xB742,0xB743,0xF6D5,0xB744,0xB745,0xB746,0xB747, +0xB748,0xB749,0xB74A,0xB74B,0xB74C,0xB74D,0xB74E,0xB74F, +0xB750,0xB751,0xB752,0xCEC8,0xB753,0xB754,0xB755,0xF0A2, +0xB756,0xF0A1,0xB757,0xB5BE,0xBCDA,0xBBFC,0xB758,0xB8E5, +0xB759,0xB75A,0xB75B,0xB75C,0xB75D,0xB75E,0xC4C2,0xB75F, +0xB760,0xB761,0xB762,0xB763,0xB764,0xB765,0xB766,0xB767, +0xB768,0xF0A3,0xB769,0xB76A,0xB76B,0xB76C,0xB76D,0xCBEB, +0xB76E,0xB76F,0xB770,0xB771,0xB772,0xB773,0xB774,0xB775, +0xB776,0xB777,0xB778,0xB779,0xB77A,0xB77B,0xB77C,0xB77D, +0xB77E,0xB780,0xB781,0xB782,0xB783,0xB784,0xB785,0xB786, +0xF0A6,0xB787,0xB788,0xB789,0xD1A8,0xB78A,0xBEBF,0xC7EE, +0xF1B6,0xF1B7,0xBFD5,0xB78B,0xB78C,0xB78D,0xB78E,0xB4A9, +0xF1B8,0xCDBB,0xB78F,0xC7D4,0xD5AD,0xB790,0xF1B9,0xB791, +0xF1BA,0xB792,0xB793,0xB794,0xB795,0xC7CF,0xB796,0xB797, +0xB798,0xD2A4,0xD6CF,0xB799,0xB79A,0xF1BB,0xBDD1,0xB4B0, +0xBEBD,0xB79B,0xB79C,0xB79D,0xB4DC,0xCED1,0xB79E,0xBFDF, +0xF1BD,0xB79F,0xB7A0,0xB840,0xB841,0xBFFA,0xF1BC,0xB842, +0xF1BF,0xB843,0xB844,0xB845,0xF1BE,0xF1C0,0xB846,0xB847, +0xB848,0xB849,0xB84A,0xF1C1,0xB84B,0xB84C,0xB84D,0xB84E, +0xB84F,0xB850,0xB851,0xB852,0xB853,0xB854,0xB855,0xC1FE, +0xB856,0xB857,0xB858,0xB859,0xB85A,0xB85B,0xB85C,0xB85D, +0xB85E,0xB85F,0xB860,0xC1A2,0xB861,0xB862,0xB863,0xB864, +0xB865,0xB866,0xB867,0xB868,0xB869,0xB86A,0xCAFA,0xB86B, +0xB86C,0xD5BE,0xB86D,0xB86E,0xB86F,0xB870,0xBEBA,0xBEB9, +0xD5C2,0xB871,0xB872,0xBFA2,0xB873,0xCDAF,0xF1B5,0xB874, +0xB875,0xB876,0xB877,0xB878,0xB879,0xBDDF,0xB87A,0xB6CB, +0xB87B,0xB87C,0xB87D,0xB87E,0xB880,0xB881,0xB882,0xB883, +0xB884,0xD6F1,0xF3C3,0xB885,0xB886,0xF3C4,0xB887,0xB8CD, +0xB888,0xB889,0xB88A,0xF3C6,0xF3C7,0xB88B,0xB0CA,0xB88C, +0xF3C5,0xB88D,0xF3C9,0xCBF1,0xB88E,0xB88F,0xB890,0xF3CB, +0xB891,0xD0A6,0xB892,0xB893,0xB1CA,0xF3C8,0xB894,0xB895, +0xB896,0xF3CF,0xB897,0xB5D1,0xB898,0xB899,0xF3D7,0xB89A, +0xF3D2,0xB89B,0xB89C,0xB89D,0xF3D4,0xF3D3,0xB7FB,0xB89E, +0xB1BF,0xB89F,0xF3CE,0xF3CA,0xB5DA,0xB8A0,0xF3D0,0xB940, +0xB941,0xF3D1,0xB942,0xF3D5,0xB943,0xB944,0xB945,0xB946, +0xF3CD,0xB947,0xBCE3,0xB948,0xC1FD,0xB949,0xF3D6,0xB94A, +0xB94B,0xB94C,0xB94D,0xB94E,0xB94F,0xF3DA,0xB950,0xF3CC, +0xB951,0xB5C8,0xB952,0xBDEE,0xF3DC,0xB953,0xB954,0xB7A4, +0xBFF0,0xD6FE,0xCDB2,0xB955,0xB4F0,0xB956,0xB2DF,0xB957, +0xF3D8,0xB958,0xF3D9,0xC9B8,0xB959,0xF3DD,0xB95A,0xB95B, +0xF3DE,0xB95C,0xF3E1,0xB95D,0xB95E,0xB95F,0xB960,0xB961, +0xB962,0xB963,0xB964,0xB965,0xB966,0xB967,0xF3DF,0xB968, +0xB969,0xF3E3,0xF3E2,0xB96A,0xB96B,0xF3DB,0xB96C,0xBFEA, +0xB96D,0xB3EF,0xB96E,0xF3E0,0xB96F,0xB970,0xC7A9,0xB971, +0xBCF2,0xB972,0xB973,0xB974,0xB975,0xF3EB,0xB976,0xB977, +0xB978,0xB979,0xB97A,0xB97B,0xB97C,0xB9BF,0xB97D,0xB97E, +0xF3E4,0xB980,0xB981,0xB982,0xB2AD,0xBBFE,0xB983,0xCBE3, +0xB984,0xB985,0xB986,0xB987,0xF3ED,0xF3E9,0xB988,0xB989, +0xB98A,0xB9DC,0xF3EE,0xB98B,0xB98C,0xB98D,0xF3E5,0xF3E6, +0xF3EA,0xC2E1,0xF3EC,0xF3EF,0xF3E8,0xBCFD,0xB98E,0xB98F, +0xB990,0xCFE4,0xB991,0xB992,0xF3F0,0xB993,0xB994,0xB995, +0xF3E7,0xB996,0xB997,0xB998,0xB999,0xB99A,0xB99B,0xB99C, +0xB99D,0xF3F2,0xB99E,0xB99F,0xB9A0,0xBA40,0xD7AD,0xC6AA, +0xBA41,0xBA42,0xBA43,0xBA44,0xF3F3,0xBA45,0xBA46,0xBA47, +0xBA48,0xF3F1,0xBA49,0xC2A8,0xBA4A,0xBA4B,0xBA4C,0xBA4D, +0xBA4E,0xB8DD,0xF3F5,0xBA4F,0xBA50,0xF3F4,0xBA51,0xBA52, +0xBA53,0xB4DB,0xBA54,0xBA55,0xBA56,0xF3F6,0xF3F7,0xBA57, +0xBA58,0xBA59,0xF3F8,0xBA5A,0xBA5B,0xBA5C,0xC0BA,0xBA5D, +0xBA5E,0xC0E9,0xBA5F,0xBA60,0xBA61,0xBA62,0xBA63,0xC5F1, +0xBA64,0xBA65,0xBA66,0xBA67,0xF3FB,0xBA68,0xF3FA,0xBA69, +0xBA6A,0xBA6B,0xBA6C,0xBA6D,0xBA6E,0xBA6F,0xBA70,0xB4D8, +0xBA71,0xBA72,0xBA73,0xF3FE,0xF3F9,0xBA74,0xBA75,0xF3FC, +0xBA76,0xBA77,0xBA78,0xBA79,0xBA7A,0xBA7B,0xF3FD,0xBA7C, +0xBA7D,0xBA7E,0xBA80,0xBA81,0xBA82,0xBA83,0xBA84,0xF4A1, +0xBA85,0xBA86,0xBA87,0xBA88,0xBA89,0xBA8A,0xF4A3,0xBBC9, +0xBA8B,0xBA8C,0xF4A2,0xBA8D,0xBA8E,0xBA8F,0xBA90,0xBA91, +0xBA92,0xBA93,0xBA94,0xBA95,0xBA96,0xBA97,0xBA98,0xBA99, +0xF4A4,0xBA9A,0xBA9B,0xBA9C,0xBA9D,0xBA9E,0xBA9F,0xB2BE, +0xF4A6,0xF4A5,0xBAA0,0xBB40,0xBB41,0xBB42,0xBB43,0xBB44, +0xBB45,0xBB46,0xBB47,0xBB48,0xBB49,0xBCAE,0xBB4A,0xBB4B, +0xBB4C,0xBB4D,0xBB4E,0xBB4F,0xBB50,0xBB51,0xBB52,0xBB53, +0xBB54,0xBB55,0xBB56,0xBB57,0xBB58,0xBB59,0xBB5A,0xBB5B, +0xBB5C,0xBB5D,0xBB5E,0xBB5F,0xBB60,0xBB61,0xBB62,0xBB63, +0xBB64,0xBB65,0xBB66,0xBB67,0xBB68,0xBB69,0xBB6A,0xBB6B, +0xBB6C,0xBB6D,0xBB6E,0xC3D7,0xD9E1,0xBB6F,0xBB70,0xBB71, +0xBB72,0xBB73,0xBB74,0xC0E0,0xF4CC,0xD7D1,0xBB75,0xBB76, +0xBB77,0xBB78,0xBB79,0xBB7A,0xBB7B,0xBB7C,0xBB7D,0xBB7E, +0xBB80,0xB7DB,0xBB81,0xBB82,0xBB83,0xBB84,0xBB85,0xBB86, +0xBB87,0xF4CE,0xC1A3,0xBB88,0xBB89,0xC6C9,0xBB8A,0xB4D6, +0xD5B3,0xBB8B,0xBB8C,0xBB8D,0xF4D0,0xF4CF,0xF4D1,0xCBDA, +0xBB8E,0xBB8F,0xF4D2,0xBB90,0xD4C1,0xD6E0,0xBB91,0xBB92, +0xBB93,0xBB94,0xB7E0,0xBB95,0xBB96,0xBB97,0xC1B8,0xBB98, +0xBB99,0xC1BB,0xF4D3,0xBEAC,0xBB9A,0xBB9B,0xBB9C,0xBB9D, +0xBB9E,0xB4E2,0xBB9F,0xBBA0,0xF4D4,0xF4D5,0xBEAB,0xBC40, +0xBC41,0xF4D6,0xBC42,0xBC43,0xBC44,0xF4DB,0xBC45,0xF4D7, +0xF4DA,0xBC46,0xBAFD,0xBC47,0xF4D8,0xF4D9,0xBC48,0xBC49, +0xBC4A,0xBC4B,0xBC4C,0xBC4D,0xBC4E,0xB8E2,0xCCC7,0xF4DC, +0xBC4F,0xB2DA,0xBC50,0xBC51,0xC3D3,0xBC52,0xBC53,0xD4E3, +0xBFB7,0xBC54,0xBC55,0xBC56,0xBC57,0xBC58,0xBC59,0xBC5A, +0xF4DD,0xBC5B,0xBC5C,0xBC5D,0xBC5E,0xBC5F,0xBC60,0xC5B4, +0xBC61,0xBC62,0xBC63,0xBC64,0xBC65,0xBC66,0xBC67,0xBC68, +0xF4E9,0xBC69,0xBC6A,0xCFB5,0xBC6B,0xBC6C,0xBC6D,0xBC6E, +0xBC6F,0xBC70,0xBC71,0xBC72,0xBC73,0xBC74,0xBC75,0xBC76, +0xBC77,0xBC78,0xCEC9,0xBC79,0xBC7A,0xBC7B,0xBC7C,0xBC7D, +0xBC7E,0xBC80,0xBC81,0xBC82,0xBC83,0xBC84,0xBC85,0xBC86, +0xBC87,0xBC88,0xBC89,0xBC8A,0xBC8B,0xBC8C,0xBC8D,0xBC8E, +0xCBD8,0xBC8F,0xCBF7,0xBC90,0xBC91,0xBC92,0xBC93,0xBDF4, +0xBC94,0xBC95,0xBC96,0xD7CF,0xBC97,0xBC98,0xBC99,0xC0DB, +0xBC9A,0xBC9B,0xBC9C,0xBC9D,0xBC9E,0xBC9F,0xBCA0,0xBD40, +0xBD41,0xBD42,0xBD43,0xBD44,0xBD45,0xBD46,0xBD47,0xBD48, +0xBD49,0xBD4A,0xBD4B,0xBD4C,0xBD4D,0xBD4E,0xBD4F,0xBD50, +0xBD51,0xBD52,0xBD53,0xBD54,0xBD55,0xBD56,0xBD57,0xBD58, +0xBD59,0xBD5A,0xBD5B,0xBD5C,0xBD5D,0xBD5E,0xBD5F,0xBD60, +0xBD61,0xBD62,0xBD63,0xBD64,0xBD65,0xBD66,0xBD67,0xBD68, +0xBD69,0xBD6A,0xBD6B,0xBD6C,0xBD6D,0xBD6E,0xBD6F,0xBD70, +0xBD71,0xBD72,0xBD73,0xBD74,0xBD75,0xBD76,0xD0F5,0xBD77, +0xBD78,0xBD79,0xBD7A,0xBD7B,0xBD7C,0xBD7D,0xBD7E,0xF4EA, +0xBD80,0xBD81,0xBD82,0xBD83,0xBD84,0xBD85,0xBD86,0xBD87, +0xBD88,0xBD89,0xBD8A,0xBD8B,0xBD8C,0xBD8D,0xBD8E,0xBD8F, +0xBD90,0xBD91,0xBD92,0xBD93,0xBD94,0xBD95,0xBD96,0xBD97, +0xBD98,0xBD99,0xBD9A,0xBD9B,0xBD9C,0xBD9D,0xBD9E,0xBD9F, +0xBDA0,0xBE40,0xBE41,0xBE42,0xBE43,0xBE44,0xBE45,0xBE46, +0xBE47,0xBE48,0xBE49,0xBE4A,0xBE4B,0xBE4C,0xF4EB,0xBE4D, +0xBE4E,0xBE4F,0xBE50,0xBE51,0xBE52,0xBE53,0xF4EC,0xBE54, +0xBE55,0xBE56,0xBE57,0xBE58,0xBE59,0xBE5A,0xBE5B,0xBE5C, +0xBE5D,0xBE5E,0xBE5F,0xBE60,0xBE61,0xBE62,0xBE63,0xBE64, +0xBE65,0xBE66,0xBE67,0xBE68,0xBE69,0xBE6A,0xBE6B,0xBE6C, +0xBE6D,0xBE6E,0xBE6F,0xBE70,0xBE71,0xBE72,0xBE73,0xBE74, +0xBE75,0xBE76,0xBE77,0xBE78,0xBE79,0xBE7A,0xBE7B,0xBE7C, +0xBE7D,0xBE7E,0xBE80,0xBE81,0xBE82,0xBE83,0xBE84,0xBE85, +0xBE86,0xBE87,0xBE88,0xBE89,0xBE8A,0xBE8B,0xBE8C,0xBE8D, +0xBE8E,0xBE8F,0xBE90,0xBE91,0xBE92,0xBE93,0xBE94,0xBE95, +0xBE96,0xBE97,0xBE98,0xBE99,0xBE9A,0xBE9B,0xBE9C,0xBE9D, +0xBE9E,0xBE9F,0xBEA0,0xBF40,0xBF41,0xBF42,0xBF43,0xBF44, +0xBF45,0xBF46,0xBF47,0xBF48,0xBF49,0xBF4A,0xBF4B,0xBF4C, +0xBF4D,0xBF4E,0xBF4F,0xBF50,0xBF51,0xBF52,0xBF53,0xBF54, +0xBF55,0xBF56,0xBF57,0xBF58,0xBF59,0xBF5A,0xBF5B,0xBF5C, +0xBF5D,0xBF5E,0xBF5F,0xBF60,0xBF61,0xBF62,0xBF63,0xBF64, +0xBF65,0xBF66,0xBF67,0xBF68,0xBF69,0xBF6A,0xBF6B,0xBF6C, +0xBF6D,0xBF6E,0xBF6F,0xBF70,0xBF71,0xBF72,0xBF73,0xBF74, +0xBF75,0xBF76,0xBF77,0xBF78,0xBF79,0xBF7A,0xBF7B,0xBF7C, +0xBF7D,0xBF7E,0xBF80,0xF7E3,0xBF81,0xBF82,0xBF83,0xBF84, +0xBF85,0xB7B1,0xBF86,0xBF87,0xBF88,0xBF89,0xBF8A,0xF4ED, +0xBF8B,0xBF8C,0xBF8D,0xBF8E,0xBF8F,0xBF90,0xBF91,0xBF92, +0xBF93,0xBF94,0xBF95,0xBF96,0xBF97,0xBF98,0xBF99,0xBF9A, +0xBF9B,0xBF9C,0xBF9D,0xBF9E,0xBF9F,0xBFA0,0xC040,0xC041, +0xC042,0xC043,0xC044,0xC045,0xC046,0xC047,0xC048,0xC049, +0xC04A,0xC04B,0xC04C,0xC04D,0xC04E,0xC04F,0xC050,0xC051, +0xC052,0xC053,0xC054,0xC055,0xC056,0xC057,0xC058,0xC059, +0xC05A,0xC05B,0xC05C,0xC05D,0xC05E,0xC05F,0xC060,0xC061, +0xC062,0xC063,0xD7EB,0xC064,0xC065,0xC066,0xC067,0xC068, +0xC069,0xC06A,0xC06B,0xC06C,0xC06D,0xC06E,0xC06F,0xC070, +0xC071,0xC072,0xC073,0xC074,0xC075,0xC076,0xC077,0xC078, +0xC079,0xC07A,0xC07B,0xF4EE,0xC07C,0xC07D,0xC07E,0xE6F9, +0xBEC0,0xE6FA,0xBAEC,0xE6FB,0xCFCB,0xE6FC,0xD4BC,0xBCB6, +0xE6FD,0xE6FE,0xBCCD,0xC8D2,0xCEB3,0xE7A1,0xC080,0xB4BF, +0xE7A2,0xC9B4,0xB8D9,0xC4C9,0xC081,0xD7DD,0xC2DA,0xB7D7, +0xD6BD,0xCEC6,0xB7C4,0xC082,0xC083,0xC5A6,0xE7A3,0xCFDF, +0xE7A4,0xE7A5,0xE7A6,0xC1B7,0xD7E9,0xC9F0,0xCFB8,0xD6AF, +0xD6D5,0xE7A7,0xB0ED,0xE7A8,0xE7A9,0xC9DC,0xD2EF,0xBEAD, +0xE7AA,0xB0F3,0xC8DE,0xBDE1,0xE7AB,0xC8C6,0xC084,0xE7AC, +0xBBE6,0xB8F8,0xD1A4,0xE7AD,0xC2E7,0xBEF8,0xBDCA,0xCDB3, +0xE7AE,0xE7AF,0xBEEE,0xD0E5,0xC085,0xCBE7,0xCCD0,0xBCCC, +0xE7B0,0xBCA8,0xD0F7,0xE7B1,0xC086,0xD0F8,0xE7B2,0xE7B3, +0xB4C2,0xE7B4,0xE7B5,0xC9FE,0xCEAC,0xC3E0,0xE7B7,0xB1C1, +0xB3F1,0xC087,0xE7B8,0xE7B9,0xD7DB,0xD5C0,0xE7BA,0xC2CC, +0xD7BA,0xE7BB,0xE7BC,0xE7BD,0xBCEA,0xC3E5,0xC0C2,0xE7BE, +0xE7BF,0xBCA9,0xC088,0xE7C0,0xE7C1,0xE7B6,0xB6D0,0xE7C2, +0xC089,0xE7C3,0xE7C4,0xBBBA,0xB5DE,0xC2C6,0xB1E0,0xE7C5, +0xD4B5,0xE7C6,0xB8BF,0xE7C8,0xE7C7,0xB7EC,0xC08A,0xE7C9, +0xB2F8,0xE7CA,0xE7CB,0xE7CC,0xE7CD,0xE7CE,0xE7CF,0xE7D0, +0xD3A7,0xCBF5,0xE7D1,0xE7D2,0xE7D3,0xE7D4,0xC9C9,0xE7D5, +0xE7D6,0xE7D7,0xE7D8,0xE7D9,0xBDC9,0xE7DA,0xF3BE,0xC08B, +0xB8D7,0xC08C,0xC8B1,0xC08D,0xC08E,0xC08F,0xC090,0xC091, +0xC092,0xC093,0xF3BF,0xC094,0xF3C0,0xF3C1,0xC095,0xC096, +0xC097,0xC098,0xC099,0xC09A,0xC09B,0xC09C,0xC09D,0xC09E, +0xB9DE,0xCDF8,0xC09F,0xC0A0,0xD8E8,0xBAB1,0xC140,0xC2DE, +0xEEB7,0xC141,0xB7A3,0xC142,0xC143,0xC144,0xC145,0xEEB9, +0xC146,0xEEB8,0xB0D5,0xC147,0xC148,0xC149,0xC14A,0xC14B, +0xEEBB,0xD5D6,0xD7EF,0xC14C,0xC14D,0xC14E,0xD6C3,0xC14F, +0xC150,0xEEBD,0xCAF0,0xC151,0xEEBC,0xC152,0xC153,0xC154, +0xC155,0xEEBE,0xC156,0xC157,0xC158,0xC159,0xEEC0,0xC15A, +0xC15B,0xEEBF,0xC15C,0xC15D,0xC15E,0xC15F,0xC160,0xC161, +0xC162,0xC163,0xD1F2,0xC164,0xC7BC,0xC165,0xC3C0,0xC166, +0xC167,0xC168,0xC169,0xC16A,0xB8E1,0xC16B,0xC16C,0xC16D, +0xC16E,0xC16F,0xC1E7,0xC170,0xC171,0xF4C6,0xD0DF,0xF4C7, +0xC172,0xCFDB,0xC173,0xC174,0xC8BA,0xC175,0xC176,0xF4C8, +0xC177,0xC178,0xC179,0xC17A,0xC17B,0xC17C,0xC17D,0xF4C9, +0xF4CA,0xC17E,0xF4CB,0xC180,0xC181,0xC182,0xC183,0xC184, +0xD9FA,0xB8FE,0xC185,0xC186,0xE5F1,0xD3F0,0xC187,0xF4E0, +0xC188,0xCECC,0xC189,0xC18A,0xC18B,0xB3E1,0xC18C,0xC18D, +0xC18E,0xC18F,0xF1B4,0xC190,0xD2EE,0xC191,0xF4E1,0xC192, +0xC193,0xC194,0xC195,0xC196,0xCFE8,0xF4E2,0xC197,0xC198, +0xC7CC,0xC199,0xC19A,0xC19B,0xC19C,0xC19D,0xC19E,0xB5D4, +0xB4E4,0xF4E4,0xC19F,0xC1A0,0xC240,0xF4E3,0xF4E5,0xC241, +0xC242,0xF4E6,0xC243,0xC244,0xC245,0xC246,0xF4E7,0xC247, +0xBAB2,0xB0BF,0xC248,0xF4E8,0xC249,0xC24A,0xC24B,0xC24C, +0xC24D,0xC24E,0xC24F,0xB7AD,0xD2ED,0xC250,0xC251,0xC252, +0xD2AB,0xC0CF,0xC253,0xBFBC,0xEBA3,0xD5DF,0xEAC8,0xC254, +0xC255,0xC256,0xC257,0xF1F3,0xB6F8,0xCBA3,0xC258,0xC259, +0xC4CD,0xC25A,0xF1E7,0xC25B,0xF1E8,0xB8FB,0xF1E9,0xBAC4, +0xD4C5,0xB0D2,0xC25C,0xC25D,0xF1EA,0xC25E,0xC25F,0xC260, +0xF1EB,0xC261,0xF1EC,0xC262,0xC263,0xF1ED,0xF1EE,0xF1EF, +0xF1F1,0xF1F0,0xC5D5,0xC264,0xC265,0xC266,0xC267,0xC268, +0xC269,0xF1F2,0xC26A,0xB6FA,0xC26B,0xF1F4,0xD2AE,0xDEC7, +0xCBCA,0xC26C,0xC26D,0xB3DC,0xC26E,0xB5A2,0xC26F,0xB9A2, +0xC270,0xC271,0xC4F4,0xF1F5,0xC272,0xC273,0xF1F6,0xC274, +0xC275,0xC276,0xC1C4,0xC1FB,0xD6B0,0xF1F7,0xC277,0xC278, +0xC279,0xC27A,0xF1F8,0xC27B,0xC1AA,0xC27C,0xC27D,0xC27E, +0xC6B8,0xC280,0xBEDB,0xC281,0xC282,0xC283,0xC284,0xC285, +0xC286,0xC287,0xC288,0xC289,0xC28A,0xC28B,0xC28C,0xC28D, +0xC28E,0xF1F9,0xB4CF,0xC28F,0xC290,0xC291,0xC292,0xC293, +0xC294,0xF1FA,0xC295,0xC296,0xC297,0xC298,0xC299,0xC29A, +0xC29B,0xC29C,0xC29D,0xC29E,0xC29F,0xC2A0,0xC340,0xEDB2, +0xEDB1,0xC341,0xC342,0xCBE0,0xD2DE,0xC343,0xCBC1,0xD5D8, +0xC344,0xC8E2,0xC345,0xC0DF,0xBCA1,0xC346,0xC347,0xC348, +0xC349,0xC34A,0xC34B,0xEBC1,0xC34C,0xC34D,0xD0A4,0xC34E, +0xD6E2,0xC34F,0xB6C7,0xB8D8,0xEBC0,0xB8CE,0xC350,0xEBBF, +0xB3A6,0xB9C9,0xD6AB,0xC351,0xB7F4,0xB7CA,0xC352,0xC353, +0xC354,0xBCE7,0xB7BE,0xEBC6,0xC355,0xEBC7,0xB0B9,0xBFCF, +0xC356,0xEBC5,0xD3FD,0xC357,0xEBC8,0xC358,0xC359,0xEBC9, +0xC35A,0xC35B,0xB7CE,0xC35C,0xEBC2,0xEBC4,0xC9F6,0xD6D7, +0xD5CD,0xD0B2,0xEBCF,0xCEB8,0xEBD0,0xC35D,0xB5A8,0xC35E, +0xC35F,0xC360,0xC361,0xC362,0xB1B3,0xEBD2,0xCCA5,0xC363, +0xC364,0xC365,0xC366,0xC367,0xC368,0xC369,0xC5D6,0xEBD3, +0xC36A,0xEBD1,0xC5DF,0xEBCE,0xCAA4,0xEBD5,0xB0FB,0xC36B, +0xC36C,0xBAFA,0xC36D,0xC36E,0xD8B7,0xF1E3,0xC36F,0xEBCA, +0xEBCB,0xEBCC,0xEBCD,0xEBD6,0xE6C0,0xEBD9,0xC370,0xBFE8, +0xD2C8,0xEBD7,0xEBDC,0xB8EC,0xEBD8,0xC371,0xBDBA,0xC372, +0xD0D8,0xC373,0xB0B7,0xC374,0xEBDD,0xC4DC,0xC375,0xC376, +0xC377,0xC378,0xD6AC,0xC379,0xC37A,0xC37B,0xB4E0,0xC37C, +0xC37D,0xC2F6,0xBCB9,0xC37E,0xC380,0xEBDA,0xEBDB,0xD4E0, +0xC6EA,0xC4D4,0xEBDF,0xC5A7,0xD9F5,0xC381,0xB2B1,0xC382, +0xEBE4,0xC383,0xBDC5,0xC384,0xC385,0xC386,0xEBE2,0xC387, +0xC388,0xC389,0xC38A,0xC38B,0xC38C,0xC38D,0xC38E,0xC38F, +0xC390,0xC391,0xC392,0xC393,0xEBE3,0xC394,0xC395,0xB8AC, +0xC396,0xCDD1,0xEBE5,0xC397,0xC398,0xC399,0xEBE1,0xC39A, +0xC1B3,0xC39B,0xC39C,0xC39D,0xC39E,0xC39F,0xC6A2,0xC3A0, +0xC440,0xC441,0xC442,0xC443,0xC444,0xC445,0xCCF3,0xC446, +0xEBE6,0xC447,0xC0B0,0xD2B8,0xEBE7,0xC448,0xC449,0xC44A, +0xB8AF,0xB8AD,0xC44B,0xEBE8,0xC7BB,0xCDF3,0xC44C,0xC44D, +0xC44E,0xEBEA,0xEBEB,0xC44F,0xC450,0xC451,0xC452,0xC453, +0xEBED,0xC454,0xC455,0xC456,0xC457,0xD0C8,0xC458,0xEBF2, +0xC459,0xEBEE,0xC45A,0xC45B,0xC45C,0xEBF1,0xC8F9,0xC45D, +0xD1FC,0xEBEC,0xC45E,0xC45F,0xEBE9,0xC460,0xC461,0xC462, +0xC463,0xB8B9,0xCFD9,0xC4E5,0xEBEF,0xEBF0,0xCCDA,0xCDC8, +0xB0F2,0xC464,0xEBF6,0xC465,0xC466,0xC467,0xC468,0xC469, +0xEBF5,0xC46A,0xB2B2,0xC46B,0xC46C,0xC46D,0xC46E,0xB8E0, +0xC46F,0xEBF7,0xC470,0xC471,0xC472,0xC473,0xC474,0xC475, +0xB1EC,0xC476,0xC477,0xCCC5,0xC4A4,0xCFA5,0xC478,0xC479, +0xC47A,0xC47B,0xC47C,0xEBF9,0xC47D,0xC47E,0xECA2,0xC480, +0xC5F2,0xC481,0xEBFA,0xC482,0xC483,0xC484,0xC485,0xC486, +0xC487,0xC488,0xC489,0xC9C5,0xC48A,0xC48B,0xC48C,0xC48D, +0xC48E,0xC48F,0xE2DF,0xEBFE,0xC490,0xC491,0xC492,0xC493, +0xCDCE,0xECA1,0xB1DB,0xD3B7,0xC494,0xC495,0xD2DC,0xC496, +0xC497,0xC498,0xEBFD,0xC499,0xEBFB,0xC49A,0xC49B,0xC49C, +0xC49D,0xC49E,0xC49F,0xC4A0,0xC540,0xC541,0xC542,0xC543, +0xC544,0xC545,0xC546,0xC547,0xC548,0xC549,0xC54A,0xC54B, +0xC54C,0xC54D,0xC54E,0xB3BC,0xC54F,0xC550,0xC551,0xEAB0, +0xC552,0xC553,0xD7D4,0xC554,0xF4AB,0xB3F4,0xC555,0xC556, +0xC557,0xC558,0xC559,0xD6C1,0xD6C2,0xC55A,0xC55B,0xC55C, +0xC55D,0xC55E,0xC55F,0xD5E9,0xBECA,0xC560,0xF4A7,0xC561, +0xD2A8,0xF4A8,0xF4A9,0xC562,0xF4AA,0xBECB,0xD3DF,0xC563, +0xC564,0xC565,0xC566,0xC567,0xC9E0,0xC9E1,0xC568,0xC569, +0xF3C2,0xC56A,0xCAE6,0xC56B,0xCCF2,0xC56C,0xC56D,0xC56E, +0xC56F,0xC570,0xC571,0xE2B6,0xCBB4,0xC572,0xCEE8,0xD6DB, +0xC573,0xF4AD,0xF4AE,0xF4AF,0xC574,0xC575,0xC576,0xC577, +0xF4B2,0xC578,0xBABD,0xF4B3,0xB0E3,0xF4B0,0xC579,0xF4B1, +0xBDA2,0xB2D5,0xC57A,0xF4B6,0xF4B7,0xB6E6,0xB2B0,0xCFCF, +0xF4B4,0xB4AC,0xC57B,0xF4B5,0xC57C,0xC57D,0xF4B8,0xC57E, +0xC580,0xC581,0xC582,0xC583,0xF4B9,0xC584,0xC585,0xCDA7, +0xC586,0xF4BA,0xC587,0xF4BB,0xC588,0xC589,0xC58A,0xF4BC, +0xC58B,0xC58C,0xC58D,0xC58E,0xC58F,0xC590,0xC591,0xC592, +0xCBD2,0xC593,0xF4BD,0xC594,0xC595,0xC596,0xC597,0xF4BE, +0xC598,0xC599,0xC59A,0xC59B,0xC59C,0xC59D,0xC59E,0xC59F, +0xF4BF,0xC5A0,0xC640,0xC641,0xC642,0xC643,0xF4DE,0xC1BC, +0xBCE8,0xC644,0xC9AB,0xD1DE,0xE5F5,0xC645,0xC646,0xC647, +0xC648,0xDCB3,0xD2D5,0xC649,0xC64A,0xDCB4,0xB0AC,0xDCB5, +0xC64B,0xC64C,0xBDDA,0xC64D,0xDCB9,0xC64E,0xC64F,0xC650, +0xD8C2,0xC651,0xDCB7,0xD3F3,0xC652,0xC9D6,0xDCBA,0xDCB6, +0xC653,0xDCBB,0xC3A2,0xC654,0xC655,0xC656,0xC657,0xDCBC, +0xDCC5,0xDCBD,0xC658,0xC659,0xCEDF,0xD6A5,0xC65A,0xDCCF, +0xC65B,0xDCCD,0xC65C,0xC65D,0xDCD2,0xBDE6,0xC2AB,0xC65E, +0xDCB8,0xDCCB,0xDCCE,0xDCBE,0xB7D2,0xB0C5,0xDCC7,0xD0BE, +0xDCC1,0xBBA8,0xC65F,0xB7BC,0xDCCC,0xC660,0xC661,0xDCC6, +0xDCBF,0xC7DB,0xC662,0xC663,0xC664,0xD1BF,0xDCC0,0xC665, +0xC666,0xDCCA,0xC667,0xC668,0xDCD0,0xC669,0xC66A,0xCEAD, +0xDCC2,0xC66B,0xDCC3,0xDCC8,0xDCC9,0xB2D4,0xDCD1,0xCBD5, +0xC66C,0xD4B7,0xDCDB,0xDCDF,0xCCA6,0xDCE6,0xC66D,0xC3E7, +0xDCDC,0xC66E,0xC66F,0xBFC1,0xDCD9,0xC670,0xB0FA,0xB9B6, +0xDCE5,0xDCD3,0xC671,0xDCC4,0xDCD6,0xC8F4,0xBFE0,0xC672, +0xC673,0xC674,0xC675,0xC9BB,0xC676,0xC677,0xC678,0xB1BD, +0xC679,0xD3A2,0xC67A,0xC67B,0xDCDA,0xC67C,0xC67D,0xDCD5, +0xC67E,0xC6BB,0xC680,0xDCDE,0xC681,0xC682,0xC683,0xC684, +0xC685,0xD7C2,0xC3AF,0xB7B6,0xC7D1,0xC3A9,0xDCE2,0xDCD8, +0xDCEB,0xDCD4,0xC686,0xC687,0xDCDD,0xC688,0xBEA5,0xDCD7, +0xC689,0xDCE0,0xC68A,0xC68B,0xDCE3,0xDCE4,0xC68C,0xDCF8, +0xC68D,0xC68E,0xDCE1,0xDDA2,0xDCE7,0xC68F,0xC690,0xC691, +0xC692,0xC693,0xC694,0xC695,0xC696,0xC697,0xC698,0xBCEB, +0xB4C4,0xC699,0xC69A,0xC3A3,0xB2E7,0xDCFA,0xC69B,0xDCF2, +0xC69C,0xDCEF,0xC69D,0xDCFC,0xDCEE,0xD2F0,0xB2E8,0xC69E, +0xC8D7,0xC8E3,0xDCFB,0xC69F,0xDCED,0xC6A0,0xC740,0xC741, +0xDCF7,0xC742,0xC743,0xDCF5,0xC744,0xC745,0xBEA3,0xDCF4, +0xC746,0xB2DD,0xC747,0xC748,0xC749,0xC74A,0xC74B,0xDCF3, +0xBCF6,0xDCE8,0xBBC4,0xC74C,0xC0F3,0xC74D,0xC74E,0xC74F, +0xC750,0xC751,0xBCD4,0xDCE9,0xDCEA,0xC752,0xDCF1,0xDCF6, +0xDCF9,0xB5B4,0xC753,0xC8D9,0xBBE7,0xDCFE,0xDCFD,0xD3AB, +0xDDA1,0xDDA3,0xDDA5,0xD2F1,0xDDA4,0xDDA6,0xDDA7,0xD2A9, +0xC754,0xC755,0xC756,0xC757,0xC758,0xC759,0xC75A,0xBAC9, +0xDDA9,0xC75B,0xC75C,0xDDB6,0xDDB1,0xDDB4,0xC75D,0xC75E, +0xC75F,0xC760,0xC761,0xC762,0xC763,0xDDB0,0xC6CE,0xC764, +0xC765,0xC0F2,0xC766,0xC767,0xC768,0xC769,0xC9AF,0xC76A, +0xC76B,0xC76C,0xDCEC,0xDDAE,0xC76D,0xC76E,0xC76F,0xC770, +0xDDB7,0xC771,0xC772,0xDCF0,0xDDAF,0xC773,0xDDB8,0xC774, +0xDDAC,0xC775,0xC776,0xC777,0xC778,0xC779,0xC77A,0xC77B, +0xDDB9,0xDDB3,0xDDAD,0xC4AA,0xC77C,0xC77D,0xC77E,0xC780, +0xDDA8,0xC0B3,0xC1AB,0xDDAA,0xDDAB,0xC781,0xDDB2,0xBBF1, +0xDDB5,0xD3A8,0xDDBA,0xC782,0xDDBB,0xC3A7,0xC783,0xC784, +0xDDD2,0xDDBC,0xC785,0xC786,0xC787,0xDDD1,0xC788,0xB9BD, +0xC789,0xC78A,0xBED5,0xC78B,0xBEFA,0xC78C,0xC78D,0xBACA, +0xC78E,0xC78F,0xC790,0xC791,0xDDCA,0xC792,0xDDC5,0xC793, +0xDDBF,0xC794,0xC795,0xC796,0xB2CB,0xDDC3,0xC797,0xDDCB, +0xB2A4,0xDDD5,0xC798,0xC799,0xC79A,0xDDBE,0xC79B,0xC79C, +0xC79D,0xC6D0,0xDDD0,0xC79E,0xC79F,0xC7A0,0xC840,0xC841, +0xDDD4,0xC1E2,0xB7C6,0xC842,0xC843,0xC844,0xC845,0xC846, +0xDDCE,0xDDCF,0xC847,0xC848,0xC849,0xDDC4,0xC84A,0xC84B, +0xC84C,0xDDBD,0xC84D,0xDDCD,0xCCD1,0xC84E,0xDDC9,0xC84F, +0xC850,0xC851,0xC852,0xDDC2,0xC3C8,0xC6BC,0xCEAE,0xDDCC, +0xC853,0xDDC8,0xC854,0xC855,0xC856,0xC857,0xC858,0xC859, +0xDDC1,0xC85A,0xC85B,0xC85C,0xDDC6,0xC2DC,0xC85D,0xC85E, +0xC85F,0xC860,0xC861,0xC862,0xD3A9,0xD3AA,0xDDD3,0xCFF4, +0xC8F8,0xC863,0xC864,0xC865,0xC866,0xC867,0xC868,0xC869, +0xC86A,0xDDE6,0xC86B,0xC86C,0xC86D,0xC86E,0xC86F,0xC870, +0xDDC7,0xC871,0xC872,0xC873,0xDDE0,0xC2E4,0xC874,0xC875, +0xC876,0xC877,0xC878,0xC879,0xC87A,0xC87B,0xDDE1,0xC87C, +0xC87D,0xC87E,0xC880,0xC881,0xC882,0xC883,0xC884,0xC885, +0xC886,0xDDD7,0xC887,0xC888,0xC889,0xC88A,0xC88B,0xD6F8, +0xC88C,0xDDD9,0xDDD8,0xB8F0,0xDDD6,0xC88D,0xC88E,0xC88F, +0xC890,0xC6CF,0xC891,0xB6AD,0xC892,0xC893,0xC894,0xC895, +0xC896,0xDDE2,0xC897,0xBAF9,0xD4E1,0xDDE7,0xC898,0xC899, +0xC89A,0xB4D0,0xC89B,0xDDDA,0xC89C,0xBFFB,0xDDE3,0xC89D, +0xDDDF,0xC89E,0xDDDD,0xC89F,0xC8A0,0xC940,0xC941,0xC942, +0xC943,0xC944,0xB5D9,0xC945,0xC946,0xC947,0xC948,0xDDDB, +0xDDDC,0xDDDE,0xC949,0xBDAF,0xDDE4,0xC94A,0xDDE5,0xC94B, +0xC94C,0xC94D,0xC94E,0xC94F,0xC950,0xC951,0xC952,0xDDF5, +0xC953,0xC3C9,0xC954,0xC955,0xCBE2,0xC956,0xC957,0xC958, +0xC959,0xDDF2,0xC95A,0xC95B,0xC95C,0xC95D,0xC95E,0xC95F, +0xC960,0xC961,0xC962,0xC963,0xC964,0xC965,0xC966,0xD8E1, +0xC967,0xC968,0xC6D1,0xC969,0xDDF4,0xC96A,0xC96B,0xC96C, +0xD5F4,0xDDF3,0xDDF0,0xC96D,0xC96E,0xDDEC,0xC96F,0xDDEF, +0xC970,0xDDE8,0xC971,0xC972,0xD0EE,0xC973,0xC974,0xC975, +0xC976,0xC8D8,0xDDEE,0xC977,0xC978,0xDDE9,0xC979,0xC97A, +0xDDEA,0xCBF2,0xC97B,0xDDED,0xC97C,0xC97D,0xB1CD,0xC97E, +0xC980,0xC981,0xC982,0xC983,0xC984,0xC0B6,0xC985,0xBCBB, +0xDDF1,0xC986,0xC987,0xDDF7,0xC988,0xDDF6,0xDDEB,0xC989, +0xC98A,0xC98B,0xC98C,0xC98D,0xC5EE,0xC98E,0xC98F,0xC990, +0xDDFB,0xC991,0xC992,0xC993,0xC994,0xC995,0xC996,0xC997, +0xC998,0xC999,0xC99A,0xC99B,0xDEA4,0xC99C,0xC99D,0xDEA3, +0xC99E,0xC99F,0xC9A0,0xCA40,0xCA41,0xCA42,0xCA43,0xCA44, +0xCA45,0xCA46,0xCA47,0xCA48,0xDDF8,0xCA49,0xCA4A,0xCA4B, +0xCA4C,0xC3EF,0xCA4D,0xC2FB,0xCA4E,0xCA4F,0xCA50,0xD5E1, +0xCA51,0xCA52,0xCEB5,0xCA53,0xCA54,0xCA55,0xCA56,0xDDFD, +0xCA57,0xB2CC,0xCA58,0xCA59,0xCA5A,0xCA5B,0xCA5C,0xCA5D, +0xCA5E,0xCA5F,0xCA60,0xC4E8,0xCADF,0xCA61,0xCA62,0xCA63, +0xCA64,0xCA65,0xCA66,0xCA67,0xCA68,0xCA69,0xCA6A,0xC7BE, +0xDDFA,0xDDFC,0xDDFE,0xDEA2,0xB0AA,0xB1CE,0xCA6B,0xCA6C, +0xCA6D,0xCA6E,0xCA6F,0xDEAC,0xCA70,0xCA71,0xCA72,0xCA73, +0xDEA6,0xBDB6,0xC8EF,0xCA74,0xCA75,0xCA76,0xCA77,0xCA78, +0xCA79,0xCA7A,0xCA7B,0xCA7C,0xCA7D,0xCA7E,0xDEA1,0xCA80, +0xCA81,0xDEA5,0xCA82,0xCA83,0xCA84,0xCA85,0xDEA9,0xCA86, +0xCA87,0xCA88,0xCA89,0xCA8A,0xDEA8,0xCA8B,0xCA8C,0xCA8D, +0xDEA7,0xCA8E,0xCA8F,0xCA90,0xCA91,0xCA92,0xCA93,0xCA94, +0xCA95,0xCA96,0xDEAD,0xCA97,0xD4CC,0xCA98,0xCA99,0xCA9A, +0xCA9B,0xDEB3,0xDEAA,0xDEAE,0xCA9C,0xCA9D,0xC0D9,0xCA9E, +0xCA9F,0xCAA0,0xCB40,0xCB41,0xB1A1,0xDEB6,0xCB42,0xDEB1, +0xCB43,0xCB44,0xCB45,0xCB46,0xCB47,0xCB48,0xCB49,0xDEB2, +0xCB4A,0xCB4B,0xCB4C,0xCB4D,0xCB4E,0xCB4F,0xCB50,0xCB51, +0xCB52,0xCB53,0xCB54,0xD1A6,0xDEB5,0xCB55,0xCB56,0xCB57, +0xCB58,0xCB59,0xCB5A,0xCB5B,0xDEAF,0xCB5C,0xCB5D,0xCB5E, +0xDEB0,0xCB5F,0xD0BD,0xCB60,0xCB61,0xCB62,0xDEB4,0xCAED, +0xDEB9,0xCB63,0xCB64,0xCB65,0xCB66,0xCB67,0xCB68,0xDEB8, +0xCB69,0xDEB7,0xCB6A,0xCB6B,0xCB6C,0xCB6D,0xCB6E,0xCB6F, +0xCB70,0xDEBB,0xCB71,0xCB72,0xCB73,0xCB74,0xCB75,0xCB76, +0xCB77,0xBDE5,0xCB78,0xCB79,0xCB7A,0xCB7B,0xCB7C,0xB2D8, +0xC3EA,0xCB7D,0xCB7E,0xDEBA,0xCB80,0xC5BA,0xCB81,0xCB82, +0xCB83,0xCB84,0xCB85,0xCB86,0xDEBC,0xCB87,0xCB88,0xCB89, +0xCB8A,0xCB8B,0xCB8C,0xCB8D,0xCCD9,0xCB8E,0xCB8F,0xCB90, +0xCB91,0xB7AA,0xCB92,0xCB93,0xCB94,0xCB95,0xCB96,0xCB97, +0xCB98,0xCB99,0xCB9A,0xCB9B,0xCB9C,0xCB9D,0xCB9E,0xCB9F, +0xCBA0,0xCC40,0xCC41,0xD4E5,0xCC42,0xCC43,0xCC44,0xDEBD, +0xCC45,0xCC46,0xCC47,0xCC48,0xCC49,0xDEBF,0xCC4A,0xCC4B, +0xCC4C,0xCC4D,0xCC4E,0xCC4F,0xCC50,0xCC51,0xCC52,0xCC53, +0xCC54,0xC4A2,0xCC55,0xCC56,0xCC57,0xCC58,0xDEC1,0xCC59, +0xCC5A,0xCC5B,0xCC5C,0xCC5D,0xCC5E,0xCC5F,0xCC60,0xCC61, +0xCC62,0xCC63,0xCC64,0xCC65,0xCC66,0xCC67,0xCC68,0xDEBE, +0xCC69,0xDEC0,0xCC6A,0xCC6B,0xCC6C,0xCC6D,0xCC6E,0xCC6F, +0xCC70,0xCC71,0xCC72,0xCC73,0xCC74,0xCC75,0xCC76,0xCC77, +0xD5BA,0xCC78,0xCC79,0xCC7A,0xDEC2,0xCC7B,0xCC7C,0xCC7D, +0xCC7E,0xCC80,0xCC81,0xCC82,0xCC83,0xCC84,0xCC85,0xCC86, +0xCC87,0xCC88,0xCC89,0xCC8A,0xCC8B,0xF2AE,0xBBA2,0xC2B2, +0xC5B0,0xC2C7,0xCC8C,0xCC8D,0xF2AF,0xCC8E,0xCC8F,0xCC90, +0xCC91,0xCC92,0xD0E9,0xCC93,0xCC94,0xCC95,0xD3DD,0xCC96, +0xCC97,0xCC98,0xEBBD,0xCC99,0xCC9A,0xCC9B,0xCC9C,0xCC9D, +0xCC9E,0xCC9F,0xCCA0,0xB3E6,0xF2B0,0xCD40,0xF2B1,0xCD41, +0xCD42,0xCAAD,0xCD43,0xCD44,0xCD45,0xCD46,0xCD47,0xCD48, +0xCD49,0xBAE7,0xF2B3,0xF2B5,0xF2B4,0xCBE4,0xCFBA,0xF2B2, +0xCAB4,0xD2CF,0xC2EC,0xCD4A,0xCD4B,0xCD4C,0xCD4D,0xCD4E, +0xCD4F,0xCD50,0xCEC3,0xF2B8,0xB0F6,0xF2B7,0xCD51,0xCD52, +0xCD53,0xCD54,0xCD55,0xF2BE,0xCD56,0xB2CF,0xCD57,0xCD58, +0xCD59,0xCD5A,0xCD5B,0xCD5C,0xD1C1,0xF2BA,0xCD5D,0xCD5E, +0xCD5F,0xCD60,0xCD61,0xF2BC,0xD4E9,0xCD62,0xCD63,0xF2BB, +0xF2B6,0xF2BF,0xF2BD,0xCD64,0xF2B9,0xCD65,0xCD66,0xF2C7, +0xF2C4,0xF2C6,0xCD67,0xCD68,0xF2CA,0xF2C2,0xF2C0,0xCD69, +0xCD6A,0xCD6B,0xF2C5,0xCD6C,0xCD6D,0xCD6E,0xCD6F,0xCD70, +0xD6FB,0xCD71,0xCD72,0xCD73,0xF2C1,0xCD74,0xC7F9,0xC9DF, +0xCD75,0xF2C8,0xB9C6,0xB5B0,0xCD76,0xCD77,0xF2C3,0xF2C9, +0xF2D0,0xF2D6,0xCD78,0xCD79,0xBBD7,0xCD7A,0xCD7B,0xCD7C, +0xF2D5,0xCDDC,0xCD7D,0xD6EB,0xCD7E,0xCD80,0xF2D2,0xF2D4, +0xCD81,0xCD82,0xCD83,0xCD84,0xB8F2,0xCD85,0xCD86,0xCD87, +0xCD88,0xF2CB,0xCD89,0xCD8A,0xCD8B,0xF2CE,0xC2F9,0xCD8C, +0xD5DD,0xF2CC,0xF2CD,0xF2CF,0xF2D3,0xCD8D,0xCD8E,0xCD8F, +0xF2D9,0xD3BC,0xCD90,0xCD91,0xCD92,0xCD93,0xB6EA,0xCD94, +0xCAF1,0xCD95,0xB7E4,0xF2D7,0xCD96,0xCD97,0xCD98,0xF2D8, +0xF2DA,0xF2DD,0xF2DB,0xCD99,0xCD9A,0xF2DC,0xCD9B,0xCD9C, +0xCD9D,0xCD9E,0xD1D1,0xF2D1,0xCD9F,0xCDC9,0xCDA0,0xCECF, +0xD6A9,0xCE40,0xF2E3,0xCE41,0xC3DB,0xCE42,0xF2E0,0xCE43, +0xCE44,0xC0AF,0xF2EC,0xF2DE,0xCE45,0xF2E1,0xCE46,0xCE47, +0xCE48,0xF2E8,0xCE49,0xCE4A,0xCE4B,0xCE4C,0xF2E2,0xCE4D, +0xCE4E,0xF2E7,0xCE4F,0xCE50,0xF2E6,0xCE51,0xCE52,0xF2E9, +0xCE53,0xCE54,0xCE55,0xF2DF,0xCE56,0xCE57,0xF2E4,0xF2EA, +0xCE58,0xCE59,0xCE5A,0xCE5B,0xCE5C,0xCE5D,0xCE5E,0xD3AC, +0xF2E5,0xB2F5,0xCE5F,0xCE60,0xF2F2,0xCE61,0xD0AB,0xCE62, +0xCE63,0xCE64,0xCE65,0xF2F5,0xCE66,0xCE67,0xCE68,0xBBC8, +0xCE69,0xF2F9,0xCE6A,0xCE6B,0xCE6C,0xCE6D,0xCE6E,0xCE6F, +0xF2F0,0xCE70,0xCE71,0xF2F6,0xF2F8,0xF2FA,0xCE72,0xCE73, +0xCE74,0xCE75,0xCE76,0xCE77,0xCE78,0xCE79,0xF2F3,0xCE7A, +0xF2F1,0xCE7B,0xCE7C,0xCE7D,0xBAFB,0xCE7E,0xB5FB,0xCE80, +0xCE81,0xCE82,0xCE83,0xF2EF,0xF2F7,0xF2ED,0xF2EE,0xCE84, +0xCE85,0xCE86,0xF2EB,0xF3A6,0xCE87,0xF3A3,0xCE88,0xCE89, +0xF3A2,0xCE8A,0xCE8B,0xF2F4,0xCE8C,0xC8DA,0xCE8D,0xCE8E, +0xCE8F,0xCE90,0xCE91,0xF2FB,0xCE92,0xCE93,0xCE94,0xF3A5, +0xCE95,0xCE96,0xCE97,0xCE98,0xCE99,0xCE9A,0xCE9B,0xC3F8, +0xCE9C,0xCE9D,0xCE9E,0xCE9F,0xCEA0,0xCF40,0xCF41,0xCF42, +0xF2FD,0xCF43,0xCF44,0xF3A7,0xF3A9,0xF3A4,0xCF45,0xF2FC, +0xCF46,0xCF47,0xCF48,0xF3AB,0xCF49,0xF3AA,0xCF4A,0xCF4B, +0xCF4C,0xCF4D,0xC2DD,0xCF4E,0xCF4F,0xF3AE,0xCF50,0xCF51, +0xF3B0,0xCF52,0xCF53,0xCF54,0xCF55,0xCF56,0xF3A1,0xCF57, +0xCF58,0xCF59,0xF3B1,0xF3AC,0xCF5A,0xCF5B,0xCF5C,0xCF5D, +0xCF5E,0xF3AF,0xF2FE,0xF3AD,0xCF5F,0xCF60,0xCF61,0xCF62, +0xCF63,0xCF64,0xCF65,0xF3B2,0xCF66,0xCF67,0xCF68,0xCF69, +0xF3B4,0xCF6A,0xCF6B,0xCF6C,0xCF6D,0xF3A8,0xCF6E,0xCF6F, +0xCF70,0xCF71,0xF3B3,0xCF72,0xCF73,0xCF74,0xF3B5,0xCF75, +0xCF76,0xCF77,0xCF78,0xCF79,0xCF7A,0xCF7B,0xCF7C,0xCF7D, +0xCF7E,0xD0B7,0xCF80,0xCF81,0xCF82,0xCF83,0xF3B8,0xCF84, +0xCF85,0xCF86,0xCF87,0xD9F9,0xCF88,0xCF89,0xCF8A,0xCF8B, +0xCF8C,0xCF8D,0xF3B9,0xCF8E,0xCF8F,0xCF90,0xCF91,0xCF92, +0xCF93,0xCF94,0xCF95,0xF3B7,0xCF96,0xC8E4,0xF3B6,0xCF97, +0xCF98,0xCF99,0xCF9A,0xF3BA,0xCF9B,0xCF9C,0xCF9D,0xCF9E, +0xCF9F,0xF3BB,0xB4C0,0xCFA0,0xD040,0xD041,0xD042,0xD043, +0xD044,0xD045,0xD046,0xD047,0xD048,0xD049,0xD04A,0xD04B, +0xD04C,0xD04D,0xEEC3,0xD04E,0xD04F,0xD050,0xD051,0xD052, +0xD053,0xF3BC,0xD054,0xD055,0xF3BD,0xD056,0xD057,0xD058, +0xD1AA,0xD059,0xD05A,0xD05B,0xF4AC,0xD0C6,0xD05C,0xD05D, +0xD05E,0xD05F,0xD060,0xD061,0xD0D0,0xD1DC,0xD062,0xD063, +0xD064,0xD065,0xD066,0xD067,0xCFCE,0xD068,0xD069,0xBDD6, +0xD06A,0xD1C3,0xD06B,0xD06C,0xD06D,0xD06E,0xD06F,0xD070, +0xD071,0xBAE2,0xE1E9,0xD2C2,0xF1C2,0xB2B9,0xD072,0xD073, +0xB1ED,0xF1C3,0xD074,0xC9C0,0xB3C4,0xD075,0xD9F2,0xD076, +0xCBA5,0xD077,0xF1C4,0xD078,0xD079,0xD07A,0xD07B,0xD6D4, +0xD07C,0xD07D,0xD07E,0xD080,0xD081,0xF1C5,0xF4C0,0xF1C6, +0xD082,0xD4AC,0xF1C7,0xD083,0xB0C0,0xF4C1,0xD084,0xD085, +0xF4C2,0xD086,0xD087,0xB4FC,0xD088,0xC5DB,0xD089,0xD08A, +0xD08B,0xD08C,0xCCBB,0xD08D,0xD08E,0xD08F,0xD0E4,0xD090, +0xD091,0xD092,0xD093,0xD094,0xCDE0,0xD095,0xD096,0xD097, +0xD098,0xD099,0xF1C8,0xD09A,0xD9F3,0xD09B,0xD09C,0xD09D, +0xD09E,0xD09F,0xD0A0,0xB1BB,0xD140,0xCFAE,0xD141,0xD142, +0xD143,0xB8A4,0xD144,0xD145,0xD146,0xD147,0xD148,0xF1CA, +0xD149,0xD14A,0xD14B,0xD14C,0xF1CB,0xD14D,0xD14E,0xD14F, +0xD150,0xB2C3,0xC1D1,0xD151,0xD152,0xD7B0,0xF1C9,0xD153, +0xD154,0xF1CC,0xD155,0xD156,0xD157,0xD158,0xF1CE,0xD159, +0xD15A,0xD15B,0xD9F6,0xD15C,0xD2E1,0xD4A3,0xD15D,0xD15E, +0xF4C3,0xC8B9,0xD15F,0xD160,0xD161,0xD162,0xD163,0xF4C4, +0xD164,0xD165,0xF1CD,0xF1CF,0xBFE3,0xF1D0,0xD166,0xD167, +0xF1D4,0xD168,0xD169,0xD16A,0xD16B,0xD16C,0xD16D,0xD16E, +0xF1D6,0xF1D1,0xD16F,0xC9D1,0xC5E1,0xD170,0xD171,0xD172, +0xC2E3,0xB9FC,0xD173,0xD174,0xF1D3,0xD175,0xF1D5,0xD176, +0xD177,0xD178,0xB9D3,0xD179,0xD17A,0xD17B,0xD17C,0xD17D, +0xD17E,0xD180,0xF1DB,0xD181,0xD182,0xD183,0xD184,0xD185, +0xBAD6,0xD186,0xB0FD,0xF1D9,0xD187,0xD188,0xD189,0xD18A, +0xD18B,0xF1D8,0xF1D2,0xF1DA,0xD18C,0xD18D,0xD18E,0xD18F, +0xD190,0xF1D7,0xD191,0xD192,0xD193,0xC8EC,0xD194,0xD195, +0xD196,0xD197,0xCDCA,0xF1DD,0xD198,0xD199,0xD19A,0xD19B, +0xE5BD,0xD19C,0xD19D,0xD19E,0xF1DC,0xD19F,0xF1DE,0xD1A0, +0xD240,0xD241,0xD242,0xD243,0xD244,0xD245,0xD246,0xD247, +0xD248,0xF1DF,0xD249,0xD24A,0xCFE5,0xD24B,0xD24C,0xD24D, +0xD24E,0xD24F,0xD250,0xD251,0xD252,0xD253,0xD254,0xD255, +0xD256,0xD257,0xD258,0xD259,0xD25A,0xD25B,0xD25C,0xD25D, +0xD25E,0xD25F,0xD260,0xD261,0xD262,0xD263,0xF4C5,0xBDF3, +0xD264,0xD265,0xD266,0xD267,0xD268,0xD269,0xF1E0,0xD26A, +0xD26B,0xD26C,0xD26D,0xD26E,0xD26F,0xD270,0xD271,0xD272, +0xD273,0xD274,0xD275,0xD276,0xD277,0xD278,0xD279,0xD27A, +0xD27B,0xD27C,0xD27D,0xF1E1,0xD27E,0xD280,0xD281,0xCEF7, +0xD282,0xD2AA,0xD283,0xF1FB,0xD284,0xD285,0xB8B2,0xD286, +0xD287,0xD288,0xD289,0xD28A,0xD28B,0xD28C,0xD28D,0xD28E, +0xD28F,0xD290,0xD291,0xD292,0xD293,0xD294,0xD295,0xD296, +0xD297,0xD298,0xD299,0xD29A,0xD29B,0xD29C,0xD29D,0xD29E, +0xD29F,0xD2A0,0xD340,0xD341,0xD342,0xD343,0xD344,0xD345, +0xD346,0xD347,0xD348,0xD349,0xD34A,0xD34B,0xD34C,0xD34D, +0xD34E,0xD34F,0xD350,0xD351,0xD352,0xD353,0xD354,0xD355, +0xD356,0xD357,0xD358,0xD359,0xD35A,0xD35B,0xD35C,0xD35D, +0xD35E,0xBCFB,0xB9DB,0xD35F,0xB9E6,0xC3D9,0xCAD3,0xEAE8, +0xC0C0,0xBEF5,0xEAE9,0xEAEA,0xEAEB,0xD360,0xEAEC,0xEAED, +0xEAEE,0xEAEF,0xBDC7,0xD361,0xD362,0xD363,0xF5FB,0xD364, +0xD365,0xD366,0xF5FD,0xD367,0xF5FE,0xD368,0xF5FC,0xD369, +0xD36A,0xD36B,0xD36C,0xBDE2,0xD36D,0xF6A1,0xB4A5,0xD36E, +0xD36F,0xD370,0xD371,0xF6A2,0xD372,0xD373,0xD374,0xF6A3, +0xD375,0xD376,0xD377,0xECB2,0xD378,0xD379,0xD37A,0xD37B, +0xD37C,0xD37D,0xD37E,0xD380,0xD381,0xD382,0xD383,0xD384, +0xD1D4,0xD385,0xD386,0xD387,0xD388,0xD389,0xD38A,0xD9EA, +0xD38B,0xD38C,0xD38D,0xD38E,0xD38F,0xD390,0xD391,0xD392, +0xD393,0xD394,0xD395,0xD396,0xD397,0xD398,0xD399,0xD39A, +0xD39B,0xD39C,0xD39D,0xD39E,0xD39F,0xD3A0,0xD440,0xD441, +0xD442,0xD443,0xD444,0xD445,0xD446,0xD447,0xD448,0xD449, +0xD44A,0xD44B,0xD44C,0xD44D,0xD44E,0xD44F,0xD450,0xD451, +0xD452,0xD453,0xD454,0xD455,0xD456,0xD457,0xD458,0xD459, +0xD45A,0xD45B,0xD45C,0xD45D,0xD45E,0xD45F,0xF6A4,0xD460, +0xD461,0xD462,0xD463,0xD464,0xD465,0xD466,0xD467,0xD468, +0xEEBA,0xD469,0xD46A,0xD46B,0xD46C,0xD46D,0xD46E,0xD46F, +0xD470,0xD471,0xD472,0xD473,0xD474,0xD475,0xD476,0xD477, +0xD478,0xD479,0xD47A,0xD47B,0xD47C,0xD47D,0xD47E,0xD480, +0xD481,0xD482,0xD483,0xD484,0xD485,0xD486,0xD487,0xD488, +0xD489,0xD48A,0xD48B,0xD48C,0xD48D,0xD48E,0xD48F,0xD490, +0xD491,0xD492,0xD493,0xD494,0xD495,0xD496,0xD497,0xD498, +0xD499,0xD5B2,0xD49A,0xD49B,0xD49C,0xD49D,0xD49E,0xD49F, +0xD4A0,0xD540,0xD541,0xD542,0xD543,0xD544,0xD545,0xD546, +0xD547,0xD3FE,0xCCDC,0xD548,0xD549,0xD54A,0xD54B,0xD54C, +0xD54D,0xD54E,0xD54F,0xCAC4,0xD550,0xD551,0xD552,0xD553, +0xD554,0xD555,0xD556,0xD557,0xD558,0xD559,0xD55A,0xD55B, +0xD55C,0xD55D,0xD55E,0xD55F,0xD560,0xD561,0xD562,0xD563, +0xD564,0xD565,0xD566,0xD567,0xD568,0xD569,0xD56A,0xD56B, +0xD56C,0xD56D,0xD56E,0xD56F,0xD570,0xD571,0xD572,0xD573, +0xD574,0xD575,0xD576,0xD577,0xD578,0xD579,0xD57A,0xD57B, +0xD57C,0xD57D,0xD57E,0xD580,0xD581,0xD582,0xD583,0xD584, +0xD585,0xD586,0xD587,0xD588,0xD589,0xD58A,0xD58B,0xD58C, +0xD58D,0xD58E,0xD58F,0xD590,0xD591,0xD592,0xD593,0xD594, +0xD595,0xD596,0xD597,0xD598,0xD599,0xD59A,0xD59B,0xD59C, +0xD59D,0xD59E,0xD59F,0xD5A0,0xD640,0xD641,0xD642,0xD643, +0xD644,0xD645,0xD646,0xD647,0xD648,0xD649,0xD64A,0xD64B, +0xD64C,0xD64D,0xD64E,0xD64F,0xD650,0xD651,0xD652,0xD653, +0xD654,0xD655,0xD656,0xD657,0xD658,0xD659,0xD65A,0xD65B, +0xD65C,0xD65D,0xD65E,0xD65F,0xD660,0xD661,0xD662,0xE5C0, +0xD663,0xD664,0xD665,0xD666,0xD667,0xD668,0xD669,0xD66A, +0xD66B,0xD66C,0xD66D,0xD66E,0xD66F,0xD670,0xD671,0xD672, +0xD673,0xD674,0xD675,0xD676,0xD677,0xD678,0xD679,0xD67A, +0xD67B,0xD67C,0xD67D,0xD67E,0xD680,0xD681,0xF6A5,0xD682, +0xD683,0xD684,0xD685,0xD686,0xD687,0xD688,0xD689,0xD68A, +0xD68B,0xD68C,0xD68D,0xD68E,0xD68F,0xD690,0xD691,0xD692, +0xD693,0xD694,0xD695,0xD696,0xD697,0xD698,0xD699,0xD69A, +0xD69B,0xD69C,0xD69D,0xD69E,0xD69F,0xD6A0,0xD740,0xD741, +0xD742,0xD743,0xD744,0xD745,0xD746,0xD747,0xD748,0xD749, +0xD74A,0xD74B,0xD74C,0xD74D,0xD74E,0xD74F,0xD750,0xD751, +0xD752,0xD753,0xD754,0xD755,0xD756,0xD757,0xD758,0xD759, +0xD75A,0xD75B,0xD75C,0xD75D,0xD75E,0xD75F,0xBEAF,0xD760, +0xD761,0xD762,0xD763,0xD764,0xC6A9,0xD765,0xD766,0xD767, +0xD768,0xD769,0xD76A,0xD76B,0xD76C,0xD76D,0xD76E,0xD76F, +0xD770,0xD771,0xD772,0xD773,0xD774,0xD775,0xD776,0xD777, +0xD778,0xD779,0xD77A,0xD77B,0xD77C,0xD77D,0xD77E,0xD780, +0xD781,0xD782,0xD783,0xD784,0xD785,0xD786,0xD787,0xD788, +0xD789,0xD78A,0xD78B,0xD78C,0xD78D,0xD78E,0xD78F,0xD790, +0xD791,0xD792,0xD793,0xD794,0xD795,0xD796,0xD797,0xD798, +0xDAA5,0xBCC6,0xB6A9,0xB8BC,0xC8CF,0xBCA5,0xDAA6,0xDAA7, +0xCCD6,0xC8C3,0xDAA8,0xC6FD,0xD799,0xD1B5,0xD2E9,0xD1B6, +0xBCC7,0xD79A,0xBDB2,0xBBE4,0xDAA9,0xDAAA,0xD1C8,0xDAAB, +0xD0ED,0xB6EF,0xC2DB,0xD79B,0xCBCF,0xB7ED,0xC9E8,0xB7C3, +0xBEF7,0xD6A4,0xDAAC,0xDAAD,0xC6C0,0xD7E7,0xCAB6,0xD79C, +0xD5A9,0xCBDF,0xD5EF,0xDAAE,0xD6DF,0xB4CA,0xDAB0,0xDAAF, +0xD79D,0xD2EB,0xDAB1,0xDAB2,0xDAB3,0xCAD4,0xDAB4,0xCAAB, +0xDAB5,0xDAB6,0xB3CF,0xD6EF,0xDAB7,0xBBB0,0xB5AE,0xDAB8, +0xDAB9,0xB9EE,0xD1AF,0xD2E8,0xDABA,0xB8C3,0xCFEA,0xB2EF, +0xDABB,0xDABC,0xD79E,0xBDEB,0xCEDC,0xD3EF,0xDABD,0xCEF3, +0xDABE,0xD3D5,0xBBE5,0xDABF,0xCBB5,0xCBD0,0xDAC0,0xC7EB, +0xD6EE,0xDAC1,0xC5B5,0xB6C1,0xDAC2,0xB7CC,0xBFCE,0xDAC3, +0xDAC4,0xCBAD,0xDAC5,0xB5F7,0xDAC6,0xC1C2,0xD7BB,0xDAC7, +0xCCB8,0xD79F,0xD2EA,0xC4B1,0xDAC8,0xB5FD,0xBBD1,0xDAC9, +0xD0B3,0xDACA,0xDACB,0xCEBD,0xDACC,0xDACD,0xDACE,0xB2F7, +0xDAD1,0xDACF,0xD1E8,0xDAD0,0xC3D5,0xDAD2,0xD7A0,0xDAD3, +0xDAD4,0xDAD5,0xD0BB,0xD2A5,0xB0F9,0xDAD6,0xC7AB,0xDAD7, +0xBDF7,0xC3A1,0xDAD8,0xDAD9,0xC3FD,0xCCB7,0xDADA,0xDADB, +0xC0BE,0xC6D7,0xDADC,0xDADD,0xC7B4,0xDADE,0xDADF,0xB9C8, +0xD840,0xD841,0xD842,0xD843,0xD844,0xD845,0xD846,0xD847, +0xD848,0xBBED,0xD849,0xD84A,0xD84B,0xD84C,0xB6B9,0xF4F8, +0xD84D,0xF4F9,0xD84E,0xD84F,0xCDE3,0xD850,0xD851,0xD852, +0xD853,0xD854,0xD855,0xD856,0xD857,0xF5B9,0xD858,0xD859, +0xD85A,0xD85B,0xEBE0,0xD85C,0xD85D,0xD85E,0xD85F,0xD860, +0xD861,0xCFF3,0xBBBF,0xD862,0xD863,0xD864,0xD865,0xD866, +0xD867,0xD868,0xBAC0,0xD4A5,0xD869,0xD86A,0xD86B,0xD86C, +0xD86D,0xD86E,0xD86F,0xE1D9,0xD870,0xD871,0xD872,0xD873, +0xF5F4,0xB1AA,0xB2F2,0xD874,0xD875,0xD876,0xD877,0xD878, +0xD879,0xD87A,0xF5F5,0xD87B,0xD87C,0xF5F7,0xD87D,0xD87E, +0xD880,0xBAD1,0xF5F6,0xD881,0xC3B2,0xD882,0xD883,0xD884, +0xD885,0xD886,0xD887,0xD888,0xF5F9,0xD889,0xD88A,0xD88B, +0xF5F8,0xD88C,0xD88D,0xD88E,0xD88F,0xD890,0xD891,0xD892, +0xD893,0xD894,0xD895,0xD896,0xD897,0xD898,0xD899,0xD89A, +0xD89B,0xD89C,0xD89D,0xD89E,0xD89F,0xD8A0,0xD940,0xD941, +0xD942,0xD943,0xD944,0xD945,0xD946,0xD947,0xD948,0xD949, +0xD94A,0xD94B,0xD94C,0xD94D,0xD94E,0xD94F,0xD950,0xD951, +0xD952,0xD953,0xD954,0xD955,0xD956,0xD957,0xD958,0xD959, +0xD95A,0xD95B,0xD95C,0xD95D,0xD95E,0xD95F,0xD960,0xD961, +0xD962,0xD963,0xD964,0xD965,0xD966,0xD967,0xD968,0xD969, +0xD96A,0xD96B,0xD96C,0xD96D,0xD96E,0xD96F,0xD970,0xD971, +0xD972,0xD973,0xD974,0xD975,0xD976,0xD977,0xD978,0xD979, +0xD97A,0xD97B,0xD97C,0xD97D,0xD97E,0xD980,0xD981,0xD982, +0xD983,0xD984,0xD985,0xD986,0xD987,0xD988,0xD989,0xD98A, +0xD98B,0xD98C,0xD98D,0xD98E,0xD98F,0xD990,0xD991,0xD992, +0xD993,0xD994,0xD995,0xD996,0xD997,0xD998,0xD999,0xD99A, +0xD99B,0xD99C,0xD99D,0xD99E,0xD99F,0xD9A0,0xDA40,0xDA41, +0xDA42,0xDA43,0xDA44,0xDA45,0xDA46,0xDA47,0xDA48,0xDA49, +0xDA4A,0xDA4B,0xDA4C,0xDA4D,0xDA4E,0xB1B4,0xD5EA,0xB8BA, +0xDA4F,0xB9B1,0xB2C6,0xD4F0,0xCFCD,0xB0DC,0xD5CB,0xBBF5, +0xD6CA,0xB7B7,0xCCB0,0xC6B6,0xB1E1,0xB9BA,0xD6FC,0xB9E1, +0xB7A1,0xBCFA,0xEADA,0xEADB,0xCCF9,0xB9F3,0xEADC,0xB4FB, +0xC3B3,0xB7D1,0xBAD8,0xEADD,0xD4F4,0xEADE,0xBCD6,0xBBDF, +0xEADF,0xC1DE,0xC2B8,0xD4DF,0xD7CA,0xEAE0,0xEAE1,0xEAE4, +0xEAE2,0xEAE3,0xC9DE,0xB8B3,0xB6C4,0xEAE5,0xCAEA,0xC9CD, +0xB4CD,0xDA50,0xDA51,0xE2D9,0xC5E2,0xEAE6,0xC0B5,0xDA52, +0xD7B8,0xEAE7,0xD7AC,0xC8FC,0xD8D3,0xD8CD,0xD4DE,0xDA53, +0xD4F9,0xC9C4,0xD3AE,0xB8D3,0xB3E0,0xDA54,0xC9E2,0xF4F6, +0xDA55,0xDA56,0xDA57,0xBAD5,0xDA58,0xF4F7,0xDA59,0xDA5A, +0xD7DF,0xDA5B,0xDA5C,0xF4F1,0xB8B0,0xD5D4,0xB8CF,0xC6F0, +0xDA5D,0xDA5E,0xDA5F,0xDA60,0xDA61,0xDA62,0xDA63,0xDA64, +0xDA65,0xB3C3,0xDA66,0xDA67,0xF4F2,0xB3AC,0xDA68,0xDA69, +0xDA6A,0xDA6B,0xD4BD,0xC7F7,0xDA6C,0xDA6D,0xDA6E,0xDA6F, +0xDA70,0xF4F4,0xDA71,0xDA72,0xF4F3,0xDA73,0xDA74,0xDA75, +0xDA76,0xDA77,0xDA78,0xDA79,0xDA7A,0xDA7B,0xDA7C,0xCCCB, +0xDA7D,0xDA7E,0xDA80,0xC8A4,0xDA81,0xDA82,0xDA83,0xDA84, +0xDA85,0xDA86,0xDA87,0xDA88,0xDA89,0xDA8A,0xDA8B,0xDA8C, +0xDA8D,0xF4F5,0xDA8E,0xD7E3,0xC5BF,0xF5C0,0xDA8F,0xDA90, +0xF5BB,0xDA91,0xF5C3,0xDA92,0xF5C2,0xDA93,0xD6BA,0xF5C1, +0xDA94,0xDA95,0xDA96,0xD4BE,0xF5C4,0xDA97,0xF5CC,0xDA98, +0xDA99,0xDA9A,0xDA9B,0xB0CF,0xB5F8,0xDA9C,0xF5C9,0xF5CA, +0xDA9D,0xC5DC,0xDA9E,0xDA9F,0xDAA0,0xDB40,0xF5C5,0xF5C6, +0xDB41,0xDB42,0xF5C7,0xF5CB,0xDB43,0xBEE0,0xF5C8,0xB8FA, +0xDB44,0xDB45,0xDB46,0xF5D0,0xF5D3,0xDB47,0xDB48,0xDB49, +0xBFE7,0xDB4A,0xB9F2,0xF5BC,0xF5CD,0xDB4B,0xDB4C,0xC2B7, +0xDB4D,0xDB4E,0xDB4F,0xCCF8,0xDB50,0xBCF9,0xDB51,0xF5CE, +0xF5CF,0xF5D1,0xB6E5,0xF5D2,0xDB52,0xF5D5,0xDB53,0xDB54, +0xDB55,0xDB56,0xDB57,0xDB58,0xDB59,0xF5BD,0xDB5A,0xDB5B, +0xDB5C,0xF5D4,0xD3BB,0xDB5D,0xB3EC,0xDB5E,0xDB5F,0xCCA4, +0xDB60,0xDB61,0xDB62,0xDB63,0xF5D6,0xDB64,0xDB65,0xDB66, +0xDB67,0xDB68,0xDB69,0xDB6A,0xDB6B,0xF5D7,0xBEE1,0xF5D8, +0xDB6C,0xDB6D,0xCCDF,0xF5DB,0xDB6E,0xDB6F,0xDB70,0xDB71, +0xDB72,0xB2C8,0xD7D9,0xDB73,0xF5D9,0xDB74,0xF5DA,0xF5DC, +0xDB75,0xF5E2,0xDB76,0xDB77,0xDB78,0xF5E0,0xDB79,0xDB7A, +0xDB7B,0xF5DF,0xF5DD,0xDB7C,0xDB7D,0xF5E1,0xDB7E,0xDB80, +0xF5DE,0xF5E4,0xF5E5,0xDB81,0xCCE3,0xDB82,0xDB83,0xE5BF, +0xB5B8,0xF5E3,0xF5E8,0xCCA3,0xDB84,0xDB85,0xDB86,0xDB87, +0xDB88,0xF5E6,0xF5E7,0xDB89,0xDB8A,0xDB8B,0xDB8C,0xDB8D, +0xDB8E,0xF5BE,0xDB8F,0xDB90,0xDB91,0xDB92,0xDB93,0xDB94, +0xDB95,0xDB96,0xDB97,0xDB98,0xDB99,0xDB9A,0xB1C4,0xDB9B, +0xDB9C,0xF5BF,0xDB9D,0xDB9E,0xB5C5,0xB2E4,0xDB9F,0xF5EC, +0xF5E9,0xDBA0,0xB6D7,0xDC40,0xF5ED,0xDC41,0xF5EA,0xDC42, +0xDC43,0xDC44,0xDC45,0xDC46,0xF5EB,0xDC47,0xDC48,0xB4DA, +0xDC49,0xD4EA,0xDC4A,0xDC4B,0xDC4C,0xF5EE,0xDC4D,0xB3F9, +0xDC4E,0xDC4F,0xDC50,0xDC51,0xDC52,0xDC53,0xDC54,0xF5EF, +0xF5F1,0xDC55,0xDC56,0xDC57,0xF5F0,0xDC58,0xDC59,0xDC5A, +0xDC5B,0xDC5C,0xDC5D,0xDC5E,0xF5F2,0xDC5F,0xF5F3,0xDC60, +0xDC61,0xDC62,0xDC63,0xDC64,0xDC65,0xDC66,0xDC67,0xDC68, +0xDC69,0xDC6A,0xDC6B,0xC9ED,0xB9AA,0xDC6C,0xDC6D,0xC7FB, +0xDC6E,0xDC6F,0xB6E3,0xDC70,0xDC71,0xDC72,0xDC73,0xDC74, +0xDC75,0xDC76,0xCCC9,0xDC77,0xDC78,0xDC79,0xDC7A,0xDC7B, +0xDC7C,0xDC7D,0xDC7E,0xDC80,0xDC81,0xDC82,0xDC83,0xDC84, +0xDC85,0xDC86,0xDC87,0xDC88,0xDC89,0xDC8A,0xEAA6,0xDC8B, +0xDC8C,0xDC8D,0xDC8E,0xDC8F,0xDC90,0xDC91,0xDC92,0xDC93, +0xDC94,0xDC95,0xDC96,0xDC97,0xDC98,0xDC99,0xDC9A,0xDC9B, +0xDC9C,0xDC9D,0xDC9E,0xDC9F,0xDCA0,0xDD40,0xDD41,0xDD42, +0xDD43,0xDD44,0xDD45,0xDD46,0xDD47,0xDD48,0xDD49,0xDD4A, +0xDD4B,0xDD4C,0xDD4D,0xDD4E,0xDD4F,0xDD50,0xDD51,0xDD52, +0xDD53,0xDD54,0xDD55,0xDD56,0xDD57,0xDD58,0xDD59,0xDD5A, +0xDD5B,0xDD5C,0xDD5D,0xDD5E,0xDD5F,0xDD60,0xDD61,0xDD62, +0xDD63,0xDD64,0xDD65,0xDD66,0xDD67,0xDD68,0xDD69,0xDD6A, +0xDD6B,0xDD6C,0xDD6D,0xDD6E,0xDD6F,0xDD70,0xDD71,0xDD72, +0xDD73,0xDD74,0xDD75,0xDD76,0xDD77,0xDD78,0xDD79,0xDD7A, +0xDD7B,0xDD7C,0xDD7D,0xDD7E,0xDD80,0xDD81,0xDD82,0xDD83, +0xDD84,0xDD85,0xDD86,0xDD87,0xDD88,0xDD89,0xDD8A,0xDD8B, +0xDD8C,0xDD8D,0xDD8E,0xDD8F,0xDD90,0xDD91,0xDD92,0xDD93, +0xDD94,0xDD95,0xDD96,0xDD97,0xDD98,0xDD99,0xDD9A,0xDD9B, +0xDD9C,0xDD9D,0xDD9E,0xDD9F,0xDDA0,0xDE40,0xDE41,0xDE42, +0xDE43,0xDE44,0xDE45,0xDE46,0xDE47,0xDE48,0xDE49,0xDE4A, +0xDE4B,0xDE4C,0xDE4D,0xDE4E,0xDE4F,0xDE50,0xDE51,0xDE52, +0xDE53,0xDE54,0xDE55,0xDE56,0xDE57,0xDE58,0xDE59,0xDE5A, +0xDE5B,0xDE5C,0xDE5D,0xDE5E,0xDE5F,0xDE60,0xB3B5,0xD4FE, +0xB9EC,0xD0F9,0xDE61,0xE9ED,0xD7AA,0xE9EE,0xC2D6,0xC8ED, +0xBAE4,0xE9EF,0xE9F0,0xE9F1,0xD6E1,0xE9F2,0xE9F3,0xE9F5, +0xE9F4,0xE9F6,0xE9F7,0xC7E1,0xE9F8,0xD4D8,0xE9F9,0xBDCE, +0xDE62,0xE9FA,0xE9FB,0xBDCF,0xE9FC,0xB8A8,0xC1BE,0xE9FD, +0xB1B2,0xBBD4,0xB9F5,0xE9FE,0xDE63,0xEAA1,0xEAA2,0xEAA3, +0xB7F8,0xBCAD,0xDE64,0xCAE4,0xE0CE,0xD4AF,0xCFBD,0xD5B7, +0xEAA4,0xD5DE,0xEAA5,0xD0C1,0xB9BC,0xDE65,0xB4C7,0xB1D9, +0xDE66,0xDE67,0xDE68,0xC0B1,0xDE69,0xDE6A,0xDE6B,0xDE6C, +0xB1E6,0xB1E7,0xDE6D,0xB1E8,0xDE6E,0xDE6F,0xDE70,0xDE71, +0xB3BD,0xC8E8,0xDE72,0xDE73,0xDE74,0xDE75,0xE5C1,0xDE76, +0xDE77,0xB1DF,0xDE78,0xDE79,0xDE7A,0xC1C9,0xB4EF,0xDE7B, +0xDE7C,0xC7A8,0xD3D8,0xDE7D,0xC6F9,0xD1B8,0xDE7E,0xB9FD, +0xC2F5,0xDE80,0xDE81,0xDE82,0xDE83,0xDE84,0xD3AD,0xDE85, +0xD4CB,0xBDFC,0xDE86,0xE5C2,0xB7B5,0xE5C3,0xDE87,0xDE88, +0xBBB9,0xD5E2,0xDE89,0xBDF8,0xD4B6,0xCEA5,0xC1AC,0xB3D9, +0xDE8A,0xDE8B,0xCCF6,0xDE8C,0xE5C6,0xE5C4,0xE5C8,0xDE8D, +0xE5CA,0xE5C7,0xB5CF,0xC6C8,0xDE8E,0xB5FC,0xE5C5,0xDE8F, +0xCAF6,0xDE90,0xDE91,0xE5C9,0xDE92,0xDE93,0xDE94,0xC3D4, +0xB1C5,0xBCA3,0xDE95,0xDE96,0xDE97,0xD7B7,0xDE98,0xDE99, +0xCDCB,0xCBCD,0xCACA,0xCCD3,0xE5CC,0xE5CB,0xC4E6,0xDE9A, +0xDE9B,0xD1A1,0xD1B7,0xE5CD,0xDE9C,0xE5D0,0xDE9D,0xCDB8, +0xD6F0,0xE5CF,0xB5DD,0xDE9E,0xCDBE,0xDE9F,0xE5D1,0xB6BA, +0xDEA0,0xDF40,0xCDA8,0xB9E4,0xDF41,0xCAC5,0xB3D1,0xCBD9, +0xD4EC,0xE5D2,0xB7EA,0xDF42,0xDF43,0xDF44,0xE5CE,0xDF45, +0xDF46,0xDF47,0xDF48,0xDF49,0xDF4A,0xE5D5,0xB4FE,0xE5D6, +0xDF4B,0xDF4C,0xDF4D,0xDF4E,0xDF4F,0xE5D3,0xE5D4,0xDF50, +0xD2DD,0xDF51,0xDF52,0xC2DF,0xB1C6,0xDF53,0xD3E2,0xDF54, +0xDF55,0xB6DD,0xCBEC,0xDF56,0xE5D7,0xDF57,0xDF58,0xD3F6, +0xDF59,0xDF5A,0xDF5B,0xDF5C,0xDF5D,0xB1E9,0xDF5E,0xB6F4, +0xE5DA,0xE5D8,0xE5D9,0xB5C0,0xDF5F,0xDF60,0xDF61,0xD2C5, +0xE5DC,0xDF62,0xDF63,0xE5DE,0xDF64,0xDF65,0xDF66,0xDF67, +0xDF68,0xDF69,0xE5DD,0xC7B2,0xDF6A,0xD2A3,0xDF6B,0xDF6C, +0xE5DB,0xDF6D,0xDF6E,0xDF6F,0xDF70,0xD4E2,0xD5DA,0xDF71, +0xDF72,0xDF73,0xDF74,0xDF75,0xE5E0,0xD7F1,0xDF76,0xDF77, +0xDF78,0xDF79,0xDF7A,0xDF7B,0xDF7C,0xE5E1,0xDF7D,0xB1DC, +0xD1FB,0xDF7E,0xE5E2,0xE5E4,0xDF80,0xDF81,0xDF82,0xDF83, +0xE5E3,0xDF84,0xDF85,0xE5E5,0xDF86,0xDF87,0xDF88,0xDF89, +0xDF8A,0xD2D8,0xDF8B,0xB5CB,0xDF8C,0xE7DF,0xDF8D,0xDAF5, +0xDF8E,0xDAF8,0xDF8F,0xDAF6,0xDF90,0xDAF7,0xDF91,0xDF92, +0xDF93,0xDAFA,0xD0CF,0xC4C7,0xDF94,0xDF95,0xB0EE,0xDF96, +0xDF97,0xDF98,0xD0B0,0xDF99,0xDAF9,0xDF9A,0xD3CA,0xBAAA, +0xDBA2,0xC7F1,0xDF9B,0xDAFC,0xDAFB,0xC9DB,0xDAFD,0xDF9C, +0xDBA1,0xD7DE,0xDAFE,0xC1DA,0xDF9D,0xDF9E,0xDBA5,0xDF9F, +0xDFA0,0xD3F4,0xE040,0xE041,0xDBA7,0xDBA4,0xE042,0xDBA8, +0xE043,0xE044,0xBDBC,0xE045,0xE046,0xE047,0xC0C9,0xDBA3, +0xDBA6,0xD6A3,0xE048,0xDBA9,0xE049,0xE04A,0xE04B,0xDBAD, +0xE04C,0xE04D,0xE04E,0xDBAE,0xDBAC,0xBAC2,0xE04F,0xE050, +0xE051,0xBFA4,0xDBAB,0xE052,0xE053,0xE054,0xDBAA,0xD4C7, +0xB2BF,0xE055,0xE056,0xDBAF,0xE057,0xB9F9,0xE058,0xDBB0, +0xE059,0xE05A,0xE05B,0xE05C,0xB3BB,0xE05D,0xE05E,0xE05F, +0xB5A6,0xE060,0xE061,0xE062,0xE063,0xB6BC,0xDBB1,0xE064, +0xE065,0xE066,0xB6F5,0xE067,0xDBB2,0xE068,0xE069,0xE06A, +0xE06B,0xE06C,0xE06D,0xE06E,0xE06F,0xE070,0xE071,0xE072, +0xE073,0xE074,0xE075,0xE076,0xE077,0xE078,0xE079,0xE07A, +0xE07B,0xB1C9,0xE07C,0xE07D,0xE07E,0xE080,0xDBB4,0xE081, +0xE082,0xE083,0xDBB3,0xDBB5,0xE084,0xE085,0xE086,0xE087, +0xE088,0xE089,0xE08A,0xE08B,0xE08C,0xE08D,0xE08E,0xDBB7, +0xE08F,0xDBB6,0xE090,0xE091,0xE092,0xE093,0xE094,0xE095, +0xE096,0xDBB8,0xE097,0xE098,0xE099,0xE09A,0xE09B,0xE09C, +0xE09D,0xE09E,0xE09F,0xDBB9,0xE0A0,0xE140,0xDBBA,0xE141, +0xE142,0xD3CF,0xF4FA,0xC7F5,0xD7C3,0xC5E4,0xF4FC,0xF4FD, +0xF4FB,0xE143,0xBEC6,0xE144,0xE145,0xE146,0xE147,0xD0EF, +0xE148,0xE149,0xB7D3,0xE14A,0xE14B,0xD4CD,0xCCAA,0xE14C, +0xE14D,0xF5A2,0xF5A1,0xBAA8,0xF4FE,0xCBD6,0xE14E,0xE14F, +0xE150,0xF5A4,0xC0D2,0xE151,0xB3EA,0xE152,0xCDAA,0xF5A5, +0xF5A3,0xBDB4,0xF5A8,0xE153,0xF5A9,0xBDCD,0xC3B8,0xBFE1, +0xCBE1,0xF5AA,0xE154,0xE155,0xE156,0xF5A6,0xF5A7,0xC4F0, +0xE157,0xE158,0xE159,0xE15A,0xE15B,0xF5AC,0xE15C,0xB4BC, +0xE15D,0xD7ED,0xE15E,0xB4D7,0xF5AB,0xF5AE,0xE15F,0xE160, +0xF5AD,0xF5AF,0xD0D1,0xE161,0xE162,0xE163,0xE164,0xE165, +0xE166,0xE167,0xC3D1,0xC8A9,0xE168,0xE169,0xE16A,0xE16B, +0xE16C,0xE16D,0xF5B0,0xF5B1,0xE16E,0xE16F,0xE170,0xE171, +0xE172,0xE173,0xF5B2,0xE174,0xE175,0xF5B3,0xF5B4,0xF5B5, +0xE176,0xE177,0xE178,0xE179,0xF5B7,0xF5B6,0xE17A,0xE17B, +0xE17C,0xE17D,0xF5B8,0xE17E,0xE180,0xE181,0xE182,0xE183, +0xE184,0xE185,0xE186,0xE187,0xE188,0xE189,0xE18A,0xB2C9, +0xE18B,0xD3D4,0xCACD,0xE18C,0xC0EF,0xD6D8,0xD2B0,0xC1BF, +0xE18D,0xBDF0,0xE18E,0xE18F,0xE190,0xE191,0xE192,0xE193, +0xE194,0xE195,0xE196,0xE197,0xB8AA,0xE198,0xE199,0xE19A, +0xE19B,0xE19C,0xE19D,0xE19E,0xE19F,0xE1A0,0xE240,0xE241, +0xE242,0xE243,0xE244,0xE245,0xE246,0xE247,0xE248,0xE249, +0xE24A,0xE24B,0xE24C,0xE24D,0xE24E,0xE24F,0xE250,0xE251, +0xE252,0xE253,0xE254,0xE255,0xE256,0xE257,0xE258,0xE259, +0xE25A,0xE25B,0xE25C,0xE25D,0xE25E,0xE25F,0xE260,0xE261, +0xE262,0xE263,0xE264,0xE265,0xE266,0xE267,0xE268,0xE269, +0xE26A,0xE26B,0xE26C,0xE26D,0xE26E,0xE26F,0xE270,0xE271, +0xE272,0xE273,0xE274,0xE275,0xE276,0xE277,0xE278,0xE279, +0xE27A,0xE27B,0xE27C,0xE27D,0xE27E,0xE280,0xE281,0xE282, +0xE283,0xE284,0xE285,0xE286,0xE287,0xE288,0xE289,0xE28A, +0xE28B,0xE28C,0xE28D,0xE28E,0xE28F,0xE290,0xE291,0xE292, +0xE293,0xE294,0xE295,0xE296,0xE297,0xE298,0xE299,0xE29A, +0xE29B,0xE29C,0xE29D,0xE29E,0xE29F,0xE2A0,0xE340,0xE341, +0xE342,0xE343,0xE344,0xE345,0xE346,0xE347,0xE348,0xE349, +0xE34A,0xE34B,0xE34C,0xE34D,0xE34E,0xE34F,0xE350,0xE351, +0xE352,0xE353,0xE354,0xE355,0xE356,0xE357,0xE358,0xE359, +0xE35A,0xE35B,0xE35C,0xE35D,0xE35E,0xE35F,0xE360,0xE361, +0xE362,0xE363,0xE364,0xE365,0xE366,0xE367,0xE368,0xE369, +0xE36A,0xE36B,0xE36C,0xE36D,0xBCF8,0xE36E,0xE36F,0xE370, +0xE371,0xE372,0xE373,0xE374,0xE375,0xE376,0xE377,0xE378, +0xE379,0xE37A,0xE37B,0xE37C,0xE37D,0xE37E,0xE380,0xE381, +0xE382,0xE383,0xE384,0xE385,0xE386,0xE387,0xF6C6,0xE388, +0xE389,0xE38A,0xE38B,0xE38C,0xE38D,0xE38E,0xE38F,0xE390, +0xE391,0xE392,0xE393,0xE394,0xE395,0xE396,0xE397,0xE398, +0xE399,0xE39A,0xE39B,0xE39C,0xE39D,0xE39E,0xE39F,0xE3A0, +0xE440,0xE441,0xE442,0xE443,0xE444,0xE445,0xF6C7,0xE446, +0xE447,0xE448,0xE449,0xE44A,0xE44B,0xE44C,0xE44D,0xE44E, +0xE44F,0xE450,0xE451,0xE452,0xE453,0xE454,0xE455,0xE456, +0xE457,0xE458,0xE459,0xE45A,0xE45B,0xE45C,0xE45D,0xE45E, +0xF6C8,0xE45F,0xE460,0xE461,0xE462,0xE463,0xE464,0xE465, +0xE466,0xE467,0xE468,0xE469,0xE46A,0xE46B,0xE46C,0xE46D, +0xE46E,0xE46F,0xE470,0xE471,0xE472,0xE473,0xE474,0xE475, +0xE476,0xE477,0xE478,0xE479,0xE47A,0xE47B,0xE47C,0xE47D, +0xE47E,0xE480,0xE481,0xE482,0xE483,0xE484,0xE485,0xE486, +0xE487,0xE488,0xE489,0xE48A,0xE48B,0xE48C,0xE48D,0xE48E, +0xE48F,0xE490,0xE491,0xE492,0xE493,0xE494,0xE495,0xE496, +0xE497,0xE498,0xE499,0xE49A,0xE49B,0xE49C,0xE49D,0xE49E, +0xE49F,0xE4A0,0xE540,0xE541,0xE542,0xE543,0xE544,0xE545, +0xE546,0xE547,0xE548,0xE549,0xE54A,0xE54B,0xE54C,0xE54D, +0xE54E,0xE54F,0xE550,0xE551,0xE552,0xE553,0xE554,0xE555, +0xE556,0xE557,0xE558,0xE559,0xE55A,0xE55B,0xE55C,0xE55D, +0xE55E,0xE55F,0xE560,0xE561,0xE562,0xE563,0xE564,0xE565, +0xE566,0xE567,0xE568,0xE569,0xE56A,0xE56B,0xE56C,0xE56D, +0xE56E,0xE56F,0xE570,0xE571,0xE572,0xE573,0xF6C9,0xE574, +0xE575,0xE576,0xE577,0xE578,0xE579,0xE57A,0xE57B,0xE57C, +0xE57D,0xE57E,0xE580,0xE581,0xE582,0xE583,0xE584,0xE585, +0xE586,0xE587,0xE588,0xE589,0xE58A,0xE58B,0xE58C,0xE58D, +0xE58E,0xE58F,0xE590,0xE591,0xE592,0xE593,0xE594,0xE595, +0xE596,0xE597,0xE598,0xE599,0xE59A,0xE59B,0xE59C,0xE59D, +0xE59E,0xE59F,0xF6CA,0xE5A0,0xE640,0xE641,0xE642,0xE643, +0xE644,0xE645,0xE646,0xE647,0xE648,0xE649,0xE64A,0xE64B, +0xE64C,0xE64D,0xE64E,0xE64F,0xE650,0xE651,0xE652,0xE653, +0xE654,0xE655,0xE656,0xE657,0xE658,0xE659,0xE65A,0xE65B, +0xE65C,0xE65D,0xE65E,0xE65F,0xE660,0xE661,0xE662,0xF6CC, +0xE663,0xE664,0xE665,0xE666,0xE667,0xE668,0xE669,0xE66A, +0xE66B,0xE66C,0xE66D,0xE66E,0xE66F,0xE670,0xE671,0xE672, +0xE673,0xE674,0xE675,0xE676,0xE677,0xE678,0xE679,0xE67A, +0xE67B,0xE67C,0xE67D,0xE67E,0xE680,0xE681,0xE682,0xE683, +0xE684,0xE685,0xE686,0xE687,0xE688,0xE689,0xE68A,0xE68B, +0xE68C,0xE68D,0xE68E,0xE68F,0xE690,0xE691,0xE692,0xE693, +0xE694,0xE695,0xE696,0xE697,0xE698,0xE699,0xE69A,0xE69B, +0xE69C,0xE69D,0xF6CB,0xE69E,0xE69F,0xE6A0,0xE740,0xE741, +0xE742,0xE743,0xE744,0xE745,0xE746,0xE747,0xF7E9,0xE748, +0xE749,0xE74A,0xE74B,0xE74C,0xE74D,0xE74E,0xE74F,0xE750, +0xE751,0xE752,0xE753,0xE754,0xE755,0xE756,0xE757,0xE758, +0xE759,0xE75A,0xE75B,0xE75C,0xE75D,0xE75E,0xE75F,0xE760, +0xE761,0xE762,0xE763,0xE764,0xE765,0xE766,0xE767,0xE768, +0xE769,0xE76A,0xE76B,0xE76C,0xE76D,0xE76E,0xE76F,0xE770, +0xE771,0xE772,0xE773,0xE774,0xE775,0xE776,0xE777,0xE778, +0xE779,0xE77A,0xE77B,0xE77C,0xE77D,0xE77E,0xE780,0xE781, +0xE782,0xE783,0xE784,0xE785,0xE786,0xE787,0xE788,0xE789, +0xE78A,0xE78B,0xE78C,0xE78D,0xE78E,0xE78F,0xE790,0xE791, +0xE792,0xE793,0xE794,0xE795,0xE796,0xE797,0xE798,0xE799, +0xE79A,0xE79B,0xE79C,0xE79D,0xE79E,0xE79F,0xE7A0,0xE840, +0xE841,0xE842,0xE843,0xE844,0xE845,0xE846,0xE847,0xE848, +0xE849,0xE84A,0xE84B,0xE84C,0xE84D,0xE84E,0xF6CD,0xE84F, +0xE850,0xE851,0xE852,0xE853,0xE854,0xE855,0xE856,0xE857, +0xE858,0xE859,0xE85A,0xE85B,0xE85C,0xE85D,0xE85E,0xE85F, +0xE860,0xE861,0xE862,0xE863,0xE864,0xE865,0xE866,0xE867, +0xE868,0xE869,0xE86A,0xE86B,0xE86C,0xE86D,0xE86E,0xE86F, +0xE870,0xE871,0xE872,0xE873,0xE874,0xE875,0xE876,0xE877, +0xE878,0xE879,0xE87A,0xF6CE,0xE87B,0xE87C,0xE87D,0xE87E, +0xE880,0xE881,0xE882,0xE883,0xE884,0xE885,0xE886,0xE887, +0xE888,0xE889,0xE88A,0xE88B,0xE88C,0xE88D,0xE88E,0xE88F, +0xE890,0xE891,0xE892,0xE893,0xE894,0xEEC4,0xEEC5,0xEEC6, +0xD5EB,0xB6A4,0xEEC8,0xEEC7,0xEEC9,0xEECA,0xC7A5,0xEECB, +0xEECC,0xE895,0xB7B0,0xB5F6,0xEECD,0xEECF,0xE896,0xEECE, +0xE897,0xB8C6,0xEED0,0xEED1,0xEED2,0xB6DB,0xB3AE,0xD6D3, +0xC4C6,0xB1B5,0xB8D6,0xEED3,0xEED4,0xD4BF,0xC7D5,0xBEFB, +0xCED9,0xB9B3,0xEED6,0xEED5,0xEED8,0xEED7,0xC5A5,0xEED9, +0xEEDA,0xC7AE,0xEEDB,0xC7AF,0xEEDC,0xB2A7,0xEEDD,0xEEDE, +0xEEDF,0xEEE0,0xEEE1,0xD7EA,0xEEE2,0xEEE3,0xBCD8,0xEEE4, +0xD3CB,0xCCFA,0xB2AC,0xC1E5,0xEEE5,0xC7A6,0xC3AD,0xE898, +0xEEE6,0xEEE7,0xEEE8,0xEEE9,0xEEEA,0xEEEB,0xEEEC,0xE899, +0xEEED,0xEEEE,0xEEEF,0xE89A,0xE89B,0xEEF0,0xEEF1,0xEEF2, +0xEEF4,0xEEF3,0xE89C,0xEEF5,0xCDAD,0xC2C1,0xEEF6,0xEEF7, +0xEEF8,0xD5A1,0xEEF9,0xCFB3,0xEEFA,0xEEFB,0xE89D,0xEEFC, +0xEEFD,0xEFA1,0xEEFE,0xEFA2,0xB8F5,0xC3FA,0xEFA3,0xEFA4, +0xBDC2,0xD2BF,0xB2F9,0xEFA5,0xEFA6,0xEFA7,0xD2F8,0xEFA8, +0xD6FD,0xEFA9,0xC6CC,0xE89E,0xEFAA,0xEFAB,0xC1B4,0xEFAC, +0xCFFA,0xCBF8,0xEFAE,0xEFAD,0xB3FA,0xB9F8,0xEFAF,0xEFB0, +0xD0E2,0xEFB1,0xEFB2,0xB7E6,0xD0BF,0xEFB3,0xEFB4,0xEFB5, +0xC8F1,0xCCE0,0xEFB6,0xEFB7,0xEFB8,0xEFB9,0xEFBA,0xD5E0, +0xEFBB,0xB4ED,0xC3AA,0xEFBC,0xE89F,0xEFBD,0xEFBE,0xEFBF, +0xE8A0,0xCEFD,0xEFC0,0xC2E0,0xB4B8,0xD7B6,0xBDF5,0xE940, +0xCFC7,0xEFC3,0xEFC1,0xEFC2,0xEFC4,0xB6A7,0xBCFC,0xBEE2, +0xC3CC,0xEFC5,0xEFC6,0xE941,0xEFC7,0xEFCF,0xEFC8,0xEFC9, +0xEFCA,0xC7C2,0xEFF1,0xB6CD,0xEFCB,0xE942,0xEFCC,0xEFCD, +0xB6C6,0xC3BE,0xEFCE,0xE943,0xEFD0,0xEFD1,0xEFD2,0xD5F2, +0xE944,0xEFD3,0xC4F7,0xE945,0xEFD4,0xC4F8,0xEFD5,0xEFD6, +0xB8E4,0xB0F7,0xEFD7,0xEFD8,0xEFD9,0xE946,0xEFDA,0xEFDB, +0xEFDC,0xEFDD,0xE947,0xEFDE,0xBEB5,0xEFE1,0xEFDF,0xEFE0, +0xE948,0xEFE2,0xEFE3,0xC1CD,0xEFE4,0xEFE5,0xEFE6,0xEFE7, +0xEFE8,0xEFE9,0xEFEA,0xEFEB,0xEFEC,0xC0D8,0xE949,0xEFED, +0xC1AD,0xEFEE,0xEFEF,0xEFF0,0xE94A,0xE94B,0xCFE2,0xE94C, +0xE94D,0xE94E,0xE94F,0xE950,0xE951,0xE952,0xE953,0xB3A4, +0xE954,0xE955,0xE956,0xE957,0xE958,0xE959,0xE95A,0xE95B, +0xE95C,0xE95D,0xE95E,0xE95F,0xE960,0xE961,0xE962,0xE963, +0xE964,0xE965,0xE966,0xE967,0xE968,0xE969,0xE96A,0xE96B, +0xE96C,0xE96D,0xE96E,0xE96F,0xE970,0xE971,0xE972,0xE973, +0xE974,0xE975,0xE976,0xE977,0xE978,0xE979,0xE97A,0xE97B, +0xE97C,0xE97D,0xE97E,0xE980,0xE981,0xE982,0xE983,0xE984, +0xE985,0xE986,0xE987,0xE988,0xE989,0xE98A,0xE98B,0xE98C, +0xE98D,0xE98E,0xE98F,0xE990,0xE991,0xE992,0xE993,0xE994, +0xE995,0xE996,0xE997,0xE998,0xE999,0xE99A,0xE99B,0xE99C, +0xE99D,0xE99E,0xE99F,0xE9A0,0xEA40,0xEA41,0xEA42,0xEA43, +0xEA44,0xEA45,0xEA46,0xEA47,0xEA48,0xEA49,0xEA4A,0xEA4B, +0xEA4C,0xEA4D,0xEA4E,0xEA4F,0xEA50,0xEA51,0xEA52,0xEA53, +0xEA54,0xEA55,0xEA56,0xEA57,0xEA58,0xEA59,0xEA5A,0xEA5B, +0xC3C5,0xE3C5,0xC9C1,0xE3C6,0xEA5C,0xB1D5,0xCECA,0xB4B3, +0xC8F2,0xE3C7,0xCFD0,0xE3C8,0xBCE4,0xE3C9,0xE3CA,0xC3C6, +0xD5A2,0xC4D6,0xB9EB,0xCEC5,0xE3CB,0xC3F6,0xE3CC,0xEA5D, +0xB7A7,0xB8F3,0xBAD2,0xE3CD,0xE3CE,0xD4C4,0xE3CF,0xEA5E, +0xE3D0,0xD1CB,0xE3D1,0xE3D2,0xE3D3,0xE3D4,0xD1D6,0xE3D5, +0xB2FB,0xC0BB,0xE3D6,0xEA5F,0xC0AB,0xE3D7,0xE3D8,0xE3D9, +0xEA60,0xE3DA,0xE3DB,0xEA61,0xB8B7,0xDAE2,0xEA62,0xB6D3, +0xEA63,0xDAE4,0xDAE3,0xEA64,0xEA65,0xEA66,0xEA67,0xEA68, +0xEA69,0xEA6A,0xDAE6,0xEA6B,0xEA6C,0xEA6D,0xC8EE,0xEA6E, +0xEA6F,0xDAE5,0xB7C0,0xD1F4,0xD2F5,0xD5F3,0xBDD7,0xEA70, +0xEA71,0xEA72,0xEA73,0xD7E8,0xDAE8,0xDAE7,0xEA74,0xB0A2, +0xCDD3,0xEA75,0xDAE9,0xEA76,0xB8BD,0xBCCA,0xC2BD,0xC2A4, +0xB3C2,0xDAEA,0xEA77,0xC2AA,0xC4B0,0xBDB5,0xEA78,0xEA79, +0xCFDE,0xEA7A,0xEA7B,0xEA7C,0xDAEB,0xC9C2,0xEA7D,0xEA7E, +0xEA80,0xEA81,0xEA82,0xB1DD,0xEA83,0xEA84,0xEA85,0xDAEC, +0xEA86,0xB6B8,0xD4BA,0xEA87,0xB3FD,0xEA88,0xEA89,0xDAED, +0xD4C9,0xCFD5,0xC5E3,0xEA8A,0xDAEE,0xEA8B,0xEA8C,0xEA8D, +0xEA8E,0xEA8F,0xDAEF,0xEA90,0xDAF0,0xC1EA,0xCCD5,0xCFDD, +0xEA91,0xEA92,0xEA93,0xEA94,0xEA95,0xEA96,0xEA97,0xEA98, +0xEA99,0xEA9A,0xEA9B,0xEA9C,0xEA9D,0xD3E7,0xC2A1,0xEA9E, +0xDAF1,0xEA9F,0xEAA0,0xCBE5,0xEB40,0xDAF2,0xEB41,0xCBE6, +0xD2FE,0xEB42,0xEB43,0xEB44,0xB8F4,0xEB45,0xEB46,0xDAF3, +0xB0AF,0xCFB6,0xEB47,0xEB48,0xD5CF,0xEB49,0xEB4A,0xEB4B, +0xEB4C,0xEB4D,0xEB4E,0xEB4F,0xEB50,0xEB51,0xEB52,0xCBED, +0xEB53,0xEB54,0xEB55,0xEB56,0xEB57,0xEB58,0xEB59,0xEB5A, +0xDAF4,0xEB5B,0xEB5C,0xE3C4,0xEB5D,0xEB5E,0xC1A5,0xEB5F, +0xEB60,0xF6BF,0xEB61,0xEB62,0xF6C0,0xF6C1,0xC4D1,0xEB63, +0xC8B8,0xD1E3,0xEB64,0xEB65,0xD0DB,0xD1C5,0xBCAF,0xB9CD, +0xEB66,0xEFF4,0xEB67,0xEB68,0xB4C6,0xD3BA,0xF6C2,0xB3FB, +0xEB69,0xEB6A,0xF6C3,0xEB6B,0xEB6C,0xB5F1,0xEB6D,0xEB6E, +0xEB6F,0xEB70,0xEB71,0xEB72,0xEB73,0xEB74,0xEB75,0xEB76, +0xF6C5,0xEB77,0xEB78,0xEB79,0xEB7A,0xEB7B,0xEB7C,0xEB7D, +0xD3EA,0xF6A7,0xD1A9,0xEB7E,0xEB80,0xEB81,0xEB82,0xF6A9, +0xEB83,0xEB84,0xEB85,0xF6A8,0xEB86,0xEB87,0xC1E3,0xC0D7, +0xEB88,0xB1A2,0xEB89,0xEB8A,0xEB8B,0xEB8C,0xCEED,0xEB8D, +0xD0E8,0xF6AB,0xEB8E,0xEB8F,0xCFF6,0xEB90,0xF6AA,0xD5F0, +0xF6AC,0xC3B9,0xEB91,0xEB92,0xEB93,0xBBF4,0xF6AE,0xF6AD, +0xEB94,0xEB95,0xEB96,0xC4DE,0xEB97,0xEB98,0xC1D8,0xEB99, +0xEB9A,0xEB9B,0xEB9C,0xEB9D,0xCBAA,0xEB9E,0xCFBC,0xEB9F, +0xEBA0,0xEC40,0xEC41,0xEC42,0xEC43,0xEC44,0xEC45,0xEC46, +0xEC47,0xEC48,0xF6AF,0xEC49,0xEC4A,0xF6B0,0xEC4B,0xEC4C, +0xF6B1,0xEC4D,0xC2B6,0xEC4E,0xEC4F,0xEC50,0xEC51,0xEC52, +0xB0D4,0xC5F9,0xEC53,0xEC54,0xEC55,0xEC56,0xF6B2,0xEC57, +0xEC58,0xEC59,0xEC5A,0xEC5B,0xEC5C,0xEC5D,0xEC5E,0xEC5F, +0xEC60,0xEC61,0xEC62,0xEC63,0xEC64,0xEC65,0xEC66,0xEC67, +0xEC68,0xEC69,0xC7E0,0xF6A6,0xEC6A,0xEC6B,0xBEB8,0xEC6C, +0xEC6D,0xBEB2,0xEC6E,0xB5E5,0xEC6F,0xEC70,0xB7C7,0xEC71, +0xBFBF,0xC3D2,0xC3E6,0xEC72,0xEC73,0xD8CC,0xEC74,0xEC75, +0xEC76,0xB8EF,0xEC77,0xEC78,0xEC79,0xEC7A,0xEC7B,0xEC7C, +0xEC7D,0xEC7E,0xEC80,0xBDF9,0xD1A5,0xEC81,0xB0D0,0xEC82, +0xEC83,0xEC84,0xEC85,0xEC86,0xF7B0,0xEC87,0xEC88,0xEC89, +0xEC8A,0xEC8B,0xEC8C,0xEC8D,0xEC8E,0xF7B1,0xEC8F,0xEC90, +0xEC91,0xEC92,0xEC93,0xD0AC,0xEC94,0xB0B0,0xEC95,0xEC96, +0xEC97,0xF7B2,0xF7B3,0xEC98,0xF7B4,0xEC99,0xEC9A,0xEC9B, +0xC7CA,0xEC9C,0xEC9D,0xEC9E,0xEC9F,0xECA0,0xED40,0xED41, +0xBECF,0xED42,0xED43,0xF7B7,0xED44,0xED45,0xED46,0xED47, +0xED48,0xED49,0xED4A,0xF7B6,0xED4B,0xB1DE,0xED4C,0xF7B5, +0xED4D,0xED4E,0xF7B8,0xED4F,0xF7B9,0xED50,0xED51,0xED52, +0xED53,0xED54,0xED55,0xED56,0xED57,0xED58,0xED59,0xED5A, +0xED5B,0xED5C,0xED5D,0xED5E,0xED5F,0xED60,0xED61,0xED62, +0xED63,0xED64,0xED65,0xED66,0xED67,0xED68,0xED69,0xED6A, +0xED6B,0xED6C,0xED6D,0xED6E,0xED6F,0xED70,0xED71,0xED72, +0xED73,0xED74,0xED75,0xED76,0xED77,0xED78,0xED79,0xED7A, +0xED7B,0xED7C,0xED7D,0xED7E,0xED80,0xED81,0xCEA4,0xC8CD, +0xED82,0xBAAB,0xE8B8,0xE8B9,0xE8BA,0xBEC2,0xED83,0xED84, +0xED85,0xED86,0xED87,0xD2F4,0xED88,0xD4CF,0xC9D8,0xED89, +0xED8A,0xED8B,0xED8C,0xED8D,0xED8E,0xED8F,0xED90,0xED91, +0xED92,0xED93,0xED94,0xED95,0xED96,0xED97,0xED98,0xED99, +0xED9A,0xED9B,0xED9C,0xED9D,0xED9E,0xED9F,0xEDA0,0xEE40, +0xEE41,0xEE42,0xEE43,0xEE44,0xEE45,0xEE46,0xEE47,0xEE48, +0xEE49,0xEE4A,0xEE4B,0xEE4C,0xEE4D,0xEE4E,0xEE4F,0xEE50, +0xEE51,0xEE52,0xEE53,0xEE54,0xEE55,0xEE56,0xEE57,0xEE58, +0xEE59,0xEE5A,0xEE5B,0xEE5C,0xEE5D,0xEE5E,0xEE5F,0xEE60, +0xEE61,0xEE62,0xEE63,0xEE64,0xEE65,0xEE66,0xEE67,0xEE68, +0xEE69,0xEE6A,0xEE6B,0xEE6C,0xEE6D,0xEE6E,0xEE6F,0xEE70, +0xEE71,0xEE72,0xEE73,0xEE74,0xEE75,0xEE76,0xEE77,0xEE78, +0xEE79,0xEE7A,0xEE7B,0xEE7C,0xEE7D,0xEE7E,0xEE80,0xEE81, +0xEE82,0xEE83,0xEE84,0xEE85,0xEE86,0xEE87,0xEE88,0xEE89, +0xEE8A,0xEE8B,0xEE8C,0xEE8D,0xEE8E,0xEE8F,0xEE90,0xEE91, +0xEE92,0xEE93,0xEE94,0xEE95,0xEE96,0xEE97,0xEE98,0xEE99, +0xEE9A,0xEE9B,0xEE9C,0xEE9D,0xEE9E,0xEE9F,0xEEA0,0xEF40, +0xEF41,0xEF42,0xEF43,0xEF44,0xEF45,0xD2B3,0xB6A5,0xC7EA, +0xF1FC,0xCFEE,0xCBB3,0xD0EB,0xE7EF,0xCDE7,0xB9CB,0xB6D9, +0xF1FD,0xB0E4,0xCBCC,0xF1FE,0xD4A4,0xC2AD,0xC1EC,0xC6C4, +0xBEB1,0xF2A1,0xBCD5,0xEF46,0xF2A2,0xF2A3,0xEF47,0xF2A4, +0xD2C3,0xC6B5,0xEF48,0xCDC7,0xF2A5,0xEF49,0xD3B1,0xBFC5, +0xCCE2,0xEF4A,0xF2A6,0xF2A7,0xD1D5,0xB6EE,0xF2A8,0xF2A9, +0xB5DF,0xF2AA,0xF2AB,0xEF4B,0xB2FC,0xF2AC,0xF2AD,0xC8A7, +0xEF4C,0xEF4D,0xEF4E,0xEF4F,0xEF50,0xEF51,0xEF52,0xEF53, +0xEF54,0xEF55,0xEF56,0xEF57,0xEF58,0xEF59,0xEF5A,0xEF5B, +0xEF5C,0xEF5D,0xEF5E,0xEF5F,0xEF60,0xEF61,0xEF62,0xEF63, +0xEF64,0xEF65,0xEF66,0xEF67,0xEF68,0xEF69,0xEF6A,0xEF6B, +0xEF6C,0xEF6D,0xEF6E,0xEF6F,0xEF70,0xEF71,0xB7E7,0xEF72, +0xEF73,0xECA9,0xECAA,0xECAB,0xEF74,0xECAC,0xEF75,0xEF76, +0xC6AE,0xECAD,0xECAE,0xEF77,0xEF78,0xEF79,0xB7C9,0xCAB3, +0xEF7A,0xEF7B,0xEF7C,0xEF7D,0xEF7E,0xEF80,0xEF81,0xE2B8, +0xF7CF,0xEF82,0xEF83,0xEF84,0xEF85,0xEF86,0xEF87,0xEF88, +0xEF89,0xEF8A,0xEF8B,0xEF8C,0xEF8D,0xEF8E,0xEF8F,0xEF90, +0xEF91,0xEF92,0xEF93,0xEF94,0xEF95,0xEF96,0xEF97,0xEF98, +0xEF99,0xEF9A,0xEF9B,0xEF9C,0xEF9D,0xEF9E,0xEF9F,0xEFA0, +0xF040,0xF041,0xF042,0xF043,0xF044,0xF7D0,0xF045,0xF046, +0xB2CD,0xF047,0xF048,0xF049,0xF04A,0xF04B,0xF04C,0xF04D, +0xF04E,0xF04F,0xF050,0xF051,0xF052,0xF053,0xF054,0xF055, +0xF056,0xF057,0xF058,0xF059,0xF05A,0xF05B,0xF05C,0xF05D, +0xF05E,0xF05F,0xF060,0xF061,0xF062,0xF063,0xF7D1,0xF064, +0xF065,0xF066,0xF067,0xF068,0xF069,0xF06A,0xF06B,0xF06C, +0xF06D,0xF06E,0xF06F,0xF070,0xF071,0xF072,0xF073,0xF074, +0xF075,0xF076,0xF077,0xF078,0xF079,0xF07A,0xF07B,0xF07C, +0xF07D,0xF07E,0xF080,0xF081,0xF082,0xF083,0xF084,0xF085, +0xF086,0xF087,0xF088,0xF089,0xF7D3,0xF7D2,0xF08A,0xF08B, +0xF08C,0xF08D,0xF08E,0xF08F,0xF090,0xF091,0xF092,0xF093, +0xF094,0xF095,0xF096,0xE2BB,0xF097,0xBCA2,0xF098,0xE2BC, +0xE2BD,0xE2BE,0xE2BF,0xE2C0,0xE2C1,0xB7B9,0xD2FB,0xBDA4, +0xCACE,0xB1A5,0xCBC7,0xF099,0xE2C2,0xB6FC,0xC8C4,0xE2C3, +0xF09A,0xF09B,0xBDC8,0xF09C,0xB1FD,0xE2C4,0xF09D,0xB6F6, +0xE2C5,0xC4D9,0xF09E,0xF09F,0xE2C6,0xCFDA,0xB9DD,0xE2C7, +0xC0A1,0xF0A0,0xE2C8,0xB2F6,0xF140,0xE2C9,0xF141,0xC1F3, +0xE2CA,0xE2CB,0xC2F8,0xE2CC,0xE2CD,0xE2CE,0xCAD7,0xD8B8, +0xD9E5,0xCFE3,0xF142,0xF143,0xF144,0xF145,0xF146,0xF147, +0xF148,0xF149,0xF14A,0xF14B,0xF14C,0xF0A5,0xF14D,0xF14E, +0xDCB0,0xF14F,0xF150,0xF151,0xF152,0xF153,0xF154,0xF155, +0xF156,0xF157,0xF158,0xF159,0xF15A,0xF15B,0xF15C,0xF15D, +0xF15E,0xF15F,0xF160,0xF161,0xF162,0xF163,0xF164,0xF165, +0xF166,0xF167,0xF168,0xF169,0xF16A,0xF16B,0xF16C,0xF16D, +0xF16E,0xF16F,0xF170,0xF171,0xF172,0xF173,0xF174,0xF175, +0xF176,0xF177,0xF178,0xF179,0xF17A,0xF17B,0xF17C,0xF17D, +0xF17E,0xF180,0xF181,0xF182,0xF183,0xF184,0xF185,0xF186, +0xF187,0xF188,0xF189,0xF18A,0xF18B,0xF18C,0xF18D,0xF18E, +0xF18F,0xF190,0xF191,0xF192,0xF193,0xF194,0xF195,0xF196, +0xF197,0xF198,0xF199,0xF19A,0xF19B,0xF19C,0xF19D,0xF19E, +0xF19F,0xF1A0,0xF240,0xF241,0xF242,0xF243,0xF244,0xF245, +0xF246,0xF247,0xF248,0xF249,0xF24A,0xF24B,0xF24C,0xF24D, +0xF24E,0xF24F,0xF250,0xF251,0xF252,0xF253,0xF254,0xF255, +0xF256,0xF257,0xF258,0xF259,0xF25A,0xF25B,0xF25C,0xF25D, +0xF25E,0xF25F,0xF260,0xF261,0xF262,0xF263,0xF264,0xF265, +0xF266,0xF267,0xF268,0xF269,0xF26A,0xF26B,0xF26C,0xF26D, +0xF26E,0xF26F,0xF270,0xF271,0xF272,0xF273,0xF274,0xF275, +0xF276,0xF277,0xF278,0xF279,0xF27A,0xF27B,0xF27C,0xF27D, +0xF27E,0xF280,0xF281,0xF282,0xF283,0xF284,0xF285,0xF286, +0xF287,0xF288,0xF289,0xF28A,0xF28B,0xF28C,0xF28D,0xF28E, +0xF28F,0xF290,0xF291,0xF292,0xF293,0xF294,0xF295,0xF296, +0xF297,0xF298,0xF299,0xF29A,0xF29B,0xF29C,0xF29D,0xF29E, +0xF29F,0xF2A0,0xF340,0xF341,0xF342,0xF343,0xF344,0xF345, +0xF346,0xF347,0xF348,0xF349,0xF34A,0xF34B,0xF34C,0xF34D, +0xF34E,0xF34F,0xF350,0xF351,0xC2ED,0xD4A6,0xCDD4,0xD1B1, +0xB3DB,0xC7FD,0xF352,0xB2B5,0xC2BF,0xE6E0,0xCABB,0xE6E1, +0xE6E2,0xBED4,0xE6E3,0xD7A4,0xCDD5,0xE6E5,0xBCDD,0xE6E4, +0xE6E6,0xE6E7,0xC2EE,0xF353,0xBDBE,0xE6E8,0xC2E6,0xBAA7, +0xE6E9,0xF354,0xE6EA,0xB3D2,0xD1E9,0xF355,0xF356,0xBFA5, +0xE6EB,0xC6EF,0xE6EC,0xE6ED,0xF357,0xF358,0xE6EE,0xC6AD, +0xE6EF,0xF359,0xC9A7,0xE6F0,0xE6F1,0xE6F2,0xE5B9,0xE6F3, +0xE6F4,0xC2E2,0xE6F5,0xE6F6,0xD6E8,0xE6F7,0xF35A,0xE6F8, +0xB9C7,0xF35B,0xF35C,0xF35D,0xF35E,0xF35F,0xF360,0xF361, +0xF7BB,0xF7BA,0xF362,0xF363,0xF364,0xF365,0xF7BE,0xF7BC, +0xBAA1,0xF366,0xF7BF,0xF367,0xF7C0,0xF368,0xF369,0xF36A, +0xF7C2,0xF7C1,0xF7C4,0xF36B,0xF36C,0xF7C3,0xF36D,0xF36E, +0xF36F,0xF370,0xF371,0xF7C5,0xF7C6,0xF372,0xF373,0xF374, +0xF375,0xF7C7,0xF376,0xCBE8,0xF377,0xF378,0xF379,0xF37A, +0xB8DF,0xF37B,0xF37C,0xF37D,0xF37E,0xF380,0xF381,0xF7D4, +0xF382,0xF7D5,0xF383,0xF384,0xF385,0xF386,0xF7D6,0xF387, +0xF388,0xF389,0xF38A,0xF7D8,0xF38B,0xF7DA,0xF38C,0xF7D7, +0xF38D,0xF38E,0xF38F,0xF390,0xF391,0xF392,0xF393,0xF394, +0xF395,0xF7DB,0xF396,0xF7D9,0xF397,0xF398,0xF399,0xF39A, +0xF39B,0xF39C,0xF39D,0xD7D7,0xF39E,0xF39F,0xF3A0,0xF440, +0xF7DC,0xF441,0xF442,0xF443,0xF444,0xF445,0xF446,0xF7DD, +0xF447,0xF448,0xF449,0xF7DE,0xF44A,0xF44B,0xF44C,0xF44D, +0xF44E,0xF44F,0xF450,0xF451,0xF452,0xF453,0xF454,0xF7DF, +0xF455,0xF456,0xF457,0xF7E0,0xF458,0xF459,0xF45A,0xF45B, +0xF45C,0xF45D,0xF45E,0xF45F,0xF460,0xF461,0xF462,0xDBCB, +0xF463,0xF464,0xD8AA,0xF465,0xF466,0xF467,0xF468,0xF469, +0xF46A,0xF46B,0xF46C,0xE5F7,0xB9ED,0xF46D,0xF46E,0xF46F, +0xF470,0xBFFD,0xBBEA,0xF7C9,0xC6C7,0xF7C8,0xF471,0xF7CA, +0xF7CC,0xF7CB,0xF472,0xF473,0xF474,0xF7CD,0xF475,0xCEBA, +0xF476,0xF7CE,0xF477,0xF478,0xC4A7,0xF479,0xF47A,0xF47B, +0xF47C,0xF47D,0xF47E,0xF480,0xF481,0xF482,0xF483,0xF484, +0xF485,0xF486,0xF487,0xF488,0xF489,0xF48A,0xF48B,0xF48C, +0xF48D,0xF48E,0xF48F,0xF490,0xF491,0xF492,0xF493,0xF494, +0xF495,0xF496,0xF497,0xF498,0xF499,0xF49A,0xF49B,0xF49C, +0xF49D,0xF49E,0xF49F,0xF4A0,0xF540,0xF541,0xF542,0xF543, +0xF544,0xF545,0xF546,0xF547,0xF548,0xF549,0xF54A,0xF54B, +0xF54C,0xF54D,0xF54E,0xF54F,0xF550,0xF551,0xF552,0xF553, +0xF554,0xF555,0xF556,0xF557,0xF558,0xF559,0xF55A,0xF55B, +0xF55C,0xF55D,0xF55E,0xF55F,0xF560,0xF561,0xF562,0xF563, +0xF564,0xF565,0xF566,0xF567,0xF568,0xF569,0xF56A,0xF56B, +0xF56C,0xF56D,0xF56E,0xF56F,0xF570,0xF571,0xF572,0xF573, +0xF574,0xF575,0xF576,0xF577,0xF578,0xF579,0xF57A,0xF57B, +0xF57C,0xF57D,0xF57E,0xF580,0xF581,0xF582,0xF583,0xF584, +0xF585,0xF586,0xF587,0xF588,0xF589,0xF58A,0xF58B,0xF58C, +0xF58D,0xF58E,0xF58F,0xF590,0xF591,0xF592,0xF593,0xF594, +0xF595,0xF596,0xF597,0xF598,0xF599,0xF59A,0xF59B,0xF59C, +0xF59D,0xF59E,0xF59F,0xF5A0,0xF640,0xF641,0xF642,0xF643, +0xF644,0xF645,0xF646,0xF647,0xF648,0xF649,0xF64A,0xF64B, +0xF64C,0xF64D,0xF64E,0xF64F,0xF650,0xF651,0xF652,0xF653, +0xF654,0xF655,0xF656,0xF657,0xF658,0xF659,0xF65A,0xF65B, +0xF65C,0xF65D,0xF65E,0xF65F,0xF660,0xF661,0xF662,0xF663, +0xF664,0xF665,0xF666,0xF667,0xF668,0xF669,0xF66A,0xF66B, +0xF66C,0xF66D,0xF66E,0xF66F,0xF670,0xF671,0xF672,0xF673, +0xF674,0xF675,0xF676,0xF677,0xF678,0xF679,0xF67A,0xF67B, +0xF67C,0xF67D,0xF67E,0xF680,0xF681,0xF682,0xF683,0xF684, +0xF685,0xF686,0xF687,0xF688,0xF689,0xF68A,0xF68B,0xF68C, +0xF68D,0xF68E,0xF68F,0xF690,0xF691,0xF692,0xF693,0xF694, +0xF695,0xF696,0xF697,0xF698,0xF699,0xF69A,0xF69B,0xF69C, +0xF69D,0xF69E,0xF69F,0xF6A0,0xF740,0xF741,0xF742,0xF743, +0xF744,0xF745,0xF746,0xF747,0xF748,0xF749,0xF74A,0xF74B, +0xF74C,0xF74D,0xF74E,0xF74F,0xF750,0xF751,0xF752,0xF753, +0xF754,0xF755,0xF756,0xF757,0xF758,0xF759,0xF75A,0xF75B, +0xF75C,0xF75D,0xF75E,0xF75F,0xF760,0xF761,0xF762,0xF763, +0xF764,0xF765,0xF766,0xF767,0xF768,0xF769,0xF76A,0xF76B, +0xF76C,0xF76D,0xF76E,0xF76F,0xF770,0xF771,0xF772,0xF773, +0xF774,0xF775,0xF776,0xF777,0xF778,0xF779,0xF77A,0xF77B, +0xF77C,0xF77D,0xF77E,0xF780,0xD3E3,0xF781,0xF782,0xF6CF, +0xF783,0xC2B3,0xF6D0,0xF784,0xF785,0xF6D1,0xF6D2,0xF6D3, +0xF6D4,0xF786,0xF787,0xF6D6,0xF788,0xB1AB,0xF6D7,0xF789, +0xF6D8,0xF6D9,0xF6DA,0xF78A,0xF6DB,0xF6DC,0xF78B,0xF78C, +0xF78D,0xF78E,0xF6DD,0xF6DE,0xCFCA,0xF78F,0xF6DF,0xF6E0, +0xF6E1,0xF6E2,0xF6E3,0xF6E4,0xC0F0,0xF6E5,0xF6E6,0xF6E7, +0xF6E8,0xF6E9,0xF790,0xF6EA,0xF791,0xF6EB,0xF6EC,0xF792, +0xF6ED,0xF6EE,0xF6EF,0xF6F0,0xF6F1,0xF6F2,0xF6F3,0xF6F4, +0xBEA8,0xF793,0xF6F5,0xF6F6,0xF6F7,0xF6F8,0xF794,0xF795, +0xF796,0xF797,0xF798,0xC8FA,0xF6F9,0xF6FA,0xF6FB,0xF6FC, +0xF799,0xF79A,0xF6FD,0xF6FE,0xF7A1,0xF7A2,0xF7A3,0xF7A4, +0xF7A5,0xF79B,0xF79C,0xF7A6,0xF7A7,0xF7A8,0xB1EE,0xF7A9, +0xF7AA,0xF7AB,0xF79D,0xF79E,0xF7AC,0xF7AD,0xC1DB,0xF7AE, +0xF79F,0xF7A0,0xF7AF,0xF840,0xF841,0xF842,0xF843,0xF844, +0xF845,0xF846,0xF847,0xF848,0xF849,0xF84A,0xF84B,0xF84C, +0xF84D,0xF84E,0xF84F,0xF850,0xF851,0xF852,0xF853,0xF854, +0xF855,0xF856,0xF857,0xF858,0xF859,0xF85A,0xF85B,0xF85C, +0xF85D,0xF85E,0xF85F,0xF860,0xF861,0xF862,0xF863,0xF864, +0xF865,0xF866,0xF867,0xF868,0xF869,0xF86A,0xF86B,0xF86C, +0xF86D,0xF86E,0xF86F,0xF870,0xF871,0xF872,0xF873,0xF874, +0xF875,0xF876,0xF877,0xF878,0xF879,0xF87A,0xF87B,0xF87C, +0xF87D,0xF87E,0xF880,0xF881,0xF882,0xF883,0xF884,0xF885, +0xF886,0xF887,0xF888,0xF889,0xF88A,0xF88B,0xF88C,0xF88D, +0xF88E,0xF88F,0xF890,0xF891,0xF892,0xF893,0xF894,0xF895, +0xF896,0xF897,0xF898,0xF899,0xF89A,0xF89B,0xF89C,0xF89D, +0xF89E,0xF89F,0xF8A0,0xF940,0xF941,0xF942,0xF943,0xF944, +0xF945,0xF946,0xF947,0xF948,0xF949,0xF94A,0xF94B,0xF94C, +0xF94D,0xF94E,0xF94F,0xF950,0xF951,0xF952,0xF953,0xF954, +0xF955,0xF956,0xF957,0xF958,0xF959,0xF95A,0xF95B,0xF95C, +0xF95D,0xF95E,0xF95F,0xF960,0xF961,0xF962,0xF963,0xF964, +0xF965,0xF966,0xF967,0xF968,0xF969,0xF96A,0xF96B,0xF96C, +0xF96D,0xF96E,0xF96F,0xF970,0xF971,0xF972,0xF973,0xF974, +0xF975,0xF976,0xF977,0xF978,0xF979,0xF97A,0xF97B,0xF97C, +0xF97D,0xF97E,0xF980,0xF981,0xF982,0xF983,0xF984,0xF985, +0xF986,0xF987,0xF988,0xF989,0xF98A,0xF98B,0xF98C,0xF98D, +0xF98E,0xF98F,0xF990,0xF991,0xF992,0xF993,0xF994,0xF995, +0xF996,0xF997,0xF998,0xF999,0xF99A,0xF99B,0xF99C,0xF99D, +0xF99E,0xF99F,0xF9A0,0xFA40,0xFA41,0xFA42,0xFA43,0xFA44, +0xFA45,0xFA46,0xFA47,0xFA48,0xFA49,0xFA4A,0xFA4B,0xFA4C, +0xFA4D,0xFA4E,0xFA4F,0xFA50,0xFA51,0xFA52,0xFA53,0xFA54, +0xFA55,0xFA56,0xFA57,0xFA58,0xFA59,0xFA5A,0xFA5B,0xFA5C, +0xFA5D,0xFA5E,0xFA5F,0xFA60,0xFA61,0xFA62,0xFA63,0xFA64, +0xFA65,0xFA66,0xFA67,0xFA68,0xFA69,0xFA6A,0xFA6B,0xFA6C, +0xFA6D,0xFA6E,0xFA6F,0xFA70,0xFA71,0xFA72,0xFA73,0xFA74, +0xFA75,0xFA76,0xFA77,0xFA78,0xFA79,0xFA7A,0xFA7B,0xFA7C, +0xFA7D,0xFA7E,0xFA80,0xFA81,0xFA82,0xFA83,0xFA84,0xFA85, +0xFA86,0xFA87,0xFA88,0xFA89,0xFA8A,0xFA8B,0xFA8C,0xFA8D, +0xFA8E,0xFA8F,0xFA90,0xFA91,0xFA92,0xFA93,0xFA94,0xFA95, +0xFA96,0xFA97,0xFA98,0xFA99,0xFA9A,0xFA9B,0xFA9C,0xFA9D, +0xFA9E,0xFA9F,0xFAA0,0xFB40,0xFB41,0xFB42,0xFB43,0xFB44, +0xFB45,0xFB46,0xFB47,0xFB48,0xFB49,0xFB4A,0xFB4B,0xFB4C, +0xFB4D,0xFB4E,0xFB4F,0xFB50,0xFB51,0xFB52,0xFB53,0xFB54, +0xFB55,0xFB56,0xFB57,0xFB58,0xFB59,0xFB5A,0xFB5B,0xC4F1, +0xF0AF,0xBCA6,0xF0B0,0xC3F9,0xFB5C,0xC5B8,0xD1BB,0xFB5D, +0xF0B1,0xF0B2,0xF0B3,0xF0B4,0xF0B5,0xD1BC,0xFB5E,0xD1EC, +0xFB5F,0xF0B7,0xF0B6,0xD4A7,0xFB60,0xCDD2,0xF0B8,0xF0BA, +0xF0B9,0xF0BB,0xF0BC,0xFB61,0xFB62,0xB8EB,0xF0BD,0xBAE8, +0xFB63,0xF0BE,0xF0BF,0xBEE9,0xF0C0,0xB6EC,0xF0C1,0xF0C2, +0xF0C3,0xF0C4,0xC8B5,0xF0C5,0xF0C6,0xFB64,0xF0C7,0xC5F4, +0xFB65,0xF0C8,0xFB66,0xFB67,0xFB68,0xF0C9,0xFB69,0xF0CA, +0xF7BD,0xFB6A,0xF0CB,0xF0CC,0xF0CD,0xFB6B,0xF0CE,0xFB6C, +0xFB6D,0xFB6E,0xFB6F,0xF0CF,0xBAD7,0xFB70,0xF0D0,0xF0D1, +0xF0D2,0xF0D3,0xF0D4,0xF0D5,0xF0D6,0xF0D8,0xFB71,0xFB72, +0xD3A5,0xF0D7,0xFB73,0xF0D9,0xFB74,0xFB75,0xFB76,0xFB77, +0xFB78,0xFB79,0xFB7A,0xFB7B,0xFB7C,0xFB7D,0xF5BA,0xC2B9, +0xFB7E,0xFB80,0xF7E4,0xFB81,0xFB82,0xFB83,0xFB84,0xF7E5, +0xF7E6,0xFB85,0xFB86,0xF7E7,0xFB87,0xFB88,0xFB89,0xFB8A, +0xFB8B,0xFB8C,0xF7E8,0xC2B4,0xFB8D,0xFB8E,0xFB8F,0xFB90, +0xFB91,0xFB92,0xFB93,0xFB94,0xFB95,0xF7EA,0xFB96,0xF7EB, +0xFB97,0xFB98,0xFB99,0xFB9A,0xFB9B,0xFB9C,0xC2F3,0xFB9D, +0xFB9E,0xFB9F,0xFBA0,0xFC40,0xFC41,0xFC42,0xFC43,0xFC44, +0xFC45,0xFC46,0xFC47,0xFC48,0xF4F0,0xFC49,0xFC4A,0xFC4B, +0xF4EF,0xFC4C,0xFC4D,0xC2E9,0xFC4E,0xF7E1,0xF7E2,0xFC4F, +0xFC50,0xFC51,0xFC52,0xFC53,0xBBC6,0xFC54,0xFC55,0xFC56, +0xFC57,0xD9E4,0xFC58,0xFC59,0xFC5A,0xCAF2,0xC0E8,0xF0A4, +0xFC5B,0xBADA,0xFC5C,0xFC5D,0xC7AD,0xFC5E,0xFC5F,0xFC60, +0xC4AC,0xFC61,0xFC62,0xF7EC,0xF7ED,0xF7EE,0xFC63,0xF7F0, +0xF7EF,0xFC64,0xF7F1,0xFC65,0xFC66,0xF7F4,0xFC67,0xF7F3, +0xFC68,0xF7F2,0xF7F5,0xFC69,0xFC6A,0xFC6B,0xFC6C,0xF7F6, +0xFC6D,0xFC6E,0xFC6F,0xFC70,0xFC71,0xFC72,0xFC73,0xFC74, +0xFC75,0xEDE9,0xFC76,0xEDEA,0xEDEB,0xFC77,0xF6BC,0xFC78, +0xFC79,0xFC7A,0xFC7B,0xFC7C,0xFC7D,0xFC7E,0xFC80,0xFC81, +0xFC82,0xFC83,0xFC84,0xF6BD,0xFC85,0xF6BE,0xB6A6,0xFC86, +0xD8BE,0xFC87,0xFC88,0xB9C4,0xFC89,0xFC8A,0xFC8B,0xD8BB, +0xFC8C,0xDCB1,0xFC8D,0xFC8E,0xFC8F,0xFC90,0xFC91,0xFC92, +0xCAF3,0xFC93,0xF7F7,0xFC94,0xFC95,0xFC96,0xFC97,0xFC98, +0xFC99,0xFC9A,0xFC9B,0xFC9C,0xF7F8,0xFC9D,0xFC9E,0xF7F9, +0xFC9F,0xFCA0,0xFD40,0xFD41,0xFD42,0xFD43,0xFD44,0xF7FB, +0xFD45,0xF7FA,0xFD46,0xB1C7,0xFD47,0xF7FC,0xF7FD,0xFD48, +0xFD49,0xFD4A,0xFD4B,0xFD4C,0xF7FE,0xFD4D,0xFD4E,0xFD4F, +0xFD50,0xFD51,0xFD52,0xFD53,0xFD54,0xFD55,0xFD56,0xFD57, +0xC6EB,0xECB4,0xFD58,0xFD59,0xFD5A,0xFD5B,0xFD5C,0xFD5D, +0xFD5E,0xFD5F,0xFD60,0xFD61,0xFD62,0xFD63,0xFD64,0xFD65, +0xFD66,0xFD67,0xFD68,0xFD69,0xFD6A,0xFD6B,0xFD6C,0xFD6D, +0xFD6E,0xFD6F,0xFD70,0xFD71,0xFD72,0xFD73,0xFD74,0xFD75, +0xFD76,0xFD77,0xFD78,0xFD79,0xFD7A,0xFD7B,0xFD7C,0xFD7D, +0xFD7E,0xFD80,0xFD81,0xFD82,0xFD83,0xFD84,0xFD85,0xB3DD, +0xF6B3,0xFD86,0xFD87,0xF6B4,0xC1E4,0xF6B5,0xF6B6,0xF6B7, +0xF6B8,0xF6B9,0xF6BA,0xC8A3,0xF6BB,0xFD88,0xFD89,0xFD8A, +0xFD8B,0xFD8C,0xFD8D,0xFD8E,0xFD8F,0xFD90,0xFD91,0xFD92, +0xFD93,0xC1FA,0xB9A8,0xEDE8,0xFD94,0xFD95,0xFD96,0xB9EA, +0xD9DF,0xFD97,0xFD98,0xFD99,0xFD9A,0xFD9B}; + + +static uint16_t tab_uni_gbk7[]={ +0xFD9C, 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, 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,0xFD9D, 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,0xFD9E, 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, 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,0xFD9F, 0, 0, 0, 0, + 0, 0, 0, 0, 0,0xFDA0, 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, +0xFE40,0xFE41,0xFE42,0xFE43, 0,0xFE44, 0,0xFE45, +0xFE46, 0, 0, 0,0xFE47, 0, 0, 0, + 0, 0, 0,0xFE48,0xFE49,0xFE4A, 0,0xFE4B, +0xFE4C, 0, 0,0xFE4D,0xFE4E,0xFE4F}; + + +static uint16_t tab_uni_gbk8[]={ +0xA955,0xA6F2, 0,0xA6F4,0xA6F5,0xA6E0,0xA6E1,0xA6F0, +0xA6F1,0xA6E2,0xA6E3,0xA6EE,0xA6EF,0xA6E6,0xA6E7,0xA6E4, +0xA6E5,0xA6E8,0xA6E9,0xA6EA,0xA6EB, 0, 0, 0, + 0,0xA968,0xA969,0xA96A,0xA96B,0xA96C,0xA96D,0xA96E, +0xA96F,0xA970,0xA971, 0,0xA972,0xA973,0xA974,0xA975, + 0,0xA976,0xA977,0xA978,0xA979,0xA97A,0xA97B,0xA97C, +0xA97D,0xA97E,0xA980,0xA981,0xA982,0xA983,0xA984, 0, +0xA985,0xA986,0xA987,0xA988, 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, + 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, 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, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0,0xA3A1,0xA3A2,0xA3A3,0xA1E7,0xA3A5,0xA3A6,0xA3A7, +0xA3A8,0xA3A9,0xA3AA,0xA3AB,0xA3AC,0xA3AD,0xA3AE,0xA3AF, +0xA3B0,0xA3B1,0xA3B2,0xA3B3,0xA3B4,0xA3B5,0xA3B6,0xA3B7, +0xA3B8,0xA3B9,0xA3BA,0xA3BB,0xA3BC,0xA3BD,0xA3BE,0xA3BF, +0xA3C0,0xA3C1,0xA3C2,0xA3C3,0xA3C4,0xA3C5,0xA3C6,0xA3C7, +0xA3C8,0xA3C9,0xA3CA,0xA3CB,0xA3CC,0xA3CD,0xA3CE,0xA3CF, +0xA3D0,0xA3D1,0xA3D2,0xA3D3,0xA3D4,0xA3D5,0xA3D6,0xA3D7, +0xA3D8,0xA3D9,0xA3DA,0xA3DB,0xA3DC,0xA3DD,0xA3DE,0xA3DF, +0xA3E0,0xA3E1,0xA3E2,0xA3E3,0xA3E4,0xA3E5,0xA3E6,0xA3E7, +0xA3E8,0xA3E9,0xA3EA,0xA3EB,0xA3EC,0xA3ED,0xA3EE,0xA3EF, +0xA3F0,0xA3F1,0xA3F2,0xA3F3,0xA3F4,0xA3F5,0xA3F6,0xA3F7, +0xA3F8,0xA3F9,0xA3FA,0xA3FB,0xA3FC,0xA3FD,0xA1AB, 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, 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, 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, +0xA1E9,0xA1EA,0xA956,0xA3FE,0xA957,0xA3A4}; + +static int func_uni_gbk_onechar(int code){ + if ((code>=0x00A4)&&(code<=0x0451)) { + return(tab_uni_gbk0[code-0x00A4]); + } else if ((code>=0x2010)&&(code<=0x2312)) { + return(tab_uni_gbk1[code-0x2010]); + } else if ((code>=0x2460)&&(code<=0x2642)) { + return(tab_uni_gbk2[code-0x2460]); + } else if ((code>=0x3000)&&(code<=0x3129)) { + return(tab_uni_gbk3[code-0x3000]); + } else if ((code>=0x3220)&&(code<=0x32A3)) { + return(tab_uni_gbk4[code-0x3220]); + } else if ((code>=0x338E)&&(code<=0x33D5)) { + return(tab_uni_gbk5[code-0x338E]); + } else if ((code>=0x4E00)&&(code<=0x9FA5)) { + return(tab_uni_gbk6[code-0x4E00]); + } else if ((code>=0xF92C)&&(code<=0xFA29)) { + return(tab_uni_gbk7[code-0xF92C]); + } else if ((code>=0xFE30)&&(code<=0xFFE5)) { + return(tab_uni_gbk8[code-0xFE30]); + } + return(0); +} + +static int +ob_wc_mb_gbk(const ObCharsetInfo *cs __attribute__((unused)), + ob_wc_t wc, unsigned char *s, unsigned char *e) +{ + int code; + + if (s >= e) { + return OB_CS_TOOSMALL; + } else if ((unsigned int) wc < 0x80) { + s[0]= (unsigned char) wc; + return 1; + } else if (!(code=func_uni_gbk_onechar(wc))) { + return OB_CS_ILUNI; + } else if (s+2>e) { + return OB_CS_TOOSMALL2; + } + s[0] = code >> 8; + s[1] = code & 0xFF; + return 2; +} + +static int ob_mb_wc_gbk(const ObCharsetInfo *cs __attribute__((unused)), + ob_wc_t *pwc, const unsigned char *s, const unsigned char *e) +{ + int hi; + if (s >= e) { + return OB_CS_TOOSMALL; + } else if ((hi = s[0]) < 0x80) { + pwc[0]=hi; + return 1; + } else if (s+2>e) { + return OB_CS_TOOSMALL2; + } else if (!(pwc[0]=func_gbk_uni_onechar( (hi<<8) + s[1]))) { + return -2; + } + + return 2; +} + + +static size_t ob_well_formed_len_gbk(const ObCharsetInfo *cs __attribute__((unused)), + const char *b, const char *e, + size_t pos, int *error) +{ + const char *b0= b; + const char *emb= e - 1; + *error= 0; + + while (pos-- && b < e) { + if ((unsigned char) b[0] < 128) { + b++; + } else if ((b < emb) && isgbkcode((unsigned char)*b, (unsigned char)b[1])) { + b+= 2; + } else { + *error= 1; + break; + } + } + return (size_t) (b - b0); +} + +static ObCollationHandler ob_gbk_collation_ci_handler = +{ + ob_strnncoll_gbk, + ob_strnncollsp_gbk, + ob_strnxfrm_gbk, + ob_like_range_mb, + ob_wildcmp_mb, + ob_instr_mb, + ob_hash_sort_simple, + ob_propagate_simple +}; + +static ObCharsetHandler ob_charset_gbk_handler= +{ + ismbchar_gbk, + mbcharlen_gbk, + ob_numchars_mb, + ob_charpos_mb, + ob_max_bytes_charpos_mb, + ob_well_formed_len_gbk, + ob_lengthsp_8bit, + ob_mb_wc_gbk, + ob_wc_mb_gbk, + ob_mb_ctype_mb, + ob_caseup_mb, + ob_casedn_mb, + ob_fill_8bit, + ob_strntol_8bit, + ob_strntoul_8bit, + ob_strntoll_8bit, + ob_strntoull_8bit, + ob_strntod_8bit, + ob_strntoull10rnd_8bit, + ob_scan_8bit +}; + + +ObCharsetInfo ob_charset_gbk_chinese_ci= +{ + 28,0,0, + OB_CS_COMPILED|OB_CS_PRIMARY|OB_CS_STRNXFRM, + "gbk", + "gbk_chinese_ci", + "", + NULL, + ctype_gbk, + to_lower_gbk, + to_upper_gbk, + sort_order_gbk, + NULL, + &ob_caseinfo_gbk, + NULL, + NULL, + 1, + 1, + 1, + 1, + 2, + 0, + 0xA967, + ' ', + 1, + 1, + 1, + &ob_charset_gbk_handler, + &ob_gbk_collation_ci_handler +}; + +ObCharsetInfo ob_charset_gbk_bin= +{ + 87,0,0, + OB_CS_COMPILED|OB_CS_BINSORT, + "gbk", + "gbk_bin", + "", + NULL, + ctype_gbk, + to_lower_gbk, + to_upper_gbk, + NULL, + NULL, + &ob_caseinfo_gbk, + NULL, + NULL, + 1, + 1, + 1, + 1, + 2, + 0, + 0xFEFE, + ' ', + 1, + 1, + 1, + &ob_charset_gbk_handler, + &ob_collation_mb_bin_handler +}; + diff --git a/src/lib/charset/ob_ctype_latin1.c b/src/lib/charset/ob_ctype_latin1.c new file mode 100644 index 0000000000000000000000000000000000000000..27262d00f333a17afe8827c7da78cb3d311a27e7 --- /dev/null +++ b/src/lib/charset/ob_ctype_latin1.c @@ -0,0 +1,407 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +/* +* +* Version: $Id +* +* Authors: +* - initial release +* +*/ +#include "lib/charset/ob_mysql_global.h" +#include "lib/charset/ob_ctype.h" +#include "lib/utility/ob_macro_utils.h" + +static unsigned char ctype_latin1[] = { + 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 16, 16, 16, 16, 16, + 16, 16, 129, 129, 129, 129, 129, 129, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, + 16, 16, 130, 130, 130, 130, 130, 130, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, + 32, 16, 0, 16, 2, 16, 16, 16, 16, 16, 16, 1, 16, 1, 0, 1, + 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 2, 0, 2, + 1, 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, + 2}; + +static unsigned char to_lower_latin1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 224, 225, 226, + 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 215, 248, 249, 250, 251, 252, 253, 254, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255}; + +static unsigned char to_upper_latin1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 192, + 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 247, 216, 217, 218, 219, 220, 221, 222, + 255}; + +static unsigned char sort_order_latin1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 65, 65, 65, + 65, 92, 91, 92, 67, 69, 69, 69, 69, 73, 73, 73, 73, 68, 78, + 79, 79, 79, 79, 93, 215, 216, 85, 85, 85, 89, 89, 222, 223, 65, + 65, 65, 65, 92, 91, 92, 67, 69, 69, 69, 69, 73, 73, 73, 73, + 68, 78, 79, 79, 79, 79, 93, 247, 216, 85, 85, 85, 89, 89, 222, + 255}; + + +static unsigned short cs_to_uni[] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, + 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, + 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, + 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, + 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, + 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, + 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, + 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, + 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, + 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, + 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, + 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, + 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, + 0x007E, 0x007F, 0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, + 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008D, 0x017D, 0x008F, + 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, + 0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x017E, 0x0178, 0x00A0, 0x00A1, + 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, + 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, + 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, + 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, + 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, + 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, + 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, + 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2, + 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, + 0x00FC, 0x00FD, 0x00FE, 0x00FF}; +static unsigned char pl00[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, + 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, + 0x60, 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, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x00, 0x81, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x8F, + 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9D, 0x00, 0x00, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, + 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, + 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, + 0xFC, 0xFD, 0xFE, 0xFF}; +static unsigned char pl01[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x9C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x8A, 0x9A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9F, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; +static unsigned char pl02[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; +static unsigned char pl20[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, + 0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00, 0x86, 0x87, 0x95, 0x00, + 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x9B, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; +static unsigned char pl21[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; +static unsigned char *uni_to_cs[] = { + pl00, pl01, pl02, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + pl20, pl21, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; + + +static int ob_mb_wc_latin1(const ObCharsetInfo *cs __attribute__((unused)), + ob_wc_t *pwc, const unsigned char *str, const unsigned char *end) { + + if (str >= end) return OB_CS_TOOSMALL; + *pwc = cs_to_uni[*str]; + return (!pwc[0] && str[0]) ? -1 : 1; + +} + +static int ob_wc_mb_latin1(const ObCharsetInfo *cs __attribute__((unused)), + ob_wc_t wc, unsigned char *str, unsigned char *end) { + const unsigned char *pl; + + if (str >= end) return OB_CS_TOOSMALL; + + if (wc > 0xFFFF) return OB_CS_ILUNI; + + pl = uni_to_cs[wc >> 8]; + str[0] = pl ? pl[wc & 0xFF] : '\0'; + return (!str[0] && wc) ? OB_CS_ILUNI : 1; +} + + + +static ObCharsetHandler ob_charset_latin1_handler= +{ + //NULL, /* init */ + NULL, /* ismbchar */ + ob_mbcharlen_8bit, /* mbcharlen */ + ob_numchars_8bit, + ob_charpos_8bit, + ob_max_bytes_charpos_8bit, + ob_well_formed_len_8bit, + ob_lengthsp_binary, + //ob_numcells_8bit, + ob_mb_wc_latin1, + ob_wc_mb_latin1, + ob_mb_ctype_8bit, + //ob_case_str_bin, + //ob_case_str_bin, + ob_caseup_8bit, + ob_casedn_8bit, + //ob_snprintf_8bit, + //ob_long10_to_str_8bit, + //ob_longlong10_to_str_8bit, + ob_fill_8bit, + ob_strntol_8bit, + ob_strntoul_8bit, + ob_strntoll_8bit, + ob_strntoull_8bit, + ob_strntod_8bit, + //ob_strtoll10_8bit, + ob_strntoull10rnd_8bit, + ob_scan_8bit +}; + + + + + +ObCharsetInfo ob_charset_latin1 = { + 8,0,0, /* number */ + OB_CS_COMPILED | OB_CS_PRIMARY, /* state */ + OB_LATIN1, /* cs name */ + OB_LATIN1_SWEDISH_CI, /* name */ + "cp1252 West European", /* comment */ + NULL, /* tailoring */ + //NULL, /* coll_param */ + ctype_latin1, + to_lower_latin1, + to_upper_latin1, + sort_order_latin1, + NULL, /* uca */ + //NULL, /* tab_to_uni */ + //NULL, /* tab_from_uni */ + &ob_unicase_default, /* caseinfo */ + NULL, /* state_map */ + NULL, /* ident_map */ + 1, /* strxfrm_multiply */ + 1, /* caseup_multiply */ + 1, /* casedn_multiply */ + 1, /* mbminlen */ + 1, /* mbmaxlen */ + 0, /* min_sort_char */ + 0xFF, /* max_sort_char */ + ' ', /* pad char */ + 0, /* escape_with_backslash_is_dangerous */ + 1, /* levels_for_compare */ + 1, /* levels_for_order */ + &ob_charset_latin1_handler, + &ob_collation_8bit_simple_ci_handler}; + +ObCharsetInfo ob_charset_latin1_bin = { + 47,0,0, /* number */ + OB_CS_COMPILED | OB_CS_BINSORT, /* state */ + OB_LATIN1, /* cs name */ + OB_LATIN1_BIN, /* name */ + "cp1252 West European", /* comment */ + NULL, /* tailoring */ + ctype_latin1, + to_lower_latin1, + to_upper_latin1, + NULL, /* sort_order */ + NULL, /* uca */ + //NULL, /* tab_to_uni */ + //NULL, /* tab_from_uni */ + &ob_unicase_default, /* caseinfo */ + NULL, /* state_map */ + NULL, /* ident_map */ + 1, /* strxfrm_multiply */ + 1, /* caseup_multiply */ + 1, /* casedn_multiply */ + 1, /* mbminlen */ + 1, /* mbmaxlen */ + 0, /* min_sort_char */ + 0xFF, /* max_sort_char */ + ' ', /* pad char */ + 0, /* escape_with_backslash_is_dangerous */ + 1, /* levels_for_compare */ + 1, /* levels_for_order */ + &ob_charset_latin1_handler, + &ob_collation_binary_handler}; + diff --git a/src/lib/charset/ob_ctype_mb.c b/src/lib/charset/ob_ctype_mb.c index 2bda0afff446d5af049eae28a461903e08bbf94d..3c463bf3850324a58ca91e5516aeb3e6823a3715 100644 --- a/src/lib/charset/ob_ctype_mb.c +++ b/src/lib/charset/ob_ctype_mb.c @@ -12,28 +12,18 @@ #include "lib/charset/ob_ctype.h" -#ifdef __cplusplus -extern "C" int check_stack_overflow_in_c(int *check_overflow); -#endif - -static void __attribute__ ((noinline)) pad_max_char_help(char *str, char *end, - char *buf, char buf_len) +static void __attribute__ ((noinline)) pad_max_char_help(char *str, char *end, char *buf, char buf_len) { - do - { - if ((str + buf_len) <= end) { - /* Enough space for the characer */ + do { + if ((str + buf_len) <= end) { memcpy(str, buf, buf_len); str+= buf_len; } else { - /* - There is no space for whole multibyte - character, then add trailing spaces. - */ *str++= ' '; } } while (str < end); } + static void pad_max_char(const ObCharsetInfo *cs, char *str, char *end) { char buf[10]; @@ -43,27 +33,27 @@ static void pad_max_char(const ObCharsetInfo *cs, char *str, char *end) memset(str, cs->max_sort_char, end - str); return; } + buf_len= 2; buf[0]= cs->max_sort_char >> 8; buf[1]= cs->max_sort_char & 0xFF; - buf_len= 2; } else { - buf_len= cs->cset->wc_mb(cs->max_sort_char, (unsigned char*) buf, + buf_len= cs->cset->wc_mb(cs, cs->max_sort_char, (unsigned char*) buf, (unsigned char*) buf + sizeof(buf)); } ob_charset_assert(buf_len > 0); pad_max_char_help(str, end ,buf, buf_len); } -int ob_like_range_mb_help(const ObCharsetInfo *cs, - size_t res_length, - char **min_str_,char **max_str_, - char **min_org_, char **min_end_, - size_t *min_length, size_t *max_length, char **max_end_) +bool ob_like_range_mb_help(const ObCharsetInfo *cs, + size_t res_length, + char **min_str_,char **max_str_, + char **min_org_, char **min_end_, + size_t *min_length,size_t *max_length, char **max_end_) { char *min_str = *min_str_; char *max_str = *max_str_; - char *max_end = *max_end_; char *min_end = *min_end_; + char *max_end = *max_end_; char *min_org = *min_org_; *min_length = ((cs->state & OB_CS_BINSORT) ? (size_t) (min_str - min_org) : res_length); *max_length = res_length; @@ -74,283 +64,276 @@ int ob_like_range_mb_help(const ObCharsetInfo *cs, pad_max_char(cs, max_str, max_end); *min_str_ = min_str; *max_str_ = max_str; - *max_end_ = max_end; *min_end_ = min_end; + *max_end_ = max_end; *min_org_ = min_org; return 0; } -int ob_like_range_mb(const ObCharsetInfo *cs, - const char *str, size_t str_len, - int escape, int w_one, int w_many, - size_t res_length, - char *min_str, char *max_str, - size_t *min_length, size_t *max_length) +bool ob_like_range_mb(const ObCharsetInfo *cs, + const char *ptr,size_t ptr_length, + pbool escape_char, pbool w_one, pbool w_many, + size_t res_length, + char *min_str,char *max_str, + size_t *min_length,size_t *max_length) { unsigned int mb_len; - const char *end = str + str_len; - char *min_org = min_str; - char *min_end = min_str + res_length; - char *max_end = max_str + res_length; - size_t maxcharlen = res_length / cs->mbmaxlen; - - for (; str != end && min_str != min_end && maxcharlen ; maxcharlen--) { - /* We assume here that escape, w_any, w_namy are one-byte characters */ - if (*str == escape && str+1 != end) { - str++; /* Skip escape */ - } else if (*str == w_one || *str == w_many) { /* '_' and '%' in SQL */ + const char *end= ptr + ptr_length; + char *min_org= min_str; + char *min_end= min_str + res_length; + char *max_end= max_str + res_length; + size_t max_char_len= res_length / cs->mbmaxlen; + const ObContractions *contractions= ob_charset_get_contractions(cs, 0); + + for (; ptr != end && min_str != min_end && max_char_len ; max_char_len--) { + if (*ptr == escape_char && ptr+1 != end) { + ptr++; + } else if (*ptr == w_one || + *ptr == w_many) { return ob_like_range_mb_help(cs,res_length, &min_str,&max_str, &min_org, &min_end, min_length, max_length, &max_end); } - if ((mb_len= cs->cset->ismbchar(str, end - str)) > 1) { - if (str+mb_len > end || min_str+mb_len > min_end) { + mb_len= ob_ismbchar(cs, ptr, end); + if ( mb_len > 1) { + if (min_str+mb_len > min_end || + ptr+mb_len > end) { break; - } + } while (mb_len--) { - *min_str++= *max_str++= *str++; + *min_str++= *max_str++= *ptr++; } } else { - //TODO support contractions - *min_str++= *max_str++= *str++; + if (contractions && ptr + 1 < end && + ob_uca_can_be_contraction_head(contractions, (unsigned char) *ptr)) { + if (ptr[1] == w_one || ptr[1] == w_many) { + return ob_like_range_mb_help(cs,res_length, &min_str,&max_str, &min_org, &min_end, min_length, max_length, &max_end); + } else if (ob_uca_can_be_contraction_tail(contractions, (unsigned char) ptr[1]) && + ob_uca_contraction2_weight(contractions, (unsigned char) ptr[0], ptr[1])) { + if (max_char_len == 1 || min_str + 1 >= min_end) { + return ob_like_range_mb_help(cs,res_length, &min_str,&max_str, &min_org, &min_end, min_length, max_length, &max_end); + } + max_char_len--; + *min_str++= *max_str++= *ptr++; + } + } + *min_str++= *max_str++= *ptr++; } } *min_length= *max_length = (size_t) (min_str - min_org); - while (min_str != min_end) - *min_str++= *max_str++= ' '; /* Because if key compression */ + while (min_end != min_str) { + *min_str++= *max_str++= ' '; + } return 0; } int ob_wildcmp_mb(const ObCharsetInfo *cs, - const char *str_ptr, const char *str_end_ptr, - const char *wild_str_ptr, const char *wild_end_ptr, - int escape_char, int w_one_char, int w_many_char) + const char *str,const char *str_end, + const char *wild_str,const char *wild_end, + int escape_char, int w_one, int w_many) { - return ob_wildcmp_mb_impl(cs, str_ptr, str_end_ptr, - wild_str_ptr, wild_end_ptr, - escape_char, w_one_char, w_many_char); + return ob_wildcmp_mb_impl(cs, str, str_end, wild_str, wild_end, escape_char, w_one, w_many, 1); } -/* -** Compare string against string with wildcard -** 0 if matched -** -1 if not matched with wildcard -** 1 if matched with wildcard -*/ - -#define INC_PTR(cs,A,B) \ - uint32_t temp_len = cs->cset->ismbchar(A, ((B)-(A))); \ - A+=(temp_len) ? temp_len : 1;\ +#define INC_PTR(cs,A,B) A+=(ob_ismbchar(cs,A,B) ? ob_ismbchar(cs,A,B) : 1) #define likeconv(s,A) (unsigned char) (s)->sort_order[(unsigned char) (A)] int ob_wildcmp_mb_impl(const ObCharsetInfo *cs, - const char *str_ptr,const char *str_end_ptr, - const char *wild_str_ptr,const char *wild_end_ptr, - int escape_char, int w_one_char, int w_many_char) + const char *str,const char *str_end, + const char *wild_str,const char *wild_end, + int escape_char, int w_one, int w_many, int recurse_level) { - int cmp_result= -1; /* Not found, using wildcards */ - - /* if (my_string_stack_guard && my_string_stack_guard(recurse_level)) */ - /* return 1; */ - //if (0 != check_stack_overflow_in_c(is_stack_overlow) || *is_stack_overlow) { - // return 1; - //} - while (wild_str_ptr != wild_end_ptr) - { - while (*wild_str_ptr != w_many_char && *wild_str_ptr != w_one_char) - { + int result= -1; + while (wild_str != wild_end) { + while (*wild_str != w_many && *wild_str != w_one) { int l; - if (*wild_str_ptr == escape_char && wild_str_ptr+1 != wild_end_ptr) - wild_str_ptr++; - if ((l = cs->cset->ismbchar(wild_str_ptr, wild_end_ptr - wild_str_ptr))) - { - if (str_ptr+l > str_end_ptr || memcmp(str_ptr, wild_str_ptr, l) != 0) - return 1; - str_ptr += l; - wild_str_ptr += l; + if (*wild_str == escape_char && wild_str+1 != wild_end) { + wild_str++; + } + if ((l = ob_ismbchar(cs, wild_str, wild_end))) { + if (str+l > str_end || memcmp(str, wild_str, l) != 0) + return 1; + str += l; + wild_str += l; + } else if (str == str_end || likeconv(cs,*wild_str++) != likeconv(cs,*str++)) { + return(1); } - else - if (str_ptr == str_end_ptr || likeconv(cs,*wild_str_ptr++) != likeconv(cs,*str_ptr++)) - return(1); /* No match */ - if (wild_str_ptr == wild_end_ptr) - return (str_ptr != str_end_ptr); /* Match if both are at end */ - cmp_result=1; /* Found an anchor char */ + if (wild_str == wild_end) { + return (str != str_end); + } + result=1; } - if (*wild_str_ptr == w_one_char) - { - do - { - if (str_ptr == str_end_ptr) /* Skip one char if possible */ - return (cmp_result); - INC_PTR(cs,str_ptr,str_end_ptr); - } while (++wild_str_ptr < wild_end_ptr && *wild_str_ptr == w_one_char); - if (wild_str_ptr == wild_end_ptr) - break; + if (*wild_str == w_one) { + do { + if (str == str_end) { + return (result); + } + INC_PTR(cs,str,str_end); + } while (++wild_str < wild_end && *wild_str == w_one); + if (wild_end == wild_str) + break; } - if (*wild_str_ptr == w_many_char) - { /* Found w_many_char */ + if (*wild_str == w_many) { unsigned char cmp; - const char* mb = wild_str_ptr; + const char* mb = wild_str; int mb_len=0; - wild_str_ptr++; - /* Remove any '%' and '_' from the wild search string */ - for (; wild_str_ptr != wild_end_ptr ; wild_str_ptr++) + wild_str++; + + for (; wild_str != wild_end ; wild_str++) { - if (*wild_str_ptr == w_many_char) - continue; - if (*wild_str_ptr == w_one_char) - { - if (str_ptr == str_end_ptr) - return (-1); - INC_PTR(cs,str_ptr,str_end_ptr); - continue; - } - break; /* Not a wild character */ + if (*wild_str == w_many) + continue; + if (*wild_str == w_one) + { + if (str == str_end) + return (-1); + INC_PTR(cs,str,str_end); + continue; + } + break; + } + if (wild_str == wild_end) { + return(0); + } else if (str == str_end) { + return -1; + } else if ((cmp= *wild_str) == escape_char && wild_str+1 != wild_end) { + cmp= *++wild_str; } - if (wild_str_ptr == wild_end_ptr) - return(0); /* Ok if w_many_char is last */ - if (str_ptr == str_end_ptr) - return -1; - - if ((cmp= *wild_str_ptr) == escape_char && wild_str_ptr+1 != wild_end_ptr) - cmp= *++wild_str_ptr; - mb=wild_str_ptr; - mb_len= cs->cset->ismbchar(wild_str_ptr, wild_end_ptr-wild_str_ptr); - INC_PTR(cs,wild_str_ptr,wild_end_ptr); /* This is compared trough cmp */ + mb=wild_str; + mb_len= ob_ismbchar(cs, wild_str, wild_end); + INC_PTR(cs,wild_str,wild_end); cmp=likeconv(cs,cmp); - do - { - for (;;) - { - if (str_ptr >= str_end_ptr) + do { + while (TRUE) { + if (str >= str_end) { return -1; - if (mb_len) - { - if (str_ptr+mb_len <= str_end_ptr && memcmp(str_ptr, mb, mb_len) == 0) + } else if (mb_len) { + if (str+mb_len <= str_end && memcmp(str, mb, mb_len) == 0) { - str_ptr += mb_len; + str += mb_len; break; } - } - else if (!cs->cset->ismbchar(str_ptr, str_end_ptr-str_ptr) && - likeconv(cs,*str_ptr) == cmp) - { - str_ptr++; + } else if (!ob_ismbchar(cs, str, str_end) && + likeconv(cs,*str) == cmp) { + str++; break; } - INC_PTR(cs,str_ptr, str_end_ptr); + INC_PTR(cs,str, str_end); + } + { + int tmp=ob_wildcmp_mb_impl(cs,str,str_end, + wild_str,wild_end,escape_char,w_one, + w_many, recurse_level + 1); + if (tmp <= 0) + return (tmp); } - { - int tmp=ob_wildcmp_mb_impl(cs,str_ptr,str_end_ptr, - wild_str_ptr,wild_end_ptr,escape_char,w_one_char, - w_many_char); - if (tmp <= 0) - return (tmp); - } - } while (str_ptr != str_end_ptr && wild_str_ptr[0] != w_many_char); + } while (str != str_end && wild_str[0] != w_many); return(-1); } } - return (str_ptr != str_end_ptr ? 1 : 0); + return (str != str_end ? 1 : 0); +} + +unsigned int __attribute__ ((noinline)) ob_instr_mb_help(size_t s_length, ob_match_t *match, unsigned int nmatch) +{ + if (!s_length) { + if (nmatch) { + match->beg= 0; + match->end= 0; + match->mb_len= 0; + } + return 1; + } + return 0; } unsigned int ob_instr_mb(const ObCharsetInfo *cs, - const char *base, size_t base_len, - const char *str, size_t str_len, - ob_match_info *match, uint32_t nmatch) + const char *b, size_t b_length, + const char *s, size_t s_length, + ob_match_t *match, unsigned int nmatch) { - const char *end, *base_begin; + const char *end, *b0; int res= 0; - if (str_len <= base_len) { - if (!str_len) { - if (nmatch) { - match->beg= 0; - match->end= 0; - match->mb_len= 0; - } - return 1; /* Empty string is always found */ + if (s_length <= b_length) { + unsigned int tmp = ob_instr_mb_help(s_length, match, nmatch); + if (tmp) { + return tmp; } - base_begin= base; - end= base+base_len-str_len+1; - while (base < end) { + b0= b; + end= b+b_length-s_length+1; + while (b < end) { int mb_len; - if (!cs->coll->strnncoll(cs, (unsigned char*) base, str_len, - (unsigned char*) str, str_len)) { + if (!cs->coll->strnncoll(cs, (unsigned char*) b, s_length, + (unsigned char*) s, s_length, 0)) { if (nmatch) { match[0].beg= 0; - match[0].end= (size_t) (base-base_begin); + match[0].end= (size_t) (b-b0); match[0].mb_len= res; if (nmatch > 1) { match[1].beg= match[0].end; - match[1].end= match[0].end+str_len; - match[1].mb_len= 0; /* Not computed */ + match[1].end= match[0].end+s_length; + match[1].mb_len= 0; } } return 2; } - mb_len= (mb_len= cs->cset->ismbchar(base, end-base)) ? mb_len : 1; - base+= mb_len; - base_len-= mb_len; + mb_len= (mb_len= ob_ismbchar(cs, b, end)) ? mb_len : 1; + b+= mb_len; + b_length-= mb_len; res++; } } return 0; } -size_t ob_numchars_mb(const ObCharsetInfo *cs, const char *str, size_t len) +size_t ob_numchars_mb(const ObCharsetInfo *cs __attribute__((unused)), const char *pos, const char *end) { - size_t count = 0; - while (len > 0) { - uint32_t mb_len = cs->cset->ismbchar(str, len); - mb_len = (mb_len > 0) ? mb_len : 1; - str += mb_len; - len -= mb_len; + size_t count= 0; + while (pos < end) { + unsigned int mb_len; + pos+= (mb_len= ob_ismbchar(cs,pos,end)) ? mb_len : 1; count++; } return count; } -size_t ob_charpos_mb(const ObCharsetInfo *cs, const char *str, size_t len, size_t pos) +size_t ob_charpos_mb(const ObCharsetInfo *cs __attribute__((unused)), const char *pos, const char *end, size_t length) { - const char *str_begin= str; - size_t err_result = len + 2; - while (pos > 0 && len > 0) { - uint32_t mb_len = cs->cset->ismbchar(str, len); - mb_len = (mb_len > 0) ? mb_len : 1; - str += mb_len; - len -= mb_len; - pos--; + const char *start= pos; + while (length && pos < end) { + unsigned int mb_len; + pos+= (mb_len= ob_ismbchar(cs, pos, end)) ? mb_len : 1; + length--; } - return (size_t) (pos > 0 ? err_result : str-str_begin); + return (size_t) (length ? end+2-start : pos-start); } -size_t ob_max_bytes_charpos_mb(const ObCharsetInfo *cs, const char *str, size_t str_len, - size_t max_bytes, size_t *char_len) +size_t ob_max_bytes_charpos_mb(const ObCharsetInfo *cs __attribute__((unused)), const char *pos, const char *end, size_t max_bytes, size_t *char_len) { - const char *str_begin = str; - while (max_bytes > 0 && str_len > 0) - { - uint32_t mb_len = cs->cset->ismbchar(str, str_len); - uint32_t bytes = mb_len ? mb_len : 1; + const char *start= pos; + while (max_bytes && pos < end) { + unsigned int mb_len; + unsigned int bytes; + mb_len = ob_ismbchar(cs, pos, end); + bytes = mb_len ? mb_len : 1; if (max_bytes < bytes) { break; } else { - str += bytes; - str_len -= bytes; + pos += bytes; max_bytes -= bytes; ++*char_len; } } - return (size_t) (str-str_begin); + return (size_t) (pos-start); } int ob_mb_ctype_mb(const ObCharsetInfo *cs __attribute__((unused)), int *ctype, const unsigned char *s, const unsigned char *e) { ob_wc_t wc; - int res = cs->cset->mb_wc(s, e, &wc); + int res = cs->cset->mb_wc(cs, &wc, s, e); if (res <= 0 || wc > 0xFFFF) { *ctype = 0; } else { @@ -361,197 +344,381 @@ int ob_mb_ctype_mb(const ObCharsetInfo *cs __attribute__((unused)), int *ctype, return res; } -//========================================================================== +static inline const ObUnicaseInfoChar* +get_case_info_for_ch(const ObCharsetInfo *cs, unsigned int page, unsigned int offs) +{ + const ObUnicaseInfoChar *p; + return cs->caseinfo ? ((p= cs->caseinfo->page[page]) ? &p[offs] : NULL) : NULL; +} + +size_t ob_casedn_mb(const ObCharsetInfo *cs, char *src, size_t src_len, + char *dst __attribute__((unused)), + size_t dstlen __attribute__((unused))) +{ + uint32_t l; + unsigned char *map=cs->to_lower; + char *src_end = src + src_len; + + while (src < src_end) { + l = cs->cset->ismbchar(cs, src, src_end); + if ( 0 != l ) { + const ObUnicaseInfoChar *ch = get_case_info_for_ch(cs, (unsigned char) src[0], (unsigned char) src[1]); + if (ch) { + *src++= ch->tolower >> 8; + *src++= ch->tolower & 0xFF; + } else { + src+= l; + } + } else { + *src= (char) map[(unsigned char)*src]; + src++; + } + } + return src_len; +} + +size_t ob_caseup_mb(const ObCharsetInfo *cs, char *src, size_t src_len, + char *dst __attribute__((unused)), + size_t dstlen __attribute__((unused))) +{ + uint32_t l; + unsigned char *map= cs->to_upper; + char *src_end= src + src_len; + while (src < src_end) { + l = cs->cset->ismbchar(cs, src, src_end); + if ( 0 != l ) { + const ObUnicaseInfoChar *ch = get_case_info_for_ch(cs, (unsigned char) src[0], (unsigned char) src[1]); + if (ch) { + *src++= ch->toupper >> 8; + *src++= ch->toupper & 0xFF; + } else { + src+= l; + } + } else { + *src=(char) map[(unsigned char) *src]; + src++; + } + } + return src_len; +} + -size_t ob_lengthsp_8bit(const char *str, size_t str_len) +const ObContractions *ob_charset_get_contractions(const ObCharsetInfo *cs, int level) { - const char *end = (const char *) skip_trailing_space((const unsigned char *)str, str_len); - return (size_t) (end-str); + return NULL; } -/* BINARY collations handlers for MB charsets */ +bool ob_uca_can_be_contraction_head(const ObContractions *c, ob_wc_t wc) +{ + return false; +} + +bool ob_uca_can_be_contraction_tail(const ObContractions *c, ob_wc_t wc) +{ + return false; +} + +uint16_t *ob_uca_contraction2_weight(const ObContractions *list, ob_wc_t wc1, ob_wc_t wc2) +{ + return NULL; +} + +size_t ob_lengthsp_8bit(const ObCharsetInfo *cs __attribute__((unused)), + const char *ptr, size_t length) +{ + const char *end; + end= (const char *) skip_trailing_space((const uchar *)ptr, length); + return (size_t) (end-ptr); +} int ob_strnncoll_mb_bin(const ObCharsetInfo *cs __attribute__((unused)), - const unsigned char *str1, size_t str1_len, - const unsigned char *str2, size_t str2_len) + const unsigned char *s, size_t slen, + const unsigned char *t, size_t tlen, + bool t_is_prefix) { - size_t len = str1_len < str2_len ? str1_len : str2_len; - int cmp = memcmp(str1, str2, len); - return cmp ? cmp : (int) (str1_len - str2_len); + size_t len= OB_MIN(slen,tlen); + int cmp= memcmp(s,t,len); + return cmp ? cmp : (int) ((t_is_prefix ? len : slen) - tlen); +} + +int __attribute__ ((noinline)) ob_strnncollsp_mb_bin_help( + const unsigned char **a_, size_t a_length, + const unsigned char **b_, size_t b_length, + const unsigned char **end_, + bool diff_if_only_endspace_difference, int *has_returned, int *res_, size_t length) +{ + *has_returned = 0; + const unsigned char *a = *a_; + const unsigned char *b = *b_; + const unsigned char *end = *end_; + int res = *res_; + int swap= 1; + if (a_length != b_length) { + if (diff_if_only_endspace_difference) { + res= 1; + } + if (a_length < b_length) { + a_length= b_length; + a= b; + swap= -1; + res= -res; + } + for (end= a + a_length-length; a < end ; a++) { + if (*a != ' ') { + *has_returned = 1; + break; + } + } + } + *a_ = a; + *b_ = b; + *end_ = end; + *res_ = res; + if (*has_returned == 1) { + return (!diff_if_only_endspace_difference && *a < ' ') ? -swap : swap; + } + return 0; } int ob_strnncollsp_mb_bin(const ObCharsetInfo *cs __attribute__((unused)), - const unsigned char *str1, size_t str1_len, - const unsigned char *str2, size_t str2_len) + const unsigned char *a, size_t a_length, + const unsigned char *b, size_t b_length, + bool diff_if_only_endspace_difference) { const unsigned char *end; size_t length; int res; - end= str1 + (length= (str1_len < str2_len ? str1_len : str2_len)); - while (str1 < end) { - if (*str1++ != *str2++) - return ((int) str1[-1] - (int) str2[-1]); + end= a + (length= OB_MIN(a_length, b_length)); + while (a < end) { + if (*a++ != *b++) { + return ((int) a[-1] - (int) b[-1]); + } } - res = 0; - if (str1_len != str2_len) { - int swap = 1; - if (str1_len < str2_len) { - str1_len = str2_len; - str1 = str2; - swap = -1; - res = -res; + res= 0; + int has_returned = 0; + int tmp = ob_strnncollsp_mb_bin_help( + &a, a_length, + &b, b_length, + &end, + diff_if_only_endspace_difference, &has_returned, &res, length); + return has_returned == 1 ? tmp : res; +} + +#define ob_strnxfrm_mb_non_ascii_char(cs, dst, src, se) \ +{ \ + switch (cs->cset->ismbchar(cs, (const char*) src, (const char*) se)) { \ + case 4: \ + *dst++= *src++; \ + \ + case 3: \ + *dst++= *src++; \ + \ + case 2: \ + *dst++= *src++; \ + \ + case 0: \ + *dst++= *src++; \ + } \ +} + +size_t ob_strnxfrm_mb(const ObCharsetInfo *cs, + unsigned char *dst, size_t dstlen, unsigned int nweights, + const unsigned char *src, size_t src_len, unsigned int flags, bool *is_valid_unicode) +{ + unsigned char *d0= dst; + unsigned char *de= dst + dstlen; + const unsigned char *se= src + src_len; + const unsigned char *sort_order= cs->sort_order; + + *is_valid_unicode = 1; + + if (dstlen >= src_len && nweights >= src_len) { + if (sort_order) { + while (src < se) { + if (*src < 128) { + *dst++= sort_order[*src++]; + } else { + ob_strnxfrm_mb_non_ascii_char(cs, dst, src, se); + } + nweights--; + } + } else { + while (src < se) { + if (*src < 128) { + *dst++= *src++; + } else { + ob_strnxfrm_mb_non_ascii_char(cs, dst, src, se); + } + nweights--; + } } - for (end = str1 + str1_len - length; str1 < end; str1++) { - if (*str1 != ' ') return (*str1 < ' ') ? -swap : swap; + goto pad; + } + + for (; src < se && nweights && dst < de; nweights--) { + int chlen; + if (*src < 128 || + !(chlen= cs->cset->ismbchar(cs, (const char*) src, (const char*) se))) { + + *dst++= sort_order ? sort_order[*src++] : *src++; + } else { + int len= (dst + chlen <= de) ? chlen : de - dst; + memcpy(dst, src, len); + dst+= len; + src+= len; } } - return res; -} -//===================================================================== +pad: + return ob_strxfrm_pad_desc_and_reverse(cs, d0, dst, de, nweights, flags, 0); +} + +#define INC_PTR(cs,A,B) A+=(ob_ismbchar(cs,A,B) ? ob_ismbchar(cs,A,B) : 1) -static int ob_wildcmp_mb_bin_impl_help(const ObCharsetInfo *cs, const char **str_ptr_, - const char **str_end_ptr_, const char **wild_str_ptr_, const char **wild_end_ptr_, int escape_char, - int w_one_char, int w_many_char, int *cmp_result, int *has_returned) +static int ob_wildcmp_mb_bin_impl_help(const ObCharsetInfo *cs, const char **str_, + const char **str_end_, const char **wildstr_, const char **wildend_, int escape_char, + int w_one, int w_many, int *result, int *has_returned) { - const char *wild_str_ptr = *wild_str_ptr_; - const char *str_end_ptr = *str_end_ptr_; - const char *str_ptr = *str_ptr_; - const char *wild_end_ptr = *wild_end_ptr_; + const char *wild_str = *wildstr_; + const char *str_end = *str_end_; + const char *str = *str_; + const char *wild_end = *wildend_; *has_returned = 0; int ret = 0; - while (*wild_str_ptr == escape_char || (*wild_str_ptr != w_many_char && *wild_str_ptr != w_one_char)) { - int l; - if (*wild_str_ptr == escape_char && wild_str_ptr + 1 != wild_end_ptr) - wild_str_ptr++; - if ((l = cs->cset->ismbchar(wild_str_ptr, wild_end_ptr-wild_str_ptr))) { - if (str_ptr + l > str_end_ptr || memcmp(str_ptr, wild_str_ptr, l) != 0) { + int l; + while (*wild_str == escape_char || (*wild_str != w_many && *wild_str != w_one)) { + if (*wild_str == escape_char && wild_str + 1 != wild_end) { + wild_str++; + } + if ((l = ob_ismbchar(cs, wild_str, wild_end))) { + if (str + l > str_end || memcmp(str, wild_str, l) != 0) { *has_returned = 1; ret = 1; break; } - str_ptr += l; - wild_str_ptr += l; - } else if (str_ptr == str_end_ptr || *wild_str_ptr++ != *str_ptr++) { + str += l; + wild_str += l; + } else if (str == str_end || *wild_str++ != *str++) { *has_returned = 1; ret = 1; break; } - if (wild_str_ptr == wild_end_ptr) { + if (wild_str == wild_end) { *has_returned = 1; - ret = (str_ptr != str_end_ptr); + ret = (str != str_end); break; + } else { + *result = 1; } - *cmp_result = 1; } - *wild_str_ptr_ = wild_str_ptr; - *str_end_ptr_ = str_end_ptr; - *str_ptr_ = str_ptr; - *wild_end_ptr_ = wild_end_ptr; + *wildstr_ = wild_str; + *str_end_ = str_end; + *str_ = str; + *wildend_ = wild_end; return ret; } -static int ob_wildcmp_mb_bin_impl(const ObCharsetInfo *cs, const char *str_ptr, - const char *str_end_ptr, const char *wild_str_ptr, const char *wild_end_ptr, int escape_char, - int w_one_char, int w_many_char, int recurse_level) +static int ob_wildcmp_mb_bin_impl(const ObCharsetInfo *cs, const char *str, + const char *str_end, const char *wild_str, const char *wild_end, int escape_char, + int w_one, int w_many, int recurse_level) { - int cmp_result = -1; - - while (wild_str_ptr != wild_end_ptr) { + int result = -1; + while (wild_str != wild_end) { int has_returned = 0; - int tmp = ob_wildcmp_mb_bin_impl_help(cs, &str_ptr,&str_end_ptr, &wild_str_ptr, &wild_end_ptr, escape_char,w_one_char,w_many_char, &cmp_result, &has_returned); + int tmp = ob_wildcmp_mb_bin_impl_help(cs, &str,&str_end, &wild_str, &wild_end, escape_char,w_one,w_many, &result, &has_returned); if (has_returned) { return tmp; - } - if (*wild_str_ptr == w_one_char) { + } else if (*wild_str == w_one) { do { - if (str_ptr == str_end_ptr) - return (cmp_result); - INC_PTR(cs, str_ptr, str_end_ptr); - } while (++wild_str_ptr < wild_end_ptr && *wild_str_ptr == w_one_char); - if (wild_str_ptr == wild_end_ptr) + if (str == str_end) { + return (result); + } else { + INC_PTR(cs, str, str_end); + } + } while (++wild_str < wild_end && *wild_str == w_one); + if (wild_str == wild_end) { break; + } } - if (*wild_str_ptr == w_many_char) { + if (*wild_str == w_many) { unsigned char cmp; - const char* mb = wild_str_ptr; + const char* mb = wild_str; int mb_len = 0; - wild_str_ptr++; - for (; wild_str_ptr != wild_end_ptr; wild_str_ptr++) { - if (*wild_str_ptr == w_many_char) + wild_str++; + + for (; wild_str != wild_end; wild_str++) { + if (*wild_str == w_many) { continue; - if (escape_char != w_one_char && *wild_str_ptr == w_one_char) { - if (str_ptr == str_end_ptr) + } else if (escape_char != w_one && *wild_str == w_one) { + if (str == str_end) { return (-1); - INC_PTR(cs, str_ptr, str_end_ptr); - continue; - } - break; + } else { + INC_PTR(cs, str, str_end); + continue; + } + } else { + break; + } } - if (wild_str_ptr == wild_end_ptr) - return (0); - if (str_ptr == str_end_ptr) + if (wild_str == wild_end) { + return (0); + } else if (str == str_end) { return -1; + } else if ((cmp = *wild_str) == escape_char && wild_str + 1 != wild_end) { + cmp = *++wild_str; + } - if ((cmp = *wild_str_ptr) == escape_char && wild_str_ptr + 1 != wild_end_ptr) - cmp = *++wild_str_ptr; - - mb = wild_str_ptr; - mb_len = cs->cset->ismbchar(wild_str_ptr, wild_end_ptr-wild_str_ptr); - INC_PTR(cs, wild_str_ptr, wild_end_ptr); + mb = wild_str; + mb_len = ob_ismbchar(cs, wild_str, wild_end); + INC_PTR(cs, wild_str, wild_end); do { - for (;;) { - if (str_ptr >= str_end_ptr) + while(TRUE) { + if (str >= str_end) { return -1; - if (mb_len) { - if (str_ptr + mb_len <= str_end_ptr && memcmp(str_ptr, mb, mb_len) == 0) { - str_ptr += mb_len; + } else if (mb_len) { + if (str + mb_len <= str_end && memcmp(str, mb, mb_len) == 0) { + str += mb_len; break; } - } else if (!cs->cset->ismbchar(str_ptr, str_end_ptr-str_ptr) && *str_ptr == cmp) { - str_ptr++; + } else if (!ob_ismbchar(cs, str, str_end) && *str == cmp) { + str++; break; } - INC_PTR(cs, str_ptr, str_end_ptr); + INC_PTR(cs, str, str_end); } { - int tmp = ob_wildcmp_mb_bin_impl(cs, str_ptr, str_end_ptr, wild_str_ptr, wild_end_ptr, - escape_char, w_one_char, w_many_char, recurse_level + 1); - if (tmp <= 0) + int tmp = ob_wildcmp_mb_bin_impl(cs, str, str_end, wild_str, wild_end, + escape_char, w_one, w_many, recurse_level + 1); + if (tmp <= 0) { return (tmp); - } - } while (str_ptr != str_end_ptr && (wild_str_ptr >= wild_end_ptr || wild_str_ptr[0] != w_many_char)); + } + } + } while (str != str_end && (wild_str >= wild_end || wild_str[0] != w_many)); return (-1); } } - return (str_ptr != str_end_ptr ? 1 : 0); + return (str != str_end ? 1 : 0); } int ob_wildcmp_mb_bin(const ObCharsetInfo *cs, const char *str,const char *str_end, - const char *wildstr,const char *wildend, - int escape, int w_one, int w_many) + const char *wild_str,const char *wild_end, + int escape_char, int w_one, int w_many) { return ob_wildcmp_mb_bin_impl(cs, str, str_end, - wildstr, wildend, - escape, w_one, w_many, 1); + wild_str, wild_end, + escape_char, w_one, w_many, 1); } -// ================================================================ - void ob_hash_sort_mb_bin(const ObCharsetInfo *cs __attribute__((unused)), - const unsigned char *key, size_t len, uint64_t *nr1, uint64_t *nr2, - const int calc_end_space, hash_algo hash_algo) + const unsigned char *key, size_t len,unsigned long int *nr1, unsigned long int *nr2, + const bool calc_end_space, hash_algo hash_algo) { const unsigned char *pos = key; - /* - Remove trailing spaces. We have to do this to be able to compare - 'A ' and 'A' as identical - */ if (!calc_end_space) { key= skip_trailing_space(key, len); } else { @@ -559,12 +726,30 @@ void ob_hash_sort_mb_bin(const ObCharsetInfo *cs __attribute__((unused)), } int length = (int)(key - pos); if (NULL == hash_algo) { - for (; pos < (unsigned char*) key ; pos++) - { - nr1[0]^=(uint64_t) ((((uint64_t) nr1[0] & 63)+nr2[0]) * ((uint64_t)*pos)) + (nr1[0] << 8); + while (pos < (unsigned char*) key) { + nr1[0]^=(unsigned long int) ((((unsigned int) nr1[0] & 63)+nr2[0]) * + ((unsigned int)*pos)) + (nr1[0] << 8); nr2[0]+=3; + pos++; } } else { nr1[0] = hash_algo((void*)pos, length, nr1[0]); } } + + + +ObCollationHandler ob_collation_mb_bin_handler = { + ob_strnncoll_mb_bin, + ob_strnncollsp_mb_bin, + ob_strnxfrm_mb, + ob_like_range_mb, + ob_wildcmp_mb_bin, + ob_instr_mb, + ob_hash_sort_mb_bin, + ob_propagate_simple +}; + + +#undef INC_PTR +#undef likeconv diff --git a/src/lib/charset/ob_ctype_simple.c b/src/lib/charset/ob_ctype_simple.c index 60527014da32fbe622e2ba12a48d8167015ba6cc..601f3906198f5cacc81924544f269a446c7c3a5b 100644 --- a/src/lib/charset/ob_ctype_simple.c +++ b/src/lib/charset/ob_ctype_simple.c @@ -17,7 +17,7 @@ #define CUTLIM (UINT64_MAX % 10) #define DIGITS_IN_ULONGLONG 20 -static uint64_t d10[DIGITS_IN_ULONGLONG]= +static ulonglong d10[DIGITS_IN_ULONGLONG]= { 1, 10, @@ -41,501 +41,749 @@ static uint64_t d10[DIGITS_IN_ULONGLONG]= 10000000000000000000ULL }; -int64_t ob_strntoll_8bit(const char *str, size_t len, int base, char **endptr, int *err) +long ob_strntol_8bit(const ObCharsetInfo *cs, + const char *nptr, size_t l, int base, + char **end_ptr, int *err) { - int is_negative; - uint64_t cutoff; - unsigned int cutlim; - uint64_t tmp_res; - const char *s, *e; - const char *save; + + const char *save, *s = nptr, *e = nptr+l; + unsigned char c; + unsigned int cut_lim; + *err= 0; + uint32 cut_off; + while (s='0' && c<='9') { + c -= '0'; + } else if (c>='A' && c<='Z') { + c = c - 'A' + 10; + } else if (c>='a' && c<='z') { + c = c - 'a' + 10; + } else { + break; + } - for(; s < e && 0x20 == *s; s++); + if (c >= base) { + break; + } else if (i > cut_off || (i == cut_off && c > cut_lim)) { + overflow = 1; + } else { + i *= (uint32) base; + i += c; + } + } - if (s == e) { - *err = EDOM; - if (endptr != NULL) { - *endptr = (char *) str; + if (s == save) { + goto NO_CONV; + } else if (end_ptr != NULL) { + *end_ptr = (char *) s; + } + + if (neg) { + if (i > (uint32) INT_MIN32) { + overflow = 1; } - return 0L; + } else if (i > INT_MAX32) { + overflow = 1; + } + + if (overflow) { + err[0]= ERANGE; + return neg ? INT_MIN32 : INT_MAX32; + } + + return (neg ? -((long) i) : (long) i); + +NO_CONV: + err[0]= EDOM; + if (end_ptr != NULL) { + *end_ptr = (char *) nptr; + } + return 0L; +} + + +ulong ob_strntoul_8bit(const ObCharsetInfo *cs, + const char *nptr, size_t l, int base, + char **end_ptr, int *err) +{ + int neg; + unsigned char c; + const char *save, *e = nptr+l, *s = nptr; + uint32 cut_off; + unsigned int cut_lim; + + *err= 0; + + while (s='0' && c<='9') { c -= '0'; - } else if (c>='A' && c<='Z') { - c = c - 'A' + 10; } else if (c>='a' && c<='z') { c = c - 'a' + 10; + } else if (c>='A' && c<='Z') { + c = c - 'A' + 10; } else { break; } if (c >= base) { break; - } - if (tmp_res > cutoff || (tmp_res == cutoff && c > cutlim)) { + } else if (i > cut_off || (i == cut_off && c > cut_lim)) { overflow = 1; } else { - tmp_res *= (uint64_t) base; - tmp_res += c; + i *= (uint32) base; + i += c; } } if (s == save) { - *err = EDOM; - if (endptr != NULL) { - *endptr = (char *) str; + goto NO_CONV; + } else if (end_ptr != NULL) { + *end_ptr = (char *) s; + } + + if (neg) { + err[0]= ERANGE; + return 0; + } else if (overflow) { + err[0]= ERANGE; + return (~(uint32) 0); + } else { + return ((long) i); + } + +NO_CONV: + err[0]= EDOM; + if (end_ptr != NULL) { + *end_ptr = (char *) nptr; + } + return 0L; +} + + +longlong ob_strntoll_8bit(const ObCharsetInfo *cs __attribute__((unused)), + const char *nptr, size_t l, int base, + char **end_ptr,int *err) +{ + ulonglong cut_off; + unsigned int cut_lim; + const char *s = nptr, *e = nptr+l, *save; + *err= 0; + + while (s='0' && c<='9') + c -= '0'; + else if (c>='A' && c<='Z') + c = c - 'A' + 10; + else if (c>='a' && c<='z') + c = c - 'a' + 10; + else + break; + if (c >= base) + break; + if (i > cut_off || (i == cut_off && c > cut_lim)) + overflow = 1; + else { + i *= (ulonglong) base; + i += c; } - return 0L; + s++; } - if (endptr != NULL) { - *endptr = (char *) s; + if (s == save) { + goto NO_CONV; + } else if (end_ptr != NULL) { + *end_ptr = (char *) s; } - if (is_negative) { - if (tmp_res > (uint64_t) INT64_MIN) { + if (neg) { + if (i > (ulonglong) LONGLONG_MIN) { overflow = 1; } - } else if (tmp_res > (uint64_t) INT64_MAX) { + } else if (i > (ulonglong) LONGLONG_MAX) { overflow = 1; - } + } if (overflow) { - *err= ERANGE; - return is_negative ? INT64_MIN : INT64_MAX; + err[0]= ERANGE; + return neg ? LONGLONG_MIN : LONGLONG_MAX; + } else { + return (neg ? -((longlong) i) : (longlong) i); } - return (is_negative ? -((int64_t) tmp_res) : (int64_t) tmp_res); +NO_CONV: + err[0]= EDOM; + if (end_ptr != NULL) { + *end_ptr = (char *) nptr; + } + return 0L; } -uint64_t ob_strntoull_8bit(const char *str, size_t len, int base, char **endptr, int *err) +ulonglong ob_strntoull_8bit(const ObCharsetInfo *cs, + const char *nptr, size_t l, int base, + char **end_ptr, int *err) { - int is_negative; - uint64_t cutoff; - unsigned int cutlim; - uint64_t tmp_res; - const char *s, *e; - const char *save; - int overflow; - *err= 0; + ulonglong cut_off; + unsigned int cut_lim; + const char *s = nptr, *e = nptr + l, *save; + *err= 0; - s = str; - e = str + len; + while (s='0' && c<='9') { c -= '0'; - } else if (c>='A' && c<='Z') { - c = c - 'A' + 10; } else if (c>='a' && c<='z') { c = c - 'a' + 10; + } else if (c>='A' && c<='Z') { + c = c - 'A' + 10; } else { break; } if (c >= base) { break; - } - if (tmp_res > cutoff || (tmp_res == cutoff && c > cutlim)) { + } else if (i > cut_off || (i == cut_off && c > cut_lim)) { overflow = 1; } else { - tmp_res *= (unsigned int) base; - tmp_res += c; + i *= (ulonglong) base; + i += c; } + s++; } if (s == save) { - *err = EDOM; - if (endptr != NULL) { - *endptr = (char *) str; - } - return 0L; - } - - if (endptr != NULL) { - *endptr = (char *) s; + goto NO_CONV; + } else if (NULL != end_ptr) { + *end_ptr = (char *) s; } if (overflow) { err[0]= ERANGE; - return UINT64_MAX; - } else if (is_negative) { + return (~(ulonglong) 0); + } else if (neg) { err[0]= ERANGE; - return -((int64_t)tmp_res); + return -((longlong) i); } else { - return ((int64_t)tmp_res); + return ((longlong) i); } - return tmp_res; +NO_CONV: + err[0]= EDOM; + if (NULL != end_ptr) { + *end_ptr = (char *) nptr; + } + return 0L; } -double ob_strntod_8bit(char *str, size_t len, char **end, int *err) + + +double ob_strntod_8bit(const ObCharsetInfo *cs __attribute__((unused)), + char *str, size_t len, + char **end, int *err) { - if (len > UINT16_MAX) { - len = UINT16_MAX; - } + if (len == INT_MAX32) { + len= 65535; + } *end= str + len; return ob_strtod(str, end, err); } -uint64_t -ob_strntoull10rnd_8bit(const char *str_ptr, size_t str_len, int unsigned_flag, - char **end_ptr, int *error) +ulonglong +ob_strntoull10rnd_8bit(const ObCharsetInfo *cs __attribute__((unused)), + const char *str, size_t len, int unsigned_flag, + char **end_ptr, int *err) { - const char *dot_ptr, *end_ptr9, *beg_ptr, *end= str_ptr + str_len; - unsigned long long value_ull; - unsigned long value_ul; + const char *dot, *end9, *beg, *end= str + len; + ulonglong ull; + unsigned long int ul; unsigned char ch; - int shift_value= 0, digits_value= 0, negative_sign, addon_value; + int shift = 0, digits = 0, neg, addon; - for ( ; str_ptr < end && (*str_ptr == ' ' || *str_ptr == '\t') ; str_ptr++); - - if (str_ptr >= end) { - goto ret_edom; + while (str < end && (*str == ' ' || *str == '\t')) { + str++; } - if ((negative_sign= (*str_ptr == '-')) || *str_ptr=='+') { - if (++str_ptr == end) { - goto ret_edom; + if (str >= end) { + goto RET_EDOM; + } else if ((neg= (*str == '-')) || *str=='+') { + if (++str == end) { + goto RET_EDOM; } } - beg_ptr= str_ptr; - end_ptr9= (str_ptr + 9) > end ? end : (str_ptr + 9); - for (value_ul= 0 ; str_ptr < end_ptr9 && (ch= (unsigned char) (*str_ptr - '0')) < 10; str_ptr++) { - value_ul= value_ul * 10 + ch; + beg= str; + end9= (str + 9) > end ? end : (str + 9); + + for (ul= 0 ; str < end9 && (ch= (unsigned char) (*str - '0')) < 10; str++) { + ul= ul * 10 + ch; } - if (str_ptr >= end) { - *end_ptr= (char*) str_ptr; - if (negative_sign) { + if (str >= end) { + *end_ptr= (char*) str; + if (neg) { if (unsigned_flag) { - *error= value_ul ? MY_ERRNO_ERANGE : 0; + *err= ul ? OB_ERRNO_ERANGE : 0; return 0; } else { - *error= 0; - return (uint64_t) (int64_t) -(int64_t) value_ul; + *err= 0; + return (ulonglong) (longlong) -(long) ul; } } else { - *error=0; - return (uint64_t) value_ul; + *err=0; + return (ulonglong) ul; } } - digits_value= str_ptr - beg_ptr; + digits= str - beg; - for (dot_ptr= NULL, value_ull= value_ul; str_ptr < end; str_ptr++) { - if ((ch= (unsigned char) (*str_ptr - '0')) < 10) { - if (value_ull < CUTOFF || (value_ull == CUTOFF && ch <= CUTLIM)) { - value_ull= value_ull * 10 + ch; - digits_value++; + for (dot= NULL, ull= ul; str < end; str++) { + if ((ch= (unsigned char) (*str - '0')) < 10) { + if (ull < CUTOFF || (ull == CUTOFF && ch <= CUTLIM)) { + ull= ull * 10 + ch; + digits++; continue; - } - - if (value_ull == CUTOFF) { - value_ull= UINT64_MAX; - addon_value= 1; - str_ptr++; + } else if (ull == CUTOFF) { + ull= ULONGLONG_MAX; + addon= 1; + str++; } else { - addon_value= (*str_ptr >= '5'); + addon= (*str >= '5'); } - if (!dot_ptr) { - for ( ; str_ptr < end && (ch= (unsigned char) (*str_ptr - '0')) < 10; shift_value++, str_ptr++); - if (str_ptr < end && *str_ptr == '.') { - str_ptr++; - for ( ; str_ptr < end && (ch= (unsigned char) (*str_ptr - '0')) < 10; str_ptr++); + if (!dot) { + while (str < end && (ch= (unsigned char) (*str - '0')) < 10) { + shift++; + str++; + } + if (str < end && *str == '.') { + str++; + while (str < end && (ch= (unsigned char) (*str - '0')) < 10) { + str++; + } } } else { - shift_value= dot_ptr - str_ptr; - for ( ; str_ptr < end && (ch= (unsigned char) (*str_ptr - '0')) < 10; str_ptr++); + shift= dot - str; + while (str < end && (ch= (unsigned char) (*str - '0')) < 10) { + str++; + } } - goto exp; + goto EXP; } - if (*str_ptr == '.') { - if (dot_ptr) { - addon_value= 0; - goto exp; + if (*str == '.') { + if (dot) { + addon= 0; + goto EXP; } else { - dot_ptr= str_ptr + 1; + dot= str + 1; } continue; } - break; } - shift_value= dot_ptr ? dot_ptr - str_ptr : 0; - addon_value= 0; - -exp: - - if (!digits_value) { - str_ptr= beg_ptr; - goto ret_edom; - } - - if (negative_sign && unsigned_flag) { - goto ret_sign; - } - if (str_ptr < end && (*str_ptr == 'e' || *str_ptr == 'E')) { - str_ptr++; - if (str_ptr < end) { - int negative_sign_exp, exponent; - if ((negative_sign_exp= (*str_ptr == '-')) || *str_ptr=='+') { - if (++str_ptr == end) - goto ret_sign; + shift= dot ? dot - str : 0; + addon= 0; + +EXP: + if (!digits) { + str= beg; + goto RET_EDOM; + } else if (neg && unsigned_flag) { + goto RET_SIGN; + } else if (str < end && (*str == 'e' || *str == 'E')) { + str++; + if (str < end) { + int neg_exp, exponent; + if ((neg_exp= (*str == '-')) || *str=='+') { + if (++str == end) { + goto RET_SIGN; + } } for (exponent= 0 ; - str_ptr < end && (ch= (unsigned char) (*str_ptr - '0')) < 10; - str_ptr++) { + str < end && (ch= (unsigned char) (*str - '0')) < 10; + str++) { exponent= exponent * 10 + ch; } - shift_value+= negative_sign_exp ? -exponent : exponent; + shift+= neg_exp ? -exponent : exponent; } } - if (shift_value == 0) { - if (addon_value) { - if (value_ull == UINT64_MAX) { - goto ret_too_big; + if (shift == 0) { + if (addon) { + if (ull == ULONGLONG_MAX) { + goto RET_TOO_LARGE; + } else { + ull++; } - value_ull++; } - goto ret_sign; + goto RET_SIGN; } - if (shift_value < 0) { - uint64_t d, r, d_half; - - if (-shift_value >= DIGITS_IN_ULONGLONG) { - goto ret_zero; - } + if (shift < 0) { + ulonglong d, r, d_half; - d= d10[-shift_value]; - r= value_ull % d; - value_ull /= d; - d_half = d/2; - if (r >= d_half) { - value_ull++; + if (-shift >= DIGITS_IN_ULONGLONG) { + goto RET_ZERO; + } else { + d= d10[-shift]; + r= ull % d; + d_half = d / 2; + ull /= d; + if (r >= d_half) { + ull++; + } + goto RET_SIGN; } - goto ret_sign; } - if (shift_value > DIGITS_IN_ULONGLONG) { - if (!value_ull) { - goto ret_sign; + if (shift > DIGITS_IN_ULONGLONG) { + if (!ull) { + goto RET_SIGN; + } else { + goto RET_TOO_LARGE; } - goto ret_too_big; } - for ( ; shift_value > 0; shift_value--, value_ull*= 10) { - if (value_ull > CUTOFF) { - goto ret_too_big; + while (shift > 0) { + if (ull > CUTOFF) { + goto RET_TOO_LARGE; + } else { + shift--; + ull*= 10; } } -ret_sign: - *end_ptr= (char*) str_ptr; +RET_SIGN: + *end_ptr= (char*) str; if (!unsigned_flag) { - if (negative_sign) { - if (value_ull > (uint64_t) INT64_MIN) { - *error= MY_ERRNO_ERANGE; - return (uint64_t) INT64_MIN; + if (neg) { + if (ull > (ulonglong) LONGLONG_MIN) { + *err= OB_ERRNO_ERANGE; + return (ulonglong) LONGLONG_MIN; + } else { + *err= 0; + return (ulonglong) -(longlong) ull; } - *error= 0; - return (uint64_t) -(int64_t) value_ull; } else { - if (value_ull > (uint64_t) INT64_MAX) { - *error= MY_ERRNO_ERANGE; - return (uint64_t) INT64_MAX; + if (ull > (ulonglong) LONGLONG_MAX) { + *err= OB_ERRNO_ERANGE; + return (ulonglong) LONGLONG_MAX; + } else { + *err= 0; + return ull; } - *error= 0; - return value_ull; } } - if (negative_sign && value_ull) { - *error= MY_ERRNO_ERANGE; + + if (neg && ull) { + *err= OB_ERRNO_ERANGE; return 0; } - *error= 0; - return value_ull; -ret_zero: - *end_ptr= (char*) str_ptr; - *error= 0; +RET_ZERO: + *end_ptr= (char*) str; + *err= 0; return 0; -ret_edom: - *end_ptr= (char*) str_ptr; - *error= MY_ERRNO_EDOM; +RET_EDOM: + *end_ptr= (char*) str; + *err= OB_ERRNO_EDOM; return 0; -ret_too_big: - *end_ptr= (char*) str_ptr; - *error= MY_ERRNO_ERANGE; +RET_TOO_LARGE: + *end_ptr= (char*) str; + *err= OB_ERRNO_ERANGE; return unsigned_flag ? - UINT64_MAX : - negative_sign ? (uint64_t) INT64_MIN : (uint64_t) INT64_MAX; + ULONGLONG_MAX : + neg ? (ulonglong) LONGLONG_MIN : (ulonglong) LONGLONG_MAX; } -size_t ob_scan_8bit(const char *str, const char *end, int sq) +void ob_strxfrm_desc_and_reverse(unsigned char *str, unsigned char *str_end, + unsigned int flags, unsigned int level) { - const char *str_begin= str; + if (flags & (OB_STRXFRM_DESC_LEVEL1 << level)) { + if (flags & (OB_STRXFRM_REVERSE_LEVEL1 << level)) { + for (str_end--; str <= str_end;) { + unsigned char tmp= *str; + *str++= ~*str_end; + *str_end--= ~tmp; + } + } else { + while (str < str_end) { + *str= ~*str; + str++; + } + } + } else if (flags & (OB_STRXFRM_REVERSE_LEVEL1 << level)) { + for (str_end--; str < str_end;) { + unsigned char tmp= *str; + *str++= *str_end; + *str_end--= tmp; + } + } +} + +size_t ob_scan_8bit(const ObCharsetInfo *cs, const char *str, const char *end, + int sq) +{ + const char *str0= str; switch (sq) { case OB_SEQ_INTTAIL: if (str < end && *str == '.') { - for(str++; str != end && *str == '0'; str++); - return (size_t) (str - str_begin); + for(str++ ; str != end && *str == '0' ; str++); + return (size_t) (str - str0); + } else { + return 0; } - return 0; case OB_SEQ_SPACES: - for (; str < end; str++) { - if (' ' != *str) { + for ( ; str < end ; str++) { + if (!ob_isspace(cs,*str)) { break; } } - return (size_t) (str - str_begin); + return (size_t) (str - str0); default: return 0; } } -//======================================================================== -int ob_like_range_simple(const ObCharsetInfo *cs, - const char *str, size_t str_len, - int escape, int w_one, int w_many, - size_t res_length, - char *min_str, char *max_str, - size_t *min_length, size_t *max_length) +size_t ob_strxfrm_pad_desc_and_reverse(const ObCharsetInfo *cs, + unsigned char *str, unsigned char *frm_end, unsigned char *str_end, + unsigned int nweights, unsigned int flags, unsigned int level) { - const char *end= str + str_len; + if (nweights && frm_end < str_end && (flags & OB_STRXFRM_PAD_WITH_SPACE)) { + unsigned int fill_len= OB_MIN((unsigned int) (str_end - frm_end), nweights * cs->mbminlen); + cs->cset->fill(cs, (char*) frm_end, fill_len, cs->pad_char); + frm_end+= fill_len; + } + ob_strxfrm_desc_and_reverse(str, frm_end, flags, level); + if ((flags & OB_STRXFRM_PAD_TO_MAXLEN) && frm_end < str_end) { + unsigned int fill_len= str_end - frm_end; + cs->cset->fill(cs, (char*) frm_end, fill_len, cs->pad_char); + frm_end= str_end; + } + return frm_end - str; +} + +size_t ob_strnxfrmlen_simple(const ObCharsetInfo *cs, size_t len) +{ + return len * (cs->strxfrm_multiply ? cs->strxfrm_multiply : 1); +} + +bool ob_like_range_simple(const ObCharsetInfo *cs, + const char *ptr, size_t ptr_len, + pbool escape_char, pbool w_one, pbool w_many, + size_t res_len, + char *min_str,char *max_str, + size_t *min_len, size_t *max_len) +{ + const char *end= ptr + ptr_len; char *min_org=min_str; - char *min_end=min_str+res_length; - size_t charlen= res_length / cs->mbmaxlen; + char *min_end=min_str+res_len; + size_t charlen= res_len / cs->mbmaxlen; - for (; str != end && min_str != min_end && charlen > 0 ; str++, charlen--) { - if (*str == escape && str+1 != end) { - str++; /* Skip escape */ - *min_str++= *max_str++ = *str; + for (; ptr != end && min_str != min_end && charlen > 0 ; ptr++, charlen--) { + if (*ptr == escape_char && ptr+1 != end) { + ptr++; + *min_str++= *max_str++ = *ptr; continue; - } - if (*str == w_one) { /* '_' in SQL */ - *min_str++='\0'; /* This should be min char */ + } else if (*ptr == w_one) { + *min_str++='\0'; *max_str++= (char) cs->max_sort_char; continue; - } - if (*str == w_many) { /* '%' in SQL */ - /* Calculate length of keys */ - *min_length= ((cs->state & OB_CS_BINSORT) ? + } else if (*ptr == w_many) { + *min_len= ((cs->state & OB_CS_BINSORT) ? (size_t) (min_str - min_org) : - res_length); - *max_length= res_length; + res_len); + *max_len= res_len; do { *min_str++= 0; *max_str++= (char) cs->max_sort_char; } while (min_str != min_end); return 0; } - *min_str++= *max_str++ = *str; + *min_str++= *max_str++ = *ptr; } - *min_length= *max_length = (size_t) (min_str - min_org); + *min_len= *max_len = (size_t) (min_str - min_org); while (min_str != min_end) { - *min_str++= *max_str++ = ' '; /* Because if key compression */ + *min_str++= *max_str++ = ' '; } return 0; } -//================================================================= +bool ob_propagate_simple(const ObCharsetInfo *cs __attribute__((unused)), + const unsigned char *str __attribute__((unused)), + size_t len __attribute__((unused))) +{ + return 1; +} +bool ob_propagate_complex(const ObCharsetInfo *cs __attribute__((unused)), + const unsigned char *str __attribute__((unused)), + size_t len __attribute__((unused))) +{ + return 0; +} void ob_fill_8bit(const ObCharsetInfo *cs __attribute__((unused)), - char *str, size_t len, int fill) + char *s, size_t l, int fill) { - memset(str, fill, len); + memset(s, fill, l); } -int64_t ob_strntoll(const char *str, size_t str_len, int base, char **end, int *err) +int64_t ob_strntoll(const char *ptr, size_t len, int base, char **end, int *err) { - return ob_strntoll_8bit(str, str_len, base, end, err); + return ob_strntoll_8bit(&ob_charset_bin, ptr, len, base, end, err); } -int64_t ob_strntoull(const char *str, size_t str_len, int base, char **end, int *err) +int64_t ob_strntoull(const char *ptr, size_t len, int base, char **end, int *err) { - return ob_strntoull_8bit(str, str_len, base, end, err); + return ob_strntoull_8bit(&ob_charset_bin, ptr, len, base, end, err); +} + +void ob_hash_sort_simple(const ObCharsetInfo *cs, + const unsigned char *key, size_t len, + unsigned long int *nr1, unsigned long int *nr2, + const bool calc_end_space, hash_algo hash_algo) +{ + unsigned char *sort_order=cs->sort_order; + const unsigned char *end; + unsigned char data[HASH_BUFFER_LENGTH]; + int length = 0; + end= calc_end_space ? key + len : skip_trailing_space(key, len); + + if (NULL == hash_algo) { + for (; key < (unsigned char*) end ; key++) { + nr1[0]^=(unsigned long int) ((((unsigned int) nr1[0] & 63)+nr2[0]) * + ((unsigned int) sort_order[(unsigned int) *key])) + (nr1[0] << 8); + nr2[0]+=3; + } + } else { + while (key < (unsigned char*)end) { + length = (int)((unsigned char*)end - key) > HASH_BUFFER_LENGTH ? + HASH_BUFFER_LENGTH : (int)((unsigned char*)end - key); + for (int i = 0; i < length; i++, key++) { + data[i] = sort_order[(unsigned int) *key]; + } + nr1[0] = hash_algo(&data, length, nr1[0]); + } + } } -const unsigned char *skip_trailing_space(const unsigned char *str, size_t len) +#define SPACE_INT 0x20202020 + +const uchar *skip_trailing_space(const uchar *ptr,size_t len) { - const unsigned char *end = str + len; - const int64_t SIZEOF_INT = 4; - const int64_t SPACE_INT = 0x20202020; + const unsigned char *end= ptr + len; if (len > 20) { - const unsigned char *end_words= (const unsigned char *)(int64_t) - (((uint64_t)(int64_t)end) / SIZEOF_INT * SIZEOF_INT); - const unsigned char *start_words= (const unsigned char *)(int64_t) - ((((uint64_t)(int64_t)str) + SIZEOF_INT - 1) / SIZEOF_INT * SIZEOF_INT); - ob_charset_assert(((uint64_t)(int64_t)str) >= SIZEOF_INT); - if (end_words > str) { + const unsigned char *end_words= (const unsigned char *)(int_ptr) + (((ulonglong)(int_ptr)end) / SIZEOF_INT * SIZEOF_INT); + const unsigned char *start_words= (const unsigned char *)(int_ptr) + ((((ulonglong)(int_ptr)ptr) + SIZEOF_INT - 1) / SIZEOF_INT * SIZEOF_INT); + ob_charset_assert(((ulonglong)(int_ptr)ptr) >= SIZEOF_INT); + if (end_words > ptr) { while (end > end_words && end[-1] == 0x20) { end--; } @@ -546,8 +794,282 @@ const unsigned char *skip_trailing_space(const unsigned char *str, size_t len) } } } - while (end > str && end[-1] == 0x20) { + while (end > ptr && end[-1] == 0x20) end--; - } return (end); } + +size_t ob_strxfrm_pad(const ObCharsetInfo *cs, unsigned char *str, unsigned char *frm_end, + unsigned char *str_end, unsigned int nweights, unsigned int flags) { + if (nweights && frm_end < str_end && (flags & OB_STRXFRM_PAD_WITH_SPACE)) { + unsigned int fill_len = OB_MIN((unsigned int)(str_end - frm_end), nweights * cs->mbminlen); + cs->cset->fill(cs, (char *)frm_end, fill_len, cs->pad_char); + frm_end += fill_len; + } + if ((flags & OB_STRXFRM_PAD_TO_MAXLEN) && frm_end < str_end) { + size_t fill_len = str_end - frm_end; + cs->cset->fill(cs, (char *)frm_end, fill_len, cs->pad_char); + frm_end = str_end; + } + return frm_end - str; +} + +size_t ob_caseup_8bit(const ObCharsetInfo *cs __attribute__((unused)), + char* src __attribute__((unused)), size_t srclen __attribute__((unused)), + char* dst __attribute__((unused)), size_t dstlen __attribute__((unused))){ + const char *end = src + srclen; + ob_charset_assert(src == dst && srclen == dstlen); + for (; src != end; src++) *src = ob_toupper(cs,*src); + return srclen; +} + +size_t ob_casedn_8bit(const ObCharsetInfo *cs __attribute__((unused)), + char* src __attribute__((unused)), size_t srclen __attribute__((unused)), + char* dst __attribute__((unused)), size_t dstlen __attribute__((unused))){ + char *end = src + srclen; + ob_charset_assert(src == dst && srclen == dstlen); + for (; src != end; src++) *src = ob_tolower(cs,*src); + return srclen; +} + +int ob_strnncoll_simple(const ObCharsetInfo *cs __attribute__((unused)), + const uchar *s, size_t slen, + const uchar *t, size_t tlen, + bool is_prefix) +{ + size_t len = (slen > tlen) ? tlen : slen; + if (is_prefix && slen > tlen) slen = tlen; + while (len--) { + if(ob_sort_order(cs,*s)!=ob_sort_order(cs,*t)) { + return (int)ob_sort_order(cs,*s) - (int)ob_sort_order(cs,*t); + } + s++; + t++; + } + return slen > tlen ? 1 : slen < tlen ? -1 : 0; +} + +static int ob_strnncollsp_simple(const ObCharsetInfo *cs + __attribute__((unused)), + const uchar *s, size_t slen, + const uchar *t, size_t tlen, + bool diff_if_only_endspace_difference + __attribute__((unused))) +{ + size_t len = (slen > tlen) ? tlen : slen; + for (size_t i = 0; i < len; i++){ + if(ob_sort_order(cs,*s)!=ob_sort_order(cs,*t)) { + return (int)ob_sort_order(cs,*s) - (int)ob_sort_order(cs,*t); + } + s++; + t++; + } + int res = 0; + if (slen != tlen) { + int swap = 1; + if (diff_if_only_endspace_difference){ + res=1; + } + /* + Check the next not space character of the longer key. If it's < ' ', + then it's smaller than the other key. + */ + if (slen < tlen) { + slen = tlen; + + s = t; + swap = -1; + res = -res; + } + /* + "a" == "a " + "a\0" < "a" + "a\0" < "a " + */ + for (const unsigned char* end = s + slen - len; s < end; s++) { + if (ob_sort_order(cs,*s) != ob_sort_order(cs,(int)(' '))) + return ob_sort_order(cs,*s) < ob_sort_order(cs,(int)(' ')) ? -swap : swap; + } + } + return res; +} + + + +static size_t ob_strnxfrm_simple(const ObCharsetInfo* cs __attribute__((unused)), unsigned char* dst, size_t dstlen, + uint nweights, const unsigned char* src, size_t srclen, unsigned int flags, bool* is_valid_unicode) +{ + uchar *dst0 = dst; + const uchar *end; + const uchar *remainder; + size_t frmlen; + frmlen = dstlen > nweights ? nweights : dstlen; + frmlen = frmlen > srclen ? srclen : frmlen; + end = src + frmlen; + remainder = src + (frmlen % 8); + for (; src < remainder;) *dst++ = ob_sort_order(cs,*src++); + while(src < end) { + *dst++ = ob_sort_order(cs,*src++); + *dst++ = ob_sort_order(cs,*src++); + *dst++ = ob_sort_order(cs,*src++); + *dst++ = ob_sort_order(cs,*src++); + *dst++ = ob_sort_order(cs,*src++); + *dst++ = ob_sort_order(cs,*src++); + *dst++ = ob_sort_order(cs,*src++); + *dst++ = ob_sort_order(cs,*src++); + } + return ob_strxfrm_pad_desc_and_reverse(cs, dst0, dst, dst0 + dstlen, nweights - srclen, flags, 0); +} + +#define likeconv(s, A) (A) +#define INC_PTR(cs, A, B) (A)++ + +static int ob_wildcmp_8bit_impl(const ObCharsetInfo* cs, const char* str_ptr, const char* str_end_ptr, + const char* wild_str, const char* wild_end, int escape_char, int w_one_char, int w_many_char, int recurse_level) +{ + int cmp_result = -1; + + while (wild_str != wild_end) { + while (*wild_str != w_many_char && *wild_str != w_one_char) { + if (*wild_str == escape_char && wild_str + 1 != wild_end) { + wild_str++; + } + if (str_ptr == str_end_ptr || likeconv(cs, *wild_str++) != likeconv(cs, *str_ptr++)) { + return 1; + } + if (wild_str == wild_end) { + return str_ptr != str_end_ptr; + } + cmp_result = 1; + } + if (*wild_str == w_one_char) { + do { + if (str_ptr == str_end_ptr) { + return (cmp_result); + } + INC_PTR(cs, str_ptr, str_end_ptr); + } while (++wild_str < wild_end && *wild_str == w_one_char); + if (wild_str == wild_end) { + break; + } + } + if (*wild_str == w_many_char) { + unsigned char cmp = 0; + wild_str++; + for (; wild_str != wild_end; wild_str++) { + if (*wild_str == w_many_char) { + continue; + } + if (*wild_str == w_one_char) { + if (str_ptr == str_end_ptr) { + return (-1); + } + INC_PTR(cs, str_ptr, str_end_ptr); + continue; + } + break; + } + if (wild_str == wild_end) { + return (0); + } + if (str_ptr == str_end_ptr) { + return (-1); + } + + if ((cmp = *wild_str) == escape_char && wild_str + 1 != wild_end) { + cmp = *++wild_str; + } + + INC_PTR(cs, wild_str, wild_end); + cmp = likeconv(cs, cmp); + do { + while (str_ptr != str_end_ptr && (unsigned char)likeconv(cs, *str_ptr) != cmp) { + str_ptr++; + } + if (str_ptr++ == str_end_ptr) { + return -1; + } + do { + int tmp = ob_wildcmp_8bit_impl( + cs, str_ptr, str_end_ptr, wild_str, wild_end, escape_char, w_one_char, w_many_char, recurse_level + 1); + if (tmp <= 0) { + return tmp; + } + } while (0); + } while (str_ptr != str_end_ptr); + return -1; + } + } + return str_ptr != str_end_ptr ? 1 : 0; +} + +int ob_wildcmp_8bit(const ObCharsetInfo* cs, const char* str, const char* str_end, const char* wildstr, + const char* wildend, int escape, int w_one, int w_many) +{ + return ob_wildcmp_8bit_impl(cs, str, str_end, wildstr, wildend, escape, w_one, w_many, 1); +} + + +uint ob_instr_simple(const ObCharsetInfo* cs __attribute__((unused)), const char* b, size_t b_length, + const char* s, size_t s_length, ob_match_t* match, uint nmatch) +{ + register const unsigned char *str, *search, *end, *search_end; + + if (s_length <= b_length) { + if (!s_length) { + if (nmatch) { + match->beg = 0; + match->end = 0; + match->mb_len = 0; + } + return 1; /* Empty string is always found */ + } + + str = (const unsigned char*)b; + search = (const unsigned char*)s; + end = (const unsigned char*)b + b_length - s_length + 1; + search_end = (const unsigned char*)s + s_length; + + skip: + while (str != end) { + if ((*str++) == (*search)) { + register const unsigned char *i, *j; + + i = str; + j = search + 1; + + while (j != search_end) + if ((*i++) != (*j++)) + goto skip; + + if (nmatch > 0) { + match[0].beg = 0; + match[0].end = (size_t)(str - (const unsigned char*)b - 1); + match[0].mb_len = match[0].end; + + if (nmatch > 1) { + match[1].beg = match[0].end; + match[1].end = match[0].end + s_length; + match[1].mb_len = match[1].end - match[1].beg; + } + } + return 2; + } + } + } + return 0; +} + + +ObCollationHandler ob_collation_8bit_simple_ci_handler = { + // NULL /* init */ + ob_strnncoll_simple, + ob_strnncollsp_simple, + ob_strnxfrm_simple, + //ob_strnxfrmlen_simple, + ob_like_range_simple, + ob_wildcmp_8bit, + //NULL,//ob_strcasecmp_8bit, + ob_instr_simple, + ob_hash_sort_simple, + ob_propagate_simple}; diff --git a/src/lib/charset/ob_ctype_uca.c b/src/lib/charset/ob_ctype_uca.c new file mode 100644 index 0000000000000000000000000000000000000000..7ab0b8f87fafbd2bdcffadc514cb442e660fee9f --- /dev/null +++ b/src/lib/charset/ob_ctype_uca.c @@ -0,0 +1,19898 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#include "lib/charset/ob_mysql_global.h" +#include "lib/charset/ob_ctype.h" + +#define OB_UCA_NPAGES 256 +#define OB_UCA_NCHARS 256 +#define OB_UCA_CMASK 255 +#define OB_UCA_PSHIFT 8 + +#define OB_UCA_MAX_EXPANSION 6 /* Maximum expansion length */ + +#define OB_UCA_CNT_FLAG_SIZE 4096 +#define OB_UCA_CNT_FLAG_MASK 4095 + +#define OB_UCA_CNT_HEAD 1 +#define OB_UCA_CNT_TAIL 2 +#define OB_UCA_CNT_MID1 4 +#define OB_UCA_CNT_MID2 8 +#define OB_UCA_CNT_MID3 16 +#define OB_UCA_CNT_MID4 32 + +#define OB_UCA_PREVIOUS_CONTEXT_HEAD 64 +#define OB_UCA_PREVIOUS_CONTEXT_TAIL 128 + +uint16 page000data[]= { /* 0000 (4 weights per char) */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0201,0x0000,0x0000,0x0000, +0x0202,0x0000,0x0000,0x0000, 0x0203,0x0000,0x0000,0x0000, +0x0204,0x0000,0x0000,0x0000, 0x0205,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0209,0x0000,0x0000,0x0000, 0x0251,0x0000,0x0000,0x0000, +0x027E,0x0000,0x0000,0x0000, 0x02D2,0x0000,0x0000,0x0000, +0x0E0F,0x0000,0x0000,0x0000, 0x02D3,0x0000,0x0000,0x0000, +0x02CF,0x0000,0x0000,0x0000, 0x0277,0x0000,0x0000,0x0000, +0x0288,0x0000,0x0000,0x0000, 0x0289,0x0000,0x0000,0x0000, +0x02C8,0x0000,0x0000,0x0000, 0x0428,0x0000,0x0000,0x0000, +0x022F,0x0000,0x0000,0x0000, 0x0221,0x0000,0x0000,0x0000, +0x025D,0x0000,0x0000,0x0000, 0x02CC,0x0000,0x0000,0x0000, +0x0E29,0x0000,0x0000,0x0000, 0x0E2A,0x0000,0x0000,0x0000, +0x0E2B,0x0000,0x0000,0x0000, 0x0E2C,0x0000,0x0000,0x0000, +0x0E2D,0x0000,0x0000,0x0000, 0x0E2E,0x0000,0x0000,0x0000, +0x0E2F,0x0000,0x0000,0x0000, 0x0E30,0x0000,0x0000,0x0000, +0x0E31,0x0000,0x0000,0x0000, 0x0E32,0x0000,0x0000,0x0000, +0x023D,0x0000,0x0000,0x0000, 0x023A,0x0000,0x0000,0x0000, +0x042C,0x0000,0x0000,0x0000, 0x042D,0x0000,0x0000,0x0000, +0x042E,0x0000,0x0000,0x0000, 0x0255,0x0000,0x0000,0x0000, +0x02C7,0x0000,0x0000,0x0000, 0x0E33,0x0000,0x0000,0x0000, +0x0E4A,0x0000,0x0000,0x0000, 0x0E60,0x0000,0x0000,0x0000, +0x0E6D,0x0000,0x0000,0x0000, 0x0E8B,0x0000,0x0000,0x0000, +0x0EB9,0x0000,0x0000,0x0000, 0x0EC1,0x0000,0x0000,0x0000, +0x0EE1,0x0000,0x0000,0x0000, 0x0EFB,0x0000,0x0000,0x0000, +0x0F10,0x0000,0x0000,0x0000, 0x0F21,0x0000,0x0000,0x0000, +0x0F2E,0x0000,0x0000,0x0000, 0x0F5B,0x0000,0x0000,0x0000, +0x0F64,0x0000,0x0000,0x0000, 0x0F82,0x0000,0x0000,0x0000, +0x0FA7,0x0000,0x0000,0x0000, 0x0FB4,0x0000,0x0000,0x0000, +0x0FC0,0x0000,0x0000,0x0000, 0x0FEA,0x0000,0x0000,0x0000, +0x1002,0x0000,0x0000,0x0000, 0x101F,0x0000,0x0000,0x0000, +0x1044,0x0000,0x0000,0x0000, 0x1051,0x0000,0x0000,0x0000, +0x105A,0x0000,0x0000,0x0000, 0x105E,0x0000,0x0000,0x0000, +0x106A,0x0000,0x0000,0x0000, 0x028A,0x0000,0x0000,0x0000, +0x02CE,0x0000,0x0000,0x0000, 0x028B,0x0000,0x0000,0x0000, +0x020F,0x0000,0x0000,0x0000, 0x021B,0x0000,0x0000,0x0000, +0x020C,0x0000,0x0000,0x0000, 0x0E33,0x0000,0x0000,0x0000, +0x0E4A,0x0000,0x0000,0x0000, 0x0E60,0x0000,0x0000,0x0000, +0x0E6D,0x0000,0x0000,0x0000, 0x0E8B,0x0000,0x0000,0x0000, +0x0EB9,0x0000,0x0000,0x0000, 0x0EC1,0x0000,0x0000,0x0000, +0x0EE1,0x0000,0x0000,0x0000, 0x0EFB,0x0000,0x0000,0x0000, +0x0F10,0x0000,0x0000,0x0000, 0x0F21,0x0000,0x0000,0x0000, +0x0F2E,0x0000,0x0000,0x0000, 0x0F5B,0x0000,0x0000,0x0000, +0x0F64,0x0000,0x0000,0x0000, 0x0F82,0x0000,0x0000,0x0000, +0x0FA7,0x0000,0x0000,0x0000, 0x0FB4,0x0000,0x0000,0x0000, +0x0FC0,0x0000,0x0000,0x0000, 0x0FEA,0x0000,0x0000,0x0000, +0x1002,0x0000,0x0000,0x0000, 0x101F,0x0000,0x0000,0x0000, +0x1044,0x0000,0x0000,0x0000, 0x1051,0x0000,0x0000,0x0000, +0x105A,0x0000,0x0000,0x0000, 0x105E,0x0000,0x0000,0x0000, +0x106A,0x0000,0x0000,0x0000, 0x028C,0x0000,0x0000,0x0000, +0x0430,0x0000,0x0000,0x0000, 0x028D,0x0000,0x0000,0x0000, +0x0433,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0206,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0209,0x0000,0x0000,0x0000, 0x0252,0x0000,0x0000,0x0000, +0x0E0E,0x0000,0x0000,0x0000, 0x0E10,0x0000,0x0000,0x0000, +0x0E0D,0x0000,0x0000,0x0000, 0x0E11,0x0000,0x0000,0x0000, +0x0431,0x0000,0x0000,0x0000, 0x02C2,0x0000,0x0000,0x0000, +0x0214,0x0000,0x0000,0x0000, 0x02C5,0x0000,0x0000,0x0000, +0x0E33,0x0000,0x0000,0x0000, 0x0286,0x0000,0x0000,0x0000, +0x042F,0x0000,0x0000,0x0000, 0x0220,0x0000,0x0000,0x0000, +0x02C6,0x0000,0x0000,0x0000, 0x0210,0x0000,0x0000,0x0000, +0x034A,0x0000,0x0000,0x0000, 0x0429,0x0000,0x0000,0x0000, +0x0E2B,0x0000,0x0000,0x0000, 0x0E2C,0x0000,0x0000,0x0000, +0x020D,0x0000,0x0000,0x0000, 0x10F8,0x0000,0x0000,0x0000, +0x02C3,0x0000,0x0000,0x0000, 0x0267,0x0000,0x0000,0x0000, +0x0219,0x0000,0x0000,0x0000, 0x0E2A,0x0000,0x0000,0x0000, +0x0F82,0x0000,0x0000,0x0000, 0x0287,0x0000,0x0000,0x0000, +0x0E2A,0x02CD,0x0E2D,0x0000, 0x0E2A,0x02CD,0x0E2B,0x0000, +0x0E2C,0x02CD,0x0E2D,0x0000, 0x0256,0x0000,0x0000,0x0000, +0x0E33,0x0000,0x0000,0x0000, 0x0E33,0x0000,0x0000,0x0000, +0x0E33,0x0000,0x0000,0x0000, 0x0E33,0x0000,0x0000,0x0000, +0x0E33,0x0000,0x0000,0x0000, 0x0E33,0x0000,0x0000,0x0000, +0x0E38,0x0000,0x0000,0x0000, 0x0E60,0x0000,0x0000,0x0000, +0x0E8B,0x0000,0x0000,0x0000, 0x0E8B,0x0000,0x0000,0x0000, +0x0E8B,0x0000,0x0000,0x0000, 0x0E8B,0x0000,0x0000,0x0000, +0x0EFB,0x0000,0x0000,0x0000, 0x0EFB,0x0000,0x0000,0x0000, +0x0EFB,0x0000,0x0000,0x0000, 0x0EFB,0x0000,0x0000,0x0000, +0x0E86,0x0000,0x0000,0x0000, 0x0F64,0x0000,0x0000,0x0000, +0x0F82,0x0000,0x0000,0x0000, 0x0F82,0x0000,0x0000,0x0000, +0x0F82,0x0000,0x0000,0x0000, 0x0F82,0x0000,0x0000,0x0000, +0x0F82,0x0000,0x0000,0x0000, 0x042B,0x0000,0x0000,0x0000, +0x0F8D,0x0000,0x0000,0x0000, 0x101F,0x0000,0x0000,0x0000, +0x101F,0x0000,0x0000,0x0000, 0x101F,0x0000,0x0000,0x0000, +0x101F,0x0000,0x0000,0x0000, 0x105E,0x0000,0x0000,0x0000, +0x1094,0x0000,0x0000,0x0000, 0x0FEA,0x0FEA,0x0000,0x0000, +0x0E33,0x0000,0x0000,0x0000, 0x0E33,0x0000,0x0000,0x0000, +0x0E33,0x0000,0x0000,0x0000, 0x0E33,0x0000,0x0000,0x0000, +0x0E33,0x0000,0x0000,0x0000, 0x0E33,0x0000,0x0000,0x0000, +0x0E38,0x0000,0x0000,0x0000, 0x0E60,0x0000,0x0000,0x0000, +0x0E8B,0x0000,0x0000,0x0000, 0x0E8B,0x0000,0x0000,0x0000, +0x0E8B,0x0000,0x0000,0x0000, 0x0E8B,0x0000,0x0000,0x0000, +0x0EFB,0x0000,0x0000,0x0000, 0x0EFB,0x0000,0x0000,0x0000, +0x0EFB,0x0000,0x0000,0x0000, 0x0EFB,0x0000,0x0000,0x0000, +0x0E86,0x0000,0x0000,0x0000, 0x0F64,0x0000,0x0000,0x0000, +0x0F82,0x0000,0x0000,0x0000, 0x0F82,0x0000,0x0000,0x0000, +0x0F82,0x0000,0x0000,0x0000, 0x0F82,0x0000,0x0000,0x0000, +0x0F82,0x0000,0x0000,0x0000, 0x042A,0x0000,0x0000,0x0000, +0x0F8D,0x0000,0x0000,0x0000, 0x101F,0x0000,0x0000,0x0000, +0x101F,0x0000,0x0000,0x0000, 0x101F,0x0000,0x0000,0x0000, +0x101F,0x0000,0x0000,0x0000, 0x105E,0x0000,0x0000,0x0000, +0x1094,0x0000,0x0000,0x0000, 0x105E,0x0000,0x0000,0x0000 +}; + +uint16 page001data[]= { /* 0100 (3 weights per char) */ +0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, +0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, +0x0E60,0x0000,0x0000, 0x0E60,0x0000,0x0000, 0x0E60,0x0000,0x0000, +0x0E60,0x0000,0x0000, 0x0E60,0x0000,0x0000, 0x0E60,0x0000,0x0000, +0x0E60,0x0000,0x0000, 0x0E60,0x0000,0x0000, 0x0E6D,0x0000,0x0000, +0x0E6D,0x0000,0x0000, 0x0E72,0x0000,0x0000, 0x0E72,0x0000,0x0000, +0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, +0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, +0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, +0x0E8B,0x0000,0x0000, 0x0EC1,0x0000,0x0000, 0x0EC1,0x0000,0x0000, +0x0EC1,0x0000,0x0000, 0x0EC1,0x0000,0x0000, 0x0EC1,0x0000,0x0000, +0x0EC1,0x0000,0x0000, 0x0EC1,0x0000,0x0000, 0x0EC1,0x0000,0x0000, +0x0EE1,0x0000,0x0000, 0x0EE1,0x0000,0x0000, 0x0EED,0x0000,0x0000, +0x0EED,0x0000,0x0000, 0x0EFB,0x0000,0x0000, 0x0EFB,0x0000,0x0000, +0x0EFB,0x0000,0x0000, 0x0EFB,0x0000,0x0000, 0x0EFB,0x0000,0x0000, +0x0EFB,0x0000,0x0000, 0x0EFB,0x0000,0x0000, 0x0EFB,0x0000,0x0000, +0x0EFB,0x0000,0x0000, 0x0EFF,0x0000,0x0000, 0x0EFB,0x0F10,0x0000, +0x0EFB,0x0F10,0x0000, 0x0F10,0x0000,0x0000, 0x0F10,0x0000,0x0000, +0x0F21,0x0000,0x0000, 0x0F21,0x0000,0x0000, 0x0FBC,0x0000,0x0000, +0x0F2E,0x0000,0x0000, 0x0F2E,0x0000,0x0000, 0x0F2E,0x0000,0x0000, +0x0F2E,0x0000,0x0000, 0x0F2E,0x0000,0x0000, 0x0F2E,0x0000,0x0000, +0x0F2E,0x0267,0x0000, 0x0F2E,0x0267,0x0000, 0x0F36,0x0000,0x0000, +0x0F36,0x0000,0x0000, 0x0F64,0x0000,0x0000, 0x0F64,0x0000,0x0000, +0x0F64,0x0000,0x0000, 0x0F64,0x0000,0x0000, 0x0F64,0x0000,0x0000, +0x0F64,0x0000,0x0000, 0x10B1,0x0F64,0x0000, 0x0F7E,0x0000,0x0000, +0x0F7E,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x0F82,0x0E8B,0x0000, 0x0F82,0x0E8B,0x0000, +0x0FC0,0x0000,0x0000, 0x0FC0,0x0000,0x0000, 0x0FC0,0x0000,0x0000, +0x0FC0,0x0000,0x0000, 0x0FC0,0x0000,0x0000, 0x0FC0,0x0000,0x0000, +0x0FEA,0x0000,0x0000, 0x0FEA,0x0000,0x0000, 0x0FEA,0x0000,0x0000, +0x0FEA,0x0000,0x0000, 0x0FEA,0x0000,0x0000, 0x0FEA,0x0000,0x0000, +0x0FEA,0x0000,0x0000, 0x0FEA,0x0000,0x0000, 0x1002,0x0000,0x0000, +0x1002,0x0000,0x0000, 0x1002,0x0000,0x0000, 0x1002,0x0000,0x0000, +0x1007,0x0000,0x0000, 0x1007,0x0000,0x0000, 0x101F,0x0000,0x0000, +0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, +0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, +0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, +0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x1051,0x0000,0x0000, +0x1051,0x0000,0x0000, 0x105E,0x0000,0x0000, 0x105E,0x0000,0x0000, +0x105E,0x0000,0x0000, 0x106A,0x0000,0x0000, 0x106A,0x0000,0x0000, +0x106A,0x0000,0x0000, 0x106A,0x0000,0x0000, 0x106A,0x0000,0x0000, +0x106A,0x0000,0x0000, 0x0FEA,0x0000,0x0000, 0x0E52,0x0000,0x0000, +0x0E58,0x0000,0x0000, 0x0E5C,0x0000,0x0000, 0x0E5C,0x0000,0x0000, +0x10A8,0x0000,0x0000, 0x10A8,0x0000,0x0000, 0x0F92,0x0000,0x0000, +0x0E65,0x0000,0x0000, 0x0E65,0x0000,0x0000, 0x0E76,0x0000,0x0000, +0x0E7A,0x0000,0x0000, 0x0E7E,0x0000,0x0000, 0x0E7E,0x0000,0x0000, +0x106A,0x1051,0x0000, 0x0E90,0x0000,0x0000, 0x0E94,0x0000,0x0000, +0x0E98,0x0000,0x0000, 0x0EBD,0x0000,0x0000, 0x0EBD,0x0000,0x0000, +0x0ED1,0x0000,0x0000, 0x0ED9,0x0000,0x0000, 0x0EE9,0x0000,0x0000, +0x0F0C,0x0000,0x0000, 0x0F08,0x0000,0x0000, 0x0F26,0x0000,0x0000, +0x0F26,0x0000,0x0000, 0x0F3B,0x0000,0x0000, 0x0F53,0x0000,0x0000, +0x1037,0x0000,0x0000, 0x0F6E,0x0000,0x0000, 0x0F72,0x0000,0x0000, +0x0F9A,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x0EDD,0x0000,0x0000, 0x0EDD,0x0000,0x0000, 0x0FAC,0x0000,0x0000, +0x0FAC,0x0000,0x0000, 0x0FC4,0x0000,0x0000, 0x10A0,0x0000,0x0000, +0x10A0,0x0000,0x0000, 0x0FF2,0x0000,0x0000, 0x0FF6,0x0000,0x0000, +0x100B,0x0000,0x0000, 0x100F,0x0000,0x0000, 0x100F,0x0000,0x0000, +0x1013,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, +0x1040,0x0000,0x0000, 0x1049,0x0000,0x0000, 0x1066,0x0000,0x0000, +0x1066,0x0000,0x0000, 0x106F,0x0000,0x0000, 0x106F,0x0000,0x0000, +0x107F,0x0000,0x0000, 0x1084,0x0000,0x0000, 0x1084,0x0000,0x0000, +0x1088,0x0000,0x0000, 0x109C,0x0000,0x0000, 0x10A4,0x0000,0x0000, +0x10A4,0x0000,0x0000, 0x1002,0x0FEA,0x0000, 0x1098,0x0000,0x0000, +0x10C8,0x0000,0x0000, 0x10CC,0x0000,0x0000, 0x10D0,0x0000,0x0000, +0x10D4,0x0000,0x0000, 0x0E6D,0x106A,0x0000, 0x0E6D,0x106A,0x0000, +0x0E6D,0x106A,0x0000, 0x0F2E,0x0F10,0x0000, 0x0F2E,0x0F10,0x0000, +0x0F2E,0x0F10,0x0000, 0x0F64,0x0F10,0x0000, 0x0F64,0x0F10,0x0000, +0x0F64,0x0F10,0x0000, 0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, +0x0EFB,0x0000,0x0000, 0x0EFB,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, +0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, +0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, +0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x0E90,0x0000,0x0000, +0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, +0x0E33,0x0000,0x0000, 0x0E38,0x0000,0x0000, 0x0E38,0x0000,0x0000, +0x0ECD,0x0000,0x0000, 0x0ECD,0x0000,0x0000, 0x0EC1,0x0000,0x0000, +0x0EC1,0x0000,0x0000, 0x0F21,0x0000,0x0000, 0x0F21,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x107F,0x0000,0x0000, 0x107F,0x0000,0x0000, +0x0F10,0x0000,0x0000, 0x0E6D,0x106A,0x0000, 0x0E6D,0x106A,0x0000, +0x0E6D,0x106A,0x0000, 0x0EC1,0x0000,0x0000, 0x0EC1,0x0000,0x0000, +0x0EE9,0x0000,0x0000, 0x1098,0x0000,0x0000, 0x0F64,0x0000,0x0000, +0x0F64,0x0000,0x0000, 0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, +0x0E38,0x0000,0x0000, 0x0E38,0x0000,0x0000, 0x0F8D,0x0000,0x0000, +0x0F8D,0x0000,0x0000 }; + +uint16 page002data[]= { /* 0200 (3 weights per char) */ +0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, +0x0E33,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, +0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0EFB,0x0000,0x0000, +0x0EFB,0x0000,0x0000, 0x0EFB,0x0000,0x0000, 0x0EFB,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x0FC0,0x0000,0x0000, 0x0FC0,0x0000,0x0000, +0x0FC0,0x0000,0x0000, 0x0FC0,0x0000,0x0000, 0x101F,0x0000,0x0000, +0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, +0x0FEA,0x0000,0x0000, 0x0FEA,0x0000,0x0000, 0x1002,0x0000,0x0000, +0x1002,0x0000,0x0000, 0x1090,0x0000,0x0000, 0x1090,0x0000,0x0000, +0x0EE1,0x0000,0x0000, 0x0EE1,0x0000,0x0000, 0x0F72,0x0000,0x0000, +0x0E82,0x0000,0x0000, 0x0FA2,0x0000,0x0000, 0x0FA2,0x0000,0x0000, +0x1073,0x0000,0x0000, 0x1073,0x0000,0x0000, 0x0E33,0x0000,0x0000, +0x0E33,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x105E,0x0000,0x0000, +0x105E,0x0000,0x0000, 0x0F4B,0x0000,0x0000, 0x0F7A,0x0000,0x0000, +0x1017,0x0000,0x0000, 0xFBC0,0x8237,0x0000, 0xFBC0,0x8238,0x0000, +0xFBC0,0x8239,0x0000, 0xFBC0,0x823A,0x0000, 0xFBC0,0x823B,0x0000, +0xFBC0,0x823C,0x0000, 0xFBC0,0x823D,0x0000, 0xFBC0,0x823E,0x0000, +0xFBC0,0x823F,0x0000, 0xFBC0,0x8240,0x0000, 0xFBC0,0x8241,0x0000, +0xFBC0,0x8242,0x0000, 0xFBC0,0x8243,0x0000, 0xFBC0,0x8244,0x0000, +0xFBC0,0x8245,0x0000, 0xFBC0,0x8246,0x0000, 0xFBC0,0x8247,0x0000, +0xFBC0,0x8248,0x0000, 0xFBC0,0x8249,0x0000, 0xFBC0,0x824A,0x0000, +0xFBC0,0x824B,0x0000, 0xFBC0,0x824C,0x0000, 0xFBC0,0x824D,0x0000, +0xFBC0,0x824E,0x0000, 0xFBC0,0x824F,0x0000, 0x0E3E,0x0000,0x0000, +0x0E42,0x0000,0x0000, 0x0E46,0x0000,0x0000, 0x0E58,0x0000,0x0000, +0x0F92,0x0000,0x0000, 0x0E69,0x0000,0x0000, 0x0E76,0x0000,0x0000, +0x0E7A,0x0000,0x0000, 0x0E9C,0x0000,0x0000, 0x0E94,0x0000,0x0000, +0x0EA0,0x0000,0x0000, 0x0E98,0x0000,0x0000, 0x0EA4,0x0000,0x0000, +0x0EA9,0x0000,0x0000, 0x0EAD,0x0000,0x0000, 0x0F19,0x0000,0x0000, +0x0ED1,0x0000,0x0000, 0x0EC5,0x0000,0x0000, 0x0EC9,0x0000,0x0000, +0x0ED9,0x0000,0x0000, 0x0EB5,0x0000,0x0000, 0x102B,0x0000,0x0000, +0x0EF1,0x0000,0x0000, 0x0EF5,0x0000,0x0000, 0x0F08,0x0000,0x0000, +0x0F0C,0x0000,0x0000, 0x0F03,0x0000,0x0000, 0x0F3F,0x0000,0x0000, +0x0F43,0x0000,0x0000, 0x0F47,0x0000,0x0000, 0x0F4F,0x0000,0x0000, +0x1037,0x0000,0x0000, 0x103C,0x0000,0x0000, 0x0F60,0x0000,0x0000, +0x0F6E,0x0000,0x0000, 0x0F76,0x0000,0x0000, 0x0F68,0x0000,0x0000, +0x0F9A,0x0000,0x0000, 0x0F88,0x0000,0x0000, 0x0F9E,0x0000,0x0000, +0x0FB0,0x0000,0x0000, 0x0FC9,0x0000,0x0000, 0x0FCE,0x0000,0x0000, +0x0FD2,0x0000,0x0000, 0x0FD6,0x0000,0x0000, 0x0FDA,0x0000,0x0000, +0x0FDE,0x0000,0x0000, 0x0FE2,0x0000,0x0000, 0x0FC4,0x0000,0x0000, +0x0FE6,0x0000,0x0000, 0x0FEE,0x0000,0x0000, 0x0FF2,0x0000,0x0000, +0x0F1D,0x0000,0x0000, 0x0FFA,0x0000,0x0000, 0x0FFE,0x0000,0x0000, +0x101B,0x0000,0x0000, 0x1013,0x0000,0x0000, 0x1027,0x0000,0x0000, +0x1040,0x0000,0x0000, 0x1049,0x0000,0x0000, 0x104D,0x0000,0x0000, +0x1056,0x0000,0x0000, 0x0F57,0x0000,0x0000, 0x1062,0x0000,0x0000, +0x1077,0x0000,0x0000, 0x107B,0x0000,0x0000, 0x107F,0x0000,0x0000, +0x108C,0x0000,0x0000, 0x10AC,0x0000,0x0000, 0x10B4,0x0000,0x0000, +0x10C4,0x0000,0x0000, 0x10D8,0x0000,0x0000, 0x10DC,0x0000,0x0000, +0x0E4E,0x0000,0x0000, 0x0EB1,0x0000,0x0000, 0x0ED5,0x0000,0x0000, +0x0EE5,0x0000,0x0000, 0x0F15,0x0000,0x0000, 0x0F2A,0x0000,0x0000, +0x0F32,0x0000,0x0000, 0x0FB8,0x0000,0x0000, 0x10BC,0x0000,0x0000, +0x10C0,0x0000,0x0000, 0x0E6D,0x106A,0x0000, 0x0E6D,0x107F,0x0000, +0x0E6D,0x107B,0x0000, 0x1002,0x0FEA,0x0000, 0x1002,0x0FF2,0x0000, +0x1002,0x0E69,0x0000, 0x0EB9,0x0F7E,0x0000, 0x0F2E,0x0FEA,0x0000, +0x0F2E,0x106A,0x0000, 0x10E0,0x0000,0x0000, 0x10E4,0x0000,0x0000, +0x102F,0x0000,0x0000, 0x1033,0x0000,0x0000, 0x0EE1,0x0000,0x0000, +0x0EF1,0x0000,0x0000, 0x0F10,0x0000,0x0000, 0x0FC0,0x0000,0x0000, +0x0FC9,0x0000,0x0000, 0x0FD2,0x0000,0x0000, 0x0FE6,0x0000,0x0000, +0x1051,0x0000,0x0000, 0x105E,0x0000,0x0000, 0x0317,0x0000,0x0000, +0x0319,0x0000,0x0000, 0x0EF9,0x0000,0x0000, 0x10B1,0x0000,0x0000, +0x0EFA,0x0000,0x0000, 0x10B3,0x0000,0x0000, 0x10B8,0x0000,0x0000, +0x10B0,0x0000,0x0000, 0x10B9,0x0000,0x0000, 0x031A,0x0000,0x0000, +0x031B,0x0000,0x0000, 0x031C,0x0000,0x0000, 0x031D,0x0000,0x0000, +0x031E,0x0000,0x0000, 0x031F,0x0000,0x0000, 0x0320,0x0000,0x0000, +0x0321,0x0000,0x0000, 0x0322,0x0000,0x0000, 0x0323,0x0000,0x0000, +0x0324,0x0000,0x0000, 0x0325,0x0000,0x0000, 0x0326,0x0000,0x0000, +0x0327,0x0000,0x0000, 0x0E01,0x0000,0x0000, 0x0E02,0x0000,0x0000, +0x0328,0x0000,0x0000, 0x0329,0x0000,0x0000, 0x032A,0x0000,0x0000, +0x032B,0x0000,0x0000, 0x032C,0x0000,0x0000, 0x032D,0x0000,0x0000, +0x0212,0x0000,0x0000, 0x0213,0x0000,0x0000, 0x0215,0x0000,0x0000, +0x021A,0x0000,0x0000, 0x020E,0x0000,0x0000, 0x0216,0x0000,0x0000, +0x032E,0x0000,0x0000, 0x032F,0x0000,0x0000, 0x0ED9,0x0000,0x0000, +0x0F2E,0x0000,0x0000, 0x0FEA,0x0000,0x0000, 0x105A,0x0000,0x0000, +0x10B4,0x0000,0x0000, 0x0330,0x0000,0x0000, 0x0331,0x0000,0x0000, +0x0332,0x0000,0x0000, 0x0333,0x0000,0x0000, 0x0334,0x0000,0x0000, +0x0335,0x0000,0x0000, 0x0336,0x0000,0x0000, 0x0337,0x0000,0x0000, +0x0338,0x0000,0x0000, 0x10B2,0x0000,0x0000, 0x0339,0x0000,0x0000, +0x033A,0x0000,0x0000, 0x033B,0x0000,0x0000, 0x033C,0x0000,0x0000, +0x033D,0x0000,0x0000, 0x033E,0x0000,0x0000, 0x033F,0x0000,0x0000, +0x0340,0x0000,0x0000, 0x0341,0x0000,0x0000, 0x0342,0x0000,0x0000, +0x0343,0x0000,0x0000, 0x0344,0x0000,0x0000, 0x0345,0x0000,0x0000, +0x0346,0x0000,0x0000, 0x0347,0x0000,0x0000, 0x0348,0x0000,0x0000, +0x0349,0x0000,0x0000 }; + +uint16 page003data[]= { /* 0300 (4 weights per char) */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0xFBC0,0x8358,0x0000,0x0000, 0xFBC0,0x8359,0x0000,0x0000, +0xFBC0,0x835A,0x0000,0x0000, 0xFBC0,0x835B,0x0000,0x0000, +0xFBC0,0x835C,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x0E33,0x0000,0x0000,0x0000, +0x0E8B,0x0000,0x0000,0x0000, 0x0EFB,0x0000,0x0000,0x0000, +0x0F82,0x0000,0x0000,0x0000, 0x101F,0x0000,0x0000,0x0000, +0x0E60,0x0000,0x0000,0x0000, 0x0E6D,0x0000,0x0000,0x0000, +0x0EE1,0x0000,0x0000,0x0000, 0x0F5B,0x0000,0x0000,0x0000, +0x0FC0,0x0000,0x0000,0x0000, 0x1002,0x0000,0x0000,0x0000, +0x1044,0x0000,0x0000,0x0000, 0x105A,0x0000,0x0000,0x0000, +0xFBC0,0x8370,0x0000,0x0000, 0xFBC0,0x8371,0x0000,0x0000, +0xFBC0,0x8372,0x0000,0x0000, 0xFBC0,0x8373,0x0000,0x0000, +0x0317,0x0000,0x0000,0x0000, 0x0318,0x0000,0x0000,0x0000, +0xFBC0,0x8376,0x0000,0x0000, 0xFBC0,0x8377,0x0000,0x0000, +0xFBC0,0x8378,0x0000,0x0000, 0xFBC0,0x8379,0x0000,0x0000, +0x10F3,0x0000,0x0000,0x0000, 0xFBC0,0x837B,0x0000,0x0000, +0xFBC0,0x837C,0x0000,0x0000, 0xFBC0,0x837D,0x0000,0x0000, +0x023A,0x0000,0x0000,0x0000, 0xFBC0,0x837F,0x0000,0x0000, +0xFBC0,0x8380,0x0000,0x0000, 0xFBC0,0x8381,0x0000,0x0000, +0xFBC0,0x8382,0x0000,0x0000, 0xFBC0,0x8383,0x0000,0x0000, +0x020D,0x0000,0x0000,0x0000, 0x0214,0x0000,0x0000,0x0000, +0x10E8,0x0000,0x0000,0x0000, 0x0267,0x0000,0x0000,0x0000, +0x10ED,0x0000,0x0000,0x0000, 0x10F1,0x0000,0x0000,0x0000, +0x10F3,0x0000,0x0000,0x0000, 0xFBC0,0x838B,0x0000,0x0000, +0x10FB,0x0000,0x0000,0x0000, 0xFBC0,0x838D,0x0000,0x0000, +0x1104,0x0000,0x0000,0x0000, 0x1109,0x0000,0x0000,0x0000, +0x10F3,0x0000,0x0000,0x0000, 0x10E8,0x0000,0x0000,0x0000, +0x10E9,0x0000,0x0000,0x0000, 0x10EA,0x0000,0x0000,0x0000, +0x10EC,0x0000,0x0000,0x0000, 0x10ED,0x0000,0x0000,0x0000, +0x10F0,0x0000,0x0000,0x0000, 0x10F1,0x0000,0x0000,0x0000, +0x10F2,0x0000,0x0000,0x0000, 0x10F3,0x0000,0x0000,0x0000, +0x10F5,0x0000,0x0000,0x0000, 0x10F6,0x0000,0x0000,0x0000, +0x10F8,0x0000,0x0000,0x0000, 0x10F9,0x0000,0x0000,0x0000, +0x10FA,0x0000,0x0000,0x0000, 0x10FB,0x0000,0x0000,0x0000, +0x10FC,0x0000,0x0000,0x0000, 0x1100,0x0000,0x0000,0x0000, +0xFBC0,0x83A2,0x0000,0x0000, 0x1102,0x0000,0x0000,0x0000, +0x1103,0x0000,0x0000,0x0000, 0x1104,0x0000,0x0000,0x0000, +0x1105,0x0000,0x0000,0x0000, 0x1106,0x0000,0x0000,0x0000, +0x1107,0x0000,0x0000,0x0000, 0x1109,0x0000,0x0000,0x0000, +0x10F3,0x0000,0x0000,0x0000, 0x1104,0x0000,0x0000,0x0000, +0x10E8,0x0000,0x0000,0x0000, 0x10ED,0x0000,0x0000,0x0000, +0x10F1,0x0000,0x0000,0x0000, 0x10F3,0x0000,0x0000,0x0000, +0x1104,0x0000,0x0000,0x0000, 0x10E8,0x0000,0x0000,0x0000, +0x10E9,0x0000,0x0000,0x0000, 0x10EA,0x0000,0x0000,0x0000, +0x10EC,0x0000,0x0000,0x0000, 0x10ED,0x0000,0x0000,0x0000, +0x10F0,0x0000,0x0000,0x0000, 0x10F1,0x0000,0x0000,0x0000, +0x10F2,0x0000,0x0000,0x0000, 0x10F3,0x0000,0x0000,0x0000, +0x10F5,0x0000,0x0000,0x0000, 0x10F6,0x0000,0x0000,0x0000, +0x10F8,0x0000,0x0000,0x0000, 0x10F9,0x0000,0x0000,0x0000, +0x10FA,0x0000,0x0000,0x0000, 0x10FB,0x0000,0x0000,0x0000, +0x10FC,0x0000,0x0000,0x0000, 0x1100,0x0000,0x0000,0x0000, +0x1102,0x0000,0x0000,0x0000, 0x1102,0x0000,0x0000,0x0000, +0x1103,0x0000,0x0000,0x0000, 0x1104,0x0000,0x0000,0x0000, +0x1105,0x0000,0x0000,0x0000, 0x1106,0x0000,0x0000,0x0000, +0x1107,0x0000,0x0000,0x0000, 0x1109,0x0000,0x0000,0x0000, +0x10F3,0x0000,0x0000,0x0000, 0x1104,0x0000,0x0000,0x0000, +0x10FB,0x0000,0x0000,0x0000, 0x1104,0x0000,0x0000,0x0000, +0x1109,0x0000,0x0000,0x0000, 0xFBC0,0x83CF,0x0000,0x0000, +0x10E9,0x0000,0x0000,0x0000, 0x10F2,0x0000,0x0000,0x0000, +0x1104,0x0000,0x0000,0x0000, 0x1104,0x0000,0x0000,0x0000, +0x1104,0x0000,0x0000,0x0000, 0x1105,0x0000,0x0000,0x0000, +0x10FC,0x0000,0x0000,0x0000, 0x10F5,0x10E8,0x10F3,0x0000, +0x10FF,0x0000,0x0000,0x0000, 0x10FF,0x0000,0x0000,0x0000, +0x10EF,0x0000,0x0000,0x0000, 0x10EF,0x0000,0x0000,0x0000, +0x10EE,0x0000,0x0000,0x0000, 0x10EE,0x0000,0x0000,0x0000, +0x10FE,0x0000,0x0000,0x0000, 0x10FE,0x0000,0x0000,0x0000, +0x110A,0x0000,0x0000,0x0000, 0x110A,0x0000,0x0000,0x0000, +0x110D,0x0000,0x0000,0x0000, 0x110D,0x0000,0x0000,0x0000, +0x110E,0x0000,0x0000,0x0000, 0x110E,0x0000,0x0000,0x0000, +0x110F,0x0000,0x0000,0x0000, 0x110F,0x0000,0x0000,0x0000, +0x1110,0x0000,0x0000,0x0000, 0x1110,0x0000,0x0000,0x0000, +0x1111,0x0000,0x0000,0x0000, 0x1111,0x0000,0x0000,0x0000, +0x1112,0x0000,0x0000,0x0000, 0x1112,0x0000,0x0000,0x0000, +0x1113,0x0000,0x0000,0x0000, 0x1113,0x0000,0x0000,0x0000, +0x10F5,0x0000,0x0000,0x0000, 0x1100,0x0000,0x0000,0x0000, +0x1102,0x0000,0x0000,0x0000, 0x10F4,0x0000,0x0000,0x0000, +0x10F2,0x0000,0x0000,0x0000, 0x10ED,0x0000,0x0000,0x0000, +0x0423,0x0000,0x0000,0x0000, 0x110B,0x0000,0x0000,0x0000, +0x110B,0x0000,0x0000,0x0000, 0x1102,0x0000,0x0000,0x0000, +0x110C,0x0000,0x0000,0x0000, 0x110C,0x0000,0x0000,0x0000, +0xFBC0,0x83FC,0x0000,0x0000, 0xFBC0,0x83FD,0x0000,0x0000, +0xFBC0,0x83FE,0x0000,0x0000, 0xFBC0,0x83FF,0x0000,0x0000 +}; + +uint16 page004data[]= { /* 0400 (3 weights per char) */ +0x1152,0x0000,0x0000, 0x1152,0x0000,0x0000, 0x1145,0x0000,0x0000, +0x114A,0x0000,0x0000, 0x115A,0x0000,0x0000, 0x1173,0x0000,0x0000, +0x1188,0x0000,0x0000, 0x118C,0x0000,0x0000, 0x1194,0x0000,0x0000, +0x11B9,0x0000,0x0000, 0x11DA,0x0000,0x0000, 0x1215,0x0000,0x0000, +0x1219,0x0000,0x0000, 0x117C,0x0000,0x0000, 0x1221,0x0000,0x0000, +0x127D,0x0000,0x0000, 0x1114,0x0000,0x0000, 0x112C,0x0000,0x0000, +0x1130,0x0000,0x0000, 0x1134,0x0000,0x0000, 0x1140,0x0000,0x0000, +0x1152,0x0000,0x0000, 0x115E,0x0000,0x0000, 0x116A,0x0000,0x0000, +0x117C,0x0000,0x0000, 0x1190,0x0000,0x0000, 0x1198,0x0000,0x0000, +0x11B0,0x0000,0x0000, 0x11BE,0x0000,0x0000, 0x11C6,0x0000,0x0000, +0x11DF,0x0000,0x0000, 0x11EF,0x0000,0x0000, 0x11FB,0x0000,0x0000, +0x1203,0x0000,0x0000, 0x120C,0x0000,0x0000, 0x121D,0x0000,0x0000, +0x1239,0x0000,0x0000, 0x123D,0x0000,0x0000, 0x1259,0x0000,0x0000, +0x1261,0x0000,0x0000, 0x1281,0x0000,0x0000, 0x1285,0x0000,0x0000, +0x1289,0x0000,0x0000, 0x128D,0x0000,0x0000, 0x1295,0x0000,0x0000, +0x12A1,0x0000,0x0000, 0x12A9,0x0000,0x0000, 0x12AD,0x0000,0x0000, +0x1114,0x0000,0x0000, 0x112C,0x0000,0x0000, 0x1130,0x0000,0x0000, +0x1134,0x0000,0x0000, 0x1140,0x0000,0x0000, 0x1152,0x0000,0x0000, +0x115E,0x0000,0x0000, 0x116A,0x0000,0x0000, 0x117C,0x0000,0x0000, +0x1190,0x0000,0x0000, 0x1198,0x0000,0x0000, 0x11B0,0x0000,0x0000, +0x11BE,0x0000,0x0000, 0x11C6,0x0000,0x0000, 0x11DF,0x0000,0x0000, +0x11EF,0x0000,0x0000, 0x11FB,0x0000,0x0000, 0x1203,0x0000,0x0000, +0x120C,0x0000,0x0000, 0x121D,0x0000,0x0000, 0x1239,0x0000,0x0000, +0x123D,0x0000,0x0000, 0x1259,0x0000,0x0000, 0x1261,0x0000,0x0000, +0x1281,0x0000,0x0000, 0x1285,0x0000,0x0000, 0x1289,0x0000,0x0000, +0x128D,0x0000,0x0000, 0x1295,0x0000,0x0000, 0x12A1,0x0000,0x0000, +0x12A9,0x0000,0x0000, 0x12AD,0x0000,0x0000, 0x1152,0x0000,0x0000, +0x1152,0x0000,0x0000, 0x1145,0x0000,0x0000, 0x114A,0x0000,0x0000, +0x115A,0x0000,0x0000, 0x1173,0x0000,0x0000, 0x1188,0x0000,0x0000, +0x118C,0x0000,0x0000, 0x1194,0x0000,0x0000, 0x11B9,0x0000,0x0000, +0x11DA,0x0000,0x0000, 0x1215,0x0000,0x0000, 0x1219,0x0000,0x0000, +0x117C,0x0000,0x0000, 0x1221,0x0000,0x0000, 0x127D,0x0000,0x0000, +0x1249,0x0000,0x0000, 0x1249,0x0000,0x0000, 0x129D,0x0000,0x0000, +0x129D,0x0000,0x0000, 0x12B1,0x0000,0x0000, 0x12B1,0x0000,0x0000, +0x12B5,0x0000,0x0000, 0x12B5,0x0000,0x0000, 0x12BD,0x0000,0x0000, +0x12BD,0x0000,0x0000, 0x12B9,0x0000,0x0000, 0x12B9,0x0000,0x0000, +0x12C1,0x0000,0x0000, 0x12C1,0x0000,0x0000, 0x12C5,0x0000,0x0000, +0x12C5,0x0000,0x0000, 0x12C9,0x0000,0x0000, 0x12C9,0x0000,0x0000, +0x12CD,0x0000,0x0000, 0x12CD,0x0000,0x0000, 0x12D1,0x0000,0x0000, +0x12D1,0x0000,0x0000, 0x12D5,0x0000,0x0000, 0x12D5,0x0000,0x0000, +0x1235,0x0000,0x0000, 0x1235,0x0000,0x0000, 0x1255,0x0000,0x0000, +0x1255,0x0000,0x0000, 0x1251,0x0000,0x0000, 0x1251,0x0000,0x0000, +0x124D,0x0000,0x0000, 0x124D,0x0000,0x0000, 0x11F7,0x0000,0x0000, +0x11F7,0x0000,0x0000, 0x034B,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0xFBC0,0x8487,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x1180,0x0000,0x0000, 0x1180,0x0000,0x0000, 0x1299,0x0000,0x0000, +0x1299,0x0000,0x0000, 0x11FF,0x0000,0x0000, 0x11FF,0x0000,0x0000, +0x1134,0x0000,0x0000, 0x1134,0x0000,0x0000, 0x1138,0x0000,0x0000, +0x1138,0x0000,0x0000, 0x113C,0x0000,0x0000, 0x113C,0x0000,0x0000, +0x1166,0x0000,0x0000, 0x1166,0x0000,0x0000, 0x114E,0x0000,0x0000, +0x114E,0x0000,0x0000, 0x119C,0x0000,0x0000, 0x119C,0x0000,0x0000, +0x11AC,0x0000,0x0000, 0x11AC,0x0000,0x0000, 0x11A8,0x0000,0x0000, +0x11A8,0x0000,0x0000, 0x11A4,0x0000,0x0000, 0x11A4,0x0000,0x0000, +0x11CE,0x0000,0x0000, 0x11CE,0x0000,0x0000, 0x11D6,0x0000,0x0000, +0x11D6,0x0000,0x0000, 0x11F3,0x0000,0x0000, 0x11F3,0x0000,0x0000, +0x12D9,0x0000,0x0000, 0x12D9,0x0000,0x0000, 0x1208,0x0000,0x0000, +0x1208,0x0000,0x0000, 0x1211,0x0000,0x0000, 0x1211,0x0000,0x0000, +0x122D,0x0000,0x0000, 0x122D,0x0000,0x0000, 0x1231,0x0000,0x0000, +0x1231,0x0000,0x0000, 0x1241,0x0000,0x0000, 0x1241,0x0000,0x0000, +0x125D,0x0000,0x0000, 0x125D,0x0000,0x0000, 0x1269,0x0000,0x0000, +0x1269,0x0000,0x0000, 0x1271,0x0000,0x0000, 0x1271,0x0000,0x0000, +0x1245,0x0000,0x0000, 0x1245,0x0000,0x0000, 0x1275,0x0000,0x0000, +0x1275,0x0000,0x0000, 0x1279,0x0000,0x0000, 0x1279,0x0000,0x0000, +0x12DD,0x0000,0x0000, 0x115E,0x0000,0x0000, 0x115E,0x0000,0x0000, +0x11A0,0x0000,0x0000, 0x11A0,0x0000,0x0000, 0x11B5,0x0000,0x0000, +0x11B5,0x0000,0x0000, 0x11D2,0x0000,0x0000, 0x11D2,0x0000,0x0000, +0x11CA,0x0000,0x0000, 0x11CA,0x0000,0x0000, 0x126D,0x0000,0x0000, +0x126D,0x0000,0x0000, 0x11C2,0x0000,0x0000, 0x11C2,0x0000,0x0000, +0xFBC0,0x84CF,0x0000, 0x1118,0x0000,0x0000, 0x1118,0x0000,0x0000, +0x111C,0x0000,0x0000, 0x111C,0x0000,0x0000, 0x1128,0x0000,0x0000, +0x1128,0x0000,0x0000, 0x1156,0x0000,0x0000, 0x1156,0x0000,0x0000, +0x1120,0x0000,0x0000, 0x1120,0x0000,0x0000, 0x1124,0x0000,0x0000, +0x1124,0x0000,0x0000, 0x1162,0x0000,0x0000, 0x1162,0x0000,0x0000, +0x116F,0x0000,0x0000, 0x116F,0x0000,0x0000, 0x1177,0x0000,0x0000, +0x1177,0x0000,0x0000, 0x117C,0x0000,0x0000, 0x117C,0x0000,0x0000, +0x1184,0x0000,0x0000, 0x1184,0x0000,0x0000, 0x11E3,0x0000,0x0000, +0x11E3,0x0000,0x0000, 0x11E7,0x0000,0x0000, 0x11E7,0x0000,0x0000, +0x11EB,0x0000,0x0000, 0x11EB,0x0000,0x0000, 0x12A5,0x0000,0x0000, +0x12A5,0x0000,0x0000, 0x121D,0x0000,0x0000, 0x121D,0x0000,0x0000, +0x1225,0x0000,0x0000, 0x1225,0x0000,0x0000, 0x1229,0x0000,0x0000, +0x1229,0x0000,0x0000, 0x1265,0x0000,0x0000, 0x1265,0x0000,0x0000, +0xFBC0,0x84F6,0x0000, 0xFBC0,0x84F7,0x0000, 0x1291,0x0000,0x0000, +0x1291,0x0000,0x0000, 0xFBC0,0x84FA,0x0000, 0xFBC0,0x84FB,0x0000, +0xFBC0,0x84FC,0x0000, 0xFBC0,0x84FD,0x0000, 0xFBC0,0x84FE,0x0000, +0xFBC0,0x84FF,0x0000 }; + +uint16 page005data[]= { /* 0500 (3 weights per char) */ +0x1144,0x0000,0x0000, 0x1144,0x0000,0x0000, 0x1149,0x0000,0x0000, +0x1149,0x0000,0x0000, 0x116E,0x0000,0x0000, 0x116E,0x0000,0x0000, +0x117B,0x0000,0x0000, 0x117B,0x0000,0x0000, 0x11BD,0x0000,0x0000, +0x11BD,0x0000,0x0000, 0x11DE,0x0000,0x0000, 0x11DE,0x0000,0x0000, +0x1207,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1210,0x0000,0x0000, +0x1210,0x0000,0x0000, 0xFBC0,0x8510,0x0000, 0xFBC0,0x8511,0x0000, +0xFBC0,0x8512,0x0000, 0xFBC0,0x8513,0x0000, 0xFBC0,0x8514,0x0000, +0xFBC0,0x8515,0x0000, 0xFBC0,0x8516,0x0000, 0xFBC0,0x8517,0x0000, +0xFBC0,0x8518,0x0000, 0xFBC0,0x8519,0x0000, 0xFBC0,0x851A,0x0000, +0xFBC0,0x851B,0x0000, 0xFBC0,0x851C,0x0000, 0xFBC0,0x851D,0x0000, +0xFBC0,0x851E,0x0000, 0xFBC0,0x851F,0x0000, 0xFBC0,0x8520,0x0000, +0xFBC0,0x8521,0x0000, 0xFBC0,0x8522,0x0000, 0xFBC0,0x8523,0x0000, +0xFBC0,0x8524,0x0000, 0xFBC0,0x8525,0x0000, 0xFBC0,0x8526,0x0000, +0xFBC0,0x8527,0x0000, 0xFBC0,0x8528,0x0000, 0xFBC0,0x8529,0x0000, +0xFBC0,0x852A,0x0000, 0xFBC0,0x852B,0x0000, 0xFBC0,0x852C,0x0000, +0xFBC0,0x852D,0x0000, 0xFBC0,0x852E,0x0000, 0xFBC0,0x852F,0x0000, +0xFBC0,0x8530,0x0000, 0x130A,0x0000,0x0000, 0x130B,0x0000,0x0000, +0x130C,0x0000,0x0000, 0x130D,0x0000,0x0000, 0x130E,0x0000,0x0000, +0x130F,0x0000,0x0000, 0x1310,0x0000,0x0000, 0x1311,0x0000,0x0000, +0x1312,0x0000,0x0000, 0x1313,0x0000,0x0000, 0x1314,0x0000,0x0000, +0x1315,0x0000,0x0000, 0x1316,0x0000,0x0000, 0x1317,0x0000,0x0000, +0x1318,0x0000,0x0000, 0x1319,0x0000,0x0000, 0x131A,0x0000,0x0000, +0x131B,0x0000,0x0000, 0x131C,0x0000,0x0000, 0x131D,0x0000,0x0000, +0x131E,0x0000,0x0000, 0x131F,0x0000,0x0000, 0x1320,0x0000,0x0000, +0x1321,0x0000,0x0000, 0x1322,0x0000,0x0000, 0x1323,0x0000,0x0000, +0x1324,0x0000,0x0000, 0x1325,0x0000,0x0000, 0x1326,0x0000,0x0000, +0x1327,0x0000,0x0000, 0x1328,0x0000,0x0000, 0x1329,0x0000,0x0000, +0x132A,0x0000,0x0000, 0x132B,0x0000,0x0000, 0x132C,0x0000,0x0000, +0x132D,0x0000,0x0000, 0x132E,0x0000,0x0000, 0x132F,0x0000,0x0000, +0xFBC0,0x8557,0x0000, 0xFBC0,0x8558,0x0000, 0x1330,0x0000,0x0000, +0x02EC,0x0000,0x0000, 0x02ED,0x0000,0x0000, 0x0253,0x0000,0x0000, +0x0230,0x0000,0x0000, 0x0257,0x0000,0x0000, 0x02EE,0x0000,0x0000, +0xFBC0,0x8560,0x0000, 0x130A,0x0000,0x0000, 0x130B,0x0000,0x0000, +0x130C,0x0000,0x0000, 0x130D,0x0000,0x0000, 0x130E,0x0000,0x0000, +0x130F,0x0000,0x0000, 0x1310,0x0000,0x0000, 0x1311,0x0000,0x0000, +0x1312,0x0000,0x0000, 0x1313,0x0000,0x0000, 0x1314,0x0000,0x0000, +0x1315,0x0000,0x0000, 0x1316,0x0000,0x0000, 0x1317,0x0000,0x0000, +0x1318,0x0000,0x0000, 0x1319,0x0000,0x0000, 0x131A,0x0000,0x0000, +0x131B,0x0000,0x0000, 0x131C,0x0000,0x0000, 0x131D,0x0000,0x0000, +0x131E,0x0000,0x0000, 0x131F,0x0000,0x0000, 0x1320,0x0000,0x0000, +0x1321,0x0000,0x0000, 0x1322,0x0000,0x0000, 0x1323,0x0000,0x0000, +0x1324,0x0000,0x0000, 0x1325,0x0000,0x0000, 0x1326,0x0000,0x0000, +0x1327,0x0000,0x0000, 0x1328,0x0000,0x0000, 0x1329,0x0000,0x0000, +0x132A,0x0000,0x0000, 0x132B,0x0000,0x0000, 0x132C,0x0000,0x0000, +0x132D,0x0000,0x0000, 0x132E,0x0000,0x0000, 0x132F,0x0000,0x0000, +0x130E,0x132B,0x0000, 0xFBC0,0x8588,0x0000, 0x023E,0x0000,0x0000, +0x0222,0x0000,0x0000, 0xFBC0,0x858B,0x0000, 0xFBC0,0x858C,0x0000, +0xFBC0,0x858D,0x0000, 0xFBC0,0x858E,0x0000, 0xFBC0,0x858F,0x0000, +0xFBC0,0x8590,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0xFBC0,0x85A2,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0xFBC0,0x85BA,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x02EF,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x02F0,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x02F1,0x0000,0x0000, 0x0000,0x0000,0x0000, 0xFBC0,0x85C5,0x0000, +0xFBC0,0x85C6,0x0000, 0xFBC0,0x85C7,0x0000, 0xFBC0,0x85C8,0x0000, +0xFBC0,0x85C9,0x0000, 0xFBC0,0x85CA,0x0000, 0xFBC0,0x85CB,0x0000, +0xFBC0,0x85CC,0x0000, 0xFBC0,0x85CD,0x0000, 0xFBC0,0x85CE,0x0000, +0xFBC0,0x85CF,0x0000, 0x1331,0x0000,0x0000, 0x1332,0x0000,0x0000, +0x1333,0x0000,0x0000, 0x1334,0x0000,0x0000, 0x1335,0x0000,0x0000, +0x1336,0x0000,0x0000, 0x1337,0x0000,0x0000, 0x1338,0x0000,0x0000, +0x1339,0x0000,0x0000, 0x133A,0x0000,0x0000, 0x133B,0x0000,0x0000, +0x133B,0x0000,0x0000, 0x133C,0x0000,0x0000, 0x133D,0x0000,0x0000, +0x133D,0x0000,0x0000, 0x133E,0x0000,0x0000, 0x133E,0x0000,0x0000, +0x133F,0x0000,0x0000, 0x1340,0x0000,0x0000, 0x1341,0x0000,0x0000, +0x1341,0x0000,0x0000, 0x1342,0x0000,0x0000, 0x1342,0x0000,0x0000, +0x1343,0x0000,0x0000, 0x1344,0x0000,0x0000, 0x1345,0x0000,0x0000, +0x1346,0x0000,0x0000, 0xFBC0,0x85EB,0x0000, 0xFBC0,0x85EC,0x0000, +0xFBC0,0x85ED,0x0000, 0xFBC0,0x85EE,0x0000, 0xFBC0,0x85EF,0x0000, +0x1336,0x1336,0x0000, 0x1336,0x133A,0x0000, 0x133A,0x133A,0x0000, +0x02F2,0x0000,0x0000, 0x02F3,0x0000,0x0000, 0xFBC0,0x85F5,0x0000, +0xFBC0,0x85F6,0x0000, 0xFBC0,0x85F7,0x0000, 0xFBC0,0x85F8,0x0000, +0xFBC0,0x85F9,0x0000, 0xFBC0,0x85FA,0x0000, 0xFBC0,0x85FB,0x0000, +0xFBC0,0x85FC,0x0000, 0xFBC0,0x85FD,0x0000, 0xFBC0,0x85FE,0x0000, +0xFBC0,0x85FF,0x0000 }; + +uint16 page006data[]= { /* 0600 (3 weights per char) */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0xFBC0,0x8604,0x0000, 0xFBC0,0x8605,0x0000, +0xFBC0,0x8606,0x0000, 0xFBC0,0x8607,0x0000, 0xFBC0,0x8608,0x0000, +0xFBC0,0x8609,0x0000, 0xFBC0,0x860A,0x0000, 0xFBC0,0x860B,0x0000, +0x0231,0x0000,0x0000, 0x0232,0x0000,0x0000, 0x034C,0x0000,0x0000, +0x034D,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0xFBC0,0x8616,0x0000, 0xFBC0,0x8617,0x0000, +0xFBC0,0x8618,0x0000, 0xFBC0,0x8619,0x0000, 0xFBC0,0x861A,0x0000, +0x023B,0x0000,0x0000, 0xFBC0,0x861C,0x0000, 0xFBC0,0x861D,0x0000, +0xFBC0,0x861E,0x0000, 0x0258,0x0000,0x0000, 0xFBC0,0x8620,0x0000, +0x1347,0x0000,0x0000, 0x1348,0x0000,0x0000, 0x1349,0x0000,0x0000, +0x134C,0x0000,0x0000, 0x134D,0x0000,0x0000, 0x134F,0x0000,0x0000, +0x1350,0x0000,0x0000, 0x1352,0x0000,0x0000, 0x1356,0x0000,0x0000, +0x1357,0x0000,0x0000, 0x1358,0x0000,0x0000, 0x135E,0x0000,0x0000, +0x1364,0x0000,0x0000, 0x1365,0x0000,0x0000, 0x1369,0x0000,0x0000, +0x136A,0x0000,0x0000, 0x1375,0x0000,0x0000, 0x1376,0x0000,0x0000, +0x1381,0x0000,0x0000, 0x1382,0x0000,0x0000, 0x1387,0x0000,0x0000, +0x1388,0x0000,0x0000, 0x138C,0x0000,0x0000, 0x138D,0x0000,0x0000, +0x138F,0x0000,0x0000, 0x1390,0x0000,0x0000, 0xFBC0,0x863B,0x0000, +0xFBC0,0x863C,0x0000, 0xFBC0,0x863D,0x0000, 0xFBC0,0x863E,0x0000, +0xFBC0,0x863F,0x0000, 0x020B,0x0000,0x0000, 0x1393,0x0000,0x0000, +0x139B,0x0000,0x0000, 0x139E,0x0000,0x0000, 0x13AB,0x0000,0x0000, +0x13B0,0x0000,0x0000, 0x13B1,0x0000,0x0000, 0x13B7,0x0000,0x0000, +0x13BD,0x0000,0x0000, 0x13C7,0x0000,0x0000, 0x13C8,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0xFBC0,0x8659,0x0000, +0xFBC0,0x865A,0x0000, 0xFBC0,0x865B,0x0000, 0xFBC0,0x865C,0x0000, +0xFBC0,0x865D,0x0000, 0xFBC0,0x865E,0x0000, 0xFBC0,0x865F,0x0000, +0x0E29,0x0000,0x0000, 0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, +0x0E2C,0x0000,0x0000, 0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, +0x0E2F,0x0000,0x0000, 0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, +0x0E32,0x0000,0x0000, 0x02D4,0x0000,0x0000, 0x0233,0x0000,0x0000, +0x0234,0x0000,0x0000, 0x02CB,0x0000,0x0000, 0x1351,0x0000,0x0000, +0x139A,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x134B,0x0000,0x0000, +0x134A,0x0000,0x0000, 0x134E,0x0000,0x0000, 0x1347,0x0000,0x0000, +0x1350,0x1347,0x0000, 0x13BD,0x1347,0x0000, 0x13C1,0x1347,0x0000, +0x13C8,0x1347,0x0000, 0x1359,0x0000,0x0000, 0x135A,0x0000,0x0000, +0x1353,0x0000,0x0000, 0x135B,0x0000,0x0000, 0x135C,0x0000,0x0000, +0x1354,0x0000,0x0000, 0x135D,0x0000,0x0000, 0x1355,0x0000,0x0000, +0x1366,0x0000,0x0000, 0x1367,0x0000,0x0000, 0x135F,0x0000,0x0000, +0x1360,0x0000,0x0000, 0x1368,0x0000,0x0000, 0x1361,0x0000,0x0000, +0x1363,0x0000,0x0000, 0x136B,0x0000,0x0000, 0x136C,0x0000,0x0000, +0x136D,0x0000,0x0000, 0x136E,0x0000,0x0000, 0x136F,0x0000,0x0000, +0x1370,0x0000,0x0000, 0x1371,0x0000,0x0000, 0x1372,0x0000,0x0000, +0x1373,0x0000,0x0000, 0x1377,0x0000,0x0000, 0x1378,0x0000,0x0000, +0x1379,0x0000,0x0000, 0x137A,0x0000,0x0000, 0x137B,0x0000,0x0000, +0x137C,0x0000,0x0000, 0x137D,0x0000,0x0000, 0x137E,0x0000,0x0000, +0x137F,0x0000,0x0000, 0x1383,0x0000,0x0000, 0x1384,0x0000,0x0000, +0x1385,0x0000,0x0000, 0x1389,0x0000,0x0000, 0x138A,0x0000,0x0000, +0x138E,0x0000,0x0000, 0x1391,0x0000,0x0000, 0x1394,0x0000,0x0000, +0x1395,0x0000,0x0000, 0x1396,0x0000,0x0000, 0x1397,0x0000,0x0000, +0x1398,0x0000,0x0000, 0x1399,0x0000,0x0000, 0x139C,0x0000,0x0000, +0x139D,0x0000,0x0000, 0x139F,0x0000,0x0000, 0x13A0,0x0000,0x0000, +0x13A1,0x0000,0x0000, 0x13A2,0x0000,0x0000, 0x13A3,0x0000,0x0000, +0x13A4,0x0000,0x0000, 0x13A5,0x0000,0x0000, 0x13A6,0x0000,0x0000, +0x13A7,0x0000,0x0000, 0x13A8,0x0000,0x0000, 0x13A9,0x0000,0x0000, +0x13AA,0x0000,0x0000, 0x13AC,0x0000,0x0000, 0x13AD,0x0000,0x0000, +0x13AE,0x0000,0x0000, 0x13AF,0x0000,0x0000, 0x13B6,0x0000,0x0000, +0x13B2,0x0000,0x0000, 0x13B3,0x0000,0x0000, 0x13B4,0x0000,0x0000, +0x13B5,0x0000,0x0000, 0x13B8,0x0000,0x0000, 0x1362,0x0000,0x0000, +0x13BC,0x0000,0x0000, 0x13B9,0x0000,0x0000, 0x13B9,0x0000,0x0000, +0x13BA,0x0000,0x0000, 0x13BE,0x0000,0x0000, 0x13BF,0x0000,0x0000, +0x13C0,0x0000,0x0000, 0x13C1,0x0000,0x0000, 0x13C2,0x0000,0x0000, +0x13C3,0x0000,0x0000, 0x13C4,0x0000,0x0000, 0x13C5,0x0000,0x0000, +0x13C9,0x0000,0x0000, 0x13CA,0x0000,0x0000, 0x13CB,0x0000,0x0000, +0x13C6,0x0000,0x0000, 0x13CC,0x0000,0x0000, 0x13CD,0x0000,0x0000, +0x13CE,0x0000,0x0000, 0x13CE,0x0000,0x0000, 0x025F,0x0000,0x0000, +0x13BC,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x13BD,0x0000,0x0000, 0x13C8,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x034E,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x1374,0x0000,0x0000, 0x1380,0x0000,0x0000, +0x0E29,0x0000,0x0000, 0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, +0x0E2C,0x0000,0x0000, 0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, +0x0E2F,0x0000,0x0000, 0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, +0x0E32,0x0000,0x0000, 0x1386,0x0000,0x0000, 0x138B,0x0000,0x0000, +0x1392,0x0000,0x0000, 0x1347,0x0000,0x0000, 0x13B0,0x0000,0x0000, +0x13BB,0x0000,0x0000 }; + +uint16 page007data[]= { /* 0700 (3 weights per char) */ +0x0270,0x0000,0x0000, 0x0260,0x0000,0x0000, 0x0261,0x0000,0x0000, +0x023F,0x0000,0x0000, 0x0240,0x0000,0x0000, 0x0241,0x0000,0x0000, +0x0242,0x0000,0x0000, 0x0243,0x0000,0x0000, 0x0244,0x0000,0x0000, +0x0259,0x0000,0x0000, 0x02F4,0x0000,0x0000, 0x02F5,0x0000,0x0000, +0x02F6,0x0000,0x0000, 0x02F7,0x0000,0x0000, 0xFBC0,0x870E,0x0000, +0x0000,0x0000,0x0000, 0x13CF,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x13D0,0x0000,0x0000, 0x13D1,0x0000,0x0000, 0x13D1,0x0000,0x0000, +0x13D3,0x0000,0x0000, 0x13D2,0x0000,0x0000, 0x13D4,0x0000,0x0000, +0x13D5,0x0000,0x0000, 0x13D6,0x0000,0x0000, 0x13D8,0x0000,0x0000, +0x13D9,0x0000,0x0000, 0x13D9,0x0000,0x0000, 0x13DA,0x0000,0x0000, +0x13DB,0x0000,0x0000, 0x13DC,0x0000,0x0000, 0x13DE,0x0000,0x0000, +0x13DF,0x0000,0x0000, 0x13E0,0x0000,0x0000, 0x13E1,0x0000,0x0000, +0x13E1,0x0000,0x0000, 0x13E2,0x0000,0x0000, 0x13E3,0x0000,0x0000, +0x13E3,0x0000,0x0000, 0x13E5,0x0000,0x0000, 0x13E6,0x0000,0x0000, +0x13E7,0x0000,0x0000, 0x13E8,0x0000,0x0000, 0x13E9,0x0000,0x0000, +0x13D0,0x0000,0x0000, 0x13D1,0x0000,0x0000, 0x13D3,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0xFBC0,0x874B,0x0000, 0xFBC0,0x874C,0x0000, 0x13D7,0x0000,0x0000, +0x13DD,0x0000,0x0000, 0x13E4,0x0000,0x0000, 0xFBC0,0x8750,0x0000, +0xFBC0,0x8751,0x0000, 0xFBC0,0x8752,0x0000, 0xFBC0,0x8753,0x0000, +0xFBC0,0x8754,0x0000, 0xFBC0,0x8755,0x0000, 0xFBC0,0x8756,0x0000, +0xFBC0,0x8757,0x0000, 0xFBC0,0x8758,0x0000, 0xFBC0,0x8759,0x0000, +0xFBC0,0x875A,0x0000, 0xFBC0,0x875B,0x0000, 0xFBC0,0x875C,0x0000, +0xFBC0,0x875D,0x0000, 0xFBC0,0x875E,0x0000, 0xFBC0,0x875F,0x0000, +0xFBC0,0x8760,0x0000, 0xFBC0,0x8761,0x0000, 0xFBC0,0x8762,0x0000, +0xFBC0,0x8763,0x0000, 0xFBC0,0x8764,0x0000, 0xFBC0,0x8765,0x0000, +0xFBC0,0x8766,0x0000, 0xFBC0,0x8767,0x0000, 0xFBC0,0x8768,0x0000, +0xFBC0,0x8769,0x0000, 0xFBC0,0x876A,0x0000, 0xFBC0,0x876B,0x0000, +0xFBC0,0x876C,0x0000, 0xFBC0,0x876D,0x0000, 0xFBC0,0x876E,0x0000, +0xFBC0,0x876F,0x0000, 0xFBC0,0x8770,0x0000, 0xFBC0,0x8771,0x0000, +0xFBC0,0x8772,0x0000, 0xFBC0,0x8773,0x0000, 0xFBC0,0x8774,0x0000, +0xFBC0,0x8775,0x0000, 0xFBC0,0x8776,0x0000, 0xFBC0,0x8777,0x0000, +0xFBC0,0x8778,0x0000, 0xFBC0,0x8779,0x0000, 0xFBC0,0x877A,0x0000, +0xFBC0,0x877B,0x0000, 0xFBC0,0x877C,0x0000, 0xFBC0,0x877D,0x0000, +0xFBC0,0x877E,0x0000, 0xFBC0,0x877F,0x0000, 0x13EA,0x0000,0x0000, +0x13ED,0x0000,0x0000, 0x13EE,0x0000,0x0000, 0x13EF,0x0000,0x0000, +0x13F1,0x0000,0x0000, 0x13F2,0x0000,0x0000, 0x13F3,0x0000,0x0000, +0x13F4,0x0000,0x0000, 0x13F7,0x0000,0x0000, 0x13F9,0x0000,0x0000, +0x13FA,0x0000,0x0000, 0x13FB,0x0000,0x0000, 0x13FD,0x0000,0x0000, +0x1401,0x0000,0x0000, 0x1402,0x0000,0x0000, 0x1404,0x0000,0x0000, +0x1405,0x0000,0x0000, 0x1409,0x0000,0x0000, 0x140A,0x0000,0x0000, +0x140B,0x0000,0x0000, 0x140C,0x0000,0x0000, 0x140D,0x0000,0x0000, +0x140E,0x0000,0x0000, 0x140F,0x0000,0x0000, 0x13FE,0x0000,0x0000, +0x13EB,0x0000,0x0000, 0x13EC,0x0000,0x0000, 0x13FC,0x0000,0x0000, +0x13F0,0x0000,0x0000, 0x1406,0x0000,0x0000, 0x1407,0x0000,0x0000, +0x1408,0x0000,0x0000, 0x13FF,0x0000,0x0000, 0x1400,0x0000,0x0000, +0x13F5,0x0000,0x0000, 0x13F6,0x0000,0x0000, 0x1403,0x0000,0x0000, +0x13F8,0x0000,0x0000, 0x1411,0x0000,0x0000, 0x1412,0x0000,0x0000, +0x1413,0x0000,0x0000, 0x1414,0x0000,0x0000, 0x1415,0x0000,0x0000, +0x1416,0x0000,0x0000, 0x1417,0x0000,0x0000, 0x1418,0x0000,0x0000, +0x1419,0x0000,0x0000, 0x141A,0x0000,0x0000, 0x141B,0x0000,0x0000, +0x1410,0x0000,0x0000, 0xFBC0,0x87B2,0x0000, 0xFBC0,0x87B3,0x0000, +0xFBC0,0x87B4,0x0000, 0xFBC0,0x87B5,0x0000, 0xFBC0,0x87B6,0x0000, +0xFBC0,0x87B7,0x0000, 0xFBC0,0x87B8,0x0000, 0xFBC0,0x87B9,0x0000, +0xFBC0,0x87BA,0x0000, 0xFBC0,0x87BB,0x0000, 0xFBC0,0x87BC,0x0000, +0xFBC0,0x87BD,0x0000, 0xFBC0,0x87BE,0x0000, 0xFBC0,0x87BF,0x0000, +0xFBC0,0x87C0,0x0000, 0xFBC0,0x87C1,0x0000, 0xFBC0,0x87C2,0x0000, +0xFBC0,0x87C3,0x0000, 0xFBC0,0x87C4,0x0000, 0xFBC0,0x87C5,0x0000, +0xFBC0,0x87C6,0x0000, 0xFBC0,0x87C7,0x0000, 0xFBC0,0x87C8,0x0000, +0xFBC0,0x87C9,0x0000, 0xFBC0,0x87CA,0x0000, 0xFBC0,0x87CB,0x0000, +0xFBC0,0x87CC,0x0000, 0xFBC0,0x87CD,0x0000, 0xFBC0,0x87CE,0x0000, +0xFBC0,0x87CF,0x0000, 0xFBC0,0x87D0,0x0000, 0xFBC0,0x87D1,0x0000, +0xFBC0,0x87D2,0x0000, 0xFBC0,0x87D3,0x0000, 0xFBC0,0x87D4,0x0000, +0xFBC0,0x87D5,0x0000, 0xFBC0,0x87D6,0x0000, 0xFBC0,0x87D7,0x0000, +0xFBC0,0x87D8,0x0000, 0xFBC0,0x87D9,0x0000, 0xFBC0,0x87DA,0x0000, +0xFBC0,0x87DB,0x0000, 0xFBC0,0x87DC,0x0000, 0xFBC0,0x87DD,0x0000, +0xFBC0,0x87DE,0x0000, 0xFBC0,0x87DF,0x0000, 0xFBC0,0x87E0,0x0000, +0xFBC0,0x87E1,0x0000, 0xFBC0,0x87E2,0x0000, 0xFBC0,0x87E3,0x0000, +0xFBC0,0x87E4,0x0000, 0xFBC0,0x87E5,0x0000, 0xFBC0,0x87E6,0x0000, +0xFBC0,0x87E7,0x0000, 0xFBC0,0x87E8,0x0000, 0xFBC0,0x87E9,0x0000, +0xFBC0,0x87EA,0x0000, 0xFBC0,0x87EB,0x0000, 0xFBC0,0x87EC,0x0000, +0xFBC0,0x87ED,0x0000, 0xFBC0,0x87EE,0x0000, 0xFBC0,0x87EF,0x0000, +0xFBC0,0x87F0,0x0000, 0xFBC0,0x87F1,0x0000, 0xFBC0,0x87F2,0x0000, +0xFBC0,0x87F3,0x0000, 0xFBC0,0x87F4,0x0000, 0xFBC0,0x87F5,0x0000, +0xFBC0,0x87F6,0x0000, 0xFBC0,0x87F7,0x0000, 0xFBC0,0x87F8,0x0000, +0xFBC0,0x87F9,0x0000, 0xFBC0,0x87FA,0x0000, 0xFBC0,0x87FB,0x0000, +0xFBC0,0x87FC,0x0000, 0xFBC0,0x87FD,0x0000, 0xFBC0,0x87FE,0x0000, +0xFBC0,0x87FF,0x0000 }; + +uint16 page009data[]= { /* 0900 (3 weights per char) */ +0xFBC0,0x8900,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x155A,0x0000,0x0000, 0x155B,0x0000,0x0000, +0x155C,0x0000,0x0000, 0x155D,0x0000,0x0000, 0x155E,0x0000,0x0000, +0x155F,0x0000,0x0000, 0x1560,0x0000,0x0000, 0x1561,0x0000,0x0000, +0x1563,0x0000,0x0000, 0x1565,0x0000,0x0000, 0x1566,0x0000,0x0000, +0x1567,0x0000,0x0000, 0x1568,0x0000,0x0000, 0x1569,0x0000,0x0000, +0x156A,0x0000,0x0000, 0x156B,0x0000,0x0000, 0x156C,0x0000,0x0000, +0x156D,0x0000,0x0000, 0x156E,0x0000,0x0000, 0x156F,0x0000,0x0000, +0x1570,0x0000,0x0000, 0x1571,0x0000,0x0000, 0x1572,0x0000,0x0000, +0x1573,0x0000,0x0000, 0x1574,0x0000,0x0000, 0x1575,0x0000,0x0000, +0x1576,0x0000,0x0000, 0x1577,0x0000,0x0000, 0x1578,0x0000,0x0000, +0x1579,0x0000,0x0000, 0x157A,0x0000,0x0000, 0x157B,0x0000,0x0000, +0x157C,0x0000,0x0000, 0x157D,0x0000,0x0000, 0x157E,0x0000,0x0000, +0x157F,0x0000,0x0000, 0x1580,0x0000,0x0000, 0x1580,0x0000,0x0000, +0x1581,0x0000,0x0000, 0x1582,0x0000,0x0000, 0x1583,0x0000,0x0000, +0x1584,0x0000,0x0000, 0x1585,0x0000,0x0000, 0x1586,0x0000,0x0000, +0x1587,0x0000,0x0000, 0x1587,0x0000,0x0000, 0x1588,0x0000,0x0000, +0x1589,0x0000,0x0000, 0x1589,0x0000,0x0000, 0x158A,0x0000,0x0000, +0x158B,0x0000,0x0000, 0x158C,0x0000,0x0000, 0x158D,0x0000,0x0000, +0x158E,0x0000,0x0000, 0xFBC0,0x893A,0x0000, 0xFBC0,0x893B,0x0000, +0x0000,0x0000,0x0000, 0x158F,0x0000,0x0000, 0x1590,0x0000,0x0000, +0x1591,0x0000,0x0000, 0x1592,0x0000,0x0000, 0x1593,0x0000,0x0000, +0x1594,0x0000,0x0000, 0x1595,0x0000,0x0000, 0x1596,0x0000,0x0000, +0x1599,0x0000,0x0000, 0x159A,0x0000,0x0000, 0x159B,0x0000,0x0000, +0x159C,0x0000,0x0000, 0x159D,0x0000,0x0000, 0x159E,0x0000,0x0000, +0x159F,0x0000,0x0000, 0x15A0,0x0000,0x0000, 0x15A1,0x0000,0x0000, +0xFBC0,0x894E,0x0000, 0xFBC0,0x894F,0x0000, 0x1559,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0xFBC0,0x8955,0x0000, 0xFBC0,0x8956,0x0000, +0xFBC0,0x8957,0x0000, 0x156D,0x0000,0x0000, 0x156E,0x0000,0x0000, +0x156F,0x0000,0x0000, 0x1574,0x0000,0x0000, 0x1579,0x0000,0x0000, +0x157A,0x0000,0x0000, 0x1582,0x0000,0x0000, 0x1586,0x0000,0x0000, +0x1562,0x0000,0x0000, 0x1564,0x0000,0x0000, 0x1597,0x0000,0x0000, +0x1598,0x0000,0x0000, 0x0268,0x0000,0x0000, 0x0269,0x0000,0x0000, +0x0E29,0x0000,0x0000, 0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, +0x0E2C,0x0000,0x0000, 0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, +0x0E2F,0x0000,0x0000, 0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, +0x0E32,0x0000,0x0000, 0x02FA,0x0000,0x0000, 0xFBC0,0x8971,0x0000, +0xFBC0,0x8972,0x0000, 0xFBC0,0x8973,0x0000, 0xFBC0,0x8974,0x0000, +0xFBC0,0x8975,0x0000, 0xFBC0,0x8976,0x0000, 0xFBC0,0x8977,0x0000, +0xFBC0,0x8978,0x0000, 0xFBC0,0x8979,0x0000, 0xFBC0,0x897A,0x0000, +0xFBC0,0x897B,0x0000, 0xFBC0,0x897C,0x0000, 0xFBC0,0x897D,0x0000, +0xFBC0,0x897E,0x0000, 0xFBC0,0x897F,0x0000, 0xFBC0,0x8980,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0xFBC0,0x8984,0x0000, 0x15A2,0x0000,0x0000, 0x15A3,0x0000,0x0000, +0x15A4,0x0000,0x0000, 0x15A5,0x0000,0x0000, 0x15A6,0x0000,0x0000, +0x15A7,0x0000,0x0000, 0x15A8,0x0000,0x0000, 0x15AA,0x0000,0x0000, +0xFBC0,0x898D,0x0000, 0xFBC0,0x898E,0x0000, 0x15AC,0x0000,0x0000, +0x15AD,0x0000,0x0000, 0xFBC0,0x8991,0x0000, 0xFBC0,0x8992,0x0000, +0x15AE,0x0000,0x0000, 0x15AF,0x0000,0x0000, 0x15B0,0x0000,0x0000, +0x15B1,0x0000,0x0000, 0x15B2,0x0000,0x0000, 0x15B3,0x0000,0x0000, +0x15B4,0x0000,0x0000, 0x15B5,0x0000,0x0000, 0x15B6,0x0000,0x0000, +0x15B7,0x0000,0x0000, 0x15B8,0x0000,0x0000, 0x15B9,0x0000,0x0000, +0x15BA,0x0000,0x0000, 0x15BB,0x0000,0x0000, 0x15BC,0x0000,0x0000, +0x15BD,0x0000,0x0000, 0x15BE,0x0000,0x0000, 0x15BF,0x0000,0x0000, +0x15C0,0x0000,0x0000, 0x15C1,0x0000,0x0000, 0x15C2,0x0000,0x0000, +0x15C3,0x0000,0x0000, 0xFBC0,0x89A9,0x0000, 0x15C4,0x0000,0x0000, +0x15C5,0x0000,0x0000, 0x15C6,0x0000,0x0000, 0x15C7,0x0000,0x0000, +0x15C8,0x0000,0x0000, 0x15C9,0x0000,0x0000, 0x15CA,0x0000,0x0000, +0xFBC0,0x89B1,0x0000, 0x15CC,0x0000,0x0000, 0xFBC0,0x89B3,0x0000, +0xFBC0,0x89B4,0x0000, 0xFBC0,0x89B5,0x0000, 0x15CE,0x0000,0x0000, +0x15CF,0x0000,0x0000, 0x15D0,0x0000,0x0000, 0x15D1,0x0000,0x0000, +0xFBC0,0x89BA,0x0000, 0xFBC0,0x89BB,0x0000, 0x0000,0x0000,0x0000, +0x15D2,0x0000,0x0000, 0x15D3,0x0000,0x0000, 0x15D4,0x0000,0x0000, +0x15D5,0x0000,0x0000, 0x15D6,0x0000,0x0000, 0x15D7,0x0000,0x0000, +0x15D8,0x0000,0x0000, 0x15D9,0x0000,0x0000, 0xFBC0,0x89C5,0x0000, +0xFBC0,0x89C6,0x0000, 0x15DC,0x0000,0x0000, 0x15DD,0x0000,0x0000, +0xFBC0,0x89C9,0x0000, 0xFBC0,0x89CA,0x0000, 0x15DE,0x0000,0x0000, +0x15DF,0x0000,0x0000, 0x15E0,0x0000,0x0000, 0xFBC0,0x89CE,0x0000, +0xFBC0,0x89CF,0x0000, 0xFBC0,0x89D0,0x0000, 0xFBC0,0x89D1,0x0000, +0xFBC0,0x89D2,0x0000, 0xFBC0,0x89D3,0x0000, 0xFBC0,0x89D4,0x0000, +0xFBC0,0x89D5,0x0000, 0xFBC0,0x89D6,0x0000, 0x15E1,0x0000,0x0000, +0xFBC0,0x89D8,0x0000, 0xFBC0,0x89D9,0x0000, 0xFBC0,0x89DA,0x0000, +0xFBC0,0x89DB,0x0000, 0x15BC,0x0000,0x0000, 0x15BD,0x0000,0x0000, +0xFBC0,0x89DE,0x0000, 0x15C9,0x0000,0x0000, 0x15A9,0x0000,0x0000, +0x15AB,0x0000,0x0000, 0x15DA,0x0000,0x0000, 0x15DB,0x0000,0x0000, +0xFBC0,0x89E4,0x0000, 0xFBC0,0x89E5,0x0000, 0x0E29,0x0000,0x0000, +0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, 0x0E2C,0x0000,0x0000, +0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, 0x0E2F,0x0000,0x0000, +0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, 0x0E32,0x0000,0x0000, +0x15CB,0x0000,0x0000, 0x15CD,0x0000,0x0000, 0x0E12,0x0000,0x0000, +0x0E13,0x0000,0x0000, 0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, +0x0E2C,0x0000,0x0000, 0x0E2D,0x0000,0x0000, 0x0DC7,0x0000,0x0000, +0x0DC8,0x0000,0x0000, 0x0350,0x0000,0x0000, 0xFBC0,0x89FB,0x0000, +0xFBC0,0x89FC,0x0000, 0xFBC0,0x89FD,0x0000, 0xFBC0,0x89FE,0x0000, +0xFBC0,0x89FF,0x0000 }; + +uint16 page00Adata[]= { /* 0A00 (3 weights per char) */ +0xFBC0,0x8A00,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0xFBC0,0x8A04,0x0000, 0x15E7,0x0000,0x0000, +0x15E8,0x0000,0x0000, 0x15EC,0x0000,0x0000, 0x15ED,0x0000,0x0000, +0x15E4,0x0000,0x0000, 0x15E5,0x0000,0x0000, 0xFBC0,0x8A0B,0x0000, +0xFBC0,0x8A0C,0x0000, 0xFBC0,0x8A0D,0x0000, 0xFBC0,0x8A0E,0x0000, +0x15EE,0x0000,0x0000, 0x15E9,0x0000,0x0000, 0xFBC0,0x8A11,0x0000, +0xFBC0,0x8A12,0x0000, 0x15E6,0x0000,0x0000, 0x15EA,0x0000,0x0000, +0x15F1,0x0000,0x0000, 0x15F2,0x0000,0x0000, 0x15F3,0x0000,0x0000, +0x15F4,0x0000,0x0000, 0x15F5,0x0000,0x0000, 0x15F6,0x0000,0x0000, +0x15F7,0x0000,0x0000, 0x15F8,0x0000,0x0000, 0x15F9,0x0000,0x0000, +0x15FA,0x0000,0x0000, 0x15FB,0x0000,0x0000, 0x15FC,0x0000,0x0000, +0x15FD,0x0000,0x0000, 0x15FE,0x0000,0x0000, 0x15FF,0x0000,0x0000, +0x1600,0x0000,0x0000, 0x1601,0x0000,0x0000, 0x1602,0x0000,0x0000, +0x1603,0x0000,0x0000, 0x1604,0x0000,0x0000, 0xFBC0,0x8A29,0x0000, +0x1605,0x0000,0x0000, 0x1606,0x0000,0x0000, 0x1607,0x0000,0x0000, +0x1608,0x0000,0x0000, 0x1609,0x0000,0x0000, 0x160A,0x0000,0x0000, +0x160B,0x0000,0x0000, 0xFBC0,0x8A31,0x0000, 0x160C,0x0000,0x0000, +0x160C,0x0000,0x0000, 0xFBC0,0x8A34,0x0000, 0x160D,0x0000,0x0000, +0x15EF,0x0000,0x0000, 0xFBC0,0x8A37,0x0000, 0x15EF,0x0000,0x0000, +0x15F0,0x0000,0x0000, 0xFBC0,0x8A3A,0x0000, 0xFBC0,0x8A3B,0x0000, +0x0000,0x0000,0x0000, 0xFBC0,0x8A3D,0x0000, 0x160F,0x0000,0x0000, +0x1610,0x0000,0x0000, 0x1611,0x0000,0x0000, 0x1612,0x0000,0x0000, +0x1613,0x0000,0x0000, 0xFBC0,0x8A43,0x0000, 0xFBC0,0x8A44,0x0000, +0xFBC0,0x8A45,0x0000, 0xFBC0,0x8A46,0x0000, 0x1614,0x0000,0x0000, +0x1615,0x0000,0x0000, 0xFBC0,0x8A49,0x0000, 0xFBC0,0x8A4A,0x0000, +0x1616,0x0000,0x0000, 0x1617,0x0000,0x0000, 0x1618,0x0000,0x0000, +0xFBC0,0x8A4E,0x0000, 0xFBC0,0x8A4F,0x0000, 0xFBC0,0x8A50,0x0000, +0xFBC0,0x8A51,0x0000, 0xFBC0,0x8A52,0x0000, 0xFBC0,0x8A53,0x0000, +0xFBC0,0x8A54,0x0000, 0xFBC0,0x8A55,0x0000, 0xFBC0,0x8A56,0x0000, +0xFBC0,0x8A57,0x0000, 0xFBC0,0x8A58,0x0000, 0x15F2,0x0000,0x0000, +0x15F3,0x0000,0x0000, 0x15F8,0x0000,0x0000, 0x160E,0x0000,0x0000, +0xFBC0,0x8A5D,0x0000, 0x1606,0x0000,0x0000, 0xFBC0,0x8A5F,0x0000, +0xFBC0,0x8A60,0x0000, 0xFBC0,0x8A61,0x0000, 0xFBC0,0x8A62,0x0000, +0xFBC0,0x8A63,0x0000, 0xFBC0,0x8A64,0x0000, 0xFBC0,0x8A65,0x0000, +0x0E29,0x0000,0x0000, 0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, +0x0E2C,0x0000,0x0000, 0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, +0x0E2F,0x0000,0x0000, 0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, +0x0E32,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x15EB,0x0000,0x0000, 0x15E3,0x0000,0x0000, 0x15E2,0x0000,0x0000, +0xFBC0,0x8A75,0x0000, 0xFBC0,0x8A76,0x0000, 0xFBC0,0x8A77,0x0000, +0xFBC0,0x8A78,0x0000, 0xFBC0,0x8A79,0x0000, 0xFBC0,0x8A7A,0x0000, +0xFBC0,0x8A7B,0x0000, 0xFBC0,0x8A7C,0x0000, 0xFBC0,0x8A7D,0x0000, +0xFBC0,0x8A7E,0x0000, 0xFBC0,0x8A7F,0x0000, 0xFBC0,0x8A80,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0xFBC0,0x8A84,0x0000, 0x161A,0x0000,0x0000, 0x161B,0x0000,0x0000, +0x161C,0x0000,0x0000, 0x161D,0x0000,0x0000, 0x161E,0x0000,0x0000, +0x161F,0x0000,0x0000, 0x1620,0x0000,0x0000, 0x1622,0x0000,0x0000, +0x1624,0x0000,0x0000, 0xFBC0,0x8A8E,0x0000, 0x1625,0x0000,0x0000, +0x1626,0x0000,0x0000, 0x1627,0x0000,0x0000, 0xFBC0,0x8A92,0x0000, +0x1628,0x0000,0x0000, 0x1629,0x0000,0x0000, 0x162A,0x0000,0x0000, +0x162B,0x0000,0x0000, 0x162C,0x0000,0x0000, 0x162D,0x0000,0x0000, +0x162E,0x0000,0x0000, 0x162F,0x0000,0x0000, 0x1630,0x0000,0x0000, +0x1631,0x0000,0x0000, 0x1632,0x0000,0x0000, 0x1633,0x0000,0x0000, +0x1634,0x0000,0x0000, 0x1635,0x0000,0x0000, 0x1636,0x0000,0x0000, +0x1637,0x0000,0x0000, 0x1638,0x0000,0x0000, 0x1639,0x0000,0x0000, +0x163A,0x0000,0x0000, 0x163B,0x0000,0x0000, 0x163C,0x0000,0x0000, +0x163D,0x0000,0x0000, 0xFBC0,0x8AA9,0x0000, 0x163E,0x0000,0x0000, +0x163F,0x0000,0x0000, 0x1640,0x0000,0x0000, 0x1641,0x0000,0x0000, +0x1642,0x0000,0x0000, 0x1643,0x0000,0x0000, 0x1644,0x0000,0x0000, +0xFBC0,0x8AB1,0x0000, 0x1645,0x0000,0x0000, 0x1646,0x0000,0x0000, +0xFBC0,0x8AB4,0x0000, 0x1647,0x0000,0x0000, 0x1648,0x0000,0x0000, +0x1649,0x0000,0x0000, 0x164A,0x0000,0x0000, 0x164B,0x0000,0x0000, +0xFBC0,0x8ABA,0x0000, 0xFBC0,0x8ABB,0x0000, 0x0000,0x0000,0x0000, +0x164C,0x0000,0x0000, 0x164D,0x0000,0x0000, 0x164E,0x0000,0x0000, +0x164F,0x0000,0x0000, 0x1650,0x0000,0x0000, 0x1651,0x0000,0x0000, +0x1652,0x0000,0x0000, 0x1653,0x0000,0x0000, 0x1656,0x0000,0x0000, +0xFBC0,0x8AC6,0x0000, 0x1657,0x0000,0x0000, 0x1658,0x0000,0x0000, +0x1659,0x0000,0x0000, 0xFBC0,0x8ACA,0x0000, 0x165A,0x0000,0x0000, +0x165B,0x0000,0x0000, 0x165C,0x0000,0x0000, 0xFBC0,0x8ACE,0x0000, +0xFBC0,0x8ACF,0x0000, 0x1619,0x0000,0x0000, 0xFBC0,0x8AD1,0x0000, +0xFBC0,0x8AD2,0x0000, 0xFBC0,0x8AD3,0x0000, 0xFBC0,0x8AD4,0x0000, +0xFBC0,0x8AD5,0x0000, 0xFBC0,0x8AD6,0x0000, 0xFBC0,0x8AD7,0x0000, +0xFBC0,0x8AD8,0x0000, 0xFBC0,0x8AD9,0x0000, 0xFBC0,0x8ADA,0x0000, +0xFBC0,0x8ADB,0x0000, 0xFBC0,0x8ADC,0x0000, 0xFBC0,0x8ADD,0x0000, +0xFBC0,0x8ADE,0x0000, 0xFBC0,0x8ADF,0x0000, 0x1621,0x0000,0x0000, +0x1623,0x0000,0x0000, 0x1654,0x0000,0x0000, 0x1655,0x0000,0x0000, +0xFBC0,0x8AE4,0x0000, 0xFBC0,0x8AE5,0x0000, 0x0E29,0x0000,0x0000, +0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, 0x0E2C,0x0000,0x0000, +0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, 0x0E2F,0x0000,0x0000, +0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, 0x0E32,0x0000,0x0000, +0xFBC0,0x8AF0,0x0000, 0x0E14,0x0000,0x0000, 0xFBC0,0x8AF2,0x0000, +0xFBC0,0x8AF3,0x0000, 0xFBC0,0x8AF4,0x0000, 0xFBC0,0x8AF5,0x0000, +0xFBC0,0x8AF6,0x0000, 0xFBC0,0x8AF7,0x0000, 0xFBC0,0x8AF8,0x0000, +0xFBC0,0x8AF9,0x0000, 0xFBC0,0x8AFA,0x0000, 0xFBC0,0x8AFB,0x0000, +0xFBC0,0x8AFC,0x0000, 0xFBC0,0x8AFD,0x0000, 0xFBC0,0x8AFE,0x0000, +0xFBC0,0x8AFF,0x0000 }; + +uint16 page00Bdata[]= { /* 0B00 (3 weights per char) */ +0xFBC0,0x8B00,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0xFBC0,0x8B04,0x0000, 0x165D,0x0000,0x0000, +0x165E,0x0000,0x0000, 0x165F,0x0000,0x0000, 0x1660,0x0000,0x0000, +0x1661,0x0000,0x0000, 0x1662,0x0000,0x0000, 0x1663,0x0000,0x0000, +0x1665,0x0000,0x0000, 0xFBC0,0x8B0D,0x0000, 0xFBC0,0x8B0E,0x0000, +0x1667,0x0000,0x0000, 0x1668,0x0000,0x0000, 0xFBC0,0x8B11,0x0000, +0xFBC0,0x8B12,0x0000, 0x1669,0x0000,0x0000, 0x166A,0x0000,0x0000, +0x166B,0x0000,0x0000, 0x166C,0x0000,0x0000, 0x166D,0x0000,0x0000, +0x166E,0x0000,0x0000, 0x166F,0x0000,0x0000, 0x1670,0x0000,0x0000, +0x1671,0x0000,0x0000, 0x1672,0x0000,0x0000, 0x1673,0x0000,0x0000, +0x1674,0x0000,0x0000, 0x1675,0x0000,0x0000, 0x1676,0x0000,0x0000, +0x1677,0x0000,0x0000, 0x1678,0x0000,0x0000, 0x1679,0x0000,0x0000, +0x167A,0x0000,0x0000, 0x167B,0x0000,0x0000, 0x167C,0x0000,0x0000, +0x167D,0x0000,0x0000, 0x167E,0x0000,0x0000, 0xFBC0,0x8B29,0x0000, +0x167F,0x0000,0x0000, 0x1680,0x0000,0x0000, 0x1681,0x0000,0x0000, +0x1682,0x0000,0x0000, 0x1683,0x0000,0x0000, 0x1684,0x0000,0x0000, +0x1686,0x0000,0x0000, 0xFBC0,0x8B31,0x0000, 0x1687,0x0000,0x0000, +0x1688,0x0000,0x0000, 0xFBC0,0x8B34,0x0000, 0x1689,0x0000,0x0000, +0x168B,0x0000,0x0000, 0x168C,0x0000,0x0000, 0x168D,0x0000,0x0000, +0x168E,0x0000,0x0000, 0xFBC0,0x8B3A,0x0000, 0xFBC0,0x8B3B,0x0000, +0x0000,0x0000,0x0000, 0x168F,0x0000,0x0000, 0x1690,0x0000,0x0000, +0x1691,0x0000,0x0000, 0x1692,0x0000,0x0000, 0x1693,0x0000,0x0000, +0x1694,0x0000,0x0000, 0x1695,0x0000,0x0000, 0xFBC0,0x8B44,0x0000, +0xFBC0,0x8B45,0x0000, 0xFBC0,0x8B46,0x0000, 0x1696,0x0000,0x0000, +0x1697,0x0000,0x0000, 0xFBC0,0x8B49,0x0000, 0xFBC0,0x8B4A,0x0000, +0x1698,0x0000,0x0000, 0x1699,0x0000,0x0000, 0x169A,0x0000,0x0000, +0xFBC0,0x8B4E,0x0000, 0xFBC0,0x8B4F,0x0000, 0xFBC0,0x8B50,0x0000, +0xFBC0,0x8B51,0x0000, 0xFBC0,0x8B52,0x0000, 0xFBC0,0x8B53,0x0000, +0xFBC0,0x8B54,0x0000, 0xFBC0,0x8B55,0x0000, 0x169B,0x0000,0x0000, +0x169C,0x0000,0x0000, 0xFBC0,0x8B58,0x0000, 0xFBC0,0x8B59,0x0000, +0xFBC0,0x8B5A,0x0000, 0xFBC0,0x8B5B,0x0000, 0x1677,0x0000,0x0000, +0x1678,0x0000,0x0000, 0xFBC0,0x8B5E,0x0000, 0x1685,0x0000,0x0000, +0x1664,0x0000,0x0000, 0x1666,0x0000,0x0000, 0xFBC0,0x8B62,0x0000, +0xFBC0,0x8B63,0x0000, 0xFBC0,0x8B64,0x0000, 0xFBC0,0x8B65,0x0000, +0x0E29,0x0000,0x0000, 0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, +0x0E2C,0x0000,0x0000, 0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, +0x0E2F,0x0000,0x0000, 0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, +0x0E32,0x0000,0x0000, 0x0351,0x0000,0x0000, 0x168A,0x0000,0x0000, +0xFBC0,0x8B72,0x0000, 0xFBC0,0x8B73,0x0000, 0xFBC0,0x8B74,0x0000, +0xFBC0,0x8B75,0x0000, 0xFBC0,0x8B76,0x0000, 0xFBC0,0x8B77,0x0000, +0xFBC0,0x8B78,0x0000, 0xFBC0,0x8B79,0x0000, 0xFBC0,0x8B7A,0x0000, +0xFBC0,0x8B7B,0x0000, 0xFBC0,0x8B7C,0x0000, 0xFBC0,0x8B7D,0x0000, +0xFBC0,0x8B7E,0x0000, 0xFBC0,0x8B7F,0x0000, 0xFBC0,0x8B80,0x0000, +0xFBC0,0x8B81,0x0000, 0x0000,0x0000,0x0000, 0x169D,0x0000,0x0000, +0xFBC0,0x8B84,0x0000, 0x169E,0x0000,0x0000, 0x169F,0x0000,0x0000, +0x16A0,0x0000,0x0000, 0x16A1,0x0000,0x0000, 0x16A2,0x0000,0x0000, +0x16A3,0x0000,0x0000, 0xFBC0,0x8B8B,0x0000, 0xFBC0,0x8B8C,0x0000, +0xFBC0,0x8B8D,0x0000, 0x16A4,0x0000,0x0000, 0x16A5,0x0000,0x0000, +0x16A6,0x0000,0x0000, 0xFBC0,0x8B91,0x0000, 0x16A7,0x0000,0x0000, +0x16A8,0x0000,0x0000, 0x16A9,0x0000,0x0000, 0x16AA,0x0000,0x0000, +0xFBC0,0x8B96,0x0000, 0xFBC0,0x8B97,0x0000, 0xFBC0,0x8B98,0x0000, +0x16AB,0x0000,0x0000, 0x16AC,0x0000,0x0000, 0xFBC0,0x8B9B,0x0000, +0x16AD,0x0000,0x0000, 0xFBC0,0x8B9D,0x0000, 0x16AE,0x0000,0x0000, +0x16AF,0x0000,0x0000, 0xFBC0,0x8BA0,0x0000, 0xFBC0,0x8BA1,0x0000, +0xFBC0,0x8BA2,0x0000, 0x16B0,0x0000,0x0000, 0x16B1,0x0000,0x0000, +0xFBC0,0x8BA5,0x0000, 0xFBC0,0x8BA6,0x0000, 0xFBC0,0x8BA7,0x0000, +0x16B2,0x0000,0x0000, 0x16B3,0x0000,0x0000, 0x16B4,0x0000,0x0000, +0xFBC0,0x8BAB,0x0000, 0xFBC0,0x8BAC,0x0000, 0xFBC0,0x8BAD,0x0000, +0x16B5,0x0000,0x0000, 0x16B6,0x0000,0x0000, 0x16B7,0x0000,0x0000, +0x16B8,0x0000,0x0000, 0x16B9,0x0000,0x0000, 0x16BA,0x0000,0x0000, +0x16BB,0x0000,0x0000, 0x16BC,0x0000,0x0000, 0xFBC0,0x8BB6,0x0000, +0x16BD,0x0000,0x0000, 0x16BE,0x0000,0x0000, 0x16BF,0x0000,0x0000, +0xFBC0,0x8BBA,0x0000, 0xFBC0,0x8BBB,0x0000, 0xFBC0,0x8BBC,0x0000, +0xFBC0,0x8BBD,0x0000, 0x16C0,0x0000,0x0000, 0x16C1,0x0000,0x0000, +0x16C2,0x0000,0x0000, 0x16C3,0x0000,0x0000, 0x16C4,0x0000,0x0000, +0xFBC0,0x8BC3,0x0000, 0xFBC0,0x8BC4,0x0000, 0xFBC0,0x8BC5,0x0000, +0x16C5,0x0000,0x0000, 0x16C6,0x0000,0x0000, 0x16C7,0x0000,0x0000, +0xFBC0,0x8BC9,0x0000, 0x16C8,0x0000,0x0000, 0x16C9,0x0000,0x0000, +0x16CA,0x0000,0x0000, 0x16CB,0x0000,0x0000, 0xFBC0,0x8BCE,0x0000, +0xFBC0,0x8BCF,0x0000, 0xFBC0,0x8BD0,0x0000, 0xFBC0,0x8BD1,0x0000, +0xFBC0,0x8BD2,0x0000, 0xFBC0,0x8BD3,0x0000, 0xFBC0,0x8BD4,0x0000, +0xFBC0,0x8BD5,0x0000, 0xFBC0,0x8BD6,0x0000, 0x16CC,0x0000,0x0000, +0xFBC0,0x8BD8,0x0000, 0xFBC0,0x8BD9,0x0000, 0xFBC0,0x8BDA,0x0000, +0xFBC0,0x8BDB,0x0000, 0xFBC0,0x8BDC,0x0000, 0xFBC0,0x8BDD,0x0000, +0xFBC0,0x8BDE,0x0000, 0xFBC0,0x8BDF,0x0000, 0xFBC0,0x8BE0,0x0000, +0xFBC0,0x8BE1,0x0000, 0xFBC0,0x8BE2,0x0000, 0xFBC0,0x8BE3,0x0000, +0xFBC0,0x8BE4,0x0000, 0xFBC0,0x8BE5,0x0000, 0xFBC0,0x8BE6,0x0000, +0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, 0x0E2C,0x0000,0x0000, +0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, 0x0E2F,0x0000,0x0000, +0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, 0x0E32,0x0000,0x0000, +0x0DC9,0x0000,0x0000, 0x0DCA,0x0000,0x0000, 0x0DCB,0x0000,0x0000, +0x0352,0x0000,0x0000, 0x0353,0x0000,0x0000, 0x0354,0x0000,0x0000, +0x0355,0x0000,0x0000, 0x0356,0x0000,0x0000, 0x0357,0x0000,0x0000, +0x0E15,0x0000,0x0000, 0x0358,0x0000,0x0000, 0xFBC0,0x8BFB,0x0000, +0xFBC0,0x8BFC,0x0000, 0xFBC0,0x8BFD,0x0000, 0xFBC0,0x8BFE,0x0000, +0xFBC0,0x8BFF,0x0000 }; + +uint16 page00Cdata[]= { /* 0C00 (3 weights per char) */ +0xFBC0,0x8C00,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0xFBC0,0x8C04,0x0000, 0x16CD,0x0000,0x0000, +0x16CE,0x0000,0x0000, 0x16CF,0x0000,0x0000, 0x16D0,0x0000,0x0000, +0x16D1,0x0000,0x0000, 0x16D2,0x0000,0x0000, 0x16D3,0x0000,0x0000, +0x16D5,0x0000,0x0000, 0xFBC0,0x8C0D,0x0000, 0x16D7,0x0000,0x0000, +0x16D8,0x0000,0x0000, 0x16D9,0x0000,0x0000, 0xFBC0,0x8C11,0x0000, +0x16DA,0x0000,0x0000, 0x16DB,0x0000,0x0000, 0x16DC,0x0000,0x0000, +0x16DD,0x0000,0x0000, 0x16DE,0x0000,0x0000, 0x16DF,0x0000,0x0000, +0x16E0,0x0000,0x0000, 0x16E1,0x0000,0x0000, 0x16E2,0x0000,0x0000, +0x16E3,0x0000,0x0000, 0x16E4,0x0000,0x0000, 0x16E5,0x0000,0x0000, +0x16E6,0x0000,0x0000, 0x16E7,0x0000,0x0000, 0x16E8,0x0000,0x0000, +0x16E9,0x0000,0x0000, 0x16EA,0x0000,0x0000, 0x16EB,0x0000,0x0000, +0x16EC,0x0000,0x0000, 0x16ED,0x0000,0x0000, 0x16EE,0x0000,0x0000, +0x16EF,0x0000,0x0000, 0x16F0,0x0000,0x0000, 0xFBC0,0x8C29,0x0000, +0x16F1,0x0000,0x0000, 0x16F2,0x0000,0x0000, 0x16F3,0x0000,0x0000, +0x16F4,0x0000,0x0000, 0x16F5,0x0000,0x0000, 0x16F6,0x0000,0x0000, +0x16F7,0x0000,0x0000, 0x16F8,0x0000,0x0000, 0x16F9,0x0000,0x0000, +0x16FA,0x0000,0x0000, 0xFBC0,0x8C34,0x0000, 0x16FB,0x0000,0x0000, +0x16FC,0x0000,0x0000, 0x16FD,0x0000,0x0000, 0x16FE,0x0000,0x0000, +0x16FF,0x0000,0x0000, 0xFBC0,0x8C3A,0x0000, 0xFBC0,0x8C3B,0x0000, +0xFBC0,0x8C3C,0x0000, 0xFBC0,0x8C3D,0x0000, 0x1700,0x0000,0x0000, +0x1701,0x0000,0x0000, 0x1702,0x0000,0x0000, 0x1703,0x0000,0x0000, +0x1704,0x0000,0x0000, 0x1705,0x0000,0x0000, 0x1706,0x0000,0x0000, +0xFBC0,0x8C45,0x0000, 0x1707,0x0000,0x0000, 0x1708,0x0000,0x0000, +0x1709,0x0000,0x0000, 0xFBC0,0x8C49,0x0000, 0x170A,0x0000,0x0000, +0x170B,0x0000,0x0000, 0x170C,0x0000,0x0000, 0x170D,0x0000,0x0000, +0xFBC0,0x8C4E,0x0000, 0xFBC0,0x8C4F,0x0000, 0xFBC0,0x8C50,0x0000, +0xFBC0,0x8C51,0x0000, 0xFBC0,0x8C52,0x0000, 0xFBC0,0x8C53,0x0000, +0xFBC0,0x8C54,0x0000, 0x170E,0x0000,0x0000, 0x170F,0x0000,0x0000, +0xFBC0,0x8C57,0x0000, 0xFBC0,0x8C58,0x0000, 0xFBC0,0x8C59,0x0000, +0xFBC0,0x8C5A,0x0000, 0xFBC0,0x8C5B,0x0000, 0xFBC0,0x8C5C,0x0000, +0xFBC0,0x8C5D,0x0000, 0xFBC0,0x8C5E,0x0000, 0xFBC0,0x8C5F,0x0000, +0x16D4,0x0000,0x0000, 0x16D6,0x0000,0x0000, 0xFBC0,0x8C62,0x0000, +0xFBC0,0x8C63,0x0000, 0xFBC0,0x8C64,0x0000, 0xFBC0,0x8C65,0x0000, +0x0E29,0x0000,0x0000, 0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, +0x0E2C,0x0000,0x0000, 0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, +0x0E2F,0x0000,0x0000, 0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, +0x0E32,0x0000,0x0000, 0xFBC0,0x8C70,0x0000, 0xFBC0,0x8C71,0x0000, +0xFBC0,0x8C72,0x0000, 0xFBC0,0x8C73,0x0000, 0xFBC0,0x8C74,0x0000, +0xFBC0,0x8C75,0x0000, 0xFBC0,0x8C76,0x0000, 0xFBC0,0x8C77,0x0000, +0xFBC0,0x8C78,0x0000, 0xFBC0,0x8C79,0x0000, 0xFBC0,0x8C7A,0x0000, +0xFBC0,0x8C7B,0x0000, 0xFBC0,0x8C7C,0x0000, 0xFBC0,0x8C7D,0x0000, +0xFBC0,0x8C7E,0x0000, 0xFBC0,0x8C7F,0x0000, 0xFBC0,0x8C80,0x0000, +0xFBC0,0x8C81,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0xFBC0,0x8C84,0x0000, 0x1710,0x0000,0x0000, 0x1711,0x0000,0x0000, +0x1712,0x0000,0x0000, 0x1713,0x0000,0x0000, 0x1714,0x0000,0x0000, +0x1715,0x0000,0x0000, 0x1716,0x0000,0x0000, 0x1718,0x0000,0x0000, +0xFBC0,0x8C8D,0x0000, 0x171A,0x0000,0x0000, 0x171B,0x0000,0x0000, +0x171C,0x0000,0x0000, 0xFBC0,0x8C91,0x0000, 0x171D,0x0000,0x0000, +0x171E,0x0000,0x0000, 0x171F,0x0000,0x0000, 0x1720,0x0000,0x0000, +0x1721,0x0000,0x0000, 0x1722,0x0000,0x0000, 0x1723,0x0000,0x0000, +0x1724,0x0000,0x0000, 0x1725,0x0000,0x0000, 0x1726,0x0000,0x0000, +0x1727,0x0000,0x0000, 0x1728,0x0000,0x0000, 0x1729,0x0000,0x0000, +0x172A,0x0000,0x0000, 0x172B,0x0000,0x0000, 0x172C,0x0000,0x0000, +0x172D,0x0000,0x0000, 0x172E,0x0000,0x0000, 0x172F,0x0000,0x0000, +0x1730,0x0000,0x0000, 0x1731,0x0000,0x0000, 0x1732,0x0000,0x0000, +0x1733,0x0000,0x0000, 0xFBC0,0x8CA9,0x0000, 0x1734,0x0000,0x0000, +0x1735,0x0000,0x0000, 0x1736,0x0000,0x0000, 0x1737,0x0000,0x0000, +0x1738,0x0000,0x0000, 0x1739,0x0000,0x0000, 0x173A,0x0000,0x0000, +0x173B,0x0000,0x0000, 0x173C,0x0000,0x0000, 0x1743,0x0000,0x0000, +0xFBC0,0x8CB4,0x0000, 0x173D,0x0000,0x0000, 0x173E,0x0000,0x0000, +0x173F,0x0000,0x0000, 0x1740,0x0000,0x0000, 0x1741,0x0000,0x0000, +0xFBC0,0x8CBA,0x0000, 0xFBC0,0x8CBB,0x0000, 0x0000,0x0000,0x0000, +0x1742,0x0000,0x0000, 0x1745,0x0000,0x0000, 0x1746,0x0000,0x0000, +0x1747,0x0000,0x0000, 0x1748,0x0000,0x0000, 0x1749,0x0000,0x0000, +0x174A,0x0000,0x0000, 0x174B,0x0000,0x0000, 0xFBC0,0x8CC5,0x0000, +0x174C,0x0000,0x0000, 0x174D,0x0000,0x0000, 0x174E,0x0000,0x0000, +0xFBC0,0x8CC9,0x0000, 0x174F,0x0000,0x0000, 0x1750,0x0000,0x0000, +0x1751,0x0000,0x0000, 0x1752,0x0000,0x0000, 0xFBC0,0x8CCE,0x0000, +0xFBC0,0x8CCF,0x0000, 0xFBC0,0x8CD0,0x0000, 0xFBC0,0x8CD1,0x0000, +0xFBC0,0x8CD2,0x0000, 0xFBC0,0x8CD3,0x0000, 0xFBC0,0x8CD4,0x0000, +0x1753,0x0000,0x0000, 0x1754,0x0000,0x0000, 0xFBC0,0x8CD7,0x0000, +0xFBC0,0x8CD8,0x0000, 0xFBC0,0x8CD9,0x0000, 0xFBC0,0x8CDA,0x0000, +0xFBC0,0x8CDB,0x0000, 0xFBC0,0x8CDC,0x0000, 0xFBC0,0x8CDD,0x0000, +0x1744,0x0000,0x0000, 0xFBC0,0x8CDF,0x0000, 0x1717,0x0000,0x0000, +0x1719,0x0000,0x0000, 0xFBC0,0x8CE2,0x0000, 0xFBC0,0x8CE3,0x0000, +0xFBC0,0x8CE4,0x0000, 0xFBC0,0x8CE5,0x0000, 0x0E29,0x0000,0x0000, +0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, 0x0E2C,0x0000,0x0000, +0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, 0x0E2F,0x0000,0x0000, +0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, 0x0E32,0x0000,0x0000, +0xFBC0,0x8CF0,0x0000, 0xFBC0,0x8CF1,0x0000, 0xFBC0,0x8CF2,0x0000, +0xFBC0,0x8CF3,0x0000, 0xFBC0,0x8CF4,0x0000, 0xFBC0,0x8CF5,0x0000, +0xFBC0,0x8CF6,0x0000, 0xFBC0,0x8CF7,0x0000, 0xFBC0,0x8CF8,0x0000, +0xFBC0,0x8CF9,0x0000, 0xFBC0,0x8CFA,0x0000, 0xFBC0,0x8CFB,0x0000, +0xFBC0,0x8CFC,0x0000, 0xFBC0,0x8CFD,0x0000, 0xFBC0,0x8CFE,0x0000, +0xFBC0,0x8CFF,0x0000 }; + +uint16 page00Ddata[]= { /* 0D00 (3 weights per char) */ +0xFBC0,0x8D00,0x0000, 0xFBC0,0x8D01,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0xFBC0,0x8D04,0x0000, 0x1755,0x0000,0x0000, +0x1756,0x0000,0x0000, 0x1757,0x0000,0x0000, 0x1758,0x0000,0x0000, +0x1759,0x0000,0x0000, 0x175A,0x0000,0x0000, 0x175B,0x0000,0x0000, +0x175D,0x0000,0x0000, 0xFBC0,0x8D0D,0x0000, 0x175F,0x0000,0x0000, +0x1760,0x0000,0x0000, 0x1761,0x0000,0x0000, 0xFBC0,0x8D11,0x0000, +0x1762,0x0000,0x0000, 0x1763,0x0000,0x0000, 0x1764,0x0000,0x0000, +0x1765,0x0000,0x0000, 0x1766,0x0000,0x0000, 0x1767,0x0000,0x0000, +0x1768,0x0000,0x0000, 0x1769,0x0000,0x0000, 0x176A,0x0000,0x0000, +0x176B,0x0000,0x0000, 0x176C,0x0000,0x0000, 0x176D,0x0000,0x0000, +0x176E,0x0000,0x0000, 0x176F,0x0000,0x0000, 0x1770,0x0000,0x0000, +0x1771,0x0000,0x0000, 0x1772,0x0000,0x0000, 0x1773,0x0000,0x0000, +0x1774,0x0000,0x0000, 0x1775,0x0000,0x0000, 0x1776,0x0000,0x0000, +0x1777,0x0000,0x0000, 0x1778,0x0000,0x0000, 0xFBC0,0x8D29,0x0000, +0x1779,0x0000,0x0000, 0x177A,0x0000,0x0000, 0x177B,0x0000,0x0000, +0x177C,0x0000,0x0000, 0x177D,0x0000,0x0000, 0x177E,0x0000,0x0000, +0x177F,0x0000,0x0000, 0x1780,0x0000,0x0000, 0x1781,0x0000,0x0000, +0x1782,0x0000,0x0000, 0x1783,0x0000,0x0000, 0x1784,0x0000,0x0000, +0x1785,0x0000,0x0000, 0x1786,0x0000,0x0000, 0x1787,0x0000,0x0000, +0x1788,0x0000,0x0000, 0xFBC0,0x8D3A,0x0000, 0xFBC0,0x8D3B,0x0000, +0xFBC0,0x8D3C,0x0000, 0xFBC0,0x8D3D,0x0000, 0x1789,0x0000,0x0000, +0x178A,0x0000,0x0000, 0x178B,0x0000,0x0000, 0x178C,0x0000,0x0000, +0x178D,0x0000,0x0000, 0x178E,0x0000,0x0000, 0xFBC0,0x8D44,0x0000, +0xFBC0,0x8D45,0x0000, 0x178F,0x0000,0x0000, 0x1790,0x0000,0x0000, +0x1791,0x0000,0x0000, 0xFBC0,0x8D49,0x0000, 0x1792,0x0000,0x0000, +0x1793,0x0000,0x0000, 0x1794,0x0000,0x0000, 0x1795,0x0000,0x0000, +0xFBC0,0x8D4E,0x0000, 0xFBC0,0x8D4F,0x0000, 0xFBC0,0x8D50,0x0000, +0xFBC0,0x8D51,0x0000, 0xFBC0,0x8D52,0x0000, 0xFBC0,0x8D53,0x0000, +0xFBC0,0x8D54,0x0000, 0xFBC0,0x8D55,0x0000, 0xFBC0,0x8D56,0x0000, +0x1796,0x0000,0x0000, 0xFBC0,0x8D58,0x0000, 0xFBC0,0x8D59,0x0000, +0xFBC0,0x8D5A,0x0000, 0xFBC0,0x8D5B,0x0000, 0xFBC0,0x8D5C,0x0000, +0xFBC0,0x8D5D,0x0000, 0xFBC0,0x8D5E,0x0000, 0xFBC0,0x8D5F,0x0000, +0x175C,0x0000,0x0000, 0x175E,0x0000,0x0000, 0xFBC0,0x8D62,0x0000, +0xFBC0,0x8D63,0x0000, 0xFBC0,0x8D64,0x0000, 0xFBC0,0x8D65,0x0000, +0x0E29,0x0000,0x0000, 0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, +0x0E2C,0x0000,0x0000, 0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, +0x0E2F,0x0000,0x0000, 0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, +0x0E32,0x0000,0x0000, 0xFBC0,0x8D70,0x0000, 0xFBC0,0x8D71,0x0000, +0xFBC0,0x8D72,0x0000, 0xFBC0,0x8D73,0x0000, 0xFBC0,0x8D74,0x0000, +0xFBC0,0x8D75,0x0000, 0xFBC0,0x8D76,0x0000, 0xFBC0,0x8D77,0x0000, +0xFBC0,0x8D78,0x0000, 0xFBC0,0x8D79,0x0000, 0xFBC0,0x8D7A,0x0000, +0xFBC0,0x8D7B,0x0000, 0xFBC0,0x8D7C,0x0000, 0xFBC0,0x8D7D,0x0000, +0xFBC0,0x8D7E,0x0000, 0xFBC0,0x8D7F,0x0000, 0xFBC0,0x8D80,0x0000, +0xFBC0,0x8D81,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0xFBC0,0x8D84,0x0000, 0x1797,0x0000,0x0000, 0x1798,0x0000,0x0000, +0x1799,0x0000,0x0000, 0x179A,0x0000,0x0000, 0x179B,0x0000,0x0000, +0x179C,0x0000,0x0000, 0x179D,0x0000,0x0000, 0x179E,0x0000,0x0000, +0x179F,0x0000,0x0000, 0x17A0,0x0000,0x0000, 0x17A1,0x0000,0x0000, +0x17A2,0x0000,0x0000, 0x17A3,0x0000,0x0000, 0x17A4,0x0000,0x0000, +0x17A5,0x0000,0x0000, 0x17A6,0x0000,0x0000, 0x17A7,0x0000,0x0000, +0x17A8,0x0000,0x0000, 0xFBC0,0x8D97,0x0000, 0xFBC0,0x8D98,0x0000, +0xFBC0,0x8D99,0x0000, 0x17A9,0x0000,0x0000, 0x17AA,0x0000,0x0000, +0x17AB,0x0000,0x0000, 0x17AC,0x0000,0x0000, 0x17AD,0x0000,0x0000, +0x17AE,0x0000,0x0000, 0x17AF,0x0000,0x0000, 0x17B0,0x0000,0x0000, +0x17B1,0x0000,0x0000, 0x17B2,0x0000,0x0000, 0x17B3,0x0000,0x0000, +0x17B4,0x0000,0x0000, 0x17B5,0x0000,0x0000, 0x17B6,0x0000,0x0000, +0x17B7,0x0000,0x0000, 0x17B8,0x0000,0x0000, 0x17B9,0x0000,0x0000, +0x17BA,0x0000,0x0000, 0x17BB,0x0000,0x0000, 0x17BC,0x0000,0x0000, +0x17BD,0x0000,0x0000, 0x17BE,0x0000,0x0000, 0x17BF,0x0000,0x0000, +0x17C0,0x0000,0x0000, 0xFBC0,0x8DB2,0x0000, 0x17C1,0x0000,0x0000, +0x17C2,0x0000,0x0000, 0x17C3,0x0000,0x0000, 0x17C4,0x0000,0x0000, +0x17C5,0x0000,0x0000, 0x17C6,0x0000,0x0000, 0x17C7,0x0000,0x0000, +0x17C8,0x0000,0x0000, 0x17C9,0x0000,0x0000, 0xFBC0,0x8DBC,0x0000, +0x17CA,0x0000,0x0000, 0xFBC0,0x8DBE,0x0000, 0xFBC0,0x8DBF,0x0000, +0x17CB,0x0000,0x0000, 0x17CC,0x0000,0x0000, 0x17CD,0x0000,0x0000, +0x17CE,0x0000,0x0000, 0x17CF,0x0000,0x0000, 0x17D0,0x0000,0x0000, +0x17D1,0x0000,0x0000, 0xFBC0,0x8DC7,0x0000, 0xFBC0,0x8DC8,0x0000, +0xFBC0,0x8DC9,0x0000, 0x17D2,0x0000,0x0000, 0xFBC0,0x8DCB,0x0000, +0xFBC0,0x8DCC,0x0000, 0xFBC0,0x8DCD,0x0000, 0xFBC0,0x8DCE,0x0000, +0x17D3,0x0000,0x0000, 0x17D4,0x0000,0x0000, 0x17D5,0x0000,0x0000, +0x17D6,0x0000,0x0000, 0x17D7,0x0000,0x0000, 0x17D8,0x0000,0x0000, +0xFBC0,0x8DD5,0x0000, 0x17D9,0x0000,0x0000, 0xFBC0,0x8DD7,0x0000, +0x17DA,0x0000,0x0000, 0x17DB,0x0000,0x0000, 0x17DC,0x0000,0x0000, +0x17DD,0x0000,0x0000, 0x17DE,0x0000,0x0000, 0x17DF,0x0000,0x0000, +0x17E0,0x0000,0x0000, 0x17E1,0x0000,0x0000, 0xFBC0,0x8DE0,0x0000, +0xFBC0,0x8DE1,0x0000, 0xFBC0,0x8DE2,0x0000, 0xFBC0,0x8DE3,0x0000, +0xFBC0,0x8DE4,0x0000, 0xFBC0,0x8DE5,0x0000, 0xFBC0,0x8DE6,0x0000, +0xFBC0,0x8DE7,0x0000, 0xFBC0,0x8DE8,0x0000, 0xFBC0,0x8DE9,0x0000, +0xFBC0,0x8DEA,0x0000, 0xFBC0,0x8DEB,0x0000, 0xFBC0,0x8DEC,0x0000, +0xFBC0,0x8DED,0x0000, 0xFBC0,0x8DEE,0x0000, 0xFBC0,0x8DEF,0x0000, +0xFBC0,0x8DF0,0x0000, 0xFBC0,0x8DF1,0x0000, 0x17E2,0x0000,0x0000, +0x17E3,0x0000,0x0000, 0x02FB,0x0000,0x0000, 0xFBC0,0x8DF5,0x0000, +0xFBC0,0x8DF6,0x0000, 0xFBC0,0x8DF7,0x0000, 0xFBC0,0x8DF8,0x0000, +0xFBC0,0x8DF9,0x0000, 0xFBC0,0x8DFA,0x0000, 0xFBC0,0x8DFB,0x0000, +0xFBC0,0x8DFC,0x0000, 0xFBC0,0x8DFD,0x0000, 0xFBC0,0x8DFE,0x0000, +0xFBC0,0x8DFF,0x0000 }; + +uint16 page00Edata[]= { /* 0E00 (3 weights per char) */ +0xFBC0,0x8E00,0x0000, 0x17E4,0x0000,0x0000, 0x17E5,0x0000,0x0000, +0x17E6,0x0000,0x0000, 0x17E7,0x0000,0x0000, 0x17E8,0x0000,0x0000, +0x17E9,0x0000,0x0000, 0x17EA,0x0000,0x0000, 0x17EB,0x0000,0x0000, +0x17EC,0x0000,0x0000, 0x17ED,0x0000,0x0000, 0x17EE,0x0000,0x0000, +0x17EF,0x0000,0x0000, 0x17F0,0x0000,0x0000, 0x17F1,0x0000,0x0000, +0x17F2,0x0000,0x0000, 0x17F3,0x0000,0x0000, 0x17F4,0x0000,0x0000, +0x17F5,0x0000,0x0000, 0x17F6,0x0000,0x0000, 0x17F7,0x0000,0x0000, +0x17F8,0x0000,0x0000, 0x17F9,0x0000,0x0000, 0x17FA,0x0000,0x0000, +0x17FB,0x0000,0x0000, 0x17FC,0x0000,0x0000, 0x17FD,0x0000,0x0000, +0x17FE,0x0000,0x0000, 0x17FF,0x0000,0x0000, 0x1800,0x0000,0x0000, +0x1801,0x0000,0x0000, 0x1802,0x0000,0x0000, 0x1803,0x0000,0x0000, +0x1804,0x0000,0x0000, 0x1805,0x0000,0x0000, 0x1806,0x0000,0x0000, +0x1807,0x0000,0x0000, 0x1808,0x0000,0x0000, 0x1809,0x0000,0x0000, +0x180A,0x0000,0x0000, 0x180B,0x0000,0x0000, 0x180C,0x0000,0x0000, +0x180D,0x0000,0x0000, 0x180E,0x0000,0x0000, 0x180F,0x0000,0x0000, +0x1810,0x0000,0x0000, 0x1811,0x0000,0x0000, 0x1812,0x0000,0x0000, +0x1813,0x0000,0x0000, 0x1814,0x0000,0x0000, 0x1815,0x0000,0x0000, +0x1816,0x0000,0x0000, 0x1817,0x0000,0x0000, 0x1818,0x0000,0x0000, +0x1819,0x0000,0x0000, 0x181A,0x0000,0x0000, 0x181B,0x0000,0x0000, +0x181C,0x0000,0x0000, 0x181D,0x0000,0x0000, 0xFBC0,0x8E3B,0x0000, +0xFBC0,0x8E3C,0x0000, 0xFBC0,0x8E3D,0x0000, 0xFBC0,0x8E3E,0x0000, +0x0E16,0x0000,0x0000, 0x181E,0x0000,0x0000, 0x181F,0x0000,0x0000, +0x1820,0x0000,0x0000, 0x1821,0x0000,0x0000, 0x1822,0x0000,0x0000, +0x1823,0x0000,0x0000, 0x0E03,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x1824,0x0000,0x0000, 0x1825,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0359,0x0000,0x0000, 0x0E29,0x0000,0x0000, +0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, 0x0E2C,0x0000,0x0000, +0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, 0x0E2F,0x0000,0x0000, +0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, 0x0E32,0x0000,0x0000, +0x02FC,0x0000,0x0000, 0x02FD,0x0000,0x0000, 0xFBC0,0x8E5C,0x0000, +0xFBC0,0x8E5D,0x0000, 0xFBC0,0x8E5E,0x0000, 0xFBC0,0x8E5F,0x0000, +0xFBC0,0x8E60,0x0000, 0xFBC0,0x8E61,0x0000, 0xFBC0,0x8E62,0x0000, +0xFBC0,0x8E63,0x0000, 0xFBC0,0x8E64,0x0000, 0xFBC0,0x8E65,0x0000, +0xFBC0,0x8E66,0x0000, 0xFBC0,0x8E67,0x0000, 0xFBC0,0x8E68,0x0000, +0xFBC0,0x8E69,0x0000, 0xFBC0,0x8E6A,0x0000, 0xFBC0,0x8E6B,0x0000, +0xFBC0,0x8E6C,0x0000, 0xFBC0,0x8E6D,0x0000, 0xFBC0,0x8E6E,0x0000, +0xFBC0,0x8E6F,0x0000, 0xFBC0,0x8E70,0x0000, 0xFBC0,0x8E71,0x0000, +0xFBC0,0x8E72,0x0000, 0xFBC0,0x8E73,0x0000, 0xFBC0,0x8E74,0x0000, +0xFBC0,0x8E75,0x0000, 0xFBC0,0x8E76,0x0000, 0xFBC0,0x8E77,0x0000, +0xFBC0,0x8E78,0x0000, 0xFBC0,0x8E79,0x0000, 0xFBC0,0x8E7A,0x0000, +0xFBC0,0x8E7B,0x0000, 0xFBC0,0x8E7C,0x0000, 0xFBC0,0x8E7D,0x0000, +0xFBC0,0x8E7E,0x0000, 0xFBC0,0x8E7F,0x0000, 0xFBC0,0x8E80,0x0000, +0x1826,0x0000,0x0000, 0x1827,0x0000,0x0000, 0xFBC0,0x8E83,0x0000, +0x1828,0x0000,0x0000, 0xFBC0,0x8E85,0x0000, 0xFBC0,0x8E86,0x0000, +0x1829,0x0000,0x0000, 0x182A,0x0000,0x0000, 0xFBC0,0x8E89,0x0000, +0x182B,0x0000,0x0000, 0xFBC0,0x8E8B,0x0000, 0xFBC0,0x8E8C,0x0000, +0x182C,0x0000,0x0000, 0xFBC0,0x8E8E,0x0000, 0xFBC0,0x8E8F,0x0000, +0xFBC0,0x8E90,0x0000, 0xFBC0,0x8E91,0x0000, 0xFBC0,0x8E92,0x0000, +0xFBC0,0x8E93,0x0000, 0x182D,0x0000,0x0000, 0x182E,0x0000,0x0000, +0x182F,0x0000,0x0000, 0x1830,0x0000,0x0000, 0xFBC0,0x8E98,0x0000, +0x1831,0x0000,0x0000, 0x1832,0x0000,0x0000, 0x1833,0x0000,0x0000, +0x1834,0x0000,0x0000, 0x1835,0x0000,0x0000, 0x1836,0x0000,0x0000, +0x1837,0x0000,0x0000, 0xFBC0,0x8EA0,0x0000, 0x1838,0x0000,0x0000, +0x1839,0x0000,0x0000, 0x183A,0x0000,0x0000, 0xFBC0,0x8EA4,0x0000, +0x183B,0x0000,0x0000, 0xFBC0,0x8EA6,0x0000, 0x183C,0x0000,0x0000, +0xFBC0,0x8EA8,0x0000, 0xFBC0,0x8EA9,0x0000, 0x183D,0x0000,0x0000, +0x183E,0x0000,0x0000, 0xFBC0,0x8EAC,0x0000, 0x183F,0x0000,0x0000, +0x1840,0x0000,0x0000, 0x1841,0x0000,0x0000, 0x1842,0x0000,0x0000, +0x1843,0x0000,0x0000, 0x1844,0x0000,0x0000, 0x1845,0x0000,0x0000, +0x1846,0x0000,0x0000, 0x1847,0x0000,0x0000, 0x1848,0x0000,0x0000, +0x1849,0x0000,0x0000, 0x184A,0x0000,0x0000, 0x184B,0x0000,0x0000, +0xFBC0,0x8EBA,0x0000, 0x184C,0x0000,0x0000, 0x184D,0x0000,0x0000, +0x184E,0x0000,0x0000, 0xFBC0,0x8EBE,0x0000, 0xFBC0,0x8EBF,0x0000, +0x184F,0x0000,0x0000, 0x1850,0x0000,0x0000, 0x1851,0x0000,0x0000, +0x1852,0x0000,0x0000, 0x1853,0x0000,0x0000, 0xFBC0,0x8EC5,0x0000, +0x0E04,0x0000,0x0000, 0xFBC0,0x8EC7,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x1854,0x0000,0x0000, 0x1855,0x0000,0x0000, 0xFBC0,0x8ECE,0x0000, +0xFBC0,0x8ECF,0x0000, 0x0E29,0x0000,0x0000, 0x0E2A,0x0000,0x0000, +0x0E2B,0x0000,0x0000, 0x0E2C,0x0000,0x0000, 0x0E2D,0x0000,0x0000, +0x0E2E,0x0000,0x0000, 0x0E2F,0x0000,0x0000, 0x0E30,0x0000,0x0000, +0x0E31,0x0000,0x0000, 0x0E32,0x0000,0x0000, 0xFBC0,0x8EDA,0x0000, +0xFBC0,0x8EDB,0x0000, 0x183E,0x1831,0x0000, 0x183E,0x1838,0x0000, +0xFBC0,0x8EDE,0x0000, 0xFBC0,0x8EDF,0x0000, 0xFBC0,0x8EE0,0x0000, +0xFBC0,0x8EE1,0x0000, 0xFBC0,0x8EE2,0x0000, 0xFBC0,0x8EE3,0x0000, +0xFBC0,0x8EE4,0x0000, 0xFBC0,0x8EE5,0x0000, 0xFBC0,0x8EE6,0x0000, +0xFBC0,0x8EE7,0x0000, 0xFBC0,0x8EE8,0x0000, 0xFBC0,0x8EE9,0x0000, +0xFBC0,0x8EEA,0x0000, 0xFBC0,0x8EEB,0x0000, 0xFBC0,0x8EEC,0x0000, +0xFBC0,0x8EED,0x0000, 0xFBC0,0x8EEE,0x0000, 0xFBC0,0x8EEF,0x0000, +0xFBC0,0x8EF0,0x0000, 0xFBC0,0x8EF1,0x0000, 0xFBC0,0x8EF2,0x0000, +0xFBC0,0x8EF3,0x0000, 0xFBC0,0x8EF4,0x0000, 0xFBC0,0x8EF5,0x0000, +0xFBC0,0x8EF6,0x0000, 0xFBC0,0x8EF7,0x0000, 0xFBC0,0x8EF8,0x0000, +0xFBC0,0x8EF9,0x0000, 0xFBC0,0x8EFA,0x0000, 0xFBC0,0x8EFB,0x0000, +0xFBC0,0x8EFC,0x0000, 0xFBC0,0x8EFD,0x0000, 0xFBC0,0x8EFE,0x0000, +0xFBC0,0x8EFF,0x0000 }; + +uint16 page00Fdata[]= { /* 0F00 (3 weights per char) */ +0x189A,0x18AD,0x0000, 0x035A,0x0000,0x0000, 0x035B,0x0000,0x0000, +0x035C,0x0000,0x0000, 0x02FE,0x0000,0x0000, 0x02FF,0x0000,0x0000, +0x0300,0x0000,0x0000, 0x0301,0x0000,0x0000, 0x0302,0x0000,0x0000, +0x0303,0x0000,0x0000, 0x0304,0x0000,0x0000, 0x0305,0x0000,0x0000, +0x0305,0x0000,0x0000, 0x0306,0x0000,0x0000, 0x0307,0x0000,0x0000, +0x0308,0x0000,0x0000, 0x0309,0x0000,0x0000, 0x030A,0x0000,0x0000, +0x030B,0x0000,0x0000, 0x035D,0x0000,0x0000, 0x024C,0x0000,0x0000, +0x035E,0x0000,0x0000, 0x035F,0x0000,0x0000, 0x0360,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0361,0x0000,0x0000, +0x0362,0x0000,0x0000, 0x0363,0x0000,0x0000, 0x0364,0x0000,0x0000, +0x0365,0x0000,0x0000, 0x0366,0x0000,0x0000, 0x0E29,0x0000,0x0000, +0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, 0x0E2C,0x0000,0x0000, +0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, 0x0E2F,0x0000,0x0000, +0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, 0x0E32,0x0000,0x0000, +0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, 0x0E2C,0x0000,0x0000, +0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, 0x0E2F,0x0000,0x0000, +0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, 0x0E32,0x0000,0x0000, +0x0E29,0x0000,0x0000, 0x0367,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0368,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0369,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x028E,0x0000,0x0000, 0x028F,0x0000,0x0000, +0x0290,0x0000,0x0000, 0x0291,0x0000,0x0000, 0x036A,0x0000,0x0000, +0x036B,0x0000,0x0000, 0x1856,0x0000,0x0000, 0x1858,0x0000,0x0000, +0x185A,0x0000,0x0000, 0x185A,0x1899,0x0000, 0x185C,0x0000,0x0000, +0x185E,0x0000,0x0000, 0x1860,0x0000,0x0000, 0x1862,0x0000,0x0000, +0xFBC0,0x8F48,0x0000, 0x1864,0x0000,0x0000, 0x1866,0x0000,0x0000, +0x1868,0x0000,0x0000, 0x186A,0x0000,0x0000, 0x186A,0x1899,0x0000, +0x186C,0x0000,0x0000, 0x186E,0x0000,0x0000, 0x1870,0x0000,0x0000, +0x1872,0x0000,0x0000, 0x1872,0x1899,0x0000, 0x1874,0x0000,0x0000, +0x1876,0x0000,0x0000, 0x1878,0x0000,0x0000, 0x187A,0x0000,0x0000, +0x187A,0x1899,0x0000, 0x187C,0x0000,0x0000, 0x187E,0x0000,0x0000, +0x1880,0x0000,0x0000, 0x1882,0x0000,0x0000, 0x1882,0x1899,0x0000, +0x1884,0x0000,0x0000, 0x1886,0x0000,0x0000, 0x1888,0x0000,0x0000, +0x188A,0x0000,0x0000, 0x188C,0x0000,0x0000, 0x188E,0x0000,0x0000, +0x1890,0x0000,0x0000, 0x1892,0x0000,0x0000, 0x1894,0x0000,0x0000, +0x1896,0x0000,0x0000, 0x1898,0x0000,0x0000, 0x189A,0x0000,0x0000, +0x1856,0x1895,0x0000, 0x188E,0x0000,0x0000, 0xFBC0,0x8F6B,0x0000, +0xFBC0,0x8F6C,0x0000, 0xFBC0,0x8F6D,0x0000, 0xFBC0,0x8F6E,0x0000, +0xFBC0,0x8F6F,0x0000, 0xFBC0,0x8F70,0x0000, 0x18A0,0x0000,0x0000, +0x18A1,0x0000,0x0000, 0x18A2,0x0000,0x0000, 0x18A5,0x0000,0x0000, +0x18A6,0x0000,0x0000, 0x18A7,0x0000,0x0000, 0x18A8,0x0000,0x0000, +0x18A9,0x0000,0x0000, 0x18AA,0x0000,0x0000, 0x18AB,0x0000,0x0000, +0x18AC,0x0000,0x0000, 0x18AD,0x0000,0x0000, 0x18AE,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x18A3,0x0000,0x0000, +0x18A4,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x18AF,0x0000,0x0000, 0x030C,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x189C,0x0000,0x0000, 0x189D,0x0000,0x0000, +0x189E,0x0000,0x0000, 0x189F,0x0000,0x0000, 0xFBC0,0x8F8C,0x0000, +0xFBC0,0x8F8D,0x0000, 0xFBC0,0x8F8E,0x0000, 0xFBC0,0x8F8F,0x0000, +0x1857,0x0000,0x0000, 0x1859,0x0000,0x0000, 0x185B,0x0000,0x0000, +0x185B,0x1899,0x0000, 0x185D,0x0000,0x0000, 0x185F,0x0000,0x0000, +0x1861,0x0000,0x0000, 0x1863,0x0000,0x0000, 0xFBC0,0x8F98,0x0000, +0x1865,0x0000,0x0000, 0x1867,0x0000,0x0000, 0x1869,0x0000,0x0000, +0x186B,0x0000,0x0000, 0x186B,0x1899,0x0000, 0x186D,0x0000,0x0000, +0x186F,0x0000,0x0000, 0x1871,0x0000,0x0000, 0x1873,0x0000,0x0000, +0x1873,0x1899,0x0000, 0x1875,0x0000,0x0000, 0x1877,0x0000,0x0000, +0x1879,0x0000,0x0000, 0x187B,0x0000,0x0000, 0x187B,0x1899,0x0000, +0x187D,0x0000,0x0000, 0x187F,0x0000,0x0000, 0x1881,0x0000,0x0000, +0x1883,0x0000,0x0000, 0x1883,0x1899,0x0000, 0x1885,0x0000,0x0000, +0x1887,0x0000,0x0000, 0x1889,0x0000,0x0000, 0x188B,0x0000,0x0000, +0x188D,0x0000,0x0000, 0x188F,0x0000,0x0000, 0x1891,0x0000,0x0000, +0x1893,0x0000,0x0000, 0x1895,0x0000,0x0000, 0x1897,0x0000,0x0000, +0x1899,0x0000,0x0000, 0x189B,0x0000,0x0000, 0x1857,0x1895,0x0000, +0x1885,0x0000,0x0000, 0x188D,0x0000,0x0000, 0x188F,0x0000,0x0000, +0xFBC0,0x8FBD,0x0000, 0x036C,0x0000,0x0000, 0x036D,0x0000,0x0000, +0x036E,0x0000,0x0000, 0x036F,0x0000,0x0000, 0x0370,0x0000,0x0000, +0x0371,0x0000,0x0000, 0x0372,0x0000,0x0000, 0x0373,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0374,0x0000,0x0000, 0x0375,0x0000,0x0000, +0x0376,0x0000,0x0000, 0x0377,0x0000,0x0000, 0x0378,0x0000,0x0000, +0x0379,0x0000,0x0000, 0xFBC0,0x8FCD,0x0000, 0xFBC0,0x8FCE,0x0000, +0x037A,0x0000,0x0000, 0xFBC0,0x8FD0,0x0000, 0xFBC0,0x8FD1,0x0000, +0xFBC0,0x8FD2,0x0000, 0xFBC0,0x8FD3,0x0000, 0xFBC0,0x8FD4,0x0000, +0xFBC0,0x8FD5,0x0000, 0xFBC0,0x8FD6,0x0000, 0xFBC0,0x8FD7,0x0000, +0xFBC0,0x8FD8,0x0000, 0xFBC0,0x8FD9,0x0000, 0xFBC0,0x8FDA,0x0000, +0xFBC0,0x8FDB,0x0000, 0xFBC0,0x8FDC,0x0000, 0xFBC0,0x8FDD,0x0000, +0xFBC0,0x8FDE,0x0000, 0xFBC0,0x8FDF,0x0000, 0xFBC0,0x8FE0,0x0000, +0xFBC0,0x8FE1,0x0000, 0xFBC0,0x8FE2,0x0000, 0xFBC0,0x8FE3,0x0000, +0xFBC0,0x8FE4,0x0000, 0xFBC0,0x8FE5,0x0000, 0xFBC0,0x8FE6,0x0000, +0xFBC0,0x8FE7,0x0000, 0xFBC0,0x8FE8,0x0000, 0xFBC0,0x8FE9,0x0000, +0xFBC0,0x8FEA,0x0000, 0xFBC0,0x8FEB,0x0000, 0xFBC0,0x8FEC,0x0000, +0xFBC0,0x8FED,0x0000, 0xFBC0,0x8FEE,0x0000, 0xFBC0,0x8FEF,0x0000, +0xFBC0,0x8FF0,0x0000, 0xFBC0,0x8FF1,0x0000, 0xFBC0,0x8FF2,0x0000, +0xFBC0,0x8FF3,0x0000, 0xFBC0,0x8FF4,0x0000, 0xFBC0,0x8FF5,0x0000, +0xFBC0,0x8FF6,0x0000, 0xFBC0,0x8FF7,0x0000, 0xFBC0,0x8FF8,0x0000, +0xFBC0,0x8FF9,0x0000, 0xFBC0,0x8FFA,0x0000, 0xFBC0,0x8FFB,0x0000, +0xFBC0,0x8FFC,0x0000, 0xFBC0,0x8FFD,0x0000, 0xFBC0,0x8FFE,0x0000, +0xFBC0,0x8FFF,0x0000 }; + +uint16 page010data[]= { /* 1000 (3 weights per char) */ +0x1931,0x0000,0x0000, 0x1932,0x0000,0x0000, 0x1933,0x0000,0x0000, +0x1934,0x0000,0x0000, 0x1935,0x0000,0x0000, 0x1936,0x0000,0x0000, +0x1937,0x0000,0x0000, 0x1938,0x0000,0x0000, 0x1939,0x0000,0x0000, +0x193A,0x0000,0x0000, 0x193B,0x0000,0x0000, 0x193C,0x0000,0x0000, +0x193D,0x0000,0x0000, 0x193E,0x0000,0x0000, 0x193F,0x0000,0x0000, +0x1940,0x0000,0x0000, 0x1941,0x0000,0x0000, 0x1942,0x0000,0x0000, +0x1943,0x0000,0x0000, 0x1944,0x0000,0x0000, 0x1945,0x0000,0x0000, +0x1946,0x0000,0x0000, 0x1947,0x0000,0x0000, 0x1948,0x0000,0x0000, +0x1949,0x0000,0x0000, 0x194A,0x0000,0x0000, 0x194B,0x0000,0x0000, +0x194C,0x0000,0x0000, 0x194D,0x0000,0x0000, 0x194E,0x0000,0x0000, +0x1951,0x0000,0x0000, 0x1952,0x0000,0x0000, 0x1953,0x0000,0x0000, +0x1954,0x0000,0x0000, 0xFBC0,0x9022,0x0000, 0x1955,0x0000,0x0000, +0x1956,0x0000,0x0000, 0x1957,0x0000,0x0000, 0x1958,0x0000,0x0000, +0x1959,0x0000,0x0000, 0xFBC0,0x9028,0x0000, 0x195A,0x0000,0x0000, +0x195B,0x0000,0x0000, 0xFBC0,0x902B,0x0000, 0x1960,0x0000,0x0000, +0x1961,0x0000,0x0000, 0x1962,0x0000,0x0000, 0x1963,0x0000,0x0000, +0x1964,0x0000,0x0000, 0x1965,0x0000,0x0000, 0x1966,0x0000,0x0000, +0xFBC0,0x9033,0x0000, 0xFBC0,0x9034,0x0000, 0xFBC0,0x9035,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x196B,0x0000,0x0000, 0xFBC0,0x903A,0x0000, 0xFBC0,0x903B,0x0000, +0xFBC0,0x903C,0x0000, 0xFBC0,0x903D,0x0000, 0xFBC0,0x903E,0x0000, +0xFBC0,0x903F,0x0000, 0x0E29,0x0000,0x0000, 0x0E2A,0x0000,0x0000, +0x0E2B,0x0000,0x0000, 0x0E2C,0x0000,0x0000, 0x0E2D,0x0000,0x0000, +0x0E2E,0x0000,0x0000, 0x0E2F,0x0000,0x0000, 0x0E30,0x0000,0x0000, +0x0E31,0x0000,0x0000, 0x0E32,0x0000,0x0000, 0x026C,0x0000,0x0000, +0x026D,0x0000,0x0000, 0x030E,0x0000,0x0000, 0x030F,0x0000,0x0000, +0x0310,0x0000,0x0000, 0x0311,0x0000,0x0000, 0x194F,0x0000,0x0000, +0x1950,0x0000,0x0000, 0x195C,0x0000,0x0000, 0x195D,0x0000,0x0000, +0x195E,0x0000,0x0000, 0x195F,0x0000,0x0000, 0x1967,0x0000,0x0000, +0x1968,0x0000,0x0000, 0x1969,0x0000,0x0000, 0x196A,0x0000,0x0000, +0xFBC0,0x905A,0x0000, 0xFBC0,0x905B,0x0000, 0xFBC0,0x905C,0x0000, +0xFBC0,0x905D,0x0000, 0xFBC0,0x905E,0x0000, 0xFBC0,0x905F,0x0000, +0xFBC0,0x9060,0x0000, 0xFBC0,0x9061,0x0000, 0xFBC0,0x9062,0x0000, +0xFBC0,0x9063,0x0000, 0xFBC0,0x9064,0x0000, 0xFBC0,0x9065,0x0000, +0xFBC0,0x9066,0x0000, 0xFBC0,0x9067,0x0000, 0xFBC0,0x9068,0x0000, +0xFBC0,0x9069,0x0000, 0xFBC0,0x906A,0x0000, 0xFBC0,0x906B,0x0000, +0xFBC0,0x906C,0x0000, 0xFBC0,0x906D,0x0000, 0xFBC0,0x906E,0x0000, +0xFBC0,0x906F,0x0000, 0xFBC0,0x9070,0x0000, 0xFBC0,0x9071,0x0000, +0xFBC0,0x9072,0x0000, 0xFBC0,0x9073,0x0000, 0xFBC0,0x9074,0x0000, +0xFBC0,0x9075,0x0000, 0xFBC0,0x9076,0x0000, 0xFBC0,0x9077,0x0000, +0xFBC0,0x9078,0x0000, 0xFBC0,0x9079,0x0000, 0xFBC0,0x907A,0x0000, +0xFBC0,0x907B,0x0000, 0xFBC0,0x907C,0x0000, 0xFBC0,0x907D,0x0000, +0xFBC0,0x907E,0x0000, 0xFBC0,0x907F,0x0000, 0xFBC0,0x9080,0x0000, +0xFBC0,0x9081,0x0000, 0xFBC0,0x9082,0x0000, 0xFBC0,0x9083,0x0000, +0xFBC0,0x9084,0x0000, 0xFBC0,0x9085,0x0000, 0xFBC0,0x9086,0x0000, +0xFBC0,0x9087,0x0000, 0xFBC0,0x9088,0x0000, 0xFBC0,0x9089,0x0000, +0xFBC0,0x908A,0x0000, 0xFBC0,0x908B,0x0000, 0xFBC0,0x908C,0x0000, +0xFBC0,0x908D,0x0000, 0xFBC0,0x908E,0x0000, 0xFBC0,0x908F,0x0000, +0xFBC0,0x9090,0x0000, 0xFBC0,0x9091,0x0000, 0xFBC0,0x9092,0x0000, +0xFBC0,0x9093,0x0000, 0xFBC0,0x9094,0x0000, 0xFBC0,0x9095,0x0000, +0xFBC0,0x9096,0x0000, 0xFBC0,0x9097,0x0000, 0xFBC0,0x9098,0x0000, +0xFBC0,0x9099,0x0000, 0xFBC0,0x909A,0x0000, 0xFBC0,0x909B,0x0000, +0xFBC0,0x909C,0x0000, 0xFBC0,0x909D,0x0000, 0xFBC0,0x909E,0x0000, +0xFBC0,0x909F,0x0000, 0x12E1,0x0000,0x0000, 0x12E2,0x0000,0x0000, +0x12E3,0x0000,0x0000, 0x12E4,0x0000,0x0000, 0x12E5,0x0000,0x0000, +0x12E6,0x0000,0x0000, 0x12E7,0x0000,0x0000, 0x12E9,0x0000,0x0000, +0x12EA,0x0000,0x0000, 0x12EB,0x0000,0x0000, 0x12EC,0x0000,0x0000, +0x12ED,0x0000,0x0000, 0x12EE,0x0000,0x0000, 0x12F0,0x0000,0x0000, +0x12F1,0x0000,0x0000, 0x12F2,0x0000,0x0000, 0x12F3,0x0000,0x0000, +0x12F4,0x0000,0x0000, 0x12F5,0x0000,0x0000, 0x12F7,0x0000,0x0000, +0x12F8,0x0000,0x0000, 0x12F9,0x0000,0x0000, 0x12FA,0x0000,0x0000, +0x12FB,0x0000,0x0000, 0x12FC,0x0000,0x0000, 0x12FD,0x0000,0x0000, +0x12FE,0x0000,0x0000, 0x12FF,0x0000,0x0000, 0x1300,0x0000,0x0000, +0x1301,0x0000,0x0000, 0x1302,0x0000,0x0000, 0x1304,0x0000,0x0000, +0x1305,0x0000,0x0000, 0x12E8,0x0000,0x0000, 0x12EF,0x0000,0x0000, +0x12F6,0x0000,0x0000, 0x1303,0x0000,0x0000, 0x1306,0x0000,0x0000, +0xFBC0,0x90C6,0x0000, 0xFBC0,0x90C7,0x0000, 0xFBC0,0x90C8,0x0000, +0xFBC0,0x90C9,0x0000, 0xFBC0,0x90CA,0x0000, 0xFBC0,0x90CB,0x0000, +0xFBC0,0x90CC,0x0000, 0xFBC0,0x90CD,0x0000, 0xFBC0,0x90CE,0x0000, +0xFBC0,0x90CF,0x0000, 0x12E1,0x0000,0x0000, 0x12E2,0x0000,0x0000, +0x12E3,0x0000,0x0000, 0x12E4,0x0000,0x0000, 0x12E5,0x0000,0x0000, +0x12E6,0x0000,0x0000, 0x12E7,0x0000,0x0000, 0x12E9,0x0000,0x0000, +0x12EA,0x0000,0x0000, 0x12EB,0x0000,0x0000, 0x12EC,0x0000,0x0000, +0x12ED,0x0000,0x0000, 0x12EE,0x0000,0x0000, 0x12F0,0x0000,0x0000, +0x12F1,0x0000,0x0000, 0x12F2,0x0000,0x0000, 0x12F3,0x0000,0x0000, +0x12F4,0x0000,0x0000, 0x12F5,0x0000,0x0000, 0x12F7,0x0000,0x0000, +0x12F8,0x0000,0x0000, 0x12F9,0x0000,0x0000, 0x12FA,0x0000,0x0000, +0x12FB,0x0000,0x0000, 0x12FC,0x0000,0x0000, 0x12FD,0x0000,0x0000, +0x12FE,0x0000,0x0000, 0x12FF,0x0000,0x0000, 0x1300,0x0000,0x0000, +0x1301,0x0000,0x0000, 0x1302,0x0000,0x0000, 0x1304,0x0000,0x0000, +0x1305,0x0000,0x0000, 0x12E8,0x0000,0x0000, 0x12EF,0x0000,0x0000, +0x12F6,0x0000,0x0000, 0x1303,0x0000,0x0000, 0x1306,0x0000,0x0000, +0x1307,0x0000,0x0000, 0x1308,0x0000,0x0000, 0x1309,0x0000,0x0000, +0xFBC0,0x90F9,0x0000, 0xFBC0,0x90FA,0x0000, 0x0271,0x0000,0x0000, +0xFBC0,0x90FC,0x0000, 0xFBC0,0x90FD,0x0000, 0xFBC0,0x90FE,0x0000, +0xFBC0,0x90FF,0x0000 }; + +uint16 page011data[]= { /* 1100 (3 weights per char) */ +0x1D62,0x0000,0x0000, 0x1D63,0x0000,0x0000, 0x1D64,0x0000,0x0000, +0x1D65,0x0000,0x0000, 0x1D66,0x0000,0x0000, 0x1D67,0x0000,0x0000, +0x1D68,0x0000,0x0000, 0x1D69,0x0000,0x0000, 0x1D6A,0x0000,0x0000, +0x1D6B,0x0000,0x0000, 0x1D6C,0x0000,0x0000, 0x1D6D,0x0000,0x0000, +0x1D6E,0x0000,0x0000, 0x1D6F,0x0000,0x0000, 0x1D70,0x0000,0x0000, +0x1D71,0x0000,0x0000, 0x1D72,0x0000,0x0000, 0x1D73,0x0000,0x0000, +0x1D74,0x0000,0x0000, 0x1D75,0x0000,0x0000, 0x1D76,0x0000,0x0000, +0x1D77,0x0000,0x0000, 0x1D78,0x0000,0x0000, 0x1D79,0x0000,0x0000, +0x1D7A,0x0000,0x0000, 0x1D7B,0x0000,0x0000, 0x1D7C,0x0000,0x0000, +0x1D7D,0x0000,0x0000, 0x1D7E,0x0000,0x0000, 0x1D7F,0x0000,0x0000, +0x1D80,0x0000,0x0000, 0x1D81,0x0000,0x0000, 0x1D82,0x0000,0x0000, +0x1D83,0x0000,0x0000, 0x1D84,0x0000,0x0000, 0x1D85,0x0000,0x0000, +0x1D86,0x0000,0x0000, 0x1D87,0x0000,0x0000, 0x1D88,0x0000,0x0000, +0x1D89,0x0000,0x0000, 0x1D8A,0x0000,0x0000, 0x1D8B,0x0000,0x0000, +0x1D8C,0x0000,0x0000, 0x1D8D,0x0000,0x0000, 0x1D8E,0x0000,0x0000, +0x1D8F,0x0000,0x0000, 0x1D90,0x0000,0x0000, 0x1D91,0x0000,0x0000, +0x1D92,0x0000,0x0000, 0x1D93,0x0000,0x0000, 0x1D94,0x0000,0x0000, +0x1D95,0x0000,0x0000, 0x1D96,0x0000,0x0000, 0x1D97,0x0000,0x0000, +0x1D98,0x0000,0x0000, 0x1D99,0x0000,0x0000, 0x1D9A,0x0000,0x0000, +0x1D9B,0x0000,0x0000, 0x1D9C,0x0000,0x0000, 0x1D9D,0x0000,0x0000, +0x1D9E,0x0000,0x0000, 0x1D9F,0x0000,0x0000, 0x1DA0,0x0000,0x0000, +0x1DA1,0x0000,0x0000, 0x1DA2,0x0000,0x0000, 0x1DA3,0x0000,0x0000, +0x1DA4,0x0000,0x0000, 0x1DA5,0x0000,0x0000, 0x1DA6,0x0000,0x0000, +0x1DA7,0x0000,0x0000, 0x1DA8,0x0000,0x0000, 0x1DA9,0x0000,0x0000, +0x1DAA,0x0000,0x0000, 0x1DAB,0x0000,0x0000, 0x1DAC,0x0000,0x0000, +0x1DAD,0x0000,0x0000, 0x1DAE,0x0000,0x0000, 0x1DAF,0x0000,0x0000, +0x1DB0,0x0000,0x0000, 0x1DB1,0x0000,0x0000, 0x1DB2,0x0000,0x0000, +0x1DB3,0x0000,0x0000, 0x1DB4,0x0000,0x0000, 0x1DB5,0x0000,0x0000, +0x1DB6,0x0000,0x0000, 0x1DB7,0x0000,0x0000, 0x1DB8,0x0000,0x0000, +0x1DB9,0x0000,0x0000, 0x1DBA,0x0000,0x0000, 0x1DBB,0x0000,0x0000, +0xFBC0,0x915A,0x0000, 0xFBC0,0x915B,0x0000, 0xFBC0,0x915C,0x0000, +0xFBC0,0x915D,0x0000, 0xFBC0,0x915E,0x0000, 0x1DBC,0x0000,0x0000, +0x1DBD,0x0000,0x0000, 0x1DBE,0x0000,0x0000, 0x1DBF,0x0000,0x0000, +0x1DC0,0x0000,0x0000, 0x1DC1,0x0000,0x0000, 0x1DC2,0x0000,0x0000, +0x1DC3,0x0000,0x0000, 0x1DC4,0x0000,0x0000, 0x1DC5,0x0000,0x0000, +0x1DC6,0x0000,0x0000, 0x1DC7,0x0000,0x0000, 0x1DC8,0x0000,0x0000, +0x1DC9,0x0000,0x0000, 0x1DCA,0x0000,0x0000, 0x1DCB,0x0000,0x0000, +0x1DCC,0x0000,0x0000, 0x1DCD,0x0000,0x0000, 0x1DCE,0x0000,0x0000, +0x1DCF,0x0000,0x0000, 0x1DD0,0x0000,0x0000, 0x1DD1,0x0000,0x0000, +0x1DD2,0x0000,0x0000, 0x1DD3,0x0000,0x0000, 0x1DD4,0x0000,0x0000, +0x1DD5,0x0000,0x0000, 0x1DD6,0x0000,0x0000, 0x1DD7,0x0000,0x0000, +0x1DD8,0x0000,0x0000, 0x1DD9,0x0000,0x0000, 0x1DDA,0x0000,0x0000, +0x1DDB,0x0000,0x0000, 0x1DDC,0x0000,0x0000, 0x1DDD,0x0000,0x0000, +0x1DDE,0x0000,0x0000, 0x1DDF,0x0000,0x0000, 0x1DE0,0x0000,0x0000, +0x1DE1,0x0000,0x0000, 0x1DE2,0x0000,0x0000, 0x1DE3,0x0000,0x0000, +0x1DE4,0x0000,0x0000, 0x1DE5,0x0000,0x0000, 0x1DE6,0x0000,0x0000, +0x1DE7,0x0000,0x0000, 0x1DE8,0x0000,0x0000, 0x1DE9,0x0000,0x0000, +0x1DEA,0x0000,0x0000, 0x1DEB,0x0000,0x0000, 0x1DEC,0x0000,0x0000, +0x1DED,0x0000,0x0000, 0x1DEE,0x0000,0x0000, 0x1DEF,0x0000,0x0000, +0x1DF0,0x0000,0x0000, 0x1DF1,0x0000,0x0000, 0x1DF2,0x0000,0x0000, +0x1DF3,0x0000,0x0000, 0x1DF4,0x0000,0x0000, 0x1DF5,0x0000,0x0000, +0x1DF6,0x0000,0x0000, 0x1DF7,0x0000,0x0000, 0x1DF8,0x0000,0x0000, +0x1DF9,0x0000,0x0000, 0x1DFA,0x0000,0x0000, 0x1DFB,0x0000,0x0000, +0x1DFC,0x0000,0x0000, 0x1DFD,0x0000,0x0000, 0x1DFE,0x0000,0x0000, +0x1DFF,0x0000,0x0000, 0xFBC0,0x91A3,0x0000, 0xFBC0,0x91A4,0x0000, +0xFBC0,0x91A5,0x0000, 0xFBC0,0x91A6,0x0000, 0xFBC0,0x91A7,0x0000, +0x1E00,0x0000,0x0000, 0x1E01,0x0000,0x0000, 0x1E02,0x0000,0x0000, +0x1E03,0x0000,0x0000, 0x1E04,0x0000,0x0000, 0x1E05,0x0000,0x0000, +0x1E06,0x0000,0x0000, 0x1E07,0x0000,0x0000, 0x1E08,0x0000,0x0000, +0x1E09,0x0000,0x0000, 0x1E0A,0x0000,0x0000, 0x1E0B,0x0000,0x0000, +0x1E0C,0x0000,0x0000, 0x1E0D,0x0000,0x0000, 0x1E0E,0x0000,0x0000, +0x1E0F,0x0000,0x0000, 0x1E10,0x0000,0x0000, 0x1E11,0x0000,0x0000, +0x1E12,0x0000,0x0000, 0x1E13,0x0000,0x0000, 0x1E14,0x0000,0x0000, +0x1E15,0x0000,0x0000, 0x1E16,0x0000,0x0000, 0x1E17,0x0000,0x0000, +0x1E18,0x0000,0x0000, 0x1E19,0x0000,0x0000, 0x1E1A,0x0000,0x0000, +0x1E1B,0x0000,0x0000, 0x1E1C,0x0000,0x0000, 0x1E1D,0x0000,0x0000, +0x1E1E,0x0000,0x0000, 0x1E1F,0x0000,0x0000, 0x1E20,0x0000,0x0000, +0x1E21,0x0000,0x0000, 0x1E22,0x0000,0x0000, 0x1E23,0x0000,0x0000, +0x1E24,0x0000,0x0000, 0x1E25,0x0000,0x0000, 0x1E26,0x0000,0x0000, +0x1E27,0x0000,0x0000, 0x1E28,0x0000,0x0000, 0x1E29,0x0000,0x0000, +0x1E2A,0x0000,0x0000, 0x1E2B,0x0000,0x0000, 0x1E2C,0x0000,0x0000, +0x1E2D,0x0000,0x0000, 0x1E2E,0x0000,0x0000, 0x1E2F,0x0000,0x0000, +0x1E30,0x0000,0x0000, 0x1E31,0x0000,0x0000, 0x1E32,0x0000,0x0000, +0x1E33,0x0000,0x0000, 0x1E34,0x0000,0x0000, 0x1E35,0x0000,0x0000, +0x1E36,0x0000,0x0000, 0x1E37,0x0000,0x0000, 0x1E38,0x0000,0x0000, +0x1E39,0x0000,0x0000, 0x1E3A,0x0000,0x0000, 0x1E3B,0x0000,0x0000, +0x1E3C,0x0000,0x0000, 0x1E3D,0x0000,0x0000, 0x1E3E,0x0000,0x0000, +0x1E3F,0x0000,0x0000, 0x1E40,0x0000,0x0000, 0x1E41,0x0000,0x0000, +0x1E42,0x0000,0x0000, 0x1E43,0x0000,0x0000, 0x1E44,0x0000,0x0000, +0x1E45,0x0000,0x0000, 0x1E46,0x0000,0x0000, 0x1E47,0x0000,0x0000, +0x1E48,0x0000,0x0000, 0x1E49,0x0000,0x0000, 0x1E4A,0x0000,0x0000, +0x1E4B,0x0000,0x0000, 0x1E4C,0x0000,0x0000, 0x1E4D,0x0000,0x0000, +0x1E4E,0x0000,0x0000, 0x1E4F,0x0000,0x0000, 0x1E50,0x0000,0x0000, +0x1E51,0x0000,0x0000, 0xFBC0,0x91FA,0x0000, 0xFBC0,0x91FB,0x0000, +0xFBC0,0x91FC,0x0000, 0xFBC0,0x91FD,0x0000, 0xFBC0,0x91FE,0x0000, +0xFBC0,0x91FF,0x0000 }; + +uint16 page012data[]= { /* 1200 (3 weights per char) */ +0x141C,0x0000,0x0000, 0x141D,0x0000,0x0000, 0x141E,0x0000,0x0000, +0x141F,0x0000,0x0000, 0x1420,0x0000,0x0000, 0x1421,0x0000,0x0000, +0x1422,0x0000,0x0000, 0xFBC0,0x9207,0x0000, 0x1423,0x0000,0x0000, +0x1424,0x0000,0x0000, 0x1425,0x0000,0x0000, 0x1426,0x0000,0x0000, +0x1427,0x0000,0x0000, 0x1428,0x0000,0x0000, 0x1429,0x0000,0x0000, +0x142A,0x0000,0x0000, 0x142B,0x0000,0x0000, 0x142C,0x0000,0x0000, +0x142D,0x0000,0x0000, 0x142E,0x0000,0x0000, 0x142F,0x0000,0x0000, +0x1430,0x0000,0x0000, 0x1431,0x0000,0x0000, 0x1432,0x0000,0x0000, +0x1433,0x0000,0x0000, 0x1434,0x0000,0x0000, 0x1435,0x0000,0x0000, +0x1436,0x0000,0x0000, 0x1437,0x0000,0x0000, 0x1438,0x0000,0x0000, +0x1439,0x0000,0x0000, 0x143A,0x0000,0x0000, 0x143B,0x0000,0x0000, +0x143C,0x0000,0x0000, 0x143D,0x0000,0x0000, 0x143E,0x0000,0x0000, +0x143F,0x0000,0x0000, 0x1440,0x0000,0x0000, 0x1441,0x0000,0x0000, +0x1442,0x0000,0x0000, 0x1443,0x0000,0x0000, 0x1444,0x0000,0x0000, +0x1445,0x0000,0x0000, 0x1446,0x0000,0x0000, 0x1447,0x0000,0x0000, +0x1448,0x0000,0x0000, 0x1449,0x0000,0x0000, 0x144A,0x0000,0x0000, +0x144B,0x0000,0x0000, 0x144C,0x0000,0x0000, 0x144D,0x0000,0x0000, +0x144E,0x0000,0x0000, 0x144F,0x0000,0x0000, 0x1450,0x0000,0x0000, +0x1451,0x0000,0x0000, 0x1452,0x0000,0x0000, 0x1453,0x0000,0x0000, +0x1454,0x0000,0x0000, 0x1455,0x0000,0x0000, 0x1456,0x0000,0x0000, +0x1457,0x0000,0x0000, 0x1458,0x0000,0x0000, 0x1459,0x0000,0x0000, +0x145A,0x0000,0x0000, 0x145B,0x0000,0x0000, 0x145C,0x0000,0x0000, +0x145D,0x0000,0x0000, 0x145E,0x0000,0x0000, 0x145F,0x0000,0x0000, +0x1460,0x0000,0x0000, 0x1461,0x0000,0x0000, 0xFBC0,0x9247,0x0000, +0x1462,0x0000,0x0000, 0xFBC0,0x9249,0x0000, 0x1463,0x0000,0x0000, +0x1464,0x0000,0x0000, 0x1465,0x0000,0x0000, 0x1466,0x0000,0x0000, +0xFBC0,0x924E,0x0000, 0xFBC0,0x924F,0x0000, 0x1467,0x0000,0x0000, +0x1468,0x0000,0x0000, 0x1469,0x0000,0x0000, 0x146A,0x0000,0x0000, +0x146B,0x0000,0x0000, 0x146C,0x0000,0x0000, 0x146D,0x0000,0x0000, +0xFBC0,0x9257,0x0000, 0x146E,0x0000,0x0000, 0xFBC0,0x9259,0x0000, +0x146F,0x0000,0x0000, 0x1470,0x0000,0x0000, 0x1471,0x0000,0x0000, +0x1472,0x0000,0x0000, 0xFBC0,0x925E,0x0000, 0xFBC0,0x925F,0x0000, +0x1473,0x0000,0x0000, 0x1474,0x0000,0x0000, 0x1475,0x0000,0x0000, +0x1476,0x0000,0x0000, 0x1477,0x0000,0x0000, 0x1478,0x0000,0x0000, +0x1479,0x0000,0x0000, 0x147A,0x0000,0x0000, 0x147B,0x0000,0x0000, +0x147C,0x0000,0x0000, 0x147D,0x0000,0x0000, 0x147E,0x0000,0x0000, +0x147F,0x0000,0x0000, 0x1480,0x0000,0x0000, 0x1481,0x0000,0x0000, +0x1482,0x0000,0x0000, 0x1483,0x0000,0x0000, 0x1484,0x0000,0x0000, +0x1485,0x0000,0x0000, 0x1486,0x0000,0x0000, 0x1487,0x0000,0x0000, +0x1488,0x0000,0x0000, 0x1489,0x0000,0x0000, 0x148A,0x0000,0x0000, +0x148B,0x0000,0x0000, 0x148C,0x0000,0x0000, 0x148D,0x0000,0x0000, +0x148E,0x0000,0x0000, 0x148F,0x0000,0x0000, 0x1490,0x0000,0x0000, +0x1491,0x0000,0x0000, 0x1492,0x0000,0x0000, 0x1493,0x0000,0x0000, +0x1494,0x0000,0x0000, 0x1495,0x0000,0x0000, 0x1496,0x0000,0x0000, +0x1497,0x0000,0x0000, 0x1498,0x0000,0x0000, 0x1499,0x0000,0x0000, +0xFBC0,0x9287,0x0000, 0x149A,0x0000,0x0000, 0xFBC0,0x9289,0x0000, +0x149B,0x0000,0x0000, 0x149C,0x0000,0x0000, 0x149D,0x0000,0x0000, +0x149E,0x0000,0x0000, 0xFBC0,0x928E,0x0000, 0xFBC0,0x928F,0x0000, +0x149F,0x0000,0x0000, 0x14A0,0x0000,0x0000, 0x14A1,0x0000,0x0000, +0x14A2,0x0000,0x0000, 0x14A3,0x0000,0x0000, 0x14A4,0x0000,0x0000, +0x14A5,0x0000,0x0000, 0x14A6,0x0000,0x0000, 0x14A7,0x0000,0x0000, +0x14A8,0x0000,0x0000, 0x14A9,0x0000,0x0000, 0x14AA,0x0000,0x0000, +0x14AB,0x0000,0x0000, 0x14AC,0x0000,0x0000, 0x14AD,0x0000,0x0000, +0x14AE,0x0000,0x0000, 0x14AF,0x0000,0x0000, 0x14B0,0x0000,0x0000, +0x14B1,0x0000,0x0000, 0x14B2,0x0000,0x0000, 0x14B3,0x0000,0x0000, +0x14B4,0x0000,0x0000, 0x14B5,0x0000,0x0000, 0x14B6,0x0000,0x0000, +0x14B7,0x0000,0x0000, 0x14B8,0x0000,0x0000, 0x14B9,0x0000,0x0000, +0x14BA,0x0000,0x0000, 0x14BB,0x0000,0x0000, 0x14BC,0x0000,0x0000, +0x14BD,0x0000,0x0000, 0xFBC0,0x92AF,0x0000, 0x14BE,0x0000,0x0000, +0xFBC0,0x92B1,0x0000, 0x14BF,0x0000,0x0000, 0x14C0,0x0000,0x0000, +0x14C1,0x0000,0x0000, 0x14C2,0x0000,0x0000, 0xFBC0,0x92B6,0x0000, +0xFBC0,0x92B7,0x0000, 0x14C3,0x0000,0x0000, 0x14C4,0x0000,0x0000, +0x14C5,0x0000,0x0000, 0x14C6,0x0000,0x0000, 0x14C7,0x0000,0x0000, +0x14C8,0x0000,0x0000, 0x14C9,0x0000,0x0000, 0xFBC0,0x92BF,0x0000, +0x14CA,0x0000,0x0000, 0xFBC0,0x92C1,0x0000, 0x14CB,0x0000,0x0000, +0x14CC,0x0000,0x0000, 0x14CD,0x0000,0x0000, 0x14CE,0x0000,0x0000, +0xFBC0,0x92C6,0x0000, 0xFBC0,0x92C7,0x0000, 0x14CF,0x0000,0x0000, +0x14D0,0x0000,0x0000, 0x14D1,0x0000,0x0000, 0x14D2,0x0000,0x0000, +0x14D3,0x0000,0x0000, 0x14D4,0x0000,0x0000, 0x14D5,0x0000,0x0000, +0xFBC0,0x92CF,0x0000, 0x14D6,0x0000,0x0000, 0x14D7,0x0000,0x0000, +0x14D8,0x0000,0x0000, 0x14D9,0x0000,0x0000, 0x14DA,0x0000,0x0000, +0x14DB,0x0000,0x0000, 0x14DC,0x0000,0x0000, 0xFBC0,0x92D7,0x0000, +0x14DD,0x0000,0x0000, 0x14DE,0x0000,0x0000, 0x14DF,0x0000,0x0000, +0x14E0,0x0000,0x0000, 0x14E1,0x0000,0x0000, 0x14E2,0x0000,0x0000, +0x14E3,0x0000,0x0000, 0x14E4,0x0000,0x0000, 0x14E5,0x0000,0x0000, +0x14E6,0x0000,0x0000, 0x14E7,0x0000,0x0000, 0x14E8,0x0000,0x0000, +0x14E9,0x0000,0x0000, 0x14EA,0x0000,0x0000, 0x14EB,0x0000,0x0000, +0x14EC,0x0000,0x0000, 0x14ED,0x0000,0x0000, 0x14EE,0x0000,0x0000, +0x14EF,0x0000,0x0000, 0x14F0,0x0000,0x0000, 0x14F1,0x0000,0x0000, +0x14F2,0x0000,0x0000, 0x14F3,0x0000,0x0000, 0xFBC0,0x92EF,0x0000, +0x14F4,0x0000,0x0000, 0x14F5,0x0000,0x0000, 0x14F6,0x0000,0x0000, +0x14F7,0x0000,0x0000, 0x14F8,0x0000,0x0000, 0x14F9,0x0000,0x0000, +0x14FA,0x0000,0x0000, 0x14FB,0x0000,0x0000, 0x14FC,0x0000,0x0000, +0x14FD,0x0000,0x0000, 0x14FE,0x0000,0x0000, 0x14FF,0x0000,0x0000, +0x1500,0x0000,0x0000, 0x1501,0x0000,0x0000, 0x1502,0x0000,0x0000, +0x1503,0x0000,0x0000 }; + +uint16 page013data[]= { /* 1300 (3 weights per char) */ +0x1504,0x0000,0x0000, 0x1505,0x0000,0x0000, 0x1506,0x0000,0x0000, +0x1507,0x0000,0x0000, 0x1508,0x0000,0x0000, 0x1509,0x0000,0x0000, +0x150A,0x0000,0x0000, 0x150B,0x0000,0x0000, 0x150C,0x0000,0x0000, +0x150D,0x0000,0x0000, 0x150E,0x0000,0x0000, 0x150F,0x0000,0x0000, +0x1510,0x0000,0x0000, 0x1511,0x0000,0x0000, 0x1512,0x0000,0x0000, +0xFBC0,0x930F,0x0000, 0x1513,0x0000,0x0000, 0xFBC0,0x9311,0x0000, +0x1514,0x0000,0x0000, 0x1515,0x0000,0x0000, 0x1516,0x0000,0x0000, +0x1517,0x0000,0x0000, 0xFBC0,0x9316,0x0000, 0xFBC0,0x9317,0x0000, +0x1518,0x0000,0x0000, 0x1519,0x0000,0x0000, 0x151A,0x0000,0x0000, +0x151B,0x0000,0x0000, 0x151C,0x0000,0x0000, 0x151D,0x0000,0x0000, +0x151E,0x0000,0x0000, 0xFBC0,0x931F,0x0000, 0x151F,0x0000,0x0000, +0x1520,0x0000,0x0000, 0x1521,0x0000,0x0000, 0x1522,0x0000,0x0000, +0x1523,0x0000,0x0000, 0x1524,0x0000,0x0000, 0x1525,0x0000,0x0000, +0x1526,0x0000,0x0000, 0x1527,0x0000,0x0000, 0x1528,0x0000,0x0000, +0x1529,0x0000,0x0000, 0x152A,0x0000,0x0000, 0x152B,0x0000,0x0000, +0x152C,0x0000,0x0000, 0x152D,0x0000,0x0000, 0x152E,0x0000,0x0000, +0x152F,0x0000,0x0000, 0x1530,0x0000,0x0000, 0x1531,0x0000,0x0000, +0x1532,0x0000,0x0000, 0x1533,0x0000,0x0000, 0x1534,0x0000,0x0000, +0x1535,0x0000,0x0000, 0x1536,0x0000,0x0000, 0x1537,0x0000,0x0000, +0x1538,0x0000,0x0000, 0x1539,0x0000,0x0000, 0x153A,0x0000,0x0000, +0x153B,0x0000,0x0000, 0x153C,0x0000,0x0000, 0x153D,0x0000,0x0000, +0x153E,0x0000,0x0000, 0x153F,0x0000,0x0000, 0x1540,0x0000,0x0000, +0x1541,0x0000,0x0000, 0x1542,0x0000,0x0000, 0x1543,0x0000,0x0000, +0x1544,0x0000,0x0000, 0x1545,0x0000,0x0000, 0xFBC0,0x9347,0x0000, +0x1546,0x0000,0x0000, 0x1547,0x0000,0x0000, 0x1548,0x0000,0x0000, +0x1549,0x0000,0x0000, 0x154A,0x0000,0x0000, 0x154B,0x0000,0x0000, +0x154C,0x0000,0x0000, 0x154D,0x0000,0x0000, 0x154E,0x0000,0x0000, +0x154F,0x0000,0x0000, 0x1550,0x0000,0x0000, 0x1551,0x0000,0x0000, +0x1552,0x0000,0x0000, 0x1553,0x0000,0x0000, 0x1554,0x0000,0x0000, +0x1555,0x0000,0x0000, 0x1556,0x0000,0x0000, 0x1557,0x0000,0x0000, +0x1558,0x0000,0x0000, 0xFBC0,0x935B,0x0000, 0xFBC0,0x935C,0x0000, +0xFBC0,0x935D,0x0000, 0xFBC0,0x935E,0x0000, 0xFBC0,0x935F,0x0000, +0xFBC0,0x9360,0x0000, 0x0245,0x0000,0x0000, 0x0262,0x0000,0x0000, +0x0246,0x0000,0x0000, 0x0247,0x0000,0x0000, 0x0248,0x0000,0x0000, +0x0249,0x0000,0x0000, 0x025A,0x0000,0x0000, 0x0272,0x0000,0x0000, +0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, 0x0E2C,0x0000,0x0000, +0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, 0x0E2F,0x0000,0x0000, +0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, 0x0E32,0x0000,0x0000, +0x0DCC,0x0000,0x0000, 0x0DCD,0x0000,0x0000, 0x0DCE,0x0000,0x0000, +0x0DCF,0x0000,0x0000, 0x0DD0,0x0000,0x0000, 0x0DD1,0x0000,0x0000, +0x0DD2,0x0000,0x0000, 0x0DD3,0x0000,0x0000, 0x0DD4,0x0000,0x0000, +0x0DD5,0x0000,0x0000, 0x0DD6,0x0000,0x0000, 0xFBC0,0x937D,0x0000, +0xFBC0,0x937E,0x0000, 0xFBC0,0x937F,0x0000, 0xFBC0,0x9380,0x0000, +0xFBC0,0x9381,0x0000, 0xFBC0,0x9382,0x0000, 0xFBC0,0x9383,0x0000, +0xFBC0,0x9384,0x0000, 0xFBC0,0x9385,0x0000, 0xFBC0,0x9386,0x0000, +0xFBC0,0x9387,0x0000, 0xFBC0,0x9388,0x0000, 0xFBC0,0x9389,0x0000, +0xFBC0,0x938A,0x0000, 0xFBC0,0x938B,0x0000, 0xFBC0,0x938C,0x0000, +0xFBC0,0x938D,0x0000, 0xFBC0,0x938E,0x0000, 0xFBC0,0x938F,0x0000, +0xFBC0,0x9390,0x0000, 0xFBC0,0x9391,0x0000, 0xFBC0,0x9392,0x0000, +0xFBC0,0x9393,0x0000, 0xFBC0,0x9394,0x0000, 0xFBC0,0x9395,0x0000, +0xFBC0,0x9396,0x0000, 0xFBC0,0x9397,0x0000, 0xFBC0,0x9398,0x0000, +0xFBC0,0x9399,0x0000, 0xFBC0,0x939A,0x0000, 0xFBC0,0x939B,0x0000, +0xFBC0,0x939C,0x0000, 0xFBC0,0x939D,0x0000, 0xFBC0,0x939E,0x0000, +0xFBC0,0x939F,0x0000, 0x1A59,0x0000,0x0000, 0x1A5A,0x0000,0x0000, +0x1A5B,0x0000,0x0000, 0x1A5C,0x0000,0x0000, 0x1A5D,0x0000,0x0000, +0x1A5E,0x0000,0x0000, 0x1A5F,0x0000,0x0000, 0x1A60,0x0000,0x0000, +0x1A61,0x0000,0x0000, 0x1A62,0x0000,0x0000, 0x1A63,0x0000,0x0000, +0x1A64,0x0000,0x0000, 0x1A65,0x0000,0x0000, 0x1A66,0x0000,0x0000, +0x1A67,0x0000,0x0000, 0x1A68,0x0000,0x0000, 0x1A69,0x0000,0x0000, +0x1A6A,0x0000,0x0000, 0x1A6B,0x0000,0x0000, 0x1A6C,0x0000,0x0000, +0x1A6D,0x0000,0x0000, 0x1A6E,0x0000,0x0000, 0x1A6F,0x0000,0x0000, +0x1A70,0x0000,0x0000, 0x1A71,0x0000,0x0000, 0x1A72,0x0000,0x0000, +0x1A73,0x0000,0x0000, 0x1A74,0x0000,0x0000, 0x1A75,0x0000,0x0000, +0x1A76,0x0000,0x0000, 0x1A77,0x0000,0x0000, 0x1A78,0x0000,0x0000, +0x1A79,0x0000,0x0000, 0x1A7A,0x0000,0x0000, 0x1A7B,0x0000,0x0000, +0x1A7C,0x0000,0x0000, 0x1A7D,0x0000,0x0000, 0x1A7E,0x0000,0x0000, +0x1A7F,0x0000,0x0000, 0x1A80,0x0000,0x0000, 0x1A81,0x0000,0x0000, +0x1A82,0x0000,0x0000, 0x1A83,0x0000,0x0000, 0x1A84,0x0000,0x0000, +0x1A85,0x0000,0x0000, 0x1A86,0x0000,0x0000, 0x1A87,0x0000,0x0000, +0x1A88,0x0000,0x0000, 0x1A89,0x0000,0x0000, 0x1A8A,0x0000,0x0000, +0x1A8B,0x0000,0x0000, 0x1A8C,0x0000,0x0000, 0x1A8D,0x0000,0x0000, +0x1A8E,0x0000,0x0000, 0x1A8F,0x0000,0x0000, 0x1A90,0x0000,0x0000, +0x1A91,0x0000,0x0000, 0x1A92,0x0000,0x0000, 0x1A93,0x0000,0x0000, +0x1A94,0x0000,0x0000, 0x1A95,0x0000,0x0000, 0x1A96,0x0000,0x0000, +0x1A97,0x0000,0x0000, 0x1A98,0x0000,0x0000, 0x1A99,0x0000,0x0000, +0x1A9A,0x0000,0x0000, 0x1A9B,0x0000,0x0000, 0x1A9C,0x0000,0x0000, +0x1A9D,0x0000,0x0000, 0x1A9E,0x0000,0x0000, 0x1A9F,0x0000,0x0000, +0x1AA0,0x0000,0x0000, 0x1AA1,0x0000,0x0000, 0x1AA2,0x0000,0x0000, +0x1AA3,0x0000,0x0000, 0x1AA4,0x0000,0x0000, 0x1AA5,0x0000,0x0000, +0x1AA6,0x0000,0x0000, 0x1AA7,0x0000,0x0000, 0x1AA8,0x0000,0x0000, +0x1AA9,0x0000,0x0000, 0x1AAA,0x0000,0x0000, 0x1AAB,0x0000,0x0000, +0x1AAC,0x0000,0x0000, 0x1AAD,0x0000,0x0000, 0xFBC0,0x93F5,0x0000, +0xFBC0,0x93F6,0x0000, 0xFBC0,0x93F7,0x0000, 0xFBC0,0x93F8,0x0000, +0xFBC0,0x93F9,0x0000, 0xFBC0,0x93FA,0x0000, 0xFBC0,0x93FB,0x0000, +0xFBC0,0x93FC,0x0000, 0xFBC0,0x93FD,0x0000, 0xFBC0,0x93FE,0x0000, +0xFBC0,0x93FF,0x0000 }; + +uint16 page014data[]= { /* 1400 (3 weights per char) */ +0xFBC0,0x9400,0x0000, 0x1AAE,0x0000,0x0000, 0x1AAF,0x0000,0x0000, +0x1AB0,0x0000,0x0000, 0x1AB1,0x0000,0x0000, 0x1AB2,0x0000,0x0000, +0x1AB3,0x0000,0x0000, 0x1AB4,0x0000,0x0000, 0x1AB5,0x0000,0x0000, +0x1AB6,0x0000,0x0000, 0x1AB7,0x0000,0x0000, 0x1AB8,0x0000,0x0000, +0x1AB9,0x0000,0x0000, 0x1ABA,0x0000,0x0000, 0x1ABB,0x0000,0x0000, +0x1ABC,0x0000,0x0000, 0x1ABD,0x0000,0x0000, 0x1ABE,0x0000,0x0000, +0x1ABF,0x0000,0x0000, 0x1AC0,0x0000,0x0000, 0x1AC1,0x0000,0x0000, +0x1AC2,0x0000,0x0000, 0x1AC3,0x0000,0x0000, 0x1AC4,0x0000,0x0000, +0x1AC5,0x0000,0x0000, 0x1AC6,0x0000,0x0000, 0x1AC7,0x0000,0x0000, +0x1AC8,0x0000,0x0000, 0x1AC9,0x0000,0x0000, 0x1ACA,0x0000,0x0000, +0x1ACB,0x0000,0x0000, 0x1ACC,0x0000,0x0000, 0x1ACD,0x0000,0x0000, +0x1ACE,0x0000,0x0000, 0x1ACF,0x0000,0x0000, 0x1AD0,0x0000,0x0000, +0x1AD1,0x0000,0x0000, 0x1AD2,0x0000,0x0000, 0x1AD3,0x0000,0x0000, +0x1AD4,0x0000,0x0000, 0x1AD5,0x0000,0x0000, 0x1AD6,0x0000,0x0000, +0x1AD7,0x0000,0x0000, 0x1AD8,0x0000,0x0000, 0x1AD9,0x0000,0x0000, +0x1ADA,0x0000,0x0000, 0x1ADB,0x0000,0x0000, 0x1ADC,0x0000,0x0000, +0x1ADD,0x0000,0x0000, 0x1ADE,0x0000,0x0000, 0x1ADF,0x0000,0x0000, +0x1AE0,0x0000,0x0000, 0x1AE1,0x0000,0x0000, 0x1AE2,0x0000,0x0000, +0x1AE3,0x0000,0x0000, 0x1AE4,0x0000,0x0000, 0x1AE5,0x0000,0x0000, +0x1AE6,0x0000,0x0000, 0x1AE7,0x0000,0x0000, 0x1AE8,0x0000,0x0000, +0x1AE9,0x0000,0x0000, 0x1AEA,0x0000,0x0000, 0x1AEB,0x0000,0x0000, +0x1AEC,0x0000,0x0000, 0x1AED,0x0000,0x0000, 0x1AEE,0x0000,0x0000, +0x1AEF,0x0000,0x0000, 0x1AF0,0x0000,0x0000, 0x1AF1,0x0000,0x0000, +0x1AF2,0x0000,0x0000, 0x1AF3,0x0000,0x0000, 0x1AF4,0x0000,0x0000, +0x1AF5,0x0000,0x0000, 0x1AF6,0x0000,0x0000, 0x1AF7,0x0000,0x0000, +0x1AF8,0x0000,0x0000, 0x1AF9,0x0000,0x0000, 0x1AFA,0x0000,0x0000, +0x1AFB,0x0000,0x0000, 0x1AFC,0x0000,0x0000, 0x1AFD,0x0000,0x0000, +0x1AFE,0x0000,0x0000, 0x1AFF,0x0000,0x0000, 0x1B00,0x0000,0x0000, +0x1B01,0x0000,0x0000, 0x1B02,0x0000,0x0000, 0x1B03,0x0000,0x0000, +0x1B04,0x0000,0x0000, 0x1B05,0x0000,0x0000, 0x1B06,0x0000,0x0000, +0x1B07,0x0000,0x0000, 0x1B08,0x0000,0x0000, 0x1B09,0x0000,0x0000, +0x1B0A,0x0000,0x0000, 0x1B0B,0x0000,0x0000, 0x1B0C,0x0000,0x0000, +0x1B0D,0x0000,0x0000, 0x1B0E,0x0000,0x0000, 0x1B0F,0x0000,0x0000, +0x1B10,0x0000,0x0000, 0x1B11,0x0000,0x0000, 0x1B12,0x0000,0x0000, +0x1B13,0x0000,0x0000, 0x1B14,0x0000,0x0000, 0x1B15,0x0000,0x0000, +0x1B16,0x0000,0x0000, 0x1B17,0x0000,0x0000, 0x1B18,0x0000,0x0000, +0x1B19,0x0000,0x0000, 0x1B1A,0x0000,0x0000, 0x1B1B,0x0000,0x0000, +0x1B1C,0x0000,0x0000, 0x1B1D,0x0000,0x0000, 0x1B1E,0x0000,0x0000, +0x1B1F,0x0000,0x0000, 0x1B20,0x0000,0x0000, 0x1B21,0x0000,0x0000, +0x1B22,0x0000,0x0000, 0x1B23,0x0000,0x0000, 0x1B24,0x0000,0x0000, +0x1B25,0x0000,0x0000, 0x1B26,0x0000,0x0000, 0x1B27,0x0000,0x0000, +0x1B28,0x0000,0x0000, 0x1B29,0x0000,0x0000, 0x1B2A,0x0000,0x0000, +0x1B2B,0x0000,0x0000, 0x1B2C,0x0000,0x0000, 0x1B2D,0x0000,0x0000, +0x1B2E,0x0000,0x0000, 0x1B2F,0x0000,0x0000, 0x1B30,0x0000,0x0000, +0x1B31,0x0000,0x0000, 0x1B32,0x0000,0x0000, 0x1B33,0x0000,0x0000, +0x1B34,0x0000,0x0000, 0x1B35,0x0000,0x0000, 0x1B36,0x0000,0x0000, +0x1B37,0x0000,0x0000, 0x1B38,0x0000,0x0000, 0x1B39,0x0000,0x0000, +0x1B3A,0x0000,0x0000, 0x1B3B,0x0000,0x0000, 0x1B3C,0x0000,0x0000, +0x1B3D,0x0000,0x0000, 0x1B3E,0x0000,0x0000, 0x1B3F,0x0000,0x0000, +0x1B40,0x0000,0x0000, 0x1B41,0x0000,0x0000, 0x1B42,0x0000,0x0000, +0x1B43,0x0000,0x0000, 0x1B44,0x0000,0x0000, 0x1B45,0x0000,0x0000, +0x1B46,0x0000,0x0000, 0x1B47,0x0000,0x0000, 0x1B48,0x0000,0x0000, +0x1B49,0x0000,0x0000, 0x1B4A,0x0000,0x0000, 0x1B4B,0x0000,0x0000, +0x1B4C,0x0000,0x0000, 0x1B4D,0x0000,0x0000, 0x1B4E,0x0000,0x0000, +0x1B4F,0x0000,0x0000, 0x1B50,0x0000,0x0000, 0x1B51,0x0000,0x0000, +0x1B52,0x0000,0x0000, 0x1B53,0x0000,0x0000, 0x1B54,0x0000,0x0000, +0x1B55,0x0000,0x0000, 0x1B56,0x0000,0x0000, 0x1B57,0x0000,0x0000, +0x1B58,0x0000,0x0000, 0x1B59,0x0000,0x0000, 0x1B5A,0x0000,0x0000, +0x1B5B,0x0000,0x0000, 0x1B5C,0x0000,0x0000, 0x1B5D,0x0000,0x0000, +0x1B5E,0x0000,0x0000, 0x1B5F,0x0000,0x0000, 0x1B60,0x0000,0x0000, +0x1B61,0x0000,0x0000, 0x1B62,0x0000,0x0000, 0x1B63,0x0000,0x0000, +0x1B64,0x0000,0x0000, 0x1B65,0x0000,0x0000, 0x1B66,0x0000,0x0000, +0x1B67,0x0000,0x0000, 0x1B68,0x0000,0x0000, 0x1B69,0x0000,0x0000, +0x1B6A,0x0000,0x0000, 0x1B6B,0x0000,0x0000, 0x1B6C,0x0000,0x0000, +0x1B6D,0x0000,0x0000, 0x1B6E,0x0000,0x0000, 0x1B6F,0x0000,0x0000, +0x1B70,0x0000,0x0000, 0x1B71,0x0000,0x0000, 0x1B72,0x0000,0x0000, +0x1B73,0x0000,0x0000, 0x1B74,0x0000,0x0000, 0x1B75,0x0000,0x0000, +0x1B76,0x0000,0x0000, 0x1B77,0x0000,0x0000, 0x1B78,0x0000,0x0000, +0x1B79,0x0000,0x0000, 0x1B7A,0x0000,0x0000, 0x1B7B,0x0000,0x0000, +0x1B7C,0x0000,0x0000, 0x1B7D,0x0000,0x0000, 0x1B7E,0x0000,0x0000, +0x1B7F,0x0000,0x0000, 0x1B80,0x0000,0x0000, 0x1B81,0x0000,0x0000, +0x1B82,0x0000,0x0000, 0x1B83,0x0000,0x0000, 0x1B84,0x0000,0x0000, +0x1B85,0x0000,0x0000, 0x1B86,0x0000,0x0000, 0x1B87,0x0000,0x0000, +0x1B88,0x0000,0x0000, 0x1B89,0x0000,0x0000, 0x1B8A,0x0000,0x0000, +0x1B8B,0x0000,0x0000, 0x1B8C,0x0000,0x0000, 0x1B8D,0x0000,0x0000, +0x1B8E,0x0000,0x0000, 0x1B8F,0x0000,0x0000, 0x1B90,0x0000,0x0000, +0x1B91,0x0000,0x0000, 0x1B92,0x0000,0x0000, 0x1B93,0x0000,0x0000, +0x1B94,0x0000,0x0000, 0x1B95,0x0000,0x0000, 0x1B96,0x0000,0x0000, +0x1B97,0x0000,0x0000, 0x1B98,0x0000,0x0000, 0x1B99,0x0000,0x0000, +0x1B9A,0x0000,0x0000, 0x1B9B,0x0000,0x0000, 0x1B9C,0x0000,0x0000, +0x1B9D,0x0000,0x0000, 0x1B9E,0x0000,0x0000, 0x1B9F,0x0000,0x0000, +0x1BA0,0x0000,0x0000, 0x1BA1,0x0000,0x0000, 0x1BA2,0x0000,0x0000, +0x1BA3,0x0000,0x0000, 0x1BA4,0x0000,0x0000, 0x1BA5,0x0000,0x0000, +0x1BA6,0x0000,0x0000, 0x1BA7,0x0000,0x0000, 0x1BA8,0x0000,0x0000, +0x1BA9,0x0000,0x0000, 0x1BAA,0x0000,0x0000, 0x1BAB,0x0000,0x0000, +0x1BAC,0x0000,0x0000 }; + +uint16 page015data[]= { /* 1500 (2 weights per char) */ +0x1BAD,0x0000, 0x1BAE,0x0000, 0x1BAF,0x0000, 0x1BB0,0x0000, +0x1BB1,0x0000, 0x1BB2,0x0000, 0x1BB3,0x0000, 0x1BB4,0x0000, +0x1BB5,0x0000, 0x1BB6,0x0000, 0x1BB7,0x0000, 0x1BB8,0x0000, +0x1BB9,0x0000, 0x1BBA,0x0000, 0x1BBB,0x0000, 0x1BBC,0x0000, +0x1BBD,0x0000, 0x1BBE,0x0000, 0x1BBF,0x0000, 0x1BC0,0x0000, +0x1BC1,0x0000, 0x1BC2,0x0000, 0x1BC3,0x0000, 0x1BC4,0x0000, +0x1BC5,0x0000, 0x1BC6,0x0000, 0x1BC7,0x0000, 0x1BC8,0x0000, +0x1BC9,0x0000, 0x1BCA,0x0000, 0x1BCB,0x0000, 0x1BCC,0x0000, +0x1BCD,0x0000, 0x1BCE,0x0000, 0x1BCF,0x0000, 0x1BD0,0x0000, +0x1BD1,0x0000, 0x1BD2,0x0000, 0x1BD3,0x0000, 0x1BD4,0x0000, +0x1BD5,0x0000, 0x1BD6,0x0000, 0x1BD7,0x0000, 0x1BD8,0x0000, +0x1BD9,0x0000, 0x1BDA,0x0000, 0x1BDB,0x0000, 0x1BDC,0x0000, +0x1BDD,0x0000, 0x1BDE,0x0000, 0x1BDF,0x0000, 0x1BE0,0x0000, +0x1BE1,0x0000, 0x1BE2,0x0000, 0x1BE3,0x0000, 0x1BE4,0x0000, +0x1BE5,0x0000, 0x1BE6,0x0000, 0x1BE7,0x0000, 0x1BE8,0x0000, +0x1BE9,0x0000, 0x1BEA,0x0000, 0x1BEB,0x0000, 0x1BEC,0x0000, +0x1BED,0x0000, 0x1BEE,0x0000, 0x1BEF,0x0000, 0x1BF0,0x0000, +0x1BF1,0x0000, 0x1BF2,0x0000, 0x1BF3,0x0000, 0x1BF4,0x0000, +0x1BF5,0x0000, 0x1BF6,0x0000, 0x1BF7,0x0000, 0x1BF8,0x0000, +0x1BF9,0x0000, 0x1BFA,0x0000, 0x1BFB,0x0000, 0x1BFC,0x0000, +0x1BFD,0x0000, 0x1BFE,0x0000, 0x1BFF,0x0000, 0x1C00,0x0000, +0x1C01,0x0000, 0x1C02,0x0000, 0x1C03,0x0000, 0x1C04,0x0000, +0x1C05,0x0000, 0x1C06,0x0000, 0x1C07,0x0000, 0x1C08,0x0000, +0x1C09,0x0000, 0x1C0A,0x0000, 0x1C0B,0x0000, 0x1C0C,0x0000, +0x1C0D,0x0000, 0x1C0E,0x0000, 0x1C0F,0x0000, 0x1C10,0x0000, +0x1C11,0x0000, 0x1C12,0x0000, 0x1C13,0x0000, 0x1C14,0x0000, +0x1C15,0x0000, 0x1C16,0x0000, 0x1C17,0x0000, 0x1C18,0x0000, +0x1C19,0x0000, 0x1C1A,0x0000, 0x1C1B,0x0000, 0x1C1C,0x0000, +0x1C1D,0x0000, 0x1C1E,0x0000, 0x1C1F,0x0000, 0x1C20,0x0000, +0x1C21,0x0000, 0x1C22,0x0000, 0x1C23,0x0000, 0x1C24,0x0000, +0x1C25,0x0000, 0x1C26,0x0000, 0x1C27,0x0000, 0x1C28,0x0000, +0x1C5B,0x0000, 0x1C29,0x0000, 0x1C2B,0x0000, 0x1C2C,0x0000, +0x1C2D,0x0000, 0x1C2E,0x0000, 0x1C2F,0x0000, 0x1C30,0x0000, +0x1C31,0x0000, 0x1C32,0x0000, 0x1C33,0x0000, 0x1C34,0x0000, +0x1C35,0x0000, 0x1C36,0x0000, 0x1C37,0x0000, 0x1C38,0x0000, +0x1C39,0x0000, 0x1C3A,0x0000, 0x1C3C,0x0000, 0x1C3D,0x0000, +0x1C3E,0x0000, 0x1C3F,0x0000, 0x1C40,0x0000, 0x1C41,0x0000, +0x1C42,0x0000, 0x1C43,0x0000, 0x1C4A,0x0000, 0x1C4B,0x0000, +0x1C4C,0x0000, 0x1C4D,0x0000, 0x1C4E,0x0000, 0x1C4F,0x0000, +0x1C50,0x0000, 0x1C51,0x0000, 0x1C52,0x0000, 0x1C53,0x0000, +0x1C54,0x0000, 0x1C55,0x0000, 0x1C56,0x0000, 0x1C57,0x0000, +0x1C58,0x0000, 0x1C59,0x0000, 0x1C5A,0x0000, 0x1C5C,0x0000, +0x1C5D,0x0000, 0x1C5E,0x0000, 0x1C5F,0x0000, 0x1C60,0x0000, +0x1C61,0x0000, 0x1C62,0x0000, 0x1C63,0x0000, 0x1C64,0x0000, +0x1C65,0x0000, 0x1C66,0x0000, 0x1C67,0x0000, 0x1C68,0x0000, +0x1C69,0x0000, 0x1C6A,0x0000, 0x1C6B,0x0000, 0x1C6C,0x0000, +0x1C6D,0x0000, 0x1C6E,0x0000, 0x1C6F,0x0000, 0x1C70,0x0000, +0x1C71,0x0000, 0x1C72,0x0000, 0x1C73,0x0000, 0x1C74,0x0000, +0x1C75,0x0000, 0x1C76,0x0000, 0x1C77,0x0000, 0x1C78,0x0000, +0x1C79,0x0000, 0x1C7A,0x0000, 0x1C7B,0x0000, 0x1C7C,0x0000, +0x1C7D,0x0000, 0x1C7E,0x0000, 0x1C7F,0x0000, 0x1C80,0x0000, +0x1C81,0x0000, 0x1C82,0x0000, 0x1C83,0x0000, 0x1C84,0x0000, +0x1C85,0x0000, 0x1C86,0x0000, 0x1C87,0x0000, 0x1C88,0x0000, +0x1C89,0x0000, 0x1C8A,0x0000, 0x1C8B,0x0000, 0x1C8C,0x0000, +0x1C8D,0x0000, 0x1C8E,0x0000, 0x1C8F,0x0000, 0x1C90,0x0000, +0x1C91,0x0000, 0x1C92,0x0000, 0x1C93,0x0000, 0x1C94,0x0000, +0x1C95,0x0000, 0x1C96,0x0000, 0x1C97,0x0000, 0x1C98,0x0000, +0x1C99,0x0000, 0x1C9A,0x0000, 0x1C9B,0x0000, 0x1C9C,0x0000, +0x1C9D,0x0000, 0x1C9E,0x0000, 0x1C9F,0x0000, 0x1CA0,0x0000, +0x1CA1,0x0000, 0x1CA2,0x0000, 0x1CA3,0x0000, 0x1CA4,0x0000, +0x1CA5,0x0000, 0x1CA6,0x0000, 0x1CA7,0x0000, 0x1CA8,0x0000, +0x1CA9,0x0000, 0x1CAA,0x0000, 0x1CAB,0x0000, 0x1CAC,0x0000, +0x1CAD,0x0000, 0x1CAE,0x0000, 0x1CAF,0x0000, 0x1CB0,0x0000, +0x1CB1,0x0000, 0x1CB2,0x0000, 0x1CB3,0x0000, 0x1CB4,0x0000 +}; + +uint16 page016data[]= { /* 1600 (3 weights per char) */ +0x1CB5,0x0000,0x0000, 0x1CB6,0x0000,0x0000, 0x1CB7,0x0000,0x0000, +0x1CB8,0x0000,0x0000, 0x1CB9,0x0000,0x0000, 0x1CBA,0x0000,0x0000, +0x1CBB,0x0000,0x0000, 0x1CBC,0x0000,0x0000, 0x1CBD,0x0000,0x0000, +0x1CBE,0x0000,0x0000, 0x1CBF,0x0000,0x0000, 0x1CC0,0x0000,0x0000, +0x1CC1,0x0000,0x0000, 0x1CC2,0x0000,0x0000, 0x1CC3,0x0000,0x0000, +0x1CC4,0x0000,0x0000, 0x1CC5,0x0000,0x0000, 0x1CC6,0x0000,0x0000, +0x1CC7,0x0000,0x0000, 0x1CC8,0x0000,0x0000, 0x1CC9,0x0000,0x0000, +0x1CCA,0x0000,0x0000, 0x1CCB,0x0000,0x0000, 0x1CCC,0x0000,0x0000, +0x1CCD,0x0000,0x0000, 0x1CCE,0x0000,0x0000, 0x1CCF,0x0000,0x0000, +0x1CD0,0x0000,0x0000, 0x1CD1,0x0000,0x0000, 0x1CD2,0x0000,0x0000, +0x1CD3,0x0000,0x0000, 0x1CD4,0x0000,0x0000, 0x1CD5,0x0000,0x0000, +0x1CD6,0x0000,0x0000, 0x1CD7,0x0000,0x0000, 0x1CD8,0x0000,0x0000, +0x1CD9,0x0000,0x0000, 0x1CDA,0x0000,0x0000, 0x1CDB,0x0000,0x0000, +0x1CDC,0x0000,0x0000, 0x1CDD,0x0000,0x0000, 0x1CDE,0x0000,0x0000, +0x1CDF,0x0000,0x0000, 0x1CE0,0x0000,0x0000, 0x1CE1,0x0000,0x0000, +0x1CE2,0x0000,0x0000, 0x1CE3,0x0000,0x0000, 0x1CE4,0x0000,0x0000, +0x1CE5,0x0000,0x0000, 0x1CE6,0x0000,0x0000, 0x1CE7,0x0000,0x0000, +0x1CE8,0x0000,0x0000, 0x1CE9,0x0000,0x0000, 0x1CEA,0x0000,0x0000, +0x1CEB,0x0000,0x0000, 0x1CEC,0x0000,0x0000, 0x1CED,0x0000,0x0000, +0x1CEE,0x0000,0x0000, 0x1CEF,0x0000,0x0000, 0x1CF0,0x0000,0x0000, +0x1CF1,0x0000,0x0000, 0x1CF2,0x0000,0x0000, 0x1CF3,0x0000,0x0000, +0x1CF4,0x0000,0x0000, 0x1CF5,0x0000,0x0000, 0x1CF6,0x0000,0x0000, +0x1CF7,0x0000,0x0000, 0x1CF8,0x0000,0x0000, 0x1CF9,0x0000,0x0000, +0x1CFA,0x0000,0x0000, 0x1CFB,0x0000,0x0000, 0x1CFC,0x0000,0x0000, +0x1CFD,0x0000,0x0000, 0x1CFE,0x0000,0x0000, 0x1CFF,0x0000,0x0000, +0x1D00,0x0000,0x0000, 0x1D01,0x0000,0x0000, 0x1D02,0x0000,0x0000, +0x1D03,0x0000,0x0000, 0x1D04,0x0000,0x0000, 0x1D05,0x0000,0x0000, +0x1D06,0x0000,0x0000, 0x1D07,0x0000,0x0000, 0x1D08,0x0000,0x0000, +0x1D09,0x0000,0x0000, 0x1D0A,0x0000,0x0000, 0x1D0B,0x0000,0x0000, +0x1D0C,0x0000,0x0000, 0x1D0D,0x0000,0x0000, 0x1D0E,0x0000,0x0000, +0x1D0F,0x0000,0x0000, 0x1D10,0x0000,0x0000, 0x1D11,0x0000,0x0000, +0x1D12,0x0000,0x0000, 0x1D13,0x0000,0x0000, 0x1D14,0x0000,0x0000, +0x1D15,0x0000,0x0000, 0x1D16,0x0000,0x0000, 0x1D17,0x0000,0x0000, +0x1D18,0x0000,0x0000, 0x1D19,0x0000,0x0000, 0x1D1A,0x0000,0x0000, +0x1D1B,0x0000,0x0000, 0x1D1C,0x0000,0x0000, 0x1D1D,0x0000,0x0000, +0x1D1E,0x0000,0x0000, 0x1D1F,0x0000,0x0000, 0x1D20,0x0000,0x0000, +0x1D21,0x0000,0x0000, 0x0316,0x0000,0x0000, 0x0265,0x0000,0x0000, +0x1C2A,0x0000,0x0000, 0x1C3B,0x0000,0x0000, 0x1C44,0x0000,0x0000, +0x1C45,0x0000,0x0000, 0x1C46,0x0000,0x0000, 0x1C47,0x0000,0x0000, +0x1C48,0x0000,0x0000, 0x1C49,0x0000,0x0000, 0xFBC0,0x9677,0x0000, +0xFBC0,0x9678,0x0000, 0xFBC0,0x9679,0x0000, 0xFBC0,0x967A,0x0000, +0xFBC0,0x967B,0x0000, 0xFBC0,0x967C,0x0000, 0xFBC0,0x967D,0x0000, +0xFBC0,0x967E,0x0000, 0xFBC0,0x967F,0x0000, 0x020A,0x0000,0x0000, +0x1D22,0x0000,0x0000, 0x1D23,0x0000,0x0000, 0x1D24,0x0000,0x0000, +0x1D25,0x0000,0x0000, 0x1D26,0x0000,0x0000, 0x1D27,0x0000,0x0000, +0x1D28,0x0000,0x0000, 0x1D29,0x0000,0x0000, 0x1D2A,0x0000,0x0000, +0x1D2B,0x0000,0x0000, 0x1D2C,0x0000,0x0000, 0x1D2D,0x0000,0x0000, +0x1D2E,0x0000,0x0000, 0x1D2F,0x0000,0x0000, 0x1D30,0x0000,0x0000, +0x1D31,0x0000,0x0000, 0x1D32,0x0000,0x0000, 0x1D33,0x0000,0x0000, +0x1D34,0x0000,0x0000, 0x1D35,0x0000,0x0000, 0x1D36,0x0000,0x0000, +0x1D37,0x0000,0x0000, 0x1D38,0x0000,0x0000, 0x1D39,0x0000,0x0000, +0x1D3A,0x0000,0x0000, 0x1D3B,0x0000,0x0000, 0x0292,0x0000,0x0000, +0x0293,0x0000,0x0000, 0xFBC0,0x969D,0x0000, 0xFBC0,0x969E,0x0000, +0xFBC0,0x969F,0x0000, 0x1D3C,0x0000,0x0000, 0x1D3C,0x0000,0x0000, +0x1D3D,0x0000,0x0000, 0x1D59,0x0000,0x0000, 0x1D3D,0x0000,0x0000, +0x1D3D,0x0000,0x0000, 0x1D3E,0x0000,0x0000, 0x1D3E,0x0000,0x0000, +0x1D3F,0x0000,0x0000, 0x1D3F,0x0000,0x0000, 0x1D57,0x0000,0x0000, +0x1D58,0x0000,0x0000, 0x1D3F,0x0000,0x0000, 0x1D3F,0x0000,0x0000, +0x1D3F,0x0000,0x0000, 0x1D40,0x0000,0x0000, 0x1D41,0x0000,0x0000, +0x1D42,0x0000,0x0000, 0x1D43,0x0000,0x0000, 0x1D43,0x0000,0x0000, +0x1D43,0x0000,0x0000, 0x1D43,0x0000,0x0000, 0x1D43,0x0000,0x0000, +0x1D44,0x0000,0x0000, 0x1D5C,0x0000,0x0000, 0x1D45,0x0000,0x0000, +0x1D46,0x0000,0x0000, 0x1D46,0x0000,0x0000, 0x1D46,0x0000,0x0000, +0x1D46,0x0000,0x0000, 0x1D47,0x0000,0x0000, 0x1D47,0x0000,0x0000, +0x1D47,0x0000,0x0000, 0x1D48,0x0000,0x0000, 0x1D48,0x0000,0x0000, +0x1D49,0x0000,0x0000, 0x1D49,0x0000,0x0000, 0x1D4A,0x0000,0x0000, +0x1D4A,0x0000,0x0000, 0x1D4B,0x0000,0x0000, 0x1D4C,0x0000,0x0000, +0x1D4D,0x0000,0x0000, 0x1D4E,0x0000,0x0000, 0x1D4E,0x0000,0x0000, +0x1D4E,0x0000,0x0000, 0x1D4E,0x0000,0x0000, 0x1D4E,0x0000,0x0000, +0x1D4F,0x0000,0x0000, 0x1D4F,0x0000,0x0000, 0x1D4F,0x0000,0x0000, +0x1D50,0x0000,0x0000, 0x1D50,0x0000,0x0000, 0x1D50,0x0000,0x0000, +0x1D4C,0x0000,0x0000, 0x1D51,0x0000,0x0000, 0x1D52,0x0000,0x0000, +0x1D52,0x0000,0x0000, 0x1D52,0x0000,0x0000, 0x1D53,0x0000,0x0000, +0x1D53,0x0000,0x0000, 0x1D54,0x0000,0x0000, 0x1D54,0x0000,0x0000, +0x1D55,0x0000,0x0000, 0x1D56,0x0000,0x0000, 0x1D5A,0x0000,0x0000, +0x1D5E,0x0000,0x0000, 0x1D5F,0x0000,0x0000, 0x1D5B,0x0000,0x0000, +0x1D5D,0x0000,0x0000, 0x1D60,0x0000,0x0000, 0x1D61,0x0000,0x0000, +0x1D61,0x0000,0x0000, 0x1D61,0x0000,0x0000, 0x1D45,0x0000,0x0000, +0x1D4E,0x0000,0x0000, 0x024E,0x0000,0x0000, 0x024F,0x0000,0x0000, +0x0250,0x0000,0x0000, 0x1D4A,0x1D53,0x0000, 0x1D52,0x1D52,0x0000, +0x1D3E,0x1D3E,0x0000, 0xFBC0,0x96F1,0x0000, 0xFBC0,0x96F2,0x0000, +0xFBC0,0x96F3,0x0000, 0xFBC0,0x96F4,0x0000, 0xFBC0,0x96F5,0x0000, +0xFBC0,0x96F6,0x0000, 0xFBC0,0x96F7,0x0000, 0xFBC0,0x96F8,0x0000, +0xFBC0,0x96F9,0x0000, 0xFBC0,0x96FA,0x0000, 0xFBC0,0x96FB,0x0000, +0xFBC0,0x96FC,0x0000, 0xFBC0,0x96FD,0x0000, 0xFBC0,0x96FE,0x0000, +0xFBC0,0x96FF,0x0000 }; + +uint16 page017data[]= { /* 1700 (3 weights per char) */ +0x18E2,0x0000,0x0000, 0x18E3,0x0000,0x0000, 0x18E4,0x0000,0x0000, +0x18E5,0x0000,0x0000, 0x18E6,0x0000,0x0000, 0x18E7,0x0000,0x0000, +0x18E8,0x0000,0x0000, 0x18E9,0x0000,0x0000, 0x18EA,0x0000,0x0000, +0x18EB,0x0000,0x0000, 0x18EC,0x0000,0x0000, 0x18ED,0x0000,0x0000, +0x18EE,0x0000,0x0000, 0xFBC0,0x970D,0x0000, 0x18EF,0x0000,0x0000, +0x18F0,0x0000,0x0000, 0x18F1,0x0000,0x0000, 0x18F2,0x0000,0x0000, +0x18F3,0x0000,0x0000, 0x18F4,0x0000,0x0000, 0x18F5,0x0000,0x0000, +0xFBC0,0x9715,0x0000, 0xFBC0,0x9716,0x0000, 0xFBC0,0x9717,0x0000, +0xFBC0,0x9718,0x0000, 0xFBC0,0x9719,0x0000, 0xFBC0,0x971A,0x0000, +0xFBC0,0x971B,0x0000, 0xFBC0,0x971C,0x0000, 0xFBC0,0x971D,0x0000, +0xFBC0,0x971E,0x0000, 0xFBC0,0x971F,0x0000, 0x18F6,0x0000,0x0000, +0x18F7,0x0000,0x0000, 0x18F8,0x0000,0x0000, 0x18F9,0x0000,0x0000, +0x18FA,0x0000,0x0000, 0x18FB,0x0000,0x0000, 0x18FC,0x0000,0x0000, +0x18FD,0x0000,0x0000, 0x18FE,0x0000,0x0000, 0x18FF,0x0000,0x0000, +0x1900,0x0000,0x0000, 0x1901,0x0000,0x0000, 0x1902,0x0000,0x0000, +0x1903,0x0000,0x0000, 0x1904,0x0000,0x0000, 0x1905,0x0000,0x0000, +0x1906,0x0000,0x0000, 0x1907,0x0000,0x0000, 0x1908,0x0000,0x0000, +0x1909,0x0000,0x0000, 0x190A,0x0000,0x0000, 0x026A,0x0000,0x0000, +0x026B,0x0000,0x0000, 0xFBC0,0x9737,0x0000, 0xFBC0,0x9738,0x0000, +0xFBC0,0x9739,0x0000, 0xFBC0,0x973A,0x0000, 0xFBC0,0x973B,0x0000, +0xFBC0,0x973C,0x0000, 0xFBC0,0x973D,0x0000, 0xFBC0,0x973E,0x0000, +0xFBC0,0x973F,0x0000, 0x190B,0x0000,0x0000, 0x190C,0x0000,0x0000, +0x190D,0x0000,0x0000, 0x190E,0x0000,0x0000, 0x190F,0x0000,0x0000, +0x1910,0x0000,0x0000, 0x1911,0x0000,0x0000, 0x1912,0x0000,0x0000, +0x1913,0x0000,0x0000, 0x1914,0x0000,0x0000, 0x1915,0x0000,0x0000, +0x1916,0x0000,0x0000, 0x1917,0x0000,0x0000, 0x1918,0x0000,0x0000, +0x1919,0x0000,0x0000, 0x191A,0x0000,0x0000, 0x191B,0x0000,0x0000, +0x191C,0x0000,0x0000, 0x191D,0x0000,0x0000, 0x191E,0x0000,0x0000, +0xFBC0,0x9754,0x0000, 0xFBC0,0x9755,0x0000, 0xFBC0,0x9756,0x0000, +0xFBC0,0x9757,0x0000, 0xFBC0,0x9758,0x0000, 0xFBC0,0x9759,0x0000, +0xFBC0,0x975A,0x0000, 0xFBC0,0x975B,0x0000, 0xFBC0,0x975C,0x0000, +0xFBC0,0x975D,0x0000, 0xFBC0,0x975E,0x0000, 0xFBC0,0x975F,0x0000, +0x191F,0x0000,0x0000, 0x1920,0x0000,0x0000, 0x1921,0x0000,0x0000, +0x1922,0x0000,0x0000, 0x1923,0x0000,0x0000, 0x1924,0x0000,0x0000, +0x1925,0x0000,0x0000, 0x1926,0x0000,0x0000, 0x1927,0x0000,0x0000, +0x1928,0x0000,0x0000, 0x1929,0x0000,0x0000, 0x192A,0x0000,0x0000, +0x192B,0x0000,0x0000, 0xFBC0,0x976D,0x0000, 0x192C,0x0000,0x0000, +0x192D,0x0000,0x0000, 0x192E,0x0000,0x0000, 0xFBC0,0x9771,0x0000, +0x192F,0x0000,0x0000, 0x1930,0x0000,0x0000, 0xFBC0,0x9774,0x0000, +0xFBC0,0x9775,0x0000, 0xFBC0,0x9776,0x0000, 0xFBC0,0x9777,0x0000, +0xFBC0,0x9778,0x0000, 0xFBC0,0x9779,0x0000, 0xFBC0,0x977A,0x0000, +0xFBC0,0x977B,0x0000, 0xFBC0,0x977C,0x0000, 0xFBC0,0x977D,0x0000, +0xFBC0,0x977E,0x0000, 0xFBC0,0x977F,0x0000, 0x196C,0x0000,0x0000, +0x196D,0x0000,0x0000, 0x196E,0x0000,0x0000, 0x196F,0x0000,0x0000, +0x1970,0x0000,0x0000, 0x1971,0x0000,0x0000, 0x1972,0x0000,0x0000, +0x1973,0x0000,0x0000, 0x1974,0x0000,0x0000, 0x1975,0x0000,0x0000, +0x1976,0x0000,0x0000, 0x1977,0x0000,0x0000, 0x1978,0x0000,0x0000, +0x1979,0x0000,0x0000, 0x197A,0x0000,0x0000, 0x197B,0x0000,0x0000, +0x197C,0x0000,0x0000, 0x197D,0x0000,0x0000, 0x197E,0x0000,0x0000, +0x197F,0x0000,0x0000, 0x1980,0x0000,0x0000, 0x1981,0x0000,0x0000, +0x1982,0x0000,0x0000, 0x1983,0x0000,0x0000, 0x1984,0x0000,0x0000, +0x1985,0x0000,0x0000, 0x1986,0x0000,0x0000, 0x1987,0x0000,0x0000, +0x1988,0x0000,0x0000, 0x1989,0x0000,0x0000, 0x198A,0x0000,0x0000, +0x198B,0x0000,0x0000, 0x198C,0x0000,0x0000, 0x198D,0x0000,0x0000, +0x198E,0x0000,0x0000, 0x1990,0x0000,0x0000, 0x1991,0x0000,0x0000, +0x1992,0x0000,0x0000, 0x1993,0x0000,0x0000, 0x1994,0x0000,0x0000, +0x1995,0x0000,0x0000, 0x1996,0x0000,0x0000, 0x1997,0x0000,0x0000, +0x1998,0x0000,0x0000, 0x1999,0x0000,0x0000, 0x199A,0x0000,0x0000, +0x199B,0x0000,0x0000, 0x199C,0x0000,0x0000, 0x199D,0x0000,0x0000, +0x199E,0x0000,0x0000, 0x199F,0x0000,0x0000, 0x19A0,0x0000,0x0000, +0x19A1,0x0000,0x0000, 0x19A2,0x0000,0x0000, 0x19A3,0x0000,0x0000, +0x19A4,0x0000,0x0000, 0x19A5,0x0000,0x0000, 0x19A6,0x0000,0x0000, +0x19A7,0x0000,0x0000, 0x19A8,0x0000,0x0000, 0x19A9,0x0000,0x0000, +0x19AA,0x0000,0x0000, 0x19AB,0x0000,0x0000, 0x19AC,0x0000,0x0000, +0x19AD,0x0000,0x0000, 0x19AE,0x0000,0x0000, 0x19AF,0x0000,0x0000, +0x19B0,0x0000,0x0000, 0x19B1,0x0000,0x0000, 0x19B2,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x19B3,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x026E,0x0000,0x0000, +0x026F,0x0000,0x0000, 0x024D,0x0000,0x0000, 0x0312,0x0000,0x0000, +0x0313,0x0000,0x0000, 0x0314,0x0000,0x0000, 0x0315,0x0000,0x0000, +0x0E17,0x0000,0x0000, 0x198F,0x0000,0x0000, 0x0000,0x0000,0x0000, +0xFBC0,0x97DE,0x0000, 0xFBC0,0x97DF,0x0000, 0x0E29,0x0000,0x0000, +0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, 0x0E2C,0x0000,0x0000, +0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, 0x0E2F,0x0000,0x0000, +0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, 0x0E32,0x0000,0x0000, +0xFBC0,0x97EA,0x0000, 0xFBC0,0x97EB,0x0000, 0xFBC0,0x97EC,0x0000, +0xFBC0,0x97ED,0x0000, 0xFBC0,0x97EE,0x0000, 0xFBC0,0x97EF,0x0000, +0x0E29,0x0000,0x0000, 0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, +0x0E2C,0x0000,0x0000, 0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, +0x0E2F,0x0000,0x0000, 0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, +0x0E32,0x0000,0x0000, 0xFBC0,0x97FA,0x0000, 0xFBC0,0x97FB,0x0000, +0xFBC0,0x97FC,0x0000, 0xFBC0,0x97FD,0x0000, 0xFBC0,0x97FE,0x0000, +0xFBC0,0x97FF,0x0000 }; + +uint16 page018data[]= { /* 1800 (3 weights per char) */ +0x02F8,0x0000,0x0000, 0x025E,0x0000,0x0000, 0x0235,0x0000,0x0000, +0x0263,0x0000,0x0000, 0x024A,0x0000,0x0000, 0x024B,0x0000,0x0000, +0x0223,0x0000,0x0000, 0x0224,0x0000,0x0000, 0x0236,0x0000,0x0000, +0x0264,0x0000,0x0000, 0x02F9,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0xFBC0,0x980F,0x0000, 0x0E29,0x0000,0x0000, 0x0E2A,0x0000,0x0000, +0x0E2B,0x0000,0x0000, 0x0E2C,0x0000,0x0000, 0x0E2D,0x0000,0x0000, +0x0E2E,0x0000,0x0000, 0x0E2F,0x0000,0x0000, 0x0E30,0x0000,0x0000, +0x0E31,0x0000,0x0000, 0x0E32,0x0000,0x0000, 0xFBC0,0x981A,0x0000, +0xFBC0,0x981B,0x0000, 0xFBC0,0x981C,0x0000, 0xFBC0,0x981D,0x0000, +0xFBC0,0x981E,0x0000, 0xFBC0,0x981F,0x0000, 0x19DF,0x0000,0x0000, +0x19E1,0x0000,0x0000, 0x19E4,0x0000,0x0000, 0x19EA,0x0000,0x0000, +0x19EC,0x0000,0x0000, 0x19EF,0x0000,0x0000, 0x19F1,0x0000,0x0000, +0x19F4,0x0000,0x0000, 0x19F5,0x0000,0x0000, 0x19F6,0x0000,0x0000, +0x19FB,0x0000,0x0000, 0x19FD,0x0000,0x0000, 0x1A00,0x0000,0x0000, +0x1A02,0x0000,0x0000, 0x1A07,0x0000,0x0000, 0x1A09,0x0000,0x0000, +0x1A0A,0x0000,0x0000, 0x1A0B,0x0000,0x0000, 0x1A12,0x0000,0x0000, +0x1A15,0x0000,0x0000, 0x1A18,0x0000,0x0000, 0x1A1D,0x0000,0x0000, +0x1A21,0x0000,0x0000, 0x1A24,0x0000,0x0000, 0x1A26,0x0000,0x0000, +0x1A28,0x0000,0x0000, 0x1A2B,0x0000,0x0000, 0x1A30,0x0000,0x0000, +0x1A31,0x0000,0x0000, 0x1A34,0x0000,0x0000, 0x1A38,0x0000,0x0000, +0x1A3B,0x0000,0x0000, 0x1A3C,0x0000,0x0000, 0x1A3D,0x0000,0x0000, +0x1A3E,0x0000,0x0000, 0x19DE,0x0000,0x0000, 0x19E2,0x0000,0x0000, +0x19E5,0x0000,0x0000, 0x19EB,0x0000,0x0000, 0x19ED,0x0000,0x0000, +0x19F0,0x0000,0x0000, 0x19F2,0x0000,0x0000, 0x19F7,0x0000,0x0000, +0x19FC,0x0000,0x0000, 0x19FE,0x0000,0x0000, 0x1A01,0x0000,0x0000, +0x1A03,0x0000,0x0000, 0x1A08,0x0000,0x0000, 0x1A13,0x0000,0x0000, +0x1A16,0x0000,0x0000, 0x1A19,0x0000,0x0000, 0x1A1E,0x0000,0x0000, +0x1A32,0x0000,0x0000, 0x1A22,0x0000,0x0000, 0x1A27,0x0000,0x0000, +0x1A2C,0x0000,0x0000, 0x1A36,0x0000,0x0000, 0x1A39,0x0000,0x0000, +0x1A3F,0x0000,0x0000, 0x1A40,0x0000,0x0000, 0x1A1B,0x0000,0x0000, +0x19E3,0x0000,0x0000, 0x19E6,0x0000,0x0000, 0x19E9,0x0000,0x0000, +0x19F3,0x0000,0x0000, 0x19EE,0x0000,0x0000, 0x19F8,0x0000,0x0000, +0x1A2D,0x0000,0x0000, 0x1A04,0x0000,0x0000, 0x1A06,0x0000,0x0000, +0x19FF,0x0000,0x0000, 0x1A0C,0x0000,0x0000, 0x1A14,0x0000,0x0000, +0x1A17,0x0000,0x0000, 0x1A1F,0x0000,0x0000, 0x1A29,0x0000,0x0000, +0x1A37,0x0000,0x0000, 0x1A3A,0x0000,0x0000, 0x1A33,0x0000,0x0000, +0x1A35,0x0000,0x0000, 0x1A41,0x0000,0x0000, 0x1A1A,0x0000,0x0000, +0x1A23,0x0000,0x0000, 0x19E7,0x0000,0x0000, 0x1A2E,0x0000,0x0000, +0x1A25,0x0000,0x0000, 0x1A2A,0x0000,0x0000, 0x1A20,0x0000,0x0000, +0xFBC0,0x9878,0x0000, 0xFBC0,0x9879,0x0000, 0xFBC0,0x987A,0x0000, +0xFBC0,0x987B,0x0000, 0xFBC0,0x987C,0x0000, 0xFBC0,0x987D,0x0000, +0xFBC0,0x987E,0x0000, 0xFBC0,0x987F,0x0000, 0x19D7,0x0000,0x0000, +0x19D8,0x0000,0x0000, 0x19D9,0x0000,0x0000, 0x19DA,0x0000,0x0000, +0x19DB,0x0000,0x0000, 0x19DC,0x0000,0x0000, 0x19DD,0x0000,0x0000, +0x19E0,0x0000,0x0000, 0x19E8,0x0000,0x0000, 0x1A2F,0x0000,0x0000, +0x19F9,0x0000,0x0000, 0x1A1C,0x0000,0x0000, 0x1A42,0x0000,0x0000, +0x1A44,0x0000,0x0000, 0x1A45,0x0000,0x0000, 0x1A47,0x0000,0x0000, +0x1A48,0x0000,0x0000, 0x1A4B,0x0000,0x0000, 0x1A4D,0x0000,0x0000, +0x1A4E,0x0000,0x0000, 0x1A50,0x0000,0x0000, 0x1A52,0x0000,0x0000, +0x1A54,0x0000,0x0000, 0x1A55,0x0000,0x0000, 0x1A49,0x0000,0x0000, +0x1A53,0x0000,0x0000, 0x1A05,0x0000,0x0000, 0x19FA,0x0000,0x0000, +0x1A0D,0x0000,0x0000, 0x1A0E,0x0000,0x0000, 0x1A43,0x0000,0x0000, +0x1A46,0x0000,0x0000, 0x1A4A,0x0000,0x0000, 0x1A4C,0x0000,0x0000, +0x1A0F,0x0000,0x0000, 0x1A51,0x0000,0x0000, 0x1A10,0x0000,0x0000, +0x1A11,0x0000,0x0000, 0x1A56,0x0000,0x0000, 0x1A57,0x0000,0x0000, +0x1A4F,0x0000,0x0000, 0x1A58,0x0000,0x0000, 0xFBC0,0x98AA,0x0000, +0xFBC0,0x98AB,0x0000, 0xFBC0,0x98AC,0x0000, 0xFBC0,0x98AD,0x0000, +0xFBC0,0x98AE,0x0000, 0xFBC0,0x98AF,0x0000, 0xFBC0,0x98B0,0x0000, +0xFBC0,0x98B1,0x0000, 0xFBC0,0x98B2,0x0000, 0xFBC0,0x98B3,0x0000, +0xFBC0,0x98B4,0x0000, 0xFBC0,0x98B5,0x0000, 0xFBC0,0x98B6,0x0000, +0xFBC0,0x98B7,0x0000, 0xFBC0,0x98B8,0x0000, 0xFBC0,0x98B9,0x0000, +0xFBC0,0x98BA,0x0000, 0xFBC0,0x98BB,0x0000, 0xFBC0,0x98BC,0x0000, +0xFBC0,0x98BD,0x0000, 0xFBC0,0x98BE,0x0000, 0xFBC0,0x98BF,0x0000, +0xFBC0,0x98C0,0x0000, 0xFBC0,0x98C1,0x0000, 0xFBC0,0x98C2,0x0000, +0xFBC0,0x98C3,0x0000, 0xFBC0,0x98C4,0x0000, 0xFBC0,0x98C5,0x0000, +0xFBC0,0x98C6,0x0000, 0xFBC0,0x98C7,0x0000, 0xFBC0,0x98C8,0x0000, +0xFBC0,0x98C9,0x0000, 0xFBC0,0x98CA,0x0000, 0xFBC0,0x98CB,0x0000, +0xFBC0,0x98CC,0x0000, 0xFBC0,0x98CD,0x0000, 0xFBC0,0x98CE,0x0000, +0xFBC0,0x98CF,0x0000, 0xFBC0,0x98D0,0x0000, 0xFBC0,0x98D1,0x0000, +0xFBC0,0x98D2,0x0000, 0xFBC0,0x98D3,0x0000, 0xFBC0,0x98D4,0x0000, +0xFBC0,0x98D5,0x0000, 0xFBC0,0x98D6,0x0000, 0xFBC0,0x98D7,0x0000, +0xFBC0,0x98D8,0x0000, 0xFBC0,0x98D9,0x0000, 0xFBC0,0x98DA,0x0000, +0xFBC0,0x98DB,0x0000, 0xFBC0,0x98DC,0x0000, 0xFBC0,0x98DD,0x0000, +0xFBC0,0x98DE,0x0000, 0xFBC0,0x98DF,0x0000, 0xFBC0,0x98E0,0x0000, +0xFBC0,0x98E1,0x0000, 0xFBC0,0x98E2,0x0000, 0xFBC0,0x98E3,0x0000, +0xFBC0,0x98E4,0x0000, 0xFBC0,0x98E5,0x0000, 0xFBC0,0x98E6,0x0000, +0xFBC0,0x98E7,0x0000, 0xFBC0,0x98E8,0x0000, 0xFBC0,0x98E9,0x0000, +0xFBC0,0x98EA,0x0000, 0xFBC0,0x98EB,0x0000, 0xFBC0,0x98EC,0x0000, +0xFBC0,0x98ED,0x0000, 0xFBC0,0x98EE,0x0000, 0xFBC0,0x98EF,0x0000, +0xFBC0,0x98F0,0x0000, 0xFBC0,0x98F1,0x0000, 0xFBC0,0x98F2,0x0000, +0xFBC0,0x98F3,0x0000, 0xFBC0,0x98F4,0x0000, 0xFBC0,0x98F5,0x0000, +0xFBC0,0x98F6,0x0000, 0xFBC0,0x98F7,0x0000, 0xFBC0,0x98F8,0x0000, +0xFBC0,0x98F9,0x0000, 0xFBC0,0x98FA,0x0000, 0xFBC0,0x98FB,0x0000, +0xFBC0,0x98FC,0x0000, 0xFBC0,0x98FD,0x0000, 0xFBC0,0x98FE,0x0000, +0xFBC0,0x98FF,0x0000 }; + +uint16 page019data[]= { /* 1900 (3 weights per char) */ +0x18B0,0x0000,0x0000, 0x18B1,0x0000,0x0000, 0x18B2,0x0000,0x0000, +0x18B3,0x0000,0x0000, 0x18B4,0x0000,0x0000, 0x18B5,0x0000,0x0000, +0x18B6,0x0000,0x0000, 0x18B7,0x0000,0x0000, 0x18B8,0x0000,0x0000, +0x18B9,0x0000,0x0000, 0x18BA,0x0000,0x0000, 0x18BB,0x0000,0x0000, +0x18BC,0x0000,0x0000, 0x18BD,0x0000,0x0000, 0x18BE,0x0000,0x0000, +0x18BF,0x0000,0x0000, 0x18C0,0x0000,0x0000, 0x18C1,0x0000,0x0000, +0x18C2,0x0000,0x0000, 0x18C3,0x0000,0x0000, 0x18C4,0x0000,0x0000, +0x18C5,0x0000,0x0000, 0x18C6,0x0000,0x0000, 0x18C7,0x0000,0x0000, +0x18C8,0x0000,0x0000, 0x18C9,0x0000,0x0000, 0x18CA,0x0000,0x0000, +0x18CB,0x0000,0x0000, 0x18CC,0x0000,0x0000, 0xFBC0,0x991D,0x0000, +0xFBC0,0x991E,0x0000, 0xFBC0,0x991F,0x0000, 0x18CD,0x0000,0x0000, +0x18CE,0x0000,0x0000, 0x18CF,0x0000,0x0000, 0x18D0,0x0000,0x0000, +0x18D1,0x0000,0x0000, 0x18D2,0x0000,0x0000, 0x18D3,0x0000,0x0000, +0x18D4,0x0000,0x0000, 0x18D5,0x0000,0x0000, 0x18D6,0x0000,0x0000, +0x18D7,0x0000,0x0000, 0x18D8,0x0000,0x0000, 0xFBC0,0x992C,0x0000, +0xFBC0,0x992D,0x0000, 0xFBC0,0x992E,0x0000, 0xFBC0,0x992F,0x0000, +0x18D9,0x0000,0x0000, 0x18DA,0x0000,0x0000, 0x18DB,0x0000,0x0000, +0x18DC,0x0000,0x0000, 0x18DD,0x0000,0x0000, 0x18DE,0x0000,0x0000, +0x18DF,0x0000,0x0000, 0x18E0,0x0000,0x0000, 0x18E1,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0xFBC0,0x993C,0x0000, 0xFBC0,0x993D,0x0000, 0xFBC0,0x993E,0x0000, +0xFBC0,0x993F,0x0000, 0x030D,0x0000,0x0000, 0xFBC0,0x9941,0x0000, +0xFBC0,0x9942,0x0000, 0xFBC0,0x9943,0x0000, 0x0254,0x0000,0x0000, +0x025B,0x0000,0x0000, 0x0E29,0x0000,0x0000, 0x0E2A,0x0000,0x0000, +0x0E2B,0x0000,0x0000, 0x0E2C,0x0000,0x0000, 0x0E2D,0x0000,0x0000, +0x0E2E,0x0000,0x0000, 0x0E2F,0x0000,0x0000, 0x0E30,0x0000,0x0000, +0x0E31,0x0000,0x0000, 0x0E32,0x0000,0x0000, 0x19B4,0x0000,0x0000, +0x19B5,0x0000,0x0000, 0x19B6,0x0000,0x0000, 0x19B7,0x0000,0x0000, +0x19B8,0x0000,0x0000, 0x19B9,0x0000,0x0000, 0x19BA,0x0000,0x0000, +0x19BB,0x0000,0x0000, 0x19BC,0x0000,0x0000, 0x19BD,0x0000,0x0000, +0x19BE,0x0000,0x0000, 0x19BF,0x0000,0x0000, 0x19C0,0x0000,0x0000, +0x19C1,0x0000,0x0000, 0x19C2,0x0000,0x0000, 0x19C3,0x0000,0x0000, +0x19C4,0x0000,0x0000, 0x19C5,0x0000,0x0000, 0x19C6,0x0000,0x0000, +0x19C7,0x0000,0x0000, 0x19C8,0x0000,0x0000, 0x19C9,0x0000,0x0000, +0x19CA,0x0000,0x0000, 0x19CB,0x0000,0x0000, 0x19CC,0x0000,0x0000, +0x19CD,0x0000,0x0000, 0x19CE,0x0000,0x0000, 0x19CF,0x0000,0x0000, +0x19D0,0x0000,0x0000, 0x19D1,0x0000,0x0000, 0xFBC0,0x996E,0x0000, +0xFBC0,0x996F,0x0000, 0x19D2,0x0000,0x0000, 0x19D3,0x0000,0x0000, +0x19D4,0x0000,0x0000, 0x19D5,0x0000,0x0000, 0x19D6,0x0000,0x0000, +0xFBC0,0x9975,0x0000, 0xFBC0,0x9976,0x0000, 0xFBC0,0x9977,0x0000, +0xFBC0,0x9978,0x0000, 0xFBC0,0x9979,0x0000, 0xFBC0,0x997A,0x0000, +0xFBC0,0x997B,0x0000, 0xFBC0,0x997C,0x0000, 0xFBC0,0x997D,0x0000, +0xFBC0,0x997E,0x0000, 0xFBC0,0x997F,0x0000, 0xFBC0,0x9980,0x0000, +0xFBC0,0x9981,0x0000, 0xFBC0,0x9982,0x0000, 0xFBC0,0x9983,0x0000, +0xFBC0,0x9984,0x0000, 0xFBC0,0x9985,0x0000, 0xFBC0,0x9986,0x0000, +0xFBC0,0x9987,0x0000, 0xFBC0,0x9988,0x0000, 0xFBC0,0x9989,0x0000, +0xFBC0,0x998A,0x0000, 0xFBC0,0x998B,0x0000, 0xFBC0,0x998C,0x0000, +0xFBC0,0x998D,0x0000, 0xFBC0,0x998E,0x0000, 0xFBC0,0x998F,0x0000, +0xFBC0,0x9990,0x0000, 0xFBC0,0x9991,0x0000, 0xFBC0,0x9992,0x0000, +0xFBC0,0x9993,0x0000, 0xFBC0,0x9994,0x0000, 0xFBC0,0x9995,0x0000, +0xFBC0,0x9996,0x0000, 0xFBC0,0x9997,0x0000, 0xFBC0,0x9998,0x0000, +0xFBC0,0x9999,0x0000, 0xFBC0,0x999A,0x0000, 0xFBC0,0x999B,0x0000, +0xFBC0,0x999C,0x0000, 0xFBC0,0x999D,0x0000, 0xFBC0,0x999E,0x0000, +0xFBC0,0x999F,0x0000, 0xFBC0,0x99A0,0x0000, 0xFBC0,0x99A1,0x0000, +0xFBC0,0x99A2,0x0000, 0xFBC0,0x99A3,0x0000, 0xFBC0,0x99A4,0x0000, +0xFBC0,0x99A5,0x0000, 0xFBC0,0x99A6,0x0000, 0xFBC0,0x99A7,0x0000, +0xFBC0,0x99A8,0x0000, 0xFBC0,0x99A9,0x0000, 0xFBC0,0x99AA,0x0000, +0xFBC0,0x99AB,0x0000, 0xFBC0,0x99AC,0x0000, 0xFBC0,0x99AD,0x0000, +0xFBC0,0x99AE,0x0000, 0xFBC0,0x99AF,0x0000, 0xFBC0,0x99B0,0x0000, +0xFBC0,0x99B1,0x0000, 0xFBC0,0x99B2,0x0000, 0xFBC0,0x99B3,0x0000, +0xFBC0,0x99B4,0x0000, 0xFBC0,0x99B5,0x0000, 0xFBC0,0x99B6,0x0000, +0xFBC0,0x99B7,0x0000, 0xFBC0,0x99B8,0x0000, 0xFBC0,0x99B9,0x0000, +0xFBC0,0x99BA,0x0000, 0xFBC0,0x99BB,0x0000, 0xFBC0,0x99BC,0x0000, +0xFBC0,0x99BD,0x0000, 0xFBC0,0x99BE,0x0000, 0xFBC0,0x99BF,0x0000, +0xFBC0,0x99C0,0x0000, 0xFBC0,0x99C1,0x0000, 0xFBC0,0x99C2,0x0000, +0xFBC0,0x99C3,0x0000, 0xFBC0,0x99C4,0x0000, 0xFBC0,0x99C5,0x0000, +0xFBC0,0x99C6,0x0000, 0xFBC0,0x99C7,0x0000, 0xFBC0,0x99C8,0x0000, +0xFBC0,0x99C9,0x0000, 0xFBC0,0x99CA,0x0000, 0xFBC0,0x99CB,0x0000, +0xFBC0,0x99CC,0x0000, 0xFBC0,0x99CD,0x0000, 0xFBC0,0x99CE,0x0000, +0xFBC0,0x99CF,0x0000, 0xFBC0,0x99D0,0x0000, 0xFBC0,0x99D1,0x0000, +0xFBC0,0x99D2,0x0000, 0xFBC0,0x99D3,0x0000, 0xFBC0,0x99D4,0x0000, +0xFBC0,0x99D5,0x0000, 0xFBC0,0x99D6,0x0000, 0xFBC0,0x99D7,0x0000, +0xFBC0,0x99D8,0x0000, 0xFBC0,0x99D9,0x0000, 0xFBC0,0x99DA,0x0000, +0xFBC0,0x99DB,0x0000, 0xFBC0,0x99DC,0x0000, 0xFBC0,0x99DD,0x0000, +0xFBC0,0x99DE,0x0000, 0xFBC0,0x99DF,0x0000, 0x037B,0x0000,0x0000, +0x037C,0x0000,0x0000, 0x037D,0x0000,0x0000, 0x037E,0x0000,0x0000, +0x037F,0x0000,0x0000, 0x0380,0x0000,0x0000, 0x0381,0x0000,0x0000, +0x0382,0x0000,0x0000, 0x0383,0x0000,0x0000, 0x0384,0x0000,0x0000, +0x0385,0x0000,0x0000, 0x0386,0x0000,0x0000, 0x0387,0x0000,0x0000, +0x0388,0x0000,0x0000, 0x0389,0x0000,0x0000, 0x038A,0x0000,0x0000, +0x038B,0x0000,0x0000, 0x038C,0x0000,0x0000, 0x038D,0x0000,0x0000, +0x038E,0x0000,0x0000, 0x038F,0x0000,0x0000, 0x0390,0x0000,0x0000, +0x0391,0x0000,0x0000, 0x0392,0x0000,0x0000, 0x0393,0x0000,0x0000, +0x0394,0x0000,0x0000, 0x0395,0x0000,0x0000, 0x0396,0x0000,0x0000, +0x0397,0x0000,0x0000, 0x0398,0x0000,0x0000, 0x0399,0x0000,0x0000, +0x039A,0x0000,0x0000 }; + +uint16 page01Ddata[]= { /* 1D00 (3 weights per char) */ +0x0E37,0x0000,0x0000, 0x0E3C,0x0000,0x0000, 0x0E3D,0x0000,0x0000, +0x0E57,0x0000,0x0000, 0x0E64,0x0000,0x0000, 0x0E71,0x0000,0x0000, +0x0E8A,0x0000,0x0000, 0x0E8F,0x0000,0x0000, 0x0EA8,0x0000,0x0000, +0x0F07,0x0000,0x0000, 0x0F14,0x0000,0x0000, 0x0F25,0x0000,0x0000, +0x0F3A,0x0000,0x0000, 0x0F5F,0x0000,0x0000, 0x0F6D,0x0000,0x0000, +0x0F86,0x0000,0x0000, 0x0F96,0x0000,0x0000, 0x0F87,0x0000,0x0000, +0x0F97,0x0000,0x0000, 0x0F91,0x0000,0x0000, 0x0F8C,0x0000,0x0000, +0x0FA6,0x0000,0x0000, 0x0F98,0x0000,0x0000, 0x0F99,0x0000,0x0000, +0x0FAB,0x0000,0x0000, 0x0FC8,0x0000,0x0000, 0x0FCD,0x0000,0x0000, +0x1006,0x0000,0x0000, 0x1023,0x0000,0x0000, 0x1024,0x0000,0x0000, +0x1025,0x0000,0x0000, 0x103B,0x0000,0x0000, 0x1048,0x0000,0x0000, +0x1055,0x0000,0x0000, 0x106E,0x0000,0x0000, 0x1083,0x0000,0x0000, +0x10BA,0x0000,0x0000, 0x10BB,0x0000,0x0000, 0x10EB,0x0000,0x0000, +0x10F7,0x0000,0x0000, 0x10FD,0x0000,0x0000, 0x1101,0x0000,0x0000, +0x1108,0x0000,0x0000, 0x11B4,0x0000,0x0000, 0x0E33,0x0000,0x0000, +0x0E38,0x0000,0x0000, 0x0E4A,0x0000,0x0000, 0x0E56,0x0000,0x0000, +0x0E6D,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0E90,0x0000,0x0000, +0x0EC1,0x0000,0x0000, 0x0EE1,0x0000,0x0000, 0x0EFB,0x0000,0x0000, +0x0F10,0x0000,0x0000, 0x0F21,0x0000,0x0000, 0x0F2E,0x0000,0x0000, +0x0F5B,0x0000,0x0000, 0x0F64,0x0000,0x0000, 0x0F6C,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x0FA2,0x0000,0x0000, 0x0FA7,0x0000,0x0000, +0x0FC0,0x0000,0x0000, 0x1002,0x0000,0x0000, 0x101F,0x0000,0x0000, +0x1051,0x0000,0x0000, 0x0E33,0x0000,0x0000, 0x0E3E,0x0000,0x0000, +0x0E42,0x0000,0x0000, 0x0E3D,0x0000,0x0000, 0x0E4A,0x0000,0x0000, +0x0E6D,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0E94,0x0000,0x0000, +0x0E98,0x0000,0x0000, 0x0EA8,0x0000,0x0000, 0x0EC1,0x0000,0x0000, +0x0F07,0x0000,0x0000, 0x0F21,0x0000,0x0000, 0x0F5B,0x0000,0x0000, +0x0F7E,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0F92,0x0000,0x0000, +0x0F98,0x0000,0x0000, 0x0F99,0x0000,0x0000, 0x0FA7,0x0000,0x0000, +0x1002,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x1024,0x0000,0x0000, +0x1037,0x0000,0x0000, 0x1044,0x0000,0x0000, 0x10BB,0x0000,0x0000, +0x10E9,0x0000,0x0000, 0x10EA,0x0000,0x0000, 0x10EC,0x0000,0x0000, +0x1105,0x0000,0x0000, 0x1106,0x0000,0x0000, 0x0EFB,0x0000,0x0000, +0x0FC0,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x1044,0x0000,0x0000, +0x10E9,0x0000,0x0000, 0x10EA,0x0000,0x0000, 0x1100,0x0000,0x0000, +0x1105,0x0000,0x0000, 0x1106,0x0000,0x0000, 0x1026,0x0000,0x0000, +0xFBC0,0x9D6C,0x0000, 0xFBC0,0x9D6D,0x0000, 0xFBC0,0x9D6E,0x0000, +0xFBC0,0x9D6F,0x0000, 0xFBC0,0x9D70,0x0000, 0xFBC0,0x9D71,0x0000, +0xFBC0,0x9D72,0x0000, 0xFBC0,0x9D73,0x0000, 0xFBC0,0x9D74,0x0000, +0xFBC0,0x9D75,0x0000, 0xFBC0,0x9D76,0x0000, 0xFBC0,0x9D77,0x0000, +0xFBC0,0x9D78,0x0000, 0xFBC0,0x9D79,0x0000, 0xFBC0,0x9D7A,0x0000, +0xFBC0,0x9D7B,0x0000, 0xFBC0,0x9D7C,0x0000, 0xFBC0,0x9D7D,0x0000, +0xFBC0,0x9D7E,0x0000, 0xFBC0,0x9D7F,0x0000, 0xFBC0,0x9D80,0x0000, +0xFBC0,0x9D81,0x0000, 0xFBC0,0x9D82,0x0000, 0xFBC0,0x9D83,0x0000, +0xFBC0,0x9D84,0x0000, 0xFBC0,0x9D85,0x0000, 0xFBC0,0x9D86,0x0000, +0xFBC0,0x9D87,0x0000, 0xFBC0,0x9D88,0x0000, 0xFBC0,0x9D89,0x0000, +0xFBC0,0x9D8A,0x0000, 0xFBC0,0x9D8B,0x0000, 0xFBC0,0x9D8C,0x0000, +0xFBC0,0x9D8D,0x0000, 0xFBC0,0x9D8E,0x0000, 0xFBC0,0x9D8F,0x0000, +0xFBC0,0x9D90,0x0000, 0xFBC0,0x9D91,0x0000, 0xFBC0,0x9D92,0x0000, +0xFBC0,0x9D93,0x0000, 0xFBC0,0x9D94,0x0000, 0xFBC0,0x9D95,0x0000, +0xFBC0,0x9D96,0x0000, 0xFBC0,0x9D97,0x0000, 0xFBC0,0x9D98,0x0000, +0xFBC0,0x9D99,0x0000, 0xFBC0,0x9D9A,0x0000, 0xFBC0,0x9D9B,0x0000, +0xFBC0,0x9D9C,0x0000, 0xFBC0,0x9D9D,0x0000, 0xFBC0,0x9D9E,0x0000, +0xFBC0,0x9D9F,0x0000, 0xFBC0,0x9DA0,0x0000, 0xFBC0,0x9DA1,0x0000, +0xFBC0,0x9DA2,0x0000, 0xFBC0,0x9DA3,0x0000, 0xFBC0,0x9DA4,0x0000, +0xFBC0,0x9DA5,0x0000, 0xFBC0,0x9DA6,0x0000, 0xFBC0,0x9DA7,0x0000, +0xFBC0,0x9DA8,0x0000, 0xFBC0,0x9DA9,0x0000, 0xFBC0,0x9DAA,0x0000, +0xFBC0,0x9DAB,0x0000, 0xFBC0,0x9DAC,0x0000, 0xFBC0,0x9DAD,0x0000, +0xFBC0,0x9DAE,0x0000, 0xFBC0,0x9DAF,0x0000, 0xFBC0,0x9DB0,0x0000, +0xFBC0,0x9DB1,0x0000, 0xFBC0,0x9DB2,0x0000, 0xFBC0,0x9DB3,0x0000, +0xFBC0,0x9DB4,0x0000, 0xFBC0,0x9DB5,0x0000, 0xFBC0,0x9DB6,0x0000, +0xFBC0,0x9DB7,0x0000, 0xFBC0,0x9DB8,0x0000, 0xFBC0,0x9DB9,0x0000, +0xFBC0,0x9DBA,0x0000, 0xFBC0,0x9DBB,0x0000, 0xFBC0,0x9DBC,0x0000, +0xFBC0,0x9DBD,0x0000, 0xFBC0,0x9DBE,0x0000, 0xFBC0,0x9DBF,0x0000, +0xFBC0,0x9DC0,0x0000, 0xFBC0,0x9DC1,0x0000, 0xFBC0,0x9DC2,0x0000, +0xFBC0,0x9DC3,0x0000, 0xFBC0,0x9DC4,0x0000, 0xFBC0,0x9DC5,0x0000, +0xFBC0,0x9DC6,0x0000, 0xFBC0,0x9DC7,0x0000, 0xFBC0,0x9DC8,0x0000, +0xFBC0,0x9DC9,0x0000, 0xFBC0,0x9DCA,0x0000, 0xFBC0,0x9DCB,0x0000, +0xFBC0,0x9DCC,0x0000, 0xFBC0,0x9DCD,0x0000, 0xFBC0,0x9DCE,0x0000, +0xFBC0,0x9DCF,0x0000, 0xFBC0,0x9DD0,0x0000, 0xFBC0,0x9DD1,0x0000, +0xFBC0,0x9DD2,0x0000, 0xFBC0,0x9DD3,0x0000, 0xFBC0,0x9DD4,0x0000, +0xFBC0,0x9DD5,0x0000, 0xFBC0,0x9DD6,0x0000, 0xFBC0,0x9DD7,0x0000, +0xFBC0,0x9DD8,0x0000, 0xFBC0,0x9DD9,0x0000, 0xFBC0,0x9DDA,0x0000, +0xFBC0,0x9DDB,0x0000, 0xFBC0,0x9DDC,0x0000, 0xFBC0,0x9DDD,0x0000, +0xFBC0,0x9DDE,0x0000, 0xFBC0,0x9DDF,0x0000, 0xFBC0,0x9DE0,0x0000, +0xFBC0,0x9DE1,0x0000, 0xFBC0,0x9DE2,0x0000, 0xFBC0,0x9DE3,0x0000, +0xFBC0,0x9DE4,0x0000, 0xFBC0,0x9DE5,0x0000, 0xFBC0,0x9DE6,0x0000, +0xFBC0,0x9DE7,0x0000, 0xFBC0,0x9DE8,0x0000, 0xFBC0,0x9DE9,0x0000, +0xFBC0,0x9DEA,0x0000, 0xFBC0,0x9DEB,0x0000, 0xFBC0,0x9DEC,0x0000, +0xFBC0,0x9DED,0x0000, 0xFBC0,0x9DEE,0x0000, 0xFBC0,0x9DEF,0x0000, +0xFBC0,0x9DF0,0x0000, 0xFBC0,0x9DF1,0x0000, 0xFBC0,0x9DF2,0x0000, +0xFBC0,0x9DF3,0x0000, 0xFBC0,0x9DF4,0x0000, 0xFBC0,0x9DF5,0x0000, +0xFBC0,0x9DF6,0x0000, 0xFBC0,0x9DF7,0x0000, 0xFBC0,0x9DF8,0x0000, +0xFBC0,0x9DF9,0x0000, 0xFBC0,0x9DFA,0x0000, 0xFBC0,0x9DFB,0x0000, +0xFBC0,0x9DFC,0x0000, 0xFBC0,0x9DFD,0x0000, 0xFBC0,0x9DFE,0x0000, +0xFBC0,0x9DFF,0x0000 }; + +uint16 page01Edata[]= { /* 1E00 (3 weights per char) */ +0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, 0x0E4A,0x0000,0x0000, +0x0E4A,0x0000,0x0000, 0x0E4A,0x0000,0x0000, 0x0E4A,0x0000,0x0000, +0x0E4A,0x0000,0x0000, 0x0E4A,0x0000,0x0000, 0x0E60,0x0000,0x0000, +0x0E60,0x0000,0x0000, 0x0E6D,0x0000,0x0000, 0x0E6D,0x0000,0x0000, +0x0E6D,0x0000,0x0000, 0x0E6D,0x0000,0x0000, 0x0E6D,0x0000,0x0000, +0x0E6D,0x0000,0x0000, 0x0E6D,0x0000,0x0000, 0x0E6D,0x0000,0x0000, +0x0E6D,0x0000,0x0000, 0x0E6D,0x0000,0x0000, 0x0E8B,0x0000,0x0000, +0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, +0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, +0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, +0x0EB9,0x0000,0x0000, 0x0EB9,0x0000,0x0000, 0x0EC1,0x0000,0x0000, +0x0EC1,0x0000,0x0000, 0x0EE1,0x0000,0x0000, 0x0EE1,0x0000,0x0000, +0x0EE1,0x0000,0x0000, 0x0EE1,0x0000,0x0000, 0x0EE1,0x0000,0x0000, +0x0EE1,0x0000,0x0000, 0x0EE1,0x0000,0x0000, 0x0EE1,0x0000,0x0000, +0x0EE1,0x0000,0x0000, 0x0EE1,0x0000,0x0000, 0x0EFB,0x0000,0x0000, +0x0EFB,0x0000,0x0000, 0x0EFB,0x0000,0x0000, 0x0EFB,0x0000,0x0000, +0x0F21,0x0000,0x0000, 0x0F21,0x0000,0x0000, 0x0F21,0x0000,0x0000, +0x0F21,0x0000,0x0000, 0x0F21,0x0000,0x0000, 0x0F21,0x0000,0x0000, +0x0F2E,0x0000,0x0000, 0x0F2E,0x0000,0x0000, 0x0F2E,0x0000,0x0000, +0x0F2E,0x0000,0x0000, 0x0F2E,0x0000,0x0000, 0x0F2E,0x0000,0x0000, +0x0F2E,0x0000,0x0000, 0x0F2E,0x0000,0x0000, 0x0F5B,0x0000,0x0000, +0x0F5B,0x0000,0x0000, 0x0F5B,0x0000,0x0000, 0x0F5B,0x0000,0x0000, +0x0F5B,0x0000,0x0000, 0x0F5B,0x0000,0x0000, 0x0F64,0x0000,0x0000, +0x0F64,0x0000,0x0000, 0x0F64,0x0000,0x0000, 0x0F64,0x0000,0x0000, +0x0F64,0x0000,0x0000, 0x0F64,0x0000,0x0000, 0x0F64,0x0000,0x0000, +0x0F64,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x0FA7,0x0000,0x0000, 0x0FA7,0x0000,0x0000, 0x0FA7,0x0000,0x0000, +0x0FA7,0x0000,0x0000, 0x0FC0,0x0000,0x0000, 0x0FC0,0x0000,0x0000, +0x0FC0,0x0000,0x0000, 0x0FC0,0x0000,0x0000, 0x0FC0,0x0000,0x0000, +0x0FC0,0x0000,0x0000, 0x0FC0,0x0000,0x0000, 0x0FC0,0x0000,0x0000, +0x0FEA,0x0000,0x0000, 0x0FEA,0x0000,0x0000, 0x0FEA,0x0000,0x0000, +0x0FEA,0x0000,0x0000, 0x0FEA,0x0000,0x0000, 0x0FEA,0x0000,0x0000, +0x0FEA,0x0000,0x0000, 0x0FEA,0x0000,0x0000, 0x0FEA,0x0000,0x0000, +0x0FEA,0x0000,0x0000, 0x1002,0x0000,0x0000, 0x1002,0x0000,0x0000, +0x1002,0x0000,0x0000, 0x1002,0x0000,0x0000, 0x1002,0x0000,0x0000, +0x1002,0x0000,0x0000, 0x1002,0x0000,0x0000, 0x1002,0x0000,0x0000, +0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, +0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, +0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, +0x101F,0x0000,0x0000, 0x1044,0x0000,0x0000, 0x1044,0x0000,0x0000, +0x1044,0x0000,0x0000, 0x1044,0x0000,0x0000, 0x1051,0x0000,0x0000, +0x1051,0x0000,0x0000, 0x1051,0x0000,0x0000, 0x1051,0x0000,0x0000, +0x1051,0x0000,0x0000, 0x1051,0x0000,0x0000, 0x1051,0x0000,0x0000, +0x1051,0x0000,0x0000, 0x1051,0x0000,0x0000, 0x1051,0x0000,0x0000, +0x105A,0x0000,0x0000, 0x105A,0x0000,0x0000, 0x105A,0x0000,0x0000, +0x105A,0x0000,0x0000, 0x105E,0x0000,0x0000, 0x105E,0x0000,0x0000, +0x106A,0x0000,0x0000, 0x106A,0x0000,0x0000, 0x106A,0x0000,0x0000, +0x106A,0x0000,0x0000, 0x106A,0x0000,0x0000, 0x106A,0x0000,0x0000, +0x0EE1,0x0000,0x0000, 0x1002,0x0000,0x0000, 0x1051,0x0000,0x0000, +0x105E,0x0000,0x0000, 0x0E33,0x10B3,0x0000, 0x0FEA,0x0000,0x0000, +0xFBC0,0x9E9C,0x0000, 0xFBC0,0x9E9D,0x0000, 0xFBC0,0x9E9E,0x0000, +0xFBC0,0x9E9F,0x0000, 0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, +0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, +0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, +0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, +0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, +0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, +0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, +0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, +0x0E33,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, +0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, +0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, +0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, +0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, +0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0EFB,0x0000,0x0000, +0x0EFB,0x0000,0x0000, 0x0EFB,0x0000,0x0000, 0x0EFB,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, +0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, +0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, +0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, +0x101F,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x105E,0x0000,0x0000, +0x105E,0x0000,0x0000, 0x105E,0x0000,0x0000, 0x105E,0x0000,0x0000, +0x105E,0x0000,0x0000, 0x105E,0x0000,0x0000, 0x105E,0x0000,0x0000, +0x105E,0x0000,0x0000, 0xFBC0,0x9EFA,0x0000, 0xFBC0,0x9EFB,0x0000, +0xFBC0,0x9EFC,0x0000, 0xFBC0,0x9EFD,0x0000, 0xFBC0,0x9EFE,0x0000, +0xFBC0,0x9EFF,0x0000 }; + +uint16 page01Fdata[]= { /* 1F00 (3 weights per char) */ +0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, +0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, +0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, +0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, +0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, +0x10E8,0x0000,0x0000, 0x10ED,0x0000,0x0000, 0x10ED,0x0000,0x0000, +0x10ED,0x0000,0x0000, 0x10ED,0x0000,0x0000, 0x10ED,0x0000,0x0000, +0x10ED,0x0000,0x0000, 0xFBC0,0x9F16,0x0000, 0xFBC0,0x9F17,0x0000, +0x10ED,0x0000,0x0000, 0x10ED,0x0000,0x0000, 0x10ED,0x0000,0x0000, +0x10ED,0x0000,0x0000, 0x10ED,0x0000,0x0000, 0x10ED,0x0000,0x0000, +0xFBC0,0x9F1E,0x0000, 0xFBC0,0x9F1F,0x0000, 0x10F1,0x0000,0x0000, +0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, +0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, +0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, +0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, +0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, +0x10F3,0x0000,0x0000, 0x10F3,0x0000,0x0000, 0x10F3,0x0000,0x0000, +0x10F3,0x0000,0x0000, 0x10F3,0x0000,0x0000, 0x10F3,0x0000,0x0000, +0x10F3,0x0000,0x0000, 0x10F3,0x0000,0x0000, 0x10F3,0x0000,0x0000, +0x10F3,0x0000,0x0000, 0x10F3,0x0000,0x0000, 0x10F3,0x0000,0x0000, +0x10F3,0x0000,0x0000, 0x10F3,0x0000,0x0000, 0x10F3,0x0000,0x0000, +0x10F3,0x0000,0x0000, 0x10FB,0x0000,0x0000, 0x10FB,0x0000,0x0000, +0x10FB,0x0000,0x0000, 0x10FB,0x0000,0x0000, 0x10FB,0x0000,0x0000, +0x10FB,0x0000,0x0000, 0xFBC0,0x9F46,0x0000, 0xFBC0,0x9F47,0x0000, +0x10FB,0x0000,0x0000, 0x10FB,0x0000,0x0000, 0x10FB,0x0000,0x0000, +0x10FB,0x0000,0x0000, 0x10FB,0x0000,0x0000, 0x10FB,0x0000,0x0000, +0xFBC0,0x9F4E,0x0000, 0xFBC0,0x9F4F,0x0000, 0x1104,0x0000,0x0000, +0x1104,0x0000,0x0000, 0x1104,0x0000,0x0000, 0x1104,0x0000,0x0000, +0x1104,0x0000,0x0000, 0x1104,0x0000,0x0000, 0x1104,0x0000,0x0000, +0x1104,0x0000,0x0000, 0xFBC0,0x9F58,0x0000, 0x1104,0x0000,0x0000, +0xFBC0,0x9F5A,0x0000, 0x1104,0x0000,0x0000, 0xFBC0,0x9F5C,0x0000, +0x1104,0x0000,0x0000, 0xFBC0,0x9F5E,0x0000, 0x1104,0x0000,0x0000, +0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, +0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, +0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, +0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, +0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, +0x1109,0x0000,0x0000, 0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, +0x10ED,0x0000,0x0000, 0x10ED,0x0000,0x0000, 0x10F1,0x0000,0x0000, +0x10F1,0x0000,0x0000, 0x10F3,0x0000,0x0000, 0x10F3,0x0000,0x0000, +0x10FB,0x0000,0x0000, 0x10FB,0x0000,0x0000, 0x1104,0x0000,0x0000, +0x1104,0x0000,0x0000, 0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, +0xFBC0,0x9F7E,0x0000, 0xFBC0,0x9F7F,0x0000, 0x10E8,0x0000,0x0000, +0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, +0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, +0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, +0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, +0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, +0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, +0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, +0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, +0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, +0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, +0x10F1,0x0000,0x0000, 0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, +0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, +0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, +0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, +0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, +0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, 0x10E8,0x0000,0x0000, +0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, +0x10E8,0x0000,0x0000, 0xFBC0,0x9FB5,0x0000, 0x10E8,0x0000,0x0000, +0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, +0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, +0x0217,0x0000,0x0000, 0x10F3,0x0000,0x0000, 0x0217,0x0000,0x0000, +0x021D,0x0000,0x0000, 0x0214,0x0000,0x0000, 0x10F1,0x0000,0x0000, +0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, 0xFBC0,0x9FC5,0x0000, +0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, 0x10ED,0x0000,0x0000, +0x10ED,0x0000,0x0000, 0x10F1,0x0000,0x0000, 0x10F1,0x0000,0x0000, +0x10F1,0x0000,0x0000, 0x0217,0x0000,0x0000, 0x0217,0x0000,0x0000, +0x0217,0x0000,0x0000, 0x10F3,0x0000,0x0000, 0x10F3,0x0000,0x0000, +0x10F3,0x0000,0x0000, 0x10F3,0x0000,0x0000, 0xFBC0,0x9FD4,0x0000, +0xFBC0,0x9FD5,0x0000, 0x10F3,0x0000,0x0000, 0x10F3,0x0000,0x0000, +0x10F3,0x0000,0x0000, 0x10F3,0x0000,0x0000, 0x10F3,0x0000,0x0000, +0x10F3,0x0000,0x0000, 0xFBC0,0x9FDC,0x0000, 0x0218,0x0000,0x0000, +0x0218,0x0000,0x0000, 0x0218,0x0000,0x0000, 0x1104,0x0000,0x0000, +0x1104,0x0000,0x0000, 0x1104,0x0000,0x0000, 0x1104,0x0000,0x0000, +0x1100,0x0000,0x0000, 0x1100,0x0000,0x0000, 0x1104,0x0000,0x0000, +0x1104,0x0000,0x0000, 0x1104,0x0000,0x0000, 0x1104,0x0000,0x0000, +0x1104,0x0000,0x0000, 0x1104,0x0000,0x0000, 0x1100,0x0000,0x0000, +0x0214,0x0000,0x0000, 0x0214,0x0000,0x0000, 0x020C,0x0000,0x0000, +0xFBC0,0x9FF0,0x0000, 0xFBC0,0x9FF1,0x0000, 0x1109,0x0000,0x0000, +0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, 0xFBC0,0x9FF5,0x0000, +0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, 0x10FB,0x0000,0x0000, +0x10FB,0x0000,0x0000, 0x1109,0x0000,0x0000, 0x1109,0x0000,0x0000, +0x1109,0x0000,0x0000, 0x020D,0x0000,0x0000, 0x0218,0x0000,0x0000, +0xFBC0,0x9FFF,0x0000 }; + +uint16 page020data[]= { /* 2000 (5 weights per char) */ +0x0209,0x0000,0x0000,0x0000,0x0000, +0x0209,0x0000,0x0000,0x0000,0x0000, +0x0209,0x0000,0x0000,0x0000,0x0000, +0x0209,0x0000,0x0000,0x0000,0x0000, +0x0209,0x0000,0x0000,0x0000,0x0000, +0x0209,0x0000,0x0000,0x0000,0x0000, +0x0209,0x0000,0x0000,0x0000,0x0000, +0x0209,0x0000,0x0000,0x0000,0x0000, +0x0209,0x0000,0x0000,0x0000,0x0000, +0x0209,0x0000,0x0000,0x0000,0x0000, +0x0209,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0225,0x0000,0x0000,0x0000,0x0000, +0x0225,0x0000,0x0000,0x0000,0x0000, +0x0226,0x0000,0x0000,0x0000,0x0000, +0x0227,0x0000,0x0000,0x0000,0x0000, +0x0228,0x0000,0x0000,0x0000,0x0000, +0x0229,0x0000,0x0000,0x0000,0x0000, +0x0432,0x0000,0x0000,0x0000,0x0000, +0x021C,0x0000,0x0000,0x0000,0x0000, +0x0278,0x0000,0x0000,0x0000,0x0000, +0x0279,0x0000,0x0000,0x0000,0x0000, +0x027A,0x0000,0x0000,0x0000,0x0000, +0x027B,0x0000,0x0000,0x0000,0x0000, +0x027F,0x0000,0x0000,0x0000,0x0000, +0x0280,0x0000,0x0000,0x0000,0x0000, +0x0281,0x0000,0x0000,0x0000,0x0000, +0x0282,0x0000,0x0000,0x0000,0x0000, +0x02D8,0x0000,0x0000,0x0000,0x0000, +0x02D9,0x0000,0x0000,0x0000,0x0000, +0x02DA,0x0000,0x0000,0x0000,0x0000, +0x02DB,0x0000,0x0000,0x0000,0x0000, +0x025D,0x0000,0x0000,0x0000,0x0000, +0x025D,0x025D,0x0000,0x0000,0x0000, +0x025D,0x025D,0x025D,0x0000,0x0000, +0x02DC,0x0000,0x0000,0x0000,0x0000, +0x0207,0x0000,0x0000,0x0000,0x0000, +0x0208,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0209,0x0000,0x0000,0x0000,0x0000, +0x02D5,0x0000,0x0000,0x0000,0x0000, +0x02D6,0x0000,0x0000,0x0000,0x0000, +0x02E0,0x0000,0x0000,0x0000,0x0000, +0x02E0,0x02E0,0x0000,0x0000,0x0000, +0x02E0,0x02E0,0x02E0,0x0000,0x0000, +0x02E1,0x0000,0x0000,0x0000,0x0000, +0x02E1,0x02E1,0x0000,0x0000,0x0000, +0x02E1,0x02E1,0x02E1,0x0000,0x0000, +0x02E4,0x0000,0x0000,0x0000,0x0000, +0x027C,0x0000,0x0000,0x0000,0x0000, +0x027D,0x0000,0x0000,0x0000,0x0000, +0x02E5,0x0000,0x0000,0x0000,0x0000, +0x0251,0x0251,0x0000,0x0000,0x0000, +0x025C,0x0000,0x0000,0x0000,0x0000, +0x0211,0x0000,0x0000,0x0000,0x0000, +0x02E6,0x0000,0x0000,0x0000,0x0000, +0x02E8,0x0000,0x0000,0x0000,0x0000, +0x02EA,0x0000,0x0000,0x0000,0x0000, +0x02EB,0x0000,0x0000,0x0000,0x0000, +0x02DD,0x0000,0x0000,0x0000,0x0000, +0x02CD,0x0000,0x0000,0x0000,0x0000, +0x0294,0x0000,0x0000,0x0000,0x0000, +0x0295,0x0000,0x0000,0x0000,0x0000, +0x0255,0x0255,0x0000,0x0000,0x0000, +0x0255,0x0251,0x0000,0x0000,0x0000, +0x0251,0x0255,0x0000,0x0000,0x0000, +0x02D1,0x0000,0x0000,0x0000,0x0000, +0x02C4,0x0000,0x0000,0x0000,0x0000, +0x02DE,0x0000,0x0000,0x0000,0x0000, +0x02DF,0x0000,0x0000,0x0000,0x0000, +0x02C9,0x0000,0x0000,0x0000,0x0000, +0x023C,0x0000,0x0000,0x0000,0x0000, +0x02E9,0x0000,0x0000,0x0000,0x0000, +0x02CA,0x0000,0x0000,0x0000,0x0000, +0x02D7,0x0000,0x0000,0x0000,0x0000, +0x022A,0x0000,0x0000,0x0000,0x0000, +0x02E7,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xA055,0x0000,0x0000,0x0000, +0xFBC0,0xA056,0x0000,0x0000,0x0000, +0x02E0,0x02E0,0x02E0,0x02E0,0x0000, +0xFBC0,0xA058,0x0000,0x0000,0x0000, +0xFBC0,0xA059,0x0000,0x0000,0x0000, +0xFBC0,0xA05A,0x0000,0x0000,0x0000, +0xFBC0,0xA05B,0x0000,0x0000,0x0000, +0xFBC0,0xA05C,0x0000,0x0000,0x0000, +0xFBC0,0xA05D,0x0000,0x0000,0x0000, +0xFBC0,0xA05E,0x0000,0x0000,0x0000, +0x0209,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xA064,0x0000,0x0000,0x0000, +0xFBC0,0xA065,0x0000,0x0000,0x0000, +0xFBC0,0xA066,0x0000,0x0000,0x0000, +0xFBC0,0xA067,0x0000,0x0000,0x0000, +0xFBC0,0xA068,0x0000,0x0000,0x0000, +0xFBC0,0xA069,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E29,0x0000,0x0000,0x0000,0x0000, +0x0EFB,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xA072,0x0000,0x0000,0x0000, +0xFBC0,0xA073,0x0000,0x0000,0x0000, +0x0E2D,0x0000,0x0000,0x0000,0x0000, +0x0E2E,0x0000,0x0000,0x0000,0x0000, +0x0E2F,0x0000,0x0000,0x0000,0x0000, +0x0E30,0x0000,0x0000,0x0000,0x0000, +0x0E31,0x0000,0x0000,0x0000,0x0000, +0x0E32,0x0000,0x0000,0x0000,0x0000, +0x0428,0x0000,0x0000,0x0000,0x0000, +0x0434,0x0000,0x0000,0x0000,0x0000, +0x042D,0x0000,0x0000,0x0000,0x0000, +0x0288,0x0000,0x0000,0x0000,0x0000, +0x0289,0x0000,0x0000,0x0000,0x0000, +0x0F64,0x0000,0x0000,0x0000,0x0000, +0x0E29,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0000,0x0000,0x0000,0x0000, +0x0E2C,0x0000,0x0000,0x0000,0x0000, +0x0E2D,0x0000,0x0000,0x0000,0x0000, +0x0E2E,0x0000,0x0000,0x0000,0x0000, +0x0E2F,0x0000,0x0000,0x0000,0x0000, +0x0E30,0x0000,0x0000,0x0000,0x0000, +0x0E31,0x0000,0x0000,0x0000,0x0000, +0x0E32,0x0000,0x0000,0x0000,0x0000, +0x0428,0x0000,0x0000,0x0000,0x0000, +0x0434,0x0000,0x0000,0x0000,0x0000, +0x042D,0x0000,0x0000,0x0000,0x0000, +0x0288,0x0000,0x0000,0x0000,0x0000, +0x0289,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xA08F,0x0000,0x0000,0x0000, +0xFBC0,0xA090,0x0000,0x0000,0x0000, +0xFBC0,0xA091,0x0000,0x0000,0x0000, +0xFBC0,0xA092,0x0000,0x0000,0x0000, +0xFBC0,0xA093,0x0000,0x0000,0x0000, +0xFBC0,0xA094,0x0000,0x0000,0x0000, +0xFBC0,0xA095,0x0000,0x0000,0x0000, +0xFBC0,0xA096,0x0000,0x0000,0x0000, +0xFBC0,0xA097,0x0000,0x0000,0x0000, +0xFBC0,0xA098,0x0000,0x0000,0x0000, +0xFBC0,0xA099,0x0000,0x0000,0x0000, +0xFBC0,0xA09A,0x0000,0x0000,0x0000, +0xFBC0,0xA09B,0x0000,0x0000,0x0000, +0xFBC0,0xA09C,0x0000,0x0000,0x0000, +0xFBC0,0xA09D,0x0000,0x0000,0x0000, +0xFBC0,0xA09E,0x0000,0x0000,0x0000, +0xFBC0,0xA09F,0x0000,0x0000,0x0000, +0x0E18,0x0000,0x0000,0x0000,0x0000, +0x0E19,0x0000,0x0000,0x0000,0x0000, +0x0E1A,0x0000,0x0000,0x0000,0x0000, +0x0E1B,0x0000,0x0000,0x0000,0x0000, +0x0E1C,0x0000,0x0000,0x0000,0x0000, +0x0E1D,0x0000,0x0000,0x0000,0x0000, +0x0E1E,0x0000,0x0000,0x0000,0x0000, +0x0E1F,0x0000,0x0000,0x0000,0x0000, +0x0FC0,0x0FEA,0x0000,0x0000,0x0000, +0x0E20,0x0000,0x0000,0x0000,0x0000, +0x0E21,0x0000,0x0000,0x0000,0x0000, +0x0E22,0x0000,0x0000,0x0000,0x0000, +0x0E23,0x0000,0x0000,0x0000,0x0000, +0x0E24,0x0000,0x0000,0x0000,0x0000, +0x0E25,0x0000,0x0000,0x0000,0x0000, +0x0E26,0x0000,0x0000,0x0000,0x0000, +0x0E27,0x0000,0x0000,0x0000,0x0000, +0x0E28,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xA0B2,0x0000,0x0000,0x0000, +0xFBC0,0xA0B3,0x0000,0x0000,0x0000, +0xFBC0,0xA0B4,0x0000,0x0000,0x0000, +0xFBC0,0xA0B5,0x0000,0x0000,0x0000, +0xFBC0,0xA0B6,0x0000,0x0000,0x0000, +0xFBC0,0xA0B7,0x0000,0x0000,0x0000, +0xFBC0,0xA0B8,0x0000,0x0000,0x0000, +0xFBC0,0xA0B9,0x0000,0x0000,0x0000, +0xFBC0,0xA0BA,0x0000,0x0000,0x0000, +0xFBC0,0xA0BB,0x0000,0x0000,0x0000, +0xFBC0,0xA0BC,0x0000,0x0000,0x0000, +0xFBC0,0xA0BD,0x0000,0x0000,0x0000, +0xFBC0,0xA0BE,0x0000,0x0000,0x0000, +0xFBC0,0xA0BF,0x0000,0x0000,0x0000, +0xFBC0,0xA0C0,0x0000,0x0000,0x0000, +0xFBC0,0xA0C1,0x0000,0x0000,0x0000, +0xFBC0,0xA0C2,0x0000,0x0000,0x0000, +0xFBC0,0xA0C3,0x0000,0x0000,0x0000, +0xFBC0,0xA0C4,0x0000,0x0000,0x0000, +0xFBC0,0xA0C5,0x0000,0x0000,0x0000, +0xFBC0,0xA0C6,0x0000,0x0000,0x0000, +0xFBC0,0xA0C7,0x0000,0x0000,0x0000, +0xFBC0,0xA0C8,0x0000,0x0000,0x0000, +0xFBC0,0xA0C9,0x0000,0x0000,0x0000, +0xFBC0,0xA0CA,0x0000,0x0000,0x0000, +0xFBC0,0xA0CB,0x0000,0x0000,0x0000, +0xFBC0,0xA0CC,0x0000,0x0000,0x0000, +0xFBC0,0xA0CD,0x0000,0x0000,0x0000, +0xFBC0,0xA0CE,0x0000,0x0000,0x0000, +0xFBC0,0xA0CF,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xA0EB,0x0000,0x0000,0x0000, +0xFBC0,0xA0EC,0x0000,0x0000,0x0000, +0xFBC0,0xA0ED,0x0000,0x0000,0x0000, +0xFBC0,0xA0EE,0x0000,0x0000,0x0000, +0xFBC0,0xA0EF,0x0000,0x0000,0x0000, +0xFBC0,0xA0F0,0x0000,0x0000,0x0000, +0xFBC0,0xA0F1,0x0000,0x0000,0x0000, +0xFBC0,0xA0F2,0x0000,0x0000,0x0000, +0xFBC0,0xA0F3,0x0000,0x0000,0x0000, +0xFBC0,0xA0F4,0x0000,0x0000,0x0000, +0xFBC0,0xA0F5,0x0000,0x0000,0x0000, +0xFBC0,0xA0F6,0x0000,0x0000,0x0000, +0xFBC0,0xA0F7,0x0000,0x0000,0x0000, +0xFBC0,0xA0F8,0x0000,0x0000,0x0000, +0xFBC0,0xA0F9,0x0000,0x0000,0x0000, +0xFBC0,0xA0FA,0x0000,0x0000,0x0000, +0xFBC0,0xA0FB,0x0000,0x0000,0x0000, +0xFBC0,0xA0FC,0x0000,0x0000,0x0000, +0xFBC0,0xA0FD,0x0000,0x0000,0x0000, +0xFBC0,0xA0FE,0x0000,0x0000,0x0000, +0xFBC0,0xA0FF,0x0000,0x0000,0x0000 +}; + +uint16 page021data[]= { /* 2100 (5 weights per char) */ +0x0E33,0x02CC,0x0E60,0x0000,0x0000, +0x0E33,0x02CC,0x0FEA,0x0000,0x0000, +0x0E60,0x0000,0x0000,0x0000,0x0000, +0x034A,0x0E60,0x0000,0x0000,0x0000, +0x039B,0x0000,0x0000,0x0000,0x0000, +0x0E60,0x02CC,0x0F82,0x0000,0x0000, +0x0E60,0x02CC,0x101F,0x0000,0x0000, +0x0E98,0x0000,0x0000,0x0000,0x0000, +0x039C,0x0000,0x0000,0x0000,0x0000, +0x034A,0x0EB9,0x0000,0x0000,0x0000, +0x0EC1,0x0000,0x0000,0x0000,0x0000, +0x0EE1,0x0000,0x0000,0x0000,0x0000, +0x0EE1,0x0000,0x0000,0x0000,0x0000, +0x0EE1,0x0000,0x0000,0x0000,0x0000, +0x0EE1,0x0000,0x0000,0x0000,0x0000, +0x0EED,0x0000,0x0000,0x0000,0x0000, +0x0EFB,0x0000,0x0000,0x0000,0x0000, +0x0EFB,0x0000,0x0000,0x0000,0x0000, +0x0F2E,0x0000,0x0000,0x0000,0x0000, +0x0F2E,0x0000,0x0000,0x0000,0x0000, +0x039D,0x0000,0x0000,0x0000,0x0000, +0x0F64,0x0000,0x0000,0x0000,0x0000, +0x0F64,0x0F82,0x0000,0x0000,0x0000, +0x039E,0x0000,0x0000,0x0000,0x0000, +0x039F,0x0000,0x0000,0x0000,0x0000, +0x0FA7,0x0000,0x0000,0x0000,0x0000, +0x0FB4,0x0000,0x0000,0x0000,0x0000, +0x0FC0,0x0000,0x0000,0x0000,0x0000, +0x0FC0,0x0000,0x0000,0x0000,0x0000, +0x0FC0,0x0000,0x0000,0x0000,0x0000, +0x03A0,0x0000,0x0000,0x0000,0x0000, +0x03A1,0x0000,0x0000,0x0000,0x0000, +0x0FEA,0x0F5B,0x0000,0x0000,0x0000, +0x1002,0x0E8B,0x0F2E,0x0000,0x0000, +0x1002,0x0F5B,0x0000,0x0000,0x0000, +0x03A2,0x0000,0x0000,0x0000,0x0000, +0x106A,0x0000,0x0000,0x0000,0x0000, +0x03A3,0x0000,0x0000,0x0000,0x0000, +0x1109,0x0000,0x0000,0x0000,0x0000, +0x03A4,0x0000,0x0000,0x0000,0x0000, +0x106A,0x0000,0x0000,0x0000,0x0000, +0x03A5,0x0000,0x0000,0x0000,0x0000, +0x0F21,0x0000,0x0000,0x0000,0x0000, +0x0E33,0x0000,0x0000,0x0000,0x0000, +0x0E4A,0x0000,0x0000,0x0000,0x0000, +0x0E60,0x0000,0x0000,0x0000,0x0000, +0x03A6,0x0000,0x0000,0x0000,0x0000, +0x0E8B,0x0000,0x0000,0x0000,0x0000, +0x0E8B,0x0000,0x0000,0x0000,0x0000, +0x0EB9,0x0000,0x0000,0x0000,0x0000, +0x03A7,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0000,0x0000,0x0000,0x0000, +0x0F82,0x0000,0x0000,0x0000,0x0000, +0x1331,0x0000,0x0000,0x0000,0x0000, +0x1332,0x0000,0x0000,0x0000,0x0000, +0x1333,0x0000,0x0000,0x0000,0x0000, +0x1334,0x0000,0x0000,0x0000,0x0000, +0x0EFB,0x0000,0x0000,0x0000,0x0000, +0x03A8,0x0000,0x0000,0x0000,0x0000, +0x0EB9,0x0E33,0x105A,0x0000,0x0000, +0xFBC0,0xA13C,0x0000,0x0000,0x0000, +0x10EA,0x0000,0x0000,0x0000,0x0000, +0x10EA,0x0000,0x0000,0x0000,0x0000, +0x10FC,0x0000,0x0000,0x0000,0x0000, +0x0427,0x0000,0x0000,0x0000,0x0000, +0x03A9,0x0000,0x0000,0x0000,0x0000, +0x03AA,0x0000,0x0000,0x0000,0x0000, +0x03AB,0x0000,0x0000,0x0000,0x0000, +0x03AC,0x0000,0x0000,0x0000,0x0000, +0x0E6D,0x0000,0x0000,0x0000,0x0000, +0x0E6D,0x0000,0x0000,0x0000,0x0000, +0x0E8B,0x0000,0x0000,0x0000,0x0000, +0x0EFB,0x0000,0x0000,0x0000,0x0000, +0x0F10,0x0000,0x0000,0x0000,0x0000, +0x03AD,0x0000,0x0000,0x0000,0x0000, +0x02D0,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xA14C,0x0000,0x0000,0x0000, +0xFBC0,0xA14D,0x0000,0x0000,0x0000, +0xFBC0,0xA14E,0x0000,0x0000,0x0000, +0xFBC0,0xA14F,0x0000,0x0000,0x0000, +0xFBC0,0xA150,0x0000,0x0000,0x0000, +0xFBC0,0xA151,0x0000,0x0000,0x0000, +0xFBC0,0xA152,0x0000,0x0000,0x0000, +0x0E2A,0x02CD,0x0E2C,0x0000,0x0000, +0x0E2B,0x02CD,0x0E2C,0x0000,0x0000, +0x0E2A,0x02CD,0x0E2E,0x0000,0x0000, +0x0E2B,0x02CD,0x0E2E,0x0000,0x0000, +0x0E2C,0x02CD,0x0E2E,0x0000,0x0000, +0x0E2D,0x02CD,0x0E2E,0x0000,0x0000, +0x0E2A,0x02CD,0x0E2F,0x0000,0x0000, +0x0E2E,0x02CD,0x0E2F,0x0000,0x0000, +0x0E2A,0x02CD,0x0E31,0x0000,0x0000, +0x0E2C,0x02CD,0x0E31,0x0000,0x0000, +0x0E2E,0x02CD,0x0E31,0x0000,0x0000, +0x0E30,0x02CD,0x0E31,0x0000,0x0000, +0x0E2A,0x02CD,0x0000,0x0000,0x0000, +0x0EFB,0x0000,0x0000,0x0000,0x0000, +0x0EFB,0x0EFB,0x0000,0x0000,0x0000, +0x0EFB,0x0EFB,0x0EFB,0x0000,0x0000, +0x0EFB,0x1044,0x0000,0x0000,0x0000, +0x1044,0x0000,0x0000,0x0000,0x0000, +0x1044,0x0EFB,0x0000,0x0000,0x0000, +0x1044,0x0EFB,0x0EFB,0x0000,0x0000, +0x1044,0x0EFB,0x0EFB,0x0EFB,0x0000, +0x0EFB,0x105A,0x0000,0x0000,0x0000, +0x105A,0x0000,0x0000,0x0000,0x0000, +0x105A,0x0EFB,0x0000,0x0000,0x0000, +0x105A,0x0EFB,0x0EFB,0x0000,0x0000, +0x0F2E,0x0000,0x0000,0x0000,0x0000, +0x0E60,0x0000,0x0000,0x0000,0x0000, +0x0E6D,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0000,0x0000,0x0000,0x0000, +0x0EFB,0x0000,0x0000,0x0000,0x0000, +0x0EFB,0x0EFB,0x0000,0x0000,0x0000, +0x0EFB,0x0EFB,0x0EFB,0x0000,0x0000, +0x0EFB,0x1044,0x0000,0x0000,0x0000, +0x1044,0x0000,0x0000,0x0000,0x0000, +0x1044,0x0EFB,0x0000,0x0000,0x0000, +0x1044,0x0EFB,0x0EFB,0x0000,0x0000, +0x1044,0x0EFB,0x0EFB,0x0EFB,0x0000, +0x0EFB,0x105A,0x0000,0x0000,0x0000, +0x105A,0x0000,0x0000,0x0000,0x0000, +0x105A,0x0EFB,0x0000,0x0000,0x0000, +0x105A,0x0EFB,0x0EFB,0x0000,0x0000, +0x0F2E,0x0000,0x0000,0x0000,0x0000, +0x0E60,0x0000,0x0000,0x0000,0x0000, +0x0E6D,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0000,0x0000,0x0000,0x0000, +0x0DD7,0x0000,0x0000,0x0000,0x0000, +0x0DD8,0x0000,0x0000,0x0000,0x0000, +0x0DD9,0x0000,0x0000,0x0000,0x0000, +0x0DDA,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xA184,0x0000,0x0000,0x0000, +0xFBC0,0xA185,0x0000,0x0000,0x0000, +0xFBC0,0xA186,0x0000,0x0000,0x0000, +0xFBC0,0xA187,0x0000,0x0000,0x0000, +0xFBC0,0xA188,0x0000,0x0000,0x0000, +0xFBC0,0xA189,0x0000,0x0000,0x0000, +0xFBC0,0xA18A,0x0000,0x0000,0x0000, +0xFBC0,0xA18B,0x0000,0x0000,0x0000, +0xFBC0,0xA18C,0x0000,0x0000,0x0000, +0xFBC0,0xA18D,0x0000,0x0000,0x0000, +0xFBC0,0xA18E,0x0000,0x0000,0x0000, +0xFBC0,0xA18F,0x0000,0x0000,0x0000, +0x03AE,0x0000,0x0000,0x0000,0x0000, +0x03B0,0x0000,0x0000,0x0000,0x0000, +0x03AF,0x0000,0x0000,0x0000,0x0000, +0x03B1,0x0000,0x0000,0x0000,0x0000, +0x03B2,0x0000,0x0000,0x0000,0x0000, +0x03B3,0x0000,0x0000,0x0000,0x0000, +0x03B4,0x0000,0x0000,0x0000,0x0000, +0x03B5,0x0000,0x0000,0x0000,0x0000, +0x03B6,0x0000,0x0000,0x0000,0x0000, +0x03B7,0x0000,0x0000,0x0000,0x0000, +0x03AE,0x0000,0x0000,0x0000,0x0000, +0x03AF,0x0000,0x0000,0x0000,0x0000, +0x03B8,0x0000,0x0000,0x0000,0x0000, +0x03B9,0x0000,0x0000,0x0000,0x0000, +0x03BA,0x0000,0x0000,0x0000,0x0000, +0x03BB,0x0000,0x0000,0x0000,0x0000, +0x03BC,0x0000,0x0000,0x0000,0x0000, +0x03BD,0x0000,0x0000,0x0000,0x0000, +0x03BE,0x0000,0x0000,0x0000,0x0000, +0x03BF,0x0000,0x0000,0x0000,0x0000, +0x03C0,0x0000,0x0000,0x0000,0x0000, +0x03C1,0x0000,0x0000,0x0000,0x0000, +0x03C2,0x0000,0x0000,0x0000,0x0000, +0x03C3,0x0000,0x0000,0x0000,0x0000, +0x03C4,0x0000,0x0000,0x0000,0x0000, +0x03C5,0x0000,0x0000,0x0000,0x0000, +0x03C6,0x0000,0x0000,0x0000,0x0000, +0x03C7,0x0000,0x0000,0x0000,0x0000, +0x03C8,0x0000,0x0000,0x0000,0x0000, +0x03C9,0x0000,0x0000,0x0000,0x0000, +0x03B2,0x0000,0x0000,0x0000,0x0000, +0x03CA,0x0000,0x0000,0x0000,0x0000, +0x03CB,0x0000,0x0000,0x0000,0x0000, +0x03CC,0x0000,0x0000,0x0000,0x0000, +0x03CD,0x0000,0x0000,0x0000,0x0000, +0x03CE,0x0000,0x0000,0x0000,0x0000, +0x03CF,0x0000,0x0000,0x0000,0x0000, +0x03D0,0x0000,0x0000,0x0000,0x0000, +0x03D1,0x0000,0x0000,0x0000,0x0000, +0x03D2,0x0000,0x0000,0x0000,0x0000, +0x03D3,0x0000,0x0000,0x0000,0x0000, +0x03D4,0x0000,0x0000,0x0000,0x0000, +0x03D5,0x0000,0x0000,0x0000,0x0000, +0x03D6,0x0000,0x0000,0x0000,0x0000, +0x03D7,0x0000,0x0000,0x0000,0x0000, +0x03D8,0x0000,0x0000,0x0000,0x0000, +0x03D9,0x0000,0x0000,0x0000,0x0000, +0x03DA,0x0000,0x0000,0x0000,0x0000, +0x03DB,0x0000,0x0000,0x0000,0x0000, +0x03DC,0x0000,0x0000,0x0000,0x0000, +0x03DD,0x0000,0x0000,0x0000,0x0000, +0x03DE,0x0000,0x0000,0x0000,0x0000, +0x03DF,0x0000,0x0000,0x0000,0x0000, +0x03E0,0x0000,0x0000,0x0000,0x0000, +0x03E1,0x0000,0x0000,0x0000,0x0000, +0x03E2,0x0000,0x0000,0x0000,0x0000, +0x03E3,0x0000,0x0000,0x0000,0x0000, +0x03E4,0x0000,0x0000,0x0000,0x0000, +0x03E5,0x0000,0x0000,0x0000,0x0000, +0x03E6,0x0000,0x0000,0x0000,0x0000, +0x03E7,0x0000,0x0000,0x0000,0x0000, +0x03E8,0x0000,0x0000,0x0000,0x0000, +0x03EC,0x0000,0x0000,0x0000,0x0000, +0x03EA,0x0000,0x0000,0x0000,0x0000, +0x03E8,0x0000,0x0000,0x0000,0x0000, +0x03E9,0x0000,0x0000,0x0000,0x0000, +0x03EA,0x0000,0x0000,0x0000,0x0000, +0x03EB,0x0000,0x0000,0x0000,0x0000, +0x03EC,0x0000,0x0000,0x0000,0x0000, +0x03ED,0x0000,0x0000,0x0000,0x0000, +0x03EE,0x0000,0x0000,0x0000,0x0000, +0x03EF,0x0000,0x0000,0x0000,0x0000, +0x03F0,0x0000,0x0000,0x0000,0x0000, +0x03F1,0x0000,0x0000,0x0000,0x0000, +0x03F2,0x0000,0x0000,0x0000,0x0000, +0x03F3,0x0000,0x0000,0x0000,0x0000, +0x03F4,0x0000,0x0000,0x0000,0x0000, +0x03F5,0x0000,0x0000,0x0000,0x0000, +0x03F6,0x0000,0x0000,0x0000,0x0000, +0x03F7,0x0000,0x0000,0x0000,0x0000, +0x03F8,0x0000,0x0000,0x0000,0x0000, +0x03F9,0x0000,0x0000,0x0000,0x0000, +0x03FA,0x0000,0x0000,0x0000,0x0000, +0x03FB,0x0000,0x0000,0x0000,0x0000, +0x03FC,0x0000,0x0000,0x0000,0x0000, +0x03FD,0x0000,0x0000,0x0000,0x0000, +0x03FE,0x0000,0x0000,0x0000,0x0000, +0x03FF,0x0000,0x0000,0x0000,0x0000, +0x0400,0x0000,0x0000,0x0000,0x0000, +0x0401,0x0000,0x0000,0x0000,0x0000, +0x0402,0x0000,0x0000,0x0000,0x0000, +0x0403,0x0000,0x0000,0x0000,0x0000, +0x0404,0x0000,0x0000,0x0000,0x0000, +0x0405,0x0000,0x0000,0x0000,0x0000, +0x0406,0x0000,0x0000,0x0000,0x0000, +0x0407,0x0000,0x0000,0x0000,0x0000, +0x0408,0x0000,0x0000,0x0000,0x0000, +0x0409,0x0000,0x0000,0x0000,0x0000, +0x040A,0x0000,0x0000,0x0000,0x0000, +0x040B,0x0000,0x0000,0x0000,0x0000, +0x040C,0x0000,0x0000,0x0000,0x0000, +0x040D,0x0000,0x0000,0x0000,0x0000, +0x040E,0x0000,0x0000,0x0000,0x0000, +0x040F,0x0000,0x0000,0x0000,0x0000, +0x0410,0x0000,0x0000,0x0000,0x0000, +0x0411,0x0000,0x0000,0x0000,0x0000, +0x0412,0x0000,0x0000,0x0000,0x0000, +0x0413,0x0000,0x0000,0x0000,0x0000, +0x0414,0x0000,0x0000,0x0000,0x0000, +0x0415,0x0000,0x0000,0x0000,0x0000, +0x0416,0x0000,0x0000,0x0000,0x0000, +0x0417,0x0000,0x0000,0x0000,0x0000 +}; + +uint16 page022data[]= { /* 2200 (4 weights per char) */ +0x0418,0x0000,0x0000,0x0000, 0x0419,0x0000,0x0000,0x0000, +0x041A,0x0000,0x0000,0x0000, 0x041B,0x0000,0x0000,0x0000, +0x041B,0x0000,0x0000,0x0000, 0x041C,0x0000,0x0000,0x0000, +0x041D,0x0000,0x0000,0x0000, 0x041E,0x0000,0x0000,0x0000, +0x041F,0x0000,0x0000,0x0000, 0x041F,0x0000,0x0000,0x0000, +0x0420,0x0000,0x0000,0x0000, 0x0421,0x0000,0x0000,0x0000, +0x0421,0x0000,0x0000,0x0000, 0x0422,0x0000,0x0000,0x0000, +0x0424,0x0000,0x0000,0x0000, 0x0425,0x0000,0x0000,0x0000, +0x0426,0x0000,0x0000,0x0000, 0x0427,0x0000,0x0000,0x0000, +0x0434,0x0000,0x0000,0x0000, 0x0435,0x0000,0x0000,0x0000, +0x0436,0x0000,0x0000,0x0000, 0x0437,0x0000,0x0000,0x0000, +0x0438,0x0000,0x0000,0x0000, 0x0439,0x0000,0x0000,0x0000, +0x043A,0x0000,0x0000,0x0000, 0x043B,0x0000,0x0000,0x0000, +0x043C,0x0000,0x0000,0x0000, 0x043D,0x0000,0x0000,0x0000, +0x043E,0x0000,0x0000,0x0000, 0x043F,0x0000,0x0000,0x0000, +0x0440,0x0000,0x0000,0x0000, 0x0441,0x0000,0x0000,0x0000, +0x0442,0x0000,0x0000,0x0000, 0x0443,0x0000,0x0000,0x0000, +0x0444,0x0000,0x0000,0x0000, 0x0445,0x0000,0x0000,0x0000, +0x0445,0x0000,0x0000,0x0000, 0x0446,0x0000,0x0000,0x0000, +0x0446,0x0000,0x0000,0x0000, 0x0447,0x0000,0x0000,0x0000, +0x0448,0x0000,0x0000,0x0000, 0x0449,0x0000,0x0000,0x0000, +0x044A,0x0000,0x0000,0x0000, 0x044B,0x0000,0x0000,0x0000, +0x044B,0x044B,0x0000,0x0000, 0x044B,0x044B,0x044B,0x0000, +0x044C,0x0000,0x0000,0x0000, 0x044C,0x044C,0x0000,0x0000, +0x044C,0x044C,0x044C,0x0000, 0x044D,0x0000,0x0000,0x0000, +0x044E,0x0000,0x0000,0x0000, 0x044F,0x0000,0x0000,0x0000, +0x0450,0x0000,0x0000,0x0000, 0x0451,0x0000,0x0000,0x0000, +0x0452,0x0000,0x0000,0x0000, 0x0453,0x0000,0x0000,0x0000, +0x0454,0x0000,0x0000,0x0000, 0x0455,0x0000,0x0000,0x0000, +0x0456,0x0000,0x0000,0x0000, 0x0457,0x0000,0x0000,0x0000, +0x0458,0x0000,0x0000,0x0000, 0x0459,0x0000,0x0000,0x0000, +0x045A,0x0000,0x0000,0x0000, 0x045B,0x0000,0x0000,0x0000, +0x045C,0x0000,0x0000,0x0000, 0x0458,0x0000,0x0000,0x0000, +0x045D,0x0000,0x0000,0x0000, 0x045E,0x0000,0x0000,0x0000, +0x045E,0x0000,0x0000,0x0000, 0x045F,0x0000,0x0000,0x0000, +0x0460,0x0000,0x0000,0x0000, 0x045F,0x0000,0x0000,0x0000, +0x0461,0x0000,0x0000,0x0000, 0x0461,0x0000,0x0000,0x0000, +0x0462,0x0000,0x0000,0x0000, 0x0463,0x0000,0x0000,0x0000, +0x0464,0x0000,0x0000,0x0000, 0x0465,0x0000,0x0000,0x0000, +0x0466,0x0000,0x0000,0x0000, 0x0467,0x0000,0x0000,0x0000, +0x0468,0x0000,0x0000,0x0000, 0x0469,0x0000,0x0000,0x0000, +0x046A,0x0000,0x0000,0x0000, 0x046B,0x0000,0x0000,0x0000, +0x046C,0x0000,0x0000,0x0000, 0x046D,0x0000,0x0000,0x0000, +0x046E,0x0000,0x0000,0x0000, 0x046F,0x0000,0x0000,0x0000, +0x0470,0x0000,0x0000,0x0000, 0x0471,0x0000,0x0000,0x0000, +0x0472,0x0000,0x0000,0x0000, 0x0473,0x0000,0x0000,0x0000, +0x0474,0x0000,0x0000,0x0000, 0x0475,0x0000,0x0000,0x0000, +0x0476,0x0000,0x0000,0x0000, 0x0477,0x0000,0x0000,0x0000, +0x042D,0x0000,0x0000,0x0000, 0x0478,0x0000,0x0000,0x0000, +0x0478,0x0000,0x0000,0x0000, 0x0479,0x0000,0x0000,0x0000, +0x047A,0x0000,0x0000,0x0000, 0x047B,0x0000,0x0000,0x0000, +0x047C,0x0000,0x0000,0x0000, 0x047D,0x0000,0x0000,0x0000, +0x047E,0x0000,0x0000,0x0000, 0x047F,0x0000,0x0000,0x0000, +0x0480,0x0000,0x0000,0x0000, 0x0481,0x0000,0x0000,0x0000, +0x0482,0x0000,0x0000,0x0000, 0x0465,0x0000,0x0000,0x0000, +0x042C,0x0000,0x0000,0x0000, 0x042E,0x0000,0x0000,0x0000, +0x047A,0x0000,0x0000,0x0000, 0x047B,0x0000,0x0000,0x0000, +0x0483,0x0000,0x0000,0x0000, 0x0484,0x0000,0x0000,0x0000, +0x0483,0x0000,0x0000,0x0000, 0x0484,0x0000,0x0000,0x0000, +0x0485,0x0000,0x0000,0x0000, 0x0486,0x0000,0x0000,0x0000, +0x0485,0x0000,0x0000,0x0000, 0x0486,0x0000,0x0000,0x0000, +0x0487,0x0000,0x0000,0x0000, 0x0488,0x0000,0x0000,0x0000, +0x0489,0x0000,0x0000,0x0000, 0x048A,0x0000,0x0000,0x0000, +0x048B,0x0000,0x0000,0x0000, 0x048C,0x0000,0x0000,0x0000, +0x0487,0x0000,0x0000,0x0000, 0x0488,0x0000,0x0000,0x0000, +0x048D,0x0000,0x0000,0x0000, 0x048E,0x0000,0x0000,0x0000, +0x048D,0x0000,0x0000,0x0000, 0x048E,0x0000,0x0000,0x0000, +0x048F,0x0000,0x0000,0x0000, 0x0490,0x0000,0x0000,0x0000, +0x048F,0x0000,0x0000,0x0000, 0x0490,0x0000,0x0000,0x0000, +0x0491,0x0000,0x0000,0x0000, 0x0492,0x0000,0x0000,0x0000, +0x0493,0x0000,0x0000,0x0000, 0x0494,0x0000,0x0000,0x0000, +0x0495,0x0000,0x0000,0x0000, 0x0496,0x0000,0x0000,0x0000, +0x0497,0x0000,0x0000,0x0000, 0x0498,0x0000,0x0000,0x0000, +0x0499,0x0000,0x0000,0x0000, 0x049A,0x0000,0x0000,0x0000, +0x049B,0x0000,0x0000,0x0000, 0x049C,0x0000,0x0000,0x0000, +0x049D,0x0000,0x0000,0x0000, 0x049E,0x0000,0x0000,0x0000, +0x049F,0x0000,0x0000,0x0000, 0x04A0,0x0000,0x0000,0x0000, +0x04A1,0x0000,0x0000,0x0000, 0x04A2,0x0000,0x0000,0x0000, +0x04A3,0x0000,0x0000,0x0000, 0x04A4,0x0000,0x0000,0x0000, +0x04A5,0x0000,0x0000,0x0000, 0x04A6,0x0000,0x0000,0x0000, +0x04A7,0x0000,0x0000,0x0000, 0x04A8,0x0000,0x0000,0x0000, +0x04A9,0x0000,0x0000,0x0000, 0x04AA,0x0000,0x0000,0x0000, +0x04AB,0x0000,0x0000,0x0000, 0x04AC,0x0000,0x0000,0x0000, +0x04AD,0x0000,0x0000,0x0000, 0x04AE,0x0000,0x0000,0x0000, +0x04AF,0x0000,0x0000,0x0000, 0x04B0,0x0000,0x0000,0x0000, +0x04B1,0x0000,0x0000,0x0000, 0x04B2,0x0000,0x0000,0x0000, +0x04A9,0x0000,0x0000,0x0000, 0x04AF,0x0000,0x0000,0x0000, +0x04B0,0x0000,0x0000,0x0000, 0x04B2,0x0000,0x0000,0x0000, +0x04B3,0x0000,0x0000,0x0000, 0x04B4,0x0000,0x0000,0x0000, +0x04B5,0x0000,0x0000,0x0000, 0x04B6,0x0000,0x0000,0x0000, +0x04B7,0x0000,0x0000,0x0000, 0x04B8,0x0000,0x0000,0x0000, +0x04B9,0x0000,0x0000,0x0000, 0x04BA,0x0000,0x0000,0x0000, +0x04BB,0x0000,0x0000,0x0000, 0x04BC,0x0000,0x0000,0x0000, +0x04BD,0x0000,0x0000,0x0000, 0x04BE,0x0000,0x0000,0x0000, +0x04BF,0x0000,0x0000,0x0000, 0x04C0,0x0000,0x0000,0x0000, +0x04C1,0x0000,0x0000,0x0000, 0x04C2,0x0000,0x0000,0x0000, +0x04C3,0x0000,0x0000,0x0000, 0x04C4,0x0000,0x0000,0x0000, +0x04C5,0x0000,0x0000,0x0000, 0x04C6,0x0000,0x0000,0x0000, +0x04C7,0x0000,0x0000,0x0000, 0x04C8,0x0000,0x0000,0x0000, +0x04C9,0x0000,0x0000,0x0000, 0x04CA,0x0000,0x0000,0x0000, +0x04CB,0x0000,0x0000,0x0000, 0x04CC,0x0000,0x0000,0x0000, +0x04CD,0x0000,0x0000,0x0000, 0x04CE,0x0000,0x0000,0x0000, +0x04CF,0x0000,0x0000,0x0000, 0x04D0,0x0000,0x0000,0x0000, +0x04D1,0x0000,0x0000,0x0000, 0x04D2,0x0000,0x0000,0x0000, +0x04D3,0x0000,0x0000,0x0000, 0x04D4,0x0000,0x0000,0x0000, +0x04D5,0x0000,0x0000,0x0000, 0x04D6,0x0000,0x0000,0x0000, +0x04D7,0x0000,0x0000,0x0000, 0x04D8,0x0000,0x0000,0x0000, +0x04D9,0x0000,0x0000,0x0000, 0x04DA,0x0000,0x0000,0x0000, +0x04DB,0x0000,0x0000,0x0000, 0x04DC,0x0000,0x0000,0x0000, +0x04DD,0x0000,0x0000,0x0000, 0x04DE,0x0000,0x0000,0x0000, +0x04DF,0x0000,0x0000,0x0000, 0x04E0,0x0000,0x0000,0x0000, +0x04E1,0x0000,0x0000,0x0000, 0x04E2,0x0000,0x0000,0x0000, +0x0489,0x0000,0x0000,0x0000, 0x048A,0x0000,0x0000,0x0000, +0x0498,0x0000,0x0000,0x0000, 0x0499,0x0000,0x0000,0x0000, +0x04E3,0x0000,0x0000,0x0000, 0x04E4,0x0000,0x0000,0x0000, +0x04E5,0x0000,0x0000,0x0000, 0x04E6,0x0000,0x0000,0x0000, +0x04E7,0x0000,0x0000,0x0000, 0x04E8,0x0000,0x0000,0x0000, +0x04B5,0x0000,0x0000,0x0000, 0x04B6,0x0000,0x0000,0x0000, +0x04B7,0x0000,0x0000,0x0000, 0x04B8,0x0000,0x0000,0x0000, +0x04E9,0x0000,0x0000,0x0000, 0x04EA,0x0000,0x0000,0x0000, +0x04EB,0x0000,0x0000,0x0000, 0x04EC,0x0000,0x0000,0x0000, +0x04ED,0x0000,0x0000,0x0000, 0x04EE,0x0000,0x0000,0x0000, +0x04EF,0x0000,0x0000,0x0000, 0x04F0,0x0000,0x0000,0x0000, +0x04F1,0x0000,0x0000,0x0000, 0x04F2,0x0000,0x0000,0x0000, +0x04F3,0x0000,0x0000,0x0000, 0x04F4,0x0000,0x0000,0x0000, +0x04F5,0x0000,0x0000,0x0000, 0x04F6,0x0000,0x0000,0x0000, +0x04F7,0x0000,0x0000,0x0000, 0x04F8,0x0000,0x0000,0x0000, +0x04F9,0x0000,0x0000,0x0000, 0x04FA,0x0000,0x0000,0x0000 +}; + +uint16 page023data[]= { /* 2300 (3 weights per char) */ +0x04FB,0x0000,0x0000, 0x04FC,0x0000,0x0000, 0x04FD,0x0000,0x0000, +0x04FE,0x0000,0x0000, 0x04FF,0x0000,0x0000, 0x0500,0x0000,0x0000, +0x0501,0x0000,0x0000, 0x0502,0x0000,0x0000, 0x0503,0x0000,0x0000, +0x0504,0x0000,0x0000, 0x0505,0x0000,0x0000, 0x0506,0x0000,0x0000, +0x0507,0x0000,0x0000, 0x0508,0x0000,0x0000, 0x0509,0x0000,0x0000, +0x050A,0x0000,0x0000, 0x050B,0x0000,0x0000, 0x050C,0x0000,0x0000, +0x050D,0x0000,0x0000, 0x050E,0x0000,0x0000, 0x050F,0x0000,0x0000, +0x0510,0x0000,0x0000, 0x0511,0x0000,0x0000, 0x0512,0x0000,0x0000, +0x0513,0x0000,0x0000, 0x0514,0x0000,0x0000, 0x0515,0x0000,0x0000, +0x0516,0x0000,0x0000, 0x0517,0x0000,0x0000, 0x0518,0x0000,0x0000, +0x0519,0x0000,0x0000, 0x051A,0x0000,0x0000, 0x051B,0x0000,0x0000, +0x051C,0x0000,0x0000, 0x051D,0x0000,0x0000, 0x051E,0x0000,0x0000, +0x051F,0x0000,0x0000, 0x0520,0x0000,0x0000, 0x0521,0x0000,0x0000, +0x0522,0x0000,0x0000, 0x0523,0x0000,0x0000, 0x02AE,0x0000,0x0000, +0x02AF,0x0000,0x0000, 0x0524,0x0000,0x0000, 0x0525,0x0000,0x0000, +0x0526,0x0000,0x0000, 0x0527,0x0000,0x0000, 0x0528,0x0000,0x0000, +0x0529,0x0000,0x0000, 0x052A,0x0000,0x0000, 0x052B,0x0000,0x0000, +0x052C,0x0000,0x0000, 0x052D,0x0000,0x0000, 0x052E,0x0000,0x0000, +0x052F,0x0000,0x0000, 0x0530,0x0000,0x0000, 0x0531,0x0000,0x0000, +0x0532,0x0000,0x0000, 0x0533,0x0000,0x0000, 0x0534,0x0000,0x0000, +0x0535,0x0000,0x0000, 0x0536,0x0000,0x0000, 0x0537,0x0000,0x0000, +0x0538,0x0000,0x0000, 0x0539,0x0000,0x0000, 0x053A,0x0000,0x0000, +0x053B,0x0000,0x0000, 0x053C,0x0000,0x0000, 0x053D,0x0000,0x0000, +0x053E,0x0000,0x0000, 0x053F,0x0000,0x0000, 0x0540,0x0000,0x0000, +0x0541,0x0000,0x0000, 0x0542,0x0000,0x0000, 0x0543,0x0000,0x0000, +0x0544,0x0000,0x0000, 0x0545,0x0000,0x0000, 0x0546,0x0000,0x0000, +0x0547,0x0000,0x0000, 0x0548,0x0000,0x0000, 0x0549,0x0000,0x0000, +0x054A,0x0000,0x0000, 0x054B,0x0000,0x0000, 0x054C,0x0000,0x0000, +0x054D,0x0000,0x0000, 0x054E,0x0000,0x0000, 0x054F,0x0000,0x0000, +0x0550,0x0000,0x0000, 0x0551,0x0000,0x0000, 0x0552,0x0000,0x0000, +0x0553,0x0000,0x0000, 0x0554,0x0000,0x0000, 0x0555,0x0000,0x0000, +0x0556,0x0000,0x0000, 0x0557,0x0000,0x0000, 0x0558,0x0000,0x0000, +0x0559,0x0000,0x0000, 0x055A,0x0000,0x0000, 0x055B,0x0000,0x0000, +0x055C,0x0000,0x0000, 0x055D,0x0000,0x0000, 0x055E,0x0000,0x0000, +0x055F,0x0000,0x0000, 0x0560,0x0000,0x0000, 0x0561,0x0000,0x0000, +0x0562,0x0000,0x0000, 0x0563,0x0000,0x0000, 0x0564,0x0000,0x0000, +0x0565,0x0000,0x0000, 0x0566,0x0000,0x0000, 0x0567,0x0000,0x0000, +0x0568,0x0000,0x0000, 0x0569,0x0000,0x0000, 0x056A,0x0000,0x0000, +0x056B,0x0000,0x0000, 0x056C,0x0000,0x0000, 0x056D,0x0000,0x0000, +0x056E,0x0000,0x0000, 0x056F,0x0000,0x0000, 0x0570,0x0000,0x0000, +0x0571,0x0000,0x0000, 0x0572,0x0000,0x0000, 0x0573,0x0000,0x0000, +0x0574,0x0000,0x0000, 0x0575,0x0000,0x0000, 0x0576,0x0000,0x0000, +0x0577,0x0000,0x0000, 0x0578,0x0000,0x0000, 0x0579,0x0000,0x0000, +0x057A,0x0000,0x0000, 0x057B,0x0000,0x0000, 0x057C,0x0000,0x0000, +0x057D,0x0000,0x0000, 0x057E,0x0000,0x0000, 0x057F,0x0000,0x0000, +0x0580,0x0000,0x0000, 0x0581,0x0000,0x0000, 0x0582,0x0000,0x0000, +0x0583,0x0000,0x0000, 0x0584,0x0000,0x0000, 0x0585,0x0000,0x0000, +0x0586,0x0000,0x0000, 0x0587,0x0000,0x0000, 0x0588,0x0000,0x0000, +0x0589,0x0000,0x0000, 0x058A,0x0000,0x0000, 0x058B,0x0000,0x0000, +0x058C,0x0000,0x0000, 0x058D,0x0000,0x0000, 0x058E,0x0000,0x0000, +0x058F,0x0000,0x0000, 0x0590,0x0000,0x0000, 0x0591,0x0000,0x0000, +0x0592,0x0000,0x0000, 0x0593,0x0000,0x0000, 0x0594,0x0000,0x0000, +0x0595,0x0000,0x0000, 0x0596,0x0000,0x0000, 0x0597,0x0000,0x0000, +0x0598,0x0000,0x0000, 0x0599,0x0000,0x0000, 0x059A,0x0000,0x0000, +0x059B,0x0000,0x0000, 0x059C,0x0000,0x0000, 0x059D,0x0000,0x0000, +0x059E,0x0000,0x0000, 0x059F,0x0000,0x0000, 0x05A0,0x0000,0x0000, +0x05A1,0x0000,0x0000, 0x05A2,0x0000,0x0000, 0x05A3,0x0000,0x0000, +0x05A4,0x0000,0x0000, 0x05A5,0x0000,0x0000, 0x05A6,0x0000,0x0000, +0x05A7,0x0000,0x0000, 0x05A8,0x0000,0x0000, 0x05A9,0x0000,0x0000, +0x05AA,0x0000,0x0000, 0x05AB,0x0000,0x0000, 0x05AC,0x0000,0x0000, +0x05AD,0x0000,0x0000, 0x05AE,0x0000,0x0000, 0x05AF,0x0000,0x0000, +0x05B0,0x0000,0x0000, 0x05B1,0x0000,0x0000, 0x05B2,0x0000,0x0000, +0x05B3,0x0000,0x0000, 0x05B4,0x0000,0x0000, 0x05B5,0x0000,0x0000, +0x05B6,0x0000,0x0000, 0x05B7,0x0000,0x0000, 0x05B8,0x0000,0x0000, +0x05B9,0x0000,0x0000, 0x05BA,0x0000,0x0000, 0x05BB,0x0000,0x0000, +0x05BC,0x0000,0x0000, 0x05BD,0x0000,0x0000, 0x05BE,0x0000,0x0000, +0x05BF,0x0000,0x0000, 0x05C0,0x0000,0x0000, 0x05C1,0x0000,0x0000, +0x05C2,0x0000,0x0000, 0x05C3,0x0000,0x0000, 0x05C4,0x0000,0x0000, +0x05C5,0x0000,0x0000, 0x05C6,0x0000,0x0000, 0x05C7,0x0000,0x0000, +0x05C8,0x0000,0x0000, 0x05C9,0x0000,0x0000, 0xFBC0,0xA3D1,0x0000, +0xFBC0,0xA3D2,0x0000, 0xFBC0,0xA3D3,0x0000, 0xFBC0,0xA3D4,0x0000, +0xFBC0,0xA3D5,0x0000, 0xFBC0,0xA3D6,0x0000, 0xFBC0,0xA3D7,0x0000, +0xFBC0,0xA3D8,0x0000, 0xFBC0,0xA3D9,0x0000, 0xFBC0,0xA3DA,0x0000, +0xFBC0,0xA3DB,0x0000, 0xFBC0,0xA3DC,0x0000, 0xFBC0,0xA3DD,0x0000, +0xFBC0,0xA3DE,0x0000, 0xFBC0,0xA3DF,0x0000, 0xFBC0,0xA3E0,0x0000, +0xFBC0,0xA3E1,0x0000, 0xFBC0,0xA3E2,0x0000, 0xFBC0,0xA3E3,0x0000, +0xFBC0,0xA3E4,0x0000, 0xFBC0,0xA3E5,0x0000, 0xFBC0,0xA3E6,0x0000, +0xFBC0,0xA3E7,0x0000, 0xFBC0,0xA3E8,0x0000, 0xFBC0,0xA3E9,0x0000, +0xFBC0,0xA3EA,0x0000, 0xFBC0,0xA3EB,0x0000, 0xFBC0,0xA3EC,0x0000, +0xFBC0,0xA3ED,0x0000, 0xFBC0,0xA3EE,0x0000, 0xFBC0,0xA3EF,0x0000, +0xFBC0,0xA3F0,0x0000, 0xFBC0,0xA3F1,0x0000, 0xFBC0,0xA3F2,0x0000, +0xFBC0,0xA3F3,0x0000, 0xFBC0,0xA3F4,0x0000, 0xFBC0,0xA3F5,0x0000, +0xFBC0,0xA3F6,0x0000, 0xFBC0,0xA3F7,0x0000, 0xFBC0,0xA3F8,0x0000, +0xFBC0,0xA3F9,0x0000, 0xFBC0,0xA3FA,0x0000, 0xFBC0,0xA3FB,0x0000, +0xFBC0,0xA3FC,0x0000, 0xFBC0,0xA3FD,0x0000, 0xFBC0,0xA3FE,0x0000, +0xFBC0,0xA3FF,0x0000 }; + +uint16 page024data[]= { /* 2400 (5 weights per char) */ +0x05CA,0x0000,0x0000,0x0000,0x0000, +0x05CB,0x0000,0x0000,0x0000,0x0000, +0x05CC,0x0000,0x0000,0x0000,0x0000, +0x05CD,0x0000,0x0000,0x0000,0x0000, +0x05CE,0x0000,0x0000,0x0000,0x0000, +0x05CF,0x0000,0x0000,0x0000,0x0000, +0x05D0,0x0000,0x0000,0x0000,0x0000, +0x05D1,0x0000,0x0000,0x0000,0x0000, +0x05D2,0x0000,0x0000,0x0000,0x0000, +0x05D3,0x0000,0x0000,0x0000,0x0000, +0x05D4,0x0000,0x0000,0x0000,0x0000, +0x05D5,0x0000,0x0000,0x0000,0x0000, +0x05D6,0x0000,0x0000,0x0000,0x0000, +0x05D7,0x0000,0x0000,0x0000,0x0000, +0x05D8,0x0000,0x0000,0x0000,0x0000, +0x05D9,0x0000,0x0000,0x0000,0x0000, +0x05DA,0x0000,0x0000,0x0000,0x0000, +0x05DB,0x0000,0x0000,0x0000,0x0000, +0x05DC,0x0000,0x0000,0x0000,0x0000, +0x05DD,0x0000,0x0000,0x0000,0x0000, +0x05DE,0x0000,0x0000,0x0000,0x0000, +0x05DF,0x0000,0x0000,0x0000,0x0000, +0x05E0,0x0000,0x0000,0x0000,0x0000, +0x05E1,0x0000,0x0000,0x0000,0x0000, +0x05E2,0x0000,0x0000,0x0000,0x0000, +0x05E3,0x0000,0x0000,0x0000,0x0000, +0x05E4,0x0000,0x0000,0x0000,0x0000, +0x05E5,0x0000,0x0000,0x0000,0x0000, +0x05E6,0x0000,0x0000,0x0000,0x0000, +0x05E7,0x0000,0x0000,0x0000,0x0000, +0x05E8,0x0000,0x0000,0x0000,0x0000, +0x05E9,0x0000,0x0000,0x0000,0x0000, +0x05EA,0x0000,0x0000,0x0000,0x0000, +0x05EB,0x0000,0x0000,0x0000,0x0000, +0x05EC,0x0000,0x0000,0x0000,0x0000, +0x05ED,0x0000,0x0000,0x0000,0x0000, +0x05EE,0x0000,0x0000,0x0000,0x0000, +0x05EF,0x0000,0x0000,0x0000,0x0000, +0x05F0,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xA427,0x0000,0x0000,0x0000, +0xFBC0,0xA428,0x0000,0x0000,0x0000, +0xFBC0,0xA429,0x0000,0x0000,0x0000, +0xFBC0,0xA42A,0x0000,0x0000,0x0000, +0xFBC0,0xA42B,0x0000,0x0000,0x0000, +0xFBC0,0xA42C,0x0000,0x0000,0x0000, +0xFBC0,0xA42D,0x0000,0x0000,0x0000, +0xFBC0,0xA42E,0x0000,0x0000,0x0000, +0xFBC0,0xA42F,0x0000,0x0000,0x0000, +0xFBC0,0xA430,0x0000,0x0000,0x0000, +0xFBC0,0xA431,0x0000,0x0000,0x0000, +0xFBC0,0xA432,0x0000,0x0000,0x0000, +0xFBC0,0xA433,0x0000,0x0000,0x0000, +0xFBC0,0xA434,0x0000,0x0000,0x0000, +0xFBC0,0xA435,0x0000,0x0000,0x0000, +0xFBC0,0xA436,0x0000,0x0000,0x0000, +0xFBC0,0xA437,0x0000,0x0000,0x0000, +0xFBC0,0xA438,0x0000,0x0000,0x0000, +0xFBC0,0xA439,0x0000,0x0000,0x0000, +0xFBC0,0xA43A,0x0000,0x0000,0x0000, +0xFBC0,0xA43B,0x0000,0x0000,0x0000, +0xFBC0,0xA43C,0x0000,0x0000,0x0000, +0xFBC0,0xA43D,0x0000,0x0000,0x0000, +0xFBC0,0xA43E,0x0000,0x0000,0x0000, +0xFBC0,0xA43F,0x0000,0x0000,0x0000, +0x05F1,0x0000,0x0000,0x0000,0x0000, +0x05F2,0x0000,0x0000,0x0000,0x0000, +0x05F3,0x0000,0x0000,0x0000,0x0000, +0x05F4,0x0000,0x0000,0x0000,0x0000, +0x05F5,0x0000,0x0000,0x0000,0x0000, +0x05F6,0x0000,0x0000,0x0000,0x0000, +0x05F7,0x0000,0x0000,0x0000,0x0000, +0x05F8,0x0000,0x0000,0x0000,0x0000, +0x05F9,0x0000,0x0000,0x0000,0x0000, +0x05FA,0x0000,0x0000,0x0000,0x0000, +0x05FB,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xA44B,0x0000,0x0000,0x0000, +0xFBC0,0xA44C,0x0000,0x0000,0x0000, +0xFBC0,0xA44D,0x0000,0x0000,0x0000, +0xFBC0,0xA44E,0x0000,0x0000,0x0000, +0xFBC0,0xA44F,0x0000,0x0000,0x0000, +0xFBC0,0xA450,0x0000,0x0000,0x0000, +0xFBC0,0xA451,0x0000,0x0000,0x0000, +0xFBC0,0xA452,0x0000,0x0000,0x0000, +0xFBC0,0xA453,0x0000,0x0000,0x0000, +0xFBC0,0xA454,0x0000,0x0000,0x0000, +0xFBC0,0xA455,0x0000,0x0000,0x0000, +0xFBC0,0xA456,0x0000,0x0000,0x0000, +0xFBC0,0xA457,0x0000,0x0000,0x0000, +0xFBC0,0xA458,0x0000,0x0000,0x0000, +0xFBC0,0xA459,0x0000,0x0000,0x0000, +0xFBC0,0xA45A,0x0000,0x0000,0x0000, +0xFBC0,0xA45B,0x0000,0x0000,0x0000, +0xFBC0,0xA45C,0x0000,0x0000,0x0000, +0xFBC0,0xA45D,0x0000,0x0000,0x0000, +0xFBC0,0xA45E,0x0000,0x0000,0x0000, +0xFBC0,0xA45F,0x0000,0x0000,0x0000, +0x0E2A,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0000,0x0000,0x0000,0x0000, +0x0E2C,0x0000,0x0000,0x0000,0x0000, +0x0E2D,0x0000,0x0000,0x0000,0x0000, +0x0E2E,0x0000,0x0000,0x0000,0x0000, +0x0E2F,0x0000,0x0000,0x0000,0x0000, +0x0E30,0x0000,0x0000,0x0000,0x0000, +0x0E31,0x0000,0x0000,0x0000,0x0000, +0x0E32,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E29,0x0000,0x0000,0x0000, +0x0E2A,0x0E2A,0x0000,0x0000,0x0000, +0x0E2A,0x0E2B,0x0000,0x0000,0x0000, +0x0E2A,0x0E2C,0x0000,0x0000,0x0000, +0x0E2A,0x0E2D,0x0000,0x0000,0x0000, +0x0E2A,0x0E2E,0x0000,0x0000,0x0000, +0x0E2A,0x0E2F,0x0000,0x0000,0x0000, +0x0E2A,0x0E30,0x0000,0x0000,0x0000, +0x0E2A,0x0E31,0x0000,0x0000,0x0000, +0x0E2A,0x0E32,0x0000,0x0000,0x0000, +0x0E2B,0x0E29,0x0000,0x0000,0x0000, +0x0288,0x0E2A,0x0289,0x0000,0x0000, +0x0288,0x0E2B,0x0289,0x0000,0x0000, +0x0288,0x0E2C,0x0289,0x0000,0x0000, +0x0288,0x0E2D,0x0289,0x0000,0x0000, +0x0288,0x0E2E,0x0289,0x0000,0x0000, +0x0288,0x0E2F,0x0289,0x0000,0x0000, +0x0288,0x0E30,0x0289,0x0000,0x0000, +0x0288,0x0E31,0x0289,0x0000,0x0000, +0x0288,0x0E32,0x0289,0x0000,0x0000, +0x0288,0x0E2A,0x0E29,0x0289,0x0000, +0x0288,0x0E2A,0x0E2A,0x0289,0x0000, +0x0288,0x0E2A,0x0E2B,0x0289,0x0000, +0x0288,0x0E2A,0x0E2C,0x0289,0x0000, +0x0288,0x0E2A,0x0E2D,0x0289,0x0000, +0x0288,0x0E2A,0x0E2E,0x0289,0x0000, +0x0288,0x0E2A,0x0E2F,0x0289,0x0000, +0x0288,0x0E2A,0x0E30,0x0289,0x0000, +0x0288,0x0E2A,0x0E31,0x0289,0x0000, +0x0288,0x0E2A,0x0E32,0x0289,0x0000, +0x0288,0x0E2B,0x0E29,0x0289,0x0000, +0x0E2A,0x025D,0x0000,0x0000,0x0000, +0x0E2B,0x025D,0x0000,0x0000,0x0000, +0x0E2C,0x025D,0x0000,0x0000,0x0000, +0x0E2D,0x025D,0x0000,0x0000,0x0000, +0x0E2E,0x025D,0x0000,0x0000,0x0000, +0x0E2F,0x025D,0x0000,0x0000,0x0000, +0x0E30,0x025D,0x0000,0x0000,0x0000, +0x0E31,0x025D,0x0000,0x0000,0x0000, +0x0E32,0x025D,0x0000,0x0000,0x0000, +0x0E2A,0x0E29,0x025D,0x0000,0x0000, +0x0E2A,0x0E2A,0x025D,0x0000,0x0000, +0x0E2A,0x0E2B,0x025D,0x0000,0x0000, +0x0E2A,0x0E2C,0x025D,0x0000,0x0000, +0x0E2A,0x0E2D,0x025D,0x0000,0x0000, +0x0E2A,0x0E2E,0x025D,0x0000,0x0000, +0x0E2A,0x0E2F,0x025D,0x0000,0x0000, +0x0E2A,0x0E30,0x025D,0x0000,0x0000, +0x0E2A,0x0E31,0x025D,0x0000,0x0000, +0x0E2A,0x0E32,0x025D,0x0000,0x0000, +0x0E2B,0x0E29,0x025D,0x0000,0x0000, +0x0288,0x0E33,0x0289,0x0000,0x0000, +0x0288,0x0E4A,0x0289,0x0000,0x0000, +0x0288,0x0E60,0x0289,0x0000,0x0000, +0x0288,0x0E6D,0x0289,0x0000,0x0000, +0x0288,0x0E8B,0x0289,0x0000,0x0000, +0x0288,0x0EB9,0x0289,0x0000,0x0000, +0x0288,0x0EC1,0x0289,0x0000,0x0000, +0x0288,0x0EE1,0x0289,0x0000,0x0000, +0x0288,0x0EFB,0x0289,0x0000,0x0000, +0x0288,0x0F10,0x0289,0x0000,0x0000, +0x0288,0x0F21,0x0289,0x0000,0x0000, +0x0288,0x0F2E,0x0289,0x0000,0x0000, +0x0288,0x0F5B,0x0289,0x0000,0x0000, +0x0288,0x0F64,0x0289,0x0000,0x0000, +0x0288,0x0F82,0x0289,0x0000,0x0000, +0x0288,0x0FA7,0x0289,0x0000,0x0000, +0x0288,0x0FB4,0x0289,0x0000,0x0000, +0x0288,0x0FC0,0x0289,0x0000,0x0000, +0x0288,0x0FEA,0x0289,0x0000,0x0000, +0x0288,0x1002,0x0289,0x0000,0x0000, +0x0288,0x101F,0x0289,0x0000,0x0000, +0x0288,0x1044,0x0289,0x0000,0x0000, +0x0288,0x1051,0x0289,0x0000,0x0000, +0x0288,0x105A,0x0289,0x0000,0x0000, +0x0288,0x105E,0x0289,0x0000,0x0000, +0x0288,0x106A,0x0289,0x0000,0x0000, +0x0E33,0x0000,0x0000,0x0000,0x0000, +0x0E4A,0x0000,0x0000,0x0000,0x0000, +0x0E60,0x0000,0x0000,0x0000,0x0000, +0x0E6D,0x0000,0x0000,0x0000,0x0000, +0x0E8B,0x0000,0x0000,0x0000,0x0000, +0x0EB9,0x0000,0x0000,0x0000,0x0000, +0x0EC1,0x0000,0x0000,0x0000,0x0000, +0x0EE1,0x0000,0x0000,0x0000,0x0000, +0x0EFB,0x0000,0x0000,0x0000,0x0000, +0x0F10,0x0000,0x0000,0x0000,0x0000, +0x0F21,0x0000,0x0000,0x0000,0x0000, +0x0F2E,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0000,0x0000,0x0000,0x0000, +0x0F64,0x0000,0x0000,0x0000,0x0000, +0x0F82,0x0000,0x0000,0x0000,0x0000, +0x0FA7,0x0000,0x0000,0x0000,0x0000, +0x0FB4,0x0000,0x0000,0x0000,0x0000, +0x0FC0,0x0000,0x0000,0x0000,0x0000, +0x0FEA,0x0000,0x0000,0x0000,0x0000, +0x1002,0x0000,0x0000,0x0000,0x0000, +0x101F,0x0000,0x0000,0x0000,0x0000, +0x1044,0x0000,0x0000,0x0000,0x0000, +0x1051,0x0000,0x0000,0x0000,0x0000, +0x105A,0x0000,0x0000,0x0000,0x0000, +0x105E,0x0000,0x0000,0x0000,0x0000, +0x106A,0x0000,0x0000,0x0000,0x0000, +0x0E33,0x0000,0x0000,0x0000,0x0000, +0x0E4A,0x0000,0x0000,0x0000,0x0000, +0x0E60,0x0000,0x0000,0x0000,0x0000, +0x0E6D,0x0000,0x0000,0x0000,0x0000, +0x0E8B,0x0000,0x0000,0x0000,0x0000, +0x0EB9,0x0000,0x0000,0x0000,0x0000, +0x0EC1,0x0000,0x0000,0x0000,0x0000, +0x0EE1,0x0000,0x0000,0x0000,0x0000, +0x0EFB,0x0000,0x0000,0x0000,0x0000, +0x0F10,0x0000,0x0000,0x0000,0x0000, +0x0F21,0x0000,0x0000,0x0000,0x0000, +0x0F2E,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0000,0x0000,0x0000,0x0000, +0x0F64,0x0000,0x0000,0x0000,0x0000, +0x0F82,0x0000,0x0000,0x0000,0x0000, +0x0FA7,0x0000,0x0000,0x0000,0x0000, +0x0FB4,0x0000,0x0000,0x0000,0x0000, +0x0FC0,0x0000,0x0000,0x0000,0x0000, +0x0FEA,0x0000,0x0000,0x0000,0x0000, +0x1002,0x0000,0x0000,0x0000,0x0000, +0x101F,0x0000,0x0000,0x0000,0x0000, +0x1044,0x0000,0x0000,0x0000,0x0000, +0x1051,0x0000,0x0000,0x0000,0x0000, +0x105A,0x0000,0x0000,0x0000,0x0000, +0x105E,0x0000,0x0000,0x0000,0x0000, +0x106A,0x0000,0x0000,0x0000,0x0000, +0x0E29,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E2A,0x0000,0x0000,0x0000, +0x0E2A,0x0E2B,0x0000,0x0000,0x0000, +0x0E2A,0x0E2C,0x0000,0x0000,0x0000, +0x0E2A,0x0E2D,0x0000,0x0000,0x0000, +0x0E2A,0x0E2E,0x0000,0x0000,0x0000, +0x0E2A,0x0E2F,0x0000,0x0000,0x0000, +0x0E2A,0x0E30,0x0000,0x0000,0x0000, +0x0E2A,0x0E31,0x0000,0x0000,0x0000, +0x0E2A,0x0E32,0x0000,0x0000,0x0000, +0x0E2B,0x0E29,0x0000,0x0000,0x0000, +0x0E2A,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0000,0x0000,0x0000,0x0000, +0x0E2C,0x0000,0x0000,0x0000,0x0000, +0x0E2D,0x0000,0x0000,0x0000,0x0000, +0x0E2E,0x0000,0x0000,0x0000,0x0000, +0x0E2F,0x0000,0x0000,0x0000,0x0000, +0x0E30,0x0000,0x0000,0x0000,0x0000, +0x0E31,0x0000,0x0000,0x0000,0x0000, +0x0E32,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E29,0x0000,0x0000,0x0000, +0x0E29,0x0000,0x0000,0x0000,0x0000 +}; + +uint16 page025data[]= { /* 2500 (2 weights per char) */ +0x05FC,0x0000, 0x05FD,0x0000, 0x05FE,0x0000, 0x05FF,0x0000, +0x0600,0x0000, 0x0601,0x0000, 0x0602,0x0000, 0x0603,0x0000, +0x0604,0x0000, 0x0605,0x0000, 0x0606,0x0000, 0x0607,0x0000, +0x0608,0x0000, 0x0609,0x0000, 0x060A,0x0000, 0x060B,0x0000, +0x060C,0x0000, 0x060D,0x0000, 0x060E,0x0000, 0x060F,0x0000, +0x0610,0x0000, 0x0611,0x0000, 0x0612,0x0000, 0x0613,0x0000, +0x0614,0x0000, 0x0615,0x0000, 0x0616,0x0000, 0x0617,0x0000, +0x0618,0x0000, 0x0619,0x0000, 0x061A,0x0000, 0x061B,0x0000, +0x061C,0x0000, 0x061D,0x0000, 0x061E,0x0000, 0x061F,0x0000, +0x0620,0x0000, 0x0621,0x0000, 0x0622,0x0000, 0x0623,0x0000, +0x0624,0x0000, 0x0625,0x0000, 0x0626,0x0000, 0x0627,0x0000, +0x0628,0x0000, 0x0629,0x0000, 0x062A,0x0000, 0x062B,0x0000, +0x062C,0x0000, 0x062D,0x0000, 0x062E,0x0000, 0x062F,0x0000, +0x0630,0x0000, 0x0631,0x0000, 0x0632,0x0000, 0x0633,0x0000, +0x0634,0x0000, 0x0635,0x0000, 0x0636,0x0000, 0x0637,0x0000, +0x0638,0x0000, 0x0639,0x0000, 0x063A,0x0000, 0x063B,0x0000, +0x063C,0x0000, 0x063D,0x0000, 0x063E,0x0000, 0x063F,0x0000, +0x0640,0x0000, 0x0641,0x0000, 0x0642,0x0000, 0x0643,0x0000, +0x0644,0x0000, 0x0645,0x0000, 0x0646,0x0000, 0x0647,0x0000, +0x0648,0x0000, 0x0649,0x0000, 0x064A,0x0000, 0x064B,0x0000, +0x064C,0x0000, 0x064D,0x0000, 0x064E,0x0000, 0x064F,0x0000, +0x0650,0x0000, 0x0651,0x0000, 0x0652,0x0000, 0x0653,0x0000, +0x0654,0x0000, 0x0655,0x0000, 0x0656,0x0000, 0x0657,0x0000, +0x0658,0x0000, 0x0659,0x0000, 0x065A,0x0000, 0x065B,0x0000, +0x065C,0x0000, 0x065D,0x0000, 0x065E,0x0000, 0x065F,0x0000, +0x0660,0x0000, 0x0661,0x0000, 0x0662,0x0000, 0x0663,0x0000, +0x0664,0x0000, 0x0665,0x0000, 0x0666,0x0000, 0x0667,0x0000, +0x0668,0x0000, 0x0669,0x0000, 0x066A,0x0000, 0x066B,0x0000, +0x066C,0x0000, 0x066D,0x0000, 0x066E,0x0000, 0x066F,0x0000, +0x0670,0x0000, 0x0671,0x0000, 0x0672,0x0000, 0x0673,0x0000, +0x0674,0x0000, 0x0675,0x0000, 0x0676,0x0000, 0x0677,0x0000, +0x0678,0x0000, 0x0679,0x0000, 0x067A,0x0000, 0x067B,0x0000, +0x067C,0x0000, 0x067D,0x0000, 0x067E,0x0000, 0x067F,0x0000, +0x0680,0x0000, 0x0681,0x0000, 0x0682,0x0000, 0x0683,0x0000, +0x0684,0x0000, 0x0685,0x0000, 0x0686,0x0000, 0x0687,0x0000, +0x0688,0x0000, 0x0689,0x0000, 0x068A,0x0000, 0x068B,0x0000, +0x068C,0x0000, 0x068D,0x0000, 0x068E,0x0000, 0x068F,0x0000, +0x0690,0x0000, 0x0691,0x0000, 0x0692,0x0000, 0x0693,0x0000, +0x0694,0x0000, 0x0695,0x0000, 0x0696,0x0000, 0x0697,0x0000, +0x0698,0x0000, 0x0699,0x0000, 0x069A,0x0000, 0x069B,0x0000, +0x069C,0x0000, 0x069D,0x0000, 0x069E,0x0000, 0x069F,0x0000, +0x06A0,0x0000, 0x06A1,0x0000, 0x06A2,0x0000, 0x06A3,0x0000, +0x06A4,0x0000, 0x06A5,0x0000, 0x06A6,0x0000, 0x06A7,0x0000, +0x06A8,0x0000, 0x06A9,0x0000, 0x06AA,0x0000, 0x06AB,0x0000, +0x06AC,0x0000, 0x06AD,0x0000, 0x06AE,0x0000, 0x06AF,0x0000, +0x06B0,0x0000, 0x06B1,0x0000, 0x06B2,0x0000, 0x06B3,0x0000, +0x06B4,0x0000, 0x06B5,0x0000, 0x06B6,0x0000, 0x06B7,0x0000, +0x06B8,0x0000, 0x06B9,0x0000, 0x06BA,0x0000, 0x06BB,0x0000, +0x06BC,0x0000, 0x06BD,0x0000, 0x06BE,0x0000, 0x06BF,0x0000, +0x06C0,0x0000, 0x06C1,0x0000, 0x06C2,0x0000, 0x06C3,0x0000, +0x06C4,0x0000, 0x06C5,0x0000, 0x06C6,0x0000, 0x06C7,0x0000, +0x06C8,0x0000, 0x06C9,0x0000, 0x06CA,0x0000, 0x06CB,0x0000, +0x06CC,0x0000, 0x06CD,0x0000, 0x06CE,0x0000, 0x06CF,0x0000, +0x06D0,0x0000, 0x06D1,0x0000, 0x06D2,0x0000, 0x06D3,0x0000, +0x06D4,0x0000, 0x06D5,0x0000, 0x06D6,0x0000, 0x06D7,0x0000, +0x06D8,0x0000, 0x06D9,0x0000, 0x06DA,0x0000, 0x06DB,0x0000, +0x06DC,0x0000, 0x06DD,0x0000, 0x06DE,0x0000, 0x06DF,0x0000, +0x06E0,0x0000, 0x06E1,0x0000, 0x06E2,0x0000, 0x06E3,0x0000, +0x06E4,0x0000, 0x06E5,0x0000, 0x06E6,0x0000, 0x06E7,0x0000, +0x06E8,0x0000, 0x06E9,0x0000, 0x06EA,0x0000, 0x06EB,0x0000, +0x06EC,0x0000, 0x06ED,0x0000, 0x06EE,0x0000, 0x06EF,0x0000, +0x06F0,0x0000, 0x06F1,0x0000, 0x06F2,0x0000, 0x06F3,0x0000, +0x06F4,0x0000, 0x06F5,0x0000, 0x06F6,0x0000, 0x06F7,0x0000, +0x06F8,0x0000, 0x06F9,0x0000, 0x06FA,0x0000, 0x06FB,0x0000 +}; + +uint16 page026data[]= { /* 2600 (3 weights per char) */ +0x06FC,0x0000,0x0000, 0x06FD,0x0000,0x0000, 0x06FE,0x0000,0x0000, +0x06FF,0x0000,0x0000, 0x0700,0x0000,0x0000, 0x0701,0x0000,0x0000, +0x0702,0x0000,0x0000, 0x0703,0x0000,0x0000, 0x0704,0x0000,0x0000, +0x0705,0x0000,0x0000, 0x0706,0x0000,0x0000, 0x0707,0x0000,0x0000, +0x0708,0x0000,0x0000, 0x0709,0x0000,0x0000, 0x070A,0x0000,0x0000, +0x070B,0x0000,0x0000, 0x070C,0x0000,0x0000, 0x070D,0x0000,0x0000, +0x070E,0x0000,0x0000, 0x070F,0x0000,0x0000, 0x0710,0x0000,0x0000, +0x0711,0x0000,0x0000, 0x0712,0x0000,0x0000, 0x0713,0x0000,0x0000, +0xFBC0,0xA618,0x0000, 0x0714,0x0000,0x0000, 0x0715,0x0000,0x0000, +0x0716,0x0000,0x0000, 0x0717,0x0000,0x0000, 0x0718,0x0000,0x0000, +0x0719,0x0000,0x0000, 0x071A,0x0000,0x0000, 0x071B,0x0000,0x0000, +0x071C,0x0000,0x0000, 0x071D,0x0000,0x0000, 0x071E,0x0000,0x0000, +0x071F,0x0000,0x0000, 0x0720,0x0000,0x0000, 0x0721,0x0000,0x0000, +0x0722,0x0000,0x0000, 0x0723,0x0000,0x0000, 0x0724,0x0000,0x0000, +0x0725,0x0000,0x0000, 0x0726,0x0000,0x0000, 0x0727,0x0000,0x0000, +0x0728,0x0000,0x0000, 0x0729,0x0000,0x0000, 0x072A,0x0000,0x0000, +0x0B2F,0x0000,0x0000, 0x0B30,0x0000,0x0000, 0x0B31,0x0000,0x0000, +0x0B32,0x0000,0x0000, 0x0B33,0x0000,0x0000, 0x0B34,0x0000,0x0000, +0x0B35,0x0000,0x0000, 0x0B36,0x0000,0x0000, 0x072B,0x0000,0x0000, +0x072C,0x0000,0x0000, 0x072D,0x0000,0x0000, 0x072E,0x0000,0x0000, +0x072F,0x0000,0x0000, 0x0730,0x0000,0x0000, 0x0731,0x0000,0x0000, +0x0732,0x0000,0x0000, 0x0733,0x0000,0x0000, 0x0734,0x0000,0x0000, +0x0735,0x0000,0x0000, 0x0736,0x0000,0x0000, 0x0737,0x0000,0x0000, +0x0738,0x0000,0x0000, 0x0739,0x0000,0x0000, 0x073A,0x0000,0x0000, +0x073B,0x0000,0x0000, 0x073C,0x0000,0x0000, 0x073D,0x0000,0x0000, +0x073E,0x0000,0x0000, 0x073F,0x0000,0x0000, 0x0740,0x0000,0x0000, +0x0741,0x0000,0x0000, 0x0742,0x0000,0x0000, 0x0743,0x0000,0x0000, +0x0744,0x0000,0x0000, 0x0745,0x0000,0x0000, 0x0746,0x0000,0x0000, +0x0747,0x0000,0x0000, 0x0748,0x0000,0x0000, 0x0749,0x0000,0x0000, +0x074A,0x0000,0x0000, 0x074B,0x0000,0x0000, 0x074C,0x0000,0x0000, +0x074D,0x0000,0x0000, 0x074E,0x0000,0x0000, 0x074F,0x0000,0x0000, +0x0750,0x0000,0x0000, 0x0751,0x0000,0x0000, 0x0752,0x0000,0x0000, +0x0753,0x0000,0x0000, 0x0754,0x0000,0x0000, 0x0755,0x0000,0x0000, +0x0756,0x0000,0x0000, 0x0757,0x0000,0x0000, 0x0758,0x0000,0x0000, +0x0759,0x0000,0x0000, 0x075A,0x0000,0x0000, 0x075B,0x0000,0x0000, +0x075C,0x0000,0x0000, 0x075D,0x0000,0x0000, 0x075E,0x0000,0x0000, +0x075F,0x0000,0x0000, 0x0D2B,0x0000,0x0000, 0x0D2C,0x0000,0x0000, +0x0D2D,0x0000,0x0000, 0x0760,0x0000,0x0000, 0x0761,0x0000,0x0000, +0x0762,0x0000,0x0000, 0x0763,0x0000,0x0000, 0x0764,0x0000,0x0000, +0x0765,0x0000,0x0000, 0x0766,0x0000,0x0000, 0x0767,0x0000,0x0000, +0x0768,0x0000,0x0000, 0x0769,0x0000,0x0000, 0x076A,0x0000,0x0000, +0x076B,0x0000,0x0000, 0x076C,0x0000,0x0000, 0x076D,0x0000,0x0000, +0xFBC0,0xA67E,0x0000, 0xFBC0,0xA67F,0x0000, 0x076E,0x0000,0x0000, +0x076F,0x0000,0x0000, 0x0770,0x0000,0x0000, 0x0771,0x0000,0x0000, +0x0772,0x0000,0x0000, 0x0773,0x0000,0x0000, 0x0774,0x0000,0x0000, +0x0775,0x0000,0x0000, 0x0776,0x0000,0x0000, 0x0777,0x0000,0x0000, +0x0B29,0x0000,0x0000, 0x0B2A,0x0000,0x0000, 0x0B2B,0x0000,0x0000, +0x0B2C,0x0000,0x0000, 0x0B2D,0x0000,0x0000, 0x0B2E,0x0000,0x0000, +0x0778,0x0000,0x0000, 0x0779,0x0000,0x0000, 0xFBC0,0xA692,0x0000, +0xFBC0,0xA693,0x0000, 0xFBC0,0xA694,0x0000, 0xFBC0,0xA695,0x0000, +0xFBC0,0xA696,0x0000, 0xFBC0,0xA697,0x0000, 0xFBC0,0xA698,0x0000, +0xFBC0,0xA699,0x0000, 0xFBC0,0xA69A,0x0000, 0xFBC0,0xA69B,0x0000, +0xFBC0,0xA69C,0x0000, 0xFBC0,0xA69D,0x0000, 0xFBC0,0xA69E,0x0000, +0xFBC0,0xA69F,0x0000, 0x077A,0x0000,0x0000, 0x077B,0x0000,0x0000, +0xFBC0,0xA6A2,0x0000, 0xFBC0,0xA6A3,0x0000, 0xFBC0,0xA6A4,0x0000, +0xFBC0,0xA6A5,0x0000, 0xFBC0,0xA6A6,0x0000, 0xFBC0,0xA6A7,0x0000, +0xFBC0,0xA6A8,0x0000, 0xFBC0,0xA6A9,0x0000, 0xFBC0,0xA6AA,0x0000, +0xFBC0,0xA6AB,0x0000, 0xFBC0,0xA6AC,0x0000, 0xFBC0,0xA6AD,0x0000, +0xFBC0,0xA6AE,0x0000, 0xFBC0,0xA6AF,0x0000, 0xFBC0,0xA6B0,0x0000, +0xFBC0,0xA6B1,0x0000, 0xFBC0,0xA6B2,0x0000, 0xFBC0,0xA6B3,0x0000, +0xFBC0,0xA6B4,0x0000, 0xFBC0,0xA6B5,0x0000, 0xFBC0,0xA6B6,0x0000, +0xFBC0,0xA6B7,0x0000, 0xFBC0,0xA6B8,0x0000, 0xFBC0,0xA6B9,0x0000, +0xFBC0,0xA6BA,0x0000, 0xFBC0,0xA6BB,0x0000, 0xFBC0,0xA6BC,0x0000, +0xFBC0,0xA6BD,0x0000, 0xFBC0,0xA6BE,0x0000, 0xFBC0,0xA6BF,0x0000, +0xFBC0,0xA6C0,0x0000, 0xFBC0,0xA6C1,0x0000, 0xFBC0,0xA6C2,0x0000, +0xFBC0,0xA6C3,0x0000, 0xFBC0,0xA6C4,0x0000, 0xFBC0,0xA6C5,0x0000, +0xFBC0,0xA6C6,0x0000, 0xFBC0,0xA6C7,0x0000, 0xFBC0,0xA6C8,0x0000, +0xFBC0,0xA6C9,0x0000, 0xFBC0,0xA6CA,0x0000, 0xFBC0,0xA6CB,0x0000, +0xFBC0,0xA6CC,0x0000, 0xFBC0,0xA6CD,0x0000, 0xFBC0,0xA6CE,0x0000, +0xFBC0,0xA6CF,0x0000, 0xFBC0,0xA6D0,0x0000, 0xFBC0,0xA6D1,0x0000, +0xFBC0,0xA6D2,0x0000, 0xFBC0,0xA6D3,0x0000, 0xFBC0,0xA6D4,0x0000, +0xFBC0,0xA6D5,0x0000, 0xFBC0,0xA6D6,0x0000, 0xFBC0,0xA6D7,0x0000, +0xFBC0,0xA6D8,0x0000, 0xFBC0,0xA6D9,0x0000, 0xFBC0,0xA6DA,0x0000, +0xFBC0,0xA6DB,0x0000, 0xFBC0,0xA6DC,0x0000, 0xFBC0,0xA6DD,0x0000, +0xFBC0,0xA6DE,0x0000, 0xFBC0,0xA6DF,0x0000, 0xFBC0,0xA6E0,0x0000, +0xFBC0,0xA6E1,0x0000, 0xFBC0,0xA6E2,0x0000, 0xFBC0,0xA6E3,0x0000, +0xFBC0,0xA6E4,0x0000, 0xFBC0,0xA6E5,0x0000, 0xFBC0,0xA6E6,0x0000, +0xFBC0,0xA6E7,0x0000, 0xFBC0,0xA6E8,0x0000, 0xFBC0,0xA6E9,0x0000, +0xFBC0,0xA6EA,0x0000, 0xFBC0,0xA6EB,0x0000, 0xFBC0,0xA6EC,0x0000, +0xFBC0,0xA6ED,0x0000, 0xFBC0,0xA6EE,0x0000, 0xFBC0,0xA6EF,0x0000, +0xFBC0,0xA6F0,0x0000, 0xFBC0,0xA6F1,0x0000, 0xFBC0,0xA6F2,0x0000, +0xFBC0,0xA6F3,0x0000, 0xFBC0,0xA6F4,0x0000, 0xFBC0,0xA6F5,0x0000, +0xFBC0,0xA6F6,0x0000, 0xFBC0,0xA6F7,0x0000, 0xFBC0,0xA6F8,0x0000, +0xFBC0,0xA6F9,0x0000, 0xFBC0,0xA6FA,0x0000, 0xFBC0,0xA6FB,0x0000, +0xFBC0,0xA6FC,0x0000, 0xFBC0,0xA6FD,0x0000, 0xFBC0,0xA6FE,0x0000, +0xFBC0,0xA6FF,0x0000 }; + +uint16 page027data[]= { /* 2700 (3 weights per char) */ +0xFBC0,0xA700,0x0000, 0x077C,0x0000,0x0000, 0x077D,0x0000,0x0000, +0x077E,0x0000,0x0000, 0x077F,0x0000,0x0000, 0xFBC0,0xA705,0x0000, +0x0780,0x0000,0x0000, 0x0781,0x0000,0x0000, 0x0782,0x0000,0x0000, +0x0783,0x0000,0x0000, 0xFBC0,0xA70A,0x0000, 0xFBC0,0xA70B,0x0000, +0x0784,0x0000,0x0000, 0x0785,0x0000,0x0000, 0x0786,0x0000,0x0000, +0x0787,0x0000,0x0000, 0x0788,0x0000,0x0000, 0x0789,0x0000,0x0000, +0x078A,0x0000,0x0000, 0x078B,0x0000,0x0000, 0x078C,0x0000,0x0000, +0x078D,0x0000,0x0000, 0x078E,0x0000,0x0000, 0x078F,0x0000,0x0000, +0x0790,0x0000,0x0000, 0x0791,0x0000,0x0000, 0x0792,0x0000,0x0000, +0x0793,0x0000,0x0000, 0x0794,0x0000,0x0000, 0x0795,0x0000,0x0000, +0x0796,0x0000,0x0000, 0x0797,0x0000,0x0000, 0x0798,0x0000,0x0000, +0x0799,0x0000,0x0000, 0x079A,0x0000,0x0000, 0x079B,0x0000,0x0000, +0x079C,0x0000,0x0000, 0x079D,0x0000,0x0000, 0x079E,0x0000,0x0000, +0x079F,0x0000,0x0000, 0xFBC0,0xA728,0x0000, 0x07A0,0x0000,0x0000, +0x07A1,0x0000,0x0000, 0x07A2,0x0000,0x0000, 0x07A3,0x0000,0x0000, +0x07A4,0x0000,0x0000, 0x07A5,0x0000,0x0000, 0x07A6,0x0000,0x0000, +0x07A7,0x0000,0x0000, 0x07A8,0x0000,0x0000, 0x07A9,0x0000,0x0000, +0x07AA,0x0000,0x0000, 0x07AB,0x0000,0x0000, 0x07AC,0x0000,0x0000, +0x07AD,0x0000,0x0000, 0x07AE,0x0000,0x0000, 0x07AF,0x0000,0x0000, +0x07B0,0x0000,0x0000, 0x07B1,0x0000,0x0000, 0x07B2,0x0000,0x0000, +0x07B3,0x0000,0x0000, 0x07B4,0x0000,0x0000, 0x07B5,0x0000,0x0000, +0x07B6,0x0000,0x0000, 0x07B7,0x0000,0x0000, 0x07B8,0x0000,0x0000, +0x07B9,0x0000,0x0000, 0x07BA,0x0000,0x0000, 0x07BB,0x0000,0x0000, +0x07BC,0x0000,0x0000, 0x07BD,0x0000,0x0000, 0x07BE,0x0000,0x0000, +0x07BF,0x0000,0x0000, 0x07C0,0x0000,0x0000, 0x07C1,0x0000,0x0000, +0x07C2,0x0000,0x0000, 0xFBC0,0xA74C,0x0000, 0x07C3,0x0000,0x0000, +0xFBC0,0xA74E,0x0000, 0x07C4,0x0000,0x0000, 0x07C5,0x0000,0x0000, +0x07C6,0x0000,0x0000, 0x07C7,0x0000,0x0000, 0xFBC0,0xA753,0x0000, +0xFBC0,0xA754,0x0000, 0xFBC0,0xA755,0x0000, 0x07C8,0x0000,0x0000, +0xFBC0,0xA757,0x0000, 0x07C9,0x0000,0x0000, 0x07CA,0x0000,0x0000, +0x07CB,0x0000,0x0000, 0x07CC,0x0000,0x0000, 0x07CD,0x0000,0x0000, +0x07CE,0x0000,0x0000, 0x07CF,0x0000,0x0000, 0xFBC0,0xA75F,0x0000, +0xFBC0,0xA760,0x0000, 0x07D0,0x0000,0x0000, 0x07D1,0x0000,0x0000, +0x07D2,0x0000,0x0000, 0x07D3,0x0000,0x0000, 0x07D4,0x0000,0x0000, +0x07D5,0x0000,0x0000, 0x07D6,0x0000,0x0000, 0x07D7,0x0000,0x0000, +0x07D8,0x0000,0x0000, 0x07D9,0x0000,0x0000, 0x07DA,0x0000,0x0000, +0x07DB,0x0000,0x0000, 0x07DC,0x0000,0x0000, 0x07DD,0x0000,0x0000, +0x07DE,0x0000,0x0000, 0x07DF,0x0000,0x0000, 0x07E0,0x0000,0x0000, +0x07E1,0x0000,0x0000, 0x07E2,0x0000,0x0000, 0x07E3,0x0000,0x0000, +0x07E4,0x0000,0x0000, 0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, +0x0E2C,0x0000,0x0000, 0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, +0x0E2F,0x0000,0x0000, 0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, +0x0E32,0x0000,0x0000, 0x0E2A,0x0E29,0x0000, 0x0E2A,0x0000,0x0000, +0x0E2B,0x0000,0x0000, 0x0E2C,0x0000,0x0000, 0x0E2D,0x0000,0x0000, +0x0E2E,0x0000,0x0000, 0x0E2F,0x0000,0x0000, 0x0E30,0x0000,0x0000, +0x0E31,0x0000,0x0000, 0x0E32,0x0000,0x0000, 0x0E2A,0x0E29,0x0000, +0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, 0x0E2C,0x0000,0x0000, +0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, 0x0E2F,0x0000,0x0000, +0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, 0x0E32,0x0000,0x0000, +0x0E2A,0x0E29,0x0000, 0x07E5,0x0000,0x0000, 0xFBC0,0xA795,0x0000, +0xFBC0,0xA796,0x0000, 0xFBC0,0xA797,0x0000, 0x07E6,0x0000,0x0000, +0x07E7,0x0000,0x0000, 0x07E8,0x0000,0x0000, 0x07E9,0x0000,0x0000, +0x07EA,0x0000,0x0000, 0x07EB,0x0000,0x0000, 0x07EC,0x0000,0x0000, +0x07ED,0x0000,0x0000, 0x07EE,0x0000,0x0000, 0x07EF,0x0000,0x0000, +0x07F0,0x0000,0x0000, 0x07F1,0x0000,0x0000, 0x07F2,0x0000,0x0000, +0x07F3,0x0000,0x0000, 0x07F4,0x0000,0x0000, 0x07F5,0x0000,0x0000, +0x07F6,0x0000,0x0000, 0x07F7,0x0000,0x0000, 0x07F8,0x0000,0x0000, +0x07F9,0x0000,0x0000, 0x07FA,0x0000,0x0000, 0x07FB,0x0000,0x0000, +0x07FC,0x0000,0x0000, 0x07FD,0x0000,0x0000, 0xFBC0,0xA7B0,0x0000, +0x07FE,0x0000,0x0000, 0x07FF,0x0000,0x0000, 0x0800,0x0000,0x0000, +0x0801,0x0000,0x0000, 0x0802,0x0000,0x0000, 0x0803,0x0000,0x0000, +0x0804,0x0000,0x0000, 0x0805,0x0000,0x0000, 0x0806,0x0000,0x0000, +0x0807,0x0000,0x0000, 0x0808,0x0000,0x0000, 0x0809,0x0000,0x0000, +0x080A,0x0000,0x0000, 0x080B,0x0000,0x0000, 0xFBC0,0xA7BF,0x0000, +0xFBC0,0xA7C0,0x0000, 0xFBC0,0xA7C1,0x0000, 0xFBC0,0xA7C2,0x0000, +0xFBC0,0xA7C3,0x0000, 0xFBC0,0xA7C4,0x0000, 0xFBC0,0xA7C5,0x0000, +0xFBC0,0xA7C6,0x0000, 0xFBC0,0xA7C7,0x0000, 0xFBC0,0xA7C8,0x0000, +0xFBC0,0xA7C9,0x0000, 0xFBC0,0xA7CA,0x0000, 0xFBC0,0xA7CB,0x0000, +0xFBC0,0xA7CC,0x0000, 0xFBC0,0xA7CD,0x0000, 0xFBC0,0xA7CE,0x0000, +0xFBC0,0xA7CF,0x0000, 0x080C,0x0000,0x0000, 0x080D,0x0000,0x0000, +0x080E,0x0000,0x0000, 0x080F,0x0000,0x0000, 0x0810,0x0000,0x0000, +0x0811,0x0000,0x0000, 0x0812,0x0000,0x0000, 0x0813,0x0000,0x0000, +0x0814,0x0000,0x0000, 0x0815,0x0000,0x0000, 0x0816,0x0000,0x0000, +0x0817,0x0000,0x0000, 0x0818,0x0000,0x0000, 0x0819,0x0000,0x0000, +0x081A,0x0000,0x0000, 0x081B,0x0000,0x0000, 0x081C,0x0000,0x0000, +0x081D,0x0000,0x0000, 0x081E,0x0000,0x0000, 0x081F,0x0000,0x0000, +0x0820,0x0000,0x0000, 0x0821,0x0000,0x0000, 0x0822,0x0000,0x0000, +0x0823,0x0000,0x0000, 0x0824,0x0000,0x0000, 0x0825,0x0000,0x0000, +0x0826,0x0000,0x0000, 0x0827,0x0000,0x0000, 0xFBC0,0xA7EC,0x0000, +0xFBC0,0xA7ED,0x0000, 0xFBC0,0xA7EE,0x0000, 0xFBC0,0xA7EF,0x0000, +0x0828,0x0000,0x0000, 0x0829,0x0000,0x0000, 0x082A,0x0000,0x0000, +0x082B,0x0000,0x0000, 0x082C,0x0000,0x0000, 0x082D,0x0000,0x0000, +0x082E,0x0000,0x0000, 0x082F,0x0000,0x0000, 0x0830,0x0000,0x0000, +0x0831,0x0000,0x0000, 0x0832,0x0000,0x0000, 0x0833,0x0000,0x0000, +0x0834,0x0000,0x0000, 0x0835,0x0000,0x0000, 0x0836,0x0000,0x0000, +0x0837,0x0000,0x0000 }; + +uint16 page028data[]= { /* 2800 (2 weights per char) */ +0x0A29,0x0000, 0x0A2A,0x0000, 0x0A2B,0x0000, 0x0A2C,0x0000, +0x0A2D,0x0000, 0x0A2E,0x0000, 0x0A2F,0x0000, 0x0A30,0x0000, +0x0A31,0x0000, 0x0A32,0x0000, 0x0A33,0x0000, 0x0A34,0x0000, +0x0A35,0x0000, 0x0A36,0x0000, 0x0A37,0x0000, 0x0A38,0x0000, +0x0A39,0x0000, 0x0A3A,0x0000, 0x0A3B,0x0000, 0x0A3C,0x0000, +0x0A3D,0x0000, 0x0A3E,0x0000, 0x0A3F,0x0000, 0x0A40,0x0000, +0x0A41,0x0000, 0x0A42,0x0000, 0x0A43,0x0000, 0x0A44,0x0000, +0x0A45,0x0000, 0x0A46,0x0000, 0x0A47,0x0000, 0x0A48,0x0000, +0x0A49,0x0000, 0x0A4A,0x0000, 0x0A4B,0x0000, 0x0A4C,0x0000, +0x0A4D,0x0000, 0x0A4E,0x0000, 0x0A4F,0x0000, 0x0A50,0x0000, +0x0A51,0x0000, 0x0A52,0x0000, 0x0A53,0x0000, 0x0A54,0x0000, +0x0A55,0x0000, 0x0A56,0x0000, 0x0A57,0x0000, 0x0A58,0x0000, +0x0A59,0x0000, 0x0A5A,0x0000, 0x0A5B,0x0000, 0x0A5C,0x0000, +0x0A5D,0x0000, 0x0A5E,0x0000, 0x0A5F,0x0000, 0x0A60,0x0000, +0x0A61,0x0000, 0x0A62,0x0000, 0x0A63,0x0000, 0x0A64,0x0000, +0x0A65,0x0000, 0x0A66,0x0000, 0x0A67,0x0000, 0x0A68,0x0000, +0x0A69,0x0000, 0x0A6A,0x0000, 0x0A6B,0x0000, 0x0A6C,0x0000, +0x0A6D,0x0000, 0x0A6E,0x0000, 0x0A6F,0x0000, 0x0A70,0x0000, +0x0A71,0x0000, 0x0A72,0x0000, 0x0A73,0x0000, 0x0A74,0x0000, +0x0A75,0x0000, 0x0A76,0x0000, 0x0A77,0x0000, 0x0A78,0x0000, +0x0A79,0x0000, 0x0A7A,0x0000, 0x0A7B,0x0000, 0x0A7C,0x0000, +0x0A7D,0x0000, 0x0A7E,0x0000, 0x0A7F,0x0000, 0x0A80,0x0000, +0x0A81,0x0000, 0x0A82,0x0000, 0x0A83,0x0000, 0x0A84,0x0000, +0x0A85,0x0000, 0x0A86,0x0000, 0x0A87,0x0000, 0x0A88,0x0000, +0x0A89,0x0000, 0x0A8A,0x0000, 0x0A8B,0x0000, 0x0A8C,0x0000, +0x0A8D,0x0000, 0x0A8E,0x0000, 0x0A8F,0x0000, 0x0A90,0x0000, +0x0A91,0x0000, 0x0A92,0x0000, 0x0A93,0x0000, 0x0A94,0x0000, +0x0A95,0x0000, 0x0A96,0x0000, 0x0A97,0x0000, 0x0A98,0x0000, +0x0A99,0x0000, 0x0A9A,0x0000, 0x0A9B,0x0000, 0x0A9C,0x0000, +0x0A9D,0x0000, 0x0A9E,0x0000, 0x0A9F,0x0000, 0x0AA0,0x0000, +0x0AA1,0x0000, 0x0AA2,0x0000, 0x0AA3,0x0000, 0x0AA4,0x0000, +0x0AA5,0x0000, 0x0AA6,0x0000, 0x0AA7,0x0000, 0x0AA8,0x0000, +0x0AA9,0x0000, 0x0AAA,0x0000, 0x0AAB,0x0000, 0x0AAC,0x0000, +0x0AAD,0x0000, 0x0AAE,0x0000, 0x0AAF,0x0000, 0x0AB0,0x0000, +0x0AB1,0x0000, 0x0AB2,0x0000, 0x0AB3,0x0000, 0x0AB4,0x0000, +0x0AB5,0x0000, 0x0AB6,0x0000, 0x0AB7,0x0000, 0x0AB8,0x0000, +0x0AB9,0x0000, 0x0ABA,0x0000, 0x0ABB,0x0000, 0x0ABC,0x0000, +0x0ABD,0x0000, 0x0ABE,0x0000, 0x0ABF,0x0000, 0x0AC0,0x0000, +0x0AC1,0x0000, 0x0AC2,0x0000, 0x0AC3,0x0000, 0x0AC4,0x0000, +0x0AC5,0x0000, 0x0AC6,0x0000, 0x0AC7,0x0000, 0x0AC8,0x0000, +0x0AC9,0x0000, 0x0ACA,0x0000, 0x0ACB,0x0000, 0x0ACC,0x0000, +0x0ACD,0x0000, 0x0ACE,0x0000, 0x0ACF,0x0000, 0x0AD0,0x0000, +0x0AD1,0x0000, 0x0AD2,0x0000, 0x0AD3,0x0000, 0x0AD4,0x0000, +0x0AD5,0x0000, 0x0AD6,0x0000, 0x0AD7,0x0000, 0x0AD8,0x0000, +0x0AD9,0x0000, 0x0ADA,0x0000, 0x0ADB,0x0000, 0x0ADC,0x0000, +0x0ADD,0x0000, 0x0ADE,0x0000, 0x0ADF,0x0000, 0x0AE0,0x0000, +0x0AE1,0x0000, 0x0AE2,0x0000, 0x0AE3,0x0000, 0x0AE4,0x0000, +0x0AE5,0x0000, 0x0AE6,0x0000, 0x0AE7,0x0000, 0x0AE8,0x0000, +0x0AE9,0x0000, 0x0AEA,0x0000, 0x0AEB,0x0000, 0x0AEC,0x0000, +0x0AED,0x0000, 0x0AEE,0x0000, 0x0AEF,0x0000, 0x0AF0,0x0000, +0x0AF1,0x0000, 0x0AF2,0x0000, 0x0AF3,0x0000, 0x0AF4,0x0000, +0x0AF5,0x0000, 0x0AF6,0x0000, 0x0AF7,0x0000, 0x0AF8,0x0000, +0x0AF9,0x0000, 0x0AFA,0x0000, 0x0AFB,0x0000, 0x0AFC,0x0000, +0x0AFD,0x0000, 0x0AFE,0x0000, 0x0AFF,0x0000, 0x0B00,0x0000, +0x0B01,0x0000, 0x0B02,0x0000, 0x0B03,0x0000, 0x0B04,0x0000, +0x0B05,0x0000, 0x0B06,0x0000, 0x0B07,0x0000, 0x0B08,0x0000, +0x0B09,0x0000, 0x0B0A,0x0000, 0x0B0B,0x0000, 0x0B0C,0x0000, +0x0B0D,0x0000, 0x0B0E,0x0000, 0x0B0F,0x0000, 0x0B10,0x0000, +0x0B11,0x0000, 0x0B12,0x0000, 0x0B13,0x0000, 0x0B14,0x0000, +0x0B15,0x0000, 0x0B16,0x0000, 0x0B17,0x0000, 0x0B18,0x0000, +0x0B19,0x0000, 0x0B1A,0x0000, 0x0B1B,0x0000, 0x0B1C,0x0000, +0x0B1D,0x0000, 0x0B1E,0x0000, 0x0B1F,0x0000, 0x0B20,0x0000, +0x0B21,0x0000, 0x0B22,0x0000, 0x0B23,0x0000, 0x0B24,0x0000, +0x0B25,0x0000, 0x0B26,0x0000, 0x0B27,0x0000, 0x0B28,0x0000 +}; + +uint16 page029data[]= { /* 2900 (2 weights per char) */ +0x0838,0x0000, 0x0839,0x0000, 0x083A,0x0000, 0x083B,0x0000, +0x083C,0x0000, 0x083D,0x0000, 0x083E,0x0000, 0x083F,0x0000, +0x0840,0x0000, 0x0841,0x0000, 0x0842,0x0000, 0x0843,0x0000, +0x0844,0x0000, 0x0845,0x0000, 0x0846,0x0000, 0x0847,0x0000, +0x0848,0x0000, 0x0849,0x0000, 0x084A,0x0000, 0x084B,0x0000, +0x084C,0x0000, 0x084D,0x0000, 0x084E,0x0000, 0x084F,0x0000, +0x0850,0x0000, 0x0851,0x0000, 0x0852,0x0000, 0x0853,0x0000, +0x0854,0x0000, 0x0855,0x0000, 0x0856,0x0000, 0x0857,0x0000, +0x0858,0x0000, 0x0859,0x0000, 0x085A,0x0000, 0x085B,0x0000, +0x085C,0x0000, 0x085D,0x0000, 0x085E,0x0000, 0x085F,0x0000, +0x0860,0x0000, 0x0861,0x0000, 0x0862,0x0000, 0x0863,0x0000, +0x0864,0x0000, 0x0865,0x0000, 0x0866,0x0000, 0x0867,0x0000, +0x0868,0x0000, 0x0869,0x0000, 0x086A,0x0000, 0x086B,0x0000, +0x086C,0x0000, 0x086D,0x0000, 0x086E,0x0000, 0x086F,0x0000, +0x0870,0x0000, 0x0871,0x0000, 0x0872,0x0000, 0x0873,0x0000, +0x0874,0x0000, 0x0875,0x0000, 0x0876,0x0000, 0x0877,0x0000, +0x0878,0x0000, 0x0879,0x0000, 0x087A,0x0000, 0x087B,0x0000, +0x087C,0x0000, 0x087D,0x0000, 0x087E,0x0000, 0x087F,0x0000, +0x0880,0x0000, 0x0881,0x0000, 0x0882,0x0000, 0x0883,0x0000, +0x0884,0x0000, 0x0885,0x0000, 0x0886,0x0000, 0x0887,0x0000, +0x0888,0x0000, 0x0889,0x0000, 0x088A,0x0000, 0x088B,0x0000, +0x088C,0x0000, 0x088D,0x0000, 0x088E,0x0000, 0x088F,0x0000, +0x0890,0x0000, 0x0891,0x0000, 0x0892,0x0000, 0x0893,0x0000, +0x0894,0x0000, 0x0895,0x0000, 0x0896,0x0000, 0x0897,0x0000, +0x0898,0x0000, 0x0899,0x0000, 0x089A,0x0000, 0x089B,0x0000, +0x089C,0x0000, 0x089D,0x0000, 0x089E,0x0000, 0x089F,0x0000, +0x08A0,0x0000, 0x08A1,0x0000, 0x08A2,0x0000, 0x08A3,0x0000, +0x08A4,0x0000, 0x08A5,0x0000, 0x08A6,0x0000, 0x08A7,0x0000, +0x08A8,0x0000, 0x08A9,0x0000, 0x08AA,0x0000, 0x08AB,0x0000, +0x08AC,0x0000, 0x08AD,0x0000, 0x08AE,0x0000, 0x08AF,0x0000, +0x08B0,0x0000, 0x08B1,0x0000, 0x08B2,0x0000, 0x08B3,0x0000, +0x08B4,0x0000, 0x08B5,0x0000, 0x08B6,0x0000, 0x08B7,0x0000, +0x08B8,0x0000, 0x08B9,0x0000, 0x08BA,0x0000, 0x0298,0x0000, +0x0299,0x0000, 0x029A,0x0000, 0x029B,0x0000, 0x029C,0x0000, +0x029D,0x0000, 0x029E,0x0000, 0x029F,0x0000, 0x02A0,0x0000, +0x02A1,0x0000, 0x02A2,0x0000, 0x02A3,0x0000, 0x02A4,0x0000, +0x02A5,0x0000, 0x02A6,0x0000, 0x02A7,0x0000, 0x02A8,0x0000, +0x02A9,0x0000, 0x02AA,0x0000, 0x02AB,0x0000, 0x02AC,0x0000, +0x02AD,0x0000, 0x08BB,0x0000, 0x08BC,0x0000, 0x08BD,0x0000, +0x08BE,0x0000, 0x08BF,0x0000, 0x08C0,0x0000, 0x08C1,0x0000, +0x08C2,0x0000, 0x08C3,0x0000, 0x08C4,0x0000, 0x08C5,0x0000, +0x08C6,0x0000, 0x08C7,0x0000, 0x08C8,0x0000, 0x08C9,0x0000, +0x08CA,0x0000, 0x08CB,0x0000, 0x08CC,0x0000, 0x08CD,0x0000, +0x08CE,0x0000, 0x08CF,0x0000, 0x08D0,0x0000, 0x08D1,0x0000, +0x08D2,0x0000, 0x08D3,0x0000, 0x08D4,0x0000, 0x08D5,0x0000, +0x08D6,0x0000, 0x08D7,0x0000, 0x08D8,0x0000, 0x08D9,0x0000, +0x08DA,0x0000, 0x08DB,0x0000, 0x08DC,0x0000, 0x08DD,0x0000, +0x08DE,0x0000, 0x08DF,0x0000, 0x08E0,0x0000, 0x08E1,0x0000, +0x08E2,0x0000, 0x08E3,0x0000, 0x08E4,0x0000, 0x08E5,0x0000, +0x08E6,0x0000, 0x08E7,0x0000, 0x08E8,0x0000, 0x08E9,0x0000, +0x08EA,0x0000, 0x08EB,0x0000, 0x08EC,0x0000, 0x08ED,0x0000, +0x08EE,0x0000, 0x08EF,0x0000, 0x08F0,0x0000, 0x08F1,0x0000, +0x08F2,0x0000, 0x08F3,0x0000, 0x08F4,0x0000, 0x08F5,0x0000, +0x08F6,0x0000, 0x08F7,0x0000, 0x08F8,0x0000, 0x08F9,0x0000, +0x08FA,0x0000, 0x08FB,0x0000, 0x08FC,0x0000, 0x08FD,0x0000, +0x08FE,0x0000, 0x08FF,0x0000, 0x0900,0x0000, 0x0901,0x0000, +0x0902,0x0000, 0x0903,0x0000, 0x0904,0x0000, 0x0905,0x0000, +0x0906,0x0000, 0x0907,0x0000, 0x0908,0x0000, 0x0909,0x0000, +0x090A,0x0000, 0x090B,0x0000, 0x090C,0x0000, 0x090D,0x0000, +0x090E,0x0000, 0x090F,0x0000, 0x0910,0x0000, 0x0911,0x0000, +0x0912,0x0000, 0x0913,0x0000, 0x0914,0x0000, 0x0915,0x0000, +0x0916,0x0000, 0x0917,0x0000, 0x0918,0x0000, 0x0919,0x0000, +0x091A,0x0000, 0x091B,0x0000, 0x091C,0x0000, 0x091D,0x0000, +0x0296,0x0000, 0x0297,0x0000, 0x091E,0x0000, 0x091F,0x0000 +}; + +uint16 page02Adata[]= { /* 2A00 (5 weights per char) */ +0x0920,0x0000,0x0000,0x0000,0x0000, +0x0921,0x0000,0x0000,0x0000,0x0000, +0x0922,0x0000,0x0000,0x0000,0x0000, +0x0923,0x0000,0x0000,0x0000,0x0000, +0x0924,0x0000,0x0000,0x0000,0x0000, +0x0925,0x0000,0x0000,0x0000,0x0000, +0x0926,0x0000,0x0000,0x0000,0x0000, +0x0927,0x0000,0x0000,0x0000,0x0000, +0x0928,0x0000,0x0000,0x0000,0x0000, +0x0929,0x0000,0x0000,0x0000,0x0000, +0x092A,0x0000,0x0000,0x0000,0x0000, +0x092B,0x0000,0x0000,0x0000,0x0000, +0x044B,0x044B,0x044B,0x044B,0x0000, +0x092C,0x0000,0x0000,0x0000,0x0000, +0x092D,0x0000,0x0000,0x0000,0x0000, +0x092E,0x0000,0x0000,0x0000,0x0000, +0x092F,0x0000,0x0000,0x0000,0x0000, +0x0930,0x0000,0x0000,0x0000,0x0000, +0x0931,0x0000,0x0000,0x0000,0x0000, +0x0932,0x0000,0x0000,0x0000,0x0000, +0x0933,0x0000,0x0000,0x0000,0x0000, +0x0934,0x0000,0x0000,0x0000,0x0000, +0x0935,0x0000,0x0000,0x0000,0x0000, +0x0936,0x0000,0x0000,0x0000,0x0000, +0x0937,0x0000,0x0000,0x0000,0x0000, +0x0938,0x0000,0x0000,0x0000,0x0000, +0x0939,0x0000,0x0000,0x0000,0x0000, +0x093A,0x0000,0x0000,0x0000,0x0000, +0x093B,0x0000,0x0000,0x0000,0x0000, +0x093C,0x0000,0x0000,0x0000,0x0000, +0x093D,0x0000,0x0000,0x0000,0x0000, +0x093E,0x0000,0x0000,0x0000,0x0000, +0x093F,0x0000,0x0000,0x0000,0x0000, +0x0940,0x0000,0x0000,0x0000,0x0000, +0x0941,0x0000,0x0000,0x0000,0x0000, +0x0942,0x0000,0x0000,0x0000,0x0000, +0x0943,0x0000,0x0000,0x0000,0x0000, +0x0944,0x0000,0x0000,0x0000,0x0000, +0x0945,0x0000,0x0000,0x0000,0x0000, +0x0946,0x0000,0x0000,0x0000,0x0000, +0x0947,0x0000,0x0000,0x0000,0x0000, +0x0948,0x0000,0x0000,0x0000,0x0000, +0x0949,0x0000,0x0000,0x0000,0x0000, +0x094A,0x0000,0x0000,0x0000,0x0000, +0x094B,0x0000,0x0000,0x0000,0x0000, +0x094C,0x0000,0x0000,0x0000,0x0000, +0x094D,0x0000,0x0000,0x0000,0x0000, +0x094E,0x0000,0x0000,0x0000,0x0000, +0x094F,0x0000,0x0000,0x0000,0x0000, +0x0950,0x0000,0x0000,0x0000,0x0000, +0x0951,0x0000,0x0000,0x0000,0x0000, +0x0952,0x0000,0x0000,0x0000,0x0000, +0x0953,0x0000,0x0000,0x0000,0x0000, +0x0954,0x0000,0x0000,0x0000,0x0000, +0x0955,0x0000,0x0000,0x0000,0x0000, +0x0956,0x0000,0x0000,0x0000,0x0000, +0x0957,0x0000,0x0000,0x0000,0x0000, +0x0958,0x0000,0x0000,0x0000,0x0000, +0x0959,0x0000,0x0000,0x0000,0x0000, +0x095A,0x0000,0x0000,0x0000,0x0000, +0x095B,0x0000,0x0000,0x0000,0x0000, +0x095C,0x0000,0x0000,0x0000,0x0000, +0x095D,0x0000,0x0000,0x0000,0x0000, +0x095E,0x0000,0x0000,0x0000,0x0000, +0x095F,0x0000,0x0000,0x0000,0x0000, +0x0960,0x0000,0x0000,0x0000,0x0000, +0x0961,0x0000,0x0000,0x0000,0x0000, +0x0962,0x0000,0x0000,0x0000,0x0000, +0x0963,0x0000,0x0000,0x0000,0x0000, +0x0964,0x0000,0x0000,0x0000,0x0000, +0x0965,0x0000,0x0000,0x0000,0x0000, +0x0966,0x0000,0x0000,0x0000,0x0000, +0x0967,0x0000,0x0000,0x0000,0x0000, +0x0968,0x0000,0x0000,0x0000,0x0000, +0x0969,0x0000,0x0000,0x0000,0x0000, +0x096A,0x0000,0x0000,0x0000,0x0000, +0x096B,0x0000,0x0000,0x0000,0x0000, +0x096C,0x0000,0x0000,0x0000,0x0000, +0x096D,0x0000,0x0000,0x0000,0x0000, +0x096E,0x0000,0x0000,0x0000,0x0000, +0x096F,0x0000,0x0000,0x0000,0x0000, +0x0970,0x0000,0x0000,0x0000,0x0000, +0x0971,0x0000,0x0000,0x0000,0x0000, +0x0972,0x0000,0x0000,0x0000,0x0000, +0x0973,0x0000,0x0000,0x0000,0x0000, +0x0974,0x0000,0x0000,0x0000,0x0000, +0x0975,0x0000,0x0000,0x0000,0x0000, +0x0976,0x0000,0x0000,0x0000,0x0000, +0x0977,0x0000,0x0000,0x0000,0x0000, +0x0978,0x0000,0x0000,0x0000,0x0000, +0x0979,0x0000,0x0000,0x0000,0x0000, +0x097A,0x0000,0x0000,0x0000,0x0000, +0x097B,0x0000,0x0000,0x0000,0x0000, +0x097C,0x0000,0x0000,0x0000,0x0000, +0x097D,0x0000,0x0000,0x0000,0x0000, +0x097E,0x0000,0x0000,0x0000,0x0000, +0x097F,0x0000,0x0000,0x0000,0x0000, +0x0980,0x0000,0x0000,0x0000,0x0000, +0x0981,0x0000,0x0000,0x0000,0x0000, +0x0982,0x0000,0x0000,0x0000,0x0000, +0x0983,0x0000,0x0000,0x0000,0x0000, +0x0984,0x0000,0x0000,0x0000,0x0000, +0x0985,0x0000,0x0000,0x0000,0x0000, +0x0986,0x0000,0x0000,0x0000,0x0000, +0x0987,0x0000,0x0000,0x0000,0x0000, +0x0988,0x0000,0x0000,0x0000,0x0000, +0x0989,0x0000,0x0000,0x0000,0x0000, +0x098A,0x0000,0x0000,0x0000,0x0000, +0x098B,0x0000,0x0000,0x0000,0x0000, +0x098C,0x0000,0x0000,0x0000,0x0000, +0x098D,0x0000,0x0000,0x0000,0x0000, +0x098E,0x0000,0x0000,0x0000,0x0000, +0x098F,0x0000,0x0000,0x0000,0x0000, +0x0990,0x0000,0x0000,0x0000,0x0000, +0x0991,0x0000,0x0000,0x0000,0x0000, +0x0992,0x0000,0x0000,0x0000,0x0000, +0x023D,0x023D,0x042D,0x0000,0x0000, +0x042D,0x042D,0x0000,0x0000,0x0000, +0x042D,0x042D,0x042D,0x0000,0x0000, +0x0993,0x0000,0x0000,0x0000,0x0000, +0x0994,0x0000,0x0000,0x0000,0x0000, +0x0995,0x0000,0x0000,0x0000,0x0000, +0x0996,0x0000,0x0000,0x0000,0x0000, +0x0997,0x0000,0x0000,0x0000,0x0000, +0x0998,0x0000,0x0000,0x0000,0x0000, +0x0999,0x0000,0x0000,0x0000,0x0000, +0x099A,0x0000,0x0000,0x0000,0x0000, +0x099B,0x0000,0x0000,0x0000,0x0000, +0x099C,0x0000,0x0000,0x0000,0x0000, +0x099D,0x0000,0x0000,0x0000,0x0000, +0x099E,0x0000,0x0000,0x0000,0x0000, +0x099F,0x0000,0x0000,0x0000,0x0000, +0x09A0,0x0000,0x0000,0x0000,0x0000, +0x09A1,0x0000,0x0000,0x0000,0x0000, +0x09A2,0x0000,0x0000,0x0000,0x0000, +0x09A3,0x0000,0x0000,0x0000,0x0000, +0x09A4,0x0000,0x0000,0x0000,0x0000, +0x09A5,0x0000,0x0000,0x0000,0x0000, +0x09A6,0x0000,0x0000,0x0000,0x0000, +0x09A7,0x0000,0x0000,0x0000,0x0000, +0x09A8,0x0000,0x0000,0x0000,0x0000, +0x09A9,0x0000,0x0000,0x0000,0x0000, +0x09AA,0x0000,0x0000,0x0000,0x0000, +0x09AB,0x0000,0x0000,0x0000,0x0000, +0x09AC,0x0000,0x0000,0x0000,0x0000, +0x09AD,0x0000,0x0000,0x0000,0x0000, +0x09AE,0x0000,0x0000,0x0000,0x0000, +0x09AF,0x0000,0x0000,0x0000,0x0000, +0x09B0,0x0000,0x0000,0x0000,0x0000, +0x09B1,0x0000,0x0000,0x0000,0x0000, +0x09B2,0x0000,0x0000,0x0000,0x0000, +0x09B3,0x0000,0x0000,0x0000,0x0000, +0x09B4,0x0000,0x0000,0x0000,0x0000, +0x09B5,0x0000,0x0000,0x0000,0x0000, +0x09B6,0x0000,0x0000,0x0000,0x0000, +0x09B7,0x0000,0x0000,0x0000,0x0000, +0x09B8,0x0000,0x0000,0x0000,0x0000, +0x09B9,0x0000,0x0000,0x0000,0x0000, +0x09BA,0x0000,0x0000,0x0000,0x0000, +0x09BB,0x0000,0x0000,0x0000,0x0000, +0x09BC,0x0000,0x0000,0x0000,0x0000, +0x09BD,0x0000,0x0000,0x0000,0x0000, +0x09BE,0x0000,0x0000,0x0000,0x0000, +0x09BF,0x0000,0x0000,0x0000,0x0000, +0x09C0,0x0000,0x0000,0x0000,0x0000, +0x09C1,0x0000,0x0000,0x0000,0x0000, +0x09C2,0x0000,0x0000,0x0000,0x0000, +0x09C3,0x0000,0x0000,0x0000,0x0000, +0x09C4,0x0000,0x0000,0x0000,0x0000, +0x09C5,0x0000,0x0000,0x0000,0x0000, +0x09C6,0x0000,0x0000,0x0000,0x0000, +0x09C7,0x0000,0x0000,0x0000,0x0000, +0x09C8,0x0000,0x0000,0x0000,0x0000, +0x09C9,0x0000,0x0000,0x0000,0x0000, +0x09CA,0x0000,0x0000,0x0000,0x0000, +0x09CB,0x0000,0x0000,0x0000,0x0000, +0x09CC,0x0000,0x0000,0x0000,0x0000, +0x09CD,0x0000,0x0000,0x0000,0x0000, +0x09CE,0x0000,0x0000,0x0000,0x0000, +0x09CF,0x0000,0x0000,0x0000,0x0000, +0x09D0,0x0000,0x0000,0x0000,0x0000, +0x09D1,0x0000,0x0000,0x0000,0x0000, +0x09D2,0x0000,0x0000,0x0000,0x0000, +0x09D3,0x0000,0x0000,0x0000,0x0000, +0x09D4,0x0000,0x0000,0x0000,0x0000, +0x09D5,0x0000,0x0000,0x0000,0x0000, +0x09D6,0x0000,0x0000,0x0000,0x0000, +0x09D7,0x0000,0x0000,0x0000,0x0000, +0x09D8,0x0000,0x0000,0x0000,0x0000, +0x09D9,0x0000,0x0000,0x0000,0x0000, +0x09DA,0x0000,0x0000,0x0000,0x0000, +0x09DB,0x0000,0x0000,0x0000,0x0000, +0x09DC,0x0000,0x0000,0x0000,0x0000, +0x09DD,0x0000,0x0000,0x0000,0x0000, +0x09DE,0x0000,0x0000,0x0000,0x0000, +0x09DF,0x0000,0x0000,0x0000,0x0000, +0x09E0,0x0000,0x0000,0x0000,0x0000, +0x09E1,0x0000,0x0000,0x0000,0x0000, +0x09E2,0x0000,0x0000,0x0000,0x0000, +0x09E3,0x0000,0x0000,0x0000,0x0000, +0x09E4,0x0000,0x0000,0x0000,0x0000, +0x09E5,0x0000,0x0000,0x0000,0x0000, +0x09E6,0x0000,0x0000,0x0000,0x0000, +0x09E7,0x0000,0x0000,0x0000,0x0000, +0x09E8,0x0000,0x0000,0x0000,0x0000, +0x09E9,0x0000,0x0000,0x0000,0x0000, +0x09EA,0x0000,0x0000,0x0000,0x0000, +0x09EB,0x0000,0x0000,0x0000,0x0000, +0x09EC,0x0000,0x0000,0x0000,0x0000, +0x09ED,0x0000,0x0000,0x0000,0x0000, +0x09EE,0x0000,0x0000,0x0000,0x0000, +0x09EF,0x0000,0x0000,0x0000,0x0000, +0x09F0,0x0000,0x0000,0x0000,0x0000, +0x09F1,0x0000,0x0000,0x0000,0x0000, +0x09F2,0x0000,0x0000,0x0000,0x0000, +0x09F3,0x0000,0x0000,0x0000,0x0000, +0x09F4,0x0000,0x0000,0x0000,0x0000, +0x09F5,0x0000,0x0000,0x0000,0x0000, +0x09F6,0x0000,0x0000,0x0000,0x0000, +0x09F7,0x0000,0x0000,0x0000,0x0000, +0x09F8,0x0000,0x0000,0x0000,0x0000, +0x09F8,0x0000,0x0000,0x0000,0x0000, +0x09F9,0x0000,0x0000,0x0000,0x0000, +0x09FA,0x0000,0x0000,0x0000,0x0000, +0x09FB,0x0000,0x0000,0x0000,0x0000, +0x09FC,0x0000,0x0000,0x0000,0x0000, +0x09FD,0x0000,0x0000,0x0000,0x0000, +0x09FE,0x0000,0x0000,0x0000,0x0000, +0x09FF,0x0000,0x0000,0x0000,0x0000, +0x0A00,0x0000,0x0000,0x0000,0x0000, +0x0A01,0x0000,0x0000,0x0000,0x0000, +0x0A02,0x0000,0x0000,0x0000,0x0000, +0x0A03,0x0000,0x0000,0x0000,0x0000, +0x0A04,0x0000,0x0000,0x0000,0x0000, +0x0A05,0x0000,0x0000,0x0000,0x0000, +0x0A06,0x0000,0x0000,0x0000,0x0000, +0x0A07,0x0000,0x0000,0x0000,0x0000, +0x0A08,0x0000,0x0000,0x0000,0x0000, +0x0A09,0x0000,0x0000,0x0000,0x0000, +0x0A0A,0x0000,0x0000,0x0000,0x0000, +0x0A0B,0x0000,0x0000,0x0000,0x0000, +0x0A0C,0x0000,0x0000,0x0000,0x0000, +0x0A0D,0x0000,0x0000,0x0000,0x0000, +0x0A0E,0x0000,0x0000,0x0000,0x0000, +0x0A0F,0x0000,0x0000,0x0000,0x0000, +0x0A10,0x0000,0x0000,0x0000,0x0000, +0x0A11,0x0000,0x0000,0x0000,0x0000, +0x0A12,0x0000,0x0000,0x0000,0x0000, +0x0A13,0x0000,0x0000,0x0000,0x0000, +0x0A14,0x0000,0x0000,0x0000,0x0000, +0x0A15,0x0000,0x0000,0x0000,0x0000, +0x0A16,0x0000,0x0000,0x0000,0x0000, +0x0A17,0x0000,0x0000,0x0000,0x0000, +0x0A18,0x0000,0x0000,0x0000,0x0000, +0x0A19,0x0000,0x0000,0x0000,0x0000, +0x0A1A,0x0000,0x0000,0x0000,0x0000 +}; + +uint16 page02Bdata[]= { /* 2B00 (3 weights per char) */ +0x0A1B,0x0000,0x0000, 0x0A1C,0x0000,0x0000, 0x0A1D,0x0000,0x0000, +0x0A1E,0x0000,0x0000, 0x0A1F,0x0000,0x0000, 0x0A20,0x0000,0x0000, +0x0A21,0x0000,0x0000, 0x0A22,0x0000,0x0000, 0x0A23,0x0000,0x0000, +0x0A24,0x0000,0x0000, 0x0A25,0x0000,0x0000, 0x0A26,0x0000,0x0000, +0x0A27,0x0000,0x0000, 0x0A28,0x0000,0x0000, 0xFBC0,0xAB0E,0x0000, +0xFBC0,0xAB0F,0x0000, 0xFBC0,0xAB10,0x0000, 0xFBC0,0xAB11,0x0000, +0xFBC0,0xAB12,0x0000, 0xFBC0,0xAB13,0x0000, 0xFBC0,0xAB14,0x0000, +0xFBC0,0xAB15,0x0000, 0xFBC0,0xAB16,0x0000, 0xFBC0,0xAB17,0x0000, +0xFBC0,0xAB18,0x0000, 0xFBC0,0xAB19,0x0000, 0xFBC0,0xAB1A,0x0000, +0xFBC0,0xAB1B,0x0000, 0xFBC0,0xAB1C,0x0000, 0xFBC0,0xAB1D,0x0000, +0xFBC0,0xAB1E,0x0000, 0xFBC0,0xAB1F,0x0000, 0xFBC0,0xAB20,0x0000, +0xFBC0,0xAB21,0x0000, 0xFBC0,0xAB22,0x0000, 0xFBC0,0xAB23,0x0000, +0xFBC0,0xAB24,0x0000, 0xFBC0,0xAB25,0x0000, 0xFBC0,0xAB26,0x0000, +0xFBC0,0xAB27,0x0000, 0xFBC0,0xAB28,0x0000, 0xFBC0,0xAB29,0x0000, +0xFBC0,0xAB2A,0x0000, 0xFBC0,0xAB2B,0x0000, 0xFBC0,0xAB2C,0x0000, +0xFBC0,0xAB2D,0x0000, 0xFBC0,0xAB2E,0x0000, 0xFBC0,0xAB2F,0x0000, +0xFBC0,0xAB30,0x0000, 0xFBC0,0xAB31,0x0000, 0xFBC0,0xAB32,0x0000, +0xFBC0,0xAB33,0x0000, 0xFBC0,0xAB34,0x0000, 0xFBC0,0xAB35,0x0000, +0xFBC0,0xAB36,0x0000, 0xFBC0,0xAB37,0x0000, 0xFBC0,0xAB38,0x0000, +0xFBC0,0xAB39,0x0000, 0xFBC0,0xAB3A,0x0000, 0xFBC0,0xAB3B,0x0000, +0xFBC0,0xAB3C,0x0000, 0xFBC0,0xAB3D,0x0000, 0xFBC0,0xAB3E,0x0000, +0xFBC0,0xAB3F,0x0000, 0xFBC0,0xAB40,0x0000, 0xFBC0,0xAB41,0x0000, +0xFBC0,0xAB42,0x0000, 0xFBC0,0xAB43,0x0000, 0xFBC0,0xAB44,0x0000, +0xFBC0,0xAB45,0x0000, 0xFBC0,0xAB46,0x0000, 0xFBC0,0xAB47,0x0000, +0xFBC0,0xAB48,0x0000, 0xFBC0,0xAB49,0x0000, 0xFBC0,0xAB4A,0x0000, +0xFBC0,0xAB4B,0x0000, 0xFBC0,0xAB4C,0x0000, 0xFBC0,0xAB4D,0x0000, +0xFBC0,0xAB4E,0x0000, 0xFBC0,0xAB4F,0x0000, 0xFBC0,0xAB50,0x0000, +0xFBC0,0xAB51,0x0000, 0xFBC0,0xAB52,0x0000, 0xFBC0,0xAB53,0x0000, +0xFBC0,0xAB54,0x0000, 0xFBC0,0xAB55,0x0000, 0xFBC0,0xAB56,0x0000, +0xFBC0,0xAB57,0x0000, 0xFBC0,0xAB58,0x0000, 0xFBC0,0xAB59,0x0000, +0xFBC0,0xAB5A,0x0000, 0xFBC0,0xAB5B,0x0000, 0xFBC0,0xAB5C,0x0000, +0xFBC0,0xAB5D,0x0000, 0xFBC0,0xAB5E,0x0000, 0xFBC0,0xAB5F,0x0000, +0xFBC0,0xAB60,0x0000, 0xFBC0,0xAB61,0x0000, 0xFBC0,0xAB62,0x0000, +0xFBC0,0xAB63,0x0000, 0xFBC0,0xAB64,0x0000, 0xFBC0,0xAB65,0x0000, +0xFBC0,0xAB66,0x0000, 0xFBC0,0xAB67,0x0000, 0xFBC0,0xAB68,0x0000, +0xFBC0,0xAB69,0x0000, 0xFBC0,0xAB6A,0x0000, 0xFBC0,0xAB6B,0x0000, +0xFBC0,0xAB6C,0x0000, 0xFBC0,0xAB6D,0x0000, 0xFBC0,0xAB6E,0x0000, +0xFBC0,0xAB6F,0x0000, 0xFBC0,0xAB70,0x0000, 0xFBC0,0xAB71,0x0000, +0xFBC0,0xAB72,0x0000, 0xFBC0,0xAB73,0x0000, 0xFBC0,0xAB74,0x0000, +0xFBC0,0xAB75,0x0000, 0xFBC0,0xAB76,0x0000, 0xFBC0,0xAB77,0x0000, +0xFBC0,0xAB78,0x0000, 0xFBC0,0xAB79,0x0000, 0xFBC0,0xAB7A,0x0000, +0xFBC0,0xAB7B,0x0000, 0xFBC0,0xAB7C,0x0000, 0xFBC0,0xAB7D,0x0000, +0xFBC0,0xAB7E,0x0000, 0xFBC0,0xAB7F,0x0000, 0xFBC0,0xAB80,0x0000, +0xFBC0,0xAB81,0x0000, 0xFBC0,0xAB82,0x0000, 0xFBC0,0xAB83,0x0000, +0xFBC0,0xAB84,0x0000, 0xFBC0,0xAB85,0x0000, 0xFBC0,0xAB86,0x0000, +0xFBC0,0xAB87,0x0000, 0xFBC0,0xAB88,0x0000, 0xFBC0,0xAB89,0x0000, +0xFBC0,0xAB8A,0x0000, 0xFBC0,0xAB8B,0x0000, 0xFBC0,0xAB8C,0x0000, +0xFBC0,0xAB8D,0x0000, 0xFBC0,0xAB8E,0x0000, 0xFBC0,0xAB8F,0x0000, +0xFBC0,0xAB90,0x0000, 0xFBC0,0xAB91,0x0000, 0xFBC0,0xAB92,0x0000, +0xFBC0,0xAB93,0x0000, 0xFBC0,0xAB94,0x0000, 0xFBC0,0xAB95,0x0000, +0xFBC0,0xAB96,0x0000, 0xFBC0,0xAB97,0x0000, 0xFBC0,0xAB98,0x0000, +0xFBC0,0xAB99,0x0000, 0xFBC0,0xAB9A,0x0000, 0xFBC0,0xAB9B,0x0000, +0xFBC0,0xAB9C,0x0000, 0xFBC0,0xAB9D,0x0000, 0xFBC0,0xAB9E,0x0000, +0xFBC0,0xAB9F,0x0000, 0xFBC0,0xABA0,0x0000, 0xFBC0,0xABA1,0x0000, +0xFBC0,0xABA2,0x0000, 0xFBC0,0xABA3,0x0000, 0xFBC0,0xABA4,0x0000, +0xFBC0,0xABA5,0x0000, 0xFBC0,0xABA6,0x0000, 0xFBC0,0xABA7,0x0000, +0xFBC0,0xABA8,0x0000, 0xFBC0,0xABA9,0x0000, 0xFBC0,0xABAA,0x0000, +0xFBC0,0xABAB,0x0000, 0xFBC0,0xABAC,0x0000, 0xFBC0,0xABAD,0x0000, +0xFBC0,0xABAE,0x0000, 0xFBC0,0xABAF,0x0000, 0xFBC0,0xABB0,0x0000, +0xFBC0,0xABB1,0x0000, 0xFBC0,0xABB2,0x0000, 0xFBC0,0xABB3,0x0000, +0xFBC0,0xABB4,0x0000, 0xFBC0,0xABB5,0x0000, 0xFBC0,0xABB6,0x0000, +0xFBC0,0xABB7,0x0000, 0xFBC0,0xABB8,0x0000, 0xFBC0,0xABB9,0x0000, +0xFBC0,0xABBA,0x0000, 0xFBC0,0xABBB,0x0000, 0xFBC0,0xABBC,0x0000, +0xFBC0,0xABBD,0x0000, 0xFBC0,0xABBE,0x0000, 0xFBC0,0xABBF,0x0000, +0xFBC0,0xABC0,0x0000, 0xFBC0,0xABC1,0x0000, 0xFBC0,0xABC2,0x0000, +0xFBC0,0xABC3,0x0000, 0xFBC0,0xABC4,0x0000, 0xFBC0,0xABC5,0x0000, +0xFBC0,0xABC6,0x0000, 0xFBC0,0xABC7,0x0000, 0xFBC0,0xABC8,0x0000, +0xFBC0,0xABC9,0x0000, 0xFBC0,0xABCA,0x0000, 0xFBC0,0xABCB,0x0000, +0xFBC0,0xABCC,0x0000, 0xFBC0,0xABCD,0x0000, 0xFBC0,0xABCE,0x0000, +0xFBC0,0xABCF,0x0000, 0xFBC0,0xABD0,0x0000, 0xFBC0,0xABD1,0x0000, +0xFBC0,0xABD2,0x0000, 0xFBC0,0xABD3,0x0000, 0xFBC0,0xABD4,0x0000, +0xFBC0,0xABD5,0x0000, 0xFBC0,0xABD6,0x0000, 0xFBC0,0xABD7,0x0000, +0xFBC0,0xABD8,0x0000, 0xFBC0,0xABD9,0x0000, 0xFBC0,0xABDA,0x0000, +0xFBC0,0xABDB,0x0000, 0xFBC0,0xABDC,0x0000, 0xFBC0,0xABDD,0x0000, +0xFBC0,0xABDE,0x0000, 0xFBC0,0xABDF,0x0000, 0xFBC0,0xABE0,0x0000, +0xFBC0,0xABE1,0x0000, 0xFBC0,0xABE2,0x0000, 0xFBC0,0xABE3,0x0000, +0xFBC0,0xABE4,0x0000, 0xFBC0,0xABE5,0x0000, 0xFBC0,0xABE6,0x0000, +0xFBC0,0xABE7,0x0000, 0xFBC0,0xABE8,0x0000, 0xFBC0,0xABE9,0x0000, +0xFBC0,0xABEA,0x0000, 0xFBC0,0xABEB,0x0000, 0xFBC0,0xABEC,0x0000, +0xFBC0,0xABED,0x0000, 0xFBC0,0xABEE,0x0000, 0xFBC0,0xABEF,0x0000, +0xFBC0,0xABF0,0x0000, 0xFBC0,0xABF1,0x0000, 0xFBC0,0xABF2,0x0000, +0xFBC0,0xABF3,0x0000, 0xFBC0,0xABF4,0x0000, 0xFBC0,0xABF5,0x0000, +0xFBC0,0xABF6,0x0000, 0xFBC0,0xABF7,0x0000, 0xFBC0,0xABF8,0x0000, +0xFBC0,0xABF9,0x0000, 0xFBC0,0xABFA,0x0000, 0xFBC0,0xABFB,0x0000, +0xFBC0,0xABFC,0x0000, 0xFBC0,0xABFD,0x0000, 0xFBC0,0xABFE,0x0000, +0xFBC0,0xABFF,0x0000 }; + +uint16 page02Edata[]= { /* 2E00 (3 weights per char) */ +0xFBC0,0xAE00,0x0000, 0xFBC0,0xAE01,0x0000, 0xFBC0,0xAE02,0x0000, +0xFBC0,0xAE03,0x0000, 0xFBC0,0xAE04,0x0000, 0xFBC0,0xAE05,0x0000, +0xFBC0,0xAE06,0x0000, 0xFBC0,0xAE07,0x0000, 0xFBC0,0xAE08,0x0000, +0xFBC0,0xAE09,0x0000, 0xFBC0,0xAE0A,0x0000, 0xFBC0,0xAE0B,0x0000, +0xFBC0,0xAE0C,0x0000, 0xFBC0,0xAE0D,0x0000, 0xFBC0,0xAE0E,0x0000, +0xFBC0,0xAE0F,0x0000, 0xFBC0,0xAE10,0x0000, 0xFBC0,0xAE11,0x0000, +0xFBC0,0xAE12,0x0000, 0xFBC0,0xAE13,0x0000, 0xFBC0,0xAE14,0x0000, +0xFBC0,0xAE15,0x0000, 0xFBC0,0xAE16,0x0000, 0xFBC0,0xAE17,0x0000, +0xFBC0,0xAE18,0x0000, 0xFBC0,0xAE19,0x0000, 0xFBC0,0xAE1A,0x0000, +0xFBC0,0xAE1B,0x0000, 0xFBC0,0xAE1C,0x0000, 0xFBC0,0xAE1D,0x0000, +0xFBC0,0xAE1E,0x0000, 0xFBC0,0xAE1F,0x0000, 0xFBC0,0xAE20,0x0000, +0xFBC0,0xAE21,0x0000, 0xFBC0,0xAE22,0x0000, 0xFBC0,0xAE23,0x0000, +0xFBC0,0xAE24,0x0000, 0xFBC0,0xAE25,0x0000, 0xFBC0,0xAE26,0x0000, +0xFBC0,0xAE27,0x0000, 0xFBC0,0xAE28,0x0000, 0xFBC0,0xAE29,0x0000, +0xFBC0,0xAE2A,0x0000, 0xFBC0,0xAE2B,0x0000, 0xFBC0,0xAE2C,0x0000, +0xFBC0,0xAE2D,0x0000, 0xFBC0,0xAE2E,0x0000, 0xFBC0,0xAE2F,0x0000, +0xFBC0,0xAE30,0x0000, 0xFBC0,0xAE31,0x0000, 0xFBC0,0xAE32,0x0000, +0xFBC0,0xAE33,0x0000, 0xFBC0,0xAE34,0x0000, 0xFBC0,0xAE35,0x0000, +0xFBC0,0xAE36,0x0000, 0xFBC0,0xAE37,0x0000, 0xFBC0,0xAE38,0x0000, +0xFBC0,0xAE39,0x0000, 0xFBC0,0xAE3A,0x0000, 0xFBC0,0xAE3B,0x0000, +0xFBC0,0xAE3C,0x0000, 0xFBC0,0xAE3D,0x0000, 0xFBC0,0xAE3E,0x0000, +0xFBC0,0xAE3F,0x0000, 0xFBC0,0xAE40,0x0000, 0xFBC0,0xAE41,0x0000, +0xFBC0,0xAE42,0x0000, 0xFBC0,0xAE43,0x0000, 0xFBC0,0xAE44,0x0000, +0xFBC0,0xAE45,0x0000, 0xFBC0,0xAE46,0x0000, 0xFBC0,0xAE47,0x0000, +0xFBC0,0xAE48,0x0000, 0xFBC0,0xAE49,0x0000, 0xFBC0,0xAE4A,0x0000, +0xFBC0,0xAE4B,0x0000, 0xFBC0,0xAE4C,0x0000, 0xFBC0,0xAE4D,0x0000, +0xFBC0,0xAE4E,0x0000, 0xFBC0,0xAE4F,0x0000, 0xFBC0,0xAE50,0x0000, +0xFBC0,0xAE51,0x0000, 0xFBC0,0xAE52,0x0000, 0xFBC0,0xAE53,0x0000, +0xFBC0,0xAE54,0x0000, 0xFBC0,0xAE55,0x0000, 0xFBC0,0xAE56,0x0000, +0xFBC0,0xAE57,0x0000, 0xFBC0,0xAE58,0x0000, 0xFBC0,0xAE59,0x0000, +0xFBC0,0xAE5A,0x0000, 0xFBC0,0xAE5B,0x0000, 0xFBC0,0xAE5C,0x0000, +0xFBC0,0xAE5D,0x0000, 0xFBC0,0xAE5E,0x0000, 0xFBC0,0xAE5F,0x0000, +0xFBC0,0xAE60,0x0000, 0xFBC0,0xAE61,0x0000, 0xFBC0,0xAE62,0x0000, +0xFBC0,0xAE63,0x0000, 0xFBC0,0xAE64,0x0000, 0xFBC0,0xAE65,0x0000, +0xFBC0,0xAE66,0x0000, 0xFBC0,0xAE67,0x0000, 0xFBC0,0xAE68,0x0000, +0xFBC0,0xAE69,0x0000, 0xFBC0,0xAE6A,0x0000, 0xFBC0,0xAE6B,0x0000, +0xFBC0,0xAE6C,0x0000, 0xFBC0,0xAE6D,0x0000, 0xFBC0,0xAE6E,0x0000, +0xFBC0,0xAE6F,0x0000, 0xFBC0,0xAE70,0x0000, 0xFBC0,0xAE71,0x0000, +0xFBC0,0xAE72,0x0000, 0xFBC0,0xAE73,0x0000, 0xFBC0,0xAE74,0x0000, +0xFBC0,0xAE75,0x0000, 0xFBC0,0xAE76,0x0000, 0xFBC0,0xAE77,0x0000, +0xFBC0,0xAE78,0x0000, 0xFBC0,0xAE79,0x0000, 0xFBC0,0xAE7A,0x0000, +0xFBC0,0xAE7B,0x0000, 0xFBC0,0xAE7C,0x0000, 0xFBC0,0xAE7D,0x0000, +0xFBC0,0xAE7E,0x0000, 0xFBC0,0xAE7F,0x0000, 0xFB40,0xCE36,0x0000, +0xFB40,0xD382,0x0000, 0xFB40,0xCE5B,0x0000, 0xFB40,0xCE5A,0x0000, +0xFB40,0xCE59,0x0000, 0xFB40,0xCEBB,0x0000, 0xFB40,0xD182,0x0000, +0xFB40,0xD1E0,0x0000, 0xFB40,0xD200,0x0000, 0xFB40,0xD202,0x0000, +0xFB40,0xD35C,0x0000, 0xFB40,0xD369,0x0000, 0xFB40,0xDC0F,0x0000, +0xFB40,0xDC0F,0x0000, 0xFB40,0xDC22,0x0000, 0xFB40,0xDC23,0x0000, +0xFB40,0xDC22,0x0000, 0xFB40,0xDC23,0x0000, 0xFB40,0xDDF3,0x0000, +0xFB40,0xDE7A,0x0000, 0xFB40,0xDF51,0x0000, 0xFB40,0xDF50,0x0000, +0xFB40,0xDFC4,0x0000, 0xFB40,0xDFC3,0x0000, 0xFB40,0xE24C,0x0000, +0xFB40,0xE535,0x0000, 0xFBC0,0xAE9A,0x0000, 0xFB40,0xE5E1,0x0000, +0xFB40,0xE5E5,0x0000, 0xFB40,0xE708,0x0000, 0xFB40,0xEB7A,0x0000, +0xFB40,0xEBCD,0x0000, 0xFB40,0xEC11,0x0000, 0xFB40,0xEC35,0x0000, +0xFB40,0xEC3A,0x0000, 0xFB40,0xF06C,0x0000, 0xFB40,0xF22B,0x0000, +0xFB40,0xF22B,0x0000, 0xFB40,0xCE2C,0x0000, 0xFB40,0xF25B,0x0000, +0xFB40,0xF2AD,0x0000, 0xFB40,0xF38B,0x0000, 0xFB40,0xF58B,0x0000, +0xFB40,0xF6EE,0x0000, 0xFB40,0xF93A,0x0000, 0xFB40,0xF93B,0x0000, +0xFB40,0xFAF9,0x0000, 0xFB40,0xFCF9,0x0000, 0xFB40,0xFE9F,0x0000, +0xFB40,0xFF53,0x0000, 0xFB40,0xFF52,0x0000, 0xFB40,0xFF53,0x0000, +0xFB40,0xFF53,0x0000, 0xFB40,0xFF52,0x0000, 0xFB40,0xFF8A,0x0000, +0xFB40,0xFF8A,0x0000, 0xFB40,0xFF8B,0x0000, 0xFB41,0x8002,0x0000, +0xFB41,0x8080,0x0000, 0xFB41,0x807F,0x0000, 0xFB41,0x8089,0x0000, +0xFB41,0x81FC,0x0000, 0xFB41,0x8279,0x0000, 0xFB41,0x8279,0x0000, +0xFB41,0x8279,0x0000, 0xFB41,0x864E,0x0000, 0xFB41,0x8864,0x0000, +0xFB41,0x8980,0x0000, 0xFB41,0x897F,0x0000, 0xFB41,0x89C1,0x0000, +0xFB41,0x89D2,0x0000, 0xFB41,0x89D2,0x0000, 0xFB41,0x8BA0,0x0000, +0xFB41,0x8D1D,0x0000, 0xFB41,0x8DB3,0x0000, 0xFB41,0x8F66,0x0000, +0xFB41,0x8FB6,0x0000, 0xFB41,0x8FB6,0x0000, 0xFB41,0x8FB6,0x0000, +0xFB41,0x9091,0x0000, 0xFB41,0x9485,0x0000, 0xFB41,0x9577,0x0000, +0xFB41,0x9578,0x0000, 0xFB41,0x957F,0x0000, 0xFB41,0x95E8,0x0000, +0xFB41,0x961C,0x0000, 0xFB41,0x961D,0x0000, 0xFB41,0x96E8,0x0000, +0xFB41,0x9752,0x0000, 0xFB41,0x97E6,0x0000, 0xFB41,0x9875,0x0000, +0xFB41,0x98CE,0x0000, 0xFB41,0x98DE,0x0000, 0xFB41,0x98DF,0x0000, +0xFB41,0x98E0,0x0000, 0xFB41,0x98E0,0x0000, 0xFB41,0x9963,0x0000, +0xFB41,0x9996,0x0000, 0xFB41,0x9A6C,0x0000, 0xFB41,0x9AA8,0x0000, +0xFB41,0x9B3C,0x0000, 0xFB41,0x9C7C,0x0000, 0xFB41,0x9E1F,0x0000, +0xFB41,0x9E75,0x0000, 0xFB41,0x9EA6,0x0000, 0xFB41,0x9EC4,0x0000, +0xFB41,0x9EFE,0x0000, 0xFB41,0x9F4A,0x0000, 0xFB41,0x9F50,0x0000, +0xFB41,0x9F52,0x0000, 0xFB41,0x9F7F,0x0000, 0xFB41,0x9F8D,0x0000, +0xFB41,0x9F99,0x0000, 0xFB41,0x9F9C,0x0000, 0xFB41,0x9F9C,0x0000, +0xFB41,0x9F9F,0x0000, 0xFBC0,0xAEF4,0x0000, 0xFBC0,0xAEF5,0x0000, +0xFBC0,0xAEF6,0x0000, 0xFBC0,0xAEF7,0x0000, 0xFBC0,0xAEF8,0x0000, +0xFBC0,0xAEF9,0x0000, 0xFBC0,0xAEFA,0x0000, 0xFBC0,0xAEFB,0x0000, +0xFBC0,0xAEFC,0x0000, 0xFBC0,0xAEFD,0x0000, 0xFBC0,0xAEFE,0x0000, +0xFBC0,0xAEFF,0x0000 }; + +uint16 page02Fdata[]= { /* 2F00 (3 weights per char) */ +0xFB40,0xCE00,0x0000, 0xFB40,0xCE28,0x0000, 0xFB40,0xCE36,0x0000, +0xFB40,0xCE3F,0x0000, 0xFB40,0xCE59,0x0000, 0xFB40,0xCE85,0x0000, +0xFB40,0xCE8C,0x0000, 0xFB40,0xCEA0,0x0000, 0xFB40,0xCEBA,0x0000, +0xFB40,0xD13F,0x0000, 0xFB40,0xD165,0x0000, 0xFB40,0xD16B,0x0000, +0xFB40,0xD182,0x0000, 0xFB40,0xD196,0x0000, 0xFB40,0xD1AB,0x0000, +0xFB40,0xD1E0,0x0000, 0xFB40,0xD1F5,0x0000, 0xFB40,0xD200,0x0000, +0xFB40,0xD29B,0x0000, 0xFB40,0xD2F9,0x0000, 0xFB40,0xD315,0x0000, +0xFB40,0xD31A,0x0000, 0xFB40,0xD338,0x0000, 0xFB40,0xD341,0x0000, +0xFB40,0xD35C,0x0000, 0xFB40,0xD369,0x0000, 0xFB40,0xD382,0x0000, +0xFB40,0xD3B6,0x0000, 0xFB40,0xD3C8,0x0000, 0xFB40,0xD3E3,0x0000, +0xFB40,0xD6D7,0x0000, 0xFB40,0xD71F,0x0000, 0xFB40,0xD8EB,0x0000, +0xFB40,0xD902,0x0000, 0xFB40,0xD90A,0x0000, 0xFB40,0xD915,0x0000, +0xFB40,0xD927,0x0000, 0xFB40,0xD973,0x0000, 0xFB40,0xDB50,0x0000, +0xFB40,0xDB80,0x0000, 0xFB40,0xDBF8,0x0000, 0xFB40,0xDC0F,0x0000, +0xFB40,0xDC22,0x0000, 0xFB40,0xDC38,0x0000, 0xFB40,0xDC6E,0x0000, +0xFB40,0xDC71,0x0000, 0xFB40,0xDDDB,0x0000, 0xFB40,0xDDE5,0x0000, +0xFB40,0xDDF1,0x0000, 0xFB40,0xDDFE,0x0000, 0xFB40,0xDE72,0x0000, +0xFB40,0xDE7A,0x0000, 0xFB40,0xDE7F,0x0000, 0xFB40,0xDEF4,0x0000, +0xFB40,0xDEFE,0x0000, 0xFB40,0xDF0B,0x0000, 0xFB40,0xDF13,0x0000, +0xFB40,0xDF50,0x0000, 0xFB40,0xDF61,0x0000, 0xFB40,0xDF73,0x0000, +0xFB40,0xDFC3,0x0000, 0xFB40,0xE208,0x0000, 0xFB40,0xE236,0x0000, +0xFB40,0xE24B,0x0000, 0xFB40,0xE52F,0x0000, 0xFB40,0xE534,0x0000, +0xFB40,0xE587,0x0000, 0xFB40,0xE597,0x0000, 0xFB40,0xE5A4,0x0000, +0xFB40,0xE5B9,0x0000, 0xFB40,0xE5E0,0x0000, 0xFB40,0xE5E5,0x0000, +0xFB40,0xE6F0,0x0000, 0xFB40,0xE708,0x0000, 0xFB40,0xE728,0x0000, +0xFB40,0xEB20,0x0000, 0xFB40,0xEB62,0x0000, 0xFB40,0xEB79,0x0000, +0xFB40,0xEBB3,0x0000, 0xFB40,0xEBCB,0x0000, 0xFB40,0xEBD4,0x0000, +0xFB40,0xEBDB,0x0000, 0xFB40,0xEC0F,0x0000, 0xFB40,0xEC14,0x0000, +0xFB40,0xEC34,0x0000, 0xFB40,0xF06B,0x0000, 0xFB40,0xF22A,0x0000, +0xFB40,0xF236,0x0000, 0xFB40,0xF23B,0x0000, 0xFB40,0xF23F,0x0000, +0xFB40,0xF247,0x0000, 0xFB40,0xF259,0x0000, 0xFB40,0xF25B,0x0000, +0xFB40,0xF2AC,0x0000, 0xFB40,0xF384,0x0000, 0xFB40,0xF389,0x0000, +0xFB40,0xF4DC,0x0000, 0xFB40,0xF4E6,0x0000, 0xFB40,0xF518,0x0000, +0xFB40,0xF51F,0x0000, 0xFB40,0xF528,0x0000, 0xFB40,0xF530,0x0000, +0xFB40,0xF58B,0x0000, 0xFB40,0xF592,0x0000, 0xFB40,0xF676,0x0000, +0xFB40,0xF67D,0x0000, 0xFB40,0xF6AE,0x0000, 0xFB40,0xF6BF,0x0000, +0xFB40,0xF6EE,0x0000, 0xFB40,0xF7DB,0x0000, 0xFB40,0xF7E2,0x0000, +0xFB40,0xF7F3,0x0000, 0xFB40,0xF93A,0x0000, 0xFB40,0xF9B8,0x0000, +0xFB40,0xF9BE,0x0000, 0xFB40,0xFA74,0x0000, 0xFB40,0xFACB,0x0000, +0xFB40,0xFAF9,0x0000, 0xFB40,0xFC73,0x0000, 0xFB40,0xFCF8,0x0000, +0xFB40,0xFF36,0x0000, 0xFB40,0xFF51,0x0000, 0xFB40,0xFF8A,0x0000, +0xFB40,0xFFBD,0x0000, 0xFB41,0x8001,0x0000, 0xFB41,0x800C,0x0000, +0xFB41,0x8012,0x0000, 0xFB41,0x8033,0x0000, 0xFB41,0x807F,0x0000, +0xFB41,0x8089,0x0000, 0xFB41,0x81E3,0x0000, 0xFB41,0x81EA,0x0000, +0xFB41,0x81F3,0x0000, 0xFB41,0x81FC,0x0000, 0xFB41,0x820C,0x0000, +0xFB41,0x821B,0x0000, 0xFB41,0x821F,0x0000, 0xFB41,0x826E,0x0000, +0xFB41,0x8272,0x0000, 0xFB41,0x8278,0x0000, 0xFB41,0x864D,0x0000, +0xFB41,0x866B,0x0000, 0xFB41,0x8840,0x0000, 0xFB41,0x884C,0x0000, +0xFB41,0x8863,0x0000, 0xFB41,0x897E,0x0000, 0xFB41,0x898B,0x0000, +0xFB41,0x89D2,0x0000, 0xFB41,0x8A00,0x0000, 0xFB41,0x8C37,0x0000, +0xFB41,0x8C46,0x0000, 0xFB41,0x8C55,0x0000, 0xFB41,0x8C78,0x0000, +0xFB41,0x8C9D,0x0000, 0xFB41,0x8D64,0x0000, 0xFB41,0x8D70,0x0000, +0xFB41,0x8DB3,0x0000, 0xFB41,0x8EAB,0x0000, 0xFB41,0x8ECA,0x0000, +0xFB41,0x8F9B,0x0000, 0xFB41,0x8FB0,0x0000, 0xFB41,0x8FB5,0x0000, +0xFB41,0x9091,0x0000, 0xFB41,0x9149,0x0000, 0xFB41,0x91C6,0x0000, +0xFB41,0x91CC,0x0000, 0xFB41,0x91D1,0x0000, 0xFB41,0x9577,0x0000, +0xFB41,0x9580,0x0000, 0xFB41,0x961C,0x0000, 0xFB41,0x96B6,0x0000, +0xFB41,0x96B9,0x0000, 0xFB41,0x96E8,0x0000, 0xFB41,0x9751,0x0000, +0xFB41,0x975E,0x0000, 0xFB41,0x9762,0x0000, 0xFB41,0x9769,0x0000, +0xFB41,0x97CB,0x0000, 0xFB41,0x97ED,0x0000, 0xFB41,0x97F3,0x0000, +0xFB41,0x9801,0x0000, 0xFB41,0x98A8,0x0000, 0xFB41,0x98DB,0x0000, +0xFB41,0x98DF,0x0000, 0xFB41,0x9996,0x0000, 0xFB41,0x9999,0x0000, +0xFB41,0x99AC,0x0000, 0xFB41,0x9AA8,0x0000, 0xFB41,0x9AD8,0x0000, +0xFB41,0x9ADF,0x0000, 0xFB41,0x9B25,0x0000, 0xFB41,0x9B2F,0x0000, +0xFB41,0x9B32,0x0000, 0xFB41,0x9B3C,0x0000, 0xFB41,0x9B5A,0x0000, +0xFB41,0x9CE5,0x0000, 0xFB41,0x9E75,0x0000, 0xFB41,0x9E7F,0x0000, +0xFB41,0x9EA5,0x0000, 0xFB41,0x9EBB,0x0000, 0xFB41,0x9EC3,0x0000, +0xFB41,0x9ECD,0x0000, 0xFB41,0x9ED1,0x0000, 0xFB41,0x9EF9,0x0000, +0xFB41,0x9EFD,0x0000, 0xFB41,0x9F0E,0x0000, 0xFB41,0x9F13,0x0000, +0xFB41,0x9F20,0x0000, 0xFB41,0x9F3B,0x0000, 0xFB41,0x9F4A,0x0000, +0xFB41,0x9F52,0x0000, 0xFB41,0x9F8D,0x0000, 0xFB41,0x9F9C,0x0000, +0xFB41,0x9FA0,0x0000, 0xFBC0,0xAFD6,0x0000, 0xFBC0,0xAFD7,0x0000, +0xFBC0,0xAFD8,0x0000, 0xFBC0,0xAFD9,0x0000, 0xFBC0,0xAFDA,0x0000, +0xFBC0,0xAFDB,0x0000, 0xFBC0,0xAFDC,0x0000, 0xFBC0,0xAFDD,0x0000, +0xFBC0,0xAFDE,0x0000, 0xFBC0,0xAFDF,0x0000, 0xFBC0,0xAFE0,0x0000, +0xFBC0,0xAFE1,0x0000, 0xFBC0,0xAFE2,0x0000, 0xFBC0,0xAFE3,0x0000, +0xFBC0,0xAFE4,0x0000, 0xFBC0,0xAFE5,0x0000, 0xFBC0,0xAFE6,0x0000, +0xFBC0,0xAFE7,0x0000, 0xFBC0,0xAFE8,0x0000, 0xFBC0,0xAFE9,0x0000, +0xFBC0,0xAFEA,0x0000, 0xFBC0,0xAFEB,0x0000, 0xFBC0,0xAFEC,0x0000, +0xFBC0,0xAFED,0x0000, 0xFBC0,0xAFEE,0x0000, 0xFBC0,0xAFEF,0x0000, +0x0DAF,0x0000,0x0000, 0x0DB0,0x0000,0x0000, 0x0DB1,0x0000,0x0000, +0x0DB2,0x0000,0x0000, 0x0DB3,0x0000,0x0000, 0x0DB4,0x0000,0x0000, +0x0DB5,0x0000,0x0000, 0x0DB6,0x0000,0x0000, 0x0DB7,0x0000,0x0000, +0x0DB8,0x0000,0x0000, 0x0DB9,0x0000,0x0000, 0x0DBA,0x0000,0x0000, +0xFBC0,0xAFFC,0x0000, 0xFBC0,0xAFFD,0x0000, 0xFBC0,0xAFFE,0x0000, +0xFBC0,0xAFFF,0x0000 }; + +uint16 page030data[]= { /* 3000 (3 weights per char) */ +0x0209,0x0000,0x0000, 0x0237,0x0000,0x0000, 0x0266,0x0000,0x0000, +0x02E2,0x0000,0x0000, 0x0DBB,0x0000,0x0000, 0x0E05,0x0000,0x0000, +0x1E5D,0x1E73,0x0000, 0x0E29,0x0000,0x0000, 0x02AE,0x0000,0x0000, +0x02AF,0x0000,0x0000, 0x02B0,0x0000,0x0000, 0x02B1,0x0000,0x0000, +0x02B2,0x0000,0x0000, 0x02B3,0x0000,0x0000, 0x02B4,0x0000,0x0000, +0x02B5,0x0000,0x0000, 0x02B6,0x0000,0x0000, 0x02B7,0x0000,0x0000, +0x0DBC,0x0000,0x0000, 0x0DBD,0x0000,0x0000, 0x02B8,0x0000,0x0000, +0x02B9,0x0000,0x0000, 0x02BA,0x0000,0x0000, 0x02BB,0x0000,0x0000, +0x02BC,0x0000,0x0000, 0x02BD,0x0000,0x0000, 0x02BE,0x0000,0x0000, +0x02BF,0x0000,0x0000, 0x022B,0x0000,0x0000, 0x0283,0x0000,0x0000, +0x0284,0x0000,0x0000, 0x0285,0x0000,0x0000, 0x0DBE,0x0000,0x0000, +0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, 0x0E2C,0x0000,0x0000, +0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, 0x0E2F,0x0000,0x0000, +0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, 0x0E32,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x022C,0x0000,0x0000, 0x0E07,0x0000,0x0000, 0x0E07,0x0000,0x0000, +0x0E08,0x0000,0x0000, 0x0E08,0x0000,0x0000, 0x0E09,0x0000,0x0000, +0x0DBC,0x0000,0x0000, 0x0DBF,0x0000,0x0000, 0xFB40,0xD341,0x0000, +0xFB40,0xD344,0x0000, 0xFB40,0xD345,0x0000, 0x0E06,0x0000,0x0000, +0x1E70,0x1E5E,0x0000, 0x02E3,0x0000,0x0000, 0x0DC0,0x0000,0x0000, +0x0DC1,0x0000,0x0000, 0xFBC0,0xB040,0x0000, 0x1E52,0x0000,0x0000, +0x1E52,0x0000,0x0000, 0x1E53,0x0000,0x0000, 0x1E53,0x0000,0x0000, +0x1E54,0x0000,0x0000, 0x1E54,0x0000,0x0000, 0x1E55,0x0000,0x0000, +0x1E55,0x0000,0x0000, 0x1E56,0x0000,0x0000, 0x1E56,0x0000,0x0000, +0x1E57,0x0000,0x0000, 0x1E57,0x0000,0x0000, 0x1E58,0x0000,0x0000, +0x1E58,0x0000,0x0000, 0x1E59,0x0000,0x0000, 0x1E59,0x0000,0x0000, +0x1E5A,0x0000,0x0000, 0x1E5A,0x0000,0x0000, 0x1E5B,0x0000,0x0000, +0x1E5B,0x0000,0x0000, 0x1E5C,0x0000,0x0000, 0x1E5C,0x0000,0x0000, +0x1E5D,0x0000,0x0000, 0x1E5D,0x0000,0x0000, 0x1E5E,0x0000,0x0000, +0x1E5E,0x0000,0x0000, 0x1E5F,0x0000,0x0000, 0x1E5F,0x0000,0x0000, +0x1E60,0x0000,0x0000, 0x1E60,0x0000,0x0000, 0x1E61,0x0000,0x0000, +0x1E61,0x0000,0x0000, 0x1E62,0x0000,0x0000, 0x1E62,0x0000,0x0000, +0x1E63,0x0000,0x0000, 0x1E63,0x0000,0x0000, 0x1E63,0x0000,0x0000, +0x1E64,0x0000,0x0000, 0x1E64,0x0000,0x0000, 0x1E65,0x0000,0x0000, +0x1E65,0x0000,0x0000, 0x1E66,0x0000,0x0000, 0x1E67,0x0000,0x0000, +0x1E68,0x0000,0x0000, 0x1E69,0x0000,0x0000, 0x1E6A,0x0000,0x0000, +0x1E6B,0x0000,0x0000, 0x1E6B,0x0000,0x0000, 0x1E6B,0x0000,0x0000, +0x1E6C,0x0000,0x0000, 0x1E6C,0x0000,0x0000, 0x1E6C,0x0000,0x0000, +0x1E6D,0x0000,0x0000, 0x1E6D,0x0000,0x0000, 0x1E6D,0x0000,0x0000, +0x1E6E,0x0000,0x0000, 0x1E6E,0x0000,0x0000, 0x1E6E,0x0000,0x0000, +0x1E6F,0x0000,0x0000, 0x1E6F,0x0000,0x0000, 0x1E6F,0x0000,0x0000, +0x1E70,0x0000,0x0000, 0x1E71,0x0000,0x0000, 0x1E72,0x0000,0x0000, +0x1E73,0x0000,0x0000, 0x1E74,0x0000,0x0000, 0x1E75,0x0000,0x0000, +0x1E75,0x0000,0x0000, 0x1E76,0x0000,0x0000, 0x1E76,0x0000,0x0000, +0x1E77,0x0000,0x0000, 0x1E77,0x0000,0x0000, 0x1E78,0x0000,0x0000, +0x1E79,0x0000,0x0000, 0x1E7A,0x0000,0x0000, 0x1E7B,0x0000,0x0000, +0x1E7C,0x0000,0x0000, 0x1E7D,0x0000,0x0000, 0x1E7D,0x0000,0x0000, +0x1E7E,0x0000,0x0000, 0x1E7F,0x0000,0x0000, 0x1E80,0x0000,0x0000, +0x1E81,0x0000,0x0000, 0x1E54,0x0000,0x0000, 0x1E57,0x0000,0x0000, +0x1E5A,0x0000,0x0000, 0xFBC0,0xB097,0x0000, 0xFBC0,0xB098,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x021E,0x0000,0x0000, +0x021F,0x0000,0x0000, 0x0E0A,0x0000,0x0000, 0x0E0A,0x0000,0x0000, +0x1E77,0x1E79,0x0000, 0x022D,0x0000,0x0000, 0x1E52,0x0000,0x0000, +0x1E52,0x0000,0x0000, 0x1E53,0x0000,0x0000, 0x1E53,0x0000,0x0000, +0x1E54,0x0000,0x0000, 0x1E54,0x0000,0x0000, 0x1E55,0x0000,0x0000, +0x1E55,0x0000,0x0000, 0x1E56,0x0000,0x0000, 0x1E56,0x0000,0x0000, +0x1E57,0x0000,0x0000, 0x1E57,0x0000,0x0000, 0x1E58,0x0000,0x0000, +0x1E58,0x0000,0x0000, 0x1E59,0x0000,0x0000, 0x1E59,0x0000,0x0000, +0x1E5A,0x0000,0x0000, 0x1E5A,0x0000,0x0000, 0x1E5B,0x0000,0x0000, +0x1E5B,0x0000,0x0000, 0x1E5C,0x0000,0x0000, 0x1E5C,0x0000,0x0000, +0x1E5D,0x0000,0x0000, 0x1E5D,0x0000,0x0000, 0x1E5E,0x0000,0x0000, +0x1E5E,0x0000,0x0000, 0x1E5F,0x0000,0x0000, 0x1E5F,0x0000,0x0000, +0x1E60,0x0000,0x0000, 0x1E60,0x0000,0x0000, 0x1E61,0x0000,0x0000, +0x1E61,0x0000,0x0000, 0x1E62,0x0000,0x0000, 0x1E62,0x0000,0x0000, +0x1E63,0x0000,0x0000, 0x1E63,0x0000,0x0000, 0x1E63,0x0000,0x0000, +0x1E64,0x0000,0x0000, 0x1E64,0x0000,0x0000, 0x1E65,0x0000,0x0000, +0x1E65,0x0000,0x0000, 0x1E66,0x0000,0x0000, 0x1E67,0x0000,0x0000, +0x1E68,0x0000,0x0000, 0x1E69,0x0000,0x0000, 0x1E6A,0x0000,0x0000, +0x1E6B,0x0000,0x0000, 0x1E6B,0x0000,0x0000, 0x1E6B,0x0000,0x0000, +0x1E6C,0x0000,0x0000, 0x1E6C,0x0000,0x0000, 0x1E6C,0x0000,0x0000, +0x1E6D,0x0000,0x0000, 0x1E6D,0x0000,0x0000, 0x1E6D,0x0000,0x0000, +0x1E6E,0x0000,0x0000, 0x1E6E,0x0000,0x0000, 0x1E6E,0x0000,0x0000, +0x1E6F,0x0000,0x0000, 0x1E6F,0x0000,0x0000, 0x1E6F,0x0000,0x0000, +0x1E70,0x0000,0x0000, 0x1E71,0x0000,0x0000, 0x1E72,0x0000,0x0000, +0x1E73,0x0000,0x0000, 0x1E74,0x0000,0x0000, 0x1E75,0x0000,0x0000, +0x1E75,0x0000,0x0000, 0x1E76,0x0000,0x0000, 0x1E76,0x0000,0x0000, +0x1E77,0x0000,0x0000, 0x1E77,0x0000,0x0000, 0x1E78,0x0000,0x0000, +0x1E79,0x0000,0x0000, 0x1E7A,0x0000,0x0000, 0x1E7B,0x0000,0x0000, +0x1E7C,0x0000,0x0000, 0x1E7D,0x0000,0x0000, 0x1E7D,0x0000,0x0000, +0x1E7E,0x0000,0x0000, 0x1E7F,0x0000,0x0000, 0x1E80,0x0000,0x0000, +0x1E81,0x0000,0x0000, 0x1E54,0x0000,0x0000, 0x1E57,0x0000,0x0000, +0x1E5A,0x0000,0x0000, 0x1E7D,0x0000,0x0000, 0x1E7E,0x0000,0x0000, +0x1E7F,0x0000,0x0000, 0x1E80,0x0000,0x0000, 0x022E,0x0000,0x0000, +0x0E0B,0x0000,0x0000, 0x0E0C,0x0000,0x0000, 0x0E0C,0x0000,0x0000, +0x1E5B,0x1E65,0x0000 }; + +uint16 page031data[]= { /* 3100 (3 weights per char) */ +0xFBC0,0xB100,0x0000, 0xFBC0,0xB101,0x0000, 0xFBC0,0xB102,0x0000, +0xFBC0,0xB103,0x0000, 0xFBC0,0xB104,0x0000, 0x1E82,0x0000,0x0000, +0x1E83,0x0000,0x0000, 0x1E84,0x0000,0x0000, 0x1E85,0x0000,0x0000, +0x1E87,0x0000,0x0000, 0x1E88,0x0000,0x0000, 0x1E89,0x0000,0x0000, +0x1E8A,0x0000,0x0000, 0x1E8B,0x0000,0x0000, 0x1E8C,0x0000,0x0000, +0x1E8F,0x0000,0x0000, 0x1E90,0x0000,0x0000, 0x1E91,0x0000,0x0000, +0x1E92,0x0000,0x0000, 0x1E94,0x0000,0x0000, 0x1E95,0x0000,0x0000, +0x1E96,0x0000,0x0000, 0x1E97,0x0000,0x0000, 0x1E98,0x0000,0x0000, +0x1E99,0x0000,0x0000, 0x1E9A,0x0000,0x0000, 0x1E9B,0x0000,0x0000, +0x1E9C,0x0000,0x0000, 0x1E9E,0x0000,0x0000, 0x1E9F,0x0000,0x0000, +0x1EA1,0x0000,0x0000, 0x1EA2,0x0000,0x0000, 0x1EA3,0x0000,0x0000, +0x1EA4,0x0000,0x0000, 0x1EA5,0x0000,0x0000, 0x1EA6,0x0000,0x0000, +0x1EA7,0x0000,0x0000, 0x1EA9,0x0000,0x0000, 0x1EAD,0x0000,0x0000, +0x1EAE,0x0000,0x0000, 0x1EAF,0x0000,0x0000, 0x1EB0,0x0000,0x0000, +0x1E86,0x0000,0x0000, 0x1E8D,0x0000,0x0000, 0x1E93,0x0000,0x0000, +0xFBC0,0xB12D,0x0000, 0xFBC0,0xB12E,0x0000, 0xFBC0,0xB12F,0x0000, +0xFBC0,0xB130,0x0000, 0x1D62,0x0000,0x0000, 0x1D63,0x0000,0x0000, +0x1E02,0x0000,0x0000, 0x1D64,0x0000,0x0000, 0x1E04,0x0000,0x0000, +0x1E05,0x0000,0x0000, 0x1D65,0x0000,0x0000, 0x1D66,0x0000,0x0000, +0x1D67,0x0000,0x0000, 0x1E08,0x0000,0x0000, 0x1E09,0x0000,0x0000, +0x1E0A,0x0000,0x0000, 0x1E0B,0x0000,0x0000, 0x1E0C,0x0000,0x0000, +0x1E0D,0x0000,0x0000, 0x1D7C,0x0000,0x0000, 0x1D68,0x0000,0x0000, +0x1D69,0x0000,0x0000, 0x1D6A,0x0000,0x0000, 0x1D83,0x0000,0x0000, +0x1D6B,0x0000,0x0000, 0x1D6C,0x0000,0x0000, 0x1D6D,0x0000,0x0000, +0x1D6E,0x0000,0x0000, 0x1D6F,0x0000,0x0000, 0x1D70,0x0000,0x0000, +0x1D71,0x0000,0x0000, 0x1D72,0x0000,0x0000, 0x1D73,0x0000,0x0000, +0x1D74,0x0000,0x0000, 0x1DBE,0x0000,0x0000, 0x1DBF,0x0000,0x0000, +0x1DC0,0x0000,0x0000, 0x1DC1,0x0000,0x0000, 0x1DC2,0x0000,0x0000, +0x1DC3,0x0000,0x0000, 0x1DC4,0x0000,0x0000, 0x1DC5,0x0000,0x0000, +0x1DC6,0x0000,0x0000, 0x1DC7,0x0000,0x0000, 0x1DC8,0x0000,0x0000, +0x1DC9,0x0000,0x0000, 0x1DCA,0x0000,0x0000, 0x1DCB,0x0000,0x0000, +0x1DCC,0x0000,0x0000, 0x1DCD,0x0000,0x0000, 0x1DCE,0x0000,0x0000, +0x1DCF,0x0000,0x0000, 0x1DD0,0x0000,0x0000, 0x1DD1,0x0000,0x0000, +0x1DD2,0x0000,0x0000, 0x1DBD,0x0000,0x0000, 0x1D76,0x0000,0x0000, +0x1D77,0x0000,0x0000, 0x1E1F,0x0000,0x0000, 0x1E20,0x0000,0x0000, +0x1E24,0x0000,0x0000, 0x1E26,0x0000,0x0000, 0x1E2B,0x0000,0x0000, +0x1E2F,0x0000,0x0000, 0x1E31,0x0000,0x0000, 0x1D7E,0x0000,0x0000, +0x1E35,0x0000,0x0000, 0x1E37,0x0000,0x0000, 0x1D7F,0x0000,0x0000, +0x1D80,0x0000,0x0000, 0x1D82,0x0000,0x0000, 0x1D84,0x0000,0x0000, +0x1D85,0x0000,0x0000, 0x1D89,0x0000,0x0000, 0x1D8B,0x0000,0x0000, +0x1D8D,0x0000,0x0000, 0x1D8E,0x0000,0x0000, 0x1D8F,0x0000,0x0000, +0x1D90,0x0000,0x0000, 0x1D91,0x0000,0x0000, 0x1D94,0x0000,0x0000, +0x1D98,0x0000,0x0000, 0x1DA2,0x0000,0x0000, 0x1DA9,0x0000,0x0000, +0x1DAE,0x0000,0x0000, 0x1E49,0x0000,0x0000, 0x1E4A,0x0000,0x0000, +0x1DB9,0x0000,0x0000, 0x1DBA,0x0000,0x0000, 0x1DBB,0x0000,0x0000, +0x1DE1,0x0000,0x0000, 0x1DE2,0x0000,0x0000, 0x1DE5,0x0000,0x0000, +0x1DEE,0x0000,0x0000, 0x1DEF,0x0000,0x0000, 0x1DF1,0x0000,0x0000, +0x1DFB,0x0000,0x0000, 0x1DFE,0x0000,0x0000, 0xFBC0,0xB18F,0x0000, +0x0DC2,0x0000,0x0000, 0x0DC3,0x0000,0x0000, 0xFB40,0xCE00,0x0000, +0xFB40,0xCE8C,0x0000, 0xFB40,0xCE09,0x0000, 0xFB40,0xD6DB,0x0000, +0xFB40,0xCE0A,0x0000, 0xFB40,0xCE2D,0x0000, 0xFB40,0xCE0B,0x0000, +0xFB40,0xF532,0x0000, 0xFB40,0xCE59,0x0000, 0xFB40,0xCE19,0x0000, +0xFB40,0xCE01,0x0000, 0xFB40,0xD929,0x0000, 0xFB40,0xD730,0x0000, +0xFB40,0xCEBA,0x0000, 0x1E82,0x0000,0x0000, 0x1E98,0x0000,0x0000, +0x1E90,0x0000,0x0000, 0x1E8B,0x0000,0x0000, 0x1EA0,0x0000,0x0000, +0x1EA0,0x0000,0x0000, 0x1E9D,0x0000,0x0000, 0x1E9C,0x0000,0x0000, +0x1EAF,0x0000,0x0000, 0x1E9B,0x0000,0x0000, 0x1EAE,0x0000,0x0000, +0x1EAF,0x0000,0x0000, 0x1EAC,0x0000,0x0000, 0x1E8E,0x0000,0x0000, +0x1EA1,0x0000,0x0000, 0x1EA3,0x0000,0x0000, 0x1EAA,0x0000,0x0000, +0x1EAB,0x0000,0x0000, 0x1EA8,0x0000,0x0000, 0x1EAE,0x0000,0x0000, +0x1E83,0x0000,0x0000, 0x1E88,0x0000,0x0000, 0x1E8C,0x0000,0x0000, +0x1E8F,0x0000,0x0000, 0xFBC0,0xB1B8,0x0000, 0xFBC0,0xB1B9,0x0000, +0xFBC0,0xB1BA,0x0000, 0xFBC0,0xB1BB,0x0000, 0xFBC0,0xB1BC,0x0000, +0xFBC0,0xB1BD,0x0000, 0xFBC0,0xB1BE,0x0000, 0xFBC0,0xB1BF,0x0000, +0xFBC0,0xB1C0,0x0000, 0xFBC0,0xB1C1,0x0000, 0xFBC0,0xB1C2,0x0000, +0xFBC0,0xB1C3,0x0000, 0xFBC0,0xB1C4,0x0000, 0xFBC0,0xB1C5,0x0000, +0xFBC0,0xB1C6,0x0000, 0xFBC0,0xB1C7,0x0000, 0xFBC0,0xB1C8,0x0000, +0xFBC0,0xB1C9,0x0000, 0xFBC0,0xB1CA,0x0000, 0xFBC0,0xB1CB,0x0000, +0xFBC0,0xB1CC,0x0000, 0xFBC0,0xB1CD,0x0000, 0xFBC0,0xB1CE,0x0000, +0xFBC0,0xB1CF,0x0000, 0xFBC0,0xB1D0,0x0000, 0xFBC0,0xB1D1,0x0000, +0xFBC0,0xB1D2,0x0000, 0xFBC0,0xB1D3,0x0000, 0xFBC0,0xB1D4,0x0000, +0xFBC0,0xB1D5,0x0000, 0xFBC0,0xB1D6,0x0000, 0xFBC0,0xB1D7,0x0000, +0xFBC0,0xB1D8,0x0000, 0xFBC0,0xB1D9,0x0000, 0xFBC0,0xB1DA,0x0000, +0xFBC0,0xB1DB,0x0000, 0xFBC0,0xB1DC,0x0000, 0xFBC0,0xB1DD,0x0000, +0xFBC0,0xB1DE,0x0000, 0xFBC0,0xB1DF,0x0000, 0xFBC0,0xB1E0,0x0000, +0xFBC0,0xB1E1,0x0000, 0xFBC0,0xB1E2,0x0000, 0xFBC0,0xB1E3,0x0000, +0xFBC0,0xB1E4,0x0000, 0xFBC0,0xB1E5,0x0000, 0xFBC0,0xB1E6,0x0000, +0xFBC0,0xB1E7,0x0000, 0xFBC0,0xB1E8,0x0000, 0xFBC0,0xB1E9,0x0000, +0xFBC0,0xB1EA,0x0000, 0xFBC0,0xB1EB,0x0000, 0xFBC0,0xB1EC,0x0000, +0xFBC0,0xB1ED,0x0000, 0xFBC0,0xB1EE,0x0000, 0xFBC0,0xB1EF,0x0000, +0x1E59,0x0000,0x0000, 0x1E5D,0x0000,0x0000, 0x1E5E,0x0000,0x0000, +0x1E65,0x0000,0x0000, 0x1E68,0x0000,0x0000, 0x1E6B,0x0000,0x0000, +0x1E6C,0x0000,0x0000, 0x1E6D,0x0000,0x0000, 0x1E6E,0x0000,0x0000, +0x1E6F,0x0000,0x0000, 0x1E72,0x0000,0x0000, 0x1E78,0x0000,0x0000, +0x1E79,0x0000,0x0000, 0x1E7A,0x0000,0x0000, 0x1E7B,0x0000,0x0000, +0x1E7C,0x0000,0x0000 }; + +uint16 page032data[]= { /* 3200 (8 weights per char) */ +0x0288,0x1D62,0x0289,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D64,0x0289,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D65,0x0289,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D67,0x0289,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D68,0x0289,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D69,0x0289,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D6B,0x0289,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D6D,0x0289,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D6E,0x0289,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D70,0x0289,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D71,0x0289,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D72,0x0289,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D73,0x0289,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D74,0x0289,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D62,0x1DBE,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D64,0x1DBE,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D65,0x1DBE,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D67,0x1DBE,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D68,0x1DBE,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D69,0x1DBE,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D6B,0x1DBE,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D6D,0x1DBE,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D6E,0x1DBE,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D70,0x1DBE,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D71,0x1DBE,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D72,0x1DBE,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D73,0x1DBE,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D74,0x1DBE,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D6E,0x1DCB,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0x1D6D,0x1DC6,0x1D6E,0x1DC2,0x1E03,0x0289,0x0000, +0x0288,0x1D6D,0x1DC6,0x1D74,0x1DCB,0x0289,0x0000,0x0000, +0xFBC0,0xB21F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xCE00,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xCE8C,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xCE09,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xD6DB,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xCE94,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xD16D,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xCE03,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xD16B,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xCE5D,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xD341,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xE708,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xF06B,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xEC34,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xE728,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB41,0x91D1,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xD71F,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xE5E5,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xE82A,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xE709,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xF93E,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xD40D,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xF279,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB41,0x8CA1,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xF95D,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xD2B4,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xCEE3,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xD47C,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xDB66,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xF6E3,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xCF01,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB41,0x8CC7,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xD354,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xF96D,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB40,0xCF11,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB41,0x81EA,0x0289,0x0000,0x0000,0x0000,0x0000, +0x0288,0xFB41,0x81F3,0x0289,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xB244,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xB245,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xB246,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xB247,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xB248,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xB249,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xB24A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xB24B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xB24C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xB24D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xB24E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xB24F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0FA7,0x1002,0x0E8B,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E2A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E2B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E2C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E2D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E2F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E30,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E31,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E32,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2C,0x0E29,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2C,0x0E2A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2C,0x0E2B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2C,0x0E2C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2C,0x0E2D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2C,0x0E2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D62,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D64,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D65,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D67,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D68,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D69,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D6B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D6D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D6E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D70,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D71,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D72,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D73,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D74,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D62,0x1DBE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D64,0x1DBE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D65,0x1DBE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D67,0x1DBE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D68,0x1DBE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D69,0x1DBE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D6B,0x1DBE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D6D,0x1DBE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D6E,0x1DBE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D70,0x1DBE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D71,0x1DBE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D72,0x1DBE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D73,0x1DBE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D74,0x1DBE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1D70,0x1DBE,0x1E0F,0x1D62,0x1DC6,0x0000,0x0000,0x0000, +0x1D6E,0x1DCB,0x1D6D,0x1DD1,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xB27E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0DC4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xCE00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xCE8C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xCE09,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xD6DB,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xCE94,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xD16D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xCE03,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xD16B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xCE5D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xD341,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xF06B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xEC34,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xE728,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB41,0x91D1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xD71F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xE82A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xE709,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xF93E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xD40D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xF279,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB41,0x8CA1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xF95D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xD2B4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xF9D8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xF537,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xD973,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB41,0x9069,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xD12A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xD370,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xECE8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB41,0x9805,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xCF11,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xD199,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xEB63,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xCE0A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xCE2D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xCE0B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xDDE6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xD3F3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xD33B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xDB97,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xDB66,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xF6E3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xCF01,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB41,0x8CC7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xD354,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xD91C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2C,0x0E2F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2C,0x0E30,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2C,0x0E31,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2C,0x0E32,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2D,0x0E29,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2D,0x0E2A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2D,0x0E2B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2D,0x0E2C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2D,0x0E2D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2D,0x0E2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2D,0x0E2F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2D,0x0E30,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2D,0x0E31,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2D,0x0E32,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2E,0x0E29,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2C,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2D,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2E,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2F,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E30,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E31,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E32,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E29,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E2A,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E2B,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000, +0x0EE1,0x0EC1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E8B,0x0FC0,0x0EC1,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E8B,0x1044,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F2E,0x1002,0x0E6D,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E52,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E53,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E54,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E55,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E56,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E57,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E58,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E59,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E5A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E5B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E5C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E5D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E5E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E5F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E60,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E61,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E62,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E63,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E64,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E65,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E66,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E67,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E68,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E69,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E70,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E71,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E72,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E73,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E74,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E75,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E76,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E77,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E78,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E79,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E7A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E7B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E7C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E7D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E7E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E7F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E80,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC0,0xB2FF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 +}; + +uint16 page033data[]= { /* 3300 (9 weights per char) */ +0x1E52,0x1E6B,0x0E0B,0x1E65,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E52,0x1E7A,0x1E6D,0x1E52,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E52,0x1E81,0x1E6E,0x1E52,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E52,0x0E0B,0x1E7A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E53,0x1E67,0x1E81,0x1E59,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E53,0x1E81,0x1E62,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E54,0x1E56,0x1E81,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E55,0x1E5E,0x1E59,0x0E0B,0x1E65,0x0000,0x0000,0x0000,0x0000, +0x1E55,0x0E0B,0x1E57,0x0E0B,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E56,0x1E81,0x1E5E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E56,0x0E0B,0x1E72,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E57,0x1E53,0x1E79,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E57,0x1E78,0x1E63,0x1E65,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E57,0x1E7C,0x1E79,0x0E0B,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E57,0x1E7C,0x1E81,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E57,0x1E81,0x1E70,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E58,0x1E57,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E58,0x1E67,0x0E0B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E58,0x1E76,0x1E79,0x0E0B,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E58,0x1E7A,0x1E61,0x0E0B,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E58,0x1E7C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E58,0x1E7C,0x1E59,0x1E78,0x1E72,0x0000,0x0000,0x0000,0x0000, +0x1E58,0x1E7C,0x1E73,0x0E0B,0x1E65,0x1E7A,0x0000,0x0000,0x0000, +0x1E58,0x1E7C,0x1E7D,0x1E63,0x1E65,0x0000,0x0000,0x0000,0x0000, +0x1E59,0x1E78,0x1E72,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E59,0x1E78,0x1E72,0x1E65,0x1E81,0x0000,0x0000,0x0000,0x0000, +0x1E59,0x1E7A,0x1E5F,0x1E53,0x1E7C,0x0000,0x0000,0x0000,0x0000, +0x1E59,0x1E7C,0x0E0B,0x1E69,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E5A,0x0E0B,0x1E5E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E5B,0x1E7A,0x1E66,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E5B,0x0E0B,0x1E6F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E5C,0x1E53,0x1E59,0x1E7A,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E5C,0x1E81,0x1E62,0x0E0B,0x1E72,0x0000,0x0000,0x0000,0x0000, +0x1E5D,0x1E79,0x1E81,0x1E59,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E5F,0x1E81,0x1E62,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E5F,0x1E81,0x1E65,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E61,0x0E0B,0x1E5E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E64,0x1E5D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E65,0x1E7A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E65,0x1E81,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E66,0x1E6A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6A,0x1E63,0x1E65,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6B,0x1E53,0x1E63,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6B,0x0E0B,0x1E5F,0x1E81,0x1E65,0x0000,0x0000,0x0000,0x0000, +0x1E6B,0x0E0B,0x1E63,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6B,0x0E0B,0x1E7B,0x1E7A,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6C,0x1E52,0x1E5E,0x1E65,0x1E7A,0x0000,0x0000,0x0000,0x0000, +0x1E6C,0x1E59,0x1E7A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6C,0x1E5B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6C,0x1E7A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6D,0x1E52,0x1E78,0x1E63,0x1E65,0x0000,0x0000,0x0000,0x0000, +0x1E6D,0x1E53,0x0E0B,0x1E65,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6D,0x1E63,0x1E5D,0x1E55,0x1E7A,0x0000,0x0000,0x0000,0x0000, +0x1E6D,0x1E78,0x1E81,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6E,0x1E59,0x1E61,0x0E0B,0x1E7A,0x0000,0x0000,0x0000,0x0000, +0x1E6E,0x1E60,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6E,0x1E67,0x1E6C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6E,0x1E7A,0x1E63,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6E,0x1E81,0x1E5E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6E,0x0E0B,0x1E5D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6E,0x0E0B,0x1E61,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6F,0x1E53,0x1E81,0x1E65,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6F,0x1E7A,0x1E65,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6F,0x1E81,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6F,0x1E81,0x1E65,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6F,0x0E0B,0x1E7A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E6F,0x0E0B,0x1E81,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E70,0x1E53,0x1E59,0x1E7C,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E70,0x1E53,0x1E7A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E70,0x1E63,0x1E6B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E70,0x1E7A,0x1E59,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E70,0x1E81,0x1E5D,0x1E77,0x1E81,0x0000,0x0000,0x0000,0x0000, +0x1E71,0x1E59,0x1E7C,0x1E81,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E71,0x1E79,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E71,0x1E79,0x1E6B,0x0E0B,0x1E7A,0x0000,0x0000,0x0000,0x0000, +0x1E73,0x1E57,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E73,0x1E57,0x1E65,0x1E81,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E73,0x0E0B,0x1E65,0x1E7A,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E75,0x0E0B,0x1E65,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E75,0x0E0B,0x1E7A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E76,0x1E52,0x1E81,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E79,0x1E63,0x1E65,0x1E7A,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E79,0x1E78,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E7A,0x1E6C,0x0E0B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E7A,0x0E0B,0x1E6D,0x1E7A,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E7B,0x1E72,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1E7B,0x1E81,0x1E65,0x1E5A,0x1E81,0x0000,0x0000,0x0000,0x0000, +0x1E7D,0x1E63,0x1E65,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E29,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2C,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2D,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2E,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2F,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E30,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E31,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E32,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E29,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E2A,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E2B,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E2C,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E2D,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E2E,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E2F,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E30,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E31,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E32,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E29,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E2A,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E2B,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E2C,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E2D,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0EE1,0x0FA7,0x0E33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E6D,0x0E33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E33,0x101F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E4A,0x0E33,0x0FC0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F82,0x1044,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0FA7,0x0E60,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E6D,0x0F5B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E6D,0x0F5B,0x0E2B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E6D,0x0F5B,0x0E2C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0EFB,0x101F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xDE73,0xFB40,0xE210,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xE62D,0xFB40,0xD48C,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xD927,0xFB40,0xEB63,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xE60E,0xFB40,0xECBB,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFB40,0xE82A,0xFB40,0xDF0F,0xFB40,0xCF1A,0xFB40,0xF93E,0x0000, +0x0FA7,0x0E33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F64,0x0E33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x10F8,0x0E33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0E33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F21,0x0E33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F21,0x0E4A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0E4A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0EC1,0x0E4A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E60,0x0E33,0x0F2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F21,0x0E60,0x0E33,0x0F2E,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0FA7,0x0EB9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F64,0x0EB9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x10F8,0x0EB9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x10F8,0x0EC1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0EC1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F21,0x0EC1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0EE1,0x106A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F21,0x0EE1,0x106A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0EE1,0x106A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0EC1,0x0EE1,0x106A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1002,0x0EE1,0x106A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x10F8,0x0F2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0F2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E6D,0x0F2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F21,0x0F2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0EB9,0x0F5B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F64,0x0F5B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x10F8,0x0F5B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0F5B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E60,0x0F5B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F21,0x0F5B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0F5B,0x0E2B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E60,0x0F5B,0x0E2B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0E2B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F21,0x0F5B,0x0E2B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0F5B,0x0E2C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E60,0x0F5B,0x0E2C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0E2C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F21,0x0F5B,0x0E2C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0437,0x0FEA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0437,0x0FEA,0x0E2B,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0FA7,0x0E33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F21,0x0FA7,0x0E33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0FA7,0x0E33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0EC1,0x0FA7,0x0E33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0FC0,0x0E33,0x0E6D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0FC0,0x0E33,0x0E6D,0x0437,0x0FEA,0x0000,0x0000,0x0000,0x0000, +0x0FC0,0x0E33,0x0E6D,0x0437,0x0FEA,0x0E2B,0x0000,0x0000,0x0000, +0x0FA7,0x0FEA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F64,0x0FEA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x10F8,0x0FEA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0FEA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0FA7,0x1044,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F64,0x1044,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x10F8,0x1044,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x1044,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F21,0x1044,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x1044,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0FA7,0x1051,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F64,0x1051,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x10F8,0x1051,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x1051,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F21,0x1051,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x1051,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F21,0x1109,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x1109,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E33,0x025D,0x0F5B,0x025D,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E4A,0x0FB4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E60,0x0E60,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E60,0x0E6D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E60,0x0437,0x0F21,0x0EC1,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E60,0x0F82,0x025D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E6D,0x0E4A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0EC1,0x105E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0EE1,0x0E33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0EE1,0x0FA7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0EFB,0x0F64,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F21,0x0F21,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F21,0x0F5B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F21,0x1002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F2E,0x0F5B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F2E,0x0F64,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F2E,0x0F82,0x0EC1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F2E,0x105A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0E4A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0EFB,0x0F2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0F5B,0x0F82,0x0F2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0FA7,0x0EE1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0FA7,0x025D,0x0F5B,0x025D,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0FA7,0x0FA7,0x0F5B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0FA7,0x0FC0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0FEA,0x0FC0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0FEA,0x1044,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1051,0x0E4A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1044,0x0437,0x0F5B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E33,0x0437,0x0F5B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2C,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2D,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2E,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2F,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E30,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E31,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E32,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E29,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E2A,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E2B,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E2C,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E2D,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E2E,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E2F,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E30,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E31,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2A,0x0E32,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E29,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E2A,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E2B,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E2C,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E2D,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E2E,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E2F,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E30,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E31,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2B,0x0E32,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2C,0x0E29,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0E2C,0x0E2A,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0EC1,0x0E33,0x0F2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 +}; + +uint16 page04Ddata[]= { /* 4D00 (3 weights per char) */ +0xFB80,0xCD00,0x0000, 0xFB80,0xCD01,0x0000, 0xFB80,0xCD02,0x0000, +0xFB80,0xCD03,0x0000, 0xFB80,0xCD04,0x0000, 0xFB80,0xCD05,0x0000, +0xFB80,0xCD06,0x0000, 0xFB80,0xCD07,0x0000, 0xFB80,0xCD08,0x0000, +0xFB80,0xCD09,0x0000, 0xFB80,0xCD0A,0x0000, 0xFB80,0xCD0B,0x0000, +0xFB80,0xCD0C,0x0000, 0xFB80,0xCD0D,0x0000, 0xFB80,0xCD0E,0x0000, +0xFB80,0xCD0F,0x0000, 0xFB80,0xCD10,0x0000, 0xFB80,0xCD11,0x0000, +0xFB80,0xCD12,0x0000, 0xFB80,0xCD13,0x0000, 0xFB80,0xCD14,0x0000, +0xFB80,0xCD15,0x0000, 0xFB80,0xCD16,0x0000, 0xFB80,0xCD17,0x0000, +0xFB80,0xCD18,0x0000, 0xFB80,0xCD19,0x0000, 0xFB80,0xCD1A,0x0000, +0xFB80,0xCD1B,0x0000, 0xFB80,0xCD1C,0x0000, 0xFB80,0xCD1D,0x0000, +0xFB80,0xCD1E,0x0000, 0xFB80,0xCD1F,0x0000, 0xFB80,0xCD20,0x0000, +0xFB80,0xCD21,0x0000, 0xFB80,0xCD22,0x0000, 0xFB80,0xCD23,0x0000, +0xFB80,0xCD24,0x0000, 0xFB80,0xCD25,0x0000, 0xFB80,0xCD26,0x0000, +0xFB80,0xCD27,0x0000, 0xFB80,0xCD28,0x0000, 0xFB80,0xCD29,0x0000, +0xFB80,0xCD2A,0x0000, 0xFB80,0xCD2B,0x0000, 0xFB80,0xCD2C,0x0000, +0xFB80,0xCD2D,0x0000, 0xFB80,0xCD2E,0x0000, 0xFB80,0xCD2F,0x0000, +0xFB80,0xCD30,0x0000, 0xFB80,0xCD31,0x0000, 0xFB80,0xCD32,0x0000, +0xFB80,0xCD33,0x0000, 0xFB80,0xCD34,0x0000, 0xFB80,0xCD35,0x0000, +0xFB80,0xCD36,0x0000, 0xFB80,0xCD37,0x0000, 0xFB80,0xCD38,0x0000, +0xFB80,0xCD39,0x0000, 0xFB80,0xCD3A,0x0000, 0xFB80,0xCD3B,0x0000, +0xFB80,0xCD3C,0x0000, 0xFB80,0xCD3D,0x0000, 0xFB80,0xCD3E,0x0000, +0xFB80,0xCD3F,0x0000, 0xFB80,0xCD40,0x0000, 0xFB80,0xCD41,0x0000, +0xFB80,0xCD42,0x0000, 0xFB80,0xCD43,0x0000, 0xFB80,0xCD44,0x0000, +0xFB80,0xCD45,0x0000, 0xFB80,0xCD46,0x0000, 0xFB80,0xCD47,0x0000, +0xFB80,0xCD48,0x0000, 0xFB80,0xCD49,0x0000, 0xFB80,0xCD4A,0x0000, +0xFB80,0xCD4B,0x0000, 0xFB80,0xCD4C,0x0000, 0xFB80,0xCD4D,0x0000, +0xFB80,0xCD4E,0x0000, 0xFB80,0xCD4F,0x0000, 0xFB80,0xCD50,0x0000, +0xFB80,0xCD51,0x0000, 0xFB80,0xCD52,0x0000, 0xFB80,0xCD53,0x0000, +0xFB80,0xCD54,0x0000, 0xFB80,0xCD55,0x0000, 0xFB80,0xCD56,0x0000, +0xFB80,0xCD57,0x0000, 0xFB80,0xCD58,0x0000, 0xFB80,0xCD59,0x0000, +0xFB80,0xCD5A,0x0000, 0xFB80,0xCD5B,0x0000, 0xFB80,0xCD5C,0x0000, +0xFB80,0xCD5D,0x0000, 0xFB80,0xCD5E,0x0000, 0xFB80,0xCD5F,0x0000, +0xFB80,0xCD60,0x0000, 0xFB80,0xCD61,0x0000, 0xFB80,0xCD62,0x0000, +0xFB80,0xCD63,0x0000, 0xFB80,0xCD64,0x0000, 0xFB80,0xCD65,0x0000, +0xFB80,0xCD66,0x0000, 0xFB80,0xCD67,0x0000, 0xFB80,0xCD68,0x0000, +0xFB80,0xCD69,0x0000, 0xFB80,0xCD6A,0x0000, 0xFB80,0xCD6B,0x0000, +0xFB80,0xCD6C,0x0000, 0xFB80,0xCD6D,0x0000, 0xFB80,0xCD6E,0x0000, +0xFB80,0xCD6F,0x0000, 0xFB80,0xCD70,0x0000, 0xFB80,0xCD71,0x0000, +0xFB80,0xCD72,0x0000, 0xFB80,0xCD73,0x0000, 0xFB80,0xCD74,0x0000, +0xFB80,0xCD75,0x0000, 0xFB80,0xCD76,0x0000, 0xFB80,0xCD77,0x0000, +0xFB80,0xCD78,0x0000, 0xFB80,0xCD79,0x0000, 0xFB80,0xCD7A,0x0000, +0xFB80,0xCD7B,0x0000, 0xFB80,0xCD7C,0x0000, 0xFB80,0xCD7D,0x0000, +0xFB80,0xCD7E,0x0000, 0xFB80,0xCD7F,0x0000, 0xFB80,0xCD80,0x0000, +0xFB80,0xCD81,0x0000, 0xFB80,0xCD82,0x0000, 0xFB80,0xCD83,0x0000, +0xFB80,0xCD84,0x0000, 0xFB80,0xCD85,0x0000, 0xFB80,0xCD86,0x0000, +0xFB80,0xCD87,0x0000, 0xFB80,0xCD88,0x0000, 0xFB80,0xCD89,0x0000, +0xFB80,0xCD8A,0x0000, 0xFB80,0xCD8B,0x0000, 0xFB80,0xCD8C,0x0000, +0xFB80,0xCD8D,0x0000, 0xFB80,0xCD8E,0x0000, 0xFB80,0xCD8F,0x0000, +0xFB80,0xCD90,0x0000, 0xFB80,0xCD91,0x0000, 0xFB80,0xCD92,0x0000, +0xFB80,0xCD93,0x0000, 0xFB80,0xCD94,0x0000, 0xFB80,0xCD95,0x0000, +0xFB80,0xCD96,0x0000, 0xFB80,0xCD97,0x0000, 0xFB80,0xCD98,0x0000, +0xFB80,0xCD99,0x0000, 0xFB80,0xCD9A,0x0000, 0xFB80,0xCD9B,0x0000, +0xFB80,0xCD9C,0x0000, 0xFB80,0xCD9D,0x0000, 0xFB80,0xCD9E,0x0000, +0xFB80,0xCD9F,0x0000, 0xFB80,0xCDA0,0x0000, 0xFB80,0xCDA1,0x0000, +0xFB80,0xCDA2,0x0000, 0xFB80,0xCDA3,0x0000, 0xFB80,0xCDA4,0x0000, +0xFB80,0xCDA5,0x0000, 0xFB80,0xCDA6,0x0000, 0xFB80,0xCDA7,0x0000, +0xFB80,0xCDA8,0x0000, 0xFB80,0xCDA9,0x0000, 0xFB80,0xCDAA,0x0000, +0xFB80,0xCDAB,0x0000, 0xFB80,0xCDAC,0x0000, 0xFB80,0xCDAD,0x0000, +0xFB80,0xCDAE,0x0000, 0xFB80,0xCDAF,0x0000, 0xFB80,0xCDB0,0x0000, +0xFB80,0xCDB1,0x0000, 0xFB80,0xCDB2,0x0000, 0xFB80,0xCDB3,0x0000, +0xFB80,0xCDB4,0x0000, 0xFB80,0xCDB5,0x0000, 0xFBC0,0xCDB6,0x0000, +0xFBC0,0xCDB7,0x0000, 0xFBC0,0xCDB8,0x0000, 0xFBC0,0xCDB9,0x0000, +0xFBC0,0xCDBA,0x0000, 0xFBC0,0xCDBB,0x0000, 0xFBC0,0xCDBC,0x0000, +0xFBC0,0xCDBD,0x0000, 0xFBC0,0xCDBE,0x0000, 0xFBC0,0xCDBF,0x0000, +0x0B37,0x0000,0x0000, 0x0B38,0x0000,0x0000, 0x0B39,0x0000,0x0000, +0x0B3A,0x0000,0x0000, 0x0B3B,0x0000,0x0000, 0x0B3C,0x0000,0x0000, +0x0B3D,0x0000,0x0000, 0x0B3E,0x0000,0x0000, 0x0B3F,0x0000,0x0000, +0x0B40,0x0000,0x0000, 0x0B41,0x0000,0x0000, 0x0B42,0x0000,0x0000, +0x0B43,0x0000,0x0000, 0x0B44,0x0000,0x0000, 0x0B45,0x0000,0x0000, +0x0B46,0x0000,0x0000, 0x0B47,0x0000,0x0000, 0x0B48,0x0000,0x0000, +0x0B49,0x0000,0x0000, 0x0B4A,0x0000,0x0000, 0x0B4B,0x0000,0x0000, +0x0B4C,0x0000,0x0000, 0x0B4D,0x0000,0x0000, 0x0B4E,0x0000,0x0000, +0x0B4F,0x0000,0x0000, 0x0B50,0x0000,0x0000, 0x0B51,0x0000,0x0000, +0x0B52,0x0000,0x0000, 0x0B53,0x0000,0x0000, 0x0B54,0x0000,0x0000, +0x0B55,0x0000,0x0000, 0x0B56,0x0000,0x0000, 0x0B57,0x0000,0x0000, +0x0B58,0x0000,0x0000, 0x0B59,0x0000,0x0000, 0x0B5A,0x0000,0x0000, +0x0B5B,0x0000,0x0000, 0x0B5C,0x0000,0x0000, 0x0B5D,0x0000,0x0000, +0x0B5E,0x0000,0x0000, 0x0B5F,0x0000,0x0000, 0x0B60,0x0000,0x0000, +0x0B61,0x0000,0x0000, 0x0B62,0x0000,0x0000, 0x0B63,0x0000,0x0000, +0x0B64,0x0000,0x0000, 0x0B65,0x0000,0x0000, 0x0B66,0x0000,0x0000, +0x0B67,0x0000,0x0000, 0x0B68,0x0000,0x0000, 0x0B69,0x0000,0x0000, +0x0B6A,0x0000,0x0000, 0x0B6B,0x0000,0x0000, 0x0B6C,0x0000,0x0000, +0x0B6D,0x0000,0x0000, 0x0B6E,0x0000,0x0000, 0x0B6F,0x0000,0x0000, +0x0B70,0x0000,0x0000, 0x0B71,0x0000,0x0000, 0x0B72,0x0000,0x0000, +0x0B73,0x0000,0x0000, 0x0B74,0x0000,0x0000, 0x0B75,0x0000,0x0000, +0x0B76,0x0000,0x0000 }; + +uint16 page0A0data[]= { /* A000 (2 weights per char) */ +0x1EB1,0x0000, 0x1EB2,0x0000, 0x1EB3,0x0000, 0x1EB4,0x0000, +0x1EB5,0x0000, 0x1EB6,0x0000, 0x1EB7,0x0000, 0x1EB8,0x0000, +0x1EB9,0x0000, 0x1EBA,0x0000, 0x1EBB,0x0000, 0x1EBC,0x0000, +0x1EBD,0x0000, 0x1EBE,0x0000, 0x1EBF,0x0000, 0x1EC0,0x0000, +0x1EC1,0x0000, 0x1EC2,0x0000, 0x1EC3,0x0000, 0x1EC4,0x0000, +0x1EC5,0x0000, 0x1EC6,0x0000, 0x1EC7,0x0000, 0x1EC8,0x0000, +0x1EC9,0x0000, 0x1ECA,0x0000, 0x1ECB,0x0000, 0x1ECC,0x0000, +0x1ECD,0x0000, 0x1ECE,0x0000, 0x1ECF,0x0000, 0x1ED0,0x0000, +0x1ED1,0x0000, 0x1ED2,0x0000, 0x1ED3,0x0000, 0x1ED4,0x0000, +0x1ED5,0x0000, 0x1ED6,0x0000, 0x1ED7,0x0000, 0x1ED8,0x0000, +0x1ED9,0x0000, 0x1EDA,0x0000, 0x1EDB,0x0000, 0x1EDC,0x0000, +0x1EDD,0x0000, 0x1EDE,0x0000, 0x1EDF,0x0000, 0x1EE0,0x0000, +0x1EE1,0x0000, 0x1EE2,0x0000, 0x1EE3,0x0000, 0x1EE4,0x0000, +0x1EE5,0x0000, 0x1EE6,0x0000, 0x1EE7,0x0000, 0x1EE8,0x0000, +0x1EE9,0x0000, 0x1EEA,0x0000, 0x1EEB,0x0000, 0x1EEC,0x0000, +0x1EED,0x0000, 0x1EEE,0x0000, 0x1EEF,0x0000, 0x1EF0,0x0000, +0x1EF1,0x0000, 0x1EF2,0x0000, 0x1EF3,0x0000, 0x1EF4,0x0000, +0x1EF5,0x0000, 0x1EF6,0x0000, 0x1EF7,0x0000, 0x1EF8,0x0000, +0x1EF9,0x0000, 0x1EFA,0x0000, 0x1EFB,0x0000, 0x1EFC,0x0000, +0x1EFD,0x0000, 0x1EFE,0x0000, 0x1EFF,0x0000, 0x1F00,0x0000, +0x1F01,0x0000, 0x1F02,0x0000, 0x1F03,0x0000, 0x1F04,0x0000, +0x1F05,0x0000, 0x1F06,0x0000, 0x1F07,0x0000, 0x1F08,0x0000, +0x1F09,0x0000, 0x1F0A,0x0000, 0x1F0B,0x0000, 0x1F0C,0x0000, +0x1F0D,0x0000, 0x1F0E,0x0000, 0x1F0F,0x0000, 0x1F10,0x0000, +0x1F11,0x0000, 0x1F12,0x0000, 0x1F13,0x0000, 0x1F14,0x0000, +0x1F15,0x0000, 0x1F16,0x0000, 0x1F17,0x0000, 0x1F18,0x0000, +0x1F19,0x0000, 0x1F1A,0x0000, 0x1F1B,0x0000, 0x1F1C,0x0000, +0x1F1D,0x0000, 0x1F1E,0x0000, 0x1F1F,0x0000, 0x1F20,0x0000, +0x1F21,0x0000, 0x1F22,0x0000, 0x1F23,0x0000, 0x1F24,0x0000, +0x1F25,0x0000, 0x1F26,0x0000, 0x1F27,0x0000, 0x1F28,0x0000, +0x1F29,0x0000, 0x1F2A,0x0000, 0x1F2B,0x0000, 0x1F2C,0x0000, +0x1F2D,0x0000, 0x1F2E,0x0000, 0x1F2F,0x0000, 0x1F30,0x0000, +0x1F31,0x0000, 0x1F32,0x0000, 0x1F33,0x0000, 0x1F34,0x0000, +0x1F35,0x0000, 0x1F36,0x0000, 0x1F37,0x0000, 0x1F38,0x0000, +0x1F39,0x0000, 0x1F3A,0x0000, 0x1F3B,0x0000, 0x1F3C,0x0000, +0x1F3D,0x0000, 0x1F3E,0x0000, 0x1F3F,0x0000, 0x1F40,0x0000, +0x1F41,0x0000, 0x1F42,0x0000, 0x1F43,0x0000, 0x1F44,0x0000, +0x1F45,0x0000, 0x1F46,0x0000, 0x1F47,0x0000, 0x1F48,0x0000, +0x1F49,0x0000, 0x1F4A,0x0000, 0x1F4B,0x0000, 0x1F4C,0x0000, +0x1F4D,0x0000, 0x1F4E,0x0000, 0x1F4F,0x0000, 0x1F50,0x0000, +0x1F51,0x0000, 0x1F52,0x0000, 0x1F53,0x0000, 0x1F54,0x0000, +0x1F55,0x0000, 0x1F56,0x0000, 0x1F57,0x0000, 0x1F58,0x0000, +0x1F59,0x0000, 0x1F5A,0x0000, 0x1F5B,0x0000, 0x1F5C,0x0000, +0x1F5D,0x0000, 0x1F5E,0x0000, 0x1F5F,0x0000, 0x1F60,0x0000, +0x1F61,0x0000, 0x1F62,0x0000, 0x1F63,0x0000, 0x1F64,0x0000, +0x1F65,0x0000, 0x1F66,0x0000, 0x1F67,0x0000, 0x1F68,0x0000, +0x1F69,0x0000, 0x1F6A,0x0000, 0x1F6B,0x0000, 0x1F6C,0x0000, +0x1F6D,0x0000, 0x1F6E,0x0000, 0x1F6F,0x0000, 0x1F70,0x0000, +0x1F71,0x0000, 0x1F72,0x0000, 0x1F73,0x0000, 0x1F74,0x0000, +0x1F75,0x0000, 0x1F76,0x0000, 0x1F77,0x0000, 0x1F78,0x0000, +0x1F79,0x0000, 0x1F7A,0x0000, 0x1F7B,0x0000, 0x1F7C,0x0000, +0x1F7D,0x0000, 0x1F7E,0x0000, 0x1F7F,0x0000, 0x1F80,0x0000, +0x1F81,0x0000, 0x1F82,0x0000, 0x1F83,0x0000, 0x1F84,0x0000, +0x1F85,0x0000, 0x1F86,0x0000, 0x1F87,0x0000, 0x1F88,0x0000, +0x1F89,0x0000, 0x1F8A,0x0000, 0x1F8B,0x0000, 0x1F8C,0x0000, +0x1F8D,0x0000, 0x1F8E,0x0000, 0x1F8F,0x0000, 0x1F90,0x0000, +0x1F91,0x0000, 0x1F92,0x0000, 0x1F93,0x0000, 0x1F94,0x0000, +0x1F95,0x0000, 0x1F96,0x0000, 0x1F97,0x0000, 0x1F98,0x0000, +0x1F99,0x0000, 0x1F9A,0x0000, 0x1F9B,0x0000, 0x1F9C,0x0000, +0x1F9D,0x0000, 0x1F9E,0x0000, 0x1F9F,0x0000, 0x1FA0,0x0000, +0x1FA1,0x0000, 0x1FA2,0x0000, 0x1FA3,0x0000, 0x1FA4,0x0000, +0x1FA5,0x0000, 0x1FA6,0x0000, 0x1FA7,0x0000, 0x1FA8,0x0000, +0x1FA9,0x0000, 0x1FAA,0x0000, 0x1FAB,0x0000, 0x1FAC,0x0000, +0x1FAD,0x0000, 0x1FAE,0x0000, 0x1FAF,0x0000, 0x1FB0,0x0000 +}; + +uint16 page0A1data[]= { /* A100 (2 weights per char) */ +0x1FB1,0x0000, 0x1FB2,0x0000, 0x1FB3,0x0000, 0x1FB4,0x0000, +0x1FB5,0x0000, 0x1FB6,0x0000, 0x1FB7,0x0000, 0x1FB8,0x0000, +0x1FB9,0x0000, 0x1FBA,0x0000, 0x1FBB,0x0000, 0x1FBC,0x0000, +0x1FBD,0x0000, 0x1FBE,0x0000, 0x1FBF,0x0000, 0x1FC0,0x0000, +0x1FC1,0x0000, 0x1FC2,0x0000, 0x1FC3,0x0000, 0x1FC4,0x0000, +0x1FC5,0x0000, 0x1FC6,0x0000, 0x1FC7,0x0000, 0x1FC8,0x0000, +0x1FC9,0x0000, 0x1FCA,0x0000, 0x1FCB,0x0000, 0x1FCC,0x0000, +0x1FCD,0x0000, 0x1FCE,0x0000, 0x1FCF,0x0000, 0x1FD0,0x0000, +0x1FD1,0x0000, 0x1FD2,0x0000, 0x1FD3,0x0000, 0x1FD4,0x0000, +0x1FD5,0x0000, 0x1FD6,0x0000, 0x1FD7,0x0000, 0x1FD8,0x0000, +0x1FD9,0x0000, 0x1FDA,0x0000, 0x1FDB,0x0000, 0x1FDC,0x0000, +0x1FDD,0x0000, 0x1FDE,0x0000, 0x1FDF,0x0000, 0x1FE0,0x0000, +0x1FE1,0x0000, 0x1FE2,0x0000, 0x1FE3,0x0000, 0x1FE4,0x0000, +0x1FE5,0x0000, 0x1FE6,0x0000, 0x1FE7,0x0000, 0x1FE8,0x0000, +0x1FE9,0x0000, 0x1FEA,0x0000, 0x1FEB,0x0000, 0x1FEC,0x0000, +0x1FED,0x0000, 0x1FEE,0x0000, 0x1FEF,0x0000, 0x1FF0,0x0000, +0x1FF1,0x0000, 0x1FF2,0x0000, 0x1FF3,0x0000, 0x1FF4,0x0000, +0x1FF5,0x0000, 0x1FF6,0x0000, 0x1FF7,0x0000, 0x1FF8,0x0000, +0x1FF9,0x0000, 0x1FFA,0x0000, 0x1FFB,0x0000, 0x1FFC,0x0000, +0x1FFD,0x0000, 0x1FFE,0x0000, 0x1FFF,0x0000, 0x2000,0x0000, +0x2001,0x0000, 0x2002,0x0000, 0x2003,0x0000, 0x2004,0x0000, +0x2005,0x0000, 0x2006,0x0000, 0x2007,0x0000, 0x2008,0x0000, +0x2009,0x0000, 0x200A,0x0000, 0x200B,0x0000, 0x200C,0x0000, +0x200D,0x0000, 0x200E,0x0000, 0x200F,0x0000, 0x2010,0x0000, +0x2011,0x0000, 0x2012,0x0000, 0x2013,0x0000, 0x2014,0x0000, +0x2015,0x0000, 0x2016,0x0000, 0x2017,0x0000, 0x2018,0x0000, +0x2019,0x0000, 0x201A,0x0000, 0x201B,0x0000, 0x201C,0x0000, +0x201D,0x0000, 0x201E,0x0000, 0x201F,0x0000, 0x2020,0x0000, +0x2021,0x0000, 0x2022,0x0000, 0x2023,0x0000, 0x2024,0x0000, +0x2025,0x0000, 0x2026,0x0000, 0x2027,0x0000, 0x2028,0x0000, +0x2029,0x0000, 0x202A,0x0000, 0x202B,0x0000, 0x202C,0x0000, +0x202D,0x0000, 0x202E,0x0000, 0x202F,0x0000, 0x2030,0x0000, +0x2031,0x0000, 0x2032,0x0000, 0x2033,0x0000, 0x2034,0x0000, +0x2035,0x0000, 0x2036,0x0000, 0x2037,0x0000, 0x2038,0x0000, +0x2039,0x0000, 0x203A,0x0000, 0x203B,0x0000, 0x203C,0x0000, +0x203D,0x0000, 0x203E,0x0000, 0x203F,0x0000, 0x2040,0x0000, +0x2041,0x0000, 0x2042,0x0000, 0x2043,0x0000, 0x2044,0x0000, +0x2045,0x0000, 0x2046,0x0000, 0x2047,0x0000, 0x2048,0x0000, +0x2049,0x0000, 0x204A,0x0000, 0x204B,0x0000, 0x204C,0x0000, +0x204D,0x0000, 0x204E,0x0000, 0x204F,0x0000, 0x2050,0x0000, +0x2051,0x0000, 0x2052,0x0000, 0x2053,0x0000, 0x2054,0x0000, +0x2055,0x0000, 0x2056,0x0000, 0x2057,0x0000, 0x2058,0x0000, +0x2059,0x0000, 0x205A,0x0000, 0x205B,0x0000, 0x205C,0x0000, +0x205D,0x0000, 0x205E,0x0000, 0x205F,0x0000, 0x2060,0x0000, +0x2061,0x0000, 0x2062,0x0000, 0x2063,0x0000, 0x2064,0x0000, +0x2065,0x0000, 0x2066,0x0000, 0x2067,0x0000, 0x2068,0x0000, +0x2069,0x0000, 0x206A,0x0000, 0x206B,0x0000, 0x206C,0x0000, +0x206D,0x0000, 0x206E,0x0000, 0x206F,0x0000, 0x2070,0x0000, +0x2071,0x0000, 0x2072,0x0000, 0x2073,0x0000, 0x2074,0x0000, +0x2075,0x0000, 0x2076,0x0000, 0x2077,0x0000, 0x2078,0x0000, +0x2079,0x0000, 0x207A,0x0000, 0x207B,0x0000, 0x207C,0x0000, +0x207D,0x0000, 0x207E,0x0000, 0x207F,0x0000, 0x2080,0x0000, +0x2081,0x0000, 0x2082,0x0000, 0x2083,0x0000, 0x2084,0x0000, +0x2085,0x0000, 0x2086,0x0000, 0x2087,0x0000, 0x2088,0x0000, +0x2089,0x0000, 0x208A,0x0000, 0x208B,0x0000, 0x208C,0x0000, +0x208D,0x0000, 0x208E,0x0000, 0x208F,0x0000, 0x2090,0x0000, +0x2091,0x0000, 0x2092,0x0000, 0x2093,0x0000, 0x2094,0x0000, +0x2095,0x0000, 0x2096,0x0000, 0x2097,0x0000, 0x2098,0x0000, +0x2099,0x0000, 0x209A,0x0000, 0x209B,0x0000, 0x209C,0x0000, +0x209D,0x0000, 0x209E,0x0000, 0x209F,0x0000, 0x20A0,0x0000, +0x20A1,0x0000, 0x20A2,0x0000, 0x20A3,0x0000, 0x20A4,0x0000, +0x20A5,0x0000, 0x20A6,0x0000, 0x20A7,0x0000, 0x20A8,0x0000, +0x20A9,0x0000, 0x20AA,0x0000, 0x20AB,0x0000, 0x20AC,0x0000, +0x20AD,0x0000, 0x20AE,0x0000, 0x20AF,0x0000, 0x20B0,0x0000 +}; + +uint16 page0A2data[]= { /* A200 (2 weights per char) */ +0x20B1,0x0000, 0x20B2,0x0000, 0x20B3,0x0000, 0x20B4,0x0000, +0x20B5,0x0000, 0x20B6,0x0000, 0x20B7,0x0000, 0x20B8,0x0000, +0x20B9,0x0000, 0x20BA,0x0000, 0x20BB,0x0000, 0x20BC,0x0000, +0x20BD,0x0000, 0x20BE,0x0000, 0x20BF,0x0000, 0x20C0,0x0000, +0x20C1,0x0000, 0x20C2,0x0000, 0x20C3,0x0000, 0x20C4,0x0000, +0x20C5,0x0000, 0x20C6,0x0000, 0x20C7,0x0000, 0x20C8,0x0000, +0x20C9,0x0000, 0x20CA,0x0000, 0x20CB,0x0000, 0x20CC,0x0000, +0x20CD,0x0000, 0x20CE,0x0000, 0x20CF,0x0000, 0x20D0,0x0000, +0x20D1,0x0000, 0x20D2,0x0000, 0x20D3,0x0000, 0x20D4,0x0000, +0x20D5,0x0000, 0x20D6,0x0000, 0x20D7,0x0000, 0x20D8,0x0000, +0x20D9,0x0000, 0x20DA,0x0000, 0x20DB,0x0000, 0x20DC,0x0000, +0x20DD,0x0000, 0x20DE,0x0000, 0x20DF,0x0000, 0x20E0,0x0000, +0x20E1,0x0000, 0x20E2,0x0000, 0x20E3,0x0000, 0x20E4,0x0000, +0x20E5,0x0000, 0x20E6,0x0000, 0x20E7,0x0000, 0x20E8,0x0000, +0x20E9,0x0000, 0x20EA,0x0000, 0x20EB,0x0000, 0x20EC,0x0000, +0x20ED,0x0000, 0x20EE,0x0000, 0x20EF,0x0000, 0x20F0,0x0000, +0x20F1,0x0000, 0x20F2,0x0000, 0x20F3,0x0000, 0x20F4,0x0000, +0x20F5,0x0000, 0x20F6,0x0000, 0x20F7,0x0000, 0x20F8,0x0000, +0x20F9,0x0000, 0x20FA,0x0000, 0x20FB,0x0000, 0x20FC,0x0000, +0x20FD,0x0000, 0x20FE,0x0000, 0x20FF,0x0000, 0x2100,0x0000, +0x2101,0x0000, 0x2102,0x0000, 0x2103,0x0000, 0x2104,0x0000, +0x2105,0x0000, 0x2106,0x0000, 0x2107,0x0000, 0x2108,0x0000, +0x2109,0x0000, 0x210A,0x0000, 0x210B,0x0000, 0x210C,0x0000, +0x210D,0x0000, 0x210E,0x0000, 0x210F,0x0000, 0x2110,0x0000, +0x2111,0x0000, 0x2112,0x0000, 0x2113,0x0000, 0x2114,0x0000, +0x2115,0x0000, 0x2116,0x0000, 0x2117,0x0000, 0x2118,0x0000, +0x2119,0x0000, 0x211A,0x0000, 0x211B,0x0000, 0x211C,0x0000, +0x211D,0x0000, 0x211E,0x0000, 0x211F,0x0000, 0x2120,0x0000, +0x2121,0x0000, 0x2122,0x0000, 0x2123,0x0000, 0x2124,0x0000, +0x2125,0x0000, 0x2126,0x0000, 0x2127,0x0000, 0x2128,0x0000, +0x2129,0x0000, 0x212A,0x0000, 0x212B,0x0000, 0x212C,0x0000, +0x212D,0x0000, 0x212E,0x0000, 0x212F,0x0000, 0x2130,0x0000, +0x2131,0x0000, 0x2132,0x0000, 0x2133,0x0000, 0x2134,0x0000, +0x2135,0x0000, 0x2136,0x0000, 0x2137,0x0000, 0x2138,0x0000, +0x2139,0x0000, 0x213A,0x0000, 0x213B,0x0000, 0x213C,0x0000, +0x213D,0x0000, 0x213E,0x0000, 0x213F,0x0000, 0x2140,0x0000, +0x2141,0x0000, 0x2142,0x0000, 0x2143,0x0000, 0x2144,0x0000, +0x2145,0x0000, 0x2146,0x0000, 0x2147,0x0000, 0x2148,0x0000, +0x2149,0x0000, 0x214A,0x0000, 0x214B,0x0000, 0x214C,0x0000, +0x214D,0x0000, 0x214E,0x0000, 0x214F,0x0000, 0x2150,0x0000, +0x2151,0x0000, 0x2152,0x0000, 0x2153,0x0000, 0x2154,0x0000, +0x2155,0x0000, 0x2156,0x0000, 0x2157,0x0000, 0x2158,0x0000, +0x2159,0x0000, 0x215A,0x0000, 0x215B,0x0000, 0x215C,0x0000, +0x215D,0x0000, 0x215E,0x0000, 0x215F,0x0000, 0x2160,0x0000, +0x2161,0x0000, 0x2162,0x0000, 0x2163,0x0000, 0x2164,0x0000, +0x2165,0x0000, 0x2166,0x0000, 0x2167,0x0000, 0x2168,0x0000, +0x2169,0x0000, 0x216A,0x0000, 0x216B,0x0000, 0x216C,0x0000, +0x216D,0x0000, 0x216E,0x0000, 0x216F,0x0000, 0x2170,0x0000, +0x2171,0x0000, 0x2172,0x0000, 0x2173,0x0000, 0x2174,0x0000, +0x2175,0x0000, 0x2176,0x0000, 0x2177,0x0000, 0x2178,0x0000, +0x2179,0x0000, 0x217A,0x0000, 0x217B,0x0000, 0x217C,0x0000, +0x217D,0x0000, 0x217E,0x0000, 0x217F,0x0000, 0x2180,0x0000, +0x2181,0x0000, 0x2182,0x0000, 0x2183,0x0000, 0x2184,0x0000, +0x2185,0x0000, 0x2186,0x0000, 0x2187,0x0000, 0x2188,0x0000, +0x2189,0x0000, 0x218A,0x0000, 0x218B,0x0000, 0x218C,0x0000, +0x218D,0x0000, 0x218E,0x0000, 0x218F,0x0000, 0x2190,0x0000, +0x2191,0x0000, 0x2192,0x0000, 0x2193,0x0000, 0x2194,0x0000, +0x2195,0x0000, 0x2196,0x0000, 0x2197,0x0000, 0x2198,0x0000, +0x2199,0x0000, 0x219A,0x0000, 0x219B,0x0000, 0x219C,0x0000, +0x219D,0x0000, 0x219E,0x0000, 0x219F,0x0000, 0x21A0,0x0000, +0x21A1,0x0000, 0x21A2,0x0000, 0x21A3,0x0000, 0x21A4,0x0000, +0x21A5,0x0000, 0x21A6,0x0000, 0x21A7,0x0000, 0x21A8,0x0000, +0x21A9,0x0000, 0x21AA,0x0000, 0x21AB,0x0000, 0x21AC,0x0000, +0x21AD,0x0000, 0x21AE,0x0000, 0x21AF,0x0000, 0x21B0,0x0000 +}; + +uint16 page0A3data[]= { /* A300 (2 weights per char) */ +0x21B1,0x0000, 0x21B2,0x0000, 0x21B3,0x0000, 0x21B4,0x0000, +0x21B5,0x0000, 0x21B6,0x0000, 0x21B7,0x0000, 0x21B8,0x0000, +0x21B9,0x0000, 0x21BA,0x0000, 0x21BB,0x0000, 0x21BC,0x0000, +0x21BD,0x0000, 0x21BE,0x0000, 0x21BF,0x0000, 0x21C0,0x0000, +0x21C1,0x0000, 0x21C2,0x0000, 0x21C3,0x0000, 0x21C4,0x0000, +0x21C5,0x0000, 0x21C6,0x0000, 0x21C7,0x0000, 0x21C8,0x0000, +0x21C9,0x0000, 0x21CA,0x0000, 0x21CB,0x0000, 0x21CC,0x0000, +0x21CD,0x0000, 0x21CE,0x0000, 0x21CF,0x0000, 0x21D0,0x0000, +0x21D1,0x0000, 0x21D2,0x0000, 0x21D3,0x0000, 0x21D4,0x0000, +0x21D5,0x0000, 0x21D6,0x0000, 0x21D7,0x0000, 0x21D8,0x0000, +0x21D9,0x0000, 0x21DA,0x0000, 0x21DB,0x0000, 0x21DC,0x0000, +0x21DD,0x0000, 0x21DE,0x0000, 0x21DF,0x0000, 0x21E0,0x0000, +0x21E1,0x0000, 0x21E2,0x0000, 0x21E3,0x0000, 0x21E4,0x0000, +0x21E5,0x0000, 0x21E6,0x0000, 0x21E7,0x0000, 0x21E8,0x0000, +0x21E9,0x0000, 0x21EA,0x0000, 0x21EB,0x0000, 0x21EC,0x0000, +0x21ED,0x0000, 0x21EE,0x0000, 0x21EF,0x0000, 0x21F0,0x0000, +0x21F1,0x0000, 0x21F2,0x0000, 0x21F3,0x0000, 0x21F4,0x0000, +0x21F5,0x0000, 0x21F6,0x0000, 0x21F7,0x0000, 0x21F8,0x0000, +0x21F9,0x0000, 0x21FA,0x0000, 0x21FB,0x0000, 0x21FC,0x0000, +0x21FD,0x0000, 0x21FE,0x0000, 0x21FF,0x0000, 0x2200,0x0000, +0x2201,0x0000, 0x2202,0x0000, 0x2203,0x0000, 0x2204,0x0000, +0x2205,0x0000, 0x2206,0x0000, 0x2207,0x0000, 0x2208,0x0000, +0x2209,0x0000, 0x220A,0x0000, 0x220B,0x0000, 0x220C,0x0000, +0x220D,0x0000, 0x220E,0x0000, 0x220F,0x0000, 0x2210,0x0000, +0x2211,0x0000, 0x2212,0x0000, 0x2213,0x0000, 0x2214,0x0000, +0x2215,0x0000, 0x2216,0x0000, 0x2217,0x0000, 0x2218,0x0000, +0x2219,0x0000, 0x221A,0x0000, 0x221B,0x0000, 0x221C,0x0000, +0x221D,0x0000, 0x221E,0x0000, 0x221F,0x0000, 0x2220,0x0000, +0x2221,0x0000, 0x2222,0x0000, 0x2223,0x0000, 0x2224,0x0000, +0x2225,0x0000, 0x2226,0x0000, 0x2227,0x0000, 0x2228,0x0000, +0x2229,0x0000, 0x222A,0x0000, 0x222B,0x0000, 0x222C,0x0000, +0x222D,0x0000, 0x222E,0x0000, 0x222F,0x0000, 0x2230,0x0000, +0x2231,0x0000, 0x2232,0x0000, 0x2233,0x0000, 0x2234,0x0000, +0x2235,0x0000, 0x2236,0x0000, 0x2237,0x0000, 0x2238,0x0000, +0x2239,0x0000, 0x223A,0x0000, 0x223B,0x0000, 0x223C,0x0000, +0x223D,0x0000, 0x223E,0x0000, 0x223F,0x0000, 0x2240,0x0000, +0x2241,0x0000, 0x2242,0x0000, 0x2243,0x0000, 0x2244,0x0000, +0x2245,0x0000, 0x2246,0x0000, 0x2247,0x0000, 0x2248,0x0000, +0x2249,0x0000, 0x224A,0x0000, 0x224B,0x0000, 0x224C,0x0000, +0x224D,0x0000, 0x224E,0x0000, 0x224F,0x0000, 0x2250,0x0000, +0x2251,0x0000, 0x2252,0x0000, 0x2253,0x0000, 0x2254,0x0000, +0x2255,0x0000, 0x2256,0x0000, 0x2257,0x0000, 0x2258,0x0000, +0x2259,0x0000, 0x225A,0x0000, 0x225B,0x0000, 0x225C,0x0000, +0x225D,0x0000, 0x225E,0x0000, 0x225F,0x0000, 0x2260,0x0000, +0x2261,0x0000, 0x2262,0x0000, 0x2263,0x0000, 0x2264,0x0000, +0x2265,0x0000, 0x2266,0x0000, 0x2267,0x0000, 0x2268,0x0000, +0x2269,0x0000, 0x226A,0x0000, 0x226B,0x0000, 0x226C,0x0000, +0x226D,0x0000, 0x226E,0x0000, 0x226F,0x0000, 0x2270,0x0000, +0x2271,0x0000, 0x2272,0x0000, 0x2273,0x0000, 0x2274,0x0000, +0x2275,0x0000, 0x2276,0x0000, 0x2277,0x0000, 0x2278,0x0000, +0x2279,0x0000, 0x227A,0x0000, 0x227B,0x0000, 0x227C,0x0000, +0x227D,0x0000, 0x227E,0x0000, 0x227F,0x0000, 0x2280,0x0000, +0x2281,0x0000, 0x2282,0x0000, 0x2283,0x0000, 0x2284,0x0000, +0x2285,0x0000, 0x2286,0x0000, 0x2287,0x0000, 0x2288,0x0000, +0x2289,0x0000, 0x228A,0x0000, 0x228B,0x0000, 0x228C,0x0000, +0x228D,0x0000, 0x228E,0x0000, 0x228F,0x0000, 0x2290,0x0000, +0x2291,0x0000, 0x2292,0x0000, 0x2293,0x0000, 0x2294,0x0000, +0x2295,0x0000, 0x2296,0x0000, 0x2297,0x0000, 0x2298,0x0000, +0x2299,0x0000, 0x229A,0x0000, 0x229B,0x0000, 0x229C,0x0000, +0x229D,0x0000, 0x229E,0x0000, 0x229F,0x0000, 0x22A0,0x0000, +0x22A1,0x0000, 0x22A2,0x0000, 0x22A3,0x0000, 0x22A4,0x0000, +0x22A5,0x0000, 0x22A6,0x0000, 0x22A7,0x0000, 0x22A8,0x0000, +0x22A9,0x0000, 0x22AA,0x0000, 0x22AB,0x0000, 0x22AC,0x0000, +0x22AD,0x0000, 0x22AE,0x0000, 0x22AF,0x0000, 0x22B0,0x0000 +}; + +uint16 page0A4data[]= { /* A400 (3 weights per char) */ +0x22B1,0x0000,0x0000, 0x22B2,0x0000,0x0000, 0x22B3,0x0000,0x0000, +0x22B4,0x0000,0x0000, 0x22B5,0x0000,0x0000, 0x22B6,0x0000,0x0000, +0x22B7,0x0000,0x0000, 0x22B8,0x0000,0x0000, 0x22B9,0x0000,0x0000, +0x22BA,0x0000,0x0000, 0x22BB,0x0000,0x0000, 0x22BC,0x0000,0x0000, +0x22BD,0x0000,0x0000, 0x22BE,0x0000,0x0000, 0x22BF,0x0000,0x0000, +0x22C0,0x0000,0x0000, 0x22C1,0x0000,0x0000, 0x22C2,0x0000,0x0000, +0x22C3,0x0000,0x0000, 0x22C4,0x0000,0x0000, 0x22C5,0x0000,0x0000, +0x22C6,0x0000,0x0000, 0x22C7,0x0000,0x0000, 0x22C8,0x0000,0x0000, +0x22C9,0x0000,0x0000, 0x22CA,0x0000,0x0000, 0x22CB,0x0000,0x0000, +0x22CC,0x0000,0x0000, 0x22CD,0x0000,0x0000, 0x22CE,0x0000,0x0000, +0x22CF,0x0000,0x0000, 0x22D0,0x0000,0x0000, 0x22D1,0x0000,0x0000, +0x22D2,0x0000,0x0000, 0x22D3,0x0000,0x0000, 0x22D4,0x0000,0x0000, +0x22D5,0x0000,0x0000, 0x22D6,0x0000,0x0000, 0x22D7,0x0000,0x0000, +0x22D8,0x0000,0x0000, 0x22D9,0x0000,0x0000, 0x22DA,0x0000,0x0000, +0x22DB,0x0000,0x0000, 0x22DC,0x0000,0x0000, 0x22DD,0x0000,0x0000, +0x22DE,0x0000,0x0000, 0x22DF,0x0000,0x0000, 0x22E0,0x0000,0x0000, +0x22E1,0x0000,0x0000, 0x22E2,0x0000,0x0000, 0x22E3,0x0000,0x0000, +0x22E4,0x0000,0x0000, 0x22E5,0x0000,0x0000, 0x22E6,0x0000,0x0000, +0x22E7,0x0000,0x0000, 0x22E8,0x0000,0x0000, 0x22E9,0x0000,0x0000, +0x22EA,0x0000,0x0000, 0x22EB,0x0000,0x0000, 0x22EC,0x0000,0x0000, +0x22ED,0x0000,0x0000, 0x22EE,0x0000,0x0000, 0x22EF,0x0000,0x0000, +0x22F0,0x0000,0x0000, 0x22F1,0x0000,0x0000, 0x22F2,0x0000,0x0000, +0x22F3,0x0000,0x0000, 0x22F4,0x0000,0x0000, 0x22F5,0x0000,0x0000, +0x22F6,0x0000,0x0000, 0x22F7,0x0000,0x0000, 0x22F8,0x0000,0x0000, +0x22F9,0x0000,0x0000, 0x22FA,0x0000,0x0000, 0x22FB,0x0000,0x0000, +0x22FC,0x0000,0x0000, 0x22FD,0x0000,0x0000, 0x22FE,0x0000,0x0000, +0x22FF,0x0000,0x0000, 0x2300,0x0000,0x0000, 0x2301,0x0000,0x0000, +0x2302,0x0000,0x0000, 0x2303,0x0000,0x0000, 0x2304,0x0000,0x0000, +0x2305,0x0000,0x0000, 0x2306,0x0000,0x0000, 0x2307,0x0000,0x0000, +0x2308,0x0000,0x0000, 0x2309,0x0000,0x0000, 0x230A,0x0000,0x0000, +0x230B,0x0000,0x0000, 0x230C,0x0000,0x0000, 0x230D,0x0000,0x0000, +0x230E,0x0000,0x0000, 0x230F,0x0000,0x0000, 0x2310,0x0000,0x0000, +0x2311,0x0000,0x0000, 0x2312,0x0000,0x0000, 0x2313,0x0000,0x0000, +0x2314,0x0000,0x0000, 0x2315,0x0000,0x0000, 0x2316,0x0000,0x0000, +0x2317,0x0000,0x0000, 0x2318,0x0000,0x0000, 0x2319,0x0000,0x0000, +0x231A,0x0000,0x0000, 0x231B,0x0000,0x0000, 0x231C,0x0000,0x0000, +0x231D,0x0000,0x0000, 0x231E,0x0000,0x0000, 0x231F,0x0000,0x0000, +0x2320,0x0000,0x0000, 0x2321,0x0000,0x0000, 0x2322,0x0000,0x0000, +0x2323,0x0000,0x0000, 0x2324,0x0000,0x0000, 0x2325,0x0000,0x0000, +0x2326,0x0000,0x0000, 0x2327,0x0000,0x0000, 0x2328,0x0000,0x0000, +0x2329,0x0000,0x0000, 0x232A,0x0000,0x0000, 0x232B,0x0000,0x0000, +0x232C,0x0000,0x0000, 0x232D,0x0000,0x0000, 0x232E,0x0000,0x0000, +0x232F,0x0000,0x0000, 0x2330,0x0000,0x0000, 0x2331,0x0000,0x0000, +0x2332,0x0000,0x0000, 0x2333,0x0000,0x0000, 0x2334,0x0000,0x0000, +0x2335,0x0000,0x0000, 0x2336,0x0000,0x0000, 0x2337,0x0000,0x0000, +0x2338,0x0000,0x0000, 0x2339,0x0000,0x0000, 0x233A,0x0000,0x0000, +0x233B,0x0000,0x0000, 0x233C,0x0000,0x0000, 0x233D,0x0000,0x0000, +0xFBC1,0xA48D,0x0000, 0xFBC1,0xA48E,0x0000, 0xFBC1,0xA48F,0x0000, +0x0BCE,0x0000,0x0000, 0x0BCF,0x0000,0x0000, 0x0BD0,0x0000,0x0000, +0x0BD1,0x0000,0x0000, 0x0BD2,0x0000,0x0000, 0x0BD3,0x0000,0x0000, +0x0BD4,0x0000,0x0000, 0x0BD5,0x0000,0x0000, 0x0BD6,0x0000,0x0000, +0x0BD7,0x0000,0x0000, 0x0BD8,0x0000,0x0000, 0x0BD9,0x0000,0x0000, +0x0BDA,0x0000,0x0000, 0x0BDB,0x0000,0x0000, 0x0BDC,0x0000,0x0000, +0x0BDD,0x0000,0x0000, 0x0BDE,0x0000,0x0000, 0x0BDF,0x0000,0x0000, +0x0BE0,0x0000,0x0000, 0x0BE1,0x0000,0x0000, 0x0BE2,0x0000,0x0000, +0x0BE3,0x0000,0x0000, 0x0BE4,0x0000,0x0000, 0x0BE5,0x0000,0x0000, +0x0BE6,0x0000,0x0000, 0x0BE7,0x0000,0x0000, 0x0BE8,0x0000,0x0000, +0x0BE9,0x0000,0x0000, 0x0BEA,0x0000,0x0000, 0x0BEB,0x0000,0x0000, +0x0BEC,0x0000,0x0000, 0x0BED,0x0000,0x0000, 0x0BEE,0x0000,0x0000, +0x0BEF,0x0000,0x0000, 0x0BF0,0x0000,0x0000, 0x0BF1,0x0000,0x0000, +0x0BF2,0x0000,0x0000, 0x0BF3,0x0000,0x0000, 0x0BF4,0x0000,0x0000, +0x0BF5,0x0000,0x0000, 0x0BF6,0x0000,0x0000, 0x0BF7,0x0000,0x0000, +0x0BF8,0x0000,0x0000, 0x0BF9,0x0000,0x0000, 0x0BFA,0x0000,0x0000, +0x0BFB,0x0000,0x0000, 0x0BFC,0x0000,0x0000, 0x0BFD,0x0000,0x0000, +0x0BFE,0x0000,0x0000, 0x0BFF,0x0000,0x0000, 0x0C00,0x0000,0x0000, +0x0C01,0x0000,0x0000, 0x0C02,0x0000,0x0000, 0x0C03,0x0000,0x0000, +0x0C04,0x0000,0x0000, 0xFBC1,0xA4C7,0x0000, 0xFBC1,0xA4C8,0x0000, +0xFBC1,0xA4C9,0x0000, 0xFBC1,0xA4CA,0x0000, 0xFBC1,0xA4CB,0x0000, +0xFBC1,0xA4CC,0x0000, 0xFBC1,0xA4CD,0x0000, 0xFBC1,0xA4CE,0x0000, +0xFBC1,0xA4CF,0x0000, 0xFBC1,0xA4D0,0x0000, 0xFBC1,0xA4D1,0x0000, +0xFBC1,0xA4D2,0x0000, 0xFBC1,0xA4D3,0x0000, 0xFBC1,0xA4D4,0x0000, +0xFBC1,0xA4D5,0x0000, 0xFBC1,0xA4D6,0x0000, 0xFBC1,0xA4D7,0x0000, +0xFBC1,0xA4D8,0x0000, 0xFBC1,0xA4D9,0x0000, 0xFBC1,0xA4DA,0x0000, +0xFBC1,0xA4DB,0x0000, 0xFBC1,0xA4DC,0x0000, 0xFBC1,0xA4DD,0x0000, +0xFBC1,0xA4DE,0x0000, 0xFBC1,0xA4DF,0x0000, 0xFBC1,0xA4E0,0x0000, +0xFBC1,0xA4E1,0x0000, 0xFBC1,0xA4E2,0x0000, 0xFBC1,0xA4E3,0x0000, +0xFBC1,0xA4E4,0x0000, 0xFBC1,0xA4E5,0x0000, 0xFBC1,0xA4E6,0x0000, +0xFBC1,0xA4E7,0x0000, 0xFBC1,0xA4E8,0x0000, 0xFBC1,0xA4E9,0x0000, +0xFBC1,0xA4EA,0x0000, 0xFBC1,0xA4EB,0x0000, 0xFBC1,0xA4EC,0x0000, +0xFBC1,0xA4ED,0x0000, 0xFBC1,0xA4EE,0x0000, 0xFBC1,0xA4EF,0x0000, +0xFBC1,0xA4F0,0x0000, 0xFBC1,0xA4F1,0x0000, 0xFBC1,0xA4F2,0x0000, +0xFBC1,0xA4F3,0x0000, 0xFBC1,0xA4F4,0x0000, 0xFBC1,0xA4F5,0x0000, +0xFBC1,0xA4F6,0x0000, 0xFBC1,0xA4F7,0x0000, 0xFBC1,0xA4F8,0x0000, +0xFBC1,0xA4F9,0x0000, 0xFBC1,0xA4FA,0x0000, 0xFBC1,0xA4FB,0x0000, +0xFBC1,0xA4FC,0x0000, 0xFBC1,0xA4FD,0x0000, 0xFBC1,0xA4FE,0x0000, +0xFBC1,0xA4FF,0x0000 }; + +uint16 page0F9data[]= { /* F900 (3 weights per char) */ +0xFB41,0x8C48,0x0000, 0xFB40,0xE6F4,0x0000, 0xFB41,0x8ECA,0x0000, +0xFB41,0x8CC8,0x0000, 0xFB40,0xEED1,0x0000, 0xFB40,0xCE32,0x0000, +0xFB40,0xD3E5,0x0000, 0xFB41,0x9F9C,0x0000, 0xFB41,0x9F9C,0x0000, +0xFB40,0xD951,0x0000, 0xFB41,0x91D1,0x0000, 0xFB40,0xD587,0x0000, +0xFB40,0xD948,0x0000, 0xFB40,0xE1F6,0x0000, 0xFB40,0xF669,0x0000, +0xFB40,0xFF85,0x0000, 0xFB41,0x863F,0x0000, 0xFB41,0x87BA,0x0000, +0xFB41,0x88F8,0x0000, 0xFB41,0x908F,0x0000, 0xFB40,0xEA02,0x0000, +0xFB40,0xED1B,0x0000, 0xFB40,0xF0D9,0x0000, 0xFB40,0xF3DE,0x0000, +0xFB41,0x843D,0x0000, 0xFB41,0x916A,0x0000, 0xFB41,0x99F1,0x0000, +0xFB40,0xCE82,0x0000, 0xFB40,0xD375,0x0000, 0xFB40,0xEB04,0x0000, +0xFB40,0xF21B,0x0000, 0xFB41,0x862D,0x0000, 0xFB41,0x9E1E,0x0000, +0xFB40,0xDD50,0x0000, 0xFB40,0xEFEB,0x0000, 0xFB41,0x85CD,0x0000, +0xFB41,0x8964,0x0000, 0xFB40,0xE2C9,0x0000, 0xFB41,0x81D8,0x0000, +0xFB41,0x881F,0x0000, 0xFB40,0xDECA,0x0000, 0xFB40,0xE717,0x0000, +0xFB40,0xED6A,0x0000, 0xFB40,0xF2FC,0x0000, 0xFB41,0x90CE,0x0000, +0xFB40,0xCF86,0x0000, 0xFB40,0xD1B7,0x0000, 0xFB40,0xD2DE,0x0000, +0xFB40,0xE4C4,0x0000, 0xFB40,0xEAD3,0x0000, 0xFB40,0xF210,0x0000, +0xFB40,0xF6E7,0x0000, 0xFB41,0x8001,0x0000, 0xFB41,0x8606,0x0000, +0xFB41,0x865C,0x0000, 0xFB41,0x8DEF,0x0000, 0xFB41,0x9732,0x0000, +0xFB41,0x9B6F,0x0000, 0xFB41,0x9DFA,0x0000, 0xFB40,0xF88C,0x0000, +0xFB40,0xF97F,0x0000, 0xFB40,0xFDA0,0x0000, 0xFB41,0x83C9,0x0000, +0xFB41,0x9304,0x0000, 0xFB41,0x9E7F,0x0000, 0xFB41,0x8AD6,0x0000, +0xFB40,0xD8DF,0x0000, 0xFB40,0xDF04,0x0000, 0xFB40,0xFC60,0x0000, +0xFB41,0x807E,0x0000, 0xFB40,0xF262,0x0000, 0xFB40,0xF8CA,0x0000, +0xFB41,0x8CC2,0x0000, 0xFB41,0x96F7,0x0000, 0xFB40,0xD8D8,0x0000, +0xFB40,0xDC62,0x0000, 0xFB40,0xEA13,0x0000, 0xFB40,0xEDDA,0x0000, +0xFB40,0xEF0F,0x0000, 0xFB40,0xFD2F,0x0000, 0xFB40,0xFE37,0x0000, +0xFB41,0x964B,0x0000, 0xFB40,0xD2D2,0x0000, 0xFB41,0x808B,0x0000, +0xFB40,0xD1DC,0x0000, 0xFB40,0xD1CC,0x0000, 0xFB40,0xFA1C,0x0000, +0xFB40,0xFDBE,0x0000, 0xFB41,0x83F1,0x0000, 0xFB41,0x9675,0x0000, +0xFB41,0x8B80,0x0000, 0xFB40,0xE2CF,0x0000, 0xFB40,0xEA02,0x0000, +0xFB41,0x8AFE,0x0000, 0xFB40,0xCE39,0x0000, 0xFB40,0xDBE7,0x0000, +0xFB40,0xE012,0x0000, 0xFB40,0xF387,0x0000, 0xFB40,0xF570,0x0000, +0xFB40,0xD317,0x0000, 0xFB40,0xF8FB,0x0000, 0xFB40,0xCFBF,0x0000, +0xFB40,0xDFA9,0x0000, 0xFB40,0xCE0D,0x0000, 0xFB40,0xECCC,0x0000, +0xFB40,0xE578,0x0000, 0xFB40,0xFD22,0x0000, 0xFB40,0xD3C3,0x0000, +0xFB40,0xD85E,0x0000, 0xFB40,0xF701,0x0000, 0xFB41,0x8449,0x0000, +0xFB41,0x8AAA,0x0000, 0xFB40,0xEBBA,0x0000, 0xFB41,0x8FB0,0x0000, +0xFB40,0xEC88,0x0000, 0xFB40,0xE2FE,0x0000, 0xFB41,0x82E5,0x0000, +0xFB40,0xE3A0,0x0000, 0xFB40,0xF565,0x0000, 0xFB40,0xCEAE,0x0000, +0xFB40,0xD169,0x0000, 0xFB40,0xD1C9,0x0000, 0xFB40,0xE881,0x0000, +0xFB40,0xFCE7,0x0000, 0xFB41,0x826F,0x0000, 0xFB41,0x8AD2,0x0000, +0xFB41,0x91CF,0x0000, 0xFB40,0xD2F5,0x0000, 0xFB40,0xD442,0x0000, +0xFB40,0xD973,0x0000, 0xFB40,0xDEEC,0x0000, 0xFB40,0xE5C5,0x0000, +0xFB40,0xEFFE,0x0000, 0xFB40,0xF92A,0x0000, 0xFB41,0x95AD,0x0000, +0xFB41,0x9A6A,0x0000, 0xFB41,0x9E97,0x0000, 0xFB41,0x9ECE,0x0000, +0xFB40,0xD29B,0x0000, 0xFB40,0xE6C6,0x0000, 0xFB40,0xEB77,0x0000, +0xFB41,0x8F62,0x0000, 0xFB40,0xDE74,0x0000, 0xFB40,0xE190,0x0000, +0xFB40,0xE200,0x0000, 0xFB40,0xE49A,0x0000, 0xFB40,0xEF23,0x0000, +0xFB40,0xF149,0x0000, 0xFB40,0xF489,0x0000, 0xFB40,0xF9CA,0x0000, +0xFB40,0xFDF4,0x0000, 0xFB41,0x806F,0x0000, 0xFB41,0x8F26,0x0000, +0xFB41,0x84EE,0x0000, 0xFB41,0x9023,0x0000, 0xFB41,0x934A,0x0000, +0xFB40,0xD217,0x0000, 0xFB40,0xD2A3,0x0000, 0xFB40,0xD4BD,0x0000, +0xFB40,0xF0C8,0x0000, 0xFB41,0x88C2,0x0000, 0xFB41,0x8AAA,0x0000, +0xFB40,0xDEC9,0x0000, 0xFB40,0xDFF5,0x0000, 0xFB40,0xE37B,0x0000, +0xFB40,0xEBAE,0x0000, 0xFB40,0xFC3E,0x0000, 0xFB40,0xF375,0x0000, +0xFB40,0xCEE4,0x0000, 0xFB40,0xD6F9,0x0000, 0xFB40,0xDBE7,0x0000, +0xFB40,0xDDBA,0x0000, 0xFB40,0xE01C,0x0000, 0xFB40,0xF3B2,0x0000, +0xFB40,0xF469,0x0000, 0xFB40,0xFF9A,0x0000, 0xFB41,0x8046,0x0000, +0xFB41,0x9234,0x0000, 0xFB41,0x96F6,0x0000, 0xFB41,0x9748,0x0000, +0xFB41,0x9818,0x0000, 0xFB40,0xCF8B,0x0000, 0xFB40,0xF9AE,0x0000, +0xFB41,0x91B4,0x0000, 0xFB41,0x96B8,0x0000, 0xFB40,0xE0E1,0x0000, +0xFB40,0xCE86,0x0000, 0xFB40,0xD0DA,0x0000, 0xFB40,0xDBEE,0x0000, +0xFB40,0xDC3F,0x0000, 0xFB40,0xE599,0x0000, 0xFB40,0xEA02,0x0000, +0xFB40,0xF1CE,0x0000, 0xFB40,0xF642,0x0000, 0xFB41,0x84FC,0x0000, +0xFB41,0x907C,0x0000, 0xFB41,0x9F8D,0x0000, 0xFB40,0xE688,0x0000, +0xFB41,0x962E,0x0000, 0xFB40,0xD289,0x0000, 0xFB40,0xE77B,0x0000, +0xFB40,0xE7F3,0x0000, 0xFB40,0xED41,0x0000, 0xFB40,0xEE9C,0x0000, +0xFB40,0xF409,0x0000, 0xFB40,0xF559,0x0000, 0xFB40,0xF86B,0x0000, +0xFB40,0xFD10,0x0000, 0xFB41,0x985E,0x0000, 0xFB40,0xD16D,0x0000, +0xFB40,0xE22E,0x0000, 0xFB41,0x9678,0x0000, 0xFB40,0xD02B,0x0000, +0xFB40,0xDD19,0x0000, 0xFB40,0xEDEA,0x0000, 0xFB41,0x8F2A,0x0000, +0xFB40,0xDF8B,0x0000, 0xFB40,0xE144,0x0000, 0xFB40,0xE817,0x0000, +0xFB40,0xF387,0x0000, 0xFB41,0x9686,0x0000, 0xFB40,0xD229,0x0000, +0xFB40,0xD40F,0x0000, 0xFB40,0xDC65,0x0000, 0xFB40,0xE613,0x0000, +0xFB40,0xE74E,0x0000, 0xFB40,0xE8A8,0x0000, 0xFB40,0xECE5,0x0000, +0xFB40,0xF406,0x0000, 0xFB40,0xF5E2,0x0000, 0xFB40,0xFF79,0x0000, +0xFB41,0x88CF,0x0000, 0xFB41,0x88E1,0x0000, 0xFB41,0x91CC,0x0000, +0xFB41,0x96E2,0x0000, 0xFB40,0xD33F,0x0000, 0xFB40,0xEEBA,0x0000, +0xFB40,0xD41D,0x0000, 0xFB40,0xF1D0,0x0000, 0xFB40,0xF498,0x0000, +0xFB41,0x85FA,0x0000, 0xFB41,0x96A3,0x0000, 0xFB41,0x9C57,0x0000, +0xFB41,0x9E9F,0x0000, 0xFB40,0xE797,0x0000, 0xFB40,0xEDCB,0x0000, +0xFB41,0x81E8,0x0000, 0xFB40,0xFACB,0x0000, 0xFB40,0xFB20,0x0000, +0xFB40,0xFC92,0x0000, 0xFB40,0xF2C0,0x0000, 0xFB40,0xF099,0x0000, +0xFB41,0x8B58,0x0000, 0xFB40,0xCEC0,0x0000, 0xFB41,0x8336,0x0000, +0xFB40,0xD23A,0x0000 }; + +uint16 page0FAdata[]= { /* FA00 (3 weights per char) */ +0xFB40,0xD207,0x0000, 0xFB40,0xDEA6,0x0000, 0xFB40,0xE2D3,0x0000, +0xFB40,0xFCD6,0x0000, 0xFB40,0xDB85,0x0000, 0xFB40,0xED1E,0x0000, +0xFB40,0xE6B4,0x0000, 0xFB41,0x8F3B,0x0000, 0xFB41,0x884C,0x0000, +0xFB41,0x964D,0x0000, 0xFB41,0x898B,0x0000, 0xFB40,0xDED3,0x0000, +0xFB40,0xD140,0x0000, 0xFB40,0xD5C0,0x0000, 0xFB41,0xFA0E,0x0000, +0xFB41,0xFA0F,0x0000, 0xFB40,0xD85A,0x0000, 0xFB41,0xFA11,0x0000, +0xFB40,0xE674,0x0000, 0xFB41,0xFA13,0x0000, 0xFB41,0xFA14,0x0000, +0xFB40,0xD1DE,0x0000, 0xFB40,0xF32A,0x0000, 0xFB40,0xF6CA,0x0000, +0xFB40,0xF93C,0x0000, 0xFB40,0xF95E,0x0000, 0xFB40,0xF965,0x0000, +0xFB40,0xF98F,0x0000, 0xFB41,0x9756,0x0000, 0xFB40,0xFCBE,0x0000, +0xFB40,0xFFBD,0x0000, 0xFB41,0xFA1F,0x0000, 0xFB41,0x8612,0x0000, +0xFB41,0xFA21,0x0000, 0xFB41,0x8AF8,0x0000, 0xFB41,0xFA23,0x0000, +0xFB41,0xFA24,0x0000, 0xFB41,0x9038,0x0000, 0xFB41,0x90FD,0x0000, +0xFB41,0xFA27,0x0000, 0xFB41,0xFA28,0x0000, 0xFB41,0xFA29,0x0000, +0xFB41,0x98EF,0x0000, 0xFB41,0x98FC,0x0000, 0xFB41,0x9928,0x0000, +0xFB41,0x9DB4,0x0000, 0xFBC1,0xFA2E,0x0000, 0xFBC1,0xFA2F,0x0000, +0xFB40,0xCFAE,0x0000, 0xFB40,0xD0E7,0x0000, 0xFB40,0xD14D,0x0000, +0xFB40,0xD2C9,0x0000, 0xFB40,0xD2E4,0x0000, 0xFB40,0xD351,0x0000, +0xFB40,0xD59D,0x0000, 0xFB40,0xD606,0x0000, 0xFB40,0xD668,0x0000, +0xFB40,0xD840,0x0000, 0xFB40,0xD8A8,0x0000, 0xFB40,0xDC64,0x0000, +0xFB40,0xDC6E,0x0000, 0xFB40,0xE094,0x0000, 0xFB40,0xE168,0x0000, +0xFB40,0xE18E,0x0000, 0xFB40,0xE1F2,0x0000, 0xFB40,0xE54F,0x0000, +0xFB40,0xE5E2,0x0000, 0xFB40,0xE691,0x0000, 0xFB40,0xE885,0x0000, +0xFB40,0xED77,0x0000, 0xFB40,0xEE1A,0x0000, 0xFB40,0xEF22,0x0000, +0xFB40,0xF16E,0x0000, 0xFB40,0xF22B,0x0000, 0xFB40,0xF422,0x0000, +0xFB40,0xF891,0x0000, 0xFB40,0xF93E,0x0000, 0xFB40,0xF949,0x0000, +0xFB40,0xF948,0x0000, 0xFB40,0xF950,0x0000, 0xFB40,0xF956,0x0000, +0xFB40,0xF95D,0x0000, 0xFB40,0xF98D,0x0000, 0xFB40,0xF98E,0x0000, +0xFB40,0xFA40,0x0000, 0xFB40,0xFA81,0x0000, 0xFB40,0xFBC0,0x0000, +0xFB40,0xFDF4,0x0000, 0xFB40,0xFE09,0x0000, 0xFB40,0xFE41,0x0000, +0xFB40,0xFF72,0x0000, 0xFB41,0x8005,0x0000, 0xFB41,0x81ED,0x0000, +0xFB41,0x8279,0x0000, 0xFB41,0x8279,0x0000, 0xFB41,0x8457,0x0000, +0xFB41,0x8910,0x0000, 0xFB41,0x8996,0x0000, 0xFB41,0x8B01,0x0000, +0xFB41,0x8B39,0x0000, 0xFB41,0x8CD3,0x0000, 0xFB41,0x8D08,0x0000, +0xFB41,0x8FB6,0x0000, 0xFB41,0x9038,0x0000, 0xFB41,0x96E3,0x0000, +0xFB41,0x97FF,0x0000, 0xFB41,0x983B,0x0000, 0xFBC1,0xFA6B,0x0000, +0xFBC1,0xFA6C,0x0000, 0xFBC1,0xFA6D,0x0000, 0xFBC1,0xFA6E,0x0000, +0xFBC1,0xFA6F,0x0000, 0xFBC1,0xFA70,0x0000, 0xFBC1,0xFA71,0x0000, +0xFBC1,0xFA72,0x0000, 0xFBC1,0xFA73,0x0000, 0xFBC1,0xFA74,0x0000, +0xFBC1,0xFA75,0x0000, 0xFBC1,0xFA76,0x0000, 0xFBC1,0xFA77,0x0000, +0xFBC1,0xFA78,0x0000, 0xFBC1,0xFA79,0x0000, 0xFBC1,0xFA7A,0x0000, +0xFBC1,0xFA7B,0x0000, 0xFBC1,0xFA7C,0x0000, 0xFBC1,0xFA7D,0x0000, +0xFBC1,0xFA7E,0x0000, 0xFBC1,0xFA7F,0x0000, 0xFBC1,0xFA80,0x0000, +0xFBC1,0xFA81,0x0000, 0xFBC1,0xFA82,0x0000, 0xFBC1,0xFA83,0x0000, +0xFBC1,0xFA84,0x0000, 0xFBC1,0xFA85,0x0000, 0xFBC1,0xFA86,0x0000, +0xFBC1,0xFA87,0x0000, 0xFBC1,0xFA88,0x0000, 0xFBC1,0xFA89,0x0000, +0xFBC1,0xFA8A,0x0000, 0xFBC1,0xFA8B,0x0000, 0xFBC1,0xFA8C,0x0000, +0xFBC1,0xFA8D,0x0000, 0xFBC1,0xFA8E,0x0000, 0xFBC1,0xFA8F,0x0000, +0xFBC1,0xFA90,0x0000, 0xFBC1,0xFA91,0x0000, 0xFBC1,0xFA92,0x0000, +0xFBC1,0xFA93,0x0000, 0xFBC1,0xFA94,0x0000, 0xFBC1,0xFA95,0x0000, +0xFBC1,0xFA96,0x0000, 0xFBC1,0xFA97,0x0000, 0xFBC1,0xFA98,0x0000, +0xFBC1,0xFA99,0x0000, 0xFBC1,0xFA9A,0x0000, 0xFBC1,0xFA9B,0x0000, +0xFBC1,0xFA9C,0x0000, 0xFBC1,0xFA9D,0x0000, 0xFBC1,0xFA9E,0x0000, +0xFBC1,0xFA9F,0x0000, 0xFBC1,0xFAA0,0x0000, 0xFBC1,0xFAA1,0x0000, +0xFBC1,0xFAA2,0x0000, 0xFBC1,0xFAA3,0x0000, 0xFBC1,0xFAA4,0x0000, +0xFBC1,0xFAA5,0x0000, 0xFBC1,0xFAA6,0x0000, 0xFBC1,0xFAA7,0x0000, +0xFBC1,0xFAA8,0x0000, 0xFBC1,0xFAA9,0x0000, 0xFBC1,0xFAAA,0x0000, +0xFBC1,0xFAAB,0x0000, 0xFBC1,0xFAAC,0x0000, 0xFBC1,0xFAAD,0x0000, +0xFBC1,0xFAAE,0x0000, 0xFBC1,0xFAAF,0x0000, 0xFBC1,0xFAB0,0x0000, +0xFBC1,0xFAB1,0x0000, 0xFBC1,0xFAB2,0x0000, 0xFBC1,0xFAB3,0x0000, +0xFBC1,0xFAB4,0x0000, 0xFBC1,0xFAB5,0x0000, 0xFBC1,0xFAB6,0x0000, +0xFBC1,0xFAB7,0x0000, 0xFBC1,0xFAB8,0x0000, 0xFBC1,0xFAB9,0x0000, +0xFBC1,0xFABA,0x0000, 0xFBC1,0xFABB,0x0000, 0xFBC1,0xFABC,0x0000, +0xFBC1,0xFABD,0x0000, 0xFBC1,0xFABE,0x0000, 0xFBC1,0xFABF,0x0000, +0xFBC1,0xFAC0,0x0000, 0xFBC1,0xFAC1,0x0000, 0xFBC1,0xFAC2,0x0000, +0xFBC1,0xFAC3,0x0000, 0xFBC1,0xFAC4,0x0000, 0xFBC1,0xFAC5,0x0000, +0xFBC1,0xFAC6,0x0000, 0xFBC1,0xFAC7,0x0000, 0xFBC1,0xFAC8,0x0000, +0xFBC1,0xFAC9,0x0000, 0xFBC1,0xFACA,0x0000, 0xFBC1,0xFACB,0x0000, +0xFBC1,0xFACC,0x0000, 0xFBC1,0xFACD,0x0000, 0xFBC1,0xFACE,0x0000, +0xFBC1,0xFACF,0x0000, 0xFBC1,0xFAD0,0x0000, 0xFBC1,0xFAD1,0x0000, +0xFBC1,0xFAD2,0x0000, 0xFBC1,0xFAD3,0x0000, 0xFBC1,0xFAD4,0x0000, +0xFBC1,0xFAD5,0x0000, 0xFBC1,0xFAD6,0x0000, 0xFBC1,0xFAD7,0x0000, +0xFBC1,0xFAD8,0x0000, 0xFBC1,0xFAD9,0x0000, 0xFBC1,0xFADA,0x0000, +0xFBC1,0xFADB,0x0000, 0xFBC1,0xFADC,0x0000, 0xFBC1,0xFADD,0x0000, +0xFBC1,0xFADE,0x0000, 0xFBC1,0xFADF,0x0000, 0xFBC1,0xFAE0,0x0000, +0xFBC1,0xFAE1,0x0000, 0xFBC1,0xFAE2,0x0000, 0xFBC1,0xFAE3,0x0000, +0xFBC1,0xFAE4,0x0000, 0xFBC1,0xFAE5,0x0000, 0xFBC1,0xFAE6,0x0000, +0xFBC1,0xFAE7,0x0000, 0xFBC1,0xFAE8,0x0000, 0xFBC1,0xFAE9,0x0000, +0xFBC1,0xFAEA,0x0000, 0xFBC1,0xFAEB,0x0000, 0xFBC1,0xFAEC,0x0000, +0xFBC1,0xFAED,0x0000, 0xFBC1,0xFAEE,0x0000, 0xFBC1,0xFAEF,0x0000, +0xFBC1,0xFAF0,0x0000, 0xFBC1,0xFAF1,0x0000, 0xFBC1,0xFAF2,0x0000, +0xFBC1,0xFAF3,0x0000, 0xFBC1,0xFAF4,0x0000, 0xFBC1,0xFAF5,0x0000, +0xFBC1,0xFAF6,0x0000, 0xFBC1,0xFAF7,0x0000, 0xFBC1,0xFAF8,0x0000, +0xFBC1,0xFAF9,0x0000, 0xFBC1,0xFAFA,0x0000, 0xFBC1,0xFAFB,0x0000, +0xFBC1,0xFAFC,0x0000, 0xFBC1,0xFAFD,0x0000, 0xFBC1,0xFAFE,0x0000, +0xFBC1,0xFAFF,0x0000 }; + +uint16 page0FBdata[]= { /* FB00 (4 weights per char) */ +0x0EB9,0x0EB9,0x0000,0x0000, 0x0EB9,0x0EFB,0x0000,0x0000, +0x0EB9,0x0F2E,0x0000,0x0000, 0x0EB9,0x0EB9,0x0EFB,0x0000, +0x0EB9,0x0EB9,0x0F2E,0x0000, 0x0FEA,0x1002,0x0000,0x0000, +0x0FEA,0x1002,0x0000,0x0000, 0xFBC1,0xFB07,0x0000,0x0000, +0xFBC1,0xFB08,0x0000,0x0000, 0xFBC1,0xFB09,0x0000,0x0000, +0xFBC1,0xFB0A,0x0000,0x0000, 0xFBC1,0xFB0B,0x0000,0x0000, +0xFBC1,0xFB0C,0x0000,0x0000, 0xFBC1,0xFB0D,0x0000,0x0000, +0xFBC1,0xFB0E,0x0000,0x0000, 0xFBC1,0xFB0F,0x0000,0x0000, +0xFBC1,0xFB10,0x0000,0x0000, 0xFBC1,0xFB11,0x0000,0x0000, +0xFBC1,0xFB12,0x0000,0x0000, 0x131D,0x131F,0x0000,0x0000, +0x131D,0x130E,0x0000,0x0000, 0x131D,0x1314,0x0000,0x0000, +0x1327,0x131F,0x0000,0x0000, 0x131D,0x1316,0x0000,0x0000, +0xFBC1,0xFB18,0x0000,0x0000, 0xFBC1,0xFB19,0x0000,0x0000, +0xFBC1,0xFB1A,0x0000,0x0000, 0xFBC1,0xFB1B,0x0000,0x0000, +0xFBC1,0xFB1C,0x0000,0x0000, 0x133A,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000, 0x133A,0x133A,0x0000,0x0000, +0x1340,0x0000,0x0000,0x0000, 0x1331,0x0000,0x0000,0x0000, +0x1334,0x0000,0x0000,0x0000, 0x1335,0x0000,0x0000,0x0000, +0x133B,0x0000,0x0000,0x0000, 0x133C,0x0000,0x0000,0x0000, +0x133D,0x0000,0x0000,0x0000, 0x1344,0x0000,0x0000,0x0000, +0x1346,0x0000,0x0000,0x0000, 0x0428,0x0000,0x0000,0x0000, +0x1345,0x0000,0x0000,0x0000, 0x1345,0x0000,0x0000,0x0000, +0x1345,0x0000,0x0000,0x0000, 0x1345,0x0000,0x0000,0x0000, +0x1331,0x0000,0x0000,0x0000, 0x1331,0x0000,0x0000,0x0000, +0x1331,0x0000,0x0000,0x0000, 0x1332,0x0000,0x0000,0x0000, +0x1333,0x0000,0x0000,0x0000, 0x1334,0x0000,0x0000,0x0000, +0x1335,0x0000,0x0000,0x0000, 0x1336,0x0000,0x0000,0x0000, +0x1337,0x0000,0x0000,0x0000, 0xFBC1,0xFB37,0x0000,0x0000, +0x1339,0x0000,0x0000,0x0000, 0x133A,0x0000,0x0000,0x0000, +0x133B,0x0000,0x0000,0x0000, 0x133B,0x0000,0x0000,0x0000, +0x133C,0x0000,0x0000,0x0000, 0xFBC1,0xFB3D,0x0000,0x0000, +0x133D,0x0000,0x0000,0x0000, 0xFBC1,0xFB3F,0x0000,0x0000, +0x133E,0x0000,0x0000,0x0000, 0x133F,0x0000,0x0000,0x0000, +0xFBC1,0xFB42,0x0000,0x0000, 0x1341,0x0000,0x0000,0x0000, +0x1341,0x0000,0x0000,0x0000, 0xFBC1,0xFB45,0x0000,0x0000, +0x1342,0x0000,0x0000,0x0000, 0x1343,0x0000,0x0000,0x0000, +0x1344,0x0000,0x0000,0x0000, 0x1345,0x0000,0x0000,0x0000, +0x1346,0x0000,0x0000,0x0000, 0x1336,0x0000,0x0000,0x0000, +0x1332,0x0000,0x0000,0x0000, 0x133B,0x0000,0x0000,0x0000, +0x1341,0x0000,0x0000,0x0000, 0x1331,0x133C,0x0000,0x0000, +0x134B,0x0000,0x0000,0x0000, 0x134B,0x0000,0x0000,0x0000, +0x1353,0x0000,0x0000,0x0000, 0x1353,0x0000,0x0000,0x0000, +0x1353,0x0000,0x0000,0x0000, 0x1353,0x0000,0x0000,0x0000, +0x1354,0x0000,0x0000,0x0000, 0x1354,0x0000,0x0000,0x0000, +0x1354,0x0000,0x0000,0x0000, 0x1354,0x0000,0x0000,0x0000, +0x1355,0x0000,0x0000,0x0000, 0x1355,0x0000,0x0000,0x0000, +0x1355,0x0000,0x0000,0x0000, 0x1355,0x0000,0x0000,0x0000, +0x135A,0x0000,0x0000,0x0000, 0x135A,0x0000,0x0000,0x0000, +0x135A,0x0000,0x0000,0x0000, 0x135A,0x0000,0x0000,0x0000, +0x135D,0x0000,0x0000,0x0000, 0x135D,0x0000,0x0000,0x0000, +0x135D,0x0000,0x0000,0x0000, 0x135D,0x0000,0x0000,0x0000, +0x1359,0x0000,0x0000,0x0000, 0x1359,0x0000,0x0000,0x0000, +0x1359,0x0000,0x0000,0x0000, 0x1359,0x0000,0x0000,0x0000, +0x1397,0x0000,0x0000,0x0000, 0x1397,0x0000,0x0000,0x0000, +0x1397,0x0000,0x0000,0x0000, 0x1397,0x0000,0x0000,0x0000, +0x1399,0x0000,0x0000,0x0000, 0x1399,0x0000,0x0000,0x0000, +0x1399,0x0000,0x0000,0x0000, 0x1399,0x0000,0x0000,0x0000, +0x1360,0x0000,0x0000,0x0000, 0x1360,0x0000,0x0000,0x0000, +0x1360,0x0000,0x0000,0x0000, 0x1360,0x0000,0x0000,0x0000, +0x135F,0x0000,0x0000,0x0000, 0x135F,0x0000,0x0000,0x0000, +0x135F,0x0000,0x0000,0x0000, 0x135F,0x0000,0x0000,0x0000, +0x1361,0x0000,0x0000,0x0000, 0x1361,0x0000,0x0000,0x0000, +0x1361,0x0000,0x0000,0x0000, 0x1361,0x0000,0x0000,0x0000, +0x1363,0x0000,0x0000,0x0000, 0x1363,0x0000,0x0000,0x0000, +0x1363,0x0000,0x0000,0x0000, 0x1363,0x0000,0x0000,0x0000, +0x1370,0x0000,0x0000,0x0000, 0x1370,0x0000,0x0000,0x0000, +0x136F,0x0000,0x0000,0x0000, 0x136F,0x0000,0x0000,0x0000, +0x1371,0x0000,0x0000,0x0000, 0x1371,0x0000,0x0000,0x0000, +0x136B,0x0000,0x0000,0x0000, 0x136B,0x0000,0x0000,0x0000, +0x137E,0x0000,0x0000,0x0000, 0x137E,0x0000,0x0000,0x0000, +0x1377,0x0000,0x0000,0x0000, 0x1377,0x0000,0x0000,0x0000, +0x139F,0x0000,0x0000,0x0000, 0x139F,0x0000,0x0000,0x0000, +0x139F,0x0000,0x0000,0x0000, 0x139F,0x0000,0x0000,0x0000, +0x13A5,0x0000,0x0000,0x0000, 0x13A5,0x0000,0x0000,0x0000, +0x13A5,0x0000,0x0000,0x0000, 0x13A5,0x0000,0x0000,0x0000, +0x13A9,0x0000,0x0000,0x0000, 0x13A9,0x0000,0x0000,0x0000, +0x13A9,0x0000,0x0000,0x0000, 0x13A9,0x0000,0x0000,0x0000, +0x13A7,0x0000,0x0000,0x0000, 0x13A7,0x0000,0x0000,0x0000, +0x13A7,0x0000,0x0000,0x0000, 0x13A7,0x0000,0x0000,0x0000, +0x13B2,0x0000,0x0000,0x0000, 0x13B2,0x0000,0x0000,0x0000, +0x13B3,0x0000,0x0000,0x0000, 0x13B3,0x0000,0x0000,0x0000, +0x13B3,0x0000,0x0000,0x0000, 0x13B3,0x0000,0x0000,0x0000, +0x13BC,0x0000,0x0000,0x0000, 0x13BC,0x0000,0x0000,0x0000, +0x13B9,0x0000,0x0000,0x0000, 0x13B9,0x0000,0x0000,0x0000, +0x13B9,0x0000,0x0000,0x0000, 0x13B9,0x0000,0x0000,0x0000, +0x13B8,0x0000,0x0000,0x0000, 0x13B8,0x0000,0x0000,0x0000, +0x13B8,0x0000,0x0000,0x0000, 0x13B8,0x0000,0x0000,0x0000, +0x13CE,0x0000,0x0000,0x0000, 0x13CE,0x0000,0x0000,0x0000, +0x13CE,0x0000,0x0000,0x0000, 0x13CE,0x0000,0x0000,0x0000, +0xFBC1,0xFBB2,0x0000,0x0000, 0xFBC1,0xFBB3,0x0000,0x0000, +0xFBC1,0xFBB4,0x0000,0x0000, 0xFBC1,0xFBB5,0x0000,0x0000, +0xFBC1,0xFBB6,0x0000,0x0000, 0xFBC1,0xFBB7,0x0000,0x0000, +0xFBC1,0xFBB8,0x0000,0x0000, 0xFBC1,0xFBB9,0x0000,0x0000, +0xFBC1,0xFBBA,0x0000,0x0000, 0xFBC1,0xFBBB,0x0000,0x0000, +0xFBC1,0xFBBC,0x0000,0x0000, 0xFBC1,0xFBBD,0x0000,0x0000, +0xFBC1,0xFBBE,0x0000,0x0000, 0xFBC1,0xFBBF,0x0000,0x0000, +0xFBC1,0xFBC0,0x0000,0x0000, 0xFBC1,0xFBC1,0x0000,0x0000, +0xFBC1,0xFBC2,0x0000,0x0000, 0xFBC1,0xFBC3,0x0000,0x0000, +0xFBC1,0xFBC4,0x0000,0x0000, 0xFBC1,0xFBC5,0x0000,0x0000, +0xFBC1,0xFBC6,0x0000,0x0000, 0xFBC1,0xFBC7,0x0000,0x0000, +0xFBC1,0xFBC8,0x0000,0x0000, 0xFBC1,0xFBC9,0x0000,0x0000, +0xFBC1,0xFBCA,0x0000,0x0000, 0xFBC1,0xFBCB,0x0000,0x0000, +0xFBC1,0xFBCC,0x0000,0x0000, 0xFBC1,0xFBCD,0x0000,0x0000, +0xFBC1,0xFBCE,0x0000,0x0000, 0xFBC1,0xFBCF,0x0000,0x0000, +0xFBC1,0xFBD0,0x0000,0x0000, 0xFBC1,0xFBD1,0x0000,0x0000, +0xFBC1,0xFBD2,0x0000,0x0000, 0x13A3,0x0000,0x0000,0x0000, +0x13A3,0x0000,0x0000,0x0000, 0x13A3,0x0000,0x0000,0x0000, +0x13A3,0x0000,0x0000,0x0000, 0x13C1,0x0000,0x0000,0x0000, +0x13C1,0x0000,0x0000,0x0000, 0x13C0,0x0000,0x0000,0x0000, +0x13C0,0x0000,0x0000,0x0000, 0x13C2,0x0000,0x0000,0x0000, +0x13C2,0x0000,0x0000,0x0000, 0x13C1,0x1347,0x0000,0x0000, +0x13C5,0x0000,0x0000,0x0000, 0x13C5,0x0000,0x0000,0x0000, +0x13BF,0x0000,0x0000,0x0000, 0x13BF,0x0000,0x0000,0x0000, +0x13C3,0x0000,0x0000,0x0000, 0x13C3,0x0000,0x0000,0x0000, +0x13CC,0x0000,0x0000,0x0000, 0x13CC,0x0000,0x0000,0x0000, +0x13CC,0x0000,0x0000,0x0000, 0x13CC,0x0000,0x0000,0x0000, +0x13C7,0x0000,0x0000,0x0000, 0x13C7,0x0000,0x0000,0x0000, +0x134F,0x1350,0x0000,0x0000, 0x134F,0x1350,0x0000,0x0000, +0x134F,0x13BC,0x0000,0x0000, 0x134F,0x13BC,0x0000,0x0000, +0x134F,0x13BD,0x0000,0x0000, 0x134F,0x13BD,0x0000,0x0000, +0x134F,0x13C1,0x0000,0x0000, 0x134F,0x13C1,0x0000,0x0000, +0x134F,0x13C0,0x0000,0x0000, 0x134F,0x13C0,0x0000,0x0000, +0x134F,0x13C2,0x0000,0x0000, 0x134F,0x13C2,0x0000,0x0000, +0x134F,0x13CC,0x0000,0x0000, 0x134F,0x13CC,0x0000,0x0000, +0x134F,0x13CC,0x0000,0x0000, 0x134F,0x13C7,0x0000,0x0000, +0x134F,0x13C7,0x0000,0x0000, 0x134F,0x13C7,0x0000,0x0000, +0x13C9,0x0000,0x0000,0x0000, 0x13C9,0x0000,0x0000,0x0000, +0x13C9,0x0000,0x0000,0x0000, 0x13C9,0x0000,0x0000,0x0000 +}; + +uint16 page0FCdata[]= { /* FC00 (3 weights per char) */ +0x134F,0x135E,0x0000, 0x134F,0x1364,0x0000, 0x134F,0x13B0,0x0000, +0x134F,0x13C7,0x0000, 0x134F,0x13C8,0x0000, 0x1352,0x135E,0x0000, +0x1352,0x1364,0x0000, 0x1352,0x1365,0x0000, 0x1352,0x13B0,0x0000, +0x1352,0x13C7,0x0000, 0x1352,0x13C8,0x0000, 0x1357,0x135E,0x0000, +0x1357,0x1364,0x0000, 0x1357,0x1365,0x0000, 0x1357,0x13B0,0x0000, +0x1357,0x13C7,0x0000, 0x1357,0x13C8,0x0000, 0x1358,0x135E,0x0000, +0x1358,0x13B0,0x0000, 0x1358,0x13C7,0x0000, 0x1358,0x13C8,0x0000, +0x135E,0x1364,0x0000, 0x135E,0x13B0,0x0000, 0x1364,0x135E,0x0000, +0x1364,0x13B0,0x0000, 0x1365,0x135E,0x0000, 0x1365,0x1364,0x0000, +0x1365,0x13B0,0x0000, 0x1381,0x135E,0x0000, 0x1381,0x1364,0x0000, +0x1381,0x1365,0x0000, 0x1381,0x13B0,0x0000, 0x1387,0x1364,0x0000, +0x1387,0x13B0,0x0000, 0x1388,0x135E,0x0000, 0x1388,0x1364,0x0000, +0x1388,0x1365,0x0000, 0x1388,0x13B0,0x0000, 0x138C,0x1364,0x0000, +0x138C,0x13B0,0x0000, 0x138D,0x13B0,0x0000, 0x138F,0x135E,0x0000, +0x138F,0x13B0,0x0000, 0x1390,0x135E,0x0000, 0x1390,0x13B0,0x0000, +0x1393,0x135E,0x0000, 0x1393,0x1364,0x0000, 0x1393,0x1365,0x0000, +0x1393,0x13B0,0x0000, 0x1393,0x13C7,0x0000, 0x1393,0x13C8,0x0000, +0x139B,0x1364,0x0000, 0x139B,0x13B0,0x0000, 0x139B,0x13C7,0x0000, +0x139B,0x13C8,0x0000, 0x139E,0x1350,0x0000, 0x139E,0x135E,0x0000, +0x139E,0x1364,0x0000, 0x139E,0x1365,0x0000, 0x139E,0x13AB,0x0000, +0x139E,0x13B0,0x0000, 0x139E,0x13C7,0x0000, 0x139E,0x13C8,0x0000, +0x13AB,0x135E,0x0000, 0x13AB,0x1364,0x0000, 0x13AB,0x1365,0x0000, +0x13AB,0x13B0,0x0000, 0x13AB,0x13C7,0x0000, 0x13AB,0x13C8,0x0000, +0x13B0,0x135E,0x0000, 0x13B0,0x1364,0x0000, 0x13B0,0x1365,0x0000, +0x13B0,0x13B0,0x0000, 0x13B0,0x13C7,0x0000, 0x13B0,0x13C8,0x0000, +0x13B1,0x135E,0x0000, 0x13B1,0x1364,0x0000, 0x13B1,0x1365,0x0000, +0x13B1,0x13B0,0x0000, 0x13B1,0x13C7,0x0000, 0x13B1,0x13C8,0x0000, +0x13B7,0x135E,0x0000, 0x13B7,0x13B0,0x0000, 0x13B7,0x13C7,0x0000, +0x13B7,0x13C8,0x0000, 0x13C8,0x135E,0x0000, 0x13C8,0x1364,0x0000, +0x13C8,0x1365,0x0000, 0x13C8,0x13B0,0x0000, 0x13C8,0x13C7,0x0000, +0x13C8,0x13C8,0x0000, 0x136A,0x0000,0x0000, 0x1375,0x0000,0x0000, +0x13C7,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x134F,0x1375,0x0000, 0x134F,0x1376,0x0000, +0x134F,0x13B0,0x0000, 0x134F,0x13B1,0x0000, 0x134F,0x13C7,0x0000, +0x134F,0x13C8,0x0000, 0x1352,0x1375,0x0000, 0x1352,0x1376,0x0000, +0x1352,0x13B0,0x0000, 0x1352,0x13B1,0x0000, 0x1352,0x13C7,0x0000, +0x1352,0x13C8,0x0000, 0x1357,0x1375,0x0000, 0x1357,0x1376,0x0000, +0x1357,0x13B0,0x0000, 0x1357,0x13B1,0x0000, 0x1357,0x13C7,0x0000, +0x1357,0x13C8,0x0000, 0x1358,0x1375,0x0000, 0x1358,0x1376,0x0000, +0x1358,0x13B0,0x0000, 0x1358,0x13B1,0x0000, 0x1358,0x13C7,0x0000, +0x1358,0x13C8,0x0000, 0x1393,0x13C7,0x0000, 0x1393,0x13C8,0x0000, +0x139B,0x13C7,0x0000, 0x139B,0x13C8,0x0000, 0x139E,0x1350,0x0000, +0x139E,0x13AB,0x0000, 0x139E,0x13B0,0x0000, 0x139E,0x13C7,0x0000, +0x139E,0x13C8,0x0000, 0x13AB,0x13B0,0x0000, 0x13AB,0x13C7,0x0000, +0x13AB,0x13C8,0x0000, 0x13B0,0x1350,0x0000, 0x13B0,0x13B0,0x0000, +0x13B1,0x1375,0x0000, 0x13B1,0x1376,0x0000, 0x13B1,0x13B0,0x0000, +0x13B1,0x13B1,0x0000, 0x13B1,0x13C7,0x0000, 0x13B1,0x13C8,0x0000, +0x13C7,0x0000,0x0000, 0x13C8,0x1375,0x0000, 0x13C8,0x1376,0x0000, +0x13C8,0x13B0,0x0000, 0x13C8,0x13B1,0x0000, 0x13C8,0x13C7,0x0000, +0x13C8,0x13C8,0x0000, 0x134F,0x135E,0x0000, 0x134F,0x1364,0x0000, +0x134F,0x1365,0x0000, 0x134F,0x13B0,0x0000, 0x134F,0x13B7,0x0000, +0x1352,0x135E,0x0000, 0x1352,0x1364,0x0000, 0x1352,0x1365,0x0000, +0x1352,0x13B0,0x0000, 0x1352,0x13B7,0x0000, 0x1357,0x135E,0x0000, +0x1357,0x1364,0x0000, 0x1357,0x1365,0x0000, 0x1357,0x13B0,0x0000, +0x1357,0x13B7,0x0000, 0x1358,0x13B0,0x0000, 0x135E,0x1364,0x0000, +0x135E,0x13B0,0x0000, 0x1364,0x135E,0x0000, 0x1364,0x13B0,0x0000, +0x1365,0x135E,0x0000, 0x1365,0x13B0,0x0000, 0x1381,0x135E,0x0000, +0x1381,0x1364,0x0000, 0x1381,0x1365,0x0000, 0x1381,0x13B0,0x0000, +0x1387,0x1364,0x0000, 0x1387,0x1365,0x0000, 0x1387,0x13B0,0x0000, +0x1388,0x135E,0x0000, 0x1388,0x1364,0x0000, 0x1388,0x1365,0x0000, +0x1388,0x13B0,0x0000, 0x138C,0x1364,0x0000, 0x138D,0x13B0,0x0000, +0x138F,0x135E,0x0000, 0x138F,0x13B0,0x0000, 0x1390,0x135E,0x0000, +0x1390,0x13B0,0x0000, 0x1393,0x135E,0x0000, 0x1393,0x1364,0x0000, +0x1393,0x1365,0x0000, 0x1393,0x13B0,0x0000, 0x139B,0x1364,0x0000, +0x139B,0x13B0,0x0000, 0x139E,0x135E,0x0000, 0x139E,0x1364,0x0000, +0x139E,0x1365,0x0000, 0x139E,0x13AB,0x0000, 0x139E,0x13B0,0x0000, +0x13AB,0x135E,0x0000, 0x13AB,0x1364,0x0000, 0x13AB,0x1365,0x0000, +0x13AB,0x13B0,0x0000, 0x13AB,0x13B7,0x0000, 0x13B0,0x135E,0x0000, +0x13B0,0x1364,0x0000, 0x13B0,0x1365,0x0000, 0x13B0,0x13B0,0x0000, +0x13B1,0x135E,0x0000, 0x13B1,0x1364,0x0000, 0x13B1,0x1365,0x0000, +0x13B1,0x13B0,0x0000, 0x13B1,0x13B7,0x0000, 0x13B7,0x135E,0x0000, +0x13B7,0x13B0,0x0000, 0x13B7,0x0000,0x0000, 0x13C8,0x135E,0x0000, +0x13C8,0x1364,0x0000, 0x13C8,0x1365,0x0000, 0x13C8,0x13B0,0x0000, +0x13C8,0x13B7,0x0000, 0x134F,0x13B0,0x0000, 0x134F,0x13B7,0x0000, +0x1352,0x13B0,0x0000, 0x1352,0x13B7,0x0000, 0x1357,0x13B0,0x0000, +0x1357,0x13B7,0x0000, 0x1358,0x13B0,0x0000, 0x1358,0x13B7,0x0000, +0x1381,0x13B0,0x0000, 0x1381,0x13B7,0x0000, 0x1382,0x13B0,0x0000, +0x1382,0x13B7,0x0000, 0x139E,0x13AB,0x0000, 0x139E,0x13B0,0x0000, +0x13AB,0x13B0,0x0000, 0x13B1,0x13B0,0x0000, 0x13B1,0x13B7,0x0000, +0x13C8,0x13B0,0x0000, 0x13C8,0x13B7,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x138C,0x13C7,0x0000, +0x138C,0x13C8,0x0000, 0x138F,0x13C7,0x0000, 0x138F,0x13C8,0x0000, +0x1390,0x13C7,0x0000, 0x1390,0x13C8,0x0000, 0x1381,0x13C7,0x0000, +0x1381,0x13C8,0x0000, 0x1382,0x13C7,0x0000, 0x1382,0x13C8,0x0000, +0x1364,0x13C7,0x0000 }; + +uint16 page0FDdata[]= { /* FD00 (9 weights per char) */ +0x1364,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x135E,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x135E,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1365,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1365,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1387,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1387,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1388,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1388,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x135E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x1365,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x1375,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1381,0x1375,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1387,0x1375,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1388,0x1375,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x138C,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x138C,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x138F,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x138F,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1390,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1390,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1381,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1381,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1364,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1364,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x135E,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x135E,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1365,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1365,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1387,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1387,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1388,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1388,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x135E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x1365,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x1375,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1381,0x1375,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1387,0x1375,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1388,0x1375,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x135E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x1365,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1381,0x13B7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x13B7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x138C,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1381,0x135E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1381,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1381,0x1365,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x135E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x1365,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x138C,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x138D,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1350,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1350,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x02C0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x02C1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFD40,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFD41,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFD42,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFD43,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFD44,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFD45,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFD46,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFD47,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFD48,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFD49,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFD4A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFD4B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFD4C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFD4D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFD4E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFD4F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1357,0x135E,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1357,0x1364,0x135E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1357,0x1364,0x135E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1357,0x1364,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1357,0x1365,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1357,0x13B0,0x135E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1357,0x13B0,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1357,0x13B0,0x1365,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x135E,0x13B0,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x135E,0x13B0,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1364,0x13B0,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1364,0x13B0,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1381,0x1364,0x135E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1381,0x135E,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1381,0x135E,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1381,0x13B0,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1381,0x13B0,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1381,0x13B0,0x135E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1381,0x13B0,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1381,0x13B0,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1387,0x1364,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1387,0x1364,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1387,0x13B0,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x1364,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x1364,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x135E,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x13B0,0x1365,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x13B0,0x1365,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x13B0,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x13B0,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1388,0x1364,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1388,0x1365,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1388,0x1365,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x138C,0x13B0,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x138C,0x13B0,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x138C,0x13B0,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x138C,0x13B0,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x138F,0x135E,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x138F,0x13B0,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x138F,0x13B0,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x138F,0x13B0,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1390,0x13B0,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1390,0x13B0,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1390,0x13B0,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1393,0x1365,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1393,0x1365,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x139B,0x13B0,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x139B,0x13B0,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13AB,0x1364,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13AB,0x1364,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13AB,0x1364,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13AB,0x135E,0x135E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13AB,0x135E,0x135E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13AB,0x1365,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13AB,0x1365,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13AB,0x13B0,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13AB,0x13B0,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B0,0x1364,0x135E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B0,0x1364,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B0,0x1364,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B0,0x135E,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B0,0x135E,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B0,0x1365,0x135E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B0,0x1365,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFD90,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFD91,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B0,0x135E,0x1365,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B7,0x13B0,0x135E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B7,0x13B0,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B1,0x1364,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B1,0x1364,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B1,0x135E,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B1,0x135E,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B1,0x135E,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B1,0x13B0,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B1,0x13B0,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13C8,0x13B0,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13C8,0x13B0,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1352,0x1365,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1357,0x135E,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1357,0x135E,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1357,0x1365,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1357,0x1365,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1357,0x13B0,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1357,0x13B0,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x135E,0x13B0,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x135E,0x1364,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x135E,0x13B0,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1381,0x1365,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1387,0x1364,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1382,0x1364,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1388,0x1364,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13AB,0x135E,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13AB,0x13B0,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13C8,0x1364,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13C8,0x135E,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13C8,0x13B0,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B0,0x13B0,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x139B,0x13B0,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B1,0x1364,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x139B,0x13B0,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13AB,0x1364,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x138F,0x13B0,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x139E,0x13B0,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B1,0x135E,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B0,0x1365,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13AB,0x135E,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x139E,0x13B0,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13AB,0x135E,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B1,0x135E,0x1364,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x135E,0x1364,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1364,0x135E,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B0,0x135E,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1393,0x13B0,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1352,0x1364,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x139E,0x13B0,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x138F,0x135E,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1387,0x13B0,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1381,0x1365,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B1,0x135E,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDC8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDC9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDCA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDCB,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDCC,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDCD,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDCE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDCF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDD0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDD1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDD2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDD3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDD4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDD5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDD6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDD7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDD8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDD9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDDA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDDB,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDDC,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDDD,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDDE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDDF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDE0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDE1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDE2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDE3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDE4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDE5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDE6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDE7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDE8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDE9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDEA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDEB,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDEC,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDED,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDEE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDEF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1387,0x13AB,0x13CE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x139B,0x13AB,0x13CE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1350,0x13AB,0x13AB,0x13B7,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1350,0x139E,0x1352,0x1375,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13B0,0x1364,0x13B0,0x1369,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1387,0x13AB,0x138F,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1375,0x1381,0x13BD,0x13AB,0x0000,0x0000,0x0000,0x0000,0x0000, +0x138F,0x13AB,0x13C8,0x13B7,0x0000,0x0000,0x0000,0x0000,0x0000, +0x13BD,0x1381,0x13AB,0x13B0,0x0000,0x0000,0x0000,0x0000,0x0000, +0x1387,0x13AB,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDFA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x135E,0x13AB,0x0209,0x135E,0x13AB,0x1350,0x13AB,0x13B7,0x0000, +0x1375,0x13C9,0x1350,0x13AB,0x0000,0x0000,0x0000,0x0000,0x0000, +0x034F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDFE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0xFBC1,0xFDFF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 +}; + +uint16 page0FEdata[]= { /* FE00 (3 weights per char) */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0xFBC1,0xFE10,0x0000, 0xFBC1,0xFE11,0x0000, +0xFBC1,0xFE12,0x0000, 0xFBC1,0xFE13,0x0000, 0xFBC1,0xFE14,0x0000, +0xFBC1,0xFE15,0x0000, 0xFBC1,0xFE16,0x0000, 0xFBC1,0xFE17,0x0000, +0xFBC1,0xFE18,0x0000, 0xFBC1,0xFE19,0x0000, 0xFBC1,0xFE1A,0x0000, +0xFBC1,0xFE1B,0x0000, 0xFBC1,0xFE1C,0x0000, 0xFBC1,0xFE1D,0x0000, +0xFBC1,0xFE1E,0x0000, 0xFBC1,0xFE1F,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0xFBC1,0xFE24,0x0000, 0xFBC1,0xFE25,0x0000, 0xFBC1,0xFE26,0x0000, +0xFBC1,0xFE27,0x0000, 0xFBC1,0xFE28,0x0000, 0xFBC1,0xFE29,0x0000, +0xFBC1,0xFE2A,0x0000, 0xFBC1,0xFE2B,0x0000, 0xFBC1,0xFE2C,0x0000, +0xFBC1,0xFE2D,0x0000, 0xFBC1,0xFE2E,0x0000, 0xFBC1,0xFE2F,0x0000, +0x025D,0x025D,0x0000, 0x0228,0x0000,0x0000, 0x0227,0x0000,0x0000, +0x021B,0x0000,0x0000, 0x021B,0x0000,0x0000, 0x0288,0x0000,0x0000, +0x0289,0x0000,0x0000, 0x028C,0x0000,0x0000, 0x028D,0x0000,0x0000, +0x02B8,0x0000,0x0000, 0x02B9,0x0000,0x0000, 0x02B6,0x0000,0x0000, +0x02B7,0x0000,0x0000, 0x02B0,0x0000,0x0000, 0x02B1,0x0000,0x0000, +0x02AE,0x0000,0x0000, 0x02AF,0x0000,0x0000, 0x02B2,0x0000,0x0000, +0x02B3,0x0000,0x0000, 0x02B4,0x0000,0x0000, 0x02B5,0x0000,0x0000, +0x0238,0x0000,0x0000, 0x0239,0x0000,0x0000, 0x028A,0x0000,0x0000, +0x028B,0x0000,0x0000, 0x0211,0x0000,0x0000, 0x0211,0x0000,0x0000, +0x0211,0x0000,0x0000, 0x0211,0x0000,0x0000, 0x021B,0x0000,0x0000, +0x021B,0x0000,0x0000, 0x021B,0x0000,0x0000, 0x022F,0x0000,0x0000, +0x0237,0x0000,0x0000, 0x025D,0x0000,0x0000, 0xFBC1,0xFE53,0x0000, +0x023A,0x0000,0x0000, 0x023D,0x0000,0x0000, 0x0255,0x0000,0x0000, +0x0251,0x0000,0x0000, 0x0228,0x0000,0x0000, 0x0288,0x0000,0x0000, +0x0289,0x0000,0x0000, 0x028C,0x0000,0x0000, 0x028D,0x0000,0x0000, +0x02B8,0x0000,0x0000, 0x02B9,0x0000,0x0000, 0x02D2,0x0000,0x0000, +0x02CF,0x0000,0x0000, 0x02C8,0x0000,0x0000, 0x0428,0x0000,0x0000, +0x0221,0x0000,0x0000, 0x042C,0x0000,0x0000, 0x042E,0x0000,0x0000, +0x042D,0x0000,0x0000, 0xFBC1,0xFE67,0x0000, 0x02CE,0x0000,0x0000, +0x0E0F,0x0000,0x0000, 0x02D3,0x0000,0x0000, 0x02C7,0x0000,0x0000, +0xFBC1,0xFE6C,0x0000, 0xFBC1,0xFE6D,0x0000, 0xFBC1,0xFE6E,0x0000, +0xFBC1,0xFE6F,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0xFBC1,0xFE75,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x1347,0x0000,0x0000, +0x1348,0x0000,0x0000, 0x1348,0x0000,0x0000, 0x1349,0x0000,0x0000, +0x1349,0x0000,0x0000, 0x134C,0x0000,0x0000, 0x134C,0x0000,0x0000, +0x134D,0x0000,0x0000, 0x134D,0x0000,0x0000, 0x134F,0x0000,0x0000, +0x134F,0x0000,0x0000, 0x134F,0x0000,0x0000, 0x134F,0x0000,0x0000, +0x1350,0x0000,0x0000, 0x1350,0x0000,0x0000, 0x1352,0x0000,0x0000, +0x1352,0x0000,0x0000, 0x1352,0x0000,0x0000, 0x1352,0x0000,0x0000, +0x1356,0x0000,0x0000, 0x1356,0x0000,0x0000, 0x1357,0x0000,0x0000, +0x1357,0x0000,0x0000, 0x1357,0x0000,0x0000, 0x1357,0x0000,0x0000, +0x1358,0x0000,0x0000, 0x1358,0x0000,0x0000, 0x1358,0x0000,0x0000, +0x1358,0x0000,0x0000, 0x135E,0x0000,0x0000, 0x135E,0x0000,0x0000, +0x135E,0x0000,0x0000, 0x135E,0x0000,0x0000, 0x1364,0x0000,0x0000, +0x1364,0x0000,0x0000, 0x1364,0x0000,0x0000, 0x1364,0x0000,0x0000, +0x1365,0x0000,0x0000, 0x1365,0x0000,0x0000, 0x1365,0x0000,0x0000, +0x1365,0x0000,0x0000, 0x1369,0x0000,0x0000, 0x1369,0x0000,0x0000, +0x136A,0x0000,0x0000, 0x136A,0x0000,0x0000, 0x1375,0x0000,0x0000, +0x1375,0x0000,0x0000, 0x1376,0x0000,0x0000, 0x1376,0x0000,0x0000, +0x1381,0x0000,0x0000, 0x1381,0x0000,0x0000, 0x1381,0x0000,0x0000, +0x1381,0x0000,0x0000, 0x1382,0x0000,0x0000, 0x1382,0x0000,0x0000, +0x1382,0x0000,0x0000, 0x1382,0x0000,0x0000, 0x1387,0x0000,0x0000, +0x1387,0x0000,0x0000, 0x1387,0x0000,0x0000, 0x1387,0x0000,0x0000, +0x1388,0x0000,0x0000, 0x1388,0x0000,0x0000, 0x1388,0x0000,0x0000, +0x1388,0x0000,0x0000, 0x138C,0x0000,0x0000, 0x138C,0x0000,0x0000, +0x138C,0x0000,0x0000, 0x138C,0x0000,0x0000, 0x138D,0x0000,0x0000, +0x138D,0x0000,0x0000, 0x138D,0x0000,0x0000, 0x138D,0x0000,0x0000, +0x138F,0x0000,0x0000, 0x138F,0x0000,0x0000, 0x138F,0x0000,0x0000, +0x138F,0x0000,0x0000, 0x1390,0x0000,0x0000, 0x1390,0x0000,0x0000, +0x1390,0x0000,0x0000, 0x1390,0x0000,0x0000, 0x1393,0x0000,0x0000, +0x1393,0x0000,0x0000, 0x1393,0x0000,0x0000, 0x1393,0x0000,0x0000, +0x139B,0x0000,0x0000, 0x139B,0x0000,0x0000, 0x139B,0x0000,0x0000, +0x139B,0x0000,0x0000, 0x139E,0x0000,0x0000, 0x139E,0x0000,0x0000, +0x139E,0x0000,0x0000, 0x139E,0x0000,0x0000, 0x13AB,0x0000,0x0000, +0x13AB,0x0000,0x0000, 0x13AB,0x0000,0x0000, 0x13AB,0x0000,0x0000, +0x13B0,0x0000,0x0000, 0x13B0,0x0000,0x0000, 0x13B0,0x0000,0x0000, +0x13B0,0x0000,0x0000, 0x13B1,0x0000,0x0000, 0x13B1,0x0000,0x0000, +0x13B1,0x0000,0x0000, 0x13B1,0x0000,0x0000, 0x13B7,0x0000,0x0000, +0x13B7,0x0000,0x0000, 0x13B7,0x0000,0x0000, 0x13B7,0x0000,0x0000, +0x13BD,0x0000,0x0000, 0x13BD,0x0000,0x0000, 0x13C7,0x0000,0x0000, +0x13C7,0x0000,0x0000, 0x13C8,0x0000,0x0000, 0x13C8,0x0000,0x0000, +0x13C8,0x0000,0x0000, 0x13C8,0x0000,0x0000, 0x13AB,0x1348,0x0000, +0x13AB,0x1348,0x0000, 0x13AB,0x1349,0x0000, 0x13AB,0x1349,0x0000, +0x13AB,0x134D,0x0000, 0x13AB,0x134D,0x0000, 0x13AB,0x1350,0x0000, +0x13AB,0x1350,0x0000, 0xFBC1,0xFEFD,0x0000, 0xFBC1,0xFEFE,0x0000, +0x0000,0x0000,0x0000 }; + +uint16 page0FFdata[]= { /* FF00 (3 weights per char) */ +0xFBC1,0xFF00,0x0000, 0x0251,0x0000,0x0000, 0x027E,0x0000,0x0000, +0x02D2,0x0000,0x0000, 0x0E0F,0x0000,0x0000, 0x02D3,0x0000,0x0000, +0x02CF,0x0000,0x0000, 0x0277,0x0000,0x0000, 0x0288,0x0000,0x0000, +0x0289,0x0000,0x0000, 0x02C8,0x0000,0x0000, 0x0428,0x0000,0x0000, +0x022F,0x0000,0x0000, 0x0221,0x0000,0x0000, 0x025D,0x0000,0x0000, +0x02CC,0x0000,0x0000, 0x0E29,0x0000,0x0000, 0x0E2A,0x0000,0x0000, +0x0E2B,0x0000,0x0000, 0x0E2C,0x0000,0x0000, 0x0E2D,0x0000,0x0000, +0x0E2E,0x0000,0x0000, 0x0E2F,0x0000,0x0000, 0x0E30,0x0000,0x0000, +0x0E31,0x0000,0x0000, 0x0E32,0x0000,0x0000, 0x023D,0x0000,0x0000, +0x023A,0x0000,0x0000, 0x042C,0x0000,0x0000, 0x042D,0x0000,0x0000, +0x042E,0x0000,0x0000, 0x0255,0x0000,0x0000, 0x02C7,0x0000,0x0000, +0x0E33,0x0000,0x0000, 0x0E4A,0x0000,0x0000, 0x0E60,0x0000,0x0000, +0x0E6D,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0EB9,0x0000,0x0000, +0x0EC1,0x0000,0x0000, 0x0EE1,0x0000,0x0000, 0x0EFB,0x0000,0x0000, +0x0F10,0x0000,0x0000, 0x0F21,0x0000,0x0000, 0x0F2E,0x0000,0x0000, +0x0F5B,0x0000,0x0000, 0x0F64,0x0000,0x0000, 0x0F82,0x0000,0x0000, +0x0FA7,0x0000,0x0000, 0x0FB4,0x0000,0x0000, 0x0FC0,0x0000,0x0000, +0x0FEA,0x0000,0x0000, 0x1002,0x0000,0x0000, 0x101F,0x0000,0x0000, +0x1044,0x0000,0x0000, 0x1051,0x0000,0x0000, 0x105A,0x0000,0x0000, +0x105E,0x0000,0x0000, 0x106A,0x0000,0x0000, 0x028A,0x0000,0x0000, +0x02CE,0x0000,0x0000, 0x028B,0x0000,0x0000, 0x020F,0x0000,0x0000, +0x021B,0x0000,0x0000, 0x020C,0x0000,0x0000, 0x0E33,0x0000,0x0000, +0x0E4A,0x0000,0x0000, 0x0E60,0x0000,0x0000, 0x0E6D,0x0000,0x0000, +0x0E8B,0x0000,0x0000, 0x0EB9,0x0000,0x0000, 0x0EC1,0x0000,0x0000, +0x0EE1,0x0000,0x0000, 0x0EFB,0x0000,0x0000, 0x0F10,0x0000,0x0000, +0x0F21,0x0000,0x0000, 0x0F2E,0x0000,0x0000, 0x0F5B,0x0000,0x0000, +0x0F64,0x0000,0x0000, 0x0F82,0x0000,0x0000, 0x0FA7,0x0000,0x0000, +0x0FB4,0x0000,0x0000, 0x0FC0,0x0000,0x0000, 0x0FEA,0x0000,0x0000, +0x1002,0x0000,0x0000, 0x101F,0x0000,0x0000, 0x1044,0x0000,0x0000, +0x1051,0x0000,0x0000, 0x105A,0x0000,0x0000, 0x105E,0x0000,0x0000, +0x106A,0x0000,0x0000, 0x028C,0x0000,0x0000, 0x0430,0x0000,0x0000, +0x028D,0x0000,0x0000, 0x0433,0x0000,0x0000, 0x029A,0x0000,0x0000, +0x029B,0x0000,0x0000, 0x0266,0x0000,0x0000, 0x02B2,0x0000,0x0000, +0x02B3,0x0000,0x0000, 0x0237,0x0000,0x0000, 0x022E,0x0000,0x0000, +0x1E80,0x0000,0x0000, 0x1E52,0x0000,0x0000, 0x1E53,0x0000,0x0000, +0x1E54,0x0000,0x0000, 0x1E55,0x0000,0x0000, 0x1E56,0x0000,0x0000, +0x1E75,0x0000,0x0000, 0x1E76,0x0000,0x0000, 0x1E77,0x0000,0x0000, +0x1E63,0x0000,0x0000, 0x0E0B,0x0000,0x0000, 0x1E52,0x0000,0x0000, +0x1E53,0x0000,0x0000, 0x1E54,0x0000,0x0000, 0x1E55,0x0000,0x0000, +0x1E56,0x0000,0x0000, 0x1E57,0x0000,0x0000, 0x1E58,0x0000,0x0000, +0x1E59,0x0000,0x0000, 0x1E5A,0x0000,0x0000, 0x1E5B,0x0000,0x0000, +0x1E5C,0x0000,0x0000, 0x1E5D,0x0000,0x0000, 0x1E5E,0x0000,0x0000, +0x1E5F,0x0000,0x0000, 0x1E60,0x0000,0x0000, 0x1E61,0x0000,0x0000, +0x1E62,0x0000,0x0000, 0x1E63,0x0000,0x0000, 0x1E64,0x0000,0x0000, +0x1E65,0x0000,0x0000, 0x1E66,0x0000,0x0000, 0x1E67,0x0000,0x0000, +0x1E68,0x0000,0x0000, 0x1E69,0x0000,0x0000, 0x1E6A,0x0000,0x0000, +0x1E6B,0x0000,0x0000, 0x1E6C,0x0000,0x0000, 0x1E6D,0x0000,0x0000, +0x1E6E,0x0000,0x0000, 0x1E6F,0x0000,0x0000, 0x1E70,0x0000,0x0000, +0x1E71,0x0000,0x0000, 0x1E72,0x0000,0x0000, 0x1E73,0x0000,0x0000, +0x1E74,0x0000,0x0000, 0x1E75,0x0000,0x0000, 0x1E76,0x0000,0x0000, +0x1E77,0x0000,0x0000, 0x1E78,0x0000,0x0000, 0x1E79,0x0000,0x0000, +0x1E7A,0x0000,0x0000, 0x1E7B,0x0000,0x0000, 0x1E7C,0x0000,0x0000, +0x1E7D,0x0000,0x0000, 0x1E81,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000, 0x1DBD,0x0000,0x0000, 0x1D62,0x0000,0x0000, +0x1D63,0x0000,0x0000, 0x1E02,0x0000,0x0000, 0x1D64,0x0000,0x0000, +0x1E04,0x0000,0x0000, 0x1E05,0x0000,0x0000, 0x1D65,0x0000,0x0000, +0x1D66,0x0000,0x0000, 0x1D67,0x0000,0x0000, 0x1E08,0x0000,0x0000, +0x1E09,0x0000,0x0000, 0x1E0A,0x0000,0x0000, 0x1E0B,0x0000,0x0000, +0x1E0C,0x0000,0x0000, 0x1E0D,0x0000,0x0000, 0x1D7C,0x0000,0x0000, +0x1D68,0x0000,0x0000, 0x1D69,0x0000,0x0000, 0x1D6A,0x0000,0x0000, +0x1D83,0x0000,0x0000, 0x1D6B,0x0000,0x0000, 0x1D6C,0x0000,0x0000, +0x1D6D,0x0000,0x0000, 0x1D6E,0x0000,0x0000, 0x1D6F,0x0000,0x0000, +0x1D70,0x0000,0x0000, 0x1D71,0x0000,0x0000, 0x1D72,0x0000,0x0000, +0x1D73,0x0000,0x0000, 0x1D74,0x0000,0x0000, 0xFBC1,0xFFBF,0x0000, +0xFBC1,0xFFC0,0x0000, 0xFBC1,0xFFC1,0x0000, 0x1DBE,0x0000,0x0000, +0x1DBF,0x0000,0x0000, 0x1DC0,0x0000,0x0000, 0x1DC1,0x0000,0x0000, +0x1DC2,0x0000,0x0000, 0x1DC3,0x0000,0x0000, 0xFBC1,0xFFC8,0x0000, +0xFBC1,0xFFC9,0x0000, 0x1DC4,0x0000,0x0000, 0x1DC5,0x0000,0x0000, +0x1DC6,0x0000,0x0000, 0x1DC7,0x0000,0x0000, 0x1DC8,0x0000,0x0000, +0x1DC9,0x0000,0x0000, 0xFBC1,0xFFD0,0x0000, 0xFBC1,0xFFD1,0x0000, +0x1DCA,0x0000,0x0000, 0x1DCB,0x0000,0x0000, 0x1DCC,0x0000,0x0000, +0x1DCD,0x0000,0x0000, 0x1DCE,0x0000,0x0000, 0x1DCF,0x0000,0x0000, +0xFBC1,0xFFD8,0x0000, 0xFBC1,0xFFD9,0x0000, 0x1DD0,0x0000,0x0000, +0x1DD1,0x0000,0x0000, 0x1DD2,0x0000,0x0000, 0xFBC1,0xFFDD,0x0000, +0xFBC1,0xFFDE,0x0000, 0xFBC1,0xFFDF,0x0000, 0x0E0E,0x0000,0x0000, +0x0E10,0x0000,0x0000, 0x042F,0x0000,0x0000, 0x0210,0x0000,0x0000, +0x0431,0x0000,0x0000, 0x0E11,0x0000,0x0000, 0x0E20,0x0000,0x0000, +0xFBC1,0xFFE7,0x0000, 0x05FE,0x0000,0x0000, 0x03AE,0x0000,0x0000, +0x03B0,0x0000,0x0000, 0x03AF,0x0000,0x0000, 0x03B1,0x0000,0x0000, +0x069C,0x0000,0x0000, 0x06C7,0x0000,0x0000, 0xFBC1,0xFFEF,0x0000, +0xFBC1,0xFFF0,0x0000, 0xFBC1,0xFFF1,0x0000, 0xFBC1,0xFFF2,0x0000, +0xFBC1,0xFFF3,0x0000, 0xFBC1,0xFFF4,0x0000, 0xFBC1,0xFFF5,0x0000, +0xFBC1,0xFFF6,0x0000, 0xFBC1,0xFFF7,0x0000, 0xFBC1,0xFFF8,0x0000, +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, +0x0DC5,0x0000,0x0000, 0x0DC6,0x0000,0x0000, 0xFBC1,0xFFFE,0x0000, +0xFBC1,0xFFFF,0x0000 }; + +uchar uca_length[256]={ +4,3,3,4,3,3,3,3,0,3,3,3,3,3,3,3, +3,3,3,3,3,2,3,3,3,3,0,0,0,3,3,3, +5,5,4,3,5,2,3,3,2,2,5,3,0,0,3,3, +3,3,8,9,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,3,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,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, +2,2,2,2,3,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,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,3,3,4,3,9,3,3 +}; +uint16 *uca_weight[256]={ +page000data,page001data,page002data,page003data, +page004data,page005data,page006data,page007data, +NULL ,page009data,page00Adata,page00Bdata, +page00Cdata,page00Ddata,page00Edata,page00Fdata, +page010data,page011data,page012data,page013data, +page014data,page015data,page016data,page017data, +page018data,page019data,NULL ,NULL , +NULL ,page01Ddata,page01Edata,page01Fdata, +page020data,page021data,page022data,page023data, +page024data,page025data,page026data,page027data, +page028data,page029data,page02Adata,page02Bdata, +NULL ,NULL ,page02Edata,page02Fdata, +page030data,page031data,page032data,page033data, +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,page04Ddata,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +page0A0data,page0A1data,page0A2data,page0A3data, +page0A4data,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,page0F9data,page0FAdata,page0FBdata, +page0FCdata,page0FDdata,page0FEdata,page0FFdata +}; + + +/******************************************************/ + +#define MY_UCA_CMASK 255 +#define MY_UCA_PSHIFT 8 + + +/* Created from allkeys.txt. Unicode version '5.2.0'. */ + +uint16 uca520_p000[]= { /* 0000 (4 weights per char) */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0000 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0002 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0004 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0006 */ +0x0000,0x0000,0x0000,0x0000, 0x0201,0x0000,0x0000,0x0000, /* 0008 */ +0x0202,0x0000,0x0000,0x0000, 0x0203,0x0000,0x0000,0x0000, /* 000A */ +0x0204,0x0000,0x0000,0x0000, 0x0205,0x0000,0x0000,0x0000, /* 000C */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 000E */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0010 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0012 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0014 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0016 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0018 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 001A */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 001C */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 001E */ +0x020A,0x0000,0x0000,0x0000, 0x026E,0x0000,0x0000,0x0000, /* 0020 */ +0x02F5,0x0000,0x0000,0x0000, 0x0362,0x0000,0x0000,0x0000, /* 0022 */ +0x11E1,0x0000,0x0000,0x0000, 0x0363,0x0000,0x0000,0x0000, /* 0024 */ +0x035F,0x0000,0x0000,0x0000, 0x02EE,0x0000,0x0000,0x0000, /* 0026 */ +0x02FF,0x0000,0x0000,0x0000, 0x0300,0x0000,0x0000,0x0000, /* 0028 */ +0x0357,0x0000,0x0000,0x0000, 0x0550,0x0000,0x0000,0x0000, /* 002A */ +0x0234,0x0000,0x0000,0x0000, 0x0223,0x0000,0x0000,0x0000, /* 002C */ +0x0281,0x0000,0x0000,0x0000, 0x035C,0x0000,0x0000,0x0000, /* 002E */ +0x1205,0x0000,0x0000,0x0000, 0x1206,0x0000,0x0000,0x0000, /* 0030 */ +0x1207,0x0000,0x0000,0x0000, 0x1208,0x0000,0x0000,0x0000, /* 0032 */ +0x1209,0x0000,0x0000,0x0000, 0x120A,0x0000,0x0000,0x0000, /* 0034 */ +0x120B,0x0000,0x0000,0x0000, 0x120C,0x0000,0x0000,0x0000, /* 0036 */ +0x120D,0x0000,0x0000,0x0000, 0x120E,0x0000,0x0000,0x0000, /* 0038 */ +0x0247,0x0000,0x0000,0x0000, 0x0243,0x0000,0x0000,0x0000, /* 003A */ +0x0554,0x0000,0x0000,0x0000, 0x0555,0x0000,0x0000,0x0000, /* 003C */ +0x0556,0x0000,0x0000,0x0000, 0x0273,0x0000,0x0000,0x0000, /* 003E */ +0x0356,0x0000,0x0000,0x0000, 0x120F,0x0000,0x0000,0x0000, /* 0040 */ +0x1225,0x0000,0x0000,0x0000, 0x123D,0x0000,0x0000,0x0000, /* 0042 */ +0x1250,0x0000,0x0000,0x0000, 0x126B,0x0000,0x0000,0x0000, /* 0044 */ +0x12A3,0x0000,0x0000,0x0000, 0x12B0,0x0000,0x0000,0x0000, /* 0046 */ +0x12D3,0x0000,0x0000,0x0000, 0x12EC,0x0000,0x0000,0x0000, /* 0048 */ +0x1305,0x0000,0x0000,0x0000, 0x131E,0x0000,0x0000,0x0000, /* 004A */ +0x1330,0x0000,0x0000,0x0000, 0x135F,0x0000,0x0000,0x0000, /* 004C */ +0x136D,0x0000,0x0000,0x0000, 0x138E,0x0000,0x0000,0x0000, /* 004E */ +0x13B3,0x0000,0x0000,0x0000, 0x13C8,0x0000,0x0000,0x0000, /* 0050 */ +0x13DA,0x0000,0x0000,0x0000, 0x1410,0x0000,0x0000,0x0000, /* 0052 */ +0x1433,0x0000,0x0000,0x0000, 0x1453,0x0000,0x0000,0x0000, /* 0054 */ +0x147B,0x0000,0x0000,0x0000, 0x148D,0x0000,0x0000,0x0000, /* 0056 */ +0x1497,0x0000,0x0000,0x0000, 0x149C,0x0000,0x0000,0x0000, /* 0058 */ +0x14AD,0x0000,0x0000,0x0000, 0x0301,0x0000,0x0000,0x0000, /* 005A */ +0x035E,0x0000,0x0000,0x0000, 0x0302,0x0000,0x0000,0x0000, /* 005C */ +0x0211,0x0000,0x0000,0x0000, 0x021D,0x0000,0x0000,0x0000, /* 005E */ +0x020E,0x0000,0x0000,0x0000, 0x120F,0x0000,0x0000,0x0000, /* 0060 */ +0x1225,0x0000,0x0000,0x0000, 0x123D,0x0000,0x0000,0x0000, /* 0062 */ +0x1250,0x0000,0x0000,0x0000, 0x126B,0x0000,0x0000,0x0000, /* 0064 */ +0x12A3,0x0000,0x0000,0x0000, 0x12B0,0x0000,0x0000,0x0000, /* 0066 */ +0x12D3,0x0000,0x0000,0x0000, 0x12EC,0x0000,0x0000,0x0000, /* 0068 */ +0x1305,0x0000,0x0000,0x0000, 0x131E,0x0000,0x0000,0x0000, /* 006A */ +0x1330,0x0000,0x0000,0x0000, 0x135F,0x0000,0x0000,0x0000, /* 006C */ +0x136D,0x0000,0x0000,0x0000, 0x138E,0x0000,0x0000,0x0000, /* 006E */ +0x13B3,0x0000,0x0000,0x0000, 0x13C8,0x0000,0x0000,0x0000, /* 0070 */ +0x13DA,0x0000,0x0000,0x0000, 0x1410,0x0000,0x0000,0x0000, /* 0072 */ +0x1433,0x0000,0x0000,0x0000, 0x1453,0x0000,0x0000,0x0000, /* 0074 */ +0x147B,0x0000,0x0000,0x0000, 0x148D,0x0000,0x0000,0x0000, /* 0076 */ +0x1497,0x0000,0x0000,0x0000, 0x149C,0x0000,0x0000,0x0000, /* 0078 */ +0x14AD,0x0000,0x0000,0x0000, 0x0303,0x0000,0x0000,0x0000, /* 007A */ +0x0558,0x0000,0x0000,0x0000, 0x0304,0x0000,0x0000,0x0000, /* 007C */ +0x055B,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 007E */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0080 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0082 */ +0x0000,0x0000,0x0000,0x0000, 0x0206,0x0000,0x0000,0x0000, /* 0084 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0086 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0088 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 008A */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 008C */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 008E */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0090 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0092 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0094 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0096 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0098 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 009A */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 009C */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 009E */ +0x020A,0x0000,0x0000,0x0000, 0x026F,0x0000,0x0000,0x0000, /* 00A0 */ +0x11E0,0x0000,0x0000,0x0000, 0x11E2,0x0000,0x0000,0x0000, /* 00A2 */ +0x11DF,0x0000,0x0000,0x0000, 0x11E3,0x0000,0x0000,0x0000, /* 00A4 */ +0x0559,0x0000,0x0000,0x0000, 0x0351,0x0000,0x0000,0x0000, /* 00A6 */ +0x0216,0x0000,0x0000,0x0000, 0x0354,0x0000,0x0000,0x0000, /* 00A8 */ +0x120F,0x0000,0x0000,0x0000, 0x02FD,0x0000,0x0000,0x0000, /* 00AA */ +0x0557,0x0000,0x0000,0x0000, 0x0222,0x0000,0x0000,0x0000, /* 00AC */ +0x0355,0x0000,0x0000,0x0000, 0x0212,0x0000,0x0000,0x0000, /* 00AE */ +0x044B,0x0000,0x0000,0x0000, 0x0551,0x0000,0x0000,0x0000, /* 00B0 */ +0x1207,0x0000,0x0000,0x0000, 0x1208,0x0000,0x0000,0x0000, /* 00B2 */ +0x020F,0x0000,0x0000,0x0000, 0x1557,0x0000,0x0000,0x0000, /* 00B4 */ +0x0352,0x0000,0x0000,0x0000, 0x0292,0x0000,0x0000,0x0000, /* 00B6 */ +0x021B,0x0000,0x0000,0x0000, 0x1206,0x0000,0x0000,0x0000, /* 00B8 */ +0x138E,0x0000,0x0000,0x0000, 0x02FE,0x0000,0x0000,0x0000, /* 00BA */ +0x1206,0x035D,0x1209,0x0000, 0x1206,0x035D,0x1207,0x0000, /* 00BC */ +0x1208,0x035D,0x1209,0x0000, 0x0274,0x0000,0x0000,0x0000, /* 00BE */ +0x120F,0x0000,0x0000,0x0000, 0x120F,0x0000,0x0000,0x0000, /* 00C0 */ +0x120F,0x0000,0x0000,0x0000, 0x120F,0x0000,0x0000,0x0000, /* 00C2 */ +0x120F,0x0000,0x0000,0x0000, 0x120F,0x0000,0x0000,0x0000, /* 00C4 */ +0x120F,0x126B,0x0000,0x0000, 0x123D,0x0000,0x0000,0x0000, /* 00C6 */ +0x126B,0x0000,0x0000,0x0000, 0x126B,0x0000,0x0000,0x0000, /* 00C8 */ +0x126B,0x0000,0x0000,0x0000, 0x126B,0x0000,0x0000,0x0000, /* 00CA */ +0x12EC,0x0000,0x0000,0x0000, 0x12EC,0x0000,0x0000,0x0000, /* 00CC */ +0x12EC,0x0000,0x0000,0x0000, 0x12EC,0x0000,0x0000,0x0000, /* 00CE */ +0x1250,0x0000,0x0000,0x0000, 0x136D,0x0000,0x0000,0x0000, /* 00D0 */ +0x138E,0x0000,0x0000,0x0000, 0x138E,0x0000,0x0000,0x0000, /* 00D2 */ +0x138E,0x0000,0x0000,0x0000, 0x138E,0x0000,0x0000,0x0000, /* 00D4 */ +0x138E,0x0000,0x0000,0x0000, 0x0553,0x0000,0x0000,0x0000, /* 00D6 */ +0x138E,0x0000,0x0000,0x0000, 0x1453,0x0000,0x0000,0x0000, /* 00D8 */ +0x1453,0x0000,0x0000,0x0000, 0x1453,0x0000,0x0000,0x0000, /* 00DA */ +0x1453,0x0000,0x0000,0x0000, 0x149C,0x0000,0x0000,0x0000, /* 00DC */ +0x14E0,0x0000,0x0000,0x0000, 0x1410,0x1410,0x0000,0x0000, /* 00DE */ +0x120F,0x0000,0x0000,0x0000, 0x120F,0x0000,0x0000,0x0000, /* 00E0 */ +0x120F,0x0000,0x0000,0x0000, 0x120F,0x0000,0x0000,0x0000, /* 00E2 */ +0x120F,0x0000,0x0000,0x0000, 0x120F,0x0000,0x0000,0x0000, /* 00E4 */ +0x120F,0x126B,0x0000,0x0000, 0x123D,0x0000,0x0000,0x0000, /* 00E6 */ +0x126B,0x0000,0x0000,0x0000, 0x126B,0x0000,0x0000,0x0000, /* 00E8 */ +0x126B,0x0000,0x0000,0x0000, 0x126B,0x0000,0x0000,0x0000, /* 00EA */ +0x12EC,0x0000,0x0000,0x0000, 0x12EC,0x0000,0x0000,0x0000, /* 00EC */ +0x12EC,0x0000,0x0000,0x0000, 0x12EC,0x0000,0x0000,0x0000, /* 00EE */ +0x1250,0x0000,0x0000,0x0000, 0x136D,0x0000,0x0000,0x0000, /* 00F0 */ +0x138E,0x0000,0x0000,0x0000, 0x138E,0x0000,0x0000,0x0000, /* 00F2 */ +0x138E,0x0000,0x0000,0x0000, 0x138E,0x0000,0x0000,0x0000, /* 00F4 */ +0x138E,0x0000,0x0000,0x0000, 0x0552,0x0000,0x0000,0x0000, /* 00F6 */ +0x138E,0x0000,0x0000,0x0000, 0x1453,0x0000,0x0000,0x0000, /* 00F8 */ +0x1453,0x0000,0x0000,0x0000, 0x1453,0x0000,0x0000,0x0000, /* 00FA */ +0x1453,0x0000,0x0000,0x0000, 0x149C,0x0000,0x0000,0x0000, /* 00FC */ +0x14E0,0x0000,0x0000,0x0000, 0x149C,0x0000,0x0000,0x0000 /* 00FE */ +}; + +uint16 uca520_p001[]= { /* 0100 (3 weights per char) */ +0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 0100 */ +0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 0103 */ +0x123D,0x0000,0x0000, 0x123D,0x0000,0x0000, 0x123D,0x0000,0x0000, /* 0106 */ +0x123D,0x0000,0x0000, 0x123D,0x0000,0x0000, 0x123D,0x0000,0x0000, /* 0109 */ +0x123D,0x0000,0x0000, 0x123D,0x0000,0x0000, 0x1250,0x0000,0x0000, /* 010C */ +0x1250,0x0000,0x0000, 0x1250,0x0000,0x0000, 0x1250,0x0000,0x0000, /* 010F */ +0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 0112 */ +0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 0115 */ +0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 0118 */ +0x126B,0x0000,0x0000, 0x12B0,0x0000,0x0000, 0x12B0,0x0000,0x0000, /* 011B */ +0x12B0,0x0000,0x0000, 0x12B0,0x0000,0x0000, 0x12B0,0x0000,0x0000, /* 011E */ +0x12B0,0x0000,0x0000, 0x12B0,0x0000,0x0000, 0x12B0,0x0000,0x0000, /* 0121 */ +0x12D3,0x0000,0x0000, 0x12D3,0x0000,0x0000, 0x12D3,0x0000,0x0000, /* 0124 */ +0x12D3,0x0000,0x0000, 0x12EC,0x0000,0x0000, 0x12EC,0x0000,0x0000, /* 0127 */ +0x12EC,0x0000,0x0000, 0x12EC,0x0000,0x0000, 0x12EC,0x0000,0x0000, /* 012A */ +0x12EC,0x0000,0x0000, 0x12EC,0x0000,0x0000, 0x12EC,0x0000,0x0000, /* 012D */ +0x12EC,0x0000,0x0000, 0x12F0,0x0000,0x0000, 0x12EC,0x1305,0x0000, /* 0130 */ +0x12EC,0x1305,0x0000, 0x1305,0x0000,0x0000, 0x1305,0x0000,0x0000, /* 0133 */ +0x131E,0x0000,0x0000, 0x131E,0x0000,0x0000, 0x13D6,0x0000,0x0000, /* 0136 */ +0x1330,0x0000,0x0000, 0x1330,0x0000,0x0000, 0x1330,0x0000,0x0000, /* 0139 */ +0x1330,0x0000,0x0000, 0x1330,0x0000,0x0000, 0x1330,0x0000,0x0000, /* 013C */ +0x1330,0x0000,0x0000, 0x1330,0x0000,0x0000, 0x1330,0x0000,0x0000, /* 013F */ +0x1330,0x0000,0x0000, 0x136D,0x0000,0x0000, 0x136D,0x0000,0x0000, /* 0142 */ +0x136D,0x0000,0x0000, 0x136D,0x0000,0x0000, 0x136D,0x0000,0x0000, /* 0145 */ +0x136D,0x0000,0x0000, 0x150B,0x136D,0x0000, 0x138A,0x0000,0x0000, /* 0148 */ +0x138A,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 014B */ +0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 014E */ +0x138E,0x0000,0x0000, 0x138E,0x126B,0x0000, 0x138E,0x126B,0x0000, /* 0151 */ +0x13DA,0x0000,0x0000, 0x13DA,0x0000,0x0000, 0x13DA,0x0000,0x0000, /* 0154 */ +0x13DA,0x0000,0x0000, 0x13DA,0x0000,0x0000, 0x13DA,0x0000,0x0000, /* 0157 */ +0x1410,0x0000,0x0000, 0x1410,0x0000,0x0000, 0x1410,0x0000,0x0000, /* 015A */ +0x1410,0x0000,0x0000, 0x1410,0x0000,0x0000, 0x1410,0x0000,0x0000, /* 015D */ +0x1410,0x0000,0x0000, 0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, /* 0160 */ +0x1433,0x0000,0x0000, 0x1433,0x0000,0x0000, 0x1433,0x0000,0x0000, /* 0163 */ +0x1438,0x0000,0x0000, 0x1438,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 0166 */ +0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 0169 */ +0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 016C */ +0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 016F */ +0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x148D,0x0000,0x0000, /* 0172 */ +0x148D,0x0000,0x0000, 0x149C,0x0000,0x0000, 0x149C,0x0000,0x0000, /* 0175 */ +0x149C,0x0000,0x0000, 0x14AD,0x0000,0x0000, 0x14AD,0x0000,0x0000, /* 0178 */ +0x14AD,0x0000,0x0000, 0x14AD,0x0000,0x0000, 0x14AD,0x0000,0x0000, /* 017B */ +0x14AD,0x0000,0x0000, 0x1410,0x0000,0x0000, 0x122D,0x0000,0x0000, /* 017E */ +0x1235,0x0000,0x0000, 0x1239,0x0000,0x0000, 0x1239,0x0000,0x0000, /* 0181 */ +0x14FE,0x0000,0x0000, 0x14FE,0x0000,0x0000, 0x139A,0x0000,0x0000, /* 0184 */ +0x1246,0x0000,0x0000, 0x1246,0x0000,0x0000, 0x1258,0x0000,0x0000, /* 0187 */ +0x125C,0x0000,0x0000, 0x1261,0x0000,0x0000, 0x1261,0x0000,0x0000, /* 018A */ +0x14AD,0x148D,0x0000, 0x1276,0x0000,0x0000, 0x127B,0x0000,0x0000, /* 018D */ +0x1280,0x0000,0x0000, 0x12AA,0x0000,0x0000, 0x12AA,0x0000,0x0000, /* 0190 */ +0x12C1,0x0000,0x0000, 0x12CB,0x0000,0x0000, 0x12DB,0x0000,0x0000, /* 0193 */ +0x1300,0x0000,0x0000, 0x12FA,0x0000,0x0000, 0x1324,0x0000,0x0000, /* 0196 */ +0x1324,0x0000,0x0000, 0x133B,0x0000,0x0000, 0x1357,0x0000,0x0000, /* 0199 */ +0x146D,0x0000,0x0000, 0x1378,0x0000,0x0000, 0x137C,0x0000,0x0000, /* 019C */ +0x13A5,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 019F */ +0x12CF,0x0000,0x0000, 0x12CF,0x0000,0x0000, 0x13BC,0x0000,0x0000, /* 01A2 */ +0x13BC,0x0000,0x0000, 0x13DE,0x0000,0x0000, 0x14F6,0x0000,0x0000, /* 01A5 */ +0x14F6,0x0000,0x0000, 0x1421,0x0000,0x0000, 0x1426,0x0000,0x0000, /* 01A8 */ +0x143E,0x0000,0x0000, 0x1442,0x0000,0x0000, 0x1442,0x0000,0x0000, /* 01AB */ +0x1446,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 01AE */ +0x1476,0x0000,0x0000, 0x1482,0x0000,0x0000, 0x14A8,0x0000,0x0000, /* 01B1 */ +0x14A8,0x0000,0x0000, 0x14B2,0x0000,0x0000, 0x14B2,0x0000,0x0000, /* 01B4 */ +0x14CA,0x0000,0x0000, 0x14CF,0x0000,0x0000, 0x14CF,0x0000,0x0000, /* 01B7 */ +0x14D4,0x0000,0x0000, 0x14EF,0x0000,0x0000, 0x14FA,0x0000,0x0000, /* 01BA */ +0x14FA,0x0000,0x0000, 0x1433,0x1410,0x0000, 0x14E6,0x0000,0x0000, /* 01BD */ +0x1525,0x0000,0x0000, 0x1529,0x0000,0x0000, 0x152D,0x0000,0x0000, /* 01C0 */ +0x1531,0x0000,0x0000, 0x1250,0x14AD,0x0000, 0x1250,0x14AD,0x0000, /* 01C3 */ +0x1250,0x14AD,0x0000, 0x1330,0x1305,0x0000, 0x1330,0x1305,0x0000, /* 01C6 */ +0x1330,0x1305,0x0000, 0x136D,0x1305,0x0000, 0x136D,0x1305,0x0000, /* 01C9 */ +0x136D,0x1305,0x0000, 0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 01CC */ +0x12EC,0x0000,0x0000, 0x12EC,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 01CF */ +0x138E,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 01D2 */ +0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 01D5 */ +0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 01D8 */ +0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x1276,0x0000,0x0000, /* 01DB */ +0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 01DE */ +0x120F,0x0000,0x0000, 0x120F,0x126B,0x0000, 0x120F,0x126B,0x0000, /* 01E1 */ +0x12BC,0x0000,0x0000, 0x12BC,0x0000,0x0000, 0x12B0,0x0000,0x0000, /* 01E4 */ +0x12B0,0x0000,0x0000, 0x131E,0x0000,0x0000, 0x131E,0x0000,0x0000, /* 01E7 */ +0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 01EA */ +0x138E,0x0000,0x0000, 0x14CA,0x0000,0x0000, 0x14CA,0x0000,0x0000, /* 01ED */ +0x1305,0x0000,0x0000, 0x1250,0x14AD,0x0000, 0x1250,0x14AD,0x0000, /* 01F0 */ +0x1250,0x14AD,0x0000, 0x12B0,0x0000,0x0000, 0x12B0,0x0000,0x0000, /* 01F3 */ +0x12DB,0x0000,0x0000, 0x14E6,0x0000,0x0000, 0x136D,0x0000,0x0000, /* 01F6 */ +0x136D,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 01F9 */ +0x120F,0x126B,0x0000, 0x120F,0x126B,0x0000, 0x138E,0x0000,0x0000, /* 01FC */ +0x138E,0x0000,0x0000 }; + +uint16 uca520_p002[]= { /* 0200 (3 weights per char) */ +0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 0200 */ +0x120F,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 0203 */ +0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x12EC,0x0000,0x0000, /* 0206 */ +0x12EC,0x0000,0x0000, 0x12EC,0x0000,0x0000, 0x12EC,0x0000,0x0000, /* 0209 */ +0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 020C */ +0x138E,0x0000,0x0000, 0x13DA,0x0000,0x0000, 0x13DA,0x0000,0x0000, /* 020F */ +0x13DA,0x0000,0x0000, 0x13DA,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 0212 */ +0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 0215 */ +0x1410,0x0000,0x0000, 0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, /* 0218 */ +0x1433,0x0000,0x0000, 0x14DC,0x0000,0x0000, 0x14DC,0x0000,0x0000, /* 021B */ +0x12D3,0x0000,0x0000, 0x12D3,0x0000,0x0000, 0x137C,0x0000,0x0000, /* 021E */ +0x1265,0x0000,0x0000, 0x13AE,0x0000,0x0000, 0x13AE,0x0000,0x0000, /* 0221 */ +0x14B8,0x0000,0x0000, 0x14B8,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 0224 */ +0x120F,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 0227 */ +0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 022A */ +0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 022D */ +0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x149C,0x0000,0x0000, /* 0230 */ +0x149C,0x0000,0x0000, 0x134D,0x0000,0x0000, 0x1385,0x0000,0x0000, /* 0233 */ +0x144A,0x0000,0x0000, 0x1309,0x0000,0x0000, 0x1250,0x1225,0x0000, /* 0236 */ +0x13C8,0x13B3,0x0000, 0x1214,0x0000,0x0000, 0x1242,0x0000,0x0000, /* 0239 */ +0x1242,0x0000,0x0000, 0x133B,0x0000,0x0000, 0x143C,0x0000,0x0000, /* 023C */ +0x141B,0x0000,0x0000, 0x14C4,0x0000,0x0000, 0x1506,0x0000,0x0000, /* 023F */ +0x1506,0x0000,0x0000, 0x122D,0x0000,0x0000, 0x145B,0x0000,0x0000, /* 0242 */ +0x1489,0x0000,0x0000, 0x1270,0x0000,0x0000, 0x1270,0x0000,0x0000, /* 0245 */ +0x130E,0x0000,0x0000, 0x130E,0x0000,0x0000, 0x13D2,0x0000,0x0000, /* 0248 */ +0x13D2,0x0000,0x0000, 0x13E4,0x0000,0x0000, 0x13E4,0x0000,0x0000, /* 024B */ +0x14A4,0x0000,0x0000, 0x14A4,0x0000,0x0000, 0x1218,0x0000,0x0000, /* 024E */ +0x121C,0x0000,0x0000, 0x1221,0x0000,0x0000, 0x1235,0x0000,0x0000, /* 0251 */ +0x139A,0x0000,0x0000, 0x124A,0x0000,0x0000, 0x1258,0x0000,0x0000, /* 0254 */ +0x125C,0x0000,0x0000, 0x1285,0x0000,0x0000, 0x127B,0x0000,0x0000, /* 0257 */ +0x1289,0x0000,0x0000, 0x1280,0x0000,0x0000, 0x128D,0x0000,0x0000, /* 025A */ +0x1293,0x0000,0x0000, 0x1297,0x0000,0x0000, 0x1316,0x0000,0x0000, /* 025D */ +0x12C1,0x0000,0x0000, 0x12B4,0x0000,0x0000, 0x12B8,0x0000,0x0000, /* 0260 */ +0x12CB,0x0000,0x0000, 0x129F,0x0000,0x0000, 0x1461,0x0000,0x0000, /* 0263 */ +0x12DF,0x0000,0x0000, 0x12E6,0x0000,0x0000, 0x12FA,0x0000,0x0000, /* 0266 */ +0x1300,0x0000,0x0000, 0x12F4,0x0000,0x0000, 0x1340,0x0000,0x0000, /* 0269 */ +0x1344,0x0000,0x0000, 0x1349,0x0000,0x0000, 0x1352,0x0000,0x0000, /* 026C */ +0x146D,0x0000,0x0000, 0x1472,0x0000,0x0000, 0x1366,0x0000,0x0000, /* 026F */ +0x1378,0x0000,0x0000, 0x1381,0x0000,0x0000, 0x1371,0x0000,0x0000, /* 0272 */ +0x13A5,0x0000,0x0000, 0x1394,0x0000,0x0000, 0x13AA,0x0000,0x0000, /* 0275 */ +0x13C3,0x0000,0x0000, 0x13E9,0x0000,0x0000, 0x13EE,0x0000,0x0000, /* 0278 */ +0x13F3,0x0000,0x0000, 0x13F8,0x0000,0x0000, 0x13FC,0x0000,0x0000, /* 027B */ +0x1400,0x0000,0x0000, 0x1405,0x0000,0x0000, 0x13DE,0x0000,0x0000, /* 027E */ +0x1409,0x0000,0x0000, 0x1417,0x0000,0x0000, 0x1421,0x0000,0x0000, /* 0281 */ +0x131A,0x0000,0x0000, 0x142A,0x0000,0x0000, 0x142F,0x0000,0x0000, /* 0284 */ +0x144F,0x0000,0x0000, 0x1446,0x0000,0x0000, 0x145B,0x0000,0x0000, /* 0287 */ +0x1476,0x0000,0x0000, 0x1482,0x0000,0x0000, 0x1489,0x0000,0x0000, /* 028A */ +0x1493,0x0000,0x0000, 0x135B,0x0000,0x0000, 0x14A0,0x0000,0x0000, /* 028D */ +0x14BC,0x0000,0x0000, 0x14C0,0x0000,0x0000, 0x14CA,0x0000,0x0000, /* 0290 */ +0x14D8,0x0000,0x0000, 0x1502,0x0000,0x0000, 0x1510,0x0000,0x0000, /* 0293 */ +0x1521,0x0000,0x0000, 0x1535,0x0000,0x0000, 0x1539,0x0000,0x0000, /* 0296 */ +0x1229,0x0000,0x0000, 0x129B,0x0000,0x0000, 0x12C5,0x0000,0x0000, /* 0299 */ +0x12D7,0x0000,0x0000, 0x1312,0x0000,0x0000, 0x132C,0x0000,0x0000, /* 029C */ +0x1334,0x0000,0x0000, 0x13CE,0x0000,0x0000, 0x1519,0x0000,0x0000, /* 029F */ +0x151D,0x0000,0x0000, 0x1250,0x14AD,0x0000, 0x1250,0x14CA,0x0000, /* 02A2 */ +0x1250,0x14C0,0x0000, 0x1433,0x1410,0x0000, 0x1433,0x1421,0x0000, /* 02A5 */ +0x1433,0x124A,0x0000, 0x12A3,0x138A,0x0000, 0x1330,0x1410,0x0000, /* 02A8 */ +0x1330,0x14AD,0x0000, 0x153D,0x0000,0x0000, 0x1541,0x0000,0x0000, /* 02AB */ +0x1465,0x0000,0x0000, 0x1469,0x0000,0x0000, 0x12D3,0x0000,0x0000, /* 02AE */ +0x12DF,0x0000,0x0000, 0x1305,0x0000,0x0000, 0x13DA,0x0000,0x0000, /* 02B1 */ +0x13E9,0x0000,0x0000, 0x13F3,0x0000,0x0000, 0x1409,0x0000,0x0000, /* 02B4 */ +0x148D,0x0000,0x0000, 0x149C,0x0000,0x0000, 0x03E9,0x0000,0x0000, /* 02B7 */ +0x03EB,0x0000,0x0000, 0x12EA,0x0000,0x0000, 0x150B,0x0000,0x0000, /* 02BA */ +0x12EB,0x0000,0x0000, 0x150D,0x0000,0x0000, 0x1514,0x0000,0x0000, /* 02BD */ +0x150A,0x0000,0x0000, 0x1515,0x0000,0x0000, 0x03EC,0x0000,0x0000, /* 02C0 */ +0x03ED,0x0000,0x0000, 0x03EE,0x0000,0x0000, 0x03EF,0x0000,0x0000, /* 02C3 */ +0x03F0,0x0000,0x0000, 0x03F1,0x0000,0x0000, 0x03F2,0x0000,0x0000, /* 02C6 */ +0x03F3,0x0000,0x0000, 0x03F4,0x0000,0x0000, 0x03F5,0x0000,0x0000, /* 02C9 */ +0x03F6,0x0000,0x0000, 0x03F7,0x0000,0x0000, 0x03F8,0x0000,0x0000, /* 02CC */ +0x03F9,0x0000,0x0000, 0x11CE,0x0000,0x0000, 0x11CF,0x0000,0x0000, /* 02CF */ +0x03FA,0x0000,0x0000, 0x03FB,0x0000,0x0000, 0x03FC,0x0000,0x0000, /* 02D2 */ +0x03FD,0x0000,0x0000, 0x03FE,0x0000,0x0000, 0x03FF,0x0000,0x0000, /* 02D5 */ +0x0214,0x0000,0x0000, 0x0215,0x0000,0x0000, 0x0217,0x0000,0x0000, /* 02D8 */ +0x021C,0x0000,0x0000, 0x0210,0x0000,0x0000, 0x0218,0x0000,0x0000, /* 02DB */ +0x0400,0x0000,0x0000, 0x0401,0x0000,0x0000, 0x12CB,0x0000,0x0000, /* 02DE */ +0x1330,0x0000,0x0000, 0x1410,0x0000,0x0000, 0x1497,0x0000,0x0000, /* 02E1 */ +0x1510,0x0000,0x0000, 0x0402,0x0000,0x0000, 0x0403,0x0000,0x0000, /* 02E4 */ +0x0404,0x0000,0x0000, 0x0405,0x0000,0x0000, 0x0406,0x0000,0x0000, /* 02E7 */ +0x0407,0x0000,0x0000, 0x0408,0x0000,0x0000, 0x0409,0x0000,0x0000, /* 02EA */ +0x040A,0x0000,0x0000, 0x150C,0x0000,0x0000, 0x040B,0x0000,0x0000, /* 02ED */ +0x040C,0x0000,0x0000, 0x040D,0x0000,0x0000, 0x040E,0x0000,0x0000, /* 02F0 */ +0x040F,0x0000,0x0000, 0x0410,0x0000,0x0000, 0x0411,0x0000,0x0000, /* 02F3 */ +0x0412,0x0000,0x0000, 0x0413,0x0000,0x0000, 0x0414,0x0000,0x0000, /* 02F6 */ +0x0415,0x0000,0x0000, 0x0416,0x0000,0x0000, 0x0417,0x0000,0x0000, /* 02F9 */ +0x0418,0x0000,0x0000, 0x0419,0x0000,0x0000, 0x041A,0x0000,0x0000, /* 02FC */ +0x041B,0x0000,0x0000 }; + +uint16 uca520_p003[]= { /* 0300 (4 weights per char) */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0300 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0302 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0304 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0306 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0308 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 030A */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 030C */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 030E */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0310 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0312 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0314 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0316 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0318 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 031A */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 031C */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 031E */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0320 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0322 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0324 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0326 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0328 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 032A */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 032C */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 032E */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0330 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0332 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0334 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0336 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0338 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 033A */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 033C */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 033E */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0340 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0342 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0344 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0346 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0348 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 034A */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 034C */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 034E */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0350 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0352 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0354 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0356 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0358 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 035A */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 035C */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 035E */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 0360 */ +0x0000,0x0000,0x0000,0x0000, 0x120F,0x0000,0x0000,0x0000, /* 0362 */ +0x126B,0x0000,0x0000,0x0000, 0x12EC,0x0000,0x0000,0x0000, /* 0364 */ +0x138E,0x0000,0x0000,0x0000, 0x1453,0x0000,0x0000,0x0000, /* 0366 */ +0x123D,0x0000,0x0000,0x0000, 0x1250,0x0000,0x0000,0x0000, /* 0368 */ +0x12D3,0x0000,0x0000,0x0000, 0x135F,0x0000,0x0000,0x0000, /* 036A */ +0x13DA,0x0000,0x0000,0x0000, 0x1433,0x0000,0x0000,0x0000, /* 036C */ +0x147B,0x0000,0x0000,0x0000, 0x1497,0x0000,0x0000,0x0000, /* 036E */ +0x154F,0x0000,0x0000,0x0000, 0x154F,0x0000,0x0000,0x0000, /* 0370 */ +0x156F,0x0000,0x0000,0x0000, 0x156F,0x0000,0x0000,0x0000, /* 0372 */ +0x03E9,0x0000,0x0000,0x0000, 0x03EA,0x0000,0x0000,0x0000, /* 0374 */ +0x154C,0x0000,0x0000,0x0000, 0x154C,0x0000,0x0000,0x0000, /* 0376 */ +0xFBC0,0x8378,0x0000,0x0000, 0xFBC0,0x8379,0x0000,0x0000, /* 0378 */ +0x1552,0x0000,0x0000,0x0000, 0x1565,0x0000,0x0000,0x0000, /* 037A */ +0x1564,0x0000,0x0000,0x0000, 0x1566,0x0000,0x0000,0x0000, /* 037C */ +0x0243,0x0000,0x0000,0x0000, 0xFBC0,0x837F,0x0000,0x0000, /* 037E */ +0xFBC0,0x8380,0x0000,0x0000, 0xFBC0,0x8381,0x0000,0x0000, /* 0380 */ +0xFBC0,0x8382,0x0000,0x0000, 0xFBC0,0x8383,0x0000,0x0000, /* 0382 */ +0x020F,0x0000,0x0000,0x0000, 0x0216,0x0000,0x0000,0x0000, /* 0384 */ +0x1545,0x0000,0x0000,0x0000, 0x0292,0x0000,0x0000,0x0000, /* 0386 */ +0x154A,0x0000,0x0000,0x0000, 0x1550,0x0000,0x0000,0x0000, /* 0388 */ +0x1552,0x0000,0x0000,0x0000, 0xFBC0,0x838B,0x0000,0x0000, /* 038A */ +0x155A,0x0000,0x0000,0x0000, 0xFBC0,0x838D,0x0000,0x0000, /* 038C */ +0x1568,0x0000,0x0000,0x0000, 0x156D,0x0000,0x0000,0x0000, /* 038E */ +0x1552,0x0000,0x0000,0x0000, 0x1545,0x0000,0x0000,0x0000, /* 0390 */ +0x1546,0x0000,0x0000,0x0000, 0x1547,0x0000,0x0000,0x0000, /* 0392 */ +0x1549,0x0000,0x0000,0x0000, 0x154A,0x0000,0x0000,0x0000, /* 0394 */ +0x154E,0x0000,0x0000,0x0000, 0x1550,0x0000,0x0000,0x0000, /* 0396 */ +0x1551,0x0000,0x0000,0x0000, 0x1552,0x0000,0x0000,0x0000, /* 0398 */ +0x1554,0x0000,0x0000,0x0000, 0x1555,0x0000,0x0000,0x0000, /* 039A */ +0x1557,0x0000,0x0000,0x0000, 0x1558,0x0000,0x0000,0x0000, /* 039C */ +0x1559,0x0000,0x0000,0x0000, 0x155A,0x0000,0x0000,0x0000, /* 039E */ +0x155B,0x0000,0x0000,0x0000, 0x1560,0x0000,0x0000,0x0000, /* 03A0 */ +0xFBC0,0x83A2,0x0000,0x0000, 0x1563,0x0000,0x0000,0x0000, /* 03A2 */ +0x1567,0x0000,0x0000,0x0000, 0x1568,0x0000,0x0000,0x0000, /* 03A4 */ +0x1569,0x0000,0x0000,0x0000, 0x156A,0x0000,0x0000,0x0000, /* 03A6 */ +0x156B,0x0000,0x0000,0x0000, 0x156D,0x0000,0x0000,0x0000, /* 03A8 */ +0x1552,0x0000,0x0000,0x0000, 0x1568,0x0000,0x0000,0x0000, /* 03AA */ +0x1545,0x0000,0x0000,0x0000, 0x154A,0x0000,0x0000,0x0000, /* 03AC */ +0x1550,0x0000,0x0000,0x0000, 0x1552,0x0000,0x0000,0x0000, /* 03AE */ +0x1568,0x0000,0x0000,0x0000, 0x1545,0x0000,0x0000,0x0000, /* 03B0 */ +0x1546,0x0000,0x0000,0x0000, 0x1547,0x0000,0x0000,0x0000, /* 03B2 */ +0x1549,0x0000,0x0000,0x0000, 0x154A,0x0000,0x0000,0x0000, /* 03B4 */ +0x154E,0x0000,0x0000,0x0000, 0x1550,0x0000,0x0000,0x0000, /* 03B6 */ +0x1551,0x0000,0x0000,0x0000, 0x1552,0x0000,0x0000,0x0000, /* 03B8 */ +0x1554,0x0000,0x0000,0x0000, 0x1555,0x0000,0x0000,0x0000, /* 03BA */ +0x1557,0x0000,0x0000,0x0000, 0x1558,0x0000,0x0000,0x0000, /* 03BC */ +0x1559,0x0000,0x0000,0x0000, 0x155A,0x0000,0x0000,0x0000, /* 03BE */ +0x155B,0x0000,0x0000,0x0000, 0x1560,0x0000,0x0000,0x0000, /* 03C0 */ +0x1563,0x0000,0x0000,0x0000, 0x1563,0x0000,0x0000,0x0000, /* 03C2 */ +0x1567,0x0000,0x0000,0x0000, 0x1568,0x0000,0x0000,0x0000, /* 03C4 */ +0x1569,0x0000,0x0000,0x0000, 0x156A,0x0000,0x0000,0x0000, /* 03C6 */ +0x156B,0x0000,0x0000,0x0000, 0x156D,0x0000,0x0000,0x0000, /* 03C8 */ +0x1552,0x0000,0x0000,0x0000, 0x1568,0x0000,0x0000,0x0000, /* 03CA */ +0x155A,0x0000,0x0000,0x0000, 0x1568,0x0000,0x0000,0x0000, /* 03CC */ +0x156D,0x0000,0x0000,0x0000, 0x1554,0x1545,0x1552,0x0000, /* 03CE */ +0x1546,0x0000,0x0000,0x0000, 0x1551,0x0000,0x0000,0x0000, /* 03D0 */ +0x1568,0x0000,0x0000,0x0000, 0x1568,0x0000,0x0000,0x0000, /* 03D2 */ +0x1568,0x0000,0x0000,0x0000, 0x1569,0x0000,0x0000,0x0000, /* 03D4 */ +0x155B,0x0000,0x0000,0x0000, 0x1554,0x1545,0x1552,0x0000, /* 03D6 */ +0x155F,0x0000,0x0000,0x0000, 0x155F,0x0000,0x0000,0x0000, /* 03D8 */ +0x154D,0x0000,0x0000,0x0000, 0x154D,0x0000,0x0000,0x0000, /* 03DA */ +0x154B,0x0000,0x0000,0x0000, 0x154B,0x0000,0x0000,0x0000, /* 03DC */ +0x155E,0x0000,0x0000,0x0000, 0x155E,0x0000,0x0000,0x0000, /* 03DE */ +0x156E,0x0000,0x0000,0x0000, 0x156E,0x0000,0x0000,0x0000, /* 03E0 */ +0x1590,0x0000,0x0000,0x0000, 0x1590,0x0000,0x0000,0x0000, /* 03E2 */ +0x1595,0x0000,0x0000,0x0000, 0x1595,0x0000,0x0000,0x0000, /* 03E4 */ +0x1596,0x0000,0x0000,0x0000, 0x1596,0x0000,0x0000,0x0000, /* 03E6 */ +0x1598,0x0000,0x0000,0x0000, 0x1598,0x0000,0x0000,0x0000, /* 03E8 */ +0x159F,0x0000,0x0000,0x0000, 0x159F,0x0000,0x0000,0x0000, /* 03EA */ +0x15A2,0x0000,0x0000,0x0000, 0x15A2,0x0000,0x0000,0x0000, /* 03EC */ +0x15A6,0x0000,0x0000,0x0000, 0x15A6,0x0000,0x0000,0x0000, /* 03EE */ +0x1554,0x0000,0x0000,0x0000, 0x1560,0x0000,0x0000,0x0000, /* 03F0 */ +0x1563,0x0000,0x0000,0x0000, 0x1553,0x0000,0x0000,0x0000, /* 03F2 */ +0x1551,0x0000,0x0000,0x0000, 0x154A,0x0000,0x0000,0x0000, /* 03F4 */ +0x054B,0x0000,0x0000,0x0000, 0x1570,0x0000,0x0000,0x0000, /* 03F6 */ +0x1570,0x0000,0x0000,0x0000, 0x1563,0x0000,0x0000,0x0000, /* 03F8 */ +0x155D,0x0000,0x0000,0x0000, 0x155D,0x0000,0x0000,0x0000, /* 03FA */ +0x1562,0x0000,0x0000,0x0000, 0x1565,0x0000,0x0000,0x0000, /* 03FC */ +0x1564,0x0000,0x0000,0x0000, 0x1566,0x0000,0x0000,0x0000 /* 03FE */ +}; + +uint16 uca520_p004[]= { /* 0400 (2 weights per char) */ +0x15F4,0x0000, 0x15F4,0x0000, 0x15E6,0x0000, 0x15EC,0x0000, /* 0400 */ +0x15FC,0x0000, 0x1619,0x0000, 0x1631,0x0000, 0x1636,0x0000, /* 0404 */ +0x163E,0x0000, 0x1668,0x0000, 0x168D,0x0000, 0x16CC,0x0000, /* 0408 */ +0x16D0,0x0000, 0x1625,0x0000, 0x16D8,0x0000, 0x1743,0x0000, /* 040C */ +0x15AC,0x0000, 0x15C4,0x0000, 0x15C8,0x0000, 0x15CC,0x0000, /* 0410 */ +0x15E0,0x0000, 0x15F4,0x0000, 0x1600,0x0000, 0x160D,0x0000, /* 0414 */ +0x1625,0x0000, 0x163A,0x0000, 0x1643,0x0000, 0x165D,0x0000, /* 0418 */ +0x166F,0x0000, 0x1678,0x0000, 0x1692,0x0000, 0x16A2,0x0000, /* 041C */ +0x16AF,0x0000, 0x16B8,0x0000, 0x16C1,0x0000, 0x16D4,0x0000, /* 0420 */ +0x16F1,0x0000, 0x16F5,0x0000, 0x171B,0x0000, 0x1725,0x0000, /* 0424 */ +0x1747,0x0000, 0x174C,0x0000, 0x1753,0x0000, 0x1758,0x0000, /* 0428 */ +0x1760,0x0000, 0x176D,0x0000, 0x1775,0x0000, 0x177B,0x0000, /* 042C */ +0x15AC,0x0000, 0x15C4,0x0000, 0x15C8,0x0000, 0x15CC,0x0000, /* 0430 */ +0x15E0,0x0000, 0x15F4,0x0000, 0x1600,0x0000, 0x160D,0x0000, /* 0434 */ +0x1625,0x0000, 0x163A,0x0000, 0x1643,0x0000, 0x165D,0x0000, /* 0438 */ +0x166F,0x0000, 0x1678,0x0000, 0x1692,0x0000, 0x16A2,0x0000, /* 043C */ +0x16AF,0x0000, 0x16B8,0x0000, 0x16C1,0x0000, 0x16D4,0x0000, /* 0440 */ +0x16F1,0x0000, 0x16F5,0x0000, 0x171B,0x0000, 0x1725,0x0000, /* 0444 */ +0x1747,0x0000, 0x174C,0x0000, 0x1753,0x0000, 0x1758,0x0000, /* 0448 */ +0x1760,0x0000, 0x176D,0x0000, 0x1775,0x0000, 0x177B,0x0000, /* 044C */ +0x15F4,0x0000, 0x15F4,0x0000, 0x15E6,0x0000, 0x15EC,0x0000, /* 0450 */ +0x15FC,0x0000, 0x1619,0x0000, 0x1631,0x0000, 0x1636,0x0000, /* 0454 */ +0x163E,0x0000, 0x1668,0x0000, 0x168D,0x0000, 0x16CC,0x0000, /* 0458 */ +0x16D0,0x0000, 0x1625,0x0000, 0x16D8,0x0000, 0x1743,0x0000, /* 045C */ +0x170A,0x0000, 0x170A,0x0000, 0x1768,0x0000, 0x1768,0x0000, /* 0460 */ +0x1780,0x0000, 0x1780,0x0000, 0x1784,0x0000, 0x1784,0x0000, /* 0464 */ +0x178E,0x0000, 0x178E,0x0000, 0x1789,0x0000, 0x1789,0x0000, /* 0468 */ +0x1793,0x0000, 0x1793,0x0000, 0x1797,0x0000, 0x1797,0x0000, /* 046C */ +0x179B,0x0000, 0x179B,0x0000, 0x179F,0x0000, 0x179F,0x0000, /* 0470 */ +0x17A3,0x0000, 0x17A3,0x0000, 0x17A7,0x0000, 0x17A7,0x0000, /* 0474 */ +0x16ED,0x0000, 0x16ED,0x0000, 0x1717,0x0000, 0x1717,0x0000, /* 0478 */ +0x1713,0x0000, 0x1713,0x0000, 0x170E,0x0000, 0x170E,0x0000, /* 047C */ +0x16AB,0x0000, 0x16AB,0x0000, 0x044C,0x0000, 0x0000,0x0000, /* 0480 */ +0x0000,0x0000, 0x0000,0x0000, 0x0000,0x0000, 0x0000,0x0000, /* 0484 */ +0x0000,0x0000, 0x0000,0x0000, 0x1629,0x0000, 0x1629,0x0000, /* 0488 */ +0x1764,0x0000, 0x1764,0x0000, 0x16B3,0x0000, 0x16B3,0x0000, /* 048C */ +0x15CC,0x0000, 0x15CC,0x0000, 0x15D0,0x0000, 0x15D0,0x0000, /* 0490 */ +0x15D8,0x0000, 0x15D8,0x0000, 0x1609,0x0000, 0x1609,0x0000, /* 0494 */ +0x15F0,0x0000, 0x15F0,0x0000, 0x1647,0x0000, 0x1647,0x0000, /* 0498 */ +0x1657,0x0000, 0x1657,0x0000, 0x1653,0x0000, 0x1653,0x0000, /* 049C */ +0x164F,0x0000, 0x164F,0x0000, 0x1680,0x0000, 0x1680,0x0000, /* 04A0 */ +0x1689,0x0000, 0x1689,0x0000, 0x16A7,0x0000, 0x16A7,0x0000, /* 04A4 */ +0x17AC,0x0000, 0x17AC,0x0000, 0x16BD,0x0000, 0x16BD,0x0000, /* 04A8 */ +0x16C7,0x0000, 0x16C7,0x0000, 0x16E4,0x0000, 0x16E4,0x0000, /* 04AC */ +0x16E8,0x0000, 0x16E8,0x0000, 0x1701,0x0000, 0x1701,0x0000, /* 04B0 */ +0x1720,0x0000, 0x1720,0x0000, 0x172E,0x0000, 0x172E,0x0000, /* 04B4 */ +0x1736,0x0000, 0x1736,0x0000, 0x1705,0x0000, 0x1705,0x0000, /* 04B8 */ +0x173B,0x0000, 0x173B,0x0000, 0x173F,0x0000, 0x173F,0x0000, /* 04BC */ +0x17B1,0x0000, 0x1600,0x0000, 0x1600,0x0000, 0x164B,0x0000, /* 04C0 */ +0x164B,0x0000, 0x1662,0x0000, 0x1662,0x0000, 0x1684,0x0000, /* 04C4 */ +0x1684,0x0000, 0x167C,0x0000, 0x167C,0x0000, 0x1732,0x0000, /* 04C8 */ +0x1732,0x0000, 0x1673,0x0000, 0x1673,0x0000, 0x17B1,0x0000, /* 04CC */ +0x15B0,0x0000, 0x15B0,0x0000, 0x15B4,0x0000, 0x15B4,0x0000, /* 04D0 */ +0x15C0,0x0000, 0x15C0,0x0000, 0x15F8,0x0000, 0x15F8,0x0000, /* 04D4 */ +0x15B8,0x0000, 0x15B8,0x0000, 0x15BC,0x0000, 0x15BC,0x0000, /* 04D8 */ +0x1605,0x0000, 0x1605,0x0000, 0x1614,0x0000, 0x1614,0x0000, /* 04DC */ +0x161E,0x0000, 0x161E,0x0000, 0x1625,0x0000, 0x1625,0x0000, /* 04E0 */ +0x162D,0x0000, 0x162D,0x0000, 0x1696,0x0000, 0x1696,0x0000, /* 04E4 */ +0x169A,0x0000, 0x169A,0x0000, 0x169E,0x0000, 0x169E,0x0000, /* 04E8 */ +0x1771,0x0000, 0x1771,0x0000, 0x16D4,0x0000, 0x16D4,0x0000, /* 04EC */ +0x16DC,0x0000, 0x16DC,0x0000, 0x16E0,0x0000, 0x16E0,0x0000, /* 04F0 */ +0x172A,0x0000, 0x172A,0x0000, 0x15DC,0x0000, 0x15DC,0x0000, /* 04F4 */ +0x175C,0x0000, 0x175C,0x0000, 0x15D4,0x0000, 0x15D4,0x0000, /* 04F8 */ +0x16F9,0x0000, 0x16F9,0x0000, 0x16FD,0x0000, 0x16FD,0x0000 /* 04FC */ +}; + +uint16 uca520_p005[]= { /* 0500 (3 weights per char) */ +0x15E4,0x0000,0x0000, 0x15E4,0x0000,0x0000, 0x15EB,0x0000,0x0000, /* 0500 */ +0x15EB,0x0000,0x0000, 0x1612,0x0000,0x0000, 0x1612,0x0000,0x0000, /* 0503 */ +0x1623,0x0000,0x0000, 0x1623,0x0000,0x0000, 0x166D,0x0000,0x0000, /* 0506 */ +0x166D,0x0000,0x0000, 0x1691,0x0000,0x0000, 0x1691,0x0000,0x0000, /* 0509 */ +0x16BC,0x0000,0x0000, 0x16BC,0x0000,0x0000, 0x16C6,0x0000,0x0000, /* 050C */ +0x16C6,0x0000,0x0000, 0x1613,0x0000,0x0000, 0x1613,0x0000,0x0000, /* 050F */ +0x1666,0x0000,0x0000, 0x1666,0x0000,0x0000, 0x166E,0x0000,0x0000, /* 0512 */ +0x166E,0x0000,0x0000, 0x16B7,0x0000,0x0000, 0x16B7,0x0000,0x0000, /* 0515 */ +0x177F,0x0000,0x0000, 0x177F,0x0000,0x0000, 0x165C,0x0000,0x0000, /* 0518 */ +0x165C,0x0000,0x0000, 0x17B0,0x0000,0x0000, 0x17B0,0x0000,0x0000, /* 051B */ +0x165B,0x0000,0x0000, 0x165B,0x0000,0x0000, 0x1667,0x0000,0x0000, /* 051E */ +0x1667,0x0000,0x0000, 0x1688,0x0000,0x0000, 0x1688,0x0000,0x0000, /* 0521 */ +0x16A6,0x0000,0x0000, 0x16A6,0x0000,0x0000, 0xFBC0,0x8526,0x0000, /* 0524 */ +0xFBC0,0x8527,0x0000, 0xFBC0,0x8528,0x0000, 0xFBC0,0x8529,0x0000, /* 0527 */ +0xFBC0,0x852A,0x0000, 0xFBC0,0x852B,0x0000, 0xFBC0,0x852C,0x0000, /* 052A */ +0xFBC0,0x852D,0x0000, 0xFBC0,0x852E,0x0000, 0xFBC0,0x852F,0x0000, /* 052D */ +0xFBC0,0x8530,0x0000, 0x1835,0x0000,0x0000, 0x1836,0x0000,0x0000, /* 0530 */ +0x1837,0x0000,0x0000, 0x1838,0x0000,0x0000, 0x1839,0x0000,0x0000, /* 0533 */ +0x183A,0x0000,0x0000, 0x183B,0x0000,0x0000, 0x183C,0x0000,0x0000, /* 0536 */ +0x183D,0x0000,0x0000, 0x183E,0x0000,0x0000, 0x183F,0x0000,0x0000, /* 0539 */ +0x1840,0x0000,0x0000, 0x1841,0x0000,0x0000, 0x1842,0x0000,0x0000, /* 053C */ +0x1843,0x0000,0x0000, 0x1844,0x0000,0x0000, 0x1845,0x0000,0x0000, /* 053F */ +0x1846,0x0000,0x0000, 0x1847,0x0000,0x0000, 0x1848,0x0000,0x0000, /* 0542 */ +0x1849,0x0000,0x0000, 0x184A,0x0000,0x0000, 0x184B,0x0000,0x0000, /* 0545 */ +0x184C,0x0000,0x0000, 0x184D,0x0000,0x0000, 0x184E,0x0000,0x0000, /* 0548 */ +0x184F,0x0000,0x0000, 0x1850,0x0000,0x0000, 0x1851,0x0000,0x0000, /* 054B */ +0x1852,0x0000,0x0000, 0x1853,0x0000,0x0000, 0x1854,0x0000,0x0000, /* 054E */ +0x1855,0x0000,0x0000, 0x1856,0x0000,0x0000, 0x1857,0x0000,0x0000, /* 0551 */ +0x1858,0x0000,0x0000, 0x1859,0x0000,0x0000, 0x185A,0x0000,0x0000, /* 0554 */ +0xFBC0,0x8557,0x0000, 0xFBC0,0x8558,0x0000, 0x185B,0x0000,0x0000, /* 0557 */ +0x0392,0x0000,0x0000, 0x0393,0x0000,0x0000, 0x0270,0x0000,0x0000, /* 055A */ +0x0235,0x0000,0x0000, 0x0276,0x0000,0x0000, 0x0394,0x0000,0x0000, /* 055D */ +0xFBC0,0x8560,0x0000, 0x1835,0x0000,0x0000, 0x1836,0x0000,0x0000, /* 0560 */ +0x1837,0x0000,0x0000, 0x1838,0x0000,0x0000, 0x1839,0x0000,0x0000, /* 0563 */ +0x183A,0x0000,0x0000, 0x183B,0x0000,0x0000, 0x183C,0x0000,0x0000, /* 0566 */ +0x183D,0x0000,0x0000, 0x183E,0x0000,0x0000, 0x183F,0x0000,0x0000, /* 0569 */ +0x1840,0x0000,0x0000, 0x1841,0x0000,0x0000, 0x1842,0x0000,0x0000, /* 056C */ +0x1843,0x0000,0x0000, 0x1844,0x0000,0x0000, 0x1845,0x0000,0x0000, /* 056F */ +0x1846,0x0000,0x0000, 0x1847,0x0000,0x0000, 0x1848,0x0000,0x0000, /* 0572 */ +0x1849,0x0000,0x0000, 0x184A,0x0000,0x0000, 0x184B,0x0000,0x0000, /* 0575 */ +0x184C,0x0000,0x0000, 0x184D,0x0000,0x0000, 0x184E,0x0000,0x0000, /* 0578 */ +0x184F,0x0000,0x0000, 0x1850,0x0000,0x0000, 0x1851,0x0000,0x0000, /* 057B */ +0x1852,0x0000,0x0000, 0x1853,0x0000,0x0000, 0x1854,0x0000,0x0000, /* 057E */ +0x1855,0x0000,0x0000, 0x1856,0x0000,0x0000, 0x1857,0x0000,0x0000, /* 0581 */ +0x1858,0x0000,0x0000, 0x1859,0x0000,0x0000, 0x185A,0x0000,0x0000, /* 0584 */ +0x1839,0x1856,0x0000, 0xFBC0,0x8588,0x0000, 0x0248,0x0000,0x0000, /* 0587 */ +0x0224,0x0000,0x0000, 0xFBC0,0x858B,0x0000, 0xFBC0,0x858C,0x0000, /* 058A */ +0xFBC0,0x858D,0x0000, 0xFBC0,0x858E,0x0000, 0xFBC0,0x858F,0x0000, /* 058D */ +0xFBC0,0x8590,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0590 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0593 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0596 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0599 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 059C */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 059F */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 05A2 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 05A5 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 05A8 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 05AB */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 05AE */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 05B1 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 05B4 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 05B7 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 05BA */ +0x0000,0x0000,0x0000, 0x0395,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 05BD */ +0x0396,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 05C0 */ +0x0397,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 05C3 */ +0x0398,0x0000,0x0000, 0x0000,0x0000,0x0000, 0xFBC0,0x85C8,0x0000, /* 05C6 */ +0xFBC0,0x85C9,0x0000, 0xFBC0,0x85CA,0x0000, 0xFBC0,0x85CB,0x0000, /* 05C9 */ +0xFBC0,0x85CC,0x0000, 0xFBC0,0x85CD,0x0000, 0xFBC0,0x85CE,0x0000, /* 05CC */ +0xFBC0,0x85CF,0x0000, 0x185C,0x0000,0x0000, 0x185D,0x0000,0x0000, /* 05CF */ +0x185E,0x0000,0x0000, 0x185F,0x0000,0x0000, 0x1860,0x0000,0x0000, /* 05D2 */ +0x1861,0x0000,0x0000, 0x1862,0x0000,0x0000, 0x1863,0x0000,0x0000, /* 05D5 */ +0x1864,0x0000,0x0000, 0x1865,0x0000,0x0000, 0x1866,0x0000,0x0000, /* 05D8 */ +0x1866,0x0000,0x0000, 0x1867,0x0000,0x0000, 0x1868,0x0000,0x0000, /* 05DB */ +0x1868,0x0000,0x0000, 0x1869,0x0000,0x0000, 0x1869,0x0000,0x0000, /* 05DE */ +0x186A,0x0000,0x0000, 0x186B,0x0000,0x0000, 0x186C,0x0000,0x0000, /* 05E1 */ +0x186C,0x0000,0x0000, 0x186D,0x0000,0x0000, 0x186D,0x0000,0x0000, /* 05E4 */ +0x186E,0x0000,0x0000, 0x186F,0x0000,0x0000, 0x1870,0x0000,0x0000, /* 05E7 */ +0x1871,0x0000,0x0000, 0xFBC0,0x85EB,0x0000, 0xFBC0,0x85EC,0x0000, /* 05EA */ +0xFBC0,0x85ED,0x0000, 0xFBC0,0x85EE,0x0000, 0xFBC0,0x85EF,0x0000, /* 05ED */ +0x1861,0x1861,0x0000, 0x1861,0x1865,0x0000, 0x1865,0x1865,0x0000, /* 05F0 */ +0x0399,0x0000,0x0000, 0x039A,0x0000,0x0000, 0xFBC0,0x85F5,0x0000, /* 05F3 */ +0xFBC0,0x85F6,0x0000, 0xFBC0,0x85F7,0x0000, 0xFBC0,0x85F8,0x0000, /* 05F6 */ +0xFBC0,0x85F9,0x0000, 0xFBC0,0x85FA,0x0000, 0xFBC0,0x85FB,0x0000, /* 05F9 */ +0xFBC0,0x85FC,0x0000, 0xFBC0,0x85FD,0x0000, 0xFBC0,0x85FE,0x0000, /* 05FC */ +0xFBC0,0x85FF,0x0000 }; + +uint16 uca520_p006[]= { /* 0600 (3 weights per char) */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0600 */ +0x0000,0x0000,0x0000, 0xFBC0,0x8604,0x0000, 0xFBC0,0x8605,0x0000, /* 0603 */ +0x0566,0x0000,0x0000, 0x0568,0x0000,0x0000, 0x044D,0x0000,0x0000, /* 0606 */ +0x0366,0x0000,0x0000, 0x0368,0x0000,0x0000, 0x11E4,0x0000,0x0000, /* 0609 */ +0x0236,0x0000,0x0000, 0x0237,0x0000,0x0000, 0x044E,0x0000,0x0000, /* 060C */ +0x044F,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 060F */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0612 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0615 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0618 */ +0x0244,0x0000,0x0000, 0xFBC0,0x861C,0x0000, 0xFBC0,0x861D,0x0000, /* 061B */ +0x0249,0x0000,0x0000, 0x0277,0x0000,0x0000, 0xFBC0,0x8620,0x0000, /* 061E */ +0x18A2,0x0000,0x0000, 0x18A3,0x0000,0x0000, 0x18A4,0x0000,0x0000, /* 0621 */ +0x18A7,0x0000,0x0000, 0x18A8,0x0000,0x0000, 0x18AC,0x0000,0x0000, /* 0624 */ +0x18AD,0x0000,0x0000, 0x18AF,0x0000,0x0000, 0x18BA,0x0000,0x0000, /* 0627 */ +0x18BB,0x0000,0x0000, 0x18BC,0x0000,0x0000, 0x18C2,0x0000,0x0000, /* 062A */ +0x18C8,0x0000,0x0000, 0x18C9,0x0000,0x0000, 0x18D3,0x0000,0x0000, /* 062D */ +0x18D4,0x0000,0x0000, 0x18E1,0x0000,0x0000, 0x18E2,0x0000,0x0000, /* 0630 */ +0x18F1,0x0000,0x0000, 0x18F2,0x0000,0x0000, 0x18FC,0x0000,0x0000, /* 0633 */ +0x18FD,0x0000,0x0000, 0x1901,0x0000,0x0000, 0x1902,0x0000,0x0000, /* 0636 */ +0x1904,0x0000,0x0000, 0x1905,0x0000,0x0000, 0x1927,0x0000,0x0000, /* 0639 */ +0x1928,0x0000,0x0000, 0x1956,0x0000,0x0000, 0x1957,0x0000,0x0000, /* 063C */ +0x1958,0x0000,0x0000, 0x020C,0x0000,0x0000, 0x190B,0x0000,0x0000, /* 063F */ +0x1915,0x0000,0x0000, 0x1918,0x0000,0x0000, 0x192B,0x0000,0x0000, /* 0642 */ +0x1931,0x0000,0x0000, 0x1934,0x0000,0x0000, 0x193D,0x0000,0x0000, /* 0645 */ +0x1943,0x0000,0x0000, 0x194F,0x0000,0x0000, 0x1950,0x0000,0x0000, /* 0648 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 064B */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 064E */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0651 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0654 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0657 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 065A */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0xFBC0,0x865F,0x0000, /* 065D */ +0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 0660 */ +0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, /* 0663 */ +0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, /* 0666 */ +0x120E,0x0000,0x0000, 0x0364,0x0000,0x0000, 0x0238,0x0000,0x0000, /* 0669 */ +0x0239,0x0000,0x0000, 0x035A,0x0000,0x0000, 0x18AE,0x0000,0x0000, /* 066C */ +0x1914,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x18A6,0x0000,0x0000, /* 066F */ +0x18A5,0x0000,0x0000, 0x18A9,0x0000,0x0000, 0x18A2,0x0000,0x0000, /* 0672 */ +0x18AD,0x18A2,0x0000, 0x1943,0x18A2,0x0000, 0x1947,0x18A2,0x0000, /* 0675 */ +0x1950,0x18A2,0x0000, 0x18BD,0x0000,0x0000, 0x18BE,0x0000,0x0000, /* 0678 */ +0x18B0,0x0000,0x0000, 0x18BF,0x0000,0x0000, 0x18C0,0x0000,0x0000, /* 067B */ +0x18B1,0x0000,0x0000, 0x18C1,0x0000,0x0000, 0x18B2,0x0000,0x0000, /* 067E */ +0x18CA,0x0000,0x0000, 0x18CB,0x0000,0x0000, 0x18C3,0x0000,0x0000, /* 0681 */ +0x18C4,0x0000,0x0000, 0x18CC,0x0000,0x0000, 0x18C5,0x0000,0x0000, /* 0684 */ +0x18C7,0x0000,0x0000, 0x18D5,0x0000,0x0000, 0x18D6,0x0000,0x0000, /* 0687 */ +0x18D7,0x0000,0x0000, 0x18D8,0x0000,0x0000, 0x18D9,0x0000,0x0000, /* 068A */ +0x18DA,0x0000,0x0000, 0x18DB,0x0000,0x0000, 0x18DC,0x0000,0x0000, /* 068D */ +0x18DD,0x0000,0x0000, 0x18E3,0x0000,0x0000, 0x18E4,0x0000,0x0000, /* 0690 */ +0x18E5,0x0000,0x0000, 0x18E6,0x0000,0x0000, 0x18E7,0x0000,0x0000, /* 0693 */ +0x18E8,0x0000,0x0000, 0x18E9,0x0000,0x0000, 0x18EA,0x0000,0x0000, /* 0696 */ +0x18EB,0x0000,0x0000, 0x18F3,0x0000,0x0000, 0x18F4,0x0000,0x0000, /* 0699 */ +0x18F5,0x0000,0x0000, 0x18FE,0x0000,0x0000, 0x18FF,0x0000,0x0000, /* 069C */ +0x1903,0x0000,0x0000, 0x1906,0x0000,0x0000, 0x190C,0x0000,0x0000, /* 069F */ +0x190D,0x0000,0x0000, 0x190E,0x0000,0x0000, 0x190F,0x0000,0x0000, /* 06A2 */ +0x1910,0x0000,0x0000, 0x1911,0x0000,0x0000, 0x1916,0x0000,0x0000, /* 06A5 */ +0x1917,0x0000,0x0000, 0x1919,0x0000,0x0000, 0x191A,0x0000,0x0000, /* 06A8 */ +0x191B,0x0000,0x0000, 0x191C,0x0000,0x0000, 0x191E,0x0000,0x0000, /* 06AB */ +0x191F,0x0000,0x0000, 0x1920,0x0000,0x0000, 0x1921,0x0000,0x0000, /* 06AE */ +0x1922,0x0000,0x0000, 0x1923,0x0000,0x0000, 0x1924,0x0000,0x0000, /* 06B1 */ +0x1925,0x0000,0x0000, 0x192C,0x0000,0x0000, 0x192D,0x0000,0x0000, /* 06B4 */ +0x192E,0x0000,0x0000, 0x192F,0x0000,0x0000, 0x1939,0x0000,0x0000, /* 06B7 */ +0x1935,0x0000,0x0000, 0x1936,0x0000,0x0000, 0x1937,0x0000,0x0000, /* 06BA */ +0x1938,0x0000,0x0000, 0x193E,0x0000,0x0000, 0x18C6,0x0000,0x0000, /* 06BD */ +0x1942,0x0000,0x0000, 0x193F,0x0000,0x0000, 0x193F,0x0000,0x0000, /* 06C0 */ +0x1940,0x0000,0x0000, 0x1944,0x0000,0x0000, 0x1945,0x0000,0x0000, /* 06C3 */ +0x1946,0x0000,0x0000, 0x1947,0x0000,0x0000, 0x1948,0x0000,0x0000, /* 06C6 */ +0x1949,0x0000,0x0000, 0x194A,0x0000,0x0000, 0x194B,0x0000,0x0000, /* 06C9 */ +0x1951,0x0000,0x0000, 0x1952,0x0000,0x0000, 0x1953,0x0000,0x0000, /* 06CC */ +0x194C,0x0000,0x0000, 0x1954,0x0000,0x0000, 0x1955,0x0000,0x0000, /* 06CF */ +0x195C,0x0000,0x0000, 0x195C,0x0000,0x0000, 0x0283,0x0000,0x0000, /* 06D2 */ +0x1942,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 06D5 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 06D8 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 06DB */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 06DE */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 06E1 */ +0x0000,0x0000,0x0000, 0x1943,0x0000,0x0000, 0x1950,0x0000,0x0000, /* 06E4 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0450,0x0000,0x0000, /* 06E7 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 06EA */ +0x0000,0x0000,0x0000, 0x18DE,0x0000,0x0000, 0x18EC,0x0000,0x0000, /* 06ED */ +0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 06F0 */ +0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, /* 06F3 */ +0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, /* 06F6 */ +0x120E,0x0000,0x0000, 0x18F6,0x0000,0x0000, 0x1900,0x0000,0x0000, /* 06F9 */ +0x1907,0x0000,0x0000, 0x18A2,0x0000,0x0000, 0x1931,0x0000,0x0000, /* 06FC */ +0x1941,0x0000,0x0000 }; + +uint16 uca520_p007[]= { /* 0700 (3 weights per char) */ +0x02B5,0x0000,0x0000, 0x0284,0x0000,0x0000, 0x0285,0x0000,0x0000, /* 0700 */ +0x024A,0x0000,0x0000, 0x024B,0x0000,0x0000, 0x024C,0x0000,0x0000, /* 0703 */ +0x024D,0x0000,0x0000, 0x024E,0x0000,0x0000, 0x024F,0x0000,0x0000, /* 0706 */ +0x0278,0x0000,0x0000, 0x039B,0x0000,0x0000, 0x039C,0x0000,0x0000, /* 0709 */ +0x039D,0x0000,0x0000, 0x039E,0x0000,0x0000, 0xFBC0,0x870E,0x0000, /* 070C */ +0x0000,0x0000,0x0000, 0x195F,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 070F */ +0x1960,0x0000,0x0000, 0x1961,0x0000,0x0000, 0x1961,0x0000,0x0000, /* 0712 */ +0x1963,0x0000,0x0000, 0x1962,0x0000,0x0000, 0x1964,0x0000,0x0000, /* 0715 */ +0x1965,0x0000,0x0000, 0x1966,0x0000,0x0000, 0x1968,0x0000,0x0000, /* 0718 */ +0x1969,0x0000,0x0000, 0x1969,0x0000,0x0000, 0x196A,0x0000,0x0000, /* 071B */ +0x196B,0x0000,0x0000, 0x196C,0x0000,0x0000, 0x196E,0x0000,0x0000, /* 071E */ +0x196F,0x0000,0x0000, 0x1970,0x0000,0x0000, 0x1971,0x0000,0x0000, /* 0721 */ +0x1971,0x0000,0x0000, 0x1972,0x0000,0x0000, 0x1973,0x0000,0x0000, /* 0724 */ +0x1973,0x0000,0x0000, 0x1975,0x0000,0x0000, 0x1976,0x0000,0x0000, /* 0727 */ +0x1977,0x0000,0x0000, 0x1978,0x0000,0x0000, 0x1979,0x0000,0x0000, /* 072A */ +0x1960,0x0000,0x0000, 0x1961,0x0000,0x0000, 0x1963,0x0000,0x0000, /* 072D */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0730 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0733 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0736 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0739 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 073C */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 073F */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0742 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0745 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0748 */ +0xFBC0,0x874B,0x0000, 0xFBC0,0x874C,0x0000, 0x1967,0x0000,0x0000, /* 074B */ +0x196D,0x0000,0x0000, 0x1974,0x0000,0x0000, 0x18B3,0x0000,0x0000, /* 074E */ +0x18B4,0x0000,0x0000, 0x18B5,0x0000,0x0000, 0x18B6,0x0000,0x0000, /* 0751 */ +0x18B7,0x0000,0x0000, 0x18B8,0x0000,0x0000, 0x18B9,0x0000,0x0000, /* 0754 */ +0x18CD,0x0000,0x0000, 0x18CE,0x0000,0x0000, 0x18DF,0x0000,0x0000, /* 0757 */ +0x18E0,0x0000,0x0000, 0x18ED,0x0000,0x0000, 0x18F7,0x0000,0x0000, /* 075A */ +0x1908,0x0000,0x0000, 0x1909,0x0000,0x0000, 0x190A,0x0000,0x0000, /* 075D */ +0x1912,0x0000,0x0000, 0x1913,0x0000,0x0000, 0x1926,0x0000,0x0000, /* 0760 */ +0x1929,0x0000,0x0000, 0x192A,0x0000,0x0000, 0x1932,0x0000,0x0000, /* 0763 */ +0x1933,0x0000,0x0000, 0x193A,0x0000,0x0000, 0x193B,0x0000,0x0000, /* 0766 */ +0x193C,0x0000,0x0000, 0x1930,0x0000,0x0000, 0x18EE,0x0000,0x0000, /* 0769 */ +0x18EF,0x0000,0x0000, 0x18F8,0x0000,0x0000, 0x18CF,0x0000,0x0000, /* 076C */ +0x18D0,0x0000,0x0000, 0x18F9,0x0000,0x0000, 0x18F0,0x0000,0x0000, /* 076F */ +0x18D1,0x0000,0x0000, 0x18AA,0x0000,0x0000, 0x18AB,0x0000,0x0000, /* 0772 */ +0x1959,0x0000,0x0000, 0x195A,0x0000,0x0000, 0x195B,0x0000,0x0000, /* 0775 */ +0x194D,0x0000,0x0000, 0x194E,0x0000,0x0000, 0x195D,0x0000,0x0000, /* 0778 */ +0x195E,0x0000,0x0000, 0x18D2,0x0000,0x0000, 0x18FA,0x0000,0x0000, /* 077B */ +0x18FB,0x0000,0x0000, 0x191D,0x0000,0x0000, 0x197A,0x0000,0x0000, /* 077E */ +0x197D,0x0000,0x0000, 0x197E,0x0000,0x0000, 0x197F,0x0000,0x0000, /* 0781 */ +0x1981,0x0000,0x0000, 0x1982,0x0000,0x0000, 0x1983,0x0000,0x0000, /* 0784 */ +0x1984,0x0000,0x0000, 0x1987,0x0000,0x0000, 0x1989,0x0000,0x0000, /* 0787 */ +0x198A,0x0000,0x0000, 0x198B,0x0000,0x0000, 0x198D,0x0000,0x0000, /* 078A */ +0x1991,0x0000,0x0000, 0x1992,0x0000,0x0000, 0x1994,0x0000,0x0000, /* 078D */ +0x1995,0x0000,0x0000, 0x1999,0x0000,0x0000, 0x199A,0x0000,0x0000, /* 0790 */ +0x199B,0x0000,0x0000, 0x199C,0x0000,0x0000, 0x199D,0x0000,0x0000, /* 0793 */ +0x199E,0x0000,0x0000, 0x199F,0x0000,0x0000, 0x198E,0x0000,0x0000, /* 0796 */ +0x197B,0x0000,0x0000, 0x197C,0x0000,0x0000, 0x198C,0x0000,0x0000, /* 0799 */ +0x1980,0x0000,0x0000, 0x1996,0x0000,0x0000, 0x1997,0x0000,0x0000, /* 079C */ +0x1998,0x0000,0x0000, 0x198F,0x0000,0x0000, 0x1990,0x0000,0x0000, /* 079F */ +0x1985,0x0000,0x0000, 0x1986,0x0000,0x0000, 0x1993,0x0000,0x0000, /* 07A2 */ +0x1988,0x0000,0x0000, 0x19A1,0x0000,0x0000, 0x19A2,0x0000,0x0000, /* 07A5 */ +0x19A3,0x0000,0x0000, 0x19A4,0x0000,0x0000, 0x19A5,0x0000,0x0000, /* 07A8 */ +0x19A6,0x0000,0x0000, 0x19A7,0x0000,0x0000, 0x19A8,0x0000,0x0000, /* 07AB */ +0x19A9,0x0000,0x0000, 0x19AA,0x0000,0x0000, 0x19AB,0x0000,0x0000, /* 07AE */ +0x19A0,0x0000,0x0000, 0xFBC0,0x87B2,0x0000, 0xFBC0,0x87B3,0x0000, /* 07B1 */ +0xFBC0,0x87B4,0x0000, 0xFBC0,0x87B5,0x0000, 0xFBC0,0x87B6,0x0000, /* 07B4 */ +0xFBC0,0x87B7,0x0000, 0xFBC0,0x87B8,0x0000, 0xFBC0,0x87B9,0x0000, /* 07B7 */ +0xFBC0,0x87BA,0x0000, 0xFBC0,0x87BB,0x0000, 0xFBC0,0x87BC,0x0000, /* 07BA */ +0xFBC0,0x87BD,0x0000, 0xFBC0,0x87BE,0x0000, 0xFBC0,0x87BF,0x0000, /* 07BD */ +0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 07C0 */ +0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, /* 07C3 */ +0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, /* 07C6 */ +0x120E,0x0000,0x0000, 0x19AC,0x0000,0x0000, 0x19AD,0x0000,0x0000, /* 07C9 */ +0x19AE,0x0000,0x0000, 0x19AF,0x0000,0x0000, 0x19B0,0x0000,0x0000, /* 07CC */ +0x19B1,0x0000,0x0000, 0x19B2,0x0000,0x0000, 0x19B3,0x0000,0x0000, /* 07CF */ +0x19B4,0x0000,0x0000, 0x19B5,0x0000,0x0000, 0x19B6,0x0000,0x0000, /* 07D2 */ +0x19B7,0x0000,0x0000, 0x19B8,0x0000,0x0000, 0x19B9,0x0000,0x0000, /* 07D5 */ +0x19BA,0x0000,0x0000, 0x19BB,0x0000,0x0000, 0x19BC,0x0000,0x0000, /* 07D8 */ +0x19BD,0x0000,0x0000, 0x19BE,0x0000,0x0000, 0x19BF,0x0000,0x0000, /* 07DB */ +0x19C0,0x0000,0x0000, 0x19C1,0x0000,0x0000, 0x19C2,0x0000,0x0000, /* 07DE */ +0x19C3,0x0000,0x0000, 0x19C4,0x0000,0x0000, 0x19C5,0x0000,0x0000, /* 07E1 */ +0x19C6,0x0000,0x0000, 0x19C7,0x0000,0x0000, 0x19C8,0x0000,0x0000, /* 07E4 */ +0x19C9,0x0000,0x0000, 0x19B8,0x0000,0x0000, 0x19B9,0x0000,0x0000, /* 07E7 */ +0x19BB,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 07EA */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 07ED */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 07F0 */ +0x0000,0x0000,0x0000, 0x19CA,0x0000,0x0000, 0x19CB,0x0000,0x0000, /* 07F3 */ +0x0452,0x0000,0x0000, 0x02B6,0x0000,0x0000, 0x023A,0x0000,0x0000, /* 07F6 */ +0x0271,0x0000,0x0000, 0x020D,0x0000,0x0000, 0xFBC0,0x87FB,0x0000, /* 07F9 */ +0xFBC0,0x87FC,0x0000, 0xFBC0,0x87FD,0x0000, 0xFBC0,0x87FE,0x0000, /* 07FC */ +0xFBC0,0x87FF,0x0000 }; + +uint16 uca520_p008[]= { /* 0800 (3 weights per char) */ +0x1888,0x0000,0x0000, 0x1889,0x0000,0x0000, 0x188A,0x0000,0x0000, /* 0800 */ +0x188B,0x0000,0x0000, 0x188C,0x0000,0x0000, 0x188D,0x0000,0x0000, /* 0803 */ +0x188E,0x0000,0x0000, 0x188F,0x0000,0x0000, 0x1890,0x0000,0x0000, /* 0806 */ +0x1891,0x0000,0x0000, 0x1892,0x0000,0x0000, 0x1893,0x0000,0x0000, /* 0809 */ +0x1894,0x0000,0x0000, 0x1895,0x0000,0x0000, 0x1896,0x0000,0x0000, /* 080C */ +0x1897,0x0000,0x0000, 0x1898,0x0000,0x0000, 0x1899,0x0000,0x0000, /* 080F */ +0x189A,0x0000,0x0000, 0x189B,0x0000,0x0000, 0x189C,0x0000,0x0000, /* 0812 */ +0x189D,0x0000,0x0000, 0x189E,0x0000,0x0000, 0x189F,0x0000,0x0000, /* 0815 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x18A0,0x0000,0x0000, /* 0818 */ +0x18A1,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 081B */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 081E */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0821 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0824 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0827 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 082A */ +0x0000,0x0000,0x0000, 0xFBC0,0x882E,0x0000, 0xFBC0,0x882F,0x0000, /* 082D */ +0x0250,0x0000,0x0000, 0x0251,0x0000,0x0000, 0x0252,0x0000,0x0000, /* 0830 */ +0x0253,0x0000,0x0000, 0x0254,0x0000,0x0000, 0x0255,0x0000,0x0000, /* 0833 */ +0x0256,0x0000,0x0000, 0x0257,0x0000,0x0000, 0x0258,0x0000,0x0000, /* 0836 */ +0x0259,0x0000,0x0000, 0x025A,0x0000,0x0000, 0x025B,0x0000,0x0000, /* 0839 */ +0x025C,0x0000,0x0000, 0x025D,0x0000,0x0000, 0x025E,0x0000,0x0000, /* 083C */ +0xFBC0,0x883F,0x0000, 0xFBC0,0x8840,0x0000, 0xFBC0,0x8841,0x0000, /* 083F */ +0xFBC0,0x8842,0x0000, 0xFBC0,0x8843,0x0000, 0xFBC0,0x8844,0x0000, /* 0842 */ +0xFBC0,0x8845,0x0000, 0xFBC0,0x8846,0x0000, 0xFBC0,0x8847,0x0000, /* 0845 */ +0xFBC0,0x8848,0x0000, 0xFBC0,0x8849,0x0000, 0xFBC0,0x884A,0x0000, /* 0848 */ +0xFBC0,0x884B,0x0000, 0xFBC0,0x884C,0x0000, 0xFBC0,0x884D,0x0000, /* 084B */ +0xFBC0,0x884E,0x0000, 0xFBC0,0x884F,0x0000, 0xFBC0,0x8850,0x0000, /* 084E */ +0xFBC0,0x8851,0x0000, 0xFBC0,0x8852,0x0000, 0xFBC0,0x8853,0x0000, /* 0851 */ +0xFBC0,0x8854,0x0000, 0xFBC0,0x8855,0x0000, 0xFBC0,0x8856,0x0000, /* 0854 */ +0xFBC0,0x8857,0x0000, 0xFBC0,0x8858,0x0000, 0xFBC0,0x8859,0x0000, /* 0857 */ +0xFBC0,0x885A,0x0000, 0xFBC0,0x885B,0x0000, 0xFBC0,0x885C,0x0000, /* 085A */ +0xFBC0,0x885D,0x0000, 0xFBC0,0x885E,0x0000, 0xFBC0,0x885F,0x0000, /* 085D */ +0xFBC0,0x8860,0x0000, 0xFBC0,0x8861,0x0000, 0xFBC0,0x8862,0x0000, /* 0860 */ +0xFBC0,0x8863,0x0000, 0xFBC0,0x8864,0x0000, 0xFBC0,0x8865,0x0000, /* 0863 */ +0xFBC0,0x8866,0x0000, 0xFBC0,0x8867,0x0000, 0xFBC0,0x8868,0x0000, /* 0866 */ +0xFBC0,0x8869,0x0000, 0xFBC0,0x886A,0x0000, 0xFBC0,0x886B,0x0000, /* 0869 */ +0xFBC0,0x886C,0x0000, 0xFBC0,0x886D,0x0000, 0xFBC0,0x886E,0x0000, /* 086C */ +0xFBC0,0x886F,0x0000, 0xFBC0,0x8870,0x0000, 0xFBC0,0x8871,0x0000, /* 086F */ +0xFBC0,0x8872,0x0000, 0xFBC0,0x8873,0x0000, 0xFBC0,0x8874,0x0000, /* 0872 */ +0xFBC0,0x8875,0x0000, 0xFBC0,0x8876,0x0000, 0xFBC0,0x8877,0x0000, /* 0875 */ +0xFBC0,0x8878,0x0000, 0xFBC0,0x8879,0x0000, 0xFBC0,0x887A,0x0000, /* 0878 */ +0xFBC0,0x887B,0x0000, 0xFBC0,0x887C,0x0000, 0xFBC0,0x887D,0x0000, /* 087B */ +0xFBC0,0x887E,0x0000, 0xFBC0,0x887F,0x0000, 0xFBC0,0x8880,0x0000, /* 087E */ +0xFBC0,0x8881,0x0000, 0xFBC0,0x8882,0x0000, 0xFBC0,0x8883,0x0000, /* 0881 */ +0xFBC0,0x8884,0x0000, 0xFBC0,0x8885,0x0000, 0xFBC0,0x8886,0x0000, /* 0884 */ +0xFBC0,0x8887,0x0000, 0xFBC0,0x8888,0x0000, 0xFBC0,0x8889,0x0000, /* 0887 */ +0xFBC0,0x888A,0x0000, 0xFBC0,0x888B,0x0000, 0xFBC0,0x888C,0x0000, /* 088A */ +0xFBC0,0x888D,0x0000, 0xFBC0,0x888E,0x0000, 0xFBC0,0x888F,0x0000, /* 088D */ +0xFBC0,0x8890,0x0000, 0xFBC0,0x8891,0x0000, 0xFBC0,0x8892,0x0000, /* 0890 */ +0xFBC0,0x8893,0x0000, 0xFBC0,0x8894,0x0000, 0xFBC0,0x8895,0x0000, /* 0893 */ +0xFBC0,0x8896,0x0000, 0xFBC0,0x8897,0x0000, 0xFBC0,0x8898,0x0000, /* 0896 */ +0xFBC0,0x8899,0x0000, 0xFBC0,0x889A,0x0000, 0xFBC0,0x889B,0x0000, /* 0899 */ +0xFBC0,0x889C,0x0000, 0xFBC0,0x889D,0x0000, 0xFBC0,0x889E,0x0000, /* 089C */ +0xFBC0,0x889F,0x0000, 0xFBC0,0x88A0,0x0000, 0xFBC0,0x88A1,0x0000, /* 089F */ +0xFBC0,0x88A2,0x0000, 0xFBC0,0x88A3,0x0000, 0xFBC0,0x88A4,0x0000, /* 08A2 */ +0xFBC0,0x88A5,0x0000, 0xFBC0,0x88A6,0x0000, 0xFBC0,0x88A7,0x0000, /* 08A5 */ +0xFBC0,0x88A8,0x0000, 0xFBC0,0x88A9,0x0000, 0xFBC0,0x88AA,0x0000, /* 08A8 */ +0xFBC0,0x88AB,0x0000, 0xFBC0,0x88AC,0x0000, 0xFBC0,0x88AD,0x0000, /* 08AB */ +0xFBC0,0x88AE,0x0000, 0xFBC0,0x88AF,0x0000, 0xFBC0,0x88B0,0x0000, /* 08AE */ +0xFBC0,0x88B1,0x0000, 0xFBC0,0x88B2,0x0000, 0xFBC0,0x88B3,0x0000, /* 08B1 */ +0xFBC0,0x88B4,0x0000, 0xFBC0,0x88B5,0x0000, 0xFBC0,0x88B6,0x0000, /* 08B4 */ +0xFBC0,0x88B7,0x0000, 0xFBC0,0x88B8,0x0000, 0xFBC0,0x88B9,0x0000, /* 08B7 */ +0xFBC0,0x88BA,0x0000, 0xFBC0,0x88BB,0x0000, 0xFBC0,0x88BC,0x0000, /* 08BA */ +0xFBC0,0x88BD,0x0000, 0xFBC0,0x88BE,0x0000, 0xFBC0,0x88BF,0x0000, /* 08BD */ +0xFBC0,0x88C0,0x0000, 0xFBC0,0x88C1,0x0000, 0xFBC0,0x88C2,0x0000, /* 08C0 */ +0xFBC0,0x88C3,0x0000, 0xFBC0,0x88C4,0x0000, 0xFBC0,0x88C5,0x0000, /* 08C3 */ +0xFBC0,0x88C6,0x0000, 0xFBC0,0x88C7,0x0000, 0xFBC0,0x88C8,0x0000, /* 08C6 */ +0xFBC0,0x88C9,0x0000, 0xFBC0,0x88CA,0x0000, 0xFBC0,0x88CB,0x0000, /* 08C9 */ +0xFBC0,0x88CC,0x0000, 0xFBC0,0x88CD,0x0000, 0xFBC0,0x88CE,0x0000, /* 08CC */ +0xFBC0,0x88CF,0x0000, 0xFBC0,0x88D0,0x0000, 0xFBC0,0x88D1,0x0000, /* 08CF */ +0xFBC0,0x88D2,0x0000, 0xFBC0,0x88D3,0x0000, 0xFBC0,0x88D4,0x0000, /* 08D2 */ +0xFBC0,0x88D5,0x0000, 0xFBC0,0x88D6,0x0000, 0xFBC0,0x88D7,0x0000, /* 08D5 */ +0xFBC0,0x88D8,0x0000, 0xFBC0,0x88D9,0x0000, 0xFBC0,0x88DA,0x0000, /* 08D8 */ +0xFBC0,0x88DB,0x0000, 0xFBC0,0x88DC,0x0000, 0xFBC0,0x88DD,0x0000, /* 08DB */ +0xFBC0,0x88DE,0x0000, 0xFBC0,0x88DF,0x0000, 0xFBC0,0x88E0,0x0000, /* 08DE */ +0xFBC0,0x88E1,0x0000, 0xFBC0,0x88E2,0x0000, 0xFBC0,0x88E3,0x0000, /* 08E1 */ +0xFBC0,0x88E4,0x0000, 0xFBC0,0x88E5,0x0000, 0xFBC0,0x88E6,0x0000, /* 08E4 */ +0xFBC0,0x88E7,0x0000, 0xFBC0,0x88E8,0x0000, 0xFBC0,0x88E9,0x0000, /* 08E7 */ +0xFBC0,0x88EA,0x0000, 0xFBC0,0x88EB,0x0000, 0xFBC0,0x88EC,0x0000, /* 08EA */ +0xFBC0,0x88ED,0x0000, 0xFBC0,0x88EE,0x0000, 0xFBC0,0x88EF,0x0000, /* 08ED */ +0xFBC0,0x88F0,0x0000, 0xFBC0,0x88F1,0x0000, 0xFBC0,0x88F2,0x0000, /* 08F0 */ +0xFBC0,0x88F3,0x0000, 0xFBC0,0x88F4,0x0000, 0xFBC0,0x88F5,0x0000, /* 08F3 */ +0xFBC0,0x88F6,0x0000, 0xFBC0,0x88F7,0x0000, 0xFBC0,0x88F8,0x0000, /* 08F6 */ +0xFBC0,0x88F9,0x0000, 0xFBC0,0x88FA,0x0000, 0xFBC0,0x88FB,0x0000, /* 08F9 */ +0xFBC0,0x88FC,0x0000, 0xFBC0,0x88FD,0x0000, 0xFBC0,0x88FE,0x0000, /* 08FC */ +0xFBC0,0x88FF,0x0000 }; + +uint16 uca520_p009[]= { /* 0900 (3 weights per char) */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0900 */ +0x0000,0x0000,0x0000, 0x1BAA,0x0000,0x0000, 0x1BAB,0x0000,0x0000, /* 0903 */ +0x1BAC,0x0000,0x0000, 0x1BAD,0x0000,0x0000, 0x1BAE,0x0000,0x0000, /* 0906 */ +0x1BAF,0x0000,0x0000, 0x1BB0,0x0000,0x0000, 0x1BB1,0x0000,0x0000, /* 0909 */ +0x1BB3,0x0000,0x0000, 0x1BB5,0x0000,0x0000, 0x1BB6,0x0000,0x0000, /* 090C */ +0x1BB7,0x0000,0x0000, 0x1BB8,0x0000,0x0000, 0x1BB9,0x0000,0x0000, /* 090F */ +0x1BBA,0x0000,0x0000, 0x1BBB,0x0000,0x0000, 0x1BBC,0x0000,0x0000, /* 0912 */ +0x1BBD,0x0000,0x0000, 0x1BBE,0x0000,0x0000, 0x1BBF,0x0000,0x0000, /* 0915 */ +0x1BC1,0x0000,0x0000, 0x1BC2,0x0000,0x0000, 0x1BC3,0x0000,0x0000, /* 0918 */ +0x1BC4,0x0000,0x0000, 0x1BC5,0x0000,0x0000, 0x1BC8,0x0000,0x0000, /* 091B */ +0x1BC9,0x0000,0x0000, 0x1BCA,0x0000,0x0000, 0x1BCB,0x0000,0x0000, /* 091E */ +0x1BCC,0x0000,0x0000, 0x1BCE,0x0000,0x0000, 0x1BCF,0x0000,0x0000, /* 0921 */ +0x1BD0,0x0000,0x0000, 0x1BD1,0x0000,0x0000, 0x1BD2,0x0000,0x0000, /* 0924 */ +0x1BD3,0x0000,0x0000, 0x1BD4,0x0000,0x0000, 0x1BD4,0x0000,0x0000, /* 0927 */ +0x1BD5,0x0000,0x0000, 0x1BD6,0x0000,0x0000, 0x1BD7,0x0000,0x0000, /* 092A */ +0x1BD9,0x0000,0x0000, 0x1BDA,0x0000,0x0000, 0x1BDB,0x0000,0x0000, /* 092D */ +0x1BDD,0x0000,0x0000, 0x1BDD,0x0000,0x0000, 0x1BDE,0x0000,0x0000, /* 0930 */ +0x1BDF,0x0000,0x0000, 0x1BDF,0x0000,0x0000, 0x1BE0,0x0000,0x0000, /* 0933 */ +0x1BE1,0x0000,0x0000, 0x1BE2,0x0000,0x0000, 0x1BE3,0x0000,0x0000, /* 0936 */ +0x1BE4,0x0000,0x0000, 0xFBC0,0x893A,0x0000, 0xFBC0,0x893B,0x0000, /* 0939 */ +0x0000,0x0000,0x0000, 0x1BE5,0x0000,0x0000, 0x1BEA,0x0000,0x0000, /* 093C */ +0x1BEB,0x0000,0x0000, 0x1BEC,0x0000,0x0000, 0x1BED,0x0000,0x0000, /* 093F */ +0x1BEE,0x0000,0x0000, 0x1BEF,0x0000,0x0000, 0x1BF0,0x0000,0x0000, /* 0942 */ +0x1BF3,0x0000,0x0000, 0x1BF5,0x0000,0x0000, 0x1BF6,0x0000,0x0000, /* 0945 */ +0x1BF8,0x0000,0x0000, 0x1BF9,0x0000,0x0000, 0x1BFA,0x0000,0x0000, /* 0948 */ +0x1BFB,0x0000,0x0000, 0x1BFC,0x0000,0x0000, 0x1BFD,0x0000,0x0000, /* 094B */ +0x1BF7,0x0000,0x0000, 0xFBC0,0x894F,0x0000, 0x1BA8,0x0000,0x0000, /* 094E */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0951 */ +0x0000,0x0000,0x0000, 0x1BF4,0x0000,0x0000, 0xFBC0,0x8956,0x0000, /* 0954 */ +0xFBC0,0x8957,0x0000, 0x1BBD,0x0000,0x0000, 0x1BBE,0x0000,0x0000, /* 0957 */ +0x1BBF,0x0000,0x0000, 0x1BC5,0x0000,0x0000, 0x1BCC,0x0000,0x0000, /* 095A */ +0x1BCE,0x0000,0x0000, 0x1BD6,0x0000,0x0000, 0x1BDB,0x0000,0x0000, /* 095D */ +0x1BB2,0x0000,0x0000, 0x1BB4,0x0000,0x0000, 0x1BF1,0x0000,0x0000, /* 0960 */ +0x1BF2,0x0000,0x0000, 0x0294,0x0000,0x0000, 0x0295,0x0000,0x0000, /* 0963 */ +0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 0966 */ +0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, /* 0969 */ +0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, /* 096C */ +0x120E,0x0000,0x0000, 0x03A1,0x0000,0x0000, 0x11D0,0x0000,0x0000, /* 096F */ +0x1BA9,0x0000,0x0000, 0xFBC0,0x8973,0x0000, 0xFBC0,0x8974,0x0000, /* 0972 */ +0xFBC0,0x8975,0x0000, 0xFBC0,0x8976,0x0000, 0xFBC0,0x8977,0x0000, /* 0975 */ +0xFBC0,0x8978,0x0000, 0x1BC6,0x0000,0x0000, 0x1BDC,0x0000,0x0000, /* 0978 */ +0x1BC0,0x0000,0x0000, 0x1BC7,0x0000,0x0000, 0x1BE6,0x0000,0x0000, /* 097B */ +0x1BCD,0x0000,0x0000, 0x1BD8,0x0000,0x0000, 0xFBC0,0x8980,0x0000, /* 097E */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0981 */ +0xFBC0,0x8984,0x0000, 0x1BFE,0x0000,0x0000, 0x1BFF,0x0000,0x0000, /* 0984 */ +0x1C00,0x0000,0x0000, 0x1C01,0x0000,0x0000, 0x1C02,0x0000,0x0000, /* 0987 */ +0x1C03,0x0000,0x0000, 0x1C04,0x0000,0x0000, 0x1C06,0x0000,0x0000, /* 098A */ +0xFBC0,0x898D,0x0000, 0xFBC0,0x898E,0x0000, 0x1C08,0x0000,0x0000, /* 098D */ +0x1C09,0x0000,0x0000, 0xFBC0,0x8991,0x0000, 0xFBC0,0x8992,0x0000, /* 0990 */ +0x1C0A,0x0000,0x0000, 0x1C0B,0x0000,0x0000, 0x1C0C,0x0000,0x0000, /* 0993 */ +0x1C0D,0x0000,0x0000, 0x1C0E,0x0000,0x0000, 0x1C0F,0x0000,0x0000, /* 0996 */ +0x1C10,0x0000,0x0000, 0x1C11,0x0000,0x0000, 0x1C12,0x0000,0x0000, /* 0999 */ +0x1C13,0x0000,0x0000, 0x1C14,0x0000,0x0000, 0x1C15,0x0000,0x0000, /* 099C */ +0x1C16,0x0000,0x0000, 0x1C17,0x0000,0x0000, 0x1C18,0x0000,0x0000, /* 099F */ +0x1C19,0x0000,0x0000, 0x1C1A,0x0000,0x0000, 0x1C1B,0x0000,0x0000, /* 09A2 */ +0x1C1C,0x0000,0x0000, 0x1C1D,0x0000,0x0000, 0x1C1E,0x0000,0x0000, /* 09A5 */ +0x1C1F,0x0000,0x0000, 0xFBC0,0x89A9,0x0000, 0x1C20,0x0000,0x0000, /* 09A8 */ +0x1C21,0x0000,0x0000, 0x1C22,0x0000,0x0000, 0x1C23,0x0000,0x0000, /* 09AB */ +0x1C24,0x0000,0x0000, 0x1C25,0x0000,0x0000, 0x1C26,0x0000,0x0000, /* 09AE */ +0xFBC0,0x89B1,0x0000, 0x1C28,0x0000,0x0000, 0xFBC0,0x89B3,0x0000, /* 09B1 */ +0xFBC0,0x89B4,0x0000, 0xFBC0,0x89B5,0x0000, 0x1C2A,0x0000,0x0000, /* 09B4 */ +0x1C2B,0x0000,0x0000, 0x1C2C,0x0000,0x0000, 0x1C2D,0x0000,0x0000, /* 09B7 */ +0xFBC0,0x89BA,0x0000, 0xFBC0,0x89BB,0x0000, 0x0000,0x0000,0x0000, /* 09BA */ +0x1C2E,0x0000,0x0000, 0x1C2F,0x0000,0x0000, 0x1C30,0x0000,0x0000, /* 09BD */ +0x1C31,0x0000,0x0000, 0x1C32,0x0000,0x0000, 0x1C33,0x0000,0x0000, /* 09C0 */ +0x1C34,0x0000,0x0000, 0x1C35,0x0000,0x0000, 0xFBC0,0x89C5,0x0000, /* 09C3 */ +0xFBC0,0x89C6,0x0000, 0x1C38,0x0000,0x0000, 0x1C39,0x0000,0x0000, /* 09C6 */ +0xFBC0,0x89C9,0x0000, 0xFBC0,0x89CA,0x0000, 0x1C3A,0x0000,0x0000, /* 09C9 */ +0x1C3B,0x0000,0x0000, 0x1C3C,0x0000,0x0000, 0x1C1B,0x1C3C,0x0000, /* 09CC */ +0xFBC0,0x89CF,0x0000, 0xFBC0,0x89D0,0x0000, 0xFBC0,0x89D1,0x0000, /* 09CF */ +0xFBC0,0x89D2,0x0000, 0xFBC0,0x89D3,0x0000, 0xFBC0,0x89D4,0x0000, /* 09D2 */ +0xFBC0,0x89D5,0x0000, 0xFBC0,0x89D6,0x0000, 0x1C3D,0x0000,0x0000, /* 09D5 */ +0xFBC0,0x89D8,0x0000, 0xFBC0,0x89D9,0x0000, 0xFBC0,0x89DA,0x0000, /* 09D8 */ +0xFBC0,0x89DB,0x0000, 0x1C18,0x0000,0x0000, 0x1C19,0x0000,0x0000, /* 09DB */ +0xFBC0,0x89DE,0x0000, 0x1C25,0x0000,0x0000, 0x1C05,0x0000,0x0000, /* 09DE */ +0x1C07,0x0000,0x0000, 0x1C36,0x0000,0x0000, 0x1C37,0x0000,0x0000, /* 09E1 */ +0xFBC0,0x89E4,0x0000, 0xFBC0,0x89E5,0x0000, 0x1205,0x0000,0x0000, /* 09E4 */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 09E7 */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 09EA */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 09ED */ +0x1C27,0x0000,0x0000, 0x1C29,0x0000,0x0000, 0x11E5,0x0000,0x0000, /* 09F0 */ +0x11E6,0x0000,0x0000, 0x1110,0x0000,0x0000, 0x1111,0x0000,0x0000, /* 09F3 */ +0x1112,0x0000,0x0000, 0x1113,0x0000,0x0000, 0x1114,0x0000,0x0000, /* 09F6 */ +0x1115,0x0000,0x0000, 0x0453,0x0000,0x0000, 0x11E7,0x0000,0x0000, /* 09F9 */ +0xFBC0,0x89FC,0x0000, 0xFBC0,0x89FD,0x0000, 0xFBC0,0x89FE,0x0000, /* 09FC */ +0xFBC0,0x89FF,0x0000 }; + +uint16 uca520_p00A[]= { /* 0A00 (3 weights per char) */ +0xFBC0,0x8A00,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0A00 */ +0x0000,0x0000,0x0000, 0xFBC0,0x8A04,0x0000, 0x1C43,0x0000,0x0000, /* 0A03 */ +0x1C44,0x0000,0x0000, 0x1C48,0x0000,0x0000, 0x1C49,0x0000,0x0000, /* 0A06 */ +0x1C40,0x0000,0x0000, 0x1C41,0x0000,0x0000, 0xFBC0,0x8A0B,0x0000, /* 0A09 */ +0xFBC0,0x8A0C,0x0000, 0xFBC0,0x8A0D,0x0000, 0xFBC0,0x8A0E,0x0000, /* 0A0C */ +0x1C4A,0x0000,0x0000, 0x1C45,0x0000,0x0000, 0xFBC0,0x8A11,0x0000, /* 0A0F */ +0xFBC0,0x8A12,0x0000, 0x1C42,0x0000,0x0000, 0x1C46,0x0000,0x0000, /* 0A12 */ +0x1C4E,0x0000,0x0000, 0x1C4F,0x0000,0x0000, 0x1C50,0x0000,0x0000, /* 0A15 */ +0x1C51,0x0000,0x0000, 0x1C52,0x0000,0x0000, 0x1C53,0x0000,0x0000, /* 0A18 */ +0x1C54,0x0000,0x0000, 0x1C55,0x0000,0x0000, 0x1C56,0x0000,0x0000, /* 0A1B */ +0x1C57,0x0000,0x0000, 0x1C58,0x0000,0x0000, 0x1C59,0x0000,0x0000, /* 0A1E */ +0x1C5A,0x0000,0x0000, 0x1C5B,0x0000,0x0000, 0x1C5C,0x0000,0x0000, /* 0A21 */ +0x1C5D,0x0000,0x0000, 0x1C5E,0x0000,0x0000, 0x1C5F,0x0000,0x0000, /* 0A24 */ +0x1C60,0x0000,0x0000, 0x1C61,0x0000,0x0000, 0xFBC0,0x8A29,0x0000, /* 0A27 */ +0x1C62,0x0000,0x0000, 0x1C63,0x0000,0x0000, 0x1C64,0x0000,0x0000, /* 0A2A */ +0x1C65,0x0000,0x0000, 0x1C66,0x0000,0x0000, 0x1C67,0x0000,0x0000, /* 0A2D */ +0x1C69,0x0000,0x0000, 0xFBC0,0x8A31,0x0000, 0x1C6A,0x0000,0x0000, /* 0A30 */ +0x1C6A,0x0000,0x0000, 0xFBC0,0x8A34,0x0000, 0x1C6B,0x0000,0x0000, /* 0A33 */ +0x1C4B,0x0000,0x0000, 0xFBC0,0x8A37,0x0000, 0x1C4B,0x0000,0x0000, /* 0A36 */ +0x1C4C,0x0000,0x0000, 0xFBC0,0x8A3A,0x0000, 0xFBC0,0x8A3B,0x0000, /* 0A39 */ +0x0000,0x0000,0x0000, 0xFBC0,0x8A3D,0x0000, 0x1C6D,0x0000,0x0000, /* 0A3C */ +0x1C6E,0x0000,0x0000, 0x1C6F,0x0000,0x0000, 0x1C70,0x0000,0x0000, /* 0A3F */ +0x1C71,0x0000,0x0000, 0xFBC0,0x8A43,0x0000, 0xFBC0,0x8A44,0x0000, /* 0A42 */ +0xFBC0,0x8A45,0x0000, 0xFBC0,0x8A46,0x0000, 0x1C72,0x0000,0x0000, /* 0A45 */ +0x1C73,0x0000,0x0000, 0xFBC0,0x8A49,0x0000, 0xFBC0,0x8A4A,0x0000, /* 0A48 */ +0x1C74,0x0000,0x0000, 0x1C75,0x0000,0x0000, 0x1C76,0x0000,0x0000, /* 0A4B */ +0xFBC0,0x8A4E,0x0000, 0xFBC0,0x8A4F,0x0000, 0xFBC0,0x8A50,0x0000, /* 0A4E */ +0x1C4D,0x0000,0x0000, 0xFBC0,0x8A52,0x0000, 0xFBC0,0x8A53,0x0000, /* 0A51 */ +0xFBC0,0x8A54,0x0000, 0xFBC0,0x8A55,0x0000, 0xFBC0,0x8A56,0x0000, /* 0A54 */ +0xFBC0,0x8A57,0x0000, 0xFBC0,0x8A58,0x0000, 0x1C4F,0x0000,0x0000, /* 0A57 */ +0x1C50,0x0000,0x0000, 0x1C55,0x0000,0x0000, 0x1C6C,0x0000,0x0000, /* 0A5A */ +0xFBC0,0x8A5D,0x0000, 0x1C63,0x0000,0x0000, 0xFBC0,0x8A5F,0x0000, /* 0A5D */ +0xFBC0,0x8A60,0x0000, 0xFBC0,0x8A61,0x0000, 0xFBC0,0x8A62,0x0000, /* 0A60 */ +0xFBC0,0x8A63,0x0000, 0xFBC0,0x8A64,0x0000, 0xFBC0,0x8A65,0x0000, /* 0A63 */ +0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 0A66 */ +0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, /* 0A69 */ +0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, /* 0A6C */ +0x120E,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0A6F */ +0x1C47,0x0000,0x0000, 0x1C3F,0x0000,0x0000, 0x1C3E,0x0000,0x0000, /* 0A72 */ +0x1C68,0x0000,0x0000, 0xFBC0,0x8A76,0x0000, 0xFBC0,0x8A77,0x0000, /* 0A75 */ +0xFBC0,0x8A78,0x0000, 0xFBC0,0x8A79,0x0000, 0xFBC0,0x8A7A,0x0000, /* 0A78 */ +0xFBC0,0x8A7B,0x0000, 0xFBC0,0x8A7C,0x0000, 0xFBC0,0x8A7D,0x0000, /* 0A7B */ +0xFBC0,0x8A7E,0x0000, 0xFBC0,0x8A7F,0x0000, 0xFBC0,0x8A80,0x0000, /* 0A7E */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0A81 */ +0xFBC0,0x8A84,0x0000, 0x1C78,0x0000,0x0000, 0x1C79,0x0000,0x0000, /* 0A84 */ +0x1C7A,0x0000,0x0000, 0x1C7B,0x0000,0x0000, 0x1C7C,0x0000,0x0000, /* 0A87 */ +0x1C7D,0x0000,0x0000, 0x1C7E,0x0000,0x0000, 0x1C80,0x0000,0x0000, /* 0A8A */ +0x1C82,0x0000,0x0000, 0xFBC0,0x8A8E,0x0000, 0x1C83,0x0000,0x0000, /* 0A8D */ +0x1C84,0x0000,0x0000, 0x1C85,0x0000,0x0000, 0xFBC0,0x8A92,0x0000, /* 0A90 */ +0x1C86,0x0000,0x0000, 0x1C87,0x0000,0x0000, 0x1C88,0x0000,0x0000, /* 0A93 */ +0x1C89,0x0000,0x0000, 0x1C8A,0x0000,0x0000, 0x1C8B,0x0000,0x0000, /* 0A96 */ +0x1C8C,0x0000,0x0000, 0x1C8D,0x0000,0x0000, 0x1C8E,0x0000,0x0000, /* 0A99 */ +0x1C8F,0x0000,0x0000, 0x1C90,0x0000,0x0000, 0x1C91,0x0000,0x0000, /* 0A9C */ +0x1C92,0x0000,0x0000, 0x1C93,0x0000,0x0000, 0x1C94,0x0000,0x0000, /* 0A9F */ +0x1C95,0x0000,0x0000, 0x1C96,0x0000,0x0000, 0x1C97,0x0000,0x0000, /* 0AA2 */ +0x1C98,0x0000,0x0000, 0x1C99,0x0000,0x0000, 0x1C9A,0x0000,0x0000, /* 0AA5 */ +0x1C9B,0x0000,0x0000, 0xFBC0,0x8AA9,0x0000, 0x1C9C,0x0000,0x0000, /* 0AA8 */ +0x1C9D,0x0000,0x0000, 0x1C9E,0x0000,0x0000, 0x1C9F,0x0000,0x0000, /* 0AAB */ +0x1CA0,0x0000,0x0000, 0x1CA1,0x0000,0x0000, 0x1CA2,0x0000,0x0000, /* 0AAE */ +0xFBC0,0x8AB1,0x0000, 0x1CA3,0x0000,0x0000, 0x1CA9,0x0000,0x0000, /* 0AB1 */ +0xFBC0,0x8AB4,0x0000, 0x1CA4,0x0000,0x0000, 0x1CA5,0x0000,0x0000, /* 0AB4 */ +0x1CA6,0x0000,0x0000, 0x1CA7,0x0000,0x0000, 0x1CA8,0x0000,0x0000, /* 0AB7 */ +0xFBC0,0x8ABA,0x0000, 0xFBC0,0x8ABB,0x0000, 0x0000,0x0000,0x0000, /* 0ABA */ +0x1CAA,0x0000,0x0000, 0x1CAB,0x0000,0x0000, 0x1CAC,0x0000,0x0000, /* 0ABD */ +0x1CAD,0x0000,0x0000, 0x1CAE,0x0000,0x0000, 0x1CAF,0x0000,0x0000, /* 0AC0 */ +0x1CB0,0x0000,0x0000, 0x1CB1,0x0000,0x0000, 0x1CB4,0x0000,0x0000, /* 0AC3 */ +0xFBC0,0x8AC6,0x0000, 0x1CB5,0x0000,0x0000, 0x1CB6,0x0000,0x0000, /* 0AC6 */ +0x1CB7,0x0000,0x0000, 0xFBC0,0x8ACA,0x0000, 0x1CB8,0x0000,0x0000, /* 0AC9 */ +0x1CB9,0x0000,0x0000, 0x1CBA,0x0000,0x0000, 0xFBC0,0x8ACE,0x0000, /* 0ACC */ +0xFBC0,0x8ACF,0x0000, 0x1C77,0x0000,0x0000, 0xFBC0,0x8AD1,0x0000, /* 0ACF */ +0xFBC0,0x8AD2,0x0000, 0xFBC0,0x8AD3,0x0000, 0xFBC0,0x8AD4,0x0000, /* 0AD2 */ +0xFBC0,0x8AD5,0x0000, 0xFBC0,0x8AD6,0x0000, 0xFBC0,0x8AD7,0x0000, /* 0AD5 */ +0xFBC0,0x8AD8,0x0000, 0xFBC0,0x8AD9,0x0000, 0xFBC0,0x8ADA,0x0000, /* 0AD8 */ +0xFBC0,0x8ADB,0x0000, 0xFBC0,0x8ADC,0x0000, 0xFBC0,0x8ADD,0x0000, /* 0ADB */ +0xFBC0,0x8ADE,0x0000, 0xFBC0,0x8ADF,0x0000, 0x1C7F,0x0000,0x0000, /* 0ADE */ +0x1C81,0x0000,0x0000, 0x1CB2,0x0000,0x0000, 0x1CB3,0x0000,0x0000, /* 0AE1 */ +0xFBC0,0x8AE4,0x0000, 0xFBC0,0x8AE5,0x0000, 0x1205,0x0000,0x0000, /* 0AE4 */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 0AE7 */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 0AEA */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 0AED */ +0xFBC0,0x8AF0,0x0000, 0x11E8,0x0000,0x0000, 0xFBC0,0x8AF2,0x0000, /* 0AF0 */ +0xFBC0,0x8AF3,0x0000, 0xFBC0,0x8AF4,0x0000, 0xFBC0,0x8AF5,0x0000, /* 0AF3 */ +0xFBC0,0x8AF6,0x0000, 0xFBC0,0x8AF7,0x0000, 0xFBC0,0x8AF8,0x0000, /* 0AF6 */ +0xFBC0,0x8AF9,0x0000, 0xFBC0,0x8AFA,0x0000, 0xFBC0,0x8AFB,0x0000, /* 0AF9 */ +0xFBC0,0x8AFC,0x0000, 0xFBC0,0x8AFD,0x0000, 0xFBC0,0x8AFE,0x0000, /* 0AFC */ +0xFBC0,0x8AFF,0x0000 }; + +uint16 uca520_p00B[]= { /* 0B00 (3 weights per char) */ +0xFBC0,0x8B00,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0B00 */ +0x0000,0x0000,0x0000, 0xFBC0,0x8B04,0x0000, 0x1CBB,0x0000,0x0000, /* 0B03 */ +0x1CBC,0x0000,0x0000, 0x1CBD,0x0000,0x0000, 0x1CBE,0x0000,0x0000, /* 0B06 */ +0x1CBF,0x0000,0x0000, 0x1CC0,0x0000,0x0000, 0x1CC1,0x0000,0x0000, /* 0B09 */ +0x1CC3,0x0000,0x0000, 0xFBC0,0x8B0D,0x0000, 0xFBC0,0x8B0E,0x0000, /* 0B0C */ +0x1CC5,0x0000,0x0000, 0x1CC6,0x0000,0x0000, 0xFBC0,0x8B11,0x0000, /* 0B0F */ +0xFBC0,0x8B12,0x0000, 0x1CC7,0x0000,0x0000, 0x1CC8,0x0000,0x0000, /* 0B12 */ +0x1CC9,0x0000,0x0000, 0x1CCA,0x0000,0x0000, 0x1CCB,0x0000,0x0000, /* 0B15 */ +0x1CCC,0x0000,0x0000, 0x1CCD,0x0000,0x0000, 0x1CCE,0x0000,0x0000, /* 0B18 */ +0x1CCF,0x0000,0x0000, 0x1CD0,0x0000,0x0000, 0x1CD1,0x0000,0x0000, /* 0B1B */ +0x1CD2,0x0000,0x0000, 0x1CD3,0x0000,0x0000, 0x1CD4,0x0000,0x0000, /* 0B1E */ +0x1CD5,0x0000,0x0000, 0x1CD6,0x0000,0x0000, 0x1CD7,0x0000,0x0000, /* 0B21 */ +0x1CD8,0x0000,0x0000, 0x1CD9,0x0000,0x0000, 0x1CDA,0x0000,0x0000, /* 0B24 */ +0x1CDB,0x0000,0x0000, 0x1CDC,0x0000,0x0000, 0xFBC0,0x8B29,0x0000, /* 0B27 */ +0x1CDD,0x0000,0x0000, 0x1CDE,0x0000,0x0000, 0x1CDF,0x0000,0x0000, /* 0B2A */ +0x1CE0,0x0000,0x0000, 0x1CE1,0x0000,0x0000, 0x1CE2,0x0000,0x0000, /* 0B2D */ +0x1CE4,0x0000,0x0000, 0xFBC0,0x8B31,0x0000, 0x1CE5,0x0000,0x0000, /* 0B30 */ +0x1CE6,0x0000,0x0000, 0xFBC0,0x8B34,0x0000, 0x1CE7,0x0000,0x0000, /* 0B33 */ +0x1CE9,0x0000,0x0000, 0x1CEA,0x0000,0x0000, 0x1CEB,0x0000,0x0000, /* 0B36 */ +0x1CEC,0x0000,0x0000, 0xFBC0,0x8B3A,0x0000, 0xFBC0,0x8B3B,0x0000, /* 0B39 */ +0x0000,0x0000,0x0000, 0x1CED,0x0000,0x0000, 0x1CEE,0x0000,0x0000, /* 0B3C */ +0x1CEF,0x0000,0x0000, 0x1CF0,0x0000,0x0000, 0x1CF1,0x0000,0x0000, /* 0B3F */ +0x1CF2,0x0000,0x0000, 0x1CF3,0x0000,0x0000, 0x1CF4,0x0000,0x0000, /* 0B42 */ +0xFBC0,0x8B45,0x0000, 0xFBC0,0x8B46,0x0000, 0x1CF7,0x0000,0x0000, /* 0B45 */ +0x1CF8,0x0000,0x0000, 0xFBC0,0x8B49,0x0000, 0xFBC0,0x8B4A,0x0000, /* 0B48 */ +0x1CF9,0x0000,0x0000, 0x1CFA,0x0000,0x0000, 0x1CFB,0x0000,0x0000, /* 0B4B */ +0xFBC0,0x8B4E,0x0000, 0xFBC0,0x8B4F,0x0000, 0xFBC0,0x8B50,0x0000, /* 0B4E */ +0xFBC0,0x8B51,0x0000, 0xFBC0,0x8B52,0x0000, 0xFBC0,0x8B53,0x0000, /* 0B51 */ +0xFBC0,0x8B54,0x0000, 0xFBC0,0x8B55,0x0000, 0x1CFC,0x0000,0x0000, /* 0B54 */ +0x1CFD,0x0000,0x0000, 0xFBC0,0x8B58,0x0000, 0xFBC0,0x8B59,0x0000, /* 0B57 */ +0xFBC0,0x8B5A,0x0000, 0xFBC0,0x8B5B,0x0000, 0x1CD5,0x0000,0x0000, /* 0B5A */ +0x1CD6,0x0000,0x0000, 0xFBC0,0x8B5E,0x0000, 0x1CE3,0x0000,0x0000, /* 0B5D */ +0x1CC2,0x0000,0x0000, 0x1CC4,0x0000,0x0000, 0x1CF5,0x0000,0x0000, /* 0B60 */ +0x1CF6,0x0000,0x0000, 0xFBC0,0x8B64,0x0000, 0xFBC0,0x8B65,0x0000, /* 0B63 */ +0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 0B66 */ +0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, /* 0B69 */ +0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, /* 0B6C */ +0x120E,0x0000,0x0000, 0x0454,0x0000,0x0000, 0x1CE8,0x0000,0x0000, /* 0B6F */ +0xFBC0,0x8B72,0x0000, 0xFBC0,0x8B73,0x0000, 0xFBC0,0x8B74,0x0000, /* 0B72 */ +0xFBC0,0x8B75,0x0000, 0xFBC0,0x8B76,0x0000, 0xFBC0,0x8B77,0x0000, /* 0B75 */ +0xFBC0,0x8B78,0x0000, 0xFBC0,0x8B79,0x0000, 0xFBC0,0x8B7A,0x0000, /* 0B78 */ +0xFBC0,0x8B7B,0x0000, 0xFBC0,0x8B7C,0x0000, 0xFBC0,0x8B7D,0x0000, /* 0B7B */ +0xFBC0,0x8B7E,0x0000, 0xFBC0,0x8B7F,0x0000, 0xFBC0,0x8B80,0x0000, /* 0B7E */ +0xFBC0,0x8B81,0x0000, 0x0000,0x0000,0x0000, 0x1D0B,0x0000,0x0000, /* 0B81 */ +0xFBC0,0x8B84,0x0000, 0x1CFF,0x0000,0x0000, 0x1D00,0x0000,0x0000, /* 0B84 */ +0x1D01,0x0000,0x0000, 0x1D02,0x0000,0x0000, 0x1D03,0x0000,0x0000, /* 0B87 */ +0x1D04,0x0000,0x0000, 0xFBC0,0x8B8B,0x0000, 0xFBC0,0x8B8C,0x0000, /* 0B8A */ +0xFBC0,0x8B8D,0x0000, 0x1D05,0x0000,0x0000, 0x1D06,0x0000,0x0000, /* 0B8D */ +0x1D07,0x0000,0x0000, 0xFBC0,0x8B91,0x0000, 0x1D08,0x0000,0x0000, /* 0B90 */ +0x1D09,0x0000,0x0000, 0x1D0A,0x0000,0x0000, 0x1D0C,0x0000,0x0000, /* 0B93 */ +0xFBC0,0x8B96,0x0000, 0xFBC0,0x8B97,0x0000, 0xFBC0,0x8B98,0x0000, /* 0B96 */ +0x1D0D,0x0000,0x0000, 0x1D0E,0x0000,0x0000, 0xFBC0,0x8B9B,0x0000, /* 0B99 */ +0x1D1E,0x0000,0x0000, 0xFBC0,0x8B9D,0x0000, 0x1D0F,0x0000,0x0000, /* 0B9C */ +0x1D10,0x0000,0x0000, 0xFBC0,0x8BA0,0x0000, 0xFBC0,0x8BA1,0x0000, /* 0B9F */ +0xFBC0,0x8BA2,0x0000, 0x1D11,0x0000,0x0000, 0x1D12,0x0000,0x0000, /* 0BA2 */ +0xFBC0,0x8BA5,0x0000, 0xFBC0,0x8BA6,0x0000, 0xFBC0,0x8BA7,0x0000, /* 0BA5 */ +0x1D13,0x0000,0x0000, 0x1D1D,0x0000,0x0000, 0x1D14,0x0000,0x0000, /* 0BA8 */ +0xFBC0,0x8BAB,0x0000, 0xFBC0,0x8BAC,0x0000, 0xFBC0,0x8BAD,0x0000, /* 0BAB */ +0x1D15,0x0000,0x0000, 0x1D16,0x0000,0x0000, 0x1D17,0x0000,0x0000, /* 0BAE */ +0x1D1C,0x0000,0x0000, 0x1D18,0x0000,0x0000, 0x1D1B,0x0000,0x0000, /* 0BB1 */ +0x1D1A,0x0000,0x0000, 0x1D19,0x0000,0x0000, 0x1D1F,0x0000,0x0000, /* 0BB4 */ +0x1D20,0x0000,0x0000, 0x1D21,0x0000,0x0000, 0x1D22,0x0000,0x0000, /* 0BB7 */ +0xFBC0,0x8BBA,0x0000, 0xFBC0,0x8BBB,0x0000, 0xFBC0,0x8BBC,0x0000, /* 0BBA */ +0xFBC0,0x8BBD,0x0000, 0x1D23,0x0000,0x0000, 0x1D24,0x0000,0x0000, /* 0BBD */ +0x1D25,0x0000,0x0000, 0x1D26,0x0000,0x0000, 0x1D27,0x0000,0x0000, /* 0BC0 */ +0xFBC0,0x8BC3,0x0000, 0xFBC0,0x8BC4,0x0000, 0xFBC0,0x8BC5,0x0000, /* 0BC3 */ +0x1D28,0x0000,0x0000, 0x1D29,0x0000,0x0000, 0x1D2A,0x0000,0x0000, /* 0BC6 */ +0xFBC0,0x8BC9,0x0000, 0x1D2B,0x0000,0x0000, 0x1D2C,0x0000,0x0000, /* 0BC9 */ +0x1D2D,0x0000,0x0000, 0x1D2E,0x0000,0x0000, 0xFBC0,0x8BCE,0x0000, /* 0BCC */ +0xFBC0,0x8BCF,0x0000, 0x1CFE,0x0000,0x0000, 0xFBC0,0x8BD1,0x0000, /* 0BCF */ +0xFBC0,0x8BD2,0x0000, 0xFBC0,0x8BD3,0x0000, 0xFBC0,0x8BD4,0x0000, /* 0BD2 */ +0xFBC0,0x8BD5,0x0000, 0xFBC0,0x8BD6,0x0000, 0x1D2F,0x0000,0x0000, /* 0BD5 */ +0xFBC0,0x8BD8,0x0000, 0xFBC0,0x8BD9,0x0000, 0xFBC0,0x8BDA,0x0000, /* 0BD8 */ +0xFBC0,0x8BDB,0x0000, 0xFBC0,0x8BDC,0x0000, 0xFBC0,0x8BDD,0x0000, /* 0BDB */ +0xFBC0,0x8BDE,0x0000, 0xFBC0,0x8BDF,0x0000, 0xFBC0,0x8BE0,0x0000, /* 0BDE */ +0xFBC0,0x8BE1,0x0000, 0xFBC0,0x8BE2,0x0000, 0xFBC0,0x8BE3,0x0000, /* 0BE1 */ +0xFBC0,0x8BE4,0x0000, 0xFBC0,0x8BE5,0x0000, 0x1205,0x0000,0x0000, /* 0BE4 */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 0BE7 */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 0BEA */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 0BED */ +0x111C,0x0000,0x0000, 0x111D,0x0000,0x0000, 0x111E,0x0000,0x0000, /* 0BF0 */ +0x0455,0x0000,0x0000, 0x0456,0x0000,0x0000, 0x0457,0x0000,0x0000, /* 0BF3 */ +0x0458,0x0000,0x0000, 0x0459,0x0000,0x0000, 0x045A,0x0000,0x0000, /* 0BF6 */ +0x11EA,0x0000,0x0000, 0x045B,0x0000,0x0000, 0xFBC0,0x8BFB,0x0000, /* 0BF9 */ +0xFBC0,0x8BFC,0x0000, 0xFBC0,0x8BFD,0x0000, 0xFBC0,0x8BFE,0x0000, /* 0BFC */ +0xFBC0,0x8BFF,0x0000 }; + +uint16 uca520_p00C[]= { /* 0C00 (3 weights per char) */ +0xFBC0,0x8C00,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0C00 */ +0x0000,0x0000,0x0000, 0xFBC0,0x8C04,0x0000, 0x1D30,0x0000,0x0000, /* 0C03 */ +0x1D31,0x0000,0x0000, 0x1D32,0x0000,0x0000, 0x1D33,0x0000,0x0000, /* 0C06 */ +0x1D34,0x0000,0x0000, 0x1D35,0x0000,0x0000, 0x1D36,0x0000,0x0000, /* 0C09 */ +0x1D38,0x0000,0x0000, 0xFBC0,0x8C0D,0x0000, 0x1D3A,0x0000,0x0000, /* 0C0C */ +0x1D3B,0x0000,0x0000, 0x1D3C,0x0000,0x0000, 0xFBC0,0x8C11,0x0000, /* 0C0F */ +0x1D3D,0x0000,0x0000, 0x1D3E,0x0000,0x0000, 0x1D3F,0x0000,0x0000, /* 0C12 */ +0x1D40,0x0000,0x0000, 0x1D41,0x0000,0x0000, 0x1D42,0x0000,0x0000, /* 0C15 */ +0x1D43,0x0000,0x0000, 0x1D44,0x0000,0x0000, 0x1D45,0x0000,0x0000, /* 0C18 */ +0x1D47,0x0000,0x0000, 0x1D48,0x0000,0x0000, 0x1D4A,0x0000,0x0000, /* 0C1B */ +0x1D4B,0x0000,0x0000, 0x1D4C,0x0000,0x0000, 0x1D4D,0x0000,0x0000, /* 0C1E */ +0x1D4E,0x0000,0x0000, 0x1D4F,0x0000,0x0000, 0x1D50,0x0000,0x0000, /* 0C21 */ +0x1D51,0x0000,0x0000, 0x1D52,0x0000,0x0000, 0x1D53,0x0000,0x0000, /* 0C24 */ +0x1D54,0x0000,0x0000, 0x1D55,0x0000,0x0000, 0xFBC0,0x8C29,0x0000, /* 0C27 */ +0x1D56,0x0000,0x0000, 0x1D57,0x0000,0x0000, 0x1D58,0x0000,0x0000, /* 0C2A */ +0x1D59,0x0000,0x0000, 0x1D5A,0x0000,0x0000, 0x1D5B,0x0000,0x0000, /* 0C2D */ +0x1D5C,0x0000,0x0000, 0x1D5D,0x0000,0x0000, 0x1D5E,0x0000,0x0000, /* 0C30 */ +0x1D64,0x0000,0x0000, 0xFBC0,0x8C34,0x0000, 0x1D5F,0x0000,0x0000, /* 0C33 */ +0x1D60,0x0000,0x0000, 0x1D61,0x0000,0x0000, 0x1D62,0x0000,0x0000, /* 0C36 */ +0x1D63,0x0000,0x0000, 0xFBC0,0x8C3A,0x0000, 0xFBC0,0x8C3B,0x0000, /* 0C39 */ +0xFBC0,0x8C3C,0x0000, 0x1D65,0x0000,0x0000, 0x1D66,0x0000,0x0000, /* 0C3C */ +0x1D67,0x0000,0x0000, 0x1D68,0x0000,0x0000, 0x1D69,0x0000,0x0000, /* 0C3F */ +0x1D6A,0x0000,0x0000, 0x1D6B,0x0000,0x0000, 0x1D6C,0x0000,0x0000, /* 0C42 */ +0xFBC0,0x8C45,0x0000, 0x1D6F,0x0000,0x0000, 0x1D70,0x0000,0x0000, /* 0C45 */ +0x1D71,0x0000,0x0000, 0xFBC0,0x8C49,0x0000, 0x1D72,0x0000,0x0000, /* 0C48 */ +0x1D73,0x0000,0x0000, 0x1D74,0x0000,0x0000, 0x1D75,0x0000,0x0000, /* 0C4B */ +0xFBC0,0x8C4E,0x0000, 0xFBC0,0x8C4F,0x0000, 0xFBC0,0x8C50,0x0000, /* 0C4E */ +0xFBC0,0x8C51,0x0000, 0xFBC0,0x8C52,0x0000, 0xFBC0,0x8C53,0x0000, /* 0C51 */ +0xFBC0,0x8C54,0x0000, 0x1D76,0x0000,0x0000, 0x1D77,0x0000,0x0000, /* 0C54 */ +0xFBC0,0x8C57,0x0000, 0x1D46,0x0000,0x0000, 0x1D49,0x0000,0x0000, /* 0C57 */ +0xFBC0,0x8C5A,0x0000, 0xFBC0,0x8C5B,0x0000, 0xFBC0,0x8C5C,0x0000, /* 0C5A */ +0xFBC0,0x8C5D,0x0000, 0xFBC0,0x8C5E,0x0000, 0xFBC0,0x8C5F,0x0000, /* 0C5D */ +0x1D37,0x0000,0x0000, 0x1D39,0x0000,0x0000, 0x1D6D,0x0000,0x0000, /* 0C60 */ +0x1D6E,0x0000,0x0000, 0xFBC0,0x8C64,0x0000, 0xFBC0,0x8C65,0x0000, /* 0C63 */ +0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 0C66 */ +0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, /* 0C69 */ +0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, /* 0C6C */ +0x120E,0x0000,0x0000, 0xFBC0,0x8C70,0x0000, 0xFBC0,0x8C71,0x0000, /* 0C6F */ +0xFBC0,0x8C72,0x0000, 0xFBC0,0x8C73,0x0000, 0xFBC0,0x8C74,0x0000, /* 0C72 */ +0xFBC0,0x8C75,0x0000, 0xFBC0,0x8C76,0x0000, 0xFBC0,0x8C77,0x0000, /* 0C75 */ +0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 0C78 */ +0x1208,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 0C7B */ +0x1208,0x0000,0x0000, 0x045C,0x0000,0x0000, 0xFBC0,0x8C80,0x0000, /* 0C7E */ +0xFBC0,0x8C81,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0C81 */ +0xFBC0,0x8C84,0x0000, 0x1D78,0x0000,0x0000, 0x1D79,0x0000,0x0000, /* 0C84 */ +0x1D7A,0x0000,0x0000, 0x1D7B,0x0000,0x0000, 0x1D7C,0x0000,0x0000, /* 0C87 */ +0x1D7D,0x0000,0x0000, 0x1D7E,0x0000,0x0000, 0x1D80,0x0000,0x0000, /* 0C8A */ +0xFBC0,0x8C8D,0x0000, 0x1D82,0x0000,0x0000, 0x1D83,0x0000,0x0000, /* 0C8D */ +0x1D84,0x0000,0x0000, 0xFBC0,0x8C91,0x0000, 0x1D85,0x0000,0x0000, /* 0C90 */ +0x1D86,0x0000,0x0000, 0x1D87,0x0000,0x0000, 0x1D88,0x0000,0x0000, /* 0C93 */ +0x1D89,0x0000,0x0000, 0x1D8A,0x0000,0x0000, 0x1D8B,0x0000,0x0000, /* 0C96 */ +0x1D8C,0x0000,0x0000, 0x1D8D,0x0000,0x0000, 0x1D8E,0x0000,0x0000, /* 0C99 */ +0x1D8F,0x0000,0x0000, 0x1D90,0x0000,0x0000, 0x1D91,0x0000,0x0000, /* 0C9C */ +0x1D92,0x0000,0x0000, 0x1D93,0x0000,0x0000, 0x1D94,0x0000,0x0000, /* 0C9F */ +0x1D95,0x0000,0x0000, 0x1D96,0x0000,0x0000, 0x1D97,0x0000,0x0000, /* 0CA2 */ +0x1D98,0x0000,0x0000, 0x1D99,0x0000,0x0000, 0x1D9A,0x0000,0x0000, /* 0CA5 */ +0x1D9B,0x0000,0x0000, 0xFBC0,0x8CA9,0x0000, 0x1D9C,0x0000,0x0000, /* 0CA8 */ +0x1D9D,0x0000,0x0000, 0x1D9E,0x0000,0x0000, 0x1D9F,0x0000,0x0000, /* 0CAB */ +0x1DA0,0x0000,0x0000, 0x1DA1,0x0000,0x0000, 0x1DA2,0x0000,0x0000, /* 0CAE */ +0x1DA3,0x0000,0x0000, 0x1DA4,0x0000,0x0000, 0x1DAA,0x0000,0x0000, /* 0CB1 */ +0xFBC0,0x8CB4,0x0000, 0x1DA5,0x0000,0x0000, 0x1DA6,0x0000,0x0000, /* 0CB4 */ +0x1DA7,0x0000,0x0000, 0x1DA8,0x0000,0x0000, 0x1DA9,0x0000,0x0000, /* 0CB7 */ +0xFBC0,0x8CBA,0x0000, 0xFBC0,0x8CBB,0x0000, 0x0000,0x0000,0x0000, /* 0CBA */ +0x1DAC,0x0000,0x0000, 0x1DAD,0x0000,0x0000, 0x1DAE,0x0000,0x0000, /* 0CBD */ +0x1DAF,0x0000,0x0000, 0x1DB0,0x0000,0x0000, 0x1DB1,0x0000,0x0000, /* 0CC0 */ +0x1DB2,0x0000,0x0000, 0x1DB3,0x0000,0x0000, 0xFBC0,0x8CC5,0x0000, /* 0CC3 */ +0x1DB6,0x0000,0x0000, 0x1DB7,0x0000,0x0000, 0x1DB8,0x0000,0x0000, /* 0CC6 */ +0xFBC0,0x8CC9,0x0000, 0x1DB9,0x0000,0x0000, 0x1DBA,0x0000,0x0000, /* 0CC9 */ +0x1DBB,0x0000,0x0000, 0x1DBC,0x0000,0x0000, 0xFBC0,0x8CCE,0x0000, /* 0CCC */ +0xFBC0,0x8CCF,0x0000, 0xFBC0,0x8CD0,0x0000, 0xFBC0,0x8CD1,0x0000, /* 0CCF */ +0xFBC0,0x8CD2,0x0000, 0xFBC0,0x8CD3,0x0000, 0xFBC0,0x8CD4,0x0000, /* 0CD2 */ +0x1DBD,0x0000,0x0000, 0x1DBE,0x0000,0x0000, 0xFBC0,0x8CD7,0x0000, /* 0CD5 */ +0xFBC0,0x8CD8,0x0000, 0xFBC0,0x8CD9,0x0000, 0xFBC0,0x8CDA,0x0000, /* 0CD8 */ +0xFBC0,0x8CDB,0x0000, 0xFBC0,0x8CDC,0x0000, 0xFBC0,0x8CDD,0x0000, /* 0CDB */ +0x1DAB,0x0000,0x0000, 0xFBC0,0x8CDF,0x0000, 0x1D7F,0x0000,0x0000, /* 0CDE */ +0x1D81,0x0000,0x0000, 0x1DB4,0x0000,0x0000, 0x1DB5,0x0000,0x0000, /* 0CE1 */ +0xFBC0,0x8CE4,0x0000, 0xFBC0,0x8CE5,0x0000, 0x1205,0x0000,0x0000, /* 0CE4 */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 0CE7 */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 0CEA */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 0CED */ +0xFBC0,0x8CF0,0x0000, 0x045D,0x0000,0x0000, 0x045E,0x0000,0x0000, /* 0CF0 */ +0xFBC0,0x8CF3,0x0000, 0xFBC0,0x8CF4,0x0000, 0xFBC0,0x8CF5,0x0000, /* 0CF3 */ +0xFBC0,0x8CF6,0x0000, 0xFBC0,0x8CF7,0x0000, 0xFBC0,0x8CF8,0x0000, /* 0CF6 */ +0xFBC0,0x8CF9,0x0000, 0xFBC0,0x8CFA,0x0000, 0xFBC0,0x8CFB,0x0000, /* 0CF9 */ +0xFBC0,0x8CFC,0x0000, 0xFBC0,0x8CFD,0x0000, 0xFBC0,0x8CFE,0x0000, /* 0CFC */ +0xFBC0,0x8CFF,0x0000 }; + +uint16 uca520_p00D[]= { /* 0D00 (3 weights per char) */ +0xFBC0,0x8D00,0x0000, 0xFBC0,0x8D01,0x0000, 0x0000,0x0000,0x0000, /* 0D00 */ +0x0000,0x0000,0x0000, 0xFBC0,0x8D04,0x0000, 0x1DBF,0x0000,0x0000, /* 0D03 */ +0x1DC0,0x0000,0x0000, 0x1DC1,0x0000,0x0000, 0x1DC2,0x0000,0x0000, /* 0D06 */ +0x1DC3,0x0000,0x0000, 0x1DC4,0x0000,0x0000, 0x1DC5,0x0000,0x0000, /* 0D09 */ +0x1DC7,0x0000,0x0000, 0xFBC0,0x8D0D,0x0000, 0x1DC9,0x0000,0x0000, /* 0D0C */ +0x1DCA,0x0000,0x0000, 0x1DCB,0x0000,0x0000, 0xFBC0,0x8D11,0x0000, /* 0D0F */ +0x1DCC,0x0000,0x0000, 0x1DCD,0x0000,0x0000, 0x1DCE,0x0000,0x0000, /* 0D12 */ +0x1DCF,0x0000,0x0000, 0x1DD0,0x0000,0x0000, 0x1DD1,0x0000,0x0000, /* 0D15 */ +0x1DD2,0x0000,0x0000, 0x1DD3,0x0000,0x0000, 0x1DD4,0x0000,0x0000, /* 0D18 */ +0x1DD5,0x0000,0x0000, 0x1DD6,0x0000,0x0000, 0x1DD7,0x0000,0x0000, /* 0D1B */ +0x1DD8,0x0000,0x0000, 0x1DD9,0x0000,0x0000, 0x1DDA,0x0000,0x0000, /* 0D1E */ +0x1DDB,0x0000,0x0000, 0x1DDC,0x0000,0x0000, 0x1DDD,0x0000,0x0000, /* 0D21 */ +0x1DDE,0x0000,0x0000, 0x1DDF,0x0000,0x0000, 0x1DE0,0x0000,0x0000, /* 0D24 */ +0x1DE1,0x0000,0x0000, 0x1DE2,0x0000,0x0000, 0xFBC0,0x8D29,0x0000, /* 0D27 */ +0x1DE3,0x0000,0x0000, 0x1DE4,0x0000,0x0000, 0x1DE5,0x0000,0x0000, /* 0D2A */ +0x1DE6,0x0000,0x0000, 0x1DE7,0x0000,0x0000, 0x1DE8,0x0000,0x0000, /* 0D2D */ +0x1DE9,0x0000,0x0000, 0x1DF2,0x0000,0x0000, 0x1DEA,0x0000,0x0000, /* 0D30 */ +0x1DF0,0x0000,0x0000, 0x1DF1,0x0000,0x0000, 0x1DEB,0x0000,0x0000, /* 0D33 */ +0x1DEC,0x0000,0x0000, 0x1DED,0x0000,0x0000, 0x1DEE,0x0000,0x0000, /* 0D36 */ +0x1DEF,0x0000,0x0000, 0xFBC0,0x8D3A,0x0000, 0xFBC0,0x8D3B,0x0000, /* 0D39 */ +0xFBC0,0x8D3C,0x0000, 0x1DF3,0x0000,0x0000, 0x1DF4,0x0000,0x0000, /* 0D3C */ +0x1DF5,0x0000,0x0000, 0x1DF6,0x0000,0x0000, 0x1DF7,0x0000,0x0000, /* 0D3F */ +0x1DF8,0x0000,0x0000, 0x1DF9,0x0000,0x0000, 0x1DFA,0x0000,0x0000, /* 0D42 */ +0xFBC0,0x8D45,0x0000, 0x1DFD,0x0000,0x0000, 0x1DFE,0x0000,0x0000, /* 0D45 */ +0x1DFF,0x0000,0x0000, 0xFBC0,0x8D49,0x0000, 0x1E00,0x0000,0x0000, /* 0D48 */ +0x1E01,0x0000,0x0000, 0x1E02,0x0000,0x0000, 0x1E04,0x0000,0x0000, /* 0D4B */ +0xFBC0,0x8D4E,0x0000, 0xFBC0,0x8D4F,0x0000, 0xFBC0,0x8D50,0x0000, /* 0D4E */ +0xFBC0,0x8D51,0x0000, 0xFBC0,0x8D52,0x0000, 0xFBC0,0x8D53,0x0000, /* 0D51 */ +0xFBC0,0x8D54,0x0000, 0xFBC0,0x8D55,0x0000, 0xFBC0,0x8D56,0x0000, /* 0D54 */ +0x1E03,0x0000,0x0000, 0xFBC0,0x8D58,0x0000, 0xFBC0,0x8D59,0x0000, /* 0D57 */ +0xFBC0,0x8D5A,0x0000, 0xFBC0,0x8D5B,0x0000, 0xFBC0,0x8D5C,0x0000, /* 0D5A */ +0xFBC0,0x8D5D,0x0000, 0xFBC0,0x8D5E,0x0000, 0xFBC0,0x8D5F,0x0000, /* 0D5D */ +0x1DC6,0x0000,0x0000, 0x1DC8,0x0000,0x0000, 0x1DFB,0x0000,0x0000, /* 0D60 */ +0x1DFC,0x0000,0x0000, 0xFBC0,0x8D64,0x0000, 0xFBC0,0x8D65,0x0000, /* 0D63 */ +0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 0D66 */ +0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, /* 0D69 */ +0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, /* 0D6C */ +0x120E,0x0000,0x0000, 0x111F,0x0000,0x0000, 0x1120,0x0000,0x0000, /* 0D6F */ +0x1121,0x0000,0x0000, 0x1122,0x0000,0x0000, 0x1123,0x0000,0x0000, /* 0D72 */ +0x1124,0x0000,0x0000, 0xFBC0,0x8D76,0x0000, 0xFBC0,0x8D77,0x0000, /* 0D75 */ +0xFBC0,0x8D78,0x0000, 0x045F,0x0000,0x0000, 0x1DDD,0x1E04,0x0000, /* 0D78 */ +0x1DE2,0x1E04,0x0000, 0x1DE9,0x1E04,0x0000, 0x1DEA,0x1E04,0x0000, /* 0D7B */ +0x1DF0,0x1E04,0x0000, 0x1DCF,0x1E04,0x0000, 0xFBC0,0x8D80,0x0000, /* 0D7E */ +0xFBC0,0x8D81,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0D81 */ +0xFBC0,0x8D84,0x0000, 0x1E05,0x0000,0x0000, 0x1E06,0x0000,0x0000, /* 0D84 */ +0x1E07,0x0000,0x0000, 0x1E08,0x0000,0x0000, 0x1E09,0x0000,0x0000, /* 0D87 */ +0x1E0A,0x0000,0x0000, 0x1E0B,0x0000,0x0000, 0x1E0C,0x0000,0x0000, /* 0D8A */ +0x1E0D,0x0000,0x0000, 0x1E0E,0x0000,0x0000, 0x1E0F,0x0000,0x0000, /* 0D8D */ +0x1E10,0x0000,0x0000, 0x1E11,0x0000,0x0000, 0x1E12,0x0000,0x0000, /* 0D90 */ +0x1E13,0x0000,0x0000, 0x1E14,0x0000,0x0000, 0x1E15,0x0000,0x0000, /* 0D93 */ +0x1E16,0x0000,0x0000, 0xFBC0,0x8D97,0x0000, 0xFBC0,0x8D98,0x0000, /* 0D96 */ +0xFBC0,0x8D99,0x0000, 0x1E17,0x0000,0x0000, 0x1E18,0x0000,0x0000, /* 0D99 */ +0x1E19,0x0000,0x0000, 0x1E1A,0x0000,0x0000, 0x1E1B,0x0000,0x0000, /* 0D9C */ +0x1E1C,0x0000,0x0000, 0x1E1D,0x0000,0x0000, 0x1E1E,0x0000,0x0000, /* 0D9F */ +0x1E1F,0x0000,0x0000, 0x1E20,0x0000,0x0000, 0x1E21,0x0000,0x0000, /* 0DA2 */ +0x1E22,0x0000,0x0000, 0x1E23,0x0000,0x0000, 0x1E24,0x0000,0x0000, /* 0DA5 */ +0x1E25,0x0000,0x0000, 0x1E26,0x0000,0x0000, 0x1E27,0x0000,0x0000, /* 0DA8 */ +0x1E28,0x0000,0x0000, 0x1E29,0x0000,0x0000, 0x1E2A,0x0000,0x0000, /* 0DAB */ +0x1E2B,0x0000,0x0000, 0x1E2C,0x0000,0x0000, 0x1E2D,0x0000,0x0000, /* 0DAE */ +0x1E2E,0x0000,0x0000, 0xFBC0,0x8DB2,0x0000, 0x1E2F,0x0000,0x0000, /* 0DB1 */ +0x1E30,0x0000,0x0000, 0x1E31,0x0000,0x0000, 0x1E32,0x0000,0x0000, /* 0DB4 */ +0x1E33,0x0000,0x0000, 0x1E34,0x0000,0x0000, 0x1E35,0x0000,0x0000, /* 0DB7 */ +0x1E36,0x0000,0x0000, 0x1E37,0x0000,0x0000, 0xFBC0,0x8DBC,0x0000, /* 0DBA */ +0x1E38,0x0000,0x0000, 0xFBC0,0x8DBE,0x0000, 0xFBC0,0x8DBF,0x0000, /* 0DBD */ +0x1E39,0x0000,0x0000, 0x1E3A,0x0000,0x0000, 0x1E3B,0x0000,0x0000, /* 0DC0 */ +0x1E3C,0x0000,0x0000, 0x1E3D,0x0000,0x0000, 0x1E3E,0x0000,0x0000, /* 0DC3 */ +0x1E3F,0x0000,0x0000, 0xFBC0,0x8DC7,0x0000, 0xFBC0,0x8DC8,0x0000, /* 0DC6 */ +0xFBC0,0x8DC9,0x0000, 0x1E51,0x0000,0x0000, 0xFBC0,0x8DCB,0x0000, /* 0DC9 */ +0xFBC0,0x8DCC,0x0000, 0xFBC0,0x8DCD,0x0000, 0xFBC0,0x8DCE,0x0000, /* 0DCC */ +0x1E40,0x0000,0x0000, 0x1E41,0x0000,0x0000, 0x1E42,0x0000,0x0000, /* 0DCF */ +0x1E43,0x0000,0x0000, 0x1E44,0x0000,0x0000, 0x1E45,0x0000,0x0000, /* 0DD2 */ +0xFBC0,0x8DD5,0x0000, 0x1E46,0x0000,0x0000, 0xFBC0,0x8DD7,0x0000, /* 0DD5 */ +0x1E47,0x0000,0x0000, 0x1E4B,0x0000,0x0000, 0x1E4C,0x0000,0x0000, /* 0DD8 */ +0x1E4D,0x0000,0x0000, 0x1E4E,0x0000,0x0000, 0x1E4F,0x0000,0x0000, /* 0DDB */ +0x1E50,0x0000,0x0000, 0x1E49,0x0000,0x0000, 0xFBC0,0x8DE0,0x0000, /* 0DDE */ +0xFBC0,0x8DE1,0x0000, 0xFBC0,0x8DE2,0x0000, 0xFBC0,0x8DE3,0x0000, /* 0DE1 */ +0xFBC0,0x8DE4,0x0000, 0xFBC0,0x8DE5,0x0000, 0xFBC0,0x8DE6,0x0000, /* 0DE4 */ +0xFBC0,0x8DE7,0x0000, 0xFBC0,0x8DE8,0x0000, 0xFBC0,0x8DE9,0x0000, /* 0DE7 */ +0xFBC0,0x8DEA,0x0000, 0xFBC0,0x8DEB,0x0000, 0xFBC0,0x8DEC,0x0000, /* 0DEA */ +0xFBC0,0x8DED,0x0000, 0xFBC0,0x8DEE,0x0000, 0xFBC0,0x8DEF,0x0000, /* 0DED */ +0xFBC0,0x8DF0,0x0000, 0xFBC0,0x8DF1,0x0000, 0x1E48,0x0000,0x0000, /* 0DF0 */ +0x1E4A,0x0000,0x0000, 0x03A5,0x0000,0x0000, 0xFBC0,0x8DF5,0x0000, /* 0DF3 */ +0xFBC0,0x8DF6,0x0000, 0xFBC0,0x8DF7,0x0000, 0xFBC0,0x8DF8,0x0000, /* 0DF6 */ +0xFBC0,0x8DF9,0x0000, 0xFBC0,0x8DFA,0x0000, 0xFBC0,0x8DFB,0x0000, /* 0DF9 */ +0xFBC0,0x8DFC,0x0000, 0xFBC0,0x8DFD,0x0000, 0xFBC0,0x8DFE,0x0000, /* 0DFC */ +0xFBC0,0x8DFF,0x0000 }; + +uint16 uca520_p00E[]= { /* 0E00 (3 weights per char) */ +0xFBC0,0x8E00,0x0000, 0x1F70,0x0000,0x0000, 0x1F71,0x0000,0x0000, /* 0E00 */ +0x1F72,0x0000,0x0000, 0x1F73,0x0000,0x0000, 0x1F74,0x0000,0x0000, /* 0E03 */ +0x1F75,0x0000,0x0000, 0x1F76,0x0000,0x0000, 0x1F77,0x0000,0x0000, /* 0E06 */ +0x1F78,0x0000,0x0000, 0x1F79,0x0000,0x0000, 0x1F7A,0x0000,0x0000, /* 0E09 */ +0x1F7B,0x0000,0x0000, 0x1F7C,0x0000,0x0000, 0x1F7D,0x0000,0x0000, /* 0E0C */ +0x1F7E,0x0000,0x0000, 0x1F7F,0x0000,0x0000, 0x1F80,0x0000,0x0000, /* 0E0F */ +0x1F81,0x0000,0x0000, 0x1F82,0x0000,0x0000, 0x1F83,0x0000,0x0000, /* 0E12 */ +0x1F84,0x0000,0x0000, 0x1F85,0x0000,0x0000, 0x1F86,0x0000,0x0000, /* 0E15 */ +0x1F87,0x0000,0x0000, 0x1F88,0x0000,0x0000, 0x1F89,0x0000,0x0000, /* 0E18 */ +0x1F8A,0x0000,0x0000, 0x1F8B,0x0000,0x0000, 0x1F8C,0x0000,0x0000, /* 0E1B */ +0x1F8D,0x0000,0x0000, 0x1F8E,0x0000,0x0000, 0x1F8F,0x0000,0x0000, /* 0E1E */ +0x1F90,0x0000,0x0000, 0x1F91,0x0000,0x0000, 0x1F92,0x0000,0x0000, /* 0E21 */ +0x1F93,0x0000,0x0000, 0x1F94,0x0000,0x0000, 0x1F95,0x0000,0x0000, /* 0E24 */ +0x1F96,0x0000,0x0000, 0x1F97,0x0000,0x0000, 0x1F98,0x0000,0x0000, /* 0E27 */ +0x1F99,0x0000,0x0000, 0x1F9A,0x0000,0x0000, 0x1F9B,0x0000,0x0000, /* 0E2A */ +0x1F9C,0x0000,0x0000, 0x1F9D,0x0000,0x0000, 0x1F9E,0x0000,0x0000, /* 0E2D */ +0x1F9F,0x0000,0x0000, 0x1FA0,0x0000,0x0000, 0x1FA1,0x0000,0x0000, /* 0E30 */ +0x1FA2,0x0000,0x0000, 0x1FA3,0x0000,0x0000, 0x1FA4,0x0000,0x0000, /* 0E33 */ +0x1FA5,0x0000,0x0000, 0x1FA6,0x0000,0x0000, 0x1FA7,0x0000,0x0000, /* 0E36 */ +0x1FA8,0x0000,0x0000, 0x1FA9,0x0000,0x0000, 0xFBC0,0x8E3B,0x0000, /* 0E39 */ +0xFBC0,0x8E3C,0x0000, 0xFBC0,0x8E3D,0x0000, 0xFBC0,0x8E3E,0x0000, /* 0E3C */ +0x11EB,0x0000,0x0000, 0x1FAA,0x0000,0x0000, 0x1FAB,0x0000,0x0000, /* 0E3F */ +0x1FAC,0x0000,0x0000, 0x1FAD,0x0000,0x0000, 0x1FAE,0x0000,0x0000, /* 0E42 */ +0x1FAF,0x0000,0x0000, 0x11D1,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0E45 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0E48 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0E4B */ +0x0000,0x0000,0x0000, 0x0467,0x0000,0x0000, 0x1205,0x0000,0x0000, /* 0E4E */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 0E51 */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 0E54 */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 0E57 */ +0x03A6,0x0000,0x0000, 0x03A7,0x0000,0x0000, 0xFBC0,0x8E5C,0x0000, /* 0E5A */ +0xFBC0,0x8E5D,0x0000, 0xFBC0,0x8E5E,0x0000, 0xFBC0,0x8E5F,0x0000, /* 0E5D */ +0xFBC0,0x8E60,0x0000, 0xFBC0,0x8E61,0x0000, 0xFBC0,0x8E62,0x0000, /* 0E60 */ +0xFBC0,0x8E63,0x0000, 0xFBC0,0x8E64,0x0000, 0xFBC0,0x8E65,0x0000, /* 0E63 */ +0xFBC0,0x8E66,0x0000, 0xFBC0,0x8E67,0x0000, 0xFBC0,0x8E68,0x0000, /* 0E66 */ +0xFBC0,0x8E69,0x0000, 0xFBC0,0x8E6A,0x0000, 0xFBC0,0x8E6B,0x0000, /* 0E69 */ +0xFBC0,0x8E6C,0x0000, 0xFBC0,0x8E6D,0x0000, 0xFBC0,0x8E6E,0x0000, /* 0E6C */ +0xFBC0,0x8E6F,0x0000, 0xFBC0,0x8E70,0x0000, 0xFBC0,0x8E71,0x0000, /* 0E6F */ +0xFBC0,0x8E72,0x0000, 0xFBC0,0x8E73,0x0000, 0xFBC0,0x8E74,0x0000, /* 0E72 */ +0xFBC0,0x8E75,0x0000, 0xFBC0,0x8E76,0x0000, 0xFBC0,0x8E77,0x0000, /* 0E75 */ +0xFBC0,0x8E78,0x0000, 0xFBC0,0x8E79,0x0000, 0xFBC0,0x8E7A,0x0000, /* 0E78 */ +0xFBC0,0x8E7B,0x0000, 0xFBC0,0x8E7C,0x0000, 0xFBC0,0x8E7D,0x0000, /* 0E7B */ +0xFBC0,0x8E7E,0x0000, 0xFBC0,0x8E7F,0x0000, 0xFBC0,0x8E80,0x0000, /* 0E7E */ +0x1FB0,0x0000,0x0000, 0x1FB1,0x0000,0x0000, 0xFBC0,0x8E83,0x0000, /* 0E81 */ +0x1FB2,0x0000,0x0000, 0xFBC0,0x8E85,0x0000, 0xFBC0,0x8E86,0x0000, /* 0E84 */ +0x1FB3,0x0000,0x0000, 0x1FB4,0x0000,0x0000, 0xFBC0,0x8E89,0x0000, /* 0E87 */ +0x1FB6,0x0000,0x0000, 0xFBC0,0x8E8B,0x0000, 0xFBC0,0x8E8C,0x0000, /* 0E8A */ +0x1FB7,0x0000,0x0000, 0xFBC0,0x8E8E,0x0000, 0xFBC0,0x8E8F,0x0000, /* 0E8D */ +0xFBC0,0x8E90,0x0000, 0xFBC0,0x8E91,0x0000, 0xFBC0,0x8E92,0x0000, /* 0E90 */ +0xFBC0,0x8E93,0x0000, 0x1FB8,0x0000,0x0000, 0x1FB9,0x0000,0x0000, /* 0E93 */ +0x1FBA,0x0000,0x0000, 0x1FBB,0x0000,0x0000, 0xFBC0,0x8E98,0x0000, /* 0E96 */ +0x1FBC,0x0000,0x0000, 0x1FBD,0x0000,0x0000, 0x1FBE,0x0000,0x0000, /* 0E99 */ +0x1FBF,0x0000,0x0000, 0x1FC0,0x0000,0x0000, 0x1FC1,0x0000,0x0000, /* 0E9C */ +0x1FC2,0x0000,0x0000, 0xFBC0,0x8EA0,0x0000, 0x1FC3,0x0000,0x0000, /* 0E9F */ +0x1FC4,0x0000,0x0000, 0x1FC5,0x0000,0x0000, 0xFBC0,0x8EA4,0x0000, /* 0EA2 */ +0x1FC6,0x0000,0x0000, 0xFBC0,0x8EA6,0x0000, 0x1FC7,0x0000,0x0000, /* 0EA5 */ +0xFBC0,0x8EA8,0x0000, 0xFBC0,0x8EA9,0x0000, 0x1FB5,0x0000,0x0000, /* 0EA8 */ +0x1FC8,0x0000,0x0000, 0xFBC0,0x8EAC,0x0000, 0x1FC9,0x0000,0x0000, /* 0EAB */ +0x1FCA,0x0000,0x0000, 0x1FCB,0x0000,0x0000, 0x1FCC,0x0000,0x0000, /* 0EAE */ +0x1FCD,0x0000,0x0000, 0x1FCE,0x0000,0x0000, 0x1FCF,0x0000,0x0000, /* 0EB1 */ +0x1FD0,0x0000,0x0000, 0x1FD1,0x0000,0x0000, 0x1FD2,0x0000,0x0000, /* 0EB4 */ +0x1FD3,0x0000,0x0000, 0x1FD4,0x0000,0x0000, 0x1FD5,0x0000,0x0000, /* 0EB7 */ +0xFBC0,0x8EBA,0x0000, 0x1FD6,0x0000,0x0000, 0x1FD7,0x0000,0x0000, /* 0EBA */ +0x1FD8,0x0000,0x0000, 0xFBC0,0x8EBE,0x0000, 0xFBC0,0x8EBF,0x0000, /* 0EBD */ +0x1FD9,0x0000,0x0000, 0x1FDA,0x0000,0x0000, 0x1FDB,0x0000,0x0000, /* 0EC0 */ +0x1FDC,0x0000,0x0000, 0x1FDD,0x0000,0x0000, 0xFBC0,0x8EC5,0x0000, /* 0EC3 */ +0x11D2,0x0000,0x0000, 0xFBC0,0x8EC7,0x0000, 0x0000,0x0000,0x0000, /* 0EC6 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0EC9 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0xFBC0,0x8ECE,0x0000, /* 0ECC */ +0xFBC0,0x8ECF,0x0000, 0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, /* 0ECF */ +0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, /* 0ED2 */ +0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, /* 0ED5 */ +0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, 0xFBC0,0x8EDA,0x0000, /* 0ED8 */ +0xFBC0,0x8EDB,0x0000, 0x1FC8,0x1FBC,0x0000, 0x1FC8,0x1FC3,0x0000, /* 0EDB */ +0xFBC0,0x8EDE,0x0000, 0xFBC0,0x8EDF,0x0000, 0xFBC0,0x8EE0,0x0000, /* 0EDE */ +0xFBC0,0x8EE1,0x0000, 0xFBC0,0x8EE2,0x0000, 0xFBC0,0x8EE3,0x0000, /* 0EE1 */ +0xFBC0,0x8EE4,0x0000, 0xFBC0,0x8EE5,0x0000, 0xFBC0,0x8EE6,0x0000, /* 0EE4 */ +0xFBC0,0x8EE7,0x0000, 0xFBC0,0x8EE8,0x0000, 0xFBC0,0x8EE9,0x0000, /* 0EE7 */ +0xFBC0,0x8EEA,0x0000, 0xFBC0,0x8EEB,0x0000, 0xFBC0,0x8EEC,0x0000, /* 0EEA */ +0xFBC0,0x8EED,0x0000, 0xFBC0,0x8EEE,0x0000, 0xFBC0,0x8EEF,0x0000, /* 0EED */ +0xFBC0,0x8EF0,0x0000, 0xFBC0,0x8EF1,0x0000, 0xFBC0,0x8EF2,0x0000, /* 0EF0 */ +0xFBC0,0x8EF3,0x0000, 0xFBC0,0x8EF4,0x0000, 0xFBC0,0x8EF5,0x0000, /* 0EF3 */ +0xFBC0,0x8EF6,0x0000, 0xFBC0,0x8EF7,0x0000, 0xFBC0,0x8EF8,0x0000, /* 0EF6 */ +0xFBC0,0x8EF9,0x0000, 0xFBC0,0x8EFA,0x0000, 0xFBC0,0x8EFB,0x0000, /* 0EF9 */ +0xFBC0,0x8EFC,0x0000, 0xFBC0,0x8EFD,0x0000, 0xFBC0,0x8EFE,0x0000, /* 0EFC */ +0xFBC0,0x8EFF,0x0000 }; + +uint16 uca520_p00F[]= { /* 0F00 (3 weights per char) */ +0x2067,0x207A,0x0000, 0x0468,0x0000,0x0000, 0x0469,0x0000,0x0000, /* 0F00 */ +0x046A,0x0000,0x0000, 0x03AA,0x0000,0x0000, 0x03AB,0x0000,0x0000, /* 0F03 */ +0x03AC,0x0000,0x0000, 0x03AD,0x0000,0x0000, 0x03AE,0x0000,0x0000, /* 0F06 */ +0x03AF,0x0000,0x0000, 0x03B0,0x0000,0x0000, 0x03B3,0x0000,0x0000, /* 0F09 */ +0x03B3,0x0000,0x0000, 0x03B4,0x0000,0x0000, 0x03B5,0x0000,0x0000, /* 0F0C */ +0x03B6,0x0000,0x0000, 0x03B7,0x0000,0x0000, 0x03B8,0x0000,0x0000, /* 0F0F */ +0x03B9,0x0000,0x0000, 0x046B,0x0000,0x0000, 0x0266,0x0000,0x0000, /* 0F12 */ +0x046C,0x0000,0x0000, 0x046D,0x0000,0x0000, 0x046E,0x0000,0x0000, /* 0F15 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x046F,0x0000,0x0000, /* 0F18 */ +0x0470,0x0000,0x0000, 0x0471,0x0000,0x0000, 0x0472,0x0000,0x0000, /* 0F1B */ +0x0473,0x0000,0x0000, 0x0474,0x0000,0x0000, 0x1205,0x0000,0x0000, /* 0F1E */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 0F21 */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 0F24 */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 0F27 */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 0F2A */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 0F2D */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 0F30 */ +0x1205,0x0000,0x0000, 0x0475,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0F33 */ +0x0476,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0477,0x0000,0x0000, /* 0F36 */ +0x0000,0x0000,0x0000, 0x0305,0x0000,0x0000, 0x0306,0x0000,0x0000, /* 0F39 */ +0x0307,0x0000,0x0000, 0x0308,0x0000,0x0000, 0x0478,0x0000,0x0000, /* 0F3C */ +0x0479,0x0000,0x0000, 0x2021,0x0000,0x0000, 0x2024,0x0000,0x0000, /* 0F3F */ +0x2026,0x0000,0x0000, 0x2026,0x2066,0x0000, 0x2028,0x0000,0x0000, /* 0F42 */ +0x202A,0x0000,0x0000, 0x202C,0x0000,0x0000, 0x202E,0x0000,0x0000, /* 0F45 */ +0xFBC0,0x8F48,0x0000, 0x2030,0x0000,0x0000, 0x2032,0x0000,0x0000, /* 0F48 */ +0x2034,0x0000,0x0000, 0x2036,0x0000,0x0000, 0x2036,0x2066,0x0000, /* 0F4B */ +0x2038,0x0000,0x0000, 0x203A,0x0000,0x0000, 0x203C,0x0000,0x0000, /* 0F4E */ +0x203E,0x0000,0x0000, 0x203E,0x2066,0x0000, 0x2040,0x0000,0x0000, /* 0F51 */ +0x2042,0x0000,0x0000, 0x2044,0x0000,0x0000, 0x2046,0x0000,0x0000, /* 0F54 */ +0x2046,0x2066,0x0000, 0x2048,0x0000,0x0000, 0x204A,0x0000,0x0000, /* 0F57 */ +0x204C,0x0000,0x0000, 0x204E,0x0000,0x0000, 0x204E,0x2066,0x0000, /* 0F5A */ +0x2050,0x0000,0x0000, 0x2052,0x0000,0x0000, 0x2054,0x0000,0x0000, /* 0F5D */ +0x2056,0x0000,0x0000, 0x2058,0x0000,0x0000, 0x205A,0x0000,0x0000, /* 0F60 */ +0x205D,0x0000,0x0000, 0x205F,0x0000,0x0000, 0x2061,0x0000,0x0000, /* 0F63 */ +0x2063,0x0000,0x0000, 0x2065,0x0000,0x0000, 0x2067,0x0000,0x0000, /* 0F66 */ +0x2021,0x2062,0x0000, 0x205A,0x0000,0x0000, 0x2023,0x0000,0x0000, /* 0F69 */ +0x205C,0x0000,0x0000, 0xFBC0,0x8F6D,0x0000, 0xFBC0,0x8F6E,0x0000, /* 0F6C */ +0xFBC0,0x8F6F,0x0000, 0xFBC0,0x8F70,0x0000, 0x206D,0x0000,0x0000, /* 0F6F */ +0x206E,0x0000,0x0000, 0x206F,0x0000,0x0000, 0x2072,0x0000,0x0000, /* 0F72 */ +0x2073,0x0000,0x0000, 0x2074,0x0000,0x0000, 0x2075,0x0000,0x0000, /* 0F75 */ +0x2076,0x0000,0x0000, 0x2077,0x0000,0x0000, 0x2078,0x0000,0x0000, /* 0F78 */ +0x2079,0x0000,0x0000, 0x207A,0x0000,0x0000, 0x207B,0x0000,0x0000, /* 0F7B */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x2070,0x0000,0x0000, /* 0F7E */ +0x2071,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0F81 */ +0x207C,0x0000,0x0000, 0x03BA,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 0F84 */ +0x0000,0x0000,0x0000, 0x2069,0x0000,0x0000, 0x206A,0x0000,0x0000, /* 0F87 */ +0x206B,0x0000,0x0000, 0x206C,0x0000,0x0000, 0xFBC0,0x8F8C,0x0000, /* 0F8A */ +0xFBC0,0x8F8D,0x0000, 0xFBC0,0x8F8E,0x0000, 0xFBC0,0x8F8F,0x0000, /* 0F8D */ +0x2022,0x0000,0x0000, 0x2025,0x0000,0x0000, 0x2027,0x0000,0x0000, /* 0F90 */ +0x2027,0x2066,0x0000, 0x2029,0x0000,0x0000, 0x202B,0x0000,0x0000, /* 0F93 */ +0x202D,0x0000,0x0000, 0x202F,0x0000,0x0000, 0xFBC0,0x8F98,0x0000, /* 0F96 */ +0x2031,0x0000,0x0000, 0x2033,0x0000,0x0000, 0x2035,0x0000,0x0000, /* 0F99 */ +0x2037,0x0000,0x0000, 0x2037,0x2066,0x0000, 0x2039,0x0000,0x0000, /* 0F9C */ +0x203B,0x0000,0x0000, 0x203D,0x0000,0x0000, 0x203F,0x0000,0x0000, /* 0F9F */ +0x203F,0x2066,0x0000, 0x2041,0x0000,0x0000, 0x2043,0x0000,0x0000, /* 0FA2 */ +0x2045,0x0000,0x0000, 0x2047,0x0000,0x0000, 0x2047,0x2066,0x0000, /* 0FA5 */ +0x2049,0x0000,0x0000, 0x204B,0x0000,0x0000, 0x204D,0x0000,0x0000, /* 0FA8 */ +0x204F,0x0000,0x0000, 0x204F,0x2066,0x0000, 0x2051,0x0000,0x0000, /* 0FAB */ +0x2053,0x0000,0x0000, 0x2055,0x0000,0x0000, 0x2057,0x0000,0x0000, /* 0FAE */ +0x2059,0x0000,0x0000, 0x205B,0x0000,0x0000, 0x205E,0x0000,0x0000, /* 0FB1 */ +0x2060,0x0000,0x0000, 0x2062,0x0000,0x0000, 0x2064,0x0000,0x0000, /* 0FB4 */ +0x2066,0x0000,0x0000, 0x2068,0x0000,0x0000, 0x2022,0x2062,0x0000, /* 0FB7 */ +0x2051,0x0000,0x0000, 0x2059,0x0000,0x0000, 0x205B,0x0000,0x0000, /* 0FBA */ +0xFBC0,0x8FBD,0x0000, 0x047A,0x0000,0x0000, 0x047B,0x0000,0x0000, /* 0FBD */ +0x047C,0x0000,0x0000, 0x047D,0x0000,0x0000, 0x047E,0x0000,0x0000, /* 0FC0 */ +0x047F,0x0000,0x0000, 0x0480,0x0000,0x0000, 0x0481,0x0000,0x0000, /* 0FC3 */ +0x0000,0x0000,0x0000, 0x0482,0x0000,0x0000, 0x0483,0x0000,0x0000, /* 0FC6 */ +0x0484,0x0000,0x0000, 0x0485,0x0000,0x0000, 0x0486,0x0000,0x0000, /* 0FC9 */ +0x0487,0x0000,0x0000, 0xFBC0,0x8FCD,0x0000, 0x0488,0x0000,0x0000, /* 0FCC */ +0x0489,0x0000,0x0000, 0x03B1,0x0000,0x0000, 0x03B2,0x0000,0x0000, /* 0FCF */ +0x03BB,0x0000,0x0000, 0x03BC,0x0000,0x0000, 0x03BD,0x0000,0x0000, /* 0FD2 */ +0x048A,0x0000,0x0000, 0x048B,0x0000,0x0000, 0x048C,0x0000,0x0000, /* 0FD5 */ +0x048D,0x0000,0x0000, 0xFBC0,0x8FD9,0x0000, 0xFBC0,0x8FDA,0x0000, /* 0FD8 */ +0xFBC0,0x8FDB,0x0000, 0xFBC0,0x8FDC,0x0000, 0xFBC0,0x8FDD,0x0000, /* 0FDB */ +0xFBC0,0x8FDE,0x0000, 0xFBC0,0x8FDF,0x0000, 0xFBC0,0x8FE0,0x0000, /* 0FDE */ +0xFBC0,0x8FE1,0x0000, 0xFBC0,0x8FE2,0x0000, 0xFBC0,0x8FE3,0x0000, /* 0FE1 */ +0xFBC0,0x8FE4,0x0000, 0xFBC0,0x8FE5,0x0000, 0xFBC0,0x8FE6,0x0000, /* 0FE4 */ +0xFBC0,0x8FE7,0x0000, 0xFBC0,0x8FE8,0x0000, 0xFBC0,0x8FE9,0x0000, /* 0FE7 */ +0xFBC0,0x8FEA,0x0000, 0xFBC0,0x8FEB,0x0000, 0xFBC0,0x8FEC,0x0000, /* 0FEA */ +0xFBC0,0x8FED,0x0000, 0xFBC0,0x8FEE,0x0000, 0xFBC0,0x8FEF,0x0000, /* 0FED */ +0xFBC0,0x8FF0,0x0000, 0xFBC0,0x8FF1,0x0000, 0xFBC0,0x8FF2,0x0000, /* 0FF0 */ +0xFBC0,0x8FF3,0x0000, 0xFBC0,0x8FF4,0x0000, 0xFBC0,0x8FF5,0x0000, /* 0FF3 */ +0xFBC0,0x8FF6,0x0000, 0xFBC0,0x8FF7,0x0000, 0xFBC0,0x8FF8,0x0000, /* 0FF6 */ +0xFBC0,0x8FF9,0x0000, 0xFBC0,0x8FFA,0x0000, 0xFBC0,0x8FFB,0x0000, /* 0FF9 */ +0xFBC0,0x8FFC,0x0000, 0xFBC0,0x8FFD,0x0000, 0xFBC0,0x8FFE,0x0000, /* 0FFC */ +0xFBC0,0x8FFF,0x0000 }; + +uint16 uca520_p010[]= { /* 1000 (4 weights per char) */ +0x21CD,0x0000,0x0000,0x0000, 0x21CF,0x0000,0x0000,0x0000, /* 1000 */ +0x21D1,0x0000,0x0000,0x0000, 0x21D4,0x0000,0x0000,0x0000, /* 1002 */ +0x21D5,0x0000,0x0000,0x0000, 0x21D7,0x0000,0x0000,0x0000, /* 1004 */ +0x21DA,0x0000,0x0000,0x0000, 0x21DC,0x0000,0x0000,0x0000, /* 1006 */ +0x21E0,0x0000,0x0000,0x0000, 0x21E4,0x0000,0x0000,0x0000, /* 1008 */ +0x21E7,0x0000,0x0000,0x0000, 0x21E8,0x0000,0x0000,0x0000, /* 100A */ +0x21EA,0x0000,0x0000,0x0000, 0x21EC,0x0000,0x0000,0x0000, /* 100C */ +0x21EE,0x0000,0x0000,0x0000, 0x21F0,0x0000,0x0000,0x0000, /* 100E */ +0x21F2,0x0000,0x0000,0x0000, 0x21F3,0x0000,0x0000,0x0000, /* 1010 */ +0x21F4,0x0000,0x0000,0x0000, 0x21F6,0x0000,0x0000,0x0000, /* 1012 */ +0x21F8,0x0000,0x0000,0x0000, 0x21FC,0x0000,0x0000,0x0000, /* 1014 */ +0x21FD,0x0000,0x0000,0x0000, 0x2202,0x0000,0x0000,0x0000, /* 1016 */ +0x2204,0x0000,0x0000,0x0000, 0x2205,0x0000,0x0000,0x0000, /* 1018 */ +0x2207,0x0000,0x0000,0x0000, 0x2209,0x0000,0x0000,0x0000, /* 101A */ +0x220D,0x0000,0x0000,0x0000, 0x220F,0x0000,0x0000,0x0000, /* 101C */ +0x2216,0x0000,0x0000,0x0000, 0x2218,0x0000,0x0000,0x0000, /* 101E */ +0x221E,0x0000,0x0000,0x0000, 0x2224,0x0000,0x0000,0x0000, /* 1020 */ +0x2225,0x0000,0x0000,0x0000, 0x2226,0x0000,0x0000,0x0000, /* 1022 */ +0x2227,0x0000,0x0000,0x0000, 0x2228,0x0000,0x0000,0x0000, /* 1024 */ +0x2229,0x0000,0x0000,0x0000, 0x222E,0x0000,0x0000,0x0000, /* 1026 */ +0x222F,0x0000,0x0000,0x0000, 0x2230,0x0000,0x0000,0x0000, /* 1028 */ +0x2231,0x0000,0x0000,0x0000, 0x2232,0x0000,0x0000,0x0000, /* 102A */ +0x2232,0x0000,0x0000,0x0000, 0x2236,0x0000,0x0000,0x0000, /* 102C */ +0x2238,0x0000,0x0000,0x0000, 0x223A,0x0000,0x0000,0x0000, /* 102E */ +0x223D,0x0000,0x0000,0x0000, 0x2242,0x0000,0x0000,0x0000, /* 1030 */ +0x2246,0x0000,0x0000,0x0000, 0x2239,0x0000,0x0000,0x0000, /* 1032 */ +0x2248,0x0000,0x0000,0x0000, 0x2244,0x0000,0x0000,0x0000, /* 1034 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 1036 */ +0x0000,0x0000,0x0000,0x0000, 0x224D,0x0000,0x0000,0x0000, /* 1038 */ +0x224E,0x0000,0x0000,0x0000, 0x2208,0x0000,0x0000,0x0000, /* 103A */ +0x220C,0x0000,0x0000,0x0000, 0x2210,0x0000,0x0000,0x0000, /* 103C */ +0x221B,0x0000,0x0000,0x0000, 0x2216,0x224D,0x2216,0x0000, /* 103E */ +0x1205,0x0000,0x0000,0x0000, 0x1206,0x0000,0x0000,0x0000, /* 1040 */ +0x1207,0x0000,0x0000,0x0000, 0x1208,0x0000,0x0000,0x0000, /* 1042 */ +0x1209,0x0000,0x0000,0x0000, 0x120A,0x0000,0x0000,0x0000, /* 1044 */ +0x120B,0x0000,0x0000,0x0000, 0x120C,0x0000,0x0000,0x0000, /* 1046 */ +0x120D,0x0000,0x0000,0x0000, 0x120E,0x0000,0x0000,0x0000, /* 1048 */ +0x029F,0x0000,0x0000,0x0000, 0x02A0,0x0000,0x0000,0x0000, /* 104A */ +0x03C2,0x0000,0x0000,0x0000, 0x03C3,0x0000,0x0000,0x0000, /* 104C */ +0x03C4,0x0000,0x0000,0x0000, 0x03C5,0x0000,0x0000,0x0000, /* 104E */ +0x2213,0x0000,0x0000,0x0000, 0x2214,0x0000,0x0000,0x0000, /* 1050 */ +0x222A,0x0000,0x0000,0x0000, 0x222B,0x0000,0x0000,0x0000, /* 1052 */ +0x222C,0x0000,0x0000,0x0000, 0x222D,0x0000,0x0000,0x0000, /* 1054 */ +0x223E,0x0000,0x0000,0x0000, 0x223F,0x0000,0x0000,0x0000, /* 1056 */ +0x2240,0x0000,0x0000,0x0000, 0x2241,0x0000,0x0000,0x0000, /* 1058 */ +0x21D6,0x0000,0x0000,0x0000, 0x21E1,0x0000,0x0000,0x0000, /* 105A */ +0x221F,0x0000,0x0000,0x0000, 0x2220,0x0000,0x0000,0x0000, /* 105C */ +0x21FB,0x0000,0x0000,0x0000, 0x2206,0x0000,0x0000,0x0000, /* 105E */ +0x220E,0x0000,0x0000,0x0000, 0x21E3,0x0000,0x0000,0x0000, /* 1060 */ +0x2249,0x0000,0x0000,0x0000, 0x224F,0x0000,0x0000,0x0000, /* 1062 */ +0x2250,0x0000,0x0000,0x0000, 0x2215,0x0000,0x0000,0x0000, /* 1064 */ +0x2223,0x0000,0x0000,0x0000, 0x224A,0x0000,0x0000,0x0000, /* 1066 */ +0x224B,0x0000,0x0000,0x0000, 0x2251,0x0000,0x0000,0x0000, /* 1068 */ +0x2252,0x0000,0x0000,0x0000, 0x2253,0x0000,0x0000,0x0000, /* 106A */ +0x2254,0x0000,0x0000,0x0000, 0x2255,0x0000,0x0000,0x0000, /* 106C */ +0x21F1,0x0000,0x0000,0x0000, 0x2221,0x0000,0x0000,0x0000, /* 106E */ +0x2222,0x0000,0x0000,0x0000, 0x2237,0x0000,0x0000,0x0000, /* 1070 */ +0x2234,0x0000,0x0000,0x0000, 0x223B,0x0000,0x0000,0x0000, /* 1072 */ +0x223C,0x0000,0x0000,0x0000, 0x21CE,0x0000,0x0000,0x0000, /* 1074 */ +0x21D0,0x0000,0x0000,0x0000, 0x21D2,0x0000,0x0000,0x0000, /* 1076 */ +0x21D8,0x0000,0x0000,0x0000, 0x21DE,0x0000,0x0000,0x0000, /* 1078 */ +0x21E5,0x0000,0x0000,0x0000, 0x21F5,0x0000,0x0000,0x0000, /* 107A */ +0x21F9,0x0000,0x0000,0x0000, 0x21FE,0x0000,0x0000,0x0000, /* 107C */ +0x21FF,0x0000,0x0000,0x0000, 0x2203,0x0000,0x0000,0x0000, /* 107E */ +0x2212,0x0000,0x0000,0x0000, 0x2219,0x0000,0x0000,0x0000, /* 1080 */ +0x2211,0x0000,0x0000,0x0000, 0x2233,0x0000,0x0000,0x0000, /* 1082 */ +0x2243,0x0000,0x0000,0x0000, 0x2245,0x0000,0x0000,0x0000, /* 1084 */ +0x224C,0x0000,0x0000,0x0000, 0x2256,0x0000,0x0000,0x0000, /* 1086 */ +0x2258,0x0000,0x0000,0x0000, 0x225A,0x0000,0x0000,0x0000, /* 1088 */ +0x225B,0x0000,0x0000,0x0000, 0x2257,0x0000,0x0000,0x0000, /* 108A */ +0x2259,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 108C */ +0x2201,0x0000,0x0000,0x0000, 0x225C,0x0000,0x0000,0x0000, /* 108E */ +0x1205,0x0000,0x0000,0x0000, 0x1206,0x0000,0x0000,0x0000, /* 1090 */ +0x1207,0x0000,0x0000,0x0000, 0x1208,0x0000,0x0000,0x0000, /* 1092 */ +0x1209,0x0000,0x0000,0x0000, 0x120A,0x0000,0x0000,0x0000, /* 1094 */ +0x120B,0x0000,0x0000,0x0000, 0x120C,0x0000,0x0000,0x0000, /* 1096 */ +0x120D,0x0000,0x0000,0x0000, 0x120E,0x0000,0x0000,0x0000, /* 1098 */ +0x225D,0x0000,0x0000,0x0000, 0x225E,0x0000,0x0000,0x0000, /* 109A */ +0x2235,0x0000,0x0000,0x0000, 0x2247,0x0000,0x0000,0x0000, /* 109C */ +0x03C6,0x0000,0x0000,0x0000, 0x03C7,0x0000,0x0000,0x0000, /* 109E */ +0x17E5,0x0000,0x0000,0x0000, 0x17E7,0x0000,0x0000,0x0000, /* 10A0 */ +0x17E9,0x0000,0x0000,0x0000, 0x17EB,0x0000,0x0000,0x0000, /* 10A2 */ +0x17ED,0x0000,0x0000,0x0000, 0x17EF,0x0000,0x0000,0x0000, /* 10A4 */ +0x17F1,0x0000,0x0000,0x0000, 0x17F5,0x0000,0x0000,0x0000, /* 10A6 */ +0x17F7,0x0000,0x0000,0x0000, 0x17F9,0x0000,0x0000,0x0000, /* 10A8 */ +0x17FB,0x0000,0x0000,0x0000, 0x17FD,0x0000,0x0000,0x0000, /* 10AA */ +0x17FF,0x0000,0x0000,0x0000, 0x1803,0x0000,0x0000,0x0000, /* 10AC */ +0x1805,0x0000,0x0000,0x0000, 0x1807,0x0000,0x0000,0x0000, /* 10AE */ +0x1809,0x0000,0x0000,0x0000, 0x180B,0x0000,0x0000,0x0000, /* 10B0 */ +0x180D,0x0000,0x0000,0x0000, 0x1811,0x0000,0x0000,0x0000, /* 10B2 */ +0x1813,0x0000,0x0000,0x0000, 0x1815,0x0000,0x0000,0x0000, /* 10B4 */ +0x1817,0x0000,0x0000,0x0000, 0x1819,0x0000,0x0000,0x0000, /* 10B6 */ +0x181B,0x0000,0x0000,0x0000, 0x181D,0x0000,0x0000,0x0000, /* 10B8 */ +0x181F,0x0000,0x0000,0x0000, 0x1821,0x0000,0x0000,0x0000, /* 10BA */ +0x1823,0x0000,0x0000,0x0000, 0x1825,0x0000,0x0000,0x0000, /* 10BC */ +0x1827,0x0000,0x0000,0x0000, 0x182B,0x0000,0x0000,0x0000, /* 10BE */ +0x182D,0x0000,0x0000,0x0000, 0x17F3,0x0000,0x0000,0x0000, /* 10C0 */ +0x1801,0x0000,0x0000,0x0000, 0x180F,0x0000,0x0000,0x0000, /* 10C2 */ +0x1829,0x0000,0x0000,0x0000, 0x182F,0x0000,0x0000,0x0000, /* 10C4 */ +0xFBC0,0x90C6,0x0000,0x0000, 0xFBC0,0x90C7,0x0000,0x0000, /* 10C6 */ +0xFBC0,0x90C8,0x0000,0x0000, 0xFBC0,0x90C9,0x0000,0x0000, /* 10C8 */ +0xFBC0,0x90CA,0x0000,0x0000, 0xFBC0,0x90CB,0x0000,0x0000, /* 10CA */ +0xFBC0,0x90CC,0x0000,0x0000, 0xFBC0,0x90CD,0x0000,0x0000, /* 10CC */ +0xFBC0,0x90CE,0x0000,0x0000, 0xFBC0,0x90CF,0x0000,0x0000, /* 10CE */ +0x17E4,0x0000,0x0000,0x0000, 0x17E6,0x0000,0x0000,0x0000, /* 10D0 */ +0x17E8,0x0000,0x0000,0x0000, 0x17EA,0x0000,0x0000,0x0000, /* 10D2 */ +0x17EC,0x0000,0x0000,0x0000, 0x17EE,0x0000,0x0000,0x0000, /* 10D4 */ +0x17F0,0x0000,0x0000,0x0000, 0x17F4,0x0000,0x0000,0x0000, /* 10D6 */ +0x17F6,0x0000,0x0000,0x0000, 0x17F8,0x0000,0x0000,0x0000, /* 10D8 */ +0x17FA,0x0000,0x0000,0x0000, 0x17FC,0x0000,0x0000,0x0000, /* 10DA */ +0x17FE,0x0000,0x0000,0x0000, 0x1802,0x0000,0x0000,0x0000, /* 10DC */ +0x1804,0x0000,0x0000,0x0000, 0x1806,0x0000,0x0000,0x0000, /* 10DE */ +0x1808,0x0000,0x0000,0x0000, 0x180A,0x0000,0x0000,0x0000, /* 10E0 */ +0x180C,0x0000,0x0000,0x0000, 0x1810,0x0000,0x0000,0x0000, /* 10E2 */ +0x1812,0x0000,0x0000,0x0000, 0x1814,0x0000,0x0000,0x0000, /* 10E4 */ +0x1816,0x0000,0x0000,0x0000, 0x1818,0x0000,0x0000,0x0000, /* 10E6 */ +0x181A,0x0000,0x0000,0x0000, 0x181C,0x0000,0x0000,0x0000, /* 10E8 */ +0x181E,0x0000,0x0000,0x0000, 0x1820,0x0000,0x0000,0x0000, /* 10EA */ +0x1822,0x0000,0x0000,0x0000, 0x1824,0x0000,0x0000,0x0000, /* 10EC */ +0x1826,0x0000,0x0000,0x0000, 0x182A,0x0000,0x0000,0x0000, /* 10EE */ +0x182C,0x0000,0x0000,0x0000, 0x17F2,0x0000,0x0000,0x0000, /* 10F0 */ +0x1800,0x0000,0x0000,0x0000, 0x180E,0x0000,0x0000,0x0000, /* 10F2 */ +0x1828,0x0000,0x0000,0x0000, 0x182E,0x0000,0x0000,0x0000, /* 10F4 */ +0x1830,0x0000,0x0000,0x0000, 0x1831,0x0000,0x0000,0x0000, /* 10F6 */ +0x1832,0x0000,0x0000,0x0000, 0x1833,0x0000,0x0000,0x0000, /* 10F8 */ +0x1834,0x0000,0x0000,0x0000, 0x02B7,0x0000,0x0000,0x0000, /* 10FA */ +0x17FE,0x0000,0x0000,0x0000, 0xFBC0,0x90FD,0x0000,0x0000, /* 10FC */ +0xFBC0,0x90FE,0x0000,0x0000, 0xFBC0,0x90FF,0x0000,0x0000 /* 10FE */ +}; + +uint16 uca520_p011[]= { /* 1100 (2 weights per char) */ +0x29B0,0x0000, 0x29B1,0x0000, 0x29B2,0x0000, 0x29B3,0x0000, /* 1100 */ +0x29B4,0x0000, 0x29B5,0x0000, 0x29B6,0x0000, 0x29B7,0x0000, /* 1104 */ +0x29B8,0x0000, 0x29B9,0x0000, 0x29BA,0x0000, 0x29BB,0x0000, /* 1108 */ +0x29BC,0x0000, 0x29BD,0x0000, 0x29BE,0x0000, 0x29BF,0x0000, /* 110C */ +0x29C0,0x0000, 0x29C1,0x0000, 0x29C2,0x0000, 0x29C3,0x0000, /* 1110 */ +0x29C4,0x0000, 0x29C5,0x0000, 0x29C6,0x0000, 0x29C7,0x0000, /* 1114 */ +0x29C8,0x0000, 0x29C9,0x0000, 0x29CA,0x0000, 0x29CB,0x0000, /* 1118 */ +0x29CC,0x0000, 0x29CD,0x0000, 0x29CE,0x0000, 0x29CF,0x0000, /* 111C */ +0x29D0,0x0000, 0x29D1,0x0000, 0x29D2,0x0000, 0x29D3,0x0000, /* 1120 */ +0x29D4,0x0000, 0x29D5,0x0000, 0x29D6,0x0000, 0x29D7,0x0000, /* 1124 */ +0x29D8,0x0000, 0x29D9,0x0000, 0x29DA,0x0000, 0x29DB,0x0000, /* 1128 */ +0x29DC,0x0000, 0x29DD,0x0000, 0x29DE,0x0000, 0x29DF,0x0000, /* 112C */ +0x29E0,0x0000, 0x29E1,0x0000, 0x29E2,0x0000, 0x29E3,0x0000, /* 1130 */ +0x29E4,0x0000, 0x29E5,0x0000, 0x29E6,0x0000, 0x29E7,0x0000, /* 1134 */ +0x29E8,0x0000, 0x29E9,0x0000, 0x29EA,0x0000, 0x29EB,0x0000, /* 1138 */ +0x29EC,0x0000, 0x29ED,0x0000, 0x29EE,0x0000, 0x29EF,0x0000, /* 113C */ +0x29F0,0x0000, 0x29F1,0x0000, 0x29F2,0x0000, 0x29F3,0x0000, /* 1140 */ +0x29F4,0x0000, 0x29F5,0x0000, 0x29F6,0x0000, 0x29F7,0x0000, /* 1144 */ +0x29F8,0x0000, 0x29F9,0x0000, 0x29FA,0x0000, 0x29FB,0x0000, /* 1148 */ +0x29FC,0x0000, 0x29FD,0x0000, 0x29FE,0x0000, 0x29FF,0x0000, /* 114C */ +0x2A00,0x0000, 0x2A01,0x0000, 0x2A02,0x0000, 0x2A03,0x0000, /* 1150 */ +0x2A04,0x0000, 0x2A05,0x0000, 0x2A06,0x0000, 0x2A07,0x0000, /* 1154 */ +0x2A08,0x0000, 0x2A09,0x0000, 0x2A0A,0x0000, 0x2A0B,0x0000, /* 1158 */ +0x2A0C,0x0000, 0x2A0D,0x0000, 0x2A0E,0x0000, 0x2A2C,0x0000, /* 115C */ +0x2A2D,0x0000, 0x2A2E,0x0000, 0x2A2F,0x0000, 0x2A30,0x0000, /* 1160 */ +0x2A31,0x0000, 0x2A32,0x0000, 0x2A33,0x0000, 0x2A34,0x0000, /* 1164 */ +0x2A35,0x0000, 0x2A36,0x0000, 0x2A37,0x0000, 0x2A38,0x0000, /* 1168 */ +0x2A39,0x0000, 0x2A3A,0x0000, 0x2A3B,0x0000, 0x2A3C,0x0000, /* 116C */ +0x2A3D,0x0000, 0x2A3E,0x0000, 0x2A3F,0x0000, 0x2A40,0x0000, /* 1170 */ +0x2A41,0x0000, 0x2A42,0x0000, 0x2A43,0x0000, 0x2A44,0x0000, /* 1174 */ +0x2A45,0x0000, 0x2A46,0x0000, 0x2A47,0x0000, 0x2A48,0x0000, /* 1178 */ +0x2A49,0x0000, 0x2A4A,0x0000, 0x2A4B,0x0000, 0x2A4C,0x0000, /* 117C */ +0x2A4D,0x0000, 0x2A4E,0x0000, 0x2A4F,0x0000, 0x2A50,0x0000, /* 1180 */ +0x2A51,0x0000, 0x2A52,0x0000, 0x2A53,0x0000, 0x2A54,0x0000, /* 1184 */ +0x2A55,0x0000, 0x2A56,0x0000, 0x2A57,0x0000, 0x2A58,0x0000, /* 1188 */ +0x2A59,0x0000, 0x2A5A,0x0000, 0x2A5B,0x0000, 0x2A5C,0x0000, /* 118C */ +0x2A5D,0x0000, 0x2A5E,0x0000, 0x2A5F,0x0000, 0x2A60,0x0000, /* 1190 */ +0x2A61,0x0000, 0x2A62,0x0000, 0x2A63,0x0000, 0x2A64,0x0000, /* 1194 */ +0x2A65,0x0000, 0x2A66,0x0000, 0x2A67,0x0000, 0x2A68,0x0000, /* 1198 */ +0x2A69,0x0000, 0x2A6A,0x0000, 0x2A6B,0x0000, 0x2A6C,0x0000, /* 119C */ +0x2A6D,0x0000, 0x2A6E,0x0000, 0x2A6F,0x0000, 0x2A70,0x0000, /* 11A0 */ +0x2A71,0x0000, 0x2A72,0x0000, 0x2A73,0x0000, 0x2A74,0x0000, /* 11A4 */ +0x2A8C,0x0000, 0x2A8D,0x0000, 0x2A8E,0x0000, 0x2A8F,0x0000, /* 11A8 */ +0x2A90,0x0000, 0x2A91,0x0000, 0x2A92,0x0000, 0x2A93,0x0000, /* 11AC */ +0x2A94,0x0000, 0x2A95,0x0000, 0x2A96,0x0000, 0x2A97,0x0000, /* 11B0 */ +0x2A98,0x0000, 0x2A99,0x0000, 0x2A9A,0x0000, 0x2A9B,0x0000, /* 11B4 */ +0x2A9C,0x0000, 0x2A9D,0x0000, 0x2A9E,0x0000, 0x2A9F,0x0000, /* 11B8 */ +0x2AA0,0x0000, 0x2AA1,0x0000, 0x2AA2,0x0000, 0x2AA3,0x0000, /* 11BC */ +0x2AA4,0x0000, 0x2AA5,0x0000, 0x2AA6,0x0000, 0x2AA7,0x0000, /* 11C0 */ +0x2AA8,0x0000, 0x2AA9,0x0000, 0x2AAA,0x0000, 0x2AAB,0x0000, /* 11C4 */ +0x2AAC,0x0000, 0x2AAD,0x0000, 0x2AAE,0x0000, 0x2AAF,0x0000, /* 11C8 */ +0x2AB0,0x0000, 0x2AB1,0x0000, 0x2AB2,0x0000, 0x2AB3,0x0000, /* 11CC */ +0x2AB4,0x0000, 0x2AB5,0x0000, 0x2AB6,0x0000, 0x2AB7,0x0000, /* 11D0 */ +0x2AB8,0x0000, 0x2AB9,0x0000, 0x2ABA,0x0000, 0x2ABB,0x0000, /* 11D4 */ +0x2ABC,0x0000, 0x2ABD,0x0000, 0x2ABE,0x0000, 0x2ABF,0x0000, /* 11D8 */ +0x2AC0,0x0000, 0x2AC1,0x0000, 0x2AC2,0x0000, 0x2AC3,0x0000, /* 11DC */ +0x2AC4,0x0000, 0x2AC5,0x0000, 0x2AC6,0x0000, 0x2AC7,0x0000, /* 11E0 */ +0x2AC8,0x0000, 0x2AC9,0x0000, 0x2ACA,0x0000, 0x2ACB,0x0000, /* 11E4 */ +0x2ACC,0x0000, 0x2ACD,0x0000, 0x2ACE,0x0000, 0x2ACF,0x0000, /* 11E8 */ +0x2AD0,0x0000, 0x2AD1,0x0000, 0x2AD2,0x0000, 0x2AD3,0x0000, /* 11EC */ +0x2AD4,0x0000, 0x2AD5,0x0000, 0x2AD6,0x0000, 0x2AD7,0x0000, /* 11F0 */ +0x2AD8,0x0000, 0x2AD9,0x0000, 0x2ADA,0x0000, 0x2ADB,0x0000, /* 11F4 */ +0x2ADC,0x0000, 0x2ADD,0x0000, 0x2ADE,0x0000, 0x2ADF,0x0000, /* 11F8 */ +0x2AE0,0x0000, 0x2AE1,0x0000, 0x2AE2,0x0000, 0x2AE3,0x0000 /* 11FC */ +}; + +uint16 uca520_p012[]= { /* 1200 (3 weights per char) */ +0x1A03,0x0000,0x0000, 0x1A04,0x0000,0x0000, 0x1A05,0x0000,0x0000, /* 1200 */ +0x1A06,0x0000,0x0000, 0x1A07,0x0000,0x0000, 0x1A08,0x0000,0x0000, /* 1203 */ +0x1A09,0x0000,0x0000, 0x1A0A,0x0000,0x0000, 0x1A0B,0x0000,0x0000, /* 1206 */ +0x1A0C,0x0000,0x0000, 0x1A0D,0x0000,0x0000, 0x1A0E,0x0000,0x0000, /* 1209 */ +0x1A0F,0x0000,0x0000, 0x1A10,0x0000,0x0000, 0x1A11,0x0000,0x0000, /* 120C */ +0x1A12,0x0000,0x0000, 0x1A14,0x0000,0x0000, 0x1A15,0x0000,0x0000, /* 120F */ +0x1A16,0x0000,0x0000, 0x1A17,0x0000,0x0000, 0x1A18,0x0000,0x0000, /* 1212 */ +0x1A19,0x0000,0x0000, 0x1A1A,0x0000,0x0000, 0x1A1B,0x0000,0x0000, /* 1215 */ +0x1A1C,0x0000,0x0000, 0x1A1D,0x0000,0x0000, 0x1A1E,0x0000,0x0000, /* 1218 */ +0x1A1F,0x0000,0x0000, 0x1A20,0x0000,0x0000, 0x1A21,0x0000,0x0000, /* 121B */ +0x1A22,0x0000,0x0000, 0x1A23,0x0000,0x0000, 0x1A29,0x0000,0x0000, /* 121E */ +0x1A2A,0x0000,0x0000, 0x1A2B,0x0000,0x0000, 0x1A2C,0x0000,0x0000, /* 1221 */ +0x1A2D,0x0000,0x0000, 0x1A2E,0x0000,0x0000, 0x1A2F,0x0000,0x0000, /* 1224 */ +0x1A30,0x0000,0x0000, 0x1A31,0x0000,0x0000, 0x1A32,0x0000,0x0000, /* 1227 */ +0x1A33,0x0000,0x0000, 0x1A34,0x0000,0x0000, 0x1A35,0x0000,0x0000, /* 122A */ +0x1A36,0x0000,0x0000, 0x1A37,0x0000,0x0000, 0x1A38,0x0000,0x0000, /* 122D */ +0x1A3A,0x0000,0x0000, 0x1A3B,0x0000,0x0000, 0x1A3C,0x0000,0x0000, /* 1230 */ +0x1A3D,0x0000,0x0000, 0x1A3E,0x0000,0x0000, 0x1A3F,0x0000,0x0000, /* 1233 */ +0x1A40,0x0000,0x0000, 0x1A41,0x0000,0x0000, 0x1A43,0x0000,0x0000, /* 1236 */ +0x1A44,0x0000,0x0000, 0x1A45,0x0000,0x0000, 0x1A46,0x0000,0x0000, /* 1239 */ +0x1A47,0x0000,0x0000, 0x1A48,0x0000,0x0000, 0x1A49,0x0000,0x0000, /* 123C */ +0x1A4A,0x0000,0x0000, 0x1A4C,0x0000,0x0000, 0x1A4D,0x0000,0x0000, /* 123F */ +0x1A4E,0x0000,0x0000, 0x1A4F,0x0000,0x0000, 0x1A50,0x0000,0x0000, /* 1242 */ +0x1A51,0x0000,0x0000, 0x1A52,0x0000,0x0000, 0x1A53,0x0000,0x0000, /* 1245 */ +0x1A54,0x0000,0x0000, 0xFBC0,0x9249,0x0000, 0x1A55,0x0000,0x0000, /* 1248 */ +0x1A56,0x0000,0x0000, 0x1A57,0x0000,0x0000, 0x1A58,0x0000,0x0000, /* 124B */ +0xFBC0,0x924E,0x0000, 0xFBC0,0x924F,0x0000, 0x1A59,0x0000,0x0000, /* 124E */ +0x1A5A,0x0000,0x0000, 0x1A5B,0x0000,0x0000, 0x1A5C,0x0000,0x0000, /* 1251 */ +0x1A5D,0x0000,0x0000, 0x1A5E,0x0000,0x0000, 0x1A5F,0x0000,0x0000, /* 1254 */ +0xFBC0,0x9257,0x0000, 0x1A60,0x0000,0x0000, 0xFBC0,0x9259,0x0000, /* 1257 */ +0x1A61,0x0000,0x0000, 0x1A62,0x0000,0x0000, 0x1A63,0x0000,0x0000, /* 125A */ +0x1A64,0x0000,0x0000, 0xFBC0,0x925E,0x0000, 0xFBC0,0x925F,0x0000, /* 125D */ +0x1A65,0x0000,0x0000, 0x1A66,0x0000,0x0000, 0x1A67,0x0000,0x0000, /* 1260 */ +0x1A68,0x0000,0x0000, 0x1A69,0x0000,0x0000, 0x1A6A,0x0000,0x0000, /* 1263 */ +0x1A6B,0x0000,0x0000, 0x1A6C,0x0000,0x0000, 0x1A72,0x0000,0x0000, /* 1266 */ +0x1A73,0x0000,0x0000, 0x1A74,0x0000,0x0000, 0x1A75,0x0000,0x0000, /* 1269 */ +0x1A76,0x0000,0x0000, 0x1A77,0x0000,0x0000, 0x1A78,0x0000,0x0000, /* 126C */ +0x1A79,0x0000,0x0000, 0x1A7A,0x0000,0x0000, 0x1A7B,0x0000,0x0000, /* 126F */ +0x1A7C,0x0000,0x0000, 0x1A7D,0x0000,0x0000, 0x1A7E,0x0000,0x0000, /* 1272 */ +0x1A7F,0x0000,0x0000, 0x1A80,0x0000,0x0000, 0x1A81,0x0000,0x0000, /* 1275 */ +0x1A83,0x0000,0x0000, 0x1A84,0x0000,0x0000, 0x1A85,0x0000,0x0000, /* 1278 */ +0x1A86,0x0000,0x0000, 0x1A87,0x0000,0x0000, 0x1A88,0x0000,0x0000, /* 127B */ +0x1A89,0x0000,0x0000, 0x1A8A,0x0000,0x0000, 0x1A8C,0x0000,0x0000, /* 127E */ +0x1A8D,0x0000,0x0000, 0x1A8E,0x0000,0x0000, 0x1A8F,0x0000,0x0000, /* 1281 */ +0x1A90,0x0000,0x0000, 0x1A91,0x0000,0x0000, 0x1A92,0x0000,0x0000, /* 1284 */ +0x1A93,0x0000,0x0000, 0x1A94,0x0000,0x0000, 0xFBC0,0x9289,0x0000, /* 1287 */ +0x1A95,0x0000,0x0000, 0x1A96,0x0000,0x0000, 0x1A97,0x0000,0x0000, /* 128A */ +0x1A98,0x0000,0x0000, 0xFBC0,0x928E,0x0000, 0xFBC0,0x928F,0x0000, /* 128D */ +0x1A99,0x0000,0x0000, 0x1A9A,0x0000,0x0000, 0x1A9B,0x0000,0x0000, /* 1290 */ +0x1A9C,0x0000,0x0000, 0x1A9D,0x0000,0x0000, 0x1A9E,0x0000,0x0000, /* 1293 */ +0x1A9F,0x0000,0x0000, 0x1AA0,0x0000,0x0000, 0x1AA2,0x0000,0x0000, /* 1296 */ +0x1AA3,0x0000,0x0000, 0x1AA4,0x0000,0x0000, 0x1AA5,0x0000,0x0000, /* 1299 */ +0x1AA6,0x0000,0x0000, 0x1AA7,0x0000,0x0000, 0x1AA8,0x0000,0x0000, /* 129C */ +0x1AA9,0x0000,0x0000, 0x1AAB,0x0000,0x0000, 0x1AAC,0x0000,0x0000, /* 129F */ +0x1AAD,0x0000,0x0000, 0x1AAE,0x0000,0x0000, 0x1AAF,0x0000,0x0000, /* 12A2 */ +0x1AB0,0x0000,0x0000, 0x1AB1,0x0000,0x0000, 0x1AB2,0x0000,0x0000, /* 12A5 */ +0x1AB4,0x0000,0x0000, 0x1AB5,0x0000,0x0000, 0x1AB6,0x0000,0x0000, /* 12A8 */ +0x1AB7,0x0000,0x0000, 0x1AB8,0x0000,0x0000, 0x1AB9,0x0000,0x0000, /* 12AB */ +0x1ABA,0x0000,0x0000, 0x1ABB,0x0000,0x0000, 0x1ABC,0x0000,0x0000, /* 12AE */ +0xFBC0,0x92B1,0x0000, 0x1ABD,0x0000,0x0000, 0x1ABE,0x0000,0x0000, /* 12B1 */ +0x1ABF,0x0000,0x0000, 0x1AC0,0x0000,0x0000, 0xFBC0,0x92B6,0x0000, /* 12B4 */ +0xFBC0,0x92B7,0x0000, 0x1AC1,0x0000,0x0000, 0x1AC2,0x0000,0x0000, /* 12B7 */ +0x1AC3,0x0000,0x0000, 0x1AC4,0x0000,0x0000, 0x1AC5,0x0000,0x0000, /* 12BA */ +0x1AC6,0x0000,0x0000, 0x1AC7,0x0000,0x0000, 0xFBC0,0x92BF,0x0000, /* 12BD */ +0x1AC8,0x0000,0x0000, 0xFBC0,0x92C1,0x0000, 0x1AC9,0x0000,0x0000, /* 12C0 */ +0x1ACA,0x0000,0x0000, 0x1ACB,0x0000,0x0000, 0x1ACC,0x0000,0x0000, /* 12C3 */ +0xFBC0,0x92C6,0x0000, 0xFBC0,0x92C7,0x0000, 0x1ACD,0x0000,0x0000, /* 12C6 */ +0x1ACE,0x0000,0x0000, 0x1ACF,0x0000,0x0000, 0x1AD0,0x0000,0x0000, /* 12C9 */ +0x1AD1,0x0000,0x0000, 0x1AD2,0x0000,0x0000, 0x1AD3,0x0000,0x0000, /* 12CC */ +0x1AD4,0x0000,0x0000, 0x1AD5,0x0000,0x0000, 0x1AD6,0x0000,0x0000, /* 12CF */ +0x1AD7,0x0000,0x0000, 0x1AD8,0x0000,0x0000, 0x1AD9,0x0000,0x0000, /* 12D2 */ +0x1ADA,0x0000,0x0000, 0x1ADB,0x0000,0x0000, 0xFBC0,0x92D7,0x0000, /* 12D5 */ +0x1ADC,0x0000,0x0000, 0x1ADD,0x0000,0x0000, 0x1ADE,0x0000,0x0000, /* 12D8 */ +0x1ADF,0x0000,0x0000, 0x1AE0,0x0000,0x0000, 0x1AE1,0x0000,0x0000, /* 12DB */ +0x1AE2,0x0000,0x0000, 0x1AE3,0x0000,0x0000, 0x1AE5,0x0000,0x0000, /* 12DE */ +0x1AE6,0x0000,0x0000, 0x1AE7,0x0000,0x0000, 0x1AE8,0x0000,0x0000, /* 12E1 */ +0x1AE9,0x0000,0x0000, 0x1AEA,0x0000,0x0000, 0x1AEB,0x0000,0x0000, /* 12E4 */ +0x1AEC,0x0000,0x0000, 0x1AED,0x0000,0x0000, 0x1AEE,0x0000,0x0000, /* 12E7 */ +0x1AEF,0x0000,0x0000, 0x1AF0,0x0000,0x0000, 0x1AF1,0x0000,0x0000, /* 12EA */ +0x1AF2,0x0000,0x0000, 0x1AF3,0x0000,0x0000, 0x1AF4,0x0000,0x0000, /* 12ED */ +0x1AF5,0x0000,0x0000, 0x1AF6,0x0000,0x0000, 0x1AF7,0x0000,0x0000, /* 12F0 */ +0x1AF8,0x0000,0x0000, 0x1AF9,0x0000,0x0000, 0x1AFA,0x0000,0x0000, /* 12F3 */ +0x1AFB,0x0000,0x0000, 0x1AFC,0x0000,0x0000, 0x1AFE,0x0000,0x0000, /* 12F6 */ +0x1AFF,0x0000,0x0000, 0x1B00,0x0000,0x0000, 0x1B01,0x0000,0x0000, /* 12F9 */ +0x1B02,0x0000,0x0000, 0x1B03,0x0000,0x0000, 0x1B04,0x0000,0x0000, /* 12FC */ +0x1B05,0x0000,0x0000 }; + +uint16 uca520_p013[]= { /* 1300 (3 weights per char) */ +0x1B07,0x0000,0x0000, 0x1B08,0x0000,0x0000, 0x1B09,0x0000,0x0000, /* 1300 */ +0x1B0A,0x0000,0x0000, 0x1B0B,0x0000,0x0000, 0x1B0C,0x0000,0x0000, /* 1303 */ +0x1B0D,0x0000,0x0000, 0x1B0E,0x0000,0x0000, 0x1B10,0x0000,0x0000, /* 1306 */ +0x1B11,0x0000,0x0000, 0x1B12,0x0000,0x0000, 0x1B13,0x0000,0x0000, /* 1309 */ +0x1B14,0x0000,0x0000, 0x1B15,0x0000,0x0000, 0x1B16,0x0000,0x0000, /* 130C */ +0x1B17,0x0000,0x0000, 0x1B18,0x0000,0x0000, 0xFBC0,0x9311,0x0000, /* 130F */ +0x1B19,0x0000,0x0000, 0x1B1A,0x0000,0x0000, 0x1B1B,0x0000,0x0000, /* 1312 */ +0x1B1C,0x0000,0x0000, 0xFBC0,0x9316,0x0000, 0xFBC0,0x9317,0x0000, /* 1315 */ +0x1B1D,0x0000,0x0000, 0x1B1E,0x0000,0x0000, 0x1B1F,0x0000,0x0000, /* 1318 */ +0x1B20,0x0000,0x0000, 0x1B21,0x0000,0x0000, 0x1B22,0x0000,0x0000, /* 131B */ +0x1B23,0x0000,0x0000, 0x1B24,0x0000,0x0000, 0x1B29,0x0000,0x0000, /* 131E */ +0x1B2A,0x0000,0x0000, 0x1B2B,0x0000,0x0000, 0x1B2C,0x0000,0x0000, /* 1321 */ +0x1B2D,0x0000,0x0000, 0x1B2E,0x0000,0x0000, 0x1B2F,0x0000,0x0000, /* 1324 */ +0x1B30,0x0000,0x0000, 0x1B32,0x0000,0x0000, 0x1B33,0x0000,0x0000, /* 1327 */ +0x1B34,0x0000,0x0000, 0x1B35,0x0000,0x0000, 0x1B36,0x0000,0x0000, /* 132A */ +0x1B37,0x0000,0x0000, 0x1B38,0x0000,0x0000, 0x1B39,0x0000,0x0000, /* 132D */ +0x1B3B,0x0000,0x0000, 0x1B3C,0x0000,0x0000, 0x1B3D,0x0000,0x0000, /* 1330 */ +0x1B3E,0x0000,0x0000, 0x1B3F,0x0000,0x0000, 0x1B40,0x0000,0x0000, /* 1333 */ +0x1B41,0x0000,0x0000, 0x1B42,0x0000,0x0000, 0x1B44,0x0000,0x0000, /* 1336 */ +0x1B45,0x0000,0x0000, 0x1B46,0x0000,0x0000, 0x1B47,0x0000,0x0000, /* 1339 */ +0x1B48,0x0000,0x0000, 0x1B49,0x0000,0x0000, 0x1B4A,0x0000,0x0000, /* 133C */ +0x1B4B,0x0000,0x0000, 0x1B4C,0x0000,0x0000, 0x1B4D,0x0000,0x0000, /* 133F */ +0x1B4E,0x0000,0x0000, 0x1B4F,0x0000,0x0000, 0x1B50,0x0000,0x0000, /* 1342 */ +0x1B51,0x0000,0x0000, 0x1B52,0x0000,0x0000, 0x1B53,0x0000,0x0000, /* 1345 */ +0x1B54,0x0000,0x0000, 0x1B55,0x0000,0x0000, 0x1B56,0x0000,0x0000, /* 1348 */ +0x1B57,0x0000,0x0000, 0x1B58,0x0000,0x0000, 0x1B59,0x0000,0x0000, /* 134B */ +0x1B5A,0x0000,0x0000, 0x1B5B,0x0000,0x0000, 0x1B60,0x0000,0x0000, /* 134E */ +0x1B61,0x0000,0x0000, 0x1B62,0x0000,0x0000, 0x1B63,0x0000,0x0000, /* 1351 */ +0x1B64,0x0000,0x0000, 0x1B65,0x0000,0x0000, 0x1B66,0x0000,0x0000, /* 1354 */ +0x1B67,0x0000,0x0000, 0x1B6D,0x0000,0x0000, 0x1B6E,0x0000,0x0000, /* 1357 */ +0x1B6F,0x0000,0x0000, 0xFBC0,0x935B,0x0000, 0xFBC0,0x935C,0x0000, /* 135A */ +0xFBC0,0x935D,0x0000, 0xFBC0,0x935E,0x0000, 0x0000,0x0000,0x0000, /* 135D */ +0x02B8,0x0000,0x0000, 0x025F,0x0000,0x0000, 0x0286,0x0000,0x0000, /* 1360 */ +0x0260,0x0000,0x0000, 0x0261,0x0000,0x0000, 0x0262,0x0000,0x0000, /* 1363 */ +0x0263,0x0000,0x0000, 0x0279,0x0000,0x0000, 0x02B9,0x0000,0x0000, /* 1366 */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 1369 */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 136C */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 136F */ +0x1125,0x0000,0x0000, 0x1126,0x0000,0x0000, 0x1127,0x0000,0x0000, /* 1372 */ +0x1128,0x0000,0x0000, 0x1129,0x0000,0x0000, 0x112A,0x0000,0x0000, /* 1375 */ +0x112B,0x0000,0x0000, 0x112C,0x0000,0x0000, 0x112D,0x0000,0x0000, /* 1378 */ +0x112E,0x0000,0x0000, 0x112F,0x0000,0x0000, 0xFBC0,0x937D,0x0000, /* 137B */ +0xFBC0,0x937E,0x0000, 0xFBC0,0x937F,0x0000, 0x1A24,0x0000,0x0000, /* 137E */ +0x1A25,0x0000,0x0000, 0x1A26,0x0000,0x0000, 0x1A27,0x0000,0x0000, /* 1381 */ +0x1A6D,0x0000,0x0000, 0x1A6E,0x0000,0x0000, 0x1A6F,0x0000,0x0000, /* 1384 */ +0x1A70,0x0000,0x0000, 0x1B5C,0x0000,0x0000, 0x1B5D,0x0000,0x0000, /* 1387 */ +0x1B5E,0x0000,0x0000, 0x1B5F,0x0000,0x0000, 0x1B68,0x0000,0x0000, /* 138A */ +0x1B69,0x0000,0x0000, 0x1B6A,0x0000,0x0000, 0x1B6B,0x0000,0x0000, /* 138D */ +0x041C,0x0000,0x0000, 0x041D,0x0000,0x0000, 0x041E,0x0000,0x0000, /* 1390 */ +0x041F,0x0000,0x0000, 0x0420,0x0000,0x0000, 0x0421,0x0000,0x0000, /* 1393 */ +0x0422,0x0000,0x0000, 0x0423,0x0000,0x0000, 0x0424,0x0000,0x0000, /* 1396 */ +0x0425,0x0000,0x0000, 0xFBC0,0x939A,0x0000, 0xFBC0,0x939B,0x0000, /* 1399 */ +0xFBC0,0x939C,0x0000, 0xFBC0,0x939D,0x0000, 0xFBC0,0x939E,0x0000, /* 139C */ +0xFBC0,0x939F,0x0000, 0x24CE,0x0000,0x0000, 0x24CF,0x0000,0x0000, /* 139F */ +0x24D0,0x0000,0x0000, 0x24D1,0x0000,0x0000, 0x24D2,0x0000,0x0000, /* 13A2 */ +0x24D3,0x0000,0x0000, 0x24D4,0x0000,0x0000, 0x24D5,0x0000,0x0000, /* 13A5 */ +0x24D6,0x0000,0x0000, 0x24D7,0x0000,0x0000, 0x24D8,0x0000,0x0000, /* 13A8 */ +0x24D9,0x0000,0x0000, 0x24DA,0x0000,0x0000, 0x24DB,0x0000,0x0000, /* 13AB */ +0x24DC,0x0000,0x0000, 0x24DD,0x0000,0x0000, 0x24DE,0x0000,0x0000, /* 13AE */ +0x24DF,0x0000,0x0000, 0x24E0,0x0000,0x0000, 0x24E1,0x0000,0x0000, /* 13B1 */ +0x24E2,0x0000,0x0000, 0x24E3,0x0000,0x0000, 0x24E4,0x0000,0x0000, /* 13B4 */ +0x24E5,0x0000,0x0000, 0x24E6,0x0000,0x0000, 0x24E7,0x0000,0x0000, /* 13B7 */ +0x24E8,0x0000,0x0000, 0x24E9,0x0000,0x0000, 0x24EA,0x0000,0x0000, /* 13BA */ +0x24EB,0x0000,0x0000, 0x24EC,0x0000,0x0000, 0x24ED,0x0000,0x0000, /* 13BD */ +0x24EE,0x0000,0x0000, 0x24EF,0x0000,0x0000, 0x24F0,0x0000,0x0000, /* 13C0 */ +0x24F1,0x0000,0x0000, 0x24F2,0x0000,0x0000, 0x24F3,0x0000,0x0000, /* 13C3 */ +0x24F4,0x0000,0x0000, 0x24F5,0x0000,0x0000, 0x24F6,0x0000,0x0000, /* 13C6 */ +0x24F7,0x0000,0x0000, 0x24F8,0x0000,0x0000, 0x24F9,0x0000,0x0000, /* 13C9 */ +0x24FA,0x0000,0x0000, 0x24FB,0x0000,0x0000, 0x24FC,0x0000,0x0000, /* 13CC */ +0x24FD,0x0000,0x0000, 0x24FE,0x0000,0x0000, 0x24FF,0x0000,0x0000, /* 13CF */ +0x2500,0x0000,0x0000, 0x2501,0x0000,0x0000, 0x2502,0x0000,0x0000, /* 13D2 */ +0x2503,0x0000,0x0000, 0x2504,0x0000,0x0000, 0x2505,0x0000,0x0000, /* 13D5 */ +0x2506,0x0000,0x0000, 0x2507,0x0000,0x0000, 0x2508,0x0000,0x0000, /* 13D8 */ +0x2509,0x0000,0x0000, 0x250A,0x0000,0x0000, 0x250B,0x0000,0x0000, /* 13DB */ +0x250C,0x0000,0x0000, 0x250D,0x0000,0x0000, 0x250E,0x0000,0x0000, /* 13DE */ +0x250F,0x0000,0x0000, 0x2510,0x0000,0x0000, 0x2511,0x0000,0x0000, /* 13E1 */ +0x2512,0x0000,0x0000, 0x2513,0x0000,0x0000, 0x2514,0x0000,0x0000, /* 13E4 */ +0x2515,0x0000,0x0000, 0x2516,0x0000,0x0000, 0x2517,0x0000,0x0000, /* 13E7 */ +0x2518,0x0000,0x0000, 0x2519,0x0000,0x0000, 0x251A,0x0000,0x0000, /* 13EA */ +0x251B,0x0000,0x0000, 0x251C,0x0000,0x0000, 0x251D,0x0000,0x0000, /* 13ED */ +0x251E,0x0000,0x0000, 0x251F,0x0000,0x0000, 0x2520,0x0000,0x0000, /* 13F0 */ +0x2521,0x0000,0x0000, 0x2522,0x0000,0x0000, 0xFBC0,0x93F5,0x0000, /* 13F3 */ +0xFBC0,0x93F6,0x0000, 0xFBC0,0x93F7,0x0000, 0xFBC0,0x93F8,0x0000, /* 13F6 */ +0xFBC0,0x93F9,0x0000, 0xFBC0,0x93FA,0x0000, 0xFBC0,0x93FB,0x0000, /* 13F9 */ +0xFBC0,0x93FC,0x0000, 0xFBC0,0x93FD,0x0000, 0xFBC0,0x93FE,0x0000, /* 13FC */ +0xFBC0,0x93FF,0x0000 }; + +uint16 uca520_p014[]= { /* 1400 (2 weights per char) */ +0x0225,0x0000, 0x2523,0x0000, 0x2524,0x0000, 0x2525,0x0000, /* 1400 */ +0x2526,0x0000, 0x2527,0x0000, 0x2528,0x0000, 0x2529,0x0000, /* 1404 */ +0x252A,0x0000, 0x252B,0x0000, 0x252C,0x0000, 0x252D,0x0000, /* 1408 */ +0x252E,0x0000, 0x252F,0x0000, 0x2530,0x0000, 0x2531,0x0000, /* 140C */ +0x2532,0x0000, 0x2533,0x0000, 0x2534,0x0000, 0x2535,0x0000, /* 1410 */ +0x2536,0x0000, 0x2537,0x0000, 0x2538,0x0000, 0x2539,0x0000, /* 1414 */ +0x253A,0x0000, 0x253B,0x0000, 0x253C,0x0000, 0x253D,0x0000, /* 1418 */ +0x253E,0x0000, 0x253F,0x0000, 0x2540,0x0000, 0x2541,0x0000, /* 141C */ +0x2542,0x0000, 0x2543,0x0000, 0x2544,0x0000, 0x2545,0x0000, /* 1420 */ +0x2546,0x0000, 0x2547,0x0000, 0x2548,0x0000, 0x2549,0x0000, /* 1424 */ +0x254A,0x0000, 0x254B,0x0000, 0x254C,0x0000, 0x254D,0x0000, /* 1428 */ +0x254E,0x0000, 0x254F,0x0000, 0x2550,0x0000, 0x2551,0x0000, /* 142C */ +0x2552,0x0000, 0x2553,0x0000, 0x2554,0x0000, 0x2555,0x0000, /* 1430 */ +0x2556,0x0000, 0x2557,0x0000, 0x2558,0x0000, 0x2559,0x0000, /* 1434 */ +0x255A,0x0000, 0x255B,0x0000, 0x255C,0x0000, 0x255D,0x0000, /* 1438 */ +0x255E,0x0000, 0x255F,0x0000, 0x2560,0x0000, 0x2561,0x0000, /* 143C */ +0x2562,0x0000, 0x2563,0x0000, 0x2564,0x0000, 0x2565,0x0000, /* 1440 */ +0x2566,0x0000, 0x2567,0x0000, 0x2568,0x0000, 0x2569,0x0000, /* 1444 */ +0x256A,0x0000, 0x256B,0x0000, 0x256C,0x0000, 0x256D,0x0000, /* 1448 */ +0x256E,0x0000, 0x256F,0x0000, 0x2570,0x0000, 0x2571,0x0000, /* 144C */ +0x2572,0x0000, 0x2573,0x0000, 0x2574,0x0000, 0x2575,0x0000, /* 1450 */ +0x2576,0x0000, 0x2577,0x0000, 0x2578,0x0000, 0x2579,0x0000, /* 1454 */ +0x257A,0x0000, 0x257B,0x0000, 0x257C,0x0000, 0x257D,0x0000, /* 1458 */ +0x257E,0x0000, 0x257F,0x0000, 0x2580,0x0000, 0x2581,0x0000, /* 145C */ +0x2582,0x0000, 0x2583,0x0000, 0x2584,0x0000, 0x2585,0x0000, /* 1460 */ +0x2586,0x0000, 0x2587,0x0000, 0x2588,0x0000, 0x2589,0x0000, /* 1464 */ +0x258A,0x0000, 0x258B,0x0000, 0x258C,0x0000, 0x258D,0x0000, /* 1468 */ +0x258E,0x0000, 0x258F,0x0000, 0x2590,0x0000, 0x2591,0x0000, /* 146C */ +0x2592,0x0000, 0x2593,0x0000, 0x2594,0x0000, 0x2595,0x0000, /* 1470 */ +0x2596,0x0000, 0x2597,0x0000, 0x2598,0x0000, 0x2599,0x0000, /* 1474 */ +0x259A,0x0000, 0x259B,0x0000, 0x259C,0x0000, 0x259D,0x0000, /* 1478 */ +0x259E,0x0000, 0x259F,0x0000, 0x25A0,0x0000, 0x25A1,0x0000, /* 147C */ +0x25A2,0x0000, 0x25A3,0x0000, 0x25A4,0x0000, 0x25A5,0x0000, /* 1480 */ +0x25A6,0x0000, 0x25A7,0x0000, 0x25A8,0x0000, 0x25A9,0x0000, /* 1484 */ +0x25AA,0x0000, 0x25AB,0x0000, 0x25AC,0x0000, 0x25AD,0x0000, /* 1488 */ +0x25AE,0x0000, 0x25AF,0x0000, 0x25B0,0x0000, 0x25B1,0x0000, /* 148C */ +0x25B2,0x0000, 0x25B3,0x0000, 0x25B4,0x0000, 0x25B5,0x0000, /* 1490 */ +0x25B6,0x0000, 0x25B7,0x0000, 0x25B8,0x0000, 0x25B9,0x0000, /* 1494 */ +0x25BA,0x0000, 0x25BB,0x0000, 0x25BC,0x0000, 0x25BD,0x0000, /* 1498 */ +0x25BE,0x0000, 0x25BF,0x0000, 0x25C0,0x0000, 0x25C1,0x0000, /* 149C */ +0x25C2,0x0000, 0x25C3,0x0000, 0x25C4,0x0000, 0x25C5,0x0000, /* 14A0 */ +0x25C6,0x0000, 0x25C7,0x0000, 0x25C8,0x0000, 0x25C9,0x0000, /* 14A4 */ +0x25CA,0x0000, 0x25CB,0x0000, 0x25CC,0x0000, 0x25CD,0x0000, /* 14A8 */ +0x25CE,0x0000, 0x25CF,0x0000, 0x25D0,0x0000, 0x25D1,0x0000, /* 14AC */ +0x25D2,0x0000, 0x25D3,0x0000, 0x25D4,0x0000, 0x25D5,0x0000, /* 14B0 */ +0x25D6,0x0000, 0x25D7,0x0000, 0x25D8,0x0000, 0x25D9,0x0000, /* 14B4 */ +0x25DA,0x0000, 0x25DB,0x0000, 0x25DC,0x0000, 0x25DD,0x0000, /* 14B8 */ +0x25DE,0x0000, 0x25DF,0x0000, 0x25E0,0x0000, 0x25E1,0x0000, /* 14BC */ +0x25E2,0x0000, 0x25E3,0x0000, 0x25E4,0x0000, 0x25E5,0x0000, /* 14C0 */ +0x25E6,0x0000, 0x25E7,0x0000, 0x25E8,0x0000, 0x25E9,0x0000, /* 14C4 */ +0x25EA,0x0000, 0x25EB,0x0000, 0x25EC,0x0000, 0x25ED,0x0000, /* 14C8 */ +0x25EE,0x0000, 0x25EF,0x0000, 0x25F0,0x0000, 0x25F1,0x0000, /* 14CC */ +0x25F2,0x0000, 0x25F3,0x0000, 0x25F4,0x0000, 0x25F5,0x0000, /* 14D0 */ +0x25F6,0x0000, 0x25F7,0x0000, 0x25F8,0x0000, 0x25F9,0x0000, /* 14D4 */ +0x25FA,0x0000, 0x25FB,0x0000, 0x25FC,0x0000, 0x25FD,0x0000, /* 14D8 */ +0x25FE,0x0000, 0x25FF,0x0000, 0x2600,0x0000, 0x2601,0x0000, /* 14DC */ +0x2602,0x0000, 0x2603,0x0000, 0x2604,0x0000, 0x2605,0x0000, /* 14E0 */ +0x2606,0x0000, 0x2607,0x0000, 0x2608,0x0000, 0x2609,0x0000, /* 14E4 */ +0x260A,0x0000, 0x260B,0x0000, 0x260C,0x0000, 0x260D,0x0000, /* 14E8 */ +0x260E,0x0000, 0x260F,0x0000, 0x2610,0x0000, 0x2611,0x0000, /* 14EC */ +0x2612,0x0000, 0x2613,0x0000, 0x2614,0x0000, 0x2615,0x0000, /* 14F0 */ +0x2616,0x0000, 0x2617,0x0000, 0x2618,0x0000, 0x2619,0x0000, /* 14F4 */ +0x261A,0x0000, 0x261B,0x0000, 0x261C,0x0000, 0x261D,0x0000, /* 14F8 */ +0x261E,0x0000, 0x261F,0x0000, 0x2620,0x0000, 0x2621,0x0000 /* 14FC */ +}; + +uint16 uca520_p015[]= { /* 1500 (2 weights per char) */ +0x2622,0x0000, 0x2623,0x0000, 0x2624,0x0000, 0x2625,0x0000, /* 1500 */ +0x2626,0x0000, 0x2627,0x0000, 0x2628,0x0000, 0x2629,0x0000, /* 1504 */ +0x262A,0x0000, 0x262B,0x0000, 0x262C,0x0000, 0x262D,0x0000, /* 1508 */ +0x262E,0x0000, 0x262F,0x0000, 0x2630,0x0000, 0x2631,0x0000, /* 150C */ +0x2632,0x0000, 0x2633,0x0000, 0x2634,0x0000, 0x2635,0x0000, /* 1510 */ +0x2636,0x0000, 0x2637,0x0000, 0x2638,0x0000, 0x2639,0x0000, /* 1514 */ +0x263A,0x0000, 0x263B,0x0000, 0x263C,0x0000, 0x263D,0x0000, /* 1518 */ +0x263E,0x0000, 0x263F,0x0000, 0x2640,0x0000, 0x2641,0x0000, /* 151C */ +0x2642,0x0000, 0x2643,0x0000, 0x2644,0x0000, 0x2645,0x0000, /* 1520 */ +0x2646,0x0000, 0x2647,0x0000, 0x2648,0x0000, 0x2649,0x0000, /* 1524 */ +0x264A,0x0000, 0x264B,0x0000, 0x264C,0x0000, 0x264D,0x0000, /* 1528 */ +0x264E,0x0000, 0x264F,0x0000, 0x2650,0x0000, 0x2651,0x0000, /* 152C */ +0x2652,0x0000, 0x2653,0x0000, 0x2654,0x0000, 0x2655,0x0000, /* 1530 */ +0x2656,0x0000, 0x2657,0x0000, 0x2658,0x0000, 0x2659,0x0000, /* 1534 */ +0x265A,0x0000, 0x265B,0x0000, 0x265C,0x0000, 0x265D,0x0000, /* 1538 */ +0x265E,0x0000, 0x265F,0x0000, 0x2660,0x0000, 0x2661,0x0000, /* 153C */ +0x2662,0x0000, 0x2663,0x0000, 0x2664,0x0000, 0x2665,0x0000, /* 1540 */ +0x2666,0x0000, 0x2667,0x0000, 0x2668,0x0000, 0x2669,0x0000, /* 1544 */ +0x266A,0x0000, 0x266B,0x0000, 0x266C,0x0000, 0x266D,0x0000, /* 1548 */ +0x266E,0x0000, 0x266F,0x0000, 0x2670,0x0000, 0x2671,0x0000, /* 154C */ +0x2672,0x0000, 0x2673,0x0000, 0x2674,0x0000, 0x2675,0x0000, /* 1550 */ +0x2676,0x0000, 0x2677,0x0000, 0x2678,0x0000, 0x2679,0x0000, /* 1554 */ +0x267A,0x0000, 0x267B,0x0000, 0x267C,0x0000, 0x267D,0x0000, /* 1558 */ +0x267E,0x0000, 0x267F,0x0000, 0x2680,0x0000, 0x2681,0x0000, /* 155C */ +0x2682,0x0000, 0x2683,0x0000, 0x2684,0x0000, 0x2685,0x0000, /* 1560 */ +0x2686,0x0000, 0x2687,0x0000, 0x2688,0x0000, 0x2689,0x0000, /* 1564 */ +0x268A,0x0000, 0x268B,0x0000, 0x268C,0x0000, 0x268D,0x0000, /* 1568 */ +0x268E,0x0000, 0x268F,0x0000, 0x2690,0x0000, 0x2691,0x0000, /* 156C */ +0x2692,0x0000, 0x2693,0x0000, 0x2694,0x0000, 0x2695,0x0000, /* 1570 */ +0x2696,0x0000, 0x2697,0x0000, 0x2698,0x0000, 0x2699,0x0000, /* 1574 */ +0x269A,0x0000, 0x269B,0x0000, 0x269C,0x0000, 0x269D,0x0000, /* 1578 */ +0x26D0,0x0000, 0x269E,0x0000, 0x26A0,0x0000, 0x26A1,0x0000, /* 157C */ +0x26A2,0x0000, 0x26A3,0x0000, 0x26A4,0x0000, 0x26A5,0x0000, /* 1580 */ +0x26A6,0x0000, 0x26A7,0x0000, 0x26A8,0x0000, 0x26A9,0x0000, /* 1584 */ +0x26AA,0x0000, 0x26AB,0x0000, 0x26AC,0x0000, 0x26AD,0x0000, /* 1588 */ +0x26AE,0x0000, 0x26AF,0x0000, 0x26B1,0x0000, 0x26B2,0x0000, /* 158C */ +0x26B3,0x0000, 0x26B4,0x0000, 0x26B5,0x0000, 0x26B6,0x0000, /* 1590 */ +0x26B7,0x0000, 0x26B8,0x0000, 0x26BF,0x0000, 0x26C0,0x0000, /* 1594 */ +0x26C1,0x0000, 0x26C2,0x0000, 0x26C3,0x0000, 0x26C4,0x0000, /* 1598 */ +0x26C5,0x0000, 0x26C6,0x0000, 0x26C7,0x0000, 0x26C8,0x0000, /* 159C */ +0x26C9,0x0000, 0x26CA,0x0000, 0x26CB,0x0000, 0x26CC,0x0000, /* 15A0 */ +0x26CD,0x0000, 0x26CE,0x0000, 0x26CF,0x0000, 0x26D1,0x0000, /* 15A4 */ +0x26D2,0x0000, 0x26D3,0x0000, 0x26D4,0x0000, 0x26D5,0x0000, /* 15A8 */ +0x26D6,0x0000, 0x26D7,0x0000, 0x26D8,0x0000, 0x26D9,0x0000, /* 15AC */ +0x26DA,0x0000, 0x26DB,0x0000, 0x26DC,0x0000, 0x26DD,0x0000, /* 15B0 */ +0x26DE,0x0000, 0x26DF,0x0000, 0x26E0,0x0000, 0x26E1,0x0000, /* 15B4 */ +0x26E2,0x0000, 0x26E3,0x0000, 0x26E4,0x0000, 0x26E5,0x0000, /* 15B8 */ +0x26E6,0x0000, 0x26E7,0x0000, 0x26E8,0x0000, 0x26E9,0x0000, /* 15BC */ +0x26EA,0x0000, 0x26EB,0x0000, 0x26EC,0x0000, 0x26ED,0x0000, /* 15C0 */ +0x26EE,0x0000, 0x26EF,0x0000, 0x26F0,0x0000, 0x26F1,0x0000, /* 15C4 */ +0x26F2,0x0000, 0x26F3,0x0000, 0x26F4,0x0000, 0x26F5,0x0000, /* 15C8 */ +0x26F6,0x0000, 0x26F7,0x0000, 0x26F8,0x0000, 0x26F9,0x0000, /* 15CC */ +0x26FA,0x0000, 0x26FB,0x0000, 0x26FC,0x0000, 0x26FD,0x0000, /* 15D0 */ +0x26FE,0x0000, 0x26FF,0x0000, 0x2700,0x0000, 0x2701,0x0000, /* 15D4 */ +0x2702,0x0000, 0x2703,0x0000, 0x2704,0x0000, 0x2705,0x0000, /* 15D8 */ +0x2706,0x0000, 0x2707,0x0000, 0x2708,0x0000, 0x2709,0x0000, /* 15DC */ +0x270A,0x0000, 0x270B,0x0000, 0x270C,0x0000, 0x270D,0x0000, /* 15E0 */ +0x270E,0x0000, 0x270F,0x0000, 0x2710,0x0000, 0x2711,0x0000, /* 15E4 */ +0x2712,0x0000, 0x2713,0x0000, 0x2714,0x0000, 0x2715,0x0000, /* 15E8 */ +0x2716,0x0000, 0x2717,0x0000, 0x2718,0x0000, 0x2719,0x0000, /* 15EC */ +0x271A,0x0000, 0x271B,0x0000, 0x271C,0x0000, 0x271D,0x0000, /* 15F0 */ +0x271E,0x0000, 0x271F,0x0000, 0x2720,0x0000, 0x2721,0x0000, /* 15F4 */ +0x2722,0x0000, 0x2723,0x0000, 0x2724,0x0000, 0x2725,0x0000, /* 15F8 */ +0x2726,0x0000, 0x2727,0x0000, 0x2728,0x0000, 0x2729,0x0000 /* 15FC */ +}; + +uint16 uca520_p016[]= { /* 1600 (3 weights per char) */ +0x272A,0x0000,0x0000, 0x272B,0x0000,0x0000, 0x272C,0x0000,0x0000, /* 1600 */ +0x272D,0x0000,0x0000, 0x272E,0x0000,0x0000, 0x272F,0x0000,0x0000, /* 1603 */ +0x2730,0x0000,0x0000, 0x2731,0x0000,0x0000, 0x2732,0x0000,0x0000, /* 1606 */ +0x2733,0x0000,0x0000, 0x2734,0x0000,0x0000, 0x2735,0x0000,0x0000, /* 1609 */ +0x2736,0x0000,0x0000, 0x2737,0x0000,0x0000, 0x2738,0x0000,0x0000, /* 160C */ +0x2739,0x0000,0x0000, 0x273A,0x0000,0x0000, 0x273B,0x0000,0x0000, /* 160F */ +0x273C,0x0000,0x0000, 0x273D,0x0000,0x0000, 0x273E,0x0000,0x0000, /* 1612 */ +0x273F,0x0000,0x0000, 0x2740,0x0000,0x0000, 0x2741,0x0000,0x0000, /* 1615 */ +0x2742,0x0000,0x0000, 0x2743,0x0000,0x0000, 0x2744,0x0000,0x0000, /* 1618 */ +0x2745,0x0000,0x0000, 0x2746,0x0000,0x0000, 0x2747,0x0000,0x0000, /* 161B */ +0x2748,0x0000,0x0000, 0x2749,0x0000,0x0000, 0x274A,0x0000,0x0000, /* 161E */ +0x274B,0x0000,0x0000, 0x274C,0x0000,0x0000, 0x274D,0x0000,0x0000, /* 1621 */ +0x274E,0x0000,0x0000, 0x274F,0x0000,0x0000, 0x2750,0x0000,0x0000, /* 1624 */ +0x2751,0x0000,0x0000, 0x2752,0x0000,0x0000, 0x2753,0x0000,0x0000, /* 1627 */ +0x2754,0x0000,0x0000, 0x2755,0x0000,0x0000, 0x2756,0x0000,0x0000, /* 162A */ +0x2757,0x0000,0x0000, 0x2758,0x0000,0x0000, 0x2759,0x0000,0x0000, /* 162D */ +0x275A,0x0000,0x0000, 0x275B,0x0000,0x0000, 0x275C,0x0000,0x0000, /* 1630 */ +0x275D,0x0000,0x0000, 0x275E,0x0000,0x0000, 0x275F,0x0000,0x0000, /* 1633 */ +0x2760,0x0000,0x0000, 0x2761,0x0000,0x0000, 0x2762,0x0000,0x0000, /* 1636 */ +0x2763,0x0000,0x0000, 0x2764,0x0000,0x0000, 0x2765,0x0000,0x0000, /* 1639 */ +0x2766,0x0000,0x0000, 0x2767,0x0000,0x0000, 0x2768,0x0000,0x0000, /* 163C */ +0x2769,0x0000,0x0000, 0x276A,0x0000,0x0000, 0x276B,0x0000,0x0000, /* 163F */ +0x276C,0x0000,0x0000, 0x276D,0x0000,0x0000, 0x276E,0x0000,0x0000, /* 1642 */ +0x276F,0x0000,0x0000, 0x2770,0x0000,0x0000, 0x2771,0x0000,0x0000, /* 1645 */ +0x2772,0x0000,0x0000, 0x2773,0x0000,0x0000, 0x2774,0x0000,0x0000, /* 1648 */ +0x2775,0x0000,0x0000, 0x2776,0x0000,0x0000, 0x2777,0x0000,0x0000, /* 164B */ +0x2778,0x0000,0x0000, 0x2779,0x0000,0x0000, 0x277A,0x0000,0x0000, /* 164E */ +0x277B,0x0000,0x0000, 0x277C,0x0000,0x0000, 0x277D,0x0000,0x0000, /* 1651 */ +0x277E,0x0000,0x0000, 0x277F,0x0000,0x0000, 0x2780,0x0000,0x0000, /* 1654 */ +0x2781,0x0000,0x0000, 0x2782,0x0000,0x0000, 0x2783,0x0000,0x0000, /* 1657 */ +0x2784,0x0000,0x0000, 0x2785,0x0000,0x0000, 0x2786,0x0000,0x0000, /* 165A */ +0x2787,0x0000,0x0000, 0x2788,0x0000,0x0000, 0x2789,0x0000,0x0000, /* 165D */ +0x278A,0x0000,0x0000, 0x278B,0x0000,0x0000, 0x278C,0x0000,0x0000, /* 1660 */ +0x278D,0x0000,0x0000, 0x278E,0x0000,0x0000, 0x278F,0x0000,0x0000, /* 1663 */ +0x2790,0x0000,0x0000, 0x2791,0x0000,0x0000, 0x2792,0x0000,0x0000, /* 1666 */ +0x2793,0x0000,0x0000, 0x2794,0x0000,0x0000, 0x2795,0x0000,0x0000, /* 1669 */ +0x2796,0x0000,0x0000, 0x03D8,0x0000,0x0000, 0x0289,0x0000,0x0000, /* 166C */ +0x269F,0x0000,0x0000, 0x26B0,0x0000,0x0000, 0x26B9,0x0000,0x0000, /* 166F */ +0x26BA,0x0000,0x0000, 0x26BB,0x0000,0x0000, 0x26BC,0x0000,0x0000, /* 1672 */ +0x26BD,0x0000,0x0000, 0x26BE,0x0000,0x0000, 0x2797,0x0000,0x0000, /* 1675 */ +0x2798,0x0000,0x0000, 0x2799,0x0000,0x0000, 0x279A,0x0000,0x0000, /* 1678 */ +0x279B,0x0000,0x0000, 0x279C,0x0000,0x0000, 0x279D,0x0000,0x0000, /* 167B */ +0x279E,0x0000,0x0000, 0x279F,0x0000,0x0000, 0x020B,0x0000,0x0000, /* 167E */ +0x27E6,0x0000,0x0000, 0x27E7,0x0000,0x0000, 0x27E8,0x0000,0x0000, /* 1681 */ +0x27E9,0x0000,0x0000, 0x27EA,0x0000,0x0000, 0x27EB,0x0000,0x0000, /* 1684 */ +0x27EC,0x0000,0x0000, 0x27ED,0x0000,0x0000, 0x27EE,0x0000,0x0000, /* 1687 */ +0x27EF,0x0000,0x0000, 0x27F0,0x0000,0x0000, 0x27F1,0x0000,0x0000, /* 168A */ +0x27F2,0x0000,0x0000, 0x27F3,0x0000,0x0000, 0x27F4,0x0000,0x0000, /* 168D */ +0x27F5,0x0000,0x0000, 0x27F6,0x0000,0x0000, 0x27F7,0x0000,0x0000, /* 1690 */ +0x27F8,0x0000,0x0000, 0x27F9,0x0000,0x0000, 0x27FA,0x0000,0x0000, /* 1693 */ +0x27FB,0x0000,0x0000, 0x27FC,0x0000,0x0000, 0x27FD,0x0000,0x0000, /* 1696 */ +0x27FE,0x0000,0x0000, 0x27FF,0x0000,0x0000, 0x0309,0x0000,0x0000, /* 1699 */ +0x030A,0x0000,0x0000, 0xFBC0,0x969D,0x0000, 0xFBC0,0x969E,0x0000, /* 169C */ +0xFBC0,0x969F,0x0000, 0x2800,0x0000,0x0000, 0x2800,0x0000,0x0000, /* 169F */ +0x2801,0x0000,0x0000, 0x281D,0x0000,0x0000, 0x2801,0x0000,0x0000, /* 16A2 */ +0x2801,0x0000,0x0000, 0x2802,0x0000,0x0000, 0x2802,0x0000,0x0000, /* 16A5 */ +0x2803,0x0000,0x0000, 0x2803,0x0000,0x0000, 0x281B,0x0000,0x0000, /* 16A8 */ +0x281C,0x0000,0x0000, 0x2803,0x0000,0x0000, 0x2803,0x0000,0x0000, /* 16AB */ +0x2803,0x0000,0x0000, 0x2804,0x0000,0x0000, 0x2805,0x0000,0x0000, /* 16AE */ +0x2806,0x0000,0x0000, 0x2807,0x0000,0x0000, 0x2807,0x0000,0x0000, /* 16B1 */ +0x2807,0x0000,0x0000, 0x2807,0x0000,0x0000, 0x2807,0x0000,0x0000, /* 16B4 */ +0x2808,0x0000,0x0000, 0x2820,0x0000,0x0000, 0x2809,0x0000,0x0000, /* 16B7 */ +0x280A,0x0000,0x0000, 0x280A,0x0000,0x0000, 0x280A,0x0000,0x0000, /* 16BA */ +0x280A,0x0000,0x0000, 0x280B,0x0000,0x0000, 0x280B,0x0000,0x0000, /* 16BD */ +0x280B,0x0000,0x0000, 0x280C,0x0000,0x0000, 0x280C,0x0000,0x0000, /* 16C0 */ +0x280D,0x0000,0x0000, 0x280D,0x0000,0x0000, 0x280E,0x0000,0x0000, /* 16C3 */ +0x280E,0x0000,0x0000, 0x280F,0x0000,0x0000, 0x2810,0x0000,0x0000, /* 16C6 */ +0x2811,0x0000,0x0000, 0x2812,0x0000,0x0000, 0x2812,0x0000,0x0000, /* 16C9 */ +0x2812,0x0000,0x0000, 0x2812,0x0000,0x0000, 0x2812,0x0000,0x0000, /* 16CC */ +0x2813,0x0000,0x0000, 0x2813,0x0000,0x0000, 0x2813,0x0000,0x0000, /* 16CF */ +0x2814,0x0000,0x0000, 0x2814,0x0000,0x0000, 0x2814,0x0000,0x0000, /* 16D2 */ +0x2810,0x0000,0x0000, 0x2815,0x0000,0x0000, 0x2816,0x0000,0x0000, /* 16D5 */ +0x2816,0x0000,0x0000, 0x2816,0x0000,0x0000, 0x2817,0x0000,0x0000, /* 16D8 */ +0x2817,0x0000,0x0000, 0x2818,0x0000,0x0000, 0x2818,0x0000,0x0000, /* 16DB */ +0x2819,0x0000,0x0000, 0x281A,0x0000,0x0000, 0x281E,0x0000,0x0000, /* 16DE */ +0x2822,0x0000,0x0000, 0x2823,0x0000,0x0000, 0x281F,0x0000,0x0000, /* 16E1 */ +0x2821,0x0000,0x0000, 0x2824,0x0000,0x0000, 0x2825,0x0000,0x0000, /* 16E4 */ +0x2825,0x0000,0x0000, 0x2825,0x0000,0x0000, 0x2809,0x0000,0x0000, /* 16E7 */ +0x2812,0x0000,0x0000, 0x026A,0x0000,0x0000, 0x026B,0x0000,0x0000, /* 16EA */ +0x026C,0x0000,0x0000, 0x280E,0x2817,0x0000, 0x2816,0x2816,0x0000, /* 16ED */ +0x2802,0x2802,0x0000, 0xFBC0,0x96F1,0x0000, 0xFBC0,0x96F2,0x0000, /* 16F0 */ +0xFBC0,0x96F3,0x0000, 0xFBC0,0x96F4,0x0000, 0xFBC0,0x96F5,0x0000, /* 16F3 */ +0xFBC0,0x96F6,0x0000, 0xFBC0,0x96F7,0x0000, 0xFBC0,0x96F8,0x0000, /* 16F6 */ +0xFBC0,0x96F9,0x0000, 0xFBC0,0x96FA,0x0000, 0xFBC0,0x96FB,0x0000, /* 16F9 */ +0xFBC0,0x96FC,0x0000, 0xFBC0,0x96FD,0x0000, 0xFBC0,0x96FE,0x0000, /* 16FC */ +0xFBC0,0x96FF,0x0000 }; + +uint16 uca520_p017[]= { /* 1700 (3 weights per char) */ +0x211D,0x0000,0x0000, 0x211E,0x0000,0x0000, 0x211F,0x0000,0x0000, /* 1700 */ +0x2120,0x0000,0x0000, 0x2121,0x0000,0x0000, 0x2122,0x0000,0x0000, /* 1703 */ +0x2123,0x0000,0x0000, 0x2124,0x0000,0x0000, 0x2125,0x0000,0x0000, /* 1706 */ +0x2126,0x0000,0x0000, 0x2127,0x0000,0x0000, 0x2128,0x0000,0x0000, /* 1709 */ +0x2129,0x0000,0x0000, 0xFBC0,0x970D,0x0000, 0x212A,0x0000,0x0000, /* 170C */ +0x212B,0x0000,0x0000, 0x212C,0x0000,0x0000, 0x212D,0x0000,0x0000, /* 170F */ +0x212E,0x0000,0x0000, 0x212F,0x0000,0x0000, 0x2130,0x0000,0x0000, /* 1712 */ +0xFBC0,0x9715,0x0000, 0xFBC0,0x9716,0x0000, 0xFBC0,0x9717,0x0000, /* 1715 */ +0xFBC0,0x9718,0x0000, 0xFBC0,0x9719,0x0000, 0xFBC0,0x971A,0x0000, /* 1718 */ +0xFBC0,0x971B,0x0000, 0xFBC0,0x971C,0x0000, 0xFBC0,0x971D,0x0000, /* 171B */ +0xFBC0,0x971E,0x0000, 0xFBC0,0x971F,0x0000, 0x2131,0x0000,0x0000, /* 171E */ +0x2132,0x0000,0x0000, 0x2133,0x0000,0x0000, 0x2134,0x0000,0x0000, /* 1721 */ +0x2135,0x0000,0x0000, 0x2136,0x0000,0x0000, 0x2137,0x0000,0x0000, /* 1724 */ +0x2138,0x0000,0x0000, 0x2139,0x0000,0x0000, 0x213A,0x0000,0x0000, /* 1727 */ +0x213B,0x0000,0x0000, 0x213C,0x0000,0x0000, 0x213D,0x0000,0x0000, /* 172A */ +0x213E,0x0000,0x0000, 0x213F,0x0000,0x0000, 0x2140,0x0000,0x0000, /* 172D */ +0x2141,0x0000,0x0000, 0x2142,0x0000,0x0000, 0x2143,0x0000,0x0000, /* 1730 */ +0x2144,0x0000,0x0000, 0x2145,0x0000,0x0000, 0x029C,0x0000,0x0000, /* 1733 */ +0x029D,0x0000,0x0000, 0xFBC0,0x9737,0x0000, 0xFBC0,0x9738,0x0000, /* 1736 */ +0xFBC0,0x9739,0x0000, 0xFBC0,0x973A,0x0000, 0xFBC0,0x973B,0x0000, /* 1739 */ +0xFBC0,0x973C,0x0000, 0xFBC0,0x973D,0x0000, 0xFBC0,0x973E,0x0000, /* 173C */ +0xFBC0,0x973F,0x0000, 0x2146,0x0000,0x0000, 0x2147,0x0000,0x0000, /* 173F */ +0x2148,0x0000,0x0000, 0x2149,0x0000,0x0000, 0x214A,0x0000,0x0000, /* 1742 */ +0x214B,0x0000,0x0000, 0x214C,0x0000,0x0000, 0x214D,0x0000,0x0000, /* 1745 */ +0x214E,0x0000,0x0000, 0x214F,0x0000,0x0000, 0x2150,0x0000,0x0000, /* 1748 */ +0x2151,0x0000,0x0000, 0x2152,0x0000,0x0000, 0x2153,0x0000,0x0000, /* 174B */ +0x2154,0x0000,0x0000, 0x2155,0x0000,0x0000, 0x2156,0x0000,0x0000, /* 174E */ +0x2157,0x0000,0x0000, 0x2158,0x0000,0x0000, 0x2159,0x0000,0x0000, /* 1751 */ +0xFBC0,0x9754,0x0000, 0xFBC0,0x9755,0x0000, 0xFBC0,0x9756,0x0000, /* 1754 */ +0xFBC0,0x9757,0x0000, 0xFBC0,0x9758,0x0000, 0xFBC0,0x9759,0x0000, /* 1757 */ +0xFBC0,0x975A,0x0000, 0xFBC0,0x975B,0x0000, 0xFBC0,0x975C,0x0000, /* 175A */ +0xFBC0,0x975D,0x0000, 0xFBC0,0x975E,0x0000, 0xFBC0,0x975F,0x0000, /* 175D */ +0x215A,0x0000,0x0000, 0x215B,0x0000,0x0000, 0x215C,0x0000,0x0000, /* 1760 */ +0x215D,0x0000,0x0000, 0x215E,0x0000,0x0000, 0x215F,0x0000,0x0000, /* 1763 */ +0x2160,0x0000,0x0000, 0x2161,0x0000,0x0000, 0x2162,0x0000,0x0000, /* 1766 */ +0x2163,0x0000,0x0000, 0x2164,0x0000,0x0000, 0x2165,0x0000,0x0000, /* 1769 */ +0x2166,0x0000,0x0000, 0xFBC0,0x976D,0x0000, 0x2167,0x0000,0x0000, /* 176C */ +0x2168,0x0000,0x0000, 0x2169,0x0000,0x0000, 0xFBC0,0x9771,0x0000, /* 176F */ +0x216A,0x0000,0x0000, 0x216B,0x0000,0x0000, 0xFBC0,0x9774,0x0000, /* 1772 */ +0xFBC0,0x9775,0x0000, 0xFBC0,0x9776,0x0000, 0xFBC0,0x9777,0x0000, /* 1775 */ +0xFBC0,0x9778,0x0000, 0xFBC0,0x9779,0x0000, 0xFBC0,0x977A,0x0000, /* 1778 */ +0xFBC0,0x977B,0x0000, 0xFBC0,0x977C,0x0000, 0xFBC0,0x977D,0x0000, /* 177B */ +0xFBC0,0x977E,0x0000, 0xFBC0,0x977F,0x0000, 0x2263,0x0000,0x0000, /* 177E */ +0x2264,0x0000,0x0000, 0x2265,0x0000,0x0000, 0x2266,0x0000,0x0000, /* 1781 */ +0x2267,0x0000,0x0000, 0x2268,0x0000,0x0000, 0x2269,0x0000,0x0000, /* 1784 */ +0x226A,0x0000,0x0000, 0x226B,0x0000,0x0000, 0x226C,0x0000,0x0000, /* 1787 */ +0x226D,0x0000,0x0000, 0x226E,0x0000,0x0000, 0x226F,0x0000,0x0000, /* 178A */ +0x2270,0x0000,0x0000, 0x2271,0x0000,0x0000, 0x2272,0x0000,0x0000, /* 178D */ +0x2273,0x0000,0x0000, 0x2274,0x0000,0x0000, 0x2275,0x0000,0x0000, /* 1790 */ +0x2276,0x0000,0x0000, 0x2277,0x0000,0x0000, 0x2278,0x0000,0x0000, /* 1793 */ +0x2279,0x0000,0x0000, 0x227A,0x0000,0x0000, 0x227B,0x0000,0x0000, /* 1796 */ +0x227C,0x0000,0x0000, 0x227D,0x0000,0x0000, 0x227E,0x0000,0x0000, /* 1799 */ +0x227F,0x0000,0x0000, 0x2280,0x0000,0x0000, 0x2281,0x0000,0x0000, /* 179C */ +0x2282,0x0000,0x0000, 0x2283,0x0000,0x0000, 0x2284,0x0000,0x0000, /* 179F */ +0x2285,0x0000,0x0000, 0x2287,0x0000,0x0000, 0x2288,0x0000,0x0000, /* 17A2 */ +0x2289,0x0000,0x0000, 0x228A,0x0000,0x0000, 0x228B,0x0000,0x0000, /* 17A5 */ +0x228C,0x0000,0x0000, 0x228D,0x0000,0x0000, 0x228E,0x0000,0x0000, /* 17A8 */ +0x228F,0x0000,0x0000, 0x2290,0x0000,0x0000, 0x2291,0x0000,0x0000, /* 17AB */ +0x2292,0x0000,0x0000, 0x2293,0x0000,0x0000, 0x2294,0x0000,0x0000, /* 17AE */ +0x2295,0x0000,0x0000, 0x2296,0x0000,0x0000, 0x2297,0x0000,0x0000, /* 17B1 */ +0x2298,0x0000,0x0000, 0x2299,0x0000,0x0000, 0x229A,0x0000,0x0000, /* 17B4 */ +0x229B,0x0000,0x0000, 0x229C,0x0000,0x0000, 0x229D,0x0000,0x0000, /* 17B7 */ +0x229E,0x0000,0x0000, 0x229F,0x0000,0x0000, 0x22A0,0x0000,0x0000, /* 17BA */ +0x22A1,0x0000,0x0000, 0x22A2,0x0000,0x0000, 0x22A3,0x0000,0x0000, /* 17BD */ +0x22A4,0x0000,0x0000, 0x22A5,0x0000,0x0000, 0x22A6,0x0000,0x0000, /* 17C0 */ +0x22A7,0x0000,0x0000, 0x22A8,0x0000,0x0000, 0x22A9,0x0000,0x0000, /* 17C3 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 17C6 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 17C9 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 17CC */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 17CF */ +0x22AA,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x02A1,0x0000,0x0000, /* 17D2 */ +0x02A2,0x0000,0x0000, 0x0267,0x0000,0x0000, 0x03CB,0x0000,0x0000, /* 17D5 */ +0x03CC,0x0000,0x0000, 0x03CD,0x0000,0x0000, 0x03CE,0x0000,0x0000, /* 17D8 */ +0x11EC,0x0000,0x0000, 0x2286,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 17DB */ +0xFBC0,0x97DE,0x0000, 0xFBC0,0x97DF,0x0000, 0x1205,0x0000,0x0000, /* 17DE */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 17E1 */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 17E4 */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 17E7 */ +0xFBC0,0x97EA,0x0000, 0xFBC0,0x97EB,0x0000, 0xFBC0,0x97EC,0x0000, /* 17EA */ +0xFBC0,0x97ED,0x0000, 0xFBC0,0x97EE,0x0000, 0xFBC0,0x97EF,0x0000, /* 17ED */ +0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 17F0 */ +0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, /* 17F3 */ +0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, /* 17F6 */ +0x120E,0x0000,0x0000, 0xFBC0,0x97FA,0x0000, 0xFBC0,0x97FB,0x0000, /* 17F9 */ +0xFBC0,0x97FC,0x0000, 0xFBC0,0x97FD,0x0000, 0xFBC0,0x97FE,0x0000, /* 17FC */ +0xFBC0,0x97FF,0x0000 }; + +uint16 uca520_p018[]= { /* 1800 (3 weights per char) */ +0x039F,0x0000,0x0000, 0x0282,0x0000,0x0000, 0x023B,0x0000,0x0000, /* 1800 */ +0x0287,0x0000,0x0000, 0x0264,0x0000,0x0000, 0x0265,0x0000,0x0000, /* 1803 */ +0x0227,0x0000,0x0000, 0x0228,0x0000,0x0000, 0x023C,0x0000,0x0000, /* 1806 */ +0x0288,0x0000,0x0000, 0x03A0,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1809 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0207,0x0000,0x0000, /* 180C */ +0xFBC0,0x980F,0x0000, 0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, /* 180F */ +0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, /* 1812 */ +0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, /* 1815 */ +0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, 0xFBC0,0x981A,0x0000, /* 1818 */ +0xFBC0,0x981B,0x0000, 0xFBC0,0x981C,0x0000, 0xFBC0,0x981D,0x0000, /* 181B */ +0xFBC0,0x981E,0x0000, 0xFBC0,0x981F,0x0000, 0x242F,0x0000,0x0000, /* 181E */ +0x2431,0x0000,0x0000, 0x2434,0x0000,0x0000, 0x243A,0x0000,0x0000, /* 1821 */ +0x243C,0x0000,0x0000, 0x243F,0x0000,0x0000, 0x2441,0x0000,0x0000, /* 1824 */ +0x2444,0x0000,0x0000, 0x2445,0x0000,0x0000, 0x2446,0x0000,0x0000, /* 1827 */ +0x244B,0x0000,0x0000, 0x244D,0x0000,0x0000, 0x2450,0x0000,0x0000, /* 182A */ +0x2452,0x0000,0x0000, 0x2457,0x0000,0x0000, 0x2459,0x0000,0x0000, /* 182D */ +0x245A,0x0000,0x0000, 0x245B,0x0000,0x0000, 0x2462,0x0000,0x0000, /* 1830 */ +0x2465,0x0000,0x0000, 0x2468,0x0000,0x0000, 0x246D,0x0000,0x0000, /* 1833 */ +0x2471,0x0000,0x0000, 0x2474,0x0000,0x0000, 0x2476,0x0000,0x0000, /* 1836 */ +0x2478,0x0000,0x0000, 0x247B,0x0000,0x0000, 0x2480,0x0000,0x0000, /* 1839 */ +0x2481,0x0000,0x0000, 0x2484,0x0000,0x0000, 0x2488,0x0000,0x0000, /* 183C */ +0x248B,0x0000,0x0000, 0x248C,0x0000,0x0000, 0x248D,0x0000,0x0000, /* 183F */ +0x248E,0x0000,0x0000, 0x242E,0x0000,0x0000, 0x2432,0x0000,0x0000, /* 1842 */ +0x2435,0x0000,0x0000, 0x243B,0x0000,0x0000, 0x243D,0x0000,0x0000, /* 1845 */ +0x2440,0x0000,0x0000, 0x2442,0x0000,0x0000, 0x2447,0x0000,0x0000, /* 1848 */ +0x244C,0x0000,0x0000, 0x244E,0x0000,0x0000, 0x2451,0x0000,0x0000, /* 184B */ +0x2453,0x0000,0x0000, 0x2458,0x0000,0x0000, 0x2463,0x0000,0x0000, /* 184E */ +0x2466,0x0000,0x0000, 0x2469,0x0000,0x0000, 0x246E,0x0000,0x0000, /* 1851 */ +0x2482,0x0000,0x0000, 0x2472,0x0000,0x0000, 0x2477,0x0000,0x0000, /* 1854 */ +0x247C,0x0000,0x0000, 0x2486,0x0000,0x0000, 0x2489,0x0000,0x0000, /* 1857 */ +0x248F,0x0000,0x0000, 0x2490,0x0000,0x0000, 0x246B,0x0000,0x0000, /* 185A */ +0x2433,0x0000,0x0000, 0x2436,0x0000,0x0000, 0x2439,0x0000,0x0000, /* 185D */ +0x2443,0x0000,0x0000, 0x243E,0x0000,0x0000, 0x2448,0x0000,0x0000, /* 1860 */ +0x247D,0x0000,0x0000, 0x2454,0x0000,0x0000, 0x2456,0x0000,0x0000, /* 1863 */ +0x244F,0x0000,0x0000, 0x245C,0x0000,0x0000, 0x2464,0x0000,0x0000, /* 1866 */ +0x2467,0x0000,0x0000, 0x246F,0x0000,0x0000, 0x2479,0x0000,0x0000, /* 1869 */ +0x2487,0x0000,0x0000, 0x248A,0x0000,0x0000, 0x2483,0x0000,0x0000, /* 186C */ +0x2485,0x0000,0x0000, 0x2491,0x0000,0x0000, 0x246A,0x0000,0x0000, /* 186F */ +0x2473,0x0000,0x0000, 0x2437,0x0000,0x0000, 0x247E,0x0000,0x0000, /* 1872 */ +0x2475,0x0000,0x0000, 0x247A,0x0000,0x0000, 0x2470,0x0000,0x0000, /* 1875 */ +0xFBC0,0x9878,0x0000, 0xFBC0,0x9879,0x0000, 0xFBC0,0x987A,0x0000, /* 1878 */ +0xFBC0,0x987B,0x0000, 0xFBC0,0x987C,0x0000, 0xFBC0,0x987D,0x0000, /* 187B */ +0xFBC0,0x987E,0x0000, 0xFBC0,0x987F,0x0000, 0x2427,0x0000,0x0000, /* 187E */ +0x2428,0x0000,0x0000, 0x2429,0x0000,0x0000, 0x242A,0x0000,0x0000, /* 1881 */ +0x242B,0x0000,0x0000, 0x242C,0x0000,0x0000, 0x242D,0x0000,0x0000, /* 1884 */ +0x2430,0x0000,0x0000, 0x2438,0x0000,0x0000, 0x247F,0x0000,0x0000, /* 1887 */ +0x2449,0x0000,0x0000, 0x246C,0x0000,0x0000, 0x2492,0x0000,0x0000, /* 188A */ +0x2494,0x0000,0x0000, 0x2495,0x0000,0x0000, 0x2497,0x0000,0x0000, /* 188D */ +0x2498,0x0000,0x0000, 0x249B,0x0000,0x0000, 0x249D,0x0000,0x0000, /* 1890 */ +0x249E,0x0000,0x0000, 0x24A0,0x0000,0x0000, 0x24A2,0x0000,0x0000, /* 1893 */ +0x24A4,0x0000,0x0000, 0x24A5,0x0000,0x0000, 0x2499,0x0000,0x0000, /* 1896 */ +0x24A3,0x0000,0x0000, 0x2455,0x0000,0x0000, 0x244A,0x0000,0x0000, /* 1899 */ +0x245D,0x0000,0x0000, 0x245E,0x0000,0x0000, 0x2493,0x0000,0x0000, /* 189C */ +0x2496,0x0000,0x0000, 0x249A,0x0000,0x0000, 0x249C,0x0000,0x0000, /* 189F */ +0x245F,0x0000,0x0000, 0x24A1,0x0000,0x0000, 0x2460,0x0000,0x0000, /* 18A2 */ +0x2461,0x0000,0x0000, 0x24A6,0x0000,0x0000, 0x24A7,0x0000,0x0000, /* 18A5 */ +0x249F,0x0000,0x0000, 0x24A9,0x0000,0x0000, 0x24A8,0x0000,0x0000, /* 18A8 */ +0xFBC0,0x98AB,0x0000, 0xFBC0,0x98AC,0x0000, 0xFBC0,0x98AD,0x0000, /* 18AB */ +0xFBC0,0x98AE,0x0000, 0xFBC0,0x98AF,0x0000, 0x27A0,0x0000,0x0000, /* 18AE */ +0x27A1,0x0000,0x0000, 0x27A2,0x0000,0x0000, 0x27A3,0x0000,0x0000, /* 18B1 */ +0x27A4,0x0000,0x0000, 0x27A5,0x0000,0x0000, 0x27A6,0x0000,0x0000, /* 18B4 */ +0x27A7,0x0000,0x0000, 0x27A8,0x0000,0x0000, 0x27A9,0x0000,0x0000, /* 18B7 */ +0x27AA,0x0000,0x0000, 0x27AB,0x0000,0x0000, 0x27AC,0x0000,0x0000, /* 18BA */ +0x27AD,0x0000,0x0000, 0x27AE,0x0000,0x0000, 0x27AF,0x0000,0x0000, /* 18BD */ +0x27B0,0x0000,0x0000, 0x27B1,0x0000,0x0000, 0x27B2,0x0000,0x0000, /* 18C0 */ +0x27B3,0x0000,0x0000, 0x27B4,0x0000,0x0000, 0x27B5,0x0000,0x0000, /* 18C3 */ +0x27B6,0x0000,0x0000, 0x27B7,0x0000,0x0000, 0x27B8,0x0000,0x0000, /* 18C6 */ +0x27B9,0x0000,0x0000, 0x27BA,0x0000,0x0000, 0x27BB,0x0000,0x0000, /* 18C9 */ +0x27BC,0x0000,0x0000, 0x27BD,0x0000,0x0000, 0x27BE,0x0000,0x0000, /* 18CC */ +0x27BF,0x0000,0x0000, 0x27C0,0x0000,0x0000, 0x27C1,0x0000,0x0000, /* 18CF */ +0x27C2,0x0000,0x0000, 0x27C3,0x0000,0x0000, 0x27C4,0x0000,0x0000, /* 18D2 */ +0x27C5,0x0000,0x0000, 0x27C6,0x0000,0x0000, 0x27C7,0x0000,0x0000, /* 18D5 */ +0x27C8,0x0000,0x0000, 0x27C9,0x0000,0x0000, 0x27CA,0x0000,0x0000, /* 18D8 */ +0x27CB,0x0000,0x0000, 0x27CC,0x0000,0x0000, 0x27CD,0x0000,0x0000, /* 18DB */ +0x27CE,0x0000,0x0000, 0x27CF,0x0000,0x0000, 0x27D0,0x0000,0x0000, /* 18DE */ +0x27D1,0x0000,0x0000, 0x27D2,0x0000,0x0000, 0x27D3,0x0000,0x0000, /* 18E1 */ +0x27D4,0x0000,0x0000, 0x27D5,0x0000,0x0000, 0x27D6,0x0000,0x0000, /* 18E4 */ +0x27D7,0x0000,0x0000, 0x27D8,0x0000,0x0000, 0x27D9,0x0000,0x0000, /* 18E7 */ +0x27DA,0x0000,0x0000, 0x27DB,0x0000,0x0000, 0x27DC,0x0000,0x0000, /* 18EA */ +0x27DD,0x0000,0x0000, 0x27DE,0x0000,0x0000, 0x27DF,0x0000,0x0000, /* 18ED */ +0x27E0,0x0000,0x0000, 0x27E1,0x0000,0x0000, 0x27E2,0x0000,0x0000, /* 18F0 */ +0x27E3,0x0000,0x0000, 0x27E4,0x0000,0x0000, 0x27E5,0x0000,0x0000, /* 18F3 */ +0xFBC0,0x98F6,0x0000, 0xFBC0,0x98F7,0x0000, 0xFBC0,0x98F8,0x0000, /* 18F6 */ +0xFBC0,0x98F9,0x0000, 0xFBC0,0x98FA,0x0000, 0xFBC0,0x98FB,0x0000, /* 18F9 */ +0xFBC0,0x98FC,0x0000, 0xFBC0,0x98FD,0x0000, 0xFBC0,0x98FE,0x0000, /* 18FC */ +0xFBC0,0x98FF,0x0000 }; + +uint16 uca520_p019[]= { /* 1900 (4 weights per char) */ +0x20EB,0x0000,0x0000,0x0000, 0x20EC,0x0000,0x0000,0x0000, /* 1900 */ +0x20ED,0x0000,0x0000,0x0000, 0x20EE,0x0000,0x0000,0x0000, /* 1902 */ +0x20EF,0x0000,0x0000,0x0000, 0x20F0,0x0000,0x0000,0x0000, /* 1904 */ +0x20F1,0x0000,0x0000,0x0000, 0x20F2,0x0000,0x0000,0x0000, /* 1906 */ +0x20F3,0x0000,0x0000,0x0000, 0x20F4,0x0000,0x0000,0x0000, /* 1908 */ +0x20F5,0x0000,0x0000,0x0000, 0x20F6,0x0000,0x0000,0x0000, /* 190A */ +0x20F7,0x0000,0x0000,0x0000, 0x20F8,0x0000,0x0000,0x0000, /* 190C */ +0x20F9,0x0000,0x0000,0x0000, 0x20FA,0x0000,0x0000,0x0000, /* 190E */ +0x20FB,0x0000,0x0000,0x0000, 0x20FC,0x0000,0x0000,0x0000, /* 1910 */ +0x20FD,0x0000,0x0000,0x0000, 0x20FE,0x0000,0x0000,0x0000, /* 1912 */ +0x20FF,0x0000,0x0000,0x0000, 0x2100,0x0000,0x0000,0x0000, /* 1914 */ +0x2101,0x0000,0x0000,0x0000, 0x2102,0x0000,0x0000,0x0000, /* 1916 */ +0x2103,0x0000,0x0000,0x0000, 0x2104,0x0000,0x0000,0x0000, /* 1918 */ +0x2105,0x0000,0x0000,0x0000, 0x2106,0x0000,0x0000,0x0000, /* 191A */ +0x2107,0x0000,0x0000,0x0000, 0xFBC0,0x991D,0x0000,0x0000, /* 191C */ +0xFBC0,0x991E,0x0000,0x0000, 0xFBC0,0x991F,0x0000,0x0000, /* 191E */ +0x2108,0x0000,0x0000,0x0000, 0x2109,0x0000,0x0000,0x0000, /* 1920 */ +0x210A,0x0000,0x0000,0x0000, 0x210B,0x0000,0x0000,0x0000, /* 1922 */ +0x210C,0x0000,0x0000,0x0000, 0x210D,0x0000,0x0000,0x0000, /* 1924 */ +0x210E,0x0000,0x0000,0x0000, 0x210F,0x0000,0x0000,0x0000, /* 1926 */ +0x2110,0x0000,0x0000,0x0000, 0x2111,0x0000,0x0000,0x0000, /* 1928 */ +0x2112,0x0000,0x0000,0x0000, 0x2113,0x0000,0x0000,0x0000, /* 192A */ +0xFBC0,0x992C,0x0000,0x0000, 0xFBC0,0x992D,0x0000,0x0000, /* 192C */ +0xFBC0,0x992E,0x0000,0x0000, 0xFBC0,0x992F,0x0000,0x0000, /* 192E */ +0x2114,0x0000,0x0000,0x0000, 0x2115,0x0000,0x0000,0x0000, /* 1930 */ +0x2116,0x0000,0x0000,0x0000, 0x2117,0x0000,0x0000,0x0000, /* 1932 */ +0x2118,0x0000,0x0000,0x0000, 0x2119,0x0000,0x0000,0x0000, /* 1934 */ +0x211A,0x0000,0x0000,0x0000, 0x211B,0x0000,0x0000,0x0000, /* 1936 */ +0x211C,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 1938 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 193A */ +0xFBC0,0x993C,0x0000,0x0000, 0xFBC0,0x993D,0x0000,0x0000, /* 193C */ +0xFBC0,0x993E,0x0000,0x0000, 0xFBC0,0x993F,0x0000,0x0000, /* 193E */ +0x03C1,0x0000,0x0000,0x0000, 0xFBC0,0x9941,0x0000,0x0000, /* 1940 */ +0xFBC0,0x9942,0x0000,0x0000, 0xFBC0,0x9943,0x0000,0x0000, /* 1942 */ +0x0272,0x0000,0x0000,0x0000, 0x027A,0x0000,0x0000,0x0000, /* 1944 */ +0x1205,0x0000,0x0000,0x0000, 0x1206,0x0000,0x0000,0x0000, /* 1946 */ +0x1207,0x0000,0x0000,0x0000, 0x1208,0x0000,0x0000,0x0000, /* 1948 */ +0x1209,0x0000,0x0000,0x0000, 0x120A,0x0000,0x0000,0x0000, /* 194A */ +0x120B,0x0000,0x0000,0x0000, 0x120C,0x0000,0x0000,0x0000, /* 194C */ +0x120D,0x0000,0x0000,0x0000, 0x120E,0x0000,0x0000,0x0000, /* 194E */ +0x22AB,0x0000,0x0000,0x0000, 0x22AC,0x0000,0x0000,0x0000, /* 1950 */ +0x22AD,0x0000,0x0000,0x0000, 0x22AE,0x0000,0x0000,0x0000, /* 1952 */ +0x22AF,0x0000,0x0000,0x0000, 0x22B0,0x0000,0x0000,0x0000, /* 1954 */ +0x22B1,0x0000,0x0000,0x0000, 0x22B2,0x0000,0x0000,0x0000, /* 1956 */ +0x22B3,0x0000,0x0000,0x0000, 0x22B4,0x0000,0x0000,0x0000, /* 1958 */ +0x22B5,0x0000,0x0000,0x0000, 0x22B6,0x0000,0x0000,0x0000, /* 195A */ +0x22B7,0x0000,0x0000,0x0000, 0x22B8,0x0000,0x0000,0x0000, /* 195C */ +0x22B9,0x0000,0x0000,0x0000, 0x22BA,0x0000,0x0000,0x0000, /* 195E */ +0x22BB,0x0000,0x0000,0x0000, 0x22BC,0x0000,0x0000,0x0000, /* 1960 */ +0x22BD,0x0000,0x0000,0x0000, 0x22BE,0x0000,0x0000,0x0000, /* 1962 */ +0x22BF,0x0000,0x0000,0x0000, 0x22C0,0x0000,0x0000,0x0000, /* 1964 */ +0x22C1,0x0000,0x0000,0x0000, 0x22C2,0x0000,0x0000,0x0000, /* 1966 */ +0x22C3,0x0000,0x0000,0x0000, 0x22C4,0x0000,0x0000,0x0000, /* 1968 */ +0x22C5,0x0000,0x0000,0x0000, 0x22C6,0x0000,0x0000,0x0000, /* 196A */ +0x22C7,0x0000,0x0000,0x0000, 0x22C8,0x0000,0x0000,0x0000, /* 196C */ +0xFBC0,0x996E,0x0000,0x0000, 0xFBC0,0x996F,0x0000,0x0000, /* 196E */ +0x22C9,0x0000,0x0000,0x0000, 0x22CA,0x0000,0x0000,0x0000, /* 1970 */ +0x22CB,0x0000,0x0000,0x0000, 0x22CC,0x0000,0x0000,0x0000, /* 1972 */ +0x22CD,0x0000,0x0000,0x0000, 0xFBC0,0x9975,0x0000,0x0000, /* 1974 */ +0xFBC0,0x9976,0x0000,0x0000, 0xFBC0,0x9977,0x0000,0x0000, /* 1976 */ +0xFBC0,0x9978,0x0000,0x0000, 0xFBC0,0x9979,0x0000,0x0000, /* 1978 */ +0xFBC0,0x997A,0x0000,0x0000, 0xFBC0,0x997B,0x0000,0x0000, /* 197A */ +0xFBC0,0x997C,0x0000,0x0000, 0xFBC0,0x997D,0x0000,0x0000, /* 197C */ +0xFBC0,0x997E,0x0000,0x0000, 0xFBC0,0x997F,0x0000,0x0000, /* 197E */ +0x22CE,0x0000,0x0000,0x0000, 0x22CF,0x0000,0x0000,0x0000, /* 1980 */ +0x22D0,0x0000,0x0000,0x0000, 0x22D1,0x0000,0x0000,0x0000, /* 1982 */ +0x22D2,0x0000,0x0000,0x0000, 0x22D3,0x0000,0x0000,0x0000, /* 1984 */ +0x22D4,0x0000,0x0000,0x0000, 0x22D5,0x0000,0x0000,0x0000, /* 1986 */ +0x22D6,0x0000,0x0000,0x0000, 0x22D7,0x0000,0x0000,0x0000, /* 1988 */ +0x22D8,0x0000,0x0000,0x0000, 0x22D9,0x0000,0x0000,0x0000, /* 198A */ +0x22DA,0x0000,0x0000,0x0000, 0x22DB,0x0000,0x0000,0x0000, /* 198C */ +0x22DC,0x0000,0x0000,0x0000, 0x22DD,0x0000,0x0000,0x0000, /* 198E */ +0x22DE,0x0000,0x0000,0x0000, 0x22DF,0x0000,0x0000,0x0000, /* 1990 */ +0x22E0,0x0000,0x0000,0x0000, 0x22E1,0x0000,0x0000,0x0000, /* 1992 */ +0x22E2,0x0000,0x0000,0x0000, 0x22E3,0x0000,0x0000,0x0000, /* 1994 */ +0x22E4,0x0000,0x0000,0x0000, 0x22E5,0x0000,0x0000,0x0000, /* 1996 */ +0x22E6,0x0000,0x0000,0x0000, 0x22E7,0x0000,0x0000,0x0000, /* 1998 */ +0x22E8,0x0000,0x0000,0x0000, 0x22E9,0x0000,0x0000,0x0000, /* 199A */ +0x22EA,0x0000,0x0000,0x0000, 0x22EB,0x0000,0x0000,0x0000, /* 199C */ +0x22EC,0x0000,0x0000,0x0000, 0x22ED,0x0000,0x0000,0x0000, /* 199E */ +0x22EE,0x0000,0x0000,0x0000, 0x22EF,0x0000,0x0000,0x0000, /* 19A0 */ +0x22F0,0x0000,0x0000,0x0000, 0x22F1,0x0000,0x0000,0x0000, /* 19A2 */ +0x22F2,0x0000,0x0000,0x0000, 0x22F3,0x0000,0x0000,0x0000, /* 19A4 */ +0x22F4,0x0000,0x0000,0x0000, 0x22F5,0x0000,0x0000,0x0000, /* 19A6 */ +0x22F6,0x0000,0x0000,0x0000, 0x22F7,0x0000,0x0000,0x0000, /* 19A8 */ +0x22F8,0x0000,0x0000,0x0000, 0x22F9,0x0000,0x0000,0x0000, /* 19AA */ +0xFBC0,0x99AC,0x0000,0x0000, 0xFBC0,0x99AD,0x0000,0x0000, /* 19AC */ +0xFBC0,0x99AE,0x0000,0x0000, 0xFBC0,0x99AF,0x0000,0x0000, /* 19AE */ +0x22FA,0x0000,0x0000,0x0000, 0x22FB,0x0000,0x0000,0x0000, /* 19B0 */ +0x22FC,0x0000,0x0000,0x0000, 0x22FD,0x0000,0x0000,0x0000, /* 19B2 */ +0x22FE,0x0000,0x0000,0x0000, 0x22FF,0x0000,0x0000,0x0000, /* 19B4 */ +0x2300,0x0000,0x0000,0x0000, 0x2301,0x0000,0x0000,0x0000, /* 19B6 */ +0x2302,0x0000,0x0000,0x0000, 0x2303,0x0000,0x0000,0x0000, /* 19B8 */ +0x2304,0x0000,0x0000,0x0000, 0x2305,0x0000,0x0000,0x0000, /* 19BA */ +0x2306,0x0000,0x0000,0x0000, 0x2307,0x0000,0x0000,0x0000, /* 19BC */ +0x2308,0x0000,0x0000,0x0000, 0x2309,0x0000,0x0000,0x0000, /* 19BE */ +0x230A,0x0000,0x0000,0x0000, 0x230B,0x0000,0x0000,0x0000, /* 19C0 */ +0x230C,0x0000,0x0000,0x0000, 0x230D,0x0000,0x0000,0x0000, /* 19C2 */ +0x230E,0x0000,0x0000,0x0000, 0x230F,0x0000,0x0000,0x0000, /* 19C4 */ +0x2310,0x0000,0x0000,0x0000, 0x2311,0x0000,0x0000,0x0000, /* 19C6 */ +0x2312,0x0000,0x0000,0x0000, 0x2313,0x0000,0x0000,0x0000, /* 19C8 */ +0xFBC0,0x99CA,0x0000,0x0000, 0xFBC0,0x99CB,0x0000,0x0000, /* 19CA */ +0xFBC0,0x99CC,0x0000,0x0000, 0xFBC0,0x99CD,0x0000,0x0000, /* 19CC */ +0xFBC0,0x99CE,0x0000,0x0000, 0xFBC0,0x99CF,0x0000,0x0000, /* 19CE */ +0x1205,0x0000,0x0000,0x0000, 0x1206,0x0000,0x0000,0x0000, /* 19D0 */ +0x1207,0x0000,0x0000,0x0000, 0x1208,0x0000,0x0000,0x0000, /* 19D2 */ +0x1209,0x0000,0x0000,0x0000, 0x120A,0x0000,0x0000,0x0000, /* 19D4 */ +0x120B,0x0000,0x0000,0x0000, 0x120C,0x0000,0x0000,0x0000, /* 19D6 */ +0x120D,0x0000,0x0000,0x0000, 0x120E,0x0000,0x0000,0x0000, /* 19D8 */ +0x1206,0x0000,0x0000,0x0000, 0xFBC0,0x99DB,0x0000,0x0000, /* 19DA */ +0xFBC0,0x99DC,0x0000,0x0000, 0xFBC0,0x99DD,0x0000,0x0000, /* 19DC */ +0x22EA,0x2300,0x0000,0x0000, 0x22EA,0x2300,0x230B,0x0000, /* 19DE */ +0x048E,0x0000,0x0000,0x0000, 0x048F,0x0000,0x0000,0x0000, /* 19E0 */ +0x0490,0x0000,0x0000,0x0000, 0x0491,0x0000,0x0000,0x0000, /* 19E2 */ +0x0492,0x0000,0x0000,0x0000, 0x0493,0x0000,0x0000,0x0000, /* 19E4 */ +0x0494,0x0000,0x0000,0x0000, 0x0495,0x0000,0x0000,0x0000, /* 19E6 */ +0x0496,0x0000,0x0000,0x0000, 0x0497,0x0000,0x0000,0x0000, /* 19E8 */ +0x0498,0x0000,0x0000,0x0000, 0x0499,0x0000,0x0000,0x0000, /* 19EA */ +0x049A,0x0000,0x0000,0x0000, 0x049B,0x0000,0x0000,0x0000, /* 19EC */ +0x049C,0x0000,0x0000,0x0000, 0x049D,0x0000,0x0000,0x0000, /* 19EE */ +0x049E,0x0000,0x0000,0x0000, 0x049F,0x0000,0x0000,0x0000, /* 19F0 */ +0x04A0,0x0000,0x0000,0x0000, 0x04A1,0x0000,0x0000,0x0000, /* 19F2 */ +0x04A2,0x0000,0x0000,0x0000, 0x04A3,0x0000,0x0000,0x0000, /* 19F4 */ +0x04A4,0x0000,0x0000,0x0000, 0x04A5,0x0000,0x0000,0x0000, /* 19F6 */ +0x04A6,0x0000,0x0000,0x0000, 0x04A7,0x0000,0x0000,0x0000, /* 19F8 */ +0x04A8,0x0000,0x0000,0x0000, 0x04A9,0x0000,0x0000,0x0000, /* 19FA */ +0x04AA,0x0000,0x0000,0x0000, 0x04AB,0x0000,0x0000,0x0000, /* 19FC */ +0x04AC,0x0000,0x0000,0x0000, 0x04AD,0x0000,0x0000,0x0000 /* 19FE */ +}; + +uint16 uca520_p01A[]= { /* 1A00 (4 weights per char) */ +0x216C,0x0000,0x0000,0x0000, 0x216D,0x0000,0x0000,0x0000, /* 1A00 */ +0x216E,0x0000,0x0000,0x0000, 0x216F,0x0000,0x0000,0x0000, /* 1A02 */ +0x2170,0x0000,0x0000,0x0000, 0x2171,0x0000,0x0000,0x0000, /* 1A04 */ +0x2172,0x0000,0x0000,0x0000, 0x2173,0x0000,0x0000,0x0000, /* 1A06 */ +0x2174,0x0000,0x0000,0x0000, 0x2175,0x0000,0x0000,0x0000, /* 1A08 */ +0x2176,0x0000,0x0000,0x0000, 0x2177,0x0000,0x0000,0x0000, /* 1A0A */ +0x2178,0x0000,0x0000,0x0000, 0x2179,0x0000,0x0000,0x0000, /* 1A0C */ +0x217A,0x0000,0x0000,0x0000, 0x217B,0x0000,0x0000,0x0000, /* 1A0E */ +0x217C,0x0000,0x0000,0x0000, 0x217D,0x0000,0x0000,0x0000, /* 1A10 */ +0x217E,0x0000,0x0000,0x0000, 0x217F,0x0000,0x0000,0x0000, /* 1A12 */ +0x2180,0x0000,0x0000,0x0000, 0x2181,0x0000,0x0000,0x0000, /* 1A14 */ +0x2182,0x0000,0x0000,0x0000, 0x2183,0x0000,0x0000,0x0000, /* 1A16 */ +0x2184,0x0000,0x0000,0x0000, 0x2185,0x0000,0x0000,0x0000, /* 1A18 */ +0x2186,0x0000,0x0000,0x0000, 0x2187,0x0000,0x0000,0x0000, /* 1A1A */ +0xFBC0,0x9A1C,0x0000,0x0000, 0xFBC0,0x9A1D,0x0000,0x0000, /* 1A1C */ +0x02BA,0x0000,0x0000,0x0000, 0x02BB,0x0000,0x0000,0x0000, /* 1A1E */ +0x2314,0x0000,0x0000,0x0000, 0x2315,0x0000,0x0000,0x0000, /* 1A20 */ +0x2316,0x0000,0x0000,0x0000, 0x2317,0x0000,0x0000,0x0000, /* 1A22 */ +0x2318,0x0000,0x0000,0x0000, 0x2319,0x0000,0x0000,0x0000, /* 1A24 */ +0x231A,0x0000,0x0000,0x0000, 0x231B,0x0000,0x0000,0x0000, /* 1A26 */ +0x231C,0x0000,0x0000,0x0000, 0x231D,0x0000,0x0000,0x0000, /* 1A28 */ +0x231E,0x0000,0x0000,0x0000, 0x231F,0x0000,0x0000,0x0000, /* 1A2A */ +0x2320,0x0000,0x0000,0x0000, 0x2321,0x0000,0x0000,0x0000, /* 1A2C */ +0x2322,0x0000,0x0000,0x0000, 0x2323,0x0000,0x0000,0x0000, /* 1A2E */ +0x2324,0x0000,0x0000,0x0000, 0x2325,0x0000,0x0000,0x0000, /* 1A30 */ +0x2326,0x0000,0x0000,0x0000, 0x2327,0x0000,0x0000,0x0000, /* 1A32 */ +0x2328,0x0000,0x0000,0x0000, 0x2329,0x0000,0x0000,0x0000, /* 1A34 */ +0x232A,0x0000,0x0000,0x0000, 0x232B,0x0000,0x0000,0x0000, /* 1A36 */ +0x232C,0x0000,0x0000,0x0000, 0x232D,0x0000,0x0000,0x0000, /* 1A38 */ +0x232E,0x0000,0x0000,0x0000, 0x232F,0x0000,0x0000,0x0000, /* 1A3A */ +0x2330,0x0000,0x0000,0x0000, 0x2331,0x0000,0x0000,0x0000, /* 1A3C */ +0x2332,0x0000,0x0000,0x0000, 0x2333,0x0000,0x0000,0x0000, /* 1A3E */ +0x2334,0x0000,0x0000,0x0000, 0x2335,0x0000,0x0000,0x0000, /* 1A40 */ +0x2336,0x0000,0x0000,0x0000, 0x2337,0x0000,0x0000,0x0000, /* 1A42 */ +0x2338,0x0000,0x0000,0x0000, 0x2339,0x0000,0x0000,0x0000, /* 1A44 */ +0x233A,0x0000,0x0000,0x0000, 0x233B,0x0000,0x0000,0x0000, /* 1A46 */ +0x233C,0x0000,0x0000,0x0000, 0x233D,0x0000,0x0000,0x0000, /* 1A48 */ +0x233E,0x0000,0x0000,0x0000, 0x233F,0x0000,0x0000,0x0000, /* 1A4A */ +0x2340,0x0000,0x0000,0x0000, 0x2349,0x0000,0x0000,0x0000, /* 1A4C */ +0x234A,0x0000,0x0000,0x0000, 0x234B,0x0000,0x0000,0x0000, /* 1A4E */ +0x234C,0x0000,0x0000,0x0000, 0x234D,0x0000,0x0000,0x0000, /* 1A50 */ +0x234E,0x0000,0x0000,0x0000, 0x2341,0x0000,0x0000,0x0000, /* 1A52 */ +0x233A,0x2360,0x233A,0x0000, 0x2343,0x0000,0x0000,0x0000, /* 1A54 */ +0x2344,0x0000,0x0000,0x0000, 0x2345,0x0000,0x0000,0x0000, /* 1A56 */ +0x231A,0x0000,0x0000,0x0000, 0x231A,0x0000,0x0000,0x0000, /* 1A58 */ +0x232F,0x0000,0x0000,0x0000, 0x232F,0x0000,0x0000,0x0000, /* 1A5A */ +0x2346,0x0000,0x0000,0x0000, 0x2347,0x0000,0x0000,0x0000, /* 1A5C */ +0x2348,0x0000,0x0000,0x0000, 0xFBC0,0x9A5F,0x0000,0x0000, /* 1A5E */ +0x2360,0x0000,0x0000,0x0000, 0x234F,0x0000,0x0000,0x0000, /* 1A60 */ +0x2351,0x0000,0x0000,0x0000, 0x2352,0x0000,0x0000,0x0000, /* 1A62 */ +0x2352,0x0000,0x0000,0x0000, 0x2353,0x0000,0x0000,0x0000, /* 1A64 */ +0x2354,0x0000,0x0000,0x0000, 0x2355,0x0000,0x0000,0x0000, /* 1A66 */ +0x2356,0x0000,0x0000,0x0000, 0x2357,0x0000,0x0000,0x0000, /* 1A68 */ +0x2358,0x0000,0x0000,0x0000, 0x2342,0x0000,0x0000,0x0000, /* 1A6A */ +0x2350,0x0000,0x0000,0x0000, 0x235F,0x0000,0x0000,0x0000, /* 1A6C */ +0x2359,0x0000,0x0000,0x0000, 0x235A,0x0000,0x0000,0x0000, /* 1A6E */ +0x235C,0x0000,0x0000,0x0000, 0x235D,0x0000,0x0000,0x0000, /* 1A70 */ +0x235E,0x0000,0x0000,0x0000, 0x235B,0x0000,0x0000,0x0000, /* 1A72 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 1A74 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 1A76 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 1A78 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 1A7A */ +0x0000,0x0000,0x0000,0x0000, 0xFBC0,0x9A7D,0x0000,0x0000, /* 1A7C */ +0xFBC0,0x9A7E,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 1A7E */ +0x1205,0x0000,0x0000,0x0000, 0x1206,0x0000,0x0000,0x0000, /* 1A80 */ +0x1207,0x0000,0x0000,0x0000, 0x1208,0x0000,0x0000,0x0000, /* 1A82 */ +0x1209,0x0000,0x0000,0x0000, 0x120A,0x0000,0x0000,0x0000, /* 1A84 */ +0x120B,0x0000,0x0000,0x0000, 0x120C,0x0000,0x0000,0x0000, /* 1A86 */ +0x120D,0x0000,0x0000,0x0000, 0x120E,0x0000,0x0000,0x0000, /* 1A88 */ +0xFBC0,0x9A8A,0x0000,0x0000, 0xFBC0,0x9A8B,0x0000,0x0000, /* 1A8A */ +0xFBC0,0x9A8C,0x0000,0x0000, 0xFBC0,0x9A8D,0x0000,0x0000, /* 1A8C */ +0xFBC0,0x9A8E,0x0000,0x0000, 0xFBC0,0x9A8F,0x0000,0x0000, /* 1A8E */ +0x1205,0x0000,0x0000,0x0000, 0x1206,0x0000,0x0000,0x0000, /* 1A90 */ +0x1207,0x0000,0x0000,0x0000, 0x1208,0x0000,0x0000,0x0000, /* 1A92 */ +0x1209,0x0000,0x0000,0x0000, 0x120A,0x0000,0x0000,0x0000, /* 1A94 */ +0x120B,0x0000,0x0000,0x0000, 0x120C,0x0000,0x0000,0x0000, /* 1A96 */ +0x120D,0x0000,0x0000,0x0000, 0x120E,0x0000,0x0000,0x0000, /* 1A98 */ +0xFBC0,0x9A9A,0x0000,0x0000, 0xFBC0,0x9A9B,0x0000,0x0000, /* 1A9A */ +0xFBC0,0x9A9C,0x0000,0x0000, 0xFBC0,0x9A9D,0x0000,0x0000, /* 1A9C */ +0xFBC0,0x9A9E,0x0000,0x0000, 0xFBC0,0x9A9F,0x0000,0x0000, /* 1A9E */ +0x03CF,0x0000,0x0000,0x0000, 0x03D0,0x0000,0x0000,0x0000, /* 1AA0 */ +0x03D1,0x0000,0x0000,0x0000, 0x03D2,0x0000,0x0000,0x0000, /* 1AA2 */ +0x03D3,0x0000,0x0000,0x0000, 0x03D4,0x0000,0x0000,0x0000, /* 1AA4 */ +0x03D5,0x0000,0x0000,0x0000, 0x11D3,0x0000,0x0000,0x0000, /* 1AA6 */ +0x02A3,0x0000,0x0000,0x0000, 0x02A4,0x0000,0x0000,0x0000, /* 1AA8 */ +0x02A5,0x0000,0x0000,0x0000, 0x02A6,0x0000,0x0000,0x0000, /* 1AAA */ +0x03D6,0x0000,0x0000,0x0000, 0x03D7,0x0000,0x0000,0x0000, /* 1AAC */ +0xFBC0,0x9AAE,0x0000,0x0000, 0xFBC0,0x9AAF,0x0000,0x0000, /* 1AAE */ +0xFBC0,0x9AB0,0x0000,0x0000, 0xFBC0,0x9AB1,0x0000,0x0000, /* 1AB0 */ +0xFBC0,0x9AB2,0x0000,0x0000, 0xFBC0,0x9AB3,0x0000,0x0000, /* 1AB2 */ +0xFBC0,0x9AB4,0x0000,0x0000, 0xFBC0,0x9AB5,0x0000,0x0000, /* 1AB4 */ +0xFBC0,0x9AB6,0x0000,0x0000, 0xFBC0,0x9AB7,0x0000,0x0000, /* 1AB6 */ +0xFBC0,0x9AB8,0x0000,0x0000, 0xFBC0,0x9AB9,0x0000,0x0000, /* 1AB8 */ +0xFBC0,0x9ABA,0x0000,0x0000, 0xFBC0,0x9ABB,0x0000,0x0000, /* 1ABA */ +0xFBC0,0x9ABC,0x0000,0x0000, 0xFBC0,0x9ABD,0x0000,0x0000, /* 1ABC */ +0xFBC0,0x9ABE,0x0000,0x0000, 0xFBC0,0x9ABF,0x0000,0x0000, /* 1ABE */ +0xFBC0,0x9AC0,0x0000,0x0000, 0xFBC0,0x9AC1,0x0000,0x0000, /* 1AC0 */ +0xFBC0,0x9AC2,0x0000,0x0000, 0xFBC0,0x9AC3,0x0000,0x0000, /* 1AC2 */ +0xFBC0,0x9AC4,0x0000,0x0000, 0xFBC0,0x9AC5,0x0000,0x0000, /* 1AC4 */ +0xFBC0,0x9AC6,0x0000,0x0000, 0xFBC0,0x9AC7,0x0000,0x0000, /* 1AC6 */ +0xFBC0,0x9AC8,0x0000,0x0000, 0xFBC0,0x9AC9,0x0000,0x0000, /* 1AC8 */ +0xFBC0,0x9ACA,0x0000,0x0000, 0xFBC0,0x9ACB,0x0000,0x0000, /* 1ACA */ +0xFBC0,0x9ACC,0x0000,0x0000, 0xFBC0,0x9ACD,0x0000,0x0000, /* 1ACC */ +0xFBC0,0x9ACE,0x0000,0x0000, 0xFBC0,0x9ACF,0x0000,0x0000, /* 1ACE */ +0xFBC0,0x9AD0,0x0000,0x0000, 0xFBC0,0x9AD1,0x0000,0x0000, /* 1AD0 */ +0xFBC0,0x9AD2,0x0000,0x0000, 0xFBC0,0x9AD3,0x0000,0x0000, /* 1AD2 */ +0xFBC0,0x9AD4,0x0000,0x0000, 0xFBC0,0x9AD5,0x0000,0x0000, /* 1AD4 */ +0xFBC0,0x9AD6,0x0000,0x0000, 0xFBC0,0x9AD7,0x0000,0x0000, /* 1AD6 */ +0xFBC0,0x9AD8,0x0000,0x0000, 0xFBC0,0x9AD9,0x0000,0x0000, /* 1AD8 */ +0xFBC0,0x9ADA,0x0000,0x0000, 0xFBC0,0x9ADB,0x0000,0x0000, /* 1ADA */ +0xFBC0,0x9ADC,0x0000,0x0000, 0xFBC0,0x9ADD,0x0000,0x0000, /* 1ADC */ +0xFBC0,0x9ADE,0x0000,0x0000, 0xFBC0,0x9ADF,0x0000,0x0000, /* 1ADE */ +0xFBC0,0x9AE0,0x0000,0x0000, 0xFBC0,0x9AE1,0x0000,0x0000, /* 1AE0 */ +0xFBC0,0x9AE2,0x0000,0x0000, 0xFBC0,0x9AE3,0x0000,0x0000, /* 1AE2 */ +0xFBC0,0x9AE4,0x0000,0x0000, 0xFBC0,0x9AE5,0x0000,0x0000, /* 1AE4 */ +0xFBC0,0x9AE6,0x0000,0x0000, 0xFBC0,0x9AE7,0x0000,0x0000, /* 1AE6 */ +0xFBC0,0x9AE8,0x0000,0x0000, 0xFBC0,0x9AE9,0x0000,0x0000, /* 1AE8 */ +0xFBC0,0x9AEA,0x0000,0x0000, 0xFBC0,0x9AEB,0x0000,0x0000, /* 1AEA */ +0xFBC0,0x9AEC,0x0000,0x0000, 0xFBC0,0x9AED,0x0000,0x0000, /* 1AEC */ +0xFBC0,0x9AEE,0x0000,0x0000, 0xFBC0,0x9AEF,0x0000,0x0000, /* 1AEE */ +0xFBC0,0x9AF0,0x0000,0x0000, 0xFBC0,0x9AF1,0x0000,0x0000, /* 1AF0 */ +0xFBC0,0x9AF2,0x0000,0x0000, 0xFBC0,0x9AF3,0x0000,0x0000, /* 1AF2 */ +0xFBC0,0x9AF4,0x0000,0x0000, 0xFBC0,0x9AF5,0x0000,0x0000, /* 1AF4 */ +0xFBC0,0x9AF6,0x0000,0x0000, 0xFBC0,0x9AF7,0x0000,0x0000, /* 1AF6 */ +0xFBC0,0x9AF8,0x0000,0x0000, 0xFBC0,0x9AF9,0x0000,0x0000, /* 1AF8 */ +0xFBC0,0x9AFA,0x0000,0x0000, 0xFBC0,0x9AFB,0x0000,0x0000, /* 1AFA */ +0xFBC0,0x9AFC,0x0000,0x0000, 0xFBC0,0x9AFD,0x0000,0x0000, /* 1AFC */ +0xFBC0,0x9AFE,0x0000,0x0000, 0xFBC0,0x9AFF,0x0000,0x0000 /* 1AFE */ +}; + +uint16 uca520_p01B[]= { /* 1B00 (3 weights per char) */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1B00 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x23A6,0x0000,0x0000, /* 1B03 */ +0x23A7,0x0000,0x0000, 0x23A8,0x0000,0x0000, 0x23A9,0x0000,0x0000, /* 1B06 */ +0x23AA,0x0000,0x0000, 0x23AB,0x0000,0x0000, 0x23AC,0x0000,0x0000, /* 1B09 */ +0x23AD,0x0000,0x0000, 0x23AE,0x0000,0x0000, 0x23AF,0x0000,0x0000, /* 1B0C */ +0x23B0,0x0000,0x0000, 0x23B1,0x0000,0x0000, 0x23B2,0x0000,0x0000, /* 1B0F */ +0x23B3,0x0000,0x0000, 0x23B4,0x0000,0x0000, 0x23B7,0x0000,0x0000, /* 1B12 */ +0x23B8,0x0000,0x0000, 0x23B9,0x0000,0x0000, 0x23BA,0x0000,0x0000, /* 1B15 */ +0x23BB,0x0000,0x0000, 0x23BC,0x0000,0x0000, 0x23BD,0x0000,0x0000, /* 1B18 */ +0x23BE,0x0000,0x0000, 0x23BF,0x0000,0x0000, 0x23C0,0x0000,0x0000, /* 1B1B */ +0x23C1,0x0000,0x0000, 0x23C2,0x0000,0x0000, 0x23C3,0x0000,0x0000, /* 1B1E */ +0x23C4,0x0000,0x0000, 0x23C5,0x0000,0x0000, 0x23C7,0x0000,0x0000, /* 1B21 */ +0x23C8,0x0000,0x0000, 0x23C9,0x0000,0x0000, 0x23CA,0x0000,0x0000, /* 1B24 */ +0x23CB,0x0000,0x0000, 0x23CD,0x0000,0x0000, 0x23CE,0x0000,0x0000, /* 1B27 */ +0x23CF,0x0000,0x0000, 0x23D0,0x0000,0x0000, 0x23D1,0x0000,0x0000, /* 1B2A */ +0x23D2,0x0000,0x0000, 0x23D3,0x0000,0x0000, 0x23D4,0x0000,0x0000, /* 1B2D */ +0x23D6,0x0000,0x0000, 0x23D7,0x0000,0x0000, 0x23D8,0x0000,0x0000, /* 1B30 */ +0x23DB,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x23DC,0x0000,0x0000, /* 1B33 */ +0x23DD,0x0000,0x0000, 0x23DE,0x0000,0x0000, 0x23DF,0x0000,0x0000, /* 1B36 */ +0x23E0,0x0000,0x0000, 0x23E1,0x0000,0x0000, 0x23E2,0x0000,0x0000, /* 1B39 */ +0x23E3,0x0000,0x0000, 0x23E4,0x0000,0x0000, 0x23E5,0x0000,0x0000, /* 1B3C */ +0x23E6,0x0000,0x0000, 0x23E7,0x0000,0x0000, 0x23E8,0x0000,0x0000, /* 1B3F */ +0x23E9,0x0000,0x0000, 0x23EA,0x0000,0x0000, 0x23EB,0x0000,0x0000, /* 1B42 */ +0x23B5,0x0000,0x0000, 0x23B6,0x0000,0x0000, 0x23C6,0x0000,0x0000, /* 1B45 */ +0x23CC,0x0000,0x0000, 0x23D5,0x0000,0x0000, 0x23D9,0x0000,0x0000, /* 1B48 */ +0x23DA,0x0000,0x0000, 0xFBC0,0x9B4C,0x0000, 0xFBC0,0x9B4D,0x0000, /* 1B4B */ +0xFBC0,0x9B4E,0x0000, 0xFBC0,0x9B4F,0x0000, 0x1205,0x0000,0x0000, /* 1B4E */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 1B51 */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 1B54 */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 1B57 */ +0x02BC,0x0000,0x0000, 0x02BD,0x0000,0x0000, 0x028A,0x0000,0x0000, /* 1B5A */ +0x0268,0x0000,0x0000, 0x02A7,0x0000,0x0000, 0x02A8,0x0000,0x0000, /* 1B5D */ +0x0226,0x0000,0x0000, 0x04AE,0x0000,0x0000, 0x04AF,0x0000,0x0000, /* 1B60 */ +0x04B0,0x0000,0x0000, 0x04B1,0x0000,0x0000, 0x04B2,0x0000,0x0000, /* 1B63 */ +0x04B3,0x0000,0x0000, 0x04B4,0x0000,0x0000, 0x04B5,0x0000,0x0000, /* 1B66 */ +0x04B6,0x0000,0x0000, 0x04B7,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1B69 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1B6C */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1B6F */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x04B8,0x0000,0x0000, /* 1B72 */ +0x04B9,0x0000,0x0000, 0x04BA,0x0000,0x0000, 0x04BB,0x0000,0x0000, /* 1B75 */ +0x04BC,0x0000,0x0000, 0x04BD,0x0000,0x0000, 0x04BE,0x0000,0x0000, /* 1B78 */ +0x04BF,0x0000,0x0000, 0x04C0,0x0000,0x0000, 0xFBC0,0x9B7D,0x0000, /* 1B7B */ +0xFBC0,0x9B7E,0x0000, 0xFBC0,0x9B7F,0x0000, 0x0000,0x0000,0x0000, /* 1B7E */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x1F1C,0x0000,0x0000, /* 1B81 */ +0x1F1D,0x0000,0x0000, 0x1F1E,0x0000,0x0000, 0x1F1F,0x0000,0x0000, /* 1B84 */ +0x1F20,0x0000,0x0000, 0x1F21,0x0000,0x0000, 0x1F22,0x0000,0x0000, /* 1B87 */ +0x1F23,0x0000,0x0000, 0x1F25,0x0000,0x0000, 0x1F26,0x0000,0x0000, /* 1B8A */ +0x1F27,0x0000,0x0000, 0x1F28,0x0000,0x0000, 0x1F29,0x0000,0x0000, /* 1B8D */ +0x1F2A,0x0000,0x0000, 0x1F2B,0x0000,0x0000, 0x1F2C,0x0000,0x0000, /* 1B90 */ +0x1F2D,0x0000,0x0000, 0x1F2E,0x0000,0x0000, 0x1F2F,0x0000,0x0000, /* 1B93 */ +0x1F30,0x0000,0x0000, 0x1F31,0x0000,0x0000, 0x1F32,0x0000,0x0000, /* 1B96 */ +0x1F33,0x0000,0x0000, 0x1F34,0x0000,0x0000, 0x1F36,0x0000,0x0000, /* 1B99 */ +0x1F38,0x0000,0x0000, 0x1F3A,0x0000,0x0000, 0x1F3B,0x0000,0x0000, /* 1B9C */ +0x1F3C,0x0000,0x0000, 0x1F3E,0x0000,0x0000, 0x1F35,0x0000,0x0000, /* 1B9F */ +0x1F37,0x0000,0x0000, 0x1F39,0x0000,0x0000, 0x1F3F,0x0000,0x0000, /* 1BA2 */ +0x1F40,0x0000,0x0000, 0x1F41,0x0000,0x0000, 0x1F42,0x0000,0x0000, /* 1BA5 */ +0x1F43,0x0000,0x0000, 0x1F44,0x0000,0x0000, 0x1F45,0x0000,0x0000, /* 1BA8 */ +0xFBC0,0x9BAB,0x0000, 0xFBC0,0x9BAC,0x0000, 0xFBC0,0x9BAD,0x0000, /* 1BAB */ +0x1F24,0x0000,0x0000, 0x1F3D,0x0000,0x0000, 0x1205,0x0000,0x0000, /* 1BAE */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 1BB1 */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 1BB4 */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 1BB7 */ +0xFBC0,0x9BBA,0x0000, 0xFBC0,0x9BBB,0x0000, 0xFBC0,0x9BBC,0x0000, /* 1BBA */ +0xFBC0,0x9BBD,0x0000, 0xFBC0,0x9BBE,0x0000, 0xFBC0,0x9BBF,0x0000, /* 1BBD */ +0xFBC0,0x9BC0,0x0000, 0xFBC0,0x9BC1,0x0000, 0xFBC0,0x9BC2,0x0000, /* 1BC0 */ +0xFBC0,0x9BC3,0x0000, 0xFBC0,0x9BC4,0x0000, 0xFBC0,0x9BC5,0x0000, /* 1BC3 */ +0xFBC0,0x9BC6,0x0000, 0xFBC0,0x9BC7,0x0000, 0xFBC0,0x9BC8,0x0000, /* 1BC6 */ +0xFBC0,0x9BC9,0x0000, 0xFBC0,0x9BCA,0x0000, 0xFBC0,0x9BCB,0x0000, /* 1BC9 */ +0xFBC0,0x9BCC,0x0000, 0xFBC0,0x9BCD,0x0000, 0xFBC0,0x9BCE,0x0000, /* 1BCC */ +0xFBC0,0x9BCF,0x0000, 0xFBC0,0x9BD0,0x0000, 0xFBC0,0x9BD1,0x0000, /* 1BCF */ +0xFBC0,0x9BD2,0x0000, 0xFBC0,0x9BD3,0x0000, 0xFBC0,0x9BD4,0x0000, /* 1BD2 */ +0xFBC0,0x9BD5,0x0000, 0xFBC0,0x9BD6,0x0000, 0xFBC0,0x9BD7,0x0000, /* 1BD5 */ +0xFBC0,0x9BD8,0x0000, 0xFBC0,0x9BD9,0x0000, 0xFBC0,0x9BDA,0x0000, /* 1BD8 */ +0xFBC0,0x9BDB,0x0000, 0xFBC0,0x9BDC,0x0000, 0xFBC0,0x9BDD,0x0000, /* 1BDB */ +0xFBC0,0x9BDE,0x0000, 0xFBC0,0x9BDF,0x0000, 0xFBC0,0x9BE0,0x0000, /* 1BDE */ +0xFBC0,0x9BE1,0x0000, 0xFBC0,0x9BE2,0x0000, 0xFBC0,0x9BE3,0x0000, /* 1BE1 */ +0xFBC0,0x9BE4,0x0000, 0xFBC0,0x9BE5,0x0000, 0xFBC0,0x9BE6,0x0000, /* 1BE4 */ +0xFBC0,0x9BE7,0x0000, 0xFBC0,0x9BE8,0x0000, 0xFBC0,0x9BE9,0x0000, /* 1BE7 */ +0xFBC0,0x9BEA,0x0000, 0xFBC0,0x9BEB,0x0000, 0xFBC0,0x9BEC,0x0000, /* 1BEA */ +0xFBC0,0x9BED,0x0000, 0xFBC0,0x9BEE,0x0000, 0xFBC0,0x9BEF,0x0000, /* 1BED */ +0xFBC0,0x9BF0,0x0000, 0xFBC0,0x9BF1,0x0000, 0xFBC0,0x9BF2,0x0000, /* 1BF0 */ +0xFBC0,0x9BF3,0x0000, 0xFBC0,0x9BF4,0x0000, 0xFBC0,0x9BF5,0x0000, /* 1BF3 */ +0xFBC0,0x9BF6,0x0000, 0xFBC0,0x9BF7,0x0000, 0xFBC0,0x9BF8,0x0000, /* 1BF6 */ +0xFBC0,0x9BF9,0x0000, 0xFBC0,0x9BFA,0x0000, 0xFBC0,0x9BFB,0x0000, /* 1BF9 */ +0xFBC0,0x9BFC,0x0000, 0xFBC0,0x9BFD,0x0000, 0xFBC0,0x9BFE,0x0000, /* 1BFC */ +0xFBC0,0x9BFF,0x0000 }; + +uint16 uca520_p01C[]= { /* 1C00 (3 weights per char) */ +0x207D,0x0000,0x0000, 0x207E,0x0000,0x0000, 0x207F,0x0000,0x0000, /* 1C00 */ +0x2080,0x0000,0x0000, 0x2081,0x0000,0x0000, 0x2082,0x0000,0x0000, /* 1C03 */ +0x2083,0x0000,0x0000, 0x2084,0x0000,0x0000, 0x2085,0x0000,0x0000, /* 1C06 */ +0x2086,0x0000,0x0000, 0x208A,0x0000,0x0000, 0x208B,0x0000,0x0000, /* 1C09 */ +0x208C,0x0000,0x0000, 0x208D,0x0000,0x0000, 0x208E,0x0000,0x0000, /* 1C0C */ +0x208F,0x0000,0x0000, 0x2090,0x0000,0x0000, 0x2091,0x0000,0x0000, /* 1C0F */ +0x2092,0x0000,0x0000, 0x2093,0x0000,0x0000, 0x2094,0x0000,0x0000, /* 1C12 */ +0x2095,0x0000,0x0000, 0x2096,0x0000,0x0000, 0x2097,0x0000,0x0000, /* 1C15 */ +0x2098,0x0000,0x0000, 0x2099,0x0000,0x0000, 0x209A,0x0000,0x0000, /* 1C18 */ +0x209C,0x0000,0x0000, 0x209E,0x0000,0x0000, 0x209F,0x0000,0x0000, /* 1C1B */ +0x20A0,0x0000,0x0000, 0x20A1,0x0000,0x0000, 0x20A2,0x0000,0x0000, /* 1C1E */ +0x20A3,0x0000,0x0000, 0x20A4,0x0000,0x0000, 0x20A5,0x0000,0x0000, /* 1C21 */ +0x209B,0x0000,0x0000, 0x209D,0x0000,0x0000, 0x20A7,0x0000,0x0000, /* 1C24 */ +0x20A8,0x0000,0x0000, 0x20A9,0x0000,0x0000, 0x20AA,0x0000,0x0000, /* 1C27 */ +0x20AB,0x0000,0x0000, 0x20AC,0x0000,0x0000, 0x20AD,0x0000,0x0000, /* 1C2A */ +0x20AE,0x0000,0x0000, 0x20AF,0x0000,0x0000, 0x20B0,0x0000,0x0000, /* 1C2D */ +0x20B1,0x0000,0x0000, 0x20B2,0x0000,0x0000, 0x20B3,0x0000,0x0000, /* 1C30 */ +0x20B4,0x0000,0x0000, 0x20B5,0x0000,0x0000, 0x20B6,0x0000,0x0000, /* 1C33 */ +0x20A6,0x0000,0x0000, 0x0000,0x0000,0x0000, 0xFBC0,0x9C38,0x0000, /* 1C36 */ +0xFBC0,0x9C39,0x0000, 0xFBC0,0x9C3A,0x0000, 0x0298,0x0000,0x0000, /* 1C39 */ +0x0299,0x0000,0x0000, 0x03BE,0x0000,0x0000, 0x03BF,0x0000,0x0000, /* 1C3C */ +0x03C0,0x0000,0x0000, 0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, /* 1C3F */ +0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, /* 1C42 */ +0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, /* 1C45 */ +0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, 0xFBC0,0x9C4A,0x0000, /* 1C48 */ +0xFBC0,0x9C4B,0x0000, 0xFBC0,0x9C4C,0x0000, 0x2087,0x0000,0x0000, /* 1C4B */ +0x2088,0x0000,0x0000, 0x2089,0x0000,0x0000, 0x1205,0x0000,0x0000, /* 1C4E */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 1C51 */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 1C54 */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 1C57 */ +0x24AA,0x0000,0x0000, 0x24AB,0x0000,0x0000, 0x24AC,0x0000,0x0000, /* 1C5A */ +0x24AD,0x0000,0x0000, 0x24AE,0x0000,0x0000, 0x24AF,0x0000,0x0000, /* 1C5D */ +0x24B0,0x0000,0x0000, 0x24B1,0x0000,0x0000, 0x24B2,0x0000,0x0000, /* 1C60 */ +0x24B3,0x0000,0x0000, 0x24B4,0x0000,0x0000, 0x24B5,0x0000,0x0000, /* 1C63 */ +0x24B6,0x0000,0x0000, 0x24B7,0x0000,0x0000, 0x24B8,0x0000,0x0000, /* 1C66 */ +0x24B9,0x0000,0x0000, 0x24BA,0x0000,0x0000, 0x24BB,0x0000,0x0000, /* 1C69 */ +0x24BC,0x0000,0x0000, 0x24BD,0x0000,0x0000, 0x24BE,0x0000,0x0000, /* 1C6C */ +0x24BF,0x0000,0x0000, 0x24C0,0x0000,0x0000, 0x24C1,0x0000,0x0000, /* 1C6F */ +0x24C2,0x0000,0x0000, 0x24C3,0x0000,0x0000, 0x24C4,0x0000,0x0000, /* 1C72 */ +0x24C5,0x0000,0x0000, 0x24C6,0x0000,0x0000, 0x24C7,0x0000,0x0000, /* 1C75 */ +0x24C8,0x0000,0x0000, 0x24C9,0x0000,0x0000, 0x24CA,0x0000,0x0000, /* 1C78 */ +0x24CB,0x0000,0x0000, 0x24CC,0x0000,0x0000, 0x24CD,0x0000,0x0000, /* 1C7B */ +0x02B3,0x0000,0x0000, 0x02B4,0x0000,0x0000, 0xFBC0,0x9C80,0x0000, /* 1C7E */ +0xFBC0,0x9C81,0x0000, 0xFBC0,0x9C82,0x0000, 0xFBC0,0x9C83,0x0000, /* 1C81 */ +0xFBC0,0x9C84,0x0000, 0xFBC0,0x9C85,0x0000, 0xFBC0,0x9C86,0x0000, /* 1C84 */ +0xFBC0,0x9C87,0x0000, 0xFBC0,0x9C88,0x0000, 0xFBC0,0x9C89,0x0000, /* 1C87 */ +0xFBC0,0x9C8A,0x0000, 0xFBC0,0x9C8B,0x0000, 0xFBC0,0x9C8C,0x0000, /* 1C8A */ +0xFBC0,0x9C8D,0x0000, 0xFBC0,0x9C8E,0x0000, 0xFBC0,0x9C8F,0x0000, /* 1C8D */ +0xFBC0,0x9C90,0x0000, 0xFBC0,0x9C91,0x0000, 0xFBC0,0x9C92,0x0000, /* 1C90 */ +0xFBC0,0x9C93,0x0000, 0xFBC0,0x9C94,0x0000, 0xFBC0,0x9C95,0x0000, /* 1C93 */ +0xFBC0,0x9C96,0x0000, 0xFBC0,0x9C97,0x0000, 0xFBC0,0x9C98,0x0000, /* 1C96 */ +0xFBC0,0x9C99,0x0000, 0xFBC0,0x9C9A,0x0000, 0xFBC0,0x9C9B,0x0000, /* 1C99 */ +0xFBC0,0x9C9C,0x0000, 0xFBC0,0x9C9D,0x0000, 0xFBC0,0x9C9E,0x0000, /* 1C9C */ +0xFBC0,0x9C9F,0x0000, 0xFBC0,0x9CA0,0x0000, 0xFBC0,0x9CA1,0x0000, /* 1C9F */ +0xFBC0,0x9CA2,0x0000, 0xFBC0,0x9CA3,0x0000, 0xFBC0,0x9CA4,0x0000, /* 1CA2 */ +0xFBC0,0x9CA5,0x0000, 0xFBC0,0x9CA6,0x0000, 0xFBC0,0x9CA7,0x0000, /* 1CA5 */ +0xFBC0,0x9CA8,0x0000, 0xFBC0,0x9CA9,0x0000, 0xFBC0,0x9CAA,0x0000, /* 1CA8 */ +0xFBC0,0x9CAB,0x0000, 0xFBC0,0x9CAC,0x0000, 0xFBC0,0x9CAD,0x0000, /* 1CAB */ +0xFBC0,0x9CAE,0x0000, 0xFBC0,0x9CAF,0x0000, 0xFBC0,0x9CB0,0x0000, /* 1CAE */ +0xFBC0,0x9CB1,0x0000, 0xFBC0,0x9CB2,0x0000, 0xFBC0,0x9CB3,0x0000, /* 1CB1 */ +0xFBC0,0x9CB4,0x0000, 0xFBC0,0x9CB5,0x0000, 0xFBC0,0x9CB6,0x0000, /* 1CB4 */ +0xFBC0,0x9CB7,0x0000, 0xFBC0,0x9CB8,0x0000, 0xFBC0,0x9CB9,0x0000, /* 1CB7 */ +0xFBC0,0x9CBA,0x0000, 0xFBC0,0x9CBB,0x0000, 0xFBC0,0x9CBC,0x0000, /* 1CBA */ +0xFBC0,0x9CBD,0x0000, 0xFBC0,0x9CBE,0x0000, 0xFBC0,0x9CBF,0x0000, /* 1CBD */ +0xFBC0,0x9CC0,0x0000, 0xFBC0,0x9CC1,0x0000, 0xFBC0,0x9CC2,0x0000, /* 1CC0 */ +0xFBC0,0x9CC3,0x0000, 0xFBC0,0x9CC4,0x0000, 0xFBC0,0x9CC5,0x0000, /* 1CC3 */ +0xFBC0,0x9CC6,0x0000, 0xFBC0,0x9CC7,0x0000, 0xFBC0,0x9CC8,0x0000, /* 1CC6 */ +0xFBC0,0x9CC9,0x0000, 0xFBC0,0x9CCA,0x0000, 0xFBC0,0x9CCB,0x0000, /* 1CC9 */ +0xFBC0,0x9CCC,0x0000, 0xFBC0,0x9CCD,0x0000, 0xFBC0,0x9CCE,0x0000, /* 1CCC */ +0xFBC0,0x9CCF,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1CCF */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1CD2 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1CD5 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1CD8 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1CDB */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1CDE */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1CE1 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1CE4 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x1BE7,0x0000,0x0000, /* 1CE7 */ +0x1BE7,0x0000,0x0000, 0x1BE7,0x0000,0x0000, 0x1BE7,0x0000,0x0000, /* 1CEA */ +0x0000,0x0000,0x0000, 0x1BE7,0x0000,0x0000, 0x1BE7,0x0000,0x0000, /* 1CED */ +0x1BE7,0x0000,0x0000, 0x1BE7,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1CF0 */ +0xFBC0,0x9CF3,0x0000, 0xFBC0,0x9CF4,0x0000, 0xFBC0,0x9CF5,0x0000, /* 1CF3 */ +0xFBC0,0x9CF6,0x0000, 0xFBC0,0x9CF7,0x0000, 0xFBC0,0x9CF8,0x0000, /* 1CF6 */ +0xFBC0,0x9CF9,0x0000, 0xFBC0,0x9CFA,0x0000, 0xFBC0,0x9CFB,0x0000, /* 1CF9 */ +0xFBC0,0x9CFC,0x0000, 0xFBC0,0x9CFD,0x0000, 0xFBC0,0x9CFE,0x0000, /* 1CFC */ +0xFBC0,0x9CFF,0x0000 }; + +uint16 uca520_p01D[]= { /* 1D00 (3 weights per char) */ +0x1213,0x0000,0x0000, 0x1216,0x0000,0x0000, 0x1217,0x0000,0x0000, /* 1D00 */ +0x1232,0x0000,0x0000, 0x1241,0x0000,0x0000, 0x1254,0x0000,0x0000, /* 1D03 */ +0x1255,0x0000,0x0000, 0x126F,0x0000,0x0000, 0x1292,0x0000,0x0000, /* 1D06 */ +0x12F9,0x0000,0x0000, 0x130D,0x0000,0x0000, 0x1322,0x0000,0x0000, /* 1D09 */ +0x1339,0x0000,0x0000, 0x1363,0x0000,0x0000, 0x1376,0x0000,0x0000, /* 1D0C */ +0x1392,0x0000,0x0000, 0x139E,0x0000,0x0000, 0x1393,0x0000,0x0000, /* 1D0F */ +0x139F,0x0000,0x0000, 0x1399,0x0000,0x0000, 0x1398,0x0000,0x0000, /* 1D12 */ +0x13B2,0x0000,0x0000, 0x13A2,0x0000,0x0000, 0x13A3,0x0000,0x0000, /* 1D15 */ +0x13B7,0x0000,0x0000, 0x13E3,0x0000,0x0000, 0x13ED,0x0000,0x0000, /* 1D18 */ +0x1437,0x0000,0x0000, 0x1457,0x0000,0x0000, 0x1458,0x0000,0x0000, /* 1D1B */ +0x1459,0x0000,0x0000, 0x1471,0x0000,0x0000, 0x147F,0x0000,0x0000, /* 1D1E */ +0x1491,0x0000,0x0000, 0x14B1,0x0000,0x0000, 0x14CE,0x0000,0x0000, /* 1D21 */ +0x1516,0x0000,0x0000, 0x1517,0x0000,0x0000, 0x1548,0x0000,0x0000, /* 1D24 */ +0x1556,0x0000,0x0000, 0x155C,0x0000,0x0000, 0x1561,0x0000,0x0000, /* 1D27 */ +0x156C,0x0000,0x0000, 0x1661,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 1D2A */ +0x120F,0x126B,0x0000, 0x1225,0x0000,0x0000, 0x1231,0x0000,0x0000, /* 1D2D */ +0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x1276,0x0000,0x0000, /* 1D30 */ +0x12B0,0x0000,0x0000, 0x12D3,0x0000,0x0000, 0x12EC,0x0000,0x0000, /* 1D33 */ +0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, /* 1D36 */ +0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, 0x1375,0x0000,0x0000, /* 1D39 */ +0x138E,0x0000,0x0000, 0x13AE,0x0000,0x0000, 0x13B3,0x0000,0x0000, /* 1D3C */ +0x13DA,0x0000,0x0000, 0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 1D3F */ +0x148D,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x1218,0x0000,0x0000, /* 1D42 */ +0x121C,0x0000,0x0000, 0x1217,0x0000,0x0000, 0x1225,0x0000,0x0000, /* 1D45 */ +0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x127B,0x0000,0x0000, /* 1D48 */ +0x1280,0x0000,0x0000, 0x1292,0x0000,0x0000, 0x12B0,0x0000,0x0000, /* 1D4B */ +0x12F9,0x0000,0x0000, 0x131E,0x0000,0x0000, 0x135F,0x0000,0x0000, /* 1D4E */ +0x138A,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x139A,0x0000,0x0000, /* 1D51 */ +0x13A2,0x0000,0x0000, 0x13A3,0x0000,0x0000, 0x13B3,0x0000,0x0000, /* 1D54 */ +0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x1458,0x0000,0x0000, /* 1D57 */ +0x146D,0x0000,0x0000, 0x147B,0x0000,0x0000, 0x1517,0x0000,0x0000, /* 1D5A */ +0x1546,0x0000,0x0000, 0x1547,0x0000,0x0000, 0x1549,0x0000,0x0000, /* 1D5D */ +0x1569,0x0000,0x0000, 0x156A,0x0000,0x0000, 0x12EC,0x0000,0x0000, /* 1D60 */ +0x13DA,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x147B,0x0000,0x0000, /* 1D63 */ +0x1546,0x0000,0x0000, 0x1547,0x0000,0x0000, 0x1560,0x0000,0x0000, /* 1D66 */ +0x1569,0x0000,0x0000, 0x156A,0x0000,0x0000, 0x145A,0x0000,0x0000, /* 1D69 */ +0x1233,0x0000,0x0000, 0x1256,0x0000,0x0000, 0x12A8,0x0000,0x0000, /* 1D6C */ +0x1364,0x0000,0x0000, 0x1377,0x0000,0x0000, 0x13BA,0x0000,0x0000, /* 1D6F */ +0x13E8,0x0000,0x0000, 0x1404,0x0000,0x0000, 0x1415,0x0000,0x0000, /* 1D72 */ +0x143D,0x0000,0x0000, 0x14B6,0x0000,0x0000, 0x12C9,0x0000,0x0000, /* 1D75 */ +0x1678,0x0000,0x0000, 0x12B0,0x0000,0x0000, 0x1433,0x12D3,0x0000, /* 1D78 */ +0x12FE,0x0000,0x0000, 0x1304,0x0000,0x0000, 0x13B8,0x0000,0x0000, /* 1D7B */ +0x145F,0x0000,0x0000, 0x147A,0x0000,0x0000, 0x1234,0x0000,0x0000, /* 1D7E */ +0x1257,0x0000,0x0000, 0x12A9,0x0000,0x0000, 0x12C0,0x0000,0x0000, /* 1D81 */ +0x1323,0x0000,0x0000, 0x1348,0x0000,0x0000, 0x1365,0x0000,0x0000, /* 1D84 */ +0x1380,0x0000,0x0000, 0x13BB,0x0000,0x0000, 0x13F2,0x0000,0x0000, /* 1D87 */ +0x1416,0x0000,0x0000, 0x1425,0x0000,0x0000, 0x1481,0x0000,0x0000, /* 1D8A */ +0x149B,0x0000,0x0000, 0x14B7,0x0000,0x0000, 0x1215,0x0000,0x0000, /* 1D8D */ +0x1220,0x0000,0x0000, 0x1260,0x0000,0x0000, 0x1274,0x0000,0x0000, /* 1D90 */ +0x1284,0x0000,0x0000, 0x1291,0x0000,0x0000, 0x127F,0x0000,0x0000, /* 1D93 */ +0x12FF,0x0000,0x0000, 0x13A0,0x0000,0x0000, 0x142E,0x0000,0x0000, /* 1D96 */ +0x1460,0x0000,0x0000, 0x14D3,0x0000,0x0000, 0x1221,0x0000,0x0000, /* 1D99 */ +0x123D,0x0000,0x0000, 0x124A,0x0000,0x0000, 0x1250,0x0000,0x0000, /* 1D9C */ +0x128D,0x0000,0x0000, 0x12A3,0x0000,0x0000, 0x1316,0x0000,0x0000, /* 1D9F */ +0x12B4,0x0000,0x0000, 0x1461,0x0000,0x0000, 0x12FA,0x0000,0x0000, /* 1DA2 */ +0x1300,0x0000,0x0000, 0x12F4,0x0000,0x0000, 0x12FE,0x0000,0x0000, /* 1DA5 */ +0x1312,0x0000,0x0000, 0x1349,0x0000,0x0000, 0x1348,0x0000,0x0000, /* 1DA8 */ +0x1334,0x0000,0x0000, 0x1366,0x0000,0x0000, 0x1472,0x0000,0x0000, /* 1DAB */ +0x1378,0x0000,0x0000, 0x1381,0x0000,0x0000, 0x1371,0x0000,0x0000, /* 1DAE */ +0x13A5,0x0000,0x0000, 0x13C3,0x0000,0x0000, 0x1417,0x0000,0x0000, /* 1DB1 */ +0x1421,0x0000,0x0000, 0x143E,0x0000,0x0000, 0x145B,0x0000,0x0000, /* 1DB4 */ +0x1476,0x0000,0x0000, 0x1457,0x0000,0x0000, 0x1482,0x0000,0x0000, /* 1DB7 */ +0x1489,0x0000,0x0000, 0x14AD,0x0000,0x0000, 0x14BC,0x0000,0x0000, /* 1DBA */ +0x14C0,0x0000,0x0000, 0x14CA,0x0000,0x0000, 0x1551,0x0000,0x0000, /* 1DBD */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1DC0 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1DC3 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1DC6 */ +0x0000,0x0000,0x0000, 0x13DA,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1DC9 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1DCC */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1DCF */ +0x14ED,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x120F,0x126B,0x0000, /* 1DD2 */ +0x120F,0x138E,0x0000, 0x120F,0x147B,0x0000, 0x123D,0x0000,0x0000, /* 1DD5 */ +0x1250,0x0000,0x0000, 0x1250,0x0000,0x0000, 0x12B0,0x0000,0x0000, /* 1DD8 */ +0x12B8,0x0000,0x0000, 0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, /* 1DDB */ +0x1334,0x0000,0x0000, 0x1363,0x0000,0x0000, 0x136D,0x0000,0x0000, /* 1DDE */ +0x1371,0x0000,0x0000, 0x13DE,0x0000,0x0000, 0x13E2,0x0000,0x0000, /* 1DE1 */ +0x1410,0x0000,0x0000, 0x1410,0x0000,0x0000, 0x14AD,0x0000,0x0000, /* 1DE4 */ +0xFBC0,0x9DE7,0x0000, 0xFBC0,0x9DE8,0x0000, 0xFBC0,0x9DE9,0x0000, /* 1DE7 */ +0xFBC0,0x9DEA,0x0000, 0xFBC0,0x9DEB,0x0000, 0xFBC0,0x9DEC,0x0000, /* 1DEA */ +0xFBC0,0x9DED,0x0000, 0xFBC0,0x9DEE,0x0000, 0xFBC0,0x9DEF,0x0000, /* 1DED */ +0xFBC0,0x9DF0,0x0000, 0xFBC0,0x9DF1,0x0000, 0xFBC0,0x9DF2,0x0000, /* 1DF0 */ +0xFBC0,0x9DF3,0x0000, 0xFBC0,0x9DF4,0x0000, 0xFBC0,0x9DF5,0x0000, /* 1DF3 */ +0xFBC0,0x9DF6,0x0000, 0xFBC0,0x9DF7,0x0000, 0xFBC0,0x9DF8,0x0000, /* 1DF6 */ +0xFBC0,0x9DF9,0x0000, 0xFBC0,0x9DFA,0x0000, 0xFBC0,0x9DFB,0x0000, /* 1DF9 */ +0xFBC0,0x9DFC,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1DFC */ +0x0000,0x0000,0x0000 }; + +uint16 uca520_p01E[]= { /* 1E00 (3 weights per char) */ +0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x1225,0x0000,0x0000, /* 1E00 */ +0x1225,0x0000,0x0000, 0x1225,0x0000,0x0000, 0x1225,0x0000,0x0000, /* 1E03 */ +0x1225,0x0000,0x0000, 0x1225,0x0000,0x0000, 0x123D,0x0000,0x0000, /* 1E06 */ +0x123D,0x0000,0x0000, 0x1250,0x0000,0x0000, 0x1250,0x0000,0x0000, /* 1E09 */ +0x1250,0x0000,0x0000, 0x1250,0x0000,0x0000, 0x1250,0x0000,0x0000, /* 1E0C */ +0x1250,0x0000,0x0000, 0x1250,0x0000,0x0000, 0x1250,0x0000,0x0000, /* 1E0F */ +0x1250,0x0000,0x0000, 0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 1E12 */ +0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 1E15 */ +0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 1E18 */ +0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 1E1B */ +0x12A3,0x0000,0x0000, 0x12A3,0x0000,0x0000, 0x12B0,0x0000,0x0000, /* 1E1E */ +0x12B0,0x0000,0x0000, 0x12D3,0x0000,0x0000, 0x12D3,0x0000,0x0000, /* 1E21 */ +0x12D3,0x0000,0x0000, 0x12D3,0x0000,0x0000, 0x12D3,0x0000,0x0000, /* 1E24 */ +0x12D3,0x0000,0x0000, 0x12D3,0x0000,0x0000, 0x12D3,0x0000,0x0000, /* 1E27 */ +0x12D3,0x0000,0x0000, 0x12D3,0x0000,0x0000, 0x12EC,0x0000,0x0000, /* 1E2A */ +0x12EC,0x0000,0x0000, 0x12EC,0x0000,0x0000, 0x12EC,0x0000,0x0000, /* 1E2D */ +0x131E,0x0000,0x0000, 0x131E,0x0000,0x0000, 0x131E,0x0000,0x0000, /* 1E30 */ +0x131E,0x0000,0x0000, 0x131E,0x0000,0x0000, 0x131E,0x0000,0x0000, /* 1E33 */ +0x1330,0x0000,0x0000, 0x1330,0x0000,0x0000, 0x1330,0x0000,0x0000, /* 1E36 */ +0x1330,0x0000,0x0000, 0x1330,0x0000,0x0000, 0x1330,0x0000,0x0000, /* 1E39 */ +0x1330,0x0000,0x0000, 0x1330,0x0000,0x0000, 0x135F,0x0000,0x0000, /* 1E3C */ +0x135F,0x0000,0x0000, 0x135F,0x0000,0x0000, 0x135F,0x0000,0x0000, /* 1E3F */ +0x135F,0x0000,0x0000, 0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, /* 1E42 */ +0x136D,0x0000,0x0000, 0x136D,0x0000,0x0000, 0x136D,0x0000,0x0000, /* 1E45 */ +0x136D,0x0000,0x0000, 0x136D,0x0000,0x0000, 0x136D,0x0000,0x0000, /* 1E48 */ +0x136D,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1E4B */ +0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1E4E */ +0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1E51 */ +0x13B3,0x0000,0x0000, 0x13B3,0x0000,0x0000, 0x13B3,0x0000,0x0000, /* 1E54 */ +0x13B3,0x0000,0x0000, 0x13DA,0x0000,0x0000, 0x13DA,0x0000,0x0000, /* 1E57 */ +0x13DA,0x0000,0x0000, 0x13DA,0x0000,0x0000, 0x13DA,0x0000,0x0000, /* 1E5A */ +0x13DA,0x0000,0x0000, 0x13DA,0x0000,0x0000, 0x13DA,0x0000,0x0000, /* 1E5D */ +0x1410,0x0000,0x0000, 0x1410,0x0000,0x0000, 0x1410,0x0000,0x0000, /* 1E60 */ +0x1410,0x0000,0x0000, 0x1410,0x0000,0x0000, 0x1410,0x0000,0x0000, /* 1E63 */ +0x1410,0x0000,0x0000, 0x1410,0x0000,0x0000, 0x1410,0x0000,0x0000, /* 1E66 */ +0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, 0x1433,0x0000,0x0000, /* 1E69 */ +0x1433,0x0000,0x0000, 0x1433,0x0000,0x0000, 0x1433,0x0000,0x0000, /* 1E6C */ +0x1433,0x0000,0x0000, 0x1433,0x0000,0x0000, 0x1433,0x0000,0x0000, /* 1E6F */ +0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 1E72 */ +0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 1E75 */ +0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 1E78 */ +0x1453,0x0000,0x0000, 0x147B,0x0000,0x0000, 0x147B,0x0000,0x0000, /* 1E7B */ +0x147B,0x0000,0x0000, 0x147B,0x0000,0x0000, 0x148D,0x0000,0x0000, /* 1E7E */ +0x148D,0x0000,0x0000, 0x148D,0x0000,0x0000, 0x148D,0x0000,0x0000, /* 1E81 */ +0x148D,0x0000,0x0000, 0x148D,0x0000,0x0000, 0x148D,0x0000,0x0000, /* 1E84 */ +0x148D,0x0000,0x0000, 0x148D,0x0000,0x0000, 0x148D,0x0000,0x0000, /* 1E87 */ +0x1497,0x0000,0x0000, 0x1497,0x0000,0x0000, 0x1497,0x0000,0x0000, /* 1E8A */ +0x1497,0x0000,0x0000, 0x149C,0x0000,0x0000, 0x149C,0x0000,0x0000, /* 1E8D */ +0x14AD,0x0000,0x0000, 0x14AD,0x0000,0x0000, 0x14AD,0x0000,0x0000, /* 1E90 */ +0x14AD,0x0000,0x0000, 0x14AD,0x0000,0x0000, 0x14AD,0x0000,0x0000, /* 1E93 */ +0x12D3,0x0000,0x0000, 0x1433,0x0000,0x0000, 0x148D,0x0000,0x0000, /* 1E96 */ +0x149C,0x0000,0x0000, 0x120F,0x150D,0x0000, 0x1410,0x0000,0x0000, /* 1E99 */ +0x141F,0x0000,0x0000, 0x1420,0x0000,0x0000, 0x1410,0x1410,0x0000, /* 1E9C */ +0x126A,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 1E9F */ +0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 1EA2 */ +0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 1EA5 */ +0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 1EA8 */ +0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 1EAB */ +0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 1EAE */ +0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 1EB1 */ +0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 1EB4 */ +0x120F,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 1EB7 */ +0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 1EBA */ +0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 1EBD */ +0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 1EC0 */ +0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 1EC3 */ +0x126B,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x12EC,0x0000,0x0000, /* 1EC6 */ +0x12EC,0x0000,0x0000, 0x12EC,0x0000,0x0000, 0x12EC,0x0000,0x0000, /* 1EC9 */ +0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1ECC */ +0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1ECF */ +0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1ED2 */ +0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1ED5 */ +0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1ED8 */ +0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1EDB */ +0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1EDE */ +0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1EE1 */ +0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 1EE4 */ +0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 1EE7 */ +0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 1EEA */ +0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 1EED */ +0x1453,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x149C,0x0000,0x0000, /* 1EF0 */ +0x149C,0x0000,0x0000, 0x149C,0x0000,0x0000, 0x149C,0x0000,0x0000, /* 1EF3 */ +0x149C,0x0000,0x0000, 0x149C,0x0000,0x0000, 0x149C,0x0000,0x0000, /* 1EF6 */ +0x149C,0x0000,0x0000, 0x1330,0x1330,0x0000, 0x1330,0x1330,0x0000, /* 1EF9 */ +0x1488,0x0000,0x0000, 0x1488,0x0000,0x0000, 0x14AC,0x0000,0x0000, /* 1EFC */ +0x14AC,0x0000,0x0000 }; + +uint16 uca520_p01F[]= { /* 1F00 (3 weights per char) */ +0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, /* 1F00 */ +0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, /* 1F03 */ +0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, /* 1F06 */ +0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, /* 1F09 */ +0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, /* 1F0C */ +0x1545,0x0000,0x0000, 0x154A,0x0000,0x0000, 0x154A,0x0000,0x0000, /* 1F0F */ +0x154A,0x0000,0x0000, 0x154A,0x0000,0x0000, 0x154A,0x0000,0x0000, /* 1F12 */ +0x154A,0x0000,0x0000, 0xFBC0,0x9F16,0x0000, 0xFBC0,0x9F17,0x0000, /* 1F15 */ +0x154A,0x0000,0x0000, 0x154A,0x0000,0x0000, 0x154A,0x0000,0x0000, /* 1F18 */ +0x154A,0x0000,0x0000, 0x154A,0x0000,0x0000, 0x154A,0x0000,0x0000, /* 1F1B */ +0xFBC0,0x9F1E,0x0000, 0xFBC0,0x9F1F,0x0000, 0x1550,0x0000,0x0000, /* 1F1E */ +0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, /* 1F21 */ +0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, /* 1F24 */ +0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, /* 1F27 */ +0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, /* 1F2A */ +0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, /* 1F2D */ +0x1552,0x0000,0x0000, 0x1552,0x0000,0x0000, 0x1552,0x0000,0x0000, /* 1F30 */ +0x1552,0x0000,0x0000, 0x1552,0x0000,0x0000, 0x1552,0x0000,0x0000, /* 1F33 */ +0x1552,0x0000,0x0000, 0x1552,0x0000,0x0000, 0x1552,0x0000,0x0000, /* 1F36 */ +0x1552,0x0000,0x0000, 0x1552,0x0000,0x0000, 0x1552,0x0000,0x0000, /* 1F39 */ +0x1552,0x0000,0x0000, 0x1552,0x0000,0x0000, 0x1552,0x0000,0x0000, /* 1F3C */ +0x1552,0x0000,0x0000, 0x155A,0x0000,0x0000, 0x155A,0x0000,0x0000, /* 1F3F */ +0x155A,0x0000,0x0000, 0x155A,0x0000,0x0000, 0x155A,0x0000,0x0000, /* 1F42 */ +0x155A,0x0000,0x0000, 0xFBC0,0x9F46,0x0000, 0xFBC0,0x9F47,0x0000, /* 1F45 */ +0x155A,0x0000,0x0000, 0x155A,0x0000,0x0000, 0x155A,0x0000,0x0000, /* 1F48 */ +0x155A,0x0000,0x0000, 0x155A,0x0000,0x0000, 0x155A,0x0000,0x0000, /* 1F4B */ +0xFBC0,0x9F4E,0x0000, 0xFBC0,0x9F4F,0x0000, 0x1568,0x0000,0x0000, /* 1F4E */ +0x1568,0x0000,0x0000, 0x1568,0x0000,0x0000, 0x1568,0x0000,0x0000, /* 1F51 */ +0x1568,0x0000,0x0000, 0x1568,0x0000,0x0000, 0x1568,0x0000,0x0000, /* 1F54 */ +0x1568,0x0000,0x0000, 0xFBC0,0x9F58,0x0000, 0x1568,0x0000,0x0000, /* 1F57 */ +0xFBC0,0x9F5A,0x0000, 0x1568,0x0000,0x0000, 0xFBC0,0x9F5C,0x0000, /* 1F5A */ +0x1568,0x0000,0x0000, 0xFBC0,0x9F5E,0x0000, 0x1568,0x0000,0x0000, /* 1F5D */ +0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, /* 1F60 */ +0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, /* 1F63 */ +0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, /* 1F66 */ +0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, /* 1F69 */ +0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, /* 1F6C */ +0x156D,0x0000,0x0000, 0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, /* 1F6F */ +0x154A,0x0000,0x0000, 0x154A,0x0000,0x0000, 0x1550,0x0000,0x0000, /* 1F72 */ +0x1550,0x0000,0x0000, 0x1552,0x0000,0x0000, 0x1552,0x0000,0x0000, /* 1F75 */ +0x155A,0x0000,0x0000, 0x155A,0x0000,0x0000, 0x1568,0x0000,0x0000, /* 1F78 */ +0x1568,0x0000,0x0000, 0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, /* 1F7B */ +0xFBC0,0x9F7E,0x0000, 0xFBC0,0x9F7F,0x0000, 0x1545,0x0000,0x0000, /* 1F7E */ +0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, /* 1F81 */ +0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, /* 1F84 */ +0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, /* 1F87 */ +0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, /* 1F8A */ +0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, /* 1F8D */ +0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, /* 1F90 */ +0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, /* 1F93 */ +0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, /* 1F96 */ +0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, /* 1F99 */ +0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, /* 1F9C */ +0x1550,0x0000,0x0000, 0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, /* 1F9F */ +0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, /* 1FA2 */ +0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, /* 1FA5 */ +0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, /* 1FA8 */ +0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, /* 1FAB */ +0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, 0x1545,0x0000,0x0000, /* 1FAE */ +0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, /* 1FB1 */ +0x1545,0x0000,0x0000, 0xFBC0,0x9FB5,0x0000, 0x1545,0x0000,0x0000, /* 1FB4 */ +0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, /* 1FB7 */ +0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, 0x1545,0x0000,0x0000, /* 1FBA */ +0x0219,0x0000,0x0000, 0x1552,0x0000,0x0000, 0x0219,0x0000,0x0000, /* 1FBD */ +0x021F,0x0000,0x0000, 0x0216,0x0000,0x0000, 0x1550,0x0000,0x0000, /* 1FC0 */ +0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, 0xFBC0,0x9FC5,0x0000, /* 1FC3 */ +0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, 0x154A,0x0000,0x0000, /* 1FC6 */ +0x154A,0x0000,0x0000, 0x1550,0x0000,0x0000, 0x1550,0x0000,0x0000, /* 1FC9 */ +0x1550,0x0000,0x0000, 0x0219,0x0000,0x0000, 0x0219,0x0000,0x0000, /* 1FCC */ +0x0219,0x0000,0x0000, 0x1552,0x0000,0x0000, 0x1552,0x0000,0x0000, /* 1FCF */ +0x1552,0x0000,0x0000, 0x1552,0x0000,0x0000, 0xFBC0,0x9FD4,0x0000, /* 1FD2 */ +0xFBC0,0x9FD5,0x0000, 0x1552,0x0000,0x0000, 0x1552,0x0000,0x0000, /* 1FD5 */ +0x1552,0x0000,0x0000, 0x1552,0x0000,0x0000, 0x1552,0x0000,0x0000, /* 1FD8 */ +0x1552,0x0000,0x0000, 0xFBC0,0x9FDC,0x0000, 0x021A,0x0000,0x0000, /* 1FDB */ +0x021A,0x0000,0x0000, 0x021A,0x0000,0x0000, 0x1568,0x0000,0x0000, /* 1FDE */ +0x1568,0x0000,0x0000, 0x1568,0x0000,0x0000, 0x1568,0x0000,0x0000, /* 1FE1 */ +0x1560,0x0000,0x0000, 0x1560,0x0000,0x0000, 0x1568,0x0000,0x0000, /* 1FE4 */ +0x1568,0x0000,0x0000, 0x1568,0x0000,0x0000, 0x1568,0x0000,0x0000, /* 1FE7 */ +0x1568,0x0000,0x0000, 0x1568,0x0000,0x0000, 0x1560,0x0000,0x0000, /* 1FEA */ +0x0216,0x0000,0x0000, 0x0216,0x0000,0x0000, 0x020E,0x0000,0x0000, /* 1FED */ +0xFBC0,0x9FF0,0x0000, 0xFBC0,0x9FF1,0x0000, 0x156D,0x0000,0x0000, /* 1FF0 */ +0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, 0xFBC0,0x9FF5,0x0000, /* 1FF3 */ +0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, 0x155A,0x0000,0x0000, /* 1FF6 */ +0x155A,0x0000,0x0000, 0x156D,0x0000,0x0000, 0x156D,0x0000,0x0000, /* 1FF9 */ +0x156D,0x0000,0x0000, 0x020F,0x0000,0x0000, 0x021A,0x0000,0x0000, /* 1FFC */ +0xFBC0,0x9FFF,0x0000 }; + +uint16 uca520_p020[]= { /* 2000 (5 weights per char) */ +0x020A,0x0000,0x0000,0x0000,0x0000, /* 2000 */ +0x020A,0x0000,0x0000,0x0000,0x0000, /* 2001 */ +0x020A,0x0000,0x0000,0x0000,0x0000, /* 2002 */ +0x020A,0x0000,0x0000,0x0000,0x0000, /* 2003 */ +0x020A,0x0000,0x0000,0x0000,0x0000, /* 2004 */ +0x020A,0x0000,0x0000,0x0000,0x0000, /* 2005 */ +0x020A,0x0000,0x0000,0x0000,0x0000, /* 2006 */ +0x020A,0x0000,0x0000,0x0000,0x0000, /* 2007 */ +0x020A,0x0000,0x0000,0x0000,0x0000, /* 2008 */ +0x020A,0x0000,0x0000,0x0000,0x0000, /* 2009 */ +0x020A,0x0000,0x0000,0x0000,0x0000, /* 200A */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 200B */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 200C */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 200D */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 200E */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 200F */ +0x0229,0x0000,0x0000,0x0000,0x0000, /* 2010 */ +0x0229,0x0000,0x0000,0x0000,0x0000, /* 2011 */ +0x022A,0x0000,0x0000,0x0000,0x0000, /* 2012 */ +0x022B,0x0000,0x0000,0x0000,0x0000, /* 2013 */ +0x022C,0x0000,0x0000,0x0000,0x0000, /* 2014 */ +0x022D,0x0000,0x0000,0x0000,0x0000, /* 2015 */ +0x055A,0x0000,0x0000,0x0000,0x0000, /* 2016 */ +0x021E,0x0000,0x0000,0x0000,0x0000, /* 2017 */ +0x02EF,0x0000,0x0000,0x0000,0x0000, /* 2018 */ +0x02F0,0x0000,0x0000,0x0000,0x0000, /* 2019 */ +0x02F1,0x0000,0x0000,0x0000,0x0000, /* 201A */ +0x02F2,0x0000,0x0000,0x0000,0x0000, /* 201B */ +0x02F6,0x0000,0x0000,0x0000,0x0000, /* 201C */ +0x02F7,0x0000,0x0000,0x0000,0x0000, /* 201D */ +0x02F8,0x0000,0x0000,0x0000,0x0000, /* 201E */ +0x02F9,0x0000,0x0000,0x0000,0x0000, /* 201F */ +0x036A,0x0000,0x0000,0x0000,0x0000, /* 2020 */ +0x036B,0x0000,0x0000,0x0000,0x0000, /* 2021 */ +0x036C,0x0000,0x0000,0x0000,0x0000, /* 2022 */ +0x036D,0x0000,0x0000,0x0000,0x0000, /* 2023 */ +0x0281,0x0000,0x0000,0x0000,0x0000, /* 2024 */ +0x0281,0x0281,0x0000,0x0000,0x0000, /* 2025 */ +0x0281,0x0281,0x0281,0x0000,0x0000, /* 2026 */ +0x036E,0x0000,0x0000,0x0000,0x0000, /* 2027 */ +0x0208,0x0000,0x0000,0x0000,0x0000, /* 2028 */ +0x0209,0x0000,0x0000,0x0000,0x0000, /* 2029 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 202A */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 202B */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 202C */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 202D */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 202E */ +0x020A,0x0000,0x0000,0x0000,0x0000, /* 202F */ +0x0365,0x0000,0x0000,0x0000,0x0000, /* 2030 */ +0x0367,0x0000,0x0000,0x0000,0x0000, /* 2031 */ +0x0372,0x0000,0x0000,0x0000,0x0000, /* 2032 */ +0x0372,0x0372,0x0000,0x0000,0x0000, /* 2033 */ +0x0372,0x0372,0x0372,0x0000,0x0000, /* 2034 */ +0x0373,0x0000,0x0000,0x0000,0x0000, /* 2035 */ +0x0373,0x0373,0x0000,0x0000,0x0000, /* 2036 */ +0x0373,0x0373,0x0373,0x0000,0x0000, /* 2037 */ +0x0376,0x0000,0x0000,0x0000,0x0000, /* 2038 */ +0x02F3,0x0000,0x0000,0x0000,0x0000, /* 2039 */ +0x02F4,0x0000,0x0000,0x0000,0x0000, /* 203A */ +0x0377,0x0000,0x0000,0x0000,0x0000, /* 203B */ +0x026E,0x026E,0x0000,0x0000,0x0000, /* 203C */ +0x027F,0x0000,0x0000,0x0000,0x0000, /* 203D */ +0x0213,0x0000,0x0000,0x0000,0x0000, /* 203E */ +0x0378,0x0000,0x0000,0x0000,0x0000, /* 203F */ +0x037A,0x0000,0x0000,0x0000,0x0000, /* 2040 */ +0x037C,0x0000,0x0000,0x0000,0x0000, /* 2041 */ +0x037D,0x0000,0x0000,0x0000,0x0000, /* 2042 */ +0x036F,0x0000,0x0000,0x0000,0x0000, /* 2043 */ +0x035D,0x0000,0x0000,0x0000,0x0000, /* 2044 */ +0x030B,0x0000,0x0000,0x0000,0x0000, /* 2045 */ +0x030C,0x0000,0x0000,0x0000,0x0000, /* 2046 */ +0x0273,0x0273,0x0000,0x0000,0x0000, /* 2047 */ +0x0273,0x026E,0x0000,0x0000,0x0000, /* 2048 */ +0x026E,0x0273,0x0000,0x0000,0x0000, /* 2049 */ +0x0361,0x0000,0x0000,0x0000,0x0000, /* 204A */ +0x0353,0x0000,0x0000,0x0000,0x0000, /* 204B */ +0x0370,0x0000,0x0000,0x0000,0x0000, /* 204C */ +0x0371,0x0000,0x0000,0x0000,0x0000, /* 204D */ +0x0358,0x0000,0x0000,0x0000,0x0000, /* 204E */ +0x0245,0x0000,0x0000,0x0000,0x0000, /* 204F */ +0x037B,0x0000,0x0000,0x0000,0x0000, /* 2050 */ +0x0359,0x0000,0x0000,0x0000,0x0000, /* 2051 */ +0x0369,0x0000,0x0000,0x0000,0x0000, /* 2052 */ +0x022E,0x0000,0x0000,0x0000,0x0000, /* 2053 */ +0x0379,0x0000,0x0000,0x0000,0x0000, /* 2054 */ +0x02D3,0x0000,0x0000,0x0000,0x0000, /* 2055 */ +0x02D4,0x0000,0x0000,0x0000,0x0000, /* 2056 */ +0x0372,0x0372,0x0372,0x0372,0x0000, /* 2057 */ +0x02D5,0x0000,0x0000,0x0000,0x0000, /* 2058 */ +0x02D6,0x0000,0x0000,0x0000,0x0000, /* 2059 */ +0x02D7,0x0000,0x0000,0x0000,0x0000, /* 205A */ +0x02D8,0x0000,0x0000,0x0000,0x0000, /* 205B */ +0x02D9,0x0000,0x0000,0x0000,0x0000, /* 205C */ +0x02DA,0x0000,0x0000,0x0000,0x0000, /* 205D */ +0x02DB,0x0000,0x0000,0x0000,0x0000, /* 205E */ +0x020A,0x0000,0x0000,0x0000,0x0000, /* 205F */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 2060 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 2061 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 2062 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 2063 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 2064 */ +0xFBC0,0xA065,0x0000,0x0000,0x0000, /* 2065 */ +0xFBC0,0xA066,0x0000,0x0000,0x0000, /* 2066 */ +0xFBC0,0xA067,0x0000,0x0000,0x0000, /* 2067 */ +0xFBC0,0xA068,0x0000,0x0000,0x0000, /* 2068 */ +0xFBC0,0xA069,0x0000,0x0000,0x0000, /* 2069 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 206A */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 206B */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 206C */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 206D */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 206E */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 206F */ +0x1205,0x0000,0x0000,0x0000,0x0000, /* 2070 */ +0x12EC,0x0000,0x0000,0x0000,0x0000, /* 2071 */ +0xFBC0,0xA072,0x0000,0x0000,0x0000, /* 2072 */ +0xFBC0,0xA073,0x0000,0x0000,0x0000, /* 2073 */ +0x1209,0x0000,0x0000,0x0000,0x0000, /* 2074 */ +0x120A,0x0000,0x0000,0x0000,0x0000, /* 2075 */ +0x120B,0x0000,0x0000,0x0000,0x0000, /* 2076 */ +0x120C,0x0000,0x0000,0x0000,0x0000, /* 2077 */ +0x120D,0x0000,0x0000,0x0000,0x0000, /* 2078 */ +0x120E,0x0000,0x0000,0x0000,0x0000, /* 2079 */ +0x0550,0x0000,0x0000,0x0000,0x0000, /* 207A */ +0x055C,0x0000,0x0000,0x0000,0x0000, /* 207B */ +0x0555,0x0000,0x0000,0x0000,0x0000, /* 207C */ +0x02FF,0x0000,0x0000,0x0000,0x0000, /* 207D */ +0x0300,0x0000,0x0000,0x0000,0x0000, /* 207E */ +0x136D,0x0000,0x0000,0x0000,0x0000, /* 207F */ +0x1205,0x0000,0x0000,0x0000,0x0000, /* 2080 */ +0x1206,0x0000,0x0000,0x0000,0x0000, /* 2081 */ +0x1207,0x0000,0x0000,0x0000,0x0000, /* 2082 */ +0x1208,0x0000,0x0000,0x0000,0x0000, /* 2083 */ +0x1209,0x0000,0x0000,0x0000,0x0000, /* 2084 */ +0x120A,0x0000,0x0000,0x0000,0x0000, /* 2085 */ +0x120B,0x0000,0x0000,0x0000,0x0000, /* 2086 */ +0x120C,0x0000,0x0000,0x0000,0x0000, /* 2087 */ +0x120D,0x0000,0x0000,0x0000,0x0000, /* 2088 */ +0x120E,0x0000,0x0000,0x0000,0x0000, /* 2089 */ +0x0550,0x0000,0x0000,0x0000,0x0000, /* 208A */ +0x055C,0x0000,0x0000,0x0000,0x0000, /* 208B */ +0x0555,0x0000,0x0000,0x0000,0x0000, /* 208C */ +0x02FF,0x0000,0x0000,0x0000,0x0000, /* 208D */ +0x0300,0x0000,0x0000,0x0000,0x0000, /* 208E */ +0xFBC0,0xA08F,0x0000,0x0000,0x0000, /* 208F */ +0x120F,0x0000,0x0000,0x0000,0x0000, /* 2090 */ +0x126B,0x0000,0x0000,0x0000,0x0000, /* 2091 */ +0x138E,0x0000,0x0000,0x0000,0x0000, /* 2092 */ +0x1497,0x0000,0x0000,0x0000,0x0000, /* 2093 */ +0x127B,0x0000,0x0000,0x0000,0x0000, /* 2094 */ +0xFBC0,0xA095,0x0000,0x0000,0x0000, /* 2095 */ +0xFBC0,0xA096,0x0000,0x0000,0x0000, /* 2096 */ +0xFBC0,0xA097,0x0000,0x0000,0x0000, /* 2097 */ +0xFBC0,0xA098,0x0000,0x0000,0x0000, /* 2098 */ +0xFBC0,0xA099,0x0000,0x0000,0x0000, /* 2099 */ +0xFBC0,0xA09A,0x0000,0x0000,0x0000, /* 209A */ +0xFBC0,0xA09B,0x0000,0x0000,0x0000, /* 209B */ +0xFBC0,0xA09C,0x0000,0x0000,0x0000, /* 209C */ +0xFBC0,0xA09D,0x0000,0x0000,0x0000, /* 209D */ +0xFBC0,0xA09E,0x0000,0x0000,0x0000, /* 209E */ +0xFBC0,0xA09F,0x0000,0x0000,0x0000, /* 209F */ +0x11ED,0x0000,0x0000,0x0000,0x0000, /* 20A0 */ +0x11EE,0x0000,0x0000,0x0000,0x0000, /* 20A1 */ +0x11EF,0x0000,0x0000,0x0000,0x0000, /* 20A2 */ +0x11F0,0x0000,0x0000,0x0000,0x0000, /* 20A3 */ +0x11F1,0x0000,0x0000,0x0000,0x0000, /* 20A4 */ +0x11F2,0x0000,0x0000,0x0000,0x0000, /* 20A5 */ +0x11F3,0x0000,0x0000,0x0000,0x0000, /* 20A6 */ +0x11F4,0x0000,0x0000,0x0000,0x0000, /* 20A7 */ +0x13DA,0x1410,0x0000,0x0000,0x0000, /* 20A8 */ +0x11F5,0x0000,0x0000,0x0000,0x0000, /* 20A9 */ +0x11F6,0x0000,0x0000,0x0000,0x0000, /* 20AA */ +0x11F7,0x0000,0x0000,0x0000,0x0000, /* 20AB */ +0x11F8,0x0000,0x0000,0x0000,0x0000, /* 20AC */ +0x11F9,0x0000,0x0000,0x0000,0x0000, /* 20AD */ +0x11FA,0x0000,0x0000,0x0000,0x0000, /* 20AE */ +0x11FB,0x0000,0x0000,0x0000,0x0000, /* 20AF */ +0x11FC,0x0000,0x0000,0x0000,0x0000, /* 20B0 */ +0x11FD,0x0000,0x0000,0x0000,0x0000, /* 20B1 */ +0x11FE,0x0000,0x0000,0x0000,0x0000, /* 20B2 */ +0x11FF,0x0000,0x0000,0x0000,0x0000, /* 20B3 */ +0x1200,0x0000,0x0000,0x0000,0x0000, /* 20B4 */ +0x1201,0x0000,0x0000,0x0000,0x0000, /* 20B5 */ +0x1202,0x0000,0x0000,0x0000,0x0000, /* 20B6 */ +0x1203,0x0000,0x0000,0x0000,0x0000, /* 20B7 */ +0x1204,0x0000,0x0000,0x0000,0x0000, /* 20B8 */ +0xFBC0,0xA0B9,0x0000,0x0000,0x0000, /* 20B9 */ +0xFBC0,0xA0BA,0x0000,0x0000,0x0000, /* 20BA */ +0xFBC0,0xA0BB,0x0000,0x0000,0x0000, /* 20BB */ +0xFBC0,0xA0BC,0x0000,0x0000,0x0000, /* 20BC */ +0xFBC0,0xA0BD,0x0000,0x0000,0x0000, /* 20BD */ +0xFBC0,0xA0BE,0x0000,0x0000,0x0000, /* 20BE */ +0xFBC0,0xA0BF,0x0000,0x0000,0x0000, /* 20BF */ +0xFBC0,0xA0C0,0x0000,0x0000,0x0000, /* 20C0 */ +0xFBC0,0xA0C1,0x0000,0x0000,0x0000, /* 20C1 */ +0xFBC0,0xA0C2,0x0000,0x0000,0x0000, /* 20C2 */ +0xFBC0,0xA0C3,0x0000,0x0000,0x0000, /* 20C3 */ +0xFBC0,0xA0C4,0x0000,0x0000,0x0000, /* 20C4 */ +0xFBC0,0xA0C5,0x0000,0x0000,0x0000, /* 20C5 */ +0xFBC0,0xA0C6,0x0000,0x0000,0x0000, /* 20C6 */ +0xFBC0,0xA0C7,0x0000,0x0000,0x0000, /* 20C7 */ +0xFBC0,0xA0C8,0x0000,0x0000,0x0000, /* 20C8 */ +0xFBC0,0xA0C9,0x0000,0x0000,0x0000, /* 20C9 */ +0xFBC0,0xA0CA,0x0000,0x0000,0x0000, /* 20CA */ +0xFBC0,0xA0CB,0x0000,0x0000,0x0000, /* 20CB */ +0xFBC0,0xA0CC,0x0000,0x0000,0x0000, /* 20CC */ +0xFBC0,0xA0CD,0x0000,0x0000,0x0000, /* 20CD */ +0xFBC0,0xA0CE,0x0000,0x0000,0x0000, /* 20CE */ +0xFBC0,0xA0CF,0x0000,0x0000,0x0000, /* 20CF */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20D0 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20D1 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20D2 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20D3 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20D4 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20D5 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20D6 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20D7 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20D8 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20D9 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20DA */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20DB */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20DC */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20DD */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20DE */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20DF */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20E0 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20E1 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20E2 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20E3 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20E4 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20E5 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20E6 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20E7 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20E8 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20E9 */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20EA */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20EB */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20EC */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20ED */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20EE */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20EF */ +0x0000,0x0000,0x0000,0x0000,0x0000, /* 20F0 */ +0xFBC0,0xA0F1,0x0000,0x0000,0x0000, /* 20F1 */ +0xFBC0,0xA0F2,0x0000,0x0000,0x0000, /* 20F2 */ +0xFBC0,0xA0F3,0x0000,0x0000,0x0000, /* 20F3 */ +0xFBC0,0xA0F4,0x0000,0x0000,0x0000, /* 20F4 */ +0xFBC0,0xA0F5,0x0000,0x0000,0x0000, /* 20F5 */ +0xFBC0,0xA0F6,0x0000,0x0000,0x0000, /* 20F6 */ +0xFBC0,0xA0F7,0x0000,0x0000,0x0000, /* 20F7 */ +0xFBC0,0xA0F8,0x0000,0x0000,0x0000, /* 20F8 */ +0xFBC0,0xA0F9,0x0000,0x0000,0x0000, /* 20F9 */ +0xFBC0,0xA0FA,0x0000,0x0000,0x0000, /* 20FA */ +0xFBC0,0xA0FB,0x0000,0x0000,0x0000, /* 20FB */ +0xFBC0,0xA0FC,0x0000,0x0000,0x0000, /* 20FC */ +0xFBC0,0xA0FD,0x0000,0x0000,0x0000, /* 20FD */ +0xFBC0,0xA0FE,0x0000,0x0000,0x0000, /* 20FE */ +0xFBC0,0xA0FF,0x0000,0x0000,0x0000 /* 20FF */ +}; + +uint16 uca520_p021[]= { /* 2100 (5 weights per char) */ +0x120F,0x035C,0x123D,0x0000,0x0000, /* 2100 */ +0x120F,0x035C,0x1410,0x0000,0x0000, /* 2101 */ +0x123D,0x0000,0x0000,0x0000,0x0000, /* 2102 */ +0x044B,0x123D,0x0000,0x0000,0x0000, /* 2103 */ +0x04C1,0x0000,0x0000,0x0000,0x0000, /* 2104 */ +0x123D,0x035C,0x138E,0x0000,0x0000, /* 2105 */ +0x123D,0x035C,0x1453,0x0000,0x0000, /* 2106 */ +0x1280,0x0000,0x0000,0x0000,0x0000, /* 2107 */ +0x04C2,0x0000,0x0000,0x0000,0x0000, /* 2108 */ +0x044B,0x12A3,0x0000,0x0000,0x0000, /* 2109 */ +0x12B0,0x0000,0x0000,0x0000,0x0000, /* 210A */ +0x12D3,0x0000,0x0000,0x0000,0x0000, /* 210B */ +0x12D3,0x0000,0x0000,0x0000,0x0000, /* 210C */ +0x12D3,0x0000,0x0000,0x0000,0x0000, /* 210D */ +0x12D3,0x0000,0x0000,0x0000,0x0000, /* 210E */ +0x12D3,0x0000,0x0000,0x0000,0x0000, /* 210F */ +0x12EC,0x0000,0x0000,0x0000,0x0000, /* 2110 */ +0x12EC,0x0000,0x0000,0x0000,0x0000, /* 2111 */ +0x1330,0x0000,0x0000,0x0000,0x0000, /* 2112 */ +0x1330,0x0000,0x0000,0x0000,0x0000, /* 2113 */ +0x04C3,0x0000,0x0000,0x0000,0x0000, /* 2114 */ +0x136D,0x0000,0x0000,0x0000,0x0000, /* 2115 */ +0x136D,0x138E,0x0000,0x0000,0x0000, /* 2116 */ +0x04C4,0x0000,0x0000,0x0000,0x0000, /* 2117 */ +0x04C5,0x0000,0x0000,0x0000,0x0000, /* 2118 */ +0x13B3,0x0000,0x0000,0x0000,0x0000, /* 2119 */ +0x13C8,0x0000,0x0000,0x0000,0x0000, /* 211A */ +0x13DA,0x0000,0x0000,0x0000,0x0000, /* 211B */ +0x13DA,0x0000,0x0000,0x0000,0x0000, /* 211C */ +0x13DA,0x0000,0x0000,0x0000,0x0000, /* 211D */ +0x04C6,0x0000,0x0000,0x0000,0x0000, /* 211E */ +0x04C7,0x0000,0x0000,0x0000,0x0000, /* 211F */ +0x1410,0x135F,0x0000,0x0000,0x0000, /* 2120 */ +0x1433,0x126B,0x1330,0x0000,0x0000, /* 2121 */ +0x1433,0x135F,0x0000,0x0000,0x0000, /* 2122 */ +0x04C8,0x0000,0x0000,0x0000,0x0000, /* 2123 */ +0x14AD,0x0000,0x0000,0x0000,0x0000, /* 2124 */ +0x04C9,0x0000,0x0000,0x0000,0x0000, /* 2125 */ +0x156D,0x0000,0x0000,0x0000,0x0000, /* 2126 */ +0x04CA,0x0000,0x0000,0x0000,0x0000, /* 2127 */ +0x14AD,0x0000,0x0000,0x0000,0x0000, /* 2128 */ +0x04CB,0x0000,0x0000,0x0000,0x0000, /* 2129 */ +0x131E,0x0000,0x0000,0x0000,0x0000, /* 212A */ +0x120F,0x0000,0x0000,0x0000,0x0000, /* 212B */ +0x1225,0x0000,0x0000,0x0000,0x0000, /* 212C */ +0x123D,0x0000,0x0000,0x0000,0x0000, /* 212D */ +0x04CC,0x0000,0x0000,0x0000,0x0000, /* 212E */ +0x126B,0x0000,0x0000,0x0000,0x0000, /* 212F */ +0x126B,0x0000,0x0000,0x0000,0x0000, /* 2130 */ +0x12A3,0x0000,0x0000,0x0000,0x0000, /* 2131 */ +0x12AE,0x0000,0x0000,0x0000,0x0000, /* 2132 */ +0x135F,0x0000,0x0000,0x0000,0x0000, /* 2133 */ +0x138E,0x0000,0x0000,0x0000,0x0000, /* 2134 */ +0x185C,0x0000,0x0000,0x0000,0x0000, /* 2135 */ +0x185D,0x0000,0x0000,0x0000,0x0000, /* 2136 */ +0x185E,0x0000,0x0000,0x0000,0x0000, /* 2137 */ +0x185F,0x0000,0x0000,0x0000,0x0000, /* 2138 */ +0x12EC,0x0000,0x0000,0x0000,0x0000, /* 2139 */ +0x04CD,0x0000,0x0000,0x0000,0x0000, /* 213A */ +0x12A3,0x120F,0x1497,0x0000,0x0000, /* 213B */ +0x155B,0x0000,0x0000,0x0000,0x0000, /* 213C */ +0x1547,0x0000,0x0000,0x0000,0x0000, /* 213D */ +0x1547,0x0000,0x0000,0x0000,0x0000, /* 213E */ +0x155B,0x0000,0x0000,0x0000,0x0000, /* 213F */ +0x054F,0x0000,0x0000,0x0000,0x0000, /* 2140 */ +0x04CE,0x0000,0x0000,0x0000,0x0000, /* 2141 */ +0x04CF,0x0000,0x0000,0x0000,0x0000, /* 2142 */ +0x04D0,0x0000,0x0000,0x0000,0x0000, /* 2143 */ +0x04D1,0x0000,0x0000,0x0000,0x0000, /* 2144 */ +0x1250,0x0000,0x0000,0x0000,0x0000, /* 2145 */ +0x1250,0x0000,0x0000,0x0000,0x0000, /* 2146 */ +0x126B,0x0000,0x0000,0x0000,0x0000, /* 2147 */ +0x12EC,0x0000,0x0000,0x0000,0x0000, /* 2148 */ +0x1305,0x0000,0x0000,0x0000,0x0000, /* 2149 */ +0x04D2,0x0000,0x0000,0x0000,0x0000, /* 214A */ +0x0360,0x0000,0x0000,0x0000,0x0000, /* 214B */ +0x04D3,0x0000,0x0000,0x0000,0x0000, /* 214C */ +0x04D4,0x0000,0x0000,0x0000,0x0000, /* 214D */ +0x12AE,0x0000,0x0000,0x0000,0x0000, /* 214E */ +0x04D5,0x0000,0x0000,0x0000,0x0000, /* 214F */ +0x1206,0x035D,0x120C,0x0000,0x0000, /* 2150 */ +0x1206,0x035D,0x120E,0x0000,0x0000, /* 2151 */ +0x1206,0x035D,0x1206,0x1205,0x0000, /* 2152 */ +0x1206,0x035D,0x1208,0x0000,0x0000, /* 2153 */ +0x1207,0x035D,0x1208,0x0000,0x0000, /* 2154 */ +0x1206,0x035D,0x120A,0x0000,0x0000, /* 2155 */ +0x1207,0x035D,0x120A,0x0000,0x0000, /* 2156 */ +0x1208,0x035D,0x120A,0x0000,0x0000, /* 2157 */ +0x1209,0x035D,0x120A,0x0000,0x0000, /* 2158 */ +0x1206,0x035D,0x120B,0x0000,0x0000, /* 2159 */ +0x120A,0x035D,0x120B,0x0000,0x0000, /* 215A */ +0x1206,0x035D,0x120D,0x0000,0x0000, /* 215B */ +0x1208,0x035D,0x120D,0x0000,0x0000, /* 215C */ +0x120A,0x035D,0x120D,0x0000,0x0000, /* 215D */ +0x120C,0x035D,0x120D,0x0000,0x0000, /* 215E */ +0x1206,0x035D,0x0000,0x0000,0x0000, /* 215F */ +0x12EC,0x0000,0x0000,0x0000,0x0000, /* 2160 */ +0x12EC,0x12EC,0x0000,0x0000,0x0000, /* 2161 */ +0x12EC,0x12EC,0x12EC,0x0000,0x0000, /* 2162 */ +0x12EC,0x147B,0x0000,0x0000,0x0000, /* 2163 */ +0x147B,0x0000,0x0000,0x0000,0x0000, /* 2164 */ +0x147B,0x12EC,0x0000,0x0000,0x0000, /* 2165 */ +0x147B,0x12EC,0x12EC,0x0000,0x0000, /* 2166 */ +0x147B,0x12EC,0x12EC,0x12EC,0x0000, /* 2167 */ +0x12EC,0x1497,0x0000,0x0000,0x0000, /* 2168 */ +0x1497,0x0000,0x0000,0x0000,0x0000, /* 2169 */ +0x1497,0x12EC,0x0000,0x0000,0x0000, /* 216A */ +0x1497,0x12EC,0x12EC,0x0000,0x0000, /* 216B */ +0x1330,0x0000,0x0000,0x0000,0x0000, /* 216C */ +0x123D,0x0000,0x0000,0x0000,0x0000, /* 216D */ +0x1250,0x0000,0x0000,0x0000,0x0000, /* 216E */ +0x135F,0x0000,0x0000,0x0000,0x0000, /* 216F */ +0x12EC,0x0000,0x0000,0x0000,0x0000, /* 2170 */ +0x12EC,0x12EC,0x0000,0x0000,0x0000, /* 2171 */ +0x12EC,0x12EC,0x12EC,0x0000,0x0000, /* 2172 */ +0x12EC,0x147B,0x0000,0x0000,0x0000, /* 2173 */ +0x147B,0x0000,0x0000,0x0000,0x0000, /* 2174 */ +0x147B,0x12EC,0x0000,0x0000,0x0000, /* 2175 */ +0x147B,0x12EC,0x12EC,0x0000,0x0000, /* 2176 */ +0x147B,0x12EC,0x12EC,0x12EC,0x0000, /* 2177 */ +0x12EC,0x1497,0x0000,0x0000,0x0000, /* 2178 */ +0x1497,0x0000,0x0000,0x0000,0x0000, /* 2179 */ +0x1497,0x12EC,0x0000,0x0000,0x0000, /* 217A */ +0x1497,0x12EC,0x12EC,0x0000,0x0000, /* 217B */ +0x1330,0x0000,0x0000,0x0000,0x0000, /* 217C */ +0x123D,0x0000,0x0000,0x0000,0x0000, /* 217D */ +0x1250,0x0000,0x0000,0x0000,0x0000, /* 217E */ +0x135F,0x0000,0x0000,0x0000,0x0000, /* 217F */ +0x1130,0x0000,0x0000,0x0000,0x0000, /* 2180 */ +0x1131,0x0000,0x0000,0x0000,0x0000, /* 2181 */ +0x1132,0x0000,0x0000,0x0000,0x0000, /* 2182 */ +0x124E,0x0000,0x0000,0x0000,0x0000, /* 2183 */ +0x124E,0x0000,0x0000,0x0000,0x0000, /* 2184 */ +0x120B,0x0000,0x0000,0x0000,0x0000, /* 2185 */ +0x1133,0x0000,0x0000,0x0000,0x0000, /* 2186 */ +0x1134,0x0000,0x0000,0x0000,0x0000, /* 2187 */ +0x1135,0x0000,0x0000,0x0000,0x0000, /* 2188 */ +0x1205,0x035D,0x1208,0x0000,0x0000, /* 2189 */ +0xFBC0,0xA18A,0x0000,0x0000,0x0000, /* 218A */ +0xFBC0,0xA18B,0x0000,0x0000,0x0000, /* 218B */ +0xFBC0,0xA18C,0x0000,0x0000,0x0000, /* 218C */ +0xFBC0,0xA18D,0x0000,0x0000,0x0000, /* 218D */ +0xFBC0,0xA18E,0x0000,0x0000,0x0000, /* 218E */ +0xFBC0,0xA18F,0x0000,0x0000,0x0000, /* 218F */ +0x04D6,0x0000,0x0000,0x0000,0x0000, /* 2190 */ +0x04D8,0x0000,0x0000,0x0000,0x0000, /* 2191 */ +0x04D7,0x0000,0x0000,0x0000,0x0000, /* 2192 */ +0x04D9,0x0000,0x0000,0x0000,0x0000, /* 2193 */ +0x04DA,0x0000,0x0000,0x0000,0x0000, /* 2194 */ +0x04DB,0x0000,0x0000,0x0000,0x0000, /* 2195 */ +0x04DC,0x0000,0x0000,0x0000,0x0000, /* 2196 */ +0x04DD,0x0000,0x0000,0x0000,0x0000, /* 2197 */ +0x04DE,0x0000,0x0000,0x0000,0x0000, /* 2198 */ +0x04DF,0x0000,0x0000,0x0000,0x0000, /* 2199 */ +0x04D6,0x0000,0x0000,0x0000,0x0000, /* 219A */ +0x04D7,0x0000,0x0000,0x0000,0x0000, /* 219B */ +0x04E0,0x0000,0x0000,0x0000,0x0000, /* 219C */ +0x04E1,0x0000,0x0000,0x0000,0x0000, /* 219D */ +0x04E2,0x0000,0x0000,0x0000,0x0000, /* 219E */ +0x04E3,0x0000,0x0000,0x0000,0x0000, /* 219F */ +0x04E4,0x0000,0x0000,0x0000,0x0000, /* 21A0 */ +0x04E5,0x0000,0x0000,0x0000,0x0000, /* 21A1 */ +0x04E6,0x0000,0x0000,0x0000,0x0000, /* 21A2 */ +0x04E7,0x0000,0x0000,0x0000,0x0000, /* 21A3 */ +0x04E8,0x0000,0x0000,0x0000,0x0000, /* 21A4 */ +0x04E9,0x0000,0x0000,0x0000,0x0000, /* 21A5 */ +0x04EA,0x0000,0x0000,0x0000,0x0000, /* 21A6 */ +0x04EB,0x0000,0x0000,0x0000,0x0000, /* 21A7 */ +0x04EC,0x0000,0x0000,0x0000,0x0000, /* 21A8 */ +0x04ED,0x0000,0x0000,0x0000,0x0000, /* 21A9 */ +0x04EE,0x0000,0x0000,0x0000,0x0000, /* 21AA */ +0x04EF,0x0000,0x0000,0x0000,0x0000, /* 21AB */ +0x04F0,0x0000,0x0000,0x0000,0x0000, /* 21AC */ +0x04F1,0x0000,0x0000,0x0000,0x0000, /* 21AD */ +0x04DA,0x0000,0x0000,0x0000,0x0000, /* 21AE */ +0x04F2,0x0000,0x0000,0x0000,0x0000, /* 21AF */ +0x04F3,0x0000,0x0000,0x0000,0x0000, /* 21B0 */ +0x04F4,0x0000,0x0000,0x0000,0x0000, /* 21B1 */ +0x04F5,0x0000,0x0000,0x0000,0x0000, /* 21B2 */ +0x04F6,0x0000,0x0000,0x0000,0x0000, /* 21B3 */ +0x04F7,0x0000,0x0000,0x0000,0x0000, /* 21B4 */ +0x04F8,0x0000,0x0000,0x0000,0x0000, /* 21B5 */ +0x04F9,0x0000,0x0000,0x0000,0x0000, /* 21B6 */ +0x04FA,0x0000,0x0000,0x0000,0x0000, /* 21B7 */ +0x04FB,0x0000,0x0000,0x0000,0x0000, /* 21B8 */ +0x04FC,0x0000,0x0000,0x0000,0x0000, /* 21B9 */ +0x04FD,0x0000,0x0000,0x0000,0x0000, /* 21BA */ +0x04FE,0x0000,0x0000,0x0000,0x0000, /* 21BB */ +0x04FF,0x0000,0x0000,0x0000,0x0000, /* 21BC */ +0x0500,0x0000,0x0000,0x0000,0x0000, /* 21BD */ +0x0501,0x0000,0x0000,0x0000,0x0000, /* 21BE */ +0x0502,0x0000,0x0000,0x0000,0x0000, /* 21BF */ +0x0503,0x0000,0x0000,0x0000,0x0000, /* 21C0 */ +0x0504,0x0000,0x0000,0x0000,0x0000, /* 21C1 */ +0x0505,0x0000,0x0000,0x0000,0x0000, /* 21C2 */ +0x0506,0x0000,0x0000,0x0000,0x0000, /* 21C3 */ +0x0507,0x0000,0x0000,0x0000,0x0000, /* 21C4 */ +0x0508,0x0000,0x0000,0x0000,0x0000, /* 21C5 */ +0x0509,0x0000,0x0000,0x0000,0x0000, /* 21C6 */ +0x050A,0x0000,0x0000,0x0000,0x0000, /* 21C7 */ +0x050B,0x0000,0x0000,0x0000,0x0000, /* 21C8 */ +0x050C,0x0000,0x0000,0x0000,0x0000, /* 21C9 */ +0x050D,0x0000,0x0000,0x0000,0x0000, /* 21CA */ +0x050E,0x0000,0x0000,0x0000,0x0000, /* 21CB */ +0x050F,0x0000,0x0000,0x0000,0x0000, /* 21CC */ +0x0510,0x0000,0x0000,0x0000,0x0000, /* 21CD */ +0x0514,0x0000,0x0000,0x0000,0x0000, /* 21CE */ +0x0512,0x0000,0x0000,0x0000,0x0000, /* 21CF */ +0x0510,0x0000,0x0000,0x0000,0x0000, /* 21D0 */ +0x0511,0x0000,0x0000,0x0000,0x0000, /* 21D1 */ +0x0512,0x0000,0x0000,0x0000,0x0000, /* 21D2 */ +0x0513,0x0000,0x0000,0x0000,0x0000, /* 21D3 */ +0x0514,0x0000,0x0000,0x0000,0x0000, /* 21D4 */ +0x0515,0x0000,0x0000,0x0000,0x0000, /* 21D5 */ +0x0516,0x0000,0x0000,0x0000,0x0000, /* 21D6 */ +0x0517,0x0000,0x0000,0x0000,0x0000, /* 21D7 */ +0x0518,0x0000,0x0000,0x0000,0x0000, /* 21D8 */ +0x0519,0x0000,0x0000,0x0000,0x0000, /* 21D9 */ +0x051A,0x0000,0x0000,0x0000,0x0000, /* 21DA */ +0x051B,0x0000,0x0000,0x0000,0x0000, /* 21DB */ +0x051C,0x0000,0x0000,0x0000,0x0000, /* 21DC */ +0x051D,0x0000,0x0000,0x0000,0x0000, /* 21DD */ +0x051E,0x0000,0x0000,0x0000,0x0000, /* 21DE */ +0x051F,0x0000,0x0000,0x0000,0x0000, /* 21DF */ +0x0520,0x0000,0x0000,0x0000,0x0000, /* 21E0 */ +0x0521,0x0000,0x0000,0x0000,0x0000, /* 21E1 */ +0x0522,0x0000,0x0000,0x0000,0x0000, /* 21E2 */ +0x0523,0x0000,0x0000,0x0000,0x0000, /* 21E3 */ +0x0524,0x0000,0x0000,0x0000,0x0000, /* 21E4 */ +0x0525,0x0000,0x0000,0x0000,0x0000, /* 21E5 */ +0x0526,0x0000,0x0000,0x0000,0x0000, /* 21E6 */ +0x0527,0x0000,0x0000,0x0000,0x0000, /* 21E7 */ +0x0528,0x0000,0x0000,0x0000,0x0000, /* 21E8 */ +0x0529,0x0000,0x0000,0x0000,0x0000, /* 21E9 */ +0x052A,0x0000,0x0000,0x0000,0x0000, /* 21EA */ +0x052B,0x0000,0x0000,0x0000,0x0000, /* 21EB */ +0x052C,0x0000,0x0000,0x0000,0x0000, /* 21EC */ +0x052D,0x0000,0x0000,0x0000,0x0000, /* 21ED */ +0x052E,0x0000,0x0000,0x0000,0x0000, /* 21EE */ +0x052F,0x0000,0x0000,0x0000,0x0000, /* 21EF */ +0x0530,0x0000,0x0000,0x0000,0x0000, /* 21F0 */ +0x0531,0x0000,0x0000,0x0000,0x0000, /* 21F1 */ +0x0532,0x0000,0x0000,0x0000,0x0000, /* 21F2 */ +0x0533,0x0000,0x0000,0x0000,0x0000, /* 21F3 */ +0x0534,0x0000,0x0000,0x0000,0x0000, /* 21F4 */ +0x0535,0x0000,0x0000,0x0000,0x0000, /* 21F5 */ +0x0536,0x0000,0x0000,0x0000,0x0000, /* 21F6 */ +0x0537,0x0000,0x0000,0x0000,0x0000, /* 21F7 */ +0x0538,0x0000,0x0000,0x0000,0x0000, /* 21F8 */ +0x0539,0x0000,0x0000,0x0000,0x0000, /* 21F9 */ +0x053A,0x0000,0x0000,0x0000,0x0000, /* 21FA */ +0x053B,0x0000,0x0000,0x0000,0x0000, /* 21FB */ +0x053C,0x0000,0x0000,0x0000,0x0000, /* 21FC */ +0x053D,0x0000,0x0000,0x0000,0x0000, /* 21FD */ +0x053E,0x0000,0x0000,0x0000,0x0000, /* 21FE */ +0x053F,0x0000,0x0000,0x0000,0x0000 /* 21FF */ +}; + +uint16 uca520_p022[]= { /* 2200 (4 weights per char) */ +0x0540,0x0000,0x0000,0x0000, 0x0541,0x0000,0x0000,0x0000, /* 2200 */ +0x0542,0x0000,0x0000,0x0000, 0x0543,0x0000,0x0000,0x0000, /* 2202 */ +0x0543,0x0000,0x0000,0x0000, 0x0544,0x0000,0x0000,0x0000, /* 2204 */ +0x0545,0x0000,0x0000,0x0000, 0x0546,0x0000,0x0000,0x0000, /* 2206 */ +0x0547,0x0000,0x0000,0x0000, 0x0547,0x0000,0x0000,0x0000, /* 2208 */ +0x0548,0x0000,0x0000,0x0000, 0x0549,0x0000,0x0000,0x0000, /* 220A */ +0x0549,0x0000,0x0000,0x0000, 0x054A,0x0000,0x0000,0x0000, /* 220C */ +0x054C,0x0000,0x0000,0x0000, 0x054D,0x0000,0x0000,0x0000, /* 220E */ +0x054E,0x0000,0x0000,0x0000, 0x054F,0x0000,0x0000,0x0000, /* 2210 */ +0x055C,0x0000,0x0000,0x0000, 0x055D,0x0000,0x0000,0x0000, /* 2212 */ +0x055E,0x0000,0x0000,0x0000, 0x055F,0x0000,0x0000,0x0000, /* 2214 */ +0x0560,0x0000,0x0000,0x0000, 0x0561,0x0000,0x0000,0x0000, /* 2216 */ +0x0562,0x0000,0x0000,0x0000, 0x0563,0x0000,0x0000,0x0000, /* 2218 */ +0x0564,0x0000,0x0000,0x0000, 0x0565,0x0000,0x0000,0x0000, /* 221A */ +0x0567,0x0000,0x0000,0x0000, 0x0569,0x0000,0x0000,0x0000, /* 221C */ +0x056A,0x0000,0x0000,0x0000, 0x056B,0x0000,0x0000,0x0000, /* 221E */ +0x056C,0x0000,0x0000,0x0000, 0x056D,0x0000,0x0000,0x0000, /* 2220 */ +0x056E,0x0000,0x0000,0x0000, 0x056F,0x0000,0x0000,0x0000, /* 2222 */ +0x056F,0x0000,0x0000,0x0000, 0x0570,0x0000,0x0000,0x0000, /* 2224 */ +0x0570,0x0000,0x0000,0x0000, 0x0571,0x0000,0x0000,0x0000, /* 2226 */ +0x0572,0x0000,0x0000,0x0000, 0x0573,0x0000,0x0000,0x0000, /* 2228 */ +0x0574,0x0000,0x0000,0x0000, 0x0575,0x0000,0x0000,0x0000, /* 222A */ +0x0575,0x0575,0x0000,0x0000, 0x0575,0x0575,0x0575,0x0000, /* 222C */ +0x0576,0x0000,0x0000,0x0000, 0x0576,0x0576,0x0000,0x0000, /* 222E */ +0x0576,0x0576,0x0576,0x0000, 0x0577,0x0000,0x0000,0x0000, /* 2230 */ +0x0578,0x0000,0x0000,0x0000, 0x0579,0x0000,0x0000,0x0000, /* 2232 */ +0x057A,0x0000,0x0000,0x0000, 0x057B,0x0000,0x0000,0x0000, /* 2234 */ +0x057C,0x0000,0x0000,0x0000, 0x057D,0x0000,0x0000,0x0000, /* 2236 */ +0x057E,0x0000,0x0000,0x0000, 0x057F,0x0000,0x0000,0x0000, /* 2238 */ +0x0580,0x0000,0x0000,0x0000, 0x0581,0x0000,0x0000,0x0000, /* 223A */ +0x0582,0x0000,0x0000,0x0000, 0x0583,0x0000,0x0000,0x0000, /* 223C */ +0x0584,0x0000,0x0000,0x0000, 0x0585,0x0000,0x0000,0x0000, /* 223E */ +0x0586,0x0000,0x0000,0x0000, 0x0582,0x0000,0x0000,0x0000, /* 2240 */ +0x0587,0x0000,0x0000,0x0000, 0x0588,0x0000,0x0000,0x0000, /* 2242 */ +0x0588,0x0000,0x0000,0x0000, 0x0589,0x0000,0x0000,0x0000, /* 2244 */ +0x058A,0x0000,0x0000,0x0000, 0x0589,0x0000,0x0000,0x0000, /* 2246 */ +0x058B,0x0000,0x0000,0x0000, 0x058B,0x0000,0x0000,0x0000, /* 2248 */ +0x058C,0x0000,0x0000,0x0000, 0x058D,0x0000,0x0000,0x0000, /* 224A */ +0x058E,0x0000,0x0000,0x0000, 0x058F,0x0000,0x0000,0x0000, /* 224C */ +0x0590,0x0000,0x0000,0x0000, 0x0591,0x0000,0x0000,0x0000, /* 224E */ +0x0592,0x0000,0x0000,0x0000, 0x0593,0x0000,0x0000,0x0000, /* 2250 */ +0x0594,0x0000,0x0000,0x0000, 0x0595,0x0000,0x0000,0x0000, /* 2252 */ +0x0596,0x0000,0x0000,0x0000, 0x0597,0x0000,0x0000,0x0000, /* 2254 */ +0x0598,0x0000,0x0000,0x0000, 0x0599,0x0000,0x0000,0x0000, /* 2256 */ +0x059A,0x0000,0x0000,0x0000, 0x059B,0x0000,0x0000,0x0000, /* 2258 */ +0x059C,0x0000,0x0000,0x0000, 0x059D,0x0000,0x0000,0x0000, /* 225A */ +0x059E,0x0000,0x0000,0x0000, 0x059F,0x0000,0x0000,0x0000, /* 225C */ +0x05A0,0x0000,0x0000,0x0000, 0x05A1,0x0000,0x0000,0x0000, /* 225E */ +0x0555,0x0000,0x0000,0x0000, 0x05A2,0x0000,0x0000,0x0000, /* 2260 */ +0x05A2,0x0000,0x0000,0x0000, 0x05A3,0x0000,0x0000,0x0000, /* 2262 */ +0x05A4,0x0000,0x0000,0x0000, 0x05A5,0x0000,0x0000,0x0000, /* 2264 */ +0x05A6,0x0000,0x0000,0x0000, 0x05A7,0x0000,0x0000,0x0000, /* 2266 */ +0x05A8,0x0000,0x0000,0x0000, 0x05A9,0x0000,0x0000,0x0000, /* 2268 */ +0x05AA,0x0000,0x0000,0x0000, 0x05AB,0x0000,0x0000,0x0000, /* 226A */ +0x05AC,0x0000,0x0000,0x0000, 0x058F,0x0000,0x0000,0x0000, /* 226C */ +0x0554,0x0000,0x0000,0x0000, 0x0556,0x0000,0x0000,0x0000, /* 226E */ +0x05A4,0x0000,0x0000,0x0000, 0x05A5,0x0000,0x0000,0x0000, /* 2270 */ +0x05AD,0x0000,0x0000,0x0000, 0x05AE,0x0000,0x0000,0x0000, /* 2272 */ +0x05AD,0x0000,0x0000,0x0000, 0x05AE,0x0000,0x0000,0x0000, /* 2274 */ +0x05AF,0x0000,0x0000,0x0000, 0x05B0,0x0000,0x0000,0x0000, /* 2276 */ +0x05AF,0x0000,0x0000,0x0000, 0x05B0,0x0000,0x0000,0x0000, /* 2278 */ +0x05B1,0x0000,0x0000,0x0000, 0x05B2,0x0000,0x0000,0x0000, /* 227A */ +0x05B3,0x0000,0x0000,0x0000, 0x05B4,0x0000,0x0000,0x0000, /* 227C */ +0x05B5,0x0000,0x0000,0x0000, 0x05B6,0x0000,0x0000,0x0000, /* 227E */ +0x05B1,0x0000,0x0000,0x0000, 0x05B2,0x0000,0x0000,0x0000, /* 2280 */ +0x05B7,0x0000,0x0000,0x0000, 0x05B8,0x0000,0x0000,0x0000, /* 2282 */ +0x05B7,0x0000,0x0000,0x0000, 0x05B8,0x0000,0x0000,0x0000, /* 2284 */ +0x05B9,0x0000,0x0000,0x0000, 0x05BA,0x0000,0x0000,0x0000, /* 2286 */ +0x05B9,0x0000,0x0000,0x0000, 0x05BA,0x0000,0x0000,0x0000, /* 2288 */ +0x05BB,0x0000,0x0000,0x0000, 0x05BC,0x0000,0x0000,0x0000, /* 228A */ +0x05BD,0x0000,0x0000,0x0000, 0x05BE,0x0000,0x0000,0x0000, /* 228C */ +0x05BF,0x0000,0x0000,0x0000, 0x05C0,0x0000,0x0000,0x0000, /* 228E */ +0x05C1,0x0000,0x0000,0x0000, 0x05C2,0x0000,0x0000,0x0000, /* 2290 */ +0x05C3,0x0000,0x0000,0x0000, 0x05C4,0x0000,0x0000,0x0000, /* 2292 */ +0x05C5,0x0000,0x0000,0x0000, 0x05C6,0x0000,0x0000,0x0000, /* 2294 */ +0x05C7,0x0000,0x0000,0x0000, 0x05C8,0x0000,0x0000,0x0000, /* 2296 */ +0x05C9,0x0000,0x0000,0x0000, 0x05CA,0x0000,0x0000,0x0000, /* 2298 */ +0x05CB,0x0000,0x0000,0x0000, 0x05CC,0x0000,0x0000,0x0000, /* 229A */ +0x05CD,0x0000,0x0000,0x0000, 0x05CE,0x0000,0x0000,0x0000, /* 229C */ +0x05CF,0x0000,0x0000,0x0000, 0x05D0,0x0000,0x0000,0x0000, /* 229E */ +0x05D1,0x0000,0x0000,0x0000, 0x05D2,0x0000,0x0000,0x0000, /* 22A0 */ +0x05D3,0x0000,0x0000,0x0000, 0x05D4,0x0000,0x0000,0x0000, /* 22A2 */ +0x05D5,0x0000,0x0000,0x0000, 0x05D6,0x0000,0x0000,0x0000, /* 22A4 */ +0x05D7,0x0000,0x0000,0x0000, 0x05D8,0x0000,0x0000,0x0000, /* 22A6 */ +0x05D9,0x0000,0x0000,0x0000, 0x05DA,0x0000,0x0000,0x0000, /* 22A8 */ +0x05DB,0x0000,0x0000,0x0000, 0x05DC,0x0000,0x0000,0x0000, /* 22AA */ +0x05D3,0x0000,0x0000,0x0000, 0x05D9,0x0000,0x0000,0x0000, /* 22AC */ +0x05DA,0x0000,0x0000,0x0000, 0x05DC,0x0000,0x0000,0x0000, /* 22AE */ +0x05DD,0x0000,0x0000,0x0000, 0x05DE,0x0000,0x0000,0x0000, /* 22B0 */ +0x05DF,0x0000,0x0000,0x0000, 0x05E0,0x0000,0x0000,0x0000, /* 22B2 */ +0x05E1,0x0000,0x0000,0x0000, 0x05E2,0x0000,0x0000,0x0000, /* 22B4 */ +0x05E3,0x0000,0x0000,0x0000, 0x05E4,0x0000,0x0000,0x0000, /* 22B6 */ +0x05E5,0x0000,0x0000,0x0000, 0x05E6,0x0000,0x0000,0x0000, /* 22B8 */ +0x05E7,0x0000,0x0000,0x0000, 0x05E8,0x0000,0x0000,0x0000, /* 22BA */ +0x05E9,0x0000,0x0000,0x0000, 0x05EA,0x0000,0x0000,0x0000, /* 22BC */ +0x05EB,0x0000,0x0000,0x0000, 0x05EC,0x0000,0x0000,0x0000, /* 22BE */ +0x05ED,0x0000,0x0000,0x0000, 0x05EE,0x0000,0x0000,0x0000, /* 22C0 */ +0x05EF,0x0000,0x0000,0x0000, 0x05F0,0x0000,0x0000,0x0000, /* 22C2 */ +0x05F1,0x0000,0x0000,0x0000, 0x05F2,0x0000,0x0000,0x0000, /* 22C4 */ +0x05F3,0x0000,0x0000,0x0000, 0x05F4,0x0000,0x0000,0x0000, /* 22C6 */ +0x05F5,0x0000,0x0000,0x0000, 0x05F6,0x0000,0x0000,0x0000, /* 22C8 */ +0x05F7,0x0000,0x0000,0x0000, 0x05F8,0x0000,0x0000,0x0000, /* 22CA */ +0x05F9,0x0000,0x0000,0x0000, 0x05FA,0x0000,0x0000,0x0000, /* 22CC */ +0x05FB,0x0000,0x0000,0x0000, 0x05FC,0x0000,0x0000,0x0000, /* 22CE */ +0x05FD,0x0000,0x0000,0x0000, 0x05FE,0x0000,0x0000,0x0000, /* 22D0 */ +0x05FF,0x0000,0x0000,0x0000, 0x0600,0x0000,0x0000,0x0000, /* 22D2 */ +0x0601,0x0000,0x0000,0x0000, 0x0602,0x0000,0x0000,0x0000, /* 22D4 */ +0x0603,0x0000,0x0000,0x0000, 0x0604,0x0000,0x0000,0x0000, /* 22D6 */ +0x0605,0x0000,0x0000,0x0000, 0x0606,0x0000,0x0000,0x0000, /* 22D8 */ +0x0607,0x0000,0x0000,0x0000, 0x0608,0x0000,0x0000,0x0000, /* 22DA */ +0x0609,0x0000,0x0000,0x0000, 0x060A,0x0000,0x0000,0x0000, /* 22DC */ +0x060B,0x0000,0x0000,0x0000, 0x060C,0x0000,0x0000,0x0000, /* 22DE */ +0x05B3,0x0000,0x0000,0x0000, 0x05B4,0x0000,0x0000,0x0000, /* 22E0 */ +0x05C2,0x0000,0x0000,0x0000, 0x05C3,0x0000,0x0000,0x0000, /* 22E2 */ +0x060D,0x0000,0x0000,0x0000, 0x060E,0x0000,0x0000,0x0000, /* 22E4 */ +0x060F,0x0000,0x0000,0x0000, 0x0610,0x0000,0x0000,0x0000, /* 22E6 */ +0x0611,0x0000,0x0000,0x0000, 0x0612,0x0000,0x0000,0x0000, /* 22E8 */ +0x05DF,0x0000,0x0000,0x0000, 0x05E0,0x0000,0x0000,0x0000, /* 22EA */ +0x05E1,0x0000,0x0000,0x0000, 0x05E2,0x0000,0x0000,0x0000, /* 22EC */ +0x0613,0x0000,0x0000,0x0000, 0x0614,0x0000,0x0000,0x0000, /* 22EE */ +0x0615,0x0000,0x0000,0x0000, 0x0616,0x0000,0x0000,0x0000, /* 22F0 */ +0x0617,0x0000,0x0000,0x0000, 0x0618,0x0000,0x0000,0x0000, /* 22F2 */ +0x0619,0x0000,0x0000,0x0000, 0x061A,0x0000,0x0000,0x0000, /* 22F4 */ +0x061B,0x0000,0x0000,0x0000, 0x061C,0x0000,0x0000,0x0000, /* 22F6 */ +0x061D,0x0000,0x0000,0x0000, 0x061E,0x0000,0x0000,0x0000, /* 22F8 */ +0x061F,0x0000,0x0000,0x0000, 0x0620,0x0000,0x0000,0x0000, /* 22FA */ +0x0621,0x0000,0x0000,0x0000, 0x0622,0x0000,0x0000,0x0000, /* 22FC */ +0x0623,0x0000,0x0000,0x0000, 0x0624,0x0000,0x0000,0x0000 /* 22FE */ +}; + +uint16 uca520_p023[]= { /* 2300 (3 weights per char) */ +0x0625,0x0000,0x0000, 0x0626,0x0000,0x0000, 0x0627,0x0000,0x0000, /* 2300 */ +0x0628,0x0000,0x0000, 0x0629,0x0000,0x0000, 0x062A,0x0000,0x0000, /* 2303 */ +0x062B,0x0000,0x0000, 0x062C,0x0000,0x0000, 0x062D,0x0000,0x0000, /* 2306 */ +0x062E,0x0000,0x0000, 0x062F,0x0000,0x0000, 0x0630,0x0000,0x0000, /* 2309 */ +0x0631,0x0000,0x0000, 0x0632,0x0000,0x0000, 0x0633,0x0000,0x0000, /* 230C */ +0x0634,0x0000,0x0000, 0x0635,0x0000,0x0000, 0x0636,0x0000,0x0000, /* 230F */ +0x0637,0x0000,0x0000, 0x0638,0x0000,0x0000, 0x0639,0x0000,0x0000, /* 2312 */ +0x063A,0x0000,0x0000, 0x063B,0x0000,0x0000, 0x063C,0x0000,0x0000, /* 2315 */ +0x063D,0x0000,0x0000, 0x063E,0x0000,0x0000, 0x063F,0x0000,0x0000, /* 2318 */ +0x0640,0x0000,0x0000, 0x0641,0x0000,0x0000, 0x0642,0x0000,0x0000, /* 231B */ +0x0643,0x0000,0x0000, 0x0644,0x0000,0x0000, 0x0645,0x0000,0x0000, /* 231E */ +0x0646,0x0000,0x0000, 0x0647,0x0000,0x0000, 0x0648,0x0000,0x0000, /* 2321 */ +0x0649,0x0000,0x0000, 0x064A,0x0000,0x0000, 0x064B,0x0000,0x0000, /* 2324 */ +0x064C,0x0000,0x0000, 0x064D,0x0000,0x0000, 0x033D,0x0000,0x0000, /* 2327 */ +0x033E,0x0000,0x0000, 0x064E,0x0000,0x0000, 0x064F,0x0000,0x0000, /* 232A */ +0x0650,0x0000,0x0000, 0x0651,0x0000,0x0000, 0x0652,0x0000,0x0000, /* 232D */ +0x0653,0x0000,0x0000, 0x0654,0x0000,0x0000, 0x0655,0x0000,0x0000, /* 2330 */ +0x0656,0x0000,0x0000, 0x0657,0x0000,0x0000, 0x0658,0x0000,0x0000, /* 2333 */ +0x0659,0x0000,0x0000, 0x065A,0x0000,0x0000, 0x065B,0x0000,0x0000, /* 2336 */ +0x065C,0x0000,0x0000, 0x065D,0x0000,0x0000, 0x065E,0x0000,0x0000, /* 2339 */ +0x065F,0x0000,0x0000, 0x0660,0x0000,0x0000, 0x0661,0x0000,0x0000, /* 233C */ +0x0662,0x0000,0x0000, 0x0663,0x0000,0x0000, 0x0664,0x0000,0x0000, /* 233F */ +0x0665,0x0000,0x0000, 0x0666,0x0000,0x0000, 0x0667,0x0000,0x0000, /* 2342 */ +0x0668,0x0000,0x0000, 0x0669,0x0000,0x0000, 0x066A,0x0000,0x0000, /* 2345 */ +0x066B,0x0000,0x0000, 0x066C,0x0000,0x0000, 0x066D,0x0000,0x0000, /* 2348 */ +0x066E,0x0000,0x0000, 0x066F,0x0000,0x0000, 0x0670,0x0000,0x0000, /* 234B */ +0x0671,0x0000,0x0000, 0x0672,0x0000,0x0000, 0x0673,0x0000,0x0000, /* 234E */ +0x0674,0x0000,0x0000, 0x0675,0x0000,0x0000, 0x0676,0x0000,0x0000, /* 2351 */ +0x0677,0x0000,0x0000, 0x0678,0x0000,0x0000, 0x0679,0x0000,0x0000, /* 2354 */ +0x067A,0x0000,0x0000, 0x067B,0x0000,0x0000, 0x067C,0x0000,0x0000, /* 2357 */ +0x067D,0x0000,0x0000, 0x067E,0x0000,0x0000, 0x067F,0x0000,0x0000, /* 235A */ +0x0680,0x0000,0x0000, 0x0681,0x0000,0x0000, 0x0682,0x0000,0x0000, /* 235D */ +0x0683,0x0000,0x0000, 0x0684,0x0000,0x0000, 0x0685,0x0000,0x0000, /* 2360 */ +0x0686,0x0000,0x0000, 0x0687,0x0000,0x0000, 0x0688,0x0000,0x0000, /* 2363 */ +0x0689,0x0000,0x0000, 0x068A,0x0000,0x0000, 0x068B,0x0000,0x0000, /* 2366 */ +0x068C,0x0000,0x0000, 0x068D,0x0000,0x0000, 0x068E,0x0000,0x0000, /* 2369 */ +0x068F,0x0000,0x0000, 0x0690,0x0000,0x0000, 0x0691,0x0000,0x0000, /* 236C */ +0x0692,0x0000,0x0000, 0x0693,0x0000,0x0000, 0x0694,0x0000,0x0000, /* 236F */ +0x0695,0x0000,0x0000, 0x0696,0x0000,0x0000, 0x0697,0x0000,0x0000, /* 2372 */ +0x0698,0x0000,0x0000, 0x0699,0x0000,0x0000, 0x069A,0x0000,0x0000, /* 2375 */ +0x069B,0x0000,0x0000, 0x069C,0x0000,0x0000, 0x069D,0x0000,0x0000, /* 2378 */ +0x069E,0x0000,0x0000, 0x069F,0x0000,0x0000, 0x06A0,0x0000,0x0000, /* 237B */ +0x06A1,0x0000,0x0000, 0x06A2,0x0000,0x0000, 0x06A3,0x0000,0x0000, /* 237E */ +0x06A4,0x0000,0x0000, 0x06A5,0x0000,0x0000, 0x06A6,0x0000,0x0000, /* 2381 */ +0x06A7,0x0000,0x0000, 0x06A8,0x0000,0x0000, 0x06A9,0x0000,0x0000, /* 2384 */ +0x06AA,0x0000,0x0000, 0x06AB,0x0000,0x0000, 0x06AC,0x0000,0x0000, /* 2387 */ +0x06AD,0x0000,0x0000, 0x06AE,0x0000,0x0000, 0x06AF,0x0000,0x0000, /* 238A */ +0x06B0,0x0000,0x0000, 0x06B1,0x0000,0x0000, 0x06B2,0x0000,0x0000, /* 238D */ +0x06B3,0x0000,0x0000, 0x06B4,0x0000,0x0000, 0x06B5,0x0000,0x0000, /* 2390 */ +0x06B6,0x0000,0x0000, 0x06B7,0x0000,0x0000, 0x06B8,0x0000,0x0000, /* 2393 */ +0x06B9,0x0000,0x0000, 0x06BA,0x0000,0x0000, 0x06BB,0x0000,0x0000, /* 2396 */ +0x06BC,0x0000,0x0000, 0x06BD,0x0000,0x0000, 0x06BE,0x0000,0x0000, /* 2399 */ +0x06BF,0x0000,0x0000, 0x06C0,0x0000,0x0000, 0x06C1,0x0000,0x0000, /* 239C */ +0x06C2,0x0000,0x0000, 0x06C3,0x0000,0x0000, 0x06C4,0x0000,0x0000, /* 239F */ +0x06C5,0x0000,0x0000, 0x06C6,0x0000,0x0000, 0x06C7,0x0000,0x0000, /* 23A2 */ +0x06C8,0x0000,0x0000, 0x06C9,0x0000,0x0000, 0x06CA,0x0000,0x0000, /* 23A5 */ +0x06CB,0x0000,0x0000, 0x06CC,0x0000,0x0000, 0x06CD,0x0000,0x0000, /* 23A8 */ +0x06CE,0x0000,0x0000, 0x06CF,0x0000,0x0000, 0x06D0,0x0000,0x0000, /* 23AB */ +0x06D1,0x0000,0x0000, 0x06D2,0x0000,0x0000, 0x06D3,0x0000,0x0000, /* 23AE */ +0x06D4,0x0000,0x0000, 0x06D5,0x0000,0x0000, 0x06D6,0x0000,0x0000, /* 23B1 */ +0x06D7,0x0000,0x0000, 0x06D8,0x0000,0x0000, 0x06D9,0x0000,0x0000, /* 23B4 */ +0x06DA,0x0000,0x0000, 0x06DB,0x0000,0x0000, 0x06DC,0x0000,0x0000, /* 23B7 */ +0x06DD,0x0000,0x0000, 0x06DE,0x0000,0x0000, 0x06DF,0x0000,0x0000, /* 23BA */ +0x06E0,0x0000,0x0000, 0x06E1,0x0000,0x0000, 0x06E2,0x0000,0x0000, /* 23BD */ +0x06E3,0x0000,0x0000, 0x06E4,0x0000,0x0000, 0x06E5,0x0000,0x0000, /* 23C0 */ +0x06E6,0x0000,0x0000, 0x06E7,0x0000,0x0000, 0x06E8,0x0000,0x0000, /* 23C3 */ +0x06E9,0x0000,0x0000, 0x06EA,0x0000,0x0000, 0x06EB,0x0000,0x0000, /* 23C6 */ +0x06EC,0x0000,0x0000, 0x06ED,0x0000,0x0000, 0x06EE,0x0000,0x0000, /* 23C9 */ +0x06EF,0x0000,0x0000, 0x06F0,0x0000,0x0000, 0x06F1,0x0000,0x0000, /* 23CC */ +0x06F2,0x0000,0x0000, 0x06F3,0x0000,0x0000, 0x06F4,0x0000,0x0000, /* 23CF */ +0x06F5,0x0000,0x0000, 0x06F6,0x0000,0x0000, 0x06F7,0x0000,0x0000, /* 23D2 */ +0x06F8,0x0000,0x0000, 0x06F9,0x0000,0x0000, 0x06FA,0x0000,0x0000, /* 23D5 */ +0x06FB,0x0000,0x0000, 0x06FC,0x0000,0x0000, 0x06FD,0x0000,0x0000, /* 23D8 */ +0x06FE,0x0000,0x0000, 0x06FF,0x0000,0x0000, 0x0700,0x0000,0x0000, /* 23DB */ +0x0701,0x0000,0x0000, 0x0702,0x0000,0x0000, 0x0703,0x0000,0x0000, /* 23DE */ +0x0704,0x0000,0x0000, 0x0705,0x0000,0x0000, 0x0706,0x0000,0x0000, /* 23E1 */ +0x0707,0x0000,0x0000, 0x0708,0x0000,0x0000, 0x0709,0x0000,0x0000, /* 23E4 */ +0x070A,0x0000,0x0000, 0x070B,0x0000,0x0000, 0xFBC0,0xA3E9,0x0000, /* 23E7 */ +0xFBC0,0xA3EA,0x0000, 0xFBC0,0xA3EB,0x0000, 0xFBC0,0xA3EC,0x0000, /* 23EA */ +0xFBC0,0xA3ED,0x0000, 0xFBC0,0xA3EE,0x0000, 0xFBC0,0xA3EF,0x0000, /* 23ED */ +0xFBC0,0xA3F0,0x0000, 0xFBC0,0xA3F1,0x0000, 0xFBC0,0xA3F2,0x0000, /* 23F0 */ +0xFBC0,0xA3F3,0x0000, 0xFBC0,0xA3F4,0x0000, 0xFBC0,0xA3F5,0x0000, /* 23F3 */ +0xFBC0,0xA3F6,0x0000, 0xFBC0,0xA3F7,0x0000, 0xFBC0,0xA3F8,0x0000, /* 23F6 */ +0xFBC0,0xA3F9,0x0000, 0xFBC0,0xA3FA,0x0000, 0xFBC0,0xA3FB,0x0000, /* 23F9 */ +0xFBC0,0xA3FC,0x0000, 0xFBC0,0xA3FD,0x0000, 0xFBC0,0xA3FE,0x0000, /* 23FC */ +0xFBC0,0xA3FF,0x0000 }; + +uint16 uca520_p024[]= { /* 2400 (5 weights per char) */ +0x070C,0x0000,0x0000,0x0000,0x0000, /* 2400 */ +0x070D,0x0000,0x0000,0x0000,0x0000, /* 2401 */ +0x070E,0x0000,0x0000,0x0000,0x0000, /* 2402 */ +0x070F,0x0000,0x0000,0x0000,0x0000, /* 2403 */ +0x0710,0x0000,0x0000,0x0000,0x0000, /* 2404 */ +0x0711,0x0000,0x0000,0x0000,0x0000, /* 2405 */ +0x0712,0x0000,0x0000,0x0000,0x0000, /* 2406 */ +0x0713,0x0000,0x0000,0x0000,0x0000, /* 2407 */ +0x0714,0x0000,0x0000,0x0000,0x0000, /* 2408 */ +0x0715,0x0000,0x0000,0x0000,0x0000, /* 2409 */ +0x0716,0x0000,0x0000,0x0000,0x0000, /* 240A */ +0x0717,0x0000,0x0000,0x0000,0x0000, /* 240B */ +0x0718,0x0000,0x0000,0x0000,0x0000, /* 240C */ +0x0719,0x0000,0x0000,0x0000,0x0000, /* 240D */ +0x071A,0x0000,0x0000,0x0000,0x0000, /* 240E */ +0x071B,0x0000,0x0000,0x0000,0x0000, /* 240F */ +0x071C,0x0000,0x0000,0x0000,0x0000, /* 2410 */ +0x071D,0x0000,0x0000,0x0000,0x0000, /* 2411 */ +0x071E,0x0000,0x0000,0x0000,0x0000, /* 2412 */ +0x071F,0x0000,0x0000,0x0000,0x0000, /* 2413 */ +0x0720,0x0000,0x0000,0x0000,0x0000, /* 2414 */ +0x0721,0x0000,0x0000,0x0000,0x0000, /* 2415 */ +0x0722,0x0000,0x0000,0x0000,0x0000, /* 2416 */ +0x0723,0x0000,0x0000,0x0000,0x0000, /* 2417 */ +0x0724,0x0000,0x0000,0x0000,0x0000, /* 2418 */ +0x0725,0x0000,0x0000,0x0000,0x0000, /* 2419 */ +0x0726,0x0000,0x0000,0x0000,0x0000, /* 241A */ +0x0727,0x0000,0x0000,0x0000,0x0000, /* 241B */ +0x0728,0x0000,0x0000,0x0000,0x0000, /* 241C */ +0x0729,0x0000,0x0000,0x0000,0x0000, /* 241D */ +0x072A,0x0000,0x0000,0x0000,0x0000, /* 241E */ +0x072B,0x0000,0x0000,0x0000,0x0000, /* 241F */ +0x072C,0x0000,0x0000,0x0000,0x0000, /* 2420 */ +0x072D,0x0000,0x0000,0x0000,0x0000, /* 2421 */ +0x072E,0x0000,0x0000,0x0000,0x0000, /* 2422 */ +0x072F,0x0000,0x0000,0x0000,0x0000, /* 2423 */ +0x0730,0x0000,0x0000,0x0000,0x0000, /* 2424 */ +0x0731,0x0000,0x0000,0x0000,0x0000, /* 2425 */ +0x0732,0x0000,0x0000,0x0000,0x0000, /* 2426 */ +0xFBC0,0xA427,0x0000,0x0000,0x0000, /* 2427 */ +0xFBC0,0xA428,0x0000,0x0000,0x0000, /* 2428 */ +0xFBC0,0xA429,0x0000,0x0000,0x0000, /* 2429 */ +0xFBC0,0xA42A,0x0000,0x0000,0x0000, /* 242A */ +0xFBC0,0xA42B,0x0000,0x0000,0x0000, /* 242B */ +0xFBC0,0xA42C,0x0000,0x0000,0x0000, /* 242C */ +0xFBC0,0xA42D,0x0000,0x0000,0x0000, /* 242D */ +0xFBC0,0xA42E,0x0000,0x0000,0x0000, /* 242E */ +0xFBC0,0xA42F,0x0000,0x0000,0x0000, /* 242F */ +0xFBC0,0xA430,0x0000,0x0000,0x0000, /* 2430 */ +0xFBC0,0xA431,0x0000,0x0000,0x0000, /* 2431 */ +0xFBC0,0xA432,0x0000,0x0000,0x0000, /* 2432 */ +0xFBC0,0xA433,0x0000,0x0000,0x0000, /* 2433 */ +0xFBC0,0xA434,0x0000,0x0000,0x0000, /* 2434 */ +0xFBC0,0xA435,0x0000,0x0000,0x0000, /* 2435 */ +0xFBC0,0xA436,0x0000,0x0000,0x0000, /* 2436 */ +0xFBC0,0xA437,0x0000,0x0000,0x0000, /* 2437 */ +0xFBC0,0xA438,0x0000,0x0000,0x0000, /* 2438 */ +0xFBC0,0xA439,0x0000,0x0000,0x0000, /* 2439 */ +0xFBC0,0xA43A,0x0000,0x0000,0x0000, /* 243A */ +0xFBC0,0xA43B,0x0000,0x0000,0x0000, /* 243B */ +0xFBC0,0xA43C,0x0000,0x0000,0x0000, /* 243C */ +0xFBC0,0xA43D,0x0000,0x0000,0x0000, /* 243D */ +0xFBC0,0xA43E,0x0000,0x0000,0x0000, /* 243E */ +0xFBC0,0xA43F,0x0000,0x0000,0x0000, /* 243F */ +0x0733,0x0000,0x0000,0x0000,0x0000, /* 2440 */ +0x0734,0x0000,0x0000,0x0000,0x0000, /* 2441 */ +0x0735,0x0000,0x0000,0x0000,0x0000, /* 2442 */ +0x0736,0x0000,0x0000,0x0000,0x0000, /* 2443 */ +0x0737,0x0000,0x0000,0x0000,0x0000, /* 2444 */ +0x0738,0x0000,0x0000,0x0000,0x0000, /* 2445 */ +0x0739,0x0000,0x0000,0x0000,0x0000, /* 2446 */ +0x073A,0x0000,0x0000,0x0000,0x0000, /* 2447 */ +0x073B,0x0000,0x0000,0x0000,0x0000, /* 2448 */ +0x073C,0x0000,0x0000,0x0000,0x0000, /* 2449 */ +0x073D,0x0000,0x0000,0x0000,0x0000, /* 244A */ +0xFBC0,0xA44B,0x0000,0x0000,0x0000, /* 244B */ +0xFBC0,0xA44C,0x0000,0x0000,0x0000, /* 244C */ +0xFBC0,0xA44D,0x0000,0x0000,0x0000, /* 244D */ +0xFBC0,0xA44E,0x0000,0x0000,0x0000, /* 244E */ +0xFBC0,0xA44F,0x0000,0x0000,0x0000, /* 244F */ +0xFBC0,0xA450,0x0000,0x0000,0x0000, /* 2450 */ +0xFBC0,0xA451,0x0000,0x0000,0x0000, /* 2451 */ +0xFBC0,0xA452,0x0000,0x0000,0x0000, /* 2452 */ +0xFBC0,0xA453,0x0000,0x0000,0x0000, /* 2453 */ +0xFBC0,0xA454,0x0000,0x0000,0x0000, /* 2454 */ +0xFBC0,0xA455,0x0000,0x0000,0x0000, /* 2455 */ +0xFBC0,0xA456,0x0000,0x0000,0x0000, /* 2456 */ +0xFBC0,0xA457,0x0000,0x0000,0x0000, /* 2457 */ +0xFBC0,0xA458,0x0000,0x0000,0x0000, /* 2458 */ +0xFBC0,0xA459,0x0000,0x0000,0x0000, /* 2459 */ +0xFBC0,0xA45A,0x0000,0x0000,0x0000, /* 245A */ +0xFBC0,0xA45B,0x0000,0x0000,0x0000, /* 245B */ +0xFBC0,0xA45C,0x0000,0x0000,0x0000, /* 245C */ +0xFBC0,0xA45D,0x0000,0x0000,0x0000, /* 245D */ +0xFBC0,0xA45E,0x0000,0x0000,0x0000, /* 245E */ +0xFBC0,0xA45F,0x0000,0x0000,0x0000, /* 245F */ +0x1206,0x0000,0x0000,0x0000,0x0000, /* 2460 */ +0x1207,0x0000,0x0000,0x0000,0x0000, /* 2461 */ +0x1208,0x0000,0x0000,0x0000,0x0000, /* 2462 */ +0x1209,0x0000,0x0000,0x0000,0x0000, /* 2463 */ +0x120A,0x0000,0x0000,0x0000,0x0000, /* 2464 */ +0x120B,0x0000,0x0000,0x0000,0x0000, /* 2465 */ +0x120C,0x0000,0x0000,0x0000,0x0000, /* 2466 */ +0x120D,0x0000,0x0000,0x0000,0x0000, /* 2467 */ +0x120E,0x0000,0x0000,0x0000,0x0000, /* 2468 */ +0x1206,0x1205,0x0000,0x0000,0x0000, /* 2469 */ +0x1206,0x1206,0x0000,0x0000,0x0000, /* 246A */ +0x1206,0x1207,0x0000,0x0000,0x0000, /* 246B */ +0x1206,0x1208,0x0000,0x0000,0x0000, /* 246C */ +0x1206,0x1209,0x0000,0x0000,0x0000, /* 246D */ +0x1206,0x120A,0x0000,0x0000,0x0000, /* 246E */ +0x1206,0x120B,0x0000,0x0000,0x0000, /* 246F */ +0x1206,0x120C,0x0000,0x0000,0x0000, /* 2470 */ +0x1206,0x120D,0x0000,0x0000,0x0000, /* 2471 */ +0x1206,0x120E,0x0000,0x0000,0x0000, /* 2472 */ +0x1207,0x1205,0x0000,0x0000,0x0000, /* 2473 */ +0x02FF,0x1206,0x0300,0x0000,0x0000, /* 2474 */ +0x02FF,0x1207,0x0300,0x0000,0x0000, /* 2475 */ +0x02FF,0x1208,0x0300,0x0000,0x0000, /* 2476 */ +0x02FF,0x1209,0x0300,0x0000,0x0000, /* 2477 */ +0x02FF,0x120A,0x0300,0x0000,0x0000, /* 2478 */ +0x02FF,0x120B,0x0300,0x0000,0x0000, /* 2479 */ +0x02FF,0x120C,0x0300,0x0000,0x0000, /* 247A */ +0x02FF,0x120D,0x0300,0x0000,0x0000, /* 247B */ +0x02FF,0x120E,0x0300,0x0000,0x0000, /* 247C */ +0x02FF,0x1206,0x1205,0x0300,0x0000, /* 247D */ +0x02FF,0x1206,0x1206,0x0300,0x0000, /* 247E */ +0x02FF,0x1206,0x1207,0x0300,0x0000, /* 247F */ +0x02FF,0x1206,0x1208,0x0300,0x0000, /* 2480 */ +0x02FF,0x1206,0x1209,0x0300,0x0000, /* 2481 */ +0x02FF,0x1206,0x120A,0x0300,0x0000, /* 2482 */ +0x02FF,0x1206,0x120B,0x0300,0x0000, /* 2483 */ +0x02FF,0x1206,0x120C,0x0300,0x0000, /* 2484 */ +0x02FF,0x1206,0x120D,0x0300,0x0000, /* 2485 */ +0x02FF,0x1206,0x120E,0x0300,0x0000, /* 2486 */ +0x02FF,0x1207,0x1205,0x0300,0x0000, /* 2487 */ +0x1206,0x0281,0x0000,0x0000,0x0000, /* 2488 */ +0x1207,0x0281,0x0000,0x0000,0x0000, /* 2489 */ +0x1208,0x0281,0x0000,0x0000,0x0000, /* 248A */ +0x1209,0x0281,0x0000,0x0000,0x0000, /* 248B */ +0x120A,0x0281,0x0000,0x0000,0x0000, /* 248C */ +0x120B,0x0281,0x0000,0x0000,0x0000, /* 248D */ +0x120C,0x0281,0x0000,0x0000,0x0000, /* 248E */ +0x120D,0x0281,0x0000,0x0000,0x0000, /* 248F */ +0x120E,0x0281,0x0000,0x0000,0x0000, /* 2490 */ +0x1206,0x1205,0x0281,0x0000,0x0000, /* 2491 */ +0x1206,0x1206,0x0281,0x0000,0x0000, /* 2492 */ +0x1206,0x1207,0x0281,0x0000,0x0000, /* 2493 */ +0x1206,0x1208,0x0281,0x0000,0x0000, /* 2494 */ +0x1206,0x1209,0x0281,0x0000,0x0000, /* 2495 */ +0x1206,0x120A,0x0281,0x0000,0x0000, /* 2496 */ +0x1206,0x120B,0x0281,0x0000,0x0000, /* 2497 */ +0x1206,0x120C,0x0281,0x0000,0x0000, /* 2498 */ +0x1206,0x120D,0x0281,0x0000,0x0000, /* 2499 */ +0x1206,0x120E,0x0281,0x0000,0x0000, /* 249A */ +0x1207,0x1205,0x0281,0x0000,0x0000, /* 249B */ +0x02FF,0x120F,0x0300,0x0000,0x0000, /* 249C */ +0x02FF,0x1225,0x0300,0x0000,0x0000, /* 249D */ +0x02FF,0x123D,0x0300,0x0000,0x0000, /* 249E */ +0x02FF,0x1250,0x0300,0x0000,0x0000, /* 249F */ +0x02FF,0x126B,0x0300,0x0000,0x0000, /* 24A0 */ +0x02FF,0x12A3,0x0300,0x0000,0x0000, /* 24A1 */ +0x02FF,0x12B0,0x0300,0x0000,0x0000, /* 24A2 */ +0x02FF,0x12D3,0x0300,0x0000,0x0000, /* 24A3 */ +0x02FF,0x12EC,0x0300,0x0000,0x0000, /* 24A4 */ +0x02FF,0x1305,0x0300,0x0000,0x0000, /* 24A5 */ +0x02FF,0x131E,0x0300,0x0000,0x0000, /* 24A6 */ +0x02FF,0x1330,0x0300,0x0000,0x0000, /* 24A7 */ +0x02FF,0x135F,0x0300,0x0000,0x0000, /* 24A8 */ +0x02FF,0x136D,0x0300,0x0000,0x0000, /* 24A9 */ +0x02FF,0x138E,0x0300,0x0000,0x0000, /* 24AA */ +0x02FF,0x13B3,0x0300,0x0000,0x0000, /* 24AB */ +0x02FF,0x13C8,0x0300,0x0000,0x0000, /* 24AC */ +0x02FF,0x13DA,0x0300,0x0000,0x0000, /* 24AD */ +0x02FF,0x1410,0x0300,0x0000,0x0000, /* 24AE */ +0x02FF,0x1433,0x0300,0x0000,0x0000, /* 24AF */ +0x02FF,0x1453,0x0300,0x0000,0x0000, /* 24B0 */ +0x02FF,0x147B,0x0300,0x0000,0x0000, /* 24B1 */ +0x02FF,0x148D,0x0300,0x0000,0x0000, /* 24B2 */ +0x02FF,0x1497,0x0300,0x0000,0x0000, /* 24B3 */ +0x02FF,0x149C,0x0300,0x0000,0x0000, /* 24B4 */ +0x02FF,0x14AD,0x0300,0x0000,0x0000, /* 24B5 */ +0x120F,0x0000,0x0000,0x0000,0x0000, /* 24B6 */ +0x1225,0x0000,0x0000,0x0000,0x0000, /* 24B7 */ +0x123D,0x0000,0x0000,0x0000,0x0000, /* 24B8 */ +0x1250,0x0000,0x0000,0x0000,0x0000, /* 24B9 */ +0x126B,0x0000,0x0000,0x0000,0x0000, /* 24BA */ +0x12A3,0x0000,0x0000,0x0000,0x0000, /* 24BB */ +0x12B0,0x0000,0x0000,0x0000,0x0000, /* 24BC */ +0x12D3,0x0000,0x0000,0x0000,0x0000, /* 24BD */ +0x12EC,0x0000,0x0000,0x0000,0x0000, /* 24BE */ +0x1305,0x0000,0x0000,0x0000,0x0000, /* 24BF */ +0x131E,0x0000,0x0000,0x0000,0x0000, /* 24C0 */ +0x1330,0x0000,0x0000,0x0000,0x0000, /* 24C1 */ +0x135F,0x0000,0x0000,0x0000,0x0000, /* 24C2 */ +0x136D,0x0000,0x0000,0x0000,0x0000, /* 24C3 */ +0x138E,0x0000,0x0000,0x0000,0x0000, /* 24C4 */ +0x13B3,0x0000,0x0000,0x0000,0x0000, /* 24C5 */ +0x13C8,0x0000,0x0000,0x0000,0x0000, /* 24C6 */ +0x13DA,0x0000,0x0000,0x0000,0x0000, /* 24C7 */ +0x1410,0x0000,0x0000,0x0000,0x0000, /* 24C8 */ +0x1433,0x0000,0x0000,0x0000,0x0000, /* 24C9 */ +0x1453,0x0000,0x0000,0x0000,0x0000, /* 24CA */ +0x147B,0x0000,0x0000,0x0000,0x0000, /* 24CB */ +0x148D,0x0000,0x0000,0x0000,0x0000, /* 24CC */ +0x1497,0x0000,0x0000,0x0000,0x0000, /* 24CD */ +0x149C,0x0000,0x0000,0x0000,0x0000, /* 24CE */ +0x14AD,0x0000,0x0000,0x0000,0x0000, /* 24CF */ +0x120F,0x0000,0x0000,0x0000,0x0000, /* 24D0 */ +0x1225,0x0000,0x0000,0x0000,0x0000, /* 24D1 */ +0x123D,0x0000,0x0000,0x0000,0x0000, /* 24D2 */ +0x1250,0x0000,0x0000,0x0000,0x0000, /* 24D3 */ +0x126B,0x0000,0x0000,0x0000,0x0000, /* 24D4 */ +0x12A3,0x0000,0x0000,0x0000,0x0000, /* 24D5 */ +0x12B0,0x0000,0x0000,0x0000,0x0000, /* 24D6 */ +0x12D3,0x0000,0x0000,0x0000,0x0000, /* 24D7 */ +0x12EC,0x0000,0x0000,0x0000,0x0000, /* 24D8 */ +0x1305,0x0000,0x0000,0x0000,0x0000, /* 24D9 */ +0x131E,0x0000,0x0000,0x0000,0x0000, /* 24DA */ +0x1330,0x0000,0x0000,0x0000,0x0000, /* 24DB */ +0x135F,0x0000,0x0000,0x0000,0x0000, /* 24DC */ +0x136D,0x0000,0x0000,0x0000,0x0000, /* 24DD */ +0x138E,0x0000,0x0000,0x0000,0x0000, /* 24DE */ +0x13B3,0x0000,0x0000,0x0000,0x0000, /* 24DF */ +0x13C8,0x0000,0x0000,0x0000,0x0000, /* 24E0 */ +0x13DA,0x0000,0x0000,0x0000,0x0000, /* 24E1 */ +0x1410,0x0000,0x0000,0x0000,0x0000, /* 24E2 */ +0x1433,0x0000,0x0000,0x0000,0x0000, /* 24E3 */ +0x1453,0x0000,0x0000,0x0000,0x0000, /* 24E4 */ +0x147B,0x0000,0x0000,0x0000,0x0000, /* 24E5 */ +0x148D,0x0000,0x0000,0x0000,0x0000, /* 24E6 */ +0x1497,0x0000,0x0000,0x0000,0x0000, /* 24E7 */ +0x149C,0x0000,0x0000,0x0000,0x0000, /* 24E8 */ +0x14AD,0x0000,0x0000,0x0000,0x0000, /* 24E9 */ +0x1205,0x0000,0x0000,0x0000,0x0000, /* 24EA */ +0x1206,0x1206,0x0000,0x0000,0x0000, /* 24EB */ +0x1206,0x1207,0x0000,0x0000,0x0000, /* 24EC */ +0x1206,0x1208,0x0000,0x0000,0x0000, /* 24ED */ +0x1206,0x1209,0x0000,0x0000,0x0000, /* 24EE */ +0x1206,0x120A,0x0000,0x0000,0x0000, /* 24EF */ +0x1206,0x120B,0x0000,0x0000,0x0000, /* 24F0 */ +0x1206,0x120C,0x0000,0x0000,0x0000, /* 24F1 */ +0x1206,0x120D,0x0000,0x0000,0x0000, /* 24F2 */ +0x1206,0x120E,0x0000,0x0000,0x0000, /* 24F3 */ +0x1207,0x1205,0x0000,0x0000,0x0000, /* 24F4 */ +0x1206,0x0000,0x0000,0x0000,0x0000, /* 24F5 */ +0x1207,0x0000,0x0000,0x0000,0x0000, /* 24F6 */ +0x1208,0x0000,0x0000,0x0000,0x0000, /* 24F7 */ +0x1209,0x0000,0x0000,0x0000,0x0000, /* 24F8 */ +0x120A,0x0000,0x0000,0x0000,0x0000, /* 24F9 */ +0x120B,0x0000,0x0000,0x0000,0x0000, /* 24FA */ +0x120C,0x0000,0x0000,0x0000,0x0000, /* 24FB */ +0x120D,0x0000,0x0000,0x0000,0x0000, /* 24FC */ +0x120E,0x0000,0x0000,0x0000,0x0000, /* 24FD */ +0x1206,0x1205,0x0000,0x0000,0x0000, /* 24FE */ +0x1205,0x0000,0x0000,0x0000,0x0000 /* 24FF */ +}; + +uint16 uca520_p025[]= { /* 2500 (2 weights per char) */ +0x073E,0x0000, 0x073F,0x0000, 0x0740,0x0000, 0x0741,0x0000, /* 2500 */ +0x0742,0x0000, 0x0743,0x0000, 0x0744,0x0000, 0x0745,0x0000, /* 2504 */ +0x0746,0x0000, 0x0747,0x0000, 0x0748,0x0000, 0x0749,0x0000, /* 2508 */ +0x074A,0x0000, 0x074B,0x0000, 0x074C,0x0000, 0x074D,0x0000, /* 250C */ +0x074E,0x0000, 0x074F,0x0000, 0x0750,0x0000, 0x0751,0x0000, /* 2510 */ +0x0752,0x0000, 0x0753,0x0000, 0x0754,0x0000, 0x0755,0x0000, /* 2514 */ +0x0756,0x0000, 0x0757,0x0000, 0x0758,0x0000, 0x0759,0x0000, /* 2518 */ +0x075A,0x0000, 0x075B,0x0000, 0x075C,0x0000, 0x075D,0x0000, /* 251C */ +0x075E,0x0000, 0x075F,0x0000, 0x0760,0x0000, 0x0761,0x0000, /* 2520 */ +0x0762,0x0000, 0x0763,0x0000, 0x0764,0x0000, 0x0765,0x0000, /* 2524 */ +0x0766,0x0000, 0x0767,0x0000, 0x0768,0x0000, 0x0769,0x0000, /* 2528 */ +0x076A,0x0000, 0x076B,0x0000, 0x076C,0x0000, 0x076D,0x0000, /* 252C */ +0x076E,0x0000, 0x076F,0x0000, 0x0770,0x0000, 0x0771,0x0000, /* 2530 */ +0x0772,0x0000, 0x0773,0x0000, 0x0774,0x0000, 0x0775,0x0000, /* 2534 */ +0x0776,0x0000, 0x0777,0x0000, 0x0778,0x0000, 0x0779,0x0000, /* 2538 */ +0x077A,0x0000, 0x077B,0x0000, 0x077C,0x0000, 0x077D,0x0000, /* 253C */ +0x077E,0x0000, 0x077F,0x0000, 0x0780,0x0000, 0x0781,0x0000, /* 2540 */ +0x0782,0x0000, 0x0783,0x0000, 0x0784,0x0000, 0x0785,0x0000, /* 2544 */ +0x0786,0x0000, 0x0787,0x0000, 0x0788,0x0000, 0x0789,0x0000, /* 2548 */ +0x078A,0x0000, 0x078B,0x0000, 0x078C,0x0000, 0x078D,0x0000, /* 254C */ +0x078E,0x0000, 0x078F,0x0000, 0x0790,0x0000, 0x0791,0x0000, /* 2550 */ +0x0792,0x0000, 0x0793,0x0000, 0x0794,0x0000, 0x0795,0x0000, /* 2554 */ +0x0796,0x0000, 0x0797,0x0000, 0x0798,0x0000, 0x0799,0x0000, /* 2558 */ +0x079A,0x0000, 0x079B,0x0000, 0x079C,0x0000, 0x079D,0x0000, /* 255C */ +0x079E,0x0000, 0x079F,0x0000, 0x07A0,0x0000, 0x07A1,0x0000, /* 2560 */ +0x07A2,0x0000, 0x07A3,0x0000, 0x07A4,0x0000, 0x07A5,0x0000, /* 2564 */ +0x07A6,0x0000, 0x07A7,0x0000, 0x07A8,0x0000, 0x07A9,0x0000, /* 2568 */ +0x07AA,0x0000, 0x07AB,0x0000, 0x07AC,0x0000, 0x07AD,0x0000, /* 256C */ +0x07AE,0x0000, 0x07AF,0x0000, 0x07B0,0x0000, 0x07B1,0x0000, /* 2570 */ +0x07B2,0x0000, 0x07B3,0x0000, 0x07B4,0x0000, 0x07B5,0x0000, /* 2574 */ +0x07B6,0x0000, 0x07B7,0x0000, 0x07B8,0x0000, 0x07B9,0x0000, /* 2578 */ +0x07BA,0x0000, 0x07BB,0x0000, 0x07BC,0x0000, 0x07BD,0x0000, /* 257C */ +0x07BE,0x0000, 0x07BF,0x0000, 0x07C0,0x0000, 0x07C1,0x0000, /* 2580 */ +0x07C2,0x0000, 0x07C3,0x0000, 0x07C4,0x0000, 0x07C5,0x0000, /* 2584 */ +0x07C6,0x0000, 0x07C7,0x0000, 0x07C8,0x0000, 0x07C9,0x0000, /* 2588 */ +0x07CA,0x0000, 0x07CB,0x0000, 0x07CC,0x0000, 0x07CD,0x0000, /* 258C */ +0x07CE,0x0000, 0x07CF,0x0000, 0x07D0,0x0000, 0x07D1,0x0000, /* 2590 */ +0x07D2,0x0000, 0x07D3,0x0000, 0x07D4,0x0000, 0x07D5,0x0000, /* 2594 */ +0x07D6,0x0000, 0x07D7,0x0000, 0x07D8,0x0000, 0x07D9,0x0000, /* 2598 */ +0x07DA,0x0000, 0x07DB,0x0000, 0x07DC,0x0000, 0x07DD,0x0000, /* 259C */ +0x07DE,0x0000, 0x07DF,0x0000, 0x07E0,0x0000, 0x07E1,0x0000, /* 25A0 */ +0x07E2,0x0000, 0x07E3,0x0000, 0x07E4,0x0000, 0x07E5,0x0000, /* 25A4 */ +0x07E6,0x0000, 0x07E7,0x0000, 0x07E8,0x0000, 0x07E9,0x0000, /* 25A8 */ +0x07EA,0x0000, 0x07EB,0x0000, 0x07EC,0x0000, 0x07ED,0x0000, /* 25AC */ +0x07EE,0x0000, 0x07EF,0x0000, 0x07F0,0x0000, 0x07F1,0x0000, /* 25B0 */ +0x07F2,0x0000, 0x07F3,0x0000, 0x07F4,0x0000, 0x07F5,0x0000, /* 25B4 */ +0x07F6,0x0000, 0x07F7,0x0000, 0x07F8,0x0000, 0x07F9,0x0000, /* 25B8 */ +0x07FA,0x0000, 0x07FB,0x0000, 0x07FC,0x0000, 0x07FD,0x0000, /* 25BC */ +0x07FE,0x0000, 0x07FF,0x0000, 0x0800,0x0000, 0x0801,0x0000, /* 25C0 */ +0x0802,0x0000, 0x0803,0x0000, 0x0804,0x0000, 0x0805,0x0000, /* 25C4 */ +0x0806,0x0000, 0x0807,0x0000, 0x0808,0x0000, 0x0809,0x0000, /* 25C8 */ +0x080A,0x0000, 0x080B,0x0000, 0x080C,0x0000, 0x080D,0x0000, /* 25CC */ +0x080E,0x0000, 0x080F,0x0000, 0x0810,0x0000, 0x0811,0x0000, /* 25D0 */ +0x0812,0x0000, 0x0813,0x0000, 0x0814,0x0000, 0x0815,0x0000, /* 25D4 */ +0x0816,0x0000, 0x0817,0x0000, 0x0818,0x0000, 0x0819,0x0000, /* 25D8 */ +0x081A,0x0000, 0x081B,0x0000, 0x081C,0x0000, 0x081D,0x0000, /* 25DC */ +0x081E,0x0000, 0x081F,0x0000, 0x0820,0x0000, 0x0821,0x0000, /* 25E0 */ +0x0822,0x0000, 0x0823,0x0000, 0x0824,0x0000, 0x0825,0x0000, /* 25E4 */ +0x0826,0x0000, 0x0827,0x0000, 0x0828,0x0000, 0x0829,0x0000, /* 25E8 */ +0x082A,0x0000, 0x082B,0x0000, 0x082C,0x0000, 0x082D,0x0000, /* 25EC */ +0x082E,0x0000, 0x082F,0x0000, 0x0830,0x0000, 0x0831,0x0000, /* 25F0 */ +0x0832,0x0000, 0x0833,0x0000, 0x0834,0x0000, 0x0835,0x0000, /* 25F4 */ +0x0836,0x0000, 0x0837,0x0000, 0x0838,0x0000, 0x0839,0x0000, /* 25F8 */ +0x083A,0x0000, 0x083B,0x0000, 0x083C,0x0000, 0x083D,0x0000 /* 25FC */ +}; + +uint16 uca520_p026[]= { /* 2600 (3 weights per char) */ +0x083E,0x0000,0x0000, 0x083F,0x0000,0x0000, 0x0840,0x0000,0x0000, /* 2600 */ +0x0841,0x0000,0x0000, 0x0842,0x0000,0x0000, 0x0843,0x0000,0x0000, /* 2603 */ +0x0844,0x0000,0x0000, 0x0845,0x0000,0x0000, 0x0846,0x0000,0x0000, /* 2606 */ +0x0847,0x0000,0x0000, 0x0848,0x0000,0x0000, 0x0849,0x0000,0x0000, /* 2609 */ +0x084A,0x0000,0x0000, 0x084B,0x0000,0x0000, 0x084C,0x0000,0x0000, /* 260C */ +0x084D,0x0000,0x0000, 0x084E,0x0000,0x0000, 0x084F,0x0000,0x0000, /* 260F */ +0x0850,0x0000,0x0000, 0x0851,0x0000,0x0000, 0x0852,0x0000,0x0000, /* 2612 */ +0x0853,0x0000,0x0000, 0x0854,0x0000,0x0000, 0x0855,0x0000,0x0000, /* 2615 */ +0x0856,0x0000,0x0000, 0x0857,0x0000,0x0000, 0x0858,0x0000,0x0000, /* 2618 */ +0x0859,0x0000,0x0000, 0x085A,0x0000,0x0000, 0x085B,0x0000,0x0000, /* 261B */ +0x085C,0x0000,0x0000, 0x085D,0x0000,0x0000, 0x085E,0x0000,0x0000, /* 261E */ +0x085F,0x0000,0x0000, 0x0860,0x0000,0x0000, 0x0861,0x0000,0x0000, /* 2621 */ +0x0862,0x0000,0x0000, 0x0863,0x0000,0x0000, 0x0864,0x0000,0x0000, /* 2624 */ +0x0865,0x0000,0x0000, 0x0866,0x0000,0x0000, 0x0867,0x0000,0x0000, /* 2627 */ +0x0868,0x0000,0x0000, 0x0869,0x0000,0x0000, 0x086A,0x0000,0x0000, /* 262A */ +0x086B,0x0000,0x0000, 0x086C,0x0000,0x0000, 0x086D,0x0000,0x0000, /* 262D */ +0x0D36,0x0000,0x0000, 0x0D37,0x0000,0x0000, 0x0D38,0x0000,0x0000, /* 2630 */ +0x0D39,0x0000,0x0000, 0x0D3A,0x0000,0x0000, 0x0D3B,0x0000,0x0000, /* 2633 */ +0x0D3C,0x0000,0x0000, 0x0D3D,0x0000,0x0000, 0x086E,0x0000,0x0000, /* 2636 */ +0x086F,0x0000,0x0000, 0x0870,0x0000,0x0000, 0x0871,0x0000,0x0000, /* 2639 */ +0x0872,0x0000,0x0000, 0x0873,0x0000,0x0000, 0x0874,0x0000,0x0000, /* 263C */ +0x0875,0x0000,0x0000, 0x0876,0x0000,0x0000, 0x0877,0x0000,0x0000, /* 263F */ +0x0878,0x0000,0x0000, 0x0879,0x0000,0x0000, 0x087A,0x0000,0x0000, /* 2642 */ +0x087B,0x0000,0x0000, 0x087C,0x0000,0x0000, 0x087D,0x0000,0x0000, /* 2645 */ +0x087E,0x0000,0x0000, 0x087F,0x0000,0x0000, 0x0880,0x0000,0x0000, /* 2648 */ +0x0881,0x0000,0x0000, 0x0882,0x0000,0x0000, 0x0883,0x0000,0x0000, /* 264B */ +0x0884,0x0000,0x0000, 0x0885,0x0000,0x0000, 0x0886,0x0000,0x0000, /* 264E */ +0x0887,0x0000,0x0000, 0x0888,0x0000,0x0000, 0x0889,0x0000,0x0000, /* 2651 */ +0x088A,0x0000,0x0000, 0x088B,0x0000,0x0000, 0x088C,0x0000,0x0000, /* 2654 */ +0x088D,0x0000,0x0000, 0x088E,0x0000,0x0000, 0x088F,0x0000,0x0000, /* 2657 */ +0x0890,0x0000,0x0000, 0x0891,0x0000,0x0000, 0x0892,0x0000,0x0000, /* 265A */ +0x0893,0x0000,0x0000, 0x0894,0x0000,0x0000, 0x0895,0x0000,0x0000, /* 265D */ +0x0896,0x0000,0x0000, 0x0897,0x0000,0x0000, 0x0898,0x0000,0x0000, /* 2660 */ +0x0899,0x0000,0x0000, 0x089A,0x0000,0x0000, 0x089B,0x0000,0x0000, /* 2663 */ +0x089C,0x0000,0x0000, 0x089D,0x0000,0x0000, 0x089E,0x0000,0x0000, /* 2666 */ +0x089F,0x0000,0x0000, 0x08A0,0x0000,0x0000, 0x08A1,0x0000,0x0000, /* 2669 */ +0x08A2,0x0000,0x0000, 0x0F7C,0x0000,0x0000, 0x0F7D,0x0000,0x0000, /* 266C */ +0x0F7E,0x0000,0x0000, 0x08A3,0x0000,0x0000, 0x08A4,0x0000,0x0000, /* 266F */ +0x08A5,0x0000,0x0000, 0x08A6,0x0000,0x0000, 0x08A7,0x0000,0x0000, /* 2672 */ +0x08A8,0x0000,0x0000, 0x08A9,0x0000,0x0000, 0x08AA,0x0000,0x0000, /* 2675 */ +0x08AB,0x0000,0x0000, 0x08AC,0x0000,0x0000, 0x08AD,0x0000,0x0000, /* 2678 */ +0x08AE,0x0000,0x0000, 0x08AF,0x0000,0x0000, 0x08B0,0x0000,0x0000, /* 267B */ +0x08B1,0x0000,0x0000, 0x08B2,0x0000,0x0000, 0x08B3,0x0000,0x0000, /* 267E */ +0x08B4,0x0000,0x0000, 0x08B5,0x0000,0x0000, 0x08B6,0x0000,0x0000, /* 2681 */ +0x08B7,0x0000,0x0000, 0x08B8,0x0000,0x0000, 0x08B9,0x0000,0x0000, /* 2684 */ +0x08BA,0x0000,0x0000, 0x08BB,0x0000,0x0000, 0x08BC,0x0000,0x0000, /* 2687 */ +0x0D30,0x0000,0x0000, 0x0D31,0x0000,0x0000, 0x0D32,0x0000,0x0000, /* 268A */ +0x0D33,0x0000,0x0000, 0x0D34,0x0000,0x0000, 0x0D35,0x0000,0x0000, /* 268D */ +0x08BD,0x0000,0x0000, 0x08BE,0x0000,0x0000, 0x08BF,0x0000,0x0000, /* 2690 */ +0x08C0,0x0000,0x0000, 0x08C1,0x0000,0x0000, 0x08C2,0x0000,0x0000, /* 2693 */ +0x08C3,0x0000,0x0000, 0x08C4,0x0000,0x0000, 0x08C5,0x0000,0x0000, /* 2696 */ +0x08C6,0x0000,0x0000, 0x08C7,0x0000,0x0000, 0x08C8,0x0000,0x0000, /* 2699 */ +0x08C9,0x0000,0x0000, 0x08CA,0x0000,0x0000, 0x08CB,0x0000,0x0000, /* 269C */ +0x08CC,0x0000,0x0000, 0x08CD,0x0000,0x0000, 0x08CE,0x0000,0x0000, /* 269F */ +0x08CF,0x0000,0x0000, 0x08D0,0x0000,0x0000, 0x08D1,0x0000,0x0000, /* 26A2 */ +0x08D2,0x0000,0x0000, 0x08D3,0x0000,0x0000, 0x08D4,0x0000,0x0000, /* 26A5 */ +0x08D5,0x0000,0x0000, 0x08D6,0x0000,0x0000, 0x08D7,0x0000,0x0000, /* 26A8 */ +0x08D8,0x0000,0x0000, 0x08D9,0x0000,0x0000, 0x08DA,0x0000,0x0000, /* 26AB */ +0x08DB,0x0000,0x0000, 0x08DC,0x0000,0x0000, 0x08DD,0x0000,0x0000, /* 26AE */ +0x08DE,0x0000,0x0000, 0x08DF,0x0000,0x0000, 0x08E0,0x0000,0x0000, /* 26B1 */ +0x08E1,0x0000,0x0000, 0x08E2,0x0000,0x0000, 0x08E3,0x0000,0x0000, /* 26B4 */ +0x08E4,0x0000,0x0000, 0x08E5,0x0000,0x0000, 0x08E6,0x0000,0x0000, /* 26B7 */ +0x08E7,0x0000,0x0000, 0x08E8,0x0000,0x0000, 0x08E9,0x0000,0x0000, /* 26BA */ +0x08EA,0x0000,0x0000, 0x08EB,0x0000,0x0000, 0x08EC,0x0000,0x0000, /* 26BD */ +0x08ED,0x0000,0x0000, 0x08EE,0x0000,0x0000, 0x08EF,0x0000,0x0000, /* 26C0 */ +0x08F0,0x0000,0x0000, 0x08F1,0x0000,0x0000, 0x08F2,0x0000,0x0000, /* 26C3 */ +0x08F3,0x0000,0x0000, 0x08F4,0x0000,0x0000, 0x08F5,0x0000,0x0000, /* 26C6 */ +0x08F6,0x0000,0x0000, 0x08F7,0x0000,0x0000, 0x08F8,0x0000,0x0000, /* 26C9 */ +0x08F9,0x0000,0x0000, 0x08FA,0x0000,0x0000, 0xFBC0,0xA6CE,0x0000, /* 26CC */ +0x08FB,0x0000,0x0000, 0x08FC,0x0000,0x0000, 0x08FD,0x0000,0x0000, /* 26CF */ +0x08FE,0x0000,0x0000, 0x08FF,0x0000,0x0000, 0x0900,0x0000,0x0000, /* 26D2 */ +0x0901,0x0000,0x0000, 0x0902,0x0000,0x0000, 0x0903,0x0000,0x0000, /* 26D5 */ +0x0904,0x0000,0x0000, 0x0905,0x0000,0x0000, 0x0906,0x0000,0x0000, /* 26D8 */ +0x0907,0x0000,0x0000, 0x0908,0x0000,0x0000, 0x0909,0x0000,0x0000, /* 26DB */ +0x090A,0x0000,0x0000, 0x090B,0x0000,0x0000, 0x090C,0x0000,0x0000, /* 26DE */ +0x090D,0x0000,0x0000, 0xFBC0,0xA6E2,0x0000, 0x090E,0x0000,0x0000, /* 26E1 */ +0xFBC0,0xA6E4,0x0000, 0xFBC0,0xA6E5,0x0000, 0xFBC0,0xA6E6,0x0000, /* 26E4 */ +0xFBC0,0xA6E7,0x0000, 0x090F,0x0000,0x0000, 0x0910,0x0000,0x0000, /* 26E7 */ +0x0911,0x0000,0x0000, 0x0912,0x0000,0x0000, 0x0913,0x0000,0x0000, /* 26EA */ +0x0914,0x0000,0x0000, 0x0915,0x0000,0x0000, 0x0916,0x0000,0x0000, /* 26ED */ +0x0917,0x0000,0x0000, 0x0918,0x0000,0x0000, 0x0919,0x0000,0x0000, /* 26F0 */ +0x091A,0x0000,0x0000, 0x091B,0x0000,0x0000, 0x091C,0x0000,0x0000, /* 26F3 */ +0x091D,0x0000,0x0000, 0x091E,0x0000,0x0000, 0x091F,0x0000,0x0000, /* 26F6 */ +0x0920,0x0000,0x0000, 0x0921,0x0000,0x0000, 0x0922,0x0000,0x0000, /* 26F9 */ +0x0923,0x0000,0x0000, 0x0924,0x0000,0x0000, 0x0925,0x0000,0x0000, /* 26FC */ +0x0926,0x0000,0x0000 }; + +uint16 uca520_p027[]= { /* 2700 (3 weights per char) */ +0xFBC0,0xA700,0x0000, 0x0927,0x0000,0x0000, 0x0928,0x0000,0x0000, /* 2700 */ +0x0929,0x0000,0x0000, 0x092A,0x0000,0x0000, 0xFBC0,0xA705,0x0000, /* 2703 */ +0x092B,0x0000,0x0000, 0x092C,0x0000,0x0000, 0x092D,0x0000,0x0000, /* 2706 */ +0x092E,0x0000,0x0000, 0xFBC0,0xA70A,0x0000, 0xFBC0,0xA70B,0x0000, /* 2709 */ +0x092F,0x0000,0x0000, 0x0930,0x0000,0x0000, 0x0931,0x0000,0x0000, /* 270C */ +0x0932,0x0000,0x0000, 0x0933,0x0000,0x0000, 0x0934,0x0000,0x0000, /* 270F */ +0x0935,0x0000,0x0000, 0x0936,0x0000,0x0000, 0x0937,0x0000,0x0000, /* 2712 */ +0x0938,0x0000,0x0000, 0x0939,0x0000,0x0000, 0x093A,0x0000,0x0000, /* 2715 */ +0x093B,0x0000,0x0000, 0x093C,0x0000,0x0000, 0x093D,0x0000,0x0000, /* 2718 */ +0x093E,0x0000,0x0000, 0x093F,0x0000,0x0000, 0x0940,0x0000,0x0000, /* 271B */ +0x0941,0x0000,0x0000, 0x0942,0x0000,0x0000, 0x0943,0x0000,0x0000, /* 271E */ +0x0944,0x0000,0x0000, 0x0945,0x0000,0x0000, 0x0946,0x0000,0x0000, /* 2721 */ +0x0947,0x0000,0x0000, 0x0948,0x0000,0x0000, 0x0949,0x0000,0x0000, /* 2724 */ +0x094A,0x0000,0x0000, 0xFBC0,0xA728,0x0000, 0x094B,0x0000,0x0000, /* 2727 */ +0x094C,0x0000,0x0000, 0x094D,0x0000,0x0000, 0x094E,0x0000,0x0000, /* 272A */ +0x094F,0x0000,0x0000, 0x0950,0x0000,0x0000, 0x0951,0x0000,0x0000, /* 272D */ +0x0952,0x0000,0x0000, 0x0953,0x0000,0x0000, 0x0954,0x0000,0x0000, /* 2730 */ +0x0955,0x0000,0x0000, 0x0956,0x0000,0x0000, 0x0957,0x0000,0x0000, /* 2733 */ +0x0958,0x0000,0x0000, 0x0959,0x0000,0x0000, 0x095A,0x0000,0x0000, /* 2736 */ +0x095B,0x0000,0x0000, 0x095C,0x0000,0x0000, 0x095D,0x0000,0x0000, /* 2739 */ +0x095E,0x0000,0x0000, 0x095F,0x0000,0x0000, 0x0960,0x0000,0x0000, /* 273C */ +0x0961,0x0000,0x0000, 0x0962,0x0000,0x0000, 0x0963,0x0000,0x0000, /* 273F */ +0x0964,0x0000,0x0000, 0x0965,0x0000,0x0000, 0x0966,0x0000,0x0000, /* 2742 */ +0x0967,0x0000,0x0000, 0x0968,0x0000,0x0000, 0x0969,0x0000,0x0000, /* 2745 */ +0x096A,0x0000,0x0000, 0x096B,0x0000,0x0000, 0x096C,0x0000,0x0000, /* 2748 */ +0x096D,0x0000,0x0000, 0xFBC0,0xA74C,0x0000, 0x096E,0x0000,0x0000, /* 274B */ +0xFBC0,0xA74E,0x0000, 0x096F,0x0000,0x0000, 0x0970,0x0000,0x0000, /* 274E */ +0x0971,0x0000,0x0000, 0x0972,0x0000,0x0000, 0xFBC0,0xA753,0x0000, /* 2751 */ +0xFBC0,0xA754,0x0000, 0xFBC0,0xA755,0x0000, 0x0973,0x0000,0x0000, /* 2754 */ +0x0974,0x0000,0x0000, 0x0975,0x0000,0x0000, 0x0976,0x0000,0x0000, /* 2757 */ +0x0977,0x0000,0x0000, 0x0978,0x0000,0x0000, 0x0979,0x0000,0x0000, /* 275A */ +0x097A,0x0000,0x0000, 0x097B,0x0000,0x0000, 0xFBC0,0xA75F,0x0000, /* 275D */ +0xFBC0,0xA760,0x0000, 0x097C,0x0000,0x0000, 0x097D,0x0000,0x0000, /* 2760 */ +0x097E,0x0000,0x0000, 0x097F,0x0000,0x0000, 0x0980,0x0000,0x0000, /* 2763 */ +0x0981,0x0000,0x0000, 0x0982,0x0000,0x0000, 0x0983,0x0000,0x0000, /* 2766 */ +0x0984,0x0000,0x0000, 0x0985,0x0000,0x0000, 0x0986,0x0000,0x0000, /* 2769 */ +0x0987,0x0000,0x0000, 0x0988,0x0000,0x0000, 0x0989,0x0000,0x0000, /* 276C */ +0x098A,0x0000,0x0000, 0x098B,0x0000,0x0000, 0x098C,0x0000,0x0000, /* 276F */ +0x098D,0x0000,0x0000, 0x098E,0x0000,0x0000, 0x098F,0x0000,0x0000, /* 2772 */ +0x0990,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 2775 */ +0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, /* 2778 */ +0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, /* 277B */ +0x120E,0x0000,0x0000, 0x1206,0x1205,0x0000, 0x1206,0x0000,0x0000, /* 277E */ +0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, /* 2781 */ +0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, /* 2784 */ +0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, 0x1206,0x1205,0x0000, /* 2787 */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 278A */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 278D */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 2790 */ +0x1206,0x1205,0x0000, 0x0991,0x0000,0x0000, 0xFBC0,0xA795,0x0000, /* 2793 */ +0xFBC0,0xA796,0x0000, 0xFBC0,0xA797,0x0000, 0x0992,0x0000,0x0000, /* 2796 */ +0x0993,0x0000,0x0000, 0x0994,0x0000,0x0000, 0x0995,0x0000,0x0000, /* 2799 */ +0x0996,0x0000,0x0000, 0x0997,0x0000,0x0000, 0x0998,0x0000,0x0000, /* 279C */ +0x0999,0x0000,0x0000, 0x099A,0x0000,0x0000, 0x099B,0x0000,0x0000, /* 279F */ +0x099C,0x0000,0x0000, 0x099D,0x0000,0x0000, 0x099E,0x0000,0x0000, /* 27A2 */ +0x099F,0x0000,0x0000, 0x09A0,0x0000,0x0000, 0x09A1,0x0000,0x0000, /* 27A5 */ +0x09A2,0x0000,0x0000, 0x09A3,0x0000,0x0000, 0x09A4,0x0000,0x0000, /* 27A8 */ +0x09A5,0x0000,0x0000, 0x09A6,0x0000,0x0000, 0x09A7,0x0000,0x0000, /* 27AB */ +0x09A8,0x0000,0x0000, 0x09A9,0x0000,0x0000, 0xFBC0,0xA7B0,0x0000, /* 27AE */ +0x09AA,0x0000,0x0000, 0x09AB,0x0000,0x0000, 0x09AC,0x0000,0x0000, /* 27B1 */ +0x09AD,0x0000,0x0000, 0x09AE,0x0000,0x0000, 0x09AF,0x0000,0x0000, /* 27B4 */ +0x09B0,0x0000,0x0000, 0x09B1,0x0000,0x0000, 0x09B2,0x0000,0x0000, /* 27B7 */ +0x09B3,0x0000,0x0000, 0x09B4,0x0000,0x0000, 0x09B5,0x0000,0x0000, /* 27BA */ +0x09B6,0x0000,0x0000, 0x09B7,0x0000,0x0000, 0xFBC0,0xA7BF,0x0000, /* 27BD */ +0x09B8,0x0000,0x0000, 0x09B9,0x0000,0x0000, 0x09BA,0x0000,0x0000, /* 27C0 */ +0x09BB,0x0000,0x0000, 0x09BC,0x0000,0x0000, 0x09BD,0x0000,0x0000, /* 27C3 */ +0x09BE,0x0000,0x0000, 0x09BF,0x0000,0x0000, 0x09C0,0x0000,0x0000, /* 27C6 */ +0x09C1,0x0000,0x0000, 0x09C2,0x0000,0x0000, 0xFBC0,0xA7CB,0x0000, /* 27C9 */ +0x09C3,0x0000,0x0000, 0xFBC0,0xA7CD,0x0000, 0xFBC0,0xA7CE,0x0000, /* 27CC */ +0xFBC0,0xA7CF,0x0000, 0x09C4,0x0000,0x0000, 0x09C5,0x0000,0x0000, /* 27CF */ +0x09C6,0x0000,0x0000, 0x09C7,0x0000,0x0000, 0x09C8,0x0000,0x0000, /* 27D2 */ +0x09C9,0x0000,0x0000, 0x09CA,0x0000,0x0000, 0x09CB,0x0000,0x0000, /* 27D5 */ +0x09CC,0x0000,0x0000, 0x09CD,0x0000,0x0000, 0x09CE,0x0000,0x0000, /* 27D8 */ +0x09CF,0x0000,0x0000, 0x09D0,0x0000,0x0000, 0x09D1,0x0000,0x0000, /* 27DB */ +0x09D2,0x0000,0x0000, 0x09D3,0x0000,0x0000, 0x09D4,0x0000,0x0000, /* 27DE */ +0x09D5,0x0000,0x0000, 0x09D6,0x0000,0x0000, 0x09D7,0x0000,0x0000, /* 27E1 */ +0x09D8,0x0000,0x0000, 0x09D9,0x0000,0x0000, 0x09DA,0x0000,0x0000, /* 27E4 */ +0x09DB,0x0000,0x0000, 0x09DC,0x0000,0x0000, 0x09DD,0x0000,0x0000, /* 27E7 */ +0x09DE,0x0000,0x0000, 0x09DF,0x0000,0x0000, 0x0325,0x0000,0x0000, /* 27EA */ +0x0326,0x0000,0x0000, 0x0327,0x0000,0x0000, 0x0328,0x0000,0x0000, /* 27ED */ +0x09E0,0x0000,0x0000, 0x09E1,0x0000,0x0000, 0x09E2,0x0000,0x0000, /* 27F0 */ +0x09E3,0x0000,0x0000, 0x09E4,0x0000,0x0000, 0x09E5,0x0000,0x0000, /* 27F3 */ +0x09E6,0x0000,0x0000, 0x09E7,0x0000,0x0000, 0x09E8,0x0000,0x0000, /* 27F6 */ +0x09E9,0x0000,0x0000, 0x09EA,0x0000,0x0000, 0x09EB,0x0000,0x0000, /* 27F9 */ +0x09EC,0x0000,0x0000, 0x09ED,0x0000,0x0000, 0x09EE,0x0000,0x0000, /* 27FC */ +0x09EF,0x0000,0x0000 }; + +uint16 uca520_p028[]= { /* 2800 (2 weights per char) */ +0x0C30,0x0000, 0x0C31,0x0000, 0x0C32,0x0000, 0x0C33,0x0000, /* 2800 */ +0x0C34,0x0000, 0x0C35,0x0000, 0x0C36,0x0000, 0x0C37,0x0000, /* 2804 */ +0x0C38,0x0000, 0x0C39,0x0000, 0x0C3A,0x0000, 0x0C3B,0x0000, /* 2808 */ +0x0C3C,0x0000, 0x0C3D,0x0000, 0x0C3E,0x0000, 0x0C3F,0x0000, /* 280C */ +0x0C40,0x0000, 0x0C41,0x0000, 0x0C42,0x0000, 0x0C43,0x0000, /* 2810 */ +0x0C44,0x0000, 0x0C45,0x0000, 0x0C46,0x0000, 0x0C47,0x0000, /* 2814 */ +0x0C48,0x0000, 0x0C49,0x0000, 0x0C4A,0x0000, 0x0C4B,0x0000, /* 2818 */ +0x0C4C,0x0000, 0x0C4D,0x0000, 0x0C4E,0x0000, 0x0C4F,0x0000, /* 281C */ +0x0C50,0x0000, 0x0C51,0x0000, 0x0C52,0x0000, 0x0C53,0x0000, /* 2820 */ +0x0C54,0x0000, 0x0C55,0x0000, 0x0C56,0x0000, 0x0C57,0x0000, /* 2824 */ +0x0C58,0x0000, 0x0C59,0x0000, 0x0C5A,0x0000, 0x0C5B,0x0000, /* 2828 */ +0x0C5C,0x0000, 0x0C5D,0x0000, 0x0C5E,0x0000, 0x0C5F,0x0000, /* 282C */ +0x0C60,0x0000, 0x0C61,0x0000, 0x0C62,0x0000, 0x0C63,0x0000, /* 2830 */ +0x0C64,0x0000, 0x0C65,0x0000, 0x0C66,0x0000, 0x0C67,0x0000, /* 2834 */ +0x0C68,0x0000, 0x0C69,0x0000, 0x0C6A,0x0000, 0x0C6B,0x0000, /* 2838 */ +0x0C6C,0x0000, 0x0C6D,0x0000, 0x0C6E,0x0000, 0x0C6F,0x0000, /* 283C */ +0x0C70,0x0000, 0x0C71,0x0000, 0x0C72,0x0000, 0x0C73,0x0000, /* 2840 */ +0x0C74,0x0000, 0x0C75,0x0000, 0x0C76,0x0000, 0x0C77,0x0000, /* 2844 */ +0x0C78,0x0000, 0x0C79,0x0000, 0x0C7A,0x0000, 0x0C7B,0x0000, /* 2848 */ +0x0C7C,0x0000, 0x0C7D,0x0000, 0x0C7E,0x0000, 0x0C7F,0x0000, /* 284C */ +0x0C80,0x0000, 0x0C81,0x0000, 0x0C82,0x0000, 0x0C83,0x0000, /* 2850 */ +0x0C84,0x0000, 0x0C85,0x0000, 0x0C86,0x0000, 0x0C87,0x0000, /* 2854 */ +0x0C88,0x0000, 0x0C89,0x0000, 0x0C8A,0x0000, 0x0C8B,0x0000, /* 2858 */ +0x0C8C,0x0000, 0x0C8D,0x0000, 0x0C8E,0x0000, 0x0C8F,0x0000, /* 285C */ +0x0C90,0x0000, 0x0C91,0x0000, 0x0C92,0x0000, 0x0C93,0x0000, /* 2860 */ +0x0C94,0x0000, 0x0C95,0x0000, 0x0C96,0x0000, 0x0C97,0x0000, /* 2864 */ +0x0C98,0x0000, 0x0C99,0x0000, 0x0C9A,0x0000, 0x0C9B,0x0000, /* 2868 */ +0x0C9C,0x0000, 0x0C9D,0x0000, 0x0C9E,0x0000, 0x0C9F,0x0000, /* 286C */ +0x0CA0,0x0000, 0x0CA1,0x0000, 0x0CA2,0x0000, 0x0CA3,0x0000, /* 2870 */ +0x0CA4,0x0000, 0x0CA5,0x0000, 0x0CA6,0x0000, 0x0CA7,0x0000, /* 2874 */ +0x0CA8,0x0000, 0x0CA9,0x0000, 0x0CAA,0x0000, 0x0CAB,0x0000, /* 2878 */ +0x0CAC,0x0000, 0x0CAD,0x0000, 0x0CAE,0x0000, 0x0CAF,0x0000, /* 287C */ +0x0CB0,0x0000, 0x0CB1,0x0000, 0x0CB2,0x0000, 0x0CB3,0x0000, /* 2880 */ +0x0CB4,0x0000, 0x0CB5,0x0000, 0x0CB6,0x0000, 0x0CB7,0x0000, /* 2884 */ +0x0CB8,0x0000, 0x0CB9,0x0000, 0x0CBA,0x0000, 0x0CBB,0x0000, /* 2888 */ +0x0CBC,0x0000, 0x0CBD,0x0000, 0x0CBE,0x0000, 0x0CBF,0x0000, /* 288C */ +0x0CC0,0x0000, 0x0CC1,0x0000, 0x0CC2,0x0000, 0x0CC3,0x0000, /* 2890 */ +0x0CC4,0x0000, 0x0CC5,0x0000, 0x0CC6,0x0000, 0x0CC7,0x0000, /* 2894 */ +0x0CC8,0x0000, 0x0CC9,0x0000, 0x0CCA,0x0000, 0x0CCB,0x0000, /* 2898 */ +0x0CCC,0x0000, 0x0CCD,0x0000, 0x0CCE,0x0000, 0x0CCF,0x0000, /* 289C */ +0x0CD0,0x0000, 0x0CD1,0x0000, 0x0CD2,0x0000, 0x0CD3,0x0000, /* 28A0 */ +0x0CD4,0x0000, 0x0CD5,0x0000, 0x0CD6,0x0000, 0x0CD7,0x0000, /* 28A4 */ +0x0CD8,0x0000, 0x0CD9,0x0000, 0x0CDA,0x0000, 0x0CDB,0x0000, /* 28A8 */ +0x0CDC,0x0000, 0x0CDD,0x0000, 0x0CDE,0x0000, 0x0CDF,0x0000, /* 28AC */ +0x0CE0,0x0000, 0x0CE1,0x0000, 0x0CE2,0x0000, 0x0CE3,0x0000, /* 28B0 */ +0x0CE4,0x0000, 0x0CE5,0x0000, 0x0CE6,0x0000, 0x0CE7,0x0000, /* 28B4 */ +0x0CE8,0x0000, 0x0CE9,0x0000, 0x0CEA,0x0000, 0x0CEB,0x0000, /* 28B8 */ +0x0CEC,0x0000, 0x0CED,0x0000, 0x0CEE,0x0000, 0x0CEF,0x0000, /* 28BC */ +0x0CF0,0x0000, 0x0CF1,0x0000, 0x0CF2,0x0000, 0x0CF3,0x0000, /* 28C0 */ +0x0CF4,0x0000, 0x0CF5,0x0000, 0x0CF6,0x0000, 0x0CF7,0x0000, /* 28C4 */ +0x0CF8,0x0000, 0x0CF9,0x0000, 0x0CFA,0x0000, 0x0CFB,0x0000, /* 28C8 */ +0x0CFC,0x0000, 0x0CFD,0x0000, 0x0CFE,0x0000, 0x0CFF,0x0000, /* 28CC */ +0x0D00,0x0000, 0x0D01,0x0000, 0x0D02,0x0000, 0x0D03,0x0000, /* 28D0 */ +0x0D04,0x0000, 0x0D05,0x0000, 0x0D06,0x0000, 0x0D07,0x0000, /* 28D4 */ +0x0D08,0x0000, 0x0D09,0x0000, 0x0D0A,0x0000, 0x0D0B,0x0000, /* 28D8 */ +0x0D0C,0x0000, 0x0D0D,0x0000, 0x0D0E,0x0000, 0x0D0F,0x0000, /* 28DC */ +0x0D10,0x0000, 0x0D11,0x0000, 0x0D12,0x0000, 0x0D13,0x0000, /* 28E0 */ +0x0D14,0x0000, 0x0D15,0x0000, 0x0D16,0x0000, 0x0D17,0x0000, /* 28E4 */ +0x0D18,0x0000, 0x0D19,0x0000, 0x0D1A,0x0000, 0x0D1B,0x0000, /* 28E8 */ +0x0D1C,0x0000, 0x0D1D,0x0000, 0x0D1E,0x0000, 0x0D1F,0x0000, /* 28EC */ +0x0D20,0x0000, 0x0D21,0x0000, 0x0D22,0x0000, 0x0D23,0x0000, /* 28F0 */ +0x0D24,0x0000, 0x0D25,0x0000, 0x0D26,0x0000, 0x0D27,0x0000, /* 28F4 */ +0x0D28,0x0000, 0x0D29,0x0000, 0x0D2A,0x0000, 0x0D2B,0x0000, /* 28F8 */ +0x0D2C,0x0000, 0x0D2D,0x0000, 0x0D2E,0x0000, 0x0D2F,0x0000 /* 28FC */ +}; + +uint16 uca520_p029[]= { /* 2900 (2 weights per char) */ +0x09F0,0x0000, 0x09F1,0x0000, 0x09F2,0x0000, 0x09F3,0x0000, /* 2900 */ +0x09F4,0x0000, 0x09F5,0x0000, 0x09F6,0x0000, 0x09F7,0x0000, /* 2904 */ +0x09F8,0x0000, 0x09F9,0x0000, 0x09FA,0x0000, 0x09FB,0x0000, /* 2908 */ +0x09FC,0x0000, 0x09FD,0x0000, 0x09FE,0x0000, 0x09FF,0x0000, /* 290C */ +0x0A00,0x0000, 0x0A01,0x0000, 0x0A02,0x0000, 0x0A03,0x0000, /* 2910 */ +0x0A04,0x0000, 0x0A05,0x0000, 0x0A06,0x0000, 0x0A07,0x0000, /* 2914 */ +0x0A08,0x0000, 0x0A09,0x0000, 0x0A0A,0x0000, 0x0A0B,0x0000, /* 2918 */ +0x0A0C,0x0000, 0x0A0D,0x0000, 0x0A0E,0x0000, 0x0A0F,0x0000, /* 291C */ +0x0A10,0x0000, 0x0A11,0x0000, 0x0A12,0x0000, 0x0A13,0x0000, /* 2920 */ +0x0A14,0x0000, 0x0A15,0x0000, 0x0A16,0x0000, 0x0A17,0x0000, /* 2924 */ +0x0A18,0x0000, 0x0A19,0x0000, 0x0A1A,0x0000, 0x0A1B,0x0000, /* 2928 */ +0x0A1C,0x0000, 0x0A1D,0x0000, 0x0A1E,0x0000, 0x0A1F,0x0000, /* 292C */ +0x0A20,0x0000, 0x0A21,0x0000, 0x0A22,0x0000, 0x0A23,0x0000, /* 2930 */ +0x0A24,0x0000, 0x0A25,0x0000, 0x0A26,0x0000, 0x0A27,0x0000, /* 2934 */ +0x0A28,0x0000, 0x0A29,0x0000, 0x0A2A,0x0000, 0x0A2B,0x0000, /* 2938 */ +0x0A2C,0x0000, 0x0A2D,0x0000, 0x0A2E,0x0000, 0x0A2F,0x0000, /* 293C */ +0x0A30,0x0000, 0x0A31,0x0000, 0x0A32,0x0000, 0x0A33,0x0000, /* 2940 */ +0x0A34,0x0000, 0x0A35,0x0000, 0x0A36,0x0000, 0x0A37,0x0000, /* 2944 */ +0x0A38,0x0000, 0x0A39,0x0000, 0x0A3A,0x0000, 0x0A3B,0x0000, /* 2948 */ +0x0A3C,0x0000, 0x0A3D,0x0000, 0x0A3E,0x0000, 0x0A3F,0x0000, /* 294C */ +0x0A40,0x0000, 0x0A41,0x0000, 0x0A42,0x0000, 0x0A43,0x0000, /* 2950 */ +0x0A44,0x0000, 0x0A45,0x0000, 0x0A46,0x0000, 0x0A47,0x0000, /* 2954 */ +0x0A48,0x0000, 0x0A49,0x0000, 0x0A4A,0x0000, 0x0A4B,0x0000, /* 2958 */ +0x0A4C,0x0000, 0x0A4D,0x0000, 0x0A4E,0x0000, 0x0A4F,0x0000, /* 295C */ +0x0A50,0x0000, 0x0A51,0x0000, 0x0A52,0x0000, 0x0A53,0x0000, /* 2960 */ +0x0A54,0x0000, 0x0A55,0x0000, 0x0A56,0x0000, 0x0A57,0x0000, /* 2964 */ +0x0A58,0x0000, 0x0A59,0x0000, 0x0A5A,0x0000, 0x0A5B,0x0000, /* 2968 */ +0x0A5C,0x0000, 0x0A5D,0x0000, 0x0A5E,0x0000, 0x0A5F,0x0000, /* 296C */ +0x0A60,0x0000, 0x0A61,0x0000, 0x0A62,0x0000, 0x0A63,0x0000, /* 2970 */ +0x0A64,0x0000, 0x0A65,0x0000, 0x0A66,0x0000, 0x0A67,0x0000, /* 2974 */ +0x0A68,0x0000, 0x0A69,0x0000, 0x0A6A,0x0000, 0x0A6B,0x0000, /* 2978 */ +0x0A6C,0x0000, 0x0A6D,0x0000, 0x0A6E,0x0000, 0x0A6F,0x0000, /* 297C */ +0x0A70,0x0000, 0x0A71,0x0000, 0x0A72,0x0000, 0x030F,0x0000, /* 2980 */ +0x0310,0x0000, 0x0311,0x0000, 0x0312,0x0000, 0x0313,0x0000, /* 2984 */ +0x0314,0x0000, 0x0315,0x0000, 0x0316,0x0000, 0x0317,0x0000, /* 2988 */ +0x0318,0x0000, 0x0319,0x0000, 0x031A,0x0000, 0x031B,0x0000, /* 298C */ +0x031C,0x0000, 0x031D,0x0000, 0x031E,0x0000, 0x031F,0x0000, /* 2990 */ +0x0320,0x0000, 0x0321,0x0000, 0x0322,0x0000, 0x0323,0x0000, /* 2994 */ +0x0324,0x0000, 0x0A73,0x0000, 0x0A74,0x0000, 0x0A75,0x0000, /* 2998 */ +0x0A76,0x0000, 0x0A77,0x0000, 0x0A78,0x0000, 0x0A79,0x0000, /* 299C */ +0x0A7A,0x0000, 0x0A7B,0x0000, 0x0A7C,0x0000, 0x0A7D,0x0000, /* 29A0 */ +0x0A7E,0x0000, 0x0A7F,0x0000, 0x0A80,0x0000, 0x0A81,0x0000, /* 29A4 */ +0x0A82,0x0000, 0x0A83,0x0000, 0x0A84,0x0000, 0x0A85,0x0000, /* 29A8 */ +0x0A86,0x0000, 0x0A87,0x0000, 0x0A88,0x0000, 0x0A89,0x0000, /* 29AC */ +0x0A8A,0x0000, 0x0A8B,0x0000, 0x0A8C,0x0000, 0x0A8D,0x0000, /* 29B0 */ +0x0A8E,0x0000, 0x0A8F,0x0000, 0x0A90,0x0000, 0x0A91,0x0000, /* 29B4 */ +0x0A92,0x0000, 0x0A93,0x0000, 0x0A94,0x0000, 0x0A95,0x0000, /* 29B8 */ +0x0A96,0x0000, 0x0A97,0x0000, 0x0A98,0x0000, 0x0A99,0x0000, /* 29BC */ +0x0A9A,0x0000, 0x0A9B,0x0000, 0x0A9C,0x0000, 0x0A9D,0x0000, /* 29C0 */ +0x0A9E,0x0000, 0x0A9F,0x0000, 0x0AA0,0x0000, 0x0AA1,0x0000, /* 29C4 */ +0x0AA2,0x0000, 0x0AA3,0x0000, 0x0AA4,0x0000, 0x0AA5,0x0000, /* 29C8 */ +0x0AA6,0x0000, 0x0AA7,0x0000, 0x0AA8,0x0000, 0x0AA9,0x0000, /* 29CC */ +0x0AAA,0x0000, 0x0AAB,0x0000, 0x0AAC,0x0000, 0x0AAD,0x0000, /* 29D0 */ +0x0AAE,0x0000, 0x0AAF,0x0000, 0x0AB0,0x0000, 0x0AB1,0x0000, /* 29D4 */ +0x0AB2,0x0000, 0x0AB3,0x0000, 0x0AB4,0x0000, 0x0AB5,0x0000, /* 29D8 */ +0x0AB6,0x0000, 0x0AB7,0x0000, 0x0AB8,0x0000, 0x0AB9,0x0000, /* 29DC */ +0x0ABA,0x0000, 0x0ABB,0x0000, 0x0ABC,0x0000, 0x0ABD,0x0000, /* 29E0 */ +0x0ABE,0x0000, 0x0ABF,0x0000, 0x0AC0,0x0000, 0x0AC1,0x0000, /* 29E4 */ +0x0AC2,0x0000, 0x0AC3,0x0000, 0x0AC4,0x0000, 0x0AC5,0x0000, /* 29E8 */ +0x0AC6,0x0000, 0x0AC7,0x0000, 0x0AC8,0x0000, 0x0AC9,0x0000, /* 29EC */ +0x0ACA,0x0000, 0x0ACB,0x0000, 0x0ACC,0x0000, 0x0ACD,0x0000, /* 29F0 */ +0x0ACE,0x0000, 0x0ACF,0x0000, 0x0AD0,0x0000, 0x0AD1,0x0000, /* 29F4 */ +0x0AD2,0x0000, 0x0AD3,0x0000, 0x0AD4,0x0000, 0x0AD5,0x0000, /* 29F8 */ +0x030D,0x0000, 0x030E,0x0000, 0x0AD6,0x0000, 0x0AD7,0x0000 /* 29FC */ +}; + +uint16 uca520_p02A[]= { /* 2A00 (5 weights per char) */ +0x0AD8,0x0000,0x0000,0x0000,0x0000, /* 2A00 */ +0x0AD9,0x0000,0x0000,0x0000,0x0000, /* 2A01 */ +0x0ADA,0x0000,0x0000,0x0000,0x0000, /* 2A02 */ +0x0ADB,0x0000,0x0000,0x0000,0x0000, /* 2A03 */ +0x0ADC,0x0000,0x0000,0x0000,0x0000, /* 2A04 */ +0x0ADD,0x0000,0x0000,0x0000,0x0000, /* 2A05 */ +0x0ADE,0x0000,0x0000,0x0000,0x0000, /* 2A06 */ +0x0ADF,0x0000,0x0000,0x0000,0x0000, /* 2A07 */ +0x0AE0,0x0000,0x0000,0x0000,0x0000, /* 2A08 */ +0x0AE1,0x0000,0x0000,0x0000,0x0000, /* 2A09 */ +0x0AE2,0x0000,0x0000,0x0000,0x0000, /* 2A0A */ +0x0AE3,0x0000,0x0000,0x0000,0x0000, /* 2A0B */ +0x0575,0x0575,0x0575,0x0575,0x0000, /* 2A0C */ +0x0AE4,0x0000,0x0000,0x0000,0x0000, /* 2A0D */ +0x0AE5,0x0000,0x0000,0x0000,0x0000, /* 2A0E */ +0x0AE6,0x0000,0x0000,0x0000,0x0000, /* 2A0F */ +0x0AE7,0x0000,0x0000,0x0000,0x0000, /* 2A10 */ +0x0AE8,0x0000,0x0000,0x0000,0x0000, /* 2A11 */ +0x0AE9,0x0000,0x0000,0x0000,0x0000, /* 2A12 */ +0x0AEA,0x0000,0x0000,0x0000,0x0000, /* 2A13 */ +0x0AEB,0x0000,0x0000,0x0000,0x0000, /* 2A14 */ +0x0AEC,0x0000,0x0000,0x0000,0x0000, /* 2A15 */ +0x0AED,0x0000,0x0000,0x0000,0x0000, /* 2A16 */ +0x0AEE,0x0000,0x0000,0x0000,0x0000, /* 2A17 */ +0x0AEF,0x0000,0x0000,0x0000,0x0000, /* 2A18 */ +0x0AF0,0x0000,0x0000,0x0000,0x0000, /* 2A19 */ +0x0AF1,0x0000,0x0000,0x0000,0x0000, /* 2A1A */ +0x0AF2,0x0000,0x0000,0x0000,0x0000, /* 2A1B */ +0x0AF3,0x0000,0x0000,0x0000,0x0000, /* 2A1C */ +0x0AF4,0x0000,0x0000,0x0000,0x0000, /* 2A1D */ +0x0AF5,0x0000,0x0000,0x0000,0x0000, /* 2A1E */ +0x0AF6,0x0000,0x0000,0x0000,0x0000, /* 2A1F */ +0x0AF7,0x0000,0x0000,0x0000,0x0000, /* 2A20 */ +0x0AF8,0x0000,0x0000,0x0000,0x0000, /* 2A21 */ +0x0AF9,0x0000,0x0000,0x0000,0x0000, /* 2A22 */ +0x0AFA,0x0000,0x0000,0x0000,0x0000, /* 2A23 */ +0x0AFB,0x0000,0x0000,0x0000,0x0000, /* 2A24 */ +0x0AFC,0x0000,0x0000,0x0000,0x0000, /* 2A25 */ +0x0AFD,0x0000,0x0000,0x0000,0x0000, /* 2A26 */ +0x0AFE,0x0000,0x0000,0x0000,0x0000, /* 2A27 */ +0x0AFF,0x0000,0x0000,0x0000,0x0000, /* 2A28 */ +0x0B00,0x0000,0x0000,0x0000,0x0000, /* 2A29 */ +0x0B01,0x0000,0x0000,0x0000,0x0000, /* 2A2A */ +0x0B02,0x0000,0x0000,0x0000,0x0000, /* 2A2B */ +0x0B03,0x0000,0x0000,0x0000,0x0000, /* 2A2C */ +0x0B04,0x0000,0x0000,0x0000,0x0000, /* 2A2D */ +0x0B05,0x0000,0x0000,0x0000,0x0000, /* 2A2E */ +0x0B06,0x0000,0x0000,0x0000,0x0000, /* 2A2F */ +0x0B07,0x0000,0x0000,0x0000,0x0000, /* 2A30 */ +0x0B08,0x0000,0x0000,0x0000,0x0000, /* 2A31 */ +0x0B09,0x0000,0x0000,0x0000,0x0000, /* 2A32 */ +0x0B0A,0x0000,0x0000,0x0000,0x0000, /* 2A33 */ +0x0B0B,0x0000,0x0000,0x0000,0x0000, /* 2A34 */ +0x0B0C,0x0000,0x0000,0x0000,0x0000, /* 2A35 */ +0x0B0D,0x0000,0x0000,0x0000,0x0000, /* 2A36 */ +0x0B0E,0x0000,0x0000,0x0000,0x0000, /* 2A37 */ +0x0B0F,0x0000,0x0000,0x0000,0x0000, /* 2A38 */ +0x0B10,0x0000,0x0000,0x0000,0x0000, /* 2A39 */ +0x0B11,0x0000,0x0000,0x0000,0x0000, /* 2A3A */ +0x0B12,0x0000,0x0000,0x0000,0x0000, /* 2A3B */ +0x0B13,0x0000,0x0000,0x0000,0x0000, /* 2A3C */ +0x0B14,0x0000,0x0000,0x0000,0x0000, /* 2A3D */ +0x0B15,0x0000,0x0000,0x0000,0x0000, /* 2A3E */ +0x0B16,0x0000,0x0000,0x0000,0x0000, /* 2A3F */ +0x0B17,0x0000,0x0000,0x0000,0x0000, /* 2A40 */ +0x0B18,0x0000,0x0000,0x0000,0x0000, /* 2A41 */ +0x0B19,0x0000,0x0000,0x0000,0x0000, /* 2A42 */ +0x0B1A,0x0000,0x0000,0x0000,0x0000, /* 2A43 */ +0x0B1B,0x0000,0x0000,0x0000,0x0000, /* 2A44 */ +0x0B1C,0x0000,0x0000,0x0000,0x0000, /* 2A45 */ +0x0B1D,0x0000,0x0000,0x0000,0x0000, /* 2A46 */ +0x0B1E,0x0000,0x0000,0x0000,0x0000, /* 2A47 */ +0x0B1F,0x0000,0x0000,0x0000,0x0000, /* 2A48 */ +0x0B20,0x0000,0x0000,0x0000,0x0000, /* 2A49 */ +0x0B21,0x0000,0x0000,0x0000,0x0000, /* 2A4A */ +0x0B22,0x0000,0x0000,0x0000,0x0000, /* 2A4B */ +0x0B23,0x0000,0x0000,0x0000,0x0000, /* 2A4C */ +0x0B24,0x0000,0x0000,0x0000,0x0000, /* 2A4D */ +0x0B25,0x0000,0x0000,0x0000,0x0000, /* 2A4E */ +0x0B26,0x0000,0x0000,0x0000,0x0000, /* 2A4F */ +0x0B27,0x0000,0x0000,0x0000,0x0000, /* 2A50 */ +0x0B28,0x0000,0x0000,0x0000,0x0000, /* 2A51 */ +0x0B29,0x0000,0x0000,0x0000,0x0000, /* 2A52 */ +0x0B2A,0x0000,0x0000,0x0000,0x0000, /* 2A53 */ +0x0B2B,0x0000,0x0000,0x0000,0x0000, /* 2A54 */ +0x0B2C,0x0000,0x0000,0x0000,0x0000, /* 2A55 */ +0x0B2D,0x0000,0x0000,0x0000,0x0000, /* 2A56 */ +0x0B2E,0x0000,0x0000,0x0000,0x0000, /* 2A57 */ +0x0B2F,0x0000,0x0000,0x0000,0x0000, /* 2A58 */ +0x0B30,0x0000,0x0000,0x0000,0x0000, /* 2A59 */ +0x0B31,0x0000,0x0000,0x0000,0x0000, /* 2A5A */ +0x0B32,0x0000,0x0000,0x0000,0x0000, /* 2A5B */ +0x0B33,0x0000,0x0000,0x0000,0x0000, /* 2A5C */ +0x0B34,0x0000,0x0000,0x0000,0x0000, /* 2A5D */ +0x0B35,0x0000,0x0000,0x0000,0x0000, /* 2A5E */ +0x0B36,0x0000,0x0000,0x0000,0x0000, /* 2A5F */ +0x0B37,0x0000,0x0000,0x0000,0x0000, /* 2A60 */ +0x0B38,0x0000,0x0000,0x0000,0x0000, /* 2A61 */ +0x0B39,0x0000,0x0000,0x0000,0x0000, /* 2A62 */ +0x0B3A,0x0000,0x0000,0x0000,0x0000, /* 2A63 */ +0x0B3B,0x0000,0x0000,0x0000,0x0000, /* 2A64 */ +0x0B3C,0x0000,0x0000,0x0000,0x0000, /* 2A65 */ +0x0B3D,0x0000,0x0000,0x0000,0x0000, /* 2A66 */ +0x0B3E,0x0000,0x0000,0x0000,0x0000, /* 2A67 */ +0x0B3F,0x0000,0x0000,0x0000,0x0000, /* 2A68 */ +0x0B40,0x0000,0x0000,0x0000,0x0000, /* 2A69 */ +0x0B41,0x0000,0x0000,0x0000,0x0000, /* 2A6A */ +0x0B42,0x0000,0x0000,0x0000,0x0000, /* 2A6B */ +0x0B43,0x0000,0x0000,0x0000,0x0000, /* 2A6C */ +0x0B44,0x0000,0x0000,0x0000,0x0000, /* 2A6D */ +0x0B45,0x0000,0x0000,0x0000,0x0000, /* 2A6E */ +0x0B46,0x0000,0x0000,0x0000,0x0000, /* 2A6F */ +0x0B47,0x0000,0x0000,0x0000,0x0000, /* 2A70 */ +0x0B48,0x0000,0x0000,0x0000,0x0000, /* 2A71 */ +0x0B49,0x0000,0x0000,0x0000,0x0000, /* 2A72 */ +0x0B4A,0x0000,0x0000,0x0000,0x0000, /* 2A73 */ +0x0247,0x0247,0x0555,0x0000,0x0000, /* 2A74 */ +0x0555,0x0555,0x0000,0x0000,0x0000, /* 2A75 */ +0x0555,0x0555,0x0555,0x0000,0x0000, /* 2A76 */ +0x0B4B,0x0000,0x0000,0x0000,0x0000, /* 2A77 */ +0x0B4C,0x0000,0x0000,0x0000,0x0000, /* 2A78 */ +0x0B4D,0x0000,0x0000,0x0000,0x0000, /* 2A79 */ +0x0B4E,0x0000,0x0000,0x0000,0x0000, /* 2A7A */ +0x0B4F,0x0000,0x0000,0x0000,0x0000, /* 2A7B */ +0x0B50,0x0000,0x0000,0x0000,0x0000, /* 2A7C */ +0x0B51,0x0000,0x0000,0x0000,0x0000, /* 2A7D */ +0x0B52,0x0000,0x0000,0x0000,0x0000, /* 2A7E */ +0x0B53,0x0000,0x0000,0x0000,0x0000, /* 2A7F */ +0x0B54,0x0000,0x0000,0x0000,0x0000, /* 2A80 */ +0x0B55,0x0000,0x0000,0x0000,0x0000, /* 2A81 */ +0x0B56,0x0000,0x0000,0x0000,0x0000, /* 2A82 */ +0x0B57,0x0000,0x0000,0x0000,0x0000, /* 2A83 */ +0x0B58,0x0000,0x0000,0x0000,0x0000, /* 2A84 */ +0x0B59,0x0000,0x0000,0x0000,0x0000, /* 2A85 */ +0x0B5A,0x0000,0x0000,0x0000,0x0000, /* 2A86 */ +0x0B5B,0x0000,0x0000,0x0000,0x0000, /* 2A87 */ +0x0B5C,0x0000,0x0000,0x0000,0x0000, /* 2A88 */ +0x0B5D,0x0000,0x0000,0x0000,0x0000, /* 2A89 */ +0x0B5E,0x0000,0x0000,0x0000,0x0000, /* 2A8A */ +0x0B5F,0x0000,0x0000,0x0000,0x0000, /* 2A8B */ +0x0B60,0x0000,0x0000,0x0000,0x0000, /* 2A8C */ +0x0B61,0x0000,0x0000,0x0000,0x0000, /* 2A8D */ +0x0B62,0x0000,0x0000,0x0000,0x0000, /* 2A8E */ +0x0B63,0x0000,0x0000,0x0000,0x0000, /* 2A8F */ +0x0B64,0x0000,0x0000,0x0000,0x0000, /* 2A90 */ +0x0B65,0x0000,0x0000,0x0000,0x0000, /* 2A91 */ +0x0B66,0x0000,0x0000,0x0000,0x0000, /* 2A92 */ +0x0B67,0x0000,0x0000,0x0000,0x0000, /* 2A93 */ +0x0B68,0x0000,0x0000,0x0000,0x0000, /* 2A94 */ +0x0B69,0x0000,0x0000,0x0000,0x0000, /* 2A95 */ +0x0B6A,0x0000,0x0000,0x0000,0x0000, /* 2A96 */ +0x0B6B,0x0000,0x0000,0x0000,0x0000, /* 2A97 */ +0x0B6C,0x0000,0x0000,0x0000,0x0000, /* 2A98 */ +0x0B6D,0x0000,0x0000,0x0000,0x0000, /* 2A99 */ +0x0B6E,0x0000,0x0000,0x0000,0x0000, /* 2A9A */ +0x0B6F,0x0000,0x0000,0x0000,0x0000, /* 2A9B */ +0x0B70,0x0000,0x0000,0x0000,0x0000, /* 2A9C */ +0x0B71,0x0000,0x0000,0x0000,0x0000, /* 2A9D */ +0x0B72,0x0000,0x0000,0x0000,0x0000, /* 2A9E */ +0x0B73,0x0000,0x0000,0x0000,0x0000, /* 2A9F */ +0x0B74,0x0000,0x0000,0x0000,0x0000, /* 2AA0 */ +0x0B75,0x0000,0x0000,0x0000,0x0000, /* 2AA1 */ +0x0B76,0x0000,0x0000,0x0000,0x0000, /* 2AA2 */ +0x0B77,0x0000,0x0000,0x0000,0x0000, /* 2AA3 */ +0x0B78,0x0000,0x0000,0x0000,0x0000, /* 2AA4 */ +0x0B79,0x0000,0x0000,0x0000,0x0000, /* 2AA5 */ +0x0B7A,0x0000,0x0000,0x0000,0x0000, /* 2AA6 */ +0x0B7B,0x0000,0x0000,0x0000,0x0000, /* 2AA7 */ +0x0B7C,0x0000,0x0000,0x0000,0x0000, /* 2AA8 */ +0x0B7D,0x0000,0x0000,0x0000,0x0000, /* 2AA9 */ +0x0B7E,0x0000,0x0000,0x0000,0x0000, /* 2AAA */ +0x0B7F,0x0000,0x0000,0x0000,0x0000, /* 2AAB */ +0x0B80,0x0000,0x0000,0x0000,0x0000, /* 2AAC */ +0x0B81,0x0000,0x0000,0x0000,0x0000, /* 2AAD */ +0x0B82,0x0000,0x0000,0x0000,0x0000, /* 2AAE */ +0x0B83,0x0000,0x0000,0x0000,0x0000, /* 2AAF */ +0x0B84,0x0000,0x0000,0x0000,0x0000, /* 2AB0 */ +0x0B85,0x0000,0x0000,0x0000,0x0000, /* 2AB1 */ +0x0B86,0x0000,0x0000,0x0000,0x0000, /* 2AB2 */ +0x0B87,0x0000,0x0000,0x0000,0x0000, /* 2AB3 */ +0x0B88,0x0000,0x0000,0x0000,0x0000, /* 2AB4 */ +0x0B89,0x0000,0x0000,0x0000,0x0000, /* 2AB5 */ +0x0B8A,0x0000,0x0000,0x0000,0x0000, /* 2AB6 */ +0x0B8B,0x0000,0x0000,0x0000,0x0000, /* 2AB7 */ +0x0B8C,0x0000,0x0000,0x0000,0x0000, /* 2AB8 */ +0x0B8D,0x0000,0x0000,0x0000,0x0000, /* 2AB9 */ +0x0B8E,0x0000,0x0000,0x0000,0x0000, /* 2ABA */ +0x0B8F,0x0000,0x0000,0x0000,0x0000, /* 2ABB */ +0x0B90,0x0000,0x0000,0x0000,0x0000, /* 2ABC */ +0x0B91,0x0000,0x0000,0x0000,0x0000, /* 2ABD */ +0x0B92,0x0000,0x0000,0x0000,0x0000, /* 2ABE */ +0x0B93,0x0000,0x0000,0x0000,0x0000, /* 2ABF */ +0x0B94,0x0000,0x0000,0x0000,0x0000, /* 2AC0 */ +0x0B95,0x0000,0x0000,0x0000,0x0000, /* 2AC1 */ +0x0B96,0x0000,0x0000,0x0000,0x0000, /* 2AC2 */ +0x0B97,0x0000,0x0000,0x0000,0x0000, /* 2AC3 */ +0x0B98,0x0000,0x0000,0x0000,0x0000, /* 2AC4 */ +0x0B99,0x0000,0x0000,0x0000,0x0000, /* 2AC5 */ +0x0B9A,0x0000,0x0000,0x0000,0x0000, /* 2AC6 */ +0x0B9B,0x0000,0x0000,0x0000,0x0000, /* 2AC7 */ +0x0B9C,0x0000,0x0000,0x0000,0x0000, /* 2AC8 */ +0x0B9D,0x0000,0x0000,0x0000,0x0000, /* 2AC9 */ +0x0B9E,0x0000,0x0000,0x0000,0x0000, /* 2ACA */ +0x0B9F,0x0000,0x0000,0x0000,0x0000, /* 2ACB */ +0x0BA0,0x0000,0x0000,0x0000,0x0000, /* 2ACC */ +0x0BA1,0x0000,0x0000,0x0000,0x0000, /* 2ACD */ +0x0BA2,0x0000,0x0000,0x0000,0x0000, /* 2ACE */ +0x0BA3,0x0000,0x0000,0x0000,0x0000, /* 2ACF */ +0x0BA4,0x0000,0x0000,0x0000,0x0000, /* 2AD0 */ +0x0BA5,0x0000,0x0000,0x0000,0x0000, /* 2AD1 */ +0x0BA6,0x0000,0x0000,0x0000,0x0000, /* 2AD2 */ +0x0BA7,0x0000,0x0000,0x0000,0x0000, /* 2AD3 */ +0x0BA8,0x0000,0x0000,0x0000,0x0000, /* 2AD4 */ +0x0BA9,0x0000,0x0000,0x0000,0x0000, /* 2AD5 */ +0x0BAA,0x0000,0x0000,0x0000,0x0000, /* 2AD6 */ +0x0BAB,0x0000,0x0000,0x0000,0x0000, /* 2AD7 */ +0x0BAC,0x0000,0x0000,0x0000,0x0000, /* 2AD8 */ +0x0BAD,0x0000,0x0000,0x0000,0x0000, /* 2AD9 */ +0x0BAE,0x0000,0x0000,0x0000,0x0000, /* 2ADA */ +0x0BAF,0x0000,0x0000,0x0000,0x0000, /* 2ADB */ +0x0BB0,0x0000,0x0000,0x0000,0x0000, /* 2ADC */ +0x0BB0,0x0000,0x0000,0x0000,0x0000, /* 2ADD */ +0x0BB1,0x0000,0x0000,0x0000,0x0000, /* 2ADE */ +0x0BB2,0x0000,0x0000,0x0000,0x0000, /* 2ADF */ +0x0BB3,0x0000,0x0000,0x0000,0x0000, /* 2AE0 */ +0x0BB4,0x0000,0x0000,0x0000,0x0000, /* 2AE1 */ +0x0BB5,0x0000,0x0000,0x0000,0x0000, /* 2AE2 */ +0x0BB6,0x0000,0x0000,0x0000,0x0000, /* 2AE3 */ +0x0BB7,0x0000,0x0000,0x0000,0x0000, /* 2AE4 */ +0x0BB8,0x0000,0x0000,0x0000,0x0000, /* 2AE5 */ +0x0BB9,0x0000,0x0000,0x0000,0x0000, /* 2AE6 */ +0x0BBA,0x0000,0x0000,0x0000,0x0000, /* 2AE7 */ +0x0BBB,0x0000,0x0000,0x0000,0x0000, /* 2AE8 */ +0x0BBC,0x0000,0x0000,0x0000,0x0000, /* 2AE9 */ +0x0BBD,0x0000,0x0000,0x0000,0x0000, /* 2AEA */ +0x0BBE,0x0000,0x0000,0x0000,0x0000, /* 2AEB */ +0x0BBF,0x0000,0x0000,0x0000,0x0000, /* 2AEC */ +0x0BC0,0x0000,0x0000,0x0000,0x0000, /* 2AED */ +0x0BC1,0x0000,0x0000,0x0000,0x0000, /* 2AEE */ +0x0BC2,0x0000,0x0000,0x0000,0x0000, /* 2AEF */ +0x0BC3,0x0000,0x0000,0x0000,0x0000, /* 2AF0 */ +0x0BC4,0x0000,0x0000,0x0000,0x0000, /* 2AF1 */ +0x0BC5,0x0000,0x0000,0x0000,0x0000, /* 2AF2 */ +0x0BC6,0x0000,0x0000,0x0000,0x0000, /* 2AF3 */ +0x0BC7,0x0000,0x0000,0x0000,0x0000, /* 2AF4 */ +0x0BC8,0x0000,0x0000,0x0000,0x0000, /* 2AF5 */ +0x0BC9,0x0000,0x0000,0x0000,0x0000, /* 2AF6 */ +0x0BCA,0x0000,0x0000,0x0000,0x0000, /* 2AF7 */ +0x0BCB,0x0000,0x0000,0x0000,0x0000, /* 2AF8 */ +0x0BCC,0x0000,0x0000,0x0000,0x0000, /* 2AF9 */ +0x0BCD,0x0000,0x0000,0x0000,0x0000, /* 2AFA */ +0x0BCE,0x0000,0x0000,0x0000,0x0000, /* 2AFB */ +0x0BCF,0x0000,0x0000,0x0000,0x0000, /* 2AFC */ +0x0BD0,0x0000,0x0000,0x0000,0x0000, /* 2AFD */ +0x0BD1,0x0000,0x0000,0x0000,0x0000, /* 2AFE */ +0x0BD2,0x0000,0x0000,0x0000,0x0000 /* 2AFF */ +}; + +uint16 uca520_p02B[]= { /* 2B00 (3 weights per char) */ +0x0BD3,0x0000,0x0000, 0x0BD4,0x0000,0x0000, 0x0BD5,0x0000,0x0000, /* 2B00 */ +0x0BD6,0x0000,0x0000, 0x0BD7,0x0000,0x0000, 0x0BD8,0x0000,0x0000, /* 2B03 */ +0x0BD9,0x0000,0x0000, 0x0BDA,0x0000,0x0000, 0x0BDB,0x0000,0x0000, /* 2B06 */ +0x0BDC,0x0000,0x0000, 0x0BDD,0x0000,0x0000, 0x0BDE,0x0000,0x0000, /* 2B09 */ +0x0BDF,0x0000,0x0000, 0x0BE0,0x0000,0x0000, 0x0BE1,0x0000,0x0000, /* 2B0C */ +0x0BE2,0x0000,0x0000, 0x0BE3,0x0000,0x0000, 0x0BE4,0x0000,0x0000, /* 2B0F */ +0x0BE5,0x0000,0x0000, 0x0BE6,0x0000,0x0000, 0x0BE7,0x0000,0x0000, /* 2B12 */ +0x0BE8,0x0000,0x0000, 0x0BE9,0x0000,0x0000, 0x0BEA,0x0000,0x0000, /* 2B15 */ +0x0BEB,0x0000,0x0000, 0x0BEC,0x0000,0x0000, 0x0BED,0x0000,0x0000, /* 2B18 */ +0x0BEE,0x0000,0x0000, 0x0BEF,0x0000,0x0000, 0x0BF0,0x0000,0x0000, /* 2B1B */ +0x0BF1,0x0000,0x0000, 0x0BF2,0x0000,0x0000, 0x0BF3,0x0000,0x0000, /* 2B1E */ +0x0BF4,0x0000,0x0000, 0x0BF5,0x0000,0x0000, 0x0BF6,0x0000,0x0000, /* 2B21 */ +0x0BF7,0x0000,0x0000, 0x0BF8,0x0000,0x0000, 0x0BF9,0x0000,0x0000, /* 2B24 */ +0x0BFA,0x0000,0x0000, 0x0BFB,0x0000,0x0000, 0x0BFC,0x0000,0x0000, /* 2B27 */ +0x0BFD,0x0000,0x0000, 0x0BFE,0x0000,0x0000, 0x0BFF,0x0000,0x0000, /* 2B2A */ +0x0C00,0x0000,0x0000, 0x0C01,0x0000,0x0000, 0x0C02,0x0000,0x0000, /* 2B2D */ +0x0C03,0x0000,0x0000, 0x0C04,0x0000,0x0000, 0x0C05,0x0000,0x0000, /* 2B30 */ +0x0C06,0x0000,0x0000, 0x0C07,0x0000,0x0000, 0x0C08,0x0000,0x0000, /* 2B33 */ +0x0C09,0x0000,0x0000, 0x0C0A,0x0000,0x0000, 0x0C0B,0x0000,0x0000, /* 2B36 */ +0x0C0C,0x0000,0x0000, 0x0C0D,0x0000,0x0000, 0x0C0E,0x0000,0x0000, /* 2B39 */ +0x0C0F,0x0000,0x0000, 0x0C10,0x0000,0x0000, 0x0C11,0x0000,0x0000, /* 2B3C */ +0x0C12,0x0000,0x0000, 0x0C13,0x0000,0x0000, 0x0C14,0x0000,0x0000, /* 2B3F */ +0x0C15,0x0000,0x0000, 0x0C16,0x0000,0x0000, 0x0C17,0x0000,0x0000, /* 2B42 */ +0x0C18,0x0000,0x0000, 0x0C19,0x0000,0x0000, 0x0C1A,0x0000,0x0000, /* 2B45 */ +0x0C1B,0x0000,0x0000, 0x0C1C,0x0000,0x0000, 0x0C1D,0x0000,0x0000, /* 2B48 */ +0x0C1E,0x0000,0x0000, 0x0C1F,0x0000,0x0000, 0xFBC0,0xAB4D,0x0000, /* 2B4B */ +0xFBC0,0xAB4E,0x0000, 0xFBC0,0xAB4F,0x0000, 0x0C20,0x0000,0x0000, /* 2B4E */ +0x0C21,0x0000,0x0000, 0x0C22,0x0000,0x0000, 0x0C23,0x0000,0x0000, /* 2B51 */ +0x0C24,0x0000,0x0000, 0x0C25,0x0000,0x0000, 0x0C26,0x0000,0x0000, /* 2B54 */ +0x0C27,0x0000,0x0000, 0x0C28,0x0000,0x0000, 0x0C29,0x0000,0x0000, /* 2B57 */ +0xFBC0,0xAB5A,0x0000, 0xFBC0,0xAB5B,0x0000, 0xFBC0,0xAB5C,0x0000, /* 2B5A */ +0xFBC0,0xAB5D,0x0000, 0xFBC0,0xAB5E,0x0000, 0xFBC0,0xAB5F,0x0000, /* 2B5D */ +0xFBC0,0xAB60,0x0000, 0xFBC0,0xAB61,0x0000, 0xFBC0,0xAB62,0x0000, /* 2B60 */ +0xFBC0,0xAB63,0x0000, 0xFBC0,0xAB64,0x0000, 0xFBC0,0xAB65,0x0000, /* 2B63 */ +0xFBC0,0xAB66,0x0000, 0xFBC0,0xAB67,0x0000, 0xFBC0,0xAB68,0x0000, /* 2B66 */ +0xFBC0,0xAB69,0x0000, 0xFBC0,0xAB6A,0x0000, 0xFBC0,0xAB6B,0x0000, /* 2B69 */ +0xFBC0,0xAB6C,0x0000, 0xFBC0,0xAB6D,0x0000, 0xFBC0,0xAB6E,0x0000, /* 2B6C */ +0xFBC0,0xAB6F,0x0000, 0xFBC0,0xAB70,0x0000, 0xFBC0,0xAB71,0x0000, /* 2B6F */ +0xFBC0,0xAB72,0x0000, 0xFBC0,0xAB73,0x0000, 0xFBC0,0xAB74,0x0000, /* 2B72 */ +0xFBC0,0xAB75,0x0000, 0xFBC0,0xAB76,0x0000, 0xFBC0,0xAB77,0x0000, /* 2B75 */ +0xFBC0,0xAB78,0x0000, 0xFBC0,0xAB79,0x0000, 0xFBC0,0xAB7A,0x0000, /* 2B78 */ +0xFBC0,0xAB7B,0x0000, 0xFBC0,0xAB7C,0x0000, 0xFBC0,0xAB7D,0x0000, /* 2B7B */ +0xFBC0,0xAB7E,0x0000, 0xFBC0,0xAB7F,0x0000, 0xFBC0,0xAB80,0x0000, /* 2B7E */ +0xFBC0,0xAB81,0x0000, 0xFBC0,0xAB82,0x0000, 0xFBC0,0xAB83,0x0000, /* 2B81 */ +0xFBC0,0xAB84,0x0000, 0xFBC0,0xAB85,0x0000, 0xFBC0,0xAB86,0x0000, /* 2B84 */ +0xFBC0,0xAB87,0x0000, 0xFBC0,0xAB88,0x0000, 0xFBC0,0xAB89,0x0000, /* 2B87 */ +0xFBC0,0xAB8A,0x0000, 0xFBC0,0xAB8B,0x0000, 0xFBC0,0xAB8C,0x0000, /* 2B8A */ +0xFBC0,0xAB8D,0x0000, 0xFBC0,0xAB8E,0x0000, 0xFBC0,0xAB8F,0x0000, /* 2B8D */ +0xFBC0,0xAB90,0x0000, 0xFBC0,0xAB91,0x0000, 0xFBC0,0xAB92,0x0000, /* 2B90 */ +0xFBC0,0xAB93,0x0000, 0xFBC0,0xAB94,0x0000, 0xFBC0,0xAB95,0x0000, /* 2B93 */ +0xFBC0,0xAB96,0x0000, 0xFBC0,0xAB97,0x0000, 0xFBC0,0xAB98,0x0000, /* 2B96 */ +0xFBC0,0xAB99,0x0000, 0xFBC0,0xAB9A,0x0000, 0xFBC0,0xAB9B,0x0000, /* 2B99 */ +0xFBC0,0xAB9C,0x0000, 0xFBC0,0xAB9D,0x0000, 0xFBC0,0xAB9E,0x0000, /* 2B9C */ +0xFBC0,0xAB9F,0x0000, 0xFBC0,0xABA0,0x0000, 0xFBC0,0xABA1,0x0000, /* 2B9F */ +0xFBC0,0xABA2,0x0000, 0xFBC0,0xABA3,0x0000, 0xFBC0,0xABA4,0x0000, /* 2BA2 */ +0xFBC0,0xABA5,0x0000, 0xFBC0,0xABA6,0x0000, 0xFBC0,0xABA7,0x0000, /* 2BA5 */ +0xFBC0,0xABA8,0x0000, 0xFBC0,0xABA9,0x0000, 0xFBC0,0xABAA,0x0000, /* 2BA8 */ +0xFBC0,0xABAB,0x0000, 0xFBC0,0xABAC,0x0000, 0xFBC0,0xABAD,0x0000, /* 2BAB */ +0xFBC0,0xABAE,0x0000, 0xFBC0,0xABAF,0x0000, 0xFBC0,0xABB0,0x0000, /* 2BAE */ +0xFBC0,0xABB1,0x0000, 0xFBC0,0xABB2,0x0000, 0xFBC0,0xABB3,0x0000, /* 2BB1 */ +0xFBC0,0xABB4,0x0000, 0xFBC0,0xABB5,0x0000, 0xFBC0,0xABB6,0x0000, /* 2BB4 */ +0xFBC0,0xABB7,0x0000, 0xFBC0,0xABB8,0x0000, 0xFBC0,0xABB9,0x0000, /* 2BB7 */ +0xFBC0,0xABBA,0x0000, 0xFBC0,0xABBB,0x0000, 0xFBC0,0xABBC,0x0000, /* 2BBA */ +0xFBC0,0xABBD,0x0000, 0xFBC0,0xABBE,0x0000, 0xFBC0,0xABBF,0x0000, /* 2BBD */ +0xFBC0,0xABC0,0x0000, 0xFBC0,0xABC1,0x0000, 0xFBC0,0xABC2,0x0000, /* 2BC0 */ +0xFBC0,0xABC3,0x0000, 0xFBC0,0xABC4,0x0000, 0xFBC0,0xABC5,0x0000, /* 2BC3 */ +0xFBC0,0xABC6,0x0000, 0xFBC0,0xABC7,0x0000, 0xFBC0,0xABC8,0x0000, /* 2BC6 */ +0xFBC0,0xABC9,0x0000, 0xFBC0,0xABCA,0x0000, 0xFBC0,0xABCB,0x0000, /* 2BC9 */ +0xFBC0,0xABCC,0x0000, 0xFBC0,0xABCD,0x0000, 0xFBC0,0xABCE,0x0000, /* 2BCC */ +0xFBC0,0xABCF,0x0000, 0xFBC0,0xABD0,0x0000, 0xFBC0,0xABD1,0x0000, /* 2BCF */ +0xFBC0,0xABD2,0x0000, 0xFBC0,0xABD3,0x0000, 0xFBC0,0xABD4,0x0000, /* 2BD2 */ +0xFBC0,0xABD5,0x0000, 0xFBC0,0xABD6,0x0000, 0xFBC0,0xABD7,0x0000, /* 2BD5 */ +0xFBC0,0xABD8,0x0000, 0xFBC0,0xABD9,0x0000, 0xFBC0,0xABDA,0x0000, /* 2BD8 */ +0xFBC0,0xABDB,0x0000, 0xFBC0,0xABDC,0x0000, 0xFBC0,0xABDD,0x0000, /* 2BDB */ +0xFBC0,0xABDE,0x0000, 0xFBC0,0xABDF,0x0000, 0xFBC0,0xABE0,0x0000, /* 2BDE */ +0xFBC0,0xABE1,0x0000, 0xFBC0,0xABE2,0x0000, 0xFBC0,0xABE3,0x0000, /* 2BE1 */ +0xFBC0,0xABE4,0x0000, 0xFBC0,0xABE5,0x0000, 0xFBC0,0xABE6,0x0000, /* 2BE4 */ +0xFBC0,0xABE7,0x0000, 0xFBC0,0xABE8,0x0000, 0xFBC0,0xABE9,0x0000, /* 2BE7 */ +0xFBC0,0xABEA,0x0000, 0xFBC0,0xABEB,0x0000, 0xFBC0,0xABEC,0x0000, /* 2BEA */ +0xFBC0,0xABED,0x0000, 0xFBC0,0xABEE,0x0000, 0xFBC0,0xABEF,0x0000, /* 2BED */ +0xFBC0,0xABF0,0x0000, 0xFBC0,0xABF1,0x0000, 0xFBC0,0xABF2,0x0000, /* 2BF0 */ +0xFBC0,0xABF3,0x0000, 0xFBC0,0xABF4,0x0000, 0xFBC0,0xABF5,0x0000, /* 2BF3 */ +0xFBC0,0xABF6,0x0000, 0xFBC0,0xABF7,0x0000, 0xFBC0,0xABF8,0x0000, /* 2BF6 */ +0xFBC0,0xABF9,0x0000, 0xFBC0,0xABFA,0x0000, 0xFBC0,0xABFB,0x0000, /* 2BF9 */ +0xFBC0,0xABFC,0x0000, 0xFBC0,0xABFD,0x0000, 0xFBC0,0xABFE,0x0000, /* 2BFC */ +0xFBC0,0xABFF,0x0000 }; + +uint16 uca520_p02C[]= { /* 2C00 (4 weights per char) */ +0x17B5,0x0000,0x0000,0x0000, 0x17B6,0x0000,0x0000,0x0000, /* 2C00 */ +0x17B7,0x0000,0x0000,0x0000, 0x17B8,0x0000,0x0000,0x0000, /* 2C02 */ +0x17B9,0x0000,0x0000,0x0000, 0x17BA,0x0000,0x0000,0x0000, /* 2C04 */ +0x17BB,0x0000,0x0000,0x0000, 0x17BC,0x0000,0x0000,0x0000, /* 2C06 */ +0x17BD,0x0000,0x0000,0x0000, 0x17BE,0x0000,0x0000,0x0000, /* 2C08 */ +0x17BF,0x0000,0x0000,0x0000, 0x17C0,0x0000,0x0000,0x0000, /* 2C0A */ +0x17C1,0x0000,0x0000,0x0000, 0x17C2,0x0000,0x0000,0x0000, /* 2C0C */ +0x17C3,0x0000,0x0000,0x0000, 0x17C4,0x0000,0x0000,0x0000, /* 2C0E */ +0x17C5,0x0000,0x0000,0x0000, 0x17C6,0x0000,0x0000,0x0000, /* 2C10 */ +0x17C7,0x0000,0x0000,0x0000, 0x17C8,0x0000,0x0000,0x0000, /* 2C12 */ +0x17C9,0x0000,0x0000,0x0000, 0x17CA,0x0000,0x0000,0x0000, /* 2C14 */ +0x17CB,0x0000,0x0000,0x0000, 0x17CC,0x0000,0x0000,0x0000, /* 2C16 */ +0x17CD,0x0000,0x0000,0x0000, 0x17CE,0x0000,0x0000,0x0000, /* 2C18 */ +0x17CF,0x0000,0x0000,0x0000, 0x17D0,0x0000,0x0000,0x0000, /* 2C1A */ +0x17D1,0x0000,0x0000,0x0000, 0x17D2,0x0000,0x0000,0x0000, /* 2C1C */ +0x17D3,0x0000,0x0000,0x0000, 0x17D4,0x0000,0x0000,0x0000, /* 2C1E */ +0x17D5,0x0000,0x0000,0x0000, 0x17D6,0x0000,0x0000,0x0000, /* 2C20 */ +0x17D7,0x0000,0x0000,0x0000, 0x17D8,0x0000,0x0000,0x0000, /* 2C22 */ +0x17D9,0x0000,0x0000,0x0000, 0x17DA,0x0000,0x0000,0x0000, /* 2C24 */ +0x17DB,0x0000,0x0000,0x0000, 0x17DC,0x0000,0x0000,0x0000, /* 2C26 */ +0x17DD,0x0000,0x0000,0x0000, 0x17DE,0x0000,0x0000,0x0000, /* 2C28 */ +0x17DF,0x0000,0x0000,0x0000, 0x17E0,0x0000,0x0000,0x0000, /* 2C2A */ +0x17E1,0x0000,0x0000,0x0000, 0x17E2,0x0000,0x0000,0x0000, /* 2C2C */ +0x17E3,0x0000,0x0000,0x0000, 0xFBC0,0xAC2F,0x0000,0x0000, /* 2C2E */ +0x17B5,0x0000,0x0000,0x0000, 0x17B6,0x0000,0x0000,0x0000, /* 2C30 */ +0x17B7,0x0000,0x0000,0x0000, 0x17B8,0x0000,0x0000,0x0000, /* 2C32 */ +0x17B9,0x0000,0x0000,0x0000, 0x17BA,0x0000,0x0000,0x0000, /* 2C34 */ +0x17BB,0x0000,0x0000,0x0000, 0x17BC,0x0000,0x0000,0x0000, /* 2C36 */ +0x17BD,0x0000,0x0000,0x0000, 0x17BE,0x0000,0x0000,0x0000, /* 2C38 */ +0x17BF,0x0000,0x0000,0x0000, 0x17C0,0x0000,0x0000,0x0000, /* 2C3A */ +0x17C1,0x0000,0x0000,0x0000, 0x17C2,0x0000,0x0000,0x0000, /* 2C3C */ +0x17C3,0x0000,0x0000,0x0000, 0x17C4,0x0000,0x0000,0x0000, /* 2C3E */ +0x17C5,0x0000,0x0000,0x0000, 0x17C6,0x0000,0x0000,0x0000, /* 2C40 */ +0x17C7,0x0000,0x0000,0x0000, 0x17C8,0x0000,0x0000,0x0000, /* 2C42 */ +0x17C9,0x0000,0x0000,0x0000, 0x17CA,0x0000,0x0000,0x0000, /* 2C44 */ +0x17CB,0x0000,0x0000,0x0000, 0x17CC,0x0000,0x0000,0x0000, /* 2C46 */ +0x17CD,0x0000,0x0000,0x0000, 0x17CE,0x0000,0x0000,0x0000, /* 2C48 */ +0x17CF,0x0000,0x0000,0x0000, 0x17D0,0x0000,0x0000,0x0000, /* 2C4A */ +0x17D1,0x0000,0x0000,0x0000, 0x17D2,0x0000,0x0000,0x0000, /* 2C4C */ +0x17D3,0x0000,0x0000,0x0000, 0x17D4,0x0000,0x0000,0x0000, /* 2C4E */ +0x17D5,0x0000,0x0000,0x0000, 0x17D6,0x0000,0x0000,0x0000, /* 2C50 */ +0x17D7,0x0000,0x0000,0x0000, 0x17D8,0x0000,0x0000,0x0000, /* 2C52 */ +0x17D9,0x0000,0x0000,0x0000, 0x17DA,0x0000,0x0000,0x0000, /* 2C54 */ +0x17DB,0x0000,0x0000,0x0000, 0x17DC,0x0000,0x0000,0x0000, /* 2C56 */ +0x17DD,0x0000,0x0000,0x0000, 0x17DE,0x0000,0x0000,0x0000, /* 2C58 */ +0x17DF,0x0000,0x0000,0x0000, 0x17E0,0x0000,0x0000,0x0000, /* 2C5A */ +0x17E1,0x0000,0x0000,0x0000, 0x17E2,0x0000,0x0000,0x0000, /* 2C5C */ +0x17E3,0x0000,0x0000,0x0000, 0xFBC0,0xAC5F,0x0000,0x0000, /* 2C5E */ +0x133F,0x0000,0x0000,0x0000, 0x133F,0x0000,0x0000,0x0000, /* 2C60 */ +0x1340,0x0000,0x0000,0x0000, 0x13B8,0x0000,0x0000,0x0000, /* 2C62 */ +0x13FC,0x0000,0x0000,0x0000, 0x1214,0x0000,0x0000,0x0000, /* 2C64 */ +0x143C,0x0000,0x0000,0x0000, 0x12E3,0x0000,0x0000,0x0000, /* 2C66 */ +0x12E3,0x0000,0x0000,0x0000, 0x1328,0x0000,0x0000,0x0000, /* 2C68 */ +0x1328,0x0000,0x0000,0x0000, 0x14C8,0x0000,0x0000,0x0000, /* 2C6A */ +0x14C8,0x0000,0x0000,0x0000, 0x121C,0x0000,0x0000,0x0000, /* 2C6C */ +0x1366,0x0000,0x0000,0x0000, 0x1218,0x0000,0x0000,0x0000, /* 2C6E */ +0x1221,0x0000,0x0000,0x0000, 0x1486,0x0000,0x0000,0x0000, /* 2C70 */ +0x1492,0x0000,0x0000,0x0000, 0x1492,0x0000,0x0000,0x0000, /* 2C72 */ +0x1487,0x0000,0x0000,0x0000, 0x12E4,0x0000,0x0000,0x0000, /* 2C74 */ +0x12E4,0x0000,0x0000,0x0000, 0x13C7,0x0000,0x0000,0x0000, /* 2C76 */ +0x1275,0x0000,0x0000,0x0000, 0x13F7,0x0000,0x0000,0x0000, /* 2C78 */ +0x13A4,0x0000,0x0000,0x0000, 0x127A,0x0000,0x0000,0x0000, /* 2C7A */ +0x1305,0x0000,0x0000,0x0000, 0x147B,0x0000,0x0000,0x0000, /* 2C7C */ +0x141B,0x0000,0x0000,0x0000, 0x14C4,0x0000,0x0000,0x0000, /* 2C7E */ +0x1571,0x0000,0x0000,0x0000, 0x1571,0x0000,0x0000,0x0000, /* 2C80 */ +0x1572,0x0000,0x0000,0x0000, 0x1572,0x0000,0x0000,0x0000, /* 2C82 */ +0x1573,0x0000,0x0000,0x0000, 0x1573,0x0000,0x0000,0x0000, /* 2C84 */ +0x1574,0x0000,0x0000,0x0000, 0x1574,0x0000,0x0000,0x0000, /* 2C86 */ +0x1575,0x0000,0x0000,0x0000, 0x1575,0x0000,0x0000,0x0000, /* 2C88 */ +0x1577,0x0000,0x0000,0x0000, 0x1577,0x0000,0x0000,0x0000, /* 2C8A */ +0x1578,0x0000,0x0000,0x0000, 0x1578,0x0000,0x0000,0x0000, /* 2C8C */ +0x1579,0x0000,0x0000,0x0000, 0x1579,0x0000,0x0000,0x0000, /* 2C8E */ +0x157A,0x0000,0x0000,0x0000, 0x157A,0x0000,0x0000,0x0000, /* 2C90 */ +0x157B,0x0000,0x0000,0x0000, 0x157B,0x0000,0x0000,0x0000, /* 2C92 */ +0x157C,0x0000,0x0000,0x0000, 0x157C,0x0000,0x0000,0x0000, /* 2C94 */ +0x157E,0x0000,0x0000,0x0000, 0x157E,0x0000,0x0000,0x0000, /* 2C96 */ +0x157F,0x0000,0x0000,0x0000, 0x157F,0x0000,0x0000,0x0000, /* 2C98 */ +0x1580,0x0000,0x0000,0x0000, 0x1580,0x0000,0x0000,0x0000, /* 2C9A */ +0x1583,0x0000,0x0000,0x0000, 0x1583,0x0000,0x0000,0x0000, /* 2C9C */ +0x1584,0x0000,0x0000,0x0000, 0x1584,0x0000,0x0000,0x0000, /* 2C9E */ +0x1585,0x0000,0x0000,0x0000, 0x1585,0x0000,0x0000,0x0000, /* 2CA0 */ +0x1586,0x0000,0x0000,0x0000, 0x1586,0x0000,0x0000,0x0000, /* 2CA2 */ +0x1587,0x0000,0x0000,0x0000, 0x1587,0x0000,0x0000,0x0000, /* 2CA4 */ +0x1588,0x0000,0x0000,0x0000, 0x1588,0x0000,0x0000,0x0000, /* 2CA6 */ +0x1589,0x0000,0x0000,0x0000, 0x1589,0x0000,0x0000,0x0000, /* 2CA8 */ +0x158A,0x0000,0x0000,0x0000, 0x158A,0x0000,0x0000,0x0000, /* 2CAA */ +0x158B,0x0000,0x0000,0x0000, 0x158B,0x0000,0x0000,0x0000, /* 2CAC */ +0x158C,0x0000,0x0000,0x0000, 0x158C,0x0000,0x0000,0x0000, /* 2CAE */ +0x158D,0x0000,0x0000,0x0000, 0x158D,0x0000,0x0000,0x0000, /* 2CB0 */ +0x15A7,0x0000,0x0000,0x0000, 0x15A7,0x0000,0x0000,0x0000, /* 2CB2 */ +0x15A8,0x0000,0x0000,0x0000, 0x15A8,0x0000,0x0000,0x0000, /* 2CB4 */ +0x1576,0x0000,0x0000,0x0000, 0x1576,0x0000,0x0000,0x0000, /* 2CB6 */ +0x157D,0x0000,0x0000,0x0000, 0x157D,0x0000,0x0000,0x0000, /* 2CB8 */ +0x1581,0x0000,0x0000,0x0000, 0x1581,0x0000,0x0000,0x0000, /* 2CBA */ +0x1582,0x0000,0x0000,0x0000, 0x1582,0x0000,0x0000,0x0000, /* 2CBC */ +0x158E,0x0000,0x0000,0x0000, 0x158E,0x0000,0x0000,0x0000, /* 2CBE */ +0x158F,0x0000,0x0000,0x0000, 0x158F,0x0000,0x0000,0x0000, /* 2CC0 */ +0x1592,0x0000,0x0000,0x0000, 0x1592,0x0000,0x0000,0x0000, /* 2CC2 */ +0x1593,0x0000,0x0000,0x0000, 0x1593,0x0000,0x0000,0x0000, /* 2CC4 */ +0x1594,0x0000,0x0000,0x0000, 0x1594,0x0000,0x0000,0x0000, /* 2CC6 */ +0x1597,0x0000,0x0000,0x0000, 0x1597,0x0000,0x0000,0x0000, /* 2CC8 */ +0x1599,0x0000,0x0000,0x0000, 0x1599,0x0000,0x0000,0x0000, /* 2CCA */ +0x159A,0x0000,0x0000,0x0000, 0x159A,0x0000,0x0000,0x0000, /* 2CCC */ +0x159B,0x0000,0x0000,0x0000, 0x159B,0x0000,0x0000,0x0000, /* 2CCE */ +0x159C,0x0000,0x0000,0x0000, 0x159C,0x0000,0x0000,0x0000, /* 2CD0 */ +0x159D,0x0000,0x0000,0x0000, 0x159D,0x0000,0x0000,0x0000, /* 2CD2 */ +0x159E,0x0000,0x0000,0x0000, 0x159E,0x0000,0x0000,0x0000, /* 2CD4 */ +0x15A1,0x0000,0x0000,0x0000, 0x15A1,0x0000,0x0000,0x0000, /* 2CD6 */ +0x15A3,0x0000,0x0000,0x0000, 0x15A3,0x0000,0x0000,0x0000, /* 2CD8 */ +0x15A4,0x0000,0x0000,0x0000, 0x15A4,0x0000,0x0000,0x0000, /* 2CDA */ +0x15A5,0x0000,0x0000,0x0000, 0x15A5,0x0000,0x0000,0x0000, /* 2CDC */ +0x15A9,0x0000,0x0000,0x0000, 0x15A9,0x0000,0x0000,0x0000, /* 2CDE */ +0x15AA,0x0000,0x0000,0x0000, 0x15AA,0x0000,0x0000,0x0000, /* 2CE0 */ +0x15AB,0x0000,0x0000,0x0000, 0x15AB,0x0000,0x0000,0x0000, /* 2CE2 */ +0x157C,0x1571,0x157B,0x0000, 0x0C2A,0x0000,0x0000,0x0000, /* 2CE4 */ +0x0C2B,0x0000,0x0000,0x0000, 0x0C2C,0x0000,0x0000,0x0000, /* 2CE6 */ +0x0C2D,0x0000,0x0000,0x0000, 0x0C2E,0x0000,0x0000,0x0000, /* 2CE8 */ +0x0C2F,0x0000,0x0000,0x0000, 0x1591,0x0000,0x0000,0x0000, /* 2CEA */ +0x1591,0x0000,0x0000,0x0000, 0x15A0,0x0000,0x0000,0x0000, /* 2CEC */ +0x15A0,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 2CEE */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* 2CF0 */ +0xFBC0,0xACF2,0x0000,0x0000, 0xFBC0,0xACF3,0x0000,0x0000, /* 2CF2 */ +0xFBC0,0xACF4,0x0000,0x0000, 0xFBC0,0xACF5,0x0000,0x0000, /* 2CF4 */ +0xFBC0,0xACF6,0x0000,0x0000, 0xFBC0,0xACF7,0x0000,0x0000, /* 2CF6 */ +0xFBC0,0xACF8,0x0000,0x0000, 0x028B,0x0000,0x0000,0x0000, /* 2CF8 */ +0x027B,0x0000,0x0000,0x0000, 0x027C,0x0000,0x0000,0x0000, /* 2CFA */ +0x02E0,0x0000,0x0000,0x0000, 0x114C,0x0000,0x0000,0x0000, /* 2CFC */ +0x028C,0x0000,0x0000,0x0000, 0x02E1,0x0000,0x0000,0x0000 /* 2CFE */ +}; + +uint16 uca520_p02D[]= { /* 2D00 (3 weights per char) */ +0x17E5,0x0000,0x0000, 0x17E7,0x0000,0x0000, 0x17E9,0x0000,0x0000, /* 2D00 */ +0x17EB,0x0000,0x0000, 0x17ED,0x0000,0x0000, 0x17EF,0x0000,0x0000, /* 2D03 */ +0x17F1,0x0000,0x0000, 0x17F5,0x0000,0x0000, 0x17F7,0x0000,0x0000, /* 2D06 */ +0x17F9,0x0000,0x0000, 0x17FB,0x0000,0x0000, 0x17FD,0x0000,0x0000, /* 2D09 */ +0x17FF,0x0000,0x0000, 0x1803,0x0000,0x0000, 0x1805,0x0000,0x0000, /* 2D0C */ +0x1807,0x0000,0x0000, 0x1809,0x0000,0x0000, 0x180B,0x0000,0x0000, /* 2D0F */ +0x180D,0x0000,0x0000, 0x1811,0x0000,0x0000, 0x1813,0x0000,0x0000, /* 2D12 */ +0x1815,0x0000,0x0000, 0x1817,0x0000,0x0000, 0x1819,0x0000,0x0000, /* 2D15 */ +0x181B,0x0000,0x0000, 0x181D,0x0000,0x0000, 0x181F,0x0000,0x0000, /* 2D18 */ +0x1821,0x0000,0x0000, 0x1823,0x0000,0x0000, 0x1825,0x0000,0x0000, /* 2D1B */ +0x1827,0x0000,0x0000, 0x182B,0x0000,0x0000, 0x182D,0x0000,0x0000, /* 2D1E */ +0x17F3,0x0000,0x0000, 0x1801,0x0000,0x0000, 0x180F,0x0000,0x0000, /* 2D21 */ +0x1829,0x0000,0x0000, 0x182F,0x0000,0x0000, 0xFBC0,0xAD26,0x0000, /* 2D24 */ +0xFBC0,0xAD27,0x0000, 0xFBC0,0xAD28,0x0000, 0xFBC0,0xAD29,0x0000, /* 2D27 */ +0xFBC0,0xAD2A,0x0000, 0xFBC0,0xAD2B,0x0000, 0xFBC0,0xAD2C,0x0000, /* 2D2A */ +0xFBC0,0xAD2D,0x0000, 0xFBC0,0xAD2E,0x0000, 0xFBC0,0xAD2F,0x0000, /* 2D2D */ +0x19CC,0x0000,0x0000, 0x19CD,0x0000,0x0000, 0x19CE,0x0000,0x0000, /* 2D30 */ +0x19CF,0x0000,0x0000, 0x19D0,0x0000,0x0000, 0x19D1,0x0000,0x0000, /* 2D33 */ +0x19D2,0x0000,0x0000, 0x19D3,0x0000,0x0000, 0x19D4,0x0000,0x0000, /* 2D36 */ +0x19D5,0x0000,0x0000, 0x19D6,0x0000,0x0000, 0x19D7,0x0000,0x0000, /* 2D39 */ +0x19D8,0x0000,0x0000, 0x19D9,0x0000,0x0000, 0x19DA,0x0000,0x0000, /* 2D3C */ +0x19DB,0x0000,0x0000, 0x19DC,0x0000,0x0000, 0x19DD,0x0000,0x0000, /* 2D3F */ +0x19DE,0x0000,0x0000, 0x19DF,0x0000,0x0000, 0x19E0,0x0000,0x0000, /* 2D42 */ +0x19E1,0x0000,0x0000, 0x19E2,0x0000,0x0000, 0x19E3,0x0000,0x0000, /* 2D45 */ +0x19E4,0x0000,0x0000, 0x19E5,0x0000,0x0000, 0x19E6,0x0000,0x0000, /* 2D48 */ +0x19E7,0x0000,0x0000, 0x19E8,0x0000,0x0000, 0x19E9,0x0000,0x0000, /* 2D4B */ +0x19EA,0x0000,0x0000, 0x19EB,0x0000,0x0000, 0x19EC,0x0000,0x0000, /* 2D4E */ +0x19ED,0x0000,0x0000, 0x19EE,0x0000,0x0000, 0x19EF,0x0000,0x0000, /* 2D51 */ +0x19F0,0x0000,0x0000, 0x19F1,0x0000,0x0000, 0x19F2,0x0000,0x0000, /* 2D54 */ +0x19F3,0x0000,0x0000, 0x19F4,0x0000,0x0000, 0x19F5,0x0000,0x0000, /* 2D57 */ +0x19F6,0x0000,0x0000, 0x19F7,0x0000,0x0000, 0x19F8,0x0000,0x0000, /* 2D5A */ +0x19F9,0x0000,0x0000, 0x19FA,0x0000,0x0000, 0x19FB,0x0000,0x0000, /* 2D5D */ +0x19FC,0x0000,0x0000, 0x19FD,0x0000,0x0000, 0x19FE,0x0000,0x0000, /* 2D60 */ +0x19FF,0x0000,0x0000, 0x1A00,0x0000,0x0000, 0x1A01,0x0000,0x0000, /* 2D63 */ +0xFBC0,0xAD66,0x0000, 0xFBC0,0xAD67,0x0000, 0xFBC0,0xAD68,0x0000, /* 2D66 */ +0xFBC0,0xAD69,0x0000, 0xFBC0,0xAD6A,0x0000, 0xFBC0,0xAD6B,0x0000, /* 2D69 */ +0xFBC0,0xAD6C,0x0000, 0xFBC0,0xAD6D,0x0000, 0xFBC0,0xAD6E,0x0000, /* 2D6C */ +0x1A02,0x0000,0x0000, 0xFBC0,0xAD70,0x0000, 0xFBC0,0xAD71,0x0000, /* 2D6F */ +0xFBC0,0xAD72,0x0000, 0xFBC0,0xAD73,0x0000, 0xFBC0,0xAD74,0x0000, /* 2D72 */ +0xFBC0,0xAD75,0x0000, 0xFBC0,0xAD76,0x0000, 0xFBC0,0xAD77,0x0000, /* 2D75 */ +0xFBC0,0xAD78,0x0000, 0xFBC0,0xAD79,0x0000, 0xFBC0,0xAD7A,0x0000, /* 2D78 */ +0xFBC0,0xAD7B,0x0000, 0xFBC0,0xAD7C,0x0000, 0xFBC0,0xAD7D,0x0000, /* 2D7B */ +0xFBC0,0xAD7E,0x0000, 0xFBC0,0xAD7F,0x0000, 0x1A13,0x0000,0x0000, /* 2D7E */ +0x1A28,0x0000,0x0000, 0x1A39,0x0000,0x0000, 0x1A42,0x0000,0x0000, /* 2D81 */ +0x1A4B,0x0000,0x0000, 0x1A71,0x0000,0x0000, 0x1A82,0x0000,0x0000, /* 2D84 */ +0x1A8B,0x0000,0x0000, 0x1AA1,0x0000,0x0000, 0x1AAA,0x0000,0x0000, /* 2D87 */ +0x1AB3,0x0000,0x0000, 0x1AE4,0x0000,0x0000, 0x1AFD,0x0000,0x0000, /* 2D8A */ +0x1B06,0x0000,0x0000, 0x1B0F,0x0000,0x0000, 0x1B31,0x0000,0x0000, /* 2D8D */ +0x1B3A,0x0000,0x0000, 0x1B43,0x0000,0x0000, 0x1B6C,0x0000,0x0000, /* 2D90 */ +0x1B25,0x0000,0x0000, 0x1B26,0x0000,0x0000, 0x1B27,0x0000,0x0000, /* 2D93 */ +0x1B28,0x0000,0x0000, 0xFBC0,0xAD97,0x0000, 0xFBC0,0xAD98,0x0000, /* 2D96 */ +0xFBC0,0xAD99,0x0000, 0xFBC0,0xAD9A,0x0000, 0xFBC0,0xAD9B,0x0000, /* 2D99 */ +0xFBC0,0xAD9C,0x0000, 0xFBC0,0xAD9D,0x0000, 0xFBC0,0xAD9E,0x0000, /* 2D9C */ +0xFBC0,0xAD9F,0x0000, 0x1B70,0x0000,0x0000, 0x1B71,0x0000,0x0000, /* 2D9F */ +0x1B72,0x0000,0x0000, 0x1B73,0x0000,0x0000, 0x1B74,0x0000,0x0000, /* 2DA2 */ +0x1B75,0x0000,0x0000, 0x1B76,0x0000,0x0000, 0xFBC0,0xADA7,0x0000, /* 2DA5 */ +0x1B77,0x0000,0x0000, 0x1B78,0x0000,0x0000, 0x1B79,0x0000,0x0000, /* 2DA8 */ +0x1B7A,0x0000,0x0000, 0x1B7B,0x0000,0x0000, 0x1B7C,0x0000,0x0000, /* 2DAB */ +0x1B7D,0x0000,0x0000, 0xFBC0,0xADAF,0x0000, 0x1B7E,0x0000,0x0000, /* 2DAE */ +0x1B7F,0x0000,0x0000, 0x1B80,0x0000,0x0000, 0x1B81,0x0000,0x0000, /* 2DB1 */ +0x1B82,0x0000,0x0000, 0x1B83,0x0000,0x0000, 0x1B84,0x0000,0x0000, /* 2DB4 */ +0xFBC0,0xADB7,0x0000, 0x1B85,0x0000,0x0000, 0x1B86,0x0000,0x0000, /* 2DB7 */ +0x1B87,0x0000,0x0000, 0x1B88,0x0000,0x0000, 0x1B89,0x0000,0x0000, /* 2DBA */ +0x1B8A,0x0000,0x0000, 0x1B8B,0x0000,0x0000, 0xFBC0,0xADBF,0x0000, /* 2DBD */ +0x1B8C,0x0000,0x0000, 0x1B8D,0x0000,0x0000, 0x1B8E,0x0000,0x0000, /* 2DC0 */ +0x1B8F,0x0000,0x0000, 0x1B90,0x0000,0x0000, 0x1B91,0x0000,0x0000, /* 2DC3 */ +0x1B92,0x0000,0x0000, 0xFBC0,0xADC7,0x0000, 0x1B93,0x0000,0x0000, /* 2DC6 */ +0x1B94,0x0000,0x0000, 0x1B95,0x0000,0x0000, 0x1B96,0x0000,0x0000, /* 2DC9 */ +0x1B97,0x0000,0x0000, 0x1B98,0x0000,0x0000, 0x1B99,0x0000,0x0000, /* 2DCC */ +0xFBC0,0xADCF,0x0000, 0x1B9A,0x0000,0x0000, 0x1B9B,0x0000,0x0000, /* 2DCF */ +0x1B9C,0x0000,0x0000, 0x1B9D,0x0000,0x0000, 0x1B9E,0x0000,0x0000, /* 2DD2 */ +0x1B9F,0x0000,0x0000, 0x1BA0,0x0000,0x0000, 0xFBC0,0xADD7,0x0000, /* 2DD5 */ +0x1BA1,0x0000,0x0000, 0x1BA2,0x0000,0x0000, 0x1BA3,0x0000,0x0000, /* 2DD8 */ +0x1BA4,0x0000,0x0000, 0x1BA5,0x0000,0x0000, 0x1BA6,0x0000,0x0000, /* 2DDB */ +0x1BA7,0x0000,0x0000, 0xFBC0,0xADDF,0x0000, 0x15C4,0x0000,0x0000, /* 2DDE */ +0x15C8,0x0000,0x0000, 0x15CC,0x0000,0x0000, 0x15E0,0x0000,0x0000, /* 2DE1 */ +0x1600,0x0000,0x0000, 0x160D,0x0000,0x0000, 0x1643,0x0000,0x0000, /* 2DE4 */ +0x165D,0x0000,0x0000, 0x166F,0x0000,0x0000, 0x1678,0x0000,0x0000, /* 2DE7 */ +0x1692,0x0000,0x0000, 0x16A2,0x0000,0x0000, 0x16AF,0x0000,0x0000, /* 2DEA */ +0x16B8,0x0000,0x0000, 0x16C1,0x0000,0x0000, 0x16F5,0x0000,0x0000, /* 2DED */ +0x171B,0x0000,0x0000, 0x1725,0x0000,0x0000, 0x1747,0x0000,0x0000, /* 2DF0 */ +0x174C,0x0000,0x0000, 0x179F,0x0000,0x0000, 0x16B8,0x16C1,0x0000, /* 2DF3 */ +0x15AC,0x0000,0x0000, 0x15F4,0x0000,0x0000, 0x1642,0x0000,0x0000, /* 2DF6 */ +0x16EC,0x0000,0x0000, 0x1768,0x0000,0x0000, 0x1775,0x0000,0x0000, /* 2DF9 */ +0x177A,0x0000,0x0000, 0x1784,0x0000,0x0000, 0x1789,0x0000,0x0000, /* 2DFC */ +0x1793,0x0000,0x0000 }; + +uint16 uca520_p02E[]= { /* 2E00 (3 weights per char) */ +0x037E,0x0000,0x0000, 0x037F,0x0000,0x0000, 0x0329,0x0000,0x0000, /* 2E00 */ +0x032A,0x0000,0x0000, 0x032B,0x0000,0x0000, 0x032C,0x0000,0x0000, /* 2E03 */ +0x0380,0x0000,0x0000, 0x0381,0x0000,0x0000, 0x0382,0x0000,0x0000, /* 2E06 */ +0x032D,0x0000,0x0000, 0x032E,0x0000,0x0000, 0x0383,0x0000,0x0000, /* 2E09 */ +0x032F,0x0000,0x0000, 0x0330,0x0000,0x0000, 0x0384,0x0000,0x0000, /* 2E0C */ +0x0385,0x0000,0x0000, 0x0386,0x0000,0x0000, 0x0387,0x0000,0x0000, /* 2E0F */ +0x0388,0x0000,0x0000, 0x0389,0x0000,0x0000, 0x038A,0x0000,0x0000, /* 2E12 */ +0x038B,0x0000,0x0000, 0x038C,0x0000,0x0000, 0x022F,0x0000,0x0000, /* 2E15 */ +0x0280,0x0000,0x0000, 0x02E2,0x0000,0x0000, 0x038D,0x0000,0x0000, /* 2E18 */ +0x038E,0x0000,0x0000, 0x0331,0x0000,0x0000, 0x0332,0x0000,0x0000, /* 2E1B */ +0x038F,0x0000,0x0000, 0x0390,0x0000,0x0000, 0x0333,0x0000,0x0000, /* 2E1E */ +0x0334,0x0000,0x0000, 0x0335,0x0000,0x0000, 0x0336,0x0000,0x0000, /* 2E21 */ +0x0337,0x0000,0x0000, 0x0338,0x0000,0x0000, 0x0339,0x0000,0x0000, /* 2E24 */ +0x033A,0x0000,0x0000, 0x033B,0x0000,0x0000, 0x033C,0x0000,0x0000, /* 2E27 */ +0x02DC,0x0000,0x0000, 0x02DD,0x0000,0x0000, 0x02DE,0x0000,0x0000, /* 2E2A */ +0x02DF,0x0000,0x0000, 0x0275,0x0000,0x0000, 0x1751,0x0000,0x0000, /* 2E2D */ +0x028D,0x0000,0x0000, 0x0293,0x0000,0x0000, 0xFBC0,0xAE32,0x0000, /* 2E30 */ +0xFBC0,0xAE33,0x0000, 0xFBC0,0xAE34,0x0000, 0xFBC0,0xAE35,0x0000, /* 2E33 */ +0xFBC0,0xAE36,0x0000, 0xFBC0,0xAE37,0x0000, 0xFBC0,0xAE38,0x0000, /* 2E36 */ +0xFBC0,0xAE39,0x0000, 0xFBC0,0xAE3A,0x0000, 0xFBC0,0xAE3B,0x0000, /* 2E39 */ +0xFBC0,0xAE3C,0x0000, 0xFBC0,0xAE3D,0x0000, 0xFBC0,0xAE3E,0x0000, /* 2E3C */ +0xFBC0,0xAE3F,0x0000, 0xFBC0,0xAE40,0x0000, 0xFBC0,0xAE41,0x0000, /* 2E3F */ +0xFBC0,0xAE42,0x0000, 0xFBC0,0xAE43,0x0000, 0xFBC0,0xAE44,0x0000, /* 2E42 */ +0xFBC0,0xAE45,0x0000, 0xFBC0,0xAE46,0x0000, 0xFBC0,0xAE47,0x0000, /* 2E45 */ +0xFBC0,0xAE48,0x0000, 0xFBC0,0xAE49,0x0000, 0xFBC0,0xAE4A,0x0000, /* 2E48 */ +0xFBC0,0xAE4B,0x0000, 0xFBC0,0xAE4C,0x0000, 0xFBC0,0xAE4D,0x0000, /* 2E4B */ +0xFBC0,0xAE4E,0x0000, 0xFBC0,0xAE4F,0x0000, 0xFBC0,0xAE50,0x0000, /* 2E4E */ +0xFBC0,0xAE51,0x0000, 0xFBC0,0xAE52,0x0000, 0xFBC0,0xAE53,0x0000, /* 2E51 */ +0xFBC0,0xAE54,0x0000, 0xFBC0,0xAE55,0x0000, 0xFBC0,0xAE56,0x0000, /* 2E54 */ +0xFBC0,0xAE57,0x0000, 0xFBC0,0xAE58,0x0000, 0xFBC0,0xAE59,0x0000, /* 2E57 */ +0xFBC0,0xAE5A,0x0000, 0xFBC0,0xAE5B,0x0000, 0xFBC0,0xAE5C,0x0000, /* 2E5A */ +0xFBC0,0xAE5D,0x0000, 0xFBC0,0xAE5E,0x0000, 0xFBC0,0xAE5F,0x0000, /* 2E5D */ +0xFBC0,0xAE60,0x0000, 0xFBC0,0xAE61,0x0000, 0xFBC0,0xAE62,0x0000, /* 2E60 */ +0xFBC0,0xAE63,0x0000, 0xFBC0,0xAE64,0x0000, 0xFBC0,0xAE65,0x0000, /* 2E63 */ +0xFBC0,0xAE66,0x0000, 0xFBC0,0xAE67,0x0000, 0xFBC0,0xAE68,0x0000, /* 2E66 */ +0xFBC0,0xAE69,0x0000, 0xFBC0,0xAE6A,0x0000, 0xFBC0,0xAE6B,0x0000, /* 2E69 */ +0xFBC0,0xAE6C,0x0000, 0xFBC0,0xAE6D,0x0000, 0xFBC0,0xAE6E,0x0000, /* 2E6C */ +0xFBC0,0xAE6F,0x0000, 0xFBC0,0xAE70,0x0000, 0xFBC0,0xAE71,0x0000, /* 2E6F */ +0xFBC0,0xAE72,0x0000, 0xFBC0,0xAE73,0x0000, 0xFBC0,0xAE74,0x0000, /* 2E72 */ +0xFBC0,0xAE75,0x0000, 0xFBC0,0xAE76,0x0000, 0xFBC0,0xAE77,0x0000, /* 2E75 */ +0xFBC0,0xAE78,0x0000, 0xFBC0,0xAE79,0x0000, 0xFBC0,0xAE7A,0x0000, /* 2E78 */ +0xFBC0,0xAE7B,0x0000, 0xFBC0,0xAE7C,0x0000, 0xFBC0,0xAE7D,0x0000, /* 2E7B */ +0xFBC0,0xAE7E,0x0000, 0xFBC0,0xAE7F,0x0000, 0xFB40,0xCE36,0x0000, /* 2E7E */ +0xFB40,0xD382,0x0000, 0xFB40,0xCE5B,0x0000, 0xFB40,0xCE5A,0x0000, /* 2E81 */ +0xFB40,0xCE59,0x0000, 0xFB40,0xCEBB,0x0000, 0xFB40,0xD182,0x0000, /* 2E84 */ +0xFB40,0xD1E0,0x0000, 0xFB40,0xD200,0x0000, 0xFB40,0xD202,0x0000, /* 2E87 */ +0xFB40,0xD35C,0x0000, 0xFB40,0xD369,0x0000, 0xFB40,0xDC0F,0x0000, /* 2E8A */ +0xFB40,0xDC0F,0x0000, 0xFB40,0xDC22,0x0000, 0xFB40,0xDC23,0x0000, /* 2E8D */ +0xFB40,0xDC22,0x0000, 0xFB40,0xDC23,0x0000, 0xFB40,0xDDF3,0x0000, /* 2E90 */ +0xFB40,0xDE7A,0x0000, 0xFB40,0xDF51,0x0000, 0xFB40,0xDF50,0x0000, /* 2E93 */ +0xFB40,0xDFC4,0x0000, 0xFB40,0xDFC3,0x0000, 0xFB40,0xE24C,0x0000, /* 2E96 */ +0xFB40,0xE535,0x0000, 0xFBC0,0xAE9A,0x0000, 0xFB40,0xE5E1,0x0000, /* 2E99 */ +0xFB40,0xE5E5,0x0000, 0xFB40,0xE708,0x0000, 0xFB40,0xEB7A,0x0000, /* 2E9C */ +0xFB40,0xEBCD,0x0000, 0xFB40,0xEC11,0x0000, 0xFB40,0xEC35,0x0000, /* 2E9F */ +0xFB40,0xEC3A,0x0000, 0xFB40,0xF06C,0x0000, 0xFB40,0xF22B,0x0000, /* 2EA2 */ +0xFB40,0xF22B,0x0000, 0xFB40,0xCE2C,0x0000, 0xFB40,0xF25B,0x0000, /* 2EA5 */ +0xFB40,0xF2AD,0x0000, 0xFB40,0xF38B,0x0000, 0xFB40,0xF58B,0x0000, /* 2EA8 */ +0xFB40,0xF6EE,0x0000, 0xFB40,0xF93A,0x0000, 0xFB40,0xF93B,0x0000, /* 2EAB */ +0xFB40,0xFAF9,0x0000, 0xFB40,0xFCF9,0x0000, 0xFB40,0xFE9F,0x0000, /* 2EAE */ +0xFB40,0xFF53,0x0000, 0xFB40,0xFF52,0x0000, 0xFB40,0xFF53,0x0000, /* 2EB1 */ +0xFB40,0xFF53,0x0000, 0xFB40,0xFF52,0x0000, 0xFB40,0xFF8A,0x0000, /* 2EB4 */ +0xFB40,0xFF8A,0x0000, 0xFB40,0xFF8B,0x0000, 0xFB41,0x8002,0x0000, /* 2EB7 */ +0xFB41,0x8080,0x0000, 0xFB41,0x807F,0x0000, 0xFB41,0x8089,0x0000, /* 2EBA */ +0xFB41,0x81FC,0x0000, 0xFB41,0x8279,0x0000, 0xFB41,0x8279,0x0000, /* 2EBD */ +0xFB41,0x8279,0x0000, 0xFB41,0x864E,0x0000, 0xFB41,0x8864,0x0000, /* 2EC0 */ +0xFB41,0x8980,0x0000, 0xFB41,0x897F,0x0000, 0xFB41,0x89C1,0x0000, /* 2EC3 */ +0xFB41,0x89D2,0x0000, 0xFB41,0x89D2,0x0000, 0xFB41,0x8BA0,0x0000, /* 2EC6 */ +0xFB41,0x8D1D,0x0000, 0xFB41,0x8DB3,0x0000, 0xFB41,0x8F66,0x0000, /* 2EC9 */ +0xFB41,0x8FB6,0x0000, 0xFB41,0x8FB6,0x0000, 0xFB41,0x8FB6,0x0000, /* 2ECC */ +0xFB41,0x9091,0x0000, 0xFB41,0x9485,0x0000, 0xFB41,0x9577,0x0000, /* 2ECF */ +0xFB41,0x9578,0x0000, 0xFB41,0x957F,0x0000, 0xFB41,0x95E8,0x0000, /* 2ED2 */ +0xFB41,0x961C,0x0000, 0xFB41,0x961D,0x0000, 0xFB41,0x96E8,0x0000, /* 2ED5 */ +0xFB41,0x9752,0x0000, 0xFB41,0x97E6,0x0000, 0xFB41,0x9875,0x0000, /* 2ED8 */ +0xFB41,0x98CE,0x0000, 0xFB41,0x98DE,0x0000, 0xFB41,0x98DF,0x0000, /* 2EDB */ +0xFB41,0x98E0,0x0000, 0xFB41,0x98E0,0x0000, 0xFB41,0x9963,0x0000, /* 2EDE */ +0xFB41,0x9996,0x0000, 0xFB41,0x9A6C,0x0000, 0xFB41,0x9AA8,0x0000, /* 2EE1 */ +0xFB41,0x9B3C,0x0000, 0xFB41,0x9C7C,0x0000, 0xFB41,0x9E1F,0x0000, /* 2EE4 */ +0xFB41,0x9E75,0x0000, 0xFB41,0x9EA6,0x0000, 0xFB41,0x9EC4,0x0000, /* 2EE7 */ +0xFB41,0x9EFE,0x0000, 0xFB41,0x9F4A,0x0000, 0xFB41,0x9F50,0x0000, /* 2EEA */ +0xFB41,0x9F52,0x0000, 0xFB41,0x9F7F,0x0000, 0xFB41,0x9F8D,0x0000, /* 2EED */ +0xFB41,0x9F99,0x0000, 0xFB41,0x9F9C,0x0000, 0xFB41,0x9F9C,0x0000, /* 2EF0 */ +0xFB41,0x9F9F,0x0000, 0xFBC0,0xAEF4,0x0000, 0xFBC0,0xAEF5,0x0000, /* 2EF3 */ +0xFBC0,0xAEF6,0x0000, 0xFBC0,0xAEF7,0x0000, 0xFBC0,0xAEF8,0x0000, /* 2EF6 */ +0xFBC0,0xAEF9,0x0000, 0xFBC0,0xAEFA,0x0000, 0xFBC0,0xAEFB,0x0000, /* 2EF9 */ +0xFBC0,0xAEFC,0x0000, 0xFBC0,0xAEFD,0x0000, 0xFBC0,0xAEFE,0x0000, /* 2EFC */ +0xFBC0,0xAEFF,0x0000 }; + +uint16 uca520_p02F[]= { /* 2F00 (3 weights per char) */ +0xFB40,0xCE00,0x0000, 0xFB40,0xCE28,0x0000, 0xFB40,0xCE36,0x0000, /* 2F00 */ +0xFB40,0xCE3F,0x0000, 0xFB40,0xCE59,0x0000, 0xFB40,0xCE85,0x0000, /* 2F03 */ +0xFB40,0xCE8C,0x0000, 0xFB40,0xCEA0,0x0000, 0xFB40,0xCEBA,0x0000, /* 2F06 */ +0xFB40,0xD13F,0x0000, 0xFB40,0xD165,0x0000, 0xFB40,0xD16B,0x0000, /* 2F09 */ +0xFB40,0xD182,0x0000, 0xFB40,0xD196,0x0000, 0xFB40,0xD1AB,0x0000, /* 2F0C */ +0xFB40,0xD1E0,0x0000, 0xFB40,0xD1F5,0x0000, 0xFB40,0xD200,0x0000, /* 2F0F */ +0xFB40,0xD29B,0x0000, 0xFB40,0xD2F9,0x0000, 0xFB40,0xD315,0x0000, /* 2F12 */ +0xFB40,0xD31A,0x0000, 0xFB40,0xD338,0x0000, 0xFB40,0xD341,0x0000, /* 2F15 */ +0xFB40,0xD35C,0x0000, 0xFB40,0xD369,0x0000, 0xFB40,0xD382,0x0000, /* 2F18 */ +0xFB40,0xD3B6,0x0000, 0xFB40,0xD3C8,0x0000, 0xFB40,0xD3E3,0x0000, /* 2F1B */ +0xFB40,0xD6D7,0x0000, 0xFB40,0xD71F,0x0000, 0xFB40,0xD8EB,0x0000, /* 2F1E */ +0xFB40,0xD902,0x0000, 0xFB40,0xD90A,0x0000, 0xFB40,0xD915,0x0000, /* 2F21 */ +0xFB40,0xD927,0x0000, 0xFB40,0xD973,0x0000, 0xFB40,0xDB50,0x0000, /* 2F24 */ +0xFB40,0xDB80,0x0000, 0xFB40,0xDBF8,0x0000, 0xFB40,0xDC0F,0x0000, /* 2F27 */ +0xFB40,0xDC22,0x0000, 0xFB40,0xDC38,0x0000, 0xFB40,0xDC6E,0x0000, /* 2F2A */ +0xFB40,0xDC71,0x0000, 0xFB40,0xDDDB,0x0000, 0xFB40,0xDDE5,0x0000, /* 2F2D */ +0xFB40,0xDDF1,0x0000, 0xFB40,0xDDFE,0x0000, 0xFB40,0xDE72,0x0000, /* 2F30 */ +0xFB40,0xDE7A,0x0000, 0xFB40,0xDE7F,0x0000, 0xFB40,0xDEF4,0x0000, /* 2F33 */ +0xFB40,0xDEFE,0x0000, 0xFB40,0xDF0B,0x0000, 0xFB40,0xDF13,0x0000, /* 2F36 */ +0xFB40,0xDF50,0x0000, 0xFB40,0xDF61,0x0000, 0xFB40,0xDF73,0x0000, /* 2F39 */ +0xFB40,0xDFC3,0x0000, 0xFB40,0xE208,0x0000, 0xFB40,0xE236,0x0000, /* 2F3C */ +0xFB40,0xE24B,0x0000, 0xFB40,0xE52F,0x0000, 0xFB40,0xE534,0x0000, /* 2F3F */ +0xFB40,0xE587,0x0000, 0xFB40,0xE597,0x0000, 0xFB40,0xE5A4,0x0000, /* 2F42 */ +0xFB40,0xE5B9,0x0000, 0xFB40,0xE5E0,0x0000, 0xFB40,0xE5E5,0x0000, /* 2F45 */ +0xFB40,0xE6F0,0x0000, 0xFB40,0xE708,0x0000, 0xFB40,0xE728,0x0000, /* 2F48 */ +0xFB40,0xEB20,0x0000, 0xFB40,0xEB62,0x0000, 0xFB40,0xEB79,0x0000, /* 2F4B */ +0xFB40,0xEBB3,0x0000, 0xFB40,0xEBCB,0x0000, 0xFB40,0xEBD4,0x0000, /* 2F4E */ +0xFB40,0xEBDB,0x0000, 0xFB40,0xEC0F,0x0000, 0xFB40,0xEC14,0x0000, /* 2F51 */ +0xFB40,0xEC34,0x0000, 0xFB40,0xF06B,0x0000, 0xFB40,0xF22A,0x0000, /* 2F54 */ +0xFB40,0xF236,0x0000, 0xFB40,0xF23B,0x0000, 0xFB40,0xF23F,0x0000, /* 2F57 */ +0xFB40,0xF247,0x0000, 0xFB40,0xF259,0x0000, 0xFB40,0xF25B,0x0000, /* 2F5A */ +0xFB40,0xF2AC,0x0000, 0xFB40,0xF384,0x0000, 0xFB40,0xF389,0x0000, /* 2F5D */ +0xFB40,0xF4DC,0x0000, 0xFB40,0xF4E6,0x0000, 0xFB40,0xF518,0x0000, /* 2F60 */ +0xFB40,0xF51F,0x0000, 0xFB40,0xF528,0x0000, 0xFB40,0xF530,0x0000, /* 2F63 */ +0xFB40,0xF58B,0x0000, 0xFB40,0xF592,0x0000, 0xFB40,0xF676,0x0000, /* 2F66 */ +0xFB40,0xF67D,0x0000, 0xFB40,0xF6AE,0x0000, 0xFB40,0xF6BF,0x0000, /* 2F69 */ +0xFB40,0xF6EE,0x0000, 0xFB40,0xF7DB,0x0000, 0xFB40,0xF7E2,0x0000, /* 2F6C */ +0xFB40,0xF7F3,0x0000, 0xFB40,0xF93A,0x0000, 0xFB40,0xF9B8,0x0000, /* 2F6F */ +0xFB40,0xF9BE,0x0000, 0xFB40,0xFA74,0x0000, 0xFB40,0xFACB,0x0000, /* 2F72 */ +0xFB40,0xFAF9,0x0000, 0xFB40,0xFC73,0x0000, 0xFB40,0xFCF8,0x0000, /* 2F75 */ +0xFB40,0xFF36,0x0000, 0xFB40,0xFF51,0x0000, 0xFB40,0xFF8A,0x0000, /* 2F78 */ +0xFB40,0xFFBD,0x0000, 0xFB41,0x8001,0x0000, 0xFB41,0x800C,0x0000, /* 2F7B */ +0xFB41,0x8012,0x0000, 0xFB41,0x8033,0x0000, 0xFB41,0x807F,0x0000, /* 2F7E */ +0xFB41,0x8089,0x0000, 0xFB41,0x81E3,0x0000, 0xFB41,0x81EA,0x0000, /* 2F81 */ +0xFB41,0x81F3,0x0000, 0xFB41,0x81FC,0x0000, 0xFB41,0x820C,0x0000, /* 2F84 */ +0xFB41,0x821B,0x0000, 0xFB41,0x821F,0x0000, 0xFB41,0x826E,0x0000, /* 2F87 */ +0xFB41,0x8272,0x0000, 0xFB41,0x8278,0x0000, 0xFB41,0x864D,0x0000, /* 2F8A */ +0xFB41,0x866B,0x0000, 0xFB41,0x8840,0x0000, 0xFB41,0x884C,0x0000, /* 2F8D */ +0xFB41,0x8863,0x0000, 0xFB41,0x897E,0x0000, 0xFB41,0x898B,0x0000, /* 2F90 */ +0xFB41,0x89D2,0x0000, 0xFB41,0x8A00,0x0000, 0xFB41,0x8C37,0x0000, /* 2F93 */ +0xFB41,0x8C46,0x0000, 0xFB41,0x8C55,0x0000, 0xFB41,0x8C78,0x0000, /* 2F96 */ +0xFB41,0x8C9D,0x0000, 0xFB41,0x8D64,0x0000, 0xFB41,0x8D70,0x0000, /* 2F99 */ +0xFB41,0x8DB3,0x0000, 0xFB41,0x8EAB,0x0000, 0xFB41,0x8ECA,0x0000, /* 2F9C */ +0xFB41,0x8F9B,0x0000, 0xFB41,0x8FB0,0x0000, 0xFB41,0x8FB5,0x0000, /* 2F9F */ +0xFB41,0x9091,0x0000, 0xFB41,0x9149,0x0000, 0xFB41,0x91C6,0x0000, /* 2FA2 */ +0xFB41,0x91CC,0x0000, 0xFB41,0x91D1,0x0000, 0xFB41,0x9577,0x0000, /* 2FA5 */ +0xFB41,0x9580,0x0000, 0xFB41,0x961C,0x0000, 0xFB41,0x96B6,0x0000, /* 2FA8 */ +0xFB41,0x96B9,0x0000, 0xFB41,0x96E8,0x0000, 0xFB41,0x9751,0x0000, /* 2FAB */ +0xFB41,0x975E,0x0000, 0xFB41,0x9762,0x0000, 0xFB41,0x9769,0x0000, /* 2FAE */ +0xFB41,0x97CB,0x0000, 0xFB41,0x97ED,0x0000, 0xFB41,0x97F3,0x0000, /* 2FB1 */ +0xFB41,0x9801,0x0000, 0xFB41,0x98A8,0x0000, 0xFB41,0x98DB,0x0000, /* 2FB4 */ +0xFB41,0x98DF,0x0000, 0xFB41,0x9996,0x0000, 0xFB41,0x9999,0x0000, /* 2FB7 */ +0xFB41,0x99AC,0x0000, 0xFB41,0x9AA8,0x0000, 0xFB41,0x9AD8,0x0000, /* 2FBA */ +0xFB41,0x9ADF,0x0000, 0xFB41,0x9B25,0x0000, 0xFB41,0x9B2F,0x0000, /* 2FBD */ +0xFB41,0x9B32,0x0000, 0xFB41,0x9B3C,0x0000, 0xFB41,0x9B5A,0x0000, /* 2FC0 */ +0xFB41,0x9CE5,0x0000, 0xFB41,0x9E75,0x0000, 0xFB41,0x9E7F,0x0000, /* 2FC3 */ +0xFB41,0x9EA5,0x0000, 0xFB41,0x9EBB,0x0000, 0xFB41,0x9EC3,0x0000, /* 2FC6 */ +0xFB41,0x9ECD,0x0000, 0xFB41,0x9ED1,0x0000, 0xFB41,0x9EF9,0x0000, /* 2FC9 */ +0xFB41,0x9EFD,0x0000, 0xFB41,0x9F0E,0x0000, 0xFB41,0x9F13,0x0000, /* 2FCC */ +0xFB41,0x9F20,0x0000, 0xFB41,0x9F3B,0x0000, 0xFB41,0x9F4A,0x0000, /* 2FCF */ +0xFB41,0x9F52,0x0000, 0xFB41,0x9F8D,0x0000, 0xFB41,0x9F9C,0x0000, /* 2FD2 */ +0xFB41,0x9FA0,0x0000, 0xFBC0,0xAFD6,0x0000, 0xFBC0,0xAFD7,0x0000, /* 2FD5 */ +0xFBC0,0xAFD8,0x0000, 0xFBC0,0xAFD9,0x0000, 0xFBC0,0xAFDA,0x0000, /* 2FD8 */ +0xFBC0,0xAFDB,0x0000, 0xFBC0,0xAFDC,0x0000, 0xFBC0,0xAFDD,0x0000, /* 2FDB */ +0xFBC0,0xAFDE,0x0000, 0xFBC0,0xAFDF,0x0000, 0xFBC0,0xAFE0,0x0000, /* 2FDE */ +0xFBC0,0xAFE1,0x0000, 0xFBC0,0xAFE2,0x0000, 0xFBC0,0xAFE3,0x0000, /* 2FE1 */ +0xFBC0,0xAFE4,0x0000, 0xFBC0,0xAFE5,0x0000, 0xFBC0,0xAFE6,0x0000, /* 2FE4 */ +0xFBC0,0xAFE7,0x0000, 0xFBC0,0xAFE8,0x0000, 0xFBC0,0xAFE9,0x0000, /* 2FE7 */ +0xFBC0,0xAFEA,0x0000, 0xFBC0,0xAFEB,0x0000, 0xFBC0,0xAFEC,0x0000, /* 2FEA */ +0xFBC0,0xAFED,0x0000, 0xFBC0,0xAFEE,0x0000, 0xFBC0,0xAFEF,0x0000, /* 2FED */ +0x10D4,0x0000,0x0000, 0x10D5,0x0000,0x0000, 0x10D6,0x0000,0x0000, /* 2FF0 */ +0x10D7,0x0000,0x0000, 0x10D8,0x0000,0x0000, 0x10D9,0x0000,0x0000, /* 2FF3 */ +0x10DA,0x0000,0x0000, 0x10DB,0x0000,0x0000, 0x10DC,0x0000,0x0000, /* 2FF6 */ +0x10DD,0x0000,0x0000, 0x10DE,0x0000,0x0000, 0x10DF,0x0000,0x0000, /* 2FF9 */ +0xFBC0,0xAFFC,0x0000, 0xFBC0,0xAFFD,0x0000, 0xFBC0,0xAFFE,0x0000, /* 2FFC */ +0xFBC0,0xAFFF,0x0000 }; + +uint16 uca520_p030[]= { /* 3000 (3 weights per char) */ +0x020A,0x0000,0x0000, 0x0240,0x0000,0x0000, 0x0291,0x0000,0x0000, /* 3000 */ +0x0374,0x0000,0x0000, 0x1104,0x0000,0x0000, 0x11D7,0x0000,0x0000, /* 3003 */ +0x2B20,0x2B36,0x0000, 0x1205,0x0000,0x0000, 0x033D,0x0000,0x0000, /* 3006 */ +0x033E,0x0000,0x0000, 0x033F,0x0000,0x0000, 0x0340,0x0000,0x0000, /* 3009 */ +0x0341,0x0000,0x0000, 0x0342,0x0000,0x0000, 0x0343,0x0000,0x0000, /* 300C */ +0x0344,0x0000,0x0000, 0x0345,0x0000,0x0000, 0x0346,0x0000,0x0000, /* 300F */ +0x1105,0x0000,0x0000, 0x1106,0x0000,0x0000, 0x0347,0x0000,0x0000, /* 3012 */ +0x0348,0x0000,0x0000, 0x0349,0x0000,0x0000, 0x034A,0x0000,0x0000, /* 3015 */ +0x034B,0x0000,0x0000, 0x034C,0x0000,0x0000, 0x034D,0x0000,0x0000, /* 3018 */ +0x034E,0x0000,0x0000, 0x0230,0x0000,0x0000, 0x02FA,0x0000,0x0000, /* 301B */ +0x02FB,0x0000,0x0000, 0x02FC,0x0000,0x0000, 0x1107,0x0000,0x0000, /* 301E */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 3021 */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 3024 */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 3027 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 302A */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 302D */ +0x0231,0x0000,0x0000, 0x11D9,0x0000,0x0000, 0x11D9,0x0000,0x0000, /* 3030 */ +0x11DA,0x0000,0x0000, 0x11DA,0x0000,0x0000, 0x11DB,0x0000,0x0000, /* 3033 */ +0x1105,0x0000,0x0000, 0x1108,0x0000,0x0000, 0xFB40,0xD341,0x0000, /* 3036 */ +0xFB40,0xD344,0x0000, 0xFB40,0xD345,0x0000, 0x11D8,0x0000,0x0000, /* 3039 */ +0x2B33,0x2B21,0x0000, 0x0375,0x0000,0x0000, 0x1109,0x0000,0x0000, /* 303C */ +0x110A,0x0000,0x0000, 0xFBC0,0xB040,0x0000, 0x2B15,0x0000,0x0000, /* 303F */ +0x2B15,0x0000,0x0000, 0x2B16,0x0000,0x0000, 0x2B16,0x0000,0x0000, /* 3042 */ +0x2B17,0x0000,0x0000, 0x2B17,0x0000,0x0000, 0x2B18,0x0000,0x0000, /* 3045 */ +0x2B18,0x0000,0x0000, 0x2B19,0x0000,0x0000, 0x2B19,0x0000,0x0000, /* 3048 */ +0x2B1A,0x0000,0x0000, 0x2B1A,0x0000,0x0000, 0x2B1B,0x0000,0x0000, /* 304B */ +0x2B1B,0x0000,0x0000, 0x2B1C,0x0000,0x0000, 0x2B1C,0x0000,0x0000, /* 304E */ +0x2B1D,0x0000,0x0000, 0x2B1D,0x0000,0x0000, 0x2B1E,0x0000,0x0000, /* 3051 */ +0x2B1E,0x0000,0x0000, 0x2B1F,0x0000,0x0000, 0x2B1F,0x0000,0x0000, /* 3054 */ +0x2B20,0x0000,0x0000, 0x2B20,0x0000,0x0000, 0x2B21,0x0000,0x0000, /* 3057 */ +0x2B21,0x0000,0x0000, 0x2B22,0x0000,0x0000, 0x2B22,0x0000,0x0000, /* 305A */ +0x2B23,0x0000,0x0000, 0x2B23,0x0000,0x0000, 0x2B24,0x0000,0x0000, /* 305D */ +0x2B24,0x0000,0x0000, 0x2B25,0x0000,0x0000, 0x2B25,0x0000,0x0000, /* 3060 */ +0x2B26,0x0000,0x0000, 0x2B26,0x0000,0x0000, 0x2B26,0x0000,0x0000, /* 3063 */ +0x2B27,0x0000,0x0000, 0x2B27,0x0000,0x0000, 0x2B28,0x0000,0x0000, /* 3066 */ +0x2B28,0x0000,0x0000, 0x2B29,0x0000,0x0000, 0x2B2A,0x0000,0x0000, /* 3069 */ +0x2B2B,0x0000,0x0000, 0x2B2C,0x0000,0x0000, 0x2B2D,0x0000,0x0000, /* 306C */ +0x2B2E,0x0000,0x0000, 0x2B2E,0x0000,0x0000, 0x2B2E,0x0000,0x0000, /* 306F */ +0x2B2F,0x0000,0x0000, 0x2B2F,0x0000,0x0000, 0x2B2F,0x0000,0x0000, /* 3072 */ +0x2B30,0x0000,0x0000, 0x2B30,0x0000,0x0000, 0x2B30,0x0000,0x0000, /* 3075 */ +0x2B31,0x0000,0x0000, 0x2B31,0x0000,0x0000, 0x2B31,0x0000,0x0000, /* 3078 */ +0x2B32,0x0000,0x0000, 0x2B32,0x0000,0x0000, 0x2B32,0x0000,0x0000, /* 307B */ +0x2B33,0x0000,0x0000, 0x2B34,0x0000,0x0000, 0x2B35,0x0000,0x0000, /* 307E */ +0x2B36,0x0000,0x0000, 0x2B37,0x0000,0x0000, 0x2B38,0x0000,0x0000, /* 3081 */ +0x2B38,0x0000,0x0000, 0x2B39,0x0000,0x0000, 0x2B39,0x0000,0x0000, /* 3084 */ +0x2B3A,0x0000,0x0000, 0x2B3A,0x0000,0x0000, 0x2B3B,0x0000,0x0000, /* 3087 */ +0x2B3C,0x0000,0x0000, 0x2B3D,0x0000,0x0000, 0x2B3E,0x0000,0x0000, /* 308A */ +0x2B3F,0x0000,0x0000, 0x2B40,0x0000,0x0000, 0x2B40,0x0000,0x0000, /* 308D */ +0x2B41,0x0000,0x0000, 0x2B42,0x0000,0x0000, 0x2B43,0x0000,0x0000, /* 3090 */ +0x2B44,0x0000,0x0000, 0x2B17,0x0000,0x0000, 0x2B1A,0x0000,0x0000, /* 3093 */ +0x2B1D,0x0000,0x0000, 0xFBC0,0xB097,0x0000, 0xFBC0,0xB098,0x0000, /* 3096 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0220,0x0000,0x0000, /* 3099 */ +0x0221,0x0000,0x0000, 0x11DC,0x0000,0x0000, 0x11DC,0x0000,0x0000, /* 309C */ +0x2B3A,0x2B3C,0x0000, 0x0232,0x0000,0x0000, 0x2B15,0x0000,0x0000, /* 309F */ +0x2B15,0x0000,0x0000, 0x2B16,0x0000,0x0000, 0x2B16,0x0000,0x0000, /* 30A2 */ +0x2B17,0x0000,0x0000, 0x2B17,0x0000,0x0000, 0x2B18,0x0000,0x0000, /* 30A5 */ +0x2B18,0x0000,0x0000, 0x2B19,0x0000,0x0000, 0x2B19,0x0000,0x0000, /* 30A8 */ +0x2B1A,0x0000,0x0000, 0x2B1A,0x0000,0x0000, 0x2B1B,0x0000,0x0000, /* 30AB */ +0x2B1B,0x0000,0x0000, 0x2B1C,0x0000,0x0000, 0x2B1C,0x0000,0x0000, /* 30AE */ +0x2B1D,0x0000,0x0000, 0x2B1D,0x0000,0x0000, 0x2B1E,0x0000,0x0000, /* 30B1 */ +0x2B1E,0x0000,0x0000, 0x2B1F,0x0000,0x0000, 0x2B1F,0x0000,0x0000, /* 30B4 */ +0x2B20,0x0000,0x0000, 0x2B20,0x0000,0x0000, 0x2B21,0x0000,0x0000, /* 30B7 */ +0x2B21,0x0000,0x0000, 0x2B22,0x0000,0x0000, 0x2B22,0x0000,0x0000, /* 30BA */ +0x2B23,0x0000,0x0000, 0x2B23,0x0000,0x0000, 0x2B24,0x0000,0x0000, /* 30BD */ +0x2B24,0x0000,0x0000, 0x2B25,0x0000,0x0000, 0x2B25,0x0000,0x0000, /* 30C0 */ +0x2B26,0x0000,0x0000, 0x2B26,0x0000,0x0000, 0x2B26,0x0000,0x0000, /* 30C3 */ +0x2B27,0x0000,0x0000, 0x2B27,0x0000,0x0000, 0x2B28,0x0000,0x0000, /* 30C6 */ +0x2B28,0x0000,0x0000, 0x2B29,0x0000,0x0000, 0x2B2A,0x0000,0x0000, /* 30C9 */ +0x2B2B,0x0000,0x0000, 0x2B2C,0x0000,0x0000, 0x2B2D,0x0000,0x0000, /* 30CC */ +0x2B2E,0x0000,0x0000, 0x2B2E,0x0000,0x0000, 0x2B2E,0x0000,0x0000, /* 30CF */ +0x2B2F,0x0000,0x0000, 0x2B2F,0x0000,0x0000, 0x2B2F,0x0000,0x0000, /* 30D2 */ +0x2B30,0x0000,0x0000, 0x2B30,0x0000,0x0000, 0x2B30,0x0000,0x0000, /* 30D5 */ +0x2B31,0x0000,0x0000, 0x2B31,0x0000,0x0000, 0x2B31,0x0000,0x0000, /* 30D8 */ +0x2B32,0x0000,0x0000, 0x2B32,0x0000,0x0000, 0x2B32,0x0000,0x0000, /* 30DB */ +0x2B33,0x0000,0x0000, 0x2B34,0x0000,0x0000, 0x2B35,0x0000,0x0000, /* 30DE */ +0x2B36,0x0000,0x0000, 0x2B37,0x0000,0x0000, 0x2B38,0x0000,0x0000, /* 30E1 */ +0x2B38,0x0000,0x0000, 0x2B39,0x0000,0x0000, 0x2B39,0x0000,0x0000, /* 30E4 */ +0x2B3A,0x0000,0x0000, 0x2B3A,0x0000,0x0000, 0x2B3B,0x0000,0x0000, /* 30E7 */ +0x2B3C,0x0000,0x0000, 0x2B3D,0x0000,0x0000, 0x2B3E,0x0000,0x0000, /* 30EA */ +0x2B3F,0x0000,0x0000, 0x2B40,0x0000,0x0000, 0x2B40,0x0000,0x0000, /* 30ED */ +0x2B41,0x0000,0x0000, 0x2B42,0x0000,0x0000, 0x2B43,0x0000,0x0000, /* 30F0 */ +0x2B44,0x0000,0x0000, 0x2B17,0x0000,0x0000, 0x2B1A,0x0000,0x0000, /* 30F3 */ +0x2B1D,0x0000,0x0000, 0x2B40,0x0000,0x0000, 0x2B41,0x0000,0x0000, /* 30F6 */ +0x2B42,0x0000,0x0000, 0x2B43,0x0000,0x0000, 0x0233,0x0000,0x0000, /* 30F9 */ +0x11DD,0x0000,0x0000, 0x11DE,0x0000,0x0000, 0x11DE,0x0000,0x0000, /* 30FC */ +0x2B1E,0x2B28,0x0000 }; + +uint16 uca520_p031[]= { /* 3100 (3 weights per char) */ +0xFBC0,0xB100,0x0000, 0xFBC0,0xB101,0x0000, 0xFBC0,0xB102,0x0000, /* 3100 */ +0xFBC0,0xB103,0x0000, 0xFBC0,0xB104,0x0000, 0x2B45,0x0000,0x0000, /* 3103 */ +0x2B46,0x0000,0x0000, 0x2B47,0x0000,0x0000, 0x2B48,0x0000,0x0000, /* 3106 */ +0x2B4A,0x0000,0x0000, 0x2B4B,0x0000,0x0000, 0x2B4C,0x0000,0x0000, /* 3109 */ +0x2B4D,0x0000,0x0000, 0x2B4E,0x0000,0x0000, 0x2B4F,0x0000,0x0000, /* 310C */ +0x2B52,0x0000,0x0000, 0x2B53,0x0000,0x0000, 0x2B54,0x0000,0x0000, /* 310F */ +0x2B55,0x0000,0x0000, 0x2B57,0x0000,0x0000, 0x2B58,0x0000,0x0000, /* 3112 */ +0x2B59,0x0000,0x0000, 0x2B5A,0x0000,0x0000, 0x2B5B,0x0000,0x0000, /* 3115 */ +0x2B5C,0x0000,0x0000, 0x2B5D,0x0000,0x0000, 0x2B5E,0x0000,0x0000, /* 3118 */ +0x2B5F,0x0000,0x0000, 0x2B61,0x0000,0x0000, 0x2B62,0x0000,0x0000, /* 311B */ +0x2B64,0x0000,0x0000, 0x2B65,0x0000,0x0000, 0x2B66,0x0000,0x0000, /* 311E */ +0x2B67,0x0000,0x0000, 0x2B68,0x0000,0x0000, 0x2B69,0x0000,0x0000, /* 3121 */ +0x2B6A,0x0000,0x0000, 0x2B6C,0x0000,0x0000, 0x2B70,0x0000,0x0000, /* 3124 */ +0x2B71,0x0000,0x0000, 0x2B72,0x0000,0x0000, 0x2B73,0x0000,0x0000, /* 3127 */ +0x2B49,0x0000,0x0000, 0x2B50,0x0000,0x0000, 0x2B56,0x0000,0x0000, /* 312A */ +0x2B74,0x0000,0x0000, 0xFBC0,0xB12E,0x0000, 0xFBC0,0xB12F,0x0000, /* 312D */ +0xFBC0,0xB130,0x0000, 0x29B0,0x0000,0x0000, 0x29B1,0x0000,0x0000, /* 3130 */ +0x2A8E,0x0000,0x0000, 0x29B2,0x0000,0x0000, 0x2A90,0x0000,0x0000, /* 3133 */ +0x2A91,0x0000,0x0000, 0x29B3,0x0000,0x0000, 0x29B4,0x0000,0x0000, /* 3136 */ +0x29B5,0x0000,0x0000, 0x2A94,0x0000,0x0000, 0x2A95,0x0000,0x0000, /* 3139 */ +0x2A96,0x0000,0x0000, 0x2A97,0x0000,0x0000, 0x2A98,0x0000,0x0000, /* 313C */ +0x2A99,0x0000,0x0000, 0x29CA,0x0000,0x0000, 0x29B6,0x0000,0x0000, /* 313F */ +0x29B7,0x0000,0x0000, 0x29B8,0x0000,0x0000, 0x29D1,0x0000,0x0000, /* 3142 */ +0x29B9,0x0000,0x0000, 0x29BA,0x0000,0x0000, 0x29BB,0x0000,0x0000, /* 3145 */ +0x29BC,0x0000,0x0000, 0x29BD,0x0000,0x0000, 0x29BE,0x0000,0x0000, /* 3148 */ +0x29BF,0x0000,0x0000, 0x29C0,0x0000,0x0000, 0x29C1,0x0000,0x0000, /* 314B */ +0x29C2,0x0000,0x0000, 0x2A2E,0x0000,0x0000, 0x2A2F,0x0000,0x0000, /* 314E */ +0x2A30,0x0000,0x0000, 0x2A31,0x0000,0x0000, 0x2A32,0x0000,0x0000, /* 3151 */ +0x2A33,0x0000,0x0000, 0x2A34,0x0000,0x0000, 0x2A35,0x0000,0x0000, /* 3154 */ +0x2A36,0x0000,0x0000, 0x2A37,0x0000,0x0000, 0x2A38,0x0000,0x0000, /* 3157 */ +0x2A39,0x0000,0x0000, 0x2A3A,0x0000,0x0000, 0x2A3B,0x0000,0x0000, /* 315A */ +0x2A3C,0x0000,0x0000, 0x2A3D,0x0000,0x0000, 0x2A3E,0x0000,0x0000, /* 315D */ +0x2A3F,0x0000,0x0000, 0x2A40,0x0000,0x0000, 0x2A41,0x0000,0x0000, /* 3160 */ +0x2A42,0x0000,0x0000, 0x2A2D,0x0000,0x0000, 0x29C4,0x0000,0x0000, /* 3163 */ +0x29C5,0x0000,0x0000, 0x2AAB,0x0000,0x0000, 0x2AAC,0x0000,0x0000, /* 3166 */ +0x2AB0,0x0000,0x0000, 0x2AB2,0x0000,0x0000, 0x2AB7,0x0000,0x0000, /* 3169 */ +0x2ABB,0x0000,0x0000, 0x2ABD,0x0000,0x0000, 0x29CC,0x0000,0x0000, /* 316C */ +0x2AC1,0x0000,0x0000, 0x2AC3,0x0000,0x0000, 0x29CD,0x0000,0x0000, /* 316F */ +0x29CE,0x0000,0x0000, 0x29D0,0x0000,0x0000, 0x29D2,0x0000,0x0000, /* 3172 */ +0x29D3,0x0000,0x0000, 0x29D7,0x0000,0x0000, 0x29D9,0x0000,0x0000, /* 3175 */ +0x29DB,0x0000,0x0000, 0x29DC,0x0000,0x0000, 0x29DD,0x0000,0x0000, /* 3178 */ +0x29DE,0x0000,0x0000, 0x29DF,0x0000,0x0000, 0x29E2,0x0000,0x0000, /* 317B */ +0x29E6,0x0000,0x0000, 0x29F0,0x0000,0x0000, 0x29F7,0x0000,0x0000, /* 317E */ +0x29FC,0x0000,0x0000, 0x2AD5,0x0000,0x0000, 0x2AD6,0x0000,0x0000, /* 3181 */ +0x2A07,0x0000,0x0000, 0x2A08,0x0000,0x0000, 0x2A09,0x0000,0x0000, /* 3184 */ +0x2A51,0x0000,0x0000, 0x2A52,0x0000,0x0000, 0x2A55,0x0000,0x0000, /* 3187 */ +0x2A5E,0x0000,0x0000, 0x2A5F,0x0000,0x0000, 0x2A61,0x0000,0x0000, /* 318A */ +0x2A6B,0x0000,0x0000, 0x2A6E,0x0000,0x0000, 0xFBC0,0xB18F,0x0000, /* 318D */ +0x110B,0x0000,0x0000, 0x110C,0x0000,0x0000, 0xFB40,0xCE00,0x0000, /* 3190 */ +0xFB40,0xCE8C,0x0000, 0xFB40,0xCE09,0x0000, 0xFB40,0xD6DB,0x0000, /* 3193 */ +0xFB40,0xCE0A,0x0000, 0xFB40,0xCE2D,0x0000, 0xFB40,0xCE0B,0x0000, /* 3196 */ +0xFB40,0xF532,0x0000, 0xFB40,0xCE59,0x0000, 0xFB40,0xCE19,0x0000, /* 3199 */ +0xFB40,0xCE01,0x0000, 0xFB40,0xD929,0x0000, 0xFB40,0xD730,0x0000, /* 319C */ +0xFB40,0xCEBA,0x0000, 0x2B45,0x0000,0x0000, 0x2B5B,0x0000,0x0000, /* 319F */ +0x2B53,0x0000,0x0000, 0x2B4E,0x0000,0x0000, 0x2B63,0x0000,0x0000, /* 31A2 */ +0x2B63,0x0000,0x0000, 0x2B60,0x0000,0x0000, 0x2B5F,0x0000,0x0000, /* 31A5 */ +0x2B72,0x0000,0x0000, 0x2B5E,0x0000,0x0000, 0x2B71,0x0000,0x0000, /* 31A8 */ +0x2B72,0x0000,0x0000, 0x2B6F,0x0000,0x0000, 0x2B51,0x0000,0x0000, /* 31AB */ +0x2B64,0x0000,0x0000, 0x2B66,0x0000,0x0000, 0x2B6D,0x0000,0x0000, /* 31AE */ +0x2B6E,0x0000,0x0000, 0x2B6B,0x0000,0x0000, 0x2B71,0x0000,0x0000, /* 31B1 */ +0x2B46,0x0000,0x0000, 0x2B4B,0x0000,0x0000, 0x2B4F,0x0000,0x0000, /* 31B4 */ +0x2B52,0x0000,0x0000, 0xFBC0,0xB1B8,0x0000, 0xFBC0,0xB1B9,0x0000, /* 31B7 */ +0xFBC0,0xB1BA,0x0000, 0xFBC0,0xB1BB,0x0000, 0xFBC0,0xB1BC,0x0000, /* 31BA */ +0xFBC0,0xB1BD,0x0000, 0xFBC0,0xB1BE,0x0000, 0xFBC0,0xB1BF,0x0000, /* 31BD */ +0x10E0,0x0000,0x0000, 0x10E1,0x0000,0x0000, 0x10E2,0x0000,0x0000, /* 31C0 */ +0x10E3,0x0000,0x0000, 0x10E4,0x0000,0x0000, 0x10E5,0x0000,0x0000, /* 31C3 */ +0x10E6,0x0000,0x0000, 0x10E7,0x0000,0x0000, 0x10E8,0x0000,0x0000, /* 31C6 */ +0x10E9,0x0000,0x0000, 0x10EA,0x0000,0x0000, 0x10EB,0x0000,0x0000, /* 31C9 */ +0x10EC,0x0000,0x0000, 0x10ED,0x0000,0x0000, 0x10EE,0x0000,0x0000, /* 31CC */ +0x10EF,0x0000,0x0000, 0x10F0,0x0000,0x0000, 0x10F1,0x0000,0x0000, /* 31CF */ +0x10F2,0x0000,0x0000, 0x10F3,0x0000,0x0000, 0x10F4,0x0000,0x0000, /* 31D2 */ +0x10F5,0x0000,0x0000, 0x10F6,0x0000,0x0000, 0x10F7,0x0000,0x0000, /* 31D5 */ +0x10F8,0x0000,0x0000, 0x10F9,0x0000,0x0000, 0x10FA,0x0000,0x0000, /* 31D8 */ +0x10FB,0x0000,0x0000, 0x10FC,0x0000,0x0000, 0x10FD,0x0000,0x0000, /* 31DB */ +0x10FE,0x0000,0x0000, 0x10FF,0x0000,0x0000, 0x1100,0x0000,0x0000, /* 31DE */ +0x1101,0x0000,0x0000, 0x1102,0x0000,0x0000, 0x1103,0x0000,0x0000, /* 31E1 */ +0xFBC0,0xB1E4,0x0000, 0xFBC0,0xB1E5,0x0000, 0xFBC0,0xB1E6,0x0000, /* 31E4 */ +0xFBC0,0xB1E7,0x0000, 0xFBC0,0xB1E8,0x0000, 0xFBC0,0xB1E9,0x0000, /* 31E7 */ +0xFBC0,0xB1EA,0x0000, 0xFBC0,0xB1EB,0x0000, 0xFBC0,0xB1EC,0x0000, /* 31EA */ +0xFBC0,0xB1ED,0x0000, 0xFBC0,0xB1EE,0x0000, 0xFBC0,0xB1EF,0x0000, /* 31ED */ +0x2B1C,0x0000,0x0000, 0x2B20,0x0000,0x0000, 0x2B21,0x0000,0x0000, /* 31F0 */ +0x2B28,0x0000,0x0000, 0x2B2B,0x0000,0x0000, 0x2B2E,0x0000,0x0000, /* 31F3 */ +0x2B2F,0x0000,0x0000, 0x2B30,0x0000,0x0000, 0x2B31,0x0000,0x0000, /* 31F6 */ +0x2B32,0x0000,0x0000, 0x2B35,0x0000,0x0000, 0x2B3B,0x0000,0x0000, /* 31F9 */ +0x2B3C,0x0000,0x0000, 0x2B3D,0x0000,0x0000, 0x2B3E,0x0000,0x0000, /* 31FC */ +0x2B3F,0x0000,0x0000 }; + +uint16 uca520_p032[]= { /* 3200 (8 weights per char) */ +0x02FF,0x29B0,0x0300,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3200 */ +0x02FF,0x29B2,0x0300,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3201 */ +0x02FF,0x29B3,0x0300,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3202 */ +0x02FF,0x29B5,0x0300,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3203 */ +0x02FF,0x29B6,0x0300,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3204 */ +0x02FF,0x29B7,0x0300,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3205 */ +0x02FF,0x29B9,0x0300,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3206 */ +0x02FF,0x29BB,0x0300,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3207 */ +0x02FF,0x29BC,0x0300,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3208 */ +0x02FF,0x29BE,0x0300,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3209 */ +0x02FF,0x29BF,0x0300,0x0000,0x0000,0x0000,0x0000,0x0000, /* 320A */ +0x02FF,0x29C0,0x0300,0x0000,0x0000,0x0000,0x0000,0x0000, /* 320B */ +0x02FF,0x29C1,0x0300,0x0000,0x0000,0x0000,0x0000,0x0000, /* 320C */ +0x02FF,0x29C2,0x0300,0x0000,0x0000,0x0000,0x0000,0x0000, /* 320D */ +0x02FF,0x29B0,0x2A2E,0x0300,0x0000,0x0000,0x0000,0x0000, /* 320E */ +0x02FF,0x29B2,0x2A2E,0x0300,0x0000,0x0000,0x0000,0x0000, /* 320F */ +0x02FF,0x29B3,0x2A2E,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3210 */ +0x02FF,0x29B5,0x2A2E,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3211 */ +0x02FF,0x29B6,0x2A2E,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3212 */ +0x02FF,0x29B7,0x2A2E,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3213 */ +0x02FF,0x29B9,0x2A2E,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3214 */ +0x02FF,0x29BB,0x2A2E,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3215 */ +0x02FF,0x29BC,0x2A2E,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3216 */ +0x02FF,0x29BE,0x2A2E,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3217 */ +0x02FF,0x29BF,0x2A2E,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3218 */ +0x02FF,0x29C0,0x2A2E,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3219 */ +0x02FF,0x29C1,0x2A2E,0x0300,0x0000,0x0000,0x0000,0x0000, /* 321A */ +0x02FF,0x29C2,0x2A2E,0x0300,0x0000,0x0000,0x0000,0x0000, /* 321B */ +0x02FF,0x29BC,0x2A3B,0x0300,0x0000,0x0000,0x0000,0x0000, /* 321C */ +0x02FF,0x29BB,0x2A36,0x29BC,0x2A32,0x2A8F,0x0300,0x0000, /* 321D */ +0x02FF,0x29BB,0x2A36,0x29C2,0x2A3B,0x0300,0x0000,0x0000, /* 321E */ +0xFBC0,0xB21F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 321F */ +0x02FF,0xFB40,0xCE00,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3220 */ +0x02FF,0xFB40,0xCE8C,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3221 */ +0x02FF,0xFB40,0xCE09,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3222 */ +0x02FF,0xFB40,0xD6DB,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3223 */ +0x02FF,0xFB40,0xCE94,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3224 */ +0x02FF,0xFB40,0xD16D,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3225 */ +0x02FF,0xFB40,0xCE03,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3226 */ +0x02FF,0xFB40,0xD16B,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3227 */ +0x02FF,0xFB40,0xCE5D,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3228 */ +0x02FF,0xFB40,0xD341,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3229 */ +0x02FF,0xFB40,0xE708,0x0300,0x0000,0x0000,0x0000,0x0000, /* 322A */ +0x02FF,0xFB40,0xF06B,0x0300,0x0000,0x0000,0x0000,0x0000, /* 322B */ +0x02FF,0xFB40,0xEC34,0x0300,0x0000,0x0000,0x0000,0x0000, /* 322C */ +0x02FF,0xFB40,0xE728,0x0300,0x0000,0x0000,0x0000,0x0000, /* 322D */ +0x02FF,0xFB41,0x91D1,0x0300,0x0000,0x0000,0x0000,0x0000, /* 322E */ +0x02FF,0xFB40,0xD71F,0x0300,0x0000,0x0000,0x0000,0x0000, /* 322F */ +0x02FF,0xFB40,0xE5E5,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3230 */ +0x02FF,0xFB40,0xE82A,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3231 */ +0x02FF,0xFB40,0xE709,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3232 */ +0x02FF,0xFB40,0xF93E,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3233 */ +0x02FF,0xFB40,0xD40D,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3234 */ +0x02FF,0xFB40,0xF279,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3235 */ +0x02FF,0xFB41,0x8CA1,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3236 */ +0x02FF,0xFB40,0xF95D,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3237 */ +0x02FF,0xFB40,0xD2B4,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3238 */ +0x02FF,0xFB40,0xCEE3,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3239 */ +0x02FF,0xFB40,0xD47C,0x0300,0x0000,0x0000,0x0000,0x0000, /* 323A */ +0x02FF,0xFB40,0xDB66,0x0300,0x0000,0x0000,0x0000,0x0000, /* 323B */ +0x02FF,0xFB40,0xF6E3,0x0300,0x0000,0x0000,0x0000,0x0000, /* 323C */ +0x02FF,0xFB40,0xCF01,0x0300,0x0000,0x0000,0x0000,0x0000, /* 323D */ +0x02FF,0xFB41,0x8CC7,0x0300,0x0000,0x0000,0x0000,0x0000, /* 323E */ +0x02FF,0xFB40,0xD354,0x0300,0x0000,0x0000,0x0000,0x0000, /* 323F */ +0x02FF,0xFB40,0xF96D,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3240 */ +0x02FF,0xFB40,0xCF11,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3241 */ +0x02FF,0xFB41,0x81EA,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3242 */ +0x02FF,0xFB41,0x81F3,0x0300,0x0000,0x0000,0x0000,0x0000, /* 3243 */ +0xFB40,0xD54F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3244 */ +0xFB40,0xDE7C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3245 */ +0xFB40,0xE587,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3246 */ +0xFB40,0xFB8F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3247 */ +0x1206,0x1205,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3248 */ +0x1207,0x1205,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3249 */ +0x1208,0x1205,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 324A */ +0x1209,0x1205,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 324B */ +0x120A,0x1205,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 324C */ +0x120B,0x1205,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 324D */ +0x120C,0x1205,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 324E */ +0x120D,0x1205,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 324F */ +0x13B3,0x1433,0x126B,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3250 */ +0x1207,0x1206,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3251 */ +0x1207,0x1207,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3252 */ +0x1207,0x1208,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3253 */ +0x1207,0x1209,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3254 */ +0x1207,0x120A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3255 */ +0x1207,0x120B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3256 */ +0x1207,0x120C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3257 */ +0x1207,0x120D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3258 */ +0x1207,0x120E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3259 */ +0x1208,0x1205,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 325A */ +0x1208,0x1206,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 325B */ +0x1208,0x1207,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 325C */ +0x1208,0x1208,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 325D */ +0x1208,0x1209,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 325E */ +0x1208,0x120A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 325F */ +0x29B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3260 */ +0x29B2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3261 */ +0x29B3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3262 */ +0x29B5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3263 */ +0x29B6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3264 */ +0x29B7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3265 */ +0x29B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3266 */ +0x29BB,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3267 */ +0x29BC,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3268 */ +0x29BE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3269 */ +0x29BF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 326A */ +0x29C0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 326B */ +0x29C1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 326C */ +0x29C2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 326D */ +0x29B0,0x2A2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 326E */ +0x29B2,0x2A2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 326F */ +0x29B3,0x2A2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3270 */ +0x29B5,0x2A2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3271 */ +0x29B6,0x2A2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3272 */ +0x29B7,0x2A2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3273 */ +0x29B9,0x2A2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3274 */ +0x29BB,0x2A2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3275 */ +0x29BC,0x2A2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3276 */ +0x29BE,0x2A2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3277 */ +0x29BF,0x2A2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3278 */ +0x29C0,0x2A2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3279 */ +0x29C1,0x2A2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 327A */ +0x29C2,0x2A2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 327B */ +0x29BE,0x2A2E,0x2A9B,0x29B0,0x2A36,0x0000,0x0000,0x0000, /* 327C */ +0x29BC,0x2A3B,0x29BB,0x2A41,0x0000,0x0000,0x0000,0x0000, /* 327D */ +0x29BB,0x2A3B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 327E */ +0x110D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 327F */ +0xFB40,0xCE00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3280 */ +0xFB40,0xCE8C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3281 */ +0xFB40,0xCE09,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3282 */ +0xFB40,0xD6DB,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3283 */ +0xFB40,0xCE94,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3284 */ +0xFB40,0xD16D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3285 */ +0xFB40,0xCE03,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3286 */ +0xFB40,0xD16B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3287 */ +0xFB40,0xCE5D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3288 */ +0xFB40,0xD341,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3289 */ +0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 328A */ +0xFB40,0xF06B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 328B */ +0xFB40,0xEC34,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 328C */ +0xFB40,0xE728,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 328D */ +0xFB41,0x91D1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 328E */ +0xFB40,0xD71F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 328F */ +0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3290 */ +0xFB40,0xE82A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3291 */ +0xFB40,0xE709,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3292 */ +0xFB40,0xF93E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3293 */ +0xFB40,0xD40D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3294 */ +0xFB40,0xF279,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3295 */ +0xFB41,0x8CA1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3296 */ +0xFB40,0xF95D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3297 */ +0xFB40,0xD2B4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3298 */ +0xFB40,0xF9D8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3299 */ +0xFB40,0xF537,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 329A */ +0xFB40,0xD973,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 329B */ +0xFB41,0x9069,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 329C */ +0xFB40,0xD12A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 329D */ +0xFB40,0xD370,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 329E */ +0xFB40,0xECE8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 329F */ +0xFB41,0x9805,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32A0 */ +0xFB40,0xCF11,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32A1 */ +0xFB40,0xD199,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32A2 */ +0xFB40,0xEB63,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32A3 */ +0xFB40,0xCE0A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32A4 */ +0xFB40,0xCE2D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32A5 */ +0xFB40,0xCE0B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32A6 */ +0xFB40,0xDDE6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32A7 */ +0xFB40,0xD3F3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32A8 */ +0xFB40,0xD33B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32A9 */ +0xFB40,0xDB97,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32AA */ +0xFB40,0xDB66,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32AB */ +0xFB40,0xF6E3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32AC */ +0xFB40,0xCF01,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32AD */ +0xFB41,0x8CC7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32AE */ +0xFB40,0xD354,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32AF */ +0xFB40,0xD91C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32B0 */ +0x1208,0x120B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32B1 */ +0x1208,0x120C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32B2 */ +0x1208,0x120D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32B3 */ +0x1208,0x120E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32B4 */ +0x1209,0x1205,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32B5 */ +0x1209,0x1206,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32B6 */ +0x1209,0x1207,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32B7 */ +0x1209,0x1208,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32B8 */ +0x1209,0x1209,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32B9 */ +0x1209,0x120A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32BA */ +0x1209,0x120B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32BB */ +0x1209,0x120C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32BC */ +0x1209,0x120D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32BD */ +0x1209,0x120E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32BE */ +0x120A,0x1205,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32BF */ +0x1206,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32C0 */ +0x1207,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32C1 */ +0x1208,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32C2 */ +0x1209,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32C3 */ +0x120A,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32C4 */ +0x120B,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32C5 */ +0x120C,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32C6 */ +0x120D,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32C7 */ +0x120E,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32C8 */ +0x1206,0x1205,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000, /* 32C9 */ +0x1206,0x1206,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000, /* 32CA */ +0x1206,0x1207,0xFB40,0xE708,0x0000,0x0000,0x0000,0x0000, /* 32CB */ +0x12D3,0x12B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32CC */ +0x126B,0x13DA,0x12B0,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32CD */ +0x126B,0x147B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32CE */ +0x1330,0x1433,0x1250,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32CF */ +0x2B15,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32D0 */ +0x2B16,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32D1 */ +0x2B17,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32D2 */ +0x2B18,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32D3 */ +0x2B19,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32D4 */ +0x2B1A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32D5 */ +0x2B1B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32D6 */ +0x2B1C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32D7 */ +0x2B1D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32D8 */ +0x2B1E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32D9 */ +0x2B1F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32DA */ +0x2B20,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32DB */ +0x2B21,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32DC */ +0x2B22,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32DD */ +0x2B23,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32DE */ +0x2B24,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32DF */ +0x2B25,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32E0 */ +0x2B26,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32E1 */ +0x2B27,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32E2 */ +0x2B28,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32E3 */ +0x2B29,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32E4 */ +0x2B2A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32E5 */ +0x2B2B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32E6 */ +0x2B2C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32E7 */ +0x2B2D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32E8 */ +0x2B2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32E9 */ +0x2B2F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32EA */ +0x2B30,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32EB */ +0x2B31,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32EC */ +0x2B32,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32ED */ +0x2B33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32EE */ +0x2B34,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32EF */ +0x2B35,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32F0 */ +0x2B36,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32F1 */ +0x2B37,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32F2 */ +0x2B38,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32F3 */ +0x2B39,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32F4 */ +0x2B3A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32F5 */ +0x2B3B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32F6 */ +0x2B3C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32F7 */ +0x2B3D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32F8 */ +0x2B3E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32F9 */ +0x2B3F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32FA */ +0x2B40,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32FB */ +0x2B41,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32FC */ +0x2B42,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32FD */ +0x2B43,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 32FE */ +0xFBC0,0xB2FF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 /* 32FF */ +}; + +uint16 uca520_p033[]= { /* 3300 (9 weights per char) */ +0x2B15,0x2B2E,0x11DD,0x2B28,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3300 */ +0x2B15,0x2B3D,0x2B30,0x2B15,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3301 */ +0x2B15,0x2B44,0x2B31,0x2B15,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3302 */ +0x2B15,0x11DD,0x2B3D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3303 */ +0x2B16,0x2B2A,0x2B44,0x2B1C,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3304 */ +0x2B16,0x2B44,0x2B25,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3305 */ +0x2B17,0x2B19,0x2B44,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3306 */ +0x2B18,0x2B21,0x2B1C,0x11DD,0x2B28,0x0000,0x0000,0x0000,0x0000, /* 3307 */ +0x2B18,0x11DD,0x2B1A,0x11DD,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3308 */ +0x2B19,0x2B44,0x2B21,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3309 */ +0x2B19,0x11DD,0x2B35,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 330A */ +0x2B1A,0x2B16,0x2B3C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 330B */ +0x2B1A,0x2B3B,0x2B26,0x2B28,0x0000,0x0000,0x0000,0x0000,0x0000, /* 330C */ +0x2B1A,0x2B3F,0x2B3C,0x11DD,0x0000,0x0000,0x0000,0x0000,0x0000, /* 330D */ +0x2B1A,0x2B3F,0x2B44,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 330E */ +0x2B1A,0x2B44,0x2B33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 330F */ +0x2B1B,0x2B1A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3310 */ +0x2B1B,0x2B2A,0x11DD,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3311 */ +0x2B1B,0x2B39,0x2B3C,0x11DD,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3312 */ +0x2B1B,0x2B3D,0x2B24,0x11DD,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3313 */ +0x2B1B,0x2B3F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3314 */ +0x2B1B,0x2B3F,0x2B1C,0x2B3B,0x2B35,0x0000,0x0000,0x0000,0x0000, /* 3315 */ +0x2B1B,0x2B3F,0x2B36,0x11DD,0x2B28,0x2B3D,0x0000,0x0000,0x0000, /* 3316 */ +0x2B1B,0x2B3F,0x2B40,0x2B26,0x2B28,0x0000,0x0000,0x0000,0x0000, /* 3317 */ +0x2B1C,0x2B3B,0x2B35,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3318 */ +0x2B1C,0x2B3B,0x2B35,0x2B28,0x2B44,0x0000,0x0000,0x0000,0x0000, /* 3319 */ +0x2B1C,0x2B3D,0x2B22,0x2B16,0x2B3F,0x0000,0x0000,0x0000,0x0000, /* 331A */ +0x2B1C,0x2B3F,0x11DD,0x2B2C,0x0000,0x0000,0x0000,0x0000,0x0000, /* 331B */ +0x2B1D,0x11DD,0x2B21,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 331C */ +0x2B1E,0x2B3D,0x2B29,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 331D */ +0x2B1E,0x11DD,0x2B32,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 331E */ +0x2B1F,0x2B16,0x2B1C,0x2B3D,0x0000,0x0000,0x0000,0x0000,0x0000, /* 331F */ +0x2B1F,0x2B44,0x2B25,0x11DD,0x2B35,0x0000,0x0000,0x0000,0x0000, /* 3320 */ +0x2B20,0x2B3C,0x2B44,0x2B1C,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3321 */ +0x2B22,0x2B44,0x2B25,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3322 */ +0x2B22,0x2B44,0x2B28,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3323 */ +0x2B24,0x11DD,0x2B21,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3324 */ +0x2B27,0x2B20,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3325 */ +0x2B28,0x2B3D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3326 */ +0x2B28,0x2B44,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3327 */ +0x2B29,0x2B2D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3328 */ +0x2B2D,0x2B26,0x2B28,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3329 */ +0x2B2E,0x2B16,0x2B26,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 332A */ +0x2B2E,0x11DD,0x2B22,0x2B44,0x2B28,0x0000,0x0000,0x0000,0x0000, /* 332B */ +0x2B2E,0x11DD,0x2B26,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 332C */ +0x2B2E,0x11DD,0x2B3E,0x2B3D,0x0000,0x0000,0x0000,0x0000,0x0000, /* 332D */ +0x2B2F,0x2B15,0x2B21,0x2B28,0x2B3D,0x0000,0x0000,0x0000,0x0000, /* 332E */ +0x2B2F,0x2B1C,0x2B3D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 332F */ +0x2B2F,0x2B1E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3330 */ +0x2B2F,0x2B3D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3331 */ +0x2B30,0x2B15,0x2B3B,0x2B26,0x2B28,0x0000,0x0000,0x0000,0x0000, /* 3332 */ +0x2B30,0x2B16,0x11DD,0x2B28,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3333 */ +0x2B30,0x2B26,0x2B20,0x2B18,0x2B3D,0x0000,0x0000,0x0000,0x0000, /* 3334 */ +0x2B30,0x2B3B,0x2B44,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3335 */ +0x2B31,0x2B1C,0x2B24,0x11DD,0x2B3D,0x0000,0x0000,0x0000,0x0000, /* 3336 */ +0x2B31,0x2B23,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3337 */ +0x2B31,0x2B2A,0x2B2F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3338 */ +0x2B31,0x2B3D,0x2B26,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3339 */ +0x2B31,0x2B44,0x2B21,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 333A */ +0x2B31,0x11DD,0x2B20,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 333B */ +0x2B31,0x11DD,0x2B24,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 333C */ +0x2B32,0x2B16,0x2B44,0x2B28,0x0000,0x0000,0x0000,0x0000,0x0000, /* 333D */ +0x2B32,0x2B3D,0x2B28,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 333E */ +0x2B32,0x2B44,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 333F */ +0x2B32,0x2B44,0x2B28,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3340 */ +0x2B32,0x11DD,0x2B3D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3341 */ +0x2B32,0x11DD,0x2B44,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3342 */ +0x2B33,0x2B16,0x2B1C,0x2B3F,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3343 */ +0x2B33,0x2B16,0x2B3D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3344 */ +0x2B33,0x2B26,0x2B2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3345 */ +0x2B33,0x2B3D,0x2B1C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3346 */ +0x2B33,0x2B44,0x2B20,0x2B3A,0x2B44,0x0000,0x0000,0x0000,0x0000, /* 3347 */ +0x2B34,0x2B1C,0x2B3F,0x2B44,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3348 */ +0x2B34,0x2B3C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3349 */ +0x2B34,0x2B3C,0x2B2E,0x11DD,0x2B3D,0x0000,0x0000,0x0000,0x0000, /* 334A */ +0x2B36,0x2B1A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 334B */ +0x2B36,0x2B1A,0x2B28,0x2B44,0x0000,0x0000,0x0000,0x0000,0x0000, /* 334C */ +0x2B36,0x11DD,0x2B28,0x2B3D,0x0000,0x0000,0x0000,0x0000,0x0000, /* 334D */ +0x2B38,0x11DD,0x2B28,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 334E */ +0x2B38,0x11DD,0x2B3D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 334F */ +0x2B39,0x2B15,0x2B44,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3350 */ +0x2B3C,0x2B26,0x2B28,0x2B3D,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3351 */ +0x2B3C,0x2B3B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3352 */ +0x2B3D,0x2B2F,0x11DD,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3353 */ +0x2B3D,0x11DD,0x2B30,0x2B3D,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3354 */ +0x2B3E,0x2B35,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3355 */ +0x2B3E,0x2B44,0x2B28,0x2B1D,0x2B44,0x0000,0x0000,0x0000,0x0000, /* 3356 */ +0x2B40,0x2B26,0x2B28,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3357 */ +0x1205,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3358 */ +0x1206,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3359 */ +0x1207,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 335A */ +0x1208,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 335B */ +0x1209,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 335C */ +0x120A,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 335D */ +0x120B,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 335E */ +0x120C,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 335F */ +0x120D,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3360 */ +0x120E,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3361 */ +0x1206,0x1205,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3362 */ +0x1206,0x1206,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3363 */ +0x1206,0x1207,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3364 */ +0x1206,0x1208,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3365 */ +0x1206,0x1209,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3366 */ +0x1206,0x120A,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3367 */ +0x1206,0x120B,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3368 */ +0x1206,0x120C,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3369 */ +0x1206,0x120D,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, /* 336A */ +0x1206,0x120E,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, /* 336B */ +0x1207,0x1205,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, /* 336C */ +0x1207,0x1206,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, /* 336D */ +0x1207,0x1207,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, /* 336E */ +0x1207,0x1208,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, /* 336F */ +0x1207,0x1209,0xFB40,0xF0B9,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3370 */ +0x12D3,0x13B3,0x120F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3371 */ +0x1250,0x120F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3372 */ +0x120F,0x1453,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3373 */ +0x1225,0x120F,0x13DA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3374 */ +0x138E,0x147B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3375 */ +0x13B3,0x123D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3376 */ +0x1250,0x135F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3377 */ +0x1250,0x135F,0x1207,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3378 */ +0x1250,0x135F,0x1208,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3379 */ +0x12EC,0x1453,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 337A */ +0xFB40,0xDE73,0xFB40,0xE210,0x0000,0x0000,0x0000,0x0000,0x0000, /* 337B */ +0xFB40,0xE62D,0xFB40,0xD48C,0x0000,0x0000,0x0000,0x0000,0x0000, /* 337C */ +0xFB40,0xD927,0xFB40,0xEB63,0x0000,0x0000,0x0000,0x0000,0x0000, /* 337D */ +0xFB40,0xE60E,0xFB40,0xECBB,0x0000,0x0000,0x0000,0x0000,0x0000, /* 337E */ +0xFB40,0xE82A,0xFB40,0xDF0F,0xFB40,0xCF1A,0xFB40,0xF93E,0x0000, /* 337F */ +0x13B3,0x120F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3380 */ +0x136D,0x120F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3381 */ +0x1557,0x120F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3382 */ +0x135F,0x120F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3383 */ +0x131E,0x120F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3384 */ +0x131E,0x1225,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3385 */ +0x135F,0x1225,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3386 */ +0x12B0,0x1225,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3387 */ +0x123D,0x120F,0x1330,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3388 */ +0x131E,0x123D,0x120F,0x1330,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3389 */ +0x13B3,0x12A3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 338A */ +0x136D,0x12A3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 338B */ +0x1557,0x12A3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 338C */ +0x1557,0x12B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 338D */ +0x135F,0x12B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 338E */ +0x131E,0x12B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 338F */ +0x12D3,0x14AD,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3390 */ +0x131E,0x12D3,0x14AD,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3391 */ +0x135F,0x12D3,0x14AD,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3392 */ +0x12B0,0x12D3,0x14AD,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3393 */ +0x1433,0x12D3,0x14AD,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3394 */ +0x1557,0x1330,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3395 */ +0x135F,0x1330,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3396 */ +0x1250,0x1330,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3397 */ +0x131E,0x1330,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3398 */ +0x12A3,0x135F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 3399 */ +0x136D,0x135F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 339A */ +0x1557,0x135F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 339B */ +0x135F,0x135F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 339C */ +0x123D,0x135F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 339D */ +0x131E,0x135F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 339E */ +0x135F,0x135F,0x1207,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 339F */ +0x123D,0x135F,0x1207,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33A0 */ +0x135F,0x1207,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33A1 */ +0x131E,0x135F,0x1207,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33A2 */ +0x135F,0x135F,0x1208,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33A3 */ +0x123D,0x135F,0x1208,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33A4 */ +0x135F,0x1208,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33A5 */ +0x131E,0x135F,0x1208,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33A6 */ +0x135F,0x055F,0x1410,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33A7 */ +0x135F,0x055F,0x1410,0x1207,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33A8 */ +0x13B3,0x120F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33A9 */ +0x131E,0x13B3,0x120F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33AA */ +0x135F,0x13B3,0x120F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33AB */ +0x12B0,0x13B3,0x120F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33AC */ +0x13DA,0x120F,0x1250,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33AD */ +0x13DA,0x120F,0x1250,0x055F,0x1410,0x0000,0x0000,0x0000,0x0000, /* 33AE */ +0x13DA,0x120F,0x1250,0x055F,0x1410,0x1207,0x0000,0x0000,0x0000, /* 33AF */ +0x13B3,0x1410,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33B0 */ +0x136D,0x1410,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33B1 */ +0x1557,0x1410,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33B2 */ +0x135F,0x1410,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33B3 */ +0x13B3,0x147B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33B4 */ +0x136D,0x147B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33B5 */ +0x1557,0x147B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33B6 */ +0x135F,0x147B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33B7 */ +0x131E,0x147B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33B8 */ +0x135F,0x147B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33B9 */ +0x13B3,0x148D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33BA */ +0x136D,0x148D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33BB */ +0x1557,0x148D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33BC */ +0x135F,0x148D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33BD */ +0x131E,0x148D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33BE */ +0x135F,0x148D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33BF */ +0x131E,0x156D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33C0 */ +0x135F,0x156D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33C1 */ +0x120F,0x0281,0x135F,0x0281,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33C2 */ +0x1225,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33C3 */ +0x123D,0x123D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33C4 */ +0x123D,0x1250,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33C5 */ +0x123D,0x055F,0x131E,0x12B0,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33C6 */ +0x123D,0x138E,0x0281,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33C7 */ +0x1250,0x1225,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33C8 */ +0x12B0,0x149C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33C9 */ +0x12D3,0x120F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33CA */ +0x12D3,0x13B3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33CB */ +0x12EC,0x136D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33CC */ +0x131E,0x131E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33CD */ +0x131E,0x135F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33CE */ +0x131E,0x1433,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33CF */ +0x1330,0x135F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33D0 */ +0x1330,0x136D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33D1 */ +0x1330,0x138E,0x12B0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33D2 */ +0x1330,0x1497,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33D3 */ +0x135F,0x1225,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33D4 */ +0x135F,0x12EC,0x1330,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33D5 */ +0x135F,0x138E,0x1330,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33D6 */ +0x13B3,0x12D3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33D7 */ +0x13B3,0x0281,0x135F,0x0281,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33D8 */ +0x13B3,0x13B3,0x135F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33D9 */ +0x13B3,0x13DA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33DA */ +0x1410,0x13DA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33DB */ +0x1410,0x147B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33DC */ +0x148D,0x1225,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33DD */ +0x147B,0x055F,0x135F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33DE */ +0x120F,0x055F,0x135F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33DF */ +0x1206,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33E0 */ +0x1207,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33E1 */ +0x1208,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33E2 */ +0x1209,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33E3 */ +0x120A,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33E4 */ +0x120B,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33E5 */ +0x120C,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33E6 */ +0x120D,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33E7 */ +0x120E,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33E8 */ +0x1206,0x1205,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33E9 */ +0x1206,0x1206,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33EA */ +0x1206,0x1207,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33EB */ +0x1206,0x1208,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33EC */ +0x1206,0x1209,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33ED */ +0x1206,0x120A,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33EE */ +0x1206,0x120B,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33EF */ +0x1206,0x120C,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33F0 */ +0x1206,0x120D,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33F1 */ +0x1206,0x120E,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33F2 */ +0x1207,0x1205,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33F3 */ +0x1207,0x1206,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33F4 */ +0x1207,0x1207,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33F5 */ +0x1207,0x1208,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33F6 */ +0x1207,0x1209,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33F7 */ +0x1207,0x120A,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33F8 */ +0x1207,0x120B,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33F9 */ +0x1207,0x120C,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33FA */ +0x1207,0x120D,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33FB */ +0x1207,0x120E,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33FC */ +0x1208,0x1205,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33FD */ +0x1208,0x1206,0xFB40,0xE5E5,0x0000,0x0000,0x0000,0x0000,0x0000, /* 33FE */ +0x12B0,0x120F,0x1330,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 /* 33FF */ +}; + +uint16 uca520_p04D[]= { /* 4D00 (3 weights per char) */ +0xFB80,0xCD00,0x0000, 0xFB80,0xCD01,0x0000, 0xFB80,0xCD02,0x0000, /* 4D00 */ +0xFB80,0xCD03,0x0000, 0xFB80,0xCD04,0x0000, 0xFB80,0xCD05,0x0000, /* 4D03 */ +0xFB80,0xCD06,0x0000, 0xFB80,0xCD07,0x0000, 0xFB80,0xCD08,0x0000, /* 4D06 */ +0xFB80,0xCD09,0x0000, 0xFB80,0xCD0A,0x0000, 0xFB80,0xCD0B,0x0000, /* 4D09 */ +0xFB80,0xCD0C,0x0000, 0xFB80,0xCD0D,0x0000, 0xFB80,0xCD0E,0x0000, /* 4D0C */ +0xFB80,0xCD0F,0x0000, 0xFB80,0xCD10,0x0000, 0xFB80,0xCD11,0x0000, /* 4D0F */ +0xFB80,0xCD12,0x0000, 0xFB80,0xCD13,0x0000, 0xFB80,0xCD14,0x0000, /* 4D12 */ +0xFB80,0xCD15,0x0000, 0xFB80,0xCD16,0x0000, 0xFB80,0xCD17,0x0000, /* 4D15 */ +0xFB80,0xCD18,0x0000, 0xFB80,0xCD19,0x0000, 0xFB80,0xCD1A,0x0000, /* 4D18 */ +0xFB80,0xCD1B,0x0000, 0xFB80,0xCD1C,0x0000, 0xFB80,0xCD1D,0x0000, /* 4D1B */ +0xFB80,0xCD1E,0x0000, 0xFB80,0xCD1F,0x0000, 0xFB80,0xCD20,0x0000, /* 4D1E */ +0xFB80,0xCD21,0x0000, 0xFB80,0xCD22,0x0000, 0xFB80,0xCD23,0x0000, /* 4D21 */ +0xFB80,0xCD24,0x0000, 0xFB80,0xCD25,0x0000, 0xFB80,0xCD26,0x0000, /* 4D24 */ +0xFB80,0xCD27,0x0000, 0xFB80,0xCD28,0x0000, 0xFB80,0xCD29,0x0000, /* 4D27 */ +0xFB80,0xCD2A,0x0000, 0xFB80,0xCD2B,0x0000, 0xFB80,0xCD2C,0x0000, /* 4D2A */ +0xFB80,0xCD2D,0x0000, 0xFB80,0xCD2E,0x0000, 0xFB80,0xCD2F,0x0000, /* 4D2D */ +0xFB80,0xCD30,0x0000, 0xFB80,0xCD31,0x0000, 0xFB80,0xCD32,0x0000, /* 4D30 */ +0xFB80,0xCD33,0x0000, 0xFB80,0xCD34,0x0000, 0xFB80,0xCD35,0x0000, /* 4D33 */ +0xFB80,0xCD36,0x0000, 0xFB80,0xCD37,0x0000, 0xFB80,0xCD38,0x0000, /* 4D36 */ +0xFB80,0xCD39,0x0000, 0xFB80,0xCD3A,0x0000, 0xFB80,0xCD3B,0x0000, /* 4D39 */ +0xFB80,0xCD3C,0x0000, 0xFB80,0xCD3D,0x0000, 0xFB80,0xCD3E,0x0000, /* 4D3C */ +0xFB80,0xCD3F,0x0000, 0xFB80,0xCD40,0x0000, 0xFB80,0xCD41,0x0000, /* 4D3F */ +0xFB80,0xCD42,0x0000, 0xFB80,0xCD43,0x0000, 0xFB80,0xCD44,0x0000, /* 4D42 */ +0xFB80,0xCD45,0x0000, 0xFB80,0xCD46,0x0000, 0xFB80,0xCD47,0x0000, /* 4D45 */ +0xFB80,0xCD48,0x0000, 0xFB80,0xCD49,0x0000, 0xFB80,0xCD4A,0x0000, /* 4D48 */ +0xFB80,0xCD4B,0x0000, 0xFB80,0xCD4C,0x0000, 0xFB80,0xCD4D,0x0000, /* 4D4B */ +0xFB80,0xCD4E,0x0000, 0xFB80,0xCD4F,0x0000, 0xFB80,0xCD50,0x0000, /* 4D4E */ +0xFB80,0xCD51,0x0000, 0xFB80,0xCD52,0x0000, 0xFB80,0xCD53,0x0000, /* 4D51 */ +0xFB80,0xCD54,0x0000, 0xFB80,0xCD55,0x0000, 0xFB80,0xCD56,0x0000, /* 4D54 */ +0xFB80,0xCD57,0x0000, 0xFB80,0xCD58,0x0000, 0xFB80,0xCD59,0x0000, /* 4D57 */ +0xFB80,0xCD5A,0x0000, 0xFB80,0xCD5B,0x0000, 0xFB80,0xCD5C,0x0000, /* 4D5A */ +0xFB80,0xCD5D,0x0000, 0xFB80,0xCD5E,0x0000, 0xFB80,0xCD5F,0x0000, /* 4D5D */ +0xFB80,0xCD60,0x0000, 0xFB80,0xCD61,0x0000, 0xFB80,0xCD62,0x0000, /* 4D60 */ +0xFB80,0xCD63,0x0000, 0xFB80,0xCD64,0x0000, 0xFB80,0xCD65,0x0000, /* 4D63 */ +0xFB80,0xCD66,0x0000, 0xFB80,0xCD67,0x0000, 0xFB80,0xCD68,0x0000, /* 4D66 */ +0xFB80,0xCD69,0x0000, 0xFB80,0xCD6A,0x0000, 0xFB80,0xCD6B,0x0000, /* 4D69 */ +0xFB80,0xCD6C,0x0000, 0xFB80,0xCD6D,0x0000, 0xFB80,0xCD6E,0x0000, /* 4D6C */ +0xFB80,0xCD6F,0x0000, 0xFB80,0xCD70,0x0000, 0xFB80,0xCD71,0x0000, /* 4D6F */ +0xFB80,0xCD72,0x0000, 0xFB80,0xCD73,0x0000, 0xFB80,0xCD74,0x0000, /* 4D72 */ +0xFB80,0xCD75,0x0000, 0xFB80,0xCD76,0x0000, 0xFB80,0xCD77,0x0000, /* 4D75 */ +0xFB80,0xCD78,0x0000, 0xFB80,0xCD79,0x0000, 0xFB80,0xCD7A,0x0000, /* 4D78 */ +0xFB80,0xCD7B,0x0000, 0xFB80,0xCD7C,0x0000, 0xFB80,0xCD7D,0x0000, /* 4D7B */ +0xFB80,0xCD7E,0x0000, 0xFB80,0xCD7F,0x0000, 0xFB80,0xCD80,0x0000, /* 4D7E */ +0xFB80,0xCD81,0x0000, 0xFB80,0xCD82,0x0000, 0xFB80,0xCD83,0x0000, /* 4D81 */ +0xFB80,0xCD84,0x0000, 0xFB80,0xCD85,0x0000, 0xFB80,0xCD86,0x0000, /* 4D84 */ +0xFB80,0xCD87,0x0000, 0xFB80,0xCD88,0x0000, 0xFB80,0xCD89,0x0000, /* 4D87 */ +0xFB80,0xCD8A,0x0000, 0xFB80,0xCD8B,0x0000, 0xFB80,0xCD8C,0x0000, /* 4D8A */ +0xFB80,0xCD8D,0x0000, 0xFB80,0xCD8E,0x0000, 0xFB80,0xCD8F,0x0000, /* 4D8D */ +0xFB80,0xCD90,0x0000, 0xFB80,0xCD91,0x0000, 0xFB80,0xCD92,0x0000, /* 4D90 */ +0xFB80,0xCD93,0x0000, 0xFB80,0xCD94,0x0000, 0xFB80,0xCD95,0x0000, /* 4D93 */ +0xFB80,0xCD96,0x0000, 0xFB80,0xCD97,0x0000, 0xFB80,0xCD98,0x0000, /* 4D96 */ +0xFB80,0xCD99,0x0000, 0xFB80,0xCD9A,0x0000, 0xFB80,0xCD9B,0x0000, /* 4D99 */ +0xFB80,0xCD9C,0x0000, 0xFB80,0xCD9D,0x0000, 0xFB80,0xCD9E,0x0000, /* 4D9C */ +0xFB80,0xCD9F,0x0000, 0xFB80,0xCDA0,0x0000, 0xFB80,0xCDA1,0x0000, /* 4D9F */ +0xFB80,0xCDA2,0x0000, 0xFB80,0xCDA3,0x0000, 0xFB80,0xCDA4,0x0000, /* 4DA2 */ +0xFB80,0xCDA5,0x0000, 0xFB80,0xCDA6,0x0000, 0xFB80,0xCDA7,0x0000, /* 4DA5 */ +0xFB80,0xCDA8,0x0000, 0xFB80,0xCDA9,0x0000, 0xFB80,0xCDAA,0x0000, /* 4DA8 */ +0xFB80,0xCDAB,0x0000, 0xFB80,0xCDAC,0x0000, 0xFB80,0xCDAD,0x0000, /* 4DAB */ +0xFB80,0xCDAE,0x0000, 0xFB80,0xCDAF,0x0000, 0xFB80,0xCDB0,0x0000, /* 4DAE */ +0xFB80,0xCDB1,0x0000, 0xFB80,0xCDB2,0x0000, 0xFB80,0xCDB3,0x0000, /* 4DB1 */ +0xFB80,0xCDB4,0x0000, 0xFB80,0xCDB5,0x0000, 0xFBC0,0xCDB6,0x0000, /* 4DB4 */ +0xFBC0,0xCDB7,0x0000, 0xFBC0,0xCDB8,0x0000, 0xFBC0,0xCDB9,0x0000, /* 4DB7 */ +0xFBC0,0xCDBA,0x0000, 0xFBC0,0xCDBB,0x0000, 0xFBC0,0xCDBC,0x0000, /* 4DBA */ +0xFBC0,0xCDBD,0x0000, 0xFBC0,0xCDBE,0x0000, 0xFBC0,0xCDBF,0x0000, /* 4DBD */ +0x0D3E,0x0000,0x0000, 0x0D3F,0x0000,0x0000, 0x0D40,0x0000,0x0000, /* 4DC0 */ +0x0D41,0x0000,0x0000, 0x0D42,0x0000,0x0000, 0x0D43,0x0000,0x0000, /* 4DC3 */ +0x0D44,0x0000,0x0000, 0x0D45,0x0000,0x0000, 0x0D46,0x0000,0x0000, /* 4DC6 */ +0x0D47,0x0000,0x0000, 0x0D48,0x0000,0x0000, 0x0D49,0x0000,0x0000, /* 4DC9 */ +0x0D4A,0x0000,0x0000, 0x0D4B,0x0000,0x0000, 0x0D4C,0x0000,0x0000, /* 4DCC */ +0x0D4D,0x0000,0x0000, 0x0D4E,0x0000,0x0000, 0x0D4F,0x0000,0x0000, /* 4DCF */ +0x0D50,0x0000,0x0000, 0x0D51,0x0000,0x0000, 0x0D52,0x0000,0x0000, /* 4DD2 */ +0x0D53,0x0000,0x0000, 0x0D54,0x0000,0x0000, 0x0D55,0x0000,0x0000, /* 4DD5 */ +0x0D56,0x0000,0x0000, 0x0D57,0x0000,0x0000, 0x0D58,0x0000,0x0000, /* 4DD8 */ +0x0D59,0x0000,0x0000, 0x0D5A,0x0000,0x0000, 0x0D5B,0x0000,0x0000, /* 4DDB */ +0x0D5C,0x0000,0x0000, 0x0D5D,0x0000,0x0000, 0x0D5E,0x0000,0x0000, /* 4DDE */ +0x0D5F,0x0000,0x0000, 0x0D60,0x0000,0x0000, 0x0D61,0x0000,0x0000, /* 4DE1 */ +0x0D62,0x0000,0x0000, 0x0D63,0x0000,0x0000, 0x0D64,0x0000,0x0000, /* 4DE4 */ +0x0D65,0x0000,0x0000, 0x0D66,0x0000,0x0000, 0x0D67,0x0000,0x0000, /* 4DE7 */ +0x0D68,0x0000,0x0000, 0x0D69,0x0000,0x0000, 0x0D6A,0x0000,0x0000, /* 4DEA */ +0x0D6B,0x0000,0x0000, 0x0D6C,0x0000,0x0000, 0x0D6D,0x0000,0x0000, /* 4DED */ +0x0D6E,0x0000,0x0000, 0x0D6F,0x0000,0x0000, 0x0D70,0x0000,0x0000, /* 4DF0 */ +0x0D71,0x0000,0x0000, 0x0D72,0x0000,0x0000, 0x0D73,0x0000,0x0000, /* 4DF3 */ +0x0D74,0x0000,0x0000, 0x0D75,0x0000,0x0000, 0x0D76,0x0000,0x0000, /* 4DF6 */ +0x0D77,0x0000,0x0000, 0x0D78,0x0000,0x0000, 0x0D79,0x0000,0x0000, /* 4DF9 */ +0x0D7A,0x0000,0x0000, 0x0D7B,0x0000,0x0000, 0x0D7C,0x0000,0x0000, /* 4DFC */ +0x0D7D,0x0000,0x0000 }; + +uint16 uca520_p0A0[]= { /* A000 (2 weights per char) */ +0x2B75,0x0000, 0x2B76,0x0000, 0x2B77,0x0000, 0x2B78,0x0000, /* A000 */ +0x2B79,0x0000, 0x2B7A,0x0000, 0x2B7B,0x0000, 0x2B7C,0x0000, /* A004 */ +0x2B7D,0x0000, 0x2B7E,0x0000, 0x2B7F,0x0000, 0x2B80,0x0000, /* A008 */ +0x2B81,0x0000, 0x2B82,0x0000, 0x2B83,0x0000, 0x2B84,0x0000, /* A00C */ +0x2B85,0x0000, 0x2B86,0x0000, 0x2B87,0x0000, 0x2B88,0x0000, /* A010 */ +0x2B89,0x0000, 0x2B8A,0x0000, 0x2B8B,0x0000, 0x2B8C,0x0000, /* A014 */ +0x2B8D,0x0000, 0x2B8E,0x0000, 0x2B8F,0x0000, 0x2B90,0x0000, /* A018 */ +0x2B91,0x0000, 0x2B92,0x0000, 0x2B93,0x0000, 0x2B94,0x0000, /* A01C */ +0x2B95,0x0000, 0x2B96,0x0000, 0x2B97,0x0000, 0x2B98,0x0000, /* A020 */ +0x2B99,0x0000, 0x2B9A,0x0000, 0x2B9B,0x0000, 0x2B9C,0x0000, /* A024 */ +0x2B9D,0x0000, 0x2B9E,0x0000, 0x2B9F,0x0000, 0x2BA0,0x0000, /* A028 */ +0x2BA1,0x0000, 0x2BA2,0x0000, 0x2BA3,0x0000, 0x2BA4,0x0000, /* A02C */ +0x2BA5,0x0000, 0x2BA6,0x0000, 0x2BA7,0x0000, 0x2BA8,0x0000, /* A030 */ +0x2BA9,0x0000, 0x2BAA,0x0000, 0x2BAB,0x0000, 0x2BAC,0x0000, /* A034 */ +0x2BAD,0x0000, 0x2BAE,0x0000, 0x2BAF,0x0000, 0x2BB0,0x0000, /* A038 */ +0x2BB1,0x0000, 0x2BB2,0x0000, 0x2BB3,0x0000, 0x2BB4,0x0000, /* A03C */ +0x2BB5,0x0000, 0x2BB6,0x0000, 0x2BB7,0x0000, 0x2BB8,0x0000, /* A040 */ +0x2BB9,0x0000, 0x2BBA,0x0000, 0x2BBB,0x0000, 0x2BBC,0x0000, /* A044 */ +0x2BBD,0x0000, 0x2BBE,0x0000, 0x2BBF,0x0000, 0x2BC0,0x0000, /* A048 */ +0x2BC1,0x0000, 0x2BC2,0x0000, 0x2BC3,0x0000, 0x2BC4,0x0000, /* A04C */ +0x2BC5,0x0000, 0x2BC6,0x0000, 0x2BC7,0x0000, 0x2BC8,0x0000, /* A050 */ +0x2BC9,0x0000, 0x2BCA,0x0000, 0x2BCB,0x0000, 0x2BCC,0x0000, /* A054 */ +0x2BCD,0x0000, 0x2BCE,0x0000, 0x2BCF,0x0000, 0x2BD0,0x0000, /* A058 */ +0x2BD1,0x0000, 0x2BD2,0x0000, 0x2BD3,0x0000, 0x2BD4,0x0000, /* A05C */ +0x2BD5,0x0000, 0x2BD6,0x0000, 0x2BD7,0x0000, 0x2BD8,0x0000, /* A060 */ +0x2BD9,0x0000, 0x2BDA,0x0000, 0x2BDB,0x0000, 0x2BDC,0x0000, /* A064 */ +0x2BDD,0x0000, 0x2BDE,0x0000, 0x2BDF,0x0000, 0x2BE0,0x0000, /* A068 */ +0x2BE1,0x0000, 0x2BE2,0x0000, 0x2BE3,0x0000, 0x2BE4,0x0000, /* A06C */ +0x2BE5,0x0000, 0x2BE6,0x0000, 0x2BE7,0x0000, 0x2BE8,0x0000, /* A070 */ +0x2BE9,0x0000, 0x2BEA,0x0000, 0x2BEB,0x0000, 0x2BEC,0x0000, /* A074 */ +0x2BED,0x0000, 0x2BEE,0x0000, 0x2BEF,0x0000, 0x2BF0,0x0000, /* A078 */ +0x2BF1,0x0000, 0x2BF2,0x0000, 0x2BF3,0x0000, 0x2BF4,0x0000, /* A07C */ +0x2BF5,0x0000, 0x2BF6,0x0000, 0x2BF7,0x0000, 0x2BF8,0x0000, /* A080 */ +0x2BF9,0x0000, 0x2BFA,0x0000, 0x2BFB,0x0000, 0x2BFC,0x0000, /* A084 */ +0x2BFD,0x0000, 0x2BFE,0x0000, 0x2BFF,0x0000, 0x2C00,0x0000, /* A088 */ +0x2C01,0x0000, 0x2C02,0x0000, 0x2C03,0x0000, 0x2C04,0x0000, /* A08C */ +0x2C05,0x0000, 0x2C06,0x0000, 0x2C07,0x0000, 0x2C08,0x0000, /* A090 */ +0x2C09,0x0000, 0x2C0A,0x0000, 0x2C0B,0x0000, 0x2C0C,0x0000, /* A094 */ +0x2C0D,0x0000, 0x2C0E,0x0000, 0x2C0F,0x0000, 0x2C10,0x0000, /* A098 */ +0x2C11,0x0000, 0x2C12,0x0000, 0x2C13,0x0000, 0x2C14,0x0000, /* A09C */ +0x2C15,0x0000, 0x2C16,0x0000, 0x2C17,0x0000, 0x2C18,0x0000, /* A0A0 */ +0x2C19,0x0000, 0x2C1A,0x0000, 0x2C1B,0x0000, 0x2C1C,0x0000, /* A0A4 */ +0x2C1D,0x0000, 0x2C1E,0x0000, 0x2C1F,0x0000, 0x2C20,0x0000, /* A0A8 */ +0x2C21,0x0000, 0x2C22,0x0000, 0x2C23,0x0000, 0x2C24,0x0000, /* A0AC */ +0x2C25,0x0000, 0x2C26,0x0000, 0x2C27,0x0000, 0x2C28,0x0000, /* A0B0 */ +0x2C29,0x0000, 0x2C2A,0x0000, 0x2C2B,0x0000, 0x2C2C,0x0000, /* A0B4 */ +0x2C2D,0x0000, 0x2C2E,0x0000, 0x2C2F,0x0000, 0x2C30,0x0000, /* A0B8 */ +0x2C31,0x0000, 0x2C32,0x0000, 0x2C33,0x0000, 0x2C34,0x0000, /* A0BC */ +0x2C35,0x0000, 0x2C36,0x0000, 0x2C37,0x0000, 0x2C38,0x0000, /* A0C0 */ +0x2C39,0x0000, 0x2C3A,0x0000, 0x2C3B,0x0000, 0x2C3C,0x0000, /* A0C4 */ +0x2C3D,0x0000, 0x2C3E,0x0000, 0x2C3F,0x0000, 0x2C40,0x0000, /* A0C8 */ +0x2C41,0x0000, 0x2C42,0x0000, 0x2C43,0x0000, 0x2C44,0x0000, /* A0CC */ +0x2C45,0x0000, 0x2C46,0x0000, 0x2C47,0x0000, 0x2C48,0x0000, /* A0D0 */ +0x2C49,0x0000, 0x2C4A,0x0000, 0x2C4B,0x0000, 0x2C4C,0x0000, /* A0D4 */ +0x2C4D,0x0000, 0x2C4E,0x0000, 0x2C4F,0x0000, 0x2C50,0x0000, /* A0D8 */ +0x2C51,0x0000, 0x2C52,0x0000, 0x2C53,0x0000, 0x2C54,0x0000, /* A0DC */ +0x2C55,0x0000, 0x2C56,0x0000, 0x2C57,0x0000, 0x2C58,0x0000, /* A0E0 */ +0x2C59,0x0000, 0x2C5A,0x0000, 0x2C5B,0x0000, 0x2C5C,0x0000, /* A0E4 */ +0x2C5D,0x0000, 0x2C5E,0x0000, 0x2C5F,0x0000, 0x2C60,0x0000, /* A0E8 */ +0x2C61,0x0000, 0x2C62,0x0000, 0x2C63,0x0000, 0x2C64,0x0000, /* A0EC */ +0x2C65,0x0000, 0x2C66,0x0000, 0x2C67,0x0000, 0x2C68,0x0000, /* A0F0 */ +0x2C69,0x0000, 0x2C6A,0x0000, 0x2C6B,0x0000, 0x2C6C,0x0000, /* A0F4 */ +0x2C6D,0x0000, 0x2C6E,0x0000, 0x2C6F,0x0000, 0x2C70,0x0000, /* A0F8 */ +0x2C71,0x0000, 0x2C72,0x0000, 0x2C73,0x0000, 0x2C74,0x0000 /* A0FC */ +}; + +uint16 uca520_p0A1[]= { /* A100 (2 weights per char) */ +0x2C75,0x0000, 0x2C76,0x0000, 0x2C77,0x0000, 0x2C78,0x0000, /* A100 */ +0x2C79,0x0000, 0x2C7A,0x0000, 0x2C7B,0x0000, 0x2C7C,0x0000, /* A104 */ +0x2C7D,0x0000, 0x2C7E,0x0000, 0x2C7F,0x0000, 0x2C80,0x0000, /* A108 */ +0x2C81,0x0000, 0x2C82,0x0000, 0x2C83,0x0000, 0x2C84,0x0000, /* A10C */ +0x2C85,0x0000, 0x2C86,0x0000, 0x2C87,0x0000, 0x2C88,0x0000, /* A110 */ +0x2C89,0x0000, 0x2C8A,0x0000, 0x2C8B,0x0000, 0x2C8C,0x0000, /* A114 */ +0x2C8D,0x0000, 0x2C8E,0x0000, 0x2C8F,0x0000, 0x2C90,0x0000, /* A118 */ +0x2C91,0x0000, 0x2C92,0x0000, 0x2C93,0x0000, 0x2C94,0x0000, /* A11C */ +0x2C95,0x0000, 0x2C96,0x0000, 0x2C97,0x0000, 0x2C98,0x0000, /* A120 */ +0x2C99,0x0000, 0x2C9A,0x0000, 0x2C9B,0x0000, 0x2C9C,0x0000, /* A124 */ +0x2C9D,0x0000, 0x2C9E,0x0000, 0x2C9F,0x0000, 0x2CA0,0x0000, /* A128 */ +0x2CA1,0x0000, 0x2CA2,0x0000, 0x2CA3,0x0000, 0x2CA4,0x0000, /* A12C */ +0x2CA5,0x0000, 0x2CA6,0x0000, 0x2CA7,0x0000, 0x2CA8,0x0000, /* A130 */ +0x2CA9,0x0000, 0x2CAA,0x0000, 0x2CAB,0x0000, 0x2CAC,0x0000, /* A134 */ +0x2CAD,0x0000, 0x2CAE,0x0000, 0x2CAF,0x0000, 0x2CB0,0x0000, /* A138 */ +0x2CB1,0x0000, 0x2CB2,0x0000, 0x2CB3,0x0000, 0x2CB4,0x0000, /* A13C */ +0x2CB5,0x0000, 0x2CB6,0x0000, 0x2CB7,0x0000, 0x2CB8,0x0000, /* A140 */ +0x2CB9,0x0000, 0x2CBA,0x0000, 0x2CBB,0x0000, 0x2CBC,0x0000, /* A144 */ +0x2CBD,0x0000, 0x2CBE,0x0000, 0x2CBF,0x0000, 0x2CC0,0x0000, /* A148 */ +0x2CC1,0x0000, 0x2CC2,0x0000, 0x2CC3,0x0000, 0x2CC4,0x0000, /* A14C */ +0x2CC5,0x0000, 0x2CC6,0x0000, 0x2CC7,0x0000, 0x2CC8,0x0000, /* A150 */ +0x2CC9,0x0000, 0x2CCA,0x0000, 0x2CCB,0x0000, 0x2CCC,0x0000, /* A154 */ +0x2CCD,0x0000, 0x2CCE,0x0000, 0x2CCF,0x0000, 0x2CD0,0x0000, /* A158 */ +0x2CD1,0x0000, 0x2CD2,0x0000, 0x2CD3,0x0000, 0x2CD4,0x0000, /* A15C */ +0x2CD5,0x0000, 0x2CD6,0x0000, 0x2CD7,0x0000, 0x2CD8,0x0000, /* A160 */ +0x2CD9,0x0000, 0x2CDA,0x0000, 0x2CDB,0x0000, 0x2CDC,0x0000, /* A164 */ +0x2CDD,0x0000, 0x2CDE,0x0000, 0x2CDF,0x0000, 0x2CE0,0x0000, /* A168 */ +0x2CE1,0x0000, 0x2CE2,0x0000, 0x2CE3,0x0000, 0x2CE4,0x0000, /* A16C */ +0x2CE5,0x0000, 0x2CE6,0x0000, 0x2CE7,0x0000, 0x2CE8,0x0000, /* A170 */ +0x2CE9,0x0000, 0x2CEA,0x0000, 0x2CEB,0x0000, 0x2CEC,0x0000, /* A174 */ +0x2CED,0x0000, 0x2CEE,0x0000, 0x2CEF,0x0000, 0x2CF0,0x0000, /* A178 */ +0x2CF1,0x0000, 0x2CF2,0x0000, 0x2CF3,0x0000, 0x2CF4,0x0000, /* A17C */ +0x2CF5,0x0000, 0x2CF6,0x0000, 0x2CF7,0x0000, 0x2CF8,0x0000, /* A180 */ +0x2CF9,0x0000, 0x2CFA,0x0000, 0x2CFB,0x0000, 0x2CFC,0x0000, /* A184 */ +0x2CFD,0x0000, 0x2CFE,0x0000, 0x2CFF,0x0000, 0x2D00,0x0000, /* A188 */ +0x2D01,0x0000, 0x2D02,0x0000, 0x2D03,0x0000, 0x2D04,0x0000, /* A18C */ +0x2D05,0x0000, 0x2D06,0x0000, 0x2D07,0x0000, 0x2D08,0x0000, /* A190 */ +0x2D09,0x0000, 0x2D0A,0x0000, 0x2D0B,0x0000, 0x2D0C,0x0000, /* A194 */ +0x2D0D,0x0000, 0x2D0E,0x0000, 0x2D0F,0x0000, 0x2D10,0x0000, /* A198 */ +0x2D11,0x0000, 0x2D12,0x0000, 0x2D13,0x0000, 0x2D14,0x0000, /* A19C */ +0x2D15,0x0000, 0x2D16,0x0000, 0x2D17,0x0000, 0x2D18,0x0000, /* A1A0 */ +0x2D19,0x0000, 0x2D1A,0x0000, 0x2D1B,0x0000, 0x2D1C,0x0000, /* A1A4 */ +0x2D1D,0x0000, 0x2D1E,0x0000, 0x2D1F,0x0000, 0x2D20,0x0000, /* A1A8 */ +0x2D21,0x0000, 0x2D22,0x0000, 0x2D23,0x0000, 0x2D24,0x0000, /* A1AC */ +0x2D25,0x0000, 0x2D26,0x0000, 0x2D27,0x0000, 0x2D28,0x0000, /* A1B0 */ +0x2D29,0x0000, 0x2D2A,0x0000, 0x2D2B,0x0000, 0x2D2C,0x0000, /* A1B4 */ +0x2D2D,0x0000, 0x2D2E,0x0000, 0x2D2F,0x0000, 0x2D30,0x0000, /* A1B8 */ +0x2D31,0x0000, 0x2D32,0x0000, 0x2D33,0x0000, 0x2D34,0x0000, /* A1BC */ +0x2D35,0x0000, 0x2D36,0x0000, 0x2D37,0x0000, 0x2D38,0x0000, /* A1C0 */ +0x2D39,0x0000, 0x2D3A,0x0000, 0x2D3B,0x0000, 0x2D3C,0x0000, /* A1C4 */ +0x2D3D,0x0000, 0x2D3E,0x0000, 0x2D3F,0x0000, 0x2D40,0x0000, /* A1C8 */ +0x2D41,0x0000, 0x2D42,0x0000, 0x2D43,0x0000, 0x2D44,0x0000, /* A1CC */ +0x2D45,0x0000, 0x2D46,0x0000, 0x2D47,0x0000, 0x2D48,0x0000, /* A1D0 */ +0x2D49,0x0000, 0x2D4A,0x0000, 0x2D4B,0x0000, 0x2D4C,0x0000, /* A1D4 */ +0x2D4D,0x0000, 0x2D4E,0x0000, 0x2D4F,0x0000, 0x2D50,0x0000, /* A1D8 */ +0x2D51,0x0000, 0x2D52,0x0000, 0x2D53,0x0000, 0x2D54,0x0000, /* A1DC */ +0x2D55,0x0000, 0x2D56,0x0000, 0x2D57,0x0000, 0x2D58,0x0000, /* A1E0 */ +0x2D59,0x0000, 0x2D5A,0x0000, 0x2D5B,0x0000, 0x2D5C,0x0000, /* A1E4 */ +0x2D5D,0x0000, 0x2D5E,0x0000, 0x2D5F,0x0000, 0x2D60,0x0000, /* A1E8 */ +0x2D61,0x0000, 0x2D62,0x0000, 0x2D63,0x0000, 0x2D64,0x0000, /* A1EC */ +0x2D65,0x0000, 0x2D66,0x0000, 0x2D67,0x0000, 0x2D68,0x0000, /* A1F0 */ +0x2D69,0x0000, 0x2D6A,0x0000, 0x2D6B,0x0000, 0x2D6C,0x0000, /* A1F4 */ +0x2D6D,0x0000, 0x2D6E,0x0000, 0x2D6F,0x0000, 0x2D70,0x0000, /* A1F8 */ +0x2D71,0x0000, 0x2D72,0x0000, 0x2D73,0x0000, 0x2D74,0x0000 /* A1FC */ +}; + +uint16 uca520_p0A2[]= { /* A200 (2 weights per char) */ +0x2D75,0x0000, 0x2D76,0x0000, 0x2D77,0x0000, 0x2D78,0x0000, /* A200 */ +0x2D79,0x0000, 0x2D7A,0x0000, 0x2D7B,0x0000, 0x2D7C,0x0000, /* A204 */ +0x2D7D,0x0000, 0x2D7E,0x0000, 0x2D7F,0x0000, 0x2D80,0x0000, /* A208 */ +0x2D81,0x0000, 0x2D82,0x0000, 0x2D83,0x0000, 0x2D84,0x0000, /* A20C */ +0x2D85,0x0000, 0x2D86,0x0000, 0x2D87,0x0000, 0x2D88,0x0000, /* A210 */ +0x2D89,0x0000, 0x2D8A,0x0000, 0x2D8B,0x0000, 0x2D8C,0x0000, /* A214 */ +0x2D8D,0x0000, 0x2D8E,0x0000, 0x2D8F,0x0000, 0x2D90,0x0000, /* A218 */ +0x2D91,0x0000, 0x2D92,0x0000, 0x2D93,0x0000, 0x2D94,0x0000, /* A21C */ +0x2D95,0x0000, 0x2D96,0x0000, 0x2D97,0x0000, 0x2D98,0x0000, /* A220 */ +0x2D99,0x0000, 0x2D9A,0x0000, 0x2D9B,0x0000, 0x2D9C,0x0000, /* A224 */ +0x2D9D,0x0000, 0x2D9E,0x0000, 0x2D9F,0x0000, 0x2DA0,0x0000, /* A228 */ +0x2DA1,0x0000, 0x2DA2,0x0000, 0x2DA3,0x0000, 0x2DA4,0x0000, /* A22C */ +0x2DA5,0x0000, 0x2DA6,0x0000, 0x2DA7,0x0000, 0x2DA8,0x0000, /* A230 */ +0x2DA9,0x0000, 0x2DAA,0x0000, 0x2DAB,0x0000, 0x2DAC,0x0000, /* A234 */ +0x2DAD,0x0000, 0x2DAE,0x0000, 0x2DAF,0x0000, 0x2DB0,0x0000, /* A238 */ +0x2DB1,0x0000, 0x2DB2,0x0000, 0x2DB3,0x0000, 0x2DB4,0x0000, /* A23C */ +0x2DB5,0x0000, 0x2DB6,0x0000, 0x2DB7,0x0000, 0x2DB8,0x0000, /* A240 */ +0x2DB9,0x0000, 0x2DBA,0x0000, 0x2DBB,0x0000, 0x2DBC,0x0000, /* A244 */ +0x2DBD,0x0000, 0x2DBE,0x0000, 0x2DBF,0x0000, 0x2DC0,0x0000, /* A248 */ +0x2DC1,0x0000, 0x2DC2,0x0000, 0x2DC3,0x0000, 0x2DC4,0x0000, /* A24C */ +0x2DC5,0x0000, 0x2DC6,0x0000, 0x2DC7,0x0000, 0x2DC8,0x0000, /* A250 */ +0x2DC9,0x0000, 0x2DCA,0x0000, 0x2DCB,0x0000, 0x2DCC,0x0000, /* A254 */ +0x2DCD,0x0000, 0x2DCE,0x0000, 0x2DCF,0x0000, 0x2DD0,0x0000, /* A258 */ +0x2DD1,0x0000, 0x2DD2,0x0000, 0x2DD3,0x0000, 0x2DD4,0x0000, /* A25C */ +0x2DD5,0x0000, 0x2DD6,0x0000, 0x2DD7,0x0000, 0x2DD8,0x0000, /* A260 */ +0x2DD9,0x0000, 0x2DDA,0x0000, 0x2DDB,0x0000, 0x2DDC,0x0000, /* A264 */ +0x2DDD,0x0000, 0x2DDE,0x0000, 0x2DDF,0x0000, 0x2DE0,0x0000, /* A268 */ +0x2DE1,0x0000, 0x2DE2,0x0000, 0x2DE3,0x0000, 0x2DE4,0x0000, /* A26C */ +0x2DE5,0x0000, 0x2DE6,0x0000, 0x2DE7,0x0000, 0x2DE8,0x0000, /* A270 */ +0x2DE9,0x0000, 0x2DEA,0x0000, 0x2DEB,0x0000, 0x2DEC,0x0000, /* A274 */ +0x2DED,0x0000, 0x2DEE,0x0000, 0x2DEF,0x0000, 0x2DF0,0x0000, /* A278 */ +0x2DF1,0x0000, 0x2DF2,0x0000, 0x2DF3,0x0000, 0x2DF4,0x0000, /* A27C */ +0x2DF5,0x0000, 0x2DF6,0x0000, 0x2DF7,0x0000, 0x2DF8,0x0000, /* A280 */ +0x2DF9,0x0000, 0x2DFA,0x0000, 0x2DFB,0x0000, 0x2DFC,0x0000, /* A284 */ +0x2DFD,0x0000, 0x2DFE,0x0000, 0x2DFF,0x0000, 0x2E00,0x0000, /* A288 */ +0x2E01,0x0000, 0x2E02,0x0000, 0x2E03,0x0000, 0x2E04,0x0000, /* A28C */ +0x2E05,0x0000, 0x2E06,0x0000, 0x2E07,0x0000, 0x2E08,0x0000, /* A290 */ +0x2E09,0x0000, 0x2E0A,0x0000, 0x2E0B,0x0000, 0x2E0C,0x0000, /* A294 */ +0x2E0D,0x0000, 0x2E0E,0x0000, 0x2E0F,0x0000, 0x2E10,0x0000, /* A298 */ +0x2E11,0x0000, 0x2E12,0x0000, 0x2E13,0x0000, 0x2E14,0x0000, /* A29C */ +0x2E15,0x0000, 0x2E16,0x0000, 0x2E17,0x0000, 0x2E18,0x0000, /* A2A0 */ +0x2E19,0x0000, 0x2E1A,0x0000, 0x2E1B,0x0000, 0x2E1C,0x0000, /* A2A4 */ +0x2E1D,0x0000, 0x2E1E,0x0000, 0x2E1F,0x0000, 0x2E20,0x0000, /* A2A8 */ +0x2E21,0x0000, 0x2E22,0x0000, 0x2E23,0x0000, 0x2E24,0x0000, /* A2AC */ +0x2E25,0x0000, 0x2E26,0x0000, 0x2E27,0x0000, 0x2E28,0x0000, /* A2B0 */ +0x2E29,0x0000, 0x2E2A,0x0000, 0x2E2B,0x0000, 0x2E2C,0x0000, /* A2B4 */ +0x2E2D,0x0000, 0x2E2E,0x0000, 0x2E2F,0x0000, 0x2E30,0x0000, /* A2B8 */ +0x2E31,0x0000, 0x2E32,0x0000, 0x2E33,0x0000, 0x2E34,0x0000, /* A2BC */ +0x2E35,0x0000, 0x2E36,0x0000, 0x2E37,0x0000, 0x2E38,0x0000, /* A2C0 */ +0x2E39,0x0000, 0x2E3A,0x0000, 0x2E3B,0x0000, 0x2E3C,0x0000, /* A2C4 */ +0x2E3D,0x0000, 0x2E3E,0x0000, 0x2E3F,0x0000, 0x2E40,0x0000, /* A2C8 */ +0x2E41,0x0000, 0x2E42,0x0000, 0x2E43,0x0000, 0x2E44,0x0000, /* A2CC */ +0x2E45,0x0000, 0x2E46,0x0000, 0x2E47,0x0000, 0x2E48,0x0000, /* A2D0 */ +0x2E49,0x0000, 0x2E4A,0x0000, 0x2E4B,0x0000, 0x2E4C,0x0000, /* A2D4 */ +0x2E4D,0x0000, 0x2E4E,0x0000, 0x2E4F,0x0000, 0x2E50,0x0000, /* A2D8 */ +0x2E51,0x0000, 0x2E52,0x0000, 0x2E53,0x0000, 0x2E54,0x0000, /* A2DC */ +0x2E55,0x0000, 0x2E56,0x0000, 0x2E57,0x0000, 0x2E58,0x0000, /* A2E0 */ +0x2E59,0x0000, 0x2E5A,0x0000, 0x2E5B,0x0000, 0x2E5C,0x0000, /* A2E4 */ +0x2E5D,0x0000, 0x2E5E,0x0000, 0x2E5F,0x0000, 0x2E60,0x0000, /* A2E8 */ +0x2E61,0x0000, 0x2E62,0x0000, 0x2E63,0x0000, 0x2E64,0x0000, /* A2EC */ +0x2E65,0x0000, 0x2E66,0x0000, 0x2E67,0x0000, 0x2E68,0x0000, /* A2F0 */ +0x2E69,0x0000, 0x2E6A,0x0000, 0x2E6B,0x0000, 0x2E6C,0x0000, /* A2F4 */ +0x2E6D,0x0000, 0x2E6E,0x0000, 0x2E6F,0x0000, 0x2E70,0x0000, /* A2F8 */ +0x2E71,0x0000, 0x2E72,0x0000, 0x2E73,0x0000, 0x2E74,0x0000 /* A2FC */ +}; + +uint16 uca520_p0A3[]= { /* A300 (2 weights per char) */ +0x2E75,0x0000, 0x2E76,0x0000, 0x2E77,0x0000, 0x2E78,0x0000, /* A300 */ +0x2E79,0x0000, 0x2E7A,0x0000, 0x2E7B,0x0000, 0x2E7C,0x0000, /* A304 */ +0x2E7D,0x0000, 0x2E7E,0x0000, 0x2E7F,0x0000, 0x2E80,0x0000, /* A308 */ +0x2E81,0x0000, 0x2E82,0x0000, 0x2E83,0x0000, 0x2E84,0x0000, /* A30C */ +0x2E85,0x0000, 0x2E86,0x0000, 0x2E87,0x0000, 0x2E88,0x0000, /* A310 */ +0x2E89,0x0000, 0x2E8A,0x0000, 0x2E8B,0x0000, 0x2E8C,0x0000, /* A314 */ +0x2E8D,0x0000, 0x2E8E,0x0000, 0x2E8F,0x0000, 0x2E90,0x0000, /* A318 */ +0x2E91,0x0000, 0x2E92,0x0000, 0x2E93,0x0000, 0x2E94,0x0000, /* A31C */ +0x2E95,0x0000, 0x2E96,0x0000, 0x2E97,0x0000, 0x2E98,0x0000, /* A320 */ +0x2E99,0x0000, 0x2E9A,0x0000, 0x2E9B,0x0000, 0x2E9C,0x0000, /* A324 */ +0x2E9D,0x0000, 0x2E9E,0x0000, 0x2E9F,0x0000, 0x2EA0,0x0000, /* A328 */ +0x2EA1,0x0000, 0x2EA2,0x0000, 0x2EA3,0x0000, 0x2EA4,0x0000, /* A32C */ +0x2EA5,0x0000, 0x2EA6,0x0000, 0x2EA7,0x0000, 0x2EA8,0x0000, /* A330 */ +0x2EA9,0x0000, 0x2EAA,0x0000, 0x2EAB,0x0000, 0x2EAC,0x0000, /* A334 */ +0x2EAD,0x0000, 0x2EAE,0x0000, 0x2EAF,0x0000, 0x2EB0,0x0000, /* A338 */ +0x2EB1,0x0000, 0x2EB2,0x0000, 0x2EB3,0x0000, 0x2EB4,0x0000, /* A33C */ +0x2EB5,0x0000, 0x2EB6,0x0000, 0x2EB7,0x0000, 0x2EB8,0x0000, /* A340 */ +0x2EB9,0x0000, 0x2EBA,0x0000, 0x2EBB,0x0000, 0x2EBC,0x0000, /* A344 */ +0x2EBD,0x0000, 0x2EBE,0x0000, 0x2EBF,0x0000, 0x2EC0,0x0000, /* A348 */ +0x2EC1,0x0000, 0x2EC2,0x0000, 0x2EC3,0x0000, 0x2EC4,0x0000, /* A34C */ +0x2EC5,0x0000, 0x2EC6,0x0000, 0x2EC7,0x0000, 0x2EC8,0x0000, /* A350 */ +0x2EC9,0x0000, 0x2ECA,0x0000, 0x2ECB,0x0000, 0x2ECC,0x0000, /* A354 */ +0x2ECD,0x0000, 0x2ECE,0x0000, 0x2ECF,0x0000, 0x2ED0,0x0000, /* A358 */ +0x2ED1,0x0000, 0x2ED2,0x0000, 0x2ED3,0x0000, 0x2ED4,0x0000, /* A35C */ +0x2ED5,0x0000, 0x2ED6,0x0000, 0x2ED7,0x0000, 0x2ED8,0x0000, /* A360 */ +0x2ED9,0x0000, 0x2EDA,0x0000, 0x2EDB,0x0000, 0x2EDC,0x0000, /* A364 */ +0x2EDD,0x0000, 0x2EDE,0x0000, 0x2EDF,0x0000, 0x2EE0,0x0000, /* A368 */ +0x2EE1,0x0000, 0x2EE2,0x0000, 0x2EE3,0x0000, 0x2EE4,0x0000, /* A36C */ +0x2EE5,0x0000, 0x2EE6,0x0000, 0x2EE7,0x0000, 0x2EE8,0x0000, /* A370 */ +0x2EE9,0x0000, 0x2EEA,0x0000, 0x2EEB,0x0000, 0x2EEC,0x0000, /* A374 */ +0x2EED,0x0000, 0x2EEE,0x0000, 0x2EEF,0x0000, 0x2EF0,0x0000, /* A378 */ +0x2EF1,0x0000, 0x2EF2,0x0000, 0x2EF3,0x0000, 0x2EF4,0x0000, /* A37C */ +0x2EF5,0x0000, 0x2EF6,0x0000, 0x2EF7,0x0000, 0x2EF8,0x0000, /* A380 */ +0x2EF9,0x0000, 0x2EFA,0x0000, 0x2EFB,0x0000, 0x2EFC,0x0000, /* A384 */ +0x2EFD,0x0000, 0x2EFE,0x0000, 0x2EFF,0x0000, 0x2F00,0x0000, /* A388 */ +0x2F01,0x0000, 0x2F02,0x0000, 0x2F03,0x0000, 0x2F04,0x0000, /* A38C */ +0x2F05,0x0000, 0x2F06,0x0000, 0x2F07,0x0000, 0x2F08,0x0000, /* A390 */ +0x2F09,0x0000, 0x2F0A,0x0000, 0x2F0B,0x0000, 0x2F0C,0x0000, /* A394 */ +0x2F0D,0x0000, 0x2F0E,0x0000, 0x2F0F,0x0000, 0x2F10,0x0000, /* A398 */ +0x2F11,0x0000, 0x2F12,0x0000, 0x2F13,0x0000, 0x2F14,0x0000, /* A39C */ +0x2F15,0x0000, 0x2F16,0x0000, 0x2F17,0x0000, 0x2F18,0x0000, /* A3A0 */ +0x2F19,0x0000, 0x2F1A,0x0000, 0x2F1B,0x0000, 0x2F1C,0x0000, /* A3A4 */ +0x2F1D,0x0000, 0x2F1E,0x0000, 0x2F1F,0x0000, 0x2F20,0x0000, /* A3A8 */ +0x2F21,0x0000, 0x2F22,0x0000, 0x2F23,0x0000, 0x2F24,0x0000, /* A3AC */ +0x2F25,0x0000, 0x2F26,0x0000, 0x2F27,0x0000, 0x2F28,0x0000, /* A3B0 */ +0x2F29,0x0000, 0x2F2A,0x0000, 0x2F2B,0x0000, 0x2F2C,0x0000, /* A3B4 */ +0x2F2D,0x0000, 0x2F2E,0x0000, 0x2F2F,0x0000, 0x2F30,0x0000, /* A3B8 */ +0x2F31,0x0000, 0x2F32,0x0000, 0x2F33,0x0000, 0x2F34,0x0000, /* A3BC */ +0x2F35,0x0000, 0x2F36,0x0000, 0x2F37,0x0000, 0x2F38,0x0000, /* A3C0 */ +0x2F39,0x0000, 0x2F3A,0x0000, 0x2F3B,0x0000, 0x2F3C,0x0000, /* A3C4 */ +0x2F3D,0x0000, 0x2F3E,0x0000, 0x2F3F,0x0000, 0x2F40,0x0000, /* A3C8 */ +0x2F41,0x0000, 0x2F42,0x0000, 0x2F43,0x0000, 0x2F44,0x0000, /* A3CC */ +0x2F45,0x0000, 0x2F46,0x0000, 0x2F47,0x0000, 0x2F48,0x0000, /* A3D0 */ +0x2F49,0x0000, 0x2F4A,0x0000, 0x2F4B,0x0000, 0x2F4C,0x0000, /* A3D4 */ +0x2F4D,0x0000, 0x2F4E,0x0000, 0x2F4F,0x0000, 0x2F50,0x0000, /* A3D8 */ +0x2F51,0x0000, 0x2F52,0x0000, 0x2F53,0x0000, 0x2F54,0x0000, /* A3DC */ +0x2F55,0x0000, 0x2F56,0x0000, 0x2F57,0x0000, 0x2F58,0x0000, /* A3E0 */ +0x2F59,0x0000, 0x2F5A,0x0000, 0x2F5B,0x0000, 0x2F5C,0x0000, /* A3E4 */ +0x2F5D,0x0000, 0x2F5E,0x0000, 0x2F5F,0x0000, 0x2F60,0x0000, /* A3E8 */ +0x2F61,0x0000, 0x2F62,0x0000, 0x2F63,0x0000, 0x2F64,0x0000, /* A3EC */ +0x2F65,0x0000, 0x2F66,0x0000, 0x2F67,0x0000, 0x2F68,0x0000, /* A3F0 */ +0x2F69,0x0000, 0x2F6A,0x0000, 0x2F6B,0x0000, 0x2F6C,0x0000, /* A3F4 */ +0x2F6D,0x0000, 0x2F6E,0x0000, 0x2F6F,0x0000, 0x2F70,0x0000, /* A3F8 */ +0x2F71,0x0000, 0x2F72,0x0000, 0x2F73,0x0000, 0x2F74,0x0000 /* A3FC */ +}; + +uint16 uca520_p0A4[]= { /* A400 (3 weights per char) */ +0x2F75,0x0000,0x0000, 0x2F76,0x0000,0x0000, 0x2F77,0x0000,0x0000, /* A400 */ +0x2F78,0x0000,0x0000, 0x2F79,0x0000,0x0000, 0x2F7A,0x0000,0x0000, /* A403 */ +0x2F7B,0x0000,0x0000, 0x2F7C,0x0000,0x0000, 0x2F7D,0x0000,0x0000, /* A406 */ +0x2F7E,0x0000,0x0000, 0x2F7F,0x0000,0x0000, 0x2F80,0x0000,0x0000, /* A409 */ +0x2F81,0x0000,0x0000, 0x2F82,0x0000,0x0000, 0x2F83,0x0000,0x0000, /* A40C */ +0x2F84,0x0000,0x0000, 0x2F85,0x0000,0x0000, 0x2F86,0x0000,0x0000, /* A40F */ +0x2F87,0x0000,0x0000, 0x2F88,0x0000,0x0000, 0x2F89,0x0000,0x0000, /* A412 */ +0x2F8A,0x0000,0x0000, 0x2F8B,0x0000,0x0000, 0x2F8C,0x0000,0x0000, /* A415 */ +0x2F8D,0x0000,0x0000, 0x2F8E,0x0000,0x0000, 0x2F8F,0x0000,0x0000, /* A418 */ +0x2F90,0x0000,0x0000, 0x2F91,0x0000,0x0000, 0x2F92,0x0000,0x0000, /* A41B */ +0x2F93,0x0000,0x0000, 0x2F94,0x0000,0x0000, 0x2F95,0x0000,0x0000, /* A41E */ +0x2F96,0x0000,0x0000, 0x2F97,0x0000,0x0000, 0x2F98,0x0000,0x0000, /* A421 */ +0x2F99,0x0000,0x0000, 0x2F9A,0x0000,0x0000, 0x2F9B,0x0000,0x0000, /* A424 */ +0x2F9C,0x0000,0x0000, 0x2F9D,0x0000,0x0000, 0x2F9E,0x0000,0x0000, /* A427 */ +0x2F9F,0x0000,0x0000, 0x2FA0,0x0000,0x0000, 0x2FA1,0x0000,0x0000, /* A42A */ +0x2FA2,0x0000,0x0000, 0x2FA3,0x0000,0x0000, 0x2FA4,0x0000,0x0000, /* A42D */ +0x2FA5,0x0000,0x0000, 0x2FA6,0x0000,0x0000, 0x2FA7,0x0000,0x0000, /* A430 */ +0x2FA8,0x0000,0x0000, 0x2FA9,0x0000,0x0000, 0x2FAA,0x0000,0x0000, /* A433 */ +0x2FAB,0x0000,0x0000, 0x2FAC,0x0000,0x0000, 0x2FAD,0x0000,0x0000, /* A436 */ +0x2FAE,0x0000,0x0000, 0x2FAF,0x0000,0x0000, 0x2FB0,0x0000,0x0000, /* A439 */ +0x2FB1,0x0000,0x0000, 0x2FB2,0x0000,0x0000, 0x2FB3,0x0000,0x0000, /* A43C */ +0x2FB4,0x0000,0x0000, 0x2FB5,0x0000,0x0000, 0x2FB6,0x0000,0x0000, /* A43F */ +0x2FB7,0x0000,0x0000, 0x2FB8,0x0000,0x0000, 0x2FB9,0x0000,0x0000, /* A442 */ +0x2FBA,0x0000,0x0000, 0x2FBB,0x0000,0x0000, 0x2FBC,0x0000,0x0000, /* A445 */ +0x2FBD,0x0000,0x0000, 0x2FBE,0x0000,0x0000, 0x2FBF,0x0000,0x0000, /* A448 */ +0x2FC0,0x0000,0x0000, 0x2FC1,0x0000,0x0000, 0x2FC2,0x0000,0x0000, /* A44B */ +0x2FC3,0x0000,0x0000, 0x2FC4,0x0000,0x0000, 0x2FC5,0x0000,0x0000, /* A44E */ +0x2FC6,0x0000,0x0000, 0x2FC7,0x0000,0x0000, 0x2FC8,0x0000,0x0000, /* A451 */ +0x2FC9,0x0000,0x0000, 0x2FCA,0x0000,0x0000, 0x2FCB,0x0000,0x0000, /* A454 */ +0x2FCC,0x0000,0x0000, 0x2FCD,0x0000,0x0000, 0x2FCE,0x0000,0x0000, /* A457 */ +0x2FCF,0x0000,0x0000, 0x2FD0,0x0000,0x0000, 0x2FD1,0x0000,0x0000, /* A45A */ +0x2FD2,0x0000,0x0000, 0x2FD3,0x0000,0x0000, 0x2FD4,0x0000,0x0000, /* A45D */ +0x2FD5,0x0000,0x0000, 0x2FD6,0x0000,0x0000, 0x2FD7,0x0000,0x0000, /* A460 */ +0x2FD8,0x0000,0x0000, 0x2FD9,0x0000,0x0000, 0x2FDA,0x0000,0x0000, /* A463 */ +0x2FDB,0x0000,0x0000, 0x2FDC,0x0000,0x0000, 0x2FDD,0x0000,0x0000, /* A466 */ +0x2FDE,0x0000,0x0000, 0x2FDF,0x0000,0x0000, 0x2FE0,0x0000,0x0000, /* A469 */ +0x2FE1,0x0000,0x0000, 0x2FE2,0x0000,0x0000, 0x2FE3,0x0000,0x0000, /* A46C */ +0x2FE4,0x0000,0x0000, 0x2FE5,0x0000,0x0000, 0x2FE6,0x0000,0x0000, /* A46F */ +0x2FE7,0x0000,0x0000, 0x2FE8,0x0000,0x0000, 0x2FE9,0x0000,0x0000, /* A472 */ +0x2FEA,0x0000,0x0000, 0x2FEB,0x0000,0x0000, 0x2FEC,0x0000,0x0000, /* A475 */ +0x2FED,0x0000,0x0000, 0x2FEE,0x0000,0x0000, 0x2FEF,0x0000,0x0000, /* A478 */ +0x2FF0,0x0000,0x0000, 0x2FF1,0x0000,0x0000, 0x2FF2,0x0000,0x0000, /* A47B */ +0x2FF3,0x0000,0x0000, 0x2FF4,0x0000,0x0000, 0x2FF5,0x0000,0x0000, /* A47E */ +0x2FF6,0x0000,0x0000, 0x2FF7,0x0000,0x0000, 0x2FF8,0x0000,0x0000, /* A481 */ +0x2FF9,0x0000,0x0000, 0x2FFA,0x0000,0x0000, 0x2FFB,0x0000,0x0000, /* A484 */ +0x2FFC,0x0000,0x0000, 0x2FFD,0x0000,0x0000, 0x2FFE,0x0000,0x0000, /* A487 */ +0x2FFF,0x0000,0x0000, 0x3000,0x0000,0x0000, 0x3001,0x0000,0x0000, /* A48A */ +0xFBC1,0xA48D,0x0000, 0xFBC1,0xA48E,0x0000, 0xFBC1,0xA48F,0x0000, /* A48D */ +0x0DD5,0x0000,0x0000, 0x0DD6,0x0000,0x0000, 0x0DD7,0x0000,0x0000, /* A490 */ +0x0DD8,0x0000,0x0000, 0x0DD9,0x0000,0x0000, 0x0DDA,0x0000,0x0000, /* A493 */ +0x0DDB,0x0000,0x0000, 0x0DDC,0x0000,0x0000, 0x0DDD,0x0000,0x0000, /* A496 */ +0x0DDE,0x0000,0x0000, 0x0DDF,0x0000,0x0000, 0x0DE0,0x0000,0x0000, /* A499 */ +0x0DE1,0x0000,0x0000, 0x0DE2,0x0000,0x0000, 0x0DE3,0x0000,0x0000, /* A49C */ +0x0DE4,0x0000,0x0000, 0x0DE5,0x0000,0x0000, 0x0DE6,0x0000,0x0000, /* A49F */ +0x0DE7,0x0000,0x0000, 0x0DE8,0x0000,0x0000, 0x0DE9,0x0000,0x0000, /* A4A2 */ +0x0DEA,0x0000,0x0000, 0x0DEB,0x0000,0x0000, 0x0DEC,0x0000,0x0000, /* A4A5 */ +0x0DED,0x0000,0x0000, 0x0DEE,0x0000,0x0000, 0x0DEF,0x0000,0x0000, /* A4A8 */ +0x0DF0,0x0000,0x0000, 0x0DF1,0x0000,0x0000, 0x0DF2,0x0000,0x0000, /* A4AB */ +0x0DF3,0x0000,0x0000, 0x0DF4,0x0000,0x0000, 0x0DF5,0x0000,0x0000, /* A4AE */ +0x0DF6,0x0000,0x0000, 0x0DF7,0x0000,0x0000, 0x0DF8,0x0000,0x0000, /* A4B1 */ +0x0DF9,0x0000,0x0000, 0x0DFA,0x0000,0x0000, 0x0DFB,0x0000,0x0000, /* A4B4 */ +0x0DFC,0x0000,0x0000, 0x0DFD,0x0000,0x0000, 0x0DFE,0x0000,0x0000, /* A4B7 */ +0x0DFF,0x0000,0x0000, 0x0E00,0x0000,0x0000, 0x0E01,0x0000,0x0000, /* A4BA */ +0x0E02,0x0000,0x0000, 0x0E03,0x0000,0x0000, 0x0E04,0x0000,0x0000, /* A4BD */ +0x0E05,0x0000,0x0000, 0x0E06,0x0000,0x0000, 0x0E07,0x0000,0x0000, /* A4C0 */ +0x0E08,0x0000,0x0000, 0x0E09,0x0000,0x0000, 0x0E0A,0x0000,0x0000, /* A4C3 */ +0x0E0B,0x0000,0x0000, 0xFBC1,0xA4C7,0x0000, 0xFBC1,0xA4C8,0x0000, /* A4C6 */ +0xFBC1,0xA4C9,0x0000, 0xFBC1,0xA4CA,0x0000, 0xFBC1,0xA4CB,0x0000, /* A4C9 */ +0xFBC1,0xA4CC,0x0000, 0xFBC1,0xA4CD,0x0000, 0xFBC1,0xA4CE,0x0000, /* A4CC */ +0xFBC1,0xA4CF,0x0000, 0x3008,0x0000,0x0000, 0x3009,0x0000,0x0000, /* A4CF */ +0x300A,0x0000,0x0000, 0x300B,0x0000,0x0000, 0x300C,0x0000,0x0000, /* A4D2 */ +0x300D,0x0000,0x0000, 0x300E,0x0000,0x0000, 0x300F,0x0000,0x0000, /* A4D5 */ +0x3010,0x0000,0x0000, 0x3011,0x0000,0x0000, 0x3012,0x0000,0x0000, /* A4D8 */ +0x3013,0x0000,0x0000, 0x3014,0x0000,0x0000, 0x3015,0x0000,0x0000, /* A4DB */ +0x3016,0x0000,0x0000, 0x3017,0x0000,0x0000, 0x3018,0x0000,0x0000, /* A4DE */ +0x3019,0x0000,0x0000, 0x301A,0x0000,0x0000, 0x301B,0x0000,0x0000, /* A4E1 */ +0x301C,0x0000,0x0000, 0x301D,0x0000,0x0000, 0x301E,0x0000,0x0000, /* A4E4 */ +0x301F,0x0000,0x0000, 0x3020,0x0000,0x0000, 0x3021,0x0000,0x0000, /* A4E7 */ +0x3024,0x0000,0x0000, 0x3022,0x0000,0x0000, 0x3025,0x0000,0x0000, /* A4EA */ +0x3023,0x0000,0x0000, 0x3026,0x0000,0x0000, 0x3027,0x0000,0x0000, /* A4ED */ +0x3028,0x0000,0x0000, 0x3029,0x0000,0x0000, 0x302A,0x0000,0x0000, /* A4F0 */ +0x302B,0x0000,0x0000, 0x302C,0x0000,0x0000, 0x302D,0x0000,0x0000, /* A4F3 */ +0x302E,0x0000,0x0000, 0x302F,0x0000,0x0000, 0x3002,0x0000,0x0000, /* A4F6 */ +0x3003,0x0000,0x0000, 0x3004,0x0000,0x0000, 0x3005,0x0000,0x0000, /* A4F9 */ +0x3007,0x0000,0x0000, 0x3006,0x0000,0x0000, 0x023D,0x0000,0x0000, /* A4FC */ +0x028E,0x0000,0x0000 }; + +uint16 uca520_p0A5[]= { /* A500 (2 weights per char) */ +0x2853,0x0000, 0x2854,0x0000, 0x2855,0x0000, 0x2856,0x0000, /* A500 */ +0x2857,0x0000, 0x2858,0x0000, 0x2859,0x0000, 0x285A,0x0000, /* A504 */ +0x285B,0x0000, 0x285C,0x0000, 0x285D,0x0000, 0x285E,0x0000, /* A508 */ +0x285F,0x0000, 0x2860,0x0000, 0x2861,0x0000, 0x2862,0x0000, /* A50C */ +0x2863,0x0000, 0x2864,0x0000, 0x2865,0x0000, 0x2866,0x0000, /* A510 */ +0x2867,0x0000, 0x2868,0x0000, 0x2869,0x0000, 0x286A,0x0000, /* A514 */ +0x286B,0x0000, 0x286C,0x0000, 0x286D,0x0000, 0x286E,0x0000, /* A518 */ +0x286F,0x0000, 0x2870,0x0000, 0x2871,0x0000, 0x2872,0x0000, /* A51C */ +0x2873,0x0000, 0x2874,0x0000, 0x2875,0x0000, 0x2876,0x0000, /* A520 */ +0x2877,0x0000, 0x2878,0x0000, 0x2879,0x0000, 0x287A,0x0000, /* A524 */ +0x287B,0x0000, 0x287C,0x0000, 0x287D,0x0000, 0x287E,0x0000, /* A528 */ +0x287F,0x0000, 0x2880,0x0000, 0x2881,0x0000, 0x2882,0x0000, /* A52C */ +0x2883,0x0000, 0x2884,0x0000, 0x2885,0x0000, 0x2886,0x0000, /* A530 */ +0x2887,0x0000, 0x2888,0x0000, 0x2889,0x0000, 0x288A,0x0000, /* A534 */ +0x288B,0x0000, 0x288C,0x0000, 0x288D,0x0000, 0x288E,0x0000, /* A538 */ +0x288F,0x0000, 0x2890,0x0000, 0x2891,0x0000, 0x2892,0x0000, /* A53C */ +0x2893,0x0000, 0x2894,0x0000, 0x2895,0x0000, 0x2896,0x0000, /* A540 */ +0x2897,0x0000, 0x2898,0x0000, 0x2899,0x0000, 0x289A,0x0000, /* A544 */ +0x289B,0x0000, 0x289C,0x0000, 0x289D,0x0000, 0x289E,0x0000, /* A548 */ +0x289F,0x0000, 0x28A0,0x0000, 0x28A1,0x0000, 0x28A2,0x0000, /* A54C */ +0x28A3,0x0000, 0x28A4,0x0000, 0x28A5,0x0000, 0x28A6,0x0000, /* A550 */ +0x28A7,0x0000, 0x28A8,0x0000, 0x28A9,0x0000, 0x28AA,0x0000, /* A554 */ +0x28AB,0x0000, 0x28AC,0x0000, 0x28AD,0x0000, 0x28AE,0x0000, /* A558 */ +0x28AF,0x0000, 0x28B0,0x0000, 0x28B1,0x0000, 0x28B2,0x0000, /* A55C */ +0x28B3,0x0000, 0x28B4,0x0000, 0x28B5,0x0000, 0x28B6,0x0000, /* A560 */ +0x28B7,0x0000, 0x28B8,0x0000, 0x28B9,0x0000, 0x28BA,0x0000, /* A564 */ +0x28BB,0x0000, 0x28BC,0x0000, 0x28BD,0x0000, 0x28BE,0x0000, /* A568 */ +0x28BF,0x0000, 0x28C0,0x0000, 0x28C1,0x0000, 0x28C2,0x0000, /* A56C */ +0x28C3,0x0000, 0x28C4,0x0000, 0x28C5,0x0000, 0x28C6,0x0000, /* A570 */ +0x28C7,0x0000, 0x28C8,0x0000, 0x28C9,0x0000, 0x28CA,0x0000, /* A574 */ +0x28CB,0x0000, 0x28CC,0x0000, 0x28CD,0x0000, 0x28CE,0x0000, /* A578 */ +0x28CF,0x0000, 0x28D0,0x0000, 0x28D1,0x0000, 0x28D2,0x0000, /* A57C */ +0x28D3,0x0000, 0x28D4,0x0000, 0x28D5,0x0000, 0x28D6,0x0000, /* A580 */ +0x28D7,0x0000, 0x28D8,0x0000, 0x28D9,0x0000, 0x28DA,0x0000, /* A584 */ +0x28DB,0x0000, 0x28DC,0x0000, 0x28DD,0x0000, 0x28DE,0x0000, /* A588 */ +0x28DF,0x0000, 0x28E0,0x0000, 0x28E1,0x0000, 0x28E2,0x0000, /* A58C */ +0x28E3,0x0000, 0x28E4,0x0000, 0x28E5,0x0000, 0x28E6,0x0000, /* A590 */ +0x28E7,0x0000, 0x28E8,0x0000, 0x28E9,0x0000, 0x28EA,0x0000, /* A594 */ +0x28EB,0x0000, 0x28EC,0x0000, 0x28ED,0x0000, 0x28EE,0x0000, /* A598 */ +0x28EF,0x0000, 0x28F0,0x0000, 0x28F1,0x0000, 0x28F2,0x0000, /* A59C */ +0x28F3,0x0000, 0x28F4,0x0000, 0x28F5,0x0000, 0x28F6,0x0000, /* A5A0 */ +0x28F7,0x0000, 0x28F8,0x0000, 0x28F9,0x0000, 0x28FA,0x0000, /* A5A4 */ +0x28FB,0x0000, 0x28FC,0x0000, 0x28FD,0x0000, 0x28FE,0x0000, /* A5A8 */ +0x28FF,0x0000, 0x2900,0x0000, 0x2901,0x0000, 0x2902,0x0000, /* A5AC */ +0x2903,0x0000, 0x2904,0x0000, 0x2905,0x0000, 0x2906,0x0000, /* A5B0 */ +0x2907,0x0000, 0x2908,0x0000, 0x2909,0x0000, 0x290A,0x0000, /* A5B4 */ +0x290B,0x0000, 0x290C,0x0000, 0x290D,0x0000, 0x290E,0x0000, /* A5B8 */ +0x290F,0x0000, 0x2910,0x0000, 0x2911,0x0000, 0x2912,0x0000, /* A5BC */ +0x2913,0x0000, 0x2914,0x0000, 0x2915,0x0000, 0x2916,0x0000, /* A5C0 */ +0x2917,0x0000, 0x2918,0x0000, 0x2919,0x0000, 0x291A,0x0000, /* A5C4 */ +0x291B,0x0000, 0x291C,0x0000, 0x291D,0x0000, 0x291E,0x0000, /* A5C8 */ +0x291F,0x0000, 0x2920,0x0000, 0x2921,0x0000, 0x2922,0x0000, /* A5CC */ +0x2923,0x0000, 0x2924,0x0000, 0x2925,0x0000, 0x2926,0x0000, /* A5D0 */ +0x2927,0x0000, 0x2928,0x0000, 0x2929,0x0000, 0x292A,0x0000, /* A5D4 */ +0x292B,0x0000, 0x292C,0x0000, 0x292D,0x0000, 0x292E,0x0000, /* A5D8 */ +0x292F,0x0000, 0x2930,0x0000, 0x2931,0x0000, 0x2932,0x0000, /* A5DC */ +0x2933,0x0000, 0x2934,0x0000, 0x2935,0x0000, 0x2936,0x0000, /* A5E0 */ +0x2937,0x0000, 0x2938,0x0000, 0x2939,0x0000, 0x293A,0x0000, /* A5E4 */ +0x293B,0x0000, 0x293C,0x0000, 0x293D,0x0000, 0x293E,0x0000, /* A5E8 */ +0x293F,0x0000, 0x2940,0x0000, 0x2941,0x0000, 0x2942,0x0000, /* A5EC */ +0x2943,0x0000, 0x2944,0x0000, 0x2945,0x0000, 0x2946,0x0000, /* A5F0 */ +0x2947,0x0000, 0x2948,0x0000, 0x2949,0x0000, 0x294A,0x0000, /* A5F4 */ +0x294B,0x0000, 0x294C,0x0000, 0x294D,0x0000, 0x294E,0x0000, /* A5F8 */ +0x294F,0x0000, 0x2950,0x0000, 0x2951,0x0000, 0x2952,0x0000 /* A5FC */ +}; + +uint16 uca520_p0A6[]= { /* A600 (3 weights per char) */ +0x2953,0x0000,0x0000, 0x2954,0x0000,0x0000, 0x2955,0x0000,0x0000, /* A600 */ +0x2956,0x0000,0x0000, 0x2957,0x0000,0x0000, 0x2958,0x0000,0x0000, /* A603 */ +0x2959,0x0000,0x0000, 0x295A,0x0000,0x0000, 0x295B,0x0000,0x0000, /* A606 */ +0x295C,0x0000,0x0000, 0x295D,0x0000,0x0000, 0x295E,0x0000,0x0000, /* A609 */ +0x295F,0x0000,0x0000, 0x023E,0x0000,0x0000, 0x028F,0x0000,0x0000, /* A60C */ +0x027D,0x0000,0x0000, 0x28AB,0x0000,0x0000, 0x28BD,0x0000,0x0000, /* A60F */ +0x28DA,0x0000,0x0000, 0x285F,0x295E,0x0000, 0x2871,0x295E,0x0000, /* A612 */ +0x2886,0x295E,0x0000, 0x289A,0x295F,0x0000, 0x28A5,0x295E,0x0000, /* A615 */ +0x28AB,0x295F,0x0000, 0x28AD,0x295F,0x0000, 0x28B3,0x295E,0x0000, /* A618 */ +0x28D8,0x295E,0x0000, 0x2907,0x295E,0x0000, 0x291E,0x295E,0x0000, /* A61B */ +0x2924,0x295F,0x0000, 0x292B,0x295E,0x0000, 0x1205,0x0000,0x0000, /* A61E */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* A621 */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* A624 */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* A627 */ +0x28C1,0x0000,0x0000, 0x2924,0x0000,0x0000, 0xFBC1,0xA62C,0x0000, /* A62A */ +0xFBC1,0xA62D,0x0000, 0xFBC1,0xA62E,0x0000, 0xFBC1,0xA62F,0x0000, /* A62D */ +0xFBC1,0xA630,0x0000, 0xFBC1,0xA631,0x0000, 0xFBC1,0xA632,0x0000, /* A630 */ +0xFBC1,0xA633,0x0000, 0xFBC1,0xA634,0x0000, 0xFBC1,0xA635,0x0000, /* A633 */ +0xFBC1,0xA636,0x0000, 0xFBC1,0xA637,0x0000, 0xFBC1,0xA638,0x0000, /* A636 */ +0xFBC1,0xA639,0x0000, 0xFBC1,0xA63A,0x0000, 0xFBC1,0xA63B,0x0000, /* A639 */ +0xFBC1,0xA63C,0x0000, 0xFBC1,0xA63D,0x0000, 0xFBC1,0xA63E,0x0000, /* A63C */ +0xFBC1,0xA63F,0x0000, 0x1611,0x0000,0x0000, 0x1611,0x0000,0x0000, /* A63F */ +0x1618,0x0000,0x0000, 0x1618,0x0000,0x0000, 0x161D,0x0000,0x0000, /* A642 */ +0x161D,0x0000,0x0000, 0x1635,0x0000,0x0000, 0x1635,0x0000,0x0000, /* A645 */ +0x1642,0x0000,0x0000, 0x1642,0x0000,0x0000, 0x16EC,0x0000,0x0000, /* A648 */ +0x16EC,0x0000,0x0000, 0x1712,0x0000,0x0000, 0x1712,0x0000,0x0000, /* A64B */ +0x1750,0x0000,0x0000, 0x1750,0x0000,0x0000, 0x1757,0x0000,0x0000, /* A64E */ +0x1757,0x0000,0x0000, 0x176C,0x0000,0x0000, 0x176C,0x0000,0x0000, /* A651 */ +0x1779,0x0000,0x0000, 0x1779,0x0000,0x0000, 0x177A,0x0000,0x0000, /* A654 */ +0x177A,0x0000,0x0000, 0x1788,0x0000,0x0000, 0x1788,0x0000,0x0000, /* A657 */ +0x178D,0x0000,0x0000, 0x178D,0x0000,0x0000, 0x1792,0x0000,0x0000, /* A65A */ +0x1792,0x0000,0x0000, 0x17AB,0x0000,0x0000, 0x17AB,0x0000,0x0000, /* A65D */ +0xFBC1,0xA660,0x0000, 0xFBC1,0xA661,0x0000, 0x15EA,0x0000,0x0000, /* A660 */ +0x15EA,0x0000,0x0000, 0x166C,0x0000,0x0000, 0x166C,0x0000,0x0000, /* A663 */ +0x1677,0x0000,0x0000, 0x1677,0x0000,0x0000, 0x1692,0x0000,0x0000, /* A666 */ +0x1692,0x0000,0x0000, 0x1692,0x0000,0x0000, 0x1692,0x0000,0x0000, /* A669 */ +0x1692,0x0000,0x0000, 0x1692,0x0000,0x0000, 0x1692,0x0000,0x0000, /* A66C */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* A66F */ +0x0000,0x0000,0x0000, 0x035B,0x0000,0x0000, 0xFBC1,0xA674,0x0000, /* A672 */ +0xFBC1,0xA675,0x0000, 0xFBC1,0xA676,0x0000, 0xFBC1,0xA677,0x0000, /* A675 */ +0xFBC1,0xA678,0x0000, 0xFBC1,0xA679,0x0000, 0xFBC1,0xA67A,0x0000, /* A678 */ +0xFBC1,0xA67B,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* A67B */ +0x0391,0x0000,0x0000, 0x1752,0x0000,0x0000, 0x15E5,0x0000,0x0000, /* A67E */ +0x15E5,0x0000,0x0000, 0x1624,0x0000,0x0000, 0x1624,0x0000,0x0000, /* A681 */ +0x1604,0x0000,0x0000, 0x1604,0x0000,0x0000, 0x173A,0x0000,0x0000, /* A684 */ +0x173A,0x0000,0x0000, 0x1622,0x0000,0x0000, 0x1622,0x0000,0x0000, /* A687 */ +0x16CB,0x0000,0x0000, 0x16CB,0x0000,0x0000, 0x16C5,0x0000,0x0000, /* A68A */ +0x16C5,0x0000,0x0000, 0x171F,0x0000,0x0000, 0x171F,0x0000,0x0000, /* A68D */ +0x1724,0x0000,0x0000, 0x1724,0x0000,0x0000, 0x1729,0x0000,0x0000, /* A690 */ +0x1729,0x0000,0x0000, 0x1709,0x0000,0x0000, 0x1709,0x0000,0x0000, /* A693 */ +0x174B,0x0000,0x0000, 0x174B,0x0000,0x0000, 0xFBC1,0xA698,0x0000, /* A696 */ +0xFBC1,0xA699,0x0000, 0xFBC1,0xA69A,0x0000, 0xFBC1,0xA69B,0x0000, /* A699 */ +0xFBC1,0xA69C,0x0000, 0xFBC1,0xA69D,0x0000, 0xFBC1,0xA69E,0x0000, /* A69C */ +0xFBC1,0xA69F,0x0000, 0x2960,0x0000,0x0000, 0x2961,0x0000,0x0000, /* A69F */ +0x2962,0x0000,0x0000, 0x2963,0x0000,0x0000, 0x2964,0x0000,0x0000, /* A6A2 */ +0x2965,0x0000,0x0000, 0x2966,0x0000,0x0000, 0x2967,0x0000,0x0000, /* A6A5 */ +0x2968,0x0000,0x0000, 0x2969,0x0000,0x0000, 0x296A,0x0000,0x0000, /* A6A8 */ +0x296B,0x0000,0x0000, 0x296C,0x0000,0x0000, 0x296D,0x0000,0x0000, /* A6AB */ +0x296E,0x0000,0x0000, 0x296F,0x0000,0x0000, 0x2970,0x0000,0x0000, /* A6AE */ +0x2971,0x0000,0x0000, 0x2972,0x0000,0x0000, 0x2973,0x0000,0x0000, /* A6B1 */ +0x2974,0x0000,0x0000, 0x2975,0x0000,0x0000, 0x2976,0x0000,0x0000, /* A6B4 */ +0x2977,0x0000,0x0000, 0x2978,0x0000,0x0000, 0x2979,0x0000,0x0000, /* A6B7 */ +0x297A,0x0000,0x0000, 0x297B,0x0000,0x0000, 0x297C,0x0000,0x0000, /* A6BA */ +0x297D,0x0000,0x0000, 0x297E,0x0000,0x0000, 0x297F,0x0000,0x0000, /* A6BD */ +0x2980,0x0000,0x0000, 0x2981,0x0000,0x0000, 0x2982,0x0000,0x0000, /* A6C0 */ +0x2983,0x0000,0x0000, 0x2984,0x0000,0x0000, 0x2985,0x0000,0x0000, /* A6C3 */ +0x2986,0x0000,0x0000, 0x2987,0x0000,0x0000, 0x2988,0x0000,0x0000, /* A6C6 */ +0x2989,0x0000,0x0000, 0x298A,0x0000,0x0000, 0x298B,0x0000,0x0000, /* A6C9 */ +0x298C,0x0000,0x0000, 0x298D,0x0000,0x0000, 0x298E,0x0000,0x0000, /* A6CC */ +0x298F,0x0000,0x0000, 0x2990,0x0000,0x0000, 0x2991,0x0000,0x0000, /* A6CF */ +0x2992,0x0000,0x0000, 0x2993,0x0000,0x0000, 0x2994,0x0000,0x0000, /* A6D2 */ +0x2995,0x0000,0x0000, 0x2996,0x0000,0x0000, 0x2997,0x0000,0x0000, /* A6D5 */ +0x2998,0x0000,0x0000, 0x2999,0x0000,0x0000, 0x299A,0x0000,0x0000, /* A6D8 */ +0x299B,0x0000,0x0000, 0x299C,0x0000,0x0000, 0x299D,0x0000,0x0000, /* A6DB */ +0x299E,0x0000,0x0000, 0x299F,0x0000,0x0000, 0x29A0,0x0000,0x0000, /* A6DE */ +0x29A1,0x0000,0x0000, 0x29A2,0x0000,0x0000, 0x29A3,0x0000,0x0000, /* A6E1 */ +0x29A4,0x0000,0x0000, 0x29A5,0x0000,0x0000, 0x29A6,0x0000,0x0000, /* A6E4 */ +0x29A7,0x0000,0x0000, 0x29A8,0x0000,0x0000, 0x29A9,0x0000,0x0000, /* A6E7 */ +0x29AA,0x0000,0x0000, 0x29AB,0x0000,0x0000, 0x29AC,0x0000,0x0000, /* A6EA */ +0x29AD,0x0000,0x0000, 0x29AE,0x0000,0x0000, 0x29AF,0x0000,0x0000, /* A6ED */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x02C8,0x0000,0x0000, /* A6F0 */ +0x0290,0x0000,0x0000, 0x026D,0x0000,0x0000, 0x023F,0x0000,0x0000, /* A6F3 */ +0x0246,0x0000,0x0000, 0x027E,0x0000,0x0000, 0xFBC1,0xA6F8,0x0000, /* A6F6 */ +0xFBC1,0xA6F9,0x0000, 0xFBC1,0xA6FA,0x0000, 0xFBC1,0xA6FB,0x0000, /* A6F9 */ +0xFBC1,0xA6FC,0x0000, 0xFBC1,0xA6FD,0x0000, 0xFBC1,0xA6FE,0x0000, /* A6FC */ +0xFBC1,0xA6FF,0x0000 }; + +uint16 uca520_p0A7[]= { /* A700 (3 weights per char) */ +0x0426,0x0000,0x0000, 0x0427,0x0000,0x0000, 0x0428,0x0000,0x0000, /* A700 */ +0x0429,0x0000,0x0000, 0x042A,0x0000,0x0000, 0x042B,0x0000,0x0000, /* A703 */ +0x042C,0x0000,0x0000, 0x042D,0x0000,0x0000, 0x042E,0x0000,0x0000, /* A706 */ +0x042F,0x0000,0x0000, 0x0430,0x0000,0x0000, 0x0431,0x0000,0x0000, /* A709 */ +0x0432,0x0000,0x0000, 0x0433,0x0000,0x0000, 0x0434,0x0000,0x0000, /* A70C */ +0x0435,0x0000,0x0000, 0x0436,0x0000,0x0000, 0x0437,0x0000,0x0000, /* A70F */ +0x0438,0x0000,0x0000, 0x0439,0x0000,0x0000, 0x043A,0x0000,0x0000, /* A712 */ +0x043B,0x0000,0x0000, 0x043C,0x0000,0x0000, 0x043D,0x0000,0x0000, /* A715 */ +0x043E,0x0000,0x0000, 0x043F,0x0000,0x0000, 0x0440,0x0000,0x0000, /* A718 */ +0x0441,0x0000,0x0000, 0x0442,0x0000,0x0000, 0x0443,0x0000,0x0000, /* A71B */ +0x0444,0x0000,0x0000, 0x0445,0x0000,0x0000, 0x0446,0x0000,0x0000, /* A71E */ +0x0447,0x0000,0x0000, 0x150E,0x0000,0x0000, 0x150E,0x0000,0x0000, /* A721 */ +0x1518,0x0000,0x0000, 0x1518,0x0000,0x0000, 0x12E5,0x0000,0x0000, /* A724 */ +0x12E5,0x0000,0x0000, 0x1433,0x14AD,0x0000, 0x1433,0x14AD,0x0000, /* A727 */ +0x14F3,0x0000,0x0000, 0x14F3,0x0000,0x0000, 0x14F4,0x0000,0x0000, /* A72A */ +0x14F4,0x0000,0x0000, 0x14F5,0x0000,0x0000, 0x14F5,0x0000,0x0000, /* A72D */ +0x12A7,0x0000,0x0000, 0x1414,0x0000,0x0000, 0x120F,0x120F,0x0000, /* A730 */ +0x120F,0x120F,0x0000, 0x120F,0x138E,0x0000, 0x120F,0x138E,0x0000, /* A733 */ +0x120F,0x1453,0x0000, 0x120F,0x1453,0x0000, 0x120F,0x147B,0x0000, /* A736 */ +0x120F,0x147B,0x0000, 0x120F,0x147B,0x0000, 0x120F,0x147B,0x0000, /* A739 */ +0x120F,0x149C,0x0000, 0x120F,0x149C,0x0000, 0x124F,0x0000,0x0000, /* A73C */ +0x124F,0x0000,0x0000, 0x1329,0x0000,0x0000, 0x1329,0x0000,0x0000, /* A73F */ +0x132A,0x0000,0x0000, 0x132A,0x0000,0x0000, 0x132B,0x0000,0x0000, /* A742 */ +0x132B,0x0000,0x0000, 0x1338,0x0000,0x0000, 0x1338,0x0000,0x0000, /* A745 */ +0x133A,0x0000,0x0000, 0x133A,0x0000,0x0000, 0x13A9,0x0000,0x0000, /* A748 */ +0x13A9,0x0000,0x0000, 0x13A1,0x0000,0x0000, 0x13A1,0x0000,0x0000, /* A74B */ +0x138E,0x138E,0x0000, 0x138E,0x138E,0x0000, 0x13B9,0x0000,0x0000, /* A74E */ +0x13B9,0x0000,0x0000, 0x13C0,0x0000,0x0000, 0x13C0,0x0000,0x0000, /* A751 */ +0x13C1,0x0000,0x0000, 0x13C1,0x0000,0x0000, 0x13CC,0x0000,0x0000, /* A754 */ +0x13CC,0x0000,0x0000, 0x13CD,0x0000,0x0000, 0x13CD,0x0000,0x0000, /* A757 */ +0x13E2,0x0000,0x0000, 0x13E2,0x0000,0x0000, 0x140F,0x0000,0x0000, /* A75A */ +0x140F,0x0000,0x0000, 0x1480,0x0000,0x0000, 0x1480,0x0000,0x0000, /* A75D */ +0x147B,0x149C,0x0000, 0x147B,0x149C,0x0000, 0x14C9,0x0000,0x0000, /* A760 */ +0x14C9,0x0000,0x0000, 0x14E4,0x0000,0x0000, 0x14E4,0x0000,0x0000, /* A763 */ +0x14E5,0x0000,0x0000, 0x14E5,0x0000,0x0000, 0x14EA,0x0000,0x0000, /* A766 */ +0x14EA,0x0000,0x0000, 0x14EB,0x0000,0x0000, 0x14EB,0x0000,0x0000, /* A769 */ +0x14EC,0x0000,0x0000, 0x14EC,0x0000,0x0000, 0x14ED,0x0000,0x0000, /* A76C */ +0x14ED,0x0000,0x0000, 0x14ED,0x0000,0x0000, 0x1269,0x0000,0x0000, /* A76F */ +0x1351,0x0000,0x0000, 0x136C,0x0000,0x0000, 0x1389,0x0000,0x0000, /* A772 */ +0x140D,0x0000,0x0000, 0x140E,0x0000,0x0000, 0x144E,0x0000,0x0000, /* A775 */ +0x14EE,0x0000,0x0000, 0x1250,0x0000,0x0000, 0x1250,0x0000,0x0000, /* A778 */ +0x12A3,0x0000,0x0000, 0x12A3,0x0000,0x0000, 0x12B0,0x0000,0x0000, /* A77B */ +0x12CA,0x0000,0x0000, 0x12CA,0x0000,0x0000, 0x1356,0x0000,0x0000, /* A77E */ +0x1356,0x0000,0x0000, 0x13DA,0x0000,0x0000, 0x13DA,0x0000,0x0000, /* A781 */ +0x1410,0x0000,0x0000, 0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, /* A784 */ +0x1433,0x0000,0x0000, 0x0448,0x0000,0x0000, 0x0449,0x0000,0x0000, /* A787 */ +0x044A,0x0000,0x0000, 0x150F,0x0000,0x0000, 0x150F,0x0000,0x0000, /* A78A */ +0xFBC1,0xA78D,0x0000, 0xFBC1,0xA78E,0x0000, 0xFBC1,0xA78F,0x0000, /* A78D */ +0xFBC1,0xA790,0x0000, 0xFBC1,0xA791,0x0000, 0xFBC1,0xA792,0x0000, /* A790 */ +0xFBC1,0xA793,0x0000, 0xFBC1,0xA794,0x0000, 0xFBC1,0xA795,0x0000, /* A793 */ +0xFBC1,0xA796,0x0000, 0xFBC1,0xA797,0x0000, 0xFBC1,0xA798,0x0000, /* A796 */ +0xFBC1,0xA799,0x0000, 0xFBC1,0xA79A,0x0000, 0xFBC1,0xA79B,0x0000, /* A799 */ +0xFBC1,0xA79C,0x0000, 0xFBC1,0xA79D,0x0000, 0xFBC1,0xA79E,0x0000, /* A79C */ +0xFBC1,0xA79F,0x0000, 0xFBC1,0xA7A0,0x0000, 0xFBC1,0xA7A1,0x0000, /* A79F */ +0xFBC1,0xA7A2,0x0000, 0xFBC1,0xA7A3,0x0000, 0xFBC1,0xA7A4,0x0000, /* A7A2 */ +0xFBC1,0xA7A5,0x0000, 0xFBC1,0xA7A6,0x0000, 0xFBC1,0xA7A7,0x0000, /* A7A5 */ +0xFBC1,0xA7A8,0x0000, 0xFBC1,0xA7A9,0x0000, 0xFBC1,0xA7AA,0x0000, /* A7A8 */ +0xFBC1,0xA7AB,0x0000, 0xFBC1,0xA7AC,0x0000, 0xFBC1,0xA7AD,0x0000, /* A7AB */ +0xFBC1,0xA7AE,0x0000, 0xFBC1,0xA7AF,0x0000, 0xFBC1,0xA7B0,0x0000, /* A7AE */ +0xFBC1,0xA7B1,0x0000, 0xFBC1,0xA7B2,0x0000, 0xFBC1,0xA7B3,0x0000, /* A7B1 */ +0xFBC1,0xA7B4,0x0000, 0xFBC1,0xA7B5,0x0000, 0xFBC1,0xA7B6,0x0000, /* A7B4 */ +0xFBC1,0xA7B7,0x0000, 0xFBC1,0xA7B8,0x0000, 0xFBC1,0xA7B9,0x0000, /* A7B7 */ +0xFBC1,0xA7BA,0x0000, 0xFBC1,0xA7BB,0x0000, 0xFBC1,0xA7BC,0x0000, /* A7BA */ +0xFBC1,0xA7BD,0x0000, 0xFBC1,0xA7BE,0x0000, 0xFBC1,0xA7BF,0x0000, /* A7BD */ +0xFBC1,0xA7C0,0x0000, 0xFBC1,0xA7C1,0x0000, 0xFBC1,0xA7C2,0x0000, /* A7C0 */ +0xFBC1,0xA7C3,0x0000, 0xFBC1,0xA7C4,0x0000, 0xFBC1,0xA7C5,0x0000, /* A7C3 */ +0xFBC1,0xA7C6,0x0000, 0xFBC1,0xA7C7,0x0000, 0xFBC1,0xA7C8,0x0000, /* A7C6 */ +0xFBC1,0xA7C9,0x0000, 0xFBC1,0xA7CA,0x0000, 0xFBC1,0xA7CB,0x0000, /* A7C9 */ +0xFBC1,0xA7CC,0x0000, 0xFBC1,0xA7CD,0x0000, 0xFBC1,0xA7CE,0x0000, /* A7CC */ +0xFBC1,0xA7CF,0x0000, 0xFBC1,0xA7D0,0x0000, 0xFBC1,0xA7D1,0x0000, /* A7CF */ +0xFBC1,0xA7D2,0x0000, 0xFBC1,0xA7D3,0x0000, 0xFBC1,0xA7D4,0x0000, /* A7D2 */ +0xFBC1,0xA7D5,0x0000, 0xFBC1,0xA7D6,0x0000, 0xFBC1,0xA7D7,0x0000, /* A7D5 */ +0xFBC1,0xA7D8,0x0000, 0xFBC1,0xA7D9,0x0000, 0xFBC1,0xA7DA,0x0000, /* A7D8 */ +0xFBC1,0xA7DB,0x0000, 0xFBC1,0xA7DC,0x0000, 0xFBC1,0xA7DD,0x0000, /* A7DB */ +0xFBC1,0xA7DE,0x0000, 0xFBC1,0xA7DF,0x0000, 0xFBC1,0xA7E0,0x0000, /* A7DE */ +0xFBC1,0xA7E1,0x0000, 0xFBC1,0xA7E2,0x0000, 0xFBC1,0xA7E3,0x0000, /* A7E1 */ +0xFBC1,0xA7E4,0x0000, 0xFBC1,0xA7E5,0x0000, 0xFBC1,0xA7E6,0x0000, /* A7E4 */ +0xFBC1,0xA7E7,0x0000, 0xFBC1,0xA7E8,0x0000, 0xFBC1,0xA7E9,0x0000, /* A7E7 */ +0xFBC1,0xA7EA,0x0000, 0xFBC1,0xA7EB,0x0000, 0xFBC1,0xA7EC,0x0000, /* A7EA */ +0xFBC1,0xA7ED,0x0000, 0xFBC1,0xA7EE,0x0000, 0xFBC1,0xA7EF,0x0000, /* A7ED */ +0xFBC1,0xA7F0,0x0000, 0xFBC1,0xA7F1,0x0000, 0xFBC1,0xA7F2,0x0000, /* A7F0 */ +0xFBC1,0xA7F3,0x0000, 0xFBC1,0xA7F4,0x0000, 0xFBC1,0xA7F5,0x0000, /* A7F3 */ +0xFBC1,0xA7F6,0x0000, 0xFBC1,0xA7F7,0x0000, 0xFBC1,0xA7F8,0x0000, /* A7F6 */ +0xFBC1,0xA7F9,0x0000, 0xFBC1,0xA7FA,0x0000, 0x12AF,0x0000,0x0000, /* A7F9 */ +0x13C2,0x0000,0x0000, 0x136A,0x0000,0x0000, 0x12F8,0x0000,0x0000, /* A7FC */ +0x136B,0x0000,0x0000 }; + +uint16 uca520_p0A8[]= { /* A800 (3 weights per char) */ +0x1E7E,0x0000,0x0000, 0x1E7F,0x0000,0x0000, 0x1E80,0x0000,0x0000, /* A800 */ +0x1E81,0x0000,0x0000, 0x1E82,0x0000,0x0000, 0x1E83,0x0000,0x0000, /* A803 */ +0x1E84,0x0000,0x0000, 0x1E85,0x0000,0x0000, 0x1E86,0x0000,0x0000, /* A806 */ +0x1E87,0x0000,0x0000, 0x1E88,0x0000,0x0000, 0x0000,0x0000,0x0000, /* A809 */ +0x1E89,0x0000,0x0000, 0x1E8A,0x0000,0x0000, 0x1E8B,0x0000,0x0000, /* A80C */ +0x1E8C,0x0000,0x0000, 0x1E8D,0x0000,0x0000, 0x1E8E,0x0000,0x0000, /* A80F */ +0x1E8F,0x0000,0x0000, 0x1E90,0x0000,0x0000, 0x1E91,0x0000,0x0000, /* A812 */ +0x1E92,0x0000,0x0000, 0x1E93,0x0000,0x0000, 0x1E94,0x0000,0x0000, /* A815 */ +0x1E95,0x0000,0x0000, 0x1E96,0x0000,0x0000, 0x1E97,0x0000,0x0000, /* A818 */ +0x1E98,0x0000,0x0000, 0x1E99,0x0000,0x0000, 0x1E9A,0x0000,0x0000, /* A81B */ +0x1E9B,0x0000,0x0000, 0x1E9C,0x0000,0x0000, 0x1E9D,0x0000,0x0000, /* A81E */ +0x1E9E,0x0000,0x0000, 0x1E9F,0x0000,0x0000, 0x1EA0,0x0000,0x0000, /* A821 */ +0x1EA1,0x0000,0x0000, 0x1EA2,0x0000,0x0000, 0x1EA3,0x0000,0x0000, /* A824 */ +0x1EA4,0x0000,0x0000, 0x0460,0x0000,0x0000, 0x0461,0x0000,0x0000, /* A827 */ +0x0462,0x0000,0x0000, 0x0463,0x0000,0x0000, 0xFBC1,0xA82C,0x0000, /* A82A */ +0xFBC1,0xA82D,0x0000, 0xFBC1,0xA82E,0x0000, 0xFBC1,0xA82F,0x0000, /* A82D */ +0x1116,0x0000,0x0000, 0x1117,0x0000,0x0000, 0x1118,0x0000,0x0000, /* A830 */ +0x1119,0x0000,0x0000, 0x111A,0x0000,0x0000, 0x111B,0x0000,0x0000, /* A833 */ +0x0464,0x0000,0x0000, 0x0465,0x0000,0x0000, 0x11E9,0x0000,0x0000, /* A836 */ +0x0466,0x0000,0x0000, 0xFBC1,0xA83A,0x0000, 0xFBC1,0xA83B,0x0000, /* A839 */ +0xFBC1,0xA83C,0x0000, 0xFBC1,0xA83D,0x0000, 0xFBC1,0xA83E,0x0000, /* A83C */ +0xFBC1,0xA83F,0x0000, 0x20B7,0x0000,0x0000, 0x20B8,0x0000,0x0000, /* A83F */ +0x20B9,0x0000,0x0000, 0x20BA,0x0000,0x0000, 0x20BB,0x0000,0x0000, /* A842 */ +0x20BC,0x0000,0x0000, 0x20BD,0x0000,0x0000, 0x20BE,0x0000,0x0000, /* A845 */ +0x20C3,0x0000,0x0000, 0x20C4,0x0000,0x0000, 0x20C5,0x0000,0x0000, /* A848 */ +0x20C6,0x0000,0x0000, 0x20C7,0x0000,0x0000, 0x20C8,0x0000,0x0000, /* A84B */ +0x20C9,0x0000,0x0000, 0x20CA,0x0000,0x0000, 0x20CB,0x0000,0x0000, /* A84E */ +0x20CC,0x0000,0x0000, 0x20CD,0x0000,0x0000, 0x20CE,0x0000,0x0000, /* A851 */ +0x20D0,0x0000,0x0000, 0x20D1,0x0000,0x0000, 0x20D2,0x0000,0x0000, /* A854 */ +0x20D3,0x0000,0x0000, 0x20D6,0x0000,0x0000, 0x20D9,0x0000,0x0000, /* A857 */ +0x20DA,0x0000,0x0000, 0x20DC,0x0000,0x0000, 0x20DD,0x0000,0x0000, /* A85A */ +0x20E0,0x0000,0x0000, 0x20E5,0x0000,0x0000, 0x20E6,0x0000,0x0000, /* A85D */ +0x20E7,0x0000,0x0000, 0x20E8,0x0000,0x0000, 0x20E1,0x0000,0x0000, /* A860 */ +0x20E2,0x0000,0x0000, 0x20E3,0x0000,0x0000, 0x20E4,0x0000,0x0000, /* A863 */ +0x20E9,0x0000,0x0000, 0x20CF,0x0000,0x0000, 0x20D4,0x0000,0x0000, /* A866 */ +0x20BF,0x0000,0x0000, 0x20C0,0x0000,0x0000, 0x20C1,0x0000,0x0000, /* A869 */ +0x20C2,0x0000,0x0000, 0x20D5,0x0000,0x0000, 0x20DB,0x0000,0x0000, /* A86C */ +0x20DE,0x0000,0x0000, 0x20DF,0x0000,0x0000, 0x20D7,0x0000,0x0000, /* A86F */ +0x20D8,0x0000,0x0000, 0x20EA,0x0000,0x0000, 0x03D9,0x0000,0x0000, /* A872 */ +0x03DA,0x0000,0x0000, 0x029A,0x0000,0x0000, 0x029B,0x0000,0x0000, /* A875 */ +0xFBC1,0xA878,0x0000, 0xFBC1,0xA879,0x0000, 0xFBC1,0xA87A,0x0000, /* A878 */ +0xFBC1,0xA87B,0x0000, 0xFBC1,0xA87C,0x0000, 0xFBC1,0xA87D,0x0000, /* A87B */ +0xFBC1,0xA87E,0x0000, 0xFBC1,0xA87F,0x0000, 0x0000,0x0000,0x0000, /* A87E */ +0x0000,0x0000,0x0000, 0x1EA5,0x0000,0x0000, 0x1EA6,0x0000,0x0000, /* A881 */ +0x1EA7,0x0000,0x0000, 0x1EA8,0x0000,0x0000, 0x1EA9,0x0000,0x0000, /* A884 */ +0x1EAA,0x0000,0x0000, 0x1EAB,0x0000,0x0000, 0x1EAC,0x0000,0x0000, /* A887 */ +0x1EAD,0x0000,0x0000, 0x1EAE,0x0000,0x0000, 0x1EAF,0x0000,0x0000, /* A88A */ +0x1EB0,0x0000,0x0000, 0x1EB1,0x0000,0x0000, 0x1EB2,0x0000,0x0000, /* A88D */ +0x1EB3,0x0000,0x0000, 0x1EB4,0x0000,0x0000, 0x1EB5,0x0000,0x0000, /* A890 */ +0x1EB6,0x0000,0x0000, 0x1EB7,0x0000,0x0000, 0x1EB8,0x0000,0x0000, /* A893 */ +0x1EB9,0x0000,0x0000, 0x1EBA,0x0000,0x0000, 0x1EBB,0x0000,0x0000, /* A896 */ +0x1EBC,0x0000,0x0000, 0x1EBD,0x0000,0x0000, 0x1EBE,0x0000,0x0000, /* A899 */ +0x1EBF,0x0000,0x0000, 0x1EC0,0x0000,0x0000, 0x1EC1,0x0000,0x0000, /* A89C */ +0x1EC2,0x0000,0x0000, 0x1EC3,0x0000,0x0000, 0x1EC4,0x0000,0x0000, /* A89F */ +0x1EC5,0x0000,0x0000, 0x1EC6,0x0000,0x0000, 0x1EC7,0x0000,0x0000, /* A8A2 */ +0x1EC8,0x0000,0x0000, 0x1EC9,0x0000,0x0000, 0x1ECA,0x0000,0x0000, /* A8A5 */ +0x1ECB,0x0000,0x0000, 0x1ECC,0x0000,0x0000, 0x1ECD,0x0000,0x0000, /* A8A8 */ +0x1ECE,0x0000,0x0000, 0x1ECF,0x0000,0x0000, 0x1ED0,0x0000,0x0000, /* A8AB */ +0x1ED1,0x0000,0x0000, 0x1ED2,0x0000,0x0000, 0x1ED3,0x0000,0x0000, /* A8AE */ +0x1ED4,0x0000,0x0000, 0x1ED5,0x0000,0x0000, 0x1ED6,0x0000,0x0000, /* A8B1 */ +0x1ED7,0x0000,0x0000, 0x1ED8,0x0000,0x0000, 0x1ED9,0x0000,0x0000, /* A8B4 */ +0x1EDA,0x0000,0x0000, 0x1EDB,0x0000,0x0000, 0x1EDC,0x0000,0x0000, /* A8B7 */ +0x1EDD,0x0000,0x0000, 0x1EDE,0x0000,0x0000, 0x1EDF,0x0000,0x0000, /* A8BA */ +0x1EE0,0x0000,0x0000, 0x1EE1,0x0000,0x0000, 0x1EE2,0x0000,0x0000, /* A8BD */ +0x1EE3,0x0000,0x0000, 0x1EE4,0x0000,0x0000, 0x1EE5,0x0000,0x0000, /* A8C0 */ +0x1EE6,0x0000,0x0000, 0x1EE7,0x0000,0x0000, 0xFBC1,0xA8C5,0x0000, /* A8C3 */ +0xFBC1,0xA8C6,0x0000, 0xFBC1,0xA8C7,0x0000, 0xFBC1,0xA8C8,0x0000, /* A8C6 */ +0xFBC1,0xA8C9,0x0000, 0xFBC1,0xA8CA,0x0000, 0xFBC1,0xA8CB,0x0000, /* A8C9 */ +0xFBC1,0xA8CC,0x0000, 0xFBC1,0xA8CD,0x0000, 0x0296,0x0000,0x0000, /* A8CC */ +0x0297,0x0000,0x0000, 0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, /* A8CF */ +0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, /* A8D2 */ +0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, /* A8D5 */ +0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, 0xFBC1,0xA8DA,0x0000, /* A8D8 */ +0xFBC1,0xA8DB,0x0000, 0xFBC1,0xA8DC,0x0000, 0xFBC1,0xA8DD,0x0000, /* A8DB */ +0xFBC1,0xA8DE,0x0000, 0xFBC1,0xA8DF,0x0000, 0x0000,0x0000,0x0000, /* A8DE */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* A8E1 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* A8E4 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* A8E7 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* A8EA */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* A8ED */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x1BE8,0x0000,0x0000, /* A8F0 */ +0x1BE8,0x0000,0x0000, 0x1BE8,0x0000,0x0000, 0x1BE8,0x0000,0x0000, /* A8F3 */ +0x1BE8,0x0000,0x0000, 0x1BE8,0x0000,0x0000, 0x03A2,0x0000,0x0000, /* A8F6 */ +0x03A3,0x0000,0x0000, 0x03A4,0x0000,0x0000, 0x1BE9,0x0000,0x0000, /* A8F9 */ +0xFBC1,0xA8FC,0x0000, 0xFBC1,0xA8FD,0x0000, 0xFBC1,0xA8FE,0x0000, /* A8FC */ +0xFBC1,0xA8FF,0x0000 }; + +uint16 uca520_p0A9[]= { /* A900 (3 weights per char) */ +0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* A900 */ +0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, /* A903 */ +0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, /* A906 */ +0x120E,0x0000,0x0000, 0x21AC,0x0000,0x0000, 0x21AD,0x0000,0x0000, /* A909 */ +0x21AE,0x0000,0x0000, 0x21AF,0x0000,0x0000, 0x21B0,0x0000,0x0000, /* A90C */ +0x21B1,0x0000,0x0000, 0x21B2,0x0000,0x0000, 0x21B3,0x0000,0x0000, /* A90F */ +0x21B4,0x0000,0x0000, 0x21B5,0x0000,0x0000, 0x21B6,0x0000,0x0000, /* A912 */ +0x21B7,0x0000,0x0000, 0x21B8,0x0000,0x0000, 0x21B9,0x0000,0x0000, /* A915 */ +0x21BA,0x0000,0x0000, 0x21BB,0x0000,0x0000, 0x21BC,0x0000,0x0000, /* A918 */ +0x21BD,0x0000,0x0000, 0x21BE,0x0000,0x0000, 0x21BF,0x0000,0x0000, /* A91B */ +0x21C0,0x0000,0x0000, 0x21C1,0x0000,0x0000, 0x21C2,0x0000,0x0000, /* A91E */ +0x21C3,0x0000,0x0000, 0x21C4,0x0000,0x0000, 0x21C5,0x0000,0x0000, /* A921 */ +0x21C6,0x0000,0x0000, 0x21C7,0x0000,0x0000, 0x21C8,0x0000,0x0000, /* A924 */ +0x21C9,0x0000,0x0000, 0x21CA,0x0000,0x0000, 0x21CB,0x0000,0x0000, /* A927 */ +0x21CC,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* A92A */ +0x0000,0x0000,0x0000, 0x03DB,0x0000,0x0000, 0x029E,0x0000,0x0000, /* A92D */ +0x2188,0x0000,0x0000, 0x2189,0x0000,0x0000, 0x218A,0x0000,0x0000, /* A930 */ +0x218B,0x0000,0x0000, 0x218C,0x0000,0x0000, 0x218D,0x0000,0x0000, /* A933 */ +0x218E,0x0000,0x0000, 0x218F,0x0000,0x0000, 0x2190,0x0000,0x0000, /* A936 */ +0x2191,0x0000,0x0000, 0x2192,0x0000,0x0000, 0x2193,0x0000,0x0000, /* A939 */ +0x2194,0x0000,0x0000, 0x2195,0x0000,0x0000, 0x2196,0x0000,0x0000, /* A93C */ +0x2197,0x0000,0x0000, 0x2198,0x0000,0x0000, 0x2199,0x0000,0x0000, /* A93F */ +0x219A,0x0000,0x0000, 0x219B,0x0000,0x0000, 0x219C,0x0000,0x0000, /* A942 */ +0x219D,0x0000,0x0000, 0x219E,0x0000,0x0000, 0x219F,0x0000,0x0000, /* A945 */ +0x21A0,0x0000,0x0000, 0x21A1,0x0000,0x0000, 0x21A2,0x0000,0x0000, /* A948 */ +0x21A3,0x0000,0x0000, 0x21A4,0x0000,0x0000, 0x21A5,0x0000,0x0000, /* A94B */ +0x21A6,0x0000,0x0000, 0x21A7,0x0000,0x0000, 0x21A8,0x0000,0x0000, /* A94E */ +0x21A9,0x0000,0x0000, 0x21AA,0x0000,0x0000, 0x21AB,0x0000,0x0000, /* A951 */ +0xFBC1,0xA954,0x0000, 0xFBC1,0xA955,0x0000, 0xFBC1,0xA956,0x0000, /* A954 */ +0xFBC1,0xA957,0x0000, 0xFBC1,0xA958,0x0000, 0xFBC1,0xA959,0x0000, /* A957 */ +0xFBC1,0xA95A,0x0000, 0xFBC1,0xA95B,0x0000, 0xFBC1,0xA95C,0x0000, /* A95A */ +0xFBC1,0xA95D,0x0000, 0xFBC1,0xA95E,0x0000, 0x02C9,0x0000,0x0000, /* A95D */ +0x2A0F,0x0000,0x0000, 0x2A10,0x0000,0x0000, 0x2A11,0x0000,0x0000, /* A960 */ +0x2A12,0x0000,0x0000, 0x2A13,0x0000,0x0000, 0x2A14,0x0000,0x0000, /* A963 */ +0x2A15,0x0000,0x0000, 0x2A16,0x0000,0x0000, 0x2A17,0x0000,0x0000, /* A966 */ +0x2A18,0x0000,0x0000, 0x2A19,0x0000,0x0000, 0x2A1A,0x0000,0x0000, /* A969 */ +0x2A1B,0x0000,0x0000, 0x2A1C,0x0000,0x0000, 0x2A1D,0x0000,0x0000, /* A96C */ +0x2A1E,0x0000,0x0000, 0x2A1F,0x0000,0x0000, 0x2A20,0x0000,0x0000, /* A96F */ +0x2A21,0x0000,0x0000, 0x2A22,0x0000,0x0000, 0x2A23,0x0000,0x0000, /* A972 */ +0x2A24,0x0000,0x0000, 0x2A25,0x0000,0x0000, 0x2A26,0x0000,0x0000, /* A975 */ +0x2A27,0x0000,0x0000, 0x2A28,0x0000,0x0000, 0x2A29,0x0000,0x0000, /* A978 */ +0x2A2A,0x0000,0x0000, 0x2A2B,0x0000,0x0000, 0xFBC1,0xA97D,0x0000, /* A97B */ +0xFBC1,0xA97E,0x0000, 0xFBC1,0xA97F,0x0000, 0x0000,0x0000,0x0000, /* A97E */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* A981 */ +0x23EC,0x0000,0x0000, 0x23ED,0x0000,0x0000, 0x23EE,0x0000,0x0000, /* A984 */ +0x23EF,0x0000,0x0000, 0x23F0,0x0000,0x0000, 0x23F1,0x0000,0x0000, /* A987 */ +0x23F2,0x0000,0x0000, 0x23F3,0x0000,0x0000, 0x23F4,0x0000,0x0000, /* A98A */ +0x23F5,0x0000,0x0000, 0x23F6,0x0000,0x0000, 0x23F7,0x0000,0x0000, /* A98D */ +0x23F8,0x0000,0x0000, 0x23F9,0x0000,0x0000, 0x23FA,0x0000,0x0000, /* A990 */ +0x23FB,0x0000,0x0000, 0x23FC,0x0000,0x0000, 0x23FD,0x0000,0x0000, /* A993 */ +0x23FE,0x0000,0x0000, 0x23FF,0x0000,0x0000, 0x2400,0x0000,0x0000, /* A996 */ +0x2401,0x0000,0x0000, 0x2402,0x0000,0x0000, 0x2403,0x0000,0x0000, /* A999 */ +0x2404,0x0000,0x0000, 0x2405,0x0000,0x0000, 0x2406,0x0000,0x0000, /* A99C */ +0x2407,0x0000,0x0000, 0x2408,0x0000,0x0000, 0x2409,0x0000,0x0000, /* A99F */ +0x240A,0x0000,0x0000, 0x240B,0x0000,0x0000, 0x240C,0x0000,0x0000, /* A9A2 */ +0x240D,0x0000,0x0000, 0x240E,0x0000,0x0000, 0x240F,0x0000,0x0000, /* A9A5 */ +0x2410,0x0000,0x0000, 0x2411,0x0000,0x0000, 0x2412,0x0000,0x0000, /* A9A8 */ +0x2414,0x0000,0x0000, 0x2414,0x0000,0x0000, 0x2416,0x0000,0x0000, /* A9AB */ +0x2417,0x0000,0x0000, 0x2418,0x0000,0x0000, 0x2419,0x0000,0x0000, /* A9AE */ +0x241A,0x0000,0x0000, 0x241B,0x0000,0x0000, 0x0000,0x0000,0x0000, /* A9B1 */ +0x241C,0x0000,0x0000, 0x2425,0x0000,0x0000, 0x241E,0x0000,0x0000, /* A9B4 */ +0x241F,0x0000,0x0000, 0x2420,0x0000,0x0000, 0x2421,0x0000,0x0000, /* A9B7 */ +0x2423,0x0000,0x0000, 0x2424,0x0000,0x0000, 0x241D,0x0000,0x0000, /* A9BA */ +0x2422,0x0000,0x0000, 0x2413,0x0000,0x0000, 0x2415,0x0000,0x0000, /* A9BD */ +0x2426,0x0000,0x0000, 0x02BE,0x0000,0x0000, 0x02BF,0x0000,0x0000, /* A9C0 */ +0x02C0,0x0000,0x0000, 0x02C1,0x0000,0x0000, 0x02C2,0x0000,0x0000, /* A9C3 */ +0x02C3,0x0000,0x0000, 0x0269,0x0000,0x0000, 0x02A9,0x0000,0x0000, /* A9C6 */ +0x02AA,0x0000,0x0000, 0x02C4,0x0000,0x0000, 0x02C5,0x0000,0x0000, /* A9C9 */ +0x02C6,0x0000,0x0000, 0x02C7,0x0000,0x0000, 0xFBC1,0xA9CE,0x0000, /* A9CC */ +0x11D4,0x0000,0x0000, 0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, /* A9CF */ +0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, /* A9D2 */ +0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, /* A9D5 */ +0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, 0xFBC1,0xA9DA,0x0000, /* A9D8 */ +0xFBC1,0xA9DB,0x0000, 0xFBC1,0xA9DC,0x0000, 0xFBC1,0xA9DD,0x0000, /* A9DB */ +0x03DC,0x0000,0x0000, 0x03DD,0x0000,0x0000, 0xFBC1,0xA9E0,0x0000, /* A9DE */ +0xFBC1,0xA9E1,0x0000, 0xFBC1,0xA9E2,0x0000, 0xFBC1,0xA9E3,0x0000, /* A9E1 */ +0xFBC1,0xA9E4,0x0000, 0xFBC1,0xA9E5,0x0000, 0xFBC1,0xA9E6,0x0000, /* A9E4 */ +0xFBC1,0xA9E7,0x0000, 0xFBC1,0xA9E8,0x0000, 0xFBC1,0xA9E9,0x0000, /* A9E7 */ +0xFBC1,0xA9EA,0x0000, 0xFBC1,0xA9EB,0x0000, 0xFBC1,0xA9EC,0x0000, /* A9EA */ +0xFBC1,0xA9ED,0x0000, 0xFBC1,0xA9EE,0x0000, 0xFBC1,0xA9EF,0x0000, /* A9ED */ +0xFBC1,0xA9F0,0x0000, 0xFBC1,0xA9F1,0x0000, 0xFBC1,0xA9F2,0x0000, /* A9F0 */ +0xFBC1,0xA9F3,0x0000, 0xFBC1,0xA9F4,0x0000, 0xFBC1,0xA9F5,0x0000, /* A9F3 */ +0xFBC1,0xA9F6,0x0000, 0xFBC1,0xA9F7,0x0000, 0xFBC1,0xA9F8,0x0000, /* A9F6 */ +0xFBC1,0xA9F9,0x0000, 0xFBC1,0xA9FA,0x0000, 0xFBC1,0xA9FB,0x0000, /* A9F9 */ +0xFBC1,0xA9FC,0x0000, 0xFBC1,0xA9FD,0x0000, 0xFBC1,0xA9FE,0x0000, /* A9FC */ +0xFBC1,0xA9FF,0x0000 }; + +uint16 uca520_p0AA[]= { /* AA00 (3 weights per char) */ +0x2361,0x0000,0x0000, 0x2362,0x0000,0x0000, 0x2363,0x0000,0x0000, /* AA00 */ +0x2364,0x0000,0x0000, 0x2365,0x0000,0x0000, 0x2366,0x0000,0x0000, /* AA03 */ +0x2367,0x0000,0x0000, 0x2368,0x0000,0x0000, 0x2369,0x0000,0x0000, /* AA06 */ +0x236A,0x0000,0x0000, 0x236B,0x0000,0x0000, 0x236C,0x0000,0x0000, /* AA09 */ +0x236D,0x0000,0x0000, 0x236E,0x0000,0x0000, 0x236F,0x0000,0x0000, /* AA0C */ +0x2370,0x0000,0x0000, 0x2371,0x0000,0x0000, 0x2372,0x0000,0x0000, /* AA0F */ +0x2373,0x0000,0x0000, 0x2374,0x0000,0x0000, 0x2375,0x0000,0x0000, /* AA12 */ +0x2376,0x0000,0x0000, 0x2377,0x0000,0x0000, 0x2378,0x0000,0x0000, /* AA15 */ +0x2379,0x0000,0x0000, 0x237A,0x0000,0x0000, 0x237B,0x0000,0x0000, /* AA18 */ +0x237C,0x0000,0x0000, 0x237D,0x0000,0x0000, 0x237E,0x0000,0x0000, /* AA1B */ +0x237F,0x0000,0x0000, 0x2380,0x0000,0x0000, 0x2381,0x0000,0x0000, /* AA1E */ +0x2382,0x0000,0x0000, 0x2383,0x0000,0x0000, 0x2384,0x0000,0x0000, /* AA21 */ +0x2385,0x0000,0x0000, 0x2386,0x0000,0x0000, 0x2387,0x0000,0x0000, /* AA24 */ +0x2388,0x0000,0x0000, 0x2389,0x0000,0x0000, 0x238E,0x0000,0x0000, /* AA27 */ +0x238F,0x0000,0x0000, 0x2390,0x0000,0x0000, 0x2391,0x0000,0x0000, /* AA2A */ +0x2392,0x0000,0x0000, 0x2393,0x0000,0x0000, 0x2394,0x0000,0x0000, /* AA2D */ +0x2395,0x0000,0x0000, 0x2396,0x0000,0x0000, 0x2397,0x0000,0x0000, /* AA30 */ +0x238A,0x0000,0x0000, 0x238B,0x0000,0x0000, 0x238C,0x0000,0x0000, /* AA33 */ +0x238D,0x0000,0x0000, 0xFBC1,0xAA37,0x0000, 0xFBC1,0xAA38,0x0000, /* AA36 */ +0xFBC1,0xAA39,0x0000, 0xFBC1,0xAA3A,0x0000, 0xFBC1,0xAA3B,0x0000, /* AA39 */ +0xFBC1,0xAA3C,0x0000, 0xFBC1,0xAA3D,0x0000, 0xFBC1,0xAA3E,0x0000, /* AA3C */ +0xFBC1,0xAA3F,0x0000, 0x2398,0x0000,0x0000, 0x2399,0x0000,0x0000, /* AA3F */ +0x239A,0x0000,0x0000, 0x239B,0x0000,0x0000, 0x239C,0x0000,0x0000, /* AA42 */ +0x239D,0x0000,0x0000, 0x239E,0x0000,0x0000, 0x239F,0x0000,0x0000, /* AA45 */ +0x23A0,0x0000,0x0000, 0x23A1,0x0000,0x0000, 0x23A2,0x0000,0x0000, /* AA48 */ +0x23A3,0x0000,0x0000, 0x23A4,0x0000,0x0000, 0x23A5,0x0000,0x0000, /* AA4B */ +0xFBC1,0xAA4E,0x0000, 0xFBC1,0xAA4F,0x0000, 0x1205,0x0000,0x0000, /* AA4E */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* AA51 */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* AA54 */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* AA57 */ +0xFBC1,0xAA5A,0x0000, 0xFBC1,0xAA5B,0x0000, 0x03DE,0x0000,0x0000, /* AA5A */ +0x02AB,0x0000,0x0000, 0x02AC,0x0000,0x0000, 0x02AD,0x0000,0x0000, /* AA5D */ +0x21D3,0x0000,0x0000, 0x21D9,0x0000,0x0000, 0x21DB,0x0000,0x0000, /* AA60 */ +0x21DD,0x0000,0x0000, 0x21E2,0x0000,0x0000, 0x21E6,0x0000,0x0000, /* AA63 */ +0x21E9,0x0000,0x0000, 0x21EB,0x0000,0x0000, 0x21ED,0x0000,0x0000, /* AA66 */ +0x21EF,0x0000,0x0000, 0x21F7,0x0000,0x0000, 0x21FA,0x0000,0x0000, /* AA69 */ +0x2217,0x0000,0x0000, 0x221A,0x0000,0x0000, 0x221C,0x0000,0x0000, /* AA6C */ +0x2200,0x0000,0x0000, 0x11D5,0x0000,0x0000, 0x221D,0x0000,0x0000, /* AA6F */ +0x21DF,0x0000,0x0000, 0x220A,0x0000,0x0000, 0x2260,0x0000,0x0000, /* AA72 */ +0x2261,0x0000,0x0000, 0x2262,0x0000,0x0000, 0x03C8,0x0000,0x0000, /* AA75 */ +0x03C9,0x0000,0x0000, 0x03CA,0x0000,0x0000, 0x220B,0x0000,0x0000, /* AA78 */ +0x225F,0x0000,0x0000, 0xFBC1,0xAA7C,0x0000, 0xFBC1,0xAA7D,0x0000, /* AA7B */ +0xFBC1,0xAA7E,0x0000, 0xFBC1,0xAA7F,0x0000, 0x1FDE,0x0000,0x0000, /* AA7E */ +0x1FDF,0x0000,0x0000, 0x1FE0,0x0000,0x0000, 0x1FE1,0x0000,0x0000, /* AA81 */ +0x1FE2,0x0000,0x0000, 0x1FE3,0x0000,0x0000, 0x1FE4,0x0000,0x0000, /* AA84 */ +0x1FE5,0x0000,0x0000, 0x1FE6,0x0000,0x0000, 0x1FE7,0x0000,0x0000, /* AA87 */ +0x1FE8,0x0000,0x0000, 0x1FE9,0x0000,0x0000, 0x1FEA,0x0000,0x0000, /* AA8A */ +0x1FEB,0x0000,0x0000, 0x1FEC,0x0000,0x0000, 0x1FED,0x0000,0x0000, /* AA8D */ +0x1FEE,0x0000,0x0000, 0x1FEF,0x0000,0x0000, 0x1FF0,0x0000,0x0000, /* AA90 */ +0x1FF1,0x0000,0x0000, 0x1FF2,0x0000,0x0000, 0x1FF3,0x0000,0x0000, /* AA93 */ +0x1FF4,0x0000,0x0000, 0x1FF5,0x0000,0x0000, 0x1FF6,0x0000,0x0000, /* AA96 */ +0x1FF7,0x0000,0x0000, 0x1FF8,0x0000,0x0000, 0x1FF9,0x0000,0x0000, /* AA99 */ +0x1FFA,0x0000,0x0000, 0x1FFB,0x0000,0x0000, 0x1FFC,0x0000,0x0000, /* AA9C */ +0x1FFD,0x0000,0x0000, 0x1FFE,0x0000,0x0000, 0x1FFF,0x0000,0x0000, /* AA9F */ +0x2000,0x0000,0x0000, 0x2001,0x0000,0x0000, 0x2002,0x0000,0x0000, /* AAA2 */ +0x2003,0x0000,0x0000, 0x2004,0x0000,0x0000, 0x2005,0x0000,0x0000, /* AAA5 */ +0x2006,0x0000,0x0000, 0x2007,0x0000,0x0000, 0x2008,0x0000,0x0000, /* AAA8 */ +0x2009,0x0000,0x0000, 0x200A,0x0000,0x0000, 0x200B,0x0000,0x0000, /* AAAB */ +0x200C,0x0000,0x0000, 0x200D,0x0000,0x0000, 0x200E,0x0000,0x0000, /* AAAE */ +0x200F,0x0000,0x0000, 0x2010,0x0000,0x0000, 0x2011,0x0000,0x0000, /* AAB1 */ +0x2012,0x0000,0x0000, 0x2013,0x0000,0x0000, 0x2014,0x0000,0x0000, /* AAB4 */ +0x2015,0x0000,0x0000, 0x2016,0x0000,0x0000, 0x2017,0x0000,0x0000, /* AAB7 */ +0x2018,0x0000,0x0000, 0x2019,0x0000,0x0000, 0x201A,0x0000,0x0000, /* AABA */ +0x201B,0x0000,0x0000, 0x201C,0x0000,0x0000, 0x0000,0x0000,0x0000, /* AABD */ +0x201D,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x201E,0x0000,0x0000, /* AAC0 */ +0xFBC1,0xAAC3,0x0000, 0xFBC1,0xAAC4,0x0000, 0xFBC1,0xAAC5,0x0000, /* AAC3 */ +0xFBC1,0xAAC6,0x0000, 0xFBC1,0xAAC7,0x0000, 0xFBC1,0xAAC8,0x0000, /* AAC6 */ +0xFBC1,0xAAC9,0x0000, 0xFBC1,0xAACA,0x0000, 0xFBC1,0xAACB,0x0000, /* AAC9 */ +0xFBC1,0xAACC,0x0000, 0xFBC1,0xAACD,0x0000, 0xFBC1,0xAACE,0x0000, /* AACC */ +0xFBC1,0xAACF,0x0000, 0xFBC1,0xAAD0,0x0000, 0xFBC1,0xAAD1,0x0000, /* AACF */ +0xFBC1,0xAAD2,0x0000, 0xFBC1,0xAAD3,0x0000, 0xFBC1,0xAAD4,0x0000, /* AAD2 */ +0xFBC1,0xAAD5,0x0000, 0xFBC1,0xAAD6,0x0000, 0xFBC1,0xAAD7,0x0000, /* AAD5 */ +0xFBC1,0xAAD8,0x0000, 0xFBC1,0xAAD9,0x0000, 0xFBC1,0xAADA,0x0000, /* AAD8 */ +0x201F,0x0000,0x0000, 0x2020,0x0000,0x0000, 0x11D6,0x0000,0x0000, /* AADB */ +0x03A8,0x0000,0x0000, 0x03A9,0x0000,0x0000, 0xFBC1,0xAAE0,0x0000, /* AADE */ +0xFBC1,0xAAE1,0x0000, 0xFBC1,0xAAE2,0x0000, 0xFBC1,0xAAE3,0x0000, /* AAE1 */ +0xFBC1,0xAAE4,0x0000, 0xFBC1,0xAAE5,0x0000, 0xFBC1,0xAAE6,0x0000, /* AAE4 */ +0xFBC1,0xAAE7,0x0000, 0xFBC1,0xAAE8,0x0000, 0xFBC1,0xAAE9,0x0000, /* AAE7 */ +0xFBC1,0xAAEA,0x0000, 0xFBC1,0xAAEB,0x0000, 0xFBC1,0xAAEC,0x0000, /* AAEA */ +0xFBC1,0xAAED,0x0000, 0xFBC1,0xAAEE,0x0000, 0xFBC1,0xAAEF,0x0000, /* AAED */ +0xFBC1,0xAAF0,0x0000, 0xFBC1,0xAAF1,0x0000, 0xFBC1,0xAAF2,0x0000, /* AAF0 */ +0xFBC1,0xAAF3,0x0000, 0xFBC1,0xAAF4,0x0000, 0xFBC1,0xAAF5,0x0000, /* AAF3 */ +0xFBC1,0xAAF6,0x0000, 0xFBC1,0xAAF7,0x0000, 0xFBC1,0xAAF8,0x0000, /* AAF6 */ +0xFBC1,0xAAF9,0x0000, 0xFBC1,0xAAFA,0x0000, 0xFBC1,0xAAFB,0x0000, /* AAF9 */ +0xFBC1,0xAAFC,0x0000, 0xFBC1,0xAAFD,0x0000, 0xFBC1,0xAAFE,0x0000, /* AAFC */ +0xFBC1,0xAAFF,0x0000 }; + +uint16 uca520_p0AB[]= { /* AB00 (3 weights per char) */ +0xFBC1,0xAB00,0x0000, 0xFBC1,0xAB01,0x0000, 0xFBC1,0xAB02,0x0000, /* AB00 */ +0xFBC1,0xAB03,0x0000, 0xFBC1,0xAB04,0x0000, 0xFBC1,0xAB05,0x0000, /* AB03 */ +0xFBC1,0xAB06,0x0000, 0xFBC1,0xAB07,0x0000, 0xFBC1,0xAB08,0x0000, /* AB06 */ +0xFBC1,0xAB09,0x0000, 0xFBC1,0xAB0A,0x0000, 0xFBC1,0xAB0B,0x0000, /* AB09 */ +0xFBC1,0xAB0C,0x0000, 0xFBC1,0xAB0D,0x0000, 0xFBC1,0xAB0E,0x0000, /* AB0C */ +0xFBC1,0xAB0F,0x0000, 0xFBC1,0xAB10,0x0000, 0xFBC1,0xAB11,0x0000, /* AB0F */ +0xFBC1,0xAB12,0x0000, 0xFBC1,0xAB13,0x0000, 0xFBC1,0xAB14,0x0000, /* AB12 */ +0xFBC1,0xAB15,0x0000, 0xFBC1,0xAB16,0x0000, 0xFBC1,0xAB17,0x0000, /* AB15 */ +0xFBC1,0xAB18,0x0000, 0xFBC1,0xAB19,0x0000, 0xFBC1,0xAB1A,0x0000, /* AB18 */ +0xFBC1,0xAB1B,0x0000, 0xFBC1,0xAB1C,0x0000, 0xFBC1,0xAB1D,0x0000, /* AB1B */ +0xFBC1,0xAB1E,0x0000, 0xFBC1,0xAB1F,0x0000, 0xFBC1,0xAB20,0x0000, /* AB1E */ +0xFBC1,0xAB21,0x0000, 0xFBC1,0xAB22,0x0000, 0xFBC1,0xAB23,0x0000, /* AB21 */ +0xFBC1,0xAB24,0x0000, 0xFBC1,0xAB25,0x0000, 0xFBC1,0xAB26,0x0000, /* AB24 */ +0xFBC1,0xAB27,0x0000, 0xFBC1,0xAB28,0x0000, 0xFBC1,0xAB29,0x0000, /* AB27 */ +0xFBC1,0xAB2A,0x0000, 0xFBC1,0xAB2B,0x0000, 0xFBC1,0xAB2C,0x0000, /* AB2A */ +0xFBC1,0xAB2D,0x0000, 0xFBC1,0xAB2E,0x0000, 0xFBC1,0xAB2F,0x0000, /* AB2D */ +0xFBC1,0xAB30,0x0000, 0xFBC1,0xAB31,0x0000, 0xFBC1,0xAB32,0x0000, /* AB30 */ +0xFBC1,0xAB33,0x0000, 0xFBC1,0xAB34,0x0000, 0xFBC1,0xAB35,0x0000, /* AB33 */ +0xFBC1,0xAB36,0x0000, 0xFBC1,0xAB37,0x0000, 0xFBC1,0xAB38,0x0000, /* AB36 */ +0xFBC1,0xAB39,0x0000, 0xFBC1,0xAB3A,0x0000, 0xFBC1,0xAB3B,0x0000, /* AB39 */ +0xFBC1,0xAB3C,0x0000, 0xFBC1,0xAB3D,0x0000, 0xFBC1,0xAB3E,0x0000, /* AB3C */ +0xFBC1,0xAB3F,0x0000, 0xFBC1,0xAB40,0x0000, 0xFBC1,0xAB41,0x0000, /* AB3F */ +0xFBC1,0xAB42,0x0000, 0xFBC1,0xAB43,0x0000, 0xFBC1,0xAB44,0x0000, /* AB42 */ +0xFBC1,0xAB45,0x0000, 0xFBC1,0xAB46,0x0000, 0xFBC1,0xAB47,0x0000, /* AB45 */ +0xFBC1,0xAB48,0x0000, 0xFBC1,0xAB49,0x0000, 0xFBC1,0xAB4A,0x0000, /* AB48 */ +0xFBC1,0xAB4B,0x0000, 0xFBC1,0xAB4C,0x0000, 0xFBC1,0xAB4D,0x0000, /* AB4B */ +0xFBC1,0xAB4E,0x0000, 0xFBC1,0xAB4F,0x0000, 0xFBC1,0xAB50,0x0000, /* AB4E */ +0xFBC1,0xAB51,0x0000, 0xFBC1,0xAB52,0x0000, 0xFBC1,0xAB53,0x0000, /* AB51 */ +0xFBC1,0xAB54,0x0000, 0xFBC1,0xAB55,0x0000, 0xFBC1,0xAB56,0x0000, /* AB54 */ +0xFBC1,0xAB57,0x0000, 0xFBC1,0xAB58,0x0000, 0xFBC1,0xAB59,0x0000, /* AB57 */ +0xFBC1,0xAB5A,0x0000, 0xFBC1,0xAB5B,0x0000, 0xFBC1,0xAB5C,0x0000, /* AB5A */ +0xFBC1,0xAB5D,0x0000, 0xFBC1,0xAB5E,0x0000, 0xFBC1,0xAB5F,0x0000, /* AB5D */ +0xFBC1,0xAB60,0x0000, 0xFBC1,0xAB61,0x0000, 0xFBC1,0xAB62,0x0000, /* AB60 */ +0xFBC1,0xAB63,0x0000, 0xFBC1,0xAB64,0x0000, 0xFBC1,0xAB65,0x0000, /* AB63 */ +0xFBC1,0xAB66,0x0000, 0xFBC1,0xAB67,0x0000, 0xFBC1,0xAB68,0x0000, /* AB66 */ +0xFBC1,0xAB69,0x0000, 0xFBC1,0xAB6A,0x0000, 0xFBC1,0xAB6B,0x0000, /* AB69 */ +0xFBC1,0xAB6C,0x0000, 0xFBC1,0xAB6D,0x0000, 0xFBC1,0xAB6E,0x0000, /* AB6C */ +0xFBC1,0xAB6F,0x0000, 0xFBC1,0xAB70,0x0000, 0xFBC1,0xAB71,0x0000, /* AB6F */ +0xFBC1,0xAB72,0x0000, 0xFBC1,0xAB73,0x0000, 0xFBC1,0xAB74,0x0000, /* AB72 */ +0xFBC1,0xAB75,0x0000, 0xFBC1,0xAB76,0x0000, 0xFBC1,0xAB77,0x0000, /* AB75 */ +0xFBC1,0xAB78,0x0000, 0xFBC1,0xAB79,0x0000, 0xFBC1,0xAB7A,0x0000, /* AB78 */ +0xFBC1,0xAB7B,0x0000, 0xFBC1,0xAB7C,0x0000, 0xFBC1,0xAB7D,0x0000, /* AB7B */ +0xFBC1,0xAB7E,0x0000, 0xFBC1,0xAB7F,0x0000, 0xFBC1,0xAB80,0x0000, /* AB7E */ +0xFBC1,0xAB81,0x0000, 0xFBC1,0xAB82,0x0000, 0xFBC1,0xAB83,0x0000, /* AB81 */ +0xFBC1,0xAB84,0x0000, 0xFBC1,0xAB85,0x0000, 0xFBC1,0xAB86,0x0000, /* AB84 */ +0xFBC1,0xAB87,0x0000, 0xFBC1,0xAB88,0x0000, 0xFBC1,0xAB89,0x0000, /* AB87 */ +0xFBC1,0xAB8A,0x0000, 0xFBC1,0xAB8B,0x0000, 0xFBC1,0xAB8C,0x0000, /* AB8A */ +0xFBC1,0xAB8D,0x0000, 0xFBC1,0xAB8E,0x0000, 0xFBC1,0xAB8F,0x0000, /* AB8D */ +0xFBC1,0xAB90,0x0000, 0xFBC1,0xAB91,0x0000, 0xFBC1,0xAB92,0x0000, /* AB90 */ +0xFBC1,0xAB93,0x0000, 0xFBC1,0xAB94,0x0000, 0xFBC1,0xAB95,0x0000, /* AB93 */ +0xFBC1,0xAB96,0x0000, 0xFBC1,0xAB97,0x0000, 0xFBC1,0xAB98,0x0000, /* AB96 */ +0xFBC1,0xAB99,0x0000, 0xFBC1,0xAB9A,0x0000, 0xFBC1,0xAB9B,0x0000, /* AB99 */ +0xFBC1,0xAB9C,0x0000, 0xFBC1,0xAB9D,0x0000, 0xFBC1,0xAB9E,0x0000, /* AB9C */ +0xFBC1,0xAB9F,0x0000, 0xFBC1,0xABA0,0x0000, 0xFBC1,0xABA1,0x0000, /* AB9F */ +0xFBC1,0xABA2,0x0000, 0xFBC1,0xABA3,0x0000, 0xFBC1,0xABA4,0x0000, /* ABA2 */ +0xFBC1,0xABA5,0x0000, 0xFBC1,0xABA6,0x0000, 0xFBC1,0xABA7,0x0000, /* ABA5 */ +0xFBC1,0xABA8,0x0000, 0xFBC1,0xABA9,0x0000, 0xFBC1,0xABAA,0x0000, /* ABA8 */ +0xFBC1,0xABAB,0x0000, 0xFBC1,0xABAC,0x0000, 0xFBC1,0xABAD,0x0000, /* ABAB */ +0xFBC1,0xABAE,0x0000, 0xFBC1,0xABAF,0x0000, 0xFBC1,0xABB0,0x0000, /* ABAE */ +0xFBC1,0xABB1,0x0000, 0xFBC1,0xABB2,0x0000, 0xFBC1,0xABB3,0x0000, /* ABB1 */ +0xFBC1,0xABB4,0x0000, 0xFBC1,0xABB5,0x0000, 0xFBC1,0xABB6,0x0000, /* ABB4 */ +0xFBC1,0xABB7,0x0000, 0xFBC1,0xABB8,0x0000, 0xFBC1,0xABB9,0x0000, /* ABB7 */ +0xFBC1,0xABBA,0x0000, 0xFBC1,0xABBB,0x0000, 0xFBC1,0xABBC,0x0000, /* ABBA */ +0xFBC1,0xABBD,0x0000, 0xFBC1,0xABBE,0x0000, 0xFBC1,0xABBF,0x0000, /* ABBD */ +0x1E52,0x0000,0x0000, 0x1E53,0x0000,0x0000, 0x1E54,0x0000,0x0000, /* ABC0 */ +0x1E55,0x0000,0x0000, 0x1E56,0x0000,0x0000, 0x1E57,0x0000,0x0000, /* ABC3 */ +0x1E58,0x0000,0x0000, 0x1E59,0x0000,0x0000, 0x1E5A,0x0000,0x0000, /* ABC6 */ +0x1E5B,0x0000,0x0000, 0x1E5C,0x0000,0x0000, 0x1E5D,0x0000,0x0000, /* ABC9 */ +0x1E5E,0x0000,0x0000, 0x1E5F,0x0000,0x0000, 0x1E60,0x0000,0x0000, /* ABCC */ +0x1E61,0x0000,0x0000, 0x1E62,0x0000,0x0000, 0x1E63,0x0000,0x0000, /* ABCF */ +0x1E64,0x0000,0x0000, 0x1E65,0x0000,0x0000, 0x1E66,0x0000,0x0000, /* ABD2 */ +0x1E67,0x0000,0x0000, 0x1E68,0x0000,0x0000, 0x1E69,0x0000,0x0000, /* ABD5 */ +0x1E6A,0x0000,0x0000, 0x1E6B,0x0000,0x0000, 0x1E6C,0x0000,0x0000, /* ABD8 */ +0x1E75,0x0000,0x0000, 0x1E76,0x0000,0x0000, 0x1E77,0x0000,0x0000, /* ABDB */ +0x1E78,0x0000,0x0000, 0x1E79,0x0000,0x0000, 0x1E7A,0x0000,0x0000, /* ABDE */ +0x1E7B,0x0000,0x0000, 0x1E7C,0x0000,0x0000, 0x1E6D,0x0000,0x0000, /* ABE1 */ +0x1E6E,0x0000,0x0000, 0x1E6F,0x0000,0x0000, 0x1E70,0x0000,0x0000, /* ABE4 */ +0x1E71,0x0000,0x0000, 0x1E72,0x0000,0x0000, 0x1E73,0x0000,0x0000, /* ABE7 */ +0x1E74,0x0000,0x0000, 0x02AE,0x0000,0x0000, 0x0000,0x0000,0x0000, /* ABEA */ +0x1E7D,0x0000,0x0000, 0xFBC1,0xABEE,0x0000, 0xFBC1,0xABEF,0x0000, /* ABED */ +0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* ABF0 */ +0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, /* ABF3 */ +0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, /* ABF6 */ +0x120E,0x0000,0x0000, 0xFBC1,0xABFA,0x0000, 0xFBC1,0xABFB,0x0000, /* ABF9 */ +0xFBC1,0xABFC,0x0000, 0xFBC1,0xABFD,0x0000, 0xFBC1,0xABFE,0x0000, /* ABFC */ +0xFBC1,0xABFF,0x0000 }; + +uint16 uca520_p0D7[]= { /* D700 (3 weights per char) */ +0xFBC1,0xD700,0x0000, 0xFBC1,0xD701,0x0000, 0xFBC1,0xD702,0x0000, /* D700 */ +0xFBC1,0xD703,0x0000, 0xFBC1,0xD704,0x0000, 0xFBC1,0xD705,0x0000, /* D703 */ +0xFBC1,0xD706,0x0000, 0xFBC1,0xD707,0x0000, 0xFBC1,0xD708,0x0000, /* D706 */ +0xFBC1,0xD709,0x0000, 0xFBC1,0xD70A,0x0000, 0xFBC1,0xD70B,0x0000, /* D709 */ +0xFBC1,0xD70C,0x0000, 0xFBC1,0xD70D,0x0000, 0xFBC1,0xD70E,0x0000, /* D70C */ +0xFBC1,0xD70F,0x0000, 0xFBC1,0xD710,0x0000, 0xFBC1,0xD711,0x0000, /* D70F */ +0xFBC1,0xD712,0x0000, 0xFBC1,0xD713,0x0000, 0xFBC1,0xD714,0x0000, /* D712 */ +0xFBC1,0xD715,0x0000, 0xFBC1,0xD716,0x0000, 0xFBC1,0xD717,0x0000, /* D715 */ +0xFBC1,0xD718,0x0000, 0xFBC1,0xD719,0x0000, 0xFBC1,0xD71A,0x0000, /* D718 */ +0xFBC1,0xD71B,0x0000, 0xFBC1,0xD71C,0x0000, 0xFBC1,0xD71D,0x0000, /* D71B */ +0xFBC1,0xD71E,0x0000, 0xFBC1,0xD71F,0x0000, 0xFBC1,0xD720,0x0000, /* D71E */ +0xFBC1,0xD721,0x0000, 0xFBC1,0xD722,0x0000, 0xFBC1,0xD723,0x0000, /* D721 */ +0xFBC1,0xD724,0x0000, 0xFBC1,0xD725,0x0000, 0xFBC1,0xD726,0x0000, /* D724 */ +0xFBC1,0xD727,0x0000, 0xFBC1,0xD728,0x0000, 0xFBC1,0xD729,0x0000, /* D727 */ +0xFBC1,0xD72A,0x0000, 0xFBC1,0xD72B,0x0000, 0xFBC1,0xD72C,0x0000, /* D72A */ +0xFBC1,0xD72D,0x0000, 0xFBC1,0xD72E,0x0000, 0xFBC1,0xD72F,0x0000, /* D72D */ +0xFBC1,0xD730,0x0000, 0xFBC1,0xD731,0x0000, 0xFBC1,0xD732,0x0000, /* D730 */ +0xFBC1,0xD733,0x0000, 0xFBC1,0xD734,0x0000, 0xFBC1,0xD735,0x0000, /* D733 */ +0xFBC1,0xD736,0x0000, 0xFBC1,0xD737,0x0000, 0xFBC1,0xD738,0x0000, /* D736 */ +0xFBC1,0xD739,0x0000, 0xFBC1,0xD73A,0x0000, 0xFBC1,0xD73B,0x0000, /* D739 */ +0xFBC1,0xD73C,0x0000, 0xFBC1,0xD73D,0x0000, 0xFBC1,0xD73E,0x0000, /* D73C */ +0xFBC1,0xD73F,0x0000, 0xFBC1,0xD740,0x0000, 0xFBC1,0xD741,0x0000, /* D73F */ +0xFBC1,0xD742,0x0000, 0xFBC1,0xD743,0x0000, 0xFBC1,0xD744,0x0000, /* D742 */ +0xFBC1,0xD745,0x0000, 0xFBC1,0xD746,0x0000, 0xFBC1,0xD747,0x0000, /* D745 */ +0xFBC1,0xD748,0x0000, 0xFBC1,0xD749,0x0000, 0xFBC1,0xD74A,0x0000, /* D748 */ +0xFBC1,0xD74B,0x0000, 0xFBC1,0xD74C,0x0000, 0xFBC1,0xD74D,0x0000, /* D74B */ +0xFBC1,0xD74E,0x0000, 0xFBC1,0xD74F,0x0000, 0xFBC1,0xD750,0x0000, /* D74E */ +0xFBC1,0xD751,0x0000, 0xFBC1,0xD752,0x0000, 0xFBC1,0xD753,0x0000, /* D751 */ +0xFBC1,0xD754,0x0000, 0xFBC1,0xD755,0x0000, 0xFBC1,0xD756,0x0000, /* D754 */ +0xFBC1,0xD757,0x0000, 0xFBC1,0xD758,0x0000, 0xFBC1,0xD759,0x0000, /* D757 */ +0xFBC1,0xD75A,0x0000, 0xFBC1,0xD75B,0x0000, 0xFBC1,0xD75C,0x0000, /* D75A */ +0xFBC1,0xD75D,0x0000, 0xFBC1,0xD75E,0x0000, 0xFBC1,0xD75F,0x0000, /* D75D */ +0xFBC1,0xD760,0x0000, 0xFBC1,0xD761,0x0000, 0xFBC1,0xD762,0x0000, /* D760 */ +0xFBC1,0xD763,0x0000, 0xFBC1,0xD764,0x0000, 0xFBC1,0xD765,0x0000, /* D763 */ +0xFBC1,0xD766,0x0000, 0xFBC1,0xD767,0x0000, 0xFBC1,0xD768,0x0000, /* D766 */ +0xFBC1,0xD769,0x0000, 0xFBC1,0xD76A,0x0000, 0xFBC1,0xD76B,0x0000, /* D769 */ +0xFBC1,0xD76C,0x0000, 0xFBC1,0xD76D,0x0000, 0xFBC1,0xD76E,0x0000, /* D76C */ +0xFBC1,0xD76F,0x0000, 0xFBC1,0xD770,0x0000, 0xFBC1,0xD771,0x0000, /* D76F */ +0xFBC1,0xD772,0x0000, 0xFBC1,0xD773,0x0000, 0xFBC1,0xD774,0x0000, /* D772 */ +0xFBC1,0xD775,0x0000, 0xFBC1,0xD776,0x0000, 0xFBC1,0xD777,0x0000, /* D775 */ +0xFBC1,0xD778,0x0000, 0xFBC1,0xD779,0x0000, 0xFBC1,0xD77A,0x0000, /* D778 */ +0xFBC1,0xD77B,0x0000, 0xFBC1,0xD77C,0x0000, 0xFBC1,0xD77D,0x0000, /* D77B */ +0xFBC1,0xD77E,0x0000, 0xFBC1,0xD77F,0x0000, 0xFBC1,0xD780,0x0000, /* D77E */ +0xFBC1,0xD781,0x0000, 0xFBC1,0xD782,0x0000, 0xFBC1,0xD783,0x0000, /* D781 */ +0xFBC1,0xD784,0x0000, 0xFBC1,0xD785,0x0000, 0xFBC1,0xD786,0x0000, /* D784 */ +0xFBC1,0xD787,0x0000, 0xFBC1,0xD788,0x0000, 0xFBC1,0xD789,0x0000, /* D787 */ +0xFBC1,0xD78A,0x0000, 0xFBC1,0xD78B,0x0000, 0xFBC1,0xD78C,0x0000, /* D78A */ +0xFBC1,0xD78D,0x0000, 0xFBC1,0xD78E,0x0000, 0xFBC1,0xD78F,0x0000, /* D78D */ +0xFBC1,0xD790,0x0000, 0xFBC1,0xD791,0x0000, 0xFBC1,0xD792,0x0000, /* D790 */ +0xFBC1,0xD793,0x0000, 0xFBC1,0xD794,0x0000, 0xFBC1,0xD795,0x0000, /* D793 */ +0xFBC1,0xD796,0x0000, 0xFBC1,0xD797,0x0000, 0xFBC1,0xD798,0x0000, /* D796 */ +0xFBC1,0xD799,0x0000, 0xFBC1,0xD79A,0x0000, 0xFBC1,0xD79B,0x0000, /* D799 */ +0xFBC1,0xD79C,0x0000, 0xFBC1,0xD79D,0x0000, 0xFBC1,0xD79E,0x0000, /* D79C */ +0xFBC1,0xD79F,0x0000, 0xFBC1,0xD7A0,0x0000, 0xFBC1,0xD7A1,0x0000, /* D79F */ +0xFBC1,0xD7A2,0x0000, 0xFBC1,0xD7A3,0x0000, 0xFBC1,0xD7A4,0x0000, /* D7A2 */ +0xFBC1,0xD7A5,0x0000, 0xFBC1,0xD7A6,0x0000, 0xFBC1,0xD7A7,0x0000, /* D7A5 */ +0xFBC1,0xD7A8,0x0000, 0xFBC1,0xD7A9,0x0000, 0xFBC1,0xD7AA,0x0000, /* D7A8 */ +0xFBC1,0xD7AB,0x0000, 0xFBC1,0xD7AC,0x0000, 0xFBC1,0xD7AD,0x0000, /* D7AB */ +0xFBC1,0xD7AE,0x0000, 0xFBC1,0xD7AF,0x0000, 0x2A75,0x0000,0x0000, /* D7AE */ +0x2A76,0x0000,0x0000, 0x2A77,0x0000,0x0000, 0x2A78,0x0000,0x0000, /* D7B1 */ +0x2A79,0x0000,0x0000, 0x2A7A,0x0000,0x0000, 0x2A7B,0x0000,0x0000, /* D7B4 */ +0x2A7C,0x0000,0x0000, 0x2A7D,0x0000,0x0000, 0x2A7E,0x0000,0x0000, /* D7B7 */ +0x2A7F,0x0000,0x0000, 0x2A80,0x0000,0x0000, 0x2A81,0x0000,0x0000, /* D7BA */ +0x2A82,0x0000,0x0000, 0x2A83,0x0000,0x0000, 0x2A84,0x0000,0x0000, /* D7BD */ +0x2A85,0x0000,0x0000, 0x2A86,0x0000,0x0000, 0x2A87,0x0000,0x0000, /* D7C0 */ +0x2A88,0x0000,0x0000, 0x2A89,0x0000,0x0000, 0x2A8A,0x0000,0x0000, /* D7C3 */ +0x2A8B,0x0000,0x0000, 0xFBC1,0xD7C7,0x0000, 0xFBC1,0xD7C8,0x0000, /* D7C6 */ +0xFBC1,0xD7C9,0x0000, 0xFBC1,0xD7CA,0x0000, 0x2AE4,0x0000,0x0000, /* D7C9 */ +0x2AE5,0x0000,0x0000, 0x2AE6,0x0000,0x0000, 0x2AE7,0x0000,0x0000, /* D7CC */ +0x2AE8,0x0000,0x0000, 0x2AE9,0x0000,0x0000, 0x2AEA,0x0000,0x0000, /* D7CF */ +0x2AEB,0x0000,0x0000, 0x2AEC,0x0000,0x0000, 0x2AED,0x0000,0x0000, /* D7D2 */ +0x2AEE,0x0000,0x0000, 0x2AEF,0x0000,0x0000, 0x2AF0,0x0000,0x0000, /* D7D5 */ +0x2AF1,0x0000,0x0000, 0x2AF2,0x0000,0x0000, 0x2AF3,0x0000,0x0000, /* D7D8 */ +0x2AF4,0x0000,0x0000, 0x2AF5,0x0000,0x0000, 0x2AF6,0x0000,0x0000, /* D7DB */ +0x2AF7,0x0000,0x0000, 0x2AF8,0x0000,0x0000, 0x2AF9,0x0000,0x0000, /* D7DE */ +0x2AFA,0x0000,0x0000, 0x2AFB,0x0000,0x0000, 0x2AFC,0x0000,0x0000, /* D7E1 */ +0x2AFD,0x0000,0x0000, 0x2AFE,0x0000,0x0000, 0x2AFF,0x0000,0x0000, /* D7E4 */ +0x2B00,0x0000,0x0000, 0x2B01,0x0000,0x0000, 0x2B02,0x0000,0x0000, /* D7E7 */ +0x2B03,0x0000,0x0000, 0x2B04,0x0000,0x0000, 0x2B05,0x0000,0x0000, /* D7EA */ +0x2B06,0x0000,0x0000, 0x2B07,0x0000,0x0000, 0x2B08,0x0000,0x0000, /* D7ED */ +0x2B09,0x0000,0x0000, 0x2B0A,0x0000,0x0000, 0x2B0B,0x0000,0x0000, /* D7F0 */ +0x2B0C,0x0000,0x0000, 0x2B0D,0x0000,0x0000, 0x2B0E,0x0000,0x0000, /* D7F3 */ +0x2B0F,0x0000,0x0000, 0x2B10,0x0000,0x0000, 0x2B11,0x0000,0x0000, /* D7F6 */ +0x2B12,0x0000,0x0000, 0x2B13,0x0000,0x0000, 0x2B14,0x0000,0x0000, /* D7F9 */ +0xFBC1,0xD7FC,0x0000, 0xFBC1,0xD7FD,0x0000, 0xFBC1,0xD7FE,0x0000, /* D7FC */ +0xFBC1,0xD7FF,0x0000 }; + +uint16 uca520_p0F9[]= { /* F900 (3 weights per char) */ +0xFB41,0x8C48,0x0000, 0xFB40,0xE6F4,0x0000, 0xFB41,0x8ECA,0x0000, /* F900 */ +0xFB41,0x8CC8,0x0000, 0xFB40,0xEED1,0x0000, 0xFB40,0xCE32,0x0000, /* F903 */ +0xFB40,0xD3E5,0x0000, 0xFB41,0x9F9C,0x0000, 0xFB41,0x9F9C,0x0000, /* F906 */ +0xFB40,0xD951,0x0000, 0xFB41,0x91D1,0x0000, 0xFB40,0xD587,0x0000, /* F909 */ +0xFB40,0xD948,0x0000, 0xFB40,0xE1F6,0x0000, 0xFB40,0xF669,0x0000, /* F90C */ +0xFB40,0xFF85,0x0000, 0xFB41,0x863F,0x0000, 0xFB41,0x87BA,0x0000, /* F90F */ +0xFB41,0x88F8,0x0000, 0xFB41,0x908F,0x0000, 0xFB40,0xEA02,0x0000, /* F912 */ +0xFB40,0xED1B,0x0000, 0xFB40,0xF0D9,0x0000, 0xFB40,0xF3DE,0x0000, /* F915 */ +0xFB41,0x843D,0x0000, 0xFB41,0x916A,0x0000, 0xFB41,0x99F1,0x0000, /* F918 */ +0xFB40,0xCE82,0x0000, 0xFB40,0xD375,0x0000, 0xFB40,0xEB04,0x0000, /* F91B */ +0xFB40,0xF21B,0x0000, 0xFB41,0x862D,0x0000, 0xFB41,0x9E1E,0x0000, /* F91E */ +0xFB40,0xDD50,0x0000, 0xFB40,0xEFEB,0x0000, 0xFB41,0x85CD,0x0000, /* F921 */ +0xFB41,0x8964,0x0000, 0xFB40,0xE2C9,0x0000, 0xFB41,0x81D8,0x0000, /* F924 */ +0xFB41,0x881F,0x0000, 0xFB40,0xDECA,0x0000, 0xFB40,0xE717,0x0000, /* F927 */ +0xFB40,0xED6A,0x0000, 0xFB40,0xF2FC,0x0000, 0xFB41,0x90CE,0x0000, /* F92A */ +0xFB40,0xCF86,0x0000, 0xFB40,0xD1B7,0x0000, 0xFB40,0xD2DE,0x0000, /* F92D */ +0xFB40,0xE4C4,0x0000, 0xFB40,0xEAD3,0x0000, 0xFB40,0xF210,0x0000, /* F930 */ +0xFB40,0xF6E7,0x0000, 0xFB41,0x8001,0x0000, 0xFB41,0x8606,0x0000, /* F933 */ +0xFB41,0x865C,0x0000, 0xFB41,0x8DEF,0x0000, 0xFB41,0x9732,0x0000, /* F936 */ +0xFB41,0x9B6F,0x0000, 0xFB41,0x9DFA,0x0000, 0xFB40,0xF88C,0x0000, /* F939 */ +0xFB40,0xF97F,0x0000, 0xFB40,0xFDA0,0x0000, 0xFB41,0x83C9,0x0000, /* F93C */ +0xFB41,0x9304,0x0000, 0xFB41,0x9E7F,0x0000, 0xFB41,0x8AD6,0x0000, /* F93F */ +0xFB40,0xD8DF,0x0000, 0xFB40,0xDF04,0x0000, 0xFB40,0xFC60,0x0000, /* F942 */ +0xFB41,0x807E,0x0000, 0xFB40,0xF262,0x0000, 0xFB40,0xF8CA,0x0000, /* F945 */ +0xFB41,0x8CC2,0x0000, 0xFB41,0x96F7,0x0000, 0xFB40,0xD8D8,0x0000, /* F948 */ +0xFB40,0xDC62,0x0000, 0xFB40,0xEA13,0x0000, 0xFB40,0xEDDA,0x0000, /* F94B */ +0xFB40,0xEF0F,0x0000, 0xFB40,0xFD2F,0x0000, 0xFB40,0xFE37,0x0000, /* F94E */ +0xFB41,0x964B,0x0000, 0xFB40,0xD2D2,0x0000, 0xFB41,0x808B,0x0000, /* F951 */ +0xFB40,0xD1DC,0x0000, 0xFB40,0xD1CC,0x0000, 0xFB40,0xFA1C,0x0000, /* F954 */ +0xFB40,0xFDBE,0x0000, 0xFB41,0x83F1,0x0000, 0xFB41,0x9675,0x0000, /* F957 */ +0xFB41,0x8B80,0x0000, 0xFB40,0xE2CF,0x0000, 0xFB40,0xEA02,0x0000, /* F95A */ +0xFB41,0x8AFE,0x0000, 0xFB40,0xCE39,0x0000, 0xFB40,0xDBE7,0x0000, /* F95D */ +0xFB40,0xE012,0x0000, 0xFB40,0xF387,0x0000, 0xFB40,0xF570,0x0000, /* F960 */ +0xFB40,0xD317,0x0000, 0xFB40,0xF8FB,0x0000, 0xFB40,0xCFBF,0x0000, /* F963 */ +0xFB40,0xDFA9,0x0000, 0xFB40,0xCE0D,0x0000, 0xFB40,0xECCC,0x0000, /* F966 */ +0xFB40,0xE578,0x0000, 0xFB40,0xFD22,0x0000, 0xFB40,0xD3C3,0x0000, /* F969 */ +0xFB40,0xD85E,0x0000, 0xFB40,0xF701,0x0000, 0xFB41,0x8449,0x0000, /* F96C */ +0xFB41,0x8AAA,0x0000, 0xFB40,0xEBBA,0x0000, 0xFB41,0x8FB0,0x0000, /* F96F */ +0xFB40,0xEC88,0x0000, 0xFB40,0xE2FE,0x0000, 0xFB41,0x82E5,0x0000, /* F972 */ +0xFB40,0xE3A0,0x0000, 0xFB40,0xF565,0x0000, 0xFB40,0xCEAE,0x0000, /* F975 */ +0xFB40,0xD169,0x0000, 0xFB40,0xD1C9,0x0000, 0xFB40,0xE881,0x0000, /* F978 */ +0xFB40,0xFCE7,0x0000, 0xFB41,0x826F,0x0000, 0xFB41,0x8AD2,0x0000, /* F97B */ +0xFB41,0x91CF,0x0000, 0xFB40,0xD2F5,0x0000, 0xFB40,0xD442,0x0000, /* F97E */ +0xFB40,0xD973,0x0000, 0xFB40,0xDEEC,0x0000, 0xFB40,0xE5C5,0x0000, /* F981 */ +0xFB40,0xEFFE,0x0000, 0xFB40,0xF92A,0x0000, 0xFB41,0x95AD,0x0000, /* F984 */ +0xFB41,0x9A6A,0x0000, 0xFB41,0x9E97,0x0000, 0xFB41,0x9ECE,0x0000, /* F987 */ +0xFB40,0xD29B,0x0000, 0xFB40,0xE6C6,0x0000, 0xFB40,0xEB77,0x0000, /* F98A */ +0xFB41,0x8F62,0x0000, 0xFB40,0xDE74,0x0000, 0xFB40,0xE190,0x0000, /* F98D */ +0xFB40,0xE200,0x0000, 0xFB40,0xE49A,0x0000, 0xFB40,0xEF23,0x0000, /* F990 */ +0xFB40,0xF149,0x0000, 0xFB40,0xF489,0x0000, 0xFB40,0xF9CA,0x0000, /* F993 */ +0xFB40,0xFDF4,0x0000, 0xFB41,0x806F,0x0000, 0xFB41,0x8F26,0x0000, /* F996 */ +0xFB41,0x84EE,0x0000, 0xFB41,0x9023,0x0000, 0xFB41,0x934A,0x0000, /* F999 */ +0xFB40,0xD217,0x0000, 0xFB40,0xD2A3,0x0000, 0xFB40,0xD4BD,0x0000, /* F99C */ +0xFB40,0xF0C8,0x0000, 0xFB41,0x88C2,0x0000, 0xFB41,0x8AAA,0x0000, /* F99F */ +0xFB40,0xDEC9,0x0000, 0xFB40,0xDFF5,0x0000, 0xFB40,0xE37B,0x0000, /* F9A2 */ +0xFB40,0xEBAE,0x0000, 0xFB40,0xFC3E,0x0000, 0xFB40,0xF375,0x0000, /* F9A5 */ +0xFB40,0xCEE4,0x0000, 0xFB40,0xD6F9,0x0000, 0xFB40,0xDBE7,0x0000, /* F9A8 */ +0xFB40,0xDDBA,0x0000, 0xFB40,0xE01C,0x0000, 0xFB40,0xF3B2,0x0000, /* F9AB */ +0xFB40,0xF469,0x0000, 0xFB40,0xFF9A,0x0000, 0xFB41,0x8046,0x0000, /* F9AE */ +0xFB41,0x9234,0x0000, 0xFB41,0x96F6,0x0000, 0xFB41,0x9748,0x0000, /* F9B1 */ +0xFB41,0x9818,0x0000, 0xFB40,0xCF8B,0x0000, 0xFB40,0xF9AE,0x0000, /* F9B4 */ +0xFB41,0x91B4,0x0000, 0xFB41,0x96B8,0x0000, 0xFB40,0xE0E1,0x0000, /* F9B7 */ +0xFB40,0xCE86,0x0000, 0xFB40,0xD0DA,0x0000, 0xFB40,0xDBEE,0x0000, /* F9BA */ +0xFB40,0xDC3F,0x0000, 0xFB40,0xE599,0x0000, 0xFB40,0xEA02,0x0000, /* F9BD */ +0xFB40,0xF1CE,0x0000, 0xFB40,0xF642,0x0000, 0xFB41,0x84FC,0x0000, /* F9C0 */ +0xFB41,0x907C,0x0000, 0xFB41,0x9F8D,0x0000, 0xFB40,0xE688,0x0000, /* F9C3 */ +0xFB41,0x962E,0x0000, 0xFB40,0xD289,0x0000, 0xFB40,0xE77B,0x0000, /* F9C6 */ +0xFB40,0xE7F3,0x0000, 0xFB40,0xED41,0x0000, 0xFB40,0xEE9C,0x0000, /* F9C9 */ +0xFB40,0xF409,0x0000, 0xFB40,0xF559,0x0000, 0xFB40,0xF86B,0x0000, /* F9CC */ +0xFB40,0xFD10,0x0000, 0xFB41,0x985E,0x0000, 0xFB40,0xD16D,0x0000, /* F9CF */ +0xFB40,0xE22E,0x0000, 0xFB41,0x9678,0x0000, 0xFB40,0xD02B,0x0000, /* F9D2 */ +0xFB40,0xDD19,0x0000, 0xFB40,0xEDEA,0x0000, 0xFB41,0x8F2A,0x0000, /* F9D5 */ +0xFB40,0xDF8B,0x0000, 0xFB40,0xE144,0x0000, 0xFB40,0xE817,0x0000, /* F9D8 */ +0xFB40,0xF387,0x0000, 0xFB41,0x9686,0x0000, 0xFB40,0xD229,0x0000, /* F9DB */ +0xFB40,0xD40F,0x0000, 0xFB40,0xDC65,0x0000, 0xFB40,0xE613,0x0000, /* F9DE */ +0xFB40,0xE74E,0x0000, 0xFB40,0xE8A8,0x0000, 0xFB40,0xECE5,0x0000, /* F9E1 */ +0xFB40,0xF406,0x0000, 0xFB40,0xF5E2,0x0000, 0xFB40,0xFF79,0x0000, /* F9E4 */ +0xFB41,0x88CF,0x0000, 0xFB41,0x88E1,0x0000, 0xFB41,0x91CC,0x0000, /* F9E7 */ +0xFB41,0x96E2,0x0000, 0xFB40,0xD33F,0x0000, 0xFB40,0xEEBA,0x0000, /* F9EA */ +0xFB40,0xD41D,0x0000, 0xFB40,0xF1D0,0x0000, 0xFB40,0xF498,0x0000, /* F9ED */ +0xFB41,0x85FA,0x0000, 0xFB41,0x96A3,0x0000, 0xFB41,0x9C57,0x0000, /* F9F0 */ +0xFB41,0x9E9F,0x0000, 0xFB40,0xE797,0x0000, 0xFB40,0xEDCB,0x0000, /* F9F3 */ +0xFB41,0x81E8,0x0000, 0xFB40,0xFACB,0x0000, 0xFB40,0xFB20,0x0000, /* F9F6 */ +0xFB40,0xFC92,0x0000, 0xFB40,0xF2C0,0x0000, 0xFB40,0xF099,0x0000, /* F9F9 */ +0xFB41,0x8B58,0x0000, 0xFB40,0xCEC0,0x0000, 0xFB41,0x8336,0x0000, /* F9FC */ +0xFB40,0xD23A,0x0000 }; + +uint16 uca520_p0FA[]= { /* FA00 (3 weights per char) */ +0xFB40,0xD207,0x0000, 0xFB40,0xDEA6,0x0000, 0xFB40,0xE2D3,0x0000, /* FA00 */ +0xFB40,0xFCD6,0x0000, 0xFB40,0xDB85,0x0000, 0xFB40,0xED1E,0x0000, /* FA03 */ +0xFB40,0xE6B4,0x0000, 0xFB41,0x8F3B,0x0000, 0xFB41,0x884C,0x0000, /* FA06 */ +0xFB41,0x964D,0x0000, 0xFB41,0x898B,0x0000, 0xFB40,0xDED3,0x0000, /* FA09 */ +0xFB40,0xD140,0x0000, 0xFB40,0xD5C0,0x0000, 0xFB41,0xFA0E,0x0000, /* FA0C */ +0xFB41,0xFA0F,0x0000, 0xFB40,0xD85A,0x0000, 0xFB41,0xFA11,0x0000, /* FA0F */ +0xFB40,0xE674,0x0000, 0xFB41,0xFA13,0x0000, 0xFB41,0xFA14,0x0000, /* FA12 */ +0xFB40,0xD1DE,0x0000, 0xFB40,0xF32A,0x0000, 0xFB40,0xF6CA,0x0000, /* FA15 */ +0xFB40,0xF93C,0x0000, 0xFB40,0xF95E,0x0000, 0xFB40,0xF965,0x0000, /* FA18 */ +0xFB40,0xF98F,0x0000, 0xFB41,0x9756,0x0000, 0xFB40,0xFCBE,0x0000, /* FA1B */ +0xFB40,0xFFBD,0x0000, 0xFB41,0xFA1F,0x0000, 0xFB41,0x8612,0x0000, /* FA1E */ +0xFB41,0xFA21,0x0000, 0xFB41,0x8AF8,0x0000, 0xFB41,0xFA23,0x0000, /* FA21 */ +0xFB41,0xFA24,0x0000, 0xFB41,0x9038,0x0000, 0xFB41,0x90FD,0x0000, /* FA24 */ +0xFB41,0xFA27,0x0000, 0xFB41,0xFA28,0x0000, 0xFB41,0xFA29,0x0000, /* FA27 */ +0xFB41,0x98EF,0x0000, 0xFB41,0x98FC,0x0000, 0xFB41,0x9928,0x0000, /* FA2A */ +0xFB41,0x9DB4,0x0000, 0xFBC1,0xFA2E,0x0000, 0xFBC1,0xFA2F,0x0000, /* FA2D */ +0xFB40,0xCFAE,0x0000, 0xFB40,0xD0E7,0x0000, 0xFB40,0xD14D,0x0000, /* FA30 */ +0xFB40,0xD2C9,0x0000, 0xFB40,0xD2E4,0x0000, 0xFB40,0xD351,0x0000, /* FA33 */ +0xFB40,0xD59D,0x0000, 0xFB40,0xD606,0x0000, 0xFB40,0xD668,0x0000, /* FA36 */ +0xFB40,0xD840,0x0000, 0xFB40,0xD8A8,0x0000, 0xFB40,0xDC64,0x0000, /* FA39 */ +0xFB40,0xDC6E,0x0000, 0xFB40,0xE094,0x0000, 0xFB40,0xE168,0x0000, /* FA3C */ +0xFB40,0xE18E,0x0000, 0xFB40,0xE1F2,0x0000, 0xFB40,0xE54F,0x0000, /* FA3F */ +0xFB40,0xE5E2,0x0000, 0xFB40,0xE691,0x0000, 0xFB40,0xE885,0x0000, /* FA42 */ +0xFB40,0xED77,0x0000, 0xFB40,0xEE1A,0x0000, 0xFB40,0xEF22,0x0000, /* FA45 */ +0xFB40,0xF16E,0x0000, 0xFB40,0xF22B,0x0000, 0xFB40,0xF422,0x0000, /* FA48 */ +0xFB40,0xF891,0x0000, 0xFB40,0xF93E,0x0000, 0xFB40,0xF949,0x0000, /* FA4B */ +0xFB40,0xF948,0x0000, 0xFB40,0xF950,0x0000, 0xFB40,0xF956,0x0000, /* FA4E */ +0xFB40,0xF95D,0x0000, 0xFB40,0xF98D,0x0000, 0xFB40,0xF98E,0x0000, /* FA51 */ +0xFB40,0xFA40,0x0000, 0xFB40,0xFA81,0x0000, 0xFB40,0xFBC0,0x0000, /* FA54 */ +0xFB40,0xFDF4,0x0000, 0xFB40,0xFE09,0x0000, 0xFB40,0xFE41,0x0000, /* FA57 */ +0xFB40,0xFF72,0x0000, 0xFB41,0x8005,0x0000, 0xFB41,0x81ED,0x0000, /* FA5A */ +0xFB41,0x8279,0x0000, 0xFB41,0x8279,0x0000, 0xFB41,0x8457,0x0000, /* FA5D */ +0xFB41,0x8910,0x0000, 0xFB41,0x8996,0x0000, 0xFB41,0x8B01,0x0000, /* FA60 */ +0xFB41,0x8B39,0x0000, 0xFB41,0x8CD3,0x0000, 0xFB41,0x8D08,0x0000, /* FA63 */ +0xFB41,0x8FB6,0x0000, 0xFB41,0x9038,0x0000, 0xFB41,0x96E3,0x0000, /* FA66 */ +0xFB41,0x97FF,0x0000, 0xFB41,0x983B,0x0000, 0xFB40,0xE075,0x0000, /* FA69 */ +0xFB84,0xC2EE,0x0000, 0xFB41,0x8218,0x0000, 0xFBC1,0xFA6E,0x0000, /* FA6C */ +0xFBC1,0xFA6F,0x0000, 0xFB40,0xCE26,0x0000, 0xFB40,0xD1B5,0x0000, /* FA6F */ +0xFB40,0xD168,0x0000, 0xFB40,0xCF80,0x0000, 0xFB40,0xD145,0x0000, /* FA72 */ +0xFB40,0xD180,0x0000, 0xFB40,0xD2C7,0x0000, 0xFB40,0xD2FA,0x0000, /* FA75 */ +0xFB40,0xD59D,0x0000, 0xFB40,0xD555,0x0000, 0xFB40,0xD599,0x0000, /* FA78 */ +0xFB40,0xD5E2,0x0000, 0xFB40,0xD85A,0x0000, 0xFB40,0xD8B3,0x0000, /* FA7B */ +0xFB40,0xD944,0x0000, 0xFB40,0xD954,0x0000, 0xFB40,0xDA62,0x0000, /* FA7E */ +0xFB40,0xDB28,0x0000, 0xFB40,0xDED2,0x0000, 0xFB40,0xDED9,0x0000, /* FA81 */ +0xFB40,0xDF69,0x0000, 0xFB40,0xDFAD,0x0000, 0xFB40,0xE0D8,0x0000, /* FA84 */ +0xFB40,0xE14E,0x0000, 0xFB40,0xE108,0x0000, 0xFB40,0xE18E,0x0000, /* FA87 */ +0xFB40,0xE160,0x0000, 0xFB40,0xE1F2,0x0000, 0xFB40,0xE234,0x0000, /* FA8A */ +0xFB40,0xE3C4,0x0000, 0xFB40,0xE41C,0x0000, 0xFB40,0xE452,0x0000, /* FA8D */ +0xFB40,0xE556,0x0000, 0xFB40,0xE674,0x0000, 0xFB40,0xE717,0x0000, /* FA90 */ +0xFB40,0xE71B,0x0000, 0xFB40,0xE756,0x0000, 0xFB40,0xEB79,0x0000, /* FA93 */ +0xFB40,0xEBBA,0x0000, 0xFB40,0xED41,0x0000, 0xFB40,0xEEDB,0x0000, /* FA96 */ +0xFB40,0xEECB,0x0000, 0xFB40,0xEF22,0x0000, 0xFB40,0xF01E,0x0000, /* FA99 */ +0xFB40,0xF16E,0x0000, 0xFB40,0xF7A7,0x0000, 0xFB40,0xF235,0x0000, /* FA9C */ +0xFB40,0xF2AF,0x0000, 0xFB40,0xF32A,0x0000, 0xFB40,0xF471,0x0000, /* FA9F */ +0xFB40,0xF506,0x0000, 0xFB40,0xF53B,0x0000, 0xFB40,0xF61D,0x0000, /* FAA2 */ +0xFB40,0xF61F,0x0000, 0xFB40,0xF6CA,0x0000, 0xFB40,0xF6DB,0x0000, /* FAA5 */ +0xFB40,0xF6F4,0x0000, 0xFB40,0xF74A,0x0000, 0xFB40,0xF740,0x0000, /* FAA8 */ +0xFB40,0xF8CC,0x0000, 0xFB40,0xFAB1,0x0000, 0xFB40,0xFBC0,0x0000, /* FAAB */ +0xFB40,0xFC7B,0x0000, 0xFB40,0xFD5B,0x0000, 0xFB40,0xFDF4,0x0000, /* FAAE */ +0xFB40,0xFF3E,0x0000, 0xFB41,0x8005,0x0000, 0xFB41,0x8352,0x0000, /* FAB1 */ +0xFB41,0x83EF,0x0000, 0xFB41,0x8779,0x0000, 0xFB41,0x8941,0x0000, /* FAB4 */ +0xFB41,0x8986,0x0000, 0xFB41,0x8996,0x0000, 0xFB41,0x8ABF,0x0000, /* FAB7 */ +0xFB41,0x8AF8,0x0000, 0xFB41,0x8ACB,0x0000, 0xFB41,0x8B01,0x0000, /* FABA */ +0xFB41,0x8AFE,0x0000, 0xFB41,0x8AED,0x0000, 0xFB41,0x8B39,0x0000, /* FABD */ +0xFB41,0x8B8A,0x0000, 0xFB41,0x8D08,0x0000, 0xFB41,0x8F38,0x0000, /* FAC0 */ +0xFB41,0x9072,0x0000, 0xFB41,0x9199,0x0000, 0xFB41,0x9276,0x0000, /* FAC3 */ +0xFB41,0x967C,0x0000, 0xFB41,0x96E3,0x0000, 0xFB41,0x9756,0x0000, /* FAC6 */ +0xFB41,0x97DB,0x0000, 0xFB41,0x97FF,0x0000, 0xFB41,0x980B,0x0000, /* FAC9 */ +0xFB41,0x983B,0x0000, 0xFB41,0x9B12,0x0000, 0xFB41,0x9F9C,0x0000, /* FACC */ +0xFB84,0xA84A,0x0000, 0xFB84,0xA844,0x0000, 0xFB84,0xB3D5,0x0000, /* FACF */ +0xFB80,0xBB9D,0x0000, 0xFB80,0xC018,0x0000, 0xFB80,0xC039,0x0000, /* FAD2 */ +0xFB84,0xD249,0x0000, 0xFB84,0xDCD0,0x0000, 0xFB84,0xFED3,0x0000, /* FAD5 */ +0xFB41,0x9F43,0x0000, 0xFB41,0x9F8E,0x0000, 0xFBC1,0xFADA,0x0000, /* FAD8 */ +0xFBC1,0xFADB,0x0000, 0xFBC1,0xFADC,0x0000, 0xFBC1,0xFADD,0x0000, /* FADB */ +0xFBC1,0xFADE,0x0000, 0xFBC1,0xFADF,0x0000, 0xFBC1,0xFAE0,0x0000, /* FADE */ +0xFBC1,0xFAE1,0x0000, 0xFBC1,0xFAE2,0x0000, 0xFBC1,0xFAE3,0x0000, /* FAE1 */ +0xFBC1,0xFAE4,0x0000, 0xFBC1,0xFAE5,0x0000, 0xFBC1,0xFAE6,0x0000, /* FAE4 */ +0xFBC1,0xFAE7,0x0000, 0xFBC1,0xFAE8,0x0000, 0xFBC1,0xFAE9,0x0000, /* FAE7 */ +0xFBC1,0xFAEA,0x0000, 0xFBC1,0xFAEB,0x0000, 0xFBC1,0xFAEC,0x0000, /* FAEA */ +0xFBC1,0xFAED,0x0000, 0xFBC1,0xFAEE,0x0000, 0xFBC1,0xFAEF,0x0000, /* FAED */ +0xFBC1,0xFAF0,0x0000, 0xFBC1,0xFAF1,0x0000, 0xFBC1,0xFAF2,0x0000, /* FAF0 */ +0xFBC1,0xFAF3,0x0000, 0xFBC1,0xFAF4,0x0000, 0xFBC1,0xFAF5,0x0000, /* FAF3 */ +0xFBC1,0xFAF6,0x0000, 0xFBC1,0xFAF7,0x0000, 0xFBC1,0xFAF8,0x0000, /* FAF6 */ +0xFBC1,0xFAF9,0x0000, 0xFBC1,0xFAFA,0x0000, 0xFBC1,0xFAFB,0x0000, /* FAF9 */ +0xFBC1,0xFAFC,0x0000, 0xFBC1,0xFAFD,0x0000, 0xFBC1,0xFAFE,0x0000, /* FAFC */ +0xFBC1,0xFAFF,0x0000 }; + +uint16 uca520_p0FB[]= { /* FB00 (4 weights per char) */ +0x12A3,0x12A3,0x0000,0x0000, 0x12A3,0x12EC,0x0000,0x0000, /* FB00 */ +0x12A3,0x1330,0x0000,0x0000, 0x12A3,0x12A3,0x12EC,0x0000, /* FB02 */ +0x12A3,0x12A3,0x1330,0x0000, 0x1410,0x1433,0x0000,0x0000, /* FB04 */ +0x1410,0x1433,0x0000,0x0000, 0xFBC1,0xFB07,0x0000,0x0000, /* FB06 */ +0xFBC1,0xFB08,0x0000,0x0000, 0xFBC1,0xFB09,0x0000,0x0000, /* FB08 */ +0xFBC1,0xFB0A,0x0000,0x0000, 0xFBC1,0xFB0B,0x0000,0x0000, /* FB0A */ +0xFBC1,0xFB0C,0x0000,0x0000, 0xFBC1,0xFB0D,0x0000,0x0000, /* FB0C */ +0xFBC1,0xFB0E,0x0000,0x0000, 0xFBC1,0xFB0F,0x0000,0x0000, /* FB0E */ +0xFBC1,0xFB10,0x0000,0x0000, 0xFBC1,0xFB11,0x0000,0x0000, /* FB10 */ +0xFBC1,0xFB12,0x0000,0x0000, 0x1848,0x184A,0x0000,0x0000, /* FB12 */ +0x1848,0x1839,0x0000,0x0000, 0x1848,0x183F,0x0000,0x0000, /* FB14 */ +0x1852,0x184A,0x0000,0x0000, 0x1848,0x1841,0x0000,0x0000, /* FB16 */ +0xFBC1,0xFB18,0x0000,0x0000, 0xFBC1,0xFB19,0x0000,0x0000, /* FB18 */ +0xFBC1,0xFB1A,0x0000,0x0000, 0xFBC1,0xFB1B,0x0000,0x0000, /* FB1A */ +0xFBC1,0xFB1C,0x0000,0x0000, 0x1865,0x0000,0x0000,0x0000, /* FB1C */ +0x0000,0x0000,0x0000,0x0000, 0x1865,0x1865,0x0000,0x0000, /* FB1E */ +0x186B,0x0000,0x0000,0x0000, 0x185C,0x0000,0x0000,0x0000, /* FB20 */ +0x185F,0x0000,0x0000,0x0000, 0x1860,0x0000,0x0000,0x0000, /* FB22 */ +0x1866,0x0000,0x0000,0x0000, 0x1867,0x0000,0x0000,0x0000, /* FB24 */ +0x1868,0x0000,0x0000,0x0000, 0x186F,0x0000,0x0000,0x0000, /* FB26 */ +0x1871,0x0000,0x0000,0x0000, 0x0550,0x0000,0x0000,0x0000, /* FB28 */ +0x1870,0x0000,0x0000,0x0000, 0x1870,0x0000,0x0000,0x0000, /* FB2A */ +0x1870,0x0000,0x0000,0x0000, 0x1870,0x0000,0x0000,0x0000, /* FB2C */ +0x185C,0x0000,0x0000,0x0000, 0x185C,0x0000,0x0000,0x0000, /* FB2E */ +0x185C,0x0000,0x0000,0x0000, 0x185D,0x0000,0x0000,0x0000, /* FB30 */ +0x185E,0x0000,0x0000,0x0000, 0x185F,0x0000,0x0000,0x0000, /* FB32 */ +0x1860,0x0000,0x0000,0x0000, 0x1861,0x0000,0x0000,0x0000, /* FB34 */ +0x1862,0x0000,0x0000,0x0000, 0xFBC1,0xFB37,0x0000,0x0000, /* FB36 */ +0x1864,0x0000,0x0000,0x0000, 0x1865,0x0000,0x0000,0x0000, /* FB38 */ +0x1866,0x0000,0x0000,0x0000, 0x1866,0x0000,0x0000,0x0000, /* FB3A */ +0x1867,0x0000,0x0000,0x0000, 0xFBC1,0xFB3D,0x0000,0x0000, /* FB3C */ +0x1868,0x0000,0x0000,0x0000, 0xFBC1,0xFB3F,0x0000,0x0000, /* FB3E */ +0x1869,0x0000,0x0000,0x0000, 0x186A,0x0000,0x0000,0x0000, /* FB40 */ +0xFBC1,0xFB42,0x0000,0x0000, 0x186C,0x0000,0x0000,0x0000, /* FB42 */ +0x186C,0x0000,0x0000,0x0000, 0xFBC1,0xFB45,0x0000,0x0000, /* FB44 */ +0x186D,0x0000,0x0000,0x0000, 0x186E,0x0000,0x0000,0x0000, /* FB46 */ +0x186F,0x0000,0x0000,0x0000, 0x1870,0x0000,0x0000,0x0000, /* FB48 */ +0x1871,0x0000,0x0000,0x0000, 0x1861,0x0000,0x0000,0x0000, /* FB4A */ +0x185D,0x0000,0x0000,0x0000, 0x1866,0x0000,0x0000,0x0000, /* FB4C */ +0x186C,0x0000,0x0000,0x0000, 0x185C,0x1867,0x0000,0x0000, /* FB4E */ +0x18A6,0x0000,0x0000,0x0000, 0x18A6,0x0000,0x0000,0x0000, /* FB50 */ +0x18B0,0x0000,0x0000,0x0000, 0x18B0,0x0000,0x0000,0x0000, /* FB52 */ +0x18B0,0x0000,0x0000,0x0000, 0x18B0,0x0000,0x0000,0x0000, /* FB54 */ +0x18B1,0x0000,0x0000,0x0000, 0x18B1,0x0000,0x0000,0x0000, /* FB56 */ +0x18B1,0x0000,0x0000,0x0000, 0x18B1,0x0000,0x0000,0x0000, /* FB58 */ +0x18B2,0x0000,0x0000,0x0000, 0x18B2,0x0000,0x0000,0x0000, /* FB5A */ +0x18B2,0x0000,0x0000,0x0000, 0x18B2,0x0000,0x0000,0x0000, /* FB5C */ +0x18BE,0x0000,0x0000,0x0000, 0x18BE,0x0000,0x0000,0x0000, /* FB5E */ +0x18BE,0x0000,0x0000,0x0000, 0x18BE,0x0000,0x0000,0x0000, /* FB60 */ +0x18C1,0x0000,0x0000,0x0000, 0x18C1,0x0000,0x0000,0x0000, /* FB62 */ +0x18C1,0x0000,0x0000,0x0000, 0x18C1,0x0000,0x0000,0x0000, /* FB64 */ +0x18BD,0x0000,0x0000,0x0000, 0x18BD,0x0000,0x0000,0x0000, /* FB66 */ +0x18BD,0x0000,0x0000,0x0000, 0x18BD,0x0000,0x0000,0x0000, /* FB68 */ +0x190F,0x0000,0x0000,0x0000, 0x190F,0x0000,0x0000,0x0000, /* FB6A */ +0x190F,0x0000,0x0000,0x0000, 0x190F,0x0000,0x0000,0x0000, /* FB6C */ +0x1911,0x0000,0x0000,0x0000, 0x1911,0x0000,0x0000,0x0000, /* FB6E */ +0x1911,0x0000,0x0000,0x0000, 0x1911,0x0000,0x0000,0x0000, /* FB70 */ +0x18C4,0x0000,0x0000,0x0000, 0x18C4,0x0000,0x0000,0x0000, /* FB72 */ +0x18C4,0x0000,0x0000,0x0000, 0x18C4,0x0000,0x0000,0x0000, /* FB74 */ +0x18C3,0x0000,0x0000,0x0000, 0x18C3,0x0000,0x0000,0x0000, /* FB76 */ +0x18C3,0x0000,0x0000,0x0000, 0x18C3,0x0000,0x0000,0x0000, /* FB78 */ +0x18C5,0x0000,0x0000,0x0000, 0x18C5,0x0000,0x0000,0x0000, /* FB7A */ +0x18C5,0x0000,0x0000,0x0000, 0x18C5,0x0000,0x0000,0x0000, /* FB7C */ +0x18C7,0x0000,0x0000,0x0000, 0x18C7,0x0000,0x0000,0x0000, /* FB7E */ +0x18C7,0x0000,0x0000,0x0000, 0x18C7,0x0000,0x0000,0x0000, /* FB80 */ +0x18DA,0x0000,0x0000,0x0000, 0x18DA,0x0000,0x0000,0x0000, /* FB82 */ +0x18D9,0x0000,0x0000,0x0000, 0x18D9,0x0000,0x0000,0x0000, /* FB84 */ +0x18DB,0x0000,0x0000,0x0000, 0x18DB,0x0000,0x0000,0x0000, /* FB86 */ +0x18D5,0x0000,0x0000,0x0000, 0x18D5,0x0000,0x0000,0x0000, /* FB88 */ +0x18EA,0x0000,0x0000,0x0000, 0x18EA,0x0000,0x0000,0x0000, /* FB8A */ +0x18E3,0x0000,0x0000,0x0000, 0x18E3,0x0000,0x0000,0x0000, /* FB8C */ +0x1919,0x0000,0x0000,0x0000, 0x1919,0x0000,0x0000,0x0000, /* FB8E */ +0x1919,0x0000,0x0000,0x0000, 0x1919,0x0000,0x0000,0x0000, /* FB90 */ +0x1920,0x0000,0x0000,0x0000, 0x1920,0x0000,0x0000,0x0000, /* FB92 */ +0x1920,0x0000,0x0000,0x0000, 0x1920,0x0000,0x0000,0x0000, /* FB94 */ +0x1924,0x0000,0x0000,0x0000, 0x1924,0x0000,0x0000,0x0000, /* FB96 */ +0x1924,0x0000,0x0000,0x0000, 0x1924,0x0000,0x0000,0x0000, /* FB98 */ +0x1922,0x0000,0x0000,0x0000, 0x1922,0x0000,0x0000,0x0000, /* FB9A */ +0x1922,0x0000,0x0000,0x0000, 0x1922,0x0000,0x0000,0x0000, /* FB9C */ +0x1935,0x0000,0x0000,0x0000, 0x1935,0x0000,0x0000,0x0000, /* FB9E */ +0x1936,0x0000,0x0000,0x0000, 0x1936,0x0000,0x0000,0x0000, /* FBA0 */ +0x1936,0x0000,0x0000,0x0000, 0x1936,0x0000,0x0000,0x0000, /* FBA2 */ +0x1942,0x0000,0x0000,0x0000, 0x1942,0x0000,0x0000,0x0000, /* FBA4 */ +0x193F,0x0000,0x0000,0x0000, 0x193F,0x0000,0x0000,0x0000, /* FBA6 */ +0x193F,0x0000,0x0000,0x0000, 0x193F,0x0000,0x0000,0x0000, /* FBA8 */ +0x193E,0x0000,0x0000,0x0000, 0x193E,0x0000,0x0000,0x0000, /* FBAA */ +0x193E,0x0000,0x0000,0x0000, 0x193E,0x0000,0x0000,0x0000, /* FBAC */ +0x195C,0x0000,0x0000,0x0000, 0x195C,0x0000,0x0000,0x0000, /* FBAE */ +0x195C,0x0000,0x0000,0x0000, 0x195C,0x0000,0x0000,0x0000, /* FBB0 */ +0xFBC1,0xFBB2,0x0000,0x0000, 0xFBC1,0xFBB3,0x0000,0x0000, /* FBB2 */ +0xFBC1,0xFBB4,0x0000,0x0000, 0xFBC1,0xFBB5,0x0000,0x0000, /* FBB4 */ +0xFBC1,0xFBB6,0x0000,0x0000, 0xFBC1,0xFBB7,0x0000,0x0000, /* FBB6 */ +0xFBC1,0xFBB8,0x0000,0x0000, 0xFBC1,0xFBB9,0x0000,0x0000, /* FBB8 */ +0xFBC1,0xFBBA,0x0000,0x0000, 0xFBC1,0xFBBB,0x0000,0x0000, /* FBBA */ +0xFBC1,0xFBBC,0x0000,0x0000, 0xFBC1,0xFBBD,0x0000,0x0000, /* FBBC */ +0xFBC1,0xFBBE,0x0000,0x0000, 0xFBC1,0xFBBF,0x0000,0x0000, /* FBBE */ +0xFBC1,0xFBC0,0x0000,0x0000, 0xFBC1,0xFBC1,0x0000,0x0000, /* FBC0 */ +0xFBC1,0xFBC2,0x0000,0x0000, 0xFBC1,0xFBC3,0x0000,0x0000, /* FBC2 */ +0xFBC1,0xFBC4,0x0000,0x0000, 0xFBC1,0xFBC5,0x0000,0x0000, /* FBC4 */ +0xFBC1,0xFBC6,0x0000,0x0000, 0xFBC1,0xFBC7,0x0000,0x0000, /* FBC6 */ +0xFBC1,0xFBC8,0x0000,0x0000, 0xFBC1,0xFBC9,0x0000,0x0000, /* FBC8 */ +0xFBC1,0xFBCA,0x0000,0x0000, 0xFBC1,0xFBCB,0x0000,0x0000, /* FBCA */ +0xFBC1,0xFBCC,0x0000,0x0000, 0xFBC1,0xFBCD,0x0000,0x0000, /* FBCC */ +0xFBC1,0xFBCE,0x0000,0x0000, 0xFBC1,0xFBCF,0x0000,0x0000, /* FBCE */ +0xFBC1,0xFBD0,0x0000,0x0000, 0xFBC1,0xFBD1,0x0000,0x0000, /* FBD0 */ +0xFBC1,0xFBD2,0x0000,0x0000, 0x191E,0x0000,0x0000,0x0000, /* FBD2 */ +0x191E,0x0000,0x0000,0x0000, 0x191E,0x0000,0x0000,0x0000, /* FBD4 */ +0x191E,0x0000,0x0000,0x0000, 0x1947,0x0000,0x0000,0x0000, /* FBD6 */ +0x1947,0x0000,0x0000,0x0000, 0x1946,0x0000,0x0000,0x0000, /* FBD8 */ +0x1946,0x0000,0x0000,0x0000, 0x1948,0x0000,0x0000,0x0000, /* FBDA */ +0x1948,0x0000,0x0000,0x0000, 0x1947,0x18A2,0x0000,0x0000, /* FBDC */ +0x194B,0x0000,0x0000,0x0000, 0x194B,0x0000,0x0000,0x0000, /* FBDE */ +0x1945,0x0000,0x0000,0x0000, 0x1945,0x0000,0x0000,0x0000, /* FBE0 */ +0x1949,0x0000,0x0000,0x0000, 0x1949,0x0000,0x0000,0x0000, /* FBE2 */ +0x1954,0x0000,0x0000,0x0000, 0x1954,0x0000,0x0000,0x0000, /* FBE4 */ +0x1954,0x0000,0x0000,0x0000, 0x1954,0x0000,0x0000,0x0000, /* FBE6 */ +0x194F,0x0000,0x0000,0x0000, 0x194F,0x0000,0x0000,0x0000, /* FBE8 */ +0x18AC,0x18AD,0x0000,0x0000, 0x18AC,0x18AD,0x0000,0x0000, /* FBEA */ +0x18AC,0x1942,0x0000,0x0000, 0x18AC,0x1942,0x0000,0x0000, /* FBEC */ +0x18AC,0x1943,0x0000,0x0000, 0x18AC,0x1943,0x0000,0x0000, /* FBEE */ +0x18AC,0x1947,0x0000,0x0000, 0x18AC,0x1947,0x0000,0x0000, /* FBF0 */ +0x18AC,0x1946,0x0000,0x0000, 0x18AC,0x1946,0x0000,0x0000, /* FBF2 */ +0x18AC,0x1948,0x0000,0x0000, 0x18AC,0x1948,0x0000,0x0000, /* FBF4 */ +0x18AC,0x1954,0x0000,0x0000, 0x18AC,0x1954,0x0000,0x0000, /* FBF6 */ +0x18AC,0x1954,0x0000,0x0000, 0x18AC,0x194F,0x0000,0x0000, /* FBF8 */ +0x18AC,0x194F,0x0000,0x0000, 0x18AC,0x194F,0x0000,0x0000, /* FBFA */ +0x1951,0x0000,0x0000,0x0000, 0x1951,0x0000,0x0000,0x0000, /* FBFC */ +0x1951,0x0000,0x0000,0x0000, 0x1951,0x0000,0x0000,0x0000 /* FBFE */ +}; + +uint16 uca520_p0FC[]= { /* FC00 (3 weights per char) */ +0x18AC,0x18C2,0x0000, 0x18AC,0x18C8,0x0000, 0x18AC,0x1931,0x0000, /* FC00 */ +0x18AC,0x194F,0x0000, 0x18AC,0x1950,0x0000, 0x18AF,0x18C2,0x0000, /* FC03 */ +0x18AF,0x18C8,0x0000, 0x18AF,0x18C9,0x0000, 0x18AF,0x1931,0x0000, /* FC06 */ +0x18AF,0x194F,0x0000, 0x18AF,0x1950,0x0000, 0x18BB,0x18C2,0x0000, /* FC09 */ +0x18BB,0x18C8,0x0000, 0x18BB,0x18C9,0x0000, 0x18BB,0x1931,0x0000, /* FC0C */ +0x18BB,0x194F,0x0000, 0x18BB,0x1950,0x0000, 0x18BC,0x18C2,0x0000, /* FC0F */ +0x18BC,0x1931,0x0000, 0x18BC,0x194F,0x0000, 0x18BC,0x1950,0x0000, /* FC12 */ +0x18C2,0x18C8,0x0000, 0x18C2,0x1931,0x0000, 0x18C8,0x18C2,0x0000, /* FC15 */ +0x18C8,0x1931,0x0000, 0x18C9,0x18C2,0x0000, 0x18C9,0x18C8,0x0000, /* FC18 */ +0x18C9,0x1931,0x0000, 0x18F1,0x18C2,0x0000, 0x18F1,0x18C8,0x0000, /* FC1B */ +0x18F1,0x18C9,0x0000, 0x18F1,0x1931,0x0000, 0x18FC,0x18C8,0x0000, /* FC1E */ +0x18FC,0x1931,0x0000, 0x18FD,0x18C2,0x0000, 0x18FD,0x18C8,0x0000, /* FC21 */ +0x18FD,0x18C9,0x0000, 0x18FD,0x1931,0x0000, 0x1901,0x18C8,0x0000, /* FC24 */ +0x1901,0x1931,0x0000, 0x1902,0x1931,0x0000, 0x1904,0x18C2,0x0000, /* FC27 */ +0x1904,0x1931,0x0000, 0x1905,0x18C2,0x0000, 0x1905,0x1931,0x0000, /* FC2A */ +0x190B,0x18C2,0x0000, 0x190B,0x18C8,0x0000, 0x190B,0x18C9,0x0000, /* FC2D */ +0x190B,0x1931,0x0000, 0x190B,0x194F,0x0000, 0x190B,0x1950,0x0000, /* FC30 */ +0x1915,0x18C8,0x0000, 0x1915,0x1931,0x0000, 0x1915,0x194F,0x0000, /* FC33 */ +0x1915,0x1950,0x0000, 0x1918,0x18AD,0x0000, 0x1918,0x18C2,0x0000, /* FC36 */ +0x1918,0x18C8,0x0000, 0x1918,0x18C9,0x0000, 0x1918,0x192B,0x0000, /* FC39 */ +0x1918,0x1931,0x0000, 0x1918,0x194F,0x0000, 0x1918,0x1950,0x0000, /* FC3C */ +0x192B,0x18C2,0x0000, 0x192B,0x18C8,0x0000, 0x192B,0x18C9,0x0000, /* FC3F */ +0x192B,0x1931,0x0000, 0x192B,0x194F,0x0000, 0x192B,0x1950,0x0000, /* FC42 */ +0x1931,0x18C2,0x0000, 0x1931,0x18C8,0x0000, 0x1931,0x18C9,0x0000, /* FC45 */ +0x1931,0x1931,0x0000, 0x1931,0x194F,0x0000, 0x1931,0x1950,0x0000, /* FC48 */ +0x1934,0x18C2,0x0000, 0x1934,0x18C8,0x0000, 0x1934,0x18C9,0x0000, /* FC4B */ +0x1934,0x1931,0x0000, 0x1934,0x194F,0x0000, 0x1934,0x1950,0x0000, /* FC4E */ +0x193D,0x18C2,0x0000, 0x193D,0x1931,0x0000, 0x193D,0x194F,0x0000, /* FC51 */ +0x193D,0x1950,0x0000, 0x1950,0x18C2,0x0000, 0x1950,0x18C8,0x0000, /* FC54 */ +0x1950,0x18C9,0x0000, 0x1950,0x1931,0x0000, 0x1950,0x194F,0x0000, /* FC57 */ +0x1950,0x1950,0x0000, 0x18D4,0x0000,0x0000, 0x18E1,0x0000,0x0000, /* FC5A */ +0x194F,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* FC5D */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* FC60 */ +0x0000,0x0000,0x0000, 0x18AC,0x18E1,0x0000, 0x18AC,0x18E2,0x0000, /* FC63 */ +0x18AC,0x1931,0x0000, 0x18AC,0x1934,0x0000, 0x18AC,0x194F,0x0000, /* FC66 */ +0x18AC,0x1950,0x0000, 0x18AF,0x18E1,0x0000, 0x18AF,0x18E2,0x0000, /* FC69 */ +0x18AF,0x1931,0x0000, 0x18AF,0x1934,0x0000, 0x18AF,0x194F,0x0000, /* FC6C */ +0x18AF,0x1950,0x0000, 0x18BB,0x18E1,0x0000, 0x18BB,0x18E2,0x0000, /* FC6F */ +0x18BB,0x1931,0x0000, 0x18BB,0x1934,0x0000, 0x18BB,0x194F,0x0000, /* FC72 */ +0x18BB,0x1950,0x0000, 0x18BC,0x18E1,0x0000, 0x18BC,0x18E2,0x0000, /* FC75 */ +0x18BC,0x1931,0x0000, 0x18BC,0x1934,0x0000, 0x18BC,0x194F,0x0000, /* FC78 */ +0x18BC,0x1950,0x0000, 0x190B,0x194F,0x0000, 0x190B,0x1950,0x0000, /* FC7B */ +0x1915,0x194F,0x0000, 0x1915,0x1950,0x0000, 0x1918,0x18AD,0x0000, /* FC7E */ +0x1918,0x192B,0x0000, 0x1918,0x1931,0x0000, 0x1918,0x194F,0x0000, /* FC81 */ +0x1918,0x1950,0x0000, 0x192B,0x1931,0x0000, 0x192B,0x194F,0x0000, /* FC84 */ +0x192B,0x1950,0x0000, 0x1931,0x18AD,0x0000, 0x1931,0x1931,0x0000, /* FC87 */ +0x1934,0x18E1,0x0000, 0x1934,0x18E2,0x0000, 0x1934,0x1931,0x0000, /* FC8A */ +0x1934,0x1934,0x0000, 0x1934,0x194F,0x0000, 0x1934,0x1950,0x0000, /* FC8D */ +0x194F,0x0000,0x0000, 0x1950,0x18E1,0x0000, 0x1950,0x18E2,0x0000, /* FC90 */ +0x1950,0x1931,0x0000, 0x1950,0x1934,0x0000, 0x1950,0x194F,0x0000, /* FC93 */ +0x1950,0x1950,0x0000, 0x18AC,0x18C2,0x0000, 0x18AC,0x18C8,0x0000, /* FC96 */ +0x18AC,0x18C9,0x0000, 0x18AC,0x1931,0x0000, 0x18AC,0x193D,0x0000, /* FC99 */ +0x18AF,0x18C2,0x0000, 0x18AF,0x18C8,0x0000, 0x18AF,0x18C9,0x0000, /* FC9C */ +0x18AF,0x1931,0x0000, 0x18AF,0x193D,0x0000, 0x18BB,0x18C2,0x0000, /* FC9F */ +0x18BB,0x18C8,0x0000, 0x18BB,0x18C9,0x0000, 0x18BB,0x1931,0x0000, /* FCA2 */ +0x18BB,0x193D,0x0000, 0x18BC,0x1931,0x0000, 0x18C2,0x18C8,0x0000, /* FCA5 */ +0x18C2,0x1931,0x0000, 0x18C8,0x18C2,0x0000, 0x18C8,0x1931,0x0000, /* FCA8 */ +0x18C9,0x18C2,0x0000, 0x18C9,0x1931,0x0000, 0x18F1,0x18C2,0x0000, /* FCAB */ +0x18F1,0x18C8,0x0000, 0x18F1,0x18C9,0x0000, 0x18F1,0x1931,0x0000, /* FCAE */ +0x18FC,0x18C8,0x0000, 0x18FC,0x18C9,0x0000, 0x18FC,0x1931,0x0000, /* FCB1 */ +0x18FD,0x18C2,0x0000, 0x18FD,0x18C8,0x0000, 0x18FD,0x18C9,0x0000, /* FCB4 */ +0x18FD,0x1931,0x0000, 0x1901,0x18C8,0x0000, 0x1902,0x1931,0x0000, /* FCB7 */ +0x1904,0x18C2,0x0000, 0x1904,0x1931,0x0000, 0x1905,0x18C2,0x0000, /* FCBA */ +0x1905,0x1931,0x0000, 0x190B,0x18C2,0x0000, 0x190B,0x18C8,0x0000, /* FCBD */ +0x190B,0x18C9,0x0000, 0x190B,0x1931,0x0000, 0x1915,0x18C8,0x0000, /* FCC0 */ +0x1915,0x1931,0x0000, 0x1918,0x18C2,0x0000, 0x1918,0x18C8,0x0000, /* FCC3 */ +0x1918,0x18C9,0x0000, 0x1918,0x192B,0x0000, 0x1918,0x1931,0x0000, /* FCC6 */ +0x192B,0x18C2,0x0000, 0x192B,0x18C8,0x0000, 0x192B,0x18C9,0x0000, /* FCC9 */ +0x192B,0x1931,0x0000, 0x192B,0x193D,0x0000, 0x1931,0x18C2,0x0000, /* FCCC */ +0x1931,0x18C8,0x0000, 0x1931,0x18C9,0x0000, 0x1931,0x1931,0x0000, /* FCCF */ +0x1934,0x18C2,0x0000, 0x1934,0x18C8,0x0000, 0x1934,0x18C9,0x0000, /* FCD2 */ +0x1934,0x1931,0x0000, 0x1934,0x193D,0x0000, 0x193D,0x18C2,0x0000, /* FCD5 */ +0x193D,0x1931,0x0000, 0x193D,0x0000,0x0000, 0x1950,0x18C2,0x0000, /* FCD8 */ +0x1950,0x18C8,0x0000, 0x1950,0x18C9,0x0000, 0x1950,0x1931,0x0000, /* FCDB */ +0x1950,0x193D,0x0000, 0x18AC,0x1931,0x0000, 0x18AC,0x193D,0x0000, /* FCDE */ +0x18AF,0x1931,0x0000, 0x18AF,0x193D,0x0000, 0x18BB,0x1931,0x0000, /* FCE1 */ +0x18BB,0x193D,0x0000, 0x18BC,0x1931,0x0000, 0x18BC,0x193D,0x0000, /* FCE4 */ +0x18F1,0x1931,0x0000, 0x18F1,0x193D,0x0000, 0x18F2,0x1931,0x0000, /* FCE7 */ +0x18F2,0x193D,0x0000, 0x1918,0x192B,0x0000, 0x1918,0x1931,0x0000, /* FCEA */ +0x192B,0x1931,0x0000, 0x1934,0x1931,0x0000, 0x1934,0x193D,0x0000, /* FCED */ +0x1950,0x1931,0x0000, 0x1950,0x193D,0x0000, 0x0000,0x0000,0x0000, /* FCF0 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x1901,0x194F,0x0000, /* FCF3 */ +0x1901,0x1950,0x0000, 0x1904,0x194F,0x0000, 0x1904,0x1950,0x0000, /* FCF6 */ +0x1905,0x194F,0x0000, 0x1905,0x1950,0x0000, 0x18F1,0x194F,0x0000, /* FCF9 */ +0x18F1,0x1950,0x0000, 0x18F2,0x194F,0x0000, 0x18F2,0x1950,0x0000, /* FCFC */ +0x18C8,0x194F,0x0000 }; + +uint16 uca520_p0FD[]= { /* FD00 (9 weights per char) */ +0x18C8,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD00 */ +0x18C2,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD01 */ +0x18C2,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD02 */ +0x18C9,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD03 */ +0x18C9,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD04 */ +0x18FC,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD05 */ +0x18FC,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD06 */ +0x18FD,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD07 */ +0x18FD,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD08 */ +0x18F2,0x18C2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD09 */ +0x18F2,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD0A */ +0x18F2,0x18C9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD0B */ +0x18F2,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD0C */ +0x18F2,0x18E1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD0D */ +0x18F1,0x18E1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD0E */ +0x18FC,0x18E1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD0F */ +0x18FD,0x18E1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD10 */ +0x1901,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD11 */ +0x1901,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD12 */ +0x1904,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD13 */ +0x1904,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD14 */ +0x1905,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD15 */ +0x1905,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD16 */ +0x18F1,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD17 */ +0x18F1,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD18 */ +0x18F2,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD19 */ +0x18F2,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD1A */ +0x18C8,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD1B */ +0x18C8,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD1C */ +0x18C2,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD1D */ +0x18C2,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD1E */ +0x18C9,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD1F */ +0x18C9,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD20 */ +0x18FC,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD21 */ +0x18FC,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD22 */ +0x18FD,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD23 */ +0x18FD,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD24 */ +0x18F2,0x18C2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD25 */ +0x18F2,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD26 */ +0x18F2,0x18C9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD27 */ +0x18F2,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD28 */ +0x18F2,0x18E1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD29 */ +0x18F1,0x18E1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD2A */ +0x18FC,0x18E1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD2B */ +0x18FD,0x18E1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD2C */ +0x18F2,0x18C2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD2D */ +0x18F2,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD2E */ +0x18F2,0x18C9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD2F */ +0x18F2,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD30 */ +0x18F1,0x193D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD31 */ +0x18F2,0x193D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD32 */ +0x1901,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD33 */ +0x18F1,0x18C2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD34 */ +0x18F1,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD35 */ +0x18F1,0x18C9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD36 */ +0x18F2,0x18C2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD37 */ +0x18F2,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD38 */ +0x18F2,0x18C9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD39 */ +0x1901,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD3A */ +0x1902,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD3B */ +0x18AD,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD3C */ +0x18AD,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD3D */ +0x034F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD3E */ +0x0350,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD3F */ +0xFBC1,0xFD40,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD40 */ +0xFBC1,0xFD41,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD41 */ +0xFBC1,0xFD42,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD42 */ +0xFBC1,0xFD43,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD43 */ +0xFBC1,0xFD44,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD44 */ +0xFBC1,0xFD45,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD45 */ +0xFBC1,0xFD46,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD46 */ +0xFBC1,0xFD47,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD47 */ +0xFBC1,0xFD48,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD48 */ +0xFBC1,0xFD49,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD49 */ +0xFBC1,0xFD4A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD4A */ +0xFBC1,0xFD4B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD4B */ +0xFBC1,0xFD4C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD4C */ +0xFBC1,0xFD4D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD4D */ +0xFBC1,0xFD4E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD4E */ +0xFBC1,0xFD4F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD4F */ +0x18BB,0x18C2,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD50 */ +0x18BB,0x18C8,0x18C2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD51 */ +0x18BB,0x18C8,0x18C2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD52 */ +0x18BB,0x18C8,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD53 */ +0x18BB,0x18C9,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD54 */ +0x18BB,0x1931,0x18C2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD55 */ +0x18BB,0x1931,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD56 */ +0x18BB,0x1931,0x18C9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD57 */ +0x18C2,0x1931,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD58 */ +0x18C2,0x1931,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD59 */ +0x18C8,0x1931,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD5A */ +0x18C8,0x1931,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD5B */ +0x18F1,0x18C8,0x18C2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD5C */ +0x18F1,0x18C2,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD5D */ +0x18F1,0x18C2,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD5E */ +0x18F1,0x1931,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD5F */ +0x18F1,0x1931,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD60 */ +0x18F1,0x1931,0x18C2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD61 */ +0x18F1,0x1931,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD62 */ +0x18F1,0x1931,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD63 */ +0x18FC,0x18C8,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD64 */ +0x18FC,0x18C8,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD65 */ +0x18FC,0x1931,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD66 */ +0x18F2,0x18C8,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD67 */ +0x18F2,0x18C8,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD68 */ +0x18F2,0x18C2,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD69 */ +0x18F2,0x1931,0x18C9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD6A */ +0x18F2,0x1931,0x18C9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD6B */ +0x18F2,0x1931,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD6C */ +0x18F2,0x1931,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD6D */ +0x18FD,0x18C8,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD6E */ +0x18FD,0x18C9,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD6F */ +0x18FD,0x18C9,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD70 */ +0x1901,0x1931,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD71 */ +0x1901,0x1931,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD72 */ +0x1901,0x1931,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD73 */ +0x1901,0x1931,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD74 */ +0x1904,0x18C2,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD75 */ +0x1904,0x1931,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD76 */ +0x1904,0x1931,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD77 */ +0x1904,0x1931,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD78 */ +0x1905,0x1931,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD79 */ +0x1905,0x1931,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD7A */ +0x1905,0x1931,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD7B */ +0x190B,0x18C9,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD7C */ +0x190B,0x18C9,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD7D */ +0x1915,0x1931,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD7E */ +0x1915,0x1931,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD7F */ +0x192B,0x18C8,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD80 */ +0x192B,0x18C8,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD81 */ +0x192B,0x18C8,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD82 */ +0x192B,0x18C2,0x18C2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD83 */ +0x192B,0x18C2,0x18C2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD84 */ +0x192B,0x18C9,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD85 */ +0x192B,0x18C9,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD86 */ +0x192B,0x1931,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD87 */ +0x192B,0x1931,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD88 */ +0x1931,0x18C8,0x18C2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD89 */ +0x1931,0x18C8,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD8A */ +0x1931,0x18C8,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD8B */ +0x1931,0x18C2,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD8C */ +0x1931,0x18C2,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD8D */ +0x1931,0x18C9,0x18C2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD8E */ +0x1931,0x18C9,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD8F */ +0xFBC1,0xFD90,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD90 */ +0xFBC1,0xFD91,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD91 */ +0x1931,0x18C2,0x18C9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD92 */ +0x193D,0x1931,0x18C2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD93 */ +0x193D,0x1931,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD94 */ +0x1934,0x18C8,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD95 */ +0x1934,0x18C8,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD96 */ +0x1934,0x18C2,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD97 */ +0x1934,0x18C2,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD98 */ +0x1934,0x18C2,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD99 */ +0x1934,0x1931,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD9A */ +0x1934,0x1931,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD9B */ +0x1950,0x1931,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD9C */ +0x1950,0x1931,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD9D */ +0x18AF,0x18C9,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD9E */ +0x18BB,0x18C2,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FD9F */ +0x18BB,0x18C2,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDA0 */ +0x18BB,0x18C9,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDA1 */ +0x18BB,0x18C9,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDA2 */ +0x18BB,0x1931,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDA3 */ +0x18BB,0x1931,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDA4 */ +0x18C2,0x1931,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDA5 */ +0x18C2,0x18C8,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDA6 */ +0x18C2,0x1931,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDA7 */ +0x18F1,0x18C9,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDA8 */ +0x18FC,0x18C8,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDA9 */ +0x18F2,0x18C8,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDAA */ +0x18FD,0x18C8,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDAB */ +0x192B,0x18C2,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDAC */ +0x192B,0x1931,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDAD */ +0x1950,0x18C8,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDAE */ +0x1950,0x18C2,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDAF */ +0x1950,0x1931,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDB0 */ +0x1931,0x1931,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDB1 */ +0x1915,0x1931,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDB2 */ +0x1934,0x18C8,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDB3 */ +0x1915,0x1931,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDB4 */ +0x192B,0x18C8,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDB5 */ +0x1904,0x1931,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDB6 */ +0x1918,0x1931,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDB7 */ +0x1934,0x18C2,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDB8 */ +0x1931,0x18C9,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDB9 */ +0x192B,0x18C2,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDBA */ +0x1918,0x1931,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDBB */ +0x192B,0x18C2,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDBC */ +0x1934,0x18C2,0x18C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDBD */ +0x18C2,0x18C8,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDBE */ +0x18C8,0x18C2,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDBF */ +0x1931,0x18C2,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDC0 */ +0x190B,0x1931,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDC1 */ +0x18AF,0x18C8,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDC2 */ +0x1918,0x1931,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDC3 */ +0x1904,0x18C2,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDC4 */ +0x18FC,0x1931,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDC5 */ +0x18F1,0x18C9,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDC6 */ +0x1934,0x18C2,0x1950,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDC7 */ +0xFBC1,0xFDC8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDC8 */ +0xFBC1,0xFDC9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDC9 */ +0xFBC1,0xFDCA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDCA */ +0xFBC1,0xFDCB,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDCB */ +0xFBC1,0xFDCC,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDCC */ +0xFBC1,0xFDCD,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDCD */ +0xFBC1,0xFDCE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDCE */ +0xFBC1,0xFDCF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDCF */ +0xFBC1,0xFDD0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDD0 */ +0xFBC1,0xFDD1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDD1 */ +0xFBC1,0xFDD2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDD2 */ +0xFBC1,0xFDD3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDD3 */ +0xFBC1,0xFDD4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDD4 */ +0xFBC1,0xFDD5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDD5 */ +0xFBC1,0xFDD6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDD6 */ +0xFBC1,0xFDD7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDD7 */ +0xFBC1,0xFDD8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDD8 */ +0xFBC1,0xFDD9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDD9 */ +0xFBC1,0xFDDA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDDA */ +0xFBC1,0xFDDB,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDDB */ +0xFBC1,0xFDDC,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDDC */ +0xFBC1,0xFDDD,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDDD */ +0xFBC1,0xFDDE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDDE */ +0xFBC1,0xFDDF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDDF */ +0xFBC1,0xFDE0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDE0 */ +0xFBC1,0xFDE1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDE1 */ +0xFBC1,0xFDE2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDE2 */ +0xFBC1,0xFDE3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDE3 */ +0xFBC1,0xFDE4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDE4 */ +0xFBC1,0xFDE5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDE5 */ +0xFBC1,0xFDE6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDE6 */ +0xFBC1,0xFDE7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDE7 */ +0xFBC1,0xFDE8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDE8 */ +0xFBC1,0xFDE9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDE9 */ +0xFBC1,0xFDEA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDEA */ +0xFBC1,0xFDEB,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDEB */ +0xFBC1,0xFDEC,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDEC */ +0xFBC1,0xFDED,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDED */ +0xFBC1,0xFDEE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDEE */ +0xFBC1,0xFDEF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDEF */ +0x18FC,0x192B,0x195C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDF0 */ +0x1915,0x192B,0x195C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDF1 */ +0x18AD,0x192B,0x192B,0x193D,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDF2 */ +0x18AD,0x1918,0x18AF,0x18E1,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDF3 */ +0x1931,0x18C8,0x1931,0x18D3,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDF4 */ +0x18FC,0x192B,0x1904,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDF5 */ +0x18E1,0x18F1,0x1943,0x192B,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDF6 */ +0x1904,0x192B,0x1950,0x193D,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDF7 */ +0x1943,0x18F1,0x192B,0x1931,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDF8 */ +0x18FC,0x192B,0x194F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDF9 */ +0x18FC,0x192B,0x194F,0x020A,0x18AD,0x192B,0x192B,0x193D,0x0000, /* FDFA */ +0x18C2,0x192B,0x020A,0x18C2,0x192B,0x18AD,0x192B,0x193D,0x0000, /* FDFB */ +0x18E1,0x1951,0x18AD,0x192B,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDFC */ +0x0451,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDFD */ +0xFBC1,0xFDFE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* FDFE */ +0xFBC1,0xFDFF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 /* FDFF */ +}; + +uint16 uca520_p0FE[]= { /* FE00 (4 weights per char) */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* FE00 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* FE02 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* FE04 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* FE06 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* FE08 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* FE0A */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* FE0C */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* FE0E */ +0x0234,0x0000,0x0000,0x0000, 0x0240,0x0000,0x0000,0x0000, /* FE10 */ +0x0291,0x0000,0x0000,0x0000, 0x0247,0x0000,0x0000,0x0000, /* FE12 */ +0x0243,0x0000,0x0000,0x0000, 0x026E,0x0000,0x0000,0x0000, /* FE14 */ +0x0273,0x0000,0x0000,0x0000, 0x0349,0x0000,0x0000,0x0000, /* FE16 */ +0x034A,0x0000,0x0000,0x0000, 0x0281,0x0281,0x0281,0x0000, /* FE18 */ +0xFBC1,0xFE1A,0x0000,0x0000, 0xFBC1,0xFE1B,0x0000,0x0000, /* FE1A */ +0xFBC1,0xFE1C,0x0000,0x0000, 0xFBC1,0xFE1D,0x0000,0x0000, /* FE1C */ +0xFBC1,0xFE1E,0x0000,0x0000, 0xFBC1,0xFE1F,0x0000,0x0000, /* FE1E */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* FE20 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* FE22 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* FE24 */ +0x0000,0x0000,0x0000,0x0000, 0xFBC1,0xFE27,0x0000,0x0000, /* FE26 */ +0xFBC1,0xFE28,0x0000,0x0000, 0xFBC1,0xFE29,0x0000,0x0000, /* FE28 */ +0xFBC1,0xFE2A,0x0000,0x0000, 0xFBC1,0xFE2B,0x0000,0x0000, /* FE2A */ +0xFBC1,0xFE2C,0x0000,0x0000, 0xFBC1,0xFE2D,0x0000,0x0000, /* FE2C */ +0xFBC1,0xFE2E,0x0000,0x0000, 0xFBC1,0xFE2F,0x0000,0x0000, /* FE2E */ +0x0281,0x0281,0x0000,0x0000, 0x022C,0x0000,0x0000,0x0000, /* FE30 */ +0x022B,0x0000,0x0000,0x0000, 0x021D,0x0000,0x0000,0x0000, /* FE32 */ +0x021D,0x0000,0x0000,0x0000, 0x02FF,0x0000,0x0000,0x0000, /* FE34 */ +0x0300,0x0000,0x0000,0x0000, 0x0303,0x0000,0x0000,0x0000, /* FE36 */ +0x0304,0x0000,0x0000,0x0000, 0x0347,0x0000,0x0000,0x0000, /* FE38 */ +0x0348,0x0000,0x0000,0x0000, 0x0345,0x0000,0x0000,0x0000, /* FE3A */ +0x0346,0x0000,0x0000,0x0000, 0x033F,0x0000,0x0000,0x0000, /* FE3C */ +0x0340,0x0000,0x0000,0x0000, 0x033D,0x0000,0x0000,0x0000, /* FE3E */ +0x033E,0x0000,0x0000,0x0000, 0x0341,0x0000,0x0000,0x0000, /* FE40 */ +0x0342,0x0000,0x0000,0x0000, 0x0343,0x0000,0x0000,0x0000, /* FE42 */ +0x0344,0x0000,0x0000,0x0000, 0x0241,0x0000,0x0000,0x0000, /* FE44 */ +0x0242,0x0000,0x0000,0x0000, 0x0301,0x0000,0x0000,0x0000, /* FE46 */ +0x0302,0x0000,0x0000,0x0000, 0x0213,0x0000,0x0000,0x0000, /* FE48 */ +0x0213,0x0000,0x0000,0x0000, 0x0213,0x0000,0x0000,0x0000, /* FE4A */ +0x0213,0x0000,0x0000,0x0000, 0x021D,0x0000,0x0000,0x0000, /* FE4C */ +0x021D,0x0000,0x0000,0x0000, 0x021D,0x0000,0x0000,0x0000, /* FE4E */ +0x0234,0x0000,0x0000,0x0000, 0x0240,0x0000,0x0000,0x0000, /* FE50 */ +0x0281,0x0000,0x0000,0x0000, 0xFBC1,0xFE53,0x0000,0x0000, /* FE52 */ +0x0243,0x0000,0x0000,0x0000, 0x0247,0x0000,0x0000,0x0000, /* FE54 */ +0x0273,0x0000,0x0000,0x0000, 0x026E,0x0000,0x0000,0x0000, /* FE56 */ +0x022C,0x0000,0x0000,0x0000, 0x02FF,0x0000,0x0000,0x0000, /* FE58 */ +0x0300,0x0000,0x0000,0x0000, 0x0303,0x0000,0x0000,0x0000, /* FE5A */ +0x0304,0x0000,0x0000,0x0000, 0x0347,0x0000,0x0000,0x0000, /* FE5C */ +0x0348,0x0000,0x0000,0x0000, 0x0362,0x0000,0x0000,0x0000, /* FE5E */ +0x035F,0x0000,0x0000,0x0000, 0x0357,0x0000,0x0000,0x0000, /* FE60 */ +0x0550,0x0000,0x0000,0x0000, 0x0223,0x0000,0x0000,0x0000, /* FE62 */ +0x0554,0x0000,0x0000,0x0000, 0x0556,0x0000,0x0000,0x0000, /* FE64 */ +0x0555,0x0000,0x0000,0x0000, 0xFBC1,0xFE67,0x0000,0x0000, /* FE66 */ +0x035E,0x0000,0x0000,0x0000, 0x11E1,0x0000,0x0000,0x0000, /* FE68 */ +0x0363,0x0000,0x0000,0x0000, 0x0356,0x0000,0x0000,0x0000, /* FE6A */ +0xFBC1,0xFE6C,0x0000,0x0000, 0xFBC1,0xFE6D,0x0000,0x0000, /* FE6C */ +0xFBC1,0xFE6E,0x0000,0x0000, 0xFBC1,0xFE6F,0x0000,0x0000, /* FE6E */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* FE70 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* FE72 */ +0x0000,0x0000,0x0000,0x0000, 0xFBC1,0xFE75,0x0000,0x0000, /* FE74 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* FE76 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* FE78 */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* FE7A */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* FE7C */ +0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000, /* FE7E */ +0x18A2,0x0000,0x0000,0x0000, 0x18A3,0x0000,0x0000,0x0000, /* FE80 */ +0x18A3,0x0000,0x0000,0x0000, 0x18A4,0x0000,0x0000,0x0000, /* FE82 */ +0x18A4,0x0000,0x0000,0x0000, 0x18A7,0x0000,0x0000,0x0000, /* FE84 */ +0x18A7,0x0000,0x0000,0x0000, 0x18A8,0x0000,0x0000,0x0000, /* FE86 */ +0x18A8,0x0000,0x0000,0x0000, 0x18AC,0x0000,0x0000,0x0000, /* FE88 */ +0x18AC,0x0000,0x0000,0x0000, 0x18AC,0x0000,0x0000,0x0000, /* FE8A */ +0x18AC,0x0000,0x0000,0x0000, 0x18AD,0x0000,0x0000,0x0000, /* FE8C */ +0x18AD,0x0000,0x0000,0x0000, 0x18AF,0x0000,0x0000,0x0000, /* FE8E */ +0x18AF,0x0000,0x0000,0x0000, 0x18AF,0x0000,0x0000,0x0000, /* FE90 */ +0x18AF,0x0000,0x0000,0x0000, 0x18BA,0x0000,0x0000,0x0000, /* FE92 */ +0x18BA,0x0000,0x0000,0x0000, 0x18BB,0x0000,0x0000,0x0000, /* FE94 */ +0x18BB,0x0000,0x0000,0x0000, 0x18BB,0x0000,0x0000,0x0000, /* FE96 */ +0x18BB,0x0000,0x0000,0x0000, 0x18BC,0x0000,0x0000,0x0000, /* FE98 */ +0x18BC,0x0000,0x0000,0x0000, 0x18BC,0x0000,0x0000,0x0000, /* FE9A */ +0x18BC,0x0000,0x0000,0x0000, 0x18C2,0x0000,0x0000,0x0000, /* FE9C */ +0x18C2,0x0000,0x0000,0x0000, 0x18C2,0x0000,0x0000,0x0000, /* FE9E */ +0x18C2,0x0000,0x0000,0x0000, 0x18C8,0x0000,0x0000,0x0000, /* FEA0 */ +0x18C8,0x0000,0x0000,0x0000, 0x18C8,0x0000,0x0000,0x0000, /* FEA2 */ +0x18C8,0x0000,0x0000,0x0000, 0x18C9,0x0000,0x0000,0x0000, /* FEA4 */ +0x18C9,0x0000,0x0000,0x0000, 0x18C9,0x0000,0x0000,0x0000, /* FEA6 */ +0x18C9,0x0000,0x0000,0x0000, 0x18D3,0x0000,0x0000,0x0000, /* FEA8 */ +0x18D3,0x0000,0x0000,0x0000, 0x18D4,0x0000,0x0000,0x0000, /* FEAA */ +0x18D4,0x0000,0x0000,0x0000, 0x18E1,0x0000,0x0000,0x0000, /* FEAC */ +0x18E1,0x0000,0x0000,0x0000, 0x18E2,0x0000,0x0000,0x0000, /* FEAE */ +0x18E2,0x0000,0x0000,0x0000, 0x18F1,0x0000,0x0000,0x0000, /* FEB0 */ +0x18F1,0x0000,0x0000,0x0000, 0x18F1,0x0000,0x0000,0x0000, /* FEB2 */ +0x18F1,0x0000,0x0000,0x0000, 0x18F2,0x0000,0x0000,0x0000, /* FEB4 */ +0x18F2,0x0000,0x0000,0x0000, 0x18F2,0x0000,0x0000,0x0000, /* FEB6 */ +0x18F2,0x0000,0x0000,0x0000, 0x18FC,0x0000,0x0000,0x0000, /* FEB8 */ +0x18FC,0x0000,0x0000,0x0000, 0x18FC,0x0000,0x0000,0x0000, /* FEBA */ +0x18FC,0x0000,0x0000,0x0000, 0x18FD,0x0000,0x0000,0x0000, /* FEBC */ +0x18FD,0x0000,0x0000,0x0000, 0x18FD,0x0000,0x0000,0x0000, /* FEBE */ +0x18FD,0x0000,0x0000,0x0000, 0x1901,0x0000,0x0000,0x0000, /* FEC0 */ +0x1901,0x0000,0x0000,0x0000, 0x1901,0x0000,0x0000,0x0000, /* FEC2 */ +0x1901,0x0000,0x0000,0x0000, 0x1902,0x0000,0x0000,0x0000, /* FEC4 */ +0x1902,0x0000,0x0000,0x0000, 0x1902,0x0000,0x0000,0x0000, /* FEC6 */ +0x1902,0x0000,0x0000,0x0000, 0x1904,0x0000,0x0000,0x0000, /* FEC8 */ +0x1904,0x0000,0x0000,0x0000, 0x1904,0x0000,0x0000,0x0000, /* FECA */ +0x1904,0x0000,0x0000,0x0000, 0x1905,0x0000,0x0000,0x0000, /* FECC */ +0x1905,0x0000,0x0000,0x0000, 0x1905,0x0000,0x0000,0x0000, /* FECE */ +0x1905,0x0000,0x0000,0x0000, 0x190B,0x0000,0x0000,0x0000, /* FED0 */ +0x190B,0x0000,0x0000,0x0000, 0x190B,0x0000,0x0000,0x0000, /* FED2 */ +0x190B,0x0000,0x0000,0x0000, 0x1915,0x0000,0x0000,0x0000, /* FED4 */ +0x1915,0x0000,0x0000,0x0000, 0x1915,0x0000,0x0000,0x0000, /* FED6 */ +0x1915,0x0000,0x0000,0x0000, 0x1918,0x0000,0x0000,0x0000, /* FED8 */ +0x1918,0x0000,0x0000,0x0000, 0x1918,0x0000,0x0000,0x0000, /* FEDA */ +0x1918,0x0000,0x0000,0x0000, 0x192B,0x0000,0x0000,0x0000, /* FEDC */ +0x192B,0x0000,0x0000,0x0000, 0x192B,0x0000,0x0000,0x0000, /* FEDE */ +0x192B,0x0000,0x0000,0x0000, 0x1931,0x0000,0x0000,0x0000, /* FEE0 */ +0x1931,0x0000,0x0000,0x0000, 0x1931,0x0000,0x0000,0x0000, /* FEE2 */ +0x1931,0x0000,0x0000,0x0000, 0x1934,0x0000,0x0000,0x0000, /* FEE4 */ +0x1934,0x0000,0x0000,0x0000, 0x1934,0x0000,0x0000,0x0000, /* FEE6 */ +0x1934,0x0000,0x0000,0x0000, 0x193D,0x0000,0x0000,0x0000, /* FEE8 */ +0x193D,0x0000,0x0000,0x0000, 0x193D,0x0000,0x0000,0x0000, /* FEEA */ +0x193D,0x0000,0x0000,0x0000, 0x1943,0x0000,0x0000,0x0000, /* FEEC */ +0x1943,0x0000,0x0000,0x0000, 0x194F,0x0000,0x0000,0x0000, /* FEEE */ +0x194F,0x0000,0x0000,0x0000, 0x1950,0x0000,0x0000,0x0000, /* FEF0 */ +0x1950,0x0000,0x0000,0x0000, 0x1950,0x0000,0x0000,0x0000, /* FEF2 */ +0x1950,0x0000,0x0000,0x0000, 0x192B,0x18A3,0x0000,0x0000, /* FEF4 */ +0x192B,0x18A3,0x0000,0x0000, 0x192B,0x18A4,0x0000,0x0000, /* FEF6 */ +0x192B,0x18A4,0x0000,0x0000, 0x192B,0x18A8,0x0000,0x0000, /* FEF8 */ +0x192B,0x18A8,0x0000,0x0000, 0x192B,0x18AD,0x0000,0x0000, /* FEFA */ +0x192B,0x18AD,0x0000,0x0000, 0xFBC1,0xFEFD,0x0000,0x0000, /* FEFC */ +0xFBC1,0xFEFE,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000 /* FEFE */ +}; + +uint16 uca520_p0FF[]= { /* FF00 (3 weights per char) */ +0xFBC1,0xFF00,0x0000, 0x026E,0x0000,0x0000, 0x02F5,0x0000,0x0000, /* FF00 */ +0x0362,0x0000,0x0000, 0x11E1,0x0000,0x0000, 0x0363,0x0000,0x0000, /* FF03 */ +0x035F,0x0000,0x0000, 0x02EE,0x0000,0x0000, 0x02FF,0x0000,0x0000, /* FF06 */ +0x0300,0x0000,0x0000, 0x0357,0x0000,0x0000, 0x0550,0x0000,0x0000, /* FF09 */ +0x0234,0x0000,0x0000, 0x0223,0x0000,0x0000, 0x0281,0x0000,0x0000, /* FF0C */ +0x035C,0x0000,0x0000, 0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, /* FF0F */ +0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, /* FF12 */ +0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, /* FF15 */ +0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, 0x0247,0x0000,0x0000, /* FF18 */ +0x0243,0x0000,0x0000, 0x0554,0x0000,0x0000, 0x0555,0x0000,0x0000, /* FF1B */ +0x0556,0x0000,0x0000, 0x0273,0x0000,0x0000, 0x0356,0x0000,0x0000, /* FF1E */ +0x120F,0x0000,0x0000, 0x1225,0x0000,0x0000, 0x123D,0x0000,0x0000, /* FF21 */ +0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x12A3,0x0000,0x0000, /* FF24 */ +0x12B0,0x0000,0x0000, 0x12D3,0x0000,0x0000, 0x12EC,0x0000,0x0000, /* FF27 */ +0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, /* FF2A */ +0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, 0x138E,0x0000,0x0000, /* FF2D */ +0x13B3,0x0000,0x0000, 0x13C8,0x0000,0x0000, 0x13DA,0x0000,0x0000, /* FF30 */ +0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, /* FF33 */ +0x147B,0x0000,0x0000, 0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, /* FF36 */ +0x149C,0x0000,0x0000, 0x14AD,0x0000,0x0000, 0x0301,0x0000,0x0000, /* FF39 */ +0x035E,0x0000,0x0000, 0x0302,0x0000,0x0000, 0x0211,0x0000,0x0000, /* FF3C */ +0x021D,0x0000,0x0000, 0x020E,0x0000,0x0000, 0x120F,0x0000,0x0000, /* FF3F */ +0x1225,0x0000,0x0000, 0x123D,0x0000,0x0000, 0x1250,0x0000,0x0000, /* FF42 */ +0x126B,0x0000,0x0000, 0x12A3,0x0000,0x0000, 0x12B0,0x0000,0x0000, /* FF45 */ +0x12D3,0x0000,0x0000, 0x12EC,0x0000,0x0000, 0x1305,0x0000,0x0000, /* FF48 */ +0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, 0x135F,0x0000,0x0000, /* FF4B */ +0x136D,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x13B3,0x0000,0x0000, /* FF4E */ +0x13C8,0x0000,0x0000, 0x13DA,0x0000,0x0000, 0x1410,0x0000,0x0000, /* FF51 */ +0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x147B,0x0000,0x0000, /* FF54 */ +0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, 0x149C,0x0000,0x0000, /* FF57 */ +0x14AD,0x0000,0x0000, 0x0303,0x0000,0x0000, 0x0558,0x0000,0x0000, /* FF5A */ +0x0304,0x0000,0x0000, 0x055B,0x0000,0x0000, 0x0311,0x0000,0x0000, /* FF5D */ +0x0312,0x0000,0x0000, 0x0291,0x0000,0x0000, 0x0341,0x0000,0x0000, /* FF60 */ +0x0342,0x0000,0x0000, 0x0240,0x0000,0x0000, 0x0233,0x0000,0x0000, /* FF63 */ +0x2B43,0x0000,0x0000, 0x2B15,0x0000,0x0000, 0x2B16,0x0000,0x0000, /* FF66 */ +0x2B17,0x0000,0x0000, 0x2B18,0x0000,0x0000, 0x2B19,0x0000,0x0000, /* FF69 */ +0x2B38,0x0000,0x0000, 0x2B39,0x0000,0x0000, 0x2B3A,0x0000,0x0000, /* FF6C */ +0x2B26,0x0000,0x0000, 0x11DD,0x0000,0x0000, 0x2B15,0x0000,0x0000, /* FF6F */ +0x2B16,0x0000,0x0000, 0x2B17,0x0000,0x0000, 0x2B18,0x0000,0x0000, /* FF72 */ +0x2B19,0x0000,0x0000, 0x2B1A,0x0000,0x0000, 0x2B1B,0x0000,0x0000, /* FF75 */ +0x2B1C,0x0000,0x0000, 0x2B1D,0x0000,0x0000, 0x2B1E,0x0000,0x0000, /* FF78 */ +0x2B1F,0x0000,0x0000, 0x2B20,0x0000,0x0000, 0x2B21,0x0000,0x0000, /* FF7B */ +0x2B22,0x0000,0x0000, 0x2B23,0x0000,0x0000, 0x2B24,0x0000,0x0000, /* FF7E */ +0x2B25,0x0000,0x0000, 0x2B26,0x0000,0x0000, 0x2B27,0x0000,0x0000, /* FF81 */ +0x2B28,0x0000,0x0000, 0x2B29,0x0000,0x0000, 0x2B2A,0x0000,0x0000, /* FF84 */ +0x2B2B,0x0000,0x0000, 0x2B2C,0x0000,0x0000, 0x2B2D,0x0000,0x0000, /* FF87 */ +0x2B2E,0x0000,0x0000, 0x2B2F,0x0000,0x0000, 0x2B30,0x0000,0x0000, /* FF8A */ +0x2B31,0x0000,0x0000, 0x2B32,0x0000,0x0000, 0x2B33,0x0000,0x0000, /* FF8D */ +0x2B34,0x0000,0x0000, 0x2B35,0x0000,0x0000, 0x2B36,0x0000,0x0000, /* FF90 */ +0x2B37,0x0000,0x0000, 0x2B38,0x0000,0x0000, 0x2B39,0x0000,0x0000, /* FF93 */ +0x2B3A,0x0000,0x0000, 0x2B3B,0x0000,0x0000, 0x2B3C,0x0000,0x0000, /* FF96 */ +0x2B3D,0x0000,0x0000, 0x2B3E,0x0000,0x0000, 0x2B3F,0x0000,0x0000, /* FF99 */ +0x2B40,0x0000,0x0000, 0x2B44,0x0000,0x0000, 0x0000,0x0000,0x0000, /* FF9C */ +0x0000,0x0000,0x0000, 0x2A2D,0x0000,0x0000, 0x29B0,0x0000,0x0000, /* FF9F */ +0x29B1,0x0000,0x0000, 0x2A8E,0x0000,0x0000, 0x29B2,0x0000,0x0000, /* FFA2 */ +0x2A90,0x0000,0x0000, 0x2A91,0x0000,0x0000, 0x29B3,0x0000,0x0000, /* FFA5 */ +0x29B4,0x0000,0x0000, 0x29B5,0x0000,0x0000, 0x2A94,0x0000,0x0000, /* FFA8 */ +0x2A95,0x0000,0x0000, 0x2A96,0x0000,0x0000, 0x2A97,0x0000,0x0000, /* FFAB */ +0x2A98,0x0000,0x0000, 0x2A99,0x0000,0x0000, 0x29CA,0x0000,0x0000, /* FFAE */ +0x29B6,0x0000,0x0000, 0x29B7,0x0000,0x0000, 0x29B8,0x0000,0x0000, /* FFB1 */ +0x29D1,0x0000,0x0000, 0x29B9,0x0000,0x0000, 0x29BA,0x0000,0x0000, /* FFB4 */ +0x29BB,0x0000,0x0000, 0x29BC,0x0000,0x0000, 0x29BD,0x0000,0x0000, /* FFB7 */ +0x29BE,0x0000,0x0000, 0x29BF,0x0000,0x0000, 0x29C0,0x0000,0x0000, /* FFBA */ +0x29C1,0x0000,0x0000, 0x29C2,0x0000,0x0000, 0xFBC1,0xFFBF,0x0000, /* FFBD */ +0xFBC1,0xFFC0,0x0000, 0xFBC1,0xFFC1,0x0000, 0x2A2E,0x0000,0x0000, /* FFC0 */ +0x2A2F,0x0000,0x0000, 0x2A30,0x0000,0x0000, 0x2A31,0x0000,0x0000, /* FFC3 */ +0x2A32,0x0000,0x0000, 0x2A33,0x0000,0x0000, 0xFBC1,0xFFC8,0x0000, /* FFC6 */ +0xFBC1,0xFFC9,0x0000, 0x2A34,0x0000,0x0000, 0x2A35,0x0000,0x0000, /* FFC9 */ +0x2A36,0x0000,0x0000, 0x2A37,0x0000,0x0000, 0x2A38,0x0000,0x0000, /* FFCC */ +0x2A39,0x0000,0x0000, 0xFBC1,0xFFD0,0x0000, 0xFBC1,0xFFD1,0x0000, /* FFCF */ +0x2A3A,0x0000,0x0000, 0x2A3B,0x0000,0x0000, 0x2A3C,0x0000,0x0000, /* FFD2 */ +0x2A3D,0x0000,0x0000, 0x2A3E,0x0000,0x0000, 0x2A3F,0x0000,0x0000, /* FFD5 */ +0xFBC1,0xFFD8,0x0000, 0xFBC1,0xFFD9,0x0000, 0x2A40,0x0000,0x0000, /* FFD8 */ +0x2A41,0x0000,0x0000, 0x2A42,0x0000,0x0000, 0xFBC1,0xFFDD,0x0000, /* FFDB */ +0xFBC1,0xFFDE,0x0000, 0xFBC1,0xFFDF,0x0000, 0x11E0,0x0000,0x0000, /* FFDE */ +0x11E2,0x0000,0x0000, 0x0557,0x0000,0x0000, 0x0212,0x0000,0x0000, /* FFE1 */ +0x0559,0x0000,0x0000, 0x11E3,0x0000,0x0000, 0x11F5,0x0000,0x0000, /* FFE4 */ +0xFBC1,0xFFE7,0x0000, 0x0740,0x0000,0x0000, 0x04D6,0x0000,0x0000, /* FFE7 */ +0x04D8,0x0000,0x0000, 0x04D7,0x0000,0x0000, 0x04D9,0x0000,0x0000, /* FFEA */ +0x07DE,0x0000,0x0000, 0x0809,0x0000,0x0000, 0xFBC1,0xFFEF,0x0000, /* FFED */ +0xFBC1,0xFFF0,0x0000, 0xFBC1,0xFFF1,0x0000, 0xFBC1,0xFFF2,0x0000, /* FFF0 */ +0xFBC1,0xFFF3,0x0000, 0xFBC1,0xFFF4,0x0000, 0xFBC1,0xFFF5,0x0000, /* FFF3 */ +0xFBC1,0xFFF6,0x0000, 0xFBC1,0xFFF7,0x0000, 0xFBC1,0xFFF8,0x0000, /* FFF6 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* FFF9 */ +0x110E,0x0000,0x0000, 0x110F,0x0000,0x0000, 0xFBC1,0xFFFE,0x0000, /* FFFC */ +0xFBC1,0xFFFF,0x0000 }; + +uint16 uca520_p100[]= { /* 10000 (3 weights per char) */ +0x3148,0x0000,0x0000, 0x3149,0x0000,0x0000, 0x314A,0x0000,0x0000, /* 10000 */ +0x314B,0x0000,0x0000, 0x314C,0x0000,0x0000, 0x314D,0x0000,0x0000, /* 10003 */ +0x314E,0x0000,0x0000, 0x314F,0x0000,0x0000, 0x3150,0x0000,0x0000, /* 10006 */ +0x3151,0x0000,0x0000, 0x3152,0x0000,0x0000, 0x3153,0x0000,0x0000, /* 10009 */ +0xFBC2,0x800C,0x0000, 0x3154,0x0000,0x0000, 0x3155,0x0000,0x0000, /* 1000C */ +0x3156,0x0000,0x0000, 0x3157,0x0000,0x0000, 0x3158,0x0000,0x0000, /* 1000F */ +0x3159,0x0000,0x0000, 0x315A,0x0000,0x0000, 0x315B,0x0000,0x0000, /* 10012 */ +0x315C,0x0000,0x0000, 0x315D,0x0000,0x0000, 0x315E,0x0000,0x0000, /* 10015 */ +0x315F,0x0000,0x0000, 0x3160,0x0000,0x0000, 0x3161,0x0000,0x0000, /* 10018 */ +0x3162,0x0000,0x0000, 0x3163,0x0000,0x0000, 0x3164,0x0000,0x0000, /* 1001B */ +0x3165,0x0000,0x0000, 0x3166,0x0000,0x0000, 0x3167,0x0000,0x0000, /* 1001E */ +0x3168,0x0000,0x0000, 0x3169,0x0000,0x0000, 0x316A,0x0000,0x0000, /* 10021 */ +0x316B,0x0000,0x0000, 0x316C,0x0000,0x0000, 0x316D,0x0000,0x0000, /* 10024 */ +0xFBC2,0x8027,0x0000, 0x316E,0x0000,0x0000, 0x316F,0x0000,0x0000, /* 10027 */ +0x3170,0x0000,0x0000, 0x3171,0x0000,0x0000, 0x3172,0x0000,0x0000, /* 1002A */ +0x3173,0x0000,0x0000, 0x3174,0x0000,0x0000, 0x3175,0x0000,0x0000, /* 1002D */ +0x3176,0x0000,0x0000, 0x3177,0x0000,0x0000, 0x3178,0x0000,0x0000, /* 10030 */ +0x3179,0x0000,0x0000, 0x317A,0x0000,0x0000, 0x317B,0x0000,0x0000, /* 10033 */ +0x317C,0x0000,0x0000, 0x317D,0x0000,0x0000, 0x317E,0x0000,0x0000, /* 10036 */ +0x317F,0x0000,0x0000, 0x3180,0x0000,0x0000, 0xFBC2,0x803B,0x0000, /* 10039 */ +0x3181,0x0000,0x0000, 0x3182,0x0000,0x0000, 0xFBC2,0x803E,0x0000, /* 1003C */ +0x3183,0x0000,0x0000, 0x3184,0x0000,0x0000, 0x3185,0x0000,0x0000, /* 1003F */ +0x3186,0x0000,0x0000, 0x3187,0x0000,0x0000, 0x3188,0x0000,0x0000, /* 10042 */ +0x3189,0x0000,0x0000, 0x318A,0x0000,0x0000, 0x318B,0x0000,0x0000, /* 10045 */ +0x318C,0x0000,0x0000, 0x318D,0x0000,0x0000, 0x318E,0x0000,0x0000, /* 10048 */ +0x318F,0x0000,0x0000, 0x3190,0x0000,0x0000, 0x3191,0x0000,0x0000, /* 1004B */ +0xFBC2,0x804E,0x0000, 0xFBC2,0x804F,0x0000, 0x3192,0x0000,0x0000, /* 1004E */ +0x3193,0x0000,0x0000, 0x3194,0x0000,0x0000, 0x3195,0x0000,0x0000, /* 10051 */ +0x3196,0x0000,0x0000, 0x3197,0x0000,0x0000, 0x3198,0x0000,0x0000, /* 10054 */ +0x3199,0x0000,0x0000, 0x319A,0x0000,0x0000, 0x319B,0x0000,0x0000, /* 10057 */ +0x319C,0x0000,0x0000, 0x319D,0x0000,0x0000, 0x319E,0x0000,0x0000, /* 1005A */ +0x319F,0x0000,0x0000, 0xFBC2,0x805E,0x0000, 0xFBC2,0x805F,0x0000, /* 1005D */ +0xFBC2,0x8060,0x0000, 0xFBC2,0x8061,0x0000, 0xFBC2,0x8062,0x0000, /* 10060 */ +0xFBC2,0x8063,0x0000, 0xFBC2,0x8064,0x0000, 0xFBC2,0x8065,0x0000, /* 10063 */ +0xFBC2,0x8066,0x0000, 0xFBC2,0x8067,0x0000, 0xFBC2,0x8068,0x0000, /* 10066 */ +0xFBC2,0x8069,0x0000, 0xFBC2,0x806A,0x0000, 0xFBC2,0x806B,0x0000, /* 10069 */ +0xFBC2,0x806C,0x0000, 0xFBC2,0x806D,0x0000, 0xFBC2,0x806E,0x0000, /* 1006C */ +0xFBC2,0x806F,0x0000, 0xFBC2,0x8070,0x0000, 0xFBC2,0x8071,0x0000, /* 1006F */ +0xFBC2,0x8072,0x0000, 0xFBC2,0x8073,0x0000, 0xFBC2,0x8074,0x0000, /* 10072 */ +0xFBC2,0x8075,0x0000, 0xFBC2,0x8076,0x0000, 0xFBC2,0x8077,0x0000, /* 10075 */ +0xFBC2,0x8078,0x0000, 0xFBC2,0x8079,0x0000, 0xFBC2,0x807A,0x0000, /* 10078 */ +0xFBC2,0x807B,0x0000, 0xFBC2,0x807C,0x0000, 0xFBC2,0x807D,0x0000, /* 1007B */ +0xFBC2,0x807E,0x0000, 0xFBC2,0x807F,0x0000, 0x31A0,0x0000,0x0000, /* 1007E */ +0x31A1,0x0000,0x0000, 0x31A2,0x0000,0x0000, 0x31A3,0x0000,0x0000, /* 10081 */ +0x31A4,0x0000,0x0000, 0x31A5,0x0000,0x0000, 0x31A6,0x0000,0x0000, /* 10084 */ +0x31A7,0x0000,0x0000, 0x31A8,0x0000,0x0000, 0x31A9,0x0000,0x0000, /* 10087 */ +0x31AA,0x0000,0x0000, 0x31AB,0x0000,0x0000, 0x31AC,0x0000,0x0000, /* 1008A */ +0x31AD,0x0000,0x0000, 0x31AE,0x0000,0x0000, 0x31AF,0x0000,0x0000, /* 1008D */ +0x31B0,0x0000,0x0000, 0x31B1,0x0000,0x0000, 0x31B2,0x0000,0x0000, /* 10090 */ +0x31B3,0x0000,0x0000, 0x31B4,0x0000,0x0000, 0x31B5,0x0000,0x0000, /* 10093 */ +0x31B6,0x0000,0x0000, 0x31B7,0x0000,0x0000, 0x31B8,0x0000,0x0000, /* 10096 */ +0x31B9,0x0000,0x0000, 0x31BA,0x0000,0x0000, 0x31BB,0x0000,0x0000, /* 10099 */ +0x31BC,0x0000,0x0000, 0x31BD,0x0000,0x0000, 0x31BE,0x0000,0x0000, /* 1009C */ +0x31BF,0x0000,0x0000, 0x31C0,0x0000,0x0000, 0x31C1,0x0000,0x0000, /* 1009F */ +0x31C2,0x0000,0x0000, 0x31C3,0x0000,0x0000, 0x31C4,0x0000,0x0000, /* 100A2 */ +0x31C5,0x0000,0x0000, 0x31C6,0x0000,0x0000, 0x31C7,0x0000,0x0000, /* 100A5 */ +0x31C8,0x0000,0x0000, 0x31C9,0x0000,0x0000, 0x31CA,0x0000,0x0000, /* 100A8 */ +0x31CB,0x0000,0x0000, 0x31CC,0x0000,0x0000, 0x31CD,0x0000,0x0000, /* 100AB */ +0x31CE,0x0000,0x0000, 0x31CF,0x0000,0x0000, 0x31D0,0x0000,0x0000, /* 100AE */ +0x31D1,0x0000,0x0000, 0x31D2,0x0000,0x0000, 0x31D3,0x0000,0x0000, /* 100B1 */ +0x31D4,0x0000,0x0000, 0x31D5,0x0000,0x0000, 0x31D6,0x0000,0x0000, /* 100B4 */ +0x31D7,0x0000,0x0000, 0x31D8,0x0000,0x0000, 0x31D9,0x0000,0x0000, /* 100B7 */ +0x31DA,0x0000,0x0000, 0x31DB,0x0000,0x0000, 0x31DC,0x0000,0x0000, /* 100BA */ +0x31DD,0x0000,0x0000, 0x31DE,0x0000,0x0000, 0x31DF,0x0000,0x0000, /* 100BD */ +0x31E0,0x0000,0x0000, 0x31E1,0x0000,0x0000, 0x31E2,0x0000,0x0000, /* 100C0 */ +0x31E3,0x0000,0x0000, 0x31E4,0x0000,0x0000, 0x31E5,0x0000,0x0000, /* 100C3 */ +0x31E6,0x0000,0x0000, 0x31E7,0x0000,0x0000, 0x31E8,0x0000,0x0000, /* 100C6 */ +0x31E9,0x0000,0x0000, 0x31EA,0x0000,0x0000, 0x31EB,0x0000,0x0000, /* 100C9 */ +0x31EC,0x0000,0x0000, 0x31ED,0x0000,0x0000, 0x31EE,0x0000,0x0000, /* 100CC */ +0x31EF,0x0000,0x0000, 0x31F0,0x0000,0x0000, 0x31F1,0x0000,0x0000, /* 100CF */ +0x31F2,0x0000,0x0000, 0x31F3,0x0000,0x0000, 0x31F4,0x0000,0x0000, /* 100D2 */ +0x31F5,0x0000,0x0000, 0x31F6,0x0000,0x0000, 0x31F7,0x0000,0x0000, /* 100D5 */ +0x31F8,0x0000,0x0000, 0x31F9,0x0000,0x0000, 0x31FA,0x0000,0x0000, /* 100D8 */ +0x31FB,0x0000,0x0000, 0x31FC,0x0000,0x0000, 0x31FD,0x0000,0x0000, /* 100DB */ +0x31FE,0x0000,0x0000, 0x31FF,0x0000,0x0000, 0x3200,0x0000,0x0000, /* 100DE */ +0x3201,0x0000,0x0000, 0x3202,0x0000,0x0000, 0x3203,0x0000,0x0000, /* 100E1 */ +0x3204,0x0000,0x0000, 0x3205,0x0000,0x0000, 0x3206,0x0000,0x0000, /* 100E4 */ +0x3207,0x0000,0x0000, 0x3208,0x0000,0x0000, 0x3209,0x0000,0x0000, /* 100E7 */ +0x320A,0x0000,0x0000, 0x320B,0x0000,0x0000, 0x320C,0x0000,0x0000, /* 100EA */ +0x320D,0x0000,0x0000, 0x320E,0x0000,0x0000, 0x320F,0x0000,0x0000, /* 100ED */ +0x3210,0x0000,0x0000, 0x3211,0x0000,0x0000, 0x3212,0x0000,0x0000, /* 100F0 */ +0x3213,0x0000,0x0000, 0x3214,0x0000,0x0000, 0x3215,0x0000,0x0000, /* 100F3 */ +0x3216,0x0000,0x0000, 0x3217,0x0000,0x0000, 0x3218,0x0000,0x0000, /* 100F6 */ +0x3219,0x0000,0x0000, 0x321A,0x0000,0x0000, 0xFBC2,0x80FB,0x0000, /* 100F9 */ +0xFBC2,0x80FC,0x0000, 0xFBC2,0x80FD,0x0000, 0xFBC2,0x80FE,0x0000, /* 100FC */ +0xFBC2,0x80FF,0x0000 }; + +uint16 uca520_p101[]= { /* 10100 (3 weights per char) */ +0x02E4,0x0000,0x0000, 0x02E5,0x0000,0x0000, 0x02E6,0x0000,0x0000, /* 10100 */ +0xFBC2,0x8103,0x0000, 0xFBC2,0x8104,0x0000, 0xFBC2,0x8105,0x0000, /* 10103 */ +0xFBC2,0x8106,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 10106 */ +0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, /* 10109 */ +0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, /* 1010C */ +0x120E,0x0000,0x0000, 0x114F,0x0000,0x0000, 0x1150,0x0000,0x0000, /* 1010F */ +0x1151,0x0000,0x0000, 0x1152,0x0000,0x0000, 0x1153,0x0000,0x0000, /* 10112 */ +0x1154,0x0000,0x0000, 0x1155,0x0000,0x0000, 0x1156,0x0000,0x0000, /* 10115 */ +0x1157,0x0000,0x0000, 0x1158,0x0000,0x0000, 0x1159,0x0000,0x0000, /* 10118 */ +0x115A,0x0000,0x0000, 0x115B,0x0000,0x0000, 0x115C,0x0000,0x0000, /* 1011B */ +0x115D,0x0000,0x0000, 0x115E,0x0000,0x0000, 0x115F,0x0000,0x0000, /* 1011E */ +0x1160,0x0000,0x0000, 0x1161,0x0000,0x0000, 0x1162,0x0000,0x0000, /* 10121 */ +0x1163,0x0000,0x0000, 0x1164,0x0000,0x0000, 0x1165,0x0000,0x0000, /* 10124 */ +0x1166,0x0000,0x0000, 0x1167,0x0000,0x0000, 0x1168,0x0000,0x0000, /* 10127 */ +0x1169,0x0000,0x0000, 0x116A,0x0000,0x0000, 0x116B,0x0000,0x0000, /* 1012A */ +0x116C,0x0000,0x0000, 0x116D,0x0000,0x0000, 0x116E,0x0000,0x0000, /* 1012D */ +0x116F,0x0000,0x0000, 0x1170,0x0000,0x0000, 0x1171,0x0000,0x0000, /* 10130 */ +0x1172,0x0000,0x0000, 0xFBC2,0x8134,0x0000, 0xFBC2,0x8135,0x0000, /* 10133 */ +0xFBC2,0x8136,0x0000, 0x0E0C,0x0000,0x0000, 0x0E0D,0x0000,0x0000, /* 10136 */ +0x0E0E,0x0000,0x0000, 0x0E0F,0x0000,0x0000, 0x0E10,0x0000,0x0000, /* 10139 */ +0x0E11,0x0000,0x0000, 0x0E12,0x0000,0x0000, 0x0E13,0x0000,0x0000, /* 1013C */ +0x0E14,0x0000,0x0000, 0x1173,0x0000,0x0000, 0x1174,0x0000,0x0000, /* 1013F */ +0x1206,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x1175,0x0000,0x0000, /* 10142 */ +0x1176,0x0000,0x0000, 0x1177,0x0000,0x0000, 0x1178,0x0000,0x0000, /* 10145 */ +0x120A,0x0000,0x0000, 0x1179,0x0000,0x0000, 0x117A,0x0000,0x0000, /* 10148 */ +0x117B,0x0000,0x0000, 0x117C,0x0000,0x0000, 0x117D,0x0000,0x0000, /* 1014B */ +0x117E,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x117F,0x0000,0x0000, /* 1014E */ +0x1180,0x0000,0x0000, 0x1181,0x0000,0x0000, 0x1182,0x0000,0x0000, /* 10151 */ +0x1183,0x0000,0x0000, 0x1184,0x0000,0x0000, 0x1185,0x0000,0x0000, /* 10154 */ +0x1186,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1206,0x0000,0x0000, /* 10157 */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 1015A */ +0x1207,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x120A,0x0000,0x0000, /* 1015D */ +0x1187,0x0000,0x0000, 0x1188,0x0000,0x0000, 0x1189,0x0000,0x0000, /* 10160 */ +0x118A,0x0000,0x0000, 0x118B,0x0000,0x0000, 0x118C,0x0000,0x0000, /* 10163 */ +0x118D,0x0000,0x0000, 0x118E,0x0000,0x0000, 0x118F,0x0000,0x0000, /* 10166 */ +0x1190,0x0000,0x0000, 0x1191,0x0000,0x0000, 0x1192,0x0000,0x0000, /* 10169 */ +0x1193,0x0000,0x0000, 0x1194,0x0000,0x0000, 0x1195,0x0000,0x0000, /* 1016C */ +0x1196,0x0000,0x0000, 0x1197,0x0000,0x0000, 0x1198,0x0000,0x0000, /* 1016F */ +0x1199,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x119A,0x0000,0x0000, /* 10172 */ +0x119B,0x0000,0x0000, 0x119C,0x0000,0x0000, 0x119D,0x0000,0x0000, /* 10175 */ +0x119E,0x0000,0x0000, 0x0E15,0x0000,0x0000, 0x0E16,0x0000,0x0000, /* 10178 */ +0x0E17,0x0000,0x0000, 0x0E18,0x0000,0x0000, 0x0E19,0x0000,0x0000, /* 1017B */ +0x0E1A,0x0000,0x0000, 0x0E1B,0x0000,0x0000, 0x0E1C,0x0000,0x0000, /* 1017E */ +0x0E1D,0x0000,0x0000, 0x0E1E,0x0000,0x0000, 0x0E1F,0x0000,0x0000, /* 10181 */ +0x0E20,0x0000,0x0000, 0x0E21,0x0000,0x0000, 0x0E22,0x0000,0x0000, /* 10184 */ +0x0E23,0x0000,0x0000, 0x0E24,0x0000,0x0000, 0x0E25,0x0000,0x0000, /* 10187 */ +0x1205,0x0000,0x0000, 0xFBC2,0x818B,0x0000, 0xFBC2,0x818C,0x0000, /* 1018A */ +0xFBC2,0x818D,0x0000, 0xFBC2,0x818E,0x0000, 0xFBC2,0x818F,0x0000, /* 1018D */ +0x0E26,0x0000,0x0000, 0x0E27,0x0000,0x0000, 0x0E28,0x0000,0x0000, /* 10190 */ +0x0E29,0x0000,0x0000, 0x0E2A,0x0000,0x0000, 0x0E2B,0x0000,0x0000, /* 10193 */ +0x0E2C,0x0000,0x0000, 0x0E2D,0x0000,0x0000, 0x0E2E,0x0000,0x0000, /* 10196 */ +0x0E2F,0x0000,0x0000, 0x0E30,0x0000,0x0000, 0x0E31,0x0000,0x0000, /* 10199 */ +0xFBC2,0x819C,0x0000, 0xFBC2,0x819D,0x0000, 0xFBC2,0x819E,0x0000, /* 1019C */ +0xFBC2,0x819F,0x0000, 0xFBC2,0x81A0,0x0000, 0xFBC2,0x81A1,0x0000, /* 1019F */ +0xFBC2,0x81A2,0x0000, 0xFBC2,0x81A3,0x0000, 0xFBC2,0x81A4,0x0000, /* 101A2 */ +0xFBC2,0x81A5,0x0000, 0xFBC2,0x81A6,0x0000, 0xFBC2,0x81A7,0x0000, /* 101A5 */ +0xFBC2,0x81A8,0x0000, 0xFBC2,0x81A9,0x0000, 0xFBC2,0x81AA,0x0000, /* 101A8 */ +0xFBC2,0x81AB,0x0000, 0xFBC2,0x81AC,0x0000, 0xFBC2,0x81AD,0x0000, /* 101AB */ +0xFBC2,0x81AE,0x0000, 0xFBC2,0x81AF,0x0000, 0xFBC2,0x81B0,0x0000, /* 101AE */ +0xFBC2,0x81B1,0x0000, 0xFBC2,0x81B2,0x0000, 0xFBC2,0x81B3,0x0000, /* 101B1 */ +0xFBC2,0x81B4,0x0000, 0xFBC2,0x81B5,0x0000, 0xFBC2,0x81B6,0x0000, /* 101B4 */ +0xFBC2,0x81B7,0x0000, 0xFBC2,0x81B8,0x0000, 0xFBC2,0x81B9,0x0000, /* 101B7 */ +0xFBC2,0x81BA,0x0000, 0xFBC2,0x81BB,0x0000, 0xFBC2,0x81BC,0x0000, /* 101BA */ +0xFBC2,0x81BD,0x0000, 0xFBC2,0x81BE,0x0000, 0xFBC2,0x81BF,0x0000, /* 101BD */ +0xFBC2,0x81C0,0x0000, 0xFBC2,0x81C1,0x0000, 0xFBC2,0x81C2,0x0000, /* 101C0 */ +0xFBC2,0x81C3,0x0000, 0xFBC2,0x81C4,0x0000, 0xFBC2,0x81C5,0x0000, /* 101C3 */ +0xFBC2,0x81C6,0x0000, 0xFBC2,0x81C7,0x0000, 0xFBC2,0x81C8,0x0000, /* 101C6 */ +0xFBC2,0x81C9,0x0000, 0xFBC2,0x81CA,0x0000, 0xFBC2,0x81CB,0x0000, /* 101C9 */ +0xFBC2,0x81CC,0x0000, 0xFBC2,0x81CD,0x0000, 0xFBC2,0x81CE,0x0000, /* 101CC */ +0xFBC2,0x81CF,0x0000, 0x0E32,0x0000,0x0000, 0x0E33,0x0000,0x0000, /* 101CF */ +0x0E34,0x0000,0x0000, 0x0E35,0x0000,0x0000, 0x0E36,0x0000,0x0000, /* 101D2 */ +0x0E37,0x0000,0x0000, 0x0E38,0x0000,0x0000, 0x0E39,0x0000,0x0000, /* 101D5 */ +0x0E3A,0x0000,0x0000, 0x0E3B,0x0000,0x0000, 0x0E3C,0x0000,0x0000, /* 101D8 */ +0x0E3D,0x0000,0x0000, 0x0E3E,0x0000,0x0000, 0x0E3F,0x0000,0x0000, /* 101DB */ +0x0E40,0x0000,0x0000, 0x0E41,0x0000,0x0000, 0x0E42,0x0000,0x0000, /* 101DE */ +0x0E43,0x0000,0x0000, 0x0E44,0x0000,0x0000, 0x0E45,0x0000,0x0000, /* 101E1 */ +0x0E46,0x0000,0x0000, 0x0E47,0x0000,0x0000, 0x0E48,0x0000,0x0000, /* 101E4 */ +0x0E49,0x0000,0x0000, 0x0E4A,0x0000,0x0000, 0x0E4B,0x0000,0x0000, /* 101E7 */ +0x0E4C,0x0000,0x0000, 0x0E4D,0x0000,0x0000, 0x0E4E,0x0000,0x0000, /* 101EA */ +0x0E4F,0x0000,0x0000, 0x0E50,0x0000,0x0000, 0x0E51,0x0000,0x0000, /* 101ED */ +0x0E52,0x0000,0x0000, 0x0E53,0x0000,0x0000, 0x0E54,0x0000,0x0000, /* 101F0 */ +0x0E55,0x0000,0x0000, 0x0E56,0x0000,0x0000, 0x0E57,0x0000,0x0000, /* 101F3 */ +0x0E58,0x0000,0x0000, 0x0E59,0x0000,0x0000, 0x0E5A,0x0000,0x0000, /* 101F6 */ +0x0E5B,0x0000,0x0000, 0x0E5C,0x0000,0x0000, 0x0E5D,0x0000,0x0000, /* 101F9 */ +0x0E5E,0x0000,0x0000, 0x0000,0x0000,0x0000, 0xFBC2,0x81FE,0x0000, /* 101FC */ +0xFBC2,0x81FF,0x0000 }; + +uint16 uca520_p102[]= { /* 10200 (3 weights per char) */ +0xFBC2,0x8200,0x0000, 0xFBC2,0x8201,0x0000, 0xFBC2,0x8202,0x0000, /* 10200 */ +0xFBC2,0x8203,0x0000, 0xFBC2,0x8204,0x0000, 0xFBC2,0x8205,0x0000, /* 10203 */ +0xFBC2,0x8206,0x0000, 0xFBC2,0x8207,0x0000, 0xFBC2,0x8208,0x0000, /* 10206 */ +0xFBC2,0x8209,0x0000, 0xFBC2,0x820A,0x0000, 0xFBC2,0x820B,0x0000, /* 10209 */ +0xFBC2,0x820C,0x0000, 0xFBC2,0x820D,0x0000, 0xFBC2,0x820E,0x0000, /* 1020C */ +0xFBC2,0x820F,0x0000, 0xFBC2,0x8210,0x0000, 0xFBC2,0x8211,0x0000, /* 1020F */ +0xFBC2,0x8212,0x0000, 0xFBC2,0x8213,0x0000, 0xFBC2,0x8214,0x0000, /* 10212 */ +0xFBC2,0x8215,0x0000, 0xFBC2,0x8216,0x0000, 0xFBC2,0x8217,0x0000, /* 10215 */ +0xFBC2,0x8218,0x0000, 0xFBC2,0x8219,0x0000, 0xFBC2,0x821A,0x0000, /* 10218 */ +0xFBC2,0x821B,0x0000, 0xFBC2,0x821C,0x0000, 0xFBC2,0x821D,0x0000, /* 1021B */ +0xFBC2,0x821E,0x0000, 0xFBC2,0x821F,0x0000, 0xFBC2,0x8220,0x0000, /* 1021E */ +0xFBC2,0x8221,0x0000, 0xFBC2,0x8222,0x0000, 0xFBC2,0x8223,0x0000, /* 10221 */ +0xFBC2,0x8224,0x0000, 0xFBC2,0x8225,0x0000, 0xFBC2,0x8226,0x0000, /* 10224 */ +0xFBC2,0x8227,0x0000, 0xFBC2,0x8228,0x0000, 0xFBC2,0x8229,0x0000, /* 10227 */ +0xFBC2,0x822A,0x0000, 0xFBC2,0x822B,0x0000, 0xFBC2,0x822C,0x0000, /* 1022A */ +0xFBC2,0x822D,0x0000, 0xFBC2,0x822E,0x0000, 0xFBC2,0x822F,0x0000, /* 1022D */ +0xFBC2,0x8230,0x0000, 0xFBC2,0x8231,0x0000, 0xFBC2,0x8232,0x0000, /* 10230 */ +0xFBC2,0x8233,0x0000, 0xFBC2,0x8234,0x0000, 0xFBC2,0x8235,0x0000, /* 10233 */ +0xFBC2,0x8236,0x0000, 0xFBC2,0x8237,0x0000, 0xFBC2,0x8238,0x0000, /* 10236 */ +0xFBC2,0x8239,0x0000, 0xFBC2,0x823A,0x0000, 0xFBC2,0x823B,0x0000, /* 10239 */ +0xFBC2,0x823C,0x0000, 0xFBC2,0x823D,0x0000, 0xFBC2,0x823E,0x0000, /* 1023C */ +0xFBC2,0x823F,0x0000, 0xFBC2,0x8240,0x0000, 0xFBC2,0x8241,0x0000, /* 1023F */ +0xFBC2,0x8242,0x0000, 0xFBC2,0x8243,0x0000, 0xFBC2,0x8244,0x0000, /* 10242 */ +0xFBC2,0x8245,0x0000, 0xFBC2,0x8246,0x0000, 0xFBC2,0x8247,0x0000, /* 10245 */ +0xFBC2,0x8248,0x0000, 0xFBC2,0x8249,0x0000, 0xFBC2,0x824A,0x0000, /* 10248 */ +0xFBC2,0x824B,0x0000, 0xFBC2,0x824C,0x0000, 0xFBC2,0x824D,0x0000, /* 1024B */ +0xFBC2,0x824E,0x0000, 0xFBC2,0x824F,0x0000, 0xFBC2,0x8250,0x0000, /* 1024E */ +0xFBC2,0x8251,0x0000, 0xFBC2,0x8252,0x0000, 0xFBC2,0x8253,0x0000, /* 10251 */ +0xFBC2,0x8254,0x0000, 0xFBC2,0x8255,0x0000, 0xFBC2,0x8256,0x0000, /* 10254 */ +0xFBC2,0x8257,0x0000, 0xFBC2,0x8258,0x0000, 0xFBC2,0x8259,0x0000, /* 10257 */ +0xFBC2,0x825A,0x0000, 0xFBC2,0x825B,0x0000, 0xFBC2,0x825C,0x0000, /* 1025A */ +0xFBC2,0x825D,0x0000, 0xFBC2,0x825E,0x0000, 0xFBC2,0x825F,0x0000, /* 1025D */ +0xFBC2,0x8260,0x0000, 0xFBC2,0x8261,0x0000, 0xFBC2,0x8262,0x0000, /* 10260 */ +0xFBC2,0x8263,0x0000, 0xFBC2,0x8264,0x0000, 0xFBC2,0x8265,0x0000, /* 10263 */ +0xFBC2,0x8266,0x0000, 0xFBC2,0x8267,0x0000, 0xFBC2,0x8268,0x0000, /* 10266 */ +0xFBC2,0x8269,0x0000, 0xFBC2,0x826A,0x0000, 0xFBC2,0x826B,0x0000, /* 10269 */ +0xFBC2,0x826C,0x0000, 0xFBC2,0x826D,0x0000, 0xFBC2,0x826E,0x0000, /* 1026C */ +0xFBC2,0x826F,0x0000, 0xFBC2,0x8270,0x0000, 0xFBC2,0x8271,0x0000, /* 1026F */ +0xFBC2,0x8272,0x0000, 0xFBC2,0x8273,0x0000, 0xFBC2,0x8274,0x0000, /* 10272 */ +0xFBC2,0x8275,0x0000, 0xFBC2,0x8276,0x0000, 0xFBC2,0x8277,0x0000, /* 10275 */ +0xFBC2,0x8278,0x0000, 0xFBC2,0x8279,0x0000, 0xFBC2,0x827A,0x0000, /* 10278 */ +0xFBC2,0x827B,0x0000, 0xFBC2,0x827C,0x0000, 0xFBC2,0x827D,0x0000, /* 1027B */ +0xFBC2,0x827E,0x0000, 0xFBC2,0x827F,0x0000, 0x3030,0x0000,0x0000, /* 1027E */ +0x3031,0x0000,0x0000, 0x3032,0x0000,0x0000, 0x3033,0x0000,0x0000, /* 10281 */ +0x3034,0x0000,0x0000, 0x3035,0x0000,0x0000, 0x3036,0x0000,0x0000, /* 10284 */ +0x3037,0x0000,0x0000, 0x3038,0x0000,0x0000, 0x3039,0x0000,0x0000, /* 10287 */ +0x303A,0x0000,0x0000, 0x303B,0x0000,0x0000, 0x303C,0x0000,0x0000, /* 1028A */ +0x303D,0x0000,0x0000, 0x303E,0x0000,0x0000, 0x303F,0x0000,0x0000, /* 1028D */ +0x3040,0x0000,0x0000, 0x3041,0x0000,0x0000, 0x3042,0x0000,0x0000, /* 10290 */ +0x3043,0x0000,0x0000, 0x3044,0x0000,0x0000, 0x3045,0x0000,0x0000, /* 10293 */ +0x3046,0x0000,0x0000, 0x3047,0x0000,0x0000, 0x3048,0x0000,0x0000, /* 10296 */ +0x3049,0x0000,0x0000, 0x304A,0x0000,0x0000, 0x304B,0x0000,0x0000, /* 10299 */ +0x304C,0x0000,0x0000, 0xFBC2,0x829D,0x0000, 0xFBC2,0x829E,0x0000, /* 1029C */ +0xFBC2,0x829F,0x0000, 0x304D,0x0000,0x0000, 0x304E,0x0000,0x0000, /* 1029F */ +0x304F,0x0000,0x0000, 0x3050,0x0000,0x0000, 0x3051,0x0000,0x0000, /* 102A2 */ +0x3052,0x0000,0x0000, 0x3053,0x0000,0x0000, 0x3054,0x0000,0x0000, /* 102A5 */ +0x3055,0x0000,0x0000, 0x3056,0x0000,0x0000, 0x3057,0x0000,0x0000, /* 102A8 */ +0x3058,0x0000,0x0000, 0x3059,0x0000,0x0000, 0x305A,0x0000,0x0000, /* 102AB */ +0x305B,0x0000,0x0000, 0x305C,0x0000,0x0000, 0x305D,0x0000,0x0000, /* 102AE */ +0x305E,0x0000,0x0000, 0x305F,0x0000,0x0000, 0x3060,0x0000,0x0000, /* 102B1 */ +0x3061,0x0000,0x0000, 0x3062,0x0000,0x0000, 0x3063,0x0000,0x0000, /* 102B4 */ +0x3064,0x0000,0x0000, 0x3065,0x0000,0x0000, 0x3066,0x0000,0x0000, /* 102B7 */ +0x3067,0x0000,0x0000, 0x3068,0x0000,0x0000, 0x3069,0x0000,0x0000, /* 102BA */ +0x306A,0x0000,0x0000, 0x306B,0x0000,0x0000, 0x306C,0x0000,0x0000, /* 102BD */ +0x306D,0x0000,0x0000, 0x306E,0x0000,0x0000, 0x306F,0x0000,0x0000, /* 102C0 */ +0x3070,0x0000,0x0000, 0x3071,0x0000,0x0000, 0x3072,0x0000,0x0000, /* 102C3 */ +0x3073,0x0000,0x0000, 0x3074,0x0000,0x0000, 0x3075,0x0000,0x0000, /* 102C6 */ +0x3076,0x0000,0x0000, 0x3077,0x0000,0x0000, 0x3078,0x0000,0x0000, /* 102C9 */ +0x3079,0x0000,0x0000, 0x307A,0x0000,0x0000, 0x307B,0x0000,0x0000, /* 102CC */ +0x307C,0x0000,0x0000, 0x307D,0x0000,0x0000, 0xFBC2,0x82D1,0x0000, /* 102CF */ +0xFBC2,0x82D2,0x0000, 0xFBC2,0x82D3,0x0000, 0xFBC2,0x82D4,0x0000, /* 102D2 */ +0xFBC2,0x82D5,0x0000, 0xFBC2,0x82D6,0x0000, 0xFBC2,0x82D7,0x0000, /* 102D5 */ +0xFBC2,0x82D8,0x0000, 0xFBC2,0x82D9,0x0000, 0xFBC2,0x82DA,0x0000, /* 102D8 */ +0xFBC2,0x82DB,0x0000, 0xFBC2,0x82DC,0x0000, 0xFBC2,0x82DD,0x0000, /* 102DB */ +0xFBC2,0x82DE,0x0000, 0xFBC2,0x82DF,0x0000, 0xFBC2,0x82E0,0x0000, /* 102DE */ +0xFBC2,0x82E1,0x0000, 0xFBC2,0x82E2,0x0000, 0xFBC2,0x82E3,0x0000, /* 102E1 */ +0xFBC2,0x82E4,0x0000, 0xFBC2,0x82E5,0x0000, 0xFBC2,0x82E6,0x0000, /* 102E4 */ +0xFBC2,0x82E7,0x0000, 0xFBC2,0x82E8,0x0000, 0xFBC2,0x82E9,0x0000, /* 102E7 */ +0xFBC2,0x82EA,0x0000, 0xFBC2,0x82EB,0x0000, 0xFBC2,0x82EC,0x0000, /* 102EA */ +0xFBC2,0x82ED,0x0000, 0xFBC2,0x82EE,0x0000, 0xFBC2,0x82EF,0x0000, /* 102ED */ +0xFBC2,0x82F0,0x0000, 0xFBC2,0x82F1,0x0000, 0xFBC2,0x82F2,0x0000, /* 102F0 */ +0xFBC2,0x82F3,0x0000, 0xFBC2,0x82F4,0x0000, 0xFBC2,0x82F5,0x0000, /* 102F3 */ +0xFBC2,0x82F6,0x0000, 0xFBC2,0x82F7,0x0000, 0xFBC2,0x82F8,0x0000, /* 102F6 */ +0xFBC2,0x82F9,0x0000, 0xFBC2,0x82FA,0x0000, 0xFBC2,0x82FB,0x0000, /* 102F9 */ +0xFBC2,0x82FC,0x0000, 0xFBC2,0x82FD,0x0000, 0xFBC2,0x82FE,0x0000, /* 102FC */ +0xFBC2,0x82FF,0x0000 }; + +uint16 uca520_p103[]= { /* 10300 (3 weights per char) */ +0x3098,0x0000,0x0000, 0x3099,0x0000,0x0000, 0x309A,0x0000,0x0000, /* 10300 */ +0x309B,0x0000,0x0000, 0x309C,0x0000,0x0000, 0x309D,0x0000,0x0000, /* 10303 */ +0x309E,0x0000,0x0000, 0x309F,0x0000,0x0000, 0x30A0,0x0000,0x0000, /* 10306 */ +0x30A1,0x0000,0x0000, 0x30A2,0x0000,0x0000, 0x30A3,0x0000,0x0000, /* 10309 */ +0x30A4,0x0000,0x0000, 0x30A5,0x0000,0x0000, 0x30A6,0x0000,0x0000, /* 1030C */ +0x30A7,0x0000,0x0000, 0x30A8,0x0000,0x0000, 0x30A9,0x0000,0x0000, /* 1030F */ +0x30AA,0x0000,0x0000, 0x30AB,0x0000,0x0000, 0x30AC,0x0000,0x0000, /* 10312 */ +0x30AD,0x0000,0x0000, 0x30AE,0x0000,0x0000, 0x30AF,0x0000,0x0000, /* 10315 */ +0x30B0,0x0000,0x0000, 0x30B1,0x0000,0x0000, 0x30B2,0x0000,0x0000, /* 10318 */ +0x30B3,0x0000,0x0000, 0x30B4,0x0000,0x0000, 0x30B5,0x0000,0x0000, /* 1031B */ +0x30B6,0x0000,0x0000, 0xFBC2,0x831F,0x0000, 0x1206,0x0000,0x0000, /* 1031E */ +0x120A,0x0000,0x0000, 0x114D,0x0000,0x0000, 0x114E,0x0000,0x0000, /* 10321 */ +0xFBC2,0x8324,0x0000, 0xFBC2,0x8325,0x0000, 0xFBC2,0x8326,0x0000, /* 10324 */ +0xFBC2,0x8327,0x0000, 0xFBC2,0x8328,0x0000, 0xFBC2,0x8329,0x0000, /* 10327 */ +0xFBC2,0x832A,0x0000, 0xFBC2,0x832B,0x0000, 0xFBC2,0x832C,0x0000, /* 1032A */ +0xFBC2,0x832D,0x0000, 0xFBC2,0x832E,0x0000, 0xFBC2,0x832F,0x0000, /* 1032D */ +0x30B7,0x0000,0x0000, 0x30B8,0x0000,0x0000, 0x30B9,0x0000,0x0000, /* 10330 */ +0x30BA,0x0000,0x0000, 0x30BB,0x0000,0x0000, 0x30BC,0x0000,0x0000, /* 10333 */ +0x30BD,0x0000,0x0000, 0x30BE,0x0000,0x0000, 0x30BF,0x0000,0x0000, /* 10336 */ +0x30C0,0x0000,0x0000, 0x30C1,0x0000,0x0000, 0x30C2,0x0000,0x0000, /* 10339 */ +0x30C3,0x0000,0x0000, 0x30C4,0x0000,0x0000, 0x30C5,0x0000,0x0000, /* 1033C */ +0x30C6,0x0000,0x0000, 0x30C7,0x0000,0x0000, 0x30C8,0x0000,0x0000, /* 1033F */ +0x30C9,0x0000,0x0000, 0x30CA,0x0000,0x0000, 0x30CB,0x0000,0x0000, /* 10342 */ +0x30CC,0x0000,0x0000, 0x30CD,0x0000,0x0000, 0x30CE,0x0000,0x0000, /* 10345 */ +0x30CF,0x0000,0x0000, 0x30D0,0x0000,0x0000, 0x30D1,0x0000,0x0000, /* 10348 */ +0xFBC2,0x834B,0x0000, 0xFBC2,0x834C,0x0000, 0xFBC2,0x834D,0x0000, /* 1034B */ +0xFBC2,0x834E,0x0000, 0xFBC2,0x834F,0x0000, 0xFBC2,0x8350,0x0000, /* 1034E */ +0xFBC2,0x8351,0x0000, 0xFBC2,0x8352,0x0000, 0xFBC2,0x8353,0x0000, /* 10351 */ +0xFBC2,0x8354,0x0000, 0xFBC2,0x8355,0x0000, 0xFBC2,0x8356,0x0000, /* 10354 */ +0xFBC2,0x8357,0x0000, 0xFBC2,0x8358,0x0000, 0xFBC2,0x8359,0x0000, /* 10357 */ +0xFBC2,0x835A,0x0000, 0xFBC2,0x835B,0x0000, 0xFBC2,0x835C,0x0000, /* 1035A */ +0xFBC2,0x835D,0x0000, 0xFBC2,0x835E,0x0000, 0xFBC2,0x835F,0x0000, /* 1035D */ +0xFBC2,0x8360,0x0000, 0xFBC2,0x8361,0x0000, 0xFBC2,0x8362,0x0000, /* 10360 */ +0xFBC2,0x8363,0x0000, 0xFBC2,0x8364,0x0000, 0xFBC2,0x8365,0x0000, /* 10363 */ +0xFBC2,0x8366,0x0000, 0xFBC2,0x8367,0x0000, 0xFBC2,0x8368,0x0000, /* 10366 */ +0xFBC2,0x8369,0x0000, 0xFBC2,0x836A,0x0000, 0xFBC2,0x836B,0x0000, /* 10369 */ +0xFBC2,0x836C,0x0000, 0xFBC2,0x836D,0x0000, 0xFBC2,0x836E,0x0000, /* 1036C */ +0xFBC2,0x836F,0x0000, 0xFBC2,0x8370,0x0000, 0xFBC2,0x8371,0x0000, /* 1036F */ +0xFBC2,0x8372,0x0000, 0xFBC2,0x8373,0x0000, 0xFBC2,0x8374,0x0000, /* 10372 */ +0xFBC2,0x8375,0x0000, 0xFBC2,0x8376,0x0000, 0xFBC2,0x8377,0x0000, /* 10375 */ +0xFBC2,0x8378,0x0000, 0xFBC2,0x8379,0x0000, 0xFBC2,0x837A,0x0000, /* 10378 */ +0xFBC2,0x837B,0x0000, 0xFBC2,0x837C,0x0000, 0xFBC2,0x837D,0x0000, /* 1037B */ +0xFBC2,0x837E,0x0000, 0xFBC2,0x837F,0x0000, 0x32E3,0x0000,0x0000, /* 1037E */ +0x32E4,0x0000,0x0000, 0x32E5,0x0000,0x0000, 0x32E6,0x0000,0x0000, /* 10381 */ +0x32E7,0x0000,0x0000, 0x32E8,0x0000,0x0000, 0x32E9,0x0000,0x0000, /* 10384 */ +0x32EA,0x0000,0x0000, 0x32EB,0x0000,0x0000, 0x32EC,0x0000,0x0000, /* 10387 */ +0x32ED,0x0000,0x0000, 0x32EE,0x0000,0x0000, 0x32EF,0x0000,0x0000, /* 1038A */ +0x32F0,0x0000,0x0000, 0x32F1,0x0000,0x0000, 0x32F2,0x0000,0x0000, /* 1038D */ +0x32F3,0x0000,0x0000, 0x32F4,0x0000,0x0000, 0x32F5,0x0000,0x0000, /* 10390 */ +0x32F6,0x0000,0x0000, 0x32F7,0x0000,0x0000, 0x32F8,0x0000,0x0000, /* 10393 */ +0x32F9,0x0000,0x0000, 0x32FA,0x0000,0x0000, 0x32FB,0x0000,0x0000, /* 10396 */ +0x32FC,0x0000,0x0000, 0x32FD,0x0000,0x0000, 0x32FE,0x0000,0x0000, /* 10399 */ +0x32FF,0x0000,0x0000, 0x3300,0x0000,0x0000, 0xFBC2,0x839E,0x0000, /* 1039C */ +0x02E7,0x0000,0x0000, 0x3301,0x0000,0x0000, 0x3302,0x0000,0x0000, /* 1039F */ +0x3303,0x0000,0x0000, 0x3304,0x0000,0x0000, 0x3305,0x0000,0x0000, /* 103A2 */ +0x3306,0x0000,0x0000, 0x3307,0x0000,0x0000, 0x3308,0x0000,0x0000, /* 103A5 */ +0x3309,0x0000,0x0000, 0x330A,0x0000,0x0000, 0x330B,0x0000,0x0000, /* 103A8 */ +0x330C,0x0000,0x0000, 0x330D,0x0000,0x0000, 0x330E,0x0000,0x0000, /* 103AB */ +0x330F,0x0000,0x0000, 0x3310,0x0000,0x0000, 0x3311,0x0000,0x0000, /* 103AE */ +0x3312,0x0000,0x0000, 0x3313,0x0000,0x0000, 0x3314,0x0000,0x0000, /* 103B1 */ +0x3315,0x0000,0x0000, 0x3316,0x0000,0x0000, 0x3317,0x0000,0x0000, /* 103B4 */ +0x3318,0x0000,0x0000, 0x3319,0x0000,0x0000, 0x331A,0x0000,0x0000, /* 103B7 */ +0x331B,0x0000,0x0000, 0x331C,0x0000,0x0000, 0x331D,0x0000,0x0000, /* 103BA */ +0x331E,0x0000,0x0000, 0x331F,0x0000,0x0000, 0x3320,0x0000,0x0000, /* 103BD */ +0x3321,0x0000,0x0000, 0x3322,0x0000,0x0000, 0x3323,0x0000,0x0000, /* 103C0 */ +0x3324,0x0000,0x0000, 0xFBC2,0x83C4,0x0000, 0xFBC2,0x83C5,0x0000, /* 103C3 */ +0xFBC2,0x83C6,0x0000, 0xFBC2,0x83C7,0x0000, 0x3325,0x0000,0x0000, /* 103C6 */ +0x3326,0x0000,0x0000, 0x3327,0x0000,0x0000, 0x3328,0x0000,0x0000, /* 103C9 */ +0x3329,0x0000,0x0000, 0x332A,0x0000,0x0000, 0x332B,0x0000,0x0000, /* 103CC */ +0x332C,0x0000,0x0000, 0x02E8,0x0000,0x0000, 0x1206,0x0000,0x0000, /* 103CF */ +0x1207,0x0000,0x0000, 0x119F,0x0000,0x0000, 0x11A0,0x0000,0x0000, /* 103D2 */ +0x11A1,0x0000,0x0000, 0xFBC2,0x83D6,0x0000, 0xFBC2,0x83D7,0x0000, /* 103D5 */ +0xFBC2,0x83D8,0x0000, 0xFBC2,0x83D9,0x0000, 0xFBC2,0x83DA,0x0000, /* 103D8 */ +0xFBC2,0x83DB,0x0000, 0xFBC2,0x83DC,0x0000, 0xFBC2,0x83DD,0x0000, /* 103DB */ +0xFBC2,0x83DE,0x0000, 0xFBC2,0x83DF,0x0000, 0xFBC2,0x83E0,0x0000, /* 103DE */ +0xFBC2,0x83E1,0x0000, 0xFBC2,0x83E2,0x0000, 0xFBC2,0x83E3,0x0000, /* 103E1 */ +0xFBC2,0x83E4,0x0000, 0xFBC2,0x83E5,0x0000, 0xFBC2,0x83E6,0x0000, /* 103E4 */ +0xFBC2,0x83E7,0x0000, 0xFBC2,0x83E8,0x0000, 0xFBC2,0x83E9,0x0000, /* 103E7 */ +0xFBC2,0x83EA,0x0000, 0xFBC2,0x83EB,0x0000, 0xFBC2,0x83EC,0x0000, /* 103EA */ +0xFBC2,0x83ED,0x0000, 0xFBC2,0x83EE,0x0000, 0xFBC2,0x83EF,0x0000, /* 103ED */ +0xFBC2,0x83F0,0x0000, 0xFBC2,0x83F1,0x0000, 0xFBC2,0x83F2,0x0000, /* 103F0 */ +0xFBC2,0x83F3,0x0000, 0xFBC2,0x83F4,0x0000, 0xFBC2,0x83F5,0x0000, /* 103F3 */ +0xFBC2,0x83F6,0x0000, 0xFBC2,0x83F7,0x0000, 0xFBC2,0x83F8,0x0000, /* 103F6 */ +0xFBC2,0x83F9,0x0000, 0xFBC2,0x83FA,0x0000, 0xFBC2,0x83FB,0x0000, /* 103F9 */ +0xFBC2,0x83FC,0x0000, 0xFBC2,0x83FD,0x0000, 0xFBC2,0x83FE,0x0000, /* 103FC */ +0xFBC2,0x83FF,0x0000 }; + +uint16 uca520_p104[]= { /* 10400 (3 weights per char) */ +0x30D2,0x0000,0x0000, 0x30D3,0x0000,0x0000, 0x30D4,0x0000,0x0000, /* 10400 */ +0x30D5,0x0000,0x0000, 0x30D6,0x0000,0x0000, 0x30D7,0x0000,0x0000, /* 10403 */ +0x30D8,0x0000,0x0000, 0x30D9,0x0000,0x0000, 0x30DA,0x0000,0x0000, /* 10406 */ +0x30DB,0x0000,0x0000, 0x30DC,0x0000,0x0000, 0x30DD,0x0000,0x0000, /* 10409 */ +0x30DE,0x0000,0x0000, 0x30DF,0x0000,0x0000, 0x30E0,0x0000,0x0000, /* 1040C */ +0x30E1,0x0000,0x0000, 0x30E2,0x0000,0x0000, 0x30E3,0x0000,0x0000, /* 1040F */ +0x30E4,0x0000,0x0000, 0x30E5,0x0000,0x0000, 0x30E6,0x0000,0x0000, /* 10412 */ +0x30E7,0x0000,0x0000, 0x30E8,0x0000,0x0000, 0x30E9,0x0000,0x0000, /* 10415 */ +0x30EA,0x0000,0x0000, 0x30EB,0x0000,0x0000, 0x30EC,0x0000,0x0000, /* 10418 */ +0x30ED,0x0000,0x0000, 0x30EE,0x0000,0x0000, 0x30EF,0x0000,0x0000, /* 1041B */ +0x30F0,0x0000,0x0000, 0x30F1,0x0000,0x0000, 0x30F2,0x0000,0x0000, /* 1041E */ +0x30F3,0x0000,0x0000, 0x30F4,0x0000,0x0000, 0x30F5,0x0000,0x0000, /* 10421 */ +0x30F6,0x0000,0x0000, 0x30F7,0x0000,0x0000, 0x30F8,0x0000,0x0000, /* 10424 */ +0x30F9,0x0000,0x0000, 0x30D2,0x0000,0x0000, 0x30D3,0x0000,0x0000, /* 10427 */ +0x30D4,0x0000,0x0000, 0x30D5,0x0000,0x0000, 0x30D6,0x0000,0x0000, /* 1042A */ +0x30D7,0x0000,0x0000, 0x30D8,0x0000,0x0000, 0x30D9,0x0000,0x0000, /* 1042D */ +0x30DA,0x0000,0x0000, 0x30DB,0x0000,0x0000, 0x30DC,0x0000,0x0000, /* 10430 */ +0x30DD,0x0000,0x0000, 0x30DE,0x0000,0x0000, 0x30DF,0x0000,0x0000, /* 10433 */ +0x30E0,0x0000,0x0000, 0x30E1,0x0000,0x0000, 0x30E2,0x0000,0x0000, /* 10436 */ +0x30E3,0x0000,0x0000, 0x30E4,0x0000,0x0000, 0x30E5,0x0000,0x0000, /* 10439 */ +0x30E6,0x0000,0x0000, 0x30E7,0x0000,0x0000, 0x30E8,0x0000,0x0000, /* 1043C */ +0x30E9,0x0000,0x0000, 0x30EA,0x0000,0x0000, 0x30EB,0x0000,0x0000, /* 1043F */ +0x30EC,0x0000,0x0000, 0x30ED,0x0000,0x0000, 0x30EE,0x0000,0x0000, /* 10442 */ +0x30EF,0x0000,0x0000, 0x30F0,0x0000,0x0000, 0x30F1,0x0000,0x0000, /* 10445 */ +0x30F2,0x0000,0x0000, 0x30F3,0x0000,0x0000, 0x30F4,0x0000,0x0000, /* 10448 */ +0x30F5,0x0000,0x0000, 0x30F6,0x0000,0x0000, 0x30F7,0x0000,0x0000, /* 1044B */ +0x30F8,0x0000,0x0000, 0x30F9,0x0000,0x0000, 0x30FA,0x0000,0x0000, /* 1044E */ +0x30FB,0x0000,0x0000, 0x30FC,0x0000,0x0000, 0x30FD,0x0000,0x0000, /* 10451 */ +0x30FE,0x0000,0x0000, 0x30FF,0x0000,0x0000, 0x3100,0x0000,0x0000, /* 10454 */ +0x3101,0x0000,0x0000, 0x3102,0x0000,0x0000, 0x3103,0x0000,0x0000, /* 10457 */ +0x3104,0x0000,0x0000, 0x3105,0x0000,0x0000, 0x3106,0x0000,0x0000, /* 1045A */ +0x3107,0x0000,0x0000, 0x3108,0x0000,0x0000, 0x3109,0x0000,0x0000, /* 1045D */ +0x310A,0x0000,0x0000, 0x310B,0x0000,0x0000, 0x310C,0x0000,0x0000, /* 10460 */ +0x310D,0x0000,0x0000, 0x310E,0x0000,0x0000, 0x310F,0x0000,0x0000, /* 10463 */ +0x3110,0x0000,0x0000, 0x3111,0x0000,0x0000, 0x3112,0x0000,0x0000, /* 10466 */ +0x3113,0x0000,0x0000, 0x3114,0x0000,0x0000, 0x3115,0x0000,0x0000, /* 10469 */ +0x3116,0x0000,0x0000, 0x3117,0x0000,0x0000, 0x3118,0x0000,0x0000, /* 1046C */ +0x3119,0x0000,0x0000, 0x311A,0x0000,0x0000, 0x311B,0x0000,0x0000, /* 1046F */ +0x311C,0x0000,0x0000, 0x311D,0x0000,0x0000, 0x311E,0x0000,0x0000, /* 10472 */ +0x311F,0x0000,0x0000, 0x3120,0x0000,0x0000, 0x3121,0x0000,0x0000, /* 10475 */ +0x3122,0x0000,0x0000, 0x3123,0x0000,0x0000, 0x3124,0x0000,0x0000, /* 10478 */ +0x3125,0x0000,0x0000, 0x3126,0x0000,0x0000, 0x3127,0x0000,0x0000, /* 1047B */ +0x3128,0x0000,0x0000, 0x3129,0x0000,0x0000, 0x312A,0x0000,0x0000, /* 1047E */ +0x312B,0x0000,0x0000, 0x312C,0x0000,0x0000, 0x312D,0x0000,0x0000, /* 10481 */ +0x312E,0x0000,0x0000, 0x312F,0x0000,0x0000, 0x3130,0x0000,0x0000, /* 10484 */ +0x3131,0x0000,0x0000, 0x3132,0x0000,0x0000, 0x3133,0x0000,0x0000, /* 10487 */ +0x3134,0x0000,0x0000, 0x3135,0x0000,0x0000, 0x3136,0x0000,0x0000, /* 1048A */ +0x3137,0x0000,0x0000, 0x3138,0x0000,0x0000, 0x3139,0x0000,0x0000, /* 1048D */ +0x313A,0x0000,0x0000, 0x313B,0x0000,0x0000, 0x313C,0x0000,0x0000, /* 10490 */ +0x313D,0x0000,0x0000, 0x313E,0x0000,0x0000, 0x313F,0x0000,0x0000, /* 10493 */ +0x3140,0x0000,0x0000, 0x3141,0x0000,0x0000, 0x3142,0x0000,0x0000, /* 10496 */ +0x3143,0x0000,0x0000, 0x3144,0x0000,0x0000, 0x3145,0x0000,0x0000, /* 10499 */ +0x3146,0x0000,0x0000, 0x3147,0x0000,0x0000, 0xFBC2,0x849E,0x0000, /* 1049C */ +0xFBC2,0x849F,0x0000, 0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, /* 1049F */ +0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, /* 104A2 */ +0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, /* 104A5 */ +0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, 0xFBC2,0x84AA,0x0000, /* 104A8 */ +0xFBC2,0x84AB,0x0000, 0xFBC2,0x84AC,0x0000, 0xFBC2,0x84AD,0x0000, /* 104AB */ +0xFBC2,0x84AE,0x0000, 0xFBC2,0x84AF,0x0000, 0xFBC2,0x84B0,0x0000, /* 104AE */ +0xFBC2,0x84B1,0x0000, 0xFBC2,0x84B2,0x0000, 0xFBC2,0x84B3,0x0000, /* 104B1 */ +0xFBC2,0x84B4,0x0000, 0xFBC2,0x84B5,0x0000, 0xFBC2,0x84B6,0x0000, /* 104B4 */ +0xFBC2,0x84B7,0x0000, 0xFBC2,0x84B8,0x0000, 0xFBC2,0x84B9,0x0000, /* 104B7 */ +0xFBC2,0x84BA,0x0000, 0xFBC2,0x84BB,0x0000, 0xFBC2,0x84BC,0x0000, /* 104BA */ +0xFBC2,0x84BD,0x0000, 0xFBC2,0x84BE,0x0000, 0xFBC2,0x84BF,0x0000, /* 104BD */ +0xFBC2,0x84C0,0x0000, 0xFBC2,0x84C1,0x0000, 0xFBC2,0x84C2,0x0000, /* 104C0 */ +0xFBC2,0x84C3,0x0000, 0xFBC2,0x84C4,0x0000, 0xFBC2,0x84C5,0x0000, /* 104C3 */ +0xFBC2,0x84C6,0x0000, 0xFBC2,0x84C7,0x0000, 0xFBC2,0x84C8,0x0000, /* 104C6 */ +0xFBC2,0x84C9,0x0000, 0xFBC2,0x84CA,0x0000, 0xFBC2,0x84CB,0x0000, /* 104C9 */ +0xFBC2,0x84CC,0x0000, 0xFBC2,0x84CD,0x0000, 0xFBC2,0x84CE,0x0000, /* 104CC */ +0xFBC2,0x84CF,0x0000, 0xFBC2,0x84D0,0x0000, 0xFBC2,0x84D1,0x0000, /* 104CF */ +0xFBC2,0x84D2,0x0000, 0xFBC2,0x84D3,0x0000, 0xFBC2,0x84D4,0x0000, /* 104D2 */ +0xFBC2,0x84D5,0x0000, 0xFBC2,0x84D6,0x0000, 0xFBC2,0x84D7,0x0000, /* 104D5 */ +0xFBC2,0x84D8,0x0000, 0xFBC2,0x84D9,0x0000, 0xFBC2,0x84DA,0x0000, /* 104D8 */ +0xFBC2,0x84DB,0x0000, 0xFBC2,0x84DC,0x0000, 0xFBC2,0x84DD,0x0000, /* 104DB */ +0xFBC2,0x84DE,0x0000, 0xFBC2,0x84DF,0x0000, 0xFBC2,0x84E0,0x0000, /* 104DE */ +0xFBC2,0x84E1,0x0000, 0xFBC2,0x84E2,0x0000, 0xFBC2,0x84E3,0x0000, /* 104E1 */ +0xFBC2,0x84E4,0x0000, 0xFBC2,0x84E5,0x0000, 0xFBC2,0x84E6,0x0000, /* 104E4 */ +0xFBC2,0x84E7,0x0000, 0xFBC2,0x84E8,0x0000, 0xFBC2,0x84E9,0x0000, /* 104E7 */ +0xFBC2,0x84EA,0x0000, 0xFBC2,0x84EB,0x0000, 0xFBC2,0x84EC,0x0000, /* 104EA */ +0xFBC2,0x84ED,0x0000, 0xFBC2,0x84EE,0x0000, 0xFBC2,0x84EF,0x0000, /* 104ED */ +0xFBC2,0x84F0,0x0000, 0xFBC2,0x84F1,0x0000, 0xFBC2,0x84F2,0x0000, /* 104F0 */ +0xFBC2,0x84F3,0x0000, 0xFBC2,0x84F4,0x0000, 0xFBC2,0x84F5,0x0000, /* 104F3 */ +0xFBC2,0x84F6,0x0000, 0xFBC2,0x84F7,0x0000, 0xFBC2,0x84F8,0x0000, /* 104F6 */ +0xFBC2,0x84F9,0x0000, 0xFBC2,0x84FA,0x0000, 0xFBC2,0x84FB,0x0000, /* 104F9 */ +0xFBC2,0x84FC,0x0000, 0xFBC2,0x84FD,0x0000, 0xFBC2,0x84FE,0x0000, /* 104FC */ +0xFBC2,0x84FF,0x0000 }; + +uint16 uca520_p108[]= { /* 10800 (3 weights per char) */ +0x321B,0x0000,0x0000, 0x321C,0x0000,0x0000, 0x321D,0x0000,0x0000, /* 10800 */ +0x321E,0x0000,0x0000, 0x321F,0x0000,0x0000, 0x3220,0x0000,0x0000, /* 10803 */ +0xFBC2,0x8806,0x0000, 0xFBC2,0x8807,0x0000, 0x3221,0x0000,0x0000, /* 10806 */ +0xFBC2,0x8809,0x0000, 0x3222,0x0000,0x0000, 0x3223,0x0000,0x0000, /* 10809 */ +0x3224,0x0000,0x0000, 0x3225,0x0000,0x0000, 0x3226,0x0000,0x0000, /* 1080C */ +0x3227,0x0000,0x0000, 0x3228,0x0000,0x0000, 0x3229,0x0000,0x0000, /* 1080F */ +0x322A,0x0000,0x0000, 0x322B,0x0000,0x0000, 0x322C,0x0000,0x0000, /* 10812 */ +0x322D,0x0000,0x0000, 0x322E,0x0000,0x0000, 0x322F,0x0000,0x0000, /* 10815 */ +0x3230,0x0000,0x0000, 0x3231,0x0000,0x0000, 0x3232,0x0000,0x0000, /* 10818 */ +0x3233,0x0000,0x0000, 0x3234,0x0000,0x0000, 0x3235,0x0000,0x0000, /* 1081B */ +0x3236,0x0000,0x0000, 0x3237,0x0000,0x0000, 0x3238,0x0000,0x0000, /* 1081E */ +0x3239,0x0000,0x0000, 0x323A,0x0000,0x0000, 0x323B,0x0000,0x0000, /* 10821 */ +0x323C,0x0000,0x0000, 0x323D,0x0000,0x0000, 0x323E,0x0000,0x0000, /* 10824 */ +0x323F,0x0000,0x0000, 0x3240,0x0000,0x0000, 0x3241,0x0000,0x0000, /* 10827 */ +0x3242,0x0000,0x0000, 0x3243,0x0000,0x0000, 0x3244,0x0000,0x0000, /* 1082A */ +0x3245,0x0000,0x0000, 0x3246,0x0000,0x0000, 0x3247,0x0000,0x0000, /* 1082D */ +0x3248,0x0000,0x0000, 0x3249,0x0000,0x0000, 0x324A,0x0000,0x0000, /* 10830 */ +0x324B,0x0000,0x0000, 0x324C,0x0000,0x0000, 0x324D,0x0000,0x0000, /* 10833 */ +0xFBC2,0x8836,0x0000, 0x324E,0x0000,0x0000, 0x324F,0x0000,0x0000, /* 10836 */ +0xFBC2,0x8839,0x0000, 0xFBC2,0x883A,0x0000, 0xFBC2,0x883B,0x0000, /* 10839 */ +0x3250,0x0000,0x0000, 0xFBC2,0x883D,0x0000, 0xFBC2,0x883E,0x0000, /* 1083C */ +0x3251,0x0000,0x0000, 0x32A4,0x0000,0x0000, 0x32A5,0x0000,0x0000, /* 1083F */ +0x32A6,0x0000,0x0000, 0x32A7,0x0000,0x0000, 0x32A8,0x0000,0x0000, /* 10842 */ +0x32A9,0x0000,0x0000, 0x32AA,0x0000,0x0000, 0x32AB,0x0000,0x0000, /* 10845 */ +0x32AC,0x0000,0x0000, 0x32AD,0x0000,0x0000, 0x32AE,0x0000,0x0000, /* 10848 */ +0x32AF,0x0000,0x0000, 0x32B0,0x0000,0x0000, 0x32B1,0x0000,0x0000, /* 1084B */ +0x32B2,0x0000,0x0000, 0x32B3,0x0000,0x0000, 0x32B4,0x0000,0x0000, /* 1084E */ +0x32B5,0x0000,0x0000, 0x32B6,0x0000,0x0000, 0x32B7,0x0000,0x0000, /* 10851 */ +0x32B8,0x0000,0x0000, 0x32B9,0x0000,0x0000, 0xFBC2,0x8856,0x0000, /* 10854 */ +0x02CA,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 10857 */ +0x1208,0x0000,0x0000, 0x11A7,0x0000,0x0000, 0x11A8,0x0000,0x0000, /* 1085A */ +0x11A9,0x0000,0x0000, 0x11AA,0x0000,0x0000, 0x11AB,0x0000,0x0000, /* 1085D */ +0xFBC2,0x8860,0x0000, 0xFBC2,0x8861,0x0000, 0xFBC2,0x8862,0x0000, /* 10860 */ +0xFBC2,0x8863,0x0000, 0xFBC2,0x8864,0x0000, 0xFBC2,0x8865,0x0000, /* 10863 */ +0xFBC2,0x8866,0x0000, 0xFBC2,0x8867,0x0000, 0xFBC2,0x8868,0x0000, /* 10866 */ +0xFBC2,0x8869,0x0000, 0xFBC2,0x886A,0x0000, 0xFBC2,0x886B,0x0000, /* 10869 */ +0xFBC2,0x886C,0x0000, 0xFBC2,0x886D,0x0000, 0xFBC2,0x886E,0x0000, /* 1086C */ +0xFBC2,0x886F,0x0000, 0xFBC2,0x8870,0x0000, 0xFBC2,0x8871,0x0000, /* 1086F */ +0xFBC2,0x8872,0x0000, 0xFBC2,0x8873,0x0000, 0xFBC2,0x8874,0x0000, /* 10872 */ +0xFBC2,0x8875,0x0000, 0xFBC2,0x8876,0x0000, 0xFBC2,0x8877,0x0000, /* 10875 */ +0xFBC2,0x8878,0x0000, 0xFBC2,0x8879,0x0000, 0xFBC2,0x887A,0x0000, /* 10878 */ +0xFBC2,0x887B,0x0000, 0xFBC2,0x887C,0x0000, 0xFBC2,0x887D,0x0000, /* 1087B */ +0xFBC2,0x887E,0x0000, 0xFBC2,0x887F,0x0000, 0xFBC2,0x8880,0x0000, /* 1087E */ +0xFBC2,0x8881,0x0000, 0xFBC2,0x8882,0x0000, 0xFBC2,0x8883,0x0000, /* 10881 */ +0xFBC2,0x8884,0x0000, 0xFBC2,0x8885,0x0000, 0xFBC2,0x8886,0x0000, /* 10884 */ +0xFBC2,0x8887,0x0000, 0xFBC2,0x8888,0x0000, 0xFBC2,0x8889,0x0000, /* 10887 */ +0xFBC2,0x888A,0x0000, 0xFBC2,0x888B,0x0000, 0xFBC2,0x888C,0x0000, /* 1088A */ +0xFBC2,0x888D,0x0000, 0xFBC2,0x888E,0x0000, 0xFBC2,0x888F,0x0000, /* 1088D */ +0xFBC2,0x8890,0x0000, 0xFBC2,0x8891,0x0000, 0xFBC2,0x8892,0x0000, /* 10890 */ +0xFBC2,0x8893,0x0000, 0xFBC2,0x8894,0x0000, 0xFBC2,0x8895,0x0000, /* 10893 */ +0xFBC2,0x8896,0x0000, 0xFBC2,0x8897,0x0000, 0xFBC2,0x8898,0x0000, /* 10896 */ +0xFBC2,0x8899,0x0000, 0xFBC2,0x889A,0x0000, 0xFBC2,0x889B,0x0000, /* 10899 */ +0xFBC2,0x889C,0x0000, 0xFBC2,0x889D,0x0000, 0xFBC2,0x889E,0x0000, /* 1089C */ +0xFBC2,0x889F,0x0000, 0xFBC2,0x88A0,0x0000, 0xFBC2,0x88A1,0x0000, /* 1089F */ +0xFBC2,0x88A2,0x0000, 0xFBC2,0x88A3,0x0000, 0xFBC2,0x88A4,0x0000, /* 108A2 */ +0xFBC2,0x88A5,0x0000, 0xFBC2,0x88A6,0x0000, 0xFBC2,0x88A7,0x0000, /* 108A5 */ +0xFBC2,0x88A8,0x0000, 0xFBC2,0x88A9,0x0000, 0xFBC2,0x88AA,0x0000, /* 108A8 */ +0xFBC2,0x88AB,0x0000, 0xFBC2,0x88AC,0x0000, 0xFBC2,0x88AD,0x0000, /* 108AB */ +0xFBC2,0x88AE,0x0000, 0xFBC2,0x88AF,0x0000, 0xFBC2,0x88B0,0x0000, /* 108AE */ +0xFBC2,0x88B1,0x0000, 0xFBC2,0x88B2,0x0000, 0xFBC2,0x88B3,0x0000, /* 108B1 */ +0xFBC2,0x88B4,0x0000, 0xFBC2,0x88B5,0x0000, 0xFBC2,0x88B6,0x0000, /* 108B4 */ +0xFBC2,0x88B7,0x0000, 0xFBC2,0x88B8,0x0000, 0xFBC2,0x88B9,0x0000, /* 108B7 */ +0xFBC2,0x88BA,0x0000, 0xFBC2,0x88BB,0x0000, 0xFBC2,0x88BC,0x0000, /* 108BA */ +0xFBC2,0x88BD,0x0000, 0xFBC2,0x88BE,0x0000, 0xFBC2,0x88BF,0x0000, /* 108BD */ +0xFBC2,0x88C0,0x0000, 0xFBC2,0x88C1,0x0000, 0xFBC2,0x88C2,0x0000, /* 108C0 */ +0xFBC2,0x88C3,0x0000, 0xFBC2,0x88C4,0x0000, 0xFBC2,0x88C5,0x0000, /* 108C3 */ +0xFBC2,0x88C6,0x0000, 0xFBC2,0x88C7,0x0000, 0xFBC2,0x88C8,0x0000, /* 108C6 */ +0xFBC2,0x88C9,0x0000, 0xFBC2,0x88CA,0x0000, 0xFBC2,0x88CB,0x0000, /* 108C9 */ +0xFBC2,0x88CC,0x0000, 0xFBC2,0x88CD,0x0000, 0xFBC2,0x88CE,0x0000, /* 108CC */ +0xFBC2,0x88CF,0x0000, 0xFBC2,0x88D0,0x0000, 0xFBC2,0x88D1,0x0000, /* 108CF */ +0xFBC2,0x88D2,0x0000, 0xFBC2,0x88D3,0x0000, 0xFBC2,0x88D4,0x0000, /* 108D2 */ +0xFBC2,0x88D5,0x0000, 0xFBC2,0x88D6,0x0000, 0xFBC2,0x88D7,0x0000, /* 108D5 */ +0xFBC2,0x88D8,0x0000, 0xFBC2,0x88D9,0x0000, 0xFBC2,0x88DA,0x0000, /* 108D8 */ +0xFBC2,0x88DB,0x0000, 0xFBC2,0x88DC,0x0000, 0xFBC2,0x88DD,0x0000, /* 108DB */ +0xFBC2,0x88DE,0x0000, 0xFBC2,0x88DF,0x0000, 0xFBC2,0x88E0,0x0000, /* 108DE */ +0xFBC2,0x88E1,0x0000, 0xFBC2,0x88E2,0x0000, 0xFBC2,0x88E3,0x0000, /* 108E1 */ +0xFBC2,0x88E4,0x0000, 0xFBC2,0x88E5,0x0000, 0xFBC2,0x88E6,0x0000, /* 108E4 */ +0xFBC2,0x88E7,0x0000, 0xFBC2,0x88E8,0x0000, 0xFBC2,0x88E9,0x0000, /* 108E7 */ +0xFBC2,0x88EA,0x0000, 0xFBC2,0x88EB,0x0000, 0xFBC2,0x88EC,0x0000, /* 108EA */ +0xFBC2,0x88ED,0x0000, 0xFBC2,0x88EE,0x0000, 0xFBC2,0x88EF,0x0000, /* 108ED */ +0xFBC2,0x88F0,0x0000, 0xFBC2,0x88F1,0x0000, 0xFBC2,0x88F2,0x0000, /* 108F0 */ +0xFBC2,0x88F3,0x0000, 0xFBC2,0x88F4,0x0000, 0xFBC2,0x88F5,0x0000, /* 108F3 */ +0xFBC2,0x88F6,0x0000, 0xFBC2,0x88F7,0x0000, 0xFBC2,0x88F8,0x0000, /* 108F6 */ +0xFBC2,0x88F9,0x0000, 0xFBC2,0x88FA,0x0000, 0xFBC2,0x88FB,0x0000, /* 108F9 */ +0xFBC2,0x88FC,0x0000, 0xFBC2,0x88FD,0x0000, 0xFBC2,0x88FE,0x0000, /* 108FC */ +0xFBC2,0x88FF,0x0000 }; + +uint16 uca520_p109[]= { /* 10900 (3 weights per char) */ +0x1872,0x0000,0x0000, 0x1873,0x0000,0x0000, 0x1874,0x0000,0x0000, /* 10900 */ +0x1875,0x0000,0x0000, 0x1876,0x0000,0x0000, 0x1877,0x0000,0x0000, /* 10903 */ +0x1878,0x0000,0x0000, 0x1879,0x0000,0x0000, 0x187A,0x0000,0x0000, /* 10906 */ +0x187B,0x0000,0x0000, 0x187C,0x0000,0x0000, 0x187D,0x0000,0x0000, /* 10909 */ +0x187E,0x0000,0x0000, 0x187F,0x0000,0x0000, 0x1880,0x0000,0x0000, /* 1090C */ +0x1881,0x0000,0x0000, 0x1882,0x0000,0x0000, 0x1883,0x0000,0x0000, /* 1090F */ +0x1884,0x0000,0x0000, 0x1885,0x0000,0x0000, 0x1886,0x0000,0x0000, /* 10912 */ +0x1887,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x11A4,0x0000,0x0000, /* 10915 */ +0x11A5,0x0000,0x0000, 0x11A6,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 10918 */ +0x1208,0x0000,0x0000, 0xFBC2,0x891C,0x0000, 0xFBC2,0x891D,0x0000, /* 1091B */ +0xFBC2,0x891E,0x0000, 0x02E9,0x0000,0x0000, 0x307E,0x0000,0x0000, /* 1091E */ +0x307F,0x0000,0x0000, 0x3080,0x0000,0x0000, 0x3081,0x0000,0x0000, /* 10921 */ +0x3082,0x0000,0x0000, 0x3083,0x0000,0x0000, 0x3084,0x0000,0x0000, /* 10924 */ +0x3085,0x0000,0x0000, 0x3086,0x0000,0x0000, 0x3087,0x0000,0x0000, /* 10927 */ +0x3088,0x0000,0x0000, 0x3089,0x0000,0x0000, 0x308A,0x0000,0x0000, /* 1092A */ +0x308B,0x0000,0x0000, 0x308C,0x0000,0x0000, 0x308D,0x0000,0x0000, /* 1092D */ +0x308E,0x0000,0x0000, 0x308F,0x0000,0x0000, 0x3090,0x0000,0x0000, /* 10930 */ +0x3091,0x0000,0x0000, 0x3092,0x0000,0x0000, 0x3093,0x0000,0x0000, /* 10933 */ +0x3094,0x0000,0x0000, 0x3095,0x0000,0x0000, 0x3096,0x0000,0x0000, /* 10936 */ +0x3097,0x0000,0x0000, 0xFBC2,0x893A,0x0000, 0xFBC2,0x893B,0x0000, /* 10939 */ +0xFBC2,0x893C,0x0000, 0xFBC2,0x893D,0x0000, 0xFBC2,0x893E,0x0000, /* 1093C */ +0x02E3,0x0000,0x0000, 0xFBC2,0x8940,0x0000, 0xFBC2,0x8941,0x0000, /* 1093F */ +0xFBC2,0x8942,0x0000, 0xFBC2,0x8943,0x0000, 0xFBC2,0x8944,0x0000, /* 10942 */ +0xFBC2,0x8945,0x0000, 0xFBC2,0x8946,0x0000, 0xFBC2,0x8947,0x0000, /* 10945 */ +0xFBC2,0x8948,0x0000, 0xFBC2,0x8949,0x0000, 0xFBC2,0x894A,0x0000, /* 10948 */ +0xFBC2,0x894B,0x0000, 0xFBC2,0x894C,0x0000, 0xFBC2,0x894D,0x0000, /* 1094B */ +0xFBC2,0x894E,0x0000, 0xFBC2,0x894F,0x0000, 0xFBC2,0x8950,0x0000, /* 1094E */ +0xFBC2,0x8951,0x0000, 0xFBC2,0x8952,0x0000, 0xFBC2,0x8953,0x0000, /* 10951 */ +0xFBC2,0x8954,0x0000, 0xFBC2,0x8955,0x0000, 0xFBC2,0x8956,0x0000, /* 10954 */ +0xFBC2,0x8957,0x0000, 0xFBC2,0x8958,0x0000, 0xFBC2,0x8959,0x0000, /* 10957 */ +0xFBC2,0x895A,0x0000, 0xFBC2,0x895B,0x0000, 0xFBC2,0x895C,0x0000, /* 1095A */ +0xFBC2,0x895D,0x0000, 0xFBC2,0x895E,0x0000, 0xFBC2,0x895F,0x0000, /* 1095D */ +0xFBC2,0x8960,0x0000, 0xFBC2,0x8961,0x0000, 0xFBC2,0x8962,0x0000, /* 10960 */ +0xFBC2,0x8963,0x0000, 0xFBC2,0x8964,0x0000, 0xFBC2,0x8965,0x0000, /* 10963 */ +0xFBC2,0x8966,0x0000, 0xFBC2,0x8967,0x0000, 0xFBC2,0x8968,0x0000, /* 10966 */ +0xFBC2,0x8969,0x0000, 0xFBC2,0x896A,0x0000, 0xFBC2,0x896B,0x0000, /* 10969 */ +0xFBC2,0x896C,0x0000, 0xFBC2,0x896D,0x0000, 0xFBC2,0x896E,0x0000, /* 1096C */ +0xFBC2,0x896F,0x0000, 0xFBC2,0x8970,0x0000, 0xFBC2,0x8971,0x0000, /* 1096F */ +0xFBC2,0x8972,0x0000, 0xFBC2,0x8973,0x0000, 0xFBC2,0x8974,0x0000, /* 10972 */ +0xFBC2,0x8975,0x0000, 0xFBC2,0x8976,0x0000, 0xFBC2,0x8977,0x0000, /* 10975 */ +0xFBC2,0x8978,0x0000, 0xFBC2,0x8979,0x0000, 0xFBC2,0x897A,0x0000, /* 10978 */ +0xFBC2,0x897B,0x0000, 0xFBC2,0x897C,0x0000, 0xFBC2,0x897D,0x0000, /* 1097B */ +0xFBC2,0x897E,0x0000, 0xFBC2,0x897F,0x0000, 0xFBC2,0x8980,0x0000, /* 1097E */ +0xFBC2,0x8981,0x0000, 0xFBC2,0x8982,0x0000, 0xFBC2,0x8983,0x0000, /* 10981 */ +0xFBC2,0x8984,0x0000, 0xFBC2,0x8985,0x0000, 0xFBC2,0x8986,0x0000, /* 10984 */ +0xFBC2,0x8987,0x0000, 0xFBC2,0x8988,0x0000, 0xFBC2,0x8989,0x0000, /* 10987 */ +0xFBC2,0x898A,0x0000, 0xFBC2,0x898B,0x0000, 0xFBC2,0x898C,0x0000, /* 1098A */ +0xFBC2,0x898D,0x0000, 0xFBC2,0x898E,0x0000, 0xFBC2,0x898F,0x0000, /* 1098D */ +0xFBC2,0x8990,0x0000, 0xFBC2,0x8991,0x0000, 0xFBC2,0x8992,0x0000, /* 10990 */ +0xFBC2,0x8993,0x0000, 0xFBC2,0x8994,0x0000, 0xFBC2,0x8995,0x0000, /* 10993 */ +0xFBC2,0x8996,0x0000, 0xFBC2,0x8997,0x0000, 0xFBC2,0x8998,0x0000, /* 10996 */ +0xFBC2,0x8999,0x0000, 0xFBC2,0x899A,0x0000, 0xFBC2,0x899B,0x0000, /* 10999 */ +0xFBC2,0x899C,0x0000, 0xFBC2,0x899D,0x0000, 0xFBC2,0x899E,0x0000, /* 1099C */ +0xFBC2,0x899F,0x0000, 0xFBC2,0x89A0,0x0000, 0xFBC2,0x89A1,0x0000, /* 1099F */ +0xFBC2,0x89A2,0x0000, 0xFBC2,0x89A3,0x0000, 0xFBC2,0x89A4,0x0000, /* 109A2 */ +0xFBC2,0x89A5,0x0000, 0xFBC2,0x89A6,0x0000, 0xFBC2,0x89A7,0x0000, /* 109A5 */ +0xFBC2,0x89A8,0x0000, 0xFBC2,0x89A9,0x0000, 0xFBC2,0x89AA,0x0000, /* 109A8 */ +0xFBC2,0x89AB,0x0000, 0xFBC2,0x89AC,0x0000, 0xFBC2,0x89AD,0x0000, /* 109AB */ +0xFBC2,0x89AE,0x0000, 0xFBC2,0x89AF,0x0000, 0xFBC2,0x89B0,0x0000, /* 109AE */ +0xFBC2,0x89B1,0x0000, 0xFBC2,0x89B2,0x0000, 0xFBC2,0x89B3,0x0000, /* 109B1 */ +0xFBC2,0x89B4,0x0000, 0xFBC2,0x89B5,0x0000, 0xFBC2,0x89B6,0x0000, /* 109B4 */ +0xFBC2,0x89B7,0x0000, 0xFBC2,0x89B8,0x0000, 0xFBC2,0x89B9,0x0000, /* 109B7 */ +0xFBC2,0x89BA,0x0000, 0xFBC2,0x89BB,0x0000, 0xFBC2,0x89BC,0x0000, /* 109BA */ +0xFBC2,0x89BD,0x0000, 0xFBC2,0x89BE,0x0000, 0xFBC2,0x89BF,0x0000, /* 109BD */ +0xFBC2,0x89C0,0x0000, 0xFBC2,0x89C1,0x0000, 0xFBC2,0x89C2,0x0000, /* 109C0 */ +0xFBC2,0x89C3,0x0000, 0xFBC2,0x89C4,0x0000, 0xFBC2,0x89C5,0x0000, /* 109C3 */ +0xFBC2,0x89C6,0x0000, 0xFBC2,0x89C7,0x0000, 0xFBC2,0x89C8,0x0000, /* 109C6 */ +0xFBC2,0x89C9,0x0000, 0xFBC2,0x89CA,0x0000, 0xFBC2,0x89CB,0x0000, /* 109C9 */ +0xFBC2,0x89CC,0x0000, 0xFBC2,0x89CD,0x0000, 0xFBC2,0x89CE,0x0000, /* 109CC */ +0xFBC2,0x89CF,0x0000, 0xFBC2,0x89D0,0x0000, 0xFBC2,0x89D1,0x0000, /* 109CF */ +0xFBC2,0x89D2,0x0000, 0xFBC2,0x89D3,0x0000, 0xFBC2,0x89D4,0x0000, /* 109D2 */ +0xFBC2,0x89D5,0x0000, 0xFBC2,0x89D6,0x0000, 0xFBC2,0x89D7,0x0000, /* 109D5 */ +0xFBC2,0x89D8,0x0000, 0xFBC2,0x89D9,0x0000, 0xFBC2,0x89DA,0x0000, /* 109D8 */ +0xFBC2,0x89DB,0x0000, 0xFBC2,0x89DC,0x0000, 0xFBC2,0x89DD,0x0000, /* 109DB */ +0xFBC2,0x89DE,0x0000, 0xFBC2,0x89DF,0x0000, 0xFBC2,0x89E0,0x0000, /* 109DE */ +0xFBC2,0x89E1,0x0000, 0xFBC2,0x89E2,0x0000, 0xFBC2,0x89E3,0x0000, /* 109E1 */ +0xFBC2,0x89E4,0x0000, 0xFBC2,0x89E5,0x0000, 0xFBC2,0x89E6,0x0000, /* 109E4 */ +0xFBC2,0x89E7,0x0000, 0xFBC2,0x89E8,0x0000, 0xFBC2,0x89E9,0x0000, /* 109E7 */ +0xFBC2,0x89EA,0x0000, 0xFBC2,0x89EB,0x0000, 0xFBC2,0x89EC,0x0000, /* 109EA */ +0xFBC2,0x89ED,0x0000, 0xFBC2,0x89EE,0x0000, 0xFBC2,0x89EF,0x0000, /* 109ED */ +0xFBC2,0x89F0,0x0000, 0xFBC2,0x89F1,0x0000, 0xFBC2,0x89F2,0x0000, /* 109F0 */ +0xFBC2,0x89F3,0x0000, 0xFBC2,0x89F4,0x0000, 0xFBC2,0x89F5,0x0000, /* 109F3 */ +0xFBC2,0x89F6,0x0000, 0xFBC2,0x89F7,0x0000, 0xFBC2,0x89F8,0x0000, /* 109F6 */ +0xFBC2,0x89F9,0x0000, 0xFBC2,0x89FA,0x0000, 0xFBC2,0x89FB,0x0000, /* 109F9 */ +0xFBC2,0x89FC,0x0000, 0xFBC2,0x89FD,0x0000, 0xFBC2,0x89FE,0x0000, /* 109FC */ +0xFBC2,0x89FF,0x0000 }; + +uint16 uca520_p10A[]= { /* 10A00 (3 weights per char) */ +0x1F46,0x0000,0x0000, 0x1F47,0x0000,0x0000, 0x1F48,0x0000,0x0000, /* 10A00 */ +0x1F49,0x0000,0x0000, 0xFBC2,0x8A04,0x0000, 0x1F4A,0x0000,0x0000, /* 10A03 */ +0x1F4B,0x0000,0x0000, 0xFBC2,0x8A07,0x0000, 0xFBC2,0x8A08,0x0000, /* 10A06 */ +0xFBC2,0x8A09,0x0000, 0xFBC2,0x8A0A,0x0000, 0xFBC2,0x8A0B,0x0000, /* 10A09 */ +0x1F4C,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 10A0C */ +0x0000,0x0000,0x0000, 0x1F4D,0x0000,0x0000, 0x1F4E,0x0000,0x0000, /* 10A0F */ +0x1F4F,0x0000,0x0000, 0x1F50,0x0000,0x0000, 0xFBC2,0x8A14,0x0000, /* 10A12 */ +0x1F51,0x0000,0x0000, 0x1F52,0x0000,0x0000, 0x1F53,0x0000,0x0000, /* 10A15 */ +0xFBC2,0x8A18,0x0000, 0x1F54,0x0000,0x0000, 0x1F55,0x0000,0x0000, /* 10A18 */ +0x1F56,0x0000,0x0000, 0x1F57,0x0000,0x0000, 0x1F58,0x0000,0x0000, /* 10A1B */ +0x1F59,0x0000,0x0000, 0x1F5A,0x0000,0x0000, 0x1F5B,0x0000,0x0000, /* 10A1E */ +0x1F5C,0x0000,0x0000, 0x1F5D,0x0000,0x0000, 0x1F5E,0x0000,0x0000, /* 10A21 */ +0x1F5F,0x0000,0x0000, 0x1F60,0x0000,0x0000, 0x1F61,0x0000,0x0000, /* 10A24 */ +0x1F62,0x0000,0x0000, 0x1F63,0x0000,0x0000, 0x1F64,0x0000,0x0000, /* 10A27 */ +0x1F65,0x0000,0x0000, 0x1F66,0x0000,0x0000, 0x1F67,0x0000,0x0000, /* 10A2A */ +0x1F68,0x0000,0x0000, 0x1F69,0x0000,0x0000, 0x1F6A,0x0000,0x0000, /* 10A2D */ +0x1F6B,0x0000,0x0000, 0x1F6C,0x0000,0x0000, 0x1F6D,0x0000,0x0000, /* 10A30 */ +0x1F6E,0x0000,0x0000, 0xFBC2,0x8A34,0x0000, 0xFBC2,0x8A35,0x0000, /* 10A33 */ +0xFBC2,0x8A36,0x0000, 0xFBC2,0x8A37,0x0000, 0x0000,0x0000,0x0000, /* 10A36 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0xFBC2,0x8A3B,0x0000, /* 10A39 */ +0xFBC2,0x8A3C,0x0000, 0xFBC2,0x8A3D,0x0000, 0xFBC2,0x8A3E,0x0000, /* 10A3C */ +0x1F6F,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 10A3F */ +0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x11B4,0x0000,0x0000, /* 10A42 */ +0x11B5,0x0000,0x0000, 0x11B6,0x0000,0x0000, 0x11B7,0x0000,0x0000, /* 10A45 */ +0xFBC2,0x8A48,0x0000, 0xFBC2,0x8A49,0x0000, 0xFBC2,0x8A4A,0x0000, /* 10A48 */ +0xFBC2,0x8A4B,0x0000, 0xFBC2,0x8A4C,0x0000, 0xFBC2,0x8A4D,0x0000, /* 10A4B */ +0xFBC2,0x8A4E,0x0000, 0xFBC2,0x8A4F,0x0000, 0x03DF,0x0000,0x0000, /* 10A4E */ +0x03E0,0x0000,0x0000, 0x03E1,0x0000,0x0000, 0x03E2,0x0000,0x0000, /* 10A51 */ +0x03E3,0x0000,0x0000, 0x03E4,0x0000,0x0000, 0x02AF,0x0000,0x0000, /* 10A54 */ +0x02B0,0x0000,0x0000, 0x03E5,0x0000,0x0000, 0xFBC2,0x8A59,0x0000, /* 10A57 */ +0xFBC2,0x8A5A,0x0000, 0xFBC2,0x8A5B,0x0000, 0xFBC2,0x8A5C,0x0000, /* 10A5A */ +0xFBC2,0x8A5D,0x0000, 0xFBC2,0x8A5E,0x0000, 0xFBC2,0x8A5F,0x0000, /* 10A5D */ +0x3252,0x0000,0x0000, 0x3253,0x0000,0x0000, 0x3254,0x0000,0x0000, /* 10A60 */ +0x3255,0x0000,0x0000, 0x3256,0x0000,0x0000, 0x3257,0x0000,0x0000, /* 10A63 */ +0x3258,0x0000,0x0000, 0x3259,0x0000,0x0000, 0x325A,0x0000,0x0000, /* 10A66 */ +0x325B,0x0000,0x0000, 0x325C,0x0000,0x0000, 0x325D,0x0000,0x0000, /* 10A69 */ +0x325E,0x0000,0x0000, 0x325F,0x0000,0x0000, 0x3260,0x0000,0x0000, /* 10A6C */ +0x3261,0x0000,0x0000, 0x3262,0x0000,0x0000, 0x3263,0x0000,0x0000, /* 10A6F */ +0x3264,0x0000,0x0000, 0x3265,0x0000,0x0000, 0x3266,0x0000,0x0000, /* 10A72 */ +0x3267,0x0000,0x0000, 0x3268,0x0000,0x0000, 0x3269,0x0000,0x0000, /* 10A75 */ +0x326A,0x0000,0x0000, 0x326B,0x0000,0x0000, 0x326C,0x0000,0x0000, /* 10A78 */ +0x326D,0x0000,0x0000, 0x326E,0x0000,0x0000, 0x1206,0x0000,0x0000, /* 10A7B */ +0x11A2,0x0000,0x0000, 0x11A3,0x0000,0x0000, 0xFBC2,0x8A80,0x0000, /* 10A7E */ +0xFBC2,0x8A81,0x0000, 0xFBC2,0x8A82,0x0000, 0xFBC2,0x8A83,0x0000, /* 10A81 */ +0xFBC2,0x8A84,0x0000, 0xFBC2,0x8A85,0x0000, 0xFBC2,0x8A86,0x0000, /* 10A84 */ +0xFBC2,0x8A87,0x0000, 0xFBC2,0x8A88,0x0000, 0xFBC2,0x8A89,0x0000, /* 10A87 */ +0xFBC2,0x8A8A,0x0000, 0xFBC2,0x8A8B,0x0000, 0xFBC2,0x8A8C,0x0000, /* 10A8A */ +0xFBC2,0x8A8D,0x0000, 0xFBC2,0x8A8E,0x0000, 0xFBC2,0x8A8F,0x0000, /* 10A8D */ +0xFBC2,0x8A90,0x0000, 0xFBC2,0x8A91,0x0000, 0xFBC2,0x8A92,0x0000, /* 10A90 */ +0xFBC2,0x8A93,0x0000, 0xFBC2,0x8A94,0x0000, 0xFBC2,0x8A95,0x0000, /* 10A93 */ +0xFBC2,0x8A96,0x0000, 0xFBC2,0x8A97,0x0000, 0xFBC2,0x8A98,0x0000, /* 10A96 */ +0xFBC2,0x8A99,0x0000, 0xFBC2,0x8A9A,0x0000, 0xFBC2,0x8A9B,0x0000, /* 10A99 */ +0xFBC2,0x8A9C,0x0000, 0xFBC2,0x8A9D,0x0000, 0xFBC2,0x8A9E,0x0000, /* 10A9C */ +0xFBC2,0x8A9F,0x0000, 0xFBC2,0x8AA0,0x0000, 0xFBC2,0x8AA1,0x0000, /* 10A9F */ +0xFBC2,0x8AA2,0x0000, 0xFBC2,0x8AA3,0x0000, 0xFBC2,0x8AA4,0x0000, /* 10AA2 */ +0xFBC2,0x8AA5,0x0000, 0xFBC2,0x8AA6,0x0000, 0xFBC2,0x8AA7,0x0000, /* 10AA5 */ +0xFBC2,0x8AA8,0x0000, 0xFBC2,0x8AA9,0x0000, 0xFBC2,0x8AAA,0x0000, /* 10AA8 */ +0xFBC2,0x8AAB,0x0000, 0xFBC2,0x8AAC,0x0000, 0xFBC2,0x8AAD,0x0000, /* 10AAB */ +0xFBC2,0x8AAE,0x0000, 0xFBC2,0x8AAF,0x0000, 0xFBC2,0x8AB0,0x0000, /* 10AAE */ +0xFBC2,0x8AB1,0x0000, 0xFBC2,0x8AB2,0x0000, 0xFBC2,0x8AB3,0x0000, /* 10AB1 */ +0xFBC2,0x8AB4,0x0000, 0xFBC2,0x8AB5,0x0000, 0xFBC2,0x8AB6,0x0000, /* 10AB4 */ +0xFBC2,0x8AB7,0x0000, 0xFBC2,0x8AB8,0x0000, 0xFBC2,0x8AB9,0x0000, /* 10AB7 */ +0xFBC2,0x8ABA,0x0000, 0xFBC2,0x8ABB,0x0000, 0xFBC2,0x8ABC,0x0000, /* 10ABA */ +0xFBC2,0x8ABD,0x0000, 0xFBC2,0x8ABE,0x0000, 0xFBC2,0x8ABF,0x0000, /* 10ABD */ +0xFBC2,0x8AC0,0x0000, 0xFBC2,0x8AC1,0x0000, 0xFBC2,0x8AC2,0x0000, /* 10AC0 */ +0xFBC2,0x8AC3,0x0000, 0xFBC2,0x8AC4,0x0000, 0xFBC2,0x8AC5,0x0000, /* 10AC3 */ +0xFBC2,0x8AC6,0x0000, 0xFBC2,0x8AC7,0x0000, 0xFBC2,0x8AC8,0x0000, /* 10AC6 */ +0xFBC2,0x8AC9,0x0000, 0xFBC2,0x8ACA,0x0000, 0xFBC2,0x8ACB,0x0000, /* 10AC9 */ +0xFBC2,0x8ACC,0x0000, 0xFBC2,0x8ACD,0x0000, 0xFBC2,0x8ACE,0x0000, /* 10ACC */ +0xFBC2,0x8ACF,0x0000, 0xFBC2,0x8AD0,0x0000, 0xFBC2,0x8AD1,0x0000, /* 10ACF */ +0xFBC2,0x8AD2,0x0000, 0xFBC2,0x8AD3,0x0000, 0xFBC2,0x8AD4,0x0000, /* 10AD2 */ +0xFBC2,0x8AD5,0x0000, 0xFBC2,0x8AD6,0x0000, 0xFBC2,0x8AD7,0x0000, /* 10AD5 */ +0xFBC2,0x8AD8,0x0000, 0xFBC2,0x8AD9,0x0000, 0xFBC2,0x8ADA,0x0000, /* 10AD8 */ +0xFBC2,0x8ADB,0x0000, 0xFBC2,0x8ADC,0x0000, 0xFBC2,0x8ADD,0x0000, /* 10ADB */ +0xFBC2,0x8ADE,0x0000, 0xFBC2,0x8ADF,0x0000, 0xFBC2,0x8AE0,0x0000, /* 10ADE */ +0xFBC2,0x8AE1,0x0000, 0xFBC2,0x8AE2,0x0000, 0xFBC2,0x8AE3,0x0000, /* 10AE1 */ +0xFBC2,0x8AE4,0x0000, 0xFBC2,0x8AE5,0x0000, 0xFBC2,0x8AE6,0x0000, /* 10AE4 */ +0xFBC2,0x8AE7,0x0000, 0xFBC2,0x8AE8,0x0000, 0xFBC2,0x8AE9,0x0000, /* 10AE7 */ +0xFBC2,0x8AEA,0x0000, 0xFBC2,0x8AEB,0x0000, 0xFBC2,0x8AEC,0x0000, /* 10AEA */ +0xFBC2,0x8AED,0x0000, 0xFBC2,0x8AEE,0x0000, 0xFBC2,0x8AEF,0x0000, /* 10AED */ +0xFBC2,0x8AF0,0x0000, 0xFBC2,0x8AF1,0x0000, 0xFBC2,0x8AF2,0x0000, /* 10AF0 */ +0xFBC2,0x8AF3,0x0000, 0xFBC2,0x8AF4,0x0000, 0xFBC2,0x8AF5,0x0000, /* 10AF3 */ +0xFBC2,0x8AF6,0x0000, 0xFBC2,0x8AF7,0x0000, 0xFBC2,0x8AF8,0x0000, /* 10AF6 */ +0xFBC2,0x8AF9,0x0000, 0xFBC2,0x8AFA,0x0000, 0xFBC2,0x8AFB,0x0000, /* 10AF9 */ +0xFBC2,0x8AFC,0x0000, 0xFBC2,0x8AFD,0x0000, 0xFBC2,0x8AFE,0x0000, /* 10AFC */ +0xFBC2,0x8AFF,0x0000 }; + +uint16 uca520_p10B[]= { /* 10B00 (3 weights per char) */ +0x326F,0x0000,0x0000, 0x3270,0x0000,0x0000, 0x3271,0x0000,0x0000, /* 10B00 */ +0x3272,0x0000,0x0000, 0x3273,0x0000,0x0000, 0x3274,0x0000,0x0000, /* 10B03 */ +0x3275,0x0000,0x0000, 0x3276,0x0000,0x0000, 0x3277,0x0000,0x0000, /* 10B06 */ +0x3278,0x0000,0x0000, 0x3279,0x0000,0x0000, 0x327A,0x0000,0x0000, /* 10B09 */ +0x327B,0x0000,0x0000, 0x327C,0x0000,0x0000, 0x327D,0x0000,0x0000, /* 10B0C */ +0x327E,0x0000,0x0000, 0x327F,0x0000,0x0000, 0x3280,0x0000,0x0000, /* 10B0F */ +0x3281,0x0000,0x0000, 0x3282,0x0000,0x0000, 0x3283,0x0000,0x0000, /* 10B12 */ +0x3284,0x0000,0x0000, 0x3285,0x0000,0x0000, 0x3286,0x0000,0x0000, /* 10B15 */ +0x3287,0x0000,0x0000, 0x3288,0x0000,0x0000, 0x3289,0x0000,0x0000, /* 10B18 */ +0x328A,0x0000,0x0000, 0x328B,0x0000,0x0000, 0x328C,0x0000,0x0000, /* 10B1B */ +0x328D,0x0000,0x0000, 0x328E,0x0000,0x0000, 0x328F,0x0000,0x0000, /* 10B1E */ +0x3290,0x0000,0x0000, 0x3291,0x0000,0x0000, 0x3292,0x0000,0x0000, /* 10B21 */ +0x3293,0x0000,0x0000, 0x3294,0x0000,0x0000, 0x3295,0x0000,0x0000, /* 10B24 */ +0x3296,0x0000,0x0000, 0x3297,0x0000,0x0000, 0x3298,0x0000,0x0000, /* 10B27 */ +0x3299,0x0000,0x0000, 0x329A,0x0000,0x0000, 0x329B,0x0000,0x0000, /* 10B2A */ +0x329C,0x0000,0x0000, 0x329C,0x0000,0x0000, 0x329D,0x0000,0x0000, /* 10B2D */ +0x329E,0x0000,0x0000, 0x329F,0x0000,0x0000, 0x32A0,0x0000,0x0000, /* 10B30 */ +0x32A1,0x0000,0x0000, 0x32A2,0x0000,0x0000, 0x32A3,0x0000,0x0000, /* 10B33 */ +0xFBC2,0x8B36,0x0000, 0xFBC2,0x8B37,0x0000, 0xFBC2,0x8B38,0x0000, /* 10B36 */ +0x03E6,0x0000,0x0000, 0x02CB,0x0000,0x0000, 0x02CC,0x0000,0x0000, /* 10B39 */ +0x02CD,0x0000,0x0000, 0x02CE,0x0000,0x0000, 0x02CF,0x0000,0x0000, /* 10B3C */ +0x02D0,0x0000,0x0000, 0x32BA,0x0000,0x0000, 0x32BB,0x0000,0x0000, /* 10B3F */ +0x32BC,0x0000,0x0000, 0x32BD,0x0000,0x0000, 0x32BE,0x0000,0x0000, /* 10B42 */ +0x32BF,0x0000,0x0000, 0x32C0,0x0000,0x0000, 0x32C1,0x0000,0x0000, /* 10B45 */ +0x32C2,0x0000,0x0000, 0x32C3,0x0000,0x0000, 0x32C4,0x0000,0x0000, /* 10B48 */ +0x32C5,0x0000,0x0000, 0x32C6,0x0000,0x0000, 0x32C7,0x0000,0x0000, /* 10B4B */ +0x32C8,0x0000,0x0000, 0x32C9,0x0000,0x0000, 0x32CA,0x0000,0x0000, /* 10B4E */ +0x32CB,0x0000,0x0000, 0x32CC,0x0000,0x0000, 0x32CD,0x0000,0x0000, /* 10B51 */ +0x32CE,0x0000,0x0000, 0x32CF,0x0000,0x0000, 0xFBC2,0x8B56,0x0000, /* 10B54 */ +0xFBC2,0x8B57,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 10B57 */ +0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x11AC,0x0000,0x0000, /* 10B5A */ +0x11AD,0x0000,0x0000, 0x11AE,0x0000,0x0000, 0x11AF,0x0000,0x0000, /* 10B5D */ +0x32D0,0x0000,0x0000, 0x32D1,0x0000,0x0000, 0x32D2,0x0000,0x0000, /* 10B60 */ +0x32D3,0x0000,0x0000, 0x32D4,0x0000,0x0000, 0x32D5,0x0000,0x0000, /* 10B63 */ +0x32D6,0x0000,0x0000, 0x32D7,0x0000,0x0000, 0x32D8,0x0000,0x0000, /* 10B66 */ +0x32D9,0x0000,0x0000, 0x32DA,0x0000,0x0000, 0x32DB,0x0000,0x0000, /* 10B69 */ +0x32DC,0x0000,0x0000, 0x32DD,0x0000,0x0000, 0x32DE,0x0000,0x0000, /* 10B6C */ +0x32DF,0x0000,0x0000, 0x32E0,0x0000,0x0000, 0x32E1,0x0000,0x0000, /* 10B6F */ +0x32E2,0x0000,0x0000, 0xFBC2,0x8B73,0x0000, 0xFBC2,0x8B74,0x0000, /* 10B72 */ +0xFBC2,0x8B75,0x0000, 0xFBC2,0x8B76,0x0000, 0xFBC2,0x8B77,0x0000, /* 10B75 */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 10B78 */ +0x1209,0x0000,0x0000, 0x11B0,0x0000,0x0000, 0x11B1,0x0000,0x0000, /* 10B7B */ +0x11B2,0x0000,0x0000, 0x11B3,0x0000,0x0000, 0xFBC2,0x8B80,0x0000, /* 10B7E */ +0xFBC2,0x8B81,0x0000, 0xFBC2,0x8B82,0x0000, 0xFBC2,0x8B83,0x0000, /* 10B81 */ +0xFBC2,0x8B84,0x0000, 0xFBC2,0x8B85,0x0000, 0xFBC2,0x8B86,0x0000, /* 10B84 */ +0xFBC2,0x8B87,0x0000, 0xFBC2,0x8B88,0x0000, 0xFBC2,0x8B89,0x0000, /* 10B87 */ +0xFBC2,0x8B8A,0x0000, 0xFBC2,0x8B8B,0x0000, 0xFBC2,0x8B8C,0x0000, /* 10B8A */ +0xFBC2,0x8B8D,0x0000, 0xFBC2,0x8B8E,0x0000, 0xFBC2,0x8B8F,0x0000, /* 10B8D */ +0xFBC2,0x8B90,0x0000, 0xFBC2,0x8B91,0x0000, 0xFBC2,0x8B92,0x0000, /* 10B90 */ +0xFBC2,0x8B93,0x0000, 0xFBC2,0x8B94,0x0000, 0xFBC2,0x8B95,0x0000, /* 10B93 */ +0xFBC2,0x8B96,0x0000, 0xFBC2,0x8B97,0x0000, 0xFBC2,0x8B98,0x0000, /* 10B96 */ +0xFBC2,0x8B99,0x0000, 0xFBC2,0x8B9A,0x0000, 0xFBC2,0x8B9B,0x0000, /* 10B99 */ +0xFBC2,0x8B9C,0x0000, 0xFBC2,0x8B9D,0x0000, 0xFBC2,0x8B9E,0x0000, /* 10B9C */ +0xFBC2,0x8B9F,0x0000, 0xFBC2,0x8BA0,0x0000, 0xFBC2,0x8BA1,0x0000, /* 10B9F */ +0xFBC2,0x8BA2,0x0000, 0xFBC2,0x8BA3,0x0000, 0xFBC2,0x8BA4,0x0000, /* 10BA2 */ +0xFBC2,0x8BA5,0x0000, 0xFBC2,0x8BA6,0x0000, 0xFBC2,0x8BA7,0x0000, /* 10BA5 */ +0xFBC2,0x8BA8,0x0000, 0xFBC2,0x8BA9,0x0000, 0xFBC2,0x8BAA,0x0000, /* 10BA8 */ +0xFBC2,0x8BAB,0x0000, 0xFBC2,0x8BAC,0x0000, 0xFBC2,0x8BAD,0x0000, /* 10BAB */ +0xFBC2,0x8BAE,0x0000, 0xFBC2,0x8BAF,0x0000, 0xFBC2,0x8BB0,0x0000, /* 10BAE */ +0xFBC2,0x8BB1,0x0000, 0xFBC2,0x8BB2,0x0000, 0xFBC2,0x8BB3,0x0000, /* 10BB1 */ +0xFBC2,0x8BB4,0x0000, 0xFBC2,0x8BB5,0x0000, 0xFBC2,0x8BB6,0x0000, /* 10BB4 */ +0xFBC2,0x8BB7,0x0000, 0xFBC2,0x8BB8,0x0000, 0xFBC2,0x8BB9,0x0000, /* 10BB7 */ +0xFBC2,0x8BBA,0x0000, 0xFBC2,0x8BBB,0x0000, 0xFBC2,0x8BBC,0x0000, /* 10BBA */ +0xFBC2,0x8BBD,0x0000, 0xFBC2,0x8BBE,0x0000, 0xFBC2,0x8BBF,0x0000, /* 10BBD */ +0xFBC2,0x8BC0,0x0000, 0xFBC2,0x8BC1,0x0000, 0xFBC2,0x8BC2,0x0000, /* 10BC0 */ +0xFBC2,0x8BC3,0x0000, 0xFBC2,0x8BC4,0x0000, 0xFBC2,0x8BC5,0x0000, /* 10BC3 */ +0xFBC2,0x8BC6,0x0000, 0xFBC2,0x8BC7,0x0000, 0xFBC2,0x8BC8,0x0000, /* 10BC6 */ +0xFBC2,0x8BC9,0x0000, 0xFBC2,0x8BCA,0x0000, 0xFBC2,0x8BCB,0x0000, /* 10BC9 */ +0xFBC2,0x8BCC,0x0000, 0xFBC2,0x8BCD,0x0000, 0xFBC2,0x8BCE,0x0000, /* 10BCC */ +0xFBC2,0x8BCF,0x0000, 0xFBC2,0x8BD0,0x0000, 0xFBC2,0x8BD1,0x0000, /* 10BCF */ +0xFBC2,0x8BD2,0x0000, 0xFBC2,0x8BD3,0x0000, 0xFBC2,0x8BD4,0x0000, /* 10BD2 */ +0xFBC2,0x8BD5,0x0000, 0xFBC2,0x8BD6,0x0000, 0xFBC2,0x8BD7,0x0000, /* 10BD5 */ +0xFBC2,0x8BD8,0x0000, 0xFBC2,0x8BD9,0x0000, 0xFBC2,0x8BDA,0x0000, /* 10BD8 */ +0xFBC2,0x8BDB,0x0000, 0xFBC2,0x8BDC,0x0000, 0xFBC2,0x8BDD,0x0000, /* 10BDB */ +0xFBC2,0x8BDE,0x0000, 0xFBC2,0x8BDF,0x0000, 0xFBC2,0x8BE0,0x0000, /* 10BDE */ +0xFBC2,0x8BE1,0x0000, 0xFBC2,0x8BE2,0x0000, 0xFBC2,0x8BE3,0x0000, /* 10BE1 */ +0xFBC2,0x8BE4,0x0000, 0xFBC2,0x8BE5,0x0000, 0xFBC2,0x8BE6,0x0000, /* 10BE4 */ +0xFBC2,0x8BE7,0x0000, 0xFBC2,0x8BE8,0x0000, 0xFBC2,0x8BE9,0x0000, /* 10BE7 */ +0xFBC2,0x8BEA,0x0000, 0xFBC2,0x8BEB,0x0000, 0xFBC2,0x8BEC,0x0000, /* 10BEA */ +0xFBC2,0x8BED,0x0000, 0xFBC2,0x8BEE,0x0000, 0xFBC2,0x8BEF,0x0000, /* 10BED */ +0xFBC2,0x8BF0,0x0000, 0xFBC2,0x8BF1,0x0000, 0xFBC2,0x8BF2,0x0000, /* 10BF0 */ +0xFBC2,0x8BF3,0x0000, 0xFBC2,0x8BF4,0x0000, 0xFBC2,0x8BF5,0x0000, /* 10BF3 */ +0xFBC2,0x8BF6,0x0000, 0xFBC2,0x8BF7,0x0000, 0xFBC2,0x8BF8,0x0000, /* 10BF6 */ +0xFBC2,0x8BF9,0x0000, 0xFBC2,0x8BFA,0x0000, 0xFBC2,0x8BFB,0x0000, /* 10BF9 */ +0xFBC2,0x8BFC,0x0000, 0xFBC2,0x8BFD,0x0000, 0xFBC2,0x8BFE,0x0000, /* 10BFC */ +0xFBC2,0x8BFF,0x0000 }; + +uint16 uca520_p10C[]= { /* 10C00 (3 weights per char) */ +0x2826,0x0000,0x0000, 0x2826,0x0000,0x0000, 0x2827,0x0000,0x0000, /* 10C00 */ +0x2828,0x0000,0x0000, 0x2828,0x0000,0x0000, 0x2829,0x0000,0x0000, /* 10C03 */ +0x282A,0x0000,0x0000, 0x282B,0x0000,0x0000, 0x282B,0x0000,0x0000, /* 10C06 */ +0x282C,0x0000,0x0000, 0x282C,0x0000,0x0000, 0x282D,0x0000,0x0000, /* 10C09 */ +0x282D,0x0000,0x0000, 0x282E,0x0000,0x0000, 0x282E,0x0000,0x0000, /* 10C0C */ +0x282F,0x0000,0x0000, 0x282F,0x0000,0x0000, 0x2830,0x0000,0x0000, /* 10C0F */ +0x2830,0x0000,0x0000, 0x2831,0x0000,0x0000, 0x2832,0x0000,0x0000, /* 10C12 */ +0x2832,0x0000,0x0000, 0x2833,0x0000,0x0000, 0x2833,0x0000,0x0000, /* 10C15 */ +0x2834,0x0000,0x0000, 0x2834,0x0000,0x0000, 0x2835,0x0000,0x0000, /* 10C18 */ +0x2835,0x0000,0x0000, 0x2836,0x0000,0x0000, 0x2836,0x0000,0x0000, /* 10C1B */ +0x2837,0x0000,0x0000, 0x2837,0x0000,0x0000, 0x2838,0x0000,0x0000, /* 10C1E */ +0x2839,0x0000,0x0000, 0x283A,0x0000,0x0000, 0x283B,0x0000,0x0000, /* 10C21 */ +0x283C,0x0000,0x0000, 0x283C,0x0000,0x0000, 0x283D,0x0000,0x0000, /* 10C24 */ +0x283D,0x0000,0x0000, 0x283E,0x0000,0x0000, 0x283E,0x0000,0x0000, /* 10C27 */ +0x283F,0x0000,0x0000, 0x283F,0x0000,0x0000, 0x2840,0x0000,0x0000, /* 10C2A */ +0x2841,0x0000,0x0000, 0x2841,0x0000,0x0000, 0x2842,0x0000,0x0000, /* 10C2D */ +0x2843,0x0000,0x0000, 0x2844,0x0000,0x0000, 0x2845,0x0000,0x0000, /* 10C30 */ +0x2845,0x0000,0x0000, 0x2846,0x0000,0x0000, 0x2846,0x0000,0x0000, /* 10C33 */ +0x2847,0x0000,0x0000, 0x2847,0x0000,0x0000, 0x2848,0x0000,0x0000, /* 10C36 */ +0x2848,0x0000,0x0000, 0x2849,0x0000,0x0000, 0x2849,0x0000,0x0000, /* 10C39 */ +0x284A,0x0000,0x0000, 0x284B,0x0000,0x0000, 0x284C,0x0000,0x0000, /* 10C3C */ +0x284D,0x0000,0x0000, 0x284D,0x0000,0x0000, 0x284E,0x0000,0x0000, /* 10C3F */ +0x284E,0x0000,0x0000, 0x284F,0x0000,0x0000, 0x284F,0x0000,0x0000, /* 10C42 */ +0x2850,0x0000,0x0000, 0x2850,0x0000,0x0000, 0x2851,0x0000,0x0000, /* 10C45 */ +0x2852,0x0000,0x0000, 0xFBC2,0x8C49,0x0000, 0xFBC2,0x8C4A,0x0000, /* 10C48 */ +0xFBC2,0x8C4B,0x0000, 0xFBC2,0x8C4C,0x0000, 0xFBC2,0x8C4D,0x0000, /* 10C4B */ +0xFBC2,0x8C4E,0x0000, 0xFBC2,0x8C4F,0x0000, 0xFBC2,0x8C50,0x0000, /* 10C4E */ +0xFBC2,0x8C51,0x0000, 0xFBC2,0x8C52,0x0000, 0xFBC2,0x8C53,0x0000, /* 10C51 */ +0xFBC2,0x8C54,0x0000, 0xFBC2,0x8C55,0x0000, 0xFBC2,0x8C56,0x0000, /* 10C54 */ +0xFBC2,0x8C57,0x0000, 0xFBC2,0x8C58,0x0000, 0xFBC2,0x8C59,0x0000, /* 10C57 */ +0xFBC2,0x8C5A,0x0000, 0xFBC2,0x8C5B,0x0000, 0xFBC2,0x8C5C,0x0000, /* 10C5A */ +0xFBC2,0x8C5D,0x0000, 0xFBC2,0x8C5E,0x0000, 0xFBC2,0x8C5F,0x0000, /* 10C5D */ +0xFBC2,0x8C60,0x0000, 0xFBC2,0x8C61,0x0000, 0xFBC2,0x8C62,0x0000, /* 10C60 */ +0xFBC2,0x8C63,0x0000, 0xFBC2,0x8C64,0x0000, 0xFBC2,0x8C65,0x0000, /* 10C63 */ +0xFBC2,0x8C66,0x0000, 0xFBC2,0x8C67,0x0000, 0xFBC2,0x8C68,0x0000, /* 10C66 */ +0xFBC2,0x8C69,0x0000, 0xFBC2,0x8C6A,0x0000, 0xFBC2,0x8C6B,0x0000, /* 10C69 */ +0xFBC2,0x8C6C,0x0000, 0xFBC2,0x8C6D,0x0000, 0xFBC2,0x8C6E,0x0000, /* 10C6C */ +0xFBC2,0x8C6F,0x0000, 0xFBC2,0x8C70,0x0000, 0xFBC2,0x8C71,0x0000, /* 10C6F */ +0xFBC2,0x8C72,0x0000, 0xFBC2,0x8C73,0x0000, 0xFBC2,0x8C74,0x0000, /* 10C72 */ +0xFBC2,0x8C75,0x0000, 0xFBC2,0x8C76,0x0000, 0xFBC2,0x8C77,0x0000, /* 10C75 */ +0xFBC2,0x8C78,0x0000, 0xFBC2,0x8C79,0x0000, 0xFBC2,0x8C7A,0x0000, /* 10C78 */ +0xFBC2,0x8C7B,0x0000, 0xFBC2,0x8C7C,0x0000, 0xFBC2,0x8C7D,0x0000, /* 10C7B */ +0xFBC2,0x8C7E,0x0000, 0xFBC2,0x8C7F,0x0000, 0xFBC2,0x8C80,0x0000, /* 10C7E */ +0xFBC2,0x8C81,0x0000, 0xFBC2,0x8C82,0x0000, 0xFBC2,0x8C83,0x0000, /* 10C81 */ +0xFBC2,0x8C84,0x0000, 0xFBC2,0x8C85,0x0000, 0xFBC2,0x8C86,0x0000, /* 10C84 */ +0xFBC2,0x8C87,0x0000, 0xFBC2,0x8C88,0x0000, 0xFBC2,0x8C89,0x0000, /* 10C87 */ +0xFBC2,0x8C8A,0x0000, 0xFBC2,0x8C8B,0x0000, 0xFBC2,0x8C8C,0x0000, /* 10C8A */ +0xFBC2,0x8C8D,0x0000, 0xFBC2,0x8C8E,0x0000, 0xFBC2,0x8C8F,0x0000, /* 10C8D */ +0xFBC2,0x8C90,0x0000, 0xFBC2,0x8C91,0x0000, 0xFBC2,0x8C92,0x0000, /* 10C90 */ +0xFBC2,0x8C93,0x0000, 0xFBC2,0x8C94,0x0000, 0xFBC2,0x8C95,0x0000, /* 10C93 */ +0xFBC2,0x8C96,0x0000, 0xFBC2,0x8C97,0x0000, 0xFBC2,0x8C98,0x0000, /* 10C96 */ +0xFBC2,0x8C99,0x0000, 0xFBC2,0x8C9A,0x0000, 0xFBC2,0x8C9B,0x0000, /* 10C99 */ +0xFBC2,0x8C9C,0x0000, 0xFBC2,0x8C9D,0x0000, 0xFBC2,0x8C9E,0x0000, /* 10C9C */ +0xFBC2,0x8C9F,0x0000, 0xFBC2,0x8CA0,0x0000, 0xFBC2,0x8CA1,0x0000, /* 10C9F */ +0xFBC2,0x8CA2,0x0000, 0xFBC2,0x8CA3,0x0000, 0xFBC2,0x8CA4,0x0000, /* 10CA2 */ +0xFBC2,0x8CA5,0x0000, 0xFBC2,0x8CA6,0x0000, 0xFBC2,0x8CA7,0x0000, /* 10CA5 */ +0xFBC2,0x8CA8,0x0000, 0xFBC2,0x8CA9,0x0000, 0xFBC2,0x8CAA,0x0000, /* 10CA8 */ +0xFBC2,0x8CAB,0x0000, 0xFBC2,0x8CAC,0x0000, 0xFBC2,0x8CAD,0x0000, /* 10CAB */ +0xFBC2,0x8CAE,0x0000, 0xFBC2,0x8CAF,0x0000, 0xFBC2,0x8CB0,0x0000, /* 10CAE */ +0xFBC2,0x8CB1,0x0000, 0xFBC2,0x8CB2,0x0000, 0xFBC2,0x8CB3,0x0000, /* 10CB1 */ +0xFBC2,0x8CB4,0x0000, 0xFBC2,0x8CB5,0x0000, 0xFBC2,0x8CB6,0x0000, /* 10CB4 */ +0xFBC2,0x8CB7,0x0000, 0xFBC2,0x8CB8,0x0000, 0xFBC2,0x8CB9,0x0000, /* 10CB7 */ +0xFBC2,0x8CBA,0x0000, 0xFBC2,0x8CBB,0x0000, 0xFBC2,0x8CBC,0x0000, /* 10CBA */ +0xFBC2,0x8CBD,0x0000, 0xFBC2,0x8CBE,0x0000, 0xFBC2,0x8CBF,0x0000, /* 10CBD */ +0xFBC2,0x8CC0,0x0000, 0xFBC2,0x8CC1,0x0000, 0xFBC2,0x8CC2,0x0000, /* 10CC0 */ +0xFBC2,0x8CC3,0x0000, 0xFBC2,0x8CC4,0x0000, 0xFBC2,0x8CC5,0x0000, /* 10CC3 */ +0xFBC2,0x8CC6,0x0000, 0xFBC2,0x8CC7,0x0000, 0xFBC2,0x8CC8,0x0000, /* 10CC6 */ +0xFBC2,0x8CC9,0x0000, 0xFBC2,0x8CCA,0x0000, 0xFBC2,0x8CCB,0x0000, /* 10CC9 */ +0xFBC2,0x8CCC,0x0000, 0xFBC2,0x8CCD,0x0000, 0xFBC2,0x8CCE,0x0000, /* 10CCC */ +0xFBC2,0x8CCF,0x0000, 0xFBC2,0x8CD0,0x0000, 0xFBC2,0x8CD1,0x0000, /* 10CCF */ +0xFBC2,0x8CD2,0x0000, 0xFBC2,0x8CD3,0x0000, 0xFBC2,0x8CD4,0x0000, /* 10CD2 */ +0xFBC2,0x8CD5,0x0000, 0xFBC2,0x8CD6,0x0000, 0xFBC2,0x8CD7,0x0000, /* 10CD5 */ +0xFBC2,0x8CD8,0x0000, 0xFBC2,0x8CD9,0x0000, 0xFBC2,0x8CDA,0x0000, /* 10CD8 */ +0xFBC2,0x8CDB,0x0000, 0xFBC2,0x8CDC,0x0000, 0xFBC2,0x8CDD,0x0000, /* 10CDB */ +0xFBC2,0x8CDE,0x0000, 0xFBC2,0x8CDF,0x0000, 0xFBC2,0x8CE0,0x0000, /* 10CDE */ +0xFBC2,0x8CE1,0x0000, 0xFBC2,0x8CE2,0x0000, 0xFBC2,0x8CE3,0x0000, /* 10CE1 */ +0xFBC2,0x8CE4,0x0000, 0xFBC2,0x8CE5,0x0000, 0xFBC2,0x8CE6,0x0000, /* 10CE4 */ +0xFBC2,0x8CE7,0x0000, 0xFBC2,0x8CE8,0x0000, 0xFBC2,0x8CE9,0x0000, /* 10CE7 */ +0xFBC2,0x8CEA,0x0000, 0xFBC2,0x8CEB,0x0000, 0xFBC2,0x8CEC,0x0000, /* 10CEA */ +0xFBC2,0x8CED,0x0000, 0xFBC2,0x8CEE,0x0000, 0xFBC2,0x8CEF,0x0000, /* 10CED */ +0xFBC2,0x8CF0,0x0000, 0xFBC2,0x8CF1,0x0000, 0xFBC2,0x8CF2,0x0000, /* 10CF0 */ +0xFBC2,0x8CF3,0x0000, 0xFBC2,0x8CF4,0x0000, 0xFBC2,0x8CF5,0x0000, /* 10CF3 */ +0xFBC2,0x8CF6,0x0000, 0xFBC2,0x8CF7,0x0000, 0xFBC2,0x8CF8,0x0000, /* 10CF6 */ +0xFBC2,0x8CF9,0x0000, 0xFBC2,0x8CFA,0x0000, 0xFBC2,0x8CFB,0x0000, /* 10CF9 */ +0xFBC2,0x8CFC,0x0000, 0xFBC2,0x8CFD,0x0000, 0xFBC2,0x8CFE,0x0000, /* 10CFC */ +0xFBC2,0x8CFF,0x0000 }; + +uint16 uca520_p10E[]= { /* 10E00 (3 weights per char) */ +0xFBC2,0x8E00,0x0000, 0xFBC2,0x8E01,0x0000, 0xFBC2,0x8E02,0x0000, /* 10E00 */ +0xFBC2,0x8E03,0x0000, 0xFBC2,0x8E04,0x0000, 0xFBC2,0x8E05,0x0000, /* 10E03 */ +0xFBC2,0x8E06,0x0000, 0xFBC2,0x8E07,0x0000, 0xFBC2,0x8E08,0x0000, /* 10E06 */ +0xFBC2,0x8E09,0x0000, 0xFBC2,0x8E0A,0x0000, 0xFBC2,0x8E0B,0x0000, /* 10E09 */ +0xFBC2,0x8E0C,0x0000, 0xFBC2,0x8E0D,0x0000, 0xFBC2,0x8E0E,0x0000, /* 10E0C */ +0xFBC2,0x8E0F,0x0000, 0xFBC2,0x8E10,0x0000, 0xFBC2,0x8E11,0x0000, /* 10E0F */ +0xFBC2,0x8E12,0x0000, 0xFBC2,0x8E13,0x0000, 0xFBC2,0x8E14,0x0000, /* 10E12 */ +0xFBC2,0x8E15,0x0000, 0xFBC2,0x8E16,0x0000, 0xFBC2,0x8E17,0x0000, /* 10E15 */ +0xFBC2,0x8E18,0x0000, 0xFBC2,0x8E19,0x0000, 0xFBC2,0x8E1A,0x0000, /* 10E18 */ +0xFBC2,0x8E1B,0x0000, 0xFBC2,0x8E1C,0x0000, 0xFBC2,0x8E1D,0x0000, /* 10E1B */ +0xFBC2,0x8E1E,0x0000, 0xFBC2,0x8E1F,0x0000, 0xFBC2,0x8E20,0x0000, /* 10E1E */ +0xFBC2,0x8E21,0x0000, 0xFBC2,0x8E22,0x0000, 0xFBC2,0x8E23,0x0000, /* 10E21 */ +0xFBC2,0x8E24,0x0000, 0xFBC2,0x8E25,0x0000, 0xFBC2,0x8E26,0x0000, /* 10E24 */ +0xFBC2,0x8E27,0x0000, 0xFBC2,0x8E28,0x0000, 0xFBC2,0x8E29,0x0000, /* 10E27 */ +0xFBC2,0x8E2A,0x0000, 0xFBC2,0x8E2B,0x0000, 0xFBC2,0x8E2C,0x0000, /* 10E2A */ +0xFBC2,0x8E2D,0x0000, 0xFBC2,0x8E2E,0x0000, 0xFBC2,0x8E2F,0x0000, /* 10E2D */ +0xFBC2,0x8E30,0x0000, 0xFBC2,0x8E31,0x0000, 0xFBC2,0x8E32,0x0000, /* 10E30 */ +0xFBC2,0x8E33,0x0000, 0xFBC2,0x8E34,0x0000, 0xFBC2,0x8E35,0x0000, /* 10E33 */ +0xFBC2,0x8E36,0x0000, 0xFBC2,0x8E37,0x0000, 0xFBC2,0x8E38,0x0000, /* 10E36 */ +0xFBC2,0x8E39,0x0000, 0xFBC2,0x8E3A,0x0000, 0xFBC2,0x8E3B,0x0000, /* 10E39 */ +0xFBC2,0x8E3C,0x0000, 0xFBC2,0x8E3D,0x0000, 0xFBC2,0x8E3E,0x0000, /* 10E3C */ +0xFBC2,0x8E3F,0x0000, 0xFBC2,0x8E40,0x0000, 0xFBC2,0x8E41,0x0000, /* 10E3F */ +0xFBC2,0x8E42,0x0000, 0xFBC2,0x8E43,0x0000, 0xFBC2,0x8E44,0x0000, /* 10E42 */ +0xFBC2,0x8E45,0x0000, 0xFBC2,0x8E46,0x0000, 0xFBC2,0x8E47,0x0000, /* 10E45 */ +0xFBC2,0x8E48,0x0000, 0xFBC2,0x8E49,0x0000, 0xFBC2,0x8E4A,0x0000, /* 10E48 */ +0xFBC2,0x8E4B,0x0000, 0xFBC2,0x8E4C,0x0000, 0xFBC2,0x8E4D,0x0000, /* 10E4B */ +0xFBC2,0x8E4E,0x0000, 0xFBC2,0x8E4F,0x0000, 0xFBC2,0x8E50,0x0000, /* 10E4E */ +0xFBC2,0x8E51,0x0000, 0xFBC2,0x8E52,0x0000, 0xFBC2,0x8E53,0x0000, /* 10E51 */ +0xFBC2,0x8E54,0x0000, 0xFBC2,0x8E55,0x0000, 0xFBC2,0x8E56,0x0000, /* 10E54 */ +0xFBC2,0x8E57,0x0000, 0xFBC2,0x8E58,0x0000, 0xFBC2,0x8E59,0x0000, /* 10E57 */ +0xFBC2,0x8E5A,0x0000, 0xFBC2,0x8E5B,0x0000, 0xFBC2,0x8E5C,0x0000, /* 10E5A */ +0xFBC2,0x8E5D,0x0000, 0xFBC2,0x8E5E,0x0000, 0xFBC2,0x8E5F,0x0000, /* 10E5D */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 10E60 */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 10E63 */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 10E66 */ +0x1136,0x0000,0x0000, 0x1137,0x0000,0x0000, 0x1138,0x0000,0x0000, /* 10E69 */ +0x1139,0x0000,0x0000, 0x113A,0x0000,0x0000, 0x113B,0x0000,0x0000, /* 10E6C */ +0x113C,0x0000,0x0000, 0x113D,0x0000,0x0000, 0x113E,0x0000,0x0000, /* 10E6F */ +0x113F,0x0000,0x0000, 0x1140,0x0000,0x0000, 0x1141,0x0000,0x0000, /* 10E72 */ +0x1142,0x0000,0x0000, 0x1143,0x0000,0x0000, 0x1144,0x0000,0x0000, /* 10E75 */ +0x1145,0x0000,0x0000, 0x1146,0x0000,0x0000, 0x1147,0x0000,0x0000, /* 10E78 */ +0x1148,0x0000,0x0000, 0x1149,0x0000,0x0000, 0x114A,0x0000,0x0000, /* 10E7B */ +0x114B,0x0000,0x0000, 0xFBC2,0x8E7F,0x0000, 0xFBC2,0x8E80,0x0000, /* 10E7E */ +0xFBC2,0x8E81,0x0000, 0xFBC2,0x8E82,0x0000, 0xFBC2,0x8E83,0x0000, /* 10E81 */ +0xFBC2,0x8E84,0x0000, 0xFBC2,0x8E85,0x0000, 0xFBC2,0x8E86,0x0000, /* 10E84 */ +0xFBC2,0x8E87,0x0000, 0xFBC2,0x8E88,0x0000, 0xFBC2,0x8E89,0x0000, /* 10E87 */ +0xFBC2,0x8E8A,0x0000, 0xFBC2,0x8E8B,0x0000, 0xFBC2,0x8E8C,0x0000, /* 10E8A */ +0xFBC2,0x8E8D,0x0000, 0xFBC2,0x8E8E,0x0000, 0xFBC2,0x8E8F,0x0000, /* 10E8D */ +0xFBC2,0x8E90,0x0000, 0xFBC2,0x8E91,0x0000, 0xFBC2,0x8E92,0x0000, /* 10E90 */ +0xFBC2,0x8E93,0x0000, 0xFBC2,0x8E94,0x0000, 0xFBC2,0x8E95,0x0000, /* 10E93 */ +0xFBC2,0x8E96,0x0000, 0xFBC2,0x8E97,0x0000, 0xFBC2,0x8E98,0x0000, /* 10E96 */ +0xFBC2,0x8E99,0x0000, 0xFBC2,0x8E9A,0x0000, 0xFBC2,0x8E9B,0x0000, /* 10E99 */ +0xFBC2,0x8E9C,0x0000, 0xFBC2,0x8E9D,0x0000, 0xFBC2,0x8E9E,0x0000, /* 10E9C */ +0xFBC2,0x8E9F,0x0000, 0xFBC2,0x8EA0,0x0000, 0xFBC2,0x8EA1,0x0000, /* 10E9F */ +0xFBC2,0x8EA2,0x0000, 0xFBC2,0x8EA3,0x0000, 0xFBC2,0x8EA4,0x0000, /* 10EA2 */ +0xFBC2,0x8EA5,0x0000, 0xFBC2,0x8EA6,0x0000, 0xFBC2,0x8EA7,0x0000, /* 10EA5 */ +0xFBC2,0x8EA8,0x0000, 0xFBC2,0x8EA9,0x0000, 0xFBC2,0x8EAA,0x0000, /* 10EA8 */ +0xFBC2,0x8EAB,0x0000, 0xFBC2,0x8EAC,0x0000, 0xFBC2,0x8EAD,0x0000, /* 10EAB */ +0xFBC2,0x8EAE,0x0000, 0xFBC2,0x8EAF,0x0000, 0xFBC2,0x8EB0,0x0000, /* 10EAE */ +0xFBC2,0x8EB1,0x0000, 0xFBC2,0x8EB2,0x0000, 0xFBC2,0x8EB3,0x0000, /* 10EB1 */ +0xFBC2,0x8EB4,0x0000, 0xFBC2,0x8EB5,0x0000, 0xFBC2,0x8EB6,0x0000, /* 10EB4 */ +0xFBC2,0x8EB7,0x0000, 0xFBC2,0x8EB8,0x0000, 0xFBC2,0x8EB9,0x0000, /* 10EB7 */ +0xFBC2,0x8EBA,0x0000, 0xFBC2,0x8EBB,0x0000, 0xFBC2,0x8EBC,0x0000, /* 10EBA */ +0xFBC2,0x8EBD,0x0000, 0xFBC2,0x8EBE,0x0000, 0xFBC2,0x8EBF,0x0000, /* 10EBD */ +0xFBC2,0x8EC0,0x0000, 0xFBC2,0x8EC1,0x0000, 0xFBC2,0x8EC2,0x0000, /* 10EC0 */ +0xFBC2,0x8EC3,0x0000, 0xFBC2,0x8EC4,0x0000, 0xFBC2,0x8EC5,0x0000, /* 10EC3 */ +0xFBC2,0x8EC6,0x0000, 0xFBC2,0x8EC7,0x0000, 0xFBC2,0x8EC8,0x0000, /* 10EC6 */ +0xFBC2,0x8EC9,0x0000, 0xFBC2,0x8ECA,0x0000, 0xFBC2,0x8ECB,0x0000, /* 10EC9 */ +0xFBC2,0x8ECC,0x0000, 0xFBC2,0x8ECD,0x0000, 0xFBC2,0x8ECE,0x0000, /* 10ECC */ +0xFBC2,0x8ECF,0x0000, 0xFBC2,0x8ED0,0x0000, 0xFBC2,0x8ED1,0x0000, /* 10ECF */ +0xFBC2,0x8ED2,0x0000, 0xFBC2,0x8ED3,0x0000, 0xFBC2,0x8ED4,0x0000, /* 10ED2 */ +0xFBC2,0x8ED5,0x0000, 0xFBC2,0x8ED6,0x0000, 0xFBC2,0x8ED7,0x0000, /* 10ED5 */ +0xFBC2,0x8ED8,0x0000, 0xFBC2,0x8ED9,0x0000, 0xFBC2,0x8EDA,0x0000, /* 10ED8 */ +0xFBC2,0x8EDB,0x0000, 0xFBC2,0x8EDC,0x0000, 0xFBC2,0x8EDD,0x0000, /* 10EDB */ +0xFBC2,0x8EDE,0x0000, 0xFBC2,0x8EDF,0x0000, 0xFBC2,0x8EE0,0x0000, /* 10EDE */ +0xFBC2,0x8EE1,0x0000, 0xFBC2,0x8EE2,0x0000, 0xFBC2,0x8EE3,0x0000, /* 10EE1 */ +0xFBC2,0x8EE4,0x0000, 0xFBC2,0x8EE5,0x0000, 0xFBC2,0x8EE6,0x0000, /* 10EE4 */ +0xFBC2,0x8EE7,0x0000, 0xFBC2,0x8EE8,0x0000, 0xFBC2,0x8EE9,0x0000, /* 10EE7 */ +0xFBC2,0x8EEA,0x0000, 0xFBC2,0x8EEB,0x0000, 0xFBC2,0x8EEC,0x0000, /* 10EEA */ +0xFBC2,0x8EED,0x0000, 0xFBC2,0x8EEE,0x0000, 0xFBC2,0x8EEF,0x0000, /* 10EED */ +0xFBC2,0x8EF0,0x0000, 0xFBC2,0x8EF1,0x0000, 0xFBC2,0x8EF2,0x0000, /* 10EF0 */ +0xFBC2,0x8EF3,0x0000, 0xFBC2,0x8EF4,0x0000, 0xFBC2,0x8EF5,0x0000, /* 10EF3 */ +0xFBC2,0x8EF6,0x0000, 0xFBC2,0x8EF7,0x0000, 0xFBC2,0x8EF8,0x0000, /* 10EF6 */ +0xFBC2,0x8EF9,0x0000, 0xFBC2,0x8EFA,0x0000, 0xFBC2,0x8EFB,0x0000, /* 10EF9 */ +0xFBC2,0x8EFC,0x0000, 0xFBC2,0x8EFD,0x0000, 0xFBC2,0x8EFE,0x0000, /* 10EFC */ +0xFBC2,0x8EFF,0x0000 }; + +uint16 uca520_p110[]= { /* 11000 (3 weights per char) */ +0xFBC2,0x9000,0x0000, 0xFBC2,0x9001,0x0000, 0xFBC2,0x9002,0x0000, /* 11000 */ +0xFBC2,0x9003,0x0000, 0xFBC2,0x9004,0x0000, 0xFBC2,0x9005,0x0000, /* 11003 */ +0xFBC2,0x9006,0x0000, 0xFBC2,0x9007,0x0000, 0xFBC2,0x9008,0x0000, /* 11006 */ +0xFBC2,0x9009,0x0000, 0xFBC2,0x900A,0x0000, 0xFBC2,0x900B,0x0000, /* 11009 */ +0xFBC2,0x900C,0x0000, 0xFBC2,0x900D,0x0000, 0xFBC2,0x900E,0x0000, /* 1100C */ +0xFBC2,0x900F,0x0000, 0xFBC2,0x9010,0x0000, 0xFBC2,0x9011,0x0000, /* 1100F */ +0xFBC2,0x9012,0x0000, 0xFBC2,0x9013,0x0000, 0xFBC2,0x9014,0x0000, /* 11012 */ +0xFBC2,0x9015,0x0000, 0xFBC2,0x9016,0x0000, 0xFBC2,0x9017,0x0000, /* 11015 */ +0xFBC2,0x9018,0x0000, 0xFBC2,0x9019,0x0000, 0xFBC2,0x901A,0x0000, /* 11018 */ +0xFBC2,0x901B,0x0000, 0xFBC2,0x901C,0x0000, 0xFBC2,0x901D,0x0000, /* 1101B */ +0xFBC2,0x901E,0x0000, 0xFBC2,0x901F,0x0000, 0xFBC2,0x9020,0x0000, /* 1101E */ +0xFBC2,0x9021,0x0000, 0xFBC2,0x9022,0x0000, 0xFBC2,0x9023,0x0000, /* 11021 */ +0xFBC2,0x9024,0x0000, 0xFBC2,0x9025,0x0000, 0xFBC2,0x9026,0x0000, /* 11024 */ +0xFBC2,0x9027,0x0000, 0xFBC2,0x9028,0x0000, 0xFBC2,0x9029,0x0000, /* 11027 */ +0xFBC2,0x902A,0x0000, 0xFBC2,0x902B,0x0000, 0xFBC2,0x902C,0x0000, /* 1102A */ +0xFBC2,0x902D,0x0000, 0xFBC2,0x902E,0x0000, 0xFBC2,0x902F,0x0000, /* 1102D */ +0xFBC2,0x9030,0x0000, 0xFBC2,0x9031,0x0000, 0xFBC2,0x9032,0x0000, /* 11030 */ +0xFBC2,0x9033,0x0000, 0xFBC2,0x9034,0x0000, 0xFBC2,0x9035,0x0000, /* 11033 */ +0xFBC2,0x9036,0x0000, 0xFBC2,0x9037,0x0000, 0xFBC2,0x9038,0x0000, /* 11036 */ +0xFBC2,0x9039,0x0000, 0xFBC2,0x903A,0x0000, 0xFBC2,0x903B,0x0000, /* 11039 */ +0xFBC2,0x903C,0x0000, 0xFBC2,0x903D,0x0000, 0xFBC2,0x903E,0x0000, /* 1103C */ +0xFBC2,0x903F,0x0000, 0xFBC2,0x9040,0x0000, 0xFBC2,0x9041,0x0000, /* 1103F */ +0xFBC2,0x9042,0x0000, 0xFBC2,0x9043,0x0000, 0xFBC2,0x9044,0x0000, /* 11042 */ +0xFBC2,0x9045,0x0000, 0xFBC2,0x9046,0x0000, 0xFBC2,0x9047,0x0000, /* 11045 */ +0xFBC2,0x9048,0x0000, 0xFBC2,0x9049,0x0000, 0xFBC2,0x904A,0x0000, /* 11048 */ +0xFBC2,0x904B,0x0000, 0xFBC2,0x904C,0x0000, 0xFBC2,0x904D,0x0000, /* 1104B */ +0xFBC2,0x904E,0x0000, 0xFBC2,0x904F,0x0000, 0xFBC2,0x9050,0x0000, /* 1104E */ +0xFBC2,0x9051,0x0000, 0xFBC2,0x9052,0x0000, 0xFBC2,0x9053,0x0000, /* 11051 */ +0xFBC2,0x9054,0x0000, 0xFBC2,0x9055,0x0000, 0xFBC2,0x9056,0x0000, /* 11054 */ +0xFBC2,0x9057,0x0000, 0xFBC2,0x9058,0x0000, 0xFBC2,0x9059,0x0000, /* 11057 */ +0xFBC2,0x905A,0x0000, 0xFBC2,0x905B,0x0000, 0xFBC2,0x905C,0x0000, /* 1105A */ +0xFBC2,0x905D,0x0000, 0xFBC2,0x905E,0x0000, 0xFBC2,0x905F,0x0000, /* 1105D */ +0xFBC2,0x9060,0x0000, 0xFBC2,0x9061,0x0000, 0xFBC2,0x9062,0x0000, /* 11060 */ +0xFBC2,0x9063,0x0000, 0xFBC2,0x9064,0x0000, 0xFBC2,0x9065,0x0000, /* 11063 */ +0xFBC2,0x9066,0x0000, 0xFBC2,0x9067,0x0000, 0xFBC2,0x9068,0x0000, /* 11066 */ +0xFBC2,0x9069,0x0000, 0xFBC2,0x906A,0x0000, 0xFBC2,0x906B,0x0000, /* 11069 */ +0xFBC2,0x906C,0x0000, 0xFBC2,0x906D,0x0000, 0xFBC2,0x906E,0x0000, /* 1106C */ +0xFBC2,0x906F,0x0000, 0xFBC2,0x9070,0x0000, 0xFBC2,0x9071,0x0000, /* 1106F */ +0xFBC2,0x9072,0x0000, 0xFBC2,0x9073,0x0000, 0xFBC2,0x9074,0x0000, /* 11072 */ +0xFBC2,0x9075,0x0000, 0xFBC2,0x9076,0x0000, 0xFBC2,0x9077,0x0000, /* 11075 */ +0xFBC2,0x9078,0x0000, 0xFBC2,0x9079,0x0000, 0xFBC2,0x907A,0x0000, /* 11078 */ +0xFBC2,0x907B,0x0000, 0xFBC2,0x907C,0x0000, 0xFBC2,0x907D,0x0000, /* 1107B */ +0xFBC2,0x907E,0x0000, 0xFBC2,0x907F,0x0000, 0x0000,0x0000,0x0000, /* 1107E */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x1EE8,0x0000,0x0000, /* 11081 */ +0x1EE9,0x0000,0x0000, 0x1EEA,0x0000,0x0000, 0x1EEB,0x0000,0x0000, /* 11084 */ +0x1EEC,0x0000,0x0000, 0x1EED,0x0000,0x0000, 0x1EEE,0x0000,0x0000, /* 11087 */ +0x1EEF,0x0000,0x0000, 0x1EF0,0x0000,0x0000, 0x1EF1,0x0000,0x0000, /* 1108A */ +0x1EF2,0x0000,0x0000, 0x1EF3,0x0000,0x0000, 0x1EF4,0x0000,0x0000, /* 1108D */ +0x1EF5,0x0000,0x0000, 0x1EF6,0x0000,0x0000, 0x1EF7,0x0000,0x0000, /* 11090 */ +0x1EF8,0x0000,0x0000, 0x1EF9,0x0000,0x0000, 0x1EFA,0x0000,0x0000, /* 11093 */ +0x1EFB,0x0000,0x0000, 0x1EFC,0x0000,0x0000, 0x1EFD,0x0000,0x0000, /* 11096 */ +0x1EFE,0x0000,0x0000, 0x1EFE,0x0000,0x0000, 0x1EFF,0x0000,0x0000, /* 11099 */ +0x1EFF,0x0000,0x0000, 0x1F00,0x0000,0x0000, 0x1F01,0x0000,0x0000, /* 1109C */ +0x1F02,0x0000,0x0000, 0x1F03,0x0000,0x0000, 0x1F04,0x0000,0x0000, /* 1109F */ +0x1F05,0x0000,0x0000, 0x1F06,0x0000,0x0000, 0x1F07,0x0000,0x0000, /* 110A2 */ +0x1F08,0x0000,0x0000, 0x1F09,0x0000,0x0000, 0x1F0A,0x0000,0x0000, /* 110A5 */ +0x1F0B,0x0000,0x0000, 0x1F0C,0x0000,0x0000, 0x1F0D,0x0000,0x0000, /* 110A8 */ +0x1F08,0x0000,0x0000, 0x1F0E,0x0000,0x0000, 0x1F0F,0x0000,0x0000, /* 110AB */ +0x1F10,0x0000,0x0000, 0x1F11,0x0000,0x0000, 0x1F12,0x0000,0x0000, /* 110AE */ +0x1F13,0x0000,0x0000, 0x1F14,0x0000,0x0000, 0x1F15,0x0000,0x0000, /* 110B1 */ +0x1F16,0x0000,0x0000, 0x1F17,0x0000,0x0000, 0x1F18,0x0000,0x0000, /* 110B4 */ +0x1F19,0x0000,0x0000, 0x1F1A,0x0000,0x0000, 0x1F1B,0x0000,0x0000, /* 110B7 */ +0x0000,0x0000,0x0000, 0x03E7,0x0000,0x0000, 0x03E8,0x0000,0x0000, /* 110BA */ +0x0000,0x0000,0x0000, 0x02D1,0x0000,0x0000, 0x02D2,0x0000,0x0000, /* 110BD */ +0x02B1,0x0000,0x0000, 0x02B2,0x0000,0x0000, 0xFBC2,0x90C2,0x0000, /* 110C0 */ +0xFBC2,0x90C3,0x0000, 0xFBC2,0x90C4,0x0000, 0xFBC2,0x90C5,0x0000, /* 110C3 */ +0xFBC2,0x90C6,0x0000, 0xFBC2,0x90C7,0x0000, 0xFBC2,0x90C8,0x0000, /* 110C6 */ +0xFBC2,0x90C9,0x0000, 0xFBC2,0x90CA,0x0000, 0xFBC2,0x90CB,0x0000, /* 110C9 */ +0xFBC2,0x90CC,0x0000, 0xFBC2,0x90CD,0x0000, 0xFBC2,0x90CE,0x0000, /* 110CC */ +0xFBC2,0x90CF,0x0000, 0xFBC2,0x90D0,0x0000, 0xFBC2,0x90D1,0x0000, /* 110CF */ +0xFBC2,0x90D2,0x0000, 0xFBC2,0x90D3,0x0000, 0xFBC2,0x90D4,0x0000, /* 110D2 */ +0xFBC2,0x90D5,0x0000, 0xFBC2,0x90D6,0x0000, 0xFBC2,0x90D7,0x0000, /* 110D5 */ +0xFBC2,0x90D8,0x0000, 0xFBC2,0x90D9,0x0000, 0xFBC2,0x90DA,0x0000, /* 110D8 */ +0xFBC2,0x90DB,0x0000, 0xFBC2,0x90DC,0x0000, 0xFBC2,0x90DD,0x0000, /* 110DB */ +0xFBC2,0x90DE,0x0000, 0xFBC2,0x90DF,0x0000, 0xFBC2,0x90E0,0x0000, /* 110DE */ +0xFBC2,0x90E1,0x0000, 0xFBC2,0x90E2,0x0000, 0xFBC2,0x90E3,0x0000, /* 110E1 */ +0xFBC2,0x90E4,0x0000, 0xFBC2,0x90E5,0x0000, 0xFBC2,0x90E6,0x0000, /* 110E4 */ +0xFBC2,0x90E7,0x0000, 0xFBC2,0x90E8,0x0000, 0xFBC2,0x90E9,0x0000, /* 110E7 */ +0xFBC2,0x90EA,0x0000, 0xFBC2,0x90EB,0x0000, 0xFBC2,0x90EC,0x0000, /* 110EA */ +0xFBC2,0x90ED,0x0000, 0xFBC2,0x90EE,0x0000, 0xFBC2,0x90EF,0x0000, /* 110ED */ +0xFBC2,0x90F0,0x0000, 0xFBC2,0x90F1,0x0000, 0xFBC2,0x90F2,0x0000, /* 110F0 */ +0xFBC2,0x90F3,0x0000, 0xFBC2,0x90F4,0x0000, 0xFBC2,0x90F5,0x0000, /* 110F3 */ +0xFBC2,0x90F6,0x0000, 0xFBC2,0x90F7,0x0000, 0xFBC2,0x90F8,0x0000, /* 110F6 */ +0xFBC2,0x90F9,0x0000, 0xFBC2,0x90FA,0x0000, 0xFBC2,0x90FB,0x0000, /* 110F9 */ +0xFBC2,0x90FC,0x0000, 0xFBC2,0x90FD,0x0000, 0xFBC2,0x90FE,0x0000, /* 110FC */ +0xFBC2,0x90FF,0x0000 }; + +uint16 uca520_p120[]= { /* 12000 (2 weights per char) */ +0x332D,0x0000, 0x332E,0x0000, 0x332F,0x0000, 0x3330,0x0000, /* 12000 */ +0x3331,0x0000, 0x3332,0x0000, 0x3333,0x0000, 0x3334,0x0000, /* 12004 */ +0x3335,0x0000, 0x3336,0x0000, 0x3337,0x0000, 0x3338,0x0000, /* 12008 */ +0x3339,0x0000, 0x333A,0x0000, 0x333B,0x0000, 0x333C,0x0000, /* 1200C */ +0x333D,0x0000, 0x333E,0x0000, 0x333F,0x0000, 0x3340,0x0000, /* 12010 */ +0x3341,0x0000, 0x3342,0x0000, 0x3343,0x0000, 0x3344,0x0000, /* 12014 */ +0x3345,0x0000, 0x3346,0x0000, 0x3347,0x0000, 0x3348,0x0000, /* 12018 */ +0x3349,0x0000, 0x334A,0x0000, 0x334B,0x0000, 0x334C,0x0000, /* 1201C */ +0x334D,0x0000, 0x334E,0x0000, 0x334F,0x0000, 0x3350,0x0000, /* 12020 */ +0x3351,0x0000, 0x3352,0x0000, 0x3353,0x0000, 0x3354,0x0000, /* 12024 */ +0x3355,0x0000, 0x3356,0x0000, 0x3357,0x0000, 0x3358,0x0000, /* 12028 */ +0x3359,0x0000, 0x335A,0x0000, 0x335B,0x0000, 0x335C,0x0000, /* 1202C */ +0x335D,0x0000, 0x335E,0x0000, 0x335F,0x0000, 0x3360,0x0000, /* 12030 */ +0x3361,0x0000, 0x3362,0x0000, 0x3363,0x0000, 0x3364,0x0000, /* 12034 */ +0x3365,0x0000, 0x3366,0x0000, 0x3367,0x0000, 0x3368,0x0000, /* 12038 */ +0x3369,0x0000, 0x336A,0x0000, 0x336B,0x0000, 0x336C,0x0000, /* 1203C */ +0x336D,0x0000, 0x336E,0x0000, 0x336F,0x0000, 0x3370,0x0000, /* 12040 */ +0x3371,0x0000, 0x3372,0x0000, 0x3373,0x0000, 0x3374,0x0000, /* 12044 */ +0x3375,0x0000, 0x3376,0x0000, 0x3377,0x0000, 0x3378,0x0000, /* 12048 */ +0x3379,0x0000, 0x337A,0x0000, 0x337B,0x0000, 0x337C,0x0000, /* 1204C */ +0x337D,0x0000, 0x337E,0x0000, 0x337F,0x0000, 0x3380,0x0000, /* 12050 */ +0x3381,0x0000, 0x3382,0x0000, 0x3383,0x0000, 0x3384,0x0000, /* 12054 */ +0x3385,0x0000, 0x3386,0x0000, 0x3387,0x0000, 0x3388,0x0000, /* 12058 */ +0x3389,0x0000, 0x338A,0x0000, 0x338B,0x0000, 0x338C,0x0000, /* 1205C */ +0x338D,0x0000, 0x338E,0x0000, 0x338F,0x0000, 0x3390,0x0000, /* 12060 */ +0x3391,0x0000, 0x3392,0x0000, 0x3393,0x0000, 0x3394,0x0000, /* 12064 */ +0x3395,0x0000, 0x3396,0x0000, 0x3397,0x0000, 0x3398,0x0000, /* 12068 */ +0x3399,0x0000, 0x339A,0x0000, 0x339B,0x0000, 0x339C,0x0000, /* 1206C */ +0x339D,0x0000, 0x339E,0x0000, 0x339F,0x0000, 0x33A0,0x0000, /* 12070 */ +0x33A1,0x0000, 0x33A2,0x0000, 0x33A3,0x0000, 0x33A4,0x0000, /* 12074 */ +0x33A5,0x0000, 0x33A6,0x0000, 0x33A7,0x0000, 0x33A8,0x0000, /* 12078 */ +0x33A9,0x0000, 0x33AA,0x0000, 0x33AB,0x0000, 0x33AC,0x0000, /* 1207C */ +0x33AD,0x0000, 0x33AE,0x0000, 0x33AF,0x0000, 0x33B0,0x0000, /* 12080 */ +0x33B1,0x0000, 0x33B2,0x0000, 0x33B3,0x0000, 0x33B4,0x0000, /* 12084 */ +0x33B5,0x0000, 0x33B6,0x0000, 0x33B7,0x0000, 0x33B8,0x0000, /* 12088 */ +0x33B9,0x0000, 0x33BA,0x0000, 0x33BB,0x0000, 0x33BC,0x0000, /* 1208C */ +0x33BD,0x0000, 0x33BE,0x0000, 0x33BF,0x0000, 0x33C0,0x0000, /* 12090 */ +0x33C1,0x0000, 0x33C2,0x0000, 0x33C3,0x0000, 0x33C4,0x0000, /* 12094 */ +0x33C5,0x0000, 0x33C6,0x0000, 0x33C7,0x0000, 0x33C8,0x0000, /* 12098 */ +0x33C9,0x0000, 0x33CA,0x0000, 0x33CB,0x0000, 0x33CC,0x0000, /* 1209C */ +0x33CD,0x0000, 0x33CE,0x0000, 0x33CF,0x0000, 0x33D0,0x0000, /* 120A0 */ +0x33D1,0x0000, 0x33D2,0x0000, 0x33D3,0x0000, 0x33D4,0x0000, /* 120A4 */ +0x33D5,0x0000, 0x33D6,0x0000, 0x33D7,0x0000, 0x33D8,0x0000, /* 120A8 */ +0x33D9,0x0000, 0x33DA,0x0000, 0x33DB,0x0000, 0x33DC,0x0000, /* 120AC */ +0x33DD,0x0000, 0x33DE,0x0000, 0x33DF,0x0000, 0x33E0,0x0000, /* 120B0 */ +0x33E1,0x0000, 0x33E2,0x0000, 0x33E3,0x0000, 0x33E4,0x0000, /* 120B4 */ +0x33E5,0x0000, 0x33E6,0x0000, 0x33E7,0x0000, 0x33E8,0x0000, /* 120B8 */ +0x33E9,0x0000, 0x33EA,0x0000, 0x33EB,0x0000, 0x33EC,0x0000, /* 120BC */ +0x33ED,0x0000, 0x33EE,0x0000, 0x33EF,0x0000, 0x33F0,0x0000, /* 120C0 */ +0x33F1,0x0000, 0x33F2,0x0000, 0x33F3,0x0000, 0x33F4,0x0000, /* 120C4 */ +0x33F5,0x0000, 0x33F6,0x0000, 0x33F7,0x0000, 0x33F8,0x0000, /* 120C8 */ +0x33F9,0x0000, 0x33FA,0x0000, 0x33FB,0x0000, 0x33FC,0x0000, /* 120CC */ +0x33FD,0x0000, 0x33FE,0x0000, 0x33FF,0x0000, 0x3400,0x0000, /* 120D0 */ +0x3401,0x0000, 0x3402,0x0000, 0x3403,0x0000, 0x3404,0x0000, /* 120D4 */ +0x3405,0x0000, 0x3406,0x0000, 0x3407,0x0000, 0x3408,0x0000, /* 120D8 */ +0x3409,0x0000, 0x340A,0x0000, 0x340B,0x0000, 0x340C,0x0000, /* 120DC */ +0x340D,0x0000, 0x340E,0x0000, 0x340F,0x0000, 0x3410,0x0000, /* 120E0 */ +0x3411,0x0000, 0x3412,0x0000, 0x3413,0x0000, 0x3414,0x0000, /* 120E4 */ +0x3415,0x0000, 0x3416,0x0000, 0x3417,0x0000, 0x3418,0x0000, /* 120E8 */ +0x3419,0x0000, 0x341A,0x0000, 0x341B,0x0000, 0x341C,0x0000, /* 120EC */ +0x341D,0x0000, 0x341E,0x0000, 0x341F,0x0000, 0x3420,0x0000, /* 120F0 */ +0x3421,0x0000, 0x3422,0x0000, 0x3423,0x0000, 0x3424,0x0000, /* 120F4 */ +0x3425,0x0000, 0x3426,0x0000, 0x3427,0x0000, 0x3428,0x0000, /* 120F8 */ +0x3429,0x0000, 0x342A,0x0000, 0x342B,0x0000, 0x342C,0x0000 /* 120FC */ +}; + +uint16 uca520_p121[]= { /* 12100 (2 weights per char) */ +0x342D,0x0000, 0x342E,0x0000, 0x342F,0x0000, 0x3430,0x0000, /* 12100 */ +0x3431,0x0000, 0x3432,0x0000, 0x3433,0x0000, 0x3434,0x0000, /* 12104 */ +0x3435,0x0000, 0x3436,0x0000, 0x3437,0x0000, 0x3438,0x0000, /* 12108 */ +0x3439,0x0000, 0x343A,0x0000, 0x343B,0x0000, 0x343C,0x0000, /* 1210C */ +0x343D,0x0000, 0x343E,0x0000, 0x343F,0x0000, 0x3440,0x0000, /* 12110 */ +0x3441,0x0000, 0x3442,0x0000, 0x3443,0x0000, 0x3444,0x0000, /* 12114 */ +0x3445,0x0000, 0x3446,0x0000, 0x3447,0x0000, 0x3448,0x0000, /* 12118 */ +0x3449,0x0000, 0x344A,0x0000, 0x344B,0x0000, 0x344C,0x0000, /* 1211C */ +0x344D,0x0000, 0x344E,0x0000, 0x344F,0x0000, 0x3450,0x0000, /* 12120 */ +0x3451,0x0000, 0x3452,0x0000, 0x3453,0x0000, 0x3454,0x0000, /* 12124 */ +0x3455,0x0000, 0x3456,0x0000, 0x3457,0x0000, 0x3458,0x0000, /* 12128 */ +0x3459,0x0000, 0x345A,0x0000, 0x345B,0x0000, 0x345C,0x0000, /* 1212C */ +0x345D,0x0000, 0x345E,0x0000, 0x345F,0x0000, 0x3460,0x0000, /* 12130 */ +0x3461,0x0000, 0x3462,0x0000, 0x3463,0x0000, 0x3464,0x0000, /* 12134 */ +0x3465,0x0000, 0x3466,0x0000, 0x3467,0x0000, 0x3468,0x0000, /* 12138 */ +0x3469,0x0000, 0x346A,0x0000, 0x346B,0x0000, 0x346C,0x0000, /* 1213C */ +0x346D,0x0000, 0x346E,0x0000, 0x346F,0x0000, 0x3470,0x0000, /* 12140 */ +0x3471,0x0000, 0x3472,0x0000, 0x3473,0x0000, 0x3474,0x0000, /* 12144 */ +0x3475,0x0000, 0x3476,0x0000, 0x3477,0x0000, 0x3478,0x0000, /* 12148 */ +0x3479,0x0000, 0x347A,0x0000, 0x347B,0x0000, 0x347C,0x0000, /* 1214C */ +0x347D,0x0000, 0x347E,0x0000, 0x347F,0x0000, 0x3480,0x0000, /* 12150 */ +0x3481,0x0000, 0x3482,0x0000, 0x3483,0x0000, 0x3484,0x0000, /* 12154 */ +0x3485,0x0000, 0x3486,0x0000, 0x3487,0x0000, 0x3488,0x0000, /* 12158 */ +0x3489,0x0000, 0x348A,0x0000, 0x348B,0x0000, 0x348C,0x0000, /* 1215C */ +0x348D,0x0000, 0x348E,0x0000, 0x348F,0x0000, 0x3490,0x0000, /* 12160 */ +0x3491,0x0000, 0x3492,0x0000, 0x3493,0x0000, 0x3494,0x0000, /* 12164 */ +0x3495,0x0000, 0x3496,0x0000, 0x3497,0x0000, 0x3498,0x0000, /* 12168 */ +0x3499,0x0000, 0x349A,0x0000, 0x349B,0x0000, 0x349C,0x0000, /* 1216C */ +0x349D,0x0000, 0x349E,0x0000, 0x349F,0x0000, 0x34A0,0x0000, /* 12170 */ +0x34A1,0x0000, 0x34A2,0x0000, 0x34A3,0x0000, 0x34A4,0x0000, /* 12174 */ +0x34A5,0x0000, 0x34A6,0x0000, 0x34A7,0x0000, 0x34A8,0x0000, /* 12178 */ +0x34A9,0x0000, 0x34AA,0x0000, 0x34AB,0x0000, 0x34AC,0x0000, /* 1217C */ +0x34AD,0x0000, 0x34AE,0x0000, 0x34AF,0x0000, 0x34B0,0x0000, /* 12180 */ +0x34B1,0x0000, 0x34B2,0x0000, 0x34B3,0x0000, 0x34B4,0x0000, /* 12184 */ +0x34B5,0x0000, 0x34B6,0x0000, 0x34B7,0x0000, 0x34B8,0x0000, /* 12188 */ +0x34B9,0x0000, 0x34BA,0x0000, 0x34BB,0x0000, 0x34BC,0x0000, /* 1218C */ +0x34BD,0x0000, 0x34BE,0x0000, 0x34BF,0x0000, 0x34C0,0x0000, /* 12190 */ +0x34C1,0x0000, 0x34C2,0x0000, 0x34C3,0x0000, 0x34C4,0x0000, /* 12194 */ +0x34C5,0x0000, 0x34C6,0x0000, 0x34C7,0x0000, 0x34C8,0x0000, /* 12198 */ +0x34C9,0x0000, 0x34CA,0x0000, 0x34CB,0x0000, 0x34CC,0x0000, /* 1219C */ +0x34CD,0x0000, 0x34CE,0x0000, 0x34CF,0x0000, 0x34D0,0x0000, /* 121A0 */ +0x34D1,0x0000, 0x34D2,0x0000, 0x34D3,0x0000, 0x34D4,0x0000, /* 121A4 */ +0x34D5,0x0000, 0x34D6,0x0000, 0x34D7,0x0000, 0x34D8,0x0000, /* 121A8 */ +0x34D9,0x0000, 0x34DA,0x0000, 0x34DB,0x0000, 0x34DC,0x0000, /* 121AC */ +0x34DD,0x0000, 0x34DE,0x0000, 0x34DF,0x0000, 0x34E0,0x0000, /* 121B0 */ +0x34E1,0x0000, 0x34E2,0x0000, 0x34E3,0x0000, 0x34E4,0x0000, /* 121B4 */ +0x34E5,0x0000, 0x34E6,0x0000, 0x34E7,0x0000, 0x34E8,0x0000, /* 121B8 */ +0x34E9,0x0000, 0x34EA,0x0000, 0x34EB,0x0000, 0x34EC,0x0000, /* 121BC */ +0x34ED,0x0000, 0x34EE,0x0000, 0x34EF,0x0000, 0x34F0,0x0000, /* 121C0 */ +0x34F1,0x0000, 0x34F2,0x0000, 0x34F3,0x0000, 0x34F4,0x0000, /* 121C4 */ +0x34F5,0x0000, 0x34F6,0x0000, 0x34F7,0x0000, 0x34F8,0x0000, /* 121C8 */ +0x34F9,0x0000, 0x34FA,0x0000, 0x34FB,0x0000, 0x34FC,0x0000, /* 121CC */ +0x34FD,0x0000, 0x34FE,0x0000, 0x34FF,0x0000, 0x3500,0x0000, /* 121D0 */ +0x3501,0x0000, 0x3502,0x0000, 0x3503,0x0000, 0x3504,0x0000, /* 121D4 */ +0x3505,0x0000, 0x3506,0x0000, 0x3507,0x0000, 0x3508,0x0000, /* 121D8 */ +0x3509,0x0000, 0x350A,0x0000, 0x350B,0x0000, 0x350C,0x0000, /* 121DC */ +0x350D,0x0000, 0x350E,0x0000, 0x350F,0x0000, 0x3510,0x0000, /* 121E0 */ +0x3511,0x0000, 0x3512,0x0000, 0x3513,0x0000, 0x3514,0x0000, /* 121E4 */ +0x3515,0x0000, 0x3516,0x0000, 0x3517,0x0000, 0x3518,0x0000, /* 121E8 */ +0x3519,0x0000, 0x351A,0x0000, 0x351B,0x0000, 0x351C,0x0000, /* 121EC */ +0x351D,0x0000, 0x351E,0x0000, 0x351F,0x0000, 0x3520,0x0000, /* 121F0 */ +0x3521,0x0000, 0x3522,0x0000, 0x3523,0x0000, 0x3524,0x0000, /* 121F4 */ +0x3525,0x0000, 0x3526,0x0000, 0x3527,0x0000, 0x3528,0x0000, /* 121F8 */ +0x3529,0x0000, 0x352A,0x0000, 0x352B,0x0000, 0x352C,0x0000 /* 121FC */ +}; + +uint16 uca520_p122[]= { /* 12200 (2 weights per char) */ +0x352D,0x0000, 0x352E,0x0000, 0x352F,0x0000, 0x3530,0x0000, /* 12200 */ +0x3531,0x0000, 0x3532,0x0000, 0x3533,0x0000, 0x3534,0x0000, /* 12204 */ +0x3535,0x0000, 0x3536,0x0000, 0x3537,0x0000, 0x3538,0x0000, /* 12208 */ +0x3539,0x0000, 0x353A,0x0000, 0x353B,0x0000, 0x353C,0x0000, /* 1220C */ +0x353D,0x0000, 0x353E,0x0000, 0x353F,0x0000, 0x3540,0x0000, /* 12210 */ +0x3541,0x0000, 0x3542,0x0000, 0x3543,0x0000, 0x3544,0x0000, /* 12214 */ +0x3545,0x0000, 0x3546,0x0000, 0x3547,0x0000, 0x3548,0x0000, /* 12218 */ +0x3549,0x0000, 0x354A,0x0000, 0x354B,0x0000, 0x354C,0x0000, /* 1221C */ +0x354D,0x0000, 0x354E,0x0000, 0x354F,0x0000, 0x3550,0x0000, /* 12220 */ +0x3551,0x0000, 0x3552,0x0000, 0x3553,0x0000, 0x3554,0x0000, /* 12224 */ +0x3555,0x0000, 0x3556,0x0000, 0x3557,0x0000, 0x3558,0x0000, /* 12228 */ +0x3559,0x0000, 0x355A,0x0000, 0x355B,0x0000, 0x355C,0x0000, /* 1222C */ +0x355D,0x0000, 0x355E,0x0000, 0x355F,0x0000, 0x3560,0x0000, /* 12230 */ +0x3561,0x0000, 0x3562,0x0000, 0x3563,0x0000, 0x3564,0x0000, /* 12234 */ +0x3565,0x0000, 0x3566,0x0000, 0x3567,0x0000, 0x3568,0x0000, /* 12238 */ +0x3569,0x0000, 0x356A,0x0000, 0x356B,0x0000, 0x356C,0x0000, /* 1223C */ +0x356D,0x0000, 0x356E,0x0000, 0x356F,0x0000, 0x3570,0x0000, /* 12240 */ +0x3571,0x0000, 0x3572,0x0000, 0x3573,0x0000, 0x3574,0x0000, /* 12244 */ +0x3575,0x0000, 0x3576,0x0000, 0x3577,0x0000, 0x3578,0x0000, /* 12248 */ +0x3579,0x0000, 0x357A,0x0000, 0x357B,0x0000, 0x357C,0x0000, /* 1224C */ +0x357D,0x0000, 0x357E,0x0000, 0x357F,0x0000, 0x3580,0x0000, /* 12250 */ +0x3581,0x0000, 0x3582,0x0000, 0x3583,0x0000, 0x3584,0x0000, /* 12254 */ +0x3585,0x0000, 0x3586,0x0000, 0x3587,0x0000, 0x3588,0x0000, /* 12258 */ +0x3589,0x0000, 0x358A,0x0000, 0x358B,0x0000, 0x358C,0x0000, /* 1225C */ +0x358D,0x0000, 0x358E,0x0000, 0x358F,0x0000, 0x3590,0x0000, /* 12260 */ +0x3591,0x0000, 0x3592,0x0000, 0x3593,0x0000, 0x3594,0x0000, /* 12264 */ +0x3595,0x0000, 0x3596,0x0000, 0x3597,0x0000, 0x3598,0x0000, /* 12268 */ +0x3599,0x0000, 0x359A,0x0000, 0x359B,0x0000, 0x359C,0x0000, /* 1226C */ +0x359D,0x0000, 0x359E,0x0000, 0x359F,0x0000, 0x35A0,0x0000, /* 12270 */ +0x35A1,0x0000, 0x35A2,0x0000, 0x35A3,0x0000, 0x35A4,0x0000, /* 12274 */ +0x35A5,0x0000, 0x35A6,0x0000, 0x35A7,0x0000, 0x35A8,0x0000, /* 12278 */ +0x35A9,0x0000, 0x35AA,0x0000, 0x35AB,0x0000, 0x35AC,0x0000, /* 1227C */ +0x35AD,0x0000, 0x35AE,0x0000, 0x35AF,0x0000, 0x35B0,0x0000, /* 12280 */ +0x35B1,0x0000, 0x35B2,0x0000, 0x35B3,0x0000, 0x35B4,0x0000, /* 12284 */ +0x35B5,0x0000, 0x35B6,0x0000, 0x35B7,0x0000, 0x35B8,0x0000, /* 12288 */ +0x35B9,0x0000, 0x35BA,0x0000, 0x35BB,0x0000, 0x35BC,0x0000, /* 1228C */ +0x35BD,0x0000, 0x35BE,0x0000, 0x35BF,0x0000, 0x35C0,0x0000, /* 12290 */ +0x35C1,0x0000, 0x35C2,0x0000, 0x35C3,0x0000, 0x35C4,0x0000, /* 12294 */ +0x35C5,0x0000, 0x35C6,0x0000, 0x35C7,0x0000, 0x35C8,0x0000, /* 12298 */ +0x35C9,0x0000, 0x35CA,0x0000, 0x35CB,0x0000, 0x35CC,0x0000, /* 1229C */ +0x35CD,0x0000, 0x35CE,0x0000, 0x35CF,0x0000, 0x35D0,0x0000, /* 122A0 */ +0x35D1,0x0000, 0x35D2,0x0000, 0x35D3,0x0000, 0x35D4,0x0000, /* 122A4 */ +0x35D5,0x0000, 0x35D6,0x0000, 0x35D7,0x0000, 0x35D8,0x0000, /* 122A8 */ +0x35D9,0x0000, 0x35DA,0x0000, 0x35DB,0x0000, 0x35DC,0x0000, /* 122AC */ +0x35DD,0x0000, 0x35DE,0x0000, 0x35DF,0x0000, 0x35E0,0x0000, /* 122B0 */ +0x35E1,0x0000, 0x35E2,0x0000, 0x35E3,0x0000, 0x35E4,0x0000, /* 122B4 */ +0x35E5,0x0000, 0x35E6,0x0000, 0x35E7,0x0000, 0x35E8,0x0000, /* 122B8 */ +0x35E9,0x0000, 0x35EA,0x0000, 0x35EB,0x0000, 0x35EC,0x0000, /* 122BC */ +0x35ED,0x0000, 0x35EE,0x0000, 0x35EF,0x0000, 0x35F0,0x0000, /* 122C0 */ +0x35F1,0x0000, 0x35F2,0x0000, 0x35F3,0x0000, 0x35F4,0x0000, /* 122C4 */ +0x35F5,0x0000, 0x35F6,0x0000, 0x35F7,0x0000, 0x35F8,0x0000, /* 122C8 */ +0x35F9,0x0000, 0x35FA,0x0000, 0x35FB,0x0000, 0x35FC,0x0000, /* 122CC */ +0x35FD,0x0000, 0x35FE,0x0000, 0x35FF,0x0000, 0x3600,0x0000, /* 122D0 */ +0x3601,0x0000, 0x3602,0x0000, 0x3603,0x0000, 0x3604,0x0000, /* 122D4 */ +0x3605,0x0000, 0x3606,0x0000, 0x3607,0x0000, 0x3608,0x0000, /* 122D8 */ +0x3609,0x0000, 0x360A,0x0000, 0x360B,0x0000, 0x360C,0x0000, /* 122DC */ +0x360D,0x0000, 0x360E,0x0000, 0x360F,0x0000, 0x3610,0x0000, /* 122E0 */ +0x3611,0x0000, 0x3612,0x0000, 0x3613,0x0000, 0x3614,0x0000, /* 122E4 */ +0x3615,0x0000, 0x3616,0x0000, 0x3617,0x0000, 0x3618,0x0000, /* 122E8 */ +0x3619,0x0000, 0x361A,0x0000, 0x361B,0x0000, 0x361C,0x0000, /* 122EC */ +0x361D,0x0000, 0x361E,0x0000, 0x361F,0x0000, 0x3620,0x0000, /* 122F0 */ +0x3621,0x0000, 0x3622,0x0000, 0x3623,0x0000, 0x3624,0x0000, /* 122F4 */ +0x3625,0x0000, 0x3626,0x0000, 0x3627,0x0000, 0x3628,0x0000, /* 122F8 */ +0x3629,0x0000, 0x362A,0x0000, 0x362B,0x0000, 0x362C,0x0000 /* 122FC */ +}; + +uint16 uca520_p123[]= { /* 12300 (3 weights per char) */ +0x362D,0x0000,0x0000, 0x362E,0x0000,0x0000, 0x362F,0x0000,0x0000, /* 12300 */ +0x3630,0x0000,0x0000, 0x3631,0x0000,0x0000, 0x3632,0x0000,0x0000, /* 12303 */ +0x3633,0x0000,0x0000, 0x3634,0x0000,0x0000, 0x3635,0x0000,0x0000, /* 12306 */ +0x3636,0x0000,0x0000, 0x3637,0x0000,0x0000, 0x3638,0x0000,0x0000, /* 12309 */ +0x3639,0x0000,0x0000, 0x363A,0x0000,0x0000, 0x363B,0x0000,0x0000, /* 1230C */ +0x363C,0x0000,0x0000, 0x363D,0x0000,0x0000, 0x363E,0x0000,0x0000, /* 1230F */ +0x363F,0x0000,0x0000, 0x3640,0x0000,0x0000, 0x3641,0x0000,0x0000, /* 12312 */ +0x3642,0x0000,0x0000, 0x3643,0x0000,0x0000, 0x3644,0x0000,0x0000, /* 12315 */ +0x3645,0x0000,0x0000, 0x3646,0x0000,0x0000, 0x3647,0x0000,0x0000, /* 12318 */ +0x3648,0x0000,0x0000, 0x3649,0x0000,0x0000, 0x364A,0x0000,0x0000, /* 1231B */ +0x364B,0x0000,0x0000, 0x364C,0x0000,0x0000, 0x364D,0x0000,0x0000, /* 1231E */ +0x364E,0x0000,0x0000, 0x364F,0x0000,0x0000, 0x3650,0x0000,0x0000, /* 12321 */ +0x3651,0x0000,0x0000, 0x3652,0x0000,0x0000, 0x3653,0x0000,0x0000, /* 12324 */ +0x3654,0x0000,0x0000, 0x3655,0x0000,0x0000, 0x3656,0x0000,0x0000, /* 12327 */ +0x3657,0x0000,0x0000, 0x3658,0x0000,0x0000, 0x3659,0x0000,0x0000, /* 1232A */ +0x365A,0x0000,0x0000, 0x365B,0x0000,0x0000, 0x365C,0x0000,0x0000, /* 1232D */ +0x365D,0x0000,0x0000, 0x365E,0x0000,0x0000, 0x365F,0x0000,0x0000, /* 12330 */ +0x3660,0x0000,0x0000, 0x3661,0x0000,0x0000, 0x3662,0x0000,0x0000, /* 12333 */ +0x3663,0x0000,0x0000, 0x3664,0x0000,0x0000, 0x3665,0x0000,0x0000, /* 12336 */ +0x3666,0x0000,0x0000, 0x3667,0x0000,0x0000, 0x3668,0x0000,0x0000, /* 12339 */ +0x3669,0x0000,0x0000, 0x366A,0x0000,0x0000, 0x366B,0x0000,0x0000, /* 1233C */ +0x366C,0x0000,0x0000, 0x366D,0x0000,0x0000, 0x366E,0x0000,0x0000, /* 1233F */ +0x366F,0x0000,0x0000, 0x3670,0x0000,0x0000, 0x3671,0x0000,0x0000, /* 12342 */ +0x3672,0x0000,0x0000, 0x3673,0x0000,0x0000, 0x3674,0x0000,0x0000, /* 12345 */ +0x3675,0x0000,0x0000, 0x3676,0x0000,0x0000, 0x3677,0x0000,0x0000, /* 12348 */ +0x3678,0x0000,0x0000, 0x3679,0x0000,0x0000, 0x367A,0x0000,0x0000, /* 1234B */ +0x367B,0x0000,0x0000, 0x367C,0x0000,0x0000, 0x367D,0x0000,0x0000, /* 1234E */ +0x367E,0x0000,0x0000, 0x367F,0x0000,0x0000, 0x3680,0x0000,0x0000, /* 12351 */ +0x3681,0x0000,0x0000, 0x3682,0x0000,0x0000, 0x3683,0x0000,0x0000, /* 12354 */ +0x3684,0x0000,0x0000, 0x3685,0x0000,0x0000, 0x3686,0x0000,0x0000, /* 12357 */ +0x3687,0x0000,0x0000, 0x3688,0x0000,0x0000, 0x3689,0x0000,0x0000, /* 1235A */ +0x368A,0x0000,0x0000, 0x368B,0x0000,0x0000, 0x368C,0x0000,0x0000, /* 1235D */ +0x368D,0x0000,0x0000, 0x368E,0x0000,0x0000, 0x368F,0x0000,0x0000, /* 12360 */ +0x3690,0x0000,0x0000, 0x3691,0x0000,0x0000, 0x3692,0x0000,0x0000, /* 12363 */ +0x3693,0x0000,0x0000, 0x3694,0x0000,0x0000, 0x3695,0x0000,0x0000, /* 12366 */ +0x3696,0x0000,0x0000, 0x3697,0x0000,0x0000, 0x3698,0x0000,0x0000, /* 12369 */ +0x3699,0x0000,0x0000, 0x369A,0x0000,0x0000, 0x369B,0x0000,0x0000, /* 1236C */ +0xFBC2,0xA36F,0x0000, 0xFBC2,0xA370,0x0000, 0xFBC2,0xA371,0x0000, /* 1236F */ +0xFBC2,0xA372,0x0000, 0xFBC2,0xA373,0x0000, 0xFBC2,0xA374,0x0000, /* 12372 */ +0xFBC2,0xA375,0x0000, 0xFBC2,0xA376,0x0000, 0xFBC2,0xA377,0x0000, /* 12375 */ +0xFBC2,0xA378,0x0000, 0xFBC2,0xA379,0x0000, 0xFBC2,0xA37A,0x0000, /* 12378 */ +0xFBC2,0xA37B,0x0000, 0xFBC2,0xA37C,0x0000, 0xFBC2,0xA37D,0x0000, /* 1237B */ +0xFBC2,0xA37E,0x0000, 0xFBC2,0xA37F,0x0000, 0xFBC2,0xA380,0x0000, /* 1237E */ +0xFBC2,0xA381,0x0000, 0xFBC2,0xA382,0x0000, 0xFBC2,0xA383,0x0000, /* 12381 */ +0xFBC2,0xA384,0x0000, 0xFBC2,0xA385,0x0000, 0xFBC2,0xA386,0x0000, /* 12384 */ +0xFBC2,0xA387,0x0000, 0xFBC2,0xA388,0x0000, 0xFBC2,0xA389,0x0000, /* 12387 */ +0xFBC2,0xA38A,0x0000, 0xFBC2,0xA38B,0x0000, 0xFBC2,0xA38C,0x0000, /* 1238A */ +0xFBC2,0xA38D,0x0000, 0xFBC2,0xA38E,0x0000, 0xFBC2,0xA38F,0x0000, /* 1238D */ +0xFBC2,0xA390,0x0000, 0xFBC2,0xA391,0x0000, 0xFBC2,0xA392,0x0000, /* 12390 */ +0xFBC2,0xA393,0x0000, 0xFBC2,0xA394,0x0000, 0xFBC2,0xA395,0x0000, /* 12393 */ +0xFBC2,0xA396,0x0000, 0xFBC2,0xA397,0x0000, 0xFBC2,0xA398,0x0000, /* 12396 */ +0xFBC2,0xA399,0x0000, 0xFBC2,0xA39A,0x0000, 0xFBC2,0xA39B,0x0000, /* 12399 */ +0xFBC2,0xA39C,0x0000, 0xFBC2,0xA39D,0x0000, 0xFBC2,0xA39E,0x0000, /* 1239C */ +0xFBC2,0xA39F,0x0000, 0xFBC2,0xA3A0,0x0000, 0xFBC2,0xA3A1,0x0000, /* 1239F */ +0xFBC2,0xA3A2,0x0000, 0xFBC2,0xA3A3,0x0000, 0xFBC2,0xA3A4,0x0000, /* 123A2 */ +0xFBC2,0xA3A5,0x0000, 0xFBC2,0xA3A6,0x0000, 0xFBC2,0xA3A7,0x0000, /* 123A5 */ +0xFBC2,0xA3A8,0x0000, 0xFBC2,0xA3A9,0x0000, 0xFBC2,0xA3AA,0x0000, /* 123A8 */ +0xFBC2,0xA3AB,0x0000, 0xFBC2,0xA3AC,0x0000, 0xFBC2,0xA3AD,0x0000, /* 123AB */ +0xFBC2,0xA3AE,0x0000, 0xFBC2,0xA3AF,0x0000, 0xFBC2,0xA3B0,0x0000, /* 123AE */ +0xFBC2,0xA3B1,0x0000, 0xFBC2,0xA3B2,0x0000, 0xFBC2,0xA3B3,0x0000, /* 123B1 */ +0xFBC2,0xA3B4,0x0000, 0xFBC2,0xA3B5,0x0000, 0xFBC2,0xA3B6,0x0000, /* 123B4 */ +0xFBC2,0xA3B7,0x0000, 0xFBC2,0xA3B8,0x0000, 0xFBC2,0xA3B9,0x0000, /* 123B7 */ +0xFBC2,0xA3BA,0x0000, 0xFBC2,0xA3BB,0x0000, 0xFBC2,0xA3BC,0x0000, /* 123BA */ +0xFBC2,0xA3BD,0x0000, 0xFBC2,0xA3BE,0x0000, 0xFBC2,0xA3BF,0x0000, /* 123BD */ +0xFBC2,0xA3C0,0x0000, 0xFBC2,0xA3C1,0x0000, 0xFBC2,0xA3C2,0x0000, /* 123C0 */ +0xFBC2,0xA3C3,0x0000, 0xFBC2,0xA3C4,0x0000, 0xFBC2,0xA3C5,0x0000, /* 123C3 */ +0xFBC2,0xA3C6,0x0000, 0xFBC2,0xA3C7,0x0000, 0xFBC2,0xA3C8,0x0000, /* 123C6 */ +0xFBC2,0xA3C9,0x0000, 0xFBC2,0xA3CA,0x0000, 0xFBC2,0xA3CB,0x0000, /* 123C9 */ +0xFBC2,0xA3CC,0x0000, 0xFBC2,0xA3CD,0x0000, 0xFBC2,0xA3CE,0x0000, /* 123CC */ +0xFBC2,0xA3CF,0x0000, 0xFBC2,0xA3D0,0x0000, 0xFBC2,0xA3D1,0x0000, /* 123CF */ +0xFBC2,0xA3D2,0x0000, 0xFBC2,0xA3D3,0x0000, 0xFBC2,0xA3D4,0x0000, /* 123D2 */ +0xFBC2,0xA3D5,0x0000, 0xFBC2,0xA3D6,0x0000, 0xFBC2,0xA3D7,0x0000, /* 123D5 */ +0xFBC2,0xA3D8,0x0000, 0xFBC2,0xA3D9,0x0000, 0xFBC2,0xA3DA,0x0000, /* 123D8 */ +0xFBC2,0xA3DB,0x0000, 0xFBC2,0xA3DC,0x0000, 0xFBC2,0xA3DD,0x0000, /* 123DB */ +0xFBC2,0xA3DE,0x0000, 0xFBC2,0xA3DF,0x0000, 0xFBC2,0xA3E0,0x0000, /* 123DE */ +0xFBC2,0xA3E1,0x0000, 0xFBC2,0xA3E2,0x0000, 0xFBC2,0xA3E3,0x0000, /* 123E1 */ +0xFBC2,0xA3E4,0x0000, 0xFBC2,0xA3E5,0x0000, 0xFBC2,0xA3E6,0x0000, /* 123E4 */ +0xFBC2,0xA3E7,0x0000, 0xFBC2,0xA3E8,0x0000, 0xFBC2,0xA3E9,0x0000, /* 123E7 */ +0xFBC2,0xA3EA,0x0000, 0xFBC2,0xA3EB,0x0000, 0xFBC2,0xA3EC,0x0000, /* 123EA */ +0xFBC2,0xA3ED,0x0000, 0xFBC2,0xA3EE,0x0000, 0xFBC2,0xA3EF,0x0000, /* 123ED */ +0xFBC2,0xA3F0,0x0000, 0xFBC2,0xA3F1,0x0000, 0xFBC2,0xA3F2,0x0000, /* 123F0 */ +0xFBC2,0xA3F3,0x0000, 0xFBC2,0xA3F4,0x0000, 0xFBC2,0xA3F5,0x0000, /* 123F3 */ +0xFBC2,0xA3F6,0x0000, 0xFBC2,0xA3F7,0x0000, 0xFBC2,0xA3F8,0x0000, /* 123F6 */ +0xFBC2,0xA3F9,0x0000, 0xFBC2,0xA3FA,0x0000, 0xFBC2,0xA3FB,0x0000, /* 123F9 */ +0xFBC2,0xA3FC,0x0000, 0xFBC2,0xA3FD,0x0000, 0xFBC2,0xA3FE,0x0000, /* 123FC */ +0xFBC2,0xA3FF,0x0000 }; + +uint16 uca520_p124[]= { /* 12400 (3 weights per char) */ +0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, /* 12400 */ +0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, /* 12403 */ +0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 12406 */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 12409 */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 1240C */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 1240F */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 12412 */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 12415 */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 12418 */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 1241B */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 1241E */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 12421 */ +0x1208,0x0000,0x0000, 0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, /* 12424 */ +0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, /* 12427 */ +0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, 0x1206,0x0000,0x0000, /* 1242A */ +0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 1242D */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x11B8,0x0000,0x0000, /* 12430 */ +0x11B9,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 12433 */ +0x1208,0x0000,0x0000, 0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, /* 12436 */ +0x120A,0x0000,0x0000, 0x1208,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 12439 */ +0x1209,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x1209,0x0000,0x0000, /* 1243C */ +0x1209,0x0000,0x0000, 0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, /* 1243F */ +0x120C,0x0000,0x0000, 0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, /* 12442 */ +0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 12445 */ +0x120E,0x0000,0x0000, 0x120E,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 12448 */ +0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, /* 1244B */ +0x120B,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 1244E */ +0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x1209,0x0000,0x0000, /* 12451 */ +0x120A,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x11BA,0x0000,0x0000, /* 12454 */ +0x11BB,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 12457 */ +0x11BC,0x0000,0x0000, 0x11BD,0x0000,0x0000, 0x11BE,0x0000,0x0000, /* 1245A */ +0x11BF,0x0000,0x0000, 0x11C0,0x0000,0x0000, 0x11C1,0x0000,0x0000, /* 1245D */ +0x11C2,0x0000,0x0000, 0x11C3,0x0000,0x0000, 0x11C4,0x0000,0x0000, /* 12460 */ +0xFBC2,0xA463,0x0000, 0xFBC2,0xA464,0x0000, 0xFBC2,0xA465,0x0000, /* 12463 */ +0xFBC2,0xA466,0x0000, 0xFBC2,0xA467,0x0000, 0xFBC2,0xA468,0x0000, /* 12466 */ +0xFBC2,0xA469,0x0000, 0xFBC2,0xA46A,0x0000, 0xFBC2,0xA46B,0x0000, /* 12469 */ +0xFBC2,0xA46C,0x0000, 0xFBC2,0xA46D,0x0000, 0xFBC2,0xA46E,0x0000, /* 1246C */ +0xFBC2,0xA46F,0x0000, 0x02EA,0x0000,0x0000, 0x02EB,0x0000,0x0000, /* 1246F */ +0x02EC,0x0000,0x0000, 0x02ED,0x0000,0x0000, 0xFBC2,0xA474,0x0000, /* 12472 */ +0xFBC2,0xA475,0x0000, 0xFBC2,0xA476,0x0000, 0xFBC2,0xA477,0x0000, /* 12475 */ +0xFBC2,0xA478,0x0000, 0xFBC2,0xA479,0x0000, 0xFBC2,0xA47A,0x0000, /* 12478 */ +0xFBC2,0xA47B,0x0000, 0xFBC2,0xA47C,0x0000, 0xFBC2,0xA47D,0x0000, /* 1247B */ +0xFBC2,0xA47E,0x0000, 0xFBC2,0xA47F,0x0000, 0xFBC2,0xA480,0x0000, /* 1247E */ +0xFBC2,0xA481,0x0000, 0xFBC2,0xA482,0x0000, 0xFBC2,0xA483,0x0000, /* 12481 */ +0xFBC2,0xA484,0x0000, 0xFBC2,0xA485,0x0000, 0xFBC2,0xA486,0x0000, /* 12484 */ +0xFBC2,0xA487,0x0000, 0xFBC2,0xA488,0x0000, 0xFBC2,0xA489,0x0000, /* 12487 */ +0xFBC2,0xA48A,0x0000, 0xFBC2,0xA48B,0x0000, 0xFBC2,0xA48C,0x0000, /* 1248A */ +0xFBC2,0xA48D,0x0000, 0xFBC2,0xA48E,0x0000, 0xFBC2,0xA48F,0x0000, /* 1248D */ +0xFBC2,0xA490,0x0000, 0xFBC2,0xA491,0x0000, 0xFBC2,0xA492,0x0000, /* 12490 */ +0xFBC2,0xA493,0x0000, 0xFBC2,0xA494,0x0000, 0xFBC2,0xA495,0x0000, /* 12493 */ +0xFBC2,0xA496,0x0000, 0xFBC2,0xA497,0x0000, 0xFBC2,0xA498,0x0000, /* 12496 */ +0xFBC2,0xA499,0x0000, 0xFBC2,0xA49A,0x0000, 0xFBC2,0xA49B,0x0000, /* 12499 */ +0xFBC2,0xA49C,0x0000, 0xFBC2,0xA49D,0x0000, 0xFBC2,0xA49E,0x0000, /* 1249C */ +0xFBC2,0xA49F,0x0000, 0xFBC2,0xA4A0,0x0000, 0xFBC2,0xA4A1,0x0000, /* 1249F */ +0xFBC2,0xA4A2,0x0000, 0xFBC2,0xA4A3,0x0000, 0xFBC2,0xA4A4,0x0000, /* 124A2 */ +0xFBC2,0xA4A5,0x0000, 0xFBC2,0xA4A6,0x0000, 0xFBC2,0xA4A7,0x0000, /* 124A5 */ +0xFBC2,0xA4A8,0x0000, 0xFBC2,0xA4A9,0x0000, 0xFBC2,0xA4AA,0x0000, /* 124A8 */ +0xFBC2,0xA4AB,0x0000, 0xFBC2,0xA4AC,0x0000, 0xFBC2,0xA4AD,0x0000, /* 124AB */ +0xFBC2,0xA4AE,0x0000, 0xFBC2,0xA4AF,0x0000, 0xFBC2,0xA4B0,0x0000, /* 124AE */ +0xFBC2,0xA4B1,0x0000, 0xFBC2,0xA4B2,0x0000, 0xFBC2,0xA4B3,0x0000, /* 124B1 */ +0xFBC2,0xA4B4,0x0000, 0xFBC2,0xA4B5,0x0000, 0xFBC2,0xA4B6,0x0000, /* 124B4 */ +0xFBC2,0xA4B7,0x0000, 0xFBC2,0xA4B8,0x0000, 0xFBC2,0xA4B9,0x0000, /* 124B7 */ +0xFBC2,0xA4BA,0x0000, 0xFBC2,0xA4BB,0x0000, 0xFBC2,0xA4BC,0x0000, /* 124BA */ +0xFBC2,0xA4BD,0x0000, 0xFBC2,0xA4BE,0x0000, 0xFBC2,0xA4BF,0x0000, /* 124BD */ +0xFBC2,0xA4C0,0x0000, 0xFBC2,0xA4C1,0x0000, 0xFBC2,0xA4C2,0x0000, /* 124C0 */ +0xFBC2,0xA4C3,0x0000, 0xFBC2,0xA4C4,0x0000, 0xFBC2,0xA4C5,0x0000, /* 124C3 */ +0xFBC2,0xA4C6,0x0000, 0xFBC2,0xA4C7,0x0000, 0xFBC2,0xA4C8,0x0000, /* 124C6 */ +0xFBC2,0xA4C9,0x0000, 0xFBC2,0xA4CA,0x0000, 0xFBC2,0xA4CB,0x0000, /* 124C9 */ +0xFBC2,0xA4CC,0x0000, 0xFBC2,0xA4CD,0x0000, 0xFBC2,0xA4CE,0x0000, /* 124CC */ +0xFBC2,0xA4CF,0x0000, 0xFBC2,0xA4D0,0x0000, 0xFBC2,0xA4D1,0x0000, /* 124CF */ +0xFBC2,0xA4D2,0x0000, 0xFBC2,0xA4D3,0x0000, 0xFBC2,0xA4D4,0x0000, /* 124D2 */ +0xFBC2,0xA4D5,0x0000, 0xFBC2,0xA4D6,0x0000, 0xFBC2,0xA4D7,0x0000, /* 124D5 */ +0xFBC2,0xA4D8,0x0000, 0xFBC2,0xA4D9,0x0000, 0xFBC2,0xA4DA,0x0000, /* 124D8 */ +0xFBC2,0xA4DB,0x0000, 0xFBC2,0xA4DC,0x0000, 0xFBC2,0xA4DD,0x0000, /* 124DB */ +0xFBC2,0xA4DE,0x0000, 0xFBC2,0xA4DF,0x0000, 0xFBC2,0xA4E0,0x0000, /* 124DE */ +0xFBC2,0xA4E1,0x0000, 0xFBC2,0xA4E2,0x0000, 0xFBC2,0xA4E3,0x0000, /* 124E1 */ +0xFBC2,0xA4E4,0x0000, 0xFBC2,0xA4E5,0x0000, 0xFBC2,0xA4E6,0x0000, /* 124E4 */ +0xFBC2,0xA4E7,0x0000, 0xFBC2,0xA4E8,0x0000, 0xFBC2,0xA4E9,0x0000, /* 124E7 */ +0xFBC2,0xA4EA,0x0000, 0xFBC2,0xA4EB,0x0000, 0xFBC2,0xA4EC,0x0000, /* 124EA */ +0xFBC2,0xA4ED,0x0000, 0xFBC2,0xA4EE,0x0000, 0xFBC2,0xA4EF,0x0000, /* 124ED */ +0xFBC2,0xA4F0,0x0000, 0xFBC2,0xA4F1,0x0000, 0xFBC2,0xA4F2,0x0000, /* 124F0 */ +0xFBC2,0xA4F3,0x0000, 0xFBC2,0xA4F4,0x0000, 0xFBC2,0xA4F5,0x0000, /* 124F3 */ +0xFBC2,0xA4F6,0x0000, 0xFBC2,0xA4F7,0x0000, 0xFBC2,0xA4F8,0x0000, /* 124F6 */ +0xFBC2,0xA4F9,0x0000, 0xFBC2,0xA4FA,0x0000, 0xFBC2,0xA4FB,0x0000, /* 124F9 */ +0xFBC2,0xA4FC,0x0000, 0xFBC2,0xA4FD,0x0000, 0xFBC2,0xA4FE,0x0000, /* 124FC */ +0xFBC2,0xA4FF,0x0000 }; + +uint16 uca520_p130[]= { /* 13000 (2 weights per char) */ +0x369C,0x0000, 0x369D,0x0000, 0x369E,0x0000, 0x369F,0x0000, /* 13000 */ +0x36A0,0x0000, 0x36A1,0x0000, 0x36A2,0x0000, 0x36A3,0x0000, /* 13004 */ +0x36A4,0x0000, 0x36A5,0x0000, 0x36A6,0x0000, 0x36A7,0x0000, /* 13008 */ +0x36A8,0x0000, 0x36A9,0x0000, 0x36AA,0x0000, 0x36AB,0x0000, /* 1300C */ +0x36AC,0x0000, 0x36AD,0x0000, 0x36AE,0x0000, 0x36AF,0x0000, /* 13010 */ +0x36B0,0x0000, 0x36B1,0x0000, 0x36B2,0x0000, 0x36B3,0x0000, /* 13014 */ +0x36B4,0x0000, 0x36B5,0x0000, 0x36B6,0x0000, 0x36B7,0x0000, /* 13018 */ +0x36B8,0x0000, 0x36B9,0x0000, 0x36BA,0x0000, 0x36BB,0x0000, /* 1301C */ +0x36BC,0x0000, 0x36BD,0x0000, 0x36BE,0x0000, 0x36BF,0x0000, /* 13020 */ +0x36C0,0x0000, 0x36C1,0x0000, 0x36C2,0x0000, 0x36C3,0x0000, /* 13024 */ +0x36C4,0x0000, 0x36C5,0x0000, 0x36C6,0x0000, 0x36C7,0x0000, /* 13028 */ +0x36C8,0x0000, 0x36C9,0x0000, 0x36CA,0x0000, 0x36CB,0x0000, /* 1302C */ +0x36CC,0x0000, 0x36CD,0x0000, 0x36CE,0x0000, 0x36CF,0x0000, /* 13030 */ +0x36D0,0x0000, 0x36D1,0x0000, 0x36D2,0x0000, 0x36D3,0x0000, /* 13034 */ +0x36D4,0x0000, 0x36D5,0x0000, 0x36D6,0x0000, 0x36D7,0x0000, /* 13038 */ +0x36D8,0x0000, 0x36D9,0x0000, 0x36DA,0x0000, 0x36DB,0x0000, /* 1303C */ +0x36DC,0x0000, 0x36DD,0x0000, 0x36DE,0x0000, 0x36DF,0x0000, /* 13040 */ +0x36E0,0x0000, 0x36E1,0x0000, 0x36E2,0x0000, 0x36E3,0x0000, /* 13044 */ +0x36E4,0x0000, 0x36E5,0x0000, 0x36E6,0x0000, 0x36E7,0x0000, /* 13048 */ +0x36E8,0x0000, 0x36E9,0x0000, 0x36EA,0x0000, 0x36EB,0x0000, /* 1304C */ +0x36EC,0x0000, 0x36ED,0x0000, 0x36EE,0x0000, 0x36EF,0x0000, /* 13050 */ +0x36F0,0x0000, 0x36F1,0x0000, 0x36F2,0x0000, 0x36F3,0x0000, /* 13054 */ +0x36F4,0x0000, 0x36F5,0x0000, 0x36F6,0x0000, 0x36F7,0x0000, /* 13058 */ +0x36F8,0x0000, 0x36F9,0x0000, 0x36FA,0x0000, 0x36FB,0x0000, /* 1305C */ +0x36FC,0x0000, 0x36FD,0x0000, 0x36FE,0x0000, 0x36FF,0x0000, /* 13060 */ +0x3700,0x0000, 0x3701,0x0000, 0x3702,0x0000, 0x3703,0x0000, /* 13064 */ +0x3704,0x0000, 0x3705,0x0000, 0x3706,0x0000, 0x3707,0x0000, /* 13068 */ +0x3708,0x0000, 0x3709,0x0000, 0x370A,0x0000, 0x370B,0x0000, /* 1306C */ +0x370C,0x0000, 0x370D,0x0000, 0x370E,0x0000, 0x370F,0x0000, /* 13070 */ +0x3710,0x0000, 0x3711,0x0000, 0x3712,0x0000, 0x3713,0x0000, /* 13074 */ +0x3714,0x0000, 0x3715,0x0000, 0x3716,0x0000, 0x3717,0x0000, /* 13078 */ +0x3718,0x0000, 0x3719,0x0000, 0x371A,0x0000, 0x371B,0x0000, /* 1307C */ +0x371C,0x0000, 0x371D,0x0000, 0x371E,0x0000, 0x371F,0x0000, /* 13080 */ +0x3720,0x0000, 0x3721,0x0000, 0x3722,0x0000, 0x3723,0x0000, /* 13084 */ +0x3724,0x0000, 0x3725,0x0000, 0x3726,0x0000, 0x3727,0x0000, /* 13088 */ +0x3728,0x0000, 0x3729,0x0000, 0x372A,0x0000, 0x372B,0x0000, /* 1308C */ +0x372C,0x0000, 0x372D,0x0000, 0x372E,0x0000, 0x372F,0x0000, /* 13090 */ +0x3730,0x0000, 0x3731,0x0000, 0x3732,0x0000, 0x3733,0x0000, /* 13094 */ +0x3734,0x0000, 0x3735,0x0000, 0x3736,0x0000, 0x3737,0x0000, /* 13098 */ +0x3738,0x0000, 0x3739,0x0000, 0x373A,0x0000, 0x373B,0x0000, /* 1309C */ +0x373C,0x0000, 0x373D,0x0000, 0x373E,0x0000, 0x373F,0x0000, /* 130A0 */ +0x3740,0x0000, 0x3741,0x0000, 0x3742,0x0000, 0x3743,0x0000, /* 130A4 */ +0x3744,0x0000, 0x3745,0x0000, 0x3746,0x0000, 0x3747,0x0000, /* 130A8 */ +0x3748,0x0000, 0x3749,0x0000, 0x374A,0x0000, 0x374B,0x0000, /* 130AC */ +0x374C,0x0000, 0x374D,0x0000, 0x374E,0x0000, 0x374F,0x0000, /* 130B0 */ +0x3750,0x0000, 0x3751,0x0000, 0x3752,0x0000, 0x3753,0x0000, /* 130B4 */ +0x3754,0x0000, 0x3755,0x0000, 0x3756,0x0000, 0x3757,0x0000, /* 130B8 */ +0x3758,0x0000, 0x3759,0x0000, 0x375A,0x0000, 0x375B,0x0000, /* 130BC */ +0x375C,0x0000, 0x375D,0x0000, 0x375E,0x0000, 0x375F,0x0000, /* 130C0 */ +0x3760,0x0000, 0x3761,0x0000, 0x3762,0x0000, 0x3763,0x0000, /* 130C4 */ +0x3764,0x0000, 0x3765,0x0000, 0x3766,0x0000, 0x3767,0x0000, /* 130C8 */ +0x3768,0x0000, 0x3769,0x0000, 0x376A,0x0000, 0x376B,0x0000, /* 130CC */ +0x376C,0x0000, 0x376D,0x0000, 0x376E,0x0000, 0x376F,0x0000, /* 130D0 */ +0x3770,0x0000, 0x3771,0x0000, 0x3772,0x0000, 0x3773,0x0000, /* 130D4 */ +0x3774,0x0000, 0x3775,0x0000, 0x3776,0x0000, 0x3777,0x0000, /* 130D8 */ +0x3778,0x0000, 0x3779,0x0000, 0x377A,0x0000, 0x377B,0x0000, /* 130DC */ +0x377C,0x0000, 0x377D,0x0000, 0x377E,0x0000, 0x377F,0x0000, /* 130E0 */ +0x3780,0x0000, 0x3781,0x0000, 0x3782,0x0000, 0x3783,0x0000, /* 130E4 */ +0x3784,0x0000, 0x3785,0x0000, 0x3786,0x0000, 0x3787,0x0000, /* 130E8 */ +0x3788,0x0000, 0x3789,0x0000, 0x378A,0x0000, 0x378B,0x0000, /* 130EC */ +0x378C,0x0000, 0x378D,0x0000, 0x378E,0x0000, 0x378F,0x0000, /* 130F0 */ +0x3790,0x0000, 0x3791,0x0000, 0x3792,0x0000, 0x3793,0x0000, /* 130F4 */ +0x3794,0x0000, 0x3795,0x0000, 0x3796,0x0000, 0x3797,0x0000, /* 130F8 */ +0x3798,0x0000, 0x3799,0x0000, 0x379A,0x0000, 0x379B,0x0000 /* 130FC */ +}; + +uint16 uca520_p131[]= { /* 13100 (2 weights per char) */ +0x379C,0x0000, 0x379D,0x0000, 0x379E,0x0000, 0x379F,0x0000, /* 13100 */ +0x37A0,0x0000, 0x37A1,0x0000, 0x37A2,0x0000, 0x37A3,0x0000, /* 13104 */ +0x37A4,0x0000, 0x37A5,0x0000, 0x37A6,0x0000, 0x37A7,0x0000, /* 13108 */ +0x37A8,0x0000, 0x37A9,0x0000, 0x37AA,0x0000, 0x37AB,0x0000, /* 1310C */ +0x37AC,0x0000, 0x37AD,0x0000, 0x37AE,0x0000, 0x37AF,0x0000, /* 13110 */ +0x37B0,0x0000, 0x37B1,0x0000, 0x37B2,0x0000, 0x37B3,0x0000, /* 13114 */ +0x37B4,0x0000, 0x37B5,0x0000, 0x37B6,0x0000, 0x37B7,0x0000, /* 13118 */ +0x37B8,0x0000, 0x37B9,0x0000, 0x37BA,0x0000, 0x37BB,0x0000, /* 1311C */ +0x37BC,0x0000, 0x37BD,0x0000, 0x37BE,0x0000, 0x37BF,0x0000, /* 13120 */ +0x37C0,0x0000, 0x37C1,0x0000, 0x37C2,0x0000, 0x37C3,0x0000, /* 13124 */ +0x37C4,0x0000, 0x37C5,0x0000, 0x37C6,0x0000, 0x37C7,0x0000, /* 13128 */ +0x37C8,0x0000, 0x37C9,0x0000, 0x37CA,0x0000, 0x37CB,0x0000, /* 1312C */ +0x37CC,0x0000, 0x37CD,0x0000, 0x37CE,0x0000, 0x37CF,0x0000, /* 13130 */ +0x37D0,0x0000, 0x37D1,0x0000, 0x37D2,0x0000, 0x37D3,0x0000, /* 13134 */ +0x37D4,0x0000, 0x37D5,0x0000, 0x37D6,0x0000, 0x37D7,0x0000, /* 13138 */ +0x37D8,0x0000, 0x37D9,0x0000, 0x37DA,0x0000, 0x37DB,0x0000, /* 1313C */ +0x37DC,0x0000, 0x37DD,0x0000, 0x37DE,0x0000, 0x37DF,0x0000, /* 13140 */ +0x37E0,0x0000, 0x37E1,0x0000, 0x37E2,0x0000, 0x37E3,0x0000, /* 13144 */ +0x37E4,0x0000, 0x37E5,0x0000, 0x37E6,0x0000, 0x37E7,0x0000, /* 13148 */ +0x37E8,0x0000, 0x37E9,0x0000, 0x37EA,0x0000, 0x37EB,0x0000, /* 1314C */ +0x37EC,0x0000, 0x37ED,0x0000, 0x37EE,0x0000, 0x37EF,0x0000, /* 13150 */ +0x37F0,0x0000, 0x37F1,0x0000, 0x37F2,0x0000, 0x37F3,0x0000, /* 13154 */ +0x37F4,0x0000, 0x37F5,0x0000, 0x37F6,0x0000, 0x37F7,0x0000, /* 13158 */ +0x37F8,0x0000, 0x37F9,0x0000, 0x37FA,0x0000, 0x37FB,0x0000, /* 1315C */ +0x37FC,0x0000, 0x37FD,0x0000, 0x37FE,0x0000, 0x37FF,0x0000, /* 13160 */ +0x3800,0x0000, 0x3801,0x0000, 0x3802,0x0000, 0x3803,0x0000, /* 13164 */ +0x3804,0x0000, 0x3805,0x0000, 0x3806,0x0000, 0x3807,0x0000, /* 13168 */ +0x3808,0x0000, 0x3809,0x0000, 0x380A,0x0000, 0x380B,0x0000, /* 1316C */ +0x380C,0x0000, 0x380D,0x0000, 0x380E,0x0000, 0x380F,0x0000, /* 13170 */ +0x3810,0x0000, 0x3811,0x0000, 0x3812,0x0000, 0x3813,0x0000, /* 13174 */ +0x3814,0x0000, 0x3815,0x0000, 0x3816,0x0000, 0x3817,0x0000, /* 13178 */ +0x3818,0x0000, 0x3819,0x0000, 0x381A,0x0000, 0x381B,0x0000, /* 1317C */ +0x381C,0x0000, 0x381D,0x0000, 0x381E,0x0000, 0x381F,0x0000, /* 13180 */ +0x3820,0x0000, 0x3821,0x0000, 0x3822,0x0000, 0x3823,0x0000, /* 13184 */ +0x3824,0x0000, 0x3825,0x0000, 0x3826,0x0000, 0x3827,0x0000, /* 13188 */ +0x3828,0x0000, 0x3829,0x0000, 0x382A,0x0000, 0x382B,0x0000, /* 1318C */ +0x382C,0x0000, 0x382D,0x0000, 0x382E,0x0000, 0x382F,0x0000, /* 13190 */ +0x3830,0x0000, 0x3831,0x0000, 0x3832,0x0000, 0x3833,0x0000, /* 13194 */ +0x3834,0x0000, 0x3835,0x0000, 0x3836,0x0000, 0x3837,0x0000, /* 13198 */ +0x3838,0x0000, 0x3839,0x0000, 0x383A,0x0000, 0x383B,0x0000, /* 1319C */ +0x383C,0x0000, 0x383D,0x0000, 0x383E,0x0000, 0x383F,0x0000, /* 131A0 */ +0x3840,0x0000, 0x3841,0x0000, 0x3842,0x0000, 0x3843,0x0000, /* 131A4 */ +0x3844,0x0000, 0x3845,0x0000, 0x3846,0x0000, 0x3847,0x0000, /* 131A8 */ +0x3848,0x0000, 0x3849,0x0000, 0x384A,0x0000, 0x384B,0x0000, /* 131AC */ +0x384C,0x0000, 0x384D,0x0000, 0x384E,0x0000, 0x384F,0x0000, /* 131B0 */ +0x3850,0x0000, 0x3851,0x0000, 0x3852,0x0000, 0x3853,0x0000, /* 131B4 */ +0x3854,0x0000, 0x3855,0x0000, 0x3856,0x0000, 0x3857,0x0000, /* 131B8 */ +0x3858,0x0000, 0x3859,0x0000, 0x385A,0x0000, 0x385B,0x0000, /* 131BC */ +0x385C,0x0000, 0x385D,0x0000, 0x385E,0x0000, 0x385F,0x0000, /* 131C0 */ +0x3860,0x0000, 0x3861,0x0000, 0x3862,0x0000, 0x3863,0x0000, /* 131C4 */ +0x3864,0x0000, 0x3865,0x0000, 0x3866,0x0000, 0x3867,0x0000, /* 131C8 */ +0x3868,0x0000, 0x3869,0x0000, 0x386A,0x0000, 0x386B,0x0000, /* 131CC */ +0x386C,0x0000, 0x386D,0x0000, 0x386E,0x0000, 0x386F,0x0000, /* 131D0 */ +0x3870,0x0000, 0x3871,0x0000, 0x3872,0x0000, 0x3873,0x0000, /* 131D4 */ +0x3874,0x0000, 0x3875,0x0000, 0x3876,0x0000, 0x3877,0x0000, /* 131D8 */ +0x3878,0x0000, 0x3879,0x0000, 0x387A,0x0000, 0x387B,0x0000, /* 131DC */ +0x387C,0x0000, 0x387D,0x0000, 0x387E,0x0000, 0x387F,0x0000, /* 131E0 */ +0x3880,0x0000, 0x3881,0x0000, 0x3882,0x0000, 0x3883,0x0000, /* 131E4 */ +0x3884,0x0000, 0x3885,0x0000, 0x3886,0x0000, 0x3887,0x0000, /* 131E8 */ +0x3888,0x0000, 0x3889,0x0000, 0x388A,0x0000, 0x388B,0x0000, /* 131EC */ +0x388C,0x0000, 0x388D,0x0000, 0x388E,0x0000, 0x388F,0x0000, /* 131F0 */ +0x3890,0x0000, 0x3891,0x0000, 0x3892,0x0000, 0x3893,0x0000, /* 131F4 */ +0x3894,0x0000, 0x3895,0x0000, 0x3896,0x0000, 0x3897,0x0000, /* 131F8 */ +0x3898,0x0000, 0x3899,0x0000, 0x389A,0x0000, 0x389B,0x0000 /* 131FC */ +}; + +uint16 uca520_p132[]= { /* 13200 (2 weights per char) */ +0x389C,0x0000, 0x389D,0x0000, 0x389E,0x0000, 0x389F,0x0000, /* 13200 */ +0x38A0,0x0000, 0x38A1,0x0000, 0x38A2,0x0000, 0x38A3,0x0000, /* 13204 */ +0x38A4,0x0000, 0x38A5,0x0000, 0x38A6,0x0000, 0x38A7,0x0000, /* 13208 */ +0x38A8,0x0000, 0x38A9,0x0000, 0x38AA,0x0000, 0x38AB,0x0000, /* 1320C */ +0x38AC,0x0000, 0x38AD,0x0000, 0x38AE,0x0000, 0x38AF,0x0000, /* 13210 */ +0x38B0,0x0000, 0x38B1,0x0000, 0x38B2,0x0000, 0x38B3,0x0000, /* 13214 */ +0x38B4,0x0000, 0x38B5,0x0000, 0x38B6,0x0000, 0x38B7,0x0000, /* 13218 */ +0x38B8,0x0000, 0x38B9,0x0000, 0x38BA,0x0000, 0x38BB,0x0000, /* 1321C */ +0x38BC,0x0000, 0x38BD,0x0000, 0x38BE,0x0000, 0x38BF,0x0000, /* 13220 */ +0x38C0,0x0000, 0x38C1,0x0000, 0x38C2,0x0000, 0x38C3,0x0000, /* 13224 */ +0x38C4,0x0000, 0x38C5,0x0000, 0x38C6,0x0000, 0x38C7,0x0000, /* 13228 */ +0x38C8,0x0000, 0x38C9,0x0000, 0x38CA,0x0000, 0x38CB,0x0000, /* 1322C */ +0x38CC,0x0000, 0x38CD,0x0000, 0x38CE,0x0000, 0x38CF,0x0000, /* 13230 */ +0x38D0,0x0000, 0x38D1,0x0000, 0x38D2,0x0000, 0x38D3,0x0000, /* 13234 */ +0x38D4,0x0000, 0x38D5,0x0000, 0x38D6,0x0000, 0x38D7,0x0000, /* 13238 */ +0x38D8,0x0000, 0x38D9,0x0000, 0x38DA,0x0000, 0x38DB,0x0000, /* 1323C */ +0x38DC,0x0000, 0x38DD,0x0000, 0x38DE,0x0000, 0x38DF,0x0000, /* 13240 */ +0x38E0,0x0000, 0x38E1,0x0000, 0x38E2,0x0000, 0x38E3,0x0000, /* 13244 */ +0x38E4,0x0000, 0x38E5,0x0000, 0x38E6,0x0000, 0x38E7,0x0000, /* 13248 */ +0x38E8,0x0000, 0x38E9,0x0000, 0x38EA,0x0000, 0x38EB,0x0000, /* 1324C */ +0x38EC,0x0000, 0x38ED,0x0000, 0x38EE,0x0000, 0x38EF,0x0000, /* 13250 */ +0x38F0,0x0000, 0x38F1,0x0000, 0x38F2,0x0000, 0x38F3,0x0000, /* 13254 */ +0x38F4,0x0000, 0x38F5,0x0000, 0x38F6,0x0000, 0x38F7,0x0000, /* 13258 */ +0x38F8,0x0000, 0x38F9,0x0000, 0x38FA,0x0000, 0x38FB,0x0000, /* 1325C */ +0x38FC,0x0000, 0x38FD,0x0000, 0x38FE,0x0000, 0x38FF,0x0000, /* 13260 */ +0x3900,0x0000, 0x3901,0x0000, 0x3902,0x0000, 0x3903,0x0000, /* 13264 */ +0x3904,0x0000, 0x3905,0x0000, 0x3906,0x0000, 0x3907,0x0000, /* 13268 */ +0x3908,0x0000, 0x3909,0x0000, 0x390A,0x0000, 0x390B,0x0000, /* 1326C */ +0x390C,0x0000, 0x390D,0x0000, 0x390E,0x0000, 0x390F,0x0000, /* 13270 */ +0x3910,0x0000, 0x3911,0x0000, 0x3912,0x0000, 0x3913,0x0000, /* 13274 */ +0x3914,0x0000, 0x3915,0x0000, 0x3916,0x0000, 0x3917,0x0000, /* 13278 */ +0x3918,0x0000, 0x3919,0x0000, 0x391A,0x0000, 0x391B,0x0000, /* 1327C */ +0x391C,0x0000, 0x391D,0x0000, 0x391E,0x0000, 0x391F,0x0000, /* 13280 */ +0x3920,0x0000, 0x3921,0x0000, 0x3922,0x0000, 0x3923,0x0000, /* 13284 */ +0x3924,0x0000, 0x3925,0x0000, 0x3926,0x0000, 0x3927,0x0000, /* 13288 */ +0x3928,0x0000, 0x3929,0x0000, 0x392A,0x0000, 0x392B,0x0000, /* 1328C */ +0x392C,0x0000, 0x392D,0x0000, 0x392E,0x0000, 0x392F,0x0000, /* 13290 */ +0x3930,0x0000, 0x3931,0x0000, 0x3932,0x0000, 0x3933,0x0000, /* 13294 */ +0x3934,0x0000, 0x3935,0x0000, 0x3936,0x0000, 0x3937,0x0000, /* 13298 */ +0x3938,0x0000, 0x3939,0x0000, 0x393A,0x0000, 0x393B,0x0000, /* 1329C */ +0x393C,0x0000, 0x393D,0x0000, 0x393E,0x0000, 0x393F,0x0000, /* 132A0 */ +0x3940,0x0000, 0x3941,0x0000, 0x3942,0x0000, 0x3943,0x0000, /* 132A4 */ +0x3944,0x0000, 0x3945,0x0000, 0x3946,0x0000, 0x3947,0x0000, /* 132A8 */ +0x3948,0x0000, 0x3949,0x0000, 0x394A,0x0000, 0x394B,0x0000, /* 132AC */ +0x394C,0x0000, 0x394D,0x0000, 0x394E,0x0000, 0x394F,0x0000, /* 132B0 */ +0x3950,0x0000, 0x3951,0x0000, 0x3952,0x0000, 0x3953,0x0000, /* 132B4 */ +0x3954,0x0000, 0x3955,0x0000, 0x3956,0x0000, 0x3957,0x0000, /* 132B8 */ +0x3958,0x0000, 0x3959,0x0000, 0x395A,0x0000, 0x395B,0x0000, /* 132BC */ +0x395C,0x0000, 0x395D,0x0000, 0x395E,0x0000, 0x395F,0x0000, /* 132C0 */ +0x3960,0x0000, 0x3961,0x0000, 0x3962,0x0000, 0x3963,0x0000, /* 132C4 */ +0x3964,0x0000, 0x3965,0x0000, 0x3966,0x0000, 0x3967,0x0000, /* 132C8 */ +0x3968,0x0000, 0x3969,0x0000, 0x396A,0x0000, 0x396B,0x0000, /* 132CC */ +0x396C,0x0000, 0x396D,0x0000, 0x396E,0x0000, 0x396F,0x0000, /* 132D0 */ +0x3970,0x0000, 0x3971,0x0000, 0x3972,0x0000, 0x3973,0x0000, /* 132D4 */ +0x3974,0x0000, 0x3975,0x0000, 0x3976,0x0000, 0x3977,0x0000, /* 132D8 */ +0x3978,0x0000, 0x3979,0x0000, 0x397A,0x0000, 0x397B,0x0000, /* 132DC */ +0x397C,0x0000, 0x397D,0x0000, 0x397E,0x0000, 0x397F,0x0000, /* 132E0 */ +0x3980,0x0000, 0x3981,0x0000, 0x3982,0x0000, 0x3983,0x0000, /* 132E4 */ +0x3984,0x0000, 0x3985,0x0000, 0x3986,0x0000, 0x3987,0x0000, /* 132E8 */ +0x3988,0x0000, 0x3989,0x0000, 0x398A,0x0000, 0x398B,0x0000, /* 132EC */ +0x398C,0x0000, 0x398D,0x0000, 0x398E,0x0000, 0x398F,0x0000, /* 132F0 */ +0x3990,0x0000, 0x3991,0x0000, 0x3992,0x0000, 0x3993,0x0000, /* 132F4 */ +0x3994,0x0000, 0x3995,0x0000, 0x3996,0x0000, 0x3997,0x0000, /* 132F8 */ +0x3998,0x0000, 0x3999,0x0000, 0x399A,0x0000, 0x399B,0x0000 /* 132FC */ +}; + +uint16 uca520_p133[]= { /* 13300 (2 weights per char) */ +0x399C,0x0000, 0x399D,0x0000, 0x399E,0x0000, 0x399F,0x0000, /* 13300 */ +0x39A0,0x0000, 0x39A1,0x0000, 0x39A2,0x0000, 0x39A3,0x0000, /* 13304 */ +0x39A4,0x0000, 0x39A5,0x0000, 0x39A6,0x0000, 0x39A7,0x0000, /* 13308 */ +0x39A8,0x0000, 0x39A9,0x0000, 0x39AA,0x0000, 0x39AB,0x0000, /* 1330C */ +0x39AC,0x0000, 0x39AD,0x0000, 0x39AE,0x0000, 0x39AF,0x0000, /* 13310 */ +0x39B0,0x0000, 0x39B1,0x0000, 0x39B2,0x0000, 0x39B3,0x0000, /* 13314 */ +0x39B4,0x0000, 0x39B5,0x0000, 0x39B6,0x0000, 0x39B7,0x0000, /* 13318 */ +0x39B8,0x0000, 0x39B9,0x0000, 0x39BA,0x0000, 0x39BB,0x0000, /* 1331C */ +0x39BC,0x0000, 0x39BD,0x0000, 0x39BE,0x0000, 0x39BF,0x0000, /* 13320 */ +0x39C0,0x0000, 0x39C1,0x0000, 0x39C2,0x0000, 0x39C3,0x0000, /* 13324 */ +0x39C4,0x0000, 0x39C5,0x0000, 0x39C6,0x0000, 0x39C7,0x0000, /* 13328 */ +0x39C8,0x0000, 0x39C9,0x0000, 0x39CA,0x0000, 0x39CB,0x0000, /* 1332C */ +0x39CC,0x0000, 0x39CD,0x0000, 0x39CE,0x0000, 0x39CF,0x0000, /* 13330 */ +0x39D0,0x0000, 0x39D1,0x0000, 0x39D2,0x0000, 0x39D3,0x0000, /* 13334 */ +0x39D4,0x0000, 0x39D5,0x0000, 0x39D6,0x0000, 0x39D7,0x0000, /* 13338 */ +0x39D8,0x0000, 0x39D9,0x0000, 0x39DA,0x0000, 0x39DB,0x0000, /* 1333C */ +0x39DC,0x0000, 0x39DD,0x0000, 0x39DE,0x0000, 0x39DF,0x0000, /* 13340 */ +0x39E0,0x0000, 0x39E1,0x0000, 0x39E2,0x0000, 0x39E3,0x0000, /* 13344 */ +0x39E4,0x0000, 0x39E5,0x0000, 0x39E6,0x0000, 0x39E7,0x0000, /* 13348 */ +0x39E8,0x0000, 0x39E9,0x0000, 0x39EA,0x0000, 0x39EB,0x0000, /* 1334C */ +0x39EC,0x0000, 0x39ED,0x0000, 0x39EE,0x0000, 0x39EF,0x0000, /* 13350 */ +0x39F0,0x0000, 0x39F1,0x0000, 0x39F2,0x0000, 0x39F3,0x0000, /* 13354 */ +0x39F4,0x0000, 0x39F5,0x0000, 0x39F6,0x0000, 0x39F7,0x0000, /* 13358 */ +0x39F8,0x0000, 0x39F9,0x0000, 0x39FA,0x0000, 0x39FB,0x0000, /* 1335C */ +0x39FC,0x0000, 0x39FD,0x0000, 0x39FE,0x0000, 0x39FF,0x0000, /* 13360 */ +0x3A00,0x0000, 0x3A01,0x0000, 0x3A02,0x0000, 0x3A03,0x0000, /* 13364 */ +0x3A04,0x0000, 0x3A05,0x0000, 0x3A06,0x0000, 0x3A07,0x0000, /* 13368 */ +0x3A08,0x0000, 0x3A09,0x0000, 0x3A0A,0x0000, 0x3A0B,0x0000, /* 1336C */ +0x3A0C,0x0000, 0x3A0D,0x0000, 0x3A0E,0x0000, 0x3A0F,0x0000, /* 13370 */ +0x3A10,0x0000, 0x3A11,0x0000, 0x3A12,0x0000, 0x3A13,0x0000, /* 13374 */ +0x3A14,0x0000, 0x3A15,0x0000, 0x3A16,0x0000, 0x3A17,0x0000, /* 13378 */ +0x3A18,0x0000, 0x3A19,0x0000, 0x3A1A,0x0000, 0x3A1B,0x0000, /* 1337C */ +0x3A1C,0x0000, 0x3A1D,0x0000, 0x3A1E,0x0000, 0x3A1F,0x0000, /* 13380 */ +0x3A20,0x0000, 0x3A21,0x0000, 0x3A22,0x0000, 0x3A23,0x0000, /* 13384 */ +0x3A24,0x0000, 0x3A25,0x0000, 0x3A26,0x0000, 0x3A27,0x0000, /* 13388 */ +0x3A28,0x0000, 0x3A29,0x0000, 0x3A2A,0x0000, 0x3A2B,0x0000, /* 1338C */ +0x3A2C,0x0000, 0x3A2D,0x0000, 0x3A2E,0x0000, 0x3A2F,0x0000, /* 13390 */ +0x3A30,0x0000, 0x3A31,0x0000, 0x3A32,0x0000, 0x3A33,0x0000, /* 13394 */ +0x3A34,0x0000, 0x3A35,0x0000, 0x3A36,0x0000, 0x3A37,0x0000, /* 13398 */ +0x3A38,0x0000, 0x3A39,0x0000, 0x3A3A,0x0000, 0x3A3B,0x0000, /* 1339C */ +0x3A3C,0x0000, 0x3A3D,0x0000, 0x3A3E,0x0000, 0x3A3F,0x0000, /* 133A0 */ +0x3A40,0x0000, 0x3A41,0x0000, 0x3A42,0x0000, 0x3A43,0x0000, /* 133A4 */ +0x3A44,0x0000, 0x3A45,0x0000, 0x3A46,0x0000, 0x3A47,0x0000, /* 133A8 */ +0x3A48,0x0000, 0x3A49,0x0000, 0x3A4A,0x0000, 0x3A4B,0x0000, /* 133AC */ +0x3A4C,0x0000, 0x3A4D,0x0000, 0x3A4E,0x0000, 0x3A4F,0x0000, /* 133B0 */ +0x3A50,0x0000, 0x3A51,0x0000, 0x3A52,0x0000, 0x3A53,0x0000, /* 133B4 */ +0x3A54,0x0000, 0x3A55,0x0000, 0x3A56,0x0000, 0x3A57,0x0000, /* 133B8 */ +0x3A58,0x0000, 0x3A59,0x0000, 0x3A5A,0x0000, 0x3A5B,0x0000, /* 133BC */ +0x3A5C,0x0000, 0x3A5D,0x0000, 0x3A5E,0x0000, 0x3A5F,0x0000, /* 133C0 */ +0x3A60,0x0000, 0x3A61,0x0000, 0x3A62,0x0000, 0x3A63,0x0000, /* 133C4 */ +0x3A64,0x0000, 0x3A65,0x0000, 0x3A66,0x0000, 0x3A67,0x0000, /* 133C8 */ +0x3A68,0x0000, 0x3A69,0x0000, 0x3A6A,0x0000, 0x3A6B,0x0000, /* 133CC */ +0x3A6C,0x0000, 0x3A6D,0x0000, 0x3A6E,0x0000, 0x3A6F,0x0000, /* 133D0 */ +0x3A70,0x0000, 0x3A71,0x0000, 0x3A72,0x0000, 0x3A73,0x0000, /* 133D4 */ +0x3A74,0x0000, 0x3A75,0x0000, 0x3A76,0x0000, 0x3A77,0x0000, /* 133D8 */ +0x3A78,0x0000, 0x3A79,0x0000, 0x3A7A,0x0000, 0x3A7B,0x0000, /* 133DC */ +0x3A7C,0x0000, 0x3A7D,0x0000, 0x3A7E,0x0000, 0x3A7F,0x0000, /* 133E0 */ +0x3A80,0x0000, 0x3A81,0x0000, 0x3A82,0x0000, 0x3A83,0x0000, /* 133E4 */ +0x3A84,0x0000, 0x3A85,0x0000, 0x3A86,0x0000, 0x3A87,0x0000, /* 133E8 */ +0x3A88,0x0000, 0x3A89,0x0000, 0x3A8A,0x0000, 0x3A8B,0x0000, /* 133EC */ +0x3A8C,0x0000, 0x3A8D,0x0000, 0x3A8E,0x0000, 0x3A8F,0x0000, /* 133F0 */ +0x3A90,0x0000, 0x3A91,0x0000, 0x3A92,0x0000, 0x3A93,0x0000, /* 133F4 */ +0x3A94,0x0000, 0x3A95,0x0000, 0x3A96,0x0000, 0x3A97,0x0000, /* 133F8 */ +0x3A98,0x0000, 0x3A99,0x0000, 0x3A9A,0x0000, 0x3A9B,0x0000 /* 133FC */ +}; + +uint16 uca520_p134[]= { /* 13400 (3 weights per char) */ +0x3A9C,0x0000,0x0000, 0x3A9D,0x0000,0x0000, 0x3A9E,0x0000,0x0000, /* 13400 */ +0x3A9F,0x0000,0x0000, 0x3AA0,0x0000,0x0000, 0x3AA1,0x0000,0x0000, /* 13403 */ +0x3AA2,0x0000,0x0000, 0x3AA3,0x0000,0x0000, 0x3AA4,0x0000,0x0000, /* 13406 */ +0x3AA5,0x0000,0x0000, 0x3AA6,0x0000,0x0000, 0x3AA7,0x0000,0x0000, /* 13409 */ +0x3AA8,0x0000,0x0000, 0x3AA9,0x0000,0x0000, 0x3AAA,0x0000,0x0000, /* 1340C */ +0x3AAB,0x0000,0x0000, 0x3AAC,0x0000,0x0000, 0x3AAD,0x0000,0x0000, /* 1340F */ +0x3AAE,0x0000,0x0000, 0x3AAF,0x0000,0x0000, 0x3AB0,0x0000,0x0000, /* 13412 */ +0x3AB1,0x0000,0x0000, 0x3AB2,0x0000,0x0000, 0x3AB3,0x0000,0x0000, /* 13415 */ +0x3AB4,0x0000,0x0000, 0x3AB5,0x0000,0x0000, 0x3AB6,0x0000,0x0000, /* 13418 */ +0x3AB7,0x0000,0x0000, 0x3AB8,0x0000,0x0000, 0x3AB9,0x0000,0x0000, /* 1341B */ +0x3ABA,0x0000,0x0000, 0x3ABB,0x0000,0x0000, 0x3ABC,0x0000,0x0000, /* 1341E */ +0x3ABD,0x0000,0x0000, 0x3ABE,0x0000,0x0000, 0x3ABF,0x0000,0x0000, /* 13421 */ +0x3AC0,0x0000,0x0000, 0x3AC1,0x0000,0x0000, 0x3AC2,0x0000,0x0000, /* 13424 */ +0x3AC3,0x0000,0x0000, 0x3AC4,0x0000,0x0000, 0x3AC5,0x0000,0x0000, /* 13427 */ +0x3AC6,0x0000,0x0000, 0x3AC7,0x0000,0x0000, 0x3AC8,0x0000,0x0000, /* 1342A */ +0x3AC9,0x0000,0x0000, 0x3ACA,0x0000,0x0000, 0xFBC2,0xB42F,0x0000, /* 1342D */ +0xFBC2,0xB430,0x0000, 0xFBC2,0xB431,0x0000, 0xFBC2,0xB432,0x0000, /* 13430 */ +0xFBC2,0xB433,0x0000, 0xFBC2,0xB434,0x0000, 0xFBC2,0xB435,0x0000, /* 13433 */ +0xFBC2,0xB436,0x0000, 0xFBC2,0xB437,0x0000, 0xFBC2,0xB438,0x0000, /* 13436 */ +0xFBC2,0xB439,0x0000, 0xFBC2,0xB43A,0x0000, 0xFBC2,0xB43B,0x0000, /* 13439 */ +0xFBC2,0xB43C,0x0000, 0xFBC2,0xB43D,0x0000, 0xFBC2,0xB43E,0x0000, /* 1343C */ +0xFBC2,0xB43F,0x0000, 0xFBC2,0xB440,0x0000, 0xFBC2,0xB441,0x0000, /* 1343F */ +0xFBC2,0xB442,0x0000, 0xFBC2,0xB443,0x0000, 0xFBC2,0xB444,0x0000, /* 13442 */ +0xFBC2,0xB445,0x0000, 0xFBC2,0xB446,0x0000, 0xFBC2,0xB447,0x0000, /* 13445 */ +0xFBC2,0xB448,0x0000, 0xFBC2,0xB449,0x0000, 0xFBC2,0xB44A,0x0000, /* 13448 */ +0xFBC2,0xB44B,0x0000, 0xFBC2,0xB44C,0x0000, 0xFBC2,0xB44D,0x0000, /* 1344B */ +0xFBC2,0xB44E,0x0000, 0xFBC2,0xB44F,0x0000, 0xFBC2,0xB450,0x0000, /* 1344E */ +0xFBC2,0xB451,0x0000, 0xFBC2,0xB452,0x0000, 0xFBC2,0xB453,0x0000, /* 13451 */ +0xFBC2,0xB454,0x0000, 0xFBC2,0xB455,0x0000, 0xFBC2,0xB456,0x0000, /* 13454 */ +0xFBC2,0xB457,0x0000, 0xFBC2,0xB458,0x0000, 0xFBC2,0xB459,0x0000, /* 13457 */ +0xFBC2,0xB45A,0x0000, 0xFBC2,0xB45B,0x0000, 0xFBC2,0xB45C,0x0000, /* 1345A */ +0xFBC2,0xB45D,0x0000, 0xFBC2,0xB45E,0x0000, 0xFBC2,0xB45F,0x0000, /* 1345D */ +0xFBC2,0xB460,0x0000, 0xFBC2,0xB461,0x0000, 0xFBC2,0xB462,0x0000, /* 13460 */ +0xFBC2,0xB463,0x0000, 0xFBC2,0xB464,0x0000, 0xFBC2,0xB465,0x0000, /* 13463 */ +0xFBC2,0xB466,0x0000, 0xFBC2,0xB467,0x0000, 0xFBC2,0xB468,0x0000, /* 13466 */ +0xFBC2,0xB469,0x0000, 0xFBC2,0xB46A,0x0000, 0xFBC2,0xB46B,0x0000, /* 13469 */ +0xFBC2,0xB46C,0x0000, 0xFBC2,0xB46D,0x0000, 0xFBC2,0xB46E,0x0000, /* 1346C */ +0xFBC2,0xB46F,0x0000, 0xFBC2,0xB470,0x0000, 0xFBC2,0xB471,0x0000, /* 1346F */ +0xFBC2,0xB472,0x0000, 0xFBC2,0xB473,0x0000, 0xFBC2,0xB474,0x0000, /* 13472 */ +0xFBC2,0xB475,0x0000, 0xFBC2,0xB476,0x0000, 0xFBC2,0xB477,0x0000, /* 13475 */ +0xFBC2,0xB478,0x0000, 0xFBC2,0xB479,0x0000, 0xFBC2,0xB47A,0x0000, /* 13478 */ +0xFBC2,0xB47B,0x0000, 0xFBC2,0xB47C,0x0000, 0xFBC2,0xB47D,0x0000, /* 1347B */ +0xFBC2,0xB47E,0x0000, 0xFBC2,0xB47F,0x0000, 0xFBC2,0xB480,0x0000, /* 1347E */ +0xFBC2,0xB481,0x0000, 0xFBC2,0xB482,0x0000, 0xFBC2,0xB483,0x0000, /* 13481 */ +0xFBC2,0xB484,0x0000, 0xFBC2,0xB485,0x0000, 0xFBC2,0xB486,0x0000, /* 13484 */ +0xFBC2,0xB487,0x0000, 0xFBC2,0xB488,0x0000, 0xFBC2,0xB489,0x0000, /* 13487 */ +0xFBC2,0xB48A,0x0000, 0xFBC2,0xB48B,0x0000, 0xFBC2,0xB48C,0x0000, /* 1348A */ +0xFBC2,0xB48D,0x0000, 0xFBC2,0xB48E,0x0000, 0xFBC2,0xB48F,0x0000, /* 1348D */ +0xFBC2,0xB490,0x0000, 0xFBC2,0xB491,0x0000, 0xFBC2,0xB492,0x0000, /* 13490 */ +0xFBC2,0xB493,0x0000, 0xFBC2,0xB494,0x0000, 0xFBC2,0xB495,0x0000, /* 13493 */ +0xFBC2,0xB496,0x0000, 0xFBC2,0xB497,0x0000, 0xFBC2,0xB498,0x0000, /* 13496 */ +0xFBC2,0xB499,0x0000, 0xFBC2,0xB49A,0x0000, 0xFBC2,0xB49B,0x0000, /* 13499 */ +0xFBC2,0xB49C,0x0000, 0xFBC2,0xB49D,0x0000, 0xFBC2,0xB49E,0x0000, /* 1349C */ +0xFBC2,0xB49F,0x0000, 0xFBC2,0xB4A0,0x0000, 0xFBC2,0xB4A1,0x0000, /* 1349F */ +0xFBC2,0xB4A2,0x0000, 0xFBC2,0xB4A3,0x0000, 0xFBC2,0xB4A4,0x0000, /* 134A2 */ +0xFBC2,0xB4A5,0x0000, 0xFBC2,0xB4A6,0x0000, 0xFBC2,0xB4A7,0x0000, /* 134A5 */ +0xFBC2,0xB4A8,0x0000, 0xFBC2,0xB4A9,0x0000, 0xFBC2,0xB4AA,0x0000, /* 134A8 */ +0xFBC2,0xB4AB,0x0000, 0xFBC2,0xB4AC,0x0000, 0xFBC2,0xB4AD,0x0000, /* 134AB */ +0xFBC2,0xB4AE,0x0000, 0xFBC2,0xB4AF,0x0000, 0xFBC2,0xB4B0,0x0000, /* 134AE */ +0xFBC2,0xB4B1,0x0000, 0xFBC2,0xB4B2,0x0000, 0xFBC2,0xB4B3,0x0000, /* 134B1 */ +0xFBC2,0xB4B4,0x0000, 0xFBC2,0xB4B5,0x0000, 0xFBC2,0xB4B6,0x0000, /* 134B4 */ +0xFBC2,0xB4B7,0x0000, 0xFBC2,0xB4B8,0x0000, 0xFBC2,0xB4B9,0x0000, /* 134B7 */ +0xFBC2,0xB4BA,0x0000, 0xFBC2,0xB4BB,0x0000, 0xFBC2,0xB4BC,0x0000, /* 134BA */ +0xFBC2,0xB4BD,0x0000, 0xFBC2,0xB4BE,0x0000, 0xFBC2,0xB4BF,0x0000, /* 134BD */ +0xFBC2,0xB4C0,0x0000, 0xFBC2,0xB4C1,0x0000, 0xFBC2,0xB4C2,0x0000, /* 134C0 */ +0xFBC2,0xB4C3,0x0000, 0xFBC2,0xB4C4,0x0000, 0xFBC2,0xB4C5,0x0000, /* 134C3 */ +0xFBC2,0xB4C6,0x0000, 0xFBC2,0xB4C7,0x0000, 0xFBC2,0xB4C8,0x0000, /* 134C6 */ +0xFBC2,0xB4C9,0x0000, 0xFBC2,0xB4CA,0x0000, 0xFBC2,0xB4CB,0x0000, /* 134C9 */ +0xFBC2,0xB4CC,0x0000, 0xFBC2,0xB4CD,0x0000, 0xFBC2,0xB4CE,0x0000, /* 134CC */ +0xFBC2,0xB4CF,0x0000, 0xFBC2,0xB4D0,0x0000, 0xFBC2,0xB4D1,0x0000, /* 134CF */ +0xFBC2,0xB4D2,0x0000, 0xFBC2,0xB4D3,0x0000, 0xFBC2,0xB4D4,0x0000, /* 134D2 */ +0xFBC2,0xB4D5,0x0000, 0xFBC2,0xB4D6,0x0000, 0xFBC2,0xB4D7,0x0000, /* 134D5 */ +0xFBC2,0xB4D8,0x0000, 0xFBC2,0xB4D9,0x0000, 0xFBC2,0xB4DA,0x0000, /* 134D8 */ +0xFBC2,0xB4DB,0x0000, 0xFBC2,0xB4DC,0x0000, 0xFBC2,0xB4DD,0x0000, /* 134DB */ +0xFBC2,0xB4DE,0x0000, 0xFBC2,0xB4DF,0x0000, 0xFBC2,0xB4E0,0x0000, /* 134DE */ +0xFBC2,0xB4E1,0x0000, 0xFBC2,0xB4E2,0x0000, 0xFBC2,0xB4E3,0x0000, /* 134E1 */ +0xFBC2,0xB4E4,0x0000, 0xFBC2,0xB4E5,0x0000, 0xFBC2,0xB4E6,0x0000, /* 134E4 */ +0xFBC2,0xB4E7,0x0000, 0xFBC2,0xB4E8,0x0000, 0xFBC2,0xB4E9,0x0000, /* 134E7 */ +0xFBC2,0xB4EA,0x0000, 0xFBC2,0xB4EB,0x0000, 0xFBC2,0xB4EC,0x0000, /* 134EA */ +0xFBC2,0xB4ED,0x0000, 0xFBC2,0xB4EE,0x0000, 0xFBC2,0xB4EF,0x0000, /* 134ED */ +0xFBC2,0xB4F0,0x0000, 0xFBC2,0xB4F1,0x0000, 0xFBC2,0xB4F2,0x0000, /* 134F0 */ +0xFBC2,0xB4F3,0x0000, 0xFBC2,0xB4F4,0x0000, 0xFBC2,0xB4F5,0x0000, /* 134F3 */ +0xFBC2,0xB4F6,0x0000, 0xFBC2,0xB4F7,0x0000, 0xFBC2,0xB4F8,0x0000, /* 134F6 */ +0xFBC2,0xB4F9,0x0000, 0xFBC2,0xB4FA,0x0000, 0xFBC2,0xB4FB,0x0000, /* 134F9 */ +0xFBC2,0xB4FC,0x0000, 0xFBC2,0xB4FD,0x0000, 0xFBC2,0xB4FE,0x0000, /* 134FC */ +0xFBC2,0xB4FF,0x0000 }; + +uint16 uca520_p1D0[]= { /* 1D000 (3 weights per char) */ +0x0E5F,0x0000,0x0000, 0x0E60,0x0000,0x0000, 0x0E61,0x0000,0x0000, /* 1D000 */ +0x0E62,0x0000,0x0000, 0x0E63,0x0000,0x0000, 0x0E64,0x0000,0x0000, /* 1D003 */ +0x0E65,0x0000,0x0000, 0x0E66,0x0000,0x0000, 0x0E67,0x0000,0x0000, /* 1D006 */ +0x0E68,0x0000,0x0000, 0x0E69,0x0000,0x0000, 0x0E6A,0x0000,0x0000, /* 1D009 */ +0x0E6B,0x0000,0x0000, 0x0E6C,0x0000,0x0000, 0x0E6D,0x0000,0x0000, /* 1D00C */ +0x0E6E,0x0000,0x0000, 0x0E6F,0x0000,0x0000, 0x0E70,0x0000,0x0000, /* 1D00F */ +0x0E71,0x0000,0x0000, 0x0E72,0x0000,0x0000, 0x0E73,0x0000,0x0000, /* 1D012 */ +0x0E74,0x0000,0x0000, 0x0E75,0x0000,0x0000, 0x0E76,0x0000,0x0000, /* 1D015 */ +0x0E77,0x0000,0x0000, 0x0E78,0x0000,0x0000, 0x0E79,0x0000,0x0000, /* 1D018 */ +0x0E7A,0x0000,0x0000, 0x0E7B,0x0000,0x0000, 0x0E7C,0x0000,0x0000, /* 1D01B */ +0x0E7D,0x0000,0x0000, 0x0E7E,0x0000,0x0000, 0x0E7F,0x0000,0x0000, /* 1D01E */ +0x0E80,0x0000,0x0000, 0x0E81,0x0000,0x0000, 0x0E82,0x0000,0x0000, /* 1D021 */ +0x0E83,0x0000,0x0000, 0x0E84,0x0000,0x0000, 0x0E85,0x0000,0x0000, /* 1D024 */ +0x0E86,0x0000,0x0000, 0x0E87,0x0000,0x0000, 0x0E88,0x0000,0x0000, /* 1D027 */ +0x0E89,0x0000,0x0000, 0x0E8A,0x0000,0x0000, 0x0E8B,0x0000,0x0000, /* 1D02A */ +0x0E8C,0x0000,0x0000, 0x0E8D,0x0000,0x0000, 0x0E8E,0x0000,0x0000, /* 1D02D */ +0x0E8F,0x0000,0x0000, 0x0E90,0x0000,0x0000, 0x0E91,0x0000,0x0000, /* 1D030 */ +0x0E92,0x0000,0x0000, 0x0E93,0x0000,0x0000, 0x0E94,0x0000,0x0000, /* 1D033 */ +0x0E95,0x0000,0x0000, 0x0E96,0x0000,0x0000, 0x0E97,0x0000,0x0000, /* 1D036 */ +0x0E98,0x0000,0x0000, 0x0E99,0x0000,0x0000, 0x0E9A,0x0000,0x0000, /* 1D039 */ +0x0E9B,0x0000,0x0000, 0x0E9C,0x0000,0x0000, 0x0E9D,0x0000,0x0000, /* 1D03C */ +0x0E9E,0x0000,0x0000, 0x0E9F,0x0000,0x0000, 0x0EA0,0x0000,0x0000, /* 1D03F */ +0x0EA1,0x0000,0x0000, 0x0EA2,0x0000,0x0000, 0x0EA3,0x0000,0x0000, /* 1D042 */ +0x0EA4,0x0000,0x0000, 0x0EA5,0x0000,0x0000, 0x0EA6,0x0000,0x0000, /* 1D045 */ +0x0EA7,0x0000,0x0000, 0x0EA8,0x0000,0x0000, 0x0EA9,0x0000,0x0000, /* 1D048 */ +0x0EAA,0x0000,0x0000, 0x0EAB,0x0000,0x0000, 0x0EAC,0x0000,0x0000, /* 1D04B */ +0x0EAD,0x0000,0x0000, 0x0EAE,0x0000,0x0000, 0x0EAF,0x0000,0x0000, /* 1D04E */ +0x0EB0,0x0000,0x0000, 0x0EB1,0x0000,0x0000, 0x0EB2,0x0000,0x0000, /* 1D051 */ +0x0EB3,0x0000,0x0000, 0x0EB4,0x0000,0x0000, 0x0EB5,0x0000,0x0000, /* 1D054 */ +0x0EB6,0x0000,0x0000, 0x0EB7,0x0000,0x0000, 0x0EB8,0x0000,0x0000, /* 1D057 */ +0x0EB9,0x0000,0x0000, 0x0EBA,0x0000,0x0000, 0x0EBB,0x0000,0x0000, /* 1D05A */ +0x0EBC,0x0000,0x0000, 0x0EBD,0x0000,0x0000, 0x0EBE,0x0000,0x0000, /* 1D05D */ +0x0EBF,0x0000,0x0000, 0x0EC0,0x0000,0x0000, 0x0EC1,0x0000,0x0000, /* 1D060 */ +0x0EC2,0x0000,0x0000, 0x0EC3,0x0000,0x0000, 0x0EC4,0x0000,0x0000, /* 1D063 */ +0x0EC5,0x0000,0x0000, 0x0EC6,0x0000,0x0000, 0x0EC7,0x0000,0x0000, /* 1D066 */ +0x0EC8,0x0000,0x0000, 0x0EC9,0x0000,0x0000, 0x0ECA,0x0000,0x0000, /* 1D069 */ +0x0ECB,0x0000,0x0000, 0x0ECC,0x0000,0x0000, 0x0ECD,0x0000,0x0000, /* 1D06C */ +0x0ECE,0x0000,0x0000, 0x0ECF,0x0000,0x0000, 0x0ED0,0x0000,0x0000, /* 1D06F */ +0x0ED1,0x0000,0x0000, 0x0ED2,0x0000,0x0000, 0x0ED3,0x0000,0x0000, /* 1D072 */ +0x0ED4,0x0000,0x0000, 0x0ED5,0x0000,0x0000, 0x0ED6,0x0000,0x0000, /* 1D075 */ +0x0ED7,0x0000,0x0000, 0x0ED8,0x0000,0x0000, 0x0ED9,0x0000,0x0000, /* 1D078 */ +0x0EDA,0x0000,0x0000, 0x0EDB,0x0000,0x0000, 0x0EDC,0x0000,0x0000, /* 1D07B */ +0x0EDD,0x0000,0x0000, 0x0EDE,0x0000,0x0000, 0x0EDF,0x0000,0x0000, /* 1D07E */ +0x0EE0,0x0000,0x0000, 0x0EE1,0x0000,0x0000, 0x0EE2,0x0000,0x0000, /* 1D081 */ +0x0EE3,0x0000,0x0000, 0x0EE4,0x0000,0x0000, 0x0EE5,0x0000,0x0000, /* 1D084 */ +0x0EE6,0x0000,0x0000, 0x0EE7,0x0000,0x0000, 0x0EE8,0x0000,0x0000, /* 1D087 */ +0x0EE9,0x0000,0x0000, 0x0EEA,0x0000,0x0000, 0x0EEB,0x0000,0x0000, /* 1D08A */ +0x0EEC,0x0000,0x0000, 0x0EED,0x0000,0x0000, 0x0EEE,0x0000,0x0000, /* 1D08D */ +0x0EEF,0x0000,0x0000, 0x0EF0,0x0000,0x0000, 0x0EF1,0x0000,0x0000, /* 1D090 */ +0x0EF2,0x0000,0x0000, 0x0EF3,0x0000,0x0000, 0x0EF4,0x0000,0x0000, /* 1D093 */ +0x0EF5,0x0000,0x0000, 0x0EF6,0x0000,0x0000, 0x0EF7,0x0000,0x0000, /* 1D096 */ +0x0EF8,0x0000,0x0000, 0x0EF9,0x0000,0x0000, 0x0EFA,0x0000,0x0000, /* 1D099 */ +0x0EFB,0x0000,0x0000, 0x0EFC,0x0000,0x0000, 0x0EFD,0x0000,0x0000, /* 1D09C */ +0x0EFE,0x0000,0x0000, 0x0EFF,0x0000,0x0000, 0x0F00,0x0000,0x0000, /* 1D09F */ +0x0F01,0x0000,0x0000, 0x0F02,0x0000,0x0000, 0x0F03,0x0000,0x0000, /* 1D0A2 */ +0x0F04,0x0000,0x0000, 0x0F05,0x0000,0x0000, 0x0F06,0x0000,0x0000, /* 1D0A5 */ +0x0F07,0x0000,0x0000, 0x0F08,0x0000,0x0000, 0x0F09,0x0000,0x0000, /* 1D0A8 */ +0x0F0A,0x0000,0x0000, 0x0F0B,0x0000,0x0000, 0x0F0C,0x0000,0x0000, /* 1D0AB */ +0x0F0D,0x0000,0x0000, 0x0F0E,0x0000,0x0000, 0x0F0F,0x0000,0x0000, /* 1D0AE */ +0x0F10,0x0000,0x0000, 0x0F11,0x0000,0x0000, 0x0F12,0x0000,0x0000, /* 1D0B1 */ +0x0F13,0x0000,0x0000, 0x0F14,0x0000,0x0000, 0x0F15,0x0000,0x0000, /* 1D0B4 */ +0x0F16,0x0000,0x0000, 0x0F17,0x0000,0x0000, 0x0F18,0x0000,0x0000, /* 1D0B7 */ +0x0F19,0x0000,0x0000, 0x0F1A,0x0000,0x0000, 0x0F1B,0x0000,0x0000, /* 1D0BA */ +0x0F1C,0x0000,0x0000, 0x0F1D,0x0000,0x0000, 0x0F1E,0x0000,0x0000, /* 1D0BD */ +0x0F1F,0x0000,0x0000, 0x0F20,0x0000,0x0000, 0x0F21,0x0000,0x0000, /* 1D0C0 */ +0x0F22,0x0000,0x0000, 0x0F23,0x0000,0x0000, 0x0F24,0x0000,0x0000, /* 1D0C3 */ +0x0F25,0x0000,0x0000, 0x0F26,0x0000,0x0000, 0x0F27,0x0000,0x0000, /* 1D0C6 */ +0x0F28,0x0000,0x0000, 0x0F29,0x0000,0x0000, 0x0F2A,0x0000,0x0000, /* 1D0C9 */ +0x0F2B,0x0000,0x0000, 0x0F2C,0x0000,0x0000, 0x0F2D,0x0000,0x0000, /* 1D0CC */ +0x0F2E,0x0000,0x0000, 0x0F2F,0x0000,0x0000, 0x0F30,0x0000,0x0000, /* 1D0CF */ +0x0F31,0x0000,0x0000, 0x0F32,0x0000,0x0000, 0x0F33,0x0000,0x0000, /* 1D0D2 */ +0x0F34,0x0000,0x0000, 0x0F35,0x0000,0x0000, 0x0F36,0x0000,0x0000, /* 1D0D5 */ +0x0F37,0x0000,0x0000, 0x0F38,0x0000,0x0000, 0x0F39,0x0000,0x0000, /* 1D0D8 */ +0x0F3A,0x0000,0x0000, 0x0F3B,0x0000,0x0000, 0x0F3C,0x0000,0x0000, /* 1D0DB */ +0x0F3D,0x0000,0x0000, 0x0F3E,0x0000,0x0000, 0x0F3F,0x0000,0x0000, /* 1D0DE */ +0x0F40,0x0000,0x0000, 0x0F41,0x0000,0x0000, 0x0F42,0x0000,0x0000, /* 1D0E1 */ +0x0F43,0x0000,0x0000, 0x0F44,0x0000,0x0000, 0x0F45,0x0000,0x0000, /* 1D0E4 */ +0x0F46,0x0000,0x0000, 0x0F47,0x0000,0x0000, 0x0F48,0x0000,0x0000, /* 1D0E7 */ +0x0F49,0x0000,0x0000, 0x0F4A,0x0000,0x0000, 0x0F4B,0x0000,0x0000, /* 1D0EA */ +0x0F4C,0x0000,0x0000, 0x0F4D,0x0000,0x0000, 0x0F4E,0x0000,0x0000, /* 1D0ED */ +0x0F4F,0x0000,0x0000, 0x0F50,0x0000,0x0000, 0x0F51,0x0000,0x0000, /* 1D0F0 */ +0x0F52,0x0000,0x0000, 0x0F53,0x0000,0x0000, 0x0F54,0x0000,0x0000, /* 1D0F3 */ +0xFBC3,0xD0F6,0x0000, 0xFBC3,0xD0F7,0x0000, 0xFBC3,0xD0F8,0x0000, /* 1D0F6 */ +0xFBC3,0xD0F9,0x0000, 0xFBC3,0xD0FA,0x0000, 0xFBC3,0xD0FB,0x0000, /* 1D0F9 */ +0xFBC3,0xD0FC,0x0000, 0xFBC3,0xD0FD,0x0000, 0xFBC3,0xD0FE,0x0000, /* 1D0FC */ +0xFBC3,0xD0FF,0x0000 }; + +uint16 uca520_p1D1[]= { /* 1D100 (3 weights per char) */ +0x0F55,0x0000,0x0000, 0x0F56,0x0000,0x0000, 0x0F57,0x0000,0x0000, /* 1D100 */ +0x0F58,0x0000,0x0000, 0x0F59,0x0000,0x0000, 0x0F5A,0x0000,0x0000, /* 1D103 */ +0x0F5B,0x0000,0x0000, 0x0F5C,0x0000,0x0000, 0x0F5D,0x0000,0x0000, /* 1D106 */ +0x0F5E,0x0000,0x0000, 0x0F5F,0x0000,0x0000, 0x0F60,0x0000,0x0000, /* 1D109 */ +0x0F61,0x0000,0x0000, 0x0F62,0x0000,0x0000, 0x0F63,0x0000,0x0000, /* 1D10C */ +0x0F64,0x0000,0x0000, 0x0F65,0x0000,0x0000, 0x0F66,0x0000,0x0000, /* 1D10F */ +0x0F67,0x0000,0x0000, 0x0F68,0x0000,0x0000, 0x0F69,0x0000,0x0000, /* 1D112 */ +0x0F6A,0x0000,0x0000, 0x0F6B,0x0000,0x0000, 0x0F6C,0x0000,0x0000, /* 1D115 */ +0x0F6D,0x0000,0x0000, 0x0F6E,0x0000,0x0000, 0x0F6F,0x0000,0x0000, /* 1D118 */ +0x0F70,0x0000,0x0000, 0x0F71,0x0000,0x0000, 0x0F72,0x0000,0x0000, /* 1D11B */ +0x0F73,0x0000,0x0000, 0x0F74,0x0000,0x0000, 0x0F75,0x0000,0x0000, /* 1D11E */ +0x0F76,0x0000,0x0000, 0x0F77,0x0000,0x0000, 0x0F78,0x0000,0x0000, /* 1D121 */ +0x0F79,0x0000,0x0000, 0x0F7A,0x0000,0x0000, 0x0F7B,0x0000,0x0000, /* 1D124 */ +0xFBC3,0xD127,0x0000, 0xFBC3,0xD128,0x0000, 0x0F8F,0x0000,0x0000, /* 1D127 */ +0x0F7F,0x0000,0x0000, 0x0F80,0x0000,0x0000, 0x0F81,0x0000,0x0000, /* 1D12A */ +0x0F82,0x0000,0x0000, 0x0F83,0x0000,0x0000, 0x0F84,0x0000,0x0000, /* 1D12D */ +0x0F85,0x0000,0x0000, 0x0F86,0x0000,0x0000, 0x0F87,0x0000,0x0000, /* 1D130 */ +0x0F88,0x0000,0x0000, 0x0F89,0x0000,0x0000, 0x0F8A,0x0000,0x0000, /* 1D133 */ +0x0F8B,0x0000,0x0000, 0x0F8C,0x0000,0x0000, 0x0F8D,0x0000,0x0000, /* 1D136 */ +0x0F8E,0x0000,0x0000, 0x0F90,0x0000,0x0000, 0x0F91,0x0000,0x0000, /* 1D139 */ +0x0F92,0x0000,0x0000, 0x0F93,0x0000,0x0000, 0x0F94,0x0000,0x0000, /* 1D13C */ +0x0F95,0x0000,0x0000, 0x0F96,0x0000,0x0000, 0x0F97,0x0000,0x0000, /* 1D13F */ +0x0F98,0x0000,0x0000, 0x0F99,0x0000,0x0000, 0x0F9A,0x0000,0x0000, /* 1D142 */ +0x0F9B,0x0000,0x0000, 0x0F9C,0x0000,0x0000, 0x0F9D,0x0000,0x0000, /* 1D145 */ +0x0F9E,0x0000,0x0000, 0x0F9F,0x0000,0x0000, 0x0FA0,0x0000,0x0000, /* 1D148 */ +0x0FA1,0x0000,0x0000, 0x0FA2,0x0000,0x0000, 0x0FA3,0x0000,0x0000, /* 1D14B */ +0x0FA4,0x0000,0x0000, 0x0FA5,0x0000,0x0000, 0x0FA6,0x0000,0x0000, /* 1D14E */ +0x0FA7,0x0000,0x0000, 0x0FA8,0x0000,0x0000, 0x0FA9,0x0000,0x0000, /* 1D151 */ +0x0FAA,0x0000,0x0000, 0x0FAB,0x0000,0x0000, 0x0FAC,0x0000,0x0000, /* 1D154 */ +0x0FAD,0x0000,0x0000, 0x0FAE,0x0000,0x0000, 0x0FAF,0x0000,0x0000, /* 1D157 */ +0x0FB0,0x0000,0x0000, 0x0FB1,0x0000,0x0000, 0x0FB2,0x0000,0x0000, /* 1D15A */ +0x0FB3,0x0000,0x0000, 0x0FAD,0x0000,0x0000, 0x0FAE,0x0000,0x0000, /* 1D15D */ +0x0FAE,0x0000,0x0000, 0x0FAE,0x0000,0x0000, 0x0FAE,0x0000,0x0000, /* 1D160 */ +0x0FAE,0x0000,0x0000, 0x0FAE,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1D163 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1D166 */ +0x0000,0x0000,0x0000, 0x0FB4,0x0000,0x0000, 0x0FB5,0x0000,0x0000, /* 1D169 */ +0x0FB6,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1D16C */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1D16F */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1D172 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1D175 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1D178 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1D17B */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1D17E */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0FB7,0x0000,0x0000, /* 1D181 */ +0x0FB8,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1D184 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1D187 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0FB9,0x0000,0x0000, /* 1D18A */ +0x0FBA,0x0000,0x0000, 0x0FBB,0x0000,0x0000, 0x0FBC,0x0000,0x0000, /* 1D18D */ +0x0FBD,0x0000,0x0000, 0x0FBE,0x0000,0x0000, 0x0FBF,0x0000,0x0000, /* 1D190 */ +0x0FC0,0x0000,0x0000, 0x0FC1,0x0000,0x0000, 0x0FC2,0x0000,0x0000, /* 1D193 */ +0x0FC3,0x0000,0x0000, 0x0FC4,0x0000,0x0000, 0x0FC5,0x0000,0x0000, /* 1D196 */ +0x0FC6,0x0000,0x0000, 0x0FC7,0x0000,0x0000, 0x0FC8,0x0000,0x0000, /* 1D199 */ +0x0FC9,0x0000,0x0000, 0x0FCA,0x0000,0x0000, 0x0FCB,0x0000,0x0000, /* 1D19C */ +0x0FCC,0x0000,0x0000, 0x0FCD,0x0000,0x0000, 0x0FCE,0x0000,0x0000, /* 1D19F */ +0x0FCF,0x0000,0x0000, 0x0FD0,0x0000,0x0000, 0x0FD1,0x0000,0x0000, /* 1D1A2 */ +0x0FD2,0x0000,0x0000, 0x0FD3,0x0000,0x0000, 0x0FD4,0x0000,0x0000, /* 1D1A5 */ +0x0FD5,0x0000,0x0000, 0x0FD6,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1D1A8 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1D1AB */ +0x0FD7,0x0000,0x0000, 0x0FD8,0x0000,0x0000, 0x0FD9,0x0000,0x0000, /* 1D1AE */ +0x0FDA,0x0000,0x0000, 0x0FDB,0x0000,0x0000, 0x0FDC,0x0000,0x0000, /* 1D1B1 */ +0x0FDD,0x0000,0x0000, 0x0FDE,0x0000,0x0000, 0x0FDF,0x0000,0x0000, /* 1D1B4 */ +0x0FE0,0x0000,0x0000, 0x0FE1,0x0000,0x0000, 0x0FE2,0x0000,0x0000, /* 1D1B7 */ +0x0FE3,0x0000,0x0000, 0x0FE2,0x0000,0x0000, 0x0FE3,0x0000,0x0000, /* 1D1BA */ +0x0FE2,0x0000,0x0000, 0x0FE3,0x0000,0x0000, 0x0FE2,0x0000,0x0000, /* 1D1BD */ +0x0FE3,0x0000,0x0000, 0x0FE4,0x0000,0x0000, 0x0FE5,0x0000,0x0000, /* 1D1C0 */ +0x0FE6,0x0000,0x0000, 0x0FE7,0x0000,0x0000, 0x0FE8,0x0000,0x0000, /* 1D1C3 */ +0x0FE9,0x0000,0x0000, 0x0FEA,0x0000,0x0000, 0x0FEB,0x0000,0x0000, /* 1D1C6 */ +0x0FEC,0x0000,0x0000, 0x0FED,0x0000,0x0000, 0x0FEE,0x0000,0x0000, /* 1D1C9 */ +0x0FEF,0x0000,0x0000, 0x0FF0,0x0000,0x0000, 0x0FF1,0x0000,0x0000, /* 1D1CC */ +0x0FF2,0x0000,0x0000, 0x0FF3,0x0000,0x0000, 0x0FF4,0x0000,0x0000, /* 1D1CF */ +0x0FF5,0x0000,0x0000, 0x0FF6,0x0000,0x0000, 0x0FF7,0x0000,0x0000, /* 1D1D2 */ +0x0FF8,0x0000,0x0000, 0x0FF9,0x0000,0x0000, 0x0FFA,0x0000,0x0000, /* 1D1D5 */ +0x0FFB,0x0000,0x0000, 0x0FFC,0x0000,0x0000, 0x0FFD,0x0000,0x0000, /* 1D1D8 */ +0x0FFE,0x0000,0x0000, 0x0FFF,0x0000,0x0000, 0x1000,0x0000,0x0000, /* 1D1DB */ +0xFBC3,0xD1DE,0x0000, 0xFBC3,0xD1DF,0x0000, 0xFBC3,0xD1E0,0x0000, /* 1D1DE */ +0xFBC3,0xD1E1,0x0000, 0xFBC3,0xD1E2,0x0000, 0xFBC3,0xD1E3,0x0000, /* 1D1E1 */ +0xFBC3,0xD1E4,0x0000, 0xFBC3,0xD1E5,0x0000, 0xFBC3,0xD1E6,0x0000, /* 1D1E4 */ +0xFBC3,0xD1E7,0x0000, 0xFBC3,0xD1E8,0x0000, 0xFBC3,0xD1E9,0x0000, /* 1D1E7 */ +0xFBC3,0xD1EA,0x0000, 0xFBC3,0xD1EB,0x0000, 0xFBC3,0xD1EC,0x0000, /* 1D1EA */ +0xFBC3,0xD1ED,0x0000, 0xFBC3,0xD1EE,0x0000, 0xFBC3,0xD1EF,0x0000, /* 1D1ED */ +0xFBC3,0xD1F0,0x0000, 0xFBC3,0xD1F1,0x0000, 0xFBC3,0xD1F2,0x0000, /* 1D1F0 */ +0xFBC3,0xD1F3,0x0000, 0xFBC3,0xD1F4,0x0000, 0xFBC3,0xD1F5,0x0000, /* 1D1F3 */ +0xFBC3,0xD1F6,0x0000, 0xFBC3,0xD1F7,0x0000, 0xFBC3,0xD1F8,0x0000, /* 1D1F6 */ +0xFBC3,0xD1F9,0x0000, 0xFBC3,0xD1FA,0x0000, 0xFBC3,0xD1FB,0x0000, /* 1D1F9 */ +0xFBC3,0xD1FC,0x0000, 0xFBC3,0xD1FD,0x0000, 0xFBC3,0xD1FE,0x0000, /* 1D1FC */ +0xFBC3,0xD1FF,0x0000 }; + +uint16 uca520_p1D2[]= { /* 1D200 (3 weights per char) */ +0x1001,0x0000,0x0000, 0x1002,0x0000,0x0000, 0x1003,0x0000,0x0000, /* 1D200 */ +0x1004,0x0000,0x0000, 0x1005,0x0000,0x0000, 0x1006,0x0000,0x0000, /* 1D203 */ +0x1007,0x0000,0x0000, 0x1008,0x0000,0x0000, 0x1009,0x0000,0x0000, /* 1D206 */ +0x100A,0x0000,0x0000, 0x100B,0x0000,0x0000, 0x100C,0x0000,0x0000, /* 1D209 */ +0x100D,0x0000,0x0000, 0x100E,0x0000,0x0000, 0x100F,0x0000,0x0000, /* 1D20C */ +0x1010,0x0000,0x0000, 0x1011,0x0000,0x0000, 0x1012,0x0000,0x0000, /* 1D20F */ +0x1013,0x0000,0x0000, 0x1014,0x0000,0x0000, 0x1015,0x0000,0x0000, /* 1D212 */ +0x1016,0x0000,0x0000, 0x1017,0x0000,0x0000, 0x1018,0x0000,0x0000, /* 1D215 */ +0x1019,0x0000,0x0000, 0x101A,0x0000,0x0000, 0x101B,0x0000,0x0000, /* 1D218 */ +0x101C,0x0000,0x0000, 0x101D,0x0000,0x0000, 0x101E,0x0000,0x0000, /* 1D21B */ +0x101F,0x0000,0x0000, 0x1020,0x0000,0x0000, 0x1021,0x0000,0x0000, /* 1D21E */ +0x1022,0x0000,0x0000, 0x1023,0x0000,0x0000, 0x1024,0x0000,0x0000, /* 1D221 */ +0x1025,0x0000,0x0000, 0x1026,0x0000,0x0000, 0x1027,0x0000,0x0000, /* 1D224 */ +0x1028,0x0000,0x0000, 0x1029,0x0000,0x0000, 0x102A,0x0000,0x0000, /* 1D227 */ +0x102B,0x0000,0x0000, 0x102C,0x0000,0x0000, 0x102D,0x0000,0x0000, /* 1D22A */ +0x102E,0x0000,0x0000, 0x102F,0x0000,0x0000, 0x1030,0x0000,0x0000, /* 1D22D */ +0x1031,0x0000,0x0000, 0x1032,0x0000,0x0000, 0x1033,0x0000,0x0000, /* 1D230 */ +0x1034,0x0000,0x0000, 0x1035,0x0000,0x0000, 0x1036,0x0000,0x0000, /* 1D233 */ +0x1037,0x0000,0x0000, 0x1038,0x0000,0x0000, 0x1039,0x0000,0x0000, /* 1D236 */ +0x103A,0x0000,0x0000, 0x103B,0x0000,0x0000, 0x103C,0x0000,0x0000, /* 1D239 */ +0x103D,0x0000,0x0000, 0x103E,0x0000,0x0000, 0x103F,0x0000,0x0000, /* 1D23C */ +0x1040,0x0000,0x0000, 0x1041,0x0000,0x0000, 0x1042,0x0000,0x0000, /* 1D23F */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* 1D242 */ +0x1043,0x0000,0x0000, 0xFBC3,0xD246,0x0000, 0xFBC3,0xD247,0x0000, /* 1D245 */ +0xFBC3,0xD248,0x0000, 0xFBC3,0xD249,0x0000, 0xFBC3,0xD24A,0x0000, /* 1D248 */ +0xFBC3,0xD24B,0x0000, 0xFBC3,0xD24C,0x0000, 0xFBC3,0xD24D,0x0000, /* 1D24B */ +0xFBC3,0xD24E,0x0000, 0xFBC3,0xD24F,0x0000, 0xFBC3,0xD250,0x0000, /* 1D24E */ +0xFBC3,0xD251,0x0000, 0xFBC3,0xD252,0x0000, 0xFBC3,0xD253,0x0000, /* 1D251 */ +0xFBC3,0xD254,0x0000, 0xFBC3,0xD255,0x0000, 0xFBC3,0xD256,0x0000, /* 1D254 */ +0xFBC3,0xD257,0x0000, 0xFBC3,0xD258,0x0000, 0xFBC3,0xD259,0x0000, /* 1D257 */ +0xFBC3,0xD25A,0x0000, 0xFBC3,0xD25B,0x0000, 0xFBC3,0xD25C,0x0000, /* 1D25A */ +0xFBC3,0xD25D,0x0000, 0xFBC3,0xD25E,0x0000, 0xFBC3,0xD25F,0x0000, /* 1D25D */ +0xFBC3,0xD260,0x0000, 0xFBC3,0xD261,0x0000, 0xFBC3,0xD262,0x0000, /* 1D260 */ +0xFBC3,0xD263,0x0000, 0xFBC3,0xD264,0x0000, 0xFBC3,0xD265,0x0000, /* 1D263 */ +0xFBC3,0xD266,0x0000, 0xFBC3,0xD267,0x0000, 0xFBC3,0xD268,0x0000, /* 1D266 */ +0xFBC3,0xD269,0x0000, 0xFBC3,0xD26A,0x0000, 0xFBC3,0xD26B,0x0000, /* 1D269 */ +0xFBC3,0xD26C,0x0000, 0xFBC3,0xD26D,0x0000, 0xFBC3,0xD26E,0x0000, /* 1D26C */ +0xFBC3,0xD26F,0x0000, 0xFBC3,0xD270,0x0000, 0xFBC3,0xD271,0x0000, /* 1D26F */ +0xFBC3,0xD272,0x0000, 0xFBC3,0xD273,0x0000, 0xFBC3,0xD274,0x0000, /* 1D272 */ +0xFBC3,0xD275,0x0000, 0xFBC3,0xD276,0x0000, 0xFBC3,0xD277,0x0000, /* 1D275 */ +0xFBC3,0xD278,0x0000, 0xFBC3,0xD279,0x0000, 0xFBC3,0xD27A,0x0000, /* 1D278 */ +0xFBC3,0xD27B,0x0000, 0xFBC3,0xD27C,0x0000, 0xFBC3,0xD27D,0x0000, /* 1D27B */ +0xFBC3,0xD27E,0x0000, 0xFBC3,0xD27F,0x0000, 0xFBC3,0xD280,0x0000, /* 1D27E */ +0xFBC3,0xD281,0x0000, 0xFBC3,0xD282,0x0000, 0xFBC3,0xD283,0x0000, /* 1D281 */ +0xFBC3,0xD284,0x0000, 0xFBC3,0xD285,0x0000, 0xFBC3,0xD286,0x0000, /* 1D284 */ +0xFBC3,0xD287,0x0000, 0xFBC3,0xD288,0x0000, 0xFBC3,0xD289,0x0000, /* 1D287 */ +0xFBC3,0xD28A,0x0000, 0xFBC3,0xD28B,0x0000, 0xFBC3,0xD28C,0x0000, /* 1D28A */ +0xFBC3,0xD28D,0x0000, 0xFBC3,0xD28E,0x0000, 0xFBC3,0xD28F,0x0000, /* 1D28D */ +0xFBC3,0xD290,0x0000, 0xFBC3,0xD291,0x0000, 0xFBC3,0xD292,0x0000, /* 1D290 */ +0xFBC3,0xD293,0x0000, 0xFBC3,0xD294,0x0000, 0xFBC3,0xD295,0x0000, /* 1D293 */ +0xFBC3,0xD296,0x0000, 0xFBC3,0xD297,0x0000, 0xFBC3,0xD298,0x0000, /* 1D296 */ +0xFBC3,0xD299,0x0000, 0xFBC3,0xD29A,0x0000, 0xFBC3,0xD29B,0x0000, /* 1D299 */ +0xFBC3,0xD29C,0x0000, 0xFBC3,0xD29D,0x0000, 0xFBC3,0xD29E,0x0000, /* 1D29C */ +0xFBC3,0xD29F,0x0000, 0xFBC3,0xD2A0,0x0000, 0xFBC3,0xD2A1,0x0000, /* 1D29F */ +0xFBC3,0xD2A2,0x0000, 0xFBC3,0xD2A3,0x0000, 0xFBC3,0xD2A4,0x0000, /* 1D2A2 */ +0xFBC3,0xD2A5,0x0000, 0xFBC3,0xD2A6,0x0000, 0xFBC3,0xD2A7,0x0000, /* 1D2A5 */ +0xFBC3,0xD2A8,0x0000, 0xFBC3,0xD2A9,0x0000, 0xFBC3,0xD2AA,0x0000, /* 1D2A8 */ +0xFBC3,0xD2AB,0x0000, 0xFBC3,0xD2AC,0x0000, 0xFBC3,0xD2AD,0x0000, /* 1D2AB */ +0xFBC3,0xD2AE,0x0000, 0xFBC3,0xD2AF,0x0000, 0xFBC3,0xD2B0,0x0000, /* 1D2AE */ +0xFBC3,0xD2B1,0x0000, 0xFBC3,0xD2B2,0x0000, 0xFBC3,0xD2B3,0x0000, /* 1D2B1 */ +0xFBC3,0xD2B4,0x0000, 0xFBC3,0xD2B5,0x0000, 0xFBC3,0xD2B6,0x0000, /* 1D2B4 */ +0xFBC3,0xD2B7,0x0000, 0xFBC3,0xD2B8,0x0000, 0xFBC3,0xD2B9,0x0000, /* 1D2B7 */ +0xFBC3,0xD2BA,0x0000, 0xFBC3,0xD2BB,0x0000, 0xFBC3,0xD2BC,0x0000, /* 1D2BA */ +0xFBC3,0xD2BD,0x0000, 0xFBC3,0xD2BE,0x0000, 0xFBC3,0xD2BF,0x0000, /* 1D2BD */ +0xFBC3,0xD2C0,0x0000, 0xFBC3,0xD2C1,0x0000, 0xFBC3,0xD2C2,0x0000, /* 1D2C0 */ +0xFBC3,0xD2C3,0x0000, 0xFBC3,0xD2C4,0x0000, 0xFBC3,0xD2C5,0x0000, /* 1D2C3 */ +0xFBC3,0xD2C6,0x0000, 0xFBC3,0xD2C7,0x0000, 0xFBC3,0xD2C8,0x0000, /* 1D2C6 */ +0xFBC3,0xD2C9,0x0000, 0xFBC3,0xD2CA,0x0000, 0xFBC3,0xD2CB,0x0000, /* 1D2C9 */ +0xFBC3,0xD2CC,0x0000, 0xFBC3,0xD2CD,0x0000, 0xFBC3,0xD2CE,0x0000, /* 1D2CC */ +0xFBC3,0xD2CF,0x0000, 0xFBC3,0xD2D0,0x0000, 0xFBC3,0xD2D1,0x0000, /* 1D2CF */ +0xFBC3,0xD2D2,0x0000, 0xFBC3,0xD2D3,0x0000, 0xFBC3,0xD2D4,0x0000, /* 1D2D2 */ +0xFBC3,0xD2D5,0x0000, 0xFBC3,0xD2D6,0x0000, 0xFBC3,0xD2D7,0x0000, /* 1D2D5 */ +0xFBC3,0xD2D8,0x0000, 0xFBC3,0xD2D9,0x0000, 0xFBC3,0xD2DA,0x0000, /* 1D2D8 */ +0xFBC3,0xD2DB,0x0000, 0xFBC3,0xD2DC,0x0000, 0xFBC3,0xD2DD,0x0000, /* 1D2DB */ +0xFBC3,0xD2DE,0x0000, 0xFBC3,0xD2DF,0x0000, 0xFBC3,0xD2E0,0x0000, /* 1D2DE */ +0xFBC3,0xD2E1,0x0000, 0xFBC3,0xD2E2,0x0000, 0xFBC3,0xD2E3,0x0000, /* 1D2E1 */ +0xFBC3,0xD2E4,0x0000, 0xFBC3,0xD2E5,0x0000, 0xFBC3,0xD2E6,0x0000, /* 1D2E4 */ +0xFBC3,0xD2E7,0x0000, 0xFBC3,0xD2E8,0x0000, 0xFBC3,0xD2E9,0x0000, /* 1D2E7 */ +0xFBC3,0xD2EA,0x0000, 0xFBC3,0xD2EB,0x0000, 0xFBC3,0xD2EC,0x0000, /* 1D2EA */ +0xFBC3,0xD2ED,0x0000, 0xFBC3,0xD2EE,0x0000, 0xFBC3,0xD2EF,0x0000, /* 1D2ED */ +0xFBC3,0xD2F0,0x0000, 0xFBC3,0xD2F1,0x0000, 0xFBC3,0xD2F2,0x0000, /* 1D2F0 */ +0xFBC3,0xD2F3,0x0000, 0xFBC3,0xD2F4,0x0000, 0xFBC3,0xD2F5,0x0000, /* 1D2F3 */ +0xFBC3,0xD2F6,0x0000, 0xFBC3,0xD2F7,0x0000, 0xFBC3,0xD2F8,0x0000, /* 1D2F6 */ +0xFBC3,0xD2F9,0x0000, 0xFBC3,0xD2FA,0x0000, 0xFBC3,0xD2FB,0x0000, /* 1D2F9 */ +0xFBC3,0xD2FC,0x0000, 0xFBC3,0xD2FD,0x0000, 0xFBC3,0xD2FE,0x0000, /* 1D2FC */ +0xFBC3,0xD2FF,0x0000 }; + +uint16 uca520_p1D3[]= { /* 1D300 (3 weights per char) */ +0x0D7E,0x0000,0x0000, 0x0D7F,0x0000,0x0000, 0x0D80,0x0000,0x0000, /* 1D300 */ +0x0D81,0x0000,0x0000, 0x0D82,0x0000,0x0000, 0x0D83,0x0000,0x0000, /* 1D303 */ +0x0D84,0x0000,0x0000, 0x0D85,0x0000,0x0000, 0x0D86,0x0000,0x0000, /* 1D306 */ +0x0D87,0x0000,0x0000, 0x0D88,0x0000,0x0000, 0x0D89,0x0000,0x0000, /* 1D309 */ +0x0D8A,0x0000,0x0000, 0x0D8B,0x0000,0x0000, 0x0D8C,0x0000,0x0000, /* 1D30C */ +0x0D8D,0x0000,0x0000, 0x0D8E,0x0000,0x0000, 0x0D8F,0x0000,0x0000, /* 1D30F */ +0x0D90,0x0000,0x0000, 0x0D91,0x0000,0x0000, 0x0D92,0x0000,0x0000, /* 1D312 */ +0x0D93,0x0000,0x0000, 0x0D94,0x0000,0x0000, 0x0D95,0x0000,0x0000, /* 1D315 */ +0x0D96,0x0000,0x0000, 0x0D97,0x0000,0x0000, 0x0D98,0x0000,0x0000, /* 1D318 */ +0x0D99,0x0000,0x0000, 0x0D9A,0x0000,0x0000, 0x0D9B,0x0000,0x0000, /* 1D31B */ +0x0D9C,0x0000,0x0000, 0x0D9D,0x0000,0x0000, 0x0D9E,0x0000,0x0000, /* 1D31E */ +0x0D9F,0x0000,0x0000, 0x0DA0,0x0000,0x0000, 0x0DA1,0x0000,0x0000, /* 1D321 */ +0x0DA2,0x0000,0x0000, 0x0DA3,0x0000,0x0000, 0x0DA4,0x0000,0x0000, /* 1D324 */ +0x0DA5,0x0000,0x0000, 0x0DA6,0x0000,0x0000, 0x0DA7,0x0000,0x0000, /* 1D327 */ +0x0DA8,0x0000,0x0000, 0x0DA9,0x0000,0x0000, 0x0DAA,0x0000,0x0000, /* 1D32A */ +0x0DAB,0x0000,0x0000, 0x0DAC,0x0000,0x0000, 0x0DAD,0x0000,0x0000, /* 1D32D */ +0x0DAE,0x0000,0x0000, 0x0DAF,0x0000,0x0000, 0x0DB0,0x0000,0x0000, /* 1D330 */ +0x0DB1,0x0000,0x0000, 0x0DB2,0x0000,0x0000, 0x0DB3,0x0000,0x0000, /* 1D333 */ +0x0DB4,0x0000,0x0000, 0x0DB5,0x0000,0x0000, 0x0DB6,0x0000,0x0000, /* 1D336 */ +0x0DB7,0x0000,0x0000, 0x0DB8,0x0000,0x0000, 0x0DB9,0x0000,0x0000, /* 1D339 */ +0x0DBA,0x0000,0x0000, 0x0DBB,0x0000,0x0000, 0x0DBC,0x0000,0x0000, /* 1D33C */ +0x0DBD,0x0000,0x0000, 0x0DBE,0x0000,0x0000, 0x0DBF,0x0000,0x0000, /* 1D33F */ +0x0DC0,0x0000,0x0000, 0x0DC1,0x0000,0x0000, 0x0DC2,0x0000,0x0000, /* 1D342 */ +0x0DC3,0x0000,0x0000, 0x0DC4,0x0000,0x0000, 0x0DC5,0x0000,0x0000, /* 1D345 */ +0x0DC6,0x0000,0x0000, 0x0DC7,0x0000,0x0000, 0x0DC8,0x0000,0x0000, /* 1D348 */ +0x0DC9,0x0000,0x0000, 0x0DCA,0x0000,0x0000, 0x0DCB,0x0000,0x0000, /* 1D34B */ +0x0DCC,0x0000,0x0000, 0x0DCD,0x0000,0x0000, 0x0DCE,0x0000,0x0000, /* 1D34E */ +0x0DCF,0x0000,0x0000, 0x0DD0,0x0000,0x0000, 0x0DD1,0x0000,0x0000, /* 1D351 */ +0x0DD2,0x0000,0x0000, 0x0DD3,0x0000,0x0000, 0x0DD4,0x0000,0x0000, /* 1D354 */ +0xFBC3,0xD357,0x0000, 0xFBC3,0xD358,0x0000, 0xFBC3,0xD359,0x0000, /* 1D357 */ +0xFBC3,0xD35A,0x0000, 0xFBC3,0xD35B,0x0000, 0xFBC3,0xD35C,0x0000, /* 1D35A */ +0xFBC3,0xD35D,0x0000, 0xFBC3,0xD35E,0x0000, 0xFBC3,0xD35F,0x0000, /* 1D35D */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 1D360 */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 1D363 */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 1D366 */ +0x11C5,0x0000,0x0000, 0x11C6,0x0000,0x0000, 0x11C7,0x0000,0x0000, /* 1D369 */ +0x11C8,0x0000,0x0000, 0x11C9,0x0000,0x0000, 0x11CA,0x0000,0x0000, /* 1D36C */ +0x11CB,0x0000,0x0000, 0x11CC,0x0000,0x0000, 0x11CD,0x0000,0x0000, /* 1D36F */ +0xFBC3,0xD372,0x0000, 0xFBC3,0xD373,0x0000, 0xFBC3,0xD374,0x0000, /* 1D372 */ +0xFBC3,0xD375,0x0000, 0xFBC3,0xD376,0x0000, 0xFBC3,0xD377,0x0000, /* 1D375 */ +0xFBC3,0xD378,0x0000, 0xFBC3,0xD379,0x0000, 0xFBC3,0xD37A,0x0000, /* 1D378 */ +0xFBC3,0xD37B,0x0000, 0xFBC3,0xD37C,0x0000, 0xFBC3,0xD37D,0x0000, /* 1D37B */ +0xFBC3,0xD37E,0x0000, 0xFBC3,0xD37F,0x0000, 0xFBC3,0xD380,0x0000, /* 1D37E */ +0xFBC3,0xD381,0x0000, 0xFBC3,0xD382,0x0000, 0xFBC3,0xD383,0x0000, /* 1D381 */ +0xFBC3,0xD384,0x0000, 0xFBC3,0xD385,0x0000, 0xFBC3,0xD386,0x0000, /* 1D384 */ +0xFBC3,0xD387,0x0000, 0xFBC3,0xD388,0x0000, 0xFBC3,0xD389,0x0000, /* 1D387 */ +0xFBC3,0xD38A,0x0000, 0xFBC3,0xD38B,0x0000, 0xFBC3,0xD38C,0x0000, /* 1D38A */ +0xFBC3,0xD38D,0x0000, 0xFBC3,0xD38E,0x0000, 0xFBC3,0xD38F,0x0000, /* 1D38D */ +0xFBC3,0xD390,0x0000, 0xFBC3,0xD391,0x0000, 0xFBC3,0xD392,0x0000, /* 1D390 */ +0xFBC3,0xD393,0x0000, 0xFBC3,0xD394,0x0000, 0xFBC3,0xD395,0x0000, /* 1D393 */ +0xFBC3,0xD396,0x0000, 0xFBC3,0xD397,0x0000, 0xFBC3,0xD398,0x0000, /* 1D396 */ +0xFBC3,0xD399,0x0000, 0xFBC3,0xD39A,0x0000, 0xFBC3,0xD39B,0x0000, /* 1D399 */ +0xFBC3,0xD39C,0x0000, 0xFBC3,0xD39D,0x0000, 0xFBC3,0xD39E,0x0000, /* 1D39C */ +0xFBC3,0xD39F,0x0000, 0xFBC3,0xD3A0,0x0000, 0xFBC3,0xD3A1,0x0000, /* 1D39F */ +0xFBC3,0xD3A2,0x0000, 0xFBC3,0xD3A3,0x0000, 0xFBC3,0xD3A4,0x0000, /* 1D3A2 */ +0xFBC3,0xD3A5,0x0000, 0xFBC3,0xD3A6,0x0000, 0xFBC3,0xD3A7,0x0000, /* 1D3A5 */ +0xFBC3,0xD3A8,0x0000, 0xFBC3,0xD3A9,0x0000, 0xFBC3,0xD3AA,0x0000, /* 1D3A8 */ +0xFBC3,0xD3AB,0x0000, 0xFBC3,0xD3AC,0x0000, 0xFBC3,0xD3AD,0x0000, /* 1D3AB */ +0xFBC3,0xD3AE,0x0000, 0xFBC3,0xD3AF,0x0000, 0xFBC3,0xD3B0,0x0000, /* 1D3AE */ +0xFBC3,0xD3B1,0x0000, 0xFBC3,0xD3B2,0x0000, 0xFBC3,0xD3B3,0x0000, /* 1D3B1 */ +0xFBC3,0xD3B4,0x0000, 0xFBC3,0xD3B5,0x0000, 0xFBC3,0xD3B6,0x0000, /* 1D3B4 */ +0xFBC3,0xD3B7,0x0000, 0xFBC3,0xD3B8,0x0000, 0xFBC3,0xD3B9,0x0000, /* 1D3B7 */ +0xFBC3,0xD3BA,0x0000, 0xFBC3,0xD3BB,0x0000, 0xFBC3,0xD3BC,0x0000, /* 1D3BA */ +0xFBC3,0xD3BD,0x0000, 0xFBC3,0xD3BE,0x0000, 0xFBC3,0xD3BF,0x0000, /* 1D3BD */ +0xFBC3,0xD3C0,0x0000, 0xFBC3,0xD3C1,0x0000, 0xFBC3,0xD3C2,0x0000, /* 1D3C0 */ +0xFBC3,0xD3C3,0x0000, 0xFBC3,0xD3C4,0x0000, 0xFBC3,0xD3C5,0x0000, /* 1D3C3 */ +0xFBC3,0xD3C6,0x0000, 0xFBC3,0xD3C7,0x0000, 0xFBC3,0xD3C8,0x0000, /* 1D3C6 */ +0xFBC3,0xD3C9,0x0000, 0xFBC3,0xD3CA,0x0000, 0xFBC3,0xD3CB,0x0000, /* 1D3C9 */ +0xFBC3,0xD3CC,0x0000, 0xFBC3,0xD3CD,0x0000, 0xFBC3,0xD3CE,0x0000, /* 1D3CC */ +0xFBC3,0xD3CF,0x0000, 0xFBC3,0xD3D0,0x0000, 0xFBC3,0xD3D1,0x0000, /* 1D3CF */ +0xFBC3,0xD3D2,0x0000, 0xFBC3,0xD3D3,0x0000, 0xFBC3,0xD3D4,0x0000, /* 1D3D2 */ +0xFBC3,0xD3D5,0x0000, 0xFBC3,0xD3D6,0x0000, 0xFBC3,0xD3D7,0x0000, /* 1D3D5 */ +0xFBC3,0xD3D8,0x0000, 0xFBC3,0xD3D9,0x0000, 0xFBC3,0xD3DA,0x0000, /* 1D3D8 */ +0xFBC3,0xD3DB,0x0000, 0xFBC3,0xD3DC,0x0000, 0xFBC3,0xD3DD,0x0000, /* 1D3DB */ +0xFBC3,0xD3DE,0x0000, 0xFBC3,0xD3DF,0x0000, 0xFBC3,0xD3E0,0x0000, /* 1D3DE */ +0xFBC3,0xD3E1,0x0000, 0xFBC3,0xD3E2,0x0000, 0xFBC3,0xD3E3,0x0000, /* 1D3E1 */ +0xFBC3,0xD3E4,0x0000, 0xFBC3,0xD3E5,0x0000, 0xFBC3,0xD3E6,0x0000, /* 1D3E4 */ +0xFBC3,0xD3E7,0x0000, 0xFBC3,0xD3E8,0x0000, 0xFBC3,0xD3E9,0x0000, /* 1D3E7 */ +0xFBC3,0xD3EA,0x0000, 0xFBC3,0xD3EB,0x0000, 0xFBC3,0xD3EC,0x0000, /* 1D3EA */ +0xFBC3,0xD3ED,0x0000, 0xFBC3,0xD3EE,0x0000, 0xFBC3,0xD3EF,0x0000, /* 1D3ED */ +0xFBC3,0xD3F0,0x0000, 0xFBC3,0xD3F1,0x0000, 0xFBC3,0xD3F2,0x0000, /* 1D3F0 */ +0xFBC3,0xD3F3,0x0000, 0xFBC3,0xD3F4,0x0000, 0xFBC3,0xD3F5,0x0000, /* 1D3F3 */ +0xFBC3,0xD3F6,0x0000, 0xFBC3,0xD3F7,0x0000, 0xFBC3,0xD3F8,0x0000, /* 1D3F6 */ +0xFBC3,0xD3F9,0x0000, 0xFBC3,0xD3FA,0x0000, 0xFBC3,0xD3FB,0x0000, /* 1D3F9 */ +0xFBC3,0xD3FC,0x0000, 0xFBC3,0xD3FD,0x0000, 0xFBC3,0xD3FE,0x0000, /* 1D3FC */ +0xFBC3,0xD3FF,0x0000 }; + +uint16 uca520_p1D4[]= { /* 1D400 (3 weights per char) */ +0x120F,0x0000,0x0000, 0x1225,0x0000,0x0000, 0x123D,0x0000,0x0000, /* 1D400 */ +0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x12A3,0x0000,0x0000, /* 1D403 */ +0x12B0,0x0000,0x0000, 0x12D3,0x0000,0x0000, 0x12EC,0x0000,0x0000, /* 1D406 */ +0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, /* 1D409 */ +0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1D40C */ +0x13B3,0x0000,0x0000, 0x13C8,0x0000,0x0000, 0x13DA,0x0000,0x0000, /* 1D40F */ +0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 1D412 */ +0x147B,0x0000,0x0000, 0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, /* 1D415 */ +0x149C,0x0000,0x0000, 0x14AD,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 1D418 */ +0x1225,0x0000,0x0000, 0x123D,0x0000,0x0000, 0x1250,0x0000,0x0000, /* 1D41B */ +0x126B,0x0000,0x0000, 0x12A3,0x0000,0x0000, 0x12B0,0x0000,0x0000, /* 1D41E */ +0x12D3,0x0000,0x0000, 0x12EC,0x0000,0x0000, 0x1305,0x0000,0x0000, /* 1D421 */ +0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, 0x135F,0x0000,0x0000, /* 1D424 */ +0x136D,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x13B3,0x0000,0x0000, /* 1D427 */ +0x13C8,0x0000,0x0000, 0x13DA,0x0000,0x0000, 0x1410,0x0000,0x0000, /* 1D42A */ +0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x147B,0x0000,0x0000, /* 1D42D */ +0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, 0x149C,0x0000,0x0000, /* 1D430 */ +0x14AD,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x1225,0x0000,0x0000, /* 1D433 */ +0x123D,0x0000,0x0000, 0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 1D436 */ +0x12A3,0x0000,0x0000, 0x12B0,0x0000,0x0000, 0x12D3,0x0000,0x0000, /* 1D439 */ +0x12EC,0x0000,0x0000, 0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, /* 1D43C */ +0x1330,0x0000,0x0000, 0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, /* 1D43F */ +0x138E,0x0000,0x0000, 0x13B3,0x0000,0x0000, 0x13C8,0x0000,0x0000, /* 1D442 */ +0x13DA,0x0000,0x0000, 0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, /* 1D445 */ +0x1453,0x0000,0x0000, 0x147B,0x0000,0x0000, 0x148D,0x0000,0x0000, /* 1D448 */ +0x1497,0x0000,0x0000, 0x149C,0x0000,0x0000, 0x14AD,0x0000,0x0000, /* 1D44B */ +0x120F,0x0000,0x0000, 0x1225,0x0000,0x0000, 0x123D,0x0000,0x0000, /* 1D44E */ +0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x12A3,0x0000,0x0000, /* 1D451 */ +0x12B0,0x0000,0x0000, 0xFBC3,0xD455,0x0000, 0x12EC,0x0000,0x0000, /* 1D454 */ +0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, /* 1D457 */ +0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1D45A */ +0x13B3,0x0000,0x0000, 0x13C8,0x0000,0x0000, 0x13DA,0x0000,0x0000, /* 1D45D */ +0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 1D460 */ +0x147B,0x0000,0x0000, 0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, /* 1D463 */ +0x149C,0x0000,0x0000, 0x14AD,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 1D466 */ +0x1225,0x0000,0x0000, 0x123D,0x0000,0x0000, 0x1250,0x0000,0x0000, /* 1D469 */ +0x126B,0x0000,0x0000, 0x12A3,0x0000,0x0000, 0x12B0,0x0000,0x0000, /* 1D46C */ +0x12D3,0x0000,0x0000, 0x12EC,0x0000,0x0000, 0x1305,0x0000,0x0000, /* 1D46F */ +0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, 0x135F,0x0000,0x0000, /* 1D472 */ +0x136D,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x13B3,0x0000,0x0000, /* 1D475 */ +0x13C8,0x0000,0x0000, 0x13DA,0x0000,0x0000, 0x1410,0x0000,0x0000, /* 1D478 */ +0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x147B,0x0000,0x0000, /* 1D47B */ +0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, 0x149C,0x0000,0x0000, /* 1D47E */ +0x14AD,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x1225,0x0000,0x0000, /* 1D481 */ +0x123D,0x0000,0x0000, 0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 1D484 */ +0x12A3,0x0000,0x0000, 0x12B0,0x0000,0x0000, 0x12D3,0x0000,0x0000, /* 1D487 */ +0x12EC,0x0000,0x0000, 0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, /* 1D48A */ +0x1330,0x0000,0x0000, 0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, /* 1D48D */ +0x138E,0x0000,0x0000, 0x13B3,0x0000,0x0000, 0x13C8,0x0000,0x0000, /* 1D490 */ +0x13DA,0x0000,0x0000, 0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, /* 1D493 */ +0x1453,0x0000,0x0000, 0x147B,0x0000,0x0000, 0x148D,0x0000,0x0000, /* 1D496 */ +0x1497,0x0000,0x0000, 0x149C,0x0000,0x0000, 0x14AD,0x0000,0x0000, /* 1D499 */ +0x120F,0x0000,0x0000, 0xFBC3,0xD49D,0x0000, 0x123D,0x0000,0x0000, /* 1D49C */ +0x1250,0x0000,0x0000, 0xFBC3,0xD4A0,0x0000, 0xFBC3,0xD4A1,0x0000, /* 1D49F */ +0x12B0,0x0000,0x0000, 0xFBC3,0xD4A3,0x0000, 0xFBC3,0xD4A4,0x0000, /* 1D4A2 */ +0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, 0xFBC3,0xD4A7,0x0000, /* 1D4A5 */ +0xFBC3,0xD4A8,0x0000, 0x136D,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1D4A8 */ +0x13B3,0x0000,0x0000, 0x13C8,0x0000,0x0000, 0xFBC3,0xD4AD,0x0000, /* 1D4AB */ +0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 1D4AE */ +0x147B,0x0000,0x0000, 0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, /* 1D4B1 */ +0x149C,0x0000,0x0000, 0x14AD,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 1D4B4 */ +0x1225,0x0000,0x0000, 0x123D,0x0000,0x0000, 0x1250,0x0000,0x0000, /* 1D4B7 */ +0xFBC3,0xD4BA,0x0000, 0x12A3,0x0000,0x0000, 0xFBC3,0xD4BC,0x0000, /* 1D4BA */ +0x12D3,0x0000,0x0000, 0x12EC,0x0000,0x0000, 0x1305,0x0000,0x0000, /* 1D4BD */ +0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, 0x135F,0x0000,0x0000, /* 1D4C0 */ +0x136D,0x0000,0x0000, 0xFBC3,0xD4C4,0x0000, 0x13B3,0x0000,0x0000, /* 1D4C3 */ +0x13C8,0x0000,0x0000, 0x13DA,0x0000,0x0000, 0x1410,0x0000,0x0000, /* 1D4C6 */ +0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x147B,0x0000,0x0000, /* 1D4C9 */ +0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, 0x149C,0x0000,0x0000, /* 1D4CC */ +0x14AD,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x1225,0x0000,0x0000, /* 1D4CF */ +0x123D,0x0000,0x0000, 0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 1D4D2 */ +0x12A3,0x0000,0x0000, 0x12B0,0x0000,0x0000, 0x12D3,0x0000,0x0000, /* 1D4D5 */ +0x12EC,0x0000,0x0000, 0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, /* 1D4D8 */ +0x1330,0x0000,0x0000, 0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, /* 1D4DB */ +0x138E,0x0000,0x0000, 0x13B3,0x0000,0x0000, 0x13C8,0x0000,0x0000, /* 1D4DE */ +0x13DA,0x0000,0x0000, 0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, /* 1D4E1 */ +0x1453,0x0000,0x0000, 0x147B,0x0000,0x0000, 0x148D,0x0000,0x0000, /* 1D4E4 */ +0x1497,0x0000,0x0000, 0x149C,0x0000,0x0000, 0x14AD,0x0000,0x0000, /* 1D4E7 */ +0x120F,0x0000,0x0000, 0x1225,0x0000,0x0000, 0x123D,0x0000,0x0000, /* 1D4EA */ +0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x12A3,0x0000,0x0000, /* 1D4ED */ +0x12B0,0x0000,0x0000, 0x12D3,0x0000,0x0000, 0x12EC,0x0000,0x0000, /* 1D4F0 */ +0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, /* 1D4F3 */ +0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1D4F6 */ +0x13B3,0x0000,0x0000, 0x13C8,0x0000,0x0000, 0x13DA,0x0000,0x0000, /* 1D4F9 */ +0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 1D4FC */ +0x147B,0x0000,0x0000 }; + +uint16 uca520_p1D5[]= { /* 1D500 (3 weights per char) */ +0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, 0x149C,0x0000,0x0000, /* 1D500 */ +0x14AD,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x1225,0x0000,0x0000, /* 1D503 */ +0xFBC3,0xD506,0x0000, 0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 1D506 */ +0x12A3,0x0000,0x0000, 0x12B0,0x0000,0x0000, 0xFBC3,0xD50B,0x0000, /* 1D509 */ +0xFBC3,0xD50C,0x0000, 0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, /* 1D50C */ +0x1330,0x0000,0x0000, 0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, /* 1D50F */ +0x138E,0x0000,0x0000, 0x13B3,0x0000,0x0000, 0x13C8,0x0000,0x0000, /* 1D512 */ +0xFBC3,0xD515,0x0000, 0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, /* 1D515 */ +0x1453,0x0000,0x0000, 0x147B,0x0000,0x0000, 0x148D,0x0000,0x0000, /* 1D518 */ +0x1497,0x0000,0x0000, 0x149C,0x0000,0x0000, 0xFBC3,0xD51D,0x0000, /* 1D51B */ +0x120F,0x0000,0x0000, 0x1225,0x0000,0x0000, 0x123D,0x0000,0x0000, /* 1D51E */ +0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x12A3,0x0000,0x0000, /* 1D521 */ +0x12B0,0x0000,0x0000, 0x12D3,0x0000,0x0000, 0x12EC,0x0000,0x0000, /* 1D524 */ +0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, /* 1D527 */ +0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1D52A */ +0x13B3,0x0000,0x0000, 0x13C8,0x0000,0x0000, 0x13DA,0x0000,0x0000, /* 1D52D */ +0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 1D530 */ +0x147B,0x0000,0x0000, 0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, /* 1D533 */ +0x149C,0x0000,0x0000, 0x14AD,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 1D536 */ +0x1225,0x0000,0x0000, 0xFBC3,0xD53A,0x0000, 0x1250,0x0000,0x0000, /* 1D539 */ +0x126B,0x0000,0x0000, 0x12A3,0x0000,0x0000, 0x12B0,0x0000,0x0000, /* 1D53C */ +0xFBC3,0xD53F,0x0000, 0x12EC,0x0000,0x0000, 0x1305,0x0000,0x0000, /* 1D53F */ +0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, 0x135F,0x0000,0x0000, /* 1D542 */ +0xFBC3,0xD545,0x0000, 0x138E,0x0000,0x0000, 0xFBC3,0xD547,0x0000, /* 1D545 */ +0xFBC3,0xD548,0x0000, 0xFBC3,0xD549,0x0000, 0x1410,0x0000,0x0000, /* 1D548 */ +0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x147B,0x0000,0x0000, /* 1D54B */ +0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, 0x149C,0x0000,0x0000, /* 1D54E */ +0xFBC3,0xD551,0x0000, 0x120F,0x0000,0x0000, 0x1225,0x0000,0x0000, /* 1D551 */ +0x123D,0x0000,0x0000, 0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 1D554 */ +0x12A3,0x0000,0x0000, 0x12B0,0x0000,0x0000, 0x12D3,0x0000,0x0000, /* 1D557 */ +0x12EC,0x0000,0x0000, 0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, /* 1D55A */ +0x1330,0x0000,0x0000, 0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, /* 1D55D */ +0x138E,0x0000,0x0000, 0x13B3,0x0000,0x0000, 0x13C8,0x0000,0x0000, /* 1D560 */ +0x13DA,0x0000,0x0000, 0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, /* 1D563 */ +0x1453,0x0000,0x0000, 0x147B,0x0000,0x0000, 0x148D,0x0000,0x0000, /* 1D566 */ +0x1497,0x0000,0x0000, 0x149C,0x0000,0x0000, 0x14AD,0x0000,0x0000, /* 1D569 */ +0x120F,0x0000,0x0000, 0x1225,0x0000,0x0000, 0x123D,0x0000,0x0000, /* 1D56C */ +0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x12A3,0x0000,0x0000, /* 1D56F */ +0x12B0,0x0000,0x0000, 0x12D3,0x0000,0x0000, 0x12EC,0x0000,0x0000, /* 1D572 */ +0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, /* 1D575 */ +0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1D578 */ +0x13B3,0x0000,0x0000, 0x13C8,0x0000,0x0000, 0x13DA,0x0000,0x0000, /* 1D57B */ +0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 1D57E */ +0x147B,0x0000,0x0000, 0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, /* 1D581 */ +0x149C,0x0000,0x0000, 0x14AD,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 1D584 */ +0x1225,0x0000,0x0000, 0x123D,0x0000,0x0000, 0x1250,0x0000,0x0000, /* 1D587 */ +0x126B,0x0000,0x0000, 0x12A3,0x0000,0x0000, 0x12B0,0x0000,0x0000, /* 1D58A */ +0x12D3,0x0000,0x0000, 0x12EC,0x0000,0x0000, 0x1305,0x0000,0x0000, /* 1D58D */ +0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, 0x135F,0x0000,0x0000, /* 1D590 */ +0x136D,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x13B3,0x0000,0x0000, /* 1D593 */ +0x13C8,0x0000,0x0000, 0x13DA,0x0000,0x0000, 0x1410,0x0000,0x0000, /* 1D596 */ +0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x147B,0x0000,0x0000, /* 1D599 */ +0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, 0x149C,0x0000,0x0000, /* 1D59C */ +0x14AD,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x1225,0x0000,0x0000, /* 1D59F */ +0x123D,0x0000,0x0000, 0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 1D5A2 */ +0x12A3,0x0000,0x0000, 0x12B0,0x0000,0x0000, 0x12D3,0x0000,0x0000, /* 1D5A5 */ +0x12EC,0x0000,0x0000, 0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, /* 1D5A8 */ +0x1330,0x0000,0x0000, 0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, /* 1D5AB */ +0x138E,0x0000,0x0000, 0x13B3,0x0000,0x0000, 0x13C8,0x0000,0x0000, /* 1D5AE */ +0x13DA,0x0000,0x0000, 0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, /* 1D5B1 */ +0x1453,0x0000,0x0000, 0x147B,0x0000,0x0000, 0x148D,0x0000,0x0000, /* 1D5B4 */ +0x1497,0x0000,0x0000, 0x149C,0x0000,0x0000, 0x14AD,0x0000,0x0000, /* 1D5B7 */ +0x120F,0x0000,0x0000, 0x1225,0x0000,0x0000, 0x123D,0x0000,0x0000, /* 1D5BA */ +0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x12A3,0x0000,0x0000, /* 1D5BD */ +0x12B0,0x0000,0x0000, 0x12D3,0x0000,0x0000, 0x12EC,0x0000,0x0000, /* 1D5C0 */ +0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, /* 1D5C3 */ +0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1D5C6 */ +0x13B3,0x0000,0x0000, 0x13C8,0x0000,0x0000, 0x13DA,0x0000,0x0000, /* 1D5C9 */ +0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 1D5CC */ +0x147B,0x0000,0x0000, 0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, /* 1D5CF */ +0x149C,0x0000,0x0000, 0x14AD,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 1D5D2 */ +0x1225,0x0000,0x0000, 0x123D,0x0000,0x0000, 0x1250,0x0000,0x0000, /* 1D5D5 */ +0x126B,0x0000,0x0000, 0x12A3,0x0000,0x0000, 0x12B0,0x0000,0x0000, /* 1D5D8 */ +0x12D3,0x0000,0x0000, 0x12EC,0x0000,0x0000, 0x1305,0x0000,0x0000, /* 1D5DB */ +0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, 0x135F,0x0000,0x0000, /* 1D5DE */ +0x136D,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x13B3,0x0000,0x0000, /* 1D5E1 */ +0x13C8,0x0000,0x0000, 0x13DA,0x0000,0x0000, 0x1410,0x0000,0x0000, /* 1D5E4 */ +0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x147B,0x0000,0x0000, /* 1D5E7 */ +0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, 0x149C,0x0000,0x0000, /* 1D5EA */ +0x14AD,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x1225,0x0000,0x0000, /* 1D5ED */ +0x123D,0x0000,0x0000, 0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 1D5F0 */ +0x12A3,0x0000,0x0000, 0x12B0,0x0000,0x0000, 0x12D3,0x0000,0x0000, /* 1D5F3 */ +0x12EC,0x0000,0x0000, 0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, /* 1D5F6 */ +0x1330,0x0000,0x0000, 0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, /* 1D5F9 */ +0x138E,0x0000,0x0000, 0x13B3,0x0000,0x0000, 0x13C8,0x0000,0x0000, /* 1D5FC */ +0x13DA,0x0000,0x0000 }; + +uint16 uca520_p1D6[]= { /* 1D600 (3 weights per char) */ +0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 1D600 */ +0x147B,0x0000,0x0000, 0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, /* 1D603 */ +0x149C,0x0000,0x0000, 0x14AD,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 1D606 */ +0x1225,0x0000,0x0000, 0x123D,0x0000,0x0000, 0x1250,0x0000,0x0000, /* 1D609 */ +0x126B,0x0000,0x0000, 0x12A3,0x0000,0x0000, 0x12B0,0x0000,0x0000, /* 1D60C */ +0x12D3,0x0000,0x0000, 0x12EC,0x0000,0x0000, 0x1305,0x0000,0x0000, /* 1D60F */ +0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, 0x135F,0x0000,0x0000, /* 1D612 */ +0x136D,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x13B3,0x0000,0x0000, /* 1D615 */ +0x13C8,0x0000,0x0000, 0x13DA,0x0000,0x0000, 0x1410,0x0000,0x0000, /* 1D618 */ +0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x147B,0x0000,0x0000, /* 1D61B */ +0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, 0x149C,0x0000,0x0000, /* 1D61E */ +0x14AD,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x1225,0x0000,0x0000, /* 1D621 */ +0x123D,0x0000,0x0000, 0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 1D624 */ +0x12A3,0x0000,0x0000, 0x12B0,0x0000,0x0000, 0x12D3,0x0000,0x0000, /* 1D627 */ +0x12EC,0x0000,0x0000, 0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, /* 1D62A */ +0x1330,0x0000,0x0000, 0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, /* 1D62D */ +0x138E,0x0000,0x0000, 0x13B3,0x0000,0x0000, 0x13C8,0x0000,0x0000, /* 1D630 */ +0x13DA,0x0000,0x0000, 0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, /* 1D633 */ +0x1453,0x0000,0x0000, 0x147B,0x0000,0x0000, 0x148D,0x0000,0x0000, /* 1D636 */ +0x1497,0x0000,0x0000, 0x149C,0x0000,0x0000, 0x14AD,0x0000,0x0000, /* 1D639 */ +0x120F,0x0000,0x0000, 0x1225,0x0000,0x0000, 0x123D,0x0000,0x0000, /* 1D63C */ +0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x12A3,0x0000,0x0000, /* 1D63F */ +0x12B0,0x0000,0x0000, 0x12D3,0x0000,0x0000, 0x12EC,0x0000,0x0000, /* 1D642 */ +0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, /* 1D645 */ +0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1D648 */ +0x13B3,0x0000,0x0000, 0x13C8,0x0000,0x0000, 0x13DA,0x0000,0x0000, /* 1D64B */ +0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 1D64E */ +0x147B,0x0000,0x0000, 0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, /* 1D651 */ +0x149C,0x0000,0x0000, 0x14AD,0x0000,0x0000, 0x120F,0x0000,0x0000, /* 1D654 */ +0x1225,0x0000,0x0000, 0x123D,0x0000,0x0000, 0x1250,0x0000,0x0000, /* 1D657 */ +0x126B,0x0000,0x0000, 0x12A3,0x0000,0x0000, 0x12B0,0x0000,0x0000, /* 1D65A */ +0x12D3,0x0000,0x0000, 0x12EC,0x0000,0x0000, 0x1305,0x0000,0x0000, /* 1D65D */ +0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, 0x135F,0x0000,0x0000, /* 1D660 */ +0x136D,0x0000,0x0000, 0x138E,0x0000,0x0000, 0x13B3,0x0000,0x0000, /* 1D663 */ +0x13C8,0x0000,0x0000, 0x13DA,0x0000,0x0000, 0x1410,0x0000,0x0000, /* 1D666 */ +0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, 0x147B,0x0000,0x0000, /* 1D669 */ +0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, 0x149C,0x0000,0x0000, /* 1D66C */ +0x14AD,0x0000,0x0000, 0x120F,0x0000,0x0000, 0x1225,0x0000,0x0000, /* 1D66F */ +0x123D,0x0000,0x0000, 0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, /* 1D672 */ +0x12A3,0x0000,0x0000, 0x12B0,0x0000,0x0000, 0x12D3,0x0000,0x0000, /* 1D675 */ +0x12EC,0x0000,0x0000, 0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, /* 1D678 */ +0x1330,0x0000,0x0000, 0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, /* 1D67B */ +0x138E,0x0000,0x0000, 0x13B3,0x0000,0x0000, 0x13C8,0x0000,0x0000, /* 1D67E */ +0x13DA,0x0000,0x0000, 0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, /* 1D681 */ +0x1453,0x0000,0x0000, 0x147B,0x0000,0x0000, 0x148D,0x0000,0x0000, /* 1D684 */ +0x1497,0x0000,0x0000, 0x149C,0x0000,0x0000, 0x14AD,0x0000,0x0000, /* 1D687 */ +0x120F,0x0000,0x0000, 0x1225,0x0000,0x0000, 0x123D,0x0000,0x0000, /* 1D68A */ +0x1250,0x0000,0x0000, 0x126B,0x0000,0x0000, 0x12A3,0x0000,0x0000, /* 1D68D */ +0x12B0,0x0000,0x0000, 0x12D3,0x0000,0x0000, 0x12EC,0x0000,0x0000, /* 1D690 */ +0x1305,0x0000,0x0000, 0x131E,0x0000,0x0000, 0x1330,0x0000,0x0000, /* 1D693 */ +0x135F,0x0000,0x0000, 0x136D,0x0000,0x0000, 0x138E,0x0000,0x0000, /* 1D696 */ +0x13B3,0x0000,0x0000, 0x13C8,0x0000,0x0000, 0x13DA,0x0000,0x0000, /* 1D699 */ +0x1410,0x0000,0x0000, 0x1433,0x0000,0x0000, 0x1453,0x0000,0x0000, /* 1D69C */ +0x147B,0x0000,0x0000, 0x148D,0x0000,0x0000, 0x1497,0x0000,0x0000, /* 1D69F */ +0x149C,0x0000,0x0000, 0x14AD,0x0000,0x0000, 0x12F0,0x0000,0x0000, /* 1D6A2 */ +0x1309,0x0000,0x0000, 0xFBC3,0xD6A6,0x0000, 0xFBC3,0xD6A7,0x0000, /* 1D6A5 */ +0x1545,0x0000,0x0000, 0x1546,0x0000,0x0000, 0x1547,0x0000,0x0000, /* 1D6A8 */ +0x1549,0x0000,0x0000, 0x154A,0x0000,0x0000, 0x154E,0x0000,0x0000, /* 1D6AB */ +0x1550,0x0000,0x0000, 0x1551,0x0000,0x0000, 0x1552,0x0000,0x0000, /* 1D6AE */ +0x1554,0x0000,0x0000, 0x1555,0x0000,0x0000, 0x1557,0x0000,0x0000, /* 1D6B1 */ +0x1558,0x0000,0x0000, 0x1559,0x0000,0x0000, 0x155A,0x0000,0x0000, /* 1D6B4 */ +0x155B,0x0000,0x0000, 0x1560,0x0000,0x0000, 0x1551,0x0000,0x0000, /* 1D6B7 */ +0x1563,0x0000,0x0000, 0x1567,0x0000,0x0000, 0x1568,0x0000,0x0000, /* 1D6BA */ +0x1569,0x0000,0x0000, 0x156A,0x0000,0x0000, 0x156B,0x0000,0x0000, /* 1D6BD */ +0x156D,0x0000,0x0000, 0x0546,0x0000,0x0000, 0x1545,0x0000,0x0000, /* 1D6C0 */ +0x1546,0x0000,0x0000, 0x1547,0x0000,0x0000, 0x1549,0x0000,0x0000, /* 1D6C3 */ +0x154A,0x0000,0x0000, 0x154E,0x0000,0x0000, 0x1550,0x0000,0x0000, /* 1D6C6 */ +0x1551,0x0000,0x0000, 0x1552,0x0000,0x0000, 0x1554,0x0000,0x0000, /* 1D6C9 */ +0x1555,0x0000,0x0000, 0x1557,0x0000,0x0000, 0x1558,0x0000,0x0000, /* 1D6CC */ +0x1559,0x0000,0x0000, 0x155A,0x0000,0x0000, 0x155B,0x0000,0x0000, /* 1D6CF */ +0x1560,0x0000,0x0000, 0x1563,0x0000,0x0000, 0x1563,0x0000,0x0000, /* 1D6D2 */ +0x1567,0x0000,0x0000, 0x1568,0x0000,0x0000, 0x1569,0x0000,0x0000, /* 1D6D5 */ +0x156A,0x0000,0x0000, 0x156B,0x0000,0x0000, 0x156D,0x0000,0x0000, /* 1D6D8 */ +0x0542,0x0000,0x0000, 0x154A,0x0000,0x0000, 0x1551,0x0000,0x0000, /* 1D6DB */ +0x1554,0x0000,0x0000, 0x1569,0x0000,0x0000, 0x1560,0x0000,0x0000, /* 1D6DE */ +0x155B,0x0000,0x0000, 0x1545,0x0000,0x0000, 0x1546,0x0000,0x0000, /* 1D6E1 */ +0x1547,0x0000,0x0000, 0x1549,0x0000,0x0000, 0x154A,0x0000,0x0000, /* 1D6E4 */ +0x154E,0x0000,0x0000, 0x1550,0x0000,0x0000, 0x1551,0x0000,0x0000, /* 1D6E7 */ +0x1552,0x0000,0x0000, 0x1554,0x0000,0x0000, 0x1555,0x0000,0x0000, /* 1D6EA */ +0x1557,0x0000,0x0000, 0x1558,0x0000,0x0000, 0x1559,0x0000,0x0000, /* 1D6ED */ +0x155A,0x0000,0x0000, 0x155B,0x0000,0x0000, 0x1560,0x0000,0x0000, /* 1D6F0 */ +0x1551,0x0000,0x0000, 0x1563,0x0000,0x0000, 0x1567,0x0000,0x0000, /* 1D6F3 */ +0x1568,0x0000,0x0000, 0x1569,0x0000,0x0000, 0x156A,0x0000,0x0000, /* 1D6F6 */ +0x156B,0x0000,0x0000, 0x156D,0x0000,0x0000, 0x0546,0x0000,0x0000, /* 1D6F9 */ +0x1545,0x0000,0x0000, 0x1546,0x0000,0x0000, 0x1547,0x0000,0x0000, /* 1D6FC */ +0x1549,0x0000,0x0000 }; + +uint16 uca520_p1D7[]= { /* 1D700 (3 weights per char) */ +0x154A,0x0000,0x0000, 0x154E,0x0000,0x0000, 0x1550,0x0000,0x0000, /* 1D700 */ +0x1551,0x0000,0x0000, 0x1552,0x0000,0x0000, 0x1554,0x0000,0x0000, /* 1D703 */ +0x1555,0x0000,0x0000, 0x1557,0x0000,0x0000, 0x1558,0x0000,0x0000, /* 1D706 */ +0x1559,0x0000,0x0000, 0x155A,0x0000,0x0000, 0x155B,0x0000,0x0000, /* 1D709 */ +0x1560,0x0000,0x0000, 0x1563,0x0000,0x0000, 0x1563,0x0000,0x0000, /* 1D70C */ +0x1567,0x0000,0x0000, 0x1568,0x0000,0x0000, 0x1569,0x0000,0x0000, /* 1D70F */ +0x156A,0x0000,0x0000, 0x156B,0x0000,0x0000, 0x156D,0x0000,0x0000, /* 1D712 */ +0x0542,0x0000,0x0000, 0x154A,0x0000,0x0000, 0x1551,0x0000,0x0000, /* 1D715 */ +0x1554,0x0000,0x0000, 0x1569,0x0000,0x0000, 0x1560,0x0000,0x0000, /* 1D718 */ +0x155B,0x0000,0x0000, 0x1545,0x0000,0x0000, 0x1546,0x0000,0x0000, /* 1D71B */ +0x1547,0x0000,0x0000, 0x1549,0x0000,0x0000, 0x154A,0x0000,0x0000, /* 1D71E */ +0x154E,0x0000,0x0000, 0x1550,0x0000,0x0000, 0x1551,0x0000,0x0000, /* 1D721 */ +0x1552,0x0000,0x0000, 0x1554,0x0000,0x0000, 0x1555,0x0000,0x0000, /* 1D724 */ +0x1557,0x0000,0x0000, 0x1558,0x0000,0x0000, 0x1559,0x0000,0x0000, /* 1D727 */ +0x155A,0x0000,0x0000, 0x155B,0x0000,0x0000, 0x1560,0x0000,0x0000, /* 1D72A */ +0x1551,0x0000,0x0000, 0x1563,0x0000,0x0000, 0x1567,0x0000,0x0000, /* 1D72D */ +0x1568,0x0000,0x0000, 0x1569,0x0000,0x0000, 0x156A,0x0000,0x0000, /* 1D730 */ +0x156B,0x0000,0x0000, 0x156D,0x0000,0x0000, 0x0546,0x0000,0x0000, /* 1D733 */ +0x1545,0x0000,0x0000, 0x1546,0x0000,0x0000, 0x1547,0x0000,0x0000, /* 1D736 */ +0x1549,0x0000,0x0000, 0x154A,0x0000,0x0000, 0x154E,0x0000,0x0000, /* 1D739 */ +0x1550,0x0000,0x0000, 0x1551,0x0000,0x0000, 0x1552,0x0000,0x0000, /* 1D73C */ +0x1554,0x0000,0x0000, 0x1555,0x0000,0x0000, 0x1557,0x0000,0x0000, /* 1D73F */ +0x1558,0x0000,0x0000, 0x1559,0x0000,0x0000, 0x155A,0x0000,0x0000, /* 1D742 */ +0x155B,0x0000,0x0000, 0x1560,0x0000,0x0000, 0x1563,0x0000,0x0000, /* 1D745 */ +0x1563,0x0000,0x0000, 0x1567,0x0000,0x0000, 0x1568,0x0000,0x0000, /* 1D748 */ +0x1569,0x0000,0x0000, 0x156A,0x0000,0x0000, 0x156B,0x0000,0x0000, /* 1D74B */ +0x156D,0x0000,0x0000, 0x0542,0x0000,0x0000, 0x154A,0x0000,0x0000, /* 1D74E */ +0x1551,0x0000,0x0000, 0x1554,0x0000,0x0000, 0x1569,0x0000,0x0000, /* 1D751 */ +0x1560,0x0000,0x0000, 0x155B,0x0000,0x0000, 0x1545,0x0000,0x0000, /* 1D754 */ +0x1546,0x0000,0x0000, 0x1547,0x0000,0x0000, 0x1549,0x0000,0x0000, /* 1D757 */ +0x154A,0x0000,0x0000, 0x154E,0x0000,0x0000, 0x1550,0x0000,0x0000, /* 1D75A */ +0x1551,0x0000,0x0000, 0x1552,0x0000,0x0000, 0x1554,0x0000,0x0000, /* 1D75D */ +0x1555,0x0000,0x0000, 0x1557,0x0000,0x0000, 0x1558,0x0000,0x0000, /* 1D760 */ +0x1559,0x0000,0x0000, 0x155A,0x0000,0x0000, 0x155B,0x0000,0x0000, /* 1D763 */ +0x1560,0x0000,0x0000, 0x1551,0x0000,0x0000, 0x1563,0x0000,0x0000, /* 1D766 */ +0x1567,0x0000,0x0000, 0x1568,0x0000,0x0000, 0x1569,0x0000,0x0000, /* 1D769 */ +0x156A,0x0000,0x0000, 0x156B,0x0000,0x0000, 0x156D,0x0000,0x0000, /* 1D76C */ +0x0546,0x0000,0x0000, 0x1545,0x0000,0x0000, 0x1546,0x0000,0x0000, /* 1D76F */ +0x1547,0x0000,0x0000, 0x1549,0x0000,0x0000, 0x154A,0x0000,0x0000, /* 1D772 */ +0x154E,0x0000,0x0000, 0x1550,0x0000,0x0000, 0x1551,0x0000,0x0000, /* 1D775 */ +0x1552,0x0000,0x0000, 0x1554,0x0000,0x0000, 0x1555,0x0000,0x0000, /* 1D778 */ +0x1557,0x0000,0x0000, 0x1558,0x0000,0x0000, 0x1559,0x0000,0x0000, /* 1D77B */ +0x155A,0x0000,0x0000, 0x155B,0x0000,0x0000, 0x1560,0x0000,0x0000, /* 1D77E */ +0x1563,0x0000,0x0000, 0x1563,0x0000,0x0000, 0x1567,0x0000,0x0000, /* 1D781 */ +0x1568,0x0000,0x0000, 0x1569,0x0000,0x0000, 0x156A,0x0000,0x0000, /* 1D784 */ +0x156B,0x0000,0x0000, 0x156D,0x0000,0x0000, 0x0542,0x0000,0x0000, /* 1D787 */ +0x154A,0x0000,0x0000, 0x1551,0x0000,0x0000, 0x1554,0x0000,0x0000, /* 1D78A */ +0x1569,0x0000,0x0000, 0x1560,0x0000,0x0000, 0x155B,0x0000,0x0000, /* 1D78D */ +0x1545,0x0000,0x0000, 0x1546,0x0000,0x0000, 0x1547,0x0000,0x0000, /* 1D790 */ +0x1549,0x0000,0x0000, 0x154A,0x0000,0x0000, 0x154E,0x0000,0x0000, /* 1D793 */ +0x1550,0x0000,0x0000, 0x1551,0x0000,0x0000, 0x1552,0x0000,0x0000, /* 1D796 */ +0x1554,0x0000,0x0000, 0x1555,0x0000,0x0000, 0x1557,0x0000,0x0000, /* 1D799 */ +0x1558,0x0000,0x0000, 0x1559,0x0000,0x0000, 0x155A,0x0000,0x0000, /* 1D79C */ +0x155B,0x0000,0x0000, 0x1560,0x0000,0x0000, 0x1551,0x0000,0x0000, /* 1D79F */ +0x1563,0x0000,0x0000, 0x1567,0x0000,0x0000, 0x1568,0x0000,0x0000, /* 1D7A2 */ +0x1569,0x0000,0x0000, 0x156A,0x0000,0x0000, 0x156B,0x0000,0x0000, /* 1D7A5 */ +0x156D,0x0000,0x0000, 0x0546,0x0000,0x0000, 0x1545,0x0000,0x0000, /* 1D7A8 */ +0x1546,0x0000,0x0000, 0x1547,0x0000,0x0000, 0x1549,0x0000,0x0000, /* 1D7AB */ +0x154A,0x0000,0x0000, 0x154E,0x0000,0x0000, 0x1550,0x0000,0x0000, /* 1D7AE */ +0x1551,0x0000,0x0000, 0x1552,0x0000,0x0000, 0x1554,0x0000,0x0000, /* 1D7B1 */ +0x1555,0x0000,0x0000, 0x1557,0x0000,0x0000, 0x1558,0x0000,0x0000, /* 1D7B4 */ +0x1559,0x0000,0x0000, 0x155A,0x0000,0x0000, 0x155B,0x0000,0x0000, /* 1D7B7 */ +0x1560,0x0000,0x0000, 0x1563,0x0000,0x0000, 0x1563,0x0000,0x0000, /* 1D7BA */ +0x1567,0x0000,0x0000, 0x1568,0x0000,0x0000, 0x1569,0x0000,0x0000, /* 1D7BD */ +0x156A,0x0000,0x0000, 0x156B,0x0000,0x0000, 0x156D,0x0000,0x0000, /* 1D7C0 */ +0x0542,0x0000,0x0000, 0x154A,0x0000,0x0000, 0x1551,0x0000,0x0000, /* 1D7C3 */ +0x1554,0x0000,0x0000, 0x1569,0x0000,0x0000, 0x1560,0x0000,0x0000, /* 1D7C6 */ +0x155B,0x0000,0x0000, 0x154B,0x0000,0x0000, 0x154B,0x0000,0x0000, /* 1D7C9 */ +0xFBC3,0xD7CC,0x0000, 0xFBC3,0xD7CD,0x0000, 0x1205,0x0000,0x0000, /* 1D7CC */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 1D7CF */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 1D7D2 */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 1D7D5 */ +0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 1D7D8 */ +0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, /* 1D7DB */ +0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, /* 1D7DE */ +0x120E,0x0000,0x0000, 0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, /* 1D7E1 */ +0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, /* 1D7E4 */ +0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, /* 1D7E7 */ +0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, 0x1205,0x0000,0x0000, /* 1D7EA */ +0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, 0x1208,0x0000,0x0000, /* 1D7ED */ +0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, 0x120B,0x0000,0x0000, /* 1D7F0 */ +0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, 0x120E,0x0000,0x0000, /* 1D7F3 */ +0x1205,0x0000,0x0000, 0x1206,0x0000,0x0000, 0x1207,0x0000,0x0000, /* 1D7F6 */ +0x1208,0x0000,0x0000, 0x1209,0x0000,0x0000, 0x120A,0x0000,0x0000, /* 1D7F9 */ +0x120B,0x0000,0x0000, 0x120C,0x0000,0x0000, 0x120D,0x0000,0x0000, /* 1D7FC */ +0x120E,0x0000,0x0000 }; + +uint16 uca520_p1F0[]= { /* 1F000 (3 weights per char) */ +0x1044,0x0000,0x0000, 0x1045,0x0000,0x0000, 0x1046,0x0000,0x0000, /* 1F000 */ +0x1047,0x0000,0x0000, 0x1048,0x0000,0x0000, 0x1049,0x0000,0x0000, /* 1F003 */ +0x104A,0x0000,0x0000, 0x104B,0x0000,0x0000, 0x104C,0x0000,0x0000, /* 1F006 */ +0x104D,0x0000,0x0000, 0x104E,0x0000,0x0000, 0x104F,0x0000,0x0000, /* 1F009 */ +0x1050,0x0000,0x0000, 0x1051,0x0000,0x0000, 0x1052,0x0000,0x0000, /* 1F00C */ +0x1053,0x0000,0x0000, 0x1054,0x0000,0x0000, 0x1055,0x0000,0x0000, /* 1F00F */ +0x1056,0x0000,0x0000, 0x1057,0x0000,0x0000, 0x1058,0x0000,0x0000, /* 1F012 */ +0x1059,0x0000,0x0000, 0x105A,0x0000,0x0000, 0x105B,0x0000,0x0000, /* 1F015 */ +0x105C,0x0000,0x0000, 0x105D,0x0000,0x0000, 0x105E,0x0000,0x0000, /* 1F018 */ +0x105F,0x0000,0x0000, 0x1060,0x0000,0x0000, 0x1061,0x0000,0x0000, /* 1F01B */ +0x1062,0x0000,0x0000, 0x1063,0x0000,0x0000, 0x1064,0x0000,0x0000, /* 1F01E */ +0x1065,0x0000,0x0000, 0x1066,0x0000,0x0000, 0x1067,0x0000,0x0000, /* 1F021 */ +0x1068,0x0000,0x0000, 0x1069,0x0000,0x0000, 0x106A,0x0000,0x0000, /* 1F024 */ +0x106B,0x0000,0x0000, 0x106C,0x0000,0x0000, 0x106D,0x0000,0x0000, /* 1F027 */ +0x106E,0x0000,0x0000, 0x106F,0x0000,0x0000, 0xFBC3,0xF02C,0x0000, /* 1F02A */ +0xFBC3,0xF02D,0x0000, 0xFBC3,0xF02E,0x0000, 0xFBC3,0xF02F,0x0000, /* 1F02D */ +0x1070,0x0000,0x0000, 0x1071,0x0000,0x0000, 0x1072,0x0000,0x0000, /* 1F030 */ +0x1073,0x0000,0x0000, 0x1074,0x0000,0x0000, 0x1075,0x0000,0x0000, /* 1F033 */ +0x1076,0x0000,0x0000, 0x1077,0x0000,0x0000, 0x1078,0x0000,0x0000, /* 1F036 */ +0x1079,0x0000,0x0000, 0x107A,0x0000,0x0000, 0x107B,0x0000,0x0000, /* 1F039 */ +0x107C,0x0000,0x0000, 0x107D,0x0000,0x0000, 0x107E,0x0000,0x0000, /* 1F03C */ +0x107F,0x0000,0x0000, 0x1080,0x0000,0x0000, 0x1081,0x0000,0x0000, /* 1F03F */ +0x1082,0x0000,0x0000, 0x1083,0x0000,0x0000, 0x1084,0x0000,0x0000, /* 1F042 */ +0x1085,0x0000,0x0000, 0x1086,0x0000,0x0000, 0x1087,0x0000,0x0000, /* 1F045 */ +0x1088,0x0000,0x0000, 0x1089,0x0000,0x0000, 0x108A,0x0000,0x0000, /* 1F048 */ +0x108B,0x0000,0x0000, 0x108C,0x0000,0x0000, 0x108D,0x0000,0x0000, /* 1F04B */ +0x108E,0x0000,0x0000, 0x108F,0x0000,0x0000, 0x1090,0x0000,0x0000, /* 1F04E */ +0x1091,0x0000,0x0000, 0x1092,0x0000,0x0000, 0x1093,0x0000,0x0000, /* 1F051 */ +0x1094,0x0000,0x0000, 0x1095,0x0000,0x0000, 0x1096,0x0000,0x0000, /* 1F054 */ +0x1097,0x0000,0x0000, 0x1098,0x0000,0x0000, 0x1099,0x0000,0x0000, /* 1F057 */ +0x109A,0x0000,0x0000, 0x109B,0x0000,0x0000, 0x109C,0x0000,0x0000, /* 1F05A */ +0x109D,0x0000,0x0000, 0x109E,0x0000,0x0000, 0x109F,0x0000,0x0000, /* 1F05D */ +0x10A0,0x0000,0x0000, 0x10A1,0x0000,0x0000, 0x10A2,0x0000,0x0000, /* 1F060 */ +0x10A3,0x0000,0x0000, 0x10A4,0x0000,0x0000, 0x10A5,0x0000,0x0000, /* 1F063 */ +0x10A6,0x0000,0x0000, 0x10A7,0x0000,0x0000, 0x10A8,0x0000,0x0000, /* 1F066 */ +0x10A9,0x0000,0x0000, 0x10AA,0x0000,0x0000, 0x10AB,0x0000,0x0000, /* 1F069 */ +0x10AC,0x0000,0x0000, 0x10AD,0x0000,0x0000, 0x10AE,0x0000,0x0000, /* 1F06C */ +0x10AF,0x0000,0x0000, 0x10B0,0x0000,0x0000, 0x10B1,0x0000,0x0000, /* 1F06F */ +0x10B2,0x0000,0x0000, 0x10B3,0x0000,0x0000, 0x10B4,0x0000,0x0000, /* 1F072 */ +0x10B5,0x0000,0x0000, 0x10B6,0x0000,0x0000, 0x10B7,0x0000,0x0000, /* 1F075 */ +0x10B8,0x0000,0x0000, 0x10B9,0x0000,0x0000, 0x10BA,0x0000,0x0000, /* 1F078 */ +0x10BB,0x0000,0x0000, 0x10BC,0x0000,0x0000, 0x10BD,0x0000,0x0000, /* 1F07B */ +0x10BE,0x0000,0x0000, 0x10BF,0x0000,0x0000, 0x10C0,0x0000,0x0000, /* 1F07E */ +0x10C1,0x0000,0x0000, 0x10C2,0x0000,0x0000, 0x10C3,0x0000,0x0000, /* 1F081 */ +0x10C4,0x0000,0x0000, 0x10C5,0x0000,0x0000, 0x10C6,0x0000,0x0000, /* 1F084 */ +0x10C7,0x0000,0x0000, 0x10C8,0x0000,0x0000, 0x10C9,0x0000,0x0000, /* 1F087 */ +0x10CA,0x0000,0x0000, 0x10CB,0x0000,0x0000, 0x10CC,0x0000,0x0000, /* 1F08A */ +0x10CD,0x0000,0x0000, 0x10CE,0x0000,0x0000, 0x10CF,0x0000,0x0000, /* 1F08D */ +0x10D0,0x0000,0x0000, 0x10D1,0x0000,0x0000, 0x10D2,0x0000,0x0000, /* 1F090 */ +0x10D3,0x0000,0x0000, 0xFBC3,0xF094,0x0000, 0xFBC3,0xF095,0x0000, /* 1F093 */ +0xFBC3,0xF096,0x0000, 0xFBC3,0xF097,0x0000, 0xFBC3,0xF098,0x0000, /* 1F096 */ +0xFBC3,0xF099,0x0000, 0xFBC3,0xF09A,0x0000, 0xFBC3,0xF09B,0x0000, /* 1F099 */ +0xFBC3,0xF09C,0x0000, 0xFBC3,0xF09D,0x0000, 0xFBC3,0xF09E,0x0000, /* 1F09C */ +0xFBC3,0xF09F,0x0000, 0xFBC3,0xF0A0,0x0000, 0xFBC3,0xF0A1,0x0000, /* 1F09F */ +0xFBC3,0xF0A2,0x0000, 0xFBC3,0xF0A3,0x0000, 0xFBC3,0xF0A4,0x0000, /* 1F0A2 */ +0xFBC3,0xF0A5,0x0000, 0xFBC3,0xF0A6,0x0000, 0xFBC3,0xF0A7,0x0000, /* 1F0A5 */ +0xFBC3,0xF0A8,0x0000, 0xFBC3,0xF0A9,0x0000, 0xFBC3,0xF0AA,0x0000, /* 1F0A8 */ +0xFBC3,0xF0AB,0x0000, 0xFBC3,0xF0AC,0x0000, 0xFBC3,0xF0AD,0x0000, /* 1F0AB */ +0xFBC3,0xF0AE,0x0000, 0xFBC3,0xF0AF,0x0000, 0xFBC3,0xF0B0,0x0000, /* 1F0AE */ +0xFBC3,0xF0B1,0x0000, 0xFBC3,0xF0B2,0x0000, 0xFBC3,0xF0B3,0x0000, /* 1F0B1 */ +0xFBC3,0xF0B4,0x0000, 0xFBC3,0xF0B5,0x0000, 0xFBC3,0xF0B6,0x0000, /* 1F0B4 */ +0xFBC3,0xF0B7,0x0000, 0xFBC3,0xF0B8,0x0000, 0xFBC3,0xF0B9,0x0000, /* 1F0B7 */ +0xFBC3,0xF0BA,0x0000, 0xFBC3,0xF0BB,0x0000, 0xFBC3,0xF0BC,0x0000, /* 1F0BA */ +0xFBC3,0xF0BD,0x0000, 0xFBC3,0xF0BE,0x0000, 0xFBC3,0xF0BF,0x0000, /* 1F0BD */ +0xFBC3,0xF0C0,0x0000, 0xFBC3,0xF0C1,0x0000, 0xFBC3,0xF0C2,0x0000, /* 1F0C0 */ +0xFBC3,0xF0C3,0x0000, 0xFBC3,0xF0C4,0x0000, 0xFBC3,0xF0C5,0x0000, /* 1F0C3 */ +0xFBC3,0xF0C6,0x0000, 0xFBC3,0xF0C7,0x0000, 0xFBC3,0xF0C8,0x0000, /* 1F0C6 */ +0xFBC3,0xF0C9,0x0000, 0xFBC3,0xF0CA,0x0000, 0xFBC3,0xF0CB,0x0000, /* 1F0C9 */ +0xFBC3,0xF0CC,0x0000, 0xFBC3,0xF0CD,0x0000, 0xFBC3,0xF0CE,0x0000, /* 1F0CC */ +0xFBC3,0xF0CF,0x0000, 0xFBC3,0xF0D0,0x0000, 0xFBC3,0xF0D1,0x0000, /* 1F0CF */ +0xFBC3,0xF0D2,0x0000, 0xFBC3,0xF0D3,0x0000, 0xFBC3,0xF0D4,0x0000, /* 1F0D2 */ +0xFBC3,0xF0D5,0x0000, 0xFBC3,0xF0D6,0x0000, 0xFBC3,0xF0D7,0x0000, /* 1F0D5 */ +0xFBC3,0xF0D8,0x0000, 0xFBC3,0xF0D9,0x0000, 0xFBC3,0xF0DA,0x0000, /* 1F0D8 */ +0xFBC3,0xF0DB,0x0000, 0xFBC3,0xF0DC,0x0000, 0xFBC3,0xF0DD,0x0000, /* 1F0DB */ +0xFBC3,0xF0DE,0x0000, 0xFBC3,0xF0DF,0x0000, 0xFBC3,0xF0E0,0x0000, /* 1F0DE */ +0xFBC3,0xF0E1,0x0000, 0xFBC3,0xF0E2,0x0000, 0xFBC3,0xF0E3,0x0000, /* 1F0E1 */ +0xFBC3,0xF0E4,0x0000, 0xFBC3,0xF0E5,0x0000, 0xFBC3,0xF0E6,0x0000, /* 1F0E4 */ +0xFBC3,0xF0E7,0x0000, 0xFBC3,0xF0E8,0x0000, 0xFBC3,0xF0E9,0x0000, /* 1F0E7 */ +0xFBC3,0xF0EA,0x0000, 0xFBC3,0xF0EB,0x0000, 0xFBC3,0xF0EC,0x0000, /* 1F0EA */ +0xFBC3,0xF0ED,0x0000, 0xFBC3,0xF0EE,0x0000, 0xFBC3,0xF0EF,0x0000, /* 1F0ED */ +0xFBC3,0xF0F0,0x0000, 0xFBC3,0xF0F1,0x0000, 0xFBC3,0xF0F2,0x0000, /* 1F0F0 */ +0xFBC3,0xF0F3,0x0000, 0xFBC3,0xF0F4,0x0000, 0xFBC3,0xF0F5,0x0000, /* 1F0F3 */ +0xFBC3,0xF0F6,0x0000, 0xFBC3,0xF0F7,0x0000, 0xFBC3,0xF0F8,0x0000, /* 1F0F6 */ +0xFBC3,0xF0F9,0x0000, 0xFBC3,0xF0FA,0x0000, 0xFBC3,0xF0FB,0x0000, /* 1F0F9 */ +0xFBC3,0xF0FC,0x0000, 0xFBC3,0xF0FD,0x0000, 0xFBC3,0xF0FE,0x0000, /* 1F0FC */ +0xFBC3,0xF0FF,0x0000 }; + +uint16 uca520_p1F1[]= { /* 1F100 (4 weights per char) */ +0x1205,0x0281,0x0000,0x0000, 0x1205,0x0234,0x0000,0x0000, /* 1F100 */ +0x1206,0x0234,0x0000,0x0000, 0x1207,0x0234,0x0000,0x0000, /* 1F102 */ +0x1208,0x0234,0x0000,0x0000, 0x1209,0x0234,0x0000,0x0000, /* 1F104 */ +0x120A,0x0234,0x0000,0x0000, 0x120B,0x0234,0x0000,0x0000, /* 1F106 */ +0x120C,0x0234,0x0000,0x0000, 0x120D,0x0234,0x0000,0x0000, /* 1F108 */ +0x120E,0x0234,0x0000,0x0000, 0xFBC3,0xF10B,0x0000,0x0000, /* 1F10A */ +0xFBC3,0xF10C,0x0000,0x0000, 0xFBC3,0xF10D,0x0000,0x0000, /* 1F10C */ +0xFBC3,0xF10E,0x0000,0x0000, 0xFBC3,0xF10F,0x0000,0x0000, /* 1F10E */ +0x02FF,0x120F,0x0300,0x0000, 0x02FF,0x1225,0x0300,0x0000, /* 1F110 */ +0x02FF,0x123D,0x0300,0x0000, 0x02FF,0x1250,0x0300,0x0000, /* 1F112 */ +0x02FF,0x126B,0x0300,0x0000, 0x02FF,0x12A3,0x0300,0x0000, /* 1F114 */ +0x02FF,0x12B0,0x0300,0x0000, 0x02FF,0x12D3,0x0300,0x0000, /* 1F116 */ +0x02FF,0x12EC,0x0300,0x0000, 0x02FF,0x1305,0x0300,0x0000, /* 1F118 */ +0x02FF,0x131E,0x0300,0x0000, 0x02FF,0x1330,0x0300,0x0000, /* 1F11A */ +0x02FF,0x135F,0x0300,0x0000, 0x02FF,0x136D,0x0300,0x0000, /* 1F11C */ +0x02FF,0x138E,0x0300,0x0000, 0x02FF,0x13B3,0x0300,0x0000, /* 1F11E */ +0x02FF,0x13C8,0x0300,0x0000, 0x02FF,0x13DA,0x0300,0x0000, /* 1F120 */ +0x02FF,0x1410,0x0300,0x0000, 0x02FF,0x1433,0x0300,0x0000, /* 1F122 */ +0x02FF,0x1453,0x0300,0x0000, 0x02FF,0x147B,0x0300,0x0000, /* 1F124 */ +0x02FF,0x148D,0x0300,0x0000, 0x02FF,0x1497,0x0300,0x0000, /* 1F126 */ +0x02FF,0x149C,0x0300,0x0000, 0x02FF,0x14AD,0x0300,0x0000, /* 1F128 */ +0x0347,0x1410,0x0348,0x0000, 0x123D,0x0000,0x0000,0x0000, /* 1F12A */ +0x13DA,0x0000,0x0000,0x0000, 0x123D,0x1250,0x0000,0x0000, /* 1F12C */ +0x148D,0x14AD,0x0000,0x0000, 0xFBC3,0xF12F,0x0000,0x0000, /* 1F12E */ +0xFBC3,0xF130,0x0000,0x0000, 0x1225,0x0000,0x0000,0x0000, /* 1F130 */ +0xFBC3,0xF132,0x0000,0x0000, 0xFBC3,0xF133,0x0000,0x0000, /* 1F132 */ +0xFBC3,0xF134,0x0000,0x0000, 0xFBC3,0xF135,0x0000,0x0000, /* 1F134 */ +0xFBC3,0xF136,0x0000,0x0000, 0xFBC3,0xF137,0x0000,0x0000, /* 1F136 */ +0xFBC3,0xF138,0x0000,0x0000, 0xFBC3,0xF139,0x0000,0x0000, /* 1F138 */ +0xFBC3,0xF13A,0x0000,0x0000, 0xFBC3,0xF13B,0x0000,0x0000, /* 1F13A */ +0xFBC3,0xF13C,0x0000,0x0000, 0x136D,0x0000,0x0000,0x0000, /* 1F13C */ +0xFBC3,0xF13E,0x0000,0x0000, 0x13B3,0x0000,0x0000,0x0000, /* 1F13E */ +0xFBC3,0xF140,0x0000,0x0000, 0xFBC3,0xF141,0x0000,0x0000, /* 1F140 */ +0x1410,0x0000,0x0000,0x0000, 0xFBC3,0xF143,0x0000,0x0000, /* 1F142 */ +0xFBC3,0xF144,0x0000,0x0000, 0xFBC3,0xF145,0x0000,0x0000, /* 1F144 */ +0x148D,0x0000,0x0000,0x0000, 0xFBC3,0xF147,0x0000,0x0000, /* 1F146 */ +0xFBC3,0xF148,0x0000,0x0000, 0xFBC3,0xF149,0x0000,0x0000, /* 1F148 */ +0x12D3,0x147B,0x0000,0x0000, 0x135F,0x147B,0x0000,0x0000, /* 1F14A */ +0x1410,0x1250,0x0000,0x0000, 0x1410,0x1410,0x0000,0x0000, /* 1F14C */ +0x13B3,0x13B3,0x147B,0x0000, 0xFBC3,0xF14F,0x0000,0x0000, /* 1F14E */ +0xFBC3,0xF150,0x0000,0x0000, 0xFBC3,0xF151,0x0000,0x0000, /* 1F150 */ +0xFBC3,0xF152,0x0000,0x0000, 0xFBC3,0xF153,0x0000,0x0000, /* 1F152 */ +0xFBC3,0xF154,0x0000,0x0000, 0xFBC3,0xF155,0x0000,0x0000, /* 1F154 */ +0xFBC3,0xF156,0x0000,0x0000, 0x12D3,0x0000,0x0000,0x0000, /* 1F156 */ +0xFBC3,0xF158,0x0000,0x0000, 0xFBC3,0xF159,0x0000,0x0000, /* 1F158 */ +0xFBC3,0xF15A,0x0000,0x0000, 0xFBC3,0xF15B,0x0000,0x0000, /* 1F15A */ +0xFBC3,0xF15C,0x0000,0x0000, 0xFBC3,0xF15D,0x0000,0x0000, /* 1F15C */ +0xFBC3,0xF15E,0x0000,0x0000, 0x13B3,0x0000,0x0000,0x0000, /* 1F15E */ +0xFBC3,0xF160,0x0000,0x0000, 0xFBC3,0xF161,0x0000,0x0000, /* 1F160 */ +0xFBC3,0xF162,0x0000,0x0000, 0xFBC3,0xF163,0x0000,0x0000, /* 1F162 */ +0xFBC3,0xF164,0x0000,0x0000, 0xFBC3,0xF165,0x0000,0x0000, /* 1F164 */ +0xFBC3,0xF166,0x0000,0x0000, 0xFBC3,0xF167,0x0000,0x0000, /* 1F166 */ +0xFBC3,0xF168,0x0000,0x0000, 0xFBC3,0xF169,0x0000,0x0000, /* 1F168 */ +0xFBC3,0xF16A,0x0000,0x0000, 0xFBC3,0xF16B,0x0000,0x0000, /* 1F16A */ +0xFBC3,0xF16C,0x0000,0x0000, 0xFBC3,0xF16D,0x0000,0x0000, /* 1F16C */ +0xFBC3,0xF16E,0x0000,0x0000, 0xFBC3,0xF16F,0x0000,0x0000, /* 1F16E */ +0xFBC3,0xF170,0x0000,0x0000, 0xFBC3,0xF171,0x0000,0x0000, /* 1F170 */ +0xFBC3,0xF172,0x0000,0x0000, 0xFBC3,0xF173,0x0000,0x0000, /* 1F172 */ +0xFBC3,0xF174,0x0000,0x0000, 0xFBC3,0xF175,0x0000,0x0000, /* 1F174 */ +0xFBC3,0xF176,0x0000,0x0000, 0xFBC3,0xF177,0x0000,0x0000, /* 1F176 */ +0xFBC3,0xF178,0x0000,0x0000, 0x1305,0x0000,0x0000,0x0000, /* 1F178 */ +0xFBC3,0xF17A,0x0000,0x0000, 0x1330,0x0000,0x0000,0x0000, /* 1F17A */ +0x135F,0x0000,0x0000,0x0000, 0xFBC3,0xF17D,0x0000,0x0000, /* 1F17C */ +0xFBC3,0xF17E,0x0000,0x0000, 0x13B3,0x0000,0x0000,0x0000, /* 1F17E */ +0xFBC3,0xF180,0x0000,0x0000, 0xFBC3,0xF181,0x0000,0x0000, /* 1F180 */ +0xFBC3,0xF182,0x0000,0x0000, 0xFBC3,0xF183,0x0000,0x0000, /* 1F182 */ +0xFBC3,0xF184,0x0000,0x0000, 0xFBC3,0xF185,0x0000,0x0000, /* 1F184 */ +0xFBC3,0xF186,0x0000,0x0000, 0xFBC3,0xF187,0x0000,0x0000, /* 1F186 */ +0xFBC3,0xF188,0x0000,0x0000, 0xFBC3,0xF189,0x0000,0x0000, /* 1F188 */ +0x13B3,0x0000,0x0000,0x0000, 0x12EC,0x123D,0x0000,0x0000, /* 1F18A */ +0x13B3,0x120F,0x0000,0x0000, 0x1410,0x120F,0x0000,0x0000, /* 1F18C */ +0xFBC3,0xF18E,0x0000,0x0000, 0xFBC3,0xF18F,0x0000,0x0000, /* 1F18E */ +0x1250,0x1305,0x0000,0x0000, 0xFBC3,0xF191,0x0000,0x0000, /* 1F190 */ +0xFBC3,0xF192,0x0000,0x0000, 0xFBC3,0xF193,0x0000,0x0000, /* 1F192 */ +0xFBC3,0xF194,0x0000,0x0000, 0xFBC3,0xF195,0x0000,0x0000, /* 1F194 */ +0xFBC3,0xF196,0x0000,0x0000, 0xFBC3,0xF197,0x0000,0x0000, /* 1F196 */ +0xFBC3,0xF198,0x0000,0x0000, 0xFBC3,0xF199,0x0000,0x0000, /* 1F198 */ +0xFBC3,0xF19A,0x0000,0x0000, 0xFBC3,0xF19B,0x0000,0x0000, /* 1F19A */ +0xFBC3,0xF19C,0x0000,0x0000, 0xFBC3,0xF19D,0x0000,0x0000, /* 1F19C */ +0xFBC3,0xF19E,0x0000,0x0000, 0xFBC3,0xF19F,0x0000,0x0000, /* 1F19E */ +0xFBC3,0xF1A0,0x0000,0x0000, 0xFBC3,0xF1A1,0x0000,0x0000, /* 1F1A0 */ +0xFBC3,0xF1A2,0x0000,0x0000, 0xFBC3,0xF1A3,0x0000,0x0000, /* 1F1A2 */ +0xFBC3,0xF1A4,0x0000,0x0000, 0xFBC3,0xF1A5,0x0000,0x0000, /* 1F1A4 */ +0xFBC3,0xF1A6,0x0000,0x0000, 0xFBC3,0xF1A7,0x0000,0x0000, /* 1F1A6 */ +0xFBC3,0xF1A8,0x0000,0x0000, 0xFBC3,0xF1A9,0x0000,0x0000, /* 1F1A8 */ +0xFBC3,0xF1AA,0x0000,0x0000, 0xFBC3,0xF1AB,0x0000,0x0000, /* 1F1AA */ +0xFBC3,0xF1AC,0x0000,0x0000, 0xFBC3,0xF1AD,0x0000,0x0000, /* 1F1AC */ +0xFBC3,0xF1AE,0x0000,0x0000, 0xFBC3,0xF1AF,0x0000,0x0000, /* 1F1AE */ +0xFBC3,0xF1B0,0x0000,0x0000, 0xFBC3,0xF1B1,0x0000,0x0000, /* 1F1B0 */ +0xFBC3,0xF1B2,0x0000,0x0000, 0xFBC3,0xF1B3,0x0000,0x0000, /* 1F1B2 */ +0xFBC3,0xF1B4,0x0000,0x0000, 0xFBC3,0xF1B5,0x0000,0x0000, /* 1F1B4 */ +0xFBC3,0xF1B6,0x0000,0x0000, 0xFBC3,0xF1B7,0x0000,0x0000, /* 1F1B6 */ +0xFBC3,0xF1B8,0x0000,0x0000, 0xFBC3,0xF1B9,0x0000,0x0000, /* 1F1B8 */ +0xFBC3,0xF1BA,0x0000,0x0000, 0xFBC3,0xF1BB,0x0000,0x0000, /* 1F1BA */ +0xFBC3,0xF1BC,0x0000,0x0000, 0xFBC3,0xF1BD,0x0000,0x0000, /* 1F1BC */ +0xFBC3,0xF1BE,0x0000,0x0000, 0xFBC3,0xF1BF,0x0000,0x0000, /* 1F1BE */ +0xFBC3,0xF1C0,0x0000,0x0000, 0xFBC3,0xF1C1,0x0000,0x0000, /* 1F1C0 */ +0xFBC3,0xF1C2,0x0000,0x0000, 0xFBC3,0xF1C3,0x0000,0x0000, /* 1F1C2 */ +0xFBC3,0xF1C4,0x0000,0x0000, 0xFBC3,0xF1C5,0x0000,0x0000, /* 1F1C4 */ +0xFBC3,0xF1C6,0x0000,0x0000, 0xFBC3,0xF1C7,0x0000,0x0000, /* 1F1C6 */ +0xFBC3,0xF1C8,0x0000,0x0000, 0xFBC3,0xF1C9,0x0000,0x0000, /* 1F1C8 */ +0xFBC3,0xF1CA,0x0000,0x0000, 0xFBC3,0xF1CB,0x0000,0x0000, /* 1F1CA */ +0xFBC3,0xF1CC,0x0000,0x0000, 0xFBC3,0xF1CD,0x0000,0x0000, /* 1F1CC */ +0xFBC3,0xF1CE,0x0000,0x0000, 0xFBC3,0xF1CF,0x0000,0x0000, /* 1F1CE */ +0xFBC3,0xF1D0,0x0000,0x0000, 0xFBC3,0xF1D1,0x0000,0x0000, /* 1F1D0 */ +0xFBC3,0xF1D2,0x0000,0x0000, 0xFBC3,0xF1D3,0x0000,0x0000, /* 1F1D2 */ +0xFBC3,0xF1D4,0x0000,0x0000, 0xFBC3,0xF1D5,0x0000,0x0000, /* 1F1D4 */ +0xFBC3,0xF1D6,0x0000,0x0000, 0xFBC3,0xF1D7,0x0000,0x0000, /* 1F1D6 */ +0xFBC3,0xF1D8,0x0000,0x0000, 0xFBC3,0xF1D9,0x0000,0x0000, /* 1F1D8 */ +0xFBC3,0xF1DA,0x0000,0x0000, 0xFBC3,0xF1DB,0x0000,0x0000, /* 1F1DA */ +0xFBC3,0xF1DC,0x0000,0x0000, 0xFBC3,0xF1DD,0x0000,0x0000, /* 1F1DC */ +0xFBC3,0xF1DE,0x0000,0x0000, 0xFBC3,0xF1DF,0x0000,0x0000, /* 1F1DE */ +0xFBC3,0xF1E0,0x0000,0x0000, 0xFBC3,0xF1E1,0x0000,0x0000, /* 1F1E0 */ +0xFBC3,0xF1E2,0x0000,0x0000, 0xFBC3,0xF1E3,0x0000,0x0000, /* 1F1E2 */ +0xFBC3,0xF1E4,0x0000,0x0000, 0xFBC3,0xF1E5,0x0000,0x0000, /* 1F1E4 */ +0xFBC3,0xF1E6,0x0000,0x0000, 0xFBC3,0xF1E7,0x0000,0x0000, /* 1F1E6 */ +0xFBC3,0xF1E8,0x0000,0x0000, 0xFBC3,0xF1E9,0x0000,0x0000, /* 1F1E8 */ +0xFBC3,0xF1EA,0x0000,0x0000, 0xFBC3,0xF1EB,0x0000,0x0000, /* 1F1EA */ +0xFBC3,0xF1EC,0x0000,0x0000, 0xFBC3,0xF1ED,0x0000,0x0000, /* 1F1EC */ +0xFBC3,0xF1EE,0x0000,0x0000, 0xFBC3,0xF1EF,0x0000,0x0000, /* 1F1EE */ +0xFBC3,0xF1F0,0x0000,0x0000, 0xFBC3,0xF1F1,0x0000,0x0000, /* 1F1F0 */ +0xFBC3,0xF1F2,0x0000,0x0000, 0xFBC3,0xF1F3,0x0000,0x0000, /* 1F1F2 */ +0xFBC3,0xF1F4,0x0000,0x0000, 0xFBC3,0xF1F5,0x0000,0x0000, /* 1F1F4 */ +0xFBC3,0xF1F6,0x0000,0x0000, 0xFBC3,0xF1F7,0x0000,0x0000, /* 1F1F6 */ +0xFBC3,0xF1F8,0x0000,0x0000, 0xFBC3,0xF1F9,0x0000,0x0000, /* 1F1F8 */ +0xFBC3,0xF1FA,0x0000,0x0000, 0xFBC3,0xF1FB,0x0000,0x0000, /* 1F1FA */ +0xFBC3,0xF1FC,0x0000,0x0000, 0xFBC3,0xF1FD,0x0000,0x0000, /* 1F1FC */ +0xFBC3,0xF1FE,0x0000,0x0000, 0xFBC3,0xF1FF,0x0000,0x0000 /* 1F1FE */ +}; + +uint16 uca520_p1F2[]= { /* 1F200 (5 weights per char) */ +0x2B32,0x2B1A,0x0000,0x0000,0x0000, /* 1F200 */ +0xFBC3,0xF201,0x0000,0x0000,0x0000, /* 1F201 */ +0xFBC3,0xF202,0x0000,0x0000,0x0000, /* 1F202 */ +0xFBC3,0xF203,0x0000,0x0000,0x0000, /* 1F203 */ +0xFBC3,0xF204,0x0000,0x0000,0x0000, /* 1F204 */ +0xFBC3,0xF205,0x0000,0x0000,0x0000, /* 1F205 */ +0xFBC3,0xF206,0x0000,0x0000,0x0000, /* 1F206 */ +0xFBC3,0xF207,0x0000,0x0000,0x0000, /* 1F207 */ +0xFBC3,0xF208,0x0000,0x0000,0x0000, /* 1F208 */ +0xFBC3,0xF209,0x0000,0x0000,0x0000, /* 1F209 */ +0xFBC3,0xF20A,0x0000,0x0000,0x0000, /* 1F20A */ +0xFBC3,0xF20B,0x0000,0x0000,0x0000, /* 1F20B */ +0xFBC3,0xF20C,0x0000,0x0000,0x0000, /* 1F20C */ +0xFBC3,0xF20D,0x0000,0x0000,0x0000, /* 1F20D */ +0xFBC3,0xF20E,0x0000,0x0000,0x0000, /* 1F20E */ +0xFBC3,0xF20F,0x0000,0x0000,0x0000, /* 1F20F */ +0xFB40,0xE24B,0x0000,0x0000,0x0000, /* 1F210 */ +0xFB40,0xDB57,0x0000,0x0000,0x0000, /* 1F211 */ +0xFB40,0xD3CC,0x0000,0x0000,0x0000, /* 1F212 */ +0x2B27,0x0000,0x0000,0x0000,0x0000, /* 1F213 */ +0xFB40,0xCE8C,0x0000,0x0000,0x0000, /* 1F214 */ +0xFB40,0xD91A,0x0000,0x0000,0x0000, /* 1F215 */ +0xFB41,0x89E3,0x0000,0x0000,0x0000, /* 1F216 */ +0xFB40,0xD929,0x0000,0x0000,0x0000, /* 1F217 */ +0xFB40,0xCEA4,0x0000,0x0000,0x0000, /* 1F218 */ +0xFB40,0xE620,0x0000,0x0000,0x0000, /* 1F219 */ +0xFB40,0xF121,0x0000,0x0000,0x0000, /* 1F21A */ +0xFB40,0xE599,0x0000,0x0000,0x0000, /* 1F21B */ +0xFB40,0xD24D,0x0000,0x0000,0x0000, /* 1F21C */ +0xFB40,0xDF8C,0x0000,0x0000,0x0000, /* 1F21D */ +0xFB40,0xD18D,0x0000,0x0000,0x0000, /* 1F21E */ +0xFB40,0xE5B0,0x0000,0x0000,0x0000, /* 1F21F */ +0xFB40,0xD21D,0x0000,0x0000,0x0000, /* 1F220 */ +0xFB40,0xFD42,0x0000,0x0000,0x0000, /* 1F221 */ +0xFB40,0xF51F,0x0000,0x0000,0x0000, /* 1F222 */ +0xFB41,0x8CA9,0x0000,0x0000,0x0000, /* 1F223 */ +0xFB40,0xD8F0,0x0000,0x0000,0x0000, /* 1F224 */ +0xFB40,0xD439,0x0000,0x0000,0x0000, /* 1F225 */ +0xFB40,0xEF14,0x0000,0x0000,0x0000, /* 1F226 */ +0xFB40,0xE295,0x0000,0x0000,0x0000, /* 1F227 */ +0xFB40,0xE355,0x0000,0x0000,0x0000, /* 1F228 */ +0xFB40,0xCE00,0x0000,0x0000,0x0000, /* 1F229 */ +0xFB40,0xCE09,0x0000,0x0000,0x0000, /* 1F22A */ +0xFB41,0x904A,0x0000,0x0000,0x0000, /* 1F22B */ +0xFB40,0xDDE6,0x0000,0x0000,0x0000, /* 1F22C */ +0xFB40,0xCE2D,0x0000,0x0000,0x0000, /* 1F22D */ +0xFB40,0xD3F3,0x0000,0x0000,0x0000, /* 1F22E */ +0xFB40,0xE307,0x0000,0x0000,0x0000, /* 1F22F */ +0xFB41,0x8D70,0x0000,0x0000,0x0000, /* 1F230 */ +0xFB40,0xE253,0x0000,0x0000,0x0000, /* 1F231 */ +0xFBC3,0xF232,0x0000,0x0000,0x0000, /* 1F232 */ +0xFBC3,0xF233,0x0000,0x0000,0x0000, /* 1F233 */ +0xFBC3,0xF234,0x0000,0x0000,0x0000, /* 1F234 */ +0xFBC3,0xF235,0x0000,0x0000,0x0000, /* 1F235 */ +0xFBC3,0xF236,0x0000,0x0000,0x0000, /* 1F236 */ +0xFBC3,0xF237,0x0000,0x0000,0x0000, /* 1F237 */ +0xFBC3,0xF238,0x0000,0x0000,0x0000, /* 1F238 */ +0xFBC3,0xF239,0x0000,0x0000,0x0000, /* 1F239 */ +0xFBC3,0xF23A,0x0000,0x0000,0x0000, /* 1F23A */ +0xFBC3,0xF23B,0x0000,0x0000,0x0000, /* 1F23B */ +0xFBC3,0xF23C,0x0000,0x0000,0x0000, /* 1F23C */ +0xFBC3,0xF23D,0x0000,0x0000,0x0000, /* 1F23D */ +0xFBC3,0xF23E,0x0000,0x0000,0x0000, /* 1F23E */ +0xFBC3,0xF23F,0x0000,0x0000,0x0000, /* 1F23F */ +0x0347,0xFB40,0xE72C,0x0348,0x0000, /* 1F240 */ +0x0347,0xFB40,0xCE09,0x0348,0x0000, /* 1F241 */ +0x0347,0xFB40,0xCE8C,0x0348,0x0000, /* 1F242 */ +0x0347,0xFB40,0xDB89,0x0348,0x0000, /* 1F243 */ +0x0347,0xFB40,0xF0B9,0x0348,0x0000, /* 1F244 */ +0x0347,0xFB40,0xE253,0x0348,0x0000, /* 1F245 */ +0x0347,0xFB40,0xF6D7,0x0348,0x0000, /* 1F246 */ +0x0347,0xFB40,0xD2DD,0x0348,0x0000, /* 1F247 */ +0x0347,0xFB40,0xE557,0x0348,0x0000, /* 1F248 */ +0xFBC3,0xF249,0x0000,0x0000,0x0000, /* 1F249 */ +0xFBC3,0xF24A,0x0000,0x0000,0x0000, /* 1F24A */ +0xFBC3,0xF24B,0x0000,0x0000,0x0000, /* 1F24B */ +0xFBC3,0xF24C,0x0000,0x0000,0x0000, /* 1F24C */ +0xFBC3,0xF24D,0x0000,0x0000,0x0000, /* 1F24D */ +0xFBC3,0xF24E,0x0000,0x0000,0x0000, /* 1F24E */ +0xFBC3,0xF24F,0x0000,0x0000,0x0000, /* 1F24F */ +0xFBC3,0xF250,0x0000,0x0000,0x0000, /* 1F250 */ +0xFBC3,0xF251,0x0000,0x0000,0x0000, /* 1F251 */ +0xFBC3,0xF252,0x0000,0x0000,0x0000, /* 1F252 */ +0xFBC3,0xF253,0x0000,0x0000,0x0000, /* 1F253 */ +0xFBC3,0xF254,0x0000,0x0000,0x0000, /* 1F254 */ +0xFBC3,0xF255,0x0000,0x0000,0x0000, /* 1F255 */ +0xFBC3,0xF256,0x0000,0x0000,0x0000, /* 1F256 */ +0xFBC3,0xF257,0x0000,0x0000,0x0000, /* 1F257 */ +0xFBC3,0xF258,0x0000,0x0000,0x0000, /* 1F258 */ +0xFBC3,0xF259,0x0000,0x0000,0x0000, /* 1F259 */ +0xFBC3,0xF25A,0x0000,0x0000,0x0000, /* 1F25A */ +0xFBC3,0xF25B,0x0000,0x0000,0x0000, /* 1F25B */ +0xFBC3,0xF25C,0x0000,0x0000,0x0000, /* 1F25C */ +0xFBC3,0xF25D,0x0000,0x0000,0x0000, /* 1F25D */ +0xFBC3,0xF25E,0x0000,0x0000,0x0000, /* 1F25E */ +0xFBC3,0xF25F,0x0000,0x0000,0x0000, /* 1F25F */ +0xFBC3,0xF260,0x0000,0x0000,0x0000, /* 1F260 */ +0xFBC3,0xF261,0x0000,0x0000,0x0000, /* 1F261 */ +0xFBC3,0xF262,0x0000,0x0000,0x0000, /* 1F262 */ +0xFBC3,0xF263,0x0000,0x0000,0x0000, /* 1F263 */ +0xFBC3,0xF264,0x0000,0x0000,0x0000, /* 1F264 */ +0xFBC3,0xF265,0x0000,0x0000,0x0000, /* 1F265 */ +0xFBC3,0xF266,0x0000,0x0000,0x0000, /* 1F266 */ +0xFBC3,0xF267,0x0000,0x0000,0x0000, /* 1F267 */ +0xFBC3,0xF268,0x0000,0x0000,0x0000, /* 1F268 */ +0xFBC3,0xF269,0x0000,0x0000,0x0000, /* 1F269 */ +0xFBC3,0xF26A,0x0000,0x0000,0x0000, /* 1F26A */ +0xFBC3,0xF26B,0x0000,0x0000,0x0000, /* 1F26B */ +0xFBC3,0xF26C,0x0000,0x0000,0x0000, /* 1F26C */ +0xFBC3,0xF26D,0x0000,0x0000,0x0000, /* 1F26D */ +0xFBC3,0xF26E,0x0000,0x0000,0x0000, /* 1F26E */ +0xFBC3,0xF26F,0x0000,0x0000,0x0000, /* 1F26F */ +0xFBC3,0xF270,0x0000,0x0000,0x0000, /* 1F270 */ +0xFBC3,0xF271,0x0000,0x0000,0x0000, /* 1F271 */ +0xFBC3,0xF272,0x0000,0x0000,0x0000, /* 1F272 */ +0xFBC3,0xF273,0x0000,0x0000,0x0000, /* 1F273 */ +0xFBC3,0xF274,0x0000,0x0000,0x0000, /* 1F274 */ +0xFBC3,0xF275,0x0000,0x0000,0x0000, /* 1F275 */ +0xFBC3,0xF276,0x0000,0x0000,0x0000, /* 1F276 */ +0xFBC3,0xF277,0x0000,0x0000,0x0000, /* 1F277 */ +0xFBC3,0xF278,0x0000,0x0000,0x0000, /* 1F278 */ +0xFBC3,0xF279,0x0000,0x0000,0x0000, /* 1F279 */ +0xFBC3,0xF27A,0x0000,0x0000,0x0000, /* 1F27A */ +0xFBC3,0xF27B,0x0000,0x0000,0x0000, /* 1F27B */ +0xFBC3,0xF27C,0x0000,0x0000,0x0000, /* 1F27C */ +0xFBC3,0xF27D,0x0000,0x0000,0x0000, /* 1F27D */ +0xFBC3,0xF27E,0x0000,0x0000,0x0000, /* 1F27E */ +0xFBC3,0xF27F,0x0000,0x0000,0x0000, /* 1F27F */ +0xFBC3,0xF280,0x0000,0x0000,0x0000, /* 1F280 */ +0xFBC3,0xF281,0x0000,0x0000,0x0000, /* 1F281 */ +0xFBC3,0xF282,0x0000,0x0000,0x0000, /* 1F282 */ +0xFBC3,0xF283,0x0000,0x0000,0x0000, /* 1F283 */ +0xFBC3,0xF284,0x0000,0x0000,0x0000, /* 1F284 */ +0xFBC3,0xF285,0x0000,0x0000,0x0000, /* 1F285 */ +0xFBC3,0xF286,0x0000,0x0000,0x0000, /* 1F286 */ +0xFBC3,0xF287,0x0000,0x0000,0x0000, /* 1F287 */ +0xFBC3,0xF288,0x0000,0x0000,0x0000, /* 1F288 */ +0xFBC3,0xF289,0x0000,0x0000,0x0000, /* 1F289 */ +0xFBC3,0xF28A,0x0000,0x0000,0x0000, /* 1F28A */ +0xFBC3,0xF28B,0x0000,0x0000,0x0000, /* 1F28B */ +0xFBC3,0xF28C,0x0000,0x0000,0x0000, /* 1F28C */ +0xFBC3,0xF28D,0x0000,0x0000,0x0000, /* 1F28D */ +0xFBC3,0xF28E,0x0000,0x0000,0x0000, /* 1F28E */ +0xFBC3,0xF28F,0x0000,0x0000,0x0000, /* 1F28F */ +0xFBC3,0xF290,0x0000,0x0000,0x0000, /* 1F290 */ +0xFBC3,0xF291,0x0000,0x0000,0x0000, /* 1F291 */ +0xFBC3,0xF292,0x0000,0x0000,0x0000, /* 1F292 */ +0xFBC3,0xF293,0x0000,0x0000,0x0000, /* 1F293 */ +0xFBC3,0xF294,0x0000,0x0000,0x0000, /* 1F294 */ +0xFBC3,0xF295,0x0000,0x0000,0x0000, /* 1F295 */ +0xFBC3,0xF296,0x0000,0x0000,0x0000, /* 1F296 */ +0xFBC3,0xF297,0x0000,0x0000,0x0000, /* 1F297 */ +0xFBC3,0xF298,0x0000,0x0000,0x0000, /* 1F298 */ +0xFBC3,0xF299,0x0000,0x0000,0x0000, /* 1F299 */ +0xFBC3,0xF29A,0x0000,0x0000,0x0000, /* 1F29A */ +0xFBC3,0xF29B,0x0000,0x0000,0x0000, /* 1F29B */ +0xFBC3,0xF29C,0x0000,0x0000,0x0000, /* 1F29C */ +0xFBC3,0xF29D,0x0000,0x0000,0x0000, /* 1F29D */ +0xFBC3,0xF29E,0x0000,0x0000,0x0000, /* 1F29E */ +0xFBC3,0xF29F,0x0000,0x0000,0x0000, /* 1F29F */ +0xFBC3,0xF2A0,0x0000,0x0000,0x0000, /* 1F2A0 */ +0xFBC3,0xF2A1,0x0000,0x0000,0x0000, /* 1F2A1 */ +0xFBC3,0xF2A2,0x0000,0x0000,0x0000, /* 1F2A2 */ +0xFBC3,0xF2A3,0x0000,0x0000,0x0000, /* 1F2A3 */ +0xFBC3,0xF2A4,0x0000,0x0000,0x0000, /* 1F2A4 */ +0xFBC3,0xF2A5,0x0000,0x0000,0x0000, /* 1F2A5 */ +0xFBC3,0xF2A6,0x0000,0x0000,0x0000, /* 1F2A6 */ +0xFBC3,0xF2A7,0x0000,0x0000,0x0000, /* 1F2A7 */ +0xFBC3,0xF2A8,0x0000,0x0000,0x0000, /* 1F2A8 */ +0xFBC3,0xF2A9,0x0000,0x0000,0x0000, /* 1F2A9 */ +0xFBC3,0xF2AA,0x0000,0x0000,0x0000, /* 1F2AA */ +0xFBC3,0xF2AB,0x0000,0x0000,0x0000, /* 1F2AB */ +0xFBC3,0xF2AC,0x0000,0x0000,0x0000, /* 1F2AC */ +0xFBC3,0xF2AD,0x0000,0x0000,0x0000, /* 1F2AD */ +0xFBC3,0xF2AE,0x0000,0x0000,0x0000, /* 1F2AE */ +0xFBC3,0xF2AF,0x0000,0x0000,0x0000, /* 1F2AF */ +0xFBC3,0xF2B0,0x0000,0x0000,0x0000, /* 1F2B0 */ +0xFBC3,0xF2B1,0x0000,0x0000,0x0000, /* 1F2B1 */ +0xFBC3,0xF2B2,0x0000,0x0000,0x0000, /* 1F2B2 */ +0xFBC3,0xF2B3,0x0000,0x0000,0x0000, /* 1F2B3 */ +0xFBC3,0xF2B4,0x0000,0x0000,0x0000, /* 1F2B4 */ +0xFBC3,0xF2B5,0x0000,0x0000,0x0000, /* 1F2B5 */ +0xFBC3,0xF2B6,0x0000,0x0000,0x0000, /* 1F2B6 */ +0xFBC3,0xF2B7,0x0000,0x0000,0x0000, /* 1F2B7 */ +0xFBC3,0xF2B8,0x0000,0x0000,0x0000, /* 1F2B8 */ +0xFBC3,0xF2B9,0x0000,0x0000,0x0000, /* 1F2B9 */ +0xFBC3,0xF2BA,0x0000,0x0000,0x0000, /* 1F2BA */ +0xFBC3,0xF2BB,0x0000,0x0000,0x0000, /* 1F2BB */ +0xFBC3,0xF2BC,0x0000,0x0000,0x0000, /* 1F2BC */ +0xFBC3,0xF2BD,0x0000,0x0000,0x0000, /* 1F2BD */ +0xFBC3,0xF2BE,0x0000,0x0000,0x0000, /* 1F2BE */ +0xFBC3,0xF2BF,0x0000,0x0000,0x0000, /* 1F2BF */ +0xFBC3,0xF2C0,0x0000,0x0000,0x0000, /* 1F2C0 */ +0xFBC3,0xF2C1,0x0000,0x0000,0x0000, /* 1F2C1 */ +0xFBC3,0xF2C2,0x0000,0x0000,0x0000, /* 1F2C2 */ +0xFBC3,0xF2C3,0x0000,0x0000,0x0000, /* 1F2C3 */ +0xFBC3,0xF2C4,0x0000,0x0000,0x0000, /* 1F2C4 */ +0xFBC3,0xF2C5,0x0000,0x0000,0x0000, /* 1F2C5 */ +0xFBC3,0xF2C6,0x0000,0x0000,0x0000, /* 1F2C6 */ +0xFBC3,0xF2C7,0x0000,0x0000,0x0000, /* 1F2C7 */ +0xFBC3,0xF2C8,0x0000,0x0000,0x0000, /* 1F2C8 */ +0xFBC3,0xF2C9,0x0000,0x0000,0x0000, /* 1F2C9 */ +0xFBC3,0xF2CA,0x0000,0x0000,0x0000, /* 1F2CA */ +0xFBC3,0xF2CB,0x0000,0x0000,0x0000, /* 1F2CB */ +0xFBC3,0xF2CC,0x0000,0x0000,0x0000, /* 1F2CC */ +0xFBC3,0xF2CD,0x0000,0x0000,0x0000, /* 1F2CD */ +0xFBC3,0xF2CE,0x0000,0x0000,0x0000, /* 1F2CE */ +0xFBC3,0xF2CF,0x0000,0x0000,0x0000, /* 1F2CF */ +0xFBC3,0xF2D0,0x0000,0x0000,0x0000, /* 1F2D0 */ +0xFBC3,0xF2D1,0x0000,0x0000,0x0000, /* 1F2D1 */ +0xFBC3,0xF2D2,0x0000,0x0000,0x0000, /* 1F2D2 */ +0xFBC3,0xF2D3,0x0000,0x0000,0x0000, /* 1F2D3 */ +0xFBC3,0xF2D4,0x0000,0x0000,0x0000, /* 1F2D4 */ +0xFBC3,0xF2D5,0x0000,0x0000,0x0000, /* 1F2D5 */ +0xFBC3,0xF2D6,0x0000,0x0000,0x0000, /* 1F2D6 */ +0xFBC3,0xF2D7,0x0000,0x0000,0x0000, /* 1F2D7 */ +0xFBC3,0xF2D8,0x0000,0x0000,0x0000, /* 1F2D8 */ +0xFBC3,0xF2D9,0x0000,0x0000,0x0000, /* 1F2D9 */ +0xFBC3,0xF2DA,0x0000,0x0000,0x0000, /* 1F2DA */ +0xFBC3,0xF2DB,0x0000,0x0000,0x0000, /* 1F2DB */ +0xFBC3,0xF2DC,0x0000,0x0000,0x0000, /* 1F2DC */ +0xFBC3,0xF2DD,0x0000,0x0000,0x0000, /* 1F2DD */ +0xFBC3,0xF2DE,0x0000,0x0000,0x0000, /* 1F2DE */ +0xFBC3,0xF2DF,0x0000,0x0000,0x0000, /* 1F2DF */ +0xFBC3,0xF2E0,0x0000,0x0000,0x0000, /* 1F2E0 */ +0xFBC3,0xF2E1,0x0000,0x0000,0x0000, /* 1F2E1 */ +0xFBC3,0xF2E2,0x0000,0x0000,0x0000, /* 1F2E2 */ +0xFBC3,0xF2E3,0x0000,0x0000,0x0000, /* 1F2E3 */ +0xFBC3,0xF2E4,0x0000,0x0000,0x0000, /* 1F2E4 */ +0xFBC3,0xF2E5,0x0000,0x0000,0x0000, /* 1F2E5 */ +0xFBC3,0xF2E6,0x0000,0x0000,0x0000, /* 1F2E6 */ +0xFBC3,0xF2E7,0x0000,0x0000,0x0000, /* 1F2E7 */ +0xFBC3,0xF2E8,0x0000,0x0000,0x0000, /* 1F2E8 */ +0xFBC3,0xF2E9,0x0000,0x0000,0x0000, /* 1F2E9 */ +0xFBC3,0xF2EA,0x0000,0x0000,0x0000, /* 1F2EA */ +0xFBC3,0xF2EB,0x0000,0x0000,0x0000, /* 1F2EB */ +0xFBC3,0xF2EC,0x0000,0x0000,0x0000, /* 1F2EC */ +0xFBC3,0xF2ED,0x0000,0x0000,0x0000, /* 1F2ED */ +0xFBC3,0xF2EE,0x0000,0x0000,0x0000, /* 1F2EE */ +0xFBC3,0xF2EF,0x0000,0x0000,0x0000, /* 1F2EF */ +0xFBC3,0xF2F0,0x0000,0x0000,0x0000, /* 1F2F0 */ +0xFBC3,0xF2F1,0x0000,0x0000,0x0000, /* 1F2F1 */ +0xFBC3,0xF2F2,0x0000,0x0000,0x0000, /* 1F2F2 */ +0xFBC3,0xF2F3,0x0000,0x0000,0x0000, /* 1F2F3 */ +0xFBC3,0xF2F4,0x0000,0x0000,0x0000, /* 1F2F4 */ +0xFBC3,0xF2F5,0x0000,0x0000,0x0000, /* 1F2F5 */ +0xFBC3,0xF2F6,0x0000,0x0000,0x0000, /* 1F2F6 */ +0xFBC3,0xF2F7,0x0000,0x0000,0x0000, /* 1F2F7 */ +0xFBC3,0xF2F8,0x0000,0x0000,0x0000, /* 1F2F8 */ +0xFBC3,0xF2F9,0x0000,0x0000,0x0000, /* 1F2F9 */ +0xFBC3,0xF2FA,0x0000,0x0000,0x0000, /* 1F2FA */ +0xFBC3,0xF2FB,0x0000,0x0000,0x0000, /* 1F2FB */ +0xFBC3,0xF2FC,0x0000,0x0000,0x0000, /* 1F2FC */ +0xFBC3,0xF2FD,0x0000,0x0000,0x0000, /* 1F2FD */ +0xFBC3,0xF2FE,0x0000,0x0000,0x0000, /* 1F2FE */ +0xFBC3,0xF2FF,0x0000,0x0000,0x0000 /* 1F2FF */ +}; + +uint16 uca520_p2F8[]= { /* 2F800 (3 weights per char) */ +0xFB40,0xCE3D,0x0000, 0xFB40,0xCE38,0x0000, 0xFB40,0xCE41,0x0000, /* 2F800 */ +0xFB84,0x8122,0x0000, 0xFB40,0xCF60,0x0000, 0xFB40,0xCFAE,0x0000, /* 2F803 */ +0xFB40,0xCFBB,0x0000, 0xFB40,0xD002,0x0000, 0xFB40,0xD07A,0x0000, /* 2F806 */ +0xFB40,0xD099,0x0000, 0xFB40,0xD0E7,0x0000, 0xFB40,0xD0CF,0x0000, /* 2F809 */ +0xFB80,0xB49E,0x0000, 0xFB84,0x863A,0x0000, 0xFB40,0xD14D,0x0000, /* 2F80C */ +0xFB40,0xD154,0x0000, 0xFB40,0xD164,0x0000, 0xFB40,0xD177,0x0000, /* 2F80F */ +0xFB84,0x851C,0x0000, 0xFB80,0xB4B9,0x0000, 0xFB40,0xD167,0x0000, /* 2F812 */ +0xFB40,0xD18D,0x0000, 0xFB84,0x854B,0x0000, 0xFB40,0xD197,0x0000, /* 2F815 */ +0xFB40,0xD1A4,0x0000, 0xFB40,0xCECC,0x0000, 0xFB40,0xD1AC,0x0000, /* 2F818 */ +0xFB40,0xD1B5,0x0000, 0xFB85,0x91DF,0x0000, 0xFB40,0xD1F5,0x0000, /* 2F81B */ +0xFB40,0xD203,0x0000, 0xFB80,0xB4DF,0x0000, 0xFB40,0xD23B,0x0000, /* 2F81E */ +0xFB40,0xD246,0x0000, 0xFB40,0xD272,0x0000, 0xFB40,0xD277,0x0000, /* 2F821 */ +0xFB80,0xB515,0x0000, 0xFB40,0xD2C7,0x0000, 0xFB40,0xD2C9,0x0000, /* 2F824 */ +0xFB40,0xD2E4,0x0000, 0xFB40,0xD2FA,0x0000, 0xFB40,0xD305,0x0000, /* 2F827 */ +0xFB40,0xD306,0x0000, 0xFB40,0xD317,0x0000, 0xFB40,0xD349,0x0000, /* 2F82A */ +0xFB40,0xD351,0x0000, 0xFB40,0xD35A,0x0000, 0xFB40,0xD373,0x0000, /* 2F82D */ +0xFB40,0xD37D,0x0000, 0xFB40,0xD37F,0x0000, 0xFB40,0xD37F,0x0000, /* 2F830 */ +0xFB40,0xD37F,0x0000, 0xFB84,0x8A2C,0x0000, 0xFB40,0xF070,0x0000, /* 2F833 */ +0xFB40,0xD3CA,0x0000, 0xFB40,0xD3DF,0x0000, 0xFB84,0x8B63,0x0000, /* 2F836 */ +0xFB40,0xD3EB,0x0000, 0xFB40,0xD3F1,0x0000, 0xFB40,0xD406,0x0000, /* 2F839 */ +0xFB40,0xD49E,0x0000, 0xFB40,0xD438,0x0000, 0xFB40,0xD448,0x0000, /* 2F83C */ +0xFB40,0xD468,0x0000, 0xFB40,0xD4A2,0x0000, 0xFB40,0xD4F6,0x0000, /* 2F83F */ +0xFB40,0xD510,0x0000, 0xFB40,0xD553,0x0000, 0xFB40,0xD563,0x0000, /* 2F842 */ +0xFB40,0xD584,0x0000, 0xFB40,0xD584,0x0000, 0xFB40,0xD599,0x0000, /* 2F845 */ +0xFB40,0xD5AB,0x0000, 0xFB40,0xD5B3,0x0000, 0xFB40,0xD5C2,0x0000, /* 2F848 */ +0xFB40,0xD716,0x0000, 0xFB40,0xD606,0x0000, 0xFB40,0xD717,0x0000, /* 2F84B */ +0xFB40,0xD651,0x0000, 0xFB40,0xD674,0x0000, 0xFB40,0xD207,0x0000, /* 2F84E */ +0xFB40,0xD8EE,0x0000, 0xFB40,0xD7CE,0x0000, 0xFB40,0xD7F4,0x0000, /* 2F851 */ +0xFB40,0xD80D,0x0000, 0xFB40,0xD78B,0x0000, 0xFB40,0xD832,0x0000, /* 2F854 */ +0xFB40,0xD831,0x0000, 0xFB40,0xD8AC,0x0000, 0xFB84,0x94E4,0x0000, /* 2F857 */ +0xFB40,0xD8F2,0x0000, 0xFB40,0xD8F7,0x0000, 0xFB40,0xD906,0x0000, /* 2F85A */ +0xFB40,0xD91A,0x0000, 0xFB40,0xD922,0x0000, 0xFB40,0xD962,0x0000, /* 2F85D */ +0xFB84,0x96A8,0x0000, 0xFB84,0x96EA,0x0000, 0xFB40,0xD9EC,0x0000, /* 2F860 */ +0xFB40,0xDA1B,0x0000, 0xFB40,0xDA27,0x0000, 0xFB40,0xD9D8,0x0000, /* 2F863 */ +0xFB40,0xDA66,0x0000, 0xFB80,0xB6EE,0x0000, 0xFB80,0xB6FC,0x0000, /* 2F866 */ +0xFB40,0xDB08,0x0000, 0xFB40,0xDB3E,0x0000, 0xFB40,0xDB3E,0x0000, /* 2F869 */ +0xFB84,0x99C8,0x0000, 0xFB40,0xDBC3,0x0000, 0xFB40,0xDBD8,0x0000, /* 2F86C */ +0xFB40,0xDBE7,0x0000, 0xFB40,0xDBF3,0x0000, 0xFB84,0x9B18,0x0000, /* 2F86F */ +0xFB40,0xDBFF,0x0000, 0xFB40,0xDC06,0x0000, 0xFB40,0xDF53,0x0000, /* 2F872 */ +0xFB40,0xDC22,0x0000, 0xFB80,0xB781,0x0000, 0xFB40,0xDC60,0x0000, /* 2F875 */ +0xFB40,0xDC6E,0x0000, 0xFB40,0xDCC0,0x0000, 0xFB40,0xDC8D,0x0000, /* 2F878 */ +0xFB84,0x9DE4,0x0000, 0xFB40,0xDD43,0x0000, 0xFB84,0x9DE6,0x0000, /* 2F87B */ +0xFB40,0xDD6E,0x0000, 0xFB40,0xDD6B,0x0000, 0xFB40,0xDD7C,0x0000, /* 2F87E */ +0xFB40,0xDDE1,0x0000, 0xFB40,0xDDE2,0x0000, 0xFB80,0xB82F,0x0000, /* 2F881 */ +0xFB40,0xDDFD,0x0000, 0xFB40,0xDE28,0x0000, 0xFB40,0xDE3D,0x0000, /* 2F884 */ +0xFB40,0xDE69,0x0000, 0xFB80,0xB862,0x0000, 0xFB84,0xA183,0x0000, /* 2F887 */ +0xFB80,0xB87C,0x0000, 0xFB40,0xDEB0,0x0000, 0xFB40,0xDEB3,0x0000, /* 2F88A */ +0xFB40,0xDEB6,0x0000, 0xFB40,0xDECA,0x0000, 0xFB85,0xA392,0x0000, /* 2F88D */ +0xFB40,0xDEFE,0x0000, 0xFB84,0xA331,0x0000, 0xFB84,0xA331,0x0000, /* 2F890 */ +0xFB41,0x8201,0x0000, 0xFB40,0xDF22,0x0000, 0xFB40,0xDF22,0x0000, /* 2F893 */ +0xFB80,0xB8C7,0x0000, 0xFB84,0xB2B8,0x0000, 0xFB84,0xE1DA,0x0000, /* 2F896 */ +0xFB40,0xDF62,0x0000, 0xFB40,0xDF6B,0x0000, 0xFB80,0xB8E3,0x0000, /* 2F899 */ +0xFB40,0xDF9A,0x0000, 0xFB40,0xDFCD,0x0000, 0xFB40,0xDFD7,0x0000, /* 2F89C */ +0xFB40,0xDFF9,0x0000, 0xFB40,0xE081,0x0000, 0xFB80,0xB93A,0x0000, /* 2F89F */ +0xFB80,0xB91C,0x0000, 0xFB40,0xE094,0x0000, 0xFB84,0xA6D4,0x0000, /* 2F8A2 */ +0xFB40,0xE0C7,0x0000, 0xFB40,0xE148,0x0000, 0xFB40,0xE14C,0x0000, /* 2F8A5 */ +0xFB40,0xE14E,0x0000, 0xFB40,0xE14C,0x0000, 0xFB40,0xE17A,0x0000, /* 2F8A8 */ +0xFB40,0xE18E,0x0000, 0xFB40,0xE1B2,0x0000, 0xFB40,0xE1A4,0x0000, /* 2F8AB */ +0xFB40,0xE1AF,0x0000, 0xFB40,0xE1DE,0x0000, 0xFB40,0xE1F2,0x0000, /* 2F8AE */ +0xFB40,0xE1F6,0x0000, 0xFB40,0xE210,0x0000, 0xFB40,0xE21B,0x0000, /* 2F8B1 */ +0xFB40,0xE25D,0x0000, 0xFB40,0xE2B1,0x0000, 0xFB40,0xE2D4,0x0000, /* 2F8B4 */ +0xFB40,0xE350,0x0000, 0xFB84,0xAB0C,0x0000, 0xFB40,0xE33D,0x0000, /* 2F8B7 */ +0xFB40,0xE2FC,0x0000, 0xFB40,0xE368,0x0000, 0xFB40,0xE383,0x0000, /* 2F8BA */ +0xFB40,0xE3E4,0x0000, 0xFB84,0xABF1,0x0000, 0xFB40,0xE422,0x0000, /* 2F8BD */ +0xFB40,0xE3C5,0x0000, 0xFB40,0xE3A9,0x0000, 0xFB80,0xBA2E,0x0000, /* 2F8C0 */ +0xFB40,0xE469,0x0000, 0xFB40,0xE47E,0x0000, 0xFB40,0xE49D,0x0000, /* 2F8C3 */ +0xFB40,0xE477,0x0000, 0xFB80,0xBA6C,0x0000, 0xFB40,0xE54F,0x0000, /* 2F8C6 */ +0xFB40,0xE56C,0x0000, 0xFB84,0xB00A,0x0000, 0xFB40,0xE5E3,0x0000, /* 2F8C9 */ +0xFB40,0xE6F8,0x0000, 0xFB40,0xE649,0x0000, 0xFB80,0xBB19,0x0000, /* 2F8CC */ +0xFB40,0xE691,0x0000, 0xFB80,0xBB08,0x0000, 0xFB80,0xBAE4,0x0000, /* 2F8CF */ +0xFB40,0xD192,0x0000, 0xFB40,0xD195,0x0000, 0xFB40,0xE700,0x0000, /* 2F8D2 */ +0xFB40,0xE69C,0x0000, 0xFB41,0x80AD,0x0000, 0xFB80,0xC3D9,0x0000, /* 2F8D5 */ +0xFB40,0xE717,0x0000, 0xFB40,0xE71B,0x0000, 0xFB40,0xE721,0x0000, /* 2F8D8 */ +0xFB40,0xE75E,0x0000, 0xFB40,0xE753,0x0000, 0xFB84,0xB3C3,0x0000, /* 2F8DB */ +0xFB80,0xBB49,0x0000, 0xFB40,0xE7FA,0x0000, 0xFB40,0xE785,0x0000, /* 2F8DE */ +0xFB40,0xE852,0x0000, 0xFB40,0xE885,0x0000, 0xFB84,0xB46D,0x0000, /* 2F8E1 */ +0xFB40,0xE88E,0x0000, 0xFB40,0xE81F,0x0000, 0xFB40,0xE914,0x0000, /* 2F8E4 */ +0xFB80,0xBB9D,0x0000, 0xFB40,0xE942,0x0000, 0xFB40,0xE9A3,0x0000, /* 2F8E7 */ +0xFB40,0xE9EA,0x0000, 0xFB40,0xEAA8,0x0000, 0xFB84,0xB6A3,0x0000, /* 2F8EA */ +0xFB40,0xEADB,0x0000, 0xFB80,0xBC18,0x0000, 0xFB40,0xEB21,0x0000, /* 2F8ED */ +0xFB84,0xB8A7,0x0000, 0xFB40,0xEB54,0x0000, 0xFB80,0xBC4E,0x0000, /* 2F8F0 */ +0xFB40,0xEB72,0x0000, 0xFB40,0xEB9F,0x0000, 0xFB40,0xEBBA,0x0000, /* 2F8F3 */ +0xFB40,0xEBBB,0x0000, 0xFB84,0xBA8D,0x0000, 0xFB84,0x9D0B,0x0000, /* 2F8F6 */ +0xFB84,0xBAFA,0x0000, 0xFB40,0xEC4E,0x0000, 0xFB84,0xBCBC,0x0000, /* 2F8F9 */ +0xFB40,0xECBF,0x0000, 0xFB40,0xECCD,0x0000, 0xFB40,0xEC67,0x0000, /* 2F8FC */ +0xFB40,0xED16,0x0000 }; + +uint16 uca520_p2F9[]= { /* 2F900 (3 weights per char) */ +0xFB40,0xED3E,0x0000, 0xFB40,0xED77,0x0000, 0xFB40,0xED41,0x0000, /* 2F900 */ +0xFB40,0xED69,0x0000, 0xFB40,0xED78,0x0000, 0xFB40,0xED85,0x0000, /* 2F903 */ +0xFB84,0xBD1E,0x0000, 0xFB40,0xED34,0x0000, 0xFB40,0xEE2F,0x0000, /* 2F906 */ +0xFB40,0xEE6E,0x0000, 0xFB80,0xBD33,0x0000, 0xFB40,0xEECB,0x0000, /* 2F909 */ +0xFB40,0xEEC7,0x0000, 0xFB84,0xBED1,0x0000, 0xFB40,0xEDF9,0x0000, /* 2F90C */ +0xFB40,0xEF6E,0x0000, 0xFB84,0xBF5E,0x0000, 0xFB84,0xBF8E,0x0000, /* 2F90F */ +0xFB40,0xEFC6,0x0000, 0xFB40,0xF039,0x0000, 0xFB40,0xF01E,0x0000, /* 2F912 */ +0xFB40,0xF01B,0x0000, 0xFB80,0xBD96,0x0000, 0xFB40,0xF04A,0x0000, /* 2F915 */ +0xFB40,0xF07D,0x0000, 0xFB40,0xF077,0x0000, 0xFB40,0xF0AD,0x0000, /* 2F918 */ +0xFB84,0x8525,0x0000, 0xFB40,0xF145,0x0000, 0xFB84,0xC263,0x0000, /* 2F91B */ +0xFB40,0xF19C,0x0000, 0xFB84,0xC3AB,0x0000, 0xFB40,0xF228,0x0000, /* 2F91E */ +0xFB40,0xF235,0x0000, 0xFB40,0xF250,0x0000, 0xFB84,0xC608,0x0000, /* 2F921 */ +0xFB40,0xF280,0x0000, 0xFB40,0xF295,0x0000, 0xFB84,0xC735,0x0000, /* 2F924 */ +0xFB84,0xC814,0x0000, 0xFB40,0xF37A,0x0000, 0xFB40,0xF38B,0x0000, /* 2F927 */ +0xFB80,0xBEAC,0x0000, 0xFB40,0xF3A5,0x0000, 0xFB80,0xBEB8,0x0000, /* 2F92A */ +0xFB80,0xBEB8,0x0000, 0xFB40,0xF447,0x0000, 0xFB40,0xF45C,0x0000, /* 2F92D */ +0xFB40,0xF471,0x0000, 0xFB40,0xF485,0x0000, 0xFB40,0xF4CA,0x0000, /* 2F930 */ +0xFB80,0xBF1B,0x0000, 0xFB40,0xF524,0x0000, 0xFB84,0xCC36,0x0000, /* 2F933 */ +0xFB40,0xF53E,0x0000, 0xFB84,0xCC92,0x0000, 0xFB40,0xF570,0x0000, /* 2F936 */ +0xFB84,0xA19F,0x0000, 0xFB40,0xF610,0x0000, 0xFB84,0xCFA1,0x0000, /* 2F939 */ +0xFB84,0xCFB8,0x0000, 0xFB84,0xD044,0x0000, 0xFB80,0xBFFC,0x0000, /* 2F93C */ +0xFB80,0xC008,0x0000, 0xFB40,0xF6F4,0x0000, 0xFB84,0xD0F3,0x0000, /* 2F93F */ +0xFB84,0xD0F2,0x0000, 0xFB84,0xD119,0x0000, 0xFB84,0xD133,0x0000, /* 2F942 */ +0xFB40,0xF71E,0x0000, 0xFB40,0xF71F,0x0000, 0xFB40,0xF71F,0x0000, /* 2F945 */ +0xFB40,0xF74A,0x0000, 0xFB80,0xC039,0x0000, 0xFB40,0xF78B,0x0000, /* 2F948 */ +0xFB80,0xC046,0x0000, 0xFB80,0xC096,0x0000, 0xFB84,0xD41D,0x0000, /* 2F94B */ +0xFB40,0xF84E,0x0000, 0xFB40,0xF88C,0x0000, 0xFB40,0xF8CC,0x0000, /* 2F94E */ +0xFB80,0xC0E3,0x0000, 0xFB84,0xD626,0x0000, 0xFB40,0xF956,0x0000, /* 2F951 */ +0xFB84,0xD69A,0x0000, 0xFB84,0xD6C5,0x0000, 0xFB40,0xF98F,0x0000, /* 2F954 */ +0xFB40,0xF9EB,0x0000, 0xFB80,0xC12F,0x0000, 0xFB40,0xFA40,0x0000, /* 2F957 */ +0xFB40,0xFA4A,0x0000, 0xFB40,0xFA4F,0x0000, 0xFB84,0xD97C,0x0000, /* 2F95A */ +0xFB84,0xDAA7,0x0000, 0xFB84,0xDAA7,0x0000, 0xFB40,0xFAEE,0x0000, /* 2F95D */ +0xFB80,0xC202,0x0000, 0xFB84,0xDBAB,0x0000, 0xFB40,0xFBC6,0x0000, /* 2F960 */ +0xFB40,0xFBC9,0x0000, 0xFB80,0xC227,0x0000, 0xFB84,0xDC80,0x0000, /* 2F963 */ +0xFB40,0xFCD2,0x0000, 0xFB80,0xC2A0,0x0000, 0xFB40,0xFCE8,0x0000, /* 2F966 */ +0xFB40,0xFCE3,0x0000, 0xFB40,0xFD00,0x0000, 0xFB84,0xDF86,0x0000, /* 2F969 */ +0xFB40,0xFD63,0x0000, 0xFB80,0xC301,0x0000, 0xFB40,0xFDC7,0x0000, /* 2F96C */ +0xFB40,0xFE02,0x0000, 0xFB40,0xFE45,0x0000, 0xFB80,0xC334,0x0000, /* 2F96F */ +0xFB84,0xE228,0x0000, 0xFB84,0xE247,0x0000, 0xFB80,0xC359,0x0000, /* 2F972 */ +0xFB84,0xE2D9,0x0000, 0xFB40,0xFF7A,0x0000, 0xFB84,0xE33E,0x0000, /* 2F975 */ +0xFB40,0xFF95,0x0000, 0xFB40,0xFFFA,0x0000, 0xFB41,0x8005,0x0000, /* 2F978 */ +0xFB84,0xE4DA,0x0000, 0xFB84,0xE523,0x0000, 0xFB41,0x8060,0x0000, /* 2F97B */ +0xFB84,0xE5A8,0x0000, 0xFB41,0x8070,0x0000, 0xFB84,0xB35F,0x0000, /* 2F97E */ +0xFB80,0xC3D5,0x0000, 0xFB41,0x80B2,0x0000, 0xFB41,0x8103,0x0000, /* 2F981 */ +0xFB80,0xC40B,0x0000, 0xFB41,0x813E,0x0000, 0xFB40,0xDAB5,0x0000, /* 2F984 */ +0xFB84,0xE7A7,0x0000, 0xFB84,0xE7B5,0x0000, 0xFB84,0xB393,0x0000, /* 2F987 */ +0xFB84,0xB39C,0x0000, 0xFB41,0x8201,0x0000, 0xFB41,0x8204,0x0000, /* 2F98A */ +0xFB41,0x8F9E,0x0000, 0xFB80,0xC46B,0x0000, 0xFB41,0x8291,0x0000, /* 2F98D */ +0xFB41,0x828B,0x0000, 0xFB41,0x829D,0x0000, 0xFB40,0xD2B3,0x0000, /* 2F990 */ +0xFB41,0x82B1,0x0000, 0xFB41,0x82B3,0x0000, 0xFB41,0x82BD,0x0000, /* 2F993 */ +0xFB41,0x82E6,0x0000, 0xFB84,0xEB3C,0x0000, 0xFB41,0x82E5,0x0000, /* 2F996 */ +0xFB41,0x831D,0x0000, 0xFB41,0x8363,0x0000, 0xFB41,0x83AD,0x0000, /* 2F999 */ +0xFB41,0x8323,0x0000, 0xFB41,0x83BD,0x0000, 0xFB41,0x83E7,0x0000, /* 2F99C */ +0xFB41,0x8457,0x0000, 0xFB41,0x8353,0x0000, 0xFB41,0x83CA,0x0000, /* 2F99F */ +0xFB41,0x83CC,0x0000, 0xFB41,0x83DC,0x0000, 0xFB84,0xEC36,0x0000, /* 2F9A2 */ +0xFB84,0xED6B,0x0000, 0xFB84,0xECD5,0x0000, 0xFB80,0xC52B,0x0000, /* 2F9A5 */ +0xFB41,0x84F1,0x0000, 0xFB41,0x84F3,0x0000, 0xFB41,0x8516,0x0000, /* 2F9A8 */ +0xFB84,0xF3CA,0x0000, 0xFB41,0x8564,0x0000, 0xFB84,0xEF2C,0x0000, /* 2F9AB */ +0xFB80,0xC55D,0x0000, 0xFB80,0xC561,0x0000, 0xFB84,0xEFB1,0x0000, /* 2F9AE */ +0xFB84,0xF0D2,0x0000, 0xFB80,0xC56B,0x0000, 0xFB41,0x8650,0x0000, /* 2F9B1 */ +0xFB41,0x865C,0x0000, 0xFB41,0x8667,0x0000, 0xFB41,0x8669,0x0000, /* 2F9B4 */ +0xFB41,0x86A9,0x0000, 0xFB41,0x8688,0x0000, 0xFB41,0x870E,0x0000, /* 2F9B7 */ +0xFB41,0x86E2,0x0000, 0xFB41,0x8779,0x0000, 0xFB41,0x8728,0x0000, /* 2F9BA */ +0xFB41,0x876B,0x0000, 0xFB41,0x8786,0x0000, 0xFB80,0xC5D7,0x0000, /* 2F9BD */ +0xFB41,0x87E1,0x0000, 0xFB41,0x8801,0x0000, 0xFB80,0xC5F9,0x0000, /* 2F9C0 */ +0xFB41,0x8860,0x0000, 0xFB41,0x8863,0x0000, 0xFB84,0xF667,0x0000, /* 2F9C3 */ +0xFB41,0x88D7,0x0000, 0xFB41,0x88DE,0x0000, 0xFB80,0xC635,0x0000, /* 2F9C6 */ +0xFB41,0x88FA,0x0000, 0xFB80,0xB4BB,0x0000, 0xFB84,0xF8AE,0x0000, /* 2F9C9 */ +0xFB84,0xF966,0x0000, 0xFB80,0xC6BE,0x0000, 0xFB80,0xC6C7,0x0000, /* 2F9CC */ +0xFB41,0x8AA0,0x0000, 0xFB41,0x8AED,0x0000, 0xFB41,0x8B8A,0x0000, /* 2F9CF */ +0xFB41,0x8C55,0x0000, 0xFB84,0xFCA8,0x0000, 0xFB41,0x8CAB,0x0000, /* 2F9D2 */ +0xFB41,0x8CC1,0x0000, 0xFB41,0x8D1B,0x0000, 0xFB41,0x8D77,0x0000, /* 2F9D5 */ +0xFB84,0xFF2F,0x0000, 0xFB84,0x8804,0x0000, 0xFB41,0x8DCB,0x0000, /* 2F9D8 */ +0xFB41,0x8DBC,0x0000, 0xFB41,0x8DF0,0x0000, 0xFB84,0x88DE,0x0000, /* 2F9DB */ +0xFB41,0x8ED4,0x0000, 0xFB41,0x8F38,0x0000, 0xFB85,0x85D2,0x0000, /* 2F9DE */ +0xFB85,0x85ED,0x0000, 0xFB41,0x9094,0x0000, 0xFB41,0x90F1,0x0000, /* 2F9E1 */ +0xFB41,0x9111,0x0000, 0xFB85,0x872E,0x0000, 0xFB41,0x911B,0x0000, /* 2F9E4 */ +0xFB41,0x9238,0x0000, 0xFB41,0x92D7,0x0000, 0xFB41,0x92D8,0x0000, /* 2F9E7 */ +0xFB41,0x927C,0x0000, 0xFB41,0x93F9,0x0000, 0xFB41,0x9415,0x0000, /* 2F9EA */ +0xFB85,0x8BFA,0x0000, 0xFB41,0x958B,0x0000, 0xFB80,0xC995,0x0000, /* 2F9ED */ +0xFB41,0x95B7,0x0000, 0xFB85,0x8D77,0x0000, 0xFB80,0xC9E6,0x0000, /* 2F9F0 */ +0xFB41,0x96C3,0x0000, 0xFB40,0xDDB2,0x0000, 0xFB41,0x9723,0x0000, /* 2F9F3 */ +0xFB85,0x9145,0x0000, 0xFB85,0x921A,0x0000, 0xFB80,0xCA6E,0x0000, /* 2F9F6 */ +0xFB80,0xCA76,0x0000, 0xFB41,0x97E0,0x0000, 0xFB85,0x940A,0x0000, /* 2F9F9 */ +0xFB80,0xCAB2,0x0000, 0xFB85,0x9496,0x0000, 0xFB41,0x980B,0x0000, /* 2F9FC */ +0xFB41,0x980B,0x0000 }; + +uint16 uca520_p2FA[]= { /* 2FA00 (3 weights per char) */ +0xFB41,0x9829,0x0000, 0xFB85,0x95B6,0x0000, 0xFB41,0x98E2,0x0000, /* 2FA00 */ +0xFB80,0xCB33,0x0000, 0xFB41,0x9929,0x0000, 0xFB41,0x99A7,0x0000, /* 2FA03 */ +0xFB41,0x99C2,0x0000, 0xFB41,0x99FE,0x0000, 0xFB80,0xCBCE,0x0000, /* 2FA06 */ +0xFB85,0x9B30,0x0000, 0xFB41,0x9B12,0x0000, 0xFB41,0x9C40,0x0000, /* 2FA09 */ +0xFB41,0x9CFD,0x0000, 0xFB80,0xCCCE,0x0000, 0xFB80,0xCCED,0x0000, /* 2FA0C */ +0xFB41,0x9D67,0x0000, 0xFB85,0xA0CE,0x0000, 0xFB80,0xCCF8,0x0000, /* 2FA0F */ +0xFB85,0xA105,0x0000, 0xFB85,0xA20E,0x0000, 0xFB85,0xA291,0x0000, /* 2FA12 */ +0xFB41,0x9EBB,0x0000, 0xFB80,0xCD56,0x0000, 0xFB41,0x9EF9,0x0000, /* 2FA15 */ +0xFB41,0x9EFE,0x0000, 0xFB41,0x9F05,0x0000, 0xFB41,0x9F0F,0x0000, /* 2FA18 */ +0xFB41,0x9F16,0x0000, 0xFB41,0x9F3B,0x0000, 0xFB85,0xA600,0x0000, /* 2FA1B */ +0xFBC5,0xFA1E,0x0000, 0xFBC5,0xFA1F,0x0000, 0xFBC5,0xFA20,0x0000, /* 2FA1E */ +0xFBC5,0xFA21,0x0000, 0xFBC5,0xFA22,0x0000, 0xFBC5,0xFA23,0x0000, /* 2FA21 */ +0xFBC5,0xFA24,0x0000, 0xFBC5,0xFA25,0x0000, 0xFBC5,0xFA26,0x0000, /* 2FA24 */ +0xFBC5,0xFA27,0x0000, 0xFBC5,0xFA28,0x0000, 0xFBC5,0xFA29,0x0000, /* 2FA27 */ +0xFBC5,0xFA2A,0x0000, 0xFBC5,0xFA2B,0x0000, 0xFBC5,0xFA2C,0x0000, /* 2FA2A */ +0xFBC5,0xFA2D,0x0000, 0xFBC5,0xFA2E,0x0000, 0xFBC5,0xFA2F,0x0000, /* 2FA2D */ +0xFBC5,0xFA30,0x0000, 0xFBC5,0xFA31,0x0000, 0xFBC5,0xFA32,0x0000, /* 2FA30 */ +0xFBC5,0xFA33,0x0000, 0xFBC5,0xFA34,0x0000, 0xFBC5,0xFA35,0x0000, /* 2FA33 */ +0xFBC5,0xFA36,0x0000, 0xFBC5,0xFA37,0x0000, 0xFBC5,0xFA38,0x0000, /* 2FA36 */ +0xFBC5,0xFA39,0x0000, 0xFBC5,0xFA3A,0x0000, 0xFBC5,0xFA3B,0x0000, /* 2FA39 */ +0xFBC5,0xFA3C,0x0000, 0xFBC5,0xFA3D,0x0000, 0xFBC5,0xFA3E,0x0000, /* 2FA3C */ +0xFBC5,0xFA3F,0x0000, 0xFBC5,0xFA40,0x0000, 0xFBC5,0xFA41,0x0000, /* 2FA3F */ +0xFBC5,0xFA42,0x0000, 0xFBC5,0xFA43,0x0000, 0xFBC5,0xFA44,0x0000, /* 2FA42 */ +0xFBC5,0xFA45,0x0000, 0xFBC5,0xFA46,0x0000, 0xFBC5,0xFA47,0x0000, /* 2FA45 */ +0xFBC5,0xFA48,0x0000, 0xFBC5,0xFA49,0x0000, 0xFBC5,0xFA4A,0x0000, /* 2FA48 */ +0xFBC5,0xFA4B,0x0000, 0xFBC5,0xFA4C,0x0000, 0xFBC5,0xFA4D,0x0000, /* 2FA4B */ +0xFBC5,0xFA4E,0x0000, 0xFBC5,0xFA4F,0x0000, 0xFBC5,0xFA50,0x0000, /* 2FA4E */ +0xFBC5,0xFA51,0x0000, 0xFBC5,0xFA52,0x0000, 0xFBC5,0xFA53,0x0000, /* 2FA51 */ +0xFBC5,0xFA54,0x0000, 0xFBC5,0xFA55,0x0000, 0xFBC5,0xFA56,0x0000, /* 2FA54 */ +0xFBC5,0xFA57,0x0000, 0xFBC5,0xFA58,0x0000, 0xFBC5,0xFA59,0x0000, /* 2FA57 */ +0xFBC5,0xFA5A,0x0000, 0xFBC5,0xFA5B,0x0000, 0xFBC5,0xFA5C,0x0000, /* 2FA5A */ +0xFBC5,0xFA5D,0x0000, 0xFBC5,0xFA5E,0x0000, 0xFBC5,0xFA5F,0x0000, /* 2FA5D */ +0xFBC5,0xFA60,0x0000, 0xFBC5,0xFA61,0x0000, 0xFBC5,0xFA62,0x0000, /* 2FA60 */ +0xFBC5,0xFA63,0x0000, 0xFBC5,0xFA64,0x0000, 0xFBC5,0xFA65,0x0000, /* 2FA63 */ +0xFBC5,0xFA66,0x0000, 0xFBC5,0xFA67,0x0000, 0xFBC5,0xFA68,0x0000, /* 2FA66 */ +0xFBC5,0xFA69,0x0000, 0xFBC5,0xFA6A,0x0000, 0xFBC5,0xFA6B,0x0000, /* 2FA69 */ +0xFBC5,0xFA6C,0x0000, 0xFBC5,0xFA6D,0x0000, 0xFBC5,0xFA6E,0x0000, /* 2FA6C */ +0xFBC5,0xFA6F,0x0000, 0xFBC5,0xFA70,0x0000, 0xFBC5,0xFA71,0x0000, /* 2FA6F */ +0xFBC5,0xFA72,0x0000, 0xFBC5,0xFA73,0x0000, 0xFBC5,0xFA74,0x0000, /* 2FA72 */ +0xFBC5,0xFA75,0x0000, 0xFBC5,0xFA76,0x0000, 0xFBC5,0xFA77,0x0000, /* 2FA75 */ +0xFBC5,0xFA78,0x0000, 0xFBC5,0xFA79,0x0000, 0xFBC5,0xFA7A,0x0000, /* 2FA78 */ +0xFBC5,0xFA7B,0x0000, 0xFBC5,0xFA7C,0x0000, 0xFBC5,0xFA7D,0x0000, /* 2FA7B */ +0xFBC5,0xFA7E,0x0000, 0xFBC5,0xFA7F,0x0000, 0xFBC5,0xFA80,0x0000, /* 2FA7E */ +0xFBC5,0xFA81,0x0000, 0xFBC5,0xFA82,0x0000, 0xFBC5,0xFA83,0x0000, /* 2FA81 */ +0xFBC5,0xFA84,0x0000, 0xFBC5,0xFA85,0x0000, 0xFBC5,0xFA86,0x0000, /* 2FA84 */ +0xFBC5,0xFA87,0x0000, 0xFBC5,0xFA88,0x0000, 0xFBC5,0xFA89,0x0000, /* 2FA87 */ +0xFBC5,0xFA8A,0x0000, 0xFBC5,0xFA8B,0x0000, 0xFBC5,0xFA8C,0x0000, /* 2FA8A */ +0xFBC5,0xFA8D,0x0000, 0xFBC5,0xFA8E,0x0000, 0xFBC5,0xFA8F,0x0000, /* 2FA8D */ +0xFBC5,0xFA90,0x0000, 0xFBC5,0xFA91,0x0000, 0xFBC5,0xFA92,0x0000, /* 2FA90 */ +0xFBC5,0xFA93,0x0000, 0xFBC5,0xFA94,0x0000, 0xFBC5,0xFA95,0x0000, /* 2FA93 */ +0xFBC5,0xFA96,0x0000, 0xFBC5,0xFA97,0x0000, 0xFBC5,0xFA98,0x0000, /* 2FA96 */ +0xFBC5,0xFA99,0x0000, 0xFBC5,0xFA9A,0x0000, 0xFBC5,0xFA9B,0x0000, /* 2FA99 */ +0xFBC5,0xFA9C,0x0000, 0xFBC5,0xFA9D,0x0000, 0xFBC5,0xFA9E,0x0000, /* 2FA9C */ +0xFBC5,0xFA9F,0x0000, 0xFBC5,0xFAA0,0x0000, 0xFBC5,0xFAA1,0x0000, /* 2FA9F */ +0xFBC5,0xFAA2,0x0000, 0xFBC5,0xFAA3,0x0000, 0xFBC5,0xFAA4,0x0000, /* 2FAA2 */ +0xFBC5,0xFAA5,0x0000, 0xFBC5,0xFAA6,0x0000, 0xFBC5,0xFAA7,0x0000, /* 2FAA5 */ +0xFBC5,0xFAA8,0x0000, 0xFBC5,0xFAA9,0x0000, 0xFBC5,0xFAAA,0x0000, /* 2FAA8 */ +0xFBC5,0xFAAB,0x0000, 0xFBC5,0xFAAC,0x0000, 0xFBC5,0xFAAD,0x0000, /* 2FAAB */ +0xFBC5,0xFAAE,0x0000, 0xFBC5,0xFAAF,0x0000, 0xFBC5,0xFAB0,0x0000, /* 2FAAE */ +0xFBC5,0xFAB1,0x0000, 0xFBC5,0xFAB2,0x0000, 0xFBC5,0xFAB3,0x0000, /* 2FAB1 */ +0xFBC5,0xFAB4,0x0000, 0xFBC5,0xFAB5,0x0000, 0xFBC5,0xFAB6,0x0000, /* 2FAB4 */ +0xFBC5,0xFAB7,0x0000, 0xFBC5,0xFAB8,0x0000, 0xFBC5,0xFAB9,0x0000, /* 2FAB7 */ +0xFBC5,0xFABA,0x0000, 0xFBC5,0xFABB,0x0000, 0xFBC5,0xFABC,0x0000, /* 2FABA */ +0xFBC5,0xFABD,0x0000, 0xFBC5,0xFABE,0x0000, 0xFBC5,0xFABF,0x0000, /* 2FABD */ +0xFBC5,0xFAC0,0x0000, 0xFBC5,0xFAC1,0x0000, 0xFBC5,0xFAC2,0x0000, /* 2FAC0 */ +0xFBC5,0xFAC3,0x0000, 0xFBC5,0xFAC4,0x0000, 0xFBC5,0xFAC5,0x0000, /* 2FAC3 */ +0xFBC5,0xFAC6,0x0000, 0xFBC5,0xFAC7,0x0000, 0xFBC5,0xFAC8,0x0000, /* 2FAC6 */ +0xFBC5,0xFAC9,0x0000, 0xFBC5,0xFACA,0x0000, 0xFBC5,0xFACB,0x0000, /* 2FAC9 */ +0xFBC5,0xFACC,0x0000, 0xFBC5,0xFACD,0x0000, 0xFBC5,0xFACE,0x0000, /* 2FACC */ +0xFBC5,0xFACF,0x0000, 0xFBC5,0xFAD0,0x0000, 0xFBC5,0xFAD1,0x0000, /* 2FACF */ +0xFBC5,0xFAD2,0x0000, 0xFBC5,0xFAD3,0x0000, 0xFBC5,0xFAD4,0x0000, /* 2FAD2 */ +0xFBC5,0xFAD5,0x0000, 0xFBC5,0xFAD6,0x0000, 0xFBC5,0xFAD7,0x0000, /* 2FAD5 */ +0xFBC5,0xFAD8,0x0000, 0xFBC5,0xFAD9,0x0000, 0xFBC5,0xFADA,0x0000, /* 2FAD8 */ +0xFBC5,0xFADB,0x0000, 0xFBC5,0xFADC,0x0000, 0xFBC5,0xFADD,0x0000, /* 2FADB */ +0xFBC5,0xFADE,0x0000, 0xFBC5,0xFADF,0x0000, 0xFBC5,0xFAE0,0x0000, /* 2FADE */ +0xFBC5,0xFAE1,0x0000, 0xFBC5,0xFAE2,0x0000, 0xFBC5,0xFAE3,0x0000, /* 2FAE1 */ +0xFBC5,0xFAE4,0x0000, 0xFBC5,0xFAE5,0x0000, 0xFBC5,0xFAE6,0x0000, /* 2FAE4 */ +0xFBC5,0xFAE7,0x0000, 0xFBC5,0xFAE8,0x0000, 0xFBC5,0xFAE9,0x0000, /* 2FAE7 */ +0xFBC5,0xFAEA,0x0000, 0xFBC5,0xFAEB,0x0000, 0xFBC5,0xFAEC,0x0000, /* 2FAEA */ +0xFBC5,0xFAED,0x0000, 0xFBC5,0xFAEE,0x0000, 0xFBC5,0xFAEF,0x0000, /* 2FAED */ +0xFBC5,0xFAF0,0x0000, 0xFBC5,0xFAF1,0x0000, 0xFBC5,0xFAF2,0x0000, /* 2FAF0 */ +0xFBC5,0xFAF3,0x0000, 0xFBC5,0xFAF4,0x0000, 0xFBC5,0xFAF5,0x0000, /* 2FAF3 */ +0xFBC5,0xFAF6,0x0000, 0xFBC5,0xFAF7,0x0000, 0xFBC5,0xFAF8,0x0000, /* 2FAF6 */ +0xFBC5,0xFAF9,0x0000, 0xFBC5,0xFAFA,0x0000, 0xFBC5,0xFAFB,0x0000, /* 2FAF9 */ +0xFBC5,0xFAFC,0x0000, 0xFBC5,0xFAFD,0x0000, 0xFBC5,0xFAFE,0x0000, /* 2FAFC */ +0xFBC5,0xFAFF,0x0000 }; + +uint16 uca520_pE00[]= { /* E0000 (3 weights per char) */ +0xFBDC,0x8000,0x0000, 0x0000,0x0000,0x0000, 0xFBDC,0x8002,0x0000, /* E0000 */ +0xFBDC,0x8003,0x0000, 0xFBDC,0x8004,0x0000, 0xFBDC,0x8005,0x0000, /* E0003 */ +0xFBDC,0x8006,0x0000, 0xFBDC,0x8007,0x0000, 0xFBDC,0x8008,0x0000, /* E0006 */ +0xFBDC,0x8009,0x0000, 0xFBDC,0x800A,0x0000, 0xFBDC,0x800B,0x0000, /* E0009 */ +0xFBDC,0x800C,0x0000, 0xFBDC,0x800D,0x0000, 0xFBDC,0x800E,0x0000, /* E000C */ +0xFBDC,0x800F,0x0000, 0xFBDC,0x8010,0x0000, 0xFBDC,0x8011,0x0000, /* E000F */ +0xFBDC,0x8012,0x0000, 0xFBDC,0x8013,0x0000, 0xFBDC,0x8014,0x0000, /* E0012 */ +0xFBDC,0x8015,0x0000, 0xFBDC,0x8016,0x0000, 0xFBDC,0x8017,0x0000, /* E0015 */ +0xFBDC,0x8018,0x0000, 0xFBDC,0x8019,0x0000, 0xFBDC,0x801A,0x0000, /* E0018 */ +0xFBDC,0x801B,0x0000, 0xFBDC,0x801C,0x0000, 0xFBDC,0x801D,0x0000, /* E001B */ +0xFBDC,0x801E,0x0000, 0xFBDC,0x801F,0x0000, 0x0000,0x0000,0x0000, /* E001E */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0021 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0024 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0027 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E002A */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E002D */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0030 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0033 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0036 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0039 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E003C */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E003F */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0042 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0045 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0048 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E004B */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E004E */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0051 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0054 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0057 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E005A */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E005D */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0060 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0063 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0066 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0069 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E006C */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E006F */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0072 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0075 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0078 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E007B */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0xFBDC,0x8080,0x0000, /* E007E */ +0xFBDC,0x8081,0x0000, 0xFBDC,0x8082,0x0000, 0xFBDC,0x8083,0x0000, /* E0081 */ +0xFBDC,0x8084,0x0000, 0xFBDC,0x8085,0x0000, 0xFBDC,0x8086,0x0000, /* E0084 */ +0xFBDC,0x8087,0x0000, 0xFBDC,0x8088,0x0000, 0xFBDC,0x8089,0x0000, /* E0087 */ +0xFBDC,0x808A,0x0000, 0xFBDC,0x808B,0x0000, 0xFBDC,0x808C,0x0000, /* E008A */ +0xFBDC,0x808D,0x0000, 0xFBDC,0x808E,0x0000, 0xFBDC,0x808F,0x0000, /* E008D */ +0xFBDC,0x8090,0x0000, 0xFBDC,0x8091,0x0000, 0xFBDC,0x8092,0x0000, /* E0090 */ +0xFBDC,0x8093,0x0000, 0xFBDC,0x8094,0x0000, 0xFBDC,0x8095,0x0000, /* E0093 */ +0xFBDC,0x8096,0x0000, 0xFBDC,0x8097,0x0000, 0xFBDC,0x8098,0x0000, /* E0096 */ +0xFBDC,0x8099,0x0000, 0xFBDC,0x809A,0x0000, 0xFBDC,0x809B,0x0000, /* E0099 */ +0xFBDC,0x809C,0x0000, 0xFBDC,0x809D,0x0000, 0xFBDC,0x809E,0x0000, /* E009C */ +0xFBDC,0x809F,0x0000, 0xFBDC,0x80A0,0x0000, 0xFBDC,0x80A1,0x0000, /* E009F */ +0xFBDC,0x80A2,0x0000, 0xFBDC,0x80A3,0x0000, 0xFBDC,0x80A4,0x0000, /* E00A2 */ +0xFBDC,0x80A5,0x0000, 0xFBDC,0x80A6,0x0000, 0xFBDC,0x80A7,0x0000, /* E00A5 */ +0xFBDC,0x80A8,0x0000, 0xFBDC,0x80A9,0x0000, 0xFBDC,0x80AA,0x0000, /* E00A8 */ +0xFBDC,0x80AB,0x0000, 0xFBDC,0x80AC,0x0000, 0xFBDC,0x80AD,0x0000, /* E00AB */ +0xFBDC,0x80AE,0x0000, 0xFBDC,0x80AF,0x0000, 0xFBDC,0x80B0,0x0000, /* E00AE */ +0xFBDC,0x80B1,0x0000, 0xFBDC,0x80B2,0x0000, 0xFBDC,0x80B3,0x0000, /* E00B1 */ +0xFBDC,0x80B4,0x0000, 0xFBDC,0x80B5,0x0000, 0xFBDC,0x80B6,0x0000, /* E00B4 */ +0xFBDC,0x80B7,0x0000, 0xFBDC,0x80B8,0x0000, 0xFBDC,0x80B9,0x0000, /* E00B7 */ +0xFBDC,0x80BA,0x0000, 0xFBDC,0x80BB,0x0000, 0xFBDC,0x80BC,0x0000, /* E00BA */ +0xFBDC,0x80BD,0x0000, 0xFBDC,0x80BE,0x0000, 0xFBDC,0x80BF,0x0000, /* E00BD */ +0xFBDC,0x80C0,0x0000, 0xFBDC,0x80C1,0x0000, 0xFBDC,0x80C2,0x0000, /* E00C0 */ +0xFBDC,0x80C3,0x0000, 0xFBDC,0x80C4,0x0000, 0xFBDC,0x80C5,0x0000, /* E00C3 */ +0xFBDC,0x80C6,0x0000, 0xFBDC,0x80C7,0x0000, 0xFBDC,0x80C8,0x0000, /* E00C6 */ +0xFBDC,0x80C9,0x0000, 0xFBDC,0x80CA,0x0000, 0xFBDC,0x80CB,0x0000, /* E00C9 */ +0xFBDC,0x80CC,0x0000, 0xFBDC,0x80CD,0x0000, 0xFBDC,0x80CE,0x0000, /* E00CC */ +0xFBDC,0x80CF,0x0000, 0xFBDC,0x80D0,0x0000, 0xFBDC,0x80D1,0x0000, /* E00CF */ +0xFBDC,0x80D2,0x0000, 0xFBDC,0x80D3,0x0000, 0xFBDC,0x80D4,0x0000, /* E00D2 */ +0xFBDC,0x80D5,0x0000, 0xFBDC,0x80D6,0x0000, 0xFBDC,0x80D7,0x0000, /* E00D5 */ +0xFBDC,0x80D8,0x0000, 0xFBDC,0x80D9,0x0000, 0xFBDC,0x80DA,0x0000, /* E00D8 */ +0xFBDC,0x80DB,0x0000, 0xFBDC,0x80DC,0x0000, 0xFBDC,0x80DD,0x0000, /* E00DB */ +0xFBDC,0x80DE,0x0000, 0xFBDC,0x80DF,0x0000, 0xFBDC,0x80E0,0x0000, /* E00DE */ +0xFBDC,0x80E1,0x0000, 0xFBDC,0x80E2,0x0000, 0xFBDC,0x80E3,0x0000, /* E00E1 */ +0xFBDC,0x80E4,0x0000, 0xFBDC,0x80E5,0x0000, 0xFBDC,0x80E6,0x0000, /* E00E4 */ +0xFBDC,0x80E7,0x0000, 0xFBDC,0x80E8,0x0000, 0xFBDC,0x80E9,0x0000, /* E00E7 */ +0xFBDC,0x80EA,0x0000, 0xFBDC,0x80EB,0x0000, 0xFBDC,0x80EC,0x0000, /* E00EA */ +0xFBDC,0x80ED,0x0000, 0xFBDC,0x80EE,0x0000, 0xFBDC,0x80EF,0x0000, /* E00ED */ +0xFBDC,0x80F0,0x0000, 0xFBDC,0x80F1,0x0000, 0xFBDC,0x80F2,0x0000, /* E00F0 */ +0xFBDC,0x80F3,0x0000, 0xFBDC,0x80F4,0x0000, 0xFBDC,0x80F5,0x0000, /* E00F3 */ +0xFBDC,0x80F6,0x0000, 0xFBDC,0x80F7,0x0000, 0xFBDC,0x80F8,0x0000, /* E00F6 */ +0xFBDC,0x80F9,0x0000, 0xFBDC,0x80FA,0x0000, 0xFBDC,0x80FB,0x0000, /* E00F9 */ +0xFBDC,0x80FC,0x0000, 0xFBDC,0x80FD,0x0000, 0xFBDC,0x80FE,0x0000, /* E00FC */ +0xFBDC,0x80FF,0x0000 }; + +uint16 uca520_pE01[]= { /* E0100 (3 weights per char) */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0100 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0103 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0106 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0109 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E010C */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E010F */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0112 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0115 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0118 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E011B */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E011E */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0121 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0124 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0127 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E012A */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E012D */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0130 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0133 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0136 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0139 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E013C */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E013F */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0142 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0145 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0148 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E014B */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E014E */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0151 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0154 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0157 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E015A */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E015D */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0160 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0163 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0166 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0169 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E016C */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E016F */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0172 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0175 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0178 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E017B */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E017E */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0181 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0184 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0187 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E018A */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E018D */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0190 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0193 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0196 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E0199 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E019C */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E019F */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01A2 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01A5 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01A8 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01AB */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01AE */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01B1 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01B4 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01B7 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01BA */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01BD */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01C0 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01C3 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01C6 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01C9 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01CC */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01CF */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01D2 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01D5 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01D8 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01DB */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01DE */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01E1 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01E4 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01E7 */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01EA */ +0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, /* E01ED */ +0xFBDC,0x81F0,0x0000, 0xFBDC,0x81F1,0x0000, 0xFBDC,0x81F2,0x0000, /* E01F0 */ +0xFBDC,0x81F3,0x0000, 0xFBDC,0x81F4,0x0000, 0xFBDC,0x81F5,0x0000, /* E01F3 */ +0xFBDC,0x81F6,0x0000, 0xFBDC,0x81F7,0x0000, 0xFBDC,0x81F8,0x0000, /* E01F6 */ +0xFBDC,0x81F9,0x0000, 0xFBDC,0x81FA,0x0000, 0xFBDC,0x81FB,0x0000, /* E01F9 */ +0xFBDC,0x81FC,0x0000, 0xFBDC,0x81FD,0x0000, 0xFBDC,0x81FE,0x0000, /* E01FC */ +0xFBDC,0x81FF,0x0000 }; + +uchar uca520_length[4352]={ +4,3,3,4,2,3,3,3,3,3,3,3,3,3,3,3, +4,2,3,3,2,2,3,3,3,4,4,3,3,3,3,3, +5,5,4,3,5,2,3,3,2,2,5,3,4,3,3,3, +3,3,8,9,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,3,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,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, +2,2,2,2,3,2,3,3,3,3,3,3,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,3,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,3,3,4,3,9,4,3, +3,3,3,3,3,0,0,0,3,3,3,3,3,0,3,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,3,3,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,3,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,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,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,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,4,5,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,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,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,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,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,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,3,3,3,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,0,0,0,0,0, +3,3,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +}; +uint16 *uca520_weight[4352]={ +uca520_p000,uca520_p001,uca520_p002,uca520_p003, +uca520_p004,uca520_p005,uca520_p006,uca520_p007, +uca520_p008,uca520_p009,uca520_p00A,uca520_p00B, +uca520_p00C,uca520_p00D,uca520_p00E,uca520_p00F, +uca520_p010,uca520_p011,uca520_p012,uca520_p013, +uca520_p014,uca520_p015,uca520_p016,uca520_p017, +uca520_p018,uca520_p019,uca520_p01A,uca520_p01B, +uca520_p01C,uca520_p01D,uca520_p01E,uca520_p01F, +uca520_p020,uca520_p021,uca520_p022,uca520_p023, +uca520_p024,uca520_p025,uca520_p026,uca520_p027, +uca520_p028,uca520_p029,uca520_p02A,uca520_p02B, +uca520_p02C,uca520_p02D,uca520_p02E,uca520_p02F, +uca520_p030,uca520_p031,uca520_p032,uca520_p033, +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,uca520_p04D,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +uca520_p0A0,uca520_p0A1,uca520_p0A2,uca520_p0A3, +uca520_p0A4,uca520_p0A5,uca520_p0A6,uca520_p0A7, +uca520_p0A8,uca520_p0A9,uca520_p0AA,uca520_p0AB, +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,uca520_p0D7, +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,uca520_p0F9,uca520_p0FA,uca520_p0FB, +uca520_p0FC,uca520_p0FD,uca520_p0FE,uca520_p0FF, +uca520_p100,uca520_p101,uca520_p102,uca520_p103, +uca520_p104,NULL ,NULL ,NULL , +uca520_p108,uca520_p109,uca520_p10A,uca520_p10B, +uca520_p10C,NULL ,uca520_p10E,NULL , +uca520_p110,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +uca520_p120,uca520_p121,uca520_p122,uca520_p123, +uca520_p124,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +uca520_p130,uca520_p131,uca520_p132,uca520_p133, +uca520_p134,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +uca520_p1D0,uca520_p1D1,uca520_p1D2,uca520_p1D3, +uca520_p1D4,uca520_p1D5,uca520_p1D6,uca520_p1D7, +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +uca520_p1F0,uca520_p1F1,uca520_p1F2,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +uca520_p2F8,uca520_p2F9,uca520_p2FA,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +uca520_pE00,uca520_pE01,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL , +NULL ,NULL ,NULL ,NULL +}; + +static uint16 nochar[]= {0,0}; + +static uchar ctype_utf8[] = { + 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16, + 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16, + 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 +}; + +ObUCAInfo ob_uca_v400= +{ + { + { + 0xFFFF, /* maxchar */ + uca_length, + uca_weight, + { /* Contractions: */ + 0, /* nitems */ + NULL, /* item */ + NULL /* flags */ + } + }, + }, + + /* Logical positions */ + 0x0009, /* first_non_ignorable p != ignore */ + 0xA48C, /* last_non_ignorable Not a CJK and not UNASSIGNED */ + + 0x0332, /* first_primary_ignorable p == 0 */ + 0x20EA, /* last_primary_ignorable */ + + 0x0000, /* first_secondary_ignorable p,s == 0 */ + 0xFE73, /* last_secondary_ignorable p,s == 0 */ + + 0x0000, /* first_tertiary_ignorable p,s,t == 0 */ + 0xFE73, /* last_tertiary_ignorable p,s,t == 0 */ + + 0x0000, /* first_trailing */ + 0x0000, /* last_trailing */ + + 0x0009, /* first_variable */ + 0x2183, /* last_variable */ +}; + +ObUCAInfo ob_uca_v520= +{ + { + { + 0x10FFFF, /* maxchar */ + uca520_length, + uca520_weight, + { /* Contractions: */ + 0, /* nitems */ + NULL, /* item */ + NULL /* flags */ + } + }, + }, + + 0x0009, /* first_non_ignorable p != ignore */ + 0x1342E, /* last_non_ignorable Not a CJK and not UASSIGNED */ + + 0x0332, /* first_primary_ignorable p == ignore */ + 0x101FD, /* last_primary_ignorable */ + + 0x0000, /* first_secondary_ignorable p,s= ignore */ + 0xFE73, /* last_secondary_ignorable */ + + 0x0000, /* first_tertiary_ignorable p,s,t == ignore */ + 0xFE73, /* last_tertiary_ignorable */ + + 0x0000, /* first_trailing */ + 0x0000, /* last_trailing */ + + 0x0009, /* first_variable if alt=non-ignorable: p != ignore */ + 0x1D371, /* last_variable if alt=shifter: p,s,t == ignore */ +}; + +typedef struct ob_uca_scanner_st +{ + const uint16 *wbeg; /* Beginning of the current weight string */ + const uchar *sbeg; /* Beginning of the input string */ + const uchar *send; /* End of the input string */ + const ObUCAWeightLevel *level; + uint16 implicit[2]; + int page; + int code; + const ObCharsetInfo *cs; +} ob_uca_scanner; + +typedef struct ob_uca_scanner_handler_st +{ + void (*init)(ob_uca_scanner *scanner, const ObCharsetInfo *cs, + const ObUCAWeightLevel *level, + const uchar *str, size_t length); + int (*next)(ob_uca_scanner *scanner); +} ob_uca_scanner_handler; + +static inline uint16 * +ob_char_weight_addr(ObUCAWeightLevel *level, uint wc) +{ + uint page, ofst; + return wc > level->maxchar ? NULL : + (level->weights[page= (wc >> 8)] ? + level->weights[page] + (ofst= (wc & 0xFF)) * level->lengths[page] : + NULL); +} + +static int ob_uca_charcmp(const ObCharsetInfo *cs, ob_wc_t wc1, ob_wc_t wc2) +{ + size_t length1, length2; + uint16 *weight1= ob_char_weight_addr(&cs->uca->level[0], wc1); /* W3-TODO */ + uint16 *weight2= ob_char_weight_addr(&cs->uca->level[0], wc2); + + /* Check if some of the characters does not have implicit weights */ + if (!weight1 || !weight2) + return wc1 != wc2; + + /* Quickly compare first weights */ + if (weight1[0] != weight2[0]) + return 1; + + /* Thoroughly compare all weights */ + length1= cs->uca->level[0].lengths[wc1 >> OB_UCA_PSHIFT]; /* W3-TODO */ + length2= cs->uca->level[0].lengths[wc2 >> OB_UCA_PSHIFT]; + + if (length1 > length2) + return memcmp((const void*)weight1, (const void*)weight2, length2*2) ? + 1: weight1[length2]; + + if (length1 < length2) + return memcmp((const void*)weight1, (const void*)weight2, length1*2) ? + 1 : weight2[length1]; + + return memcmp((const void*)weight1, (const void*)weight2, length1*2); +} + +static inline int +ob_space_weight(const ObCharsetInfo *cs) /* W3-TODO */ +{ + return cs->uca->level[0].weights[0][0x20 * cs->uca->level[0].lengths[0]]; +} + +static int ob_strnncoll_uca(const ObCharsetInfo *cs, + ob_uca_scanner_handler *scanner_handler, + const uchar *s, size_t slen, + const uchar *t, size_t tlen, + bool t_is_prefix) +{ + ob_uca_scanner sscanner; + ob_uca_scanner tscanner; + int s_res; + int t_res; + + scanner_handler->init(&sscanner, cs, &cs->uca->level[0], s, slen); + scanner_handler->init(&tscanner, cs, &cs->uca->level[0], t, tlen); + + do + { + s_res= scanner_handler->next(&sscanner); + t_res= scanner_handler->next(&tscanner); + } while ( s_res == t_res && s_res >0); + + return (t_is_prefix && t_res < 0) ? 0 : (s_res - t_res); +} + +static void +ob_uca_scanner_init_any(ob_uca_scanner *scanner, + const ObCharsetInfo *cs, + const ObUCAWeightLevel *level, + const uchar *str, size_t length) +{ + /* Note, no needs to initialize scanner->wbeg */ + scanner->sbeg= str; + scanner->send= str + length; + scanner->wbeg= nochar; + scanner->level= level; + scanner->cs= cs; +} + +static inline bool +ob_uca_have_contractions_quick(const ObUCAWeightLevel *level) +{ + return (level->contractions.nitems > 0); +} + +bool +ob_uca_can_be_previous_context_head(const ObContractions *list, ob_wc_t wc) +{ + return list->flags[wc & OB_UCA_CNT_FLAG_MASK] & OB_UCA_PREVIOUS_CONTEXT_HEAD; +} + + +bool +ob_uca_can_be_previous_context_tail(const ObContractions *list, ob_wc_t wc) +{ + return list->flags[wc & OB_UCA_CNT_FLAG_MASK] & OB_UCA_PREVIOUS_CONTEXT_TAIL; +} + +uint16 * +ob_uca_previous_context_find(ob_uca_scanner *scanner, + ob_wc_t wc0, ob_wc_t wc1) +{ + const ObContractions *list= &scanner->level->contractions; + ObContraction *c, *last; + for (c= list->item, last= c + list->nitems; c < last; c++) + { + if (c->with_context && wc0 == c->ch[0] && wc1 == c->ch[1]) + { + scanner->wbeg= c->weight + 1; + return c->weight; + } + } + return NULL; +} + +static inline bool +ob_uca_can_be_contraction_part(const ObContractions *c, ob_wc_t wc, int flag) +{ + return c->flags[wc & OB_UCA_CNT_FLAG_MASK] & flag; +} + +static int +ob_wmemcmp(ob_wc_t *a, ob_wc_t *b, size_t len) +{ + return memcmp(a, b, len * sizeof(ob_wc_t)); +} + +static inline uint16 * +ob_uca_contraction_weight(const ObContractions *list, ob_wc_t *wc, size_t len) +{ + ObContraction *c, *last; + for (c= list->item, last= c + list->nitems; c < last; c++) + { + if ((len == OB_UCA_MAX_CONTRACTION || c->ch[len] == 0) && + !c->with_context && + !ob_wmemcmp(c->ch, wc, len)) + return c->weight; + } + return NULL; +} + +static uint16 * +ob_uca_scanner_contraction_find(ob_uca_scanner *scanner, ob_wc_t *wc) +{ + size_t clen= 1; + int flag; + const uchar *s, *beg[OB_UCA_MAX_CONTRACTION]; + memset(beg, 0, sizeof(beg)); + + /* Scan all contraction candidates */ + for (s= scanner->sbeg, flag= OB_UCA_CNT_MID1; + clen < OB_UCA_MAX_CONTRACTION; + flag<<= 1) + { + int mblen; + if ((mblen= scanner->cs->cset->mb_wc(scanner->cs, &wc[clen], + s, scanner->send)) <= 0) + break; + beg[clen]= s= s + mblen; + if (!ob_uca_can_be_contraction_part(&scanner->level->contractions, + wc[clen++], flag)) + break; + } + + /* Find among candidates the longest real contraction */ + for ( ; clen > 1; clen--) + { + uint16 *cweight; + if (ob_uca_can_be_contraction_tail(&scanner->level->contractions, + wc[clen - 1]) && + (cweight= ob_uca_contraction_weight(&scanner->level->contractions, + wc, clen))) + { + scanner->wbeg= cweight + 1; + scanner->sbeg= beg[clen - 1]; + return cweight; + } + } + + return NULL; /* No contractions were found */ +} + +static inline int +ob_uca_scanner_next_implicit(ob_uca_scanner *scanner) +{ + scanner->code= (scanner->page << 8) + scanner->code; + scanner->implicit[0]= (scanner->code & 0x7FFF) | 0x8000; + scanner->implicit[1]= 0; + scanner->wbeg= scanner->implicit; + + scanner->page= scanner->page >> 7; + + if (scanner->code >= 0x3400 && scanner->code <= 0x4DB5) + scanner->page+= 0xFB80; + else if (scanner->code >= 0x4E00 && scanner->code <= 0x9FA5) + scanner->page+= 0xFB40; + else + scanner->page+= 0xFBC0; + + return scanner->page; +} + +static int ob_uca_scanner_next_any(ob_uca_scanner *scanner) +{ + if (scanner->wbeg[0]) /* More weights left from the previous step: */ + return *scanner->wbeg++; /* return the next weight from expansion */ + + do + { + uint16 *wpage; + ob_wc_t wc[OB_UCA_MAX_CONTRACTION]; + int mblen; + + /* Get next character */ + if (((mblen= scanner->cs->cset->mb_wc(scanner->cs, wc, + scanner->sbeg, + scanner->send)) <= 0)) + return -1; + + scanner->sbeg+= mblen; + if (wc[0] > scanner->level->maxchar) + { + /* Return 0xFFFD as weight for all characters outside BMP */ + scanner->wbeg= nochar; + return 0xFFFD; + } + + if (ob_uca_have_contractions_quick(scanner->level)) + { + uint16 *cweight; + + if (ob_uca_can_be_previous_context_tail(&scanner->level->contractions, + wc[0]) && + scanner->wbeg != nochar && /* if not the very first character */ + ob_uca_can_be_previous_context_head(&scanner->level->contractions, + (wc[1]= ((scanner->page << 8) + + scanner->code))) && + (cweight= ob_uca_previous_context_find(scanner, wc[1], wc[0]))) + { + scanner->page= scanner->code= 0; /* Clear for the next character */ + return *cweight; + } + else if (ob_uca_can_be_contraction_head(&scanner->level->contractions, + wc[0])) + { + /* Check if w[0] starts a contraction */ + if ((cweight= ob_uca_scanner_contraction_find(scanner, wc))) + return *cweight; + } + } + + /* Process single character */ + scanner->page= wc[0] >> 8; + scanner->code= wc[0] & 0xFF; + + /* If weight page for w[0] does not exist, then calculate algoritmically */ + if (!(wpage= scanner->level->weights[scanner->page])) + return ob_uca_scanner_next_implicit(scanner); + + /* Calculate pointer to w[0]'s weight, using page and offset */ + scanner->wbeg= wpage + + scanner->code * scanner->level->lengths[scanner->page]; + } while (!scanner->wbeg[0]); /* Skip ignorable characters */ + + return *scanner->wbeg++; +} + +static ob_uca_scanner_handler ob_any_uca_scanner_handler= +{ + ob_uca_scanner_init_any, + ob_uca_scanner_next_any +}; + +static int ob_strnncoll_any_uca(const ObCharsetInfo *cs, + const uchar *s, size_t slen, + const uchar *t, size_t tlen, + bool t_is_prefix) +{ + return ob_strnncoll_uca(cs, &ob_any_uca_scanner_handler, + s, slen, t, tlen, t_is_prefix); +} + +static int ob_strnncollsp_uca(const ObCharsetInfo *cs, + ob_uca_scanner_handler *scanner_handler, + const uchar *s, size_t slen, + const uchar *t, size_t tlen, + bool diff_if_only_endspace_difference) +{ + ob_uca_scanner sscanner, tscanner; + int s_res, t_res; + +//#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE +// diff_if_only_endspace_difference= 0; +//#endif + + scanner_handler->init(&sscanner, cs, &cs->uca->level[0], s, slen); + scanner_handler->init(&tscanner, cs, &cs->uca->level[0], t, tlen); + + do + { + s_res= scanner_handler->next(&sscanner); + t_res= scanner_handler->next(&tscanner); + } while ( s_res == t_res && s_res >0); + + if (s_res > 0 && t_res < 0) + { + if (diff_if_only_endspace_difference) + return 1; + /* Calculate weight for SPACE character */ + t_res= ob_space_weight(cs); + + /* compare the first string to spaces */ + do + { + if (s_res != t_res) + return (s_res - t_res); + s_res= scanner_handler->next(&sscanner); + } while (s_res > 0); + return 0; + } + + if (s_res < 0 && t_res > 0) + { + if (diff_if_only_endspace_difference) + return -1; + /* Calculate weight for SPACE character */ + s_res= ob_space_weight(cs); + + /* compare the second string to spaces */ + do + { + if (s_res != t_res) + return (s_res - t_res); + t_res= scanner_handler->next(&tscanner); + } while (t_res > 0); + return 0; + } + + return ( s_res - t_res ); +} + +static int ob_strnncollsp_any_uca(const ObCharsetInfo *cs, + const uchar *s, size_t slen, + const uchar *t, size_t tlen, + bool diff_if_only_endspace_difference) +{ + return ob_strnncollsp_uca(cs, &ob_any_uca_scanner_handler, + s, slen, t, tlen, + diff_if_only_endspace_difference); +} + +static size_t +ob_strnxfrm_uca(const ObCharsetInfo *cs, + ob_uca_scanner_handler *scanner_handler, + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags) +{ + uchar *d0= dst; + uchar *de= dst + dstlen; + int s_res; + ob_uca_scanner scanner; + scanner_handler->init(&scanner, cs, &cs->uca->level[0], src, srclen); + + for (; dst < de && nweights && + (s_res= scanner_handler->next(&scanner)) > 0 ; nweights--) + { + *dst++= s_res >> 8; + if (dst < de) + *dst++= s_res & 0xFF; + } + + if (dst < de && nweights && (flags & OB_STRXFRM_PAD_WITH_SPACE)) + { + uint space_count= OB_MIN((uint) (de - dst) / 2, nweights); + s_res= ob_space_weight(cs); + for (; space_count ; space_count--) + { + *dst++= s_res >> 8; + *dst++= s_res & 0xFF; + } + } + ob_strxfrm_desc_and_reverse(d0, dst, flags, 0); + if ((flags & OB_STRXFRM_PAD_TO_MAXLEN) && dst < de) + { + s_res= ob_space_weight(cs); + for ( ; dst < de; ) + { + *dst++= s_res >> 8; + if (dst < de) + *dst++= s_res & 0xFF; + } + } + return dst - d0; +} + +static size_t ob_strnxfrm_any_uca(const ObCharsetInfo *cs, + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags, + bool *is_valid_unicode) +{ + return ob_strnxfrm_uca(cs, &ob_any_uca_scanner_handler, + dst, dstlen, nweights, src, srclen, flags); +} + +static +int ob_wildcmp_uca_impl(const ObCharsetInfo *cs, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many, int recurse_level) +{ + int result= -1; /* Not found, using wildcards */ + ob_wc_t s_wc, w_wc; + int scan; + int (*mb_wc)(const struct ObCharsetInfo *, ob_wc_t *, + const uchar *, const uchar *); + mb_wc= cs->cset->mb_wc; + + /** if (ob_string_stack_guard && ob_string_stack_guard(recurse_level)) */ + /** return 1; */ + while (wildstr != wildend) + { + while (1) + { + bool escaped= 0; + if ((scan= mb_wc(cs, &w_wc, (const uchar*)wildstr, + (const uchar*)wildend)) <= 0) + return 1; + + if (w_wc == (ob_wc_t)w_many) + { + result= 1; /* Found an anchor char */ + break; + } + + wildstr+= scan; + if (w_wc == (ob_wc_t)escape) + { + if ((scan= mb_wc(cs, &w_wc, (const uchar*)wildstr, + (const uchar*)wildend)) <= 0) + return 1; + wildstr+= scan; + escaped= 1; + } + + if ((scan= mb_wc(cs, &s_wc, (const uchar*)str, + (const uchar*)str_end)) <= 0) + return 1; + str+= scan; + + if (!escaped && w_wc == (ob_wc_t)w_one) + { + result= 1; /* Found an anchor char */ + } + else + { + if (ob_uca_charcmp(cs,s_wc,w_wc)) + return 1; + } + if (wildstr == wildend) + return (str != str_end); /* Match if both are at end */ + } + + if (w_wc == (ob_wc_t)w_many) + { /* Found w_many */ + + /* Remove any '%' and '_' from the wild search string */ + for ( ; wildstr != wildend ; ) + { + if ((scan= mb_wc(cs, &w_wc, (const uchar*)wildstr, + (const uchar*)wildend)) <= 0) + return 1; + + if (w_wc == (ob_wc_t)w_many) + { + wildstr+= scan; + continue; + } + + if (w_wc == (ob_wc_t)w_one) + { + wildstr+= scan; + if ((scan= mb_wc(cs, &s_wc, (const uchar*)str, + (const uchar*)str_end)) <= 0) + return 1; + str+= scan; + continue; + } + break; /* Not a wild character */ + } + + if (wildstr == wildend) + return 0; /* Ok if w_many is last */ + + if (str == str_end) + return -1; + + if ((scan= mb_wc(cs, &w_wc, (const uchar*)wildstr, + (const uchar*)wildend)) <= 0) + return 1; + + if (w_wc == (ob_wc_t)escape) + { + wildstr+= scan; + if ((scan= mb_wc(cs, &w_wc, (const uchar*)wildstr, + (const uchar*)wildend)) <= 0) + return 1; + } + + while (1) + { + /* Skip until the first character from wildstr is found */ + while (str != str_end) + { + if ((scan= mb_wc(cs, &s_wc, (const uchar*)str, + (const uchar*)str_end)) <= 0) + return 1; + + if (!ob_uca_charcmp(cs,s_wc,w_wc)) + break; + str+= scan; + } + if (str == str_end) + return -1; + + result= ob_wildcmp_uca_impl(cs, str, str_end, wildstr, wildend, + escape, w_one, w_many, recurse_level + 1); + + if (result <= 0) + return result; + + str+= scan; + } + } + } + return (str != str_end ? 1 : 0); +} + +int ob_wildcmp_uca(const ObCharsetInfo *cs, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many) +{ + return ob_wildcmp_uca_impl(cs, str, str_end, + wildstr, wildend, + escape, w_one, w_many, 1); +} + +static void ob_hash_sort_uca(const ObCharsetInfo *cs, + ob_uca_scanner_handler *scanner_handler, + const uchar *s, size_t slen, + ulong *n1, ulong *n2, + const bool calc_end_space, + hash_algo hash_algo) +{ + int s_res, space_weight; + ob_uca_scanner scanner; + uchar data[HASH_BUFFER_LENGTH]; + uint length = 0; + //slen= cs->cset->lengthsp(cs, (char*) s, slen); + scanner_handler->init(&scanner, cs, &cs->uca->level[0], s, slen); + space_weight = ob_space_weight(cs); + int has_tail_space = 0; + + if (NULL == hash_algo) { + ulong n1_without_tail_space, n2_without_tail_space; + + while ((s_res= scanner_handler->next(&scanner)) >0) + { + if (!calc_end_space) { + if (!has_tail_space && s_res == space_weight) { + has_tail_space = 1; + n1_without_tail_space = *n1; + n2_without_tail_space = *n2; + } else if (has_tail_space && s_res != space_weight) { + has_tail_space = 0; + } else if ((has_tail_space && s_res == space_weight) + || (!has_tail_space && s_res != space_weight)) { + //do nothing + } + } + + n1[0]^= (((n1[0] & 63)+n2[0])*(s_res >> 8))+ (n1[0] << 8); + n2[0]+=3; + n1[0]^= (((n1[0] & 63)+n2[0])*(s_res & 0xFF))+ (n1[0] << 8); + n2[0]+=3; + } + if (has_tail_space) { + *n1 = n1_without_tail_space; + *n2 = n2_without_tail_space; + } + } else { + ulong n1_without_space; + while ((s_res= scanner_handler->next(&scanner)) >0) + { + if (!calc_end_space) { + if (!has_tail_space && s_res == space_weight) { + has_tail_space = 1; + n1_without_space = hash_algo((void*) &data, length, n1[0]); + } else if (has_tail_space && s_res != space_weight) { + has_tail_space = 0; + } else if ((has_tail_space && s_res == space_weight) + || (!has_tail_space && s_res != space_weight)) { + //do nothing + } + } + + if (length > HASH_BUFFER_LENGTH - 4) { + n1[0] = hash_algo((void*) &data, length, n1[0]); + length = 0; + } + memcpy(data + length, &s_res, 4); + length += 4; + } + if (has_tail_space) { + n1[0] = n1_without_space; + } else { + if (length > 0) { + n1[0] = hash_algo((void*) &data, length, n1[0]); + } + } + } +} + +static void ob_hash_sort_any_uca(const ObCharsetInfo *cs, + const uchar *s, size_t slen, + ulong *n1, ulong *n2, + const bool calc_end_space, hash_algo hash_algo) +{ + ob_hash_sort_uca(cs, &ob_any_uca_scanner_handler, s, slen, n1, n2, calc_end_space, hash_algo); +} + +static ObCollationHandler ob_collation_any_uca_handler = +{ + // ob_coll_init_uca, /* init */ + ob_strnncoll_any_uca, + ob_strnncollsp_any_uca, + ob_strnxfrm_any_uca, + /** my_strnxfrmlen_simple, */ + ob_like_range_mb, + ob_wildcmp_uca, + /** NULL, */ + ob_instr_mb, + ob_hash_sort_any_uca, + ob_propagate_complex +}; + +static ObCollationHandler ob_collation_utf16_uca_handler = +{ + // ob_coll_init_uca, /* init */ + ob_strnncoll_any_uca, + ob_strnncollsp_any_uca, + ob_strnxfrm_any_uca, + // my_strnxfrmlen_simple, + ob_like_range_generic, + ob_wildcmp_uca, + // NULL, + ob_instr_mb, + ob_hash_sort_any_uca, + ob_propagate_complex +}; + +#define OB_CS_UTF8MB4_UCA_FLAGS (OB_CS_COMPILED|OB_CS_STRNXFRM|OB_CS_UNICODE|OB_CS_UNICODE_SUPPLEMENT) + +ObCharsetInfo ob_charset_utf8mb4_unicode_ci= +{ + 224,0,0, /* number */ + OB_CS_UTF8MB4_UCA_FLAGS,/* state */ + OB_UTF8MB4, /* csname */ + OB_UTF8MB4_UNICODE_CI,/* name */ + "", /* comment */ + "", /* tailoring */ + ctype_utf8, /* ctype */ + NULL, /* to_lower */ + NULL, /* to_upper */ + NULL, /* sort_order */ + &ob_uca_v400, /* uca */ + //NULL, /* tab_to_uni */ + //NULL, /* tab_from_uni */ + &ob_unicase_default, /* caseinfo */ + NULL, /* state_map */ + NULL, /* ident_map */ + 8, /* strxfrm_multiply */ + 1, /* caseup_multiply */ + 1, /* casedn_multiply */ + 1, /* mbminlen */ + 4, /* mbmaxlen */ + 9, /* min_sort_char */ + 0xFFFF, /* max_sort_char */ + ' ', /* pad char */ + 0, /* escape_with_backslash_is_dangerous */ + 1, /* levels_for_compare */ + 1, /* levels_for_order */ + &ob_charset_utf8mb4_handler, + &ob_collation_any_uca_handler +}; + +#define OB_CS_UTF16_UCA_FLAGS (OB_CS_COMPILED|OB_CS_STRNXFRM|OB_CS_UNICODE|OB_CS_NONASCII) + +ObCharsetInfo ob_charset_utf16_unicode_ci= +{ + 101,0,0, /* number */ + OB_CS_UTF16_UCA_FLAGS,/* state */ + OB_UTF16, /* csname */ + OB_UTF16_UNICODE_CI, /* name */ + "", /* comment */ + "", /* tailoring */ + NULL, /* ctype */ + NULL, /* to_lower */ + NULL, /* to_upper */ + NULL, /* sort_order */ + &ob_uca_v400, /* uca */ + // NULL, /* tab_to_uni */ + // NULL, /* tab_from_uni */ + &ob_unicase_default, /* caseinfo */ + NULL, /* state_map */ + NULL, /* ident_map */ + 8, /* strxfrm_multiply */ + 1, /* caseup_multiply */ + 1, /* casedn_multiply */ + 2, /* mbminlen */ + 4, /* mbmaxlen */ + 9, /* min_sort_char */ + 0xFFFF, /* max_sort_char */ + ' ', /* pad char */ + 0, /* escape_with_backslash_is_dangerous */ + 1, /* levels_for_compare */ + 1, /* levels_for_order */ + &ob_charset_utf16_handler, + &ob_collation_utf16_uca_handler +}; diff --git a/src/lib/charset/ob_ctype_utf16.c b/src/lib/charset/ob_ctype_utf16.c new file mode 100644 index 0000000000000000000000000000000000000000..11c857d03052ac10a846a7cc32a3b60adf0b22d4 --- /dev/null +++ b/src/lib/charset/ob_ctype_utf16.c @@ -0,0 +1,1235 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#include "lib/charset/ob_ctype.h" +#include "lib/charset/ob_dtoa.h" + +#define OB_UTF16_HIGH_HEAD(x) ((((unsigned char) (x)) & 0xFC) == 0xD8) +#define OB_UTF16_LOW_HEAD(x) ((((unsigned char) (x)) & 0xFC) == 0xDC) +#define OB_UTF16_SURROGATE(x) (((x) & 0xF800) == 0xD800) + +#define OB_UTF16_WC2(a, begin) ((a << 8) + begin) + +static inline int +ob_bincmp(const unsigned char *str, const unsigned char *se, + const unsigned char *t, const unsigned char *te) +{ + int s_len= (int) (se - str), t_len= (int) (te - t); + int len= OB_MIN(s_len, t_len); + int cmp= memcmp(str, t, len); + return cmp ? cmp : s_len - t_len; +} + +static inline void +ob_tosort_utf16(ObUnicaseInfo *uni_plane, ob_wc_t *wc) +{ + if (*wc <= uni_plane->maxchar) { + const ObUnicaseInfoChar *page; + if ((page = uni_plane->page[*wc >> 8])) { + *wc= page[*wc & 0xFF].sort; + } + } else { + *wc= OB_CS_REPLACEMENT_CHARACTER; + } +} + +static unsigned int ob_mbcharlen_utf16(const ObCharsetInfo *cs __attribute__((unused)), + unsigned int c __attribute__((unused))) +{ + ob_charset_assert(0); + return OB_UTF16_HIGH_HEAD(c) ? 4 : 2; +} + +static unsigned int ob_ismbchar_utf16(const ObCharsetInfo *cs, const char *begin, const char *end) +{ + ob_wc_t wc; + int res= cs->cset->mb_wc(cs, &wc, (const unsigned char *) begin, (const unsigned char *) end); + return (unsigned int) (res > 0 ? res : 0); +} + +static size_t ob_numchars_utf16(const ObCharsetInfo *cs, + const char *begin, const char *end) +{ + size_t nchars= 0; + size_t char_len= ob_ismbchar_utf16(cs, begin, end); + while (char_len != 0) { + begin+= char_len; + nchars++; + char_len= ob_ismbchar_utf16(cs, begin, end); + } + return nchars; +} + +static size_t +ob_charpos_utf16(const ObCharsetInfo *cs, + const char *begin, const char *end, size_t pos) +{ + const char *b0= begin; + unsigned int char_len; + while (pos) { + if (!(char_len= ob_ismbchar(cs, begin, end))) { + return (end + 2 - b0); + } else { + begin += char_len; + pos--; + } + } + return (size_t) (pos ? (end + 2 - b0) : (begin - b0)); +} + +static size_t +ob_well_formed_len_utf16(const ObCharsetInfo *cs, + const char *begin, const char *end, + size_t nchars, int *error) +{ + const char *b0= begin; + unsigned int char_len; + *error= 0; + while (nchars) { + if (!(char_len = cs->cset->ismbchar(cs, begin, end))) { + *error= begin < end ? 1 : 0; + break; + } else { + begin += char_len; + nchars--; + } + } + return (size_t) (begin - b0); +} + +static size_t +ob_lengthsp_mb2(const ObCharsetInfo *cs __attribute__((unused)), + const char *ptr, size_t length) +{ + const char *end= ptr + length; + while (end > ptr + 1 && end[-1] == ' ' && end[-2] == '\0') + end-= 2; + return (size_t) (end - ptr); +} + +#define OB_UTF16_WC4(a, begin, c, d) (((a & 3) << 18) + (begin << 10) + \ + ((c & 3) << 8) + d + 0x10000) + +static int +ob_utf16_uni(const ObCharsetInfo *cs __attribute__((unused)), + ob_wc_t *pwc, const unsigned char *str, const unsigned char *end) +{ + if (str + 2 > end) { + return OB_CS_TOOSMALL2; + } else if (OB_UTF16_HIGH_HEAD(*str)) { + if (str + 4 > end) { + return OB_CS_TOOSMALL4; + } else if (!OB_UTF16_LOW_HEAD(str[2])) { + return OB_CS_ILSEQ; + } else { + *pwc= OB_UTF16_WC4(str[0], str[1], str[2], str[3]); + return 4; + } + } else if (OB_UTF16_LOW_HEAD(*str)) { + return OB_CS_ILSEQ; + } else { + *pwc= OB_UTF16_WC2(str[0], str[1]); + } + return 2; +} + +static int +ob_uni_utf16(const ObCharsetInfo *cs __attribute__((unused)), + ob_wc_t wc, unsigned char *str, unsigned char *end) +{ + if (wc <= 0xFFFF) { + if (str + 2 > end) { + return OB_CS_TOOSMALL2; + } else if (OB_UTF16_SURROGATE(wc)) { + return OB_CS_ILUNI; + } else { + *str++= (unsigned char) (wc >> 8); + *str= (unsigned char) (wc & 0xFF); + return 2; + } + } else if (wc <= 0x10FFFF) { + if (str + 4 > end) { + return OB_CS_TOOSMALL4; + } else { + *str++= (unsigned char) ((wc-= 0x10000) >> 18) | 0xD8; + *str++= (unsigned char) (wc >> 10) & 0xFF; + *str++= (unsigned char) ((wc >> 8) & 3) | 0xDC; + *str= (unsigned char) wc & 0xFF; + return 4; + } + } + + return OB_CS_ILUNI; +} + +static inline void +ob_toupper_utf16(ObUnicaseInfo *uni_plane, ob_wc_t *wc) +{ + const ObUnicaseInfoChar *page; + if ((*wc <= uni_plane->maxchar) && (page= uni_plane->page[*wc >> 8])) + *wc= page[*wc & 0xFF].toupper; +} + +static inline void +ob_tolower_utf16(ObUnicaseInfo *uni_plane, ob_wc_t *wc) +{ + const ObUnicaseInfoChar *page; + if ((*wc <= uni_plane->maxchar) && (page= uni_plane->page[*wc >> 8])) { + *wc= page[*wc & 0xFF].tolower; + } + return; +} + +static size_t +ob_caseup_utf16(const ObCharsetInfo *cs, char *src, size_t srclen, + char *dst __attribute__((unused)), + size_t dst_len __attribute__((unused))) +{ + ob_wc_t wc; + int res; + char *srcend= src + srclen; + ObUnicaseInfo *uni_plane= cs->caseinfo; + ob_charset_assert(src == dst && srclen == dst_len); + + while ((src < srcend) && + (res= cs->cset->mb_wc(cs, &wc, (unsigned char *) src, (unsigned char *) srcend)) > 0) { + ob_toupper_utf16(uni_plane, &wc); + if (res != cs->cset->wc_mb(cs, wc, (unsigned char *) src, (unsigned char *) srcend)) { + break; + } else { + src+= res; + } + } + return srclen; +} + +static size_t +ob_casedn_utf16(const ObCharsetInfo *cs, char *src, size_t srclen, + char *dst __attribute__((unused)), + size_t dst_len __attribute__((unused))) +{ + ob_wc_t wc; + int res; + char *srcend= src + srclen; + ObUnicaseInfo *uni_plane= cs->caseinfo; + ob_charset_assert(src == dst && srclen == dst_len); + + while ((src < srcend) && + (res= cs->cset->mb_wc(cs, &wc, (unsigned char *) src, (unsigned char *) srcend)) > 0) { + ob_tolower_utf16(uni_plane, &wc); + if (res != cs->cset->wc_mb(cs, wc, (unsigned char *) src, (unsigned char *) srcend)) + break; + src+= res; + } + return srclen; +} + +static void +ob_fill_mb2(const ObCharsetInfo *cs, char *str, size_t s_len, int fill) +{ + char buf[10]; + int buf_len; + + ob_charset_assert((s_len % 2) == 0); + + buf_len= cs->cset->wc_mb(cs, (ob_wc_t) fill, (unsigned char*) buf, + (unsigned char*) buf + sizeof(buf)); + + ob_charset_assert(buf_len > 0); + + while (s_len >= (size_t) buf_len) { + memcpy(str, buf, (size_t) buf_len); + str+= buf_len; + s_len-= buf_len; + } + + while (s_len) { + *str++= 0x00; + s_len--; + } +} + +static long +ob_strntol_mb2_or_mb4(const ObCharsetInfo *cs, + const char *nptr, size_t l, int base, + char **end_ptr, int *err) +{ + int negative= 0; + int overflow; + int cnv; + ob_wc_t wc; + unsigned int cut_lim; + uint32_t cut_off; + uint32_t res; + const unsigned char *str= (const unsigned char*) nptr; + const unsigned char *end= (const unsigned char*) nptr+l; + const unsigned char *save; + + *err=0; + while (TRUE) { + cnv = cs->cset->mb_wc(cs, &wc, str, end); + if (cnv > 0) { + if (wc == ' ') { + //do nothing + } else if (wc == '\t') { + //do nothing + } else if (wc == '-') { + negative = !negative; + } else if (wc == '+') { + //do nothing + } else { + break; + } + } else { + if (end_ptr != NULL) *end_ptr= (char*) str; + err[0]= (cnv==OB_CS_ILSEQ) ? EILSEQ : EDOM; + return 0; + } + str+= cnv; + } + + res = 0; + overflow = 0; + cut_off = ((uint32_t)~0L) / (uint32_t) base; + cut_lim = (unsigned int) (((uint32_t)~0L) % (uint32_t) base); + save = str; + + do { + cnv= cs->cset->mb_wc(cs, &wc, str, end); + if ( cnv > 0) { + str += cnv; + if (wc >= '0' && wc <= '9') { + wc-= '0'; + } else if (wc >= 'A' && wc <= 'Z') { + wc= wc - 'A' + 10; + } else if (wc >= 'a' && wc <= 'z') { + wc= wc - 'a' + 10; + } else { + break; + } + if ((int)wc >= base) { + break; + } else if ((res == cut_off && wc > cut_lim) || res > cut_off) { + overflow= 1; + } else { + res*= (uint32_t) base; + res+= wc; + } + } else if (cnv == OB_CS_ILSEQ) { + if (NULL != end_ptr) { + *end_ptr = (char*) str; + } + err[0]= EILSEQ; + return 0; + } else { + break; + } + } while(TRUE); + + if (end_ptr != NULL) { + *end_ptr = (char *) str; + } + if (str == save) { + err[0]= EDOM; + return 0L; + } else if (negative) { + if (res > (uint32_t) INT_MIN32) + overflow= 1; + } else if (res > INT_MAX32) { + overflow= 1; + } + + if (overflow) { + err[0]= ERANGE; + return negative ? INT_MIN32 : INT_MAX32; + } + + return (negative ? -((long) res) : (long) res); +} + +static unsigned long int +ob_strntoul_mb2_or_mb4(const ObCharsetInfo *cs, + const char *nptr, size_t l, int base, + char **end_ptr, int *err) +{ + int negative= 0; + int overflow; + int cnv; + ob_wc_t wc; + unsigned int cut_lim; + uint32_t cut_off; + uint32_t res; + const unsigned char *str= (const unsigned char*) nptr; + const unsigned char *end= (const unsigned char*) nptr + l; + const unsigned char *save; + + *err= 0; + while (TRUE) { + cnv= cs->cset->mb_wc(cs, &wc, str, end); + if (cnv > 0) { + if (wc == ' ') { + //do nothing + } else if (wc == '\t') { + //do nothing + } else if (wc == '-') { + negative = !negative; + } else if (wc == '+') { + //do nothing + } else { + break; + } + } else { + if (NULL != end_ptr) { + *end_ptr= (char*)str; + } + err[0]= (cnv == OB_CS_ILSEQ) ? EILSEQ : EDOM; + return 0; + } + str+= cnv; + } + + overflow= 0; + res= 0; + save= str; + cut_off= ((uint32_t)~0L) / (uint32_t) base; + cut_lim= (unsigned int) (((uint32_t)~0L) % (uint32_t) base); + + while (TRUE) { + cnv= cs->cset->mb_wc(cs, &wc, str, end); + if (cnv > 0) { + str+= cnv; + if (wc >= '0' && wc <= '9') { + wc-= '0'; + } else if (wc >= 'A' && wc <= 'Z') { + wc= wc - 'A' + 10; + } else if (wc >= 'a' && wc <= 'z') { + wc= wc - 'a' + 10; + } else { + break; + } + if ((int) base <= wc ) { + break; + } else if ((res == cut_off && wc > cut_lim) || res > cut_off) { + overflow = 1; + } else { + res*= (uint32_t) base; + res+= wc; + } + } else if (cnv == OB_CS_ILSEQ) { + if (end_ptr != NULL ) { + *end_ptr= (char*)str; + } + err[0]= EILSEQ; + return 0; + } else { + break; + } + } + + if (end_ptr != NULL) + *end_ptr= (char *) str; + + if (str == save) { + err[0]= EDOM; + return 0L; + } else if (overflow) { + err[0]= (ERANGE); + return (~(uint32_t) 0); + } + + return (negative ? -((long) res) : (long) res); +} + +static longlong +ob_strntoll_mb2_or_mb4(const ObCharsetInfo *cs, + const char *nptr, size_t l, int base, + char **end_ptr, int *err) +{ + int negative=0; + int overflow; + int cnv; + ob_wc_t wc; + uint64_t cut_off; + unsigned int cut_lim; + uint64_t res; + const unsigned char *str= (const unsigned char*) nptr; + const unsigned char *end= (const unsigned char*) nptr+l; + const unsigned char *save; + + *err= 0; + while (TRUE) { + cnv=cs->cset->mb_wc(cs,&wc,str,end); + if (cnv > 0) { + if (wc == ' ') { + //do nothing + } else if (wc == '\t') { + //do nothing + } else if (wc == '-') { + negative = !negative; + } else if (wc == '+') { + //do nothing + } else { + break; + } + } else { + if (NULL != end_ptr) { + *end_ptr = (char*)str; + } + err[0] = (cnv == OB_CS_ILSEQ) ? EILSEQ : EDOM; + return 0; + } + str+=cnv; + } + + overflow = 0; + res = 0; + save = str; + cut_off = (~(uint64_t) 0) / (unsigned long int) base; + cut_lim = (unsigned int) ((~(uint64_t) 0) % (unsigned long int) base); + + while (TRUE) { + cnv=cs->cset->mb_wc(cs,&wc,str,end); + if (cnv > 0) { + str+=cnv; + if ( wc>='0' && wc<='9') { + wc -= '0'; + } else if ( wc>='A' && wc<='Z') { + wc = wc - 'A' + 10; + } else if ( wc>='a' && wc<='z') { + wc = wc - 'a' + 10; + } else { + break; + } + if ((int)wc >= base) { + break; + } else if (res > cut_off || (res == cut_off && wc > cut_lim)) { + overflow = 1; + } else { + res *= (uint64_t) base; + res += wc; + } + } else if (cnv == OB_CS_ILSEQ) { + if (NULL != end_ptr ) + *end_ptr = (char*)str; + err[0]=EILSEQ; + return 0; + } else { + break; + } + } + + if (end_ptr != NULL) { + *end_ptr = (char *) str; + } + + if (str == save) { + err[0]=EDOM; + return 0L; + } + + if (negative) { + if (res > (uint64_t) LONGLONG_MIN) { + overflow = 1; + } + } else if (res > (uint64_t) LONGLONG_MAX) { + overflow = 1; + } + + if (overflow) { + err[0]=ERANGE; + return negative ? LONGLONG_MIN : LONGLONG_MAX; + } + + return (negative ? -((int64_t)res) : (int64_t)res); +} + +static ulonglong +ob_strntoull_mb2_or_mb4(const ObCharsetInfo *cs, + const char *nptr, size_t l, int base, + char **end_ptr, int *err) +{ + int negative = 0; + int overflow = 0; + int cnv; + ob_wc_t wc; + uint64_t cut_off; + unsigned int cut_lim; + uint64_t res = 0; + const unsigned char *str= (const unsigned char*) nptr; + const unsigned char *end= (const unsigned char*) nptr + l; + const unsigned char *save; + + *err= 0; + while (TRUE) { + cnv = cs->cset->mb_wc(cs, &wc, str, end); + if (cnv > 0) { + if ( wc>='0' && wc<='9') { + wc -= '0'; + } else if ( wc>='A' && wc<='Z') { + wc = wc - 'A' + 10; + } else if ( wc>='a' && wc<='z') { + wc = wc - 'a' + 10; + } else { + break; + } + } else { + err[0]= (cnv==OB_CS_ILSEQ) ? EILSEQ : EDOM; + if (NULL != end_ptr) { + *end_ptr = (char*)str; + } + return 0; + } + str+=cnv; + } + + save = str; + cut_off = (~(uint64_t) 0) / (unsigned long int) base; + cut_lim = (unsigned int) ((~(uint64_t) 0) % (unsigned long int) base); + + while(TRUE) { + cnv=cs->cset->mb_wc(cs,&wc,str,end); + if ( cnv> 0 ) { + str+=cnv; + if ( wc>='0' && wc<='9') { + wc -= '0'; + } else if ( wc>='A' && wc<='Z') { + wc = wc - 'A' + 10; + } else if ( wc>='a' && wc<='z') { + wc = wc - 'a' + 10; + } else { + break; + } + if ((int)wc >= base) { + break; + } else if (res > cut_off || (res == cut_off && wc > cut_lim)) { + overflow = 1; + } else { + res *= (uint64_t) base; + res += wc; + } + } else if (OB_CS_ILSEQ == cnv) { + err[0] = EILSEQ; + if (NULL != end_ptr) { + *end_ptr = (char*)str; + } + return 0; + } else { + break; + } + } + + if (NULL != end_ptr) { + *end_ptr = (char *) str; + } + if (str == save) { + err[0]= EDOM; + return 0L; + } else if (overflow) { + err[0]= ERANGE; + return (~(uint64_t) 0); + } + return (negative ? -((int64_t) res) : (int64_t) res); +} + +static double +ob_strntod_mb2_or_mb4(const ObCharsetInfo *cs, + char *nptr, size_t length, + char **end_ptr, int *err) +{ + char buf[256]; + double res; + char *begin= buf; + const unsigned char *str= (const unsigned char*) nptr; + const unsigned char *end; + ob_wc_t wc; + int cnv; + + *err= 0; + + if (length >= sizeof(buf)) { + length= sizeof(buf) - 1; + } + + end= str + length; + cnv= cs->cset->mb_wc(cs,&wc,str,end); + while (cnv > 0) { + str+= cnv; + if (wc > (int) (unsigned char) 'e' || !wc) { + break; + } else { + *begin++= (char) wc; + cnv= cs->cset->mb_wc(cs,&wc,str,end); + } + } + *end_ptr = begin; + res= ob_strtod(buf, end_ptr, err); + *end_ptr= nptr + cs->mbminlen * (size_t) (*end_ptr - buf); + return res; +} + +static ulonglong +ob_strntoull10rnd_mb2_or_mb4(const ObCharsetInfo *cs, + const char *nptr, size_t length, + int unsign_fl, + char **end_ptr, int *err) +{ + char buf[256], *begin= buf; + ob_wc_t wc; + int cnv; + uint64_t res; + const unsigned char *end; + const unsigned char *str= (const unsigned char*) nptr; + + if (length >= sizeof(buf)) { + length= sizeof(buf)-1; + } + end= str + length; + cnv= cs->cset->mb_wc(cs,&wc,str,end); + while (cnv > 0) { + str += cnv; + if (wc > (int) (unsigned char) 'e' || !wc) { + break; + } else { + *begin++= (char) wc; + cnv= cs->cset->mb_wc(cs,&wc,str,end); + } + } + + res= ob_strntoull10rnd_8bit(cs, buf, begin - buf, unsign_fl, end_ptr, err); + *end_ptr= (char*) nptr + cs->mbminlen * (size_t) (*end_ptr - buf); + return res; +} + +static size_t +ob_scan_mb2(const ObCharsetInfo *cs, + const char *str, const char *end, int sequence_type) +{ + const char *str0= str; + ob_wc_t wc; + int res; + + switch (sequence_type) { + case OB_SEQ_SPACES: + for (res= cs->cset->mb_wc(cs, &wc, (const unsigned char *) str, (const unsigned char *) end); + res > 0 && wc == ' '; + str+= res, res= cs->cset->mb_wc(cs, &wc, (const unsigned char *) str, (const unsigned char *) end)) { + } + return (size_t) (str - str0); + default: + return 0; + } +} + +static int +ob_strnncoll_utf16_bin(const ObCharsetInfo *cs, + const unsigned char *str, size_t s_len, + const unsigned char *t, size_t t_len, + bool t_is_prefix) +{ + int s_res,t_res; + ob_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc); + const unsigned char *se=str+s_len; + const unsigned char *te=t+t_len; + + while ( str < se && t < te ) { + s_res= cs->cset->mb_wc(cs, &s_wc, str, se); + t_res= cs->cset->mb_wc(cs, &t_wc, t, te); + + if (s_res <= 0 || t_res <= 0) { + return ob_bincmp(str, se, t, te); + } else if (s_wc != t_wc) { + return s_wc > t_wc ? 1 : -1; + } else { + str+= s_res; + t+= t_res; + } + } + return (int) (t_is_prefix ? (t - te) : ((se - str) - (te - t))); +} + +static int +ob_strnncollsp_utf16_bin(const ObCharsetInfo *cs, + const unsigned char *str, size_t s_len, + const unsigned char *t, size_t t_len, + bool diff_if_only_endspace_difference) +{ + int res; + ob_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc); + const unsigned char *se= str + s_len, *te= t + t_len; + + if (!diff_if_only_endspace_difference) { + ob_charset_assert((s_len % 2) == 0); + ob_charset_assert((t_len % 2) == 0); + } + + while (str < se && t < te) { + int s_res= cs->cset->mb_wc(cs, &s_wc, str, se); + int t_res= cs->cset->mb_wc(cs, &t_wc, t, te); + + if (s_res <= 0 || t_res <= 0) { + return ob_bincmp(str, se, t, te); + } else if (s_wc != t_wc) { + return s_wc > t_wc ? 1 : -1; + } else { + str+= s_res; + t+= t_res; + } + } + + s_len= (size_t) (se - str); + t_len= (size_t) (te - t); + res= 0; + + if (s_len != t_len) { + int s_res, swap= 1; + if (diff_if_only_endspace_difference) { + return s_len < t_len ? -1 : 1; + } else if (s_len < t_len) { + s_len= t_len; + str= t; + se= te; + swap= -1; + res= -res; + } + + while (str < se) { + if ((s_res= cs->cset->mb_wc(cs, &s_wc, str, se)) < 0) { + return 0; + } else if (s_wc != ' ') { + return (s_wc < ' ') ? -swap : swap; + } else { + str += s_res; + } + } + } + return res; +} + +static int +ob_wildcmp_utf16_bin(const ObCharsetInfo *cs, + const char *str,const char *str_end, + const char *wild_str,const char *wild_end, + int escape_char, int w_one, int w_many) +{ + return ob_wildcmp_unicode(cs, str, str_end, wild_str, wild_end, + escape_char, w_one, w_many, NULL); +} + +static void +ob_hash_sort_utf16_bin(const ObCharsetInfo *cs, + const unsigned char *pos, size_t len, + unsigned long int *nr1, unsigned long int *nr2, + const bool calc_end_space, hash_algo hash_algo) +{ + const unsigned char *end= pos + (calc_end_space ? len : cs->cset->lengthsp(cs, (const char *) pos, len)); + + if (NULL == hash_algo) { + while (pos < end) { + nr1[0]^=(unsigned long int) ((((unsigned int) nr1[0] & 63)+nr2[0]) * + ((unsigned int)*pos)) + (nr1[0] << 8); + nr2[0]+=3; + pos++; + } + } else { + nr1[0] = hash_algo((void*)pos, (int)(end - pos), nr1[0]); + } +} + +static int +ob_strnncoll_utf16(const ObCharsetInfo *cs, + const unsigned char *str, size_t s_len, + const unsigned char *t, size_t t_len, + bool t_is_prefix) +{ + int s_res, t_res; + ob_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc); + const unsigned char *se= str + s_len; + const unsigned char *te= t + t_len; + ObUnicaseInfo *uni_plane= cs->caseinfo; + + while (str < se && t < te) { + s_res= cs->cset->mb_wc(cs, &s_wc, str, se); + t_res= cs->cset->mb_wc(cs, &t_wc, t, te); + + if (s_res <= 0 || t_res <= 0) { + return ob_bincmp(str, se, t, te); + } else { + ob_tosort_utf16(uni_plane, &s_wc); + ob_tosort_utf16(uni_plane, &t_wc); + } + if (s_wc != t_wc) { + return s_wc > t_wc ? 1 : -1; + } else { + str+= s_res; + t+= t_res; + } + } + return (int) (t_is_prefix ? (t - te) : ((se - str) - (te - t))); +} + +static int +ob_strnncollsp_utf16(const ObCharsetInfo *cs, + const unsigned char *str, size_t s_len, + const unsigned char *t, size_t t_len, + bool diff_if_only_endspace_difference) +{ + int res; + ob_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc); + const unsigned char *se= str + s_len, *te= t + t_len; + ObUnicaseInfo *uni_plane= cs->caseinfo; + + ob_charset_assert((s_len % 2) == 0); + ob_charset_assert((t_len % 2) == 0); + + while (str < se && t < te) { + int s_res= cs->cset->mb_wc(cs, &s_wc, str, se); + int t_res= cs->cset->mb_wc(cs, &t_wc, t, te); + + if (s_res <= 0 || t_res <= 0) { + return ob_bincmp(str, se, t, te); + } else { + ob_tosort_utf16(uni_plane, &s_wc); + ob_tosort_utf16(uni_plane, &t_wc); + } + if (s_wc != t_wc) { + return s_wc > t_wc ? 1 : -1; + } else { + str+= s_res; + t+= t_res; + } + } + + s_len= (size_t) (se - str); + t_len= (size_t) (te - t); + res= 0; + + if (s_len != t_len) { + int s_res, swap= 1; + if (diff_if_only_endspace_difference) { + return s_len < t_len ? -1 : 1; + } else if (s_len < t_len) { + s_len= t_len; + str= t; + se= te; + swap= -1; + res= -res; + } + + while (str < se) { + if ((s_res= cs->cset->mb_wc(cs, &s_wc, str, se)) < 0) { + ob_charset_assert(0); + return 0; + } else if (s_wc != ' ') { + return (s_wc < ' ') ? -swap : swap; + } else { + str+= s_res; + } + } + } + return res; +} + +static int +ob_wildcmp_utf16_ci(const ObCharsetInfo *cs, + const char *str,const char *str_end, + const char *wild_str,const char *wild_end, + int escape_char, int w_one, int w_many) +{ + ObUnicaseInfo *uni_plane= cs->caseinfo; + return ob_wildcmp_unicode(cs, str, str_end, wild_str, wild_end, + escape_char, w_one, w_many, uni_plane); +} + +static void +ob_hash_sort_utf16(const ObCharsetInfo *cs, const unsigned char *str, size_t s_len, + unsigned long int *n1, unsigned long int *n2, const bool calc_end_space, hash_algo hash_algo) +{ + ob_wc_t wc; + int res; + unsigned int length = 0; + unsigned char data[HASH_BUFFER_LENGTH]; + const unsigned char *end= str + (calc_end_space ? s_len : cs->cset->lengthsp(cs, (const char *) str, s_len)); + ObUnicaseInfo *uni_plane= cs->caseinfo; + + if (NULL == hash_algo) { + while ((str < end) && (res= cs->cset->mb_wc(cs, &wc, (unsigned char *) str, (unsigned char *) end)) > 0) + { + ob_tosort_utf16(uni_plane, &wc); + n1[0]^= (((n1[0] & 63) + n2[0]) * (wc & 0xFF)) + (n1[0] << 8); + n2[0]+= 3; + n1[0]^= (((n1[0] & 63) + n2[0]) * (wc >> 8)) + (n1[0] << 8); + n2[0]+= 3; + str+= res; + } + } else { + while ((str < end) && (res= cs->cset->mb_wc(cs, &wc, (unsigned char *) str, (unsigned char *) end)) > 0) + { + ob_tosort_utf16(uni_plane, &wc); + if (length > HASH_BUFFER_LENGTH - 2) + { + n1[0] = hash_algo((void*) &data, length, n1[0]); + length = 0; + } + data[length++] = (unsigned char)wc; + data[length++] = (unsigned char)(wc >> 8); + str+= res; + } + if (length > 0) { + n1[0] = hash_algo((void*) &data, length, n1[0]); + } + } +} + +bool +ob_like_range_generic(const ObCharsetInfo *cs, + const char *ptr, size_t ptr_length, + char escape_char, char w_one, char w_many, + size_t res_length, + char *min_str,char *max_str, + size_t *min_length,size_t *max_length) +{ + const char *min_org = min_str; + const char *max_org = max_str; + char *min_end= min_str + res_length; + char *max_end= max_str + res_length; + const char *end = ptr + ptr_length; + size_t char_len= res_length / cs->mbmaxlen; + size_t res_length_diff; + const ObContractions *contractions= ob_charset_get_contractions(cs, 0); + + while (char_len > 0) { + ob_wc_t wc, wc2; + int res = cs->cset->mb_wc(cs, &wc, (unsigned char*) ptr, (unsigned char*) end); + if (res <= 0) { + if (res == OB_CS_ILSEQ) { + return TRUE; + } else { + break; + } + } else { + ptr+= res; + } + + if (wc == (ob_wc_t) escape_char) { + res = cs->cset->mb_wc(cs, &wc, (unsigned char*) ptr, (unsigned char*) end); + if (res <= 0) { + if (res == OB_CS_ILSEQ) { + return TRUE; + } + } else { + ptr+= res; + } + res= cs->cset->wc_mb(cs, wc, (unsigned char*) min_str, (unsigned char*) min_end); + if (res <= 0) { + goto PAD_SET_LEN; + } else { + min_str+= res; + res= cs->cset->wc_mb(cs, wc, (unsigned char*) max_str, (unsigned char*) max_end); + } + if (res <= 0) { + goto PAD_SET_LEN; + } else { + max_str+= res; + continue; + } + } else if (wc == (ob_wc_t) w_one) { + res= cs->cset->wc_mb(cs, cs->min_sort_char, (unsigned char*) min_str, (unsigned char*) min_end); + if (res <= 0) { + goto PAD_SET_LEN; + } else { + min_str+= res; + res= cs->cset->wc_mb(cs, cs->max_sort_char, (unsigned char*) max_str, (unsigned char*) max_end); + } + if ( res <= 0) { + goto PAD_SET_LEN; + } else { + max_str+= res; + continue; + } + } else if ((ob_wc_t) w_many == wc) { + *min_length= ((cs->state & OB_CS_BINSORT) ? (size_t) (min_str - min_org) : res_length); + *max_length= res_length; + goto PAD_MIN_MAX; + } + res= cs->cset->mb_wc(cs, &wc2, (unsigned char*) ptr, (unsigned char*) end); + if (contractions && + ob_uca_can_be_contraction_head(contractions, wc) && + (res) > 0) { + uint16_t *weight; + if ((wc2 == (ob_wc_t) w_one || wc2 == (ob_wc_t) w_many)) { + *min_length= *max_length= res_length; + goto PAD_MIN_MAX; + } else if ((weight= ob_uca_contraction2_weight(contractions, wc, wc2)) && + weight[0] && + ob_uca_can_be_contraction_tail(contractions, wc2)) { + if (char_len == 1) { + *min_length= *max_length= res_length; + goto PAD_MIN_MAX; + } else { + char_len--; + ptr+= res; + res= cs->cset->wc_mb(cs, wc, (unsigned char*) min_str, (unsigned char*) min_end); + } + if (res <= 0) { + goto PAD_SET_LEN; + } else { + min_str+= res; + } + res= cs->cset->wc_mb(cs, wc, (unsigned char*) max_str, (unsigned char*) max_end); + if (res <= 0) { + goto PAD_SET_LEN; + } else { + max_str+= res; + wc= wc2; + } + } + } + res= cs->cset->wc_mb(cs, wc, (unsigned char*) min_str, (unsigned char*) min_end); + if (res <= 0) { + goto PAD_SET_LEN; + } else { + min_str+= res; + res= cs->cset->wc_mb(cs, wc, (unsigned char*) max_str, (unsigned char*) max_end); + } + if (res <= 0) { + goto PAD_SET_LEN; + } else { + max_str+= res; + char_len--; + } + } + +PAD_SET_LEN: + *min_length= (size_t) (min_str - min_org); + *max_length= (size_t) (max_str - max_org); + +PAD_MIN_MAX: + res_length_diff= res_length % cs->mbminlen; + cs->cset->fill(cs, min_str, min_end - min_str - res_length_diff, cs->min_sort_char); + cs->cset->fill(cs, max_str, max_end - max_str - res_length_diff, cs->max_sort_char); + + if (res_length_diff != 0) { + memset(min_end - res_length_diff, 0, res_length_diff); + memset(max_end - res_length_diff, 0, res_length_diff); + } + return FALSE; +} + +ObCharsetHandler ob_charset_utf16_handler= +{ + ob_ismbchar_utf16, + ob_mbcharlen_utf16, + ob_numchars_utf16, + ob_charpos_utf16, + ob_max_bytes_charpos_mb, + ob_well_formed_len_utf16, + ob_lengthsp_mb2, + ob_utf16_uni, + ob_uni_utf16, + ob_mb_ctype_mb, + ob_caseup_utf16, + ob_casedn_utf16, + ob_fill_mb2, + ob_strntol_mb2_or_mb4, + ob_strntoul_mb2_or_mb4, + ob_strntoll_mb2_or_mb4, + ob_strntoull_mb2_or_mb4, + ob_strntod_mb2_or_mb4, + ob_strntoull10rnd_mb2_or_mb4, + ob_scan_mb2 +}; + +static ObCollationHandler ob_collation_utf16_bin_handler = +{ + ob_strnncoll_utf16_bin, + ob_strnncollsp_utf16_bin, + ob_strnxfrm_unicode_full_bin, + ob_like_range_generic, + ob_wildcmp_utf16_bin, + ob_instr_mb, + ob_hash_sort_utf16_bin, + ob_propagate_simple +}; + +static ObCollationHandler ob_collation_utf16_general_ci_handler = +{ + ob_strnncoll_utf16, + ob_strnncollsp_utf16, + ob_strnxfrm_unicode, + ob_like_range_generic, + ob_wildcmp_utf16_ci, + ob_instr_mb, + ob_hash_sort_utf16, + ob_propagate_simple +}; + +ObCharsetInfo ob_charset_utf16_bin= +{ + 55,0,0, + OB_CS_COMPILED|OB_CS_BINSORT|OB_CS_STRNXFRM|OB_CS_UNICODE|OB_CS_NONASCII, + OB_UTF16, + OB_UTF16_BIN, + "UTF-16 Unicode", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &ob_unicase_default, + NULL, + NULL, + 1, + 1, + 1, + 2, + 4, + 0, + 0xFFFF, + ' ', + 0, + 1, + 1, + &ob_charset_utf16_handler, + &ob_collation_utf16_bin_handler +}; + +ObCharsetInfo ob_charset_utf16_general_ci= +{ + 54,0,0, + OB_CS_COMPILED|OB_CS_PRIMARY|OB_CS_STRNXFRM|OB_CS_UNICODE|OB_CS_NONASCII, + OB_UTF16, + OB_UTF16_GENERAL_CI, + "UTF-16 Unicode", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &ob_unicase_default, + NULL, + NULL, + 1, + 1, + 1, + 2, + 4, + 0, + 0xFFFF, + ' ', + 0, + 1, + 1, + &ob_charset_utf16_handler, + &ob_collation_utf16_general_ci_handler +}; diff --git a/src/lib/charset/ob_ctype_utf8.c b/src/lib/charset/ob_ctype_utf8.c index a9e4e9bf4e07ebac944744078c4b973953d0a6c5..1bb09ed4dda95434c12a31bfa648f318cfdd7eca 100644 --- a/src/lib/charset/ob_ctype_utf8.c +++ b/src/lib/charset/ob_ctype_utf8.c @@ -15,1281 +15,1521 @@ #include "lib/charset/ob_uctype.h" #include "lib/utility/ob_macro_utils.h" -#define IS_CONTINUATION_BYTE(c) (((c) ^ 0x80) < 0x40) + +#define IS_CONTINUATION_BYTE(code) (((code) >> 6) == 0x02) static unsigned char ctype_utf8mb4[]= { - 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x28, 0x28, 0x28, 0x28, 0x28, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x48, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x10, 0x10, 0x10, 0x10, - 0x20, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 + 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16, + 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16, + 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 }; static unsigned char to_lower_utf8mb4[]= { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 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, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 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, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95, + 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 }; static unsigned char to_upper_utf8mb4[]= { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, - 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, - 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff -}; - - -static uint32_t lower00[]={ - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, - 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, - 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, - 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, - 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, - 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00D7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, -}; - -static uint32_t upper00[]={ - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, - 0x0060, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, - 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, - 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, - 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, - 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x039C, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, - 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, - 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, - 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00F7, - 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x0178, -}; - -static uint32_t sort00[]={ - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, - 0x0060, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, - 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, - 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, - 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, - 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x039C, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x00C6, 0x0043, - 0x0045, 0x0045, 0x0045, 0x0045, 0x0049, 0x0049, 0x0049, 0x0049, - 0x00D0, 0x004E, 0x004F, 0x004F, 0x004F, 0x004F, 0x004F, 0x00D7, - 0x00D8, 0x0055, 0x0055, 0x0055, 0x0055, 0x0059, 0x00DE, 0x0053, - 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x00C6, 0x0043, - 0x0045, 0x0045, 0x0045, 0x0045, 0x0049, 0x0049, 0x0049, 0x0049, - 0x00D0, 0x004E, 0x004F, 0x004F, 0x004F, 0x004F, 0x004F, 0x00F7, - 0x00D8, 0x0055, 0x0055, 0x0055, 0x0055, 0x0059, 0x00DE, 0x0059, -}; - -static uint32_t lower01[]={ - 0x0101, 0x0101, 0x0103, 0x0103, 0x0105, 0x0105, 0x0107, 0x0107, - 0x0109, 0x0109, 0x010B, 0x010B, 0x010D, 0x010D, 0x010F, 0x010F, - 0x0111, 0x0111, 0x0113, 0x0113, 0x0115, 0x0115, 0x0117, 0x0117, - 0x0119, 0x0119, 0x011B, 0x011B, 0x011D, 0x011D, 0x011F, 0x011F, - 0x0121, 0x0121, 0x0123, 0x0123, 0x0125, 0x0125, 0x0127, 0x0127, - 0x0129, 0x0129, 0x012B, 0x012B, 0x012D, 0x012D, 0x012F, 0x012F, - 0x0069, 0x0131, 0x0133, 0x0133, 0x0135, 0x0135, 0x0137, 0x0137, - 0x0138, 0x013A, 0x013A, 0x013C, 0x013C, 0x013E, 0x013E, 0x0140, - 0x0140, 0x0142, 0x0142, 0x0144, 0x0144, 0x0146, 0x0146, 0x0148, - 0x0148, 0x0149, 0x014B, 0x014B, 0x014D, 0x014D, 0x014F, 0x014F, - 0x0151, 0x0151, 0x0153, 0x0153, 0x0155, 0x0155, 0x0157, 0x0157, - 0x0159, 0x0159, 0x015B, 0x015B, 0x015D, 0x015D, 0x015F, 0x015F, - 0x0161, 0x0161, 0x0163, 0x0163, 0x0165, 0x0165, 0x0167, 0x0167, - 0x0169, 0x0169, 0x016B, 0x016B, 0x016D, 0x016D, 0x016F, 0x016F, - 0x0171, 0x0171, 0x0173, 0x0173, 0x0175, 0x0175, 0x0177, 0x0177, - 0x00FF, 0x017A, 0x017A, 0x017C, 0x017C, 0x017E, 0x017E, 0x017F, - 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188, - 0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259, - 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268, - 0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275, - 0x01A1, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x0280, 0x01A8, - 0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01B0, - 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292, - 0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF, - 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9, - 0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC, 0x01CE, 0x01CE, 0x01D0, - 0x01D0, 0x01D2, 0x01D2, 0x01D4, 0x01D4, 0x01D6, 0x01D6, 0x01D8, - 0x01D8, 0x01DA, 0x01DA, 0x01DC, 0x01DC, 0x01DD, 0x01DF, 0x01DF, - 0x01E1, 0x01E1, 0x01E3, 0x01E3, 0x01E5, 0x01E5, 0x01E7, 0x01E7, - 0x01E9, 0x01E9, 0x01EB, 0x01EB, 0x01ED, 0x01ED, 0x01EF, 0x01EF, - 0x01F0, 0x01F3, 0x01F3, 0x01F3, 0x01F5, 0x01F5, 0x0195, 0x01BF, - 0x01F9, 0x01F9, 0x01FB, 0x01FB, 0x01FD, 0x01FD, 0x01FF, 0x01FF, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127, + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 }; -static uint32_t upper01[]={ - 0x0100, 0x0100, 0x0102, 0x0102, 0x0104, 0x0104, 0x0106, 0x0106, - 0x0108, 0x0108, 0x010A, 0x010A, 0x010C, 0x010C, 0x010E, 0x010E, - 0x0110, 0x0110, 0x0112, 0x0112, 0x0114, 0x0114, 0x0116, 0x0116, - 0x0118, 0x0118, 0x011A, 0x011A, 0x011C, 0x011C, 0x011E, 0x011E, - 0x0120, 0x0120, 0x0122, 0x0122, 0x0124, 0x0124, 0x0126, 0x0126, - 0x0128, 0x0128, 0x012A, 0x012A, 0x012C, 0x012C, 0x012E, 0x012E, - 0x0130, 0x0049, 0x0132, 0x0132, 0x0134, 0x0134, 0x0136, 0x0136, - 0x0138, 0x0139, 0x0139, 0x013B, 0x013B, 0x013D, 0x013D, 0x013F, - 0x013F, 0x0141, 0x0141, 0x0143, 0x0143, 0x0145, 0x0145, 0x0147, - 0x0147, 0x0149, 0x014A, 0x014A, 0x014C, 0x014C, 0x014E, 0x014E, - 0x0150, 0x0150, 0x0152, 0x0152, 0x0154, 0x0154, 0x0156, 0x0156, - 0x0158, 0x0158, 0x015A, 0x015A, 0x015C, 0x015C, 0x015E, 0x015E, - 0x0160, 0x0160, 0x0162, 0x0162, 0x0164, 0x0164, 0x0166, 0x0166, - 0x0168, 0x0168, 0x016A, 0x016A, 0x016C, 0x016C, 0x016E, 0x016E, - 0x0170, 0x0170, 0x0172, 0x0172, 0x0174, 0x0174, 0x0176, 0x0176, - 0x0178, 0x0179, 0x0179, 0x017B, 0x017B, 0x017D, 0x017D, 0x0053, - 0x0180, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187, - 0x0187, 0x0189, 0x018A, 0x018B, 0x018B, 0x018D, 0x018E, 0x018F, - 0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01F6, 0x0196, 0x0197, - 0x0198, 0x0198, 0x019A, 0x019B, 0x019C, 0x019D, 0x019E, 0x019F, - 0x01A0, 0x01A0, 0x01A2, 0x01A2, 0x01A4, 0x01A4, 0x01A6, 0x01A7, - 0x01A7, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AC, 0x01AE, 0x01AF, - 0x01AF, 0x01B1, 0x01B2, 0x01B3, 0x01B3, 0x01B5, 0x01B5, 0x01B7, - 0x01B8, 0x01B8, 0x01BA, 0x01BB, 0x01BC, 0x01BC, 0x01BE, 0x01F7, - 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C4, 0x01C4, 0x01C7, - 0x01C7, 0x01C7, 0x01CA, 0x01CA, 0x01CA, 0x01CD, 0x01CD, 0x01CF, - 0x01CF, 0x01D1, 0x01D1, 0x01D3, 0x01D3, 0x01D5, 0x01D5, 0x01D7, - 0x01D7, 0x01D9, 0x01D9, 0x01DB, 0x01DB, 0x018E, 0x01DE, 0x01DE, - 0x01E0, 0x01E0, 0x01E2, 0x01E2, 0x01E4, 0x01E4, 0x01E6, 0x01E6, - 0x01E8, 0x01E8, 0x01EA, 0x01EA, 0x01EC, 0x01EC, 0x01EE, 0x01EE, - 0x01F0, 0x01F1, 0x01F1, 0x01F1, 0x01F4, 0x01F4, 0x01F6, 0x01F7, - 0x01F8, 0x01F8, 0x01FA, 0x01FA, 0x01FC, 0x01FC, 0x01FE, 0x01FE, -}; - -static uint32_t sort01[]={ - 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0043, 0x0043, - 0x0043, 0x0043, 0x0043, 0x0043, 0x0043, 0x0043, 0x0044, 0x0044, - 0x0110, 0x0110, 0x0045, 0x0045, 0x0045, 0x0045, 0x0045, 0x0045, - 0x0045, 0x0045, 0x0045, 0x0045, 0x0047, 0x0047, 0x0047, 0x0047, - 0x0047, 0x0047, 0x0047, 0x0047, 0x0048, 0x0048, 0x0126, 0x0126, - 0x0049, 0x0049, 0x0049, 0x0049, 0x0049, 0x0049, 0x0049, 0x0049, - 0x0049, 0x0049, 0x0132, 0x0132, 0x004A, 0x004A, 0x004B, 0x004B, - 0x0138, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C, 0x013F, - 0x013F, 0x0141, 0x0141, 0x004E, 0x004E, 0x004E, 0x004E, 0x004E, - 0x004E, 0x0149, 0x014A, 0x014A, 0x004F, 0x004F, 0x004F, 0x004F, - 0x004F, 0x004F, 0x0152, 0x0152, 0x0052, 0x0052, 0x0052, 0x0052, - 0x0052, 0x0052, 0x0053, 0x0053, 0x0053, 0x0053, 0x0053, 0x0053, - 0x0053, 0x0053, 0x0054, 0x0054, 0x0054, 0x0054, 0x0166, 0x0166, - 0x0055, 0x0055, 0x0055, 0x0055, 0x0055, 0x0055, 0x0055, 0x0055, - 0x0055, 0x0055, 0x0055, 0x0055, 0x0057, 0x0057, 0x0059, 0x0059, - 0x0059, 0x005A, 0x005A, 0x005A, 0x005A, 0x005A, 0x005A, 0x0053, - 0x0180, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187, - 0x0187, 0x0189, 0x018A, 0x018B, 0x018B, 0x018D, 0x018E, 0x018F, - 0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01F6, 0x0196, 0x0197, - 0x0198, 0x0198, 0x019A, 0x019B, 0x019C, 0x019D, 0x019E, 0x019F, - 0x004F, 0x004F, 0x01A2, 0x01A2, 0x01A4, 0x01A4, 0x01A6, 0x01A7, - 0x01A7, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AC, 0x01AE, 0x0055, - 0x0055, 0x01B1, 0x01B2, 0x01B3, 0x01B3, 0x01B5, 0x01B5, 0x01B7, - 0x01B8, 0x01B8, 0x01BA, 0x01BB, 0x01BC, 0x01BC, 0x01BE, 0x01F7, - 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C4, 0x01C4, 0x01C7, - 0x01C7, 0x01C7, 0x01CA, 0x01CA, 0x01CA, 0x0041, 0x0041, 0x0049, - 0x0049, 0x004F, 0x004F, 0x0055, 0x0055, 0x0055, 0x0055, 0x0055, - 0x0055, 0x0055, 0x0055, 0x0055, 0x0055, 0x018E, 0x0041, 0x0041, - 0x0041, 0x0041, 0x00C6, 0x00C6, 0x01E4, 0x01E4, 0x0047, 0x0047, - 0x004B, 0x004B, 0x004F, 0x004F, 0x004F, 0x004F, 0x01B7, 0x01B7, - 0x004A, 0x01F1, 0x01F1, 0x01F1, 0x0047, 0x0047, 0x01F6, 0x01F7, - 0x004E, 0x004E, 0x0041, 0x0041, 0x00C6, 0x00C6, 0x00D8, 0x00D8, -}; - -static uint32_t lower02[]={ - 0x0201, 0x0201, 0x0203, 0x0203, 0x0205, 0x0205, 0x0207, 0x0207, - 0x0209, 0x0209, 0x020B, 0x020B, 0x020D, 0x020D, 0x020F, 0x020F, - 0x0211, 0x0211, 0x0213, 0x0213, 0x0215, 0x0215, 0x0217, 0x0217, - 0x0219, 0x0219, 0x021B, 0x021B, 0x021D, 0x021D, 0x021F, 0x021F, - 0x0220, 0x0221, 0x0223, 0x0223, 0x0225, 0x0225, 0x0227, 0x0227, - 0x0229, 0x0229, 0x022B, 0x022B, 0x022D, 0x022D, 0x022F, 0x022F, - 0x0231, 0x0231, 0x0233, 0x0233, 0x0234, 0x0235, 0x0236, 0x0237, - 0x0238, 0x0239, 0x023A, 0x023B, 0x023C, 0x023D, 0x023E, 0x023F, - 0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247, - 0x0248, 0x0249, 0x024A, 0x024B, 0x024C, 0x024D, 0x024E, 0x024F, - 0x0250, 0x0251, 0x0252, 0x0253, 0x0254, 0x0255, 0x0256, 0x0257, - 0x0258, 0x0259, 0x025A, 0x025B, 0x025C, 0x025D, 0x025E, 0x025F, - 0x0260, 0x0261, 0x0262, 0x0263, 0x0264, 0x0265, 0x0266, 0x0267, - 0x0268, 0x0269, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x026F, - 0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277, - 0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F, - 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0286, 0x0287, - 0x0288, 0x0289, 0x028A, 0x028B, 0x028C, 0x028D, 0x028E, 0x028F, - 0x0290, 0x0291, 0x0292, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297, - 0x0298, 0x0299, 0x029A, 0x029B, 0x029C, 0x029D, 0x029E, 0x029F, - 0x02A0, 0x02A1, 0x02A2, 0x02A3, 0x02A4, 0x02A5, 0x02A6, 0x02A7, - 0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x02AC, 0x02AD, 0x02AE, 0x02AF, - 0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6, 0x02B7, - 0x02B8, 0x02B9, 0x02BA, 0x02BB, 0x02BC, 0x02BD, 0x02BE, 0x02BF, - 0x02C0, 0x02C1, 0x02C2, 0x02C3, 0x02C4, 0x02C5, 0x02C6, 0x02C7, - 0x02C8, 0x02C9, 0x02CA, 0x02CB, 0x02CC, 0x02CD, 0x02CE, 0x02CF, - 0x02D0, 0x02D1, 0x02D2, 0x02D3, 0x02D4, 0x02D5, 0x02D6, 0x02D7, - 0x02D8, 0x02D9, 0x02DA, 0x02DB, 0x02DC, 0x02DD, 0x02DE, 0x02DF, - 0x02E0, 0x02E1, 0x02E2, 0x02E3, 0x02E4, 0x02E5, 0x02E6, 0x02E7, - 0x02E8, 0x02E9, 0x02EA, 0x02EB, 0x02EC, 0x02ED, 0x02EE, 0x02EF, - 0x02F0, 0x02F1, 0x02F2, 0x02F3, 0x02F4, 0x02F5, 0x02F6, 0x02F7, - 0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, 0x02FD, 0x02FE, 0x02FF, -}; - -static uint32_t upper02[]={ - 0x0200, 0x0200, 0x0202, 0x0202, 0x0204, 0x0204, 0x0206, 0x0206, - 0x0208, 0x0208, 0x020A, 0x020A, 0x020C, 0x020C, 0x020E, 0x020E, - 0x0210, 0x0210, 0x0212, 0x0212, 0x0214, 0x0214, 0x0216, 0x0216, - 0x0218, 0x0218, 0x021A, 0x021A, 0x021C, 0x021C, 0x021E, 0x021E, - 0x0220, 0x0221, 0x0222, 0x0222, 0x0224, 0x0224, 0x0226, 0x0226, - 0x0228, 0x0228, 0x022A, 0x022A, 0x022C, 0x022C, 0x022E, 0x022E, - 0x0230, 0x0230, 0x0232, 0x0232, 0x0234, 0x0235, 0x0236, 0x0237, - 0x0238, 0x0239, 0x023A, 0x023B, 0x023C, 0x023D, 0x023E, 0x023F, - 0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247, - 0x0248, 0x0249, 0x024A, 0x024B, 0x024C, 0x024D, 0x024E, 0x024F, - 0x0250, 0x0251, 0x0252, 0x0181, 0x0186, 0x0255, 0x0189, 0x018A, - 0x0258, 0x018F, 0x025A, 0x0190, 0x025C, 0x025D, 0x025E, 0x025F, - 0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267, - 0x0197, 0x0196, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x019C, - 0x0270, 0x0271, 0x019D, 0x0273, 0x0274, 0x019F, 0x0276, 0x0277, - 0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F, - 0x01A6, 0x0281, 0x0282, 0x01A9, 0x0284, 0x0285, 0x0286, 0x0287, - 0x01AE, 0x0289, 0x01B1, 0x01B2, 0x028C, 0x028D, 0x028E, 0x028F, - 0x0290, 0x0291, 0x01B7, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297, - 0x0298, 0x0299, 0x029A, 0x029B, 0x029C, 0x029D, 0x029E, 0x029F, - 0x02A0, 0x02A1, 0x02A2, 0x02A3, 0x02A4, 0x02A5, 0x02A6, 0x02A7, - 0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x02AC, 0x02AD, 0x02AE, 0x02AF, - 0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6, 0x02B7, - 0x02B8, 0x02B9, 0x02BA, 0x02BB, 0x02BC, 0x02BD, 0x02BE, 0x02BF, - 0x02C0, 0x02C1, 0x02C2, 0x02C3, 0x02C4, 0x02C5, 0x02C6, 0x02C7, - 0x02C8, 0x02C9, 0x02CA, 0x02CB, 0x02CC, 0x02CD, 0x02CE, 0x02CF, - 0x02D0, 0x02D1, 0x02D2, 0x02D3, 0x02D4, 0x02D5, 0x02D6, 0x02D7, - 0x02D8, 0x02D9, 0x02DA, 0x02DB, 0x02DC, 0x02DD, 0x02DE, 0x02DF, - 0x02E0, 0x02E1, 0x02E2, 0x02E3, 0x02E4, 0x02E5, 0x02E6, 0x02E7, - 0x02E8, 0x02E9, 0x02EA, 0x02EB, 0x02EC, 0x02ED, 0x02EE, 0x02EF, - 0x02F0, 0x02F1, 0x02F2, 0x02F3, 0x02F4, 0x02F5, 0x02F6, 0x02F7, - 0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, 0x02FD, 0x02FE, 0x02FF, -}; - -static uint32_t sort02[]={ - 0x0041, 0x0041, 0x0041, 0x0041, 0x0045, 0x0045, 0x0045, 0x0045, - 0x0049, 0x0049, 0x0049, 0x0049, 0x004F, 0x004F, 0x004F, 0x004F, - 0x0052, 0x0052, 0x0052, 0x0052, 0x0055, 0x0055, 0x0055, 0x0055, - 0x0053, 0x0053, 0x0054, 0x0054, 0x021C, 0x021C, 0x0048, 0x0048, - 0x0220, 0x0221, 0x0222, 0x0222, 0x0224, 0x0224, 0x0041, 0x0041, - 0x0045, 0x0045, 0x004F, 0x004F, 0x004F, 0x004F, 0x004F, 0x004F, - 0x004F, 0x004F, 0x0059, 0x0059, 0x0234, 0x0235, 0x0236, 0x0237, - 0x0238, 0x0239, 0x023A, 0x023B, 0x023C, 0x023D, 0x023E, 0x023F, - 0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247, - 0x0248, 0x0249, 0x024A, 0x024B, 0x024C, 0x024D, 0x024E, 0x024F, - 0x0250, 0x0251, 0x0252, 0x0181, 0x0186, 0x0255, 0x0189, 0x018A, - 0x0258, 0x018F, 0x025A, 0x0190, 0x025C, 0x025D, 0x025E, 0x025F, - 0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267, - 0x0197, 0x0196, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x019C, - 0x0270, 0x0271, 0x019D, 0x0273, 0x0274, 0x019F, 0x0276, 0x0277, - 0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F, - 0x01A6, 0x0281, 0x0282, 0x01A9, 0x0284, 0x0285, 0x0286, 0x0287, - 0x01AE, 0x0289, 0x01B1, 0x01B2, 0x028C, 0x028D, 0x028E, 0x028F, - 0x0290, 0x0291, 0x01B7, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297, - 0x0298, 0x0299, 0x029A, 0x029B, 0x029C, 0x029D, 0x029E, 0x029F, - 0x02A0, 0x02A1, 0x02A2, 0x02A3, 0x02A4, 0x02A5, 0x02A6, 0x02A7, - 0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x02AC, 0x02AD, 0x02AE, 0x02AF, - 0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6, 0x02B7, - 0x02B8, 0x02B9, 0x02BA, 0x02BB, 0x02BC, 0x02BD, 0x02BE, 0x02BF, - 0x02C0, 0x02C1, 0x02C2, 0x02C3, 0x02C4, 0x02C5, 0x02C6, 0x02C7, - 0x02C8, 0x02C9, 0x02CA, 0x02CB, 0x02CC, 0x02CD, 0x02CE, 0x02CF, - 0x02D0, 0x02D1, 0x02D2, 0x02D3, 0x02D4, 0x02D5, 0x02D6, 0x02D7, - 0x02D8, 0x02D9, 0x02DA, 0x02DB, 0x02DC, 0x02DD, 0x02DE, 0x02DF, - 0x02E0, 0x02E1, 0x02E2, 0x02E3, 0x02E4, 0x02E5, 0x02E6, 0x02E7, - 0x02E8, 0x02E9, 0x02EA, 0x02EB, 0x02EC, 0x02ED, 0x02EE, 0x02EF, - 0x02F0, 0x02F1, 0x02F2, 0x02F3, 0x02F4, 0x02F5, 0x02F6, 0x02F7, - 0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, 0x02FD, 0x02FE, 0x02FF, -}; - -static uint32_t lower03[]={ - 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, - 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F, - 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, - 0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F, - 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, - 0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F, - 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337, - 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F, - 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347, - 0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F, - 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, - 0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F, - 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, - 0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F, - 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377, - 0x0378, 0x0379, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, 0x037F, - 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x03AC, 0x0387, - 0x03AD, 0x03AE, 0x03AF, 0x038B, 0x03CC, 0x038D, 0x03CD, 0x03CE, - 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, - 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, - 0x03C0, 0x03C1, 0x03A2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, - 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, - 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, - 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, - 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, - 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03CF, - 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7, - 0x03D8, 0x03D9, 0x03DB, 0x03DB, 0x03DD, 0x03DD, 0x03DF, 0x03DF, - 0x03E1, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7, - 0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF, - 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7, - 0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF, -}; - -static uint32_t upper03[]={ - 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, - 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F, - 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, - 0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F, - 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, - 0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F, - 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337, - 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F, - 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0399, 0x0346, 0x0347, - 0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F, - 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, - 0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F, - 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, - 0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F, - 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377, - 0x0378, 0x0379, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, 0x037F, - 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387, - 0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F, - 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, - 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, - 0x03A0, 0x03A1, 0x03A2, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, - 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x0386, 0x0388, 0x0389, 0x038A, - 0x03B0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, - 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, - 0x03A0, 0x03A1, 0x03A3, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, - 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x038C, 0x038E, 0x038F, 0x03CF, - 0x0392, 0x0398, 0x03D2, 0x03D3, 0x03D4, 0x03A6, 0x03A0, 0x03D7, - 0x03D8, 0x03D9, 0x03DA, 0x03DA, 0x03DC, 0x03DC, 0x03DE, 0x03DE, - 0x03E0, 0x03E0, 0x03E2, 0x03E2, 0x03E4, 0x03E4, 0x03E6, 0x03E6, - 0x03E8, 0x03E8, 0x03EA, 0x03EA, 0x03EC, 0x03EC, 0x03EE, 0x03EE, - 0x039A, 0x03A1, 0x03A3, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7, - 0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF, -}; - -static uint32_t sort03[]={ - 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, - 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F, - 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, - 0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F, - 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, - 0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F, - 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337, - 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F, - 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0399, 0x0346, 0x0347, - 0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F, - 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, - 0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F, - 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, - 0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F, - 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377, - 0x0378, 0x0379, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, 0x037F, - 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0391, 0x0387, - 0x0395, 0x0397, 0x0399, 0x038B, 0x039F, 0x038D, 0x03A5, 0x03A9, - 0x0399, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, - 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, - 0x03A0, 0x03A1, 0x03A2, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, - 0x03A8, 0x03A9, 0x0399, 0x03A5, 0x0391, 0x0395, 0x0397, 0x0399, - 0x03A5, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, - 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, - 0x03A0, 0x03A1, 0x03A3, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, - 0x03A8, 0x03A9, 0x0399, 0x03A5, 0x039F, 0x03A5, 0x03A9, 0x03CF, - 0x0392, 0x0398, 0x03D2, 0x03D2, 0x03D2, 0x03A6, 0x03A0, 0x03D7, - 0x03D8, 0x03D9, 0x03DA, 0x03DA, 0x03DC, 0x03DC, 0x03DE, 0x03DE, - 0x03E0, 0x03E0, 0x03E2, 0x03E2, 0x03E4, 0x03E4, 0x03E6, 0x03E6, - 0x03E8, 0x03E8, 0x03EA, 0x03EA, 0x03EC, 0x03EC, 0x03EE, 0x03EE, - 0x039A, 0x03A1, 0x03A3, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7, - 0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF, -}; - -static uint32_t lower04[]={ - 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, - 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F, - 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, - 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, - 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, - 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, - 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, - 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, - 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, - 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, - 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, - 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F, - 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467, - 0x0469, 0x0469, 0x046B, 0x046B, 0x046D, 0x046D, 0x046F, 0x046F, - 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0477, 0x0477, - 0x0479, 0x0479, 0x047B, 0x047B, 0x047D, 0x047D, 0x047F, 0x047F, - 0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, - 0x0488, 0x0489, 0x048A, 0x048B, 0x048D, 0x048D, 0x048F, 0x048F, - 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497, - 0x0499, 0x0499, 0x049B, 0x049B, 0x049D, 0x049D, 0x049F, 0x049F, - 0x04A1, 0x04A1, 0x04A3, 0x04A3, 0x04A5, 0x04A5, 0x04A7, 0x04A7, - 0x04A9, 0x04A9, 0x04AB, 0x04AB, 0x04AD, 0x04AD, 0x04AF, 0x04AF, - 0x04B1, 0x04B1, 0x04B3, 0x04B3, 0x04B5, 0x04B5, 0x04B7, 0x04B7, - 0x04B9, 0x04B9, 0x04BB, 0x04BB, 0x04BD, 0x04BD, 0x04BF, 0x04BF, - 0x04C0, 0x04C2, 0x04C2, 0x04C4, 0x04C4, 0x04C5, 0x04C6, 0x04C8, - 0x04C8, 0x04C9, 0x04CA, 0x04CC, 0x04CC, 0x04CD, 0x04CE, 0x04CF, - 0x04D1, 0x04D1, 0x04D3, 0x04D3, 0x04D5, 0x04D5, 0x04D7, 0x04D7, - 0x04D9, 0x04D9, 0x04DB, 0x04DB, 0x04DD, 0x04DD, 0x04DF, 0x04DF, - 0x04E1, 0x04E1, 0x04E3, 0x04E3, 0x04E5, 0x04E5, 0x04E7, 0x04E7, - 0x04E9, 0x04E9, 0x04EB, 0x04EB, 0x04ED, 0x04ED, 0x04EF, 0x04EF, - 0x04F1, 0x04F1, 0x04F3, 0x04F3, 0x04F5, 0x04F5, 0x04F6, 0x04F7, - 0x04F9, 0x04F9, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF, -}; - -static uint32_t upper04[]={ - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, - 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040D, 0x040E, 0x040F, - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, - 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, - 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, - 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, - 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, - 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, - 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, - 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040D, 0x040E, 0x040F, - 0x0460, 0x0460, 0x0462, 0x0462, 0x0464, 0x0464, 0x0466, 0x0466, - 0x0468, 0x0468, 0x046A, 0x046A, 0x046C, 0x046C, 0x046E, 0x046E, - 0x0470, 0x0470, 0x0472, 0x0472, 0x0474, 0x0474, 0x0476, 0x0476, - 0x0478, 0x0478, 0x047A, 0x047A, 0x047C, 0x047C, 0x047E, 0x047E, - 0x0480, 0x0480, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, - 0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048C, 0x048E, 0x048E, - 0x0490, 0x0490, 0x0492, 0x0492, 0x0494, 0x0494, 0x0496, 0x0496, - 0x0498, 0x0498, 0x049A, 0x049A, 0x049C, 0x049C, 0x049E, 0x049E, - 0x04A0, 0x04A0, 0x04A2, 0x04A2, 0x04A4, 0x04A4, 0x04A6, 0x04A6, - 0x04A8, 0x04A8, 0x04AA, 0x04AA, 0x04AC, 0x04AC, 0x04AE, 0x04AE, - 0x04B0, 0x04B0, 0x04B2, 0x04B2, 0x04B4, 0x04B4, 0x04B6, 0x04B6, - 0x04B8, 0x04B8, 0x04BA, 0x04BA, 0x04BC, 0x04BC, 0x04BE, 0x04BE, - 0x04C0, 0x04C1, 0x04C1, 0x04C3, 0x04C3, 0x04C5, 0x04C6, 0x04C7, - 0x04C7, 0x04C9, 0x04CA, 0x04CB, 0x04CB, 0x04CD, 0x04CE, 0x04CF, - 0x04D0, 0x04D0, 0x04D2, 0x04D2, 0x04D4, 0x04D4, 0x04D6, 0x04D6, - 0x04D8, 0x04D8, 0x04DA, 0x04DA, 0x04DC, 0x04DC, 0x04DE, 0x04DE, - 0x04E0, 0x04E0, 0x04E2, 0x04E2, 0x04E4, 0x04E4, 0x04E6, 0x04E6, - 0x04E8, 0x04E8, 0x04EA, 0x04EA, 0x04EC, 0x04EC, 0x04EE, 0x04EE, - 0x04F0, 0x04F0, 0x04F2, 0x04F2, 0x04F4, 0x04F4, 0x04F6, 0x04F7, - 0x04F8, 0x04F8, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF, -}; - -static uint32_t sort04[]={ - 0x0415, 0x0415, 0x0402, 0x0413, 0x0404, 0x0405, 0x0406, 0x0406, - 0x0408, 0x0409, 0x040A, 0x040B, 0x041A, 0x0418, 0x0423, 0x040F, - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, - 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, - 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, - 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, - 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, - 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, - 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, - 0x0415, 0x0415, 0x0402, 0x0413, 0x0404, 0x0405, 0x0406, 0x0406, - 0x0408, 0x0409, 0x040A, 0x040B, 0x041A, 0x0418, 0x0423, 0x040F, - 0x0460, 0x0460, 0x0462, 0x0462, 0x0464, 0x0464, 0x0466, 0x0466, - 0x0468, 0x0468, 0x046A, 0x046A, 0x046C, 0x046C, 0x046E, 0x046E, - 0x0470, 0x0470, 0x0472, 0x0472, 0x0474, 0x0474, 0x0474, 0x0474, - 0x0478, 0x0478, 0x047A, 0x047A, 0x047C, 0x047C, 0x047E, 0x047E, - 0x0480, 0x0480, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, - 0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048C, 0x048E, 0x048E, - 0x0490, 0x0490, 0x0492, 0x0492, 0x0494, 0x0494, 0x0496, 0x0496, - 0x0498, 0x0498, 0x049A, 0x049A, 0x049C, 0x049C, 0x049E, 0x049E, - 0x04A0, 0x04A0, 0x04A2, 0x04A2, 0x04A4, 0x04A4, 0x04A6, 0x04A6, - 0x04A8, 0x04A8, 0x04AA, 0x04AA, 0x04AC, 0x04AC, 0x04AE, 0x04AE, - 0x04B0, 0x04B0, 0x04B2, 0x04B2, 0x04B4, 0x04B4, 0x04B6, 0x04B6, - 0x04B8, 0x04B8, 0x04BA, 0x04BA, 0x04BC, 0x04BC, 0x04BE, 0x04BE, - 0x04C0, 0x0416, 0x0416, 0x04C3, 0x04C3, 0x04C5, 0x04C6, 0x04C7, - 0x04C7, 0x04C9, 0x04CA, 0x04CB, 0x04CB, 0x04CD, 0x04CE, 0x04CF, - 0x0410, 0x0410, 0x0410, 0x0410, 0x04D4, 0x04D4, 0x0415, 0x0415, - 0x04D8, 0x04D8, 0x04D8, 0x04D8, 0x0416, 0x0416, 0x0417, 0x0417, - 0x04E0, 0x04E0, 0x0418, 0x0418, 0x0418, 0x0418, 0x041E, 0x041E, - 0x04E8, 0x04E8, 0x04E8, 0x04E8, 0x042D, 0x042D, 0x0423, 0x0423, - 0x0423, 0x0423, 0x0423, 0x0423, 0x0427, 0x0427, 0x04F6, 0x04F7, - 0x042B, 0x042B, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF, -}; - -static uint32_t lower05[]={ - 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, - 0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F, - 0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517, - 0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F, - 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527, - 0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F, - 0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, - 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F, - 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, - 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F, - 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557, - 0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F, - 0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, - 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F, - 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, - 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F, - 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587, - 0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F, - 0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597, - 0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F, - 0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7, - 0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF, - 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, - 0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, - 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x05C5, 0x05C6, 0x05C7, - 0x05C8, 0x05C9, 0x05CA, 0x05CB, 0x05CC, 0x05CD, 0x05CE, 0x05CF, - 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, - 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, - 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, - 0x05E8, 0x05E9, 0x05EA, 0x05EB, 0x05EC, 0x05ED, 0x05EE, 0x05EF, - 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x05F5, 0x05F6, 0x05F7, - 0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, -}; - -static uint32_t upper05[]={ - 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, - 0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F, - 0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517, - 0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F, - 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527, - 0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F, - 0x0530, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537, - 0x0538, 0x0539, 0x053A, 0x053B, 0x053C, 0x053D, 0x053E, 0x053F, - 0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547, - 0x0548, 0x0549, 0x054A, 0x054B, 0x054C, 0x054D, 0x054E, 0x054F, - 0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0557, - 0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F, - 0x0560, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537, - 0x0538, 0x0539, 0x053A, 0x053B, 0x053C, 0x053D, 0x053E, 0x053F, - 0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547, - 0x0548, 0x0549, 0x054A, 0x054B, 0x054C, 0x054D, 0x054E, 0x054F, - 0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0587, - 0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F, - 0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597, - 0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F, - 0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7, - 0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF, - 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, - 0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, - 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x05C5, 0x05C6, 0x05C7, - 0x05C8, 0x05C9, 0x05CA, 0x05CB, 0x05CC, 0x05CD, 0x05CE, 0x05CF, - 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, - 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, - 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, - 0x05E8, 0x05E9, 0x05EA, 0x05EB, 0x05EC, 0x05ED, 0x05EE, 0x05EF, - 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x05F5, 0x05F6, 0x05F7, - 0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, -}; - -static uint32_t sort05[]={ - 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, - 0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F, - 0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517, - 0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F, - 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527, - 0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F, - 0x0530, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537, - 0x0538, 0x0539, 0x053A, 0x053B, 0x053C, 0x053D, 0x053E, 0x053F, - 0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547, - 0x0548, 0x0549, 0x054A, 0x054B, 0x054C, 0x054D, 0x054E, 0x054F, - 0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0557, - 0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F, - 0x0560, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537, - 0x0538, 0x0539, 0x053A, 0x053B, 0x053C, 0x053D, 0x053E, 0x053F, - 0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547, - 0x0548, 0x0549, 0x054A, 0x054B, 0x054C, 0x054D, 0x054E, 0x054F, - 0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0587, - 0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F, - 0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597, - 0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F, - 0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7, - 0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF, - 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, - 0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, - 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x05C5, 0x05C6, 0x05C7, - 0x05C8, 0x05C9, 0x05CA, 0x05CB, 0x05CC, 0x05CD, 0x05CE, 0x05CF, - 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, - 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, - 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, - 0x05E8, 0x05E9, 0x05EA, 0x05EB, 0x05EC, 0x05ED, 0x05EE, 0x05EF, - 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x05F5, 0x05F6, 0x05F7, - 0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, -}; -static uint32_t lower1E[]={ - 0x1E01, 0x1E01, 0x1E03, 0x1E03, 0x1E05, 0x1E05, 0x1E07, 0x1E07, - 0x1E09, 0x1E09, 0x1E0B, 0x1E0B, 0x1E0D, 0x1E0D, 0x1E0F, 0x1E0F, - 0x1E11, 0x1E11, 0x1E13, 0x1E13, 0x1E15, 0x1E15, 0x1E17, 0x1E17, - 0x1E19, 0x1E19, 0x1E1B, 0x1E1B, 0x1E1D, 0x1E1D, 0x1E1F, 0x1E1F, - 0x1E21, 0x1E21, 0x1E23, 0x1E23, 0x1E25, 0x1E25, 0x1E27, 0x1E27, - 0x1E29, 0x1E29, 0x1E2B, 0x1E2B, 0x1E2D, 0x1E2D, 0x1E2F, 0x1E2F, - 0x1E31, 0x1E31, 0x1E33, 0x1E33, 0x1E35, 0x1E35, 0x1E37, 0x1E37, - 0x1E39, 0x1E39, 0x1E3B, 0x1E3B, 0x1E3D, 0x1E3D, 0x1E3F, 0x1E3F, - 0x1E41, 0x1E41, 0x1E43, 0x1E43, 0x1E45, 0x1E45, 0x1E47, 0x1E47, - 0x1E49, 0x1E49, 0x1E4B, 0x1E4B, 0x1E4D, 0x1E4D, 0x1E4F, 0x1E4F, - 0x1E51, 0x1E51, 0x1E53, 0x1E53, 0x1E55, 0x1E55, 0x1E57, 0x1E57, - 0x1E59, 0x1E59, 0x1E5B, 0x1E5B, 0x1E5D, 0x1E5D, 0x1E5F, 0x1E5F, - 0x1E61, 0x1E61, 0x1E63, 0x1E63, 0x1E65, 0x1E65, 0x1E67, 0x1E67, - 0x1E69, 0x1E69, 0x1E6B, 0x1E6B, 0x1E6D, 0x1E6D, 0x1E6F, 0x1E6F, - 0x1E71, 0x1E71, 0x1E73, 0x1E73, 0x1E75, 0x1E75, 0x1E77, 0x1E77, - 0x1E79, 0x1E79, 0x1E7B, 0x1E7B, 0x1E7D, 0x1E7D, 0x1E7F, 0x1E7F, - 0x1E81, 0x1E81, 0x1E83, 0x1E83, 0x1E85, 0x1E85, 0x1E87, 0x1E87, - 0x1E89, 0x1E89, 0x1E8B, 0x1E8B, 0x1E8D, 0x1E8D, 0x1E8F, 0x1E8F, - 0x1E91, 0x1E91, 0x1E93, 0x1E93, 0x1E95, 0x1E95, 0x1E96, 0x1E97, - 0x1E98, 0x1E99, 0x1E9A, 0x1E9B, 0x1E9C, 0x1E9D, 0x1E9E, 0x1E9F, - 0x1EA1, 0x1EA1, 0x1EA3, 0x1EA3, 0x1EA5, 0x1EA5, 0x1EA7, 0x1EA7, - 0x1EA9, 0x1EA9, 0x1EAB, 0x1EAB, 0x1EAD, 0x1EAD, 0x1EAF, 0x1EAF, - 0x1EB1, 0x1EB1, 0x1EB3, 0x1EB3, 0x1EB5, 0x1EB5, 0x1EB7, 0x1EB7, - 0x1EB9, 0x1EB9, 0x1EBB, 0x1EBB, 0x1EBD, 0x1EBD, 0x1EBF, 0x1EBF, - 0x1EC1, 0x1EC1, 0x1EC3, 0x1EC3, 0x1EC5, 0x1EC5, 0x1EC7, 0x1EC7, - 0x1EC9, 0x1EC9, 0x1ECB, 0x1ECB, 0x1ECD, 0x1ECD, 0x1ECF, 0x1ECF, - 0x1ED1, 0x1ED1, 0x1ED3, 0x1ED3, 0x1ED5, 0x1ED5, 0x1ED7, 0x1ED7, - 0x1ED9, 0x1ED9, 0x1EDB, 0x1EDB, 0x1EDD, 0x1EDD, 0x1EDF, 0x1EDF, - 0x1EE1, 0x1EE1, 0x1EE3, 0x1EE3, 0x1EE5, 0x1EE5, 0x1EE7, 0x1EE7, - 0x1EE9, 0x1EE9, 0x1EEB, 0x1EEB, 0x1EED, 0x1EED, 0x1EEF, 0x1EEF, - 0x1EF1, 0x1EF1, 0x1EF3, 0x1EF3, 0x1EF5, 0x1EF5, 0x1EF7, 0x1EF7, - 0x1EF9, 0x1EF9, 0x1EFA, 0x1EFB, 0x1EFC, 0x1EFD, 0x1EFE, 0x1EFF, +static ObUnicaseInfoChar plane00_utf8[]={ + {0x0000,0x0000,0x0000}, {0x0001,0x0001,0x0001}, + {0x0002,0x0002,0x0002}, {0x0003,0x0003,0x0003}, + {0x0004,0x0004,0x0004}, {0x0005,0x0005,0x0005}, + {0x0006,0x0006,0x0006}, {0x0007,0x0007,0x0007}, + {0x0008,0x0008,0x0008}, {0x0009,0x0009,0x0009}, + {0x000A,0x000A,0x000A}, {0x000B,0x000B,0x000B}, + {0x000C,0x000C,0x000C}, {0x000D,0x000D,0x000D}, + {0x000E,0x000E,0x000E}, {0x000F,0x000F,0x000F}, + {0x0010,0x0010,0x0010}, {0x0011,0x0011,0x0011}, + {0x0012,0x0012,0x0012}, {0x0013,0x0013,0x0013}, + {0x0014,0x0014,0x0014}, {0x0015,0x0015,0x0015}, + {0x0016,0x0016,0x0016}, {0x0017,0x0017,0x0017}, + {0x0018,0x0018,0x0018}, {0x0019,0x0019,0x0019}, + {0x001A,0x001A,0x001A}, {0x001B,0x001B,0x001B}, + {0x001C,0x001C,0x001C}, {0x001D,0x001D,0x001D}, + {0x001E,0x001E,0x001E}, {0x001F,0x001F,0x001F}, + {0x0020,0x0020,0x0020}, {0x0021,0x0021,0x0021}, + {0x0022,0x0022,0x0022}, {0x0023,0x0023,0x0023}, + {0x0024,0x0024,0x0024}, {0x0025,0x0025,0x0025}, + {0x0026,0x0026,0x0026}, {0x0027,0x0027,0x0027}, + {0x0028,0x0028,0x0028}, {0x0029,0x0029,0x0029}, + {0x002A,0x002A,0x002A}, {0x002B,0x002B,0x002B}, + {0x002C,0x002C,0x002C}, {0x002D,0x002D,0x002D}, + {0x002E,0x002E,0x002E}, {0x002F,0x002F,0x002F}, + {0x0030,0x0030,0x0030}, {0x0031,0x0031,0x0031}, + {0x0032,0x0032,0x0032}, {0x0033,0x0033,0x0033}, + {0x0034,0x0034,0x0034}, {0x0035,0x0035,0x0035}, + {0x0036,0x0036,0x0036}, {0x0037,0x0037,0x0037}, + {0x0038,0x0038,0x0038}, {0x0039,0x0039,0x0039}, + {0x003A,0x003A,0x003A}, {0x003B,0x003B,0x003B}, + {0x003C,0x003C,0x003C}, {0x003D,0x003D,0x003D}, + {0x003E,0x003E,0x003E}, {0x003F,0x003F,0x003F}, + {0x0040,0x0040,0x0040}, {0x0041,0x0061,0x0041}, + {0x0042,0x0062,0x0042}, {0x0043,0x0063,0x0043}, + {0x0044,0x0064,0x0044}, {0x0045,0x0065,0x0045}, + {0x0046,0x0066,0x0046}, {0x0047,0x0067,0x0047}, + {0x0048,0x0068,0x0048}, {0x0049,0x0069,0x0049}, + {0x004A,0x006A,0x004A}, {0x004B,0x006B,0x004B}, + {0x004C,0x006C,0x004C}, {0x004D,0x006D,0x004D}, + {0x004E,0x006E,0x004E}, {0x004F,0x006F,0x004F}, + {0x0050,0x0070,0x0050}, {0x0051,0x0071,0x0051}, + {0x0052,0x0072,0x0052}, {0x0053,0x0073,0x0053}, + {0x0054,0x0074,0x0054}, {0x0055,0x0075,0x0055}, + {0x0056,0x0076,0x0056}, {0x0057,0x0077,0x0057}, + {0x0058,0x0078,0x0058}, {0x0059,0x0079,0x0059}, + {0x005A,0x007A,0x005A}, {0x005B,0x005B,0x005B}, + {0x005C,0x005C,0x005C}, {0x005D,0x005D,0x005D}, + {0x005E,0x005E,0x005E}, {0x005F,0x005F,0x005F}, + {0x0060,0x0060,0x0060}, {0x0041,0x0061,0x0041}, + {0x0042,0x0062,0x0042}, {0x0043,0x0063,0x0043}, + {0x0044,0x0064,0x0044}, {0x0045,0x0065,0x0045}, + {0x0046,0x0066,0x0046}, {0x0047,0x0067,0x0047}, + {0x0048,0x0068,0x0048}, {0x0049,0x0069,0x0049}, + {0x004A,0x006A,0x004A}, {0x004B,0x006B,0x004B}, + {0x004C,0x006C,0x004C}, {0x004D,0x006D,0x004D}, + {0x004E,0x006E,0x004E}, {0x004F,0x006F,0x004F}, + {0x0050,0x0070,0x0050}, {0x0051,0x0071,0x0051}, + {0x0052,0x0072,0x0052}, {0x0053,0x0073,0x0053}, + {0x0054,0x0074,0x0054}, {0x0055,0x0075,0x0055}, + {0x0056,0x0076,0x0056}, {0x0057,0x0077,0x0057}, + {0x0058,0x0078,0x0058}, {0x0059,0x0079,0x0059}, + {0x005A,0x007A,0x005A}, {0x007B,0x007B,0x007B}, + {0x007C,0x007C,0x007C}, {0x007D,0x007D,0x007D}, + {0x007E,0x007E,0x007E}, {0x007F,0x007F,0x007F}, + {0x0080,0x0080,0x0080}, {0x0081,0x0081,0x0081}, + {0x0082,0x0082,0x0082}, {0x0083,0x0083,0x0083}, + {0x0084,0x0084,0x0084}, {0x0085,0x0085,0x0085}, + {0x0086,0x0086,0x0086}, {0x0087,0x0087,0x0087}, + {0x0088,0x0088,0x0088}, {0x0089,0x0089,0x0089}, + {0x008A,0x008A,0x008A}, {0x008B,0x008B,0x008B}, + {0x008C,0x008C,0x008C}, {0x008D,0x008D,0x008D}, + {0x008E,0x008E,0x008E}, {0x008F,0x008F,0x008F}, + {0x0090,0x0090,0x0090}, {0x0091,0x0091,0x0091}, + {0x0092,0x0092,0x0092}, {0x0093,0x0093,0x0093}, + {0x0094,0x0094,0x0094}, {0x0095,0x0095,0x0095}, + {0x0096,0x0096,0x0096}, {0x0097,0x0097,0x0097}, + {0x0098,0x0098,0x0098}, {0x0099,0x0099,0x0099}, + {0x009A,0x009A,0x009A}, {0x009B,0x009B,0x009B}, + {0x009C,0x009C,0x009C}, {0x009D,0x009D,0x009D}, + {0x009E,0x009E,0x009E}, {0x009F,0x009F,0x009F}, + {0x00A0,0x00A0,0x00A0}, {0x00A1,0x00A1,0x00A1}, + {0x00A2,0x00A2,0x00A2}, {0x00A3,0x00A3,0x00A3}, + {0x00A4,0x00A4,0x00A4}, {0x00A5,0x00A5,0x00A5}, + {0x00A6,0x00A6,0x00A6}, {0x00A7,0x00A7,0x00A7}, + {0x00A8,0x00A8,0x00A8}, {0x00A9,0x00A9,0x00A9}, + {0x00AA,0x00AA,0x00AA}, {0x00AB,0x00AB,0x00AB}, + {0x00AC,0x00AC,0x00AC}, {0x00AD,0x00AD,0x00AD}, + {0x00AE,0x00AE,0x00AE}, {0x00AF,0x00AF,0x00AF}, + {0x00B0,0x00B0,0x00B0}, {0x00B1,0x00B1,0x00B1}, + {0x00B2,0x00B2,0x00B2}, {0x00B3,0x00B3,0x00B3}, + {0x00B4,0x00B4,0x00B4}, {0x039C,0x00B5,0x039C}, + {0x00B6,0x00B6,0x00B6}, {0x00B7,0x00B7,0x00B7}, + {0x00B8,0x00B8,0x00B8}, {0x00B9,0x00B9,0x00B9}, + {0x00BA,0x00BA,0x00BA}, {0x00BB,0x00BB,0x00BB}, + {0x00BC,0x00BC,0x00BC}, {0x00BD,0x00BD,0x00BD}, + {0x00BE,0x00BE,0x00BE}, {0x00BF,0x00BF,0x00BF}, + {0x00C0,0x00E0,0x0041}, {0x00C1,0x00E1,0x0041}, + {0x00C2,0x00E2,0x0041}, {0x00C3,0x00E3,0x0041}, + {0x00C4,0x00E4,0x0041}, {0x00C5,0x00E5,0x0041}, + {0x00C6,0x00E6,0x00C6}, {0x00C7,0x00E7,0x0043}, + {0x00C8,0x00E8,0x0045}, {0x00C9,0x00E9,0x0045}, + {0x00CA,0x00EA,0x0045}, {0x00CB,0x00EB,0x0045}, + {0x00CC,0x00EC,0x0049}, {0x00CD,0x00ED,0x0049}, + {0x00CE,0x00EE,0x0049}, {0x00CF,0x00EF,0x0049}, + {0x00D0,0x00F0,0x00D0}, {0x00D1,0x00F1,0x004E}, + {0x00D2,0x00F2,0x004F}, {0x00D3,0x00F3,0x004F}, + {0x00D4,0x00F4,0x004F}, {0x00D5,0x00F5,0x004F}, + {0x00D6,0x00F6,0x004F}, {0x00D7,0x00D7,0x00D7}, + {0x00D8,0x00F8,0x00D8}, {0x00D9,0x00F9,0x0055}, + {0x00DA,0x00FA,0x0055}, {0x00DB,0x00FB,0x0055}, + {0x00DC,0x00FC,0x0055}, {0x00DD,0x00FD,0x0059}, + {0x00DE,0x00FE,0x00DE}, {0x00DF,0x00DF,0x0053}, + {0x00C0,0x00E0,0x0041}, {0x00C1,0x00E1,0x0041}, + {0x00C2,0x00E2,0x0041}, {0x00C3,0x00E3,0x0041}, + {0x00C4,0x00E4,0x0041}, {0x00C5,0x00E5,0x0041}, + {0x00C6,0x00E6,0x00C6}, {0x00C7,0x00E7,0x0043}, + {0x00C8,0x00E8,0x0045}, {0x00C9,0x00E9,0x0045}, + {0x00CA,0x00EA,0x0045}, {0x00CB,0x00EB,0x0045}, + {0x00CC,0x00EC,0x0049}, {0x00CD,0x00ED,0x0049}, + {0x00CE,0x00EE,0x0049}, {0x00CF,0x00EF,0x0049}, + {0x00D0,0x00F0,0x00D0}, {0x00D1,0x00F1,0x004E}, + {0x00D2,0x00F2,0x004F}, {0x00D3,0x00F3,0x004F}, + {0x00D4,0x00F4,0x004F}, {0x00D5,0x00F5,0x004F}, + {0x00D6,0x00F6,0x004F}, {0x00F7,0x00F7,0x00F7}, + {0x00D8,0x00F8,0x00D8}, {0x00D9,0x00F9,0x0055}, + {0x00DA,0x00FA,0x0055}, {0x00DB,0x00FB,0x0055}, + {0x00DC,0x00FC,0x0055}, {0x00DD,0x00FD,0x0059}, + {0x00DE,0x00FE,0x00DE}, {0x0178,0x00FF,0x0059} }; -static uint32_t upper1E[]={ - 0x1E00, 0x1E00, 0x1E02, 0x1E02, 0x1E04, 0x1E04, 0x1E06, 0x1E06, - 0x1E08, 0x1E08, 0x1E0A, 0x1E0A, 0x1E0C, 0x1E0C, 0x1E0E, 0x1E0E, - 0x1E10, 0x1E10, 0x1E12, 0x1E12, 0x1E14, 0x1E14, 0x1E16, 0x1E16, - 0x1E18, 0x1E18, 0x1E1A, 0x1E1A, 0x1E1C, 0x1E1C, 0x1E1E, 0x1E1E, - 0x1E20, 0x1E20, 0x1E22, 0x1E22, 0x1E24, 0x1E24, 0x1E26, 0x1E26, - 0x1E28, 0x1E28, 0x1E2A, 0x1E2A, 0x1E2C, 0x1E2C, 0x1E2E, 0x1E2E, - 0x1E30, 0x1E30, 0x1E32, 0x1E32, 0x1E34, 0x1E34, 0x1E36, 0x1E36, - 0x1E38, 0x1E38, 0x1E3A, 0x1E3A, 0x1E3C, 0x1E3C, 0x1E3E, 0x1E3E, - 0x1E40, 0x1E40, 0x1E42, 0x1E42, 0x1E44, 0x1E44, 0x1E46, 0x1E46, - 0x1E48, 0x1E48, 0x1E4A, 0x1E4A, 0x1E4C, 0x1E4C, 0x1E4E, 0x1E4E, - 0x1E50, 0x1E50, 0x1E52, 0x1E52, 0x1E54, 0x1E54, 0x1E56, 0x1E56, - 0x1E58, 0x1E58, 0x1E5A, 0x1E5A, 0x1E5C, 0x1E5C, 0x1E5E, 0x1E5E, - 0x1E60, 0x1E60, 0x1E62, 0x1E62, 0x1E64, 0x1E64, 0x1E66, 0x1E66, - 0x1E68, 0x1E68, 0x1E6A, 0x1E6A, 0x1E6C, 0x1E6C, 0x1E6E, 0x1E6E, - 0x1E70, 0x1E70, 0x1E72, 0x1E72, 0x1E74, 0x1E74, 0x1E76, 0x1E76, - 0x1E78, 0x1E78, 0x1E7A, 0x1E7A, 0x1E7C, 0x1E7C, 0x1E7E, 0x1E7E, - 0x1E80, 0x1E80, 0x1E82, 0x1E82, 0x1E84, 0x1E84, 0x1E86, 0x1E86, - 0x1E88, 0x1E88, 0x1E8A, 0x1E8A, 0x1E8C, 0x1E8C, 0x1E8E, 0x1E8E, - 0x1E90, 0x1E90, 0x1E92, 0x1E92, 0x1E94, 0x1E94, 0x1E96, 0x1E97, - 0x1E98, 0x1E99, 0x1E9A, 0x1E60, 0x1E9C, 0x1E9D, 0x1E9E, 0x1E9F, - 0x1EA0, 0x1EA0, 0x1EA2, 0x1EA2, 0x1EA4, 0x1EA4, 0x1EA6, 0x1EA6, - 0x1EA8, 0x1EA8, 0x1EAA, 0x1EAA, 0x1EAC, 0x1EAC, 0x1EAE, 0x1EAE, - 0x1EB0, 0x1EB0, 0x1EB2, 0x1EB2, 0x1EB4, 0x1EB4, 0x1EB6, 0x1EB6, - 0x1EB8, 0x1EB8, 0x1EBA, 0x1EBA, 0x1EBC, 0x1EBC, 0x1EBE, 0x1EBE, - 0x1EC0, 0x1EC0, 0x1EC2, 0x1EC2, 0x1EC4, 0x1EC4, 0x1EC6, 0x1EC6, - 0x1EC8, 0x1EC8, 0x1ECA, 0x1ECA, 0x1ECC, 0x1ECC, 0x1ECE, 0x1ECE, - 0x1ED0, 0x1ED0, 0x1ED2, 0x1ED2, 0x1ED4, 0x1ED4, 0x1ED6, 0x1ED6, - 0x1ED8, 0x1ED8, 0x1EDA, 0x1EDA, 0x1EDC, 0x1EDC, 0x1EDE, 0x1EDE, - 0x1EE0, 0x1EE0, 0x1EE2, 0x1EE2, 0x1EE4, 0x1EE4, 0x1EE6, 0x1EE6, - 0x1EE8, 0x1EE8, 0x1EEA, 0x1EEA, 0x1EEC, 0x1EEC, 0x1EEE, 0x1EEE, - 0x1EF0, 0x1EF0, 0x1EF2, 0x1EF2, 0x1EF4, 0x1EF4, 0x1EF6, 0x1EF6, - 0x1EF8, 0x1EF8, 0x1EFA, 0x1EFB, 0x1EFC, 0x1EFD, 0x1EFE, 0x1EFF, +static ObUnicaseInfoChar plane01_utf8[]={ + {0x0100,0x0101,0x0041}, {0x0100,0x0101,0x0041}, + {0x0102,0x0103,0x0041}, {0x0102,0x0103,0x0041}, + {0x0104,0x0105,0x0041}, {0x0104,0x0105,0x0041}, + {0x0106,0x0107,0x0043}, {0x0106,0x0107,0x0043}, + {0x0108,0x0109,0x0043}, {0x0108,0x0109,0x0043}, + {0x010A,0x010B,0x0043}, {0x010A,0x010B,0x0043}, + {0x010C,0x010D,0x0043}, {0x010C,0x010D,0x0043}, + {0x010E,0x010F,0x0044}, {0x010E,0x010F,0x0044}, + {0x0110,0x0111,0x0110}, {0x0110,0x0111,0x0110}, + {0x0112,0x0113,0x0045}, {0x0112,0x0113,0x0045}, + {0x0114,0x0115,0x0045}, {0x0114,0x0115,0x0045}, + {0x0116,0x0117,0x0045}, {0x0116,0x0117,0x0045}, + {0x0118,0x0119,0x0045}, {0x0118,0x0119,0x0045}, + {0x011A,0x011B,0x0045}, {0x011A,0x011B,0x0045}, + {0x011C,0x011D,0x0047}, {0x011C,0x011D,0x0047}, + {0x011E,0x011F,0x0047}, {0x011E,0x011F,0x0047}, + {0x0120,0x0121,0x0047}, {0x0120,0x0121,0x0047}, + {0x0122,0x0123,0x0047}, {0x0122,0x0123,0x0047}, + {0x0124,0x0125,0x0048}, {0x0124,0x0125,0x0048}, + {0x0126,0x0127,0x0126}, {0x0126,0x0127,0x0126}, + {0x0128,0x0129,0x0049}, {0x0128,0x0129,0x0049}, + {0x012A,0x012B,0x0049}, {0x012A,0x012B,0x0049}, + {0x012C,0x012D,0x0049}, {0x012C,0x012D,0x0049}, + {0x012E,0x012F,0x0049}, {0x012E,0x012F,0x0049}, + {0x0130,0x0069,0x0049}, {0x0049,0x0131,0x0049}, + {0x0132,0x0133,0x0132}, {0x0132,0x0133,0x0132}, + {0x0134,0x0135,0x004A}, {0x0134,0x0135,0x004A}, + {0x0136,0x0137,0x004B}, {0x0136,0x0137,0x004B}, + {0x0138,0x0138,0x0138}, {0x0139,0x013A,0x004C}, + {0x0139,0x013A,0x004C}, {0x013B,0x013C,0x004C}, + {0x013B,0x013C,0x004C}, {0x013D,0x013E,0x004C}, + {0x013D,0x013E,0x004C}, {0x013F,0x0140,0x013F}, + {0x013F,0x0140,0x013F}, {0x0141,0x0142,0x0141}, + {0x0141,0x0142,0x0141}, {0x0143,0x0144,0x004E}, + {0x0143,0x0144,0x004E}, {0x0145,0x0146,0x004E}, + {0x0145,0x0146,0x004E}, {0x0147,0x0148,0x004E}, + {0x0147,0x0148,0x004E}, {0x0149,0x0149,0x0149}, + {0x014A,0x014B,0x014A}, {0x014A,0x014B,0x014A}, + {0x014C,0x014D,0x004F}, {0x014C,0x014D,0x004F}, + {0x014E,0x014F,0x004F}, {0x014E,0x014F,0x004F}, + {0x0150,0x0151,0x004F}, {0x0150,0x0151,0x004F}, + {0x0152,0x0153,0x0152}, {0x0152,0x0153,0x0152}, + {0x0154,0x0155,0x0052}, {0x0154,0x0155,0x0052}, + {0x0156,0x0157,0x0052}, {0x0156,0x0157,0x0052}, + {0x0158,0x0159,0x0052}, {0x0158,0x0159,0x0052}, + {0x015A,0x015B,0x0053}, {0x015A,0x015B,0x0053}, + {0x015C,0x015D,0x0053}, {0x015C,0x015D,0x0053}, + {0x015E,0x015F,0x0053}, {0x015E,0x015F,0x0053}, + {0x0160,0x0161,0x0053}, {0x0160,0x0161,0x0053}, + {0x0162,0x0163,0x0054}, {0x0162,0x0163,0x0054}, + {0x0164,0x0165,0x0054}, {0x0164,0x0165,0x0054}, + {0x0166,0x0167,0x0166}, {0x0166,0x0167,0x0166}, + {0x0168,0x0169,0x0055}, {0x0168,0x0169,0x0055}, + {0x016A,0x016B,0x0055}, {0x016A,0x016B,0x0055}, + {0x016C,0x016D,0x0055}, {0x016C,0x016D,0x0055}, + {0x016E,0x016F,0x0055}, {0x016E,0x016F,0x0055}, + {0x0170,0x0171,0x0055}, {0x0170,0x0171,0x0055}, + {0x0172,0x0173,0x0055}, {0x0172,0x0173,0x0055}, + {0x0174,0x0175,0x0057}, {0x0174,0x0175,0x0057}, + {0x0176,0x0177,0x0059}, {0x0176,0x0177,0x0059}, + {0x0178,0x00FF,0x0059}, {0x0179,0x017A,0x005A}, + {0x0179,0x017A,0x005A}, {0x017B,0x017C,0x005A}, + {0x017B,0x017C,0x005A}, {0x017D,0x017E,0x005A}, + {0x017D,0x017E,0x005A}, {0x0053,0x017F,0x0053}, + {0x0180,0x0180,0x0180}, {0x0181,0x0253,0x0181}, + {0x0182,0x0183,0x0182}, {0x0182,0x0183,0x0182}, + {0x0184,0x0185,0x0184}, {0x0184,0x0185,0x0184}, + {0x0186,0x0254,0x0186}, {0x0187,0x0188,0x0187}, + {0x0187,0x0188,0x0187}, {0x0189,0x0256,0x0189}, + {0x018A,0x0257,0x018A}, {0x018B,0x018C,0x018B}, + {0x018B,0x018C,0x018B}, {0x018D,0x018D,0x018D}, + {0x018E,0x01DD,0x018E}, {0x018F,0x0259,0x018F}, + {0x0190,0x025B,0x0190}, {0x0191,0x0192,0x0191}, + {0x0191,0x0192,0x0191}, {0x0193,0x0260,0x0193}, + {0x0194,0x0263,0x0194}, {0x01F6,0x0195,0x01F6}, + {0x0196,0x0269,0x0196}, {0x0197,0x0268,0x0197}, + {0x0198,0x0199,0x0198}, {0x0198,0x0199,0x0198}, + {0x019A,0x019A,0x019A}, {0x019B,0x019B,0x019B}, + {0x019C,0x026F,0x019C}, {0x019D,0x0272,0x019D}, + {0x019E,0x019E,0x019E}, {0x019F,0x0275,0x019F}, + {0x01A0,0x01A1,0x004F}, {0x01A0,0x01A1,0x004F}, + {0x01A2,0x01A3,0x01A2}, {0x01A2,0x01A3,0x01A2}, + {0x01A4,0x01A5,0x01A4}, {0x01A4,0x01A5,0x01A4}, + {0x01A6,0x0280,0x01A6}, {0x01A7,0x01A8,0x01A7}, + {0x01A7,0x01A8,0x01A7}, {0x01A9,0x0283,0x01A9}, + {0x01AA,0x01AA,0x01AA}, {0x01AB,0x01AB,0x01AB}, + {0x01AC,0x01AD,0x01AC}, {0x01AC,0x01AD,0x01AC}, + {0x01AE,0x0288,0x01AE}, {0x01AF,0x01B0,0x0055}, + {0x01AF,0x01B0,0x0055}, {0x01B1,0x028A,0x01B1}, + {0x01B2,0x028B,0x01B2}, {0x01B3,0x01B4,0x01B3}, + {0x01B3,0x01B4,0x01B3}, {0x01B5,0x01B6,0x01B5}, + {0x01B5,0x01B6,0x01B5}, {0x01B7,0x0292,0x01B7}, + {0x01B8,0x01B9,0x01B8}, {0x01B8,0x01B9,0x01B8}, + {0x01BA,0x01BA,0x01BA}, {0x01BB,0x01BB,0x01BB}, + {0x01BC,0x01BD,0x01BC}, {0x01BC,0x01BD,0x01BC}, + {0x01BE,0x01BE,0x01BE}, {0x01F7,0x01BF,0x01F7}, + {0x01C0,0x01C0,0x01C0}, {0x01C1,0x01C1,0x01C1}, + {0x01C2,0x01C2,0x01C2}, {0x01C3,0x01C3,0x01C3}, + {0x01C4,0x01C6,0x01C4}, {0x01C4,0x01C6,0x01C4}, + {0x01C4,0x01C6,0x01C4}, {0x01C7,0x01C9,0x01C7}, + {0x01C7,0x01C9,0x01C7}, {0x01C7,0x01C9,0x01C7}, + {0x01CA,0x01CC,0x01CA}, {0x01CA,0x01CC,0x01CA}, + {0x01CA,0x01CC,0x01CA}, {0x01CD,0x01CE,0x0041}, + {0x01CD,0x01CE,0x0041}, {0x01CF,0x01D0,0x0049}, + {0x01CF,0x01D0,0x0049}, {0x01D1,0x01D2,0x004F}, + {0x01D1,0x01D2,0x004F}, {0x01D3,0x01D4,0x0055}, + {0x01D3,0x01D4,0x0055}, {0x01D5,0x01D6,0x0055}, + {0x01D5,0x01D6,0x0055}, {0x01D7,0x01D8,0x0055}, + {0x01D7,0x01D8,0x0055}, {0x01D9,0x01DA,0x0055}, + {0x01D9,0x01DA,0x0055}, {0x01DB,0x01DC,0x0055}, + {0x01DB,0x01DC,0x0055}, {0x018E,0x01DD,0x018E}, + {0x01DE,0x01DF,0x0041}, {0x01DE,0x01DF,0x0041}, + {0x01E0,0x01E1,0x0041}, {0x01E0,0x01E1,0x0041}, + {0x01E2,0x01E3,0x00C6}, {0x01E2,0x01E3,0x00C6}, + {0x01E4,0x01E5,0x01E4}, {0x01E4,0x01E5,0x01E4}, + {0x01E6,0x01E7,0x0047}, {0x01E6,0x01E7,0x0047}, + {0x01E8,0x01E9,0x004B}, {0x01E8,0x01E9,0x004B}, + {0x01EA,0x01EB,0x004F}, {0x01EA,0x01EB,0x004F}, + {0x01EC,0x01ED,0x004F}, {0x01EC,0x01ED,0x004F}, + {0x01EE,0x01EF,0x01B7}, {0x01EE,0x01EF,0x01B7}, + {0x01F0,0x01F0,0x004A}, {0x01F1,0x01F3,0x01F1}, + {0x01F1,0x01F3,0x01F1}, {0x01F1,0x01F3,0x01F1}, + {0x01F4,0x01F5,0x0047}, {0x01F4,0x01F5,0x0047}, + {0x01F6,0x0195,0x01F6}, {0x01F7,0x01BF,0x01F7}, + {0x01F8,0x01F9,0x004E}, {0x01F8,0x01F9,0x004E}, + {0x01FA,0x01FB,0x0041}, {0x01FA,0x01FB,0x0041}, + {0x01FC,0x01FD,0x00C6}, {0x01FC,0x01FD,0x00C6}, + {0x01FE,0x01FF,0x00D8}, {0x01FE,0x01FF,0x00D8} }; -static uint32_t sort1E[]={ - 0x0041, 0x0041, 0x0042, 0x0042, 0x0042, 0x0042, 0x0042, 0x0042, - 0x0043, 0x0043, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, - 0x0044, 0x0044, 0x0044, 0x0044, 0x0045, 0x0045, 0x0045, 0x0045, - 0x0045, 0x0045, 0x0045, 0x0045, 0x0045, 0x0045, 0x0046, 0x0046, - 0x0047, 0x0047, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, - 0x0048, 0x0048, 0x0048, 0x0048, 0x0049, 0x0049, 0x0049, 0x0049, - 0x004B, 0x004B, 0x004B, 0x004B, 0x004B, 0x004B, 0x004C, 0x004C, - 0x004C, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C, 0x004D, 0x004D, - 0x004D, 0x004D, 0x004D, 0x004D, 0x004E, 0x004E, 0x004E, 0x004E, - 0x004E, 0x004E, 0x004E, 0x004E, 0x004F, 0x004F, 0x004F, 0x004F, - 0x004F, 0x004F, 0x004F, 0x004F, 0x0050, 0x0050, 0x0050, 0x0050, - 0x0052, 0x0052, 0x0052, 0x0052, 0x0052, 0x0052, 0x0052, 0x0052, - 0x0053, 0x0053, 0x0053, 0x0053, 0x0053, 0x0053, 0x0053, 0x0053, - 0x0053, 0x0053, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054, - 0x0054, 0x0054, 0x0055, 0x0055, 0x0055, 0x0055, 0x0055, 0x0055, - 0x0055, 0x0055, 0x0055, 0x0055, 0x0056, 0x0056, 0x0056, 0x0056, - 0x0057, 0x0057, 0x0057, 0x0057, 0x0057, 0x0057, 0x0057, 0x0057, - 0x0057, 0x0057, 0x0058, 0x0058, 0x0058, 0x0058, 0x0059, 0x0059, - 0x005A, 0x005A, 0x005A, 0x005A, 0x005A, 0x005A, 0x0048, 0x0054, - 0x0057, 0x0059, 0x1E9A, 0x0053, 0x1E9C, 0x1E9D, 0x1E9E, 0x1E9F, - 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, - 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, - 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, - 0x0045, 0x0045, 0x0045, 0x0045, 0x0045, 0x0045, 0x0045, 0x0045, - 0x0045, 0x0045, 0x0045, 0x0045, 0x0045, 0x0045, 0x0045, 0x0045, - 0x0049, 0x0049, 0x0049, 0x0049, 0x004F, 0x004F, 0x004F, 0x004F, - 0x004F, 0x004F, 0x004F, 0x004F, 0x004F, 0x004F, 0x004F, 0x004F, - 0x004F, 0x004F, 0x004F, 0x004F, 0x004F, 0x004F, 0x004F, 0x004F, - 0x004F, 0x004F, 0x004F, 0x004F, 0x0055, 0x0055, 0x0055, 0x0055, - 0x0055, 0x0055, 0x0055, 0x0055, 0x0055, 0x0055, 0x0055, 0x0055, - 0x0055, 0x0055, 0x0059, 0x0059, 0x0059, 0x0059, 0x0059, 0x0059, - 0x0059, 0x0059, 0x1EFA, 0x1EFB, 0x1EFC, 0x1EFD, 0x1EFE, 0x1EFF, +static ObUnicaseInfoChar plane02_utf8[]={ + {0x0200,0x0201,0x0041}, {0x0200,0x0201,0x0041}, + {0x0202,0x0203,0x0041}, {0x0202,0x0203,0x0041}, + {0x0204,0x0205,0x0045}, {0x0204,0x0205,0x0045}, + {0x0206,0x0207,0x0045}, {0x0206,0x0207,0x0045}, + {0x0208,0x0209,0x0049}, {0x0208,0x0209,0x0049}, + {0x020A,0x020B,0x0049}, {0x020A,0x020B,0x0049}, + {0x020C,0x020D,0x004F}, {0x020C,0x020D,0x004F}, + {0x020E,0x020F,0x004F}, {0x020E,0x020F,0x004F}, + {0x0210,0x0211,0x0052}, {0x0210,0x0211,0x0052}, + {0x0212,0x0213,0x0052}, {0x0212,0x0213,0x0052}, + {0x0214,0x0215,0x0055}, {0x0214,0x0215,0x0055}, + {0x0216,0x0217,0x0055}, {0x0216,0x0217,0x0055}, + {0x0218,0x0219,0x0053}, {0x0218,0x0219,0x0053}, + {0x021A,0x021B,0x0054}, {0x021A,0x021B,0x0054}, + {0x021C,0x021D,0x021C}, {0x021C,0x021D,0x021C}, + {0x021E,0x021F,0x0048}, {0x021E,0x021F,0x0048}, + {0x0220,0x0220,0x0220}, {0x0221,0x0221,0x0221}, + {0x0222,0x0223,0x0222}, {0x0222,0x0223,0x0222}, + {0x0224,0x0225,0x0224}, {0x0224,0x0225,0x0224}, + {0x0226,0x0227,0x0041}, {0x0226,0x0227,0x0041}, + {0x0228,0x0229,0x0045}, {0x0228,0x0229,0x0045}, + {0x022A,0x022B,0x004F}, {0x022A,0x022B,0x004F}, + {0x022C,0x022D,0x004F}, {0x022C,0x022D,0x004F}, + {0x022E,0x022F,0x004F}, {0x022E,0x022F,0x004F}, + {0x0230,0x0231,0x004F}, {0x0230,0x0231,0x004F}, + {0x0232,0x0233,0x0059}, {0x0232,0x0233,0x0059}, + {0x0234,0x0234,0x0234}, {0x0235,0x0235,0x0235}, + {0x0236,0x0236,0x0236}, {0x0237,0x0237,0x0237}, + {0x0238,0x0238,0x0238}, {0x0239,0x0239,0x0239}, + {0x023A,0x023A,0x023A}, {0x023B,0x023B,0x023B}, + {0x023C,0x023C,0x023C}, {0x023D,0x023D,0x023D}, + {0x023E,0x023E,0x023E}, {0x023F,0x023F,0x023F}, + {0x0240,0x0240,0x0240}, {0x0241,0x0241,0x0241}, + {0x0242,0x0242,0x0242}, {0x0243,0x0243,0x0243}, + {0x0244,0x0244,0x0244}, {0x0245,0x0245,0x0245}, + {0x0246,0x0246,0x0246}, {0x0247,0x0247,0x0247}, + {0x0248,0x0248,0x0248}, {0x0249,0x0249,0x0249}, + {0x024A,0x024A,0x024A}, {0x024B,0x024B,0x024B}, + {0x024C,0x024C,0x024C}, {0x024D,0x024D,0x024D}, + {0x024E,0x024E,0x024E}, {0x024F,0x024F,0x024F}, + {0x0250,0x0250,0x0250}, {0x0251,0x0251,0x0251}, + {0x0252,0x0252,0x0252}, {0x0181,0x0253,0x0181}, + {0x0186,0x0254,0x0186}, {0x0255,0x0255,0x0255}, + {0x0189,0x0256,0x0189}, {0x018A,0x0257,0x018A}, + {0x0258,0x0258,0x0258}, {0x018F,0x0259,0x018F}, + {0x025A,0x025A,0x025A}, {0x0190,0x025B,0x0190}, + {0x025C,0x025C,0x025C}, {0x025D,0x025D,0x025D}, + {0x025E,0x025E,0x025E}, {0x025F,0x025F,0x025F}, + {0x0193,0x0260,0x0193}, {0x0261,0x0261,0x0261}, + {0x0262,0x0262,0x0262}, {0x0194,0x0263,0x0194}, + {0x0264,0x0264,0x0264}, {0x0265,0x0265,0x0265}, + {0x0266,0x0266,0x0266}, {0x0267,0x0267,0x0267}, + {0x0197,0x0268,0x0197}, {0x0196,0x0269,0x0196}, + {0x026A,0x026A,0x026A}, {0x026B,0x026B,0x026B}, + {0x026C,0x026C,0x026C}, {0x026D,0x026D,0x026D}, + {0x026E,0x026E,0x026E}, {0x019C,0x026F,0x019C}, + {0x0270,0x0270,0x0270}, {0x0271,0x0271,0x0271}, + {0x019D,0x0272,0x019D}, {0x0273,0x0273,0x0273}, + {0x0274,0x0274,0x0274}, {0x019F,0x0275,0x019F}, + {0x0276,0x0276,0x0276}, {0x0277,0x0277,0x0277}, + {0x0278,0x0278,0x0278}, {0x0279,0x0279,0x0279}, + {0x027A,0x027A,0x027A}, {0x027B,0x027B,0x027B}, + {0x027C,0x027C,0x027C}, {0x027D,0x027D,0x027D}, + {0x027E,0x027E,0x027E}, {0x027F,0x027F,0x027F}, + {0x01A6,0x0280,0x01A6}, {0x0281,0x0281,0x0281}, + {0x0282,0x0282,0x0282}, {0x01A9,0x0283,0x01A9}, + {0x0284,0x0284,0x0284}, {0x0285,0x0285,0x0285}, + {0x0286,0x0286,0x0286}, {0x0287,0x0287,0x0287}, + {0x01AE,0x0288,0x01AE}, {0x0289,0x0289,0x0289}, + {0x01B1,0x028A,0x01B1}, {0x01B2,0x028B,0x01B2}, + {0x028C,0x028C,0x028C}, {0x028D,0x028D,0x028D}, + {0x028E,0x028E,0x028E}, {0x028F,0x028F,0x028F}, + {0x0290,0x0290,0x0290}, {0x0291,0x0291,0x0291}, + {0x01B7,0x0292,0x01B7}, {0x0293,0x0293,0x0293}, + {0x0294,0x0294,0x0294}, {0x0295,0x0295,0x0295}, + {0x0296,0x0296,0x0296}, {0x0297,0x0297,0x0297}, + {0x0298,0x0298,0x0298}, {0x0299,0x0299,0x0299}, + {0x029A,0x029A,0x029A}, {0x029B,0x029B,0x029B}, + {0x029C,0x029C,0x029C}, {0x029D,0x029D,0x029D}, + {0x029E,0x029E,0x029E}, {0x029F,0x029F,0x029F}, + {0x02A0,0x02A0,0x02A0}, {0x02A1,0x02A1,0x02A1}, + {0x02A2,0x02A2,0x02A2}, {0x02A3,0x02A3,0x02A3}, + {0x02A4,0x02A4,0x02A4}, {0x02A5,0x02A5,0x02A5}, + {0x02A6,0x02A6,0x02A6}, {0x02A7,0x02A7,0x02A7}, + {0x02A8,0x02A8,0x02A8}, {0x02A9,0x02A9,0x02A9}, + {0x02AA,0x02AA,0x02AA}, {0x02AB,0x02AB,0x02AB}, + {0x02AC,0x02AC,0x02AC}, {0x02AD,0x02AD,0x02AD}, + {0x02AE,0x02AE,0x02AE}, {0x02AF,0x02AF,0x02AF}, + {0x02B0,0x02B0,0x02B0}, {0x02B1,0x02B1,0x02B1}, + {0x02B2,0x02B2,0x02B2}, {0x02B3,0x02B3,0x02B3}, + {0x02B4,0x02B4,0x02B4}, {0x02B5,0x02B5,0x02B5}, + {0x02B6,0x02B6,0x02B6}, {0x02B7,0x02B7,0x02B7}, + {0x02B8,0x02B8,0x02B8}, {0x02B9,0x02B9,0x02B9}, + {0x02BA,0x02BA,0x02BA}, {0x02BB,0x02BB,0x02BB}, + {0x02BC,0x02BC,0x02BC}, {0x02BD,0x02BD,0x02BD}, + {0x02BE,0x02BE,0x02BE}, {0x02BF,0x02BF,0x02BF}, + {0x02C0,0x02C0,0x02C0}, {0x02C1,0x02C1,0x02C1}, + {0x02C2,0x02C2,0x02C2}, {0x02C3,0x02C3,0x02C3}, + {0x02C4,0x02C4,0x02C4}, {0x02C5,0x02C5,0x02C5}, + {0x02C6,0x02C6,0x02C6}, {0x02C7,0x02C7,0x02C7}, + {0x02C8,0x02C8,0x02C8}, {0x02C9,0x02C9,0x02C9}, + {0x02CA,0x02CA,0x02CA}, {0x02CB,0x02CB,0x02CB}, + {0x02CC,0x02CC,0x02CC}, {0x02CD,0x02CD,0x02CD}, + {0x02CE,0x02CE,0x02CE}, {0x02CF,0x02CF,0x02CF}, + {0x02D0,0x02D0,0x02D0}, {0x02D1,0x02D1,0x02D1}, + {0x02D2,0x02D2,0x02D2}, {0x02D3,0x02D3,0x02D3}, + {0x02D4,0x02D4,0x02D4}, {0x02D5,0x02D5,0x02D5}, + {0x02D6,0x02D6,0x02D6}, {0x02D7,0x02D7,0x02D7}, + {0x02D8,0x02D8,0x02D8}, {0x02D9,0x02D9,0x02D9}, + {0x02DA,0x02DA,0x02DA}, {0x02DB,0x02DB,0x02DB}, + {0x02DC,0x02DC,0x02DC}, {0x02DD,0x02DD,0x02DD}, + {0x02DE,0x02DE,0x02DE}, {0x02DF,0x02DF,0x02DF}, + {0x02E0,0x02E0,0x02E0}, {0x02E1,0x02E1,0x02E1}, + {0x02E2,0x02E2,0x02E2}, {0x02E3,0x02E3,0x02E3}, + {0x02E4,0x02E4,0x02E4}, {0x02E5,0x02E5,0x02E5}, + {0x02E6,0x02E6,0x02E6}, {0x02E7,0x02E7,0x02E7}, + {0x02E8,0x02E8,0x02E8}, {0x02E9,0x02E9,0x02E9}, + {0x02EA,0x02EA,0x02EA}, {0x02EB,0x02EB,0x02EB}, + {0x02EC,0x02EC,0x02EC}, {0x02ED,0x02ED,0x02ED}, + {0x02EE,0x02EE,0x02EE}, {0x02EF,0x02EF,0x02EF}, + {0x02F0,0x02F0,0x02F0}, {0x02F1,0x02F1,0x02F1}, + {0x02F2,0x02F2,0x02F2}, {0x02F3,0x02F3,0x02F3}, + {0x02F4,0x02F4,0x02F4}, {0x02F5,0x02F5,0x02F5}, + {0x02F6,0x02F6,0x02F6}, {0x02F7,0x02F7,0x02F7}, + {0x02F8,0x02F8,0x02F8}, {0x02F9,0x02F9,0x02F9}, + {0x02FA,0x02FA,0x02FA}, {0x02FB,0x02FB,0x02FB}, + {0x02FC,0x02FC,0x02FC}, {0x02FD,0x02FD,0x02FD}, + {0x02FE,0x02FE,0x02FE}, {0x02FF,0x02FF,0x02FF} }; -static uint32_t lower1F[]={ - 0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07, - 0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07, - 0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x1F16, 0x1F17, - 0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x1F1E, 0x1F1F, - 0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27, - 0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27, - 0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37, - 0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37, - 0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x1F46, 0x1F47, - 0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x1F4E, 0x1F4F, - 0x1F50, 0x1F51, 0x1F52, 0x1F53, 0x1F54, 0x1F55, 0x1F56, 0x1F57, - 0x1F58, 0x1F51, 0x1F5A, 0x1F53, 0x1F5C, 0x1F55, 0x1F5E, 0x1F57, - 0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67, - 0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67, - 0x1F70, 0x1F71, 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1F76, 0x1F77, - 0x1F78, 0x1F79, 0x1F7A, 0x1F7B, 0x1F7C, 0x1F7D, 0x1F7E, 0x1F7F, - 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, - 0x1FB0, 0x1FB1, 0x1FB2, 0x1FB3, 0x1FB4, 0x1FB5, 0x1FB6, 0x1FB7, - 0x1FB0, 0x1FB1, 0x1F70, 0x1F71, 0x1FB3, 0x1FBD, 0x1FBE, 0x1FBF, - 0x1FC0, 0x1FC1, 0x1FC2, 0x1FC3, 0x1FC4, 0x1FC5, 0x1FC6, 0x1FC7, - 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1FC3, 0x1FCD, 0x1FCE, 0x1FCF, - 0x1FD0, 0x1FD1, 0x1FD2, 0x1FD3, 0x1FD4, 0x1FD5, 0x1FD6, 0x1FD7, - 0x1FD0, 0x1FD1, 0x1F76, 0x1F77, 0x1FDC, 0x1FDD, 0x1FDE, 0x1FDF, - 0x1FE0, 0x1FE1, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FE5, 0x1FE6, 0x1FE7, - 0x1FE0, 0x1FE1, 0x1F7A, 0x1F7B, 0x1FE5, 0x1FED, 0x1FEE, 0x1FEF, - 0x1FF0, 0x1FF1, 0x1FF2, 0x1FF3, 0x1FF4, 0x1FF5, 0x1FF6, 0x1FF7, - 0x1F78, 0x1F79, 0x1F7C, 0x1F7D, 0x1FF3, 0x1FFD, 0x1FFE, 0x1FFF, +static ObUnicaseInfoChar plane03_utf8[]={ + {0x0300,0x0300,0x0300}, {0x0301,0x0301,0x0301}, + {0x0302,0x0302,0x0302}, {0x0303,0x0303,0x0303}, + {0x0304,0x0304,0x0304}, {0x0305,0x0305,0x0305}, + {0x0306,0x0306,0x0306}, {0x0307,0x0307,0x0307}, + {0x0308,0x0308,0x0308}, {0x0309,0x0309,0x0309}, + {0x030A,0x030A,0x030A}, {0x030B,0x030B,0x030B}, + {0x030C,0x030C,0x030C}, {0x030D,0x030D,0x030D}, + {0x030E,0x030E,0x030E}, {0x030F,0x030F,0x030F}, + {0x0310,0x0310,0x0310}, {0x0311,0x0311,0x0311}, + {0x0312,0x0312,0x0312}, {0x0313,0x0313,0x0313}, + {0x0314,0x0314,0x0314}, {0x0315,0x0315,0x0315}, + {0x0316,0x0316,0x0316}, {0x0317,0x0317,0x0317}, + {0x0318,0x0318,0x0318}, {0x0319,0x0319,0x0319}, + {0x031A,0x031A,0x031A}, {0x031B,0x031B,0x031B}, + {0x031C,0x031C,0x031C}, {0x031D,0x031D,0x031D}, + {0x031E,0x031E,0x031E}, {0x031F,0x031F,0x031F}, + {0x0320,0x0320,0x0320}, {0x0321,0x0321,0x0321}, + {0x0322,0x0322,0x0322}, {0x0323,0x0323,0x0323}, + {0x0324,0x0324,0x0324}, {0x0325,0x0325,0x0325}, + {0x0326,0x0326,0x0326}, {0x0327,0x0327,0x0327}, + {0x0328,0x0328,0x0328}, {0x0329,0x0329,0x0329}, + {0x032A,0x032A,0x032A}, {0x032B,0x032B,0x032B}, + {0x032C,0x032C,0x032C}, {0x032D,0x032D,0x032D}, + {0x032E,0x032E,0x032E}, {0x032F,0x032F,0x032F}, + {0x0330,0x0330,0x0330}, {0x0331,0x0331,0x0331}, + {0x0332,0x0332,0x0332}, {0x0333,0x0333,0x0333}, + {0x0334,0x0334,0x0334}, {0x0335,0x0335,0x0335}, + {0x0336,0x0336,0x0336}, {0x0337,0x0337,0x0337}, + {0x0338,0x0338,0x0338}, {0x0339,0x0339,0x0339}, + {0x033A,0x033A,0x033A}, {0x033B,0x033B,0x033B}, + {0x033C,0x033C,0x033C}, {0x033D,0x033D,0x033D}, + {0x033E,0x033E,0x033E}, {0x033F,0x033F,0x033F}, + {0x0340,0x0340,0x0340}, {0x0341,0x0341,0x0341}, + {0x0342,0x0342,0x0342}, {0x0343,0x0343,0x0343}, + {0x0344,0x0344,0x0344}, {0x0399,0x0345,0x0399}, + {0x0346,0x0346,0x0346}, {0x0347,0x0347,0x0347}, + {0x0348,0x0348,0x0348}, {0x0349,0x0349,0x0349}, + {0x034A,0x034A,0x034A}, {0x034B,0x034B,0x034B}, + {0x034C,0x034C,0x034C}, {0x034D,0x034D,0x034D}, + {0x034E,0x034E,0x034E}, {0x034F,0x034F,0x034F}, + {0x0350,0x0350,0x0350}, {0x0351,0x0351,0x0351}, + {0x0352,0x0352,0x0352}, {0x0353,0x0353,0x0353}, + {0x0354,0x0354,0x0354}, {0x0355,0x0355,0x0355}, + {0x0356,0x0356,0x0356}, {0x0357,0x0357,0x0357}, + {0x0358,0x0358,0x0358}, {0x0359,0x0359,0x0359}, + {0x035A,0x035A,0x035A}, {0x035B,0x035B,0x035B}, + {0x035C,0x035C,0x035C}, {0x035D,0x035D,0x035D}, + {0x035E,0x035E,0x035E}, {0x035F,0x035F,0x035F}, + {0x0360,0x0360,0x0360}, {0x0361,0x0361,0x0361}, + {0x0362,0x0362,0x0362}, {0x0363,0x0363,0x0363}, + {0x0364,0x0364,0x0364}, {0x0365,0x0365,0x0365}, + {0x0366,0x0366,0x0366}, {0x0367,0x0367,0x0367}, + {0x0368,0x0368,0x0368}, {0x0369,0x0369,0x0369}, + {0x036A,0x036A,0x036A}, {0x036B,0x036B,0x036B}, + {0x036C,0x036C,0x036C}, {0x036D,0x036D,0x036D}, + {0x036E,0x036E,0x036E}, {0x036F,0x036F,0x036F}, + {0x0370,0x0370,0x0370}, {0x0371,0x0371,0x0371}, + {0x0372,0x0372,0x0372}, {0x0373,0x0373,0x0373}, + {0x0374,0x0374,0x0374}, {0x0375,0x0375,0x0375}, + {0x0376,0x0376,0x0376}, {0x0377,0x0377,0x0377}, + {0x0378,0x0378,0x0378}, {0x0379,0x0379,0x0379}, + {0x037A,0x037A,0x037A}, {0x037B,0x037B,0x037B}, + {0x037C,0x037C,0x037C}, {0x037D,0x037D,0x037D}, + {0x037E,0x037E,0x037E}, {0x037F,0x037F,0x037F}, + {0x0380,0x0380,0x0380}, {0x0381,0x0381,0x0381}, + {0x0382,0x0382,0x0382}, {0x0383,0x0383,0x0383}, + {0x0384,0x0384,0x0384}, {0x0385,0x0385,0x0385}, + {0x0386,0x03AC,0x0391}, {0x0387,0x0387,0x0387}, + {0x0388,0x03AD,0x0395}, {0x0389,0x03AE,0x0397}, + {0x038A,0x03AF,0x0399}, {0x038B,0x038B,0x038B}, + {0x038C,0x03CC,0x039F}, {0x038D,0x038D,0x038D}, + {0x038E,0x03CD,0x03A5}, {0x038F,0x03CE,0x03A9}, + {0x0390,0x0390,0x0399}, {0x0391,0x03B1,0x0391}, + {0x0392,0x03B2,0x0392}, {0x0393,0x03B3,0x0393}, + {0x0394,0x03B4,0x0394}, {0x0395,0x03B5,0x0395}, + {0x0396,0x03B6,0x0396}, {0x0397,0x03B7,0x0397}, + {0x0398,0x03B8,0x0398}, {0x0399,0x03B9,0x0399}, + {0x039A,0x03BA,0x039A}, {0x039B,0x03BB,0x039B}, + {0x039C,0x03BC,0x039C}, {0x039D,0x03BD,0x039D}, + {0x039E,0x03BE,0x039E}, {0x039F,0x03BF,0x039F}, + {0x03A0,0x03C0,0x03A0}, {0x03A1,0x03C1,0x03A1}, + {0x03A2,0x03A2,0x03A2}, {0x03A3,0x03C3,0x03A3}, + {0x03A4,0x03C4,0x03A4}, {0x03A5,0x03C5,0x03A5}, + {0x03A6,0x03C6,0x03A6}, {0x03A7,0x03C7,0x03A7}, + {0x03A8,0x03C8,0x03A8}, {0x03A9,0x03C9,0x03A9}, + {0x03AA,0x03CA,0x0399}, {0x03AB,0x03CB,0x03A5}, + {0x0386,0x03AC,0x0391}, {0x0388,0x03AD,0x0395}, + {0x0389,0x03AE,0x0397}, {0x038A,0x03AF,0x0399}, + {0x03B0,0x03B0,0x03A5}, {0x0391,0x03B1,0x0391}, + {0x0392,0x03B2,0x0392}, {0x0393,0x03B3,0x0393}, + {0x0394,0x03B4,0x0394}, {0x0395,0x03B5,0x0395}, + {0x0396,0x03B6,0x0396}, {0x0397,0x03B7,0x0397}, + {0x0398,0x03B8,0x0398}, {0x0399,0x03B9,0x0399}, + {0x039A,0x03BA,0x039A}, {0x039B,0x03BB,0x039B}, + {0x039C,0x03BC,0x039C}, {0x039D,0x03BD,0x039D}, + {0x039E,0x03BE,0x039E}, {0x039F,0x03BF,0x039F}, + {0x03A0,0x03C0,0x03A0}, {0x03A1,0x03C1,0x03A1}, + {0x03A3,0x03C2,0x03A3}, {0x03A3,0x03C3,0x03A3}, + {0x03A4,0x03C4,0x03A4}, {0x03A5,0x03C5,0x03A5}, + {0x03A6,0x03C6,0x03A6}, {0x03A7,0x03C7,0x03A7}, + {0x03A8,0x03C8,0x03A8}, {0x03A9,0x03C9,0x03A9}, + {0x03AA,0x03CA,0x0399}, {0x03AB,0x03CB,0x03A5}, + {0x038C,0x03CC,0x039F}, {0x038E,0x03CD,0x03A5}, + {0x038F,0x03CE,0x03A9}, {0x03CF,0x03CF,0x03CF}, + {0x0392,0x03D0,0x0392}, {0x0398,0x03D1,0x0398}, + {0x03D2,0x03D2,0x03D2}, {0x03D3,0x03D3,0x03D2}, + {0x03D4,0x03D4,0x03D2}, {0x03A6,0x03D5,0x03A6}, + {0x03A0,0x03D6,0x03A0}, {0x03D7,0x03D7,0x03D7}, + {0x03D8,0x03D8,0x03D8}, {0x03D9,0x03D9,0x03D9}, + {0x03DA,0x03DB,0x03DA}, {0x03DA,0x03DB,0x03DA}, + {0x03DC,0x03DD,0x03DC}, {0x03DC,0x03DD,0x03DC}, + {0x03DE,0x03DF,0x03DE}, {0x03DE,0x03DF,0x03DE}, + {0x03E0,0x03E1,0x03E0}, {0x03E0,0x03E1,0x03E0}, + {0x03E2,0x03E3,0x03E2}, {0x03E2,0x03E3,0x03E2}, + {0x03E4,0x03E5,0x03E4}, {0x03E4,0x03E5,0x03E4}, + {0x03E6,0x03E7,0x03E6}, {0x03E6,0x03E7,0x03E6}, + {0x03E8,0x03E9,0x03E8}, {0x03E8,0x03E9,0x03E8}, + {0x03EA,0x03EB,0x03EA}, {0x03EA,0x03EB,0x03EA}, + {0x03EC,0x03ED,0x03EC}, {0x03EC,0x03ED,0x03EC}, + {0x03EE,0x03EF,0x03EE}, {0x03EE,0x03EF,0x03EE}, + {0x039A,0x03F0,0x039A}, {0x03A1,0x03F1,0x03A1}, + {0x03A3,0x03F2,0x03A3}, {0x03F3,0x03F3,0x03F3}, + {0x03F4,0x03F4,0x03F4}, {0x03F5,0x03F5,0x03F5}, + {0x03F6,0x03F6,0x03F6}, {0x03F7,0x03F7,0x03F7}, + {0x03F8,0x03F8,0x03F8}, {0x03F9,0x03F9,0x03F9}, + {0x03FA,0x03FA,0x03FA}, {0x03FB,0x03FB,0x03FB}, + {0x03FC,0x03FC,0x03FC}, {0x03FD,0x03FD,0x03FD}, + {0x03FE,0x03FE,0x03FE}, {0x03FF,0x03FF,0x03FF} }; -static uint32_t upper1F[]={ - 0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F, - 0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F, - 0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x1F16, 0x1F17, - 0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x1F1E, 0x1F1F, - 0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F, - 0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F, - 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F, - 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F, - 0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x1F46, 0x1F47, - 0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x1F4E, 0x1F4F, - 0x1F50, 0x1F59, 0x1F52, 0x1F5B, 0x1F54, 0x1F5D, 0x1F56, 0x1F5F, - 0x1F58, 0x1F59, 0x1F5A, 0x1F5B, 0x1F5C, 0x1F5D, 0x1F5E, 0x1F5F, - 0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F, - 0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F, - 0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB, - 0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB, 0x1FFA, 0x1FFB, 0x1F7E, 0x1F7F, - 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, - 0x1FB8, 0x1FB9, 0x1FB2, 0x1FBC, 0x1FB4, 0x1FB5, 0x1FB6, 0x1FB7, - 0x1FB8, 0x1FB9, 0x1FBA, 0x1FBB, 0x1FBC, 0x1FBD, 0x0399, 0x1FBF, - 0x1FC0, 0x1FC1, 0x1FC2, 0x1FCC, 0x1FC4, 0x1FC5, 0x1FC6, 0x1FC7, - 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FCC, 0x1FCD, 0x1FCE, 0x1FCF, - 0x1FD8, 0x1FD9, 0x1FD2, 0x1FD3, 0x1FD4, 0x1FD5, 0x1FD6, 0x1FD7, - 0x1FD8, 0x1FD9, 0x1FDA, 0x1FDB, 0x1FDC, 0x1FDD, 0x1FDE, 0x1FDF, - 0x1FE8, 0x1FE9, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FEC, 0x1FE6, 0x1FE7, - 0x1FE8, 0x1FE9, 0x1FEA, 0x1FEB, 0x1FEC, 0x1FED, 0x1FEE, 0x1FEF, - 0x1FF0, 0x1FF1, 0x1FF2, 0x1FFC, 0x1FF4, 0x1FF5, 0x1FF6, 0x1FF7, - 0x1FF8, 0x1FF9, 0x1FFA, 0x1FFB, 0x1FFC, 0x1FFD, 0x1FFE, 0x1FFF, +static ObUnicaseInfoChar plane04_utf8[]={ + {0x0400,0x0450,0x0415}, {0x0401,0x0451,0x0415}, + {0x0402,0x0452,0x0402}, {0x0403,0x0453,0x0413}, + {0x0404,0x0454,0x0404}, {0x0405,0x0455,0x0405}, + {0x0406,0x0456,0x0406}, {0x0407,0x0457,0x0406}, + {0x0408,0x0458,0x0408}, {0x0409,0x0459,0x0409}, + {0x040A,0x045A,0x040A}, {0x040B,0x045B,0x040B}, + {0x040C,0x045C,0x041A}, {0x040D,0x045D,0x0418}, + {0x040E,0x045E,0x0423}, {0x040F,0x045F,0x040F}, + {0x0410,0x0430,0x0410}, {0x0411,0x0431,0x0411}, + {0x0412,0x0432,0x0412}, {0x0413,0x0433,0x0413}, + {0x0414,0x0434,0x0414}, {0x0415,0x0435,0x0415}, + {0x0416,0x0436,0x0416}, {0x0417,0x0437,0x0417}, + {0x0418,0x0438,0x0418}, {0x0419,0x0439,0x0419}, + {0x041A,0x043A,0x041A}, {0x041B,0x043B,0x041B}, + {0x041C,0x043C,0x041C}, {0x041D,0x043D,0x041D}, + {0x041E,0x043E,0x041E}, {0x041F,0x043F,0x041F}, + {0x0420,0x0440,0x0420}, {0x0421,0x0441,0x0421}, + {0x0422,0x0442,0x0422}, {0x0423,0x0443,0x0423}, + {0x0424,0x0444,0x0424}, {0x0425,0x0445,0x0425}, + {0x0426,0x0446,0x0426}, {0x0427,0x0447,0x0427}, + {0x0428,0x0448,0x0428}, {0x0429,0x0449,0x0429}, + {0x042A,0x044A,0x042A}, {0x042B,0x044B,0x042B}, + {0x042C,0x044C,0x042C}, {0x042D,0x044D,0x042D}, + {0x042E,0x044E,0x042E}, {0x042F,0x044F,0x042F}, + {0x0410,0x0430,0x0410}, {0x0411,0x0431,0x0411}, + {0x0412,0x0432,0x0412}, {0x0413,0x0433,0x0413}, + {0x0414,0x0434,0x0414}, {0x0415,0x0435,0x0415}, + {0x0416,0x0436,0x0416}, {0x0417,0x0437,0x0417}, + {0x0418,0x0438,0x0418}, {0x0419,0x0439,0x0419}, + {0x041A,0x043A,0x041A}, {0x041B,0x043B,0x041B}, + {0x041C,0x043C,0x041C}, {0x041D,0x043D,0x041D}, + {0x041E,0x043E,0x041E}, {0x041F,0x043F,0x041F}, + {0x0420,0x0440,0x0420}, {0x0421,0x0441,0x0421}, + {0x0422,0x0442,0x0422}, {0x0423,0x0443,0x0423}, + {0x0424,0x0444,0x0424}, {0x0425,0x0445,0x0425}, + {0x0426,0x0446,0x0426}, {0x0427,0x0447,0x0427}, + {0x0428,0x0448,0x0428}, {0x0429,0x0449,0x0429}, + {0x042A,0x044A,0x042A}, {0x042B,0x044B,0x042B}, + {0x042C,0x044C,0x042C}, {0x042D,0x044D,0x042D}, + {0x042E,0x044E,0x042E}, {0x042F,0x044F,0x042F}, + {0x0400,0x0450,0x0415}, {0x0401,0x0451,0x0415}, + {0x0402,0x0452,0x0402}, {0x0403,0x0453,0x0413}, + {0x0404,0x0454,0x0404}, {0x0405,0x0455,0x0405}, + {0x0406,0x0456,0x0406}, {0x0407,0x0457,0x0406}, + {0x0408,0x0458,0x0408}, {0x0409,0x0459,0x0409}, + {0x040A,0x045A,0x040A}, {0x040B,0x045B,0x040B}, + {0x040C,0x045C,0x041A}, {0x040D,0x045D,0x0418}, + {0x040E,0x045E,0x0423}, {0x040F,0x045F,0x040F}, + {0x0460,0x0461,0x0460}, {0x0460,0x0461,0x0460}, + {0x0462,0x0463,0x0462}, {0x0462,0x0463,0x0462}, + {0x0464,0x0465,0x0464}, {0x0464,0x0465,0x0464}, + {0x0466,0x0467,0x0466}, {0x0466,0x0467,0x0466}, + {0x0468,0x0469,0x0468}, {0x0468,0x0469,0x0468}, + {0x046A,0x046B,0x046A}, {0x046A,0x046B,0x046A}, + {0x046C,0x046D,0x046C}, {0x046C,0x046D,0x046C}, + {0x046E,0x046F,0x046E}, {0x046E,0x046F,0x046E}, + {0x0470,0x0471,0x0470}, {0x0470,0x0471,0x0470}, + {0x0472,0x0473,0x0472}, {0x0472,0x0473,0x0472}, + {0x0474,0x0475,0x0474}, {0x0474,0x0475,0x0474}, + {0x0476,0x0477,0x0474}, {0x0476,0x0477,0x0474}, + {0x0478,0x0479,0x0478}, {0x0478,0x0479,0x0478}, + {0x047A,0x047B,0x047A}, {0x047A,0x047B,0x047A}, + {0x047C,0x047D,0x047C}, {0x047C,0x047D,0x047C}, + {0x047E,0x047F,0x047E}, {0x047E,0x047F,0x047E}, + {0x0480,0x0481,0x0480}, {0x0480,0x0481,0x0480}, + {0x0482,0x0482,0x0482}, {0x0483,0x0483,0x0483}, + {0x0484,0x0484,0x0484}, {0x0485,0x0485,0x0485}, + {0x0486,0x0486,0x0486}, {0x0487,0x0487,0x0487}, + {0x0488,0x0488,0x0488}, {0x0489,0x0489,0x0489}, + {0x048A,0x048A,0x048A}, {0x048B,0x048B,0x048B}, + {0x048C,0x048D,0x048C}, {0x048C,0x048D,0x048C}, + {0x048E,0x048F,0x048E}, {0x048E,0x048F,0x048E}, + {0x0490,0x0491,0x0490}, {0x0490,0x0491,0x0490}, + {0x0492,0x0493,0x0492}, {0x0492,0x0493,0x0492}, + {0x0494,0x0495,0x0494}, {0x0494,0x0495,0x0494}, + {0x0496,0x0497,0x0496}, {0x0496,0x0497,0x0496}, + {0x0498,0x0499,0x0498}, {0x0498,0x0499,0x0498}, + {0x049A,0x049B,0x049A}, {0x049A,0x049B,0x049A}, + {0x049C,0x049D,0x049C}, {0x049C,0x049D,0x049C}, + {0x049E,0x049F,0x049E}, {0x049E,0x049F,0x049E}, + {0x04A0,0x04A1,0x04A0}, {0x04A0,0x04A1,0x04A0}, + {0x04A2,0x04A3,0x04A2}, {0x04A2,0x04A3,0x04A2}, + {0x04A4,0x04A5,0x04A4}, {0x04A4,0x04A5,0x04A4}, + {0x04A6,0x04A7,0x04A6}, {0x04A6,0x04A7,0x04A6}, + {0x04A8,0x04A9,0x04A8}, {0x04A8,0x04A9,0x04A8}, + {0x04AA,0x04AB,0x04AA}, {0x04AA,0x04AB,0x04AA}, + {0x04AC,0x04AD,0x04AC}, {0x04AC,0x04AD,0x04AC}, + {0x04AE,0x04AF,0x04AE}, {0x04AE,0x04AF,0x04AE}, + {0x04B0,0x04B1,0x04B0}, {0x04B0,0x04B1,0x04B0}, + {0x04B2,0x04B3,0x04B2}, {0x04B2,0x04B3,0x04B2}, + {0x04B4,0x04B5,0x04B4}, {0x04B4,0x04B5,0x04B4}, + {0x04B6,0x04B7,0x04B6}, {0x04B6,0x04B7,0x04B6}, + {0x04B8,0x04B9,0x04B8}, {0x04B8,0x04B9,0x04B8}, + {0x04BA,0x04BB,0x04BA}, {0x04BA,0x04BB,0x04BA}, + {0x04BC,0x04BD,0x04BC}, {0x04BC,0x04BD,0x04BC}, + {0x04BE,0x04BF,0x04BE}, {0x04BE,0x04BF,0x04BE}, + {0x04C0,0x04C0,0x04C0}, {0x04C1,0x04C2,0x0416}, + {0x04C1,0x04C2,0x0416}, {0x04C3,0x04C4,0x04C3}, + {0x04C3,0x04C4,0x04C3}, {0x04C5,0x04C5,0x04C5}, + {0x04C6,0x04C6,0x04C6}, {0x04C7,0x04C8,0x04C7}, + {0x04C7,0x04C8,0x04C7}, {0x04C9,0x04C9,0x04C9}, + {0x04CA,0x04CA,0x04CA}, {0x04CB,0x04CC,0x04CB}, + {0x04CB,0x04CC,0x04CB}, {0x04CD,0x04CD,0x04CD}, + {0x04CE,0x04CE,0x04CE}, {0x04CF,0x04CF,0x04CF}, + {0x04D0,0x04D1,0x0410}, {0x04D0,0x04D1,0x0410}, + {0x04D2,0x04D3,0x0410}, {0x04D2,0x04D3,0x0410}, + {0x04D4,0x04D5,0x04D4}, {0x04D4,0x04D5,0x04D4}, + {0x04D6,0x04D7,0x0415}, {0x04D6,0x04D7,0x0415}, + {0x04D8,0x04D9,0x04D8}, {0x04D8,0x04D9,0x04D8}, + {0x04DA,0x04DB,0x04D8}, {0x04DA,0x04DB,0x04D8}, + {0x04DC,0x04DD,0x0416}, {0x04DC,0x04DD,0x0416}, + {0x04DE,0x04DF,0x0417}, {0x04DE,0x04DF,0x0417}, + {0x04E0,0x04E1,0x04E0}, {0x04E0,0x04E1,0x04E0}, + {0x04E2,0x04E3,0x0418}, {0x04E2,0x04E3,0x0418}, + {0x04E4,0x04E5,0x0418}, {0x04E4,0x04E5,0x0418}, + {0x04E6,0x04E7,0x041E}, {0x04E6,0x04E7,0x041E}, + {0x04E8,0x04E9,0x04E8}, {0x04E8,0x04E9,0x04E8}, + {0x04EA,0x04EB,0x04E8}, {0x04EA,0x04EB,0x04E8}, + {0x04EC,0x04ED,0x042D}, {0x04EC,0x04ED,0x042D}, + {0x04EE,0x04EF,0x0423}, {0x04EE,0x04EF,0x0423}, + {0x04F0,0x04F1,0x0423}, {0x04F0,0x04F1,0x0423}, + {0x04F2,0x04F3,0x0423}, {0x04F2,0x04F3,0x0423}, + {0x04F4,0x04F5,0x0427}, {0x04F4,0x04F5,0x0427}, + {0x04F6,0x04F6,0x04F6}, {0x04F7,0x04F7,0x04F7}, + {0x04F8,0x04F9,0x042B}, {0x04F8,0x04F9,0x042B}, + {0x04FA,0x04FA,0x04FA}, {0x04FB,0x04FB,0x04FB}, + {0x04FC,0x04FC,0x04FC}, {0x04FD,0x04FD,0x04FD}, + {0x04FE,0x04FE,0x04FE}, {0x04FF,0x04FF,0x04FF} }; -static uint32_t sort1F[]={ - 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, - 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, - 0x0395, 0x0395, 0x0395, 0x0395, 0x0395, 0x0395, 0x1F16, 0x1F17, - 0x0395, 0x0395, 0x0395, 0x0395, 0x0395, 0x0395, 0x1F1E, 0x1F1F, - 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, - 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, - 0x0399, 0x0399, 0x0399, 0x0399, 0x0399, 0x0399, 0x0399, 0x0399, - 0x0399, 0x0399, 0x0399, 0x0399, 0x0399, 0x0399, 0x0399, 0x0399, - 0x039F, 0x039F, 0x039F, 0x039F, 0x039F, 0x039F, 0x1F46, 0x1F47, - 0x039F, 0x039F, 0x039F, 0x039F, 0x039F, 0x039F, 0x1F4E, 0x1F4F, - 0x03A5, 0x03A5, 0x03A5, 0x03A5, 0x03A5, 0x03A5, 0x03A5, 0x03A5, - 0x1F58, 0x03A5, 0x1F5A, 0x03A5, 0x1F5C, 0x03A5, 0x1F5E, 0x03A5, - 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, - 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, - 0x0391, 0x1FBB, 0x0395, 0x1FC9, 0x0397, 0x1FCB, 0x0399, 0x1FDB, - 0x039F, 0x1FF9, 0x03A5, 0x1FEB, 0x03A9, 0x1FFB, 0x1F7E, 0x1F7F, - 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, - 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, - 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, - 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, - 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, - 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, - 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x1FB5, 0x0391, 0x0391, - 0x0391, 0x0391, 0x0391, 0x1FBB, 0x0391, 0x1FBD, 0x0399, 0x1FBF, - 0x1FC0, 0x1FC1, 0x0397, 0x0397, 0x0397, 0x1FC5, 0x0397, 0x0397, - 0x0395, 0x1FC9, 0x0397, 0x1FCB, 0x0397, 0x1FCD, 0x1FCE, 0x1FCF, - 0x0399, 0x0399, 0x0399, 0x1FD3, 0x1FD4, 0x1FD5, 0x0399, 0x0399, - 0x0399, 0x0399, 0x0399, 0x1FDB, 0x1FDC, 0x1FDD, 0x1FDE, 0x1FDF, - 0x03A5, 0x03A5, 0x03A5, 0x1FE3, 0x03A1, 0x03A1, 0x03A5, 0x03A5, - 0x03A5, 0x03A5, 0x03A5, 0x1FEB, 0x03A1, 0x1FED, 0x1FEE, 0x1FEF, - 0x1FF0, 0x1FF1, 0x03A9, 0x03A9, 0x03A9, 0x1FF5, 0x03A9, 0x03A9, - 0x039F, 0x1FF9, 0x03A9, 0x1FFB, 0x03A9, 0x1FFD, 0x1FFE, 0x1FFF, +static ObUnicaseInfoChar plane05_utf8[]={ + {0x0500,0x0500,0x0500}, {0x0501,0x0501,0x0501}, + {0x0502,0x0502,0x0502}, {0x0503,0x0503,0x0503}, + {0x0504,0x0504,0x0504}, {0x0505,0x0505,0x0505}, + {0x0506,0x0506,0x0506}, {0x0507,0x0507,0x0507}, + {0x0508,0x0508,0x0508}, {0x0509,0x0509,0x0509}, + {0x050A,0x050A,0x050A}, {0x050B,0x050B,0x050B}, + {0x050C,0x050C,0x050C}, {0x050D,0x050D,0x050D}, + {0x050E,0x050E,0x050E}, {0x050F,0x050F,0x050F}, + {0x0510,0x0510,0x0510}, {0x0511,0x0511,0x0511}, + {0x0512,0x0512,0x0512}, {0x0513,0x0513,0x0513}, + {0x0514,0x0514,0x0514}, {0x0515,0x0515,0x0515}, + {0x0516,0x0516,0x0516}, {0x0517,0x0517,0x0517}, + {0x0518,0x0518,0x0518}, {0x0519,0x0519,0x0519}, + {0x051A,0x051A,0x051A}, {0x051B,0x051B,0x051B}, + {0x051C,0x051C,0x051C}, {0x051D,0x051D,0x051D}, + {0x051E,0x051E,0x051E}, {0x051F,0x051F,0x051F}, + {0x0520,0x0520,0x0520}, {0x0521,0x0521,0x0521}, + {0x0522,0x0522,0x0522}, {0x0523,0x0523,0x0523}, + {0x0524,0x0524,0x0524}, {0x0525,0x0525,0x0525}, + {0x0526,0x0526,0x0526}, {0x0527,0x0527,0x0527}, + {0x0528,0x0528,0x0528}, {0x0529,0x0529,0x0529}, + {0x052A,0x052A,0x052A}, {0x052B,0x052B,0x052B}, + {0x052C,0x052C,0x052C}, {0x052D,0x052D,0x052D}, + {0x052E,0x052E,0x052E}, {0x052F,0x052F,0x052F}, + {0x0530,0x0530,0x0530}, {0x0531,0x0561,0x0531}, + {0x0532,0x0562,0x0532}, {0x0533,0x0563,0x0533}, + {0x0534,0x0564,0x0534}, {0x0535,0x0565,0x0535}, + {0x0536,0x0566,0x0536}, {0x0537,0x0567,0x0537}, + {0x0538,0x0568,0x0538}, {0x0539,0x0569,0x0539}, + {0x053A,0x056A,0x053A}, {0x053B,0x056B,0x053B}, + {0x053C,0x056C,0x053C}, {0x053D,0x056D,0x053D}, + {0x053E,0x056E,0x053E}, {0x053F,0x056F,0x053F}, + {0x0540,0x0570,0x0540}, {0x0541,0x0571,0x0541}, + {0x0542,0x0572,0x0542}, {0x0543,0x0573,0x0543}, + {0x0544,0x0574,0x0544}, {0x0545,0x0575,0x0545}, + {0x0546,0x0576,0x0546}, {0x0547,0x0577,0x0547}, + {0x0548,0x0578,0x0548}, {0x0549,0x0579,0x0549}, + {0x054A,0x057A,0x054A}, {0x054B,0x057B,0x054B}, + {0x054C,0x057C,0x054C}, {0x054D,0x057D,0x054D}, + {0x054E,0x057E,0x054E}, {0x054F,0x057F,0x054F}, + {0x0550,0x0580,0x0550}, {0x0551,0x0581,0x0551}, + {0x0552,0x0582,0x0552}, {0x0553,0x0583,0x0553}, + {0x0554,0x0584,0x0554}, {0x0555,0x0585,0x0555}, + {0x0556,0x0586,0x0556}, {0x0557,0x0557,0x0557}, + {0x0558,0x0558,0x0558}, {0x0559,0x0559,0x0559}, + {0x055A,0x055A,0x055A}, {0x055B,0x055B,0x055B}, + {0x055C,0x055C,0x055C}, {0x055D,0x055D,0x055D}, + {0x055E,0x055E,0x055E}, {0x055F,0x055F,0x055F}, + {0x0560,0x0560,0x0560}, {0x0531,0x0561,0x0531}, + {0x0532,0x0562,0x0532}, {0x0533,0x0563,0x0533}, + {0x0534,0x0564,0x0534}, {0x0535,0x0565,0x0535}, + {0x0536,0x0566,0x0536}, {0x0537,0x0567,0x0537}, + {0x0538,0x0568,0x0538}, {0x0539,0x0569,0x0539}, + {0x053A,0x056A,0x053A}, {0x053B,0x056B,0x053B}, + {0x053C,0x056C,0x053C}, {0x053D,0x056D,0x053D}, + {0x053E,0x056E,0x053E}, {0x053F,0x056F,0x053F}, + {0x0540,0x0570,0x0540}, {0x0541,0x0571,0x0541}, + {0x0542,0x0572,0x0542}, {0x0543,0x0573,0x0543}, + {0x0544,0x0574,0x0544}, {0x0545,0x0575,0x0545}, + {0x0546,0x0576,0x0546}, {0x0547,0x0577,0x0547}, + {0x0548,0x0578,0x0548}, {0x0549,0x0579,0x0549}, + {0x054A,0x057A,0x054A}, {0x054B,0x057B,0x054B}, + {0x054C,0x057C,0x054C}, {0x054D,0x057D,0x054D}, + {0x054E,0x057E,0x054E}, {0x054F,0x057F,0x054F}, + {0x0550,0x0580,0x0550}, {0x0551,0x0581,0x0551}, + {0x0552,0x0582,0x0552}, {0x0553,0x0583,0x0553}, + {0x0554,0x0584,0x0554}, {0x0555,0x0585,0x0555}, + {0x0556,0x0586,0x0556}, {0x0587,0x0587,0x0587}, + {0x0588,0x0588,0x0588}, {0x0589,0x0589,0x0589}, + {0x058A,0x058A,0x058A}, {0x058B,0x058B,0x058B}, + {0x058C,0x058C,0x058C}, {0x058D,0x058D,0x058D}, + {0x058E,0x058E,0x058E}, {0x058F,0x058F,0x058F}, + {0x0590,0x0590,0x0590}, {0x0591,0x0591,0x0591}, + {0x0592,0x0592,0x0592}, {0x0593,0x0593,0x0593}, + {0x0594,0x0594,0x0594}, {0x0595,0x0595,0x0595}, + {0x0596,0x0596,0x0596}, {0x0597,0x0597,0x0597}, + {0x0598,0x0598,0x0598}, {0x0599,0x0599,0x0599}, + {0x059A,0x059A,0x059A}, {0x059B,0x059B,0x059B}, + {0x059C,0x059C,0x059C}, {0x059D,0x059D,0x059D}, + {0x059E,0x059E,0x059E}, {0x059F,0x059F,0x059F}, + {0x05A0,0x05A0,0x05A0}, {0x05A1,0x05A1,0x05A1}, + {0x05A2,0x05A2,0x05A2}, {0x05A3,0x05A3,0x05A3}, + {0x05A4,0x05A4,0x05A4}, {0x05A5,0x05A5,0x05A5}, + {0x05A6,0x05A6,0x05A6}, {0x05A7,0x05A7,0x05A7}, + {0x05A8,0x05A8,0x05A8}, {0x05A9,0x05A9,0x05A9}, + {0x05AA,0x05AA,0x05AA}, {0x05AB,0x05AB,0x05AB}, + {0x05AC,0x05AC,0x05AC}, {0x05AD,0x05AD,0x05AD}, + {0x05AE,0x05AE,0x05AE}, {0x05AF,0x05AF,0x05AF}, + {0x05B0,0x05B0,0x05B0}, {0x05B1,0x05B1,0x05B1}, + {0x05B2,0x05B2,0x05B2}, {0x05B3,0x05B3,0x05B3}, + {0x05B4,0x05B4,0x05B4}, {0x05B5,0x05B5,0x05B5}, + {0x05B6,0x05B6,0x05B6}, {0x05B7,0x05B7,0x05B7}, + {0x05B8,0x05B8,0x05B8}, {0x05B9,0x05B9,0x05B9}, + {0x05BA,0x05BA,0x05BA}, {0x05BB,0x05BB,0x05BB}, + {0x05BC,0x05BC,0x05BC}, {0x05BD,0x05BD,0x05BD}, + {0x05BE,0x05BE,0x05BE}, {0x05BF,0x05BF,0x05BF}, + {0x05C0,0x05C0,0x05C0}, {0x05C1,0x05C1,0x05C1}, + {0x05C2,0x05C2,0x05C2}, {0x05C3,0x05C3,0x05C3}, + {0x05C4,0x05C4,0x05C4}, {0x05C5,0x05C5,0x05C5}, + {0x05C6,0x05C6,0x05C6}, {0x05C7,0x05C7,0x05C7}, + {0x05C8,0x05C8,0x05C8}, {0x05C9,0x05C9,0x05C9}, + {0x05CA,0x05CA,0x05CA}, {0x05CB,0x05CB,0x05CB}, + {0x05CC,0x05CC,0x05CC}, {0x05CD,0x05CD,0x05CD}, + {0x05CE,0x05CE,0x05CE}, {0x05CF,0x05CF,0x05CF}, + {0x05D0,0x05D0,0x05D0}, {0x05D1,0x05D1,0x05D1}, + {0x05D2,0x05D2,0x05D2}, {0x05D3,0x05D3,0x05D3}, + {0x05D4,0x05D4,0x05D4}, {0x05D5,0x05D5,0x05D5}, + {0x05D6,0x05D6,0x05D6}, {0x05D7,0x05D7,0x05D7}, + {0x05D8,0x05D8,0x05D8}, {0x05D9,0x05D9,0x05D9}, + {0x05DA,0x05DA,0x05DA}, {0x05DB,0x05DB,0x05DB}, + {0x05DC,0x05DC,0x05DC}, {0x05DD,0x05DD,0x05DD}, + {0x05DE,0x05DE,0x05DE}, {0x05DF,0x05DF,0x05DF}, + {0x05E0,0x05E0,0x05E0}, {0x05E1,0x05E1,0x05E1}, + {0x05E2,0x05E2,0x05E2}, {0x05E3,0x05E3,0x05E3}, + {0x05E4,0x05E4,0x05E4}, {0x05E5,0x05E5,0x05E5}, + {0x05E6,0x05E6,0x05E6}, {0x05E7,0x05E7,0x05E7}, + {0x05E8,0x05E8,0x05E8}, {0x05E9,0x05E9,0x05E9}, + {0x05EA,0x05EA,0x05EA}, {0x05EB,0x05EB,0x05EB}, + {0x05EC,0x05EC,0x05EC}, {0x05ED,0x05ED,0x05ED}, + {0x05EE,0x05EE,0x05EE}, {0x05EF,0x05EF,0x05EF}, + {0x05F0,0x05F0,0x05F0}, {0x05F1,0x05F1,0x05F1}, + {0x05F2,0x05F2,0x05F2}, {0x05F3,0x05F3,0x05F3}, + {0x05F4,0x05F4,0x05F4}, {0x05F5,0x05F5,0x05F5}, + {0x05F6,0x05F6,0x05F6}, {0x05F7,0x05F7,0x05F7}, + {0x05F8,0x05F8,0x05F8}, {0x05F9,0x05F9,0x05F9}, + {0x05FA,0x05FA,0x05FA}, {0x05FB,0x05FB,0x05FB}, + {0x05FC,0x05FC,0x05FC}, {0x05FD,0x05FD,0x05FD}, + {0x05FE,0x05FE,0x05FE}, {0x05FF,0x05FF,0x05FF} }; -static uint32_t lower21[]={ - 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107, - 0x2108, 0x2109, 0x210A, 0x210B, 0x210C, 0x210D, 0x210E, 0x210F, - 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117, - 0x2118, 0x2119, 0x211A, 0x211B, 0x211C, 0x211D, 0x211E, 0x211F, - 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x03C9, 0x2127, - 0x2128, 0x2129, 0x006B, 0x00E5, 0x212C, 0x212D, 0x212E, 0x212F, - 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137, - 0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, 0x213F, - 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147, - 0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F, - 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, - 0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F, - 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, - 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, - 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, - 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, - 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187, - 0x2188, 0x2189, 0x218A, 0x218B, 0x218C, 0x218D, 0x218E, 0x218F, - 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197, - 0x2198, 0x2199, 0x219A, 0x219B, 0x219C, 0x219D, 0x219E, 0x219F, - 0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, 0x21A5, 0x21A6, 0x21A7, - 0x21A8, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21AE, 0x21AF, - 0x21B0, 0x21B1, 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, 0x21B7, - 0x21B8, 0x21B9, 0x21BA, 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF, - 0x21C0, 0x21C1, 0x21C2, 0x21C3, 0x21C4, 0x21C5, 0x21C6, 0x21C7, - 0x21C8, 0x21C9, 0x21CA, 0x21CB, 0x21CC, 0x21CD, 0x21CE, 0x21CF, - 0x21D0, 0x21D1, 0x21D2, 0x21D3, 0x21D4, 0x21D5, 0x21D6, 0x21D7, - 0x21D8, 0x21D9, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21DE, 0x21DF, - 0x21E0, 0x21E1, 0x21E2, 0x21E3, 0x21E4, 0x21E5, 0x21E6, 0x21E7, - 0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, 0x21ED, 0x21EE, 0x21EF, - 0x21F0, 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, 0x21F6, 0x21F7, - 0x21F8, 0x21F9, 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, 0x21FF, +static ObUnicaseInfoChar plane1E_utf8[]={ + {0x1E00,0x1E01,0x0041}, {0x1E00,0x1E01,0x0041}, + {0x1E02,0x1E03,0x0042}, {0x1E02,0x1E03,0x0042}, + {0x1E04,0x1E05,0x0042}, {0x1E04,0x1E05,0x0042}, + {0x1E06,0x1E07,0x0042}, {0x1E06,0x1E07,0x0042}, + {0x1E08,0x1E09,0x0043}, {0x1E08,0x1E09,0x0043}, + {0x1E0A,0x1E0B,0x0044}, {0x1E0A,0x1E0B,0x0044}, + {0x1E0C,0x1E0D,0x0044}, {0x1E0C,0x1E0D,0x0044}, + {0x1E0E,0x1E0F,0x0044}, {0x1E0E,0x1E0F,0x0044}, + {0x1E10,0x1E11,0x0044}, {0x1E10,0x1E11,0x0044}, + {0x1E12,0x1E13,0x0044}, {0x1E12,0x1E13,0x0044}, + {0x1E14,0x1E15,0x0045}, {0x1E14,0x1E15,0x0045}, + {0x1E16,0x1E17,0x0045}, {0x1E16,0x1E17,0x0045}, + {0x1E18,0x1E19,0x0045}, {0x1E18,0x1E19,0x0045}, + {0x1E1A,0x1E1B,0x0045}, {0x1E1A,0x1E1B,0x0045}, + {0x1E1C,0x1E1D,0x0045}, {0x1E1C,0x1E1D,0x0045}, + {0x1E1E,0x1E1F,0x0046}, {0x1E1E,0x1E1F,0x0046}, + {0x1E20,0x1E21,0x0047}, {0x1E20,0x1E21,0x0047}, + {0x1E22,0x1E23,0x0048}, {0x1E22,0x1E23,0x0048}, + {0x1E24,0x1E25,0x0048}, {0x1E24,0x1E25,0x0048}, + {0x1E26,0x1E27,0x0048}, {0x1E26,0x1E27,0x0048}, + {0x1E28,0x1E29,0x0048}, {0x1E28,0x1E29,0x0048}, + {0x1E2A,0x1E2B,0x0048}, {0x1E2A,0x1E2B,0x0048}, + {0x1E2C,0x1E2D,0x0049}, {0x1E2C,0x1E2D,0x0049}, + {0x1E2E,0x1E2F,0x0049}, {0x1E2E,0x1E2F,0x0049}, + {0x1E30,0x1E31,0x004B}, {0x1E30,0x1E31,0x004B}, + {0x1E32,0x1E33,0x004B}, {0x1E32,0x1E33,0x004B}, + {0x1E34,0x1E35,0x004B}, {0x1E34,0x1E35,0x004B}, + {0x1E36,0x1E37,0x004C}, {0x1E36,0x1E37,0x004C}, + {0x1E38,0x1E39,0x004C}, {0x1E38,0x1E39,0x004C}, + {0x1E3A,0x1E3B,0x004C}, {0x1E3A,0x1E3B,0x004C}, + {0x1E3C,0x1E3D,0x004C}, {0x1E3C,0x1E3D,0x004C}, + {0x1E3E,0x1E3F,0x004D}, {0x1E3E,0x1E3F,0x004D}, + {0x1E40,0x1E41,0x004D}, {0x1E40,0x1E41,0x004D}, + {0x1E42,0x1E43,0x004D}, {0x1E42,0x1E43,0x004D}, + {0x1E44,0x1E45,0x004E}, {0x1E44,0x1E45,0x004E}, + {0x1E46,0x1E47,0x004E}, {0x1E46,0x1E47,0x004E}, + {0x1E48,0x1E49,0x004E}, {0x1E48,0x1E49,0x004E}, + {0x1E4A,0x1E4B,0x004E}, {0x1E4A,0x1E4B,0x004E}, + {0x1E4C,0x1E4D,0x004F}, {0x1E4C,0x1E4D,0x004F}, + {0x1E4E,0x1E4F,0x004F}, {0x1E4E,0x1E4F,0x004F}, + {0x1E50,0x1E51,0x004F}, {0x1E50,0x1E51,0x004F}, + {0x1E52,0x1E53,0x004F}, {0x1E52,0x1E53,0x004F}, + {0x1E54,0x1E55,0x0050}, {0x1E54,0x1E55,0x0050}, + {0x1E56,0x1E57,0x0050}, {0x1E56,0x1E57,0x0050}, + {0x1E58,0x1E59,0x0052}, {0x1E58,0x1E59,0x0052}, + {0x1E5A,0x1E5B,0x0052}, {0x1E5A,0x1E5B,0x0052}, + {0x1E5C,0x1E5D,0x0052}, {0x1E5C,0x1E5D,0x0052}, + {0x1E5E,0x1E5F,0x0052}, {0x1E5E,0x1E5F,0x0052}, + {0x1E60,0x1E61,0x0053}, {0x1E60,0x1E61,0x0053}, + {0x1E62,0x1E63,0x0053}, {0x1E62,0x1E63,0x0053}, + {0x1E64,0x1E65,0x0053}, {0x1E64,0x1E65,0x0053}, + {0x1E66,0x1E67,0x0053}, {0x1E66,0x1E67,0x0053}, + {0x1E68,0x1E69,0x0053}, {0x1E68,0x1E69,0x0053}, + {0x1E6A,0x1E6B,0x0054}, {0x1E6A,0x1E6B,0x0054}, + {0x1E6C,0x1E6D,0x0054}, {0x1E6C,0x1E6D,0x0054}, + {0x1E6E,0x1E6F,0x0054}, {0x1E6E,0x1E6F,0x0054}, + {0x1E70,0x1E71,0x0054}, {0x1E70,0x1E71,0x0054}, + {0x1E72,0x1E73,0x0055}, {0x1E72,0x1E73,0x0055}, + {0x1E74,0x1E75,0x0055}, {0x1E74,0x1E75,0x0055}, + {0x1E76,0x1E77,0x0055}, {0x1E76,0x1E77,0x0055}, + {0x1E78,0x1E79,0x0055}, {0x1E78,0x1E79,0x0055}, + {0x1E7A,0x1E7B,0x0055}, {0x1E7A,0x1E7B,0x0055}, + {0x1E7C,0x1E7D,0x0056}, {0x1E7C,0x1E7D,0x0056}, + {0x1E7E,0x1E7F,0x0056}, {0x1E7E,0x1E7F,0x0056}, + {0x1E80,0x1E81,0x0057}, {0x1E80,0x1E81,0x0057}, + {0x1E82,0x1E83,0x0057}, {0x1E82,0x1E83,0x0057}, + {0x1E84,0x1E85,0x0057}, {0x1E84,0x1E85,0x0057}, + {0x1E86,0x1E87,0x0057}, {0x1E86,0x1E87,0x0057}, + {0x1E88,0x1E89,0x0057}, {0x1E88,0x1E89,0x0057}, + {0x1E8A,0x1E8B,0x0058}, {0x1E8A,0x1E8B,0x0058}, + {0x1E8C,0x1E8D,0x0058}, {0x1E8C,0x1E8D,0x0058}, + {0x1E8E,0x1E8F,0x0059}, {0x1E8E,0x1E8F,0x0059}, + {0x1E90,0x1E91,0x005A}, {0x1E90,0x1E91,0x005A}, + {0x1E92,0x1E93,0x005A}, {0x1E92,0x1E93,0x005A}, + {0x1E94,0x1E95,0x005A}, {0x1E94,0x1E95,0x005A}, + {0x1E96,0x1E96,0x0048}, {0x1E97,0x1E97,0x0054}, + {0x1E98,0x1E98,0x0057}, {0x1E99,0x1E99,0x0059}, + {0x1E9A,0x1E9A,0x1E9A}, {0x1E60,0x1E9B,0x0053}, + {0x1E9C,0x1E9C,0x1E9C}, {0x1E9D,0x1E9D,0x1E9D}, + {0x1E9E,0x1E9E,0x1E9E}, {0x1E9F,0x1E9F,0x1E9F}, + {0x1EA0,0x1EA1,0x0041}, {0x1EA0,0x1EA1,0x0041}, + {0x1EA2,0x1EA3,0x0041}, {0x1EA2,0x1EA3,0x0041}, + {0x1EA4,0x1EA5,0x0041}, {0x1EA4,0x1EA5,0x0041}, + {0x1EA6,0x1EA7,0x0041}, {0x1EA6,0x1EA7,0x0041}, + {0x1EA8,0x1EA9,0x0041}, {0x1EA8,0x1EA9,0x0041}, + {0x1EAA,0x1EAB,0x0041}, {0x1EAA,0x1EAB,0x0041}, + {0x1EAC,0x1EAD,0x0041}, {0x1EAC,0x1EAD,0x0041}, + {0x1EAE,0x1EAF,0x0041}, {0x1EAE,0x1EAF,0x0041}, + {0x1EB0,0x1EB1,0x0041}, {0x1EB0,0x1EB1,0x0041}, + {0x1EB2,0x1EB3,0x0041}, {0x1EB2,0x1EB3,0x0041}, + {0x1EB4,0x1EB5,0x0041}, {0x1EB4,0x1EB5,0x0041}, + {0x1EB6,0x1EB7,0x0041}, {0x1EB6,0x1EB7,0x0041}, + {0x1EB8,0x1EB9,0x0045}, {0x1EB8,0x1EB9,0x0045}, + {0x1EBA,0x1EBB,0x0045}, {0x1EBA,0x1EBB,0x0045}, + {0x1EBC,0x1EBD,0x0045}, {0x1EBC,0x1EBD,0x0045}, + {0x1EBE,0x1EBF,0x0045}, {0x1EBE,0x1EBF,0x0045}, + {0x1EC0,0x1EC1,0x0045}, {0x1EC0,0x1EC1,0x0045}, + {0x1EC2,0x1EC3,0x0045}, {0x1EC2,0x1EC3,0x0045}, + {0x1EC4,0x1EC5,0x0045}, {0x1EC4,0x1EC5,0x0045}, + {0x1EC6,0x1EC7,0x0045}, {0x1EC6,0x1EC7,0x0045}, + {0x1EC8,0x1EC9,0x0049}, {0x1EC8,0x1EC9,0x0049}, + {0x1ECA,0x1ECB,0x0049}, {0x1ECA,0x1ECB,0x0049}, + {0x1ECC,0x1ECD,0x004F}, {0x1ECC,0x1ECD,0x004F}, + {0x1ECE,0x1ECF,0x004F}, {0x1ECE,0x1ECF,0x004F}, + {0x1ED0,0x1ED1,0x004F}, {0x1ED0,0x1ED1,0x004F}, + {0x1ED2,0x1ED3,0x004F}, {0x1ED2,0x1ED3,0x004F}, + {0x1ED4,0x1ED5,0x004F}, {0x1ED4,0x1ED5,0x004F}, + {0x1ED6,0x1ED7,0x004F}, {0x1ED6,0x1ED7,0x004F}, + {0x1ED8,0x1ED9,0x004F}, {0x1ED8,0x1ED9,0x004F}, + {0x1EDA,0x1EDB,0x004F}, {0x1EDA,0x1EDB,0x004F}, + {0x1EDC,0x1EDD,0x004F}, {0x1EDC,0x1EDD,0x004F}, + {0x1EDE,0x1EDF,0x004F}, {0x1EDE,0x1EDF,0x004F}, + {0x1EE0,0x1EE1,0x004F}, {0x1EE0,0x1EE1,0x004F}, + {0x1EE2,0x1EE3,0x004F}, {0x1EE2,0x1EE3,0x004F}, + {0x1EE4,0x1EE5,0x0055}, {0x1EE4,0x1EE5,0x0055}, + {0x1EE6,0x1EE7,0x0055}, {0x1EE6,0x1EE7,0x0055}, + {0x1EE8,0x1EE9,0x0055}, {0x1EE8,0x1EE9,0x0055}, + {0x1EEA,0x1EEB,0x0055}, {0x1EEA,0x1EEB,0x0055}, + {0x1EEC,0x1EED,0x0055}, {0x1EEC,0x1EED,0x0055}, + {0x1EEE,0x1EEF,0x0055}, {0x1EEE,0x1EEF,0x0055}, + {0x1EF0,0x1EF1,0x0055}, {0x1EF0,0x1EF1,0x0055}, + {0x1EF2,0x1EF3,0x0059}, {0x1EF2,0x1EF3,0x0059}, + {0x1EF4,0x1EF5,0x0059}, {0x1EF4,0x1EF5,0x0059}, + {0x1EF6,0x1EF7,0x0059}, {0x1EF6,0x1EF7,0x0059}, + {0x1EF8,0x1EF9,0x0059}, {0x1EF8,0x1EF9,0x0059}, + {0x1EFA,0x1EFA,0x1EFA}, {0x1EFB,0x1EFB,0x1EFB}, + {0x1EFC,0x1EFC,0x1EFC}, {0x1EFD,0x1EFD,0x1EFD}, + {0x1EFE,0x1EFE,0x1EFE}, {0x1EFF,0x1EFF,0x1EFF} }; -static uint32_t upper21[]={ - 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107, - 0x2108, 0x2109, 0x210A, 0x210B, 0x210C, 0x210D, 0x210E, 0x210F, - 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117, - 0x2118, 0x2119, 0x211A, 0x211B, 0x211C, 0x211D, 0x211E, 0x211F, - 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x2126, 0x2127, - 0x2128, 0x2129, 0x212A, 0x212B, 0x212C, 0x212D, 0x212E, 0x212F, - 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137, - 0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, 0x213F, - 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147, - 0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F, - 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, - 0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F, - 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, - 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, - 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, - 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, - 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187, - 0x2188, 0x2189, 0x218A, 0x218B, 0x218C, 0x218D, 0x218E, 0x218F, - 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197, - 0x2198, 0x2199, 0x219A, 0x219B, 0x219C, 0x219D, 0x219E, 0x219F, - 0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, 0x21A5, 0x21A6, 0x21A7, - 0x21A8, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21AE, 0x21AF, - 0x21B0, 0x21B1, 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, 0x21B7, - 0x21B8, 0x21B9, 0x21BA, 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF, - 0x21C0, 0x21C1, 0x21C2, 0x21C3, 0x21C4, 0x21C5, 0x21C6, 0x21C7, - 0x21C8, 0x21C9, 0x21CA, 0x21CB, 0x21CC, 0x21CD, 0x21CE, 0x21CF, - 0x21D0, 0x21D1, 0x21D2, 0x21D3, 0x21D4, 0x21D5, 0x21D6, 0x21D7, - 0x21D8, 0x21D9, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21DE, 0x21DF, - 0x21E0, 0x21E1, 0x21E2, 0x21E3, 0x21E4, 0x21E5, 0x21E6, 0x21E7, - 0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, 0x21ED, 0x21EE, 0x21EF, - 0x21F0, 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, 0x21F6, 0x21F7, - 0x21F8, 0x21F9, 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, 0x21FF, +static ObUnicaseInfoChar plane1F_utf8[]={ + {0x1F08,0x1F00,0x0391}, {0x1F09,0x1F01,0x0391}, + {0x1F0A,0x1F02,0x0391}, {0x1F0B,0x1F03,0x0391}, + {0x1F0C,0x1F04,0x0391}, {0x1F0D,0x1F05,0x0391}, + {0x1F0E,0x1F06,0x0391}, {0x1F0F,0x1F07,0x0391}, + {0x1F08,0x1F00,0x0391}, {0x1F09,0x1F01,0x0391}, + {0x1F0A,0x1F02,0x0391}, {0x1F0B,0x1F03,0x0391}, + {0x1F0C,0x1F04,0x0391}, {0x1F0D,0x1F05,0x0391}, + {0x1F0E,0x1F06,0x0391}, {0x1F0F,0x1F07,0x0391}, + {0x1F18,0x1F10,0x0395}, {0x1F19,0x1F11,0x0395}, + {0x1F1A,0x1F12,0x0395}, {0x1F1B,0x1F13,0x0395}, + {0x1F1C,0x1F14,0x0395}, {0x1F1D,0x1F15,0x0395}, + {0x1F16,0x1F16,0x1F16}, {0x1F17,0x1F17,0x1F17}, + {0x1F18,0x1F10,0x0395}, {0x1F19,0x1F11,0x0395}, + {0x1F1A,0x1F12,0x0395}, {0x1F1B,0x1F13,0x0395}, + {0x1F1C,0x1F14,0x0395}, {0x1F1D,0x1F15,0x0395}, + {0x1F1E,0x1F1E,0x1F1E}, {0x1F1F,0x1F1F,0x1F1F}, + {0x1F28,0x1F20,0x0397}, {0x1F29,0x1F21,0x0397}, + {0x1F2A,0x1F22,0x0397}, {0x1F2B,0x1F23,0x0397}, + {0x1F2C,0x1F24,0x0397}, {0x1F2D,0x1F25,0x0397}, + {0x1F2E,0x1F26,0x0397}, {0x1F2F,0x1F27,0x0397}, + {0x1F28,0x1F20,0x0397}, {0x1F29,0x1F21,0x0397}, + {0x1F2A,0x1F22,0x0397}, {0x1F2B,0x1F23,0x0397}, + {0x1F2C,0x1F24,0x0397}, {0x1F2D,0x1F25,0x0397}, + {0x1F2E,0x1F26,0x0397}, {0x1F2F,0x1F27,0x0397}, + {0x1F38,0x1F30,0x0399}, {0x1F39,0x1F31,0x0399}, + {0x1F3A,0x1F32,0x0399}, {0x1F3B,0x1F33,0x0399}, + {0x1F3C,0x1F34,0x0399}, {0x1F3D,0x1F35,0x0399}, + {0x1F3E,0x1F36,0x0399}, {0x1F3F,0x1F37,0x0399}, + {0x1F38,0x1F30,0x0399}, {0x1F39,0x1F31,0x0399}, + {0x1F3A,0x1F32,0x0399}, {0x1F3B,0x1F33,0x0399}, + {0x1F3C,0x1F34,0x0399}, {0x1F3D,0x1F35,0x0399}, + {0x1F3E,0x1F36,0x0399}, {0x1F3F,0x1F37,0x0399}, + {0x1F48,0x1F40,0x039F}, {0x1F49,0x1F41,0x039F}, + {0x1F4A,0x1F42,0x039F}, {0x1F4B,0x1F43,0x039F}, + {0x1F4C,0x1F44,0x039F}, {0x1F4D,0x1F45,0x039F}, + {0x1F46,0x1F46,0x1F46}, {0x1F47,0x1F47,0x1F47}, + {0x1F48,0x1F40,0x039F}, {0x1F49,0x1F41,0x039F}, + {0x1F4A,0x1F42,0x039F}, {0x1F4B,0x1F43,0x039F}, + {0x1F4C,0x1F44,0x039F}, {0x1F4D,0x1F45,0x039F}, + {0x1F4E,0x1F4E,0x1F4E}, {0x1F4F,0x1F4F,0x1F4F}, + {0x1F50,0x1F50,0x03A5}, {0x1F59,0x1F51,0x03A5}, + {0x1F52,0x1F52,0x03A5}, {0x1F5B,0x1F53,0x03A5}, + {0x1F54,0x1F54,0x03A5}, {0x1F5D,0x1F55,0x03A5}, + {0x1F56,0x1F56,0x03A5}, {0x1F5F,0x1F57,0x03A5}, + {0x1F58,0x1F58,0x1F58}, {0x1F59,0x1F51,0x03A5}, + {0x1F5A,0x1F5A,0x1F5A}, {0x1F5B,0x1F53,0x03A5}, + {0x1F5C,0x1F5C,0x1F5C}, {0x1F5D,0x1F55,0x03A5}, + {0x1F5E,0x1F5E,0x1F5E}, {0x1F5F,0x1F57,0x03A5}, + {0x1F68,0x1F60,0x03A9}, {0x1F69,0x1F61,0x03A9}, + {0x1F6A,0x1F62,0x03A9}, {0x1F6B,0x1F63,0x03A9}, + {0x1F6C,0x1F64,0x03A9}, {0x1F6D,0x1F65,0x03A9}, + {0x1F6E,0x1F66,0x03A9}, {0x1F6F,0x1F67,0x03A9}, + {0x1F68,0x1F60,0x03A9}, {0x1F69,0x1F61,0x03A9}, + {0x1F6A,0x1F62,0x03A9}, {0x1F6B,0x1F63,0x03A9}, + {0x1F6C,0x1F64,0x03A9}, {0x1F6D,0x1F65,0x03A9}, + {0x1F6E,0x1F66,0x03A9}, {0x1F6F,0x1F67,0x03A9}, + {0x1FBA,0x1F70,0x0391}, {0x1FBB,0x1F71,0x1FBB}, + {0x1FC8,0x1F72,0x0395}, {0x1FC9,0x1F73,0x1FC9}, + {0x1FCA,0x1F74,0x0397}, {0x1FCB,0x1F75,0x1FCB}, + {0x1FDA,0x1F76,0x0399}, {0x1FDB,0x1F77,0x1FDB}, + {0x1FF8,0x1F78,0x039F}, {0x1FF9,0x1F79,0x1FF9}, + {0x1FEA,0x1F7A,0x03A5}, {0x1FEB,0x1F7B,0x1FEB}, + {0x1FFA,0x1F7C,0x03A9}, {0x1FFB,0x1F7D,0x1FFB}, + {0x1F7E,0x1F7E,0x1F7E}, {0x1F7F,0x1F7F,0x1F7F}, + {0x1F88,0x1F80,0x0391}, {0x1F89,0x1F81,0x0391}, + {0x1F8A,0x1F82,0x0391}, {0x1F8B,0x1F83,0x0391}, + {0x1F8C,0x1F84,0x0391}, {0x1F8D,0x1F85,0x0391}, + {0x1F8E,0x1F86,0x0391}, {0x1F8F,0x1F87,0x0391}, + {0x1F88,0x1F80,0x0391}, {0x1F89,0x1F81,0x0391}, + {0x1F8A,0x1F82,0x0391}, {0x1F8B,0x1F83,0x0391}, + {0x1F8C,0x1F84,0x0391}, {0x1F8D,0x1F85,0x0391}, + {0x1F8E,0x1F86,0x0391}, {0x1F8F,0x1F87,0x0391}, + {0x1F98,0x1F90,0x0397}, {0x1F99,0x1F91,0x0397}, + {0x1F9A,0x1F92,0x0397}, {0x1F9B,0x1F93,0x0397}, + {0x1F9C,0x1F94,0x0397}, {0x1F9D,0x1F95,0x0397}, + {0x1F9E,0x1F96,0x0397}, {0x1F9F,0x1F97,0x0397}, + {0x1F98,0x1F90,0x0397}, {0x1F99,0x1F91,0x0397}, + {0x1F9A,0x1F92,0x0397}, {0x1F9B,0x1F93,0x0397}, + {0x1F9C,0x1F94,0x0397}, {0x1F9D,0x1F95,0x0397}, + {0x1F9E,0x1F96,0x0397}, {0x1F9F,0x1F97,0x0397}, + {0x1FA8,0x1FA0,0x03A9}, {0x1FA9,0x1FA1,0x03A9}, + {0x1FAA,0x1FA2,0x03A9}, {0x1FAB,0x1FA3,0x03A9}, + {0x1FAC,0x1FA4,0x03A9}, {0x1FAD,0x1FA5,0x03A9}, + {0x1FAE,0x1FA6,0x03A9}, {0x1FAF,0x1FA7,0x03A9}, + {0x1FA8,0x1FA0,0x03A9}, {0x1FA9,0x1FA1,0x03A9}, + {0x1FAA,0x1FA2,0x03A9}, {0x1FAB,0x1FA3,0x03A9}, + {0x1FAC,0x1FA4,0x03A9}, {0x1FAD,0x1FA5,0x03A9}, + {0x1FAE,0x1FA6,0x03A9}, {0x1FAF,0x1FA7,0x03A9}, + {0x1FB8,0x1FB0,0x0391}, {0x1FB9,0x1FB1,0x0391}, + {0x1FB2,0x1FB2,0x0391}, {0x1FBC,0x1FB3,0x0391}, + {0x1FB4,0x1FB4,0x0391}, {0x1FB5,0x1FB5,0x1FB5}, + {0x1FB6,0x1FB6,0x0391}, {0x1FB7,0x1FB7,0x0391}, + {0x1FB8,0x1FB0,0x0391}, {0x1FB9,0x1FB1,0x0391}, + {0x1FBA,0x1F70,0x0391}, {0x1FBB,0x1F71,0x1FBB}, + {0x1FBC,0x1FB3,0x0391}, {0x1FBD,0x1FBD,0x1FBD}, + {0x0399,0x1FBE,0x0399}, {0x1FBF,0x1FBF,0x1FBF}, + {0x1FC0,0x1FC0,0x1FC0}, {0x1FC1,0x1FC1,0x1FC1}, + {0x1FC2,0x1FC2,0x0397}, {0x1FCC,0x1FC3,0x0397}, + {0x1FC4,0x1FC4,0x0397}, {0x1FC5,0x1FC5,0x1FC5}, + {0x1FC6,0x1FC6,0x0397}, {0x1FC7,0x1FC7,0x0397}, + {0x1FC8,0x1F72,0x0395}, {0x1FC9,0x1F73,0x1FC9}, + {0x1FCA,0x1F74,0x0397}, {0x1FCB,0x1F75,0x1FCB}, + {0x1FCC,0x1FC3,0x0397}, {0x1FCD,0x1FCD,0x1FCD}, + {0x1FCE,0x1FCE,0x1FCE}, {0x1FCF,0x1FCF,0x1FCF}, + {0x1FD8,0x1FD0,0x0399}, {0x1FD9,0x1FD1,0x0399}, + {0x1FD2,0x1FD2,0x0399}, {0x1FD3,0x1FD3,0x1FD3}, + {0x1FD4,0x1FD4,0x1FD4}, {0x1FD5,0x1FD5,0x1FD5}, + {0x1FD6,0x1FD6,0x0399}, {0x1FD7,0x1FD7,0x0399}, + {0x1FD8,0x1FD0,0x0399}, {0x1FD9,0x1FD1,0x0399}, + {0x1FDA,0x1F76,0x0399}, {0x1FDB,0x1F77,0x1FDB}, + {0x1FDC,0x1FDC,0x1FDC}, {0x1FDD,0x1FDD,0x1FDD}, + {0x1FDE,0x1FDE,0x1FDE}, {0x1FDF,0x1FDF,0x1FDF}, + {0x1FE8,0x1FE0,0x03A5}, {0x1FE9,0x1FE1,0x03A5}, + {0x1FE2,0x1FE2,0x03A5}, {0x1FE3,0x1FE3,0x1FE3}, + {0x1FE4,0x1FE4,0x03A1}, {0x1FEC,0x1FE5,0x03A1}, + {0x1FE6,0x1FE6,0x03A5}, {0x1FE7,0x1FE7,0x03A5}, + {0x1FE8,0x1FE0,0x03A5}, {0x1FE9,0x1FE1,0x03A5}, + {0x1FEA,0x1F7A,0x03A5}, {0x1FEB,0x1F7B,0x1FEB}, + {0x1FEC,0x1FE5,0x03A1}, {0x1FED,0x1FED,0x1FED}, + {0x1FEE,0x1FEE,0x1FEE}, {0x1FEF,0x1FEF,0x1FEF}, + {0x1FF0,0x1FF0,0x1FF0}, {0x1FF1,0x1FF1,0x1FF1}, + {0x1FF2,0x1FF2,0x03A9}, {0x1FFC,0x1FF3,0x03A9}, + {0x1FF4,0x1FF4,0x03A9}, {0x1FF5,0x1FF5,0x1FF5}, + {0x1FF6,0x1FF6,0x03A9}, {0x1FF7,0x1FF7,0x03A9}, + {0x1FF8,0x1F78,0x039F}, {0x1FF9,0x1F79,0x1FF9}, + {0x1FFA,0x1F7C,0x03A9}, {0x1FFB,0x1F7D,0x1FFB}, + {0x1FFC,0x1FF3,0x03A9}, {0x1FFD,0x1FFD,0x1FFD}, + {0x1FFE,0x1FFE,0x1FFE}, {0x1FFF,0x1FFF,0x1FFF} }; -static uint32_t sort21[]={ - 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107, - 0x2108, 0x2109, 0x210A, 0x210B, 0x210C, 0x210D, 0x210E, 0x210F, - 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117, - 0x2118, 0x2119, 0x211A, 0x211B, 0x211C, 0x211D, 0x211E, 0x211F, - 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x2126, 0x2127, - 0x2128, 0x2129, 0x212A, 0x212B, 0x212C, 0x212D, 0x212E, 0x212F, - 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137, - 0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, 0x213F, - 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147, - 0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F, - 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, - 0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F, - 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, - 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, - 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, - 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, - 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187, - 0x2188, 0x2189, 0x218A, 0x218B, 0x218C, 0x218D, 0x218E, 0x218F, - 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197, - 0x2198, 0x2199, 0x219A, 0x219B, 0x219C, 0x219D, 0x219E, 0x219F, - 0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, 0x21A5, 0x21A6, 0x21A7, - 0x21A8, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21AE, 0x21AF, - 0x21B0, 0x21B1, 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, 0x21B7, - 0x21B8, 0x21B9, 0x21BA, 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF, - 0x21C0, 0x21C1, 0x21C2, 0x21C3, 0x21C4, 0x21C5, 0x21C6, 0x21C7, - 0x21C8, 0x21C9, 0x21CA, 0x21CB, 0x21CC, 0x21CD, 0x21CE, 0x21CF, - 0x21D0, 0x21D1, 0x21D2, 0x21D3, 0x21D4, 0x21D5, 0x21D6, 0x21D7, - 0x21D8, 0x21D9, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21DE, 0x21DF, - 0x21E0, 0x21E1, 0x21E2, 0x21E3, 0x21E4, 0x21E5, 0x21E6, 0x21E7, - 0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, 0x21ED, 0x21EE, 0x21EF, - 0x21F0, 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, 0x21F6, 0x21F7, - 0x21F8, 0x21F9, 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, 0x21FF, +static ObUnicaseInfoChar plane21_utf8[]={ + {0x2100,0x2100,0x2100}, {0x2101,0x2101,0x2101}, + {0x2102,0x2102,0x2102}, {0x2103,0x2103,0x2103}, + {0x2104,0x2104,0x2104}, {0x2105,0x2105,0x2105}, + {0x2106,0x2106,0x2106}, {0x2107,0x2107,0x2107}, + {0x2108,0x2108,0x2108}, {0x2109,0x2109,0x2109}, + {0x210A,0x210A,0x210A}, {0x210B,0x210B,0x210B}, + {0x210C,0x210C,0x210C}, {0x210D,0x210D,0x210D}, + {0x210E,0x210E,0x210E}, {0x210F,0x210F,0x210F}, + {0x2110,0x2110,0x2110}, {0x2111,0x2111,0x2111}, + {0x2112,0x2112,0x2112}, {0x2113,0x2113,0x2113}, + {0x2114,0x2114,0x2114}, {0x2115,0x2115,0x2115}, + {0x2116,0x2116,0x2116}, {0x2117,0x2117,0x2117}, + {0x2118,0x2118,0x2118}, {0x2119,0x2119,0x2119}, + {0x211A,0x211A,0x211A}, {0x211B,0x211B,0x211B}, + {0x211C,0x211C,0x211C}, {0x211D,0x211D,0x211D}, + {0x211E,0x211E,0x211E}, {0x211F,0x211F,0x211F}, + {0x2120,0x2120,0x2120}, {0x2121,0x2121,0x2121}, + {0x2122,0x2122,0x2122}, {0x2123,0x2123,0x2123}, + {0x2124,0x2124,0x2124}, {0x2125,0x2125,0x2125}, + {0x2126,0x03C9,0x2126}, {0x2127,0x2127,0x2127}, + {0x2128,0x2128,0x2128}, {0x2129,0x2129,0x2129}, + {0x212A,0x006B,0x212A}, {0x212B,0x00E5,0x212B}, + {0x212C,0x212C,0x212C}, {0x212D,0x212D,0x212D}, + {0x212E,0x212E,0x212E}, {0x212F,0x212F,0x212F}, + {0x2130,0x2130,0x2130}, {0x2131,0x2131,0x2131}, + {0x2132,0x2132,0x2132}, {0x2133,0x2133,0x2133}, + {0x2134,0x2134,0x2134}, {0x2135,0x2135,0x2135}, + {0x2136,0x2136,0x2136}, {0x2137,0x2137,0x2137}, + {0x2138,0x2138,0x2138}, {0x2139,0x2139,0x2139}, + {0x213A,0x213A,0x213A}, {0x213B,0x213B,0x213B}, + {0x213C,0x213C,0x213C}, {0x213D,0x213D,0x213D}, + {0x213E,0x213E,0x213E}, {0x213F,0x213F,0x213F}, + {0x2140,0x2140,0x2140}, {0x2141,0x2141,0x2141}, + {0x2142,0x2142,0x2142}, {0x2143,0x2143,0x2143}, + {0x2144,0x2144,0x2144}, {0x2145,0x2145,0x2145}, + {0x2146,0x2146,0x2146}, {0x2147,0x2147,0x2147}, + {0x2148,0x2148,0x2148}, {0x2149,0x2149,0x2149}, + {0x214A,0x214A,0x214A}, {0x214B,0x214B,0x214B}, + {0x214C,0x214C,0x214C}, {0x214D,0x214D,0x214D}, + {0x214E,0x214E,0x214E}, {0x214F,0x214F,0x214F}, + {0x2150,0x2150,0x2150}, {0x2151,0x2151,0x2151}, + {0x2152,0x2152,0x2152}, {0x2153,0x2153,0x2153}, + {0x2154,0x2154,0x2154}, {0x2155,0x2155,0x2155}, + {0x2156,0x2156,0x2156}, {0x2157,0x2157,0x2157}, + {0x2158,0x2158,0x2158}, {0x2159,0x2159,0x2159}, + {0x215A,0x215A,0x215A}, {0x215B,0x215B,0x215B}, + {0x215C,0x215C,0x215C}, {0x215D,0x215D,0x215D}, + {0x215E,0x215E,0x215E}, {0x215F,0x215F,0x215F}, + {0x2160,0x2170,0x2160}, {0x2161,0x2171,0x2161}, + {0x2162,0x2172,0x2162}, {0x2163,0x2173,0x2163}, + {0x2164,0x2174,0x2164}, {0x2165,0x2175,0x2165}, + {0x2166,0x2176,0x2166}, {0x2167,0x2177,0x2167}, + {0x2168,0x2178,0x2168}, {0x2169,0x2179,0x2169}, + {0x216A,0x217A,0x216A}, {0x216B,0x217B,0x216B}, + {0x216C,0x217C,0x216C}, {0x216D,0x217D,0x216D}, + {0x216E,0x217E,0x216E}, {0x216F,0x217F,0x216F}, + {0x2160,0x2170,0x2160}, {0x2161,0x2171,0x2161}, + {0x2162,0x2172,0x2162}, {0x2163,0x2173,0x2163}, + {0x2164,0x2174,0x2164}, {0x2165,0x2175,0x2165}, + {0x2166,0x2176,0x2166}, {0x2167,0x2177,0x2167}, + {0x2168,0x2178,0x2168}, {0x2169,0x2179,0x2169}, + {0x216A,0x217A,0x216A}, {0x216B,0x217B,0x216B}, + {0x216C,0x217C,0x216C}, {0x216D,0x217D,0x216D}, + {0x216E,0x217E,0x216E}, {0x216F,0x217F,0x216F}, + {0x2180,0x2180,0x2180}, {0x2181,0x2181,0x2181}, + {0x2182,0x2182,0x2182}, {0x2183,0x2183,0x2183}, + {0x2184,0x2184,0x2184}, {0x2185,0x2185,0x2185}, + {0x2186,0x2186,0x2186}, {0x2187,0x2187,0x2187}, + {0x2188,0x2188,0x2188}, {0x2189,0x2189,0x2189}, + {0x218A,0x218A,0x218A}, {0x218B,0x218B,0x218B}, + {0x218C,0x218C,0x218C}, {0x218D,0x218D,0x218D}, + {0x218E,0x218E,0x218E}, {0x218F,0x218F,0x218F}, + {0x2190,0x2190,0x2190}, {0x2191,0x2191,0x2191}, + {0x2192,0x2192,0x2192}, {0x2193,0x2193,0x2193}, + {0x2194,0x2194,0x2194}, {0x2195,0x2195,0x2195}, + {0x2196,0x2196,0x2196}, {0x2197,0x2197,0x2197}, + {0x2198,0x2198,0x2198}, {0x2199,0x2199,0x2199}, + {0x219A,0x219A,0x219A}, {0x219B,0x219B,0x219B}, + {0x219C,0x219C,0x219C}, {0x219D,0x219D,0x219D}, + {0x219E,0x219E,0x219E}, {0x219F,0x219F,0x219F}, + {0x21A0,0x21A0,0x21A0}, {0x21A1,0x21A1,0x21A1}, + {0x21A2,0x21A2,0x21A2}, {0x21A3,0x21A3,0x21A3}, + {0x21A4,0x21A4,0x21A4}, {0x21A5,0x21A5,0x21A5}, + {0x21A6,0x21A6,0x21A6}, {0x21A7,0x21A7,0x21A7}, + {0x21A8,0x21A8,0x21A8}, {0x21A9,0x21A9,0x21A9}, + {0x21AA,0x21AA,0x21AA}, {0x21AB,0x21AB,0x21AB}, + {0x21AC,0x21AC,0x21AC}, {0x21AD,0x21AD,0x21AD}, + {0x21AE,0x21AE,0x21AE}, {0x21AF,0x21AF,0x21AF}, + {0x21B0,0x21B0,0x21B0}, {0x21B1,0x21B1,0x21B1}, + {0x21B2,0x21B2,0x21B2}, {0x21B3,0x21B3,0x21B3}, + {0x21B4,0x21B4,0x21B4}, {0x21B5,0x21B5,0x21B5}, + {0x21B6,0x21B6,0x21B6}, {0x21B7,0x21B7,0x21B7}, + {0x21B8,0x21B8,0x21B8}, {0x21B9,0x21B9,0x21B9}, + {0x21BA,0x21BA,0x21BA}, {0x21BB,0x21BB,0x21BB}, + {0x21BC,0x21BC,0x21BC}, {0x21BD,0x21BD,0x21BD}, + {0x21BE,0x21BE,0x21BE}, {0x21BF,0x21BF,0x21BF}, + {0x21C0,0x21C0,0x21C0}, {0x21C1,0x21C1,0x21C1}, + {0x21C2,0x21C2,0x21C2}, {0x21C3,0x21C3,0x21C3}, + {0x21C4,0x21C4,0x21C4}, {0x21C5,0x21C5,0x21C5}, + {0x21C6,0x21C6,0x21C6}, {0x21C7,0x21C7,0x21C7}, + {0x21C8,0x21C8,0x21C8}, {0x21C9,0x21C9,0x21C9}, + {0x21CA,0x21CA,0x21CA}, {0x21CB,0x21CB,0x21CB}, + {0x21CC,0x21CC,0x21CC}, {0x21CD,0x21CD,0x21CD}, + {0x21CE,0x21CE,0x21CE}, {0x21CF,0x21CF,0x21CF}, + {0x21D0,0x21D0,0x21D0}, {0x21D1,0x21D1,0x21D1}, + {0x21D2,0x21D2,0x21D2}, {0x21D3,0x21D3,0x21D3}, + {0x21D4,0x21D4,0x21D4}, {0x21D5,0x21D5,0x21D5}, + {0x21D6,0x21D6,0x21D6}, {0x21D7,0x21D7,0x21D7}, + {0x21D8,0x21D8,0x21D8}, {0x21D9,0x21D9,0x21D9}, + {0x21DA,0x21DA,0x21DA}, {0x21DB,0x21DB,0x21DB}, + {0x21DC,0x21DC,0x21DC}, {0x21DD,0x21DD,0x21DD}, + {0x21DE,0x21DE,0x21DE}, {0x21DF,0x21DF,0x21DF}, + {0x21E0,0x21E0,0x21E0}, {0x21E1,0x21E1,0x21E1}, + {0x21E2,0x21E2,0x21E2}, {0x21E3,0x21E3,0x21E3}, + {0x21E4,0x21E4,0x21E4}, {0x21E5,0x21E5,0x21E5}, + {0x21E6,0x21E6,0x21E6}, {0x21E7,0x21E7,0x21E7}, + {0x21E8,0x21E8,0x21E8}, {0x21E9,0x21E9,0x21E9}, + {0x21EA,0x21EA,0x21EA}, {0x21EB,0x21EB,0x21EB}, + {0x21EC,0x21EC,0x21EC}, {0x21ED,0x21ED,0x21ED}, + {0x21EE,0x21EE,0x21EE}, {0x21EF,0x21EF,0x21EF}, + {0x21F0,0x21F0,0x21F0}, {0x21F1,0x21F1,0x21F1}, + {0x21F2,0x21F2,0x21F2}, {0x21F3,0x21F3,0x21F3}, + {0x21F4,0x21F4,0x21F4}, {0x21F5,0x21F5,0x21F5}, + {0x21F6,0x21F6,0x21F6}, {0x21F7,0x21F7,0x21F7}, + {0x21F8,0x21F8,0x21F8}, {0x21F9,0x21F9,0x21F9}, + {0x21FA,0x21FA,0x21FA}, {0x21FB,0x21FB,0x21FB}, + {0x21FC,0x21FC,0x21FC}, {0x21FD,0x21FD,0x21FD}, + {0x21FE,0x21FE,0x21FE}, {0x21FF,0x21FF,0x21FF} }; -static uint32_t lower24[]={ - 0x2400, 0x2401, 0x2402, 0x2403, 0x2404, 0x2405, 0x2406, 0x2407, - 0x2408, 0x2409, 0x240A, 0x240B, 0x240C, 0x240D, 0x240E, 0x240F, - 0x2410, 0x2411, 0x2412, 0x2413, 0x2414, 0x2415, 0x2416, 0x2417, - 0x2418, 0x2419, 0x241A, 0x241B, 0x241C, 0x241D, 0x241E, 0x241F, - 0x2420, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x2427, - 0x2428, 0x2429, 0x242A, 0x242B, 0x242C, 0x242D, 0x242E, 0x242F, - 0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437, - 0x2438, 0x2439, 0x243A, 0x243B, 0x243C, 0x243D, 0x243E, 0x243F, - 0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447, - 0x2448, 0x2449, 0x244A, 0x244B, 0x244C, 0x244D, 0x244E, 0x244F, - 0x2450, 0x2451, 0x2452, 0x2453, 0x2454, 0x2455, 0x2456, 0x2457, - 0x2458, 0x2459, 0x245A, 0x245B, 0x245C, 0x245D, 0x245E, 0x245F, - 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, - 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, 0x246F, - 0x2470, 0x2471, 0x2472, 0x2473, 0x2474, 0x2475, 0x2476, 0x2477, - 0x2478, 0x2479, 0x247A, 0x247B, 0x247C, 0x247D, 0x247E, 0x247F, - 0x2480, 0x2481, 0x2482, 0x2483, 0x2484, 0x2485, 0x2486, 0x2487, - 0x2488, 0x2489, 0x248A, 0x248B, 0x248C, 0x248D, 0x248E, 0x248F, - 0x2490, 0x2491, 0x2492, 0x2493, 0x2494, 0x2495, 0x2496, 0x2497, - 0x2498, 0x2499, 0x249A, 0x249B, 0x249C, 0x249D, 0x249E, 0x249F, - 0x24A0, 0x24A1, 0x24A2, 0x24A3, 0x24A4, 0x24A5, 0x24A6, 0x24A7, - 0x24A8, 0x24A9, 0x24AA, 0x24AB, 0x24AC, 0x24AD, 0x24AE, 0x24AF, - 0x24B0, 0x24B1, 0x24B2, 0x24B3, 0x24B4, 0x24B5, 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, - 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, 0x24EA, 0x24EB, 0x24EC, 0x24ED, 0x24EE, 0x24EF, - 0x24F0, 0x24F1, 0x24F2, 0x24F3, 0x24F4, 0x24F5, 0x24F6, 0x24F7, - 0x24F8, 0x24F9, 0x24FA, 0x24FB, 0x24FC, 0x24FD, 0x24FE, 0x24FF, +static ObUnicaseInfoChar plane24_utf8[]={ + {0x2400,0x2400,0x2400}, {0x2401,0x2401,0x2401}, + {0x2402,0x2402,0x2402}, {0x2403,0x2403,0x2403}, + {0x2404,0x2404,0x2404}, {0x2405,0x2405,0x2405}, + {0x2406,0x2406,0x2406}, {0x2407,0x2407,0x2407}, + {0x2408,0x2408,0x2408}, {0x2409,0x2409,0x2409}, + {0x240A,0x240A,0x240A}, {0x240B,0x240B,0x240B}, + {0x240C,0x240C,0x240C}, {0x240D,0x240D,0x240D}, + {0x240E,0x240E,0x240E}, {0x240F,0x240F,0x240F}, + {0x2410,0x2410,0x2410}, {0x2411,0x2411,0x2411}, + {0x2412,0x2412,0x2412}, {0x2413,0x2413,0x2413}, + {0x2414,0x2414,0x2414}, {0x2415,0x2415,0x2415}, + {0x2416,0x2416,0x2416}, {0x2417,0x2417,0x2417}, + {0x2418,0x2418,0x2418}, {0x2419,0x2419,0x2419}, + {0x241A,0x241A,0x241A}, {0x241B,0x241B,0x241B}, + {0x241C,0x241C,0x241C}, {0x241D,0x241D,0x241D}, + {0x241E,0x241E,0x241E}, {0x241F,0x241F,0x241F}, + {0x2420,0x2420,0x2420}, {0x2421,0x2421,0x2421}, + {0x2422,0x2422,0x2422}, {0x2423,0x2423,0x2423}, + {0x2424,0x2424,0x2424}, {0x2425,0x2425,0x2425}, + {0x2426,0x2426,0x2426}, {0x2427,0x2427,0x2427}, + {0x2428,0x2428,0x2428}, {0x2429,0x2429,0x2429}, + {0x242A,0x242A,0x242A}, {0x242B,0x242B,0x242B}, + {0x242C,0x242C,0x242C}, {0x242D,0x242D,0x242D}, + {0x242E,0x242E,0x242E}, {0x242F,0x242F,0x242F}, + {0x2430,0x2430,0x2430}, {0x2431,0x2431,0x2431}, + {0x2432,0x2432,0x2432}, {0x2433,0x2433,0x2433}, + {0x2434,0x2434,0x2434}, {0x2435,0x2435,0x2435}, + {0x2436,0x2436,0x2436}, {0x2437,0x2437,0x2437}, + {0x2438,0x2438,0x2438}, {0x2439,0x2439,0x2439}, + {0x243A,0x243A,0x243A}, {0x243B,0x243B,0x243B}, + {0x243C,0x243C,0x243C}, {0x243D,0x243D,0x243D}, + {0x243E,0x243E,0x243E}, {0x243F,0x243F,0x243F}, + {0x2440,0x2440,0x2440}, {0x2441,0x2441,0x2441}, + {0x2442,0x2442,0x2442}, {0x2443,0x2443,0x2443}, + {0x2444,0x2444,0x2444}, {0x2445,0x2445,0x2445}, + {0x2446,0x2446,0x2446}, {0x2447,0x2447,0x2447}, + {0x2448,0x2448,0x2448}, {0x2449,0x2449,0x2449}, + {0x244A,0x244A,0x244A}, {0x244B,0x244B,0x244B}, + {0x244C,0x244C,0x244C}, {0x244D,0x244D,0x244D}, + {0x244E,0x244E,0x244E}, {0x244F,0x244F,0x244F}, + {0x2450,0x2450,0x2450}, {0x2451,0x2451,0x2451}, + {0x2452,0x2452,0x2452}, {0x2453,0x2453,0x2453}, + {0x2454,0x2454,0x2454}, {0x2455,0x2455,0x2455}, + {0x2456,0x2456,0x2456}, {0x2457,0x2457,0x2457}, + {0x2458,0x2458,0x2458}, {0x2459,0x2459,0x2459}, + {0x245A,0x245A,0x245A}, {0x245B,0x245B,0x245B}, + {0x245C,0x245C,0x245C}, {0x245D,0x245D,0x245D}, + {0x245E,0x245E,0x245E}, {0x245F,0x245F,0x245F}, + {0x2460,0x2460,0x2460}, {0x2461,0x2461,0x2461}, + {0x2462,0x2462,0x2462}, {0x2463,0x2463,0x2463}, + {0x2464,0x2464,0x2464}, {0x2465,0x2465,0x2465}, + {0x2466,0x2466,0x2466}, {0x2467,0x2467,0x2467}, + {0x2468,0x2468,0x2468}, {0x2469,0x2469,0x2469}, + {0x246A,0x246A,0x246A}, {0x246B,0x246B,0x246B}, + {0x246C,0x246C,0x246C}, {0x246D,0x246D,0x246D}, + {0x246E,0x246E,0x246E}, {0x246F,0x246F,0x246F}, + {0x2470,0x2470,0x2470}, {0x2471,0x2471,0x2471}, + {0x2472,0x2472,0x2472}, {0x2473,0x2473,0x2473}, + {0x2474,0x2474,0x2474}, {0x2475,0x2475,0x2475}, + {0x2476,0x2476,0x2476}, {0x2477,0x2477,0x2477}, + {0x2478,0x2478,0x2478}, {0x2479,0x2479,0x2479}, + {0x247A,0x247A,0x247A}, {0x247B,0x247B,0x247B}, + {0x247C,0x247C,0x247C}, {0x247D,0x247D,0x247D}, + {0x247E,0x247E,0x247E}, {0x247F,0x247F,0x247F}, + {0x2480,0x2480,0x2480}, {0x2481,0x2481,0x2481}, + {0x2482,0x2482,0x2482}, {0x2483,0x2483,0x2483}, + {0x2484,0x2484,0x2484}, {0x2485,0x2485,0x2485}, + {0x2486,0x2486,0x2486}, {0x2487,0x2487,0x2487}, + {0x2488,0x2488,0x2488}, {0x2489,0x2489,0x2489}, + {0x248A,0x248A,0x248A}, {0x248B,0x248B,0x248B}, + {0x248C,0x248C,0x248C}, {0x248D,0x248D,0x248D}, + {0x248E,0x248E,0x248E}, {0x248F,0x248F,0x248F}, + {0x2490,0x2490,0x2490}, {0x2491,0x2491,0x2491}, + {0x2492,0x2492,0x2492}, {0x2493,0x2493,0x2493}, + {0x2494,0x2494,0x2494}, {0x2495,0x2495,0x2495}, + {0x2496,0x2496,0x2496}, {0x2497,0x2497,0x2497}, + {0x2498,0x2498,0x2498}, {0x2499,0x2499,0x2499}, + {0x249A,0x249A,0x249A}, {0x249B,0x249B,0x249B}, + {0x249C,0x249C,0x249C}, {0x249D,0x249D,0x249D}, + {0x249E,0x249E,0x249E}, {0x249F,0x249F,0x249F}, + {0x24A0,0x24A0,0x24A0}, {0x24A1,0x24A1,0x24A1}, + {0x24A2,0x24A2,0x24A2}, {0x24A3,0x24A3,0x24A3}, + {0x24A4,0x24A4,0x24A4}, {0x24A5,0x24A5,0x24A5}, + {0x24A6,0x24A6,0x24A6}, {0x24A7,0x24A7,0x24A7}, + {0x24A8,0x24A8,0x24A8}, {0x24A9,0x24A9,0x24A9}, + {0x24AA,0x24AA,0x24AA}, {0x24AB,0x24AB,0x24AB}, + {0x24AC,0x24AC,0x24AC}, {0x24AD,0x24AD,0x24AD}, + {0x24AE,0x24AE,0x24AE}, {0x24AF,0x24AF,0x24AF}, + {0x24B0,0x24B0,0x24B0}, {0x24B1,0x24B1,0x24B1}, + {0x24B2,0x24B2,0x24B2}, {0x24B3,0x24B3,0x24B3}, + {0x24B4,0x24B4,0x24B4}, {0x24B5,0x24B5,0x24B5}, + {0x24B6,0x24D0,0x24B6}, {0x24B7,0x24D1,0x24B7}, + {0x24B8,0x24D2,0x24B8}, {0x24B9,0x24D3,0x24B9}, + {0x24BA,0x24D4,0x24BA}, {0x24BB,0x24D5,0x24BB}, + {0x24BC,0x24D6,0x24BC}, {0x24BD,0x24D7,0x24BD}, + {0x24BE,0x24D8,0x24BE}, {0x24BF,0x24D9,0x24BF}, + {0x24C0,0x24DA,0x24C0}, {0x24C1,0x24DB,0x24C1}, + {0x24C2,0x24DC,0x24C2}, {0x24C3,0x24DD,0x24C3}, + {0x24C4,0x24DE,0x24C4}, {0x24C5,0x24DF,0x24C5}, + {0x24C6,0x24E0,0x24C6}, {0x24C7,0x24E1,0x24C7}, + {0x24C8,0x24E2,0x24C8}, {0x24C9,0x24E3,0x24C9}, + {0x24CA,0x24E4,0x24CA}, {0x24CB,0x24E5,0x24CB}, + {0x24CC,0x24E6,0x24CC}, {0x24CD,0x24E7,0x24CD}, + {0x24CE,0x24E8,0x24CE}, {0x24CF,0x24E9,0x24CF}, + {0x24B6,0x24D0,0x24B6}, {0x24B7,0x24D1,0x24B7}, + {0x24B8,0x24D2,0x24B8}, {0x24B9,0x24D3,0x24B9}, + {0x24BA,0x24D4,0x24BA}, {0x24BB,0x24D5,0x24BB}, + {0x24BC,0x24D6,0x24BC}, {0x24BD,0x24D7,0x24BD}, + {0x24BE,0x24D8,0x24BE}, {0x24BF,0x24D9,0x24BF}, + {0x24C0,0x24DA,0x24C0}, {0x24C1,0x24DB,0x24C1}, + {0x24C2,0x24DC,0x24C2}, {0x24C3,0x24DD,0x24C3}, + {0x24C4,0x24DE,0x24C4}, {0x24C5,0x24DF,0x24C5}, + {0x24C6,0x24E0,0x24C6}, {0x24C7,0x24E1,0x24C7}, + {0x24C8,0x24E2,0x24C8}, {0x24C9,0x24E3,0x24C9}, + {0x24CA,0x24E4,0x24CA}, {0x24CB,0x24E5,0x24CB}, + {0x24CC,0x24E6,0x24CC}, {0x24CD,0x24E7,0x24CD}, + {0x24CE,0x24E8,0x24CE}, {0x24CF,0x24E9,0x24CF}, + {0x24EA,0x24EA,0x24EA}, {0x24EB,0x24EB,0x24EB}, + {0x24EC,0x24EC,0x24EC}, {0x24ED,0x24ED,0x24ED}, + {0x24EE,0x24EE,0x24EE}, {0x24EF,0x24EF,0x24EF}, + {0x24F0,0x24F0,0x24F0}, {0x24F1,0x24F1,0x24F1}, + {0x24F2,0x24F2,0x24F2}, {0x24F3,0x24F3,0x24F3}, + {0x24F4,0x24F4,0x24F4}, {0x24F5,0x24F5,0x24F5}, + {0x24F6,0x24F6,0x24F6}, {0x24F7,0x24F7,0x24F7}, + {0x24F8,0x24F8,0x24F8}, {0x24F9,0x24F9,0x24F9}, + {0x24FA,0x24FA,0x24FA}, {0x24FB,0x24FB,0x24FB}, + {0x24FC,0x24FC,0x24FC}, {0x24FD,0x24FD,0x24FD}, + {0x24FE,0x24FE,0x24FE}, {0x24FF,0x24FF,0x24FF} }; -static uint32_t upper24[]={ - 0x2400, 0x2401, 0x2402, 0x2403, 0x2404, 0x2405, 0x2406, 0x2407, - 0x2408, 0x2409, 0x240A, 0x240B, 0x240C, 0x240D, 0x240E, 0x240F, - 0x2410, 0x2411, 0x2412, 0x2413, 0x2414, 0x2415, 0x2416, 0x2417, - 0x2418, 0x2419, 0x241A, 0x241B, 0x241C, 0x241D, 0x241E, 0x241F, - 0x2420, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x2427, - 0x2428, 0x2429, 0x242A, 0x242B, 0x242C, 0x242D, 0x242E, 0x242F, - 0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437, - 0x2438, 0x2439, 0x243A, 0x243B, 0x243C, 0x243D, 0x243E, 0x243F, - 0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447, - 0x2448, 0x2449, 0x244A, 0x244B, 0x244C, 0x244D, 0x244E, 0x244F, - 0x2450, 0x2451, 0x2452, 0x2453, 0x2454, 0x2455, 0x2456, 0x2457, - 0x2458, 0x2459, 0x245A, 0x245B, 0x245C, 0x245D, 0x245E, 0x245F, - 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, - 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, 0x246F, - 0x2470, 0x2471, 0x2472, 0x2473, 0x2474, 0x2475, 0x2476, 0x2477, - 0x2478, 0x2479, 0x247A, 0x247B, 0x247C, 0x247D, 0x247E, 0x247F, - 0x2480, 0x2481, 0x2482, 0x2483, 0x2484, 0x2485, 0x2486, 0x2487, - 0x2488, 0x2489, 0x248A, 0x248B, 0x248C, 0x248D, 0x248E, 0x248F, - 0x2490, 0x2491, 0x2492, 0x2493, 0x2494, 0x2495, 0x2496, 0x2497, - 0x2498, 0x2499, 0x249A, 0x249B, 0x249C, 0x249D, 0x249E, 0x249F, - 0x24A0, 0x24A1, 0x24A2, 0x24A3, 0x24A4, 0x24A5, 0x24A6, 0x24A7, - 0x24A8, 0x24A9, 0x24AA, 0x24AB, 0x24AC, 0x24AD, 0x24AE, 0x24AF, - 0x24B0, 0x24B1, 0x24B2, 0x24B3, 0x24B4, 0x24B5, 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, - 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, 0x24EA, 0x24EB, 0x24EC, 0x24ED, 0x24EE, 0x24EF, - 0x24F0, 0x24F1, 0x24F2, 0x24F3, 0x24F4, 0x24F5, 0x24F6, 0x24F7, - 0x24F8, 0x24F9, 0x24FA, 0x24FB, 0x24FC, 0x24FD, 0x24FE, 0x24FF, +static ObUnicaseInfoChar planeFF_utf8[]={ + {0xFF00,0xFF00,0xFF00}, {0xFF01,0xFF01,0xFF01}, + {0xFF02,0xFF02,0xFF02}, {0xFF03,0xFF03,0xFF03}, + {0xFF04,0xFF04,0xFF04}, {0xFF05,0xFF05,0xFF05}, + {0xFF06,0xFF06,0xFF06}, {0xFF07,0xFF07,0xFF07}, + {0xFF08,0xFF08,0xFF08}, {0xFF09,0xFF09,0xFF09}, + {0xFF0A,0xFF0A,0xFF0A}, {0xFF0B,0xFF0B,0xFF0B}, + {0xFF0C,0xFF0C,0xFF0C}, {0xFF0D,0xFF0D,0xFF0D}, + {0xFF0E,0xFF0E,0xFF0E}, {0xFF0F,0xFF0F,0xFF0F}, + {0xFF10,0xFF10,0xFF10}, {0xFF11,0xFF11,0xFF11}, + {0xFF12,0xFF12,0xFF12}, {0xFF13,0xFF13,0xFF13}, + {0xFF14,0xFF14,0xFF14}, {0xFF15,0xFF15,0xFF15}, + {0xFF16,0xFF16,0xFF16}, {0xFF17,0xFF17,0xFF17}, + {0xFF18,0xFF18,0xFF18}, {0xFF19,0xFF19,0xFF19}, + {0xFF1A,0xFF1A,0xFF1A}, {0xFF1B,0xFF1B,0xFF1B}, + {0xFF1C,0xFF1C,0xFF1C}, {0xFF1D,0xFF1D,0xFF1D}, + {0xFF1E,0xFF1E,0xFF1E}, {0xFF1F,0xFF1F,0xFF1F}, + {0xFF20,0xFF20,0xFF20}, {0xFF21,0xFF41,0xFF21}, + {0xFF22,0xFF42,0xFF22}, {0xFF23,0xFF43,0xFF23}, + {0xFF24,0xFF44,0xFF24}, {0xFF25,0xFF45,0xFF25}, + {0xFF26,0xFF46,0xFF26}, {0xFF27,0xFF47,0xFF27}, + {0xFF28,0xFF48,0xFF28}, {0xFF29,0xFF49,0xFF29}, + {0xFF2A,0xFF4A,0xFF2A}, {0xFF2B,0xFF4B,0xFF2B}, + {0xFF2C,0xFF4C,0xFF2C}, {0xFF2D,0xFF4D,0xFF2D}, + {0xFF2E,0xFF4E,0xFF2E}, {0xFF2F,0xFF4F,0xFF2F}, + {0xFF30,0xFF50,0xFF30}, {0xFF31,0xFF51,0xFF31}, + {0xFF32,0xFF52,0xFF32}, {0xFF33,0xFF53,0xFF33}, + {0xFF34,0xFF54,0xFF34}, {0xFF35,0xFF55,0xFF35}, + {0xFF36,0xFF56,0xFF36}, {0xFF37,0xFF57,0xFF37}, + {0xFF38,0xFF58,0xFF38}, {0xFF39,0xFF59,0xFF39}, + {0xFF3A,0xFF5A,0xFF3A}, {0xFF3B,0xFF3B,0xFF3B}, + {0xFF3C,0xFF3C,0xFF3C}, {0xFF3D,0xFF3D,0xFF3D}, + {0xFF3E,0xFF3E,0xFF3E}, {0xFF3F,0xFF3F,0xFF3F}, + {0xFF40,0xFF40,0xFF40}, {0xFF21,0xFF41,0xFF21}, + {0xFF22,0xFF42,0xFF22}, {0xFF23,0xFF43,0xFF23}, + {0xFF24,0xFF44,0xFF24}, {0xFF25,0xFF45,0xFF25}, + {0xFF26,0xFF46,0xFF26}, {0xFF27,0xFF47,0xFF27}, + {0xFF28,0xFF48,0xFF28}, {0xFF29,0xFF49,0xFF29}, + {0xFF2A,0xFF4A,0xFF2A}, {0xFF2B,0xFF4B,0xFF2B}, + {0xFF2C,0xFF4C,0xFF2C}, {0xFF2D,0xFF4D,0xFF2D}, + {0xFF2E,0xFF4E,0xFF2E}, {0xFF2F,0xFF4F,0xFF2F}, + {0xFF30,0xFF50,0xFF30}, {0xFF31,0xFF51,0xFF31}, + {0xFF32,0xFF52,0xFF32}, {0xFF33,0xFF53,0xFF33}, + {0xFF34,0xFF54,0xFF34}, {0xFF35,0xFF55,0xFF35}, + {0xFF36,0xFF56,0xFF36}, {0xFF37,0xFF57,0xFF37}, + {0xFF38,0xFF58,0xFF38}, {0xFF39,0xFF59,0xFF39}, + {0xFF3A,0xFF5A,0xFF3A}, {0xFF5B,0xFF5B,0xFF5B}, + {0xFF5C,0xFF5C,0xFF5C}, {0xFF5D,0xFF5D,0xFF5D}, + {0xFF5E,0xFF5E,0xFF5E}, {0xFF5F,0xFF5F,0xFF5F}, + {0xFF60,0xFF60,0xFF60}, {0xFF61,0xFF61,0xFF61}, + {0xFF62,0xFF62,0xFF62}, {0xFF63,0xFF63,0xFF63}, + {0xFF64,0xFF64,0xFF64}, {0xFF65,0xFF65,0xFF65}, + {0xFF66,0xFF66,0xFF66}, {0xFF67,0xFF67,0xFF67}, + {0xFF68,0xFF68,0xFF68}, {0xFF69,0xFF69,0xFF69}, + {0xFF6A,0xFF6A,0xFF6A}, {0xFF6B,0xFF6B,0xFF6B}, + {0xFF6C,0xFF6C,0xFF6C}, {0xFF6D,0xFF6D,0xFF6D}, + {0xFF6E,0xFF6E,0xFF6E}, {0xFF6F,0xFF6F,0xFF6F}, + {0xFF70,0xFF70,0xFF70}, {0xFF71,0xFF71,0xFF71}, + {0xFF72,0xFF72,0xFF72}, {0xFF73,0xFF73,0xFF73}, + {0xFF74,0xFF74,0xFF74}, {0xFF75,0xFF75,0xFF75}, + {0xFF76,0xFF76,0xFF76}, {0xFF77,0xFF77,0xFF77}, + {0xFF78,0xFF78,0xFF78}, {0xFF79,0xFF79,0xFF79}, + {0xFF7A,0xFF7A,0xFF7A}, {0xFF7B,0xFF7B,0xFF7B}, + {0xFF7C,0xFF7C,0xFF7C}, {0xFF7D,0xFF7D,0xFF7D}, + {0xFF7E,0xFF7E,0xFF7E}, {0xFF7F,0xFF7F,0xFF7F}, + {0xFF80,0xFF80,0xFF80}, {0xFF81,0xFF81,0xFF81}, + {0xFF82,0xFF82,0xFF82}, {0xFF83,0xFF83,0xFF83}, + {0xFF84,0xFF84,0xFF84}, {0xFF85,0xFF85,0xFF85}, + {0xFF86,0xFF86,0xFF86}, {0xFF87,0xFF87,0xFF87}, + {0xFF88,0xFF88,0xFF88}, {0xFF89,0xFF89,0xFF89}, + {0xFF8A,0xFF8A,0xFF8A}, {0xFF8B,0xFF8B,0xFF8B}, + {0xFF8C,0xFF8C,0xFF8C}, {0xFF8D,0xFF8D,0xFF8D}, + {0xFF8E,0xFF8E,0xFF8E}, {0xFF8F,0xFF8F,0xFF8F}, + {0xFF90,0xFF90,0xFF90}, {0xFF91,0xFF91,0xFF91}, + {0xFF92,0xFF92,0xFF92}, {0xFF93,0xFF93,0xFF93}, + {0xFF94,0xFF94,0xFF94}, {0xFF95,0xFF95,0xFF95}, + {0xFF96,0xFF96,0xFF96}, {0xFF97,0xFF97,0xFF97}, + {0xFF98,0xFF98,0xFF98}, {0xFF99,0xFF99,0xFF99}, + {0xFF9A,0xFF9A,0xFF9A}, {0xFF9B,0xFF9B,0xFF9B}, + {0xFF9C,0xFF9C,0xFF9C}, {0xFF9D,0xFF9D,0xFF9D}, + {0xFF9E,0xFF9E,0xFF9E}, {0xFF9F,0xFF9F,0xFF9F}, + {0xFFA0,0xFFA0,0xFFA0}, {0xFFA1,0xFFA1,0xFFA1}, + {0xFFA2,0xFFA2,0xFFA2}, {0xFFA3,0xFFA3,0xFFA3}, + {0xFFA4,0xFFA4,0xFFA4}, {0xFFA5,0xFFA5,0xFFA5}, + {0xFFA6,0xFFA6,0xFFA6}, {0xFFA7,0xFFA7,0xFFA7}, + {0xFFA8,0xFFA8,0xFFA8}, {0xFFA9,0xFFA9,0xFFA9}, + {0xFFAA,0xFFAA,0xFFAA}, {0xFFAB,0xFFAB,0xFFAB}, + {0xFFAC,0xFFAC,0xFFAC}, {0xFFAD,0xFFAD,0xFFAD}, + {0xFFAE,0xFFAE,0xFFAE}, {0xFFAF,0xFFAF,0xFFAF}, + {0xFFB0,0xFFB0,0xFFB0}, {0xFFB1,0xFFB1,0xFFB1}, + {0xFFB2,0xFFB2,0xFFB2}, {0xFFB3,0xFFB3,0xFFB3}, + {0xFFB4,0xFFB4,0xFFB4}, {0xFFB5,0xFFB5,0xFFB5}, + {0xFFB6,0xFFB6,0xFFB6}, {0xFFB7,0xFFB7,0xFFB7}, + {0xFFB8,0xFFB8,0xFFB8}, {0xFFB9,0xFFB9,0xFFB9}, + {0xFFBA,0xFFBA,0xFFBA}, {0xFFBB,0xFFBB,0xFFBB}, + {0xFFBC,0xFFBC,0xFFBC}, {0xFFBD,0xFFBD,0xFFBD}, + {0xFFBE,0xFFBE,0xFFBE}, {0xFFBF,0xFFBF,0xFFBF}, + {0xFFC0,0xFFC0,0xFFC0}, {0xFFC1,0xFFC1,0xFFC1}, + {0xFFC2,0xFFC2,0xFFC2}, {0xFFC3,0xFFC3,0xFFC3}, + {0xFFC4,0xFFC4,0xFFC4}, {0xFFC5,0xFFC5,0xFFC5}, + {0xFFC6,0xFFC6,0xFFC6}, {0xFFC7,0xFFC7,0xFFC7}, + {0xFFC8,0xFFC8,0xFFC8}, {0xFFC9,0xFFC9,0xFFC9}, + {0xFFCA,0xFFCA,0xFFCA}, {0xFFCB,0xFFCB,0xFFCB}, + {0xFFCC,0xFFCC,0xFFCC}, {0xFFCD,0xFFCD,0xFFCD}, + {0xFFCE,0xFFCE,0xFFCE}, {0xFFCF,0xFFCF,0xFFCF}, + {0xFFD0,0xFFD0,0xFFD0}, {0xFFD1,0xFFD1,0xFFD1}, + {0xFFD2,0xFFD2,0xFFD2}, {0xFFD3,0xFFD3,0xFFD3}, + {0xFFD4,0xFFD4,0xFFD4}, {0xFFD5,0xFFD5,0xFFD5}, + {0xFFD6,0xFFD6,0xFFD6}, {0xFFD7,0xFFD7,0xFFD7}, + {0xFFD8,0xFFD8,0xFFD8}, {0xFFD9,0xFFD9,0xFFD9}, + {0xFFDA,0xFFDA,0xFFDA}, {0xFFDB,0xFFDB,0xFFDB}, + {0xFFDC,0xFFDC,0xFFDC}, {0xFFDD,0xFFDD,0xFFDD}, + {0xFFDE,0xFFDE,0xFFDE}, {0xFFDF,0xFFDF,0xFFDF}, + {0xFFE0,0xFFE0,0xFFE0}, {0xFFE1,0xFFE1,0xFFE1}, + {0xFFE2,0xFFE2,0xFFE2}, {0xFFE3,0xFFE3,0xFFE3}, + {0xFFE4,0xFFE4,0xFFE4}, {0xFFE5,0xFFE5,0xFFE5}, + {0xFFE6,0xFFE6,0xFFE6}, {0xFFE7,0xFFE7,0xFFE7}, + {0xFFE8,0xFFE8,0xFFE8}, {0xFFE9,0xFFE9,0xFFE9}, + {0xFFEA,0xFFEA,0xFFEA}, {0xFFEB,0xFFEB,0xFFEB}, + {0xFFEC,0xFFEC,0xFFEC}, {0xFFED,0xFFED,0xFFED}, + {0xFFEE,0xFFEE,0xFFEE}, {0xFFEF,0xFFEF,0xFFEF}, + {0xFFF0,0xFFF0,0xFFF0}, {0xFFF1,0xFFF1,0xFFF1}, + {0xFFF2,0xFFF2,0xFFF2}, {0xFFF3,0xFFF3,0xFFF3}, + {0xFFF4,0xFFF4,0xFFF4}, {0xFFF5,0xFFF5,0xFFF5}, + {0xFFF6,0xFFF6,0xFFF6}, {0xFFF7,0xFFF7,0xFFF7}, + {0xFFF8,0xFFF8,0xFFF8}, {0xFFF9,0xFFF9,0xFFF9}, + {0xFFFA,0xFFFA,0xFFFA}, {0xFFFB,0xFFFB,0xFFFB}, + {0xFFFC,0xFFFC,0xFFFC}, {0xFFFD,0xFFFD,0xFFFD}, + {0xFFFE,0xFFFE,0xFFFE}, {0xFFFF,0xFFFF,0xFFFF} }; -static uint32_t sort24[]={ - 0x2400, 0x2401, 0x2402, 0x2403, 0x2404, 0x2405, 0x2406, 0x2407, - 0x2408, 0x2409, 0x240A, 0x240B, 0x240C, 0x240D, 0x240E, 0x240F, - 0x2410, 0x2411, 0x2412, 0x2413, 0x2414, 0x2415, 0x2416, 0x2417, - 0x2418, 0x2419, 0x241A, 0x241B, 0x241C, 0x241D, 0x241E, 0x241F, - 0x2420, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x2427, - 0x2428, 0x2429, 0x242A, 0x242B, 0x242C, 0x242D, 0x242E, 0x242F, - 0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437, - 0x2438, 0x2439, 0x243A, 0x243B, 0x243C, 0x243D, 0x243E, 0x243F, - 0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447, - 0x2448, 0x2449, 0x244A, 0x244B, 0x244C, 0x244D, 0x244E, 0x244F, - 0x2450, 0x2451, 0x2452, 0x2453, 0x2454, 0x2455, 0x2456, 0x2457, - 0x2458, 0x2459, 0x245A, 0x245B, 0x245C, 0x245D, 0x245E, 0x245F, - 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, - 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, 0x246F, - 0x2470, 0x2471, 0x2472, 0x2473, 0x2474, 0x2475, 0x2476, 0x2477, - 0x2478, 0x2479, 0x247A, 0x247B, 0x247C, 0x247D, 0x247E, 0x247F, - 0x2480, 0x2481, 0x2482, 0x2483, 0x2484, 0x2485, 0x2486, 0x2487, - 0x2488, 0x2489, 0x248A, 0x248B, 0x248C, 0x248D, 0x248E, 0x248F, - 0x2490, 0x2491, 0x2492, 0x2493, 0x2494, 0x2495, 0x2496, 0x2497, - 0x2498, 0x2499, 0x249A, 0x249B, 0x249C, 0x249D, 0x249E, 0x249F, - 0x24A0, 0x24A1, 0x24A2, 0x24A3, 0x24A4, 0x24A5, 0x24A6, 0x24A7, - 0x24A8, 0x24A9, 0x24AA, 0x24AB, 0x24AC, 0x24AD, 0x24AE, 0x24AF, - 0x24B0, 0x24B1, 0x24B2, 0x24B3, 0x24B4, 0x24B5, 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, - 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, 0x24EA, 0x24EB, 0x24EC, 0x24ED, 0x24EE, 0x24EF, - 0x24F0, 0x24F1, 0x24F2, 0x24F3, 0x24F4, 0x24F5, 0x24F6, 0x24F7, - 0x24F8, 0x24F9, 0x24FA, 0x24FB, 0x24FC, 0x24FD, 0x24FE, 0x24FF, -}; - -static uint32_t lowerFF[]={ - 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07, - 0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F, - 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17, - 0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F, - 0xFF20, 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, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F, - 0xFF40, 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, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F, - 0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67, - 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, - 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77, - 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, - 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, - 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, - 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, - 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, - 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7, - 0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF, - 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7, - 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF, - 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7, - 0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF, - 0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7, - 0xFFD8, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF, - 0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7, - 0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF, - 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7, - 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF, -}; - -static uint32_t upperFF[]={ - 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07, - 0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F, - 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17, - 0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F, - 0xFF20, 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, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F, - 0xFF40, 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, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F, - 0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67, - 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, - 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77, - 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, - 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, - 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, - 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, - 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, - 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7, - 0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF, - 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7, - 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF, - 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7, - 0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF, - 0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7, - 0xFFD8, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF, - 0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7, - 0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF, - 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7, - 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF, -}; - -static uint32_t sortFF[]={ - 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07, - 0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F, - 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17, - 0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F, - 0xFF20, 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, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F, - 0xFF40, 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, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F, - 0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67, - 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, - 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77, - 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, - 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, - 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, - 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, - 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, - 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7, - 0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF, - 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7, - 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF, - 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7, - 0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF, - 0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7, - 0xFFD8, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF, - 0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7, - 0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF, - 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7, - 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF, -}; - -static uint32_t *ob_toupper_pages_utf8[256]= +static const ObUnicaseInfoChar *ob_unicase_pages_default[256]= { - upper00, upper01, upper02, upper03, upper04, upper05, NULL, NULL, + plane00_utf8, plane01_utf8, plane02_utf8, plane03_utf8, plane04_utf8, plane05_utf8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, upper1E, upper1F, - NULL, upper21, NULL, NULL, upper24, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, plane1E_utf8, plane1F_utf8, + NULL, plane21_utf8, NULL, NULL, plane24_utf8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -1316,601 +1556,617 @@ static uint32_t *ob_toupper_pages_utf8[256]= NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, upperFF, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, planeFF_utf8 }; -static uint32_t *ob_tolower_pages_utf8[256]= +ObUnicaseInfo ob_unicase_default= { - lower00, lower01, lower02, lower03, lower04, lower05, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, lower1E, lower1F, - NULL, lower21, NULL, NULL, lower24, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, lowerFF, + 0xFFFF, + ob_unicase_pages_default }; -static uint32_t *ob_sort_pages_utf8[256]= -{ - sort00, sort01, sort02, sort03, sort04, sort05, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, sort1E, sort1F, - NULL, sort21, NULL, NULL, sort24, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, sortFF, -}; - -ObUnicasePages utf8_unicase_pages = { - ob_toupper_pages_utf8, - ob_tolower_pages_utf8, - ob_sort_pages_utf8, -}; - - -//========================================================================== - -static int ob_valid_mbcharlen_utf8mb4(const unsigned char *str, size_t len) +static int ob_valid_mbcharlen_utf8mb4(const unsigned char* str, const unsigned char *str_e) { int ret = 0; - + int len = str_e - str; if (OB_UNLIKELY(len <= 0)) { - ret = OB_CS_ERR_TOOSMALL; - } else if (str[0] < 0x80) { + ret = OB_CS_TOOSMALL; + } else if (str[0] < 0x80) { //0xxxxxxx (1 byte, 7bits) ret = 1; - } else if (str[0] < 0xE0) { + } else if (str[0] < 0xC2) { // 1100000x 10xxxxxx (code points < 1 byte) + ret = OB_CS_ILSEQ; + } else if (str[0] < 0xE0) { //110xxxxx 10xxxxxx (2 bytes, 11bits) if (OB_UNLIKELY(len < 2)) { - ret = OB_CS_ERR_TOOSMALL2; - } else if (OB_UNLIKELY(!(IS_CONTINUATION_BYTE(str[1]) - && str[0] >= 0xC2))) { - ret = OB_CS_ERR_ILLEGAL_SEQUENCE; + ret = OB_CS_TOOSMALL2; + } else if (OB_UNLIKELY(!(IS_CONTINUATION_BYTE(str[1])))) { + ret = OB_CS_ILSEQ; } else { ret = 2; } - } else if (str[0] < 0xF0) { + } else if (str[0] < 0xF0) { // 1110xxxx 10xxxxxx 10xxxxxx (3 bytes, 16 bits) if (OB_UNLIKELY(len < 3)) { - ret = OB_CS_ERR_TOOSMALL3; - } else if (OB_UNLIKELY(!(IS_CONTINUATION_BYTE(str[1]) - && IS_CONTINUATION_BYTE(str[2]) - && (str[0] >= 0xE1 || str[1] >= 0xA0)))) { - ret = OB_CS_ERR_ILLEGAL_SEQUENCE; + ret = OB_CS_TOOSMALL3; + } else if (OB_UNLIKELY(!(IS_CONTINUATION_BYTE(str[1]) && IS_CONTINUATION_BYTE(str[2]) && + (str[0] >= 0xE1 || str[1] >= 0xA0)))) { + // check the code points + // 11100001 10xxxxxx 10xxxxxx (>= 13 bits) + // 111xxxxx 101xxxxx 10xxxxxx (at least 12 bits) + ret = OB_CS_ILSEQ; } else { ret = 3; } - } else if (str[0] < 0xF5) { + } else if (str[0] < 0xF5) { // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx if (OB_UNLIKELY(len < 4)) { - ret = OB_CS_ERR_TOOSMALL4; - } else if (OB_UNLIKELY(!(IS_CONTINUATION_BYTE(str[1]) - && IS_CONTINUATION_BYTE(str[2]) - && IS_CONTINUATION_BYTE(str[3]) - && (str[0] >= 0xF1 || str[1] >= 0x90) - && (str[0] <= 0xF3 || str[1] <= 0x8F)))) { - ret = OB_CS_ERR_ILLEGAL_SEQUENCE; + ret = OB_CS_TOOSMALL4; + } else if (OB_UNLIKELY( + !(IS_CONTINUATION_BYTE(str[1]) && IS_CONTINUATION_BYTE(str[2]) && IS_CONTINUATION_BYTE(str[3]) && + (str[0] >= 0xF1 || str[1] >= 0x90) && (str[0] <= 0xF3 || str[1] <= 0x8F)))) { + ret = OB_CS_ILSEQ; } else { ret = 4; } } else { - ret = OB_CS_ERR_ILLEGAL_SEQUENCE; + ret = OB_CS_ILSEQ; } return ret; } -static uint32_t ob_ismbchar_utf8mb4(const char *str, size_t len) +static unsigned int ob_ismbchar_utf8mb4(const ObCharsetInfo *cs, const char *begin, const char *end) { - int res = ob_valid_mbcharlen_utf8mb4((const unsigned char*)str, len); + int res = ob_valid_mbcharlen_utf8mb4((const unsigned char*)begin, (const unsigned char*)end); return (res > 1) ? res : 0; } -static size_t ob_well_formed_len_utf8mb4(const char *str, size_t len, - size_t nchars, int *error) + +static unsigned int ob_mbcharlen_utf8mb4(const ObCharsetInfo *cs __attribute__((unused)), unsigned int code) { - const char *str_begin= str; + int len = 0; + if (code < 0x80) { + return len = 1; + } else if (code < 0xc2) { + return len = 0; + } else if (code < 0xe0) { + return len = 2; + } else if (code < 0xf0) { + return len = 3; + } else if (code < 0xf8) { + return len = 4; + } + return len; +} + +static size_t ob_well_formed_len_utf8mb4(const ObCharsetInfo *cs, + const char *begin, const char *end, + size_t pos, int *error) +{ + const char *b_start = begin; *error = 0; - for (; nchars > 0 && len > 0; nchars--) { - int mb_char_len = 0; - if ((mb_char_len= ob_valid_mbcharlen_utf8mb4((unsigned char*) str, len)) < 0) { - *error= mb_char_len; + while (pos--) + { + int mb_len; + if ((mb_len = ob_valid_mbcharlen_utf8mb4((unsigned char*) begin, (unsigned char*) end)) <= 0) { + *error = begin < end ? 1 : 0; break; + } else { + begin += mb_len; } - str += mb_char_len; - len -= mb_char_len; } - return (size_t) (str - str_begin); + return (size_t) (begin - b_start); } -static int ob_mb_wc_utf8mb4(const unsigned char *str, const unsigned char *end, ob_wc_t* wchar) +static int ob_mb_wc_utf8mb4(const ObCharsetInfo *cs __attribute__((unused)), + ob_wc_t * pwc, const unsigned char *src, const unsigned char *end) { - int ret = OB_CS_SUCCESS; - int bytes = 0; - size_t len = (size_t)(end - str); - if (OB_UNLIKELY(len <= 0)) { - ret = OB_CS_ERR_TOOSMALL; - } else if (str[0] < 0x80) { - *wchar = str[0]; - bytes = 1; - } else if (OB_UNLIKELY(str[0] < 0xC2)) { - ret = OB_CS_ERR_ILLEGAL_SEQUENCE; - } else if (str[0] < 0xE0) { - if (OB_UNLIKELY(len < 2)) { - ret = OB_CS_ERR_TOOSMALL2; - } else if (OB_UNLIKELY(!(IS_CONTINUATION_BYTE(str[1])))) { - ret = OB_CS_ERR_ILLEGAL_SEQUENCE; - } else { - *wchar = ((ob_wc_t) (str[0] & 0x1F) << 6) - | (ob_wc_t) (str[1] ^ 0x80); - bytes = 2; - } - } else if (str[0] < 0xF0) { - if (OB_UNLIKELY(len < 3)) { - ret = OB_CS_ERR_TOOSMALL3; - } else if (OB_UNLIKELY(!(IS_CONTINUATION_BYTE(str[1]) - && IS_CONTINUATION_BYTE(str[2]) - && (str[0] >= 0xE1 || str[1] >= 0xA0)))) { - ret = OB_CS_ERR_ILLEGAL_SEQUENCE; - } else { - *wchar = ((ob_wc_t) (str[0] & 0x0f) << 12) - | ((ob_wc_t) (str[1] ^ 0x80) << 6) - | (ob_wc_t) (str[2] ^ 0x80); - bytes = 3; - } - } else if (str[0] < 0xF5) { - if (OB_UNLIKELY(len < 4)) { - ret = OB_CS_ERR_TOOSMALL4; - } else if (OB_UNLIKELY(!(IS_CONTINUATION_BYTE(str[1]) && - IS_CONTINUATION_BYTE(str[2]) && - IS_CONTINUATION_BYTE(str[3]) && - (str[0] >= 0xF1 || str[1] >= 0x90) && - (str[0] <= 0xF3 || str[1] <= 0x8F)))) { - ret = OB_CS_ERR_ILLEGAL_SEQUENCE; - } else { - *wchar= ((ob_wc_t) (str[0] & 0x07) << 18) - | ((ob_wc_t) (str[1] ^ 0x80) << 12) - | ((ob_wc_t) (str[2] ^ 0x80) << 6) - | (ob_wc_t) (str[3] ^ 0x80); - } - bytes = 4; - } else { - ret = OB_CS_ERR_ILLEGAL_SEQUENCE; + int ret = 0; + ret = ob_valid_mbcharlen_utf8mb4(src, end); + if (ret == 1) { + *pwc= src[0]; + } else if (ret == 2) { + *pwc= ((ob_wc_t) (src[0] & 0x1f) << 6) | (ob_wc_t) (src[1] ^ 0x80); //code point + } else if (ret == 3) { + *pwc= ((ob_wc_t) (src[0] & 0x0f) << 12) | + ((ob_wc_t) (src[1] ^ 0x80) << 6) | + (ob_wc_t) (src[2] ^ 0x80); + } else if (ret == 4) { + *pwc = ((ob_wc_t) (src[0] & 0x07) << 18) | + ((ob_wc_t) (src[1] ^ 0x80) << 12) | + ((ob_wc_t) (src[2] ^ 0x80) << 6) | + (ob_wc_t) (src[3] ^ 0x80); } - return OB_CS_SUCC(ret) ? bytes : ret; + return ret; } -static int ob_wc_mb_utf8mb4(ob_wc_t wchar, unsigned char *str, unsigned char *end) +static int ob_wc_mb_utf8mb4(const ObCharsetInfo *cs __attribute__((unused)), + ob_wc_t w_char, unsigned char *r, unsigned char *end) { int bytes = 0; int ret = 0; - int64_t len = (int64_t)(end - str); + int64_t len = (int64_t)(end - r); if (OB_UNLIKELY(len <= 0)) { - ret = OB_CS_ERR_TOOSMALL; - } else if (wchar < 0x80) { + ret = OB_CS_TOOSMALL; + } else if (w_char < 0x80) { //7 U+0000 U+007F 1 0xxxxxxx bytes = 1; - } else if (wchar < 0x800) { + } else if (w_char < 0x800) {//11 U+0080 U+07FF 2 110xxxxx 10xxxxxx bytes = 2; - } else if (wchar < 0x10000) { + } else if (w_char < 0x10000) {//16 U+0800 U+FFFF 3 1110xxxx 10xxxxxx 10xxxxxx bytes = 3; - } else if (wchar < 0x200000) { + } else if (w_char < 0x200000) {// 21 U+10000 U+1FFFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx bytes = 4; } else { - ret = OB_CS_ERR_ILLEGAL_UNICODE; + ret = OB_CS_ILUNI; } - if (OB_UNLIKELY(bytes > len)) { - ret = OB_CS_ERR_TOOSMALLN(bytes); + if (OB_UNLIKELY(ret != 0)) { + //do nothing + } else if (OB_UNLIKELY(bytes > len)) { + ret = OB_CS_TOOSMALLN(bytes); } else { switch (bytes) { - case 4: - str[3] = (unsigned char) (0x80 | (wchar & 0x3F)); - wchar = (wchar >> 6) | 0x10000; - case 3: - str[2] = (unsigned char) (0x80 | (wchar & 0x3F)); - wchar = (wchar >> 6) | 0x800; - case 2: - str[1] = (unsigned char) (0x80 | (wchar & 0x3F)); - wchar = (wchar >> 6) | 0xC0; - case 1: - str[0] = (unsigned char) wchar; + case 4: r[3] = (unsigned char) (0x80 | (w_char & 0x3f)); w_char >>= 6; w_char |= 0x10000; + case 3: r[2] = (unsigned char) (0x80 | (w_char & 0x3f)); w_char >>= 6; w_char |= 0x800; + case 2: r[1] = (unsigned char) (0x80 | (w_char & 0x3f)); w_char >>= 6; w_char |= 0xc0; + case 1: r[0] = (unsigned char) w_char; } + ret = bytes; } - - return OB_CS_SUCC(ret) ? bytes : ret; + return ret; } -static inline void ob_page_help_utf8mb4(uint32_t **plane, ob_wc_t *wchar) +static inline void ob_tolower_utf8mb4(ObUnicaseInfo *uni_plane, ob_wc_t *wc) { - if (*wchar <= 0xFFFF) { - uint32_t *page = plane[(*wchar >> 8)]; + if (*wc <= uni_plane->maxchar) { + const ObUnicaseInfoChar *page = uni_plane->page[(*wc >> 8)]; if (OB_NOT_NULL(page)) { - *wchar= page[*wchar & 0xFF]; + *wc= page[*wc & 0xFF].tolower; } } -} - -static inline void ob_tolower_utf8mb4(uint32_t **lower_plane, ob_wc_t *wchar) -{ - ob_page_help_utf8mb4(lower_plane, wchar); + return; } -static inline void ob_toupper_utf8mb4(uint32_t **upper_plane, ob_wc_t *wchar) +static inline void ob_toupper_utf8mb4(ObUnicaseInfo *uni_plane, ob_wc_t *wc) { - ob_page_help_utf8mb4(upper_plane, wchar); + if (*wc <= uni_plane->maxchar) { + const ObUnicaseInfoChar *page = uni_plane->page[(*wc >> 8)]; + if (OB_NOT_NULL(page)) { + *wc= page[*wc & 0xFF].toupper; + } + } + return; } - -static size_t ob_caseup_utf8mb4(const ObCharsetInfo *cs, - char *src, size_t srclen, - char *dst, size_t dstlen) +static size_t ob_caseup_utf8mb4(const ObCharsetInfo *cs, char *src, size_t srclen, + char *dst, size_t dstlen) { - int ret = OB_CS_SUCCESS; - ob_wc_t wchar; - int srcres = 0; - int dstres = 0; - char *srcend= src + srclen; - char *dstend= dst + dstlen; - char *dstbegin = dst; - uint32_t **upper_pages= cs->caseinfo->upper_pages; - while (src < srcend && dst < dstend) { - if (OB_LIKELY((srcres = ob_mb_wc_utf8mb4((unsigned char *) src, - (unsigned char*) srcend, &wchar)) > 0)) { - ob_toupper_utf8mb4(upper_pages, &wchar); - if (OB_UNLIKELY((dstres = ob_wc_mb_utf8mb4(wchar, (unsigned char*) dst, - (unsigned char*) dstend)) <= 0)) { - ret = OB_CS_ERR_ILLEGAL_UNICODE; - break; - } + ob_wc_t w_char; + int srcres = 0, dstres = 0; + char *srcend = src + srclen, *dstend = dst + dstlen, *dst0 = dst; + ObUnicaseInfo *uni_plane= cs->caseinfo; + ob_charset_assert(src != dst || cs->caseup_multiply == 1); + while ((src < srcend)) { + if ((srcres = ob_mb_wc_utf8mb4(cs, &w_char, (unsigned char *) src, (unsigned char*) srcend)) <= 0) { + break; + } + ob_toupper_utf8mb4(uni_plane, &w_char); + if ((dstres = ob_wc_mb_utf8mb4(cs, w_char, (unsigned char*) dst, (unsigned char*) dstend)) <= 0) { + break; } else { - *dst = *src; - srcres = 1; - dstres = 1; + src += srcres; + dst += dstres; } - src+= srcres; - dst+= dstres; } - return OB_CS_SUCC(ret) ? (size_t) (dst - dstbegin) : ret; + return (size_t) (dst - dst0); } static size_t ob_casedn_utf8mb4(const ObCharsetInfo *cs, - char *src, size_t srclen, - char *dst, size_t dstlen) + char *src, size_t srclen, + char *dst, size_t dstlen) { - int ret = OB_CS_SUCCESS; - ob_wc_t wchar; - int srcres = 0; - int dstres = 0; - char *srcend= src + srclen; - char *dstend= dst + dstlen; - char *dstbegin = dst; - uint32_t **lower_pages= cs->caseinfo->lower_pages; - while (src < srcend && dst < dstend) { - if (OB_LIKELY((srcres = ob_mb_wc_utf8mb4((unsigned char *) src, - (unsigned char*) srcend, &wchar)) > 0)) { - ob_tolower_utf8mb4(lower_pages, &wchar); - if (OB_UNLIKELY((dstres = ob_wc_mb_utf8mb4(wchar, (unsigned char*) dst, - (unsigned char*) dstend)) <= 0)) { - ret = OB_CS_ERR_ILLEGAL_UNICODE; - break; - } + ob_wc_t w_char; + int srcres = 0, dstres = 0; + char *srcend = src + srclen, *dstend= dst + dstlen, *dst0= dst; + ObUnicaseInfo *uni_plane= cs->caseinfo; + ob_charset_assert(src != dst || cs->casedn_multiply == 1); + while ((src < srcend) && + (srcres = ob_mb_wc_utf8mb4(cs, &w_char, + (unsigned char*) src, (unsigned char*) srcend)) > 0) { + ob_tolower_utf8mb4(uni_plane, &w_char); + if ((dstres = ob_wc_mb_utf8mb4(cs, w_char, (unsigned char*) dst, (unsigned char*) dstend)) <= 0) { + break; } else { - *dst = *src; - srcres = 1; - dstres = 1; + src += srcres; + dst += dstres; } - src+= srcres; - dst+= dstres; } - return OB_CS_SUCC(ret) ? (size_t) (dst - dstbegin) : ret; + return (size_t) (dst - dst0); } -static inline int bincmp_utf8mb4(const unsigned char *src, size_t src_len, - const unsigned char *dst, size_t dst_len) +static inline int bincmp_utf8mb4(const unsigned char *src, const unsigned char *se, + const unsigned char *dst, const unsigned char *te) { - int min_len= src_len < dst_len ? src_len : dst_len; - int cmp= memcmp(src, dst, min_len); - return !!(cmp) ? cmp : src_len - dst_len; + int srclen = (int) (se - src), dstlen= (int) (te - dst); + int len = srclen < dstlen ? srclen : dstlen; + int cmp = memcmp(src, dst, len); + return cmp ? cmp : srclen - dstlen; } -static inline void ob_tosort_unicode(uint32_t **sort_plane, ob_wc_t *wchar) +static inline void ob_tosort_unicode(ObUnicaseInfo *uni_plane, ob_wc_t *wc, unsigned int flags) { - if (*wchar <= 0xFFFF) { - uint32_t *page = sort_plane[*wchar >> 8]; - if (OB_NOT_NULL(page)) { - *wchar= page[*wchar & 0xFF]; - } + if (*wc <= uni_plane->maxchar) { + const ObUnicaseInfoChar *page; + if (OB_NOT_NULL(page = uni_plane->page[*wc >> 8])) { + *wc= (flags & OB_CS_LOWER_SORT) ? + page[*wc & 0xFF].tolower : + page[*wc & 0xFF].sort; + } } else { - *wchar = OB_CS_REPLACEMENT_CHARACTER; + *wc = OB_CS_REPLACEMENT_CHARACTER; } } static int ob_strnncoll_utf8mb4(const ObCharsetInfo *cs, - const unsigned char *src, size_t src_len, - const unsigned char *dst, size_t dst_len) + const unsigned char *src, size_t srclen, + const unsigned char *dst, size_t dstlen, + bool t_is_prefix) +{ + ob_wc_t src_wc = 0, dst_wc = 0; + const unsigned char *se = src + srclen; + const unsigned char *te = dst + dstlen; + ObUnicaseInfo *uni_plane = cs->caseinfo; + while ( src < se && dst < te ) { + int s_res = ob_mb_wc_utf8mb4(cs, &src_wc, src, se); + int t_res = ob_mb_wc_utf8mb4(cs, &dst_wc, dst, te); + if ( s_res <= 0 || t_res <= 0 ) { + return bincmp_utf8mb4(src, se, dst, te); + } + ob_tosort_unicode(uni_plane, &src_wc, cs->state); + ob_tosort_unicode(uni_plane, &dst_wc, cs->state); + if ( src_wc != dst_wc ) { + return src_wc > dst_wc ? 1 : -1; + } else { + src += s_res; + dst += t_res; + } + } + return (int) (t_is_prefix ? (dst - te) : ((se - src) - (te - dst))); +} + +int __attribute__ ((noinline)) ob_strnncollsp_utf8mb4_help( + const unsigned char **s_, size_t srclen, + const unsigned char **t_, size_t dstlen, + const unsigned char **se_, const unsigned char **te_, + bool diff_if_only_endspace_difference, int *has_returned, int *res_) { - ob_wc_t src_wchar = 0; - ob_wc_t dst_wchar = 0; - const unsigned char *src_end = src + src_len; - const unsigned char *dst_end = dst + dst_len; - uint32_t **sort_pages = cs->caseinfo->sort_pages; - while (src < src_end && dst < dst_end) { - int src_res = ob_mb_wc_utf8mb4(src, src_end, &src_wchar); - int dst_res = ob_mb_wc_utf8mb4(dst, dst_end, &dst_wchar); - if (src_res <= 0 || dst_res <= 0) { - /* Incorrect string, compare bytewise */ - return bincmp_utf8mb4(src, src_end-src, dst, dst_end-dst); + const unsigned char *src = *s_; + const unsigned char *dst = *t_; + const unsigned char *se = *se_; + const unsigned char *te = *te_; + int res = *res_; + *has_returned = 0; + int swap= 1; + if (srclen != dstlen) { + if (diff_if_only_endspace_difference) { + res= 1; + } + if (srclen < dstlen) { + srclen= dstlen; + src= dst; + se= te; + swap= -1; + res= -res; } - ob_tosort_unicode(sort_pages, &src_wchar); - ob_tosort_unicode(sort_pages, &dst_wchar); - if (src_wchar != dst_wchar) { - return src_wchar > dst_wchar ? 1 : -1; + while (src < se) { + if (*src != ' ') { + *has_returned = 1; + break; + } + src++; } - src+= src_res; - dst+= dst_res; } - return (int) ((src_end - src) - (dst_end - dst)); + *s_ = src; + *t_ = dst; + *se_ = se; + *te_ = te; + *res_ = res; + if (*has_returned == 1) { + return (!diff_if_only_endspace_difference && (*src < ' ')) ? -swap : swap; + } + return 0; } static int ob_strnncollsp_utf8mb4(const ObCharsetInfo *cs, - const unsigned char *src, size_t src_len, - const unsigned char *dst, size_t dst_len) + const unsigned char *src, size_t srclen, + const unsigned char *dst, size_t dstlen, + bool diff_if_only_endspace_difference) { - int res = 0; - ob_wc_t src_wchar = 0; - ob_wc_t dst_wchar = 0; - const unsigned char *src_end = src + src_len; - const unsigned char *dst_end = dst + dst_len; - uint32_t **sort_pages = cs->caseinfo->sort_pages; - while (src < src_end && dst < dst_end) { - int src_res = ob_mb_wc_utf8mb4(src, src_end, &src_wchar); - int dst_res = ob_mb_wc_utf8mb4(dst, dst_end, &dst_wchar); - if (src_res <= 0 || dst_res <= 0) { - /* Incorrect string, compare bytewise */ - return bincmp_utf8mb4(src, src_end-src, dst, dst_end-dst); + int res; + ob_wc_t src_wc = 0, dst_wc = 0; + const unsigned char *se= src + srclen, *te= dst + dstlen; + ObUnicaseInfo *uni_plane= cs->caseinfo; + while ( src < se && dst < te ) { + int s_res= ob_mb_wc_utf8mb4(cs, &src_wc, src, se); + int t_res= ob_mb_wc_utf8mb4(cs, &dst_wc, dst, te); + if ( s_res <= 0 || t_res <= 0 ) { + return bincmp_utf8mb4(src, se, dst, te); } - ob_tosort_unicode(sort_pages, &src_wchar); - ob_tosort_unicode(sort_pages, &dst_wchar); - if (src_wchar != dst_wchar) { - return src_wchar > dst_wchar ? 1 : -1; + ob_tosort_unicode(uni_plane, &src_wc, cs->state); + ob_tosort_unicode(uni_plane, &dst_wc, cs->state); + if ( src_wc != dst_wc ) { + return src_wc > dst_wc ? 1 : -1; + } else { + src +=s_res; + dst +=t_res; } - src+= src_res; - dst+= dst_res; } - src_len= (size_t) (src_end - src); - dst_len= (size_t) (dst_end - dst); - if (src_len != dst_len) { - int swap = 1; - if (src_len < dst_len) { - src_len = dst_len; - src = dst; - src_end = dst_end; - swap = -1; - res = -res; + srclen = (size_t) (se-src); + dstlen = (size_t) (te-dst); + res= 0; + int has_returned = 0; + int tmp = ob_strnncollsp_utf8mb4_help( + &src, srclen, + &dst, dstlen, + &se, &te, + diff_if_only_endspace_difference, &has_returned, &res); + return has_returned ? tmp : res; +} + +static size_t ob_strxfrm_pad_nweights_unicode(unsigned char *str, unsigned char *strend, size_t nweights) +{ + ob_charset_assert(str && str <= strend); + unsigned char *str0 = str; + for (; str < strend && nweights; nweights--) { + *str++= 0x00; + if (str < strend) { + *str++= 0x20; } - for (; src < src_end; src++) { - if (*src != ' ') return (*src < ' ') ? -swap : swap; + } + return str - str0; +} + +static size_t ob_strxfrm_pad_unicode(unsigned char *str, unsigned char *strend) +{ + unsigned char *str0= str; + ob_charset_assert(str && str <= strend); + while (str < strend) { + *str++= 0x00; + if (str < strend) { + *str++= 0x20; } } - return res; + return str - str0; +} + +void ob_strnxfrm_unicode_help(unsigned char **dst, + unsigned char **de, + unsigned int nweights, + unsigned int flags, + unsigned char **dst0) +{ + if (*dst < *de && nweights && (flags & OB_STRXFRM_PAD_WITH_SPACE)) + *dst += ob_strxfrm_pad_nweights_unicode(*dst, *de, nweights); + ob_strxfrm_desc_and_reverse(*dst0, *dst, flags, 0); + if ((flags & OB_STRXFRM_PAD_TO_MAXLEN) && *dst < *de) { + *dst += ob_strxfrm_pad_unicode(*dst, *de); + } + return; } size_t ob_strnxfrm_unicode(const ObCharsetInfo *cs, - unsigned char *dst, size_t dst_len, uint32_t nweights, - const unsigned char *src, size_t src_len, int *is_valid_unicode) + unsigned char *dst, size_t dstlen, unsigned int nweights, + const unsigned char *src, size_t srclen, unsigned int flags, bool *is_valid_unicode) { - ob_wc_t wchar = 0; - int cur_len = 0; - unsigned char *dst_begin= dst; - unsigned char *dst_end= dst + dst_len; - const unsigned char *src_end= src + src_len; - uint32_t **sort_pages= (cs->state & OB_CS_BINSORT) ? NULL : cs->caseinfo->sort_pages; + ob_wc_t wc; + int res; + unsigned char *dst0= dst; + unsigned char *de= dst + dstlen; + const unsigned char *se= src + srclen; + ObUnicaseInfo *uni_plane= (cs->state & OB_CS_BINSORT) ? NULL : cs->caseinfo; + wc = 0; + ob_charset_assert(src); *is_valid_unicode = 1; - - for (; dst < dst_end && nweights; nweights--) { - if ((cur_len = cs->cset->mb_wc(src, src_end, &wchar)) <= 0) { - if (src < src_end) { + for (; dst < de && nweights; nweights--) { + if ((res= cs->cset->mb_wc(cs, &wc, src, se)) <= 0) { + if (src < se) { *is_valid_unicode = 0; } break; } - src += cur_len; - if (sort_pages) { - ob_tosort_unicode(sort_pages, &wchar); + src+= res; + if (OB_NOT_NULL(uni_plane)) { + ob_tosort_unicode(uni_plane, &wc, cs->state); } - if ((cur_len = cs->cset->wc_mb(wchar, dst, dst_end)) <= 0) { + if ((res= cs->cset->wc_mb(cs, wc, dst, de)) <= 0) { break; + } else { + dst+= res; } - dst += cur_len; } - //ob_strnxfrm_unicode_help(&dst, &dst_end, nweights, &dst0); - return dst - dst_begin; + ob_strnxfrm_unicode_help(&dst,&de, nweights, flags, &dst0); + return dst - dst0; } -//============================================================== +static int ob_wildcmp_unicode_impl_help(const ObCharsetInfo *cs, + const char **str_,const char **str_end_, + ob_charset_conv_mb_wc mb_wc, + const char **wild_str_, const char **wild_end_, + int escape_char, int w_one, int w_many, + ob_wc_t *s_wc_, + ob_wc_t *w_wc_, + int *scan_, + int *result_, + ObUnicaseInfo *weights, + int *has_returned) +{ + int ret = 0; + const char *str = *str_; + const char *str_end = *str_end_; + const char *wild_str = *wild_str_; + const char *wild_end = *wild_end_; + ob_wc_t src_wc = *s_wc_; + ob_wc_t w_wc = *w_wc_; + int scan = *scan_; + int result = *result_; + *has_returned = 0; + while (1) { + bool escaped= 0; + if ((scan= mb_wc(cs, &w_wc, (const unsigned char*)wild_str, + (const unsigned char*)wild_end)) <= 0) { + ret = 1; + *has_returned = 1; + break; + } else if (w_wc == (ob_wc_t) w_many) { + result = 1; + break; + } + wild_str += scan; + if (w_wc == (ob_wc_t) escape_char && wild_str < wild_end) { + if ((scan= mb_wc(cs, &w_wc, (const unsigned char*)wild_str, + (const unsigned char*)wild_end)) <= 0) { + ret = 1; + *has_returned = 1; + break; + } else { + wild_str += scan; + escaped = 1; + } + } + if ((scan = mb_wc(cs, &src_wc, (const unsigned char*)str, + (const unsigned char*)str_end)) <= 0) { + ret = 1; + *has_returned = 1; + break; + } else { + str += scan; + } + + if (!escaped && w_wc == (ob_wc_t) w_one) { + result = 1; + } else { + if (weights) { + ob_tosort_unicode(weights, &src_wc, cs->state); + ob_tosort_unicode(weights, &w_wc, cs->state); + } + if (src_wc != w_wc) { + ret = 1; + *has_returned = 1; + break; + } + } + if (wild_str == wild_end) { + ret = (str != str_end); + *has_returned = 1; + break; + } + } + *str_ = str; + *str_end_ = str_end; + *wild_str_ = wild_str; + *wild_end_ = wild_end; + *s_wc_ = src_wc; + *w_wc_ = w_wc; + *scan_ = scan; + *result_ = result; + return ret; +} static int ob_wildcmp_unicode_impl(const ObCharsetInfo *cs, const char *str,const char *str_end, - const char *wildstr,const char *wildend, - int escape, int w_one, int w_many, - uint32_t **weights, int recurse_level) + const char *wild_str,const char *wild_end, + int escape_char, int w_one, int w_many, + ObUnicaseInfo *weights, int recurse_level) { - int result= -1; /* Not found, using wildcards */ - ob_wc_t s_wc = 0; + int result= -1; + ob_wc_t src_wc = 0; ob_wc_t w_wc = 0; - int scan_len = 0; - ob_charset_conv_mb_wc mb_wc = cs->cset->mb_wc; - - /*if (ob_string_stack_guard && ob_string_stack_guard(recurse_level)) - return 1;*/ - while (wildstr != wildend) { - while (1) - { - int escaped= 0; - if ((scan_len = mb_wc((const unsigned char*)wildstr, - (const unsigned char*)wildend, &w_wc)) <= 0) { - return 1; - } - if (w_wc == (uint32_t) w_many) { - result = 1; /* Found an anchor char */ - break; - } - wildstr += scan_len; - - if (w_wc == (uint32_t) escape && wildstr < wildend) { - if ((scan_len = mb_wc((const unsigned char*)wildstr, - (const unsigned char*)wildend, &w_wc)) <= 0) { - return 1; - } - wildstr += scan_len; - escaped = 1; - } - - if ((scan_len = mb_wc((const unsigned char*)str, - (const unsigned char*)str_end, &s_wc)) <= 0) { - return 1; - } - str += scan_len; - - if (!escaped && w_wc == (uint32_t) w_one) { - result = 1; /* Found an anchor char */ - } else { - if (weights) { - ob_tosort_unicode(weights, &s_wc); - ob_tosort_unicode(weights, &w_wc); - } - if (s_wc != w_wc) { - return 1; /* No match */ - } - } - if (wildstr == wildend) { - return (str != str_end); /* Match if both are at end */ - } - } - - if (w_wc == (uint32_t) w_many) { /* Found w_many */ - /* Remove any '%' and '_' from the wild search string */ - for ( ; wildstr != wildend ; ) { - if ((scan_len = mb_wc((const unsigned char*)wildstr, - (const unsigned char*)wildend, &w_wc)) <= 0) { + int scan = 0; + int (*mb_wc)(const ObCharsetInfo *, ob_wc_t *, const unsigned char *, const unsigned char *); + mb_wc= cs->cset->mb_wc; + + while (wild_str != wild_end) { + int has_returned = 0; + int tmp = ob_wildcmp_unicode_impl_help(cs, + &str,&str_end, + mb_wc, + &wild_str, &wild_end, + escape_char, + w_one, + w_many, + &src_wc, + &w_wc, + &scan, + &result, + weights, + &has_returned); + if (has_returned == 1) { + return tmp; + } else if (w_wc == (ob_wc_t) w_many) { + while (wild_str != wild_end) { + if ((scan= mb_wc(cs, &w_wc, (const unsigned char*)wild_str, + (const unsigned char*)wild_end)) <= 0) { return 1; - } - - if (w_wc == (uint32_t)w_many) { - wildstr+= scan_len; + } else if (w_wc == (ob_wc_t)w_many) { + wild_str+= scan; continue; - } - - if (w_wc == (uint32_t)w_one) { - wildstr+= scan_len; - if ((scan_len = mb_wc((const unsigned char*)str, - (const unsigned char*)str_end, &s_wc)) <= 0) { + } else if (w_wc == (ob_wc_t)w_one) { + wild_str+= scan; + if ((scan= mb_wc(cs, &src_wc, (const unsigned char*)str, + (const unsigned char*)str_end)) <=0) { return 1; + } else { + str+= scan; + continue; } - str+= scan_len; - continue; } - break; /* Not a wild character */ - } - - if (wildstr == wildend) { - return 0; /* Ok if w_many is last */ + break; } - if (str == str_end) { + if (wild_str == wild_end) { + return 0; + } else if (str == str_end) { return -1; - } - - if ((scan_len = mb_wc((const unsigned char*)wildstr, - (const unsigned char*)wildend, &w_wc)) <= 0) { + } else if ((scan= mb_wc(cs, &w_wc, (const unsigned char*)wild_str, + (const unsigned char*)wild_end)) <=0) { return 1; + } else { + wild_str+= scan; } - wildstr+= scan_len; - if (w_wc == (uint32_t)escape) { - if (wildstr < wildend) { - if ((scan_len = mb_wc((const unsigned char*)wildstr, - (const unsigned char*)wildend, &w_wc)) <= 0) { + if (w_wc == (ob_wc_t)escape_char) { + if (wild_str < wild_end) { + if ((scan= mb_wc(cs, &w_wc, (const unsigned char*)wild_str, + (const unsigned char*)wild_end)) <=0) { return 1; + } else { + wild_str+= scan; } - wildstr+= scan_len; } } - /* Skip until the first character from wildstr is found */ while (1) { while (str != str_end) { - if ((scan_len = mb_wc((const unsigned char*)str, - (const unsigned char*)str_end, &s_wc)) <= 0) { + if ((scan= mb_wc(cs, &src_wc, (const unsigned char*)str, + (const unsigned char*)str_end)) <=0) { return 1; + } else if (weights) { + ob_tosort_unicode(weights, &src_wc, cs->state); + ob_tosort_unicode(weights, &w_wc, cs->state); } - if (weights) { - ob_tosort_unicode(weights, &s_wc); - ob_tosort_unicode(weights, &w_wc); - } - - if (s_wc == w_wc) { + if (src_wc == w_wc) { break; + } else { + str+= scan; } - str+= scan_len; } if (str == str_end) { return -1; + } else { + str+= scan; } - - str+= scan_len; - result = ob_wildcmp_unicode_impl(cs, str, str_end, wildstr, wildend, - escape, w_one, w_many, - weights, recurse_level + 1); - if (result <= 0) - return result; + result= ob_wildcmp_unicode_impl(cs, str, str_end, wild_str, wild_end, + escape_char, w_one, w_many, + weights, recurse_level + 1); + if (result <= 0) return result; } } } @@ -1919,64 +2175,57 @@ static int ob_wildcmp_unicode_impl(const ObCharsetInfo *cs, int ob_wildcmp_unicode(const ObCharsetInfo *cs, const char *str,const char *str_end, - const char *wildstr,const char *wildend, - int escape, int w_one, int w_many, - uint32_t **weights) + const char *wild_str,const char *wild_end, + int escape_char, int w_one, int w_many, + ObUnicaseInfo *weights) { - return ob_wildcmp_unicode_impl(cs, str, str_end, wildstr, wildend, escape, w_one, w_many, weights, 1); + return ob_wildcmp_unicode_impl(cs, str, str_end, wild_str, wild_end, escape_char, w_one, w_many, weights, 1); } static int ob_wildcmp_utf8mb4(const ObCharsetInfo *cs, - const char *str, const char *strend, - const char *wildstr, const char *wildend, - int escape, int w_one, int w_many) + const char *str, const char *strend, + const char *wild_str, const char *wild_end, + int escape_char, int w_one, int w_many) { - return ob_wildcmp_unicode(cs, str, strend, wildstr, wildend, escape, w_one, w_many, - cs->caseinfo->sort_pages); + return ob_wildcmp_unicode(cs, str, strend, wild_str, wild_end, escape_char, w_one, w_many, cs->caseinfo); } -//====================================================================== -static inline void ob_hash_add(uint64_t *n1, uint64_t *n2, uint32_t ch) + +static inline void ob_hash_add(unsigned long int *n1, unsigned long int *n2, unsigned int ch) { n1[0]^= (((n1[0] & 63) + n2[0]) * (ch)) + (n1[0] << 8); n2[0]+= 3; } -static void ob_hash_sort_utf8mb4(const ObCharsetInfo *cs, const unsigned char *s, size_t slen, - uint64_t *n1, uint64_t *n2, - const int calc_end_space, hash_algo hash_algo) +static void ob_hash_sort_utf8mb4(const ObCharsetInfo *cs, const unsigned char *src, size_t srclen, + unsigned long int *n1, unsigned long int *n2, const bool calc_end_space, hash_algo hash_algo) { ob_wc_t wc; int res; - const unsigned char *e= s + slen; - uint32_t **sort_pages= cs->caseinfo->sort_pages; + const unsigned char *end= src + srclen; + ObUnicaseInfo *uni_plane= cs->caseinfo; int length = 0; unsigned char data[HASH_BUFFER_LENGTH]; - /* - Remove trailing spaces if calc_end_space is false: for char(Oracle/MySql mode) or Varchar(MySql mode). - We do this to be able to compare 'A ' and 'A' as identical - */ if (!calc_end_space) { - while (e > s && e[-1] == ' ') { - e--; - } + while (end > src && end[-1] == ' ') + end--; } if (NULL == hash_algo) { - while ((res= ob_mb_wc_utf8mb4((unsigned char*) s, (unsigned char*) e, &wc)) > 0) { - ob_tosort_unicode(sort_pages, &wc); - ob_hash_add(n1, n2, (uint32_t) (wc & 0xFF)); - ob_hash_add(n1, n2, (uint32_t) (wc >> 8) & 0xFF); + while ((res= ob_mb_wc_utf8mb4(cs, &wc, (unsigned char*) src, (unsigned char*) end)) > 0) { + ob_tosort_unicode(uni_plane, &wc, cs->state); + ob_hash_add(n1, n2, (unsigned int) (wc & 0xFF)); + ob_hash_add(n1, n2, (unsigned int) (wc >> 8) & 0xFF); if (wc > 0xFFFF) { - ob_hash_add(n1, n2, (uint32_t) (wc >> 16) & 0xFF); + ob_hash_add(n1, n2, (unsigned int) (wc >> 16) & 0xFF); } - s+= res; + src+= res; } } else { - while ((res= ob_mb_wc_utf8mb4((unsigned char*) s, (unsigned char*) e, &wc)) > 0) { - ob_tosort_unicode(sort_pages, &wc); + while ((res= ob_mb_wc_utf8mb4(cs, &wc, (unsigned char*) src, (unsigned char*) end)) > 0) { + ob_tosort_unicode(uni_plane, &wc, cs->state); if (length > HASH_BUFFER_LENGTH - 2 || (HASH_BUFFER_LENGTH - 2 == length && wc > 0xFFFF)) { *n1 = hash_algo((void*) &data, length, *n1); length = 0; @@ -1986,7 +2235,7 @@ static void ob_hash_sort_utf8mb4(const ObCharsetInfo *cs, const unsigned char *s if (wc > 0xFFFF) { data[length++] = (unsigned char)(wc >> 16); } - s+= res; + src+= res; } if (length > 0) { *n1 = hash_algo((void*) &data, length, *n1); @@ -1994,12 +2243,9 @@ static void ob_hash_sort_utf8mb4(const ObCharsetInfo *cs, const unsigned char *s } } -//====================================================================== - size_t ob_strnxfrm_unicode_full_bin(const ObCharsetInfo *cs, - unsigned char *dst, size_t dstlen, uint32_t nweights, - const unsigned char *src, size_t srclen, - int *is_valid_unicode) + unsigned char *dst, size_t dstlen, unsigned int nweights, + const unsigned char *src, size_t srclen, unsigned int flags, bool *is_valid_unicode) { ob_wc_t wc; unsigned char *dst0= dst; @@ -2011,27 +2257,198 @@ size_t ob_strnxfrm_unicode_full_bin(const ObCharsetInfo *cs, *is_valid_unicode = 1; for ( ; dst < de && nweights; nweights--) { int res; - if ((res= cs->cset->mb_wc(src, se, &wc)) <= 0) { + if ((res= cs->cset->mb_wc(cs, &wc, src, se)) <= 0) { + if (src < se) { + *is_valid_unicode = 0; + } + break; + } else { + src+= res; + } + if ((res= cs->cset->wc_mb(cs, wc, dst, de)) <= 0) { + break; + } else { + dst+= res; + } + } + if (flags & OB_STRXFRM_PAD_WITH_SPACE) { + for ( ; dst < de && nweights; nweights--) { + *dst++= 0x00; + if (dst < de) { + *dst++= 0x00; + if (dst < de) { + *dst++= 0x20; + } + } + } + } + ob_strxfrm_desc_and_reverse(dst0, dst, flags, 0); + if (flags & OB_STRXFRM_PAD_TO_MAXLEN) { + while (dst < de) { + *dst++= 0x00; + if (dst < de) { + *dst++= 0x00; + if (dst < de) { + *dst++= 0x20; + } + } + } + } + return dst - dst0; +} + + +size_t ob_varlen_encoding_for_memcmp(const struct ObCharsetInfo* cs, + uchar* dst, size_t dst_len, uint nweights, + const uchar *src, size_t src_len, + bool *is_valid_unicode, bool is_sort) +{ + ob_wc_t wc; + int res; + uchar *dst0= dst; + uchar *de= dst + dst_len; + const uchar *se= src + src_len; + ObUnicaseInfo *uni_plane= (cs->state & OB_CS_BINSORT) ? NULL : cs->caseinfo; + wc = 0; + ob_charset_assert(src); + *is_valid_unicode = 1; + for (; dst < de && nweights; nweights--) + { + if ((res= cs->cset->mb_wc(cs, &wc, src, se)) <= 0) { if (src < se) { *is_valid_unicode = 0; } break; } src+= res; - if ((res= cs->cset->wc_mb(wc, dst, de)) <= 0) { + // if is 0x000000 + if (wc == 0x00000000) { + res = cs->cset->wc_mb(cs, wc, dst, de); + dst += res; + wc = 0x00000001; + } + if (1 == is_sort && NULL != uni_plane) + ob_tosort_unicode(uni_plane, &wc, cs->state); + // replace code above with code below. + if ((res= cs->cset->wc_mb(cs, wc, dst, de)) <= 0) + break; + dst+= res; + } + // adds 0x00, 0x00 + *dst = 0x00; + *(dst+1) = 0x00; + dst += 2; + //ob_strnxfrm_unicode_help(&dst,&de, nweights, flags, &dst0); + return dst - dst0; +} +uint16_t find_space_char_count(const uchar* src, const uchar* se) +{ + int space_cnt = 1; + while (*(src+space_cnt) == 0x20 && (src+space_cnt)state & OB_CS_BINSORT) ? NULL : cs->caseinfo; + wc = 0; + ob_charset_assert(src); + *is_valid_unicode = 1; + uint16_t space_cnt = 0xFFFF; + for (; dst < de && nweights; nweights--) + { + // for reslovable multiple bytes, only space's first byte is 0x20, + // in utf8 encoding scheme. + if (*src == 0x20) { + space_cnt = find_space_char_count(src, se); + if (space_cnt == 0) break; + *(dst) = 0x20; + if (*(src+space_cnt) > 0x20){ + *(dst+1)=0x21; + // flip + uint16_t tmp_cnt = space_cnt ^ 0xFFFF; + *(dst+2)=*((uchar*)&tmp_cnt+1); + *(dst+3)=*(&tmp_cnt); + } else { + *(dst+1) = 0x19; + *(dst+2)=*((uchar*)&space_cnt+1); + *(dst+3)=*(&space_cnt); + } + dst += 4; + src += space_cnt; + } + if ((res= cs->cset->mb_wc(cs, &wc, src, se)) <= 0) { + if (src < se) { + *is_valid_unicode = 0; + } break; } + src+= res; + if (1 == is_sort && NULL != uni_plane) + ob_tosort_unicode(uni_plane, &wc, cs->state); + // replace code above with code below. + if ((res= cs->cset->wc_mb(cs, wc, dst, de)) <= 0) + break; dst+= res; + //abort(); } - + // adds 0x20, 0x20 + *dst = 0x20; + *(dst+1) = 0x20; + dst += 2; + //ob_strnxfrm_unicode_help(&dst,&de, nweights, flags, &dst0); return dst - dst0; } +size_t ob_strnxfrm_unicode_varlen(const struct ObCharsetInfo* cs, + uchar* dst, size_t dst_len, uint nweights, + const uchar *src, size_t srclen, + bool is_memcmp, bool *is_valid_unicode) +{ + if (is_memcmp) { + return ob_varlen_encoding_for_memcmp(cs, dst, dst_len, nweights, + src, srclen, is_valid_unicode, 1); + } else { + return ob_varlen_encoding_for_spacecmp(cs, dst, dst_len, nweights, + src, srclen, is_valid_unicode, 1); + } +} + +size_t ob_strnxfrm_unicode_full_bin_varlen(const struct ObCharsetInfo* cs, + uchar* dst, size_t dst_len, uint nweights, + const uchar *src, size_t srclen, + bool is_memcmp, bool *is_valid_unicode) +{ + if (is_memcmp) { + return ob_varlen_encoding_for_memcmp(cs, dst, dst_len, nweights, + src, srclen, is_valid_unicode, 0); + } else { + return ob_varlen_encoding_for_spacecmp(cs, dst, dst_len, nweights, + src, srclen, is_valid_unicode, 0); + } +} -//====================================================================== +size_t ob_strnxfrmlen_utf8mb4(const ObCharsetInfo *cs __attribute__((unused)), size_t len) +{ + return (len * 2 + 2) / 4; +} + +size_t ob_strnxfrmlen_unicode_full_bin(const ObCharsetInfo *cs, size_t len) +{ + return ((len + 3) / cs->mbmaxlen) * 3; +} ObCharsetHandler ob_charset_utf8mb4_handler= { ob_ismbchar_utf8mb4, + ob_mbcharlen_utf8mb4, ob_numchars_mb, ob_charpos_mb, ob_max_bytes_charpos_mb, @@ -2043,6 +2460,8 @@ ObCharsetHandler ob_charset_utf8mb4_handler= ob_caseup_utf8mb4, ob_casedn_utf8mb4, ob_fill_8bit, + ob_strntol_8bit, + ob_strntoul_8bit, ob_strntoll_8bit, ob_strntoull_8bit, ob_strntod_8bit, @@ -2059,6 +2478,7 @@ static ObCollationHandler ob_collation_utf8mb4_general_ci_handler= ob_wildcmp_utf8mb4, ob_instr_mb, ob_hash_sort_utf8mb4, + ob_propagate_complex }; static ObCollationHandler ob_collation_utf8mb4_bin_handler = @@ -2070,65 +2490,68 @@ static ObCollationHandler ob_collation_utf8mb4_bin_handler = ob_wildcmp_mb_bin, ob_instr_mb, ob_hash_sort_mb_bin, + ob_propagate_simple }; ObCharsetInfo ob_charset_utf8mb4_general_ci= { - 45,0,0, /* number */ - OB_CS_COMPILED|OB_CS_PRIMARY|OB_CS_STRNXFRM|OB_CS_UNICODE|OB_CS_UNICODE_SUPPLEMENT, /* state */ - OB_UTF8MB4, /* cs name */ - OB_UTF8MB4_GENERAL_CI,/* name */ - "UTF-8 Unicode", /* comment */ - NULL, /* tailoring */ - ctype_utf8mb4, /* ctype */ - to_lower_utf8mb4, /* to_lower */ - to_upper_utf8mb4, /* to_upper */ - to_upper_utf8mb4, /* sort_order */ - &utf8_unicase_pages,/* caseinfo */ - NULL, /* state_map */ - NULL, /* ident_map */ - 1, /* strxfrm_multiply */ - 1, /* caseup_multiply */ - 1, /* casedn_multiply */ - 1, /* mbminlen */ - 4, /* mbmaxlen */ - 0, /* min_sort_char */ - 0xFFFF, /* max_sort_char */ - ' ', /* pad char */ - 0, /* escape_with_backslash_is_dangerous */ - 1, /* levels_for_compare */ - 1, /* levels_for_order */ + 45,0,0, + OB_CS_COMPILED|OB_CS_PRIMARY|OB_CS_STRNXFRM|OB_CS_UNICODE|OB_CS_UNICODE_SUPPLEMENT, + OB_UTF8MB4, + OB_UTF8MB4_GENERAL_CI, + "UTF-8 Unicode", + NULL, + ctype_utf8mb4, + to_lower_utf8mb4, + to_upper_utf8mb4, + to_upper_utf8mb4, + NULL, + &ob_unicase_default, + NULL, + NULL, + 1, + 1, + 1, + 1, + 4, + 0, + 0xFFFF, + ' ', + 0, + 1, + 1, &ob_charset_utf8mb4_handler, &ob_collation_utf8mb4_general_ci_handler }; ObCharsetInfo ob_charset_utf8mb4_bin= { - 46,0,0, /* number */ + 46,0,0, OB_CS_COMPILED|OB_CS_BINSORT|OB_CS_STRNXFRM| - OB_CS_UNICODE|OB_CS_UNICODE_SUPPLEMENT, /* state */ - OB_UTF8MB4, /* cs name */ - OB_UTF8MB4_BIN, /* name */ - "UTF-8 Unicode", /* comment */ - NULL, /* tailoring */ - ctype_utf8mb4, /* ctype */ - to_lower_utf8mb4, /* to_lower */ - to_upper_utf8mb4, /* to_upper */ - NULL, /* sort_order */ - &utf8_unicase_pages,/* caseinfo */ - NULL, /* state_map */ - NULL, /* ident_map */ - 1, /* strxfrm_multiply */ - 1, /* caseup_multiply */ - 1, /* casedn_multiply */ - 1, /* mbminlen */ - 4, /* mbmaxlen */ - 0, /* min_sort_char */ - 0xFFFF, /* max_sort_char */ - ' ', /* pad char */ - 0, /* escape_with_backslash_is_dangerous */ - 1, /* levels_for_compare */ - 1, /* levels_for_order */ + OB_CS_UNICODE|OB_CS_UNICODE_SUPPLEMENT, + OB_UTF8MB4, + OB_UTF8MB4_BIN, + "UTF-8 Unicode", + NULL, + ctype_utf8mb4, + to_lower_utf8mb4, + to_upper_utf8mb4, + NULL, + NULL, + &ob_unicase_default, + NULL, + NULL, + 1, + 1, + 1, + 1, + 4, + 0, + 0xFFFF, + ' ', + 0, + 1, + 1, &ob_charset_utf8mb4_handler, &ob_collation_utf8mb4_bin_handler }; diff --git a/src/lib/charset/ob_dtoa.c b/src/lib/charset/ob_dtoa.c index c2e28fa00366a17b6bd3103499d0b1b8334ca2b7..96d928529ca34e17c054b002e0a42e3796bce9b5 100644 --- a/src/lib/charset/ob_dtoa.c +++ b/src/lib/charset/ob_dtoa.c @@ -8,63 +8,32 @@ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PubL v2 for more details. - * - * ************************************************************** - * - * This file incorporates work covered by the following copyright and - * permission notice: - * - * The author of this software is David M. Gay. - * - * Copyright (c) 1991, 2000, 2001 by Lucent Technologies. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. */ -#include "lib/charset/ob_dtoa.h" -#include "lib/charset/ob_mysql_global.h" - -#define NOT_FIXED_DEC 31 /* - We want to use the 'e' format in some cases even if we have enough space - for the 'f' one just to mimic sprintf("%.15g") behavior for large integers, - and to improve it for numbers < 10^(-4). - That is, for |x| < 1 we require |x| >= 10^(-15), and for |x| > 1 we require - it to be integer and be <= 10^DBL_DIG for the 'f' format to be used. - We don't lose precision, but make cases like "1e200" or "0.00001" look nicer. +* +* Version: $Id +* +* Authors: +* - initial release +* */ -#define MAX_DECPT_FOR_F_FORMAT DBL_DIG -//================================================== -/** - Appears to suffice to not call malloc() in most cases. - @todo - see if it is possible to get rid of malloc(). - this constant is sufficient to avoid malloc() on all inputs I have tried. -*/ - -#define DTOA_BUF_MAX_SIZE (460 * sizeof(void *)) +#include "lib/charset/ob_dtoa.h" +#include "lib/charset/ob_mysql_global.h" -/* Magic value returned by dtoa() to indicate overflow */ #define DTOA_OVERFLOW 9999 -#define SIZEOF_CHARP 8 - -#define OB_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1)) +#define MAX_DECPT_FOR_F_FORMAT DBL_DIG +#define NOT_FIXED_DEC 31 +#define DTOA_BUF_MAX_SIZE (460 * sizeof(void *)) +#define Scale_Bit 0x10 +#define n_bigtens 5 static double ob_strtod_int(const char *, char **, int *, char *, size_t); static char *dtoa(double, int, int, int *, int *, char **, char *, size_t); static void dtoa_free(char *, char *, size_t); -size_t ob_fcvt_overflow(char *to, ob_bool *error) +size_t ob_fcvt_overflow(char *to, bool *error) { *to++= '0'; *to= '\0'; @@ -106,47 +75,14 @@ void ob_fcvt_help(char **end, char **dst, char **dend, int sign, int decpt, { if (len <= decpt && dst_ptr < dend_ptr) *dst_ptr++= '.'; - for (i= *precision - MY_MAX(0, (len - decpt)); i > 0 && dst_ptr < dend_ptr; i--) + for (i= *precision - OB_MAX(0, (len - decpt)); i > 0 && dst_ptr < dend_ptr; i--) *dst_ptr++= '0'; } *dst = dst_ptr; } } - -/** - @brief - Converts a given floating point number to a zero-terminated string - representation using the 'f' format. - - @details - This function is a wrapper around dtoa() to do the same as - sprintf(to, "%-.*f", precision, x), though the conversion is usually more - precise. The only difference is in handling [-,+]infinity and nan values, - in which case we print '0\0' to the output string and indicate an overflow. - - @param x the input floating point number. - @param precision the number of digits after the decimal point. - All properties of sprintf() apply: - - if the number of significant digits after the decimal - point is less than precision, the resulting string is - right-padded with zeros - - if the precision is 0, no decimal point appears - - if a decimal point appears, at least one digit appears - before it - @param to pointer to the output buffer. The longest string which - ob_fcvt() can return is FLOATING_POINT_BUFFER bytes - (including the terminating '\0'). - @param error if not NULL, points to a location where the status of - conversion is stored upon return. - FALSE successful conversion - TRUE the input number is [-,+]infinity or nan. - The output string in this case is always '0'. - @return number of written characters (excluding terminating '\0') -*/ - - -size_t ob_fcvt(double x, int precision, int width, char *to, ob_bool *error) +size_t ob_fcvt(double x, int precision, int width, char *to, bool *error) { int decpt, sign; char *res, *end, *dst= to, *dend= to + width; @@ -167,9 +103,8 @@ size_t ob_fcvt(double x, int precision, int width, char *to, ob_bool *error) return dst - to; } -//================================================================================= -size_t ob_gcvt_overflow(char *to, ob_bool *error) +size_t ob_gcvt_overflow(char *to, bool *error) { *to++= '0'; *to= '\0'; @@ -180,7 +115,7 @@ size_t ob_gcvt_overflow(char *to, ob_bool *error) void ob_gcvt_help1(int *width, int *len, char **dend, char **src, char **end, char **dst, int sign, int decpt, char *buf, size_t sizeofbuf, - char **res, ob_bool *error, double x) + char **res, bool *error, double x) { const char *dend_ptr = *dend; int i = 0; @@ -230,13 +165,13 @@ void ob_gcvt_help1(int *width, int *len, char **dend, char **src, void ob_gcvt_help2(int *width, int *len, char **dend, char **src, char **end, char **dst, int sign, int decpt, char *buf, size_t sizeofbuf, - int *exp_len, char **res, ob_bool *error, double x, ob_bool use_oracle_mode) + int *exp_len, char **res, bool *error, double x, bool use_oracle_mode) { const char *dend_ptr = *dend; char *dst_ptr = *dst; char *src_ptr = *src; int decpt_sign= 0; - const int MAX_DOUBLE_SIZE = 30;//-1.2345678912345679e+001 + const int MAX_DOUBLE_SIZE = 30; if (--decpt < 0) { decpt= -decpt; @@ -265,15 +200,10 @@ void ob_gcvt_help2(int *width, int *len, char **dend, char **src, const int need_check_buf = (*dend - *dst) < MAX_DOUBLE_SIZE; if (need_check_buf) { - /* - At this point we are sure we have enough space to put all digits - returned by dtoa - */ if (sign && dst_ptr < dend_ptr) *dst_ptr++= '-'; if (dst_ptr < dend_ptr) *dst_ptr++= *src_ptr++; - //zero const int is_zero = (dst_ptr < dend_ptr && use_oracle_mode && (*(src_ptr - 1) == '0') && ((*len) == 1)); if (is_zero) { if (sign) { @@ -324,14 +254,9 @@ void ob_gcvt_help2(int *width, int *len, char **dend, char **src, } } } else { - /* - At this point we are sure we have enough space to put all digits - returned by dtoa - */ if (sign) *dst_ptr++= '-'; *dst_ptr++= *src_ptr++; - //zero int is_zero = (use_oracle_mode && (*(src_ptr - 1) == '0') && ((*len) == 1)); if (is_zero) { if (sign) { @@ -379,88 +304,25 @@ void ob_gcvt_help2(int *width, int *len, char **dend, char **src, *src = src_ptr; } -/** - @brief - Converts a given floating point number to a zero-terminated string - representation with a given field width using the 'e' format - (aka scientific notation) or the 'f' one. - - @details - The format is chosen automatically to provide the most number of significant - digits (and thus, precision) with a given field width. In many cases, the - result is similar to that of sprintf(to, "%g", x) with a few notable - differences: - - the conversion is usually more precise than C library functions. - - there is no 'precision' argument. instead, we specify the number of - characters available for conversion (i.e. a field width). - - the result never exceeds the specified field width. If the field is too - short to contain even a rounded decimal representation, ob_gcvt() - indicates overflow and truncates the output string to the specified width. - - float-type arguments are handled differently than double ones. For a - float input number (i.e. when the 'type' argument is OB_GCVT_ARG_FLOAT) - we deliberately limit the precision of conversion by FLT_DIG digits to - avoid garbage past the significant digits. - - unlike sprintf(), in cases where the 'e' format is preferred, we don't - zero-pad the exponent to save space for significant digits. The '+' sign - for a positive exponent does not appear for the same reason. - - @param x the input floating point number. - @param type is either OB_GCVT_ARG_FLOAT or OB_GCVT_ARG_DOUBLE. - Specifies the type of the input number (see notes above). - @param width field width in characters. The minimal field width to - hold any number representation (albeit rounded) is 7 - characters ("-Ne-NNN"). - @param to pointer to the output buffer. The result is always - zero-terminated, and the longest returned string is thus - 'width + 1' bytes. - @param error if not NULL, points to a location where the status of - conversion is stored upon return. - FALSE successful conversion - TRUE the input number is [-,+]infinity or nan. - The output string in this case is always '0'. - @return number of written characters (excluding terminating '\0') - - @todo - Check if it is possible and makes sense to do our own rounding on top of - dtoa() instead of calling dtoa() twice in (rare) cases when the resulting - string representation does not fit in the specified field width and we want - to re-round the input number with fewer significant digits. Examples: - - ob_gcvt(-9e-3, ..., 4, ...); - ob_gcvt(-9e-3, ..., 2, ...); - ob_gcvt(1.87e-3, ..., 4, ...); - ob_gcvt(55, ..., 1, ...); - - We do our best to minimize such cases by: - - - passing to dtoa() the field width as the number of significant digits - - - removing the sign of the number early (and decreasing the width before - passing it to dtoa()) - - - choosing the proper format to preserve the most number of significant - digits. -*/ -size_t ob_gcvt(double x, ob_gcvt_arg_type type, int width, char *to, ob_bool *error) +size_t ob_gcvt(double x, ob_gcvt_arg_type type, int width, char *to, bool *error) { return ob_gcvt_strict(x, type, width, to, error, FALSE, FALSE); } size_t ob_gcvt_opt(double x, ob_gcvt_arg_type type, int width, char *to, - ob_bool *error, ob_bool use_oracle_mode) + bool *error, bool use_oracle_mode) { return ob_gcvt_strict(x, type, width, to, error, use_oracle_mode, use_oracle_mode); } -//when use_oracle_mode, float/double has fix format like -//1.23456791E+017/1.2345678901234568E+017, -1.23456791E+017/-1.2345678901234568E+017, -1.0E-017 size_t ob_gcvt_strict(double x, ob_gcvt_arg_type type, int width, char *to, - ob_bool *error, ob_bool use_oracle_mode, ob_bool use_force_e_format) + bool *error, bool use_oracle_mode, bool use_force_e_format) { + int width_check = width; int decpt, sign, len, exp_len; char *res, *src, *end, *dst= to, *dend= dst + width; char buf[DTOA_BUF_MAX_SIZE]; - ob_bool have_space, force_e_format; + bool have_space, force_e_format; const int TMP_MAX_DECPT_FOR_F_FORMAT = MAX_DECPT_FOR_F_FORMAT; if (!(width > 0 && to != NULL)) { return 0; @@ -470,10 +332,9 @@ size_t ob_gcvt_strict(double x, ob_gcvt_arg_type type, int width, char *to, const int ORACLE_FLT_DIG = 9;//mysql FLT_DIG=6 const int ORACLE_DBL_DIG = 17; const int CURR_FLT_DIG = (use_oracle_mode ? ORACLE_FLT_DIG : FLT_DIG); - // in oracle mode, max length of binary_float is 9, binary_double is 17. const int dtoa_width = (type == OB_GCVT_ARG_DOUBLE - ? (use_oracle_mode ? MY_MIN(ORACLE_DBL_DIG, width) : width) - : (MY_MIN(width, CURR_FLT_DIG))); + ? (use_oracle_mode ? OB_MIN(ORACLE_DBL_DIG, width) : width) + : (OB_MIN(width, CURR_FLT_DIG))); const int mode = use_oracle_mode ? 2 : 4; res= dtoa(x, mode, dtoa_width, &decpt, &sign, &end, buf, sizeof(buf)); if (decpt == DTOA_OVERFLOW) { @@ -484,74 +345,16 @@ size_t ob_gcvt_strict(double x, ob_gcvt_arg_type type, int width, char *to, *error= FALSE; src= res; len= end - res; - /* - Number of digits in the exponent from the 'e' conversion. - The sign of the exponent is taken into account separetely, we don't need - to count it here. - */ + exp_len= 1 + (decpt >= 101 || decpt <= -99) + (decpt >= 11 || decpt <= -9); - /* - Do we have enough space for all digits in the 'f' format? - Let 'len' be the number of significant digits returned by dtoa, - and F be the length of the resulting decimal representation. - Consider the following cases: - 1. decpt <= 0, i.e. we have "0.NNN" => F = len - decpt + 2 - 2. 0 < decpt < len, i.e. we have "NNN.NNN" => F = len + 1 - 3. len <= decpt, i.e. we have "NNN00" => F = decpt - */ have_space= (decpt <= 0 ? (len - decpt + 2) : ((decpt > 0 && decpt < len) ? (len + 1) : decpt)) <= width; - /* - The following is true when no significant digits can be placed with the - specified field width using the 'f' format, and the 'e' format - will not be truncated. - */ + force_e_format= (decpt <= 0 && width <= (2 - decpt) && width >= (3 + exp_len)); - /* - Assume that we don't have enough space to place all significant digits in - the 'f' format. We have to choose between the 'e' format and the 'f' one - to keep as many significant digits as possible. - Let E and F be the lengths of decimal representaion in the 'e' and 'f' - formats, respectively. We want to use the 'f' format if, and only if F <= E. - Consider the following cases: - 1. decpt <= 0. - F = len - decpt + 2 (see above) - E = len + (len > 1) + 1 + 1 (decpt <= -99) + (decpt <= -9) + 1 - ("N.NNe-MMM") - (F <= E) <=> (len == 1 && decpt >= -1) || (len > 1 && decpt >= -2) - We also need to ensure that if the 'f' format is chosen, - the field width allows us to place at least one significant digit - (i.e. width > 2 - decpt). If not, we prefer the 'e' format. - 2. 0 < decpt < len - F = len + 1 (see above) - E = len + 1 + 1 + ... ("N.NNeMMM") - F is always less than E. - 3. len <= decpt <= width - In this case we have enough space to represent the number in the 'f' - format, so we prefer it with some exceptions. - 4. width < decpt - The number cannot be represented in the 'f' format at all, always use - the 'e' 'one. - */ - -// if ((have_space || -// /* -// Not enough space, let's see if the 'f' format provides the most number -// of significant digits. -// */ -// ((decpt <= width && (decpt >= -1 || (decpt == -2 && -// (len > 1 || !force_e_format)))) && -// !force_e_format)) && -// /* -// Use the 'e' format in some cases even if we have enough space for the -// 'f' one. See comment for MAX_DECPT_FOR_F_FORMAT. -// */ -// (!have_space || (decpt >= -TMP_MAX_DECPT_FOR_F_FORMAT + 1 && -// (decpt <= TMP_MAX_DECPT_FOR_F_FORMAT || len > decpt)))) if (!use_force_e_format && ((have_space && (decpt >= -TMP_MAX_DECPT_FOR_F_FORMAT + 1 && (decpt <= TMP_MAX_DECPT_FOR_F_FORMAT || len > decpt))) @@ -568,7 +371,11 @@ size_t ob_gcvt_strict(double x, ob_gcvt_arg_type type, int width, char *to, &exp_len, &res, error, x, use_oracle_mode); } dtoa_free(res, buf, sizeof(buf)); - *dst= '\0'; + if (dst - to < width_check) { + *dst= '\0'; + } else { + return 0; + } return dst - to; } @@ -589,53 +396,11 @@ double ob_strtod(const char *str, char **end, int *error) double ob_atof(const char *nptr) { int error; - const char *end= nptr+65535; /* Should be enough */ + const char *end= nptr+65535; return (ob_strtod(nptr, (char**) &end, &error)); } -/**************************************************************** - * - * The author of this software is David M. Gay. - * - * Copyright (c) 1991, 2000, 2001 by Lucent Technologies. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - * - ***************************************************************/ -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - - -/* - On a machine with IEEE extended-precision registers, it is - necessary to specify double-precision (53-bit) rounding precision - before invoking strtod or dtoa. If the machine uses (the equivalent - of) Intel 80x87 arithmetic, the call - _control87(PC_53, MCW_PC); - does this with many compilers. Whether this or another call is - appropriate depends on the compiler; for this to work, it may be - necessary to #include "float.h" or another system-dependent header - file. -*/ - -/* - #define Honor_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 - and dtoa should round accordingly. - #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 - and Honor_FLT_ROUNDS is not #defined. - -*/ - typedef int32 Long; typedef uint32 ULong; typedef int64 LLong; @@ -645,21 +410,15 @@ typedef union { double d; ULong L[2]; } U; #if defined(WORDS_BIGENDIAN) || (defined(__FLOAT_WORD_ORDER) && \ (__FLOAT_WORD_ORDER == __BIG_ENDIAN)) -#define word0(x) (x)->L[0] -#define word1(x) (x)->L[1] +COPY_BIGINT WORD0(x) (x)->L[0] +#define WORD1(x) (x)->L[1] #else -#define word0(x) (x)->L[1] -#define word1(x) (x)->L[0] +#define WORD0(x) (x)->L[1] +#define WORD1(x) (x)->L[0] #endif #define dval(x) (x)->d -/* #define P DBL_MANT_DIG */ -/* Ten_pmax= floor(P*log(2)/log(5)) */ -/* Bletch= (highest power of 2 < DBL_MAX_10_EXP) / 16 */ -/* Quick_max= floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ -/* Int_max= floor(P*log(FLT_RADIX)/log(10) - 1) */ - #define Exp_shift 20 #define Exp_shift1 20 #define Exp_msk1 0x100000 @@ -706,50 +465,36 @@ typedef union { double d; ULong L[2]; } U; #define Big1 0xffffffff #define FFFFFFFF 0xffffffffUL -/* This is tested to be enough for dtoa */ #define Kmax 15 -#define copy_bigint(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \ +#define COPY_BIGINT(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \ 2*sizeof(int) + y->wds*sizeof(ULong)) -/* Arbitrary-length integer */ -typedef struct Bigint +typedef struct _bigint { union { - ULong *x; /* points right after this Bigint object */ - struct Bigint *next; /* to maintain free lists */ + ULong *x; + struct _bigint *next; } p; - int k; /* 2^k = maxwds */ - int maxwds; /* maximum length in 32-bit words */ - int sign; /* not zero if number is negative */ - int wds; /* current length in 32-bit words */ + int k; + int maxwds; + int sign; + int wds; } Bigint; -/* A simple stack-memory based allocator for Bigints */ typedef struct ObStackAllocator { char *begin; char *free; char *end; - /* - Having list of free blocks lets us reduce maximum required amount - of memory from ~4000 bytes to < 1680 (tested on x86). - */ Bigint *freelist[Kmax+1]; } ObStackAllocator; -/* - Try to allocate object on stack, and resort to malloc if all - stack memory is used. Ensure allocated objects to be aligned by the pointer - size in order to not break the alignment rules when storing a pointer to a - Bigint. -*/ - static Bigint *alloc_bigint(int k, ObStackAllocator *alloc) { Bigint *rv; @@ -760,7 +505,7 @@ static Bigint *alloc_bigint(int k, ObStackAllocator *alloc) } else { int x, len; x = 1 << k; - len = OB_ALIGN(sizeof(Bigint) + x * sizeof(ULong), SIZEOF_CHARP); + len = MY_ALIGN(sizeof(Bigint) + x * sizeof(ULong), SIZEOF_CHARP); if (alloc->free + len <= alloc->end) { rv = (Bigint*) alloc->free; alloc->free += len; @@ -776,23 +521,14 @@ static Bigint *alloc_bigint(int k, ObStackAllocator *alloc) } -/* - If object was allocated on stack, try putting it to the free - list. Otherwise call free(). -*/ static void free_bigint(Bigint *v, ObStackAllocator *alloc) { if (v != NULL) { - char *gptr= (char*) v; /* generic pointer */ - if (gptr < alloc->begin || gptr >= alloc->end) { - free(gptr); + char *g_ptr= (char*) v; + if (g_ptr < alloc->begin || g_ptr >= alloc->end) { + free(g_ptr); } else if (v->k <= Kmax) { - /* - Maintain free lists only for stack objects: this way we don't - have to bother with freeing lists in the end of dtoa; - heap should not be used normally anyway. - */ v->p.next= alloc->freelist[v->k]; alloc->freelist[v->k]= v; } @@ -800,44 +536,27 @@ static void free_bigint(Bigint *v, ObStackAllocator *alloc) } -/* - This is to place return value of dtoa in: tries to use stack - as well, but passes by free lists management and just aligns len by - the pointer size in order to not break the alignment rules when storing a - pointer to a Bigint. -*/ - static char *dtoa_alloc(int i, ObStackAllocator *alloc) { char *rv; - int aligned_size = OB_ALIGN(i, SIZEOF_CHARP); + int aligned_size = MY_ALIGN(i, SIZEOF_CHARP); if (alloc->free + aligned_size <= alloc->end) { rv = alloc->free; alloc->free += aligned_size; } else { - rv = malloc(i); + rv = (char*)malloc(i); } return rv; } - -/* - dtoa_free() must be used to free values s returned by dtoa() - This is the counterpart of dtoa_alloc() -*/ - -static void dtoa_free(char *gptr, char *buf, size_t buf_size) +static void dtoa_free(char *g_ptr, char *buf, size_t buf_size) { - if (gptr < buf || gptr >= buf + buf_size) { - free(gptr); + if (g_ptr < buf || g_ptr >= buf + buf_size) { + free(g_ptr); } } -/* Bigint arithmetic functions */ - -/* Multiply by m and add a */ - static Bigint *mult_and_add(Bigint *b, int m, int a, ObStackAllocator *alloc) { int i, wds; @@ -861,7 +580,7 @@ static Bigint *mult_and_add(Bigint *b, int m, int a, ObStackAllocator *alloc) if (wds >= b->maxwds) { b1= alloc_bigint(b->k+1, alloc); - copy_bigint(b1, b); + COPY_BIGINT(b1, b); free_bigint(b, alloc); b= b1; } @@ -871,20 +590,6 @@ static Bigint *mult_and_add(Bigint *b, int m, int a, ObStackAllocator *alloc) return b; } -/** - Converts a string to Bigint. - - Now we have nd0 digits, starting at s, followed by a - decimal point, followed by nd-nd0 digits. - Unless nd0 == nd, in which case we have a number of the form: - ".xxxxxx" or "xxxxxx." - - @param s Input string, already partially parsed by ob_strtod_int(). - @param nd0 Number of digits before decimal point. - @param nd Total number of digits. - @param y9 Pre-computed value of the first nine digits. - @param alloc Stack allocator for Bigints. - */ static Bigint *string2bigint(const char *s, int nd0, int nd, ULong y9, ObStackAllocator *alloc) { Bigint *b; @@ -904,11 +609,10 @@ static Bigint *string2bigint(const char *s, int nd0, int nd, ULong y9, ObStackAl do b= mult_and_add(b, 10, *s++ - '0', alloc); while (++i < nd0); - s++; /* skip '.' */ + s++; } else s+= 10; - /* now do the fractional part */ for(; i < nd; i++) b= mult_and_add(b, 10, *s++ - '0', alloc); return b; @@ -999,8 +703,6 @@ static int lo0bits(ULong *y) } -/* Convert integer to Bigint number */ - static Bigint *integer2bigint(int i, ObStackAllocator *alloc) { Bigint *b; @@ -1011,7 +713,6 @@ static Bigint *integer2bigint(int i, ObStackAllocator *alloc) } -/* Multiply two Bigint numbers */ static Bigint *bigint_mul_bigint(Bigint *a, Bigint *b, ObStackAllocator *alloc) { @@ -1064,11 +765,6 @@ static Bigint *bigint_mul_bigint(Bigint *a, Bigint *b, ObStackAllocator *alloc) } -/* - Precalculated array of powers of 5: tested to be enough for - vasting majority of dtoa_r cases. -*/ - static ULong powers5[]= { 625UL, @@ -1093,7 +789,6 @@ static ULong powers5[]= static Bigint p5_a[]= { - /* { x } - k - maxwds - sign - wds */ { { powers5 }, 1, 1, 0, 1 }, { { powers5 + 1 }, 1, 1, 0, 1 }, { { powers5 + 2 }, 1, 2, 0, 2 }, @@ -1110,7 +805,7 @@ static Bigint *pow5mult(Bigint *b, int k, ObStackAllocator *alloc) Bigint *b1, *p5, *p51=NULL; int i; static int p05[3]= { 5, 25, 125 }; - ob_bool overflow= FALSE; + bool overflow= FALSE; if ((i= k & 3)) b= mult_and_add(b, p05[i-1], 0, alloc); @@ -1128,7 +823,6 @@ static Bigint *pow5mult(Bigint *b, int k, ObStackAllocator *alloc) } if (!(k>>= 1)) break; - /* Calculate next power of 5 */ if (overflow) { p51= bigint_mul_bigint(p5, p5, alloc); @@ -1272,9 +966,9 @@ static double ulp(U *x) register Long L; U u; - L= (word0(x) & Exp_mask) - (P - 1)*Exp_msk1; - word0(&u) = L; - word1(&u) = 0; + L= (WORD0(x) & Exp_mask) - (P - 1)*Exp_msk1; + WORD0(&u) = L; + WORD1(&u) = 0; return dval(&u); } @@ -1284,8 +978,8 @@ static double b2d(Bigint *a, int *e) ULong *xa, *xa0, w, y, z; int k; U d; -#define d0 word0(&d) -#define d1 word1(&d) +#define d0 WORD0(&d) +#define d1 WORD1(&d) xa0= a->p.x; xa= xa0 + a->wds; @@ -1324,14 +1018,14 @@ static Bigint *d2b(U *d, int *e, int *bits, ObStackAllocator *alloc) int de, k; ULong *x, y, z; int i; -#define d0 word0(d) -#define d1 word1(d) +#define d0 WORD0(d) +#define d1 WORD1(d) b= alloc_bigint(1, alloc); x= b->p.x; z= d0 & Frac_mask; - d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ + d0 &= 0x7fffffff; if ((de= (int)(d0 >> Exp_shift))) z|= Exp_msk1; if ((y= d1)) @@ -1342,7 +1036,6 @@ static Bigint *d2b(U *d, int *e, int *bits, ObStackAllocator *alloc) if (k >= 0 && k <32) { z >>= k; } else { - } } else @@ -1381,11 +1074,11 @@ static double ratio(Bigint *a, Bigint *b) dval(&db)= b2d(b, &kb); k= ka - kb + 32*(a->wds - b->wds); if (k > 0) - word0(&da)+= k*Exp_msk1; + WORD0(&da)+= k*Exp_msk1; else { k= -k; - word0(&db)+= k*Exp_msk1; + WORD0(&db)+= k*Exp_msk1; } return dval(&da) / dval(&db); } @@ -1400,43 +1093,8 @@ static const double tens[] = static const double bigtens[]= { 1e16, 1e32, 1e64, 1e128, 1e256 }; static const double tinytens[]= { 1e-16, 1e-32, 1e-64, 1e-128, - 9007199254740992.*9007199254740992.e-256 /* = 2^106 * 1e-53 */ + 9007199254740992.*9007199254740992.e-256 }; -/* - The factor of 2^53 in tinytens[4] helps us avoid setting the underflow - flag unnecessarily. It leads to a song and dance at the end of strtod. -*/ -#define Scale_Bit 0x10 -#define n_bigtens 5 - -/* - strtod for IEEE--arithmetic machines. - - This strtod returns a nearest machine number to the input decimal - string (or sets errno to EOVERFLOW). Ties are broken by the IEEE round-even - rule. - - Inspired loosely by William D. Clinger's paper "How to Read Floating - Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101]. - - Modifications: - - 1. We only require IEEE (not IEEE double-extended). - 2. We get by with floating-point arithmetic in a case that - Clinger missed -- when we're computing d * 10^n - for a small integer d and the integer n is not too - much larger than 22 (the maximum integer k for which - we can represent 10^k exactly), we may be able to - compute (d*10^k) * 10^(e-k) with just one roundoff. - 3. Rather than a bit-at-a-time adjustment of the binary - result in the hard case, we use floating-point - arithmetic to determine the adjustment to within - one bit; only in really hard cases do we need to - compute a second residual. - 4. Because of 3., we don't need a large table of powers of 10 - for ten-to-e (just some small tables, e.g. of 10^k - for 0 <= k <= 22). -*/ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, size_t buf_size) { @@ -1469,7 +1127,6 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s switch (*s) { case '-': sign= 1; - /* no break */ case '+': s++; goto break2; @@ -1504,7 +1161,10 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s nd0= nd; if (s < end && c == '.') { - c= *++s; + s++; + if(s < end) { + c = *s; + } if (!nd) { for (; s < end; ++s) @@ -1528,12 +1188,6 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s c= *s; if (c < '0' || c > '9') break; - /* - Here we are parsing the fractional part. - We can stop counting digits after a while: the extra digits - will not contribute to the actual result produced by string2bigint(). - We have to continue scanning, in case there is an exponent part. - */ if (nd < 2 * DBL_DIG) { nz++; @@ -1576,18 +1230,18 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s } if (s < end && c >= '0' && c <= '9') { - while (s < end && c == '0') - c= *++s; + while (s < end && c == '0') { + s++; + if(s < end) + c= *s; + } if (s < end && c > '0' && c <= '9') { L= c - '0'; s1= s; while (++s < end && (c= *s) >= '0' && c <= '9') L= 10*L + c - '0'; if (s - s1 > 8 || L > 19999) - /* Avoid confusion from exponents - * so large that e might overflow. - */ - e= 19999; /* safe for 16 bit ints */ + e= 19999; else e= (int)L; if (esign) @@ -1610,14 +1264,6 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s goto ret; } e1= e -= nf; - - /* - Now we have nd0 digits, starting at s0, followed by a - decimal point, followed by nd-nd0 digits. The number we're - after is the integer represented by those digits times - 10**e - */ - if (!nd0) nd0= nd; k= nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; @@ -1644,25 +1290,19 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s if (e <= Ten_pmax) { #ifdef Honor_FLT_ROUNDS - /* round correctly FLT_ROUNDS = 2 or 3 */ if (sign) { rv.d= -rv.d; sign= 0; } #endif - /* rv = */ rounded_product(dval(&rv), tens[e]); + rounded_product(dval(&rv), tens[e]); goto ret; } i= DBL_DIG - nd; if (e <= Ten_pmax + i) { - /* - A fancier test would sometimes let us do - this for larger i values. - */ #ifdef Honor_FLT_ROUNDS - /* round correctly FLT_ROUNDS = 2 or 3 */ if (sign) { rv.d= -rv.d; @@ -1671,7 +1311,7 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s #endif e-= i; dval(&rv)*= tens[i]; - /* rv = */ rounded_product(dval(&rv), tens[e]); + rounded_product(dval(&rv), tens[e]); goto ret; } } @@ -1679,14 +1319,13 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s else if (e >= -Ten_pmax) { #ifdef Honor_FLT_ROUNDS - /* round correctly FLT_ROUNDS = 2 or 3 */ if (sign) { rv.d= -rv.d; sign= 0; } #endif - /* rv = */ rounded_quotient(dval(&rv), tens[-e]); + rounded_quotient(dval(&rv), tens[-e]); goto ret; } #endif @@ -1710,7 +1349,6 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s } #endif - /* Get starting approximation = rv * 10**e1 */ if (e1 > 0) { @@ -1722,25 +1360,24 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s { ovfl: *error= EOVERFLOW; - /* Can't trust HUGE_VAL */ + #ifdef Honor_FLT_ROUNDS switch (rounding) { - case 0: /* toward 0 */ - case 3: /* toward -infinity */ - word0(&rv)= Big0; - word1(&rv)= Big1; + case 0: + case 3: + WORD0(&rv)= Big0; + WORD1(&rv)= Big1; break; default: - word0(&rv)= Exp_mask; - word1(&rv)= 0; + WORD0(&rv)= Exp_mask; + WORD1(&rv)= 0; } -#else /*Honor_FLT_ROUNDS*/ - word0(&rv)= Exp_mask; - word1(&rv)= 0; -#endif /*Honor_FLT_ROUNDS*/ +#else + WORD0(&rv)= Exp_mask; + WORD1(&rv)= 0; +#endif #ifdef SET_INEXACT - /* set overflow bit */ dval(&rv0)= 1e300; dval(&rv0)*= dval(&rv0); #endif @@ -1752,19 +1389,17 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s for(j= 0; e1 > 1; j++, e1>>= 1) if (e1 & 1) dval(&rv)*= bigtens[j]; - /* The last multiplication could overflow. */ - word0(&rv)-= P*Exp_msk1; + WORD0(&rv)-= P*Exp_msk1; dval(&rv)*= bigtens[j]; - if ((z= word0(&rv) & Exp_mask) > Exp_msk1 * (DBL_MAX_EXP + Bias - P)) + if ((z= WORD0(&rv) & Exp_mask) > Exp_msk1 * (DBL_MAX_EXP + Bias - P)) goto ovfl; if (z > Exp_msk1 * (DBL_MAX_EXP + Bias - 1 - P)) { - /* set to largest number (Can't trust DBL_MAX) */ - word0(&rv)= Big0; - word1(&rv)= Big1; + WORD0(&rv)= Big0; + WORD1(&rv)= Big1; } else - word0(&rv)+= P*Exp_msk1; + WORD0(&rv)+= P*Exp_msk1; } } else if (e1 < 0) @@ -1781,19 +1416,18 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s for(j= 0; e1 > 0; j++, e1>>= 1) if (e1 & 1) dval(&rv)*= tinytens[j]; - if (scale && (j = 2 * P + 1 - ((word0(&rv) & Exp_mask) >> Exp_shift)) > 0) + if (scale && (j = 2 * P + 1 - ((WORD0(&rv) & Exp_mask) >> Exp_shift)) > 0) { - /* scaled rv is denormal; zap j low bits */ if (j >= 32) { - word1(&rv)= 0; + WORD1(&rv)= 0; if (j >= 53) - word0(&rv)= (P + 2) * Exp_msk1; + WORD0(&rv)= (P + 2) * Exp_msk1; else - word0(&rv)&= 0xffffffff << (j - 32); + WORD0(&rv)&= 0xffffffff << (j - 32); } else - word1(&rv)&= 0xffffffff << j; + WORD1(&rv)&= 0xffffffff << j; } if (!dval(&rv)) { @@ -1806,17 +1440,13 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s } } - /* Now the hard part -- adjusting rv to the correct value.*/ - - /* Put digits into bd: true value = bd * 10^e */ - bd0= string2bigint(s0, nd0, nd, y, &alloc); for(;;) { bd= alloc_bigint(bd0->k, &alloc); - copy_bigint(bd, bd0); - bb= d2b(&rv, &bbe, &bbbits, &alloc); /* rv = bb * 2^bbe */ + COPY_BIGINT(bd, bd0); + bb= d2b(&rv, &bbe, &bbbits, &alloc); bs= integer2bigint(1, &alloc); if (e >= 0) @@ -1839,8 +1469,8 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s bs2++; #endif j= bbe - scale; - i= j + bbbits - 1; /* logb(rv) */ - if (i < Emin) /* denormal */ + i= j + bbbits - 1; + if (i < Emin) j+= P - Emin; else j= P + 1 - bbbits; @@ -1880,10 +1510,8 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s { if (i < 0) { - /* Error is less than an ulp */ if (!delta->p.x[0] && delta->wds <= 1) { - /* exact */ #ifdef SET_INEXACT inexact= 0; #endif @@ -1900,9 +1528,9 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s else if (!dsign) { adj.d= -1.; - if (!word1(&rv) && !(word0(&rv) & Frac_mask)) + if (!WORD1(&rv) && !(WORD0(&rv) & Frac_mask)) { - y= word0(&rv) & Exp_mask; + y= WORD0(&rv) & Exp_mask; if (!scale || y > 2*P*Exp_msk1) { delta= left_shift(delta, Log2P, &alloc); @@ -1911,8 +1539,8 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s } } apply_adj: - if (scale && (y= word0(&rv) & Exp_mask) <= 2 * P * Exp_msk1) - word0(&adj)+= (2 * P + 1) * Exp_msk1 - y; + if (scale && (y= WORD0(&rv) & Exp_mask) <= 2 * P * Exp_msk1) + WORD0(&adj)+= (2 * P + 1) * Exp_msk1 - y; dval(&rv)+= adj.d * ulp(&rv); } break; @@ -1922,7 +1550,6 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s adj.d= 1.; if (adj.d <= 0x7ffffffe) { - /* adj = rounding ? ceil(adj) : floor(adj); */ y= adj.d; if (y != adj.d) { @@ -1931,8 +1558,8 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s adj.d= y; } } - if (scale && (y= word0(&rv) & Exp_mask) <= 2 * P * Exp_msk1) - word0(&adj)+= (2 * P + 1) * Exp_msk1 - y; + if (scale && (y= WORD0(&rv) & Exp_mask) <= 2 * P * Exp_msk1) + WORD0(&adj)+= (2 * P + 1) * Exp_msk1 - y; adj.d*= ulp(&rv); if (dsign) dval(&rv)+= adj.d; @@ -1940,16 +1567,12 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s dval(&rv)-= adj.d; goto cont; } -#endif /*Honor_FLT_ROUNDS*/ +#endif if (i < 0) { - /* - Error is less than half an ulp -- check for special case of mantissa - a power of two. - */ - if (dsign || word1(&rv) || word0(&rv) & Bndry_mask || - (word0(&rv) & Exp_mask) <= (2 * P + 1) * Exp_msk1) + if (dsign || WORD1(&rv) || WORD0(&rv) & Bndry_mask || + (WORD0(&rv) & Exp_mask) <= (2 * P + 1) * Exp_msk1) { #ifdef SET_INEXACT if (!delta->x[0] && delta->wds <= 1) @@ -1959,7 +1582,6 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s } if (!delta->p.x[0] && delta->wds <= 1) { - /* exact result */ #ifdef SET_INEXACT inexact= 0; #endif @@ -1972,44 +1594,40 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s } if (i == 0) { - /* exactly half-way between */ if (dsign) { - if ((word0(&rv) & Bndry_mask1) == Bndry_mask1 && - word1(&rv) == - ((scale && (y = word0(&rv) & Exp_mask) <= 2 * P * Exp_msk1) ? + if ((WORD0(&rv) & Bndry_mask1) == Bndry_mask1 && + WORD1(&rv) == + ((scale && (y = WORD0(&rv) & Exp_mask) <= 2 * P * Exp_msk1) ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) : 0xffffffff)) { - /*boundary case -- increment exponent*/ - word0(&rv)= (word0(&rv) & Exp_mask) + Exp_msk1; - word1(&rv) = 0; + WORD0(&rv)= (WORD0(&rv) & Exp_mask) + Exp_msk1; + WORD1(&rv) = 0; dsign = 0; break; } } - else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) + else if (!(WORD0(&rv) & Bndry_mask) && !WORD1(&rv)) { drop_down: - /* boundary case -- decrement exponent */ + if (scale) { - L= word0(&rv) & Exp_mask; + L= WORD0(&rv) & Exp_mask; if (L <= (2 *P + 1) * Exp_msk1) { if (L > (P + 2) * Exp_msk1) - /* round even ==> accept rv */ break; - /* rv = smallest denormal */ goto undfl; } } - L= (word0(&rv) & Exp_mask) - Exp_msk1; - word0(&rv)= L | Bndry_mask1; - word1(&rv)= 0xffffffff; + L= (WORD0(&rv) & Exp_mask) - Exp_msk1; + WORD0(&rv)= L | Bndry_mask1; + WORD1(&rv)= 0xffffffff; break; } - if (!(word1(&rv) & LSB)) + if (!(WORD1(&rv) & LSB)) break; if (dsign) dval(&rv)+= ulp(&rv); @@ -2026,16 +1644,15 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s { if (dsign) aadj= aadj1= 1.; - else if (word1(&rv) || word0(&rv) & Bndry_mask) + else if (WORD1(&rv) || WORD0(&rv) & Bndry_mask) { - if (word1(&rv) == Tiny1 && !word0(&rv)) + if (WORD1(&rv) == Tiny1 && !WORD0(&rv)) goto undfl; aadj= 1.; aadj1= -1.; } else { - /* special case -- power of FLT_RADIX to be rounded down... */ if (aadj < 2. / FLT_RADIX) aadj= 1. / FLT_RADIX; else @@ -2050,38 +1667,36 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s #ifdef Check_FLT_ROUNDS switch (Rounding) { - case 2: /* towards +infinity */ + case 2: aadj1-= 0.5; break; - case 0: /* towards 0 */ - case 3: /* towards -infinity */ + case 0: + case 3: aadj1+= 0.5; } #else if (Flt_Rounds == 0) aadj1+= 0.5; -#endif /*Check_FLT_ROUNDS*/ +#endif } - y= word0(&rv) & Exp_mask; - - /* Check for overflow */ + y= WORD0(&rv) & Exp_mask; if (y == Exp_msk1 * (DBL_MAX_EXP + Bias - 1)) { dval(&rv0)= dval(&rv); - word0(&rv)-= P * Exp_msk1; + WORD0(&rv)-= P * Exp_msk1; adj.d= aadj1 * ulp(&rv); dval(&rv)+= adj.d; - if ((word0(&rv) & Exp_mask) >= Exp_msk1 * (DBL_MAX_EXP + Bias - P)) + if ((WORD0(&rv) & Exp_mask) >= Exp_msk1 * (DBL_MAX_EXP + Bias - P)) { - if (word0(&rv0) == Big0 && word1(&rv0) == Big1) + if (WORD0(&rv0) == Big0 && WORD1(&rv0) == Big1) goto ovfl; - word0(&rv)= Big0; - word1(&rv)= Big1; + WORD0(&rv)= Big0; + WORD1(&rv)= Big1; goto cont; } else - word0(&rv)+= P * Exp_msk1; + WORD0(&rv)+= P * Exp_msk1; } else { @@ -2095,7 +1710,7 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s aadj1= dsign ? aadj : -aadj; } dval(&aadj2) = aadj1; - word0(&aadj2)+= (2 * P + 1) * Exp_msk1 - y; + WORD0(&aadj2)+= (2 * P + 1) * Exp_msk1 - y; aadj1= dval(&aadj2); adj.d= aadj1 * ulp(&rv); dval(&rv)+= adj.d; @@ -2108,16 +1723,14 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s dval(&rv)+= adj.d; } } - z= word0(&rv) & Exp_mask; + z= WORD0(&rv) & Exp_mask; #ifndef SET_INEXACT if (!scale) if (y == z) { - /* Can we stop now? */ L= (Long)aadj; aadj-= L; - /* The tolerances below are conservative. */ - if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) + if (dsign || WORD1(&rv) || WORD0(&rv) & Bndry_mask) { if (aadj < .4999999 || aadj > .5000001) break; @@ -2137,8 +1750,8 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s { if (!oldinexact) { - word0(&rv0)= Exp_1 + (70 << Exp_shift); - word1(&rv0)= 0; + WORD0(&rv0)= Exp_1 + (70 << Exp_shift); + WORD1(&rv0)= 0; dval(&rv0)+= 1.; } } @@ -2147,14 +1760,13 @@ static double ob_strtod_int(const char *s00, char **se, int *error, char *buf, s #endif if (scale) { - word0(&rv0)= Exp_1 - 2 * P * Exp_msk1; - word1(&rv0)= 0; + WORD0(&rv0)= Exp_1 - 2 * P * Exp_msk1; + WORD1(&rv0)= 0; dval(&rv)*= dval(&rv0); } #ifdef SET_INEXACT - if (inexact && !(word0(&rv) & Exp_mask)) + if (inexact && !(WORD0(&rv) & Exp_mask)) { - /* set underflow bit */ dval(&rv0)= 1e-300; dval(&rv0)*= dval(&rv0); } @@ -2184,7 +1796,7 @@ static int quorem(Bigint *b, Bigint *S) sxe= sx + --n; bx= b->p.x; bxe= bx + n; - q= *bxe / (*sxe + 1); /* ensure q <= true quotient */ + q= *bxe / (*sxe + 1); if (q) { borrow= 0; @@ -2234,80 +1846,9 @@ static int quorem(Bigint *b, Bigint *S) return q; } - -/* - dtoa for IEEE arithmetic (dmg): convert double to ASCII string. - - Inspired by "How to Print Floating-Point Numbers Accurately" by - Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126]. - - Modifications: - 1. Rather than iterating, we use a simple numeric overestimate - to determine k= floor(log10(d)). We scale relevant - quantities using O(log2(k)) rather than O(k) multiplications. - 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't - try to generate digits strictly left to right. Instead, we - compute with fewer bits and propagate the carry if necessary - when rounding the final digit up. This is often faster. - 3. Under the assumption that input will be rounded nearest, - mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. - That is, we allow equality in stopping tests when the - round-nearest rule will give the same floating-point value - as would satisfaction of the stopping test with strict - inequality. - 4. We remove common factors of powers of 2 from relevant - quantities. - 5. When converting floating-point integers less than 1e16, - we use floating-point arithmetic rather than resorting - to multiple-precision integers. - 6. When asked to produce fewer than 15 digits, we first try - to get by with floating-point arithmetic; we resort to - multiple-precision integer arithmetic only if we cannot - guarantee that the floating-point calculation has given - the correctly rounded result. For k requested digits and - "uniformly" distributed input, the probability is - something like 10^(k-15) that we must resort to the Long - calculation. - */ - static char *dtoa(double dd, int mode, int ndigits, int *decpt, int *sign, char **rve, char *buf, size_t buf_size) { - /* - Arguments ndigits, decpt, sign are similar to those - of ecvt and fcvt; trailing zeros are suppressed from - the returned string. If not null, *rve is set to point - to the end of the return value. If d is +-Infinity or NaN, - then *decpt is set to DTOA_OVERFLOW. - - mode: - 0 ==> shortest string that yields d when read in - and rounded to nearest. - 1 ==> like 0, but with Steele & White stopping rule; - e.g. with IEEE P754 arithmetic , mode 0 gives - 1e23 whereas mode 1 gives 9.999999999999999e22. - 2 ==> max(1,ndigits) significant digits. This gives a - return value similar to that of ecvt, except - that trailing zeros are suppressed. - 3 ==> through ndigits past the decimal point. This - gives a return value similar to that from fcvt, - except that trailing zeros are suppressed, and - ndigits can be negative. - 4,5 ==> similar to 2 and 3, respectively, but (in - round-nearest mode) with the tests of mode 0 to - possibly return a shorter string that rounds to d. - With IEEE arithmetic and compilation with - -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same - as modes 2 and 3 when FLT_ROUNDS != 1. - 6-9 ==> Debugging modes similar to mode - 4: don't try - fast floating-point estimate (if applicable). - - Values of mode other than 0-9 are treated as mode 0. - - Sufficient space is allocated to the return value - to hold the suppressed trailing zeros. - */ - int bbits, b2, b5, be, dig, i, ieps, ilim = 0, ilim0, ilim1 = 0, j, j1, k, k0, k_check, leftright, m2, m5, s2, s5, spec_case, try_quick; @@ -2328,20 +1869,18 @@ static char *dtoa(double dd, int mode, int ndigits, int *decpt, int *sign, memset(alloc.freelist, 0, sizeof(alloc.freelist)); u.d= dd; - if (word0(&u) & Sign_bit) + if (WORD0(&u) & Sign_bit) { - /* set sign for everything, including 0's and NaNs */ *sign= 1; - word0(&u) &= ~Sign_bit; /* clear sign bit */ + WORD0(&u) &= ~Sign_bit; } else *sign= 0; - /* If infinity, set decpt to DTOA_OVERFLOW, if 0 set it to 1 */ - if (((word0(&u) & Exp_mask) == Exp_mask && (*decpt= DTOA_OVERFLOW)) || + + if (((WORD0(&u) & Exp_mask) == Exp_mask && (*decpt= DTOA_OVERFLOW)) || (!dval(&u) && (*decpt= 1))) { - /* Infinity, NaN, 0 */ char *res= (char*) dtoa_alloc(2, &alloc); res[0]= '0'; res[1]= '\0'; @@ -2362,54 +1901,31 @@ static char *dtoa(double dd, int mode, int ndigits, int *decpt, int *sign, #endif b= d2b(&u, &be, &bbits, &alloc); - if ((i= (int)(word0(&u) >> Exp_shift1 & (Exp_mask>>Exp_shift1)))) + if ((i= (int)(WORD0(&u) >> Exp_shift1 & (Exp_mask>>Exp_shift1)))) { dval(&d2)= dval(&u); - word0(&d2) &= Frac_mask1; - word0(&d2) |= Exp_11; - - /* - log(x) ~=~ log(1.5) + (x-1.5)/1.5 - log10(x) = log(x) / log(10) - ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) - log10(d)= (i-Bias)*log(2)/log(10) + log10(d2) - - This suggests computing an approximation k to log10(d) by - - k= (i - Bias)*0.301029995663981 - + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); - - We want k to be too large rather than too small. - The error in the first-order Taylor series approximation - is in our favor, so we just round up the constant enough - to compensate for any error in the multiplication of - (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077, - and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, - adding 1e-13 to the constant term more than suffices. - Hence we adjust the constant term to 0.1760912590558. - (We could get a more accurate k by invoking log10, - but this is probably not worthwhile.) - */ + WORD0(&d2) &= Frac_mask1; + WORD0(&d2) |= Exp_11; + i-= Bias; denorm= 0; } else { - /* d is denormalized */ i= bbits + be + (Bias + (P-1) - 1); - x= i > 32 ? word0(&u) << (64 - i) | word1(&u) >> (i - 32) - : word1(&u) << (32 - i); + x= i > 32 ? WORD0(&u) << (64 - i) | WORD1(&u) >> (i - 32) + : WORD1(&u) << (32 - i); dval(&d2)= x; - word0(&d2)-= 31*Exp_msk1; /* adjust exponent */ + WORD0(&d2)-= 31*Exp_msk1; i-= (Bias + (P-1) - 1) + 1; denorm= 1; } ds= (dval(&d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; k= (int)ds; if (ds < 0. && ds != k) - k--; /* want k= floor(ds) */ + k--; k_check= 1; if (k >= 0 && k <= Ten_pmax) { @@ -2464,7 +1980,6 @@ static char *dtoa(double dd, int mode, int ndigits, int *decpt, int *sign, break; case 2: leftright= 0; - /* no break */ case 4: if (ndigits <= 0) ndigits= 1; @@ -2472,7 +1987,6 @@ static char *dtoa(double dd, int mode, int ndigits, int *decpt, int *sign, break; case 3: leftright= 0; - /* no break */ case 5: i= ndigits + k + 1; ilim= i; @@ -2489,19 +2003,17 @@ static char *dtoa(double dd, int mode, int ndigits, int *decpt, int *sign, if (ilim >= 0 && ilim <= Quick_max && try_quick) { - /* Try to get by with floating-point arithmetic. */ i= 0; dval(&d2)= dval(&u); k0= k; ilim0= ilim; - ieps= 2; /* conservative */ + ieps= 2; if (k > 0) { ds= tens[k&0xf]; j= k >> 4; if (j & Bletch) { - /* prevent overflows */ j&= Bletch - 1; dval(&u)/= bigtens[n_bigtens-1]; ieps++; @@ -2538,7 +2050,7 @@ static char *dtoa(double dd, int mode, int ndigits, int *decpt, int *sign, ieps++; } dval(&eps)= ieps*dval(&u) + 7.; - word0(&eps)-= (P-1)*Exp_msk1; + WORD0(&eps)-= (P-1)*Exp_msk1; if (ilim == 0) { S= mhi= 0; @@ -2551,7 +2063,6 @@ static char *dtoa(double dd, int mode, int ndigits, int *decpt, int *sign, } if (leftright) { - /* Use Steele & White method of only generating digits needed. */ dval(&eps)= 0.5/tens[ilim-1] - dval(&eps); for (i= 0;;) { @@ -2570,7 +2081,6 @@ static char *dtoa(double dd, int mode, int ndigits, int *decpt, int *sign, } else { - /* Generate ilim digits, then fix them up. */ dval(&eps)*= tens[ilim-1]; for (i= 1;; i++, dval(&u)*= 10.) { @@ -2599,11 +2109,9 @@ static char *dtoa(double dd, int mode, int ndigits, int *decpt, int *sign, ilim= ilim0; } - /* Do we have a "small" integer? */ if (be >= 0 && k <= Int_max) { - /* Yes. */ ds= tens[k]; if (ndigits < 0 && ilim <= 0) { @@ -2617,7 +2125,6 @@ static char *dtoa(double dd, int mode, int ndigits, int *decpt, int *sign, L= (Long)(dval(&u) / ds); dval(&u)-= L*ds; #ifdef Check_FLT_ROUNDS - /* If FLT_ROUNDS == 2, L will usually be high by 1 */ if (dval(&u) < 0) { L--; @@ -2697,7 +2204,6 @@ bump_up: if (s5 > 0) S= pow5mult(S, s5, &alloc); - /* Check for special case that d is a normalized power of 2. */ spec_case= 0; if ((mode < 2 || leftright) @@ -2706,25 +2212,16 @@ bump_up: #endif ) { - if (!word1(&u) && !(word0(&u) & Bndry_mask) && - (word0(&u) & (Exp_mask & (~Exp_msk1))) + if (!WORD1(&u) && !(WORD0(&u) & Bndry_mask) && + (WORD0(&u) & (Exp_mask & (~Exp_msk1))) ) { - /* The special case */ b2+= Log2P; s2+= Log2P; spec_case= 1; } } - /* - Arrange for convenient computation of quotients: - shift left if necessary so divisor has 4 leading 0 bits. - - Perhaps we should just compute leading 28 bits of S once - a nd for all and pass them and a shift to quorem, so it - can do shifts and ors to compute the numerator for q. - */ if ((i= ((s5 ? 32 - hi0bits(S->p.x[S->wds-1]) : 1) + s2) & 0x1f)) i= 32 - i; if (i > 4) @@ -2750,7 +2247,6 @@ bump_up: if (bigint_cmp(b,S) < 0) { k--; - /* we botched the k estimate */ b= mult_and_add(b, 10, 0, &alloc); if (leftright) mhi= mult_and_add(mhi, 10, 0, &alloc); @@ -2761,7 +2257,6 @@ bump_up: { if (ilim < 0 || bigint_cmp(b,S= mult_and_add(S,5,0, &alloc)) <= 0) { - /* no digits, fcvt style */ no_digits: k= -1 - ndigits; goto ret; @@ -2776,27 +2271,22 @@ one_digit: if (m2 > 0) mhi= left_shift(mhi, m2, &alloc); - /* - Compute mlo -- check for special case that d is a normalized power of 2. - */ - mlo= mhi; if (spec_case) { mhi= alloc_bigint(mhi->k, &alloc); - copy_bigint(mhi, mlo); + COPY_BIGINT(mhi, mlo); mhi= left_shift(mhi, Log2P, &alloc); } for (i= 1;;i++) { dig= quorem(b,S) + '0'; - /* Do we yet have the shortest decimal string that will round to d? */ j= bigint_cmp(b, mlo); delta= bigint_diff(S, mhi, &alloc); j1= delta->sign ? 1 : bigint_cmp(b, delta); free_bigint(delta, &alloc); - if (j1 == 0 && mode != 1 && !(word1(&u) & 1) + if (j1 == 0 && mode != 1 && !(WORD1(&u) & 1) #ifdef Honor_FLT_ROUNDS && rounding >= 1 #endif @@ -2809,7 +2299,7 @@ one_digit: *s++= dig; goto ret; } - if (j < 0 || (j == 0 && mode != 1 && !(word1(&u) & 1))) + if (j < 0 || (j == 0 && mode != 1 && !(WORD1(&u) & 1))) { if (!b->p.x[0] && b->wds <= 1) { @@ -2821,7 +2311,7 @@ one_digit: case 0: goto accept_dig; case 2: goto keep_dig; } -#endif /*Honor_FLT_ROUNDS*/ +#endif if (j1 > 0) { b= left_shift(b, 1, &alloc); @@ -2841,7 +2331,7 @@ accept_dig: goto accept_dig; #endif if (dig == '9') - { /* possible if i == 1 */ + { round_9_up: *s++= '9'; goto roundoff; @@ -2878,7 +2368,6 @@ keep_dig: b= mult_and_add(b, 10, 0, &alloc); } - /* Round off last digit */ #ifdef Honor_FLT_ROUNDS switch (rounding) { diff --git a/src/lib/charset/ob_dtoa.h b/src/lib/charset/ob_dtoa.h index 3ec82257565139a70ed1c3cc6f5551d986352d96..f87ce8395fcb4542defb49ce9226f0697b6c20ed 100644 --- a/src/lib/charset/ob_dtoa.h +++ b/src/lib/charset/ob_dtoa.h @@ -31,12 +31,12 @@ typedef enum //================================================== double ob_strtod(const char *str, char **end, int *error); -size_t ob_fcvt(double x, int precision, int width, char *to, ob_bool *error); -size_t ob_gcvt(double x, ob_gcvt_arg_type type, int width, char *to, ob_bool *error); -size_t ob_gcvt_opt(double x, ob_gcvt_arg_type type, int width, char *to, ob_bool *error, - ob_bool use_oracle_mode); -size_t ob_gcvt_strict(double x, ob_gcvt_arg_type type, int width, char *to, ob_bool *error, - ob_bool use_oracle_mode, ob_bool use_force_e_format); +size_t ob_fcvt(double x, int precision, int width, char *to, bool *error); +size_t ob_gcvt(double x, ob_gcvt_arg_type type, int width, char *to, bool *error); +size_t ob_gcvt_opt(double x, ob_gcvt_arg_type type, int width, char *to, bool *error, + bool use_oracle_mode); +size_t ob_gcvt_strict(double x, ob_gcvt_arg_type type, int width, char *to, bool *error, + bool use_oracle_mode, bool use_force_e_format); #ifdef __cplusplus } diff --git a/src/lib/charset/ob_mysql_global.h b/src/lib/charset/ob_mysql_global.h index 269ba3f67e0671c451bdaf94871324dcbf694f20..5ff826da18b52718acf7923244abd411196455b6 100644 --- a/src/lib/charset/ob_mysql_global.h +++ b/src/lib/charset/ob_mysql_global.h @@ -13,6 +13,49 @@ #ifndef OCEANBASE_LIB_OBMYSQL_OB_MYSQL_GLOBAL_ #define OCEANBASE_LIB_OBMYSQL_OB_MYSQL_GLOBAL_ +#define MY_GLOBAL_INCLUDED + + + +#if !defined(__WIN__) && defined(_WIN32) +#define __WIN__ +#endif + +#define INNODB_COMPATIBILITY_HOOKS + +#ifdef __CYGWIN__ + +#undef WIN +#undef WIN32 +#undef _WIN +#undef _WIN32 +#undef _WIN64 +#undef __WIN__ +#undef __WIN32__ +#define HAS_ERRNO_AS_DEFINE +#endif + +#if defined(i386) && !defined(__i386__) +#define __i386__ +#endif + + +#ifdef __cplusplus +#define C_MODE_START extern "C" { +#define C_MODE_END } +#else +#define C_MODE_START +#define C_MODE_END +#endif + +#ifdef __cplusplus +#define CPP_UNNAMED_NS_START namespace { +#define CPP_UNNAMED_NS_END } +#endif + + +#include "lib/charset/ob_config.h" +#include #include #include #include @@ -37,96 +80,307 @@ #include -#define TRUE (1) -#define FALSE (0) -#define MY_MAX(a, b) ((a) > (b) ? (a) : (b)) -#define MY_MIN(a, b) ((a) < (b) ? (a) : (b)) -typedef unsigned char uchar; -typedef signed char int8; +#if defined(_lint) || defined(FORCE_INIT_OF_VARS) || \ + (defined(__GNUC__) && defined(__cplusplus)) +#define LINT_INIT(var) var= 0 +#else +#define LINT_INIT(var) +#endif + + +#if defined(_lint) || defined(FORCE_INIT_OF_VARS) || \ + defined(__cplusplus) || !defined(__GNUC__) +#define UNINIT_VAR(x) x= 0 +#else + +#define UNINIT_VAR(x) x= x +#endif + + +#define set_if_smaller(a,b) do { if ((a) > (b)) (a)=(b); } while(0) + + + +#ifndef TRUE +#define TRUE (1) +#define FALSE (0) +#endif + + + + + +typedef int File; +typedef int my_socket; +#define INVALID_SOCKET -1 + +#define sig_handler RETSIGTYPE + +#define OB_MAX(a, b) ((a) > (b) ? (a) : (b)) +#define OB_MIN(a, b) ((a) < (b) ? (a) : (b)) + + +#define MY_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1)) +#define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double)) + + +#define NullS (char *) 0 + +#ifdef STDCALL +#undef STDCALL +#endif + +#ifdef _WIN32 +#define STDCALL __stdcall +#else +#define STDCALL +#endif + + +#ifndef HAS_UCHAR +typedef unsigned char uchar; +#endif + +#ifndef HAS_UINT8 typedef unsigned char uint8; -typedef short int16; -typedef unsigned short uint16; -typedef int int32; -typedef unsigned int uint32; -typedef unsigned long ulong; -typedef unsigned long ulonglong; -typedef long longlong; +#endif +#ifndef HAS_INT16 +typedef short int16; +#endif +#ifndef HAS_UINT16 +typedef unsigned short uint16; +#endif +#ifndef HAS_INT32 +typedef int int32; +#endif +#ifndef HAS_UINT32 +typedef unsigned int uint32; +#endif + + +#ifndef longlong_defined + +#if SIZEOF_LONG_LONG != 8 || !defined(HAS_LONG_LONG) +typedef unsigned long ulonglong; +typedef long longlong; +#else +typedef unsigned long long int ulonglong; +typedef long long int longlong; +#endif + +#if !defined(__USE_MISC) && !defined(HAS_ULONG) +typedef unsigned long ulong; +#endif + +#endif +#ifndef HAS_INT64 typedef longlong int64; +#endif +#ifndef HAS_UINT64 typedef ulonglong uint64; -typedef char ob_bool; +#endif + + +#if SIZEOF_CHARP == SIZEOF_INT +typedef int int_ptr; +#elif SIZEOF_CHARP == SIZEOF_LONG +typedef long int_ptr; +#elif SIZEOF_CHARP == SIZEOF_LONG_LONG +typedef long long int_ptr; +#else +#error sizeof(void *) is neither sizeof(int) nor sizeof(long) nor sizeof(long long) +#endif + +#if defined(NO_CLIENT_LONG_LONG) +typedef unsigned long my_ulonglong; +#elif !defined (__WIN__) +typedef unsigned long long my_ulonglong; +#else +typedef unsigned __int64 my_ulonglong; +#endif + +#if !defined(_WIN32) +typedef off_t os_off_t; +#if SIZEOF_OFF_T <= 4 +typedef unsigned long ob_off_t; +#else +typedef ulonglong ob_off_t; +#endif + +#if defined(_WIN32) +typedef unsigned long long ob_off_t; +typedef unsigned long long os_off_t; +#endif +#endif +#define MY_FILEPOS_ERROR (~(ob_off_t) 0) + +typedef ulonglong table_map; +typedef ulonglong nesting_map; + +typedef int myf; +typedef char my_bool; + + + +#define MYF(v) (myf) (v) + +#ifndef LL +#ifdef HAS_LONG_LONG +#define LL(A) A ## LL +#else +#define LL(A) A ## L +#endif +#endif + +#ifndef ULL +#ifdef HAS_LONG_LONG +#define ULL(A) A ## ULL +#else +#define ULL(A) A ## UL +#endif +#endif + + +#if !defined(HAS_UINT) +#undef HAS_UINT +#define HAS_UINT typedef unsigned int uint; typedef unsigned short ushort; +#endif + + +#if defined(__GNUC__) && !defined(_lint) +typedef char pchar; +typedef char puchar; +typedef char pbool; +typedef short pshort; +typedef float pfloat; +#else +typedef int pchar; +typedef uint puchar; +typedef int pbool; +typedef int pshort; +typedef double pfloat; +#endif +C_MODE_START +typedef int (*qsort_cmp)(const void *,const void *); +typedef int (*qsort_cmp2)(const void*, const void *,const void *); +C_MODE_END +#define qsort_t RETQSORTTYPE + + +#if defined(HAS_LONG_LONG) && !defined(LONGLONG_MIN) +#define LONGLONG_MIN ((long long) 0x8000000000000000LL) +#define LONGLONG_MAX ((long long) 0x7FFFFFFFFFFFFFFFLL) +#endif +#if defined(HAS_LONG_LONG) && !defined(ULONGLONG_MAX) -//=================================================================== - - - -#define ob_sint1korr(P) (*((int8_t*)(P))) -#define ob_uint1korr(P) (*((uint8_t *)P)) - -#define ob_sint2korr(P) (int16) (*((int16 *) (P))) -#define ob_sint3korr(P) ((int32) ((((uchar) (P)[2]) & 128) ? \ - (((uint32) 255L << 24) | \ - (((uint32) (uchar) (P)[2]) << 16) |\ - (((uint32) (uchar) (P)[1]) << 8) | \ - ((uint32) (uchar) (P)[0])) : \ - (((uint32) (uchar) (P)[2]) << 16) |\ - (((uint32) (uchar) (P)[1]) << 8) | \ - ((uint32) (uchar) (P)[0]))) -#define ob_sint4korr(P) (int32) (*((int32 *) (P))) -#define ob_uint2korr(P) (uint16) (*((uint16 *) (P))) -#define ob_uint3korr(P) (uint32) (((uint32) ((uchar) (P)[0])) +\ - (((uint32) ((uchar) (P)[1])) << 8) +\ - (((uint32) ((uchar) (P)[2])) << 16)) -#define ob_uint4korr(P) (uint32) (*((uint32 *) (P))) -#define ob_uint5korr(P) ((ulonglong)(((uint32) ((uchar) (P)[0])) +\ - (((uint32) ((uchar) (P)[1])) << 8) +\ - (((uint32) ((uchar) (P)[2])) << 16) +\ - (((uint32) ((uchar) (P)[3])) << 24)) +\ - (((ulonglong) ((uchar) (P)[4])) << 32)) -#define ob_uint6korr(P) ((ulonglong)(((uint32) ((uchar) (P)[0])) + \ - (((uint32) ((uchar) (P)[1])) << 8) + \ - (((uint32) ((uchar) (P)[2])) << 16) + \ - (((uint32) ((uchar) (P)[3])) << 24)) + \ - (((ulonglong) ((uchar) (P)[4])) << 32) + \ - (((ulonglong) ((uchar) (P)[5])) << 40)) -#define ob_uint8korr(P) (ulonglong) (*((ulonglong *) (P))) -#define ob_sint8korr(P) (longlong) (*((longlong *) (P))) - -#define ob_int1store(P,V) do { *((uint8_t *)(P)) = (uint8_t)(V); } while (0) - -#define ob_int2store(P,V) do { uchar *pP= (uchar*)(P);\ - *((uint16*)(pP))= (uint16) (V);\ - } while (0) - -#define ob_int3store(P,V) do { *(P)= (uchar) ((V));\ - *(P+1)=(uchar) (((uint) (V) >> 8));\ - *(P+2)=(uchar) (((V) >> 16));\ +#ifdef ULLONG_MAX +#define ULONGLONG_MAX ULLONG_MAX +#else +#define ULONGLONG_MAX ((unsigned long long)(~0ULL)) +#endif +#endif + +#define INT_MAX8 0x7F +#define INT_MIN8 (~0x7F) +#define UINT_MAX8 0xFF +#define INT_MAX16 0x7FFF +#define INT_MIN16 (~0x7FFF) +#define UINT_MAX16 0xFFFF +#define INT_MAX24 0x007FFFFF +#define INT_MIN24 (~0x007FFFFF) +#define UINT_MAX24 0x00FFFFFF +#define INT_MAX32 0x7FFFFFFFL +#define INT_MIN32 (~0x7FFFFFFFL) +#define UINT_MAX32 0xFFFFFFFFL +#define INT_MAX64 0x7FFFFFFFFFFFFFFFLL +#define INT_MIN64 (~0x7FFFFFFFFFFFFFFFLL) + +#ifndef DBL_MAX +#define DBL_MAX 1.79769313486231470e+308 +#define FLT_MAX ((float)3.40282346638528860e+38) +#endif +#ifndef DBL_MIN +#define DBL_MIN 4.94065645841246544e-324 +#define FLT_MIN ((float)1.40129846432481707e-45) +#endif + +#define int1store(T,A) do { *((uint8_t *)(T)) = (uint8_t)(A); } while (0) +#define int2store(T,A) do { unsigned char *pT= (unsigned char*)(T);\ + *((unsigned short*)(pT))= (unsigned short) (A);\ } while (0) -#define ob_int4store(P,V) do { uchar *pP= (uchar*)(P);\ - *((uint32 *) (pP))= (uint32) (V); \ - } while (0) - -#define ob_int5store(P,V) do { *(P)= (uchar)((V));\ - *((P)+1)=(uchar) (((V) >> 8));\ - *((P)+2)=(uchar) (((V) >> 16));\ - *((P)+3)=(uchar) (((V) >> 24));\ - *((P)+4)=(uchar) (((V) >> 32));\ - } while(0) -#define ob_int6store(P,V) do { *(P)= (uchar)((V)); \ - *((P)+1)=(uchar) (((V) >> 8)); \ - *((P)+2)=(uchar) (((V) >> 16)); \ - *((P)+3)=(uchar) (((V) >> 24)); \ - *((P)+4)=(uchar) (((V) >> 32)); \ - *((P)+5)=(uchar) (((V) >> 40)); \ - } while(0) -#define ob_int8store(P,V) do { uchar *pP= (uchar*)(P);\ - *((ulonglong *) (pP))= (ulonglong) (V);\ - } while(0) +#define int3store(T,A) do { *(T)= (unsigned char) ((A));\ + *(T+1)=(unsigned char) (((uint) (A) >> 8));\ + *(T+2)=(unsigned char) (((A) >> 16));\ + } while (0) +#define int4store(T,A) do { unsigned char *pT= (unsigned char*)(T);\ + *((unsigned int *) (pT))= (unsigned int) (A); \ + } while (0) + +#define int5store(T,A) do { *(T)= (unsigned char)((A));\ + *((T)+1)=(unsigned char) (((A) >> 8));\ + *((T)+2)=(unsigned char) (((A) >> 16));\ + *((T)+3)=(unsigned char) (((A) >> 24));\ + *((T)+4)=(unsigned char) (((A) >> 32));\ + } while(0) +#define int6store(T,A) do { *(T)= (unsigned char)((A)); \ + *((T)+1)=(unsigned char) (((A) >> 8)); \ + *((T)+2)=(unsigned char) (((A) >> 16)); \ + *((T)+3)=(unsigned char) (((A) >> 24)); \ + *((T)+4)=(unsigned char) (((A) >> 32)); \ + *((T)+5)=(unsigned char) (((A) >> 40)); \ + } while(0) +#define int8store(T,A) do { unsigned char *pT= (unsigned char*)(T);\ + *((uint64 *) (pT))= (uint64) (A);\ + } while(0) + +#define uint1korr(A) (*((uint8_t *)A)) +#define uint2korr(A) (unsigned short) (*((unsigned short *) (A))) +#define uint3korr(A) (unsigned int) (((unsigned int) ((unsigned char) (A)[0])) +\ + (((unsigned int) ((unsigned char) (A)[1])) << 8) +\ + (((unsigned int) ((unsigned char) (A)[2])) << 16)) +#define uint4korr(A) (unsigned int) (*((unsigned int *) (A))) +#define uint5korr(A) ((uint64)(((unsigned int) ((unsigned char) (A)[0])) +\ + (((unsigned int) ((unsigned char) (A)[1])) << 8) +\ + (((unsigned int) ((unsigned char) (A)[2])) << 16) +\ + (((unsigned int) ((unsigned char) (A)[3])) << 24)) +\ + (((uint64) ((unsigned char) (A)[4])) << 32)) +#define uint6korr(A) ((uint64)(((unsigned int) ((unsigned char) (A)[0])) + \ + (((unsigned int) ((unsigned char) (A)[1])) << 8) + \ + (((unsigned int) ((unsigned char) (A)[2])) << 16) + \ + (((unsigned int) ((unsigned char) (A)[3])) << 24)) + \ + (((uint64) ((unsigned char) (A)[4])) << 32) + \ + (((uint64) ((unsigned char) (A)[5])) << 40)) +#define uint8korr(A) (uint64) (*((uint64 *) (A))) + + +#define sint1korr(A) (*((int8_t*)(A))) +#define sint2korr(A) (short) (*((short *) (A))) +#define sint3korr(A) ((int) ((((unsigned char) (A)[2]) & 128) ? \ + (((unsigned int) 255L << 24) | \ + (((unsigned int) (unsigned char) (A)[2]) << 16) |\ + (((unsigned int) (unsigned char) (A)[1]) << 8) | \ + ((unsigned int) (unsigned char) (A)[0])) : \ + (((unsigned int) (unsigned char) (A)[2]) << 16) |\ + (((unsigned int) (unsigned char) (A)[1]) << 8) | \ + ((unsigned int) (unsigned char) (A)[0]))) +#define sint4korr(A) (int) (*((int *) (A))) +#define sint8korr(A) (int64) (*((int64 *) (A))) + + + +#ifndef MYSQL_PLUGIN_IMPORT +#if (defined(_WIN32) && defined(MYSQL_DYNAMIC_PLUGIN)) +#define MYSQL_PLUGIN_IMPORT __declspec(dllimport) +#else +#define MYSQL_PLUGIN_IMPORT +#endif +#endif enum loglevel { ERROR_LEVEL= 0, diff --git a/src/lib/checksum/ob_crc64.cpp b/src/lib/checksum/ob_crc64.cpp index 397d7ce9943b5d8a41959ddb9a8a96d341cecc9b..b27ed232da7a8a9895e6cae35e66837907c7a9c2 100644 --- a/src/lib/checksum/ob_crc64.cpp +++ b/src/lib/checksum/ob_crc64.cpp @@ -424,9 +424,12 @@ for RHEL4 support (GCC 3 doesn't support this instruction) */ asm(".byte 0xf2, 0x48, 0x0f, 0x38, 0xf1, 0x0a" \ : "=c"(crc) : "c"(crc), "d"(buf)); \ len -= 8, buf += 8 +#elif defined(__aarch64__) +#include "arm_acle.h" +#define crc32_sse42_quadword crc = __crc32cd((uint32_t)(crc), *(int64_t*)buf); len -= 8, buf += 8 +#define crc32_sse42_byte crc = __crc32cb((uint32_t)(crc), (uint8_t)*buf); len--, buf++ #endif /* defined(__GNUC__) && defined(__x86_64__) */ -/* inline static uint64_t crc64_sse42(uint64_t uCRC64, const char *buf, int64_t len) { @@ -455,21 +458,10 @@ inline static uint64_t crc64_sse42(uint64_t uCRC64, return crc; } -*/ +/* static uint64_t crc64_sse42_manually(uint64_t crc, const char *buf, int64_t len) { - /** - * crc32tab is generated by: - * // bit-reversed poly 0x1EDC6F41 - * const uint32_t poly = 0x82f63b78; - * for (int n = 0; n < 256; n++) { - * uint32_t c = (uint32_t)n; - * for (int k = 0; k < 8; k++) - * c = c & 1 ? poly ^ (c >> 1) : c >> 1; - * crc32tab[n] = c; - * } - */ const static uint32_t crc32tab[] = { 0x00000000L, 0xf26b8303L, 0xe13b70f7L, 0x1350f3f4L, 0xc79a971fL, @@ -532,23 +524,612 @@ static uint64_t crc64_sse42_manually(uint64_t crc, const char *buf, int64_t len) return crc; } +*/ + +uint64_t fast_crc64_sse42_manually(uint64_t crc, const char *buf, int64_t len) +{ + /* CRC polynomial tables generated by: + * java -cp build/test/classes/:build/classes/ \ + * org.apache.hadoop.util.TestPureJavaCrc32\$Table 82F63B78 + */ + const static uint32_t T8_0[] = + { + 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, + 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, + 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, + 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, + 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, + 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, + 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, + 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, + 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, + 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, + 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, + 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, + 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, + 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, + 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, + 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, + 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, + 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, + 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, + 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, + 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, + 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, + 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, + 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, + 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, + 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, + 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, + 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, + 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, + 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, + 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, + 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, + 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, + 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, + 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, + 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, + 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, + 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, + 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, + 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, + 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, + 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, + 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, + 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, + 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, + 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, + 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, + 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, + 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, + 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, + 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, + 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, + 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, + 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, + 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, + 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, + 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, + 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, + 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, + 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, + 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, + 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, + 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, + 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351 + }; + + const static uint32_t T8_1[] = + { + 0x00000000, 0x13A29877, 0x274530EE, 0x34E7A899, + 0x4E8A61DC, 0x5D28F9AB, 0x69CF5132, 0x7A6DC945, + 0x9D14C3B8, 0x8EB65BCF, 0xBA51F356, 0xA9F36B21, + 0xD39EA264, 0xC03C3A13, 0xF4DB928A, 0xE7790AFD, + 0x3FC5F181, 0x2C6769F6, 0x1880C16F, 0x0B225918, + 0x714F905D, 0x62ED082A, 0x560AA0B3, 0x45A838C4, + 0xA2D13239, 0xB173AA4E, 0x859402D7, 0x96369AA0, + 0xEC5B53E5, 0xFFF9CB92, 0xCB1E630B, 0xD8BCFB7C, + 0x7F8BE302, 0x6C297B75, 0x58CED3EC, 0x4B6C4B9B, + 0x310182DE, 0x22A31AA9, 0x1644B230, 0x05E62A47, + 0xE29F20BA, 0xF13DB8CD, 0xC5DA1054, 0xD6788823, + 0xAC154166, 0xBFB7D911, 0x8B507188, 0x98F2E9FF, + 0x404E1283, 0x53EC8AF4, 0x670B226D, 0x74A9BA1A, + 0x0EC4735F, 0x1D66EB28, 0x298143B1, 0x3A23DBC6, + 0xDD5AD13B, 0xCEF8494C, 0xFA1FE1D5, 0xE9BD79A2, + 0x93D0B0E7, 0x80722890, 0xB4958009, 0xA737187E, + 0xFF17C604, 0xECB55E73, 0xD852F6EA, 0xCBF06E9D, + 0xB19DA7D8, 0xA23F3FAF, 0x96D89736, 0x857A0F41, + 0x620305BC, 0x71A19DCB, 0x45463552, 0x56E4AD25, + 0x2C896460, 0x3F2BFC17, 0x0BCC548E, 0x186ECCF9, + 0xC0D23785, 0xD370AFF2, 0xE797076B, 0xF4359F1C, + 0x8E585659, 0x9DFACE2E, 0xA91D66B7, 0xBABFFEC0, + 0x5DC6F43D, 0x4E646C4A, 0x7A83C4D3, 0x69215CA4, + 0x134C95E1, 0x00EE0D96, 0x3409A50F, 0x27AB3D78, + 0x809C2506, 0x933EBD71, 0xA7D915E8, 0xB47B8D9F, + 0xCE1644DA, 0xDDB4DCAD, 0xE9537434, 0xFAF1EC43, + 0x1D88E6BE, 0x0E2A7EC9, 0x3ACDD650, 0x296F4E27, + 0x53028762, 0x40A01F15, 0x7447B78C, 0x67E52FFB, + 0xBF59D487, 0xACFB4CF0, 0x981CE469, 0x8BBE7C1E, + 0xF1D3B55B, 0xE2712D2C, 0xD69685B5, 0xC5341DC2, + 0x224D173F, 0x31EF8F48, 0x050827D1, 0x16AABFA6, + 0x6CC776E3, 0x7F65EE94, 0x4B82460D, 0x5820DE7A, + 0xFBC3FAF9, 0xE861628E, 0xDC86CA17, 0xCF245260, + 0xB5499B25, 0xA6EB0352, 0x920CABCB, 0x81AE33BC, + 0x66D73941, 0x7575A136, 0x419209AF, 0x523091D8, + 0x285D589D, 0x3BFFC0EA, 0x0F186873, 0x1CBAF004, + 0xC4060B78, 0xD7A4930F, 0xE3433B96, 0xF0E1A3E1, + 0x8A8C6AA4, 0x992EF2D3, 0xADC95A4A, 0xBE6BC23D, + 0x5912C8C0, 0x4AB050B7, 0x7E57F82E, 0x6DF56059, + 0x1798A91C, 0x043A316B, 0x30DD99F2, 0x237F0185, + 0x844819FB, 0x97EA818C, 0xA30D2915, 0xB0AFB162, + 0xCAC27827, 0xD960E050, 0xED8748C9, 0xFE25D0BE, + 0x195CDA43, 0x0AFE4234, 0x3E19EAAD, 0x2DBB72DA, + 0x57D6BB9F, 0x447423E8, 0x70938B71, 0x63311306, + 0xBB8DE87A, 0xA82F700D, 0x9CC8D894, 0x8F6A40E3, + 0xF50789A6, 0xE6A511D1, 0xD242B948, 0xC1E0213F, + 0x26992BC2, 0x353BB3B5, 0x01DC1B2C, 0x127E835B, + 0x68134A1E, 0x7BB1D269, 0x4F567AF0, 0x5CF4E287, + 0x04D43CFD, 0x1776A48A, 0x23910C13, 0x30339464, + 0x4A5E5D21, 0x59FCC556, 0x6D1B6DCF, 0x7EB9F5B8, + 0x99C0FF45, 0x8A626732, 0xBE85CFAB, 0xAD2757DC, + 0xD74A9E99, 0xC4E806EE, 0xF00FAE77, 0xE3AD3600, + 0x3B11CD7C, 0x28B3550B, 0x1C54FD92, 0x0FF665E5, + 0x759BACA0, 0x663934D7, 0x52DE9C4E, 0x417C0439, + 0xA6050EC4, 0xB5A796B3, 0x81403E2A, 0x92E2A65D, + 0xE88F6F18, 0xFB2DF76F, 0xCFCA5FF6, 0xDC68C781, + 0x7B5FDFFF, 0x68FD4788, 0x5C1AEF11, 0x4FB87766, + 0x35D5BE23, 0x26772654, 0x12908ECD, 0x013216BA, + 0xE64B1C47, 0xF5E98430, 0xC10E2CA9, 0xD2ACB4DE, + 0xA8C17D9B, 0xBB63E5EC, 0x8F844D75, 0x9C26D502, + 0x449A2E7E, 0x5738B609, 0x63DF1E90, 0x707D86E7, + 0x0A104FA2, 0x19B2D7D5, 0x2D557F4C, 0x3EF7E73B, + 0xD98EEDC6, 0xCA2C75B1, 0xFECBDD28, 0xED69455F, + 0x97048C1A, 0x84A6146D, 0xB041BCF4, 0xA3E32483 + }; + + const static uint32_t T8_2[] = + { + 0x00000000, 0xA541927E, 0x4F6F520D, 0xEA2EC073, + 0x9EDEA41A, 0x3B9F3664, 0xD1B1F617, 0x74F06469, + 0x38513EC5, 0x9D10ACBB, 0x773E6CC8, 0xD27FFEB6, + 0xA68F9ADF, 0x03CE08A1, 0xE9E0C8D2, 0x4CA15AAC, + 0x70A27D8A, 0xD5E3EFF4, 0x3FCD2F87, 0x9A8CBDF9, + 0xEE7CD990, 0x4B3D4BEE, 0xA1138B9D, 0x045219E3, + 0x48F3434F, 0xEDB2D131, 0x079C1142, 0xA2DD833C, + 0xD62DE755, 0x736C752B, 0x9942B558, 0x3C032726, + 0xE144FB14, 0x4405696A, 0xAE2BA919, 0x0B6A3B67, + 0x7F9A5F0E, 0xDADBCD70, 0x30F50D03, 0x95B49F7D, + 0xD915C5D1, 0x7C5457AF, 0x967A97DC, 0x333B05A2, + 0x47CB61CB, 0xE28AF3B5, 0x08A433C6, 0xADE5A1B8, + 0x91E6869E, 0x34A714E0, 0xDE89D493, 0x7BC846ED, + 0x0F382284, 0xAA79B0FA, 0x40577089, 0xE516E2F7, + 0xA9B7B85B, 0x0CF62A25, 0xE6D8EA56, 0x43997828, + 0x37691C41, 0x92288E3F, 0x78064E4C, 0xDD47DC32, + 0xC76580D9, 0x622412A7, 0x880AD2D4, 0x2D4B40AA, + 0x59BB24C3, 0xFCFAB6BD, 0x16D476CE, 0xB395E4B0, + 0xFF34BE1C, 0x5A752C62, 0xB05BEC11, 0x151A7E6F, + 0x61EA1A06, 0xC4AB8878, 0x2E85480B, 0x8BC4DA75, + 0xB7C7FD53, 0x12866F2D, 0xF8A8AF5E, 0x5DE93D20, + 0x29195949, 0x8C58CB37, 0x66760B44, 0xC337993A, + 0x8F96C396, 0x2AD751E8, 0xC0F9919B, 0x65B803E5, + 0x1148678C, 0xB409F5F2, 0x5E273581, 0xFB66A7FF, + 0x26217BCD, 0x8360E9B3, 0x694E29C0, 0xCC0FBBBE, + 0xB8FFDFD7, 0x1DBE4DA9, 0xF7908DDA, 0x52D11FA4, + 0x1E704508, 0xBB31D776, 0x511F1705, 0xF45E857B, + 0x80AEE112, 0x25EF736C, 0xCFC1B31F, 0x6A802161, + 0x56830647, 0xF3C29439, 0x19EC544A, 0xBCADC634, + 0xC85DA25D, 0x6D1C3023, 0x8732F050, 0x2273622E, + 0x6ED23882, 0xCB93AAFC, 0x21BD6A8F, 0x84FCF8F1, + 0xF00C9C98, 0x554D0EE6, 0xBF63CE95, 0x1A225CEB, + 0x8B277743, 0x2E66E53D, 0xC448254E, 0x6109B730, + 0x15F9D359, 0xB0B84127, 0x5A968154, 0xFFD7132A, + 0xB3764986, 0x1637DBF8, 0xFC191B8B, 0x595889F5, + 0x2DA8ED9C, 0x88E97FE2, 0x62C7BF91, 0xC7862DEF, + 0xFB850AC9, 0x5EC498B7, 0xB4EA58C4, 0x11ABCABA, + 0x655BAED3, 0xC01A3CAD, 0x2A34FCDE, 0x8F756EA0, + 0xC3D4340C, 0x6695A672, 0x8CBB6601, 0x29FAF47F, + 0x5D0A9016, 0xF84B0268, 0x1265C21B, 0xB7245065, + 0x6A638C57, 0xCF221E29, 0x250CDE5A, 0x804D4C24, + 0xF4BD284D, 0x51FCBA33, 0xBBD27A40, 0x1E93E83E, + 0x5232B292, 0xF77320EC, 0x1D5DE09F, 0xB81C72E1, + 0xCCEC1688, 0x69AD84F6, 0x83834485, 0x26C2D6FB, + 0x1AC1F1DD, 0xBF8063A3, 0x55AEA3D0, 0xF0EF31AE, + 0x841F55C7, 0x215EC7B9, 0xCB7007CA, 0x6E3195B4, + 0x2290CF18, 0x87D15D66, 0x6DFF9D15, 0xC8BE0F6B, + 0xBC4E6B02, 0x190FF97C, 0xF321390F, 0x5660AB71, + 0x4C42F79A, 0xE90365E4, 0x032DA597, 0xA66C37E9, + 0xD29C5380, 0x77DDC1FE, 0x9DF3018D, 0x38B293F3, + 0x7413C95F, 0xD1525B21, 0x3B7C9B52, 0x9E3D092C, + 0xEACD6D45, 0x4F8CFF3B, 0xA5A23F48, 0x00E3AD36, + 0x3CE08A10, 0x99A1186E, 0x738FD81D, 0xD6CE4A63, + 0xA23E2E0A, 0x077FBC74, 0xED517C07, 0x4810EE79, + 0x04B1B4D5, 0xA1F026AB, 0x4BDEE6D8, 0xEE9F74A6, + 0x9A6F10CF, 0x3F2E82B1, 0xD50042C2, 0x7041D0BC, + 0xAD060C8E, 0x08479EF0, 0xE2695E83, 0x4728CCFD, + 0x33D8A894, 0x96993AEA, 0x7CB7FA99, 0xD9F668E7, + 0x9557324B, 0x3016A035, 0xDA386046, 0x7F79F238, + 0x0B899651, 0xAEC8042F, 0x44E6C45C, 0xE1A75622, + 0xDDA47104, 0x78E5E37A, 0x92CB2309, 0x378AB177, + 0x437AD51E, 0xE63B4760, 0x0C158713, 0xA954156D, + 0xE5F54FC1, 0x40B4DDBF, 0xAA9A1DCC, 0x0FDB8FB2, + 0x7B2BEBDB, 0xDE6A79A5, 0x3444B9D6, 0x91052BA8 + }; + + const static uint32_t T8_3[] = + { + 0x00000000, 0xDD45AAB8, 0xBF672381, 0x62228939, + 0x7B2231F3, 0xA6679B4B, 0xC4451272, 0x1900B8CA, + 0xF64463E6, 0x2B01C95E, 0x49234067, 0x9466EADF, + 0x8D665215, 0x5023F8AD, 0x32017194, 0xEF44DB2C, + 0xE964B13D, 0x34211B85, 0x560392BC, 0x8B463804, + 0x924680CE, 0x4F032A76, 0x2D21A34F, 0xF06409F7, + 0x1F20D2DB, 0xC2657863, 0xA047F15A, 0x7D025BE2, + 0x6402E328, 0xB9474990, 0xDB65C0A9, 0x06206A11, + 0xD725148B, 0x0A60BE33, 0x6842370A, 0xB5079DB2, + 0xAC072578, 0x71428FC0, 0x136006F9, 0xCE25AC41, + 0x2161776D, 0xFC24DDD5, 0x9E0654EC, 0x4343FE54, + 0x5A43469E, 0x8706EC26, 0xE524651F, 0x3861CFA7, + 0x3E41A5B6, 0xE3040F0E, 0x81268637, 0x5C632C8F, + 0x45639445, 0x98263EFD, 0xFA04B7C4, 0x27411D7C, + 0xC805C650, 0x15406CE8, 0x7762E5D1, 0xAA274F69, + 0xB327F7A3, 0x6E625D1B, 0x0C40D422, 0xD1057E9A, + 0xABA65FE7, 0x76E3F55F, 0x14C17C66, 0xC984D6DE, + 0xD0846E14, 0x0DC1C4AC, 0x6FE34D95, 0xB2A6E72D, + 0x5DE23C01, 0x80A796B9, 0xE2851F80, 0x3FC0B538, + 0x26C00DF2, 0xFB85A74A, 0x99A72E73, 0x44E284CB, + 0x42C2EEDA, 0x9F874462, 0xFDA5CD5B, 0x20E067E3, + 0x39E0DF29, 0xE4A57591, 0x8687FCA8, 0x5BC25610, + 0xB4868D3C, 0x69C32784, 0x0BE1AEBD, 0xD6A40405, + 0xCFA4BCCF, 0x12E11677, 0x70C39F4E, 0xAD8635F6, + 0x7C834B6C, 0xA1C6E1D4, 0xC3E468ED, 0x1EA1C255, + 0x07A17A9F, 0xDAE4D027, 0xB8C6591E, 0x6583F3A6, + 0x8AC7288A, 0x57828232, 0x35A00B0B, 0xE8E5A1B3, + 0xF1E51979, 0x2CA0B3C1, 0x4E823AF8, 0x93C79040, + 0x95E7FA51, 0x48A250E9, 0x2A80D9D0, 0xF7C57368, + 0xEEC5CBA2, 0x3380611A, 0x51A2E823, 0x8CE7429B, + 0x63A399B7, 0xBEE6330F, 0xDCC4BA36, 0x0181108E, + 0x1881A844, 0xC5C402FC, 0xA7E68BC5, 0x7AA3217D, + 0x52A0C93F, 0x8FE56387, 0xEDC7EABE, 0x30824006, + 0x2982F8CC, 0xF4C75274, 0x96E5DB4D, 0x4BA071F5, + 0xA4E4AAD9, 0x79A10061, 0x1B838958, 0xC6C623E0, + 0xDFC69B2A, 0x02833192, 0x60A1B8AB, 0xBDE41213, + 0xBBC47802, 0x6681D2BA, 0x04A35B83, 0xD9E6F13B, + 0xC0E649F1, 0x1DA3E349, 0x7F816A70, 0xA2C4C0C8, + 0x4D801BE4, 0x90C5B15C, 0xF2E73865, 0x2FA292DD, + 0x36A22A17, 0xEBE780AF, 0x89C50996, 0x5480A32E, + 0x8585DDB4, 0x58C0770C, 0x3AE2FE35, 0xE7A7548D, + 0xFEA7EC47, 0x23E246FF, 0x41C0CFC6, 0x9C85657E, + 0x73C1BE52, 0xAE8414EA, 0xCCA69DD3, 0x11E3376B, + 0x08E38FA1, 0xD5A62519, 0xB784AC20, 0x6AC10698, + 0x6CE16C89, 0xB1A4C631, 0xD3864F08, 0x0EC3E5B0, + 0x17C35D7A, 0xCA86F7C2, 0xA8A47EFB, 0x75E1D443, + 0x9AA50F6F, 0x47E0A5D7, 0x25C22CEE, 0xF8878656, + 0xE1873E9C, 0x3CC29424, 0x5EE01D1D, 0x83A5B7A5, + 0xF90696D8, 0x24433C60, 0x4661B559, 0x9B241FE1, + 0x8224A72B, 0x5F610D93, 0x3D4384AA, 0xE0062E12, + 0x0F42F53E, 0xD2075F86, 0xB025D6BF, 0x6D607C07, + 0x7460C4CD, 0xA9256E75, 0xCB07E74C, 0x16424DF4, + 0x106227E5, 0xCD278D5D, 0xAF050464, 0x7240AEDC, + 0x6B401616, 0xB605BCAE, 0xD4273597, 0x09629F2F, + 0xE6264403, 0x3B63EEBB, 0x59416782, 0x8404CD3A, + 0x9D0475F0, 0x4041DF48, 0x22635671, 0xFF26FCC9, + 0x2E238253, 0xF36628EB, 0x9144A1D2, 0x4C010B6A, + 0x5501B3A0, 0x88441918, 0xEA669021, 0x37233A99, + 0xD867E1B5, 0x05224B0D, 0x6700C234, 0xBA45688C, + 0xA345D046, 0x7E007AFE, 0x1C22F3C7, 0xC167597F, + 0xC747336E, 0x1A0299D6, 0x782010EF, 0xA565BA57, + 0xBC65029D, 0x6120A825, 0x0302211C, 0xDE478BA4, + 0x31035088, 0xEC46FA30, 0x8E647309, 0x5321D9B1, + 0x4A21617B, 0x9764CBC3, 0xF54642FA, 0x2803E842 + }; + + const static uint32_t T8_4[] = + { + 0x00000000, 0x38116FAC, 0x7022DF58, 0x4833B0F4, + 0xE045BEB0, 0xD854D11C, 0x906761E8, 0xA8760E44, + 0xC5670B91, 0xFD76643D, 0xB545D4C9, 0x8D54BB65, + 0x2522B521, 0x1D33DA8D, 0x55006A79, 0x6D1105D5, + 0x8F2261D3, 0xB7330E7F, 0xFF00BE8B, 0xC711D127, + 0x6F67DF63, 0x5776B0CF, 0x1F45003B, 0x27546F97, + 0x4A456A42, 0x725405EE, 0x3A67B51A, 0x0276DAB6, + 0xAA00D4F2, 0x9211BB5E, 0xDA220BAA, 0xE2336406, + 0x1BA8B557, 0x23B9DAFB, 0x6B8A6A0F, 0x539B05A3, + 0xFBED0BE7, 0xC3FC644B, 0x8BCFD4BF, 0xB3DEBB13, + 0xDECFBEC6, 0xE6DED16A, 0xAEED619E, 0x96FC0E32, + 0x3E8A0076, 0x069B6FDA, 0x4EA8DF2E, 0x76B9B082, + 0x948AD484, 0xAC9BBB28, 0xE4A80BDC, 0xDCB96470, + 0x74CF6A34, 0x4CDE0598, 0x04EDB56C, 0x3CFCDAC0, + 0x51EDDF15, 0x69FCB0B9, 0x21CF004D, 0x19DE6FE1, + 0xB1A861A5, 0x89B90E09, 0xC18ABEFD, 0xF99BD151, + 0x37516AAE, 0x0F400502, 0x4773B5F6, 0x7F62DA5A, + 0xD714D41E, 0xEF05BBB2, 0xA7360B46, 0x9F2764EA, + 0xF236613F, 0xCA270E93, 0x8214BE67, 0xBA05D1CB, + 0x1273DF8F, 0x2A62B023, 0x625100D7, 0x5A406F7B, + 0xB8730B7D, 0x806264D1, 0xC851D425, 0xF040BB89, + 0x5836B5CD, 0x6027DA61, 0x28146A95, 0x10050539, + 0x7D1400EC, 0x45056F40, 0x0D36DFB4, 0x3527B018, + 0x9D51BE5C, 0xA540D1F0, 0xED736104, 0xD5620EA8, + 0x2CF9DFF9, 0x14E8B055, 0x5CDB00A1, 0x64CA6F0D, + 0xCCBC6149, 0xF4AD0EE5, 0xBC9EBE11, 0x848FD1BD, + 0xE99ED468, 0xD18FBBC4, 0x99BC0B30, 0xA1AD649C, + 0x09DB6AD8, 0x31CA0574, 0x79F9B580, 0x41E8DA2C, + 0xA3DBBE2A, 0x9BCAD186, 0xD3F96172, 0xEBE80EDE, + 0x439E009A, 0x7B8F6F36, 0x33BCDFC2, 0x0BADB06E, + 0x66BCB5BB, 0x5EADDA17, 0x169E6AE3, 0x2E8F054F, + 0x86F90B0B, 0xBEE864A7, 0xF6DBD453, 0xCECABBFF, + 0x6EA2D55C, 0x56B3BAF0, 0x1E800A04, 0x269165A8, + 0x8EE76BEC, 0xB6F60440, 0xFEC5B4B4, 0xC6D4DB18, + 0xABC5DECD, 0x93D4B161, 0xDBE70195, 0xE3F66E39, + 0x4B80607D, 0x73910FD1, 0x3BA2BF25, 0x03B3D089, + 0xE180B48F, 0xD991DB23, 0x91A26BD7, 0xA9B3047B, + 0x01C50A3F, 0x39D46593, 0x71E7D567, 0x49F6BACB, + 0x24E7BF1E, 0x1CF6D0B2, 0x54C56046, 0x6CD40FEA, + 0xC4A201AE, 0xFCB36E02, 0xB480DEF6, 0x8C91B15A, + 0x750A600B, 0x4D1B0FA7, 0x0528BF53, 0x3D39D0FF, + 0x954FDEBB, 0xAD5EB117, 0xE56D01E3, 0xDD7C6E4F, + 0xB06D6B9A, 0x887C0436, 0xC04FB4C2, 0xF85EDB6E, + 0x5028D52A, 0x6839BA86, 0x200A0A72, 0x181B65DE, + 0xFA2801D8, 0xC2396E74, 0x8A0ADE80, 0xB21BB12C, + 0x1A6DBF68, 0x227CD0C4, 0x6A4F6030, 0x525E0F9C, + 0x3F4F0A49, 0x075E65E5, 0x4F6DD511, 0x777CBABD, + 0xDF0AB4F9, 0xE71BDB55, 0xAF286BA1, 0x9739040D, + 0x59F3BFF2, 0x61E2D05E, 0x29D160AA, 0x11C00F06, + 0xB9B60142, 0x81A76EEE, 0xC994DE1A, 0xF185B1B6, + 0x9C94B463, 0xA485DBCF, 0xECB66B3B, 0xD4A70497, + 0x7CD10AD3, 0x44C0657F, 0x0CF3D58B, 0x34E2BA27, + 0xD6D1DE21, 0xEEC0B18D, 0xA6F30179, 0x9EE26ED5, + 0x36946091, 0x0E850F3D, 0x46B6BFC9, 0x7EA7D065, + 0x13B6D5B0, 0x2BA7BA1C, 0x63940AE8, 0x5B856544, + 0xF3F36B00, 0xCBE204AC, 0x83D1B458, 0xBBC0DBF4, + 0x425B0AA5, 0x7A4A6509, 0x3279D5FD, 0x0A68BA51, + 0xA21EB415, 0x9A0FDBB9, 0xD23C6B4D, 0xEA2D04E1, + 0x873C0134, 0xBF2D6E98, 0xF71EDE6C, 0xCF0FB1C0, + 0x6779BF84, 0x5F68D028, 0x175B60DC, 0x2F4A0F70, + 0xCD796B76, 0xF56804DA, 0xBD5BB42E, 0x854ADB82, + 0x2D3CD5C6, 0x152DBA6A, 0x5D1E0A9E, 0x650F6532, + 0x081E60E7, 0x300F0F4B, 0x783CBFBF, 0x402DD013, + 0xE85BDE57, 0xD04AB1FB, 0x9879010F, 0xA0686EA3 + }; + + const static uint32_t T8_5[] = + { + 0x00000000, 0xEF306B19, 0xDB8CA0C3, 0x34BCCBDA, + 0xB2F53777, 0x5DC55C6E, 0x697997B4, 0x8649FCAD, + 0x6006181F, 0x8F367306, 0xBB8AB8DC, 0x54BAD3C5, + 0xD2F32F68, 0x3DC34471, 0x097F8FAB, 0xE64FE4B2, + 0xC00C303E, 0x2F3C5B27, 0x1B8090FD, 0xF4B0FBE4, + 0x72F90749, 0x9DC96C50, 0xA975A78A, 0x4645CC93, + 0xA00A2821, 0x4F3A4338, 0x7B8688E2, 0x94B6E3FB, + 0x12FF1F56, 0xFDCF744F, 0xC973BF95, 0x2643D48C, + 0x85F4168D, 0x6AC47D94, 0x5E78B64E, 0xB148DD57, + 0x370121FA, 0xD8314AE3, 0xEC8D8139, 0x03BDEA20, + 0xE5F20E92, 0x0AC2658B, 0x3E7EAE51, 0xD14EC548, + 0x570739E5, 0xB83752FC, 0x8C8B9926, 0x63BBF23F, + 0x45F826B3, 0xAAC84DAA, 0x9E748670, 0x7144ED69, + 0xF70D11C4, 0x183D7ADD, 0x2C81B107, 0xC3B1DA1E, + 0x25FE3EAC, 0xCACE55B5, 0xFE729E6F, 0x1142F576, + 0x970B09DB, 0x783B62C2, 0x4C87A918, 0xA3B7C201, + 0x0E045BEB, 0xE13430F2, 0xD588FB28, 0x3AB89031, + 0xBCF16C9C, 0x53C10785, 0x677DCC5F, 0x884DA746, + 0x6E0243F4, 0x813228ED, 0xB58EE337, 0x5ABE882E, + 0xDCF77483, 0x33C71F9A, 0x077BD440, 0xE84BBF59, + 0xCE086BD5, 0x213800CC, 0x1584CB16, 0xFAB4A00F, + 0x7CFD5CA2, 0x93CD37BB, 0xA771FC61, 0x48419778, + 0xAE0E73CA, 0x413E18D3, 0x7582D309, 0x9AB2B810, + 0x1CFB44BD, 0xF3CB2FA4, 0xC777E47E, 0x28478F67, + 0x8BF04D66, 0x64C0267F, 0x507CEDA5, 0xBF4C86BC, + 0x39057A11, 0xD6351108, 0xE289DAD2, 0x0DB9B1CB, + 0xEBF65579, 0x04C63E60, 0x307AF5BA, 0xDF4A9EA3, + 0x5903620E, 0xB6330917, 0x828FC2CD, 0x6DBFA9D4, + 0x4BFC7D58, 0xA4CC1641, 0x9070DD9B, 0x7F40B682, + 0xF9094A2F, 0x16392136, 0x2285EAEC, 0xCDB581F5, + 0x2BFA6547, 0xC4CA0E5E, 0xF076C584, 0x1F46AE9D, + 0x990F5230, 0x763F3929, 0x4283F2F3, 0xADB399EA, + 0x1C08B7D6, 0xF338DCCF, 0xC7841715, 0x28B47C0C, + 0xAEFD80A1, 0x41CDEBB8, 0x75712062, 0x9A414B7B, + 0x7C0EAFC9, 0x933EC4D0, 0xA7820F0A, 0x48B26413, + 0xCEFB98BE, 0x21CBF3A7, 0x1577387D, 0xFA475364, + 0xDC0487E8, 0x3334ECF1, 0x0788272B, 0xE8B84C32, + 0x6EF1B09F, 0x81C1DB86, 0xB57D105C, 0x5A4D7B45, + 0xBC029FF7, 0x5332F4EE, 0x678E3F34, 0x88BE542D, + 0x0EF7A880, 0xE1C7C399, 0xD57B0843, 0x3A4B635A, + 0x99FCA15B, 0x76CCCA42, 0x42700198, 0xAD406A81, + 0x2B09962C, 0xC439FD35, 0xF08536EF, 0x1FB55DF6, + 0xF9FAB944, 0x16CAD25D, 0x22761987, 0xCD46729E, + 0x4B0F8E33, 0xA43FE52A, 0x90832EF0, 0x7FB345E9, + 0x59F09165, 0xB6C0FA7C, 0x827C31A6, 0x6D4C5ABF, + 0xEB05A612, 0x0435CD0B, 0x308906D1, 0xDFB96DC8, + 0x39F6897A, 0xD6C6E263, 0xE27A29B9, 0x0D4A42A0, + 0x8B03BE0D, 0x6433D514, 0x508F1ECE, 0xBFBF75D7, + 0x120CEC3D, 0xFD3C8724, 0xC9804CFE, 0x26B027E7, + 0xA0F9DB4A, 0x4FC9B053, 0x7B757B89, 0x94451090, + 0x720AF422, 0x9D3A9F3B, 0xA98654E1, 0x46B63FF8, + 0xC0FFC355, 0x2FCFA84C, 0x1B736396, 0xF443088F, + 0xD200DC03, 0x3D30B71A, 0x098C7CC0, 0xE6BC17D9, + 0x60F5EB74, 0x8FC5806D, 0xBB794BB7, 0x544920AE, + 0xB206C41C, 0x5D36AF05, 0x698A64DF, 0x86BA0FC6, + 0x00F3F36B, 0xEFC39872, 0xDB7F53A8, 0x344F38B1, + 0x97F8FAB0, 0x78C891A9, 0x4C745A73, 0xA344316A, + 0x250DCDC7, 0xCA3DA6DE, 0xFE816D04, 0x11B1061D, + 0xF7FEE2AF, 0x18CE89B6, 0x2C72426C, 0xC3422975, + 0x450BD5D8, 0xAA3BBEC1, 0x9E87751B, 0x71B71E02, + 0x57F4CA8E, 0xB8C4A197, 0x8C786A4D, 0x63480154, + 0xE501FDF9, 0x0A3196E0, 0x3E8D5D3A, 0xD1BD3623, + 0x37F2D291, 0xD8C2B988, 0xEC7E7252, 0x034E194B, + 0x8507E5E6, 0x6A378EFF, 0x5E8B4525, 0xB1BB2E3C + }; + + const static uint32_t T8_6[] = + { + 0x00000000, 0x68032CC8, 0xD0065990, 0xB8057558, + 0xA5E0C5D1, 0xCDE3E919, 0x75E69C41, 0x1DE5B089, + 0x4E2DFD53, 0x262ED19B, 0x9E2BA4C3, 0xF628880B, + 0xEBCD3882, 0x83CE144A, 0x3BCB6112, 0x53C84DDA, + 0x9C5BFAA6, 0xF458D66E, 0x4C5DA336, 0x245E8FFE, + 0x39BB3F77, 0x51B813BF, 0xE9BD66E7, 0x81BE4A2F, + 0xD27607F5, 0xBA752B3D, 0x02705E65, 0x6A7372AD, + 0x7796C224, 0x1F95EEEC, 0xA7909BB4, 0xCF93B77C, + 0x3D5B83BD, 0x5558AF75, 0xED5DDA2D, 0x855EF6E5, + 0x98BB466C, 0xF0B86AA4, 0x48BD1FFC, 0x20BE3334, + 0x73767EEE, 0x1B755226, 0xA370277E, 0xCB730BB6, + 0xD696BB3F, 0xBE9597F7, 0x0690E2AF, 0x6E93CE67, + 0xA100791B, 0xC90355D3, 0x7106208B, 0x19050C43, + 0x04E0BCCA, 0x6CE39002, 0xD4E6E55A, 0xBCE5C992, + 0xEF2D8448, 0x872EA880, 0x3F2BDDD8, 0x5728F110, + 0x4ACD4199, 0x22CE6D51, 0x9ACB1809, 0xF2C834C1, + 0x7AB7077A, 0x12B42BB2, 0xAAB15EEA, 0xC2B27222, + 0xDF57C2AB, 0xB754EE63, 0x0F519B3B, 0x6752B7F3, + 0x349AFA29, 0x5C99D6E1, 0xE49CA3B9, 0x8C9F8F71, + 0x917A3FF8, 0xF9791330, 0x417C6668, 0x297F4AA0, + 0xE6ECFDDC, 0x8EEFD114, 0x36EAA44C, 0x5EE98884, + 0x430C380D, 0x2B0F14C5, 0x930A619D, 0xFB094D55, + 0xA8C1008F, 0xC0C22C47, 0x78C7591F, 0x10C475D7, + 0x0D21C55E, 0x6522E996, 0xDD279CCE, 0xB524B006, + 0x47EC84C7, 0x2FEFA80F, 0x97EADD57, 0xFFE9F19F, + 0xE20C4116, 0x8A0F6DDE, 0x320A1886, 0x5A09344E, + 0x09C17994, 0x61C2555C, 0xD9C72004, 0xB1C40CCC, + 0xAC21BC45, 0xC422908D, 0x7C27E5D5, 0x1424C91D, + 0xDBB77E61, 0xB3B452A9, 0x0BB127F1, 0x63B20B39, + 0x7E57BBB0, 0x16549778, 0xAE51E220, 0xC652CEE8, + 0x959A8332, 0xFD99AFFA, 0x459CDAA2, 0x2D9FF66A, + 0x307A46E3, 0x58796A2B, 0xE07C1F73, 0x887F33BB, + 0xF56E0EF4, 0x9D6D223C, 0x25685764, 0x4D6B7BAC, + 0x508ECB25, 0x388DE7ED, 0x808892B5, 0xE88BBE7D, + 0xBB43F3A7, 0xD340DF6F, 0x6B45AA37, 0x034686FF, + 0x1EA33676, 0x76A01ABE, 0xCEA56FE6, 0xA6A6432E, + 0x6935F452, 0x0136D89A, 0xB933ADC2, 0xD130810A, + 0xCCD53183, 0xA4D61D4B, 0x1CD36813, 0x74D044DB, + 0x27180901, 0x4F1B25C9, 0xF71E5091, 0x9F1D7C59, + 0x82F8CCD0, 0xEAFBE018, 0x52FE9540, 0x3AFDB988, + 0xC8358D49, 0xA036A181, 0x1833D4D9, 0x7030F811, + 0x6DD54898, 0x05D66450, 0xBDD31108, 0xD5D03DC0, + 0x8618701A, 0xEE1B5CD2, 0x561E298A, 0x3E1D0542, + 0x23F8B5CB, 0x4BFB9903, 0xF3FEEC5B, 0x9BFDC093, + 0x546E77EF, 0x3C6D5B27, 0x84682E7F, 0xEC6B02B7, + 0xF18EB23E, 0x998D9EF6, 0x2188EBAE, 0x498BC766, + 0x1A438ABC, 0x7240A674, 0xCA45D32C, 0xA246FFE4, + 0xBFA34F6D, 0xD7A063A5, 0x6FA516FD, 0x07A63A35, + 0x8FD9098E, 0xE7DA2546, 0x5FDF501E, 0x37DC7CD6, + 0x2A39CC5F, 0x423AE097, 0xFA3F95CF, 0x923CB907, + 0xC1F4F4DD, 0xA9F7D815, 0x11F2AD4D, 0x79F18185, + 0x6414310C, 0x0C171DC4, 0xB412689C, 0xDC114454, + 0x1382F328, 0x7B81DFE0, 0xC384AAB8, 0xAB878670, + 0xB66236F9, 0xDE611A31, 0x66646F69, 0x0E6743A1, + 0x5DAF0E7B, 0x35AC22B3, 0x8DA957EB, 0xE5AA7B23, + 0xF84FCBAA, 0x904CE762, 0x2849923A, 0x404ABEF2, + 0xB2828A33, 0xDA81A6FB, 0x6284D3A3, 0x0A87FF6B, + 0x17624FE2, 0x7F61632A, 0xC7641672, 0xAF673ABA, + 0xFCAF7760, 0x94AC5BA8, 0x2CA92EF0, 0x44AA0238, + 0x594FB2B1, 0x314C9E79, 0x8949EB21, 0xE14AC7E9, + 0x2ED97095, 0x46DA5C5D, 0xFEDF2905, 0x96DC05CD, + 0x8B39B544, 0xE33A998C, 0x5B3FECD4, 0x333CC01C, + 0x60F48DC6, 0x08F7A10E, 0xB0F2D456, 0xD8F1F89E, + 0xC5144817, 0xAD1764DF, 0x15121187, 0x7D113D4F + }; + + const static uint32_t T8_7[] = + { + 0x00000000, 0x493C7D27, 0x9278FA4E, 0xDB448769, + 0x211D826D, 0x6821FF4A, 0xB3657823, 0xFA590504, + 0x423B04DA, 0x0B0779FD, 0xD043FE94, 0x997F83B3, + 0x632686B7, 0x2A1AFB90, 0xF15E7CF9, 0xB86201DE, + 0x847609B4, 0xCD4A7493, 0x160EF3FA, 0x5F328EDD, + 0xA56B8BD9, 0xEC57F6FE, 0x37137197, 0x7E2F0CB0, + 0xC64D0D6E, 0x8F717049, 0x5435F720, 0x1D098A07, + 0xE7508F03, 0xAE6CF224, 0x7528754D, 0x3C14086A, + 0x0D006599, 0x443C18BE, 0x9F789FD7, 0xD644E2F0, + 0x2C1DE7F4, 0x65219AD3, 0xBE651DBA, 0xF759609D, + 0x4F3B6143, 0x06071C64, 0xDD439B0D, 0x947FE62A, + 0x6E26E32E, 0x271A9E09, 0xFC5E1960, 0xB5626447, + 0x89766C2D, 0xC04A110A, 0x1B0E9663, 0x5232EB44, + 0xA86BEE40, 0xE1579367, 0x3A13140E, 0x732F6929, + 0xCB4D68F7, 0x827115D0, 0x593592B9, 0x1009EF9E, + 0xEA50EA9A, 0xA36C97BD, 0x782810D4, 0x31146DF3, + 0x1A00CB32, 0x533CB615, 0x8878317C, 0xC1444C5B, + 0x3B1D495F, 0x72213478, 0xA965B311, 0xE059CE36, + 0x583BCFE8, 0x1107B2CF, 0xCA4335A6, 0x837F4881, + 0x79264D85, 0x301A30A2, 0xEB5EB7CB, 0xA262CAEC, + 0x9E76C286, 0xD74ABFA1, 0x0C0E38C8, 0x453245EF, + 0xBF6B40EB, 0xF6573DCC, 0x2D13BAA5, 0x642FC782, + 0xDC4DC65C, 0x9571BB7B, 0x4E353C12, 0x07094135, + 0xFD504431, 0xB46C3916, 0x6F28BE7F, 0x2614C358, + 0x1700AEAB, 0x5E3CD38C, 0x857854E5, 0xCC4429C2, + 0x361D2CC6, 0x7F2151E1, 0xA465D688, 0xED59ABAF, + 0x553BAA71, 0x1C07D756, 0xC743503F, 0x8E7F2D18, + 0x7426281C, 0x3D1A553B, 0xE65ED252, 0xAF62AF75, + 0x9376A71F, 0xDA4ADA38, 0x010E5D51, 0x48322076, + 0xB26B2572, 0xFB575855, 0x2013DF3C, 0x692FA21B, + 0xD14DA3C5, 0x9871DEE2, 0x4335598B, 0x0A0924AC, + 0xF05021A8, 0xB96C5C8F, 0x6228DBE6, 0x2B14A6C1, + 0x34019664, 0x7D3DEB43, 0xA6796C2A, 0xEF45110D, + 0x151C1409, 0x5C20692E, 0x8764EE47, 0xCE589360, + 0x763A92BE, 0x3F06EF99, 0xE44268F0, 0xAD7E15D7, + 0x572710D3, 0x1E1B6DF4, 0xC55FEA9D, 0x8C6397BA, + 0xB0779FD0, 0xF94BE2F7, 0x220F659E, 0x6B3318B9, + 0x916A1DBD, 0xD856609A, 0x0312E7F3, 0x4A2E9AD4, + 0xF24C9B0A, 0xBB70E62D, 0x60346144, 0x29081C63, + 0xD3511967, 0x9A6D6440, 0x4129E329, 0x08159E0E, + 0x3901F3FD, 0x703D8EDA, 0xAB7909B3, 0xE2457494, + 0x181C7190, 0x51200CB7, 0x8A648BDE, 0xC358F6F9, + 0x7B3AF727, 0x32068A00, 0xE9420D69, 0xA07E704E, + 0x5A27754A, 0x131B086D, 0xC85F8F04, 0x8163F223, + 0xBD77FA49, 0xF44B876E, 0x2F0F0007, 0x66337D20, + 0x9C6A7824, 0xD5560503, 0x0E12826A, 0x472EFF4D, + 0xFF4CFE93, 0xB67083B4, 0x6D3404DD, 0x240879FA, + 0xDE517CFE, 0x976D01D9, 0x4C2986B0, 0x0515FB97, + 0x2E015D56, 0x673D2071, 0xBC79A718, 0xF545DA3F, + 0x0F1CDF3B, 0x4620A21C, 0x9D642575, 0xD4585852, + 0x6C3A598C, 0x250624AB, 0xFE42A3C2, 0xB77EDEE5, + 0x4D27DBE1, 0x041BA6C6, 0xDF5F21AF, 0x96635C88, + 0xAA7754E2, 0xE34B29C5, 0x380FAEAC, 0x7133D38B, + 0x8B6AD68F, 0xC256ABA8, 0x19122CC1, 0x502E51E6, + 0xE84C5038, 0xA1702D1F, 0x7A34AA76, 0x3308D751, + 0xC951D255, 0x806DAF72, 0x5B29281B, 0x1215553C, + 0x230138CF, 0x6A3D45E8, 0xB179C281, 0xF845BFA6, + 0x021CBAA2, 0x4B20C785, 0x906440EC, 0xD9583DCB, + 0x613A3C15, 0x28064132, 0xF342C65B, 0xBA7EBB7C, + 0x4027BE78, 0x091BC35F, 0xD25F4436, 0x9B633911, + 0xA777317B, 0xEE4B4C5C, 0x350FCB35, 0x7C33B612, + 0x866AB316, 0xCF56CE31, 0x14124958, 0x5D2E347F, + 0xE54C35A1, 0xAC704886, 0x7734CFEF, 0x3E08B2C8, + 0xC451B7CC, 0x8D6DCAEB, 0x56294D82, 0x1F1530A5 + }; + + uint64_t localCrc = crc; + int64_t off = 0; + while (len > 7) { + uint64_t c0 = buf[off++] ^ localCrc; + uint64_t c1 = buf[off++] ^ (localCrc >>= 8); + uint64_t c2 = buf[off++] ^ (localCrc >>= 8); + uint64_t c3 = buf[off++] ^ (localCrc >>= 8); + localCrc = (T8_7[c0 & 0xff] ^ T8_6[c1 & 0xff]) ^ (T8_5[c2 & 0xff] ^ T8_4[c3 & 0xff]); + + c3 = T8_3[buf[off++] & 0xff]; + c2 = T8_2[buf[off++] & 0xff]; + c1 = T8_1[buf[off++] & 0xff]; + c0 = T8_0[buf[off++] & 0xff]; + localCrc ^= (c3 ^ c2) ^ (c1 ^ c0); + + len -= 8; + } + while (len > 0) { + localCrc = (localCrc >> 8) ^ T8_0[(localCrc ^ buf[off++]) & 0xff]; + len--; + } + + crc = (localCrc & 0xffffffffL); + + return crc; +} + uint64_t crc64_sse42_dispatch(uint64_t crc, const char *buf, int64_t len) { -/* + #if defined (__x86_64__) uint32_t a = 0; uint32_t b = 0; uint32_t c = 0; uint32_t d = 0; asm("cpuid": "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(1)); - if (c & (1 << 20)) { + if ((c & (1 << 20)) != 0) { ob_crc64_sse42_func = &crc64_sse42; _OB_LOG(INFO, "Use CPU crc32 instructs for crc64 calculate"); } else { -*/ - ob_crc64_sse42_func = &crc64_sse42_manually; + ob_crc64_sse42_func = &fast_crc64_sse42_manually; + _OB_LOG(INFO, "Use manual crc32 table lookup for crc64 calculate"); + } + #elif defined(__aarch64__) + #if 1 + ob_crc64_sse42_func = &crc64_sse42; + _OB_LOG(INFO, "Use CPU crc32 instructs for crc64 calculate"); + #else + ob_crc64_sse42_func = &fast_crc64_sse42_manually; _OB_LOG(INFO, "Use manual crc32 table lookup for crc64 calculate"); -// } + #endif + #else + #error arch unsupported + #endif return (*ob_crc64_sse42_func)(crc, buf, len); } diff --git a/src/lib/encode/ob_base64_encode.cpp b/src/lib/encode/ob_base64_encode.cpp index 27df4693c7ea4bf172cee2f8acdb32129d825d47..b9a520f89e454c18a42619a611316ff26b8c09c9 100644 --- a/src/lib/encode/ob_base64_encode.cpp +++ b/src/lib/encode/ob_base64_encode.cpp @@ -24,6 +24,26 @@ char ObBase64Encoder::BASE64_CHARS[] = "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; +int ObBase64Encoder::FROM_BASE64_TABLE[] = +{ +/*00*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2,-1,-1, +/*10*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +/*20*/ -2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, /* !"#$%&'()*+,-./ */ +/*30*/ 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, /* 0123456789:;<=>? */ +/*40*/ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, /* @ABCDEFGHIJKLMNO */ +/*50*/ 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, /* PQRSTUVWXYZ[\]^_ */ +/*60*/ -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, /* `abcdefghijklmno */ +/*70*/ 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, /* pqrstuvwxyz{|}~ */ +/*80*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +/*90*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +/*A0*/ -2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +/*B0*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +/*C0*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +/*D0*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +/*E0*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +/*F0*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 +}; + template struct InitBase64Values { @@ -127,7 +147,8 @@ int ObBase64Encoder::encode(const uint8_t *input, const int64_t input_len, } int ObBase64Encoder::decode(const char *input, const int64_t input_len, - uint8_t *output, const int64_t output_len, int64_t &pos) + uint8_t *output, const int64_t output_len, + int64_t &pos, bool skip_spaces) { int ret = OB_SUCCESS; if (OB_ISNULL(input) || OB_ISNULL(output) || @@ -136,23 +157,28 @@ int ObBase64Encoder::decode(const char *input, const int64_t input_len, _OB_LOG(WARN, "invalid argument input=%p, output=%p, input_len=%ld, output_len=%ld, pos=%ld", input, output, input_len, output_len, pos); } else { - // unused - // int64_t remain_len = input_len; uint8_t uint8_array_3[3]; uint8_t uint8_array_4[4]; int64_t i = 0; int64_t rounds = input_len / 4; - if ((rounds * 3) + pos > output_len) { + if (OB_UNLIKELY(rounds * 3 + pos > output_len)) { ret = OB_BUF_NOT_ENOUGH; _OB_LOG(WARN, "buffer not enough, pos=%ld, output_len=%ld, input_len=%ld", pos, output_len, input_len); } const char *iter_input = input; + int64_t skipped_spaces = 0; for(; OB_SUCC(ret) && '=' != *iter_input && iter_input < input + input_len; iter_input++) { if (OB_UNLIKELY(!is_base64_char(*iter_input))) { - ret = OB_INVALID_ROWID; - _OB_LOG(WARN, "invalid base64 char, cur_idx=%ld, char=%c", + if (skip_spaces) { + if (my_base64_decoder_skip_spaces(*iter_input)) { + ++skipped_spaces; + } + } else { + ret = OB_INVALID_ARGUMENT; + _OB_LOG(WARN, "invalid base64 char, cur_idx=%ld, char=%c", iter_input - input, *iter_input); + } } else { uint8_array_4[i++] = (uint8_t)(*iter_input); if (4 == i) { @@ -172,14 +198,26 @@ int ObBase64Encoder::decode(const char *input, const int64_t input_len, } // for end int64_t cur_idx = iter_input - input; for (const char *iter = iter_input; iter < input + input_len; iter++) { - // all the rest chars must be '=' - if (OB_UNLIKELY('=' != *iter)) { - ret = OB_INVALID_ROWID; + if (skip_spaces) { + if (my_base64_decoder_skip_spaces(*iter)) { + ++skipped_spaces; + } + } else { + // all the rest chars must be '=' + if (OB_UNLIKELY('=' != *iter)) { + ret = OB_INVALID_ARGUMENT; + } } - } // end for - if (OB_UNLIKELY(cur_idx + 3 <= input_len)) { + }// end for + if (skip_spaces) { + int64_t valid_len = input_len - skipped_spaces; + if (valid_len % 4 != 0 || valid_len < 4 || cur_idx + 3 <= valid_len) { + ret = OB_INVALID_ARGUMENT; + } + } + if (OB_UNLIKELY((cur_idx + 3 <= input_len) && !skip_spaces)) { // only last char or last two chars can be '=' - ret = OB_INVALID_ROWID; + ret = OB_INVALID_ARGUMENT; } else if (i > 0) { for (int k = 0; k < i; k++) { uint8_array_4[k] = BASE64_VALUES[uint8_array_4[k]]; @@ -189,7 +227,11 @@ int ObBase64Encoder::decode(const char *input, const int64_t input_len, if (OB_UNLIKELY(pos + i - 1 >= output_len)) { ret = OB_BUF_NOT_ENOUGH; - _OB_LOG(WARN, "buffer not enought, pos=%ld, output_len = %ld, i = %ld", pos, output_len, i); + if (skip_spaces && (pos + i - 1 >= output_len)) { + ret = OB_INVALID_ARGUMENT; + } else { + _OB_LOG(WARN, "buffer not enough, pos=%ld, output_len = %ld, i = %ld", pos, output_len, i); + } } else { for (int k = 0; k < i - 1; k++) { output[pos++] = (uint8_t)(uint8_array_3[k]); @@ -199,6 +241,7 @@ int ObBase64Encoder::decode(const char *input, const int64_t input_len, } return ret; } + } } // end namespace oceanbase diff --git a/src/lib/encode/ob_base64_encode.h b/src/lib/encode/ob_base64_encode.h index b128aae984e64c9eed859d4db8b20326392b9c47..70e3381f66d9879be4e993d4ac700c99ec8eab76 100644 --- a/src/lib/encode/ob_base64_encode.h +++ b/src/lib/encode/ob_base64_encode.h @@ -26,6 +26,7 @@ private: template friend class InitBase64Values; static char BASE64_CHARS[]; +static int FROM_BASE64_TABLE[]; static uint8_t BASE64_VALUES[256]; @@ -33,6 +34,14 @@ static char BASE64_CHARS[]; { return std::isalnum(c) || c == '+' || c == '/'; } + + static inline bool my_base64_decoder_skip_spaces(char c) + { + if (FROM_BASE64_TABLE[(uint8_t) c] != -2) { + return false; + } + return true; + } public: static int64_t needed_encoded_length(const int64_t buf_size) { @@ -48,7 +57,8 @@ public: char* output, const int64_t output_len, int64_t &pos); static int decode(const char* input, const int64_t input_len, - uint8_t* output, const int64_t output_len, int64_t &pos); + uint8_t* output, const int64_t output_len, + int64_t &pos, bool skip_spaces = false); }; } // end namespace common } // end namespace oceanbase diff --git a/src/lib/encrypt/ob_encrypted_helper.h b/src/lib/encrypt/ob_encrypted_helper.h index fde0d54fd1b9012e79ecc7af0b0237f99c1e8b7b..476f6567660015fc58d4b6272d898ac668509581 100644 --- a/src/lib/encrypt/ob_encrypted_helper.h +++ b/src/lib/encrypt/ob_encrypted_helper.h @@ -20,7 +20,7 @@ #define SCRAMBLE_LENGTH 20 #define SHA1_HASH_SIZE 20 /* Hash size in bytes */ -#define ENC_STRING_BUF_LEN SCRAMBLE_LENGTH * 2 + 1 //strlen(hash str) + '*' +#define ENC_STRING_BUF_LEN SCRAMBLE_LENGTH * 2 + 2 //strlen(hash str) + '*' + '\0' #define ENC_BUF_LEN SCRAMBLE_LENGTH * 2 + 2 //strlen(hash str) + '*' + '\0' #define SHA1CircularShift(bits,word) (((word) << (bits)) | ((word) >> (32-(bits)))) diff --git a/src/lib/hash/ob_build_in_hashmap.h b/src/lib/hash/ob_build_in_hashmap.h index 61fb13c8ed1d612dab633b8ee50fd1e8e21b0232..20bfb26df323b4fc0a0d5da7e74fccd98e650b25 100644 --- a/src/lib/hash/ob_build_in_hashmap.h +++ b/src/lib/hash/ob_build_in_hashmap.h @@ -16,6 +16,7 @@ #include "lib/hash_func/ob_hash_func.h" #include "lib/hash/ob_hashutils.h" #include "lib/list/ob_intrusive_list.h" +#include "lib/lock/ob_drw_lock.h" namespace oceanbase { @@ -240,11 +241,117 @@ public: return ret; } -private: +protected: ObBuildInBucket buckets_[bucket_num]; int64_t count_; // of elements stored in the map. BucketChain bucket_chain_; }; + +template +class ObBuildInHashMapForRefCount : public ObBuildInHashMap { +public: + // Make embedded types easier to use by importing them to the class namespace. + typedef H Hasher; // Rename and promote. + typedef typename Hasher::Key Key; // Key type. + typedef typename Hasher::Value Value; // Stored value (element) type. + typedef typename Hasher::ListHead ListHead; // Anchor for value chain. + + ObBuildInHashMapForRefCount() : ObBuildInHashMap() {} + + // put a key value pair into HashMap + // @retval OB_SUCCESS for success + // @retval OB_HASH_EXIST when the value's pointer already exist + int set_refactored(Value *value) + { + int ret = OB_SUCCESS; + Key key = Hasher::key(value); + obsys::CWLockGuard wlock(locks_[Hasher::hash(key) % bucket_num]); + ret = ObBuildInHashMap::set_refactored(value); + if (OB_SUCC(ret)) { + Hasher::inc_ref(value); + } + return ret; + } + + // put a key value pair into HashMap + // @retval OB_SUCCESS for success + // @retval OB_HASH_EXIST when the value's key already exist + int unique_set(Value *value) + { + int ret = OB_SUCCESS; + Key key = Hasher::key(value); + obsys::CWLockGuard wlock(locks_[Hasher::hash(key) % bucket_num]); + struct ObBuildInHashMap::ObBuildInBucket &bucket = ObBuildInHashMap::buckets_[Hasher::hash(key) % bucket_num]; + if (!bucket.chain_.in(value)) { + Value *v = bucket.chain_.head_; + while (NULL != v && ((!Hasher::equal(key, Hasher::key(v)) && (v != value)) || 0 == Hasher::get_ref(v))) { + v = ListHead::next(v); + } + if (NULL == v) { + bucket.chain_.push(value); + ++ObBuildInHashMap::count_; + // not empty, put it on the non-empty list. + if (1 == ++(bucket.count_)) { + ObBuildInHashMap::bucket_chain_.push(&bucket); + } + } else { + ret = OB_HASH_EXIST; + } + } else { + ret = OB_HASH_EXIST; + } + if (OB_SUCC(ret)) { + Hasher::inc_ref(value); + } + return ret; + } + + // @retval OB_SUCCESS for success + // @retval OB_HASH_NOT_EXIST for key not exist + int get_refactored(Key key, Value *&value) + { + int ret = OB_HASH_NOT_EXIST; + obsys::CRLockGuard rlock(locks_[Hasher::hash(key) % bucket_num]); + const struct ObBuildInHashMap::ObBuildInBucket &bucket = ObBuildInHashMap::buckets_[Hasher::hash(key) % bucket_num]; + Value *v = bucket.chain_.head_; + while (NULL != v && (!Hasher::equal(key, Hasher::key(v)) || 0 == Hasher::get_ref(v))) { + v = ListHead::next(v); + } + if (NULL != (value = v)) { + ret = OB_SUCCESS;; + } + if (OB_SUCC(ret)) { + while (true) { + int64_t ref = Hasher::get_ref(v); + if(ref > 0) { + if (!Hasher::bcas_ref(value, ref, ref + 1)) { + PAUSE(); + } else { + break; + } + } else { + ret = OB_HASH_NOT_EXIST; + value = NULL; + break; + } + } + } + return ret; + } + + void remove(Value* value) + { + if (NULL != value) { + obsys::CWLockGuard wlock(locks_[Hasher::hash(Hasher::key(value)) % bucket_num]); + ObBuildInHashMap::remove(value); + Hasher::destroy(value); + } + } + +protected: + mutable obsys::CRWLock locks_[bucket_num]; +}; + } // namespace hash } // namespace common } // namespace oceanbase diff --git a/src/lib/lock/ob_bucket_lock.h b/src/lib/lock/ob_bucket_lock.h index 3e850cbb782bfce5323c6f946917fb4ea2a3c26c..a4ef58a3de88c95a1c76cc5fd4bdd21958956db8 100644 --- a/src/lib/lock/ob_bucket_lock.h +++ b/src/lib/lock/ob_bucket_lock.h @@ -23,8 +23,10 @@ namespace common class ObBucketLock { public: - ObBucketLock(); - virtual ~ObBucketLock(); + /* this function is defined for c driver client compile */ + ObBucketLock() {} + /* this function is defined for c driver client compile */ + virtual ~ObBucketLock() {} int init( const uint64_t bucket_cnt, const uint32_t latch_id = ObLatchIds::DEFAULT_BUCKET_LOCK, diff --git a/src/lib/lock/ob_latch.cpp b/src/lib/lock/ob_latch.cpp index a53ef8838a74ff177035c3666156f7620c0e22c8..9d717f8256f6f2e8f1846bc700b8de44195923ce 100644 --- a/src/lib/lock/ob_latch.cpp +++ b/src/lib/lock/ob_latch.cpp @@ -279,7 +279,10 @@ int ObLatchWaitQueue::try_lock( COMMON_LOG(ERROR, "Fail to add proc to wait list, ", K(ret)); } } - proc.wait_ = 1; + + if (OB_EAGAIN == ret) { + proc.wait_ = 1; + } } unlock_bucket(bucket); diff --git a/src/lib/net/ob_addr.cpp b/src/lib/net/ob_addr.cpp index ee6fa0bae79c960a61070e97fd750e57e573186d..eda722a765be2b67cc13ecc081f013e6efc5e4df 100644 --- a/src/lib/net/ob_addr.cpp +++ b/src/lib/net/ob_addr.cpp @@ -28,29 +28,49 @@ namespace common // -------------------------------------------------------- // class ObAddr implements // -------------------------------------------------------- -uint32_t ObAddr::convert_ipv4_addr(const char *ip) +int ObAddr::convert_ipv4_addr(const char *ip) { - in_addr binary; - int iret = 0; - uint32_t result = 0; + int ret = OB_SUCCESS; + in_addr in; if (!OB_ISNULL(ip)) { - memset(&binary, 0, sizeof (binary)); - iret = inet_pton(AF_INET, ip, &binary); - if (iret == -1) { // no support family - binary.s_addr = 0; - } else if (iret == 0) { // invalid ip string - binary.s_addr = 0; + MEMSET(&in, 0, sizeof (in)); + int rt = inet_pton(AF_INET, ip, &in); + if (rt != 1) { // wrong ip or error + in.s_addr = 0; + ret = OB_ERR_UNEXPECTED; + LOG_WARN("convert ipv4 addr failed", K(ip)); + } else { + ip_.v4_ = ntohl(in.s_addr); } - result = ntohl(binary.s_addr); } - return result; + return ret; +} + +int ObAddr::convert_ipv6_addr(const char *ip) +{ + int ret = OB_SUCCESS; + in6_addr in6; + if (!OB_ISNULL(ip)) { + memset(&in6, 0, sizeof(in6)); + ret = inet_pton(AF_INET6, ip, &in6); + if (ret != 1) { + memset(&in6, 0, sizeof(in6)); + ret = OB_ERR_UNEXPECTED; + LOG_WARN("convert ipv6 addr failed", K(ip)); + } else { + ret = OB_SUCCESS; + // Stored here in big-endian format + MEMCPY(ip_.v6_, in6.s6_addr, sizeof(ip_.v6_)); + } + } + return ret; } int ObAddr::parse_from_cstring(const char *ipport) { int ret = OB_SUCCESS; - char buf[INET6_ADDRSTRLEN] = ""; + char buf[MAX_IP_ADDR_LENGTH] = ""; int port = 0; if (!OB_ISNULL(ipport)) { @@ -73,15 +93,16 @@ int ObAddr::parse_from_cstring(const char *ipport) if (OB_SUCC(ret)) { if ('[' != buf[0]) { // IPV4 format - if (false == set_ipv4_addr(buf, port)) - { + if (false == set_ipv4_addr(buf, port)) { ret = OB_INVALID_ARGUMENT; } } else { // IPV6 format const char *ipv6 = buf + 1; if (']' == buf[strlen(buf) - 1]) { buf[strlen(buf) - 1] = '\0'; - IGNORE_RETURN set_ipv6_addr(ipv6, port); + if (!set_ipv6_addr(ipv6, port)) { + ret = OB_INVALID_ARGUMENT; + } } else { ret = OB_INVALID_ARGUMENT; } @@ -109,6 +130,17 @@ int64_t ObAddr::to_string(char *buffer, const int64_t size) const (ip_.v4_ >> 8) & 0xFF, (ip_.v4_) & 0xFF); } + } else if (version_ == IPV6) { + char buf[MAX_IP_ADDR_LENGTH]; + struct in6_addr in6; + memset(buf, 0, sizeof(buf)); + MEMCPY(in6.s6_addr, ip_.v6_, sizeof(ip_.v6_)); + inet_ntop(AF_INET6, &in6, buf, MAX_IP_ADDR_LENGTH); + if (port_ > 0) { + databuff_printf(buffer, size, pos, "\"[%s]:%d\"", buf, port_); + } else { + databuff_printf(buffer, size, pos, "\"%s\"", buf); + } } } return pos; @@ -124,6 +156,13 @@ bool ObAddr::ip_to_string(char *buffer, const int32_t size) const (ip_.v4_ >> 16) & 0xFF, (ip_.v4_ >> 8) & 0xFF, (ip_.v4_) & 0xFF); + } else if (version_ == IPV6) { + char buf[MAX_IP_ADDR_LENGTH]; + struct in6_addr in6; + memset(buf, 0, sizeof(buf)); + MEMCPY(in6.s6_addr, ip_.v6_, sizeof(ip_.v6_)); + inet_ntop(AF_INET6, &in6, buf, MAX_IP_ADDR_LENGTH); + snprintf(buffer, size, "%s", buf); } res = true; } @@ -133,58 +172,74 @@ bool ObAddr::ip_to_string(char *buffer, const int32_t size) const int ObAddr::ip_port_to_string(char *buffer, const int32_t size) const { int ret = OB_SUCCESS; + int ret_len = 0; if (NULL == buffer || size <= 0) { ret = OB_INVALID_ARGUMENT; } else if (version_ == IPV6) { - ret = OB_NOT_SUPPORTED; + char buf[MAX_IP_ADDR_LENGTH]; + struct in6_addr in6; + memset(buf, 0, sizeof(buf)); + MEMCPY(in6.s6_addr, ip_.v6_, sizeof(ip_.v6_)); + inet_ntop(AF_INET6, &in6, buf, MAX_IP_ADDR_LENGTH); + ret_len = snprintf(buffer, size, "[%s]:%d", buf, port_); } else { - int ret_len = snprintf(buffer, size, "%d.%d.%d.%d:%d", + ret_len = snprintf(buffer, size, "%d.%d.%d.%d:%d", (ip_.v4_ >> 24) & 0XFF, (ip_.v4_ >> 16) & 0xFF, (ip_.v4_ >> 8) & 0xFF, (ip_.v4_) & 0xFF, port_); - if (ret_len < 0) { - ret = OB_ERR_SYS; - } else if (ret_len >= size) { - ret = OB_SIZE_OVERFLOW; - } + } + + if (ret_len < 0) { + ret = OB_ERR_SYS; + } else if (ret_len >= size) { + ret = OB_SIZE_OVERFLOW; } return ret; } bool ObAddr::set_ipv6_addr(const char *ip, const int32_t port) { - UNUSED(ip); - UNUSED(port); - _OB_LOG(WARN, "set ipv6 address is not complete"); - return false; -} + bool bret = true; + int ret = OB_SUCCESS; + if (NULL == ip || port < 0) { + bret = false; + } else if (OB_FAIL(convert_ipv6_addr(ip))) { + bret = false; + } else { + version_ = IPV6; + port_ = port; + } + return bret; +} bool ObAddr::set_ipv4_addr(const char *ip, const int32_t port) { - bool ret = true; - if (NULL == ip || port <= 0) { - ret = false; + bool bret = true; + int ret = OB_SUCCESS; + if (NULL == ip || port < 0) { + bret = false; + } else if (OB_FAIL(convert_ipv4_addr(ip))) { + bret = false; } else { version_ = IPV4; - ip_.v4_ = convert_ipv4_addr(ip); port_ = port; } - return ret; + return bret; } -bool ObAddr::set_ipv4_addr(const ObString &ip, const int32_t port) +bool ObAddr::set_ip_addr(const ObString &ip, const int32_t port) { bool ret = true; - char ip_buf[OB_IP_STR_BUFF] = ""; - if (ip.length() >= OB_IP_STR_BUFF) { + char ip_buf[MAX_IP_ADDR_LENGTH] = ""; + if (ip.length() >= MAX_IP_ADDR_LENGTH) { ret = false; } else { // ObString may be not terminated by '\0' MEMCPY(ip_buf, ip.ptr(), ip.length()); - ret = set_ipv4_addr(ip_buf, port); + ret = set_ip_addr(ip_buf, port); } return ret; } @@ -194,8 +249,12 @@ bool ObAddr::is_valid() const bool valid = true; if (port_ <= 0) { valid = false; + } else if (IPV4 == version_) { + valid = (0 != ip_.v4_); + } else if (IPV6 == version_) { + valid = ((0 != ip_.v6_[0]) || (0 != ip_.v6_[1]) || (0 != ip_.v6_[2]) || (0 != ip_.v6_[3])); } else { - valid = (IPV4 == version_) && (0 != ip_.v4_); + valid = false; } return valid; } @@ -235,10 +294,17 @@ void ObAddr::set_ipv4_server_id(const int64_t ipv4_server_id) bool ObAddr::operator <(const ObAddr &rv) const { - if ((version_ != rv.version_) || (IPV4 != version_)) { + int64_t ipcmp = 0; + if (version_ != rv.version_) { LOG_ERROR("comparision between different IP versions hasn't supported!"); + } else if (IPV4 == version_) { + ipcmp = static_cast(ip_.v4_) - static_cast(rv.ip_.v4_); + } else if (IPV6 == version_) { + int pos = 0; + for (; ipcmp == 0 && pos < IPV6_LEN; pos++) { + ipcmp = ip_.v6_[pos] - rv.ip_.v6_[pos]; + } } - int ipcmp = ip_.v4_ - rv.ip_.v4_; return (ipcmp < 0) || (0 == ipcmp && port_ < rv.port_); } @@ -271,6 +337,68 @@ void ObAddr::set_port(int32_t port) port_ = port; } +struct sockaddr_storage ObAddr::get_sockaddr() const +{ + struct sockaddr_storage sock_addr; + memset(&sock_addr, 0, sizeof(struct sockaddr_storage)); + if (version_ == IPV4) { + struct sockaddr_in in; + memset(&in, 0, sizeof(struct sockaddr_in)); + in.sin_family = AF_INET; + in.sin_port = (htons)(static_cast(port_)); + in.sin_addr.s_addr = htonl(ip_.v4_); + MEMCPY(&sock_addr, &in, sizeof(in)); + } else if (version_ == IPV6) { + struct sockaddr_in6 in6; + memset(&in6, 0, sizeof(struct sockaddr_in6)); + in6.sin6_family = AF_INET6; + in6.sin6_port = (htons)(static_cast(port_)); + MEMCPY(in6.sin6_addr.s6_addr, ip_.v6_, sizeof(ip_.v6_)); + MEMCPY(&sock_addr, &in6, sizeof(in6)); + } + + return sock_addr; +} + +void ObAddr::set_sockaddr(const struct sockaddr &sock_addr) +{ + if (sock_addr.sa_family == AF_INET) { + version_ = IPV4; + const struct sockaddr_in &in = (struct sockaddr_in&)(sock_addr); + port_ = ntohs(in.sin_port); + ip_.v4_ = ntohl(in.sin_addr.s_addr); + } else if (sock_addr.sa_family == AF_INET6) { + version_ = IPV6; + const struct sockaddr_in6 &in6 = (struct sockaddr_in6&)(sock_addr); + port_ = ntohs(in6.sin6_port); + MEMCPY(ip_.v6_, in6.sin6_addr.s6_addr, sizeof(ip_.v6_)); + } +} + +bool ObAddr::set_ip_addr(const char *ip, const int32_t port) +{ + bool bret = false; + const char *ch = strchr(ip, ':'); + if (NULL != ch) { + bret = set_ipv6_addr(ip, port); + } else { + bret = set_ipv4_addr(ip, port); + } + return bret; +} + +bool ObAddr::set_ipv6_addr(const uint64_t ipv6_high, const uint64_t ipv6_low, const int32_t port) +{ + bool ret = true; + uint64_t *high = reinterpret_cast(&ip_.v6_[0]); + uint64_t *low = reinterpret_cast(&ip_.v6_[8]); + *high = ipv6_high; + *low = ipv6_low; + version_ = IPV6; + port_= port; + return ret; +} + OB_SERIALIZE_MEMBER(ObAddr, version_, ip_.v6_[0], ip_.v6_[1], ip_.v6_[2], ip_.v6_[3], port_); } // end namespace common diff --git a/src/lib/net/ob_addr.h b/src/lib/net/ob_addr.h index 5d92f6f2ea53816e6e0494902baea3dd77ea92b5..21383a8816f188e1ba145c81ffd5f8e71969b51f 100644 --- a/src/lib/net/ob_addr.h +++ b/src/lib/net/ob_addr.h @@ -19,28 +19,33 @@ #include "lib/container/ob_se_array.h" #include "lib/json/ob_yson.h" #include "lib/ob_name_id_def.h" +#include "iocore/net/ob_inet.h" namespace oceanbase { namespace common { +#define IPV6_LEN 16 + class ObAddr { OB_UNIS_VERSION(1); public: enum VER { - IPV4 = 4, IPV6 = 6 + IPV4 = 4, + IPV6 = 6, + IPINVALID, }; ObAddr() - : version_(IPV4), ip_(), port_(0) + : version_(IPINVALID), ip_(), port_(0) { memset(&ip_, 0, sizeof(ip_)); } ObAddr(VER version, const char *ip, const int32_t port) - : version_(IPV4), ip_(), port_(0) + : version_(IPINVALID), ip_(), port_(0) { memset(&ip_, 0, sizeof(ip_)); if (version == IPV4) { @@ -50,15 +55,20 @@ public: } } + // The server_id format cannot be used in the case of IPV6 + // TODO: Consider removing it explicit ObAddr(const int64_t ipv4_server_id) - : version_(IPV4), ip_(), port_(0) + : version_(IPINVALID), ip_(), port_(0) { + // server_id only supports IPV4 format + version_ = IPV4; ip_.v4_ = static_cast(0x00000000ffffffff & (ipv4_server_id >> 32)); port_ = static_cast(0x00000000ffffffff & ipv4_server_id); } void reset() { + version_ = IPINVALID; port_ = 0; memset(&ip_, 0, sizeof (ip_)); } @@ -68,7 +78,10 @@ public: return (IPV4 == version_ && INADDR_LOOPBACK == ip_.v4_) || (IPV6 == version_ && IN6_IS_ADDR_LOOPBACK(ip_.v6_)); } - static uint32_t convert_ipv4_addr(const char *ip); + int convert_ipv4_addr(const char *ip); + int convert_ipv6_addr(const char *ip); + struct sockaddr_storage get_sockaddr() const; + void set_sockaddr(const struct sockaddr &sock_addr); int64_t to_string(char *buffer, const int64_t size) const; bool ip_to_string(char *buffer, const int32_t size) const; @@ -76,10 +89,12 @@ public: TO_YSON_KV(ID(ip), ip_.v4_, ID(port), port_); + bool set_ip_addr(const char *ip, const int32_t port); + bool set_ip_addr(const ObString &ip, const int32_t port); bool set_ipv6_addr(const char *ip, const int32_t port); + bool set_ipv6_addr(const uint64_t ipv6_high, const uint64_t ipv6_low, const int32_t port); bool set_ipv4_addr(const char *ip, const int32_t port); bool set_ipv4_addr(const uint32_t ip, const int32_t port); - bool set_ipv4_addr(const ObString &ip, const int32_t port); int parse_from_cstring(const char *ip_str); int64_t get_ipv4_server_id() const; @@ -89,6 +104,7 @@ public: bool operator !=(const ObAddr &rv) const; bool operator ==(const ObAddr &rv) const; bool operator < (const ObAddr &rv) const; + ObAddr& operator = (const ObAddr &rv); int compare(const ObAddr &rv) const; bool is_equal_except_port(const ObAddr &rv) const; inline int32_t get_version() const { return version_; } @@ -102,10 +118,12 @@ public: void reset_ipv4_10(int ip = 10); -private: +public: VER version_; union { + // v4 addresses are stored in native byte order, + // v6 addresses are stored in network byte order uint32_t v4_; //host byte order uint32_t v6_[4]; } ip_; @@ -139,6 +157,16 @@ bool ObAddr::operator ==(const ObAddr &rv) const && ip_.v6_[2] == rv.ip_.v6_[2] && ip_.v6_[3] == rv.ip_.v6_[3]; } +ObAddr& ObAddr::operator =(const ObAddr &rv) +{ + if (this != &rv) { + version_ = rv.version_; + port_ = rv.port_; + MEMCPY(ip_.v6_, rv.ip_.v6_, sizeof(ip_.v6_)); + } + return *this; +} + int ObAddr::compare(const ObAddr &rv) const { return memcmp(this, &rv, sizeof(ObAddr)); diff --git a/src/lib/ob_define.h b/src/lib/ob_define.h index 96a831197714933c80d00d9b0e35226326d0630b..e80ff17f96504581d175e64072f48e52e1f71a87 100644 --- a/src/lib/ob_define.h +++ b/src/lib/ob_define.h @@ -53,7 +53,7 @@ const int64_t OB_MAX_CLUSTER_ID = 4294901759; const int64_t OB_INVALID_CLUSTER_ID = -1; const int64_t OB_INVALID_ORG_CLUSTER_ID = 0; const int64_t OB_MAX_ITERATOR = 16; -const int64_t MAX_IP_ADDR_LENGTH = 32; +const int64_t MAX_IP_ADDR_LENGTH = 64; const int64_t MAX_IP_PORT_LENGTH = MAX_IP_ADDR_LENGTH + 5; const int64_t MAX_IP_PORT_SQL_LENGTH = MAX_IP_ADDR_LENGTH + 10; const int64_t OB_MAX_SQL_ID_LENGTH = 32; @@ -178,7 +178,6 @@ const int64_t OB_MAX_BATCH_NUMBER = 100; const int64_t OB_MAX_TABLET_LIST_NUMBER = 64; const int64_t OB_MAX_DISK_NUMBER = 16; // must no more than ObTimer::MAX_TASK_NUM const int64_t OB_MAX_TIME_STR_LENGTH = 64; -const int64_t OB_IP_STR_BUFF = 30; //TODO: uniform IP/PORR length const int64_t OB_IP_PORT_STR_BUFF = 64; const int64_t OB_RANGE_STR_BUFSIZ = 512; const int64_t OB_MAX_FETCH_CMD_LENGTH = 2048; @@ -392,8 +391,6 @@ const char *const OB_INTERNAL_USER = "__ob_server"; const char *const OB_SERVER_ROLE_VAR_NAME = "__ob_server_role"; //trace id const char *const OB_TRACE_ID_VAR_NAME = "__ob_trace_id"; -const char *const OB_TRACE_INFO_VAR_NAME = "ob_trace_info"; -const char *const OB_TRACE_INFO_CLIENT_IP = "client_ip"; const int64_t MAX_IP_BUFFER_LEN = 32; /////////////////////////////////////////////////////////// @@ -568,9 +565,16 @@ static const char *const OB_MYSQL_PROXY_SESSION_VARS = "__proxy_session_v static const char *const OB_MYSQL_SCRAMBLE = "__proxy_scramble"; static const char *const OB_MYSQL_PROXY_VERSION = "__proxy_version"; +// another conn attr for different client type which is supported ob2.0 protocol or not +static const char *const OB_MYSQL_CLIENT_LIBOBCLIENT_MODE = "__ob_libobclient"; +static const char *const OB_MYSQL_CLIENT_JDBC_CLIENT_MODE = "__ob_jdbc_client"; + // for java client static const char *const OB_MYSQL_JAVA_CLIENT_MODE_NAME = "__ob_java_client"; +// conn attr which transparent transit to observer +static const char *const OB_MYSQL_OB_CLIENT = "__ob_client"; + // for obproxy and observer compatibility enum ObCapabilityFlagShift { @@ -582,11 +586,15 @@ enum ObCapabilityFlagShift OB_CAP_PRIORITY_HIT_SHIFT, OB_CAP_CHECKSUM_SWITCH_SHIFT, OB_CAP_OCJ_ENABLE_EXTRA_OK_PACKET_SHIFT, - OB_CAP_OB_PROTOCOL_V2_SHIFT, + OB_CAP_OB_PROTOCOL_V2_SHIFT, // 8 OB_CAP_EXTRA_OK_PACKET_FOR_STATISTICS_SHIFT, OB_CAP_ABUNDANT_FEEDBACK, OB_CAP_PL_ROUTE_SHIFT, OB_CAP_PROXY_REROUTE_SHIFT, + OB_CAP_PROXY_SESSION_SYNC_SHIFT, // 13 + OB_CAP_PROXY_FULL_LINK_TRACING_SHIFT, // 14 + OB_CAP_PROXY_NEW_EXTRA_INFO_SHIFT, // 15 + OB_CAP_PROXY_SESSION_VAR_SYNC_SHIFT, // 16 }; #define OB_TEST_CAPABILITY(cap, tg_cap) (((cap) & (tg_cap)) == (tg_cap)) @@ -602,6 +610,11 @@ enum ObCapabilityFlagShift #define OB_CAP_EXTRA_OK_PACKET_FOR_STATISTICS OB_CAP_GET_TYPE(common::OB_CAP_EXTRA_OK_PACKET_FOR_STATISTICS_SHIFT) #define OB_CAP_PL_ROUTE OB_CAP_GET_TYPE(common::OB_CAP_PL_ROUTE_SHIFT) #define OB_CAP_PROXY_REROUTE OB_CAP_GET_TYPE(common::OB_CAP_PROXY_REROUTE_SHIFT) +#define OB_CAP_PROXY_SESSION_SYNC OB_CAP_GET_TYPE(common::OB_CAP_PROXY_SESSION_SYNC_SHIFT) +#define OB_CAP_PROXY_FULL_LINK_TRACING OB_CAP_GET_TYPE(common::OB_CAP_PROXY_FULL_LINK_TRACING_SHIFT) +#define OB_CAP_PROXY_NEW_EXTRA_INFO OB_CAP_GET_TYPE(common::OB_CAP_PROXY_NEW_EXTRA_INFO_SHIFT) +#define OB_CAP_PROXY_SESSION_VAR_SYNC OB_CAP_GET_TYPE(common::OB_CAP_PROXY_SESSION_VAR_SYNC_SHIFT) + // for obproxy debug #define OBPROXY_DEBUG 0 @@ -758,7 +771,7 @@ static const int64_t OB_DEFAULT_MAX_TABLET_SIZE = 256 * 1024 * 1024 static const int32_t OB_DEFAULT_CHARACTER_SET = 33; //UTF8 static const int64_t OB_MYSQL_PACKET_BUFF_SIZE = 6 * 1024; //6KB static const int64_t OB_MAX_THREAD_NUM = 4096; -static const int64_t OB_MAX_CPU_NUM = 64; +static const int64_t OB_MAX_CPU_NUM = 256; static const int64_t OB_MAX_STATICS_PER_TABLE = 128; static const int64_t OB_INDEX_WRITE_START_DELAY = 20 * 1000 * 1000; //20s diff --git a/src/lib/ob_errno.cpp b/src/lib/ob_errno.cpp index cd22aa14e0f9f7f51a1937c6fda5ac90ad744a1c..9814f317ad89765fb3c16f5136418a82b72d07a0 100644 --- a/src/lib/ob_errno.cpp +++ b/src/lib/ob_errno.cpp @@ -8,11 +8,6 @@ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PubL v2 for more details. - * - * ************************************************************* - * - * DO NOT EDIT. This file is automatically generated from `ob_errno.def'. - * */ #include "ob_errno.h" @@ -1443,7 +1438,7 @@ static struct ObStrErrorInit STR_USER_ERROR[-OB_ERR_INVALID_COLUMN_NUM] = "Operand should contain %d column(s)"; MYSQL_ERRNO[-OB_ERR_PREPARE_STMT_NOT_FOUND] = ER_UNKNOWN_STMT_HANDLER; SQLSTATE[-OB_ERR_PREPARE_STMT_NOT_FOUND] = "HY007"; - STR_ERROR[-OB_ERR_PREPARE_STMT_NOT_FOUND] = "Unknown prepared statement"; + STR_ERROR[-OB_ERR_PREPARE_STMT_NOT_FOUND] = "Unknown prepared statement handle"; STR_USER_ERROR[-OB_ERR_PREPARE_STMT_NOT_FOUND] = "statement not prepared, stmt_id=%u"; MYSQL_ERRNO[-OB_ERR_SYS_VARIABLE_UNKNOWN] = ER_UNKNOWN_SYSTEM_VARIABLE; SQLSTATE[-OB_ERR_SYS_VARIABLE_UNKNOWN] = "HY000"; @@ -2657,6 +2652,14 @@ static struct ObStrErrorInit SQLSTATE[-OB_TRANS_RPC_TIMEOUT] = "25000"; STR_ERROR[-OB_TRANS_RPC_TIMEOUT] = "transaction rpc timeout"; STR_USER_ERROR[-OB_TRANS_RPC_TIMEOUT] = "transaction rpc timeout"; + + // in transaction internal routing, if sql not supported to be executed on participant sent to participant + // server return OB_TRANS_FREE_ROUTE_NOT_SUPPORTED + // proxy downgrade transaction internal routing and send the rest of sql to coordinator + MYSQL_ERRNO[-OB_TRANS_FREE_ROUTE_NOT_SUPPORTED] = -1; + SQLSTATE[-OB_TRANS_FREE_ROUTE_NOT_SUPPORTED] = "HY000"; + STR_ERROR[-OB_TRANS_FREE_ROUTE_NOT_SUPPORTED] = "Query is not supported to be executed on txn participant node"; + STR_USER_ERROR[-OB_TRANS_FREE_ROUTE_NOT_SUPPORTED] = "Query is not supported to be executed on txn participant node"; MYSQL_ERRNO[-OB_LOG_ID_NOT_FOUND] = -1; SQLSTATE[-OB_LOG_ID_NOT_FOUND] = "HY000"; STR_ERROR[-OB_LOG_ID_NOT_FOUND] = "log id not found"; @@ -2883,8 +2886,8 @@ static struct ObStrErrorInit STR_USER_ERROR[-OB_ERR_NULL_DB_VAL_TESTLOAD_TABLE_MAP] = "Null database variable for testload table map to execute testload query"; MYSQL_ERRNO[-OB_ERR_BATCH_INSERT_FOUND] = -1; SQLSTATE[-OB_ERR_BATCH_INSERT_FOUND] = "HY000"; - STR_ERROR[-OB_ERR_BATCH_INSERT_FOUND] = "Batch insert is not supported for sharding table"; - STR_USER_ERROR[-OB_ERR_BATCH_INSERT_FOUND] = "Batch insert is not supported for sharding table"; + STR_ERROR[-OB_ERR_BATCH_INSERT_FOUND] = "Batch insert is not supported"; + STR_USER_ERROR[-OB_ERR_BATCH_INSERT_FOUND] = "Batch insert is not supported"; MYSQL_ERRNO[-OB_ERR_UNSUPPORT_DIFF_TOPOLOGY] = 7202; SQLSTATE[-OB_ERR_UNSUPPORT_DIFF_TOPOLOGY] = "HY000"; STR_ERROR[-OB_ERR_UNSUPPORT_DIFF_TOPOLOGY] = "Not support different topology table join"; diff --git a/src/lib/ob_errno.h b/src/lib/ob_errno.h index 39f10dbe42d87e4ca357d6d5f9a879083f4a2e59..df603c1e2966ad4d0b4c6866a704ba266474a722 100644 --- a/src/lib/ob_errno.h +++ b/src/lib/ob_errno.h @@ -8,10 +8,6 @@ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PubL v2 for more details. - * - * ************************************************************* - * - * DO NOT EDIT. This file is automatically generated from `ob_errno.def'. */ #ifndef OCEANBASE_LIB_OB_ERRNO_H_ @@ -23,6 +19,7 @@ namespace oceanbase { namespace common { + static const int OB_INTERNAL_ERROR = -600; static const int OB_ORA_FATAL_ERROR = -603; static const int64_t OB_MAX_ERROR_CODE = 10000; static const int OB_LAST_ERROR_CODE = -8003; @@ -704,6 +701,7 @@ namespace common static const int OB_PARTITION_IS_STOPPED = -6228; static const int OB_PARTITION_IS_BLOCKED = -6229; static const int OB_TRANS_RPC_TIMEOUT = -6230; + static const int OB_TRANS_FREE_ROUTE_NOT_SUPPORTED = -6279; static const int OB_LOG_ID_NOT_FOUND = -6301; static const int OB_LSR_THREAD_STOPPED = -6302; static const int OB_NO_LOG = -6303; @@ -1425,6 +1423,7 @@ namespace common #define OB_PARTITION_IS_STOPPED__USER_ERROR_MSG "Partition has been stopped" #define OB_PARTITION_IS_BLOCKED__USER_ERROR_MSG "Partition has been blocked" #define OB_TRANS_RPC_TIMEOUT__USER_ERROR_MSG "transaction rpc timeout" +#define OB_TRANS_FREE_ROUTE_NOT_SUPPORTED__USER_ERROR_MSG "Query is not supported to be executed on txn participant node" #define OB_LOG_ID_NOT_FOUND__USER_ERROR_MSG "log id not found" #define OB_LSR_THREAD_STOPPED__USER_ERROR_MSG "log scan runnable thread stop" #define OB_NO_LOG__USER_ERROR_MSG "no log ever scanned" diff --git a/src/lib/ob_name_id_def.h b/src/lib/ob_name_id_def.h index b9cb2d46d2909855496d33244bb7763113beb9a7..c77b060aad793dd72077b2e5fa9875410d51cadd 100644 --- a/src/lib/ob_name_id_def.h +++ b/src/lib/ob_name_id_def.h @@ -334,7 +334,8 @@ enum ObNameId }; // get name at runtime -const char* get_name(int32_t id); +/* this function is defined for c driver client compile */ +inline const char* get_name(int32_t id) {((void)(id)); return nullptr;}; const char* get_description(int32_t id); } // end namespace name_id_map } // end namespace oceanbase diff --git a/src/lib/oblog/ob_async_log_struct.h b/src/lib/oblog/ob_async_log_struct.h index 6d72dc5355ab842cc8043b9a6de78736f425c46a..79876ece87e4a3ab87728ba89a56e5bfd52fed40 100644 --- a/src/lib/oblog/ob_async_log_struct.h +++ b/src/lib/oblog/ob_async_log_struct.h @@ -20,7 +20,6 @@ #include #include #include "lib/ob_errno.h" -#include "lib/oblog/ob_log_module.h" #include "lib/utility/ob_macro_utils.h" namespace oceanbase @@ -38,6 +37,8 @@ enum ObLogFDType { FD_CONFIG_FILE, //obproxy_config.file FD_POOL_FILE, FD_POOL_STAT_FILE, + FD_TRACE_FILE, // ob20 full link trace interface + FD_DRIVER_CLIENT_FILE, MAX_FD_FILE, }; @@ -96,6 +97,7 @@ public: void set_fd_type(const ObLogFDType fd_type) { fd_type_ = fd_type;} bool is_xflush_file() const { return FD_XFLUSH_FILE == fd_type_; } bool is_default_file() const { return FD_DEFAULT_FILE == fd_type_; } + bool is_trace_file() const { return FD_TRACE_FILE == fd_type_; } void deep_copy_header_only(const ObLogItem &other); private: diff --git a/src/lib/oblog/ob_log.cpp b/src/lib/oblog/ob_log.cpp index 6bb5e9fff33a2e8f5aa87c1086057da51e2c8f1c..2b9d7e08d834a699ae6b932b4d9083bfdf209804 100644 --- a/src/lib/oblog/ob_log.cpp +++ b/src/lib/oblog/ob_log.cpp @@ -375,7 +375,7 @@ ObLogger::~ObLogger() (void)pthread_mutex_destroy(&file_size_mutex_); } -void ObLogger::destory_async_log_thread() +void ObLogger::destroy_async_log_thread() { set_enable_async_log(false); set_stop_flush(); @@ -748,6 +748,12 @@ void ObLogger::log_data(const ObLogFDType type, * '###' is consultation flag for Inspection Module * ${content} is value of config in json format. */ head_size = snprintf(head, MAX_LOG_HEAD_SIZE, "###"); //just print '###' + } else if (FD_TRACE_FILE == type) { + head_size = snprintf(head, MAX_LOG_HEAD_SIZE, + "[%04d-%02d-%02d %02d:%02d:%02d.%06ld] " + "%s (%s:%d) [%ld][" TRACE_ID_FORMAT "] ", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec, + location.function_, base_file_name, location.line_, GETTID(), trace_id_0, trace_id_1); } else if (is_monitor_file(type)) { head_size = snprintf(head, MAX_LOG_HEAD_SIZE, "%04d-%02d-%02d %02d:%02d:%02d.%06ld,", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, @@ -1625,6 +1631,16 @@ int ObLogger::async_log_data_header(const ObLogFDType type, ret = logdata_printf(data_buf, item.get_buf_size(), pos, "%04d-%02d-%02d %02d:%02d:%02d.%06ld,", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec); + } else if (item.is_trace_file()) { + const char *base_file_name = (NULL != file ? strrchr(file, '/') : NULL); + const uint64_t *trace_id = ObCurTraceId::get(); + uint64_t trace_id_0 = (OB_ISNULL(trace_id)) ? OB_INVALID_ID : trace_id[0]; + uint64_t trace_id_1 = (OB_ISNULL(trace_id)) ? OB_INVALID_ID : trace_id[1]; + ret = logdata_printf(data_buf, item.get_buf_size(), pos, + "[%04d-%02d-%02d %02d:%02d:%02d.%06ld] " + "%s (%s:%d) [%ld][" TRACE_ID_FORMAT "] ", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec, + function, base_file_name, line, GETTID(), trace_id_0, trace_id_1); } else { //only print base filename. const char *base_file_name = (NULL != file ? strrchr(file, '/') : NULL); @@ -1693,14 +1709,11 @@ void ObLogger::get_pop_limit(const int32_t level, int64_t &timeout_us) { switch (level) { case OB_LOG_LEVEL_ERROR: { - timeout_us = 100;//100us - break; - } - case OB_LOG_LEVEL_WARN: { timeout_us = 10;//10us break; } - // if INFO Level, no wait + // if INFO/WARN Level, no wait + case OB_LOG_LEVEL_WARN: default: { timeout_us = 0;//0us break; @@ -1729,7 +1742,7 @@ int ObLogger::check_error_log(ObLogItem &log_item) { static const char* const BACKTRACE_END = " BACKTRACE:"; int ret = OB_SUCCESS; - if (OB_LIKELY(OB_LOG_LEVEL_ERROR == log_item.get_log_level())) { + if (OB_LIKELY(OB_LOG_LEVEL_ERROR == log_item.get_log_level()) && !log_item.is_trace_file()) { int64_t pos = (log_item.get_data_len() > 0 ? log_item.get_data_len() - 1 : 0); char *buf = log_item.get_buf(); const int64_t buf_size = log_item.get_buf_size(); diff --git a/src/lib/oblog/ob_log.h b/src/lib/oblog/ob_log.h index 26359f58664dfd1f595fa0aa1e2e1677f57068ae..bab4572a24f7ada90a410e4a5a1d5ca9b719214b 100644 --- a/src/lib/oblog/ob_log.h +++ b/src/lib/oblog/ob_log.h @@ -283,7 +283,7 @@ private: public: ~ObLogger(); - void destory_async_log_thread(); + void destroy_async_log_thread(); int init_async_log_thread(const int64_t stacksize = 0); void destroy_free_litem_queue(); diff --git a/src/lib/oblog/ob_log_module.h b/src/lib/oblog/ob_log_module.h index bf950454b1d62b613069ee1ae1eaa78ffbd29eb6..1f6249cfa8d21b871fc5eeb6112cd20d76f281a0 100644 --- a/src/lib/oblog/ob_log_module.h +++ b/src/lib/oblog/ob_log_module.h @@ -256,6 +256,17 @@ LOG_MOD_END(STORAGETEST) #define _OBPROXY_POOL_STAT_LOG(level, _fmt_, args...) \ (OB_MONITOR_LOG_NEED_TO_PRINT(level) ? _OB_PRINT_TYPE(FD_POOL_STAT_FILE, NULL, level, _fmt_, ##args) : (void) 0) +#define OBPROXY_TRACE_LOG(level, infoString, args...) \ + (OB_MONITOR_LOG_NEED_TO_PRINT(level) ? OB_PRINT_TYPE(FD_TRACE_FILE, NULL, level, infoString, ##args) : (void) 0) +#define _OBPROXY_TRACE_LOG(level, _fmt_, args...) \ + (OB_MONITOR_LOG_NEED_TO_PRINT(level) ? _OB_PRINT_TYPE(FD_TRACE_FILE, NULL, level, _fmt_, ##args) : (void) 0) + +#define OBPROXY_DRIVER_CLIENT_LOG(level, infoString, args...) \ + (OB_LOG_NEED_TO_PRINT(level) ? OB_PRINT_TYPE(FD_DRIVER_CLIENT_FILE, NULL, level, infoString, ##args) : (void) 0) +#define _OBPROXY_DRIVER_CLIENT_LOG(level, _fmt_, args...) \ + (OB_LOG_NEED_TO_PRINT(level) ? _OB_PRINT_TYPE(FD_DRIVER_CLIENT_FILE, NULL, level, _fmt_, ##args) : (void) 0) + + #define _OB_NUM_LEVEL_LOG(level, _fmt_, args...) \ (OB_LOGGER.need_to_print(level) ? \ OB_LOGGER.log_message("", OB_LOG_NUM_LEVEL(level), _fmt_, ##args) : (void) 0) diff --git a/src/lib/oblog/ob_log_print_kv.h b/src/lib/oblog/ob_log_print_kv.h index fedee40e40504cc1b44e0b7c7912e9d96624371b..af937bd4ad82b158742ac1cb69e2bfac487189ea 100644 --- a/src/lib/oblog/ob_log_print_kv.h +++ b/src/lib/oblog/ob_log_print_kv.h @@ -21,6 +21,7 @@ #include "lib/utility/ob_macro_utils.h" #include "lib/utility/ob_template_utils.h" #include "lib/alloc/alloc_assist.h" +#include "obproxy/ob_proxy_init.h" #define LOG_N_TRUE "true" #define LOG_N_FLASE "false" @@ -37,8 +38,8 @@ int logdata_printf(char *buf, const int64_t buf_len, int64_t &pos, const char *f __attribute__((format(printf, 4, 5))); int logdata_vprintf(char *buf, const int64_t buf_len, int64_t &pos, const char *fmt, va_list args); -#define LOG_STDERR(...) do {if(isatty(STDERR_FILENO)) {fprintf(stderr, __VA_ARGS__); }} while(0) -#define LOG_STDOUT(...) do {if(isatty(STDOUT_FILENO)) {fprintf(stdout, __VA_ARGS__); }} while(0) +#define LOG_STDERR(...) do { if(oceanbase::obproxy::RUN_MODE_PROXY == oceanbase::obproxy::g_run_mode && isatty(STDERR_FILENO)) {fprintf(stderr, __VA_ARGS__); }} while(0) +#define LOG_STDOUT(...) do {if(oceanbase::obproxy::RUN_MODE_PROXY == oceanbase::obproxy::g_run_mode && isatty(STDOUT_FILENO)) {fprintf(stdout, __VA_ARGS__); }} while(0) //print errmsg of errno.As strerror not thread-safe, need //to call ERRMSG, KERRMSG which use this class. @@ -370,6 +371,46 @@ int logdata_print_kv(char *buf, const int64_t buf_len, int64_t &pos, const char return logdata_print_key_obj(buf, buf_len, pos, key, false, obj); } +class ObILogKV +{ +public: + virtual int print(char *buf, int64_t buf_len, int64_t &pos, const bool with_comma) const = 0; +}; + +template +class ObLogKV; + +template +class ObLogKV : public ObILogKV +{ +public: + ObLogKV(const char *key, const T &value) : key_(key), value_(value) {} + int print(char *buf, int64_t buf_len, int64_t &pos, const bool with_comma) const override + { + return logdata_print_key_obj(buf, buf_len, pos, key_, + with_comma, value_); + } +private: + const char *key_; + const T &value_; +}; + +template T& unmove(T&& v) { return v; } + +template +class ObLogKV : public ObILogKV +{ +public: + ObLogKV(const char *key, const T &&value) : key_(key), value_(unmove(value)) {} + int print(char *buf, int64_t buf_len, int64_t &pos, const bool with_comma) const override + { + return logdata_print_key_obj(buf, buf_len, pos, key_, + with_comma, value_); + } +private: + const char *key_; + const T &value_; +}; } } @@ -679,4 +720,35 @@ int logdata_print_kv(char *buf, const int64_t buf_len, int64_t &pos, const char log_buffer.check_and_unlock(); \ } +#define LOG_KV(key, obj) \ + (::oceanbase::common::ObILogKV&&)::oceanbase::common::ObLogKV::value>(key, obj) +#define LOG_KVS_0() +#define LOG_KVS_1() +#define LOG_KVS_2(key, obj) , LOG_KV(key, obj) +#define LOG_KVS_4(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_2(args) +#define LOG_KVS_6(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_4(args) +#define LOG_KVS_8(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_6(args) +#define LOG_KVS_10(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_8(args) +#define LOG_KVS_12(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_10(args) +#define LOG_KVS_14(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_12(args) +#define LOG_KVS_16(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_14(args) +#define LOG_KVS_18(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_16(args) +#define LOG_KVS_20(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_18(args) +#define LOG_KVS_22(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_20(args) +#define LOG_KVS_24(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_22(args) +#define LOG_KVS_26(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_24(args) +#define LOG_KVS_28(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_26(args) +#define LOG_KVS_30(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_28(args) +#define LOG_KVS_32(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_30(args) +#define LOG_KVS_34(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_32(args) +#define LOG_KVS_36(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_34(args) +#define LOG_KVS_38(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_36(args) +#define LOG_KVS_40(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_38(args) +#define LOG_KVS_42(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_40(args) +#define LOG_KVS_44(key, obj, args...) , LOG_KV(key, obj) LOG_KVS_42(args) + +#define LOG_KVS_(N, ...) CONCAT(LOG_KVS_, N)(__VA_ARGS__) +#define LOG_KVS(...) "placeholder" LOG_KVS_(ARGS_NUM(__VA_ARGS__), __VA_ARGS__) + #endif diff --git a/src/lib/oblog/ob_simple_trace.h b/src/lib/oblog/ob_simple_trace.h new file mode 100644 index 0000000000000000000000000000000000000000..bd960bc97f6c2ff938de8ea6c283ebdc1170b5b4 --- /dev/null +++ b/src/lib/oblog/ob_simple_trace.h @@ -0,0 +1,190 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef _OB_SIMPLE_TRACE_H +#define _OB_SIMPLE_TRACE_H + +#include "lib/oblog/ob_log.h" + +namespace oceanbase +{ +namespace common +{ + +template +class ObSimpleTraceBase +{ +public: + ObSimpleTraceBase() { reset(); } + ~ObSimpleTraceBase() { } + void reset() + { + pos_ = 0; + buf_[0] = '\0'; + } + template + int log_it(const char *info, Args const & ... args) + { + int ret = common::OB_SUCCESS; + const int64_t saved_pos = pos_; + const char delimiter1[] = " | "; + const char delimiter2[] = "... | "; + if (OB_FAIL(fill_buffer(buf_, BUFFER_SIZE - sizeof(delimiter2), pos_, info, args...))) { + if ((BUFFER_SIZE - saved_pos) >= BUFFER_SIZE / 2) { + // rewrite ret + ret = OB_SUCCESS; + (void)databuff_printf(buf_, BUFFER_SIZE, pos_, delimiter2); + } + } else { + (void)databuff_printf(buf_, BUFFER_SIZE, pos_, delimiter1); + } + if (OB_FAIL(ret)) { + pos_ = saved_pos; + buf_[pos_] = '\0'; + } + return ret; + } + int64_t to_string(char *buf, const int64_t buf_len) const + { + int64_t pos = 0; + databuff_printf(buf, buf_len, pos, "%s", buf_); + return pos; + } +private: + int fill_kv(char *buf, const int64_t buf_len, int64_t &pos, + const bool with_comma) + { + UNUSED(buf); + UNUSED(buf_len); + UNUSED(pos); + UNUSED(with_comma); + return common::OB_SUCCESS; + } + + int fill_kv(char *buf, const int64_t buf_len, int64_t &pos, + const bool with_comma, + const ObILogKV &kv) + { + return kv.print(buf, buf_len, pos, with_comma); + } + + template + int fill_kv(char *buf, const int64_t buf_len, int64_t &pos, + const bool with_comma, + const Key &key, + const Value &value, + Args const & ... args) + { + int ret = OB_SUCCESS; + ret = fill_kv(buf, buf_len, pos, with_comma, LOG_KV(key, value)); + if (OB_SUCC(ret)) { + ret = fill_kv(buf, buf_len, pos, 1, args...); + } + return ret; + } + template + int fill_buffer(char *data, const int64_t buf_len, + int64_t &pos, + const char *info, + Args const & ... args) + { + int ret = OB_SUCCESS; + int64_t tmp_pos = pos; + ret = databuff_printf(data, buf_len, pos, "%s ", info); + if (OB_SUCC(ret)) { + ret = fill_kv(data, buf_len, pos, 0, args...); + } + if (OB_SUCC(ret) && OB_UNLIKELY(OB_LOGGER.get_log_level() >= OB_LOG_LEVEL_TRACE)) { + char tmp_buf[1024]; + memset(tmp_buf, 0, sizeof(tmp_buf)); + int64_t copy_len = pos - tmp_pos > 1023 ? 1023 : pos - tmp_pos; + MEMCPY(tmp_buf, data + tmp_pos, copy_len); + OB_LOG(TRACE, "trace_log", K(tmp_buf)); + } + return ret; + } +private: + char buf_[BUFFER_SIZE]; + int64_t pos_; +}; + +template +class ObSimpleTrace +{ +public: + ObSimpleTrace() { reset(); } + ~ObSimpleTrace() { } + void reset() + { + first_idx_ = 0; + cur_idx_ = 0; + need_print_ = false; + for (int64_t i = 0; i < BASE_TRACE_CNT; i++) { + traces_[i].reset(); + } + } + template + void log_it(const char *info, Args const & ... args) + { + if (need_print_) { + int ret = common::OB_SUCCESS; + for (int64_t i = 0; i < 2; i++) { + cur_idx_ = (cur_idx_ + i) % BASE_TRACE_CNT; + if (1 == i) { + if (cur_idx_ == first_idx_) { + if (OB_UNLIKELY(OB_LOGGER.get_log_level() >= OB_LOG_LEVEL_TRACE)) { + // _LOG(TRACE, "print_trace_log", K(*this)); + } else { + first_idx_ = (first_idx_ + 1) % BASE_TRACE_CNT; + } + } + traces_[cur_idx_].reset(); + } + if (OB_SUCC(traces_[cur_idx_].log_it(info, args...))) { + break; + } + } + (void)ret; + } + } + int64_t to_string(char *buf, const int64_t buf_len) const + { + int64_t pos = 0; + for (int64_t i = 0; i < BASE_TRACE_CNT; i++) { + if (pos < buf_len) { + const int64_t idx = (first_idx_ + i) % BASE_TRACE_CNT; + const int64_t size = traces_[idx].to_string(buf + pos, buf_len - pos); + pos = pos + size; + if (idx == cur_idx_) { + break; + } + } else { + break; + } + } + return pos; + } + void set_need_print(const bool &need_print) { need_print_ = need_print; } +private: + static const int64_t BASE_TRACE_CNT = 4; + static const int64_t BUFFER_SIZE = TRACE_SIZE / BASE_TRACE_CNT; +private: + ObSimpleTraceBase traces_[BASE_TRACE_CNT]; + int64_t first_idx_; + int64_t cur_idx_; + bool need_print_; +}; + +} // end namespace common +} // end namespace oceanbase + +#endif /* _OB_TRACE_EVENT_H */ diff --git a/src/lib/profile/ob_trace_id.h b/src/lib/profile/ob_trace_id.h index 8610cd1267e23a834de8e53d086ea437faed8aa7..80b620ed5bfe822f15f2307218c1f53bbadb6fbf 100644 --- a/src/lib/profile/ob_trace_id.h +++ b/src/lib/profile/ob_trace_id.h @@ -20,7 +20,9 @@ namespace oceanbase { namespace common { -#define TRACE_ID_FORMAT "Y%lX-%lX" + +#define TRACE_ID_FORMAT "Y%lX-%016lX" + struct ObCurTraceId { class SeqGenerator @@ -35,6 +37,7 @@ struct ObCurTraceId inline bool is_invalid() { return id_.seq_ == 0 ? true : false; } inline void init(const ObAddr &ip_port) { + // TODO: Consider whether to support IPv6 id_.seq_ = ATOMIC_AAF(&(SeqGenerator::seq_generator_), 1); id_.ip_ = ip_port.get_ipv4(); id_.reserved_ = 0; @@ -112,6 +115,8 @@ struct ObCurTraceId } }; +uint64_t ObCurTraceId::SeqGenerator::seq_generator_ = 0; + int32_t LogExtraHeaderCallback(char *buf, int32_t buf_size, int level, const char *file, int line, const char *function, pthread_t tid); diff --git a/src/lib/rowid/ob_urowid.cpp b/src/lib/rowid/ob_urowid.cpp index 04952c765b9c1b0c558abc99ff0cc36fca48e10e..c114edf7d78ad3efde927a9e3abdef7b0ada5f9d 100644 --- a/src/lib/rowid/ob_urowid.cpp +++ b/src/lib/rowid/ob_urowid.cpp @@ -16,6 +16,9 @@ #include "lib/encode/ob_base64_encode.h" #include "lib/allocator/ob_allocator.h" #include "lib/container/ob_iarray.h" +#include "obproxy/opsql/expr_resolver/ob_expr_resolver.h" +#include "obproxy/proxy/route/obproxy_part_info.h" +#include "rpc/obmysql/ob_mysql_util.h" namespace oceanbase { @@ -91,9 +94,8 @@ int ObURowIDData::inner_get_pk_value(const uint8_t *rowid_buf, int64_t &pos, ObObj &pk_val) { int ret = OB_SUCCESS; - int64_t needed_size = 4 + pk_val.get_string_len(); - if (OB_LIKELY(pos + needed_size <= rowid_buf_len)) { - uint32_t rowid_len = *(reinterpret_cast(rowid_buf + pos)); + uint32_t rowid_len = *(reinterpret_cast(rowid_buf + pos)); + if (OB_LIKELY(pos + 4 + rowid_len <= rowid_buf_len)) { pos += 4; const char *rowid_content = (const char *)rowid_buf + pos; pk_val.set_urowid(rowid_content, rowid_len); @@ -133,7 +135,8 @@ int ObURowIDData::inner_get_pk_value(const uint8_t *rowid_buf, *(reinterpret_cast(rowid_buf + pos)); \ pos += sizeof(ObNumberDesc); \ int64_t digits_len = sizeof(uint32_t) * num_desc.len_; \ - if (OB_LIKELY(pos + digits_len <= rowid_buf_len)) { \ + if (OB_LIKELY(0 <= digits_len && digits_len <= rowid_buf_len \ + && pos + digits_len <= rowid_buf_len)) { \ const uint32_t *digits = reinterpret_cast(rowid_buf + pos); \ pos += digits_len; \ pk_val.set_##type(num_desc, const_cast(digits)); \ @@ -159,7 +162,7 @@ int ObURowIDData::inner_get_pk_value(const uint8_t *rowid_buf, int32_t char_len = \ *(reinterpret_cast(rowid_buf + pos)); \ pos += 4; \ - if (OB_LIKELY(pos + char_len <= rowid_buf_len)) { \ + if (OB_LIKELY(0 <= char_len && pos + char_len <= rowid_buf_len)) { \ const char *str_val = (const char *)rowid_buf + pos; \ pos += char_len; \ ObString str_value(char_len, str_val); \ @@ -206,19 +209,19 @@ DEF_GET_POD_PK_VALUE(ObIntType, int, int64_t); DEF_GET_POD_PK_VALUE(ObFloatType, float, float); DEF_GET_POD_PK_VALUE(ObDoubleType, double, double); DEF_GET_POD_PK_VALUE(ObDateTimeType, datetime, int64_t); -// DEF_GET_POD_PK_VALUE(ObIntervalYMType, interval_ym, int64_t); +//DEF_GET_POD_PK_VALUE(ObIntervalYMType, interval_ym, int64_t); DEF_GET_NUMBER_PK_VALUE(ObNumberType, number); DEF_GET_NUMBER_PK_VALUE(ObNumberFloatType, number_float); DEF_GET_CHAR_PK_VALUE(ObVarcharType, varchar); DEF_GET_CHAR_PK_VALUE(ObCharType, char); -// DEF_GET_CHAR_PK_VALUE(ObNVarchar2Type, nvarchar2); -// DEF_GET_CHAR_PK_VALUE(ObNCharType, nchar); +DEF_GET_CHAR_PK_VALUE(ObNVarchar2Type, nvarchar2); +DEF_GET_CHAR_PK_VALUE(ObNCharType, nchar); -// DEF_GET_OTIME_PK_VALUE(ObTimestampTZType, timestamp_tz, uint32_t); -// DEF_GET_OTIME_PK_VALUE(ObTimestampLTZType, timestamp_ltz, uint16_t); -// DEF_GET_OTIME_PK_VALUE(ObTimestampNanoType, timestamp_nano, uint16_t); +DEF_GET_OTIME_PK_VALUE(ObTimestampTZType, timestamp_tz, uint32_t); +DEF_GET_OTIME_PK_VALUE(ObTimestampLTZType, timestamp_ltz, uint16_t); +DEF_GET_OTIME_PK_VALUE(ObTimestampNanoType, timestamp_nano, uint16_t); #define ALL_TYPES_USED_IN_INNER_FUNC \ ObNullType, \ @@ -294,10 +297,14 @@ ObURowIDData::get_pk_val_func ObURowIDData::inner_get_funcs_[ObMaxType] = { inline int ObURowIDData::get_pk_value(ObObjType obj_type, int64_t &pos, ObObj &pk_val) const { int ret = OB_SUCCESS; - if (OB_UNLIKELY(obj_type >= ObMaxType) + const uint8_t version = get_version(); + if (OB_UNLIKELY(PK_ROWID_VERSION != version && NO_PK_ROWID_VERSION != version)) { + ret = OB_INVALID_ROWID; + COMMON_LOG(WARN, "invalid rowid version", K(ret), K(version)); + } else if (OB_UNLIKELY(obj_type >= ObMaxType) || OB_UNLIKELY(NULL == inner_get_funcs_[obj_type])) { ret = OB_INVALID_ROWID; - COMMON_LOG(WARN, "invalid type or get null for get pk function", K(obj_type)); + COMMON_LOG(WARN, "invalid type or get null for get pk function", K(ret), K(obj_type)); } else { ret = inner_get_funcs_[obj_type](rowid_content_, rowid_len_, pos, pk_val); } @@ -368,13 +375,18 @@ int ObURowIDData::decode_base64_str(const char *input, const int64_t input_len, OB_UNLIKELY(input_len < 1 || output_len < 0 || pos < 0 || pos >= output_len)) { ret = OB_INVALID_ARGUMENT; COMMON_LOG(WARN, "invalid argument", K(ret)); - } else if (OB_UNLIKELY(input[0] != '*')) { - ret = OB_INVALID_ROWID; - COMMON_LOG(WARN, "invalid urowid format", K(ret)); - } else if (OB_FAIL(ObBase64Encoder::decode(input + 1, input_len - 1, - output, output_len, pos))) { - COMMON_LOG(WARN, "failed to decode base64 str", K(ret)); + } else { + if (input[0] == '*') { + if (OB_FAIL(ObBase64Encoder::decode(input + 1, input_len - 1, output, output_len, pos))) { + COMMON_LOG(WARN, "failed to decode base64 str", K(ret)); + } + } else { + if (OB_FAIL(ObBase64Encoder::decode(input, input_len, output, output_len, pos))) { + COMMON_LOG(WARN, "failed to decode base64 str", K(ret)); + } + } } + return ret; } @@ -383,63 +395,131 @@ int ObURowIDData::decode2urowid(const char* input, const int64_t input_len, { int ret = OB_SUCCESS; uint8_t *decoded_buf = NULL; - int64_t decoded_buf_len = needed_urowid_buf_size(input_len); + int64_t decoded_buf_len = 0; int64_t pos = 0; - if (OB_ISNULL(input)) { + int64_t base64_input_len = 0; + if (OB_UNLIKELY(OB_NOT_NULL(urowid_data.rowid_content_))) { + ret = OB_INIT_TWICE; + COMMON_LOG(WARN, "init twice", K(ret)); + } else if (OB_UNLIKELY(OB_ISNULL(input) || input_len < 1)) { ret = OB_INVALID_ARGUMENT; - COMMON_LOG(WARN, "invalid argument", K(input), K(input_len)); + COMMON_LOG(WARN, "invalid argument", K(ret), K(input), K(input_len)); + } else { + if (input[0] == '*') { + input += 1; + base64_input_len = input_len - 1; + } else { + base64_input_len = input_len; + } + } + if (OB_FAIL(ret)) { + } else if (OB_FALSE_IT(decoded_buf_len = ObBase64Encoder::needed_decoded_length(base64_input_len))) { } else if (OB_UNLIKELY(decoded_buf_len <= 0 || decoded_buf_len % 3 != 0)) { ret = OB_INVALID_ROWID; COMMON_LOG(WARN, "invalid base64 str for rowid", K(ret), K(decoded_buf_len)); - } else if (OB_UNLIKELY(input[0] != '*') || OB_UNLIKELY(input_len < 1)) { - ret = OB_INVALID_ROWID; - COMMON_LOG(WARN, "invalid rowid", K(ret)); } else if (OB_ISNULL(decoded_buf = (uint8_t *)allocator.alloc(decoded_buf_len))) { ret = OB_ALLOCATE_MEMORY_FAILED; COMMON_LOG(WARN, "failed to allocate memory", K(ret), K(decoded_buf_len)); - } else if (OB_FAIL(decode_base64_str(input, input_len, decoded_buf, decoded_buf_len, pos))) { + } else if (OB_FAIL(ObBase64Encoder::decode(input, base64_input_len, decoded_buf, decoded_buf_len, pos))) { COMMON_LOG(WARN, "failed to decode base64_str to urowid", K(ret)); ret = OB_INVALID_ROWID; } else { urowid_data.rowid_content_ = decoded_buf; urowid_data.rowid_len_ = pos; // check validity after decoding - if (urowid_data.is_valid_urowid()) { - // do nothing - } else { + if (!urowid_data.is_valid_urowid()) { + urowid_data.rowid_content_ = NULL; + urowid_data.rowid_len_ = 0; ret = OB_INVALID_ROWID; + } else { + // do nothing } } + if (OB_FAIL(ret) && nullptr != decoded_buf) { + allocator.free(decoded_buf); + } return ret; } +bool ObURowIDData::is_valid_version(int64_t v) +{ + bool bret = true; + + if (INVALID_ROWID_VERSION == v) { + bret = false; + } else if (PK_ROWID_VERSION != v + && NO_PK_ROWID_VERSION != v + && HEAP_TABLE_ROWID_VERSION != v + && EXT_HEAP_TABLE_ROWID_VERSION != v) { + if (!is_valid_part_gen_col_version(v)) { + bret = false; + } + } + + return bret; +} + bool ObURowIDData::is_valid_urowid() const { bool is_valid = true; int ret = OB_SUCCESS; - // dba_len is always 0 for now - if (OB_ISNULL(rowid_content_) || OB_UNLIKELY(rowid_len_ <= 2) || - OB_UNLIKELY(0 != rowid_content_[0]) || - OB_UNLIKELY(!is_valid_version(rowid_content_[1]))) { - is_valid = false; - } else { + const uint8_t version = get_version(); + if (HEAP_TABLE_ROWID_VERSION == version) { + is_valid = rowid_len_ == HEAP_ORGANIZED_TABLE_ROWID_CONTENT_BUF_SIZE; + } else if (EXT_HEAP_TABLE_ROWID_VERSION == version) { + is_valid = rowid_len_ == EXT_HEAP_ORGANIZED_TABLE_ROWID_CONTENT_BUF_SIZE; + } else if (NO_PK_ROWID_VERSION == version || PK_ROWID_VERSION == version) { int64_t pos = get_pk_content_offset(); ObObj obj; - for(; is_valid && pos < rowid_len_;) - { + for (; is_valid && pos < rowid_len_; ) { ObObjType obj_type = get_pk_type(pos); if (OB_UNLIKELY(ob_is_invalid_obj_type(obj_type))) { is_valid = false; + COMMON_LOG(WARN, "invalid obj type", K(obj_type)); } else if (OB_FAIL(get_pk_value(obj_type, pos, obj))) { is_valid = false; } else { // do nothing } } + } else { + is_valid = false; + COMMON_LOG(WARN, "unexpected urowid version", K(version)); } return is_valid; } +uint8_t ObURowIDData::get_version() const +{ + uint8_t version = INVALID_ROWID_VERSION; + if (OB_NOT_NULL(rowid_content_) && 0 < rowid_len_) { + uint8_t raw_version = rowid_content_[0]; + if (HEAP_TABLE_ROWID_VERSION <= raw_version) { + version = raw_version & 0xE0; + if (HEAP_TABLE_ROWID_VERSION == version + && rowid_len_ == HEAP_ORGANIZED_TABLE_ROWID_CONTENT_BUF_SIZE) { + // valid + } else if (EXT_HEAP_TABLE_ROWID_VERSION == version + && rowid_len_ == EXT_HEAP_ORGANIZED_TABLE_ROWID_CONTENT_BUF_SIZE) { + // valid + } else { + version = INVALID_ROWID_VERSION; + } + } else { + int64_t offset = get_version_offset(); + if (offset < rowid_len_) { + raw_version = rowid_content_[offset]; + if (PK_ROWID_VERSION == raw_version || NO_PK_ROWID_VERSION == raw_version) { + version = raw_version; + } else if (is_valid_part_gen_col_version(raw_version)) { + version = PK_ROWID_VERSION; + } + } + } + } + return version; +} + int64_t ObURowIDData::get_obj_size(const ObObj &pk_val) { int64_t ret_size = 1; // for obj type @@ -742,27 +822,235 @@ int ObURowIDData::set_rowid_content(const ObIArray &pk_vals, return ret; } +// used for ob4.x +// format: | 3bit version | 37bit tablet id | 40bit self-increasing column | +int ObURowIDData::parse_heap_organized_table_rowid(uint64_t &tablet_id, uint64_t &auto_inc) const +{ + int ret = OB_SUCCESS; + if (rowid_len_ != HEAP_ORGANIZED_TABLE_ROWID_CONTENT_BUF_SIZE) { + ret = OB_ERR_UNEXPECTED; + COMMON_LOG(WARN, "invalid rowid buf size", K(ret)); + } else { + int pos = 0; + tablet_id = static_cast(rowid_content_[pos++] & 0x1F) << HEAP_TABLE_ROWID_NON_EMBEDED_TABLET_ID_BITS; + for (int i = 1; i <= HEAP_TABLE_ROWID_NON_EMBEDED_TABLET_ID_BITS / 8; i++) { + tablet_id += static_cast(rowid_content_[pos++]) + << (HEAP_TABLE_ROWID_NON_EMBEDED_TABLET_ID_BITS - 8 * i); + } + auto_inc = 0; + for (int i = 4; i >= 0; i--) { + uint64_t x = static_cast(rowid_content_[pos++]); + auto_inc += x << (i * 8); + } + } + return ret; +} + +// used for ob4.x extended +// format: | 3bit version | 61bit tablet id | 64bit self-increasing column | +int ObURowIDData::parse_ext_heap_organized_table_rowid(uint64_t &tablet_id, uint64_t &auto_inc) +{ + int ret = OB_SUCCESS; + if (rowid_len_ != EXT_HEAP_ORGANIZED_TABLE_ROWID_CONTENT_BUF_SIZE) { + ret = OB_ERR_UNEXPECTED; + COMMON_LOG(WARN, "invalid rowid buf size", K(ret)); + } else { + int pos = 0; + tablet_id = static_cast(rowid_content_[pos++] & 0x1F) << EXT_HEAP_TABLE_ROWID_NON_EMBEDED_TABLET_ID_BITS; + for (int64_t i = 1; i <= EXT_HEAP_TABLE_ROWID_NON_EMBEDED_TABLET_ID_BITS / 8; i++) { + tablet_id += static_cast(rowid_content_[pos++]) + << (EXT_HEAP_TABLE_ROWID_NON_EMBEDED_TABLET_ID_BITS - 8 * i); + } + auto_inc = 0; + for (int i = 7; i >= 0; i--) { + uint64_t x = static_cast(rowid_content_[pos++]); + auto_inc += x << (i * 8); + } + } + return ret; +} + int ObURowIDData::get_pk_vals(ObIArray &pk_vals) { int ret = OB_SUCCESS; - int64_t pos = get_pk_content_offset(); - while (OB_SUCC(ret) && pos < get_buf_len()) { - if (OB_LIKELY(pos + 1 <= get_buf_len())) { - ObObjType type = get_pk_type(pos); - ObObj tmp_obj; - if (OB_LIKELY(is_valid_obj_type(type))) { - if (OB_FAIL(get_pk_value(type, pos, tmp_obj))) { - COMMON_LOG(WARN, "failed to get pk value", K(ret)); - } else if (OB_FAIL(pk_vals.push_back(tmp_obj))) { - COMMON_LOG(WARN, "failed to push back element", K(ret)); + int64_t pos = 0; + if (OB_UNLIKELY(!is_valid_urowid())) { + ret = OB_INVALID_ROWID; + COMMON_LOG(WARN, "invalid rowid", K(ret)); + } else if (is_physical_rowid()) { + if (OB_FAIL(get_rowkey_for_heap_organized_table(pk_vals))) { + COMMON_LOG(WARN, "failed to get rowkey for heap organized_table", K(ret)); + } else { + /* do nothing */ + } + } else { + pos = get_pk_content_offset(); + while (OB_SUCC(ret) && pos < get_buf_len()) { + if (OB_LIKELY(pos + 1 <= get_buf_len())) { + ObObjType type = get_pk_type(pos); + ObObj tmp_obj; + if (OB_LIKELY(is_valid_obj_type(type))) { + if (OB_FAIL(get_pk_value(type, pos, tmp_obj))) { + COMMON_LOG(WARN, "failed to get pk value", K(ret)); + } else if (OB_FAIL(pk_vals.push_back(tmp_obj))) { + COMMON_LOG(WARN, "failed to push back element", K(ret)); + } + } else { + ret = OB_INVALID_ROWID; } } else { ret = OB_INVALID_ROWID; } - } else { - ret = OB_INVALID_ROWID; } } + + return ret; +} + +int ObURowIDData::get_rowkey_for_heap_organized_table(ObIArray &rowkey) +{ + int ret = OB_SUCCESS; + uint8_t version = get_version(); + uint64_t tablet_id = 0; + uint64_t auto_inc = 0; + if (HEAP_TABLE_ROWID_VERSION == version) { + if (OB_FAIL(parse_heap_organized_table_rowid(tablet_id, auto_inc))) { + COMMON_LOG(WARN, "failed to parse rowid", K(ret)); + } + } else if (EXT_HEAP_TABLE_ROWID_VERSION == version) { + if (OB_FAIL(parse_ext_heap_organized_table_rowid(tablet_id, auto_inc))) { + COMMON_LOG(WARN, "failed to parse rowid", K(ret)); + } + } else { + ret = OB_INVALID_ROWID; + COMMON_LOG(WARN, "invalid rowid", K(ret)); + } + + if (OB_SUCC(ret)) { + ObObj tmp_obj; + tmp_obj.set_uint64(auto_inc); + if (OB_FAIL(rowkey.push_back(tmp_obj))) { + COMMON_LOG(WARN, "failed to push back element", K(ret)); + } + } + return ret; +} + +int ObURowIDData::get_obobj_or_partition_id_from_decoded(obproxy::proxy::ObProxyPartInfo &part_info, + obproxy::opsql::ObExprResolverResult &resolve_result, + int64_t &partition_id, + common::ObIAllocator &allocator) +{ + int ret = OB_SUCCESS; + + const uint8_t version = get_version(); + switch (version) { + case HEAP_TABLE_ROWID_VERSION: { + // 0x80 ob4.0 + uint64_t tablet_id = 0; + uint64_t auto_inc = 0; + if (OB_FAIL(parse_heap_organized_table_rowid(tablet_id, auto_inc))) { + COMMON_LOG(WARN, "fail to parse heap organized table rowid", K(ret)); + } else { + partition_id = static_cast(tablet_id); + COMMON_LOG(DEBUG, "succ to get tablet id from ob4.0", K(partition_id)); + } + break; + } + case EXT_HEAP_TABLE_ROWID_VERSION: { + // 0xA0 ob4.0 extended + uint64_t tablet_id = 0; + uint64_t auto_inc = 0; + if (OB_FAIL(parse_ext_heap_organized_table_rowid(tablet_id, auto_inc))) { + COMMON_LOG(WARN, "fail to parse ext heap organized table rowid", K(ret)); + } else { + partition_id = static_cast(tablet_id); + COMMON_LOG(DEBUG, "succ to get tablet id from ob4.0 extended", K(partition_id)); + } + break; + } + case NO_PK_ROWID_VERSION: + case PK_ROWID_VERSION: { + // ob2.x 3.x + if (OB_FAIL(get_obobj_from_decoded(part_info, resolve_result, allocator))) { + COMMON_LOG(WARN, "fail to get obobj from decoded", K(ret)); + } + break; + } + default : { + ret = OB_ERR_UNEXPECTED; + COMMON_LOG(WARN, "unexpected version for rowid", K(version)); + } + } + + return ret; +} + +// used for ob2.x 3.x +int ObURowIDData::get_obobj_from_decoded(obproxy::proxy::ObProxyPartInfo &part_info, + obproxy::opsql::ObExprResolverResult &resolve_result, + common::ObIAllocator &allocator) +{ + int ret = OB_SUCCESS; + + ObArray pk_vals; + if (OB_FAIL(get_pk_vals(pk_vals))) { + COMMON_LOG(WARN, "fail to get pk vals", K(ret)); + } else { + ObProxyPartKeyInfo &key_info = part_info.get_part_key_info(); + + for (int64_t i = 0; OB_SUCC(ret) && i < key_info.key_num_; ++i) { + ObProxyPartKey &part_key = key_info.part_keys_[i]; + if (PART_KEY_LEVEL_ONE == part_key.level_ && !resolve_result.ranges_[0].start_key_.is_valid()) { + if (OB_FAIL(resolve_result.ranges_[0].build_row_key(part_info.get_part_columns().count(), allocator))) { + COMMON_LOG(WARN, "fail to build row key", K(ret)); + } + } else if (PART_KEY_LEVEL_TWO == part_key.level_ && !resolve_result.ranges_[1].start_key_.is_valid()) { + if (OB_FAIL(resolve_result.ranges_[1].build_row_key(part_info.get_sub_part_columns().count(), allocator))) { + COMMON_LOG(WARN, "fail to build row key", K(ret)); + } + } + + if (part_key.idx_in_rowid_ >= 0 + && part_key.idx_in_rowid_ < pk_vals.count()) { + ObObj &obj = pk_vals.at(part_key.idx_in_rowid_); + ObObjType type = obj.get_type(); + if (ObCharType == type || ObNCharType == type) { + int32_t val_len = obj.get_val_len(); + const char* obj_str = obj.get_string_ptr(); + while (val_len > 1) { + if (OB_PADDING_CHAR == *(obj_str + val_len - 1)) { + --val_len; + } else { + break; + } + } + obj.set_string(type, obj.get_string_ptr(), val_len); + } + + if (part_key.level_ == 0 || part_key.level_ > 2) { + ret = OB_ERR_UNEXPECTED; + COMMON_LOG(WARN, "part key level unexpected", K(part_key.level_)); + } else { + int level = static_cast(part_key.level_ - 1); + ObObj *target_start = const_cast(resolve_result.ranges_[level].start_key_.get_obj_ptr()) + + part_key.idx_in_part_columns_; + ObObj *target_end = const_cast(resolve_result.ranges_[level].end_key_.get_obj_ptr()) + + part_key.idx_in_part_columns_; + // no need to deep copy + *target_start = obj; + *target_end = obj; + resolve_result.ranges_[level].border_flag_.set_inclusive_start(); + resolve_result.ranges_[level].border_flag_.set_inclusive_end(); + COMMON_LOG(DEBUG, "succ to get val from rowid", K(obj), K(level), K(part_key.idx_in_part_columns_)); + } + } else { + ret = OB_ERR_UNEXPECTED; + COMMON_LOG(WARN, "calc partition id using rowid failed", K(part_key.idx_in_rowid_), K(pk_vals.count())); + } + } // for + } // else + return ret; } @@ -770,8 +1058,29 @@ DEF_TO_STRING(ObURowIDData) { int ret = OB_SUCCESS; int64_t pos = 0; + uint64_t tablet_id = 0; + uint64_t auto_inc = 0; + int64_t version = get_version(); + if (OB_FAIL(parse_heap_organized_table_rowid(tablet_id, auto_inc))) { + version = INVALID_ROWID_VERSION; + } J_OBJ_START(); - if (OB_LIKELY(rowid_len_ >= 2)) { // dba_len is zero for now + if (INVALID_ROWID_VERSION == version) { + // do nothing + } else if (HEAP_TABLE_ROWID_VERSION == version) { + ObObj tmp_obj; + J_KV("VERSION", version); + J_COMMA(); + J_KV("TABLET ID", tablet_id); + J_COMMA(); + J_NAME("Content"); + J_COLON(); + J_ARRAY_START(); + tmp_obj.set_uint64(auto_inc); + BUF_PRINTO(tmp_obj); + J_COMMA(); + J_ARRAY_END(); + } else { J_KV("DBA LEN", rowid_content_[0]); J_COMMA(); J_KV("VERSION", rowid_content_[1]); @@ -781,7 +1090,7 @@ DEF_TO_STRING(ObURowIDData) J_COLON(); J_ARRAY_START(); // skip print dba len - if (OB_LIKELY(rowid_pos < rowid_len_)){ + if (OB_LIKELY(rowid_pos < rowid_len_)) { ObObj pk_val; for(; OB_SUCC(ret) && rowid_pos < rowid_len_;) { ObObjType obj_type = get_pk_type(rowid_pos); @@ -796,8 +1105,8 @@ DEF_TO_STRING(ObURowIDData) } } } - J_ARRAY_END(); } + J_ARRAY_END(); } J_OBJ_END(); return pos; @@ -842,15 +1151,10 @@ OB_DEF_DESERIALIZE(ObURowIDData) rowid_len_ = rowid_buf_len; rowid_content_ = (uint8_t *)buf + pos; pos += rowid_buf_len; - - uint8_t version = get_version(); - if (OB_UNLIKELY(!is_valid_version(version))) { - ret = OB_ERR_UNEXPECTED; - COMMON_LOG(ERROR, "unexpected urowid version", K(ret), K(version)); - } } return ret; } + } // end namespace common } // end namespace oceanbase diff --git a/src/lib/rowid/ob_urowid.h b/src/lib/rowid/ob_urowid.h index 89adf8a2edaea022425b32c2ea5e804699cfe123..6346e74f593118bee639f47ae354489c93ee5e2a 100644 --- a/src/lib/rowid/ob_urowid.h +++ b/src/lib/rowid/ob_urowid.h @@ -20,6 +20,19 @@ namespace oceanbase { +namespace obproxy +{ +namespace proxy +{ +class ObProxyPartInfo; +} // proxy + +namespace opsql +{ +class ObExprResolverResult; +} // opsql +} // obproxy + namespace common { class ObObj; @@ -37,16 +50,42 @@ private: static get_pk_val_func inner_get_funcs_[ObMaxType]; static set_pk_val_func inner_set_funcs_[ObMaxType]; public: - const static int64_t PK_ROWID_VERSION = 1; - const static int64_t NO_PK_ROWID_VERSION = 2; + enum ObURowIDDataVersion { + INVALID_ROWID_VERSION = 0, + PK_ROWID_VERSION = 1, + NO_PK_ROWID_VERSION = 2, + HEAP_TABLE_ROWID_VERSION = 128, // 0x80 + EXT_HEAP_TABLE_ROWID_VERSION = 160, // 0xA0 + }; + const static uint8_t OB40_ROWID_VERSION_OFFSET = 3; + static constexpr int64_t HEAP_ORGANIZED_TABLE_ROWID_CONTENT_BUF_SIZE = 10; + static constexpr int64_t EXT_HEAP_ORGANIZED_TABLE_ROWID_CONTENT_BUF_SIZE = 16; + + static constexpr int64_t HEAP_TABLE_ROWID_NON_EMBEDED_TABLET_ID_BITS = 32; + static constexpr int64_t EXT_HEAP_TABLE_ROWID_NON_EMBEDED_TABLET_ID_BITS = 56; + int64_t rowid_len_; /* - * memory layout + * logical rowid (pk rowid and no pk rowid) * +-----------+---------+---------+--------------+ * | 1 byte | dba len | 1 bytye | pk_len bytes | * +-----------+---------+---------+--------------+ * | dba len | dba | version | pk_content | * +-----------+---------+---------+--------------+ + * + * heap-organized table rowid + * +--------------+-----------+----------------+ + * | 3 bit | 37 bit | 40 bit | + * +--------------+-----------+----------------+ + * | version >> 5 | tablet_id | auto_increment | + * +--------------+-----------+----------------+ + * + * extended heap-organized table rowid + * +--------------+-----------+----------------+ + * | 3 bit | 61 bit | 64 bit | + * +--------------+-----------+----------------+ + * | version >> 5 | tablet_id | auto_increment | + * +--------------+-----------+----------------+ */ const uint8_t *rowid_content_; @@ -74,12 +113,6 @@ public: return get_guess_dba_len() + 1; } - inline uint8_t get_version() const - { - OB_ASSERT(rowid_len_ >= get_version_offset() + 1); - return rowid_content_[get_version_offset()]; - } - inline int64_t get_pk_content_offset() const { return get_version_offset() + 1; @@ -98,10 +131,18 @@ public: bool operator <=(const ObURowIDData &other) const; bool operator >=(const ObURowIDData &other) const; + inline bool is_physical_rowid() const + { + uint8_t version = get_version(); + return HEAP_TABLE_ROWID_VERSION == version || EXT_HEAP_TABLE_ROWID_VERSION == version; + } + int64_t needed_base64_buffer_size() const; int get_base64_str(char *buf, const int64_t buf_len, int64_t &pos) const; static int decode2urowid(const char *input, const int64_t input_len, ObIAllocator &alloc, ObURowIDData &urowid_data); + + static bool is_valid_version(int64_t v); bool is_valid_urowid() const; int set_rowid_content(const ObIArray &pk_vals, @@ -110,16 +151,11 @@ public: const int64_t dba_len = 0, const uint8_t* guess_dba = NULL); int get_pk_vals(ObIArray &pk_vals); - - static bool is_valid_version(int64_t v) - { - bool bret = true; - if (PK_ROWID_VERSION != v && NO_PK_ROWID_VERSION != v - && !is_valid_part_gen_col_version(v)) { - bret = false; - } - return bret; - } + int get_rowkey_for_heap_organized_table(ObIArray &rowkey); + int get_obobj_or_partition_id_from_decoded(obproxy::proxy::ObProxyPartInfo &part_info, + obproxy::opsql::ObExprResolverResult &resolve_result, + int64_t &partition_id, + common::ObIAllocator &allocator); // if highest bit is 1, lower 7 bits of version filed indicates how many primar key obj static bool is_valid_part_gen_col_version(int64_t v) @@ -146,11 +182,7 @@ public: return ret; } - int64_t get_part_gen_col_cnt() - { - uint8_t ver = get_version(); - return (ver & 0x80) ? (ver & 0x7F) : 0; - } + uint8_t get_version() const; DECLARE_TO_STRING; private: @@ -195,6 +227,14 @@ private: rowid_len_ = 0; rowid_content_ = NULL; } + + int parse_heap_organized_table_rowid(uint64_t &tablet_id, uint64_t &auto_inc) const; + int parse_ext_heap_organized_table_rowid(uint64_t &tablet_id, uint64_t &auto_inc); + + int get_obobj_from_decoded(obproxy::proxy::ObProxyPartInfo &part_info, + obproxy::opsql::ObExprResolverResult &resolve_result, + common::ObIAllocator &allocator); + }; } // end namespace common } // end namespace oceanbase diff --git a/src/lib/timezone/ob_time_convert.cpp b/src/lib/timezone/ob_time_convert.cpp index 8e92be2ade64977437170a1903c4dead730318d0..94cd069f26160d76678a49db27936e80a6bfd0fb 100644 --- a/src/lib/timezone/ob_time_convert.cpp +++ b/src/lib/timezone/ob_time_convert.cpp @@ -409,6 +409,32 @@ int ObTimeConverter::str_to_datetime(const ObString &str, const ObTimeZoneInfo * return ret; } +/** + * @brief cast str to oracle date with format + * + * @param str input string of date + * @param cvrt_ctx + * @param value out param, oracle DATE result + * @return int + */ +int ObTimeConverter::str_to_date_oracle(const ObString &str, + const ObTimeConvertCtx &cvrt_ctx, + ObDateTime &value) +{ + int ret = OB_SUCCESS; + ObTime ob_time; + ObDateTime result_value = 0; + ObScale scale = 0; + if (OB_FAIL(str_to_ob_time_oracle_dfm(str, cvrt_ctx, ObDateTimeType, ob_time, scale))) { + LOG_WARN("failed to convert str to ob_time", K(str), K(cvrt_ctx.oracle_nls_format_)); + } else if (OB_FAIL(ob_time_to_datetime(ob_time, cvrt_ctx.tz_info_, result_value))) { + LOG_WARN("convert ob_time to datetime failed", K(ret), K(ob_time)); + } else { + value = result_value; + } + return ret; +} + int ObTimeConverter::str_to_datetime_format(const ObString &str, const ObString &fmt, const ObTimeZoneInfo *tz_info, int64_t &value, int16_t *scale) { @@ -3111,7 +3137,7 @@ int ObTimeConverter::ob_time_to_str(const ObTime &ob_time, ObDTMode mode, int16_ int ObTimeConverter::data_fmt_nd(char *buffer, int64_t buf_len, int64_t &pos, const int64_t n, int64_t target) { int ret = OB_SUCCESS; - if (OB_UNLIKELY(n <= 0 || target < 0 || target > 999999)) { + if (OB_UNLIKELY(n <= 0 || target < 0 || target > 999999999)) { ret = OB_ERR_UNEXPECTED; LIB_TIME_LOG(ERROR, "invalid argument", K(ret), K(n), K(target)); } else if (OB_UNLIKELY(n > buf_len - pos)) { @@ -3698,6 +3724,8 @@ int ObTimeConverter::ob_time_to_str_oracle_dfm(const ObTime &ob_time, break; } case ObDFMFlag::FF: { + // FF default FF9 in oracle + int64_t scale = ObDFMFlag::FF9 - ObDFMFlag::FF1 + 1; if (OB_UNLIKELY(!HAS_TYPE_ORACLE(ob_time.mode_))) { ret = OB_INVALID_DATE_FORMAT; } else if (0 == scale) { diff --git a/src/lib/timezone/ob_time_convert.h b/src/lib/timezone/ob_time_convert.h index e5e3a5b78f13ff01201fc7d10b1b34d940397ff5..863a26eea19998cccafe55ea595a8487829d210d 100644 --- a/src/lib/timezone/ob_time_convert.h +++ b/src/lib/timezone/ob_time_convert.h @@ -251,6 +251,7 @@ public: static int int_to_time(int64_t int64, int64_t &value); static int int_to_year(int64_t int64, uint8_t &value); static int str_to_datetime(const ObString &str, const ObTimeZoneInfo *tz_info, int64_t &value, int16_t *scale = NULL); + static int str_to_date_oracle(const ObString &str, const ObTimeConvertCtx &cvrt_ctx, ObDateTime &value); static int str_to_datetime_format(const ObString &str, const ObString &fmt, const ObTimeZoneInfo *tz_info, int64_t &value, int16_t *scale = NULL); static int str_is_date_format(const ObString &str, bool &date_flag); @@ -345,7 +346,7 @@ public: ObDTMode mode, int32_t &delta); static int ob_time_to_str_oracle_dfm(const ObTime &ob_time, ObScale scale, const ObString &format, char *buf, int64_t buf_len, int64_t &pos); - static int ob_time_to_datetime(ObTime &ob_time, const ObTimeZoneInfo *sp, int64_t &value); + static int ob_time_to_datetime(ObTime &ob_time, const ObTimeZoneInfo *tz_info, int64_t &value); static int32_t ob_time_to_date(ObTime &ob_time); static int ob_time_to_otimestamp(ObTime &ob_time, ObOTimestampData &value); static int64_t ob_time_to_time(const ObTime &ob_time); diff --git a/src/lib/trace/ob_trace.cpp b/src/lib/trace/ob_trace.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8c7a3cd1848d7418ba833e9c760285f400799058 --- /dev/null +++ b/src/lib/trace/ob_trace.cpp @@ -0,0 +1,569 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#include "ob_trace.h" + +#include +#include +#include + +#include "lib/trace/ob_trace_def.h" +#include "lib/oblog/ob_log_module.h" +#include "lib/time/ob_time_utility.h" + +using namespace oceanbase::trace; +using namespace oceanbase::common; + +namespace oceanbase +{ + +namespace sql +{ +ObFLTSpanMgr* __attribute__((weak)) get_flt_span_manager() +{ + return NULL; +} +int __attribute__((weak)) handle_span_record(char* buf, const int64_t buf_len, ObFLTSpanMgr* flt_span_manager) +{ + UNUSED(buf); + UNUSED(buf_len); + UNUSED(flt_span_manager); + return 0; +} +} + +namespace trace +{ +#define UUID_PATTERN "%8.8lx-%4.4lx-%4.4lx-%4.4lx-%12.12lx" +#define TRACE_PATTERN "{\"trace_id\":\""UUID_PATTERN"\",\"name\":\"%s\",\"id\":\""UUID_PATTERN"\",\"start_ts\":%ld,\"end_ts\":%ld,\"parent_id\":\""UUID_PATTERN"\",\"is_follow\":%s" +#define UUID_TOSTRING(uuid) \ +((uuid).high_ >> 32), ((uuid).high_ >> 16 & 0xffff), ((uuid).high_ & 0xffff), \ +((uuid).low_ >> 48), ((uuid).low_ & 0xffffffffffff) + + +static const char* __span_type_mapper[] = { +#define FLT_DEF_SPAN(name, comment) #name, +#define __HIGH_LEVEL_SPAN +#define __MIDDLE_LEVEL_SPAN +#define __LOW_LEVEL_SPAN +#include "lib/trace/ob_trace_def.h" +#undef __LOW_LEVEL_SPAN +#undef __MIDDLE_LEVEL_SPAN +#undef __HIGH_LEVEL_SPAN +#undef FLT_DEF_SPAN +}; +thread_local ObTrace* ObTrace::save_buffer = NULL; + +void flush_trace() +{ + auto& trace = *OBTRACE; + auto& current_span = trace.current_span_; + if (trace.is_inited() && !current_span.is_empty()) { + auto* span = current_span.get_first(); + if (!trace.is_auto_flush()) { + _LIB_LOG(INFO, "FLT flush trace, trace_id="UUID_PATTERN", root_span_id="UUID_PATTERN", buffer_size=%ld, offset=%ld, current_span size=%d, freed_span size=%d, policy=0x%x", + UUID_TOSTRING(trace.get_trace_id()), + UUID_TOSTRING(trace.get_root_span_id()), + trace.buffer_size_, + trace.offset_, + trace.current_span_.get_size(), + trace.freed_span_.get_size(), + trace.get_policy()); + } + //SET_OB_LOG_TRACE_MODE(); + //PRINT_OB_LOG_TRACE_BUF(COMMON, INFO); + while (current_span.get_header() != span) { + auto* next = span->get_next(); + if (NULL != span->tags_ || 0 != span->end_ts_) { + int64_t pos = 0; + thread_local char buf[MAX_TRACE_LOG_SIZE]; + int ret = common::OB_SUCCESS; + auto* tag = span->tags_; + bool first = true; + INIT_SPAN(span); + while (OB_SUCC(ret) && OB_NOT_NULL(tag)) { + if (pos + 10 >= MAX_TRACE_LOG_SIZE) { + ret = common::OB_BUF_NOT_ENOUGH; + } else { + buf[pos++] = ','; + if (first) { + strcpy(buf + pos, "\"tags\":["); + pos += 8; + first = false; + } + ret = tag->tostring(buf, MAX_TRACE_LOG_SIZE, pos); + tag = tag->next_; + } + } + if (0 != pos) { + if (pos + 1 < MAX_TRACE_LOG_SIZE) { + buf[pos++] = ']'; + buf[pos++] = 0; + } else { + buf[MAX_TRACE_LOG_SIZE - 2] = ']'; + buf[MAX_TRACE_LOG_SIZE - 1] = 0; + } + } + INIT_SPAN(span->source_span_); + _OBPROXY_TRACE_LOG(INFO, + TRACE_PATTERN "%s}", + UUID_TOSTRING(trace.get_trace_id()), + __span_type_mapper[span->span_type_], + UUID_TOSTRING(span->span_id_), + span->start_ts_, + span->end_ts_, + UUID_TOSTRING(OB_ISNULL(span->source_span_) ? + OBTRACE->get_root_span_id() : span->source_span_->span_id_), + span->is_follow_ ? "true" : "false", + buf); + buf[0] = '\0'; + IGNORE_RETURN sql::handle_span_record(buf, MAX_TRACE_LOG_SIZE, sql::get_flt_span_manager()); + if (0 != span->end_ts_) { + current_span.remove(span); + trace.freed_span_.add_first(span); + } + span->tags_ = NULL; + } + span = next; + } + //PRINT_OB_LOG_TRACE_BUF(OBTRACE, INFO); + //CANCLE_OB_LOG_TRACE_MODE(); + trace.offset_ = trace.buffer_size_ / 2; + } +} + +double get_random_percentage() +{ + uint64_t random_u64 = UUID::gen_rand(); + return static_cast(random_u64) / static_cast(UINT64_MAX); +} + +uint64_t UUID::gen_rand() +{ + static thread_local std::random_device dev; + static thread_local std::mt19937 rng(dev()); + static thread_local std::uniform_int_distribution dist; + return dist(rng); +} + +UUID UUID::gen() +{ + UUID ret; + ret.high_ = ObTimeUtility::current_time(); + ret.low_ = gen_rand(); + return ret; +} + +UUID::UUID(const char* uuid) +{ + high_ = low_ = 0; + for (auto i = 0; i < 18; ++i) { + if (8 == i || 13 == i) { + continue; + } else if (uuid[i] >= '0' && uuid[i] <= '9') { + high_ = (high_ << 4) + (uuid[i] - '0'); + } else if (uuid[i] >= 'a' && uuid[i] <= 'f') { + high_ = (high_ << 4) + (uuid[i] - 'a') + 10; + } else if (uuid[i] >= 'A' && uuid[i] <= 'F') { + high_ = (high_ << 4) + (uuid[i] - 'A') + 10; + } else { + return; + } + } + for (auto i = 19; i < 36; ++i) { + if (23 == i) { + continue; + } else if (uuid[i] >= '0' && uuid[i] <= '9') { + low_ = (low_ << 4) + (uuid[i] - '0'); + } else if (uuid[i] >= 'a' && uuid[i] <= 'f') { + low_ = (low_ << 4) + (uuid[i] - 'a') + 10; + } else if (uuid[i] >= 'A' && uuid[i] <= 'F') { + low_ = (low_ << 4) + (uuid[i] - 'A') + 10; + } else { + return; + } + } +} + +int UUID::tostring(char* buf, const int64_t buf_len, int64_t& pos) const +{ + int ret = common::OB_SUCCESS; + const char* transfer = "0123456789abcdef"; + if (pos + 37 > buf_len) { + ret = common::OB_BUF_NOT_ENOUGH; + } else { + buf[pos++] = transfer[high_ >> 60 & 0xf]; + buf[pos++] = transfer[high_ >> 56 & 0xf]; + buf[pos++] = transfer[high_ >> 52 & 0xf]; + buf[pos++] = transfer[high_ >> 48 & 0xf]; + buf[pos++] = transfer[high_ >> 44 & 0xf]; + buf[pos++] = transfer[high_ >> 40 & 0xf]; + buf[pos++] = transfer[high_ >> 36 & 0xf]; + buf[pos++] = transfer[high_ >> 32 & 0xf]; + buf[pos++] = '-'; + buf[pos++] = transfer[high_ >> 28 & 0xf]; + buf[pos++] = transfer[high_ >> 24 & 0xf]; + buf[pos++] = transfer[high_ >> 20 & 0xf]; + buf[pos++] = transfer[high_ >> 16 & 0xf]; + buf[pos++] = '-'; + buf[pos++] = transfer[high_ >> 12 & 0xf]; + buf[pos++] = transfer[high_ >> 8 & 0xf]; + buf[pos++] = transfer[high_ >> 4 & 0xf]; + buf[pos++] = transfer[high_ >> 0 & 0xf]; + buf[pos++] = '-'; + buf[pos++] = transfer[ low_ >> 60 & 0xf]; + buf[pos++] = transfer[ low_ >> 56 & 0xf]; + buf[pos++] = transfer[ low_ >> 52 & 0xf]; + buf[pos++] = transfer[ low_ >> 48 & 0xf]; + buf[pos++] = '-'; + buf[pos++] = transfer[ low_ >> 44 & 0xf]; + buf[pos++] = transfer[ low_ >> 40 & 0xf]; + buf[pos++] = transfer[ low_ >> 36 & 0xf]; + buf[pos++] = transfer[ low_ >> 32 & 0xf]; + buf[pos++] = transfer[ low_ >> 28 & 0xf]; + buf[pos++] = transfer[ low_ >> 24 & 0xf]; + buf[pos++] = transfer[ low_ >> 20 & 0xf]; + buf[pos++] = transfer[ low_ >> 16 & 0xf]; + buf[pos++] = transfer[ low_ >> 12 & 0xf]; + buf[pos++] = transfer[ low_ >> 8 & 0xf]; + buf[pos++] = transfer[ low_ >> 4 & 0xf]; + buf[pos++] = transfer[ low_ >> 0 & 0xf]; + buf[pos ] = '\0'; + } + return ret; +} + +int UUID::serialize(char* buf, const int64_t buf_len, int64_t& pos) const +{ + int ret = common::OB_SUCCESS; + if (OB_FAIL(common::serialization::encode_i64(buf, buf_len, pos, high_))) { + // LOG_WARN("deserialize failed", K(ret), K(buf), K(buf_len), K(pos)); + } else if (OB_FAIL(common::serialization::encode_i64(buf, buf_len, pos, low_))) { + // LOG_WARN("deserialize failed", K(ret), K(buf), K(buf_len), K(pos)); + } + return ret; +} + +int UUID::deserialize(const char* buf, const int64_t buf_len, int64_t& pos) +{ + int ret = common::OB_SUCCESS; + if (OB_FAIL(common::serialization::decode_i64(buf, buf_len, pos, reinterpret_cast(&high_)))) { + // LOG_WARN("deserialize failed", K(ret), K(buf), K(buf_len), K(pos)); + } else if (OB_FAIL(common::serialization::decode_i64(buf, buf_len, pos, reinterpret_cast(&low_)))) { + // LOG_WARN("deserialize failed", K(ret), K(buf), K(buf_len), K(pos)); + } + return ret; +} + +int to_string_and_strip(const char* str, const int64_t length, char* buf, const int64_t buf_len, int64_t& pos) +{ + int ret = common::OB_SUCCESS; + char from[] = "\"\n\r\\\t"; + const char* to[] = { "\\\"", "\\n", "\\r", "\\\\", " "}; + buf[pos++] = '\"'; + for (auto j = 0; j < length && str[j]; ++j) { + bool conv = false; + for (auto i = 0; i < sizeof(from) - 1; ++i) { + if (from[i] == str[j]) { + for (const char* toc = to[i]; *toc; ++toc) { + if (pos < buf_len) { + buf[pos++] = *toc; + } else { + ret = common::OB_BUF_NOT_ENOUGH; + } + } + conv = true; + break; + } + } + if (!conv) { + if (pos < buf_len) { + buf[pos++] = str[j]; + } else { + ret = common::OB_BUF_NOT_ENOUGH; + } + } + } + if (OB_FAIL(ret) || pos + 2 >= buf_len) { + buf[buf_len - 1] = 0; + } else { + buf[pos++] = '\"'; + buf[pos++] = '}'; + buf[pos] = 0; + } + return ret; +} + +template<> +int ObTagCtx::tostring(char* buf, const int64_t buf_len, int64_t& pos) +{ + int ret = common::OB_SUCCESS; + if (OB_FAIL(ObTagCtxBase::tostring(buf, buf_len, pos))) { + // do nothing + } else { + ret = to_string_and_strip(data_.ptr(), data_.length(), buf, buf_len, pos); + } + return ret; +} + +template<> +int ObTagCtx::tostring(char* buf, const int64_t buf_len, int64_t& pos) +{ + int ret = common::OB_SUCCESS; + if (OB_FAIL(ObTagCtxBase::tostring(buf, buf_len, pos))) { + // do nothing + } else { + ret = to_string_and_strip(data_, INT64_MAX, buf, buf_len, pos); + } + return ret; +} + +template<> +int ObTagCtx::tostring(char* buf, const int64_t buf_len, int64_t& pos) +{ + int ret = common::OB_SUCCESS; + if (OB_FAIL(ObTagCtxBase::tostring(buf, buf_len, pos))) { + // do nothing + } else { + ret = to_string_and_strip((char*)&data_, INT64_MAX, buf, buf_len, pos); + } + return ret; +} + +ObSpanCtx::ObSpanCtx() + : span_id_(), + source_span_(NULL), + start_ts_(0), + end_ts_(0), + tags_(NULL), + span_type_(0), + is_follow_(false) +{ +} + +// use local buffer for obproxy, not tsi buffer as observer +ObTrace* ObTrace::get_instance() +{ + thread_local char default_buffer[MIN_BUFFER_SIZE]; + struct Guard { + Guard(char* buffer, int64_t size) { + IGNORE_RETURN new(buffer) ObTrace(size); + } + }; + thread_local Guard guard(default_buffer, MIN_BUFFER_SIZE); + if (OB_ISNULL(save_buffer)) { + save_buffer = (ObTrace*)default_buffer; + } + return save_buffer; +} + +// special set api for obproxy, inorder to manage the thread local buffer by obproxy itself. +void ObTrace::set_trace_buffer(void* buffer, int64_t buffer_size) +{ + if (OB_ISNULL(buffer) || buffer_size < MIN_BUFFER_SIZE) { + save_buffer = NULL; + } else { + if (!((ObTrace*)buffer)->check_magic()) { + IGNORE_RETURN new(buffer) ObTrace(buffer_size); + _LIB_LOG(DEBUG, "set trace buffer, set buffer size:%ld", buffer_size); + } + save_buffer = (ObTrace*)buffer; + } +} + +ObTrace::ObTrace(int64_t buffer_size) + : magic_code_(MAGIC_CODE), + buffer_size_(buffer_size - sizeof(ObTrace)), + offset_(buffer_size_ / 2), + current_span_(), + freed_span_(), + last_active_span_(NULL), + trace_id_(), + root_span_id_(), + policy_(0), + seq_(0) +{ + for (auto i = 0; i < (offset_ / sizeof(ObSpanCtx)); ++i) { + IGNORE_RETURN freed_span_.add_last(new(data_ + i * sizeof(ObSpanCtx)) ObSpanCtx); + } +} + +void ObTrace::init(UUID trace_id, UUID root_span_id, uint8_t policy) +{ + #ifndef NDEBUG + if (check_magic()) { + check_leak_span(); + } + #endif + reset(); + trace_id_ = trace_id; + root_span_id_ = root_span_id; + policy_ = policy; +} + +UUID ObTrace::begin() +{ + trace_id_ = UUID::gen(); + return trace_id_; +} + +void ObTrace::end() +{ + #ifndef NDEBUG + check_leak_span(); + #endif + reset(); +} + +ObSpanCtx* ObTrace::begin_span(uint32_t span_type, uint8_t level, bool is_follow) +{ + ObSpanCtx* new_span = NULL; + if (!trace_id_.is_inited() || level > level_) { + // do nothing + } else { + if (freed_span_.is_empty()) { + FLUSH_TRACE(); + } + if (freed_span_.is_empty()) { + check_leak_span(); + } else { + new_span = freed_span_.remove_last(); + current_span_.add_first(new_span); + new_span->span_type_ = static_cast(span_type); + new_span->span_id_.high_ = 0; + new_span->span_id_.low_ = ++seq_; + new_span->source_span_ = last_active_span_; + new_span->is_follow_ = is_follow; + new_span->start_ts_ = ObTimeUtility::current_time(); + new_span->end_ts_ = 0; + new_span->tags_ = NULL; + last_active_span_ = new_span; + } + } + return new_span; +} + +void ObTrace::end_span(ObSpanCtx* span) +{ + if (!trace_id_.is_inited() || OB_ISNULL(span) || !span->span_id_.is_inited()) { + // do nothing + } else { + span->end_ts_ = ObTimeUtility::current_time(); + last_active_span_ = span->source_span_; + } +} + +// clear all tags and span which is ended before +void ObTrace::reset_span() +{ + #ifndef NDEBUG + if (!check_magic()) { + LIB_LOG(ERROR, "trace buffer was not inited"); + } + #endif + // remove all end span + if (is_inited() && !current_span_.is_empty()) { + auto* span = current_span_.get_first(); + while (current_span_.get_header() != span) { + auto* next = span->get_next(); + if (0 != span->end_ts_) { + current_span_.remove(span); + freed_span_.add_first(span); + } + span->tags_ = nullptr; + span = next; + } + } + offset_ = buffer_size_ / 2; +} + +int ObTrace::serialize(char* buf, const int64_t buf_len, int64_t& pos) const +{ + int ret = common::OB_SUCCESS; + auto* span = const_cast(this)->last_active_span_; + INIT_SPAN(span); + auto& span_id = span == NULL ? root_span_id_ : span->span_id_; + if (OB_FAIL(trace_id_.serialize(buf, buf_len, pos))) { + // LOG_WARN("serialize failed", K(ret), K(buf), K(buf_len), K(pos)); + } else if (OB_FAIL(span_id.serialize(buf, buf_len, pos))) { + // LOG_WARN("serialize failed", K(ret), K(buf), K(buf_len), K(pos)); + } else if (OB_FAIL(common::serialization::encode_i8(buf, buf_len, pos, policy_))) { + // LOG_WARN("serialize failed", K(ret), K(buf), K(buf_len), K(pos)); + } else { + // do nothing + } + return ret; +} + +int ObTrace::deserialize(const char* buf, const int64_t buf_len, int64_t& pos) +{ + int ret = common::OB_SUCCESS; + if (OB_FAIL(trace_id_.deserialize(buf, buf_len, pos))) { + // LOG_WARN("deserialize failed", K(ret), K(buf), K(buf_len), K(pos)); + } else if (OB_FAIL(root_span_id_.deserialize(buf, buf_len, pos))) { + // LOG_WARN("deserialize failed", K(ret), K(buf), K(buf_len), K(pos)); + } else if (OB_FAIL(common::serialization::decode_i8(buf, buf_len, pos, reinterpret_cast(&policy_)))) { + // LOG_WARN("deserialize failed", K(ret), K(buf), K(buf_len), K(pos)); + } else { + // do nothing + } + return ret; +} + +void ObTrace::check_leak_span() +{ + ObSpanCtx* span = current_span_.get_first(); + while (current_span_.get_header() != span) { + if (0 == span->end_ts_) { + LIB_LOG(ERROR, "there were leak span"); + dump_span(); + break; + } + span = span->get_next(); + } +} + +void ObTrace::reset() +{ + #ifndef NDEBUG + if (!check_magic()) { + LIB_LOG(ERROR, "trace buffer was not inited"); + } + #endif + offset_ = buffer_size_ / 2; + freed_span_.push_range(current_span_); + last_active_span_ = NULL; + trace_id_ = UUID(); + root_span_id_ = UUID(); + policy_ = 0; + seq_ = 0; +} + +void ObTrace::dump_span() +{ + constexpr int64_t buf_len = 1 << 10; + char buf[buf_len]; + int64_t pos = 0; + int ret = common::OB_SUCCESS; + auto* span = current_span_.get_first(); + IGNORE_RETURN databuff_printf(buf, buf_len, pos, "active_span: "); + while (OB_SUCC(ret) && current_span_.get_header() != span) { + if (0 == span->end_ts_) { + ret = databuff_printf(buf, buf_len, pos, "%s, ", __span_type_mapper[span->span_type_]); + } + span = span->get_next(); + } + _LIB_LOG(ERROR, "%s", buf); +} + +} +} diff --git a/src/lib/trace/ob_trace.h b/src/lib/trace/ob_trace.h new file mode 100644 index 0000000000000000000000000000000000000000..26f05fd828f972721b53899bdd37be390e9ca924 --- /dev/null +++ b/src/lib/trace/ob_trace.h @@ -0,0 +1,363 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ +#ifndef _OB_TRACE_H +#define _OB_TRACE_H + +#include "ob_trace_def.h" +#include "lib/list/ob_dlist.h" +#include "lib/utility/utility.h" + +#include "lib/ob_errno.h" // ? +#include "lib/ob_define.h" // ? + +#define MAX_TRACE_LOG_SIZE (1L << 13) // 8K + +#define SET_TRACE_BUFFER(buffer, size) OBTRACE->set_trace_buffer(buffer, size) +#define FLT_BEGIN_TRACE() (OBTRACE->begin()) +#define FLT_END_TRACE() (OBTRACE->end()) +#define FLT_BEGIN_SPAN(span_type) FLT_BEGIN_CHILD_SPAN(span_type) +#define FLT_BEGIN_CHILD_SPAN(span_type) (OBTRACE->begin_span(::oceanbase::trace::ObSpanType::span_type, GET_SPANLEVEL(::oceanbase::trace::ObSpanType::span_type), false)) +#define FLT_BEGIN_FOLLOW_SPAN(span_type) (OBTRACE->begin_span(::oceanbase::trace::ObSpanType::span_type, GET_SPANLEVEL(::oceanbase::trace::ObSpanType::span_type), true)) +#define FLT_END_SPAN(span) \ +if (OB_NOT_NULL(span)) { \ + OBTRACE->end_span(span); \ + if (span->span_id_.is_inited() && OBTRACE->is_auto_flush()) { \ + FLUSH_TRACE(); \ + } \ +} +#define FLT_RESET_SPAN() (OBTRACE->reset_span()) +#define FLT_END_CURRENT_SPAN() FLT_END_SPAN(OBTRACE->last_active_span_) +#define FLT_SET_TAG(...) (OBTRACE->set_tag(__VA_ARGS__)) +#define FLT_SET_LOG() +#define FLT_SET_TRACE_LEVEL(level) (OBTRACE->set_level(level)) +#define FLT_SET_AUTO_FLUSH(value) (OBTRACE->set_auto_flush(value)) + +#define INIT_SPAN(span) \ +if (OB_NOT_NULL(span) && 0 == span->span_id_.high_) { \ + span->span_id_.low_ = trace::UUID::gen_rand(); \ + span->span_id_.high_ = span->start_ts_; \ +} + +namespace oceanbase +{ +namespace sql +{ +class ObFLTSpanMgr; +extern ObFLTSpanMgr* get_flt_span_manager(); +extern int handle_span_record(char* buf, const int64_t buf_len, ObFLTSpanMgr* flt_span_manager); +} +} +#define FLUSH_TRACE() ::oceanbase::trace::flush_trace(); + +#define FLTSpanGuard(span_type) ::oceanbase::trace::__ObFLTSpanGuard __##span_type##__LINE__(::oceanbase::trace::ObSpanType::span_type, GET_SPANLEVEL(::oceanbase::trace::ObSpanType::span_type)) + +#define OBTRACE ::oceanbase::trace::ObTrace::get_instance() + +namespace oceanbase +{ +namespace trace +{ +extern void flush_trace(); +extern double get_random_percentage(); + +struct UUID +{ + static UUID gen(); + static uint64_t gen_rand(); + UUID() : low_(0), high_(0) {} + explicit UUID(const char* uuid); + bool equal(const UUID& that) const { return 0 == memcmp(this, &that, sizeof(UUID)); } + void reset() { low_ = 0; high_ = 0; } + OB_INLINE bool is_inited() const { return low_ != 0 || high_ != 0; } + int tostring(char* buf, const int64_t buf_len, int64_t& pos) const; + int serialize(char* buf, const int64_t buf_len, int64_t& pos) const; + int deserialize(const char* buf, const int64_t buf_len, int64_t& pos); + int64_t get_serialize_size() const { return 16; } + int64_t to_string(char* buf, const int64_t buf_len) const + { + int64_t pos = 0; + int ret = tostring(buf, buf_len, pos); + if (OB_FAIL(ret)) { + pos = 0; + } + return pos; + } + union { + struct { + uint64_t low_; + uint64_t high_; + }; + struct { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint8_t clock_seq_hi_and_reserved; + uint8_t clock_seq_low; + uint8_t node[6]; + }; + }; +}; + +struct FltTransCtx { +public: + FltTransCtx() + : trace_id_(), span_id_(), policy_(0) + {} + TO_STRING_KV(K_(trace_id), K_(span_id), K_(level), K_(auto_flush)); + +public: + UUID trace_id_; + UUID span_id_; + union { + uint8_t policy_; + struct { + uint8_t level_ : 7; + bool auto_flush_ : 1; + }; + }; +}; + +struct ObTagCtxBase +{ + ObTagCtxBase() {} + virtual ~ObTagCtxBase() {} + virtual int tostring(char* buf, const int64_t buf_len, int64_t& pos) + { + int ret = common::OB_SUCCESS; + const auto l = strlen(__tag_name_mapper[tag_type_]); + if (pos + l + 7 >= buf_len) { + buf[std::min(pos - 1, buf_len - 1)] = '\0'; + ret = common::OB_BUF_NOT_ENOUGH; + } else { + buf[pos++] = '{'; + buf[pos++] = '\"'; + IGNORE_RETURN strcpy(buf + pos, __tag_name_mapper[tag_type_]); + pos += l; + buf[pos++] = '\"'; + buf[pos++] = ':'; + buf[pos] = '\0'; + } + return ret; + } + ObTagCtxBase* next_; + uint16_t tag_type_; +}; + +// if T has member to_string, add quote for it. +template +int tag_to_string(char* buf, const int64_t buf_len, int64_t& pos, const T& value, common::TrueType) +{ + int ret = common::OB_SUCCESS; + if (pos + value.length() + 4 >= buf_len) { + ret = common::OB_BUF_NOT_ENOUGH; + } else { + buf[pos++] = '\"'; + ret = common::logdata_print_obj(buf, buf_len, pos, value); + buf[pos++] = '\"'; + buf[pos++] = '}'; + buf[pos] = '\0'; + } + return ret; +} + +// else use default to_string +template +int tag_to_string(char* buf, const int64_t buf_len, int64_t& pos, const T& value, common::FalseType) +{ + int ret = common::OB_SUCCESS; + if (OB_FAIL(common::logdata_print_obj(buf, buf_len, pos, value))) { + // do nothing + } else if (pos + 1 >= buf_len) { + ret = common::OB_BUF_NOT_ENOUGH; + } else { + buf[pos++] = '}'; + buf[pos] = '\0'; + } + return ret; +} + +template +struct ObTagCtx final : public ObTagCtxBase +{ + ObTagCtx() {} + virtual ~ObTagCtx() override {} + virtual int tostring(char* buf, const int64_t buf_len, int64_t& pos) override + { + int ret = common::OB_SUCCESS; + if (OB_FAIL(ObTagCtxBase::tostring(buf, buf_len, pos))) { + // do nothing + } else { + ret = tag_to_string(buf, buf_len, pos, data_, common::BoolType()); + } + return ret; + } + T data_; +}; + +struct ObSpanCtx final : public common::ObDLinkBase +{ + ObSpanCtx(); + + UUID span_id_; + ObSpanCtx* source_span_; + int64_t start_ts_; + int64_t end_ts_; + ObTagCtxBase* tags_; + uint16_t span_type_; + bool is_follow_; +}; + +struct ObTrace +{ + static constexpr uint64_t MAGIC_CODE = 0x1234567887654321ul; + static constexpr int64_t DEFAULT_BUFFER_SIZE = (1L << 16); // do not used now + static constexpr int64_t MIN_BUFFER_SIZE = (1L << 13); + static ObTrace* get_instance(); + static void set_trace_buffer(void* buffer, int64_t buffer_size); + ObTrace(int64_t buffer_size); + void init(FltTransCtx &flt_ctx) + { + root_span_id_ = flt_ctx.span_id_; + trace_id_ = flt_ctx.trace_id_; + policy_ = flt_ctx.policy_; + } + void init(UUID trace_id, UUID root_span_id, uint8_t policy = 0); + bool is_inited() { return check_magic() && trace_id_.is_inited(); } + UUID begin(); + void end(); + ObSpanCtx* begin_span(uint32_t span_type, uint8_t level, bool is_follow); + void end_span(ObSpanCtx* span_id); + void reset_span(); + template + void set_tag(ObTagType tag_type, const T& value, Targs... Fargs) + { + if (trace_id_.is_inited() + && OB_NOT_NULL(last_active_span_) + && GET_TAGLEVEL(tag_type) <= level_) { + if (OB_UNLIKELY(!append_tag(tag_type, value))) { + FLUSH_TRACE(); + IGNORE_RETURN append_tag(tag_type, value); + } + set_tag(std::forward(Fargs)...); + } + } + int serialize(char* buf, const int64_t buf_len, int64_t& pos) const; + int deserialize(const char* buf, const int64_t buf_len, int64_t& pos); + int64_t get_serialize_size() const { return 33; } + OB_INLINE UUID get_trace_id() { return trace_id_; } + OB_INLINE UUID get_root_span_id() { return root_span_id_; } + OB_INLINE uint8_t get_policy() { return policy_; } + OB_INLINE void set_level(uint8_t level) { level_ = 0x7f & level; } + OB_INLINE void set_auto_flush(bool auto_flush) { auto_flush_ = auto_flush; } + OB_INLINE bool is_auto_flush() { return auto_flush_; } + void check_leak_span(); + void reset(); + void dump_span(); + template::value && !std::is_convertible::value, bool>::type = true> + bool append_tag(ObTagType tag_type, const T& value) + { + int ret = false; + if (offset_ + sizeof(ObTagCtx) >= buffer_size_) { + // do nothing + } else { + ObTagCtx* tag = new (data_ + offset_) ObTagCtx; + tag->next_ = last_active_span_->tags_; + last_active_span_->tags_ = tag; + tag->tag_type_ = tag_type; + tag->data_ = value; + offset_ += sizeof(ObTagCtx); + ret = true; + } + return ret; + } + template::value, bool>::type = true> + bool append_tag(ObTagType tag_type, const T& value) + { + int ret = false; + common::ObString v(""); + if (OB_ISNULL(value.ptr())) { + // do nothing + } else { + v = value; + } + + auto l = value.length(); + if (offset_ + sizeof(ObTagCtx) + l + 1 - sizeof(void*) >= buffer_size_) { + // do nothing + } else { + ObTagCtx* tag = new (data_ + offset_) ObTagCtx; + tag->next_ = last_active_span_->tags_; + last_active_span_->tags_ = tag; + tag->tag_type_ = tag_type; + memcpy(&(tag->data_), value.ptr(), l); + offset_ += (sizeof(ObTagCtx) + l + 1 - sizeof(void*)); + data_[offset_ - 1] = '\0'; + ret = true; + } + + return ret; + } + template::value, bool>::type = true> + bool append_tag(ObTagType tag_type, const T& value) + { + return append_tag(tag_type, OB_ISNULL(value) ? common::ObString("") : common::ObString(value)); + } +private: + bool check_magic() { return MAGIC_CODE == magic_code_; } + void set_tag() {} +private: + static thread_local ObTrace* save_buffer; + uint64_t magic_code_; +public: + int64_t buffer_size_; + int64_t offset_; + common::ObDList current_span_; + common::ObDList freed_span_; + ObSpanCtx* last_active_span_; +private: + UUID trace_id_; + UUID root_span_id_; + union { + uint8_t policy_; + struct { + uint8_t level_ : 7; + bool auto_flush_ : 1; + }; + }; + uint64_t seq_; + char data_[0]; +}; + +class __ObFLTSpanGuard +{ +public: + __ObFLTSpanGuard(uint32_t span_type, uint8_t level) + { + span_ = OBTRACE->begin_span(span_type, level, false); +#ifndef NDEBUG + if (OB_NOT_NULL(span_) && span_->span_id_.is_inited()) { + FLT_SET_TAG(span_back_trace, common::lbt()); + } +#endif + } + ~__ObFLTSpanGuard() { FLT_END_SPAN(span_); } +private: + ObSpanCtx* span_; +}; + +template<> +int ObTagCtx::tostring(char* buf, const int64_t buf_len, int64_t& pos); + +} // trace +} // oceanbase + +#endif /* _OB_TRACE_H */ \ No newline at end of file diff --git a/src/lib/trace/ob_trace_def.h b/src/lib/trace/ob_trace_def.h new file mode 100644 index 0000000000000000000000000000000000000000..adbd3af1504f3ef0bec68736c0ff0fd3787f79ba --- /dev/null +++ b/src/lib/trace/ob_trace_def.h @@ -0,0 +1,169 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ +#ifdef FLT_DEF_SPAN + +#ifdef __HIGH_LEVEL_SPAN +FLT_DEF_SPAN(ob_proxy, "obproxy") +FLT_DEF_SPAN(ob_proxy_server_process_req, "server process req") +FLT_DEF_SPAN(ob_proxy_partition_location_lookup, "proxy partition location lookup") +#endif // __HIGH_LEVEL_SPAN + +#ifdef __MIDDLE_LEVEL_SPAN +FLT_DEF_SPAN(ob_proxy_server_response_read, "read resp from server") +FLT_DEF_SPAN(ob_proxy_cluster_resource_create, "proxy create cluster resource") +#endif // __MIDDLE_LEVEL_SPAN + +#ifdef __LOW_LEVEL_SPAN +FLT_DEF_SPAN(ob_proxy_do_observer_open, "proxy connect with server") +FLT_DEF_SPAN(ob_proxy_client_response_write, "proxy write resp to client") +FLT_DEF_SPAN(ob_proxy_server_request_write, "proxy write req to server") +#endif // __LOW_LEVEL_SPAN + +#endif // DEF_SPAN + + +#ifdef FLT_DEF_TAG + +#ifdef __HIGH_LEVEL_TAG +FLT_DEF_TAG(query_start_ts, "server query start ts") +FLT_DEF_TAG(query_end_ts, "server query end ts") +FLT_DEF_TAG(client_host, "client host addr") + +// debug +FLT_DEF_TAG(span_back_trace, "full link tracing debug") +#endif // __HIGH_LEVEL_TAG + +#ifdef __MIDDLE_LEVEL_TAG +#endif // __MIDDLE_LEVEL_TAG + +#ifdef __LOW_LEVEL_TAG +#endif // __LOW_LEVEL_TAG + +#endif // DEF_TAG + + +#ifndef _OB_TRACE_DEF_H +#define _OB_TRACE_DEF_H + +#include +#include "lib/utility/ob_macro_utils.h" + +enum ObTagType +{ +#define FLT_DEF_TAG(name, comment) name, +#define __HIGH_LEVEL_TAG +#define __MIDDLE_LEVEL_TAG +#define __LOW_LEVEL_TAG +#include "lib/trace/ob_trace_def.h" +#undef __LOW_LEVEL_TAG +#undef __MIDDLE_LEVEL_TAG +#undef __HIGH_LEVEL_TAG +#undef FLT_DEF_TAG +}; + +namespace oceanbase +{ +namespace trace +{ +#define GET_SPANLEVEL(ID) (::oceanbase::trace::__SpanIdMapper::level) +#define GET_TAGLEVEL(ID) (::oceanbase::trace::__tag_level_mapper[ID]) + +enum ObSpanType +{ +#define __HIGH_LEVEL_SPAN +#define __MIDDLE_LEVEL_SPAN +#define __LOW_LEVEL_SPAN +#define FLT_DEF_SPAN(name, comment) name, +#include "lib/trace/ob_trace_def.h" +#undef FLT_DEF_SPAN +#undef __LOW_LEVEL_SPAN +#undef __MIDDLE_LEVEL_SPAN +#undef __HIGH_LEVEL_SPAN +}; + +static const uint8_t __tag_level_mapper[] = { +#define FLT_DEF_TAG(ID, comment) 1, +#define __HIGH_LEVEL_TAG +#include "lib/trace/ob_trace_def.h" +#undef __HIGH_LEVEL_TAG +#undef FLT_DEF_TAG + +#define FLT_DEF_TAG(ID, comment) 2, +#define __MIDDLE_LEVEL_TAG +#include "lib/trace/ob_trace_def.h" +#undef __MIDDLE_LEVEL_TAG +#undef FLT_DEF_TAG + +#define FLT_DEF_TAG(ID, comment) 3, +#define __LOW_LEVEL_TAG +#include "lib/trace/ob_trace_def.h" +#undef __LOW_LEVEL_TAG +#undef FLT_DEF_TAG +}; + +static const char* __tag_name_mapper[] = { +#define FLT_DEF_TAG(name, comment) #name, +#define __HIGH_LEVEL_TAG +#define __MIDDLE_LEVEL_TAG +#define __LOW_LEVEL_TAG +#include "lib/trace/ob_trace_def.h" +#undef __LOW_LEVEL_TAG +#undef __MIDDLE_LEVEL_TAG +#undef __HIGH_LEVEL_TAG +#undef FLT_DEF_TAG +}; + + +template +class __SpanIdMapper {}; + +#define FLT_DEF_SPAN(ID, comment) \ +template <> \ +class __SpanIdMapper \ +{ \ +public: \ + static constexpr uint8_t level = 1; \ +}; +#define __HIGH_LEVEL_SPAN +#include "lib/trace/ob_trace_def.h" +#undef __HIGH_LEVEL_SPAN +#undef FLT_DEF_SPAN + +#define FLT_DEF_SPAN(ID, comment) \ +template <> \ +class __SpanIdMapper \ +{ \ +public: \ + static constexpr uint8_t level = 2; \ +}; +#define __MIDDLE_LEVEL_SPAN +#include "lib/trace/ob_trace_def.h" +#undef __MIDDLE_LEVEL_SPAN +#undef FLT_DEF_SPAN + +#define FLT_DEF_SPAN(ID, comment) \ +template <> \ +class __SpanIdMapper \ +{ \ +public: \ + static constexpr uint8_t level = 3; \ +}; +#define __LOW_LEVEL_SPAN +#include "lib/trace/ob_trace_def.h" +#undef __LOW_LEVEL_SPAN +#undef FLT_DEF_SPAN + +} // trace +} // oceanbase + +#endif /* _OB_TRACE_DEF_H */ + \ No newline at end of file diff --git a/src/lib/utility/ob_2_0_full_link_trace_info.cpp b/src/lib/utility/ob_2_0_full_link_trace_info.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d22c4ffe4af4f58a843e7a027b90c70e7cbfad84 --- /dev/null +++ b/src/lib/utility/ob_2_0_full_link_trace_info.cpp @@ -0,0 +1,545 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ +#define USING_LOG_PREFIX PROXY + +#include "lib/utility/ob_2_0_full_link_trace_info.h" +#include "lib/oblog/ob_log.h" + + +namespace oceanbase +{ + +namespace common +{ + +// pos=0, len->sub_len, buf->sub_buf +int FLTExtraInfo::deserialize(const char *buf, const int64_t len, int64_t &pos) +{ + int ret = OB_SUCCESS; + int64_t buf_end = pos + len; + + while (OB_SUCC(ret) && pos < len) { + int32_t v_len = 0; + int16_t id = 0; + if (OB_FAIL(Ob20FullLinkTraceTransUtil::resolve_type_and_len(buf, buf_end, pos, id, v_len))) { + LOG_WARN("fail to resolve type and len", K(ret)); + } else if (OB_FAIL(deserialize_field(static_cast(id), v_len, buf, buf_end, pos))) { + LOG_WARN("fail to deserialize field", K(ret), K(id)); + } else { + //nothing + } + } + + return ret; +} + +int FLTControlInfo::serialize(char *buf, const int64_t len, int64_t &pos) +{ + int ret = OB_SUCCESS; + + int64_t orig_pos = pos; + if (pos + FLT_TYPE_AND_LEN > len) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("buf size overflow", K(len), K(pos)); + } else { + pos += FLT_TYPE_AND_LEN; + + if (OB_FAIL(ret)) { + // nothing + } else if (OB_FAIL(Ob20FullLinkTraceTransUtil::store_int1(buf, len, pos, level_, FLT_LEVEL))) { + LOG_WARN("fail to store int1", K(ret)); + } else if (OB_FAIL(Ob20FullLinkTraceTransUtil::store_double(buf, len, pos, sample_percentage_, + FLT_SAMPLE_PERCENTAGE))) { + LOG_WARN("fail to store sample pct", K(ret)); + } else if (OB_FAIL(Ob20FullLinkTraceTransUtil::store_int1(buf, len, pos, record_policy_, FLT_RECORD_POLICY))) { + LOG_WARN("fail to store int1", K(ret)); + } else if (OB_FAIL(Ob20FullLinkTraceTransUtil::store_double(buf, len, pos, print_sample_percentage_, + FLT_PRINT_SAMPLE_PCT))) { + LOG_WARN("fail to store print sample pct", K(ret)); + } else if (OB_FAIL(Ob20FullLinkTraceTransUtil::store_int8(buf, len, pos, slow_query_threshold_, + FLT_SLOW_QUERY_THRES))) { + LOG_WARN("fail to store slow query threshold", K(ret)); + } else { + int32_t total_len = static_cast(pos - orig_pos - FLT_TYPE_AND_LEN); + if (OB_FAIL(Ob20FullLinkTraceTransUtil::store_type_and_len(buf, len, orig_pos, type_, total_len))) { + LOG_WARN("fail to store type and len", K(ret)); + } else { + LOG_DEBUG("succ to serialize control info", K(pos), K(len), K(total_len)); + } + } + } + + return ret; +} + +int FLTControlInfo::deserialize_field(FullLinkTraceExtraInfoId id, + const int64_t v_len, + const char *buf, + const int64_t len, + int64_t &pos) +{ + int ret = OB_SUCCESS; + + if (id == FLT_LEVEL) { + if (OB_FAIL(Ob20FullLinkTraceTransUtil::get_int1(buf, len, pos, v_len, level_))) { + LOG_WARN("fail to resolve level", K(ret)); + } + } else if (id == FLT_SAMPLE_PERCENTAGE) { + if (OB_FAIL(Ob20FullLinkTraceTransUtil::get_double(buf, len, pos, v_len, sample_percentage_))) { + LOG_WARN("fail to resolve sample percentage", K(ret)); + } + } else if (id == FLT_RECORD_POLICY) { + int8_t rc = 0; + if (OB_FAIL(Ob20FullLinkTraceTransUtil::get_int1(buf, len, pos, v_len, rc))) { + LOG_WARN("fail to resolve record policy", K(ret)); + } else { + record_policy_ = static_cast(rc); + } + } else if (id == FLT_PRINT_SAMPLE_PCT) { + if (OB_FAIL(Ob20FullLinkTraceTransUtil::get_double(buf, len, pos, v_len, print_sample_percentage_))) { + LOG_WARN("fail to resolve print sample percentage", K(ret)); + } + } else if (id == FLT_SLOW_QUERY_THRES) { + if (OB_FAIL(Ob20FullLinkTraceTransUtil::get_int8(buf, len, pos, v_len, slow_query_threshold_))) { + LOG_WARN("fail to resolve slow query threshold", K(ret)); + } + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected control info id", K(ret), K(id)); + } + + if (OB_SUCC(ret)) { + set_need_send(true); + } + + return ret; +} + +// total: 62 +int64_t FLTControlInfo::get_serialize_size() +{ + return FLT_TYPE_AND_LEN + + FLT_TYPE_AND_LEN + sizeof(level_) + + FLT_TYPE_AND_LEN + sizeof(sample_percentage_) + + FLT_TYPE_AND_LEN + sizeof(int8_t) + + FLT_TYPE_AND_LEN + sizeof(print_sample_percentage_) + + FLT_TYPE_AND_LEN + sizeof(slow_query_threshold_); +} + +void FLTSpanInfo::reset() { + trace_enable_ = false; + force_print_ = false; + trace_id_.reset(); + span_id_.reset(); +} + +int FLTSpanInfo::serialize(char *buf, const int64_t len, int64_t &pos) +{ + int ret = OB_SUCCESS; + + int64_t orig_pos = pos; + if (pos + FLT_TYPE_AND_LEN > len) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("buf size overflow", K(len), K(pos)); + } else { + pos += FLT_TYPE_AND_LEN; + + if (OB_FAIL(ret)) { + //nothing + } else if (OB_FAIL(Ob20FullLinkTraceTransUtil::store_int1(buf, len, pos, trace_enable_, FLT_TRACE_ENABLE))) { + LOG_WARN("fail to store int1", K(ret)); + } else if (OB_FAIL(Ob20FullLinkTraceTransUtil::store_int1(buf, len, pos, force_print_, FLT_FORCE_PRINT))) { + LOG_WARN("fail to store int1", K(ret)); + } else if (OB_FAIL(Ob20FullLinkTraceTransUtil::store_int1(buf, len, pos, ref_type_, FLT_REF_TYPE))) { + LOG_WARN("fail to store int1", K(ret)); + } else if (OB_FAIL(Ob20FullLinkTraceTransUtil::store_uuid(buf, len, pos, trace_id_, FLT_TRACE_ID))) { + LOG_WARN("fail to store trace id", K(ret)); + } else if (OB_FAIL(Ob20FullLinkTraceTransUtil::store_uuid(buf, len, pos, span_id_, FLT_SPAN_ID))) { + LOG_WARN("fail to store span id", K(ret)); + } else { + // fill type and len in the head + int32_t total_len = static_cast(pos - orig_pos - FLT_TYPE_AND_LEN); + if (OB_SUCC(ret) + && OB_FAIL(Ob20FullLinkTraceTransUtil::store_type_and_len(buf, len, orig_pos, type_, total_len))) { + LOG_WARN("fail to store type and len in head", K(ret)); + } else { + LOG_DEBUG("succ to seri span info", K(pos), K(len), K(type_), K(total_len)); + } + } + } + + return ret; +} + +int FLTSpanInfo::deserialize_field(FullLinkTraceExtraInfoId id, + const int64_t v_len, + const char *buf, + const int64_t len, + int64_t &pos) +{ + int ret = OB_SUCCESS; + + if (id == FLT_TRACE_ENABLE) { + int8_t v = 0; + if (OB_FAIL(Ob20FullLinkTraceTransUtil::get_int1(buf, len, pos, v_len, v))) { + LOG_WARN("fail to resolve trace enable", K(ret)); + } else { + trace_enable_ = static_cast(v); + } + } else if (id == FLT_FORCE_PRINT) { + int8_t v = 0; + if (OB_FAIL(Ob20FullLinkTraceTransUtil::get_int1(buf, len, pos, v_len, v))) { + LOG_WARN("fail to resolve force print", K(ret)); + } else { + force_print_ = static_cast(v); + } + } else if (id == FLT_TRACE_ID) { + if (OB_FAIL(Ob20FullLinkTraceTransUtil::get_uuid(buf, len, pos, v_len, trace_id_))) { + LOG_WARN("fail to resolve trace id", K(ret)); + } + } else if (id == FLT_REF_TYPE) { + int8_t v = 0; + if (OB_FAIL(Ob20FullLinkTraceTransUtil::get_int1(buf, len, pos, v_len, v))) { + LOG_WARN("fail to get ref type", K(ret)); + } else { + ref_type_ = static_cast(v); + } + } else if (id == FLT_SPAN_ID) { + if (OB_FAIL(Ob20FullLinkTraceTransUtil::get_uuid(buf, len, pos, v_len, span_id_))) { + LOG_WARN("fail to get span id", K(ret)); + } + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected span info id", K(ret), K(id)); + } + + return ret; +} + +// total: 71 +int64_t FLTSpanInfo::get_serialize_size() +{ + + return FLT_TYPE_AND_LEN + + FLT_TYPE_AND_LEN + sizeof(trace_enable_) + + FLT_TYPE_AND_LEN + sizeof(force_print_) + + FLT_TYPE_AND_LEN + trace_id_.get_serialize_size() + + FLT_TYPE_AND_LEN + sizeof(int8_t) + + FLT_TYPE_AND_LEN + trace_id_.get_serialize_size(); // single span_id UUID +} + +int FLTQueryInfo::serialize(char *buf, const int64_t len, int64_t &pos) +{ + int ret = OB_SUCCESS; + + int64_t orig_pos = pos; + if (pos + FLT_TYPE_AND_LEN > len) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("buf size overflow", K(len), K(pos)); + } else { + pos += FLT_TYPE_AND_LEN; + + if (OB_FAIL(Ob20FullLinkTraceTransUtil::store_int8(buf, len, pos, query_start_ts_, FLT_QUERY_START_TIMESTAMP))) { + LOG_WARN("fail to store int8", K(ret)); + } else if (OB_FAIL(Ob20FullLinkTraceTransUtil::store_int8(buf, len, pos, query_end_ts_, FLT_QUERY_END_TIMESTAMP))) { + LOG_WARN("fail to store int8", K(ret)); + } else { + int32_t total_len = static_cast(pos - orig_pos - FLT_TYPE_AND_LEN); + if (OB_FAIL(Ob20FullLinkTraceTransUtil::store_type_and_len(buf, len, orig_pos, type_, total_len))) { + LOG_WARN("fail to store type and len", K(ret)); + } else { + LOG_DEBUG("succ to serialize query info", K(pos), K(len), K(total_len)); + } + } + } + + return ret; +} + +int FLTQueryInfo::deserialize_field(FullLinkTraceExtraInfoId id, + const int64_t v_len, + const char *buf, + const int64_t len, + int64_t &pos) +{ + int ret = OB_SUCCESS; + + if (id == FLT_QUERY_START_TIMESTAMP) { + if (OB_FAIL(Ob20FullLinkTraceTransUtil::get_int8(buf, len, pos, v_len, query_start_ts_))) { + LOG_WARN("fail to resolve query start timestamp", K(ret)); + } + } else if (id == FLT_QUERY_END_TIMESTAMP) { + if (OB_FAIL(Ob20FullLinkTraceTransUtil::get_int8(buf, len, pos, v_len, query_end_ts_))) { + LOG_WARN("fail to resolve query end timestamp", K(ret)); + } + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected query info id", K(ret), K(id)); + } + + return ret; +} + +// 34 +int64_t FLTQueryInfo::get_serialize_size() +{ + return FLT_TYPE_AND_LEN + + FLT_TYPE_AND_LEN + sizeof(query_start_ts_) + + FLT_TYPE_AND_LEN + sizeof(query_end_ts_); +} + +int FLTAppInfo::serialize(char *buf, const int64_t len, int64_t &pos) +{ + int ret = OB_SUCCESS; + + if (OB_FAIL(Ob20FullLinkTraceTransUtil::store_str(buf, len, pos, flt_app_info_buf_, + static_cast(flt_app_info_buf_len_), FLT_APP_INFO))) { + LOG_WARN("fail to store str as app info", K(ret)); + } else { + LOG_DEBUG("succ to serialize FLTAppInfo"); + } + + return ret; +} + +// only save the buffer, transfer to server, no need to decode content +int FLTAppInfo::deserialize(const char *buf, const int64_t len, int64_t &pos) +{ + int ret = OB_SUCCESS; + + MEMCPY(flt_app_info_buf_, buf, len); + flt_app_info_buf_len_ = len; + pos += len; + + LOG_DEBUG("succ to deserialize app info", K(pos)); + + return ret; +} + +int FLTAppInfo::deserialize_field(FullLinkTraceExtraInfoId id, const int64_t v_len, + const char *buf, const int64_t len, int64_t &pos) +{ + UNUSED(v_len); + UNUSED(buf); + UNUSED(len); + UNUSED(pos); + + LOG_WARN("flt app info need deserialize directly, unexpected error to invoke here", K(id)); + + return OB_ERR_UNEXPECTED; +} + +// 256 + 6 = 262 at max +int64_t FLTAppInfo::get_serialize_size() +{ + return FLT_TYPE_AND_LEN + flt_app_info_buf_len_; +} + +FLTAppInfo &FLTAppInfo::operator=(const FLTAppInfo &other) +{ + if (this != &other) { + if (other.flt_app_info_buf_len_ != 0) { + MEMCPY(flt_app_info_buf_, other.flt_app_info_buf_, other.flt_app_info_buf_len_); + flt_app_info_buf_len_ = other.flt_app_info_buf_len_; + } + } + + return *this; +} + +int FLTDriverSpanInfo::serialize(char *buf, const int64_t len, int64_t &pos) +{ + UNUSED(buf); + UNUSED(len); + UNUSED(pos); + + int ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected serialize type", K(type_)); + + return ret; +} + +// after this info resolved, use TRACE interface to print immediatly, other wise the buf will be freed, +// proxy will not persist the mem of buf +int FLTDriverSpanInfo::deserialize_field(FullLinkTraceExtraInfoId id, + const int64_t v_len, + const char *buf, + const int64_t len, + int64_t &pos) +{ + int ret = OB_SUCCESS; + + if (id == FLT_DRV_SPAN) { + char *ptr = NULL; + if (OB_FAIL(Ob20FullLinkTraceTransUtil::get_str(buf, len, pos, v_len, ptr))) { + LOG_WARN("fail to get str for driver span info", K(ret)); + } else { + curr_driver_span_.assign_ptr(ptr, static_cast(v_len)); + } + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected extra info id", K(ret), K(id)); + } + + return ret; +} + +int64_t FLTDriverSpanInfo::get_serialize_size() +{ + return 0; +} + +/* + * deserialize from full_trc + * the format described in ob_2_0_full_link_trace_util.h + * check while ret back, if (pos != len) err + */ +int FLTObjManage::deserialize(const char *buf, const int64_t len, int64_t &pos) +{ + int ret = OB_SUCCESS; + + while (OB_SUCC(ret) && pos < len) { + int16_t first_type = 0; + int32_t first_len = 0; + FLTExtraInfo *extra = NULL; + + if (OB_FAIL(Ob20FullLinkTraceTransUtil::resolve_type_and_len(buf, + len, + pos, + first_type, + first_len))) { + LOG_WARN("fail to resolve first type and len", K(ret), K(buf), K(len), K(pos)); + break; + } else if (OB_FAIL(get_extra_info_ref_by_type(static_cast(first_type), extra))) { + LOG_WARN("fail to get extra info ref by type", K(ret)); + break; + } else { + int64_t second_pos = 0; + if (OB_FAIL(extra->deserialize(buf + pos, first_len, second_pos))) { + LOG_WARN("fail to deserialize extra", K(ret)); + } else if (second_pos != first_len) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected error, please check the packet content or the deserialize logic", + K(ret), K(first_len), K(second_pos)); + } else { + pos += second_pos; + } + } + } + + return ret; +} + +int FLTObjManage::get_extra_info_ref_by_type(FullLinkTraceExtraInfoType type, FLTExtraInfo* &extra) +{ + int ret = OB_SUCCESS; + + if (type <= FLT_EXTRA_TYPE_BEGIN || type >= FLT_EXTRA_TYPE_END) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected flt extra info type", K(ret), K(type)); + } else { + if (type == FLT_SPAN_INFO) { + span_info_.reset(); + extra = &span_info_; + } else if (type == FLT_CONTROL_INFO) { + control_info_.reset(); + extra = &control_info_; + } else if (type == FLT_QUERY_INFO) { + query_info_.reset(); + extra = &query_info_; + } else if (type == FLT_APP_INFO) { + app_info_.reset(); + extra = &app_info_; + } else if (type == FLT_DRIVER_SPAN_INFO) { + extra = &driver_span_info_; + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected extra info type", K(ret), K(type)); + } + } + + return ret; +} + +void FLTObjManage::reset() +{ + span_info_.reset(); + control_info_.reset(); + query_info_.reset(); + app_info_.reset(); // memset! + driver_span_info_.reset(); // memset! + trace_log_info_.reset(); +} + +int64_t FLTTraceLogInfo::to_string(char *buf, const int64_t buf_len) const +{ + int64_t pos = 0; + J_OBJ_START(); + J_KV("is_init", is_inited_, + "proxy_root_span_begin_time", proxy_root_span_begin_time_); + if (proxy_root_span_ctx_ != NULL) { + J_COMMA(); + J_KV("proxy_root_span_ctx_uuid", proxy_root_span_ctx_->span_id_, + "proxy_root_span_ctx_start_ts", proxy_root_span_ctx_->start_ts_, + "proxy_root_span_ctx_end_ts", proxy_root_span_ctx_->end_ts_); + } + if (server_process_req_ctx_ != NULL) { + J_COMMA(); + J_KV("server_process_req_ctx_uuid", server_process_req_ctx_->span_id_, + "server_process_req_ctx_start_ts", server_process_req_ctx_->start_ts_, + "server_process_req_ctx_end_ts", server_process_req_ctx_->end_ts_); + } + if (server_response_read_ctx_ != NULL) { + J_COMMA(); + J_KV("server_response_read_ctx_uuid", server_response_read_ctx_->span_id_, + "server_response_read_ctx_start_ts", server_response_read_ctx_->start_ts_, + "server_response_read_ctx_end_ts", server_response_read_ctx_->end_ts_); + } + if (cluster_resource_create_ctx_ != NULL) { + J_COMMA(); + J_KV("cluster_resource_create_ctx_uuid", cluster_resource_create_ctx_->span_id_, + "cluster_resource_create_ctx_start_ts", cluster_resource_create_ctx_->start_ts_, + "cluster_resource_create_ctx_end_ts", cluster_resource_create_ctx_->end_ts_); + } + if (partition_location_lookup_ctx_ != NULL) { + J_COMMA(); + J_KV("partition_location_lookup_ctx_uuid", partition_location_lookup_ctx_->span_id_, + "partition_location_lookup_ctx_start_ts", partition_location_lookup_ctx_->start_ts_, + "partition_location_lookup_ctx_end_ts", partition_location_lookup_ctx_->end_ts_); + } + if (do_observer_open_ctx_ != NULL) { + J_COMMA(); + J_KV("do_observer_open_ctx_uuid", do_observer_open_ctx_->span_id_, + "do_observer_open_ctx_start_ts", do_observer_open_ctx_->start_ts_, + "do_observer_open_ctx_end_ts", do_observer_open_ctx_->end_ts_); + } + if (client_response_write_ctx_ != NULL) { + J_COMMA(); + J_KV("client_response_write_ctx_uuid", client_response_write_ctx_->span_id_, + "client_response_write_ctx_start_ts", client_response_write_ctx_->start_ts_, + "client_response_write_ctx_end_ts", client_response_write_ctx_->end_ts_); + } + if (server_request_write_ctx_ != NULL) { + J_COMMA(); + J_KV("server_request_write_ctx_uuid", server_request_write_ctx_->span_id_, + "server_request_write_ctx_start_ts", server_request_write_ctx_->start_ts_, + "server_request_write_ctx_end_ts", server_request_write_ctx_->end_ts_); + } + J_OBJ_END(); + return pos; +} + + +} // common + +} // oceanbase + diff --git a/src/lib/utility/ob_2_0_full_link_trace_info.h b/src/lib/utility/ob_2_0_full_link_trace_info.h new file mode 100644 index 0000000000000000000000000000000000000000..b4b0d19d60397905a897236ff4cb1718cbcc649e --- /dev/null +++ b/src/lib/utility/ob_2_0_full_link_trace_info.h @@ -0,0 +1,399 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef _OBPROXY_OB_2_0_FULL_LINK_TRACE_INFO_H_ +#define _OBPROXY_OB_2_0_FULL_LINK_TRACE_INFO_H_ + +#include "lib/charset/ob_mysql_global.h" +#include "common/ob_object.h" +#include "lib/utility/ob_2_0_full_link_trace_util.h" +#include "lib/trace/ob_trace.h" +#include "lib/container/ob_se_array.h" + +namespace oceanbase +{ + +namespace common +{ + +using namespace oceanbase::trace; + +#define FLT_APP_INFO_BUF_MAX (260) +#define FLT_EXTRA_INFO_DEF(extra_id, id, type) extra_id = id, + +/* + * oceanbase protocol 2.0, extra info id + */ +enum FullLinkTraceExtraInfoId +{ + // here to add driver's id + FLT_EXTRA_INFO_DEF(FLT_DRV_SPAN, 1, obmysql::OB_MYSQL_TYPE_VAR_STRING) + FLT_EXTRA_INFO_DEF(FLT_DRIVER_END, 1000, obmysql::OB_MYSQL_TYPE_NOT_DEFINED) + + // here to add proxy's id + FLT_EXTRA_INFO_DEF(FLT_PROXY_END, 2000, obmysql::OB_MYSQL_TYPE_NOT_DEFINED) + + // APP_INFO + FLT_EXTRA_INFO_DEF(FLT_CLIENT_IDENTIFIER, 2001, obmysql::OB_MYSQL_TYPE_VAR_STRING) + FLT_EXTRA_INFO_DEF(FLT_MODULE, 2002, obmysql::OB_MYSQL_TYPE_VAR_STRING) + FLT_EXTRA_INFO_DEF(FLT_ACTION, 2003, obmysql::OB_MYSQL_TYPE_VAR_STRING) + FLT_EXTRA_INFO_DEF(FLT_CLIENT_INFO, 2004, obmysql::OB_MYSQL_TYPE_VAR_STRING) + + // QUERY INFO + FLT_EXTRA_INFO_DEF(FLT_QUERY_START_TIMESTAMP, 2010, obmysql::OB_MYSQL_TYPE_LONGLONG) + FLT_EXTRA_INFO_DEF(FLT_QUERY_END_TIMESTAMP, 2011, obmysql::OB_MYSQL_TYPE_LONGLONG) + + // CONTROL INFO + FLT_EXTRA_INFO_DEF(FLT_LEVEL, 2020, obmysql::OB_MYSQL_TYPE_TINY) + FLT_EXTRA_INFO_DEF(FLT_SAMPLE_PERCENTAGE, 2021, obmysql::OB_MYSQL_TYPE_DOUBLE) + FLT_EXTRA_INFO_DEF(FLT_RECORD_POLICY, 2022, obmysql::OB_MYSQL_TYPE_TINY) + FLT_EXTRA_INFO_DEF(FLT_PRINT_SAMPLE_PCT, 2023, obmysql::OB_MYSQL_TYPE_DOUBLE) + FLT_EXTRA_INFO_DEF(FLT_SLOW_QUERY_THRES, 2024, obmysql::OB_MYSQL_TYPE_LONGLONG) + + // tdo print_sample_percentage && slow_query_threshold + + // SPAN INFO + FLT_EXTRA_INFO_DEF(FLT_TRACE_ENABLE, 2030, obmysql::OB_MYSQL_TYPE_TINY) + FLT_EXTRA_INFO_DEF(FLT_FORCE_PRINT, 2031, obmysql::OB_MYSQL_TYPE_TINY) + FLT_EXTRA_INFO_DEF(FLT_TRACE_ID, 2032, obmysql::OB_MYSQL_TYPE_VAR_STRING) // uuid type + FLT_EXTRA_INFO_DEF(FLT_REF_TYPE, 2033, obmysql::OB_MYSQL_TYPE_TINY) + FLT_EXTRA_INFO_DEF(FLT_SPAN_ID, 2034, obmysql::OB_MYSQL_TYPE_VAR_STRING) // uuid type + + // END + FLT_EXTRA_INFO_DEF(FLT_EXTRA_INFO_END, 2040, obmysql::OB_MYSQL_TYPE_NOT_DEFINED) +}; + +enum FullLinkTraceExtraInfoType +{ + FLT_EXTRA_TYPE_BEGIN = 0, + + FLT_DRIVER_SPAN_INFO = 1, + FLT_EXTRA_INFO_DRIVER_END = 1000, + + FLT_APP_INFO = 2001, + FLT_QUERY_INFO, + FLT_CONTROL_INFO, + FLT_SPAN_INFO, + + FLT_EXTRA_TYPE_END +}; + +enum FullLinkTraceRecordPolicy { + RP_ALL = 1, + RP_ONLY_SLOW_QUERY = 2, + RP_SAMPLE_AND_SLOW_QUERY = 3, + MAX_RECORD_POLICY = 4 +}; + +/* + * according to the format of FLT, see ob_2_0_full_link_trace_util.h + * each deserialize function could be invoke more than one in one loop to analyze multi-objs in the same type + * attention to the manage of pos, pos init to 0 is recommended. otherwise the logic will be error. + */ +class FLTExtraInfo { +public: + FLTExtraInfo() : type_(FLT_EXTRA_TYPE_END) {} + virtual ~FLTExtraInfo() {} + + virtual int deserialize(const char *buf, const int64_t len, int64_t &pos); + virtual int serialize(char *buf, const int64_t len, int64_t &pos) = 0; + virtual int deserialize_field(FullLinkTraceExtraInfoId extra_id, const int64_t v_len, + const char *buf, const int64_t len, int64_t &pos) = 0; + virtual int64_t get_serialize_size() = 0; + + bool is_app_info() { return type_ == FLT_APP_INFO; } + bool is_query_info() { return type_ == FLT_QUERY_INFO; } + bool is_control_info() { return type_ == FLT_CONTROL_INFO; } + bool is_span_info() { return type_ == FLT_SPAN_INFO; } + +public: + FullLinkTraceExtraInfoType type_; +}; + + +class FLTControlInfo : public FLTExtraInfo +{ +public: + FLTControlInfo() + : level_(0), + sample_percentage_(-1), + record_policy_(MAX_RECORD_POLICY), + print_sample_percentage_(-1), + slow_query_threshold_(-1), + is_need_send_(false) + + { type_ = FLT_CONTROL_INFO; } + ~FLTControlInfo () {} + + bool is_valid() const { + return type_ == FLT_CONTROL_INFO + && is_level_valid() + && sample_percentage_ >= 0 + && sample_percentage_ <= 1 + && record_policy_ >= RP_ALL + && record_policy_ < MAX_RECORD_POLICY + && print_sample_percentage_ >= 0 + && print_sample_percentage_ <= 1 + && slow_query_threshold_ > 0; + } + + inline bool is_level_valid() const { return level_ > 0 && level_ <= 3; } + + void reset() { + level_ = 0; + sample_percentage_ = -1; + record_policy_ = MAX_RECORD_POLICY; + print_sample_percentage_ = -1; + slow_query_threshold_ = -1; + is_need_send_ = false; + } + + OB_INLINE void set_need_send(bool sent) { is_need_send_ = sent; } + OB_INLINE bool is_need_send() const { return is_need_send_; } + + virtual int serialize(char *buf, const int64_t len, int64_t &pos); + virtual int deserialize_field(FullLinkTraceExtraInfoId extra_id, const int64_t v_len, + const char *buf, const int64_t len, int64_t &pos); + virtual int64_t get_serialize_size(); + + TO_STRING_KV(K_(level), K_(sample_percentage), K_(record_policy), + K_(print_sample_percentage), K_(slow_query_threshold), K_(type), K_(is_need_send)); + +public: + int8_t level_; // span level + double sample_percentage_; // control trace enable percentage + FullLinkTraceRecordPolicy record_policy_; // record policy + double print_sample_percentage_; // control force print percentage + int64_t slow_query_threshold_; // slow query threshold (us) + + /* + * whether the control info needed sent to client,do not seri/deseri it + * observer could send invalid span info to proxy/client + * while it has been changed, proxy should send it back to client + */ + bool is_need_send_; +}; + +enum FLTSpanRefType { + SYNC, + ASYNC, + MAX_REF_TYPE +}; + +class FLTSpanInfo : public FLTExtraInfo +{ +public: + FLTSpanInfo() + : trace_enable_(false), + force_print_(false), + ref_type_(MAX_REF_TYPE), + trace_id_(), + span_id_() + { + type_ = FLT_SPAN_INFO; + } + + ~FLTSpanInfo() {} + + void reset(); + + bool is_valid() const { + return trace_id_.is_inited() + && span_id_.is_inited() + && type_ == FLT_SPAN_INFO + && ref_type_ != MAX_REF_TYPE; + } + + virtual int serialize(char *buf, const int64_t len, int64_t &pos); + virtual int deserialize_field(FullLinkTraceExtraInfoId extra_id, const int64_t v_len, + const char *buf, const int64_t len, int64_t &pos); + virtual int64_t get_serialize_size(); + + TO_STRING_KV(K_(trace_enable), K_(force_print), K_(ref_type), K_(trace_id), K_(span_id), K_(type)); + +public: + bool trace_enable_; + bool force_print_; + FLTSpanRefType ref_type_; + UUID trace_id_; + UUID span_id_; +}; + +// resolve from server response ok packet, use TRACE interface to print +class FLTQueryInfo : public FLTExtraInfo +{ +public: + FLTQueryInfo() : query_start_ts_(0), query_end_ts_(0) { type_ = FLT_QUERY_INFO; } + ~FLTQueryInfo() {} + + virtual int serialize(char *buf, const int64_t len, int64_t &pos); + virtual int deserialize_field(FullLinkTraceExtraInfoId extra_id, const int64_t v_len, + const char *buf, const int64_t len, int64_t &pos); + virtual int64_t get_serialize_size(); + + void reset() { + query_start_ts_ = 0; + query_end_ts_ = 0; + } + + bool is_valid() const { + return (type_ == FLT_QUERY_INFO) + && (query_start_ts_ != 0 || query_end_ts_ != 0); + } + + TO_STRING_KV(K_(query_start_ts), K_(query_end_ts), K_(type)); + +public: + int64_t query_start_ts_; + int64_t query_end_ts_; +}; + + +class FLTAppInfo : public FLTExtraInfo +{ +public: + FLTAppInfo() : flt_app_info_buf_len_(0) { type_ = FLT_APP_INFO; } + //FLTAppInfo(const FLTAppInfo &other) { *this = other; } + ~FLTAppInfo() {} + + virtual int deserialize(const char *buf, const int64_t len, int64_t &pos); + virtual int serialize(char *buf, const int64_t len, int64_t &pos); + virtual int deserialize_field(FullLinkTraceExtraInfoId id, const int64_t v_len, + const char *buf, const int64_t len, int64_t &pos); + virtual int64_t get_serialize_size(); + + FLTAppInfo &operator=(const FLTAppInfo &other); + + void reset() { + MEMSET(flt_app_info_buf_, 0, sizeof(flt_app_info_buf_)); + flt_app_info_buf_len_ = 0; + type_ = FLT_APP_INFO; + } + + bool is_valid() const { + return flt_app_info_buf_len_ > 0 + && type_ == FLT_APP_INFO; + } + + TO_STRING_KV(K_(flt_app_info_buf), K_(flt_app_info_buf_len), K_(type)); + +public: + char flt_app_info_buf_[FLT_APP_INFO_BUF_MAX]; // ref to design document, max: 64*4 + int64_t flt_app_info_buf_len_; // ref to ObZoneStateInfo, stored in obmysqlsm +}; + + +// resolve from client request, use TRACE interface to print +class FLTDriverSpanInfo : public FLTExtraInfo +{ +public: + FLTDriverSpanInfo() { type_ = FLT_DRIVER_SPAN_INFO; } + ~FLTDriverSpanInfo() {} + + virtual int serialize(char *buf, const int64_t len, int64_t &pos); + virtual int deserialize_field(FullLinkTraceExtraInfoId extra_id, const int64_t v_len, + const char *buf, const int64_t len, int64_t &pos); + virtual int64_t get_serialize_size(); + + void reset() { + curr_driver_span_.reset(); + type_ = FLT_DRIVER_SPAN_INFO; + } + + bool is_valid() const { + return (type_ == FLT_DRIVER_SPAN_INFO) + && (!curr_driver_span_.empty()); + } + + TO_STRING_KV(K_(curr_driver_span), K_(type)); + +public: + ObString curr_driver_span_; +}; + +// full link trace log info +class FLTTraceLogInfo { +public: + FLTTraceLogInfo() : is_inited_(false), proxy_root_span_begin_time_(-1) {} + ~FLTTraceLogInfo() {} + + void reset() { + MEMSET(this, 0x0, sizeof(FLTTraceLogInfo)); + is_inited_ = false; + proxy_root_span_begin_time_ = -1; + proxy_root_span_ctx_ = NULL; + server_process_req_ctx_ = NULL; + server_response_read_ctx_ = NULL; + cluster_resource_create_ctx_ = NULL; + partition_location_lookup_ctx_ = NULL; + do_observer_open_ctx_ = NULL; + client_response_write_ctx_ = NULL; + server_request_write_ctx_ = NULL; + } + + DECLARE_TO_STRING; + +public: + bool is_inited_; // is init or not + int64_t proxy_root_span_begin_time_; // us + + // all ctx pointers here are managed by logic, the real memory is in OBTRACE buffer + // proxy root + ObSpanCtx *proxy_root_span_ctx_; + + // another span ids + // it is recommend to use FLT_BEGIN_SPAN, FLT_END_CURRENT_SPAN() without span id arg + // it is more efficient, but the sequence should be same + ObSpanCtx *server_process_req_ctx_; + ObSpanCtx *server_response_read_ctx_; + ObSpanCtx *cluster_resource_create_ctx_; + ObSpanCtx *partition_location_lookup_ctx_; + ObSpanCtx *do_observer_open_ctx_; + ObSpanCtx *client_response_write_ctx_; + ObSpanCtx *server_request_write_ctx_; + +private: + DISALLOW_COPY_AND_ASSIGN(FLTTraceLogInfo); +}; + +struct FLTObjManage { +public: + FLTObjManage() {} + ~FLTObjManage() {} + + int deserialize(const char *buf, const int64_t len, int64_t &pos); // deserialize from full_trc string + int get_extra_info_ref_by_type(FullLinkTraceExtraInfoType type, FLTExtraInfo *&extra); + + void reset(); + + TO_STRING_KV(K_(span_info), K_(control_info), K_(query_info), K_(app_info), + K_(driver_span_info), K_(trace_log_info)); + +public: + FLTSpanInfo span_info_; // trace manage, client->proxy, proxy generate span_id ->server + FLTControlInfo control_info_; // server->proxy->client + FLTQueryInfo query_info_; // server->proxy, proxy print + FLTAppInfo app_info_; + FLTDriverSpanInfo driver_span_info_; // client->proxy, proxy print; need operator= or print immediately + + FLTTraceLogInfo trace_log_info_; // full link trace info + +private: + DISALLOW_COPY_AND_ASSIGN(FLTObjManage); +}; + +} // oommon + +} // oceanbase + +#endif + diff --git a/src/lib/utility/ob_2_0_full_link_trace_util.cpp b/src/lib/utility/ob_2_0_full_link_trace_util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e770829a2ee78a5609d5ac3de31b6cf026ee9cfd --- /dev/null +++ b/src/lib/utility/ob_2_0_full_link_trace_util.cpp @@ -0,0 +1,450 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ +#define USING_LOG_PREFIX PROXY + +#include "lib/utility/ob_2_0_full_link_trace_util.h" +#include "rpc/obmysql/ob_mysql_util.h" +#include "lib/oblog/ob_log.h" + + +namespace oceanbase +{ + +namespace common +{ + +int Ob20FullLinkTraceTransUtil::store_type_and_len(char *buf, int64_t len, int64_t &pos, int16_t type, int32_t v_len) +{ + int ret = OB_SUCCESS; + + if (OB_ISNULL(buf)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid input", K(ret)); + } else if (len < pos + FLT_TYPE_AND_LEN) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("size overflow", K(ret), K(len), K(pos)); + } else if (OB_FAIL(obmysql::ObMySQLUtil::store_int2(buf, len, type, pos))){ + LOG_WARN("failed to store type", K(ret), K(type), K(buf), K(len)); + } else if (OB_FAIL(obmysql::ObMySQLUtil::store_int4(buf, len, v_len, pos))) { + LOG_WARN("failed to store v_len", K(ret), K(buf)); + } else { + // do nothing + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::store_str(char *buf, int64_t len, int64_t &pos, const char *str, + const int32_t str_len, int16_t type) +{ + int ret = OB_SUCCESS; + + if (len < pos + str_len + FLT_TYPE_AND_LEN) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("size overflow", K(ret), K(len), K(pos), K(str_len)); + } else if (OB_FAIL(store_type_and_len(buf, len, pos, type, str_len))) { + LOG_WARN("fail to store type and len", K(ret)); + } else { + MEMCPY(buf + pos, str, str_len); + pos += str_len; + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::store_int1(char *buf, int64_t len, int64_t &pos, int8_t v, int16_t type) +{ + int ret = OB_SUCCESS; + + int32_t v_len = 1; + if (len < pos + FLT_TYPE_AND_LEN + v_len) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("size overflow", K(ret), K(len), K(pos)); + } else if (OB_FAIL(store_type_and_len(buf, len, pos, type, v_len))) { + LOG_WARN("failed to store type and len", K(v), K(buf), K(len)); + } else if (OB_FAIL(obmysql::ObMySQLUtil::store_int1(buf, len, v, pos))) { + LOG_WARN("failed to store int1", K(ret), K(buf)); + } else { + // do nothing + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::store_int2(char *buf, int64_t len, int64_t &pos, int16_t v, int16_t type) +{ + int ret = OB_SUCCESS; + + int32_t v_len = 2; + if (len < pos + FLT_TYPE_AND_LEN + v_len) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("size overflow", K(ret), K(len), K(pos)); + } else if (OB_FAIL(store_type_and_len(buf, len, pos, type, v_len))) { + LOG_WARN("failed to store type", K(v), K(buf), K(len)); + } else if (OB_FAIL(obmysql::ObMySQLUtil::store_int2(buf, len, v, pos))) { + LOG_WARN("failed to store int2", K(ret), K(buf)); + } else { + // do nothing + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::store_int3(char *buf, int64_t len, int64_t &pos, int32_t v, int16_t type) +{ + int ret = OB_SUCCESS; + + int32_t v_len = 3; + if (len < pos + FLT_TYPE_AND_LEN + v_len) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("size overflow", K(ret), K(len), K(pos)); + } else if (OB_FAIL(store_type_and_len(buf, len, pos, type, v_len))) { + LOG_WARN("failed to store type", K(v), K(buf), K(len)); + } else if (OB_FAIL(obmysql::ObMySQLUtil::store_int3(buf, len, v, pos))) { + LOG_WARN("failed to store int3", K(ret), K(buf)); + } else { + // do nothing + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::store_int4(char *buf, int64_t len, int64_t &pos, int32_t v, int16_t type) +{ + int ret = OB_SUCCESS; + + int32_t v_len = 4; + if (len < pos + FLT_TYPE_AND_LEN + v_len) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("size overflow", K(ret), K(len), K(pos)); + } else if (OB_FAIL(store_type_and_len(buf, len, pos, type, v_len))) { + LOG_WARN("failed to store type", K(v), K(buf), K(len)); + } else if (OB_FAIL(obmysql::ObMySQLUtil::store_int4(buf, len, v, pos))) { + LOG_WARN("failed to store int4", K(ret), K(buf)); + } else { + // do nothing + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::store_int5(char *buf, int64_t len, int64_t &pos, int64_t v, int16_t type) +{ + int ret = OB_SUCCESS; + + int32_t v_len = 5; + if (len < pos + FLT_TYPE_AND_LEN + v_len) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("size overflow", K(ret), K(len), K(pos)); + } else if (OB_FAIL(store_type_and_len(buf, len, pos, type, v_len))) { + LOG_WARN("failed to store type", K(v), K(buf), K(len)); + } else if (OB_FAIL(obmysql::ObMySQLUtil::store_int5(buf, len, v, pos))) { + LOG_WARN("failed to store int5", K(ret), K(buf)); + } else { + // do nothing + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::store_int6(char *buf, int64_t len, int64_t &pos, int64_t v, int16_t type) +{ + int ret = OB_SUCCESS; + + int32_t v_len = 6; + if (len < pos + FLT_TYPE_AND_LEN + v_len) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("size overflow", K(ret), K(len), K(pos)); + } else if (OB_FAIL(store_type_and_len(buf, len, pos, type, v_len))) { + LOG_WARN("failed to store type", K(v), K(buf), K(len)); + } else if (OB_FAIL(obmysql::ObMySQLUtil::store_int6(buf, len, v, pos))) { + LOG_WARN("failed to store int6", K(ret), K(buf)); + } else { + // do nothing + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::store_int8(char *buf, int64_t len, int64_t &pos, int64_t v, int16_t type) +{ + int ret = OB_SUCCESS; + + int32_t v_len = 8; + if (len < pos + FLT_TYPE_AND_LEN + v_len) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("size overflow", K(ret), K(len), K(pos)); + } else if (OB_FAIL(store_type_and_len(buf, len, pos, type, v_len))) { + LOG_WARN("failed to store type", K(v), K(buf), K(len)); + } else if (OB_FAIL(obmysql::ObMySQLUtil::store_int8(buf, len, v, pos))) { + LOG_WARN("failed to store int8", K(ret), K(buf)); + } else { + // do nothing + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::store_double(char *buf, const int64_t len, int64_t &pos, double val, int16_t type) +{ + int ret = OB_SUCCESS; + + int32_t v_len = sizeof(double); + if (len < pos + FLT_TYPE_AND_LEN + v_len) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("size overflow", K(ret), K(len), K(pos), K(v_len)); + } else if (OB_FAIL(store_type_and_len(buf, len, pos, type, v_len))) { + LOG_WARN("failed to store type", K(type), K(buf), K(len)); + } else { + MEMCPY(buf + pos, &val, v_len); + pos += v_len; + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::store_float(char *buf, const int64_t len, int64_t &pos, float val, int16_t type) +{ + int ret = OB_SUCCESS; + + int32_t v_len = sizeof(float); + if (len < pos + FLT_TYPE_AND_LEN + v_len) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("size overflow", K(ret), K(len), K(pos), K(v_len)); + } else if (OB_FAIL(store_type_and_len(buf, len, pos, type, v_len))) { + LOG_WARN("failed to store type", K(type), K(buf), K(len)); + } else { + MEMCPY(buf + pos, &val, v_len); + pos += v_len; + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::store_uuid(char *buf, const int64_t len, int64_t &pos, trace::UUID uuid, int16_t type) +{ + int ret = OB_SUCCESS; + + int32_t v_len = static_cast(uuid.get_serialize_size()); + if (len < pos + FLT_TYPE_AND_LEN + v_len) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("size overflow", K(ret), K(len), K(pos)); + } else if (OB_FAIL(store_type_and_len(buf, len, pos, type, v_len))) { + LOG_WARN("fail to store type", K(ret)); + } else if (OB_FAIL(uuid.serialize(buf, len, pos))) { + LOG_WARN("fail to serialize UUID", K(ret)); + } else { + //nothing + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::resolve_type_and_len(const char *buf, + int64_t len, + int64_t &pos, + int16_t &type, + int32_t &v_len) +{ + int ret = OB_SUCCESS; + + if (OB_ISNULL(buf)){ + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(ret)); + } else if (len < pos + FLT_TYPE_AND_LEN) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("size overflow", K(ret), K(pos), K(len)); + } else { + const char *tmp_buf = buf + pos; + obmysql::ObMySQLUtil::get_int2(tmp_buf, type); + pos += 2; + obmysql::ObMySQLUtil::get_int4(tmp_buf, v_len); + pos += 4; + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::get_str(const char *buf, int64_t len, int64_t &pos, int64_t str_len, char *&str) +{ + int ret = OB_SUCCESS; + + if (pos + str_len > len) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("size overflow", K(ret), K(pos), K(str_len), K(len)); + } else { + str = (char *)(buf + pos); + pos += str_len; + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::get_int1(const char *buf, int64_t len, int64_t &pos, int64_t v_len, int8_t &val) +{ + int ret = OB_SUCCESS; + + if (pos + v_len > len || v_len != 1) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid input", K(ret), K(pos), K(v_len), K(len)); + } else { + const char *data = buf + pos; + obmysql::ObMySQLUtil::get_int1(data, val); + pos += 1; + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::get_int2(const char *buf, int64_t len, int64_t &pos, int64_t v_len, int16_t &val) +{ + int ret = OB_SUCCESS; + + if (pos + v_len > len || v_len != 2) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid input", K(ret), K(pos), K(v_len), K(len)); + } else { + const char *data = buf + pos; + obmysql::ObMySQLUtil::get_int2(data, val); + pos += 2; + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::get_int3(const char *buf, int64_t len, int64_t &pos, int64_t v_len, int32_t &val) +{ + int ret = OB_SUCCESS; + + if (pos + v_len > len || v_len != 3) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid input", K(ret), K(pos), K(v_len), K(len)); + } else { + const char *data = buf + pos; + obmysql::ObMySQLUtil::get_int3(data, val); + pos += 3; + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::get_int4(const char *buf, int64_t len, int64_t &pos, int64_t v_len, int32_t &val) +{ + int ret = OB_SUCCESS; + + if (pos + v_len > len || v_len != 4) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid input", K(ret), K(pos), K(v_len), K(len)); + } else { + const char *data = buf + pos; + obmysql::ObMySQLUtil::get_int4(data, val); + pos += 4; + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::get_int8(const char *buf, int64_t len, int64_t &pos, int64_t v_len, int64_t &val) +{ + int ret = OB_SUCCESS; + + if (pos + v_len > len || v_len != 8) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid input", K(ret), K(pos), K(v_len), K(len)); + } else { + const char *data = buf + pos; + obmysql::ObMySQLUtil::get_int8(data, val); + pos += 8; + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::get_double(const char *buf, int64_t len, int64_t &pos, int64_t v_len, double &val) +{ + int ret = OB_SUCCESS; + + int64_t d_len = sizeof(double); + if (pos + v_len > len || v_len != d_len) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid input", K(pos), K(v_len), K(len), K(d_len)); + } else { + val = (*((double *)(buf + pos))); + pos += d_len; + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::get_float(const char *buf, int64_t len, int64_t &pos, int64_t v_len, float &val) +{ + int ret = OB_SUCCESS; + + int64_t f_len = sizeof(float); + if (pos + v_len > len || v_len != f_len) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid input", K(pos), K(v_len), K(len), K(f_len)); + } else { + val = (*((float *)(buf + pos))); + pos += f_len; + } + + return ret; +} + +int Ob20FullLinkTraceTransUtil::get_uuid(const char *buf, int64_t len, int64_t &pos, int64_t v_len, trace::UUID &uuid) +{ + int ret = OB_SUCCESS; + + int64_t uuid_len = sizeof(trace::UUID); + if (pos + v_len > len || v_len != uuid_len) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid input", K(ret), K(pos), K(v_len), K(len), K(uuid_len)); + } else if (OB_FAIL(uuid.deserialize(buf, len, pos))) { + LOG_WARN("fail to deserialize uuid", K(ret)); + } else { + //nothing + } + + return ret; +} + +// total size +int64_t Ob20FullLinkTraceTransUtil::get_serialize_size(int64_t seri_size) +{ + return FLT_TYPE_AND_LEN + seri_size; +} + +int Ob20FullLinkTraceTransUtil::resolve_type(const char *buf, int64_t len, int64_t &pos, int16_t &type) +{ + int ret = OB_SUCCESS; + + if (OB_ISNULL(buf)){ + ret = OB_INVALID_ARGUMENT; + LOG_WARN("Invalid argument, null buf ptr."); + } else if (pos + 2 > len) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("Failed to check pos len", K(pos), K(len)); + } else { + const char *data_type = buf + pos; + obmysql::ObMySQLUtil::get_int2(data_type, type); + pos += 2; + } + + return ret; +} + + +} // common + +} // oceanbase + diff --git a/src/lib/utility/ob_2_0_full_link_trace_util.h b/src/lib/utility/ob_2_0_full_link_trace_util.h new file mode 100644 index 0000000000000000000000000000000000000000..9515cb5b366d1064920435b00ae395885c109f8a --- /dev/null +++ b/src/lib/utility/ob_2_0_full_link_trace_util.h @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef _OBPROXY_OB_2_0_FULL_LINK_TRACE_UTIL_H_ +#define _OBPROXY_OB_2_0_FULL_LINK_TRACE_UTIL_H_ + +#include "lib/trace/ob_trace.h" + +namespace oceanbase +{ + +namespace common +{ + +/* + * serialize or deserialize the buf as full link trace format in ob20 protocol payload + * buf stored in extra info in ob20 payload data + * format: + * key: "full_trc" + * value: "[type1][len1] + [key_id1][v_len1][value1] + [key_id2][v_len2][value2] + ... + [type2][len2] + [key_id3][v_len3][value3] + [key_id4][v_len4][value4] + ..." + * byte size: type(2byte), len(4byte), key_id(2byte), v_len(4byte), value(accord to v_len) + * attention: + 1: each type+len define the range of data it covered, check the boundary by len + 2: there could be more than one type+len in each ob20 payload data + 3: the key_id is defined previously, which is the same for client & proxy & server + * + */ + +#define FLT_TYPE_LEN 2 +#define FLT_TOTAL_LEN 4 +#define FLT_TYPE_AND_LEN (FLT_TYPE_LEN + FLT_TOTAL_LEN) + +class Ob20FullLinkTraceTransUtil +{ +public: + // save type+len + static int store_type_and_len(char *buf, int64_t len, int64_t &pos, int16_t type, int32_t v_len); + static int store_str(char *buf, int64_t len, int64_t &pos, const char *str, const int32_t str_len, int16_t type); + + // serialize data + static int store_int1(char *buf, int64_t len, int64_t &pos, int8_t v, int16_t type); + static int store_int2(char *buf, int64_t len, int64_t &pos, int16_t v, int16_t type); + static int store_int3(char *buf, int64_t len, int64_t &pos, int32_t v, int16_t type); + static int store_int4(char *buf, int64_t len, int64_t &pos, int32_t v, int16_t type); + static int store_int5(char *buf, int64_t len, int64_t &pos, int64_t v, int16_t type); + static int store_int6(char *buf, int64_t len, int64_t &pos, int64_t v, int16_t type); + static int store_int8(char *buf, int64_t len, int64_t &pos, int64_t v, int16_t type); + + static int store_double(char *buf, const int64_t len, int64_t &pos, double val, int16_t type); + static int store_float(char *buf, const int64_t len, int64_t &pos, float val, int16_t type); + static int store_uuid(char *buf, const int64_t len, int64_t &pos, trace::UUID uuid, int16_t type); + + // decode type+len + static int resolve_type_and_len(const char *buf, int64_t len, int64_t &pos, int16_t &type, int32_t &v_len); + static int get_str(const char *buf, int64_t len, int64_t &pos, int64_t str_len, char *&str); + + // deserialize data + static int get_int1(const char *buf, int64_t len, int64_t &pos, int64_t v_len, int8_t &val); + static int get_int2(const char *buf, int64_t len, int64_t &pos, int64_t v_len, int16_t &val); + static int get_int3(const char *buf, int64_t len, int64_t &pos, int64_t v_len, int32_t &val); + static int get_int4(const char *buf, int64_t len, int64_t &pos, int64_t v_len, int32_t &val); + static int get_int8(const char *buf, int64_t len, int64_t &pos, int64_t v_len, int64_t &val); + + static int get_double(const char *buf, int64_t len, int64_t &pos, int64_t v_len, double &val); + static int get_float(const char *buf, int64_t len, int64_t &pos, int64_t v_len, float &val); + static int get_uuid(const char *buf, int64_t len, int64_t &pos, int64_t v_len, trace::UUID &uuid); + + // total size + static int64_t get_serialize_size(int64_t seri_size); + + // resolve new extra info protocol, extra id(type) + static int resolve_type(const char *buf, int64_t len, int64_t &pos, int16_t &type); + +private: + DISALLOW_COPY_AND_ASSIGN(Ob20FullLinkTraceTransUtil); +}; + + +} // common + +} // oceanbase + +#endif // _OBPROXY_OB_2_0_FULL_LINK_TRACE_UTIL_H_ + diff --git a/src/lib/utility/ob_macro_utils.h b/src/lib/utility/ob_macro_utils.h index e08161d0fff5d0db419b740cc01be9860d3a9e78..e36395f2c16a83388937acbd9814aa1348401074 100644 --- a/src/lib/utility/ob_macro_utils.h +++ b/src/lib/utility/ob_macro_utils.h @@ -556,6 +556,8 @@ for (__typeof__((c).at(0)) *it = ((c).count() > 0 ? &(c).at(0) : NULL), *__INNER #define IS_NOT_INIT (OB_UNLIKELY(!is_inited_)) #define IS_INIT (OB_LIKELY(is_inited_)) +#define IS_CLUSTER_VERSION_LESS_THAN_V4(version) (version < 4) + #define RETRY_FUNC(stop_flag, var, func, args...) \ do {\ if (OB_SUCC(ret)) \ diff --git a/src/lib/utility/utility.h b/src/lib/utility/utility.h index dc0a3214696937bee1dd53a541fe316d374ec239..a900f433a301e4da9ccf613f695fc72b91619e7c 100644 --- a/src/lib/utility/utility.h +++ b/src/lib/utility/utility.h @@ -27,6 +27,7 @@ #include "lib/container/ob_iarray.h" #define FALSE_IT(stmt) ({ (stmt); false; }) +#define OB_FALSE_IT(stmt) ({ (stmt); false; }) #define CPUID_STD_SSE4_2 0x00100000 diff --git a/src/obproxy/Makemodule.am b/src/obproxy/Makemodule.am index df2de637cb227d566b19745ffea6ee9f05c805c4..4a08e92adddad03b50a63df7d315218eed9c9a41 100644 --- a/src/obproxy/Makemodule.am +++ b/src/obproxy/Makemodule.am @@ -10,7 +10,11 @@ AM_CPPFLAGS += -I${top_srcdir}/src/obproxy\ obproxy_libobproxy_la_LIBADD := dbconfig/libdbconfig.la lib/regex/regex/libregex.la prometheus/libprometheus_exporter.la noinst_LTLIBRARIES += obproxy/libobproxy.la -bin_PROGRAMS += obproxy/obproxy +if HAVE_SO + lib_LTLIBRARIES += obproxy/libobproxy_so.la +else + bin_PROGRAMS += obproxy/obproxy +endif include obproxy/iocore/eventsystem/Makemodule.am include obproxy/iocore/net/Makemodule.am @@ -30,6 +34,7 @@ include obproxy/opsql/Makemodule.am include obproxy/packet/Makemodule.am include obproxy/dbconfig/Makemodule.am include obproxy/engine/Makemodule.am +include obproxy/driver/c/Makemodule.am include obproxy/optimizer/Makemodule.am include obproxy/executor/Makemodule.am include obproxy/qos/Makemodule.am @@ -41,6 +46,9 @@ pub_source = \ obproxy/ob_proxy_main.cpp \ obproxy/ob_proxy.h \ obproxy/ob_proxy.cpp +init_so_source =\ + obproxy/ob_proxy_init.h\ + obproxy/ob_proxy_init.cpp obproxy_sources :=\ ${iocore_eventsystem_sources}\ @@ -51,6 +59,7 @@ ${proxy_api_sources}\ ${proxy_plugins_sources}\ ${proxy_mysqllib_sources}\ ${proxy_mysql_client_sources}\ +${obproxy_c_driver_sources}\ ${proxy_mysql_route_sources}\ ${proxy_mysql_shard_sources}\ ${obutils_sources}\ @@ -70,6 +79,8 @@ ${obproxy_executor_sources}\ ${obproxy_optimizer_sources}\ ${obproxy_engine_sources}\ ${qos_sources}\ +${init_so_source}\ +${pub_source}\ ${omt_sources} obproxy_libobproxy_la_SOURCES :=\ @@ -80,8 +91,15 @@ ${rpc_obmysql_packet_sources} ${obproxy_rpc_obmysql_sources} ${rpc_common_source ${obproxy_sql_sources}\ ${obproxy_sources} +if HAVE_SO + obproxy_libobproxy_so_la_SOURCES := + obproxy_libobproxy_so_la_LIBADD := obproxy/libobproxy.la lib/compress/libzlib_1.0.la lib/compress/libzstd_1.3.8.la ${BIN_LDFLAGS} ${DEP_DIR}/lib64/libprometheus-cpp-pull.a ${DEP_DIR}/lib64/libprometheus-cpp-core.a ${RUNTIME_DIR}/lib/libob_sql_proxy_parser_static.a ${DEP_DIR}/lib/libssl.a ${DEP_DIR}/lib/libcrypto.a -lpthread + + obproxy_libobproxy_so_la_LDFLAGS :=${AM_LDFLAGS} ${DEP_DIR}/lib/libgrpc++.a -lpthread -lc -lm -lrt ${DEP_DIR}/lib/libcurl.a -ldl -L${DEP_DIR}/lib -llber ${DEP_DIR}/lib/sqlite/libsqlite3.a ${DEP_DIR}/lib/libgrpc_cronet.a ${DEP_DIR}/lib/libgrpc++_cronet.a -shared ${DEP_DIR}/lib64/libprotobuf.a -fPIC +endif + nodist_obproxy_libobproxy_la_SOURCES = build_version.c -obproxy_obproxy_SOURCES := obproxy/main.cpp ${pub_source} +obproxy_obproxy_SOURCES := obproxy/main.cpp obproxy_obproxy_LDADD_BASE := obproxy/libobproxy.la lib/compress/libzlib_1.0.la lib/compress/libzstd_1.3.8.la ${BIN_LDFLAGS} ${DEP_DIR}/lib64/libprotobuf.a ${DEP_DIR}/lib/libgrpc.a ${DEP_DIR}/lib/libgrpc++.a ${DEP_DIR}/lib/libgrpc_unsecure.a ${DEP_DIR}/lib/libgrpc++_unsecure.a ${DEP_DIR}/lib/libgrpc++_reflection.a ${DEP_DIR}/lib/libgrpcpp_channelz.a ${DEP_DIR}/lib/libgrpc++_error_details.a ${DEP_DIR}/lib/libgrpc_cronet.a ${DEP_DIR}/lib/libgrpc++_cronet.a ${DEP_DIR}/lib/libgpr.a ${DEP_DIR}/lib/libaddress_sorting.a ${DEP_DIR}/lib/libcares.a ${DEP_DIR}/lib64/libprometheus-cpp-pull.a ${DEP_DIR}/lib64/libprometheus-cpp-core.a ${RUNTIME_DIR}/lib/libob_sql_proxy_parser_static.a ${DEP_DIR}/lib/libssl.a ${DEP_DIR}/lib/libcrypto.a -lpthread ${DEP_DIR}/lib/libcurl.a ${DEP_DIR}/lib/libcrypto.a ${DEP_DIR}/lib/sqlite/libsqlite3.a obproxy_obproxy_LDFLAGS :=${AM_LDFLAGS} -lpthread -lc -lm -lrt -ldl -L${DEP_DIR}/lib diff --git a/src/obproxy/cmd/Makemodule.am b/src/obproxy/cmd/Makemodule.am index 29c172e408a37fe867cec76c6f3a8ff9f056ffcd..a5f18aacdf385b44694328e82131c1e3d3c00d80 100644 --- a/src/obproxy/cmd/Makemodule.am +++ b/src/obproxy/cmd/Makemodule.am @@ -60,4 +60,6 @@ obproxy/cmd/ob_show_topology_handler.cpp\ obproxy/cmd/ob_sequence_info_handler.h\ obproxy/cmd/ob_sequence_info_handler.cpp\ obproxy/cmd/ob_show_db_version_handler.h\ -obproxy/cmd/ob_show_db_version_handler.cpp +obproxy/cmd/ob_show_db_version_handler.cpp\ +obproxy/cmd/ob_show_table_status_handler.h\ +obproxy/cmd/ob_show_table_status_handler.cpp diff --git a/src/obproxy/cmd/ob_alter_config_handler.cpp b/src/obproxy/cmd/ob_alter_config_handler.cpp index 5181bcdbde57da3d4a20addeac53c22da447929a..983f16cb4eb130b6fcaee91a83992dced21b56ab 100644 --- a/src/obproxy/cmd/ob_alter_config_handler.cpp +++ b/src/obproxy/cmd/ob_alter_config_handler.cpp @@ -33,8 +33,7 @@ namespace obproxy { namespace obutils { -ObAlterConfigSetHandler::ObAlterConfigSetHandler(ObContinuation *cont, ObMIOBuffer *buf, - const ObInternalCmdInfo &info) +ObAlterConfigSetHandler::ObAlterConfigSetHandler(ObContinuation *cont, ObMIOBuffer *buf, const ObInternalCmdInfo &info) : ObInternalCmdHandler(cont, buf, info), capability_(info.get_capability()) { SET_HANDLER(&ObAlterConfigSetHandler::handle_set_config); @@ -130,14 +129,10 @@ int ObAlterConfigSetHandler::handle_set_config(int event, void *data) } } - // If it is an ssl switch, it needs to be synchronized to ssl_config_table for compatibility - if (OB_SUCC(ret)) { - if (0 == key_string.case_compare("enable_client_ssl") - || 0 == key_string.case_compare("enable_server_ssl")) { - if (OB_FAIL(get_global_config_processor().store_cloud_config("ssl_config", "*", "*", key_string, value_string))) { - LOG_WARN("store cloud ssl config failed", K(ret)); - } - } + // Global configuration items need to be synchronized to the proxy_config table + if (OB_SUCC(ret) && + OB_FAIL(get_global_config_processor().store_global_proxy_config(key_string, value_string))) { + LOG_WARN("store proxy config failed", K(ret)); } //5. rollback @@ -147,6 +142,9 @@ int ObAlterConfigSetHandler::handle_set_config(int event, void *data) if (OB_UNLIKELY(OB_SUCCESS != (tmp_ret = get_global_proxy_config().update_config_item( key_string, ObString::make_string(old_value))))) { WARN_ICMD("fail to back to old config", K(key_string), K(old_value), K(tmp_ret)); + } else if (OB_UNLIKELY(OB_SUCCESS != (tmp_ret = + get_global_config_processor().store_global_proxy_config(key_string, old_value)))) { + WARN_ICMD("fail to store global proxy config", K(key_string), K(old_value), K(tmp_ret)); } else { DEBUG_ICMD("succ to back to old config", K(key_string), K(old_value)); } diff --git a/src/obproxy/cmd/ob_alter_config_handler.h b/src/obproxy/cmd/ob_alter_config_handler.h index cb6012e9b6dda5351bccb9e6d211b92d476598f4..726b2065157b461b886d7daa96028ffd6f5a26d8 100644 --- a/src/obproxy/cmd/ob_alter_config_handler.h +++ b/src/obproxy/cmd/ob_alter_config_handler.h @@ -25,8 +25,7 @@ namespace obutils class ObAlterConfigSetHandler : public ObInternalCmdHandler { public: - ObAlterConfigSetHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObAlterConfigSetHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObAlterConfigSetHandler() {} int handle_set_config(int event, void *data); diff --git a/src/obproxy/cmd/ob_alter_resource_handler.cpp b/src/obproxy/cmd/ob_alter_resource_handler.cpp index 25c36c65532acde449b93c1886e5f022d944e69d..f6ac0f38369a903c8944dead076e57741bedac1f 100644 --- a/src/obproxy/cmd/ob_alter_resource_handler.cpp +++ b/src/obproxy/cmd/ob_alter_resource_handler.cpp @@ -28,8 +28,7 @@ namespace obproxy { namespace obutils { -ObAlterResourceHandler::ObAlterResourceHandler(ObContinuation *cont, ObMIOBuffer *buf, - const ObInternalCmdInfo &info) +ObAlterResourceHandler::ObAlterResourceHandler(ObContinuation *cont, ObMIOBuffer *buf, const ObInternalCmdInfo &info) : ObInternalCmdHandler(cont, buf, info), capability_(info.get_capability()) { SET_HANDLER(&ObAlterResourceHandler::handle_delete_cluster); diff --git a/src/obproxy/cmd/ob_alter_resource_handler.h b/src/obproxy/cmd/ob_alter_resource_handler.h index 373c7719494035e7ed1d81829f54d86b50e17ec9..444b72afdfbcc11cbcfeff67a69684d7f7d36492 100644 --- a/src/obproxy/cmd/ob_alter_resource_handler.h +++ b/src/obproxy/cmd/ob_alter_resource_handler.h @@ -25,8 +25,7 @@ namespace obutils class ObAlterResourceHandler : public ObInternalCmdHandler { public: - ObAlterResourceHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObAlterResourceHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObAlterResourceHandler() {} int handle_delete_cluster(int event, void *data); diff --git a/src/obproxy/cmd/ob_cmd_handler.cpp b/src/obproxy/cmd/ob_cmd_handler.cpp index e7028c4b97d8569658f10bed0d6dccdb2ab7bd7a..39e1350567801c57c1d478bdc1fd97d9d86ba52c 100644 --- a/src/obproxy/cmd/ob_cmd_handler.cpp +++ b/src/obproxy/cmd/ob_cmd_handler.cpp @@ -13,36 +13,30 @@ #define USING_LOG_PREFIX PROXY_CMD #include "cmd/ob_cmd_handler.h" #include "rpc/obmysql/ob_mysql_global.h" +#include "obproxy/proxy/mysqllib/ob_2_0_protocol_utils.h" using namespace oceanbase::obproxy::event; using namespace oceanbase::obmysql; +using namespace oceanbase::obproxy::proxy; namespace oceanbase { namespace obproxy { -ObCmdHandler::ObCmdHandler(ObMIOBuffer *buf, uint8_t pkg_seq, int64_t memory_limit) +ObCmdHandler::ObCmdHandler(ObMIOBuffer *buf, ObCmdInfo &info) : external_buf_(buf), - internal_buf_(NULL), internal_reader_(NULL), internal_buf_limited_(memory_limit), - is_inited_(false), header_encoded_(false), - seq_(pkg_seq), original_seq_(seq_) + internal_buf_(NULL), internal_reader_(NULL), internal_buf_limited_(info.get_memory_limit()), + protocol_(info.get_protocol()), ob20_param_(info.get_ob20_param()), is_inited_(false), header_encoded_(false), + seq_(info.get_seq()), original_seq_(info.get_seq()) { } ObCmdHandler::~ObCmdHandler() { is_inited_ = false; - if (OB_LIKELY(NULL != internal_reader_)) { - int ret = OB_SUCCESS; - if (OB_FAIL(internal_reader_->consume(internal_reader_->read_avail()))) { - WARN_CMD("fail to consume ", K(ret)); - } - internal_reader_ = NULL; - } - if (OB_LIKELY(NULL != internal_buf_)) { - free_miobuffer(internal_buf_); - internal_buf_ = NULL; - } + destroy_internal_buf(); + protocol_ = ObProxyProtocol::PROTOCOL_NORMAL; + ob20_param_.reset(); } int ObCmdHandler::init(const bool is_query_cmd/*true*/) @@ -94,10 +88,27 @@ int ObCmdHandler::reset() } else { internal_buf_->reset(); seq_ = original_seq_; + // could not reset protocol and ob20 param, cause we need fill external buf according to protocol } return ret; } +void ObCmdHandler::destroy_internal_buf() +{ + if (OB_LIKELY(NULL != internal_reader_)) { + int ret = OB_SUCCESS; + if (OB_FAIL(internal_reader_->consume(internal_reader_->read_avail()))) { + WARN_CMD("fail to consume ", K(ret)); + } + internal_reader_ = NULL; + } + + if (OB_LIKELY(NULL != internal_buf_)) { + free_miobuffer(internal_buf_); + internal_buf_ = NULL; + } +} + int ObCmdHandler::encode_header(const ObString *cname, const EMySQLFieldType *ctype, const int64_t size) { int ret = OB_SUCCESS; @@ -130,6 +141,38 @@ int ObCmdHandler::encode_header(const ObString *cname, const EMySQLFieldType *ct return ret; } +int ObCmdHandler::encode_header(const ObProxyColumnSchema *column_schema, const int64_t size) +{ + int ret = OB_SUCCESS; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + WARN_ICMD("it has not inited", K(ret)); + } else if (OB_ISNULL(column_schema) || OB_UNLIKELY(size <= 0)) { + ret = OB_INVALID_ARGUMENT; + } else { + ObArray fields; + ObMySQLField field; + //TODO: ref the observer to_mysql_field(), make the encode better + field.charsetnr_ = ObCharset::get_default_collation(ObCharset::get_default_charset()); + for (int64_t i = 0; (OB_SUCC(ret) && i < size); ++i) { + field.cname_ = column_schema[i].cname_; + field.org_cname_ = column_schema[i].cname_; + field.type_ = column_schema[i].ctype_; + if (OB_FAIL(fields.push_back(field))) { + WARN_ICMD("fail to push field into array", K(field), K(ret)); + } + } + if (OB_SUCC(ret)) { + if (OB_FAIL(ObMysqlPacketUtil::encode_header(*internal_buf_, seq_, fields))) { + WARN_ICMD("fail to encode header", K(ret)); + } else { + DEBUG_ICMD("succ to encode header", K(fields)); + } + } + } + return ret; +} + int ObCmdHandler::encode_row_packet(const ObNewRow &row, const bool need_limit_size/*true*/) { int ret = OB_SUCCESS; @@ -165,36 +208,27 @@ int ObCmdHandler::encode_eof_packet() return ret; } +// write packet in mysql format to internal buf, then trans it to external buf as ob20/mysql int ObCmdHandler::encode_err_packet(const int errcode) { int ret = OB_SUCCESS; - const int32_t MAX_MSG_BUF_SIZE = 256; - char msg_buf[MAX_MSG_BUF_SIZE]; + if (IS_NOT_INIT) { ret = OB_NOT_INIT; WARN_CMD("it has not inited", K(ret)); - } else if (OB_FAIL(reset())) {//before encode_err_packet, we need clean buf + } else if (OB_FAIL(reset())) { // before encode err packet, we need clean buf WARN_CMD("fail to do reset", K(errcode), K(ret)); } else { - const char *errmsg = ob_strerror(errcode); - int32_t length = 0; - if (OB_ISNULL(errmsg)) { - length = snprintf(msg_buf, sizeof(msg_buf), "Unknown user error"); + char *err_msg = NULL; + if (OB_FAIL(packet::ObProxyPacketWriter::get_err_buf(errcode, err_msg))) { + WARN_CMD("fail to get err buf", K(ret)); + } else if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet(*internal_buf_, seq_, errcode, err_msg))) { + WARN_CMD("fail to encode err packet", K(errcode), K(err_msg), K(ret)); } else { - length = snprintf(msg_buf, sizeof(msg_buf), errmsg); - } - if (OB_UNLIKELY(length <= 0) || OB_UNLIKELY(length >= MAX_MSG_BUF_SIZE)) { - ret = OB_BUF_NOT_ENOUGH; - WARN_CMD("msg_buf is not enough", K(length), K(errmsg), K(ret)); - } else {} - } - if (OB_SUCC(ret)) { - if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet_buf(*internal_buf_, seq_, errcode, msg_buf))) { - WARN_CMD("fail to encode err packet", K(errcode), K(msg_buf), K(ret)); - } else { - INFO_CMD("succ to encode err packet", K(errcode), K(msg_buf)); + INFO_CMD("succ to encode err packet", K(errcode), K(err_msg)); } } + return ret; } @@ -213,22 +247,49 @@ int ObCmdHandler::encode_ok_packet(const int64_t affected_rows, return ret; } +bool ObCmdHandler::match_like(const ObString &str_text, const ObString &str_pattern) const +{ + bool ret = false; + if (str_pattern.empty()) { + ret = true; + } else if (str_text.empty()) { + //return false if text config namme is NULL + } else { + ret = ObCharset::wildcmp(CS_TYPE_UTF8MB4_BIN, str_text, str_pattern, 0, '_', '%'); + } + return ret; +} + int ObCmdHandler::fill_external_buf() { int ret = OB_SUCCESS; - int64_t data_size = internal_reader_->read_avail(); - int64_t bytes_written = 0; - if (OB_FAIL(external_buf_->remove_append(internal_reader_, bytes_written))) { - ERROR_CMD("Error while remove_append to external_buf_!", "Attempted size", data_size, - "wrote size", bytes_written, K(ret)); - } else if (OB_UNLIKELY(bytes_written != data_size)) { - ret = OB_ERR_UNEXPECTED; - WARN_CMD("unexpected result", "Attempted size", data_size, - "wrote size", bytes_written, K(ret)); + + if (OB_LIKELY(protocol_ == ObProxyProtocol::PROTOCOL_OB20)) { + if (OB_FAIL(ObProto20Utils::consume_and_compress_data(internal_reader_, external_buf_, + internal_reader_->read_avail(), ob20_param_))) { + WARN_ICMD("fail to consume and compress to ob20 packet", K(ret), K_(ob20_param)); + } else { + DEBUG_ICMD("succ to write to client in ob20", K_(ob20_param)); + } + } else if (protocol_ == ObProxyProtocol::PROTOCOL_NORMAL) { + // mysql + int64_t data_size = internal_reader_->read_avail(); + int64_t bytes_written = 0; + if (OB_FAIL(external_buf_->remove_append(internal_reader_, bytes_written))) { + ERROR_CMD("Error while remove_append to external_buf_!", "Attempted size", data_size, + "wrote size", bytes_written, K(ret)); + } else if (OB_UNLIKELY(bytes_written != data_size)) { + ret = OB_ERR_UNEXPECTED; + WARN_CMD("unexpected result", "Attempted size", data_size, "wrote size", bytes_written, K(ret)); + } else { + internal_reader_ = NULL; + DEBUG_CMD("succ to write to client in mysql", "Attempted size", bytes_written); + } } else { - internal_reader_ = NULL; - DEBUG_CMD("succ to write to client", "Attempted size", bytes_written); + ret = OB_ERR_UNEXPECTED; + WARN_ICMD("unexpected protocol error", K(ret), K_(protocol)); } + return ret; } diff --git a/src/obproxy/cmd/ob_cmd_handler.h b/src/obproxy/cmd/ob_cmd_handler.h index e23b88e139ed7997c7581192392400c864004235..26e9eb815077911f1211e9635184336f56501590 100644 --- a/src/obproxy/cmd/ob_cmd_handler.h +++ b/src/obproxy/cmd/ob_cmd_handler.h @@ -16,6 +16,10 @@ #include "packet/ob_mysql_packet_util.h" #include "iocore/eventsystem/ob_io_buffer.h" #include "common/obsm_row.h" +#include "lib/oblog/ob_log_module.h" +#include "lib/utility/ob_print_utils.h" +#include "obproxy/packet/ob_proxy_packet_writer.h" +#include "cmd/ob_internal_cmd_handler.h" namespace oceanbase { @@ -27,19 +31,50 @@ namespace obproxy #define WARN_CMD(fmt...) PROXY_CMD_LOG(WARN, ##fmt) #define ERROR_CMD(fmt...) PROXY_CMD_LOG(ERROR, ##fmt) +class ObCmdInfo { +public: + ObCmdInfo() { reset(); } + ObCmdInfo(uint8_t seq, int64_t memory_limit, proxy::ObProxyProtocol protocol, + proxy::Ob20ProtocolHeaderParam &ob20_param) : + seq_(seq), memory_limit_(memory_limit), protocol_(protocol), ob20_param_(ob20_param) {} + ~ObCmdInfo () {} + + void reset() { + seq_ = 0; + memory_limit_ = 0; + protocol_ = proxy::ObProxyProtocol::PROTOCOL_NORMAL; + ob20_param_.reset(); + } + + uint8_t get_seq() const { return seq_; } + int64_t get_memory_limit() const { return memory_limit_; } + proxy::ObProxyProtocol get_protocol() const { return protocol_; } + proxy::Ob20ProtocolHeaderParam &get_ob20_param() { return ob20_param_; } + + TO_STRING_KV(K_(seq), K_(memory_limit), K_(protocol), K_(ob20_param)); + +private: + uint8_t seq_; + int64_t memory_limit_; + proxy::ObProxyProtocol protocol_; + proxy::Ob20ProtocolHeaderParam ob20_param_; +}; + class ObCmdHandler { public: - ObCmdHandler(event::ObMIOBuffer *buf, uint8_t pkg_seq, int64_t memory_limit); + ObCmdHandler(event::ObMIOBuffer *buf, ObCmdInfo &info); virtual ~ObCmdHandler(); int init(const bool is_query_cmd = true); int reset();//clean buf and reset seq + void destroy_internal_buf(); int fill_external_buf(); bool is_inited() const { return is_inited_; }; bool is_buf_empty() const { return original_seq_ == seq_; } protected: + int encode_header(const ObProxyColumnSchema *column_schema, const int64_t size); int encode_header(const common::ObString *cname, const obmysql::EMySQLFieldType *ctype, const int64_t size); int encode_row_packet(const common::ObNewRow &row, const bool need_limit_size = true); @@ -51,24 +86,34 @@ protected: int encode_err_packet(const int errcode, const T ¶m) { int ret = OB_SUCCESS; - if (IS_NOT_INIT) { + if (IS_NOT_INIT){ ret = OB_NOT_INIT; - WARN_CMD("it has not inited", K(ret)); - } else if (OB_FAIL(reset())) { //before encode_err_packet, we need clean buf - WARN_CMD("fail to do reset", K(errcode), K(ret)); - } else if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet(*internal_buf_, seq_, errcode, param))) { - WARN_CMD("fail to encode err packet", K(errcode), K(ret)); + WARN_ICMD("it has not inited", K(ret)); + } else if (OB_FAIL(reset())) { // before encode err packet, we need clean buf + WARN_ICMD("fail to do reset", K(errcode), K(ret)); } else { - INFO_CMD("succ to encode err packet", K(errcode)); + char *err_msg = NULL; + if (OB_FAIL(packet::ObProxyPacketWriter::get_user_err_buf(errcode, err_msg, param))) { + WARN_ICMD("fail to get user err buf", K(errcode), K(ret)); + } else if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet(*internal_buf_, seq_, errcode, err_msg))) { + WARN_ICMD("fail to encode err packet buf", K(errcode), K(ret)); + } else { + INFO_ICMD("succ to encode err packet", K(errcode)); + } } return ret; } + bool match_like(const ObString &str_text, const ObString &str_pattern) const; + protected: event::ObMIOBuffer *external_buf_; event::ObMIOBuffer *internal_buf_; event::ObIOBufferReader *internal_reader_; int64_t internal_buf_limited_; + + proxy::ObProxyProtocol protocol_; + proxy::Ob20ProtocolHeaderParam ob20_param_; bool is_inited_; bool header_encoded_; diff --git a/src/obproxy/cmd/ob_config_v2_handler.cpp b/src/obproxy/cmd/ob_config_v2_handler.cpp index e916b3d2070ea7ab313a1cdfc86f6dc12e522634..15de2736a104e3e4682f9c16df2cad9d52676615 100644 --- a/src/obproxy/cmd/ob_config_v2_handler.cpp +++ b/src/obproxy/cmd/ob_config_v2_handler.cpp @@ -44,8 +44,7 @@ namespace oceanbase namespace obproxy { -ObConfigV2Handler::ObConfigV2Handler(ObContinuation *cont, ObMIOBuffer *buf, - const ObInternalCmdInfo &info) +ObConfigV2Handler::ObConfigV2Handler(ObContinuation *cont, ObMIOBuffer *buf, const ObInternalCmdInfo &info) : ObInternalCmdHandler(cont, buf, info), sqlite3_column_name_(), sqlite3_column_value_(), cmd_type_(info.get_cmd_type()), capability_(info.get_capability()) @@ -69,8 +68,8 @@ int ObConfigV2Handler::main_handler(int event, void *data) event_ret = handle_dml_stmt(); break; default: - ret = OB_ERR_UNEXPECTED; - WARN_ICMD("unknown type", "cmd_type", get_print_stmt_name(cmd_type_)); + ret = OB_NOT_SUPPORTED; + WARN_ICMD("unknown type", "cmd_type", get_print_stmt_name(cmd_type_), K(ret)); event_ret = internal_error_callback(ret); } diff --git a/src/obproxy/cmd/ob_config_v2_handler.h b/src/obproxy/cmd/ob_config_v2_handler.h index 192e7898e01568e18dddfc58297b291c0557c36c..c45bedbdbd425177ab70dde03ae438f4e2ad69d3 100644 --- a/src/obproxy/cmd/ob_config_v2_handler.h +++ b/src/obproxy/cmd/ob_config_v2_handler.h @@ -47,10 +47,7 @@ namespace proxy class ObConfigV2Handler : public ObInternalCmdHandler { public: - ObConfigV2Handler(event::ObContinuation *cont, - event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); - + ObConfigV2Handler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); ~ObConfigV2Handler() {} int main_handler(int event, void *data); diff --git a/src/obproxy/cmd/ob_dds_config_handler.cpp b/src/obproxy/cmd/ob_dds_config_handler.cpp index 58cd32ca7a89287f9b5d76f53ea357599ab0c232..4bd3ceb93dcc61af98f1327ea0ab8b75b03f4207 100644 --- a/src/obproxy/cmd/ob_dds_config_handler.cpp +++ b/src/obproxy/cmd/ob_dds_config_handler.cpp @@ -85,8 +85,7 @@ private: }; static SessionMap session_map; -ObDdsConfigHandler::ObDdsConfigHandler(ObContinuation *cont, ObMIOBuffer *buf, - const ObInternalCmdInfo &info) +ObDdsConfigHandler::ObDdsConfigHandler(ObContinuation *cont, ObMIOBuffer *buf, const ObInternalCmdInfo &info) : ObInternalCmdHandler(cont, buf, info), sub_type_(info.get_sub_cmd_type()), cmd_type_(info.get_cmd_type()), capability_(info.get_capability()) { @@ -362,7 +361,6 @@ int ObDdsConfigHandler::handle_parse_where_fields(ObArenaAllocator* allocator, O } else { ObExprParser expr_parser(*allocator, parse_mode); expr_result.part_key_info_.key_num_ = 0; - expr_result.target_mask_ = 0; if (OB_FAIL(expr_parser.parse_reqsql(sql, sql_parse_result.get_parsed_length(), expr_result, sql_parse_result.get_stmt_type(), connection_collation))) { diff --git a/src/obproxy/cmd/ob_dds_config_handler.h b/src/obproxy/cmd/ob_dds_config_handler.h index da9a976f96df5597d774c8344f1e3173081b87a9..bcf4e0b881d510472e2a54c91e724bc7f0fcf95f 100644 --- a/src/obproxy/cmd/ob_dds_config_handler.h +++ b/src/obproxy/cmd/ob_dds_config_handler.h @@ -33,9 +33,7 @@ namespace obutils class ObDdsConfigHandler : public ObInternalCmdHandler { public: - ObDdsConfigHandler(event::ObContinuation *cont, - event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObDdsConfigHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObDdsConfigHandler() {} int main_handler(int event, void *data); diff --git a/src/obproxy/cmd/ob_internal_cmd_handler.cpp b/src/obproxy/cmd/ob_internal_cmd_handler.cpp index afe5f9b428682aef4c5993e52ab61a3c1014804c..be03c433450ceeed714cc9fa53cf0526aad5fb95 100644 --- a/src/obproxy/cmd/ob_internal_cmd_handler.cpp +++ b/src/obproxy/cmd/ob_internal_cmd_handler.cpp @@ -16,6 +16,7 @@ #include "iocore/eventsystem/ob_ethread.h" #include "iocore/net/ob_net_def.h" #include "proxy/mysql/ob_mysql_client_session.h" +#include "obproxy/proxy/mysqllib/ob_2_0_protocol_utils.h" using namespace oceanbase::obmysql; using namespace oceanbase::share::schema; @@ -26,10 +27,10 @@ namespace oceanbase { namespace obproxy { -ObInternalCmdHandler::ObInternalCmdHandler(ObContinuation *cont, ObMIOBuffer *buf, - const ObInternalCmdInfo &info) +ObInternalCmdHandler::ObInternalCmdHandler(ObContinuation *cont, ObMIOBuffer *buf, const ObInternalCmdInfo &info) : ObContinuation(), cs_handler_(NULL), cs_id_(info.get_cs_id()), external_buf_(buf), internal_buf_(NULL), internal_reader_(NULL), internal_buf_limited_(info.get_memory_limit()), + protocol_(info.get_protocol()), ob20_param_(info.get_ob20_head_param()), is_inited_(false), header_encoded_(false), seq_(info.get_pkt_seq()), original_seq_(seq_), saved_event_(-1), like_name_() { @@ -50,17 +51,9 @@ ObInternalCmdHandler::~ObInternalCmdHandler() action_.mutex_.release(); mutex_.release(); cs_handler_ = NULL; - if (OB_LIKELY(NULL != internal_reader_)) { - int ret = OB_SUCCESS; - if (OB_FAIL(internal_reader_->consume(internal_reader_->read_avail()))) { - WARN_ICMD("fail to consume ", K(ret)); - } - internal_reader_ = NULL; - } - if (OB_LIKELY(NULL != internal_buf_)) { - free_miobuffer(internal_buf_); - internal_buf_ = NULL; - } + destroy_internal_buf(); + protocol_ = ObProxyProtocol::PROTOCOL_NORMAL; + ob20_param_.reset(); } int ObInternalCmdHandler::init(const bool is_query_cmd/*true*/) @@ -118,10 +111,27 @@ int ObInternalCmdHandler::reset() } else { internal_buf_->reset(); seq_ = original_seq_; + // could not reset protocol and ob20_param in handler, cause we need filll external buf according to protocol } return ret; } +void ObInternalCmdHandler::destroy_internal_buf() +{ + if (OB_LIKELY(NULL != internal_reader_)) { + int ret = OB_SUCCESS; + if (OB_FAIL(internal_reader_->consume(internal_reader_->read_avail()))) { + WARN_ICMD("fail to consume ", K(ret)); + } + internal_reader_ = NULL; + } + + if (OB_LIKELY(NULL != internal_buf_)) { + free_miobuffer(internal_buf_); + internal_buf_ = NULL; + } +} + int ObInternalCmdHandler::encode_header(const ObString *cname, const EMySQLFieldType *ctype, const int64_t size) { int ret = OB_SUCCESS; @@ -221,36 +231,27 @@ int ObInternalCmdHandler::encode_eof_packet() return ret; } +// write packet in mysql format to internal buf, then trans it to external buf as ob20/mysql int ObInternalCmdHandler::encode_err_packet(const int errcode) { int ret = OB_SUCCESS; - const int32_t MAX_MSG_BUF_SIZE = 256; - char msg_buf[MAX_MSG_BUF_SIZE]; + if (IS_NOT_INIT) { ret = OB_NOT_INIT; WARN_ICMD("it has not inited", K(ret)); - } else if (OB_FAIL(reset())) {//before encode_err_packet, we need clean buf + } else if (OB_FAIL(reset())) { // before encode err packet, we need clean buf WARN_ICMD("fail to do reset", K(errcode), K(ret)); } else { - const char *errmsg = ob_strerror(errcode); - int32_t length = 0; - if (OB_ISNULL(errmsg)) { - length = snprintf(msg_buf, sizeof(msg_buf), "Unknown user error"); + char *err_msg = NULL; + if (OB_FAIL(packet::ObProxyPacketWriter::get_err_buf(errcode, err_msg))) { + WARN_ICMD("fail to get err buf", K(ret)); + } else if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet(*internal_buf_, seq_, errcode, err_msg))) { + WARN_ICMD("fail to encode err packet", K(errcode), K(err_msg), K(ret)); } else { - length = snprintf(msg_buf, sizeof(msg_buf), errmsg); - } - if (OB_UNLIKELY(length <= 0) || OB_UNLIKELY(length >= MAX_MSG_BUF_SIZE)) { - ret = OB_BUF_NOT_ENOUGH; - WARN_ICMD("msg_buf is not enough", K(length), K(errmsg), K(ret)); - } else {} - } - if (OB_SUCC(ret)) { - if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet_buf(*internal_buf_, seq_, errcode, msg_buf))) { - WARN_ICMD("fail to encode err packet", K(errcode), K(msg_buf), K(ret)); - } else { - INFO_ICMD("succ to encode err packet", K(errcode), K(msg_buf)); + INFO_ICMD("succ to encode err packet", K(errcode), K(err_msg)); } } + return ret; } @@ -543,9 +544,6 @@ int ObInternalCmdHandler::internal_error_callback(int errcode) int ret = OB_SUCCESS; int event_ret = EVENT_NONE; - if (OB_BUF_NOT_ENOUGH != errcode && OB_ERR_OPERATOR_UNKNOWN != errcode && OB_SEQUENCE_ERROR != errcode) { - errcode = OB_RESULT_UNKNOWN; - } if (OB_FAIL(encode_err_packet(errcode))) { WARN_ICMD("fail to encode internal err packet, callback", K(errcode), K(ret)); event_ret = handle_callback(INTERNAL_CMD_EVENTS_FAILED, NULL); @@ -559,19 +557,33 @@ int ObInternalCmdHandler::internal_error_callback(int errcode) int ObInternalCmdHandler::fill_external_buf() { int ret = OB_SUCCESS; - int64_t data_size = internal_reader_->read_avail(); - int64_t bytes_written = 0; - if (OB_FAIL(external_buf_->remove_append(internal_reader_, bytes_written))) { - ERROR_ICMD("Error while remove_append to external_buf_!", "Attempted size", data_size, - "wrote size", bytes_written, K(ret)); - } else if (OB_UNLIKELY(bytes_written != data_size)) { - ret = OB_ERR_UNEXPECTED; - WARN_ICMD("unexpected result", "Attempted size", data_size, - "wrote size", bytes_written, K(ret)); + + if (OB_LIKELY(protocol_ == ObProxyProtocol::PROTOCOL_OB20)) { + if (OB_FAIL(ObProto20Utils::consume_and_compress_data(internal_reader_, external_buf_, + internal_reader_->read_avail(), ob20_param_))) { + WARN_ICMD("fail to consume and compress to ob20 packet", K(ret), K_(ob20_param)); + } else { + DEBUG_ICMD("succ to write to client in ob20", K_(ob20_param)); + } + } else if (protocol_ == ObProxyProtocol::PROTOCOL_NORMAL) { + // mysql + int64_t data_size = internal_reader_->read_avail(); + int64_t bytes_written = 0; + if (OB_FAIL(external_buf_->remove_append(internal_reader_, bytes_written))) { + ERROR_ICMD("Error while remove_append to external_buf_!", "Attempted size", data_size, + "wrote size", bytes_written, K(ret)); + } else if (OB_UNLIKELY(bytes_written != data_size)) { + ret = OB_ERR_UNEXPECTED; + WARN_ICMD("unexpected result", "Attempted size", data_size, "wrote size", bytes_written, K(ret)); + } else { + internal_reader_ = NULL; + DEBUG_ICMD("succ to write to client in mysql", "Attempted size", bytes_written); + } } else { - internal_reader_ = NULL; - DEBUG_ICMD("succ to write to client", "Attempted size", bytes_written); + ret = OB_ERR_UNEXPECTED; + WARN_ICMD("unexpected protocol type", K(ret), K_(protocol)); } + return ret; } @@ -608,7 +620,8 @@ int ObInternalCmdHandler::handle_callback(int event, void *data) MUTEX_TRY_LOCK(lock, action_.mutex_, submit_thread_); if (lock.is_locked()) { if (!action_.cancelled_) { - if (INTERNAL_CMD_EVENTS_SUCCESS == saved_event_ && OB_SUCCESS != fill_external_buf()) { + if (INTERNAL_CMD_EVENTS_SUCCESS == saved_event_ + && OB_SUCCESS != fill_external_buf()) { saved_event_ = INTERNAL_CMD_EVENTS_FAILED; } DEBUG_ICMD("do callback now", K_(saved_event)); diff --git a/src/obproxy/cmd/ob_internal_cmd_handler.h b/src/obproxy/cmd/ob_internal_cmd_handler.h index 5c17953c4762e87f246192406af3b6390bc4bdd6..224221db51207bcb0465b34203055486963cef2d 100644 --- a/src/obproxy/cmd/ob_internal_cmd_handler.h +++ b/src/obproxy/cmd/ob_internal_cmd_handler.h @@ -19,6 +19,8 @@ #include "common/obsm_row.h" #include "packet/ob_mysql_packet_util.h" #include "iocore/eventsystem/ob_io_buffer.h" +#include "obproxy/packet/ob_proxy_packet_writer.h" + namespace oceanbase { @@ -27,6 +29,7 @@ namespace obproxy namespace proxy { class ObMysqlClientSession; +class Ob20ProtocolHeaderParam; } class ObInternalCmdHandler; @@ -88,8 +91,7 @@ typedef common::ObSEArray CSIDHanders; class ObInternalCmdHandler : public event::ObContinuation { public: - ObInternalCmdHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObInternalCmdHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObInternalCmdHandler(); static bool is_constructor_argument_valid(const event::ObContinuation *cont, @@ -103,6 +105,7 @@ public: int init(const bool is_query_cmd = true); int reset();//clean buf and reset seq + void destroy_internal_buf(); int fill_external_buf(); event::ObAction &get_action() { return action_; } bool is_inited() const { return is_inited_; }; @@ -137,12 +140,17 @@ protected: if (IS_NOT_INIT){ ret = OB_NOT_INIT; WARN_ICMD("it has not inited", K(ret)); - } else if (OB_FAIL(reset())) { //before encode_err_packet, we need clean buf + } else if (OB_FAIL(reset())) { // before encode err packet, we need clean buf WARN_ICMD("fail to do reset", K(errcode), K(ret)); - } else if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet(*internal_buf_, seq_, errcode, param))) { - WARN_ICMD("fail to encode err packet", K(errcode), K(ret)); } else { - INFO_ICMD("succ to encode err packet", K(errcode)); + char *err_msg = NULL; + if (OB_FAIL(packet::ObProxyPacketWriter::get_user_err_buf(errcode, err_msg, param))) { + WARN_ICMD("fail to get user err buf", K(errcode), K(ret)); + } else if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet(*internal_buf_, seq_, errcode, err_msg))) { + WARN_ICMD("fail to encode err packet buf", K(errcode), K(ret)); + } else { + INFO_ICMD("succ to encode err packet", K(errcode)); + } } return ret; } @@ -174,6 +182,9 @@ protected: event::ObMIOBuffer *internal_buf_; event::ObIOBufferReader *internal_reader_; int64_t internal_buf_limited_; + + proxy::ObProxyProtocol protocol_; + proxy::Ob20ProtocolHeaderParam ob20_param_; bool is_inited_; bool header_encoded_; diff --git a/src/obproxy/cmd/ob_internal_cmd_processor.cpp b/src/obproxy/cmd/ob_internal_cmd_processor.cpp index 8d33a8b605971e88851465ac0751edd5b5810110..66800915622dfdb38b881c3723cb8996adeb7a76 100644 --- a/src/obproxy/cmd/ob_internal_cmd_processor.cpp +++ b/src/obproxy/cmd/ob_internal_cmd_processor.cpp @@ -27,6 +27,42 @@ namespace oceanbase { namespace obproxy { + +void ObInternalCmdInfo::reset() +{ + session_priv_ = NULL; + pkt_seq_ = -1; + type_ = OBPROXY_T_INVALID; + sub_type_ = OBPROXY_T_SUB_INVALID; + err_type_ = OBPROXY_T_ERR_INVALID; + capability_.capability_ = 0; + memory_limit_ = 0; + is_internal_user_ = false; + first_int_ = -1; + second_int_ = -1; + third_int_ = -1; + first_string_.reset(); + second_string_.reset(); + first_str_[0] = '\0'; + second_str_[0] = '\0'; + protocol_ = ObProxyProtocol::PROTOCOL_NORMAL; + ob20_param_.reset(); +} + +int64_t ObInternalCmdInfo::to_string(char* buf, const int64_t buf_len) const +{ + int64_t pos = 0; + J_OBJ_START(); + J_KV("type", get_obproxy_stmt_name(type_), + "sub_type", get_obproxy_sub_stmt_name(sub_type_), + "err_type", get_obproxy_err_stmt_name(err_type_), + K_(pkt_seq), K_(capability_.capability), + K_(memory_limit), K_(is_internal_user), K_(first_int), K_(second_int), K_(third_int), + K_(first_string), K_(second_string), KPC_(session_priv)); + J_OBJ_END(); + return pos; +} + ObInternalCmdProcessor &get_global_internal_cmd_processor() { static ObInternalCmdProcessor internal_cmd_processor; @@ -54,6 +90,7 @@ int ObInternalCmdProcessor::execute_cmd(ObContinuation *cont, ObInternalCmdInfo { int ret = OB_SUCCESS; action = NULL; + DRWLock::WRLockGuard guard(internal_cmd_lock_); const ObProxyBasicStmtType type = info.get_cmd_type(); ObMysqlSM *sm = reinterpret_cast(cont); ObString table_name; @@ -67,7 +104,7 @@ int ObInternalCmdProcessor::execute_cmd(ObContinuation *cont, ObInternalCmdInfo ObProxyMysqlRequest &client_request = sm->trans_state_.trans_info_.client_request_; table_name = client_request.get_parse_result().get_table_name(); } - + if (OB_FAIL(ret)) { // do nothing } else if (get_global_config_processor().is_table_in_service(table_name) diff --git a/src/obproxy/cmd/ob_internal_cmd_processor.h b/src/obproxy/cmd/ob_internal_cmd_processor.h index e161af24862f835514fa711906e42e7d251c4796..e4c896a46394b0658125c122a045d6520e57113a 100644 --- a/src/obproxy/cmd/ob_internal_cmd_processor.h +++ b/src/obproxy/cmd/ob_internal_cmd_processor.h @@ -14,12 +14,14 @@ #define OBPROXY_INTERNAL_CMD_PROCESSOR_H #include "lib/utility/ob_print_utils.h" +#include "lib/lock/ob_drw_lock.h" #include "rpc/obmysql/ob_mysql_packet.h" #include "opsql/parser/ob_proxy_parse_result.h" #include "iocore/eventsystem/ob_event.h" #include "iocore/net/ob_inet.h" -#include "utils/ob_proxy_privilege_check.h" +#include "proxy/mysqllib/ob_mysql_common_define.h" +#include "proxy/mysqllib/ob_2_0_protocol_struct.h" #define INTERNAL_CMD_EVENTS_SUCCESS INTERNAL_CMD_EVENTS_START + 1 #define INTERNAL_CMD_EVENTS_FAILED INTERNAL_CMD_EVENTS_START + 2 @@ -40,6 +42,8 @@ class ObContinuation; class ObMIOBuffer; } +class ObProxySessionPrivInfo; + #define DEBUG_ICMD(fmt...) PROXY_ICMD_LOG(DEBUG, ##fmt) #define INFO_ICMD(fmt...) PROXY_ICMD_LOG(INFO, ##fmt) #define WARN_ICMD(fmt...) PROXY_ICMD_LOG(WARN, ##fmt) @@ -53,24 +57,7 @@ public: ObInternalCmdInfo() { reset(); } ~ObInternalCmdInfo() { } - void reset() - { - session_priv_ = NULL; - pkt_seq_ = -1; - type_ = OBPROXY_T_INVALID; - sub_type_ = OBPROXY_T_SUB_INVALID; - err_type_ = OBPROXY_T_ERR_INVALID; - capability_.capability_ = 0; - memory_limit_ = 0; - is_internal_user_ = false; - first_int_ = -1; - second_int_ = -1; - third_int_ = -1; - first_string_.reset(); - second_string_.reset(); - first_str_[0] = '\0'; - second_str_[0] = '\0'; - } + void reset(); uint8_t get_pkt_seq() const { return pkt_seq_; } obmysql::ObMySQLCapabilityFlags get_capability() const { return capability_; } @@ -100,6 +87,13 @@ public: const common::ObString &get_cluster_string() const { return first_string_; } const common::ObString &get_large_key_string() const { return second_string_; } + proxy::ObProxyProtocol get_protocol() const { return protocol_; } + proxy::Ob20ProtocolHeaderParam &get_ob20_head_param() { return ob20_param_; } + const proxy::Ob20ProtocolHeaderParam &get_ob20_head_param() const { return ob20_param_; } + + void set_protocol(const proxy::ObProxyProtocol protocol) { protocol_ = protocol; } + void set_ob20_head_param(const proxy::Ob20ProtocolHeaderParam ¶m) { ob20_param_ = param; } + void set_pkt_seq(const uint8_t pkt_seq) { pkt_seq_ = pkt_seq; } void set_cmd_type(const ObProxyBasicStmtType type) { type_ = type; } void set_sub_cmd_type(const ObProxyBasicStmtSubType type) { sub_type_ = type; } @@ -129,14 +123,11 @@ public: } } - TO_STRING_KV("type", get_obproxy_stmt_name(type_), - "sub_type", get_obproxy_sub_stmt_name(sub_type_), - "err_type", get_obproxy_err_stmt_name(err_type_), - K_(pkt_seq), K_(capability_.capability), - K_(memory_limit), K_(is_internal_user), K_(first_int), K_(second_int), K_(third_int), - K_(first_string), K_(second_string), KPC_(session_priv)); + int64_t to_string(char* buf, const int64_t buf_len) const; + +public: + ObProxySessionPrivInfo *session_priv_; - ObProxySessionPrivInfo *session_priv_; private: uint8_t pkt_seq_; ObProxyBasicStmtType type_; @@ -169,12 +160,15 @@ private: char first_str_[common::OB_MAX_CONFIG_NAME_LEN]; char second_str_[common::OB_MAX_CONFIG_VALUE_LEN]; + proxy::ObProxyProtocol protocol_; + proxy::Ob20ProtocolHeaderParam ob20_param_; + private: DISALLOW_COPY_AND_ASSIGN(ObInternalCmdInfo); }; typedef int (*ObInternalCmdCallbackFunc) (event::ObContinuation *cont, ObInternalCmdInfo &info, - event::ObMIOBuffer *buf, event::ObAction *&action); + event::ObMIOBuffer *buf, event::ObAction *&action); struct ObCmdTableInfo { @@ -189,7 +183,7 @@ struct ObCmdTableInfo class ObInternalCmdProcessor { public: - ObInternalCmdProcessor() :is_inited_(false), reload_config_(NULL) + ObInternalCmdProcessor() :is_inited_(false), reload_config_(NULL), internal_cmd_lock_() { memset(cmd_table_, 0, sizeof(cmd_table_)); } @@ -198,7 +192,7 @@ public: int init(obutils::ObProxyReloadConfig *reload_config); int execute_cmd(event::ObContinuation *cont, ObInternalCmdInfo &info, - event::ObMIOBuffer *buf, event::ObAction *&action); + event::ObMIOBuffer *buf, event::ObAction *&action); //register funcs int register_cmd(const ObProxyBasicStmtType type, ObInternalCmdCallbackFunc func, bool skip_type_check = false); obutils::ObProxyReloadConfig *get_reload_config() { return reload_config_; } @@ -207,6 +201,7 @@ private: bool is_inited_; obutils::ObProxyReloadConfig *reload_config_; //used for alter config set ObCmdTableInfo cmd_table_[OBPROXY_T_MAX]; + common::DRWLock internal_cmd_lock_; DISALLOW_COPY_AND_ASSIGN(ObInternalCmdProcessor); }; diff --git a/src/obproxy/cmd/ob_kill_global_session_handler.cpp b/src/obproxy/cmd/ob_kill_global_session_handler.cpp index afe90132e87f1654c65d0f8d67d131cd005ee4b7..d748b8f049dffdc2fa493ad347c440db561b70b7 100644 --- a/src/obproxy/cmd/ob_kill_global_session_handler.cpp +++ b/src/obproxy/cmd/ob_kill_global_session_handler.cpp @@ -56,6 +56,7 @@ int ObKillGlobalSessionHandler::handle_kill_global_session_info(int event, void } return event_ret; } + int ObKillGlobalSessionHandler::encode_err_packet(const int errcode) { int ret = OB_SUCCESS; @@ -78,7 +79,7 @@ int ObKillGlobalSessionHandler::encode_err_packet(const int errcode) } else {} } if (OB_SUCC(ret)) { - if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet_buf(*internal_buf_, seq_, errcode, msg_buf))) { + if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet(*internal_buf_, seq_, errcode, msg_buf))) { WARN_ICMD("fail to encode err packet", K(errcode), K(msg_buf), K(ret)); } else { INFO_ICMD("succ to encode err packet", K(errcode), K(msg_buf)); diff --git a/src/obproxy/cmd/ob_kill_global_session_handler.h b/src/obproxy/cmd/ob_kill_global_session_handler.h index 9a258ce431fb08e4ad8e79d6701ad543f893d4dc..58d4e01ef81ec777c1dfc7cc5d058e0d34acaa51 100644 --- a/src/obproxy/cmd/ob_kill_global_session_handler.h +++ b/src/obproxy/cmd/ob_kill_global_session_handler.h @@ -23,8 +23,7 @@ namespace proxy class ObKillGlobalSessionHandler : public ObInternalCmdHandler { public: - ObKillGlobalSessionHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObKillGlobalSessionHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObKillGlobalSessionHandler() {} int handle_kill_global_session_info(int event, void *data); int handle_kill_session_info(); diff --git a/src/obproxy/cmd/ob_kill_op_handler.cpp b/src/obproxy/cmd/ob_kill_op_handler.cpp index c4b04603397f0417019efd244c98ef2b01e5fea7..83c4c016cf1b8709456db332cb490f8f53b99938 100644 --- a/src/obproxy/cmd/ob_kill_op_handler.cpp +++ b/src/obproxy/cmd/ob_kill_op_handler.cpp @@ -26,8 +26,7 @@ namespace obproxy { namespace proxy { -ObKillOpHandler::ObKillOpHandler(ObContinuation *cont, ObMIOBuffer *buf, - const ObInternalCmdInfo &info) +ObKillOpHandler::ObKillOpHandler(ObContinuation *cont, ObMIOBuffer *buf, const ObInternalCmdInfo &info) : ObInternalCmdHandler(cont, buf, info), sub_type_(info.get_sub_cmd_type()), ss_id_(info.get_ss_id()), capability_(info.get_capability()), cs_id_array_() { diff --git a/src/obproxy/cmd/ob_kill_op_handler.h b/src/obproxy/cmd/ob_kill_op_handler.h index d72c76c1a3156735e61a99494b2d98792cde456e..08883bbafbbab6765699bd7ffc5fdd42a22721e4 100644 --- a/src/obproxy/cmd/ob_kill_op_handler.h +++ b/src/obproxy/cmd/ob_kill_op_handler.h @@ -25,8 +25,7 @@ namespace proxy class ObKillOpHandler : public ObInternalCmdHandler { public: - ObKillOpHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObKillOpHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObKillOpHandler() { cs_id_array_.destroy(); } int handle_kill_option(int event, void *data); virtual CSIDHanders *get_cs_id_array() { return &cs_id_array_; } diff --git a/src/obproxy/cmd/ob_select_database_handler.cpp b/src/obproxy/cmd/ob_select_database_handler.cpp index c120e42b3337252a550f549966b98a49fef2b62f..72895e235de4e8fb3e47b66bc02e788faf681a49 100644 --- a/src/obproxy/cmd/ob_select_database_handler.cpp +++ b/src/obproxy/cmd/ob_select_database_handler.cpp @@ -33,8 +33,8 @@ enum const static ObString &column_name = ObString::make_string("database()"); const static EMySQLFieldType column_type = OB_MYSQL_TYPE_VARCHAR; -ObSelectDatabaseHandler::ObSelectDatabaseHandler(ObMIOBuffer *buf, uint8_t pkg_seq, int64_t memory_limit) - : ObCmdHandler(buf, pkg_seq, memory_limit) +ObSelectDatabaseHandler::ObSelectDatabaseHandler(ObMIOBuffer *buf, ObCmdInfo &info) + : ObCmdHandler(buf, info) { } @@ -100,12 +100,13 @@ int ObSelectDatabaseHandler::dump_payload(const ObString &logic_database_name) return ret; } -int ObSelectDatabaseHandler::select_database_cmd_callback(ObMIOBuffer *buf, uint8_t pkg_seq, int64_t memory_limit, const ObString &logic_database_name) +int ObSelectDatabaseHandler::select_database_cmd_callback(ObMIOBuffer *buf, ObCmdInfo &info, + const ObString &logic_database_name) { int ret = OB_SUCCESS; ObSelectDatabaseHandler *handler = NULL; - if (OB_ISNULL(handler = new(std::nothrow) ObSelectDatabaseHandler(buf, pkg_seq, memory_limit))) { + if (OB_ISNULL(handler = new(std::nothrow) ObSelectDatabaseHandler(buf, info))) { ret = OB_ALLOCATE_MEMORY_FAILED; ERROR_CMD("fail to new ObSelectDatabaseHandler", K(ret)); } else if (OB_FAIL(handler->init())) { diff --git a/src/obproxy/cmd/ob_select_database_handler.h b/src/obproxy/cmd/ob_select_database_handler.h index 0f31dcd21357ee9ba3e6914c7b67ddd1d5ade240..c622526dcc7b2f47122a4ea623c85cd92bd6a2d6 100644 --- a/src/obproxy/cmd/ob_select_database_handler.h +++ b/src/obproxy/cmd/ob_select_database_handler.h @@ -25,11 +25,12 @@ namespace obutils class ObSelectDatabaseHandler : public ObCmdHandler { public: - ObSelectDatabaseHandler(event::ObMIOBuffer *buf, uint8_t pkg_seq, int64_t memory_limit); + ObSelectDatabaseHandler(event::ObMIOBuffer *buf, ObCmdInfo &info); virtual ~ObSelectDatabaseHandler() {} int handle_select_database(const ObString &logic_database_name); - static int select_database_cmd_callback(event::ObMIOBuffer *buf, uint8_t pkg_seq, int64_t memory_limit, const ObString &logic_database_name); + static int select_database_cmd_callback(event::ObMIOBuffer *buf, ObCmdInfo &info, + const ObString &logic_database_name); private: int dump_header(); diff --git a/src/obproxy/cmd/ob_sequence_info_handler.cpp b/src/obproxy/cmd/ob_sequence_info_handler.cpp index 06ceec7256d6c36e92b6e5703900cb94b3e47a5c..d0fc0450f21ed75db9138a6cac35306d9534ce04 100644 --- a/src/obproxy/cmd/ob_sequence_info_handler.cpp +++ b/src/obproxy/cmd/ob_sequence_info_handler.cpp @@ -175,7 +175,8 @@ int ObSequenceInfoHandler::handle_shard_sequence_params() } else if (!param_.tnt_id_.empty() && param_.tnt_col_.empty()) { snprintf(err_msg_, SEQUENCE_ERR_MSG_SIZE, "tnt_col is empty while tnt_id used"); ret = OB_ERR_UNEXPECTED; - } else if (OB_FAIL(ObProxyShardUtils::get_real_info(*logic_db_info, + } else if (OB_FAIL(ObProxyShardUtils::get_real_info(session_info, + *logic_db_info, sequence_table_name, parse_result, shard_conn, @@ -211,6 +212,9 @@ int ObSequenceInfoHandler::handle_shard_sequence_params() table_id_ = table_id; group_id_ = group_id; eid_ = es_id; + session_info.set_group_id(group_id); + session_info.set_table_id(table_id); + session_info.set_es_id(es_id); snprintf(seq_id_buf_, 2048, "%.*s-%.*s-%.*s-%.*s-%.*s-%.*s-%02ld-%02ld-%02ld", logic_tenant_name_.config_string_.length(), logic_tenant_name_.config_string_.ptr(), @@ -222,6 +226,11 @@ int ObSequenceInfoHandler::handle_shard_sequence_params() group_id_, table_id_, eid_); param_.seq_id_ = ObString(seq_id_buf_); } + + if (NULL != logic_db_info) { + logic_db_info->dec_ref(); + logic_db_info = NULL; + } LOG_DEBUG("Left handle_shard_sequence_params", K(param_), K(table_id_), K(group_id_), K(eid_)); return ret; } @@ -294,7 +303,7 @@ int ObSequenceInfoHandler::encode_err_packet(const int errcode) } else {} } if (OB_SUCC(ret)) { - if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet_buf(*internal_buf_, seq_, errcode, msg_buf))) { + if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet(*internal_buf_, seq_, errcode, msg_buf))) { WARN_ICMD("fail to encode err packet", K(errcode), K(msg_buf), K(ret)); } else { INFO_ICMD("succ to encode err packet", K(errcode), K(msg_buf)); diff --git a/src/obproxy/cmd/ob_sequence_info_handler.h b/src/obproxy/cmd/ob_sequence_info_handler.h index 25b7d88fd248be37568c5a00793376171adf710b..01dccb63a5a294448f7baf1265452c8495641288 100644 --- a/src/obproxy/cmd/ob_sequence_info_handler.h +++ b/src/obproxy/cmd/ob_sequence_info_handler.h @@ -29,8 +29,7 @@ class ObSequenceInfo; class ObSequenceInfoHandler : public ObInternalCmdHandler { public: - ObSequenceInfoHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObSequenceInfoHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObSequenceInfoHandler(); protected: int encode_err_packet(const int errcode); diff --git a/src/obproxy/cmd/ob_show_cluster_handler.cpp b/src/obproxy/cmd/ob_show_cluster_handler.cpp index ed3436e0e00fc3a1b15e3178b46d1d8dd23200fc..4e2e36b82d24db5e727b6d2f7e7a358c17ac22a1 100644 --- a/src/obproxy/cmd/ob_show_cluster_handler.cpp +++ b/src/obproxy/cmd/ob_show_cluster_handler.cpp @@ -71,8 +71,7 @@ const ObProxyColumnSchema CLUSTER_IDC_COLUMN_ARRAY[OB_CCI_MAX_CLUSTER_COLUMN_ID] }; -ObShowClusterHandler::ObShowClusterHandler(ObContinuation *cont, ObMIOBuffer *buf, - const ObInternalCmdInfo &info) +ObShowClusterHandler::ObShowClusterHandler(ObContinuation *cont, ObMIOBuffer *buf, const ObInternalCmdInfo &info) : ObInternalCmdHandler(cont, buf, info), sub_type_(info.get_sub_cmd_type()) { SET_HANDLER(&ObShowClusterHandler::handle_show_cluster); diff --git a/src/obproxy/cmd/ob_show_cluster_handler.h b/src/obproxy/cmd/ob_show_cluster_handler.h index ace3ea01e2aa52bb77d1be267ce29e81e00bf8d5..651c144f08653557a4c01864c7ef1e36b2341424 100644 --- a/src/obproxy/cmd/ob_show_cluster_handler.h +++ b/src/obproxy/cmd/ob_show_cluster_handler.h @@ -26,8 +26,7 @@ class ObProxyIDCInfo; class ObShowClusterHandler : public ObInternalCmdHandler { public: - ObShowClusterHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObShowClusterHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObShowClusterHandler() {} int handle_show_cluster(int event, void *data); diff --git a/src/obproxy/cmd/ob_show_config_handler.cpp b/src/obproxy/cmd/ob_show_config_handler.cpp index 1986632866d2807edf17c84d8de44923a81b97b5..f31396984f49c04adafbad0e236d0dbea2928f3f 100644 --- a/src/obproxy/cmd/ob_show_config_handler.cpp +++ b/src/obproxy/cmd/ob_show_config_handler.cpp @@ -75,8 +75,7 @@ const ObProxyColumnSchema SYSLOG_LEVEL_COLUMN_ARRAY[OB_SLC_MAX_SYSLOG_LEVEL_COLU ObProxyColumnSchema::make_schema(OB_SLC_USAGE, "usage", OB_MYSQL_TYPE_VARCHAR), }; -ObShowConfigHandler::ObShowConfigHandler(ObContinuation *cont, ObMIOBuffer *buf, - const ObInternalCmdInfo &info) +ObShowConfigHandler::ObShowConfigHandler(ObContinuation *cont, ObMIOBuffer *buf, const ObInternalCmdInfo &info) : ObInternalCmdHandler(cont, buf, info), sub_type_(info.get_sub_cmd_type()) { SET_HANDLER(&ObShowConfigHandler::handle_show_config); diff --git a/src/obproxy/cmd/ob_show_config_handler.h b/src/obproxy/cmd/ob_show_config_handler.h index e9242b7ec80fe69d603dacbdcf8242af1fcdf869..23dd3e729f17cde70b24f349e5c05b4592fa90fb 100644 --- a/src/obproxy/cmd/ob_show_config_handler.h +++ b/src/obproxy/cmd/ob_show_config_handler.h @@ -28,9 +28,7 @@ namespace obutils class ObShowConfigHandler : public ObInternalCmdHandler { public: - ObShowConfigHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); - + ObShowConfigHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObShowConfigHandler() {} int handle_show_config(int event, void *data); diff --git a/src/obproxy/cmd/ob_show_congestion_handler.cpp b/src/obproxy/cmd/ob_show_congestion_handler.cpp index e059ec24eb316b0e286ff1b152fb473c00bcea59..ed807392aaaf4c8f786c7c6f012bc00b95df42d5 100644 --- a/src/obproxy/cmd/ob_show_congestion_handler.cpp +++ b/src/obproxy/cmd/ob_show_congestion_handler.cpp @@ -49,6 +49,8 @@ enum OB_CC_ALIVE_LAST_FAIL_TIME, OB_CC_ALIVE_FAILURE_EVENTS, OB_CC_REF_COUNT, + OB_CC_DETECT_CONGESTED, + OB_CC_LAST_DETECT_CONGESTED, OB_CC_MAX_CONGESTION_COLUMN_ID, }; @@ -71,11 +73,12 @@ const ObProxyColumnSchema CONGESTION_COLUMN_ARRAY[OB_CC_MAX_CONGESTION_COLUMN_ID ObProxyColumnSchema::make_schema(OB_CC_ALIVE_LAST_FAIL_TIME, "alive_last_fail_time", obmysql::OB_MYSQL_TYPE_VARCHAR), ObProxyColumnSchema::make_schema(OB_CC_ALIVE_FAILURE_EVENTS, "alive_failure_events", obmysql::OB_MYSQL_TYPE_LONGLONG), ObProxyColumnSchema::make_schema(OB_CC_REF_COUNT, "ref_count", obmysql::OB_MYSQL_TYPE_LONGLONG), + ObProxyColumnSchema::make_schema(OB_CC_DETECT_CONGESTED, "detect_congested", obmysql::OB_MYSQL_TYPE_LONGLONG), + ObProxyColumnSchema::make_schema(OB_CC_LAST_DETECT_CONGESTED, "last_detect_congested",obmysql::OB_MYSQL_TYPE_VARCHAR), }; -ObShowCongestionHandler::ObShowCongestionHandler(ObContinuation *cont, ObMIOBuffer *buf, - const ObInternalCmdInfo &info) +ObShowCongestionHandler::ObShowCongestionHandler(ObContinuation *cont, ObMIOBuffer *buf, const ObInternalCmdInfo &info) : ObInternalCmdHandler(cont, buf, info), sub_type_(info.get_sub_cmd_type()), idx_(0), list_bucket_(0) { @@ -234,6 +237,7 @@ int ObShowCongestionHandler::dump_item(const ObCongestionEntry *entry, const ObS int ret = OB_SUCCESS; char alive_timebuf[64]; char dead_timebuf[64]; + char detect_timebuf[64]; char conn_last_fail[64]; char alive_last_fail[64]; ip_port_text_buffer server_ip; @@ -297,8 +301,7 @@ int ObShowCongestionHandler::dump_item(const ObCongestionEntry *entry, const ObS if (OB_SUCC(ret)) { if (OB_UNLIKELY(strftime_len <= 0) || OB_UNLIKELY(strftime_len >= sizeof(dead_timebuf))) { ret = OB_BUF_NOT_ENOUGH; - WARN_ICMD("timebuf is not enough", K(strftime_len), "timebuf length", sizeof(dead_timebuf), - K(dead_timebuf), K(ret)); + WARN_ICMD("timebuf is not enough", K(strftime_len), K(dead_timebuf), K(ret)); } else { cells[OB_CC_LAST_DEAD_CONGESTED].set_varchar(dead_timebuf); } @@ -323,8 +326,7 @@ int ObShowCongestionHandler::dump_item(const ObCongestionEntry *entry, const ObS if (OB_SUCC(ret)) { if (OB_UNLIKELY(strftime_len <= 0) || OB_UNLIKELY(strftime_len >= sizeof(conn_last_fail))) { ret = OB_BUF_NOT_ENOUGH; - WARN_ICMD("timebuf is not enough", K(strftime_len), "timebuf length", sizeof(conn_last_fail), - K(conn_last_fail), K(ret)); + WARN_ICMD("timebuf is not enough", K(strftime_len), K(conn_last_fail), K(ret)); } else { cells[OB_CC_CONN_LAST_FAIL_TIME].set_varchar(conn_last_fail); } @@ -348,14 +350,37 @@ int ObShowCongestionHandler::dump_item(const ObCongestionEntry *entry, const ObS if (OB_SUCC(ret)) { if (OB_UNLIKELY(strftime_len <= 0) || OB_UNLIKELY(strftime_len >= sizeof(alive_last_fail))) { ret = OB_BUF_NOT_ENOUGH; - WARN_ICMD("timebuf is not enough", K(strftime_len), "timebuf length", sizeof(alive_last_fail), - K(alive_last_fail), K(ret)); + WARN_ICMD("timebuf is not enough", K(strftime_len), K(ret)); } else { cells[OB_CC_ALIVE_LAST_FAIL_TIME].set_varchar(alive_last_fail); } } } + if (OB_SUCC(ret)) { + cells[OB_CC_DETECT_CONGESTED].set_int(entry->detect_congested_); + if (0 != entry->last_detect_congested_) { + t = entry->last_detect_congested_; + if (OB_ISNULL(localtime_r(&t, &struct_tm))) { + ret = OB_ERR_UNEXPECTED; + WARN_ICMD("fail to converts the calendar time timep to broken-time representation", K(t), K(ret)); + } else { + strftime_len = strftime(detect_timebuf, sizeof(detect_timebuf), "%Y-%m-%d %H:%M:%S", &struct_tm); + } + } else { + strftime_len = snprintf(detect_timebuf, sizeof(detect_timebuf), "%ld", entry->last_detect_congested_); + } + + if (OB_SUCC(ret)) { + if (OB_UNLIKELY(strftime_len <= 0) || OB_UNLIKELY(strftime_len >= sizeof(detect_timebuf))) { + ret = OB_BUF_NOT_ENOUGH; + WARN_ICMD("timebuf is not enough", K(strftime_len), K(detect_timebuf), K(ret)); + } else { + cells[OB_CC_LAST_DETECT_CONGESTED].set_varchar(detect_timebuf); + } + } + } + if (OB_SUCC(ret)) { cells[OB_CC_ALIVE_FAILURE_EVENTS].set_int(entry->alive_fail_history_.events_); cells[OB_CC_REF_COUNT].set_int(entry->ref_count_); diff --git a/src/obproxy/cmd/ob_show_congestion_handler.h b/src/obproxy/cmd/ob_show_congestion_handler.h index 4fb47912af9664e5cd0f3dfca8a83b8079355dbd..9f7b110608305a211547ba7f783671843fce2b30 100644 --- a/src/obproxy/cmd/ob_show_congestion_handler.h +++ b/src/obproxy/cmd/ob_show_congestion_handler.h @@ -26,8 +26,7 @@ class ObClusterResource; class ObShowCongestionHandler : public ObInternalCmdHandler { public: - ObShowCongestionHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObShowCongestionHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObShowCongestionHandler() { destroy(); } private: diff --git a/src/obproxy/cmd/ob_show_databases_handler.cpp b/src/obproxy/cmd/ob_show_databases_handler.cpp index e002f8cb27835932489d41acf837c77cece36d4d..0a408064e159eab7e91be8efd613e74f8e20ea52 100644 --- a/src/obproxy/cmd/ob_show_databases_handler.cpp +++ b/src/obproxy/cmd/ob_show_databases_handler.cpp @@ -35,8 +35,8 @@ enum const static ObString &column_name = ObString::make_string("Database"); const static EMySQLFieldType column_type = OB_MYSQL_TYPE_VARCHAR; -ObShowDatabasesHandler::ObShowDatabasesHandler(ObMIOBuffer *buf, uint8_t pkg_seq, int64_t memory_limit) - : ObCmdHandler(buf, pkg_seq, memory_limit) +ObShowDatabasesHandler::ObShowDatabasesHandler(ObMIOBuffer *buf, ObCmdInfo &info) + : ObCmdHandler(buf, info) { } @@ -106,12 +106,13 @@ int ObShowDatabasesHandler::dump_database(const ObString &logic_tenant_name) return ret; } -int ObShowDatabasesHandler::show_databases_cmd_callback(ObMIOBuffer *buf, uint8_t pkg_seq, int64_t memory_limit, const ObString &logic_tenant_name) +int ObShowDatabasesHandler::show_databases_cmd_callback(ObMIOBuffer *buf, ObCmdInfo &info, + const ObString &logic_tenant_name) { int ret = OB_SUCCESS; ObShowDatabasesHandler *handler = NULL; - if (OB_ISNULL(handler = new(std::nothrow) ObShowDatabasesHandler(buf, pkg_seq, memory_limit))) { + if (OB_ISNULL(handler = new(std::nothrow) ObShowDatabasesHandler(buf, info))) { ret = OB_ALLOCATE_MEMORY_FAILED; ERROR_CMD("fail to new ObShowDatabasesHandler", K(ret)); } else if (OB_FAIL(handler->init())) { diff --git a/src/obproxy/cmd/ob_show_databases_handler.h b/src/obproxy/cmd/ob_show_databases_handler.h index 07cc21c44de0347baf2167ef852b0af256abe5bc..aeb61574b153e30d28de90d79c492c81a62da529 100644 --- a/src/obproxy/cmd/ob_show_databases_handler.h +++ b/src/obproxy/cmd/ob_show_databases_handler.h @@ -24,11 +24,12 @@ namespace obutils class ObShowDatabasesHandler : public ObCmdHandler { public: - ObShowDatabasesHandler(event::ObMIOBuffer *buf, uint8_t pkg_seq, int64_t memory_limit); + ObShowDatabasesHandler(event::ObMIOBuffer *buf, ObCmdInfo &info); virtual ~ObShowDatabasesHandler() {} int handle_show_databases(const ObString &logic_tenant_name); - static int show_databases_cmd_callback(event::ObMIOBuffer *buf, uint8_t pkg_seq, int64_t memory_limit, const ObString &logic_tenant_name); + static int show_databases_cmd_callback(event::ObMIOBuffer *buf, ObCmdInfo &info, + const ObString &logic_tenant_name); private: int dump_database_header(); diff --git a/src/obproxy/cmd/ob_show_db_version_handler.cpp b/src/obproxy/cmd/ob_show_db_version_handler.cpp index 1f2023d69b37ca084c9bb48603ce0ad90059313a..32f2c8bf3e784c9dbbbab45c79c41e64738878bf 100644 --- a/src/obproxy/cmd/ob_show_db_version_handler.cpp +++ b/src/obproxy/cmd/ob_show_db_version_handler.cpp @@ -42,8 +42,8 @@ static const EMySQLFieldType column_type[OB_CC_MAX_DATABASE_COLUMN_ID] = { OB_MYSQL_TYPE_VARCHAR }; -ObShowDBVersionHandler::ObShowDBVersionHandler(ObMIOBuffer *buf, uint8_t pkg_seq, int64_t memory_limit) - : ObCmdHandler(buf, pkg_seq, memory_limit) +ObShowDBVersionHandler::ObShowDBVersionHandler(ObMIOBuffer *buf, ObCmdInfo &info) + : ObCmdHandler(buf, info) { } @@ -111,14 +111,14 @@ int ObShowDBVersionHandler::dump_db_version(const ObString &logic_tenant_name, c return ret; } -int ObShowDBVersionHandler::show_db_version_cmd_callback(ObMIOBuffer *buf, uint8_t pkg_seq, int64_t memory_limit, +int ObShowDBVersionHandler::show_db_version_cmd_callback(ObMIOBuffer *buf, ObCmdInfo &info, const ObString &logic_tenant_name, const ObString &logic_db_name) { int ret = OB_SUCCESS; ObShowDBVersionHandler *handler = NULL; - if (OB_ISNULL(handler = new(std::nothrow) ObShowDBVersionHandler(buf, pkg_seq, memory_limit))) { + if (OB_ISNULL(handler = new(std::nothrow) ObShowDBVersionHandler(buf, info))) { ret = OB_ALLOCATE_MEMORY_FAILED; ERROR_CMD("fail to new ObShowDBVersionHandler", K(ret)); } else if (OB_FAIL(handler->init())) { diff --git a/src/obproxy/cmd/ob_show_db_version_handler.h b/src/obproxy/cmd/ob_show_db_version_handler.h index 0f1e6e4f237716f595edef4f744b74908fa9a39d..03d7ae49b9b8435dc0fc20e819c342d702a59d74 100644 --- a/src/obproxy/cmd/ob_show_db_version_handler.h +++ b/src/obproxy/cmd/ob_show_db_version_handler.h @@ -24,11 +24,11 @@ namespace obutils class ObShowDBVersionHandler : public ObCmdHandler { public: - ObShowDBVersionHandler(event::ObMIOBuffer *buf, uint8_t pkg_seq, int64_t memory_limit); + ObShowDBVersionHandler(event::ObMIOBuffer *buf, ObCmdInfo &info); virtual ~ObShowDBVersionHandler() {} int handle_show_db_version(const ObString &logic_tenant_name, const ObString &logic_db_name); - static int show_db_version_cmd_callback(event::ObMIOBuffer *buf, uint8_t pkg_seq, int64_t memory_limit, + static int show_db_version_cmd_callback(event::ObMIOBuffer *buf, ObCmdInfo &info, const ObString &logic_tenant_name, const ObString &logic_db_name); diff --git a/src/obproxy/cmd/ob_show_global_session_handler.h b/src/obproxy/cmd/ob_show_global_session_handler.h index 1d03f4e61090f693bd05bf25e8b72932f45e41ff..790d385de6bcf5a5df2bf583a5d930a312aa79da 100644 --- a/src/obproxy/cmd/ob_show_global_session_handler.h +++ b/src/obproxy/cmd/ob_show_global_session_handler.h @@ -24,8 +24,7 @@ namespace proxy class ObShowGlobalSessionHandler : public ObInternalCmdHandler { public: - ObShowGlobalSessionHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObShowGlobalSessionHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObShowGlobalSessionHandler() {} int handle_show_global_session_info(int event, void *data); int dump_header(); diff --git a/src/obproxy/cmd/ob_show_info_handler.cpp b/src/obproxy/cmd/ob_show_info_handler.cpp index 6c9d6dfc4b5854e0120d4b70a145a874706b142d..432034ab8453912eb3a9457bf7eae87036c7972e 100644 --- a/src/obproxy/cmd/ob_show_info_handler.cpp +++ b/src/obproxy/cmd/ob_show_info_handler.cpp @@ -73,8 +73,7 @@ const ObProxyColumnSchema DETAIL_COLUMN_ARRAY[OB_IC_DETAIL_MAX_COLUMN_ID] = { }; -ObShowInfoHandler::ObShowInfoHandler(ObContinuation *cont, ObMIOBuffer *buf, - const ObInternalCmdInfo &info) +ObShowInfoHandler::ObShowInfoHandler(ObContinuation *cont, ObMIOBuffer *buf, const ObInternalCmdInfo &info) : ObInternalCmdHandler(cont, buf, info), sub_type_(info.get_sub_cmd_type()) { SET_HANDLER(&ObShowInfoHandler::main_handle); diff --git a/src/obproxy/cmd/ob_show_info_handler.h b/src/obproxy/cmd/ob_show_info_handler.h index 3b0853f988a7b4eeb84002afb873790e38904838..0490c6fb46c58ad4f299250563d5a5944504d6ec 100644 --- a/src/obproxy/cmd/ob_show_info_handler.h +++ b/src/obproxy/cmd/ob_show_info_handler.h @@ -34,8 +34,7 @@ namespace proxy class ObShowInfoHandler : public ObInternalCmdHandler { public: - ObShowInfoHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObShowInfoHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObShowInfoHandler() {}; private: diff --git a/src/obproxy/cmd/ob_show_memory_handler.h b/src/obproxy/cmd/ob_show_memory_handler.h index af0ce1eb8843e51172ea395d3b55b3167a1074d0..0aa9dcd13ca166c006e426d3881015a51f408717 100644 --- a/src/obproxy/cmd/ob_show_memory_handler.h +++ b/src/obproxy/cmd/ob_show_memory_handler.h @@ -29,8 +29,7 @@ namespace obutils class ObShowMemoryHandler : public ObInternalCmdHandler { public: - ObShowMemoryHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObShowMemoryHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObShowMemoryHandler() {} int handle_show_memory(int event, void *data); int handle_show_objpool(int event, void *data); diff --git a/src/obproxy/cmd/ob_show_net_handler.cpp b/src/obproxy/cmd/ob_show_net_handler.cpp index 6e58cb51250989def5af803cfc5e373cccadf844..c898e90e8a9ba2ea85904059c9414026074d99ba 100644 --- a/src/obproxy/cmd/ob_show_net_handler.cpp +++ b/src/obproxy/cmd/ob_show_net_handler.cpp @@ -139,8 +139,7 @@ const ObProxyColumnSchema CONN_COLUMN_ARRAY[OB_CC_MAX_CONN_COLUMN_ID] = { ObProxyColumnSchema::make_schema(OB_CC_COMMENTS, "comments", OB_MYSQL_TYPE_VARCHAR) }; -ObShowNetHandler::ObShowNetHandler(ObContinuation *cont, ObMIOBuffer *buf, - const ObInternalCmdInfo &info) +ObShowNetHandler::ObShowNetHandler(ObContinuation *cont, ObMIOBuffer *buf, const ObInternalCmdInfo &info) : ObInternalCmdHandler(cont, buf, info), thread_id_(info.get_thread_id()), limit_rows_(info.get_limit_rows()), limit_offset_(info.get_limit_offset()), next_thread_id_(0) { diff --git a/src/obproxy/cmd/ob_show_net_handler.h b/src/obproxy/cmd/ob_show_net_handler.h index a8772e6521b2b5795c0b2b24c8eae42ab5240e83..ebe6f6b9ac0ae0cda59dc26f4081ee99b8bfa55f 100644 --- a/src/obproxy/cmd/ob_show_net_handler.h +++ b/src/obproxy/cmd/ob_show_net_handler.h @@ -26,8 +26,7 @@ class ObNetHandler; class ObShowNetHandler : public ObInternalCmdHandler { public: - ObShowNetHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObShowNetHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObShowNetHandler() {} int handle_show_threads(int event, event::ObEvent *e); int handle_show_connections(int event, event::ObEvent *e); diff --git a/src/obproxy/cmd/ob_show_resource_handler.cpp b/src/obproxy/cmd/ob_show_resource_handler.cpp index d4ad0154a0704cb6284342124eb58da4918feffc..ba8afbebf733090f332408bd7799701981274116 100644 --- a/src/obproxy/cmd/ob_show_resource_handler.cpp +++ b/src/obproxy/cmd/ob_show_resource_handler.cpp @@ -66,8 +66,7 @@ const ObProxyColumnSchema RESOURCE_COLUMN_ARRAY[OB_CR_MAX_RESOURCE_COLUMN_ID] = ObProxyColumnSchema::make_schema(OB_CR_LAST_FETCH_IDC_LIST_TIME_STR, "last_fetch_idc_list_time", obmysql::OB_MYSQL_TYPE_VARCHAR), }; -ObShowResourceHandler::ObShowResourceHandler(ObContinuation *cont, ObMIOBuffer *buf, - const ObInternalCmdInfo &info) +ObShowResourceHandler::ObShowResourceHandler(ObContinuation *cont, ObMIOBuffer *buf, const ObInternalCmdInfo &info) : ObInternalCmdHandler(cont, buf, info) { SET_HANDLER(&ObShowResourceHandler::handle_show_resource); diff --git a/src/obproxy/cmd/ob_show_resource_handler.h b/src/obproxy/cmd/ob_show_resource_handler.h index 4cf1080718e298d5660df44f6dc8485cabec1c49..14f0c72e2c95f166eb78177b4ce7b488d2080f2e 100644 --- a/src/obproxy/cmd/ob_show_resource_handler.h +++ b/src/obproxy/cmd/ob_show_resource_handler.h @@ -25,9 +25,7 @@ class ObClusterResource; class ObShowResourceHandler : public ObInternalCmdHandler { public: - ObShowResourceHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); - + ObShowResourceHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObShowResourceHandler() {} int handle_show_resource(int event, void *data); diff --git a/src/obproxy/cmd/ob_show_route_handler.cpp b/src/obproxy/cmd/ob_show_route_handler.cpp index 7d177fb95a104f1b2334bacd71244cb9d77bf95c..fcbc499669cfeb1abb9e6505877e85e48316df7e 100644 --- a/src/obproxy/cmd/ob_show_route_handler.cpp +++ b/src/obproxy/cmd/ob_show_route_handler.cpp @@ -157,8 +157,7 @@ int extract_entry_time(const ObRouteEntry &entry, char *create_timebuf, char *va char *access_timebuf, char *update_timebuf, char *expire_timebuf, char *relative_expire_timebuf, const uint32_t buf_len); -ObShowRouteHandler::ObShowRouteHandler(ObContinuation *cont, ObMIOBuffer *buf, - const ObInternalCmdInfo &info) +ObShowRouteHandler::ObShowRouteHandler(ObContinuation *cont, ObMIOBuffer *buf, const ObInternalCmdInfo &info) : ObInternalCmdHandler(cont, buf, info), sub_type_(info.get_sub_cmd_type()), list_bucket_(0) { if (!info.get_large_key_string().empty()) { @@ -464,8 +463,6 @@ int ObShowRouteHandler::dump_table_item(const ObTableEntry &entry) int ret = OB_SUCCESS; const int64_t count = entry.get_server_count(); ObSqlString server_addr; - uint32_t ipv4 = 0; - int32_t port = 0; ObRole role = INVALID_ROLE; ObReplicaType replica_type = REPLICA_TYPE_MAX; const ObTenantServer *ts = NULL; @@ -480,30 +477,24 @@ int ObShowRouteHandler::dump_table_item(const ObTableEntry &entry) part_info = entry.get_part_info(); } for (int64_t i = 0; i < count && OB_SUCC(ret); ++i) { + char ip_port_buf[MAX_IP_ADDR_LENGTH]; + memset(ip_port_buf, 0, sizeof(ip_port_buf)); if (NULL != ts) { - ipv4 = ts->get_replica_location(i)->server_.get_ipv4(); - port = ts->get_replica_location(i)->server_.get_port(); role = ts->get_replica_location(i)->role_; replica_type = ts->get_replica_location(i)->replica_type_; + ts->get_replica_location(i)->server_.ip_port_to_string(ip_port_buf, sizeof(ip_port_buf)); } else if (NULL != pl) { - ipv4 = pl->get_replica(i)->server_.get_ipv4(); - port = pl->get_replica(i)->server_.get_port(); role = pl->get_replica(i)->role_; replica_type = pl->get_replica(i)->replica_type_; + pl->get_replica(i)->server_.ip_port_to_string(ip_port_buf, sizeof(ip_port_buf)); } else { - ipv4 = 0; - port = -1; role = INVALID_ROLE; replica_type = REPLICA_TYPE_MAX; } const ObString &string = ObProxyReplicaLocation::get_replica_type_string(replica_type); - if (OB_FAIL(server_addr.append_fmt("server[%ld]=%d.%d.%d.%d:%d,%s,%.*s; ", + if (OB_FAIL(server_addr.append_fmt("server[%ld]=%s,%s,%.*s; ", i, - (ipv4 >> 24) & 0XFF, - (ipv4 >> 16) & 0xFF, - (ipv4 >> 8) & 0xFF, - (ipv4) & 0xFF, - port, + ip_port_buf, role2str(role), string.length(), string.ptr()))) { WARN_ICMD("fail to append server_addr", K(i), K(ret)); @@ -675,24 +666,18 @@ int ObShowRouteHandler::dump_partition_item(const ObPartitionEntry &entry) int ret = OB_SUCCESS; const int64_t count = entry.get_server_count(); ObSqlString server_addr; - uint32_t ipv4 = 0; - int32_t port = 0; ObRole role = INVALID_ROLE; ObReplicaType replica_type = REPLICA_TYPE_MAX; const ObProxyPartitionLocation &pl = entry.get_pl(); for (int64_t i = 0; i < count && OB_SUCC(ret); ++i) { - ipv4 = pl.get_replica(i)->server_.get_ipv4(); - port = pl.get_replica(i)->server_.get_port(); role = pl.get_replica(i)->role_; replica_type = pl.get_replica(i)->replica_type_; const ObString &string = ObProxyReplicaLocation::get_replica_type_string(replica_type); - if (OB_FAIL(server_addr.append_fmt("server[%ld]=%d.%d.%d.%d:%d,%s,%.*s; ", + char ip_port_buf[MAX_IP_ADDR_LENGTH]; + pl.get_replica(i)->server_.ip_port_to_string(ip_port_buf, sizeof(ip_port_buf)); + if (OB_FAIL(server_addr.append_fmt("server[%ld]=%s,%s,%.*s; ", i, - (ipv4 >> 24) & 0XFF, - (ipv4 >> 16) & 0xFF, - (ipv4 >> 8) & 0xFF, - (ipv4) & 0xFF, - port, + ip_port_buf, role2str(role), string.length(), string.ptr()))) { WARN_ICMD("fail to append server_addr", K(i), K(ret)); diff --git a/src/obproxy/cmd/ob_show_route_handler.h b/src/obproxy/cmd/ob_show_route_handler.h index 439110e69306d0c0248b7904405247687aa37210..0111570e17bafa5eb541c2e3a1b05e6f006ee495 100644 --- a/src/obproxy/cmd/ob_show_route_handler.h +++ b/src/obproxy/cmd/ob_show_route_handler.h @@ -27,8 +27,7 @@ namespace proxy class ObShowRouteHandler : public ObInternalCmdHandler { public: - ObShowRouteHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObShowRouteHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObShowRouteHandler() {} int handle_show_table(int event, void *data); int handle_show_partition(int event, void *data); diff --git a/src/obproxy/cmd/ob_show_session_handler.cpp b/src/obproxy/cmd/ob_show_session_handler.cpp index 679eb6aa739f98794400cc44ea9e6daff0204693..3f95612ba29f22107faca7a5f780cd592850fa50 100644 --- a/src/obproxy/cmd/ob_show_session_handler.cpp +++ b/src/obproxy/cmd/ob_show_session_handler.cpp @@ -137,8 +137,7 @@ const ObProxyColumnSchema STAT_COLUMN_ARRAY[OB_SSC_MAX_STAT_COLUMN_ID] ObProxyColumnSchema::make_schema(OB_SSC_VALUE, "value", OB_MYSQL_TYPE_LONGLONG), }; -ObShowSessionHandler::ObShowSessionHandler(ObContinuation *cont, ObMIOBuffer *buf, - const ObInternalCmdInfo &info) +ObShowSessionHandler::ObShowSessionHandler(ObContinuation *cont, ObMIOBuffer *buf, const ObInternalCmdInfo &info) : ObInternalCmdHandler(cont, buf, info), sub_type_(info.get_sub_cmd_type()), list_bucket_(0), cs_id_array_() { diff --git a/src/obproxy/cmd/ob_show_session_handler.h b/src/obproxy/cmd/ob_show_session_handler.h index 3372cd7ad0d63be0404fa046e31ba4fd04a38442..9de2d98156eac8c11e003cd3419d900fe9e8db00 100644 --- a/src/obproxy/cmd/ob_show_session_handler.h +++ b/src/obproxy/cmd/ob_show_session_handler.h @@ -45,8 +45,7 @@ enum ObServerSessionType class ObShowSessionHandler : public ObInternalCmdHandler { public: - ObShowSessionHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObShowSessionHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObShowSessionHandler() { cs_id_array_.destroy(); } int handle_cs_list(int event, void *data); int handle_cs_details(int event, void *data); diff --git a/src/obproxy/cmd/ob_show_sm_handler.cpp b/src/obproxy/cmd/ob_show_sm_handler.cpp index 9fe5f18f369931196585a43ea11b73a705f5e405..dc87665fd72a4b03cdb71bb66f37b9fe54a6a1d3 100644 --- a/src/obproxy/cmd/ob_show_sm_handler.cpp +++ b/src/obproxy/cmd/ob_show_sm_handler.cpp @@ -50,8 +50,7 @@ const ObProxyColumnSchema SM_COLUMN_ARRAY[OB_SMC_MAX_SM_COLUMN_ID] = { ObProxyColumnSchema::make_schema(OB_SMC_SM_INFO, "sm_info", obmysql::OB_MYSQL_TYPE_VARCHAR), }; -ObShowSMHandler::ObShowSMHandler(ObContinuation *cont, ObMIOBuffer *buf, - const ObInternalCmdInfo &info) +ObShowSMHandler::ObShowSMHandler(ObContinuation *cont, ObMIOBuffer *buf, const ObInternalCmdInfo &info) : ObInternalCmdHandler(cont, buf, info), is_hash_set_inited_(false), list_bucket_(0), sm_id_(info.get_sm_id()) { diff --git a/src/obproxy/cmd/ob_show_sm_handler.h b/src/obproxy/cmd/ob_show_sm_handler.h index 3d4d3667273badecd9cd501a85382bb379208970..7546a5df1b0b1c4a40e482387af087fca49c1f34 100644 --- a/src/obproxy/cmd/ob_show_sm_handler.h +++ b/src/obproxy/cmd/ob_show_sm_handler.h @@ -29,8 +29,7 @@ namespace proxy class ObShowSMHandler : public ObInternalCmdHandler { public: - ObShowSMHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObShowSMHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObShowSMHandler() { got_id_set_.destroy(); } int dump_smlist(); int init_hash_set(); //now only show smlist need init diff --git a/src/obproxy/cmd/ob_show_sqlaudit_handler.cpp b/src/obproxy/cmd/ob_show_sqlaudit_handler.cpp index e24963dc448a1a86f6abc148254e8369b90044c5..73a7282b220b60b178770cf60b8fe04d5c2a6408 100644 --- a/src/obproxy/cmd/ob_show_sqlaudit_handler.cpp +++ b/src/obproxy/cmd/ob_show_sqlaudit_handler.cpp @@ -368,9 +368,10 @@ enum OB_SSA_SERVER_SEND_SAVED_LOGIN_TIME, OB_SSA_SERVER_SEND_USE_DATABASE_TIME, OB_SSA_SERVER_SEND_SESSION_VARIABLE_TIME, + OB_SSA_SERVER_SEND_SESSION_USER_VARIABLE_TIME, OB_SSA_SERVER_SEND_ALL_SESSION_VARIABLE_TIME, - OB_SSA_SERVER_SEND_LAST_INSERT_ID_TIME, OB_SSA_SERVER_SEND_START_TRANS_TIME, + OB_SSA_SERVER_SEND_XA_START_TIME, OB_SSA_BUILD_SERVER_REQUEST_TIME, OB_SSA_PLUGIN_COMPRESS_REQUEST_TIME, OB_SSA_PREPARE_SEND_REQUEST_TO_SERVER_TIME, @@ -408,9 +409,10 @@ const ObProxyColumnSchema SSA_COLUMN_ARRAY[OB_SSA_MAX_COLUMN_ID] = { ObProxyColumnSchema::make_schema(OB_SSA_SERVER_SEND_SAVED_LOGIN_TIME, "server_send_saved_login_ns", obmysql::OB_MYSQL_TYPE_LONG), ObProxyColumnSchema::make_schema(OB_SSA_SERVER_SEND_USE_DATABASE_TIME, "server_send_use_database_ns", obmysql::OB_MYSQL_TYPE_LONG), ObProxyColumnSchema::make_schema(OB_SSA_SERVER_SEND_SESSION_VARIABLE_TIME, "server_send_session_variable_ns", obmysql::OB_MYSQL_TYPE_LONG), + ObProxyColumnSchema::make_schema(OB_SSA_SERVER_SEND_SESSION_USER_VARIABLE_TIME, "server_send_session_user_variable_ns", obmysql::OB_MYSQL_TYPE_LONG), ObProxyColumnSchema::make_schema(OB_SSA_SERVER_SEND_ALL_SESSION_VARIABLE_TIME, "server_send_all_session_variable_ns", obmysql::OB_MYSQL_TYPE_LONG), - ObProxyColumnSchema::make_schema(OB_SSA_SERVER_SEND_LAST_INSERT_ID_TIME, "server_send_last_insert_id_ns", obmysql::OB_MYSQL_TYPE_LONG), ObProxyColumnSchema::make_schema(OB_SSA_SERVER_SEND_START_TRANS_TIME, "server_send_start_trans_ns", obmysql::OB_MYSQL_TYPE_LONG), + ObProxyColumnSchema::make_schema(OB_SSA_SERVER_SEND_XA_START_TIME, "server_send_xa_start_ns", obmysql::OB_MYSQL_TYPE_LONG), ObProxyColumnSchema::make_schema(OB_SSA_BUILD_SERVER_REQUEST_TIME, "build_server_request_ns", obmysql::OB_MYSQL_TYPE_LONG), ObProxyColumnSchema::make_schema(OB_SSA_PLUGIN_COMPRESS_REQUEST_TIME, "plugin_compress_request_ns", obmysql::OB_MYSQL_TYPE_LONG), ObProxyColumnSchema::make_schema(OB_SSA_PREPARE_SEND_REQUEST_TO_SERVER_TIME, "prepare_send_request_to_server_ns", obmysql::OB_MYSQL_TYPE_LONG), @@ -424,8 +426,7 @@ const ObProxyColumnSchema SSA_COLUMN_ARRAY[OB_SSA_MAX_COLUMN_ID] = { ObProxyColumnSchema::make_schema(OB_SSA_REQUEST_TOTAL_TIME, "request_total_ns", obmysql::OB_MYSQL_TYPE_LONG) }; -ObShowSqlauditHandler::ObShowSqlauditHandler(ObContinuation *cont, ObMIOBuffer *buf, - const ObInternalCmdInfo &info) +ObShowSqlauditHandler::ObShowSqlauditHandler(ObContinuation *cont, ObMIOBuffer *buf, const ObInternalCmdInfo &info) : ObInternalCmdHandler(cont, buf, info), audit_id_offset_(info.get_limit_offset()), audit_id_limit_(info.get_limit_rows()), sm_id_(info.get_sm_id()), sub_cmd_type_(info.get_sub_cmd_type()) @@ -550,9 +551,10 @@ int ObShowSqlauditHandler::dump_sqlaudit_record(ObSqlauditRecord &record) cells[OB_SSA_SERVER_SEND_SAVED_LOGIN_TIME].set_int(record.cmd_time_stat_.server_send_saved_login_time_); cells[OB_SSA_SERVER_SEND_USE_DATABASE_TIME].set_int(record.cmd_time_stat_.server_send_use_database_time_); cells[OB_SSA_SERVER_SEND_SESSION_VARIABLE_TIME].set_int(record.cmd_time_stat_.server_send_session_variable_time_); + cells[OB_SSA_SERVER_SEND_SESSION_USER_VARIABLE_TIME].set_int(record.cmd_time_stat_.server_send_session_user_variable_time_); cells[OB_SSA_SERVER_SEND_ALL_SESSION_VARIABLE_TIME].set_int(record.cmd_time_stat_.server_send_all_session_variable_time_); - cells[OB_SSA_SERVER_SEND_LAST_INSERT_ID_TIME].set_int(record.cmd_time_stat_.server_send_last_insert_id_time_); cells[OB_SSA_SERVER_SEND_START_TRANS_TIME].set_int(record.cmd_time_stat_.server_send_start_trans_time_); + cells[OB_SSA_SERVER_SEND_XA_START_TIME].set_int(record.cmd_time_stat_.server_send_xa_start_time_); cells[OB_SSA_BUILD_SERVER_REQUEST_TIME].set_int(record.cmd_time_stat_.build_server_request_time_); cells[OB_SSA_PLUGIN_COMPRESS_REQUEST_TIME].set_int(record.cmd_time_stat_.plugin_compress_request_time_); cells[OB_SSA_PLUGIN_DECOMPRESS_RESPONSE_TIME].set_int(record.cmd_time_stat_.plugin_decompress_response_time_); diff --git a/src/obproxy/cmd/ob_show_sqlaudit_handler.h b/src/obproxy/cmd/ob_show_sqlaudit_handler.h index 7f9a44ea488eaf8d121806815baa87fdca6ac9a2..14ffc2f5fd0734d8b07c310576f7e639d5b828e3 100644 --- a/src/obproxy/cmd/ob_show_sqlaudit_handler.h +++ b/src/obproxy/cmd/ob_show_sqlaudit_handler.h @@ -150,8 +150,7 @@ private: class ObShowSqlauditHandler : public ObInternalCmdHandler { public: - ObShowSqlauditHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObShowSqlauditHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObShowSqlauditHandler() { } int handle_show_sqlaudit(int event, event::ObEvent *e); diff --git a/src/obproxy/cmd/ob_show_stat_handler.h b/src/obproxy/cmd/ob_show_stat_handler.h index c61dae44afbc00140cc8b103bb9df1a354d241b2..df5365e723b6e3857bba21b6820217554965aff0 100644 --- a/src/obproxy/cmd/ob_show_stat_handler.h +++ b/src/obproxy/cmd/ob_show_stat_handler.h @@ -25,8 +25,7 @@ namespace obutils class ObShowStatHandler : public ObInternalCmdHandler { public: - ObShowStatHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObShowStatHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObShowStatHandler() {} private: diff --git a/src/obproxy/cmd/ob_show_table_status_handler.cpp b/src/obproxy/cmd/ob_show_table_status_handler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3feba8ddaf6801cf951c6bb2365d6a52b1fa22f7 --- /dev/null +++ b/src/obproxy/cmd/ob_show_table_status_handler.cpp @@ -0,0 +1,181 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#define USING_LOG_PREFIX PROXY_CMD + +#include "cmd/ob_show_table_status_handler.h" +#include "proxy/shard/obproxy_shard_utils.h" +#include "lib/container/ob_array_iterator.h" + +using namespace oceanbase::obproxy::event; +using namespace oceanbase::obproxy::proxy; +using namespace oceanbase::obmysql; + +namespace oceanbase +{ +namespace obproxy +{ +namespace obutils +{ + +enum +{ + OB_STS_NAME = 0, + OB_STS_ENGINE, + OB_STS_VERSION, + OB_STS_ROW_FORMAT, + OB_STS_ROWS, + OB_STS_AVG_ROW_LENGTH, + OB_STS_DATA_LENGTH, + OB_STS_MAX_DATA_LENGTH, + OB_STS_INDEX_LENGTH, + OB_STS_DATA_FREE, + OB_STS_AUTO_INCREMENT, + OB_STS_CREATE_TIME, + OB_STS_UPDATE_TIME, + OB_STS_CHECK_TIME, + OB_STS_COLLATION, + OB_STS_CHECKSUM, + OB_STS_CREATE_OPTIONS, + OB_STS_COMMENT, + OB_STS_MAX_COLUMN_ID, +}; + +const ObProxyColumnSchema SHOW_TABLE_STATUS_ARRAY[OB_STS_MAX_COLUMN_ID] = { + ObProxyColumnSchema::make_schema(OB_STS_NAME, "Name", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_STS_ENGINE, "Engine", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_STS_VERSION, "Version", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_STS_ROW_FORMAT, "Row_format", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_STS_ROWS, "Rows", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_STS_AVG_ROW_LENGTH, "Avg_row_length", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_STS_DATA_LENGTH, "Data_length", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_STS_MAX_DATA_LENGTH, "Max_data_length", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_STS_INDEX_LENGTH, "Index_length", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_STS_DATA_FREE, "Data_free", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_STS_AUTO_INCREMENT, "Auto_increment", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_STS_CREATE_TIME, "Create_time", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_STS_UPDATE_TIME, "Update_time", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_STS_CHECK_TIME, "Check_time", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_STS_COLLATION, "Collation", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_STS_CHECKSUM, "Checksum", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_STS_CREATE_OPTIONS, "Create_options", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_STS_COMMENT, "Comment", OB_MYSQL_TYPE_VARCHAR), +}; + +ObShowTableStatusHandler::ObShowTableStatusHandler(ObMIOBuffer *buf, ObCmdInfo &info) + : ObCmdHandler(buf, info) +{ +} + +int ObShowTableStatusHandler::handle_show_table_status(const ObString &logic_tenant_name, const ObString &logic_database_name, + ObString &logic_table_name) +{ + int ret = OB_SUCCESS; + + if (OB_FAIL(encode_header(SHOW_TABLE_STATUS_ARRAY, OB_STS_MAX_COLUMN_ID))) { + WARN_CMD("fail to dump tables header", K(ret)); + } else if (OB_FAIL(dump_table(logic_tenant_name, logic_database_name, logic_table_name))) { + WARN_CMD("fail to dump tables", K(ret)); + } else if (OB_FAIL(encode_eof_packet())) { + WARN_CMD("fail to encode eof packet", K(ret)); + } else { + INFO_CMD("succ to build show table status"); + } + + if (OB_FAIL(ret)) { + if (OB_FAIL(encode_err_packet(ret))) { + WARN_CMD("fail to encode internal err packet, callback", K(ret)); + } else { + INFO_CMD("succ to encode internal err packet, callback"); + ret = OB_SUCCESS; + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(fill_external_buf())) { + WARN_CMD("fail to fill_external_buf", K(ret)); + } + } + return ret; +} + +int ObShowTableStatusHandler::dump_table(const ObString &logic_tenant_name, const ObString &logic_database_name, + ObString &logic_table_name) +{ + int ret = OB_SUCCESS; + typedef ObArray ObStringArray; + ObStringArray table_names; + ObNewRow row; + ObObj cells[OB_STS_MAX_COLUMN_ID]; + + if (OB_FAIL(ObProxyShardUtils::get_all_schema_table(logic_tenant_name, logic_database_name, table_names))) { + WARN_CMD("fail to get all tables", K(logic_tenant_name), K(ret)); + } else { + string_to_upper_case(logic_table_name.ptr(), logic_table_name.length()); + for (ObStringArray::iterator it = table_names.begin(); OB_SUCC(ret) && it != table_names.end(); it++) { + if (match_like(*it, logic_table_name)) { + cells[OB_STS_NAME].set_varchar(*it); + cells[OB_STS_ENGINE].set_varchar("Innodb"); + cells[OB_STS_VERSION].set_varchar("10"); + cells[OB_STS_ROW_FORMAT].set_varchar("Dynamic"); + cells[OB_STS_ROWS].set_varchar("0"); + cells[OB_STS_AVG_ROW_LENGTH].set_varchar("0"); + cells[OB_STS_DATA_LENGTH].set_varchar("0"); + cells[OB_STS_MAX_DATA_LENGTH].set_varchar("0"); + cells[OB_STS_INDEX_LENGTH].set_varchar("0"); + cells[OB_STS_DATA_FREE].set_varchar("0"); + cells[OB_STS_AUTO_INCREMENT].set_varchar("NULL"); + cells[OB_STS_CREATE_TIME].set_varchar("NULL"); + cells[OB_STS_UPDATE_TIME].set_varchar("NULL"); + cells[OB_STS_CHECK_TIME].set_varchar("NULL"); + cells[OB_STS_COLLATION].set_varchar(""); + cells[OB_STS_CHECKSUM].set_varchar(""); + cells[OB_STS_CREATE_OPTIONS].set_varchar(""); + cells[OB_STS_COMMENT].set_varchar(""); + + row.cells_ = cells; + row.count_ = OB_STS_MAX_COLUMN_ID; + if (OB_FAIL(encode_row_packet(row))) { + WARN_CMD("fail to encode row packet", K(row), K(ret)); + } + } + } + } + return ret; +} + +int ObShowTableStatusHandler::show_table_status_cmd_callback(ObMIOBuffer *buf, ObCmdInfo &info, + const ObString &logic_tenant_name, const ObString &logic_database_name, + ObString &logic_table_name) +{ + int ret = OB_SUCCESS; + ObShowTableStatusHandler *handler = NULL; + + if (OB_ISNULL(handler = new(std::nothrow) ObShowTableStatusHandler(buf, info))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + ERROR_CMD("fail to new ObShowTableStatusHandler", K(ret)); + } else if (OB_FAIL(handler->init())) { + WARN_CMD("fail to init for ObShowTableStatusHandler"); + } else if (OB_FAIL(handler->handle_show_table_status(logic_tenant_name, logic_database_name, logic_table_name))) { + DEBUG_CMD("succ to schedule ObShowTableStatusHandler"); + } + + if (OB_LIKELY(NULL != handler)) { + delete handler; + handler = NULL; + } + return ret; +} + +} // end of namespace obutils +} // end of namespace obproxy +} // end of namespace oceanbase diff --git a/src/obproxy/cmd/ob_show_table_status_handler.h b/src/obproxy/cmd/ob_show_table_status_handler.h new file mode 100644 index 0000000000000000000000000000000000000000..a84f684e9b003fab1740088f38c66507d3b74f01 --- /dev/null +++ b/src/obproxy/cmd/ob_show_table_status_handler.h @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef OBPROXY_SHOW_TABLE_STATUS_HANDLER_H +#define OBPROXY_SHOW_TABLE_STATUS_HANDLER_H + +#include "cmd/ob_cmd_handler.h" + +namespace oceanbase +{ +namespace obproxy +{ +namespace obutils +{ +class ObShowTableStatusHandler : public ObCmdHandler +{ +public: + ObShowTableStatusHandler(event::ObMIOBuffer *buf, ObCmdInfo &info); + virtual ~ObShowTableStatusHandler() {} + int handle_show_table_status(const ObString &logic_tenant_name, const ObString &logic_database_name, + ObString &logic_table_name); + + static int show_table_status_cmd_callback(event::ObMIOBuffer *buf, ObCmdInfo &info, + const ObString &logic_tenant_name, const ObString &logic_database_name, + ObString &logic_table_name); + +private: + int dump_table(const ObString &logic_tenant_name, const ObString &logic_database_name, + ObString &logic_table_name); + + DISALLOW_COPY_AND_ASSIGN(ObShowTableStatusHandler); +}; +} // end of namespace obutils +} // end of namespace obproxy +} // end of namespace oceanbase + +#endif /* OBPROXY_SHOW_TABLE_STATUS_HANDLER_H */ diff --git a/src/obproxy/cmd/ob_show_tables_handler.cpp b/src/obproxy/cmd/ob_show_tables_handler.cpp index 0adf58fd78a88679455509ae9f3fb7118dcb2392..f74bc468f2230c9efefbce5aee341cadf24c1513 100644 --- a/src/obproxy/cmd/ob_show_tables_handler.cpp +++ b/src/obproxy/cmd/ob_show_tables_handler.cpp @@ -29,21 +29,23 @@ namespace obutils enum { OB_CC_NAME = 0, + OB_CC_TYPE, OB_CC_MAX_TABLE_COLUMN_ID, }; -ObShowTablesHandler::ObShowTablesHandler(ObMIOBuffer *buf, uint8_t pkg_seq, int64_t memory_limit) - : ObCmdHandler(buf, pkg_seq, memory_limit) +ObShowTablesHandler::ObShowTablesHandler(ObMIOBuffer *buf, ObCmdInfo &info, ObProxyBasicStmtSubType sub_type) + : ObCmdHandler(buf, info), sub_type_(sub_type) { } -int ObShowTablesHandler::handle_show_tables(const ObString &logic_tenant_name, const ObString &logic_database_name) +int ObShowTablesHandler::handle_show_tables(const ObString &logic_tenant_name, const ObString &logic_database_name, + ObString &logic_table_name) { int ret = OB_SUCCESS; if (OB_FAIL(dump_table_header(logic_database_name))) { WARN_CMD("fail to dump tables header", K(ret)); - } else if (OB_FAIL(dump_table(logic_tenant_name, logic_database_name))) { + } else if (OB_FAIL(dump_table(logic_tenant_name, logic_database_name, logic_table_name))) { WARN_CMD("fail to dump tables", K(ret)); } else if (OB_FAIL(encode_eof_packet())) { WARN_CMD("fail to encode eof packet", K(ret)); @@ -72,54 +74,77 @@ int ObShowTablesHandler::dump_table_header(const ObString &logic_database_name) { int ret = OB_SUCCESS; + ObProxyColumnSchema SHOW_TABLES_ARRAY[OB_CC_MAX_TABLE_COLUMN_ID] = { + ObProxyColumnSchema::make_schema(OB_CC_NAME, "", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_CC_TYPE, "Table_type", OB_MYSQL_TYPE_VARCHAR), + }; + char column_name[OB_MAX_DATABASE_NAME_LENGTH] = "Tables_in_"; logic_database_name.to_string(column_name + strlen(column_name), OB_MAX_DATABASE_NAME_LENGTH - strlen(column_name)); + SHOW_TABLES_ARRAY[0].cname_ = ObString(column_name); - const ObString &column_name_str = ObString(column_name); - const EMySQLFieldType column_type = OB_MYSQL_TYPE_VARCHAR; + int64_t size = OB_CC_MAX_TABLE_COLUMN_ID; + if (OBPROXY_T_SUB_SHOW_TABLES == sub_type_) { + size = OB_CC_MAX_TABLE_COLUMN_ID - 1; + } - if (OB_FAIL(encode_header(&column_name_str, &column_type, OB_CC_MAX_TABLE_COLUMN_ID))) { + if (OB_FAIL(encode_header(SHOW_TABLES_ARRAY, size))) { WARN_CMD("fail to encode header", K(ret)); } return ret; } -int ObShowTablesHandler::dump_table(const ObString &logic_tenant_name, const ObString &logic_database_name) +int ObShowTablesHandler::dump_table(const ObString &logic_tenant_name, const ObString &logic_database_name, + ObString &logic_table_name) { int ret = OB_SUCCESS; typedef ObArray ObStringArray; ObStringArray table_names; ObNewRow row; ObObj cells[OB_CC_MAX_TABLE_COLUMN_ID]; + int64_t size = OB_CC_MAX_TABLE_COLUMN_ID; + if (OBPROXY_T_SUB_SHOW_TABLES == sub_type_) { + size = OB_CC_MAX_TABLE_COLUMN_ID - 1; + } if (OB_FAIL(ObProxyShardUtils::get_all_schema_table(logic_tenant_name, logic_database_name, table_names))) { WARN_CMD("fail to get all tables", K(logic_tenant_name), K(ret)); } else { - for (ObStringArray::iterator it = table_names.begin(); it != table_names.end(); it++) { - cells[OB_CC_NAME].set_varchar(*it); - - row.cells_ = cells; - row.count_ = OB_CC_MAX_TABLE_COLUMN_ID; - if (OB_FAIL(encode_row_packet(row))) { - WARN_CMD("fail to encode row packet", K(row), K(ret)); + string_to_upper_case(logic_table_name.ptr(), logic_table_name.length()); + for (ObStringArray::iterator it = table_names.begin(); OB_SUCC(ret) && it != table_names.end(); it++) { + if (match_like(*it, logic_table_name)) { + cells[OB_CC_NAME].set_varchar(*it); + if (OBPROXY_T_SUB_SHOW_FULL_TABLES == sub_type_) { + cells[OB_CC_TYPE].set_varchar("BASE TABLE"); + } + + row.cells_ = cells; + row.count_ = size; + if (OB_FAIL(encode_row_packet(row))) { + WARN_CMD("fail to encode row packet", K(row), K(ret)); + } } } } return ret; } -int ObShowTablesHandler::show_tables_cmd_callback(ObMIOBuffer *buf, uint8_t pkg_seq, int64_t memory_limit, const ObString &logic_tenant_name, const ObString &logic_database_name) +int ObShowTablesHandler::show_tables_cmd_callback(ObMIOBuffer *buf, ObCmdInfo &info, + ObProxyBasicStmtSubType sub_type, + const ObString &logic_tenant_name, + const ObString &logic_database_name, + ObString &logic_table_name) { int ret = OB_SUCCESS; ObShowTablesHandler *handler = NULL; - if (OB_ISNULL(handler = new(std::nothrow) ObShowTablesHandler(buf, pkg_seq, memory_limit))) { + if (OB_ISNULL(handler = new(std::nothrow) ObShowTablesHandler(buf, info, sub_type))) { ret = OB_ALLOCATE_MEMORY_FAILED; ERROR_CMD("fail to new ObShowTablesHandler", K(ret)); } else if (OB_FAIL(handler->init())) { WARN_CMD("fail to init for ObShowTablesHandler"); - } else if (OB_FAIL(handler->handle_show_tables(logic_tenant_name, logic_database_name))) { + } else if (OB_FAIL(handler->handle_show_tables(logic_tenant_name, logic_database_name, logic_table_name))) { DEBUG_CMD("succ to schedule ObShowTablesHandler"); } diff --git a/src/obproxy/cmd/ob_show_tables_handler.h b/src/obproxy/cmd/ob_show_tables_handler.h index c8419b8ab5289cf6646c2b5ec7146d369c3a58cc..104c6b8dd007b59dff8705dcc26f256cc9805e74 100644 --- a/src/obproxy/cmd/ob_show_tables_handler.h +++ b/src/obproxy/cmd/ob_show_tables_handler.h @@ -24,15 +24,22 @@ namespace obutils class ObShowTablesHandler : public ObCmdHandler { public: - ObShowTablesHandler(event::ObMIOBuffer *buf, uint8_t pkg_seq, int64_t memory_limit); + ObShowTablesHandler(event::ObMIOBuffer *buf, ObCmdInfo &info, ObProxyBasicStmtSubType sub_type); virtual ~ObShowTablesHandler() {} - int handle_show_tables(const ObString &logic_tenant_name, const ObString &logic_database_name); + int handle_show_tables(const ObString &logic_tenant_name, const ObString &logic_database_name, + ObString &logic_table_name); - static int show_tables_cmd_callback(event::ObMIOBuffer *buf, uint8_t pkg_seq, int64_t memory_limit, const ObString &logic_tenant_name, const ObString &logic_database_name); + static int show_tables_cmd_callback(event::ObMIOBuffer *buf, ObCmdInfo &info, ObProxyBasicStmtSubType sub_type, + const ObString &logic_tenant_name, const ObString &logic_database_name, + ObString &logic_table_name); private: int dump_table_header(const ObString &logic_database_name); - int dump_table(const ObString &logic_tenant_name, const ObString &logic_database_name); + int dump_table(const ObString &logic_tenant_name, const ObString &logic_database_name, + ObString &logic_table_name); + +private: + ObProxyBasicStmtSubType sub_type_; DISALLOW_COPY_AND_ASSIGN(ObShowTablesHandler); }; diff --git a/src/obproxy/cmd/ob_show_topology_handler.cpp b/src/obproxy/cmd/ob_show_topology_handler.cpp index 135bb807242549d5546c5e4c3fe7d8ac465594b1..341ee436848b3f243c541ca71bb05f1296ba1e78 100644 --- a/src/obproxy/cmd/ob_show_topology_handler.cpp +++ b/src/obproxy/cmd/ob_show_topology_handler.cpp @@ -13,8 +13,8 @@ #define USING_LOG_PREFIX PROXY_CMD #include "cmd/ob_show_topology_handler.h" -#include "iocore/eventsystem/ob_event_processor.h" #include "dbconfig/ob_proxy_db_config_info.h" +#include "iocore/eventsystem/ob_event_processor.h" #include "lib/string/ob_sql_string.h" using namespace oceanbase::common; @@ -45,17 +45,38 @@ static const EMySQLFieldType column_type[OB_TC_MAX_COLUMN_ID] = { OB_MYSQL_TYPE_LONG }; -ObShowTopologyHandler::ObShowTopologyHandler(ObMIOBuffer *buf, uint8_t pkg_seq, int64_t memory_limit) - : ObCmdHandler(buf, pkg_seq, memory_limit) +//TopologyColumnID for sharding +enum +{ + OB_TC_ID = 0, + OB_TC_GROUP_NAME, + OB_TC_TABLE_NAME, + OB_TC_SCHEMA_TYPE, + OB_TC_SHARD_KEY, + OB_TC_SHARD_RULE, + OB_TC_SHARD_MAX_COLUMN_ID, +}; + +const ObProxyColumnSchema SHOW_TOPOLOGY_ARRAY[OB_TC_SHARD_MAX_COLUMN_ID] = { + ObProxyColumnSchema::make_schema(OB_TC_ID, "id", OB_MYSQL_TYPE_LONG), + ObProxyColumnSchema::make_schema(OB_TC_GROUP_NAME, "group_name", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_TC_TABLE_NAME, "table_name", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_TC_SCHEMA_TYPE, "schema_type", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_TC_SHARD_KEY, "shard_key", OB_MYSQL_TYPE_VARCHAR), + ObProxyColumnSchema::make_schema(OB_TC_SHARD_RULE, "shard_rule", OB_MYSQL_TYPE_VARCHAR), +}; + +ObShowTopologyHandler::ObShowTopologyHandler(ObMIOBuffer *buf, ObCmdInfo &info) + : ObCmdHandler(buf, info) { } -int ObShowTopologyHandler::handle_show_topology(const ObString &tenant_name, - const ObString &db_name, - const ObString &group_name) +int ObShowTopologyHandler::handle_show_elastic_id(const ObString &tenant_name, + const ObString &db_name, + const ObString &group_name) { int ret = OB_SUCCESS; - if (OB_FAIL(dump_topology_header())) { + if (OB_FAIL(dump_elastic_id_header())) { WARN_CMD("fail to dump_header", K(ret)); } else { ObDbConfigCache &dbconfig_cache = get_global_dbconfig_cache(); @@ -144,7 +165,7 @@ int ObShowTopologyHandler::dump_elastic_id(const int64_t eid) return ret; } -int ObShowTopologyHandler::dump_topology_header() +int ObShowTopologyHandler::dump_elastic_id_header() { int ret = OB_SUCCESS; if (OB_FAIL(encode_header(column_name, column_type, OB_TC_MAX_COLUMN_ID))) { @@ -153,9 +174,8 @@ int ObShowTopologyHandler::dump_topology_header() return ret; } -int ObShowTopologyHandler::show_topology_cmd_callback(ObMIOBuffer *buf, - uint8_t pkg_seq, - int64_t memory_limit, +int ObShowTopologyHandler::show_elastic_id_cmd_callback(ObMIOBuffer *buf, + ObCmdInfo &info, const ObString &logic_tenant_name, const ObString &logic_database_name, const ObString &group_name) @@ -163,12 +183,12 @@ int ObShowTopologyHandler::show_topology_cmd_callback(ObMIOBuffer *buf, int ret = OB_SUCCESS; ObShowTopologyHandler *handler = NULL; - if (OB_ISNULL(handler = new(std::nothrow) ObShowTopologyHandler(buf, pkg_seq, memory_limit))) { + if (OB_ISNULL(handler = new(std::nothrow) ObShowTopologyHandler(buf, info))) { ret = OB_ALLOCATE_MEMORY_FAILED; ERROR_CMD("fail to new ObShowTopologyHandler", K(ret)); } else if (OB_FAIL(handler->init())) { WARN_CMD("fail to init for ObShowTopologyHandler"); - } else if (OB_FAIL(handler->handle_show_topology(logic_tenant_name, logic_database_name, group_name))){ + } else if (OB_FAIL(handler->handle_show_elastic_id(logic_tenant_name, logic_database_name, group_name))){ WARN_CMD("fail to handle show topology", K(logic_tenant_name), K(logic_database_name), K(group_name), K(ret)); } @@ -179,6 +199,255 @@ int ObShowTopologyHandler::show_topology_cmd_callback(ObMIOBuffer *buf, return ret; } + +int ObShowTopologyHandler::show_topology_cmd_callback(ObMIOBuffer *buf, + ObCmdInfo &info, + const ObString &logic_tenant_name, + const ObString &logic_database_name, + const ObString &table_name) +{ + int ret = OB_SUCCESS; + ObShowTopologyHandler *handler = NULL; + + if (OB_ISNULL(handler = new(std::nothrow) ObShowTopologyHandler(buf, info))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + ERROR_CMD("fail to new ObShowTopologyHandler", K(ret)); + } else if (OB_FAIL(handler->init())) { + WARN_CMD("fail to init for ObShowTopologyHandler"); + } else if (OB_FAIL(handler->handle_show_topology(logic_tenant_name, logic_database_name, table_name))){ + WARN_CMD("fail to handle show topology", K(logic_tenant_name), K(logic_database_name), K(ret)); + } + + if (OB_LIKELY(NULL != handler)) { + delete handler; + handler = NULL; + } + return ret; +} + +int ObShowTopologyHandler::handle_show_topology(const ObString &tenant_name, + const ObString &db_name, + const ObString &table_name) +{ + int ret = OB_SUCCESS; + if (OB_FAIL(encode_header(SHOW_TOPOLOGY_ARRAY, OB_TC_SHARD_MAX_COLUMN_ID))) { + WARN_CMD("fail to dump_header", K(ret)); + } else { + ObDbConfigCache &dbconfig_cache = get_global_dbconfig_cache(); + ObDbConfigLogicDb *db_info = NULL; + ObShardRule *shard_rule = NULL; + if (OB_ISNULL(db_info = dbconfig_cache.get_exist_db_info(tenant_name, db_name))) { + ret = OB_ERR_BAD_DATABASE; + WARN_CMD("logic database not exist", K(tenant_name), K(db_name), K(ret)); + } else if (OB_UNLIKELY(db_info->is_single_shard_db_table())) { + if (OB_FAIL(dump_shard_topology_for_single_db(table_name))) { + WARN_CMD("fail to encode topology packet for single db", K(tenant_name), K(db_name), K(ret)); + } + } else if (OB_FAIL(db_info->get_shard_rule(shard_rule, table_name))) { + // no logic table + ret = OB_TABLE_NOT_EXIST; + } else if (OB_UNLIKELY((1 == shard_rule->db_size_) && (1 == shard_rule->tb_size_))) { + if (OB_FAIL(dump_shard_topology_for_shard_db_single_tb(table_name))) { + WARN_CMD("fail to encode topology packet for shard_db_single_tb", K(tenant_name), K(db_name), K(shard_rule->db_size_), K(shard_rule->tb_size_), K(ret)); + } + } else if (OB_UNLIKELY(1 == shard_rule->tb_size_)) { + if (OB_FAIL(dump_shard_topology_for_shard_db_non_shard_tb(table_name, shard_rule))) { + WARN_CMD("fail to encode topology packet for shard_db_non_shard_tb", K(tenant_name), K(db_name), K(shard_rule->db_size_), K(shard_rule->tb_size_), K(ret)); + } + } else { + if (OB_FAIL(dump_shard_topology_for_shard_db_shard_tb(shard_rule))) { + WARN_CMD("fail to encode topology packet for shard_db_shard_tb", K(tenant_name), K(db_name), K(shard_rule->db_size_), K(shard_rule->tb_size_), K(ret)); + } + } + + if (NULL != db_info) { + db_info->dec_ref(); + db_info = NULL; + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(encode_eof_packet())) { + WARN_CMD("fail to encode eof packet", K(ret)); + } + } + + if (OB_FAIL(ret)) { + if (OB_FAIL(encode_err_packet(ret))) { + WARN_CMD("fail to encode internal err packet, callback", K(ret)); + } else { + INFO_CMD("succ to encode internal err packet, callback"); + ret = OB_SUCCESS; + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(fill_external_buf())) { + WARN_CMD("fail to fill_external_buf", K(ret)); + } + } + return ret; +} + +int ObShowTopologyHandler::dump_shard_topology_for_single_db(ObString table_name) +{ + int ret = OB_SUCCESS; + ObNewRow row; + ObObj cells[OB_TC_SHARD_MAX_COLUMN_ID]; + cells[OB_TC_ID].set_int(0); + cells[OB_TC_GROUP_NAME].set_varchar("group_00"); + cells[OB_TC_TABLE_NAME].set_varchar(table_name); + cells[OB_TC_SCHEMA_TYPE].set_varchar("SINGLE"); + cells[OB_TC_SHARD_KEY].set_null(); + cells[OB_TC_SHARD_RULE].set_null(); + row.cells_ = cells; + row.count_ = OB_TC_SHARD_MAX_COLUMN_ID; + if (OB_FAIL(encode_row_packet(row))) { + WARN_CMD("fail to encode row packet for shard", K(row), K(ret)); + } + return ret; +} + +int ObShowTopologyHandler::dump_shard_topology_for_shard_db_single_tb(ObString table_name) +{ + int ret = OB_SUCCESS; + ObNewRow row; + ObObj cells[OB_TC_SHARD_MAX_COLUMN_ID]; + cells[OB_TC_ID].set_int(0); + cells[OB_TC_GROUP_NAME].set_varchar("group_00"); + cells[OB_TC_TABLE_NAME].set_varchar(table_name); + cells[OB_TC_SCHEMA_TYPE].set_varchar("SHARD"); + cells[OB_TC_SHARD_KEY].set_null(); + cells[OB_TC_SHARD_RULE].set_null(); + row.cells_ = cells; + row.count_ = OB_TC_SHARD_MAX_COLUMN_ID; + if (OB_FAIL(encode_row_packet(row))) { + WARN_CMD("fail to encode row packet for shard", K(row), K(ret)); + } + return ret; +} + +int ObShowTopologyHandler::dump_shard_topology_for_shard_db_non_shard_tb(ObString table_name, ObShardRule *shard_rule) +{ + int ret = OB_SUCCESS; + ObNewRow row; + ObObj cells[OB_TC_SHARD_MAX_COLUMN_ID]; + int size = OB_TC_SHARD_MAX_COLUMN_ID; + ObString real_group_name; + ObString real_table_name = table_name; + char group_name_buf[OB_MAX_TABLEGROUP_NAME_LENGTH]; + ObString schema_type("SHARD"); + char shard_key_buf[OB_MAX_COLUMN_NAME_LENGTH]; + ObString shard_key_str = get_shard_key_str(*shard_rule, shard_key_buf, OB_MAX_COLUMN_NAME_LENGTH); + ObString shard_rule_str = get_shard_rule_str(*shard_rule); + + int64_t count = shard_rule->db_size_; + for(int64_t index = 0; index < count; ++index) { + int64_t group_index = index; + shard_rule->get_real_name_by_index(shard_rule->db_size_, + shard_rule->db_suffix_len_, group_index, + shard_rule->db_prefix_.config_string_, + shard_rule->db_tail_.config_string_, + group_name_buf, OB_MAX_TABLEGROUP_NAME_LENGTH); + real_group_name = ObString::make_string(group_name_buf); + cells[OB_TC_ID].set_int(index); + cells[OB_TC_GROUP_NAME].set_varchar(real_group_name); + cells[OB_TC_TABLE_NAME].set_varchar(real_table_name); + cells[OB_TC_SCHEMA_TYPE].set_varchar(schema_type); + cells[OB_TC_SHARD_KEY].set_varchar(shard_key_str); + cells[OB_TC_SHARD_RULE].set_varchar(shard_rule_str); + row.cells_ = cells; + row.count_ = size; + if (OB_FAIL(encode_row_packet(row))) { + WARN_CMD("fail to encode row packet for shard", K(row), K(ret)); + } + } + return ret; +} + +int ObShowTopologyHandler::dump_shard_topology_for_shard_db_shard_tb(ObShardRule *shard_rule) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY((0 == shard_rule->db_size_) || (shard_rule->tb_size_ < shard_rule->db_size_))) { + WARN_CMD("wrong shard rule for shard_db_shard_tb", K(shard_rule->db_size_), K(shard_rule->tb_size_), K(ret)); + } else { + ObNewRow row; + ObObj cells[OB_TC_SHARD_MAX_COLUMN_ID]; + int size = OB_TC_SHARD_MAX_COLUMN_ID; + ObString real_group_name; + ObString real_table_name; + char group_name_buf[OB_MAX_TABLEGROUP_NAME_LENGTH]; + char table_name_buf[OB_MAX_USER_TABLE_NAME_LENGTH]; + char shard_key_buf[OB_MAX_COLUMN_NAME_LENGTH]; + ObString schema_type("SHARD"); + ObString shard_key_str = get_shard_key_str(*shard_rule, shard_key_buf, OB_MAX_COLUMN_NAME_LENGTH); + ObString shard_rule_str = get_shard_rule_str(*shard_rule); + + int64_t count = shard_rule->tb_size_; + for(int64_t index = 0; index < count; ++index) { + int64_t group_index = index / (shard_rule->tb_size_ / shard_rule->db_size_); + shard_rule->get_real_name_by_index(shard_rule->db_size_, + shard_rule->db_suffix_len_, group_index, + shard_rule->db_prefix_.config_string_, + shard_rule->db_tail_.config_string_, + group_name_buf, OB_MAX_TABLEGROUP_NAME_LENGTH); + shard_rule->get_real_name_by_index(shard_rule->tb_size_, + shard_rule->tb_suffix_len_, index, + shard_rule->tb_prefix_.config_string_, + shard_rule->tb_tail_.config_string_, + table_name_buf, OB_MAX_USER_TABLE_NAME_LENGTH); + real_group_name = ObString::make_string(group_name_buf); + real_table_name = ObString::make_string(table_name_buf); + cells[OB_TC_ID].set_int(index); + cells[OB_TC_GROUP_NAME].set_varchar(real_group_name); + cells[OB_TC_TABLE_NAME].set_varchar(real_table_name); + cells[OB_TC_SCHEMA_TYPE].set_varchar(schema_type); + cells[OB_TC_SHARD_KEY].set_varchar(shard_key_str); + cells[OB_TC_SHARD_RULE].set_varchar(shard_rule_str); + row.cells_ = cells; + row.count_ = size; + if (OB_FAIL(encode_row_packet(row))) { + WARN_CMD("fail to encode row packet for shard", K(row), K(ret)); + } + } + } + return ret; +} + +ObString ObShowTopologyHandler::get_shard_key_str(dbconfig::ObShardRule& shard_rule, char* const target_buf, const int target_buf_len) +{ + ObString ret_str = ObString::make_string("empty shard key"); + if (OB_LIKELY(0 != shard_rule.tb_rules_.count())) { + ObString& origin_string = shard_rule.tb_rules_.at(0).shard_rule_str_.config_string_; + for(int i = 0; i < origin_string.length(); ++i) { + if(origin_string[i] != '#') { + continue; + } else { + int j = i + 1; + while(j < origin_string.length() && origin_string[j] != '#') { + ++j; + } + if((j == origin_string.length()) || (j - i - 1) >= target_buf_len) { + ret_str = ObString::make_string("error shard key"); + } else { + MEMCPY(target_buf, origin_string.ptr() + i + 1, j - i - 1); + ret_str.assign_ptr(target_buf, j - i - 1); + } + break; + } + } + } + return ret_str; +} + +ObString ObShowTopologyHandler::get_shard_rule_str(dbconfig::ObShardRule& shard_rule) +{ + ObString ret_str = ObString::make_string("empty shard rule"); + if (OB_LIKELY(0 != shard_rule.tb_rules_.count())) { + ret_str = shard_rule.tb_rules_.at(0).shard_rule_str_.config_string_; + } + return ret_str; +} } // end of namespace proxy } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/cmd/ob_show_topology_handler.h b/src/obproxy/cmd/ob_show_topology_handler.h index 58ab6b31040326d8a0fae67be35805bdbab68421..0cb0c667f6788c7aed0442a22b632042d7d4005a 100644 --- a/src/obproxy/cmd/ob_show_topology_handler.h +++ b/src/obproxy/cmd/ob_show_topology_handler.h @@ -22,33 +22,48 @@ namespace obproxy namespace dbconfig { class ObGroupCluster; +class ObShardRule; } + namespace obutils { class ObShowTopologyHandler : public ObCmdHandler { public: - ObShowTopologyHandler(event::ObMIOBuffer *buf, uint8_t pkg_seq, - int64_t memory_limit); + ObShowTopologyHandler(event::ObMIOBuffer *buf, ObCmdInfo &info); virtual ~ObShowTopologyHandler() {} + int handle_show_elastic_id(const common::ObString &tenant_name, + const common::ObString &db_name, + const common::ObString &group_name); + static int show_elastic_id_cmd_callback(event::ObMIOBuffer *buf, + ObCmdInfo &info, + const common::ObString &logic_tenant_name, + const common::ObString &logic_database_name, + const common::ObString &group_name); int handle_show_topology(const common::ObString &tenant_name, const common::ObString &db_name, - const common::ObString &group_name); + const common::ObString &table_name); static int show_topology_cmd_callback(event::ObMIOBuffer *buf, - uint8_t pkg_seq, - int64_t memory_limit, + ObCmdInfo &info, const common::ObString &logic_tenant_name, const common::ObString &logic_database_name, - const common::ObString &group_name); + const common::ObString &table_name); public: static const int64_t OB_MAX_ELASTIC_ID_COUNT = 256; private: - int dump_topology_header(); + int dump_elastic_id_header(); int dump_elastic_id(const int64_t eid); + int dump_shard_topology_for_single_db(ObString table_name); + int dump_shard_topology_for_shard_db_single_tb(ObString table_name); + int dump_shard_topology_for_shard_db_non_shard_tb(ObString table_name, dbconfig::ObShardRule *shard_rule); + int dump_shard_topology_for_shard_db_shard_tb(dbconfig::ObShardRule *shard_rule); + + ObString get_shard_key_str(dbconfig::ObShardRule& shard_rule, char* const target_buf, const int target_buf_len); + ObString get_shard_rule_str(dbconfig::ObShardRule& shard_rule); private: DISALLOW_COPY_AND_ASSIGN(ObShowTopologyHandler); }; diff --git a/src/obproxy/cmd/ob_show_trace_handler.cpp b/src/obproxy/cmd/ob_show_trace_handler.cpp index a61ab7072a88ac75648ce76c09a6855c7368179e..924a147ccd817cb158dd8127f572dd75c229cc71 100644 --- a/src/obproxy/cmd/ob_show_trace_handler.cpp +++ b/src/obproxy/cmd/ob_show_trace_handler.cpp @@ -53,8 +53,7 @@ const ObProxyColumnSchema TRACE_COLUMN_ARRAY[OB_TC_MAX_TRACE_COLUMN_ID] = { ObProxyColumnSchema::make_schema(OB_TC_COST, "cost_time_us", OB_MYSQL_TYPE_LONG), }; -ObShowTraceHandler::ObShowTraceHandler(ObContinuation *cont, ObMIOBuffer *buf, - const ObInternalCmdInfo &info) +ObShowTraceHandler::ObShowTraceHandler(ObContinuation *cont, ObMIOBuffer *buf, const ObInternalCmdInfo &info) : ObInternalCmdHandler(cont, buf, info), sub_type_(info.get_sub_cmd_type()), attempt_limit_(info.get_attempt_limit()), cs_id_array_() { diff --git a/src/obproxy/cmd/ob_show_trace_handler.h b/src/obproxy/cmd/ob_show_trace_handler.h index 1e87dcc1541cdf50a6230d0b46d4d547040d0d9b..1383c6583de022e2496a70ca377ef2cb3bd12ca1 100644 --- a/src/obproxy/cmd/ob_show_trace_handler.h +++ b/src/obproxy/cmd/ob_show_trace_handler.h @@ -25,8 +25,7 @@ namespace proxy class ObShowTraceHandler : public ObInternalCmdHandler { public: - ObShowTraceHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObShowTraceHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObShowTraceHandler() { cs_id_array_.destroy(); } int handle_trace(int event, void *data); virtual CSIDHanders *get_cs_id_array() { return &cs_id_array_; } diff --git a/src/obproxy/cmd/ob_show_vip_handler.cpp b/src/obproxy/cmd/ob_show_vip_handler.cpp index b8aaecb0be5d8c5c74d34b40cab09b514833cb03..2574107e9eabc2767f2926626156c6f689dc8e5d 100644 --- a/src/obproxy/cmd/ob_show_vip_handler.cpp +++ b/src/obproxy/cmd/ob_show_vip_handler.cpp @@ -16,6 +16,8 @@ #include "utils/ob_proxy_utils.h" #include "iocore/eventsystem/ob_task.h" #include "iocore/eventsystem/ob_event_processor.h" +#include "share/config/ob_config.h" +#include "obutils/ob_config_processor.h" using namespace oceanbase::common; using namespace oceanbase::share; @@ -51,8 +53,7 @@ const ObProxyColumnSchema VIP_COLUMN_ARRAY[OB_VC_MAX_VIP_COLUMN_ID] = { ObProxyColumnSchema::make_schema(OB_VC_INFO, "info", OB_MYSQL_TYPE_VARCHAR), }; -ObShowVipHandler::ObShowVipHandler(ObContinuation *cont, ObMIOBuffer *buf, - const ObInternalCmdInfo &info) +ObShowVipHandler::ObShowVipHandler(ObContinuation *cont, ObMIOBuffer *buf, const ObInternalCmdInfo &info) : ObInternalCmdHandler(cont, buf, info) { SET_HANDLER(&ObShowVipHandler::main_handler); @@ -69,7 +70,6 @@ int ObShowVipHandler::main_handler(int event, void *data) } else if (OB_FAIL(dump_header())) { WARN_ICMD("fail to dump header", K(ret)); } else { - ObVipTenantCache &vt_cache = get_global_vip_tenant_processor().get_vt_cache(); ObVipTenant vip_tenant; if (!like_name_.empty()) { //dump one vip tenant @@ -88,9 +88,9 @@ int ObShowVipHandler::main_handler(int event, void *data) WARN_ICMD("unexpected argument", K(vip_string), K(match_name), K(ret)); } else if (OB_FAIL(get_int_value(match_name, vport))) { WARN_ICMD("fail to get_int_value", K(match_name), K(vport), K(ret)); - } else if (!vip_addr.addr_.set_ipv4_addr(vip_string, static_cast(vport))) { + } else if (!vip_addr.addr_.set_ip_addr(vip_string, static_cast(vport))) { ret = OB_INVALID_ARGUMENT; - WARN_ICMD("fail to set_ipv4_addr", K(vip_string), K(vport), K(ret)); + WARN_ICMD("fail to set_ip_addr", K(vip_string), K(vport), K(ret)); } else if (!vip_addr.is_valid()) { ret = OB_INVALID_ARGUMENT; WARN_ICMD("invalid vip_addr", K(vip_addr), K(match_name), K(ret)); @@ -100,32 +100,38 @@ int ObShowVipHandler::main_handler(int event, void *data) } if (OB_SUCC(ret)) { - if (OB_FAIL(vt_cache.get(vip_addr, vip_tenant))) { - WARN_ICMD("fail to get vip_tenant", K(ret)); - if (OB_ENTRY_NOT_EXIST == ret) { - //empty result - ret = OB_SUCCESS; + ObConfigItem tenant_item; + ObConfigItem cluster_item; + bool found = false; + vip_tenant.vip_addr_ = vip_addr; + if (OB_FAIL(get_global_config_processor().get_proxy_config_with_level( + vip_tenant.vip_addr_, "", "", "proxy_tenant_name", tenant_item, "LEVEL_VIP", found))) { + WARN_ICMD("get proxy tenant name config failed", K(vip_tenant.vip_addr_), K(ret)); + } + if (OB_SUCC(ret) && found) { + if (OB_FAIL(get_global_config_processor().get_proxy_config_with_level( + vip_tenant.vip_addr_, "", "", "rootservice_cluster_name", cluster_item, "LEVEL_VIP", found))) { + WARN_ICMD("get cluster name config failed", K(vip_tenant.vip_addr_), K(ret)); + } + } + if (OB_SUCC(ret) && found) { + if (OB_FAIL(vip_tenant.set_tenant_cluster(tenant_item.str(), cluster_item.str()))) { + WARN_ICMD("set tenant and cluster name failed", K(tenant_item), K(cluster_item), K(ret)); + } else if (OB_FAIL(dump_item(vip_tenant))) { + WARN_ICMD("fail to dump item", K(vip_tenant), K(ret)); } - } else if (OB_FAIL(dump_item(vip_tenant))) { - WARN_ICMD("fail to dump item", K(vip_tenant), K(ret)); + } else { + WARN_ICMD("fail to get vip_tenant", K(ret)); } } else { ret = OB_ERR_OPERATOR_UNKNOWN;//return this errno } } else { //dump all vip tenant - ObVipTenantCache::VTHashMap *cache_map = NULL; - obsys::CRLockGuard guard(vt_cache.rwlock_); - if (OB_ISNULL(cache_map = vt_cache.get_cache_map())) { - ret = OB_ERR_UNEXPECTED; - WARN_ICMD("cache_map is null", K(ret)); - } else { - for (ObVipTenantCache::VTHashMap::iterator it = cache_map->begin(); - OB_SUCC(ret) && it != cache_map->end(); ++it) { - if (OB_FAIL(dump_item(*it))) { - WARN_ICMD("fail to dump item", K(*it), K(ret)); - } - } + const char* select_sql = "SELECT a.vid, a.vip, a.vport, a.value, b.value FROM proxy_config as a, proxy_config as b " + "where a.name = 'proxy_tenant_nane' and b.name = 'rootservice_cluster_name';"; + if (get_global_config_processor().execute(select_sql, ObShowVipHandler::sqlite3_callback, this)) { + WARN_ICMD("fail to execute sql", K(ret)); } } } @@ -181,6 +187,40 @@ int ObShowVipHandler::dump_item(const ObVipTenant &vip_tenant) return ret; } +int ObShowVipHandler::sqlite3_callback(void *data, int argc, char **argv, char **column_name) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(NULL == data || NULL == argv || NULL == column_name || 5 != argc)) { + ret = OB_ERR_UNEXPECTED; + WARN_ICMD("argument is unexpected", K(argc), K(ret)); + } else { + ObShowVipHandler *handler = reinterpret_cast(data); + char* vip; + int64_t vport = 0; + int64_t vid = -1; + ObVipTenant vip_tenant; + ObString tenant; + ObString cluster; + if (OB_UNLIKELY(NULL == argv[0] || NULL == argv[1] || NULL == argv[2] || NULL == argv[3] || NULL == argv[4])) { + ret = OB_ERR_UNEXPECTED; + WARN_ICMD("argument is unexpected", K(ret)); + } else { + vid = atoi(argv[0]); + vip = argv[1]; + vport = atoi(argv[2]); + tenant = argv[3]; + cluster = argv[4]; + vip_tenant.vip_addr_.set(vip, static_cast(vport), vid); + if (OB_FAIL(vip_tenant.set_tenant_cluster(tenant, cluster))) { + WARN_ICMD("fail to set tenant cluster", K(vip_tenant), K(ret)); + } else if (OB_FAIL(handler->dump_item(vip_tenant))) { + WARN_ICMD("fail to dump item", K(vip_tenant), K(ret)); + } + } + } + return ret; +} + static int show_vip_cmd_callback(ObContinuation *cont, ObInternalCmdInfo &info, ObMIOBuffer *buf, ObAction *&action) { diff --git a/src/obproxy/cmd/ob_show_vip_handler.h b/src/obproxy/cmd/ob_show_vip_handler.h index 10d4ebac68f51bebd7122ab2ae2ca39fcec8732a..07f60b49cf731f9f70df3873106d4ee6983e1af0 100644 --- a/src/obproxy/cmd/ob_show_vip_handler.h +++ b/src/obproxy/cmd/ob_show_vip_handler.h @@ -25,8 +25,8 @@ namespace obutils class ObShowVipHandler : public ObInternalCmdHandler { public: - ObShowVipHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObShowVipHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, + const ObInternalCmdInfo &info); virtual ~ObShowVipHandler() {} int main_handler(int event, void *data); @@ -34,6 +34,7 @@ private: int dump_header(); int dump_body(); int dump_item(const ObVipTenant &vip_tenant); + static int sqlite3_callback(void *data, int argc, char **argv, char **column_name); DISALLOW_COPY_AND_ASSIGN(ObShowVipHandler); }; diff --git a/src/obproxy/cmd/ob_show_warning_handler.h b/src/obproxy/cmd/ob_show_warning_handler.h index ed60658be0e1cb5b2b2914593e7912f65dc484a0..069985622ef5bde38b68e33533f135582779cd89 100644 --- a/src/obproxy/cmd/ob_show_warning_handler.h +++ b/src/obproxy/cmd/ob_show_warning_handler.h @@ -136,8 +136,7 @@ struct ObShowWaringParam class ObShowWarningHandler : public ObInternalCmdHandler { public: - ObShowWarningHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, - const ObInternalCmdInfo &info); + ObShowWarningHandler(event::ObContinuation *cont, event::ObMIOBuffer *buf, const ObInternalCmdInfo &info); virtual ~ObShowWarningHandler() { } int handle_show_warning(int event, event::ObEvent *e); diff --git a/src/obproxy/dbconfig/grpc/ob_proxy_grpc_client.cpp b/src/obproxy/dbconfig/grpc/ob_proxy_grpc_client.cpp index 0aa658bbb0daaf79e09d6e7f19d026e80cd16f7e..d2fdaf1d692e402395d52d14b1aea0d2380875bb 100644 --- a/src/obproxy/dbconfig/grpc/ob_proxy_grpc_client.cpp +++ b/src/obproxy/dbconfig/grpc/ob_proxy_grpc_client.cpp @@ -156,15 +156,15 @@ int ObGrpcClient::fill_request_node(DiscoveryRequest &request) const char *is_sidecar = getenv("IS_SIDECAR"); if (OB_NOT_NULL(is_sidecar) && OB_UNLIKELY(strncmp(is_sidecar, "false", strlen(is_sidecar)) == 0)) {// app is not in sidecar - char ipstr[OB_IP_STR_BUFF]; - MEMSET(ipstr, 0, OB_IP_STR_BUFF); + char ipstr[MAX_IP_ADDR_LENGTH]; + MEMSET(ipstr, 0, MAX_IP_ADDR_LENGTH); ObSEArray labels; char json[MAX_REQUEST_LABELS_LENGTH]; MEMSET(json, 0, sizeof(json)); - if (OB_FAIL(getip_from_nodeid(ipstr, OB_IP_STR_BUFF))) { + if (OB_FAIL(getip_from_nodeid(ipstr, MAX_IP_ADDR_LENGTH))) { LOG_WARN("can not get ip from node id", K(ret)); } else if (OB_UNLIKELY(strlen(ipstr) == 0)) { ret = OB_ERR_UNEXPECTED; @@ -227,7 +227,7 @@ int ObGrpcClient::getip_from_nodeid(char *ipstr, int64_t length) if (OB_SUCC(ret)) { if (OB_UNLIKELY(length < ip.length())) { ret = OB_SIZE_OVERFLOW; - LOG_WARN("IP string in node id is longer than OB_IP_STR_BUFF", K(length), K(ip.length()), K(ret)); + LOG_WARN("IP string in node id is longer than MAX_IP_ADDR_LENGTH", K(length), K(ip.length()), K(ret)); } else { memcpy(ipstr, ip.ptr(), ip.length()); ipstr[ip.length()] = '\0'; @@ -321,7 +321,17 @@ int ObGrpcClient::to_json(ObIArray& labels, char *json, int bool ObGrpcClient::sync_read(DiscoveryResponse &response) { - return stream_->Read(&response); + bool status = false; + int ret = OB_SUCCESS; + status = stream_->Read(&response); + if (!status) { + LOG_INFO("the stream has been closed, will rebuild the grpc client stream"); + finish_rpc(); + if (OB_FAIL(init_stream())) { + LOG_WARN("fail to init stream", K(ret)); + } + } + return status; } void ObGrpcClient::finish_rpc() diff --git a/src/obproxy/dbconfig/ob_proxy_db_config_info.cpp b/src/obproxy/dbconfig/ob_proxy_db_config_info.cpp index fe753d86a21ecc44ecb25eb8cbeb9bd33403a0a2..be5030c6eb79c1b07548d87d69536398e8899e9e 100644 --- a/src/obproxy/dbconfig/ob_proxy_db_config_info.cpp +++ b/src/obproxy/dbconfig/ob_proxy_db_config_info.cpp @@ -1636,10 +1636,9 @@ int ObShardRule::get_physic_index(const SqlFieldResult &sql_result, const ObProxyShardRuleInfo &rule = rules.at(i); ObProxyExprCtx expr_ctx(physic_size, type, is_elastic_index, &allocator); ObProxyExpr *proxy_expr = rule.expr_; - ObObj result_obj; ObSEArray result_array; int64_t tmp_index = OBPROXY_MAX_DBMESH_ID; - + int64_t tmp_index_for_one_obj = OBPROXY_MAX_DBMESH_ID; LOG_DEBUG("begin to calc rule", K(rule)); ObProxyExprCalcItem calc_item(const_cast(&sql_result)); @@ -1654,16 +1653,23 @@ int ObShardRule::get_physic_index(const SqlFieldResult &sql_result, LOG_WARN("calc proxy expr failed", K(ret)); } } else { - result_obj = result_array.at(0); - ObObj tmp_obj; - if (OB_FAIL(ObProxyFuncExpr::get_int_obj(result_obj, tmp_obj))) { - LOG_WARN("get int obj failed", K(result_obj), K(ret)); - } else if (OB_FAIL(tmp_obj.get_int(tmp_index))) { - LOG_WARN("get int failed", K(ret)); - } else { - if (tmp_index < 0 || tmp_index >= physic_size) { - ret = OB_EXPR_CALC_ERROR; - LOG_WARN("invalid index", K(tmp_index), K(physic_size), K(ret)); + for(int64_t j = 0; OB_SUCC(ret) && j < result_array.count(); j++) { + ObObj& result_obj = result_array.at(j); + ObObj tmp_obj; + if (OB_FAIL(ObProxyFuncExpr::get_int_obj(result_obj, tmp_obj, allocator))) { + LOG_WARN("get int obj failed", K(result_obj), K(ret)); + } else if (OB_FAIL(tmp_obj.get_int(tmp_index_for_one_obj))) { + LOG_WARN("get int failed", K(ret)); + } else if (tmp_index_for_one_obj < 0 || tmp_index_for_one_obj >= physic_size) { + ret = OB_EXPR_CALC_ERROR; + LOG_WARN("invalid index", K(tmp_index_for_one_obj), K(physic_size), K(ret)); + } else if (OBPROXY_MAX_DBMESH_ID == tmp_index) { + tmp_index = tmp_index_for_one_obj; + } else if (tmp_index != tmp_index_for_one_obj) { + ret = OB_ERR_DISTRIBUTED_NOT_SUPPORTED; + LOG_WARN("different physic index for one sharding key is not supported", K(tmp_index), K(last_index), K(ret)); + } else { + //nothing } } } @@ -1749,7 +1755,7 @@ int ObShardRule::get_physic_index_array(const SqlFieldResult &sql_result, for (int64_t i = 0; OB_SUCC(ret) && i < result_obj_array.count(); i++) { ObObj tmp_obj; int64_t tmp_index; - if (OB_FAIL(ObProxyFuncExpr::get_int_obj(result_obj_array.at(i), tmp_obj))) { + if (OB_FAIL(ObProxyFuncExpr::get_int_obj(result_obj_array.at(i), tmp_obj, allocator))) { LOG_WARN("get int obj failed", K(ret), K(result_obj_array.at(i))); } else if (OB_FAIL(tmp_obj.get_int(tmp_index))) { LOG_WARN("get int failed", K(ret)); @@ -2009,6 +2015,91 @@ int ObDbConfigLogicDb::get_shard_router(const ObString &tb_name, ObShardRouter * return ret; } +int ObDbConfigLogicDb::get_first_group_shard_connector(ObShardConnector *&shard_conn, int64_t es_id, + bool is_read_stmt, ObTestLoadType testload_type) +{ + int ret = OB_SUCCESS; + + ObShardTpo *shard_tpo = NULL; + ObGroupCluster *gc_info = NULL; + + if (OB_FAIL(get_shard_tpo(shard_tpo))) { + LOG_WARN("fail to get shard tpo info", K(ret)); + } else if (OB_ISNULL(shard_tpo)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("shard tpo info is null", K(ret)); + } else if (is_single_shard_db_table()) { + ObShardTpo::GCHashMap::iterator it = (const_cast(shard_tpo->gc_map_)).begin(); + gc_info = &(*it); + } else { + ObShardRule *logic_tb_info = NULL; + { + ObDbConfigCache &dbconfig_cache = get_global_dbconfig_cache(); + obsys::CRLockGuard guard(dbconfig_cache.rwlock_); + ObDbConfigChildArrayInfo::CCRHashMap &map = const_cast::CCRHashMap &>(sr_array_.ccr_map_); + for (ObDbConfigChildArrayInfo::CCRHashMap::iterator it = map.begin(); it != map.end(); ++it) { + ObShardRouter::MarkedRuleHashMap &mr_map = it->mr_map_; + for (ObShardRouter::MarkedRuleHashMap::iterator sub_it = mr_map.begin(); + sub_it != mr_map.end(); ++sub_it) { + logic_tb_info = &(*sub_it); + break; + } + } + } + + if (OB_SUCC(ret)) { + char real_database_name[OB_MAX_DATABASE_NAME_LENGTH]; + if (OB_FAIL(logic_tb_info->get_real_name_by_index(logic_tb_info->db_size_, logic_tb_info->db_suffix_len_, 0, + logic_tb_info->db_prefix_.config_string_, + logic_tb_info->db_tail_.config_string_, + real_database_name, OB_MAX_DATABASE_NAME_LENGTH))) { + LOG_WARN("fail to get real group name", KPC(logic_tb_info), K(ret)); + } else if (OB_FAIL(shard_tpo->get_group_cluster(ObString::make_string(real_database_name), gc_info))) { + LOG_DEBUG("group does not exist", "phy_db_name", real_database_name, K(ret)); + } else if (OB_ISNULL(gc_info)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("group cluster info is null", "phy_db_name", real_database_name, K(ret)); + } + } + } + + if (OB_SUCC(ret)) { + // Calculate es_id + int64_t es_size = gc_info->get_es_size(); + ObString shard_name; + if (-1 == es_id || OBPROXY_MAX_DBMESH_ID == es_id) { + if (OB_FAIL(gc_info->get_elastic_id_by_weight(es_id, is_read_stmt))) { + LOG_WARN("fail to get eid by read weight", KPC(gc_info)); + } else { + LOG_DEBUG("succ to get eid by weight", K(es_id)); + } + } else if (OB_UNLIKELY(es_id >= es_size)) { + ret = OB_EXPR_CALC_ERROR; + LOG_WARN("es index is larger than elastic array", K(es_id), K(es_size), K(ret)); + } + } + + if (OB_SUCC(ret)) { + ObString shard_name; + if (FALSE_IT(shard_name = gc_info->get_shard_name_by_eid(es_id))) { + } else if (TESTLOAD_NON != testload_type) { + if (OB_FAIL(get_testload_shard_connector(shard_name, testload_prefix_.config_string_, shard_conn))) { + LOG_WARN("testload shard connector not exist", "testload_type", get_testload_type_str(testload_type), + K(shard_name), "testload_prefix", testload_prefix_, K(ret)); + } + } else if (OB_FAIL(get_shard_connector(shard_name, shard_conn))) { + LOG_WARN("shard connector does not exist", K(shard_name), K(ret)); + } + } + + if (NULL != shard_tpo) { + shard_tpo->dec_ref(); + shard_tpo = NULL; + } + + return ret; +} + int ObDbConfigLogicDb::get_all_shard_table(ObIArray &all_table) { int ret = OB_SUCCESS; @@ -2193,7 +2284,7 @@ int64_t ObShardConnector::to_string(char *buf, const int64_t buf_len) const J_OBJ_START(); pos += ObDbConfigChild::to_string(buf + pos, buf_len - pos); J_COMMA(); - J_KV(K_(shard_name), K_(shard_type), K_(shard_url), K_(username), K_(password), + J_KV(K_(shard_name), K_(shard_type), K_(shard_url), K_(username), K_(database_name), K_(tenant_name), K_(cluster_name), K_(server_type), K_(physic_addr), K_(is_physic_ip), K_(physic_port), K_(read_consistency), "enc_type", get_enc_type_str(enc_type_)); @@ -3729,7 +3820,8 @@ int ObDbConfigLogicDb::get_shard_table_info(const ObString &table_name, char *real_table_name, int64_t tb_name_len, int64_t &group_index, int64_t &tb_index, int64_t &es_index, const ObString &hint_table, ObTestLoadType testload_type, - const bool is_read_stmt) + const bool is_read_stmt, + const int64_t last_es_index /*OBPROXY_MAX_DBMESH_ID*/) { int ret = OB_SUCCESS; @@ -3766,7 +3858,12 @@ int ObDbConfigLogicDb::get_shard_table_info(const ObString &table_name, bool is_elastic_index = true; ObString shard_name; if (-1 == es_index || (OBPROXY_MAX_DBMESH_ID == es_index && logic_tb_info->es_rules_.empty())) { - if (OB_FAIL(gc_info->get_elastic_id_by_weight(es_index, is_read_stmt))) { + if (is_read_stmt + && (last_es_index >= 0) + && (last_es_index < es_size)) { + //In multiple statements, the read request can use the effective es id of the previous statement + es_index = last_es_index; + } else if (OB_FAIL(gc_info->get_elastic_id_by_weight(es_index, is_read_stmt))) { LOG_WARN("fail to get eid by read weight", KPC(gc_info)); } else { LOG_DEBUG("succ to get eid by weight", K(es_index)); @@ -3850,7 +3947,7 @@ int ObDbConfigLogicDb::get_single_table_info(const ObString &table_name, char *real_table_name, int64_t tb_name_len, int64_t &group_id, int64_t &table_id, int64_t &es_id, const ObString &hint_table, ObTestLoadType testload_type, - const bool is_read_stmt) + const bool is_read_stmt, const int64_t last_es_id/*OBPROXY_MAX_DBMESH_ID*/) { int ret = OB_SUCCESS; @@ -3871,7 +3968,12 @@ int ObDbConfigLogicDb::get_single_table_info(const ObString &table_name, const ObGroupCluster &gc_info = *it; int64_t es_size = gc_info.get_es_size(); if (es_id < 0 || OBPROXY_MAX_DBMESH_ID == es_id) { - if (OB_FAIL(gc_info.get_elastic_id_by_weight(es_id, is_read_stmt))) { + if (is_read_stmt + && (last_es_id >= 0) + && (last_es_id < es_size)) { + //In multiple statements, the read request can use the effective es id of the previous statement + es_id = last_es_id; + } if (OB_FAIL(gc_info.get_elastic_id_by_weight(es_id, is_read_stmt))) { LOG_WARN("fail to get random eid", K(gc_info)); } } else if (OB_UNLIKELY(es_id >= es_size)) { @@ -4135,10 +4237,26 @@ int ObDbConfigCache::load_local_dbconfig() } event::ObFixedArenaAllocator allocator; while (OB_SUCC(ret) && NULL != (ent = readdir(dbconfig_dir))) { - allocator.reuse(); - if (ent->d_type == DT_DIR - && LOCAL_DIR.compare(ent->d_name) != 0 - && PARENT_DIR.compare(ent->d_name) != 0) { + bool is_need_load = false; + if (LOCAL_DIR.compare(ent->d_name) == 0 || PARENT_DIR.compare(ent->d_name) == 0) { + // do nothing + } else if (ent->d_type == DT_DIR) { + is_need_load = true; + } else if (ent->d_type == DT_UNKNOWN) { + struct stat st; + char *full_path = NULL; + allocator.reuse(); + if (OB_FAIL(ObLayout::merge_file_path(layout_dbconfig_dir, ent->d_name, allocator, full_path))) { + LOG_WARN("fail to merge file", K(layout_dbconfig_dir), "name", ent->d_name, K(ret)); + } else if (0 != (stat(full_path, &st))) { + ret = OB_IO_ERROR; + LOG_WARN("fail to stat dir", K(full_path), KERRMSGS, K(ret)); + } else if (S_ISDIR(st.st_mode)) { + is_need_load = true; + } + } + + if (OB_SUCC(ret) && is_need_load) { if (OB_FAIL(load_logic_tenant_config(ObString::make_string(ent->d_name)))) { LOG_WARN("fail to load tenant config", "tenant_dir", ent->d_name, K(ret)); } @@ -4541,8 +4659,8 @@ int ObDbConfigLogicDb::get_table_name_by_index(ObSqlParseResult &parse_result, { int ret = OB_SUCCESS; - ObProxySelectStmt *select_stmt = static_cast(parse_result.get_proxy_stmt()); - ObProxySelectStmt::ExprMap &table_exprs_map = select_stmt->get_table_exprs_map(); + ObProxyDMLStmt *dml_stmt = static_cast(parse_result.get_proxy_stmt()); + ObProxyDMLStmt::ExprMap &table_exprs_map = dml_stmt->get_table_exprs_map(); SqlFieldResult &sql_result = parse_result.get_sql_filed_result(); char real_table_name[OB_MAX_TABLE_NAME_LENGTH]; @@ -4554,8 +4672,8 @@ int ObDbConfigLogicDb::get_table_name_by_index(ObSqlParseResult &parse_result, for (int64_t i = 0; OB_SUCC(ret) && i < table_index_array.count(); i++) { int64_t tb_index = table_index_array.at(i); - ObProxySelectStmt::ExprMap::iterator iter = table_exprs_map.begin(); - ObProxySelectStmt::ExprMap::iterator end = table_exprs_map.end(); + ObProxyDMLStmt::ExprMap::iterator iter = table_exprs_map.begin(); + ObProxyDMLStmt::ExprMap::iterator end = table_exprs_map.end(); table_name_map_wrapper.reuse(); for (; OB_SUCC(ret) && iter != end; iter++) { diff --git a/src/obproxy/dbconfig/ob_proxy_db_config_info.h b/src/obproxy/dbconfig/ob_proxy_db_config_info.h index 7465e7e4a9cf314e1c1c62f3fd695634a40a2aa2..faf21f07b14866e171e1ae275734c3eb199e0be5 100644 --- a/src/obproxy/dbconfig/ob_proxy_db_config_info.h +++ b/src/obproxy/dbconfig/ob_proxy_db_config_info.h @@ -936,7 +936,8 @@ public: char *real_table_name, int64_t tb_name_len, int64_t &group_id, int64_t &table_id, int64_t &es_id, const common::ObString &hint_table, - ObTestLoadType testload_type, const bool is_read_stmt); + ObTestLoadType testload_type, const bool is_read_stmt, + const int64_t last_es_id = OBPROXY_MAX_DBMESH_ID); int get_shard_table_info(const common::ObString &table_name, obutils::SqlFieldResult &sql_result, ObShardConnector *&shard_conn, @@ -944,7 +945,8 @@ public: char *real_table_name, int64_t tb_name_len, int64_t &group_index, int64_t &tb_index, int64_t &es_index, const common::ObString &hint_table, - ObTestLoadType testload_type, const bool is_read_stmt); + ObTestLoadType testload_type, const bool is_read_stmt, + const int64_t last_es_index = OBPROXY_MAX_DBMESH_ID); int get_shard_prop(const common::ObString & shard_name, ObShardProp* &shard_prop); int get_real_table_name(const ObString &table_name, obutils::SqlFieldResult &sql_result, @@ -968,6 +970,8 @@ public: int64_t es_index, common::ObIArray &group_index_array, common::ObIArray &shard_connector_array); + int get_first_group_shard_connector(ObShardConnector *&shard_conn, int64_t es_id, + bool is_read_stmt, ObTestLoadType testload_type); int get_table_name_by_index(obutils::ObSqlParseResult &parse_result, ObTestLoadType testload_type, ObIAllocator &allocator, diff --git a/src/obproxy/dbconfig/ob_proxy_db_config_processor.cpp b/src/obproxy/dbconfig/ob_proxy_db_config_processor.cpp index 529410593abea0572983c45d8f9453379634931e..d417f73ae70b0da2289369a5982ff2b1163cb2d6 100644 --- a/src/obproxy/dbconfig/ob_proxy_db_config_processor.cpp +++ b/src/obproxy/dbconfig/ob_proxy_db_config_processor.cpp @@ -45,7 +45,7 @@ ObDbConfigProcessor &get_global_db_config_processor() //------ ObDbConfigProcessor------ ObDbConfigProcessor::ObDbConfigProcessor() - : is_inited_(false), is_config_inited_(false), is_bt_updated_(false), startup_time_str_(), gc_pool_() + : is_inited_(false), is_config_inited_(false), is_client_avail_(false), is_bt_updated_(false), startup_time_str_(), gc_pool_() { startup_time_buf_[0] = '\0'; } @@ -53,32 +53,19 @@ ObDbConfigProcessor::ObDbConfigProcessor() int ObDbConfigProcessor::init(const int64_t client_count, int64_t startup_time_us) { int ret = OB_SUCCESS; - bool is_client_avail = false; if (OB_UNLIKELY(is_inited_)) { ret = OB_INIT_TWICE; LOG_WARN("init twice", K(ret)); } else if (OB_FAIL(set_startup_time(startup_time_us))) { LOG_WARN("fail to set startup time", K(startup_time_us), K(ret)); - } else if (!get_global_proxy_config().use_local_dbconfig && OB_FAIL(gc_pool_.init(client_count, is_client_avail))) { - LOG_WARN("fail to init grpc client pool", K(client_count), K(is_client_avail), K(ret)); + } else if (!get_global_proxy_config().use_local_dbconfig && OB_FAIL(gc_pool_.init(client_count, is_client_avail_))) { + LOG_WARN("fail to init grpc client pool", K(client_count), K_(is_client_avail), K(ret)); + } else if (get_global_proxy_config().use_local_dbconfig && OB_FAIL(get_global_inotify_processor().init())) { + LOG_WARN("fail to init inotify processor", K(ret)); } else { is_inited_ = true; } - if (!is_client_avail) { - LOG_INFO("grpc client pool is not avail, will load local dbmesh config", K(is_client_avail)); - if (OB_FAIL(get_global_dbconfig_cache().load_local_dbconfig())) { - LOG_WARN("fail to load local dbconfig, we can fetch from dataplane later", K(ret)); - } else { - is_config_inited_ = true; - LOG_INFO("succ to load local dbconfig"); - } - } - if (OB_SUCC(ret)) { - if (get_global_proxy_config().use_local_dbconfig - && OB_FAIL(get_global_inotify_processor().init())) { - LOG_WARN("fail to init inotify processor", K(ret)); - } - } + return ret; } @@ -93,6 +80,42 @@ int ObDbConfigProcessor::set_startup_time(int64_t startup_time_us) return ret; } +int ObDbConfigProcessor::start() +{ + int ret = OB_SUCCESS; + if (!get_global_proxy_config().use_local_dbconfig) { + if (!is_client_avail_) { + LOG_INFO("grpc client pool is not avail, will load local sharding config"); + if (OB_FAIL(get_global_dbconfig_cache().load_local_dbconfig())) { + LOG_WARN("fail to load local dbconfig, we can fetch from dataplane later", K(ret)); + } else { + is_config_inited_ = true; + LOG_INFO("succ to load local dbconfig"); + } + } else if (OB_FAIL(init_sharding_config())) { + LOG_ERROR("fail to init sharding config", K(ret)); + } + + if (OB_SUCC(ret) && get_global_proxy_config().is_control_plane_used()) { + if (OB_FAIL(start_watch_parent_crd())) { + LOG_WARN("fail to start watch parent crd", K(ret)); + } + } + } else { + if (OB_FAIL(get_global_dbconfig_cache().load_local_dbconfig())) { + LOG_WARN("fail to load local dbconfig when use_local_dbconfig", K(ret)); + } else { + is_config_inited_ = true; + LOG_INFO("succ to load local dbconfig"); + if (OB_FAIL(get_global_inotify_processor().start_watch_sharding_config())) { + LOG_WARN("fail to start inotify watch sharding config", K(ret)); + } + } + } + + return ret; +} + int ObDbConfigProcessor::start_watch_parent_crd() { int ret = OB_SUCCESS; diff --git a/src/obproxy/dbconfig/ob_proxy_db_config_processor.h b/src/obproxy/dbconfig/ob_proxy_db_config_processor.h index 62802a5f41455a26625d3fe1b0ccff3e59635f8a..4b27dcef96368a6e4c08b15f28ff43e05f1e9368 100644 --- a/src/obproxy/dbconfig/ob_proxy_db_config_processor.h +++ b/src/obproxy/dbconfig/ob_proxy_db_config_processor.h @@ -38,6 +38,7 @@ public: ~ObDbConfigProcessor() {} int init(const int64_t client_count, int64_t startup_time_us); + int start(); int init_sharding_config(); int start_watch_parent_crd(); bool is_config_inited() const { return is_config_inited_; } @@ -52,6 +53,7 @@ public: private: bool is_inited_; bool is_config_inited_; + bool is_client_avail_; bool is_bt_updated_; common::ObString startup_time_str_; char startup_time_buf_[common::OB_MAX_TIMESTAMP_LENGTH]; diff --git a/src/obproxy/dbconfig/ob_proxy_pb_utils.cpp b/src/obproxy/dbconfig/ob_proxy_pb_utils.cpp index dd0a3f4115d111a44aeebb115351d2e832dc1bf2..82f3af9946f6001e783eb2bb60b240ba330020de 100644 --- a/src/obproxy/dbconfig/ob_proxy_pb_utils.cpp +++ b/src/obproxy/dbconfig/ob_proxy_pb_utils.cpp @@ -26,6 +26,7 @@ #include "utils/ob_layout.h" #include "utils/ob_proxy_blowfish.h" #include "obutils/ob_proxy_config_utils.h" +#include "proxy/mysqllib/ob_proxy_auth_parser.h" #include "dbconfig/protobuf/dds-api/database.pb.h" #include "dbconfig/protobuf/dds-api/databaseAuthorities.pb.h" #include "dbconfig/protobuf/dds-api/databaseVariables.pb.h" @@ -448,19 +449,25 @@ int ObProxyPbUtils::parse_shard_url(const std::string &shard_url, ObShardConnect void ObProxyPbUtils::parse_shard_auth_user(ObShardConnector &conn_info) { - const static char separator = ':'; - const char *pos = NULL; + int ret = OB_SUCCESS; + + bool is_standard_username = false; + char separator = '\0'; ObString full_user_name = conn_info.full_username_.config_string_; ObString user; ObString tenant; ObString cluster; - pos = full_user_name.find(separator); - cluster = full_user_name.split_on(pos); - tenant = full_user_name.split_on(separator); - user = full_user_name; - conn_info.tenant_name_.assign_ptr(tenant.ptr(), tenant.length()); - conn_info.cluster_name_.assign_ptr(cluster.ptr(), cluster.length()); - conn_info.username_.assign_ptr(user.ptr(), user.length()); + ObString cluster_id_str; + + ObProxyAuthParser::analyze_user_name_attr(full_user_name, is_standard_username, separator); + if (OB_FAIL(ObProxyAuthParser::handle_full_user_name(full_user_name, separator, user, tenant, + cluster, cluster_id_str))) { + LOG_WARN("fail to handle full user name", K(full_user_name), K(separator), K(ret)); + } else { + conn_info.tenant_name_.assign_ptr(tenant.ptr(), tenant.length()); + conn_info.cluster_name_.assign_ptr(cluster.ptr(), cluster.length()); + conn_info.username_.assign_ptr(user.ptr(), user.length()); + } } int ObProxyPbUtils::dump_tenant_info_to_file(ObDbConfigLogicTenant &tenant_info) diff --git a/src/obproxy/driver/c/Makemodule.am b/src/obproxy/driver/c/Makemodule.am new file mode 100644 index 0000000000000000000000000000000000000000..ffb8c232c3909d3141599518f685aadc7678a34e --- /dev/null +++ b/src/obproxy/driver/c/Makemodule.am @@ -0,0 +1,3 @@ +obproxy_c_driver_sources:=\ +obproxy/driver/c/ob_proxy_vc_c.h\ +obproxy/driver/c/ob_proxy_vc_c.cpp \ No newline at end of file diff --git a/src/obproxy/driver/c/ob_proxy_vc_c.cpp b/src/obproxy/driver/c/ob_proxy_vc_c.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b5d8e17f3f07d7a644ef7d22dfd8b28db024e40b --- /dev/null +++ b/src/obproxy/driver/c/ob_proxy_vc_c.cpp @@ -0,0 +1,231 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#include "ob_proxy_vc_c.h" +#include "proxy/client/ob_driver_client.h" +#include "ob_proxy_init.h" +#include "lib/oblog/ob_log.h" +#include "lib/objectpool/ob_concurrency_objpool.h" + +#include + +using namespace oceanbase::common; +using namespace oceanbase::obproxy; +using namespace oceanbase::obproxy::proxy; + +int ob_proxy_vc_c_init(const char *config, void **p_driver_client) +{ + int ret = OB_SUCCESS; + ObDriverClient *driver_client = NULL; + + if (OB_ISNULL(config) || OB_ISNULL(p_driver_client)) { + ret = OB_INVALID_ARGUMENT; + MPRINT("invalid argument config=%p, p_driver_client=%p, ret=%d", config, p_driver_client, ret); + } else if (OB_FAIL(init_obproxy_client(config))) { + MPRINT("init obproxy client failed, ret=%d", ret); + } else if (OB_ISNULL(driver_client = new(std::nothrow) ObDriverClient())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + OBPROXY_DRIVER_CLIENT_LOG(WARN, "driver client is null unexpected", K(ret)); + } else if (OB_FAIL(driver_client->init())) { + OBPROXY_DRIVER_CLIENT_LOG(WARN, "driver client init failed", K(ret)); + } else { + *p_driver_client = static_cast(driver_client); + OBPROXY_DRIVER_CLIENT_LOG(DEBUG, "create driver_client success", KP(driver_client)); + } + + if(OB_FAIL(ret) && OB_NOT_NULL(driver_client)) { + delete driver_client; + } + + return ret; +} + +int ob_proxy_vc_c_connect(void *driver_client_handle, int64_t conn_timeout, int64_t sock_timeout) +{ + int ret = OB_SUCCESS; + ObDriverClient *driver_client; + + if (OB_ISNULL(driver_client_handle) || conn_timeout < 0 || sock_timeout < 0) { + ret = OB_INVALID_ARGUMENT; + OBPROXY_DRIVER_CLIENT_LOG(WARN, "invalid argument", KP(driver_client_handle), K(conn_timeout), K(sock_timeout), K(ret)); + } else { + driver_client = static_cast(driver_client_handle); + driver_client->set_connect_timeout(conn_timeout); + + if (conn_timeout == 0 && OB_FAIL(driver_client->sync_connect())) { + OBPROXY_DRIVER_CLIENT_LOG(WARN, "driver client connect failed", K(ret)); + } else if (conn_timeout > 0 && OB_FAIL(driver_client->sync_connect_with_timeout())) { + OBPROXY_DRIVER_CLIENT_LOG(WARN, "driver client connect with timeout failed", K(conn_timeout), K(ret)); + } else { + driver_client->set_send_timeout(sock_timeout); + driver_client->set_recv_timeout(sock_timeout); + OBPROXY_DRIVER_CLIENT_LOG(DEBUG, "driver client connect success", K(driver_client)); + } + } + + return ret; +} + +int ob_proxy_vc_c_recv(void *driver_client_handle, char *buffer, int64_t offset, int64_t mlen, int64_t *recv_len, int64_t flag) +{ + int ret = OB_SUCCESS; + int64_t rlen = 0; + ObDriverClient *driver_client; + UNUSED(flag); + + if (OB_ISNULL(driver_client_handle) || OB_ISNULL(buffer) || OB_ISNULL(recv_len)) { + ret = OB_INVALID_ARGUMENT; + OBPROXY_DRIVER_CLIENT_LOG(WARN, "invalid argument", KP(driver_client_handle), K(buffer), K(recv_len), K(ret)); + } else { + driver_client = static_cast(driver_client_handle); + if (OB_FAIL(driver_client->sync_recv_with_timeout(buffer + offset, mlen, rlen))) { + OBPROXY_DRIVER_CLIENT_LOG(WARN, "sync recv failed", K(ret)); + } else { + if (rlen < 0) { + switch (errno) { + case ECONNRESET: + case EPIPE: + OBPROXY_DRIVER_CLIENT_LOG(WARN, "Connection reset", "errno", errno); + break; + case EBADF: + OBPROXY_DRIVER_CLIENT_LOG(WARN, "Socket closed", "errno", errno); + break; + case EINTR: + OBPROXY_DRIVER_CLIENT_LOG(WARN, "Operation interrupted", "errno", errno); + break; + default: + OBPROXY_DRIVER_CLIENT_LOG(WARN, "socket read error", "errno", errno); + break; + } + ret = OB_ERR_UNEXPECTED; + } else if (rlen == 0) { + ret = OB_ERR_UNEXPECTED; + OBPROXY_DRIVER_CLIENT_LOG(WARN, "peer close", KP(driver_client), K(ret)); + } else { + OBPROXY_DRIVER_CLIENT_LOG(DEBUG, "read success", K(rlen)); + *recv_len = rlen; + } + } + } + + return ret; +} + +int ob_proxy_vc_c_send(void *driver_client_handle, const char *buffer, int64_t offset, int64_t mlen, int64_t *send_len, int64_t flag) +{ + int ret = OB_SUCCESS; + int64_t wlen = 0; + ObDriverClient *driver_client; + UNUSED(flag); + + if (OB_ISNULL(driver_client_handle) || OB_ISNULL(buffer) || OB_ISNULL(send_len)) { + ret = OB_INVALID_ARGUMENT; + OBPROXY_DRIVER_CLIENT_LOG(WARN, "invalid argument", KP(driver_client_handle), K(buffer), K(send_len), K(ret)); + } else { + driver_client = static_cast(driver_client_handle); + + if (OB_FAIL(driver_client->sync_send_with_timeout(buffer + offset, mlen, wlen))) { + ret = OB_ERR_UNEXPECTED; //send error; + OBPROXY_DRIVER_CLIENT_LOG(WARN, "sync_send_with_timeout failed", K(wlen), K(ret)); + } else { + if (wlen > 0) { + OBPROXY_DRIVER_CLIENT_LOG(DEBUG, "sync write success", K(wlen)); + *send_len = wlen; + } else { + ret = ob_get_sys_errno(); + if (errno == ECONNRESET) { + OBPROXY_DRIVER_CLIENT_LOG(WARN, "wlen is unexpected, connection reset", K(wlen), K(ret)); + } else { + OBPROXY_DRIVER_CLIENT_LOG(WARN, "wlen is unexpected, write failed", K(wlen), K(ret)); + } + } + } + } + + return ret; +} + +int ob_proxy_vc_c_close(void *driver_client_handle) +{ + int ret = OB_SUCCESS; + ObDriverClient *driver_client; + + if (OB_ISNULL(driver_client_handle)) { + ret = OB_INVALID_ARGUMENT; + OBPROXY_DRIVER_CLIENT_LOG(WARN, "invalid argument", KP(driver_client_handle), K(ret)); + } else { + OBPROXY_DRIVER_CLIENT_LOG(DEBUG, "free driver client", KP(driver_client_handle)); + driver_client = static_cast(driver_client_handle); + delete driver_client; + driver_client = NULL; + } + + return ret; +} + +int ob_proxy_vc_set_timeout(void *driver_client_handle, int type, int timeout) +{ + int ret = OB_SUCCESS; + ObDriverClient *driver_client; + const int C_DRIVER_CONNECT_TIMEOUT = 0; + const int C_DRIVER_READ_TIMEOUT = 1; + const int C_DRIVER_WRITE_TIMEOUT = 2; + const int C_DRIVER_TIMEOUT_MAX = 3; + + if (OB_ISNULL(driver_client_handle) || type < 0 || C_DRIVER_TIMEOUT_MAX <= type) { + ret = OB_INVALID_ARGUMENT; + OBPROXY_DRIVER_CLIENT_LOG(WARN, "invalid argument", KP(driver_client_handle), K(type), K(ret)); + } else { + driver_client = static_cast(driver_client_handle); + + if (C_DRIVER_CONNECT_TIMEOUT == type) { + driver_client->set_connect_timeout(timeout); + } else if (C_DRIVER_READ_TIMEOUT == type) { + driver_client->set_recv_timeout(timeout); + } else if (C_DRIVER_WRITE_TIMEOUT == type) { + driver_client->set_send_timeout(timeout); + } + + OBPROXY_DRIVER_CLIENT_LOG(DEBUG, "driver client set timeout succ", K(type), K(timeout)); + } + + return ret; +} + +int ob_proxy_vc_get_timeout(void *driver_client_handle, int type, int *timeout) +{ + int ret = OB_SUCCESS; + ObDriverClient *driver_client; + const int C_DRIVER_CONNECT_TIMEOUT = 0; + const int C_DRIVER_READ_TIMEOUT = 1; + const int C_DRIVER_WRITE_TIMEOUT = 2; + const int C_DRIVER_TIMEOUT_MAX = 3; + + if (OB_ISNULL(driver_client_handle) || OB_ISNULL(timeout) || type < C_DRIVER_CONNECT_TIMEOUT || C_DRIVER_TIMEOUT_MAX <= type) { + ret = OB_INVALID_ARGUMENT; + OBPROXY_DRIVER_CLIENT_LOG(WARN, "invalid argument", KP(driver_client_handle), KP(timeout), K(type), K(ret)); + } else { + driver_client = static_cast(driver_client_handle); + + if (C_DRIVER_CONNECT_TIMEOUT == type) { + *timeout = static_cast(driver_client->get_connect_timeout()); + } else if (C_DRIVER_READ_TIMEOUT == type) { + *timeout = static_cast(driver_client->get_recv_timeout()); + } else if (C_DRIVER_WRITE_TIMEOUT == type) { + *timeout = static_cast(driver_client->get_send_timeout()); + } + + OBPROXY_DRIVER_CLIENT_LOG(DEBUG, "driver client get timeout succ", K(type), "timeout", *timeout); + } + + return ret; +} \ No newline at end of file diff --git a/src/obproxy/driver/c/ob_proxy_vc_c.h b/src/obproxy/driver/c/ob_proxy_vc_c.h new file mode 100644 index 0000000000000000000000000000000000000000..80f37d8ae90894e1834e47a0681a106f23004ae9 --- /dev/null +++ b/src/obproxy/driver/c/ob_proxy_vc_c.h @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef _OB_OPROXY_VC_C_H +#define _OB_OPROXY_VC_C_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief + * libobclient calls this function to init obproxy and get driver_client handle + * @param config obproxy config string + * @param driver_client point to driver_client handle + * @return int OB_SUCCESS means success and other means failure + */ +int ob_proxy_vc_c_init(const char *config, void **driver_client); + +/** + * @brief + * libobclient calls this function to connect to obproxy + * @param driver_client driver_client handle + * @param conn_timeout connection timeout + * @param sock_timeout socket timeout + * @return int + */ +int ob_proxy_vc_c_connect(void *driver_client, int64_t conn_timeout, int64_t sock_timeout); + +/** + * @brief + * libobclient calls this function to receive data from obproxy + * @param driver_client driver_client handle + * @param buffer receive buffer + * @param offset buffer offset + * @param mlen max receive length + * @param recv_len point to receive length + * @param flag receive flag + * @return int + */ +int ob_proxy_vc_c_recv(void *driver_client, char *buffer, int64_t offset, int64_t mlen, int64_t *recv_len, int64_t flag); + +/** + * @brief + * libobclient calls this function to send data to obproxy + * @param driver_client driver_client handle + * @param buffer send buffer + * @param offset buffer offset + * @param mlen send buffer len + * @param send_len point to send length + * @param flag send flag + * @return int + */ +int ob_proxy_vc_c_send(void *driver_client, const char *buffer, int64_t offset, int64_t mlen, int64_t *send_len, int64_t flag); + +/** + * @brief + * libobclient calls this function to close driver client, but not stop obproxy service + * @param driver_client driver_client handle + * @return int + */ +int ob_proxy_vc_c_close(void *driver_client); + +/** + * @brief + * libobclient calls this function to set timeout + * @param driver_client driver_client handle + * @param type type for timeout + * @param timeout ms + * @return int + */ +int ob_proxy_vc_set_timeout(void *driver_client, int type, int timeout); + +/** + * @brief + * libobclient calls this function to get timeout + * @param driver_client driver_client handle + * @param type type for timeout + * @param timeout ms + * @return int + */ +int ob_proxy_vc_get_timeout(void *driver_client_handle, int type, int *timeout); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_OB_OPROXY_VC_JNI_H */ \ No newline at end of file diff --git a/src/obproxy/engine/Makemodule.am b/src/obproxy/engine/Makemodule.am index 75b4e148bc4d9a098cec31c39e97705ec373df4d..44a328ebcf9a5d0fcdd93e5a482de18bbd9fbb7f 100644 --- a/src/obproxy/engine/Makemodule.am +++ b/src/obproxy/engine/Makemodule.am @@ -11,4 +11,6 @@ obproxy/engine/ob_proxy_operator_agg.cpp\ obproxy/engine/ob_proxy_operator_table_scan.h\ obproxy/engine/ob_proxy_operator_table_scan.cpp\ obproxy/engine/ob_proxy_operator_async_task.h\ -obproxy/engine/ob_proxy_operator_async_task.cpp +obproxy/engine/ob_proxy_operator_async_task.cpp\ +obproxy/engine/ob_proxy_operator_cont.h\ +obproxy/engine/ob_proxy_operator_cont.cpp diff --git a/src/obproxy/engine/ob_proxy_operator_agg.cpp b/src/obproxy/engine/ob_proxy_operator_agg.cpp index 959d9f4f6d7864e0143e6998ef0ed97d43e30f8f..2f3d9f0ffec83be2ca9688cc2d24be77a7d5fbd9 100644 --- a/src/obproxy/engine/ob_proxy_operator_agg.cpp +++ b/src/obproxy/engine/ob_proxy_operator_agg.cpp @@ -604,7 +604,7 @@ int ObProxyStreamAggOp::handle_response_result(void *data, bool &is_final, ObPro ResultRow *row = NULL; while (OB_SUCC(ret) && OB_SUCC(opres->next(row))) { ObProxyGroupUnit group_unit(allocator_); - if (OB_FAIL(group_unit.init(row, group_exprs))) { + if (OB_FAIL(group_unit.init(row, result_fields_, group_exprs))) { LOG_WARN("fail to init group unit", K(ret)); } else if (NULL == current_group_unit_) { if (OB_FAIL(ObProxyGroupUnit::create_group_unit(allocator_, current_group_unit_, group_unit))) { @@ -732,7 +732,7 @@ int ObProxyMemMergeAggOp::handle_response_result(void *data, bool &is_final, ObP while (OB_SUCC(ret) && OB_SUCC(opres->next(row))) { ObProxyGroupUnit group_unit(allocator_); ObProxyGroupUnit *current_group_unit = NULL; - if (OB_FAIL(group_unit.init(row, group_exprs))) { + if (OB_FAIL(group_unit.init(row, result_fields_, group_exprs))) { LOG_WARN("fail to init group unit", K(ret)); } else if (OB_FAIL(group_unit_map_.get_refactored(group_unit, current_group_unit))) { if (OB_HASH_NOT_EXIST == ret) { @@ -827,7 +827,8 @@ ObProxyGroupUnit::~ObProxyGroupUnit() } } -int ObProxyGroupUnit::init(ResultRow *row, const ObIArray& group_exprs) +int ObProxyGroupUnit::init(ResultRow *row, ResultFields *result_fields, + const ObIArray& group_exprs) { int ret = OB_SUCCESS; @@ -837,11 +838,21 @@ int ObProxyGroupUnit::init(ResultRow *row, const ObIArray& gr for (int64_t i = 0; OB_SUCC(ret) && i < group_exprs.count(); i++) { if (OB_FAIL(group_exprs.at(i)->calc(ctx, calc_item, group_values_))) { LOG_WARN("fail to calc group exprs", K(ret)); + } else { + int64_t index = group_exprs.at(i)->get_expr()->get_index(); + if (-1 != index) { + ObObj &value = group_values_.at(i); + if (OB_FAIL(change_sql_value(value, result_fields->at(index), &allocator_))) { + LOG_WARN("fail to change sql value", K(value), + "filed", result_fields->at(index), K(ret)); + } + } } } if (OB_SUCC(ret)) { row_ = row; + result_fields_ = result_fields; } return ret; @@ -880,6 +891,7 @@ int ObProxyGroupUnit::assign(const ObProxyGroupUnit &group_unit) LOG_WARN("fail to assign group value", K(ret)); } else { row_ = group_unit.get_row(); + result_fields_ = group_unit.get_result_fields(); } return ret; @@ -898,8 +910,19 @@ int ObProxyGroupUnit::do_aggregate(ResultRow *row) agg_values.reuse(); if (OB_FAIL(agg_unit->get_agg_expr()->calc(ctx, calc_item, agg_values))) { LOG_WARN("fail to calc agg expr", K(ret)); - } else if (OB_FAIL(agg_unit->merge(agg_values))) { - LOG_WARN("fail to merge agg value", K(ret)); + } else { + int64_t index = agg_unit->get_agg_expr()->get_index(); + if (-1 != index) { + ObObj &value = agg_values.at(0); + if (OB_FAIL(change_sql_value(value, result_fields_->at(index), &allocator_))) { + LOG_WARN("fail to change sql value", K(value), + "filed", result_fields_->at(index), K(ret)); + } + } + + if (OB_SUCC(ret) && OB_FAIL(agg_unit->merge(agg_values))) { + LOG_WARN("fail to merge agg value", K(ret)); + } } } diff --git a/src/obproxy/engine/ob_proxy_operator_agg.h b/src/obproxy/engine/ob_proxy_operator_agg.h index 223d84968a6ed8cca1a1c5c2ee7c2f170d0439d3..82792f3f59240852c598ad97a3a3cb9f0fc242d0 100644 --- a/src/obproxy/engine/ob_proxy_operator_agg.h +++ b/src/obproxy/engine/ob_proxy_operator_agg.h @@ -350,12 +350,13 @@ class ObProxyGroupUnit { public: ObProxyGroupUnit(common::ObIAllocator &allocator) - : allocator_(allocator), row_(NULL), + : allocator_(allocator), row_(NULL), result_fields_(NULL), group_values_(ObModIds::OB_SE_ARRAY_ENGINE, ENGINE_ARRAY_NEW_ALLOC_SIZE), agg_units_(ObModIds::OB_SE_ARRAY_ENGINE, ENGINE_ARRAY_NEW_ALLOC_SIZE) {} ~ObProxyGroupUnit(); - int init(ResultRow *row, const common::ObIArray& group_by_exprs); + int init(ResultRow *row, ResultFields *result_fields, + const common::ObIArray& group_by_exprs); uint64_t hash() const; bool operator==(const ObProxyGroupUnit &group_unit) const; @@ -366,6 +367,7 @@ public: int set_agg_value(); ResultRow *get_row() const { return row_; } + ResultFields *get_result_fields() const { return result_fields_; } const common::ObIArray& get_group_values() const { return group_values_; } const common::ObIArray& get_agg_units() { return agg_units_;; } @@ -385,6 +387,7 @@ public: private: common::ObIAllocator &allocator_; ResultRow *row_; + ResultFields *result_fields_; common::ObSEArray group_values_; common::ObSEArray agg_units_; }; diff --git a/src/obproxy/engine/ob_proxy_operator_cont.cpp b/src/obproxy/engine/ob_proxy_operator_cont.cpp new file mode 100644 index 0000000000000000000000000000000000000000..edb49005137f7d342fee88547a97ea9a6fabdbbb --- /dev/null +++ b/src/obproxy/engine/ob_proxy_operator_cont.cpp @@ -0,0 +1,301 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#define USING_LOG_PREFIX PROXY + +#include "ob_proxy_operator_cont.h" +#include "lib/oblog/ob_log_module.h" + +using namespace oceanbase::common; +using namespace oceanbase::obproxy::event; +using namespace oceanbase::obproxy::obutils; + +namespace oceanbase +{ +namespace obproxy +{ +namespace engine +{ + +int ObProxyOperatorCont::init(ObProxyOperator* operator_root, uint8_t seq, const int64_t timeout_ms) +{ + int ret = OB_SUCCESS; + + if (OB_UNLIKELY(NULL != buf_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected buf is not null", K(ret)); + } else if (OB_ISNULL(buf_ = new_empty_miobuffer())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to new_empty_miobuffer for buf", K(ret)); + } else if (OB_ISNULL(buf_reader_ = buf_->alloc_reader())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to allocate buffer reader", K(ret)); + } else { + operator_root_ = operator_root; + timeout_ms_ = timeout_ms; + seq_ = seq; + } + + return ret; +} + +int ObProxyOperatorCont::main_handler(int event, void *data) +{ + int ret = OB_SUCCESS; + + if (NULL == execute_thread_) { + execute_thread_ = &self_ethread(); + } + + switch (event) { + case EVENT_INTERVAL: { + timeout_action_ = NULL; + // If it has been canceled, then the underlying operator has been released, + // and here we need to set pending_action_ to NULL + if (action_.cancelled_) { + pending_action_ = NULL; + } + + if (OB_FAIL(handle_timeout())) { + LOG_WARN("fail to handle timeout"); + } + break; + } + case EVENT_IMMEDIATE: { + pending_action_ = NULL; + if (OB_FAIL(cancel_timeout_action())) { + LOG_WARN("fail to cancel_timeout_action", K(ret)); + } else if (OB_FAIL(handle_event_start())) { + LOG_INFO("fail to handle event start", K(ret)); + } else if (OB_FAIL(schedule_timeout())) { + LOG_WARN("fail to schedule timeout action", K(ret)); + } + break; + } + case VC_EVENT_READ_COMPLETE: { + pending_action_ = NULL; + if (OB_FAIL(cancel_timeout_action())) { + LOG_WARN("fail to cancel_timeout_action", K(ret)); + } else if (OB_FAIL(handle_event_complete(data))) { + LOG_WARN("fail to handle event complete", K(ret)); + } + break; + } + case ASYNC_PROCESS_INFORM_OUT_EVENT: { + pending_action_ = NULL; + if (OB_FAIL(cancel_timeout_action())) { + LOG_WARN("fail to cancel_timeout_action", K(ret)); + } else if (OB_FAIL(handle_event_inform_out())) { + LOG_WARN("fail to handle inform out event", K(ret)); + } + break; + } + case VC_EVENT_ACTIVE_TIMEOUT: + case EVENT_ERROR: + default: { + pending_action_ = NULL; + if (OB_FAIL(cancel_timeout_action())) { + LOG_WARN("fail to cancel_timeout_action", K(ret)); + } else if (action_.cancelled_) { + terminate_ = true; + LOG_INFO("async task has been cancelled, will kill itself", K(ret)); + } else if (NULL != cb_cont_) { + need_callback_ = true; + } else { + terminate_ = true; + } + + if (EVENT_ERROR != event || VC_EVENT_ACTIVE_TIMEOUT != event) { + LOG_WARN("error state, nerver run here", K(event), K(ret)); + } else { + LOG_INFO("error state", K(event)); + } + break; + } + } + + if (!terminate_ && (need_callback_ || OB_FAIL(ret))) { + if (execute_thread_ == &self_ethread()) { + execute_thread_->is_need_thread_pool_event_ = true; + } + if (OB_FAIL(handle_callback())) { + LOG_WARN("fail to handle callback", K(ret)); + } + } + + if (terminate_) { + if (execute_thread_ == &self_ethread()) { + execute_thread_->is_need_thread_pool_event_ = true; + } + destroy(); + } + + return EVENT_DONE; +} + +int ObProxyOperatorCont::init_task() +{ + int ret = OB_SUCCESS; + + if (OB_FAIL(operator_root_->open(this, pending_action_, timeout_ms_))) { + LOG_WARN("fail to open operator", K_(timeout_ms), K(ret)); + } else if (OB_FAIL(operator_root_->get_next_row())) { + LOG_WARN("fail to get next row", K(ret)); + } else if (OB_ISNULL(pending_action_)) { + LOG_WARN("pending action should not be null", K(ret)); + } + + return ret; +} + +int ObProxyOperatorCont::finish_task(void *data) +{ + int ret = OB_SUCCESS; + + ObProxyResultResp *result_resp = reinterpret_cast(data); + if (result_resp->is_resultset_resp()) { + if (OB_FAIL(build_executor_resp(buf_, seq_, result_resp))) { + LOG_WARN("fail to build shard scan resp", K(ret)); + } + } else if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet(*buf_, seq_, result_resp->get_err_code(), result_resp->get_err_msg()))) { + LOG_WARN("fail to encode err pacekt buf", K_(seq), "errmsg", result_resp->get_err_msg(), + "errcode", result_resp->get_err_code(), K(ret)); + } + + return ret; +} + +int ObProxyOperatorCont::schedule_timeout() +{ + int ret = OB_SUCCESS; + + if (OB_UNLIKELY(NULL != timeout_action_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("timeout action must be NULL", K_(timeout_action), K(ret)); + } else if (OB_ISNULL(timeout_action_ = execute_thread_->schedule_in(this, HRTIME_MSECONDS(timeout_ms_)))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to schedule timeout", K_(timeout_action), K_(timeout_ms), K(ret)); + } + + return ret; +} + +int ObProxyOperatorCont::build_executor_resp(ObMIOBuffer *write_buf, uint8_t &seq, ObProxyResultResp *result_resp) +{ + int ret = OB_SUCCESS; + int64_t column_count = result_resp->get_column_count(); + ObSEArray *fields = NULL; + ObSEArray ob_fields; + + // header , cols , first eof + if (OB_SUCC(ret)) { + if (OB_FAIL(result_resp->get_fields(fields))) { + LOG_WARN("fail to push field", K(fields), K(ret)); + } else if (OB_ISNULL(fields)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fields should not be null", K(ret)); + } else if (OB_UNLIKELY(fields->count() != column_count)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fields count should equal column_count", K(column_count), "fileds count", fields->count(), K(ret)); + } else if (OB_FAIL(ObMysqlPacketUtil::encode_header(*write_buf, seq, *fields))) { + LOG_WARN("fail to encode header", K(fields), K(seq), K(ret)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < column_count; i++) { + obmysql::ObMySQLField &mysql_field = fields->at(i); + ObField ob_field; + if (OB_FAIL(ObSMUtils::to_ob_field(mysql_field, ob_field))) { + LOG_WARN("fail to covert to ob field", K(mysql_field), K(ret)); + } else if (OB_FAIL(ob_fields.push_back(ob_field))) { + LOG_WARN("fail to push ob field", K(ob_field), K(ret)); + } + } + } + } + + // rows + if (OB_SUCC(ret)) { + ObObj *objs = NULL; + int64_t buf_len = sizeof(ObObj) * column_count; + + if (OB_ISNULL(objs = static_cast(op_fixed_mem_alloc(buf_len)))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to alloc obj array", K(column_count), K(ret)); + } else { + ObNewRow row; + //ObSEArray *row_array; + ObSEArray *row_array; + while ((OB_SUCC(ret)) && (OB_SUCC(result_resp->next(row_array)))) { + if (OB_ISNULL(row_array)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("row_array should not be null", K(ret)); + } else if (OB_UNLIKELY(row_array->count() != column_count)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("row_array count should equal column_count", K(column_count), "row_array count", row_array->count(), K(ret)); + } + + for (int64_t i = 0; OB_SUCC(ret) && i < column_count; i++) { + objs[i] = *(row_array->at(i)); + } + + if (OB_SUCC(ret)) { + row.cells_ = objs; + row.count_ = column_count; + if (OB_FAIL(ObMysqlPacketUtil::encode_row_packet(*write_buf, seq, row, &ob_fields))) { + LOG_WARN("fail to encode row", K(seq), K(row), K(ret)); + } else { + row.reset(); + row_array = NULL; + } + } + } + + if (OB_ITER_END == ret) { + ret = OB_SUCCESS; + } + } + + if (OB_NOT_NULL(objs)) { + op_fixed_mem_free(objs, buf_len); + objs = NULL; + } + } + + // second eof + if (OB_SUCC(ret)) { + if (OB_FAIL(ObMysqlPacketUtil::encode_eof_packet(*write_buf, seq))) { + LOG_WARN("fail to encode row", K(seq), K(ret)); + } + } + + return ret; +} + +void ObProxyOperatorCont::destroy() +{ + LOG_DEBUG("ObProxyOperatorCont will be destroyed", KP(this)); + + if (OB_LIKELY(NULL != buf_reader_)) { + buf_reader_->dealloc(); + buf_reader_ = NULL; + } + + if (OB_LIKELY(NULL != buf_)) { + free_miobuffer(buf_); + buf_ = NULL; + } + + ObAsyncCommonTask::destroy(); +} + +} // end of namespace engine +} // end of namespace obproxy +} // end of namespace oceanbase diff --git a/src/obproxy/engine/ob_proxy_operator_cont.h b/src/obproxy/engine/ob_proxy_operator_cont.h new file mode 100644 index 0000000000000000000000000000000000000000..632fc91962afd71a1afe90c7b1ca0b0d99773ba8 --- /dev/null +++ b/src/obproxy/engine/ob_proxy_operator_cont.h @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef OBPROXY_OPERATOR_CONT_H +#define OBPROXY_OPERATOR_CONT_H + +#include "obutils/ob_async_common_task.h" +#include "ob_proxy_operator.h" + +namespace oceanbase +{ +namespace obproxy +{ +namespace engine +{ + +class ObProxyOperatorCont : public obutils::ObAsyncCommonTask +{ +public: + ObProxyOperatorCont(event::ObContinuation *cb_cont, event::ObEThread *submit_thread) + : ObAsyncCommonTask(cb_cont->mutex_, "operator cont", cb_cont, submit_thread), + seq_(0), timeout_ms_(0), operator_root_(NULL), execute_thread_(NULL), data_(NULL), + buf_(NULL), buf_reader_(NULL) + { + SET_HANDLER(&ObProxyOperatorCont::main_handler); + } + + ~ObProxyOperatorCont() {} + + int main_handler(int event, void *data); + int init(ObProxyOperator* operator_root, uint8_t seq, const int64_t timeout_ms = 0); + virtual int init_task(); + virtual int finish_task(void *data); + virtual void *get_callback_data() { return buf_reader_; } + virtual int schedule_timeout(); + virtual void destroy(); + +private: + int build_executor_resp(event::ObMIOBuffer *write_buf, uint8_t &seq, ObProxyResultResp *result_resp); + +private: + uint8_t seq_; + int64_t timeout_ms_; + ObProxyOperator* operator_root_; + event::ObEThread *execute_thread_; + void *data_; + event::ObMIOBuffer *buf_; + event::ObIOBufferReader *buf_reader_; + DISALLOW_COPY_AND_ASSIGN(ObProxyOperatorCont); +}; + +} // end of namespace engine +} // end of namespace obproxy +} // end of namespace oceanbase + +#endif // OBPROXY_OPERATOR_CONT_H diff --git a/src/obproxy/engine/ob_proxy_operator_result.h b/src/obproxy/engine/ob_proxy_operator_result.h index 575d7027becd5179f65700deeeb88e77d4c1bea2..05793b7ddf25f21572d4cab1e8ce4888eeaf8e7b 100644 --- a/src/obproxy/engine/ob_proxy_operator_result.h +++ b/src/obproxy/engine/ob_proxy_operator_result.h @@ -15,6 +15,7 @@ #include "common/ob_row.h" //#include "common/ob_field.h" #include "common/obsm_utils.h" +#include "common/ob_obj_cast.h" #include "rpc/obmysql/ob_mysql_field.h" #include "proxy/mysqllib/ob_resultset_fetcher.h" #include "lib/container/ob_se_array.h" @@ -123,6 +124,44 @@ int change_sql_field(const ObMysqlField *src_field, obmysql::ObMySQLField *&dst_ return ret; } +int change_sql_value(ObObj &value, obmysql::ObMySQLField &field, ObIAllocator *allocator) +{ + int ret = OB_SUCCESS; + + if (value.is_varchar()) { + ObObjType ob_type; + ObCollationType cs_type = static_cast(field.charsetnr_); + // utf8_general_ci => CS_TYPE_UTF8MB4_GENERAL_CI + if (33 == field.charsetnr_) { + cs_type = CS_TYPE_UTF8MB4_GENERAL_CI; + // utf8_bin => CS_TYPE_UTF8MB4_BIN + } else if (83 == field.charsetnr_) { + cs_type = CS_TYPE_UTF8MB4_BIN; + } + + value.set_collation_type(cs_type); + + if (0 != value.get_string_len()) { + // Convert the column to a specific type, if it cannot be converted, keep varchar + if (OB_FAIL(ObSMUtils::get_ob_type(ob_type, field.type_))) { + COMMON_LOG(INFO, "cast ob type from mysql type failed", K(ob_type), "elem_type", field.type_, K(ret)); + ret = OB_SUCCESS; + } else if (ObTimestampType == ob_type || ObTimeType == ob_type + || ObDateType == ob_type || ObDateTimeType == ob_type) { + //do nothing + } else { + ObCastCtx cast_ctx(allocator, NULL, CM_NULL_ON_WARN, cs_type); + // use src_obj as buf_obj + if (OB_FAIL(ObObjCasterV2::to_type(ob_type, cs_type, cast_ctx, value, value))) { + COMMON_LOG(WARN, "failed to cast obj", "row", value, K(ob_type), K(cs_type), K(ret)); + } + } + } + } + + return ret; +} + class ObProxyResultResp : public executor::ObProxyParallelResp { public: diff --git a/src/obproxy/engine/ob_proxy_operator_sort.cpp b/src/obproxy/engine/ob_proxy_operator_sort.cpp index 8f3122258877f24595b7f3f89f563f25391eb52f..3ee286fda8ac2b6edacc20a7a2fb1aa905855bf0 100644 --- a/src/obproxy/engine/ob_proxy_operator_sort.cpp +++ b/src/obproxy/engine/ob_proxy_operator_sort.cpp @@ -405,7 +405,7 @@ int ObProxyMemMergeSortOp::handle_response_result(void *data, bool &is_final, Ob } else if (OB_ISNULL(sort_unit = new (tmp_buf) ObProxyMemMergeSortUnit(allocator_))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to new merge sort unit", K(ret)); - } else if (OB_FAIL(sort_unit->init(row, input->get_order_exprs()))) { + } else if (OB_FAIL(sort_unit->init(row, result_fields_, input->get_order_exprs()))) { LOG_WARN("fail to init sort unit", K(ret)); } else if (OB_FAIL(sort_units_.push_back(sort_unit))) { LOG_WARN("fail to push back sort unit", K(ret)); @@ -460,7 +460,7 @@ int ObProxyMemMergeSortOp::handle_response_result(void *data, bool &is_final, Ob return ret; } -int ObProxyMemMergeSortUnit::init(ResultRow *row, ObIArray &order_exprs) +int ObProxyMemMergeSortUnit::init(ResultRow *row, ResultFields *result_fields, ObIArray &order_exprs) { int ret = OB_SUCCESS; @@ -468,6 +468,7 @@ int ObProxyMemMergeSortUnit::init(ResultRow *row, ObIArray &o LOG_WARN("fail to assign order exprs", K(ret)); } else { row_ = row; + result_fields_ = result_fields; if (OB_FAIL(calc_order_values())) { LOG_WARN("fail to get order value", K(ret)); } @@ -487,6 +488,15 @@ int ObProxyMemMergeSortUnit::calc_order_values() for (int64_t i = 0; OB_SUCC(ret) && i < order_exprs_.count(); i++) { if (OB_FAIL(order_exprs_.at(i)->calc(ctx, calc_item, order_values_))) { LOG_WARN("fail to calc order exprs", K(ret)); + } else { + int64_t index = order_exprs_.at(i)->get_expr()->get_index(); + if (-1 != index) { + ObObj &value = order_values_.at(i); + if (OB_FAIL(change_sql_value(value, result_fields_->at(index), &allocator_))) { + LOG_WARN("fail to change sql value", K(value), + "filed", result_fields_->at(index), K(ret)); + } + } } } @@ -566,7 +576,7 @@ int ObProxyStreamSortOp::handle_response_result(void *data, bool &is_final, ObPr } else if (OB_ISNULL(sort_unit = new (tmp_buf) ObProxyStreamSortUnit(allocator_))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to new merge sort unit", K(ret)); - } else if (OB_FAIL(sort_unit->init(opres, input->get_order_exprs()))) { + } else if (OB_FAIL(sort_unit->init(opres, result_fields_, input->get_order_exprs()))) { LOG_WARN("fail to init sort unit", K(ret)); } else if (OB_FAIL(sort_units_.push_back(sort_unit))) { LOG_WARN("fail to push back sort unit", K(ret)); @@ -638,7 +648,8 @@ int ObProxyStreamSortOp::handle_response_result(void *data, bool &is_final, ObPr return ret; } -int ObProxyStreamSortUnit::init(ObProxyResultResp* result_set, common::ObIArray &order_exprs) +int ObProxyStreamSortUnit::init(ObProxyResultResp* result_set, ResultFields *result_fields, + common::ObIArray &order_exprs) { int ret = OB_SUCCESS; if (OB_FAIL(order_exprs_.assign((order_exprs)))) { @@ -646,6 +657,9 @@ int ObProxyStreamSortUnit::init(ObProxyResultResp* result_set, common::ObIArray< } else if (OB_ISNULL(result_set_ = result_set)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("result set should not NULL", K(ret)); + } else if (OB_ISNULL(result_fields_ = result_fields)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("result fields should not NULL", K(ret)); } else if (OB_FAIL(next())) { // The first time, there must be a result, so it must not be OB_ITER_END LOG_WARN("fail to exec next", K(ret)); diff --git a/src/obproxy/engine/ob_proxy_operator_sort.h b/src/obproxy/engine/ob_proxy_operator_sort.h index 033c73d4e52db4938b984881e9d8946f9b24b5a9..a59c55c307d4cff69e76c6aa86d3314fae4f405c 100644 --- a/src/obproxy/engine/ob_proxy_operator_sort.h +++ b/src/obproxy/engine/ob_proxy_operator_sort.h @@ -142,12 +142,13 @@ class ObProxyMemMergeSortUnit { public: ObProxyMemMergeSortUnit(common::ObIAllocator &allocator) - : allocator_(allocator), row_(NULL), + : allocator_(allocator), row_(NULL), result_fields_(NULL), order_values_(ObModIds::OB_SE_ARRAY_ENGINE, ENGINE_ARRAY_NEW_ALLOC_SIZE), order_exprs_(ObModIds::OB_SE_ARRAY_ENGINE, ENGINE_ARRAY_NEW_ALLOC_SIZE) {} ~ObProxyMemMergeSortUnit() {} - int init(ResultRow *row, common::ObIArray &order_exprs); + int init(ResultRow *row, ResultFields *result_fields, + common::ObIArray &order_exprs); virtual bool compare(const ObProxyMemMergeSortUnit* sort_unit) const; int calc_order_values(); @@ -159,6 +160,7 @@ public: protected: common::ObIAllocator &allocator_; ResultRow *row_; + ResultFields *result_fields_; common::ObSEArray order_values_; common::ObSEArray order_exprs_; }; @@ -188,7 +190,8 @@ public: : ObProxyMemMergeSortUnit(allocator), result_set_(NULL) {} ~ObProxyStreamSortUnit() {} - int init(ObProxyResultResp* result_set, common::ObIArray &order_exprs); + int init(ObProxyResultResp* result_set, ResultFields *result_fields, + common::ObIArray &order_exprs); virtual bool compare(const ObProxyStreamSortUnit* sort_unit) const; int next(); diff --git a/src/obproxy/engine/ob_proxy_operator_table_scan.cpp b/src/obproxy/engine/ob_proxy_operator_table_scan.cpp index eb6fd78f0064ec4717ee7288c41fbb4493d9f834..ddd8de528734919058269b8609c2610345d9a7e6 100644 --- a/src/obproxy/engine/ob_proxy_operator_table_scan.cpp +++ b/src/obproxy/engine/ob_proxy_operator_table_scan.cpp @@ -20,6 +20,7 @@ #include "executor/ob_proxy_parallel_cont.h" #include "executor/ob_proxy_parallel_execute_cont.h" #include "proxy/shard/obproxy_shard_utils.h" +#include "proxy/mysqllib/ob_proxy_mysql_request.h" using namespace oceanbase::obproxy::executor; using namespace oceanbase::common; @@ -28,6 +29,15 @@ namespace oceanbase { namespace obproxy { namespace engine { +ObProxyTableScanOp::~ObProxyTableScanOp() +{ + for (int64_t i = 0; i < pres_array_.count(); i++) { + executor::ObProxyParallelResp *pres = pres_array_.at(i); + op_free(pres); + pres = NULL; + } +} + int ObProxyTableScanOp::open(event::ObContinuation *cont, event::ObAction *&action, const int64_t timeout_ms) { child_cnt_ = 1; //fake child @@ -77,7 +87,8 @@ int ObProxyTableScanOp::get_next_row() "phy table count", table_name_maps.count(), "shard prop count", shard_props.count(), "dbkey count", db_key_names.count(), K(ret)); - } else if (OB_FAIL(sql_parser.parse_sql_by_obparser(request_sql, NORMAL_PARSE_MODE, parse_result, true))) { + } else if (OB_FAIL(sql_parser.parse_sql_by_obparser(proxy::ObProxyMysqlRequest::get_parse_sql(request_sql), + NORMAL_PARSE_MODE, parse_result, true))) { LOG_WARN("parse_sql_by_obparser failed", K(request_sql), K(ret)); } @@ -88,10 +99,9 @@ int ObProxyTableScanOp::get_next_row() ObSqlString new_sql; char *tmp_buf = NULL; bool is_oracle_mode = db_key_name->server_type_ == common::DB_OB_ORACLE; - if (OB_FAIL(proxy::ObProxyShardUtils::do_rewrite_shard_select_request(request_sql, parse_result, is_oracle_mode, - table_name_map_warraper.get_hash_map(), - db_key_name->database_name_, false, - new_sql))) { + if (OB_FAIL(proxy::ObProxyShardUtils::rewrite_shard_dml_request(request_sql, new_sql, parse_result, + is_oracle_mode, table_name_map_warraper.get_hash_map(), + db_key_name->database_name_, false))) { LOG_WARN("fail to rewrite shard request", K(request_sql), K(is_oracle_mode), K(ret)); } else if (OB_ISNULL(tmp_buf = (char *)allocator_.alloc(new_sql.length()))) { ret = common::OB_ALLOCATE_MEMORY_FAILED; @@ -135,6 +145,8 @@ int ObProxyTableScanOp::handle_result(void *data, bool &is_final, ObProxyResultR } else if (OB_ISNULL(pres = reinterpret_cast(data))) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid input, pres type is not match", K(ret)); + } else if (OB_FAIL(pres_array_.push_back(pres))) { + LOG_WARN("fail to push result resp to array", K(ret)); } else { if (pres->is_ok_resp()) { // it is the OK packet // For the OK package, it is only necessary to construct an OK package in the case of @@ -156,10 +168,6 @@ int ObProxyTableScanOp::handle_result(void *data, bool &is_final, ObProxyResultR } LOG_DEBUG("handle_result success", K(ret), K(pres)); } - if (OB_NOT_NULL(pres)) { - op_free(pres); - pres = NULL; - } return ret; } diff --git a/src/obproxy/engine/ob_proxy_operator_table_scan.h b/src/obproxy/engine/ob_proxy_operator_table_scan.h index 1c14c926727edf36856e7f3bf90c390435ba99df..1571070dfdd847afea1baa457f73526671bfd8d9 100644 --- a/src/obproxy/engine/ob_proxy_operator_table_scan.h +++ b/src/obproxy/engine/ob_proxy_operator_table_scan.h @@ -32,7 +32,7 @@ public: set_op_type(PHY_TABLE_SCAN); } - virtual ~ObProxyTableScanOp() {}; + virtual ~ObProxyTableScanOp(); virtual int open(event::ObContinuation *cont, event::ObAction *&action, const int64_t timeout_ms = 0); virtual int get_next_row(); @@ -53,6 +53,7 @@ private: protected: int64_t sub_sql_count_; + common::ObSEArray pres_array_; }; class ObProxyTableScanInput : public ObProxyOpInput diff --git a/src/obproxy/executor/ob_proxy_parallel_execute_cont.cpp b/src/obproxy/executor/ob_proxy_parallel_execute_cont.cpp index 51994759c90426d5ed939ee7b6d94863be998eec..92884bfc85c9a51044eb513d04b27b781297f333 100644 --- a/src/obproxy/executor/ob_proxy_parallel_execute_cont.cpp +++ b/src/obproxy/executor/ob_proxy_parallel_execute_cont.cpp @@ -27,6 +27,16 @@ namespace obproxy namespace executor { +int64_t ObProxyParallelResp::to_string(char *buf, int64_t buf_len) const +{ + int64_t pos = 0; + J_OBJ_START(); + J_KV(K_(column_count), K_(cont_index), + KP_(resp), KP_(rs_fetcher)); + J_OBJ_END(); + return pos; +} + ObProxyParallelResp::~ObProxyParallelResp() { if (OB_NOT_NULL(resp_)) { @@ -66,7 +76,6 @@ int ObProxyParallelResp::next(ObObj *&rows) { int ret = OB_SUCCESS; - ObMysqlField *fields = rs_fetcher_->get_field(); int64_t buf_len = (sizeof(ObObj) * column_count_); char *buf = NULL; @@ -79,50 +88,9 @@ int ObProxyParallelResp::next(ObObj *&rows) LOG_WARN("fail to alloc mem", K(buf_len), K(ret)); } else { rows = new (buf) ObObj[column_count_]; - ObObjType ob_type; for (int64_t i = 0; OB_SUCC(ret) && i < column_count_; i++) { if (OB_FAIL(rs_fetcher_->get_obj(i, rows[i]))) { LOG_WARN("fail to get varchar", K(i), K(ret)); - } else if (rows[i].need_deep_copy()) { - int64_t copy_size = rows[i].get_deep_copy_size(); - int64_t pos = 0; - buf = NULL; - if (OB_ISNULL(buf = static_cast(allocator_->alloc(copy_size)))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to alloc mem", K(copy_size), K(ret)); - } else if (OB_FAIL(rows[i].deep_copy(rows[i], buf, copy_size, pos))) { - LOG_WARN("fail to deep coy", "obj", rows[i], K(copy_size), K(ret)); - } - } - - if (OB_SUCC(ret) && rows[i].is_varchar()) { - ObCollationType cs_type = static_cast(fields[i].charsetnr_); - // utf8_general_ci => CS_TYPE_UTF8MB4_GENERAL_CI - if (33 == fields[i].charsetnr_) { - cs_type = CS_TYPE_UTF8MB4_GENERAL_CI; - // utf8_bin => CS_TYPE_UTF8MB4_BIN - } else if (83 == fields[i].charsetnr_) { - cs_type = CS_TYPE_UTF8MB4_BIN; - } - - rows[i].set_collation_type(cs_type); - - if (0 != rows[i].get_string_len()) { - // if can not convert, stay varchar type - if (OB_FAIL(ObSMUtils::get_ob_type(ob_type, fields[i].type_))) { - LOG_INFO("cast ob type from mysql type failed", K(ob_type), "elem_type", fields[i].type_, K(ret)); - ret = OB_SUCCESS; - } else if (ObTimestampType == ob_type || ObTimeType == ob_type - || ObDateType == ob_type || ObDateTimeType == ob_type) { - //do nothing - } else { - ObCastCtx cast_ctx(allocator_, NULL, CM_NULL_ON_WARN, cs_type); - // use src_obj as buf_obj - if (OB_FAIL(ObObjCasterV2::to_type(ob_type, cs_type, cast_ctx, rows[i], rows[i]))) { - COMMON_LOG(WARN, "failed to cast obj", "idx", i, "row", rows[i], K(ob_type), K(cs_type), K(ret)); - } - } - } } } } @@ -201,6 +169,8 @@ int ObProxyParallelExecuteCont::init_task() int ret = OB_SUCCESS; ObMysqlRequestParam request_param; + request_param.ob_client_flags_.client_flags_.OB_CLIENT_SKIP_AUTOCOMMIT = 1; + request_param.ob_client_flags_.client_flags_.OB_CLIENT_SEND_REQUEST_DIRECT = 1; request_param.sql_ = request_sql_; if (OB_FAIL(mysql_proxy_->async_read(this, request_param, pending_action_))) { LOG_WARN("fail to async read", K_(request_sql), K(ret)); diff --git a/src/obproxy/executor/ob_proxy_parallel_execute_cont.h b/src/obproxy/executor/ob_proxy_parallel_execute_cont.h index 98cb30db9acd991f8dd824ba31a5758472f1be2b..ac0ff672fa8dddf39f55d03d13b50a0f210fcae3 100644 --- a/src/obproxy/executor/ob_proxy_parallel_execute_cont.h +++ b/src/obproxy/executor/ob_proxy_parallel_execute_cont.h @@ -44,6 +44,7 @@ public: ObMysqlField *get_field() const { return rs_fetcher_->get_field(); } int64_t get_column_count() { return column_count_; } int64_t get_cont_index() { return cont_index_; } + int64_t to_string(char *buf, int64_t buf_len) const; private: proxy::ObClientMysqlResp *resp_; diff --git a/src/obproxy/iocore/eventsystem/Makemodule.am b/src/obproxy/iocore/eventsystem/Makemodule.am index be135867942dd9e2616a9ca3062d4dc88a0686a0..bc8951c93f8c8f9147dbde1defc0f92afef107e5 100644 --- a/src/obproxy/iocore/eventsystem/Makemodule.am +++ b/src/obproxy/iocore/eventsystem/Makemodule.am @@ -19,6 +19,8 @@ obproxy/iocore/eventsystem/ob_priority_event_queue.h\ obproxy/iocore/eventsystem/ob_processor.h\ obproxy/iocore/eventsystem/ob_protected_queue.h\ obproxy/iocore/eventsystem/ob_protected_queue.cpp\ +obproxy/iocore/eventsystem/ob_protected_queue_thread_pool.cpp\ +obproxy/iocore/eventsystem/ob_protected_queue_thread_pool.h\ obproxy/iocore/eventsystem/ob_thread.h\ obproxy/iocore/eventsystem/ob_thread.cpp\ obproxy/iocore/eventsystem/ob_vconnection.h\ @@ -32,4 +34,6 @@ obproxy/iocore/eventsystem/ob_grpc_task.h\ obproxy/iocore/eventsystem/ob_grpc_task.cpp\ obproxy/iocore/eventsystem/ob_shard_watch_task.h\ obproxy/iocore/eventsystem/ob_shard_watch_task.cpp\ +obproxy/iocore/eventsystem/ob_shard_scan_all_task.h\ +obproxy/iocore/eventsystem/ob_shard_scan_all_task.cpp\ obproxy/iocore/eventsystem/ob_thread_impl.h diff --git a/src/obproxy/iocore/eventsystem/ob_ethread.cpp b/src/obproxy/iocore/eventsystem/ob_ethread.cpp index a71e6ff888ec1cd615a035b4569914bcba937958..6ce48ff4cd97397be94847bc9d9cda3f1aad2691 100644 --- a/src/obproxy/iocore/eventsystem/ob_ethread.cpp +++ b/src/obproxy/iocore/eventsystem/ob_ethread.cpp @@ -65,12 +65,16 @@ ObEThread::ObEThread() cache_cleaner_(NULL), sql_table_map_(NULL), ps_entry_cache_(NULL), + text_ps_entry_cache_(NULL), random_seed_(NULL), + is_need_thread_pool_event_(false), + thread_pool_event_queue_(NULL), warn_log_buf_(NULL), warn_log_buf_start_(NULL), tt_(REGULAR), pending_event_(NULL), - thread_prometheus_(NULL) + thread_prometheus_(NULL), + use_status_(false) { #if OB_HAVE_EVENTFD evfd_ = -1; @@ -101,12 +105,16 @@ ObEThread::ObEThread(const ObThreadType att, const int64_t anid) cache_cleaner_(NULL), sql_table_map_(NULL), ps_entry_cache_(NULL), + text_ps_entry_cache_(NULL), random_seed_(NULL), + is_need_thread_pool_event_(false), + thread_pool_event_queue_(NULL), warn_log_buf_(NULL), warn_log_buf_start_(NULL), tt_(att), pending_event_(NULL), - thread_prometheus_(NULL) + thread_prometheus_(NULL), + use_status_(false) { #if OB_HAVE_EVENTFD evfd_ = -1; @@ -137,12 +145,16 @@ ObEThread::ObEThread(const ObThreadType att, ObEvent *e) cache_cleaner_(NULL), sql_table_map_(NULL), ps_entry_cache_(NULL), + text_ps_entry_cache_(NULL), random_seed_(NULL), + is_need_thread_pool_event_(false), + thread_pool_event_queue_(NULL), warn_log_buf_(NULL), warn_log_buf_start_(NULL), tt_(att), pending_event_(e), - thread_prometheus_(NULL) + thread_prometheus_(NULL), + use_status_(false) { #if OB_HAVE_EVENTFD evfd_ = -1; @@ -269,6 +281,9 @@ inline void ObEThread::process_event(ObEvent *e, const int calling_code) event_queue_external_.enqueue_local(e); } else { if (e->cancelled_) { + if (e->is_thread_pool_event_) { + is_need_thread_pool_event_ = true; + } free_event(*e); } else { const ObContinuation *c_temp = e->continuation_; @@ -283,7 +298,7 @@ inline void ObEThread::process_event(ObEvent *e, const int calling_code) if (OB_UNLIKELY(e->in_the_priority_queue_)) { LOG_WARN("event should not in in_the_priority_queue here", K(*e)); } else if (OB_UNLIKELY(c_temp != e->continuation_)) { - LOG_WARN("event should not in in_the_priority_queue here", K(*e)); + LOG_WARN("c_temp should equal e->continuation_", K(*e)); } else {/*do nothing*/} MUTEX_RELEASE(lock); @@ -352,6 +367,7 @@ inline void ObEThread::dequeue_local_event(Que(ObEvent, link_) &negative_queue) // If successful, call the continuation, otherwise put the event back into the queue. void ObEThread::execute() { + thread_id_ = GETTID(); switch (tt_) { case REGULAR: { Que(ObEvent, link_) negative_queue; @@ -437,7 +453,16 @@ void ObEThread::execute() if (ethreads_to_be_signalled_count_ > 0) { flush_signals(this); } - if (OB_UNLIKELY(OB_SUCCESS != event_queue_external_.dequeue_timed(next_time, true))) { + + if (is_need_thread_pool_event_ && NULL != thread_pool_event_queue_) { + if (OB_UNLIKELY(OB_SUCCESS != thread_pool_event_queue_->dequeue_timed(next_time, e))) { + LOG_WARN("fail to dequeue time in event_queue_external_"); + } else if (NULL != e) { + is_need_thread_pool_event_ = false; + e->ethread_ = this; + process_event(e, e->callback_event_); + } + } else if (OB_UNLIKELY(OB_SUCCESS != event_queue_external_.dequeue_timed(next_time, true))) { LOG_WARN("fail to dequeue time in event_queue_external_"); } } diff --git a/src/obproxy/iocore/eventsystem/ob_ethread.h b/src/obproxy/iocore/eventsystem/ob_ethread.h index 2b7eecf90c0654c94987e6268dfdc8fc515d5af9..ae78a12617934981bda5501f0eade99dd88d054f 100644 --- a/src/obproxy/iocore/eventsystem/ob_ethread.h +++ b/src/obproxy/iocore/eventsystem/ob_ethread.h @@ -34,6 +34,7 @@ #include "iocore/eventsystem/ob_thread.h" #include "iocore/eventsystem/ob_priority_event_queue.h" #include "iocore/eventsystem/ob_protected_queue.h" +#include "iocore/eventsystem/ob_protected_queue_thread_pool.h" #include "lib/container/ob_vector.h" namespace oceanbase @@ -56,7 +57,7 @@ class ObPartitionRefHashMap; class ObRoutineRefHashMap; class ObSqlTableRefHashMap; class ObCacheCleaner; -class ObBasePsEntryCache; +class ObBasePsEntryThreadCache; } namespace net { @@ -324,13 +325,14 @@ public: proxy::ObSqlTableRefHashMap &get_sql_table_map() { return *sql_table_map_; } proxy::ObPartitionRefHashMap &get_partition_map() { return *partition_map_; } proxy::ObRoutineRefHashMap &get_routine_map() { return *routine_map_; } - proxy::ObBasePsEntryCache &get_ps_entry_cache() { return *ps_entry_cache_; } + proxy::ObBasePsEntryThreadCache &get_ps_entry_cache() { return *ps_entry_cache_; } + proxy::ObBasePsEntryThreadCache &get_text_ps_entry_cache() { return *text_ps_entry_cache_; } obutils::ObCongestionRefHashMap &get_cgt_map() { return *congestion_map_; } common::ObMysqlRandom &get_random_seed() { return *random_seed_; } ObProxyMutex &get_mutex() { return *mutex_; } - TO_STRING_KV(K_(id), K_(tid), K_(event_types), K_(tt), K_(stack_start), - K_(ethreads_to_be_signalled_count), K_(cur_time)); + TO_STRING_KV(K_(id), K_(tid), K_(thread_id), K_(event_types), K_(tt), K_(stack_start), + K_(ethreads_to_be_signalled_count), K_(cur_time), K_(use_status)); private: void process_event(ObEvent *e, const int calling_code); @@ -379,15 +381,20 @@ public: obutils::ObCongestionRefHashMap *congestion_map_; proxy::ObCacheCleaner *cache_cleaner_; proxy::ObSqlTableRefHashMap *sql_table_map_; - proxy::ObBasePsEntryCache *ps_entry_cache_; + proxy::ObBasePsEntryThreadCache *ps_entry_cache_; + proxy::ObBasePsEntryThreadCache *text_ps_entry_cache_; common::ObMysqlRandom *random_seed_; + bool is_need_thread_pool_event_; + ObProtectedQueueThreadPool *thread_pool_event_queue_; + char *warn_log_buf_; char *warn_log_buf_start_; ObThreadType tt_; ObEvent *pending_event_; // For dedicated event thread prometheus::ObThreadPrometheus *thread_prometheus_; + bool use_status_; private: // prevent unauthorized copies (Not implemented) diff --git a/src/obproxy/iocore/eventsystem/ob_event.h b/src/obproxy/iocore/eventsystem/ob_event.h index b08d0ddcbd15b8166eebf7f9d5fa0040910d3594..ecfa64ac0dadc32459133e92be51f4b4a1af3fa0 100644 --- a/src/obproxy/iocore/eventsystem/ob_event.h +++ b/src/obproxy/iocore/eventsystem/ob_event.h @@ -208,6 +208,7 @@ public: uint32_t in_the_prot_queue_:1; uint32_t in_the_priority_queue_:1; uint32_t in_heap_:4; + uint32_t is_thread_pool_event_; int32_t callback_event_; ObHRTime timeout_at_; @@ -235,6 +236,7 @@ inline ObEvent::ObEvent() in_the_prot_queue_(false), in_the_priority_queue_(false), in_heap_(0), + is_thread_pool_event_(false), callback_event_(EVENT_NONE), timeout_at_(0), period_(0), diff --git a/src/obproxy/iocore/eventsystem/ob_event_processor.cpp b/src/obproxy/iocore/eventsystem/ob_event_processor.cpp index 91b9c946ebc4cdaaf30ea86fa2fbb1bb6be1185a..c7587f1956dafa6faf4d859f8a90226a35f70927 100644 --- a/src/obproxy/iocore/eventsystem/ob_event_processor.cpp +++ b/src/obproxy/iocore/eventsystem/ob_event_processor.cpp @@ -34,6 +34,7 @@ #include "iocore/eventsystem/ob_event_system.h" #include #include "utils/ob_cpu_affinity.h" +#include "ob_proxy_init.h" using namespace oceanbase::common; @@ -45,6 +46,18 @@ namespace event { class ObEventProcessor g_event_processor; +int ObEventProcessor::init_thread(ObEThread *&t) +{ + int ret = OB_SUCCESS; + if (OB_FAIL(t->init())) { + LOG_WARN("fail to init event", K(ret)); + delete t; + t = NULL; + } + + return ret; +} + int ObEventProcessor::spawn_event_threads( const int64_t thread_count, const char *et_name, const int64_t stacksize, ObEventThreadType &etype) @@ -52,6 +65,7 @@ int ObEventProcessor::spawn_event_threads( int ret = OB_SUCCESS; char thr_name[MAX_THREAD_NAME_LENGTH]; ObEventThreadType new_thread_group_id = MAX_EVENT_TYPES; + int64_t net_thread_count = 0; etype = MAX_EVENT_TYPES; if (OB_UNLIKELY((event_thread_count_ + thread_count) > MAX_EVENT_THREADS) || OB_UNLIKELY(thread_count <= 0)) { @@ -68,16 +82,15 @@ int ObEventProcessor::spawn_event_threads( LOG_WARN("invalid parameters", K(stacksize), K(ret)); } else { new_thread_group_id = (ObEventThreadType)thread_group_count_; + net_thread_count = thread_count_for_type_[ET_CALL]; ObEThread *t = NULL; for (int64_t i = 0; i < thread_count && OB_SUCC(ret); ++i) { - if (OB_ISNULL(t = new(std::nothrow) ObEThread(REGULAR, event_thread_count_ + i))) { + if (OB_ISNULL(t = new(std::nothrow) ObEThread(REGULAR, MAX_THREADS_IN_EACH_TYPE + event_thread_count_ - net_thread_count + i))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("fail to allocator memory for REGULAR ObEThread", K(i), K(thread_count), K(ret)); - } else if (OB_FAIL(t->init())) { - LOG_WARN("fail to init event", K(i), K(ret)); - delete t; - t = NULL; + } else if (OB_FAIL(init_thread(t))) { + LOG_WARN("fail to init thread", K(i), K(ret)); } else { all_event_threads_[event_thread_count_ + i] = t; event_thread_[new_thread_group_id][i] = t; @@ -110,6 +123,61 @@ int ObEventProcessor::spawn_event_threads( return ret; } +int ObEventProcessor::spawn_net_threads(const int64_t thread_count, + const char *et_name, const int64_t stacksize) +{ + int ret = OB_SUCCESS; + char thr_name[MAX_THREAD_NAME_LENGTH]; + + if (OB_UNLIKELY((event_thread_count_ + thread_count) > MAX_EVENT_THREADS) || OB_UNLIKELY(thread_count <= 0)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid parameters", K(thread_count), K(event_thread_count_), K(MAX_EVENT_THREADS), K(ret)); + } else if (OB_ISNULL(et_name)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid parameters, et_name is null", K(ret)); + } else if (OB_UNLIKELY(stacksize < 0)) {//when equal to 0, use the default thread size 8M; + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid parameters", K(stacksize), K(ret)); + } else { + ObEThread *t = NULL; + int64_t net_thread_count = thread_count_for_type_[ET_CALL]; + for (int64_t i = 0; i < thread_count && OB_SUCC(ret); ++i) { + if (OB_ISNULL(t = new(std::nothrow) ObEThread(REGULAR, net_thread_count + i))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_ERROR("fail to allocate memory for REGULAR ObEThread", K(i), K(thread_count), K(ret)); + } else if (OB_FAIL(init_thread(t))) { + LOG_WARN("fail to init thread", K(i), K(ret)); + } else { + all_event_threads_[event_thread_count_ + i] = t; + event_thread_[ET_CALL][net_thread_count + i] = t; + t->set_event_thread_type(ET_CALL); + } + } + + if (OB_SUCC(ret)) { + int32_t length = 0; + for (int64_t i = 0; i < thread_count && OB_SUCC(ret); ++i) { + length = snprintf(thr_name, sizeof(thr_name), "[%s %ld]", et_name, thread_count_for_type_[ET_CALL] + i); + if (OB_UNLIKELY(length <= 0) || OB_UNLIKELY(length >= static_cast(sizeof(thr_name)))) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("fail to format thread name", K(length), K(ret)); + } else if (OB_FAIL(event_thread_[ET_CALL][net_thread_count + i]->start(thr_name, stacksize))) { + LOG_WARN("fail to start event thread", K(ET_CALL), K(i), K(thread_count), K(ret)); + } else {/*do nothing*/} + } + thread_count_for_type_[ET_CALL] += thread_count; + event_thread_count_ += thread_count; + } + } + + if (OB_SUCC(ret)) { + LOG_DEBUG("succ to create tenant thread group", K(thr_name), K(thread_count), + K(event_thread_count_), K(thread_count_for_type_[ET_CALL])); + } + return ret; +} + + inline int ObEventProcessor::init_one_event_thread(const int64_t index) { int ret = OB_SUCCESS; @@ -123,6 +191,7 @@ inline int ObEventProcessor::init_one_event_thread(const int64_t index) delete t; t = NULL; } else { + // It should be noted here that the thread with index 0 in rich client mode will be created if (0 == index) { this_thread() = t; global_mutex = t->mutex_; @@ -158,7 +227,8 @@ int64_t ObEventProcessor::get_cpu_count() } int ObEventProcessor::start(const int64_t net_thread_count, const int64_t stacksize, - const bool enable_cpu_topology/*false*/, const bool automatic_match_work_thread/*true*/) + const bool enable_cpu_topology/*false*/, const bool automatic_match_work_thread/*true*/, + const bool enable_cpu_isolate/*false*/) { int ret = OB_SUCCESS; char thr_name[MAX_THREAD_NAME_LENGTH]; @@ -175,13 +245,16 @@ int ObEventProcessor::start(const int64_t net_thread_count, const int64_t stacks ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid parameters", K(stacksize), K(ret)); } else { - if (!automatic_match_work_thread || OB_UNLIKELY((cpu_num = get_cpu_count()) <= 0) || cpu_num > net_thread_count) { cpu_num = net_thread_count; } + if (enable_cpu_isolate && cpu_num < MAX_OTHER_GROUP_NET_THREADS) { + cpu_num = MAX_OTHER_GROUP_NET_THREADS; + } + event_thread_count_ = cpu_num; thread_group_count_ = 1; @@ -233,7 +306,7 @@ int ObEventProcessor::start(const int64_t net_thread_count, const int64_t stacks if (OB_UNLIKELY(length <= 0) || OB_UNLIKELY(length >= static_cast(sizeof(thr_name)))) { ret = OB_SIZE_OVERFLOW; LOG_WARN("fail format thread name", K(length), K(ret)); - } else if ((0 != i) && OB_FAIL(all_event_threads_[i]->start(thr_name, stacksize))) { + } else if ((0 != i || RUN_MODE_CLIENT == g_run_mode) && OB_FAIL(all_event_threads_[i]->start(thr_name, stacksize))) { LOG_WARN("fail to start event thread", K(thr_name), K(ret)); } else { if (bind_cpu) { diff --git a/src/obproxy/iocore/eventsystem/ob_event_processor.h b/src/obproxy/iocore/eventsystem/ob_event_processor.h index 5c7acac3e768dca5ad01317275a9b5c39a9c1790..cfe8da2a91562b5dbe857f95b6d4bf6aed439bec 100644 --- a/src/obproxy/iocore/eventsystem/ob_event_processor.h +++ b/src/obproxy/iocore/eventsystem/ob_event_processor.h @@ -35,6 +35,7 @@ #include "iocore/eventsystem/ob_ethread.h" #include "iocore/eventsystem/ob_event.h" #include "iocore/eventsystem/ob_io_buffer.h" +#include "lib/lock/ob_drw_lock.h" namespace oceanbase { @@ -55,6 +56,8 @@ const int64_t MAX_EVENT_THREADS = OB_MAX_NUMBER_EVENT_THREADS; const int64_t MAX_EVENT_THREADS = 512; #endif +const int64_t MAX_OTHER_GROUP_NET_THREADS = 8; + #ifndef offsetof #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #endif @@ -149,6 +152,10 @@ public: */ int spawn_event_threads(const int64_t thread_count, const char *et_name, const int64_t stacksize, ObEventThreadType &etype); + int spawn_net_threads(const int64_t thread_count, const char *et_name, + const int64_t stacksize); + + virtual int init_thread(ObEThread *&t); /** * Schedules the continuation on a specific ObEThread to receive an event @@ -279,7 +286,8 @@ public: * @return 0 if successful, and a negative value otherwise. */ virtual int start(const int64_t net_thread_count, const int64_t stacksize = DEFAULT_STACKSIZE, - const bool enable_cpu_topology = false, const bool automatic_match_work_thread = true); + const bool enable_cpu_topology = false, const bool automatic_match_work_thread = true, + const bool enable_cpu_isolate = false); /** * Stop the ObEventProcessor. Attempts to stop the ObEventProcessor and @@ -297,7 +305,7 @@ public: */ int64_t allocate(const int64_t size); - ObEvent *schedule(ObEvent *e, const ObEventThreadType etype, const bool fast_signal = false); + virtual ObEvent *schedule(ObEvent *e, const ObEventThreadType etype, const bool fast_signal = false); ObEThread *assign_thread(const ObEventThreadType etype); @@ -353,6 +361,7 @@ public: ObEThread *all_dedicate_threads_[MAX_EVENT_THREADS]; int64_t dedicate_thread_count_; // No. of dedicated threads volatile int64_t thread_data_used_; + common::DRWLock lock_; private: bool started_; @@ -364,6 +373,7 @@ inline ObEventProcessor::ObEventProcessor() thread_group_count_(0), dedicate_thread_count_(0), thread_data_used_(0), + lock_(), started_(false) { memset(all_event_threads_, 0, sizeof(all_event_threads_)); @@ -409,7 +419,7 @@ inline ObEThread *ObEventProcessor::assign_thread(const ObEventThreadType etype) return (event_thread_[etype][next]); } -inline ObEvent *ObEventProcessor::schedule( +ObEvent *ObEventProcessor::schedule( ObEvent *event, const ObEventThreadType etype, const bool fast_signal) { event->ethread_ = assign_thread(etype); diff --git a/src/obproxy/iocore/eventsystem/ob_protected_queue_thread_pool.cpp b/src/obproxy/iocore/eventsystem/ob_protected_queue_thread_pool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8a6a642082e8a74aa38e11e4a3e769f647509907 --- /dev/null +++ b/src/obproxy/iocore/eventsystem/ob_protected_queue_thread_pool.cpp @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#define USING_LOG_PREFIX PROXY_EVENT + +#include "iocore/eventsystem/ob_event_system.h" +#include "iocore/net/ob_unix_net.h" + +using namespace oceanbase::common; + +namespace oceanbase +{ +namespace obproxy +{ +namespace event +{ + +void ObProtectedQueueThreadPool::enqueue(ObEvent *e) +{ + if (OB_ISNULL(e)) { + LOG_WARN("event NULL, it should not happened"); + } else if (OB_UNLIKELY(e->in_the_prot_queue_) || OB_UNLIKELY(e->in_the_priority_queue_)) { + LOG_WARN("event has already in queue, it should not happened", K(*e)); + } else { + int ret = OB_SUCCESS; + e->in_the_prot_queue_ = 1; + atomic_list_.push(e); + + if (OB_FAIL(signal())) { + LOG_WARN("fail to do signal, it should not happened", K(ret)); + } + } +} + +int ObProtectedQueueThreadPool::dequeue_timed(const ObHRTime timeout, ObEvent *&event) +{ + int ret = OB_SUCCESS; + + if (NULL != (event= (ObEvent *)(atomic_list_.pop()))) { + event->in_the_prot_queue_ = 0; + } else { + if (OB_FAIL(mutex_acquire(&lock_))) { + LOG_ERROR("fail to acquire mutex", K(ret)); + } else { + if (atomic_list_.empty()) { + timespec ts = hrtime_to_timespec(timeout); + cond_timedwait(&might_have_data_, &lock_, &ts); + } + + if (NULL != (event= (ObEvent *)(atomic_list_.pop()))) { + event->in_the_prot_queue_ = 0; + } + + int tmp_ret = OB_SUCCESS; + if (OB_UNLIKELY(OB_SUCCESS != (tmp_ret = mutex_release(&lock_)))) { + LOG_ERROR("fail to release mutex", K(tmp_ret)); + } + } + } + + return ret; +} + +} // end of namespace event +} // end of namespace obproxy +} // end of namespace oceanbase diff --git a/src/obproxy/iocore/eventsystem/ob_protected_queue_thread_pool.h b/src/obproxy/iocore/eventsystem/ob_protected_queue_thread_pool.h new file mode 100644 index 0000000000000000000000000000000000000000..668caa6e0b8adb6b0ad0077ace54067a0b88732f --- /dev/null +++ b/src/obproxy/iocore/eventsystem/ob_protected_queue_thread_pool.h @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef OBPROXY_PROTECTED_QUEUE_THREAD_POOL_H +#define OBPROXY_PROTECTED_QUEUE_THREAD_POOL_H + +#include "iocore/eventsystem/ob_event.h" + +namespace oceanbase +{ +namespace obproxy +{ +namespace event +{ + +class ObProtectedQueueThreadPool +{ +public: + ObProtectedQueueThreadPool() : is_inited_(false) {} + ~ObProtectedQueueThreadPool() { } + + int init(); + void enqueue(ObEvent *e); + int dequeue_timed(const ObHRTime timeout, ObEvent *&event); + int signal(); + +public: + bool is_inited_; + common::ObAtomicList atomic_list_; + ObMutex lock_; + ObProxyThreadCond might_have_data_; + +private: + DISALLOW_COPY_AND_ASSIGN(ObProtectedQueueThreadPool); +}; + +inline int ObProtectedQueueThreadPool::init() +{ + int ret = common::OB_SUCCESS; + ObEvent e; + if (OB_FAIL(common::mutex_init(&lock_))) { + PROXY_EVENT_LOG(WARN, "fail to init mutex", K(ret)); + } else if (OB_FAIL(atomic_list_.init("ObProtectedQueueThreadPool", + reinterpret_cast(&e.link_.next_) - reinterpret_cast(&e)))) { + PROXY_EVENT_LOG(WARN, "fail to init atomic_list_", K(ret)); + } else if (OB_FAIL(cond_init(&might_have_data_))) { + PROXY_EVENT_LOG(WARN, "fail to init ObProxyThreadCond", K(ret)); + } else { + is_inited_ = 0; + } + return ret; +} + +inline int ObProtectedQueueThreadPool::signal() +{ + int ret = common::OB_SUCCESS; + // Need to get the lock before you can signal the thread + if (OB_FAIL(common::mutex_acquire(&lock_))) { + PROXY_EVENT_LOG(ERROR, "fail to acquire lock", K(ret)); + } else { + if (OB_FAIL(cond_signal(&might_have_data_))) { + PROXY_EVENT_LOG(WARN, "fail to call cond_signal", K(ret)); + } + + int tmp_ret = common::OB_SUCCESS; + if (OB_UNLIKELY(common::OB_SUCCESS != ( tmp_ret = common::mutex_release(&lock_)))) { + PROXY_EVENT_LOG(WARN, "fail to release mutex", K(tmp_ret)); + } + } + return ret; +} + +} // end of namespace event +} // end of namespace obproxy +} // end of namespace oceanbase + +#endif // OBPROXY_PROTECTED_QUEUE_THREAD_POOL_H diff --git a/src/obproxy/iocore/eventsystem/ob_shard_scan_all_task.cpp b/src/obproxy/iocore/eventsystem/ob_shard_scan_all_task.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b1abca64c7dc2a7a1b2f886f3bcb018b22256d25 --- /dev/null +++ b/src/obproxy/iocore/eventsystem/ob_shard_scan_all_task.cpp @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#define USING_LOG_PREFIX PROXY_EVENT + +#include "iocore/eventsystem/ob_shard_scan_all_task.h" +#include "iocore/eventsystem/ob_event_system.h" + +using namespace oceanbase::common; + +namespace oceanbase +{ +namespace obproxy +{ +namespace event +{ +ObEventThreadType ET_SHARD_SCAN_ALL = ET_CALL; +ObShardScanAllTaskProcessor g_shard_scan_all_task_processor; + +// Note that if the number of task_threads is 0, all continuations scheduled for +// ET_SHARD_SCAN_ALL ends up running on ET_CALL (which is the net-threads). +int ObShardScanAllTaskProcessor::start(const int64_t shard_scan_all_threads, const int64_t stacksize) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(thread_pool_event_queue_ = new (std::nothrow) ObProtectedQueueThreadPool())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to new ObProtectedQueueThreadPool", K(ret)); + } else if (OB_FAIL(thread_pool_event_queue_->init())) { + LOG_WARN("fail to init thread_pool_event_queue", K(ret)); + } else if (OB_FAIL(spawn_event_threads(shard_scan_all_threads, "ET_SHARD_SCAN_ALL", stacksize, ET_SHARD_SCAN_ALL))) { + LOG_WARN("fail to spawn event threads for ET_SHARD_SCAN_ALL", K(ret)); + } + + return ret; +} + +int ObShardScanAllTaskProcessor::init_thread(ObEThread *&t) +{ + int ret = OB_SUCCESS; + + if (OB_FAIL(t->init())) { + LOG_WARN("fail to init event", K(ret)); + delete t; + t = NULL; + } else { + t->thread_pool_event_queue_ = thread_pool_event_queue_; + t->is_need_thread_pool_event_ = true; + } + + return ret; +} + +ObEvent *ObShardScanAllTaskProcessor::schedule(ObEvent *event, const ObEventThreadType etype, const bool fast_signal) +{ + UNUSED(fast_signal); + UNUSED(etype); + + if (NULL != event->continuation_->mutex_) { + event->mutex_ = event->continuation_->mutex_; + } else { + event->continuation_->mutex_ = event->ethread_->mutex_; + event->mutex_ = event->continuation_->mutex_; + } + event->is_thread_pool_event_ = true; + thread_pool_event_queue_->enqueue(event); + return event; +} + +} // end of namespace event +} // end of namespace obproxy +} // end of namespace oceanbase diff --git a/src/obproxy/iocore/eventsystem/ob_shard_scan_all_task.h b/src/obproxy/iocore/eventsystem/ob_shard_scan_all_task.h new file mode 100644 index 0000000000000000000000000000000000000000..b2ef2590af36f6e52bad13ef361845e851a44f20 --- /dev/null +++ b/src/obproxy/iocore/eventsystem/ob_shard_scan_all_task.h @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef OBPROXY_SHARD_SCAN_ALL_TASK_H +#define OBPROXY_SHARD_SCAN_ALL_TASK_H + +#include "iocore/eventsystem/ob_event_processor.h" +#include "iocore/eventsystem/ob_event.h" +#include "iocore/eventsystem/ob_protected_queue_thread_pool.h" + +namespace oceanbase +{ +namespace obproxy +{ +namespace event +{ +extern ObEventThreadType ET_SHARD_SCAN_ALL; + +class ObShardScanAllTaskProcessor : public ObEventProcessor +{ +public: + ObShardScanAllTaskProcessor() : ObEventProcessor(), thread_pool_event_queue_(NULL) {} + virtual ~ObShardScanAllTaskProcessor() {} + int start(const int64_t shard_scan_all_threads, const int64_t stacksize = DEFAULT_STACKSIZE); + + virtual int init_thread(ObEThread *&t); + virtual ObEvent *schedule(ObEvent *event, const ObEventThreadType etype, const bool fast_signal); + +private: + ObProtectedQueueThreadPool *thread_pool_event_queue_; +}; + +extern ObShardScanAllTaskProcessor g_shard_scan_all_task_processor; +} // end of namespace event +} // end of namespace obproxy +} // end of namespace oceanbase + +#endif // OBPROXY_SHARD_SCAN_ALL_TASK_H diff --git a/src/obproxy/iocore/eventsystem/ob_thread.h b/src/obproxy/iocore/eventsystem/ob_thread.h index df2f67db44b30cdf89b65f2a139b4a64b3de3d20..6e12e67396c477cb14754992659e0ad56e017bac 100644 --- a/src/obproxy/iocore/eventsystem/ob_thread.h +++ b/src/obproxy/iocore/eventsystem/ob_thread.h @@ -66,7 +66,7 @@ static const int DEFAULT_STACKSIZE = 1048576; // 1MB class ObThread { public: - ObThread() : tid_(0), mutex_(NULL), mutex_ptr_(NULL) {} + ObThread() : tid_(0), thread_id_(0), mutex_(NULL), mutex_ptr_(NULL) {} virtual ~ObThread() { } @@ -84,6 +84,7 @@ public: * processors and you should not modify it directly. */ ObThreadId tid_; + int64_t thread_id_; /** * ObThread lock to ensure atomic operations. The thread lock available diff --git a/src/obproxy/iocore/eventsystem/ob_vconnection.h b/src/obproxy/iocore/eventsystem/ob_vconnection.h index ef3dfe6071fd35e0b6472024fb412240de555e78..d413b7f0b3a9805f8564f6d49c9d5a4c6d79f21a 100644 --- a/src/obproxy/iocore/eventsystem/ob_vconnection.h +++ b/src/obproxy/iocore/eventsystem/ob_vconnection.h @@ -98,6 +98,8 @@ class ObProxyMutex; #define VC_EVENT_ACTIVE_TIMEOUT (VC_EVENT_EVENTS_START+6) #define VC_EVENT_HELLO_PKT_READ_READY (VC_EVENT_EVENTS_START+7) +// OBProxy detect server dead, should close connection +#define VC_EVENT_DETECT_SERVER_DEAD (VC_EVENT_EVENTS_START+8) // ObEvent return codes #define VC_EVENT_DONE CONTINUATION_DONE @@ -184,6 +186,8 @@ public: * No activity was performed for a certain period. * VC_EVENT_ACTIVE_TIMEOUT * Write operation continued beyond a time limit. + * VC_EVENT_DETECT_SERVER_DEAD + * find Server dead, close connection * VC_EVENT_ERROR * An error occurred during the write * @@ -622,6 +626,10 @@ static inline const char *get_vc_event_name(int32_t event) ret = "VC_EVENT_ACTIVE_TIMEOUT"; break; + case VC_EVENT_DETECT_SERVER_DEAD: + ret = "VC_EVENT_DETECT_SERVER_DEAD"; + break; + default: ret = "unknown event"; break; diff --git a/src/obproxy/iocore/net/ob_connection.cpp b/src/obproxy/iocore/net/ob_connection.cpp index 66dee9a9b45c79a444e12a12a0d1cab201926348..4ee0c9daf02dcb21269f3bf5f4db5beb3c05e43c 100644 --- a/src/obproxy/iocore/net/ob_connection.cpp +++ b/src/obproxy/iocore/net/ob_connection.cpp @@ -30,6 +30,8 @@ #include "iocore/net/ob_connection.h" #include "utils/ob_proxy_hot_upgrader.h" +#include "utils/ob_layout.h" +#include "ob_proxy_init.h" using namespace oceanbase::common; using namespace oceanbase::obproxy::event; @@ -390,6 +392,50 @@ int ObServerConnection::setup_fd_for_listen( const int32_t send_bufsize) { int ret = OB_SUCCESS; + if (RUN_MODE_PROXY == g_run_mode) { + if (OB_FAIL(setup_fd_for_listen_proxy_mode(non_blocking, recv_bufsize, send_bufsize))) { + PROXY_SOCK_LOG(WARN, "setup_fd_for_listen_proxy_mode failed", K(ret)); + } + } else if (RUN_MODE_CLIENT == g_run_mode) { + if (OB_FAIL(setup_fd_for_listen_client_mode(non_blocking, recv_bufsize, send_bufsize))) { + PROXY_SOCK_LOG(WARN, "setup_fd_for_listen_client_mode failed", K(ret)); + } + } + + return ret; +} + +int ObServerConnection::setup_fd_for_listen_client_mode( + const bool non_blocking, + const int32_t recv_bufsize, + const int32_t send_bufsize) +{ + UNUSED(recv_bufsize); + UNUSED(send_bufsize); + int ret = OB_SUCCESS; + + if (non_blocking && OB_FAIL(ObSocketManager::nonblocking(fd_))) { + PROXY_SOCK_LOG(WARN, "fail to set fd nonblocking", K(fd_), K(ret)); + } + + if (OB_FAIL(ret)) { + // make coverity happy + int tmp_ret = ret; + if (OB_FAIL(close())) { + PROXY_SOCK_LOG(WARN, "fail to close server connection", K(ret)); + } + ret = tmp_ret; + } + return ret; +} + + +int ObServerConnection::setup_fd_for_listen_proxy_mode( + const bool non_blocking, + const int32_t recv_bufsize, + const int32_t send_bufsize) +{ + int ret = OB_SUCCESS; if (OB_FAIL(ObSocketManager::set_sndbuf_and_rcvbuf_size(fd_, send_bufsize, recv_bufsize, SNDBUF_AND_RCVBUF_PREC))) { @@ -458,7 +504,7 @@ int ObServerConnection::setup_fd_for_listen( // make coverity happy int tmp_ret = ret; if (OB_FAIL(close())) { - PROXY_SOCK_LOG(WARN, "fail to close server connection", K(tmp_ret)); + PROXY_SOCK_LOG(WARN, "fail to close server connection", K(ret)); } ret = tmp_ret; } @@ -467,6 +513,55 @@ int ObServerConnection::setup_fd_for_listen( int ObServerConnection::listen(const bool non_blocking, const int32_t recv_bufsize, const int32_t send_bufsize) +{ + int ret = OB_SUCCESS; + if (RUN_MODE_PROXY == g_run_mode) { + if (OB_FAIL(listen_proxy_mode(non_blocking, recv_bufsize, send_bufsize))) { + PROXY_SOCK_LOG(WARN, "listen proxy mode failed", K(ret)); + } + } else if (RUN_MODE_CLIENT == g_run_mode) { + if (OB_FAIL(listen_client_mode(non_blocking, recv_bufsize, send_bufsize))) { + PROXY_SOCK_LOG(WARN, "listen client mode failed", K(ret)); + } + } + + return ret; +} + +int ObServerConnection::listen_client_mode(const bool non_blocking, const int32_t recv_bufsize, + const int32_t send_bufsize) +{ + int ret = OB_SUCCESS; + struct sockaddr_un *addr = (struct sockaddr_un*)&addr_.unix_domain_; + addr->sun_family = AF_UNIX; + memset(addr->sun_path, 0, sizeof(addr->sun_path)); + strncpy(addr->sun_path, get_global_layout().get_unix_domain_path(), sizeof(addr->sun_path) - 1); + if (OB_FAIL(ObSocketManager::socket(AF_UNIX, SOCK_STREAM, 0, fd_))) { + PROXY_SOCK_LOG(WARN, "fail to create socket", K(ret), KERRMSGS); + } else if (OB_FAIL(setup_fd_for_listen_client_mode(non_blocking, recv_bufsize, send_bufsize))) { + PROXY_SOCK_LOG(WARN, "fail to setup_fd_for_listen", K(ret)); + } else if (OB_FAIL(ObSocketManager::bind(fd_, &addr_.sa_, sizeof(*addr)))) { + PROXY_SOCK_LOG(WARN, "fail to bind", K(ret)); + } else if (OB_FAIL(ObSocketManager::listen(fd_, LISTEN_BACKLOG))) { + PROXY_SOCK_LOG(WARN, "fail to listen", KERRMSGS, K(ret)); + } else { + ObHotUpgraderInfo &info = get_global_hot_upgrade_info(); + info.ipv4_fd_ = fd_; + } + + if (OB_FAIL(ret)) { + // make coverity happy + int tmp_ret = ret; + if (OB_FAIL(close())) { + PROXY_SOCK_LOG(WARN, "fail to close server connection", K(ret)); + } + ret = tmp_ret; + } + return ret; +} + +int ObServerConnection::listen_proxy_mode(const bool non_blocking, const int32_t recv_bufsize, + const int32_t send_bufsize) { int ret = OB_SUCCESS; if (!ops_is_ip(accept_addr_)) { @@ -478,21 +573,23 @@ int ObServerConnection::listen(const bool non_blocking, const int32_t recv_bufsi ObHotUpgraderInfo &info = get_global_hot_upgrade_info(); if (OB_FAIL(ObSocketManager::socket(addr_.sa_.sa_family, SOCK_STREAM, IPPROTO_TCP, fd_))) { - PROXY_SOCK_LOG(WARN, "failed to create socket", K(addr_), KERRMSGS, K(ret)); + PROXY_SOCK_LOG(WARN, "fail to create socket", K(addr_), KERRMSGS, K(ret)); } else if (OB_FAIL(setup_fd_for_listen(non_blocking, recv_bufsize, send_bufsize))) { - PROXY_SOCK_LOG(WARN, "failed to setup_fd_for_listen", K(addr_), K(ret)); + PROXY_SOCK_LOG(WARN, "fail to setup_fd_for_listen", K(addr_), K(ret)); } else if (OB_FAIL(ObSocketManager::bind(fd_, &addr_.sa_, static_cast(ops_ip_size(addr_.sa_))))) { - PROXY_SOCK_LOG(WARN, "failed to bind", K(addr_), KERRMSGS, K(ret)); + PROXY_SOCK_LOG(WARN, "fail to bind", K(addr_), KERRMSGS, K(ret)); } else if (OB_FAIL(ObSocketManager::listen(fd_, LISTEN_BACKLOG))) { - PROXY_SOCK_LOG(WARN, "failed to listen", K(addr_), KERRMSGS, K(ret)); + PROXY_SOCK_LOG(WARN, "fail to listen", K(addr_), KERRMSGS, K(ret)); } else { // Original just did this on port == 0. int64_t namelen = sizeof(addr_); if (OB_FAIL(ObSocketManager::getsockname(fd_, &addr_.sa_, &namelen))) { PROXY_SOCK_LOG(WARN, "failed to getsockname", K(addr_), KERRMSGS, K(ret)); - } else { - info.fd_ = fd_; + } else if (addr_.is_ip4()) { + info.ipv4_fd_ = fd_; + } else if (addr_.is_ip6()) { + info.ipv6_fd_ = fd_; } } @@ -500,7 +597,7 @@ int ObServerConnection::listen(const bool non_blocking, const int32_t recv_bufsi // make coverity happy int tmp_ret = ret; if (OB_FAIL(close())) { - PROXY_SOCK_LOG(WARN, "fail to close server connection", K(tmp_ret)); + PROXY_SOCK_LOG(WARN, "fail to close server connection", K(ret)); } ret = tmp_ret; } diff --git a/src/obproxy/iocore/net/ob_connection.h b/src/obproxy/iocore/net/ob_connection.h index 31cf184e77ca12b20813dbfe620e21ae755c7add..bc87bc031bde919edf5f9358b7565d4a674901bb 100644 --- a/src/obproxy/iocore/net/ob_connection.h +++ b/src/obproxy/iocore/net/ob_connection.h @@ -159,6 +159,22 @@ public: // Client side (inbound) local IP address. ObIpEndpoint accept_addr_; +private: + int setup_fd_for_listen_proxy_mode( + const bool non_blocking = false, + const int32_t recv_bufsize = 0, + const int32_t send_bufsize = 0); + int setup_fd_for_listen_client_mode( + const bool non_blocking = false, + const int32_t recv_bufsize = 0, + const int32_t send_bufsize = 0); + int listen_proxy_mode(const bool non_blocking = false, + const int32_t recv_bufsize = 0, + const int32_t send_bufsize = 0); + int listen_client_mode(const bool non_blocking = false, + const int32_t recv_bufsize = 0, + const int32_t send_bufsize = 0); + private: static const int32_t LISTEN_BACKLOG; }; diff --git a/src/obproxy/iocore/net/ob_inet.cpp b/src/obproxy/iocore/net/ob_inet.cpp index 3cfe40a171f478dc7ee8e1a8beb54512274c0aaa..f37e0e4296fd0e02a1b388a22df8251497566931 100644 --- a/src/obproxy/iocore/net/ob_inet.cpp +++ b/src/obproxy/iocore/net/ob_inet.cpp @@ -41,14 +41,27 @@ namespace obproxy namespace net { +uint64_t ObIpEndpoint::hash(const uint64_t hash) const +{ + char buf[MAX_IP_ADDR_LENGTH]; + int64_t pos = to_string(buf, MAX_IP_ADDR_LENGTH); + return murmurhash(buf, static_cast(pos), hash); +} + int64_t ObIpEndpoint::to_string(char *buf, const int64_t buf_len) const { - char ip_buff[INET6_ADDRSTRLEN]; + char ip_buff[MAX_IP_ADDR_LENGTH]; int64_t pos = 0; J_OBJ_START(); - databuff_printf(buf, buf_len, pos, "%s:%u", - ops_ip_ntop(*this, ip_buff, sizeof(ip_buff)), - ops_ip_port_host_order(*this)); + if (is_ip6()) { + databuff_printf(buf, buf_len, pos, "[%s]:%u", + ops_ip_ntop(*this, ip_buff, sizeof(ip_buff)), + ops_ip_port_host_order(*this)); + } else { + databuff_printf(buf, buf_len, pos, "%s:%u", + ops_ip_ntop(*this, ip_buff, sizeof(ip_buff)), + ops_ip_port_host_order(*this)); + } J_OBJ_END(); return pos; } diff --git a/src/obproxy/iocore/net/ob_inet.h b/src/obproxy/iocore/net/ob_inet.h index 369d8ce39fdd0bd6883a1a2d596321e01715fda8..6321c6e5229860e496ae4b4758177dc16cadffbc 100644 --- a/src/obproxy/iocore/net/ob_inet.h +++ b/src/obproxy/iocore/net/ob_inet.h @@ -92,10 +92,15 @@ union ObIpEndpoint memset(this, 0, sizeof(ObIpEndpoint)); assign(addr); } + explicit ObIpEndpoint(const sockaddr_storage &addr) { + memset(this, 0, sizeof(ObIpEndpoint)); + assign(addr); + } ObIpEndpoint (const ObIpEndpoint &point) { MEMCPY(this, &point, sizeof(ObIpEndpoint)); } void operator= (const ObIpEndpoint &point) { MEMCPY(this, &point, sizeof(ObIpEndpoint)); } ObIpEndpoint &assign(const sockaddr &ip); + ObIpEndpoint &assign(const sockaddr_storage &ip); ObIpEndpoint &assign(const ObIpAddr &addr, const in_port_t port = 0); // Test for valid IP address. @@ -107,6 +112,8 @@ union ObIpEndpoint // Test for IPv6. bool is_ip6() const; + bool is_unix_domain() const; + uint16_t family() const; // Set to be any address for family family. // family must be AF_INET or AF_INET6. @@ -129,13 +136,14 @@ union ObIpEndpoint int64_t get_port_host_order() const; uint32_t get_ip4_host_order() const; - uint64_t hash(const uint64_t hash = 0) const { return common::murmurhash(&sa_, sizeof(sockaddr), hash); } + uint64_t hash(const uint64_t hash = 0) const; int64_t to_string(char *buffer, const int64_t size) const; struct sockaddr sa_; // Generic address. struct sockaddr_in sin_; // IPv4 struct sockaddr_in6 sin6_; // IPv6 + struct sockaddr_un unix_domain_; // unix_domain }; // Reset an address to invalid. @@ -485,8 +493,17 @@ inline const uint8_t *ops_ip_addr8_cast(const ObIpEndpoint &ip) // @return true if this is an IP loopback address, false otherwise. inline bool ops_is_ip_loopback(const sockaddr &ip) { - return (AF_INET == ip.sa_family && 0x7F == ops_ip_addr8_cast(ip)[0]) - || (AF_INET6 == ip.sa_family && IN6_IS_ADDR_LOOPBACK(&ops_ip6_addr_cast(ip))); + bool zret = false; + if (ops_is_ip4(ip)) { + in_addr_t a = ops_ip4_addr_cast(ip); + zret = (a == 0x100007F); + } else if (ops_is_ip6(ip)) { + in6_addr a = ops_ip6_addr_cast(ip); + zret = ((a.s6_addr32[0] == 0 && a.s6_addr32[1] == 0 && a.s6_addr32[2] == 0 + && a.s6_addr[12] == 0 && a.s6_addr[13] == 0 && a.s6_addr[14] == 0 + && a.s6_addr[15] == 1)); + } + return zret; } inline bool ops_is_ip_loopback(const ObIpEndpoint &ip) @@ -556,6 +573,8 @@ inline bool ops_ip_copy(sockaddr &dst, const sockaddr &src) case AF_INET6: n = sizeof(sockaddr_in6); break; + case AF_UNIX: + break; } switch (dst.sa_family) { case AF_INET: @@ -1034,6 +1053,12 @@ inline ObIpEndpoint& ObIpEndpoint::assign(const sockaddr &ip) return *this; } +inline ObIpEndpoint& ObIpEndpoint::assign(const sockaddr_storage &ip) +{ + ops_ip_copy(sa_, ops_ip_sa_cast(ip)); + return *this; +} + inline in_port_t& ObIpEndpoint::port() { return ops_ip_port_cast(sa_); @@ -1061,6 +1086,7 @@ inline bool ObIpEndpoint::is_valid() const inline bool ObIpEndpoint::is_ip4() const { return AF_INET == sa_.sa_family; } inline bool ObIpEndpoint::is_ip6() const { return AF_INET6 == sa_.sa_family; } +inline bool ObIpEndpoint::is_unix_domain() const { return AF_UNIX == sa_.sa_family; } inline uint16_t ObIpEndpoint::family() const { return sa_.sa_family; } inline ObIpEndpoint& ObIpEndpoint::set_to_any_addr(const int family) diff --git a/src/obproxy/iocore/net/ob_net_accept.cpp b/src/obproxy/iocore/net/ob_net_accept.cpp index 1a4d12ca569235b4b2ddcdbedd8136ece5118664..c43c0ee57469692e1574bed91f59fbee20ab6f06 100644 --- a/src/obproxy/iocore/net/ob_net_accept.cpp +++ b/src/obproxy/iocore/net/ob_net_accept.cpp @@ -32,9 +32,22 @@ #include "iocore/net/ob_net_accept.h" #include "iocore/net/ob_net.h" #include "iocore/net/ob_event_io.h" +#include "ob_proxy_init.h" +#include "omt/ob_resource_unit_table_processor.h" +#include "proxy/mysql/ob_mysql_client_session.h" +#include "proxy/route/ob_table_cache.h" +#include "obutils/ob_congestion_manager.h" +#include "proxy/route/ob_partition_cache.h" +#include "proxy/route/ob_routine_cache.h" +#include "proxy/route/ob_sql_table_cache.h" +#include "prometheus/ob_prometheus_processor.h" using namespace oceanbase::common; +using namespace oceanbase::obproxy::obutils; using namespace oceanbase::obproxy::event; +using namespace oceanbase::obproxy::omt; +using namespace oceanbase::obproxy::proxy; +using namespace oceanbase::obproxy::prometheus; namespace oceanbase { @@ -252,7 +265,6 @@ int ObNetAccept::init_accept_per_thread() int ObNetAccept::do_listen(const bool non_blocking) { - int ret = OB_SUCCESS; PROXY_NET_LOG(DEBUG, "ObNetAccept::do_listen", K(server_.fd_), K(non_blocking)); const ObHotUpgraderInfo &info = get_global_hot_upgrade_info(); @@ -308,6 +320,102 @@ int ObNetAccept::do_listen(const bool non_blocking) return ret; } +int ObNetAccept::fetch_vip_tenant(ObUnixNetVConnection* vc, ObVipTenant& vip_tenant, bool& lookup_success) +{ + int ret = OB_SUCCESS; + int64_t vid; + bool found = false; + ObConfigItem tenant_item; + ObConfigItem cluster_item; + if (OB_ISNULL(vc)) { + ret = OB_ERR_UNEXPECTED; + PROXY_NET_LOG(WARN, "vc pointer is null", K(ret)); + } else { + vid = static_cast(vc->get_virtual_vid()); + vip_tenant.vip_addr_.set(vc->get_virtual_addr(), vid); + if (OB_FAIL(get_global_config_processor().get_proxy_config_with_level( + vip_tenant.vip_addr_, "", "", "proxy_tenant_name", tenant_item, "LEVEL_VIP", found))) { + PROXY_NET_LOG(WARN, "get proxy tenant name config failed", K(vip_tenant.vip_addr_), K(ret)); + } + + if (OB_SUCC(ret) && found) { + if (OB_FAIL(get_global_config_processor().get_proxy_config_with_level( + vip_tenant.vip_addr_, "", "", "rootservice_cluster_name", cluster_item, "LEVEL_VIP", found))) { + PROXY_NET_LOG(WARN, "get cluster name config failed", K(vip_tenant.vip_addr_), K(ret)); + } + } + + if (OB_SUCC(ret) && found) { + if (OB_FAIL(vip_tenant.set_tenant_cluster(tenant_item.str(), cluster_item.str()))) { + PROXY_CS_LOG(WARN, "set tenant and cluster name failed", K(tenant_item), K(cluster_item), K(ret)); + } else { + lookup_success = true; + } + } + } + return ret; +} + +int ObNetAccept::fetch_tenant_cpu(ObVipTenant& vip_tenant, ObTenantCpu*& tenant_cpu, bool& lookup_success) +{ + int ret = OB_SUCCESS; + ObString key_name; + char vip_name[MAX_IP_ADDR_LENGTH]; + common::ObFixedLengthString key_string; + if (OB_UNLIKELY(!vip_tenant.vip_addr_.addr_.ip_to_string(vip_name, static_cast(sizeof(vip_name))))) { + ret = OB_ERR_UNEXPECTED; + PROXY_NET_LOG(WARN, "fail to covert ip to string", K(vip_name), K(ret)); + } else if (OB_FAIL(build_tenant_cluster_vip_name(vip_tenant.tenant_name_, vip_tenant.cluster_name_, vip_name, key_string))) { + PROXY_NET_LOG(WARN, "build tenant cluser vip name failed", K(vip_tenant), K(ret)); + } else if (FALSE_IT(key_name = ObString::make_string(key_string.ptr()))) { + } else if (OB_FAIL(get_global_cpu_table_processor().get_tenant_cpu(key_name, tenant_cpu))) { + PROXY_NET_LOG(DEBUG, "get tenant cpu failed", K(key_name), K(ret)); + } else { + lookup_success = true; + } + return ret; +} + +int ObNetAccept::handle_tenant_cpu_isolated(ObTenantCpu* tenant_cpu, ObEThread*& ethread) +{ + int ret = OB_SUCCESS; + // 1. Assign as many threads as there are max_thread_num, and then save the thread id + // 2. Create the tenant's cgroup filesystem + // 2.1 Write cfs_period_us and cfs_quota_us to the cgroup filesystem + // 2.2 tasks that write the thread id to the cgroup filesystem + if (OB_ISNULL(tenant_cpu)) { + ret = OB_ERR_UNEXPECTED; + PROXY_NET_LOG(WARN, "tenant cpu point is null", K(ret)); + } else { + if (tenant_cpu->thread_array_.count() < tenant_cpu->max_thread_num_) { + DRWLock::WRLockGuard guard(g_event_processor.lock_); + if (tenant_cpu->thread_array_.count() < tenant_cpu->max_thread_num_) { + ethread = get_schedule_vip_ethread(); + if (OB_ISNULL(ethread)) { + ret = OB_ERR_UNEXPECTED; + PROXY_NET_LOG(ERROR, "fail to get_shedule_ethread", K(ret)); + } else if (OB_FAIL(tenant_cpu->acquire_more_worker(ethread->thread_id_))) { + PROXY_NET_LOG(WARN, "acquire more worker failed", K(ret)); + } else { + ethread->use_status_ = true; + tenant_cpu->thread_array_.push_back(ethread); + } + } else { + ethread = tenant_cpu->get_tenant_schedule_ethread(); + } + } else { + ethread = tenant_cpu->get_tenant_schedule_ethread(); + } + } + + // for debug + if (OB_NOT_NULL(ethread)) { + PROXY_NET_LOG(DEBUG, "has acquire thread", K(ethread->thread_id_), KPC(tenant_cpu), KPC(ethread)); + } + + return ret; +} + int ObNetAccept::do_blocking_accept() { int ret = OB_SUCCESS; @@ -363,14 +471,33 @@ int ObNetAccept::do_blocking_accept() SET_CONTINUATION_HANDLER(vc, reinterpret_cast(&ObUnixNetVConnection::accept_event)); - ethread = get_schedule_ethread(); - if(OB_ISNULL(ethread)) { + ObVipTenant vip_tenant; + ObTenantCpu* tenant_cpu = NULL; + bool lookup_vip_tenant_success = false; + bool lookup_tenant_cpu_success = false; + if (get_global_proxy_config().enable_cpu_isolate) { + fetch_vip_tenant(vc, vip_tenant, lookup_vip_tenant_success); + if (lookup_vip_tenant_success) { + fetch_tenant_cpu(vip_tenant, tenant_cpu, lookup_tenant_cpu_success); + } + if (lookup_vip_tenant_success && lookup_tenant_cpu_success) { + if (OB_FAIL(handle_tenant_cpu_isolated(tenant_cpu, ethread))) { + PROXY_NET_LOG(ERROR, "handle tenant cpu isolate failed", K(ret)); + } + tenant_cpu->dec_ref(); + } else { + ethread = get_schedule_other_ethread(); + } + } else { + ethread = get_schedule_ethread(); + } + + if (OB_ISNULL(ethread)) { ret = OB_ERR_UNEXPECTED; PROXY_NET_LOG(ERROR, "fail to get_shedule_ethread", K(ret)); } else { NET_ATOMIC_INCREMENT_DYN_STAT(ethread, NET_CLIENT_CONNECTIONS_CURRENTLY_OPEN); - - if(OB_ISNULL(ethread->schedule_imm_signal(vc))) { + if (OB_ISNULL(ethread->schedule_imm_signal(vc))) { ret = OB_ERR_UNEXPECTED; PROXY_NET_LOG(ERROR, "fail to schedule_imm_signal vc", K(ret)); } @@ -403,6 +530,105 @@ inline ObEThread *ObNetAccept::get_schedule_ethread() return target_ethread; } +inline ObEThread *ObNetAccept::get_schedule_other_ethread() +{ + ObEventThreadType etype = ET_NET; + ObEThread **netthreads = g_event_processor.event_thread_[etype]; + ObEThread *target_ethread = NULL; + int64_t min_conn_cnt = -1; + int64_t tmp_cnt = -1; + + for (int64_t i = 0; i < MAX_OTHER_GROUP_NET_THREADS; ++i) { + NET_THREAD_READ_DYN_SUM(netthreads[i], NET_CLIENT_CONNECTIONS_CURRENTLY_OPEN, tmp_cnt); + if (0 == i || tmp_cnt < min_conn_cnt) { + min_conn_cnt = tmp_cnt; + target_ethread = netthreads[i]; + } + tmp_cnt = -1; + } + return target_ethread; +} + +inline ObEThread *ObNetAccept::get_schedule_vip_ethread() +{ + int ret = OB_SUCCESS; + ObEventThreadType etype = ET_NET; + int64_t net_thread_count = g_event_processor.thread_count_for_type_[etype]; + ObEThread **netthreads = g_event_processor.event_thread_[etype]; + ObEThread *target_ethread = NULL; + + for (int64_t i = MAX_OTHER_GROUP_NET_THREADS; i < net_thread_count; ++i) { + if (!netthreads[i]->use_status_) { + target_ethread = netthreads[i]; + break; + } + } + + if (OB_ISNULL(target_ethread)) { + if (OB_FAIL(create_one_net_ethread(target_ethread))) { + PROXY_NET_LOG(WARN, "create net thread failed", K(ret)); + } + } + + return target_ethread; +} + +int ObNetAccept::create_one_net_ethread(ObEThread*& target_ethread) +{ + int ret = OB_SUCCESS; + target_ethread = NULL; + bool is_new_net_thread = false; + int64_t event_thread_count = 0; + int64_t net_thread_count = g_event_processor.thread_count_for_type_[ET_CALL]; + int64_t stack_size = get_global_proxy_config().stack_size; + + if (OB_FAIL(g_event_processor.spawn_net_threads(1, "ET_NET", stack_size))) { + PROXY_NET_LOG(ERROR, "fail to spawn event threads for ET_NET", K(ret)); + } else { + is_new_net_thread = true; + event_thread_count = g_event_processor.event_thread_count_; + net_thread_count = g_event_processor.thread_count_for_type_[ET_CALL]; + target_ethread = g_event_processor.event_thread_[ET_CALL][net_thread_count - 1]; + if (OB_FAIL(initialize_thread_for_net(target_ethread))) { + PROXY_NET_LOG(ERROR, "fail to initialize thread for net", K(ret)); + } else if (OB_FAIL(init_cs_map_for_one_thread(net_thread_count - 1))) { + PROXY_NET_LOG(ERROR, "fail to init cs_map for thread", K(net_thread_count), K(ret)); + } else if (OB_FAIL(init_table_map_for_one_thread(net_thread_count - 1))) { + PROXY_NET_LOG(ERROR, "fail to init table_map for thread", K(net_thread_count), K(ret)); + } else if (OB_FAIL(init_congestion_map_for_one_thread(net_thread_count - 1))) { + PROXY_NET_LOG(ERROR, "fail to init congestion_map for thread", K(net_thread_count), K(ret)); + } else if (OB_FAIL(init_partition_map_for_one_thread(net_thread_count - 1))) { + PROXY_NET_LOG(ERROR, "fail to init partition_map for thread", K(net_thread_count), K(ret)); + } else if (OB_FAIL(init_routine_map_for_one_thread(net_thread_count - 1))) { + PROXY_NET_LOG(ERROR, "fail to init routine_map for thread", K(net_thread_count), K(ret)); + } else if (OB_FAIL(init_sql_table_map_for_one_thread(net_thread_count - 1))) { + PROXY_NET_LOG(ERROR, "fail to init sql_table_map for thread", K(net_thread_count), K(ret)); + } else if (OB_FAIL(init_ps_entry_cache_for_one_thread(net_thread_count - 1))) { + PROXY_NET_LOG(ERROR, "fail to init ps entry cache for thread", K(net_thread_count), K(ret)); + } else if (OB_FAIL(init_text_ps_entry_cache_for_one_thread(net_thread_count - 1))) { + PROXY_NET_LOG(ERROR, "fail to init text ps entry cache for thread", K(net_thread_count), K(ret)); + } else if (OB_FAIL(init_random_seed_for_one_thread(net_thread_count - 1))) { + PROXY_NET_LOG(ERROR, "fail to init random seed for thread", K(net_thread_count), K(ret)); + } else if (OB_FAIL(ObCacheCleaner::schedule_one_cache_cleaner(net_thread_count - 1))) { + PROXY_NET_LOG(ERROR, "fail to init cleaner cache for thread", K(net_thread_count), K(ret)); + } else if (OB_FAIL(g_ob_prometheus_processor.start_one_prometheus(net_thread_count - 1))) { + PROXY_NET_LOG(ERROR, "fail to start one prometheus", K(net_thread_count), K(ret)); + } else { + PROXY_NET_LOG(INFO, "new thread", K(ET_CALL), K(net_thread_count), KPC(target_ethread)); + } + } + + if (OB_FAIL(ret) && is_new_net_thread) { + delete target_ethread; + target_ethread = NULL; + g_event_processor.all_event_threads_[event_thread_count - 1] = NULL; + g_event_processor.event_thread_[ET_CALL][net_thread_count -1] = NULL; + g_event_processor.thread_count_for_type_[ET_CALL] -= 1; + g_event_processor.event_thread_count_ -= 1; + } + return ret; +} + inline bool ObNetAccept::accept_balance(ObEThread *ethread) { ObEThread *scheduled_ethread = get_schedule_ethread(); diff --git a/src/obproxy/iocore/net/ob_net_accept.h b/src/obproxy/iocore/net/ob_net_accept.h index 0a258c540a15146b2037e27908a6a904ffe597ec..a452ec295f1156dbc4be290926537963644db37e 100644 --- a/src/obproxy/iocore/net/ob_net_accept.h +++ b/src/obproxy/iocore/net/ob_net_accept.h @@ -44,6 +44,8 @@ #include "utils/ob_proxy_hot_upgrader.h" #include "iocore/net/ob_unix_net.h" #include "iocore/net/ob_connection.h" +#include "omt/ob_cpu_table_processor.h" +#include "obutils/ob_vip_tenant_processor.h" namespace oceanbase { @@ -118,10 +120,17 @@ private: void cancel(); // for loading balance, get the ethread which has minimal client connections event::ObEThread *get_schedule_ethread(); + event::ObEThread *get_schedule_vip_ethread(); + event::ObEThread *get_schedule_other_ethread(); + int create_one_net_ethread(event::ObEThread*& target_ethread); // for connection balance in each ethread, // only the ethread which has minimal client connections will do accept bool accept_balance(event::ObEThread *ethread); + int fetch_vip_tenant(ObUnixNetVConnection* vc, obutils::ObVipTenant& vip_tenant, bool& lookup_success); + int fetch_tenant_cpu(obutils::ObVipTenant& vip_tenant, omt::ObTenantCpu*& tenant_cpu, bool& lookup_success); + int handle_tenant_cpu_isolated(omt::ObTenantCpu* tenant_cpu, event::ObEThread*& ethread); + public: ObServerConnection server_; void *alloc_cache_; diff --git a/src/obproxy/iocore/net/ob_net_vconnection.h b/src/obproxy/iocore/net/ob_net_vconnection.h index 6ab615ea9af6946984f7f067f3bc8a989d306a15..6fa432012b25d094621b73aa519f5f770e8de8c9 100644 --- a/src/obproxy/iocore/net/ob_net_vconnection.h +++ b/src/obproxy/iocore/net/ob_net_vconnection.h @@ -419,35 +419,23 @@ protected: virtual int get_socket() = 0; public: - // Returns local ip. - // @deprecated get_local_addr() should be used instead for AF_INET6 compatibility. - in_addr_t get_local_ip(); // Returns local port uint16_t get_local_port(); // Returns local sockaddr storage const sockaddr &get_local_addr(); - // Returns remote ip. - // @deprecated get_remote_addr() should be used instead for AF_INET6 compatibility. - in_addr_t get_remote_ip(); // Returns remote port uint16_t get_remote_port(); // Returns remote sockaddr storage const sockaddr &get_remote_addr(); - // Returns virual ip. - // @deprecated get_virtual_addr() should be used instead for AF_INET6 compatibility. - in_addr_t get_virtual_ip(); // Returns virtual port uint16_t get_virtual_port(); // Returns virtual vid(vpc id) uint32_t get_virtual_vid(); // Returns virtual sockaddr storage const sockaddr &get_virtual_addr(); - const sockaddr &get_real_client_addr(); - in_addr_t get_real_client_ip(); - uint16_t get_real_client_port(); // Force an event if a write operation empties the write buffer. // @@ -476,7 +464,7 @@ protected: ObIpEndpoint local_addr_; // it is local proxy addr ObIpEndpoint remote_addr_; // if from accept, it is client addr, otherwise it is server addr ObIpEndpoint real_client_addr_; - ObIpEndpoint virtual_addr_; + ObIpEndpoint virtual_addr_; // vip addr uint32_t virtual_vid_; bool got_local_addr_; @@ -504,13 +492,6 @@ inline ObNetVConnection::ObNetVConnection() ob_zero(real_client_addr_); } -// local -inline in_addr_t ObNetVConnection::get_local_ip() -{ - const sockaddr addr = get_local_addr(); - return ops_is_ip4(addr) ? ops_ip4_addr_cast(addr) : 0; -} - //@return The local port in host order. inline uint16_t ObNetVConnection::get_local_port() { @@ -530,13 +511,6 @@ inline const sockaddr &ObNetVConnection::get_local_addr() return local_addr_.sa_; } -// remote -inline in_addr_t ObNetVConnection::get_remote_ip() -{ - const sockaddr &addr = get_remote_addr(); - return ops_is_ip4(addr) ? ops_ip4_addr_cast(addr) : 0; -} - // @return The remote port in host order. inline uint16_t ObNetVConnection::get_remote_port() { @@ -561,17 +535,6 @@ inline const sockaddr &ObNetVConnection::get_real_client_addr() return real_client_addr_.sa_; } -inline in_addr_t ObNetVConnection::get_real_client_ip() -{ - const sockaddr addr = get_real_client_addr(); - return ops_is_ip4(addr) ? ops_ip4_addr_cast(addr) : 0; -} - -inline uint16_t ObNetVConnection::get_real_client_port() -{ - return ops_ip_port_host_order(get_real_client_addr()); -} - // virtual inline const sockaddr &ObNetVConnection::get_virtual_addr() { @@ -582,12 +545,6 @@ inline const sockaddr &ObNetVConnection::get_virtual_addr() return virtual_addr_.sa_; } -inline in_addr_t ObNetVConnection::get_virtual_ip() -{ - const sockaddr addr = get_virtual_addr(); - return ops_is_ip4(addr) ? ops_ip4_addr_cast(addr) : 0; -} - inline uint16_t ObNetVConnection::get_virtual_port() { return ops_ip_port_host_order(get_virtual_addr()); @@ -595,6 +552,10 @@ inline uint16_t ObNetVConnection::get_virtual_port() inline uint32_t ObNetVConnection::get_virtual_vid() { + if (!got_virtual_addr_) { + set_virtual_addr(); + got_virtual_addr_ = true; + } return virtual_vid_; } diff --git a/src/obproxy/iocore/net/ob_socket_manager.h b/src/obproxy/iocore/net/ob_socket_manager.h index 223b62e3d5ad2ee454f9d33c07d154ff7f3af5e8..6d784b9e40f7df1d6de2492cd3a636c7c4f3efe0 100644 --- a/src/obproxy/iocore/net/ob_socket_manager.h +++ b/src/obproxy/iocore/net/ob_socket_manager.h @@ -568,6 +568,7 @@ int ObSocketManager::ssl_accept(SSL *ssl, bool &is_connected, int &tmp_code) { int ret = common::OB_SUCCESS; + ERR_clear_error(); if (OB_ISNULL(ssl) || is_connected) { ret = common::OB_INVALID_ARGUMENT; PROXY_NET_LOG(WARN, "invalid argument", K(ret), K(is_connected)); @@ -578,6 +579,11 @@ int ObSocketManager::ssl_accept(SSL *ssl, bool &is_connected, int &tmp_code) if (SSL_ERROR_NONE == tmp_code) { PROXY_NET_LOG(DEBUG, "ssl server accept succ", K(ret)); is_connected = true; + } else if (SSL_ERROR_WANT_WRITE == tmp_code || SSL_ERROR_WANT_READ == tmp_code) { + // do nothing + } else if (SSL_ERROR_ZERO_RETURN == tmp_code || ERR_peek_error() == 0) { + ret = common::OB_SSL_ERROR; + PROXY_NET_LOG(WARN, "peer closed connection in ssl accept", K(ret)); } else { ret = handle_ssl_error(tmp_code); } @@ -593,7 +599,8 @@ int ObSocketManager::ssl_accept(SSL *ssl, bool &is_connected, int &tmp_code) int ObSocketManager::ssl_connect(SSL *ssl, bool &is_connected, int &tmp_code) { int ret = common::OB_SUCCESS; - + + ERR_clear_error(); if (OB_ISNULL(ssl) || is_connected) { ret = common::OB_INVALID_ARGUMENT; PROXY_NET_LOG(WARN, "invalid argument", K(ret), K(is_connected)); @@ -604,6 +611,11 @@ int ObSocketManager::ssl_connect(SSL *ssl, bool &is_connected, int &tmp_code) if (SSL_ERROR_NONE == tmp_code) { PROXY_NET_LOG(DEBUG, "ssl client connect succ", K(ret)); is_connected = true; + } else if (SSL_ERROR_WANT_WRITE == tmp_code || SSL_ERROR_WANT_READ == tmp_code) { + // do nothing + } else if (SSL_ERROR_ZERO_RETURN == tmp_code || ERR_peek_error() == 0) { + ret = common::OB_SSL_ERROR; + PROXY_NET_LOG(WARN, "peer closed connection in ssl connect", K(ret)); } else { ret = handle_ssl_error(tmp_code); } @@ -620,6 +632,7 @@ int ObSocketManager::ssl_read(SSL *ssl, void *buf, const size_t size, int64_t &count, int &tmp_code) { int ret = common::OB_SUCCESS; + ERR_clear_error(); if (OB_ISNULL(ssl) || OB_ISNULL(buf)) { ret = common::OB_INVALID_ARGUMENT; } else if (0 == size) { @@ -642,6 +655,7 @@ int ObSocketManager::ssl_write(SSL *ssl, const void *buf, const size_t size, int64_t &count, int &tmp_code) { int ret = common::OB_SUCCESS; + ERR_clear_error(); if (OB_ISNULL(ssl) || OB_ISNULL(buf)) { ret = common::OB_INVALID_ARGUMENT; } else if (0 == size) { @@ -671,12 +685,38 @@ inline int ObSocketManager::handle_ssl_error(int tmp_code) ret = common::OB_SSL_ERROR; PROXY_NET_LOG(WARN, "the ssl peer has closed", K(ret)); break; + case SSL_ERROR_SYSCALL: { + unsigned long e = ERR_peek_error(); + if (e == 0) { + ret = common::OB_SSL_ERROR; + PROXY_NET_LOG(WARN, "the ssl peer has closed", K(ret)); + } else { + ret = ob_get_sys_errno(); + // Shouldn't have come here, be defensive + if (common::OB_SUCCESS == ret) { + ret = common::OB_SSL_ERROR; + } + char temp_buf[512]; + ERR_error_string_n(e, temp_buf, sizeof(temp_buf)); + PROXY_NET_LOG(WARN, "system error happen", K(ret), K(temp_buf), K(tmp_code)); + } + break; + } + case SSL_ERROR_SSL: { + unsigned long e = ERR_peek_error(); + ret = common::OB_SSL_ERROR; + if (e == 0) { + PROXY_NET_LOG(WARN, "the ssl peer has closed", K(ret)); + } else { + char temp_buf[512]; + ERR_error_string_n(e, temp_buf, sizeof(temp_buf)); + PROXY_NET_LOG(WARN, "system error happen", K(ret), K(temp_buf), K(tmp_code)); + } + break; + } default: ret = common::OB_SSL_ERROR; - char temp_buf[512]; - unsigned long e = ERR_peek_last_error(); - ERR_error_string_n(e, temp_buf, sizeof(temp_buf)); - PROXY_NET_LOG(WARN, "SSL error", K(e), K(temp_buf), K(errno), K(strerror(errno))); + PROXY_NET_LOG(WARN, "unexpected error", K(ret), K(tmp_code)); break; } diff --git a/src/obproxy/iocore/net/ob_unix_net.cpp b/src/obproxy/iocore/net/ob_unix_net.cpp index 64a7e42ed6bf04b544641b5e6756d28460f5870c..37d4a2894f0f421070673203bd653c2f4d34788e 100644 --- a/src/obproxy/iocore/net/ob_unix_net.cpp +++ b/src/obproxy/iocore/net/ob_unix_net.cpp @@ -34,9 +34,11 @@ #include "iocore/net/ob_unix_net.h" #include "iocore/net/ob_event_io.h" #include "iocore/net/ob_timerfd_manager.h" +#include "obutils/ob_resource_pool_processor.h" using namespace oceanbase::common; using namespace oceanbase::obproxy::event; +using namespace oceanbase::obproxy::obutils; namespace oceanbase { @@ -80,6 +82,17 @@ static inline int net_signal_hook_function(ObEThread &thread) return ret; } +void send_signal_when_exit_normally() +{ + if (g_proxy_fatal_errcode == OB_SUCCESS) { + pid_t parent_pid= getppid(); + if (parent_pid != 1) { + PROXY_NET_LOG(INFO, "obproxy child will send SIGUSR2 to parent", K(parent_pid)); + kill(parent_pid, SIGUSR2); + } + } +} + void proxy_exit_once() { // no connection opened, graceful exit flag is true, graceful exit timeout, exit!! @@ -98,7 +111,7 @@ void proxy_exit_once() } ret = OB_SUCCESS;//ignore error } - OB_LOGGER.destory_async_log_thread(); + OB_LOGGER.destroy_async_log_thread(); _exit(1); } @@ -307,6 +320,7 @@ int ObInactivityCop::check_inactivity(int event, ObEvent *e) if (global_connections > 0) { if (info.graceful_exit_end_time_ >= info.graceful_exit_start_time_ && info.graceful_exit_end_time_ <= now) { + send_signal_when_exit_normally(); pthread_once(&g_exit_once, proxy_exit_once); } else { int64_t thread_local_client_connections = 0; @@ -315,6 +329,7 @@ int ObInactivityCop::check_inactivity(int event, ObEvent *e) K(global_connections), K(thread_local_client_connections), K(g_proxy_fatal_errcode)); } } else { + send_signal_when_exit_normally(); pthread_once(&g_exit_once, proxy_exit_once); } } else { @@ -347,7 +362,7 @@ int ObInactivityCop::check_inactivity(int event, ObEvent *e) PROXY_NET_LOG(WARN, "fail to close unix net vconnection", K(vc), K(close_ret)); } } else { - + int32_t event = EVENT_NONE; if (vc->get_is_force_timeout() || (info.graceful_exit_end_time_ >= info.graceful_exit_start_time_ && info.graceful_exit_end_time_ > 0 @@ -355,6 +370,16 @@ int ObInactivityCop::check_inactivity(int event, ObEvent *e) vc->next_inactivity_timeout_at_ = now; // force the connection timeout } + if (now != vc->next_inactivity_timeout_at_) { + ObIpEndpoint ip(vc->get_remote_addr()); + if (0 < get_global_proxy_config().server_detect_mode + && vc->source_type_ == ObUnixNetVConnection::VC_CONNECT + && OB_HASH_EXIST == get_global_resource_pool_processor().ip_set_.exist_refactored(ip)) { + PROXY_NET_LOG(WARN, "detect server dead, close connection", K(ip)); + event = EVENT_ERROR; + } + } + // set a default inactivity timeout if one is not set if (0 == vc->next_inactivity_timeout_at_ && default_inactivity_timeout_ > 0) { PROXY_NET_LOG(DEBUG, "inactivity timeout not set, setting a default", @@ -378,6 +403,8 @@ int ObInactivityCop::check_inactivity(int event, ObEvent *e) "next_inactivity_timeout_at", hrtime_to_sec(vc->next_inactivity_timeout_at_), "inactivity_timeout_in", hrtime_to_sec(vc->inactivity_timeout_in_)); vc->handle_event(EVENT_IMMEDIATE, e); + } else if (EVENT_NONE != event) { + vc->handle_event(event, e); } } } diff --git a/src/obproxy/iocore/net/ob_unix_net_processor.cpp b/src/obproxy/iocore/net/ob_unix_net_processor.cpp index e3ab0fcd6fa1807309af62223e8ba61245648a67..27f409d1d34771f4c63bf27b5a8f4d92619b2ddd 100644 --- a/src/obproxy/iocore/net/ob_unix_net_processor.cpp +++ b/src/obproxy/iocore/net/ob_unix_net_processor.cpp @@ -250,7 +250,7 @@ inline ObAction *ObUnixNetProcessor::accept_internal(ObContinuation &cont, int f if (OB_FAIL(ret)) { if (NULL != na) { if (NULL != na->action_) { - delete na->action_; + // na->action is of type ObPtr na->action_ = NULL; } else { delete na; @@ -459,6 +459,15 @@ private: } break; + case VC_EVENT_DETECT_SERVER_DEAD: + PROXY_NET_LOG(WARN, "detect server addr dead", "addr", vc_->con_.addr_, K(this)); + vc_->do_io_close(); + if (!action_.cancelled_) { + action_.continuation_->handle_event(NET_EVENT_OPEN_FAILED, + reinterpret_cast(-ENET_CONNECT_FAILED)); + } + break; + default: PROXY_NET_LOG(WARN, "unknown connect event"); if (!action_.cancelled_) { diff --git a/src/obproxy/iocore/net/ob_unix_net_vconnection.cpp b/src/obproxy/iocore/net/ob_unix_net_vconnection.cpp index fb93028bdea849f5e923b73aa2a35733a955bfad..764248ebc768cd56e985f1de0b77e55085703827 100644 --- a/src/obproxy/iocore/net/ob_unix_net_vconnection.cpp +++ b/src/obproxy/iocore/net/ob_unix_net_vconnection.cpp @@ -117,6 +117,7 @@ inline int ObUnixNetVConnection::read_signal_and_update(const int event) case VC_EVENT_ERROR: case VC_EVENT_ACTIVE_TIMEOUT: case VC_EVENT_INACTIVITY_TIMEOUT: + case VC_EVENT_DETECT_SERVER_DEAD: PROXY_NET_LOG(DEBUG, "null read.vio cont, closing vc", K(event), K(this)); closed_ = 1; break; @@ -151,6 +152,7 @@ inline int ObUnixNetVConnection::write_signal_and_update(const int event) case VC_EVENT_ERROR: case VC_EVENT_ACTIVE_TIMEOUT: case VC_EVENT_INACTIVITY_TIMEOUT: + case VC_EVENT_DETECT_SERVER_DEAD: PROXY_NET_LOG(DEBUG, "null write.vio cont, closing vc", K(event), K(this)); closed_ = 1; break; @@ -1193,13 +1195,46 @@ void ObUnixNetVConnection::remove_from_keep_alive_lru() } int ObUnixNetVConnection::set_virtual_addr() +{ + int ret = OB_SUCCESS; + get_remote_addr(); + + if (OB_UNLIKELY(get_global_proxy_config().enable_qa_mode)) { + // Simulate public cloud SLB to assign IP addresses + // Get the real client address first, then modify the virutal address + do_set_virtual_addr(); + if (OB_FAIL(ops_ip_pton(get_global_proxy_config().qa_mode_mock_public_cloud_slb_addr, virtual_addr_))) { + PROXY_CS_LOG(WARN, "fail to ops ip pton", "qa_mode_mock_public_cloud_slb_addr", + get_global_proxy_config().qa_mode_mock_public_cloud_slb_addr, K(ret)); + } else { + virtual_vid_ = static_cast(get_global_proxy_config().qa_mode_mock_public_cloud_vid); + } + } else if (remote_addr_.is_ip4()) { + ret = do_set_virtual_addr(); + } else { + real_client_addr_ = remote_addr_; + virtual_addr_ = remote_addr_; + virtual_addr_.sin6_.sin6_port = htons(2883); + } + + return ret; +} + +int ObUnixNetVConnection::do_set_virtual_addr() { int ret = OB_SUCCESS; struct vtoa_get_vs4rds vs; int vs_len = sizeof(struct vtoa_get_vs4rds); if (OB_FAIL(get_vip4rds(con_.fd_, &vs, &vs_len))) { - PROXY_NET_LOG(DEBUG, "fail to get_vip4rds", K(ret)); + PROXY_NET_LOG(DEBUG, "fail to get_vip4rds, use remote ip as virtual ip", K(ret)); + + sockaddr_in sin_c; + sin_c.sin_family = AF_INET; + sin_c.sin_port = htons(2883); + sin_c.sin_addr.s_addr = vs.caddr; + + virtual_addr_.assign(ops_ip_sa_cast(sin_c)); } else { ObIpAddr ip_addr(vs.entrytable.vaddr); virtual_addr_.assign(ip_addr, vs.entrytable.vport); @@ -1217,21 +1252,13 @@ int ObUnixNetVConnection::set_virtual_addr() sin_d.sin_port = vs.dport; sin_d.sin_addr.s_addr = vs.daddr; - if (OB_SUCCESS == ret) { - PROXY_NET_LOG(INFO, "vip connect", - "protocol", vs.protocol, - "fd", con_.fd_, - "vid", virtual_vid_, - "vaddr", virtual_addr_, - "caddr", ObIpEndpoint(ops_ip_sa_cast(sin_c)), - "daddr", ObIpEndpoint(ops_ip_sa_cast(sin_d))); - } else { - PROXY_NET_LOG(DEBUG, "tcp connect", - "protocol", vs.protocol, - "fd", con_.fd_, - "caddr", ObIpEndpoint(ops_ip_sa_cast(sin_c)), - "daddr", ObIpEndpoint(ops_ip_sa_cast(sin_d))); - } + PROXY_NET_LOG(INFO, "vip connect", + "protocol", vs.protocol, + "fd", con_.fd_, + "vid", virtual_vid_, + "vaddr", virtual_addr_, + "caddr", ObIpEndpoint(ops_ip_sa_cast(sin_c)), + "daddr", ObIpEndpoint(ops_ip_sa_cast(sin_d))); return ret; } @@ -1445,7 +1472,7 @@ int ObUnixNetVConnection::main_event(int event, ObEvent *e) if (OB_ISNULL(e)) { ret = OB_ERR_UNEXPECTED; PROXY_NET_LOG(WARN, "occur fatal error", K(event), K(e), K(ret)); - } else if (OB_UNLIKELY(EVENT_IMMEDIATE != event && EVENT_INTERVAL != event)) { + } else if (OB_UNLIKELY(EVENT_IMMEDIATE != event && EVENT_INTERVAL != event && EVENT_ERROR != event)) { ret = OB_ERR_UNEXPECTED; PROXY_NET_LOG(WARN, "occur fatal error", K(event), K(e), K(ret)); } else if (thread_ != this_ethread()) { @@ -1486,6 +1513,8 @@ int ObUnixNetVConnection::main_event(int event, ObEvent *e) signal_event = VC_EVENT_INACTIVITY_TIMEOUT; signal_timeout_at = &next_inactivity_timeout_at_; } + } else if (EVENT_ERROR == event) { + signal_event = VC_EVENT_DETECT_SERVER_DEAD; } else { signal_event = VC_EVENT_ACTIVE_TIMEOUT; signal_timeout = &active_timeout_action_; @@ -1705,6 +1734,9 @@ int ObUnixNetVConnection::ssl_server_handshake(ObEThread &thread) if (NULL == ssl_) { ret = OB_ERR_UNEXPECTED; PROXY_NET_LOG(WARN, "ssl server handshake event", K(ret)); + } else if (!lock.is_locked()) { + nh_->write_ready_list_.in_or_enqueue(this); + nh_->read_ready_list_.in_or_enqueue(this); } else if (OB_FAIL(ObSocketManager::ssl_accept(ssl_, ssl_connected_, tmp_code))) { handle_ssl_err_code(tmp_code); read_.triggered_ = false; @@ -1734,6 +1766,9 @@ int ObUnixNetVConnection::ssl_client_handshake(ObEThread &thread) if (NULL == ssl_) { ret = OB_ERR_UNEXPECTED; PROXY_NET_LOG(WARN, "ssl client handshake event", K(ret)); + } else if (!lock.is_locked()) { + nh_->write_ready_list_.in_or_enqueue(this); + nh_->read_ready_list_.in_or_enqueue(this); } else if (OB_FAIL(ObSocketManager::ssl_connect(ssl_, ssl_connected_, tmp_code))) { handle_ssl_err_code(tmp_code); write_.triggered_ = false; diff --git a/src/obproxy/iocore/net/ob_unix_net_vconnection.h b/src/obproxy/iocore/net/ob_unix_net_vconnection.h index 33459f4753978db5c21ce7b56e9eb3ef399370f2..863e64df576b741c4e7a032f9a32027eb715a070 100644 --- a/src/obproxy/iocore/net/ob_unix_net_vconnection.h +++ b/src/obproxy/iocore/net/ob_unix_net_vconnection.h @@ -110,6 +110,7 @@ private: virtual bool get_data(const int32_t id, void *data); // unused !!! virtual int get_socket(); virtual int set_tcp_init_cwnd(const int32_t init_cwnd); + int do_set_virtual_addr(); public: int init(); diff --git a/src/obproxy/ob_proxy.cpp b/src/obproxy/ob_proxy.cpp index 36003e15a3b1bd4ef7195ce66f7652fdeae51ef8..cc8444a7b29f3447766d6abecfdcbbf501d85ee5 100644 --- a/src/obproxy/ob_proxy.cpp +++ b/src/obproxy/ob_proxy.cpp @@ -75,6 +75,7 @@ #include "obutils/ob_session_pool_processor.h" #include "obutils/ob_config_processor.h" #include "iocore/net/ob_ssl_processor.h" +#include "ob_proxy_init.h" using namespace oceanbase::common; using namespace oceanbase::share; @@ -173,7 +174,7 @@ int ObProxy::init(ObProxyOptions &opts, ObAppVersionInfo &proxy_version) LOG_ERROR("fail to init ssl processor", K(ret)); } else if (OB_FAIL(init_config())) { LOG_ERROR("fail to init config", K(ret)); - } else if (get_global_config_processor().init()) { + } else if (OB_FAIL(get_global_config_processor().init())) { LOG_ERROR("fail to init config processor", K(ret)); } else if (OB_FAIL(config_->enable_sharding && dbconfig_processor.init(config_->grpc_client_num, ObProxyMain::get_instance()->get_startup_time()))) { @@ -194,9 +195,11 @@ int ObProxy::init(ObProxyOptions &opts, ObAppVersionInfo &proxy_version) } else if (OB_FAIL(app_config_processor.init())) { LOG_ERROR("fail to init app config processor", K(ret)); } else { - // if fail to init prometheus, do not stop the startup of obproxy - if (g_ob_prometheus_processor.init()) { - LOG_WARN("fail to init prometheus processor"); + if (RUN_MODE_PROXY == g_run_mode) { + // if fail to init prometheus, do not stop the startup of obproxy + if (OB_FAIL(g_ob_prometheus_processor.init())) { + LOG_WARN("fail to init prometheus processor", K(ret)); + } } #if OB_HAS_TESTS @@ -247,9 +250,33 @@ void ObProxy::destroy() if (OB_FAIL(ObAsyncCommonTask::destroy_repeat_task(mmp_init_cont_))) { LOG_WARN("fail to destroy meta proxy init task", K(ret)); } + ObThreadId tid = 0; + for (int64_t i = 0; i < g_event_processor.dedicate_thread_count_ && OB_SUCC(ret); ++i) { + tid = g_event_processor.all_dedicate_threads_[i]->tid_; + if (OB_FAIL(thread_cancel(tid))) { + PROXY_NET_LOG(WARN, "fail to do thread_cancel", K(tid), K(ret)); + } else if (OB_FAIL(thread_join(tid))) { + PROXY_NET_LOG(WARN, "fail to do thread_join", K(tid), K(ret)); + } else { + PROXY_NET_LOG(INFO, "graceful exit, dedicated thread exited", K(tid)); + } + ret = OB_SUCCESS;//ignore error + } - proxy_opts_ = NULL; - mysql_config_params_ = NULL; + for (int64_t i = 0; i < g_event_processor.event_thread_count_ && OB_SUCC(ret); ++i) { + tid = g_event_processor.all_event_threads_[i]->tid_; + if (OB_FAIL(thread_cancel(tid))) { + PROXY_NET_LOG(WARN, "fail to do thread_cancel", K(tid), K(ret)); + } else if (OB_FAIL(thread_join(tid))) { + PROXY_NET_LOG(WARN, "fail to do thread_join", K(tid), K(ret)); + } else { + PROXY_NET_LOG(INFO, "graceful exit, event thread exited", K(tid)); + } + ret = OB_SUCCESS;//ignore error + } + + OB_LOGGER.destroy_async_log_thread(); + _exit(0); } } @@ -262,7 +289,7 @@ int ObProxy::start() } else if (OB_FAIL(ObMysqlProxyServerMain::start_mysql_proxy_server(*mysql_config_params_))) { LOG_ERROR("fail to start mysql proxy server", K(ret)); } else if (OB_FAIL(ObProxyMain::get_instance()->schedule_detect_task())) { - LOG_ERROR("fail to schedule detech task", K(ret)); + LOG_ERROR("fail to schedule detect task", K(ret)); } else { // we can't strongly dependent on the OCP. @@ -326,7 +353,7 @@ int ObProxy::start() } else if (OB_FAIL(ObCacheCleaner::schedule_cache_cleaner())) { LOG_WARN("fail to alloc and schedule cache cleaner", K(ret)); } else if (config_->is_metadb_used() && OB_FAIL(proxy_table_processor_.start_check_table_task())) { - LOG_WARN("fail to start check table check", K(ret)); + LOG_WARN("fail to start check table task", K(ret)); } else if (OB_FAIL(hot_upgrade_processor_.start_hot_upgrade_task())) { LOG_WARN("fail to start hot upgrade task", K(ret)); } else if (OB_FAIL(log_file_processor_->start_cleanup_log_file())) { @@ -338,22 +365,20 @@ int ObProxy::start() } else if (OB_FAIL(tenant_stat_mgr_->start_tenant_stat_dump_task())) { LOG_ERROR("fail to start_tenant_stat_dump_task", K(ret)); } else if (OB_FAIL(g_ob_qos_stat_processor.start_qos_stat_clean_task())) { - LOG_ERROR("fail to start_tenant_stat_dump_task", K(ret)); + LOG_ERROR("fail to start_qos_stat_clean_task", K(ret)); } else if (config_->enable_sharding - && config_->is_control_plane_used() - && !config_->use_local_dbconfig - && OB_FAIL(get_global_db_config_processor().start_watch_parent_crd())) { - LOG_WARN("fail to start watch parent crd", K(ret)); - } else if (config_->enable_sharding - && config_->use_local_dbconfig - && OB_FAIL(get_global_inotify_processor().start_watch_sharding_config())) { - LOG_WARN("fail to start inotify watch sharding config", K(ret)); + && OB_FAIL(get_global_db_config_processor().start())) { + LOG_WARN("fail to start sharding", K(ret)); } else if (OB_FAIL(config_->is_pool_mode && get_global_session_pool_processor().start_session_pool_task())) { LOG_WARN("fail to start_session_pool_task", K(ret)); + } else if (OB_FAIL(ObMysqlProxyServerMain::start_mysql_proxy_acceptor())) { + LOG_ERROR("fail to start accept server", K(ret)); } else { - // if fail to init prometheus, do not stop the startup of obproxy - if (g_ob_prometheus_processor.start_prometheus()) { - LOG_WARN("fail to start prometheus"); + if (RUN_MODE_PROXY == g_run_mode) { + // if fail to init prometheus, do not stop the startup of obproxy + if (OB_FAIL(g_ob_prometheus_processor.start_prometheus())) { + LOG_WARN("fail to start prometheus", K(ret)); + } } mysql_config_params_ = NULL; @@ -377,7 +402,9 @@ int ObProxy::start() } info.is_parent_ = true; } - this_ethread()->execute(); + if (RUN_MODE_PROXY == g_run_mode) { + this_ethread()->execute(); + } } } return ret; @@ -415,7 +442,7 @@ int ObProxy::init_user_specified_config() { int ret = OB_SUCCESS; //1. set config from cmd -o name=value - if (NULL != proxy_opts_->optstr_ && OB_FAIL(config_->add_extra_config(proxy_opts_->optstr_))) { + if (NULL != proxy_opts_->optstr_ && OB_FAIL(config_->add_extra_config_from_opt(proxy_opts_->optstr_))) { LOG_WARN("fail to add extra config", K(ret)); //2. set config from cmd other opts @@ -942,6 +969,7 @@ int ObProxy::get_meta_table_server(ObIArray &replicas, O ObString password(config_->observer_sys_password.str()); ObString password1(config_->observer_sys_password1.str()); ObSEArray rs_list; + int64_t cluster_version = 0; // first get from local if (OB_FAIL(cs_processor_->get_cluster_rs_list(cluster_name, OB_DEFAULT_CLUSTER_ID, rs_list))) { @@ -961,11 +989,47 @@ int ObProxy::get_meta_table_server(ObIArray &replicas, O if (rs_list.count() <= 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("rs_list count must > 0", K(ret)); - } else if (OB_FAIL(raw_client.init(user_name, password, database, password1))) { + } else if (OB_FAIL(raw_client.init(user_name, password, database, cluster_name, password1))) { LOG_WARN("fail to init raw mysql client", K(ret)); } else if (OB_FAIL(raw_client.set_server_addr(rs_list))) { LOG_WARN("fail to set server addr", K(ret)); - } else { + } + + if (OB_SUCC(ret)) { + const char *sql = "select ob_version() as cluster_version"; + ObClientMysqlResp *resp = NULL; + ObResultSetFetcher *rs_fetcher = NULL; + if (OB_FAIL(raw_client.sync_raw_execute(sql, timeout_ms, resp))) { + LOG_WARN("fail to sync raw execute", K(resp), K(timeout_ms), K(ret)); + } else if (OB_ISNULL(resp)) { + ret = OB_NO_RESULT; + LOG_WARN("resp is null", K(ret)); + } else if (OB_FAIL(resp->get_resultset_fetcher(rs_fetcher))) { + LOG_WARN("fail to get resultset fetcher", K(ret)); + } else if (OB_ISNULL(rs_fetcher)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("rs fetcher is NULL", K(ret)); + } + + while (OB_SUCC(ret) && OB_SUCC(rs_fetcher->next())) { + ObString cluster_version_str; + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(*rs_fetcher, "cluster_version", cluster_version_str); + int64_t version = 0; + for (int64_t i = 0; i < cluster_version_str.length() && cluster_version_str[i] != '.'; i++) { + version = version * 10 + cluster_version_str[i] - '0'; + } + cluster_version = version; + } + + ret = OB_SUCCESS; + + if (NULL != resp) { + op_free(resp); + resp = NULL; + } + } + + if (OB_SUCC(ret)) { ObString meta_tenant_name = username.after('@'); if (meta_tenant_name.empty()) { meta_tenant_name.assign_ptr(OB_SYS_TENANT_NAME, @@ -983,7 +1047,7 @@ int ObProxy::get_meta_table_server(ObIArray &replicas, O ObResultSetFetcher *rs_fetcher = NULL; ObTableEntry *entry = NULL; ObProxyPartitionLocation pl; - if (OB_FAIL(ObRouteUtils::get_table_entry_sql(sql, OB_SHORT_SQL_LENGTH, name))) { + if (OB_FAIL(ObRouteUtils::get_table_entry_sql(sql, OB_SHORT_SQL_LENGTH, name, false, cluster_version))) { LOG_WARN("fail to get table entry sql", K(sql), K(ret)); } else if (OB_FAIL(raw_client.sync_raw_execute(sql, timeout_ms, resp))) { LOG_WARN("fail to sync raw execute", K(sql), K(resp), K(timeout_ms), K(ret)); @@ -997,7 +1061,7 @@ int ObProxy::get_meta_table_server(ObIArray &replicas, O LOG_WARN("rs fetcher is NULL", K(ret)); } else if (OB_FAIL(ObTableEntry::alloc_and_init_table_entry(name, 0, OB_DEFAULT_CLUSTER_ID, entry))) { LOG_WARN("fail to alloc and init table entry", K(name), K(ret)); - } else if (OB_FAIL(ObRouteUtils::fetch_table_entry(*rs_fetcher, *entry))) { + } else if (OB_FAIL(ObRouteUtils::fetch_table_entry(*rs_fetcher, *entry, cluster_version))) { LOG_WARN("fail to fetch one table entry info", K(ret)); } else if (OB_FAIL(entry->get_random_servers(pl))) { LOG_WARN("fail to get random servers", K(ret)); diff --git a/src/obproxy/ob_proxy.h b/src/obproxy/ob_proxy.h index 7b92747be842626e3cbd478818cace876cbf61af..adbb394ba86d66e3300a4d8b8c5a12d9410ffc47 100644 --- a/src/obproxy/ob_proxy.h +++ b/src/obproxy/ob_proxy.h @@ -40,6 +40,7 @@ namespace proxy { class ObMysqlConfigParams; } + class ObLogFileProcessor; class ObInternalCmdProcessor; diff --git a/src/obproxy/ob_proxy_init.cpp b/src/obproxy/ob_proxy_init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4300cfe69b2e706f988d42da486fd62d41b84ea7 --- /dev/null +++ b/src/obproxy/ob_proxy_init.cpp @@ -0,0 +1,130 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * + * ************************************************************* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "ob_proxy_main.h" +#include "lib/oblog/ob_warning_buffer.h" +#include "ob_proxy_init.h" +#include "lib/json/ob_json.h" +#include "obutils/ob_proxy_json_config_info.h" + +using namespace oceanbase::common; +using namespace oceanbase::json; +using namespace oceanbase::obproxy::obutils; + +namespace oceanbase +{ +namespace obproxy +{ + +OBPROXY_RUN_MODE g_run_mode = RUN_MODE_PROXY; +static bool is_obproxy_inited = false; +DRWLock local_init_lock; + +int init_obproxy_client(const ObString &config) +{ + int ret = OB_SUCCESS; + if (!is_obproxy_inited) { + DRWLock::WRLockGuard lock(local_init_lock); + if (!is_obproxy_inited) { + static const int DEFAULT_MMAP_MAX_VAL = 1024 * 1024 * 1024; // 1G + mallopt(M_MMAP_MAX, DEFAULT_MMAP_MAX_VAL); + mallopt(M_ARENA_MAX, 1); // disable malloc multiple arena pool + + setlocale(LC_ALL, ""); + + // turn warn log on so that there's a obproxy.log.wf file which records + // all WARN and ERROR logs in log directory. + ObWarningBuffer::set_warn_log_on(true); + // DISABLE_DIA(); disable di_cache stat + + g_run_mode = RUN_MODE_CLIENT; + int argc = 0; + char argv[10][4096]; + memset(argv, 0, sizeof(argv)); + MEMCPY(argv[0], "./bin/obproxy", strlen("./bin/obproxy")); + argc++; + if (!config.empty()) { + Parser parser; + json::Value *json_value = NULL; + ObArenaAllocator json_allocator(ObModIds::OB_JSON_PARSER); + if (OB_FAIL(parser.init(&json_allocator))) { + MPRINT("json parser init failed, ret =%d", ret); + } else if (OB_FAIL(parser.parse(config.ptr(), config.length(), json_value))) { + MPRINT("json parse failed, ret =%d", ret); + } else if (OB_FAIL(ObProxyJsonUtils::check_config_info_type(json_value, json::JT_OBJECT))) { + MPRINT("check config info type failed, ret=%d", ret); + } else { + DLIST_FOREACH(p, json_value->get_object()) { + if (0 == p->name_.case_compare("proxy_config")) { + if (OB_FAIL(ObProxyJsonUtils::check_config_info_type(p->value_, json::JT_STRING))) { + MPRINT("check config info type failed, ret=%d", ret); + } else { + MEMCPY(argv[argc++], "-o", strlen("-o")); + MEMCPY(argv[argc++], p->value_->get_string().ptr(), p->value_->get_string().length()); + } + } + } + } + } + + if (OB_SUCC(ret)) { + char *tmp_argv[10]; + for (int i = 0; i < argc; i++) { + tmp_argv[i] = argv[i]; + } + ObProxyMain *proxy_main = ObProxyMain::get_instance(); + if (OB_ISNULL(proxy_main)) { + ret = OB_ERR_UNEXPECTED; + MPRINT("fail to get obproxy main instance, ret=%d", ret); + } else if (OB_FAIL(proxy_main->start(argc, tmp_argv))) { + MPRINT("fail to start obproxy, ret=%d", ret); + } else { + is_obproxy_inited = true; + atexit(destroy_obproxy_client); + } + } + } + } + + return ret; +} + +void destroy_obproxy_client() +{ + ObProxyMain *proxy_main = ObProxyMain::get_instance(); + if (OB_NOT_NULL(proxy_main)) { + proxy_main->destroy(); + } +} + +} +} + diff --git a/src/obproxy/ob_proxy_init.h b/src/obproxy/ob_proxy_init.h new file mode 100644 index 0000000000000000000000000000000000000000..4c76fc2b4f4a4b99dc85b15b6858b15873e31a41 --- /dev/null +++ b/src/obproxy/ob_proxy_init.h @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * + * ************************************************************* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBPROXY_INIT_H_ +#define OBPROXY_INIT_H_ + +namespace oceanbase +{ +namespace common +{ +class ObString; +} +namespace obproxy +{ +enum OBPROXY_RUN_MODE { + RUN_MODE_PROXY, + RUN_MODE_CLIENT, + RUN_MODE_INVALID, +}; + +extern OBPROXY_RUN_MODE g_run_mode; + +int init_obproxy_client(const common::ObString& config); + +void destroy_obproxy_client(); + +} // end of obproxy +} // end of oceanbase + + +#endif diff --git a/src/obproxy/ob_proxy_main.cpp b/src/obproxy/ob_proxy_main.cpp index ceb87398cea9c864ef84c98032d3572ddfdce6ff..3a5161b37feaeea270728b99a0f1aec84ffaf152 100644 --- a/src/obproxy/ob_proxy_main.cpp +++ b/src/obproxy/ob_proxy_main.cpp @@ -28,6 +28,7 @@ #include "obutils/ob_async_common_task.h" #include "cmd/ob_show_sqlaudit_handler.h" +#include "ob_proxy_init.h" using namespace oceanbase::common; using namespace oceanbase::lib; @@ -311,7 +312,7 @@ int ObProxyMain::parse_cmd_line(const int argc, char *const argv[], ObProxyOptio if (0 == c) { if (OB_FAIL(parse_short_opt(long_opts[long_opts_idx].val, optarg, opts))) { - MPRINT("fail to parse long opt, ret=%d", ret); + MPRINT("fail to parse short opt, ret=%d", ret); break; } } else { @@ -398,6 +399,10 @@ int ObProxyMain::get_log_file_name(const ObLogFDType type, char *file_name, cons ret_len = snprintf(log_file_name, OB_MAX_LOG_FILE_NAME_LEN, "obproxy_pool.log"); } else if (FD_POOL_STAT_FILE == type) { ret_len = snprintf(log_file_name, OB_MAX_LOG_FILE_NAME_LEN, "obproxy_pool_stat.log"); + } else if (FD_TRACE_FILE == type) { + ret_len = snprintf(log_file_name, OB_MAX_LOG_FILE_NAME_LEN, "obproxy_trace.log"); + } else if (FD_DRIVER_CLIENT_FILE == type) { + ret_len = snprintf(log_file_name, OB_MAX_LOG_FILE_NAME_LEN, "obproxy_client.log"); } else { ret_len = snprintf(log_file_name, OB_MAX_LOG_FILE_NAME_LEN, "obproxy.log"); } @@ -434,7 +439,7 @@ int ObProxyMain::start(const int argc, char *const argv[]) ObProxyOptions opts; memset(&opts, 0, sizeof(opts)); - if (OB_FAIL(print_args(argc, argv))) { + if (RUN_MODE_PROXY == g_run_mode && OB_FAIL(print_args(argc, argv))) { MPRINT("fail to print args, ret=%d", ret); } else if (OB_FAIL(parse_cmd_line(argc, argv, opts))) { if (OB_NOT_RUNNING != ret) { @@ -446,7 +451,7 @@ int ObProxyMain::start(const int argc, char *const argv[]) const ObHotUpgraderInfo &info = get_global_hot_upgrade_info(); // if inherited, don not use daemon - if (OB_SUCC(ret)) { + if (RUN_MODE_PROXY == g_run_mode && OB_SUCC(ret)) { if (!opts.nodaemon_ && !info.is_inherited_) { if (OB_FAIL(use_daemon())) { MPRINT("fail to use deamon, ret=%d", ret); @@ -454,16 +459,16 @@ int ObProxyMain::start(const int argc, char *const argv[]) } } - if (OB_SUCC(ret)) { + if (RUN_MODE_PROXY == g_run_mode && OB_SUCC(ret)) { if (info.is_inherited_) { - if (OB_FAIL(close_all_fd(info.fd_))) { + if (OB_FAIL(close_all_fd(info.ipv4_fd_, info.ipv6_fd_))) { MPRINT("fail to close all fd, ret=%d", ret); } } } if (OB_SUCC(ret)) { - if (OB_FAIL(get_global_layout().init(info.argv_[0]))) { + if (OB_FAIL(get_global_layout().init(argv[0]))) { MPRINT("fail to init global layout, ret=%d", ret); } else if (OB_FAIL(init_log())) { MPRINT("fail to init log, ret=%d", ret); @@ -475,7 +480,8 @@ int ObProxyMain::start(const int argc, char *const argv[]) app_info_.setup(PACKAGE_STRING, APP_NAME, RELEASEID); _LOG_INFO("%s-%s", app_info_.full_version_info_str_, build_version()); if (info.is_inherited_) { - LOG_INFO("obproxy will start by hot upgrade", " listen fd", info.fd_, K(info)); + LOG_INFO("obproxy will start by hot upgrade", " listen ipv4 fd", info.ipv4_fd_, + "listen ipv6 fd", info.ipv6_fd_, K(info)); } else { LOG_INFO("has no inherited sockets, start new obproxy", K(info)); } @@ -493,18 +499,28 @@ int ObProxyMain::handle_inherited_sockets(const int argc, char *const argv[]) int ret = OB_SUCCESS; ObHotUpgraderInfo &info = get_global_hot_upgrade_info(); - if (OB_UNLIKELY(argc <= 0) || OB_ISNULL(argv) || OB_ISNULL(argv[0])) { + if (RUN_MODE_CLIENT == g_run_mode) { + // do nothing + } else if (OB_UNLIKELY(argc <= 0) || OB_ISNULL(argv) || OB_ISNULL(argv[0])) { ret = OB_INVALID_ARGUMENT; MPRINT("invalid argument, argc=%d, argv=%p, ret=%d", argc, argv, ret); } else { info.set_main_arg(argc, argv); - char *inherited = NULL; + char *inherited_ipv4 = NULL; + char *inherited_ipv6 = NULL; - if (NULL == (inherited = getenv(OBPROXY_INHERITED_FD))) { + inherited_ipv4 = getenv(OBPROXY_INHERITED_IPV4_FD); + inherited_ipv6 = getenv(OBPROXY_INHERITED_IPV6_FD); + if (NULL == inherited_ipv4 && NULL == inherited_ipv6) { // has no inherited sockets, will start new obproxy, // and set it HU_STATE_WAIT_HU_CMD state info.update_state(HU_STATE_WAIT_HU_CMD); info.is_parent_ = true; + } else if (NULL == inherited_ipv4) { + // Allow IPv6 to be empty + // because it may be a hot upgrade from a lower version to a higher version + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("ipv4 should not be NULL", K(ret)); } else if (info.is_inherited_) { ret = OB_ERR_UNEXPECTED; MPRINT("hot upgrade info is_inherited can't be true, ret=%d", ret); @@ -512,11 +528,18 @@ int ObProxyMain::handle_inherited_sockets(const int argc, char *const argv[]) // obproxy will start by hot upgrade // we will set it HU_STATE_WAIT_CR_CMD state and HU_STATUS_NEW_PROXY_CREATED_SUCC status info.is_inherited_ = true; - info.fd_ = atoi(inherited); + info.ipv4_fd_ = atoi(inherited_ipv4); + + if (NULL != inherited_ipv6) { + info.ipv6_fd_ = atoi(inherited_ipv6); + } + info.update_state(HU_STATE_WAIT_HU_CMD); info.is_parent_ = false; - if (OB_FAIL(unsetenv(OBPROXY_INHERITED_FD))) { - MPRINT("fail to unsetenv OBPROXY_INHERITED_FD, ret=%d", ret); + if (OB_FAIL(unsetenv(OBPROXY_INHERITED_IPV4_FD))) { + MPRINT("fail to unsetenv OBPROXY_INHERITED_IPV4_FD, ret=%d", ret); + } else if (OB_FAIL(unsetenv(OBPROXY_INHERITED_IPV6_FD))) { + MPRINT("fail to unsetenv OBPROXY_INHERITED_IPV6_FD, ret=%d", ret); } } } @@ -534,7 +557,13 @@ int ObProxyMain::init_log() LOG_ERROR("fail to get log file name", K(type), K(ret)); } else { if (FD_DEFAULT_FILE == type) { - OB_LOGGER.set_file_name(type, log_file_name, true, true); + if (RUN_MODE_PROXY == g_run_mode) { + OB_LOGGER.set_file_name(type, log_file_name, true, true); + } else if (RUN_MODE_CLIENT == g_run_mode) { + OB_LOGGER.set_file_name(type, log_file_name, false, true); + } else { + MPRINT("invalid g_run_mode, mode=%d", g_run_mode); + } } else { OB_LOGGER.set_file_name(type, log_file_name); } @@ -576,6 +605,8 @@ int ObProxyMain::init_signal() LOG_WARN("fail to add_sig_direct_catched", K(ret)); } else if (OB_FAIL(add_sig_direct_catched(action, SIGUSR1))) { LOG_WARN("fail to add_sig_direct_catched", K(ret)); + } else if (OB_FAIL(add_sig_direct_catched(action, SIGUSR2))) { + LOG_WARN("fail to add_sig_direct_catched", K(ret)); } else if (OB_FAIL(add_sig_direct_catched(action, 43))) { LOG_WARN("fail to add_sig_direct_catched", K(ret)); @@ -736,16 +767,17 @@ int ObProxyMain::do_detect_sig() // -1 : wait for any sub process while((pid = waitpid(-1, &stat, WNOHANG)) > 0) { LOG_INFO("sub process exit", K(info), K(pid), "status", stat, KERRMSGS); - if (info.sub_pid_ == pid) { - info.reset_sub_pid(); - // after sub was exited, we need passing this status - if (OB_LIKELY(common::OB_SUCCESS == lib::mutex_acquire(&info.hot_upgrade_mutex_))) { + if (OB_LIKELY(common::OB_SUCCESS == lib::mutex_acquire(&info.hot_upgrade_mutex_))) { + if (info.sub_pid_ == pid) { + info.reset_sub_pid(); + // after sub was exited, we need passing this status info.update_sub_status(HU_STATUS_EXITED); info.parent_hot_upgrade_flag_ = false; lib::mutex_release(&info.hot_upgrade_mutex_); + } else { + LOG_WARN("sub process exit, but recv it late"); } - } else { - LOG_WARN("sub process exit, but recv it late"); + lib::mutex_release(&info.hot_upgrade_mutex_); } } break; @@ -824,6 +856,17 @@ void ObProxyMain::sig_direct_handler(const int sig) } break; } + case SIGUSR2: { + ObHotUpgraderInfo &info = get_global_hot_upgrade_info(); + if (OB_LIKELY(common::OB_SUCCESS == lib::mutex_acquire(&info.hot_upgrade_mutex_))) { + // If the SIGUSR2 signal is received, + // the child process is considered to exit normally, + // and the child process is ignored + info.reset_sub_pid(); + lib::mutex_release(&info.hot_upgrade_mutex_); + } + break; + } case SIGTERM: case SIGINT: { ObHotUpgraderInfo &info = get_global_hot_upgrade_info(); @@ -943,7 +986,7 @@ int ObProxyMain::do_monitor_mem() } } - if (is_out_of_mem_limit) { + if (is_out_of_mem_limit && RUN_MODE_PROXY == g_run_mode) { LOG_ERROR("obproxy's memroy is out of limit, will be going to commit suicide", K(mem_limited), "OTHER_MEMORY_SIZE", static_cast(OTHER_MEMORY_SIZE), K(is_out_of_mem_limit), K(cur_pos)); @@ -1031,7 +1074,7 @@ int ObProxyMain::do_detect_sqlaudit() return ret; } -int ObProxyMain::close_all_fd(const int32_t listen_fd) +int ObProxyMain::close_all_fd(const int32_t listen_ipv4_fd, const int32_t listen_ipv6_fd) { //this func can't print log, because log isn't initialized int ret = OB_SUCCESS; @@ -1040,7 +1083,7 @@ int ObProxyMain::close_all_fd(const int32_t listen_fd) DIR *fd_dir = NULL; char fd_dir_path [OB_MAX_FILE_NAME_LENGTH]; - if (OB_UNLIKELY(listen_fd < 3)) { + if (OB_UNLIKELY(listen_ipv4_fd < 3 && listen_ipv6_fd < 3)) { ret = OB_INVALID_ARGUMENT; } else { int n = snprintf(fd_dir_path, OB_MAX_FILE_NAME_LENGTH, "/proc/%d/fd", pid); @@ -1060,7 +1103,8 @@ int ObProxyMain::close_all_fd(const int32_t listen_fd) fd = static_cast(strtol(de->d_name, NULL, 10)); if (fd < 0) { continue; - } else if (fd < 3 || fd == dirfd(fd_dir) || fd == listen_fd) { + } else if (fd < 3 || fd == dirfd(fd_dir) || fd == listen_ipv4_fd + || fd == listen_ipv6_fd) { continue; } else { if (OB_UNLIKELY(0 != close(fd))) { diff --git a/src/obproxy/ob_proxy_main.h b/src/obproxy/ob_proxy_main.h index e29857810bdfca1d54aa96ec6f3691ba03c3157a..35a5d8a4415044510150ce2d7b8e43fe023c8951 100644 --- a/src/obproxy/ob_proxy_main.h +++ b/src/obproxy/ob_proxy_main.h @@ -86,7 +86,7 @@ private: int init_log(); int init_signal(); - int close_all_fd(const int32_t listen_fd); + int close_all_fd(const int32_t listen_ipv4_fd, const int32_t listen_ipv6_fd); class ObLogLevel { diff --git a/src/obproxy/obutils/ob_async_common_task.cpp b/src/obproxy/obutils/ob_async_common_task.cpp index 501541f0a945aca4a1460b8a98ad6554fdf85fc6..cb05e6f1ead70a4bc38b2ee7f95e10360a177710 100644 --- a/src/obproxy/obutils/ob_async_common_task.cpp +++ b/src/obproxy/obutils/ob_async_common_task.cpp @@ -117,7 +117,7 @@ int ObAsyncCommonTask::main_handler(int event, void *data) return EVENT_DONE; } -inline int ObAsyncCommonTask::handle_event_start() +int ObAsyncCommonTask::handle_event_start() { int ret = OB_SUCCESS; if (action_.cancelled_) { @@ -134,7 +134,7 @@ inline int ObAsyncCommonTask::handle_event_start() return ret; } -inline int ObAsyncCommonTask::handle_event_complete(void *data) +int ObAsyncCommonTask::handle_event_complete(void *data) { int ret = OB_SUCCESS; if (action_.cancelled_) { diff --git a/src/obproxy/obutils/ob_config_processor.cpp b/src/obproxy/obutils/ob_config_processor.cpp index ede75b11827af9be05a5f09cc486a1de3c0011c8..19dd90043784855b01d4cf85bdf09fae5324c1d9 100644 --- a/src/obproxy/obutils/ob_config_processor.cpp +++ b/src/obproxy/obutils/ob_config_processor.cpp @@ -34,10 +34,14 @@ #include "opsql/parser/ob_proxy_parser.h" #include "iocore/eventsystem/ob_ethread.h" #include "obutils/ob_proxy_sql_parser.h" +#include "obutils/ob_proxy_stmt.h" #include "cmd/ob_config_v2_handler.h" #include "omt/ob_white_list_table_processor.h" #include "omt/ob_resource_unit_table_processor.h" #include "omt/ob_ssl_config_table_processor.h" +#include "omt/ob_proxy_config_table_processor.h" +#include "obutils/ob_vip_tenant_cache.h" +#include "utils/ob_proxy_utils.h" using namespace obsys; using namespace oceanbase::common; @@ -54,34 +58,45 @@ namespace obproxy namespace obutils { +//the table name need to be lower case, or func'handle_dml_stmt' will get error #define MAX_INIT_SQL_LEN 1024 -static const char* sqlite3_db_name = "etc/proxyconfig.db"; +static const char* sqlite3_db_name = "proxyconfig.db"; static const char* all_table_version_table_name = "all_table_version"; static const char* white_list_table_name = "white_list"; static const char* resource_unit_table_name = "resource_unit"; static const char *ssl_config_table_name = "ssl_config"; -static const char *table_name_array[] = {white_list_table_name, resource_unit_table_name, ssl_config_table_name}; +static const char *proxy_config_table_name = "proxy_config"; +static const char *table_name_array[] = {white_list_table_name, resource_unit_table_name, ssl_config_table_name, proxy_config_table_name}; static const char* create_all_table_version_table = "create table if not exists " "all_table_version(gmt_created date default (datetime('now', 'localtime')), " "gmt_modified date, table_name varchar(1000), " "version int default 0, primary key(table_name))"; -static const char* create_white_list_table = +static const char* create_white_list_table = "create table if not exists " "white_list(gmt_created date default (datetime('now', 'localtime')), gmt_modified date, " - "cluster_name varchar(256), tenant_name varchar(256), name varchar(256), " - "value text, primary key(cluster_name, tenant_name))"; -static const char* create_resource_unit_table = + "cluster_name varchar(256) collate nocase, tenant_name varchar(256) collate nocase, name varchar(256) collate nocase, " + "value text collate nocase, primary key(cluster_name, tenant_name))"; +static const char* create_resource_unit_table = "create table if not exists " "resource_unit(gmt_created date default (datetime('now', 'localtime')), " - "gmt_modified date, cluster_name varchar(256), tenant_name varchar(256), " - "name varchar(256), value text, primary key(cluster_name, tenant_name, name))"; + "gmt_modified date, cluster_name varchar(256) collate nocase, tenant_name varchar(256) collate nocase, " + "name varchar(256) collate nocase, value text collate nocase, primary key(cluster_name, tenant_name, name))"; static const char* create_ssl_config_table = "create table if not exists " "ssl_config(gmt_created date default (datetime('now', 'localtime')), gmt_modified date, " - "cluster_name varchar(256), tenant_name varchar(256), name varchar(256), value text, " - "primary key(cluster_name, tenant_name, name))"; + "cluster_name varchar(256) collate nocase, tenant_name varchar(256) collate nocase, name varchar(256) collate nocase, " + " value text collate nocase, primary key(cluster_name, tenant_name, name))"; + +static const char* create_proxy_config_table = + "create table if not exists " + "proxy_config(vid int NOT NULL default -1, vip varchar(100) NOT NULL default '', " + "vport int NOT NULL default 0, tenant_name varchar(128) collate nocase NOT NULL default '', " + "cluster_name varchar(260) collate nocase NOT NULL default '', " + "name varchar(130) collate nocase NOT NULL, value varchar(4100) NOT NULL, info varchar(1024), " + "range varchar(64), need_reboot bool, visible_level varchar(20), config_level varchar(20) NOT NULL, " + "primary key(vid, vip, vport, tenant_name, cluster_name, name))"; ObConfigProcessor &get_global_config_processor() { @@ -89,8 +104,7 @@ ObConfigProcessor &get_global_config_processor() return g_config_processor; } -ObFnParams::ObFnParams() : config_type_(OBPROXY_CONFIG_INVALID), - stmt_type_(OBPROXY_T_INVALID), +ObFnParams::ObFnParams() : stmt_type_(OBPROXY_T_INVALID), table_name_(), fields_(NULL) {} @@ -110,14 +124,38 @@ ObConfigProcessor::~ObConfigProcessor() int ObConfigProcessor::init() { int ret = OB_SUCCESS; + const char *dir = NULL; if (OB_FAIL(table_handler_map_.create(32, ObModIds::OB_HASH_BUCKET))) { LOG_WARN("create hash map failed", K(ret)); - } else if (SQLITE_OK != sqlite3_open_v2( - sqlite3_db_name, &proxy_config_db_, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL)) { + } else if (OB_ISNULL(dir = get_global_layout().get_etc_dir())) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("sqlite3 open failed", K(ret), "err_msg", sqlite3_errmsg(proxy_config_db_)); + LOG_WARN("get etc dir failed", K(ret)); + } else { + char *path = NULL; + ObFixedArenaAllocator allocator; + if (OB_FAIL(ObLayout::merge_file_path(dir, sqlite3_db_name, allocator, path))) { + LOG_WARN("fail to merge file path", K(sqlite3_db_name), K(ret)); + } else if (OB_ISNULL(path)) { + ret = OB_ERR_UNEXPECTED; + } else if (SQLITE_OK != sqlite3_open_v2( + path, &proxy_config_db_, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("sqlite3 open failed", K(ret), "path", path, "err_msg", sqlite3_errmsg(proxy_config_db_)); + } + } + + if (OB_FAIL(ret)) { + // do nothing } else if (OB_FAIL(check_and_create_table())) { LOG_WARN("check create table failed", K(ret)); + } else { + get_global_proxy_config().proxy_config_db_ = proxy_config_db_; + } + + if (OB_FAIL(ret)) { + // do nothing + } else if (OB_FAIL(get_global_proxy_config().dump_config_to_sqlite())) { + LOG_WARN("dump config to sqlite3 failed", K(ret)); } else { // TODO: Compatibility Check if (OB_FAIL(get_global_white_list_table_processor().init())) { @@ -126,22 +164,15 @@ int ObConfigProcessor::init() LOG_WARN("resource unit table processor init failed", K(ret)); } else if (OB_FAIL(get_global_ssl_config_table_processor().init())) { LOG_WARN("ssl config table processor init failed", K(ret)); + } else if (OB_FAIL(get_global_proxy_config_table_processor().init())) { + LOG_WARN("proxy config table processor init failed", K(ret)); } else if (OB_FAIL(init_config_from_disk())) { LOG_WARN("init config from disk failed", K(ret)); + } else { + get_global_proxy_config_table_processor().set_need_sync_to_file(true); } } - // Do compatibility processing, currently it is related to ssl, - // if the -o startup parameter specifies that synchronization is required here - if (OB_SUCC(ret)) { - if (OB_FAIL(store_cloud_config(ssl_config_table_name, "*", "*", "enable_client_ssl", - get_global_proxy_config().enable_client_ssl.str()))) { - LOG_WARN("store client ssl failed", K(ret)); - } else if (OB_FAIL(store_cloud_config(ssl_config_table_name, "*", "*", "enable_server_ssl", - get_global_proxy_config().enable_server_ssl.str()))) { - LOG_WARN("store server ssl failed", K(ret)); - } - } return ret; } @@ -154,21 +185,26 @@ int ObConfigProcessor::init_callback(void *data, int argc, char **argv, char **c } else { ObConfigHandler *handler = reinterpret_cast(data); ObCloudFnParams params; - params.config_type_ = OBPROXY_CONFIG_CLOUD; params.stmt_type_ = OBPROXY_T_REPLACE; SqlFieldResult field_result; for (int64_t i = 0; OB_SUCC(ret) && i < argc; i++) { if (NULL == argv[i]) { continue; } else { - SqlField sql_field; - sql_field.column_name_.set_string(column_name[i], static_cast(strlen(column_name[i]))); - sql_field.value_type_ = TOKEN_STR_VAL; - sql_field.column_value_.set_value(static_cast(strlen(argv[i])), argv[i]); - if (OB_FAIL(field_result.fields_.push_back(sql_field))) { - LOG_WARN("push back failed", K(ret)); + SqlField *sql_field = NULL; + if (OB_FAIL(SqlField::alloc_sql_field(sql_field))) { + LOG_WARN("fail to alloc sql field", K(ret)); } else { - field_result.field_num_++; + sql_field->column_name_.set_value(static_cast(strlen(column_name[i])), column_name[i]); + sql_field->value_type_ = TOKEN_STR_VAL; + sql_field->column_value_.set_value(static_cast(strlen(argv[i])), argv[i]); + if (OB_FAIL(field_result.fields_.push_back(sql_field))) { + sql_field->reset(); + sql_field = NULL; + LOG_WARN("push back failed", K(ret)); + } else { + field_result.field_num_++; + } } } } @@ -178,11 +214,11 @@ int ObConfigProcessor::init_callback(void *data, int argc, char **argv, char **c const char* cluster_name_str = "cluster_name"; const char* tenant_name_str = "tenant_name"; for (int64_t i = 0; i < field_result.field_num_; i++) { - SqlField &field = field_result.fields_.at(i); - if (field.column_name_.string_ == cluster_name_str) { - params.cluster_name_ = field.column_value_.config_string_; - } else if (field.column_name_.string_ == tenant_name_str) { - params.tenant_name_ = field.column_value_.config_string_; + SqlField* field = field_result.fields_.at(i); + if (field->column_name_.config_string_ == cluster_name_str) { + params.cluster_name_ = field->column_value_.config_string_; + } else if (field->column_name_.config_string_ == tenant_name_str) { + params.tenant_name_ = field->column_value_.config_string_; } } @@ -192,7 +228,7 @@ int ObConfigProcessor::init_callback(void *data, int argc, char **argv, char **c LOG_WARN("execute fn failed", K(ret)); } - if (OB_FAIL(handler->commit_func_(is_success))) { + if (OB_FAIL(handler->commit_func_(¶ms, is_success))) { LOG_WARN("commit func failed", K(ret), K(is_success)); } } @@ -246,7 +282,7 @@ int ObConfigProcessor::execute(ObString &sql, const ObProxyBasicStmtType stmt_ty ObProxyParser obproxy_parser(allocator, NORMAL_PARSE_MODE); if (OB_FAIL(obproxy_parser.obparse(parse_sql, parse_result))) { LOG_WARN("fail to parse sql", K(sql), K(ret)); - } else if (OB_FAIL(handle_dml_stmt(sql, parse_result))) { + } else if (OB_FAIL(handle_dml_stmt(sql, parse_result, allocator))) { LOG_WARN("handle stmt failed", K(ret), K(sql)); } } @@ -270,6 +306,9 @@ int ObConfigProcessor::check_and_create_table() } else if (SQLITE_OK != sqlite3_exec(proxy_config_db_, create_ssl_config_table, NULL, 0, &err_msg)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("exec create ssl config table sql failed", K(ret), "err_msg", err_msg); + } else if (SQLITE_OK != sqlite3_exec(proxy_config_db_, create_proxy_config_table, NULL, 0, &err_msg)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("exec create proxy config table sql failed", K(ret), "err_msg", err_msg); } if (NULL != err_msg) { @@ -279,163 +318,7 @@ int ObConfigProcessor::check_and_create_table() return ret; } -int ObConfigProcessor::resolve_insert(const ParseNode* node, ResolveContext &ctx) -{ - int ret = OB_SUCCESS; - if (OB_ISNULL(node) || T_INSERT != node->type_) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("node is null or wrong type unexpected", K(ret)); - } else { - if (node->children_[1] != NULL) { - if (node->children_[1]->type_ == T_INSERT) { - ctx.stmt_type_ = OBPROXY_T_INSERT; - } else if (node->children_[1]->type_ == T_REPLACE) { - ctx.stmt_type_ = OBPROXY_T_REPLACE; - } - } - - if (node->children_[0] != NULL && node->children_[0]->type_ == T_SINGLE_TABLE_INSERT) { - ParseNode* tmp_node = node->children_[0]; - if (tmp_node->children_[0] != NULL && tmp_node->children_[0]->type_ == T_INSERT_INTO_CLAUSE) { - ParseNode* tmp_node1 = tmp_node->children_[0]; - if (tmp_node1->children_[0] != NULL && tmp_node1->children_[0]->type_ == T_ORG) { - ParseNode* tmp_node2 = tmp_node1->children_[0]; - if (tmp_node2->children_[0] != NULL && tmp_node2->children_[0]->type_ == T_RELATION_FACTOR) { - ParseNode* tmp_node3 = tmp_node2->children_[0]; - ctx.table_name_.assign_ptr(tmp_node3->str_value_, static_cast(tmp_node3->str_len_)); - if (OB_FAIL(table_handler_map_.get_refactored(ctx.table_name_, ctx.handler_))) { - LOG_DEBUG("fail to get handler by table name", K(ret), K(ctx.table_name_)); - ret = OB_SUCCESS; - } else { - ctx.config_type_ = ctx.handler_.config_type_; - } - } - } - - if (!ctx.table_name_.empty() && tmp_node1->children_[1] != NULL && tmp_node1->children_[1]->type_ == T_COLUMN_LIST) { - ParseNode *tmp_node2 = tmp_node1->children_[1]; - for (int64_t i = 0; OB_SUCC(ret) && i < tmp_node2->num_child_; i++) { - if (NULL != tmp_node2->children_[i]) { - ObString column_name; - column_name.assign_ptr(tmp_node2->children_[i]->str_value_, static_cast(tmp_node2->children_[i]->str_len_)); - if (OB_FAIL(ctx.column_name_array_.push_back(column_name))) { - LOG_WARN("column name push back failed", K(ret), K(column_name)); - } - } - } - } - } - - if (!ctx.table_name_.empty() && tmp_node->children_[1] != NULL && tmp_node->children_[1]->type_ == T_VALUE_LIST) { - ParseNode* tmp_node1 = tmp_node->children_[1]; - if (tmp_node1->children_[0] != NULL && tmp_node1->children_[0]->type_ == T_VALUE_VECTOR) { - ParseNode* tmp_node2 = tmp_node1->children_[0]; - for (int64_t i = 0; OB_SUCC(ret) && ctx.column_name_array_.count() == tmp_node2->num_child_ && i < tmp_node2->num_child_; i++) { - if (tmp_node2->children_[i] != NULL) { - if (tmp_node2->children_[i]->type_ == T_INT) { - SqlField field; - field.column_name_.set(ctx.column_name_array_.at(i)); - field.value_type_ = TOKEN_INT_VAL; - field.column_int_value_ = tmp_node2->children_[i]->value_; - ctx.sql_field_.fields_.push_back(field); - ctx.sql_field_.field_num_++; - } else if (tmp_node2->children_[i]->type_ == T_VARCHAR) { - SqlField field; - field.column_name_.set(ctx.column_name_array_.at(i)); - field.value_type_ = TOKEN_STR_VAL; - ObString value; - if (tmp_node2->children_[i]->str_len_ - 2 <= 0) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected len", K(ret)); - } else { - value.assign_ptr(tmp_node2->children_[i]->str_value_ + 1, static_cast(tmp_node2->children_[i]->str_len_ - 2)); - field.column_value_.set_value(value); - ctx.sql_field_.fields_.push_back(field); - ctx.sql_field_.field_num_++; - } - } - } - } - } - } - } - } - - return ret; -} - -int ObConfigProcessor::resolve_delete(const ParseNode* node, ResolveContext &ctx) -{ - int ret = OB_SUCCESS; - if (OB_ISNULL(node) || T_DELETE != node->type_) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("node is null or wrong type", K(ret)); - } else { - ctx.stmt_type_ = OBPROXY_T_DELETE; - if (node->children_[0] != NULL && node->children_[0]->type_ == T_DELETE_TABLE_NODE) { - ParseNode *tmp_node = node->children_[0]; - if (tmp_node->children_[1] != NULL && tmp_node->children_[1]->type_ == T_TABLE_REFERENCES) { - ParseNode *tmp_node1 = tmp_node->children_[1]; - if (tmp_node1->children_[0] != NULL && tmp_node1->children_[0]->type_ == T_ORG) { - ParseNode *tmp_node2 = tmp_node1->children_[0]; - if (tmp_node2->children_[0] != NULL && tmp_node2->children_[0]->type_ == T_RELATION_FACTOR) { - ctx.table_name_.assign_ptr(tmp_node2->children_[0]->str_value_, static_cast(tmp_node2->children_[0]->str_len_)); - if (OB_FAIL(table_handler_map_.get_refactored(ctx.table_name_, ctx.handler_))) { - LOG_DEBUG("fail to get handler by table name", K(ret), K(ctx.table_name_)); - ret = OB_SUCCESS; - } else { - ctx.config_type_ = ctx.handler_.config_type_; - } - } - } - } - } - - if (!ctx.table_name_.empty() && node->children_[1] != NULL && node->children_[1]->type_ == T_WHERE_CLAUSE) { - ParseNode* tmp_node = node->children_[1]; - if (tmp_node->children_[0] != NULL && tmp_node->children_[0]->type_ == T_OP_AND) { - ParseNode* tmp_node1 = tmp_node->children_[0]; - for (int64_t i = 0; OB_SUCC(ret) && i < tmp_node1->num_child_; i++) { - if (tmp_node1->children_[i] != NULL && tmp_node1->children_[i]->type_ == T_OP_EQ) { - ParseNode* tmp_node2 = tmp_node1->children_[i]; - SqlField field; - if (tmp_node2->children_[0] != NULL && tmp_node2->children_[0]->type_ == T_COLUMN_REF) { - ObString column_name; - column_name.assign_ptr(tmp_node2->children_[0]->str_value_, static_cast(tmp_node2->children_[0]->str_len_)); - field.column_name_.set(column_name); - LOG_DEBUG("parse column name", K(column_name), K(i)); - } - - if (tmp_node2->children_[1] != NULL) { - if (tmp_node2->children_[1]->type_ == T_INT) { - field.value_type_ = TOKEN_INT_VAL; - field.column_int_value_ = tmp_node2->children_[1]->value_; - ctx.sql_field_.fields_.push_back(field); - ctx.sql_field_.field_num_++; - } else if (tmp_node2->children_[1]->type_ == T_VARCHAR) { - if (tmp_node2->children_[1]->str_len_ - 2 <= 0) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected len", K(ret)); - } else { - ObString value; - value.assign_ptr(tmp_node2->children_[1]->str_value_ + 1, static_cast(tmp_node2->children_[1]->str_len_ - 2)); - field.value_type_ = TOKEN_STR_VAL; - field.column_value_.set_value(value); - ctx.sql_field_.fields_.push_back(field); - ctx.sql_field_.field_num_++; - LOG_DEBUG("parse column value", K(value), K(i)); - } - } - } - } - } - } - } - } - return ret; -} - -int ObConfigProcessor::handle_dml_stmt(ObString &sql, ParseResult& parse_result) +int ObConfigProcessor::handle_dml_stmt(ObString &sql, ParseResult& parse_result, ObArenaAllocator&allocator) { int ret = OB_SUCCESS; if (OB_UNLIKELY(IS_DEBUG_ENABLED())) { @@ -458,23 +341,38 @@ int ObConfigProcessor::handle_dml_stmt(ObString &sql, ParseResult& parse_result) ret = OB_ERR_UNEXPECTED; LOG_DEBUG("unexpected null child", K(ret)); } else { - // At present, our grammar parsing is relatively fixed. There can only be two equal conditions - // after the delete statement where, otherwise an error will be reported - // The new requirement is changed to the implementation of ob_proxy_stmt - ResolveContext ctx; + ObProxyDMLStmt *stmt = NULL; + ObProxyInsertStmt *insert_stmt = NULL; + ObProxyDeleteStmt *delete_stmt = NULL; switch(node->type_) { case T_INSERT: { - if (OB_FAIL(resolve_insert(node, ctx))) { - LOG_WARN("resove insert failed", K(ret)); + if (OB_ISNULL(insert_stmt = op_alloc_args(ObProxyInsertStmt, allocator))) { + LOG_WARN("alloc insert stmt failed", K(ret)); + } else if (OB_FAIL(insert_stmt->init())) { + LOG_WARN("insert stmt init failed", K(ret)); + } else if (OB_FAIL(insert_stmt->handle_parse_result(parse_result))) { + LOG_WARN("insert stmt handle parse result failed", K(ret)); + } else if (insert_stmt->has_unsupport_expr_type()) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("insert stmt has unsupport expr type", K(ret)); } + stmt = insert_stmt; break; } case T_DELETE: { - if (OB_FAIL(resolve_delete(node, ctx))) { - LOG_WARN("resolve delete failed", K(ret)); + if (OB_ISNULL(delete_stmt = op_alloc_args(ObProxyDeleteStmt, allocator))) { + LOG_WARN("alloc delete stmt failed", K(ret)); + } else if (OB_FAIL(delete_stmt->init())) { + LOG_WARN("delete stmt init failed", K(ret)); + } else if (OB_FAIL(delete_stmt->handle_parse_result(parse_result))) { + LOG_WARN("delete stmt handle parse result failed", K(ret)); + } else if (delete_stmt->has_unsupport_expr_type()) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("insert stmt has unsupport expr type", K(ret)); } + stmt = delete_stmt; break; } default: @@ -486,23 +384,31 @@ int ObConfigProcessor::handle_dml_stmt(ObString &sql, ParseResult& parse_result) bool is_success = true; bool is_execute = false; int tmp_ret = OB_SUCCESS; - if (OB_SUCC(ret) && OBPROXY_CONFIG_CLOUD == ctx.config_type_ && !ctx.table_name_.empty()) { - params.config_type_ = ctx.config_type_; - params.stmt_type_ = ctx.stmt_type_; - params.table_name_ = ctx.table_name_; - params.fields_ = &ctx.sql_field_; + ObConfigHandler handler; + if (OB_SUCC(ret)) { + params.stmt_type_ = stmt->get_stmt_type(); + params.table_name_ = stmt->get_table_name(); + params.fields_ = &(stmt->get_dml_field_result()); const char* cluster_name_str = "cluster_name"; const char* tenant_name_str = "tenant_name"; - for (int64_t i = 0; i < ctx.sql_field_.field_num_; i++) { - SqlField &field = ctx.sql_field_.fields_.at(i); - if (field.column_name_.string_ == cluster_name_str) { - params.cluster_name_ = field.column_value_.config_string_; - } else if (field.column_name_.string_ == tenant_name_str) { - params.tenant_name_ = field.column_value_.config_string_; + for (int64_t i = 0; i < params.fields_->field_num_; i++) { + SqlField* field = params.fields_->fields_.at(i); + if (field->column_name_.config_string_ == cluster_name_str) { + params.cluster_name_ = field->column_value_.config_string_; + } else if (field->column_name_.config_string_ == tenant_name_str) { + params.tenant_name_ = field->column_value_.config_string_; } } - - if (OB_FAIL(ctx.handler_.execute_func_(¶ms))) { + //table name is UPPER CASE in stmt, need convert to lower case as origin + //depends on the assumption that the table name in 'table_handler_map_' is lower case + string_to_lower_case(params.table_name_.ptr(), params.table_name_.length()); + if (OB_FAIL(table_handler_map_.get_refactored(params.table_name_, handler))) { + if (params.table_name_ == all_table_version_table_name) { + ret = OB_SUCCESS; + } else { + LOG_WARN("get table handler failed", K_(params.table_name), K(ret)); + } + } else if (OB_FAIL(handler.execute_func_(¶ms))) { is_execute = true; LOG_WARN("execute fn failed", K(ret)); } else { @@ -520,12 +426,31 @@ int ObConfigProcessor::handle_dml_stmt(ObString &sql, ParseResult& parse_result) } else { memcpy(sql_buf, sql.ptr(), sql.length()); sql_buf[sql.length()] = '\0'; - if (SQLITE_OK != sqlite3_exec(proxy_config_db_, sql_buf, NULL, 0, &err_msg)) { + if (SQLITE_OK != sqlite3_exec(proxy_config_db_, "begin;", NULL, 0, &err_msg)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("sqlite3 exec failed", K(sql), "err_msg", err_msg); + sqlite3_free(err_msg); + } + + if (OB_SUCC(ret) && SQLITE_OK != sqlite3_exec(proxy_config_db_, sql_buf, NULL, 0, &err_msg)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("sqlite3 exec failed", K(sql), "err_msg", err_msg); sqlite3_free(err_msg); } ob_free(sql_buf); + + if (OB_SUCC(ret) && NULL != handler.before_commit_func_) { + if (OB_FAIL(handler.before_commit_func_(proxy_config_db_))) { + LOG_WARN("before commit func failed", K_(params.table_name), K(ret)); + } + } + + const char *end_sql = OB_SUCCESS == ret ? "commit;" : "rollback;"; + if (SQLITE_OK != sqlite3_exec(proxy_config_db_, end_sql, NULL, 0, &err_msg)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("sqlite3 exec failed", K(sql), "err_msg", err_msg); + sqlite3_free(err_msg); + } } tmp_ret = ret; } @@ -535,11 +460,20 @@ int ObConfigProcessor::handle_dml_stmt(ObString &sql, ParseResult& parse_result) } if (is_execute) { - if (OB_FAIL(ctx.handler_.commit_func_(is_success))) { + if (OB_FAIL(handler.commit_func_(¶ms, is_success))) { LOG_WARN("commit failed", K(ret), K(is_success)); } } ret = (OB_SUCCESS != tmp_ret ? tmp_ret : ret); + + if (NULL != insert_stmt) { + op_free(insert_stmt); + insert_stmt = NULL; + } + if (NULL != delete_stmt) { + op_free(delete_stmt); + delete_stmt = NULL; + } } return ret; @@ -606,7 +540,7 @@ int ObConfigProcessor::handle_select_stmt(ObString& sql, obproxy::ObConfigV2Hand return ret; } -int ObConfigProcessor::register_callback(const common::ObString &table_name, ObConfigHandler&handler) +int ObConfigProcessor::register_callback(const common::ObString &table_name, ObConfigHandler &handler) { int ret = OB_SUCCESS; if (OB_FAIL(table_handler_map_.set_refactored(table_name, handler))) { @@ -622,26 +556,35 @@ bool ObConfigProcessor::is_table_in_service(const ObString &table_name) if (table_name == all_table_version_table_name || table_name == white_list_table_name || table_name == resource_unit_table_name - || table_name == ssl_config_table_name) { + || table_name == ssl_config_table_name + || table_name == proxy_config_table_name) { is_in_service = true; } return is_in_service; } -int ObConfigProcessor::store_cloud_config(const ObString &table_name, - const ObString &cluster_name, - const ObString &tenant_name, - const ObString &name, - const ObString &value) +int ObConfigProcessor::execute(const char* sql, int (*callback)(void*, int, char**, char**), void* handler) +{ + int ret = OB_SUCCESS; + char *err_msg = NULL; + if (SQLITE_OK != sqlite3_exec(proxy_config_db_, sql, callback, handler, &err_msg)) { + ret = OB_ERR_UNEXPECTED; + WARN_ICMD("exec sql failed", K(ret), "err_msg", err_msg); + sqlite3_free(err_msg); + } + return ret; +} + +int ObConfigProcessor::store_global_ssl_config(const ObString &name, const ObString &value) { int ret = OB_SUCCESS; - if (OB_UNLIKELY(cluster_name.empty() || tenant_name.empty() || name.empty() || value.empty())) { + if (OB_UNLIKELY(name.empty() || value.empty())) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid argument", K(cluster_name), K(tenant_name), K(name), K(value)); + LOG_WARN("invalid argument", K(name), K(value)); } else { - const char *sql = "replace into %.*s(cluster_name, tenant_name, name, value) values('%.*s', '%.*s', '%.*s', '%.*s')"; - int64_t buf_len = cluster_name.length() + tenant_name.length() + name.length() + value.length() + strlen(sql); + const char *sql = "replace into ssl_config(cluster_name, tenant_name, name, value) values('*', '*', '%.*s', '%.*s')"; + int64_t buf_len = name.length() + value.length() + strlen(sql); char *sql_buf = (char*)ob_malloc(buf_len + 1, ObModIds::OB_PROXY_CONFIG_TABLE); if (OB_ISNULL(sql_buf)) { ret = OB_ALLOCATE_MEMORY_FAILED; @@ -649,9 +592,7 @@ int ObConfigProcessor::store_cloud_config(const ObString &table_name, } else { ObString sql_string; int64_t len = 0; - len = static_cast(snprintf(sql_buf, buf_len, sql, table_name.length(), table_name.ptr(), - cluster_name.length(), cluster_name.ptr(), - tenant_name.length(), tenant_name.ptr(), + len = static_cast(snprintf(sql_buf, buf_len, sql, name.length(), name.ptr(), value.length(), value.ptr())); sql_string.assign_ptr(sql_buf, static_cast(len)); @@ -671,6 +612,162 @@ int ObConfigProcessor::store_cloud_config(const ObString &table_name, return ret; } +int ObConfigProcessor::store_proxy_config_with_level(int64_t vid, const ObString &vip, int64_t vport, + const ObString &tenant_name, const ObString &cluster_name, + const ObString &name, const ObString& value, const ObString &level) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(name.empty() || level.empty())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(name), K(level)); + } else { + const char *sql = + "replace into proxy_config(vid, vip, vport, cluster_name, tenant_name, name, value, config_level) " + "values(%ld, '%.*s', %ld, '%.*s', '%.*s', '%.*s', '%.*s', '%.*s')"; + char vid_buf[64]; + char vport_buf[64]; + int32_t vid_len = snprintf(vid_buf, sizeof(vid_buf), "%ld", vid); + int32_t vport_len = snprintf(vport_buf, sizeof(vport_buf), "%ld", vport); + int64_t buf_len = vid_len + vport_len + vip.length() + tenant_name.length() + cluster_name.length() + name.length() + value.length() + level.length() + strlen(sql); + char *sql_buf = (char*)ob_malloc(buf_len + 1, ObModIds::OB_PROXY_CONFIG_TABLE); + if (OB_ISNULL(sql_buf)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("allocate memory failed", K(ret), K(buf_len)); + } else { + ObString sql_string; + int32_t len = 0; + get_global_proxy_config_table_processor().set_need_sync_to_file(false); + len = static_cast(snprintf(sql_buf, buf_len, sql, + vid, + vip.length(), vip.ptr(), + vport, + cluster_name.length(), cluster_name.ptr(), + tenant_name.length(), tenant_name.ptr(), + name.length(), name.ptr(), + value.length(), value.ptr(), + level.length(), level.ptr())); + sql_string.assign_ptr(sql_buf, len); + LOG_DEBUG("execute sql", K(sql_string)); + if (OB_UNLIKELY(len <= 0)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to fill sql", K(len), K(ret)); + } else if (OB_FAIL(execute(sql_string, OBPROXY_T_REPLACE, NULL))) { + LOG_WARN("execute sql failed", K(ret)); + } + get_global_proxy_config_table_processor().set_need_sync_to_file(true); + } + + if (OB_NOT_NULL(sql_buf)) { + ob_free(sql_buf); + } + } + + return ret; +} + +int ObConfigProcessor::store_global_proxy_config(const ObString &name, const ObString &value) +{ + int ret = OB_SUCCESS; + if (OB_FAIL(store_proxy_config_with_level(-1, "", 0, "", "", name, value, "LEVEL_GLOBAL"))) { + LOG_WARN("store_proxy_config_with_level failed", K(ret)); + } + return ret; +} + +int ObConfigProcessor::get_proxy_config_with_level(const ObVipAddr &addr, const common::ObString &cluster_name, + const common::ObString &tenant_name, const common::ObString& name, + common::ObConfigItem &ret_item, const ObString level, bool &found) +{ + int ret = OB_SUCCESS; + ObProxyConfigItem proxy_item; + if (OB_FAIL(get_global_proxy_config_table_processor().get_config_item( + addr, cluster_name, tenant_name, name, proxy_item))) { + if (OB_HASH_NOT_EXIST != ret) { + LOG_WARN("get config item failed", K(addr), K(cluster_name), K(tenant_name), K(name), K(ret)); + } else { + ret = OB_SUCCESS; + } + } else if (0 != strcasecmp(proxy_item.config_level_.ptr(), level.ptr())) { + ret = OB_SUCCESS; + LOG_TRACE("vip config level not match", K(proxy_item), K(level)); + } else { + found = true; + ret_item = proxy_item.config_item_; + } + + return ret; +} + +int ObConfigProcessor::get_proxy_config(const ObVipAddr &addr, const ObString &cluster_name, + const ObString &tenant_name, const ObString& name, + ObConfigItem &ret_item) +{ + int ret = OB_SUCCESS; + ObVipAddr tmp_addr = addr; + ObString tmp_cluster_name = cluster_name; + ObString tmp_tenant_name = tenant_name; + bool found = false; + if (OB_FAIL(get_proxy_config_with_level(tmp_addr, tmp_cluster_name, tmp_tenant_name, name, ret_item, "LEVEL_VIP", found))) { + LOG_WARN("get_proxy_config_with_level failed", K(ret)); + } + + if (OB_SUCC(ret) && !found) { + tmp_addr.reset(); + if (OB_FAIL(get_proxy_config_with_level(tmp_addr, tmp_cluster_name, tmp_tenant_name, name, ret_item, "LEVEL_TENANT", found))) { + LOG_WARN("get_proxy_config_with_level failed", K(ret)); + } + } + + if (OB_SUCC(ret) && !found) { + tmp_tenant_name.reset(); + if (OB_FAIL(get_proxy_config_with_level(tmp_addr, tmp_cluster_name, tmp_tenant_name, name, ret_item, "LEVEL_CLUSTER", found))) { + LOG_WARN("get_proxy_config_with_level failed", K(ret)); + } + } + + if (OB_SUCC(ret) && !found) { + if (OB_FAIL(get_global_proxy_config().get_config_item(name, ret_item))) { + LOG_WARN("get global config item failed", K(ret)); + } + } + + LOG_DEBUG("get proxy config", K(ret_item), K(found), K(ret)); + + return ret; +} + +int ObConfigProcessor::get_proxy_config_bool_item(const ObVipAddr &addr, const ObString &cluster_name, + const ObString &tenant_name, const ObString& name, + ObConfigBoolItem &ret_item) +{ + int ret = OB_SUCCESS; + ObConfigItem item; + if (OB_FAIL(get_proxy_config(addr, cluster_name, tenant_name, name, item))) { + LOG_WARN("get proxy config failed", K(addr), K(cluster_name), K(tenant_name), K(name), K(ret)); + } else { + ret_item.set(item.str()); + LOG_DEBUG("get bool item succ", K(ret_item)); + } + + return ret; +} + +int ObConfigProcessor::get_proxy_config_int_item(const ObVipAddr &addr, const ObString &cluster_name, + const ObString &tenant_name, const ObString& name, + ObConfigIntItem &ret_item) +{ + int ret = OB_SUCCESS; + ObConfigItem item; + if (OB_FAIL(get_proxy_config(addr, cluster_name, tenant_name, name, item))) { + LOG_WARN("get proxy config failed", K(addr), K(cluster_name), K(tenant_name), K(name), K(ret)); + } else { + ret_item.set(item.str()); + LOG_DEBUG("get int item succ", K(ret_item)); + } + + return ret; +} + } // end of obutils } // end of obproxy } // end of oceanbase diff --git a/src/obproxy/obutils/ob_config_processor.h b/src/obproxy/obutils/ob_config_processor.h index 5e425681346a5250671f00d6da6c7d132f503b1c..156789a806dcf95f381a9731558a49868df7a54b 100644 --- a/src/obproxy/obutils/ob_config_processor.h +++ b/src/obproxy/obutils/ob_config_processor.h @@ -50,21 +50,18 @@ class ObConfigV2Handler; namespace obutils { -enum ObConfigType -{ - OBPROXY_CONFIG_INVALID = -1, - OBPROXY_CONFIG_CLOUD, - OBPROXY_CONFIG_MAX -}; +struct ObVipAddr; typedef int (*config_processor_execute) (void *); -typedef int (*config_processor_commit) (bool is_success); +typedef int (*config_processor_commit) (void*, bool is_success); +typedef int (*config_processor_before_commit) (void *); struct ObConfigHandler { + ObConfigHandler() : execute_func_(NULL), commit_func_(NULL), before_commit_func_(NULL) {} config_processor_execute execute_func_; config_processor_commit commit_func_; - ObConfigType config_type_; + config_processor_before_commit before_commit_func_; }; typedef common::hash::ObHashMap, ObConfigHandler> ConfigHandlerHashMap; @@ -76,7 +73,6 @@ public: ~ObFnParams(); public: - ObConfigType config_type_; ObProxyBasicStmtType stmt_type_; common::ObString table_name_; SqlFieldResult *fields_; @@ -93,21 +89,6 @@ public: common::ObString tenant_name_; }; -struct ResolveContext -{ - ResolveContext() : stmt_type_(OBPROXY_T_INVALID), table_name_(), - config_type_(OBPROXY_CONFIG_INVALID), column_name_array_(), - sql_field_(), handler_() - {} - - ObProxyBasicStmtType stmt_type_; - common::ObString table_name_; - ObConfigType config_type_; - common::ObSEArray column_name_array_; - obutils::SqlFieldResult sql_field_; - ObConfigHandler handler_; -}; - class ObConfigProcessor { public: @@ -118,20 +99,34 @@ public: int execute(common::ObString &sql, const ObProxyBasicStmtType stmt_type, obproxy::ObConfigV2Handler *handler); int register_callback(const common::ObString &table_name, ObConfigHandler&handler); bool is_table_in_service(const common::ObString &table_name); - int store_cloud_config(const common::ObString &table_name, - const common::ObString &cluster_name, - const common::ObString& tenant_name, - const common::ObString& name, - const common::ObString &value); + int store_global_ssl_config(const common::ObString& name, const common::ObString &value); + int store_global_proxy_config(const common::ObString &name, const common::ObString &value); + int store_vip_tenant_cluster_config(int64_t vid, const ObString &vip, int64_t vport, + const ObString &name, const ObString &value); + int store_proxy_config_with_level(int64_t vid, const ObString &vip, int64_t vport, + const ObString &cluster_name, const ObString &tenant_name, + const ObString &name, const ObString &value, const ObString &level); + + int get_proxy_config(const ObVipAddr &addr, const common::ObString &cluster_name, + const common::ObString &tenant_name, const common::ObString& name, + common::ObConfigItem &ret_item); + int get_proxy_config_bool_item(const ObVipAddr &addr, const common::ObString &cluster_name, + const common::ObString &tenant_name, const common::ObString& name, + common::ObConfigBoolItem &ret_item); + int get_proxy_config_int_item(const ObVipAddr &addr, const common::ObString &cluster_name, + const common::ObString &tenant_name, const common::ObString& name, + common::ObConfigIntItem &ret_item); + int get_proxy_config_with_level(const ObVipAddr &addr, const common::ObString &cluster_name, + const common::ObString &tenant_name, const common::ObString& name, + common::ObConfigItem &ret_item, const ObString level, bool &found); + int execute(const char* sql, int (*callback)(void*, int, char**, char**), void* handler); private: int init_config_from_disk(); int check_and_create_table(); - int resolve_insert(const ParseNode* node, ResolveContext &ctx); - int resolve_delete(const ParseNode* node, ResolveContext &ctx); - int handle_dml_stmt(common::ObString &sql, ParseResult& parse_result); + int handle_dml_stmt(common::ObString &sql, ParseResult& parse_result, ObArenaAllocator&allocator); int handle_select_stmt(common::ObString &sql, obproxy::ObConfigV2Handler *v2_handler); - + static int init_callback(void *data, int argc, char **argv, char **column_name); static int sqlite3_callback(void *data, int argc, char **argv, char **column_name); private: diff --git a/src/obproxy/obutils/ob_config_server_processor.cpp b/src/obproxy/obutils/ob_config_server_processor.cpp index f35d0a9b51a7dcae3fdc884aa09d04115045a48a..38d158f858e450fee2699b0efd5b3fbff9cf0920 100644 --- a/src/obproxy/obutils/ob_config_server_processor.cpp +++ b/src/obproxy/obutils/ob_config_server_processor.cpp @@ -1868,7 +1868,7 @@ int ObConfigServerProcessor::parse_json_config_info(const ObString &json, const bool is_metadb_changed = false; if (OB_ISNULL(json_info = op_alloc(ObProxyJsonConfigInfo))) { ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_ERROR("fail to alloc mem fot json config info", K(ret)); + LOG_ERROR("fail to alloc mem for json config info", K(ret)); } else if (OB_FAIL(json_info->parse(root))) { LOG_WARN("fail to parse json info", K(ret)); } else if (!json_info->is_valid()) { diff --git a/src/obproxy/obutils/ob_congestion_entry.cpp b/src/obproxy/obutils/ob_congestion_entry.cpp index 410e795928c92cc2eff0a7c0bee62a665af52edf..ec3cbf7b610ae44b7b201a186f36f0e6445ce613 100644 --- a/src/obproxy/obutils/ob_congestion_entry.cpp +++ b/src/obproxy/obutils/ob_congestion_entry.cpp @@ -12,10 +12,12 @@ #define USING_LOG_PREFIX PROXY #include "obutils/ob_congestion_entry.h" +#include "obutils/ob_resource_pool_processor.h" using namespace oceanbase::common; using namespace oceanbase::obproxy::event; using namespace oceanbase::obproxy::net; +using namespace oceanbase::obproxy::obutils; namespace oceanbase { @@ -88,6 +90,8 @@ ObCongestionEntry::ObCongestionEntry(const ObIpEndpoint &ip) : server_state_(ACTIVE), entry_state_(ENTRY_AVAIL), control_config_(NULL),zone_state_(NULL), last_dead_congested_(0), dead_congested_(0), last_alive_congested_(0),alive_congested_(0), + last_detect_congested_(0), detect_congested_(0), + last_client_feedback_congested_(0), stat_client_feedback_failures_(0), client_feedback_congested_(0), stat_conn_failures_(0), stat_alive_failures_(0), last_revalidate_time_us_(0), cr_version_(-1) { @@ -266,6 +270,18 @@ int64_t ObCongestionEntry::to_string(char *buf, const int64_t buf_len) const databuff_printf(buf, buf_len, pos, "last_dead_congested=%s,", str_time); } + J_KV(K_(detect_congested)); + J_COMMA(); + if (detect_congested_) { + struct tm time; + time_t seconds = last_detect_congested_; + localtime_r(&seconds, &time); + snprintf(str_time, sizeof(str_time), "%04d/%02d/%02d %02d:%02d:%02d", + time.tm_year + 1900, time.tm_mon + 1, time.tm_mday, + time.tm_hour, time.tm_min, time.tm_sec); + databuff_printf(buf, buf_len, pos, "last_detect_congested=%s,", str_time); + } + J_KV(K_(stat_alive_failures), K_(stat_conn_failures), K_(cr_version)); J_COMMA(); @@ -303,6 +319,12 @@ const char *ObCongestionEntry::get_server_state_name(const ObServerState state) case REPLAY: state_ret = "REPLAY"; break; + case DETECT_ALIVE: + state_ret = "DETECT_ALIVE"; + break; + case DETECT_DEAD: + state_ret = "DETECT_DEAD"; + break; default: break; } @@ -359,7 +381,7 @@ void ObCongestionEntry::set_alive_failed_at(const ObHRTime t) (void)ATOMIC_FAA(&stat_alive_failures_, 1); if (control_config_->alive_failure_threshold_ >= 0) { int64_t time = hrtime_to_sec(t); - LOG_INFO("alive failed at", K(t)); + LOG_INFO("alive failed at", K(t), KPC(this)); MUTEX_TRY_LOCK(lock, fail_hist_lock_, this_ethread()); if (lock.is_locked()) { alive_fail_history_.regist_event(time); @@ -369,7 +391,32 @@ void ObCongestionEntry::set_alive_failed_at(const ObHRTime t) if (new_congested && !ATOMIC_TAS(&alive_congested_, 1)) { last_alive_congested_ = alive_fail_history_.last_event_; // action congested ? - LOG_INFO("set_alive_congested", KPC(this)); + LOG_INFO("set alive congested", KPC(this)); + } + } + } else { + LOG_DEBUG("failure info lost due to lock contention", + KPC(this), K(time)); + } + } +} + +void ObCongestionEntry::set_client_feedback_failed_at(const ObHRTime t) +{ + (void)ATOMIC_FAA(&stat_client_feedback_failures_, 1); + if (control_config_->alive_failure_threshold_ >= 0) { + int64_t time = hrtime_to_sec(t); + LOG_INFO("client feedback failed at", K(t)); + MUTEX_TRY_LOCK(lock, fail_hist_lock_, this_ethread()); + if (lock.is_locked()) { + client_feedback_fail_history_.regist_event(time); + if (!client_feedback_congested_) { + bool new_congested = check_client_feedback_congested(); + // TODO: This used to signal via SNMP + if (new_congested && !ATOMIC_TAS(&client_feedback_congested_, 1)) { + last_client_feedback_congested_ = client_feedback_fail_history_.last_event_; + // action congested ? + LOG_INFO("set_client_feedback_congested", KPC(this)); } } } else { @@ -414,7 +461,7 @@ void ObCongestionEntry::set_alive_congested() // action congested ? } else { last_alive_congested_ = ObTimeUtility::extract_second(ObTimeUtility::current_time()); - LOG_INFO("set_alive_congested", KPC(this)); + LOG_INFO("set alive congested", KPC(this)); } } @@ -445,6 +492,24 @@ void ObCongestionEntry::set_dead_congested_free() } } +void ObCongestionEntry::set_detect_congested() +{ + if (ATOMIC_TAS(&detect_congested_, 1)) { + // Action congested ? + } else { + last_detect_congested_ = ObTimeUtility::extract_second(ObTimeUtility::current_time()); + LOG_INFO("set detect congested", KPC(this)); + } +} + +void ObCongestionEntry::set_detect_congested_free() +{ + if (ATOMIC_TAS(&detect_congested_, 0)) { + // action not congested ? + LOG_INFO("set detect congested free", KPC(this)); + } +} + } // end of namespace obutils } // end of namespace obproxy diff --git a/src/obproxy/obutils/ob_congestion_entry.h b/src/obproxy/obutils/ob_congestion_entry.h index 10c0350274c5b5da691b7785fb6e1afa24067b53..0c9f04f1a3c4f1a3a47ce434fab1adee4d61b03b 100644 --- a/src/obproxy/obutils/ob_congestion_entry.h +++ b/src/obproxy/obutils/ob_congestion_entry.h @@ -233,7 +233,9 @@ struct ObCongestionEntry : public ObCongestionRefCnt DELETING, DELETED, UPGRADE, - REPLAY + REPLAY, + DETECT_ALIVE, + DETECT_DEAD, }; enum ObEntryState @@ -265,6 +267,7 @@ struct ObCongestionEntry : public ObCongestionRefCnt bool is_dead_congested() const; bool is_force_alive_congested() const; bool is_alive_congested() const; + bool is_detect_congested() const; bool is_congested() const; bool is_zone_merging() const; bool is_zone_upgrading() const; @@ -283,8 +286,11 @@ struct ObCongestionEntry : public ObCongestionRefCnt void set_alive_congested_free(); void set_dead_congested(); void set_dead_congested_free(); + void set_detect_congested(); + void set_detect_congested_free(); void set_dead_failed_at(const ObHRTime t); void set_alive_failed_at(const ObHRTime t); + void set_client_feedback_failed_at(const ObHRTime t); // Connection controls bool alive_need_retry(const ObHRTime t); @@ -295,6 +301,7 @@ struct ObCongestionEntry : public ObCongestionRefCnt void reset_fail_history(); bool check_dead_congested(); bool check_alive_congested(); + bool check_client_feedback_congested(); // ObCongestionEntry and ObCongestionControl config interaction helper functions int validate_config(ObCongestionControlConfig *config); @@ -330,6 +337,14 @@ struct ObCongestionEntry : public ObCongestionRefCnt ObHRTime last_alive_congested_; // unit second volatile int64_t alive_congested_; + ObHRTime last_detect_congested_; + volatile int64_t detect_congested_; + + ObFailHistory client_feedback_fail_history_; + ObHRTime last_client_feedback_congested_; + volatile int64_t stat_client_feedback_failures_; + int64_t client_feedback_congested_; + volatile int64_t stat_conn_failures_; volatile int64_t stat_alive_failures_; int64_t last_revalidate_time_us_; // unit us @@ -369,6 +384,11 @@ inline bool ObCongestionEntry::is_dead_congested() const return (1 == dead_congested_); } +inline bool ObCongestionEntry::is_detect_congested() const +{ + return (1 == detect_congested_); +} + inline bool ObCongestionEntry::is_zone_merging() const { bool bret = false; @@ -392,7 +412,8 @@ inline bool ObCongestionEntry::is_congested() const // watch out the priority below: return (is_dead_congested() || is_force_alive_congested() - || is_alive_congested()); + || is_alive_congested() + || is_detect_congested()); } inline bool ObCongestionEntry::check_dead_congested() @@ -423,12 +444,27 @@ inline bool ObCongestionEntry::check_alive_congested() return bret; } +inline bool ObCongestionEntry::check_client_feedback_congested() +{ + bool bret = false; + if (1 == client_feedback_congested_) { + bret = true; + } else if (control_config_->alive_failure_threshold_ < 0) { + bret = false; + } else { + bret = control_config_->alive_failure_threshold_ <= client_feedback_fail_history_.events_; + } + + return bret; +} + inline void ObCongestionEntry::reset_fail_history() { conn_fail_history_.init(control_config_->fail_window_sec_); dead_congested_ = 0; alive_fail_history_.init(control_config_->fail_window_sec_); alive_congested_ = 0; + client_feedback_fail_history_.init(control_config_->fail_window_sec_); } void ObCongestionEntry::free() diff --git a/src/obproxy/obutils/ob_congestion_manager.cpp b/src/obproxy/obutils/ob_congestion_manager.cpp index ee58fb8fb1b71d851c7a54c2c1f5585317890f45..1be3253b95572cbb503770fb66470113ff6c7b19 100644 --- a/src/obproxy/obutils/ob_congestion_manager.cpp +++ b/src/obproxy/obutils/ob_congestion_manager.cpp @@ -380,6 +380,13 @@ int ObCongestionManager::add_new_server(const net::ObIpEndpoint &ip, case ObCongestionEntry::ACTIVE_CONGESTED: entry->set_dead_free_alive_congested(); break; + case ObCongestionEntry::DETECT_ALIVE: + entry->set_detect_congested_free(); + entry->set_alive_congested_free(); + break; + case ObCongestionEntry::DETECT_DEAD: + entry->set_detect_congested(); + break; case ObCongestionEntry::DELETED: case ObCongestionEntry::DELETING: case ObCongestionEntry::UPGRADE: @@ -599,6 +606,13 @@ int ObCongestionManager::process(const int64_t buck_id, ObCongestRequestParam *p entry = NULL; } break; + case ObCongestionEntry::DETECT_ALIVE: + entry->set_detect_congested_free(); + entry->set_alive_congested_free(); + break; + case ObCongestionEntry::DETECT_DEAD: + entry->set_detect_congested(); + break; case ObCongestionEntry::DELETING: case ObCongestionEntry::UPGRADE: default: @@ -971,6 +985,13 @@ int ObCongestionManager::revalidate_server(const ObIpEndpoint &ip, case ObCongestionEntry::ACTIVE_CONGESTED: entry->set_dead_free_alive_congested(); break; + case ObCongestionEntry::DETECT_ALIVE: + entry->set_detect_congested_free(); + entry->set_alive_congested_free(); + break; + case ObCongestionEntry::DETECT_DEAD: + entry->set_detect_congested(); + break; case ObCongestionEntry::DELETED: entry = remove_entry(hash, ip); if (NULL != entry) { @@ -996,7 +1017,7 @@ int ObCongestionManager::revalidate_server(const ObIpEndpoint &ip, } } else { LOG_DEBUG("failed to lock_bucket, add to todo_list", "server_state", - ObCongestionEntry::get_server_state_name(server_state), K(*entry)); + ObCongestionEntry::get_server_state_name(server_state)); ObCongestRequestParam *param = op_alloc(ObCongestRequestParam); if (OB_ISNULL(param)) { ret = OB_ALLOCATE_MEMORY_FAILED; @@ -1255,6 +1276,27 @@ int init_congestion_map_for_thread() return ret; } +int init_congestion_map_for_one_thread(int64_t index) +{ + int ret = OB_SUCCESS; + ObEThread **ethreads = NULL; + if (OB_ISNULL(ethreads = g_event_processor.event_thread_[ET_CALL])) { + ret = OB_ERR_UNEXPECTED; + PROXY_NET_LOG(ERROR, "fail to get ET_NET thread", K(ret)); + } else if (OB_ISNULL(ethreads[index])) { + ret = OB_ERR_UNEXPECTED; + PROXY_NET_LOG(ERROR, "fail to get ET_NET thread", K(ret)); + } else { + if (OB_ISNULL(ethreads[index]->congestion_map_ = new (std::nothrow) ObCongestionRefHashMap(ObModIds::OB_PROXY_CONGESTION_ENTRY_MAP))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to new ObCongestionRefHashMap", K(index), K(ethreads[index]), K(ret)); + } else if (OB_FAIL(ethreads[index]->congestion_map_->init())) { + LOG_WARN("fail to init cgt_map", K(ret)); + } + } + return ret; +} + int ObCongestionRefHashMap::clean_hash_map() { int ret = OB_SUCCESS; diff --git a/src/obproxy/obutils/ob_congestion_manager.h b/src/obproxy/obutils/ob_congestion_manager.h index dd7dce441bbe2b8ae38e2bc0105e9f860075f6b2..53d4e15144fa10360e3049904c495d3360583c2b 100644 --- a/src/obproxy/obutils/ob_congestion_manager.h +++ b/src/obproxy/obutils/ob_congestion_manager.h @@ -251,6 +251,7 @@ private: }; int init_congestion_map_for_thread(); +int init_congestion_map_for_one_thread(int64_t index); } // end of namespace obutils } // end of namespace obproxy diff --git a/src/obproxy/obutils/ob_hot_upgrade_processor.cpp b/src/obproxy/obutils/ob_hot_upgrade_processor.cpp index 5ddfbc27d9a5ceea2fe0614652cfa779d8b3fb80..bedfce3e10f1aeabd8b3d8a312732603558bed0f 100644 --- a/src/obproxy/obutils/ob_hot_upgrade_processor.cpp +++ b/src/obproxy/obutils/ob_hot_upgrade_processor.cpp @@ -110,7 +110,7 @@ int ObProxyHotUpgrader::get_envp(char **&envp) { static const int64_t OBPROXY_ENVP_MAX_SIZE = 128; int ret = OB_SUCCESS; - int64_t count = 1; // envp's valid items count + int64_t count = 2; // envp's valid items count bool is_obproxy_root_set = false; char *obproxy_root = NULL; if (NULL != (obproxy_root = getenv("OBPROXY_ROOT"))) { @@ -128,7 +128,8 @@ int ObProxyHotUpgrader::get_envp(char **&envp) memset(var, 0, size); envp = reinterpret_cast(var); envp[0] = reinterpret_cast(malloc(OBPROXY_ENVP_MAX_SIZE)); - if (OB_ISNULL(envp[0])) { + envp[1] = reinterpret_cast(malloc(OBPROXY_ENVP_MAX_SIZE)); + if (OB_ISNULL(envp[0]) || OB_ISNULL(envp[1])) { ret = OB_ALLOCATE_MEMORY_FAILED; free(var); var = NULL; @@ -137,16 +138,23 @@ int ObProxyHotUpgrader::get_envp(char **&envp) } else { const ObHotUpgraderInfo &info = get_global_hot_upgrade_info(); int64_t length = snprintf(envp[0], static_cast(OBPROXY_ENVP_MAX_SIZE), - OBPROXY_INHERITED_FD"=%d", info.fd_); + OBPROXY_INHERITED_IPV4_FD"=%d", info.ipv4_fd_); if (OB_UNLIKELY(length <= 0) || OB_UNLIKELY(length >= OBPROXY_ENVP_MAX_SIZE)) { ret = OB_BUF_NOT_ENOUGH; LOG_WARN("buf not enought", K(length), "envp[0]_length", OBPROXY_ENVP_MAX_SIZE, K(envp[0]), K(ret)); + } else { + int64_t length = snprintf(envp[1], static_cast(OBPROXY_ENVP_MAX_SIZE), + OBPROXY_INHERITED_IPV6_FD"=%d", info.ipv6_fd_); + if (OB_UNLIKELY(length <= 0) || OB_UNLIKELY(length >= OBPROXY_ENVP_MAX_SIZE)) { + ret = OB_BUF_NOT_ENOUGH; + LOG_WARN("buf not enought", K(length), "envp[0]_length", OBPROXY_ENVP_MAX_SIZE, K(envp[1]), K(ret)); + } } } //set OBPROXY_ROOT if (OB_SUCC(ret) && is_obproxy_root_set) { - envp[1] = reinterpret_cast(malloc(OBPROXY_ENVP_MAX_SIZE)); - if (OB_ISNULL(envp[1])) { + envp[2] = reinterpret_cast(malloc(OBPROXY_ENVP_MAX_SIZE)); + if (OB_ISNULL(envp[2])) { ret = OB_ALLOCATE_MEMORY_FAILED; free(envp[0]); free(var); @@ -154,11 +162,11 @@ int ObProxyHotUpgrader::get_envp(char **&envp) envp = NULL; LOG_ERROR("fail to malloc", K(ret)); } else { - int64_t length = snprintf(envp[1], static_cast(OBPROXY_ENVP_MAX_SIZE), + int64_t length = snprintf(envp[2], static_cast(OBPROXY_ENVP_MAX_SIZE), "OBPROXY_ROOT=%s", obproxy_root); if (OB_UNLIKELY(length <= 0) || OB_UNLIKELY(length >= OBPROXY_ENVP_MAX_SIZE)) { ret = OB_BUF_NOT_ENOUGH; - LOG_WARN("buf not enought", K(length), "envp[1]_length", OBPROXY_ENVP_MAX_SIZE, K(envp[1]), K(ret)); + LOG_WARN("buf not enought", K(length), "envp[2]_length", OBPROXY_ENVP_MAX_SIZE, K(envp[2]), K(ret)); } } } @@ -1289,6 +1297,8 @@ int ObHotUpgradeProcessor::init_raw_client(ObRawMysqlClient &raw_client, const O char passwd_staged1_buf[ENC_STRING_BUF_LEN] = {0}; // 1B '*' + 40B octal num ObProxyLoginInfo login_info; int64_t pos = 0; + char cluster_name_buf[OB_PROXY_FULL_USER_NAME_MAX_LEN + 1]; + ObString cluster_name; switch (type) { case USER_TYPE_METADB: { @@ -1311,14 +1321,13 @@ int ObHotUpgradeProcessor::init_raw_client(ObRawMysqlClient &raw_client, const O break; } case USER_TYPE_PROXYRO: { - char cluster_name[OB_PROXY_FULL_USER_NAME_MAX_LEN + 1]; - cluster_name[0] = '\0'; - if (OB_FAIL(get_global_config_server_processor().get_default_cluster_name(cluster_name, OB_PROXY_FULL_USER_NAME_MAX_LEN + 1))) { + cluster_name_buf[0] = '\0'; + if (OB_FAIL(get_global_config_server_processor().get_default_cluster_name(cluster_name_buf, OB_PROXY_FULL_USER_NAME_MAX_LEN + 1))) { LOG_WARN("fail to get default cluster name", K(ret)); } else { - ObString default_cname = '\0' == cluster_name[0] + ObString default_cname = '\0' == cluster_name_buf[0] ? ObString::make_string(OB_PROXY_DEFAULT_CLUSTER_NAME) - : ObString::make_string(cluster_name); + : ObString::make_string(cluster_name_buf); if (OB_FAIL(databuff_printf(full_user_name, OB_PROXY_FULL_USER_NAME_MAX_LEN + 1, pos, "%s#%.*s", ObProxyTableInfo::READ_ONLY_USERNAME, default_cname.length(), default_cname.ptr()))) { LOG_WARN("fail to databuff_printf", "username", ObProxyTableInfo::READ_ONLY_USERNAME, K(default_cname), K(ret)); @@ -1330,6 +1339,7 @@ int ObHotUpgradeProcessor::init_raw_client(ObRawMysqlClient &raw_client, const O static_cast(strlen(get_global_proxy_config().observer_sys_password1.str()))); string_db.assign_ptr(ObProxyTableInfo::READ_ONLY_DATABASE, static_cast(STRLEN(ObProxyTableInfo::READ_ONLY_DATABASE))); + cluster_name.assign_ptr(cluster_name_buf, static_cast(strlen(cluster_name_buf))); } } break; @@ -1357,12 +1367,12 @@ int ObHotUpgradeProcessor::init_raw_client(ObRawMysqlClient &raw_client, const O if (OB_SUCC(ret)) { ObSEArray local_addrs; ObAddr addr; - if (OB_UNLIKELY(!addr.set_ipv4_addr(proxy_ip_, proxy_port_))) { + if (OB_UNLIKELY(!addr.set_ip_addr(proxy_ip_, proxy_port_))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to set addr", K(proxy_ip_), K(proxy_port_), K(ret)); } else if (OB_FAIL(local_addrs.push_back(addr))) { LOG_WARN("fail to push addr to local_addrs", K(addr), K(ret)); - } else if (OB_FAIL(raw_client.init(string_username, string_passwd, string_db, string_passwd1))) { + } else if (OB_FAIL(raw_client.init(string_username, string_passwd, string_db, cluster_name, string_passwd1))) { LOG_WARN("fail to init raw mysql client", K(string_username), K(string_db), K(ret)); } else if (OB_FAIL(raw_client.set_server_addr(local_addrs))) { LOG_WARN("fail to set server addr", K(ret)); diff --git a/src/obproxy/obutils/ob_hot_upgrade_processor.h b/src/obproxy/obutils/ob_hot_upgrade_processor.h index 86798808ae6d2cdf2f27c5bb784417012c4430e2..518240016acf729f73f0cfbd99f3adabc2eae4c3 100644 --- a/src/obproxy/obutils/ob_hot_upgrade_processor.h +++ b/src/obproxy/obutils/ob_hot_upgrade_processor.h @@ -133,7 +133,7 @@ private: ObAsyncCommonTask *hu_cont_; ObAsyncCommonTask *hot_upgrade_cont_; ObHotUpgraderInfo &info_; - char proxy_ip_[common::OB_IP_STR_BUFF]; // ip primary key + char proxy_ip_[common::MAX_IP_ADDR_LENGTH]; // ip primary key char proxy_self_md5_[OB_DEFAULT_PROXY_MD5_LEN + 1]; int32_t proxy_port_; // port primary key int64_t upgrade_failures_; // upgrade failures when handling 'hot_upgrade' cmd diff --git a/src/obproxy/obutils/ob_log_file_processor.cpp b/src/obproxy/obutils/ob_log_file_processor.cpp index 29e741a3aa9c225ace5dcba262154c685cec862d..21b46cabf0d1c266b2055d2f3b2c63b674c31600 100644 --- a/src/obproxy/obutils/ob_log_file_processor.cpp +++ b/src/obproxy/obutils/ob_log_file_processor.cpp @@ -90,7 +90,7 @@ int ObLogFileProcessor::start_cleanup_log_file() LOG_WARN("log file processor is not inited", K(ret)); } else if (OB_UNLIKELY(NULL != cleanup_cont_)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("log file cleanup task has already been schuduled", K_(cleanup_cont), K(ret)); + LOG_WARN("log file cleanup task has already been scheduled", K_(cleanup_cont), K(ret)); } else { int64_t interval_us = get_global_proxy_config().log_cleanup_interval; if (OB_ISNULL(cleanup_cont_ = ObAsyncCommonTask::create_and_start_repeat_task(interval_us, @@ -98,7 +98,7 @@ int ObLogFileProcessor::start_cleanup_log_file() ObLogFileProcessor::do_repeat_task, ObLogFileProcessor::update_interval))) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("fail to create and start cleanup task", K(interval_us), K(ret)); + LOG_WARN("fail to create and start log cleanup task", K(interval_us), K(ret)); } else { LOG_INFO("succ to create and start log cleanup task", K(interval_us)); } diff --git a/src/obproxy/obutils/ob_proxy_config.cpp b/src/obproxy/obutils/ob_proxy_config.cpp index b144b021e3efe3b1866cac41c3da962074360693..4340c9ecac20ee36699c0e2590e0d9007b04fcc3 100644 --- a/src/obproxy/obutils/ob_proxy_config.cpp +++ b/src/obproxy/obutils/ob_proxy_config.cpp @@ -214,6 +214,31 @@ int ObProxyConfig::dump_config_to_local() return ret; } +int ObProxyConfig::dump_config_to_sqlite() +{ + int ret = OB_SUCCESS; + CRLockGuard guard(rwlock_); + ObConfigContainer::const_iterator it = container_.begin(); + for (; OB_SUCC(ret) && it != container_.end(); ++it) { + const char *sql = "replace into proxy_config(name, value, config_level) values('%s', '%s', 'LEVEL_GLOBAL')"; + char buf[1024]; + char *err_msg = NULL; + int64_t len = static_cast(snprintf(buf, 1024, sql, it->first.str(), it->second->str())); + if (OB_UNLIKELY(len <= 0) || OB_UNLIKELY(len >= 1024)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to fill sql", K(buf), K(len), K(ret)); + } else if (SQLITE_OK != sqlite3_exec(proxy_config_db_, buf, NULL, 0, &err_msg)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("exec replace into proxy config failed", K(ret), "sql", buf, "err_msg", err_msg); + } + + if (NULL != err_msg) { + sqlite3_free(err_msg); + } + } + return ret; +} + int ObProxyConfig::set_value_safe(ObConfigItem *item, const ObString &value, const bool allow_invalid_value/*true*/) { @@ -353,6 +378,29 @@ int ObProxyConfig::get_old_config_value(const common::ObString &key_name, char * return ret; } +int ObProxyConfig::get_config_item(const common::ObString &key_name, ObConfigItem &ret_item) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(key_name.empty()) + || OB_UNLIKELY(key_name.length() >= static_cast(OB_MAX_CONFIG_NAME_LEN))) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(key_name), K(ret)); + } else { + ObConfigItem *const *item = NULL; + ObConfigStringKey key(key_name); + + if (OB_ISNULL(item = container_.get(key))) { + ret = OB_ERR_SYS_CONFIG_UNKNOWN; + LOG_WARN("unknown key_name", K(key_name), K(ret)); + } else { + //we need lock it whenever handle item->value + CRLockGuard guard(rwlock_); + ret_item = **item; + } + } + return ret; +} + void ObProxyConfig::update_log_level(const bool level_flag) { int ret = OB_SUCCESS; @@ -368,7 +416,9 @@ void ObProxyConfig::update_log_level(const bool level_flag) LOG_WARN(" fail to update sys log level", K(ret)); } else if (OB_FAIL(dump_config_to_local())) { LOG_WARN("dump config fail, inc log level fail", K(ret)); - } else { + } else if (OB_FAIL(dump_config_to_sqlite())) { + LOG_WARN("dump config failed, inc log level fail", K(ret)); + } { //do nothing } diff --git a/src/obproxy/obutils/ob_proxy_config.h b/src/obproxy/obutils/ob_proxy_config.h index 17bc690a81043d770932248e25f14f2e2579930e..ada88e218f77f07d3f6c2ae407a6d27017953960 100644 --- a/src/obproxy/obutils/ob_proxy_config.h +++ b/src/obproxy/obutils/ob_proxy_config.h @@ -13,6 +13,7 @@ #ifndef OBPROXY_CONFIG_H #define OBPROXY_CONFIG_H +#include #include "lib/hash/ob_hashmap.h" #include "share/config/ob_common_config.h" #include "iocore/net/ob_inet.h" @@ -68,7 +69,8 @@ public: // FIXME: here we use true value to init dump_config_res_, so that in start period, // if proxy fail to load config from local and ocp database, // we wont dump default config to local. - ObProxyConfig() : with_config_server_(false), with_control_plane_(false), rwlock_() + ObProxyConfig() : with_config_server_(false), with_control_plane_(false), + proxy_config_db_(NULL), rwlock_() { original_value_str_[0] = '\0'; set_app_name(app_name); @@ -90,10 +92,12 @@ public: //dump config to local file int dump_config_to_local(); + int dump_config_to_sqlite(); int update_config_item(const common::ObString &key_name, const common::ObString &value); int update_user_config_item(const common::ObString &key_name, const common::ObString &value); int get_old_config_value(const common::ObString &key_name, char *buf, const int64_t buf_size); + int get_config_item(const common::ObString &key_name, common::ObConfigItem &ret_item); // if level_flag = true, we will up sys log level // otherwise we will down sys log level @@ -134,6 +138,7 @@ public: bool with_config_server_; bool with_control_plane_; char app_name_str_[common::OB_MAX_APP_NAME_LENGTH + 1]; + sqlite3 *proxy_config_db_; private: char original_value_str_[common::OB_MAX_CONFIG_VALUE_LEN]; @@ -143,6 +148,8 @@ private: public: // FIXME: DEF_INT can not compare with 0(<, >, >=, <=) mutable obsys::CRWLock rwlock_; + // xa transaction + DEF_BOOL(enable_xa_route, "true", "whether to enable hold XA_START and route to the partition that the next dml will visit",CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); // refresh local config DEF_BOOL(refresh_json_config, "false", "force update json info if refresh_json_config is true", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_MEMORY); DEF_BOOL(refresh_rslist, "false", "when refresh config server, update all rslist if refresh_rslist is true", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_MEMORY); @@ -213,7 +220,7 @@ public: DEF_INT(server_tcp_keepcnt, "5", "[0,9]", "tcp keepalive probe count, 0 means use default value by kernel", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_INT(server_tcp_user_timeout, "0", "[0,20]", "tcp user timeout, unit is s, 0 means no user timeout", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); - DEF_INT(client_sock_option_flag_out, "2", "[0,]","client sock param, option flag out, bit 1: NO_DELAY, bit 2: KEEP_ALIVE", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); + DEF_INT(client_sock_option_flag_out, "3", "[0,]","client sock param, option flag out, bit 1: NO_DELAY, bit 2: KEEP_ALIVE", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_INT(client_tcp_keepidle, "5", "[0,7200]", "client tcp keepalive idle time, unit is second, 0 means use default value by kernel", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_INT(client_tcp_keepintvl, "5", "[0,75]", "client tcp keepalive interval time, unit is second, 0 means use default value by kernel", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_INT(client_tcp_keepcnt, "5", "[0,9]", "client tcp keepalive probe count, 0 means use default value by kernel", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); @@ -228,6 +235,7 @@ public: DEF_INT(block_thread_num, "1", "[1,4]", "proxy block thread num, [1, 4]", CFG_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_INT(grpc_thread_num, "8", "[8,16]", "proxy grpc thread num, [8, 16]", CFG_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_INT(grpc_client_num, "9", "[9,16]", "proxy grpc client num, [9, 16]", CFG_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); + DEF_INT(shard_scan_thread_num, "0", "[0,128]", "proxy shard scan thread num, if 0, use (real work thread num/2), [0, 128]", CFG_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_BOOL(automatic_match_work_thread, "true", "ignore work_thread_num configuration item, use the count of cpu for current proxy work thread num", CFG_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_BOOL(enable_strict_kernel_release, "true", "If is true, proxy only support 5u/6u/7u redhat. Otherwise no care kernel release, and proxy maybe unstable", CFG_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); DEF_CAP(max_log_file_size, "256MB", "[1MB,1G]", "max size of log file, [1MB, 1G]", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); @@ -259,6 +267,8 @@ public: DEF_BOOL(ignore_local_config, "true", "ignore all local cached files, start proxy with remote json", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_IP(local_bound_ip, "0.0.0.0", "local bound ip(any)", CFG_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); DEF_INT(listen_port, "6688", "(1024,65536)", "obproxy listen port", CFG_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); + DEF_INT(ip_listen_mode, "1", "[1, 3]", "1 means ipv4 listen mode, 2 means ipv6 listen mode, 3 means ipv4 and ipv6 listen mode", CFG_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); + DEF_IP(local_bound_ipv6_ip, "::", "local bound ipv6 ip(any)", CFG_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); DEF_STR(obproxy_config_server_url, "", "url of config info(rs list and so on)", CFG_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); DEF_STR(proxy_service_mode, "client", "proxy deploy and service mode: 1.client(default); 2.server", CFG_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); DEF_INT(proxy_id, "0", "[0, 255]", "used to identify each obproxy, it can not be zero if proxy_service_mode is server", CFG_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); @@ -279,11 +289,18 @@ public: DEF_TIME(congestion_retry_interval, "20s", "[1s,1h]", "congestion retry interval, [1s, 1h]", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_TIME(min_congested_connect_timeout, "100ms", "[1ms,1h]", "if client connect timeout after the time, proxy set target server alive congested, [1ms, 1h]", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_BOOL(enable_congestion, "true", "enable congestion feature or not", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); + DEF_INT(server_detect_mode, "1", "[0,2]", "0 means no detect, 1 means target server detect, 2 means all server detect", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); + DEF_INT(server_detect_fail_threshold, "3", "[1,10000]", "server detect try times", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); + DEF_TIME(server_detect_refresh_interval, "1s", "[1ms, 1h]", "the interval to refresh server state for getting zone or server newest state, [10ms, 1h]", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); + DEF_TIME(detect_server_timeout, "5s", "[1s,1h]", "detect server sql timeout, [1s, 1h]", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_BOOL(enable_bad_route_reject, "false", "if enabled, bad route request will be rejected, e.g. first statement of transaction opened by BEGIN(or START TRANSACTION) without table name", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_BOOL(enable_partition_table_route, "true", "if enabled, partition table will be accurate routing", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_BOOL(enable_compression_protocol, "true", "if enabled, proxy will use compression protocol with server", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_BOOL(enable_ob_protocol_v2, "true", "if enabled, proxy will use oceanbase protocol 2.0 with server", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); + DEF_BOOL(enable_ob_protocol_v2_with_client, "true", "if enabled, proxy will use oceanbase protocol 2.0 with client", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); + DEF_BOOL(enable_transaction_internal_routing, "true", "if enabled, proxy will route the dml statement in a transaction to different servers", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); + DEF_BOOL(enable_reroute, "false", "if this and protocol_v2 enabled, proxy will reroute when routing error", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_BOOL(enable_pl_route, "true", "if enabled, pl will be accurate routing", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_BOOL(enable_cached_server, "true", "if enabled, use cached server session when no table entry", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); @@ -294,7 +311,10 @@ public: // sqlaudit DEF_CAP(sqlaudit_mem_limited, "0", "[0,1G]", "sqlaudit memory limited, [0, 1GB]", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); - DEF_CAP(internal_cmd_mem_limited, "64K", "[0,64MB]", "internal cmd response memory limited, [0, 64MB], 0 means unlimited", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); + DEF_CAP(internal_cmd_mem_limited, "16M", "[0,64MB]", "internal cmd response memory limited, [0, 64MB], 0 means unlimited", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); + + // target db servers + DEF_STR(target_db_server, "", "proxy will choose to route target db server addr forcibly, format ip0:port0,ip1:port1,ip2:port2;ip3:port3;ip4:port4", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); //debug DEF_STR(test_server_addr, "", "proxy will choose this addr(if not empty) as observer addr forcibly, format ip1:sql_port1;ip2:sql_port2", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); @@ -354,6 +374,8 @@ public: DEF_INT(qa_mode_mock_public_cloud_vid, "1", "[1,102400]", "mock public cloud vid", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_STR(proxy_route_policy, "", "proxy route policy", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); + DEF_BOOL(enable_cpu_isolate, "false", "enable cpu isolate or not", CFG_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); + DEF_STR(mysql_version, "5.6.25", "returned version for mysql mode, default value is 5.6.25. If set, proxy will send new version when user connect to proxy", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER) // sql table cache DEF_BOOL(enable_index_route, "false", "enable index route or not", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); @@ -381,6 +403,8 @@ public: // primary zone DEF_STR(proxy_primary_zone_name, "", "primary zone name for proxy ldc route. If not empty, proxy only route to the zone", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); + DEF_BOOL(enable_primary_zone, "true", "enable proxy route according to the tenant primary zone priority while proxy calculate route failed.", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); + // LGD config DEF_BOOL(enable_ldg, "false", "enable proxy to support ldg", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); DEF_TIME(ldg_info_refresh_interval, "20s", "[10s,1d]", "config server info refresh task interval, [10s, 1d]", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); @@ -435,14 +459,10 @@ public: // beyond trust sdk DEF_STR(domain_name, "", "app domain name", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); - DEF_BOOL(bt_use_antvip, "true", "if enabled, will use ant vip for bt sdk", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_STR(bt_server_addr, "", "beyond trust server address or hostname", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); - DEF_STR(bt_antvip_server_addr, "", "beyond trust antvip server", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); - DEF_STR(bt_server_antvip, "", "beyond trust server antvip", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); - DEF_BOOL(bt_local_work_mode, "false", "true means LOCAL_CERT_MODE and false means CITADEL_CERT_MODE", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); - DEF_STR(bt_env_mode, "TENANT_MODE", "beyond trust env mode", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); - DEF_STR(bt_instance_id, "", "beyond trust instance id for INSTANCEID env mode", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); DEF_INT(bt_retry_times, "3", "[0,100]", "beyond trust sdk retry times", CFG_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); + DEF_STR(bt_mode, "", "beyond trust mode", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); + DEF_STR(citadel_agent_ip, "", "bkmi citadel agent ip", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER); // proxyro@sys and root@proxysys passwd DEF_STR(inspector_password, "", "password for inspector user", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); @@ -457,6 +477,18 @@ public: DEF_BOOL(enable_stat, "true", "if enabled, will collect stat info", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); DEF_INT(digest_sql_length, "1024", "0 means use default print sql len, otherwise is digest_sql_length", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); + + DEF_INT(obproxy_read_only, "1", "[0,1]", "read write type: 0 means ReadOnly, 1 means ReadWrite", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); + DEF_INT(obproxy_read_consistency, "0", "[0,1]", "request target: 0 means leader; 1 means follower", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); + + DEF_BOOL(enable_global_ps_cache, "true", "if enabled, use global ps cache", CFG_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); + + DEF_BOOL(enable_read_write_split, "false", "if enabled, use read write split mode", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); + DEF_BOOL(enable_transaction_split, "false", "if enabled, support transaction split", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); + + // binlog service + DEF_STR(binlog_service_ip, "", "binlog service ip, format ip1:sql_port1", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); + DEF_BOOL(enable_binlog_service, "false", "if enabled, obproxy will send binlog request to OBLogProxy", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS); }; ObProxyConfig &get_global_proxy_config(); diff --git a/src/obproxy/obutils/ob_proxy_config_manager.cpp b/src/obproxy/obutils/ob_proxy_config_manager.cpp index ea501d3740043c4879b343841e26054b5e4f2758..32bf670b75df7283e3bcdb5ebaf34c47f280fb68 100644 --- a/src/obproxy/obutils/ob_proxy_config_manager.cpp +++ b/src/obproxy/obutils/ob_proxy_config_manager.cpp @@ -174,9 +174,9 @@ int ObProxyConfigManager::update_local_config(const int64_t new_config_version, //3. reload config to memory if (OB_SUCC(ret)) { if (OB_FAIL((*reload_config_func_)(proxy_config_))) { - WARN_ICMD("fail to reload config", K(ret)); + LOG_WARN("fail to reload config", K(ret)); } else { - DEBUG_ICMD("succ to update local config"); + LOG_DEBUG("succ to update local config"); } } @@ -186,12 +186,12 @@ int ObProxyConfigManager::update_local_config(const int64_t new_config_version, if (has_serialized) { obsys::CWLockGuard guard(proxy_config_.rwlock_); if (OB_UNLIKELY(OB_SUCCESS != (tmp_ret = (proxy_config_.deserialize(orig_buf, write_pos, read_pos))))) { - WARN_ICMD("fail to deserialize old config", K(write_pos), K(read_pos), K(tmp_ret)); + LOG_WARN("fail to deserialize old config", K(write_pos), K(read_pos), K(tmp_ret)); } else if (OB_UNLIKELY(write_pos != read_pos)) { tmp_ret = OB_DESERIALIZE_ERROR; LOG_WARN("deserialize proxy config failed", K(write_pos), K(read_pos), K(tmp_ret)); } else { - DEBUG_ICMD("succ to deserialize old config", K(write_pos), K(read_pos)); + LOG_DEBUG("succ to deserialize old config", K(write_pos), K(read_pos)); } } if (has_dump_config && OB_LIKELY(OB_SUCCESS == tmp_ret)) { diff --git a/src/obproxy/obutils/ob_proxy_config_processor.cpp b/src/obproxy/obutils/ob_proxy_config_processor.cpp index 9595a8398b38d2f40f89ff11b5ce3f1e895e9224..47625237d3635256fe3fa02bf77d792e920786a1 100644 --- a/src/obproxy/obutils/ob_proxy_config_processor.cpp +++ b/src/obproxy/obutils/ob_proxy_config_processor.cpp @@ -1653,10 +1653,26 @@ int ObProxyConfigProcessor::load_local_config() } event::ObFixedArenaAllocator allocator; while (OB_SUCC(ret) && NULL != (ent = readdir(etc_dir))) { - allocator.reuse(); + bool is_need_load = false; + if (NULL != memchr(ent->d_name, '.', ent->d_reclen)) { + // do nothing + } else if (ent->d_type == DT_DIR) { + is_need_load = true; + } else if (ent->d_type == DT_UNKNOWN) { + struct stat st; + char *full_path = NULL; + allocator.reuse(); + if (OB_FAIL(ObLayout::merge_file_path(layout_etc_dir, ent->d_name, allocator, full_path))) { + LOG_WARN("fail to merge file", K(layout_etc_dir), "name", ent->d_name, K(ret)); + } else if (0 != (stat(full_path, &st))) { + ret = OB_IO_ERROR; + LOG_WARN("fail to stat dir", K(full_path), KERRMSGS, K(ret)); + } else if (S_ISDIR(st.st_mode)) { + is_need_load = true; + } + } // we only load current config dir - if (ent->d_type == DT_DIR - && NULL == memchr(ent->d_name, '.', ent->d_reclen)) { + if (OB_SUCC(ret) && is_need_load) { if (OB_FAIL(load_local_app_config(ObString::make_string(ent->d_name)))) { LOG_WARN("fail to load app config", "app name", ent->d_name, K(ret)); } @@ -2192,8 +2208,8 @@ int ObProxyConfigProcessor::update_app_security_config(const ObString &appname, if (OB_UNLIKELY(len <= 0 || len > json_len)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fill sql failed", K(len), K(json_len), K(ret)); - } else if (OB_FAIL(get_global_config_processor().store_cloud_config("ssl_config", "*", "*", "key_info", json_buf))) { - LOG_WARN("execute sql failed", K(ret)); + } else if (OB_FAIL(get_global_config_processor().store_global_ssl_config("key_info", json_buf))) { + LOG_WARN("store global ssl config failed", K(ret)); } } diff --git a/src/obproxy/obutils/ob_proxy_config_utils.cpp b/src/obproxy/obutils/ob_proxy_config_utils.cpp index e82608cba5fde68eb8c55125e9a28137515a02d2..e97774d304d6fdc61aa32988f665d1fe675cc6d3 100644 --- a/src/obproxy/obutils/ob_proxy_config_utils.cpp +++ b/src/obproxy/obutils/ob_proxy_config_utils.cpp @@ -18,8 +18,10 @@ #include "utils/ob_layout.h" #include "obutils/ob_proxy_config.h" #include "proxy/client/ob_mysql_proxy.h" +#include "ob_proxy_init.h" using namespace oceanbase::common; +using namespace oceanbase::obproxy; using namespace oceanbase::obproxy::event; using namespace oceanbase::obproxy::proxy; @@ -569,7 +571,9 @@ int ObProxyConfigUtils::load_config_from_file(ObProxyConfig &proxy_config) if (OB_ISNULL(buf = static_cast(ob_malloc(OB_PROXY_CONFIG_BUFFER_SIZE, mem_attr)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("ob tc malloc memory for buf fail", K(ret)); - } else if (OB_FAIL(ObProxyFileUtils::read(CFG_DUMP_NAME, buf, OB_PROXY_CONFIG_BUFFER_SIZE, read_len))) { + // If it is a rich client mode, the configuration will not be read from the local file + } else if (RUN_MODE_PROXY == g_run_mode + && OB_FAIL(ObProxyFileUtils::read(CFG_DUMP_NAME, buf, OB_PROXY_CONFIG_BUFFER_SIZE, read_len))) { // no need to print warn log, the caller will do it } else { obsys::CWLockGuard guard(proxy_config.rwlock_); @@ -898,8 +902,20 @@ void ObProxyFileUtils::clear_dir(const char *dir) if (LOCAL_DIR == ent->d_name || PARENT_DIR == ent->d_name) { continue; } + bool is_dir = false; snprintf(tmp_path, FileDirectoryUtils::MAX_PATH, "%s/%s", dir, ent->d_name); if (ent->d_type == DT_DIR) { + is_dir = true; + } else if (ent->d_type == DT_UNKNOWN) { + struct stat st; + if (0 != (stat(tmp_path, &st))) { + LOG_WARN("fail to stat dir", K(tmp_path), KERRMSGS); + } else { + is_dir = S_ISDIR(st.st_mode); + } + } + + if (is_dir) { clear_dir(tmp_path); } else { ::unlink(tmp_path); diff --git a/src/obproxy/obutils/ob_proxy_json_config_info.cpp b/src/obproxy/obutils/ob_proxy_json_config_info.cpp index 092d05d6bee9c10bf39ad5c5da4f389c0063f472..2aa9b2f657623e27bc9d0dee24fbe02a782f9d0b 100644 --- a/src/obproxy/obutils/ob_proxy_json_config_info.cpp +++ b/src/obproxy/obutils/ob_proxy_json_config_info.cpp @@ -2103,7 +2103,7 @@ int ObProxyJsonUtils::rslist_to_json(const LocationList &addr_list, const char * } } if (OB_SUCC(ret)) { - char ip_buf[OB_IP_STR_BUFF]; + char ip_buf[MAX_IP_ADDR_LENGTH]; for (int64_t i = 0; OB_SUCC(ret) && i < addr_list.count(); ++i) { ip_buf[0] = '\0'; if (i > 0) { diff --git a/src/obproxy/obutils/ob_proxy_sql_parser.cpp b/src/obproxy/obutils/ob_proxy_sql_parser.cpp index eab47c2bfb56d229c5cc4d93191e421da9d023bc..d8bd290535db7301cc71b16427bacb98093f0b43 100644 --- a/src/obproxy/obutils/ob_proxy_sql_parser.cpp +++ b/src/obproxy/obutils/ob_proxy_sql_parser.cpp @@ -17,6 +17,7 @@ #include "opsql/parser/ob_proxy_parser.h" #include "dbconfig/ob_proxy_db_config_info.h" #include "proxy/shard/obproxy_shard_utils.h" +#include "obproxy/utils/ob_proxy_utils.h" using namespace oceanbase::common; using namespace oceanbase::obproxy::opsql; @@ -27,6 +28,7 @@ namespace obproxy { namespace obutils { +#define ISSPACE(c) ((c) == ' ' || (c) == '\n' || (c) == '\r' || (c) == '\t' || (c) == '\f' || (c) == '\v') void ObSqlParseResult::clear_proxy_stmt() { @@ -54,7 +56,7 @@ int ObSqlParseResult::set_real_table_name(const char *table_name, int64_t len) return ret; } -inline int ObSqlParseResult::set_db_name(const ObProxyParseString &database_name, +int ObSqlParseResult::set_db_name(const ObProxyParseString &database_name, const bool use_lower_case_name/*false*/, const bool drop_origin_db_table_name /*false*/) { @@ -108,43 +110,47 @@ inline int ObSqlParseResult::set_db_table_name(const ObProxyParseString &databas MEMCPY(origin_dml_buf_.table_name_buf_, table_name.str_, table_name.str_len_); origin_table_name_.assign_ptr(origin_dml_buf_.table_name_buf_, table_name.str_len_); } + } + } - // assign package name when table name is valid - if (OB_UNLIKELY(NULL != package_name.str_ && 0 != package_name.str_len_)) { - if (OB_UNLIKELY(package_name.str_len_ > OB_MAX_TABLE_NAME_LENGTH) - || OB_UNLIKELY(package_name.str_len_ < 0)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid argument", K(ret)); - } else { - MEMCPY(dml_buf_.package_name_buf_, package_name.str_, package_name.str_len_); - if (use_lower_case_name) { - string_to_lower_case(dml_buf_.package_name_buf_, package_name.str_len_); - } - package_name_.assign_ptr(dml_buf_.package_name_buf_, package_name.str_len_); - package_name_quote_ = package_name.quote_type_; + if (OB_SUCC(ret)) { + // assign package name when table name is valid + if (OB_UNLIKELY(NULL != package_name.str_ && 0 != package_name.str_len_)) { + if (OB_UNLIKELY(package_name.str_len_ > OB_MAX_TABLE_NAME_LENGTH) + || OB_UNLIKELY(package_name.str_len_ < 0)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(ret)); + } else { + MEMCPY(dml_buf_.package_name_buf_, package_name.str_, package_name.str_len_); + if (use_lower_case_name) { + string_to_lower_case(dml_buf_.package_name_buf_, package_name.str_len_); } + package_name_.assign_ptr(dml_buf_.package_name_buf_, package_name.str_len_); + package_name_quote_ = package_name.quote_type_; } + } + } - // assign database name when table name is valid - if (OB_SUCC(ret)) { - if (OB_FAIL(set_db_name(database_name, use_lower_case_name, drop_origin_db_table_name))) { - LOG_WARN("fail to set db name", K(database_name.str_len_), K(ret)); - } - } + // assign database name when table name is valid + if (OB_SUCC(ret)) { + if (OB_FAIL(set_db_name(database_name, use_lower_case_name, drop_origin_db_table_name))) { + LOG_WARN("fail to set db name", K(database_name.str_len_), K(ret)); + } + } - if (OB_UNLIKELY(NULL != alias_name.str_ && 0 != alias_name.str_len_)) { - if (OB_UNLIKELY(alias_name.str_len_ > OB_MAX_TABLE_NAME_LENGTH) - || OB_UNLIKELY(alias_name.str_len_ < 0)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid argument", K(ret)); - } else { - MEMCPY(dml_buf_.alias_name_buf_, alias_name.str_, alias_name.str_len_); - if (use_lower_case_name) { - string_to_lower_case(dml_buf_.alias_name_buf_, alias_name.str_len_); - } - alias_name_.assign_ptr(dml_buf_.alias_name_buf_, alias_name.str_len_); - alias_name_quote_ = alias_name.quote_type_; + if (OB_SUCC(ret)) { + if (OB_UNLIKELY(NULL != alias_name.str_ && 0 != alias_name.str_len_)) { + if (OB_UNLIKELY(alias_name.str_len_ > OB_MAX_TABLE_NAME_LENGTH) + || OB_UNLIKELY(alias_name.str_len_ < 0)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(ret)); + } else { + MEMCPY(dml_buf_.alias_name_buf_, alias_name.str_, alias_name.str_len_); + if (use_lower_case_name) { + string_to_lower_case(dml_buf_.alias_name_buf_, alias_name.str_len_); } + alias_name_.assign_ptr(dml_buf_.alias_name_buf_, alias_name.str_len_); + alias_name_quote_ = alias_name.quote_type_; } } } @@ -186,7 +192,7 @@ inline int ObSqlParseResult::set_col_name(const ObProxyParseString &col_name) inline int ObSqlParseResult::set_call_prarms(const ObProxyCallParseInfo &call_parse_info) { int ret = OB_SUCCESS; - if (OB_UNLIKELY(!is_call_stmt())) { + if (OB_UNLIKELY(!is_call_stmt() && !is_text_ps_call_stmt())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("not a call stmt should not set col name", K(ret)); } else if (OB_UNLIKELY(call_parse_info.node_count_ < 0)) { @@ -195,24 +201,33 @@ inline int ObSqlParseResult::set_call_prarms(const ObProxyCallParseInfo &call_pa } else if (call_parse_info.node_count_ >= 0) { call_info_.is_param_valid_ = true; call_info_.param_count_ = call_parse_info.node_count_; - ObProxyCallParam tmp_param; + ObProxyCallParam* tmp_param = NULL; ObProxyCallParseNode *tmp_node = call_parse_info.head_; - while(tmp_node && OB_SUCC(ret)) { - tmp_param.reset(); - tmp_param.type_ = tmp_node->type_; - if (CALL_TOKEN_INT_VAL == tmp_node->type_) { - tmp_param.str_value_.set_integer(tmp_node->int_value_); - } else if (CALL_TOKEN_PLACE_HOLDER == tmp_node->type_) { - // for place holder, store its pos - tmp_param.str_value_.set_integer(tmp_node->placeholder_idx_); + while(OB_SUCC(ret) && tmp_node) { + tmp_param = NULL; + if (OB_FAIL(ObProxyCallParam::alloc_call_param(tmp_param))) { + LOG_WARN("fail to alloc call param", K(ret)); } else { - const ObString tmp_string(tmp_node->str_value_.str_len_, tmp_node->str_value_.str_); - tmp_param.str_value_.set(tmp_string); - } // end node_type - if (OB_FAIL(call_info_.params_.push_back(tmp_param))) { - LOG_WARN("fail to push back call param", K(tmp_param), K(ret)); + tmp_param->type_ = tmp_node->type_; + if (CALL_TOKEN_INT_VAL == tmp_node->type_) { + tmp_param->str_value_.set_integer(tmp_node->int_value_); + } else if (CALL_TOKEN_PLACE_HOLDER == tmp_node->type_) { + // for place holder, store its pos + tmp_param->str_value_.set_integer(tmp_node->placeholder_idx_); + } else { + tmp_param->str_value_.set_value(tmp_node->str_value_.str_len_, tmp_node->str_value_.str_); + } // end node_type + if (OB_FAIL(call_info_.params_.push_back(tmp_param))) { + LOG_WARN("fail to push back call param", K(tmp_param), K(ret)); + } + + if (OB_FAIL(ret) && NULL != tmp_param) { + tmp_param->reset(); + tmp_param = NULL; + } + + tmp_node = tmp_node->next_; } - tmp_node = tmp_node->next_; } } return ret; @@ -370,26 +385,35 @@ int ObSqlParseResult::set_dbmesh_route_info(const ObProxyParseResult &parse_resu ObShardColumnNode *tmp_node = route_info.head_; fileds_result_.field_num_ = 0; fileds_result_.fields_.reuse(); - SqlField field; + SqlField* field = NULL; while(tmp_node) { - field.reset(); + field = NULL; tmp_str.assign_ptr(tmp_node->tb_name_.str_, tmp_node->tb_name_.str_len_); const ObString table_name = tmp_str.trim(); if (is_dual_request_ || table_name.case_compare(table_name_) == 0) { tmp_str.assign_ptr(tmp_node->col_name_.str_, tmp_node->col_name_.str_len_); - field.column_name_.set(tmp_str); - SqlColumnValue column_value; - if (DBMESH_TOKEN_STR_VAL == tmp_node->type_) { - column_value.value_type_ = TOKEN_STR_VAL; - tmp_str.assign_ptr(tmp_node->col_str_value_.str_, tmp_node->col_str_value_.str_len_); - column_value.column_value_.set(tmp_str); - field.column_values_.push_back(column_value); + if (OB_FAIL(SqlField::alloc_sql_field(field))) { + LOG_WARN("fail to alloc sql field", K(ret)); } else { - LOG_INFO("unknown column value type", "token type", - get_obproxy_dbmesh_token_type(tmp_node->type_)); - } - if (field.is_valid() && OB_SUCCESS == fileds_result_.fields_.push_back(field)) { - ++fileds_result_.field_num_; + field->column_name_.set_value(tmp_str); + SqlColumnValue column_value; + if (DBMESH_TOKEN_STR_VAL == tmp_node->type_) { + column_value.value_type_ = TOKEN_STR_VAL; + tmp_str.assign_ptr(tmp_node->col_str_value_.str_, tmp_node->col_str_value_.str_len_); + column_value.column_value_.set_value(tmp_str); + if (OB_FAIL(field->column_values_.push_back(column_value))) { + LOG_WARN("field push back column values failed", K(column_value), K(ret)); + } + } else { + LOG_INFO("unknown column value type", "token type", + get_obproxy_dbmesh_token_type(tmp_node->type_)); + } + if (OB_SUCC(ret) && field->is_valid() && OB_SUCCESS == fileds_result_.fields_.push_back(field)) { + ++fileds_result_.field_num_; + } else if (NULL != field) { + field->reset(); + field = NULL; + } } } tmp_node = tmp_node->next_; @@ -426,23 +450,38 @@ int ObSqlParseResult::set_dbmesh_route_info(const ObProxyParseResult &parse_resu use_dbp_hint_ = true; dbp_route_info_.scan_all_ = dbp_route_info.scan_all_; } + + if (OB_SUCC(ret) && dbp_route_info.sticky_session_) { + use_dbp_hint_ = true; + dbp_route_info_.sticky_session_ = dbp_route_info.sticky_session_; + } + if (OB_SUCC(ret) && dbp_route_info.has_shard_key_) { use_dbp_hint_ = true; fileds_result_.field_num_ = 0; fileds_result_.fields_.reuse(); dbp_route_info_.has_shard_key_ = dbp_route_info.has_shard_key_; - SqlField field; for (int i = 0; OB_SUCC(ret) && i < dbp_route_info.shard_key_count_;i++) { + SqlField* field = NULL; SqlColumnValue column_value; - field.reset(); - field.column_name_.set_string(dbp_route_info.shard_key_infos_[i].left_str_.str_, - dbp_route_info.shard_key_infos_[i].left_str_.str_len_); - column_value.column_value_.set_string(dbp_route_info.shard_key_infos_[i].right_str_.str_, - dbp_route_info.shard_key_infos_[i].right_str_.str_len_); - column_value.value_type_ = TOKEN_STR_VAL; - field.column_values_.push_back(column_value); - if (field.is_valid() && OB_SUCC(fileds_result_.fields_.push_back(field))) { - ++fileds_result_.field_num_; + if (OB_FAIL(SqlField::alloc_sql_field(field))) { + LOG_WARN("fail to alloc sql field", K(ret)); + } else { + field->column_name_.set_value(dbp_route_info.shard_key_infos_[i].left_str_.str_len_, + dbp_route_info.shard_key_infos_[i].left_str_.str_); + column_value.column_value_.set_value(dbp_route_info.shard_key_infos_[i].right_str_.str_len_, + dbp_route_info.shard_key_infos_[i].right_str_.str_); + column_value.value_type_ = TOKEN_STR_VAL; + if (OB_FAIL(field->column_values_.push_back(column_value))) { + LOG_WARN("fail to push back to column_values", K(ret)); + } else if (field->is_valid() && OB_SUCC(fileds_result_.fields_.push_back(field))) { + ++fileds_result_.field_num_; + } + + if (OB_FAIL(ret) || !field->is_valid()) { + field->reset(); + field = NULL; + } } } } @@ -469,74 +508,85 @@ int ObSqlParseResult::set_var_info(const ObProxyParseResult &parse_result) ObString tmp_str; ObProxySetVarNode *tmp_node = set_parse_info.head_; - SetVarNode var_node; - while(tmp_node) { - var_node.reset(); - - var_node.var_type_ = tmp_node->type_; - - tmp_str.assign_ptr(tmp_node->name_.str_, tmp_node->name_.str_len_); - var_node.var_name_.set(tmp_str); - - var_node.value_type_ = tmp_node->value_type_; - if (SET_VALUE_TYPE_INT == tmp_node->value_type_) { - var_node.int_value_ = tmp_node->int_value_; - // float will be coverted to double - } else if (SET_VALUE_TYPE_NUMBER == tmp_node->value_type_) { - tmp_str.assign_ptr(tmp_node->str_value_.str_, tmp_node->str_value_.str_len_); - var_node.str_value_.set(tmp_str); + SetVarNode* var_node = NULL; + while(OB_SUCC(ret) && tmp_node) { + var_node = NULL; + if (OB_FAIL(SetVarNode::alloc_var_node(var_node))) { + LOG_WARN("fail to alloc var node", K(ret)); } else { - // compatible observer: - // for user var: the var will be returned from observer by OK packet: - // 1. if varchar is digital, observer return value not with ' - // 2. if varchar is string, observer return vaue with ' - // so, varchar type, do not add ' when format SQL - // for sys var: varchar type will add ' on format SQL - if (SET_VAR_USER == tmp_node->type_) { + var_node->var_type_ = tmp_node->type_; + tmp_str.assign_ptr(tmp_node->name_.str_, tmp_node->name_.str_len_); + var_node->var_name_.set_value(tmp_str); + + var_node->value_type_ = tmp_node->value_type_; + if (SET_VALUE_TYPE_INT == tmp_node->value_type_) { + var_node->int_value_ = tmp_node->int_value_; + //Floating point numbers will be converted to double type when saving + } else if (SET_VALUE_TYPE_NUMBER == tmp_node->value_type_) { tmp_str.assign_ptr(tmp_node->str_value_.str_, tmp_node->str_value_.str_len_); - if (OBPROXY_QUOTE_T_SINGLE == tmp_node->str_value_.quote_type_) { - var_node.str_value_.set_with_squote(tmp_str); - } else if (OBPROXY_QUOTE_T_DOUBLE == tmp_node->str_value_.quote_type_) { - var_node.str_value_.set_with_dquote(tmp_str); + var_node->str_value_.set_value(tmp_str); + } else { + // compatible observer: + // for user var: the var will be returned from observer by OK packet: + // 1. if varchar is digital, observer return value not with ' + // 2. if varchar is string, observer return vaue with ' + // so, varchar type, do not add ' when format SQL + // for sys var: varchar type will add ' on format SQL + if (SET_VAR_USER == tmp_node->type_) { + tmp_str.assign_ptr(tmp_node->str_value_.str_, tmp_node->str_value_.str_len_); + if (OBPROXY_QUOTE_T_SINGLE == tmp_node->str_value_.quote_type_) { + var_node->str_value_.set_value_with_quote(tmp_str, '\''); + } else if (OBPROXY_QUOTE_T_DOUBLE == tmp_node->str_value_.quote_type_) { + var_node->str_value_.set_value_with_quote(tmp_str, '"'); + } + } else { + tmp_str.assign_ptr(tmp_node->str_value_.str_, tmp_node->str_value_.str_len_); + var_node->str_value_.set_value(tmp_str); } + } + + if (OB_SUCCESS == set_info_.var_nodes_.push_back(var_node)) { + ++set_info_.node_count_; } else { - tmp_str.assign_ptr(tmp_node->str_value_.str_, tmp_node->str_value_.str_len_); - var_node.str_value_.set(tmp_str); + var_node->reset(); + var_node = NULL; } - } - if (OB_SUCCESS == set_info_.var_nodes_.push_back(var_node)) { - ++set_info_.node_count_; + tmp_node = tmp_node->next_; } - - tmp_node = tmp_node->next_; } } return ret; } -int ObSqlParseResult::set_text_ps_execute_info(const ObProxyTextPsExecuteParseInfo &execute_parse_info) +int ObSqlParseResult::set_text_ps_info(ObProxyTextPsInfo& text_ps_info, + const ObProxyTextPsParseInfo& parse_info) { int ret = OB_SUCCESS; if (OB_UNLIKELY(!is_text_ps_stmt())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("not text ps stmt", K(ret)); - } else if (OB_UNLIKELY(execute_parse_info.node_count_ < 0)) { + } else if (OB_UNLIKELY(parse_info.node_count_ < 0)) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid argument", K(execute_parse_info.node_count_), K(ret)); - } else if (execute_parse_info.node_count_ > 0) { - text_ps_execute_info_.is_param_valid_ = true; - text_ps_execute_info_.param_count_ = execute_parse_info.node_count_; - ObProxyTextPsExecuteParam tmp_param; - ObProxyTextPsExecuteParseNode *tmp_node = execute_parse_info.head_; + LOG_WARN("invalid argument", K(parse_info.node_count_), K(ret)); + } else if (parse_info.node_count_ > 0) { + text_ps_info.is_param_valid_ = true; + text_ps_info.param_count_ = parse_info.node_count_; + ObProxyTextPsParam* tmp_param = NULL; + ObProxyTextPsParseNode *tmp_node = parse_info.head_; while (OB_SUCC(ret) && OB_NOT_NULL(tmp_node)) { - tmp_param.reset(); - const ObString tmp_string(tmp_node->str_value_.str_len_, tmp_node->str_value_.str_); - tmp_param.str_value_.set(tmp_string); - - if (OB_FAIL(text_ps_execute_info_.params_.push_back(tmp_param))) { - LOG_WARN("fail to push back text ps execute info", K(tmp_param), K(ret)); + tmp_param = NULL; + if (OB_FAIL(ObProxyTextPsParam::alloc_text_ps_param(tmp_node->str_value_.str_, tmp_node->str_value_.str_len_, tmp_param))) { + LOG_WARN("fail to alloc text ps param", K(ret)); + } else { + const ObString tmp_string(tmp_node->str_value_.str_len_, tmp_node->str_value_.str_); + tmp_param->str_value_.set_value(tmp_string); + if (OB_FAIL(text_ps_info.params_.push_back(tmp_param))) { + tmp_param->reset(); + tmp_param = NULL; + LOG_WARN("fail to push back text ps execute info", KPC(tmp_param), K(ret)); + } } tmp_node = tmp_node->next_; } @@ -567,10 +617,16 @@ int ObSqlParseResult::load_result(const ObProxyParseResult &parse_result, parsed_length_ = static_cast(parse_result.end_pos_ - parse_result.start_pos_); text_ps_inner_stmt_type_ = parse_result.text_ps_inner_stmt_type_; - if (OB_UNLIKELY(is_sharding_request && NULL != parse_result.table_info_.table_name_.str_ && parse_result.table_info_.table_name_.str_len_ > 0)) { + if (OB_UNLIKELY(is_sharding_request && NULL != parse_result.table_info_.table_name_.str_ + && parse_result.table_info_.table_name_.str_len_ > 0)) { dbmesh_route_info_.tb_pos_ = parse_result.table_info_.table_name_.str_ - parse_result.start_pos_; } + if (OB_UNLIKELY(is_sharding_request && NULL != parse_result.table_info_.database_name_.str_ + && parse_result.table_info_.database_name_.str_len_ > 0)) { + dbmesh_route_info_.db_pos_ = parse_result.table_info_.database_name_.str_ - parse_result.start_pos_; + } + if (OB_UNLIKELY(NULL != parse_result.trace_id_.str_ && 0 < parse_result.trace_id_.str_len_ && OB_MAX_OBPROXY_TRACE_ID_LENGTH > parse_result.trace_id_.str_len_)) { @@ -585,9 +641,21 @@ int ObSqlParseResult::load_result(const ObProxyParseResult &parse_result, rpc_id_.assign_ptr(rpc_id_buf_, parse_result.rpc_id_.str_len_); } + if (OB_UNLIKELY(NULL != parse_result.target_db_server_.str_ + && 0 < parse_result.target_db_server_.str_len_)) { + if (OB_ISNULL(target_db_server_) && OB_ISNULL(target_db_server_ = op_alloc(ObTargetDbServer))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc memory for target db server", K(ret)); + } else if (OB_FAIL(target_db_server_->init(parse_result.target_db_server_.str_, parse_result.target_db_server_.str_len_))) { + LOG_WARN("fail to init target db server from sql comment", K(ret)); + } else { + LOG_DEBUG("succ to init target db server from sql comment", K(ret)); + } + } + // if is dml stmt, then set db/table name if (OB_LIKELY(is_dml_stmt() || is_call_stmt() || (is_text_ps_stmt() && is_text_ps_inner_dml_stmt()) - || is_show_create_table_stmt() || is_desc_table_stmt())) { + || is_show_stmt() || is_desc_table_stmt())) { if (OB_FAIL(set_db_table_name(parse_result.table_info_.database_name_, parse_result.table_info_.package_name_, parse_result.table_info_.table_name_, @@ -600,7 +668,7 @@ int ObSqlParseResult::load_result(const ObProxyParseResult &parse_result, if (is_sharding_request) { stmt_type_ = OBPROXY_T_INVALID; } - } else if (OB_UNLIKELY(is_call_stmt())) { + } else if (OB_UNLIKELY(is_call_stmt() || is_text_ps_call_stmt())) { if (OB_FAIL(set_call_prarms(parse_result.call_parse_info_))) { LOG_WARN("failed to set_call_prarms", K(ret)); } @@ -625,7 +693,7 @@ int ObSqlParseResult::load_result(const ObProxyParseResult &parse_result, if (OB_FAIL(set_var_info(parse_result))) { LOG_WARN("fail to set var info", K(ret)); } - } else if (is_show_topology_stmt()) { + } else if (is_show_elastic_id_stmt()) { ObString tmp_string(parse_result.cmd_info_.string_[0].str_len_, parse_result.cmd_info_.string_[0].str_); if (!tmp_string.empty()) { cmd_info_.string_[0].set(tmp_string); @@ -658,11 +726,23 @@ int ObSqlParseResult::load_result(const ObProxyParseResult &parse_result, ret = OB_ERR_UNEXPECTED; LOG_WARN("text ps name is null", K(ret)); } else { - MEMCPY(text_ps_buf_.text_ps_name_buf_, parse_result.text_ps_name_.str_, parse_result.text_ps_name_.str_len_); - text_ps_name_.assign_ptr(text_ps_buf_.text_ps_name_buf_, parse_result.text_ps_name_.str_len_); - if (OBPROXY_T_TEXT_PS_EXECUTE == parse_result.stmt_type_) { - if (OB_FAIL(set_text_ps_execute_info(parse_result.text_ps_execute_parse_info_))) { - LOG_WARN("fail to set text ps execute info", K(ret)); + if (NULL != text_ps_buf_) { + allocator_.free(text_ps_buf_); + text_ps_buf_ = NULL; + text_ps_buf_len_ = 0; + } + if (OB_ISNULL(text_ps_buf_ = static_cast(allocator_.alloc(parse_result.text_ps_name_.str_len_)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc mem", K(parse_result.text_ps_name_.str_len_), K(ret)); + } else { + text_ps_buf_len_ = parse_result.text_ps_name_.str_len_; + MEMCPY(text_ps_buf_, parse_result.text_ps_name_.str_, parse_result.text_ps_name_.str_len_); + text_ps_name_.assign_ptr(text_ps_buf_, text_ps_buf_len_); + string_to_upper_case(text_ps_name_.ptr(), text_ps_name_.length()); + if (OBPROXY_T_TEXT_PS_EXECUTE == parse_result.stmt_type_ || OBPROXY_T_TEXT_PS_PREPARE == parse_result.stmt_type_) { + if (OB_FAIL(set_text_ps_info(text_ps_info_, parse_result.text_ps_parse_info_))) { + LOG_WARN("fail to set text ps execute info", K(ret)); + } } } } @@ -726,8 +806,7 @@ int64_t ObProxyCallParam::to_string(char *buf, const int64_t buf_len) const { int64_t pos = 0; J_OBJ_START(); - J_KV("type", get_obproxy_call_token_type(type_), - K_(str_value)); + J_KV("type", get_obproxy_call_token_type(type_), K_(str_value), K_(is_alloc)); J_OBJ_END(); return pos; } @@ -741,16 +820,61 @@ int64_t ObProxyCallInfo::to_string(char *buf, const int64_t buf_len) const return pos; } -int64_t ObProxyTextPsExecuteParam::to_string(char *buf, const int64_t buf_len) const +ObProxyCallInfo::ObProxyCallInfo(const ObProxyCallInfo &other) +{ + int ret = OB_SUCCESS; + is_param_valid_ = other.is_param_valid_; + param_count_ = other.param_count_; + for (int64_t i = 0; OB_SUCC(ret) && i < param_count_; i++) { + ObProxyCallParam *param = other.params_.at(i); + ObProxyCallParam *tmp_param = NULL; + if (OB_FAIL(ObProxyCallParam::alloc_call_param(tmp_param))) { + LOG_WARN("fail to alloc call param", K(ret)); + } else { + *tmp_param = *param; + if (OB_FAIL(params_.push_back(tmp_param))) { + tmp_param->reset(); + tmp_param = NULL; + LOG_ERROR("fail to assign param", K(ret)); + } + } + } +} + +ObProxyCallInfo& ObProxyCallInfo::operator=(const ObProxyCallInfo &other) +{ + int ret = OB_SUCCESS; + if (this != &other) { + is_param_valid_ = other.is_param_valid_; + param_count_ = other.param_count_; + for (int64_t i = 0; OB_SUCC(ret) && i < param_count_; i++) { + ObProxyCallParam *param = other.params_.at(i); + ObProxyCallParam *tmp_param = NULL; + if (OB_FAIL(ObProxyCallParam::alloc_call_param(tmp_param))) { + LOG_WARN("fail to alloc call param", K(ret)); + } else { + *tmp_param = *param; + if (OB_FAIL(params_.push_back(tmp_param))) { + tmp_param->reset(); + tmp_param = NULL; + LOG_ERROR("fail to assign param", K(ret)); + } + } + } + } + return *this; +} + +int64_t ObProxyTextPsParam::to_string(char *buf, const int64_t buf_len) const { int64_t pos = 0; J_OBJ_START(); - J_KV(K_(str_value)); + J_KV(K_(str_value), K_(is_alloc)); J_OBJ_END(); return pos; } -int64_t ObProxyTextPsExecuteInfo::to_string(char *buf, const int64_t buf_len) const +int64_t ObProxyTextPsInfo::to_string(char *buf, const int64_t buf_len) const { int64_t pos = 0; J_OBJ_START(); @@ -759,6 +883,52 @@ int64_t ObProxyTextPsExecuteInfo::to_string(char *buf, const int64_t buf_len) co return pos; } +ObProxyTextPsInfo::ObProxyTextPsInfo(const ObProxyTextPsInfo &other) +{ + + int ret = OB_SUCCESS; + is_param_valid_ = other.is_param_valid_; + param_count_ = other.param_count_; + for (int64_t i = 0; OB_SUCC(ret) && i < param_count_; i++) { + ObProxyTextPsParam *param = other.params_.at(i); + ObProxyTextPsParam *tmp_param = NULL; + if (OB_FAIL(ObProxyTextPsParam::alloc_text_ps_param(param->str_value_.ptr(), param->str_value_.length(), tmp_param))) { + LOG_WARN("fai lto alloc text ps param", K(ret)); + } else { + *tmp_param = *param; + if (OB_FAIL(params_.push_back(tmp_param))) { + tmp_param->reset(); + tmp_param = NULL; + LOG_WARN("fail to push back text ps param", K(ret)); + } + } + } +} + +ObProxyTextPsInfo& ObProxyTextPsInfo::operator=(const ObProxyTextPsInfo &other) +{ + int ret = OB_SUCCESS; + if (this != &other) { + is_param_valid_ = other.is_param_valid_; + param_count_ = other.param_count_; + for (int64_t i = 0; OB_SUCC(ret) && i < param_count_; i++) { + ObProxyTextPsParam *param = other.params_.at(i); + ObProxyTextPsParam *tmp_param = NULL; + if (OB_FAIL(ObProxyTextPsParam::alloc_text_ps_param(param->str_value_.ptr(), param->str_value_.length(), tmp_param))) { + LOG_WARN("fai lto alloc text ps param", K(ret)); + } else { + *tmp_param = *param; + if (OB_FAIL(params_.push_back(tmp_param))) { + tmp_param->reset(); + tmp_param = NULL; + LOG_WARN("fail to push back text ps param", K(ret)); + } + } + } + } + return *this; +} + int64_t ObProxySimpleRouteInfo::to_string(char *buf, const int64_t buf_len) const { int64_t pos = 0; @@ -805,7 +975,7 @@ int64_t DbMeshRouteInfo::to_string(char *buf, const int64_t buf_len) const { int64_t pos = 0; J_OBJ_START(); - J_KV(K_(testload), K_(group_idx), K_(tb_idx), K_(es_idx), + J_KV(K_(testload), K_(group_idx), K_(tb_idx), K_(es_idx), K_(db_pos), K_(tb_pos), K_(index_tb_pos), K_(table_name), K_(disaster_status), K_(tnt_id)); J_OBJ_END(); return pos; @@ -816,7 +986,8 @@ int64_t SetVarNode::to_string(char* buf, const int64_t buf_len) const int64_t pos = 0; J_OBJ_START(); J_KV(K_(var_type), - K_(var_name)); + K_(var_name), + K_(is_alloc)); if (SET_VALUE_TYPE_INT == value_type_) { J_COMMA(); J_KV(K_(int_value)); @@ -896,6 +1067,7 @@ int ObProxySqlParser::parse_sql(const ObString &sql, drop_origin_db_table_name, is_sharding_request))) { LOG_INFO("fail to load result, will go on anyway", K(sql), K(use_lower_case_name), K(tmp_ret)); } else { + sql_parse_result.set_multi_semicolon_in_stmt(ObProxySqlParser::is_multi_semicolon_in_stmt(sql)); LOG_DEBUG("success to do proxy parse", K(sql_parse_result)); } @@ -1192,7 +1364,7 @@ int ObSqlParseResult::load_ob_parse_result(const ParseResult &parse_result, if (OB_ISNULL(buf = (char*)allocator_.alloc(sizeof(ObProxySelectStmt)))) { LOG_WARN("failed to alloc buf"); ret = OB_ALLOCATE_MEMORY_FAILED; - } else if (OB_ISNULL(select_stmt = new (buf) ObProxySelectStmt())) { + } else if (OB_ISNULL(select_stmt = new (buf) ObProxySelectStmt(allocator_))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to new ObProxySelectStmt", K(ret)); } else if (OB_FAIL(select_stmt->init())) { @@ -1200,18 +1372,90 @@ int ObSqlParseResult::load_ob_parse_result(const ParseResult &parse_result, } else { select_stmt->set_sql_string(sql); select_stmt->set_stmt_type(OBPROXY_T_SELECT); - select_stmt->set_allocator(&allocator_); - select_stmt->field_results_ = &fileds_result_; + select_stmt->set_field_results(&fileds_result_); select_stmt->set_table_name(origin_table_name_); proxy_stmt_ = select_stmt; if (OB_FAIL(proxy_stmt_->handle_parse_result(parse_result))) { - LOG_WARN("handle_parse_result failed", K(ret)); + LOG_WARN("handle select parse result failed", K(ret)); } else { has_for_update_ = select_stmt->has_for_update(); } } } break; + case T_INSERT: + if (need_handle_result) { + char* buf = NULL; + ObProxyInsertStmt* insert_stmt= NULL; + if (OB_ISNULL(buf = (char*)allocator_.alloc(sizeof(ObProxyInsertStmt)))) { + LOG_WARN("failed to alloc buf"); + ret = OB_ALLOCATE_MEMORY_FAILED; + } else if (OB_ISNULL(insert_stmt = new (buf) ObProxyInsertStmt(allocator_))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to new ObProxyInsertStmt", K(ret)); + } else if (OB_FAIL(insert_stmt->init())) { + LOG_WARN("init failed", K(ret)); + } else { + insert_stmt->set_sql_string(sql); + insert_stmt->set_stmt_type(OBPROXY_T_INSERT); + insert_stmt->set_field_results(&fileds_result_); + insert_stmt->set_table_name(origin_table_name_); + proxy_stmt_ = insert_stmt; + if (OB_FAIL(proxy_stmt_->handle_parse_result(parse_result))) { + LOG_WARN("handle Insert parse result failed", K(ret)); + } + } + } + break; + case T_DELETE: + if (need_handle_result) { + char* buf = NULL; + ObProxyDeleteStmt* delete_stmt= NULL; + if (OB_ISNULL(buf = (char*)allocator_.alloc(sizeof(ObProxyDeleteStmt)))) { + LOG_WARN("failed to alloc buf"); + ret = OB_ALLOCATE_MEMORY_FAILED; + } else if (OB_ISNULL(delete_stmt = new (buf) ObProxyDeleteStmt(allocator_))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to new ObProxyDeleteStmt", K(ret)); + } else if (OB_FAIL(delete_stmt->init())) { + LOG_WARN("init failed", K(ret)); + } else { + delete_stmt->set_sql_string(sql); + delete_stmt->set_stmt_type(OBPROXY_T_DELETE); + delete_stmt->set_field_results(&fileds_result_); + delete_stmt->set_table_name(origin_table_name_); + proxy_stmt_ = delete_stmt; + if (OB_FAIL(proxy_stmt_->handle_parse_result(parse_result))) { + LOG_WARN("handle delete parse result failed", K(ret)); + } + } + } + break; + //TODO + case T_UPDATE: + if (need_handle_result) { + char* buf = NULL; + ObProxyUpdateStmt* update_stmt= NULL; + if (OB_ISNULL(buf = (char*)allocator_.alloc(sizeof(ObProxyUpdateStmt)))) { + LOG_WARN("failed to alloc buf"); + ret = OB_ALLOCATE_MEMORY_FAILED; + } else if (OB_ISNULL(update_stmt = new (buf) ObProxyUpdateStmt(allocator_))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to new ObProxyUpdateStmt", K(ret)); + } else if (OB_FAIL(update_stmt->init())) { + LOG_WARN("init failed", K(ret)); + } else { + update_stmt->set_sql_string(sql); + update_stmt->set_stmt_type(OBPROXY_T_UPDATE); + update_stmt->set_field_results(&fileds_result_); + update_stmt->set_table_name(origin_table_name_); + proxy_stmt_ = update_stmt; + if (OB_FAIL(proxy_stmt_->handle_parse_result(parse_result))) { + LOG_WARN("handle update parse result failed", K(ret)); + } + } + } + break; default: LOG_DEBUG("node type", "node_type", get_type_name(node->type_)); } @@ -1264,6 +1508,182 @@ int ObProxySqlParser::parse_sql_by_obparser(const ObString &sql, return ret; } +// A simplified version from observer +int ObProxySqlParser::split_multiple_stmt(const ObString &stmt, + ObIArray &queries) +{ + int ret = OB_SUCCESS; + + int64_t offset = 0; + int64_t remain = stmt.length(); + + trim_multi_stmt(stmt, remain); + + // Special handling for empty statements + if (OB_UNLIKELY(0 >= remain)) { + ObString part; + ret = queries.push_back(part); + } + + while (remain > 0 && OB_SUCC(ret)) { + int64_t str_len = 0; + + //calc the end position of a single sql. + get_single_sql(stmt, offset, remain, str_len); + str_len = str_len == remain ? str_len : str_len + 1; + ObString query(static_cast(str_len), stmt.ptr() + offset); + + remain -= str_len; + offset += str_len; + + if (remain < 0 || offset > stmt.length()) { + LOG_ERROR("split_multiple_stmt data error", + K(remain), K(offset), K(stmt.length()), K(ret)); + } else if(OB_FAIL(queries.push_back(query))){ + LOG_WARN("fail to push back part of multi stmt", K(stmt), K(ret)); + } + } + + return ret; +} + +// avoid separeting sql by semicolons in quotes or comment. +void ObProxySqlParser::get_single_sql(const common::ObString &stmt, int64_t offset, int64_t remain, int64_t &str_len) { + /* following two flags are used to mark wether we are in comment, if in comment, ';' can't be used to split sql*/ + // in -- comment + bool comment_flag = false; + // in /*! comment */ or /* comment */ + bool c_comment_flag = false; + /* follwing three flags are used to mark wether we are in quotes.*/ + // in '', single quotes + bool sq_flag = false; + // in "", double quotes + bool dq_flag = false; + // in ``, backticks. + bool bt_flag = false; + //bool is_escape = false; + + bool in_comment = false; + bool in_string = false; + while (str_len < remain && (in_comment || in_string || (stmt[str_len + offset] != ';'))) { + if (!in_comment && !in_string) { + if (str_len + 1 >= remain) { + } else if ((stmt[str_len + offset] == '-' && stmt[str_len + offset + 1] == '-') || stmt[str_len + offset + 1] == '#') { + comment_flag = true; + } else if (stmt[str_len + offset] == '/' && stmt[str_len + offset + 1] == '*') { + c_comment_flag = true; + } else if (stmt[str_len + offset] == '\'') { + sq_flag = true; + } else if (stmt[str_len + offset] == '"') { + dq_flag = true; + } else if (stmt[str_len + offset] == '`') { + bt_flag = true; + } + } else if (in_comment) { + if (comment_flag) { + if (stmt[str_len + offset] == '\r' || stmt[str_len + offset] == '\n') { + comment_flag = false; + } + } else if (c_comment_flag) { + if (str_len + 1 >= remain) { + + } else if (stmt[str_len + offset] == '*' && (str_len + 1 < remain) && stmt[str_len + offset + 1] == '/') { + c_comment_flag = false; + } + } + } else if (in_string) { + if (str_len + 1 >= remain) { + } else if (!bt_flag && stmt[str_len + offset] == '\\') { + // in mysql mode, handle the escape char in '' and "" + ++ str_len; + } else if (sq_flag) { + if (stmt[str_len + offset] == '\'') { + sq_flag = false; + } + } else if (dq_flag) { + if (stmt[str_len + offset] == '"') { + dq_flag = false; + } + } else if (bt_flag) { + if (stmt[str_len + offset] == '`') { + bt_flag = false; + } + } + } + ++ str_len; + + // update states. + in_comment = comment_flag || c_comment_flag; + in_string = sq_flag || bt_flag || dq_flag; + } +} + +int ObProxySqlParser::preprocess_multi_stmt(ObArenaAllocator &allocator, + char* &multi_sql_buf, + const int64_t origin_sql_length, + ObSEArray &sql_array) +{ + int ret = OB_SUCCESS; + + const int64_t PARSE_EXTRA_CHAR_NUM = 2; + const int64_t total_sql_length = origin_sql_length + + (sql_array.count() * PARSE_EXTRA_CHAR_NUM); + + if (OB_ISNULL(multi_sql_buf = static_cast(allocator.alloc(total_sql_length)))) { + ret = OB_REACH_MEMORY_LIMIT; + LOG_WARN("fail to alloc memory for multi_sql_buf", K(ret), K(total_sql_length)); + } else { + MEMSET(multi_sql_buf, '\0', total_sql_length); + int64_t pos = 0; + for (int64_t i = 0; i < sql_array.count(); ++i) { + ObString& sql = sql_array.at(i); + MEMCPY(multi_sql_buf + pos ,sql.ptr(), sql.length()); + sql.assign_ptr(multi_sql_buf + pos, sql.length()); + pos += sql.length() + PARSE_EXTRA_CHAR_NUM; + } + } + + return ret; +} + +void ObProxySqlParser::trim_multi_stmt(const common::ObString &stmt, int64_t &remain) +{ + // Bypass parser's unfriendly approach to empty query processing: remove the trailing spaces by yourself + while (remain > 0 && ISSPACE(stmt[remain - 1])) { + --remain; + } + //Remove the last '\0' to be compatible with mysql + if (remain > 0 && '\0' == stmt[remain - 1]) { + --remain; + } + //remove trailing spaces + while (remain > 0 && ISSPACE(stmt[remain - 1])) { + --remain; + } +} + +bool ObProxySqlParser::is_multi_semicolon_in_stmt(const common::ObString &stmt) +{ + bool is_multi = false; + int64_t offset = 0; + int64_t remain = stmt.length(); + int64_t str_len = 0; + trim_multi_stmt(stmt, remain); + + // Special handling for empty statements + if (OB_UNLIKELY(0 >= remain)) { + } else { + get_single_sql(stmt, offset, remain, str_len); + remain -= str_len; + // 2: remain space for `;` and `\0` + if (remain > 2) { + is_multi = true; + } + } + return is_multi; +} + + int64_t ObParseNode::to_string(char *buf, const int64_t buf_len) const { int64_t pos = 0; @@ -1284,6 +1704,135 @@ int64_t ObParseNode::to_string(char *buf, const int64_t buf_len) const return pos; } +void ObProxyCallParam::reset() +{ + type_ = CALL_TOKEN_NONE; + str_value_.reset(); + if (is_alloc_) { + is_alloc_ = false; + ob_free(this); + } +} + +int ObProxyCallParam::alloc_call_param(ObProxyCallParam*& param) +{ + int ret = OB_SUCCESS; + char* buf = NULL; + int64_t alloc_size = sizeof(ObProxyCallParam); + ObMemAttr mem_attr; + mem_attr.mod_id_ = common::ObModIds::OB_PROXY_SQL_PARSE; + if (OB_ISNULL(buf = static_cast(ob_malloc(alloc_size, mem_attr)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc mem for call param", K(alloc_size), K(ret)); + } else { + param = new (buf) ObProxyCallParam(); + param->is_alloc_ = true; + } + return ret; +} + +void ObProxyTextPsParam::reset() +{ + str_value_.reset(); + if (is_alloc_) { + is_alloc_ = false; + ob_free(this); + } +} + +int ObProxyTextPsParam::alloc_text_ps_param(const char* str, const int str_len, ObProxyTextPsParam*& param) +{ + int ret = OB_SUCCESS; + char* buf = NULL; + int64_t alloc_size = sizeof(ObProxyTextPsParam); + param = NULL; + ObMemAttr mem_attr; + mem_attr.mod_id_ = ObModIds::OB_PROXY_SQL_PARSE; + if (OB_UNLIKELY(NULL == str || str_len <= 0)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(str), K(str_len), K(ret)); + } else if (OB_ISNULL(buf = static_cast(ob_malloc(alloc_size, mem_attr)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc mem for param", K(alloc_size), K(ret)); + } else { + param = new (buf) ObProxyTextPsParam(); + param->is_alloc_ = true; + } + + if (OB_SUCC(ret)) { + param->str_value_.set_value(str_len, str); + } + + if (OB_FAIL(ret) && NULL != param) { + param->reset(); + } + return ret; +} + +void SetVarNode::reset() +{ + value_type_ = SET_VALUE_TYPE_NONE; + var_type_ = SET_VAR_TYPE_NONE; + var_name_.reset(); + int_value_ = 0; + str_value_.reset(); + if (is_alloc_) { + is_alloc_ = false; + ob_free(this); + } +} + +int SetVarNode::alloc_var_node(SetVarNode*& node) +{ + int ret = OB_SUCCESS; + char* buf = NULL; + int64_t alloc_size = sizeof(SetVarNode); + ObMemAttr mem_attr; + mem_attr.mod_id_ = ObModIds::OB_PROXY_SQL_PARSE; + if (OB_ISNULL(buf = static_cast(ob_malloc(alloc_size, mem_attr)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc mem for var node", K(alloc_size), K(ret)); + } else { + node = new (buf) SetVarNode(); + node->is_alloc_ = true; + } + return ret; +} + +int SqlField::alloc_sql_field(SqlField*& field) +{ + int ret = OB_SUCCESS; + char* buf = NULL; + int64_t alloc_size = sizeof(SqlField); + ObMemAttr mem_attr; + mem_attr.mod_id_ = ObModIds::OB_PROXY_SQL_PARSE; + if (OB_ISNULL(buf = static_cast(ob_malloc(alloc_size, mem_attr)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc mem for call param", K(alloc_size), K(ret)); + } else { + field = new (buf) SqlField(); + field->is_alloc_ = true; + } + return ret; +} + +SqlField& SqlField::operator=(const SqlField& other) +{ + int ret = OB_SUCCESS; + if (this != &other) { + column_name_ = other.column_name_; + value_type_ = other.value_type_; + column_int_value_ = other.column_int_value_; + column_value_ = other.column_value_; + for (int i = 0; OB_SUCC(ret) && i < other.column_values_.count(); i++) { + if (OB_FAIL(column_values_.push_back(other.column_values_.at(i)))) { + LOG_WARN("fail to push back column values", K(ret)); + } + } + } + return *this; +} + } // end of namespace obutils } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/obutils/ob_proxy_sql_parser.h b/src/obproxy/obutils/ob_proxy_sql_parser.h index 9a763c992fb6e7dddd65b1024dc6d85d9a2f76a6..54bf0e8799d2f1e134fe1c78c75a404d294094e8 100644 --- a/src/obproxy/obutils/ob_proxy_sql_parser.h +++ b/src/obproxy/obutils/ob_proxy_sql_parser.h @@ -23,6 +23,8 @@ #include "common/ob_hint.h" #include "lib/utility/ob_print_utils.h" #include "utils/ob_proxy_lib.h" +#include "utils/ob_proxy_utils.h" +#include "utils/ob_target_db_server.h" #include "obutils/ob_proxy_string_utils.h" #include #include @@ -30,8 +32,8 @@ #define OBPROXY_MAX_STRING_VALUE_LENGTH 512 -#define OBPROXY_CALL_NODE_COUNT 20 -#define OBPROXY_TEXT_PS_EXECUTE_NODE_COUNT 20 +#define OBPROXY_CALL_NODE_COUNT 3 +#define OBPROXY_TEXT_PS_EXECUTE_NODE_COUNT 3 using namespace oceanbase::obproxy::opsql; @@ -65,10 +67,6 @@ struct ObInternalSelectBuf { char col_name_buf_[common::OB_MAX_COLUMN_NAME_LENGTH]; }; -struct ObTextPsBuf { - char text_ps_name_buf_[common::OB_MAX_TEXT_PS_NAME_LENGTH]; -}; - template class ObFixSizeString { public: @@ -76,6 +74,11 @@ public: ~ObFixSizeString() { string_.reset(); } int64_t get_max_size() const { return size - 2; } + inline const common::ObString& get_string() const + { + return string_; + } + ObFixSizeString(const ObFixSizeString &other) { *this = other; @@ -178,84 +181,72 @@ struct ObProxyCmdInfo struct ObProxyCallParam { - ObProxyCallParam() { reset(); } + ObProxyCallParam() : type_(CALL_TOKEN_NONE), str_value_(), is_alloc_(false) {} ~ObProxyCallParam() { reset(); } DECLARE_TO_STRING; - void reset() - { - type_ = CALL_TOKEN_NONE; - str_value_.reset(); - } - static int32_t get_fix_buf_size() { return OBPROXY_MAX_STRING_VALUE_LENGTH; } + void reset(); + static int alloc_call_param(ObProxyCallParam*& param); ObProxyCallTokenType type_; - ObFixSizeString str_value_; + ObProxyVariantString str_value_; + bool is_alloc_; }; struct ObProxyCallInfo { - ObProxyCallInfo() { reset(); } + ObProxyCallInfo() : params_(), param_count_(0), is_param_valid_(false) {} ~ObProxyCallInfo() { reset(); } + ObProxyCallInfo(const ObProxyCallInfo &other); DECLARE_TO_STRING; - ObProxyCallInfo& operator=(const ObProxyCallInfo &other) - { - if (this != &other) { - is_param_valid_ = other.is_param_valid_; - param_count_ = other.param_count_; - params_.assign(other.params_); - } - return *this; - } + ObProxyCallInfo& operator=(const ObProxyCallInfo &other); void reset() { + for (int64_t i = 0; i < param_count_; i++) { + ObProxyCallParam *param = params_.at(i); + param->reset(); + } param_count_ = 0; is_param_valid_ = false; params_.reset(); } bool is_valid() const { return is_param_valid_ && 0 <= param_count_; } - common::ObSEArray params_; + common::ObSEArray params_; int32_t param_count_; bool is_param_valid_;//whether size is valid }; -struct ObProxyTextPsExecuteParam +struct ObProxyTextPsParam { - ObProxyTextPsExecuteParam() { reset(); } - ~ObProxyTextPsExecuteParam() { reset(); } + ObProxyTextPsParam() : str_value_(), is_alloc_(false) { } + ~ObProxyTextPsParam() { reset(); } DECLARE_TO_STRING; - void reset() - { - str_value_.reset(); - } - static int32_t get_fix_buf_size() { return OBPROXY_MAX_STRING_VALUE_LENGTH; } - - ObFixSizeString str_value_; + void reset(); + static int alloc_text_ps_param(const char* str, const int str_len, ObProxyTextPsParam*& param); + ObProxyVariantString str_value_; + bool is_alloc_; }; -struct ObProxyTextPsExecuteInfo +struct ObProxyTextPsInfo { - ObProxyTextPsExecuteInfo() { reset(); } - ~ObProxyTextPsExecuteInfo() { reset(); } + ObProxyTextPsInfo() : params_(), param_count_(0), is_param_valid_(false) {} + ~ObProxyTextPsInfo() { reset(); } + ObProxyTextPsInfo(const ObProxyTextPsInfo &other); DECLARE_TO_STRING; - ObProxyTextPsExecuteInfo& operator=(const ObProxyTextPsExecuteInfo &other) - { - if (this != &other) { - is_param_valid_ = other.is_param_valid_; - param_count_ = other.param_count_; - params_.assign(other.params_); - } - return *this; - } + ObProxyTextPsInfo& operator=(const ObProxyTextPsInfo &other); void reset() { + for (int64_t i = 0; i < param_count_; i++) { + ObProxyTextPsParam *param = params_.at(i); + param->reset(); + } param_count_ = 0; is_param_valid_ = false; params_.reset(); } bool is_valid() const { return is_param_valid_ && 0 <= param_count_; } - common::ObSEArray params_; + common::ObSEArray params_; int32_t param_count_; bool is_param_valid_;//whether size is valid }; @@ -300,14 +291,16 @@ struct SqlColumnValue column_int_value_ = 0; column_value_.reset(); } - TO_STRING_KV(K_(value_type), K(column_int_value_), K(column_value_)); + TO_STRING_KV(K_(value_type), K_(column_int_value), K_(column_value)); ObProxyTokenType value_type_; int64_t column_int_value_; - ObFixSizeString column_value_; + ObProxyVariantString column_value_; }; struct SqlField { - SqlField() { reset(); } + SqlField() : column_name_(), column_values_(), value_type_(TOKEN_NONE), + column_int_value_(0), column_value_(), is_alloc_(false) {} + ~SqlField() { reset(); } void reset() { @@ -316,31 +309,26 @@ struct SqlField { column_int_value_ = 0; column_value_.reset(); column_values_.reset(); + if (is_alloc_) { + is_alloc_ = false; + ob_free(this); + } } DECLARE_TO_STRING; bool is_valid() const { return column_values_.count() > 0; } - SqlField& operator=(const SqlField& other) - { - if (this != &other) { - column_name_ = other.column_name_; - value_type_ = other.value_type_; - column_int_value_ = other.column_int_value_; - column_value_ = other.column_value_; - for (int i = 0; i < other.column_values_.count(); i++) { - column_values_.push_back(other.column_values_.at(i)); - } - } - return *this; - } + SqlField& operator=(const SqlField& other); + + static int alloc_sql_field(SqlField*& field); + ObProxyVariantString column_name_; - ObFixSizeString column_name_; common::ObSEArray column_values_; // TODO: erase deprecated ObProxyTokenType value_type_; int64_t column_int_value_; - obutils::ObProxyVariantString column_value_; + ObProxyVariantString column_value_; + bool is_alloc_; }; struct SqlFieldResult { @@ -349,13 +337,17 @@ struct SqlFieldResult { void reset() { + for (int64_t i = 0; i < field_num_; i++) { + SqlField* field = fields_.at(i); + field->reset(); + } field_num_ = 0; fields_.reset(); } DECLARE_TO_STRING; int field_num_; - common::ObSEArray fields_; + common::ObSEArray fields_; }; struct DbMeshRouteInfo { @@ -368,6 +360,7 @@ struct DbMeshRouteInfo { tb_idx_ = OBPROXY_MAX_DBMESH_ID; es_idx_ = OBPROXY_MAX_DBMESH_ID; testload_ = OBPROXY_MAX_DBMESH_ID; + db_pos_ = common::OB_INVALID_INDEX; tb_pos_ = common::OB_INVALID_INDEX; index_tb_pos_ = common::OB_INVALID_INDEX; table_name_.reset(); @@ -392,6 +385,7 @@ struct DbMeshRouteInfo { int64_t tb_idx_; int64_t es_idx_; int64_t testload_; + int64_t db_pos_; // dml database name pos int64_t tb_pos_; // dml table name pos, not hint table pos int64_t index_tb_pos_; // index table pos from hint common::ObString table_name_; @@ -403,40 +397,44 @@ struct DbMeshRouteInfo { }; struct SetVarNode { - SetVarNode() { reset(); } + SetVarNode() : var_name_(), int_value_(0), str_value_(), + value_type_(SET_VALUE_TYPE_NONE), + var_type_(SET_VAR_TYPE_NONE), is_alloc_(false) {} ~SetVarNode() { reset(); } - void reset() { - var_name_.reset(); - str_value_.reset(); - int_value_ = 0; - value_type_ = SET_VALUE_TYPE_ONE; - var_type_ = SET_VAR_TYPE_NONE; - } + void reset(); + static int alloc_var_node(SetVarNode*& node); DECLARE_TO_STRING; - ObFixSizeString var_name_; + ObProxyVariantString var_name_; int64_t int_value_; - ObFixSizeString str_value_; - + obutils::ObProxyVariantString str_value_; ObProxySetValueType value_type_; ObProxySetVarType var_type_; + bool is_alloc_; }; struct ObProxySetInfo { - ObProxySetInfo() { reset(); } + ObProxySetInfo() : node_count_(0), var_nodes_() {} ~ObProxySetInfo() { reset(); } void reset() { + for (int64_t i = 0; i < node_count_; i++) { + SetVarNode *node = var_nodes_.at(i); + node->reset(); + } node_count_ = 0; var_nodes_.reset(); } DECLARE_TO_STRING; int node_count_; - common::ObSEArray var_nodes_; + common::ObSEArray var_nodes_; + +private: + DISALLOW_COPY_AND_ASSIGN(ObProxySetInfo); }; struct DbpRouteInfo { @@ -448,6 +446,7 @@ struct DbpRouteInfo { has_group_info_ = false; group_idx_ = OBPROXY_MAX_DBMESH_ID; scan_all_ = false; + sticky_session_ = false; table_name_.reset(); has_shard_key_ = false; } @@ -460,11 +459,11 @@ struct DbpRouteInfo { bool is_group_info_valid() const { // table_name can be empty - return OBPROXY_MAX_DBMESH_ID != group_idx_ && group_idx_ >= 0 && !scan_all_; + return OBPROXY_MAX_DBMESH_ID != group_idx_ && group_idx_ >= 0 && !scan_all_ && !sticky_session_; } bool is_shard_key_valid() const { - return !scan_all_; + return !scan_all_ && !sticky_session_; } bool is_error_info() const @@ -483,6 +482,7 @@ struct DbpRouteInfo { bool has_group_info_; int64_t group_idx_; bool scan_all_; + bool sticky_session_; common::ObString table_name_; char table_name_str_[common::OB_MAX_TABLE_NAME_LENGTH]; bool has_shard_key_; @@ -516,7 +516,7 @@ typedef struct _ObProxyDualParseResult struct ObSqlParseResult { ObSqlParseResult() : allocator_(common::ObModIds::OB_PROXY_SHARDING_PARSE), - ob_parser_result_(NULL), proxy_stmt_(NULL) { reset(); } + text_ps_buf_(NULL), text_ps_buf_len_(0), target_db_server_(NULL), ob_parser_result_(NULL), proxy_stmt_(NULL) { reset(); } ~ObSqlParseResult() { reset(); } void clear_proxy_stmt(); void reset(bool is_reset_origin_db_table = true); @@ -546,7 +546,6 @@ struct ObSqlParseResult bool is_show_session_stmt() const { return OBPROXY_T_ICMD_SHOW_SESSION == stmt_type_; } bool is_select_tx_ro() const { return OBPROXY_T_SELECT_TX_RO == stmt_type_; } bool is_select_proxy_version() const { return OBPROXY_T_SELECT_PROXY_VERSION == stmt_type_; } - bool is_set_autocommit_0() const { return OBPROXY_T_SET_AC_0 == stmt_type_; } bool is_select_route_addr() const { return OBPROXY_T_SELECT_ROUTE_ADDR == stmt_type_; } bool is_set_route_addr() const { return OBPROXY_T_SET_ROUTE_ADDR == stmt_type_; } bool is_set_ob_read_consistency() const { return OBPROXY_T_SET_OB_READ_CONSISTENCY == stmt_type_; } @@ -562,7 +561,9 @@ struct ObSqlParseResult } bool is_show_databases_stmt() const { return OBPROXY_T_SHOW == stmt_type_ && OBPROXY_T_SUB_SHOW_DATABASES == cmd_sub_type_; } bool is_show_tables_stmt() const { return OBPROXY_T_SHOW == stmt_type_ && OBPROXY_T_SUB_SHOW_TABLES == cmd_sub_type_; } - bool is_show_create_table_stmt() const { return OBPROXY_T_SHOW == stmt_type_ && OBPROXY_T_SUB_SHOW_CREATE_TABLE == cmd_sub_type_; } + bool is_show_full_tables_stmt() const { return OBPROXY_T_SHOW == stmt_type_ && OBPROXY_T_SUB_SHOW_FULL_TABLES == cmd_sub_type_; } + bool is_show_table_status_stmt() const { return OBPROXY_T_SHOW == stmt_type_ && OBPROXY_T_SUB_SHOW_TABLE_STATUS == cmd_sub_type_; } + bool is_show_elastic_id_stmt() const { return OBPROXY_T_SHOW == stmt_type_ && OBPROXY_T_SUB_SHOW_ELASTIC_ID == cmd_sub_type_; } bool is_show_topology_stmt() const { return OBPROXY_T_SHOW == stmt_type_ && OBPROXY_T_SUB_SHOW_TOPOLOGY == cmd_sub_type_; } bool is_show_db_version_stmt() const { return OBPROXY_T_SHOW == stmt_type_ && OBPROXY_T_SUB_SHOW_DB_VERSION == cmd_sub_type_; } bool is_desc_table_stmt() const { return OBPROXY_T_DESC == stmt_type_ && OBPROXY_T_SUB_DESC_TABLE == cmd_sub_type_; } @@ -597,9 +598,20 @@ struct ObSqlParseResult || is_noaudit_stmt(); } - bool is_text_ps_stmt() const { return is_text_ps_prepare_stmt() || is_text_ps_execute_stmt(); } + bool is_text_ps_stmt() const { return is_text_ps_prepare_stmt() || is_text_ps_execute_stmt() || is_text_ps_drop_stmt(); } bool is_text_ps_prepare_stmt() const { return OBPROXY_T_TEXT_PS_PREPARE == stmt_type_; } bool is_text_ps_execute_stmt() const { return OBPROXY_T_TEXT_PS_EXECUTE == stmt_type_; } + bool is_text_ps_drop_stmt() const { return OBPROXY_T_TEXT_PS_DROP == stmt_type_; } + + bool is_binlog_stmt() const + { + return OBPROXY_T_SHOW_MASTER_STATUS == stmt_type_ + || OBPROXY_T_SHOW_BINARY_LOGS == stmt_type_ + || OBPROXY_T_SHOW_BINLOG_EVENTS == stmt_type_ + || OBPROXY_T_PURGE_BINARY_LOGS == stmt_type_ + || OBPROXY_T_RESET_MASTER == stmt_type_ + || OBPROXY_T_SHOW_BINLOG_SERVER_FOR_TENANT == stmt_type_; + } bool is_internal_select() const { return is_select_tx_ro() || is_select_proxy_version(); } bool is_dual_request() const {return is_dual_request_;} @@ -624,6 +636,7 @@ struct ObSqlParseResult bool is_shard_special_cmd() const; + bool is_multi_semicolon_in_stmt() const { return is_multi_semicolon_in_stmt_; } bool has_last_insert_id() const { return has_last_insert_id_; } bool has_found_rows() const { return has_found_rows_; } bool has_row_count() const { return has_row_count_; } @@ -639,6 +652,7 @@ struct ObSqlParseResult bool has_show_warnings() const { return is_show_warnings_stmt(); } bool need_hold_start_trans() const { return is_start_trans_stmt(); } + bool need_hold_xa_start() const { return is_xa_start_stmt_; } // has a function depend on the sql last executed, such as found_rows , row_count, etc. bool has_dependent_func() const; // whether a sql is not supported by PROXY (BUT it is supported by observer) @@ -664,6 +678,9 @@ struct ObSqlParseResult const common::ObString get_trace_id() const { return trace_id_; } const common::ObString get_rpc_id() const { return rpc_id_; } + // route server addrs in sql comment + ObTargetDbServer* get_target_db_server() const { return target_db_server_; } + char *get_table_name_str() { return table_name_.ptr(); } int64_t get_table_name_length() const { return table_name_.length(); } char *get_package_name_str() { return package_name_.ptr(); } @@ -681,6 +698,7 @@ struct ObSqlParseResult void set_stmt_type(const ObProxyBasicStmtType type) { stmt_type_ = type; } void set_err_stmt_type(const ObProxyErrorStmtType type) { cmd_err_type_ = type; } + void set_xa_start_stmt(bool is_xa_start) { is_xa_start_stmt_ = is_xa_start; } int set_db_name(const ObProxyParseString &database_name, const bool use_lower_case_name = false, const bool drop_origin_db_table_name = false); @@ -694,7 +712,8 @@ struct ObSqlParseResult int set_simple_route_info(const ObProxyParseResult &parse_result); int set_dbmesh_route_info(const ObProxyParseResult &obproxy_parse_result); int set_var_info(const ObProxyParseResult &parse_result); - int set_text_ps_execute_info(const ObProxyTextPsExecuteParseInfo &execute_parse_info); + int set_text_ps_info(ObProxyTextPsInfo& text_ps_info, const ObProxyTextPsParseInfo &execute_parse_info); + void set_multi_semicolon_in_stmt(bool is_multi_semicolon_in_stmt) {is_multi_semicolon_in_stmt_ = is_multi_semicolon_in_stmt;} int load_result(const ObProxyParseResult &obproxy_parse_result, const bool use_lower_case_name = false, const bool save_origin_db_table_name = false, @@ -724,7 +743,7 @@ struct ObSqlParseResult cmd_info_ = other.cmd_info_; call_info_ = other.call_info_; route_info_ = other.route_info_; - text_ps_execute_info_ = other.text_ps_execute_info_; + text_ps_info_ = other.text_ps_info_; has_last_insert_id_ = other.has_last_insert_id_; has_found_rows_ = other.has_found_rows_; has_row_count_ = other.has_row_count_; @@ -732,6 +751,7 @@ struct ObSqlParseResult has_simple_route_info_ = other.has_simple_route_info_; has_anonymous_block_ = other.has_anonymous_block_; has_for_update_ = other.has_for_update_; + is_xa_start_stmt_ = other.is_xa_start_stmt_; stmt_type_ = other.stmt_type_; hint_query_timeout_ = other.hint_query_timeout_; parsed_length_ = other.parsed_length_; @@ -740,7 +760,6 @@ struct ObSqlParseResult hint_consistency_level_ = other.hint_consistency_level_; dml_buf_ = other.dml_buf_; internal_select_buf_ = other.internal_select_buf_; - text_ps_buf_ = other.text_ps_buf_; part_name_buf_ = other.part_name_buf_; table_name_quote_ = other.table_name_quote_; package_name_quote_ = other.package_name_quote_; @@ -748,13 +767,27 @@ struct ObSqlParseResult alias_name_quote_ = other.alias_name_quote_; col_name_quote_ = other.col_name_quote_; text_ps_inner_stmt_type_ = other.text_ps_inner_stmt_type_; + is_multi_semicolon_in_stmt_ = other.is_multi_semicolon_in_stmt_; table_name_.assign_ptr(dml_buf_.table_name_buf_, other.table_name_.length()); package_name_.assign_ptr(dml_buf_.package_name_buf_, other.package_name_.length()); database_name_.assign_ptr(dml_buf_.database_name_buf_, other.database_name_.length()); alias_name_.assign_ptr(dml_buf_.alias_name_buf_, other.alias_name_.length()); col_name_.assign_ptr(internal_select_buf_.col_name_buf_, other.col_name_.length()); part_name_.assign_ptr(part_name_buf_.part_name_buf_, other.part_name_.length()); - text_ps_name_.assign_ptr(text_ps_buf_.text_ps_name_buf_, other.text_ps_name_.length()); + if (NULL != text_ps_buf_) { + allocator_.free(text_ps_buf_); + text_ps_buf_ = NULL; + text_ps_buf_len_ = 0; + } + if (NULL != other.text_ps_buf_ && other.text_ps_buf_len_ > 0) { + if (OB_ISNULL(text_ps_buf_ = static_cast(allocator_.alloc(other.text_ps_buf_len_)))) { + PROXY_LOG(WARN, "fail to alloc mem", K(other.text_ps_buf_len_)); + } else { + MEMCPY(text_ps_buf_, other.text_ps_buf_, other.text_ps_buf_len_); + text_ps_buf_len_ = other.text_ps_buf_len_; + text_ps_name_.assign_ptr(text_ps_buf_, text_ps_buf_len_); + } + } /* some sharding variablies do not copy */ has_shard_comment_ = other.has_shard_comment_; @@ -766,6 +799,18 @@ struct ObSqlParseResult trace_id_.assign_ptr(trace_id_buf_, other.trace_id_.length()); MEMCPY(rpc_id_buf_, other.rpc_id_buf_, other.rpc_id_.length()); rpc_id_.assign_ptr(rpc_id_buf_, other.rpc_id_.length()); + + // copy target db server in sql comment + if (OB_ISNULL(other.target_db_server_)) { + if (OB_NOT_NULL(target_db_server_)) { + op_free(target_db_server_); + target_db_server_ = NULL; + } + } else if (OB_ISNULL(target_db_server_) && OB_ISNULL(target_db_server_ = op_alloc(ObTargetDbServer))) { + PROXY_LOG(WARN, "fail to alloc memory for target db server"); + } else { + *target_db_server_ = *other.target_db_server_; + } } return *this; } @@ -790,6 +835,7 @@ struct ObSqlParseResult database_name_quote_ = other.database_name_quote_; alias_name_quote_ = other.alias_name_quote_; col_name_quote_ = other.col_name_quote_; + is_multi_semicolon_in_stmt_ = other.is_multi_semicolon_in_stmt_; table_name_.assign_ptr(dml_buf_.table_name_buf_, other.table_name_.length()); package_name_.assign_ptr(dml_buf_.package_name_buf_, other.package_name_.length()); database_name_.assign_ptr(dml_buf_.database_name_buf_, other.database_name_.length()); @@ -807,12 +853,24 @@ struct ObSqlParseResult trace_id_.assign_ptr(trace_id_buf_, other.trace_id_.length()); MEMCPY(rpc_id_buf_, other.rpc_id_buf_, other.rpc_id_.length()); rpc_id_.assign_ptr(rpc_id_buf_, other.rpc_id_.length()); + + // copy target db server addr in sql comment + if (OB_ISNULL(other.target_db_server_)) { + if (OB_NOT_NULL(target_db_server_)) { + op_free(target_db_server_); + target_db_server_ = NULL; + } + } else if (OB_ISNULL(target_db_server_) && OB_ISNULL(target_db_server_ = op_alloc(ObTargetDbServer))) { + PROXY_LOG(WARN, "fail to alloc memory target db server"); + } else { + *target_db_server_ = *other.target_db_server_; + } } ObProxyCmdInfo cmd_info_; ObProxyCallInfo call_info_; ObProxySimpleRouteInfo route_info_; - ObProxyTextPsExecuteInfo text_ps_execute_info_; + ObProxyTextPsInfo text_ps_info_; oceanbase::common::ObArenaAllocator allocator_; private: bool has_last_insert_id_; @@ -824,6 +882,7 @@ private: bool is_dual_request_; bool has_anonymous_block_; bool has_for_update_; + bool is_xa_start_stmt_; ObProxyBasicStmtType stmt_type_; int64_t hint_query_timeout_; int64_t parsed_length_; // next parser can starts with (orig_sql + parsed_length_) @@ -852,7 +911,8 @@ private: ObPartNameBuf part_name_buf_; // text ps common::ObString text_ps_name_; - ObTextPsBuf text_ps_buf_; + char* text_ps_buf_; + int32_t text_ps_buf_len_; ObProxyBasicStmtType text_ps_inner_stmt_type_; common::ObString trace_id_; @@ -860,6 +920,8 @@ private: common::ObString rpc_id_; char rpc_id_buf_[common::OB_MAX_OBPROXY_TRACE_ID_LENGTH]; + ObTargetDbServer *target_db_server_; + SqlFieldResult fileds_result_; int64_t batch_insert_values_count_; DbMeshRouteInfo dbmesh_route_info_; @@ -868,6 +930,7 @@ private: bool use_dbp_hint_; ObProxyDualParseResult dual_result_; ObDmlBuf origin_dml_buf_; + bool is_multi_semicolon_in_stmt_; // buffer holder union { @@ -913,6 +976,15 @@ public: oceanbase::common::ObArenaAllocator &allocator); static int init_ob_parser_node(oceanbase::common::ObArenaAllocator &allocator, ObParseNode *&ob_node); static int get_parse_allocator(common::ObArenaAllocator *&allocator); + static int split_multiple_stmt(const common::ObString &stmt, + common::ObIArray &queries); + static void get_single_sql(const common::ObString &stmt, int64_t offset, int64_t remain, int64_t &str_len); + static int preprocess_multi_stmt(common::ObArenaAllocator &allocator, + char* &multi_sql_buf, + const int64_t origin_sql_length, + common::ObSEArray &sql_array); + static void trim_multi_stmt(const common::ObString &stmt, int64_t &remain); + static bool is_multi_semicolon_in_stmt(const common::ObString &stmt); }; inline void ObSqlParseResult::reset(bool is_reset_origin_db_table /* true */) @@ -926,6 +998,7 @@ inline void ObSqlParseResult::reset(bool is_reset_origin_db_table /* true */) is_dual_request_ = false; has_anonymous_block_ = false; has_for_update_ = false; + is_xa_start_stmt_ = false; stmt_type_ = OBPROXY_T_INVALID; cmd_sub_type_ = OBPROXY_T_SUB_INVALID; cmd_err_type_ = OBPROXY_T_ERR_INVALID; @@ -940,6 +1013,11 @@ inline void ObSqlParseResult::reset(bool is_reset_origin_db_table /* true */) part_name_.reset(); trace_id_.reset(); rpc_id_.reset(); + + if (OB_NOT_NULL(target_db_server_)) { + op_free(target_db_server_); + target_db_server_ = NULL; + } if (is_reset_origin_db_table) { origin_table_name_.reset(); @@ -951,12 +1029,14 @@ inline void ObSqlParseResult::reset(bool is_reset_origin_db_table /* true */) cmd_info_.reset(); call_info_.reset(); route_info_.reset(); - text_ps_execute_info_.reset(); + text_ps_info_.reset(); table_name_quote_ = OBPROXY_QUOTE_T_INVALID; package_name_quote_ = OBPROXY_QUOTE_T_INVALID; database_name_quote_ = OBPROXY_QUOTE_T_INVALID; alias_name_quote_ = OBPROXY_QUOTE_T_INVALID; col_name_quote_ = OBPROXY_QUOTE_T_INVALID; + text_ps_buf_ = NULL; + text_ps_buf_len_ = 0; text_ps_name_.reset(); text_ps_inner_stmt_type_ = OBPROXY_T_INVALID; @@ -971,6 +1051,7 @@ inline void ObSqlParseResult::reset(bool is_reset_origin_db_table /* true */) col_name_quote_ = OBPROXY_QUOTE_T_INVALID; dbp_route_info_.reset(); use_dbp_hint_ = false; + is_multi_semicolon_in_stmt_ = false; ob_parser_result_ = NULL; //TODO check delete it } @@ -1064,7 +1145,6 @@ inline bool ObSqlParseResult::is_internal_request() const { return (is_not_supported() || is_internal_select() - || is_set_autocommit_0() || is_set_route_addr() || is_select_route_addr() || is_ping_proxy_cmd()); @@ -1081,6 +1161,7 @@ inline bool ObSqlParseResult::is_shard_special_cmd() const || is_use_db_stmt() || is_show_databases_stmt() || is_show_db_version_stmt() + || is_show_elastic_id_stmt() || is_show_topology_stmt()); } @@ -1103,7 +1184,6 @@ inline bool ObSqlParseResult::is_need_resp_ok_cmd() const { return (is_set_stmt() || is_start_trans_stmt() - || is_set_autocommit_0() || is_commit_stmt() || is_rollback_stmt()); } diff --git a/src/obproxy/obutils/ob_proxy_stmt.cpp b/src/obproxy/obutils/ob_proxy_stmt.cpp index 70277b706975a9432ec553e90e5739df6ceed785..b61a71523cf72950649d2ead6ccceebfbe77de4b 100644 --- a/src/obproxy/obutils/ob_proxy_stmt.cpp +++ b/src/obproxy/obutils/ob_proxy_stmt.cpp @@ -22,32 +22,22 @@ namespace obproxy { namespace obutils { -int ObProxyDMLStmt::condition_exprs_to_sql_string(common::ObSqlString& sql_string) + +ObProxyDMLStmt::ObProxyDMLStmt(common::ObIAllocator& allocator): ObProxyStmt(allocator), limit_offset_(0), limit_size_(-1), limit_token_off_(-1), dml_field_results_(), comments_(), + column_name_array_(), table_name_(), is_inited_(false), has_unsupport_expr_type_(false), table_pos_array_(), has_rollup_(false), has_for_update_(false), from_token_off_(-1), t_case_level_(0) { - UNUSED(sql_string); - int ret = OB_SUCCESS; - return ret; + field_results_ = &dml_field_results_; } -int ObProxyDMLStmt::limit_to_sql_string(common::ObSqlString& sql_string) +ObProxyDMLStmt::~ObProxyDMLStmt() { - int ret = OB_SUCCESS; - if (limit_size_ > 0) { - if (OB_FAIL(sql_string.append_fmt(" LIMIT %d, %d", limit_offset_, limit_size_))) { - LOG_WARN("fail to append", K(ret)); - } + ExprMap::iterator iter = table_exprs_map_.begin(); + ExprMap::iterator end = table_exprs_map_.end(); + for (; iter != end; iter++) { + ObProxyExpr *expr = iter->second; + expr->~ObProxyExpr(); } - return ret; -} -ObProxySelectStmt::ObProxySelectStmt() : is_inited_(false), has_rollup_(false), - has_for_update_(false), has_unsupport_expr_type_(false), - from_token_off_(-1) -{ - -} -ObProxySelectStmt::~ObProxySelectStmt() -{ for (int64_t i = 0; i < select_exprs_.count(); i++) { ObProxyExpr *expr = select_exprs_.at(i); expr->~ObProxyExpr(); @@ -63,18 +53,11 @@ ObProxySelectStmt::~ObProxySelectStmt() order_expr->~ObProxyOrderItem(); } - ExprMap::iterator iter = table_exprs_map_.begin(); - ExprMap::iterator end = table_exprs_map_.end(); - for (; iter != end; iter++) { - ObProxyExpr *expr = iter->second; - expr->~ObProxyExpr(); - } - table_exprs_map_.destroy(); alias_table_map_.destroy(); } -int ObProxySelectStmt::init() +int ObProxyDMLStmt::init() { int ret = OB_SUCCESS; if (is_inited_) { @@ -90,222 +73,332 @@ int ObProxySelectStmt::init() return ret; } -int ObProxySelectStmt::handle_parse_result(const ParseResult &parse_result) +ObProxyExprType ObProxyDMLStmt::get_expr_type_by_node_type(const ObItemType& item_type) +{ + ObProxyExprType expr_type = OB_PROXY_EXPR_TYPE_NONE; + switch(item_type) { + case T_OP_ADD: + expr_type = OB_PROXY_EXPR_TYPE_FUNC_ADD; + break; + case T_OP_MINUS: + expr_type = OB_PROXY_EXPR_TYPE_FUNC_SUB; + break; + case T_OP_MUL: + expr_type = OB_PROXY_EXPR_TYPE_FUNC_MUL; + break; + case T_OP_DIV: + expr_type = OB_PROXY_EXPR_TYPE_FUNC_DIV; + break; + case T_FUN_SUM: + expr_type = OB_PROXY_EXPR_TYPE_FUNC_SUM; + break; + case T_FUN_MAX: + expr_type = OB_PROXY_EXPR_TYPE_FUNC_MAX; + break; + case T_FUN_MIN: + expr_type = OB_PROXY_EXPR_TYPE_FUNC_MIN; + break; + case T_FUN_COUNT: + expr_type = OB_PROXY_EXPR_TYPE_FUNC_COUNT; + break; + case T_FUN_AVG: + expr_type = OB_PROXY_EXPR_TYPE_FUNC_AVG; + break; + default: + break; + } + return expr_type; +} + +int ObProxyDMLStmt::get_expr_by_type(ObProxyExpr* &expr, ObProxyExprType type) +{ + int ret = OB_SUCCESS; + char* buf = NULL; +#define ALLOC_PROXY_EXPR_BY_TYPE(ExprClass) \ + if (OB_ISNULL(buf = (char*)(allocator_.alloc(sizeof(ExprClass))))) { \ + ret = OB_ALLOCATE_MEMORY_FAILED; \ + LOG_WARN("fail to alloc mem", K(ret)); \ + } else if (OB_ISNULL(expr = new (buf)ExprClass())) { \ + ret = OB_ALLOCATE_MEMORY_FAILED; \ + LOG_WARN("fail to new expr", K(ret)); \ + } else { \ + expr->set_expr_type(type);\ + } + + switch(type) { + case OB_PROXY_EXPR_TYPE_CONST: + ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprConst); + break; + case OB_PROXY_EXPR_TYPE_SHARDING_CONST: + ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprShardingConst); + break; + case OB_PROXY_EXPR_TYPE_TABLE: + ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprTable); + break; + case OB_PROXY_EXPR_TYPE_COLUMN: + ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprColumn); + break; + case OB_PROXY_EXPR_TYPE_STAR: + ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprStar); + break; + case OB_PROXY_EXPR_TYPE_FUNC_ADD: + ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprAdd); + break; + case OB_PROXY_EXPR_TYPE_FUNC_SUB: + ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprSub); + break; + case OB_PROXY_EXPR_TYPE_FUNC_MUL: + ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprMul); + break; + case OB_PROXY_EXPR_TYPE_FUNC_DIV: + ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprDiv); + break; + case OB_PROXY_EXPR_TYPE_FUNC_SUM: + ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprSum); + break; + case OB_PROXY_EXPR_TYPE_FUNC_COUNT: + ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprCount); + break; + case OB_PROXY_EXPR_TYPE_FUNC_AVG: + ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprAvg); + break; + case OB_PROXY_EXPR_TYPE_FUNC_MAX: + ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprMax); + break; + case OB_PROXY_EXPR_TYPE_FUNC_MIN: + ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprMin); + break; + case OB_PROXY_EXPR_TYPE_FUNC_ORDER: + ALLOC_PROXY_EXPR_BY_TYPE(ObProxyOrderItem); + break; + case OB_PROXY_EXPR_TYPE_FUNC_GROUP: + ALLOC_PROXY_EXPR_BY_TYPE(ObProxyGroupItem); + break; + default: + has_unsupport_expr_type_ = true; + LOG_WARN("unexpected type", K(type)); + break; + } + return ret; +} + +int ObProxyDMLStmt::handle_from_list(ParseNode* node) { int ret = OB_SUCCESS; ParseNode* tmp_node = NULL; - ParseNode* node = parse_result.result_tree_->children_[0]; for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { tmp_node = node->children_[i]; if (NULL == tmp_node) { // do nothing - } else if (i == PARSE_SELECT_HAVING) { - has_unsupport_expr_type_ = true; - LOG_WARN("having not support", K(ret), K(sql_string_)); } else { switch(tmp_node->type_) { - case T_FROM_LIST: - from_token_off_ = tmp_node->token_off_; - ret = handle_from_list(tmp_node); + case T_ORG: + case T_ALIAS: + if (OB_FAIL(handle_table_node_to_expr(tmp_node))) { + LOG_WARN("fail to handle table node to expr", K(sql_string_), K(ret)); + } + break; + case T_OP_EQ: + case T_OP_IN: + if (OB_FAIL(handle_column_and_value(tmp_node))) { + LOG_WARN("fail to handle where node", K(sql_string_), K(ret)); + } + break; + case T_COLUMN_REF: { + ObProxyExprTable* expr_table = NULL; + ObProxyExpr* expr = NULL; + if (OB_FAIL(column_ref_to_expr(tmp_node, expr, expr_table))) { + LOG_WARN("fail to column ref to expr", K(ret)); + } + if (OB_NOT_NULL(expr)) { + expr->~ObProxyExpr(); + } break; + } default: + if (OB_FAIL(handle_from_list(tmp_node))) { + LOG_WARN("fail to handle from list", K(sql_string_), K(ret)); + } break; } } } + return ret; +} +int ObProxyDMLStmt::handle_table_node_to_expr(ParseNode* node) +{ + int ret = OB_SUCCESS; + ParseNode* tmp_node = NULL; + ObProxyExprTable* expr_table = NULL; + bool is_sub_query = false; for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { tmp_node = node->children_[i]; if (NULL == tmp_node) { - // do nothing + //do nothing } else { switch(tmp_node->type_) { - case T_HINT_OPTION_LIST: - ret = handle_hint_clause(tmp_node); - break; - case T_PROJECT_LIST: - ret = handle_project_list(tmp_node); - break; - case T_FROM_LIST: - break; - case T_WHERE_CLAUSE: - ret = handle_where_clause(tmp_node); - break; - case T_GROUPBY_CLAUSE: - ret = handle_groupby_clause(tmp_node); - break; - case T_ORDER_BY: - ret = handle_orderby_clause(tmp_node); + case T_RELATION_FACTOR: + if (OB_FAIL(get_table_and_db_expr(tmp_node, expr_table))) { + LOG_WARN("fail to get table expr", K(ret)); + } break; - case T_COMMA_LIMIT_CLAUSE: - case T_LIMIT_CLAUSE: - ret = handle_limit_clause(tmp_node); + case T_IDENT: + if (is_sub_query) { + // skip alias + } else if (OB_ISNULL(expr_table)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to get expr table", K(ret)); + } else if (OB_UNLIKELY(NULL == tmp_node->str_value_ || 0 >= tmp_node->str_len_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("alias token meet some wrong", "str len", tmp_node->str_len_, K(ret)); + } else { + ObString alias_table(static_cast(tmp_node->str_len_), tmp_node->str_value_); + if (OB_FAIL(alias_table_map_.set_refactored(alias_table, expr_table))) { + LOG_WARN("fail to add alias table set", K(alias_table), K(ret)); + } + } break; - case T_SFU_INT: - has_for_update_ = true; + case T_SELECT: + if (OB_FAIL(do_handle_parse_result(tmp_node))) { + LOG_WARN("fail to do handle parse result", "node_type", get_type_name(tmp_node->type_), K(ret)); + } else { + is_sub_query = true; + } break; - case T_QEURY_EXPRESSION_LIST: //distinct not support now default: has_unsupport_expr_type_ = true; - LOG_WARN("unsupport type", "node_type", get_type_name(tmp_node->type_), K(sql_string_), K(ret)); + LOG_WARN("unsupport type", "node_type", get_type_name(node->type_), K(node->str_value_)); } } } - if (OB_SUCC(ret) && OB_FAIL(handle_comment_list(parse_result))) { - LOG_WARN("handle_comment_list failed", K(ret), K(sql_string_)); - } - return ret; -} -int ObProxySelectStmt::handle_comment_list(const ParseResult &parse_result) -{ - int ret = OB_SUCCESS; - for (int i = 0; OB_SUCC(ret) && i < parse_result.comment_cnt_; i++) { - TokenPosInfo& token_info = parse_result.comment_list_[i]; - ObString comment(token_info.token_len_, sql_string_.ptr() + token_info.token_off_); - if (OB_FAIL(comments_.push_back(comment))) { - LOG_WARN("push_back failed", K(ret), K(comment), K(sql_string_)); - } else { - LOG_DEBUG("push_back succ", K(comment)); - } - } - return ret; -} -int ObProxySelectStmt::comments_to_sql_string(common::ObSqlString& sql_string) -{ - int ret = OB_SUCCESS; - for (int i = 0; OB_SUCC(ret) && i < comments_.count(); i++) { - if (OB_FAIL(sql_string.append(comments_.at(i)))) { - LOG_WARN("fail to append", K(ret), K(i), K(comments_.at(i)), K(sql_string_)); - } - } return ret; } -int ObProxySelectStmt::hint_exprs_to_sql_string(common::ObSqlString& sql_string) -{ - UNUSED(sql_string); - int ret = OB_SUCCESS; - return ret; -} -int ObProxySelectStmt::select_exprs_to_sql_string(common::ObSqlString& sql_string) +int ObProxyDMLStmt::get_table_and_db_expr(ParseNode* node, ObProxyExprTable* &expr_table) { int ret = OB_SUCCESS; - if (select_exprs_.count() < 1) { + + ObObj obj; + ParseNode* table_node = NULL; + ParseNode* db_node = NULL; + ObProxyExpr* expr = NULL; + if (OB_ISNULL(node)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_T_RELATION_FACTOR_NUM_CHILD /* 2 */ != node->num_child_) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid select_exprs_ count", K(select_exprs_.count()), K(sql_string_)); - } else { - for (int64_t i = 0; OB_SUCC(ret) && i < select_exprs_.count(); i++) { - if (OB_FAIL(select_exprs_.at(i)->to_sql_string(sql_string))) { - LOG_WARN("to sql_string failed", K(i), K(ret), K(sql_string_)); - } else if (i >= select_exprs_.count() - 1) { - // no need add , do nothing - } else if (OB_FAIL(sql_string.append(", "))) { - LOG_WARN("fail to append", K(i), K(ret), K(sql_string_)); - } - } - } - return ret; -} -int ObProxySelectStmt::table_exprs_to_sql_string(common::ObSqlString& sql_string) -{ - UNUSED(sql_string); - int ret = OB_SUCCESS; - return ret; -} -int ObProxySelectStmt::group_by_exprs_to_sql_string(common::ObSqlString& sql_string) -{ - int ret = OB_SUCCESS; - if (group_by_exprs_.count() <= 0) { - // do nothing - } else if (OB_FAIL(sql_string.append(" GROUP BY "))) { - LOG_WARN("fail to append", K(ret), K(sql_string_)); + LOG_WARN("T_RELATION_FACTOR children node is not 2", K(node->num_child_), K(ret)); + } else if (FALSE_IT(db_node = node->children_[0])) { + } else if (NULL != db_node + && OB_UNLIKELY(T_IDENT != db_node->type_ || NULL == db_node->str_value_ || 0 >= db_node->str_len_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("T_RELATION_FACTOR unexpected table entry", "node type", db_node->type_, + "str len", db_node->str_len_, K(ret)); + } else if (OB_ISNULL(table_node = node->children_[1])) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_UNLIKELY(T_IDENT != table_node->type_ || NULL == table_node->str_value_ || 0 >= table_node->str_len_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("T_RELATION_FACTOR unexpected table entry", "node type", table_node->type_, + "str len", table_node->str_len_, K(ret)); } else { - for (int i = 0; OB_SUCC(ret) && i < group_by_exprs_.count(); i++) { - if (OB_FAIL(group_by_exprs_.at(i)->to_sql_string(sql_string))) { - LOG_WARN("to sql_string failed", K(i), K(ret), K(sql_string_)); - } else if (i >= group_by_exprs_.count() - 1) { - // no need add , do nothing - } else if (OB_FAIL(sql_string.append(", "))) { - LOG_WARN("append failed", K(i), K(ret), K(sql_string_)); + ObString table_name(static_cast(table_node->str_len_), table_node->str_value_); + string_to_upper_case(table_name.ptr(), table_name.length()); // change all to upper to store + if (OB_FAIL(table_exprs_map_.get_refactored(table_name, expr))) { /* same table keep last one. */ + if (OB_HASH_NOT_EXIST == ret) { + if(table_name_.empty()) + table_name_ = table_name; // set 'table_name_' be the first table name in SQL, and convert to UPPER CASE + if (OB_FAIL(get_expr_by_type(expr, OB_PROXY_EXPR_TYPE_TABLE))) { + LOG_WARN("get_expr_by_type failed", K(ret)); + } else if (OB_ISNULL(expr_table = dynamic_cast(expr))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("dynamic_cast failed", K(ret)); + } else { + if (NULL != db_node) { + ObString database_name(static_cast(db_node->str_len_), db_node->str_value_); + string_to_upper_case(database_name.ptr(), database_name.length()); // change all to upper to store + expr_table->set_database_name(db_node->str_value_, static_cast(db_node->str_len_)); + } + expr_table->set_table_name(table_node->str_value_, static_cast(table_node->str_len_)); + + if (OB_FAIL(table_exprs_map_.set_refactored(table_name, expr_table))) { /* same table keep last one. */ + LOG_WARN("fail to add table expr", K(table_name), K(ret)); + } + } + } else { + LOG_WARN("fail to get table expr", K(table_name), K(ret)); } - } - if (OB_SUCC(ret) && has_rollup_) { - if (OB_FAIL(sql_string.append(" WITH ROLLUP"))) { - LOG_WARN("append failed", K(ret), K(sql_string_)); + } else { + if (OB_ISNULL(expr_table = dynamic_cast(expr))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("dynamic_cast failed", K(ret)); + } else if (NULL != db_node && expr_table->get_database_name().empty()) { + ObString database_name(static_cast(db_node->str_len_), db_node->str_value_); + string_to_upper_case(database_name.ptr(), database_name.length()); // change all to upper to store + expr_table->set_database_name(db_node->str_value_, static_cast(db_node->str_len_)); } } } - return ret; -} -int ObProxySelectStmt::order_by_exprs_to_sql_string(common::ObSqlString& sql_string) -{ - int ret = OB_SUCCESS; - if (order_by_exprs_.count() <= 0) { - // do nothing - } else if (OB_FAIL(sql_string.append(" ORDER BY "))) { - LOG_WARN("fail to append", K(ret), K(sql_string_)); - } else { - for (int i = 0; OB_SUCC(ret) && i < order_by_exprs_.count(); i++) { - if (OB_FAIL(order_by_exprs_.at(i)->to_sql_string(sql_string))) { - LOG_WARN("to sql_string failed", K(i), K(ret), K(sql_string_)); - } else if (i >= order_by_exprs_.count() - 1) { - // no need add , do nothing - } else if (OB_FAIL(sql_string.append(", "))) { - LOG_WARN("append failed", K(i), K(ret), K(sql_string_)); - } + + + if (OB_SUCC(ret)) { + ObProxyExprTablePos expr_table_pos; + if (NULL != db_node) { + expr_table_pos.set_database_pos(db_node->token_off_); + } + expr_table_pos.set_table_pos(table_node->token_off_); + expr_table_pos.set_table_expr(expr_table); + if (OB_FAIL(table_pos_array_.push_back(expr_table_pos))) { + LOG_WARN("fail to push expr table pos", K(ret)); } } - return ret; -} -//REFER:https://dev.mysql.com/doc/refman/8.0/en/select.html -int ObProxySelectStmt::to_sql_string(common::ObSqlString& sql_string) -{ - int ret = OB_SUCCESS; - if (OB_FAIL(comments_to_sql_string(sql_string))) { - LOG_WARN("comments_to_sql_string failed", K(ret), K(sql_string_)); - } else if (OB_FAIL(sql_string.append("SELECT "))) { - LOG_WARN("fail to append", K(ret), K(sql_string_)); - } else if (OB_FAIL(hint_exprs_to_sql_string(sql_string))) { - LOG_WARN("hint_exprs_to_sql_string failed", K(ret), K(sql_string_)); - } else if (OB_FAIL(select_exprs_to_sql_string(sql_string))) { - LOG_WARN("select_exprs_to_sql_string failed", K(ret), K(sql_string_)); - } else if (OB_FAIL(table_exprs_to_sql_string(sql_string))) { - LOG_WARN("table_exprs_to_sql_string failed", K(ret), K(sql_string_)); - } else if (OB_FAIL(condition_exprs_to_sql_string(sql_string))) { - LOG_WARN("condition_exprs_to_sql_string faield", K(ret), K(sql_string_)); - } else if (OB_FAIL(group_by_exprs_to_sql_string(sql_string))) { - LOG_WARN("group_by_exprs_to_sql_string failed", K(ret), K(sql_string_)); - } else if (OB_FAIL(order_by_exprs_to_sql_string(sql_string))) { - LOG_WARN("order_by_exprs_to_sql_string failed", K(ret), K(sql_string_)); - } else if (OB_FAIL(limit_to_sql_string(sql_string))) { - LOG_WARN("limit_to_sql_string", K(ret), K(sql_string_)); - } else { - LOG_DEBUG("sql_string is", K(sql_string)); - } return ret; } -int ObProxySelectStmt::handle_hint_clause(ParseNode* node) +int ObProxyDMLStmt::handle_table_and_db_node(ParseNode* node, ObProxyExprTable* &expr_table) { int ret = OB_SUCCESS; - ParseNode* tmp_node = NULL; - for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { - tmp_node = node->children_[i]; - if (NULL == tmp_node) { - // do nothing - } else { - switch(tmp_node->type_) { - case T_RELATION_FACTOR: - if (OB_FAIL(handle_table_and_db_in_hint(tmp_node))) { - LOG_WARN("fail to handle table and db in hint", K(ret)); + ParseNode* db_node = node->children_[0]; + ParseNode* table_node = node->children_[1]; + if (OB_ISNULL(table_node)) { + // do nothing + } else if (OB_UNLIKELY(T_IDENT != table_node->type_ || NULL == table_node->str_value_ || 0 >= table_node->str_len_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected table node", "node type", table_node->type_, "str len", table_node->str_len_, K(ret)); + } else if (NULL != db_node + && OB_UNLIKELY(T_IDENT != db_node->type_ || NULL == db_node->str_value_ || 0 >= db_node->str_len_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected db node", "node type", db_node->type_, "str len", db_node->str_len_, K(ret)); + } else { + ObProxyExpr* expr = NULL; + ObString table_name = ObString::make_string(table_node->str_value_); + if (OB_SUCCESS == alias_table_map_.get_refactored(table_name, expr)) { + if (OB_ISNULL(expr_table = dynamic_cast(expr))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("dynamic_cast failed", K(ret)); + } + } else { + string_to_upper_case(table_name.ptr(), table_name.length()); // change all to upper to store + if (OB_SUCCESS == table_exprs_map_.get_refactored(table_name, expr)) { + if (OB_ISNULL(expr_table = dynamic_cast(expr))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("dynamic_cast failed", K(ret)); + } else { + // Only the real table name needs to be rewritten, not the alias + ObProxyExprTablePos expr_table_pos; + if (NULL != db_node) { + expr_table_pos.set_database_pos(db_node->token_off_); } - break; - default: - ret = handle_hint_clause(tmp_node); - break; + expr_table_pos.set_table_pos(table_node->token_off_); + expr_table_pos.set_table_expr(expr_table); + if (OB_FAIL(table_pos_array_.push_back(expr_table_pos))) { + LOG_WARN("fail to push expr table pos", K(ret)); + } + } } } } @@ -313,298 +406,338 @@ int ObProxySelectStmt::handle_hint_clause(ParseNode* node) return ret; } -int ObProxySelectStmt::handle_limit_clause(ParseNode* node) +int ObProxyDMLStmt::handle_table_references(ParseNode *node) { int ret = OB_SUCCESS; - ParseNode* tmp_node = NULL; - int64_t tmp_val = 0; - limit_token_off_ = node->token_off_; for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { - tmp_node = node->children_[i]; + ParseNode *tmp_node = node->children_[i]; if (NULL == tmp_node) { //do nothing } else { - switch(tmp_node->type_) { - case T_INT: - if(OB_FAIL(get_int_value(tmp_node->str_value_, tmp_val))) { - LOG_WARN("get_int_value failed", K(ret), K(tmp_node->str_value_), K(sql_string_)); - } else { - limit_offset_ = static_cast(tmp_val); + switch (tmp_node->type_) { + case T_ORG: + case T_ALIAS: + if (OB_FAIL(handle_table_node_to_expr(tmp_node))) { + LOG_WARN("fail to handle table node to expr", K(sql_string_), K(ret)); } break; - case T_LIMIT_INT: - if(OB_FAIL(get_int_value(tmp_node->str_value_, tmp_val))) { - LOG_WARN("get_int_value failed", K(ret), K(tmp_node->str_value_), K(sql_string_)); - } else { - limit_size_ = static_cast(tmp_val); - } + //sql: delete tbl_name1,tbl_name2 ... + //MULTI DELETE STMT is not support now + case T_RELATION_FACTOR: break; default: has_unsupport_expr_type_ = true; - LOG_WARN("unsupport type", "node_type", get_type_name(tmp_node->type_), K(sql_string_)); + LOG_WARN("unknown node type", K_(tmp_node->type), K(ret)); } } } return ret; } -int ObProxySelectStmt::handle_project_list(ParseNode* node) +int ObProxyDMLStmt::handle_where_clause(ParseNode* node) { int ret = OB_SUCCESS; ParseNode* tmp_node = NULL; - ObProxyExpr* expr = NULL; - for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { - tmp_node = node->children_[i]; - expr = NULL; - if (NULL == tmp_node) { - // do nothing - } else { - switch(tmp_node->type_) { - case T_PROJECT_STRING: - if (OB_FAIL(project_string_to_expr(tmp_node, expr))) { - LOG_WARN("project_string_to_expr failed", K(sql_string_), K(ret)); - } else if (OB_FAIL(select_exprs_.push_back(expr))) { - LOG_WARN("push to array failed", K(sql_string_), K(ret)); + if (OB_ISNULL(field_results_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null"); + } else { + for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { + tmp_node = node->children_[i]; + if (NULL == tmp_node) { + // do nothing + } else { + switch(tmp_node->type_) { + case T_OP_EQ: + case T_OP_IN: + if (OB_FAIL(handle_column_and_value(tmp_node))) { + LOG_WARN("fail to handle where node", K(sql_string_), K(ret)); + } + break; + case T_COLUMN_REF: { + ObProxyExprTable* expr_table = NULL; + ObProxyExpr* expr = NULL; + if (OB_FAIL(column_ref_to_expr(tmp_node, expr, expr_table))) { + LOG_WARN("fail to column ref to expr", K(ret)); + } + if (OB_NOT_NULL(expr)) { + expr->~ObProxyExpr(); + } + break; } - break; - default: - has_unsupport_expr_type_ = true; - LOG_WARN("unsupport type", "node_type", get_type_name(tmp_node->type_), K(sql_string_)); - } - - if (OB_FAIL(ret) && OB_NOT_NULL(expr)) { - expr->~ObProxyExpr(); + case T_CASE: + t_case_level_++; + if (OB_FAIL(handle_where_clause(tmp_node))) { + LOG_WARN("handle_where_nodes failed", K(sql_string_), K(ret)); + } + t_case_level_--; + break; + default: + if (OB_FAIL(handle_where_clause(tmp_node))) { + LOG_WARN("handle_where_nodes failed", K(sql_string_), K(ret)); + } + break; + } } } } return ret; } -int ObProxySelectStmt::get_const_expr(ParseNode* node, ObProxyExpr* &expr) +int ObProxyDMLStmt::handle_column_and_value(ParseNode* node) { int ret = OB_SUCCESS; - ObProxyExprConst* expr_const = NULL; - if (OB_ISNULL(node)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("unexpected null", K(sql_string_), K(ret)); - } else if (OB_FAIL(get_expr_by_type(expr, OB_PROXY_EXPR_TYPE_CONST))) { - LOG_WARN("get_expr_by_type failed", K(ret), K(sql_string_)); - } else if (OB_ISNULL(expr_const = dynamic_cast(expr))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("dynamic_cast failed", K(ret)); - } else { - ObObj obj; - if (node->type_ == T_INT) { - int64_t value = 0; - if (OB_FAIL(get_int_value(node->str_value_, value, 10))) { - LOG_WARN("fail to int value", K(ret), K(node->str_value_), K(sql_string_)); + ParseNode* tmp_node = NULL; + ObProxyExpr* expr = NULL; + bool have_column = false; + SqlField sql_field; + SqlColumnValue column_value; + bool is_skip_field = false; + if (t_case_level_ > 0) { + is_skip_field = true; + } + if (OB_ISNULL(field_results_)) { + LOG_WARN("unexpected null"); + ret = OB_ERR_UNEXPECTED; + } else { + for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { + tmp_node = node->children_[i]; + if (NULL == tmp_node) { + //do nothing } else { - obj.set_int(value); - expr_const->set_object(obj); - LOG_DEBUG("add int value", K(obj)); + switch(tmp_node->type_) { + case T_COLUMN_REF: { + ObProxyExprColumn* expr_column = NULL; + ObProxyExprTable* expr_table = NULL; + if (OB_FAIL(column_ref_to_expr(tmp_node, expr, expr_table))) { + LOG_WARN("fal to get column expr", K(ret)); + } else if (OB_ISNULL(expr_column = dynamic_cast(expr))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("dynamic_cast failed", K(ret)); + } else if (have_column) { + // where t1.c1 = t2.c2 + is_skip_field = true; + } else { + if (NULL == expr_table + || 0 == expr_table->get_table_name().case_compare(table_name_)) { + sql_field.column_name_.set_value(expr_column->get_column_name()); + } else { + is_skip_field = true; + } + have_column = true; + } + + if (OB_NOT_NULL(expr)) { + expr->~ObProxyExpr(); + } + break; + } + case T_INT: + case T_NUMBER: + if (T_INT == tmp_node->type_) { + sql_field.value_type_ = TOKEN_INT_VAL; + sql_field.column_int_value_ = tmp_node->value_; + } + column_value.value_type_ = TOKEN_STR_VAL; + column_value.column_value_.set_value(tmp_node->str_value_); + ret = sql_field.column_values_.push_back(column_value); + break; + case T_VARCHAR: + ret = handle_varchar_node_in_column_value(tmp_node, sql_field); + break; + case T_EXPR_LIST: + if (OB_FAIL(handle_expr_list_node_in_column_value(tmp_node, sql_field))) { + LOG_WARN("handle_expr_list_node_in_column_value failed", K(ret), K(i), K(sql_string_)); + } + break; + default: + is_skip_field = true; + has_unsupport_expr_type_ = true; + LOG_WARN("unexpected expr type", "node_type", get_type_name(tmp_node->type_), K(sql_string_)); + } + } + } + + if (OB_SUCC(ret) && !is_skip_field) { + int duplicate_column_idx = -1; + for (int i = 0; i < field_results_->fields_.count(); i++) { + if (0 == sql_field.column_name_.config_string_.case_compare(field_results_->fields_[i]->column_name_.config_string_)) { + duplicate_column_idx = i; + break; + } + } + if (-1 != duplicate_column_idx) { + for (int i = 0; OB_SUCC(ret) && i < sql_field.column_values_.count(); i++) { + SqlColumnValue tmp_column_value = sql_field.column_values_[i]; + if (OB_FAIL(field_results_->fields_.at(duplicate_column_idx)->column_values_.push_back(tmp_column_value))) { + LOG_WARN("push_back failed", K(ret), K(sql_string_)); + } + } + } else { + SqlField *tmp_field = NULL; + if (OB_ISNULL(tmp_field = op_alloc(SqlField))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to allocate memory for sqlfield", K(ret)); + } else { + *tmp_field = sql_field; + if (OB_FAIL(field_results_->fields_.push_back(tmp_field))) { + tmp_field->reset(); + tmp_field = NULL; + LOG_WARN("push_back failed", K(ret), K(sql_string_)); + } else { + ++field_results_->field_num_; + LOG_DEBUG("add sql_field", KPC(tmp_field), K(field_results_->field_num_)); + } + } } - } else { - ObString var(node->token_len_, node->str_value_); - obj.set_varchar(var); - expr_const->set_object(obj); - LOG_DEBUG("add varchar value", K(obj)); } } return ret; } -int ObProxySelectStmt::get_sharding_const_expr(ParseNode* node, ObProxyExpr* &expr) +int ObProxyDMLStmt::handle_varchar_node_in_column_value(ParseNode* node, SqlField& sql_field) { int ret = OB_SUCCESS; - ObProxyExprShardingConst* expr_const = NULL; + ParseNode* tmp_varchar_node = NULL; + SqlColumnValue column_value; + int i = 0; if (OB_ISNULL(node)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("unexpected null", K(sql_string_), K(ret)); - } else if (OB_FAIL(get_expr_by_type(expr, OB_PROXY_EXPR_TYPE_SHARDING_CONST))) { - LOG_WARN("get_expr_by_type failed", K(ret), K(sql_string_)); - } else if (OB_ISNULL(expr_const = dynamic_cast(expr))) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("dynamic_cast failed", K(ret)); + LOG_WARN("unexpected null", K(ret)); + } else if (node->num_child_ == 0) { + //there is implicit type conversion: const char* -> ObString + sql_field.column_value_.set_value(node->str_value_); + column_value.value_type_ = TOKEN_STR_VAL; + column_value.column_value_.set_value(node->str_value_); + ret = sql_field.column_values_.push_back(column_value); } else { - expr_const->set_expr_name(node->str_value_, node->token_len_); - } - return ret; -} + tmp_varchar_node = NULL; + for (i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { + if ((node->children_[i] == NULL) || (node->children_[i]->type_ != T_VARCHAR)) { + //do nothing + } else { + tmp_varchar_node = node->children_[i]; + break; + } + } + if (tmp_varchar_node == NULL) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("shoule not null here", K(ret), K(node->str_value_), K(sql_string_)); + } else { + //there is implicit type conversion: const char* -> ObString + sql_field.column_value_.set_value(tmp_varchar_node->str_value_); + sql_field.value_type_ = TOKEN_STR_VAL; + column_value.value_type_ = TOKEN_STR_VAL; + column_value.column_value_.set_value(tmp_varchar_node->str_value_); + if (OB_FAIL(sql_field.column_values_.push_back(column_value))) { + LOG_WARN("fail to push column_value", K(ret)); + } -ObProxyExprType ObProxySelectStmt::get_expr_type_by_node_type(const ObItemType& item_type) -{ - ObProxyExprType expr_type = OB_PROXY_EXPR_TYPE_NONE; - switch(item_type) { - case T_OP_ADD: - expr_type = OB_PROXY_EXPR_TYPE_FUNC_ADD; - break; - case T_OP_MINUS: - expr_type = OB_PROXY_EXPR_TYPE_FUNC_SUB; - break; - case T_OP_MUL: - expr_type = OB_PROXY_EXPR_TYPE_FUNC_MUL; - break; - case T_OP_DIV: - expr_type = OB_PROXY_EXPR_TYPE_FUNC_DIV; - break; - case T_FUN_SUM: - expr_type = OB_PROXY_EXPR_TYPE_FUNC_SUM; - break; - case T_FUN_MAX: - expr_type = OB_PROXY_EXPR_TYPE_FUNC_MAX; - break; - case T_FUN_MIN: - expr_type = OB_PROXY_EXPR_TYPE_FUNC_MIN; - break; - case T_FUN_COUNT: - expr_type = OB_PROXY_EXPR_TYPE_FUNC_COUNT; - break; - case T_FUN_AVG: - expr_type = OB_PROXY_EXPR_TYPE_FUNC_AVG; - break; - default: - break; + bool need_save = false; + ShardingPosType type = SHARDING_POS_NONE; + if (0 == sql_field.column_name_.config_string_.case_compare("SCHEMA_NAME") + || 0 == sql_field.column_name_.config_string_.case_compare("TABLE_SCHEMA")) { + need_save = true; + type = SHARDING_POS_DB; + } else if (0 == sql_field.column_name_.config_string_.case_compare("TABLE_NAME")) { + need_save = true; + type = SHARDING_POS_TABLE; + } + + if (need_save) { + ObProxyDbTablePos db_table_pos; + db_table_pos.set_pos(tmp_varchar_node->token_off_); + db_table_pos.set_name(tmp_varchar_node->str_value_); + db_table_pos.set_type(type); + if (OB_FAIL(db_table_pos_array_.push_back(db_table_pos))) { + LOG_WARN("fail to push expr table pos", K(ret)); + } + } + } } - return expr_type; + return ret; } -int ObProxySelectStmt::get_expr_by_type(ObProxyExpr* &expr, ObProxyExprType type) +int ObProxyDMLStmt::handle_expr_list_node_in_column_value(ParseNode* node, SqlField& sql_field) { int ret = OB_SUCCESS; - char* buf = NULL; -#define ALLOC_PROXY_EXPR_BY_TYPE(ExprClass) \ - if (OB_ISNULL(buf = (char*)(allocator_->alloc(sizeof(ExprClass))))) { \ - ret = OB_ALLOCATE_MEMORY_FAILED; \ - LOG_WARN("fail to alloc mem", K(ret)); \ - } else if (OB_ISNULL(expr = new (buf)ExprClass())) { \ - ret = OB_ALLOCATE_MEMORY_FAILED; \ - LOG_WARN("fail to new expr", K(ret)); \ - } else { \ - expr->set_expr_type(type);\ + ParseNode* tmp_node = NULL; + SqlColumnValue column_value; + for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { + tmp_node = node->children_[i]; + if (NULL == tmp_node) { + //do nothing + } else { + switch(tmp_node->type_) { + case T_VARCHAR: + ret = handle_varchar_node_in_column_value(tmp_node, sql_field); + break; + case T_INT: + default: + column_value.value_type_ = TOKEN_STR_VAL; + column_value.column_value_.set_value(tmp_node->str_value_); + if (OB_FAIL(sql_field.column_values_.push_back(column_value))) { + LOG_WARN("push_back failed", K(i), K(sql_string_), K(ret)); + } + break; + } } - - switch(type) { - case OB_PROXY_EXPR_TYPE_CONST: - ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprConst); - break; - case OB_PROXY_EXPR_TYPE_SHARDING_CONST: - ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprShardingConst); - break; - case OB_PROXY_EXPR_TYPE_TABLE: - ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprTable); - break; - case OB_PROXY_EXPR_TYPE_COLUMN: - ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprColumn); - break; - case OB_PROXY_EXPR_TYPE_STAR: - ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprStar); - break; - case OB_PROXY_EXPR_TYPE_FUNC_ADD: - ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprAdd); - break; - case OB_PROXY_EXPR_TYPE_FUNC_SUB: - ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprSub); - break; - case OB_PROXY_EXPR_TYPE_FUNC_MUL: - ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprMul); - break; - case OB_PROXY_EXPR_TYPE_FUNC_DIV: - ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprDiv); - break; - case OB_PROXY_EXPR_TYPE_FUNC_SUM: - ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprSum); - break; - case OB_PROXY_EXPR_TYPE_FUNC_COUNT: - ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprCount); - break; - case OB_PROXY_EXPR_TYPE_FUNC_AVG: - ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprAvg); - break; - case OB_PROXY_EXPR_TYPE_FUNC_MAX: - ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprMax); - break; - case OB_PROXY_EXPR_TYPE_FUNC_MIN: - ALLOC_PROXY_EXPR_BY_TYPE(ObProxyExprMin); - break; - case OB_PROXY_EXPR_TYPE_FUNC_ORDER: - ALLOC_PROXY_EXPR_BY_TYPE(ObProxyOrderItem); - break; - case OB_PROXY_EXPR_TYPE_FUNC_GROUP: - ALLOC_PROXY_EXPR_BY_TYPE(ObProxyGroupItem); - break; - default: - has_unsupport_expr_type_ = true; - LOG_WARN("unexpected type", K(type)); - break; } return ret; } -int ObProxySelectStmt::handle_table_and_db_node(ParseNode* node, ObProxyExprTable* &expr_table) +int ObProxyDMLStmt::handle_assign_list(ParseNode *node) { int ret = OB_SUCCESS; - - ParseNode* db_node = node->children_[0]; - ParseNode* table_node = node->children_[1]; - if (OB_ISNULL(table_node)) { - // do nothing - } else if (OB_UNLIKELY(T_IDENT != table_node->type_ || NULL == table_node->str_value_ || 0 >= table_node->token_len_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected table node", "node type", table_node->type_, "token len", table_node->token_len_, K(ret)); - } else if (NULL != db_node - && OB_UNLIKELY(T_IDENT != db_node->type_ || NULL == db_node->str_value_ || 0 >= db_node->token_len_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected db node", "node type", db_node->type_, "token len", db_node->token_len_, K(ret)); - } else { - ObProxyExpr* expr = NULL; - ObString table_name = ObString::make_string(table_node->str_value_); - if (OB_SUCCESS == alias_table_map_.get_refactored(table_name, expr)) { - if (OB_ISNULL(expr_table = dynamic_cast(expr))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("dynamic_cast failed", K(ret)); - } + for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { + ParseNode *tmp_node = node->children_[i]; + if (NULL == tmp_node) { + //do nothing } else { - string_to_upper_case(table_name.ptr(), table_name.length()); // change all to upper to store - if (OB_SUCCESS == table_exprs_map_.get_refactored(table_name, expr)) { - if (OB_ISNULL(expr_table = dynamic_cast(expr))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("dynamic_cast failed", K(ret)); - } else { - // Only the real table name needs to be rewritten, not the alias - ObProxyExprTablePos expr_table_pos; - if (NULL != db_node) { - expr_table_pos.set_database_pos(db_node->token_off_); + switch (tmp_node->type_) { + case T_ASSIGN_ITEM: + if (OB_FAIL(handle_column_and_value(tmp_node))) { + LOG_WARN("handle op and failed", K(ret)); } - expr_table_pos.set_table_pos(table_node->token_off_); - expr_table_pos.set_table_expr(expr_table); - if (OB_FAIL(table_pos_array_.push_back(expr_table_pos))) { - LOG_WARN("fail to push expr table pos", K(ret)); - } - } + break; + default: + has_unsupport_expr_type_ = true; + LOG_WARN("unknown node type", K_(tmp_node->type), K(ret)); + break; } } } - return ret; } -int ObProxySelectStmt::handle_table_and_db_in_hint(ParseNode* node) +int ObProxyDMLStmt::handle_column_ref_in_list(ParseNode *node) { int ret = OB_SUCCESS; - + ObProxyExpr* expr = NULL; + ObProxyExprColumn* expr_column = NULL; ObProxyExprTable* expr_table = NULL; - - if (OB_T_RELATION_FACTOR_NUM_CHILD /* 2 */ != node->num_child_) { + ObString column_name; + if (OB_FAIL(column_ref_to_expr(node, expr, expr_table))) { + LOG_WARN("fal to get column expr", K(ret)); + } else if (OB_ISNULL(expr_column = dynamic_cast(expr))) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("children node is not 2", "child num", node->num_child_, K(ret)); - } else if (OB_FAIL(handle_table_and_db_node(node, expr_table))) { - LOG_WARN("fail to handle table and db node", K(ret)); + LOG_WARN("dynamic_cast failed", K(ret)); + } else if ((NULL != expr_table) + && (0 != expr_table->get_table_name().case_compare(table_name_))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("table name is wrong in assign list", K(ret)); + } else { + column_name = expr_column->get_column_name(); + } + if(OB_SUCC(ret)) { + if (OB_FAIL(column_name_array_.push_back(column_name))) { + LOG_WARN("column name push back failed", K(ret)); + } } - return ret; } -int ObProxySelectStmt::column_ref_to_expr(ParseNode* node, ObProxyExpr* &expr, ObProxyExprTable* &expr_table) +int ObProxyDMLStmt::column_ref_to_expr(ParseNode* node, ObProxyExpr* &expr, ObProxyExprTable* &expr_table) { int ret = OB_SUCCESS; @@ -633,9 +766,9 @@ int ObProxySelectStmt::column_ref_to_expr(ParseNode* node, ObProxyExpr* &expr, O ret = OB_ERR_UNEXPECTED; LOG_WARN("dynamic_cast failed", K(ret)); } else { - expr_column->set_column_name(column_node->str_value_, column_node->token_len_); + expr_column->set_column_name(column_node->str_value_, static_cast(column_node->str_len_)); if (OB_NOT_NULL(table_node)) { - expr_column->set_table_name(table_node->str_value_, table_node->token_len_); + expr_column->set_table_name(table_node->str_value_, static_cast(table_node->str_len_)); if (NULL != expr_table) { expr_column->set_real_table_name(expr_table->get_table_name()); } @@ -650,463 +783,541 @@ int ObProxySelectStmt::column_ref_to_expr(ParseNode* node, ObProxyExpr* &expr, O LOG_WARN("dynamic_cast failed", K(ret)); } else { if (OB_NOT_NULL(table_node)) { - expr_star->set_table_name(table_node->str_value_, table_node->token_len_); + expr_star->set_table_name(table_node->str_value_, static_cast(table_node->str_len_)); } } } } - + + return ret; +} + +int ObProxyDMLStmt::condition_exprs_to_sql_string(common::ObSqlString& sql_string) +{ + UNUSED(sql_string); + int ret = OB_SUCCESS; + return ret; +} + +int ObProxyDMLStmt::limit_to_sql_string(common::ObSqlString& sql_string) +{ + int ret = OB_SUCCESS; + if (limit_size_ > 0) { + if (OB_FAIL(sql_string.append_fmt(" LIMIT %d, %d", limit_offset_, limit_size_))) { + LOG_WARN("fail to append", K(ret)); + } + } return ret; } -int ObProxySelectStmt::alias_node_to_expr(ParseNode* node, ObProxyExpr* &expr, ParseNode* string_node) +int ObProxyDMLStmt::do_handle_parse_result(ParseNode* node) { int ret = OB_SUCCESS; + ParseNode* tmp_node = NULL; - expr = NULL; + for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { tmp_node = node->children_[i]; if (NULL == tmp_node) { - //do nothing + // do nothing + } else if (i == PARSE_SELECT_HAVING) { + has_unsupport_expr_type_ = true; + LOG_WARN("having not support", K(ret), K(sql_string_)); } else { switch(tmp_node->type_) { - case T_IDENT: - if (OB_ISNULL(expr)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("fail to get expr table", K(ret)); - } else if (OB_UNLIKELY(NULL == tmp_node->str_value_ || 0 >= tmp_node->token_len_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("alias token meet some wrong", "token len", tmp_node->token_len_, K(ret)); - } else { - expr->set_alias_name(tmp_node->str_value_, tmp_node->token_len_); - } + case T_FROM_LIST: + from_token_off_ = tmp_node->token_off_; + ret = handle_from_list(tmp_node); break; default: - if (OB_FAIL(string_node_to_expr(tmp_node, expr, string_node))) { - LOG_WARN("string_node_to_expr failed", K(i), K(ret)); - } + break; } } } - return ret; -} -int ObProxySelectStmt::func_node_to_expr(ParseNode* node, ObProxyExpr* &expr) -{ - int ret = OB_SUCCESS; - ParseNode* tmp_node = NULL; - ObProxyExpr* tmp_expr = NULL; - ObProxyFuncExpr* func_expr = NULL; - ObProxyExprType expr_type = get_expr_type_by_node_type(node->type_); - if (OB_FAIL(get_expr_by_type(expr, expr_type))) { - LOG_WARN("get_expr_by_type failed", K(ret)); - } else if (OB_ISNULL(func_expr = dynamic_cast(expr))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("dynamic_cast failed", K(ret)); - } else { - switch(node->type_) { - case T_FUN_SUM: - case T_FUN_COUNT: - case T_FUN_MAX: - case T_FUN_MIN: - case T_FUN_AVG: - func_expr->has_agg_ = 1; - break; - default: - func_expr->has_agg_ = 0; - break; - } - } for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { tmp_node = node->children_[i]; - tmp_expr = NULL; if (NULL == tmp_node) { // do nothing - } else if (tmp_node->type_ == T_ALL) { - // count func have T_ALL node, no need handle - } else if (OB_FAIL(string_node_to_expr(tmp_node, tmp_expr))){ - LOG_WARN("string_node_to_expr failed", K(ret)); - } else if (OB_FAIL(func_expr->add_param_expr(tmp_expr))) { - LOG_WARN("add_param_expr failed", K(ret), K(sql_string_)); } else { - if (tmp_expr->has_agg_) { - func_expr->has_agg_ = 1; + switch(tmp_node->type_) { + case T_HINT_OPTION_LIST: + ret = handle_hint_clause(tmp_node); + break; + case T_PROJECT_LIST: + ret = handle_project_list(tmp_node); + break; + case T_FROM_LIST: + break; + case T_WHERE_CLAUSE: + ret = handle_where_clause(tmp_node); + break; + case T_GROUPBY_CLAUSE: + ret = handle_groupby_clause(tmp_node); + break; + case T_ORDER_BY: + ret = handle_orderby_clause(tmp_node); + break; + case T_COMMA_LIMIT_CLAUSE: + case T_LIMIT_CLAUSE: + ret = handle_limit_clause(tmp_node); + break; + case T_SFU_INT: + has_for_update_ = true; + break; + case T_SET_UNION: + ret = handle_union_clause(tmp_node); + break; + case T_SELECT: + if (OB_FAIL(do_handle_parse_result(tmp_node))) { + LOG_WARN("fail to do handle parse result", "node_type", get_type_name(tmp_node->type_), K(ret)); + } + break; + case T_QEURY_EXPRESSION_LIST: //distinct not support now + default: + has_unsupport_expr_type_ = true; + LOG_WARN("unsupport type", "node_type", get_type_name(tmp_node->type_), K(sql_string_), K(ret)); } } } - if (OB_SUCC(ret)) { - func_expr->set_expr_name(node->str_value_, node->token_len_); - } - return ret; } -int ObProxySelectStmt::check_node_has_agg(ParseNode* node) + +int ObProxyDMLStmt::handle_comment_list(const ParseResult &parse_result) { int ret = OB_SUCCESS; - ParseNode* tmp_node = NULL; - if (OB_ISNULL(node)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null", K(sql_string_)); - } - for(int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { - tmp_node = node->children_[i]; - if (NULL == tmp_node) { - //do nothing + for (int i = 0; OB_SUCC(ret) && i < parse_result.comment_cnt_; i++) { + TokenPosInfo& token_info = parse_result.comment_list_[i]; + ObString comment(token_info.token_len_, sql_string_.ptr() + token_info.token_off_); + if (OB_FAIL(comments_.push_back(comment))) { + LOG_WARN("push_back failed", K(ret), K(comment), K(sql_string_)); } else { - switch(tmp_node->type_) { - case T_FUN_SUM: - case T_FUN_COUNT: - case T_FUN_MAX: - case T_FUN_MIN: - case T_FUN_AVG: - has_unsupport_expr_type_ = true; - LOG_WARN("node has agg", "node_type", get_type_name(tmp_node->type_), K(ret), K(sql_string_)); - break; - default: - if (OB_FAIL(check_node_has_agg(tmp_node))) { - LOG_WARN("check_node_has_agg failed", K(ret)); - } - break; - } + LOG_DEBUG("push_back succ", K(comment)); } } return ret; } -//we do not cover all sys func. if sys func do not have agg func, pass it to server as string -int ObProxySelectStmt::func_sys_node_to_expr(ParseNode* node, ObProxyExpr* &expr, ParseNode* string_node) + +int ObProxyDMLStmt::comments_to_sql_string(common::ObSqlString& sql_string) { int ret = OB_SUCCESS; - if (OB_FAIL(check_node_has_agg(node))) { - LOG_WARN("check_node_has_agg failed", K(ret)); - } else if (string_node == NULL) { - if (OB_FAIL(get_sharding_const_expr(node, expr))) { - LOG_WARN("get_sharding_const_expr faield", K(ret)); + for (int i = 0; OB_SUCC(ret) && i < comments_.count(); i++) { + if (OB_FAIL(sql_string.append(comments_.at(i)))) { + LOG_WARN("fail to append", K(ret), K(i), K(comments_.at(i)), K(sql_string_)); } - } else if (OB_FAIL(get_sharding_const_expr(string_node, expr))) { - LOG_WARN("get_sharding_const_expr faield", K(ret)); } return ret; } -int ObProxySelectStmt::string_node_to_expr(ParseNode* node, ObProxyExpr* &expr, ParseNode* string_node) +int ObProxyDMLStmt::hint_exprs_to_sql_string(common::ObSqlString& sql_string) { + UNUSED(sql_string); int ret = OB_SUCCESS; - int i = 0; - switch(node->type_) { - case T_STAR: - if (OB_FAIL(get_expr_by_type(expr, OB_PROXY_EXPR_TYPE_STAR))) { - LOG_WARN("get_expr_by_type failed", K(ret), K(sql_string_)); - } - break; - case T_COLUMN_REF: { - ObProxyExprTable* expr_table = NULL; - if (OB_FAIL(column_ref_to_expr(node, expr, expr_table))) { - LOG_WARN("fail to column ref to expr", K(ret)); + return ret; +} +int ObProxyDMLStmt::select_exprs_to_sql_string(common::ObSqlString& sql_string) +{ + int ret = OB_SUCCESS; + if (select_exprs_.count() < 1) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid select_exprs_ count", K(select_exprs_.count()), K(sql_string_)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < select_exprs_.count(); i++) { + if (OB_FAIL(select_exprs_.at(i)->to_sql_string(sql_string))) { + LOG_WARN("to sql_string failed", K(i), K(ret), K(sql_string_)); + } else if (i >= select_exprs_.count() - 1) { + // no need add , do nothing + } else if (OB_FAIL(sql_string.append(", "))) { + LOG_WARN("fail to append", K(i), K(ret), K(sql_string_)); } - break; } - case T_ALL: - break; - case T_ALIAS: - if (OB_FAIL(alias_node_to_expr(node, expr, string_node))) { - LOG_WARN("fail to alias node to expr", K(ret)); - } - break; - case T_FUN_SYS: // not support fun sys, as string_node - if (OB_FAIL(func_sys_node_to_expr(node, expr, string_node))) { - LOG_WARN("fail to func sys node to expr", K(ret)); - } - break; - case T_IDENT: - case T_INT: - if (OB_FAIL(get_const_expr(node, expr))) { - LOG_WARN("fail to get sharding const expr", K(ret)); - } - break; - case T_VARCHAR: - //varchar has varchar child, if child is 0 not have child - if (node->num_child_ == 0) { - if (OB_FAIL(get_const_expr(node, expr))) { - LOG_WARN("fail to get sharding const expr succ", K(ret)); - } - } else { - for (i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { - if (node->children_[i] == NULL) { - //do nothing - } else if (expr != NULL) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("expr should null", K(ret), K(i), K(node->str_value_), K(sql_string_)); - } else if (OB_FAIL(get_const_expr(node->children_[i], expr))) { - LOG_WARN("fail to get sharding const expr succ", K(ret)); - } - } + } + return ret; +} + +int ObProxyDMLStmt::table_exprs_to_sql_string(common::ObSqlString& sql_string) +{ + UNUSED(sql_string); + int ret = OB_SUCCESS; + return ret; +} + +int ObProxyDMLStmt::group_by_exprs_to_sql_string(common::ObSqlString& sql_string) +{ + int ret = OB_SUCCESS; + if (group_by_exprs_.count() <= 0) { + // do nothing + } else if (OB_FAIL(sql_string.append(" GROUP BY "))) { + LOG_WARN("fail to append", K(ret), K(sql_string_)); + } else { + for (int i = 0; OB_SUCC(ret) && i < group_by_exprs_.count(); i++) { + if (OB_FAIL(group_by_exprs_.at(i)->to_sql_string(sql_string))) { + LOG_WARN("to sql_string failed", K(i), K(ret), K(sql_string_)); + } else if (i >= group_by_exprs_.count() - 1) { + // no need add , do nothing + } else if (OB_FAIL(sql_string.append(", "))) { + LOG_WARN("append failed", K(i), K(ret), K(sql_string_)); } - break; - case T_OP_ADD: - case T_OP_MINUS: - case T_OP_MUL: - case T_OP_DIV: - case T_FUN_SUM: - case T_FUN_COUNT: - case T_FUN_MAX: - case T_FUN_MIN: - case T_FUN_AVG: - if (OB_FAIL(func_node_to_expr(node, expr))) { - LOG_WARN("fail to add func node expr succ", K(ret)); + } + if (OB_SUCC(ret) && has_rollup_) { + if (OB_FAIL(sql_string.append(" WITH ROLLUP"))) { + LOG_WARN("append failed", K(ret), K(sql_string_)); } - break; - default: - if (OB_FAIL(check_node_has_agg(node))) { - LOG_WARN("unsupport type", "node_type", get_type_name(node->type_), K(node->str_value_)); - } else if (string_node == NULL) { - has_unsupport_expr_type_ = true; - LOG_WARN("unsupport type", "node_type", get_type_name(node->type_), K(node->str_value_), K(sql_string_)); - } else if (OB_FAIL(get_sharding_const_expr(string_node, expr))) { - LOG_WARN("get_sharding_const_expr failed", K(ret)); + } + } + return ret; +} + +int ObProxyDMLStmt::order_by_exprs_to_sql_string(common::ObSqlString& sql_string) +{ + int ret = OB_SUCCESS; + if (order_by_exprs_.count() <= 0) { + // do nothing + } else if (OB_FAIL(sql_string.append(" ORDER BY "))) { + LOG_WARN("fail to append", K(ret), K(sql_string_)); + } else { + for (int i = 0; OB_SUCC(ret) && i < order_by_exprs_.count(); i++) { + if (OB_FAIL(order_by_exprs_.at(i)->to_sql_string(sql_string))) { + LOG_WARN("to sql_string failed", K(i), K(ret), K(sql_string_)); + } else if (i >= order_by_exprs_.count() - 1) { + // no need add , do nothing + } else if (OB_FAIL(sql_string.append(", "))) { + LOG_WARN("append failed", K(i), K(ret), K(sql_string_)); } + } + } + return ret; +} + +//REFER:https://dev.mysql.com/doc/refman/8.0/en/select.html +int ObProxyDMLStmt::to_sql_string(common::ObSqlString& sql_string) +{ + int ret = OB_SUCCESS; + if (OB_FAIL(comments_to_sql_string(sql_string))) { + LOG_WARN("comments_to_sql_string failed", K(ret), K(sql_string_)); + } else if (OB_FAIL(sql_string.append("SELECT "))) { + LOG_WARN("fail to append", K(ret), K(sql_string_)); + } else if (OB_FAIL(hint_exprs_to_sql_string(sql_string))) { + LOG_WARN("hint_exprs_to_sql_string failed", K(ret), K(sql_string_)); + } else if (OB_FAIL(select_exprs_to_sql_string(sql_string))) { + LOG_WARN("select_exprs_to_sql_string failed", K(ret), K(sql_string_)); + } else if (OB_FAIL(table_exprs_to_sql_string(sql_string))) { + LOG_WARN("table_exprs_to_sql_string failed", K(ret), K(sql_string_)); + } else if (OB_FAIL(condition_exprs_to_sql_string(sql_string))) { + LOG_WARN("condition_exprs_to_sql_string faield", K(ret), K(sql_string_)); + } else if (OB_FAIL(group_by_exprs_to_sql_string(sql_string))) { + LOG_WARN("group_by_exprs_to_sql_string failed", K(ret), K(sql_string_)); + } else if (OB_FAIL(order_by_exprs_to_sql_string(sql_string))) { + LOG_WARN("order_by_exprs_to_sql_string failed", K(ret), K(sql_string_)); + } else if (OB_FAIL(limit_to_sql_string(sql_string))) { + LOG_WARN("limit_to_sql_string", K(ret), K(sql_string_)); + } else { + LOG_DEBUG("sql_string is", K(sql_string)); } return ret; } -int ObProxySelectStmt::project_string_to_expr(ParseNode* node, ObProxyExpr* &expr) + +int ObProxyDMLStmt::handle_union_clause(ParseNode* node) { int ret = OB_SUCCESS; ParseNode* tmp_node = NULL; + bool has_unsupport_expr_type = true; + for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { tmp_node = node->children_[i]; if (NULL == tmp_node) { // do nothing - } else if (expr != NULL) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("expr not null", K(node->str_value_), K(node->num_child_), K(sql_string_), K(ret)); - } else if (OB_FAIL(string_node_to_expr(tmp_node, expr, node))) { - LOG_WARN("string_node_to_expr failed", K(sql_string_), K(ret)); + } else { + switch(tmp_node->type_) { + case T_ALL: + has_unsupport_expr_type = false; + break; + default: + LOG_WARN("unsupport type", "node_type", get_type_name(tmp_node->type_), K(ret)); + break; + } } } + + if (has_unsupport_expr_type) { + has_unsupport_expr_type_ = true; + } + return ret; } -int ObProxySelectStmt::get_table_and_db_expr(ParseNode* node, ObProxyExprTable* &expr_table) +int ObProxyDMLStmt::handle_hint_clause(ParseNode* node) { int ret = OB_SUCCESS; + ParseNode* tmp_node = NULL; - ObObj obj; - ParseNode* table_node = NULL; - ParseNode* db_node = NULL; - ObProxyExpr* expr = NULL; - if (OB_ISNULL(node)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("unexpected null", K(ret)); - } else if (OB_T_RELATION_FACTOR_NUM_CHILD /* 2 */ != node->num_child_) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("T_RELATION_FACTOR children node is not 2", K(node->num_child_), K(ret)); - } else if (FALSE_IT(db_node = node->children_[0])) { - } else if (NULL != db_node - && OB_UNLIKELY(T_IDENT != db_node->type_ || NULL == db_node->str_value_ || 0 >= db_node->token_len_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("T_RELATION_FACTOR unexpected table entry", "node type", db_node->type_, - "token len", db_node->token_len_, K(ret)); - } else if (OB_ISNULL(table_node = node->children_[1])) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null", K(ret)); - } else if (OB_UNLIKELY(T_IDENT != table_node->type_ || NULL == table_node->str_value_ || 0 >= table_node->token_len_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("T_RELATION_FACTOR unexpected table entry", "node type", table_node->type_, - "token len", table_node->token_len_, K(ret)); - } else { - ObString table_name(table_node->token_len_, table_node->str_value_); - string_to_upper_case(table_name.ptr(), table_name.length()); // change all to upper to store - if (OB_FAIL(table_exprs_map_.get_refactored(table_name, expr))) { /* same table keep last one. */ - if (OB_HASH_NOT_EXIST == ret) { - if (OB_FAIL(get_expr_by_type(expr, OB_PROXY_EXPR_TYPE_TABLE))) { - LOG_WARN("get_expr_by_type failed", K(ret)); - } else if (OB_ISNULL(expr_table = dynamic_cast(expr))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("dynamic_cast failed", K(ret)); - } else { - if (NULL != db_node) { - ObString database_name(db_node->token_len_, db_node->str_value_); - string_to_upper_case(database_name.ptr(), database_name.length()); // change all to upper to store - expr_table->set_database_name(db_node->str_value_, db_node->token_len_); - } - expr_table->set_table_name(table_node->str_value_, table_node->token_len_); - - if (OB_FAIL(table_exprs_map_.set_refactored(table_name, expr_table))) { /* same table keep last one. */ - LOG_WARN("fail to add table expr", K(table_name), K(ret)); + for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { + tmp_node = node->children_[i]; + if (NULL == tmp_node) { + // do nothing + } else { + switch(tmp_node->type_) { + case T_RELATION_FACTOR: + if (OB_FAIL(handle_table_and_db_in_hint(tmp_node))) { + LOG_WARN("fail to handle table and db in hint", K(ret)); } - } - } else { - LOG_WARN("fail to get table expr", K(table_name), K(ret)); - } - } else { - if (OB_ISNULL(expr_table = dynamic_cast(expr))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("dynamic_cast failed", K(ret)); - } else if (NULL != db_node && expr_table->get_database_name().empty()) { - ObString database_name(db_node->token_len_, db_node->str_value_); - string_to_upper_case(database_name.ptr(), database_name.length()); // change all to upper to store - expr_table->set_database_name(db_node->str_value_, db_node->token_len_); + break; + default: + ret = handle_hint_clause(tmp_node); + break; } } } - - if (OB_SUCC(ret)) { - ObProxyExprTablePos expr_table_pos; - if (NULL != db_node) { - expr_table_pos.set_database_pos(db_node->token_off_); - } - expr_table_pos.set_table_pos(table_node->token_off_); - expr_table_pos.set_table_expr(expr_table); - if (OB_FAIL(table_pos_array_.push_back(expr_table_pos))) { - LOG_WARN("fail to push expr table pos", K(ret)); - } - } - return ret; } -int ObProxySelectStmt::handle_table_node_to_expr(ParseNode* node) +int ObProxyDMLStmt::handle_limit_clause(ParseNode* node) { int ret = OB_SUCCESS; ParseNode* tmp_node = NULL; - ObProxyExprTable* expr_table = NULL; + int64_t tmp_val = 0; + limit_token_off_ = node->token_off_; for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { tmp_node = node->children_[i]; if (NULL == tmp_node) { //do nothing } else { switch(tmp_node->type_) { - case T_RELATION_FACTOR: - if (OB_FAIL(get_table_and_db_expr(tmp_node, expr_table))) { - LOG_WARN("fail to get table expr", K(ret)); + case T_INT: + if(OB_FAIL(get_int_value(tmp_node->str_value_, tmp_val))) { + LOG_WARN("get_int_value failed", K(ret), K(tmp_node->str_value_), K(sql_string_)); + } else { + limit_offset_ = static_cast(tmp_val); } break; - case T_IDENT: - if (OB_ISNULL(expr_table)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("fail to get expr table", K(ret)); - } else if (OB_UNLIKELY(NULL == tmp_node->str_value_ || 0 >= tmp_node->token_len_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("alias token meet some wrong", "token len", tmp_node->token_len_, K(ret)); + case T_LIMIT_INT: + if(OB_FAIL(get_int_value(tmp_node->str_value_, tmp_val))) { + LOG_WARN("get_int_value failed", K(ret), K(tmp_node->str_value_), K(sql_string_)); } else { - ObString alias_table = ObString::make_string(tmp_node->str_value_); - if (OB_FAIL(alias_table_map_.set_refactored(alias_table, expr_table))) { - LOG_WARN("fail to add alias table set", K(alias_table), K(ret)); - } + limit_size_ = static_cast(tmp_val); } break; default: has_unsupport_expr_type_ = true; - LOG_WARN("unsupport type", "node_type", get_type_name(node->type_), K(node->str_value_)); + LOG_WARN("unsupport type", "node_type", get_type_name(tmp_node->type_), K(sql_string_)); } } } return ret; } -int ObProxySelectStmt::handle_from_list(ParseNode* node) +int ObProxyDMLStmt::handle_project_list(ParseNode* node) { int ret = OB_SUCCESS; ParseNode* tmp_node = NULL; - + ObProxyExpr* expr = NULL; for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { tmp_node = node->children_[i]; + expr = NULL; if (NULL == tmp_node) { // do nothing - } else { + } else { + switch(tmp_node->type_) { + case T_PROJECT_STRING: + if (OB_FAIL(project_string_to_expr(tmp_node, expr))) { + LOG_WARN("project_string_to_expr failed", K(sql_string_), K(ret)); + } else if (OB_FAIL(select_exprs_.push_back(expr))) { + LOG_WARN("push to array failed", K(sql_string_), K(ret)); + } + break; + default: + has_unsupport_expr_type_ = true; + LOG_WARN("unsupport type", "node_type", get_type_name(tmp_node->type_), K(sql_string_)); + } + + if (OB_FAIL(ret) && OB_NOT_NULL(expr)) { + expr->~ObProxyExpr(); + } + } + } + return ret; +} + +int ObProxyDMLStmt::get_const_expr(ParseNode* node, ObProxyExpr* &expr) +{ + int ret = OB_SUCCESS; + ObProxyExprConst* expr_const = NULL; + if (OB_ISNULL(node)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("unexpected null", K(sql_string_), K(ret)); + } else if (OB_FAIL(get_expr_by_type(expr, OB_PROXY_EXPR_TYPE_CONST))) { + LOG_WARN("get_expr_by_type failed", K(ret), K(sql_string_)); + } else if (OB_ISNULL(expr_const = dynamic_cast(expr))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("dynamic_cast failed", K(ret)); + } else { + ObObj obj; + if (node->type_ == T_INT) { + int64_t value = 0; + if (OB_FAIL(get_int_value(node->str_value_, value, 10))) { + LOG_WARN("fail to int value", K(ret), K(node->str_value_), K(sql_string_)); + } else { + obj.set_int(value); + expr_const->set_object(obj); + LOG_DEBUG("add int value", K(obj)); + } + } else { + ObString var(static_cast(node->str_len_), node->str_value_); + obj.set_varchar(var); + expr_const->set_object(obj); + LOG_DEBUG("add varchar value", K(obj)); + } + } + return ret; +} + +int ObProxyDMLStmt::get_sharding_const_expr(ParseNode* node, ObProxyExpr* &expr) +{ + int ret = OB_SUCCESS; + ObProxyExprShardingConst* expr_const = NULL; + if (OB_ISNULL(node)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("unexpected null", K(sql_string_), K(ret)); + } else if (OB_FAIL(get_expr_by_type(expr, OB_PROXY_EXPR_TYPE_SHARDING_CONST))) { + LOG_WARN("get_expr_by_type failed", K(ret), K(sql_string_)); + } else if (OB_ISNULL(expr_const = dynamic_cast(expr))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("dynamic_cast failed", K(ret)); + } else { + expr_const->set_expr_name(node->str_value_, static_cast(node->str_len_)); + } + return ret; +} + +int ObProxyDMLStmt::handle_table_and_db_in_hint(ParseNode* node) +{ + int ret = OB_SUCCESS; + + ObProxyExprTable* expr_table = NULL; + + if (OB_T_RELATION_FACTOR_NUM_CHILD /* 2 */ != node->num_child_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("children node is not 2", "child num", node->num_child_, K(ret)); + } else if (OB_FAIL(handle_table_and_db_node(node, expr_table))) { + LOG_WARN("fail to handle table and db node", K(ret)); + } + + return ret; +} + + +int ObProxyDMLStmt::alias_node_to_expr(ParseNode* node, ObProxyExpr* &expr, ParseNode* string_node) +{ + int ret = OB_SUCCESS; + ParseNode* tmp_node = NULL; + expr = NULL; + for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { + tmp_node = node->children_[i]; + if (NULL == tmp_node) { + //do nothing + } else { switch(tmp_node->type_) { - case T_ORG: - case T_ALIAS: - if (OB_FAIL(handle_table_node_to_expr(tmp_node))) { - LOG_WARN("fail to handle table node to expr", K(sql_string_), K(ret)); - } - break; - case T_OP_EQ: - case T_OP_IN: - if (OB_FAIL(handle_where_node(tmp_node))) { - LOG_WARN("fail to handle where node", K(sql_string_), K(ret)); - } - break; - case T_COLUMN_REF: { - ObProxyExprTable* expr_table = NULL; - ObProxyExpr* expr = NULL; - if (OB_FAIL(column_ref_to_expr(tmp_node, expr, expr_table))) { - LOG_WARN("fail to column ref to expr", K(ret)); - } - if (OB_NOT_NULL(expr)) { - expr->~ObProxyExpr(); + case T_IDENT: + if (OB_ISNULL(expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to get expr table", K(ret)); + } else if (OB_UNLIKELY(NULL == tmp_node->str_value_ || 0 >= tmp_node->str_len_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("alias token meet some wrong", "str len", tmp_node->str_len_, K(ret)); + } else { + expr->set_alias_name(tmp_node->str_value_, static_cast(tmp_node->str_len_)); } break; - } default: - if (OB_FAIL(handle_from_list(tmp_node))) { - LOG_WARN("fail to handle from list", K(sql_string_), K(ret)); + if (OB_FAIL(string_node_to_expr(tmp_node, expr, string_node))) { + LOG_WARN("string_node_to_expr failed", K(i), K(ret)); } - break; } } } return ret; } -int ObProxySelectStmt::handle_varchar_node_in_where_condition(ParseNode* node, SqlField& sql_field) +int ObProxyDMLStmt::func_node_to_expr(ParseNode* node, ObProxyExpr* &expr) { int ret = OB_SUCCESS; - ParseNode* tmp_varchar_node = NULL; - SqlColumnValue column_value; - int i = 0; - if (OB_ISNULL(node)) { + ParseNode* tmp_node = NULL; + ObProxyExpr* tmp_expr = NULL; + ObProxyFuncExpr* func_expr = NULL; + ObProxyExprType expr_type = get_expr_type_by_node_type(node->type_); + if (OB_FAIL(get_expr_by_type(expr, expr_type))) { + LOG_WARN("get_expr_by_type failed", K(ret)); + } else if (OB_ISNULL(func_expr = dynamic_cast(expr))) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null", K(ret)); - } else if (node->num_child_ == 0) { - column_value.value_type_ = TOKEN_STR_VAL; - column_value.column_value_.set(node->str_value_); - sql_field.column_values_.push_back(column_value); + LOG_WARN("dynamic_cast failed", K(ret)); } else { - tmp_varchar_node = NULL; - for (i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { - if (node->children_[i] == NULL) { - //do nothing - } else if (tmp_varchar_node != NULL) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("should null here", K(ret), K(node->str_value_), K(sql_string_)); - } else { - tmp_varchar_node = node->children_[i]; - } + switch(node->type_) { + case T_FUN_SUM: + case T_FUN_COUNT: + case T_FUN_MAX: + case T_FUN_MIN: + case T_FUN_AVG: + func_expr->has_agg_ = 1; + break; + default: + func_expr->has_agg_ = 0; + break; } - if (tmp_varchar_node == NULL) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("shoule not null here", K(ret), K(node->str_value_), K(sql_string_)); + } + for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { + tmp_node = node->children_[i]; + tmp_expr = NULL; + if (NULL == tmp_node) { + // do nothing + } else if (tmp_node->type_ == T_ALL) { + // There are T_ALL nodes under the COUNT function, do not need to be processed, do nothing + } else if (OB_FAIL(string_node_to_expr(tmp_node, tmp_expr))){ + LOG_WARN("string_node_to_expr failed", K(ret)); + } else if (NULL == tmp_expr) { + // Argument in func is of unsupported type + LOG_WARN("tmp_expr is empty", "type", tmp_node->type_, K(ret)); + } else if (OB_FAIL(func_expr->add_param_expr(tmp_expr))) { + LOG_WARN("add_param_expr failed", K(ret), K(sql_string_)); } else { - column_value.value_type_ = TOKEN_STR_VAL; - column_value.column_value_.set(tmp_varchar_node->str_value_); - sql_field.column_values_.push_back(column_value); + if (tmp_expr->has_agg_) { + func_expr->has_agg_ = 1; + } } } + + if (OB_SUCC(ret)) { + func_expr->set_expr_name(node->str_value_, static_cast(node->str_len_)); + } + return ret; } - -int ObProxySelectStmt::handle_where_expr_list_node(ParseNode* node, SqlField& sql_field) +int ObProxyDMLStmt::check_node_has_agg(ParseNode* node) { int ret = OB_SUCCESS; ParseNode* tmp_node = NULL; - SqlColumnValue column_value; + if (OB_ISNULL(node)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(sql_string_)); + } for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { tmp_node = node->children_[i]; if (NULL == tmp_node) { //do nothing } else { switch(tmp_node->type_) { - case T_VARCHAR: - ret = handle_varchar_node_in_where_condition(tmp_node, sql_field); + case T_FUN_SUM: + case T_FUN_COUNT: + case T_FUN_MAX: + case T_FUN_MIN: + case T_FUN_AVG: + has_unsupport_expr_type_ = true; + LOG_WARN("node has agg", "node_type", get_type_name(tmp_node->type_), K(ret), K(sql_string_)); break; - case T_INT: default: - column_value.value_type_ = TOKEN_STR_VAL; - column_value.column_value_.set(tmp_node->str_value_); - if (OB_FAIL(sql_field.column_values_.push_back(column_value))) { - LOG_WARN("push_back failed", K(i), K(sql_string_), K(ret)); + if (OB_FAIL(check_node_has_agg(tmp_node))) { + LOG_WARN("check_node_has_agg failed", K(ret)); } break; } @@ -1114,129 +1325,123 @@ int ObProxySelectStmt::handle_where_expr_list_node(ParseNode* node, SqlField& sq } return ret; } - -int ObProxySelectStmt::handle_where_node(ParseNode* node) +//we do not cover all sys func. if sys func do not have agg func, pass it to server as string +int ObProxyDMLStmt::func_sys_node_to_expr(ParseNode* node, ObProxyExpr* &expr, ParseNode* string_node) { int ret = OB_SUCCESS; - ParseNode* tmp_node = NULL; - ObProxyExpr* expr = NULL; - bool have_column = false; - SqlField sql_field; - SqlColumnValue column_value; - bool is_skip_field = false; - if (OB_ISNULL(field_results_)) { - LOG_WARN("unexpected null"); - ret = OB_ERR_UNEXPECTED; - } else { - for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { - tmp_node = node->children_[i]; - if (NULL == tmp_node) { - //do nothing - } else { - switch(tmp_node->type_) { - case T_COLUMN_REF: { - ObProxyExprColumn* expr_column = NULL; - ObProxyExprTable* expr_table = NULL; - if (OB_FAIL(column_ref_to_expr(tmp_node, expr, expr_table))) { - LOG_WARN("fal to get column expr", K(ret)); - } else if (OB_ISNULL(expr_column = dynamic_cast(expr))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("dynamic_cast failed", K(ret)); - } else if (have_column) { - // where t1.c1 = t2.c2 - is_skip_field = true; - } else { - if (NULL == expr_table - || 0 == expr_table->get_table_name().case_compare(table_name_)) { - sql_field.column_name_.set(expr_column->get_column_name()); - } else { - is_skip_field = true; - } - have_column = true; - } - - if (OB_NOT_NULL(expr)) { - expr->~ObProxyExpr(); - } - break; - } - case T_INT: - case T_NUMBER: - column_value.value_type_ = TOKEN_STR_VAL; - column_value.column_value_.set(tmp_node->str_value_); - sql_field.column_values_.push_back(column_value); - break; - case T_VARCHAR: - ret = handle_varchar_node_in_where_condition(tmp_node, sql_field); - break; - case T_EXPR_LIST: - if (OB_FAIL(handle_where_expr_list_node(tmp_node, sql_field))) { - LOG_WARN("handle_where_expr_list_node failed", K(ret), K(i), K(sql_string_)); - } - break; - default: - has_unsupport_expr_type_ = true; - LOG_WARN("unexpected expr type", "node_type", get_type_name(tmp_node->type_), K(sql_string_)); - } - } - } - - if (OB_SUCC(ret) && !is_skip_field) { - if (OB_FAIL(field_results_->fields_.push_back(sql_field))) { - LOG_WARN("push_back failed", K(ret), K(sql_string_)); - } else { - ++field_results_->field_num_; - LOG_DEBUG("add sql_field", K(sql_field), K(field_results_->field_num_)); - } + if (OB_FAIL(check_node_has_agg(node))) { + LOG_WARN("check_node_has_agg failed", K(ret)); + } else if (string_node == NULL) { + if (OB_FAIL(get_sharding_const_expr(node, expr))) { + LOG_WARN("get_sharding_const_expr faield", K(ret)); } + } else if (OB_FAIL(get_sharding_const_expr(string_node, expr))) { + LOG_WARN("get_sharding_const_expr faield", K(ret)); } return ret; } -int ObProxySelectStmt::handle_where_clause(ParseNode* node) +int ObProxyDMLStmt::string_node_to_expr(ParseNode* node, ObProxyExpr* &expr, ParseNode* string_node) { int ret = OB_SUCCESS; - ParseNode* tmp_node = NULL; - if (OB_ISNULL(field_results_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null"); - } else { - for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { - tmp_node = node->children_[i]; - if (NULL == tmp_node) { - // do nothing + int i = 0; + switch(node->type_) { + case T_STAR: + if (OB_FAIL(get_expr_by_type(expr, OB_PROXY_EXPR_TYPE_STAR))) { + LOG_WARN("get_expr_by_type failed", K(ret), K(sql_string_)); + } + break; + case T_COLUMN_REF: { + ObProxyExprTable* expr_table = NULL; + if (OB_FAIL(column_ref_to_expr(node, expr, expr_table))) { + LOG_WARN("fail to column ref to expr", K(ret)); + } + break; + } + case T_ALL: + break; + case T_ALIAS: + if (OB_FAIL(alias_node_to_expr(node, expr, string_node))) { + LOG_WARN("fail to alias node to expr", K(ret)); + } + break; + case T_FUN_SYS: // not support fun sys, as string_node + if (OB_FAIL(func_sys_node_to_expr(node, expr, string_node))) { + LOG_WARN("fail to func sys node to expr", K(ret)); + } + break; + case T_IDENT: + case T_INT: + if (OB_FAIL(get_const_expr(node, expr))) { + LOG_WARN("fail to get sharding const expr", K(ret)); + } + break; + case T_VARCHAR: + //varchar has varchar child, if child is 0 not have child + if (node->num_child_ == 0) { + if (OB_FAIL(get_const_expr(node, expr))) { + LOG_WARN("fail to get sharding const expr succ", K(ret)); + } } else { - switch(tmp_node->type_) { - case T_OP_EQ: - case T_OP_IN: - if (OB_FAIL(handle_where_node(tmp_node))) { - LOG_WARN("fail to handle where node", K(sql_string_), K(ret)); - } - break; - case T_COLUMN_REF: { - ObProxyExprTable* expr_table = NULL; - ObProxyExpr* expr = NULL; - if (OB_FAIL(column_ref_to_expr(tmp_node, expr, expr_table))) { - LOG_WARN("fail to column ref to expr", K(ret)); - } - if (OB_NOT_NULL(expr)) { - expr->~ObProxyExpr(); - } - break; + for (i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { + if (node->children_[i] == NULL) { + //do nothing + } else if (expr != NULL) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("expr should null", K(ret), K(i), K(node->str_value_), K(sql_string_)); + } else if (OB_FAIL(get_const_expr(node->children_[i], expr))) { + LOG_WARN("fail to get sharding const expr succ", K(ret)); } - default: - if (OB_FAIL(handle_where_clause(tmp_node))) { - LOG_WARN("handle_where_nodes failed", K(sql_string_), K(ret)); - } - break; } } + break; + case T_OP_ADD: + case T_OP_MINUS: + case T_OP_MUL: + case T_OP_DIV: + case T_FUN_SUM: + case T_FUN_COUNT: + case T_FUN_MAX: + case T_FUN_MIN: + case T_FUN_AVG: + if (OB_FAIL(func_node_to_expr(node, expr))) { + LOG_WARN("fail to add func node expr succ", K(ret)); + } + break; + default: + //Does not support type detection whether there is agg, + //if not, use the string of string_node to construct transparent transmission + if (OB_FAIL(check_node_has_agg(node))) { + LOG_WARN("unsupport type", "node_type", get_type_name(node->type_), K(node->str_value_)); + } else if (string_node == NULL) { + has_unsupport_expr_type_ = true; + LOG_WARN("unsupport type", "node_type", get_type_name(node->type_), K(node->str_value_), K(sql_string_)); + } else if (OB_FAIL(get_sharding_const_expr(string_node, expr))) { + LOG_WARN("get_sharding_const_expr failed", K(ret)); + } + } + return ret; +} +int ObProxyDMLStmt::project_string_to_expr(ParseNode* node, ObProxyExpr* &expr) +{ + int ret = OB_SUCCESS; + ParseNode* tmp_node = NULL; + for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { + tmp_node = node->children_[i]; + if (NULL == tmp_node) { + // do nothing + } else if (expr != NULL) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("expr not null", K(node->str_value_), K(node->num_child_), K(sql_string_), K(ret)); + } else if (OB_FAIL(string_node_to_expr(tmp_node, expr, node))) { + LOG_WARN("string_node_to_expr failed", K(sql_string_), K(ret)); } } return ret; } -int ObProxySelectStmt::handle_sort_key_node(ParseNode* node, ObProxyExpr* &expr, const SortListType& sort_list_type) + +int ObProxyDMLStmt::handle_sort_key_node(ParseNode* node, ObProxyExpr* &expr, const SortListType& sort_list_type) { int ret = OB_SUCCESS; ParseNode* tmp_node = NULL; @@ -1255,7 +1460,7 @@ int ObProxySelectStmt::handle_sort_key_node(ParseNode* node, ObProxyExpr* &expr, order_direction = NULLS_LAST_DESC; break; default: - if (OB_FAIL(string_node_to_expr(tmp_node, tmp_expr))) { + if (OB_FAIL(string_node_to_expr(tmp_node, tmp_expr, tmp_node))) { LOG_WARN("string_node_to_expr failed", K(ret), K(sql_string_)); } else if (T_INT == tmp_node->type_) { ObProxyExprConst* expr_const = NULL; @@ -1304,7 +1509,7 @@ int ObProxySelectStmt::handle_sort_key_node(ParseNode* node, ObProxyExpr* &expr, } return ret; } -int ObProxySelectStmt::handle_sort_list_node(ParseNode* node, const SortListType& sort_list_type) +int ObProxyDMLStmt::handle_sort_list_node(ParseNode* node, const SortListType& sort_list_type) { int ret = OB_SUCCESS; ParseNode* tmp_node = NULL; @@ -1357,7 +1562,7 @@ int ObProxySelectStmt::handle_sort_list_node(ParseNode* node, const SortListType } return ret; } -int ObProxySelectStmt::handle_with_rollup_in_groupby(ParseNode* node) +int ObProxyDMLStmt::handle_with_rollup_in_groupby(ParseNode* node) { int ret = OB_SUCCESS; ParseNode* tmp_node = NULL; @@ -1384,7 +1589,7 @@ int ObProxySelectStmt::handle_with_rollup_in_groupby(ParseNode* node) return ret; } -int ObProxySelectStmt::handle_groupby_clause(ParseNode* node) +int ObProxyDMLStmt::handle_groupby_clause(ParseNode* node) { int ret = OB_SUCCESS; ParseNode* tmp_node = NULL; @@ -1403,7 +1608,7 @@ int ObProxySelectStmt::handle_groupby_clause(ParseNode* node) return ret; } -int ObProxySelectStmt::handle_orderby_clause(ParseNode* node) +int ObProxyDMLStmt::handle_orderby_clause(ParseNode* node) { int ret = OB_SUCCESS; ParseNode* tmp_node = NULL; @@ -1422,6 +1627,386 @@ int ObProxySelectStmt::handle_orderby_clause(ParseNode* node) return ret; } +int ObProxySelectStmt::handle_parse_result(const ParseResult &parse_result) +{ + int ret = OB_SUCCESS; + ParseNode* node = parse_result.result_tree_->children_[0]; + + if (OB_FAIL(do_handle_parse_result(node))) { + LOG_WARN("fail to do handle parse result", K(sql_string_), "node_type", get_type_name(node->type_), K(ret)); + } else if (OB_FAIL(handle_comment_list(parse_result))) { + LOG_WARN("handle_comment_list failed", K(ret), K(sql_string_)); + } + + return ret; +} + +int ObProxyInsertStmt::handle_parse_result(const ParseResult &parse_result) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(parse_result.result_tree_) || OB_ISNULL(parse_result.result_tree_->children_[0])) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("result info is null unexpected", K(ret)); + } else { + ParseNode* node = parse_result.result_tree_->children_[0]; + for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { + ParseNode* tmp_node = node->children_[i]; + if (NULL == tmp_node) { + //do nothing + } else { + switch (tmp_node->type_) { + case T_REPLACE: + stmt_type_ = OBPROXY_T_REPLACE; + break; + case T_HINT_OPTION_LIST: + ret = handle_hint_clause(tmp_node); + break; + case T_SINGLE_TABLE_INSERT: + if (OB_FAIL(handle_single_table_insert(tmp_node))) { + LOG_WARN("handle single table insert failed", K(ret)); + } + break; + case T_INSERT: + //nothing + break; + default: + has_unsupport_expr_type_ = true; + LOG_WARN("unknown node type", K_(tmp_node->type), K(ret)); + break; + } + } + } + } + + if(OB_SUCC(ret)) { + if (OB_FAIL(handle_comment_list(parse_result))) { + LOG_WARN("handle_comment_list failed", K(ret), K(sql_string_)); + } + } + return ret; +} + +int ObProxyInsertStmt::handle_single_table_insert(ParseNode *node) +{ + int ret = OB_SUCCESS; + for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { + ParseNode* tmp_node = node->children_[i]; + if (NULL == tmp_node) { + ///do nothing + } else { + switch (tmp_node->type_) { + case T_INSERT_INTO_CLAUSE: + if (OB_FAIL(handle_insert_into(tmp_node))) { + LOG_WARN("fail to handle insert into", K(ret)); + } + break; + case T_VALUE_LIST: + if (OB_FAIL(handle_value_list(tmp_node))) { + LOG_WARN("fail to handle value list", K(ret)); + } + break; + case T_ASSIGN_LIST: + if (OB_FAIL(handle_assign_list(tmp_node))) { + LOG_WARN("fail to handle assign list", K(ret)); + } + break; + case T_SELECT: + if (OB_FAIL(do_handle_parse_result(tmp_node))) { + LOG_WARN("fail to do handle parse result", "node_type", get_type_name(tmp_node->type_), K(ret)); + } + break; + default: + has_unsupport_expr_type_ = true; + LOG_WARN("unknown node type", K_(tmp_node->type), K(ret)); + } + } + } + + return ret; +} + +int ObProxyInsertStmt::handle_insert_into(ParseNode *node) +{ + int ret = OB_SUCCESS; + for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { + ParseNode* tmp_node = node->children_[i]; + if (NULL == tmp_node) { + //do nothing + } else { + switch (tmp_node->type_) { + case T_ORG: + if (OB_FAIL(handle_table_node_to_expr(tmp_node))) { + LOG_WARN("handle org failed", K(ret)); + } + break; + case T_COLUMN_LIST: + if (OB_FAIL(handle_column_list(tmp_node))) { + LOG_WARN("handle column list failed", K(ret)); + } + break; + default: + has_unsupport_expr_type_ = true; + LOG_WARN("unknown node type", K_(tmp_node->type), K(ret)); + break; + } + } + } + + return ret; +} + +int ObProxyInsertStmt::handle_value_list(ParseNode *node) +{ + int ret = OB_SUCCESS; + for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { + ParseNode *tmp_node = node->children_[i]; + if (NULL == tmp_node) { + //do nothing + } else { + switch (tmp_node->type_) { + case T_VALUE_VECTOR: + if (OB_FAIL(handle_value_vector(tmp_node))) { + LOG_WARN("handle value vector failed", K(ret)); + } + break; + default: + has_unsupport_expr_type_ = true; + LOG_WARN("unknown node type", K_(tmp_node->type), K(ret)); + break; + } + } + } + + return ret; +} + +int ObProxyInsertStmt::handle_column_list(ParseNode *node) +{ + int ret = OB_SUCCESS; + for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { + ParseNode *tmp_node = node->children_[i]; + if (NULL == tmp_node) { + //do nothing + } else { + switch (tmp_node->type_) { + case T_COLUMN_REF: + if (OB_FAIL(handle_column_ref_in_list(tmp_node))) { + LOG_WARN("handle column ref failed", K(ret)); + } + break; + default: + has_unsupport_expr_type_ = true; + LOG_WARN("unknown ndoe type", K_(tmp_node->type), K(ret)); + } + } + } + return ret; +} + +int ObProxyInsertStmt::handle_value_vector(ParseNode *node) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(column_name_array_.empty())) { + ret = OB_EXPR_CALC_ERROR; + LOG_WARN("need column name in value vector", K(ret)); + } else if (OB_UNLIKELY(node->num_child_ != column_name_array_.count())){ + ret = OB_ERR_PARSER_SYNTAX; + LOG_WARN("the num of column name do not match value vector", K(ret)); + } else { + bool is_skip_field = false; + SqlColumnValue column_value; + for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { + ParseNode *tmp_node = node->children_[i]; + SqlField *sql_field = NULL; + if (NULL == tmp_node) { + // do nothing + } else if (OB_ISNULL(sql_field = op_alloc(SqlField))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to allocate memory for sqlfield", K(ret)); + } else { + is_skip_field = false; + column_value.reset(); + sql_field->column_name_.set_value(column_name_array_.at(i)); + switch (tmp_node->type_) { + case T_INT: + { + sql_field->value_type_ = TOKEN_INT_VAL; + sql_field->column_int_value_ = tmp_node->value_; + column_value.value_type_ = TOKEN_STR_VAL; + column_value.column_value_.set_value(tmp_node->str_value_); + ret = sql_field->column_values_.push_back(column_value); + break; + } + case T_VARCHAR: + { + ret = handle_varchar_node_in_column_value(tmp_node, *sql_field); + break; + } + case T_OP_NEG: + { + ParseNode *child_node = tmp_node->children_[0]; + if (child_node->type_ == T_INT) { + sql_field->value_type_ = TOKEN_INT_VAL; + sql_field->column_int_value_ = -1 * (child_node->value_); + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unknown node type", K_(child_node->type), K(ret)); + } + break; + } + default: + column_value.value_type_ = TOKEN_NONE; + ret = sql_field->column_values_.push_back(column_value); + has_unsupport_expr_type_ = true; + LOG_WARN("unknown node type", "node type", tmp_node->type_, K(ret)); + break; + } + if (OB_SUCC(ret) && !is_skip_field) { + int duplicate_column_idx = -1; + for (int i = 0; i < field_results_->fields_.count(); i++) { + if (0 == sql_field->column_name_.config_string_.case_compare(field_results_->fields_[i]->column_name_.config_string_)) { + duplicate_column_idx = i; + break; + } + } + if (OB_UNLIKELY(-1 != duplicate_column_idx)) { + for (int i = 0; OB_SUCC(ret) && i < sql_field->column_values_.count(); i++) { + SqlColumnValue tmp_column_value = sql_field->column_values_[i]; + if (OB_FAIL(field_results_->fields_.at(duplicate_column_idx)->column_values_.push_back(tmp_column_value))) { + LOG_WARN("push_back failed", K(ret), K(sql_string_)); + } + } + } else if (OB_FAIL(field_results_->fields_.push_back(sql_field))) { + LOG_WARN("push_back failed", K(ret), K(sql_string_)); + } else { + ++field_results_->field_num_; + LOG_DEBUG("add sql_field", KPC(sql_field), K(field_results_->field_num_)); + } + } + if (OB_FAIL(ret) && NULL != sql_field) { + sql_field->reset(); + sql_field = NULL; + } + } + } + } + + return ret; +} + +int ObProxyDeleteStmt::handle_parse_result(const ParseResult &parse_result) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(parse_result.result_tree_) || OB_ISNULL(parse_result.result_tree_->children_[0])) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("parse result info is null unexpected", K(ret)); + } else { + ParseNode* node = parse_result.result_tree_->children_[0]; + if (node->type_ == T_DELETE) { + stmt_type_ = OBPROXY_T_DELETE; + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unknown node type", K(node->type_), K(ret)); + } + + for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { + ParseNode* tmp_node = node->children_[i]; + if (NULL == tmp_node) { + //do nothing + } else { + switch (tmp_node->type_) { + case T_DELETE_TABLE_NODE: + if (OB_FAIL(handle_delete_table_node(tmp_node))) { + LOG_WARN("handle delete table node failed", K(ret)); + } + break; + case T_HINT_OPTION_LIST: + ret = handle_hint_clause(tmp_node); + break; + case T_WHERE_CLAUSE: + if (OB_FAIL(handle_where_clause(tmp_node))) { + LOG_WARN("handle where clause failed", K(ret)); + } + break; + default: + has_unsupport_expr_type_ = true; + LOG_WARN("unknown node type", K_(tmp_node->type), K(ret)); + break; + } + } + } + } + + return ret; +} + +int ObProxyDeleteStmt::handle_delete_table_node(ParseNode *node) +{ + int ret = OB_SUCCESS; + for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { + ParseNode *tmp_node = node->children_[i]; + if (NULL == tmp_node) { + //do nothing + } else { + switch (tmp_node->type_) { + case T_TABLE_REFERENCES: + if (OB_FAIL(handle_table_references(tmp_node))) { + LOG_WARN("handle table references failed", K(ret)); + } + break; + default: + has_unsupport_expr_type_ = true; + LOG_WARN("unknown node type", K_(tmp_node->type), K(ret)); + } + } + } + return ret; +} + +int ObProxyUpdateStmt::handle_parse_result(const ParseResult &parse_result) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(parse_result.result_tree_) || OB_ISNULL(parse_result.result_tree_->children_[0])) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("parse result info is null unexpected", K(ret)); + } else { + ParseNode* node = parse_result.result_tree_->children_[0]; + + for (int i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { + ParseNode* tmp_node = node->children_[i]; + if (NULL == tmp_node) { + //do nothing + } else { + switch (tmp_node->type_) { + case T_TABLE_REFERENCES: + if (OB_FAIL(handle_table_references(tmp_node))) { + LOG_WARN("handle where clause failed", K(ret)); + } + break; + case T_HINT_OPTION_LIST: + ret = handle_hint_clause(tmp_node); + break; + case T_ASSIGN_LIST: + if (OB_FAIL(handle_assign_list(tmp_node))) { + LOG_WARN("handle where clause failed", K(ret)); + } + break; + case T_WHERE_CLAUSE: + if (OB_FAIL(handle_where_clause(tmp_node))) { + LOG_WARN("handle where clause failed", K(ret)); + } + break; + default: + has_unsupport_expr_type_ = true; + LOG_WARN("unknown node type", K_(tmp_node->type), K(ret)); + break; + } + } + } + } + return ret; +} + } // end of namespace obutils } // end of namespace obproxy diff --git a/src/obproxy/obutils/ob_proxy_stmt.h b/src/obproxy/obutils/ob_proxy_stmt.h index 68156c764d893256ebaa463a60c5ec88df155f51..39942588c88bde03bb2e5d853a2fee215cf190e0 100644 --- a/src/obproxy/obutils/ob_proxy_stmt.h +++ b/src/obproxy/obutils/ob_proxy_stmt.h @@ -56,76 +56,155 @@ private: ObProxyExprTable* table_expr_; }; +enum ShardingPosType { + SHARDING_POS_NONE = 0, + SHARDING_POS_DB, + SHARDING_POS_TABLE, +}; + +class ObProxyDbTablePos { +public: + ObProxyDbTablePos() : pos_(-1), name_(), type_(SHARDING_POS_NONE) {} + virtual ~ObProxyDbTablePos() {} + + void set_pos(const int32_t pos) { pos_ = pos; } + int32_t get_pos() { return pos_; } + + void set_type(const ShardingPosType type) { type_ = type; } + ShardingPosType get_type() { return type_; } + + void set_name(const ObString &name) { name_ = name; } + ObString &get_name() { return name_; } + + bool operator<(ObProxyDbTablePos &db_table_pos) + { + return pos_ < db_table_pos.get_pos(); + } + + TO_STRING_KV(K_(pos), K_(name), K_(type)); + +private: + int32_t pos_; + ObString name_; + ShardingPosType type_; +}; + class ObProxyStmt { public: - ObProxyStmt() : stmt_type_(OBPROXY_T_INVALID), allocator_(NULL) {} + ObProxyStmt(common::ObIAllocator& allocator) : stmt_type_(OBPROXY_T_INVALID), allocator_(allocator) {} virtual ~ObProxyStmt() {} virtual int handle_parse_result(const ParseResult &parse_result) = 0; void set_stmt_type(ObProxyBasicStmtType stmt_type) { stmt_type_ = stmt_type; } - void set_allocator(common::ObIAllocator* allocator) { allocator_ = allocator; } void set_sql_string(const common::ObString& sql_string) { sql_string_ = sql_string; } ObProxyBasicStmtType get_stmt_type() { return stmt_type_; } virtual int to_sql_string(common::ObSqlString& sql_string) = 0; protected: ObProxyBasicStmtType stmt_type_; - common::ObIAllocator* allocator_; + common::ObIAllocator& allocator_; common::ObString sql_string_; }; +enum SortListType { + SORT_LIST_NONE = 0, + SORT_LIST_IN_GROUP_BY, + SORT_LSIT_IN_ORDER_BY, + SORT_LIST_TYPE_MAX, +}; + class ObProxyDMLStmt : public ObProxyStmt { public: - ObProxyDMLStmt(): limit_offset_(0), limit_size_(-1), limit_token_off_(-1), field_results_(NULL) {} - virtual ~ObProxyDMLStmt() {} + typedef common::hash::ObHashMap ExprMap; + typedef common::ObSEArray TablePosArray; + typedef common::ObSEArray DbTablePosArray; + +public: + ObProxyDMLStmt(common::ObIAllocator& allocator); + virtual ~ObProxyDMLStmt(); + int init(); + virtual int handle_parse_result(const ParseResult &parse_result) + { + UNUSED(parse_result); + return common::OB_SUCCESS; + } + void set_table_name(const common::ObString& table_name) { table_name_ = table_name; } + void set_field_results(SqlFieldResult* real_field_results_ptr) { field_results_ = real_field_results_ptr; } + + //if 'table_name_' is not set, 'table_name_' means the first table name in SQL and is converted to UPPER CASE + const common::ObString& get_table_name() const { return table_name_; } + SqlFieldResult& get_dml_field_result() { return dml_field_results_; } + + bool has_unsupport_expr_type() const { return has_unsupport_expr_type_; } + ExprMap& get_table_exprs_map() { return table_exprs_map_; } + TablePosArray& get_table_pos_array() { return table_pos_array_; } + DbTablePosArray& get_db_table_pos_array() { return db_table_pos_array_; } + protected: + ObProxyExprType get_expr_type_by_node_type(const ObItemType& item_type); + int get_expr_by_type(ObProxyExpr* &expr, ObProxyExprType type); + + //for from + int handle_from_list(ParseNode* node); + int handle_table_node_to_expr(ParseNode* node); + int get_table_and_db_expr(ParseNode* node, ObProxyExprTable* &expr_table); + int handle_table_and_db_node(ParseNode* node, ObProxyExprTable* &expr_table); + //for from in delete and update + int handle_table_references(ParseNode *node); + + //for where + int handle_where_clause(ParseNode* node); + + //for set + int handle_assign_list(ParseNode *node); + + //for column + int handle_column_and_value(ParseNode* node); + int handle_varchar_node_in_column_value(ParseNode* node, SqlField& sql_field); + int handle_expr_list_node_in_column_value(ParseNode* node, SqlField& sql_field); + int handle_column_ref_in_list(ParseNode *node); + int column_ref_to_expr(ParseNode* node, ObProxyExpr* &expr, ObProxyExprTable* &expr_table); + int condition_exprs_to_sql_string(common::ObSqlString& sql_string); int limit_to_sql_string(common::ObSqlString& sql_string); public: int limit_offset_; int limit_size_; int64_t limit_token_off_; - SqlFieldResult* field_results_; // pointer to parseResult - common::ObSEArray comments_; -}; -enum SortListType { - SORT_LIST_NONE = 0, - SORT_LIST_IN_GROUP_BY, - SORT_LSIT_IN_ORDER_BY, - SORT_LIST_TYPE_MAX, -}; + //pointer to parseResult, default point to 'dml_field_results_' + //if 'field_results_' is not set, ObProxyDMLStmt save the parseResult in 'dml_field_results_' + //if 'field_results_' is set by caller, caller need save the parseResult + SqlFieldResult* field_results_; + SqlFieldResult dml_field_results_; -class ObProxySelectStmt : public ObProxyDMLStmt -{ + common::ObSEArray comments_; + // Store dml related information + common::ObSEArray column_name_array_; + common::ObString table_name_; + +protected: + bool is_inited_; + bool has_unsupport_expr_type_; + ExprMap table_exprs_map_; + ExprMap alias_table_map_; + common::ObSEArray table_pos_array_; + common::ObSEArray db_table_pos_array_; + +/*for sub select*/ public: - ObProxySelectStmt(); - virtual ~ObProxySelectStmt(); - int init(); - virtual int handle_parse_result(const ParseResult &parse_result); int handle_project_list(ParseNode* node); int handle_project_string(ParseNode* node); - int handle_from_list(ParseNode* node); int handle_hint_clause(ParseNode* node); - int handle_where_clause(ParseNode* node); int handle_groupby_clause(ParseNode* node); int handle_orderby_clause(ParseNode* node); int handle_limit_clause(ParseNode* node); + int handle_union_clause(ParseNode* node); int handle_comment_list(const ParseResult &parse_result); virtual int to_sql_string(common::ObSqlString& sql_string); bool has_for_update() const { return has_for_update_; } - bool has_unsupport_expr_type() const { return has_unsupport_expr_type_; } - void set_table_name(const common::ObString& table_name) { table_name_ = table_name; } int64_t get_from_token_off() { return from_token_off_; } -public: - typedef common::hash::ObHashMap ExprMap; - typedef common::ObSEArray TablePosArray; - -public: - ExprMap& get_table_exprs_map() { return table_exprs_map_; } - TablePosArray& get_table_pos_array() { return table_pos_array_; } - -private: +protected: int project_string_to_expr(ParseNode* node, ObProxyExpr* &expr); int string_node_to_expr(ParseNode* node, ObProxyExpr* &expr, ParseNode* string_node = NULL); int alias_node_to_expr(ParseNode* node, ObProxyExpr* &expr, ParseNode* string_node = NULL); @@ -138,50 +217,99 @@ private: int max_node_to_expr(ParseNode* node, ObProxyExpr* &expr); int min_node_to_expr(ParseNode* node, ObProxyExpr* &expr); - int column_ref_to_expr(ParseNode* node, ObProxyExpr* &expr, ObProxyExprTable* &expr_table); int get_const_expr(ParseNode* node, ObProxyExpr* &expr); int get_sharding_const_expr(ParseNode* node, ObProxyExpr* &expr); - int get_expr_by_type(ObProxyExpr* &expr, ObProxyExprType type); - ObProxyExprType get_expr_type_by_node_type(const ObItemType& item_type); - - int get_table_and_db_expr(ParseNode* node, ObProxyExprTable* &expr_table); - int handle_table_node_to_expr(ParseNode* node); - int handle_table_and_db_node(ParseNode* node, ObProxyExprTable* &expr_table); int handle_table_and_db_in_hint(ParseNode* node); - //for where - int handle_where_node(ParseNode* node); - int handle_where_expr_list_node(ParseNode* node, SqlField& sql_field); - int handle_varchar_node_in_where_condition(ParseNode* node, SqlField& sql_field); + //for group by int handle_with_rollup_in_groupby(ParseNode* node); int handle_sort_list_node(ParseNode* node, const SortListType& sort_list_type); int handle_sort_key_node(ParseNode* node, ObProxyExpr* &expr, const SortListType& sort_list_type); -private: +protected: + int do_handle_parse_result(ParseNode* node); int comments_to_sql_string(common::ObSqlString& sql_string); int hint_exprs_to_sql_string(common::ObSqlString& sql_string); int select_exprs_to_sql_string(common::ObSqlString& sql_string); int table_exprs_to_sql_string(common::ObSqlString& sql_string); int group_by_exprs_to_sql_string(common::ObSqlString& sql_string); int order_by_exprs_to_sql_string(common::ObSqlString& sql_string); -private: + int check_node_has_agg(ParseNode* node); public: common::ObSEArray select_exprs_; common::ObSEArray group_by_exprs_; //select groupby expression common::ObSEArray order_by_exprs_; -private: - common::ObString table_name_; - bool is_inited_; +protected: bool has_rollup_; bool has_for_update_; - bool has_unsupport_expr_type_; int64_t from_token_off_; - ExprMap table_exprs_map_; - ExprMap alias_table_map_; - common::ObSEArray table_pos_array_; + int64_t t_case_level_; }; + +class ObProxySelectStmt : public ObProxyDMLStmt +{ +public: + ObProxySelectStmt(common::ObIAllocator& allocator) : ObProxyDMLStmt(allocator) {} + virtual ~ObProxySelectStmt() {} + virtual int handle_parse_result(const ParseResult &parse_result); +}; + +class ObProxyInsertStmt : public ObProxyDMLStmt +{ +public: + ObProxyInsertStmt(common::ObIAllocator& allocator) : ObProxyDMLStmt(allocator) {} + ~ObProxyInsertStmt() {} + int handle_parse_result(const ParseResult &parse_result); + int to_sql_string(common::ObSqlString& sql_string) + { + UNUSED(sql_string); + return common::OB_SUCCESS; + } +private: + int handle_single_table_insert(ParseNode *node); + int handle_insert_into(ParseNode *node); + int handle_value_list(ParseNode *node); + int handle_column_list(ParseNode *node); + int handle_value_vector(ParseNode *node); +private: + DISALLOW_COPY_AND_ASSIGN(ObProxyInsertStmt); +}; + +class ObProxyDeleteStmt : public ObProxyDMLStmt +{ +public: + ObProxyDeleteStmt(common::ObIAllocator& allocator) : ObProxyDMLStmt(allocator) {} + ~ObProxyDeleteStmt() {} + int handle_parse_result(const ParseResult &parse_result); + int to_sql_string(common::ObSqlString& sql_string) + { + UNUSED(sql_string); + return common::OB_SUCCESS; + } +private: + int handle_delete_table_node(ParseNode *node); +private: + DISALLOW_COPY_AND_ASSIGN(ObProxyDeleteStmt); +}; + + +class ObProxyUpdateStmt : public ObProxyDMLStmt +{ +public: + ObProxyUpdateStmt(common::ObIAllocator& allocator) : ObProxyDMLStmt(allocator) {} + ~ObProxyUpdateStmt() {} + int handle_parse_result(const ParseResult &parse_result); + int to_sql_string(common::ObSqlString& sql_string) + { + UNUSED(sql_string); + return common::OB_SUCCESS; + } +private: + DISALLOW_COPY_AND_ASSIGN(ObProxyUpdateStmt); +}; + } // end of namespace obutils } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/obutils/ob_proxy_string_utils.cpp b/src/obproxy/obutils/ob_proxy_string_utils.cpp index 802876b9e7ff699f78f025044a3f28638f0a607c..c32caeb5ebc9bbafc237fb0f26856c7fe591c3ec 100644 --- a/src/obproxy/obutils/ob_proxy_string_utils.cpp +++ b/src/obproxy/obutils/ob_proxy_string_utils.cpp @@ -23,7 +23,7 @@ namespace obproxy { namespace obutils { -ObProxyVariantString::ObProxyVariantString():data_(NULL), data_size_(0) +ObProxyVariantString::ObProxyVariantString(): config_string_(), data_(NULL), data_size_(0) { } @@ -47,7 +47,7 @@ ObProxyVariantString& ObProxyVariantString::operator=(const ObProxyVariantString { if (&vstr != this) { reset(); - set_value(vstr.data_size_, vstr.data_); + set_value(vstr.config_string_.length(), vstr.config_string_.ptr()); } return *this; } @@ -92,6 +92,41 @@ bool ObProxyVariantString::set_value(const int32_t len, const char *value) return true; } +bool ObProxyVariantString::set_value_with_quote(const common::ObString &value, const char quote) +{ + return set_value_with_quote(value.length(), value.ptr(), quote); +} + +bool ObProxyVariantString::set_value_with_quote(const int32_t len, const char *value, const char quote) +{ + reset(); + data_size_ = len + 3; + data_ = (char*)ob_malloc(data_size_); + if (OB_ISNULL(data_)) { + LOG_WARN("ob_malloc failed", K_(data_size)); + return false; + } else { + data_[0] = quote; + MEMCPY(data_ + 1, value, len); + data_[len + 1] = quote; + data_[len + 2] = '\0'; + config_string_.assign_ptr(data_, len + 2); + } + + return true; +} + +void ObProxyVariantString::set_integer(const int64_t other) +{ + char buf[1024]; + const int32_t len = snprintf(buf, 1024, "%ld", other); + if (len <= 0 || len >= 1024) { + LOG_ERROR("snprintf failed", K(other)); + } else { + set_value(len, buf); + } +} + } // end of namespace obutils } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/obutils/ob_proxy_string_utils.h b/src/obproxy/obutils/ob_proxy_string_utils.h index 1e5ce7bd043a5792345fef8942bc9125ce19f2d4..8bd004329f18c7f068badc415427ff4d693833cb 100644 --- a/src/obproxy/obutils/ob_proxy_string_utils.h +++ b/src/obproxy/obutils/ob_proxy_string_utils.h @@ -44,7 +44,10 @@ public: bool init(common::ObMalloc* allocator, const int64_t mod_id); bool set_value(const common::ObString &value); bool set_value(const int32_t len, const char *value); + bool set_value_with_quote(const common::ObString &value, const char quote); + bool set_value_with_quote(const int32_t len, const char *value, const char quote); uint64_t hash(uint64_t seed = 0) const { return config_string_.hash(seed); } + void set_integer(const int64_t other); common::ObString config_string_; DECLARE_TO_STRING; private: diff --git a/src/obproxy/obutils/ob_proxy_table_processor.h b/src/obproxy/obutils/ob_proxy_table_processor.h index 84424575041e03c5918223bfd164cf3e651da756..f847b00070a90995c19bb60ed2733f91bbec3969 100644 --- a/src/obproxy/obutils/ob_proxy_table_processor.h +++ b/src/obproxy/obutils/ob_proxy_table_processor.h @@ -68,7 +68,7 @@ public: DECLARE_TO_STRING; public: - char proxy_ip_[common::OB_IP_STR_BUFF]; // ip primary key + char proxy_ip_[common::MAX_IP_ADDR_LENGTH]; // ip primary key char regist_time_str_[common::OB_MAX_TIME_STR_LENGTH + 1]; // the time when one obproxy register to observer char app_name_[common::OB_MAX_APP_NAME_LENGTH + 1]; // application proxy used for char binary_version_[OB_MAX_PROXY_BINARY_VERSION_LEN + 1]; // man readable version diff --git a/src/obproxy/obutils/ob_proxy_table_processor_utils.cpp b/src/obproxy/obutils/ob_proxy_table_processor_utils.cpp index e1fdc15f87b68863853d9dfe0f2ad1d2edb4218c..7e8600dcd58263e490d37feb75ca8233ee8a0580 100644 --- a/src/obproxy/obutils/ob_proxy_table_processor_utils.cpp +++ b/src/obproxy/obutils/ob_proxy_table_processor_utils.cpp @@ -453,7 +453,7 @@ int ObProxyTableProcessorUtils::fill_local_vt_cache(ObMysqlResultHandler &result int64_t tmp_real_str_len = 0; int64_t vid = 0; int64_t vport = 0; - char vip[OB_IP_STR_BUFF]; + char vip[MAX_IP_ADDR_LENGTH]; vip[0] = '\0'; ObString tenant_name; ObString cluster_name; @@ -472,7 +472,7 @@ int ObProxyTableProcessorUtils::fill_local_vt_cache(ObMysqlResultHandler &result while (OB_SUCC(ret) && OB_SUCC(result_handler.next())) { PROXY_EXTRACT_INT_FIELD_MYSQL(result_handler, "vid", vid, int64_t); - PROXY_EXTRACT_STRBUF_FIELD_MYSQL(result_handler, "vip", vip, OB_IP_STR_BUFF, tmp_real_str_len); + PROXY_EXTRACT_STRBUF_FIELD_MYSQL(result_handler, "vip", vip, MAX_IP_ADDR_LENGTH, tmp_real_str_len); PROXY_EXTRACT_INT_FIELD_MYSQL(result_handler, "vport", vport, int64_t); PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(result_handler, "tenant_name", tenant_name); PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(result_handler, "cluster_name", cluster_name); @@ -506,8 +506,7 @@ int ObProxyTableProcessorUtils::fill_local_vt_cache(ObMysqlResultHandler &result if (OB_ISNULL(vip_tenant = op_alloc(ObVipTenant))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to alloc memory for ObVipTenant", K(ret)); - } else if (FALSE_IT(vip_tenant->vip_addr_.set(ObAddr::convert_ipv4_addr(vip), - static_cast(vport), vid))) { + } else if (FALSE_IT(vip_tenant->vip_addr_.set(vip, static_cast(vport), vid))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to set vip_addr", K(vip), K(vport), K(vid), K(ret)); } else if (OB_FAIL(vip_tenant->set_tenant_cluster(tenant_name, cluster_name))) { @@ -522,16 +521,47 @@ int ObProxyTableProcessorUtils::fill_local_vt_cache(ObMysqlResultHandler &result } else if (OB_FAIL(cache_map.unique_set(vip_tenant))) { LOG_WARN("fail to insert one vip_tenant into cache_map", K(*vip_tenant), K(ret)); } else { - LOG_DEBUG("succ to insert one vip_tenant into cache_map", K(*vip_tenant)); - vip_tenant = NULL; - vid = 0; - vip[0] = '\0'; - vport = 0; - tenant_name.reset(); - cluster_name.reset(); - info_config = NULL; - request_target_type = -1; - rw_type = -1; + char request_target_buf[32]; + char rw_buf[32]; + ObString request_target_string; + ObString rw_string; + int32_t request_len = snprintf(request_target_buf, sizeof(request_target_buf), "%ld", request_target_type); + int32_t rw_len = snprintf(rw_buf, sizeof(rw_buf), "%ld", rw_type); + request_target_string.assign_ptr(request_target_buf, request_len); + rw_string.assign_ptr(rw_buf, rw_len); + if (OB_FAIL(get_global_config_processor().store_proxy_config_with_level( + vid, vip, vport, "", "", "proxy_tenant_name", tenant_name, "LEVEL_VIP"))) { + LOG_WARN("store proxy_tenant_name failed", K(vid), K(vip), K(vport), K(tenant_name), K(cluster_name), K(ret)); + } else if (OB_FAIL(get_global_config_processor().store_proxy_config_with_level( + vid, vip, vport, "", "", "rootservice_cluster_name", cluster_name, "LEVEL_VIP"))) { + LOG_WARN("store rootservice_cluster_name failed", K(vid), K(vip), K(vport), K(tenant_name), K(cluster_name), K(ret)); + } + if (OB_SUCC(ret) && -1 != rw_type) { + if (OB_FAIL(get_global_config_processor().store_proxy_config_with_level( + vid, vip, vport, tenant_name, cluster_name, "obproxy_read_only", rw_string, "LEVEL_VIP"))) { + LOG_WARN("store obporxy_read_only failed", K(vid), K(vip), K(vport), K(tenant_name), K(cluster_name), K(rw_type), K(ret)); + } + } + if (OB_SUCC(ret) && -1 != request_target_type) { + if (OB_FAIL(get_global_config_processor().store_proxy_config_with_level( + vid, vip, vport, tenant_name, cluster_name, "obproxy_read_consistency", request_target_string, "LEVEL_VIP"))) { + LOG_WARN("store obproxy_read_consistency failed", K(vid), K(vip), K(vport), K(tenant_name), K(cluster_name), K(request_target_type), K(ret)); + } + } + if (OB_SUCC(ret)) { + LOG_DEBUG("succ to insert one vip_tenant into cache_map", K(*vip_tenant)); + vip_tenant = NULL; + vid = 0; + vip[0] = '\0'; + vport = 0; + tenant_name.reset(); + cluster_name.reset(); + info_config = NULL; + request_target_type = -1; + rw_type = -1; + request_target_string.reset(); + rw_string.reset(); + } } }//end if OB_SUCCESS }//end of while @@ -554,23 +584,24 @@ int ObProxyTableProcessorUtils::fill_local_vt_cache(ObMysqlResultHandler &result int ObProxyTableProcessorUtils::get_proxy_local_addr(ObAddr &addr) { int ret = OB_SUCCESS; - char ip_str[OB_IP_STR_BUFF] = {'\0'}; + char ip_str[MAX_IP_ADDR_LENGTH] = {'\0'}; const ObHotUpgraderInfo &info = get_global_hot_upgrade_info(); in_port_t port = 0; ObIpAddr inbound_ip; // get inbound ip and port if (OB_LIKELY(info.is_inherited_)) { - if (OB_UNLIKELY(NO_FD == info.fd_)) { + // Does not support ipv6 yet + if (OB_UNLIKELY(NO_FD == info.ipv4_fd_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("this process is inherited born, but listen fd is invalid", - "is_inherited", info.is_inherited_, "fd", info.fd_, K(ret)); + "is_inherited", info.is_inherited_, "fd", info.ipv4_fd_, K(ret)); } else { struct sockaddr sock_addr; int64_t namelen = sizeof(sock_addr); memset(&sock_addr, 0, namelen); - if (OB_FAIL(ObSocketManager::getsockname(info.fd_, &sock_addr , &namelen))) { - LOG_WARN("fail to get sock name", K(info.fd_), K(ret)); + if (OB_FAIL(ObSocketManager::getsockname(info.ipv4_fd_, &sock_addr , &namelen))) { + LOG_WARN("fail to get sock name", K(info.ipv4_fd_), K(ret)); } else { struct sockaddr_in *ain = (sockaddr_in *)&sock_addr; inbound_ip.assign(sock_addr); @@ -590,7 +621,7 @@ int ObProxyTableProcessorUtils::get_proxy_local_addr(ObAddr &addr) // check valid if (OB_SUCC(ret)) { - inbound_ip.get_ip_str(ip_str, OB_IP_STR_BUFF); + inbound_ip.get_ip_str(ip_str, MAX_IP_ADDR_LENGTH); ObAddr any_addr(ObAddr::IPV4, INADDR_ANY_IP, port); ObAddr local_addr(ObAddr::IPV4, INADDR_LOOPBACK_IP, port); ObAddr inbound_addr(ObAddr::IPV4, ip_str, port); @@ -600,15 +631,15 @@ int ObProxyTableProcessorUtils::get_proxy_local_addr(ObAddr &addr) // if inbound_addr == 0.0.0.0 or 127.0.0.1, we treat it as not user specified ip, // and in this case, we get one local net addr; if (inbound_addr == any_addr || inbound_addr == local_addr) { - memset(ip_str, 0, OB_IP_STR_BUFF); - if (OB_FAIL(get_one_local_addr(ip_str, OB_IP_STR_BUFF))) { + memset(ip_str, 0, MAX_IP_ADDR_LENGTH); + if (OB_FAIL(get_one_local_addr(ip_str, MAX_IP_ADDR_LENGTH))) { LOG_WARN("fail to get one local addr", K(ret)); } } } if (OB_SUCC(ret)) { - addr.set_ipv4_addr(ip_str, port); + addr.set_ip_addr(ip_str, port); if (OB_UNLIKELY(!addr.is_valid())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid addr", K(addr), K(ret)); diff --git a/src/obproxy/obutils/ob_resource_pool_processor.cpp b/src/obproxy/obutils/ob_resource_pool_processor.cpp index 13e75ee14cb3318a76a037746f2ef5748ad14c72..7a343bfd8a3796335b41f47f82e620cab955c62a 100644 --- a/src/obproxy/obutils/ob_resource_pool_processor.cpp +++ b/src/obproxy/obutils/ob_resource_pool_processor.cpp @@ -25,6 +25,9 @@ #include "proxy/mysqllib/ob_proxy_auth_parser.h" #include "proxy/client/ob_mysql_proxy.h" #include "obutils/ob_async_common_task.h" +#include "lib/container/ob_array_iterator.h" +#include "lib/container/ob_se_array_iterator.h" +#include "lib/encrypt/ob_encrypted_helper.h" using namespace obsys; using namespace oceanbase::common; @@ -44,7 +47,8 @@ namespace obutils { ObResourcePoolProcessor g_rp_processor; -const static char *CHEK_CLUSTER_ROLE_SQL = +const static char *CHECK_VERSION_SQL = "SELECT ob_version() AS cluster_version"; +const static char *CHEK_CLUSTER_INFO_SQL = "SELECT /*+READ_CONSISTENCY(WEAK)*/ cluster_role, cluster_status FROM oceanbase.%s LIMIT 1"; const static char *OBPROXY_V_DATABASE_TNAME = "v$ob_cluster"; const static char *INIT_SS_INFO_SQL = @@ -52,6 +56,13 @@ const static char *INIT_SS_INFO_SQL = "FROM oceanbase.%s ss left join oceanbase.%s zs " "ON zs.zone = ss.zone " "WHERE ss.svr_port > 0 ORDER BY ss.zone LIMIT %ld;"; +const static char *INIT_SS_INFO_SQL_V4 = + "SELECT /*READ_CONSISTENCY(WEAK)*/ parameters.value as cluster, zs.zone AS zone, zs.status AS zone_status, ss.status AS server_status, " + "zs.region AS region, zs.idc AS spare4, zs.type AS spare5, ss.svr_ip AS svr_ip, ss.sql_port AS svr_port, " + "ss.start_service_time is not null AS start_service_time, ss.stop_time is not null as stop_time " + "FROM oceanbase.%s ss left join oceanbase.%s zs " + "ON zs.zone = ss.zone join V$OB_PARAMETERS parameters " + "WHERE ss.svr_port > 0 and parameters.name = 'cluster' ORDER BY ss.zone LIMIT %ld;"; const static char *PRIMARY_ROLE = "PRIMARY"; const static char *ROLE_VALID = "VALID"; @@ -219,14 +230,103 @@ int ObIDCListFetchCont::init_task() return ret; } +//---------------------ObCheckVersionCont-------------------------// +class ObCheckVersionCont : public ObAsyncCommonTask +{ +public: + ObCheckVersionCont(ObClusterResource *cr, const int64_t cluster_id, + ObContinuation *cb_cont, ObEThread *submit_thread) + : ObAsyncCommonTask(cb_cont->mutex_, "cluster_role_check_task", cb_cont, submit_thread), + check_result_(false), cr_(cr), cluster_id_(cluster_id) {} + virtual ~ObCheckVersionCont() {} + + virtual void destroy(); + virtual int init_task(); + virtual int finish_task(void *data); + virtual void *get_callback_data(); + +private: + bool check_result_; + ObClusterResource *cr_; + int64_t cluster_id_; + DISALLOW_COPY_AND_ASSIGN(ObCheckVersionCont); +}; + +void ObCheckVersionCont::destroy() +{ + if (NULL != cr_) { + // inc_ref() in add_async_task() + cr_->dec_ref(); + cr_ = NULL; + } + ObAsyncCommonTask::destroy(); +} + +int ObCheckVersionCont::init_task() +{ + int ret = OB_SUCCESS; + if (OB_FAIL(cr_->mysql_proxy_.async_read(this, CHECK_VERSION_SQL, pending_action_))) { + LOG_WARN("fail to async read", K(ret)); + } else if (OB_ISNULL(pending_action_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("pending action can not be NULL", K_(pending_action), K(ret)); + } + + return ret; +} + +int ObCheckVersionCont::finish_task(void *data) +{ + int ret = OB_SUCCESS; + const ObString &cluster_name = cr_->cluster_info_key_.cluster_name_.config_string_; + if (OB_ISNULL(data)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("data is null, fail to check clsuter version", K(cluster_name), K(ret)); + } else { + ObClientMysqlResp *resp = reinterpret_cast(data); + ObMysqlResultHandler handler; + handler.set_resp(resp); + if (OB_FAIL(handler.next())) { + check_result_ = true; + ret = OB_SUCCESS; + } else { + ObString cluster_version; + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(handler, "cluster_version", cluster_version); + int64_t version = 0; + for (int64_t i = 0; i < cluster_version.length() && cluster_version[i] != '.'; i++) { + version = version * 10 + cluster_version[i] - '0'; + } + + cr_->cluster_version_ = version; + + if (OB_SUCC(ret)) { + if (OB_UNLIKELY(OB_ITER_END != handler.next())) { // check if this is only one + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to get cluster version, there is more than one record", K(ret)); + } else { + check_result_ = true; + } + } + } + } + + return ret; +} + +inline void *ObCheckVersionCont::get_callback_data() +{ + return static_cast(&check_result_); +} + //---------------------ObClusterCheckRoleCont---------------------// -class ObClusterRoleCheckCont : public ObAsyncCommonTask +class ObClusterInfoCheckCont : public ObAsyncCommonTask { public: - ObClusterRoleCheckCont(ObClusterResource *cr, ObContinuation *cb_cont, ObEThread *submit_thread) + ObClusterInfoCheckCont(ObClusterResource *cr, const int64_t cluster_id, + ObContinuation *cb_cont, ObEThread *submit_thread) : ObAsyncCommonTask(cb_cont->mutex_, "cluster_role_check_task", cb_cont, submit_thread), - check_result_(false), cr_(cr) {} - virtual ~ObClusterRoleCheckCont() {} + check_result_(false), cr_(cr), cluster_id_(cluster_id) {} + virtual ~ObClusterInfoCheckCont() {} virtual void destroy(); virtual int init_task(); @@ -236,10 +336,11 @@ public: private: bool check_result_; ObClusterResource *cr_; - DISALLOW_COPY_AND_ASSIGN(ObClusterRoleCheckCont); + int64_t cluster_id_; + DISALLOW_COPY_AND_ASSIGN(ObClusterInfoCheckCont); }; -void ObClusterRoleCheckCont::destroy() +void ObClusterInfoCheckCont::destroy() { if (NULL != cr_) { // inc_ref() in add_async_task() @@ -249,12 +350,12 @@ void ObClusterRoleCheckCont::destroy() ObAsyncCommonTask::destroy(); } -int ObClusterRoleCheckCont::init_task() +int ObClusterInfoCheckCont::init_task() { int ret = OB_SUCCESS; char sql[OB_SHORT_SQL_LENGTH]; sql[0] = '\0'; - int64_t len = snprintf(sql, OB_SHORT_SQL_LENGTH, CHEK_CLUSTER_ROLE_SQL, OBPROXY_V_DATABASE_TNAME); + int64_t len = snprintf(sql, OB_SHORT_SQL_LENGTH, CHEK_CLUSTER_INFO_SQL, OBPROXY_V_DATABASE_TNAME); if (OB_UNLIKELY(len <= 0) || OB_UNLIKELY(len >= OB_SHORT_SQL_LENGTH)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to fill sql", K(len), K(ret)); @@ -268,7 +369,7 @@ int ObClusterRoleCheckCont::init_task() return ret; } -int ObClusterRoleCheckCont::finish_task(void *data) +int ObClusterInfoCheckCont::finish_task(void *data) { int ret = OB_SUCCESS; const ObString &cluster_name = cr_->cluster_info_key_.cluster_name_.config_string_; @@ -301,16 +402,23 @@ int ObClusterRoleCheckCont::finish_task(void *data) if (OB_UNLIKELY(OB_ITER_END != handler.next())) { // check if this is only one ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to get cluster role, there is more than one record", K(ret)); - } else if (OB_UNLIKELY(0 != cluster_role.case_compare(PRIMARY_ROLE)) - || OB_UNLIKELY(0 != cluster_status.case_compare(ROLE_VALID))) { - ret = OB_OBCONFIG_APPNAME_MISMATCH; - LOG_WARN("fail to check cluster role", "expected cluster role", PRIMARY_ROLE, - "remote cluster role", cluster_role, - "expected cluster status", ROLE_VALID, - "remore cluster status", cluster_status, K(ret)); + } else if (OB_DEFAULT_CLUSTER_ID == cluster_id_ + && get_global_proxy_config().with_config_server_ + && get_global_proxy_config().enable_standby) { + if (OB_UNLIKELY(0 != cluster_role.case_compare(PRIMARY_ROLE)) + || OB_UNLIKELY(0 != cluster_status.case_compare(ROLE_VALID))) { + ret = OB_OBCONFIG_APPNAME_MISMATCH; + LOG_WARN("fail to check cluster role", "expected cluster role", PRIMARY_ROLE, + "remote cluster role", cluster_role, + "expected cluster status", ROLE_VALID, + "remote cluster status", cluster_status, K(ret)); + } else { + check_result_ = true; + } } else { check_result_ = true; } + } } } @@ -318,7 +426,7 @@ int ObClusterRoleCheckCont::finish_task(void *data) return ret; } -inline void *ObClusterRoleCheckCont::get_callback_data() +inline void *ObClusterInfoCheckCont::get_callback_data() { return static_cast(&check_result_); } @@ -360,10 +468,18 @@ int ObServerStateInfoInitCont::init_task() int ret = OB_SUCCESS; char sql[OB_SHORT_SQL_LENGTH]; sql[0] = '\0'; - int64_t len = snprintf(sql, OB_SHORT_SQL_LENGTH, INIT_SS_INFO_SQL, - OB_ALL_VIRTUAL_PROXY_SERVER_STAT_TNAME, - OB_ALL_VIRTUAL_ZONE_STAT_TNAME, - INT64_MAX); + int64_t len = 0; + if (IS_CLUSTER_VERSION_LESS_THAN_V4(cr_->cluster_version_)) { + len = snprintf(sql, OB_SHORT_SQL_LENGTH, INIT_SS_INFO_SQL, + OB_ALL_VIRTUAL_PROXY_SERVER_STAT_TNAME, + OB_ALL_VIRTUAL_ZONE_STAT_TNAME, + INT64_MAX); + } else { + len = snprintf(sql, OB_SHORT_SQL_LENGTH, INIT_SS_INFO_SQL_V4, + DBA_OB_SERVERS_VNAME, + DBA_OB_ZONES_VNAME, + INT64_MAX); + } if (OB_UNLIKELY(len <= 0) || OB_UNLIKELY(len >= OB_SHORT_SQL_LENGTH)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to fill sql", K(len), K(ret)); @@ -396,7 +512,7 @@ int ObServerStateInfoInitCont::finish_task(void *data) const int64_t MAX_DISPLAY_STATUS_LEN = 64; char display_status_str[MAX_DISPLAY_STATUS_LEN]; ObServerStatus::DisplayStatus server_status = ObServerStatus::OB_DISPLAY_MAX; - char ip_str[OB_IP_STR_BUFF]; + char ip_str[MAX_IP_ADDR_LENGTH]; int64_t port = 0; int64_t tmp_real_str_len = 0; int64_t start_service_time = 0; @@ -425,10 +541,15 @@ int ObServerStateInfoInitCont::finish_task(void *data) server_state.reset(); zone_state.reset(); + if (IS_CLUSTER_VERSION_LESS_THAN_V4(cr_->cluster_version_)) { + PROXY_EXTRACT_INT_FIELD_MYSQL(result_handler, "is_merging", ss_info.is_merging_, int64_t); + } else { + ss_info.is_merging_ = 0; + } + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(result_handler, "zone", zone_name); - PROXY_EXTRACT_INT_FIELD_MYSQL(result_handler, "is_merging", ss_info.is_merging_, int64_t); PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(result_handler, "zone_status", zone_status); - PROXY_EXTRACT_STRBUF_FIELD_MYSQL(result_handler, "svr_ip", ip_str, OB_IP_STR_BUFF, tmp_real_str_len); + PROXY_EXTRACT_STRBUF_FIELD_MYSQL(result_handler, "svr_ip", ip_str, MAX_IP_ADDR_LENGTH, tmp_real_str_len); PROXY_EXTRACT_INT_FIELD_MYSQL(result_handler, "svr_port", port, int64_t); PROXY_EXTRACT_INT_FIELD_MYSQL(result_handler, "start_service_time", start_service_time, int64_t); PROXY_EXTRACT_INT_FIELD_MYSQL(result_handler, "stop_time", stop_time, int64_t); @@ -533,8 +654,8 @@ int ObServerStateInfoInitCont::finish_task(void *data) ret = OB_SUCCESS; continue; } else if (OB_ISNULL(ObServerStateRefreshUtils::get_zone_info_ptr(zones_state, zone_name))) { - LOG_INFO("this server can not find it's zone, maybe it's zone has been " - "deleted, so treat this server as deleted also", K(server_state), K(zone_name), K(zones_state)); + LOG_INFO("this server can not find it's zone, maybe it's zone has been " + "deleted, so treat this server as deleted also", K(server_state), K(zone_name), K(zones_state)); ret = OB_SUCCESS; continue; } else { @@ -562,7 +683,7 @@ int ObServerStateInfoInitCont::finish_task(void *data) for (int i = 0; (OB_SUCC(ret)) && (i < zone_names.count()); ++i) { ObString &each_zone_name = zone_names.at(i); ObServerStateInfo &each_servers_state = servers_state.at(i); - if (OB_ISNULL(each_servers_state.zone_state_ = + if (OB_ISNULL(each_servers_state.zone_state_ = ObServerStateRefreshUtils::get_zone_info_ptr(zones_state, each_zone_name))) { ret = OB_INVALID_ARGUMENT; LOG_WARN("unexpected situation, the corresponding zone_state has been searched before.", @@ -833,10 +954,15 @@ int ObClusterResourceCreateCont::add_async_task() this, &self_ethread()); } break; - case CHECK_CLUSTER_ROLE: - LOG_INFO("will add CHECK_CLUSTER_ROLE task", K(this), K_(cluster_name), K_(cluster_id)); + case CHECK_VERSION: + LOG_INFO("will add CHECK_VERSION task", K(this), K_(cluster_name), K_(cluster_id)); + created_cr_->inc_ref(); + async_cont = new(std::nothrow) ObCheckVersionCont(created_cr_, cluster_id_, this, &self_ethread()); + break; + case CHECK_CLUSTER_INFO: + LOG_INFO("will add CHECK_CLUSTER_INFO task", K(this), K_(cluster_name), K_(cluster_id)); created_cr_->inc_ref(); - async_cont = new(std::nothrow) ObClusterRoleCheckCont(created_cr_, this, &self_ethread()); + async_cont = new(std::nothrow) ObClusterInfoCheckCont(created_cr_, cluster_id_, this, &self_ethread()); break; case INIT_SS_INFO: LOG_INFO("will add INIT_SS_INFO task", K(this), K_(cluster_name), K_(cluster_id)); @@ -1060,14 +1186,17 @@ int ObClusterResourceCreateCont::handle_async_task_complete(void *data) result = *(static_cast(data)); if (result) { if (INIT_RS == init_status_) { + init_status_ = CHECK_VERSION; + } else if (CHECK_VERSION == init_status_) { if (OB_DEFAULT_CLUSTER_ID == cluster_id_ && get_global_proxy_config().with_config_server_ - && get_global_proxy_config().enable_standby) { - init_status_ = CHECK_CLUSTER_ROLE; + && get_global_proxy_config().enable_standby + && IS_CLUSTER_VERSION_LESS_THAN_V4(created_cr_->cluster_version_)) { + init_status_ = CHECK_CLUSTER_INFO; } else { init_status_ = INIT_SS_INFO; } - } else if (CHECK_CLUSTER_ROLE == init_status_) { + } else if (CHECK_CLUSTER_INFO == init_status_) { init_status_ = INIT_SS_INFO; } else if (INIT_SS_INFO == init_status_) { init_status_ = INIT_IDC_LIST; @@ -1102,7 +1231,7 @@ int ObClusterResourceCreateCont::handle_async_task_complete(void *data) LOG_WARN("fail to add rslist fetch task", K_(cluster_name), K(ret)); init_status_ = old_status; } - } else if (CHECK_CLUSTER_ROLE == init_status_) { + } else if (CHECK_CLUSTER_INFO == init_status_) { // 2. master cluster role is not primary, try to loop all sub cluster rs list result = true; const bool is_rslist = false; @@ -1350,7 +1479,7 @@ int ObClusterResourceCreateCont::build() if (OB_SUCC(ret) && INIT_BORN == init_status_) { if (OB_FAIL(created_cr_->init_local_config(rp_processor_.config_))) { - LOG_WARN("fail to build local"); + LOG_WARN("fail to build local", K(ret)); } else { init_status_ = INIT_RS; } @@ -1393,13 +1522,7 @@ int ObClusterResourceCreateCont::build() } else if (OB_FAIL(ObRouteUtils::build_and_add_sys_dummy_entry(cluster_name_, cluster_id_, rs_list, is_rslist))) { LOG_WARN("fail to build and add dummy entry", K_(cluster_name), K_(cluster_id), K(rs_list), K(ret)); } else { - if (OB_DEFAULT_CLUSTER_ID == cluster_id_ - && get_global_proxy_config().with_config_server_ - && get_global_proxy_config().enable_standby) { - init_status_ = CHECK_CLUSTER_ROLE; - } else { - init_status_ = INIT_SS_INFO; - } + init_status_ = CHECK_VERSION; LOG_DEBUG("try next status", K_(cluster_name), K_(cluster_id), K(new_failure_count), K(rs_list), K(is_rslist_from_local_), K(init_status_)); } @@ -1407,18 +1530,22 @@ int ObClusterResourceCreateCont::build() } } - if (OB_SUCC(ret) && CHECK_CLUSTER_ROLE == init_status_) { - int64_t cluster_id = OB_DEFAULT_CLUSTER_ID; - ObConfigServerProcessor &cs_processor = get_global_config_server_processor(); - if (OB_FAIL(cs_processor.get_master_cluster_id(cluster_name_, cluster_id) - || OB_DEFAULT_CLUSTER_ID == cluster_id)) { - // mayby no master on config server, here try a cluster rs list by random - const bool is_rslist = false; - ObSEArray rs_list; - if (OB_FAIL(cs_processor.get_next_master_cluster_rslist(cluster_name_, rs_list))) { - LOG_WARN("fail to get next master cluster rslist", K_(cluster_name)); - } else if (OB_FAIL(ObRouteUtils::build_and_add_sys_dummy_entry(cluster_name_, cluster_id_, rs_list, is_rslist))) { - LOG_WARN("fail to build and add dummy entry", K_(cluster_name), K_(cluster_id), K(rs_list), K(ret)); + if (OB_SUCC(ret) && CHECK_CLUSTER_INFO == init_status_) { + if (OB_DEFAULT_CLUSTER_ID == cluster_id_ + && get_global_proxy_config().with_config_server_ + && get_global_proxy_config().enable_standby) { + int64_t cluster_id = OB_DEFAULT_CLUSTER_ID; + ObConfigServerProcessor &cs_processor = get_global_config_server_processor(); + if (OB_FAIL(cs_processor.get_master_cluster_id(cluster_name_, cluster_id) + || OB_DEFAULT_CLUSTER_ID == cluster_id)) { + // mayby no master on config server, here try a cluster rs list by random + const bool is_rslist = false; + ObSEArray rs_list; + if (OB_FAIL(cs_processor.get_next_master_cluster_rslist(cluster_name_, rs_list))) { + LOG_WARN("fail to get next master cluster rslist", K_(cluster_name)); + } else if (OB_FAIL(ObRouteUtils::build_and_add_sys_dummy_entry(cluster_name_, cluster_id_, rs_list, is_rslist))) { + LOG_WARN("fail to build and add dummy entry", K_(cluster_name), K_(cluster_id), K(rs_list), K(ret)); + } } } @@ -1428,7 +1555,8 @@ int ObClusterResourceCreateCont::build() } if (OB_SUCC(ret) - && (INIT_SYSVAR == init_status_ + && (CHECK_VERSION == init_status_ + || INIT_SYSVAR == init_status_ || INIT_SS_INFO == init_status_ || INIT_IDC_LIST == init_status_)) { if (OB_FAIL(add_async_task())) { @@ -1464,6 +1592,8 @@ int ObClusterResource::init(const common::ObString &cluster_name, int64_t cluste } else if (OB_FAIL(pending_list_.init("cr init pending list", reinterpret_cast(&(reinterpret_cast (0))->link_)))) { LOG_WARN("fail to init pending list", K(ret)); + } else if (OB_FAIL(alive_addr_set_.create(4))) { + LOG_WARN("alive_addr_set create failed", K(ret)); } else { is_inited_ = true; version_ = version; @@ -1492,10 +1622,34 @@ int ObClusterResource::init_local_config(const ObResourcePoolConfig &config) int64_t timeout_ms = usec_to_msec(config.short_async_task_timeout_); const ObString user_name(ObProxyTableInfo::READ_ONLY_USERNAME); const ObString database(ObProxyTableInfo::READ_ONLY_DATABASE); - ObString password(get_global_proxy_config().observer_sys_password.str()); - ObString password1(get_global_proxy_config().observer_sys_password1.str()); + ObString cluster_name = cluster_info_key_.cluster_name_.config_string_; + ObConfigItem item; + char password[ENC_STRING_BUF_LEN]; + char password1[ENC_STRING_BUF_LEN]; + memset(password, 0, sizeof (password)); + memset(password1, 0, sizeof (password1)); + + ObVipAddr addr; + if (OB_FAIL(get_global_config_processor().get_proxy_config( + addr, cluster_name, "", ObProxyTableInfo::OBSERVER_SYS_PASSWORD, item))) { + LOG_WARN("get observer_sys_password config failed", K(cluster_name), K(ret)); + } else { + MEMCPY(password, item.str(), strlen(item.str())); + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(get_global_config_processor().get_proxy_config( + addr, cluster_name, "", ObProxyTableInfo::OBSERVER_SYS_PASSWORD1, item))) { + LOG_WARN("get observer_sys_password1 config failed", K(cluster_name), K(ret)); + } else { + MEMCPY(password1, item.str(), strlen(item.str())); + } + } - if (OB_FAIL(mysql_proxy_.init(timeout_ms, user_name, password, database, password1))) { + + if (OB_FAIL(ret)) { + // do nothing + } else if (OB_FAIL(mysql_proxy_.init(timeout_ms, user_name, password, database, cluster_name, password1))) { LOG_WARN("fail to init mysql proxy", K(ret)); } else if (OB_FAIL(rebuild_mysql_client_pool( get_global_resource_pool_processor().get_default_cluster_resource()))) { @@ -1542,24 +1696,42 @@ int ObClusterResource::init_local_config(const ObResourcePoolConfig &config) int ObClusterResource::init_server_state_processor(const ObResourcePoolConfig &config) { int ret = OB_SUCCESS; + ObConfigServerProcessor &cs_processor = get_global_config_server_processor(); + uint64_t last_rs_list_hash = 0; bool is_metadb = (0 == cluster_info_key_.cluster_name_.get_string().case_compare(OB_META_DB_CLUSTER_NAME)); - if (OB_ISNULL(ss_refresh_cont_ = op_alloc(ObServerStateRefreshCont))) { + if (OB_FAIL(cs_processor.get_rs_list_hash(cluster_info_key_.cluster_name_.config_string_, + cluster_info_key_.cluster_id_, last_rs_list_hash))) { + LOG_WARN("fail to get_last_rs_list_hash", K_(cluster_info_key), K(ret)); + } else if (OB_ISNULL(ss_refresh_cont_ = op_alloc(ObServerStateRefreshCont))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to alloc ObServerStateRefreshCont", K(ret)); - } else if (!is_metadb && OB_FAIL(ss_refresh_cont_->init(this, config.server_state_refresh_interval_))) { + } else if (!is_metadb && OB_FAIL(ss_refresh_cont_->init(this, config.server_state_refresh_interval_, last_rs_list_hash))) { LOG_WARN("fail to init server state processor", K_(cluster_info_key), K(ret)); - } else if (is_metadb && OB_FAIL(ss_refresh_cont_->init(this, config.metadb_server_state_refresh_interval_))) { + } else if (is_metadb && OB_FAIL(ss_refresh_cont_->init(this, config.metadb_server_state_refresh_interval_, last_rs_list_hash))) { LOG_WARN("fail to init metadb server state processor", K_(cluster_info_key), K(ret)); + } else if (!is_metadb && OB_ISNULL(detect_server_state_cont_ = op_alloc(ObDetectServerStateCont))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc ObDetectServerStateCont", K(ret)); + } else if (!is_metadb && OB_FAIL(detect_server_state_cont_->init(this, config.server_detect_refresh_interval_))) { + LOG_WARN("fail to init detect server state cont", K_(config.server_detect_refresh_interval), K(ret)); } else { bool imm = true; - if (OB_FAIL(ss_refresh_cont_->schedule_refresh_server_state(imm))){ - LOG_WARN("fail to start refresh server state", K(ret)); + if (OB_FAIL(ss_refresh_cont_->schedule_refresh_server_state(imm))) { + LOG_WARN("fail to start schedule refresh server state", K(ret)); + } else if (!is_metadb && OB_FAIL(detect_server_state_cont_->schedule_detect_server_state())) { + LOG_WARN("fail to start schedule detect server state", K(ret)); } } if (OB_FAIL(ret)) { - ss_refresh_cont_->kill_this(); - ss_refresh_cont_ = NULL; + if (NULL != ss_refresh_cont_) { + ss_refresh_cont_->kill_this(); + ss_refresh_cont_ = NULL; + } + if (NULL != detect_server_state_cont_) { + detect_server_state_cont_->kill_this(); + detect_server_state_cont_ = NULL; + } } return ret; } @@ -1655,6 +1827,8 @@ void ObClusterResource::destroy() int ret = OB_SUCCESS; if (OB_FAIL(stop_refresh_server_state())) { LOG_WARN("fail to stop refresh server state", K(ret)); + } else if (OB_FAIL(stop_detect_server_state())) { + LOG_WARN("fail to stop detect server state", K(ret)); } destroy_location_tenant_info(); @@ -1699,6 +1873,20 @@ int ObClusterResource::stop_refresh_server_state() return ret; } +int ObClusterResource::stop_detect_server_state() +{ + int ret = OB_SUCCESS; + if (NULL != detect_server_state_cont_) { + if (OB_ISNULL(g_event_processor.schedule_imm(detect_server_state_cont_, ET_CALL, DESTROY_SERVER_STATE_EVENT))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to schedule imm DESTROY_SERVER_STATE_EVENT", KPC_(detect_server_state_cont), K(ret)); + } + LOG_DEBUG("stop detect server state", KPC(this)); + detect_server_state_cont_ = NULL; + } + return ret; +} + int ObClusterResource::update_sys_ldg_info(ObSysLdgInfo *sys_ldg_info) { int ret = OB_SUCCESS; @@ -1722,53 +1910,80 @@ void ObClusterResource::destroy_location_tenant_info() iter != location_tenant_info_map_.end();) { tmp_iter = iter; ++iter; - op_free(&(*tmp_iter)); + ObLocationTenantInfo *tmp_ptr = &(*tmp_iter); + tmp_ptr->dec_ref(); + tmp_ptr = NULL; } location_tenant_info_map_.reset(); } -int ObClusterResource::update_location_tenant_info(ObSEArray& tenant_array, - ObSEArray& locality_array) +int ObClusterResource::update_location_tenant_info(ObSEArray &tenant_array, + ObSEArray &locality_array, + ObSEArray &primary_zone_array) { int ret = OB_SUCCESS; - if (tenant_array.count() != 0 && (tenant_array.count() == locality_array.count())) { + + int64_t tenant_num = tenant_array.count(); + int64_t locality_num = locality_array.count(); + int64_t primary_zone_num = primary_zone_array.count(); + + if (tenant_num != 0 + && (tenant_num == locality_num + && tenant_num == primary_zone_num)) { DRWLock::WRLockGuard lock(location_tenant_info_lock_); ObLocationTenantInfoHashMap::iterator tmp_iter; for (ObLocationTenantInfoHashMap::iterator iter = location_tenant_info_map_.begin(); - iter != location_tenant_info_map_.end();) { + iter != location_tenant_info_map_.end();) { tmp_iter = iter; ++iter; - op_free(&(*tmp_iter)); + ObLocationTenantInfo *tmp_ptr = &(*tmp_iter); + tmp_ptr->dec_ref(); + tmp_ptr = NULL; } location_tenant_info_map_.reset(); + LOG_DEBUG("reset location tenant info map done"); for (int64_t i = 0; OB_SUCC(ret) && i < tenant_array.count(); i++) { ObString &tenant_name = tenant_array.at(i); ObString &locality = locality_array.at(i); - ObLocationTenantInfo *info = op_alloc(ObLocationTenantInfo); - if (OB_ISNULL(info)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("update location tenant info allo memory failed", K(ret)); - } else if (tenant_name.length() >= OB_MAX_TENANT_NAME_LENGTH) { + ObString &primary_zone = primary_zone_array.at(i); + + if (tenant_name.length() >= OB_MAX_TENANT_NAME_LENGTH + || primary_zone.length() >= MAX_ZONE_LIST_LENGTH) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("tenant_name is too long", K(ret), K(tenant_name)); + LOG_WARN("tenant name or primary zone string oversize", K(ret), K(tenant_name), K(primary_zone)); } else { - MEMCPY(info->tenant_name_str_, tenant_name.ptr(), tenant_name.length()); - info->tenant_name_.assign_ptr(info->tenant_name_str_, tenant_name.length()); - info->version_ = locality.hash(); - if (OB_FAIL(location_tenant_info_map_.unique_set(info))) { - LOG_ERROR("fail to add location tenant info, already exist, never happen", - K(tenant_name), K_(cluster_info_key)); - if (NULL != info) { - op_free(info); + ObLocationTenantInfo *info = NULL; + if (OB_ISNULL(info = op_alloc(ObLocationTenantInfo))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("update location tenant info alloc memory failed", K(ret)); + } else { + info->inc_ref(); + MEMCPY(info->tenant_name_str_, tenant_name.ptr(), tenant_name.length()); + info->tenant_name_.assign_ptr(info->tenant_name_str_, tenant_name.length()); + info->version_ = locality.hash(); + + // cut origin primary zone string to priority array & weight array + if (OB_FAIL(info->resolve_location_tenant_info_primary_zone(primary_zone))) { + LOG_ERROR("fail to resolve location tenant info primary zone", K(ret), K(primary_zone), K(tenant_name)); + } else if (OB_FAIL(location_tenant_info_map_.unique_set(info))) { + LOG_ERROR("fail to add location tenant info, already exist, never happen", + K(tenant_name), K_(cluster_info_key)); + } else { + LOG_DEBUG("succ to add tenant location info to map", KPC(info)); + } + + if (OB_FAIL(ret) && OB_NOT_NULL(info)) { + info->dec_ref(); info = NULL; } } } - } - } + } // for + } // if in wlock + return ret; } @@ -1813,7 +2028,11 @@ uint64_t ObClusterResource::get_location_tenant_version(const ObString &tenant_n ObLocationTenantInfo *info = NULL; DRWLock::RDLockGuard lock(location_tenant_info_lock_); if (OB_FAIL(location_tenant_info_map_.get_refactored(tenant_name, info))) { - LOG_WARN("get tenant version failed", K(tenant_name)); + if (OB_LIKELY(ret == OB_HASH_NOT_EXIST)) { + LOG_DEBUG("get tenant version failed", K(tenant_name)); + } else { + LOG_WARN("get tenant version failed, please check", K(ret), K(tenant_name)); + } } else if (NULL != info) { version = info->version_; } @@ -1822,6 +2041,63 @@ uint64_t ObClusterResource::get_location_tenant_version(const ObString &tenant_n return version; } +int ObClusterResource::get_location_tenant_info(const ObString &tenant_name, ObLocationTenantInfo *&info_out) +{ + int ret = OB_SUCCESS; + + if (!tenant_name.empty() && tenant_name != OB_SYS_TENANT_NAME) { + ObLocationTenantInfo *info = NULL; + DRWLock::RDLockGuard lock(location_tenant_info_lock_); + if (OB_FAIL(location_tenant_info_map_.get_refactored(tenant_name, info))) { + LOG_DEBUG("do not find location tenant info from map, maybe no right to visit table", K(ret), K(tenant_name)); + } else if (info != NULL) { + info->inc_ref(); + info_out = info; + LOG_DEBUG("find location tenant info from map", K(info)); + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected error, get null ptr from map", K(tenant_name)); + } + } + + return ret; +} + +void ObLocationTenantInfo::destroy() +{ + op_free(this); +} + +/* + * the primary_zone from __all_tenant of each tenant could be empty/RANDOM, do not save it + * use the tenant location cache while no primary zone appropriately + */ +int ObLocationTenantInfo::resolve_location_tenant_info_primary_zone(ObString &primary_zone) +{ + int ret = OB_SUCCESS; + + if (!primary_zone.empty() + && 0 != primary_zone.case_compare(OB_RANDOM_PRIMARY_ZONE)) { + // save origin str + MEMCPY(primary_zone_str_, primary_zone.ptr(), primary_zone.length()); + primary_zone_.assign_ptr(primary_zone_str_, primary_zone.length()); + + // resolve to zone priority array + // resolve to zone weight priority array + if (OB_FAIL(split_weight_group(primary_zone_, primary_zone_prio_array_, primary_zone_prio_weight_array_))) { + LOG_WARN("fail to resolve primary zone", K(ret), K(primary_zone_)); + } else if (primary_zone_prio_array_.count() != primary_zone_prio_weight_array_.count()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected array count check", K(tenant_name_), K(version_), K(primary_zone_prio_array_.count()), + K(primary_zone_prio_weight_array_.count())); + } else { + LOG_DEBUG("succ to resolve primary zone", KPC(this)); + } + } + + return ret; +} + ObResourceDeleteActor *ObResourceDeleteActor::alloc(ObClusterResource *cr) { int ret = OB_SUCCESS; @@ -1886,6 +2162,10 @@ bool ObResourcePoolConfig::update(const ObProxyConfig &config) congestion_failure_threshold_ = config.congestion_failure_threshold; bret = true; } + if (server_detect_refresh_interval_ != config.server_detect_refresh_interval.get()) { + server_detect_refresh_interval_ = config.server_detect_refresh_interval; + bret = true; + } return bret; } @@ -1913,6 +2193,8 @@ int ObResourcePoolProcessor::init(ObProxyConfig &config, proxy::ObMysqlProxy &me // impossible } else if (OB_FAIL(default_cr_->init_local_config(config_))) { LOG_WARN("fail to build local default cluster resource", K(ret)); + } else if (OB_FAIL(ip_set_.create(8))) { + LOG_WARN("ip_set create failed", K(ret)); } else { default_cr_->inc_ref(); default_sysvar_set_->inc_ref(); @@ -2184,6 +2466,7 @@ int ObResourcePoolProcessor::update_config_param() const int64_t server_state_refresh_interval = config_.server_state_refresh_interval_; const int64_t metadb_server_state_refresh_interval = config_.metadb_server_state_refresh_interval_; const int64_t mysql_client_timeout_ms = (config_.short_async_task_timeout_ / 1000); + const int64_t detect_server_state_refresh_interval = config_.server_detect_refresh_interval_; ObCongestionControlConfig *control_config = NULL; if (OB_ISNULL(control_config = op_alloc(ObCongestionControlConfig))) { ret = OB_ALLOCATE_MEMORY_FAILED; @@ -2213,7 +2496,11 @@ int ObResourcePoolProcessor::update_config_param() LOG_WARN("fail to update metadb state refresh task interval", K(cr_iter->cluster_info_key_), K(ret)); } else if (OB_FAIL(cr_iter->mysql_proxy_.set_timeout_ms(mysql_client_timeout_ms))) { LOG_WARN("fail to update mysql proxy timeout", K(mysql_client_timeout_ms), K(ret)); - } else {} + } else if ((NULL != cr_iter->ss_refresh_cont_) + && !is_metadb + && OB_FAIL(cr_iter->detect_server_state_cont_->set_detect_server_state_interval(detect_server_state_refresh_interval))) { + LOG_WARN("fail to set detect server state interval", K(ret)); + } } } // end for control_config->dec_ref(); @@ -2391,6 +2678,8 @@ int ObResourcePoolProcessor::delete_cluster_resource(const ObString &cluster_nam RESOURCE_POOL_INCREMENT_DYN_STAT(DELETE_CLUSTER_RESOURCE_COUNT); if (OB_FAIL(cr->stop_refresh_server_state())) { LOG_WARN("fail to stop refresh server state", K(ret)); + } else if (OB_FAIL(cr->stop_detect_server_state())) { + LOG_WARN("fail to stop detect server state", K(ret)); } else { // push to every work thread int64_t thread_count = g_event_processor.thread_count_for_type_[ET_CALL]; diff --git a/src/obproxy/obutils/ob_resource_pool_processor.h b/src/obproxy/obutils/ob_resource_pool_processor.h index dbb4b2a952567680aff37f1f5040b8312bce079e..b484795702269de5ed8135e79286733d7ce62da3 100644 --- a/src/obproxy/obutils/ob_resource_pool_processor.h +++ b/src/obproxy/obutils/ob_resource_pool_processor.h @@ -23,6 +23,7 @@ #include "obutils/ob_safe_snapshot_manager.h" #include "obutils/ob_proxy_json_config_info.h" #include "lib/lock/ob_drw_lock.h" +#include "lib/hash/ob_hashset.h" namespace oceanbase { @@ -35,6 +36,8 @@ class ObTableEntry; } namespace obutils { +const char *const OB_RANDOM_PRIMARY_ZONE = "RANDOM"; + #define CLUSTER_RESOURCE_CREATE_EVENT (CLUSTER_RESOURCE_EVENT_EVENTS_START + 1) #define CLUSTER_RESOURCE_INFORM_OUT_EVENT (CLUSTER_RESOURCE_EVENT_EVENTS_START + 2) #define CLUSTER_RESOURCE_CREATE_COMPLETE_EVENT (CLUSTER_RESOURCE_EVENT_EVENTS_START + 3) @@ -102,7 +105,8 @@ enum ObClusterResourceInitState { INIT_BORN = 0, INIT_RS, - CHECK_CLUSTER_ROLE, + CHECK_VERSION, + CHECK_CLUSTER_INFO, INIT_SS_INFO, INIT_IDC_LIST, INIT_SYSVAR, @@ -171,6 +175,48 @@ private: typedef int (event::ObContinuation::*process_cr_pfn) (void *data); + +typedef common::ObSEArray PrimaryZonePrioArrayType; +typedef common::ObSEArray PrimaryZonePrioWeightArrayType; + +class ObLocationTenantInfo : public common::ObSharedRefCount +{ +public: + ObLocationTenantInfo() : tenant_name_(), version_(0), primary_zone_(), + primary_zone_prio_array_(), primary_zone_prio_weight_array_() + { + memset(tenant_name_str_, 0x0, sizeof(tenant_name_str_)); + memset(primary_zone_str_, 0x0, sizeof(primary_zone_str_)); + } + virtual ~ObLocationTenantInfo() {} + virtual void free() { destroy(); }; + void destroy(); + + virtual int64_t to_string(char *buf, const int64_t buf_len) const + { + int64_t pos = 0; + J_OBJ_START(); + J_KV(K_(tenant_name), K_(version), K_(primary_zone), + K_(primary_zone_prio_array), K_(primary_zone_prio_weight_array)); + J_OBJ_END(); + return pos; + } + + int resolve_location_tenant_info_primary_zone(common::ObString &primary_zone); + +public: + common::ObString tenant_name_; + char tenant_name_str_[common::OB_MAX_TENANT_NAME_LENGTH]; + uint64_t version_; + + common::ObString primary_zone_; + char primary_zone_str_[common::MAX_ZONE_LIST_LENGTH]; //real:MAX_ZONE_LENGTH*MAX_ZONE_NUM, this is mem optimization + PrimaryZonePrioArrayType primary_zone_prio_array_; //pz priority zone name array, related to char buf + PrimaryZonePrioWeightArrayType primary_zone_prio_weight_array_; //pz priority weight array + + LINK(ObLocationTenantInfo, cr_link_); +}; + class ObProxyConfig; class ObResourcePoolConfig; class ObClusterResource : public common::ObSharedRefCount @@ -178,18 +224,18 @@ class ObClusterResource : public common::ObSharedRefCount public: ObClusterResource() : sys_var_set_processor_(), congestion_manager_(), ss_refresh_cont_(NULL), - mysql_proxy_(), server_state_version_(0), dummy_entry_(NULL), + detect_server_state_cont_(NULL), mysql_proxy_(), server_state_version_(0), dummy_entry_(NULL), cluster_info_key_(), last_access_time_ns_(0), deleting_completed_thread_num_(0), version_(0), fetch_rslist_task_count_(0), fetch_idc_list_task_count_(0), last_idc_list_refresh_time_ns_(0), last_rslist_refresh_time_ns_(0), - pending_list_(), is_inited_(false), cr_state_(CR_BORN), sys_ldg_info_map_(), + pending_list_(), cluster_version_(0), alive_addr_set_(), is_inited_(false), cr_state_(CR_BORN), sys_ldg_info_map_(), sys_ldg_info_lock_(), location_tenant_info_lock_(), location_tenant_info_map_() {} virtual ~ObClusterResource() {} virtual void free(); bool is_congestion_avail() { return congestion_manager_.is_congestion_avail(); } bool is_base_servers_added() const { return congestion_manager_.is_base_servers_added(); } - int init(const common::ObString &cluster_name, const int64_t cluster_id, const int64_t versin); + int init(const common::ObString &cluster_name, const int64_t cluster_id, const int64_t version); int init_local_config(const ObResourcePoolConfig &config); int init_server_state_processor(const ObResourcePoolConfig &config); @@ -212,6 +258,7 @@ public: bool inc_and_test_deleting_complete(); int stop_refresh_server_state(); + int stop_detect_server_state(); bool is_default_cluster_resource() const { return (ObString::make_string(OB_PROXY_DEFAULT_CLUSTER_NAME) == get_cluster_name()); } bool is_metadb_cluster_resource() const { return (ObString::make_string(OB_META_DB_CLUSTER_NAME) == get_cluster_name()); } @@ -258,38 +305,17 @@ public: }; typedef common::hash::ObBuildInHashMap ObSysLdgInfoMap; - int update_location_tenant_info(common::ObSEArray& tenant_array, - common::ObSEArray& locality_array); + int update_location_tenant_info(common::ObSEArray &tenant_array, + common::ObSEArray &locality_array, + common::ObSEArray &primary_zone_array); uint64_t get_location_tenant_version(const ObString& tenant_name); + int get_location_tenant_info(const ObString &tenant_name, ObLocationTenantInfo *&info_out); void destroy_location_tenant_info(); private: int set_cluster_info(const common::ObString &cluster_name, const int64_t cluster_id); private: - struct ObLocationTenantInfo - { - public: - ObLocationTenantInfo() : tenant_name_(), version_(0) - { - memset(tenant_name_str_, 0, sizeof(tenant_name_str_)); - } - ~ObLocationTenantInfo() {} - virtual int64_t to_string(char *buf, const int64_t buf_len) const - { - int64_t pos = 0; - J_OBJ_START(); - J_KV(K_(tenant_name), K_(version)); - J_OBJ_END(); - return pos; - } - public: - ObString tenant_name_; - char tenant_name_str_[OB_MAX_TENANT_NAME_LENGTH]; - uint64_t version_; - LINK(ObLocationTenantInfo, cr_link_); - }; - struct ObLocationTenantInfoHashing { typedef const ObString &Key; @@ -310,6 +336,7 @@ public: proxy::ObSysVarSetProcessor sys_var_set_processor_; ObCongestionManager congestion_manager_; ObServerStateRefreshCont *ss_refresh_cont_; + ObDetectServerStateCont *detect_server_state_cont_; proxy::ObMysqlProxy mysql_proxy_; volatile uint64_t server_state_version_; @@ -330,6 +357,8 @@ public: int64_t last_idc_list_refresh_time_ns_; int64_t last_rslist_refresh_time_ns_; common::ObAtomicList pending_list_; + int64_t cluster_version_; + common::hash::ObHashSet alive_addr_set_; LINK(ObClusterResource, cr_link_); private: @@ -369,7 +398,8 @@ struct ObResourcePoolConfig TO_STRING_KV(K_(long_async_task_timeout), K_(short_async_task_timeout), K_(server_state_refresh_interval), K_(metadb_server_state_refresh_interval), K_(min_keep_congestion_interval_us), K_(congestion_retry_interval_us), - K_(congestion_fail_window_us), K_(congestion_failure_threshold)); + K_(congestion_fail_window_us), K_(congestion_failure_threshold), + K_(server_detect_refresh_interval)); int64_t long_async_task_timeout_; int64_t short_async_task_timeout_; @@ -379,6 +409,7 @@ struct ObResourcePoolConfig int64_t congestion_retry_interval_us_; int64_t congestion_fail_window_us_; int64_t congestion_failure_threshold_; + int64_t server_detect_refresh_interval_; }; class ObResourcePoolProcessor @@ -461,6 +492,7 @@ public: ObResourcePoolConfig config_; obsys::CRWLock cr_map_rwlock_; // used to protect cluster resource map ObCRHashMap cr_map_; + common::hash::ObHashSet ip_set_; private: DISALLOW_COPY_AND_ASSIGN(ObResourcePoolProcessor); diff --git a/src/obproxy/obutils/ob_server_state_processor.cpp b/src/obproxy/obutils/ob_server_state_processor.cpp index 03d5a296ab959e3b0b556a12ad729201c55d6435..346ade5fd61679ce21d3725963f845eab9261ecb 100644 --- a/src/obproxy/obutils/ob_server_state_processor.cpp +++ b/src/obproxy/obutils/ob_server_state_processor.cpp @@ -27,6 +27,7 @@ using namespace oceanbase::common; using namespace oceanbase::common::sqlclient; +using namespace oceanbase::common::hash; using namespace oceanbase::share; using namespace oceanbase::obproxy::net; using namespace oceanbase::obproxy::proxy; @@ -44,6 +45,11 @@ static const char *SELECT_ZONE_STATE_INFO_SQL = "SELECT /*+READ_CONSISTENCY(WEAK)*/ * " "FROM oceanbase.%s LIMIT %ld"; +static const char *SELECT_ZONE_STATE_INFO_SQL_V4 = + "SELECT /*+READ_CONSISTENCY(WEAK)*/ zone, status, " + "0 AS is_merging, region, idc AS spare4, type AS spare5 " + "FROM oceanbase.%s LIMIT %ld"; + //when server fail to start, its status is inactive, but its port == 0. //it is design defect, but proxy need compatible with it. //so select svr_port > 0 one @@ -52,6 +58,12 @@ const static char *SELECT_SERVER_STATE_INFO_SQL = "FROM oceanbase.%s " "WHERE svr_port > 0 ORDER BY zone LIMIT %ld"; +const static char *SELECT_SERVER_STATE_INFO_SQL_V4 = + "SELECT /*+READ_CONSISTENCY(WEAK)*/ svr_ip, sql_port AS svr_port, zone, status, " + "start_service_time is not null AS start_service_time, stop_time is not null as stop_time " + "FROM oceanbase.%s " + "WHERE svr_port > 0 ORDER BY zone LIMIT %ld"; + const static char *SELECT_CLUSTER_ROEL_SQL = "SELECT /*+READ_CONSISTENCY(WEAK)*/ cluster_role, cluster_status, primary_cluster_id " "FROM oceanbase.v$ob_cluster LIMIT 1"; @@ -60,11 +72,36 @@ const static char *SYS_LDG_INFO_SQL = "SELECT TENANT_ID, TENANT_NAME, CLUSTER_ID, CLUSTER_NAME, LDG_ROLE " "FROM oceanbase.ldg_standby_status"; const static char *SELECT_ALL_TENANT_SQL = - "SELECT /*+READ_CONSISTENCY(WEAK)*/ tenant_name, locality FROM oceanbase.__all_tenant " - "where previous_locality = '' and tenant_id != 1"; + "SELECT /*+READ_CONSISTENCY(WEAK)*/ tenant_name, locality, previous_locality, primary_zone " + "FROM oceanbase.%s where %s and tenant_id != 1"; + +class ObDetectOneServerStateCont : public obutils::ObAsyncCommonTask +{ +public: + ObDetectOneServerStateCont(); + virtual ~ObDetectOneServerStateCont() {} + virtual void destroy() { kill_this(); } + virtual int main_handler(int event, void *data); + void kill_this(); + int init(ObClusterResource *cluster_resource, ObAddr addr); + +private: + int detect_server_state_by_sql(); + int handle_client_resp(void *data); +private: + ObClusterResource *cluster_resource_; + ObAddr addr_; + ObMysqlClient *mysql_client_; + ObMysqlProxy mysql_proxy_; + +private: + DISALLOW_COPY_AND_ASSIGN(ObDetectOneServerStateCont); +}; //-------------------------------ObServerStateRefreshCont----------------------------------------// -int ObServerStateRefreshCont::init(ObClusterResource *cr, int64_t ss_refresh_interval_us) +int ObServerStateRefreshCont::init(ObClusterResource *cr, + int64_t ss_refresh_interval_us, + uint64_t last_rs_list_hash) { int ret = OB_SUCCESS; @@ -82,6 +119,7 @@ int ObServerStateRefreshCont::init(ObClusterResource *cr, int64_t ss_refresh_int ss_refresh_interval_us_ = ss_refresh_interval_us; cluster_name_.assign_ptr(cluster_resource_->get_cluster_name().ptr(), cluster_resource_->get_cluster_name().length()); cluster_id_ = cluster_resource_->get_cluster_id(); + last_server_list_hash_ = last_rs_list_hash; is_inited_ = true; } return ret; @@ -152,7 +190,8 @@ int ObServerStateRefreshCont::schedule_refresh_server_state(const bool imm /*fal int64_t delay_us = 0; bool need_refresh_cluster_role = get_global_proxy_config().with_config_server_ && get_global_proxy_config().enable_standby - && OB_DEFAULT_CLUSTER_ID == cluster_id_; + && OB_DEFAULT_CLUSTER_ID == cluster_id_ + && IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_resource_->cluster_version_); if (imm) { if (OB_ISNULL(pending_action_ = self_ethread().schedule_imm( this, need_refresh_cluster_role? REFRESH_CLUSTER_ROLE_EVENT : REFRESH_ZONE_STATE_EVENT))) { @@ -231,7 +270,7 @@ int ObServerStateRefreshCont::main_handler(int event, void *data) pending_action_ = NULL; cur_job_event_ = event; if (OB_FAIL(refresh_server_state())) { - LOG_WARN("fail to refresh zone state", K(ret)); + LOG_WARN("fail to refresh server state", K(ret)); } break; } @@ -304,6 +343,7 @@ int ObServerStateRefreshCont::main_handler(int event, void *data) } else if (ss_refresh_failure_ >= MAX_REFRESH_FAILURE) { bool need_refresh_cluster_role = get_global_proxy_config().with_config_server_ && get_global_proxy_config().enable_standby + && IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_resource_->cluster_version_) && OB_DEFAULT_CLUSTER_ID == cluster_id_ && has_slave_clusters; imm_reschedule = false; @@ -398,8 +438,15 @@ int ObServerStateRefreshCont::refresh_zone_state() int ret = OB_SUCCESS; char sql[OB_SHORT_SQL_LENGTH]; sql[0] = '\0'; - int64_t len = snprintf(sql, OB_SHORT_SQL_LENGTH, SELECT_ZONE_STATE_INFO_SQL, - OB_ALL_VIRTUAL_ZONE_STAT_TNAME, INT64_MAX); + int64_t len = 0; + if (IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_resource_->cluster_version_)) { + len = snprintf(sql, OB_SHORT_SQL_LENGTH, SELECT_ZONE_STATE_INFO_SQL, + OB_ALL_VIRTUAL_ZONE_STAT_TNAME, INT64_MAX); + } else { + len = snprintf(sql, OB_SHORT_SQL_LENGTH, SELECT_ZONE_STATE_INFO_SQL_V4, + DBA_OB_ZONES_VNAME, INT64_MAX); + } + if (OB_UNLIKELY(len <= 0 || len >= OB_SHORT_SQL_LENGTH)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to fill sql", K(len), K(sql), K(ret)); @@ -420,8 +467,14 @@ int ObServerStateRefreshCont::refresh_server_state() int ret = OB_SUCCESS; char sql[OB_SHORT_SQL_LENGTH]; sql[0] = '\0'; - const int64_t len = static_cast(snprintf(sql, OB_SHORT_SQL_LENGTH, SELECT_SERVER_STATE_INFO_SQL, - OB_ALL_VIRTUAL_PROXY_SERVER_STAT_TNAME, INT64_MAX)); + int64_t len =0; + if (IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_resource_->cluster_version_)) { + len = static_cast(snprintf(sql, OB_SHORT_SQL_LENGTH, SELECT_SERVER_STATE_INFO_SQL, + OB_ALL_VIRTUAL_PROXY_SERVER_STAT_TNAME, INT64_MAX)); + } else { + len = static_cast(snprintf(sql, OB_SHORT_SQL_LENGTH, SELECT_SERVER_STATE_INFO_SQL_V4, + DBA_OB_SERVERS_VNAME, INT64_MAX)); + } if (OB_UNLIKELY(len <= 0) || OB_UNLIKELY(len >= OB_SHORT_SQL_LENGTH)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to fill sql", K(len), K(sql), K(ret)); @@ -520,19 +573,42 @@ int ObServerStateRefreshCont::handle_all_tenant(void *data) result_handler.set_resp(resp); ObString tenant_name; ObString locality; + ObString previous_locality; + ObString primary_zone; ObSEArray tenant_array; ObSEArray locality_array; + ObSEArray primary_zone_array; while (OB_SUCC(ret) && OB_SUCC(result_handler.next())) { tenant_name.reset(); locality.reset(); + previous_locality.reset(); + primary_zone.reset(); PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(result_handler, "tenant_name", tenant_name); PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(result_handler, "locality", locality); + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(result_handler, "previous_locality", previous_locality); + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(result_handler, "primary_zone", primary_zone); + if (OB_FAIL(tenant_array.push_back(tenant_name))) { LOG_WARN("tenant array push back failed", K(ret)); - } else if (OB_FAIL(locality_array.push_back(locality))) { - LOG_WARN("locality array push back failed", K(ret)); + } else if (OB_FAIL(primary_zone_array.push_back(primary_zone))) { + LOG_WARN("primary zone array push back failed", K(ret)); + } else { + /* + * in oceanbase.__all_tenant, the column of previous_locality not empty + * means the locality is in changing state by the control of rootserver, otherwise the locality is stable. + */ + if (previous_locality.empty()) { + if (OB_FAIL(locality_array.push_back(locality))) { + LOG_WARN("fail to push locality to array", K(ret)); + } + } else { + if (OB_FAIL(locality_array.push_back(previous_locality))) { + LOG_WARN("fail to push previous locality to array", K(ret)); + } + } } } + if (ret != OB_ITER_END) { // handle case of fail to access __all_tenant on alipay main site: do not exec error handling process if (ER_TABLEACCESS_DENIED_ERROR == resp->get_err_code()) { @@ -542,13 +618,14 @@ int ObServerStateRefreshCont::handle_all_tenant(void *data) LOG_WARN("fail to get all tenant info", K(ret)); } } else { - if (OB_FAIL(cluster_resource_->update_location_tenant_info(tenant_array, locality_array))) { + if (OB_FAIL(cluster_resource_->update_location_tenant_info(tenant_array, locality_array, primary_zone_array))) { LOG_WARN("update location tenant info failed", K(ret)); } else { LOG_DEBUG("update location tenant info succ"); } ret = OB_SUCCESS; } + if (OB_SUCC(ret) && OB_FAIL(schedule_refresh_server_state())) { LOG_WARN("fail to schedule refresh server state", K(ret)); } @@ -710,7 +787,7 @@ int ObServerStateRefreshCont::handle_server_state(void *data) } } } - + if (OB_SUCC(ret)) { if (get_global_proxy_config().check_tenant_locality_change) { if (OB_FAIL(schedule_imm(REFRESH_ALL_TENANT_EVENT))) { @@ -752,7 +829,9 @@ int ObServerStateRefreshCont::refresh_all_tenant() int ret = OB_SUCCESS; char sql[OB_SHORT_SQL_LENGTH]; sql[0] = '\0'; - const int64_t len = static_cast(snprintf(sql, OB_SHORT_SQL_LENGTH, SELECT_ALL_TENANT_SQL)); + const int64_t len = static_cast(snprintf(sql, OB_SHORT_SQL_LENGTH, SELECT_ALL_TENANT_SQL, + IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_resource_->cluster_version_) ? OB_ALL_TENANT_TNAME : DBA_OB_TENANTS_VNAME, + IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_resource_->cluster_version_) ? "previous_locality = ''" : "previous_locality is null")); if (OB_UNLIKELY(len <= 0)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to fill sql", K(len), K(sql), K(ret)); @@ -810,9 +889,10 @@ int ObServerStateRefreshCont::update_last_zs_state( if (cluster_resource_->is_avail()) { const uint64_t new_ss_version = cluster_resource_->server_state_version_ + 1; - common::ObIArray &server_state_info = cluster_resource_->get_server_state_info(new_ss_version); common::DRWLock &server_state_lock = cluster_resource_->get_server_state_lock(new_ss_version); server_state_lock.wrlock(); + common::ObIArray &server_state_info = cluster_resource_->get_server_state_info(new_ss_version); + common::ObIArray &old_server_state_info = cluster_resource_->get_server_state_info(new_ss_version - 1); server_state_info.reuse(); ObServerStateSimpleInfo simple_server_info; for (int64_t i = 0; OB_SUCC(ret) && i < servers_state.count(); ++i) { @@ -833,20 +913,35 @@ int ObServerStateRefreshCont::update_last_zs_state( LOG_WARN("fail to set region name", "region_name", server_state.zone_state_->region_name_, K(ret)); } else if (OB_FAIL(simple_server_info.set_idc_name(server_state.zone_state_->idc_name_))) { LOG_WARN("fail to set idc name", "idc_name", server_state.zone_state_->idc_name_, K(ret)); - } else if (OB_FAIL(server_state_info.push_back(simple_server_info))) { - LOG_WARN("fail to push back server_info", K(simple_server_info), K(ret)); + } + if (OB_SUCC(ret)) { + for (int64_t i = 0; i < old_server_state_info.count(); i++) { + ObServerStateSimpleInfo &tmp_info = old_server_state_info.at(i); + if (simple_server_info.addr_ == tmp_info.addr_) { + simple_server_info.request_sql_cnt_ = tmp_info.request_sql_cnt_; + simple_server_info.last_response_time_ = tmp_info.last_response_time_; + simple_server_info.detect_fail_cnt_ = tmp_info.detect_fail_cnt_; + tmp_info.reset(); + break; + } + } + LOG_DEBUG("update server state info", K(simple_server_info), K(new_ss_version)); + if (OB_FAIL(server_state_info.push_back(simple_server_info))) { + LOG_WARN("fail to push back server_info", K(simple_server_info), K(ret)); + } } } } if (OB_SUCC(ret)) { + ATOMIC_AAF(&(cluster_resource_->server_state_version_), 1); LOG_INFO("succ to update servers_info_version", "cluster_info", cluster_name_, "cluster_id", cluster_id_, "server_state_version", cluster_resource_->server_state_version_, + K(cluster_resource_), K(server_state_info)); } server_state_lock.wrunlock(); - ATOMIC_AAF(&(cluster_resource_->server_state_version_), 1); } } } @@ -1096,7 +1191,7 @@ int ObServerStateRefreshCont::handle_newest_server( K(servers_state), K(cur_servers_state_hash), K_(cluster_name), K_(cluster_id)); } - if (is_servers_state_changed) { + if (is_servers_state_changed || 0 != get_global_resource_pool_processor().ip_set_.size()) { // check rslist to see if need to update rslist, ignore ret if (OB_FAIL(handle_rs_changed(servers_state))) { LOG_WARN("fail to handle rslist changed", K(ret)); @@ -1143,9 +1238,14 @@ int ObServerStateRefreshCont::do_update_server(const ObServerStateInfo &ss_info) } } + ObIpEndpoint ip(ss_info.replica_.server_.get_sockaddr()); + if (!need_update && ObCongestionEntry::ACTIVE == ss_info.cgt_server_state_) { + if (OB_HASH_EXIST == get_global_resource_pool_processor().ip_set_.exist_refactored(ip)) { + need_update = true; + } + } + if (need_update) { - ObIpEndpoint ip; - ops_ip_copy(ip.sa_, ss_info.replica_.server_.get_ipv4(), static_cast(ss_info.replica_.server_.get_port())); bool is_init = !congestion_manager_->is_base_servers_added(); int64_t cr_version = cluster_resource_->version_; if (OB_FAIL(congestion_manager_->update_server(ip, cr_version, cgt_server_state, zone_name, region_name, is_init))) { @@ -1405,8 +1505,7 @@ int ObServerStateRefreshCont::handle_deleted_server(ObIArray } if (!found) { LOG_INFO("deleted server", "ss_info", last_ss_info); - ops_ip_copy(ip.sa_, last_ss_info.replica_.server_.get_ipv4(), - static_cast(last_ss_info.replica_.server_.get_port())); + ip.assign(last_ss_info.replica_.server_.get_sockaddr()); int64_t cr_version = cluster_resource_->version_; if (OB_FAIL(congestion_manager_->update_server(ip, cr_version, ObCongestionEntry::DELETED, last_ss_info.zone_state_->zone_name_, @@ -1496,8 +1595,8 @@ int ObServerStateRefreshUtils::get_zone_state_info(ObMysqlResultHandler &result_ idc_name.reset(); zone_type.reset(); PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(result_handler, "zone", zone_name); - PROXY_EXTRACT_INT_FIELD_MYSQL(result_handler, "is_merging", zone_state.is_merging_, int64_t); PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(result_handler, "status", zone_status); + PROXY_EXTRACT_INT_FIELD_MYSQL(result_handler, "is_merging", zone_state.is_merging_, int64_t); if (OB_SUCC(ret)) { PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(result_handler, "region", region_name); @@ -1567,7 +1666,7 @@ int ObServerStateRefreshUtils::get_server_state_info( { int ret = OB_SUCCESS; - char ip_str[OB_IP_STR_BUFF]; + char ip_str[MAX_IP_ADDR_LENGTH]; int64_t port = 0; ObServerStateInfo server_state; const int64_t MAX_DISPLAY_STATUS_LEN = 64; @@ -1583,7 +1682,7 @@ int ObServerStateRefreshUtils::get_server_state_info( display_status_str[0] = '\0'; zone_name[0] = '\0'; PROXY_EXTRACT_STRBUF_FIELD_MYSQL(result_handler, "svr_ip", ip_str, - OB_IP_STR_BUFF, tmp_real_str_len); + MAX_IP_ADDR_LENGTH, tmp_real_str_len); PROXY_EXTRACT_INT_FIELD_MYSQL(result_handler, "svr_port", port, int64_t); PROXY_EXTRACT_STRBUF_FIELD_MYSQL(result_handler, "zone", zone_name, MAX_ZONE_LENGTH + 1, zone_name_len); @@ -1767,6 +1866,418 @@ int ObServerStateRefreshUtils::order_servers_state(const ObIArrayinc_ref(); + cluster_resource_ = cr; + server_detect_state_interval_us_ = server_detect_refresh_interval_us; + is_inited_ = true; + } + return ret; +} + +void ObDetectServerStateCont::kill_this() +{ + if (is_inited_) { + LOG_INFO("ObDetectServerStateCont will kill self", KPC(this)); + int ret = OB_SUCCESS; + // cancel pending action at first + // ignore ret + if (OB_FAIL(cancel_pending_action())) { + LOG_WARN("fail to cancel pending action", K(ret)); + } + + if (OB_LIKELY(NULL != cluster_resource_)) { + cluster_resource_->dec_ref(); + cluster_resource_ = NULL; + } + + server_detect_state_interval_us_ = 0; + kill_this_ = false; + is_inited_ = false; + } + mutex_.release(); + op_free(this); +} + +DEF_TO_STRING(ObDetectServerStateCont) +{ + int64_t pos = 0; + J_OBJ_START(); + J_KV(K_(is_inited), K_(kill_this), K_(server_detect_state_interval_us), KP_(pending_action), KPC_(cluster_resource)); + J_OBJ_END(); + return pos; +} + +int ObDetectServerStateCont::schedule_detect_server_state() +{ + int ret = OB_SUCCESS; + const int64_t server_detect_mode = get_global_proxy_config().server_detect_mode; + if (OB_UNLIKELY(!is_inited_)) { + ret = OB_NOT_INIT; + LOG_WARN("not init", K_(is_inited), K(ret)); + } else if (get_global_hot_upgrade_info().is_graceful_exit_timeout(get_hrtime())) { + ret = OB_SERVER_IS_STOPPING; + LOG_WARN("proxy need exit now", K(ret)); + } else if (OB_UNLIKELY(!self_ethread().is_event_thread_type(ET_CALL))) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("server state refresh cont must be scheduled in work thread", K(ret)); + } else if (server_detect_mode > 0) { + int64_t ss_version = cluster_resource_->server_state_version_; + common::DRWLock &server_state_lock = cluster_resource_->get_server_state_lock(ss_version); + server_state_lock.rdlock(); + common::ObIArray &server_state_info = + cluster_resource_->get_server_state_info(ss_version); + ObHashSet addr_set; + addr_set.create(4); + + for (int i = 0; i < server_state_info.count(); i++) { + ObServerStateSimpleInfo &info = server_state_info.at(i); + bool check_pass = true; + // Accurate detection method + if (1 == server_detect_mode) { + check_pass = (info.request_sql_cnt_ > 0); + LOG_DEBUG("check detect one server", K(server_detect_mode), K_(info.request_sql_cnt), K(check_pass)); + } + + if (check_pass || info.detect_fail_cnt_ > 0) { + // There is no need to judge whether the push_back is successful here + ObDetectOneServerStateCont *cont = NULL; + if (OB_ISNULL(cont = op_alloc(ObDetectOneServerStateCont))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc ObDetectOneServerStateCont", K(ret)); + } else if (OB_FAIL(cont->init(cluster_resource_, info.addr_))) { + LOG_WARN("fail to init detect server state cont", K(ret)); + } else if (OB_ISNULL(self_ethread().schedule_imm(cont, DETECT_SERVER_STATE_EVENT))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("schedule detect one server state failed", K(ret)); + } + LOG_DEBUG("schedule detect one server state", K(info), K(ss_version)); + } else { + ObIpEndpoint point(info.addr_.get_sockaddr()); + if (OB_HASH_EXIST == get_global_resource_pool_processor().ip_set_.exist_refactored(point)) { + addr_set.set_refactored(info.addr_); + } else if (OB_HASH_EXIST == cluster_resource_->alive_addr_set_.exist_refactored(point)) { + addr_set.set_refactored(info.addr_); + } + } + } + + ObHashSet::iterator it = addr_set.begin(); + while (it != addr_set.end()) { + ObAddr &addr = it->first; + ObDetectOneServerStateCont *cont = NULL; + if (OB_ISNULL(cont = op_alloc(ObDetectOneServerStateCont))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc ObDetectOneServerStateCont", K(ret)); + } else if (OB_FAIL(cont->init(cluster_resource_, addr))) { + LOG_WARN("fail to init detect server cont", K(ret)); + } else if (OB_ISNULL(self_ethread().schedule_imm(cont, DETECT_SERVER_STATE_EVENT))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("schedule detect one server state failed", K(ret)); + } + it++; + LOG_DEBUG("schedule detect one server state", K(addr), K(ss_version)); + } + server_state_lock.rdunlock(); + } + + if (OB_UNLIKELY(server_detect_state_interval_us_ <= 0)) { + ret = OB_INNER_STAT_ERROR; + LOG_WARN("delay must greater than zero", K_(server_detect_state_interval_us), K(ret)); + } else if (OB_ISNULL(pending_action_ = self_ethread().schedule_in(this, + HRTIME_USECONDS(server_detect_state_interval_us_), DETECT_SERVER_STATE_EVENT))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to schedule refresh server state", K_(server_detect_state_interval_us), + K(server_detect_mode), KPC_(cluster_resource), K(ret)); + } + + LOG_DEBUG("schedule detect server state", K_(server_detect_state_interval_us), + K(server_detect_mode), KPC_(cluster_resource), K(ret)); + + return ret; +} + +int ObDetectServerStateCont::main_handler(int event, void *data) +{ + UNUSED(data); + int event_ret = EVENT_CONT; + int ret = OB_SUCCESS; + LOG_DEBUG("[ObDetectServerStateCont::main_handler] ", K(event), K(kill_this_)); + + switch (event) { + case DESTROY_SERVER_STATE_EVENT: { + if (0 == ATOMIC_CAS(&set_interval_task_count_, 0, 0)) { + LOG_INFO("ObDetectServerStateCont will terminate", KPC_(cluster_resource)); + kill_this_ = true; + } else { + LOG_INFO("there are still set_interval tasks which have been scheduled," + " we should reschedule destroy event", KPC(this)); + if (OB_ISNULL(self_ethread().schedule_imm(this, DESTROY_SERVER_STATE_EVENT))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to schedule DESTROY_SERVER_STATE_EVENT", KPC(this), K(ret)); + } + } + break; + } + case EVENT_IMMEDIATE: { + ATOMIC_DEC(&set_interval_task_count_); + if (OB_FAIL(cancel_pending_action())) { + LOG_WARN("cancel pending action failed", K(ret)); + } else if (OB_FAIL(schedule_detect_server_state())) { + LOG_WARN("fail to schedule detect server state", K(ret)); + } + break; + } + case DETECT_SERVER_STATE_EVENT: { + pending_action_ = NULL; + if (OB_FAIL(schedule_detect_server_state())) { + LOG_WARN("fail to schedule detect server state", K(ret)); + } + break; + } + default: { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unknown event", K(event), K(ret)); + break; + } + } + + if (kill_this_) { + event_ret = EVENT_DONE; + kill_this(); + } + + return event_ret; +} + +int ObDetectServerStateCont::cancel_pending_action() +{ + int ret = OB_SUCCESS; + if (NULL != pending_action_) { + if (OB_FAIL(pending_action_->cancel())) { + LOG_WARN("fail to cancel pending action", K_(pending_action), K(ret)); + } else { + pending_action_ = NULL; + } + } + + return ret; +} + +int ObDetectServerStateCont::set_detect_server_state_interval(const int64_t refresh_interval) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(refresh_interval <= 0)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid detect server state interval", K(refresh_interval), K(ret)); + } else { + server_detect_state_interval_us_ = refresh_interval; + ATOMIC_INC(&set_interval_task_count_); + if (OB_ISNULL(g_event_processor.schedule_imm(this, ET_CALL))) { + ATOMIC_DEC(&set_interval_task_count_); + ret = OB_ERR_UNEXPECTED; + LOG_WARN("schedule imm detect_server_state task error", K(ret)); + } + + } + LOG_DEBUG("set detect server state interval", K_(server_detect_state_interval_us), K(refresh_interval)); + + return ret; +} + +ObDetectOneServerStateCont::ObDetectOneServerStateCont() + : ObAsyncCommonTask(NULL, "detect_server_state_task"), + cluster_resource_(NULL), addr_(), mysql_client_(NULL), + mysql_proxy_() +{ + SET_HANDLER(&ObDetectOneServerStateCont::main_handler); +} + +int ObDetectOneServerStateCont::init(ObClusterResource *cluster_resource, ObAddr addr) +{ + int ret = OB_SUCCESS; + const int64_t timeout_ms = usec_to_msec(get_global_proxy_config().detect_server_timeout); + if (OB_UNLIKELY(NULL == cluster_resource || !addr.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("init obdetectserverstate cont failed", K(cluster_resource), K(ret)); + // The detection only depends on whether OBServer returns OB_MYSQL_COM_HANDSHAKE, + // and will not log in. The following parameters will not be actually used, + // only for the initialization of class objects + // user_name : detect_username + // password : detect_password + // database : detect_database + } else if (OB_FAIL(mysql_proxy_.init(timeout_ms, ObProxyTableInfo::DETECT_USERNAME_USER, "detect_password", "detect_database"))) { + LOG_WARN("fail to init mysql proxy", K(ret)); + } else { + cluster_resource->inc_ref(); + cluster_resource_ = cluster_resource; + addr_ = addr; + if (OB_ISNULL(mysql_client_ = op_alloc(ObMysqlClient))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to allocate ObMysqlClient", K(ret)); + } else if (OB_FAIL(mysql_client_->init_detect_client(cluster_resource_))) { + LOG_WARN("fail to init detect client", K(ret)); + } + + if (OB_FAIL(ret) && (NULL != mysql_client_)) { + mysql_client_->kill_this(); + mysql_client_ = NULL; + } + } + + return ret; +} + +void ObDetectOneServerStateCont::kill_this() +{ + int ret = OB_SUCCESS; + + if (OB_LIKELY(NULL != cluster_resource_)) { + cluster_resource_->dec_ref(); + cluster_resource_ = NULL; + } + if (OB_LIKELY(NULL != mysql_client_)) { + mysql_client_->kill_this(); + mysql_client_ = NULL; + } + if (OB_FAIL(cancel_timeout_action())) { + LOG_WARN("fail to cancel timeout action", K(ret)); + } + + if (OB_FAIL(cancel_pending_action())) { + LOG_WARN("fail to cancel pending action", K(ret)); + } + + action_.set_continuation(NULL); + op_free(this); +} + +int ObDetectOneServerStateCont::main_handler(int event, void *data) +{ + int he_ret = EVENT_CONT; + int ret = OB_SUCCESS; + + switch (event) { + case EVENT_IMMEDIATE: + case DETECT_SERVER_STATE_EVENT: { + if (OB_FAIL(detect_server_state_by_sql())) { + LOG_WARN("detect server by sql failed", K(ret)); + } + break; + } + case CLIENT_TRANSPORT_MYSQL_RESP_EVENT: { + if (OB_FAIL(handle_client_resp(data))) { + LOG_WARN("fail to handle client resp", K(ret)); + } + break; + } + default: { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unknown event", K(event), K(data), K(ret)); + break; + } + } + + if (OB_FAIL(ret) || terminate_) { + terminate_ = true; + kill_this(); + he_ret = EVENT_DONE; + } + + return he_ret; +} + +int ObDetectOneServerStateCont::detect_server_state_by_sql() +{ + int ret = OB_SUCCESS; + char sql[] = "select 'detect server' from dual"; + LOG_DEBUG("begin to detect server", K_(addr)); + ObMysqlRequestParam request_param(sql); + request_param.set_target_addr(addr_); + request_param.set_mysql_client(mysql_client_); + request_param.set_is_detect_client(true); + const int64_t timeout_ms = usec_to_msec(get_global_proxy_config().detect_server_timeout); + if (OB_FAIL(mysql_proxy_.async_read(this, request_param, pending_action_, timeout_ms))) { + LOG_WARN("fail to async read", K(ret)); + } + + return ret; +} + +int ObDetectOneServerStateCont::handle_client_resp(void *data) +{ + int ret = OB_SUCCESS; + common::DRWLock &server_state_lock1 = cluster_resource_->get_server_state_lock(0); + common::DRWLock &server_state_lock2 = cluster_resource_->get_server_state_lock(1); + server_state_lock1.rdlock(); + server_state_lock2.rdlock(); + common::ObIArray &server_state_info = + cluster_resource_->get_server_state_info(cluster_resource_->server_state_version_); + bool found = false; + for (int i = 0; !found && i < server_state_info.count(); i++) { + ObServerStateSimpleInfo &info = server_state_info.at(i); + ObIpEndpoint ip(info.addr_.get_sockaddr()); + ObCongestionEntry::ObServerState state = ObCongestionEntry::ObServerState::ACTIVE; + if (addr_ == info.addr_) { + if (NULL != data) { + (void)ATOMIC_SET(&info.detect_fail_cnt_, 0); + state = ObCongestionEntry::ObServerState::DETECT_ALIVE; + cluster_resource_->alive_addr_set_.erase_refactored(ip); + get_global_resource_pool_processor().ip_set_.erase_refactored(ip); + LOG_DEBUG("detect server alive", K(info)); + } else { + int64_t fail_cnt = ATOMIC_AAF(&info.detect_fail_cnt_, 1); + LOG_WARN("detect server dead", K(info)); + if (fail_cnt >= get_global_proxy_config().server_detect_fail_threshold) { + // If the detection failure exceeds the number of retries, the server needs to be added to the blacklist + (void)ATOMIC_SET(&info.detect_fail_cnt_, 0); + state = ObCongestionEntry::ObServerState::DETECT_DEAD; + get_global_resource_pool_processor().ip_set_.set_refactored(ip); + } + } + + if (ObCongestionEntry::ObServerState::DETECT_DEAD == state + || ObCongestionEntry::ObServerState::DETECT_ALIVE == state) { + ObCongestionManager &congestion_manager = cluster_resource_->congestion_manager_; + bool is_init = !congestion_manager.is_base_servers_added(); + int64_t cr_version = cluster_resource_->version_; + if (OB_FAIL(congestion_manager.update_server(ip, cr_version, state, + info.zone_name_, info.region_name_, is_init))) { + LOG_WARN("fail to update update server", K(cr_version), K(ip), K(is_init), K(ret)); + } + } + found = true; + } + } + + if (!found) { + ObIpEndpoint ip(addr_.get_sockaddr()); + get_global_resource_pool_processor().ip_set_.erase_refactored(ip); + cluster_resource_->alive_addr_set_.erase_refactored(ip); + LOG_WARN("server not in cluster", K(ip), KPC_(cluster_resource)); + } + server_state_lock2.rdunlock(); + server_state_lock1.rdunlock(); + if (NULL != data) { + ObClientMysqlResp *resp = reinterpret_cast(data); + op_free(resp); + data = NULL; + } + terminate_ = true; + + return ret; +} + } // end of namespace obutils } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/obutils/ob_server_state_processor.h b/src/obproxy/obutils/ob_server_state_processor.h index 637b5afa4485963b67433a84d1fd4ced5941a684..0bd723e9a99c2b34fc6e48a36a4fc3155beec575 100644 --- a/src/obproxy/obutils/ob_server_state_processor.h +++ b/src/obproxy/obutils/ob_server_state_processor.h @@ -24,6 +24,7 @@ #define REFRESH_CLUSTER_ROLE_EVENT (SERVER_STATE_EVENT_EVENTS_START + 4) #define REFRESH_LDG_INFO_EVENT (SERVER_STATE_EVENT_EVENTS_START + 5) #define REFRESH_ALL_TENANT_EVENT (SERVER_STATE_EVENT_EVENTS_START + 6) +#define DETECT_SERVER_STATE_EVENT (SERVER_STATE_EVENT_EVENTS_START + 7) namespace oceanbase { @@ -38,21 +39,24 @@ namespace obutils { class ObClusterResource; class ObCongestionManager; + class ObServerStateRefreshCont : public event::ObContinuation { public: ObServerStateRefreshCont() : ObContinuation(NULL), is_inited_(false), kill_this_(false), need_reset_in_error_(false), - cur_job_event_(0), cluster_resource_(NULL), - mysql_proxy_(NULL), congestion_manager_(NULL), pending_action_(NULL), - ss_refresh_interval_us_(0), ss_refresh_failure_(0), set_interval_task_count_(0), cluster_id_(OB_INVALID_CLUSTER_ID), + cur_job_event_(0), cluster_resource_(NULL), mysql_proxy_(NULL), congestion_manager_(NULL), pending_action_(NULL), + ss_refresh_interval_us_(0), ss_refresh_failure_(0), + set_interval_task_count_(0), cluster_id_(OB_INVALID_CLUSTER_ID), cluster_name_(), last_zones_state_hash_(0), last_servers_state_hash_(0), last_server_list_hash_(0) { SET_HANDLER(&ObServerStateRefreshCont::main_handler); } virtual ~ObServerStateRefreshCont() {} - int init(ObClusterResource *cr, int64_t ss_refresh_interval_us); + int init(ObClusterResource *cr, + int64_t ss_refresh_interval_us, + uint64_t last_rs_list_hash); int schedule_refresh_server_state(const bool imm = false); int set_server_state_refresh_interval(const int64_t interval); @@ -155,6 +159,40 @@ public: static int order_servers_state(const common::ObIArray &servers_state, LocationList &server_list); }; +class ObDetectServerStateCont : public event::ObContinuation +{ +public: + ObDetectServerStateCont() : is_inited_(false), kill_this_(false), cluster_resource_(NULL), + server_detect_state_interval_us_(0), pending_action_(NULL), set_interval_task_count_(0) + { + SET_HANDLER(&ObDetectServerStateCont::main_handler); + } + virtual ~ObDetectServerStateCont() {} + virtual void destroy() { kill_this(); } + virtual int main_handler(int event, void *data); + void kill_this(); + int init(ObClusterResource *cluster_resource, int64_t server_detect_refresh_interval_us); + + int schedule_detect_server_state(); + int set_detect_server_state_interval(const int64_t refresth_interval); + + DECLARE_TO_STRING; + +private: + int cancel_pending_action(); + +private: + bool is_inited_; + bool kill_this_; + ObClusterResource *cluster_resource_; + int64_t server_detect_state_interval_us_; + event::ObAction *pending_action_; + volatile int64_t set_interval_task_count_; + +private: + DISALLOW_COPY_AND_ASSIGN(ObDetectServerStateCont); +}; + } // end of namespace obutils } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/obutils/ob_state_info.h b/src/obproxy/obutils/ob_state_info.h index 88b7e76a2d68a094c714d0abd820f2a47f0e2bee..f039bd8dcb0278689b7c69cea612544ceb8888b3 100644 --- a/src/obproxy/obutils/ob_state_info.h +++ b/src/obproxy/obutils/ob_state_info.h @@ -107,6 +107,11 @@ public: common::ObZoneType zone_type_; bool is_merging_; bool is_force_congested_; + // The number of SQLs currently being executed by the server + int64_t request_sql_cnt_; + // The last time the request was sent + int64_t last_response_time_; + int64_t detect_fail_cnt_; private: char zone_name_buf_[common::MAX_ZONE_LENGTH]; char region_name_buf_[common::MAX_REGION_LENGTH]; @@ -281,10 +286,13 @@ inline int ObServerStateInfo::add_addr(const char *ip, const int64_t port) inline ObServerStateSimpleInfo &ObServerStateSimpleInfo::operator=(const ObServerStateSimpleInfo &other) { if (this != &other) { - addr_.set_ipv4_addr(other.addr_.get_ipv4(), other.addr_.get_port()); + addr_ = other.addr_; is_merging_ = other.is_merging_; is_force_congested_ = other.is_force_congested_; zone_type_ = other.zone_type_; + request_sql_cnt_ = other.request_sql_cnt_; + last_response_time_ = other.last_response_time_; + detect_fail_cnt_ = other.detect_fail_cnt_; if (other.zone_name_.empty()) { zone_name_.reset(); } else { @@ -321,8 +329,8 @@ inline int ObServerStateSimpleInfo::set_addr(const common::ObAddr &addr) if (OB_UNLIKELY(!addr.is_valid())) { ret = common::OB_INVALID_ARGUMENT; PROXY_LOG(WARN, "invalid argument", K(addr), K(ret)); - } else if (OB_UNLIKELY(!addr_.set_ipv4_addr(addr.get_ipv4(), addr.get_port()))) { - ret = common::OB_INVALID_ARGUMENT; + } else { + addr_ = addr; } return ret; } @@ -330,7 +338,7 @@ inline int ObServerStateSimpleInfo::set_addr(const common::ObAddr &addr) inline int ObServerStateSimpleInfo::set_addr(const char *ip, const int64_t port) { int ret = common::OB_SUCCESS; - if (OB_UNLIKELY(!addr_.set_ipv4_addr(ip, static_cast(port)))) { + if (OB_UNLIKELY(!addr_.set_ip_addr(ip, static_cast(port)))) { ret = common::OB_INVALID_ARGUMENT; } return ret; @@ -385,7 +393,10 @@ inline int64_t ObServerStateSimpleInfo::to_string(char *buf, const int64_t buf_l K_(idc_name), "zone_type", common::zone_type_to_str(zone_type_), K_(is_merging), - K_(is_force_congested)); + K_(is_force_congested), + K_(request_sql_cnt), + K_(last_response_time), + K_(detect_fail_cnt)); J_OBJ_END(); return pos; } diff --git a/src/obproxy/obutils/ob_vip_tenant_cache.cpp b/src/obproxy/obutils/ob_vip_tenant_cache.cpp index 0d3a41d505209c3e2db3d5201778def65a65ece8..51b27f90b220b578a8db7b20dd3eb8af22234e12 100644 --- a/src/obproxy/obutils/ob_vip_tenant_cache.cpp +++ b/src/obproxy/obutils/ob_vip_tenant_cache.cpp @@ -23,7 +23,19 @@ namespace obproxy namespace obutils { -void ObVipAddr::set(const int32_t ip, const int32_t port, const int64_t vid) +void ObVipAddr::set(const char* ip, const int32_t port, const int64_t vid) +{ + if (NULL == ip || 0 == strcasecmp(ip, "") || port <= 0) { + addr_.reset(); + } else if (OB_UNLIKELY(!addr_.set_ip_addr(ip, port))) { + LOG_WARN("fail to set_ip_addr", K(ip), K(port), K(addr_)); + addr_.reset(); + } else { + vid_ = vid; + } +} + +void ObVipAddr::set_ipv4(int32_t ip, const int32_t port, const int64_t vid) { if (OB_UNLIKELY(!addr_.set_ipv4_addr(ip, port))) { LOG_WARN("fail to set_ipv4_addr", K(ip), K(port), K(addr_)); @@ -33,6 +45,12 @@ void ObVipAddr::set(const int32_t ip, const int32_t port, const int64_t vid) } } +void ObVipAddr::set(const struct sockaddr &addr, const int64_t vid) +{ + addr_.set_sockaddr(addr); + vid_ = vid; +} + int ObVipTenant::set_tenant_cluster(const ObString &tenant_name, const ObString &cluster_name) { int ret = OB_SUCCESS; diff --git a/src/obproxy/obutils/ob_vip_tenant_cache.h b/src/obproxy/obutils/ob_vip_tenant_cache.h index 487c6b0a54e35d2edd27bc52914ccada2a14328d..95c2aefacd733d829115400d165cd39e727bfd3a 100644 --- a/src/obproxy/obutils/ob_vip_tenant_cache.h +++ b/src/obproxy/obutils/ob_vip_tenant_cache.h @@ -24,6 +24,19 @@ namespace obproxy namespace obutils { +enum ObVipTenantRequestType +{ + InvalidRequestType = -1, + RequestLeader, + RequestFollower, +}; +enum ObVipTenantRWType +{ + InvalidRWType = -1, + ReadOnly, + ReadWrite, +}; + struct ObVipAddr { public: @@ -33,7 +46,9 @@ public: bool is_valid() const { return (addr_.is_valid() && vid_ >= 0); } void reset() { vid_ = -1; addr_.reset(); } bool operator==(const ObVipAddr &vip_addr) const { return (vip_addr.vid_ == vid_ && vip_addr.addr_ == addr_); } - void set(const int32_t ip, const int32_t port, const int64_t vid); + void set(const char* ip, const int32_t port, const int64_t vid); + void set_ipv4(int32_t ip, const int32_t port, const int64_t vid); + void set(const struct sockaddr &addr, const int64_t vid); TO_STRING_KV(K_(addr), K_(vid)); public: @@ -43,20 +58,6 @@ public: struct ObVipTenant { -private: - enum ObVipTenantRequestType - { - InvalidRequestType = -1, - RequestLeader, - RequestFollower, - }; - enum ObVipTenantRWType - { - InvalidRWType = -1, - ReadOnly, - ReadWrite, - }; - public: ObVipTenant() : vip_addr_(), tenant_name_(), cluster_name_(), request_target_type_(InvalidRequestType), rw_type_(InvalidRWType) diff --git a/src/obproxy/omt/Makemodule.am b/src/obproxy/omt/Makemodule.am index 0f7b2cef6ffb7cfbc2642c028ceadb68bd83357e..bcd42f3c25c04bba4f35949d9fe90072c824bc1f 100644 --- a/src/obproxy/omt/Makemodule.am +++ b/src/obproxy/omt/Makemodule.am @@ -6,4 +6,14 @@ obproxy/omt/ob_resource_unit_table_processor.cpp\ obproxy/omt/ob_vip_tenant_conn.h\ obproxy/omt/ob_vip_tenant_conn.cpp\ obproxy/omt/ob_ssl_config_table_processor.h\ -obproxy/omt/ob_ssl_config_table_processor.cpp +obproxy/omt/ob_ssl_config_table_processor.cpp\ +obproxy/omt/ob_conn_table_processor.h\ +obproxy/omt/ob_conn_table_processor.cpp\ +obproxy/omt/ob_cpu_table_processor.h\ +obproxy/omt/ob_cpu_table_processor.cpp\ +obproxy/omt/ob_vip_tenant_cpu.h\ +obproxy/omt/ob_vip_tenant_cpu.cpp\ +obproxy/omt/ob_cgroup_ctrl.h\ +obproxy/omt/ob_cgroup_ctrl.cpp\ +obproxy/omt/ob_proxy_config_table_processor.h\ +obproxy/omt/ob_proxy_config_table_processor.cpp \ No newline at end of file diff --git a/src/obproxy/omt/ob_cgroup_ctrl.cpp b/src/obproxy/omt/ob_cgroup_ctrl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c154859e10c4bbc34b9afa5599ab8d986fecc0c5 --- /dev/null +++ b/src/obproxy/omt/ob_cgroup_ctrl.cpp @@ -0,0 +1,283 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * + * ************************************************************* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define USING_LOG_PREFIX PROXY + +#include "ob_cgroup_ctrl.h" +#include "lib/file/file_directory_utils.h" +#include "lib/utility/ob_macro_utils.h" +#include "lib/utility/utility.h" +#include "lib/oblog/ob_log.h" + +#include +#include + +using namespace oceanbase::common; + +namespace oceanbase +{ +namespace obproxy +{ +namespace omt +{ + +// Create cgroup initial directory structure +int ObCgroupCtrl::init() +{ + int ret = OB_SUCCESS; + // cgroup + // ├── tenant_cluster_vip1 + // | ├── cpu.cfs_period_us + // | ├── cpu.cfs_quota_us + // | └── cpu.tasks + // └── tenant_cluster_vip2 + // ├── cpu.cfs_period_us + // ├── cpu.cfs_quota_us + // └── cpu.tasks + // 1. Initialize the obproxy root cgroup + if (OB_FAIL(init_cgroup_root_dir(root_cgroup_))) { + LOG_WARN("init cgroup dir failed", K(ret), K(root_cgroup_)); + // 2. Create a user cgroup for the user tenant + } else if (init_cgroup_dir(user_cgroup_)) { + LOG_WARN("init tenants cgroup dir failed", K(ret), K(user_cgroup_)); + } else if (init_cgroup_dir(other_cgroup_)) { + LOG_WARN("init other cgroup dir failed", K(ret), K(other_cgroup_)); + } else { + valid_ = true; + LOG_DEBUG("init cgroup dir succ"); + } + + return ret; +} + +int ObCgroupCtrl::create_tenant_cgroup(const ObString& tenant_id) +{ + int ret = OB_SUCCESS; + char tenant_cg_dir[PATH_BUFSIZE]; + bool exist_cgroup = false; + const char *top_cgroup = user_cgroup_; + snprintf(tenant_cg_dir, PATH_BUFSIZE, "%s/%.*s", top_cgroup, tenant_id.length(), tenant_id.ptr()); + if (OB_FAIL(FileDirectoryUtils::is_exists(tenant_cg_dir, exist_cgroup))) { + LOG_WARN("fail check file exist", K(tenant_cg_dir), K(ret)); + } else if (!exist_cgroup && OB_FAIL(init_cgroup_dir(tenant_cg_dir))) { + // note: Support concurrent creation of the same directory, all return OB_SUCCESS + LOG_WARN("init tenant cgroup dir failed", K(ret), K(tenant_cg_dir), K(tenant_id)); + } + return ret; +} + +int ObCgroupCtrl::remove_tenant_cgroup(const ObString& tenant_id) +{ + int ret = OB_SUCCESS; + char tenant_path[PATH_BUFSIZE]; + char tenant_task_path[PATH_BUFSIZE]; + char other_task_path[PATH_BUFSIZE]; + const char *top_cgroup = user_cgroup_; + snprintf(tenant_path, PATH_BUFSIZE, "%s/%.*s", top_cgroup, tenant_id.length(), tenant_id.ptr()); + snprintf(tenant_task_path, PATH_BUFSIZE, "%s/%.*s/tasks", top_cgroup, tenant_id.length(), tenant_id.ptr()); + snprintf(other_task_path, PATH_BUFSIZE, "%s/tasks", other_cgroup_); + FILE* tenant_task_file = NULL; + if (OB_ISNULL(tenant_task_file = fopen(tenant_task_path, "r"))) { + ret = OB_IO_ERROR; + LOG_WARN("open tenant task path failed", K(ret), K(tenant_task_path), K(errno), KERRMSG); + } else { + char tid_buf[VALUE_BUFSIZE]; + while (fgets(tid_buf, VALUE_BUFSIZE, tenant_task_file)) { + if (OB_FAIL(write_string_to_file(other_task_path, tid_buf))) { + LOG_WARN("remove tenant task failed", K(ret), K(other_task_path), K(tenant_id)); + break; + } + } + fclose(tenant_task_file); + } + if (OB_SUCC(ret) && OB_FAIL(FileDirectoryUtils::delete_directory(tenant_path))) { + LOG_WARN("remove tenant cgroup directory failed", K(ret), K(tenant_path), K(tenant_id)); + } else { + LOG_INFO("remove tenant cgroup directory success", K(tenant_path), K(tenant_id)); + } + return ret; +} + +int ObCgroupCtrl::add_thread_to_cgroup(const ObString tenant_id, const int64_t tid) +{ + int ret = OB_SUCCESS; + char task_path[PATH_BUFSIZE]; + char tid_value[VALUE_BUFSIZE]; + snprintf(task_path, PATH_BUFSIZE, "%s/%.*s/tasks", user_cgroup_, tenant_id.length(), tenant_id.ptr()); + snprintf(tid_value, VALUE_BUFSIZE, "%d", (uint32_t)tid); + if(OB_FAIL(write_string_to_file(task_path, tid_value))) { + LOG_WARN("add tid to cgroup failed", K(ret), K(task_path), K(tid_value), K(tenant_id)); + } else { + LOG_DEBUG("add tid to cgroup succ", K(task_path), K(tid_value), K(tenant_id)); + } + + return ret; +} + +int ObCgroupCtrl::set_cpu_cfs_quota(const ObString tenant_id, const int32_t cfs_quota_us) +{ + int ret = OB_SUCCESS; + char cfs_path[PATH_BUFSIZE]; + char cfs_value[VALUE_BUFSIZE]; + const char *top_cgroup = user_cgroup_; + snprintf(cfs_path, PATH_BUFSIZE, "%s/%.*s/cpu.cfs_quota_us", top_cgroup, tenant_id.length(), tenant_id.ptr()); + snprintf(cfs_value, VALUE_BUFSIZE, "%d", cfs_quota_us); + if(OB_FAIL(write_string_to_file(cfs_path, cfs_value))) { + LOG_WARN("set cpu cfs quota failed", K(ret), K(cfs_path), K(cfs_value), K(tenant_id)); + } else { + LOG_INFO("set cpu cfs quota success", K(cfs_path), K(cfs_value), K(tenant_id)); + } + return ret; +} + +// TODO: This value can be unchanged, and the same value is shared globally, +// so there is no need to read from the file system every time. +int ObCgroupCtrl::get_cpu_cfs_period(const ObString tenant_id, int32_t &cfs_period_us) +{ + int ret = OB_SUCCESS; + char cfs_path[PATH_BUFSIZE]; + char cfs_value[VALUE_BUFSIZE]; + const char *top_cgroup = user_cgroup_; + snprintf(cfs_path, PATH_BUFSIZE, "%s/%.*s/cpu.cfs_period_us", + top_cgroup, tenant_id.length(), tenant_id.ptr()); + if(OB_FAIL(get_string_from_file(cfs_path, cfs_value))) { + LOG_WARN("get cpu cfs quota failed", K(ret), K(cfs_path), K(cfs_value), K(tenant_id)); + } else { + cfs_period_us = atoi(cfs_value); + } + return ret; +} + +int ObCgroupCtrl::init_cgroup_root_dir(const char *cgroup_path) +{ + int ret = OB_SUCCESS; + char current_path[PATH_BUFSIZE]; + char value_buf[VALUE_BUFSIZE]; + bool exist_cgroup = false; + if (OB_ISNULL(cgroup_path)) { + ret = OB_INVALID_ARGUMENT; + LIB_LOG(WARN, "invalid arguments.", K(cgroup_path), K(ret)); + } else if (OB_FAIL(FileDirectoryUtils::is_exists(cgroup_path, exist_cgroup))) { + LOG_WARN("fail check file exist", K(cgroup_path), K(ret)); + } else if (!exist_cgroup) { + ret = OB_FILE_NOT_EXIST; + LOG_WARN("no cgroup directory found. disable cgroup support", K(cgroup_path), K(ret)); + } else { + // set mems and cpus + // The cpu may be discontinuous, and it is very complicated to detect it + // This always inherits the parent's settings, no need to detect it + // Subsequent child cgroups no longer need to set mems and cpus + if (OB_SUCC(ret)) { + snprintf(current_path, PATH_BUFSIZE, "%s/cgroup.clone_children", cgroup_path); + snprintf(value_buf, VALUE_BUFSIZE, "1"); + if (OB_FAIL(write_string_to_file(current_path, value_buf))) { + LOG_WARN("fail set value to file", K(current_path), K(ret)); + } + } + } + return ret; +} + +int ObCgroupCtrl::init_cgroup_dir(const char *cgroup_path) +{ + int ret = OB_SUCCESS; + char current_path[PATH_BUFSIZE]; + char value_buf[VALUE_BUFSIZE]; + if (OB_ISNULL(cgroup_path)) { + ret = OB_INVALID_ARGUMENT; + LIB_LOG(WARN, "invalid arguments.", K(cgroup_path), K(ret)); + } else if (OB_FAIL(FileDirectoryUtils::create_directory(cgroup_path))) { + LOG_WARN("create tenant cgroup dir failed", K(ret), K(cgroup_path)); + } else { + // set mems and cpus + // The cpu may be discontinuous, and it is very complicated to detect it + // This always inherits the parent's settings, no need to detect it + // Subsequent child cgroups no longer need to set mems and cpus + if (OB_SUCC(ret)) { + snprintf(current_path, PATH_BUFSIZE, "%s/cgroup.clone_children", cgroup_path); + snprintf(value_buf, VALUE_BUFSIZE, "1"); + if (OB_FAIL(write_string_to_file(current_path, value_buf))) { + LOG_WARN("fail set value to file", K(current_path), K(ret)); + } + LOG_DEBUG("debug print clone", K(current_path), K(value_buf)); + } + } + return ret; +} + +int ObCgroupCtrl::write_string_to_file(const char *filename, const char *content) +{ + int ret = OB_SUCCESS; + int fd = -1; + long int tmp_ret = -1; + if ((fd = ::open(filename, O_WRONLY)) < 0) { + ret = OB_IO_ERROR; + LOG_WARN("open file error", K(filename), K(errno), KERRMSG, K(ret)); + } else if ((tmp_ret = ::write(fd, content, strlen(content))) < 0) { + ret = OB_IO_ERROR; + LOG_WARN("write file error", + K(filename), K(content), K(ret), K(errno), KERRMSG, K(ret)); + } else { + // do nothing + } + if (fd > 0 && 0 != ::close(fd)) { + ret = OB_IO_ERROR; + LOG_WARN("close file error", + K(filename), K(fd), K(errno), KERRMSG, K(ret)); + } + return ret; +} + +int ObCgroupCtrl::get_string_from_file(const char *filename, char content[VALUE_BUFSIZE]) +{ + int ret = OB_SUCCESS; + int fd = -1; + long int tmp_ret = -1; + if ((fd = ::open(filename, O_RDONLY)) < 0) { + ret = OB_IO_ERROR; + LOG_WARN("open file error", K(filename), K(errno), KERRMSG, K(ret)); + } else if ((tmp_ret = ::read(fd, content, VALUE_BUFSIZE)) < 0) { + ret = OB_IO_ERROR; + LOG_WARN("read file error", + K(filename), K(content), K(ret), K(errno), KERRMSG, K(ret)); + } else { + // do nothing + } + if (fd > 0 && 0 != ::close(fd)) { + ret = OB_IO_ERROR; + LOG_WARN("close file error", + K(filename), K(fd), K(errno), KERRMSG, K(ret)); + } + return ret; +} + +} // end of namespace omt +} // end of namespace obproxy +} // end of namespace oceanbase diff --git a/src/obproxy/omt/ob_cgroup_ctrl.h b/src/obproxy/omt/ob_cgroup_ctrl.h new file mode 100644 index 0000000000000000000000000000000000000000..d3940564aa6405b7749cd3f1d0f334754ca5075d --- /dev/null +++ b/src/obproxy/omt/ob_cgroup_ctrl.h @@ -0,0 +1,108 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * + * ************************************************************* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OB_CGROUP_CTRL_H +#define OB_CGROUP_CTRL_H + +#include +#include +#include "lib/string/ob_string.h" + +namespace oceanbase +{ +namespace obproxy +{ +namespace omt +{ + +class ObCgroupCtrl +{ +public: + ObCgroupCtrl() + : valid_(false) + {} + virtual ~ObCgroupCtrl() {} + int init(); + // void destroy() { /* tid is automatically removed from cgroup tasks after the process exits */ } + bool is_valid() { return valid_; } + + // Create tenant cgroup group and initialize + int create_tenant_cgroup(const common::ObString& tenant_id); + + // delete tenant cgroup rules + int remove_tenant_cgroup(const common::ObString& tenant_id); + + // Add tid to the specified tenant cgroup. will deprecate + int add_thread_to_cgroup(const common::ObString tenant_id, const int64_t tid); + + // Set the cpu.shares of the specified tenant cgroup group + // int set_cpu_shares(const ObString tenant_id, const int32_t cpu_shares); + // int get_cpu_shares(const ObString tenant_id, int32_t &cpu_shares); + + // Set the cpu.cfs_quota_us of the specified tenant cgroup group + int set_cpu_cfs_quota(const common::ObString tenant_id, const int32_t cfs_quota_us); + // Get the period value of a tenant's group for calculating cfs_quota_us + int get_cpu_cfs_period(const common::ObString tenant_id, int32_t &cfs_period_us); + // Get the cpuacct.usage of a cgroup group + // int get_cpu_usage(const uint64_t tenant_id, int32_t &cpu_usage); +private: + // The initialization script of obproxy will resume the cgroup soft link, + // and the directory layout is as follows: + // ---bin/ + // |-etc/ + // |-... + // |_cgroup --> /sys/fs/cgroup/obproxy/obproxy_name + // | + // |_ user + // |- tenant_cluster_vip1 + // |- tenant_cluster_vip2 + // |_ ... + // + const char *root_cgroup_ = "cgroup"; + const char *other_cgroup_ = "cgroup/other"; + const char *user_cgroup_ = "cgroup/user"; + static const int32_t PATH_BUFSIZE = 512; + static const int32_t VALUE_BUFSIZE = 32; + // Before using ObCgroupCtrl, you need to judge whether the group_ctrl object is valid. If it is false, the cgroup mechanism will be skipped. + // The possible reasons for false are that the cgroup directory does not have permission to operate, the operating system does not support cgroups, etc. + bool valid_; + +private: + int init_cgroup_root_dir(const char *cgroup_path); + int init_cgroup_dir(const char *cgroup_path); + int write_string_to_file(const char *filename, const char *content); + int get_string_from_file(const char *filename, char content[VALUE_BUFSIZE]); +}; + +} // end of namespace omt +} // end of namespace obproxy +} // end of namespace oceanbase + +#endif // OB_CGROUP_CTRL_H diff --git a/src/obproxy/omt/ob_conn_table_processor.cpp b/src/obproxy/omt/ob_conn_table_processor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..73bb19ee6b49baf38171b35070bed4f171f91d55 --- /dev/null +++ b/src/obproxy/omt/ob_conn_table_processor.cpp @@ -0,0 +1,463 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * + * ************************************************************* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define USING_LOG_PREFIX PROXY + +#include "ob_conn_table_processor.h" +#include "obutils/ob_proxy_json_config_info.h" + +namespace oceanbase +{ +namespace obproxy +{ +namespace omt +{ + +static const char* JSON_OBPROXY_VIP = "vip"; +static const char* JSON_OBPROXY_VALUE = "value"; +static const uint32_t column_num = 4; + +using namespace oceanbase::common; +using namespace oceanbase::obproxy::obutils; +using namespace oceanbase::json; + +extern int build_tenant_cluster_vip_name(const ObString &tenant_name, const ObString &cluster_name, const ObString &vip_name, + ObFixedLengthString &key_string); + +int ObConnTableProcessor::commit(bool is_success) +{ + int ret = OB_SUCCESS; + if (!is_success) { + ret = conn_rollback(); + } + conn_backup_status_ = false; + return ret; +} + +void ObConnTableProcessor::destroy() +{ + DRWLock::WRLockGuard guard(rwlock_); + vt_conn_cache_.destroy(); +} + +bool ObConnTableProcessor::check_and_inc_conn( + ObString& cluster_name, ObString& tenant_name, ObString& ip_name) +{ + int ret = OB_SUCCESS; + bool throttle = false; + ObVipTenantConn* vt_conn = NULL; + int64_t cur_used_connections = 0; + + if (OB_FAIL(inc_conn(cluster_name, tenant_name, ip_name, cur_used_connections))) { + throttle = true; + LOG_WARN("fail to get or create used conn", K(cluster_name), K(tenant_name), K(ip_name), K(ret)); + } + + if (OB_SUCC(ret)) { + DRWLock::RDLockGuard guard(rwlock_); + if (OB_FAIL(get_vt_conn_object(cluster_name, tenant_name, ip_name, vt_conn))) { + if (OB_ENTRY_NOT_EXIST == ret) { + // Scheme review comments: Connections without configuration information are allowed to access + LOG_DEBUG("get vip tenant connect failed", K(ret)); + } else { + // Other errors, access denied + dec_conn(cluster_name, tenant_name, ip_name); + throttle = true; + } + } else { + if (cur_used_connections <= vt_conn->max_connections_) { + LOG_DEBUG("vip tenant connect info", K(cur_used_connections), KPC(vt_conn)); + } else { + LOG_WARN("used connections reach throttle", K(cur_used_connections), K(vt_conn->max_connections_), KPC(vt_conn)); + dec_conn(cluster_name, tenant_name, ip_name); + throttle = true; + } + } + } + + return throttle; +} + +int ObConnTableProcessor::inc_conn(ObString& cluster_name, ObString& tenant_name, ObString& ip_name, + int64_t& cur_used_connections) +{ + int ret = OB_SUCCESS; + ObString key_name; + ObUsedConn* used_conn = NULL; + common::ObFixedLengthString key_string; + if (OB_FAIL(build_tenant_cluster_vip_name(tenant_name, cluster_name, ip_name, key_string))) { + LOG_WARN("build tenant cluser vip name failed", K(tenant_name), K(cluster_name), K(ip_name), K(ret)); + } else { + key_name = ObString::make_string(key_string.ptr()); + if (OB_FAIL(get_or_create_used_conn(key_name, used_conn, cur_used_connections))) { + LOG_WARN("create used conn failed", K(key_name), K(ret)); + } else { + used_conn->dec_ref(); + } + } + return ret; +} + +void ObConnTableProcessor::dec_conn( + ObString& cluster_name, ObString& tenant_name, ObString& ip_name) +{ + int ret = OB_SUCCESS; + ObUsedConn* used_conn = NULL; + int64_t cur_used_connections = 0; + common::ObFixedLengthString key_string; + + if (OB_FAIL(build_tenant_cluster_vip_name(tenant_name, cluster_name, ip_name, key_string))) { + LOG_WARN("build tenant cluster vip name failed", K(ret), K(tenant_name), K(cluster_name), K(ip_name)); + } else { + ObString key_name = ObString::make_string(key_string.ptr()); + if (OB_FAIL(get_used_conn(key_name, false, used_conn, cur_used_connections))) { + LOG_WARN("fail to get used conn in map", K(key_name), K(ret)); + } else { + if (OB_NOT_NULL(used_conn)) { + if (ATOMIC_FAA(&used_conn->max_used_connections_, -1) > 1) { + LOG_DEBUG("dec conn", KPC(used_conn)); + } else { + DRWLock::WRLockGuard guard(used_conn_rwlock_); + if (0 == used_conn->max_used_connections_ && used_conn->is_in_map_) { + erase_used_conn(key_name, used_conn); + LOG_DEBUG("erase used conn", K(key_name)); + } + } + used_conn->dec_ref(); + } + } + } +} + +int ObConnTableProcessor::get_vt_conn_object( + ObString& cluster_name, ObString& tenant_name, ObString& vip_name, ObVipTenantConn*& vt_conn) +{ + int ret = OB_SUCCESS; + + common::ObFixedLengthString key_string; + if (OB_FAIL(build_tenant_cluster_vip_name(tenant_name, cluster_name, vip_name, key_string))) { + LOG_WARN("build tenant cluser vip name failed", K(ret), K(tenant_name), K(cluster_name), K(vip_name)); + } else { + ObString key_name = ObString::make_string(key_string.ptr()); + if (OB_FAIL(vt_conn_cache_.get(key_name, vt_conn))) { + if (OB_ENTRY_NOT_EXIST == ret) { + LOG_DEBUG("vip tenant connect not in cache", K(cluster_name), K(tenant_name), K(vip_name), K(ret)); + } else { + LOG_WARN("fail to get vip tenant connect in cache", K(cluster_name), K(tenant_name), K(vip_name), K(ret)); + } + } else { + LOG_DEBUG("succ to get vip tenant connect in cache", K(cluster_name), K(tenant_name), K(vip_name), KPC(vt_conn)); + } + } + + return ret; +} + +int ObConnTableProcessor::alloc_and_init_vt_conn( + ObString& cluster_name, ObString& tenant_name, ObString& vip_name, + uint32_t max_connections, ObVipTenantConn*& vt_conn) +{ + int ret = OB_SUCCESS; + ObVipTenantConn* tmp_vt_conn = NULL; + + if (OB_UNLIKELY(cluster_name.empty()) || OB_UNLIKELY(tenant_name.empty())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("name is empty", K(cluster_name), K(tenant_name), K(vip_name), K(ret)); + } else if (OB_ISNULL(tmp_vt_conn = op_alloc(ObVipTenantConn))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc memory for ObVipTenantConn", K(ret)); + } else if (OB_FAIL(tmp_vt_conn->set(cluster_name, tenant_name, vip_name, max_connections))) { + LOG_WARN("fail to set vip tenant connect info", K(ret)); + } else { + vt_conn = tmp_vt_conn; + LOG_DEBUG("succ to set vip tenant connect object", KPC(vt_conn)); + } + + if (OB_FAIL(ret) && OB_NOT_NULL(tmp_vt_conn)) { + ob_free(tmp_vt_conn); + tmp_vt_conn = NULL; + } + + return ret; +} + +// local vip json format: +//[ +// { +// "vip" : "127.0.0.1", +// "value" : "1000" +// }, +// { +// "vip" : "0.0.0.1", +// "value" : "2000" +// } +//] +int ObConnTableProcessor::fill_local_vt_conn_cache( + ObString& cluster_name, ObString& tenant_name, ObString& vip_name) +{ + int ret = OB_SUCCESS; + Parser parser; + json::Value *info_config = NULL; + ObArenaAllocator json_allocator(ObModIds::OB_JSON_PARSER); + + int max_connections = 0; + ObString vip_list_str; + if (OB_UNLIKELY(cluster_name.empty()) || OB_UNLIKELY(tenant_name.empty()) || OB_UNLIKELY(vip_name.empty())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("name is empty", K(cluster_name), K(tenant_name), K(vip_name), K(ret)); + } else if (OB_FAIL(parser.init(&json_allocator))) { + LOG_WARN("json parser init failed", K(ret)); + } else if (OB_FAIL(parser.parse(vip_name.ptr(), vip_name.length(), info_config))) { + LOG_WARN("parse json failed", K(ret), "vip_json_str", get_print_json(vip_name)); + } else if (OB_FAIL(ObProxyJsonUtils::check_config_info_type(info_config, json::JT_ARRAY))) { + LOG_WARN("check config info type failed", K(ret)); + } else { + DLIST_FOREACH(it, info_config->get_array()) { + if (OB_FAIL(ObProxyJsonUtils::check_config_info_type(it, json::JT_OBJECT))) { + LOG_WARN("check config info type failed", K(ret)); + } else { + DLIST_FOREACH(p, it->get_object()) { + if (p->name_ == JSON_OBPROXY_VIP) { + if (OB_FAIL(ObProxyJsonUtils::check_config_info_type(p->value_, json::JT_STRING))) { + LOG_WARN("check config info type failed", K(ret)); + } else { + vip_list_str = p->value_->get_string(); + } + } else if (p->name_ == JSON_OBPROXY_VALUE) { + if (OB_FAIL(ObProxyJsonUtils::check_config_info_type(p->value_, json::JT_NUMBER))) { + LOG_WARN("check config info type failed", K(ret)); + } else { + max_connections = (uint32_t)p->value_->get_number(); + } + } + } + } + + ObVipTenantConn* vt_conn = NULL; + if (OB_SUCC(ret)) { + DRWLock::WRLockGuard guard(rwlock_); + if (OB_FAIL(get_vt_conn_object(cluster_name, tenant_name, vip_list_str, vt_conn))) { + if (OB_ENTRY_NOT_EXIST == ret) { + if (OB_FAIL(alloc_and_init_vt_conn(cluster_name, tenant_name, vip_list_str, max_connections, vt_conn))) { + LOG_WARN("fail to alloc and init vip tenant connect", K(ret)); + } else if (OB_FAIL(vt_conn_cache_.set(vt_conn))) { + LOG_WARN("fail to insert one vip tenant conn into conn_map", K(vt_conn), K(ret)); + if (OB_LIKELY(NULL != vt_conn)) { + vt_conn->destroy(); + vt_conn = NULL; + } + } else { + LOG_DEBUG("succ to insert one vip tenant connect into conn_map", K(*vt_conn)); + } + } + } else { + vt_conn->max_connections_ = max_connections; + LOG_DEBUG("update vip tenant connect in cache", K(vt_conn)); + } + } + + if (OB_FAIL(ret)) { + if (OB_LIKELY(NULL != info_config)) { + info_config = NULL; + } + } + } + } + + return ret; +} + +int ObConnTableProcessor::backup_local_vt_conn_cache() +{ + int ret = OB_SUCCESS; + + DRWLock::WRLockGuard guard(rwlock_); + if (OB_FAIL(vt_conn_cache_.backup())) { + LOG_WARN("backup connect cache failed"); + } else { + conn_backup_status_ = true; + } + + return ret; +} + +int ObConnTableProcessor::conn_handle_replace_config( + ObString& cluster_name, ObString& tenant_name, ObString& name_str, ObString& value_str) +{ + UNUSED(name_str); + int ret = OB_SUCCESS; + + if (OB_UNLIKELY(cluster_name.empty()) || OB_UNLIKELY(tenant_name.empty())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("tenant or cluster is null", K(ret), K(cluster_name), K(tenant_name)); + } else if (OB_FAIL(backup_local_vt_conn_cache())) { + LOG_WARN("backup vip tenant connect cache failed", K(ret)); + } else if (OB_FAIL(fill_local_vt_conn_cache(cluster_name, tenant_name, value_str))) { + LOG_WARN("update vip tenant connect cache failed", K(ret)); + } else { + LOG_DEBUG("update vip tenant connect cache succed", "count", get_conn_map_count()); + } + + return ret; +} + +int ObConnTableProcessor::conn_handle_delete_config(ObString& cluster_name, ObString& tenant_name) +{ + int ret = OB_SUCCESS; + + if (OB_UNLIKELY(cluster_name.empty()) || OB_UNLIKELY(tenant_name.empty())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("tenant_name or cluster_name is null", K(ret), K(cluster_name), K(tenant_name)); + } else { + if (OB_FAIL(backup_local_vt_conn_cache())) { + LOG_WARN("backup vip tenant connect cache failed", K(ret)); + } else { + DRWLock::WRLockGuard guard(rwlock_); + vt_conn_cache_.erase(cluster_name, tenant_name); + } + } + + return ret; +} + +int ObConnTableProcessor::conn_rollback() +{ + int ret = OB_SUCCESS; + LOG_INFO("conn rollback"); + DRWLock::WRLockGuard guard(rwlock_); + // The backup can be rolled back only if the backup is successful + if (OB_LIKELY(conn_backup_status_)) { + if (OB_FAIL(vt_conn_cache_.recover())) { + LOG_WARN("recover connect cache failed"); + } + } + + return ret; +} + +int ObConnTableProcessor::create_used_conn(ObString& key_name, + ObUsedConn*& used_conn, int64_t& cur_used_connections) +{ + int ret = OB_SUCCESS; + DRWLock::WRLockGuard guard(used_conn_rwlock_); + ObUsedConn* tmp_used_conn = NULL; + if (OB_FAIL(used_conn_cache_.get(key_name, tmp_used_conn))) { + if (OB_HASH_NOT_EXIST == ret) { + char *buf = NULL; + int64_t alloc_size = sizeof(ObUsedConn); + if (OB_ISNULL(buf = static_cast(op_fixed_mem_alloc(alloc_size)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc memory for used conn", K(alloc_size), K(ret)); + } else { + used_conn = new (buf) ObUsedConn(key_name); + used_conn->inc_ref(); + if (OB_FAIL(used_conn_cache_.set(used_conn))) { + LOG_WARN("fail to set used conn map", K(key_name), KPC(used_conn), K(ret)); + } else { + used_conn->is_in_map_ = true; + } + } + + if (OB_SUCC(ret)) { + used_conn->inc_ref(); + cur_used_connections = ATOMIC_AAF(&used_conn->max_used_connections_, 1); + } else if (OB_NOT_NULL(used_conn)) { + used_conn->dec_ref(); + used_conn = NULL; + } + } + } else { + used_conn = tmp_used_conn; + used_conn->inc_ref(); + cur_used_connections = ATOMIC_AAF(&used_conn->max_used_connections_, 1); + } + + return ret; +} + +int ObConnTableProcessor::get_used_conn(ObString& key_name, bool is_need_inc_used_connections, + ObUsedConn*& used_conn, int64_t& cur_used_connections) +{ + int ret = OB_SUCCESS; + DRWLock::RDLockGuard guard(used_conn_rwlock_); + ObUsedConn* tmp_used_conn = NULL; + if (OB_FAIL(used_conn_cache_.get(key_name, tmp_used_conn))) { + } else { + used_conn = tmp_used_conn; + used_conn->inc_ref(); + if (is_need_inc_used_connections) { + cur_used_connections = ATOMIC_AAF(&used_conn->max_used_connections_, 1); + } + LOG_DEBUG("succ to get used conn from map", K(key_name), KPC(used_conn), K(cur_used_connections)); + } + + return ret; +} + +int ObConnTableProcessor::get_or_create_used_conn(ObString& key_name, + ObUsedConn*& used_conn, int64_t& cur_used_connections) +{ + int ret = OB_SUCCESS; + if (OB_FAIL(get_used_conn(key_name, true, used_conn, cur_used_connections))) { + if (OB_HASH_NOT_EXIST == ret) { + if (OB_FAIL(create_used_conn(key_name, used_conn, cur_used_connections))) { + LOG_WARN("fail to create used conn", K(key_name), K(ret)); + } else { + LOG_DEBUG("succ to create used conn", K(key_name), K(cur_used_connections), KPC(used_conn)); + } + } else { + LOG_WARN("fail to get used conn", K(key_name), K(ret)); + } + } + return ret; +} + +int ObConnTableProcessor::erase_used_conn(ObString& key_name, ObUsedConn* used_conn) +{ + int ret = OB_SUCCESS; + if (OB_FAIL(used_conn_cache_.erase(key_name))) { + LOG_WARN("erase used conn failed", K(key_name)); + } else { + used_conn->is_in_map_ = false; + used_conn->dec_ref(); + } + + return ret; +} + +ObConnTableProcessor &get_global_conn_table_processor() +{ + static ObConnTableProcessor conn_table_processor; + return conn_table_processor; +} + +} // end of namespace omt +} // end of namespace obproxy +} // end of namespace oceanbase diff --git a/src/obproxy/omt/ob_conn_table_processor.h b/src/obproxy/omt/ob_conn_table_processor.h new file mode 100644 index 0000000000000000000000000000000000000000..97d921b91699347a1d15e56185b21956d0428a30 --- /dev/null +++ b/src/obproxy/omt/ob_conn_table_processor.h @@ -0,0 +1,110 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * + * ************************************************************* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBPROXY_CONN_TABLE_PROCESSOR_H +#define OBPROXY_CONN_TABLE_PROCESSOR_H + +#include "obutils/ob_config_processor.h" +#include "lib/lock/ob_drw_lock.h" +#include "ob_vip_tenant_conn.h" +#include "ob_vip_tenant_cpu.h" + +namespace oceanbase +{ +namespace obproxy +{ +namespace omt +{ + +class ObConnTableProcessor +{ +public: + ObConnTableProcessor() : conn_backup_status_(false), rwlock_(), used_conn_rwlock_() {} + virtual ~ObConnTableProcessor() { destroy(); } + void destroy(); + int commit(bool is_success); + + bool check_and_inc_conn(common::ObString& cluster_name, + common::ObString& tenant_name, common::ObString& ip_name); + + int inc_conn(common::ObString& cluster_name, common::ObString& tenant_name, common::ObString& ip_name, + int64_t& cur_used_connections); + + void dec_conn(common::ObString& cluster_name, + common::ObString& tenant_name, common::ObString& ip_name); + + int get_vt_conn_object(common::ObString& cluster_name, common::ObString& tenant_name, + common::ObString& vip_name, ObVipTenantConn*& vt_conn); + + int alloc_and_init_vt_conn(common::ObString& cluster_name, common::ObString& tenant_name, + common::ObString& vip_name, uint32_t max_connections, ObVipTenantConn*& vt_conn); + + int fill_local_vt_conn_cache(common::ObString& cluster_name, common::ObString& tenant_name, + common::ObString& vip_name); + + int backup_local_vt_conn_cache(); + + int conn_handle_replace_config(common::ObString& cluster_name, common::ObString& tenant_name, + common::ObString& name_str, common::ObString& value_str); + int conn_handle_delete_config(common::ObString& cluster_name, common::ObString& tenant_name); + + ObVipTenantConnCache &get_vt_conn_cache() { return vt_conn_cache_; } + int conn_rollback(); + + int64_t get_conn_map_count() const { return vt_conn_cache_.get_conn_map_count(); } + ObVipTenantConnCache::VTHashMap* get_conn_map() { return vt_conn_cache_.get_conn_map(); } + ObVipTenantConnCache::VTHashMap& get_conn_map_replica() { return vt_conn_cache_.get_conn_map_replica(); } + + int create_used_conn(common::ObString& key_name, ObUsedConn*& used_conn, int64_t& cur_used_connections); + int get_used_conn(common::ObString& key_name, bool is_need_inc_used_connections, ObUsedConn*& used_conn, int64_t& cur_used_connections); + int erase_used_conn(common::ObString& key_name, ObUsedConn* used_conn); + int get_or_create_used_conn(common::ObString& key_name, ObUsedConn*& used_conn, int64_t& cur_used_connections); + + TO_STRING_KV(K_(conn_backup_status)); + +private: + bool conn_backup_status_; // false: backup failed; true: backup successful + + common::DRWLock rwlock_; + ObVipTenantConnCache vt_conn_cache_; + + common::DRWLock used_conn_rwlock_; + ObUsedConnCache used_conn_cache_; + + DISALLOW_COPY_AND_ASSIGN(ObConnTableProcessor); +}; + +ObConnTableProcessor &get_global_conn_table_processor(); + +} // end of namespace omt +} // end of namespace obproxy +} // end of namespace oceanbase + +#endif /* OBPROXY_CONN_TABLE_PROCESSOR_H */ diff --git a/src/obproxy/omt/ob_cpu_table_processor.cpp b/src/obproxy/omt/ob_cpu_table_processor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dc9638e0d47605b09a5a94416b259a04d798cb3a --- /dev/null +++ b/src/obproxy/omt/ob_cpu_table_processor.cpp @@ -0,0 +1,351 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * + * ************************************************************* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define USING_LOG_PREFIX PROXY + +#include "ob_cpu_table_processor.h" +#include "obutils/ob_proxy_json_config_info.h" +#include "obproxy/utils/ob_proxy_utils.h" + +namespace oceanbase +{ +namespace obproxy +{ +namespace omt +{ + +static const char* JSON_OBPROXY_VIP = "vip"; +static const char* JSON_OBPROXY_VALUE = "value"; +static const uint32_t column_num = 4; + +using namespace oceanbase::common; +using namespace oceanbase::obproxy::event; +using namespace oceanbase::obproxy::obutils; +using namespace oceanbase::json; + +extern int build_tenant_cluster_vip_name(const ObString &tenant_name, const ObString &cluster_name, const ObString &vip_name, + ObFixedLengthString &key_string); + +void ObCpuTableProcessor::commit(bool is_success) +{ + if (!is_success) { + cpu_rollback(); + } else { + cpu_commit(); + } + is_cpu_backup_succ_ = false; +} + +int ObCpuTableProcessor::init() +{ + int ret = OB_SUCCESS; + int tmp_ret = OB_SUCCESS; + if (OB_SUCCESS != (tmp_ret = cgroup_ctrl_.init())) { + // cgroup failure does not affect initialization + LOG_WARN("fail to init tenant cgroup ctrl", K(tmp_ret)); + } + return ret; +} + +void ObCpuTableProcessor::destroy() +{ + DRWLock::WRLockGuard guard(tenant_cpu_rwlock_); + tenant_cpu_cache_.destroy(); +} + +int ObCpuTableProcessor::cpu_handle_replace_config( + ObString& cluster_name, ObString& tenant_name, ObString& name_str, ObString& value_str) +{ + UNUSED(name_str); + int ret = OB_SUCCESS; + + if (OB_UNLIKELY(cluster_name.empty()) || OB_UNLIKELY(tenant_name.empty())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("tenant or cluster is null", K(ret), K(cluster_name), K(tenant_name)); + } else if (FALSE_IT(backup_local_cpu_cache())) { + } else if (OB_FAIL(fill_local_cpu_cache(cluster_name, tenant_name, value_str))) { + LOG_WARN("update vip tenant cpu cache failed", K(ret)); + } else { + LOG_INFO("update vip tenant cpu cache succ", "count", get_cpu_map_count(), K(cluster_name), K(tenant_name), K(value_str)); + } + + return ret; +} + +int ObCpuTableProcessor::cpu_handle_delete_config(ObString& cluster_name, ObString& tenant_name) +{ + int ret = OB_SUCCESS; + + if (OB_UNLIKELY(cluster_name.empty()) || OB_UNLIKELY(tenant_name.empty())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("tenant_name or cluster_name is null", K(ret), K(cluster_name), K(tenant_name)); + } else { + backup_local_cpu_cache(); + DRWLock::WRLockGuard guard(tenant_cpu_rwlock_); + tenant_cpu_cache_.erase(cluster_name, tenant_name); + LOG_INFO("erase vip tenant cpu cache succ", "count", get_cpu_map_count(), K(cluster_name), K(tenant_name)); + } + + return ret; +} + +void ObCpuTableProcessor::backup_local_cpu_cache() +{ + DRWLock::WRLockGuard guard(tenant_cpu_rwlock_); + tenant_cpu_cache_.backup(); + is_cpu_backup_succ_ = true; +} + +int ObCpuTableProcessor::check_json_value(bool has_set_vip, ObString vip_list_str, + bool has_set_value, ObString value) +{ + int ret = OB_SUCCESS; + if (has_set_vip && vip_list_str.empty()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("check json value failed", K(ret), K(has_set_vip), K(vip_list_str)); + } + if (OB_SUCC(ret)) { + if (!has_set_value || value.empty()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("check json value failed", K(ret), K(has_set_value), K(value)); + } + } + return ret; +} + +int ObCpuTableProcessor::fill_local_cpu_cache( + ObString& cluster_name, ObString& tenant_name, ObString& vip_name) +{ + int ret = OB_SUCCESS; + Parser parser; + json::Value *info_config = NULL; + ObArenaAllocator json_allocator(ObModIds::OB_JSON_PARSER); + + ObString max_cpu_usage = 0; + double double_max_cpu_usage = 0.0; + ObString vip_list_str; + bool has_set_vip = false; + bool has_set_value = false; + if (OB_UNLIKELY(cluster_name.empty()) || OB_UNLIKELY(tenant_name.empty()) || OB_UNLIKELY(vip_name.empty())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("name is empty", K(cluster_name), K(tenant_name), K(vip_name), K(ret)); + } else if (OB_FAIL(parser.init(&json_allocator))) { + LOG_WARN("json parser init failed", K(ret)); + } else if (OB_FAIL(parser.parse(vip_name.ptr(), vip_name.length(), info_config))) { + LOG_WARN("parse json failed", K(ret), "vip_json_str", get_print_json(vip_name)); + } else if (OB_FAIL(ObProxyJsonUtils::check_config_info_type(info_config, json::JT_ARRAY))) { + LOG_WARN("check config info type failed", K(ret)); + } else { + DLIST_FOREACH(it, info_config->get_array()) { + if (OB_FAIL(ObProxyJsonUtils::check_config_info_type(it, json::JT_OBJECT))) { + LOG_WARN("check config info type failed", K(ret)); + } else { + DLIST_FOREACH(p, it->get_object()) { + if (p->name_ == JSON_OBPROXY_VIP) { + if (OB_FAIL(ObProxyJsonUtils::check_config_info_type(p->value_, json::JT_STRING))) { + LOG_WARN("check config info type failed", K(ret)); + } else { + vip_list_str = p->value_->get_string(); + has_set_vip = true; + } + } else if (p->name_ == JSON_OBPROXY_VALUE) { + // note: Since json only supports integers but not doubles for numeric parsing, the JT_STRING type is used here + if (OB_FAIL(ObProxyJsonUtils::check_config_info_type(p->value_, json::JT_STRING))) { + LOG_WARN("check config info type failed", K(ret)); + } else { + max_cpu_usage = p->value_->get_string(); + has_set_value = true; + } + } + } + } + if (OB_SUCC(ret)) { + if (OB_FAIL(check_json_value(has_set_vip, vip_list_str, has_set_value, max_cpu_usage))) { + LOG_WARN("check json value failed", K(cluster_name), K(tenant_name), K(vip_list_str), K(max_cpu_usage), K(ret)); + } else if (OB_FAIL(get_double_value(max_cpu_usage, double_max_cpu_usage))) { + LOG_WARN("fail to get double", K(max_cpu_usage), K(double_max_cpu_usage), K(ret)); + } else if (OB_FAIL(handle_cpu_config(cluster_name, tenant_name, vip_list_str, double_max_cpu_usage))) { + LOG_WARN("update config faild", K(cluster_name), K(tenant_name), K(vip_list_str), K(double_max_cpu_usage), K(ret)); + } + } + } + if (OB_SUCC(ret)) { + if (OB_FAIL(check_cpu_config())) { + LOG_WARN("check config faild", K(ret)); + } else if (OB_FAIL(update_cpu_config())) { + LOG_WARN("update cpu config faild", K(ret)); + } + } + } + + return ret; +} + +int ObCpuTableProcessor::handle_cpu_config( + ObString& cluster_name, ObString& tenant_name, ObString& vip_name, double max_cpu_usage) +{ + int ret = OB_SUCCESS; + ObString key_name; + ObTenantCpu* tenant_cpu = NULL; + common::ObFixedLengthString key_string; + if (max_cpu_usage <= 0) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("max cpu usage error", K(max_cpu_usage), K(ret)); + } else if (OB_FAIL(build_tenant_cluster_vip_name(tenant_name, cluster_name, vip_name, key_string))) { + LOG_WARN("build tenant cluser vip name failed", K(tenant_name), K(cluster_name), K(vip_name), K(ret)); + } else { + key_name = ObString::make_string(key_string.ptr()); + if (OB_FAIL(get_or_create_tenant_cpu(cluster_name, tenant_name, vip_name, key_name, max_cpu_usage, tenant_cpu))) { + LOG_WARN("create tenant cpu failed", K(key_name), K(ret)); + } else { + tenant_cpu->max_cpu_usage_ = max_cpu_usage; + tenant_cpu->max_thread_num_ = (int64_t)ceil(tenant_cpu->max_cpu_usage_); + if (INSTANCE_CREATE_STATUS != tenant_cpu->instance_status_) { + tenant_cpu->instance_status_ = INSTANCE_UPDATE_STATUS; + } + tenant_cpu->dec_ref(); + } + } + return ret; +} + +int ObCpuTableProcessor::check_cpu_config() +{ + int ret = OB_SUCCESS; + DRWLock::RDLockGuard guard(tenant_cpu_rwlock_); + if (OB_FAIL(tenant_cpu_cache_.check())) { + LOG_WARN("check cpu config failed", K(ret)); + } + return ret; +} + +int ObCpuTableProcessor::update_cpu_config() +{ + int ret = OB_SUCCESS; + DRWLock::WRLockGuard guard(tenant_cpu_rwlock_); + if (OB_FAIL(tenant_cpu_cache_.update())) { + LOG_WARN("update cpu config failed", K(ret)); + } + return ret; +} + +int ObCpuTableProcessor::create_tenant_cpu(ObString& cluster_name, ObString& tenant_name, + ObString& vip_name, ObString& key_name, double max_cpu_usage, ObTenantCpu*& tenant_cpu) +{ + int ret = OB_SUCCESS; + DRWLock::WRLockGuard guard(tenant_cpu_rwlock_); + ObTenantCpu* tmp_tenant_cpu = NULL; + if (OB_FAIL(tenant_cpu_cache_.get(key_name, tmp_tenant_cpu))) { + if (OB_HASH_NOT_EXIST == ret) { + char *buf = NULL; + int64_t alloc_size = sizeof(ObTenantCpu); + if (OB_ISNULL(buf = static_cast(op_fixed_mem_alloc(alloc_size)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc memory for tenant cpu", K(alloc_size), K(ret)); + } else { + tenant_cpu = new (buf) ObTenantCpu(cluster_name, tenant_name, vip_name, key_name, max_cpu_usage, cgroup_ctrl_); + tenant_cpu->inc_ref(); + if (OB_FAIL(tenant_cpu_cache_.set(tenant_cpu))) { + LOG_WARN("fail to set tenant cpu map", K(key_name), KPC(tenant_cpu), K(ret)); + } + } + if (OB_SUCC(ret)) { + tenant_cpu->inc_ref(); + } else if (OB_NOT_NULL(tenant_cpu)) { + tenant_cpu->dec_ref(); + tenant_cpu = NULL; + } + } + } else { + tenant_cpu = tmp_tenant_cpu; + tenant_cpu->inc_ref(); + } + + return ret; +} + +int ObCpuTableProcessor::get_tenant_cpu(ObString& key_name, ObTenantCpu*& tenant_cpu) +{ + int ret = OB_SUCCESS; + DRWLock::RDLockGuard guard(tenant_cpu_rwlock_); + ObTenantCpu* tmp_tenant_cpu = NULL; + if (OB_FAIL(tenant_cpu_cache_.get(key_name, tmp_tenant_cpu))) { + } else { + tenant_cpu = tmp_tenant_cpu; + tenant_cpu->inc_ref(); + LOG_DEBUG("succ to get tenant cpu from map", K(key_name), KPC(tenant_cpu)); + } + + return ret; +} + +int ObCpuTableProcessor::get_or_create_tenant_cpu(ObString& cluster_name, ObString& tenant_name, + ObString& vip_name, ObString& key_name, double max_cpu_usage, ObTenantCpu*& tenant_cpu) +{ + int ret = OB_SUCCESS; + if (OB_FAIL(get_tenant_cpu(key_name, tenant_cpu))) { + if (OB_HASH_NOT_EXIST == ret) { + if (OB_FAIL(create_tenant_cpu(cluster_name, tenant_name, vip_name, key_name, max_cpu_usage, tenant_cpu))) { + LOG_WARN("fail to create tenant cpu", K(key_name), K(ret)); + } else { + LOG_DEBUG("succ to create tenant cpu", K(key_name), K(max_cpu_usage), KPC(tenant_cpu)); + } + } else { + LOG_WARN("fail to get tenant cpu", K(key_name), K(ret)); + } + } + return ret; +} + +void ObCpuTableProcessor::cpu_rollback() +{ + LOG_INFO("cpu rollback"); + DRWLock::WRLockGuard guard(tenant_cpu_rwlock_); + if (OB_LIKELY(is_cpu_backup_succ_)) { + tenant_cpu_cache_.recover(); + } +} + +void ObCpuTableProcessor::cpu_commit() +{ + LOG_INFO("cpu commit"); + DRWLock::WRLockGuard guard(tenant_cpu_rwlock_); + tenant_cpu_cache_.commit(); +} + +ObCpuTableProcessor &get_global_cpu_table_processor() +{ + static ObCpuTableProcessor cpu_table_processor; + return cpu_table_processor; +} + +} // end of namespace omt +} // end of namespace obproxy +} // end of namespace oceanbase diff --git a/src/obproxy/omt/ob_cpu_table_processor.h b/src/obproxy/omt/ob_cpu_table_processor.h new file mode 100644 index 0000000000000000000000000000000000000000..5141997c43c5e8f8da27bc2352248dad0ef88809 --- /dev/null +++ b/src/obproxy/omt/ob_cpu_table_processor.h @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * + * ************************************************************* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBPROXY_CPU_TABLE_PROCESSOR_H +#define OBPROXY_CPU_TABLE_PROCESSOR_H + +#include "obutils/ob_config_processor.h" +#include "lib/lock/ob_drw_lock.h" +#include "ob_vip_tenant_cpu.h" + +namespace oceanbase +{ +namespace obproxy +{ +namespace omt +{ + +class ObCpuTableProcessor +{ +public: + ObCpuTableProcessor() : is_cpu_backup_succ_(false), tenant_cpu_rwlock_() {} + virtual ~ObCpuTableProcessor() { destroy(); } + int init(); + void destroy(); + void commit(bool is_success); + int check_json_value(bool has_set_vip, common::ObString vip_list_str, bool has_set_value, common::ObString value); + int cpu_handle_replace_config(common::ObString& cluster_name, common::ObString& tenant_name, common::ObString& name_str, common::ObString& value_str); + int cpu_handle_delete_config(common::ObString& cluster_name, common::ObString& tenant_name); + void backup_local_cpu_cache(); + int fill_local_cpu_cache(common::ObString& cluster_name, common::ObString& tenant_name, common::ObString& vip_name); + int create_tenant_cpu(common::ObString& cluster_name, common::ObString& tenant_name, common::ObString& vip_name, common::ObString& key_name, double max_cpu_usage, ObTenantCpu*& tenant_cpu); + int get_tenant_cpu(common::ObString& key_name, ObTenantCpu*& tenant_cpu); + int get_or_create_tenant_cpu(common::ObString& cluster_name, common::ObString& tenant_name, common::ObString& vip_name, common::ObString& key_name, double max_cpu_usage, ObTenantCpu*& tenant_cpu); + void cpu_rollback(); + void cpu_commit(); + int64_t get_cpu_map_count() { return tenant_cpu_cache_.get_cpu_map_count(); } + int handle_cpu_config(common::ObString& cluster_name, common::ObString& tenant_name, common::ObString& vip_name, double max_cpu_usage); + int check_cpu_config(); + int update_cpu_config(); + + TO_STRING_KV(K_(is_cpu_backup_succ)); + +private: + bool is_cpu_backup_succ_; // false: backup failed; true: backup successful + ObCgroupCtrl cgroup_ctrl_; + common::DRWLock tenant_cpu_rwlock_; + ObTenantCpuCache tenant_cpu_cache_; + + DISALLOW_COPY_AND_ASSIGN(ObCpuTableProcessor); +}; + +ObCpuTableProcessor &get_global_cpu_table_processor(); + +} // end of namespace omt +} // end of namespace obproxy +} // end of namespace oceanbase + +#endif /* OBPROXY_CPU_TABLE_PROCESSOR_H */ diff --git a/src/obproxy/omt/ob_proxy_config_table_processor.cpp b/src/obproxy/omt/ob_proxy_config_table_processor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f3a1966acddda098c9e6c323f3e0ab1fdb2fbf1f --- /dev/null +++ b/src/obproxy/omt/ob_proxy_config_table_processor.cpp @@ -0,0 +1,661 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * + * ************************************************************* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define USING_LOG_PREFIX PROXY + +#include "omt/ob_proxy_config_table_processor.h" +#include "obutils/ob_config_processor.h" +#include "obutils/ob_proxy_config.h" +#include "obutils/ob_proxy_reload_config.h" +#include "lib/encrypt/ob_encrypted_helper.h" +#include "cmd/ob_internal_cmd_processor.h" + +static const char *config_name_array[] = {"proxy_route_policy", "proxy_idc_name", "enable_cloud_full_username", + "enable_client_ssl", "enable_server_ssl", + "obproxy_read_consistency", "obproxy_read_only", + "proxy_tenant_name", "rootservice_cluster_name", + "enable_read_write_split", "enable_transaction_split", + "target_db_server", "observer_sys_password", + "observer_sys_password1"}; + +static const char *EXECUTE_SQL = + "replace into proxy_config(vip, vid, vport, cluster_name, tenant_name, name, value, config_level) values(" + "'%.*s', %ld, %ld, '%.*s', '%.*s', '%s', '%s', '%.*s')"; + +using namespace oceanbase::common; +using namespace oceanbase::obproxy::obutils; +namespace oceanbase +{ +namespace obproxy +{ +namespace omt +{ + +ObProxyConfigItem* ObProxyConfigItem::clone() +{ + ObProxyConfigItem *ret = NULL; + if (OB_ISNULL(ret = op_alloc(ObProxyConfigItem))) { + LOG_WARN("op_alloc ObProxyConfigItem failed"); + } else { + ret->vip_addr_ = vip_addr_; + ret->tenant_name_ = tenant_name_; + ret->cluster_name_ = cluster_name_; + ret->config_level_ = config_level_; + ret->config_item_ = config_item_; + } + + return ret; +} + +ObProxyConfigItem::ObProxyConfigItem(const ObProxyConfigItem& item) +{ + vip_addr_ = item.vip_addr_; + cluster_name_ = item.cluster_name_; + tenant_name_ = item.tenant_name_; + config_level_ = item.config_level_; + config_item_ = config_item_; +} + +ObProxyConfigItem& ObProxyConfigItem::operator =(const ObProxyConfigItem &item) +{ + if (this != &item) { + vip_addr_ = item.vip_addr_; + cluster_name_ = item.cluster_name_; + tenant_name_ = item.tenant_name_; + config_level_ = item.config_level_; + config_item_ = item.config_item_; + } + return *this; +} + +int64_t ObProxyConfigItem::to_string(char *buf, const int64_t buf_len) const +{ + int64_t pos = 0; + J_OBJ_START(); + J_KV(K_(vip_addr), K_(tenant_name), K_(cluster_name), K_(config_level), K_(config_item)); + J_OBJ_END(); + return pos; +} + +uint64_t ObProxyConfigItem::get_hash() const +{ + uint64_t hash = 0; + void *data = (void*)(&vip_addr_); + hash = murmurhash(data, sizeof(ObVipAddr), 0); + hash = tenant_name_.hash(hash); + hash = cluster_name_.hash(hash); + hash = murmurhash(config_item_.name(), static_cast(strlen(config_item_.name())), hash); + return hash; +} + +int ObProxyConfigTableProcessor::execute(void *arg) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(NULL == arg)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("arg is null unexpected", K(ret)); + } else { + ObCloudFnParams *params = reinterpret_cast(arg); + if (NULL == params->fields_) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("fields is null unexpected", K(ret)); + } else if (params->stmt_type_ == OBPROXY_T_REPLACE) { + if (OB_FAIL(get_global_proxy_config_table_processor().set_proxy_config(params->fields_))) { + LOG_WARN("set proxy config failed", K(ret)); + } + } else if (params->stmt_type_ == OBPROXY_T_DELETE) { + if (OB_FAIL(get_global_proxy_config_table_processor().delete_proxy_config(params->fields_))) { + LOG_WARN("delete proxy config failed", K(ret)); + } + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected stmt type", K(params->stmt_type_), K(ret)); + } + } + + return ret; +} + +int ObProxyConfigTableProcessor::commit(void *arg, bool is_success) +{ + UNUSED(arg); + if (is_success) { + get_global_proxy_config_table_processor().inc_index(); + get_global_proxy_config_table_processor().inc_config_version(); + } else { + LOG_WARN("proxy config commit failed", K(is_success)); + } + + get_global_proxy_config_table_processor().clear_execute_sql(); + get_global_proxy_config_table_processor().clean_hashmap( + get_global_proxy_config_table_processor().get_backup_hashmap()); + + return OB_SUCCESS; +} + +int ObProxyConfigTableProcessor::before_commit(void *arg) +{ + sqlite3 *db = (sqlite3*)arg; + return get_global_proxy_config_table_processor().commit_execute_sql(db); +} + +void ObProxyConfigTableProcessor::inc_index() +{ + DRWLock::WRLockGuard guard(proxy_config_lock_); + index_ = (index_ + 1) % 2; +} + +ObProxyConfigTableProcessor &get_global_proxy_config_table_processor() +{ + static ObProxyConfigTableProcessor g_proxy_config_table_processor; + return g_proxy_config_table_processor; +} + +int ObProxyConfigTableProcessor::init() +{ + int ret = OB_SUCCESS; + ObConfigHandler handler; + handler.execute_func_ = &ObProxyConfigTableProcessor::execute; + handler.commit_func_ = &ObProxyConfigTableProcessor::commit; + handler.before_commit_func_ = &ObProxyConfigTableProcessor::before_commit; + if (OB_FAIL(get_global_config_processor().register_callback("proxy_config", handler))) { + LOG_WARN("register proxy config table callback failed", K(ret)); + } + + return ret; +} + +void ObProxyConfigTableProcessor::clean_hashmap(ProxyConfigHashMap &config_map) +{ + DRWLock::WRLockGuard guard(proxy_config_lock_); + clean_hashmap_with_lock(config_map); +} + +void ObProxyConfigTableProcessor::clean_hashmap_with_lock(ProxyConfigHashMap &config_map) +{ + ProxyConfigHashMap::iterator last = config_map.end(); + ProxyConfigHashMap::iterator tmp; + for (ProxyConfigHashMap::iterator it = config_map.begin(); it != last;) { + tmp = it; + ++it; + tmp->destroy(); + } + config_map.reset(); +} + +int ObProxyConfigTableProcessor::backup_hashmap_with_lock() +{ + int ret = OB_SUCCESS; + int64_t backup_index = (index_ + 1) % 2; + ProxyConfigHashMap &backup_map = proxy_config_map_array_[backup_index]; + ProxyConfigHashMap ¤t_map = proxy_config_map_array_[index_]; + clean_hashmap_with_lock(backup_map); + ProxyConfigHashMap::iterator last = current_map.end(); + for (ProxyConfigHashMap::iterator it = current_map.begin(); OB_SUCC(ret) && it != last; ++it) { + ObProxyConfigItem *item = static_cast(&(*it))->clone(); + if (NULL == item) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("clone ObProxyConfigItem failed", K(ret)); + } else if (OB_FAIL(backup_map.unique_set(item))) { + LOG_WARN("backup map set refactored failed", K(ret)); + } + } + + if (OB_FAIL(ret)) { + clean_hashmap_with_lock(backup_map); + } + + return ret; +} + +int ObProxyConfigTableProcessor::set_proxy_config(void *arg) +{ + int ret = OB_SUCCESS; + ObProxyConfigItem *item = NULL; + DRWLock::WRLockGuard guard(proxy_config_lock_); + if (OB_ISNULL(arg)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(ret)); + } else if (OB_FAIL(backup_hashmap_with_lock())) { + LOG_WARN("backup hashmap failed", K(ret)); + } else if (OB_ISNULL(item = op_alloc(ObProxyConfigItem))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("op alloc ObProxyConfigItem failed", K(ret)); + } else { + ObString vip; + int64_t vport = 0; + int64_t vid = -1; + ObString name; + SqlFieldResult *sql_fields = static_cast(arg); + for (int i = 0; OB_SUCC(ret) && i < sql_fields->field_num_; i++) { + SqlField &sql_field = *(sql_fields->fields_.at(i)); + if (0 == sql_field.column_name_.config_string_.case_compare("vip")) { + if (TOKEN_STR_VAL != sql_field.value_type_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpeted type", K(sql_field.value_type_), K(ret)); + } else { + vip = sql_field.column_value_.config_string_; + } + } else if (0 == sql_field.column_name_.config_string_.case_compare("vport")) { + if (TOKEN_STR_VAL == sql_field.value_type_) { + vport = atoi(sql_field.column_value_.config_string_.ptr()); + } else if (TOKEN_INT_VAL == sql_field.value_type_) { + vport = sql_field.column_int_value_; + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid value type", K(sql_field.value_type_), K(ret)); + } + } else if (0 == sql_field.column_name_.config_string_.case_compare("vid")) { + if (TOKEN_STR_VAL == sql_field.value_type_) { + vid = atoi(sql_field.column_value_.config_string_.ptr()); + } else if (TOKEN_INT_VAL == sql_field.value_type_) { + vid = sql_field.column_int_value_; + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid value type", K(sql_field.value_type_), K(ret)); + } + } else if (0 == sql_field.column_name_.config_string_.case_compare("config_level")) { + if (TOKEN_STR_VAL != sql_field.value_type_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpeted type", K(sql_field.value_type_), K(ret)); + } else { + item->config_level_.assign(sql_field.column_value_.config_string_.ptr()); + } + } else if (0 == sql_field.column_name_.config_string_.case_compare("tenant_name")) { + if (TOKEN_STR_VAL != sql_field.value_type_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpeted type", K(sql_field.value_type_), K(ret)); + } else { + item->tenant_name_.assign(sql_field.column_value_.config_string_.ptr()); + } + } else if (0 == sql_field.column_name_.config_string_.case_compare("cluster_name")) { + if (TOKEN_STR_VAL != sql_field.value_type_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpeted type", K(sql_field.value_type_), K(ret)); + } else { + item->cluster_name_.assign(sql_field.column_value_.config_string_.ptr()); + } + } else if (0 == sql_field.column_name_.config_string_.case_compare("name")) { + if (TOKEN_STR_VAL != sql_field.value_type_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpeted type", K(sql_field.value_type_), K(ret)); + } else { + ObString &name = sql_field.column_value_.config_string_; + item->config_item_.set_name(name.ptr()); + } + } else if (0 == sql_field.column_name_.config_string_.case_compare("value")) { + if (TOKEN_STR_VAL != sql_field.value_type_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpeted type", K(sql_field.value_type_), K(ret)); + } else { + item->config_item_.set_value(sql_field.column_value_.config_string_); + } + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected column name", K(sql_field.column_name_.config_string_)); + } + } + + if (OB_SUCC(ret)) { + item->vip_addr_.set(vip.ptr(), static_cast(vport), vid); + if (0 != strcasecmp("LEVEL_GLOBAL", item->config_level_.ptr()) + && !is_config_in_service(item->config_item_.name())) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("multi level config not supported", K(item), K(ret)); + } else { + ProxyConfigHashMap &backup_map = proxy_config_map_array_[(index_ + 1) % 2]; + // Unique_set needs to be guaranteed to be the last step, + // and the previous failure needs to release the item memory + ObProxyConfigItem* tmp_item = backup_map.remove(*item); + if (NULL != tmp_item) { + tmp_item->destroy(); + tmp_item = NULL; + } + + // need_sync_to_file_ indicates that it is not a command set by alter proxyconfig, + // but a configuration item set by proxy_config + if (need_sync_to_file_) { + if ((0 == strcasecmp("obproxy_sys_password", item->config_item_.name()) + || 0 == strcasecmp("observer_sys_password", item->config_item_.name()) + || 0 == strcasecmp("observer_sys_password1", item->config_item_.name())) + && (NULL != item->config_item_.str() && '\0' != *item->config_item_.str())) { + char value_str[common::OB_MAX_CONFIG_VALUE_LEN + 1]; + char passwd_staged1_buf[ENC_STRING_BUF_LEN]; + ObString tmp_value_string; + ObString passwd_string(ENC_STRING_BUF_LEN, passwd_staged1_buf); + if (OB_FAIL(ObEncryptedHelper::encrypt_passwd_to_stage1(item->config_item_.str(), passwd_string))) { + LOG_WARN("encrypt_passwd_to_stage1 failed", K(ret)); + } else { + MEMCPY(value_str, passwd_staged1_buf + 1, 40); + value_str[40] = '\0'; + tmp_value_string.assign(value_str, 40); + item->config_item_.set_value(tmp_value_string); + char sql[1024]; + int64_t len = static_cast(snprintf(sql, 1024, EXECUTE_SQL, vip.length(), vip.ptr(), vid, vport, + item->cluster_name_.size(), item->cluster_name_.ptr(), + item->tenant_name_.size(), item->tenant_name_.ptr(), + item->config_item_.name(), item->config_item_.str(), + item->config_level_.size(), item->config_level_.ptr())); + if (OB_UNLIKELY(len <= 0 || len >= 1024)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get execute sql failed", K(len), K(ret)); + } else { + ObProxyVariantString buf_string; + buf_string.set_value(sql); + if (OB_FAIL(execute_sql_array_.push_back(buf_string))) { + LOG_WARN("execute_sql_array push back failed", K(ret)); + } + } + } + } + } + + if (OB_SUCC(ret) && need_sync_to_file_ && 0 == strcasecmp("LEVEL_GLOBAL", item->config_level_.ptr()) && + OB_FAIL(alter_proxy_config(item->config_item_.name(), item->config_item_.str()))) { + LOG_WARN("alter proxyconfig failed", K(ret)); + } else if (OB_FAIL(backup_map.unique_set(item))) { + LOG_WARN("backup map unique_set failed", K(ret)); + } + } + } + if (OB_FAIL(ret)) { + if (NULL != item) { + item->destroy(); + item = NULL; + } + } + } + + return ret; +} + +int ObProxyConfigTableProcessor::delete_proxy_config(void *arg) +{ + // todo: Intercept and delete global configuration items + int ret = OB_SUCCESS; + DRWLock::WRLockGuard guard(proxy_config_lock_); + if (OB_ISNULL(arg)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(ret)); + } else if (OB_FAIL(backup_hashmap_with_lock())) { + LOG_WARN("backup hashmap failed", K(ret)); + } else { + SqlFieldResult *fields = static_cast(arg); + ProxyConfigHashMap &backup_map = proxy_config_map_array_[(index_ + 1) % 2]; + ProxyConfigHashMap::iterator last = backup_map.end(); + for (ProxyConfigHashMap::iterator it = backup_map.begin(); OB_SUCC(ret) && it != last;) { + ObProxyConfigItem &item = *it; + bool need_delete = true; + ++it; + for (int i = 0; OB_SUCC(ret) && need_delete && i < fields->field_num_; i++) { + SqlField* sql_field = fields->fields_.at(i); + if (0 == sql_field->column_name_.config_string_.case_compare("vip")) { + char ip_buf[256]; + item.vip_addr_.addr_.ip_to_string(ip_buf, 256); + if (TOKEN_STR_VAL != sql_field->value_type_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpeted type", K(sql_field->value_type_), K(ret)); + } else if (0 != strcasecmp(ip_buf, sql_field->column_value_.config_string_.ptr())) { + need_delete = false; + } + } else if (0 == sql_field->column_name_.config_string_.case_compare("vport")) { + int64_t vport = 0; + if (TOKEN_STR_VAL == sql_field->value_type_) { + vport = atoi(sql_field->column_value_.config_string_.ptr()); + } else if (TOKEN_INT_VAL == sql_field->value_type_) { + vport = sql_field->column_int_value_; + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid value type", K(ret)); + } + if (OB_SUCC(ret)) { + if (vport != item.vip_addr_.addr_.port_) { + need_delete = false; + } + } + } else if (0 == sql_field->column_name_.config_string_.case_compare("vid")) { + int64_t vid = 0; + if (TOKEN_STR_VAL == sql_field->value_type_) { + vid = atoi(sql_field->column_value_.config_string_.ptr()); + } else if (TOKEN_INT_VAL == sql_field->value_type_) { + vid = sql_field->column_int_value_; + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid value type", K(ret)); + } + if (OB_SUCC(ret)) { + if (vid != item.vip_addr_.vid_) { + need_delete = false; + } + } + } else if (0 == sql_field->column_name_.config_string_.case_compare("config_level")) { + if (TOKEN_STR_VAL != sql_field->value_type_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpeted type", K(sql_field->value_type_), K(ret)); + } else if (0 != strcasecmp(item.config_level_.ptr(), sql_field->column_value_.config_string_.ptr())) { + need_delete = false; + } + } else if (0 == sql_field->column_name_.config_string_.case_compare("tenant_name")) { + if (TOKEN_STR_VAL != sql_field->value_type_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpeted type", K(sql_field->value_type_), K(ret)); + } else if (0 != strcasecmp(item.tenant_name_.ptr(), sql_field->column_value_.config_string_.ptr())) { + need_delete = false; + } + } else if (0 == sql_field->column_name_.config_string_.case_compare("cluster_name")) { + if (TOKEN_STR_VAL != sql_field->value_type_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpeted type", K(sql_field->value_type_), K(ret)); + } else if (0 != strcasecmp(item.cluster_name_.ptr(), sql_field->column_value_.config_string_.ptr())) { + need_delete = false; + } + } else if (0 == sql_field->column_name_.config_string_.case_compare("name")) { + if (TOKEN_STR_VAL != sql_field->value_type_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpeted type", K(sql_field->value_type_), K(ret)); + } else if (0 != strcasecmp(item.config_item_.name(), sql_field->column_value_.config_string_.ptr())) { + need_delete = false; + } + } else if (0 == sql_field->column_name_.config_string_.case_compare("value")) { + if (TOKEN_STR_VAL != sql_field->value_type_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpeted type", K(sql_field->value_type_), K(ret)); + } else if (0 != strcasecmp(item.config_item_.str(), sql_field->column_value_.config_string_.ptr())) { + need_delete = false; + } + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected column name", K(sql_field->column_name_)); + } + } + + if (OB_SUCC(ret) && need_delete) { + if (item.config_level_ == "LEVEL_GLOBAL") { + ret = OB_NOT_SUPPORTED; + LOG_WARN("delete global config unsupported", K(ret)); + } else { + backup_map.remove(&item); + item.destroy(); + } + } + } + } + + return ret; +} + +int ObProxyConfigTableProcessor::get_config_item(const obutils::ObVipAddr &addr, + const ObString &cluster_name, + const ObString &tenant_name, + const common::ObString &name, + ObProxyConfigItem &item) +{ + int ret = OB_SUCCESS; + DRWLock::RDLockGuard guard(proxy_config_lock_); + ObProxyConfigItem *proxy_config_item = NULL; + ProxyConfigHashMap ¤t_map = proxy_config_map_array_[index_]; + + ObProxyConfigItem key; + key.vip_addr_ = addr; + key.config_item_.set_name(name.ptr()); + if (OB_FAIL(key.cluster_name_.assign(cluster_name))) { + LOG_WARN("assign cluster_name failed", K(ret)); + } else if (OB_FAIL(key.tenant_name_.assign(tenant_name))) { + LOG_WARN("assign tenant name failed", K(ret)); + } else if (OB_FAIL(current_map.get_refactored(key, proxy_config_item))) { + if (OB_HASH_NOT_EXIST != ret) { + LOG_WARN("get config item failed", K(addr), K(cluster_name), K(tenant_name), K(ret)); + } + } else if (OB_ISNULL(proxy_config_item)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("proxy config item is null unexpected", K(ret)); + } else { + item = *proxy_config_item; + LOG_TRACE("get config item succ", K(addr), K(cluster_name), K(tenant_name), K(item)); + } + + return ret; +} + +int ObProxyConfigTableProcessor::alter_proxy_config(const common::ObString &key_string, + const common::ObString &value_string) +{ + int ret = OB_SUCCESS; + char *old_value = NULL; + bool has_update_config = false; + bool has_dump_config = false; + ObProxyReloadConfig *reload_config = NULL; + ObString tmp_value_string = value_string; + if (OB_UNLIKELY(key_string.empty())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(key_string), K(value_string), K(ret)); + } else { + if (OB_ISNULL(reload_config = get_global_internal_cmd_processor().get_reload_config())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get reload config", K(ret)); + } else if (OB_ISNULL(old_value = static_cast(op_fixed_mem_alloc(OB_MAX_CONFIG_VALUE_LEN)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc mem for old_value", "size", OB_MAX_CONFIG_VALUE_LEN, K(ret)); + } else if (OB_FAIL(get_global_proxy_config().get_old_config_value(key_string, old_value, OB_MAX_CONFIG_VALUE_LEN))) { + LOG_WARN("fail to get old config value", K(key_string), K(ret)); + } else if (OB_FAIL(get_global_proxy_config().update_config_item(key_string, tmp_value_string))) { + LOG_WARN("fail to update config", K(key_string), K(tmp_value_string), K(ret)); + } else { + has_update_config = true; + LOG_DEBUG("succ to update config", K(key_string), K(value_string), K(old_value)); + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(get_global_proxy_config().check_proxy_serviceable())) { + LOG_WARN("fail to check proxy serviceable", K(ret)); + } else if (OB_FAIL(get_global_proxy_config().dump_config_to_local())) { + LOG_WARN("fail to dump_config_to_local", K(ret)); + } else { + has_dump_config = true; + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL((*reload_config)(get_global_proxy_config()))) { + WARN_ICMD("fail to reload config, but config has already dumped!!", K(ret)); + } else { + DEBUG_ICMD("succ to update config", K(key_string), K(value_string)); + } + } + + if (OB_FAIL(ret)) { + int tmp_ret = OB_SUCCESS; + if (has_update_config) { + if (OB_UNLIKELY(OB_SUCCESS != (tmp_ret = get_global_proxy_config().update_config_item( + key_string, ObString::make_string(old_value))))) { + LOG_WARN("fail to back to old config", K(key_string), K(old_value), K(tmp_ret)); + } else { + LOG_DEBUG("succ to back to old config", K(key_string), K(old_value)); + } + } + if (has_dump_config && OB_LIKELY(OB_SUCCESS == tmp_ret)) { + if (OB_UNLIKELY(OB_SUCCESS != (tmp_ret = get_global_proxy_config().dump_config_to_local()))) { + LOG_WARN("fail to dump old config", K(tmp_ret)); + } else { + LOG_DEBUG("succ to dump old config"); + } + } + } + } + + return ret; +} + +bool ObProxyConfigTableProcessor::is_config_in_service(const ObString &config_name) +{ + bool is_in_service = false; + for(int64_t i = 0; i < (sizeof(config_name_array) / sizeof(const char*)); i++) { + if (config_name == config_name_array[i]) { + is_in_service = true; + break; + } + } + + return is_in_service; +} + +int ObProxyConfigTableProcessor::commit_execute_sql(sqlite3 *db) +{ + int ret = OB_SUCCESS; + if (execute_sql_array_.count() > 0) { + if (OB_UNLIKELY(NULL == db)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("sqlite db is null unexpected", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < execute_sql_array_.count(); i++) { + char *err_msg = NULL; + ObString sql = execute_sql_array_.at(i).config_string_; + if (SQLITE_OK != sqlite3_exec(db, sql.ptr(), NULL, 0, &err_msg)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("exec failed", K(ret), "err_msg", err_msg); + } + + if (NULL != err_msg) { + sqlite3_free(err_msg); + } + } + } + + return ret; +} + +void ObProxyConfigTableProcessor::clear_execute_sql() +{ + execute_sql_array_.reset(); +} + +} // end of omt +} // end of obprxy +} // end of oceanbase diff --git a/src/obproxy/omt/ob_proxy_config_table_processor.h b/src/obproxy/omt/ob_proxy_config_table_processor.h new file mode 100644 index 0000000000000000000000000000000000000000..ef1728258deaa09274731288f5b6b5986961f87b --- /dev/null +++ b/src/obproxy/omt/ob_proxy_config_table_processor.h @@ -0,0 +1,148 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * + * ************************************************************* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OB_PROXY_CONFIG_TABLE_PROCESSOR_H_ +#define OB_PROXY_CONFIG_TABLE_PROCESSOR_H_ + +#include + +#include "lib/lock/ob_drw_lock.h" +#include "obutils/ob_vip_tenant_cache.h" +#include "lib/string/ob_fixed_length_string.h" +#include "share/config/ob_config.h" +#include "obutils/ob_proxy_string_utils.h" + +namespace oceanbase +{ +namespace obproxy +{ +namespace omt +{ + +#define MAX_CONFIG_LEVEL_LENGTH 20 + +class ObProxyConfigItem +{ +public: + ObProxyConfigItem() : vip_addr_(), tenant_name_(), cluster_name_(), config_level_(), config_item_() {} + ~ObProxyConfigItem() {} + ObProxyConfigItem(const ObProxyConfigItem &item); + ObProxyConfigItem& operator =(const ObProxyConfigItem &item); + void destroy() + { + op_free(this); + } + + int64_t to_string(char *buf, const int64_t buf_len) const; + + ObProxyConfigItem* clone(); + uint64_t get_hash() const; + obutils::ObVipAddr vip_addr_; + common::ObFixedLengthString tenant_name_; + common::ObFixedLengthString cluster_name_; + common::ObFixedLengthString config_level_; + common::ObConfigItem config_item_; + + LINK(ObProxyConfigItem, proxy_config_item_link_); +}; + +class ObProxyConfigTableProcessor +{ +public: + struct ObProxyConfigItemHashing + { + typedef const ObProxyConfigItem& Key; + typedef ObProxyConfigItem Value; + typedef ObDLList(ObProxyConfigItem, proxy_config_item_link_) ListHead; + + static uint64_t hash(Key key) + { + return key.get_hash(); + } + + static Key key(Value *value) { return *value; } + + static bool equal(Key lhs, Key rhs) + { + return lhs.vip_addr_ == rhs.vip_addr_ + && lhs.tenant_name_ == rhs.tenant_name_ + && lhs.cluster_name_ == rhs.cluster_name_ + && 0 == strcasecmp(lhs.config_item_.name(), rhs.config_item_.name()); + } + }; + typedef common::hash::ObBuildInHashMap ProxyConfigHashMap; + +public: + ObProxyConfigTableProcessor() : index_(0), proxy_config_lock_(obsys::WRITE_PRIORITY), + config_version_(0), need_sync_to_file_(false), + execute_sql_array_() {} + ~ObProxyConfigTableProcessor() {} + + int init(); + void inc_index(); + void clean_hashmap(ProxyConfigHashMap &map); + int set_proxy_config(void *arg); + int delete_proxy_config(void *arg); + int get_config_item(const obutils::ObVipAddr &addr, const common::ObString &cluster_name, + const common::ObString &teannt_name, const common::ObString &name, + ObProxyConfigItem &item); + const uint64_t get_config_version() const { return config_version_; } + void inc_config_version() { config_version_++; } + void set_need_sync_to_file(const bool bvalue) { need_sync_to_file_ = bvalue; } + ProxyConfigHashMap& get_backup_hashmap() { return proxy_config_map_array_[(index_ + 1) % 2]; } + int commit_execute_sql(sqlite3 *db); + void clear_execute_sql(); +private: + void clean_hashmap_with_lock(ProxyConfigHashMap &map); + int backup_hashmap_with_lock(); + int alter_proxy_config(const common::ObString &key_string, const common::ObString &value_string); + bool is_config_in_service(const common::ObString &config_name); + static int execute(void *arg); + static int commit(void* arg, bool is_success); + static int before_commit(void * arg); + +private: + ProxyConfigHashMap proxy_config_map_array_[2]; + int64_t index_; + common::DRWLock proxy_config_lock_; + uint64_t config_version_; + bool need_sync_to_file_; + common::ObSEArray execute_sql_array_; +private: + DISALLOW_COPY_AND_ASSIGN(ObProxyConfigTableProcessor); +}; + +extern ObProxyConfigTableProcessor &get_global_proxy_config_table_processor(); + +} // end of omt +} // end of obproxy +} // end of oceanbase + +#endif diff --git a/src/obproxy/omt/ob_resource_unit_table_processor.cpp b/src/obproxy/omt/ob_resource_unit_table_processor.cpp index 35c5f4f5a3721006c7f3efb2cf9388e916511063..6311e3b763083b6d07213e84f273c6d09b37e78b 100644 --- a/src/obproxy/omt/ob_resource_unit_table_processor.cpp +++ b/src/obproxy/omt/ob_resource_unit_table_processor.cpp @@ -31,12 +31,8 @@ #define USING_LOG_PREFIX PROXY #include "ob_resource_unit_table_processor.h" -#include "obutils/ob_proxy_json_config_info.h" - -using namespace obsys; -using namespace oceanbase::common; -using namespace oceanbase::obproxy::obutils; -using namespace oceanbase::json; +#include "ob_conn_table_processor.h" +#include "ob_cpu_table_processor.h" namespace oceanbase { @@ -45,368 +41,120 @@ namespace obproxy namespace omt { -static const char* JSON_OBPROXY_VIP = "vip"; -static const char* JSON_OBPROXY_VALUE = "value"; -static const uint32_t column_num = 4; - using namespace oceanbase::common; +using namespace oceanbase::obproxy::obutils; -ObResourceUnitTableProcessor::ObResourceUnitTableProcessor() - : is_inited_(false), backup_status_(false), rwlock_(), used_conn_rwlock_() -{ -} - -void ObResourceUnitTableProcessor::destroy() -{ - if (OB_LIKELY(is_inited_)) { - is_inited_ = false; - DRWLock::WRLockGuard guard(rwlock_); - vt_conn_cache_.destroy(); - } -} - -int ObResourceUnitTableProcessor::init() -{ - int ret = OB_SUCCESS; - - if (OB_UNLIKELY(is_inited_)) { - ret = OB_INIT_TWICE; - LOG_WARN("init twice", K(ret)); - } else { - ObConfigHandler handler; - ObString table_name = ObString::make_string("resource_unit"); - handler.execute_func_ = &execute; - handler.commit_func_ = &commit; - handler.config_type_ = OBPROXY_CONFIG_CLOUD; - if (OB_FAIL(get_global_config_processor().register_callback(table_name, handler))) { - LOG_WARN("register callback info failed", K(ret)); - } else { - is_inited_ = true; - } - } - - return ret; -} +const char* conn_name = "resource_max_connections"; +const char* cpu_name = "resource_cpu"; -int ObResourceUnitTableProcessor::execute(void* cloud_params) +int ObResourceUnitTableProcessor::get_config_params(void* args, + ObString& cluster_str, ObString& tenant_str, ObString& name_str, ObString& value_str, ObProxyBasicStmtType& stmt_type) { int ret = OB_SUCCESS; - - if (OB_ISNULL(cloud_params)) { - LOG_WARN("params should not be null"); + if (OB_ISNULL(args)) { ret = OB_INVALID_ARGUMENT; + LOG_WARN("params is null", K(ret)); } else { - ObCloudFnParams* params = (ObCloudFnParams*)cloud_params; - ObString name_str; - ObString value_str; - ObString cluster_name = params->cluster_name_; - ObString tenant_name = params->tenant_name_; + ObCloudFnParams* params = (ObCloudFnParams*)args; + cluster_str = params->cluster_name_; + tenant_str = params->tenant_name_; + stmt_type = params->stmt_type_; SqlFieldResult* fields = params->fields_; - ObProxyBasicStmtType stmt_type = params->stmt_type_; - if (OB_UNLIKELY(cluster_name.empty()) || OB_UNLIKELY(tenant_name.empty())) { + if (OB_UNLIKELY(cluster_str.empty()) || OB_UNLIKELY(tenant_str.empty())) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("tenant_name or cluster_name is null", K(ret), K(cluster_name), K(tenant_name)); + LOG_WARN("tenant or cluster is null", K(ret), K(cluster_str), K(tenant_str)); } else if (OB_ISNULL(fields)) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("fields is null unexpected", K(ret)); + LOG_WARN("fields is null", K(ret)); } else { // The storage format is:[cluster|tenant|name|value] for (int64_t i = 0; i < fields->field_num_; i++) { - SqlField& sql_field = fields->fields_.at(i); - if (0 == sql_field.column_name_.string_.case_compare("name")) { - name_str = sql_field.column_value_.config_string_; - } else if (0 == sql_field.column_name_.string_.case_compare("value")) { - value_str = sql_field.column_value_.config_string_; + SqlField* sql_field = fields->fields_.at(i); + if (0 == sql_field->column_name_.config_string_.case_compare("name")) { + name_str = sql_field->column_value_.config_string_; + } else if (0 == sql_field->column_name_.config_string_.case_compare("value")) { + value_str = sql_field->column_value_.config_string_; } } - - if (OBPROXY_T_REPLACE == stmt_type) { - if (OB_FAIL(get_global_resource_unit_table_processor().handle_replace_config( - cluster_name, tenant_name, name_str, value_str))) { - LOG_WARN("fail to handle replace cmd"); - } - } else if (OBPROXY_T_DELETE == stmt_type) { - if (OB_FAIL(get_global_resource_unit_table_processor().handle_delete_config( - cluster_name, tenant_name, name_str))) { - LOG_WARN("fail to handle delete cmd"); - } - } else { - LOG_WARN("operation is unexpected"); - ret = OB_NOT_SUPPORTED; - } - } - } - - return ret; -} - -int ObResourceUnitTableProcessor::commit(bool is_success) -{ - int ret = OB_SUCCESS; - - if (!is_success) { - ret = get_global_resource_unit_table_processor().rollback(); - } - get_global_resource_unit_table_processor().set_backup_status(false); - - return ret; -} - -bool ObResourceUnitTableProcessor::check_and_inc_conn( - ObString& cluster_name, ObString& tenant_name, ObString& ip_name) -{ - int ret = OB_SUCCESS; - bool throttle = false; - ObVipTenantConn* vt_conn = NULL; - int64_t cur_used_connections = 0; - - if (OB_FAIL(inc_conn(cluster_name, tenant_name, ip_name, cur_used_connections))) { - throttle = true; - LOG_WARN("fail to get or create used conn", K(cluster_name), K(tenant_name), K(ip_name), K(ret)); - } - - if (OB_SUCC(ret)) { - DRWLock::RDLockGuard guard(rwlock_); - if (OB_FAIL(get_vt_conn_object(cluster_name, tenant_name, ip_name, vt_conn))) { - if (OB_ENTRY_NOT_EXIST == ret) { - // Scheme review comments: Connections without configuration information are allowed to access - LOG_DEBUG("get vip tenant connect failed", K(ret)); - } else { - // Other errors, access denied - dec_conn(cluster_name, tenant_name, ip_name); - throttle = true; - } - } else { - if (cur_used_connections <= vt_conn->max_connections_) { - LOG_DEBUG("vip tenant connect info", K(cur_used_connections), KPC(vt_conn)); - } else { - LOG_WARN("used connections reach throttle", K(cur_used_connections), K(vt_conn->max_connections_), KPC(vt_conn)); - dec_conn(cluster_name, tenant_name, ip_name); - throttle = true; - } - } - } - - return throttle; -} - -int ObResourceUnitTableProcessor::inc_conn(ObString& cluster_name, ObString& tenant_name, ObString& ip_name, - int64_t& cur_used_connections) -{ - int ret = OB_SUCCESS; - ObString key_name; - ObUsedConn* used_conn = NULL; - common::ObFixedLengthString key_string; - if (OB_FAIL(build_tenant_cluster_vip_name(tenant_name, cluster_name, ip_name, key_string))) { - LOG_WARN("build tenant cluser vip name failed", K(tenant_name), K(cluster_name), K(ip_name), K(ret)); - } else { - key_name = ObString::make_string(key_string.ptr()); - if (OB_FAIL(get_or_create_used_conn(key_name, used_conn, cur_used_connections))) { - LOG_WARN("create used conn failed", K(key_name), K(ret)); - } else { - used_conn->dec_ref(); } } return ret; } -void ObResourceUnitTableProcessor::dec_conn( - ObString& cluster_name, ObString& tenant_name, ObString& ip_name) +int ObResourceUnitTableProcessor::execute(void* args) { int ret = OB_SUCCESS; - ObUsedConn* used_conn = NULL; - int64_t cur_used_connections = 0; - common::ObFixedLengthString key_string; - - if (OB_FAIL(build_tenant_cluster_vip_name(tenant_name, cluster_name, ip_name, key_string))) { - LOG_WARN("build tenant cluster vip name failed", K(ret), K(tenant_name), K(cluster_name), K(ip_name)); + ObString cluster_name; + ObString tenant_name; + ObString name_str; + ObString value_str; + ObProxyBasicStmtType stmt_type; + if (OB_FAIL(get_config_params(args, cluster_name, tenant_name, name_str, value_str, stmt_type))) { + LOG_WARN("fail to get config params", K(ret), K(cluster_name), K(tenant_name), K(name_str), K(value_str), K(stmt_type)); } else { - ObString key_name = ObString::make_string(key_string.ptr()); - if (OB_FAIL(get_used_conn(key_name, false, used_conn, cur_used_connections))) { - LOG_WARN("fail to get used conn in map", K(key_name), K(ret)); - } else { - if (OB_NOT_NULL(used_conn)) { - if (ATOMIC_FAA(&used_conn->max_used_connections_, -1) > 1) { - } else { - DRWLock::WRLockGuard guard(used_conn_rwlock_); - if (0 == used_conn->max_used_connections_ && used_conn->is_in_map_) { - erase_used_conn(key_name, used_conn); - LOG_DEBUG("erase used conn", K(key_name)); - } - } - used_conn->dec_ref(); + LOG_DEBUG("execute cloud config", K(cluster_name), K(tenant_name), K(name_str), K(value_str), K(stmt_type)); + if (OBPROXY_T_REPLACE == stmt_type) { + if (OB_FAIL(get_global_resource_unit_table_processor().handle_replace_config( + cluster_name, tenant_name, name_str, value_str))) { + LOG_WARN("fail to handle replace cmd", K(ret), K(cluster_name), K(tenant_name), K(name_str), K(value_str)); } - } - } -} - -int ObResourceUnitTableProcessor::get_vt_conn_object( - ObString& cluster_name, ObString& tenant_name, ObString& vip_name, ObVipTenantConn*& vt_conn) -{ - int ret = OB_SUCCESS; - - common::ObFixedLengthString key_string; - if (OB_FAIL(build_tenant_cluster_vip_name(tenant_name, cluster_name, vip_name, key_string))) { - LOG_WARN("build tenant cluser vip name failed", K(ret), K(tenant_name), K(cluster_name), K(vip_name)); - } else { - ObString key_name = ObString::make_string(key_string.ptr()); - if (OB_FAIL(vt_conn_cache_.get(key_name, vt_conn))) { - if (OB_ENTRY_NOT_EXIST == ret) { - LOG_DEBUG("vip tenant connect not in cache", K(cluster_name), K(tenant_name), K(vip_name), K(ret)); - } else { - LOG_WARN("fail to get vip tenant connect in cache", K(cluster_name), K(tenant_name), K(vip_name), K(ret)); + } else if (OBPROXY_T_DELETE == stmt_type) { + if (OB_FAIL(get_global_resource_unit_table_processor().handle_delete_config( + cluster_name, tenant_name, name_str))) { + LOG_WARN("fail to handle delete cmd", K(ret), K(cluster_name), K(tenant_name), K(name_str)); } } else { - LOG_DEBUG("succ to get vip tenant connect in cache", K(cluster_name), K(tenant_name), K(vip_name), KPC(vt_conn)); + ret = OB_NOT_SUPPORTED; + LOG_WARN("operation is unexpected", K(ret), K(stmt_type)); } } return ret; } -int ObResourceUnitTableProcessor::build_tenant_cluster_vip_name(const ObString &tenant_name, const ObString &cluster_name, - const ObString &vip_name, ObFixedLengthString &key_string) -{ - int ret = OB_SUCCESS; - char buf[OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + OB_IP_STR_BUFF]; - int64_t len = 0; - len = static_cast(snprintf(buf, OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + OB_IP_STR_BUFF, "%.*s#%.*s|%.*s", - tenant_name.length(), tenant_name.ptr(), - cluster_name.length(), cluster_name.ptr(), - vip_name.length(), vip_name.ptr())); - if (OB_UNLIKELY(len <= 0) || OB_UNLIKELY(len >= OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + OB_IP_STR_BUFF)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("fail to fill buf", K(ret), K(tenant_name), K(cluster_name), K(vip_name)); - } else if (OB_FAIL(key_string.assign(buf))) { - LOG_WARN("assign failed", K(ret)); - } - - return ret; -} - -int ObResourceUnitTableProcessor::alloc_and_init_vt_conn( - ObString& cluster_name, ObString& tenant_name, ObString& vip_name, - uint32_t max_connections, ObVipTenantConn*& vt_conn) +int ObResourceUnitTableProcessor::commit(void* args, bool is_success) { int ret = OB_SUCCESS; - ObVipTenantConn* tmp_vt_conn = NULL; - - if (OB_UNLIKELY(cluster_name.empty()) || OB_UNLIKELY(tenant_name.empty())) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("name is empty", K(cluster_name), K(tenant_name), K(vip_name), K(ret)); - } else if (OB_ISNULL(tmp_vt_conn = op_alloc(ObVipTenantConn))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to alloc memory for ObVipTenantConn", K(ret)); - } else if (OB_FAIL(tmp_vt_conn->set(cluster_name, tenant_name, vip_name, max_connections))) { - LOG_WARN("fail to set vip tenant connect info", K(ret)); + ObString cluster_name; + ObString tenant_name; + ObString name_str; + ObString value_str; + ObProxyBasicStmtType stmt_type; + if (OB_FAIL(get_config_params(args, cluster_name, tenant_name, name_str, value_str, stmt_type))) { + LOG_WARN("fail to get config params", K(ret), K(cluster_name), K(tenant_name), K(name_str), K(value_str), K(stmt_type)); } else { - vt_conn = tmp_vt_conn; - LOG_DEBUG("succ to set vip tenant connect object", K(*vt_conn)); - } - - if (OB_FAIL(ret) && OB_NOT_NULL(tmp_vt_conn)) { - ob_free(tmp_vt_conn); - tmp_vt_conn = NULL; - } - - return ret; -} - -// local vip json format: -//[ -// { -// "vip" : "127.0.0.1", -// "value" : "1000" -// }, -// { -// "vip" : "0.0.0.1", -// "value" : "2000" -// } -//] -int ObResourceUnitTableProcessor::fill_local_vt_conn_cache( - ObString& cluster_name, ObString& tenant_name, ObString& vip_name) -{ - int ret = OB_SUCCESS; - Parser parser; - json::Value *info_config = NULL; - ObArenaAllocator json_allocator(ObModIds::OB_JSON_PARSER); - - int max_connections = 0; - ObString vip_list_str; - if (OB_UNLIKELY(cluster_name.empty()) || OB_UNLIKELY(tenant_name.empty()) || OB_UNLIKELY(vip_name.empty())) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("name is empty", K(cluster_name), K(tenant_name), K(vip_name), K(ret)); - } else if (OB_FAIL(parser.init(&json_allocator))) { - LOG_WARN("json parser init failed", K(ret)); - } else if (OB_FAIL(parser.parse(vip_name.ptr(), vip_name.length(), info_config))) { - LOG_WARN("parse json failed", K(ret), "vip_json_str", get_print_json(vip_name)); - } else if (OB_FAIL(ObProxyJsonUtils::check_config_info_type(info_config, json::JT_ARRAY))) { - LOG_WARN("check config info type failed", K(ret)); - } else { - DLIST_FOREACH(it, info_config->get_array()) { - if (OB_FAIL(ObProxyJsonUtils::check_config_info_type(it, json::JT_OBJECT))) { - LOG_WARN("check config info type failed", K(ret)); - } else { - DLIST_FOREACH(p, it->get_object()) { - if (p->name_ == JSON_OBPROXY_VIP) { - if (OB_FAIL(ObProxyJsonUtils::check_config_info_type(p->value_, json::JT_STRING))) { - LOG_WARN("check config info type failed", K(ret)); - } else { - vip_list_str = p->value_->get_string(); - } - } else if (p->name_ == JSON_OBPROXY_VALUE) { - if (OB_FAIL(ObProxyJsonUtils::check_config_info_type(p->value_, json::JT_NUMBER))) { - LOG_WARN("check config info type failed", K(ret)); - } else { - max_connections = (uint32_t)p->value_->get_number(); - } - } - } - } - - ObVipTenantConn* vt_conn = NULL; - if (OB_SUCC(ret)) { - DRWLock::WRLockGuard guard(rwlock_); - if (OB_FAIL(get_vt_conn_object(cluster_name, tenant_name, vip_list_str, vt_conn))) { - if (OB_ENTRY_NOT_EXIST == ret) { - if (OB_FAIL(alloc_and_init_vt_conn(cluster_name, tenant_name, vip_list_str, max_connections, vt_conn))) { - LOG_WARN("fail to alloc and init vip tenant connect", K(ret)); - } else if (OB_FAIL(vt_conn_cache_.set(vt_conn))) { - LOG_WARN("fail to insert one vip tenant conn into conn_map", K(vt_conn), K(ret)); - if (OB_LIKELY(NULL != vt_conn)) { - vt_conn->destroy(); - vt_conn = NULL; - } - } else { - LOG_DEBUG("succ to insert one vip tenant connect into conn_map", K(*vt_conn)); - } - } - } else { - vt_conn->max_connections_ = max_connections; - LOG_DEBUG("update vip tenant connect in cache", K(vt_conn)); - } - } - - if (OB_FAIL(ret)) { - if (OB_LIKELY(NULL != info_config)) { - info_config = NULL; - } + LOG_DEBUG("commit cloud config", K(cluster_name), K(tenant_name), K(name_str), K(value_str), K(stmt_type), K(is_success)); + if (name_str == conn_name) { + if (OB_FAIL(get_global_conn_table_processor().commit(is_success))) { + LOG_WARN("fail to handle connection commit", K(ret), K(cluster_name), K(tenant_name), K(name_str)); } + } else if (name_str == cpu_name) { + get_global_cpu_table_processor().commit(is_success); } } return ret; } -int ObResourceUnitTableProcessor::backup_local_vt_conn_cache() +int ObResourceUnitTableProcessor::init() { int ret = OB_SUCCESS; - DRWLock::WRLockGuard guard(rwlock_); - if (OB_FAIL(vt_conn_cache_.backup())) { - LOG_WARN("backup connect cache failed"); + if (OB_UNLIKELY(is_inited_)) { + ret = OB_INIT_TWICE; + LOG_WARN("init twice", K(ret)); } else { - backup_status_ = true; + ObConfigHandler handler; + ObString table_name = ObString::make_string("resource_unit"); + handler.execute_func_ = &execute; + handler.commit_func_ = &commit; + if (OB_FAIL(get_global_config_processor().register_callback(table_name, handler))) { + LOG_WARN("register callback info failed", K(ret)); + } else if (OB_FAIL(get_global_cpu_table_processor().init())) { + LOG_WARN("init cpu processor failed", K(ret)); + } else { + is_inited_ = true; + } } return ret; @@ -416,26 +164,21 @@ int ObResourceUnitTableProcessor::handle_replace_config( ObString& cluster_name, ObString& tenant_name, ObString& name_str, ObString& value_str) { int ret = OB_SUCCESS; - if (OB_UNLIKELY(name_str.empty()) || OB_UNLIKELY(value_str.empty())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("name or value is null", K(ret), K(name_str), K(value_str)); } else { - if (0 == name_str.case_compare("resource_max_connections")) { - if (OB_FAIL(conn_handle_replace_config(cluster_name, tenant_name, name_str, value_str))) { - LOG_WARN("fail to replace vip tenant connection"); + if (name_str == conn_name) { + if (OB_FAIL(get_global_conn_table_processor().conn_handle_replace_config(cluster_name, tenant_name, name_str, value_str))) { + LOG_WARN("fail to replace connection config", K(ret), K(cluster_name), K(tenant_name), K(name_str), K(value_str)); + } + } else if (name_str == cpu_name) { + if (OB_FAIL(get_global_cpu_table_processor().cpu_handle_replace_config(cluster_name, tenant_name, name_str, value_str))) { + LOG_WARN("fail to replace cpu config", K(ret), K(cluster_name), K(tenant_name), K(name_str), K(value_str)); } - } else if (0 == name_str.case_compare("resource_memory")) { - // TODO:qianyuan.rqy - ret = OB_NOT_SUPPORTED; - LOG_WARN("now not support", K(name_str), K(ret)); - } else if (0 == name_str.case_compare("resource_cpu")) { - // TODO:qianyuan.rqy - ret = OB_NOT_SUPPORTED; - LOG_WARN("now not support", K(name_str), K(ret)); } else { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("table is unexpected", K(name_str)); + ret = OB_NOT_SUPPORTED; + LOG_WARN("operation is unexpected", K(ret), K(name_str)); } } @@ -443,173 +186,50 @@ int ObResourceUnitTableProcessor::handle_replace_config( } int ObResourceUnitTableProcessor::handle_delete_config( - ObString& cluster_name, ObString& tenant_name, ObString& name_str) + ObString& cluster_name, ObString& tenant_name, ObString& name_str) { int ret = OB_SUCCESS; - + // note: Now only supports the deletion of cluster and tenant information if (name_str.empty()) { - // Remove all resource isolation configurations - if (OB_FAIL(conn_handle_delete_config(cluster_name, tenant_name))) { - LOG_WARN("fail to execute vip tenant connection"); - } - // TODO:The configuration information of other features needs to be deleted later - } else if (0 == name_str.case_compare("resource_max_connections")) { - if (OB_FAIL(conn_handle_delete_config(cluster_name, tenant_name))) { - LOG_WARN("fail to execute vip tenant connection"); + if (OB_FAIL(get_global_conn_table_processor().conn_handle_delete_config(cluster_name, tenant_name))) { + LOG_WARN("fail to handle delete conn config", K(ret), K(cluster_name), K(tenant_name)); } - } else if (0 == name_str.case_compare("resource_memory")) { - ret = OB_NOT_SUPPORTED; - LOG_WARN("now not support", K(name_str), K(ret)); - } else if (0 == name_str.case_compare("resource_cpu")) { - ret = OB_NOT_SUPPORTED; - LOG_WARN("now not support", K(name_str), K(ret)); - } else { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("table is unexpected", K(name_str)); - } - - return ret; -} - -int ObResourceUnitTableProcessor::conn_handle_replace_config( - ObString& cluster_name, ObString& tenant_name, ObString& name_str, ObString& value_str) -{ - UNUSED(name_str); - int ret = OB_SUCCESS; - - if (OB_UNLIKELY(cluster_name.empty()) || OB_UNLIKELY(tenant_name.empty())) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("tenant or cluster is null", K(ret), K(cluster_name), K(tenant_name)); - } else if (OB_FAIL(backup_local_vt_conn_cache())) { - LOG_WARN("backup vip tenant connect cache failed", K(ret)); - } else if (OB_FAIL(fill_local_vt_conn_cache(cluster_name, tenant_name, value_str))) { - LOG_WARN("update vip tenant connect cache failed", K(ret)); - } else { - LOG_DEBUG("update vip tenant connect cache succed", "count", get_conn_map_count()); - } - - return ret; -} - -int ObResourceUnitTableProcessor::conn_handle_delete_config(ObString& cluster_name, ObString& tenant_name) -{ - int ret = OB_SUCCESS; - - if (OB_UNLIKELY(cluster_name.empty()) || OB_UNLIKELY(tenant_name.empty())) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("tenant_name or cluster_name is null", K(ret), K(cluster_name), K(tenant_name)); - } else { - if (OB_FAIL(backup_local_vt_conn_cache())) { - LOG_WARN("backup vip tenant connect cache failed", K(ret)); - } else { - DRWLock::WRLockGuard guard(rwlock_); - vt_conn_cache_.erase(cluster_name, tenant_name); + if (OB_SUCC(ret)) { + if (OB_FAIL(get_global_cpu_table_processor().cpu_handle_delete_config(cluster_name, tenant_name))) { + LOG_WARN("fail to handle delete cpu config", K(ret), K(cluster_name), K(tenant_name), K(name_str)); + } } - } - - return ret; -} - -int ObResourceUnitTableProcessor::rollback() -{ - int ret = OB_SUCCESS; - - DRWLock::WRLockGuard guard(rwlock_); - // The backup can be rolled back only if the backup is successful - if (OB_LIKELY(backup_status_)) { - if (OB_FAIL(vt_conn_cache_.recover())) { - LOG_WARN("recover connect cache failed"); + } else if (name_str == conn_name) { + if (OB_FAIL(get_global_conn_table_processor().conn_handle_delete_config(cluster_name, tenant_name))) { + LOG_WARN("fail to handle delete conn config", K(ret), K(cluster_name), K(tenant_name), K(name_str)); } - } - - return ret; -} - -int ObResourceUnitTableProcessor::create_used_conn(ObString& key_name, - ObUsedConn*& used_conn, int64_t& cur_used_connections) -{ - int ret = OB_SUCCESS; - DRWLock::WRLockGuard guard(used_conn_rwlock_); - ObUsedConn* tmp_used_conn = NULL; - if (OB_FAIL(used_conn_cache_.get(key_name, tmp_used_conn))) { - if (OB_HASH_NOT_EXIST == ret) { - char *buf = NULL; - int64_t alloc_size = sizeof(ObUsedConn); - if (OB_ISNULL(buf = static_cast(op_fixed_mem_alloc(alloc_size)))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to alloc memory for used conn", K(alloc_size), K(ret)); - } else { - used_conn = new (buf) ObUsedConn(key_name); - used_conn->inc_ref(); - if (OB_FAIL(used_conn_cache_.set(used_conn))) { - LOG_WARN("fail to set used conn map", K(key_name), KPC(used_conn), K(ret)); - } else { - used_conn->is_in_map_ = true; - } - } - - if (OB_SUCC(ret)) { - used_conn->inc_ref(); - cur_used_connections = ATOMIC_AAF(&used_conn->max_used_connections_, 1); - } else if (OB_NOT_NULL(used_conn)) { - used_conn->dec_ref(); - used_conn = NULL; - } + } else if (name_str == cpu_name) { + if (OB_FAIL(get_global_cpu_table_processor().cpu_handle_delete_config(cluster_name, tenant_name))) { + LOG_WARN("fail to handle delete cpu config", K(ret), K(cluster_name), K(tenant_name), K(name_str)); } } else { - used_conn = tmp_used_conn; - used_conn->inc_ref(); - cur_used_connections = ATOMIC_AAF(&used_conn->max_used_connections_, 1); - } - - return ret; -} - -int ObResourceUnitTableProcessor::get_used_conn(ObString& key_name, bool is_need_inc_used_connections, - ObUsedConn*& used_conn, int64_t& cur_used_connections) -{ - int ret = OB_SUCCESS; - DRWLock::RDLockGuard guard(used_conn_rwlock_); - ObUsedConn* tmp_used_conn = NULL; - if (OB_FAIL(used_conn_cache_.get(key_name, tmp_used_conn))) { - } else { - used_conn = tmp_used_conn; - used_conn->inc_ref(); - if (is_need_inc_used_connections) { - cur_used_connections = ATOMIC_AAF(&used_conn->max_used_connections_, 1); - } - LOG_DEBUG("succ to get used conn from map", K(key_name), KPC(used_conn), K(cur_used_connections)); + ret = OB_NOT_SUPPORTED; + LOG_WARN("operation is unexpected", K(ret), K(name_str)); } return ret; } -int ObResourceUnitTableProcessor::get_or_create_used_conn(ObString& key_name, - ObUsedConn*& used_conn, int64_t& cur_used_connections) -{ - int ret = OB_SUCCESS; - if (OB_FAIL(get_used_conn(key_name, true, used_conn, cur_used_connections))) { - if (OB_HASH_NOT_EXIST == ret) { - if (OB_FAIL(create_used_conn(key_name, used_conn, cur_used_connections))) { - LOG_WARN("fail to create used conn", K(key_name), K(ret)); - } else { - LOG_DEBUG("succ to create used conn", K(key_name), K(cur_used_connections), KPC(used_conn)); - } - } else { - LOG_WARN("fail to get used conn", K(key_name), K(ret)); - } - } - return ret; -} - -int ObResourceUnitTableProcessor::erase_used_conn(ObString& key_name, ObUsedConn* used_conn) +int build_tenant_cluster_vip_name(const ObString &tenant_name, const ObString &cluster_name, + const ObString &vip_name, ObFixedLengthString &key_string) { int ret = OB_SUCCESS; - if (OB_FAIL(used_conn_cache_.erase(key_name))) { - LOG_WARN("erase used conn failed", K(key_name)); - } else { - used_conn->is_in_map_ = false; - used_conn->dec_ref(); + char buf[OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + MAX_IP_ADDR_LENGTH]; + int64_t len = 0; + len = static_cast(snprintf(buf, OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + MAX_IP_ADDR_LENGTH, "%.*s#%.*s|%.*s", + tenant_name.length(), tenant_name.ptr(), + cluster_name.length(), cluster_name.ptr(), + vip_name.length(), vip_name.ptr())); + if (OB_UNLIKELY(len <= 0) || OB_UNLIKELY(len >= OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + MAX_IP_ADDR_LENGTH)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to fill buf", K(ret), K(tenant_name), K(cluster_name), K(vip_name)); + } else if (OB_FAIL(key_string.assign(buf))) { + LOG_WARN("assign failed", K(ret)); } return ret; @@ -617,8 +237,8 @@ int ObResourceUnitTableProcessor::erase_used_conn(ObString& key_name, ObUsedConn ObResourceUnitTableProcessor &get_global_resource_unit_table_processor() { - static ObResourceUnitTableProcessor t_processor; - return t_processor; + static ObResourceUnitTableProcessor resource_unit_table_processor; + return resource_unit_table_processor; } } // end of namespace omt diff --git a/src/obproxy/omt/ob_resource_unit_table_processor.h b/src/obproxy/omt/ob_resource_unit_table_processor.h index fe188c3bac4c8ca81d15c5bb9fe1157811284f81..f8f90838e3d075eb1702b0a527eb791c9e1d2486 100644 --- a/src/obproxy/omt/ob_resource_unit_table_processor.h +++ b/src/obproxy/omt/ob_resource_unit_table_processor.h @@ -28,12 +28,10 @@ * limitations under the License. */ -#ifndef OBPROXY_TENANT_PROCESSOR_H -#define OBPROXY_TENANT_PROCESSOR_H +#ifndef OBPROXY_RESOURCE_UNIT_TABLE_PROCESSOR_H +#define OBPROXY_RESOURCE_UNIT_TABLE_PROCESSOR_H #include "obutils/ob_config_processor.h" -#include "lib/lock/ob_drw_lock.h" -#include "ob_vip_tenant_conn.h" namespace oceanbase { @@ -45,80 +43,28 @@ namespace omt class ObResourceUnitTableProcessor { public: - ObResourceUnitTableProcessor(); - virtual ~ObResourceUnitTableProcessor() { destroy(); } - + ObResourceUnitTableProcessor() : is_inited_(false) {} + virtual ~ObResourceUnitTableProcessor() {} + static int execute(void* args); + static int commit(void* args, bool is_success); int init(); - void destroy(); - static int execute(void* cloud_params); - static int commit(bool is_success); - - // Handling vip tenant connection related - bool check_and_inc_conn(common::ObString& cluster_name, - common::ObString& tenant_name, common::ObString& ip_name); - - int inc_conn(common::ObString& cluster_name, common::ObString& tenant_name, common::ObString& ip_name, - int64_t& cur_used_connections); - - void dec_conn(common::ObString& cluster_name, - common::ObString& tenant_name, common::ObString& ip_name); - - int build_tenant_cluster_vip_name(const common::ObString &tenant_name, - const common::ObString &cluster_name, const common::ObString &vip_name, - common::ObFixedLengthString& key_string); - - int get_vt_conn_object(common::ObString& cluster_name, common::ObString& tenant_name, - common::ObString& vip_name, ObVipTenantConn*& vt_conn); - - int alloc_and_init_vt_conn(common::ObString& cluster_name, common::ObString& tenant_name, - common::ObString& vip_name, uint32_t max_connections, ObVipTenantConn*& vt_conn); - - int fill_local_vt_conn_cache(common::ObString& cluster_name, common::ObString& tenant_name, - common::ObString& vip_name); - - int backup_local_vt_conn_cache(); - - int handle_replace_config(common::ObString& cluster_name, common::ObString& tenant_name, - common::ObString& name_str, common::ObString& value_str); - int handle_delete_config(common::ObString& cluster_name, common::ObString& tenant_name, - common::ObString& name_str); - - int conn_handle_replace_config(common::ObString& cluster_name, common::ObString& tenant_name, - common::ObString& name_str, common::ObString& value_str); - int conn_handle_delete_config(common::ObString& cluster_name, common::ObString& tenant_name); - - ObVipTenantConnCache &get_vt_conn_cache() { return vt_conn_cache_; } - int rollback(); - void set_backup_status(bool status) { backup_status_ = status; } - - int64_t get_conn_map_count() const { return vt_conn_cache_.get_conn_map_count(); } - ObVipTenantConnCache::VTHashMap* get_conn_map() { return vt_conn_cache_.get_conn_map(); } - ObVipTenantConnCache::VTHashMap& get_conn_map_replica() { return vt_conn_cache_.get_conn_map_replica(); } - - int create_used_conn(common::ObString& key_name, ObUsedConn*& used_conn, int64_t& cur_used_connections); - int get_used_conn(common::ObString& key_name, bool is_need_inc_used_connections, ObUsedConn*& used_conn, int64_t& cur_used_connections); - int erase_used_conn(common::ObString& key_name, ObUsedConn* used_conn); - int get_or_create_used_conn(common::ObString& key_name, ObUsedConn*& used_conn, int64_t& cur_used_connections); - - TO_STRING_KV(K_(is_inited), K_(backup_status)); + static int get_config_params(void* args, common::ObString& cluster_str, common::ObString& tenant_str, + common::ObString& name_str, common::ObString& value_str, ObProxyBasicStmtType& stmt_type); + int handle_replace_config(common::ObString& cluster_name, common::ObString& tenant_name, common::ObString& name_str, common::ObString& value_str); + int handle_delete_config(common::ObString& cluster_name, common::ObString& tenant_name, common::ObString& name_str); + TO_STRING_KV(K_(is_inited)); private: bool is_inited_; - bool backup_status_; // false: backup fail; true: backup success - - common::DRWLock rwlock_; - ObVipTenantConnCache vt_conn_cache_; - - common::DRWLock used_conn_rwlock_; - ObUsedConnCache used_conn_cache_; - DISALLOW_COPY_AND_ASSIGN(ObResourceUnitTableProcessor); }; ObResourceUnitTableProcessor &get_global_resource_unit_table_processor(); - +int build_tenant_cluster_vip_name(const common::ObString &tenant_name, + const common::ObString &cluster_name, const common::ObString &vip_name, + common::ObFixedLengthString& key_string); } // end of namespace omt } // end of namespace obproxy } // end of namespace oceanbase -#endif /* OBPROXY_TENANT_PROCESSOR_H */ +#endif /* OBPROXY_RESOURCE_UNIT_TABLE_PROCESSOR_H */ diff --git a/src/obproxy/omt/ob_ssl_config_table_processor.cpp b/src/obproxy/omt/ob_ssl_config_table_processor.cpp index bfc0be6fbd178dfd55f9c85a50b310478ebcd798..7f05b7404f633804b71caa78c47f6ec16b00ed5e 100644 --- a/src/obproxy/omt/ob_ssl_config_table_processor.cpp +++ b/src/obproxy/omt/ob_ssl_config_table_processor.cpp @@ -72,11 +72,11 @@ int ObSSLConfigTableProcessor::execute(void *arg) LOG_WARN("execute failed, tenant_name or cluster_name is null", K(ret), K(cluster_name), K(tenant_name)); } else { for (int64_t i = 0; i < params->fields_->field_num_; i++) { - SqlField &sql_field = params->fields_->fields_.at(i); - if (sql_field.column_name_.string_ == "value") { - value = sql_field.column_value_.config_string_; - } else if (sql_field.column_name_.string_ == "name") { - name = sql_field.column_value_.config_string_; + SqlField *sql_field = params->fields_->fields_.at(i); + if (0 == sql_field->column_name_.config_string_.case_compare("value")) { + value = sql_field->column_value_.config_string_; + } else if (0 == sql_field->column_name_.config_string_.case_compare("name")) { + name = sql_field->column_value_.config_string_; } } @@ -101,8 +101,9 @@ int ObSSLConfigTableProcessor::execute(void *arg) return ret; } -int ObSSLConfigTableProcessor::commit(bool is_success) +int ObSSLConfigTableProcessor::commit(void* arg, bool is_success) { + UNUSED(arg); if (is_success) { get_global_ssl_config_table_processor().inc_index(); get_global_ssl_config_table_processor().handle_delete(); @@ -128,7 +129,6 @@ int ObSSLConfigTableProcessor::init() ObConfigHandler handler; handler.execute_func_ = &ObSSLConfigTableProcessor::execute; handler.commit_func_ = &ObSSLConfigTableProcessor::commit; - handler.config_type_ = OBPROXY_CONFIG_CLOUD; if (OB_FAIL(ssl_config_map_array_[0].create(32, ObModIds::OB_PROXY_SSL_RELATED))) { LOG_WARN("create hash map failed", K(ret)); } else if (OB_FAIL(ssl_config_map_array_[1].create(32, ObModIds::OB_PROXY_SSL_RELATED))) { @@ -146,6 +146,7 @@ int ObSSLConfigTableProcessor::set_ssl_config(const ObString &cluster_name, const ObString &value) { int ret = OB_SUCCESS; + DRWLock::WRLockGuard guard(ssl_config_lock_); if (OB_UNLIKELY(cluster_name.empty() || tenant_name.empty() || name.empty() || value.empty())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("set ssl config failed, invalid argument", K(cluster_name), K(tenant_name), K(name), K(value), K(ret)); @@ -158,7 +159,6 @@ int ObSSLConfigTableProcessor::set_ssl_config(const ObString &cluster_name, if (OB_FAIL(paste_tenant_and_cluster_name(tenant_name, cluster_name, key_string))) { LOG_WARN("paster tenant and cluser name failed", K(ret), K(tenant_name), K(cluster_name)); } else { - DRWLock::WRLockGuard guard(ssl_config_lock_); SSLConfigHashMap &backup_map = ssl_config_map_array_[(index_ + 1) % 2]; if (OB_FAIL(backup_map.get_refactored(key_string, ssl_config_info))) { if (OB_HASH_NOT_EXIST == ret) { @@ -169,37 +169,7 @@ int ObSSLConfigTableProcessor::set_ssl_config(const ObString &cluster_name, } if (OB_SUCC(ret)) { - if (0 == name.compare("enable_client_ssl")) { - if (0 == value.case_compare("true")) { - ssl_config_info.enable_client_ssl_ = true; - } else if (0 == value.case_compare("false")) { - ssl_config_info.enable_client_ssl_ = false; - } else { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("set enable_client_ssl failed", K(ret), K(name), K(value)); - } - - if (OB_SUCC(ret) && cluster_name == "*" && tenant_name == "*") { - if (OB_FAIL(alter_ssl_config(name, value))) { - LOG_WARN("alter ssl config faield", K(ret), K(name), K(value)); - } - } - } else if (0 == name.compare("enable_server_ssl")) { - if (0 == value.case_compare("true")) { - ssl_config_info.enable_server_ssl_ = true; - } else if (0 == value.case_compare("false")) { - ssl_config_info.enable_server_ssl_ = false; - } else { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("set enable_server_ssl failed", K(ret), K(name), K(value)); - } - - if (OB_SUCC(ret) && cluster_name == "*" && tenant_name == "*") { - if (OB_FAIL(alter_ssl_config(name, value))) { - LOG_WARN("alter ssl config faield", K(ret), K(name), K(value)); - } - } - } else if (0 == name.compare("key_info")) { + if (0 == name.compare("key_info")) { Parser parser; json::Value *json_value = NULL; ObArenaAllocator json_allocator(ObModIds::OB_JSON_PARSER); @@ -273,6 +243,7 @@ int ObSSLConfigTableProcessor::set_ssl_config(const ObString &cluster_name, int ObSSLConfigTableProcessor::delete_ssl_config(ObString &cluster_name, ObString &tenant_name) { int ret = OB_SUCCESS; + DRWLock::WRLockGuard guard(ssl_config_lock_); if (cluster_name.empty() || tenant_name.empty()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("cluster name or tenant name empty unexpected", K(ret)); @@ -284,20 +255,11 @@ int ObSSLConfigTableProcessor::delete_ssl_config(ObString &cluster_name, ObStrin if (OB_FAIL(paste_tenant_and_cluster_name(tenant_name, cluster_name, key_string))) { LOG_WARN("paste tenant and cluster name failed", K(ret), K(tenant_name), K(cluster_name)); } else { - DRWLock::WRLockGuard guard(ssl_config_lock_); SSLConfigHashMap &backup_map = ssl_config_map_array_[(index_ + 1) % 2]; if (OB_FAIL(backup_map.erase_refactored(key_string))) { LOG_WARN("addr hash map erase failed", K(ret)); } else { delete_info_ = key_string; - - if (cluster_name == "*" && tenant_name == "*") { - if (OB_FAIL(alter_ssl_config("enable_client_ssl", "false"))) { - LOG_WARN("alter client ssl config failed", K(ret)); - } else if (OB_FAIL(alter_ssl_config("enable_server_ssl", "false"))) { - LOG_WARN("alter server ssl config failed", K(ret)); - } - } } } } @@ -307,8 +269,6 @@ int ObSSLConfigTableProcessor::delete_ssl_config(ObString &cluster_name, ObStrin void SSLConfigInfo::reset() { - enable_client_ssl_ = false; - enable_server_ssl_ = false; is_key_info_valid_ = false; } @@ -316,7 +276,7 @@ int64_t SSLConfigInfo::to_string(char *buf, const int64_t buf_len) const { int64_t pos = 0; J_OBJ_START(); - J_KV(K_(enable_client_ssl), K_(enable_server_ssl), K_(is_key_info_valid)); + J_KV(K_(is_key_info_valid)); J_OBJ_END(); return pos; } @@ -348,20 +308,18 @@ void ObSSLConfigTableProcessor::inc_index() void ObSSLConfigTableProcessor::handle_delete() { - DRWLock::WRLockGuard guard(ssl_config_lock_); + DRWLock::WRLockGuard guard(ssl_config_lock_); if (!delete_info_.is_empty()) { g_ssl_processor.release_ssl_ctx(delete_info_); delete_info_.reset(); } } -bool ObSSLConfigTableProcessor::is_ssl_supported(const common::ObString &cluster_name, - const common::ObString &tenant_name, - bool is_client) +bool ObSSLConfigTableProcessor::is_ssl_key_info_valid(const common::ObString &cluster_name, + const common::ObString &tenant_name) { bool bret = false; int ret = OB_SUCCESS; - LOG_DEBUG("check ssl support", K(cluster_name), K(tenant_name), K(is_client)); if (OB_UNLIKELY(IS_DEBUG_ENABLED())) { get_global_ssl_config_table_processor().print_config(); } @@ -412,9 +370,8 @@ bool ObSSLConfigTableProcessor::is_ssl_supported(const common::ObString &cluster } if (OB_SUCC(ret)) { - bool enable_ssl = is_client ? ssl_config_info.enable_client_ssl_ : ssl_config_info.enable_server_ssl_; - bret = enable_ssl && ssl_config_info.is_key_info_valid_; - LOG_DEBUG("get ssl config", K(enable_ssl), K(bret), K(cluster_name), K(tenant_name), K(is_client)); + bret = ssl_config_info.is_key_info_valid_; + LOG_DEBUG("get ssl config", K(cluster_name), K(tenant_name), K(bret)); } return bret; } @@ -428,94 +385,6 @@ void ObSSLConfigTableProcessor::print_config() } } -bool ObSSLConfigTableProcessor::is_ssl_key_info_valid(const ObString &cluster_name, - const ObString &tenant_name) -{ - bool bret = false; - int ret = OB_SUCCESS; - if (OB_UNLIKELY(cluster_name.empty() || tenant_name.empty())) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid argument", K(cluster_name), K(tenant_name), K(ret)); - } else { - SSLConfigInfo ssl_config_info; - ssl_config_info.reset(); - ObFixedLengthString key_string; - DRWLock::RDLockGuard guard(ssl_config_lock_); - SSLConfigHashMap ¤t_map = ssl_config_map_array_[index_]; - if (OB_FAIL(paste_tenant_and_cluster_name(tenant_name, cluster_name, key_string))) { - LOG_WARN("paste tenant and cluster_name failed", K(ret), K(tenant_name), K(cluster_name)); - } else if (OB_FAIL(current_map.get_refactored(key_string, ssl_config_info))) { - if (OB_HASH_NOT_EXIST != ret) { - LOG_WARN("ssl ctx map get refactored failed", K(ret), K(cluster_name), K(tenant_name)); - } else { - ret = OB_SUCCESS; - } - } else { - LOG_DEBUG("get ssl config from tenant succ", K(ssl_config_info)); - // Currently, the settings ensure that source_type, ca, public_key and private_key are set at the same time - if (ssl_config_info.is_key_info_valid_) { - bret = true; - } - } - } - return bret; -} - -int ObSSLConfigTableProcessor::alter_ssl_config(const common::ObString &key_string, const common::ObString &value_string) -{ - int ret = OB_SUCCESS; - char *old_value = NULL; - bool has_update_config = false; - bool has_dump_config = false; - if (OB_UNLIKELY(key_string.empty() || value_string.empty())) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid argument", K(ret)); - } else { - if (OB_ISNULL(old_value = static_cast(op_fixed_mem_alloc(OB_MAX_CONFIG_VALUE_LEN)))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to alloc mem for old_value", "size", OB_MAX_CONFIG_VALUE_LEN, K(ret)); - } else if (OB_FAIL(get_global_proxy_config().get_old_config_value(key_string, old_value, OB_MAX_CONFIG_VALUE_LEN))) { - LOG_WARN("fail to get old config value", K(key_string), K(ret)); - } else if (OB_FAIL(get_global_proxy_config().update_config_item(key_string, value_string))) { - LOG_WARN("fail to update config", K(key_string), K(value_string), K(ret)); - } else { - has_update_config = true; - LOG_DEBUG("succ to update config", K(key_string), K(value_string), K(old_value)); - } - - if (OB_SUCC(ret)) { - if (OB_FAIL(get_global_proxy_config().check_proxy_serviceable())) { - LOG_WARN("fail to check proxy serviceable", K(ret)); - } else if (OB_FAIL(get_global_proxy_config().dump_config_to_local())) { - LOG_WARN("fail to dump_config_to_local", K(ret)); - } else { - has_dump_config = true; - } - } - - if (OB_FAIL(ret)) { - int tmp_ret = OB_SUCCESS; - if (has_update_config) { - if (OB_UNLIKELY(OB_SUCCESS != (tmp_ret = get_global_proxy_config().update_config_item( - key_string, ObString::make_string(old_value))))) { - LOG_WARN("fail to back to old config", K(key_string), K(old_value), K(tmp_ret)); - } else { - LOG_DEBUG("succ to back to old config", K(key_string), K(old_value)); - } - } - if (has_dump_config && OB_LIKELY(OB_SUCCESS == tmp_ret)) { - if (OB_UNLIKELY(OB_SUCCESS != (tmp_ret = get_global_proxy_config().dump_config_to_local()))) { - LOG_WARN("fail to dump old config", K(tmp_ret)); - } else { - LOG_DEBUG("succ to dump old config"); - } - } - } - } - - return ret; -} - } // end of omt } // end of obproxy } // end of oceanbase diff --git a/src/obproxy/omt/ob_ssl_config_table_processor.h b/src/obproxy/omt/ob_ssl_config_table_processor.h index a8c0311aaa24c86d36289ae99b202552eb6c21fa..a6d7675f7baaae3395f2a52ebe6f85baef6eba60 100644 --- a/src/obproxy/omt/ob_ssl_config_table_processor.h +++ b/src/obproxy/omt/ob_ssl_config_table_processor.h @@ -46,8 +46,6 @@ namespace omt struct SSLConfigInfo { SSLConfigInfo() { reset(); } - bool enable_client_ssl_; - bool enable_server_ssl_; bool is_key_info_valid_; void reset(); @@ -66,14 +64,12 @@ public: int set_ssl_config(const common::ObString &cluster_name, const common::ObString &tenant_name, const common::ObString &name, const common::ObString &value); int delete_ssl_config(common::ObString &cluster_name, common::ObString &tenant_name); - bool is_ssl_supported(const common::ObString &cluster_name, const common::ObString &tenant_name, bool is_client); bool is_ssl_key_info_valid(const common::ObString &cluster_name, const common::ObString &tenant_name); void print_config(); private: int backup_hash_map(); - int alter_ssl_config(const common::ObString &key, const common::ObString &value); static int execute(void *arg); - static int commit(bool is_success); + static int commit(void* arg, bool is_success); private: typedef common::hash::ObHashMap, SSLConfigInfo> SSLConfigHashMap; @@ -86,7 +82,7 @@ private: DISALLOW_COPY_AND_ASSIGN(ObSSLConfigTableProcessor); }; -ObSSLConfigTableProcessor &get_global_ssl_config_table_processor(); +extern ObSSLConfigTableProcessor &get_global_ssl_config_table_processor(); } // end of omt } // end of obproxy diff --git a/src/obproxy/omt/ob_vip_tenant_conn.cpp b/src/obproxy/omt/ob_vip_tenant_conn.cpp index 972aca39b9e420b88b9028a2d40cc50e9e707b47..86f3480bfef15b540b6c3f784a97ae389f6ea20d 100644 --- a/src/obproxy/omt/ob_vip_tenant_conn.cpp +++ b/src/obproxy/omt/ob_vip_tenant_conn.cpp @@ -32,7 +32,7 @@ #include "ob_vip_tenant_conn.h" #include "lib/oblog/ob_log.h" -#include "omt/ob_resource_unit_table_processor.h" +#include "omt/ob_conn_table_processor.h" namespace oceanbase { @@ -44,6 +44,9 @@ namespace omt using namespace obsys; using namespace oceanbase::common; +extern int build_tenant_cluster_vip_name(const ObString &tenant_name, const ObString &cluster_name, const ObString &vip_name, + ObFixedLengthString &key_string); + int ObVipTenantConn::set_tenant_cluster(const ObString &tenant_name, const ObString &cluster_name) { int ret = OB_SUCCESS; @@ -63,7 +66,7 @@ int ObVipTenantConn::set_tenant_cluster(const ObString &tenant_name, const ObStr int ObVipTenantConn::set_addr(const common::ObString addr) { int ret = OB_SUCCESS; - if (addr.empty() || addr.length() > OB_IP_STR_BUFF) { + if (addr.empty() || addr.length() > MAX_IP_ADDR_LENGTH) { ret = OB_INVALID_ARGUMENT; LOG_WARN("name invalid", K(addr), K(ret)); } else { @@ -77,9 +80,8 @@ int ObVipTenantConn::set_full_name() { int ret = OB_SUCCESS; - ObFixedLengthString full_name; - if (OB_FAIL(get_global_resource_unit_table_processor().build_tenant_cluster_vip_name( - tenant_name_, cluster_name_, vip_name_, full_name))) { + ObFixedLengthString full_name; + if (OB_FAIL(build_tenant_cluster_vip_name(tenant_name_, cluster_name_, vip_name_, full_name))) { LOG_WARN("build tenant cluser and vip name failed", K(ret), K_(tenant_name), K_(cluster_name), K_(vip_name)); } else { MEMCPY(full_name_str_, full_name.ptr(), full_name.size()); @@ -147,7 +149,7 @@ int ObVipTenantConnCache::get(ObString& key_name, ObVipTenantConn*& vt_conn) int ret = OB_SUCCESS; ObVipTenantConn *tmp_vt_conn = NULL; - if (key_name.empty() || key_name.length() > OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + OB_IP_STR_BUFF) { + if (key_name.empty() || key_name.length() > OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + MAX_IP_ADDR_LENGTH) { ret = OB_INVALID_ARGUMENT; LOG_WARN("name invalid", K(key_name), K(ret)); } else { @@ -229,19 +231,19 @@ int ObVipTenantConnCache::backup() //CWLockGuard guard(rwlock_); // Initialization state: - // vt_conn_map_ = vt_conn_map_array[0]; + // vt_conn_map_ = vt_conn_map_array[0]; // replica_vt_conn_map = vt_conn_map_array[1]; VTHashMap& replica_vt_conn_map = get_conn_map_replica(); clear_conn_map(replica_vt_conn_map); // Even if an error occurs in the backup process and an error is returned to the cloud platform, vt_conn_map_ is still the previous configuration information VTHashMap::iterator last = vt_conn_map_->end(); for (VTHashMap::iterator it = vt_conn_map_->begin(); it != last; ++it) { - ObVipTenantConn* tmp_vt_conn = NULL; + ObVipTenantConn* tmp_vt_conn = NULL; if (OB_ISNULL(tmp_vt_conn = op_alloc(ObVipTenantConn))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to alloc memory for ObVipTenantConn", K(ret)); } else if (OB_FAIL(tmp_vt_conn->set( - it->cluster_name_, it->tenant_name_, it->vip_name_, it->max_connections_))) { + it->cluster_name_, it->tenant_name_, it->vip_name_, it->max_connections_))) { LOG_WARN("fail to set vip tenant connect info", K(ret)); } else if (OB_FAIL(replica_vt_conn_map.unique_set(tmp_vt_conn))) { LOG_WARN("insert vip tenant connection failed", K(ret)); @@ -300,7 +302,7 @@ void ObVipTenantConnCache::dump_conn_map(VTHashMap &cache_map) int ObUsedConnCache::get(ObString& key_name, ObUsedConn*& used_conn) { int ret = OB_SUCCESS; - if (key_name.empty() || key_name.length() > OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + OB_IP_STR_BUFF) { + if (key_name.empty() || key_name.length() > OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + MAX_IP_ADDR_LENGTH) { ret = OB_INVALID_ARGUMENT; LOG_WARN("name invalid", K(key_name), K(ret)); } else if (OB_FAIL(used_conn_map_.get_refactored(key_name, used_conn))) { @@ -324,7 +326,7 @@ int ObUsedConnCache::set(ObUsedConn* used_conn) int ObUsedConnCache::erase(ObString& key_name) { int ret = OB_SUCCESS; - if (key_name.empty() || key_name.length() > OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + OB_IP_STR_BUFF) { + if (key_name.empty() || key_name.length() > OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + MAX_IP_ADDR_LENGTH) { ret = OB_INVALID_ARGUMENT; LOG_WARN("name invalid", K(key_name), K(ret)); } else if (OB_FAIL(used_conn_map_.erase_refactored(key_name))) { diff --git a/src/obproxy/omt/ob_vip_tenant_conn.h b/src/obproxy/omt/ob_vip_tenant_conn.h index c5d9015f7eed90e6e7a32b0ec86e43416056e6e3..ea3de354b07fc9ece030c71b44fdb4297781b9f8 100644 --- a/src/obproxy/omt/ob_vip_tenant_conn.h +++ b/src/obproxy/omt/ob_vip_tenant_conn.h @@ -78,10 +78,10 @@ public: LINK(ObVipTenantConn, vt_link_); private: - char tenant_name_str_[common::OB_MAX_TENANT_NAME_LENGTH]; + char tenant_name_str_[common::OB_MAX_TENANT_NAME_LENGTH]; char cluster_name_str_[OB_PROXY_MAX_CLUSTER_NAME_LENGTH]; - char vip_name_str_[common::OB_IP_STR_BUFF]; - char full_name_str_[OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + common::OB_IP_STR_BUFF]; + char vip_name_str_[common::MAX_IP_ADDR_LENGTH]; + char full_name_str_[OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + common::MAX_IP_ADDR_LENGTH]; DISALLOW_COPY_AND_ASSIGN(ObVipTenantConn); }; @@ -109,7 +109,7 @@ public: typedef common::hash::ObBuildInHashMap VTHashMap; public: - + int set(ObVipTenantConn* vt); int get(common::ObString& key_name, ObVipTenantConn*& vt_conn); int erase(common::ObString& cluster_name, common::ObString& tenant_name); @@ -132,10 +132,11 @@ private: class ObUsedConn : public common::ObSharedRefCount { public: ObUsedConn(common::ObString& full_name) : max_used_connections_(0), is_in_map_(false) { - if (full_name.length() < OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + common::OB_IP_STR_BUFF) { + if (full_name.length() < OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + common::MAX_IP_ADDR_LENGTH) { MEMCPY(full_name_str_, full_name.ptr(), full_name.length()); full_name_.assign_ptr(full_name_str_, (int32_t)full_name.length()); } + memset(&used_conn_link_, 0, sizeof(used_conn_link_)); } virtual ~ObUsedConn() { reset(); }; virtual void free() { destroy(); } @@ -157,7 +158,7 @@ public: bool is_in_map_; private: - char full_name_str_[OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + common::OB_IP_STR_BUFF]; + char full_name_str_[OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + common::MAX_IP_ADDR_LENGTH]; DISALLOW_COPY_AND_ASSIGN(ObUsedConn); }; diff --git a/src/obproxy/omt/ob_vip_tenant_cpu.cpp b/src/obproxy/omt/ob_vip_tenant_cpu.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5260ec22d35ce735ec44103d5ee2537fc8595af3 --- /dev/null +++ b/src/obproxy/omt/ob_vip_tenant_cpu.cpp @@ -0,0 +1,326 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * + * ************************************************************* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define USING_LOG_PREFIX PROXY + +#include "ob_vip_tenant_cpu.h" +#include "lib/oblog/ob_log.h" +#include "iocore/net/ob_net_def.h" + +namespace oceanbase +{ +namespace obproxy +{ +namespace omt +{ + +using namespace oceanbase::common; +using namespace oceanbase::obproxy::event; + +ObTenantCpu::ObTenantCpu(ObString& cluster_name, ObString& tenant_name, + ObString& vip_name, ObString& full_name, double max_cpu_usage, ObCgroupCtrl &cgroup_ctrl) + : max_cpu_usage_(max_cpu_usage), backup_max_cpu_usage_(max_cpu_usage), + cgroup_ctrl_(cgroup_ctrl), index_(0), is_inited_(false), instance_status_(INSTANCE_CREATE_STATUS) +{ + if (cluster_name.length() < OB_PROXY_MAX_CLUSTER_NAME_LENGTH) { + MEMCPY(cluster_name_str_, cluster_name.ptr(), cluster_name.length()); + cluster_name_.assign_ptr(cluster_name_str_, cluster_name.length()); + } + if (tenant_name.length() < OB_MAX_TENANT_NAME_LENGTH) { + MEMCPY(tenant_name_str_, tenant_name.ptr(), tenant_name.length()); + tenant_name_.assign_ptr(tenant_name_str_, tenant_name.length()); + } + if (vip_name.length() < MAX_IP_ADDR_LENGTH) { + MEMCPY(vip_name_str_, vip_name.ptr(), vip_name.length()); + vip_name_.assign_ptr(vip_name_str_, vip_name.length()); + } + if (full_name.length() < OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + MAX_IP_ADDR_LENGTH) { + MEMCPY(full_name_str_, full_name.ptr(), full_name.length()); + full_name_.assign_ptr(full_name_str_, full_name.length()); + } + max_thread_num_ = (int64_t)ceil(max_cpu_usage_); + backup_max_thread_num_ = max_thread_num_; + memset(&cpu_link_, 0, sizeof(cpu_link_)); +} + +int ObTenantCpu::init() +{ + int ret = OB_SUCCESS; + ObString tenant_id = full_name_; + if (cgroup_ctrl_.is_valid()) { + if (!is_inited_) { + if (OB_FAIL(cgroup_ctrl_.create_tenant_cgroup(tenant_id))) { + LOG_WARN("create tenant cgroup failed", K(ret), K(tenant_id)); + } else { + is_inited_ = true; + } + } + } else { + ret = OB_FILE_NOT_EXIST; + LOG_WARN("cgroup is not valid", K(ret)); + } + return ret; +} + +void ObTenantCpu::destroy() +{ + LOG_INFO("tenant cpu will be destroyed", KPC(this)); + if (is_inited_) { + remove_tenant_cgroup(); + } + ObEThread* ethread = NULL; + for (int i = 0; i < thread_array_.count(); ++i) { + ethread = NULL; + thread_array_.at(i, ethread); + if (OB_NOT_NULL(ethread)) { + ethread->use_status_ = false; + } + } + reset(); + int64_t total_len = sizeof(ObTenantCpu); + op_fixed_mem_free(this, total_len); +} + +void ObTenantCpu::remove_tenant_cgroup() +{ + LOG_INFO("tenant cgroup will be destroyed", KPC(this)); + int tmp_ret = OB_SUCCESS; + ObString tenant_id = full_name_; + if (cgroup_ctrl_.is_valid() && OB_SUCCESS != (tmp_ret = cgroup_ctrl_.remove_tenant_cgroup(tenant_id))) { + LOG_WARN("remove tenant cgroup failed", K(tmp_ret), K(tenant_id)); + } + is_inited_ = false; +} + +void ObTenantCpu::reset() +{ + tenant_name_.reset(); + cluster_name_.reset(); + vip_name_.reset(); + full_name_.reset(); + max_thread_num_ = 0; + backup_max_thread_num_ = 0; + max_cpu_usage_ = 0.0; + backup_max_cpu_usage_ = 0.0; + thread_array_.reset(); +} + +int ObTenantCpu::acquire_more_worker(const int64_t tid) +{ + int ret = OB_SUCCESS; + int tmp_ret = OB_SUCCESS; + ObString tenant_id = full_name_; + if (cgroup_ctrl_.is_valid() && OB_SUCCESS != (tmp_ret = cgroup_ctrl_.add_thread_to_cgroup(tenant_id, tid))) { + LOG_WARN("add thread to cgroup failed", K(ret), K(tenant_id), K(tid)); + } + return ret; +} + +int ObTenantCpu::set_unit_max_cpu(double cpu) +{ + int ret = OB_SUCCESS; + ObString tenant_id = full_name_; + if (cgroup_ctrl_.is_valid()) { + int32_t cfs_period_us = 0; + if (OB_FAIL(cgroup_ctrl_.get_cpu_cfs_period(tenant_id, cfs_period_us))) { + LOG_WARN("get cpu cfs period failed", K(ret), K(tenant_id), K(cfs_period_us)); + } else if (OB_FAIL(cgroup_ctrl_.set_cpu_cfs_quota(tenant_id, (uint32_t)(cfs_period_us * cpu)))) { + LOG_WARN("set cpu cfs quota failed", K(ret), K(tenant_id), K(cfs_period_us * cpu)); + } + } else { + ret = OB_FILE_NOT_EXIST; + LOG_WARN("cgroup is not valid", K(ret)); + } + return ret; +} + +void ObTenantCpuCache::destroy() +{ + clear_cpu_map(vt_cpu_map_); +} + +int64_t ObTenantCpuCache::get_cpu_map_count() +{ + int64_t ret = -1; + ret = vt_cpu_map_.count(); + return ret; +} + +int ObTenantCpuCache::get(ObString& key_name, ObTenantCpu*& tenant_cpu) +{ + int ret = OB_SUCCESS; + if (key_name.empty() || key_name.length() > OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + MAX_IP_ADDR_LENGTH) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("name invalid", K(key_name), K(ret)); + } else if (OB_FAIL(vt_cpu_map_.get_refactored(key_name, tenant_cpu))) { + LOG_DEBUG("fail to get tenant cpu", K(key_name), K(ret)); + } + return ret; +} + +int ObTenantCpuCache::set(ObTenantCpu* tenant_cpu) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(tenant_cpu)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("tenant cpu is null", K(ret)); + } else if (OB_FAIL(vt_cpu_map_.unique_set(tenant_cpu))) { + LOG_WARN("fail to set tenant cpu", K(tenant_cpu), K(ret)); + } + return ret; +} + +int ObTenantCpuCache::erase(ObString& cluster_name, ObString& tenant_name) +{ + int ret = OB_SUCCESS; + LOG_INFO("erase cpu config"); + if (cluster_name.empty() || tenant_name.empty()) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid input value", K(ret), K(cluster_name), K(tenant_name)); + } else { + VTCpuHashMap::iterator last = vt_cpu_map_.end(); + for (VTCpuHashMap::iterator it = vt_cpu_map_.begin(); it != last;) { + if (it->cluster_name_ == cluster_name && it->tenant_name_ == tenant_name) { + VTCpuHashMap::iterator tmp = it; + ++it; + vt_cpu_map_.erase_refactored(tmp->full_name_); + tmp->dec_ref(); + } else { + ++it; + } + } + } + + return ret; +} + +void ObTenantCpuCache::backup() +{ + LOG_INFO("backup cpu config"); + VTCpuHashMap::iterator last = vt_cpu_map_.end(); + for (VTCpuHashMap::iterator it = vt_cpu_map_.begin(); it != last; ++it) { + it->backup_max_cpu_usage_ = it->max_cpu_usage_; + it->backup_max_thread_num_ = it->max_thread_num_; + } +} + +int ObTenantCpuCache::recover() +{ + int ret = OB_SUCCESS; + VTCpuHashMap::iterator last = vt_cpu_map_.end(); + for (VTCpuHashMap::iterator it = vt_cpu_map_.begin(); it != last && OB_SUCC(ret);) { + if (INSTANCE_CREATE_STATUS == it->instance_status_) { + VTCpuHashMap::iterator tmp = it; + ++it; + vt_cpu_map_.erase_refactored(tmp->full_name_); + tmp->dec_ref(); + } else { + if (INSTANCE_UPDATE_STATUS == it->instance_status_) { + it->max_cpu_usage_ = it->backup_max_cpu_usage_; + it->max_thread_num_ = it->backup_max_thread_num_; + if (OB_FAIL(it->set_unit_max_cpu(it->max_cpu_usage_))) { + LOG_WARN("set max cpu failed", K(ret)); + } + } + ++it; + } + } + return ret; +} + +int ObTenantCpuCache::check() +{ + LOG_INFO("check cpu config"); + int ret = OB_SUCCESS; + double max_cpu_value = 0.0; + int64_t max_thread_hold = 0; + int64_t cpu_num = g_event_processor.get_cpu_count(); + + VTCpuHashMap::iterator it = vt_cpu_map_.begin(); + for (; it != vt_cpu_map_.end(); ++it) { + max_cpu_value += it->max_cpu_usage_; + max_thread_hold += std::max(it->thread_array_.count(), it->max_thread_num_); + } + if ((max_cpu_value - (double)cpu_num > 0) || (max_thread_hold > MAX_THREADS_IN_EACH_TYPE)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("check config params failed", K(max_cpu_value), K(max_thread_hold), K(cpu_num)); + } + return ret; +} + +int ObTenantCpuCache::update() +{ + int ret = OB_SUCCESS; + LOG_INFO("update cpu config"); + VTCpuHashMap::iterator last = vt_cpu_map_.end(); + for (VTCpuHashMap::iterator it = vt_cpu_map_.begin(); it != last && OB_SUCC(ret); ++it) { + if (INSTANCE_CREATE_STATUS == it->instance_status_ || INSTANCE_UPDATE_STATUS == it->instance_status_) { + if (OB_FAIL(it->init())) { + LOG_WARN("init tenant cgroup failed", K(ret)); + } else if (OB_FAIL(it->set_unit_max_cpu(it->max_cpu_usage_))) { + LOG_WARN("set max cpu failed", K(ret)); + } + } + } + return ret; +} + +void ObTenantCpuCache::commit() +{ + VTCpuHashMap::iterator last = vt_cpu_map_.end(); + for (VTCpuHashMap::iterator it = vt_cpu_map_.begin(); it != last; ++it) { + it->instance_status_ = INSTANCE_COMMIT_STATUS; + } +} + +void ObTenantCpuCache::clear_cpu_map(VTCpuHashMap &cache_map) +{ + VTCpuHashMap::iterator last = cache_map.end(); + VTCpuHashMap::iterator tmp; + for (VTCpuHashMap::iterator it = cache_map.begin(); it != last;) { + tmp = it; + ++it; + tmp->dec_ref(); + } + cache_map.reset(); +} + +void ObTenantCpuCache::dump_cpu_map(VTCpuHashMap &cache_map) +{ + VTCpuHashMap::iterator last = cache_map.end(); + for (VTCpuHashMap::iterator it = cache_map.begin(); it != last; ++it) { + LOG_INFO("key: ", K(it->full_name_)); + LOG_INFO("value: ", K(it->max_cpu_usage_)); + } +} + +} // end of namespace omt +} // end of namespace obproxy +} // end of namespace oceanbase diff --git a/src/obproxy/omt/ob_vip_tenant_cpu.h b/src/obproxy/omt/ob_vip_tenant_cpu.h new file mode 100644 index 0000000000000000000000000000000000000000..d0ee29ae4f1ddf0a4bcf34cca94d40602f180c5f --- /dev/null +++ b/src/obproxy/omt/ob_vip_tenant_cpu.h @@ -0,0 +1,151 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * + * ************************************************************* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OB_VIP_TENANT_CPU_H +#define OB_VIP_TENANT_CPU_H + +#include "lib/hash/ob_build_in_hashmap.h" +#include "utils/ob_proxy_lib.h" +#include "iocore/eventsystem/ob_buf_allocator.h" +#include "iocore/eventsystem/ob_ethread.h" +#include "lib/container/ob_se_array.h" +#include "lib/lock/ob_drw_lock.h" +#include "ob_cgroup_ctrl.h" + +namespace oceanbase +{ +namespace obproxy +{ +namespace omt +{ + +enum ObTenantCpuStatus { + INSTANCE_CREATE_STATUS = 0, + INSTANCE_UPDATE_STATUS, + INSTANCE_COMMIT_STATUS +}; + +class ObTenantCpu : public common::ObSharedRefCount { +public: + ObTenantCpu( + common::ObString& cluster_name, + common::ObString& tenant_name, + common::ObString& vip_name, + common::ObString& full_name, + double max_cpu_usage, + ObCgroupCtrl &cgroup_ctrl); + virtual ~ObTenantCpu() { reset(); }; + virtual void free() { destroy(); } + int init(); + void destroy(); + void remove_tenant_cgroup(); + void reset(); + event::ObEThread* get_tenant_schedule_ethread() { + return thread_array_[index_++ % thread_array_.count()]; + } + + int set_unit_max_cpu(double cpu); + int acquire_more_worker(const int64_t tid); + + TO_STRING_KV(K_(tenant_name), K_(cluster_name), K_(vip_name), K_(full_name), + K_(max_thread_num), K_(backup_max_thread_num), K_(max_cpu_usage), K_(backup_max_cpu_usage), + K_(index), K_(is_inited), K_(instance_status)); + +public: + common::ObString tenant_name_; + common::ObString cluster_name_; + common::ObString vip_name_; + common::ObString full_name_; + int64_t max_thread_num_; + int64_t backup_max_thread_num_; + double max_cpu_usage_; + double backup_max_cpu_usage_; + ObCgroupCtrl &cgroup_ctrl_; + int64_t index_; + bool is_inited_; + ObTenantCpuStatus instance_status_; + common::ObSEArray thread_array_; + + LINK(ObTenantCpu, cpu_link_); + +private: + char tenant_name_str_[common::OB_MAX_TENANT_NAME_LENGTH]; + char cluster_name_str_[OB_PROXY_MAX_CLUSTER_NAME_LENGTH]; + char vip_name_str_[common::MAX_IP_ADDR_LENGTH]; + char full_name_str_[OB_PROXY_MAX_TENANT_CLUSTER_NAME_LENGTH + common::MAX_IP_ADDR_LENGTH]; + DISALLOW_COPY_AND_ASSIGN(ObTenantCpu); +}; + +class ObTenantCpuCache +{ +public: + ObTenantCpuCache() : vt_cpu_map_() { } + virtual ~ObTenantCpuCache() { } + + void destroy(); + +public: + static const int64_t HASH_BUCKET_SIZE = 64; + + struct VTCacheHashing + { + typedef const common::ObString &Key; + typedef ObTenantCpu Value; + typedef ObDLList(ObTenantCpu, cpu_link_) ListHead; + + static uint64_t hash(Key key) { return key.hash(); } + static Key key(Value *value) { return value->full_name_; } + static bool equal(Key lhs, Key rhs) { return lhs == rhs; } + }; + typedef common::hash::ObBuildInHashMap VTCpuHashMap; + +public: + int set(ObTenantCpu* vt); + int get(common::ObString& key_name, ObTenantCpu*& vt_conn); + int erase(common::ObString& cluster_name, common::ObString& tenant_name); + void backup(); + int recover(); + int check(); + int update(); + void commit(); + int64_t get_cpu_map_count(); + void clear_cpu_map(VTCpuHashMap &cache_map); + void dump_cpu_map(VTCpuHashMap &cache_map); + +private: + VTCpuHashMap vt_cpu_map_; + DISALLOW_COPY_AND_ASSIGN(ObTenantCpuCache); +}; + +} // namespace omt +} // namespace obproxy +} // namespace oceanbase + +#endif // OB_VIP_TENANT_CPU_H diff --git a/src/obproxy/omt/ob_white_list_table_processor.cpp b/src/obproxy/omt/ob_white_list_table_processor.cpp index c434d8504b8513e6e03220cbd777347b810ad1b6..b332c216efc8c3ea7844cdc1a2656e14452489af 100644 --- a/src/obproxy/omt/ob_white_list_table_processor.cpp +++ b/src/obproxy/omt/ob_white_list_table_processor.cpp @@ -63,9 +63,9 @@ int ObWhiteListTableProcessor::execute(void *arg) LOG_WARN("execute failed, tenant_name or cluster_name is null", K(ret), K(cluster_name), K(tenant_name)); } else { for (int64_t i = 0; i < params->fields_->field_num_; i++) { - SqlField &sql_field = params->fields_->fields_.at(i); - if (sql_field.column_name_.string_ == "value") { - ip_list = sql_field.column_value_.config_string_; + SqlField *sql_field = params->fields_->fields_.at(i); + if (0 == sql_field->column_name_.config_string_.case_compare("value")) { + ip_list = sql_field->column_value_.config_string_; } } @@ -86,8 +86,9 @@ int ObWhiteListTableProcessor::execute(void *arg) return ret; } -int ObWhiteListTableProcessor::commit(bool is_success) +int ObWhiteListTableProcessor::commit(void* arg, bool is_success) { + UNUSED(arg); if (is_success) { get_global_white_list_table_processor().inc_index(); if (OB_UNLIKELY(IS_DEBUG_ENABLED())) { @@ -96,6 +97,8 @@ int ObWhiteListTableProcessor::commit(bool is_success) } else { LOG_WARN("white list commit failed"); } + get_global_white_list_table_processor().clean_hashmap( + get_global_white_list_table_processor().get_backup_hashmap()); return OB_SUCCESS; } @@ -112,7 +115,6 @@ int ObWhiteListTableProcessor::init() ObConfigHandler handler; handler.execute_func_ = &ObWhiteListTableProcessor::execute; handler.commit_func_ = &ObWhiteListTableProcessor::commit; - handler.config_type_ = OBPROXY_CONFIG_CLOUD; if (OB_FAIL(addr_hash_map_array_[0].create(32, ObModIds::OB_HASH_BUCKET))) { LOG_WARN("create hash map failed", K(ret)); } else if (OB_FAIL(addr_hash_map_array_[1].create(32, ObModIds::OB_HASH_BUCKET))) { @@ -140,6 +142,7 @@ int ObWhiteListTableProcessor::set_ip_list(ObString &cluster_name, ObString &ten { int ret = OB_SUCCESS; + DRWLock::WRLockGuard guard(white_list_lock_); if (cluster_name.empty() || tenant_name.empty() || ip_list.empty()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("argument is unexpected", K(ret), K(cluster_name), K(tenant_name), K(ip_list)); @@ -151,6 +154,7 @@ int ObWhiteListTableProcessor::set_ip_list(ObString &cluster_name, ObString &ten int pos = 0; AddrStruct ip_addr; memset(&ip_addr, 0, sizeof(AddrStruct)); + bool set_ip = false; while (OB_SUCC(ret) && pos < ip_list.length()) { if (ip_list[pos] == ',' || pos == ip_list.length() - 1 || ip_list[pos] == '/') { char buf[64]; @@ -161,10 +165,16 @@ int ObWhiteListTableProcessor::set_ip_list(ObString &cluster_name, ObString &ten } memcpy(buf, start, len); buf[len] = '\0'; - if (ip_addr.ip_ == 0) { - if (OB_FAIL(ip_to_int(buf, ip_addr.ip_))) { - LOG_WARN("ip to int failed", K(ret)); + if (!set_ip) { + if (false == ip_addr.addr_.set_ip_addr(buf, 0)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("set ip addr failed", K(buf), K(ret)); break; + } else { + if (ObAddr::VER::IPV4 == ip_addr.addr_.version_) { + ip_addr.v4_ = to_little_endian(htonl(ip_addr.addr_.ip_.v4_)); + } + set_ip = true; } } else { ip_addr.net_ = atoi(buf); @@ -180,6 +190,7 @@ int ObWhiteListTableProcessor::set_ip_list(ObString &cluster_name, ObString &ten LOG_WARN("ip addr push back failed", K(ret)); } else { memset(&ip_addr, 0, sizeof(AddrStruct)); + set_ip = false; } } pos++; @@ -196,7 +207,6 @@ int ObWhiteListTableProcessor::set_ip_list(ObString &cluster_name, ObString &ten if (OB_FAIL(paste_tenant_and_cluster_name(tenant_name, cluster_name, key_string))) { LOG_WARN("paster tenant and cluser name failed", K(ret), K(tenant_name), K(cluster_name)); } else { - DRWLock::WRLockGuard guard(white_list_lock_); WhiteListHashMap &backup_map = addr_hash_map_array_[(index_ + 1) % 2]; if (OB_FAIL(backup_map.set_refactored(key_string, addr_array, 1))) { LOG_WARN("addr hash map set failed", K(ret)); @@ -210,6 +220,7 @@ int ObWhiteListTableProcessor::set_ip_list(ObString &cluster_name, ObString &ten int ObWhiteListTableProcessor::delete_ip_list(ObString &cluster_name, ObString &tenant_name) { int ret = OB_SUCCESS; + DRWLock::WRLockGuard guard(white_list_lock_); if (cluster_name.empty() || tenant_name.empty()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("cluster name or tenant name empty unexpected", K(ret)); @@ -221,7 +232,6 @@ int ObWhiteListTableProcessor::delete_ip_list(ObString &cluster_name, ObString & if (OB_FAIL(paste_tenant_and_cluster_name(tenant_name, cluster_name, key_string))) { LOG_WARN("paste tenant and cluster name failed", K(ret), K(tenant_name), K(cluster_name)); } else { - DRWLock::WRLockGuard guard(white_list_lock_); WhiteListHashMap &backup_map = addr_hash_map_array_[(index_ + 1) % 2]; if (OB_FAIL(backup_map.erase_refactored(key_string))) { LOG_WARN("addr hash map erase failed", K(ret)); @@ -232,26 +242,26 @@ int ObWhiteListTableProcessor::delete_ip_list(ObString &cluster_name, ObString & return ret; } -bool ObWhiteListTableProcessor::can_ip_pass(ObString &cluster_name, ObString &tenant_name, ObString &user_name, char* ip) +bool ObWhiteListTableProcessor::can_ip_pass(ObString &cluster_name, ObString &tenant_name, + ObString &user_name, const struct sockaddr& addr) { - uint32_t ip_value = 0; - int ret = OB_SUCCESS; bool can_pass = false; - if (OB_FAIL(ip_to_int(ip, ip_value))) { - LOG_WARN("ip to in failed", K(ret)); - } else { - can_pass = can_ip_pass(cluster_name, tenant_name, user_name, ip_value, false); + if (net::ops_is_ip4(addr)) { + can_pass = can_ipv4_pass(cluster_name, tenant_name, user_name, addr); + } else if (net::ops_is_ip6(addr)) { + can_pass = can_ipv6_pass(cluster_name, tenant_name, user_name, addr); } return can_pass; } -bool ObWhiteListTableProcessor::can_ip_pass(ObString &cluster_name, ObString &tenant_name, - ObString &user_name, uint32_t src_ip, bool is_big_endian) +bool ObWhiteListTableProcessor::can_ipv4_pass(ObString &cluster_name, ObString &tenant_name, + ObString &user_name, const struct sockaddr& in_addr) { int ret = OB_SUCCESS; bool can_pass = false; - uint32_t ip = is_big_endian ? to_little_endian(src_ip) : src_ip; - LOG_DEBUG("check can ip pass", K(cluster_name), K(tenant_name), K(ip)); + ObIpEndpoint endpoint(in_addr); + uint32_t ip = to_little_endian(endpoint.sin_.sin_addr.s_addr); + LOG_DEBUG("check can ip pass", K(cluster_name), K(tenant_name), K(endpoint)); if (!cluster_name.empty() && !tenant_name.empty()) { ObFixedLengthString key_string; if (OB_FAIL(paste_tenant_and_cluster_name(tenant_name, cluster_name, key_string))) { @@ -263,22 +273,71 @@ bool ObWhiteListTableProcessor::can_ip_pass(ObString &cluster_name, ObString &te if (OB_SUCC(current_map.get_refactored(key_string, ip_array))) { for (int64_t i = 0; !can_pass && i < ip_array.count(); i++) { AddrStruct addr = ip_array.at(i); - if (0 == addr.ip_) { + if (0 == addr.v4_) { can_pass = true; } else if (0 == addr.net_) { - can_pass = (addr.ip_ == ip); + can_pass = (addr.v4_ == ip); } else { uint32_t mask = 0xffffffff; - can_pass = (addr.ip_ == (ip & (mask << (32 - addr.net_)))); + can_pass = (addr.v4_ == (ip & (mask << (32 - addr.net_)))); } - if (OB_UNLIKELY(IS_DEBUG_ENABLED())) { - ObIpEndpoint client_info; - ObIpEndpoint white_list_info; - client_info.sin_.sin_addr.s_addr = __bswap_32(ip); - client_info.sin_.sin_family = AF_INET; - white_list_info.sin_.sin_addr.s_addr = __bswap_32(addr.ip_); - white_list_info.sin_.sin_family = AF_INET; - LOG_DEBUG("ip check can pass", K(client_info), K(white_list_info), "mask", addr.net_, K(can_pass)); + } + } else if (OB_HASH_NOT_EXIST == ret) { + can_pass = true; + } else { + LOG_WARN("unexpected error", K(ret)); + } + } + } else { + LOG_WARN("cluster_name or tenant_name is empty", K(cluster_name), K(tenant_name), K(endpoint)); + } + + if (!can_pass) { + LOG_WARN("can not pass white_list", K(cluster_name), K(tenant_name), K(user_name), K(endpoint)); + } + + return can_pass; +} + +bool ObWhiteListTableProcessor::can_ipv6_pass(ObString &cluster_name, ObString &tenant_name, + ObString &user_name, const struct sockaddr& in6_addr) +{ + int ret = OB_SUCCESS; + bool can_pass =false; + ObIpEndpoint endpoint(in6_addr); + LOG_DEBUG("check can ip pass", K(cluster_name), K(tenant_name), K(endpoint)); + if (!cluster_name.empty() && !tenant_name.empty()) { + ObFixedLengthString key_string; + if (OB_FAIL(paste_tenant_and_cluster_name(tenant_name, cluster_name, key_string))) { + LOG_WARN("paste tenant and cluster name failed", K(ret), K(tenant_name), K(cluster_name)); + } else { + ObSEArray ip_array; + DRWLock::RDLockGuard guard(white_list_lock_); + WhiteListHashMap ¤t_map = addr_hash_map_array_[index_]; + if (OB_SUCC(current_map.get_refactored(key_string, ip_array))) { + for (int64_t i = 0; !can_pass && i < ip_array.count(); i++) { + AddrStruct addr = ip_array.at(i); + if (addr.addr_.ip_.v6_[0] == 0 && addr.addr_.ip_.v6_[1] == 0 + && addr.addr_.ip_.v6_[2] == 0 && addr.addr_.ip_.v6_[3] == 0) { + can_pass = true; + } else { + int64_t net = addr.net_; + int64_t index = 0; + can_pass = true; + sockaddr_storage ss = addr.addr_.get_sockaddr(); + sockaddr_in6 &in6 = *(sockaddr_in6*)(&ss); + while ((net - 8) >= 0 && can_pass) { + if (in6.sin6_addr.s6_addr[index] != endpoint.sin6_.sin6_addr.s6_addr[index]) { + can_pass = false; + } + index++; + net -= 8; + } + + if (net && can_pass) { + can_pass = in6.sin6_addr.s6_addr[index] == + (endpoint.sin6_.sin6_addr.s6_addr[index] & (0xff << (8 - net))); + } } } } else if (OB_HASH_NOT_EXIST == ret) { @@ -288,13 +347,11 @@ bool ObWhiteListTableProcessor::can_ip_pass(ObString &cluster_name, ObString &te } } } else { - LOG_WARN("cluster_name or tenant_name is empty", K(cluster_name), K(tenant_name), K(ip)); + LOG_WARN("cluster_name or tenant_name is empty", K(cluster_name), K(tenant_name), K(endpoint)); } if (!can_pass) { - struct sockaddr_in address; - address.sin_addr.s_addr = __bswap_32(ip); - LOG_WARN("can not pass white_list", K(cluster_name), K(tenant_name), K(user_name), "client_ip", inet_ntoa(address.sin_addr)); + LOG_WARN("can not pass white_list", K(cluster_name), K(tenant_name), K(user_name), K(endpoint)); } return can_pass; @@ -303,10 +360,8 @@ bool ObWhiteListTableProcessor::can_ip_pass(ObString &cluster_name, ObString &te int64_t AddrStruct::to_string(char *buf, const int64_t buf_len) const { int64_t pos = 0; - in_addr addr; - addr.s_addr = static_cast(ip_); J_OBJ_START(); - J_KV("ip", inet_ntoa(addr), K_(net)); + J_KV(K_(addr), K_(net)); J_OBJ_END(); return pos; } @@ -336,6 +391,12 @@ void ObWhiteListTableProcessor::inc_index() index_ = (index_ + 1) % 2; } +void ObWhiteListTableProcessor::clean_hashmap(WhiteListHashMap& whitelist_map) +{ + DRWLock::WRLockGuard guard(white_list_lock_); + whitelist_map.reuse(); +} + void ObWhiteListTableProcessor::print_config() { DRWLock::RDLockGuard guard(white_list_lock_); @@ -345,9 +406,7 @@ void ObWhiteListTableProcessor::print_config() LOG_DEBUG("white list map info", K(iter->first)); for (int64_t i = 0; i < iter->second.count(); i++) { AddrStruct addr_info = iter->second.at(i); - struct sockaddr_in address; - address.sin_addr.s_addr = __bswap_32(addr_info.ip_); - LOG_DEBUG("ip/net info", "ip", inet_ntoa(address.sin_addr), "mask", addr_info.net_); + LOG_DEBUG("ip/net info", K(addr_info)); } } } diff --git a/src/obproxy/omt/ob_white_list_table_processor.h b/src/obproxy/omt/ob_white_list_table_processor.h index d1260e1a95b231c652911394e383a672f07f32ed..cbfc2d6fb07ba0bfc7b2aacd845b604ad9f40a1f 100644 --- a/src/obproxy/omt/ob_white_list_table_processor.h +++ b/src/obproxy/omt/ob_white_list_table_processor.h @@ -35,6 +35,7 @@ #include "lib/container/ob_se_array.h" #include "lib/lock/ob_drw_lock.h" #include "utils/ob_proxy_lib.h" +#include "lib/net/ob_addr.h" namespace oceanbase { @@ -45,7 +46,8 @@ namespace omt struct AddrStruct { - uint32_t ip_; + common::ObAddr addr_; + uint32_t v4_; uint32_t net_; int64_t to_string(char *buf, const int64_t buf_len) const; @@ -53,35 +55,40 @@ struct AddrStruct class ObWhiteListTableProcessor { +typedef common::hash::ObHashMap, common::ObSEArray > WhiteListHashMap; public: ObWhiteListTableProcessor() : index_(0), white_list_lock_(obsys::WRITE_PRIORITY) {} ~ObWhiteListTableProcessor() {} int init(); bool can_ip_pass(common::ObString &cluster_name, common::ObString &tenant_name, - common::ObString &user_name, uint32_t src_ip, bool is_big_endian); - bool can_ip_pass(common::ObString &cluster_name, common::ObString &tenant_name, common::ObString &user_name, char *ip); + common::ObString &user_name, const struct sockaddr& addr); int set_ip_list(common::ObString &cluster_name, common::ObString &tenant_name, common::ObString &ip_list); int delete_ip_list(common::ObString &cluster_name, common::ObString &tenant_name); void inc_index(); void print_config(); + WhiteListHashMap& get_backup_hashmap() { return addr_hash_map_array_[(index_ + 1) % 2]; } + void clean_hashmap(WhiteListHashMap& whitelist_map); private: int32_t ip_to_int(char *addr, uint32_t &value); int backup_hash_map(); uint32_t to_little_endian(uint32_t value); + bool can_ipv4_pass(common::ObString &cluster_name, common::ObString &tenant_name, + common::ObString &user_name, const struct sockaddr& in_addr); + bool can_ipv6_pass(common::ObString &cluster_name, common::ObString &tenant_name, + common::ObString &user_name, const struct sockaddr& in6_addr); private: static int execute(void *arg); - static int commit(bool is_success); + static int commit(void* arg, bool is_success); private: - typedef common::hash::ObHashMap, common::ObSEArray > WhiteListHashMap; WhiteListHashMap addr_hash_map_array_[2]; int64_t index_; private: common::DRWLock white_list_lock_; }; -ObWhiteListTableProcessor &get_global_white_list_table_processor(); +extern ObWhiteListTableProcessor &get_global_white_list_table_processor(); } // end of omt } // end of obproxy diff --git a/src/obproxy/opsql/Makemodule.am b/src/obproxy/opsql/Makemodule.am index 10a3edb8c133b6e0081a43ba012a1b3d2cf9b0c0..8dfabedb7707bcc70a6c64b7a64a65d28b260129 100644 --- a/src/obproxy/opsql/Makemodule.am +++ b/src/obproxy/opsql/Makemodule.am @@ -10,8 +10,15 @@ obproxy/opsql/parser/ob_proxy_parser_utf8_lex.h\ obproxy/opsql/parser/ob_proxy_parser_utf8_tab.c\ obproxy/opsql/parser/ob_proxy_parser_utf8_tab.h +opsql_parser_gbk_sources:=\ +obproxy/opsql/parser/ob_proxy_parser_gbk_lex.c\ +obproxy/opsql/parser/ob_proxy_parser_gbk_lex.h\ +obproxy/opsql/parser/ob_proxy_parser_gbk_tab.c\ +obproxy/opsql/parser/ob_proxy_parser_gbk_tab.h + opsql_parser_sources:=\ ${opsql_parser_utf8_sources}\ +${opsql_parser_gbk_sources}\ obproxy/opsql/parser/ob_proxy_parse_result.h\ obproxy/opsql/parser/ob_proxy_parse_result.cpp\ obproxy/opsql/parser/ob_proxy_parser.h @@ -26,8 +33,15 @@ obproxy/opsql/expr_parser/ob_expr_parser_utf8_lex.h\ obproxy/opsql/expr_parser/ob_expr_parser_utf8_tab.c\ obproxy/opsql/expr_parser/ob_expr_parser_utf8_tab.h +opsql_expr_gbk_parser_sources:=\ +obproxy/opsql/expr_parser/ob_expr_parser_gbk_lex.c\ +obproxy/opsql/expr_parser/ob_expr_parser_gbk_lex.h\ +obproxy/opsql/expr_parser/ob_expr_parser_gbk_tab.c\ +obproxy/opsql/expr_parser/ob_expr_parser_gbk_tab.h + opsql_expr_parser_sources:=\ ${opsql_expr_utf8_parser_sources}\ +${opsql_expr_gbk_parser_sources}\ obproxy/opsql/expr_parser/ob_expr_parse_result.h\ obproxy/opsql/expr_parser/ob_expr_parse_result.cpp\ obproxy/opsql/expr_parser/ob_expr_parser_utils.h\ diff --git a/src/obproxy/opsql/dual_parser/ob_dual_parser.cpp b/src/obproxy/opsql/dual_parser/ob_dual_parser.cpp index 6fe7f4096c3570df37ad74a68bfe9196239acf6e..57b6a9744369ada8f51a615f06bc0ee03f0dabe2 100644 --- a/src/obproxy/opsql/dual_parser/ob_dual_parser.cpp +++ b/src/obproxy/opsql/dual_parser/ob_dual_parser.cpp @@ -394,7 +394,6 @@ int ObProxyDualParser::parse_where_fields(ObCollationType connection_collation) } ObExprParseMode parse_mode = SELECT_STMT_PARSE_MODE; ObExprParseResult& expr_result = result_->expr_result_; - expr_result.target_mask_ = FIRST_PART_MASK; // set for init success if (OB_FAIL(ObProxySqlParser::get_parse_allocator(allocator_))) { } else if (OB_ISNULL(allocator_)) { ret = OB_ERR_UNEXPECTED; diff --git a/src/obproxy/opsql/expr_parser/gen_parser.sh b/src/obproxy/opsql/expr_parser/gen_parser.sh index 6727bc42bf7a96e87b6868db4e9a43f8522b7fec..8453c1514363546de646909464f7bfa02b5707e3 100755 --- a/src/obproxy/opsql/expr_parser/gen_parser.sh +++ b/src/obproxy/opsql/expr_parser/gen_parser.sh @@ -107,3 +107,105 @@ sed "/Setup the input buffer state to scan the given bytes/,/}/{s/\tbuf\[i\] = y rm -f ob_expr_parser_utf8.l rm -f ob_expr_parser_utf8.y rm -f ob_expr_parser_utf8.output + + +# generate oracle gbk expr_parser(support multi_byte_space, multi_byte_commai, multi_byte_left_parenthesis, multi_byte_right_parenthesis) +##1.copy lex and yacc files +cat ob_expr_parser.y > ob_expr_parser_gbk.y +cat ob_expr_parser.l > ob_expr_parser_gbk.l +##2.replace name +sed "s/ob_expr_parser_yy/ob_expr_parser_gbk_yy/g" -i ob_expr_parser_gbk.y +sed "s/ob_expr_parser_yy/ob_expr_parser_gbk_yy/g" -i ob_expr_parser_gbk.l +sed "s/ob_expr_parser_lex/ob_expr_parser_gbk_lex/g" -i ob_expr_parser_gbk.y +sed "s/ob_expr_parser_lex/ob_expr_parser_gbk_lex/g" -i ob_expr_parser_gbk.l +sed "s/ob_expr_parser_tab/ob_expr_parser_gbk_tab/g" -i ob_expr_parser_gbk.l +sed "s/ob_expr_parser_fatal_error/ob_expr_gbk_parser_fatal_error/g" -i ob_expr_parser_gbk.y +sed "s/ob_expr_parser_fatal_error/ob_expr_gbk_parser_fatal_error/g" -i ob_expr_parser_gbk.l +sed "s/ob_expr_parse_sql/ob_expr_parse_gbk_sql/g" -i ob_expr_parser_gbk.y +##3.add multi_byte_space, multi_byte_comma, multi_byte_left_parenthesis, multi_byte_right_parenthesis code. +sed "s/multi_byte_space \[\\\u3000\]/multi_byte_space ([\\\xa1][\\\xa1])/g" -i ob_expr_parser_gbk.l +sed "s/multi_byte_comma \[\\\uff0c\]/multi_byte_comma ([\\\xa3][\\\xac])/g" -i ob_expr_parser_gbk.l +sed "s/multi_byte_left_parenthesis \[\\\uff08\]/multi_byte_left_parenthesis ([\\\xa3][\\\xa8])/g" -i ob_expr_parser_gbk.l +sed "s/multi_byte_right_parenthesis \[\\\uff09\]/multi_byte_right_parenthesis ([\\\xa3][\\\xa9])/g" -i ob_expr_parser_gbk.l +sed 's/space \[ \\t\\n\\r\\f\]/space (\[ \\t\\n\\r\\f\]|{multi_byte_space})/g' -i ob_expr_parser_gbk.l +##4.generate oracle gbk parser files + +# run bison +#bison -p obexpr -v -Werror -d ob_expr_parser.y -o ob_expr_parser_tab.c +bison -v -Werror -d ob_expr_parser_gbk.y -o ob_expr_parser_gbk_tab.c +if [ $? -ne 0 ] +then + echo Compile error[$?], abort. + exit 1 +fi + +# format tab.h +sed "s/YY\([a-zA-Z_]*\)/OBEXPR\1/g" -i ob_expr_parser_gbk_tab.h +sed "s/yy\([a-zA-Z_]*\)/obexpr\1/g" -i ob_expr_parser_gbk_tab.h +sed "/Tokens/i #ifndef YY_OBEXPR_OB_EXPR_PARSER_TAB_H_INCLUDED\n\ +# define YY_OBEXPR_OB_EXPR_PARSER_TAB_H_INCLUDED\n\ +/* Debug traces. */\n\ +#ifndef OBEXPR_UTF8_DEBUG\n\ +# if defined YYDEBUG\n\ +#if YYDEBUG\n\ +# define OBEXPR_UTF8_DEBUG 1\n\ +# else\n\ +# define OBEXPR_UTF8_DEBUG 0\n\ +# endif\n\ +# else /* ! defined YYDEBUG */\n\ +# define OBEXPR_UTF8_DEBUG 0\n\ +# endif /* ! defined YYDEBUG */\n\ +#endif /* ! defined OBEXPR_UTF8_DEBUG */\n\ +#if OBEXPR_UTF8_DEBUG\n\ +extern int ob_expr_parser_gbk_yydebug;\n\ +#endif" -i ob_expr_parser_gbk_tab.h +echo "#endif" >> ob_expr_parser_gbk_tab.h + +# formart tab.c +sed "/#define yyparse/i #define YYSTYPE OBEXPRSTYPE\n#define YYLTYPE OBEXPRLTYPE" -i ob_expr_parser_gbk_tab.c +sed "/Tokens/,/Copy the second/{s/YY\([a-zA-Z_]\)/OBEXPR\1/g}" -i ob_expr_parser_gbk_tab.c +sed "/Tokens/,/Copy the second/{s/yy\([a-zA-Z_]\)/obexpr\1/g}" -i ob_expr_parser_gbk_tab.c +sed "s/yylex (\&yylval, \&yylloc)/yylex (\&yylval, \&yylloc, YYLEX_PARAM)/g" -i ob_expr_parser_gbk_tab.c +sed "/Tokens/i #ifndef YY_OBEXPR_OB_EXPR_PARSER_TAB_H_INCLUDED\n\ +# define YY_OBEXPR_OB_EXPR_PARSER_TAB_H_INCLUDED\n\ +/* Debug traces. */\n\ +#ifndef OBEXPR_UTF8_DEBUG\n\ +# if defined YYDEBUG\n\ +#if YYDEBUG\n\ +# define OBEXPR_UTF8_DEBUG 1\n\ +# else\n\ +# define OBEXPR_UTF8_DEBUG 0\n\ +# endif\n\ +# else /* ! defined YYDEBUG */\n\ +# define OBEXPR_UTF8_DEBUG 0\n\ +# endif /* ! defined YYDEBUG */\n\ +#endif /* ! defined OBEXPR_UTF8_DEBUG */\n\ +#if OBEXPR_UTF8_DEBUG\n\ +extern int ob_expr_parser_gbk_yydebug;\n\ +#endif" -i ob_expr_parser_gbk_tab.c +sed "/Copy the second/i #endif" -i ob_expr_parser_gbk_tab.c +sed "/Cause a token to be read/a \ +\ \ if (SELECT_STMT_PARSE_MODE == result->parse_mode_) {\n\ + yychar = DUMMY_SELECT_CLAUSE;\n\ + } else if (INSERT_STMT_PARSE_MODE == result->parse_mode_) {\n\ + yychar = DUMMY_INSERT_CLAUSE;\n\ + }\n\ +" -i ob_expr_parser_gbk_tab.c + +# run flex +#flex -P obexpr -Cfea -o ob_expr_parser_lex.c ob_expr_parser.l ob_expr_parser_tab.h +flex -o ob_expr_parser_gbk_lex.c ob_expr_parser_gbk.l ob_expr_parser_gbk_tab.h + +# format lex.h +sed "s/YYSTYPE/OBEXPRSTYPE/g" -i ob_expr_parser_gbk_lex.h +sed "s/YYLTYPE/OBEXPRLTYPE/g" -i ob_expr_parser_gbk_lex.h +sed "/static int yy_top_state (yyscan_t yyscanner );/d" -i ob_expr_parser_gbk_lex.c +sed "/static int yy_top_state/,/\}/d" -i ob_expr_parser_gbk_lex.c +sed "/\*yy_cp = '\\\0';/d" -i ob_expr_parser_gbk_lex.c +sed "/Setup the input buffer state to scan the given bytes/,/}/{/int i/d}" -i ob_expr_parser_gbk_lex.c +sed "/Setup the input buffer state to scan the given bytes/,/}/{/for ( i = 0; i < _yybytes_len; ++i )/d}" -i ob_expr_parser_gbk_lex.c +sed "/Setup the input buffer state to scan the given bytes/,/}/{s/\tbuf\[i\] = yybytes\[i\]/memcpy(buf, yybytes, _yybytes_len)/g}" -i ob_expr_parser_gbk_lex.c +##5.clean useless files +rm -f ob_expr_parser_gbk.l +rm -f ob_expr_parser_gbk.y +rm -f ob_expr_parser_gbk.output diff --git a/src/obproxy/opsql/expr_parser/ob_expr_parse_result.h b/src/obproxy/opsql/expr_parser/ob_expr_parse_result.h index 92656067b8071b7db842b9eb3b3bc3e73f8b8489..4dfee39df81b24ca24ad94e301972dd61dd1bfc4 100644 --- a/src/obproxy/opsql/expr_parser/ob_expr_parse_result.h +++ b/src/obproxy/opsql/expr_parser/ob_expr_parse_result.h @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include "opsql/ob_proxy_parse_type.h" #include "opsql/func_expr_parser/ob_func_expr_parse_result.h" @@ -122,9 +124,18 @@ typedef struct _ObProxyTokenList ObProxyTokenNode *tail_; } ObProxyTokenList; +/** + * @brief If level_ == PART_KEY_LEVEL_ONE, first_part_column_idx_ will be set. + * If level_ == PART_KEY_LEVEL_TWO, second_part_column_idx_ will be set. + * If level_ == PART_KEY_LEVEL_BOTH, both of them will be set. + * first_part_column_idx_: the column's idx in partition expression + * second_part_column_idx_: the column's idx in subpartition expression + */ typedef struct _ObProxyRelationExpr { int64_t column_idx_; + int64_t first_part_column_idx_; + int64_t second_part_column_idx_; ObProxyTokenList *left_value_; ObProxyTokenList *right_value_; ObProxyFunctionType type_; @@ -148,17 +159,21 @@ typedef struct _ObProxyPartKeyAccuracy { typedef struct _ObProxyPartKey { ObProxyParseString name_; + ObProxyParseString default_value_; // serialized value ObProxyPartKeyLevel level_; - int64_t idx_; // column position + int64_t idx_; // pos in schema columns int64_t obj_type_; // ObObjType int64_t cs_type_; // ObCollationType + bool is_exist_in_sql_; // is part key exist in sql bool is_generated_; int64_t generated_col_idx_; int64_t param_num_; ObProxyExprType func_type_; ObProxyParamNode *params_[OBPROXY_MAX_PARAM_NUM]; // used to store generated func param - int64_t idx_in_rowid_; + int64_t real_source_idx_; // the real source idx of generated key, have no params_ + int64_t idx_in_rowid_; // pos in rowid + int64_t idx_in_part_columns_; // pos in part expr columns ObProxyPartKeyAccuracy accuracy_; } ObProxyPartKey; @@ -183,7 +198,6 @@ typedef struct _ObExprParseResult ObExprParseMode parse_mode_; ObProxyTableInfo table_info_; ObProxyPartKeyInfo part_key_info_; - int64_t target_mask_; // scanner buffer void *yyscan_info_; // yy_scan_t @@ -193,7 +207,6 @@ typedef struct _ObExprParseResult jmp_buf jmp_buf_; // handle fatal error const char *start_pos_; const char *end_pos_; - int64_t cur_mask_; // if cur_flag_ == target_flag_ means we will finish parse int64_t column_idx_; int64_t values_list_idx_; int64_t multi_param_values_; @@ -203,11 +216,23 @@ typedef struct _ObExprParseResult // result argument ObProxyRelationInfo relation_info_; ObProxyRelationInfo all_relation_info_; - // oracle rowid + + // hash rowid or not bool has_rowid_; - ObProxyParseString rowid_str_; } ObExprParseResult; +static const char *g_ROWID = "ROWID"; +static inline bool is_equal_to_rowid(ObProxyParseString *str) +{ + bool bret = false; + if (str == NULL || str->str_ == NULL || str->str_len_ != 5) { + // ret + } else { + bret = (strncasecmp(str->str_, g_ROWID, 5) == 0) ? true : false; + } + return bret; +} + #ifdef __cplusplus extern "C" const char* get_expr_parse_mode(const ObExprParseMode mode); extern "C" const char* get_obproxy_function_type(const ObProxyFunctionType type); diff --git a/src/obproxy/opsql/expr_parser/ob_expr_parser.h b/src/obproxy/opsql/expr_parser/ob_expr_parser.h index aa6ba7882bce8c4b06a012caa59afa6d79c912a8..e39db222816cbfe3fa6dc5dd0cea3168165bcce3 100644 --- a/src/obproxy/opsql/expr_parser/ob_expr_parser.h +++ b/src/obproxy/opsql/expr_parser/ob_expr_parser.h @@ -20,6 +20,7 @@ #include "lib/string/ob_string.h" extern "C" int ob_expr_parse_utf8_sql(ObExprParseResult *p, const char *pszSql, size_t iLen); +extern "C" int ob_expr_parse_gbk_sql(ObExprParseResult *p, const char *pszSql, size_t iLen); namespace oceanbase { @@ -32,6 +33,7 @@ namespace obproxy { namespace opsql { + class ObExprParser { public: @@ -74,7 +76,6 @@ inline int ObExprParser::init_result(ObExprParseResult &parse_result, const char parse_result.tmp_buf_ = NULL; parse_result.tmp_len_ = 0; parse_result.end_pos_ = NULL; - parse_result.cur_mask_ = 0; parse_result.column_idx_ = 0; parse_result.values_list_idx_ = 0; parse_result.multi_param_values_ = 0; @@ -85,12 +86,13 @@ inline int ObExprParser::init_result(ObExprParseResult &parse_result, const char parse_result.relation_info_.relation_num_ = 0; parse_result.all_relation_info_.relation_num_ = 0; parse_result.all_relation_info_.right_value_num_ = 0; + for (int64_t i = 0; i < parse_result.part_key_info_.key_num_; ++i) { + parse_result.part_key_info_.part_keys_[i].is_exist_in_sql_ = false; + } - if (0 == parse_result.target_mask_ - || INVALID_PARSE_MODE == parse_result.parse_mode_) { + if (INVALID_PARSE_MODE == parse_result.parse_mode_) { ret = common::OB_INVALID_ARGUMENT; PROXY_LOG(DEBUG, "failed to initialized parser, maybe parse sql for shard user", - K(parse_result.target_mask_), K(parse_result.parse_mode_), K(ret)); } @@ -112,6 +114,17 @@ inline int ObExprParser::parse(const common::ObString &sql_string, PROXY_LOG(WARN, "failed to initialized parser", KERRMSGS, K(ret)); } else { switch (connection_collation) { + //case 28/*CS_TYPE_GBK_CHINESE_CI*/: + //case 87/*CS_TYPE_GBK_BIN*/: + case 248/*CS_TYPE_GB18030_CHINESE_CI*/: + case 249/*CS_TYPE_GB18030_BIN*/: + if (common::OB_SUCCESS != ob_expr_parse_gbk_sql(&parse_result, + sql_string.ptr(), + static_cast(sql_string.length()))) { + ret = common::OB_ERR_PARSE_SQL; + PROXY_LOG(WARN, "failed to parser gbk sql", KERRMSGS, K(connection_collation), K(ret)); + } + break; case 45/*CS_TYPE_UTF8MB4_GENERAL_CI*/: case 46/*CS_TYPE_UTF8MB4_BIN*/: default: @@ -135,6 +148,8 @@ inline int ObExprParser::parse_reqsql(const common::ObString &req_sql, int64_t p common::ObString expr_sql = obproxy::proxy::ObProxyMysqlRequest::get_expr_sql(req_sql, parsed_length); const char *expr_sql_str = expr_sql.ptr(); const char *pos = NULL; + char* replace_sql_str = NULL; + int replace_sql_len = 0; if (OB_LIKELY(NULL != expr_sql_str)) { if (SELECT_STMT_PARSE_MODE == parse_mode_) { if (NULL != (pos = strcasestr(expr_sql_str, "JOIN"))) { @@ -159,11 +174,45 @@ inline int ObExprParser::parse_reqsql(const common::ObString &req_sql, int64_t p if (NULL != pos) { expr_sql += static_cast(pos - expr_sql_str); } + + if (OBPROXY_T_TEXT_PS_PREPARE == stmt_type || OBPROXY_T_TEXT_PS_EXECUTE == stmt_type) { + int i, j, index = 0; + replace_sql_len = expr_sql.length(); + if (OB_ISNULL(replace_sql_str = static_cast(op_fixed_mem_alloc(replace_sql_len)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + PROXY_LOG(WARN, "fail to alloc mem", "alloc_size", replace_sql_len, K(ret)); + } else { + // PREPARE ps_stmt FROM 'select * from test9 where ID = \\'001\\''; remove escape symbols + for (i = 0; i < expr_sql.length() - 1; ++i) { + if (expr_sql[i] == 0x5c && (expr_sql[i+1] == 0x27 || expr_sql[i+1] == 0x22)) { + // do nothing + } else { + replace_sql_str[index++] = expr_sql[i]; + } + } + replace_sql_str[index++] = expr_sql[i]; + + // PREPARE ps_stmt FROM 'select * from test9 where ID = \\'001\\''; remove trailing single quotes + if (replace_sql_str[index-3] == 0x27 || replace_sql_str[index-3] == 0x22) { + for (j = index - 3; j < index - 1; ++j) { + replace_sql_str[j] = replace_sql_str[j+1]; + } + index -= 1; + } + PROXY_LOG(DEBUG, "parse length", K(index), K(replace_sql_len), K(replace_sql_str)); + expr_sql.assign_ptr(replace_sql_str, index); + } + } } - if (OB_FAIL(parse(expr_sql, expr_result, connection_collation))) { - PROXY_LOG(DEBUG, "fail to do expr parse", K(expr_sql), K(ret)); - } else { - PROXY_LOG(DEBUG, "succ to do expr parse", "expr_result", ObExprParseResultPrintWrapper(expr_result), K(expr_sql)); + if (OB_SUCC(ret)) { + if (OB_FAIL(parse(expr_sql, expr_result, connection_collation))) { + PROXY_LOG(DEBUG, "fail to do expr parse", K(expr_sql), K(ret)); + } else { + PROXY_LOG(DEBUG, "succ to do expr parse", "expr_result", ObExprParseResultPrintWrapper(expr_result), K(expr_sql)); + } + } + if (NULL != replace_sql_str) { + op_fixed_mem_free(replace_sql_str, replace_sql_len); } return ret; } diff --git a/src/obproxy/opsql/expr_parser/ob_expr_parser.l b/src/obproxy/opsql/expr_parser/ob_expr_parser.l index eccb3bcd030c4eabd1875d7dccc0193072c48f4f..ff498367b159fcd33bd2344e48e91bfb792b3ffe 100644 --- a/src/obproxy/opsql/expr_parser/ob_expr_parser.l +++ b/src/obproxy/opsql/expr_parser/ob_expr_parser.l @@ -43,6 +43,12 @@ do {\ #define RETURN_NAME_OB() \ { store_expr_str(yytext, yyleng, yytext + yyleng, yyscanner); return NAME_OB; } +#define RETURN_ROW_ID() \ + { store_expr_str(yytext, yyleng, yytext + yyleng, yyscanner); return ROW_ID; } + +#define RETURN_REVERSED_EXPR_FUNC() \ + { store_expr_str(yytext, yyleng, yytext + yyleng, yyscanner); return REVERSED_EXPR_FUNC; } + %} %x in_c_comment @@ -57,8 +63,10 @@ multi_byte_left_parenthesis [\uff08] multi_byte_right_parenthesis [\uff09] space [ \t\n\r\f] identifer ([A-Za-z0-9$_]*) -int_num [\-\+]?[0-9]+ -number ([\-]?[0-9]+E[-+]?[0-9]+)|([\-]?[0-9]+"."[0-9]*E[-+]?[0-9]+)|([\-]?"."[0-9]+E[-+]?[0-9]+)|([\-]?[0-9]+"."[0-9]*)|([\-]?"."[0-9]+) + +/* limit the length of int_num from 1 to 17 in case of int64_t out of bound, 17 -> [ ( length of 2^64 ) - 2 ]*/ +int_num [\-\+]?[0-9]{1,17} +number ([\-]?[0-9]+E[-+]?[0-9]+)|([\-]?[0-9]+"."[0-9]*E[-+]?[0-9]+)|([\-]?"."[0-9]+E[-+]?[0-9]+)|([\-]?[0-9]+"."[0-9]*)|([\-]?"."[0-9]+)|([\-\+]?[0-9]{18,}) non_newline [^\n\r] sql_comment ("--"{space}+{non_newline}*)|(#{non_newline}*) @@ -101,7 +109,7 @@ FOR { return END_WHERE; } LIMIT { return END_WHERE; } GROUP { return END_WHERE; } HAVING { return END_WHERE; } -ROWID { return ROWID; } +ROWID { RETURN_ROW_ID(); } JOIN { return JOIN; } ON { return ON; } @@ -111,6 +119,9 @@ AND { return AND_OP; } OR { return OR_OP; } "||" { return OR_OP; } IN { return IN; } +IS { return IS; } +NULL { return TOKEN_NULL; } +NOT { return NOT; } "=" { return COMP_EQ; } "<=>" { return COMP_NSEQ; } ">=" { return COMP_GE; } @@ -120,6 +131,7 @@ IN { return IN; } "!="|"<>" { return COMP_NE; } "?" { return PLACE_HOLDER; } ":"{int_num} { store_pos_place_holder(yytext + 1, yyscanner); return POS_PLACE_HOLDER; } +"SYSDATE" { RETURN_REVERSED_EXPR_FUNC();} {int_num} { RETURN_INT_VAL(); } {number} { RETURN_NUMBER_VAL(); } diff --git a/src/obproxy/opsql/expr_parser/ob_expr_parser.y b/src/obproxy/opsql/expr_parser/ob_expr_parser.y index 2bf5701be7bb1e715f74dd45c68a006a07debe66..e190314c84ada488c4e09a0298e75985f3f86362 100644 --- a/src/obproxy/opsql/expr_parser/ob_expr_parser.y +++ b/src/obproxy/opsql/expr_parser/ob_expr_parser.y @@ -55,8 +55,8 @@ static inline void add_token_list(ObProxyTokenList *list, ObProxyTokenList *next if (OB_ISNULL(list) || OB_ISNULL(next_list)) { } else if (NULL != list->tail_ && NULL != next_list->head_ - && (TOKEN_INT_VAL == list->tail_->type_ || TOKEN_STR_VAL == list->tail_->type_) - && (TOKEN_INT_VAL == next_list->head_->type_ || TOKEN_STR_VAL == next_list->head_->type_)) { + && (TOKEN_INT_VAL == list->tail_->type_ || TOKEN_STR_VAL == list->tail_->type_ || TOKEN_FUNC == list->tail_->type_) + && (TOKEN_INT_VAL == next_list->head_->type_ || TOKEN_STR_VAL == next_list->head_->type_ || TOKEN_FUNC == next_list->head_->type_)) { list->tail_->next_ = next_list->head_; list->tail_ = next_list->head_; list->tail_->next_ = NULL; @@ -128,11 +128,18 @@ static inline void set_part_key_column_idx(ObExprParseResult *result, ObProxyPar for (i = 0; i < result->part_key_info_.key_num_; ++i) { if (is_equal(column_name, &result->part_key_info_.part_keys_[i].name_)) { result->part_key_info_.part_keys_[i].idx_ = result->column_idx_; - break; + result->part_key_info_.part_keys_[i].is_exist_in_sql_ = true; } } } +static inline void init_part_key_all_match(ObExprParseResult *result) +{ + for (int64_t i = 0; i < result->part_key_info_.key_num_; ++i) { + result->part_key_info_.part_keys_[i].is_exist_in_sql_ = true; + } +} + #define malloc_node(node, result, type) \ do { \ if (OB_ISNULL(node = ((ObProxyTokenNode *)obproxy_parse_malloc(sizeof(ObProxyTokenNode), \ @@ -167,18 +174,13 @@ static inline void set_part_key_column_idx(ObExprParseResult *result, ObProxyPar do { \ if (NULL == relation) { \ } else { \ - int64_t new_mask = get_mask(relation->type_, relation->level_); \ - if ((result->cur_mask_ | new_mask) != result->cur_mask_) { \ + if (relation->level_ != PART_KEY_LEVEL_ZERO) { \ if (result->relation_info_.relation_num_ < OBPROXY_MAX_RELATION_NUM) { \ result->relation_info_.relations_[result->relation_info_.relation_num_++] = relation; \ - result->cur_mask_ = (result->cur_mask_ | new_mask); \ } else { \ /* YYACCEPT; */ \ } \ } \ - if ((result->cur_mask_ & result->target_mask_) == result->target_mask_) { \ - /* YYACCEPT; */ \ - } \ } \ } while(0) \ @@ -188,6 +190,7 @@ static int64_t get_part_key_idx(ObProxyParseString *db_name, ObExprParseResult *result) { int64_t part_key_idx = IDX_NO_PART_KEY_COLUMN; + if (result->part_key_info_.key_num_ > 0) { if (NULL != db_name && !is_equal(db_name, &result->table_info_.database_name_)) { part_key_idx = IDX_NO_PART_KEY_COLUMN; @@ -208,9 +211,9 @@ static int64_t get_part_key_idx(ObProxyParseString *db_name, return part_key_idx; } static inline void add_relation(ObExprParseResult *result, - ObProxyTokenList *left_value, - ObProxyFunctionType type, - ObProxyTokenList *right_value) + ObProxyTokenList *left_value, + ObProxyFunctionType type, + ObProxyTokenList *right_value) { if (result->all_relation_info_.relation_num_ < OBPROXY_MAX_RELATION_NUM) { ObProxyRelationExpr *relation = NULL; @@ -247,6 +250,92 @@ static inline void add_relation(ObExprParseResult *result, } } +static inline void set_relation_part_with_column_idx(int64_t idx_in_schema_columns, + ObExprParseResult *result, + ObProxyPartKeyLevel *level, + int64_t *first_part_column_idx, + int64_t *second_part_column_idx) +{ + if (OB_ISNULL(level) && OB_ISNULL(first_part_column_idx) && + OB_ISNULL(second_part_column_idx) && OB_ISNULL(result)) { + // do nothing + } else { + *level = PART_KEY_LEVEL_ZERO; + *first_part_column_idx = 0; + *second_part_column_idx = 0; + bool is_level_one = false; + bool is_level_two = false; + for (int i = 0; i < result->part_key_info_.key_num_; i++) { + // make sure the part_key exist in sql to avoid the uninitialized idx_ + if (idx_in_schema_columns == result->part_key_info_.part_keys_[i].idx_ && result->part_key_info_.part_keys_[i].is_exist_in_sql_) { + if (result->part_key_info_.part_keys_[i].level_ == PART_KEY_LEVEL_ONE) { + is_level_one = true; + *first_part_column_idx = result->part_key_info_.part_keys_[i].idx_in_part_columns_; + } else if (result->part_key_info_.part_keys_[i].level_ == PART_KEY_LEVEL_TWO) { + is_level_two = true; + *second_part_column_idx = result->part_key_info_.part_keys_[i].idx_in_part_columns_; + } + } + } + if (is_level_one) { + *level = PART_KEY_LEVEL_ONE; + } + if (is_level_two) { + *level = PART_KEY_LEVEL_TWO; + } + if (is_level_one && is_level_two) { + *level = PART_KEY_LEVEL_BOTH; + } + } +} + +static inline void set_relation_part_with_column_name(ObProxyParseString *column, + ObExprParseResult *result, + ObProxyPartKeyLevel *level, + int64_t *first_part_column_idx, + int64_t *second_part_column_idx) +{ + if (OB_ISNULL(column) + || OB_ISNULL(result) + || OB_ISNULL(level) + || OB_ISNULL(first_part_column_idx) + || OB_ISNULL(second_part_column_idx)) { + // do nothing + } else if (result->has_rowid_ + && is_equal_to_rowid(column)) { + // handle rowid + *level = PART_KEY_LEVEL_ONE; + *first_part_column_idx = 0; + *second_part_column_idx = 0; + } else { + *level = PART_KEY_LEVEL_ZERO; + *first_part_column_idx = 0; + *second_part_column_idx = 0; + bool is_level_one = false; + bool is_level_two = false; + for (int i = 0; i < result->part_key_info_.key_num_; i++) { + if (is_equal(&result->part_key_info_.part_keys_[i].name_, column)) { + if (result->part_key_info_.part_keys_[i].level_ == PART_KEY_LEVEL_ONE) { + is_level_one = true; + *first_part_column_idx = result->part_key_info_.part_keys_[i].idx_in_part_columns_; + } else if (result->part_key_info_.part_keys_[i].level_ == PART_KEY_LEVEL_TWO) { + is_level_two = true; + *second_part_column_idx = result->part_key_info_.part_keys_[i].idx_in_part_columns_; + } + } + } + if (is_level_one) { + *level = PART_KEY_LEVEL_ONE; + } + if (is_level_two) { + *level = PART_KEY_LEVEL_TWO; + } + if (is_level_one && is_level_two) { + *level = PART_KEY_LEVEL_BOTH; + } + } +} + static inline ObProxyRelationExpr *get_relation(ObExprParseResult *result, ObProxyTokenList *left_value, @@ -257,25 +346,25 @@ static inline ObProxyRelationExpr *get_relation(ObExprParseResult *result, ObProxyTokenList *tmp_left = NULL; ObProxyTokenList *tmp_right = NULL; ObProxyFunctionType tmp_type = F_NONE; - ObProxyPartKeyLevel tmp_level = PART_KEY_LEVEL_ZERO; int64_t tmp_column_idx_ = -1; + ObProxyParseString *tmp_column = NULL; if (NULL != left_value->column_node_ && TOKEN_COLUMN == left_value->column_node_->type_ && left_value->column_node_->part_key_idx_ >= 0) { tmp_left = left_value; - tmp_level = result->part_key_info_.part_keys_[left_value->column_node_->part_key_idx_].level_; tmp_right = right_value; tmp_type = type; tmp_column_idx_ = left_value->column_node_->part_key_idx_; + tmp_column = &left_value->column_node_->column_name_; } else if (NULL != right_value->column_node_ && TOKEN_COLUMN == right_value->column_node_->type_ && right_value->column_node_->part_key_idx_ >= 0) { tmp_left = right_value; - tmp_level = result->part_key_info_.part_keys_[right_value->column_node_->part_key_idx_].level_; tmp_right = left_value; tmp_type = get_reverse_func(type); tmp_column_idx_ = right_value->column_node_->part_key_idx_; + tmp_column = &right_value->column_node_->column_name_; } if (NULL == tmp_left || NULL == tmp_right || F_COMP_NE == tmp_type) { @@ -288,7 +377,11 @@ static inline ObProxyRelationExpr *get_relation(ObExprParseResult *result, relation->left_value_ = tmp_left; relation->type_ = tmp_type; relation->right_value_ = tmp_right; - relation->level_ = tmp_level; + set_relation_part_with_column_name(tmp_column, + result, + &relation->level_, + &relation->first_part_column_idx_, + &relation->second_part_column_idx_); } return relation; } @@ -302,14 +395,20 @@ static inline ObProxyRelationExpr *get_values_relation(ObExprParseResult *result } else { int64_t i = 0; for (i = 0; i < result->part_key_info_.key_num_; ++i) { - if (result->values_list_idx_ == result->part_key_info_.part_keys_[i].idx_) { + // make sure the part_key exist in sql to avoid the uninitialized idx_ + if (result->values_list_idx_ == result->part_key_info_.part_keys_[i].idx_ && result->part_key_info_.part_keys_[i].is_exist_in_sql_) { if (OB_ISNULL(relation = ((ObProxyRelationExpr *)obproxy_parse_malloc( sizeof(ObProxyRelationExpr), result->malloc_pool_)))) { } else { relation->column_idx_ = i; relation->type_ = F_COMP_EQ; relation->right_value_ = right_value; - relation->level_ = result->part_key_info_.part_keys_[i].level_; + relation->left_value_ = NULL; + set_relation_part_with_column_idx(result->values_list_idx_, + result, + &relation->level_, + &relation->first_part_column_idx_, + &relation->second_part_column_idx_); } break; } @@ -359,12 +458,12 @@ static inline void add_right_relation_value(ObExprParseResult *result, %token DUMMY_SELECT_CLAUSE DUMMY_INSERT_CLAUSE /* reserved keyword */ %token WHERE AS VALUES SET END_WHERE JOIN -%token AND_OP OR_OP IN ON BETWEEN ROWID +%token AND_OP OR_OP IN ON BETWEEN IS TOKEN_NULL NOT %token COMP_EQ COMP_NSEQ COMP_GE COMP_GT COMP_LE COMP_LT COMP_NE %token PLACE_HOLDER %token END_P ERROR IGNORED_WORD /* type token */ -%token NAME_OB STR_VAL +%token NAME_OB STR_VAL ROW_ID REVERSED_EXPR_FUNC %token INT_VAL POS_PLACE_HOLDER %type comp %type token opt_column @@ -418,12 +517,8 @@ bool_pri: expr comp expr { add_relation(result, $1, $2,$3); $$ = get_relation(re add_relation(result, $1, F_COMP_LE, $5); $$ = NULL; } - | ROWID COMP_EQ STR_VAL - { - result->has_rowid_ =true; - result->rowid_str_ = $3; - $$ = NULL; - } + | expr IS TOKEN_NULL { $$ = NULL; } + | expr IS NOT TOKEN_NULL { $$ = NULL; } comp: COMP_EQ { $$ = F_COMP_EQ; } | COMP_NSEQ { $$ = F_COMP_NSEQ; } @@ -445,7 +540,15 @@ func_param_list: { $$ = NULL; } /* empty */ | token_list ',' token_list { add_token_list($1, $3); $$ = $1; } | func_param_list ',' token_list { add_token_list($1, $3); $$ = $1; } -token: NAME_OB +token: + ROW_ID + { + malloc_node($$, result, TOKEN_COLUMN); + $$->part_key_idx_ = 0; + $$->column_name_ = $1; + result->has_rowid_ = true; + } + | NAME_OB { malloc_node($$, result, TOKEN_COLUMN); $$->part_key_idx_ = get_part_key_idx(NULL, NULL, &$1, result); @@ -463,6 +566,11 @@ token: NAME_OB $$->part_key_idx_ = get_part_key_idx(&$1, &$3, &$5, result); $$->column_name_ = $5; } + | REVERSED_EXPR_FUNC + { + malloc_node($$, result, TOKEN_FUNC); + $$->str_value_ = $1; + } | NAME_OB '(' token_list ')' { malloc_node($$, result, TOKEN_FUNC); @@ -512,7 +620,7 @@ values_expr_lists: '(' values_expr_list ')' result->multi_param_values_++; } -opt_column_list: /* empty */ +opt_column_list: /* empty */ { init_part_key_all_match(result);} | '(' column_list ')' /* column_list: NAME_OB { result->column_idx_ = 0; set_part_key_column_idx(result, &$1); } diff --git a/src/obproxy/opsql/expr_parser/ob_expr_parser_gbk_lex.c b/src/obproxy/opsql/expr_parser/ob_expr_parser_gbk_lex.c new file mode 100644 index 0000000000000000000000000000000000000000..4be99343017e3c09f4c273c6362f32ecaca1a413 --- /dev/null +++ b/src/obproxy/opsql/expr_parser/ob_expr_parser_gbk_lex.c @@ -0,0 +1,2833 @@ +#line 2 "ob_expr_parser_gbk_lex.c" + +#line 4 "ob_expr_parser_gbk_lex.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yyg->yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yyg->yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE ob_expr_parser_gbk_yyrestart(yyin ,yyscanner ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = yyg->yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via ob_expr_parser_gbk_yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ + ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] + +void ob_expr_parser_gbk_yyrestart (FILE *input_file ,yyscan_t yyscanner ); +void ob_expr_parser_gbk_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +YY_BUFFER_STATE ob_expr_parser_gbk_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); +void ob_expr_parser_gbk_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void ob_expr_parser_gbk_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void ob_expr_parser_gbk_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +void ob_expr_parser_gbk_yypop_buffer_state (yyscan_t yyscanner ); + +static void ob_expr_parser_gbk_yyensure_buffer_stack (yyscan_t yyscanner ); +static void ob_expr_parser_gbk_yy_load_buffer_state (yyscan_t yyscanner ); +static void ob_expr_parser_gbk_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); + +#define YY_FLUSH_BUFFER ob_expr_parser_gbk_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner) + +YY_BUFFER_STATE ob_expr_parser_gbk_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); +YY_BUFFER_STATE ob_expr_parser_gbk_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +YY_BUFFER_STATE ob_expr_parser_gbk_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); + +void *ob_expr_parser_gbk_yyalloc (yy_size_t ,yyscan_t yyscanner ); +void *ob_expr_parser_gbk_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); +void ob_expr_parser_gbk_yyfree (void * ,yyscan_t yyscanner ); + +#define yy_new_buffer ob_expr_parser_gbk_yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + ob_expr_parser_gbk_yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + ob_expr_parser_gbk_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + ob_expr_parser_gbk_yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + ob_expr_parser_gbk_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define ob_expr_parser_gbk_yywrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +typedef int yy_state_type; + +#define yytext_ptr yytext_r + +static yy_state_type yy_get_previous_state (yyscan_t yyscanner ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner); +static int yy_get_next_buffer (yyscan_t yyscanner ); +static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yyg->yytext_ptr = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + yyg->yy_hold_char = *yy_cp; \ + yyg->yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 61 +#define YY_END_OF_BUFFER 62 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[269] = + { 0, + 34, 34, 0, 0, 0, 0, 0, 0, 0, 0, + 62, 60, 35, 35, 39, 50, 35, 34, 39, 39, + 44, 37, 38, 39, 36, 39, 39, 39, 32, 39, + 27, 22, 25, 29, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 56, 39, + 60, 60, 43, 42, 43, 45, 46, 61, 51, 52, + 61, 58, 59, 35, 0, 28, 35, 34, 15, 32, + 0, 0, 32, 33, 40, 33, 32, 34, 0, 30, + 26, 24, 34, 2, 34, 34, 34, 34, 18, 19, + 34, 34, 34, 34, 12, 16, 34, 34, 34, 34, + + 34, 17, 37, 38, 36, 0, 41, 45, 0, 0, + 47, 0, 0, 48, 51, 0, 53, 0, 0, 0, + 54, 58, 57, 32, 35, 0, 32, 0, 0, 33, + 0, 32, 0, 33, 30, 23, 14, 34, 6, 34, + 34, 34, 34, 21, 34, 34, 5, 34, 34, 34, + 49, 0, 49, 0, 55, 0, 55, 0, 32, 35, + 35, 35, 32, 33, 0, 33, 0, 33, 32, 30, + 34, 34, 34, 11, 34, 20, 34, 34, 34, 34, + 0, 0, 0, 0, 32, 32, 32, 30, 34, 8, + 34, 7, 10, 34, 4, 1, 0, 0, 49, 0, + + 0, 0, 55, 0, 32, 32, 32, 30, 34, 9, + 34, 3, 32, 32, 32, 30, 13, 31, 32, 32, + 32, 30, 32, 32, 32, 30, 32, 32, 32, 30, + 32, 32, 32, 30, 32, 32, 32, 30, 32, 32, + 32, 30, 32, 32, 32, 30, 32, 32, 32, 30, + 32, 32, 32, 30, 32, 32, 32, 30, 32, 32, + 33, 30, 33, 33, 33, 33, 33, 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 2, 4, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 21, 9, 22, + 23, 24, 25, 9, 26, 27, 8, 28, 29, 30, + 31, 32, 33, 34, 8, 35, 36, 37, 38, 39, + 8, 40, 41, 42, 43, 44, 45, 8, 46, 8, + 1, 47, 1, 9, 8, 48, 49, 50, 8, 51, + + 52, 53, 54, 55, 56, 57, 8, 58, 59, 60, + 61, 62, 8, 63, 64, 65, 66, 67, 68, 8, + 69, 8, 1, 70, 1, 9, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 71, 1, 72, 1, 1, 1, 1, 73, 74, 1, + 1, 75, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[76] = + { 0, + 1, 1, 2, 2, 1, 3, 1, 4, 1, 1, + 5, 1, 1, 1, 1, 1, 1, 1, 1, 4, + 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 6, 7, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int16_t yy_base[285] = + { 0, + 0, 0, 73, 74, 67, 68, 74, 75, 611, 610, + 631, 660, 80, 87, 601, 660, 0, 0, 660, 598, + 660, 660, 660, 585, 660, 75, 574, 579, 76, 82, + 62, 660, 560, 660, 63, 72, 65, 66, 81, 71, + 71, 77, 73, 80, 75, 96, 92, 105, 660, 482, + 480, 71, 660, 660, 133, 0, 152, 0, 0, 164, + 0, 0, 501, 170, 477, 660, 0, 0, 660, 527, + 173, 526, 160, 133, 660, 159, 164, 175, 524, 523, + 518, 660, 110, 0, 122, 143, 148, 147, 0, 0, + 161, 160, 155, 163, 0, 0, 154, 159, 161, 168, + + 175, 660, 660, 660, 660, 186, 660, 0, 226, 530, + 660, 522, 467, 660, 0, 230, 660, 531, 519, 464, + 660, 0, 660, 514, 236, 462, 225, 193, 231, 227, + 235, 239, 512, 511, 509, 660, 0, 197, 0, 206, + 220, 221, 227, 0, 226, 229, 0, 235, 221, 226, + 660, 515, 513, 267, 660, 517, 508, 271, 490, 146, + 290, 292, 270, 489, 484, 483, 481, 478, 280, 470, + 251, 243, 265, 0, 262, 0, 278, 282, 281, 282, + 310, 414, 313, 400, 450, 306, 310, 440, 289, 0, + 289, 0, 0, 281, 295, 0, 341, 345, 361, 363, + + 347, 367, 351, 372, 438, 359, 362, 437, 300, 0, + 354, 0, 434, 367, 372, 421, 0, 0, 416, 375, + 379, 413, 405, 380, 392, 403, 402, 397, 400, 393, + 387, 410, 417, 385, 383, 422, 427, 382, 374, 430, + 435, 369, 366, 443, 447, 348, 320, 448, 455, 258, + 247, 460, 463, 211, 198, 468, 473, 195, 187, 476, + 488, 660, 137, 493, 498, 99, 501, 660, 553, 560, + 567, 574, 581, 94, 588, 595, 602, 609, 616, 622, + 629, 636, 643, 650 + } ; + +static yyconst flex_int16_t yy_def[285] = + { 0, + 268, 1, 269, 269, 270, 270, 271, 271, 272, 272, + 268, 268, 268, 268, 268, 268, 273, 274, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 274, 268, + 268, 268, 268, 268, 274, 274, 274, 274, 274, 274, + 274, 274, 274, 274, 274, 274, 274, 274, 268, 268, + 268, 268, 268, 268, 268, 275, 268, 276, 277, 268, + 278, 279, 268, 268, 268, 268, 273, 274, 268, 268, + 268, 268, 268, 268, 268, 268, 274, 274, 268, 268, + 268, 268, 274, 274, 274, 274, 274, 274, 274, 274, + 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, + + 274, 268, 268, 268, 268, 268, 268, 275, 268, 280, + 268, 268, 268, 268, 277, 268, 268, 281, 268, 268, + 268, 279, 268, 268, 282, 268, 268, 268, 268, 268, + 268, 274, 268, 274, 268, 268, 274, 274, 274, 274, + 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, + 268, 280, 280, 268, 268, 281, 281, 268, 268, 282, + 282, 282, 268, 268, 268, 268, 268, 268, 274, 268, + 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, + 283, 268, 284, 268, 268, 268, 274, 268, 274, 274, + 274, 274, 274, 274, 274, 274, 283, 283, 283, 283, + + 284, 284, 284, 284, 268, 268, 274, 268, 274, 274, + 274, 274, 268, 268, 274, 268, 274, 274, 268, 268, + 274, 268, 268, 268, 274, 268, 268, 268, 274, 268, + 268, 268, 274, 268, 268, 268, 274, 268, 268, 268, + 274, 268, 268, 268, 274, 268, 268, 268, 274, 268, + 268, 268, 274, 268, 268, 268, 274, 268, 268, 268, + 274, 268, 268, 268, 274, 268, 268, 0, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268 + } ; + +static yyconst flex_int16_t yy_nxt[736] = + { 0, + 12, 13, 14, 13, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 19, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 18, 18, 37, + 38, 39, 40, 41, 42, 18, 43, 44, 18, 45, + 46, 18, 18, 47, 48, 18, 12, 49, 35, 36, + 18, 18, 37, 38, 39, 40, 41, 42, 18, 43, + 44, 18, 45, 46, 18, 18, 47, 48, 18, 50, + 51, 52, 12, 12, 12, 54, 54, 57, 57, 60, + 60, 64, 64, 64, 81, 66, 55, 55, 64, 64, + 64, 71, 72, 76, 73, 77, 79, 68, 79, 83, + + 85, 80, 86, 84, 78, 87, 88, 89, 91, 92, + 93, 90, 97, 58, 58, 94, 95, 100, 266, 96, + 61, 61, 83, 85, 98, 86, 84, 78, 87, 88, + 89, 91, 92, 93, 90, 97, 101, 137, 94, 95, + 100, 99, 96, 103, 104, 105, 106, 98, 268, 268, + 65, 107, 74, 109, 109, 109, 266, 65, 110, 101, + 137, 129, 111, 138, 99, 116, 116, 116, 112, 117, + 118, 64, 64, 64, 125, 125, 125, 76, 130, 127, + 119, 76, 139, 132, 129, 140, 138, 131, 128, 133, + 141, 133, 78, 142, 134, 143, 144, 145, 146, 106, + + 147, 148, 149, 150, 107, 139, 263, 133, 140, 133, + 131, 128, 164, 141, 262, 78, 142, 259, 143, 144, + 145, 146, 113, 147, 148, 149, 150, 109, 109, 109, + 258, 116, 116, 116, 120, 155, 151, 161, 125, 125, + 65, 171, 76, 126, 163, 165, 130, 165, 172, 167, + 166, 167, 173, 128, 168, 131, 76, 174, 169, 175, + 176, 177, 178, 179, 171, 180, 255, 78, 181, 181, + 181, 172, 183, 183, 183, 173, 128, 254, 131, 189, + 174, 190, 175, 176, 177, 178, 179, 76, 180, 186, + 78, 161, 125, 125, 268, 268, 113, 76, 128, 187, + + 120, 191, 189, 192, 190, 193, 162, 194, 78, 195, + 196, 198, 181, 181, 202, 183, 183, 209, 203, 210, + 199, 128, 211, 76, 191, 206, 192, 76, 193, 207, + 194, 78, 195, 196, 128, 212, 217, 182, 78, 251, + 209, 184, 210, 268, 268, 211, 198, 181, 181, 268, + 268, 199, 203, 268, 268, 199, 203, 128, 212, 217, + 162, 78, 161, 268, 268, 268, 268, 250, 202, 183, + 183, 199, 203, 199, 268, 268, 76, 203, 214, 76, + 200, 215, 218, 204, 76, 247, 220, 128, 246, 76, + 78, 221, 76, 243, 224, 128, 76, 76, 225, 228, + + 78, 242, 239, 128, 238, 218, 235, 78, 128, 76, + 128, 229, 234, 78, 76, 200, 232, 76, 128, 233, + 78, 231, 230, 78, 227, 128, 128, 76, 78, 236, + 78, 128, 226, 198, 76, 223, 237, 204, 128, 76, + 222, 240, 202, 78, 76, 78, 241, 76, 128, 244, + 128, 78, 76, 219, 245, 78, 216, 213, 128, 208, + 76, 128, 248, 78, 76, 76, 249, 252, 78, 205, + 183, 128, 76, 128, 253, 78, 128, 76, 78, 256, + 76, 128, 257, 78, 181, 76, 78, 260, 128, 188, + 76, 78, 261, 76, 128, 264, 128, 168, 78, 128, + + 168, 78, 166, 166, 128, 76, 78, 265, 164, 185, + 76, 128, 267, 157, 78, 76, 78, 265, 76, 128, + 267, 128, 157, 153, 78, 153, 78, 128, 170, 128, + 134, 164, 125, 159, 116, 158, 157, 109, 154, 78, + 153, 136, 135, 80, 128, 74, 124, 64, 123, 78, + 64, 102, 128, 53, 53, 53, 53, 53, 53, 53, + 56, 56, 56, 56, 56, 56, 56, 59, 59, 59, + 59, 59, 59, 59, 62, 62, 62, 62, 62, 62, + 62, 67, 82, 67, 67, 67, 67, 67, 108, 108, + 108, 108, 75, 74, 108, 114, 114, 114, 114, 114, + + 114, 114, 115, 115, 70, 115, 115, 69, 115, 121, + 121, 121, 121, 121, 121, 121, 122, 122, 122, 122, + 122, 122, 152, 66, 152, 152, 152, 152, 152, 156, + 268, 156, 156, 156, 156, 156, 160, 160, 160, 160, + 160, 160, 160, 197, 197, 197, 197, 197, 197, 197, + 201, 201, 201, 201, 201, 201, 201, 63, 63, 11, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268 + } ; + +static yyconst flex_int16_t yy_chk[736] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 4, 5, 6, 7, + 8, 13, 13, 13, 31, 31, 3, 4, 14, 14, + 14, 26, 26, 29, 26, 29, 30, 274, 30, 35, + + 36, 30, 37, 35, 29, 38, 39, 40, 41, 42, + 43, 40, 45, 5, 6, 43, 44, 47, 266, 44, + 7, 8, 35, 36, 46, 37, 35, 29, 38, 39, + 40, 41, 42, 43, 40, 45, 48, 83, 43, 44, + 47, 46, 44, 52, 52, 52, 55, 46, 160, 160, + 13, 55, 74, 57, 57, 57, 263, 14, 57, 48, + 83, 74, 57, 85, 46, 60, 60, 60, 57, 60, + 60, 64, 64, 64, 71, 71, 71, 73, 76, 73, + 60, 77, 86, 77, 74, 87, 85, 76, 73, 78, + 88, 78, 77, 91, 78, 92, 93, 94, 97, 106, + + 98, 99, 100, 101, 106, 86, 259, 128, 87, 128, + 76, 73, 128, 88, 258, 77, 91, 255, 92, 93, + 94, 97, 57, 98, 99, 100, 101, 109, 109, 109, + 254, 116, 116, 116, 60, 116, 109, 125, 125, 125, + 64, 138, 127, 71, 127, 129, 130, 129, 140, 131, + 129, 131, 141, 127, 131, 130, 132, 142, 132, 143, + 145, 146, 148, 149, 138, 150, 251, 132, 154, 154, + 154, 140, 158, 158, 158, 141, 127, 250, 130, 171, + 142, 172, 143, 145, 146, 148, 149, 163, 150, 163, + 132, 161, 161, 161, 162, 162, 109, 169, 163, 169, + + 116, 173, 171, 175, 172, 177, 125, 178, 169, 179, + 180, 181, 181, 181, 183, 183, 183, 189, 183, 191, + 181, 163, 194, 186, 173, 186, 175, 187, 177, 187, + 178, 169, 179, 180, 186, 195, 209, 154, 187, 247, + 189, 158, 191, 197, 197, 194, 198, 198, 198, 201, + 201, 197, 201, 203, 203, 198, 203, 186, 195, 209, + 161, 187, 162, 199, 199, 200, 200, 246, 202, 202, + 202, 199, 202, 200, 204, 204, 206, 204, 206, 207, + 181, 207, 211, 183, 214, 243, 214, 206, 242, 215, + 207, 215, 220, 239, 220, 214, 221, 224, 221, 224, + + 215, 238, 235, 220, 234, 211, 231, 221, 224, 225, + 206, 225, 230, 207, 228, 198, 228, 229, 214, 229, + 225, 227, 226, 215, 223, 228, 220, 232, 229, 232, + 221, 224, 222, 200, 233, 219, 233, 202, 232, 236, + 216, 236, 204, 225, 237, 233, 237, 240, 228, 240, + 236, 229, 241, 213, 241, 237, 208, 205, 240, 188, + 244, 232, 244, 241, 245, 248, 245, 248, 233, 185, + 184, 244, 249, 236, 249, 245, 248, 252, 237, 252, + 253, 240, 253, 249, 182, 256, 241, 256, 252, 170, + 257, 253, 257, 260, 244, 260, 256, 168, 245, 248, + + 167, 257, 166, 165, 260, 261, 249, 261, 164, 159, + 264, 252, 264, 157, 253, 265, 261, 265, 267, 256, + 267, 264, 156, 153, 257, 152, 265, 260, 135, 267, + 134, 133, 126, 124, 120, 119, 118, 113, 112, 261, + 110, 81, 80, 79, 264, 72, 70, 65, 63, 265, + 51, 50, 267, 269, 269, 269, 269, 269, 269, 269, + 270, 270, 270, 270, 270, 270, 270, 271, 271, 271, + 271, 271, 271, 271, 272, 272, 272, 272, 272, 272, + 272, 273, 33, 273, 273, 273, 273, 273, 275, 275, + 275, 275, 28, 27, 275, 276, 276, 276, 276, 276, + + 276, 276, 277, 277, 24, 277, 277, 20, 277, 278, + 278, 278, 278, 278, 278, 278, 279, 279, 279, 279, + 279, 279, 280, 15, 280, 280, 280, 280, 280, 281, + 11, 281, 281, 281, 281, 281, 282, 282, 282, 282, + 282, 282, 282, 283, 283, 283, 283, 283, 283, 283, + 284, 284, 284, 284, 284, 284, 284, 10, 9, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268 + } ; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +#line 1 "ob_expr_parser_gbk.l" +#define YY_NO_INPUT 1 +#line 7 "ob_expr_parser_gbk.l" +#define YYSTYPE OBEXPRSTYPE +#define YYLTYPE OBEXPRLTYPE +#include +#include "opsql/ob_proxy_parse_define.h" +#include "opsql/ob_proxy_parse_malloc.h" +#include "opsql/expr_parser/ob_expr_parse_result.h" +#include "opsql/expr_parser/ob_expr_parser_gbk_tab.h" +extern void ob_expr_gbk_parser_fatal_error(yyconst char *msg, yyscan_t yyscanner); + +void store_expr_str(char* str, int64_t str_len, char* end_ptr, void *yyscanner); +void store_pos_place_holder(char* str, void *yyscanner); + +#define YY_FATAL_ERROR(msg) ob_expr_gbk_parser_fatal_error(msg, yyscanner) + +#define PUSH_STATE(state) \ + { yy_push_state(state, yyscanner); } + +#define POP_STATE(state) \ + { yy_pop_state(yyscanner); } + +#define RETURN_INT_VAL() \ +do {\ + errno = 0;\ + yylval->num = strtoll(yytext, NULL, 10);\ + if (0 != errno) {\ + yylval->num = 0;\ + }\ + return INT_VAL;\ +} while (0); + +#define RETURN_STR_VAL() \ + { store_expr_str(yytext, yyleng, yytext + yyleng, yyscanner); return STR_VAL; } + +#define RETURN_NUMBER_VAL() \ + { store_expr_str(yytext, yyleng, yytext + yyleng, yyscanner); return STR_VAL; } + +#define RETURN_NAME_OB() \ + { store_expr_str(yytext, yyleng, yytext + yyleng, yyscanner); return NAME_OB; } + +#define RETURN_ROW_ID() \ + { store_expr_str(yytext, yyleng, yytext + yyleng, yyscanner); return ROW_ID; } + +#define RETURN_REVERSED_EXPR_FUNC() \ + { store_expr_str(yytext, yyleng, yytext + yyleng, yyscanner); return REVERSED_EXPR_FUNC; } + + + + + +/*following character status will be rewrite by gen_parse.sh according to connection character*/ +/* limit the length of int_num from 1 to 17 in case of int64_t out of bound, 17 -> [ ( length of 2^64 ) - 2 ]*/ +#line 740 "ob_expr_parser_gbk_lex.c" + +#define INITIAL 0 +#define in_c_comment 1 +#define sq 2 +#define dq 3 +#define bt 4 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* Holds the entire state of the reentrant scanner. */ +struct yyguts_t + { + + /* User-defined. Not touched by flex. */ + YY_EXTRA_TYPE yyextra_r; + + /* The rest are the same as the globals declared in the non-reentrant scanner. */ + FILE *yyin_r, *yyout_r; + size_t yy_buffer_stack_top; /**< index of top of stack. */ + size_t yy_buffer_stack_max; /**< capacity of stack. */ + YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ + char yy_hold_char; + int yy_n_chars; + int yyleng_r; + char *yy_c_buf_p; + int yy_init; + int yy_start; + int yy_did_buffer_switch_on_eof; + int yy_start_stack_ptr; + int yy_start_stack_depth; + int *yy_start_stack; + yy_state_type yy_last_accepting_state; + char* yy_last_accepting_cpos; + + int yylineno_r; + int yy_flex_debug_r; + + char *yytext_r; + int yy_more_flag; + int yy_more_len; + + YYSTYPE * yylval_r; + + YYLTYPE * yylloc_r; + + }; /* end struct yyguts_t */ + +static int yy_init_globals (yyscan_t yyscanner ); + + /* This must go here because YYSTYPE and YYLTYPE are included + * from bison output in section 1.*/ + # define yylval yyg->yylval_r + + # define yylloc yyg->yylloc_r + +int ob_expr_parser_gbk_yylex_init (yyscan_t* scanner); + +int ob_expr_parser_gbk_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int ob_expr_parser_gbk_yylex_destroy (yyscan_t yyscanner ); + +int ob_expr_parser_gbk_yyget_debug (yyscan_t yyscanner ); + +void ob_expr_parser_gbk_yyset_debug (int debug_flag ,yyscan_t yyscanner ); + +YY_EXTRA_TYPE ob_expr_parser_gbk_yyget_extra (yyscan_t yyscanner ); + +void ob_expr_parser_gbk_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); + +FILE *ob_expr_parser_gbk_yyget_in (yyscan_t yyscanner ); + +void ob_expr_parser_gbk_yyset_in (FILE * in_str ,yyscan_t yyscanner ); + +FILE *ob_expr_parser_gbk_yyget_out (yyscan_t yyscanner ); + +void ob_expr_parser_gbk_yyset_out (FILE * out_str ,yyscan_t yyscanner ); + +int ob_expr_parser_gbk_yyget_leng (yyscan_t yyscanner ); + +char *ob_expr_parser_gbk_yyget_text (yyscan_t yyscanner ); + +int ob_expr_parser_gbk_yyget_lineno (yyscan_t yyscanner ); + +void ob_expr_parser_gbk_yyset_lineno (int line_number ,yyscan_t yyscanner ); + +YYSTYPE * ob_expr_parser_gbk_yyget_lval (yyscan_t yyscanner ); + +void ob_expr_parser_gbk_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); + + YYLTYPE *ob_expr_parser_gbk_yyget_lloc (yyscan_t yyscanner ); + + void ob_expr_parser_gbk_yyset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int ob_expr_parser_gbk_yywrap (yyscan_t yyscanner ); +#else +extern int ob_expr_parser_gbk_yywrap (yyscan_t yyscanner ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (yyscan_t yyscanner ); +#else +static int input (yyscan_t yyscanner ); +#endif + +#endif + + static void yy_push_state (int new_state ,yyscan_t yyscanner); + + static void yy_pop_state (yyscan_t yyscanner ); + + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + int n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int ob_expr_parser_gbk_yylex \ + (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner); + +#define YY_DECL int ob_expr_parser_gbk_yylex \ + (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +#line 102 "ob_expr_parser_gbk.l" + +#line 991 "ob_expr_parser_gbk_lex.c" + + yylval = yylval_param; + + yylloc = yylloc_param; + + if ( !yyg->yy_init ) + { + yyg->yy_init = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yyg->yy_start ) + yyg->yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + ob_expr_parser_gbk_yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + ob_expr_parser_gbk_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + } + + ob_expr_parser_gbk_yy_load_buffer_state(yyscanner ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yyg->yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yyg->yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yyg->yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 269 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 660 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yyg->yy_hold_char; + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 103 "ob_expr_parser_gbk.l" +{ return WHERE; } + YY_BREAK +case 2: +YY_RULE_SETUP +#line 104 "ob_expr_parser_gbk.l" +{ return AS; } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 105 "ob_expr_parser_gbk.l" +{ return VALUES; } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 106 "ob_expr_parser_gbk.l" +{ return VALUES; } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 107 "ob_expr_parser_gbk.l" +{ return SET; } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 108 "ob_expr_parser_gbk.l" +{ return END_WHERE; } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 109 "ob_expr_parser_gbk.l" +{ return END_WHERE; } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 110 "ob_expr_parser_gbk.l" +{ return END_WHERE; } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 111 "ob_expr_parser_gbk.l" +{ return END_WHERE; } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 112 "ob_expr_parser_gbk.l" +{ RETURN_ROW_ID(); } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 114 "ob_expr_parser_gbk.l" +{ return JOIN; } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 115 "ob_expr_parser_gbk.l" +{ return ON; } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 116 "ob_expr_parser_gbk.l" +{ return BETWEEN; } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 117 "ob_expr_parser_gbk.l" +{ return AND_OP; } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 118 "ob_expr_parser_gbk.l" +{ return AND_OP; } + YY_BREAK +case 16: +YY_RULE_SETUP +#line 119 "ob_expr_parser_gbk.l" +{ return OR_OP; } + YY_BREAK +case 17: +YY_RULE_SETUP +#line 120 "ob_expr_parser_gbk.l" +{ return OR_OP; } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 121 "ob_expr_parser_gbk.l" +{ return IN; } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 122 "ob_expr_parser_gbk.l" +{ return IS; } + YY_BREAK +case 20: +YY_RULE_SETUP +#line 123 "ob_expr_parser_gbk.l" +{ return TOKEN_NULL; } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 124 "ob_expr_parser_gbk.l" +{ return NOT; } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 125 "ob_expr_parser_gbk.l" +{ return COMP_EQ; } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 126 "ob_expr_parser_gbk.l" +{ return COMP_NSEQ; } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 127 "ob_expr_parser_gbk.l" +{ return COMP_GE; } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 128 "ob_expr_parser_gbk.l" +{ return COMP_GT; } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 129 "ob_expr_parser_gbk.l" +{ return COMP_LE; } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 130 "ob_expr_parser_gbk.l" +{ return COMP_LT; } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 131 "ob_expr_parser_gbk.l" +{ return COMP_NE; } + YY_BREAK +case 29: +YY_RULE_SETUP +#line 132 "ob_expr_parser_gbk.l" +{ return PLACE_HOLDER; } + YY_BREAK +case 30: +YY_RULE_SETUP +#line 133 "ob_expr_parser_gbk.l" +{ store_pos_place_holder(yytext + 1, yyscanner); return POS_PLACE_HOLDER; } + YY_BREAK +case 31: +YY_RULE_SETUP +#line 134 "ob_expr_parser_gbk.l" +{ RETURN_REVERSED_EXPR_FUNC();} + YY_BREAK +case 32: +YY_RULE_SETUP +#line 136 "ob_expr_parser_gbk.l" +{ RETURN_INT_VAL(); } + YY_BREAK +case 33: +YY_RULE_SETUP +#line 137 "ob_expr_parser_gbk.l" +{ RETURN_NUMBER_VAL(); } + YY_BREAK +case 34: +YY_RULE_SETUP +#line 138 "ob_expr_parser_gbk.l" +{ RETURN_NAME_OB(); } + YY_BREAK +case 35: +/* rule 35 can match eol */ +YY_RULE_SETUP +#line 139 "ob_expr_parser_gbk.l" +{ } + YY_BREAK +case 36: +YY_RULE_SETUP +#line 140 "ob_expr_parser_gbk.l" +{ return ','; } + YY_BREAK +case 37: +YY_RULE_SETUP +#line 141 "ob_expr_parser_gbk.l" +{ return '('; } + YY_BREAK +case 38: +YY_RULE_SETUP +#line 142 "ob_expr_parser_gbk.l" +{ return ')'; } + YY_BREAK +case 39: +YY_RULE_SETUP +#line 143 "ob_expr_parser_gbk.l" +{ return yytext[0]; } + YY_BREAK +/* comment */ +case 40: +YY_RULE_SETUP +#line 146 "ob_expr_parser_gbk.l" +{ PUSH_STATE(in_c_comment); } + YY_BREAK +case 41: +YY_RULE_SETUP +#line 147 "ob_expr_parser_gbk.l" +{ POP_STATE(); } + YY_BREAK +case 42: +/* rule 42 can match eol */ +YY_RULE_SETUP +#line 148 "ob_expr_parser_gbk.l" +{} + YY_BREAK +case 43: +YY_RULE_SETUP +#line 149 "ob_expr_parser_gbk.l" +{} + YY_BREAK +/* quote */ +case 44: +YY_RULE_SETUP +#line 152 "ob_expr_parser_gbk.l" +{ + PUSH_STATE(sq); + ObExprParseResult *p = (ObExprParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->tmp_buf_ = (yytext + 1); + p->tmp_start_ptr_ = yytext; + p->tmp_len_ = 0; + } +} + YY_BREAK +case 45: +/* rule 45 can match eol */ +YY_RULE_SETUP +#line 162 "ob_expr_parser_gbk.l" +{ + ObExprParseResult *p = (ObExprParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->tmp_len_ += yyleng; + } +} + YY_BREAK +case 46: +YY_RULE_SETUP +#line 169 "ob_expr_parser_gbk.l" +{ + POP_STATE(); + ObExprParseResult *p = (ObExprParseResult *)yyextra; + if (OB_NOTNULL(p)) { + store_expr_str(p->tmp_buf_, p->tmp_len_, p->tmp_start_ptr_ + p->tmp_len_ + 2, yyscanner); + } + return STR_VAL; +} + YY_BREAK +case 47: +YY_RULE_SETUP +#line 178 "ob_expr_parser_gbk.l" +{} + YY_BREAK +case 48: +/* rule 48 can match eol */ +YY_RULE_SETUP +#line 179 "ob_expr_parser_gbk.l" +{ + ObExprParseResult *p = (ObExprParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->tmp_len_ += yyleng; + } +} + YY_BREAK +case 49: +/* rule 49 can match eol */ +YY_RULE_SETUP +#line 185 "ob_expr_parser_gbk.l" +{} + YY_BREAK +case YY_STATE_EOF(sq): +#line 186 "ob_expr_parser_gbk.l" +{ return ERROR; } + YY_BREAK +/* dquote */ +case 50: +YY_RULE_SETUP +#line 190 "ob_expr_parser_gbk.l" +{ + PUSH_STATE(dq); + ObExprParseResult *p = (ObExprParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->tmp_buf_ = (yytext + 1); + p->tmp_start_ptr_ = yytext; + p->tmp_len_ = 0; + } +} + YY_BREAK +case 51: +/* rule 51 can match eol */ +YY_RULE_SETUP +#line 200 "ob_expr_parser_gbk.l" +{ + ObExprParseResult *p = (ObExprParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->tmp_len_ += yyleng; + } +} + YY_BREAK +case 52: +YY_RULE_SETUP +#line 207 "ob_expr_parser_gbk.l" +{ + POP_STATE(); + ObExprParseResult *p = (ObExprParseResult *)yyextra; + if (OB_NOTNULL(p)) { + store_expr_str(p->tmp_buf_, p->tmp_len_, p->tmp_start_ptr_ + p->tmp_len_ + 2, yyscanner); + if (p->is_oracle_mode_) { + return NAME_OB; + } + } + return STR_VAL; +} + YY_BREAK +case 53: +YY_RULE_SETUP +#line 219 "ob_expr_parser_gbk.l" +{} + YY_BREAK +case 54: +/* rule 54 can match eol */ +YY_RULE_SETUP +#line 220 "ob_expr_parser_gbk.l" +{} + YY_BREAK +case 55: +/* rule 55 can match eol */ +YY_RULE_SETUP +#line 221 "ob_expr_parser_gbk.l" +{} + YY_BREAK +case YY_STATE_EOF(dq): +#line 222 "ob_expr_parser_gbk.l" +{ return ERROR; } + YY_BREAK +/* backtick */ +case 56: +YY_RULE_SETUP +#line 226 "ob_expr_parser_gbk.l" +{ + PUSH_STATE(bt); + ObExprParseResult *p = (ObExprParseResult *)yyextra; + if (NULL != p) { + p->tmp_buf_ = (char *)obproxy_parse_malloc(OBPROXY_MAX_NAME_LENGTH, p->malloc_pool_); + p->tmp_start_ptr_ = yytext; + p->tmp_len_ = 0; + } +} + YY_BREAK +case 57: +YY_RULE_SETUP +#line 236 "ob_expr_parser_gbk.l" +{ + ObExprParseResult *p = (ObExprParseResult *)yyextra; + if (NULL != p && NULL != p->tmp_buf_ && p->tmp_len_ + 1 < OBPROXY_MAX_NAME_LENGTH) { + p->tmp_buf_[p->tmp_len_++] = '`'; + } +} + YY_BREAK +case 58: +/* rule 58 can match eol */ +YY_RULE_SETUP +#line 243 "ob_expr_parser_gbk.l" +{ + ObExprParseResult *p = (ObExprParseResult *)yyextra; + if (NULL != p && NULL != p->tmp_buf_ && p->tmp_len_ + yyleng < OBPROXY_MAX_NAME_LENGTH) { + memcpy(p->tmp_buf_ + p->tmp_len_, yytext, yyleng); + p->tmp_len_ += yyleng; + } +} + YY_BREAK +case 59: +YY_RULE_SETUP +#line 251 "ob_expr_parser_gbk.l" +{ + POP_STATE(); + ObExprParseResult *p = (ObExprParseResult *)yyextra; + if (NULL != p && NULL != p->tmp_buf_) { + yylval->str.str_ = obproxy_parse_strndup(p->tmp_buf_, p->tmp_len_, p->malloc_pool_); + yylval->str.str_len_ = p->tmp_len_; + yylval->str.end_ptr_ = p->tmp_start_ptr_ + p->tmp_len_ + 2; + } + return NAME_OB; +} + YY_BREAK +case YY_STATE_EOF(bt): +#line 262 "ob_expr_parser_gbk.l" +{ + return ERROR; +} + YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(in_c_comment): +#line 266 "ob_expr_parser_gbk.l" +{ return END_P; } + YY_BREAK +case 60: +YY_RULE_SETUP +#line 267 "ob_expr_parser_gbk.l" +{ return IGNORED_WORD; } + YY_BREAK +case 61: +YY_RULE_SETUP +#line 268 "ob_expr_parser_gbk.l" +ECHO; + YY_BREAK +#line 1491 "ob_expr_parser_gbk_lex.c" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yyg->yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * ob_expr_parser_gbk_yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); + + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yyg->yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yyg->yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_END_OF_FILE: + { + yyg->yy_did_buffer_switch_on_eof = 0; + + if ( ob_expr_parser_gbk_yywrap(yyscanner ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = + yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yyg->yy_c_buf_p = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of ob_expr_parser_gbk_yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = yyg->yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) (yyg->yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + ob_expr_parser_gbk_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + yyg->yy_n_chars, (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + if ( yyg->yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + ob_expr_parser_gbk_yyrestart(yyin ,yyscanner); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) ob_expr_parser_gbk_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + yyg->yy_n_chars += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (yyscan_t yyscanner) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_current_state = yyg->yy_start; + + for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 269 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) +{ + register int yy_is_jam; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ + register char *yy_cp = yyg->yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 269 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 268); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (yyscan_t yyscanner) +#else + static int input (yyscan_t yyscanner) +#endif + +{ + int c; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + *yyg->yy_c_buf_p = yyg->yy_hold_char; + + if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + /* This was really a NUL. */ + *yyg->yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yyg->yy_c_buf_p - yyg->yytext_ptr; + ++yyg->yy_c_buf_p; + + switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + ob_expr_parser_gbk_yyrestart(yyin ,yyscanner); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( ob_expr_parser_gbk_yywrap(yyscanner ) ) + return EOF; + + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(yyscanner); +#else + return input(yyscanner); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = yyg->yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ + *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ + yyg->yy_hold_char = *++yyg->yy_c_buf_p; + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * @param yyscanner The scanner object. + * @note This function does not reset the start condition to @c INITIAL . + */ + void ob_expr_parser_gbk_yyrestart (FILE * input_file , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! YY_CURRENT_BUFFER ){ + ob_expr_parser_gbk_yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + ob_expr_parser_gbk_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + } + + ob_expr_parser_gbk_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); + ob_expr_parser_gbk_yy_load_buffer_state(yyscanner ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * @param yyscanner The scanner object. + */ + void ob_expr_parser_gbk_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* TODO. We should be able to replace this entire function body + * with + * ob_expr_parser_gbk_yypop_buffer_state(); + * ob_expr_parser_gbk_yypush_buffer_state(new_buffer); + */ + ob_expr_parser_gbk_yyensure_buffer_stack (yyscanner); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + ob_expr_parser_gbk_yy_load_buffer_state(yyscanner ); + + /* We don't actually know whether we did this switch during + * EOF (ob_expr_parser_gbk_yywrap()) processing, but the only time this flag + * is looked at is after ob_expr_parser_gbk_yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yyg->yy_did_buffer_switch_on_eof = 1; +} + +static void ob_expr_parser_gbk_yy_load_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + yyg->yy_hold_char = *yyg->yy_c_buf_p; +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * @param yyscanner The scanner object. + * @return the allocated buffer state. + */ + YY_BUFFER_STATE ob_expr_parser_gbk_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) ob_expr_parser_gbk_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in ob_expr_parser_gbk_yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) ob_expr_parser_gbk_yyalloc(b->yy_buf_size + 2 ,yyscanner ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in ob_expr_parser_gbk_yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + ob_expr_parser_gbk_yy_init_buffer(b,file ,yyscanner); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with ob_expr_parser_gbk_yy_create_buffer() + * @param yyscanner The scanner object. + */ + void ob_expr_parser_gbk_yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + ob_expr_parser_gbk_yyfree((void *) b->yy_ch_buf ,yyscanner ); + + ob_expr_parser_gbk_yyfree((void *) b ,yyscanner ); +} + +#ifndef __cplusplus +extern int isatty (int ); +#endif /* __cplusplus */ + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a ob_expr_parser_gbk_yyrestart() or at EOF. + */ + static void ob_expr_parser_gbk_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) + +{ + int oerrno = errno; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + ob_expr_parser_gbk_yy_flush_buffer(b ,yyscanner); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then ob_expr_parser_gbk_yy_init_buffer was _probably_ + * called from ob_expr_parser_gbk_yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * @param yyscanner The scanner object. + */ + void ob_expr_parser_gbk_yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + ob_expr_parser_gbk_yy_load_buffer_state(yyscanner ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * @param yyscanner The scanner object. + */ +void ob_expr_parser_gbk_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (new_buffer == NULL) + return; + + ob_expr_parser_gbk_yyensure_buffer_stack(yyscanner); + + /* This block is copied from ob_expr_parser_gbk_yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + yyg->yy_buffer_stack_top++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from ob_expr_parser_gbk_yy_switch_to_buffer. */ + ob_expr_parser_gbk_yy_load_buffer_state(yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * @param yyscanner The scanner object. + */ +void ob_expr_parser_gbk_yypop_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (!YY_CURRENT_BUFFER) + return; + + ob_expr_parser_gbk_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner); + YY_CURRENT_BUFFER_LVALUE = NULL; + if (yyg->yy_buffer_stack_top > 0) + --yyg->yy_buffer_stack_top; + + if (YY_CURRENT_BUFFER) { + ob_expr_parser_gbk_yy_load_buffer_state(yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void ob_expr_parser_gbk_yyensure_buffer_stack (yyscan_t yyscanner) +{ + int num_to_alloc; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (!yyg->yy_buffer_stack) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + yyg->yy_buffer_stack = (struct yy_buffer_state**)ob_expr_parser_gbk_yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in ob_expr_parser_gbk_yyensure_buffer_stack()" ); + + memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + yyg->yy_buffer_stack_max = num_to_alloc; + yyg->yy_buffer_stack_top = 0; + return; + } + + if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = yyg->yy_buffer_stack_max + grow_size; + yyg->yy_buffer_stack = (struct yy_buffer_state**)ob_expr_parser_gbk_yyrealloc + (yyg->yy_buffer_stack, + num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in ob_expr_parser_gbk_yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); + yyg->yy_buffer_stack_max = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE ob_expr_parser_gbk_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) ob_expr_parser_gbk_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in ob_expr_parser_gbk_yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + ob_expr_parser_gbk_yy_switch_to_buffer(b ,yyscanner ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to ob_expr_parser_gbk_yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * ob_expr_parser_gbk_yy_scan_bytes() instead. + */ +YY_BUFFER_STATE ob_expr_parser_gbk_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner) +{ + + return ob_expr_parser_gbk_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner); +} + +/** Setup the input buffer state to scan the given bytes. The next call to ob_expr_parser_gbk_yylex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE ob_expr_parser_gbk_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) ob_expr_parser_gbk_yyalloc(n ,yyscanner ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in ob_expr_parser_gbk_yy_scan_bytes()" ); + + memcpy(buf, yybytes, _yybytes_len); + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = ob_expr_parser_gbk_yy_scan_buffer(buf,n ,yyscanner); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in ob_expr_parser_gbk_yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + + static void yy_push_state (int new_state , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( yyg->yy_start_stack_ptr >= yyg->yy_start_stack_depth ) + { + yy_size_t new_size; + + yyg->yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yyg->yy_start_stack_depth * sizeof( int ); + + if ( ! yyg->yy_start_stack ) + yyg->yy_start_stack = (int *) ob_expr_parser_gbk_yyalloc(new_size ,yyscanner ); + + else + yyg->yy_start_stack = (int *) ob_expr_parser_gbk_yyrealloc((void *) yyg->yy_start_stack,new_size ,yyscanner ); + + if ( ! yyg->yy_start_stack ) + YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); + } + + yyg->yy_start_stack[yyg->yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); +} + + static void yy_pop_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( --yyg->yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yyg->yy_start_stack[yyg->yy_start_stack_ptr]); +} + + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = yyg->yy_hold_char; \ + yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ + yyg->yy_hold_char = *yyg->yy_c_buf_p; \ + *yyg->yy_c_buf_p = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the user-defined data for this scanner. + * @param yyscanner The scanner object. + */ +YY_EXTRA_TYPE ob_expr_parser_gbk_yyget_extra (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyextra; +} + +/** Get the current line number. + * @param yyscanner The scanner object. + */ +int ob_expr_parser_gbk_yyget_lineno (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yylineno; +} + +/** Get the current column number. + * @param yyscanner The scanner object. + */ +int ob_expr_parser_gbk_yyget_column (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yycolumn; +} + +/** Get the input stream. + * @param yyscanner The scanner object. + */ +FILE *ob_expr_parser_gbk_yyget_in (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyin; +} + +/** Get the output stream. + * @param yyscanner The scanner object. + */ +FILE *ob_expr_parser_gbk_yyget_out (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyout; +} + +/** Get the length of the current token. + * @param yyscanner The scanner object. + */ +int ob_expr_parser_gbk_yyget_leng (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyleng; +} + +/** Get the current token. + * @param yyscanner The scanner object. + */ + +char *ob_expr_parser_gbk_yyget_text (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yytext; +} + +/** Set the user-defined data. This data is never touched by the scanner. + * @param user_defined The data to be associated with this scanner. + * @param yyscanner The scanner object. + */ +void ob_expr_parser_gbk_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyextra = user_defined ; +} + +/** Set the current line number. + * @param line_number + * @param yyscanner The scanner object. + */ +void ob_expr_parser_gbk_yyset_lineno (int line_number , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* lineno is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + yy_fatal_error( "ob_expr_parser_gbk_yyset_lineno called with no buffer" , yyscanner); + + yylineno = line_number; +} + +/** Set the current column. + * @param line_number + * @param yyscanner The scanner object. + */ +void ob_expr_parser_gbk_yyset_column (int column_no , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* column is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + yy_fatal_error( "ob_expr_parser_gbk_yyset_column called with no buffer" , yyscanner); + + yycolumn = column_no; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * @param yyscanner The scanner object. + * @see ob_expr_parser_gbk_yy_switch_to_buffer + */ +void ob_expr_parser_gbk_yyset_in (FILE * in_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyin = in_str ; +} + +void ob_expr_parser_gbk_yyset_out (FILE * out_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyout = out_str ; +} + +int ob_expr_parser_gbk_yyget_debug (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yy_flex_debug; +} + +void ob_expr_parser_gbk_yyset_debug (int bdebug , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yy_flex_debug = bdebug ; +} + +/* Accessor methods for yylval and yylloc */ + +YYSTYPE * ob_expr_parser_gbk_yyget_lval (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yylval; +} + +void ob_expr_parser_gbk_yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yylval = yylval_param; +} + +YYLTYPE *ob_expr_parser_gbk_yyget_lloc (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yylloc; +} + +void ob_expr_parser_gbk_yyset_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yylloc = yylloc_param; +} + +/* User-visible API */ + +/* ob_expr_parser_gbk_yylex_init is special because it creates the scanner itself, so it is + * the ONLY reentrant function that doesn't take the scanner as the last argument. + * That's why we explicitly handle the declaration, instead of using our macros. + */ + +int ob_expr_parser_gbk_yylex_init(yyscan_t* ptr_yy_globals) + +{ + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) ob_expr_parser_gbk_yyalloc ( sizeof( struct yyguts_t ), NULL ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + return yy_init_globals ( *ptr_yy_globals ); +} + +/* ob_expr_parser_gbk_yylex_init_extra has the same functionality as ob_expr_parser_gbk_yylex_init, but follows the + * convention of taking the scanner as the last argument. Note however, that + * this is a *pointer* to a scanner, as it will be allocated by this call (and + * is the reason, too, why this function also must handle its own declaration). + * The user defined value in the first argument will be available to ob_expr_parser_gbk_yyalloc in + * the yyextra field. + */ + +int ob_expr_parser_gbk_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) + +{ + struct yyguts_t dummy_yyguts; + + ob_expr_parser_gbk_yyset_extra (yy_user_defined, &dummy_yyguts); + + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) ob_expr_parser_gbk_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in + yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + ob_expr_parser_gbk_yyset_extra (yy_user_defined, *ptr_yy_globals); + + return yy_init_globals ( *ptr_yy_globals ); +} + +static int yy_init_globals (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from ob_expr_parser_gbk_yylex_destroy(), so don't allocate here. + */ + + yyg->yy_buffer_stack = 0; + yyg->yy_buffer_stack_top = 0; + yyg->yy_buffer_stack_max = 0; + yyg->yy_c_buf_p = (char *) 0; + yyg->yy_init = 0; + yyg->yy_start = 0; + + yyg->yy_start_stack_ptr = 0; + yyg->yy_start_stack_depth = 0; + yyg->yy_start_stack = NULL; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * ob_expr_parser_gbk_yylex_init() + */ + return 0; +} + +/* ob_expr_parser_gbk_yylex_destroy is for both reentrant and non-reentrant scanners. */ +int ob_expr_parser_gbk_yylex_destroy (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + ob_expr_parser_gbk_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); + YY_CURRENT_BUFFER_LVALUE = NULL; + ob_expr_parser_gbk_yypop_buffer_state(yyscanner); + } + + /* Destroy the stack itself. */ + ob_expr_parser_gbk_yyfree(yyg->yy_buffer_stack ,yyscanner); + yyg->yy_buffer_stack = NULL; + + /* Destroy the start condition stack. */ + ob_expr_parser_gbk_yyfree(yyg->yy_start_stack ,yyscanner ); + yyg->yy_start_stack = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * ob_expr_parser_gbk_yylex() is called, initialization will occur. */ + yy_init_globals( yyscanner); + + /* Destroy the main struct (reentrant only). */ + ob_expr_parser_gbk_yyfree ( yyscanner , yyscanner ); + yyscanner = NULL; + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +#define YYTABLES_NAME "yytables" + +#line 268 "ob_expr_parser_gbk.l" + + + +inline void *ob_expr_parser_gbk_yyalloc(size_t bytes,void *yyscanner) +{ + void *ptr_ret = NULL; + ObExprParseResult *p = ob_expr_parser_gbk_yyget_extra(yyscanner); + if (OB_ISNULL(p)) { + // print err into msg buffer later + } else { + ptr_ret = obproxy_parse_malloc(bytes, p->malloc_pool_); + } + return ptr_ret; +} + +inline void *ob_expr_parser_gbk_yyrealloc(void *ptr,size_t bytes,void *yyscanner) +{ + void *ptr_ret = NULL; + ObExprParseResult *p = ob_expr_parser_gbk_yyget_extra(yyscanner); + if (OB_ISNULL(p)) { + // print err into msg buffer later + } else { + ptr_ret = obproxy_parse_realloc(ptr, bytes, p->malloc_pool_); + } + return ptr_ret; + +} + +inline void ob_expr_parser_gbk_yyfree(void *ptr,void *yyscanner) +{ + // Do nothing -- we leave it to the garbage collector. + obproxy_parse_free(ptr); +} + +inline void store_expr_str(char* str, int64_t str_len, char*end_ptr, void *yyscanner) +{ + YYSTYPE *lval = ob_expr_parser_gbk_yyget_lval(yyscanner); + if (OB_ISNULL(lval)) { + // do nothing + } else { + lval->str.str_ = str; + lval->str.end_ptr_ = end_ptr; + lval->str.str_len_ = str_len; + } +} + +inline void store_pos_place_holder(char *str, void *yyscanner) +{ + YYSTYPE *lval = ob_expr_parser_gbk_yyget_lval(yyscanner); + if (OB_ISNULL(lval)) { + // do nothing + } else { + errno = 0; + lval->num = strtoll(str, NULL, 10); + if (0 != errno) { + lval->num = 0; + } + } +} + +/* A Bison parser, made by GNU Bison 2.4.1. */ + +/* Skeleton interface for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + + +#ifndef YY_OBEXPR_OB_EXPR_PARSER_TAB_H_INCLUDED +# define YY_OBEXPR_OB_EXPR_PARSER_TAB_H_INCLUDED +/* Debug traces. */ +#ifndef OBEXPR_UTF8_DEBUG +# if defined YYDEBUG +#if YYDEBUG +# define OBEXPR_UTF8_DEBUG 1 +# else +# define OBEXPR_UTF8_DEBUG 0 +# endif +# else /* ! defined YYDEBUG */ +# define OBEXPR_UTF8_DEBUG 0 +# endif /* ! defined YYDEBUG */ +#endif /* ! defined OBEXPR_UTF8_DEBUG */ +#if OBEXPR_UTF8_DEBUG +extern int ob_expr_parser_gbk_yydebug; +#endif +/* Tokens. */ +#ifndef OBEXPRTOKENTYPE +# define OBEXPRTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum obexprtokentype { + DUMMY_SELECT_CLAUSE = 258, + DUMMY_INSERT_CLAUSE = 259, + WHERE = 260, + AS = 261, + VALUES = 262, + SET = 263, + END_WHERE = 264, + JOIN = 265, + AND_OP = 266, + OR_OP = 267, + IN = 268, + ON = 269, + BETWEEN = 270, + IS = 271, + TOKEN_NULL = 272, + NOT = 273, + COMP_EQ = 274, + COMP_NSEQ = 275, + COMP_GE = 276, + COMP_GT = 277, + COMP_LE = 278, + COMP_LT = 279, + COMP_NE = 280, + PLACE_HOLDER = 281, + END_P = 282, + ERROR = 283, + IGNORED_WORD = 284, + NAME_OB = 285, + STR_VAL = 286, + ROW_ID = 287, + REVERSED_EXPR_FUNC = 288, + INT_VAL = 289, + POS_PLACE_HOLDER = 290 + }; +#endif + + + +#if ! defined OBEXPRSTYPE && ! defined OBEXPRSTYPE_IS_DECLARED +typedef union OBEXPRSTYPE +{ + + + int64_t num; + ObProxyParseString str; + ObProxyFunctionType func; + ObProxyOperatorType operator; + ObProxyTokenNode *node; + ObProxyTokenList *list; + ObProxyRelationExpr *relation; + + + +} OBEXPRSTYPE; +# define OBEXPRSTYPE_IS_TRIVIAL 1 +# define obexprstype OBEXPRSTYPE /* obsolescent; will be withdrawn */ +# define OBEXPRSTYPE_IS_DECLARED 1 +#endif + + + +#if ! defined OBEXPRLTYPE && ! defined OBEXPRLTYPE_IS_DECLARED +typedef struct OBEXPRLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} OBEXPRLTYPE; +# define obexprltype OBEXPRLTYPE /* obsolescent; will be withdrawn */ +# define OBEXPRLTYPE_IS_DECLARED 1 +# define OBEXPRLTYPE_IS_TRIVIAL 1 +#endif + + + +#endif + diff --git a/src/obproxy/opsql/expr_parser/ob_expr_parser_gbk_lex.h b/src/obproxy/opsql/expr_parser/ob_expr_parser_gbk_lex.h new file mode 100644 index 0000000000000000000000000000000000000000..6f76d34d39f32c656dab7dd22e0d8553b02afca3 --- /dev/null +++ b/src/obproxy/opsql/expr_parser/ob_expr_parser_gbk_lex.h @@ -0,0 +1,349 @@ +#ifndef ob_expr_parser_gbk_yyHEADER_H +#define ob_expr_parser_gbk_yyHEADER_H 1 +#define ob_expr_parser_gbk_yyIN_HEADER 1 + +#line 6 "ob_expr_parser_gbk_lex.h" + +#line 8 "ob_expr_parser_gbk_lex.h" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +void ob_expr_parser_gbk_yyrestart (FILE *input_file ,yyscan_t yyscanner ); +void ob_expr_parser_gbk_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +YY_BUFFER_STATE ob_expr_parser_gbk_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); +void ob_expr_parser_gbk_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void ob_expr_parser_gbk_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void ob_expr_parser_gbk_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +void ob_expr_parser_gbk_yypop_buffer_state (yyscan_t yyscanner ); + +YY_BUFFER_STATE ob_expr_parser_gbk_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); +YY_BUFFER_STATE ob_expr_parser_gbk_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +YY_BUFFER_STATE ob_expr_parser_gbk_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); + +void *ob_expr_parser_gbk_yyalloc (yy_size_t ,yyscan_t yyscanner ); +void *ob_expr_parser_gbk_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); +void ob_expr_parser_gbk_yyfree (void * ,yyscan_t yyscanner ); + +/* Begin user sect3 */ + +#define ob_expr_parser_gbk_yywrap(n) 1 +#define YY_SKIP_YYWRAP + +#define yytext_ptr yytext_r + +#ifdef YY_HEADER_EXPORT_START_CONDITIONS +#define INITIAL 0 +#define in_c_comment 1 +#define sq 2 +#define dq 3 +#define bt 4 + +#endif + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +int ob_expr_parser_gbk_yylex_init (yyscan_t* scanner); + +int ob_expr_parser_gbk_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int ob_expr_parser_gbk_yylex_destroy (yyscan_t yyscanner ); + +int ob_expr_parser_gbk_yyget_debug (yyscan_t yyscanner ); + +void ob_expr_parser_gbk_yyset_debug (int debug_flag ,yyscan_t yyscanner ); + +YY_EXTRA_TYPE ob_expr_parser_gbk_yyget_extra (yyscan_t yyscanner ); + +void ob_expr_parser_gbk_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); + +FILE *ob_expr_parser_gbk_yyget_in (yyscan_t yyscanner ); + +void ob_expr_parser_gbk_yyset_in (FILE * in_str ,yyscan_t yyscanner ); + +FILE *ob_expr_parser_gbk_yyget_out (yyscan_t yyscanner ); + +void ob_expr_parser_gbk_yyset_out (FILE * out_str ,yyscan_t yyscanner ); + +int ob_expr_parser_gbk_yyget_leng (yyscan_t yyscanner ); + +char *ob_expr_parser_gbk_yyget_text (yyscan_t yyscanner ); + +int ob_expr_parser_gbk_yyget_lineno (yyscan_t yyscanner ); + +void ob_expr_parser_gbk_yyset_lineno (int line_number ,yyscan_t yyscanner ); + +OBEXPRSTYPE * ob_expr_parser_gbk_yyget_lval (yyscan_t yyscanner ); + +void ob_expr_parser_gbk_yyset_lval (OBEXPRSTYPE * yylval_param ,yyscan_t yyscanner ); + + OBEXPRLTYPE *ob_expr_parser_gbk_yyget_lloc (yyscan_t yyscanner ); + + void ob_expr_parser_gbk_yyset_lloc (OBEXPRLTYPE * yylloc_param ,yyscan_t yyscanner ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int ob_expr_parser_gbk_yywrap (yyscan_t yyscanner ); +#else +extern int ob_expr_parser_gbk_yywrap (yyscan_t yyscanner ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int ob_expr_parser_gbk_yylex \ + (OBEXPRSTYPE * yylval_param,OBEXPRLTYPE * yylloc_param ,yyscan_t yyscanner); + +#define YY_DECL int ob_expr_parser_gbk_yylex \ + (OBEXPRSTYPE * yylval_param, OBEXPRLTYPE * yylloc_param , yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +#undef YY_NEW_FILE +#undef YY_FLUSH_BUFFER +#undef yy_set_bol +#undef yy_new_buffer +#undef yy_set_interactive +#undef YY_DO_BEFORE_ACTION + +#ifdef YY_DECL_IS_OURS +#undef YY_DECL_IS_OURS +#undef YY_DECL +#endif + +#line 268 "ob_expr_parser_gbk.l" + + +#line 348 "ob_expr_parser_gbk_lex.h" +#undef ob_expr_parser_gbk_yyIN_HEADER +#endif /* ob_expr_parser_gbk_yyHEADER_H */ diff --git a/src/obproxy/opsql/expr_parser/ob_expr_parser_gbk_tab.c b/src/obproxy/opsql/expr_parser/ob_expr_parser_gbk_tab.c new file mode 100644 index 0000000000000000000000000000000000000000..41f0d84ca2b8e79c8e24a4cba8d676e3b7000382 --- /dev/null +++ b/src/obproxy/opsql/expr_parser/ob_expr_parser_gbk_tab.c @@ -0,0 +1,2684 @@ + +/* A Bison parser, made by GNU Bison 2.4.1. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.4.1" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 1 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + +/* Using locations. */ +#define YYLSP_NEEDED 1 + +/* Substitute the variable and function names. */ +#define YYSTYPE OBEXPRSTYPE +#define YYLTYPE OBEXPRLTYPE +#define yyparse ob_expr_parser_gbk_yyparse +#define yylex ob_expr_parser_gbk_yylex +#define yyerror ob_expr_parser_gbk_yyerror +#define yylval ob_expr_parser_gbk_yylval +#define yychar ob_expr_parser_gbk_yychar +#define yydebug ob_expr_parser_gbk_yydebug +#define yynerrs ob_expr_parser_gbk_yynerrs +#define yylloc ob_expr_parser_gbk_yylloc + +/* Copy the first part of user declarations. */ + + +#include +#include "opsql/ob_proxy_parse_define.h" +#include "opsql/expr_parser/ob_expr_parse_result.h" + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + + +#ifndef YY_OBEXPR_OB_EXPR_PARSER_TAB_H_INCLUDED +# define YY_OBEXPR_OB_EXPR_PARSER_TAB_H_INCLUDED +/* Debug traces. */ +#ifndef OBEXPR_UTF8_DEBUG +# if defined YYDEBUG +#if YYDEBUG +# define OBEXPR_UTF8_DEBUG 1 +# else +# define OBEXPR_UTF8_DEBUG 0 +# endif +# else /* ! defined YYDEBUG */ +# define OBEXPR_UTF8_DEBUG 0 +# endif /* ! defined YYDEBUG */ +#endif /* ! defined OBEXPR_UTF8_DEBUG */ +#if OBEXPR_UTF8_DEBUG +extern int ob_expr_parser_gbk_yydebug; +#endif +/* Tokens. */ +#ifndef OBEXPRTOKENTYPE +# define OBEXPRTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum obexprtokentype { + DUMMY_SELECT_CLAUSE = 258, + DUMMY_INSERT_CLAUSE = 259, + WHERE = 260, + AS = 261, + VALUES = 262, + SET = 263, + END_WHERE = 264, + JOIN = 265, + AND_OP = 266, + OR_OP = 267, + IN = 268, + ON = 269, + BETWEEN = 270, + IS = 271, + TOKEN_NULL = 272, + NOT = 273, + COMP_EQ = 274, + COMP_NSEQ = 275, + COMP_GE = 276, + COMP_GT = 277, + COMP_LE = 278, + COMP_LT = 279, + COMP_NE = 280, + PLACE_HOLDER = 281, + END_P = 282, + ERROR = 283, + IGNORED_WORD = 284, + NAME_OB = 285, + STR_VAL = 286, + ROW_ID = 287, + REVERSED_EXPR_FUNC = 288, + INT_VAL = 289, + POS_PLACE_HOLDER = 290 + }; +#endif + + + +#if ! defined OBEXPRSTYPE && ! defined OBEXPRSTYPE_IS_DECLARED +typedef union OBEXPRSTYPE +{ + + + int64_t num; + ObProxyParseString str; + ObProxyFunctionType func; + ObProxyOperatorType operator; + ObProxyTokenNode *node; + ObProxyTokenList *list; + ObProxyRelationExpr *relation; + + + +} OBEXPRSTYPE; +# define OBEXPRSTYPE_IS_TRIVIAL 1 +# define obexprstype OBEXPRSTYPE /* obsolescent; will be withdrawn */ +# define OBEXPRSTYPE_IS_DECLARED 1 +#endif + +#if ! defined OBEXPRLTYPE && ! defined OBEXPRLTYPE_IS_DECLARED +typedef struct OBEXPRLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} OBEXPRLTYPE; +# define obexprltype OBEXPRLTYPE /* obsolescent; will be withdrawn */ +# define OBEXPRLTYPE_IS_DECLARED 1 +# define OBEXPRLTYPE_IS_TRIVIAL 1 +#endif + + +#endif +/* Copy the second part of user declarations. */ + + +#include "ob_expr_parser_gbk_lex.h" +#define YYLEX_PARAM result->yyscan_info_ +extern void yyerror(YYLTYPE* yylloc, ObExprParseResult* p, char* s,...); +extern void *obproxy_parse_malloc(const size_t nbyte, void *malloc_pool); + +static inline bool is_equal(ObProxyParseString *l, ObProxyParseString *r) +{ + return NULL != l && NULL != r && l->str_len_ == r->str_len_ + && 0 == strncasecmp(l->str_, r->str_, l->str_len_); +} + +static inline void add_token(ObProxyTokenList *list, ObExprParseResult *result, ObProxyTokenNode *node) +{ + UNUSED(result); // use for perf later + if (OB_ISNULL(list) || OB_ISNULL(node)) { + // do nothing + } else { + if (TOKEN_COLUMN == node->type_) { + list->column_node_ = node; + } + if (NULL != list->tail_) { + list->tail_->next_ = node; + list->tail_ = node; + } + } +} + +// expr in (xxx,xxx,xxx) +static inline void add_token_list(ObProxyTokenList *list, ObProxyTokenList *next_list) +{ + if (OB_ISNULL(list) || OB_ISNULL(next_list)) { + } else if (NULL != list->tail_ + && NULL != next_list->head_ + && (TOKEN_INT_VAL == list->tail_->type_ || TOKEN_STR_VAL == list->tail_->type_ || TOKEN_FUNC == list->tail_->type_) + && (TOKEN_INT_VAL == next_list->head_->type_ || TOKEN_STR_VAL == next_list->head_->type_ || TOKEN_FUNC == next_list->head_->type_)) { + list->tail_->next_ = next_list->head_; + list->tail_ = next_list->head_; + list->tail_->next_ = NULL; + } +} + +static inline ObProxyFunctionType get_reverse_func(ObProxyFunctionType type) +{ + ObProxyFunctionType ret_type = type; + switch (type) { + case F_COMP_GE: + ret_type = F_COMP_LE; + break; + case F_COMP_GT: + ret_type = F_COMP_LT; + break; + case F_COMP_LE: + ret_type = F_COMP_GE; + break; + case F_COMP_LT: + ret_type = F_COMP_GT; + break; + default: + // do nothing + break; + } + return ret_type; +} + +static inline int64_t get_mask(ObProxyFunctionType type, ObProxyPartKeyLevel level) +{ + int64_t mask = 0; + int64_t flag = NO_BOUND_FLAG; + switch (type) { + case F_COMP_EQ: + case F_COMP_NSEQ: + flag = BOTH_BOUND_FLAG; + break; + case F_COMP_GE: + case F_COMP_GT: + flag = LOW_BOUND_FLAG; + break; + case F_COMP_LE: + case F_COMP_LT: + flag = HIGH_BOUND_FLAG; + break; + default: + break; + } + switch (level) { + case PART_KEY_LEVEL_ONE: + mask = GET_FIRST_PART_MASK(flag); + break; + case PART_KEY_LEVEL_TWO: + mask = GET_SUB_PART_MASK(flag); + break; + case PART_KEY_LEVEL_BOTH: + mask = GET_FIRST_PART_MASK(flag) | GET_SUB_PART_MASK(flag); + break; + default: + break; + } + return mask; +} + +static inline void set_part_key_column_idx(ObExprParseResult *result, ObProxyParseString *column_name) +{ + int64_t i = 0; + for (i = 0; i < result->part_key_info_.key_num_; ++i) { + if (is_equal(column_name, &result->part_key_info_.part_keys_[i].name_)) { + result->part_key_info_.part_keys_[i].idx_ = result->column_idx_; + result->part_key_info_.part_keys_[i].is_exist_in_sql_ = true; + } + } +} + +static inline void init_part_key_all_match(ObExprParseResult *result) +{ + for (int64_t i = 0; i < result->part_key_info_.key_num_; ++i) { + result->part_key_info_.part_keys_[i].is_exist_in_sql_ = true; + } +} + +#define malloc_node(node, result, type) \ + do { \ + if (OB_ISNULL(node = ((ObProxyTokenNode *)obproxy_parse_malloc(sizeof(ObProxyTokenNode), \ + result->malloc_pool_)))) { \ + YYABORT; \ + } else { \ + node->type_ = type; \ + node->child_ = NULL; \ + node->next_ = NULL; \ + } \ + } while(0) \ + +#define malloc_list(list, result, node) \ + do { \ + if (OB_ISNULL(list = ((ObProxyTokenList *)obproxy_parse_malloc(sizeof(ObProxyTokenList), \ + result->malloc_pool_)))) { \ + YYABORT; \ + } else if (OB_ISNULL(node)) { \ + list->column_node_ = NULL; \ + } else { \ + if (TOKEN_COLUMN == node->type_) { \ + list->column_node_ = node; \ + } else { \ + list->column_node_ = NULL; \ + } \ + list->head_ = node; \ + list->tail_ = node; \ + } \ + } while(0) \ + +#define check_and_add_relation(result, relation) \ + do { \ + if (NULL == relation) { \ + } else { \ + if (relation->level_ != PART_KEY_LEVEL_ZERO) { \ + if (result->relation_info_.relation_num_ < OBPROXY_MAX_RELATION_NUM) { \ + result->relation_info_.relations_[result->relation_info_.relation_num_++] = relation; \ + } else { \ + /* YYACCEPT; */ \ + } \ + } \ + } \ + } while(0) \ + +static int64_t get_part_key_idx(ObProxyParseString *db_name, + ObProxyParseString *table_name, + ObProxyParseString *column_name, + ObExprParseResult *result) +{ + int64_t part_key_idx = IDX_NO_PART_KEY_COLUMN; + + if (result->part_key_info_.key_num_ > 0) { + if (NULL != db_name && !is_equal(db_name, &result->table_info_.database_name_)) { + part_key_idx = IDX_NO_PART_KEY_COLUMN; + } else if (NULL != table_name + && !is_equal(table_name, &result->table_info_.table_name_) + && !is_equal(table_name, &result->table_info_.alias_name_)) { + part_key_idx = IDX_NO_PART_KEY_COLUMN; + } else if (NULL != column_name) { + int64_t i = 0; + for (i = 0; i < result->part_key_info_.key_num_ && part_key_idx < 0; ++i) { + if (is_equal(column_name, &result->part_key_info_.part_keys_[i].name_)) { + part_key_idx = i; + break; + } + } + } + } + return part_key_idx; +} +static inline void add_relation(ObExprParseResult *result, + ObProxyTokenList *left_value, + ObProxyFunctionType type, + ObProxyTokenList *right_value) +{ + if (result->all_relation_info_.relation_num_ < OBPROXY_MAX_RELATION_NUM) { + ObProxyRelationExpr *relation = NULL; + ObProxyTokenList *tmp_left = NULL; + ObProxyTokenList *tmp_right = NULL; + ObProxyFunctionType tmp_type = F_NONE; + ObProxyPartKeyLevel tmp_level = PART_KEY_LEVEL_ZERO; + + if (NULL != left_value->column_node_ + && TOKEN_COLUMN == left_value->column_node_->type_) { + tmp_left = left_value; + tmp_right = right_value; + tmp_type = type; + } else if (NULL != right_value->column_node_ + && TOKEN_COLUMN == right_value->column_node_->type_) { + tmp_left = right_value; + tmp_right = left_value; + tmp_type = get_reverse_func(type); + } + + if (NULL == tmp_left || NULL == tmp_right || F_COMP_NE == tmp_type) { + // will return null + } else if (OB_ISNULL(relation = ((ObProxyRelationExpr *)obproxy_parse_malloc( + sizeof(ObProxyRelationExpr), result->malloc_pool_)))) { + // will return null + } else { + relation->left_value_ = tmp_left; + relation->type_ = tmp_type; + relation->right_value_ = tmp_right; + relation->level_ = tmp_level; + + result->all_relation_info_.relations_[result->all_relation_info_.relation_num_++] = relation; + } + } +} + +static inline void set_relation_part_with_column_idx(int64_t idx_in_schema_columns, + ObExprParseResult *result, + ObProxyPartKeyLevel *level, + int64_t *first_part_column_idx, + int64_t *second_part_column_idx) +{ + if (OB_ISNULL(level) && OB_ISNULL(first_part_column_idx) && + OB_ISNULL(second_part_column_idx) && OB_ISNULL(result)) { + // do nothing + } else { + *level = PART_KEY_LEVEL_ZERO; + *first_part_column_idx = 0; + *second_part_column_idx = 0; + bool is_level_one = false; + bool is_level_two = false; + for (int i = 0; i < result->part_key_info_.key_num_; i++) { + // make sure the part_key exist in sql to avoid the uninitialized idx_ + if (idx_in_schema_columns == result->part_key_info_.part_keys_[i].idx_ && result->part_key_info_.part_keys_[i].is_exist_in_sql_) { + if (result->part_key_info_.part_keys_[i].level_ == PART_KEY_LEVEL_ONE) { + is_level_one = true; + *first_part_column_idx = result->part_key_info_.part_keys_[i].idx_in_part_columns_; + } else if (result->part_key_info_.part_keys_[i].level_ == PART_KEY_LEVEL_TWO) { + is_level_two = true; + *second_part_column_idx = result->part_key_info_.part_keys_[i].idx_in_part_columns_; + } + } + } + if (is_level_one) { + *level = PART_KEY_LEVEL_ONE; + } + if (is_level_two) { + *level = PART_KEY_LEVEL_TWO; + } + if (is_level_one && is_level_two) { + *level = PART_KEY_LEVEL_BOTH; + } + } +} + +static inline void set_relation_part_with_column_name(ObProxyParseString *column, + ObExprParseResult *result, + ObProxyPartKeyLevel *level, + int64_t *first_part_column_idx, + int64_t *second_part_column_idx) +{ + if (OB_ISNULL(column) + || OB_ISNULL(result) + || OB_ISNULL(level) + || OB_ISNULL(first_part_column_idx) + || OB_ISNULL(second_part_column_idx)) { + // do nothing + } else if (result->has_rowid_ + && is_equal_to_rowid(column)) { + // handle rowid + *level = PART_KEY_LEVEL_ONE; + *first_part_column_idx = 0; + *second_part_column_idx = 0; + } else { + *level = PART_KEY_LEVEL_ZERO; + *first_part_column_idx = 0; + *second_part_column_idx = 0; + bool is_level_one = false; + bool is_level_two = false; + for (int i = 0; i < result->part_key_info_.key_num_; i++) { + if (is_equal(&result->part_key_info_.part_keys_[i].name_, column)) { + if (result->part_key_info_.part_keys_[i].level_ == PART_KEY_LEVEL_ONE) { + is_level_one = true; + *first_part_column_idx = result->part_key_info_.part_keys_[i].idx_in_part_columns_; + } else if (result->part_key_info_.part_keys_[i].level_ == PART_KEY_LEVEL_TWO) { + is_level_two = true; + *second_part_column_idx = result->part_key_info_.part_keys_[i].idx_in_part_columns_; + } + } + } + if (is_level_one) { + *level = PART_KEY_LEVEL_ONE; + } + if (is_level_two) { + *level = PART_KEY_LEVEL_TWO; + } + if (is_level_one && is_level_two) { + *level = PART_KEY_LEVEL_BOTH; + } + } +} + + +static inline ObProxyRelationExpr *get_relation(ObExprParseResult *result, + ObProxyTokenList *left_value, + ObProxyFunctionType type, + ObProxyTokenList *right_value) +{ + ObProxyRelationExpr *relation = NULL; + ObProxyTokenList *tmp_left = NULL; + ObProxyTokenList *tmp_right = NULL; + ObProxyFunctionType tmp_type = F_NONE; + int64_t tmp_column_idx_ = -1; + ObProxyParseString *tmp_column = NULL; + + if (NULL != left_value->column_node_ + && TOKEN_COLUMN == left_value->column_node_->type_ + && left_value->column_node_->part_key_idx_ >= 0) { + tmp_left = left_value; + tmp_right = right_value; + tmp_type = type; + tmp_column_idx_ = left_value->column_node_->part_key_idx_; + tmp_column = &left_value->column_node_->column_name_; + } else if (NULL != right_value->column_node_ + && TOKEN_COLUMN == right_value->column_node_->type_ + && right_value->column_node_->part_key_idx_ >= 0) { + tmp_left = right_value; + tmp_right = left_value; + tmp_type = get_reverse_func(type); + tmp_column_idx_ = right_value->column_node_->part_key_idx_; + tmp_column = &right_value->column_node_->column_name_; + } + + if (NULL == tmp_left || NULL == tmp_right || F_COMP_NE == tmp_type) { + // will return null + } else if (OB_ISNULL(relation = ((ObProxyRelationExpr *)obproxy_parse_malloc( + sizeof(ObProxyRelationExpr), result->malloc_pool_)))) { + // will return null + } else { + relation->column_idx_ = tmp_column_idx_; + relation->left_value_ = tmp_left; + relation->type_ = tmp_type; + relation->right_value_ = tmp_right; + set_relation_part_with_column_name(tmp_column, + result, + &relation->level_, + &relation->first_part_column_idx_, + &relation->second_part_column_idx_); + } + return relation; +} + +static inline ObProxyRelationExpr *get_values_relation(ObExprParseResult *result, + ObProxyTokenList *right_value) +{ + ObProxyRelationExpr *relation = NULL; + if (NULL == right_value) { + // will return null + } else { + int64_t i = 0; + for (i = 0; i < result->part_key_info_.key_num_; ++i) { + // make sure the part_key exist in sql to avoid the uninitialized idx_ + if (result->values_list_idx_ == result->part_key_info_.part_keys_[i].idx_ && result->part_key_info_.part_keys_[i].is_exist_in_sql_) { + if (OB_ISNULL(relation = ((ObProxyRelationExpr *)obproxy_parse_malloc( + sizeof(ObProxyRelationExpr), result->malloc_pool_)))) { + } else { + relation->column_idx_ = i; + relation->type_ = F_COMP_EQ; + relation->right_value_ = right_value; + relation->left_value_ = NULL; + set_relation_part_with_column_idx(result->values_list_idx_, + result, + &relation->level_, + &relation->first_part_column_idx_, + &relation->second_part_column_idx_); + } + break; + } + } + } + return relation; +} + +static inline void add_left_relation_value(ObExprParseResult *result, + ObProxyTokenList *left_value) +{ + ObProxyRelationExpr *relation = NULL; + if (NULL == left_value) { + // will return + } else if (result->all_relation_info_.relation_num_ >= OBPROXY_MAX_RELATION_NUM) { + // do nothing + } else if (OB_ISNULL(relation = ((ObProxyRelationExpr *)obproxy_parse_malloc( + sizeof(ObProxyRelationExpr), result->malloc_pool_)))) { + } else { + relation->type_ = F_COMP_EQ; + relation->left_value_ = left_value; + relation->right_value_ = NULL; + result->all_relation_info_.relations_[result->all_relation_info_.relation_num_++] = relation; + } +} + +static inline void add_right_relation_value(ObExprParseResult *result, + ObProxyTokenList *right_value) +{ + if (NULL == right_value) { + // will return + } else if (result->all_relation_info_.relation_num_ >= OBPROXY_MAX_RELATION_NUM) { + // do nohting + } else if (result->all_relation_info_.right_value_num_ >= result->all_relation_info_.relation_num_) { + // ignore + } else if (OB_ISNULL(result->all_relation_info_.relations_[result->all_relation_info_.right_value_num_])) { + } else { + ObProxyRelationExpr *relation = result->all_relation_info_.relations_[result->all_relation_info_.right_value_num_++]; + relation->type_ = F_COMP_EQ; + relation->right_value_ = right_value; + } +} + + + + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int yyi) +#else +static int +YYID (yyi) + int yyi; +#endif +{ + return yyi; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \ + && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; + YYLTYPE yyls_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + + 2 * YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 17 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 242 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 48 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 24 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 83 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 149 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 290 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 47, 2, 2, 2, 45, 46, 2, + 39, 36, 43, 41, 40, 42, 38, 44, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 37, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint16 yyprhs[] = +{ + 0, 0, 3, 6, 9, 13, 16, 21, 23, 25, + 27, 29, 31, 33, 36, 40, 43, 48, 52, 57, + 63, 70, 72, 76, 82, 86, 92, 96, 102, 108, + 114, 120, 124, 129, 131, 133, 135, 137, 139, 141, + 143, 145, 149, 151, 153, 156, 157, 161, 165, 167, + 169, 173, 179, 181, 186, 191, 193, 195, 197, 199, + 201, 203, 205, 207, 209, 211, 213, 215, 220, 225, + 229, 231, 235, 241, 242, 246, 248, 252, 254, 256, + 260, 262, 266, 267 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 49, 0, -1, 3, 50, -1, 4, 64, -1, 5, + 55, 51, -1, 52, 51, -1, 52, 5, 55, 51, + -1, 1, -1, 9, -1, 36, -1, 37, -1, 27, + -1, 53, -1, 52, 53, -1, 54, 14, 55, -1, + 10, 30, -1, 10, 30, 38, 30, -1, 10, 30, + 30, -1, 10, 30, 6, 30, -1, 10, 30, 38, + 30, 30, -1, 10, 30, 38, 30, 6, 30, -1, + 56, -1, 55, 11, 56, -1, 39, 55, 11, 56, + 36, -1, 55, 12, 56, -1, 39, 55, 12, 56, + 36, -1, 59, 57, 59, -1, 59, 57, 39, 59, + 36, -1, 39, 59, 57, 59, 36, -1, 59, 13, + 39, 58, 36, -1, 59, 15, 59, 11, 59, -1, + 59, 16, 17, -1, 59, 16, 18, 17, -1, 19, + -1, 20, -1, 21, -1, 22, -1, 23, -1, 24, + -1, 25, -1, 59, -1, 58, 40, 59, -1, 60, + -1, 62, -1, 60, 62, -1, -1, 60, 40, 60, + -1, 61, 40, 60, -1, 32, -1, 30, -1, 30, + 38, 30, -1, 30, 38, 30, 38, 30, -1, 33, + -1, 30, 39, 60, 36, -1, 30, 39, 61, 36, + -1, 34, -1, 31, -1, 63, -1, 26, -1, 35, + -1, 41, -1, 42, -1, 43, -1, 44, -1, 45, + -1, 46, -1, 47, -1, 66, 7, 65, 51, -1, + 8, 70, 71, 51, -1, 14, 55, 51, -1, 50, + -1, 39, 69, 36, -1, 65, 40, 39, 69, 36, + -1, -1, 39, 67, 36, -1, 68, -1, 67, 40, + 68, -1, 30, -1, 59, -1, 69, 40, 59, -1, + 56, -1, 70, 40, 56, -1, -1, 5, 55, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 475, 475, 476, 478, 479, 480, 481, 483, 484, + 485, 486, 488, 489, 491, 493, 494, 495, 496, 497, + 498, 500, 501, 502, 503, 504, 506, 507, 508, 509, + 510, 520, 521, 523, 524, 525, 526, 527, 528, 529, + 531, 532, 534, 536, 537, 539, 540, 541, 544, 551, + 557, 563, 569, 574, 580, 586, 587, 588, 589, 595, + 601, 602, 603, 604, 605, 606, 607, 609, 610, 611, + 612, 614, 618, 623, 624, 629, 633, 638, 644, 654, + 664, 665, 667, 668 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "DUMMY_SELECT_CLAUSE", + "DUMMY_INSERT_CLAUSE", "WHERE", "AS", "VALUES", "SET", "END_WHERE", + "JOIN", "AND_OP", "OR_OP", "IN", "ON", "BETWEEN", "IS", "TOKEN_NULL", + "NOT", "COMP_EQ", "COMP_NSEQ", "COMP_GE", "COMP_GT", "COMP_LE", + "COMP_LT", "COMP_NE", "PLACE_HOLDER", "END_P", "ERROR", "IGNORED_WORD", + "NAME_OB", "STR_VAL", "ROW_ID", "REVERSED_EXPR_FUNC", "INT_VAL", + "POS_PLACE_HOLDER", "')'", "';'", "'.'", "'('", "','", "'+'", "'-'", + "'*'", "'/'", "'%'", "'&'", "'!'", "$accept", "start", "select_root", + "end_flag", "join_expr_list", "join_on_expr", "join_expr", "cond_expr", + "bool_pri", "comp", "in_expr_list", "expr", "token_list", + "func_param_list", "token", "operator", "insert_root", + "values_expr_lists", "opt_column_list", "column_list", "opt_column", + "values_expr_list", "set_expr", "opt_where_clause", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 41, 59, 46, 40, + 44, 43, 45, 42, 47, 37, 38, 33 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 48, 49, 49, 50, 50, 50, 50, 51, 51, + 51, 51, 52, 52, 53, 54, 54, 54, 54, 54, + 54, 55, 55, 55, 55, 55, 56, 56, 56, 56, + 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, + 58, 58, 59, 60, 60, 61, 61, 61, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 63, 63, 63, 63, 63, 63, 63, 64, 64, 64, + 64, 65, 65, 66, 66, 67, 67, 68, 69, 69, + 70, 70, 71, 71 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 2, 2, 3, 2, 4, 1, 1, 1, + 1, 1, 1, 2, 3, 2, 4, 3, 4, 5, + 6, 1, 3, 5, 3, 5, 3, 5, 5, 5, + 5, 3, 4, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 1, 1, 2, 0, 3, 3, 1, 1, + 3, 5, 1, 4, 4, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 4, 4, 3, + 1, 3, 5, 0, 3, 1, 3, 1, 1, 3, + 1, 3, 0, 2 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 0, 0, 0, 0, 7, 0, 0, 2, 0, 12, + 0, 0, 0, 0, 70, 3, 0, 1, 58, 49, + 56, 48, 52, 55, 59, 0, 60, 61, 62, 63, + 64, 65, 66, 0, 21, 0, 42, 43, 57, 15, + 0, 8, 11, 9, 10, 5, 13, 0, 0, 80, + 82, 0, 77, 0, 75, 0, 0, 45, 0, 0, + 0, 0, 4, 0, 0, 0, 33, 34, 35, 36, + 37, 38, 39, 0, 44, 0, 17, 0, 0, 14, + 0, 0, 0, 0, 69, 74, 0, 0, 0, 50, + 0, 0, 0, 0, 0, 22, 24, 0, 0, 31, + 0, 0, 26, 18, 16, 6, 0, 83, 81, 68, + 76, 78, 0, 0, 67, 0, 53, 0, 54, 0, + 22, 24, 26, 0, 40, 0, 32, 0, 0, 19, + 0, 71, 0, 0, 51, 46, 47, 23, 25, 28, + 29, 0, 30, 27, 20, 79, 0, 41, 72 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = +{ + -1, 3, 7, 45, 8, 9, 10, 33, 34, 73, + 123, 35, 36, 91, 37, 38, 15, 88, 16, 53, + 54, 112, 50, 83 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -54 +static const yytype_int16 yypact[] = +{ + 16, 77, 8, 7, -54, 109, -5, -54, 22, -54, + 24, 131, 109, 38, -54, -54, 44, -54, -54, 6, + -54, -54, -54, -54, -54, 109, -54, -54, -54, -54, + -54, -54, -54, 68, -54, 210, 175, -54, -54, 5, + 109, -54, -54, -54, -54, -54, -54, 109, 175, -54, + 0, 68, -54, -28, -54, 15, 43, 175, 79, 210, + 131, 131, -54, 36, 175, 75, -54, -54, -54, -54, + -54, -54, -54, 153, -54, 53, -54, 56, 68, 85, + 217, 109, 131, 62, -54, -54, 38, 175, -3, 50, + 87, -10, 131, 131, 153, -54, -54, 175, 83, -54, + 86, 175, -54, -54, 11, -54, 175, 85, -54, -54, + -54, -54, 10, 67, -54, 80, -54, 175, -54, 175, + 73, 76, 78, 21, -54, 175, -54, 88, 81, -54, + 78, -54, 175, 175, -54, 175, 175, -54, -54, -54, + -54, 175, -54, -54, -54, -54, 27, -54, -54 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -54, -54, 113, -23, -54, 117, -54, -11, -8, -38, + -54, -25, -53, -54, -34, -54, -54, -54, -54, -54, + 40, 3, -54, -54 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -74 +static const yytype_int16 yytable[] = +{ + 59, 51, 74, 49, 90, 81, 41, 17, 85, 4, + 62, 75, 86, 5, 58, -73, 11, 128, 6, 1, + 2, 94, 12, 80, 42, 39, 118, 40, 84, 78, + 119, 41, 6, 43, 44, 76, 79, 113, 47, 98, + 82, 129, 106, 77, 56, 57, 131, 13, 102, 42, + 132, 55, 95, 96, 87, 105, 74, 140, 43, 44, + 109, 141, 111, 148, 135, 114, 136, 132, 52, 122, + 107, 41, 124, 89, 108, 97, 127, 41, 4, 60, + 61, 130, 5, 103, 120, 121, 104, 6, 115, 42, + 92, 93, 99, 100, 125, 42, 60, 61, 43, 44, + 142, 74, 74, 126, 43, 44, 133, 145, 111, 137, + 134, 144, 138, 18, 139, 14, 147, 19, 20, 21, + 22, 23, 24, 116, 143, 46, 110, 117, 26, 27, + 28, 29, 30, 31, 32, 18, 146, 0, 0, 19, + 20, 21, 22, 23, 24, 0, 0, 0, 25, 0, + 26, 27, 28, 29, 30, 31, 32, 18, 0, 0, + 0, 19, 20, 21, 22, 23, 24, 0, 0, 0, + 48, 0, 26, 27, 28, 29, 30, 31, 32, 18, + 0, 0, 0, 19, 20, 21, 22, 23, 24, 0, + 0, 0, 101, 0, 26, 27, 28, 29, 30, 31, + 32, 18, 0, 0, 0, 19, 20, 21, 22, 23, + 24, 0, 0, 0, 0, 0, 26, 27, 28, 29, + 30, 31, 32, 63, 0, 64, 65, 0, 0, 66, + 67, 68, 69, 70, 71, 72, 66, 67, 68, 69, + 70, 71, 72 +}; + +static const yytype_int16 yycheck[] = +{ + 25, 12, 36, 11, 57, 5, 9, 0, 36, 1, + 33, 6, 40, 5, 25, 7, 8, 6, 10, 3, + 4, 59, 14, 48, 27, 30, 36, 5, 51, 40, + 40, 9, 10, 36, 37, 30, 47, 40, 14, 64, + 40, 30, 80, 38, 38, 39, 36, 39, 73, 27, + 40, 7, 60, 61, 39, 78, 90, 36, 36, 37, + 83, 40, 87, 36, 117, 88, 119, 40, 30, 94, + 81, 9, 97, 30, 82, 39, 101, 9, 1, 11, + 12, 106, 5, 30, 92, 93, 30, 10, 38, 27, + 11, 12, 17, 18, 11, 27, 11, 12, 36, 37, + 125, 135, 136, 17, 36, 37, 39, 132, 133, 36, + 30, 30, 36, 26, 36, 2, 141, 30, 31, 32, + 33, 34, 35, 36, 36, 8, 86, 40, 41, 42, + 43, 44, 45, 46, 47, 26, 133, -1, -1, 30, + 31, 32, 33, 34, 35, -1, -1, -1, 39, -1, + 41, 42, 43, 44, 45, 46, 47, 26, -1, -1, + -1, 30, 31, 32, 33, 34, 35, -1, -1, -1, + 39, -1, 41, 42, 43, 44, 45, 46, 47, 26, + -1, -1, -1, 30, 31, 32, 33, 34, 35, -1, + -1, -1, 39, -1, 41, 42, 43, 44, 45, 46, + 47, 26, -1, -1, -1, 30, 31, 32, 33, 34, + 35, -1, -1, -1, -1, -1, 41, 42, 43, 44, + 45, 46, 47, 13, -1, 15, 16, -1, -1, 19, + 20, 21, 22, 23, 24, 25, 19, 20, 21, 22, + 23, 24, 25 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 3, 4, 49, 1, 5, 10, 50, 52, 53, + 54, 8, 14, 39, 50, 64, 66, 0, 26, 30, + 31, 32, 33, 34, 35, 39, 41, 42, 43, 44, + 45, 46, 47, 55, 56, 59, 60, 62, 63, 30, + 5, 9, 27, 36, 37, 51, 53, 14, 39, 56, + 70, 55, 30, 67, 68, 7, 38, 39, 55, 59, + 11, 12, 51, 13, 15, 16, 19, 20, 21, 22, + 23, 24, 25, 57, 62, 6, 30, 38, 55, 55, + 59, 5, 40, 71, 51, 36, 40, 39, 65, 30, + 60, 61, 11, 12, 57, 56, 56, 39, 59, 17, + 18, 39, 59, 30, 30, 51, 57, 55, 56, 51, + 68, 59, 69, 40, 51, 38, 36, 40, 36, 40, + 56, 56, 59, 58, 59, 11, 17, 59, 6, 30, + 59, 36, 40, 39, 30, 60, 60, 36, 36, 36, + 36, 40, 59, 36, 30, 59, 69, 59, 36 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (&yylloc, result, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) +#else +# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value, Location, result); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, ObExprParseResult* result) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, result) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; + YYLTYPE const * const yylocationp; + ObExprParseResult* result; +#endif +{ + if (!yyvaluep) + return; + YYUSE (yylocationp); + YYUSE (result); +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, ObExprParseResult* result) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, result) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; + YYLTYPE const * const yylocationp; + ObExprParseResult* result; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + YY_LOCATION_PRINT (yyoutput, *yylocationp); + YYFPRINTF (yyoutput, ": "); + yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, result); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +#else +static void +yy_stack_print (yybottom, yytop) + yytype_int16 *yybottom; + yytype_int16 *yytop; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, ObExprParseResult* result) +#else +static void +yy_reduce_print (yyvsp, yylsp, yyrule, result) + YYSTYPE *yyvsp; + YYLTYPE *yylsp; + int yyrule; + ObExprParseResult* result; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + , &(yylsp[(yyi + 1) - (yynrhs)]) , result); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, yylsp, Rule, result); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, ObExprParseResult* result) +#else +static void +yydestruct (yymsg, yytype, yyvaluep, yylocationp, result) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; + YYLTYPE *yylocationp; + ObExprParseResult* result; +#endif +{ + YYUSE (yyvaluep); + YYUSE (yylocationp); + YYUSE (result); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + +/* Prevent warnings from -Wmissing-prototypes. */ +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (ObExprParseResult* result); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + + + +/*-------------------------. +| yyparse or yypush_parse. | +`-------------------------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (ObExprParseResult* result) +#else +int +yyparse (result) + ObExprParseResult* result; +#endif +#endif +{ +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Location data for the lookahead symbol. */ +YYLTYPE yylloc; + + /* Number of syntax errors so far. */ + int yynerrs; + + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + `yyss': related to states. + `yyvs': related to semantic values. + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + /* The location stack. */ + YYLTYPE yylsa[YYINITDEPTH]; + YYLTYPE *yyls; + YYLTYPE *yylsp; + + /* The locations where the error started and ended. */ + YYLTYPE yyerror_range[2]; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + YYLTYPE yyloc; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yytoken = 0; + yyss = yyssa; + yyvs = yyvsa; + yyls = yylsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + if (SELECT_STMT_PARSE_MODE == result->parse_mode_) { + yychar = DUMMY_SELECT_CLAUSE; + } else if (INSERT_STMT_PARSE_MODE == result->parse_mode_) { + yychar = DUMMY_INSERT_CLAUSE; + } + + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + yyssp = yyss; + yyvsp = yyvs; + yylsp = yyls; + +#if YYLTYPE_IS_TRIVIAL + /* Initialize the default location before parsing starts. */ + yylloc.first_line = yylloc.last_line = 1; + yylloc.first_column = yylloc.last_column = 1; +#endif + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + YYLTYPE *yyls1 = yyls; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yyls1, yysize * sizeof (*yylsp), + &yystacksize); + + yyls = yyls1; + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); + YYSTACK_RELOCATE (yyls_alloc, yyls); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + yylsp = yyls + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + *++yylsp = yylloc; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + /* Default location. */ + YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 4: + + { YYACCEPT; ;} + break; + + case 5: + + { YYACCEPT; ;} + break; + + case 6: + + { YYACCEPT; ;} + break; + + case 7: + + { YYACCEPT; ;} + break; + + case 21: + + { check_and_add_relation(result, (yyvsp[(1) - (1)].relation)); ;} + break; + + case 22: + + { check_and_add_relation(result, (yyvsp[(3) - (3)].relation)); ;} + break; + + case 23: + + { check_and_add_relation(result, (yyvsp[(4) - (5)].relation)); ;} + break; + + case 24: + + { check_and_add_relation(result, (yyvsp[(3) - (3)].relation)); ;} + break; + + case 25: + + { check_and_add_relation(result, (yyvsp[(4) - (5)].relation)); ;} + break; + + case 26: + + { add_relation(result, (yyvsp[(1) - (3)].list), (yyvsp[(2) - (3)].func),(yyvsp[(3) - (3)].list)); (yyval.relation) = get_relation(result, (yyvsp[(1) - (3)].list), (yyvsp[(2) - (3)].func), (yyvsp[(3) - (3)].list)); ;} + break; + + case 27: + + { add_relation(result, (yyvsp[(1) - (5)].list), (yyvsp[(2) - (5)].func),(yyvsp[(4) - (5)].list)); (yyval.relation) = get_relation(result, (yyvsp[(1) - (5)].list), (yyvsp[(2) - (5)].func), (yyvsp[(4) - (5)].list)); ;} + break; + + case 28: + + { (yyval.relation) = get_relation(result, (yyvsp[(2) - (5)].list), (yyvsp[(3) - (5)].func), (yyvsp[(4) - (5)].list)); add_relation(result, (yyvsp[(2) - (5)].list), (yyvsp[(3) - (5)].func),(yyvsp[(4) - (5)].list)); ;} + break; + + case 29: + + { (yyval.relation) = get_relation(result, (yyvsp[(1) - (5)].list), F_COMP_EQ, (yyvsp[(4) - (5)].list)); add_relation(result, (yyvsp[(1) - (5)].list), F_COMP_EQ,(yyvsp[(4) - (5)].list)); ;} + break; + + case 30: + + { + (yyval.relation) = get_relation(result, (yyvsp[(1) - (5)].list), F_COMP_GE, (yyvsp[(3) - (5)].list)); + check_and_add_relation(result, (yyval.relation)); + add_relation(result, (yyvsp[(1) - (5)].list), F_COMP_GE, (yyvsp[(3) - (5)].list)); + (yyval.relation) = get_relation(result, (yyvsp[(1) - (5)].list), F_COMP_LE, (yyvsp[(5) - (5)].list)); + check_and_add_relation(result, (yyval.relation)); + add_relation(result, (yyvsp[(1) - (5)].list), F_COMP_LE, (yyvsp[(5) - (5)].list)); + (yyval.relation) = NULL; + ;} + break; + + case 31: + + { (yyval.relation) = NULL; ;} + break; + + case 32: + + { (yyval.relation) = NULL; ;} + break; + + case 33: + + { (yyval.func) = F_COMP_EQ; ;} + break; + + case 34: + + { (yyval.func) = F_COMP_NSEQ; ;} + break; + + case 35: + + { (yyval.func) = F_COMP_GE; ;} + break; + + case 36: + + { (yyval.func) = F_COMP_GT; ;} + break; + + case 37: + + { (yyval.func) = F_COMP_LE; ;} + break; + + case 38: + + { (yyval.func) = F_COMP_LT; ;} + break; + + case 39: + + { (yyval.func) = F_COMP_NE; ;} + break; + + case 40: + + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 41: + + { (yyval.list) = (yyvsp[(1) - (3)].list); add_token_list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); ;} + break; + + case 42: + + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 43: + + { malloc_list((yyval.list), result, (yyvsp[(1) - (1)].node)); ;} + break; + + case 44: + + { add_token((yyvsp[(1) - (2)].list), result, (yyvsp[(2) - (2)].node)); (yyval.list) = (yyvsp[(1) - (2)].list); ;} + break; + + case 45: + + { (yyval.list) = NULL; ;} + break; + + case 46: + + { add_token_list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); (yyval.list) = (yyvsp[(1) - (3)].list); ;} + break; + + case 47: + + { add_token_list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); (yyval.list) = (yyvsp[(1) - (3)].list); ;} + break; + + case 48: + + { + malloc_node((yyval.node), result, TOKEN_COLUMN); + (yyval.node)->part_key_idx_ = 0; + (yyval.node)->column_name_ = (yyvsp[(1) - (1)].str); + result->has_rowid_ = true; + ;} + break; + + case 49: + + { + malloc_node((yyval.node), result, TOKEN_COLUMN); + (yyval.node)->part_key_idx_ = get_part_key_idx(NULL, NULL, &(yyvsp[(1) - (1)].str), result); + (yyval.node)->column_name_ = (yyvsp[(1) - (1)].str); + ;} + break; + + case 50: + + { + malloc_node((yyval.node), result, TOKEN_COLUMN); + (yyval.node)->part_key_idx_ = get_part_key_idx(NULL, &(yyvsp[(1) - (3)].str), &(yyvsp[(3) - (3)].str), result); + (yyval.node)->column_name_ = (yyvsp[(3) - (3)].str); + ;} + break; + + case 51: + + { + malloc_node((yyval.node), result, TOKEN_COLUMN); + (yyval.node)->part_key_idx_ = get_part_key_idx(&(yyvsp[(1) - (5)].str), &(yyvsp[(3) - (5)].str), &(yyvsp[(5) - (5)].str), result); + (yyval.node)->column_name_ = (yyvsp[(5) - (5)].str); + ;} + break; + + case 52: + + { + malloc_node((yyval.node), result, TOKEN_FUNC); + (yyval.node)->str_value_ = (yyvsp[(1) - (1)].str); + ;} + break; + + case 53: + + { + malloc_node((yyval.node), result, TOKEN_FUNC); + (yyval.node)->str_value_ = (yyvsp[(1) - (4)].str); + (yyval.node)->child_ = (yyvsp[(3) - (4)].list); + ;} + break; + + case 54: + + { + malloc_node((yyval.node), result, TOKEN_FUNC); + (yyval.node)->str_value_ = (yyvsp[(1) - (4)].str); + (yyval.node)->child_ = (yyvsp[(3) - (4)].list); + ;} + break; + + case 55: + + { malloc_node((yyval.node), result, TOKEN_INT_VAL); (yyval.node)->int_value_ = (yyvsp[(1) - (1)].num); ;} + break; + + case 56: + + { malloc_node((yyval.node), result, TOKEN_STR_VAL); (yyval.node)->str_value_ = (yyvsp[(1) - (1)].str); ;} + break; + + case 57: + + { malloc_node((yyval.node), result, TOKEN_OPERATOR); (yyval.node)->operator_ = (yyvsp[(1) - (1)].operator); ;} + break; + + case 58: + + { + result->placeholder_list_idx_++; + malloc_node((yyval.node), result, TOKEN_PLACE_HOLDER); + (yyval.node)->placeholder_idx_ = result->placeholder_list_idx_ - 1; + ;} + break; + + case 59: + + { + malloc_node((yyval.node), result, TOKEN_PLACE_HOLDER); + (yyval.node)->placeholder_idx_ = (yyvsp[(1) - (1)].num); + ;} + break; + + case 60: + + { (yyval.operator) = OPT_ADD; ;} + break; + + case 61: + + { (yyval.operator) = OPT_MINUS; ;} + break; + + case 62: + + { (yyval.operator) = OPT_MUL; ;} + break; + + case 63: + + { (yyval.operator) = OPT_DIV; ;} + break; + + case 64: + + { (yyval.operator) = OPT_MOD; ;} + break; + + case 65: + + { (yyval.operator) = OPT_AND; ;} + break; + + case 66: + + { (yyval.operator) = OPT_NOT; ;} + break; + + case 67: + + { YYACCEPT; ;} + break; + + case 68: + + { YYACCEPT; ;} + break; + + case 69: + + { YYACCEPT; ;} + break; + + case 71: + + { + result->multi_param_values_++; + ;} + break; + + case 72: + + { + result->multi_param_values_++; + ;} + break; + + case 73: + + { init_part_key_all_match(result);;} + break; + + case 75: + + { + malloc_list((yyval.list), result, (yyvsp[(1) - (1)].node)); + add_left_relation_value(result, (yyval.list)); + ;} + break; + + case 76: + + { + malloc_list((yyval.list), result, (yyvsp[(3) - (3)].node)); + add_left_relation_value(result, (yyval.list)); + ;} + break; + + case 77: + + { + set_part_key_column_idx(result, &(yyvsp[(1) - (1)].str)); + result->column_idx_++; + malloc_node((yyval.node), result, TOKEN_COLUMN); + (yyval.node)->column_name_ = (yyvsp[(1) - (1)].str); + ;} + break; + + case 78: + + { + if (result->multi_param_values_ < 1) { + result->values_list_idx_ = 0; + result->all_relation_info_.right_value_num_ = 0; + ObProxyRelationExpr *relation = get_values_relation(result, (yyvsp[(1) - (1)].list)); + check_and_add_relation(result, relation); + add_right_relation_value(result, (yyvsp[(1) - (1)].list)); + } + ;} + break; + + case 79: + + { + if (result->multi_param_values_ < 1) { + result->values_list_idx_++; + ObProxyRelationExpr *relation = get_values_relation(result, (yyvsp[(3) - (3)].list)); + check_and_add_relation(result, relation); + add_right_relation_value(result, (yyvsp[(3) - (3)].list)); + } + ;} + break; + + case 80: + + { check_and_add_relation(result, (yyvsp[(1) - (1)].relation)); ;} + break; + + case 81: + + { check_and_add_relation(result, (yyvsp[(3) - (3)].relation)); ;} + break; + + case 83: + + {;} + break; + + + + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + *++yylsp = yyloc; + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (&yylloc, result, YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (&yylloc, result, yymsg); + } + else + { + yyerror (&yylloc, result, YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + yyerror_range[0] = yylloc; + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval, &yylloc, result); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + yyerror_range[0] = yylsp[1-yylen]; + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + yyerror_range[0] = *yylsp; + yydestruct ("Error: popping", + yystos[yystate], yyvsp, yylsp, result); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + *++yyvsp = yylval; + + yyerror_range[1] = yylloc; + /* Using YYLLOC is tempting, but would change the location of + the lookahead. YYLOC is available though. */ + YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2); + *++yylsp = yyloc; + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined(yyoverflow) || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (&yylloc, result, YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, &yylloc, result); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp, yylsp, result); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + + + +void yyerror(YYLTYPE* yylloc, ObExprParseResult* p, char* s, ...) +{ + // do nothing +} + +void ob_expr_gbk_parser_fatal_error(yyconst char *msg, yyscan_t yyscanner) +{ + fprintf(stderr, "FATAL ERROR:%s\n", msg); + ObExprParseResult *p = ob_expr_parser_gbk_yyget_extra(yyscanner); + if (OB_ISNULL(p)) { + fprintf(stderr, "unexpected null parse result\n"); + } else { + longjmp(p->jmp_buf_, 1);//the secord param must be non-zero value + } +} + +int ob_expr_parse_gbk_sql(ObExprParseResult* p, const char* buf, size_t len) +{ + int ret = OB_SUCCESS; + //obexprdebug = 1; + if (OB_ISNULL(p) || OB_ISNULL(buf) || OB_UNLIKELY(len <= 0)) { + ret = OB_INVALID_ARGUMENT; + // print err msg later + } else if (OB_FAIL(ob_expr_parser_gbk_yylex_init_extra(p, &(p->yyscan_info_)))) { + // print err msg later + } else { + int val = setjmp(p->jmp_buf_); + if (val) { + ret = OB_PARSER_ERR_PARSE_SQL; + } else { + ob_expr_parser_gbk_yy_scan_buffer((char *)buf, len, p->yyscan_info_); + if (OB_FAIL(ob_expr_parser_gbk_yyparse(p))) { + // print err msg later + } else { + // do nothing + } + } + } + + return ret; +} + diff --git a/src/obproxy/opsql/expr_parser/ob_expr_parser_gbk_tab.h b/src/obproxy/opsql/expr_parser/ob_expr_parser_gbk_tab.h new file mode 100644 index 0000000000000000000000000000000000000000..9c8c5a669c8466a29469930e3038696d2481dae1 --- /dev/null +++ b/src/obproxy/opsql/expr_parser/ob_expr_parser_gbk_tab.h @@ -0,0 +1,135 @@ + +/* A Bison parser, made by GNU Bison 2.4.1. */ + +/* Skeleton interface for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + + +#ifndef YY_OBEXPR_OB_EXPR_PARSER_TAB_H_INCLUDED +# define YY_OBEXPR_OB_EXPR_PARSER_TAB_H_INCLUDED +/* Debug traces. */ +#ifndef OBEXPR_UTF8_DEBUG +# if defined YYDEBUG +#if YYDEBUG +# define OBEXPR_UTF8_DEBUG 1 +# else +# define OBEXPR_UTF8_DEBUG 0 +# endif +# else /* ! defined YYDEBUG */ +# define OBEXPR_UTF8_DEBUG 0 +# endif /* ! defined YYDEBUG */ +#endif /* ! defined OBEXPR_UTF8_DEBUG */ +#if OBEXPR_UTF8_DEBUG +extern int ob_expr_parser_gbk_yydebug; +#endif +/* Tokens. */ +#ifndef OBEXPRTOKENTYPE +# define OBEXPRTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum obexprtokentype { + DUMMY_SELECT_CLAUSE = 258, + DUMMY_INSERT_CLAUSE = 259, + WHERE = 260, + AS = 261, + VALUES = 262, + SET = 263, + END_WHERE = 264, + JOIN = 265, + AND_OP = 266, + OR_OP = 267, + IN = 268, + ON = 269, + BETWEEN = 270, + IS = 271, + TOKEN_NULL = 272, + NOT = 273, + COMP_EQ = 274, + COMP_NSEQ = 275, + COMP_GE = 276, + COMP_GT = 277, + COMP_LE = 278, + COMP_LT = 279, + COMP_NE = 280, + PLACE_HOLDER = 281, + END_P = 282, + ERROR = 283, + IGNORED_WORD = 284, + NAME_OB = 285, + STR_VAL = 286, + ROW_ID = 287, + REVERSED_EXPR_FUNC = 288, + INT_VAL = 289, + POS_PLACE_HOLDER = 290 + }; +#endif + + + +#if ! defined OBEXPRSTYPE && ! defined OBEXPRSTYPE_IS_DECLARED +typedef union OBEXPRSTYPE +{ + + + int64_t num; + ObProxyParseString str; + ObProxyFunctionType func; + ObProxyOperatorType operator; + ObProxyTokenNode *node; + ObProxyTokenList *list; + ObProxyRelationExpr *relation; + + + +} OBEXPRSTYPE; +# define OBEXPRSTYPE_IS_TRIVIAL 1 +# define obexprstype OBEXPRSTYPE /* obsolescent; will be withdrawn */ +# define OBEXPRSTYPE_IS_DECLARED 1 +#endif + + + +#if ! defined OBEXPRLTYPE && ! defined OBEXPRLTYPE_IS_DECLARED +typedef struct OBEXPRLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} OBEXPRLTYPE; +# define obexprltype OBEXPRLTYPE /* obsolescent; will be withdrawn */ +# define OBEXPRLTYPE_IS_DECLARED 1 +# define OBEXPRLTYPE_IS_TRIVIAL 1 +#endif + + + +#endif diff --git a/src/obproxy/opsql/expr_parser/ob_expr_parser_utf8_lex.c b/src/obproxy/opsql/expr_parser/ob_expr_parser_utf8_lex.c index 911ee235c003552e9d1f259412473f5892e32c3d..c9ed9c7ba53cc6635f4c5f089b0bc1fe3c2a3e10 100644 --- a/src/obproxy/opsql/expr_parser/ob_expr_parser_utf8_lex.c +++ b/src/obproxy/opsql/expr_parser/ob_expr_parser_utf8_lex.c @@ -348,8 +348,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); yyg->yy_hold_char = *yy_cp; \ yyg->yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 57 -#define YY_END_OF_BUFFER 58 +#define YY_NUM_RULES 61 +#define YY_END_OF_BUFFER 62 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -357,30 +357,38 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[197] = +static yyconst flex_int16_t yy_accept[279] = { 0, - 30, 30, 0, 0, 0, 0, 0, 0, 0, 0, - 58, 56, 31, 31, 35, 46, 31, 30, 35, 35, - 40, 33, 34, 35, 32, 35, 35, 35, 28, 35, - 24, 19, 22, 26, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 52, 35, 56, - 56, 39, 38, 39, 41, 42, 57, 47, 48, 57, - 54, 55, 31, 0, 25, 31, 30, 15, 28, 0, - 0, 28, 29, 36, 29, 28, 30, 0, 27, 23, - 21, 30, 2, 30, 30, 30, 30, 18, 30, 30, - 12, 16, 30, 30, 30, 30, 17, 0, 0, 0, - - 37, 41, 0, 0, 43, 0, 0, 44, 47, 0, - 49, 0, 0, 0, 50, 54, 53, 31, 0, 0, - 0, 29, 0, 0, 29, 20, 14, 30, 6, 30, - 30, 30, 30, 30, 5, 30, 30, 33, 34, 32, - 45, 0, 45, 0, 0, 51, 0, 51, 0, 0, - 31, 31, 31, 0, 29, 0, 29, 0, 29, 30, - 30, 30, 11, 30, 30, 30, 30, 0, 0, 0, - 0, 31, 30, 8, 30, 7, 10, 4, 1, 0, - 0, 45, 0, 0, 0, 0, 51, 0, 0, 30, - 9, 3, 0, 0, 13, 0 - + 34, 34, 0, 0, 0, 0, 0, 0, 0, 0, + 62, 60, 35, 35, 39, 50, 35, 34, 39, 39, + 44, 37, 38, 39, 36, 39, 39, 39, 32, 39, + 27, 22, 25, 29, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 56, 39, + 60, 60, 43, 42, 43, 45, 46, 61, 51, 52, + 61, 58, 59, 35, 0, 28, 35, 34, 15, 32, + 0, 0, 32, 33, 40, 33, 32, 34, 0, 30, + 26, 24, 34, 2, 34, 34, 34, 34, 18, 19, + 34, 34, 34, 34, 12, 16, 34, 34, 34, 34, + + 34, 17, 0, 0, 0, 41, 45, 0, 0, 47, + 0, 0, 48, 51, 0, 53, 0, 0, 0, 54, + 58, 57, 32, 35, 0, 32, 0, 0, 33, 0, + 32, 0, 33, 30, 23, 14, 34, 6, 34, 34, + 34, 34, 21, 34, 34, 5, 34, 34, 34, 37, + 38, 36, 49, 0, 49, 0, 0, 55, 0, 55, + 0, 0, 32, 35, 35, 35, 0, 32, 33, 0, + 33, 0, 33, 32, 30, 34, 34, 34, 11, 34, + 20, 34, 34, 34, 34, 0, 0, 0, 0, 32, + 35, 32, 32, 30, 34, 8, 34, 7, 10, 34, + + 4, 1, 0, 0, 49, 0, 0, 0, 0, 55, + 0, 0, 32, 32, 32, 30, 34, 9, 34, 3, + 0, 0, 32, 32, 32, 30, 13, 31, 32, 32, + 32, 30, 32, 32, 32, 30, 32, 32, 32, 30, + 32, 32, 32, 30, 32, 32, 32, 30, 32, 32, + 32, 30, 32, 32, 32, 30, 32, 32, 32, 30, + 32, 32, 32, 30, 32, 32, 32, 30, 32, 32, + 33, 30, 33, 33, 33, 33, 33, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -393,167 +401,204 @@ static yyconst flex_int32_t yy_ec[256] = 20, 20, 20, 20, 20, 20, 20, 21, 9, 22, 23, 24, 25, 9, 26, 27, 8, 28, 29, 30, 31, 32, 33, 34, 8, 35, 36, 37, 38, 39, - 8, 40, 41, 42, 43, 44, 45, 8, 8, 8, - 1, 46, 1, 9, 8, 47, 48, 49, 8, 50, + 8, 40, 41, 42, 43, 44, 45, 8, 46, 8, + 1, 47, 1, 9, 8, 48, 49, 50, 8, 51, - 51, 52, 53, 54, 55, 56, 8, 57, 58, 59, - 60, 61, 8, 62, 63, 64, 65, 66, 67, 8, - 8, 8, 1, 68, 1, 9, 1, 69, 1, 1, - 1, 1, 1, 1, 1, 70, 71, 1, 1, 72, + 52, 53, 54, 55, 56, 57, 8, 58, 59, 60, + 61, 62, 8, 63, 64, 65, 66, 67, 68, 8, + 69, 8, 1, 70, 1, 9, 1, 71, 1, 1, + 1, 1, 1, 1, 1, 72, 73, 1, 1, 74, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 73, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 75, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 74, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 75, 1, + 1, 1, 1, 1, 1, 1, 76, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 77, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; -static yyconst flex_int32_t yy_meta[76] = +static yyconst flex_int32_t yy_meta[78] = { 0, 1, 1, 2, 2, 1, 3, 1, 4, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 6, 7, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 6, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 1, 1, 1, - 1, 1, 1, 1, 1 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, + 1, 1, 1, 1, 1, 1, 1 } ; -static yyconst flex_int16_t yy_base[213] = +static yyconst flex_int16_t yy_base[295] = { 0, - 0, 0, 73, 74, 67, 68, 74, 75, 330, 329, - 375, 517, 80, 87, 351, 517, 0, 0, 517, 363, - 517, 517, 517, 352, 517, 75, 351, 356, 76, 82, - 62, 517, 346, 517, 63, 72, 65, 66, 81, 71, - 71, 77, 75, 73, 87, 91, 86, 517, 300, 297, - 292, 517, 517, 105, 0, 139, 0, 0, 145, 0, - 0, 317, 155, 294, 517, 0, 0, 517, 342, 161, - 341, 148, 116, 517, 124, 151, 159, 340, 339, 334, - 517, 132, 0, 128, 132, 135, 134, 0, 148, 147, - 0, 0, 139, 143, 151, 158, 517, 288, 118, 177, - - 517, 0, 212, 345, 517, 338, 285, 517, 0, 218, - 517, 347, 334, 281, 517, 0, 517, 208, 273, 210, - 211, 212, 219, 318, 311, 517, 0, 173, 0, 190, - 204, 201, 209, 210, 0, 201, 205, 517, 517, 517, - 517, 312, 306, 244, 247, 517, 296, 294, 247, 229, - 194, 250, 253, 220, 268, 255, 250, 197, 184, 229, - 222, 225, 0, 226, 241, 242, 243, 274, 132, 293, - 124, 270, 250, 0, 250, 0, 0, 246, 0, 301, - 304, 316, 322, 86, 307, 326, 331, 337, 66, 277, - 0, 0, 341, 343, 0, 517, 412, 419, 426, 433, - - 440, 94, 447, 454, 461, 468, 475, 481, 488, 495, - 502, 509 + 0, 0, 75, 76, 69, 70, 76, 77, 533, 532, + 579, 696, 82, 89, 555, 696, 0, 0, 696, 566, + 696, 696, 696, 555, 696, 77, 552, 557, 78, 84, + 64, 696, 547, 696, 65, 74, 67, 68, 83, 73, + 73, 79, 75, 82, 77, 98, 94, 107, 696, 499, + 496, 491, 696, 696, 132, 0, 152, 0, 0, 168, + 0, 0, 517, 145, 493, 696, 0, 0, 696, 543, + 174, 542, 161, 132, 696, 137, 162, 177, 541, 540, + 532, 696, 132, 0, 122, 133, 148, 144, 0, 0, + 160, 159, 157, 165, 0, 0, 156, 160, 162, 169, + + 177, 696, 482, 158, 191, 696, 0, 231, 538, 696, + 530, 475, 696, 0, 234, 696, 538, 520, 465, 696, + 0, 696, 511, 243, 457, 223, 200, 234, 219, 238, + 239, 507, 502, 499, 696, 0, 211, 0, 217, 228, + 225, 230, 0, 229, 232, 0, 238, 224, 229, 696, + 696, 696, 696, 497, 492, 270, 424, 696, 485, 482, + 274, 416, 464, 204, 278, 290, 396, 277, 442, 437, + 435, 434, 433, 280, 430, 270, 262, 265, 0, 261, + 0, 276, 279, 279, 282, 310, 375, 314, 372, 422, + 332, 319, 320, 419, 301, 0, 302, 0, 0, 299, + + 301, 0, 340, 355, 359, 364, 366, 370, 375, 379, + 385, 362, 406, 375, 376, 403, 332, 0, 355, 0, + 395, 405, 402, 392, 395, 399, 0, 0, 397, 396, + 400, 382, 381, 412, 416, 380, 377, 420, 440, 367, + 360, 441, 445, 340, 335, 453, 457, 332, 327, 460, + 461, 325, 303, 465, 478, 295, 276, 481, 482, 250, + 199, 486, 496, 192, 178, 500, 503, 148, 133, 506, + 521, 696, 120, 522, 525, 101, 539, 696, 591, 598, + 605, 612, 619, 96, 626, 633, 640, 647, 654, 660, + 667, 674, 681, 688 + } ; -static yyconst flex_int16_t yy_def[213] = +static yyconst flex_int16_t yy_def[295] = { 0, - 196, 1, 197, 197, 198, 198, 199, 199, 200, 200, - 196, 196, 196, 196, 196, 196, 201, 202, 196, 196, - 196, 196, 196, 196, 196, 196, 196, 196, 202, 196, - 196, 196, 196, 196, 202, 202, 202, 202, 202, 202, - 202, 202, 202, 202, 202, 202, 202, 196, 196, 196, - 196, 196, 196, 196, 203, 196, 204, 205, 196, 206, - 207, 196, 196, 196, 196, 201, 202, 196, 196, 196, - 196, 196, 196, 196, 196, 202, 202, 196, 196, 196, - 196, 202, 202, 202, 202, 202, 202, 202, 202, 202, - 202, 202, 202, 202, 202, 202, 196, 196, 196, 196, - - 196, 203, 196, 208, 196, 196, 196, 196, 205, 196, - 196, 209, 196, 196, 196, 207, 196, 210, 196, 196, - 196, 196, 196, 196, 202, 196, 202, 202, 202, 202, - 202, 202, 202, 202, 202, 202, 202, 196, 196, 196, - 196, 208, 208, 196, 196, 196, 209, 209, 196, 196, - 210, 210, 210, 196, 196, 196, 196, 196, 196, 202, - 202, 202, 202, 202, 202, 202, 202, 211, 196, 212, - 196, 210, 202, 202, 202, 202, 202, 202, 202, 211, - 211, 211, 211, 196, 212, 212, 212, 212, 196, 202, - 202, 202, 211, 212, 202, 0, 196, 196, 196, 196, - - 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, - 196, 196 + 278, 1, 279, 279, 280, 280, 281, 281, 282, 282, + 278, 278, 278, 278, 278, 278, 283, 284, 278, 278, + 278, 278, 278, 278, 278, 278, 278, 278, 284, 278, + 278, 278, 278, 278, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 278, 278, + 278, 278, 278, 278, 278, 285, 278, 286, 287, 278, + 288, 289, 278, 278, 278, 278, 283, 284, 278, 278, + 278, 278, 278, 278, 278, 278, 284, 284, 278, 278, + 278, 278, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + + 284, 278, 278, 278, 278, 278, 285, 278, 290, 278, + 278, 278, 278, 287, 278, 278, 291, 278, 278, 278, + 289, 278, 278, 292, 278, 278, 278, 278, 278, 278, + 284, 278, 284, 278, 278, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 278, + 278, 278, 278, 290, 290, 278, 278, 278, 291, 291, + 278, 278, 278, 292, 292, 292, 278, 278, 278, 278, + 278, 278, 278, 284, 278, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 293, 278, 294, 278, 278, + 292, 278, 284, 278, 284, 284, 284, 284, 284, 284, + + 284, 284, 293, 293, 293, 293, 278, 294, 294, 294, + 294, 278, 278, 278, 284, 278, 284, 284, 284, 284, + 293, 294, 278, 278, 284, 278, 284, 284, 278, 278, + 284, 278, 278, 278, 284, 278, 278, 278, 284, 278, + 278, 278, 284, 278, 278, 278, 284, 278, 278, 278, + 284, 278, 278, 278, 284, 278, 278, 278, 284, 278, + 278, 278, 284, 278, 278, 278, 284, 278, 278, 278, + 284, 278, 278, 278, 284, 278, 278, 0, 278, 278, + 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 278, 278, 278, 278 + } ; -static yyconst flex_int16_t yy_nxt[593] = +static yyconst flex_int16_t yy_nxt[774] = { 0, 12, 13, 14, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 19, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 18, 18, 37, - 38, 39, 40, 41, 42, 18, 18, 43, 18, 44, - 45, 18, 18, 46, 47, 12, 48, 35, 36, 18, - 18, 37, 38, 39, 40, 41, 42, 18, 18, 43, - 18, 44, 45, 18, 18, 46, 47, 49, 12, 12, - 12, 12, 12, 50, 51, 53, 53, 56, 56, 59, - 59, 63, 63, 63, 80, 65, 54, 54, 63, 63, - 63, 70, 71, 75, 72, 76, 78, 67, 78, 82, - - 84, 79, 85, 83, 77, 86, 87, 88, 89, 90, - 93, 91, 57, 57, 92, 94, 95, 96, 100, 60, - 60, 82, 84, 101, 85, 83, 77, 86, 87, 88, - 89, 90, 93, 91, 170, 73, 92, 94, 95, 96, - 103, 103, 103, 122, 121, 104, 110, 110, 110, 105, - 111, 112, 123, 64, 168, 106, 63, 63, 63, 127, - 64, 113, 118, 118, 118, 75, 121, 72, 75, 128, - 76, 129, 130, 124, 123, 124, 120, 131, 125, 77, - 132, 127, 133, 134, 135, 136, 137, 138, 139, 140, - 100, 128, 189, 129, 130, 101, 196, 196, 120, 131, - - 184, 77, 132, 159, 133, 134, 135, 136, 137, 152, - 118, 118, 107, 103, 103, 103, 159, 160, 114, 110, - 110, 110, 141, 146, 124, 156, 124, 156, 64, 155, - 157, 122, 161, 158, 119, 158, 162, 163, 159, 160, - 123, 164, 165, 166, 167, 168, 168, 168, 170, 170, - 170, 152, 118, 118, 161, 196, 196, 173, 162, 163, - 174, 175, 123, 164, 165, 166, 167, 176, 177, 157, - 178, 179, 196, 196, 157, 181, 168, 168, 190, 173, - 191, 153, 174, 175, 182, 107, 192, 155, 118, 176, - 177, 114, 178, 179, 186, 170, 170, 110, 187, 148, - - 190, 148, 191, 196, 196, 181, 168, 168, 192, 196, - 196, 182, 187, 195, 182, 103, 143, 169, 196, 196, - 171, 172, 143, 153, 196, 196, 182, 186, 170, 170, - 125, 187, 182, 196, 196, 195, 187, 155, 152, 196, - 196, 154, 187, 196, 196, 196, 196, 183, 187, 150, - 149, 182, 148, 145, 144, 143, 63, 126, 79, 79, - 73, 69, 98, 117, 99, 98, 188, 97, 81, 74, - 73, 69, 68, 65, 196, 62, 62, 183, 196, 196, - 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, - 193, 196, 196, 196, 196, 196, 196, 196, 196, 188, - - 196, 196, 196, 196, 196, 194, 196, 196, 196, 181, - 196, 186, 52, 52, 52, 52, 52, 52, 52, 55, - 55, 55, 55, 55, 55, 55, 58, 58, 58, 58, - 58, 58, 58, 61, 61, 61, 61, 61, 61, 61, - 66, 196, 66, 66, 66, 66, 66, 102, 102, 102, - 102, 196, 196, 102, 108, 108, 108, 108, 108, 108, - 108, 109, 109, 196, 109, 109, 196, 109, 115, 115, - 115, 115, 115, 115, 115, 116, 116, 116, 116, 116, - 116, 142, 196, 142, 142, 142, 142, 142, 147, 196, - 147, 147, 147, 147, 147, 151, 151, 151, 151, 151, - - 151, 151, 180, 180, 180, 180, 180, 180, 180, 185, - 185, 185, 185, 185, 185, 185, 11, 196, 196, 196, - 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, - 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, - 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, - 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, - 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, - 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, - 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, - 196, 196 - + 38, 39, 40, 41, 42, 18, 43, 44, 18, 45, + 46, 18, 18, 47, 48, 18, 12, 49, 35, 36, + 18, 18, 37, 38, 39, 40, 41, 42, 18, 43, + 44, 18, 45, 46, 18, 18, 47, 48, 18, 50, + 12, 12, 12, 12, 12, 51, 52, 54, 54, 57, + 57, 60, 60, 64, 64, 64, 81, 66, 55, 55, + 64, 64, 64, 71, 72, 76, 73, 77, 79, 68, + + 79, 83, 85, 80, 86, 84, 78, 87, 88, 89, + 91, 92, 93, 90, 97, 58, 58, 94, 95, 100, + 276, 96, 61, 61, 83, 85, 98, 86, 84, 78, + 87, 88, 89, 91, 92, 93, 90, 97, 101, 276, + 94, 95, 100, 99, 96, 105, 64, 64, 64, 98, + 106, 74, 273, 108, 108, 108, 129, 65, 109, 136, + 128, 101, 110, 137, 65, 130, 99, 272, 111, 115, + 115, 115, 138, 116, 117, 124, 124, 124, 76, 76, + 126, 131, 136, 128, 118, 139, 137, 140, 130, 127, + 78, 132, 141, 132, 142, 138, 133, 269, 143, 144, + + 145, 146, 147, 148, 105, 149, 278, 278, 139, 106, + 140, 268, 127, 78, 132, 141, 132, 142, 265, 169, + 65, 143, 144, 145, 146, 147, 148, 112, 149, 150, + 151, 152, 108, 108, 108, 115, 115, 115, 129, 158, + 76, 153, 168, 119, 165, 124, 124, 130, 170, 125, + 170, 127, 172, 171, 172, 176, 76, 173, 174, 177, + 178, 179, 180, 181, 182, 183, 184, 78, 185, 264, + 130, 186, 186, 186, 127, 188, 188, 188, 176, 165, + 124, 124, 177, 178, 179, 180, 181, 182, 183, 184, + 78, 185, 278, 278, 76, 261, 192, 76, 195, 193, + + 196, 197, 198, 199, 200, 127, 112, 201, 78, 119, + 202, 204, 186, 186, 260, 209, 188, 188, 166, 210, + 205, 195, 257, 196, 197, 198, 199, 200, 127, 217, + 201, 78, 218, 202, 278, 278, 76, 76, 214, 215, + 219, 220, 278, 278, 256, 187, 253, 127, 78, 189, + 205, 252, 217, 166, 249, 218, 204, 186, 186, 248, + 191, 278, 278, 219, 220, 205, 278, 278, 227, 205, + 127, 78, 278, 278, 205, 210, 209, 188, 188, 245, + 210, 278, 278, 228, 210, 206, 244, 278, 278, 211, + 210, 227, 76, 76, 224, 225, 241, 278, 278, 240, + + 237, 236, 165, 127, 78, 205, 228, 278, 278, 76, + 210, 230, 76, 76, 231, 234, 233, 76, 232, 235, + 127, 229, 226, 78, 127, 223, 127, 78, 78, 76, + 206, 238, 188, 76, 221, 239, 186, 76, 216, 242, + 127, 213, 212, 127, 78, 207, 78, 127, 127, 194, + 211, 78, 173, 173, 171, 222, 171, 76, 76, 243, + 246, 169, 76, 127, 247, 204, 124, 78, 78, 127, + 76, 127, 250, 78, 76, 209, 251, 76, 76, 254, + 255, 127, 76, 190, 258, 78, 115, 160, 127, 78, + 160, 78, 127, 127, 108, 76, 78, 259, 76, 76, + + 262, 263, 155, 76, 127, 266, 78, 155, 78, 127, + 78, 127, 78, 76, 127, 267, 127, 76, 175, 270, + 76, 133, 271, 76, 78, 274, 169, 167, 127, 78, + 163, 78, 127, 78, 127, 162, 161, 127, 76, 76, + 275, 277, 76, 160, 275, 157, 156, 78, 155, 78, + 127, 127, 64, 78, 78, 135, 76, 127, 277, 134, + 80, 74, 123, 103, 122, 104, 103, 127, 102, 82, + 75, 74, 78, 127, 70, 69, 78, 66, 278, 63, + 63, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 127, 53, 53, 53, 53, 53, 53, 53, 56, 56, + + 56, 56, 56, 56, 56, 59, 59, 59, 59, 59, + 59, 59, 62, 62, 62, 62, 62, 62, 62, 67, + 278, 67, 67, 67, 67, 67, 107, 107, 107, 107, + 278, 278, 107, 113, 113, 113, 113, 113, 113, 113, + 114, 114, 278, 114, 114, 278, 114, 120, 120, 120, + 120, 120, 120, 120, 121, 121, 121, 121, 121, 121, + 154, 278, 154, 154, 154, 154, 154, 159, 278, 159, + 159, 159, 159, 159, 164, 164, 164, 164, 164, 164, + 164, 203, 203, 203, 203, 203, 203, 203, 208, 208, + 208, 208, 208, 208, 208, 11, 278, 278, 278, 278, + + 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 278, 278, 278 } ; -static yyconst flex_int16_t yy_chk[593] = +static yyconst flex_int16_t yy_chk[774] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -562,65 +607,84 @@ static yyconst flex_int16_t yy_chk[593] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 3, 4, 5, 6, 7, - 8, 13, 13, 13, 31, 31, 3, 4, 14, 14, - 14, 26, 26, 29, 26, 29, 30, 202, 30, 35, - - 36, 30, 37, 35, 29, 38, 39, 40, 41, 42, - 44, 43, 5, 6, 43, 45, 46, 47, 54, 7, - 8, 35, 36, 54, 37, 35, 29, 38, 39, 40, - 41, 42, 44, 43, 189, 73, 43, 45, 46, 47, - 56, 56, 56, 75, 73, 56, 59, 59, 59, 56, - 59, 59, 75, 13, 184, 56, 63, 63, 63, 82, - 14, 59, 70, 70, 70, 72, 73, 72, 76, 84, - 76, 85, 86, 77, 75, 77, 72, 87, 77, 76, - 89, 82, 90, 93, 94, 95, 96, 99, 99, 99, - 100, 84, 171, 85, 86, 100, 151, 151, 72, 87, - - 169, 76, 89, 159, 90, 93, 94, 95, 96, 118, - 118, 118, 56, 103, 103, 103, 158, 128, 59, 110, - 110, 110, 103, 110, 120, 121, 120, 121, 63, 120, - 121, 122, 130, 123, 70, 123, 131, 132, 123, 128, - 122, 133, 134, 136, 137, 144, 144, 144, 149, 149, - 149, 152, 152, 152, 130, 153, 153, 160, 131, 132, - 161, 162, 122, 133, 134, 136, 137, 164, 165, 157, - 166, 167, 172, 172, 156, 168, 168, 168, 173, 160, - 175, 118, 161, 162, 168, 103, 178, 155, 154, 164, - 165, 110, 166, 167, 170, 170, 170, 150, 170, 148, - - 173, 147, 175, 180, 180, 181, 181, 181, 178, 185, - 185, 180, 185, 190, 181, 145, 143, 144, 182, 182, - 149, 153, 142, 152, 183, 183, 182, 186, 186, 186, - 125, 186, 183, 187, 187, 190, 187, 124, 172, 188, - 188, 119, 188, 193, 193, 194, 194, 168, 194, 114, - 113, 193, 112, 107, 106, 104, 98, 80, 79, 78, - 71, 69, 64, 62, 51, 50, 170, 49, 33, 28, - 27, 24, 20, 15, 11, 10, 9, 181, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 183, 0, 0, 0, 0, 0, 0, 0, 0, 186, - - 0, 0, 0, 0, 0, 188, 0, 0, 0, 193, - 0, 194, 197, 197, 197, 197, 197, 197, 197, 198, - 198, 198, 198, 198, 198, 198, 199, 199, 199, 199, - 199, 199, 199, 200, 200, 200, 200, 200, 200, 200, - 201, 0, 201, 201, 201, 201, 201, 203, 203, 203, - 203, 0, 0, 203, 204, 204, 204, 204, 204, 204, - 204, 205, 205, 0, 205, 205, 0, 205, 206, 206, - 206, 206, 206, 206, 206, 207, 207, 207, 207, 207, - 207, 208, 0, 208, 208, 208, 208, 208, 209, 0, - 209, 209, 209, 209, 209, 210, 210, 210, 210, 210, - - 210, 210, 211, 211, 211, 211, 211, 211, 211, 212, - 212, 212, 212, 212, 212, 212, 196, 196, 196, 196, - 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, - 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, - 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, - 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, - 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, - 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, - 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, - 196, 196 - + 1, 1, 1, 1, 1, 1, 1, 3, 4, 5, + 6, 7, 8, 13, 13, 13, 31, 31, 3, 4, + 14, 14, 14, 26, 26, 29, 26, 29, 30, 284, + + 30, 35, 36, 30, 37, 35, 29, 38, 39, 40, + 41, 42, 43, 40, 45, 5, 6, 43, 44, 47, + 276, 44, 7, 8, 35, 36, 46, 37, 35, 29, + 38, 39, 40, 41, 42, 43, 40, 45, 48, 273, + 43, 44, 47, 46, 44, 55, 64, 64, 64, 46, + 55, 74, 269, 57, 57, 57, 76, 13, 57, 83, + 74, 48, 57, 85, 14, 76, 46, 268, 57, 60, + 60, 60, 86, 60, 60, 71, 71, 71, 73, 77, + 73, 77, 83, 74, 60, 87, 85, 88, 76, 73, + 77, 78, 91, 78, 92, 86, 78, 265, 93, 94, + + 97, 98, 99, 100, 105, 101, 164, 164, 87, 105, + 88, 264, 73, 77, 127, 91, 127, 92, 261, 127, + 64, 93, 94, 97, 98, 99, 100, 57, 101, 104, + 104, 104, 108, 108, 108, 115, 115, 115, 129, 115, + 126, 108, 126, 60, 124, 124, 124, 129, 128, 71, + 128, 126, 130, 128, 130, 137, 131, 130, 131, 139, + 140, 141, 142, 144, 145, 147, 148, 131, 149, 260, + 129, 156, 156, 156, 126, 161, 161, 161, 137, 165, + 165, 165, 139, 140, 141, 142, 144, 145, 147, 148, + 131, 149, 166, 166, 168, 257, 168, 174, 176, 174, + + 177, 178, 180, 182, 183, 168, 108, 184, 174, 115, + 185, 186, 186, 186, 256, 188, 188, 188, 124, 188, + 186, 176, 253, 177, 178, 180, 182, 183, 168, 195, + 184, 174, 197, 185, 191, 191, 192, 193, 192, 193, + 200, 201, 203, 203, 252, 156, 249, 192, 193, 161, + 203, 248, 195, 165, 245, 197, 204, 204, 204, 244, + 166, 205, 205, 200, 201, 204, 206, 206, 217, 205, + 192, 193, 208, 208, 206, 208, 209, 209, 209, 241, + 209, 210, 210, 219, 210, 186, 240, 211, 211, 188, + 211, 217, 214, 215, 214, 215, 237, 221, 221, 236, + + 233, 232, 191, 214, 215, 221, 219, 222, 222, 224, + 222, 224, 225, 230, 225, 230, 229, 231, 226, 231, + 224, 223, 216, 225, 230, 213, 214, 215, 231, 234, + 204, 234, 212, 235, 206, 235, 207, 238, 194, 238, + 234, 190, 189, 224, 235, 187, 225, 230, 238, 175, + 209, 231, 173, 172, 171, 211, 170, 239, 242, 239, + 242, 169, 243, 234, 243, 221, 167, 235, 239, 242, + 246, 238, 246, 243, 247, 222, 247, 250, 251, 250, + 251, 246, 254, 163, 254, 247, 162, 160, 250, 251, + 159, 239, 242, 254, 157, 255, 243, 255, 258, 259, + + 258, 259, 155, 262, 246, 262, 255, 154, 247, 258, + 259, 250, 251, 263, 262, 263, 254, 266, 134, 266, + 267, 133, 267, 270, 263, 270, 132, 125, 266, 255, + 123, 267, 258, 259, 270, 119, 118, 262, 271, 274, + 271, 274, 275, 117, 275, 112, 111, 263, 109, 271, + 274, 266, 103, 275, 267, 81, 277, 270, 277, 80, + 79, 72, 70, 65, 63, 52, 51, 277, 50, 33, + 28, 27, 271, 274, 24, 20, 275, 15, 11, 10, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 277, 279, 279, 279, 279, 279, 279, 279, 280, 280, + + 280, 280, 280, 280, 280, 281, 281, 281, 281, 281, + 281, 281, 282, 282, 282, 282, 282, 282, 282, 283, + 0, 283, 283, 283, 283, 283, 285, 285, 285, 285, + 0, 0, 285, 286, 286, 286, 286, 286, 286, 286, + 287, 287, 0, 287, 287, 0, 287, 288, 288, 288, + 288, 288, 288, 288, 289, 289, 289, 289, 289, 289, + 290, 0, 290, 290, 290, 290, 290, 291, 0, 291, + 291, 291, 291, 291, 292, 292, 292, 292, 292, 292, + 292, 293, 293, 293, 293, 293, 293, 293, 294, 294, + 294, 294, 294, 294, 294, 278, 278, 278, 278, 278, + + 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 278, 278, 278 } ; /* The intent behind this definition is that it'll catch @@ -672,12 +736,19 @@ do {\ #define RETURN_NAME_OB() \ { store_expr_str(yytext, yyleng, yytext + yyleng, yyscanner); return NAME_OB; } +#define RETURN_ROW_ID() \ + { store_expr_str(yytext, yyleng, yytext + yyleng, yyscanner); return ROW_ID; } + +#define RETURN_REVERSED_EXPR_FUNC() \ + { store_expr_str(yytext, yyleng, yytext + yyleng, yyscanner); return REVERSED_EXPR_FUNC; } + /*following character status will be rewrite by gen_parse.sh according to connection character*/ -#line 682 "ob_expr_parser_utf8_lex.c" +/* limit the length of int_num from 1 to 17 in case of int64_t out of bound, 17 -> [ ( length of 2^64 ) - 2 ]*/ +#line 753 "ob_expr_parser_utf8_lex.c" #define INITIAL 0 #define in_c_comment 1 @@ -925,9 +996,9 @@ YY_DECL register int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; -#line 94 "ob_expr_parser_utf8.l" +#line 102 "ob_expr_parser_utf8.l" -#line 933 "ob_expr_parser_utf8_lex.c" +#line 1004 "ob_expr_parser_utf8_lex.c" yylval = yylval_param; @@ -984,13 +1055,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 197 ) + if ( yy_current_state >= 279 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 517 ); + while ( yy_base[yy_current_state] != 696 ); yy_find_action: yy_act = yy_accept[yy_current_state]; @@ -1016,206 +1087,226 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 95 "ob_expr_parser_utf8.l" +#line 103 "ob_expr_parser_utf8.l" { return WHERE; } YY_BREAK case 2: YY_RULE_SETUP -#line 96 "ob_expr_parser_utf8.l" +#line 104 "ob_expr_parser_utf8.l" { return AS; } YY_BREAK case 3: YY_RULE_SETUP -#line 97 "ob_expr_parser_utf8.l" +#line 105 "ob_expr_parser_utf8.l" { return VALUES; } YY_BREAK case 4: YY_RULE_SETUP -#line 98 "ob_expr_parser_utf8.l" +#line 106 "ob_expr_parser_utf8.l" { return VALUES; } YY_BREAK case 5: YY_RULE_SETUP -#line 99 "ob_expr_parser_utf8.l" +#line 107 "ob_expr_parser_utf8.l" { return SET; } YY_BREAK case 6: YY_RULE_SETUP -#line 100 "ob_expr_parser_utf8.l" +#line 108 "ob_expr_parser_utf8.l" { return END_WHERE; } YY_BREAK case 7: YY_RULE_SETUP -#line 101 "ob_expr_parser_utf8.l" +#line 109 "ob_expr_parser_utf8.l" { return END_WHERE; } YY_BREAK case 8: YY_RULE_SETUP -#line 102 "ob_expr_parser_utf8.l" +#line 110 "ob_expr_parser_utf8.l" { return END_WHERE; } YY_BREAK case 9: YY_RULE_SETUP -#line 103 "ob_expr_parser_utf8.l" +#line 111 "ob_expr_parser_utf8.l" { return END_WHERE; } YY_BREAK case 10: YY_RULE_SETUP -#line 104 "ob_expr_parser_utf8.l" -{ return ROWID; } +#line 112 "ob_expr_parser_utf8.l" +{ RETURN_ROW_ID(); } YY_BREAK case 11: YY_RULE_SETUP -#line 106 "ob_expr_parser_utf8.l" +#line 114 "ob_expr_parser_utf8.l" { return JOIN; } YY_BREAK case 12: YY_RULE_SETUP -#line 107 "ob_expr_parser_utf8.l" +#line 115 "ob_expr_parser_utf8.l" { return ON; } YY_BREAK case 13: YY_RULE_SETUP -#line 108 "ob_expr_parser_utf8.l" +#line 116 "ob_expr_parser_utf8.l" { return BETWEEN; } YY_BREAK case 14: YY_RULE_SETUP -#line 109 "ob_expr_parser_utf8.l" +#line 117 "ob_expr_parser_utf8.l" { return AND_OP; } YY_BREAK case 15: YY_RULE_SETUP -#line 110 "ob_expr_parser_utf8.l" +#line 118 "ob_expr_parser_utf8.l" { return AND_OP; } YY_BREAK case 16: YY_RULE_SETUP -#line 111 "ob_expr_parser_utf8.l" +#line 119 "ob_expr_parser_utf8.l" { return OR_OP; } YY_BREAK case 17: YY_RULE_SETUP -#line 112 "ob_expr_parser_utf8.l" +#line 120 "ob_expr_parser_utf8.l" { return OR_OP; } YY_BREAK case 18: YY_RULE_SETUP -#line 113 "ob_expr_parser_utf8.l" +#line 121 "ob_expr_parser_utf8.l" { return IN; } YY_BREAK case 19: YY_RULE_SETUP -#line 114 "ob_expr_parser_utf8.l" -{ return COMP_EQ; } +#line 122 "ob_expr_parser_utf8.l" +{ return IS; } YY_BREAK case 20: YY_RULE_SETUP -#line 115 "ob_expr_parser_utf8.l" -{ return COMP_NSEQ; } +#line 123 "ob_expr_parser_utf8.l" +{ return TOKEN_NULL; } YY_BREAK case 21: YY_RULE_SETUP -#line 116 "ob_expr_parser_utf8.l" -{ return COMP_GE; } +#line 124 "ob_expr_parser_utf8.l" +{ return NOT; } YY_BREAK case 22: YY_RULE_SETUP -#line 117 "ob_expr_parser_utf8.l" -{ return COMP_GT; } +#line 125 "ob_expr_parser_utf8.l" +{ return COMP_EQ; } YY_BREAK case 23: YY_RULE_SETUP -#line 118 "ob_expr_parser_utf8.l" -{ return COMP_LE; } +#line 126 "ob_expr_parser_utf8.l" +{ return COMP_NSEQ; } YY_BREAK case 24: YY_RULE_SETUP -#line 119 "ob_expr_parser_utf8.l" -{ return COMP_LT; } +#line 127 "ob_expr_parser_utf8.l" +{ return COMP_GE; } YY_BREAK case 25: YY_RULE_SETUP -#line 120 "ob_expr_parser_utf8.l" -{ return COMP_NE; } +#line 128 "ob_expr_parser_utf8.l" +{ return COMP_GT; } YY_BREAK case 26: YY_RULE_SETUP -#line 121 "ob_expr_parser_utf8.l" -{ return PLACE_HOLDER; } +#line 129 "ob_expr_parser_utf8.l" +{ return COMP_LE; } YY_BREAK case 27: YY_RULE_SETUP -#line 122 "ob_expr_parser_utf8.l" -{ store_pos_place_holder(yytext + 1, yyscanner); return POS_PLACE_HOLDER; } +#line 130 "ob_expr_parser_utf8.l" +{ return COMP_LT; } YY_BREAK case 28: YY_RULE_SETUP -#line 124 "ob_expr_parser_utf8.l" -{ RETURN_INT_VAL(); } +#line 131 "ob_expr_parser_utf8.l" +{ return COMP_NE; } YY_BREAK case 29: YY_RULE_SETUP -#line 125 "ob_expr_parser_utf8.l" -{ RETURN_NUMBER_VAL(); } +#line 132 "ob_expr_parser_utf8.l" +{ return PLACE_HOLDER; } YY_BREAK case 30: YY_RULE_SETUP -#line 126 "ob_expr_parser_utf8.l" -{ RETURN_NAME_OB(); } +#line 133 "ob_expr_parser_utf8.l" +{ store_pos_place_holder(yytext + 1, yyscanner); return POS_PLACE_HOLDER; } YY_BREAK case 31: -/* rule 31 can match eol */ YY_RULE_SETUP -#line 127 "ob_expr_parser_utf8.l" -{ } +#line 134 "ob_expr_parser_utf8.l" +{ RETURN_REVERSED_EXPR_FUNC();} YY_BREAK case 32: YY_RULE_SETUP -#line 128 "ob_expr_parser_utf8.l" -{ return ','; } +#line 136 "ob_expr_parser_utf8.l" +{ RETURN_INT_VAL(); } YY_BREAK case 33: YY_RULE_SETUP -#line 129 "ob_expr_parser_utf8.l" -{ return '('; } +#line 137 "ob_expr_parser_utf8.l" +{ RETURN_NUMBER_VAL(); } YY_BREAK case 34: YY_RULE_SETUP -#line 130 "ob_expr_parser_utf8.l" -{ return ')'; } +#line 138 "ob_expr_parser_utf8.l" +{ RETURN_NAME_OB(); } YY_BREAK case 35: +/* rule 35 can match eol */ YY_RULE_SETUP -#line 131 "ob_expr_parser_utf8.l" +#line 139 "ob_expr_parser_utf8.l" +{ } + YY_BREAK +case 36: +YY_RULE_SETUP +#line 140 "ob_expr_parser_utf8.l" +{ return ','; } + YY_BREAK +case 37: +YY_RULE_SETUP +#line 141 "ob_expr_parser_utf8.l" +{ return '('; } + YY_BREAK +case 38: +YY_RULE_SETUP +#line 142 "ob_expr_parser_utf8.l" +{ return ')'; } + YY_BREAK +case 39: +YY_RULE_SETUP +#line 143 "ob_expr_parser_utf8.l" { return yytext[0]; } YY_BREAK /* comment */ -case 36: +case 40: YY_RULE_SETUP -#line 134 "ob_expr_parser_utf8.l" +#line 146 "ob_expr_parser_utf8.l" { PUSH_STATE(in_c_comment); } YY_BREAK -case 37: +case 41: YY_RULE_SETUP -#line 135 "ob_expr_parser_utf8.l" +#line 147 "ob_expr_parser_utf8.l" { POP_STATE(); } YY_BREAK -case 38: -/* rule 38 can match eol */ +case 42: +/* rule 42 can match eol */ YY_RULE_SETUP -#line 136 "ob_expr_parser_utf8.l" +#line 148 "ob_expr_parser_utf8.l" {} YY_BREAK -case 39: +case 43: YY_RULE_SETUP -#line 137 "ob_expr_parser_utf8.l" +#line 149 "ob_expr_parser_utf8.l" {} YY_BREAK /* quote */ -case 40: +case 44: YY_RULE_SETUP -#line 140 "ob_expr_parser_utf8.l" +#line 152 "ob_expr_parser_utf8.l" { PUSH_STATE(sq); ObExprParseResult *p = (ObExprParseResult *)yyextra; @@ -1226,10 +1317,10 @@ YY_RULE_SETUP } } YY_BREAK -case 41: -/* rule 41 can match eol */ +case 45: +/* rule 45 can match eol */ YY_RULE_SETUP -#line 150 "ob_expr_parser_utf8.l" +#line 162 "ob_expr_parser_utf8.l" { ObExprParseResult *p = (ObExprParseResult *)yyextra; if (OB_NOTNULL(p)) { @@ -1237,9 +1328,9 @@ YY_RULE_SETUP } } YY_BREAK -case 42: +case 46: YY_RULE_SETUP -#line 157 "ob_expr_parser_utf8.l" +#line 169 "ob_expr_parser_utf8.l" { POP_STATE(); ObExprParseResult *p = (ObExprParseResult *)yyextra; @@ -1249,15 +1340,15 @@ YY_RULE_SETUP return STR_VAL; } YY_BREAK -case 43: +case 47: YY_RULE_SETUP -#line 166 "ob_expr_parser_utf8.l" +#line 178 "ob_expr_parser_utf8.l" {} YY_BREAK -case 44: -/* rule 44 can match eol */ +case 48: +/* rule 48 can match eol */ YY_RULE_SETUP -#line 167 "ob_expr_parser_utf8.l" +#line 179 "ob_expr_parser_utf8.l" { ObExprParseResult *p = (ObExprParseResult *)yyextra; if (OB_NOTNULL(p)) { @@ -1265,20 +1356,20 @@ YY_RULE_SETUP } } YY_BREAK -case 45: -/* rule 45 can match eol */ +case 49: +/* rule 49 can match eol */ YY_RULE_SETUP -#line 173 "ob_expr_parser_utf8.l" +#line 185 "ob_expr_parser_utf8.l" {} YY_BREAK case YY_STATE_EOF(sq): -#line 174 "ob_expr_parser_utf8.l" +#line 186 "ob_expr_parser_utf8.l" { return ERROR; } YY_BREAK /* dquote */ -case 46: +case 50: YY_RULE_SETUP -#line 178 "ob_expr_parser_utf8.l" +#line 190 "ob_expr_parser_utf8.l" { PUSH_STATE(dq); ObExprParseResult *p = (ObExprParseResult *)yyextra; @@ -1289,10 +1380,10 @@ YY_RULE_SETUP } } YY_BREAK -case 47: -/* rule 47 can match eol */ +case 51: +/* rule 51 can match eol */ YY_RULE_SETUP -#line 188 "ob_expr_parser_utf8.l" +#line 200 "ob_expr_parser_utf8.l" { ObExprParseResult *p = (ObExprParseResult *)yyextra; if (OB_NOTNULL(p)) { @@ -1300,9 +1391,9 @@ YY_RULE_SETUP } } YY_BREAK -case 48: +case 52: YY_RULE_SETUP -#line 195 "ob_expr_parser_utf8.l" +#line 207 "ob_expr_parser_utf8.l" { POP_STATE(); ObExprParseResult *p = (ObExprParseResult *)yyextra; @@ -1315,31 +1406,31 @@ YY_RULE_SETUP return STR_VAL; } YY_BREAK -case 49: +case 53: YY_RULE_SETUP -#line 207 "ob_expr_parser_utf8.l" +#line 219 "ob_expr_parser_utf8.l" {} YY_BREAK -case 50: -/* rule 50 can match eol */ +case 54: +/* rule 54 can match eol */ YY_RULE_SETUP -#line 208 "ob_expr_parser_utf8.l" +#line 220 "ob_expr_parser_utf8.l" {} YY_BREAK -case 51: -/* rule 51 can match eol */ +case 55: +/* rule 55 can match eol */ YY_RULE_SETUP -#line 209 "ob_expr_parser_utf8.l" +#line 221 "ob_expr_parser_utf8.l" {} YY_BREAK case YY_STATE_EOF(dq): -#line 210 "ob_expr_parser_utf8.l" +#line 222 "ob_expr_parser_utf8.l" { return ERROR; } YY_BREAK /* backtick */ -case 52: +case 56: YY_RULE_SETUP -#line 214 "ob_expr_parser_utf8.l" +#line 226 "ob_expr_parser_utf8.l" { PUSH_STATE(bt); ObExprParseResult *p = (ObExprParseResult *)yyextra; @@ -1350,9 +1441,9 @@ YY_RULE_SETUP } } YY_BREAK -case 53: +case 57: YY_RULE_SETUP -#line 224 "ob_expr_parser_utf8.l" +#line 236 "ob_expr_parser_utf8.l" { ObExprParseResult *p = (ObExprParseResult *)yyextra; if (NULL != p && NULL != p->tmp_buf_ && p->tmp_len_ + 1 < OBPROXY_MAX_NAME_LENGTH) { @@ -1360,10 +1451,10 @@ YY_RULE_SETUP } } YY_BREAK -case 54: -/* rule 54 can match eol */ +case 58: +/* rule 58 can match eol */ YY_RULE_SETUP -#line 231 "ob_expr_parser_utf8.l" +#line 243 "ob_expr_parser_utf8.l" { ObExprParseResult *p = (ObExprParseResult *)yyextra; if (NULL != p && NULL != p->tmp_buf_ && p->tmp_len_ + yyleng < OBPROXY_MAX_NAME_LENGTH) { @@ -1372,9 +1463,9 @@ YY_RULE_SETUP } } YY_BREAK -case 55: +case 59: YY_RULE_SETUP -#line 239 "ob_expr_parser_utf8.l" +#line 251 "ob_expr_parser_utf8.l" { POP_STATE(); ObExprParseResult *p = (ObExprParseResult *)yyextra; @@ -1387,27 +1478,27 @@ YY_RULE_SETUP } YY_BREAK case YY_STATE_EOF(bt): -#line 250 "ob_expr_parser_utf8.l" +#line 262 "ob_expr_parser_utf8.l" { return ERROR; } YY_BREAK case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(in_c_comment): -#line 254 "ob_expr_parser_utf8.l" +#line 266 "ob_expr_parser_utf8.l" { return END_P; } YY_BREAK -case 56: +case 60: YY_RULE_SETUP -#line 255 "ob_expr_parser_utf8.l" +#line 267 "ob_expr_parser_utf8.l" { return IGNORED_WORD; } YY_BREAK -case 57: +case 61: YY_RULE_SETUP -#line 256 "ob_expr_parser_utf8.l" +#line 268 "ob_expr_parser_utf8.l" ECHO; YY_BREAK -#line 1413 "ob_expr_parser_utf8_lex.c" +#line 1504 "ob_expr_parser_utf8_lex.c" case YY_END_OF_BUFFER: { @@ -1699,7 +1790,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 197 ) + if ( yy_current_state >= 279 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1728,11 +1819,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 197 ) + if ( yy_current_state >= 279 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 196); + yy_is_jam = (yy_current_state == 278); return yy_is_jam ? 0 : yy_current_state; } @@ -2557,7 +2648,7 @@ static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) #define YYTABLES_NAME "yytables" -#line 256 "ob_expr_parser_utf8.l" +#line 268 "ob_expr_parser_utf8.l" @@ -2688,22 +2779,26 @@ extern int ob_expr_parser_utf8_yydebug; IN = 268, ON = 269, BETWEEN = 270, - ROWID = 271, - COMP_EQ = 272, - COMP_NSEQ = 273, - COMP_GE = 274, - COMP_GT = 275, - COMP_LE = 276, - COMP_LT = 277, - COMP_NE = 278, - PLACE_HOLDER = 279, - END_P = 280, - ERROR = 281, - IGNORED_WORD = 282, - NAME_OB = 283, - STR_VAL = 284, - INT_VAL = 285, - POS_PLACE_HOLDER = 286 + IS = 271, + TOKEN_NULL = 272, + NOT = 273, + COMP_EQ = 274, + COMP_NSEQ = 275, + COMP_GE = 276, + COMP_GT = 277, + COMP_LE = 278, + COMP_LT = 279, + COMP_NE = 280, + PLACE_HOLDER = 281, + END_P = 282, + ERROR = 283, + IGNORED_WORD = 284, + NAME_OB = 285, + STR_VAL = 286, + ROW_ID = 287, + REVERSED_EXPR_FUNC = 288, + INT_VAL = 289, + POS_PLACE_HOLDER = 290 }; #endif diff --git a/src/obproxy/opsql/expr_parser/ob_expr_parser_utf8_lex.h b/src/obproxy/opsql/expr_parser/ob_expr_parser_utf8_lex.h index c6b56173141f8c21144f5c09ed767089a72dcf06..330e2a7312f6914bf136aaa38c25e85e950704ef 100644 --- a/src/obproxy/opsql/expr_parser/ob_expr_parser_utf8_lex.h +++ b/src/obproxy/opsql/expr_parser/ob_expr_parser_utf8_lex.h @@ -341,7 +341,7 @@ extern int ob_expr_parser_utf8_yylex \ #undef YY_DECL #endif -#line 256 "ob_expr_parser_utf8.l" +#line 268 "ob_expr_parser_utf8.l" #line 348 "ob_expr_parser_utf8_lex.h" diff --git a/src/obproxy/opsql/expr_parser/ob_expr_parser_utf8_tab.c b/src/obproxy/opsql/expr_parser/ob_expr_parser_utf8_tab.c index c123daaeed58438a31f6d50092a7a72a87446262..437bec45c75f8ea256107a125bf9e6f13f847f12 100644 --- a/src/obproxy/opsql/expr_parser/ob_expr_parser_utf8_tab.c +++ b/src/obproxy/opsql/expr_parser/ob_expr_parser_utf8_tab.c @@ -139,22 +139,26 @@ extern int ob_expr_parser_utf8_yydebug; IN = 268, ON = 269, BETWEEN = 270, - ROWID = 271, - COMP_EQ = 272, - COMP_NSEQ = 273, - COMP_GE = 274, - COMP_GT = 275, - COMP_LE = 276, - COMP_LT = 277, - COMP_NE = 278, - PLACE_HOLDER = 279, - END_P = 280, - ERROR = 281, - IGNORED_WORD = 282, - NAME_OB = 283, - STR_VAL = 284, - INT_VAL = 285, - POS_PLACE_HOLDER = 286 + IS = 271, + TOKEN_NULL = 272, + NOT = 273, + COMP_EQ = 274, + COMP_NSEQ = 275, + COMP_GE = 276, + COMP_GT = 277, + COMP_LE = 278, + COMP_LT = 279, + COMP_NE = 280, + PLACE_HOLDER = 281, + END_P = 282, + ERROR = 283, + IGNORED_WORD = 284, + NAME_OB = 285, + STR_VAL = 286, + ROW_ID = 287, + REVERSED_EXPR_FUNC = 288, + INT_VAL = 289, + POS_PLACE_HOLDER = 290 }; #endif @@ -232,8 +236,8 @@ static inline void add_token_list(ObProxyTokenList *list, ObProxyTokenList *next if (OB_ISNULL(list) || OB_ISNULL(next_list)) { } else if (NULL != list->tail_ && NULL != next_list->head_ - && (TOKEN_INT_VAL == list->tail_->type_ || TOKEN_STR_VAL == list->tail_->type_) - && (TOKEN_INT_VAL == next_list->head_->type_ || TOKEN_STR_VAL == next_list->head_->type_)) { + && (TOKEN_INT_VAL == list->tail_->type_ || TOKEN_STR_VAL == list->tail_->type_ || TOKEN_FUNC == list->tail_->type_) + && (TOKEN_INT_VAL == next_list->head_->type_ || TOKEN_STR_VAL == next_list->head_->type_ || TOKEN_FUNC == next_list->head_->type_)) { list->tail_->next_ = next_list->head_; list->tail_ = next_list->head_; list->tail_->next_ = NULL; @@ -305,11 +309,18 @@ static inline void set_part_key_column_idx(ObExprParseResult *result, ObProxyPar for (i = 0; i < result->part_key_info_.key_num_; ++i) { if (is_equal(column_name, &result->part_key_info_.part_keys_[i].name_)) { result->part_key_info_.part_keys_[i].idx_ = result->column_idx_; - break; + result->part_key_info_.part_keys_[i].is_exist_in_sql_ = true; } } } +static inline void init_part_key_all_match(ObExprParseResult *result) +{ + for (int64_t i = 0; i < result->part_key_info_.key_num_; ++i) { + result->part_key_info_.part_keys_[i].is_exist_in_sql_ = true; + } +} + #define malloc_node(node, result, type) \ do { \ if (OB_ISNULL(node = ((ObProxyTokenNode *)obproxy_parse_malloc(sizeof(ObProxyTokenNode), \ @@ -344,18 +355,13 @@ static inline void set_part_key_column_idx(ObExprParseResult *result, ObProxyPar do { \ if (NULL == relation) { \ } else { \ - int64_t new_mask = get_mask(relation->type_, relation->level_); \ - if ((result->cur_mask_ | new_mask) != result->cur_mask_) { \ + if (relation->level_ != PART_KEY_LEVEL_ZERO) { \ if (result->relation_info_.relation_num_ < OBPROXY_MAX_RELATION_NUM) { \ result->relation_info_.relations_[result->relation_info_.relation_num_++] = relation; \ - result->cur_mask_ = (result->cur_mask_ | new_mask); \ } else { \ /* YYACCEPT; */ \ } \ } \ - if ((result->cur_mask_ & result->target_mask_) == result->target_mask_) { \ - /* YYACCEPT; */ \ - } \ } \ } while(0) \ @@ -365,6 +371,7 @@ static int64_t get_part_key_idx(ObProxyParseString *db_name, ObExprParseResult *result) { int64_t part_key_idx = IDX_NO_PART_KEY_COLUMN; + if (result->part_key_info_.key_num_ > 0) { if (NULL != db_name && !is_equal(db_name, &result->table_info_.database_name_)) { part_key_idx = IDX_NO_PART_KEY_COLUMN; @@ -385,9 +392,9 @@ static int64_t get_part_key_idx(ObProxyParseString *db_name, return part_key_idx; } static inline void add_relation(ObExprParseResult *result, - ObProxyTokenList *left_value, - ObProxyFunctionType type, - ObProxyTokenList *right_value) + ObProxyTokenList *left_value, + ObProxyFunctionType type, + ObProxyTokenList *right_value) { if (result->all_relation_info_.relation_num_ < OBPROXY_MAX_RELATION_NUM) { ObProxyRelationExpr *relation = NULL; @@ -424,6 +431,92 @@ static inline void add_relation(ObExprParseResult *result, } } +static inline void set_relation_part_with_column_idx(int64_t idx_in_schema_columns, + ObExprParseResult *result, + ObProxyPartKeyLevel *level, + int64_t *first_part_column_idx, + int64_t *second_part_column_idx) +{ + if (OB_ISNULL(level) && OB_ISNULL(first_part_column_idx) && + OB_ISNULL(second_part_column_idx) && OB_ISNULL(result)) { + // do nothing + } else { + *level = PART_KEY_LEVEL_ZERO; + *first_part_column_idx = 0; + *second_part_column_idx = 0; + bool is_level_one = false; + bool is_level_two = false; + for (int i = 0; i < result->part_key_info_.key_num_; i++) { + // make sure the part_key exist in sql to avoid the uninitialized idx_ + if (idx_in_schema_columns == result->part_key_info_.part_keys_[i].idx_ && result->part_key_info_.part_keys_[i].is_exist_in_sql_) { + if (result->part_key_info_.part_keys_[i].level_ == PART_KEY_LEVEL_ONE) { + is_level_one = true; + *first_part_column_idx = result->part_key_info_.part_keys_[i].idx_in_part_columns_; + } else if (result->part_key_info_.part_keys_[i].level_ == PART_KEY_LEVEL_TWO) { + is_level_two = true; + *second_part_column_idx = result->part_key_info_.part_keys_[i].idx_in_part_columns_; + } + } + } + if (is_level_one) { + *level = PART_KEY_LEVEL_ONE; + } + if (is_level_two) { + *level = PART_KEY_LEVEL_TWO; + } + if (is_level_one && is_level_two) { + *level = PART_KEY_LEVEL_BOTH; + } + } +} + +static inline void set_relation_part_with_column_name(ObProxyParseString *column, + ObExprParseResult *result, + ObProxyPartKeyLevel *level, + int64_t *first_part_column_idx, + int64_t *second_part_column_idx) +{ + if (OB_ISNULL(column) + || OB_ISNULL(result) + || OB_ISNULL(level) + || OB_ISNULL(first_part_column_idx) + || OB_ISNULL(second_part_column_idx)) { + // do nothing + } else if (result->has_rowid_ + && is_equal_to_rowid(column)) { + // handle rowid + *level = PART_KEY_LEVEL_ONE; + *first_part_column_idx = 0; + *second_part_column_idx = 0; + } else { + *level = PART_KEY_LEVEL_ZERO; + *first_part_column_idx = 0; + *second_part_column_idx = 0; + bool is_level_one = false; + bool is_level_two = false; + for (int i = 0; i < result->part_key_info_.key_num_; i++) { + if (is_equal(&result->part_key_info_.part_keys_[i].name_, column)) { + if (result->part_key_info_.part_keys_[i].level_ == PART_KEY_LEVEL_ONE) { + is_level_one = true; + *first_part_column_idx = result->part_key_info_.part_keys_[i].idx_in_part_columns_; + } else if (result->part_key_info_.part_keys_[i].level_ == PART_KEY_LEVEL_TWO) { + is_level_two = true; + *second_part_column_idx = result->part_key_info_.part_keys_[i].idx_in_part_columns_; + } + } + } + if (is_level_one) { + *level = PART_KEY_LEVEL_ONE; + } + if (is_level_two) { + *level = PART_KEY_LEVEL_TWO; + } + if (is_level_one && is_level_two) { + *level = PART_KEY_LEVEL_BOTH; + } + } +} + static inline ObProxyRelationExpr *get_relation(ObExprParseResult *result, ObProxyTokenList *left_value, @@ -434,25 +527,25 @@ static inline ObProxyRelationExpr *get_relation(ObExprParseResult *result, ObProxyTokenList *tmp_left = NULL; ObProxyTokenList *tmp_right = NULL; ObProxyFunctionType tmp_type = F_NONE; - ObProxyPartKeyLevel tmp_level = PART_KEY_LEVEL_ZERO; int64_t tmp_column_idx_ = -1; + ObProxyParseString *tmp_column = NULL; if (NULL != left_value->column_node_ && TOKEN_COLUMN == left_value->column_node_->type_ && left_value->column_node_->part_key_idx_ >= 0) { tmp_left = left_value; - tmp_level = result->part_key_info_.part_keys_[left_value->column_node_->part_key_idx_].level_; tmp_right = right_value; tmp_type = type; tmp_column_idx_ = left_value->column_node_->part_key_idx_; + tmp_column = &left_value->column_node_->column_name_; } else if (NULL != right_value->column_node_ && TOKEN_COLUMN == right_value->column_node_->type_ && right_value->column_node_->part_key_idx_ >= 0) { tmp_left = right_value; - tmp_level = result->part_key_info_.part_keys_[right_value->column_node_->part_key_idx_].level_; tmp_right = left_value; tmp_type = get_reverse_func(type); tmp_column_idx_ = right_value->column_node_->part_key_idx_; + tmp_column = &right_value->column_node_->column_name_; } if (NULL == tmp_left || NULL == tmp_right || F_COMP_NE == tmp_type) { @@ -465,7 +558,11 @@ static inline ObProxyRelationExpr *get_relation(ObExprParseResult *result, relation->left_value_ = tmp_left; relation->type_ = tmp_type; relation->right_value_ = tmp_right; - relation->level_ = tmp_level; + set_relation_part_with_column_name(tmp_column, + result, + &relation->level_, + &relation->first_part_column_idx_, + &relation->second_part_column_idx_); } return relation; } @@ -479,14 +576,20 @@ static inline ObProxyRelationExpr *get_values_relation(ObExprParseResult *result } else { int64_t i = 0; for (i = 0; i < result->part_key_info_.key_num_; ++i) { - if (result->values_list_idx_ == result->part_key_info_.part_keys_[i].idx_) { + // make sure the part_key exist in sql to avoid the uninitialized idx_ + if (result->values_list_idx_ == result->part_key_info_.part_keys_[i].idx_ && result->part_key_info_.part_keys_[i].is_exist_in_sql_) { if (OB_ISNULL(relation = ((ObProxyRelationExpr *)obproxy_parse_malloc( sizeof(ObProxyRelationExpr), result->malloc_pool_)))) { } else { relation->column_idx_ = i; relation->type_ = F_COMP_EQ; relation->right_value_ = right_value; - relation->level_ = result->part_key_info_.part_keys_[i].level_; + relation->left_value_ = NULL; + set_relation_part_with_column_idx(result->values_list_idx_, + result, + &relation->level_, + &relation->first_part_column_idx_, + &relation->second_part_column_idx_); } break; } @@ -748,20 +851,20 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 17 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 221 +#define YYLAST 242 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 44 +#define YYNTOKENS 48 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 24 /* YYNRULES -- Number of rules. */ -#define YYNRULES 80 +#define YYNRULES 83 /* YYNRULES -- Number of states. */ -#define YYNSTATES 146 +#define YYNSTATES 149 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 286 +#define YYMAXUTOK 290 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -772,9 +875,9 @@ static const yytype_uint8 yytranslate[] = 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 43, 2, 2, 2, 41, 42, 2, - 35, 32, 39, 37, 36, 38, 34, 40, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 33, + 2, 2, 2, 47, 2, 2, 2, 45, 46, 2, + 39, 36, 43, 41, 40, 42, 38, 44, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 37, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -797,7 +900,8 @@ static const yytype_uint8 yytranslate[] = 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31 + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35 }; #if YYDEBUG @@ -808,58 +912,58 @@ static const yytype_uint16 yyprhs[] = 0, 0, 3, 6, 9, 13, 16, 21, 23, 25, 27, 29, 31, 33, 36, 40, 43, 48, 52, 57, 63, 70, 72, 76, 82, 86, 92, 96, 102, 108, - 114, 120, 124, 126, 128, 130, 132, 134, 136, 138, - 140, 144, 146, 148, 151, 152, 156, 160, 162, 166, - 172, 177, 182, 184, 186, 188, 190, 192, 194, 196, - 198, 200, 202, 204, 206, 211, 216, 220, 222, 226, - 232, 233, 237, 239, 243, 245, 247, 251, 253, 257, - 258 + 114, 120, 124, 129, 131, 133, 135, 137, 139, 141, + 143, 145, 149, 151, 153, 156, 157, 161, 165, 167, + 169, 173, 179, 181, 186, 191, 193, 195, 197, 199, + 201, 203, 205, 207, 209, 211, 213, 215, 220, 225, + 229, 231, 235, 241, 242, 246, 248, 252, 254, 256, + 260, 262, 266, 267 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { - 45, 0, -1, 3, 46, -1, 4, 60, -1, 5, - 51, 47, -1, 48, 47, -1, 48, 5, 51, 47, - -1, 1, -1, 9, -1, 32, -1, 33, -1, 25, - -1, 49, -1, 48, 49, -1, 50, 14, 51, -1, - 10, 28, -1, 10, 28, 34, 28, -1, 10, 28, - 28, -1, 10, 28, 6, 28, -1, 10, 28, 34, - 28, 28, -1, 10, 28, 34, 28, 6, 28, -1, - 52, -1, 51, 11, 52, -1, 35, 51, 11, 52, - 32, -1, 51, 12, 52, -1, 35, 51, 12, 52, - 32, -1, 55, 53, 55, -1, 55, 53, 35, 55, - 32, -1, 35, 55, 53, 55, 32, -1, 55, 13, - 35, 54, 32, -1, 55, 15, 55, 11, 55, -1, - 16, 17, 29, -1, 17, -1, 18, -1, 19, -1, - 20, -1, 21, -1, 22, -1, 23, -1, 55, -1, - 54, 36, 55, -1, 56, -1, 58, -1, 56, 58, - -1, -1, 56, 36, 56, -1, 57, 36, 56, -1, - 28, -1, 28, 34, 28, -1, 28, 34, 28, 34, - 28, -1, 28, 35, 56, 32, -1, 28, 35, 57, - 32, -1, 30, -1, 29, -1, 59, -1, 24, -1, - 31, -1, 37, -1, 38, -1, 39, -1, 40, -1, - 41, -1, 42, -1, 43, -1, 62, 7, 61, 47, - -1, 8, 66, 67, 47, -1, 14, 51, 47, -1, - 46, -1, 35, 65, 32, -1, 61, 36, 35, 65, - 32, -1, -1, 35, 63, 32, -1, 64, -1, 63, - 36, 64, -1, 28, -1, 55, -1, 65, 36, 55, - -1, 52, -1, 66, 36, 52, -1, -1, 5, 51, - -1 + 49, 0, -1, 3, 50, -1, 4, 64, -1, 5, + 55, 51, -1, 52, 51, -1, 52, 5, 55, 51, + -1, 1, -1, 9, -1, 36, -1, 37, -1, 27, + -1, 53, -1, 52, 53, -1, 54, 14, 55, -1, + 10, 30, -1, 10, 30, 38, 30, -1, 10, 30, + 30, -1, 10, 30, 6, 30, -1, 10, 30, 38, + 30, 30, -1, 10, 30, 38, 30, 6, 30, -1, + 56, -1, 55, 11, 56, -1, 39, 55, 11, 56, + 36, -1, 55, 12, 56, -1, 39, 55, 12, 56, + 36, -1, 59, 57, 59, -1, 59, 57, 39, 59, + 36, -1, 39, 59, 57, 59, 36, -1, 59, 13, + 39, 58, 36, -1, 59, 15, 59, 11, 59, -1, + 59, 16, 17, -1, 59, 16, 18, 17, -1, 19, + -1, 20, -1, 21, -1, 22, -1, 23, -1, 24, + -1, 25, -1, 59, -1, 58, 40, 59, -1, 60, + -1, 62, -1, 60, 62, -1, -1, 60, 40, 60, + -1, 61, 40, 60, -1, 32, -1, 30, -1, 30, + 38, 30, -1, 30, 38, 30, 38, 30, -1, 33, + -1, 30, 39, 60, 36, -1, 30, 39, 61, 36, + -1, 34, -1, 31, -1, 63, -1, 26, -1, 35, + -1, 41, -1, 42, -1, 43, -1, 44, -1, 45, + -1, 46, -1, 47, -1, 66, 7, 65, 51, -1, + 8, 70, 71, 51, -1, 14, 55, 51, -1, 50, + -1, 39, 69, 36, -1, 65, 40, 39, 69, 36, + -1, -1, 39, 67, 36, -1, 68, -1, 67, 40, + 68, -1, 30, -1, 59, -1, 69, 40, 59, -1, + 56, -1, 70, 40, 56, -1, -1, 5, 55, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 376, 376, 377, 379, 380, 381, 382, 384, 385, - 386, 387, 389, 390, 392, 394, 395, 396, 397, 398, - 399, 401, 402, 403, 404, 405, 407, 408, 409, 410, - 411, 421, 428, 429, 430, 431, 432, 433, 434, 436, - 437, 439, 441, 442, 444, 445, 446, 448, 454, 460, - 466, 472, 478, 479, 480, 481, 487, 493, 494, 495, - 496, 497, 498, 499, 501, 502, 503, 504, 506, 510, - 515, 516, 521, 525, 530, 536, 546, 556, 557, 559, - 560 + 0, 475, 475, 476, 478, 479, 480, 481, 483, 484, + 485, 486, 488, 489, 491, 493, 494, 495, 496, 497, + 498, 500, 501, 502, 503, 504, 506, 507, 508, 509, + 510, 520, 521, 523, 524, 525, 526, 527, 528, 529, + 531, 532, 534, 536, 537, 539, 540, 541, 544, 551, + 557, 563, 569, 574, 580, 586, 587, 588, 589, 595, + 601, 602, 603, 604, 605, 606, 607, 609, 610, 611, + 612, 614, 618, 623, 624, 629, 633, 638, 644, 654, + 664, 665, 667, 668 }; #endif @@ -870,13 +974,14 @@ static const char *const yytname[] = { "$end", "error", "$undefined", "DUMMY_SELECT_CLAUSE", "DUMMY_INSERT_CLAUSE", "WHERE", "AS", "VALUES", "SET", "END_WHERE", - "JOIN", "AND_OP", "OR_OP", "IN", "ON", "BETWEEN", "ROWID", "COMP_EQ", - "COMP_NSEQ", "COMP_GE", "COMP_GT", "COMP_LE", "COMP_LT", "COMP_NE", - "PLACE_HOLDER", "END_P", "ERROR", "IGNORED_WORD", "NAME_OB", "STR_VAL", - "INT_VAL", "POS_PLACE_HOLDER", "')'", "';'", "'.'", "'('", "','", "'+'", - "'-'", "'*'", "'/'", "'%'", "'&'", "'!'", "$accept", "start", - "select_root", "end_flag", "join_expr_list", "join_on_expr", "join_expr", - "cond_expr", "bool_pri", "comp", "in_expr_list", "expr", "token_list", + "JOIN", "AND_OP", "OR_OP", "IN", "ON", "BETWEEN", "IS", "TOKEN_NULL", + "NOT", "COMP_EQ", "COMP_NSEQ", "COMP_GE", "COMP_GT", "COMP_LE", + "COMP_LT", "COMP_NE", "PLACE_HOLDER", "END_P", "ERROR", "IGNORED_WORD", + "NAME_OB", "STR_VAL", "ROW_ID", "REVERSED_EXPR_FUNC", "INT_VAL", + "POS_PLACE_HOLDER", "')'", "';'", "'.'", "'('", "','", "'+'", "'-'", + "'*'", "'/'", "'%'", "'&'", "'!'", "$accept", "start", "select_root", + "end_flag", "join_expr_list", "join_on_expr", "join_expr", "cond_expr", + "bool_pri", "comp", "in_expr_list", "expr", "token_list", "func_param_list", "token", "operator", "insert_root", "values_expr_lists", "opt_column_list", "column_list", "opt_column", "values_expr_list", "set_expr", "opt_where_clause", 0 @@ -891,23 +996,23 @@ static const yytype_uint16 yytoknum[] = 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 41, 59, 46, 40, 44, 43, 45, 42, - 47, 37, 38, 33 + 285, 286, 287, 288, 289, 290, 41, 59, 46, 40, + 44, 43, 45, 42, 47, 37, 38, 33 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 44, 45, 45, 46, 46, 46, 46, 47, 47, - 47, 47, 48, 48, 49, 50, 50, 50, 50, 50, - 50, 51, 51, 51, 51, 51, 52, 52, 52, 52, - 52, 52, 53, 53, 53, 53, 53, 53, 53, 54, - 54, 55, 56, 56, 57, 57, 57, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 59, 59, 59, - 59, 59, 59, 59, 60, 60, 60, 60, 61, 61, - 62, 62, 63, 63, 64, 65, 65, 66, 66, 67, - 67 + 0, 48, 49, 49, 50, 50, 50, 50, 51, 51, + 51, 51, 52, 52, 53, 54, 54, 54, 54, 54, + 54, 55, 55, 55, 55, 55, 56, 56, 56, 56, + 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, + 58, 58, 59, 60, 60, 61, 61, 61, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 63, 63, 63, 63, 63, 63, 63, 64, 64, 64, + 64, 65, 65, 66, 66, 67, 67, 68, 69, 69, + 70, 70, 71, 71 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ @@ -916,12 +1021,12 @@ static const yytype_uint8 yyr2[] = 0, 2, 2, 2, 3, 2, 4, 1, 1, 1, 1, 1, 1, 2, 3, 2, 4, 3, 4, 5, 6, 1, 3, 5, 3, 5, 3, 5, 5, 5, - 5, 3, 1, 1, 1, 1, 1, 1, 1, 1, - 3, 1, 1, 2, 0, 3, 3, 1, 3, 5, - 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 4, 4, 3, 1, 3, 5, - 0, 3, 1, 3, 1, 1, 3, 1, 3, 0, - 2 + 5, 3, 4, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 1, 1, 2, 0, 3, 3, 1, 1, + 3, 5, 1, 4, 4, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 4, 4, 3, + 1, 3, 5, 0, 3, 1, 3, 1, 1, 3, + 1, 3, 0, 2 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -930,138 +1035,142 @@ static const yytype_uint8 yyr2[] = static const yytype_uint8 yydefact[] = { 0, 0, 0, 0, 7, 0, 0, 2, 0, 12, - 0, 0, 0, 0, 67, 3, 0, 1, 0, 55, - 47, 53, 52, 56, 0, 57, 58, 59, 60, 61, - 62, 63, 0, 21, 0, 41, 42, 54, 15, 0, - 8, 11, 9, 10, 5, 13, 0, 0, 77, 79, - 0, 74, 0, 72, 0, 0, 0, 44, 0, 0, - 0, 0, 4, 0, 0, 32, 33, 34, 35, 36, - 37, 38, 0, 43, 0, 17, 0, 0, 14, 0, - 0, 0, 0, 66, 71, 0, 0, 0, 31, 48, - 0, 0, 0, 0, 0, 22, 24, 0, 0, 0, - 26, 18, 16, 6, 0, 80, 78, 65, 73, 75, - 0, 0, 64, 0, 50, 0, 51, 0, 22, 24, - 26, 0, 39, 0, 0, 0, 19, 0, 68, 0, - 0, 49, 45, 46, 23, 25, 28, 29, 0, 30, - 27, 20, 76, 0, 40, 69 + 0, 0, 0, 0, 70, 3, 0, 1, 58, 49, + 56, 48, 52, 55, 59, 0, 60, 61, 62, 63, + 64, 65, 66, 0, 21, 0, 42, 43, 57, 15, + 0, 8, 11, 9, 10, 5, 13, 0, 0, 80, + 82, 0, 77, 0, 75, 0, 0, 45, 0, 0, + 0, 0, 4, 0, 0, 0, 33, 34, 35, 36, + 37, 38, 39, 0, 44, 0, 17, 0, 0, 14, + 0, 0, 0, 0, 69, 74, 0, 0, 0, 50, + 0, 0, 0, 0, 0, 22, 24, 0, 0, 31, + 0, 0, 26, 18, 16, 6, 0, 83, 81, 68, + 76, 78, 0, 0, 67, 0, 53, 0, 54, 0, + 22, 24, 26, 0, 40, 0, 32, 0, 0, 19, + 0, 71, 0, 0, 51, 46, 47, 23, 25, 28, + 29, 0, 30, 27, 20, 79, 0, 41, 72 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - -1, 3, 7, 44, 8, 9, 10, 32, 33, 72, - 121, 34, 35, 91, 36, 37, 15, 87, 16, 52, - 53, 110, 49, 82 + -1, 3, 7, 45, 8, 9, 10, 33, 34, 73, + 123, 35, 36, 91, 37, 38, 15, 88, 16, 53, + 54, 112, 50, 83 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -53 +#define YYPACT_NINF -54 static const yytype_int16 yypact[] = { - 25, 83, 7, 26, -53, 80, -15, -53, 34, -53, - 10, 100, 80, 18, -53, -53, 57, -53, 69, -53, - 19, -53, -53, -53, 80, -53, -53, -53, -53, -53, - -53, -53, 65, -53, 191, 160, -53, -53, 21, 80, - -53, -53, -53, -53, -53, -53, 80, 160, -53, 1, - 65, -53, -25, -53, 54, 63, 66, 160, 23, 191, - 100, 100, -53, 60, 160, -53, -53, -53, -53, -53, - -53, -53, 140, -53, 74, -53, 75, 65, 67, 198, - 80, 100, 36, -53, -53, 18, 160, 0, -53, 73, - 120, -14, 100, 100, 140, -53, -53, 160, 101, 160, - -53, -53, 13, -53, 160, 67, -53, -53, -53, -53, - 24, 78, -53, 97, -53, 160, -53, 160, 94, 95, - 102, 49, -53, 160, 104, 105, -53, 102, -53, 160, - 160, -53, 160, 160, -53, -53, -53, -53, 160, -53, - -53, -53, -53, 55, -53, -53 + 16, 77, 8, 7, -54, 109, -5, -54, 22, -54, + 24, 131, 109, 38, -54, -54, 44, -54, -54, 6, + -54, -54, -54, -54, -54, 109, -54, -54, -54, -54, + -54, -54, -54, 68, -54, 210, 175, -54, -54, 5, + 109, -54, -54, -54, -54, -54, -54, 109, 175, -54, + 0, 68, -54, -28, -54, 15, 43, 175, 79, 210, + 131, 131, -54, 36, 175, 75, -54, -54, -54, -54, + -54, -54, -54, 153, -54, 53, -54, 56, 68, 85, + 217, 109, 131, 62, -54, -54, 38, 175, -3, 50, + 87, -10, 131, 131, 153, -54, -54, 175, 83, -54, + 86, 175, -54, -54, 11, -54, 175, 85, -54, -54, + -54, -54, 10, 67, -54, 80, -54, 175, -54, 175, + 73, 76, 78, 21, -54, 175, -54, 88, 81, -54, + 78, -54, 175, 175, -54, 175, 175, -54, -54, -54, + -54, 175, -54, -54, -54, -54, 27, -54, -54 }; /* YYPGOTO[NTERM-NUM]. */ -static const yytype_int16 yypgoto[] = +static const yytype_int8 yypgoto[] = { - -53, -53, 130, -30, -53, 137, -53, -8, -10, -49, - -53, -24, -52, -53, -32, -53, -53, -53, -53, -53, - 61, 17, -53, -53 + -54, -54, 113, -23, -54, 117, -54, -11, -8, -38, + -54, -25, -53, -54, -34, -54, -54, -54, -54, -54, + 40, 3, -54, -54 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -71 +#define YYTABLE_NINF -74 static const yytype_int16 yytable[] = { - 59, 48, 62, 73, 50, 90, 80, 84, 4, 40, - 94, 85, 5, 38, -70, 11, 58, 6, 116, 125, - 83, 12, 117, 79, 46, 41, 17, 74, 1, 2, - 104, 77, 42, 43, 92, 93, 111, 81, 78, 39, - 98, 126, 13, 40, 6, 40, 51, 103, 100, 75, - 95, 96, 107, 56, 57, 76, 128, 112, 73, 41, - 129, 41, 109, 132, 54, 133, 42, 43, 42, 43, - 120, 106, 105, 122, 40, 124, 60, 61, 60, 61, - 127, 137, 118, 119, 4, 138, 55, 145, 5, 86, - 41, 129, 88, 6, 89, 97, 18, 42, 43, 139, - 73, 73, 101, 102, 19, 142, 109, 113, 20, 21, - 22, 23, 123, 130, 144, 24, 18, 25, 26, 27, - 28, 29, 30, 31, 19, 131, 134, 135, 20, 21, - 22, 23, 14, 141, 136, 47, 140, 25, 26, 27, - 28, 29, 30, 31, 19, 45, 108, 143, 20, 21, - 22, 23, 114, 0, 0, 0, 115, 25, 26, 27, - 28, 29, 30, 31, 19, 0, 0, 0, 20, 21, - 22, 23, 0, 0, 0, 99, 0, 25, 26, 27, - 28, 29, 30, 31, 19, 0, 0, 0, 20, 21, - 22, 23, 0, 0, 0, 0, 0, 25, 26, 27, - 28, 29, 30, 31, 63, 0, 64, 0, 65, 66, - 67, 68, 69, 70, 71, 65, 66, 67, 68, 69, - 70, 71 + 59, 51, 74, 49, 90, 81, 41, 17, 85, 4, + 62, 75, 86, 5, 58, -73, 11, 128, 6, 1, + 2, 94, 12, 80, 42, 39, 118, 40, 84, 78, + 119, 41, 6, 43, 44, 76, 79, 113, 47, 98, + 82, 129, 106, 77, 56, 57, 131, 13, 102, 42, + 132, 55, 95, 96, 87, 105, 74, 140, 43, 44, + 109, 141, 111, 148, 135, 114, 136, 132, 52, 122, + 107, 41, 124, 89, 108, 97, 127, 41, 4, 60, + 61, 130, 5, 103, 120, 121, 104, 6, 115, 42, + 92, 93, 99, 100, 125, 42, 60, 61, 43, 44, + 142, 74, 74, 126, 43, 44, 133, 145, 111, 137, + 134, 144, 138, 18, 139, 14, 147, 19, 20, 21, + 22, 23, 24, 116, 143, 46, 110, 117, 26, 27, + 28, 29, 30, 31, 32, 18, 146, 0, 0, 19, + 20, 21, 22, 23, 24, 0, 0, 0, 25, 0, + 26, 27, 28, 29, 30, 31, 32, 18, 0, 0, + 0, 19, 20, 21, 22, 23, 24, 0, 0, 0, + 48, 0, 26, 27, 28, 29, 30, 31, 32, 18, + 0, 0, 0, 19, 20, 21, 22, 23, 24, 0, + 0, 0, 101, 0, 26, 27, 28, 29, 30, 31, + 32, 18, 0, 0, 0, 19, 20, 21, 22, 23, + 24, 0, 0, 0, 0, 0, 26, 27, 28, 29, + 30, 31, 32, 63, 0, 64, 65, 0, 0, 66, + 67, 68, 69, 70, 71, 72, 66, 67, 68, 69, + 70, 71, 72 }; static const yytype_int16 yycheck[] = { - 24, 11, 32, 35, 12, 57, 5, 32, 1, 9, - 59, 36, 5, 28, 7, 8, 24, 10, 32, 6, - 50, 14, 36, 47, 14, 25, 0, 6, 3, 4, - 79, 39, 32, 33, 11, 12, 36, 36, 46, 5, - 64, 28, 35, 9, 10, 9, 28, 77, 72, 28, - 60, 61, 82, 34, 35, 34, 32, 87, 90, 25, - 36, 25, 86, 115, 7, 117, 32, 33, 32, 33, - 94, 81, 80, 97, 9, 99, 11, 12, 11, 12, - 104, 32, 92, 93, 1, 36, 17, 32, 5, 35, - 25, 36, 29, 10, 28, 35, 16, 32, 33, 123, - 132, 133, 28, 28, 24, 129, 130, 34, 28, 29, - 30, 31, 11, 35, 138, 35, 16, 37, 38, 39, - 40, 41, 42, 43, 24, 28, 32, 32, 28, 29, - 30, 31, 2, 28, 32, 35, 32, 37, 38, 39, - 40, 41, 42, 43, 24, 8, 85, 130, 28, 29, - 30, 31, 32, -1, -1, -1, 36, 37, 38, 39, - 40, 41, 42, 43, 24, -1, -1, -1, 28, 29, - 30, 31, -1, -1, -1, 35, -1, 37, 38, 39, - 40, 41, 42, 43, 24, -1, -1, -1, 28, 29, - 30, 31, -1, -1, -1, -1, -1, 37, 38, 39, - 40, 41, 42, 43, 13, -1, 15, -1, 17, 18, - 19, 20, 21, 22, 23, 17, 18, 19, 20, 21, - 22, 23 + 25, 12, 36, 11, 57, 5, 9, 0, 36, 1, + 33, 6, 40, 5, 25, 7, 8, 6, 10, 3, + 4, 59, 14, 48, 27, 30, 36, 5, 51, 40, + 40, 9, 10, 36, 37, 30, 47, 40, 14, 64, + 40, 30, 80, 38, 38, 39, 36, 39, 73, 27, + 40, 7, 60, 61, 39, 78, 90, 36, 36, 37, + 83, 40, 87, 36, 117, 88, 119, 40, 30, 94, + 81, 9, 97, 30, 82, 39, 101, 9, 1, 11, + 12, 106, 5, 30, 92, 93, 30, 10, 38, 27, + 11, 12, 17, 18, 11, 27, 11, 12, 36, 37, + 125, 135, 136, 17, 36, 37, 39, 132, 133, 36, + 30, 30, 36, 26, 36, 2, 141, 30, 31, 32, + 33, 34, 35, 36, 36, 8, 86, 40, 41, 42, + 43, 44, 45, 46, 47, 26, 133, -1, -1, 30, + 31, 32, 33, 34, 35, -1, -1, -1, 39, -1, + 41, 42, 43, 44, 45, 46, 47, 26, -1, -1, + -1, 30, 31, 32, 33, 34, 35, -1, -1, -1, + 39, -1, 41, 42, 43, 44, 45, 46, 47, 26, + -1, -1, -1, 30, 31, 32, 33, 34, 35, -1, + -1, -1, 39, -1, 41, 42, 43, 44, 45, 46, + 47, 26, -1, -1, -1, 30, 31, 32, 33, 34, + 35, -1, -1, -1, -1, -1, 41, 42, 43, 44, + 45, 46, 47, 13, -1, 15, 16, -1, -1, 19, + 20, 21, 22, 23, 24, 25, 19, 20, 21, 22, + 23, 24, 25 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { - 0, 3, 4, 45, 1, 5, 10, 46, 48, 49, - 50, 8, 14, 35, 46, 60, 62, 0, 16, 24, - 28, 29, 30, 31, 35, 37, 38, 39, 40, 41, - 42, 43, 51, 52, 55, 56, 58, 59, 28, 5, - 9, 25, 32, 33, 47, 49, 14, 35, 52, 66, - 51, 28, 63, 64, 7, 17, 34, 35, 51, 55, - 11, 12, 47, 13, 15, 17, 18, 19, 20, 21, - 22, 23, 53, 58, 6, 28, 34, 51, 51, 55, - 5, 36, 67, 47, 32, 36, 35, 61, 29, 28, - 56, 57, 11, 12, 53, 52, 52, 35, 55, 35, - 55, 28, 28, 47, 53, 51, 52, 47, 64, 55, - 65, 36, 47, 34, 32, 36, 32, 36, 52, 52, - 55, 54, 55, 11, 55, 6, 28, 55, 32, 36, - 35, 28, 56, 56, 32, 32, 32, 32, 36, 55, - 32, 28, 55, 65, 55, 32 + 0, 3, 4, 49, 1, 5, 10, 50, 52, 53, + 54, 8, 14, 39, 50, 64, 66, 0, 26, 30, + 31, 32, 33, 34, 35, 39, 41, 42, 43, 44, + 45, 46, 47, 55, 56, 59, 60, 62, 63, 30, + 5, 9, 27, 36, 37, 51, 53, 14, 39, 56, + 70, 55, 30, 67, 68, 7, 38, 39, 55, 59, + 11, 12, 51, 13, 15, 16, 19, 20, 21, 22, + 23, 24, 25, 57, 62, 6, 30, 38, 55, 55, + 59, 5, 40, 71, 51, 36, 40, 39, 65, 30, + 60, 61, 11, 12, 57, 56, 56, 39, 59, 17, + 18, 39, 59, 30, 30, 51, 57, 55, 56, 51, + 68, 59, 69, 40, 51, 38, 36, 40, 36, 40, + 56, 56, 59, 58, 59, 11, 17, 59, 6, 30, + 59, 36, 40, 39, 30, 60, 60, 36, 36, 36, + 36, 40, 59, 36, 30, 59, 69, 59, 36 }; #define yyerrok (yyerrstatus = 0) @@ -1998,81 +2107,77 @@ yyreduce: case 31: - { - result->has_rowid_ =true; - result->rowid_str_ = (yyvsp[(3) - (3)].str); - (yyval.relation) = NULL; - ;} + { (yyval.relation) = NULL; ;} break; case 32: - { (yyval.func) = F_COMP_EQ; ;} + { (yyval.relation) = NULL; ;} break; case 33: - { (yyval.func) = F_COMP_NSEQ; ;} + { (yyval.func) = F_COMP_EQ; ;} break; case 34: - { (yyval.func) = F_COMP_GE; ;} + { (yyval.func) = F_COMP_NSEQ; ;} break; case 35: - { (yyval.func) = F_COMP_GT; ;} + { (yyval.func) = F_COMP_GE; ;} break; case 36: - { (yyval.func) = F_COMP_LE; ;} + { (yyval.func) = F_COMP_GT; ;} break; case 37: - { (yyval.func) = F_COMP_LT; ;} + { (yyval.func) = F_COMP_LE; ;} break; case 38: - { (yyval.func) = F_COMP_NE; ;} + { (yyval.func) = F_COMP_LT; ;} break; case 39: - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + { (yyval.func) = F_COMP_NE; ;} break; case 40: - { (yyval.list) = (yyvsp[(1) - (3)].list); add_token_list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); ;} + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} break; case 41: - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + { (yyval.list) = (yyvsp[(1) - (3)].list); add_token_list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); ;} break; case 42: - { malloc_list((yyval.list), result, (yyvsp[(1) - (1)].node)); ;} + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} break; case 43: - { add_token((yyvsp[(1) - (2)].list), result, (yyvsp[(2) - (2)].node)); (yyval.list) = (yyvsp[(1) - (2)].list); ;} + { malloc_list((yyval.list), result, (yyvsp[(1) - (1)].node)); ;} break; case 44: - { (yyval.list) = NULL; ;} + { add_token((yyvsp[(1) - (2)].list), result, (yyvsp[(2) - (2)].node)); (yyval.list) = (yyvsp[(1) - (2)].list); ;} break; case 45: - { add_token_list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); (yyval.list) = (yyvsp[(1) - (3)].list); ;} + { (yyval.list) = NULL; ;} break; case 46: @@ -2082,6 +2187,21 @@ yyreduce: case 47: + { add_token_list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); (yyval.list) = (yyvsp[(1) - (3)].list); ;} + break; + + case 48: + + { + malloc_node((yyval.node), result, TOKEN_COLUMN); + (yyval.node)->part_key_idx_ = 0; + (yyval.node)->column_name_ = (yyvsp[(1) - (1)].str); + result->has_rowid_ = true; + ;} + break; + + case 49: + { malloc_node((yyval.node), result, TOKEN_COLUMN); (yyval.node)->part_key_idx_ = get_part_key_idx(NULL, NULL, &(yyvsp[(1) - (1)].str), result); @@ -2089,7 +2209,7 @@ yyreduce: ;} break; - case 48: + case 50: { malloc_node((yyval.node), result, TOKEN_COLUMN); @@ -2098,7 +2218,7 @@ yyreduce: ;} break; - case 49: + case 51: { malloc_node((yyval.node), result, TOKEN_COLUMN); @@ -2107,7 +2227,15 @@ yyreduce: ;} break; - case 50: + case 52: + + { + malloc_node((yyval.node), result, TOKEN_FUNC); + (yyval.node)->str_value_ = (yyvsp[(1) - (1)].str); + ;} + break; + + case 53: { malloc_node((yyval.node), result, TOKEN_FUNC); @@ -2116,7 +2244,7 @@ yyreduce: ;} break; - case 51: + case 54: { malloc_node((yyval.node), result, TOKEN_FUNC); @@ -2125,22 +2253,22 @@ yyreduce: ;} break; - case 52: + case 55: { malloc_node((yyval.node), result, TOKEN_INT_VAL); (yyval.node)->int_value_ = (yyvsp[(1) - (1)].num); ;} break; - case 53: + case 56: { malloc_node((yyval.node), result, TOKEN_STR_VAL); (yyval.node)->str_value_ = (yyvsp[(1) - (1)].str); ;} break; - case 54: + case 57: { malloc_node((yyval.node), result, TOKEN_OPERATOR); (yyval.node)->operator_ = (yyvsp[(1) - (1)].operator); ;} break; - case 55: + case 58: { result->placeholder_list_idx_++; @@ -2149,7 +2277,7 @@ yyreduce: ;} break; - case 56: + case 59: { malloc_node((yyval.node), result, TOKEN_PLACE_HOLDER); @@ -2157,71 +2285,76 @@ yyreduce: ;} break; - case 57: + case 60: { (yyval.operator) = OPT_ADD; ;} break; - case 58: + case 61: { (yyval.operator) = OPT_MINUS; ;} break; - case 59: + case 62: { (yyval.operator) = OPT_MUL; ;} break; - case 60: + case 63: { (yyval.operator) = OPT_DIV; ;} break; - case 61: + case 64: { (yyval.operator) = OPT_MOD; ;} break; - case 62: + case 65: { (yyval.operator) = OPT_AND; ;} break; - case 63: + case 66: { (yyval.operator) = OPT_NOT; ;} break; - case 64: + case 67: { YYACCEPT; ;} break; - case 65: + case 68: { YYACCEPT; ;} break; - case 66: + case 69: { YYACCEPT; ;} break; - case 68: + case 71: { result->multi_param_values_++; ;} break; - case 69: + case 72: { result->multi_param_values_++; ;} break; - case 72: + case 73: + + { init_part_key_all_match(result);;} + break; + + case 75: { malloc_list((yyval.list), result, (yyvsp[(1) - (1)].node)); @@ -2229,7 +2362,7 @@ yyreduce: ;} break; - case 73: + case 76: { malloc_list((yyval.list), result, (yyvsp[(3) - (3)].node)); @@ -2237,7 +2370,7 @@ yyreduce: ;} break; - case 74: + case 77: { set_part_key_column_idx(result, &(yyvsp[(1) - (1)].str)); @@ -2247,7 +2380,7 @@ yyreduce: ;} break; - case 75: + case 78: { if (result->multi_param_values_ < 1) { @@ -2260,7 +2393,7 @@ yyreduce: ;} break; - case 76: + case 79: { if (result->multi_param_values_ < 1) { @@ -2272,17 +2405,17 @@ yyreduce: ;} break; - case 77: + case 80: { check_and_add_relation(result, (yyvsp[(1) - (1)].relation)); ;} break; - case 78: + case 81: { check_and_add_relation(result, (yyvsp[(3) - (3)].relation)); ;} break; - case 80: + case 83: {;} break; diff --git a/src/obproxy/opsql/expr_parser/ob_expr_parser_utf8_tab.h b/src/obproxy/opsql/expr_parser/ob_expr_parser_utf8_tab.h index fb99836093dc701c3014aa4c19b977e7c7cf848f..9fee13472ff99664f57d0d10d38da1fad73ea086 100644 --- a/src/obproxy/opsql/expr_parser/ob_expr_parser_utf8_tab.h +++ b/src/obproxy/opsql/expr_parser/ob_expr_parser_utf8_tab.h @@ -69,22 +69,26 @@ extern int ob_expr_parser_utf8_yydebug; IN = 268, ON = 269, BETWEEN = 270, - ROWID = 271, - COMP_EQ = 272, - COMP_NSEQ = 273, - COMP_GE = 274, - COMP_GT = 275, - COMP_LE = 276, - COMP_LT = 277, - COMP_NE = 278, - PLACE_HOLDER = 279, - END_P = 280, - ERROR = 281, - IGNORED_WORD = 282, - NAME_OB = 283, - STR_VAL = 284, - INT_VAL = 285, - POS_PLACE_HOLDER = 286 + IS = 271, + TOKEN_NULL = 272, + NOT = 273, + COMP_EQ = 274, + COMP_NSEQ = 275, + COMP_GE = 276, + COMP_GT = 277, + COMP_LE = 278, + COMP_LT = 279, + COMP_NE = 280, + PLACE_HOLDER = 281, + END_P = 282, + ERROR = 283, + IGNORED_WORD = 284, + NAME_OB = 285, + STR_VAL = 286, + ROW_ID = 287, + REVERSED_EXPR_FUNC = 288, + INT_VAL = 289, + POS_PLACE_HOLDER = 290 }; #endif diff --git a/src/obproxy/opsql/expr_parser/ob_expr_parser_utils.h b/src/obproxy/opsql/expr_parser/ob_expr_parser_utils.h index fa1a4576f214eb387a2d16c743ae7043aae736fe..543d202698ccc8c3a35605c99be3a7fdedb25c78 100644 --- a/src/obproxy/opsql/expr_parser/ob_expr_parser_utils.h +++ b/src/obproxy/opsql/expr_parser/ob_expr_parser_utils.h @@ -116,7 +116,7 @@ public: { int64_t pos = 0; J_OBJ_START(); - //VBUF_PRINTF("alias_name: %.*s\n", result_.alias_name_.str_len_, result_.alias_name_.str_); + VBUF_PRINTF("has_rowid_: %d\n", result_.has_rowid_); for (int64_t i = 0; i < result_.relation_info_.relation_num_; ++i) { print_relation(buf, buf_len, pos, 0, result_.relation_info_.relations_[i]); } diff --git a/src/obproxy/opsql/expr_resolver/ob_expr_resolver.cpp b/src/obproxy/opsql/expr_resolver/ob_expr_resolver.cpp index ecb6802a614e7784a2269a99522d9a39a74c4dca..6a656e7e64481166858505a7f25ada97ce557cc1 100644 --- a/src/obproxy/opsql/expr_resolver/ob_expr_resolver.cpp +++ b/src/obproxy/opsql/expr_resolver/ob_expr_resolver.cpp @@ -11,6 +11,10 @@ */ #define USING_LOG_PREFIX PROXY +#include "opsql/func_expr_resolver/ob_func_expr_resolver.h" +#include "opsql/func_expr_parser/ob_func_expr_parser.h" +#include "opsql/func_expr_resolver/proxy_expr/ob_proxy_expr_factory.h" +#include "opsql/func_expr_resolver/proxy_expr/ob_proxy_expr.h" #include "opsql/expr_resolver/ob_expr_resolver.h" #include "proxy/route/obproxy_part_info.h" #include "proxy/route/obproxy_expr_calculator.h" @@ -20,11 +24,14 @@ #include "proxy/mysql/ob_prepare_statement_struct.h" #include "obutils/ob_proxy_sql_parser.h" #include "utils/ob_proxy_utils.h" +#include "dbconfig/ob_proxy_db_config_info.h" +#include "common/ob_obj_compare.h" using namespace oceanbase::common; using namespace oceanbase::obproxy::proxy; using namespace oceanbase::obproxy::obutils; using namespace oceanbase::obmysql; +using namespace oceanbase::obproxy::dbconfig; namespace oceanbase { @@ -60,6 +67,51 @@ int64_t ObExprResolverResult::to_string(char *buf, const int64_t buf_len) const return pos; } +/** + * @brief The range's border flag is decided by the last valid column. + * If use range directly, the range will cover partition which + * doesn't contain the data. + * + * @param range + * @param border_flags all columns' border flag + * @return int + */ +int ObExprResolver::preprocess_range(ObNewRange &range, ObIArray &border_flags) { + int ret = OB_SUCCESS; + ObObj *obj_start = const_cast(range.start_key_.get_obj_ptr()); + ObObj *obj_end = const_cast(range.end_key_.get_obj_ptr()); + int64_t invalid_idx = range.start_key_.get_obj_cnt(); + for (int64_t i = 0; i < range.start_key_.get_obj_cnt(); i++) { + // find the last valid col, + // use the last valid col's border flag as range's border flag + range.border_flag_.set_data(border_flags.at(i).get_data()); + if (OB_ISNULL(obj_start) || OB_ISNULL(obj_end)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null pointer"); + } else { + ObCompareCtx cmp_ctx(ObMaxType, CS_TYPE_INVALID, true, INVALID_TZ_OFF); + bool need_cast = false; + ObObj cmp_result(false); + if (OB_FAIL(ObObjCmpFuncs::compare(cmp_result, *obj_start, *obj_end, cmp_ctx, ObCmpOp::CO_EQ, need_cast))) { + LOG_WARN("fail to compare", K(ret)); + invalid_idx = i + 1; + ret = OB_SUCCESS; + break; + } else if (!cmp_result.get_bool()) { + invalid_idx = i + 1; + break; + } + } + } + // set the cols after invalid_idx(included) to (max : min) + for (int64_t i = invalid_idx; i < range.start_key_.get_obj_cnt(); i++) { + (obj_start + i)->set_max_value(); + (obj_end + i)->set_min_value(); + } + LOG_DEBUG("succ to simplify range", K(range)); + return ret; +} + int ObExprResolver::resolve(ObExprResolverContext &ctx, ObExprResolverResult &result) { int ret = OB_SUCCESS; @@ -67,27 +119,156 @@ int ObExprResolver::resolve(ObExprResolverContext &ctx, ObExprResolverResult &re ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid ctx", K(ctx.relation_info_), K(ret)); } else { - // ignore ret in for loop - for (int64_t i = 0; i < ctx.relation_info_->relation_num_; ++i) { - if (OB_ISNULL(ctx.relation_info_->relations_[i])) { - LOG_INFO("relations is not valid here, ignore it", - K(ctx.relation_info_->relations_[i]), K(i)); - } else if (OB_UNLIKELY(ctx.relation_info_->relations_[i]->level_ == PART_KEY_LEVEL_ZERO)) { - LOG_INFO("level is zero, ignore it"); + proxy::ObProxyPartInfo *part_info = ctx.part_info_; + + // to store partition column's border flag as order above like + // "where c2 > 1 and c1 < 33" => ordered_part_col_border [(exclusive_start, exclusive_end] + ObSEArray part_columns_border; + ObSEArray sub_part_columns_border; + + // init range and border + if (part_info->get_part_level() >= share::schema::PARTITION_LEVEL_ONE) { + if (OB_FAIL(result.ranges_[0].build_row_key(part_info->get_part_columns().count(), allocator_))) { + LOG_WARN("fail to init range", K(ret)); + } else { + for (int i = 0; OB_SUCC(ret) && i < part_info->get_part_columns().count(); i++) { + if (OB_FAIL(part_columns_border.push_back(ObBorderFlag()))) { + LOG_WARN("fail to push border flag", K(i), K(ret)); + } + } + } + } + if (part_info->get_part_level() == share::schema::PARTITION_LEVEL_TWO) { + if (OB_FAIL(result.ranges_[1].build_row_key(part_info->get_sub_part_columns().count(), allocator_))) { + LOG_WARN("fail to init range", K(ret)); } else { - int64_t part_idx = (ctx.relation_info_->relations_[i]->level_ >= PART_KEY_LEVEL_BOTH) ? 0 - : static_cast(ctx.relation_info_->relations_[i]->level_ - 1); - if (OB_FAIL(resolve_token_list(ctx.relation_info_->relations_[i], - ctx.part_info_, - ctx.client_request_, - ctx.client_info_, - ctx.ps_id_entry_, - ctx.text_ps_entry_, - result.ranges_[part_idx]))) { - LOG_INFO("fail to resolve token list, ignore it", K(ret)); + for (int i = 0; OB_SUCC(ret) && i < part_info->get_sub_part_columns().count(); i++) { + if (OB_FAIL(sub_part_columns_border.push_back(ObBorderFlag()))) { + LOG_WARN("fail to push border flag", K(i), K(ret)); + } } } } + + if (OB_SUCC(ret)) { + ObObj *target_obj = NULL; + void *tmp_buf = NULL; + + // ignore ret in for loop + // resolve every relation + for (int64_t i = 0; i < ctx.relation_info_->relation_num_; ++i) { + if (OB_ISNULL(ctx.relation_info_->relations_[i])) { + LOG_INFO("relations is not valid here, ignore it", + K(ctx.relation_info_->relations_[i]), K(i)); + } else if (OB_UNLIKELY(ctx.relation_info_->relations_[i]->level_ == PART_KEY_LEVEL_ZERO)) { + LOG_INFO("level is zero, ignore it"); + } else { + if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObObj)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc new obj", K(ret)); + } else if (OB_ISNULL(target_obj = new (tmp_buf) ObObj())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to do placement new", K(ret)); + } else if (OB_FAIL(resolve_token_list(ctx.relation_info_->relations_[i], ctx.part_info_, ctx.client_request_, + ctx.client_info_, ctx.ps_id_entry_, ctx.text_ps_entry_, target_obj, + ctx.sql_field_result_))) { + LOG_INFO("fail to resolve token list, ignore it", K(ret)); + } else if ((PART_KEY_LEVEL_ONE == ctx.relation_info_->relations_[i]->level_ || + PART_KEY_LEVEL_BOTH == ctx.relation_info_->relations_[i]->level_) && + OB_FAIL(place_obj_to_range(ctx.relation_info_->relations_[i]->type_, + ctx.relation_info_->relations_[i]->first_part_column_idx_, + target_obj, &result.ranges_[0], part_columns_border))) { + LOG_WARN("fail to place obj to range of part level one", K(ret)); + } else if ((PART_KEY_LEVEL_TWO == ctx.relation_info_->relations_[i]->level_ || + PART_KEY_LEVEL_BOTH == ctx.relation_info_->relations_[i]->level_) && + OB_FAIL(place_obj_to_range(ctx.relation_info_->relations_[i]->type_, + ctx.relation_info_->relations_[i]->second_part_column_idx_, + target_obj, &result.ranges_[1], sub_part_columns_border))) { + LOG_WARN("fail to place obj to range of part level two", K(ret)); + } else {} + if (OB_NOT_NULL(target_obj)) { + allocator_.free(target_obj); + } + } + } + + if (OB_SUCC(ret) && ctx.is_insert_stm_) { + if(OB_FAIL(handle_default_value(ctx.parse_result_->part_key_info_, + ctx.client_info_, result.ranges_, + ctx.sql_field_result_,part_columns_border, + sub_part_columns_border, part_info->is_oracle_mode()))){ + LOG_WARN("fail to handle default value of part keys", K(ret)); + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(preprocess_range(result.ranges_[0], part_columns_border))) { + LOG_WARN("fail to preprocess range, part key level 0", K(ret)); + } else if (OB_FAIL(preprocess_range(result.ranges_[1], sub_part_columns_border))) { + LOG_WARN("fail to preprocess range, part key level 1", K(ret)); + } else {} + } + } + } + return ret; +} + +/** + * @brief 1. Place the resolved partition obj to range.start_key_/range.end_key_[idx]. + * The idx is the obj's according column's idx in partition expression. + * 2. Set the border flag of the partition obj. Use the border flag later in ObExprResolver::preprocess_range. + * + * @param relation + * @param part_info + * @param target_obj + * @param range out + * @param border_flags out + * @param part_columns + * @return int + */ +int ObExprResolver::place_obj_to_range(ObProxyFunctionType type, + int64_t idx_in_part_columns, + ObObj *target_obj, + ObNewRange *range, + ObIArray &border_flags) +{ + int ret = OB_SUCCESS; + ObObj *start_obj = const_cast(range->start_key_.get_obj_ptr()) + idx_in_part_columns; + ObObj *end_obj = const_cast(range->end_key_.get_obj_ptr()) + idx_in_part_columns; + if (OB_ISNULL(start_obj) || OB_ISNULL(end_obj) || OB_ISNULL(target_obj)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null pointer"); + } + + // 1. deep copy the resolved obj to right position in result.ranges_[x] + // 2. set the resolved obj's border flag + if (OB_SUCC(ret)) { + switch (type) { + case F_COMP_EQ: + *start_obj = *target_obj; + *end_obj = *target_obj; + border_flags.at(idx_in_part_columns).set_inclusive_start(); + border_flags.at(idx_in_part_columns).set_inclusive_end(); + break; + case F_COMP_GE: + *start_obj = *target_obj; + border_flags.at(idx_in_part_columns).set_inclusive_start(); + break; + case F_COMP_GT: + *start_obj = *target_obj; + break; + case F_COMP_LE: + *end_obj = *target_obj; + border_flags.at(idx_in_part_columns).set_inclusive_end(); + break; + case F_COMP_LT: + *end_obj = *target_obj; + break; + default: + LOG_INFO("this func is not useful for range", "func_type", + get_obproxy_function_type(type)); + break; + } // end of switch } return ret; } @@ -108,177 +289,365 @@ int ObExprResolver::resolve_token_list(ObProxyRelationExpr *relation, ObClientSessionInfo *client_info, ObPsIdEntry *ps_id_entry, ObTextPsEntry *text_ps_entry, - ObNewRange &range) + ObObj *target_obj, + SqlFieldResult *sql_field_result, + const bool has_rowid) { int ret = OB_SUCCESS; UNUSED(text_ps_entry); - if (OB_ISNULL(relation) || OB_ISNULL(part_info)) { + if (OB_ISNULL(target_obj)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("target_obj is null"); + } else if (OB_ISNULL(relation) || OB_ISNULL(part_info)) { ret = OB_INVALID_ARGUMENT; LOG_INFO("relation or part info is null", K(relation), K(part_info), K(ret)); } else if (OB_ISNULL(relation->right_value_) || OB_ISNULL(relation->right_value_->head_)) { ret = OB_INVALID_ARGUMENT; LOG_INFO("token list or head is null", K(relation->right_value_), K(ret)); } else { - ObObj *target_obj = NULL; - void *tmp_buf = NULL; + ObProxyTokenNode *token = relation->right_value_->head_; + int64_t col_idx = relation->column_idx_; + if (TOKEN_STR_VAL == token->type_) { + target_obj->set_varchar(token->str_value_.str_, token->str_value_.str_len_); + target_obj->set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); + } else if (TOKEN_INT_VAL == token->type_) { + target_obj->set_int(token->int_value_); + } else if (TOKEN_PLACE_HOLDER == token->type_) { + int64_t param_index = token->placeholder_idx_; + if (OB_FAIL(get_obj_with_param(*target_obj, client_request, client_info, + part_info, ps_id_entry, param_index))) { + LOG_DEBUG("fail to get target obj with param", K(ret)); + } + } else if (TOKEN_FUNC == token->type_) { + if (OB_FAIL(calc_token_func_obj(token, client_info, *target_obj, sql_field_result, part_info->is_oracle_mode()))) { + LOG_WARN("fail to calc token func obj", K(ret)); + } + } else { + ret = OB_INVALID_ARGUMENT; + } + + if (OB_SUCC(ret) + && !has_rowid + && part_info->has_generated_key()) { + int64_t target_idx = -1; + ObProxyPartKeyInfo &part_key_info = part_info->get_part_key_info(); + if (col_idx >= part_key_info.key_num_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("relation column index is invalid", K(col_idx), K(part_key_info.key_num_), K(ret)); + } else if (part_key_info.part_keys_[col_idx].is_generated_) { + // do nothing, user sql explicitly contains value for generated key, no need to calculate + } else if (FALSE_IT(target_idx = part_key_info.part_keys_[col_idx].generated_col_idx_)) { + // will not come here + } else if (OB_UNLIKELY(0 > target_idx)) { + LOG_DEBUG("this relation's part key is not used to generate column"); + } else if (OB_UNLIKELY(target_idx >= part_key_info.key_num_) + || OB_UNLIKELY(!part_key_info.part_keys_[target_idx].is_generated_) + || OB_UNLIKELY(part_key_info.part_keys_[target_idx].level_ != relation->level_)) { + ret = OB_ENTRY_NOT_EXIST; + LOG_WARN("fail to get generated key value, source key is not offered", + K(col_idx), K(part_key_info.key_num_), K(target_idx), K(ret)); + } else if (OB_FAIL(calc_generated_key_value(*target_obj, part_key_info.part_keys_[col_idx], + part_info->is_oracle_mode()))) { + LOG_WARN("fail to get generated key value", K(target_obj), K(ret)); + } else { + LOG_DEBUG("succ to calculate generated key value", K(target_obj), K(ret)); + } + } + + if (OB_SUCC(ret) && ObStringTC == target_obj->get_type_class()) { + // The character set of the string parsed from the parser uses the value of the variable collation_connection + target_obj->set_collation_type(static_cast(client_info->get_collation_connection())); + } + } // end of else + return ret; +} + +/* + * calculate func token, convert token node to param node to reuse func resolver + */ +int ObExprResolver::calc_token_func_obj(ObProxyTokenNode *token, + ObClientSessionInfo *client_session_info, + ObObj &target_obj, + SqlFieldResult *sql_field_result, + const bool is_oracle_mode) +{ + int ret = OB_SUCCESS; + ObProxyParamNode *param_node = NULL; + ObProxyExprFactory factory(allocator_); + ObFuncExprResolverContext ctx(&allocator_, &factory); + ObFuncExprResolver resolver(ctx); + ObProxyExpr *expr; + + if (OB_FAIL(convert_token_node_to_param_node(token, param_node))) { + LOG_WARN("fail to convert func token to param node", K(ret)); + } else if (OB_ISNULL(param_node)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to convert func token to param node", K(ret)); + } else if (OB_FAIL(resolver.resolve(param_node, expr))) { + LOG_WARN("proxy expr resolve failed", K(ret)); + } else { + ObSEArray result_array; + ObProxyExprCalcItem calc_item(const_cast(sql_field_result)); + ObProxyExprCtx expr_ctx(0, TESTLOAD_NON, false, &allocator_, client_session_info); + expr_ctx.is_oracle_mode = is_oracle_mode; + if (OB_FAIL(expr->calc(expr_ctx, calc_item, result_array))) { + LOG_WARN("calc expr result failed", K(ret)); + } else if (OB_FAIL(result_array.at(0, target_obj))) { + LOG_WARN("get expr calc result fail", K(ret)); + } + } + + return ret; +} + +int ObExprResolver::handle_default_value(ObProxyPartKeyInfo &part_key_info, + proxy::ObClientSessionInfo *client_info, + common::ObNewRange ranges[], + obutils::SqlFieldResult *sql_field_result, + ObIArray &part_border_flags, + ObIArray &sub_part_border_flags, + bool is_oracle_mode) +{ + int ret = OB_SUCCESS; + ObObj *target_obj = NULL; + void *tmp_buf = NULL; + for (int i = 0; OB_SUCC(ret) && i < part_key_info.key_num_; i++) { + ObProxyPartKeyLevel level = part_key_info.part_keys_[i].level_; + int64_t column_idx = part_key_info.part_keys_[i].idx_in_part_columns_; + bool is_need_default_val = false; + if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObObj)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to alloc new obj", K(ret)); - } else { - target_obj = new (tmp_buf) ObObj(); - - ObProxyFunctionType &func_type = relation->type_; - ObProxyTokenNode *token = relation->right_value_->head_; - int64_t col_idx = relation->column_idx_; - if (TOKEN_STR_VAL == token->type_) { - target_obj->set_varchar(token->str_value_.str_, token->str_value_.str_len_); - target_obj->set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); - } else if (TOKEN_INT_VAL == token->type_) { - target_obj->set_int(token->int_value_); - } else if (TOKEN_PLACE_HOLDER == token->type_) { - int64_t param_index = token->placeholder_idx_; - if (OB_FAIL(get_obj_with_param(*target_obj, client_request, client_info, - part_info, ps_id_entry, param_index))) { - LOG_DEBUG("fail to get target obj with param", K(ret)); + } else if (OB_ISNULL(target_obj = new (tmp_buf) ObObj())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to do placement new ObObj", K(ret)); + } + + if(OB_SUCC(ret)){ + if (part_key_info.part_keys_[i].is_generated_ && !part_key_info.part_keys_[i].is_exist_in_sql_) { + int source_idx = -1; + ObProxyParseString *var_str = NULL; + for (int j = 0; j < part_key_info.key_num_; j++) { + if (part_key_info.part_keys_[j].generated_col_idx_ == i + && !part_key_info.part_keys_[j].is_exist_in_sql_) { + source_idx = j; + break; + } } - } else if (TOKEN_FUNC == token->type_) { - if (OB_FAIL(calc_token_func_obj(token, client_info, *target_obj))) { - LOG_WARN("fail to calc token func obj", K(ret)); + if (source_idx >= 0) { + int64_t real_source_idx = part_key_info.part_keys_[source_idx].real_source_idx_; + if (real_source_idx < 0 || real_source_idx > OBPROXY_MAX_PART_KEY_NUM){ + // invalid real source idx + } else if (FALSE_IT(var_str = &part_key_info.part_keys_[real_source_idx].default_value_) || var_str->str_len_ < 0 ){ + } else if (OB_FAIL(parse_and_resolve_default_value(*var_str, client_info, sql_field_result, target_obj, is_oracle_mode))){ + LOG_WARN("parse and resolve default value of partition key failed", K(ret)); + } else if (OB_FAIL(calc_generated_key_value(*target_obj, part_key_info.part_keys_[source_idx], is_oracle_mode))) { + LOG_WARN("fail to get generated key value", K(target_obj), K(ret)); + } else { + is_need_default_val = true; + } + } + } else if (!part_key_info.part_keys_[i].is_exist_in_sql_) { + ObProxyParseString &var_str = part_key_info.part_keys_[i].default_value_; + if (var_str.str_len_ > 0) { + if (OB_FAIL(parse_and_resolve_default_value(var_str, client_info, sql_field_result, target_obj, is_oracle_mode))) { + LOG_WARN("parse and resolve default value of partition key failed", K(ret)); + } else { + is_need_default_val = true; + } } - } else { - ret = OB_INVALID_ARGUMENT; } + } + + if (OB_SUCC(ret) && is_need_default_val) { + if ((PART_KEY_LEVEL_ONE == level || PART_KEY_LEVEL_BOTH == level) && + OB_FAIL(place_obj_to_range(F_COMP_EQ, column_idx, target_obj, &ranges[0], part_border_flags))) { + LOG_WARN("fail to place obj to range of part level one", K(ret)); + } else if ((PART_KEY_LEVEL_TWO == level || PART_KEY_LEVEL_BOTH == level) && + OB_FAIL(place_obj_to_range(F_COMP_EQ, column_idx, target_obj, &ranges[1], sub_part_border_flags))) { + LOG_WARN("fail to place obj to range of part level two", K(ret)); + } else {} + } + if (OB_NOT_NULL(target_obj)) { + allocator_.free(target_obj); + } + } + return ret; +} - if (part_info->has_generated_key()) { - int64_t target_idx = -1; - ObProxyPartKeyInfo &part_key_info = part_info->get_part_key_info(); - if (col_idx >= part_key_info.key_num_) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("relation column index is invalid", K(col_idx), K(part_key_info.key_num_), K(ret)); - } else if (part_key_info.part_keys_[col_idx].is_generated_) { - // do nothing, user sql explicitly contains value for generated key, no need to calculate - } else if (FALSE_IT(target_idx = part_key_info.part_keys_[col_idx].generated_col_idx_)) { - // will not come here - } else if (OB_UNLIKELY(target_idx >= part_key_info.key_num_) - || OB_UNLIKELY(target_idx < 0) - || OB_UNLIKELY(!part_key_info.part_keys_[target_idx].is_generated_) - || OB_UNLIKELY(part_key_info.part_keys_[target_idx].level_ != relation->level_)) { - ret = OB_ENTRY_NOT_EXIST; - LOG_WARN("fail to get generated key value, source key is not offered", - K(col_idx), K(part_key_info.key_num_), K(target_idx), K(ret)); - } else if (OB_FAIL(calc_generated_key_value(*target_obj, part_key_info.part_keys_[col_idx], - part_info->is_oracle_mode()))) { - LOG_WARN("fail to get generated key value", K(target_obj), K(ret)); +int ObExprResolver::parse_and_resolve_default_value(ObProxyParseString &default_value, + ObClientSessionInfo *client_session_info, + SqlFieldResult *sql_field_result, + ObObj *target_obj, + bool is_oracle_mode) +{ + int ret = OB_SUCCESS; + number::ObNumber nb; + if (default_value.str_len_ > 0 ){ + int64_t tmp_pos = 0; + if (OB_FAIL(target_obj->deserialize(default_value.str_ , default_value.str_len_, tmp_pos))) { + LOG_WARN("fail to deserialize default value of part key"); + } else if (FALSE_IT(LOG_DEBUG("default value deserialize succ" , K(*target_obj)))) { + } else if (target_obj->is_varchar() && is_oracle_mode) { + // oracle mode return the default as a unresolved varchar type obj + ObString default_value_expr = target_obj->get_varchar(); + if (default_value_expr.empty()) { + target_obj->set_varchar(ObString()); + } else if ('\'' == default_value_expr[0]) { + // match string type + ObString dst; + if (2 >= default_value_expr.length()) { + dst = ObString(); + // remove single quotes + } else if (OB_FAIL(ob_sub_str(allocator_, default_value_expr, 1, default_value_expr.length() - 2, dst))) { + LOG_WARN("get sub stirng of default value failed", K(ret)); + } + if (OB_SUCC(ret)) { + target_obj->set_varchar(dst); + } + } else if ( OB_SUCCESS == nb.from(default_value_expr.ptr(), default_value_expr.length(), allocator_)) { + // match positive number + } else if ('-' == default_value_expr[0] && 4 <= default_value_expr.length()) { + // match megative number + // server return negative with brackets, -1 -> -(1) + ObString number_part; + char *buf = NULL; + if(OB_FAIL(ob_sub_str(allocator_, default_value_expr, 2, default_value_expr.length() - 2, number_part))) { + LOG_WARN("get default value number part fail", K(ret)); + } else if (OB_ISNULL(buf = static_cast(allocator_.alloc(number_part.length() + 1)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("alloc memory failed", K(ret)); } else { - LOG_DEBUG("succ to calculate generated key value", K(target_obj), K(ret)); + MEMCPY(buf, "-", 1); + MEMCPY(buf + 1, number_part.ptr(), number_part.length()); + target_obj->set_varchar(ObString(number_part.length()+1, buf)); } - } + } else { + // match expr + ObFuncExprParser parser(allocator_, SHARDING_EXPR_FUNC_PARSE_MODE); + ObFuncExprParseResult result; - if (OB_SUCC(ret) && ObStringTC == target_obj->get_type_class()) { - // The character set of the string parsed from the parser uses the value of the variable collation_connection - target_obj->set_collation_type(static_cast(client_info->get_collation_connection())); - } + ObProxyExprFactory factory(allocator_); + ObFuncExprResolverContext ctx(&allocator_, &factory); + ObFuncExprResolver resolver(ctx); + ObProxyExpr *expr; - if (OB_SUCC(ret)) { - switch (func_type) { - case F_COMP_EQ: - range.start_key_.assign(target_obj, 1); - range.end_key_.assign(target_obj, 1); - range.border_flag_.set_inclusive_start(); - range.border_flag_.set_inclusive_end(); - break; - case F_COMP_GE: - range.start_key_.assign(target_obj, 1); - range.border_flag_.set_inclusive_start(); - break; - case F_COMP_GT: - range.start_key_.assign(target_obj, 1); - break; - case F_COMP_LE: - range.end_key_.assign(target_obj, 1); - range.border_flag_.set_inclusive_end(); - break; - case F_COMP_LT: - range.end_key_.assign(target_obj, 1); - break; - default: - LOG_INFO("this func is not useful for range", "func_type", - get_obproxy_function_type(func_type)); - break; - } // end of switch - } // end of if - } // end of else - } // end of else + if (OB_FAIL(parser.parse(default_value_expr, result))) { + LOG_INFO("parse default value expr failed", K(ret)); + } else if (OB_FAIL(resolver.resolve(result.param_node_, expr))) { + LOG_INFO("proxy expr resolve failed", K(ret)); + } else { + ObSEArray result_array; + ObProxyExprCalcItem calc_item(const_cast(sql_field_result)); + ObProxyExprCtx expr_ctx(0, TESTLOAD_NON, false, &allocator_, client_session_info); + expr_ctx.is_oracle_mode = is_oracle_mode; + if (OB_FAIL(expr->calc(expr_ctx, calc_item, result_array))) { + LOG_WARN("calc expr result failed", K(ret)); + } else if (OB_FAIL(result_array.at(0, *target_obj))) { + LOG_WARN("get expr calc result fail", K(ret)); + } + } + } + } else { + // mysql mode return the default value with resolved obj in column's type + // do nothing + } + } + if (OB_SUCC(ret) && ObStringTC == target_obj->get_type_class()) { + LOG_DEBUG("parse and resolve default value succ", K(*target_obj), K(ret)); + target_obj->set_collation_type(static_cast(client_session_info->get_collation_connection())); + } return ret; } -/* - * currently only support to_date/to_timestamp function - * currently support at least one param, at most two params now - */ -int ObExprResolver::calc_token_func_obj(ObProxyTokenNode *token, - ObClientSessionInfo *client_session_info, - ObObj &target_obj) +int ObExprResolver::convert_token_node_to_param_node(ObProxyTokenNode *token, + ObProxyParamNode *¶m) { int ret = OB_SUCCESS; - ObObjType target_type = ObMaxType; - ObString func_name(token->str_value_.str_len_ ,token->str_value_.str_); - - if (func_name.case_compare("to_date") == 0) { - target_type = ObDateTimeType; - } else if (func_name.case_compare("to_timestamp") == 0) { - target_type = ObTimestampNanoType; + if (OB_ISNULL(token)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(ret)); } else { - /* more function could be supported */ + void *tmp_buf = NULL; + if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObProxyParamNode)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc new param node", K(ret)); + } else { + param = new(tmp_buf) ObProxyParamNode(); + param->next_ = NULL; + if (TOKEN_INT_VAL == token->type_) { + param->int_value_ = token->int_value_; + param->type_ = PARAM_INT_VAL; + } else if (TOKEN_STR_VAL == token->type_) { + param->str_value_ = token->str_value_; + param->type_ = PARAM_STR_VAL; + } else if (TOKEN_FUNC == token->type_) { + if (OB_FAIL(recursive_convert_func_token(token, param))) { + LOG_WARN("convert func token node to param node failed", K(ret)); + } + } else { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("unexpected token node type, please check", K(ret), K(param->type_)); + } + } } + return ret; +} - if (target_type == ObMaxType) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("fail to parse token func, unsupported function name", K(ret), K(func_name)); - } else if (OB_ISNULL(token->child_) - || OB_ISNULL(token->child_->head_)){ +int ObExprResolver::recursive_convert_func_token(ObProxyTokenNode *token, + ObProxyParamNode *param) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(token) || OB_ISNULL(param) || token->type_ != TOKEN_FUNC) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("fail to parse token func, param list null", K(ret), K(token->str_value_.str_)); - } else { - ObCollationType collation = ObCharset::get_default_collation(ObCharset::get_default_charset()); - target_obj.set_collation_type(collation); - - ObProxyTokenNode *param_node = token->child_->head_; - if (param_node->type_ == TOKEN_STR_VAL) { - target_obj.set_varchar(param_node->str_value_.str_, param_node->str_value_.str_len_); - } else if (param_node->type_ == TOKEN_INT_VAL) { - target_obj.set_int(param_node->int_value_); + LOG_WARN("invalid argument", K(ret)); + } + + ObString func_name(token->str_value_.str_len_, token->str_value_.str_); + ObProxyExprType func_type = get_expr_token_func_type(&func_name); + if (OB_SUCC(ret) && func_type == OB_PROXY_EXPR_TYPE_NONE) { + ret = OB_ERR_FUNCTION_UNKNOWN; + LOG_WARN("unsupported func type", K(ret), K(func_name), K(func_type)); + } + + if (OB_SUCC(ret)) { + void *tmp_buf = NULL; + param->type_ = PARAM_FUNC; + if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObFuncExprNode)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc new func expr node", K(ret)); } else { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("unexpected token node type, please check", K(ret), K(param_node->type_)); - } - - if (OB_SUCC(ret)) { - ObString nls_format; - if (param_node->next_ != NULL) { - nls_format.assign_ptr(param_node->next_->str_value_.str_, param_node->next_->str_value_.str_len_); - } - - ObTimeZoneInfo tz_info; - ObDataTypeCastParams dtc_params; + param->func_expr_node_ = new(tmp_buf) ObFuncExprNode(); + param->func_expr_node_->func_type_ = func_type; + param->func_expr_node_->child_ = NULL; - if (!nls_format.empty()) { - dtc_params.tz_info_ = &tz_info; - dtc_params.set_nls_format_by_type(target_type, nls_format); + if (OB_ISNULL(token->child_)) { + // do nothing + } else if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObProxyParamNodeList)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc new token list", K(ret)); } else { - dtc_params.tz_info_ = &tz_info; - if (OB_FAIL(ObExprCalcTool::build_dtc_params(client_session_info, target_type, dtc_params))) { - LOG_WARN("fail to build dtc params", K(ret), K(target_type)); + param->func_expr_node_->child_ = new(tmp_buf) ObProxyParamNodeList(); + ObProxyParamNode head; + ObProxyParamNode *param_cur = &head; + ObProxyTokenNode *token_child = token->child_->head_; + int64_t child_num = 0; + for (; OB_SUCC(ret) && token_child != NULL; token_child = token_child->next_, param_cur = param_cur->next_) { + if (OB_FAIL(convert_token_node_to_param_node(token_child, param_cur->next_))) { + LOG_WARN("recursive convert func token failed", K(ret)); + } else { + child_num++; + } + } + if (OB_SUCC(ret)) { + param->func_expr_node_->child_->tail_ = param_cur; + param->func_expr_node_->child_->head_ = head.next_; + param->func_expr_node_->child_->child_num_ = child_num; } - } - - ObCastCtx cast_ctx(&allocator_, &dtc_params, CM_NULL_ON_WARN, collation); - if (OB_SUCC(ret) && OB_FAIL(ObObjCasterV2::to_type(target_type, collation, cast_ctx, target_obj, target_obj))) { - LOG_WARN("fail to cast obj", K(ret), K(target_obj), K(target_type), K(collation)); } } } - return ret; } @@ -344,21 +713,21 @@ int ObExprResolver::get_obj_with_param(ObObj &target_obj, ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid placeholder idx", K(param_index), K(call_info), K(ret)); } else { - const ObProxyCallParam &call_param = call_info.params_.at(param_index); - if (CALL_TOKEN_INT_VAL == call_param.type_) { + const ObProxyCallParam* call_param = call_info.params_.at(param_index); + if (CALL_TOKEN_INT_VAL == call_param->type_) { int64_t int_val = 0; - if (OB_FAIL(get_int_value(call_param.str_value_.string_, int_val))) { - LOG_WARN("fail to get int value", K(call_param.str_value_.string_), K(ret)); + if (OB_FAIL(get_int_value(call_param->str_value_.config_string_, int_val))) { + LOG_WARN("fail to get int value", K(call_param->str_value_.config_string_), K(ret)); } else { target_obj.set_int(int_val); } - } else if (CALL_TOKEN_STR_VAL == call_param.type_) { - target_obj.set_varchar(call_param.str_value_.string_); + } else if (CALL_TOKEN_STR_VAL == call_param->type_) { + target_obj.set_varchar(call_param->str_value_.config_string_); target_obj.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); - } else if (CALL_TOKEN_PLACE_HOLDER == call_param.type_) { + } else if (CALL_TOKEN_PLACE_HOLDER == call_param->type_) { need_use_execute_param = true; - if (OB_FAIL(get_int_value(call_param.str_value_.string_, execute_param_index))) { - LOG_WARN("fail to get int value", K(call_param.str_value_.string_), K(ret)); + if (OB_FAIL(get_int_value(call_param->str_value_.config_string_, execute_param_index))) { + LOG_WARN("fail to get int value", K(call_param->str_value_.config_string_), K(ret)); } } } @@ -390,17 +759,34 @@ int ObExprResolver::get_obj_with_param(ObObj &target_obj, if (OB_SUCC(ret) && need_use_execute_param && client_request->get_parse_result().is_text_ps_execute_stmt()) { + LOG_DEBUG("will cal obj with value from ps execute param", K(execute_param_index)); ObSqlParseResult &parse_result = client_request->get_parse_result(); - ObProxyTextPsExecuteInfo execute_info = parse_result.text_ps_execute_info_; - if (param_index >= execute_info.param_count_) { + ObProxyTextPsInfo execute_info = parse_result.text_ps_info_; + if (execute_param_index >= execute_info.param_count_) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("param index is large than param count", K(param_index), + LOG_WARN("param index is large than param count", K(execute_param_index), K(execute_info.param_count_), K(ret)); } else { - ObProxyTextPsExecuteParam ¶m = execute_info.params_.at(param_index); - ObString user_variable_name = param.str_value_.string_; + ObProxyTextPsParam* param = execute_info.params_.at(execute_param_index); + ObString user_variable_name = param->str_value_.config_string_; if (OB_FAIL(static_cast(*client_info).get_user_variable_value(user_variable_name, target_obj))) { LOG_WARN("get user variable failed", K(ret), K(user_variable_name)); + } else { + ObString user_var; + int tmp_ret = OB_SUCCESS; + if (target_obj.is_varchar()) { + if (OB_SUCCESS != (tmp_ret = target_obj.get_varchar(user_var))) { + LOG_WARN("get varchar failed", K(tmp_ret)); + } else { + char* ptr = user_var.ptr(); + int32_t len = user_var.length(); + // user var has store ' into value + if ((user_var[0] == 0x27 && user_var[len-1] == 0x27) || + (user_var[0] == 0x22 && user_var[len-1] == 0x22)) { + target_obj.set_varchar(ptr + 1, len - 2); + } + } + } } } } @@ -430,6 +816,63 @@ int ObExprResolver::get_obj_with_param(ObObj &target_obj, return ret; } +ObProxyExprType ObExprResolver::get_expr_token_func_type(ObString *func) +{ + ObProxyExprType type = OB_PROXY_EXPR_TYPE_NONE; + if (func == NULL) { + type = OB_PROXY_EXPR_TYPE_NONE; + } else if (0 == func->case_compare("HASH")) { + type = OB_PROXY_EXPR_TYPE_FUNC_HASH; + } else if (0 == func->case_compare("SUBSTR")) { + type = OB_PROXY_EXPR_TYPE_FUNC_SUBSTR; + } else if (0 == func->case_compare("CONCAT")) { + type = OB_PROXY_EXPR_TYPE_FUNC_CONCAT; + } else if (0 == func->case_compare("TOINT")) { + type = OB_PROXY_EXPR_TYPE_FUNC_TOINT; + } else if (0 == func->case_compare("DIV")) { + type = OB_PROXY_EXPR_TYPE_FUNC_DIV; + } else if (0 == func->case_compare("ADD")) { + type = OB_PROXY_EXPR_TYPE_FUNC_ADD; + } else if (0 == func->case_compare("SUB")) { + type = OB_PROXY_EXPR_TYPE_FUNC_SUB; + } else if (0 == func->case_compare("MUL")) { + type = OB_PROXY_EXPR_TYPE_FUNC_MUL; + } else if (0 == func->case_compare("SUM")) { + type = OB_PROXY_EXPR_TYPE_FUNC_SUM; + } else if (0 == func->case_compare("CONUT")) { + type = OB_PROXY_EXPR_TYPE_FUNC_COUNT; + } else if (0 == func->case_compare("MAX")) { + type = OB_PROXY_EXPR_TYPE_FUNC_MAX; + } else if (0 == func->case_compare("MIN")) { + type = OB_PROXY_EXPR_TYPE_FUNC_MIN; + } else if (0 == func->case_compare("AVG")) { + type = OB_PROXY_EXPR_TYPE_FUNC_AVG; + } else if (0 == func->case_compare("GROUP")) { + type = OB_PROXY_EXPR_TYPE_FUNC_GROUP; + } else if (0 == func->case_compare("ORDER")) { + type = OB_PROXY_EXPR_TYPE_FUNC_ORDER; + } else if (0 == func->case_compare("TESTLOAD")) { + type = OB_PROXY_EXPR_TYPE_FUNC_TESTLOAD; + } else if (0 == func->case_compare("SPLIT")) { + type = OB_PROXY_EXPR_TYPE_FUNC_SPLIT; + } else if (0 == func->case_compare("TO_DATE")) { + type = OB_PROXY_EXPR_TYPE_FUNC_TO_DATE; + } else if (0 == func->case_compare("TO_TIMESTAMP")) { + type = OB_PROXY_EXPR_TYPE_FUNC_TO_TIMESTAMP; + } else if (0 == func->case_compare("NVL")) { + type = OB_PROXY_EXPR_TYPE_FUNC_NVL; + } else if (0 == func->case_compare("TO_CHAR")) { + type = OB_PROXY_EXPR_TYPE_FUNC_TO_CHAR; + } else if (0 == func->case_compare("SYSDATE")) { + type = OB_PROXY_EXPR_TYPE_FUNC_SYSDATE; + } else if (0 == func->case_compare("MOD")) { + type = OB_PROXY_EXPR_TYPE_FUNC_MOD; + } else { + type = OB_PROXY_EXPR_TYPE_NONE; + } + return type; +} + } // end of opsql } // end of obproxy } // end of oceanbase diff --git a/src/obproxy/opsql/expr_resolver/ob_expr_resolver.h b/src/obproxy/opsql/expr_resolver/ob_expr_resolver.h index fc515185de73a46311b50b87f2c58abc975754b7..082b2eec2a3fd17fafba0fcf420ab6db2a40b5f9 100644 --- a/src/obproxy/opsql/expr_resolver/ob_expr_resolver.h +++ b/src/obproxy/opsql/expr_resolver/ob_expr_resolver.h @@ -25,6 +25,12 @@ class ObNewRange; } namespace obproxy { + +namespace obutils +{ +struct SqlFieldResult; +} + namespace proxy { class ObProxyPartInfo; @@ -38,7 +44,8 @@ namespace opsql struct ObExprResolverContext { ObExprResolverContext() : relation_info_(NULL), part_info_(NULL), client_request_(NULL), - ps_id_entry_(NULL), text_ps_entry_(NULL), client_info_(NULL) {} + ps_id_entry_(NULL), text_ps_entry_(NULL), client_info_(NULL), + sql_field_result_(NULL) {} // parse result ObProxyRelationInfo *relation_info_; proxy::ObProxyPartInfo *part_info_; @@ -47,6 +54,9 @@ struct ObExprResolverContext proxy::ObPsIdEntry *ps_id_entry_; proxy::ObTextPsEntry *text_ps_entry_; proxy::ObClientSessionInfo *client_info_; + obutils::SqlFieldResult *sql_field_result_; + ObExprParseResult *parse_result_; + bool is_insert_stm_; }; class ObExprResolverResult @@ -67,17 +77,27 @@ public: ~ObExprResolver() {} int resolve(ObExprResolverContext &ctx, ObExprResolverResult &result); -private: int resolve_token_list(ObProxyRelationExpr *relation, proxy::ObProxyPartInfo *part_info, proxy::ObProxyMysqlRequest *client_request, proxy::ObClientSessionInfo *client_info, proxy::ObPsIdEntry *ps_entry, proxy::ObTextPsEntry *text_ps_entry, - common::ObNewRange &range); + common::ObObj *target_obj, + obutils::SqlFieldResult *sql_field_result, + const bool has_rowid = false); +private: + int preprocess_range(common::ObNewRange &range, common::ObIArray &border_flags); + int place_obj_to_range(ObProxyFunctionType type, + int64_t idx_in_part_columns, + common::ObObj *target_obj, + common::ObNewRange *range, + common::ObIArray &border_flags); int calc_token_func_obj(ObProxyTokenNode *token, proxy::ObClientSessionInfo *client_session_info, - common::ObObj &target_obj); + common::ObObj &target_obj, + obutils::SqlFieldResult *sql_field_result, + const bool is_oracle_mode); int calc_generated_key_value(common::ObObj &obj, const ObProxyPartKey &part_key, const bool is_oracle_mode); int get_obj_with_param(common::ObObj &target_obj, proxy::ObProxyMysqlRequest *client_request, @@ -85,6 +105,24 @@ private: proxy::ObProxyPartInfo *part_info, proxy::ObPsIdEntry *ps_entry, const int64_t param_index); + int convert_token_node_to_param_node(ObProxyTokenNode *token, + ObProxyParamNode *¶m); + int recursive_convert_func_token(ObProxyTokenNode *token, + ObProxyParamNode *param); + int handle_default_value(ObProxyPartKeyInfo &part_info, + proxy::ObClientSessionInfo *client_info, + common::ObNewRange range[], + obutils::SqlFieldResult *sql_field_result, + common::ObIArray &part_border_flags, + common::ObIArray &sub_part_border_flags, + bool is_oracle_mode); + int parse_and_resolve_default_value(ObProxyParseString &default_value_expr, + proxy::ObClientSessionInfo *client_session_info, + obutils::SqlFieldResult *sql_field_result, + common::ObObj *target_obj, + bool is_oracle_mode); + + ObProxyExprType get_expr_token_func_type(common::ObString *func); common::ObIAllocator &allocator_; DISALLOW_COPY_AND_ASSIGN(ObExprResolver); diff --git a/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser.l b/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser.l index 06aef3ab96299bf5796d7eec746909a4333ea1d7..420b291eb0a1cb51799689ecfb76ec5eb2c06101 100644 --- a/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser.l +++ b/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser.l @@ -63,8 +63,11 @@ do {\ space [ \t\n\r\f] identifer ([A-Za-z0-9$_]*) -int_num [\-\+]?[0-9]+ -number ([0-9]+E[-+]?[0-9]+)|([0-9]+"."[0-9]*E[-+]?[0-9]+)|("."[0-9]+E[-+]?[0-9]+)|([0-9]+"."[0-9]*)|("."[0-9]+) + +/* limit the length of int_num from 1 to 17 in case of int64_t out of bound, 17 -> [ ( length of 2^64 ) - 2 ]*/ +int_num [\-\+]?[0-9]{1,17} +number ([\-]?[0-9]+E[-+]?[0-9]+)|([\-]?[0-9]+"."[0-9]*E[-+]?[0-9]+)|([\-]?"."[0-9]+E[-+]?[0-9]+)|([\-]?[0-9]+"."[0-9]*)|([\-]?"."[0-9]+)|([\-\+]?[0-9]{18,}) + whitespace ({space}+) c_cmt_begin \/\* @@ -97,16 +100,22 @@ rightbracket \) endtoken \# %% -substr { return FUNC_SUBSTR; } -substring { return FUNC_SUBSTR; } -concat { return FUNC_CONCAT; } -hash { return FUNC_HASH; } -toint { return FUNC_TOINT; } -div { return FUNC_DIV; } -add { return FUNC_ADD; } -sub { return FUNC_SUB; } -mul { return FUNC_MUL; } -testload { return FUNC_TESTLOAD; } +substr { return FUNC_SUBSTR; } +substring { return FUNC_SUBSTR; } +concat { return FUNC_CONCAT; } +hash { return FUNC_HASH; } +toint { return FUNC_TOINT; } +div { return FUNC_DIV; } +add { return FUNC_ADD; } +sub { return FUNC_SUB; } +mul { return FUNC_MUL; } +testload { return FUNC_TESTLOAD; } +to_date { return FUNC_TO_DATE; } +to_timestamp { return FUNC_TO_TIMESTAMP; } +nvl { return FUNC_NVL; } +to_char { return FUNC_TO_CHAR; } +mod { return FUNC_MOD; } +sysdate { return FUNC_SYSDATE; } {endtoken} { return TOKEN_SPECIAL; } diff --git a/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser.y b/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser.y index db953fa1ad7a0565d4c984d3935eae901f064b3c..5e32e90e32209faa867de6f279cf1d55d825f31a 100644 --- a/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser.y +++ b/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser.y @@ -83,11 +83,12 @@ static inline void add_param_node(ObProxyParamNodeList *list, ObFuncExprParseRes %token DUMMY_FUNCTION_CLAUSE /* reserved keyword */ %token TOKEN_SPECIAL FUNC_SUBSTR FUNC_CONCAT FUNC_HASH FUNC_TOINT FUNC_DIV FUNC_ADD FUNC_SUB FUNC_MUL FUNC_TESTLOAD +%token FUNC_TO_DATE FUNC_TO_TIMESTAMP FUNC_NVL FUNC_TO_CHAR FUNC_MOD FUNC_SYSDATE %token END_P ERROR IGNORED_WORD /* type token */ %token NAME_OB STR_VAL NUMBER_VAL %token INT_VAL -%type func_name +%type func_name reserved_func %type param_list %type func_expr %type param @@ -113,6 +114,11 @@ func_expr: func_name '(' param_list ')' malloc_func_expr_node($$, result, $1); $$->child_ = NULL; } + | reserved_func + { + malloc_func_expr_node($$, result, $1); + $$->child_ = NULL; + } func_name: FUNC_SUBSTR { $$ = OB_PROXY_EXPR_TYPE_FUNC_SUBSTR; } | FUNC_CONCAT { $$ = OB_PROXY_EXPR_TYPE_FUNC_CONCAT; } @@ -123,6 +129,13 @@ func_name: FUNC_SUBSTR { $$ = OB_PROXY_EXPR_TYPE_FUNC_SUBSTR; } | FUNC_SUB { $$ = OB_PROXY_EXPR_TYPE_FUNC_SUB; } | FUNC_MUL { $$ = OB_PROXY_EXPR_TYPE_FUNC_MUL; } | FUNC_TESTLOAD { $$ = OB_PROXY_EXPR_TYPE_FUNC_TESTLOAD; } + | FUNC_TO_DATE { $$ = OB_PROXY_EXPR_TYPE_FUNC_TO_DATE; } + | FUNC_TO_TIMESTAMP { $$ = OB_PROXY_EXPR_TYPE_FUNC_TO_TIMESTAMP; } + | FUNC_NVL { $$ = OB_PROXY_EXPR_TYPE_FUNC_NVL; } + | FUNC_TO_CHAR { $$ = OB_PROXY_EXPR_TYPE_FUNC_TO_CHAR; } + | FUNC_MOD { $$ = OB_PROXY_EXPR_TYPE_FUNC_MOD; } + +reserved_func: FUNC_SYSDATE { $$ = OB_PROXY_EXPR_TYPE_FUNC_SYSDATE; } param_list: param { diff --git a/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser_lex.c b/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser_lex.c index 0a5152330a4976f74bcd76973275f0807e0125b2..3580edb3c22802689665f4dae3fb9e589a86aea0 100644 --- a/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser_lex.c +++ b/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser_lex.c @@ -348,8 +348,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); yyg->yy_hold_char = *yy_cp; \ yyg->yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 41 -#define YY_END_OF_BUFFER 42 +#define YY_NUM_RULES 47 +#define YY_END_OF_BUFFER 48 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -357,21 +357,30 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[115] = +static yyconst flex_int16_t yy_accept[201] = { 0, - 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, - 42, 40, 18, 18, 19, 30, 11, 14, 24, 19, - 19, 19, 12, 14, 14, 14, 14, 14, 14, 14, - 36, 23, 22, 23, 25, 26, 41, 31, 32, 41, - 38, 39, 18, 16, 0, 14, 0, 15, 12, 13, - 20, 13, 12, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 0, 17, 0, 21, 25, 0, 27, 28, - 31, 0, 33, 34, 38, 37, 0, 13, 0, 0, - 13, 7, 14, 6, 14, 9, 8, 14, 14, 29, - 35, 0, 13, 0, 13, 13, 14, 4, 14, 14, - - 14, 14, 14, 14, 5, 3, 1, 14, 14, 14, - 14, 10, 2, 0 + 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, + 48, 46, 24, 24, 25, 36, 17, 20, 30, 25, + 25, 25, 25, 18, 20, 20, 20, 20, 20, 20, + 20, 20, 42, 29, 28, 29, 31, 32, 47, 37, + 38, 47, 44, 45, 24, 22, 0, 20, 0, 21, + 18, 0, 18, 19, 26, 19, 18, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, + 23, 0, 27, 31, 0, 33, 34, 37, 0, 39, + 40, 44, 43, 18, 18, 0, 0, 19, 0, 18, + 0, 19, 7, 20, 6, 20, 15, 9, 13, 8, + + 20, 20, 20, 20, 35, 41, 18, 18, 19, 0, + 19, 0, 19, 18, 20, 4, 20, 20, 20, 20, + 20, 20, 20, 18, 18, 18, 20, 20, 20, 20, + 5, 20, 20, 20, 18, 18, 18, 3, 1, 20, + 20, 20, 20, 20, 18, 18, 18, 20, 16, 20, + 14, 11, 20, 18, 18, 18, 20, 10, 20, 18, + 18, 18, 2, 20, 18, 18, 18, 20, 18, 18, + 18, 20, 18, 18, 18, 12, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 19, 19, 19, 19, 19, 19, 0 + } ; static yyconst flex_int32_t yy_ec[256] = @@ -380,16 +389,16 @@ static yyconst flex_int32_t yy_ec[256] = 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 5, 6, 7, 4, 4, 8, 4, - 4, 9, 10, 4, 10, 11, 12, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 4, 4, 1, - 4, 1, 4, 4, 14, 15, 16, 17, 18, 7, - 19, 20, 21, 7, 7, 22, 23, 24, 25, 7, - 7, 26, 27, 28, 29, 30, 7, 7, 7, 7, - 1, 31, 1, 4, 7, 32, 33, 34, 35, 36, - - 37, 7, 38, 39, 40, 7, 7, 41, 42, 43, - 44, 7, 7, 45, 46, 47, 48, 49, 7, 7, - 7, 7, 1, 4, 1, 4, 1, 1, 1, 1, + 4, 9, 10, 4, 11, 12, 13, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 4, 4, 1, + 4, 1, 4, 4, 15, 16, 17, 18, 19, 7, + 20, 21, 22, 7, 7, 23, 24, 25, 26, 27, + 7, 28, 29, 30, 31, 32, 7, 7, 33, 7, + 1, 34, 1, 4, 35, 36, 37, 38, 39, 40, + + 41, 7, 42, 43, 44, 7, 7, 45, 46, 47, + 48, 49, 7, 50, 51, 52, 53, 54, 7, 7, + 55, 7, 1, 4, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -406,123 +415,202 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst flex_int32_t yy_meta[50] = +static yyconst flex_int32_t yy_meta[56] = { 0, 1, 1, 1, 1, 2, 1, 3, 4, 1, 1, - 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, + 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 5, 3, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 5, 6, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3 + 3, 3, 3, 3, 3 } ; -static yyconst flex_int16_t yy_base[128] = +static yyconst flex_int16_t yy_base[214] = { 0, - 0, 0, 47, 48, 44, 45, 49, 50, 217, 216, - 247, 250, 56, 58, 250, 241, 250, 0, 237, 231, - 230, 233, 51, 46, 40, 45, 53, 39, 41, 53, - 209, 250, 250, 65, 0, 90, 0, 0, 97, 0, - 0, 208, 70, 250, 234, 0, 230, 250, 212, 78, - 250, 88, 92, 94, 77, 71, 78, 82, 89, 97, - 89, 96, 190, 250, 109, 250, 0, 130, 250, 250, - 0, 117, 250, 250, 0, 250, 113, 121, 127, 200, - 199, 0, 108, 0, 121, 0, 115, 116, 121, 250, - 250, 194, 193, 149, 146, 70, 132, 0, 119, 126, - - 121, 122, 125, 127, 0, 0, 132, 140, 131, 139, - 138, 0, 0, 250, 176, 182, 188, 194, 199, 76, - 200, 202, 208, 214, 220, 226, 232 + 0, 0, 53, 54, 50, 51, 55, 56, 384, 382, + 415, 508, 62, 64, 508, 403, 508, 0, 398, 389, + 56, 388, 390, 57, 54, 47, 52, 60, 51, 46, + 48, 61, 361, 508, 508, 79, 0, 103, 0, 0, + 105, 0, 0, 342, 110, 508, 369, 0, 365, 508, + 358, 351, 102, 101, 508, 103, 111, 117, 100, 94, + 92, 97, 111, 109, 110, 118, 106, 107, 115, 328, + 508, 136, 508, 0, 158, 508, 508, 0, 160, 508, + 508, 0, 508, 345, 155, 161, 166, 154, 168, 169, + 341, 340, 0, 147, 0, 149, 0, 0, 0, 155, + + 167, 157, 164, 173, 508, 508, 335, 185, 331, 328, + 326, 319, 317, 186, 178, 0, 164, 186, 179, 178, + 193, 202, 196, 316, 219, 223, 189, 193, 192, 202, + 0, 214, 202, 210, 314, 233, 234, 0, 227, 236, + 242, 230, 240, 242, 308, 251, 254, 237, 0, 249, + 0, 0, 240, 307, 274, 282, 256, 0, 248, 288, + 285, 291, 0, 270, 273, 294, 297, 266, 268, 305, + 306, 287, 258, 315, 325, 0, 206, 329, 338, 139, + 339, 348, 133, 349, 357, 125, 363, 369, 124, 372, + 373, 79, 381, 382, 77, 393, 397, 72, 405, 508, + + 446, 452, 458, 464, 469, 80, 470, 472, 478, 484, + 490, 496, 502 } ; -static yyconst flex_int16_t yy_def[128] = +static yyconst flex_int16_t yy_def[214] = { 0, - 114, 1, 115, 115, 116, 116, 117, 117, 118, 118, - 114, 114, 114, 114, 114, 119, 114, 120, 121, 114, - 114, 114, 120, 120, 120, 120, 120, 120, 120, 120, - 122, 114, 114, 114, 123, 114, 124, 125, 114, 126, - 127, 114, 114, 114, 119, 120, 121, 114, 114, 114, - 114, 114, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 122, 114, 114, 114, 123, 114, 114, 114, - 125, 114, 114, 114, 127, 114, 114, 114, 114, 114, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 114, - 114, 114, 114, 114, 114, 114, 120, 120, 120, 120, - - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 0, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114 + 200, 1, 201, 201, 202, 202, 203, 203, 204, 204, + 200, 200, 200, 200, 200, 205, 200, 206, 207, 200, + 200, 200, 200, 206, 206, 206, 206, 206, 206, 206, + 206, 206, 208, 200, 200, 200, 209, 200, 210, 211, + 200, 212, 213, 200, 200, 200, 205, 206, 207, 200, + 200, 200, 200, 200, 200, 200, 206, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 208, + 200, 200, 200, 209, 200, 200, 200, 211, 200, 200, + 200, 213, 200, 200, 200, 200, 200, 200, 200, 206, + 200, 206, 206, 206, 206, 206, 206, 206, 206, 206, + + 206, 206, 206, 206, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 206, 206, 206, 206, 206, 206, 206, + 206, 206, 206, 200, 200, 206, 206, 206, 206, 206, + 206, 206, 206, 206, 200, 200, 206, 206, 206, 206, + 206, 206, 206, 206, 200, 200, 206, 206, 206, 206, + 206, 206, 206, 200, 200, 206, 206, 206, 206, 200, + 200, 206, 206, 206, 200, 200, 206, 206, 200, 200, + 206, 206, 200, 200, 206, 206, 200, 200, 206, 200, + 200, 206, 200, 200, 206, 200, 200, 206, 200, 200, + 206, 200, 200, 206, 200, 200, 206, 200, 200, 0, + + 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200 } ; -static yyconst flex_int16_t yy_nxt[300] = +static yyconst flex_int16_t yy_nxt[564] = { 0, 12, 13, 14, 15, 16, 17, 18, 19, 15, 20, - 21, 22, 23, 24, 18, 25, 26, 18, 18, 27, - 18, 18, 28, 18, 18, 18, 29, 30, 18, 18, - 12, 31, 24, 18, 25, 26, 18, 18, 27, 18, - 18, 28, 18, 18, 18, 29, 30, 18, 18, 33, - 33, 36, 36, 39, 39, 34, 34, 43, 43, 43, - 43, 52, 55, 53, 56, 57, 58, 59, 54, 60, - 61, 43, 43, 65, 37, 37, 66, 62, 46, 40, - 40, 55, 96, 56, 57, 58, 59, 54, 60, 61, - 50, 68, 68, 82, 83, 77, 62, 69, 72, 72, - - 78, 73, 52, 80, 53, 79, 81, 84, 85, 54, - 86, 87, 82, 83, 77, 88, 89, 65, 72, 72, - 66, 91, 92, 97, 79, 93, 84, 85, 54, 86, - 87, 68, 68, 78, 88, 89, 94, 90, 79, 95, - 98, 99, 97, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 79, 95, 98, - 99, 95, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 32, 32, 32, 32, - 32, 32, 35, 35, 35, 35, 35, 35, 38, 38, - 38, 38, 38, 38, 41, 41, 41, 41, 41, 41, - - 45, 45, 47, 47, 63, 93, 93, 63, 67, 67, - 67, 81, 96, 67, 70, 70, 70, 70, 70, 70, - 71, 64, 71, 71, 49, 71, 74, 74, 74, 74, - 74, 74, 75, 75, 75, 75, 75, 48, 44, 76, - 64, 51, 50, 49, 48, 44, 114, 42, 42, 11, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114 - + 21, 22, 23, 24, 25, 18, 26, 27, 18, 18, + 28, 18, 18, 29, 30, 18, 18, 18, 31, 32, + 18, 18, 18, 12, 18, 33, 25, 18, 26, 27, + 18, 18, 28, 18, 18, 29, 30, 18, 18, 18, + 31, 32, 18, 18, 18, 35, 35, 38, 38, 41, + 41, 36, 36, 45, 45, 45, 45, 52, 56, 53, + 57, 59, 60, 61, 62, 58, 63, 65, 66, 68, + 67, 64, 48, 39, 39, 198, 69, 72, 42, 42, + 198, 73, 195, 59, 60, 61, 62, 58, 63, 65, + + 66, 68, 67, 64, 75, 75, 79, 79, 69, 80, + 76, 45, 45, 56, 54, 85, 88, 93, 94, 87, + 86, 89, 56, 95, 90, 96, 91, 91, 97, 58, + 92, 98, 99, 100, 101, 102, 103, 192, 189, 93, + 94, 87, 86, 89, 72, 95, 186, 96, 73, 104, + 97, 58, 183, 98, 99, 100, 101, 102, 103, 75, + 75, 79, 79, 115, 106, 105, 56, 88, 108, 116, + 91, 91, 89, 86, 109, 110, 110, 112, 112, 111, + 56, 113, 114, 117, 118, 115, 119, 58, 120, 121, + 122, 116, 127, 128, 89, 86, 56, 56, 125, 126, + + 129, 130, 123, 86, 58, 117, 118, 131, 119, 58, + 120, 121, 122, 132, 127, 128, 133, 134, 138, 180, + 139, 140, 129, 130, 123, 86, 58, 141, 142, 131, + 56, 143, 136, 144, 56, 132, 137, 86, 133, 134, + 138, 58, 139, 140, 56, 56, 146, 147, 148, 141, + 142, 86, 58, 143, 149, 144, 150, 151, 152, 86, + 153, 157, 56, 58, 155, 56, 158, 156, 159, 86, + 148, 177, 58, 86, 58, 163, 149, 164, 150, 151, + 152, 173, 153, 157, 168, 56, 169, 161, 158, 172, + 159, 86, 86, 56, 58, 162, 56, 163, 166, 164, + + 58, 165, 56, 86, 167, 56, 168, 170, 56, 58, + 171, 172, 86, 176, 86, 58, 56, 56, 174, 175, + 160, 154, 58, 86, 58, 86, 56, 145, 178, 135, + 113, 58, 113, 86, 86, 176, 56, 58, 179, 111, + 56, 111, 181, 58, 109, 86, 58, 86, 124, 56, + 56, 182, 184, 92, 109, 86, 58, 86, 107, 56, + 56, 185, 187, 71, 54, 58, 58, 86, 56, 86, + 188, 84, 50, 46, 56, 58, 190, 83, 58, 86, + 56, 86, 191, 56, 56, 193, 194, 58, 58, 86, + 86, 58, 56, 56, 196, 197, 71, 58, 55, 86, + + 58, 54, 51, 86, 56, 50, 199, 46, 56, 58, + 197, 86, 86, 58, 200, 58, 56, 44, 199, 44, + 200, 86, 58, 86, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 86, 200, 200, 200, 58, 200, 200, + 200, 200, 200, 200, 200, 86, 34, 34, 34, 34, + 34, 34, 37, 37, 37, 37, 37, 37, 40, 40, + 40, 40, 40, 40, 43, 43, 43, 43, 43, 43, + 47, 47, 49, 49, 70, 200, 200, 70, 74, 74, + 74, 200, 200, 74, 77, 77, 77, 77, 77, 77, + 78, 200, 78, 78, 200, 78, 81, 81, 81, 81, + + 81, 81, 82, 82, 82, 82, 82, 11, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200 } ; -static yyconst flex_int16_t yy_chk[300] = +static yyconst flex_int16_t yy_chk[564] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, - 4, 5, 6, 7, 8, 3, 4, 13, 13, 14, - 14, 23, 24, 23, 25, 26, 27, 28, 23, 29, - 30, 43, 43, 34, 5, 6, 34, 30, 120, 7, - 8, 24, 96, 25, 26, 27, 28, 23, 29, 30, - 50, 36, 36, 55, 56, 50, 30, 36, 39, 39, - - 52, 39, 53, 54, 53, 52, 54, 57, 58, 53, - 59, 60, 55, 56, 50, 61, 62, 65, 72, 72, - 65, 72, 77, 83, 52, 77, 57, 58, 53, 59, - 60, 68, 68, 78, 61, 62, 79, 68, 78, 79, - 85, 87, 83, 88, 89, 97, 99, 100, 101, 102, - 103, 104, 107, 108, 109, 110, 111, 78, 95, 85, - 87, 94, 88, 89, 97, 99, 100, 101, 102, 103, - 104, 107, 108, 109, 110, 111, 115, 115, 115, 115, - 115, 115, 116, 116, 116, 116, 116, 116, 117, 117, - 117, 117, 117, 117, 118, 118, 118, 118, 118, 118, - - 119, 119, 121, 121, 122, 93, 92, 122, 123, 123, - 123, 81, 80, 123, 124, 124, 124, 124, 124, 124, - 125, 63, 125, 125, 49, 125, 126, 126, 126, 126, - 126, 126, 127, 127, 127, 127, 127, 47, 45, 42, - 31, 22, 21, 20, 19, 16, 11, 10, 9, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114 - + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 4, 5, 6, 7, + 8, 3, 4, 13, 13, 14, 14, 21, 24, 21, + 24, 25, 26, 27, 28, 24, 29, 30, 31, 32, + 31, 29, 206, 5, 6, 198, 32, 36, 7, 8, + 195, 36, 192, 25, 26, 27, 28, 24, 29, 30, + + 31, 32, 31, 29, 38, 38, 41, 41, 32, 41, + 38, 45, 45, 53, 54, 53, 56, 59, 60, 54, + 53, 56, 57, 61, 57, 62, 58, 58, 63, 57, + 58, 64, 65, 66, 67, 68, 69, 189, 186, 59, + 60, 54, 53, 56, 72, 61, 183, 62, 72, 69, + 63, 57, 180, 64, 65, 66, 67, 68, 69, 75, + 75, 79, 79, 94, 79, 75, 85, 88, 85, 96, + 86, 86, 88, 85, 86, 87, 87, 89, 89, 87, + 90, 89, 90, 100, 101, 94, 102, 90, 103, 104, + 104, 96, 115, 117, 88, 85, 108, 114, 108, 114, + + 118, 119, 104, 108, 114, 100, 101, 120, 102, 90, + 103, 104, 104, 121, 115, 117, 122, 123, 127, 177, + 128, 129, 118, 119, 104, 108, 114, 130, 132, 120, + 125, 133, 125, 134, 126, 121, 126, 125, 122, 123, + 127, 126, 128, 129, 136, 137, 136, 137, 139, 130, + 132, 136, 137, 133, 140, 134, 141, 142, 143, 125, + 144, 148, 146, 126, 146, 147, 150, 147, 153, 146, + 139, 173, 147, 136, 137, 157, 140, 159, 141, 142, + 143, 169, 144, 148, 164, 155, 165, 155, 150, 168, + 153, 146, 155, 156, 147, 156, 161, 157, 161, 159, + + 156, 160, 162, 161, 162, 166, 164, 166, 167, 162, + 167, 168, 166, 172, 155, 167, 170, 171, 170, 171, + 154, 145, 156, 170, 171, 161, 174, 135, 174, 124, + 113, 162, 112, 174, 166, 172, 175, 167, 175, 111, + 178, 110, 178, 175, 109, 170, 171, 178, 107, 179, + 181, 179, 181, 92, 91, 174, 179, 181, 84, 182, + 184, 182, 184, 70, 52, 175, 182, 184, 185, 178, + 185, 51, 49, 47, 187, 185, 187, 44, 179, 181, + 188, 187, 188, 190, 191, 190, 191, 188, 182, 184, + 190, 191, 193, 194, 193, 194, 33, 185, 23, 193, + + 194, 22, 20, 187, 196, 19, 196, 16, 197, 188, + 197, 196, 190, 191, 11, 197, 199, 10, 199, 9, + 0, 193, 194, 199, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 196, 0, 0, 0, 197, 0, 0, + 0, 0, 0, 0, 0, 199, 201, 201, 201, 201, + 201, 201, 202, 202, 202, 202, 202, 202, 203, 203, + 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, + 205, 205, 207, 207, 208, 0, 0, 208, 209, 209, + 209, 0, 0, 209, 210, 210, 210, 210, 210, 210, + 211, 0, 211, 211, 0, 211, 212, 212, 212, 212, + + 212, 212, 213, 213, 213, 213, 213, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200 } ; /* The intent behind this definition is that it'll catch @@ -590,7 +678,8 @@ do {\ -#line 595 "ob_func_expr_parser_lex.c" +/* limit the length of int_num from 1 to 17 in case of int64_t out of bound, 17 -> [ ( length of 2^64 ) - 2 ]*/ +#line 684 "ob_func_expr_parser_lex.c" #define INITIAL 0 #define in_c_comment 1 @@ -838,9 +927,9 @@ YY_DECL register int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; -#line 99 "ob_func_expr_parser.l" +#line 102 "ob_func_expr_parser.l" -#line 846 "ob_func_expr_parser_lex.c" +#line 935 "ob_func_expr_parser_lex.c" yylval = yylval_param; @@ -897,13 +986,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 115 ) + if ( yy_current_state >= 201 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 250 ); + while ( yy_base[yy_current_state] != 508 ); yy_find_action: yy_act = yy_accept[yy_current_state]; @@ -929,126 +1018,156 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 100 "ob_func_expr_parser.l" +#line 103 "ob_func_expr_parser.l" { return FUNC_SUBSTR; } YY_BREAK case 2: YY_RULE_SETUP -#line 101 "ob_func_expr_parser.l" +#line 104 "ob_func_expr_parser.l" { return FUNC_SUBSTR; } YY_BREAK case 3: YY_RULE_SETUP -#line 102 "ob_func_expr_parser.l" +#line 105 "ob_func_expr_parser.l" { return FUNC_CONCAT; } YY_BREAK case 4: YY_RULE_SETUP -#line 103 "ob_func_expr_parser.l" +#line 106 "ob_func_expr_parser.l" { return FUNC_HASH; } YY_BREAK case 5: YY_RULE_SETUP -#line 104 "ob_func_expr_parser.l" +#line 107 "ob_func_expr_parser.l" { return FUNC_TOINT; } YY_BREAK case 6: YY_RULE_SETUP -#line 105 "ob_func_expr_parser.l" +#line 108 "ob_func_expr_parser.l" { return FUNC_DIV; } YY_BREAK case 7: YY_RULE_SETUP -#line 106 "ob_func_expr_parser.l" +#line 109 "ob_func_expr_parser.l" { return FUNC_ADD; } YY_BREAK case 8: YY_RULE_SETUP -#line 107 "ob_func_expr_parser.l" +#line 110 "ob_func_expr_parser.l" { return FUNC_SUB; } YY_BREAK case 9: YY_RULE_SETUP -#line 108 "ob_func_expr_parser.l" +#line 111 "ob_func_expr_parser.l" { return FUNC_MUL; } YY_BREAK case 10: YY_RULE_SETUP -#line 109 "ob_func_expr_parser.l" +#line 112 "ob_func_expr_parser.l" { return FUNC_TESTLOAD; } YY_BREAK case 11: YY_RULE_SETUP -#line 111 "ob_func_expr_parser.l" -{ return TOKEN_SPECIAL; } +#line 113 "ob_func_expr_parser.l" +{ return FUNC_TO_DATE; } YY_BREAK case 12: YY_RULE_SETUP -#line 113 "ob_func_expr_parser.l" -{ RETURN_INT_VAL(); } +#line 114 "ob_func_expr_parser.l" +{ return FUNC_TO_TIMESTAMP; } YY_BREAK case 13: YY_RULE_SETUP -#line 114 "ob_func_expr_parser.l" -{ RETURN_NUMBER_VAL(); } +#line 115 "ob_func_expr_parser.l" +{ return FUNC_NVL; } YY_BREAK case 14: YY_RULE_SETUP -#line 115 "ob_func_expr_parser.l" -{ RETURN_NAME_OB(); } +#line 116 "ob_func_expr_parser.l" +{ return FUNC_TO_CHAR; } YY_BREAK case 15: YY_RULE_SETUP -#line 116 "ob_func_expr_parser.l" -{ RETURN_NAME_OB_WITH_QUOTE(OBPROXY_QUOTE_T_SINGLE); } +#line 117 "ob_func_expr_parser.l" +{ return FUNC_MOD; } YY_BREAK case 16: YY_RULE_SETUP -#line 117 "ob_func_expr_parser.l" -{ RETURN_NAME_OB_WITH_QUOTE(OBPROXY_QUOTE_T_DOUBLE); } +#line 118 "ob_func_expr_parser.l" +{ return FUNC_SYSDATE; } YY_BREAK case 17: YY_RULE_SETUP -#line 118 "ob_func_expr_parser.l" -{ RETURN_NAME_OB_WITH_QUOTE(OBPROXY_QUOTE_T_BACK); } +#line 120 "ob_func_expr_parser.l" +{ return TOKEN_SPECIAL; } YY_BREAK case 18: -/* rule 18 can match eol */ YY_RULE_SETUP -#line 119 "ob_func_expr_parser.l" -{ } +#line 122 "ob_func_expr_parser.l" +{ RETURN_INT_VAL(); } YY_BREAK case 19: YY_RULE_SETUP -#line 120 "ob_func_expr_parser.l" +#line 123 "ob_func_expr_parser.l" +{ RETURN_NUMBER_VAL(); } + YY_BREAK +case 20: +YY_RULE_SETUP +#line 124 "ob_func_expr_parser.l" +{ RETURN_NAME_OB(); } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 125 "ob_func_expr_parser.l" +{ RETURN_NAME_OB_WITH_QUOTE(OBPROXY_QUOTE_T_SINGLE); } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 126 "ob_func_expr_parser.l" +{ RETURN_NAME_OB_WITH_QUOTE(OBPROXY_QUOTE_T_DOUBLE); } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 127 "ob_func_expr_parser.l" +{ RETURN_NAME_OB_WITH_QUOTE(OBPROXY_QUOTE_T_BACK); } + YY_BREAK +case 24: +/* rule 24 can match eol */ +YY_RULE_SETUP +#line 128 "ob_func_expr_parser.l" +{ } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 129 "ob_func_expr_parser.l" { return yytext[0]; } YY_BREAK /* comment */ -case 20: +case 26: YY_RULE_SETUP -#line 123 "ob_func_expr_parser.l" +#line 132 "ob_func_expr_parser.l" { PUSH_STATE(in_c_comment); } YY_BREAK -case 21: +case 27: YY_RULE_SETUP -#line 124 "ob_func_expr_parser.l" +#line 133 "ob_func_expr_parser.l" { POP_STATE(); } YY_BREAK -case 22: -/* rule 22 can match eol */ +case 28: +/* rule 28 can match eol */ YY_RULE_SETUP -#line 125 "ob_func_expr_parser.l" +#line 134 "ob_func_expr_parser.l" {} YY_BREAK -case 23: +case 29: YY_RULE_SETUP -#line 126 "ob_func_expr_parser.l" +#line 135 "ob_func_expr_parser.l" {} YY_BREAK /* quote */ -case 24: +case 30: YY_RULE_SETUP -#line 129 "ob_func_expr_parser.l" +#line 138 "ob_func_expr_parser.l" { PUSH_STATE(sq); ObFuncExprParseResult *p = (ObFuncExprParseResult *)yyextra; @@ -1059,10 +1178,10 @@ YY_RULE_SETUP } } YY_BREAK -case 25: -/* rule 25 can match eol */ +case 31: +/* rule 31 can match eol */ YY_RULE_SETUP -#line 139 "ob_func_expr_parser.l" +#line 148 "ob_func_expr_parser.l" { ObFuncExprParseResult *p = (ObFuncExprParseResult *)yyextra; if (OB_NOTNULL(p)) { @@ -1070,9 +1189,9 @@ YY_RULE_SETUP } } YY_BREAK -case 26: +case 32: YY_RULE_SETUP -#line 146 "ob_func_expr_parser.l" +#line 155 "ob_func_expr_parser.l" { POP_STATE(); ObFuncExprParseResult *p = (ObFuncExprParseResult *)yyextra; @@ -1082,31 +1201,31 @@ YY_RULE_SETUP return STR_VAL; } YY_BREAK -case 27: +case 33: YY_RULE_SETUP -#line 155 "ob_func_expr_parser.l" +#line 164 "ob_func_expr_parser.l" {} YY_BREAK -case 28: -/* rule 28 can match eol */ +case 34: +/* rule 34 can match eol */ YY_RULE_SETUP -#line 156 "ob_func_expr_parser.l" +#line 165 "ob_func_expr_parser.l" {} YY_BREAK -case 29: -/* rule 29 can match eol */ +case 35: +/* rule 35 can match eol */ YY_RULE_SETUP -#line 157 "ob_func_expr_parser.l" +#line 166 "ob_func_expr_parser.l" {} YY_BREAK case YY_STATE_EOF(sq): -#line 158 "ob_func_expr_parser.l" +#line 167 "ob_func_expr_parser.l" { return ERROR; } YY_BREAK /* dquote */ -case 30: +case 36: YY_RULE_SETUP -#line 162 "ob_func_expr_parser.l" +#line 171 "ob_func_expr_parser.l" { PUSH_STATE(dq); ObFuncExprParseResult *p = (ObFuncExprParseResult *)yyextra; @@ -1117,10 +1236,10 @@ YY_RULE_SETUP } } YY_BREAK -case 31: -/* rule 31 can match eol */ +case 37: +/* rule 37 can match eol */ YY_RULE_SETUP -#line 172 "ob_func_expr_parser.l" +#line 181 "ob_func_expr_parser.l" { ObFuncExprParseResult *p = (ObFuncExprParseResult *)yyextra; if (OB_NOTNULL(p)) { @@ -1128,9 +1247,9 @@ YY_RULE_SETUP } } YY_BREAK -case 32: +case 38: YY_RULE_SETUP -#line 179 "ob_func_expr_parser.l" +#line 188 "ob_func_expr_parser.l" { POP_STATE(); ObFuncExprParseResult *p = (ObFuncExprParseResult *)yyextra; @@ -1140,31 +1259,31 @@ YY_RULE_SETUP return STR_VAL; } YY_BREAK -case 33: +case 39: YY_RULE_SETUP -#line 188 "ob_func_expr_parser.l" +#line 197 "ob_func_expr_parser.l" {} YY_BREAK -case 34: -/* rule 34 can match eol */ +case 40: +/* rule 40 can match eol */ YY_RULE_SETUP -#line 189 "ob_func_expr_parser.l" +#line 198 "ob_func_expr_parser.l" {} YY_BREAK -case 35: -/* rule 35 can match eol */ +case 41: +/* rule 41 can match eol */ YY_RULE_SETUP -#line 190 "ob_func_expr_parser.l" +#line 199 "ob_func_expr_parser.l" {} YY_BREAK case YY_STATE_EOF(dq): -#line 191 "ob_func_expr_parser.l" +#line 200 "ob_func_expr_parser.l" { return ERROR; } YY_BREAK /* backtick */ -case 36: +case 42: YY_RULE_SETUP -#line 195 "ob_func_expr_parser.l" +#line 204 "ob_func_expr_parser.l" { PUSH_STATE(bt); ObFuncExprParseResult *p = (ObFuncExprParseResult *)yyextra; @@ -1175,9 +1294,9 @@ YY_RULE_SETUP } } YY_BREAK -case 37: +case 43: YY_RULE_SETUP -#line 205 "ob_func_expr_parser.l" +#line 214 "ob_func_expr_parser.l" { ObFuncExprParseResult *p = (ObFuncExprParseResult *)yyextra; if (NULL != p && NULL != p->tmp_buf_ && p->tmp_len_ + 1 < OBPROXY_MAX_NAME_LENGTH) { @@ -1185,10 +1304,10 @@ YY_RULE_SETUP } } YY_BREAK -case 38: -/* rule 38 can match eol */ +case 44: +/* rule 44 can match eol */ YY_RULE_SETUP -#line 212 "ob_func_expr_parser.l" +#line 221 "ob_func_expr_parser.l" { ObFuncExprParseResult *p = (ObFuncExprParseResult *)yyextra; if (NULL != p && NULL != p->tmp_buf_ && p->tmp_len_ + yyleng < OBPROXY_MAX_NAME_LENGTH) { @@ -1197,9 +1316,9 @@ YY_RULE_SETUP } } YY_BREAK -case 39: +case 45: YY_RULE_SETUP -#line 220 "ob_func_expr_parser.l" +#line 229 "ob_func_expr_parser.l" { POP_STATE(); ObFuncExprParseResult *p = (ObFuncExprParseResult *)yyextra; @@ -1212,27 +1331,27 @@ YY_RULE_SETUP } YY_BREAK case YY_STATE_EOF(bt): -#line 231 "ob_func_expr_parser.l" +#line 240 "ob_func_expr_parser.l" { return ERROR; } YY_BREAK case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(in_c_comment): -#line 235 "ob_func_expr_parser.l" +#line 244 "ob_func_expr_parser.l" { return END_P; } YY_BREAK -case 40: +case 46: YY_RULE_SETUP -#line 236 "ob_func_expr_parser.l" +#line 245 "ob_func_expr_parser.l" { return IGNORED_WORD; } YY_BREAK -case 41: +case 47: YY_RULE_SETUP -#line 237 "ob_func_expr_parser.l" +#line 246 "ob_func_expr_parser.l" ECHO; YY_BREAK -#line 1238 "ob_func_expr_parser_lex.c" +#line 1357 "ob_func_expr_parser_lex.c" case YY_END_OF_BUFFER: { @@ -1524,7 +1643,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 115 ) + if ( yy_current_state >= 201 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1553,11 +1672,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 115 ) + if ( yy_current_state >= 201 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 114); + yy_is_jam = (yy_current_state == 200); return yy_is_jam ? 0 : yy_current_state; } @@ -2382,7 +2501,7 @@ static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) #define YYTABLES_NAME "yytables" -#line 237 "ob_func_expr_parser.l" +#line 246 "ob_func_expr_parser.l" @@ -2511,13 +2630,19 @@ extern int obfuncexprdebug; FUNC_SUB = 266, FUNC_MUL = 267, FUNC_TESTLOAD = 268, - END_P = 269, - ERROR = 270, - IGNORED_WORD = 271, - NAME_OB = 272, - STR_VAL = 273, - NUMBER_VAL = 274, - INT_VAL = 275 + FUNC_TO_DATE = 269, + FUNC_TO_TIMESTAMP = 270, + FUNC_NVL = 271, + FUNC_TO_CHAR = 272, + FUNC_MOD = 273, + FUNC_SYSDATE = 274, + END_P = 275, + ERROR = 276, + IGNORED_WORD = 277, + NAME_OB = 278, + STR_VAL = 279, + NUMBER_VAL = 280, + INT_VAL = 281 }; #endif diff --git a/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser_lex.h b/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser_lex.h index 14f5fb507edd16ea60793c413c65f7efae1b2f82..3d8a11e8578b51110a808e9a47fca3ce9e758c83 100644 --- a/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser_lex.h +++ b/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser_lex.h @@ -341,7 +341,7 @@ extern int obfuncexprlex \ #undef YY_DECL #endif -#line 237 "ob_func_expr_parser.l" +#line 246 "ob_func_expr_parser.l" #line 348 "ob_func_expr_parser_lex.h" diff --git a/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser_tab.c b/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser_tab.c index 49ab7202071018dc7bbe2ecae7bea763ca2962ae..abb236463f508ab28c2777f27dfd9b9e348d1c0a 100644 --- a/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser_tab.c +++ b/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser_tab.c @@ -138,13 +138,19 @@ extern int obfuncexprdebug; FUNC_SUB = 266, FUNC_MUL = 267, FUNC_TESTLOAD = 268, - END_P = 269, - ERROR = 270, - IGNORED_WORD = 271, - NAME_OB = 272, - STR_VAL = 273, - NUMBER_VAL = 274, - INT_VAL = 275 + FUNC_TO_DATE = 269, + FUNC_TO_TIMESTAMP = 270, + FUNC_NVL = 271, + FUNC_TO_CHAR = 272, + FUNC_MOD = 273, + FUNC_SYSDATE = 274, + END_P = 275, + ERROR = 276, + IGNORED_WORD = 277, + NAME_OB = 278, + STR_VAL = 279, + NUMBER_VAL = 280, + INT_VAL = 281 }; #endif @@ -460,22 +466,22 @@ union yyalloc #endif /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 15 +#define YYFINAL 22 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 46 +#define YYLAST 64 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 24 +#define YYNTOKENS 30 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 7 +#define YYNNTS 8 /* YYNRULES -- Number of rules. */ -#define YYNRULES 22 +#define YYNRULES 29 /* YYNRULES -- Number of states. */ -#define YYNSTATES 30 +#define YYNSTATES 37 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 275 +#define YYMAXUTOK 281 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -487,7 +493,7 @@ static const yytype_uint8 yytranslate[] = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 21, 22, 2, 2, 23, 2, 2, 2, 2, 2, + 27, 28, 2, 2, 29, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -510,7 +516,8 @@ static const yytype_uint8 yytranslate[] = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20 + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26 }; #if YYDEBUG @@ -519,27 +526,28 @@ static const yytype_uint8 yytranslate[] = static const yytype_uint8 yyprhs[] = { 0, 0, 3, 5, 7, 9, 14, 18, 20, 22, - 24, 26, 28, 30, 32, 34, 36, 38, 42, 46, - 48, 50, 52 + 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, + 44, 46, 48, 50, 52, 56, 60, 62, 64, 66 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { - 25, 0, -1, 26, -1, 27, -1, 1, -1, 28, - 21, 29, 22, -1, 28, 21, 22, -1, 5, -1, - 6, -1, 7, -1, 8, -1, 9, -1, 10, -1, - 11, -1, 12, -1, 13, -1, 30, -1, 29, 23, - 30, -1, 4, 17, 4, -1, 17, -1, 20, -1, - 18, -1, 27, -1 + 31, 0, -1, 32, -1, 33, -1, 1, -1, 34, + 27, 36, 28, -1, 34, 27, 28, -1, 35, -1, + 5, -1, 6, -1, 7, -1, 8, -1, 9, -1, + 10, -1, 11, -1, 12, -1, 13, -1, 14, -1, + 15, -1, 16, -1, 17, -1, 18, -1, 19, -1, + 37, -1, 36, 29, 37, -1, 4, 23, 4, -1, + 23, -1, 26, -1, 24, -1, 33, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 96, 96, 98, 104, 106, 111, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 127, 131, 137, 138, - 139, 140, 141 + 0, 97, 97, 99, 105, 107, 112, 117, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 138, 140, 144, 150, 151, 152, 153, 154 }; #endif @@ -550,10 +558,12 @@ static const char *const yytname[] = { "$end", "error", "$undefined", "DUMMY_FUNCTION_CLAUSE", "TOKEN_SPECIAL", "FUNC_SUBSTR", "FUNC_CONCAT", "FUNC_HASH", "FUNC_TOINT", "FUNC_DIV", - "FUNC_ADD", "FUNC_SUB", "FUNC_MUL", "FUNC_TESTLOAD", "END_P", "ERROR", - "IGNORED_WORD", "NAME_OB", "STR_VAL", "NUMBER_VAL", "INT_VAL", "'('", - "')'", "','", "$accept", "start", "func_root", "func_expr", "func_name", - "param_list", "param", 0 + "FUNC_ADD", "FUNC_SUB", "FUNC_MUL", "FUNC_TESTLOAD", "FUNC_TO_DATE", + "FUNC_TO_TIMESTAMP", "FUNC_NVL", "FUNC_TO_CHAR", "FUNC_MOD", + "FUNC_SYSDATE", "END_P", "ERROR", "IGNORED_WORD", "NAME_OB", "STR_VAL", + "NUMBER_VAL", "INT_VAL", "'('", "')'", "','", "$accept", "start", + "func_root", "func_expr", "func_name", "reserved_func", "param_list", + "param", 0 }; #endif @@ -564,24 +574,24 @@ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 40, 41, 44 + 275, 276, 277, 278, 279, 280, 281, 40, 41, 44 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 24, 25, 26, 26, 27, 27, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 29, 29, 30, 30, - 30, 30, 30 + 0, 30, 31, 32, 32, 33, 33, 33, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 35, 36, 36, 37, 37, 37, 37, 37 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 1, 1, 1, 4, 3, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, - 1, 1, 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 3, 1, 1, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -589,15 +599,16 @@ static const yytype_uint8 yyr2[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 0, 4, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 0, 2, 3, 0, 1, 0, 0, 19, 21, - 20, 6, 22, 0, 16, 0, 5, 0, 18, 17 + 0, 4, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 0, 2, 3, + 0, 7, 1, 0, 0, 26, 28, 27, 6, 29, + 0, 23, 0, 5, 0, 25, 24 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - -1, 11, 12, 22, 14, 23, 24 + -1, 17, 18, 29, 20, 21, 30, 31 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing @@ -605,15 +616,16 @@ static const yytype_int8 yydefgoto[] = #define YYPACT_NINF -13 static const yytype_int8 yypact[] = { - 33, -13, -13, -13, -13, -13, -13, -13, -13, -13, - -13, 12, -13, -13, -6, -13, -4, 0, -13, -13, - -13, -13, -13, -12, -13, 25, -13, 15, -13, -13 + 45, -13, -13, -13, -13, -13, -13, -13, -13, -13, + -13, -13, -13, -13, -13, -13, -13, 18, -13, -13, + -6, -13, -13, -4, 0, -13, -13, -13, -13, -13, + -12, -13, 37, -13, 21, -13, -13 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { - -13, -13, -13, 30, -13, -13, 4 + -13, -13, -13, 42, -13, -13, -13, 9 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If @@ -623,20 +635,24 @@ static const yytype_int8 yypgoto[] = #define YYTABLE_NINF -1 static const yytype_uint8 yytable[] = { - 17, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 26, 27, 15, 18, 19, 16, 20, 25, 21, 17, - 2, 3, 4, 5, 6, 7, 8, 9, 10, 28, - 13, 29, 18, 19, 1, 20, 0, 0, 2, 3, - 4, 5, 6, 7, 8, 9, 10 + 24, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 33, 34, 22, 25, + 26, 23, 27, 32, 28, 24, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 35, 19, 36, 25, 26, 1, 27, 0, 0, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16 }; static const yytype_int8 yycheck[] = { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 22, 23, 0, 17, 18, 21, 20, 17, 22, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 4, - 0, 27, 17, 18, 1, 20, -1, -1, 5, 6, - 7, 8, 9, 10, 11, 12, 13 + 14, 15, 16, 17, 18, 19, 28, 29, 0, 23, + 24, 27, 26, 23, 28, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 4, 0, 34, 23, 24, 1, 26, -1, -1, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -644,8 +660,9 @@ static const yytype_int8 yycheck[] = static const yytype_uint8 yystos[] = { 0, 1, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 25, 26, 27, 28, 0, 21, 4, 17, 18, - 20, 22, 27, 29, 30, 17, 22, 23, 4, 30 + 13, 14, 15, 16, 17, 18, 19, 31, 32, 33, + 34, 35, 0, 27, 4, 23, 24, 26, 28, 33, + 36, 37, 23, 28, 29, 4, 37 }; #define yyerrok (yyerrstatus = 0) @@ -1528,57 +1545,95 @@ yyreduce: case 7: - { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_SUBSTR; ;} + { + malloc_func_expr_node((yyval.func_node), result, (yyvsp[(1) - (1)].function_type)); + (yyval.func_node)->child_ = NULL; + ;} break; case 8: - { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_CONCAT; ;} + { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_SUBSTR; ;} break; case 9: - { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_HASH; ;} + { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_CONCAT; ;} break; case 10: - { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_TOINT; ;} + { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_HASH; ;} break; case 11: - { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_DIV; ;} + { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_TOINT; ;} break; case 12: - { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_ADD; ;} + { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_DIV; ;} break; case 13: - { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_SUB; ;} + { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_ADD; ;} break; case 14: - { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_MUL; ;} + { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_SUB; ;} break; case 15: - { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_TESTLOAD; ;} + { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_MUL; ;} break; case 16: + { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_TESTLOAD; ;} + break; + + case 17: + + { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_TO_DATE; ;} + break; + + case 18: + + { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_TO_TIMESTAMP; ;} + break; + + case 19: + + { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_NVL; ;} + break; + + case 20: + + { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_TO_CHAR; ;} + break; + + case 21: + + { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_MOD; ;} + break; + + case 22: + + { (yyval.function_type) = OB_PROXY_EXPR_TYPE_FUNC_SYSDATE; ;} + break; + + case 23: + { malloc_list((yyval.list), result, (yyvsp[(1) - (1)].param_node)); ;} break; - case 17: + case 24: { add_param_node((yyvsp[(1) - (3)].list), result, (yyvsp[(3) - (3)].param_node)); @@ -1586,27 +1641,27 @@ yyreduce: ;} break; - case 18: + case 25: { malloc_param_node((yyval.param_node), result, PARAM_COLUMN); (yyval.param_node)->col_name_ = (yyvsp[(2) - (3)].str); ;} break; - case 19: + case 26: { malloc_param_node((yyval.param_node), result, PARAM_COLUMN); (yyval.param_node)->col_name_ = (yyvsp[(1) - (1)].str); ;} break; - case 20: + case 27: { malloc_param_node((yyval.param_node), result, PARAM_INT_VAL); (yyval.param_node)->int_value_ = (yyvsp[(1) - (1)].num); ;} break; - case 21: + case 28: { malloc_param_node((yyval.param_node), result, PARAM_STR_VAL); (yyval.param_node)->str_value_ = (yyvsp[(1) - (1)].str); ;} break; - case 22: + case 29: { malloc_param_node((yyval.param_node), result, PARAM_FUNC); (yyval.param_node)->func_expr_node_ = (yyvsp[(1) - (1)].func_node); ;} break; diff --git a/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser_tab.h b/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser_tab.h index 1eb7984eece858119b09751b39682ffe9bdb1873..4f199b4b4a34e847a041077b18dc727803e6d001 100644 --- a/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser_tab.h +++ b/src/obproxy/opsql/func_expr_parser/ob_func_expr_parser_tab.h @@ -67,13 +67,19 @@ extern int obfuncexprdebug; FUNC_SUB = 266, FUNC_MUL = 267, FUNC_TESTLOAD = 268, - END_P = 269, - ERROR = 270, - IGNORED_WORD = 271, - NAME_OB = 272, - STR_VAL = 273, - NUMBER_VAL = 274, - INT_VAL = 275 + FUNC_TO_DATE = 269, + FUNC_TO_TIMESTAMP = 270, + FUNC_NVL = 271, + FUNC_TO_CHAR = 272, + FUNC_MOD = 273, + FUNC_SYSDATE = 274, + END_P = 275, + ERROR = 276, + IGNORED_WORD = 277, + NAME_OB = 278, + STR_VAL = 279, + NUMBER_VAL = 280, + INT_VAL = 281 }; #endif diff --git a/src/obproxy/opsql/func_expr_resolver/ob_func_expr_resolver.cpp b/src/obproxy/opsql/func_expr_resolver/ob_func_expr_resolver.cpp index f586ef93f7f7065c7b8d5c44d62f4209e876eb4c..c8b4dffb44f83e78e9a6e93dbc3af5fa3bba607c 100644 --- a/src/obproxy/opsql/func_expr_resolver/ob_func_expr_resolver.cpp +++ b/src/obproxy/opsql/func_expr_resolver/ob_func_expr_resolver.cpp @@ -50,6 +50,11 @@ int ObFuncExprResolver::recursive_resolve_proxy_expr(const ObProxyParamNode *nod ObProxyExprConst *str_expr = NULL; if(OB_FAIL(ctx_.expr_factory_->create_proxy_expr(OB_PROXY_EXPR_TYPE_CONST, str_expr))) { LOG_WARN("create proxy expr failed", K(ret)); + } else if (0 == node->str_value_.str_len_) { + ObObj &obj = str_expr->get_object(); + obj.set_varchar(NULL, 0); + obj.set_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI); + expr = str_expr; } else { ObIAllocator &allocator = *ctx_.allocator_; char *buf = NULL; @@ -103,6 +108,8 @@ int ObFuncExprResolver::recursive_resolve_proxy_expr(const ObProxyParamNode *nod ObProxyFuncExpr *func_expr = NULL; if (OB_FAIL(create_func_expr_by_type(func_expr_node, func_expr))) { LOG_WARN("create func expr by type failed", K(ret)); + } else if (OB_ISNULL(func_expr_node->child_)) { + // do nothing } else { ObProxyParamNodeList *child = func_expr_node->child_; ObProxyParamNode* tmp_param_node = child->head_; @@ -242,6 +249,68 @@ int ObFuncExprResolver::create_func_expr_by_type(const ObFuncExprNode *func_expr } } break; + case OB_PROXY_EXPR_TYPE_FUNC_TO_DATE: + { + ObProxyExprToTimeHandler *todate_expr = NULL; + if (OB_FAIL(ctx_.expr_factory_->create_proxy_expr(OB_PROXY_EXPR_TYPE_FUNC_TO_DATE, todate_expr))) { + LOG_WARN("create proxy to_date failed", K(ret)); + } else { + todate_expr->set_target_type(ObDateTimeType); + func_expr = todate_expr; + } + } + break; + case OB_PROXY_EXPR_TYPE_FUNC_TO_TIMESTAMP: + { + ObProxyExprToTimeHandler *totimestamp_expr = NULL; + if (OB_FAIL(ctx_.expr_factory_->create_proxy_expr(OB_PROXY_EXPR_TYPE_FUNC_TO_TIMESTAMP, totimestamp_expr))) { + LOG_WARN("create proxy to_timestamp failed", K(ret)); + } else { + totimestamp_expr->set_target_type(ObTimestampNanoType); + func_expr = totimestamp_expr; + } + } + break; + case OB_PROXY_EXPR_TYPE_FUNC_NVL: + { + ObProxyExprNvl *nvl_expr = NULL; + if (OB_FAIL(ctx_.expr_factory_->create_proxy_expr(OB_PROXY_EXPR_TYPE_FUNC_NVL, nvl_expr))) { + LOG_WARN("create proxy nvl failed", K(ret)); + } else { + func_expr = nvl_expr; + } + } + break; + case OB_PROXY_EXPR_TYPE_FUNC_TO_CHAR: + { + ObProxyExprToChar *tochar_expr = NULL; + if (OB_FAIL(ctx_.expr_factory_->create_proxy_expr(OB_PROXY_EXPR_TYPE_FUNC_TO_CHAR, tochar_expr))) { + LOG_WARN("create proxy to_char failed", K(ret)); + } else { + func_expr = tochar_expr; + } + } + break; + case OB_PROXY_EXPR_TYPE_FUNC_SYSDATE: + { + ObProxyExprSysdate *sysdate_expr = NULL; + if (OB_FAIL(ctx_.expr_factory_->create_proxy_expr(OB_PROXY_EXPR_TYPE_FUNC_SYSDATE, sysdate_expr))) { + LOG_WARN("create proxy sysdate failed", K(ret)); + } else { + func_expr = sysdate_expr; + } + } + break; + case OB_PROXY_EXPR_TYPE_FUNC_MOD: + { + ObProxyExprMod *mod_expr = NULL; + if (OB_FAIL(ctx_.expr_factory_->create_proxy_expr(OB_PROXY_EXPR_TYPE_FUNC_MOD, mod_expr))) { + LOG_WARN("create proxy mod failed", K(ret)); + } else { + func_expr = mod_expr; + } + } + break; default: ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected type", K(func_expr_node->func_type_), K(ret)); diff --git a/src/obproxy/opsql/func_expr_resolver/proxy_expr/ob_proxy_expr.cpp b/src/obproxy/opsql/func_expr_resolver/proxy_expr/ob_proxy_expr.cpp index 9c3bb18f048eae98afc23debe3bd842d095d928c..323a9a142bf83f06e13d10c2a0c28bde23ce7a3a 100644 --- a/src/obproxy/opsql/func_expr_resolver/proxy_expr/ob_proxy_expr.cpp +++ b/src/obproxy/opsql/func_expr_resolver/proxy_expr/ob_proxy_expr.cpp @@ -12,10 +12,16 @@ #define USING_LOG_PREFIX PROXY -#include "common/ob_obj_cast.h" #include "opsql/func_expr_resolver/proxy_expr/ob_proxy_expr.h" -#include "utils/ob_proxy_utils.h" +#include "common/ob_obj_cast.h" +#include "common/ob_obj_type.h" #include "dbconfig/ob_proxy_db_config_info.h" +#include "lib/time/ob_time_utility.h" +#include "proxy/route/obproxy_expr_calculator.h" +#include "utils/ob_proxy_utils.h" +#include "common/expression/ob_expr_regexp_context.h" +#include "lib/utility/utility.h" +#include namespace oceanbase { @@ -226,10 +232,10 @@ int ObProxyExprColumn::calc(const ObProxyExprCtx &ctx, const ObProxyExprCalcItem } else if (result_obj_array.count() == len && ObProxyExprCalcItem::FROM_SQL_FIELD == calc_item.source_) { bool found = false; for (int64_t i = 0; OB_SUCC(ret) && i < calc_item.sql_result_->field_num_; i++) { - SqlField &field = calc_item.sql_result_->fields_.at(i); - if (0 == field.column_name_.string_.case_compare(column_name_)) { + SqlField* field = calc_item.sql_result_->fields_.at(i); + if (0 == field->column_name_.config_string_.case_compare(column_name_)) { found = true; - common::ObSEArray &column_values = field.column_values_; + common::ObSEArray &column_values = field->column_values_; for (int64_t j = 0; OB_SUCC(ret) && j < column_values.count(); j++) { ObObj result_obj; SqlColumnValue &sql_column_value = column_values.at(j); @@ -240,7 +246,7 @@ int ObProxyExprColumn::calc(const ObProxyExprCtx &ctx, const ObProxyExprCalcItem LOG_WARN("push back obj failed", K(ret), K(result_obj)); } } else if (TOKEN_STR_VAL == sql_column_value.value_type_) { - ObString value = sql_column_value.column_value_.string_; + ObString value = sql_column_value.column_value_.config_string_; result_obj.set_varchar(value); result_obj.set_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI); if (OB_FAIL(result_obj_array.push_back(result_obj))) { @@ -362,26 +368,19 @@ int ObProxyFuncExpr::calc_param_expr(const ObProxyExprCtx &ctx, return ret; } -int ObProxyFuncExpr::get_int_obj(const ObObj &src, ObObj &dst) +int ObProxyFuncExpr::get_int_obj(const ObObj &src, ObObj &dst, common::ObIAllocator &allocator) { int ret = OB_SUCCESS; - if (src.is_varchar()) { - ObString str; - int64_t val; - if (OB_FAIL(src.get_varchar(str))) { - LOG_WARN("get varchar failed", K(ret)); - } else if (OB_FAIL(get_int_value(str, val))) { - LOG_WARN("get int value failed", K(ret), K(src)); - } else { - dst.set_int(val); + if (!src.is_int()) { + ObCollationType collation = ObCharset::get_default_collation(ObCharset::get_default_charset()); + ObCastCtx cast_ctx(&allocator, NULL, CM_NULL_ON_WARN, collation); + if (OB_FAIL(ObObjCasterV2::to_type(ObIntType, collation, cast_ctx, src, dst))) { + LOG_WARN("cast obj to varchar obj fail", K(ret)); } - } else if (src.is_int()) { - dst = src; } else { - ret = OB_EXPR_CALC_ERROR; - LOG_WARN("invalid type to int", K(ret)); - } + dst = src; + } return ret; } @@ -389,22 +388,14 @@ int ObProxyFuncExpr::get_int_obj(const ObObj &src, ObObj &dst) int ObProxyFuncExpr::get_varchar_obj(const common::ObObj &src, common::ObObj &dst, common::ObIAllocator &allocator) { int ret = OB_SUCCESS; - if (src.is_int()) { - char *buf = NULL; - const int64_t buf_len = 256; - if (OB_ISNULL(buf = static_cast(allocator.alloc(buf_len)))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("alloc buf failed", K(ret), K(buf_len)); - } else { - snprintf(buf, buf_len, "%ld", src.get_int()); - dst.set_varchar(buf, static_cast(strlen(buf))); - dst.set_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI); + if (!src.is_varchar()) { + ObCollationType collation = ObCharset::get_default_collation(ObCharset::get_default_charset()); + ObCastCtx cast_ctx(&allocator, NULL, CM_NULL_ON_WARN, collation); + if (OB_FAIL(ObObjCasterV2::to_type(ObVarcharType, collation, cast_ctx, src, dst))) { + LOG_WARN("cast obj to varchar obj fail", K(ret)); } } else if (src.is_varchar()) { dst = src; - } else { - ret = OB_EXPR_CALC_ERROR; - LOG_INFO("get varchar obj failed", K(src), K(ret)); } return ret; @@ -456,7 +447,7 @@ int ObProxyExprHash::calc(const ObProxyExprCtx &ctx, tmp_obj = param_result_array.at(j).at(i); } if (OB_FAIL(param_result.push_back(tmp_obj))) { - LOG_WARN("push back obj faile", K(ret), K(i), K(j)); + LOG_WARN("push back obj failed", K(ret), K(i), K(j)); } } @@ -475,7 +466,7 @@ int ObProxyExprHash::calc(const ObProxyExprCtx &ctx, LOG_DEBUG("test load type", K(test_load_obj)); } - if (OB_FAIL(get_int_obj(test_load_obj, obj1))) { + if (OB_FAIL(get_int_obj(test_load_obj, obj1, *ctx.allocator_))) { LOG_WARN("get int obj failed", K(ret), K(test_load_obj)); } else if (OB_FAIL(obj1.get_int(index))) { LOG_WARN("get int failed", K(ret), K(obj1)); @@ -483,7 +474,7 @@ int ObProxyExprHash::calc(const ObProxyExprCtx &ctx, if (OB_SUCC(ret) && param_array_.count() == 2) { ObObj obj2; - if (OB_FAIL(get_int_obj(param_result.at(1), obj2))) { + if (OB_FAIL(get_int_obj(param_result.at(1), obj2, *ctx.allocator_))) { LOG_WARN("get int obj failed", K(ret)); } else if (OB_FAIL(obj2.get_int(num))) { LOG_WARN("get int failed", K(ret)); @@ -507,7 +498,7 @@ int ObProxyExprHash::calc(const ObProxyExprCtx &ctx, } } } - } while (++i < cnt); + } while (OB_SUCC(ret) && ++i < cnt); } } ObProxyExpr::print_proxy_expr(this); @@ -544,7 +535,7 @@ int ObProxyExprSubStr::calc(const ObProxyExprCtx &ctx, tmp_obj = param_result_array.at(j).at(i); } if (OB_FAIL(param_result.push_back(tmp_obj))) { - LOG_WARN("push back obj faile", K(ret), K(i), K(j)); + LOG_WARN("push back obj failed", K(ret), K(i), K(j)); } } @@ -556,6 +547,9 @@ int ObProxyExprSubStr::calc(const ObProxyExprCtx &ctx, int64_t substr_len = -1; ObObj first_obj; + // substr retrun NULL on out of bounds params + bool is_invalid_params = false; + if (OB_FAIL(get_varchar_obj(param_result.at(0), first_obj, *ctx.allocator_))) { LOG_WARN("get varchar obj failed", K(ret)); } else if (OB_FAIL(first_obj.get_varchar(value))) { @@ -567,26 +561,33 @@ int ObProxyExprSubStr::calc(const ObProxyExprCtx &ctx, if (OB_SUCC(ret)) { ObObj obj; - if (OB_FAIL(get_int_obj(param_result.at(1), obj))) { + if (OB_FAIL(get_int_obj(param_result.at(1), obj, *ctx.allocator_))) { LOG_WARN("get int obj failed", K(ret)); } else if (OB_FAIL(obj.get_int(start_pos))) { LOG_WARN("get int failed", K(ret)); } } - + if (start_pos == 0) { + if (ctx.is_oracle_mode) { + // 1 and 0 treated as thr first character in oracle + start_pos = 1; + } else { + is_invalid_params = true; + } + } if (OB_SUCC(ret) && 3 == param_result.count()) { ObObj obj; - if (OB_FAIL(get_int_obj(param_result.at(2), obj))) { + if (OB_FAIL(get_int_obj(param_result.at(2), obj, *ctx.allocator_))) { LOG_WARN("get int obj failed", K(ret)); } else if (OB_FAIL(obj.get_int(substr_len))) { LOG_WARN("get int failed", K(ret)); } else if (substr_len <= 0) { - ret = OB_INVALID_ARGUMENT_FOR_SUBSTR; - LOG_WARN("substr function param 3 is less than 1", K(ret)); + is_invalid_params = true; + LOG_DEBUG("substr function param 3 is less than 1", K(ret)); } } - if (OB_SUCC(ret)) { + if (OB_SUCC(ret) && !is_invalid_params) { value_length = value.length(); if (start_pos < 0) { start_pos = value_length + start_pos + 1; @@ -597,26 +598,37 @@ int ObProxyExprSubStr::calc(const ObProxyExprCtx &ctx, } if (start_pos <= 0 || start_pos > value_length || substr_len <= 0 || substr_len > value_length || start_pos + substr_len - 1 > value_length) { - ret = OB_INVALID_ARGUMENT_FOR_SUBSTR; - LOG_WARN("column value length does not match", K(start_pos), - K(substr_len), K(value_length), K(value), K(ret)); + is_invalid_params = true; + LOG_DEBUG("invalid substr params", K(start_pos), K(substr_len), K(value_length), K(value), K(ret)); } + } - if (OB_SUCC(ret)) { + if (OB_SUCC(ret)) { + if(is_invalid_params) { + if (ctx.is_oracle_mode) { + result_obj.set_null(); + } else { + result_obj.set_varchar(ObString()); + } + } else { ObString result_str; result_str.assign_ptr(value.ptr() + start_pos - 1, static_cast(substr_len)); result_obj.set_varchar(result_str); result_obj.set_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI); - if (OB_FAIL(check_varchar_empty(result_obj))) { LOG_WARN("check varchar emtpy failed", K(ret)); - } else if (OB_FAIL(result_obj_array.push_back(result_obj))) { - LOG_WARN("result obj array push back failed", K(ret)); - } + } } } + + if (OB_SUCC(ret)) { + if (OB_FAIL(result_obj_array.push_back(result_obj))) { + LOG_WARN("result obj array push back failed", K(ret)); + } + } + } - } while (++i < cnt); + } while (OB_SUCC(ret) && ++i < cnt); } } ObProxyExpr::print_proxy_expr(this); @@ -653,7 +665,7 @@ int ObProxyExprConcat::calc(const ObProxyExprCtx &ctx, tmp_obj = param_result_array.at(j).at(i); } if (OB_FAIL(param_result.push_back(tmp_obj))) { - LOG_WARN("push back obj faile", K(ret), K(i), K(j)); + LOG_WARN("push back obj failed", K(ret), K(i), K(j)); } } @@ -709,7 +721,7 @@ int ObProxyExprConcat::calc(const ObProxyExprCtx &ctx, } } } - } while (++i < cnt); + } while (OB_SUCC(ret) && ++i < cnt); } } ObProxyExpr::print_proxy_expr(this); @@ -746,19 +758,19 @@ int ObProxyExprToInt::calc(const ObProxyExprCtx &ctx, tmp_obj = param_result_array.at(j).at(i); } if (OB_FAIL(param_result.push_back(tmp_obj))) { - LOG_WARN("push back obj faile", K(ret), K(i), K(j)); + LOG_WARN("push back obj failed", K(ret), K(i), K(j)); } } if (OB_SUCC(ret)) { ObObj result_obj; ObObj &obj = param_result.at(0); - if (OB_FAIL(get_int_obj(obj, result_obj))) { + if (OB_FAIL(get_int_obj(obj, result_obj, *ctx.allocator_))) { LOG_WARN("get int obj failed", K(ret)); } else if (OB_FAIL(result_obj_array.push_back(result_obj))) { LOG_WARN("result obj array push back failed", K(ret)); } } - } while (++i < cnt); + } while (OB_SUCC(ret) && ++i < cnt); } } ObProxyExpr::print_proxy_expr(this); @@ -774,7 +786,7 @@ int ObProxyExprDiv::calc(const ObProxyExprCtx &ctx, common::ObSEArray, 4> param_result_array; int cnt = 0; int64_t len = result_obj_array.count(); - + if (-1 != index_ && ObProxyExprCalcItem::FROM_OBJ_ARRAY == calc_item.source_ && !has_agg_) { if (OB_FAIL(ObProxyExpr::calc(ctx, calc_item, result_obj_array))) { LOG_WARN("calc expr failed", K(ret)); @@ -799,7 +811,7 @@ int ObProxyExprDiv::calc(const ObProxyExprCtx &ctx, tmp_obj = param_result_array.at(j).at(i); } if (OB_FAIL(param_result.push_back(tmp_obj))) { - LOG_WARN("push back obj faile", K(ret), K(i), K(j)); + LOG_WARN("push back obj failed", K(ret), K(i), K(j)); } } @@ -810,7 +822,7 @@ int ObProxyExprDiv::calc(const ObProxyExprCtx &ctx, if (ObDoubleTC == obj1.get_type_class() || ObDoubleTC == obj2.get_type_class()) { if (OB_FAIL((get_obj_for_calc(ctx.allocator_, obj1, obj2)))) { LOG_WARN("get double obj failed", K(obj1), K(obj2), K(ret)); - } else if (fabs(obj2.get_double()) == 0.0) { + } else if (fabs(obj2.get_double()) < DBL_EPSILON) { result_obj.set_null(); } else { double obj1_d = obj1.get_double(); @@ -820,6 +832,8 @@ int ObProxyExprDiv::calc(const ObProxyExprCtx &ctx, } else if (ObFloatTC == obj1.get_type_class() || ObFloatTC == obj2.get_type_class()) { if (OB_FAIL((get_obj_for_calc(ctx.allocator_, obj1, obj2)))) { LOG_WARN("get float obj failed", K(obj1), K(obj2), K(ret)); + } else if (fabs(obj2.get_float()) < FLT_EPSILON) { + result_obj.set_null(); } else { float obj1_f = obj1.get_float(); float obj2_f = obj2.get_float(); @@ -846,9 +860,9 @@ int ObProxyExprDiv::calc(const ObProxyExprCtx &ctx, } } } else { - if (OB_FAIL(get_int_obj(param_result.at(0), obj1))) { + if (OB_FAIL(get_int_obj(param_result.at(0), obj1, *ctx.allocator_))) { LOG_WARN("get int obj failed", K(ret)); - } else if (OB_FAIL(get_int_obj(param_result.at(1), obj2))) { + } else if (OB_FAIL(get_int_obj(param_result.at(1), obj2, *ctx.allocator_))) { LOG_WARN("get int obj failed", K(ret)); } else { int64_t num1 = obj1.get_int(); @@ -866,7 +880,7 @@ int ObProxyExprDiv::calc(const ObProxyExprCtx &ctx, LOG_WARN("result obj array push back failed", K(ret)); } } - } while (++i < cnt); + } while (OB_SUCC(ret) && ++i < cnt); } } ObProxyExpr::print_proxy_expr(this); @@ -907,7 +921,7 @@ int ObProxyExprAdd::calc(const ObProxyExprCtx &ctx, tmp_obj = param_result_array.at(j).at(i); } if (OB_FAIL(param_result.push_back(tmp_obj))) { - LOG_WARN("push back obj faile", K(ret), K(i), K(j)); + LOG_WARN("push back obj failed", K(ret), K(i), K(j)); } } @@ -950,9 +964,9 @@ int ObProxyExprAdd::calc(const ObProxyExprCtx &ctx, } } } else { - if (OB_FAIL(get_int_obj(param_result.at(0), obj1))) { + if (OB_FAIL(get_int_obj(param_result.at(0), obj1, *ctx.allocator_))) { LOG_WARN("get int obj failed", K(ret)); - } else if (OB_FAIL(get_int_obj(param_result.at(1), obj2))) { + } else if (OB_FAIL(get_int_obj(param_result.at(1), obj2, *ctx.allocator_))) { LOG_WARN("get int obj failed", K(ret)); } else { int64_t num1 = obj1.get_int(); @@ -970,7 +984,7 @@ int ObProxyExprAdd::calc(const ObProxyExprCtx &ctx, LOG_WARN("result obj array push back failed", K(ret)); } } - } while (++i < cnt); + } while (OB_SUCC(ret) && ++i < cnt); } } ObProxyExpr::print_proxy_expr(this); @@ -1011,7 +1025,7 @@ int ObProxyExprSub::calc(const ObProxyExprCtx &ctx, tmp_obj = param_result_array.at(j).at(i); } if (OB_FAIL(param_result.push_back(tmp_obj))) { - LOG_WARN("push back obj faile", K(ret), K(i), K(j)); + LOG_WARN("push back obj failed", K(ret), K(i), K(j)); } } @@ -1054,9 +1068,9 @@ int ObProxyExprSub::calc(const ObProxyExprCtx &ctx, } } } else { - if (OB_FAIL(get_int_obj(param_result.at(0), obj1))) { + if (OB_FAIL(get_int_obj(param_result.at(0), obj1, *ctx.allocator_))) { LOG_WARN("get int obj failed", K(ret)); - } else if (OB_FAIL(get_int_obj(param_result.at(1), obj2))) { + } else if (OB_FAIL(get_int_obj(param_result.at(1), obj2, *ctx.allocator_))) { LOG_WARN("get int obj failed", K(ret)); } else { int64_t num1 = obj1.get_int(); @@ -1074,7 +1088,7 @@ int ObProxyExprSub::calc(const ObProxyExprCtx &ctx, LOG_WARN("result obj array push back failed", K(ret)); } } - } while (++i < cnt); + } while (OB_SUCC(ret) && ++i < cnt); } } ObProxyExpr::print_proxy_expr(this); @@ -1115,7 +1129,7 @@ int ObProxyExprMul::calc(const ObProxyExprCtx &ctx, tmp_obj = param_result_array.at(j).at(i); } if (OB_FAIL(param_result.push_back(tmp_obj))) { - LOG_WARN("push back obj faile", K(ret), K(i), K(j)); + LOG_WARN("push back obj failed", K(ret), K(i), K(j)); } } @@ -1158,9 +1172,9 @@ int ObProxyExprMul::calc(const ObProxyExprCtx &ctx, } } } else { - if (OB_FAIL(get_int_obj(param_result.at(0), obj1))) { + if (OB_FAIL(get_int_obj(param_result.at(0), obj1, *ctx.allocator_))) { LOG_WARN("get int obj failed", K(ret)); - } else if (OB_FAIL(get_int_obj(param_result.at(1), obj2))) { + } else if (OB_FAIL(get_int_obj(param_result.at(1), obj2, *ctx.allocator_))) { LOG_WARN("get int obj failed", K(ret)); } else { int64_t num1 = obj1.get_int(); @@ -1178,7 +1192,7 @@ int ObProxyExprMul::calc(const ObProxyExprCtx &ctx, LOG_WARN("result obj array push back failed", K(ret)); } } - } while (++i < cnt); + } while (OB_SUCC(ret) && ++i < cnt); } } ObProxyExpr::print_proxy_expr(this); @@ -1215,7 +1229,7 @@ int ObProxyExprTestLoad::calc(const ObProxyExprCtx &ctx, tmp_obj = param_result_array.at(j).at(i); } if (OB_FAIL(param_result.push_back(tmp_obj))) { - LOG_WARN("push back obj faile", K(ret), K(i), K(j)); + LOG_WARN("push back obj failed", K(ret), K(i), K(j)); } } @@ -1236,7 +1250,7 @@ int ObProxyExprTestLoad::calc(const ObProxyExprCtx &ctx, } } } - } while (++i < cnt); + } while (OB_SUCC(ret) && ++i < cnt); } } ObProxyExpr::print_proxy_expr(this); @@ -1273,7 +1287,7 @@ int ObProxyExprSplit::calc(const ObProxyExprCtx &ctx, tmp_obj = param_result_array.at(j).at(i); } if (OB_FAIL(param_result.push_back(tmp_obj))) { - LOG_WARN("push back obj faile", K(ret), K(i), K(j)); + LOG_WARN("push back obj failed", K(ret), K(i), K(j)); } } @@ -1303,7 +1317,7 @@ int ObProxyExprSplit::calc(const ObProxyExprCtx &ctx, if (OB_SUCC(ret)) { ObObj obj; - if (OB_FAIL(get_int_obj(param_result.at(2), obj))) { + if (OB_FAIL(get_int_obj(param_result.at(2), obj, *ctx.allocator_))) { LOG_WARN("get int obj failed", K(ret)); } else if (OB_FAIL(obj.get_int(index))) { LOG_WARN("get int failed", K(ret)); @@ -1374,7 +1388,7 @@ int ObProxyExprSplit::calc(const ObProxyExprCtx &ctx, } } } - } while (++i < cnt); + } while (OB_SUCC(ret) && ++i < cnt); } } ObProxyExpr::print_proxy_expr(this); @@ -1404,7 +1418,7 @@ int ObProxyExprAvg::calc(const ObProxyExprCtx &ctx, const ObProxyExprCalcItem &c if (ObDoubleTC == obj1.get_type_class() || ObDoubleTC == obj2.get_type_class()) { if (OB_FAIL((get_obj_for_calc(ctx.allocator_, obj1, obj2)))) { LOG_WARN("get double obj failed", K(obj1), K(obj2), K(ret)); - } else if (fabs(obj2.get_double()) == 0.0) { + } else if (fabs(obj2.get_double()) < DBL_EPSILON) { result_obj.set_null(); } else { double obj1_d = obj1.get_double(); @@ -1414,6 +1428,8 @@ int ObProxyExprAvg::calc(const ObProxyExprCtx &ctx, const ObProxyExprCalcItem &c } else if (ObFloatTC == obj1.get_type_class() || ObFloatTC == obj2.get_type_class()) { if (OB_FAIL((get_obj_for_calc(ctx.allocator_, obj1, obj2)))) { LOG_WARN("get float obj failed", K(obj1), K(obj2), K(ret)); + } else if (fabs(obj2.get_float() < FLT_EPSILON)) { + result_obj.set_null(); } else { float obj1_f = obj1.get_float(); float obj2_f = obj2.get_float(); @@ -1440,9 +1456,9 @@ int ObProxyExprAvg::calc(const ObProxyExprCtx &ctx, const ObProxyExprCalcItem &c } } } else { - if (OB_FAIL(get_int_obj(param_result.at(0), obj1))) { + if (OB_FAIL(get_int_obj(param_result.at(0), obj1, *ctx.allocator_))) { LOG_WARN("get int obj failed", K(ret)); - } else if (OB_FAIL(get_int_obj(param_result.at(1), obj2))) { + } else if (OB_FAIL(get_int_obj(param_result.at(1), obj2, *ctx.allocator_))) { LOG_WARN("get int obj failed", K(ret)); } else { int64_t num1 = obj1.get_int(); @@ -1471,6 +1487,383 @@ int ObProxyExprAvg::calc(const ObProxyExprCtx &ctx, const ObProxyExprCalcItem &c return ret; } +/* + * for to_date and to_timestamp, only support at least one param, at most two params + */ +int ObProxyExprToTimeHandler::calc(const ObProxyExprCtx &ctx, + const ObProxyExprCalcItem &calc_item, + common::ObIArray &result_obj_array) +{ + int ret = OB_SUCCESS; + common::ObSEArray, 4> param_result_array; + int cnt = 0; + int64_t len = result_obj_array.count(); + + if (OB_FAIL(ObProxyExpr::calc(ctx, calc_item, result_obj_array))) { + LOG_WARN("calc expr failed", K(ret), K(param_array_.count())); + } else if (len == result_obj_array.count()) { + if (OB_UNLIKELY(param_array_.count() < 1)) { + ret = OB_EXPR_CALC_ERROR; + LOG_WARN("to_date should have at least one param", K(ret)); + } else if (OB_FAIL(calc_param_expr(ctx, calc_item, param_result_array, cnt))) { + LOG_WARN("calc param expr failed", K(ret)); + } else { + int i = 0; + do { + common::ObSEArray param_result; + for (int64_t j = 0; OB_SUCC(ret) && j < param_result_array.count(); j++) { + ObObj tmp_obj; + if (param_result_array.at(j).count() == 1) { + tmp_obj = param_result_array.at(j).at(0); + } else { + tmp_obj = param_result_array.at(j).at(i); + } + if (OB_FAIL(param_result.push_back(tmp_obj))) { + LOG_WARN("push back obj failed", K(ret), K(i), K(j)); + } + } + + ObObjTypeClass type = param_result.at(0).get_type_class(); + if (OB_SUCC(ret) && type != ObStringTC && type != ObIntTC && type != ObNumberTC) { + ret = OB_EXPR_CALC_ERROR; + LOG_WARN("unexpected the first param type of to_date", K(type)); + } + + ObTimeZoneInfo tz_info; + ObDataTypeCastParams dtc_params; + if (OB_SUCC(ret)) { + ObObj second_obj; + ObString nls_format; + + if (2 == param_result.count()) { + if(OB_FAIL(get_varchar_obj(param_result.at(1), second_obj, *ctx.allocator_))){ + LOG_WARN("get varchar obj failed", K(ret)); + } else if (OB_FAIL(second_obj.get_varchar(nls_format))) { + LOG_WARN("get varchar failded", K(ret)); + } else { + if (!nls_format.empty()) { + dtc_params.tz_info_ = &tz_info; + dtc_params.set_nls_format_by_type(target_type_, nls_format); + } else { + dtc_params.tz_info_ = &tz_info; + if (OB_FAIL(proxy::ObExprCalcTool::build_dtc_params( + ctx.client_session_info_, target_type_, dtc_params))) { + LOG_WARN("fail to build dtc params", K(ret), K(target_type_)); + } + } + } + } + } + + ObCollationType collation = ObCharset::get_default_collation(ObCharset::get_default_charset()); + ObCastCtx cast_ctx(ctx.allocator_, &dtc_params, CM_NULL_ON_WARN, collation); + param_result.at(0).set_collation_type(collation); + if (OB_SUCC(ret) && OB_FAIL(ObObjCasterV2::to_type(target_type_, collation, cast_ctx, + param_result.at(0), param_result.at(0)))) { + LOG_WARN("fail to cast obj", K(ret), K(target_type_), K(collation)); + } + if (OB_SUCC(ret) && OB_FAIL(result_obj_array.push_back(param_result.at(0)))) { + LOG_WARN("result obj array push back failed", K(ret)); + } + } while (OB_SUCC(ret) && ++i < cnt); + } + } + ObProxyExpr::print_proxy_expr(this); + return ret; +} + +int ObProxyExprNvl::calc(const ObProxyExprCtx &ctx, + const ObProxyExprCalcItem &calc_item, + common::ObIArray &result_obj_array) +{ + int ret = OB_SUCCESS; + common::ObSEArray, 4> param_result_array; + int cnt = 0; + int64_t len = result_obj_array.count(); + + if (OB_FAIL(ObProxyExpr::calc(ctx, calc_item, result_obj_array))) { + LOG_WARN("calc expr failed", K(ret), K(param_array_.count())); + } else if (len == result_obj_array.count()) { + if (OB_UNLIKELY(param_array_.count() != 2)) { + ret = OB_EXPR_CALC_ERROR; + LOG_WARN("nvl should have two param", K(ret)); + } else if (OB_FAIL(calc_param_expr(ctx, calc_item, param_result_array, cnt))) { + LOG_WARN("calc param expr failed", K(ret)); + } else { + int i = 0; + do { + common::ObSEArray param_result; + for (int64_t j = 0; OB_SUCC(ret) && j < param_result_array.count(); j++) { + ObObj tmp_obj; + if (param_result_array.at(j).count() == 1) { + tmp_obj = param_result_array.at(j).at(0); + } else { + tmp_obj = param_result_array.at(j).at(i); + } + if (OB_FAIL(param_result.push_back(tmp_obj))) { + LOG_WARN("push back obj failed", K(ret), K(i), K(j)); + } + } + + ObObj result_obj = param_result.at(0); + ObObj second_obj = param_result.at(1); + if (OB_SUCC(ret)) { + // null expr or empty varchar treated as null + if (result_obj.is_null()) { + result_obj = second_obj; + } else if (result_obj.is_string_type()) { + ObString str; + if (OB_FAIL(result_obj.get_string(str))) { + LOG_WARN("get varchar of param failed", K(ret)); + } else if (str.empty()) { + result_obj = second_obj; + } + } + } + + if (OB_SUCC(ret) && OB_FAIL(result_obj_array.push_back(result_obj))) { + LOG_WARN("result obj array push back failed", K(ret)); + } + } while (OB_SUCC(ret) && ++i < cnt); + } + } + ObProxyExpr::print_proxy_expr(this); + return ret; +} + +/* + * only support datetime format. + */ +int ObProxyExprToChar::calc(const ObProxyExprCtx &ctx, + const ObProxyExprCalcItem &calc_item, + common::ObIArray &result_obj_array) +{ + int ret = OB_SUCCESS; + common::ObSEArray, 4> param_result_array; + int cnt = 0; + int64_t len = result_obj_array.count(); + + if (OB_FAIL(ObProxyExpr::calc(ctx, calc_item, result_obj_array))) { + LOG_WARN("calc expr failed", K(ret), K(param_array_.count())); + } else if (len == result_obj_array.count()) { + if (OB_UNLIKELY(param_array_.count() < 1) || OB_UNLIKELY(param_array_.count() > 2)) { + ret = OB_EXPR_CALC_ERROR; + LOG_WARN("to_char should have one or two param", K(ret), K(param_array_.count())); + } else if (OB_FAIL(calc_param_expr(ctx, calc_item, param_result_array, cnt))) { + LOG_WARN("calc param expr failed", K(ret)); + } else { + int i = 0; + do { + common::ObSEArray param_result; + for (int64_t j = 0; OB_SUCC(ret) && j < param_result_array.count(); j++) { + ObObj tmp_obj; + if (param_result_array.at(j).count() == 1) { + tmp_obj = param_result_array.at(j).at(0); + } else { + tmp_obj = param_result_array.at(j).at(i); + } + if (OB_FAIL(param_result.push_back(tmp_obj))) { + LOG_WARN("push back obj failed", K(ret), K(i), K(j)); + } + } + if (OB_SUCC(ret)) { + ObObjType target_type = ObVarcharType; + ObObj result_obj = param_result.at(0); + ObObj second_obj; + ObString nls_format; + ObTimeZoneInfo tz_info; + ObDataTypeCastParams dtc_params = ObDataTypeCastParams(); + + // to_char(datetime) return NULL when nls_format parmas is '' + bool is_empty_format = false; + + ObCollationType collation = ObCharset::get_default_collation(ObCharset::get_default_charset()); + dtc_params.tz_info_ = &tz_info; + + if (ObDateTimeTC != param_result.at(0).get_type_class() && ObOTimestampTC != param_result.at(0).get_type_class()) { + ret = OB_EXPR_CALC_ERROR; + LOG_WARN("unsupported first param type of to_char", K(param_result.at(0).get_type_class())); + } else if (2 == param_result.count()) { + if (OB_FAIL(get_varchar_obj(param_result.at(1), second_obj, *ctx.allocator_))) { + LOG_WARN("get varchar obj failed", K(ret)); + } else if (OB_FAIL(second_obj.get_varchar(nls_format))) { + LOG_WARN("get varchar failed", K(ret)); + } else { + if (!nls_format.empty()) { + // ObObjCasterV2 only support ObOTimestampTC to format by nls_format, here convert ObDateTimeTC to ObTimestampTZType + dtc_params.set_nls_format_by_type(ObTimestampTZType, nls_format); + ObCastCtx cast_ctx_otimestamp(ctx.allocator_, &dtc_params, CM_NULL_ON_WARN, collation); + if (OB_FAIL(ObObjCasterV2::to_type(ObTimestampTZType, collation, cast_ctx_otimestamp, + result_obj, result_obj))) { + LOG_WARN("cast DateTime to ObTimestampTZTType failed", K(ret)); + } + } else { + is_empty_format = true; + } + } + } + + if (OB_SUCC(ret)) { + ObCastCtx cast_ctx(ctx.allocator_, &dtc_params, CM_NULL_ON_WARN, collation); + if (param_array_.count() == 1) { + // do nothing + } else if (is_empty_format) { + result_obj.set_null(); + } else if (OB_FAIL(ObObjCasterV2::to_type(target_type, collation, cast_ctx, result_obj, result_obj))) { + LOG_WARN("fail to cast obj to timestamp", K(ret), K(result_obj), K(target_type), K(collation)); + } + } + + if (OB_SUCC(ret) && OB_FAIL(result_obj_array.push_back(result_obj))) { + LOG_WARN("result obj array push back failed", K(ret)); + } + } + } while (OB_SUCC(ret) && ++i < cnt); + } + } + ObProxyExpr::print_proxy_expr(this); + return ret; +} + +int ObProxyExprSysdate::calc(const ObProxyExprCtx &ctx, + const ObProxyExprCalcItem &calc_item, + common::ObIArray &result_obj_array) +{ + int ret = OB_SUCCESS; + int cnt = 0; + int64_t len = result_obj_array.count(); + + if (OB_FAIL(ObProxyExpr::calc(ctx, calc_item, result_obj_array))) { + LOG_WARN("calc expr failed", K(ret)); + } else if (len == result_obj_array.count()) { + if (OB_UNLIKELY(param_array_.count() > 0)) { + ret = OB_EXPR_CALC_ERROR; + LOG_WARN("sysdate should have no param", K(ret)); + } else { + int i = 0; + do { + common::ObSEArray param_result; + if (OB_SUCC(ret)) { + ObObjType target_type = ObDateTimeType; + + int64 now = common::ObTimeUtility::current_time(); + // calc timezone offset to correct the time zone info + int64 gm_time_buf = (int64)((time_t)now - mktime(gmtime((time_t *)&now))) * 1000000; + + ObObj result_obj; + result_obj.set_timestamp(now + gm_time_buf); + ObTimeZoneInfo tz_info; + ObCollationType collation = ObCharset::get_default_collation(ObCharset::get_default_charset()); + if (OB_SUCC(ret)) { + ObCastCtx cast_ctx(ctx.allocator_, NULL, CM_NULL_ON_WARN, collation); + if (OB_FAIL(ObObjCasterV2::to_type(target_type, collation, cast_ctx, result_obj, result_obj))) { + LOG_WARN("fail to cast obj to timestamp", K(ret), K(result_obj), K(target_type), K(collation)); + } else if (OB_FAIL(result_obj_array.push_back(result_obj))) { + LOG_WARN("result obj array push back failed", K(ret)); + } + } + } + } while (OB_SUCC(ret) && ++i < cnt); + } + } + ObProxyExpr::print_proxy_expr(this); + return ret; +} + +/* + * refer to the implementation of oracle + * mod calculate: MOD(n1, n2) = n1 - n2 * FLOOR(n1/n2) + * when ( n2 = 0 ), return n1 + */ +int ObProxyExprMod::calc(const ObProxyExprCtx &ctx, + const ObProxyExprCalcItem &calc_item, + common::ObIArray &result_obj_array) +{ + int ret = OB_SUCCESS; + common::ObSEArray, 4> param_result_array; + int cnt = 0; + int64_t len = result_obj_array.count(); + + if (-1 != index_ && + ObProxyExprCalcItem::FROM_OBJ_ARRAY == calc_item.source_ && !has_agg_) { + if (OB_FAIL(ObProxyExpr::calc(ctx, calc_item, result_obj_array))) { + LOG_WARN("calc expr failed", K(ret)); + } + } + + if (OB_SUCC(ret) && len == result_obj_array.count()) { + if (2 != param_array_.count()) { + ret = OB_EXPR_CALC_ERROR; + LOG_WARN("mod should have two param", K(ret), K(param_array_.count())); + } else if (OB_FAIL( + calc_param_expr(ctx, calc_item, param_result_array, cnt))) { + LOG_WARN("calc param result failed", K(ret)); + } else { + int i = 0; + do { + common::ObSEArray param_result; + for (int64_t j = 0; OB_SUCC(ret) && j < param_result_array.count(); j++) { + ObObj tmp_obj; + if (param_result_array.at(j).count() == 1) { + tmp_obj = param_result_array.at(j).at(0); + } else { + tmp_obj = param_result_array.at(j).at(i); + } + if (OB_FAIL(param_result.push_back(tmp_obj))) { + LOG_WARN("push back obj failed", K(ret), K(i), K(j)); + } + } + + if (OB_SUCC(ret)) { + ObObj obj1 = param_result.at(0); + ObObj obj2 = param_result.at(1); + ObObj result_obj; + + if (ObDoubleTC == obj1.get_type_class() || + ObDoubleTC == obj2.get_type_class()) { + if (OB_FAIL((get_obj_for_calc(ctx.allocator_, obj1, obj2)))) { + LOG_WARN("get double obj failed", K(obj1), K(obj2), K(ret)); + } else if (fabs(obj2.get_double()) < DBL_EPSILON) { + result_obj.set_double(obj1.get_double()); + } else { + double obj1_d = obj1.get_double(); + double obj2_d = obj2.get_double(); + result_obj.set_double(obj1_d - obj2_d * floor(obj1_d / obj1_d)); + } + } else if (ObFloatTC == obj1.get_type_class() || ObFloatTC == obj2.get_type_class()) { + if (OB_FAIL((get_obj_for_calc(ctx.allocator_, obj1, obj2)))) { + LOG_WARN("get float obj failed", K(obj1), K(obj2), K(ret)); + } else if (fabs(obj2.get_float()) < FLT_EPSILON) { + result_obj.set_float(obj1.get_float()); + } else { + float obj1_f = obj1.get_float(); + float obj2_f = obj2.get_float(); + result_obj.set_float(obj1_f - obj2_f * floor(obj1_f / obj1_f)); + } + } else { + number::ObNumber res_nmb; + if (OB_FAIL((get_obj_for_calc(ctx.allocator_, obj1, obj2)))) { + LOG_WARN("get number obj failed", K(ret), K(obj1), K(obj2)); + } else if (obj2.get_number().is_zero()) { + result_obj.set_number(obj1.get_number()); + } else if (OB_FAIL(obj1.get_number().rem(obj2.get_number(), res_nmb, *ctx.allocator_))) { + LOG_WARN("failed to mod numbers", K(ret), K(obj1), K(obj2)); + } else if (OB_SUCC(ret)) { + result_obj.set_number(res_nmb); + } + } + + if (OB_SUCC(ret) && OB_FAIL(result_obj_array.push_back(result_obj))) { + LOG_WARN("result obj array push back failed", K(ret)); + } + } + } while (OB_SUCC(ret) && ++i < cnt); + } + } + ObProxyExpr::print_proxy_expr(this); + return ret; +} + } // end opsql } // end obproxy } // end oceanbase diff --git a/src/obproxy/opsql/func_expr_resolver/proxy_expr/ob_proxy_expr.h b/src/obproxy/opsql/func_expr_resolver/proxy_expr/ob_proxy_expr.h index cda8fca6ae2dfe5f89f937399243884285528842..e7ff0800841cad4984fa37a5dda91d1929584812 100644 --- a/src/obproxy/opsql/func_expr_resolver/proxy_expr/ob_proxy_expr.h +++ b/src/obproxy/opsql/func_expr_resolver/proxy_expr/ob_proxy_expr.h @@ -13,10 +13,11 @@ #ifndef OB_FUNC_EXPR_PROXY_EXPR_H #define OB_FUNC_EXPR_PROXY_EXPR_H -#include "opsql/func_expr_resolver/proxy_expr/ob_proxy_expr_type.h" #include "dbconfig/ob_proxy_db_config_info.h" #include "lib/allocator/ob_mod_define.h" #include "lib/ob_define.h" +#include "opsql/func_expr_resolver/proxy_expr/ob_proxy_expr_type.h" +#include "proxy/mysqllib/ob_proxy_session_info.h" namespace oceanbase { @@ -30,15 +31,26 @@ class ObProxyExprCtx { public: explicit ObProxyExprCtx(const int64_t physical_size, dbconfig::ObTestLoadType type, - bool is_elastic_index, common::ObIAllocator* allocator) + bool is_elastic_index, common::ObIAllocator *allocator) : sharding_physical_size_(physical_size), test_load_type_(type), is_elastic_index_(is_elastic_index), - allocator_(allocator), scale_(-1) {} + allocator_(allocator), scale_(-1), is_oracle_mode(false) {} + explicit ObProxyExprCtx(const int64_t physical_size, + dbconfig::ObTestLoadType type, bool is_elastic_index, + common::ObIAllocator *allocator, + proxy::ObClientSessionInfo *client_session_info) + : sharding_physical_size_(physical_size), test_load_type_(type), + is_elastic_index_(is_elastic_index), allocator_(allocator), scale_(-1), + client_session_info_(client_session_info), is_oracle_mode(false) {} ~ObProxyExprCtx() {} void set_sharding_physical_size(const int64_t physical_size) { sharding_physical_size_ = physical_size; } void set_test_load_type(const dbconfig::ObTestLoadType type) { test_load_type_ = type; } void set_is_elastic_index(const bool is_elastic_index) { is_elastic_index_ = is_elastic_index; } void set_scale(const int64_t scale) { scale_ = scale; }; + void set_client_session_info(proxy::ObClientSessionInfo *client_session_info) + { + client_session_info_ = client_session_info; + } public: int64_t sharding_physical_size_; @@ -46,6 +58,8 @@ public: bool is_elastic_index_; common::ObIAllocator *allocator_; int64_t scale_; + proxy::ObClientSessionInfo *client_session_info_; + bool is_oracle_mode; }; struct ObProxyExprCalcItem { @@ -255,6 +269,8 @@ public: virtual ~ObProxyFuncExpr(); int add_param_expr(ObProxyExpr* expr) { return param_array_.push_back(expr); } + int64_t get_param_conut() { return param_array_.count(); } + int calc_param_expr(const ObProxyExprCtx &ctx, const ObProxyExprCalcItem &calc_item, common::ObSEArray, 4> ¶m_result, int &cnt); @@ -263,7 +279,7 @@ public: void set_param_array(common::ObSEArray& param_array) { param_array_ = param_array; } public: - static int get_int_obj(const common::ObObj &src, common::ObObj &dst); + static int get_int_obj(const common::ObObj &src, common::ObObj &dst, common::ObIAllocator &allocator); static int get_varchar_obj(const common::ObObj &src, common::ObObj &dst, common::ObIAllocator &allocator); int check_varchar_empty(const common::ObObj& result); @@ -415,6 +431,56 @@ public: common::ObIArray &result_obj_array); }; +// include to_date and to_timestamp +class ObProxyExprToTimeHandler : public ObProxyFuncExpr +{ +public: + explicit ObProxyExprToTimeHandler() {} + explicit ObProxyExprToTimeHandler(ObObjType &target_type) : target_type_(target_type) {} + ~ObProxyExprToTimeHandler() {} + int calc(const ObProxyExprCtx &ctx, const ObProxyExprCalcItem &calc_item, + common::ObIArray &result_obj_array); + void set_target_type(ObObjType target_type) { target_type_ = target_type; } +private: + ObObjType target_type_; +}; + +class ObProxyExprNvl : public ObProxyFuncExpr +{ +public: + explicit ObProxyExprNvl() {} + ~ObProxyExprNvl() {} + int calc(const ObProxyExprCtx &ctx, const ObProxyExprCalcItem &calc_item, + common::ObIArray &result_obj_array); +}; + +class ObProxyExprToChar : public ObProxyFuncExpr +{ +public: + explicit ObProxyExprToChar() {} + ~ObProxyExprToChar() {} + int calc(const ObProxyExprCtx &ctx, const ObProxyExprCalcItem &calc_item, + common::ObIArray &result_obj_array); +}; + +class ObProxyExprSysdate : public ObProxyFuncExpr +{ +public: + explicit ObProxyExprSysdate() {} + ~ObProxyExprSysdate() {} + int calc(const ObProxyExprCtx &ctx, const ObProxyExprCalcItem &calc_item, + common::ObIArray &result_obj_array); +}; + +class ObProxyExprMod : public ObProxyFuncExpr +{ +public: + explicit ObProxyExprMod() {} + ~ObProxyExprMod() {} + int calc(const ObProxyExprCtx &ctx, const ObProxyExprCalcItem &calc_item, + common::ObIArray &result_obj_array); +}; + } // end opsql } // end obproxy } // end oceanbase diff --git a/src/obproxy/opsql/func_expr_resolver/proxy_expr/ob_proxy_expr_type.h b/src/obproxy/opsql/func_expr_resolver/proxy_expr/ob_proxy_expr_type.h index 6554cb50407929af81e558b81b1409aa3e88d38c..115929f36c060ef5716668872426e56f76c74474 100644 --- a/src/obproxy/opsql/func_expr_resolver/proxy_expr/ob_proxy_expr_type.h +++ b/src/obproxy/opsql/func_expr_resolver/proxy_expr/ob_proxy_expr_type.h @@ -38,6 +38,12 @@ typedef enum ObProxyExprType OB_PROXY_EXPR_TYPE_FUNC_ORDER, OB_PROXY_EXPR_TYPE_FUNC_TESTLOAD, OB_PROXY_EXPR_TYPE_FUNC_SPLIT, + OB_PROXY_EXPR_TYPE_FUNC_TO_DATE, + OB_PROXY_EXPR_TYPE_FUNC_TO_TIMESTAMP, + OB_PROXY_EXPR_TYPE_FUNC_NVL, + OB_PROXY_EXPR_TYPE_FUNC_TO_CHAR, + OB_PROXY_EXPR_TYPE_FUNC_SYSDATE, + OB_PROXY_EXPR_TYPE_FUNC_MOD, OB_PROXY_EXPR_TYPE_MAX, }ObProxyExprType; @@ -112,6 +118,24 @@ const char* get_expr_type_name(int expr_type) case OB_PROXY_EXPR_TYPE_FUNC_TESTLOAD: type_name = "OB_PROXY_EXPR_TYPE_FUNC_TESTLOAD"; break; + case OB_PROXY_EXPR_TYPE_FUNC_TO_DATE: + type_name = "OB_PROXY_EXPR_TYPE_FUNC_TO_DATE"; + break; + case OB_PROXY_EXPR_TYPE_FUNC_TO_TIMESTAMP: + type_name = "OB_PROXY_EXPR_TYPE_FUNC_TO_TIMESTAMP"; + break; + case OB_PROXY_EXPR_TYPE_FUNC_NVL: + type_name = "OB_PROXY_EXPR_TYPE_FUNC_NVL"; + break; + case OB_PROXY_EXPR_TYPE_FUNC_TO_CHAR: + type_name = "OB_PROXY_EXPR_TYPE_FUNC_TO_CHAR"; + break; + case OB_PROXY_EXPR_TYPE_FUNC_SYSDATE: + type_name = "OB_PROXY_EXPR_TYPE_FUNC_SYSDATE"; + break; + case OB_PROXY_EXPR_TYPE_FUNC_MOD: + type_name = "OB_PROXY_EXPR_TYPE_FUNC_MOD"; + break; case OB_PROXY_EXPR_TYPE_MAX: type_name = "OB_PROXY_EXPR_TYPE_MAX"; break; diff --git a/src/obproxy/opsql/parser/gen_parser.sh b/src/obproxy/opsql/parser/gen_parser.sh index e0cfd92237902a5e77f0d483ed50bc380c618430..08c5d717a2901cf44d1cb61c6e7612d85cddd97b 100755 --- a/src/obproxy/opsql/parser/gen_parser.sh +++ b/src/obproxy/opsql/parser/gen_parser.sh @@ -26,6 +26,29 @@ sed "s/multi_byte_comma \[\\\uff0c\]/multi_byte_comma sed "s/multi_byte_left_parenthesis \[\\\uff08\]/multi_byte_left_parenthesis ([\\\xef\][\\\xbc\][\\\x88])/g" -i ob_proxy_parser_utf8.l sed "s/multi_byte_right_parenthesis \[\\\uff09\]/multi_byte_right_parenthesis ([\\\xef\][\\\xbc\][\\\x89])/g" -i ob_proxy_parser_utf8.l sed 's/space \[ \\t\\n\\r\\f\]/space (\[ \\t\\n\\r\\f\]|{multi_byte_space})/g' -i ob_proxy_parser_utf8.l +echo "U [\x80-\xbf] +U_1_1 [\x80] +U_1_2 [\x81-\xbf] +U_1_3 [\x80-\xbb] +U_1_4 [\xbc] +U_1_5 [\xbd-\xbf] +U_1_6 [\x80-\x87] +U_1_7 [\x8a-\x8b] +U_1_8 [\x8d-\xbf] +U_2 [\xc2-\xdf] +U_3 [\xe0-\xe2] +U_3_1 [\xe3] +U_3_2 [\xe4-\xee] +U_3_3 [\xef] +U_4 [\xf0-\xf4] +u_except_space ({U_3_1}{U_1_2}{U}|{U_3_1}{U_1_1}{U_1_2}) +u_except_comma_parenthesis ({U_3_3}{U_1_3}{U}|{U_3_3}{U_1_4}{U_1_6}|{U_3_3}{U_1_4}{U_1_7}|{U_3_3}{U_1_4}{U_1_8}|{U_3_3}{U_1_5}{U}) +UTF8_CHAR ({U_2}{U}|{U_3}{U}{U}|{u_except_space}|{U_3_2}{U}{U}|{u_except_comma_parenthesis}|{U_4}{U}{U}{U})" > utf8.txt +sed '/following character status will be rewrite by gen_parse.sh according to connection character/d' -i ob_proxy_parser_utf8.l +sed '/multi_byte_connect_char \/\*According to connection character to set by gen_parse.sh\*\//r utf8.txt' -i ob_proxy_parser_utf8.l +sed '/multi_byte_connect_char \/\*According to connection character to set by gen_parse.sh\*\//d' -i ob_proxy_parser_utf8.l +sed 's/space \[ \\t\\n\\r\\f\]/space (\[ \\t\\n\\r\\f\]|{multi_byte_space})/g' -i ob_proxy_parser_utf8.l +sed 's/multi_byte_connect_char/UTF8_CHAR/g' -i ob_proxy_parser_utf8.l ##4.generate oracle utf8 parser files # run bison @@ -100,3 +123,119 @@ sed "/Setup the input buffer state to scan the given bytes/,/}/{s/\tbuf\[i\] = y rm -f ob_proxy_parser_utf8.l rm -f ob_proxy_parser_utf8.y rm -f ob_proxy_parser_utf8.output + + +# generate oracle gbk obproxy_parser(support multi_byte_space, multi_byte_comma, multi_byte_left_parenthesis, multi_byte_right_parenthesis) +##1.copy lex and yacc files +cat ob_proxy_parser.y > ob_proxy_parser_gbk.y +cat ob_proxy_parser.l > ob_proxy_parser_gbk.l +##2.replace name +sed "s/ob_proxy_parser_yy/ob_proxy_parser_gbk_yy/g" -i ob_proxy_parser_gbk.y +sed "s/ob_proxy_parser_yy/ob_proxy_parser_gbk_yy/g" -i ob_proxy_parser_gbk.l +sed "s/ob_proxy_parser_lex/ob_proxy_parser_gbk_lex/g" -i ob_proxy_parser_gbk.y +sed "s/ob_proxy_parser_lex/ob_proxy_parser_gbk_lex/g" -i ob_proxy_parser_gbk.l +sed "s/ob_proxy_parser_tab/ob_proxy_parser_gbk_tab/g" -i ob_proxy_parser_gbk.l +sed "s/ob_proxy_parser_fatal_error/ob_proxy_gbk_parser_fatal_error/g" -i ob_proxy_parser_gbk.y +sed "s/ob_proxy_parser_fatal_error/ob_proxy_gbk_parser_fatal_error/g" -i ob_proxy_parser_gbk.l +sed "s/obproxy_parse_sql/obproxy_parse_gbk_sql/g" -i ob_proxy_parser_gbk.y +##3.add multi_byte_space, multi_byte_comma, multi_byte_left_parenthesis, multi_byte_right_parenthesis code. +sed "s/multi_byte_space \[\\\u3000\]/multi_byte_space ([\\\xa1][\\\xa1])/g" -i ob_proxy_parser_gbk.l +sed "s/multi_byte_comma \[\\\uff0c\]/multi_byte_comma ([\\\xa3][\\\xac])/g" -i ob_proxy_parser_gbk.l +sed "s/multi_byte_left_parenthesis \[\\\uff08\]/multi_byte_left_parenthesis ([\\\xa3][\\\xa8])/g" -i ob_proxy_parser_gbk.l +sed "s/multi_byte_right_parenthesis \[\\\uff09\]/multi_byte_right_parenthesis ([\\\xa3][\\\xa9])/g" -i ob_proxy_parser_gbk.l +sed 's/space \[ \\t\\n\\r\\f\]/space (\[ \\t\\n\\r\\f\]|{multi_byte_space})/g' -i ob_proxy_parser_gbk.l +echo "GB_1 [\x81-\xfe] +GB_1_1 [\x81-\xa0] +GB_1_2 [\xa1] +GB_1_3 [\xa2] +GB_1_4 [\xa3] +GB_1_5 [\xa4-\xf2] +GB_2 [\x40-\xfe] +GB_2_1 [\x40-\xa0] +GB_2_2 [\xa2-\xfe] +GB_2_3 [\x40-\xa7] +GB_2_4 [\xaa-\xab] +GB_2_5 [\xad-\xfe] +GB_3 [\x30-\x39] +g_except_space ({GB_1_2}{GB_2_1}|{GB_1_2}{GB_2_2}) +g_except_comma_parenthesis ({GB_1_4}{GB_2_3}|{GB_1_4}{GB_2_4}|{GB_1_4}{GB_2_5}) +GB_CHAR ({GB_1_1}{GB_2}|{g_except_space}|{GB_1_3}{GB_2}|{g_except_comma_parenthesis}|{GB_1_5}{GB_2}|{GB_1}{GB_3}{GB_1}{GB_3})" > gbk.txt +sed '/following character status will be rewrite by gen_parse.sh according to connection character/d' -i ob_proxy_parser_gbk.l +sed '/multi_byte_connect_char \/\*According to connection character to set by gen_parse.sh\*\//r gbk.txt' -i ob_proxy_parser_gbk.l +sed '/multi_byte_connect_char \/\*According to connection character to set by gen_parse.sh\*\//d' -i ob_proxy_parser_gbk.l +sed 's/space \[ \\t\\n\\r\\f\]/space (\[ \\t\\n\\r\\f\]|{multi_byte_space})/g' -i ob_proxy_parser_gbk.l +sed 's/multi_byte_connect_char/GB_CHAR/g' -i ob_proxy_parser_gbk.l +##4.generate oracle gbk parser files + +# run bison +#bison -p obproxy -v -Werror -d ob_proxy_parser.y -o ob_proxy_parser_tab.c +bison -v -Werror -d ob_proxy_parser_gbk.y -o ob_proxy_parser_gbk_tab.c +if [ $? -ne 0 ] +then + echo Compile error[$?], abort. + exit 1 +fi + +# format tab.h +sed "s/YY\([a-zA-Z_]*\)/OBPROXY\1/g" -i ob_proxy_parser_gbk_tab.h +sed "s/yy\([a-zA-Z_]*\)/obproxy\1/g" -i ob_proxy_parser_gbk_tab.h +sed "/Tokens/i #ifndef YY_OBPROXY_OB_PROXY_PARSER_TAB_H_INCLUDED\n\ +# define YY_OBPROXY_OB_PROXY_PARSER_TAB_H_INCLUDED\n\ +/* Debug traces. */\n\ +#ifndef OBPROXY_GBK_DEBUG\n\ +# if defined YYDEBUG\n\ +#if YYDEBUG\n\ +# define OBPROXY_GBK_DEBUG 1\n\ +# else\n\ +# define OBPROXY_GBK_DEBUG 0\n\ +# endif\n\ +# else /* ! defined YYDEBUG */\n\ +# define OBPROXY_GBK_DEBUG 0\n\ +# endif /* ! defined YYDEBUG */\n\ +#endif /* ! defined OBPROXY_GBK_DEBUG */\n\ +#if OBPROXY_GBK_DEBUG\n\ +extern int ob_proxy_parser_gbk_yydebug;\n\ +#endif" -i ob_proxy_parser_gbk_tab.h +echo "#endif" >> ob_proxy_parser_gbk_tab.h + +# formart tab.c +sed "/#define yyparse/i #define YYSTYPE OBPROXYSTYPE\n#define YYLTYPE OBPROXYLTYPE" -i ob_proxy_parser_gbk_tab.c +sed "/Tokens/,/Copy the second/{s/YY\([a-zA-Z_]\)/OBPROXY\1/g}" -i ob_proxy_parser_gbk_tab.c +sed "/Tokens/,/Copy the second/{s/yy\([a-zA-Z_]\)/obproxy\1/g}" -i ob_proxy_parser_gbk_tab.c +sed "s/yylex (\&yylval, \&yylloc)/yylex (\&yylval, \&yylloc, YYLEX_PARAM)/g" -i ob_proxy_parser_gbk_tab.c +sed "/Tokens/i #ifndef YY_OBPROXY_OB_PROXY_PARSER_TAB_H_INCLUDED\n\ +# define YY_OBPROXY_OB_PROXY_PARSER_TAB_H_INCLUDED\n\ +/* Debug traces. */\n\ +#ifndef OBPROXY_GBK_DEBUG\n\ +# if defined YYDEBUG\n\ +#if YYDEBUG\n\ +# define OBPROXY_GBK_DEBUG 1\n\ +# else\n\ +# define OBPROXY_GBK_DEBUG 0\n\ +# endif\n\ +# else /* ! defined YYDEBUG */\n\ +# define OBPROXY_GBK_DEBUG 0\n\ +# endif /* ! defined YYDEBUG */\n\ +#endif /* ! defined OBPROXY_GBK_DEBUG */\n\ +#if OBPROXY_GBK_DEBUG\n\ +extern int ob_proxy_parser_gbk_yydebug;\n\ +#endif" -i ob_proxy_parser_gbk_tab.c +sed "/Copy the second/i #endif" -i ob_proxy_parser_gbk_tab.c + +# run flex +#flex -P obproxy -Cfea -o ob_proxy_parser_lex.c ob_proxy_parser.l ob_proxy_parser_tab.h +flex -o ob_proxy_parser_gbk_lex.c ob_proxy_parser_gbk.l ob_proxy_parser_gbk_tab.h + +# format lex.h +sed "s/YYSTYPE/OBPROXYSTYPE/g" -i ob_proxy_parser_gbk_lex.h +sed "s/YYLTYPE/OBPROXYLTYPE/g" -i ob_proxy_parser_gbk_lex.h +sed "/static int yy_top_state (yyscan_t yyscanner );/d" -i ob_proxy_parser_gbk_lex.c +sed "/static int yy_top_state/,/\}/d" -i ob_proxy_parser_gbk_lex.c +sed "/\*yy_cp = '\\\0';/d" -i ob_proxy_parser_gbk_lex.c +sed "/Setup the input buffer state to scan the given bytes/,/}/{/int i/d}" -i ob_proxy_parser_gbk_lex.c +sed "/Setup the input buffer state to scan the given bytes/,/}/{/for ( i = 0; i < _yybytes_len; ++i )/d}" -i ob_proxy_parser_gbk_lex.c +sed "/Setup the input buffer state to scan the given bytes/,/}/{s/\tbuf\[i\] = yybytes\[i\]/memcpy(buf, yybytes, _yybytes_len)/g}" -i ob_proxy_parser_gbk_lex.c +##5.clean useless files +rm -f ob_proxy_parser_gbk.l +rm -f ob_proxy_parser_gbk.y +rm -f ob_proxy_parser_gbk.output diff --git a/src/obproxy/opsql/parser/ob_proxy_parse_result.cpp b/src/obproxy/opsql/parser/ob_proxy_parse_result.cpp index 2af63a5a084c40242a67ed514942f6f2eff0351a..97046f70d6f9465ec63f44ea4a3c9bc8a70800ac 100644 --- a/src/obproxy/opsql/parser/ob_proxy_parse_result.cpp +++ b/src/obproxy/opsql/parser/ob_proxy_parse_result.cpp @@ -116,9 +116,6 @@ const char* get_print_stmt_name(const ObProxyBasicStmtType type) case OBPROXY_T_SELECT_TX_RO: str_ret = "SELECT_TX_RO"; break; - case OBPROXY_T_SET_AC_0: - str_ret = "SET"; - break; case OBPROXY_T_PING_PROXY: str_ret = "PING"; break; @@ -181,6 +178,9 @@ const char* get_print_stmt_name(const ObProxyBasicStmtType type) case OBPROXY_T_TEXT_PS_EXECUTE: str_ret = "TEXT_PS_EXECUTE"; break; + case OBPROXY_T_TEXT_PS_DROP: + str_ret = "TEXT_PS_DROP"; + break; case OBPROXY_T_LOGIN: str_ret = "LOGIN"; break; @@ -188,6 +188,25 @@ const char* get_print_stmt_name(const ObProxyBasicStmtType type) str_ret = "DESC"; break; + case OBPROXY_T_SHOW_MASTER_STATUS: + str_ret = "SHOW_MASTER_STATUS"; + break; + case OBPROXY_T_SHOW_BINLOG_EVENTS: + str_ret = "SHOW_BINLOG_EVENTS"; + break; + case OBPROXY_T_PURGE_BINARY_LOGS: + str_ret = "PURGE_BINARY_LOGS"; + break; + case OBPROXY_T_RESET_MASTER: + str_ret = "RESET_MASTER"; + break; + case OBPROXY_T_SHOW_BINLOG_SERVER_FOR_TENANT: + str_ret = "SHOW_BINLOG_SERVER_FOR_TENANT"; + break; + case OBPROXY_T_SHOW_BINARY_LOGS: + str_ret = "SHOW_BINARY_LOGS"; + break; + case OBPROXY_T_INVALID: case OBPROXY_T_MAX: case OBPROXY_T_OTHERS: @@ -345,9 +364,6 @@ const char* get_obproxy_stmt_name(const ObProxyBasicStmtType type) case OBPROXY_T_SELECT_PROXY_VERSION: str_ret = "OBPROXY_T_SELECT_PROXY_VERSION"; break; - case OBPROXY_T_SET_AC_0: - str_ret = "OBPROXY_T_SET_AC_0"; - break; case OBPROXY_T_SHOW_WARNINGS: str_ret = "OBPROXY_T_SHOW_WARNINGS"; break; @@ -405,6 +421,15 @@ const char* get_obproxy_stmt_name(const ObProxyBasicStmtType type) case OBPROXY_T_TEXT_PS_EXECUTE: str_ret = "OBPROXY_T_TEXT_PS_EXECUTE"; break; + case OBPROXY_T_TEXT_PS_DROP: + str_ret = "OBPROXY_T_TEXT_PS_DROP"; + break; + case OBPROXY_T_LOGIN: + str_ret = "OBPROXY_T_LOGIN"; + break; + case OBPROXY_T_DESC: + str_ret = "OBPROXY_T_DESC"; + break; case OBPROXY_T_MAX: str_ret = "OBPROXY_T_MAX"; break; @@ -500,6 +525,9 @@ const char* get_obproxy_sub_stmt_name(const ObProxyBasicStmtSubType type) case OBPROXY_T_SUB_ROUTE_ROUTINE: str_ret = "OBPROXY_T_SUB_ROUTE_ROUTINE"; break; + case OBPROXY_T_SUB_SHOW_ELASTIC_ID: + str_ret = "OBPROXY_T_SUB_SHOW_ELASTIC_ID"; + break; case OBPROXY_T_SUB_SHOW_TOPOLOGY: str_ret = "OBPROXY_T_SUB_SHOW_TOPOLOGY"; break; @@ -509,6 +537,27 @@ const char* get_obproxy_sub_stmt_name(const ObProxyBasicStmtSubType type) case OBPROXY_T_SUB_SELECT_DATABASE: str_ret = "OBPROXY_T_SUB_SELECT_DATABASE"; break; + case OBPROXY_T_SUB_SHOW_DATABASES: + str_ret = "OBPROXY_T_SUB_SHOW_DATABASES"; + break; + case OBPROXY_T_SUB_SHOW_TABLES: + str_ret = "OBPROXY_T_SUB_SHOW_TABLES"; + break; + case OBPROXY_T_SUB_SHOW_FULL_TABLES: + str_ret = "OBPROXY_T_SUB_SHOW_FULL_TABLES"; + break; + case OBPROXY_T_SUB_SHOW_TABLE_STATUS: + str_ret = "OBPROXY_T_SUB_SHOW_TABLE_STATUS"; + break; + case OBPROXY_T_SUB_SHOW_CREATE_TABLE: + str_ret = "OBPROXY_T_SUB_SHOW_CREATE_TABLE"; + break; + case OBPROXY_T_SUB_SHOW_COLUMNS: + str_ret = "OBPROXY_T_SUB_SHOW_COLUMNS"; + break; + case OBPROXY_T_SUB_SHOW_INDEX: + str_ret = "OBPROXY_T_SUB_SHOW_INDEX"; + break; case OBPROXY_T_SUB_DESC_TABLE: str_ret = "OBPROXY_T_SUB_DESC_TABLE"; break; diff --git a/src/obproxy/opsql/parser/ob_proxy_parse_result.h b/src/obproxy/opsql/parser/ob_proxy_parse_result.h index 5cf911bd14a0f5aba347be094bf1653143d54365..04574905a64b187406b67a273080176cdcb6bf0a 100644 --- a/src/obproxy/opsql/parser/ob_proxy_parse_result.h +++ b/src/obproxy/opsql/parser/ob_proxy_parse_result.h @@ -87,7 +87,6 @@ typedef enum ObProxyBasicStmtType // internal request OBPROXY_T_BEGIN, OBPROXY_T_SELECT_TX_RO, - OBPROXY_T_SET_AC_0, OBPROXY_T_PING_PROXY, OBPROXY_T_SELECT_ROUTE_ADDR, OBPROXY_T_SET_ROUTE_ADDR, @@ -121,10 +120,19 @@ typedef enum ObProxyBasicStmtType // text ps OBPROXY_T_TEXT_PS_PREPARE, OBPROXY_T_TEXT_PS_EXECUTE, + OBPROXY_T_TEXT_PS_DROP, // only for print obproxy_stat log OBPROXY_T_LOGIN, + // binglog related + OBPROXY_T_SHOW_MASTER_STATUS, + OBPROXY_T_SHOW_BINARY_LOGS, + OBPROXY_T_SHOW_BINLOG_EVENTS, + OBPROXY_T_PURGE_BINARY_LOGS, + OBPROXY_T_RESET_MASTER, + OBPROXY_T_SHOW_BINLOG_SERVER_FOR_TENANT, + OBPROXY_T_MAX } ObProxyBasicStmtType; @@ -192,9 +200,14 @@ typedef enum ObProxyBasicStmtSubType //show OBPROXY_T_SUB_SHOW_DATABASES, OBPROXY_T_SUB_SHOW_TABLES, + OBPROXY_T_SUB_SHOW_FULL_TABLES, + OBPROXY_T_SUB_SHOW_TABLE_STATUS, OBPROXY_T_SUB_SHOW_CREATE_TABLE, + OBPROXY_T_SUB_SHOW_ELASTIC_ID, OBPROXY_T_SUB_SHOW_TOPOLOGY, OBPROXY_T_SUB_SHOW_DB_VERSION, + OBPROXY_T_SUB_SHOW_COLUMNS, + OBPROXY_T_SUB_SHOW_INDEX, //select OBPROXY_T_SUB_SELECT_DATABASE, @@ -271,18 +284,18 @@ typedef struct _ObProxyCallParseInfo int32_t node_count_; } ObProxyCallParseInfo; -typedef struct _ObProxyTextPsExecuteParseNode +typedef struct _ObProxyTextPsParseNode { ObProxyParseString str_value_; - struct _ObProxyTextPsExecuteParseNode *next_; -} ObProxyTextPsExecuteParseNode; + struct _ObProxyTextPsParseNode *next_; +} ObProxyTextPsParseNode; -typedef struct _ObProxyTextPsExecuteParseInfo +typedef struct _ObProxyTextPsParseInfo { - ObProxyTextPsExecuteParseNode *head_; - ObProxyTextPsExecuteParseNode *tail_; + ObProxyTextPsParseNode *head_; + ObProxyTextPsParseNode *tail_; int32_t node_count_; -} ObProxyTextPsExecuteParseInfo; +} ObProxyTextPsParseInfo; typedef struct _ObProxySimpleRouteParseInfo { @@ -327,7 +340,7 @@ typedef struct _ObDbMeshRouteInfo typedef enum _ObProxySetValueType { - SET_VALUE_TYPE_ONE = 0, + SET_VALUE_TYPE_NONE = 0, SET_VALUE_TYPE_STR, SET_VALUE_TYPE_INT, SET_VALUE_TYPE_NUMBER, @@ -374,6 +387,7 @@ typedef struct _ObDbpRouteInfo ObProxyParseString table_name_; ObProxyParseString group_idx_str_; bool scan_all_; + bool sticky_session_; bool has_shard_key_; ObDbpShardKeyInfo shard_key_infos_[OBPROXY_MAX_DBP_SHARD_KEY_NUM]; int shard_key_count_; @@ -421,6 +435,9 @@ typedef struct _ObProxyParseResult ObProxyParseString col_name_; ObProxyParseString trace_id_; ObProxyParseString rpc_id_; + + // store the route server address in sql comment + ObProxyParseString target_db_server_; // read_consistency ObProxyReadConsistencyType read_consistency_type_; // db/table name @@ -433,8 +450,8 @@ typedef struct _ObProxyParseResult ObProxySimpleRouteParseInfo simple_route_info_; // partiton(p1) ObProxyParseString part_name_; - // text ps execute user variables - ObProxyTextPsExecuteParseInfo text_ps_execute_parse_info_; + // text ps user variables + ObProxyTextPsParseInfo text_ps_parse_info_; // text ps name ObProxyParseString text_ps_name_; // text ps inner sql stmt type diff --git a/src/obproxy/opsql/parser/ob_proxy_parser.h b/src/obproxy/opsql/parser/ob_proxy_parser.h index 3941f3c97cd498ac8f44085fb5f9c029777b20ab..27167a992bccead0bf65d1127cb2845bb847b49c 100644 --- a/src/obproxy/opsql/parser/ob_proxy_parser.h +++ b/src/obproxy/opsql/parser/ob_proxy_parser.h @@ -24,6 +24,7 @@ #include extern "C" int obproxy_parse_utf8_sql(ObProxyParseResult *p, const char *pszSql, size_t iLen); +extern "C" int obproxy_parse_gbk_sql(ObProxyParseResult *p, const char *pszSql, size_t iLen); namespace oceanbase { @@ -151,6 +152,7 @@ inline int ObProxyParser::obparse(const common::ObString &sql_string, common::ObString parse_sql_string = sql_string; //set ; ob parse need end with ; bool add_semicolon = false; + char origin_byte = parse_sql_string.ptr()[sql_string.length() - 2]; if (parse_sql_string.ptr()[sql_string.length() - 3] != ';') { parse_sql_string.ptr()[sql_string.length() - 2] = ';'; add_semicolon = true; @@ -168,7 +170,7 @@ inline int ObProxyParser::obparse(const common::ObString &sql_string, } } if (add_semicolon) { - parse_sql_string.ptr()[sql_string.length() - 2] = '\0'; + parse_sql_string.ptr()[sql_string.length() - 2] = origin_byte; } } return ret; @@ -184,6 +186,16 @@ inline int ObProxyParser::parse(const common::ObString &sql_string, PROXY_LOG(WARN, "failed to initialized parser", KERRMSGS, K(ret)); } else { switch (connection_collation) { + //case 28/*CS_TYPE_GBK_CHINESE_CI*/: + //case 87/*CS_TYPE_GBK_BIN*/: + case 248/*CS_TYPE_GB18030_CHINESE_CI*/: + case 249/*CS_TYPE_GB18030_BIN*/: + if (common::OB_SUCCESS != obproxy_parse_gbk_sql(&parse_result, + sql_string.ptr(), + static_cast(sql_string.length()))) { + ret = common::OB_ERR_PARSE_SQL; + } + break; case 45/*CS_TYPE_UTF8MB4_GENERAL_CI*/: case 46/*CS_TYPE_UTF8MB4_BIN*/: default: diff --git a/src/obproxy/opsql/parser/ob_proxy_parser.l b/src/obproxy/opsql/parser/ob_proxy_parser.l index 008511631635520cfb4b78f9015f38c5d19208bc..ef1c29f7b618740139531a041bf8274e3bc18b53 100644 --- a/src/obproxy/opsql/parser/ob_proxy_parser.l +++ b/src/obproxy/opsql/parser/ob_proxy_parser.l @@ -269,17 +269,23 @@ do {\ %x prepare %x insert_all_expr %x set_expr +%x show_elastic_id %x show_topology +%x show_tables +%x proxy_icmd_state /*following character status will be rewrite by gen_parse.sh according to connection character*/ multi_byte_space [\u3000] multi_byte_comma [\uff0c] multi_byte_left_parenthesis [\uff08] multi_byte_right_parenthesis [\uff09] +multi_byte_connect_char /*According to connection character to set by gen_parse.sh*/ space [ \t\n\r\f] -identifer ([A-Za-z0-9$_]*) -int_num [\-\+]?[0-9]+ -number ([0-9]+E[-+]?[0-9]+)|([0-9]+"."[0-9]*E[-+]?[0-9]+)|("."[0-9]+E[-+]?[0-9]+)|([0-9]+"."[0-9]*)|("."[0-9]+) +identifer (([A-Za-z0-9$_#]|{multi_byte_connect_char})*) + +/* limit the length of int_num from 1 to 17 in case of int64_t out of bound, 17 -> [ ( length of 2^64 ) - 2 ]*/ +int_num [\-\+]?[0-9]{1,17} +number ([\-]?[0-9]+E[-+]?[0-9]+)|([\-]?[0-9]+"."[0-9]*E[-+]?[0-9]+)|([\-]?"."[0-9]+E[-+]?[0-9]+)|([\-]?[0-9]+"."[0-9]*)|([\-]?"."[0-9]+)|([\-\+]?[0-9]{18,}) comment_identifer [\-\+]?{identifer} odp_comment_identifer ([\-\+]?[A-Za-z0-9$_\-]*) @@ -298,7 +304,6 @@ c_cmt_end \*+\/ tx_read_only (@@session{space}*\.{space}*tx_read_only|@@tx_read_only) autocommit (@@session{space}*\.{space}*autocommit|@@autocommit|autocommit) -autocommit_0 ({autocommit}{space}*={space}*0) set_names (set{space}+names{space}+) set_charset (set{space}+charset{space}+|set{space}+character{space}+set{space}+) set_password (set{space}+password{space}+) @@ -350,8 +355,12 @@ show_proxytrace (show{space}+proxytrace) show_proxyinfo (show{space}+proxyinfo) show_databases (show{space}+databases) show_tables (show{space}+tables) +show_full_tables (show{space}+full{space}+tables) show_create_table (show{space}+create{space}+table) -show_topology (show{space}+elastic_id) +show_columns (show{space}+(full{space}+)?(columns|fields)) +show_index (show{space}+(index|indexes|keys)) +show_elastic_id (show{space}+elastic_id) +show_topology (show{space}+topology) show_db_version (show{space}+database_version) select_database (select{space}+database({leftbracket}|{multi_byte_left_parenthesis})({rightbracket}|{multi_byte_right_parenthesis})) alter_proxyconfig (alter{space}+proxyconfig) @@ -363,6 +372,15 @@ select_proxy_version (select{space}+proxy_version{space}*({leftbracket}|{m select_obproxy_route_addr (select{space}+@obproxy_route_addr) set_obproxy_route_addr (set{space}+@obproxy_route_addr) + +/* binlog relate SQL */ +show_master_status (show{space}+master{space}+status) +show_binary_logs (show{space}+binary{space}+logs) +show_binlog_events (show{space}+binlog{space}+events) +purge_binary_logs (purge{space}+binary{space}+logs) +reset_master (reset{space}+master) +show_binlog_server_for_tenant (show{space}+binlog{space}+server{space}+for{space}+tenant) + %% /* basic dml stmt: */ @@ -384,7 +402,7 @@ CALL { SET_BASIC_STMT(OBPROXY_T_CALL); return CALL; } DECLARE { SET_HAS_ANONYMOUS_BLOCK(); PUSH_STATE(in_anonymous_block); } WHEN { ObProxyParseResult *p = yyget_extra(yyscanner); if (OB_NOTNULL(p)) { - if (OBPROXY_T_INSERT == p->cur_stmt_type_) + if (OBPROXY_T_INSERT == p->cur_stmt_type_) PUSH_STATE(insert_all_expr); } return WHEN; } @@ -397,12 +415,16 @@ TRUNCATE { return TRUNCATE; } RENAME { return RENAME; } INDEX { return INDEX; } TABLE { return TABLE; } +STATUS { return STATUS; } +FROM { return FROM; } UNIQUE { return UNIQUE; } /* ps stmt */ USING { return USING; } PREPARE { PUSH_STATE(prepare); return PREPARE; } EXECUTE { return EXECUTE; } +DEALLOCATE { return DEALLOCATE; } + /* oracle ddl stmt */ GRANT { return GRANT; } @@ -435,7 +457,7 @@ ALL { return ALL; } LIKE { return LIKE; } PARTITION { return PARTITION; } BINARY { return BINARY; } -GROUP_NAME { return GROUP_NAME; } +GROUP_NAME { RETURN_NON_RESERVED_KEYWORD(GROUP_NAME); } /* to make bison easy, do not return these reserved keyword in non strict mode */ IGNORE { RETURN_IGNORED_WORD(); } @@ -491,10 +513,11 @@ VARIABLES { RETURN_NON_RESERVED_KEYWORD(VARIABLES); } STAT { RETURN_NON_RESERVED_KEYWORD(STAT); } /*show config*/ -{show_proxyconfig} { SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_CONFIG); return SHOW_PROXYCONFIG; } +{show_proxyconfig} { SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_CONFIG); PUSH_STATE(proxy_icmd_state); return SHOW_PROXYCONFIG; } -DIFF { RETURN_NON_RESERVED_KEYWORD(DIFF); } -USER { RETURN_NON_RESERVED_KEYWORD(USER); } +"DIFF" { RETURN_NON_RESERVED_KEYWORD(DIFF); } +"USER" { RETURN_NON_RESERVED_KEYWORD(USER); } +"LIKE" { POP_STATE(); return LIKE; } /*show sm*/ {show_proxysm} { SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_SM); return SHOW_PROXYSM; } @@ -538,17 +561,31 @@ REFRESH { RETURN_NON_RESERVED_KEYWORD(REFRESH); } UPGRADE { RETURN_NON_RESERVED_KEYWORD(UPGRADE); } IDC { RETURN_NON_RESERVED_KEYWORD(IDC); } -{show_topology} { SET_BASIC_STMT(OBPROXY_T_SHOW); PUSH_STATE(show_topology); return SHOW_TOPOLOGY; } -"FROM" { POP_STATE(); PUSH_STATE(INITIAL); return FROM; } -"WHERE" { POP_STATE(); PUSH_STATE(INITIAL); return WHERE; } -<> { return END_P; } -{whitespace} { } -; { POP_STATE(); PUSH_STATE(INITIAL); return yytext[0]; } -. { return ERROR; } +{show_elastic_id} { SET_BASIC_STMT(OBPROXY_T_SHOW); PUSH_STATE(show_elastic_id ); return SHOW_ELASTIC_ID; } +"FROM" { POP_STATE(); PUSH_STATE(INITIAL); return FROM; } +"WHERE" { POP_STATE(); PUSH_STATE(INITIAL); return WHERE; } +<> { return END_P; } +{whitespace} { } +; { POP_STATE(); PUSH_STATE(INITIAL); return yytext[0]; } +. { return ERROR; } + +{show_topology} { SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_TOPOLOGY; } {show_db_version} { SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_DB_VERSION; } {show_databases} { SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_DATABASES; } -{show_tables} { SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_TABLES; } + +{show_tables} { SET_BASIC_STMT(OBPROXY_T_SHOW); PUSH_STATE(show_tables); return SHOW_TABLES; } +{show_full_tables} { SET_BASIC_STMT(OBPROXY_T_SHOW); PUSH_STATE(show_tables); return SHOW_FULL_TABLES; } + +"FROM" { POP_STATE(); PUSH_STATE(INITIAL); return FROM; } +"LIKE" { POP_STATE(); PUSH_STATE(INITIAL); return LIKE; } +<> { return END_P; } +{whitespace} { } +; { POP_STATE(); PUSH_STATE(INITIAL); return yytext[0]; } +. { return ERROR; } +{show_columns} { SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_COLUMNS; } +{show_index} { SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_INDEX; } + {show_create_table} { SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_CREATE_TABLE; } {select_database} { SET_DML_STMT(OBPROXY_T_SELECT); return SELECT_DATABASE; } {select_proxy_version} { SET_DML_STMT(OBPROXY_T_SELECT_PROXY_VERSION); return SELECT_PROXY_VERSION; } @@ -624,7 +661,13 @@ LAST_INSERT_ID { SET_LAST_INSERT_ID(); RETURN_NON_RESERVED_KEYWORD(NAME_OB); } return MERGE_HINT_BEGIN; } -{autocommit_0} { return AUTOCOMMIT_0; } +{show_master_status} { SET_BASIC_STMT(OBPROXY_T_SHOW_MASTER_STATUS); return SHOW_MASTER_STATUS; } +{show_binary_logs} { SET_BASIC_STMT(OBPROXY_T_SHOW_BINARY_LOGS); return SHOW_BINARY_LOGS; } +{show_binlog_events} { SET_BASIC_STMT(OBPROXY_T_SHOW_BINLOG_EVENTS); return SHOW_BINLOG_EVENTS; } +{purge_binary_logs} { SET_BASIC_STMT(OBPROXY_T_PURGE_BINARY_LOGS); return PURGE_BINARY_LOGS; } +{reset_master} { SET_BASIC_STMT(OBPROXY_T_RESET_MASTER); return RESET_MASTER; } +{show_binlog_server_for_tenant} { SET_BASIC_STMT(OBPROXY_T_SHOW_BINLOG_SERVER_FOR_TENANT); return SHOW_BINLOG_SERVER_FOR_TENANT; } + "global" { return GLOBAL; } "session" { return SESSION; } {int_num} { RETURN_INT_NUM(); } @@ -779,6 +822,7 @@ LAST_INSERT_ID { SET_LAST_INSERT_ID(); RETURN_NON_RESERVED_KEYWORD(NAME_OB); } {space}*"trace_id" { PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(TRACE_ID); } {space}*{comment_identifer}"." { PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT_NAME_OB_DOT(NAME_OB_DOT); } {space}*"rpc_id" { PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(RPC_ID); } +{space}*"target_db_server" { PUSH_STATE(in_odp_comment_expr); return TARGET_DB_SERVER; } "group_id" { return GROUP_ID; } "table_id" { return TABLE_ID; } @@ -789,6 +833,7 @@ LAST_INSERT_ID { SET_LAST_INSERT_ID(); RETURN_NON_RESERVED_KEYWORD(NAME_OB); } "tnt_id" { return TNT_ID; } "trace_id" { return TRACE_ID; } "rpc_id" { return RPC_ID; } +"target_db_server" { return TARGET_DB_SERVER; } {sqbegin} { ENTER_QUOTE_STATE(comment_sq); } {comma}|{multi_byte_comma} { return ','; } {odp_comment_identifer} { RETURN_NON_RESERVED_KEYWORD(NAME_OB); } @@ -859,6 +904,7 @@ LAST_INSERT_ID { SET_LAST_INSERT_ID(); RETURN_NON_RESERVED_KEYWORD(NAME_OB); } "$ROUTE" { return ROUTE_TAG; } "$SYS" { return SYS_TAG; } "SCAN_ALL" { return SCAN_ALL; } +"STICKY_SESSION" { return STICKY_SESSION; } "SHARDING_KEY" { return SHARD_KEY; } "table_name" { return TABLE_NAME;} "parallelism" { return PARALL; } @@ -870,7 +916,7 @@ LAST_INSERT_ID { SET_LAST_INSERT_ID(); RETURN_NON_RESERVED_KEYWORD(NAME_OB); } {multi_byte_right_parenthesis} { return ')'; } {comma}|{multi_byte_comma} { return ','; } {space} { } -{comment_identifer} { RETURN_NON_RESERVED_KEYWORD(NAME_OB); } +{odp_comment_identifer} { RETURN_NON_RESERVED_KEYWORD(NAME_OB); } {c_cmt_end} { ObProxyParseResult *p = (ObProxyParseResult *)yyextra; @@ -973,7 +1019,8 @@ LAST_INSERT_ID { SET_LAST_INSERT_ID(); RETURN_NON_RESERVED_KEYWORD(NAME_OB); } && OBPROXY_T_INVALID < p->cur_stmt_type_ && (p->cur_stmt_type_ < OBPROXY_T_ICMD_MAX || OBPROXY_T_CALL == p->cur_stmt_type_ - || OBPROXY_T_SET == p->cur_stmt_type_) + || OBPROXY_T_SET == p->cur_stmt_type_ + || OBPROXY_T_SHOW == p->cur_stmt_type_) && OB_NOTNULL(p->tmp_buf_)) { store_str_with_quote(OBPROXY_QUOTE_T_SINGLE, p->tmp_buf_, p->tmp_len_, p->tmp_start_ptr_ + p->tmp_len_ + 2, yyscanner); return NAME_OB; @@ -1036,7 +1083,8 @@ LAST_INSERT_ID { SET_LAST_INSERT_ID(); RETURN_NON_RESERVED_KEYWORD(NAME_OB); } && OBPROXY_T_INVALID < p->cur_stmt_type_ && (p->cur_stmt_type_ < OBPROXY_T_ICMD_MAX || OBPROXY_T_CALL == p->cur_stmt_type_ - || OBPROXY_T_SET == p->cur_stmt_type_) + || OBPROXY_T_SET == p->cur_stmt_type_ + || OBPROXY_T_SHOW == p->cur_stmt_type_) && OB_NOTNULL(p->tmp_buf_)) { store_str_with_quote(OBPROXY_QUOTE_T_DOUBLE, p->tmp_buf_, p->tmp_len_, p->tmp_start_ptr_ + p->tmp_len_ + 2, yyscanner); return NAME_OB; @@ -1110,7 +1158,6 @@ LAST_INSERT_ID { SET_LAST_INSERT_ID(); RETURN_NON_RESERVED_KEYWORD(NAME_OB); } "last_insert_id" { SET_LAST_INSERT_ID(); RETURN_IGNORED_WORD(); } "global" { SET_GLOBAL_SET_STMT(); RETURN_IGNORED_WORD(); } {tx_read_only} { RETURN_COL_NAME(TX_READ_ONLY); } -{autocommit_0} { return AUTOCOMMIT_0; } {identifer} { RETURN_IGNORED_WORD(); } <> { return END_P; } {whitespace} { } @@ -1139,11 +1186,12 @@ LAST_INSERT_ID { SET_LAST_INSERT_ID(); RETURN_NON_RESERVED_KEYWORD(NAME_OB); } . { RETURN_IGNORED_WORD(); } "FROM" { return FROM; } +"@" { return yytext[0]; } {identifer} { RETURN_NON_RESERVED_KEYWORD(NAME_OB); } {dquote} { POP_STATE(); } {quote} { POP_STATE(); } -"BEGIN" { POP_STATE(); return BEGI;} +"BEGIN" { POP_STATE(); RETURN_NON_RESERVED_KEYWORD(BEGI);} . {} <> { return END_P; } diff --git a/src/obproxy/opsql/parser/ob_proxy_parser.y b/src/obproxy/opsql/parser/ob_proxy_parser.y index d3c63e32e9fd23af7df91634c198d92a6c1606d0..dbd0eda371de3393ecb5be0d5d36548c1a68781b 100644 --- a/src/obproxy/opsql/parser/ob_proxy_parser.y +++ b/src/obproxy/opsql/parser/ob_proxy_parser.y @@ -39,9 +39,6 @@ static inline void handle_stmt_end(ObProxyParseResult* result) case OBPROXY_T_SELECT_TX_RO: result->stmt_type_ = OBPROXY_T_SELECT; break; - case OBPROXY_T_SET_AC_0: - result->stmt_type_ = OBPROXY_T_OTHERS; - break; case OBPROXY_T_BEGIN: result->stmt_type_ = OBPROXY_T_OTHERS; break; @@ -60,7 +57,7 @@ static inline void handle_stmt_end(ObProxyParseResult* result) } } else { result->stmt_type_ = result->cur_stmt_type_; - } + } if (OBPROXY_T_TEXT_PS_PREPARE == result->text_ps_inner_stmt_type_) { ObProxyBasicStmtType tmp_type = result->cur_stmt_type_; @@ -189,24 +186,24 @@ do { } \ } while(0) \ -#define add_text_ps_execute_node(text_ps_execute_parse_info, execute_parse_node) \ +#define add_text_ps_node(text_ps_parse_info, parse_node) \ do { \ - if (NULL != text_ps_execute_parse_info.tail_) {\ - text_ps_execute_parse_info.tail_->next_ = execute_parse_node;\ - text_ps_execute_parse_info.tail_ = execute_parse_node;\ + if (NULL != text_ps_parse_info.tail_) {\ + text_ps_parse_info.tail_->next_ = parse_node;\ + text_ps_parse_info.tail_ = parse_node;\ } else {\ - text_ps_execute_parse_info.head_ = execute_parse_node;\ - text_ps_execute_parse_info.tail_ = execute_parse_node;\ + text_ps_parse_info.head_ = parse_node;\ + text_ps_parse_info.tail_ = parse_node;\ }\ - ++text_ps_execute_parse_info.node_count_;\ + ++text_ps_parse_info.node_count_;\ } while(0) -#define malloc_execute_parse_node(execute_parse_node) \ +#define malloc_parse_node(parse_node) \ do { \ - if (OB_ISNULL(execute_parse_node = ((ObProxyTextPsExecuteParseNode *)obproxy_parse_malloc(sizeof(ObProxyTextPsExecuteParseNode), result->malloc_pool_)))) { \ + if (OB_ISNULL(parse_node = ((ObProxyTextPsParseNode *)obproxy_parse_malloc(sizeof(ObProxyTextPsParseNode), result->malloc_pool_)))) { \ YYABORT; \ } else { \ - execute_parse_node->next_ = NULL; \ + parse_node->next_ = NULL; \ } \ } while(0) \ @@ -284,24 +281,24 @@ extern void *obproxy_parse_malloc(const size_t nbyte, void *malloc_pool); /* dummy token */ %token DUMMY_WHERE_CLAUSE DUMMY_INSERT_CLAUSE /* reserved keyword */ -%token SELECT DELETE INSERT UPDATE REPLACE MERGE SHOW SET CALL CREATE DROP ALTER TRUNCATE RENAME TABLE UNIQUE +%token SELECT DELETE INSERT UPDATE REPLACE MERGE SHOW SET CALL CREATE DROP ALTER TRUNCATE RENAME TABLE STATUS UNIQUE %token GRANT REVOKE ANALYZE PURGE COMMENT %token FROM DUAL -%token PREPARE EXECUTE USING +%token PREPARE EXECUTE USING DEALLOCATE %token SELECT_HINT_BEGIN UPDATE_HINT_BEGIN DELETE_HINT_BEGIN INSERT_HINT_BEGIN REPLACE_HINT_BEGIN MERGE_HINT_BEGIN HINT_END COMMENT_BEGIN COMMENT_END ROUTE_TABLE ROUTE_PART_KEY QUERY_TIMEOUT READ_CONSISTENCY WEAK STRONG FROZEN PLACE_HOLDER -%token END_P ERROR +%token END_P ERROR %token WHEN /* non-reserved keyword */ %token FLASHBACK AUDIT NOAUDIT %token BEGI START TRANSACTION READ ONLY WITH CONSISTENT SNAPSHOT INDEX XA %token WARNINGS ERRORS TRACE %token QUICK COUNT AS WHERE VALUES ORDER GROUP HAVING INTO UNION FOR -%token TX_READ_ONLY AUTOCOMMIT_0 SELECT_OBPROXY_ROUTE_ADDR SET_OBPROXY_ROUTE_ADDR +%token TX_READ_ONLY SELECT_OBPROXY_ROUTE_ADDR SET_OBPROXY_ROUTE_ADDR %token NAME_OB_DOT NAME_OB EXPLAIN DESC DESCRIBE NAME_STR %token USE HELP SET_NAMES SET_CHARSET SET_PASSWORD SET_DEFAULT SET_OB_READ_CONSISTENCY SET_TX_READ_ONLY GLOBAL SESSION %token NUMBER_VAL -%token GROUP_ID TABLE_ID ELASTIC_ID TESTLOAD ODP_COMMENT TNT_ID DISASTER_STATUS TRACE_ID RPC_ID -%token DBP_COMMENT ROUTE_TAG SYS_TAG TABLE_NAME SCAN_ALL PARALL SHARD_KEY +%token GROUP_ID TABLE_ID ELASTIC_ID TESTLOAD ODP_COMMENT TNT_ID DISASTER_STATUS TRACE_ID RPC_ID TARGET_DB_SERVER +%token DBP_COMMENT ROUTE_TAG SYS_TAG TABLE_NAME SCAN_ALL STICKY_SESSION PARALL SHARD_KEY %token INT_NUM %type right_string_val tracer_right_string_val name_right_string_val %type call_expr @@ -323,12 +320,13 @@ extern void *obproxy_parse_malloc(const size_t nbyte, void *malloc_pool); %token SHOW_PROXYSTAT REFRESH %token SHOW_PROXYTRACE %token SHOW_PROXYINFO BINARY UPGRADE IDC -%token SHOW_TOPOLOGY GROUP_NAME SHOW_DB_VERSION -%token SHOW_DATABASES SHOW_TABLES SELECT_DATABASE SHOW_CREATE_TABLE SELECT_PROXY_VERSION +%token SHOW_ELASTIC_ID SHOW_TOPOLOGY GROUP_NAME SHOW_DB_VERSION +%token SHOW_DATABASES SHOW_TABLES SHOW_FULL_TABLES SELECT_DATABASE SHOW_CREATE_TABLE SELECT_PROXY_VERSION SHOW_COLUMNS SHOW_INDEX %token ALTER_PROXYCONFIG %token ALTER_PROXYRESOURCE %token PING_PROXY %token KILL_PROXYSESSION KILL_GLOBALSESSION KILL QUERY +%token SHOW_MASTER_STATUS SHOW_BINARY_LOGS SHOW_BINLOG_EVENTS PURGE_BINARY_LOGS RESET_MASTER SHOW_BINLOG_SERVER_FOR_TENANT %type table_factor non_reserved_keyword var_name %start root @@ -339,12 +337,15 @@ root: sql_stmts { HANDLE_ACCEPT(); } sql_stmts: sql_stmt | sql_stmts sql_stmt -sql_stmt: stmt END_P { handle_stmt_end(result); HANDLE_ACCEPT(); } - | stmt ';' { handle_stmt_end(result); } - | stmt ';' END_P { handle_stmt_end(result); HANDLE_ACCEPT(); } +sql_stmt: comment_stmt END_P { handle_stmt_end(result); HANDLE_ACCEPT(); } + | comment_stmt ';' { handle_stmt_end(result); } + | comment_stmt ';' END_P { handle_stmt_end(result); HANDLE_ACCEPT(); } | ';' { handle_stmt_end(result); } | ';' END_P { handle_stmt_end(result); HANDLE_ACCEPT(); } - | BEGI stmt ';' { handle_stmt_end(result); } + | BEGI comment_stmt ';' { handle_stmt_end(result); } + +comment_stmt: stmt + | comment_expr_list stmt stmt: select_stmt {} | insert_stmt {} @@ -353,7 +354,6 @@ stmt: select_stmt {} | update_stmt {} | delete_stmt {} | explain_stmt {} - | comment_stmt {} | begin_stmt {} | show_stmt {} | hooked_stmt {} @@ -370,6 +370,7 @@ stmt: select_stmt {} | ddl_stmt {} | text_ps_stmt {} | merge_stmt {} + | binlog_stmt {} | other_stmt { result->cur_stmt_type_ = OBPROXY_T_OTHERS; } select_stmt: select_with_opt_hint select_expr_list opt_from @@ -381,13 +382,6 @@ explain_stmt: explain_or_desc_stmt select_stmt | explain_or_desc_stmt replace_stmt | explain_or_desc_stmt merge_stmt -comment_stmt: comment_expr_list select_stmt - | comment_expr_list insert_stmt - | comment_expr_list update_stmt - | comment_expr_list delete_stmt - | comment_expr_list replace_stmt - | comment_expr_list merge_stmt - ddl_stmt: mysql_ddl_stmt | oracle_ddl_stmt @@ -411,20 +405,32 @@ text_ps_from_stmt: select_stmt {} | call_stmt {} | merge_stmt {} -text_ps_using_var_list: '@' NAME_OB - { - ObProxyTextPsExecuteParseNode *node = NULL; - malloc_execute_parse_node(node); - node->str_value_ = $2; - add_text_ps_execute_node(result->text_ps_execute_parse_info_, node); - } - | text_ps_using_var_list ',' '@' NAME_OB - { - ObProxyTextPsExecuteParseNode *node = NULL; - malloc_execute_parse_node(node); - node->str_value_ = $4; - add_text_ps_execute_node(result->text_ps_execute_parse_info_, node); - } +text_ps_execute_using_var_list: '@' NAME_OB + { + ObProxyTextPsParseNode *node = NULL; + malloc_parse_node(node); + node->str_value_ = $2; + add_text_ps_node(result->text_ps_parse_info_, node); + } + | text_ps_execute_using_var_list ',' '@' NAME_OB + { + ObProxyTextPsParseNode *node = NULL; + malloc_parse_node(node); + node->str_value_ = $4; + add_text_ps_node(result->text_ps_parse_info_, node); + } + +text_ps_prepare_var_list: '@' NAME_OB + { + ObProxyTextPsParseNode *node = NULL; + malloc_parse_node(node); + node->str_value_ = $2; + add_text_ps_node(result->text_ps_parse_info_, node); + } + +text_ps_prepare_args_stmt : text_ps_prepare_var_list + | text_ps_from_stmt + text_ps_prepare_stmt: PREPARE var_name FROM { @@ -432,18 +438,32 @@ text_ps_prepare_stmt: PREPARE var_name FROM result->text_ps_name_ = $2; } -text_ps_stmt: text_ps_prepare_stmt text_ps_from_stmt +text_ps_execute_stmt: EXECUTE var_name + { + result->cur_stmt_type_ = OBPROXY_T_TEXT_PS_EXECUTE; + result->text_ps_name_ = $2; + } + | EXECUTE var_name USING + { + result->cur_stmt_type_ = OBPROXY_T_TEXT_PS_EXECUTE; + result->text_ps_name_ = $2; + } + +text_ps_stmt: text_ps_prepare_stmt text_ps_prepare_args_stmt + { + } + | text_ps_execute_stmt text_ps_execute_using_var_list { } - | EXECUTE var_name + | DROP PREPARE var_name { - result->cur_stmt_type_ = OBPROXY_T_TEXT_PS_EXECUTE; - result->text_ps_name_ = $2; + result->cur_stmt_type_ = OBPROXY_T_TEXT_PS_DROP; + result->text_ps_name_ = $3; } - | EXECUTE var_name USING text_ps_using_var_list + | DEALLOCATE PREPARE var_name { - result->cur_stmt_type_ = OBPROXY_T_TEXT_PS_EXECUTE; - result->text_ps_name_ = $2; + result->cur_stmt_type_ = OBPROXY_T_TEXT_PS_DROP; + result->text_ps_name_ = $3; } oracle_ddl_stmt: GRANT { result->cur_stmt_type_ = OBPROXY_T_GRANT; } @@ -475,45 +495,97 @@ select_tx_read_only_stmt: SELECT TX_READ_ONLY { result->cur_stmt_type_ = OBPROXY select_proxy_version_stmt: SELECT_PROXY_VERSION | SELECT_PROXY_VERSION AS var_name { result->col_name_ = $3; } -set_autocommit_0_stmt: SET AUTOCOMMIT_0 { result->cur_stmt_type_ = OBPROXY_T_SET_AC_0; } - | SET AUTOCOMMIT_0 expr_list - hooked_stmt: select_tx_read_only_stmt {} | select_proxy_version_stmt {} - | set_autocommit_0_stmt {} | select_obproxy_route_addr_stmt {} | set_obproxy_route_addr_stmt {} | shard_special_stmt {} shard_special_stmt: show_es_id_stmt {} + | show_topology_stmt {} | show_db_version_stmt {} | SELECT_DATABASE { result->sub_stmt_type_ = OBPROXY_T_SUB_SELECT_DATABASE; } | SHOW_DATABASES { result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_DATABASES; } - | SHOW_TABLES { result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TABLES; } + | show_tables_stmt {} + | show_table_status_stmt {} + | show_columns_stmt {} + | show_index_stmt {} | SHOW_CREATE_TABLE routine_name_stmt { result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_CREATE_TABLE; } - | explain_or_desc routine_name_stmt + | explain_or_desc var_name { + result->table_info_.table_name_ = $2; result->cur_stmt_type_ = OBPROXY_T_DESC; result->sub_stmt_type_ = OBPROXY_T_SUB_DESC_TABLE; } +show_columns_stmt: SHOW_COLUMNS FROM NAME_OB + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_COLUMNS; + result->table_info_.table_name_ = $3; + } + | SHOW_COLUMNS FROM NAME_OB FROM NAME_OB + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_COLUMNS; + result->table_info_.table_name_ = $3; + result->table_info_.database_name_ = $5; + } + +show_index_stmt: SHOW_INDEX FROM NAME_OB + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_INDEX; + result->table_info_.table_name_ = $3; + } + | SHOW_INDEX FROM NAME_OB FROM NAME_OB + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_INDEX; + result->table_info_.table_name_ = $3; + result->table_info_.database_name_ = $5; + } + +opt_show_like: /*empty*/ {} + | LIKE NAME_OB { result->table_info_.table_name_ = $2; } + +opt_show_from: /*empty*/ {} + | FROM NAME_OB { result->table_info_.database_name_ = $2; } + +show_tables_stmt: SHOW_TABLES opt_show_from opt_show_like + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TABLES; + } + | SHOW_FULL_TABLES opt_show_from opt_show_like + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_FULL_TABLES; + } + +show_table_status_stmt: SHOW TABLE STATUS opt_show_from opt_show_like + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TABLE_STATUS; + } + show_db_version_stmt: SHOW_DB_VERSION { result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_DB_VERSION; } -show_es_id_stmt: SHOW_TOPOLOGY { result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TOPOLOGY; } - | SHOW_TOPOLOGY FROM NAME_OB +show_es_id_stmt: SHOW_ELASTIC_ID { result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_ELASTIC_ID; } + | SHOW_ELASTIC_ID FROM NAME_OB { SET_ICMD_ONE_STRING($3); - result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TOPOLOGY; + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_ELASTIC_ID; } - | SHOW_TOPOLOGY WHERE GROUP_NAME '=' NAME_OB + | SHOW_ELASTIC_ID WHERE GROUP_NAME '=' NAME_OB { SET_ICMD_SECOND_STRING($5); - result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TOPOLOGY; + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_ELASTIC_ID; } - | SHOW_TOPOLOGY FROM NAME_OB WHERE GROUP_NAME '=' NAME_OB + | SHOW_ELASTIC_ID FROM NAME_OB WHERE GROUP_NAME '=' NAME_OB { SET_ICMD_ONE_STRING($3); SET_ICMD_SECOND_STRING($7); + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_ELASTIC_ID; + } + +show_topology_stmt: SHOW_TOPOLOGY { result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TOPOLOGY; } + | SHOW_TOPOLOGY FROM NAME_OB + { + result->table_info_.table_name_ = $3; result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TOPOLOGY; } @@ -703,7 +775,7 @@ comment_expr: COMMENT_BEGIN comment_list COMMENT_END {} | COMMENT_BEGIN DISASTER_STATUS '=' right_string_val odp_comment_list COMMENT_END { result->dbmesh_route_info_.disaster_status_str_ = $4; } | COMMENT_BEGIN DBP_COMMENT ROUTE_TAG '=' '{' dbp_comment_list '}' COMMENT_END {} | COMMENT_BEGIN DBP_COMMENT SYS_TAG '=' '{' dbp_sys_comment '}' COMMENT_END {} - + | COMMENT_BEGIN TARGET_DB_SERVER '=' right_string_val odp_comment_list COMMENT_END { result->target_db_server_ = $4; } comment_list: /* empty */ {} | comment_list comment @@ -726,6 +798,7 @@ dbp_comment: GROUP_ID '(' right_string_val ')' } | SCAN_ALL '(' ')' { result->dbp_route_info_.scan_all_ = true; } | SCAN_ALL '(' PARALL '=' right_string_val ')' { result->dbp_route_info_.scan_all_ = true; } + | STICKY_SESSION '(' ')' { result->dbp_route_info_.sticky_session_ = true; } | SHARD_KEY '(' dbp_kv_comment_list ')' {result->dbp_route_info_.has_shard_key_ = true;} dbp_sys_comment: TRACE '(' tracer_right_string_val')' { result->trace_id_ = $3; } @@ -754,6 +827,7 @@ odp_comment: GROUP_ID '=' right_string_val { result->dbmesh_route_info_.group_ | RPC_ID '=' tracer_right_string_val { result->rpc_id_ = $3; } | TNT_ID '=' right_string_val { result->dbmesh_route_info_.tnt_id_str_ = $3; } | DISASTER_STATUS '=' right_string_val { result->dbmesh_route_info_.disaster_status_str_ = $3; } + | TARGET_DB_SERVER '=' right_string_val { result->target_db_server_ = $3; } | NAME_OB '.' NAME_OB '=' name_right_string_val { malloc_shard_column_node($$, $1, $3, DBMESH_TOKEN_STR_VAL); @@ -780,10 +854,10 @@ delete_with_opt_hint: DELETE insert_with_opt_hint: INSERT insert_all_when | INSERT_HINT_BEGIN hint_list_with_end insert_all_when -insert_all_when: +insert_all_when: | ALL | ALL WHEN - + replace_with_opt_hint: REPLACE | REPLACE_HINT_BEGIN hint_list_with_end merge_with_opt_hint: MERGE @@ -843,6 +917,13 @@ icmd_stmt: show_proxynet | kill_globalsession | kill_mysql +binlog_stmt: SHOW_MASTER_STATUS {} + | SHOW_BINARY_LOGS {} + | SHOW_BINLOG_EVENTS {} + | PURGE_BINARY_LOGS {} + | RESET_MASTER {} + | SHOW_BINLOG_SERVER_FOR_TENANT {} + /* limit param stmt*/ opt_limit: /*empty*/ @@ -1104,24 +1185,7 @@ non_reserved_keyword: START | UPGRADE | IDC | QUERY - | GROUP_ID - | TABLE_ID - | ELASTIC_ID - | TESTLOAD | GROUP_NAME - | ODP_COMMENT - | TNT_ID - | DISASTER_STATUS - | TRACE_ID - | RPC_ID - | DBP_COMMENT - | ROUTE_TAG - | SYS_TAG - | TABLE_NAME - | PARALL - | SCAN_ALL - | SHARD_KEY - | INDEX | FLASHBACK | AUDIT | NOAUDIT diff --git a/src/obproxy/opsql/parser/ob_proxy_parser_gbk_lex.c b/src/obproxy/opsql/parser/ob_proxy_parser_gbk_lex.c new file mode 100644 index 0000000000000000000000000000000000000000..6e7ce96ca1371e13d6edfdb042beffc59bed29e5 --- /dev/null +++ b/src/obproxy/opsql/parser/ob_proxy_parser_gbk_lex.c @@ -0,0 +1,9140 @@ +#line 2 "ob_proxy_parser_gbk_lex.c" + +#line 4 "ob_proxy_parser_gbk_lex.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yyg->yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yyg->yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE ob_proxy_parser_gbk_yyrestart(yyin ,yyscanner ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = yyg->yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via ob_proxy_parser_gbk_yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ + ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] + +void ob_proxy_parser_gbk_yyrestart (FILE *input_file ,yyscan_t yyscanner ); +void ob_proxy_parser_gbk_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +YY_BUFFER_STATE ob_proxy_parser_gbk_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); +void ob_proxy_parser_gbk_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void ob_proxy_parser_gbk_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void ob_proxy_parser_gbk_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +void ob_proxy_parser_gbk_yypop_buffer_state (yyscan_t yyscanner ); + +static void ob_proxy_parser_gbk_yyensure_buffer_stack (yyscan_t yyscanner ); +static void ob_proxy_parser_gbk_yy_load_buffer_state (yyscan_t yyscanner ); +static void ob_proxy_parser_gbk_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); + +#define YY_FLUSH_BUFFER ob_proxy_parser_gbk_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner) + +YY_BUFFER_STATE ob_proxy_parser_gbk_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); +YY_BUFFER_STATE ob_proxy_parser_gbk_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +YY_BUFFER_STATE ob_proxy_parser_gbk_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); + +void *ob_proxy_parser_gbk_yyalloc (yy_size_t ,yyscan_t yyscanner ); +void *ob_proxy_parser_gbk_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); +void ob_proxy_parser_gbk_yyfree (void * ,yyscan_t yyscanner ); + +#define yy_new_buffer ob_proxy_parser_gbk_yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + ob_proxy_parser_gbk_yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + ob_proxy_parser_gbk_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + ob_proxy_parser_gbk_yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + ob_proxy_parser_gbk_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define ob_proxy_parser_gbk_yywrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +typedef int yy_state_type; + +#define yytext_ptr yytext_r + +static yy_state_type yy_get_previous_state (yyscan_t yyscanner ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner); +static int yy_get_next_buffer (yyscan_t yyscanner ); +static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yyg->yytext_ptr = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + yyg->yy_hold_char = *yy_cp; \ + yyg->yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 344 +#define YY_END_OF_BUFFER 345 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[2515] = + { 0, + 147, 147, 195, 195, 0, 0, 0, 0, 208, 208, + 238, 238, 0, 0, 0, 0, 0, 0, 267, 267, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 315, 315, 0, 0, + 0, 0, 333, 333, 338, 338, 0, 0, 174, 174, + 0, 0, 0, 0, 0, 0, 0, 0, 345, 343, + 157, 157, 153, 291, 147, 147, 280, 154, 153, 145, + 343, 153, 153, 146, 152, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 297, 343, + + 343, 343, 343, 343, 343, 197, 344, 195, 194, 197, + 197, 188, 195, 195, 195, 195, 195, 195, 197, 197, + 197, 197, 197, 197, 201, 200, 201, 203, 203, 344, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 213, 213, + 208, 213, 213, 208, 208, 213, 213, 213, 213, 213, + 213, 213, 242, 241, 241, 238, 236, 242, 238, 237, + 238, 240, 239, 238, 238, 238, 238, 238, 242, 242, + 248, 247, 247, 244, 248, 245, 248, 248, 250, 249, + 249, 249, 250, 250, 250, 269, 266, 266, 267, 261, + + 262, 269, 267, 265, 267, 267, 267, 267, 267, 267, + 269, 269, 271, 270, 344, 344, 277, 276, 276, 274, + 272, 273, 277, 277, 277, 279, 278, 278, 278, 279, + 279, 279, 286, 287, 344, 281, 282, 344, 292, 293, + 344, 299, 300, 302, 303, 318, 316, 316, 307, 315, + 315, 308, 306, 318, 317, 318, 315, 315, 315, 315, + 309, 318, 318, 318, 318, 318, 318, 342, 342, 325, + 324, 324, 322, 324, 323, 320, 321, 325, 325, 325, + 325, 335, 334, 334, 328, 333, 333, 329, 326, 327, + 335, 333, 333, 333, 335, 335, 335, 335, 335, 335, + + 339, 338, 340, 337, 338, 344, 344, 344, 344, 344, + 344, 184, 184, 182, 176, 176, 180, 174, 174, 179, + 182, 173, 182, 182, 172, 178, 177, 174, 174, 181, + 182, 182, 182, 182, 182, 182, 117, 115, 115, 115, + 117, 116, 117, 117, 117, 127, 125, 125, 125, 127, + 126, 127, 127, 127, 344, 344, 344, 157, 0, 149, + 0, 0, 0, 0, 0, 0, 0, 157, 147, 157, + 157, 157, 157, 157, 157, 147, 0, 0, 0, 0, + 0, 0, 0, 148, 0, 0, 0, 0, 0, 0, + 146, 0, 0, 146, 151, 198, 151, 146, 147, 147, + + 147, 44, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 8, 0, 150, 0, 0, 0, + 0, 0, 0, 0, 147, 155, 156, 145, 195, 0, + 0, 0, 0, 0, 0, 0, 196, 188, 188, 195, + 195, 195, 195, 195, 195, 0, 195, 185, 186, 0, + 199, 0, 0, 0, 223, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 210, 0, 0, 0, 0, 0, 0, + 0, 208, 0, 0, 0, 0, 0, 0, 0, 209, + 0, 0, 0, 0, 0, 0, 0, 212, 208, 208, + 0, 211, 0, 0, 0, 0, 0, 0, 0, 208, + 238, 0, 243, 238, 238, 238, 238, 238, 238, 238, + 238, 241, 237, 0, 246, 247, 245, 0, 249, 249, + 267, 267, 267, 0, 268, 267, 267, 267, 267, 267, + 267, 267, 266, 263, 264, 265, 271, 270, 0, 275, + + 276, 273, 0, 278, 278, 286, 0, 0, 288, 0, + 0, 289, 281, 0, 0, 283, 0, 0, 284, 0, + 294, 0, 0, 0, 295, 299, 298, 302, 301, 316, + 0, 316, 315, 316, 316, 316, 316, 316, 316, 315, + 0, 0, 0, 0, 0, 0, 0, 0, 315, 315, + 315, 315, 315, 0, 315, 306, 0, 324, 0, 324, + 0, 0, 320, 321, 334, 0, 334, 333, 334, 334, + 334, 334, 334, 334, 333, 0, 0, 0, 0, 0, + 0, 0, 333, 333, 333, 0, 333, 326, 327, 338, + 0, 0, 0, 0, 0, 0, 338, 0, 338, 0, + + 176, 0, 176, 174, 176, 176, 176, 176, 176, 176, + 174, 0, 0, 0, 0, 0, 0, 172, 0, 0, + 172, 175, 175, 172, 174, 174, 174, 0, 174, 173, + 115, 0, 115, 0, 0, 0, 125, 0, 125, 0, + 0, 0, 0, 0, 0, 0, 0, 157, 147, 0, + 0, 146, 157, 0, 146, 0, 0, 151, 0, 146, + 0, 147, 55, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 42, 147, 147, 147, 147, 147, 147, + 147, 111, 147, 147, 147, 147, 147, 147, 147, 147, + + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 13, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 53, 147, 147, 147, 147, 147, + 147, 0, 0, 0, 188, 188, 195, 195, 195, 195, + 195, 195, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 208, 208, 0, 0, 0, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 267, 267, 267, 267, 267, 267, + 267, 267, 267, 290, 0, 290, 0, 285, 0, 285, + + 0, 296, 0, 296, 0, 316, 315, 316, 0, 0, + 0, 315, 315, 315, 315, 315, 0, 0, 324, 0, + 0, 334, 333, 334, 0, 333, 333, 333, 0, 338, + 0, 0, 176, 174, 172, 176, 0, 172, 0, 0, + 175, 0, 172, 0, 174, 174, 174, 0, 115, 0, + 0, 0, 125, 0, 0, 0, 0, 0, 0, 0, + 157, 0, 146, 157, 157, 157, 146, 151, 0, 151, + 0, 151, 146, 147, 147, 147, 147, 147, 147, 14, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 49, + 18, 147, 147, 147, 147, 147, 25, 147, 147, 147, + + 74, 147, 147, 147, 147, 61, 138, 147, 56, 147, + 147, 147, 147, 147, 147, 71, 147, 147, 147, 147, + 147, 147, 147, 51, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 0, 0, 7, 147, 147, 90, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 16, 147, 52, 0, 188, 188, 195, 195, + 195, 195, 195, 190, 0, 0, 0, 0, 214, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 208, 208, + 0, 238, 238, 238, 238, 238, 238, 238, 238, 238, + 267, 253, 267, 267, 267, 267, 267, 267, 267, 0, + + 0, 0, 0, 0, 0, 316, 316, 316, 316, 0, + 0, 315, 305, 315, 315, 315, 0, 324, 324, 324, + 0, 334, 334, 334, 334, 333, 333, 333, 336, 183, + 176, 172, 176, 176, 176, 172, 175, 0, 175, 0, + 175, 172, 174, 174, 115, 115, 115, 113, 0, 125, + 125, 125, 123, 124, 92, 94, 93, 146, 146, 146, + 19, 147, 147, 37, 9, 147, 147, 147, 147, 147, + 66, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 31, 39, 147, 147, 147, 22, 147, 0, + 0, 147, 54, 147, 6, 147, 147, 147, 41, 147, + + 0, 0, 147, 34, 139, 65, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 147, 10, 147, 23, 147, + 69, 147, 147, 43, 147, 147, 147, 27, 47, 147, + 147, 45, 188, 188, 195, 193, 195, 195, 195, 251, + 0, 0, 0, 0, 0, 204, 0, 0, 0, 0, + 208, 206, 238, 238, 238, 238, 238, 238, 238, 238, + 238, 267, 267, 267, 267, 267, 267, 267, 260, 0, + 0, 290, 0, 0, 0, 285, 0, 0, 0, 296, + 0, 0, 0, 315, 0, 315, 0, 0, 315, 315, + + 315, 341, 0, 333, 333, 333, 172, 172, 172, 174, + 174, 114, 146, 146, 146, 0, 0, 147, 147, 58, + 147, 11, 147, 147, 17, 147, 147, 147, 2, 147, + 68, 147, 147, 147, 147, 147, 40, 147, 60, 3, + 0, 0, 0, 147, 147, 0, 0, 0, 147, 147, + 84, 147, 0, 0, 147, 0, 0, 147, 21, 147, + 0, 0, 32, 147, 147, 147, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, + 24, 82, 147, 147, 26, 4, 147, 46, 147, 147, + + 188, 188, 192, 195, 195, 191, 0, 0, 0, 0, + 224, 0, 0, 0, 221, 0, 208, 238, 238, 238, + 234, 238, 238, 238, 232, 238, 252, 267, 267, 267, + 267, 267, 267, 0, 0, 315, 0, 0, 0, 0, + 0, 315, 315, 0, 315, 0, 0, 0, 0, 0, + 0, 0, 313, 315, 315, 319, 333, 333, 333, 172, + 172, 172, 170, 174, 146, 146, 146, 0, 0, 33, + 147, 35, 147, 147, 147, 15, 63, 0, 0, 0, + 147, 29, 48, 147, 147, 147, 147, 0, 0, 0, + 0, 0, 147, 147, 0, 0, 38, 103, 147, 0, + + 28, 0, 0, 107, 5, 0, 0, 147, 100, 147, + 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, 147, + 147, 147, 0, 0, 0, 110, 147, 147, 188, 188, + 195, 195, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 208, 238, 238, 238, 238, 238, 238, 238, 238, + 267, 267, 267, 267, 267, 267, 0, 0, 315, 0, + 0, 0, 0, 0, 315, 0, 315, 0, 315, 315, + 315, 0, 0, 315, 315, 333, 333, 333, 172, 172, + + 172, 171, 146, 146, 146, 0, 147, 147, 147, 147, + 0, 0, 50, 147, 147, 147, 147, 0, 0, 0, + 0, 147, 147, 0, 0, 163, 147, 0, 0, 0, + 0, 0, 0, 12, 147, 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, 73, 147, 20, 0, + 0, 147, 67, 188, 188, 195, 195, 0, 0, 215, + 205, 216, 0, 0, 219, 222, 207, 238, 238, 226, + 227, 238, 238, 230, 233, 259, 267, 254, 267, 267, + + 267, 0, 0, 315, 0, 0, 0, 0, 0, 315, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 315, + 315, 333, 333, 333, 172, 172, 172, 146, 146, 146, + 0, 88, 147, 147, 147, 0, 0, 160, 36, 147, + 147, 147, 0, 0, 161, 0, 0, 147, 147, 0, + 0, 0, 0, 57, 0, 0, 0, 0, 0, 143, + 0, 0, 0, 0, 0, 158, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 129, 0, 0, + 0, 0, 0, 0, 0, 147, 0, 0, 159, 89, + + 188, 188, 195, 195, 0, 0, 0, 0, 238, 238, + 238, 238, 267, 267, 267, 267, 0, 0, 315, 0, + 304, 0, 0, 0, 0, 0, 0, 0, 304, 0, + 0, 0, 0, 0, 0, 0, 315, 311, 333, 333, + 331, 172, 172, 172, 146, 146, 146, 0, 83, 72, + 30, 0, 0, 0, 0, 142, 59, 147, 0, 0, + 0, 0, 0, 0, 147, 147, 0, 0, 0, 135, + 0, 0, 0, 162, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 129, 0, 0, 0, 0, 0, + 0, 0, 147, 0, 0, 0, 0, 188, 188, 195, + 195, 0, 218, 217, 0, 238, 229, 228, 238, 267, + 267, 267, 257, 0, 0, 0, 0, 310, 304, 0, + 0, 0, 0, 0, 0, 0, 0, 315, 330, 333, + 172, 172, 172, 146, 146, 146, 0, 0, 0, 0, + 147, 0, 0, 0, 0, 0, 147, 147, 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, 128, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 121, 0, 0, 70, 0, 0, + 0, 188, 188, 195, 195, 0, 0, 238, 238, 258, + 267, 267, 0, 0, 0, 0, 0, 304, 315, 333, + 172, 172, 172, 146, 146, 146, 0, 0, 0, 147, + 0, 0, 0, 147, 62, 0, 0, 0, 0, 0, + 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 76, 0, 78, 0, 0, 0, 0, 0, 0, 0, + 0, 128, 0, 0, 0, 0, 0, 0, 129, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 95, 0, 0, 0, 0, 0, 105, 0, 188, 188, + 195, 195, 0, 0, 238, 238, 256, 267, 0, 0, + 304, 315, 333, 172, 172, 172, 146, 146, 146, 0, + 0, 0, 64, 0, 0, 0, 147, 163, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, + 0, 0, 0, 0, 0, 101, 104, 118, 0, 188, + 188, 187, 195, 0, 0, 238, 238, 267, 0, 0, + 315, 333, 172, 172, 172, 146, 146, 146, 0, 0, + + 160, 0, 161, 0, 0, 0, 144, 0, 0, 0, + 0, 0, 158, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 120, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 109, 0, + 0, 0, 0, 106, 0, 159, 0, 188, 188, 195, + 0, 0, 238, 238, 255, 0, 314, 312, 332, 172, + 172, 172, 146, 146, 146, 0, 0, 0, 0, 0, + 162, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 99, 0, 108, 188, 188, 195, 220, 0, 231, 238, + 0, 172, 172, 172, 146, 146, 146, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 80, 165, 0, 0, 0, 0, 122, + 0, 0, 87, 0, 91, 0, 102, 0, 0, 188, + 188, 189, 225, 235, 0, 172, 172, 172, 146, 146, + 146, 133, 0, 0, 136, 167, 0, 131, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, + 0, 130, 0, 0, 0, 96, 0, 0, 86, 188, + 188, 0, 172, 172, 172, 146, 146, 147, 0, 137, + + 0, 0, 0, 0, 0, 80, 0, 76, 0, 0, + 166, 0, 0, 85, 164, 0, 97, 188, 0, 172, + 172, 174, 151, 151, 147, 134, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 175, 175, + 174, 151, 151, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 98, 0, 175, 175, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 119, 0, 0, + 132, 0, 0, 0, 0, 0, 0, 0, 314, 0, + 0, 0, 0, 141, 79, 0, 0, 0, 0, 0, + 0, 79, 0, 0, 0, 79, 0, 0, 0, 140, + + 0, 80, 0, 0, 0, 0, 0, 0, 169, 0, + 0, 0, 79, 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 2, 4, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 5, 6, 7, 8, 5, 5, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 19, 20, 1, + 21, 1, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 50, 52, 53, 54, 55, 56, 57, 58, + + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 52, 81, 52, 50, 50, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 83, 84, 85, 86, 86, 86, 86, 87, 88, 89, + 89, 90, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 1 + } ; + +static yyconst flex_int32_t yy_meta[93] = + { 0, + 1, 2, 3, 3, 1, 4, 5, 6, 7, 1, + 1, 1, 2, 1, 8, 9, 1, 10, 11, 1, + 1, 1, 12, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 12, + 13, 12, 10, 14, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 12, 15, 15, 15, 15, 15, 16, 17, 15, 18, + 15, 15 + + } ; + +static yyconst flex_int16_t yy_base[2700] = + { 0, + 0, 0, 92, 0, 182, 183, 195, 0, 287, 0, + 379, 0, 470, 474, 487, 491, 0, 0, 576, 0, + 667, 670, 679, 690, 701, 712, 466, 471, 472, 476, + 481, 486, 4126, 4121, 4118, 4099, 797, 0, 494, 495, + 888, 902, 987, 0, 1079, 0, 499, 501, 1171, 0, + 1262, 1269, 0, 0, 1290, 1297, 481, 486, 4152,15625, + 898, 1276,15625, 1300, 1392, 643, 1334,15625, 4133,15625, + 172, 4121, 4126, 1469,15625, 1546, 508, 898, 720, 905, + 1295, 1429, 913, 1432, 726, 1478, 721, 1504, 1550, 1583, + 1554, 1508, 1616, 1621, 1632, 1412, 1679, 1413, 1631, 1681, + + 1721, 1729, 669, 1738, 4092,15625,15625, 1738,15625, 494, + 4091, 1749, 1770, 1781, 1799, 1816, 1835, 1851, 1937, 1943, + 1949, 658, 1955, 4077,15625,15625, 495,15625, 2035, 2126, + 2217, 497, 483, 0,15625, 483, 483, 488, 507, 511, + 499, 910, 2308, 4011, 0, 4075, 0, 4074,15625, 1998, + 2088, 2152, 531, 2167, 2205, 2191, 1961, 2050, 2320, 4071, + 2326, 4069,15625,15625,15625, 0,15625, 546, 0,15625, + 0,15625,15625, 510, 640, 637, 650, 1279, 4003, 3995, + 15625,15625,15625,15625, 667,15625, 4001, 3992,15625,15625, + 15625,15625, 683, 3998, 3915,15625,15625,15625, 699,15625, + + 15625, 748, 0,15625, 0, 0, 702, 723, 1734, 894, + 3856, 679,15625,15625, 3852, 3846,15625,15625,15625,15625, + 15625,15625, 751, 3844, 3837,15625,15625,15625,15625, 764, + 3840, 104, 0, 1510, 0, 0, 2025, 0,15625, 2142, + 0, 0, 3868, 0, 3860,15625, 1283, 1366,15625, 2407, + 2179,15625,15625, 3898,15625, 3889, 2462, 1420, 1303, 855, + 15625, 2333, 2387, 2424, 700, 2459, 3892,15625, 723,15625, + 1461, 1501,15625, 0,15625,15625,15625, 3862, 891, 3787, + 703,15625, 1722, 1797,15625, 2554, 2432,15625,15625,15625, + 3852, 2503, 2572, 2583, 2669, 2675, 2681, 892, 2687, 3848, + + 15625, 2527,15625,15625, 2687, 2737, 2774, 2786, 3844, 2792, + 3841,15625, 888,15625, 1810, 1813,15625, 2873, 2815,15625, + 3812,15625, 778, 3809, 2950,15625,15625, 2302, 1337,15625, + 2799, 2858, 2922, 680, 2929, 3808,15625, 1909, 1927, 0, + 3803,15625, 887, 901, 3734,15625, 1950, 1972, 0, 3800, + 15625, 902, 923, 3731, 1251, 1258, 1267, 1978, 3729,15625, + 2905, 2993, 2999, 3006, 3789, 3055, 3783, 0, 3136, 3228, + 3710, 0, 3250, 0, 3774, 3006, 3063, 3111, 3117, 3739, + 3266, 3736, 3090,15625, 3272, 3278, 3291, 3732, 3326, 3730, + 3726, 2067, 3694, 1576, 1480,15625, 1481, 3392, 1735, 3330, + + 2036, 1649, 2428, 2165, 1748, 2007, 2768, 2329, 1931, 3367, + 2684, 2910, 3084, 2805, 3346, 3385, 3401, 3260, 3427, 2724, + 2427, 2916, 3430, 3431, 3297, 3478, 2690, 3482, 3339, 3483, + 2374, 3489, 3173, 3497, 3502, 3049, 3503, 3518, 3566, 3558, + 3571, 3550, 3594, 3622, 3636, 3639, 3642, 3647, 3655, 3656, + 3702, 3705, 3353, 3706, 3710, 3699,15625, 3744, 3748, 3752, + 3684, 3798, 3678, 3120, 3713,15625,15625,15625, 3752, 3801, + 3838, 3850, 3673, 3857, 3671, 771,15625, 3630, 3858, 3882, + 3870, 3904, 3951, 3935, 3973, 3962, 3984,15625,15625, 903, + 15625, 4075, 4166, 0,15625, 1286, 1296, 1307, 1411, 1468, + + 2127, 4257, 3560, 0, 3623, 0, 3611, 3532, 1258,15625, + 1493, 1492, 1521, 1531, 1532, 1544, 1560, 1600, 1553, 1554, + 1599, 4037, 0,15625, 4101, 4090, 4188, 4270, 3589, 4276, + 3561, 4130, 4282, 4294, 4332, 3555, 4346, 3554, 4141,15625, + 4353, 4371, 4408, 3547, 4421, 3533, 1325,15625, 4394, 4408, + 4433,15625, 4519, 4522, 4525, 3517, 4528, 3511, 4421, 4470, + 0, 1359,15625, 1588, 1609, 1613, 1637, 1671, 1628, 1666, + 1730,15625,15625, 1383,15625,15625,15625, 1415,15625,15625, + 0, 1717, 1797, 1421,15625, 1808, 1856, 1891, 1941, 1939, + 1952, 1959,15625,15625,15625,15625,15625,15625, 1422,15625, + + 15625,15625, 1439,15625,15625, 0, 2460, 3500,15625, 3493, + 3409,15625, 0, 2524, 3482,15625, 3472, 3402,15625, 2201, + 15625, 3462, 3438, 3369,15625, 0,15625, 0,15625, 2111, + 3367, 0, 4609, 4701, 3358, 0, 4723, 0, 3417, 4499, + 4589, 4739, 4745, 3409, 4751, 3398, 2396, 1943, 4589, 4566, + 4754, 4774, 4802, 4693, 4785,15625, 1992, 2446, 3331, 0, + 2595, 2006,15625,15625, 2598, 3309, 0, 4894, 4986, 3305, + 0, 5008, 0, 3368, 4836, 4801, 5024, 5030, 3361, 5036, + 3357, 2620, 4868, 5037, 5053, 4847, 4879,15625,15625, 4978, + 5139, 5145, 5151, 3348, 5157, 3342, 5160, 5171, 5182, 2003, + + 2626, 3271, 0, 5274, 5366, 3267, 0, 5388, 0, 3313, + 5216, 5404, 5410, 5416, 3309, 5429, 3294, 3293, 2630, 3292, + 3795, 2088, 2304, 5495, 3856, 3865, 4390, 5227, 3804,15625, + 2647, 3224, 0, 2682, 2029, 2051, 2712, 3221, 0, 2859, + 2065, 2078, 2103, 2101, 2130, 5247, 5442, 5258, 5587, 5416, + 5454, 3285, 2866, 3219, 3878, 1769, 1780, 2689, 2213, 5664, + 3279, 5474, 5531, 5741, 2320, 2773, 2476, 2887, 2943, 2993, + 2780, 3369, 3512, 3406, 3044, 3436, 3408, 2426, 3494, 3631, + 3138, 3532, 2308, 2131, 3564, 2987, 3619, 3057, 3500, 3557, + 3569, 2258, 3666, 2270, 2347, 3704, 3585, 3955, 2453, 3677, + + 2479, 3155, 3340, 3859, 3634, 3699, 2478, 3956, 3247, 4073, + 3949, 3819, 3952, 3499, 3858, 3957, 4071, 2502, 3857, 4175, + 4072, 2752, 2620, 4264, 3751, 4259, 5030, 4307, 2652, 4383, + 4331, 5145, 4149, 4076, 2813, 4382, 4297, 4146, 5151, 5622, + 4536, 5542, 5613, 3276, 3275, 5624, 5642, 5707, 5695, 5761, + 5772, 5800, 3274, 5877, 5954, 3958, 4413, 3684, 4369, 2867, + 4732, 4255, 5157, 3160, 4412, 3273, 5784, 5812, 5823, 5908, + 5897, 5937, 5836, 5976, 3265, 2893, 2935, 3095, 3229, 3286, + 3321, 3357, 3201, 3412, 3508, 3626, 3701, 3881, 3964, 4039, + 4150, 4208, 4280,15625, 3244, 3190, 4000,15625, 3187, 3184, + + 4152,15625, 3154, 3127, 4198, 5847, 6068, 4643, 3048, 4315, + 4323, 5965, 6050, 6087, 6118, 6018, 3112, 4382, 4665, 3045, + 4442, 5866, 6210, 4681, 3044, 6160, 6191, 6231, 3108, 6267, + 3104, 4496, 6098, 6359, 3103, 4747, 3037, 5018, 2565, 2566, + 4776, 2748, 6436, 3093, 6253, 6513, 5058, 3086, 5089, 3001, + 4527, 4527, 5130, 3000, 4577, 4606, 4726, 4772, 4777, 3058, + 3057, 3051, 3050, 0, 5147, 2983, 5166, 3046, 3037, 3030, + 3013, 3012, 6590, 6667, 5372, 5621, 5279, 5378, 4809, 4900, + 6355, 5044, 6345, 5280, 5397, 5120, 5402, 5564, 5443, 4901, + 5115, 5165, 5477, 5611, 6353, 6072, 5373, 5479, 5615, 5700, + + 5400, 5424, 5401, 5698, 5447, 5614, 6387, 5763, 5616, 5699, + 5766, 6213, 6358, 5768, 6360, 5617, 5702, 6361, 6419, 6073, + 6425, 6357, 6366, 5703, 6427, 6057, 6215, 5901, 6422, 6090, + 6363, 6431, 6432, 6758, 6493, 6474, 5904, 6051, 5767, 6433, + 6438, 6489, 6054, 6441, 6126, 5960, 6194, 6508, 6501, 6509, + 6510, 6547, 5902, 6511, 6075, 3009, 3008, 6538, 6550, 6568, + 6613, 6631, 6761, 6642, 6721, 6838, 6122, 6216,15625, 6511, + 6433, 6512, 6513, 6700, 6704, 6589, 3007, 3002, 6777, 6811, + 3001, 6126, 6193, 6218, 6227, 6303, 6304, 6331, 6371, 6378, + 6438, 0, 6444, 6500, 2965, 6509, 6524, 6531, 6532, 5565, + + 2921, 6661, 2903, 6610, 2902, 2952, 0, 5568, 2860, 6665, + 2882, 6849, 6940, 6950, 6772, 6956, 6673, 0, 6664, 2850, + 6686, 2913, 0, 6685, 2838, 6958, 6908, 6977, 6799,15625, + 2900, 2898, 0, 6788, 2831, 6890, 2895, 2859, 2853, 2841, + 2840, 7054, 7131, 6739, 0, 6831, 2773,15625, 6741, 0, + 6834, 2771,15625,15625,15625,15625,15625, 2834, 6948, 7208, + 7299, 7006, 7049, 6975, 7015, 7033, 7081, 7074, 7093, 7088, + 7097, 7100, 7118, 7121, 7106, 7149, 7164, 7170, 7188, 7196, + 7231, 7235, 7203, 7266, 7246, 7238, 7261, 7242, 7279, 7309, + 7324, 7331, 7271, 7354, 7334, 7364, 7395, 7357, 7369, 7399, + + 7406, 7405, 7446, 7416, 7432, 7458, 7463, 7466, 7477, 7481, + 7488, 7493, 7498, 7504, 7508, 6755, 6752, 6758, 6764, 6764, + 6818, 6827, 2765, 7590, 7547, 7528, 7517, 7554, 7520, 7582, + 7524, 7666, 7672, 7575, 7675, 7678, 7639, 7602, 7610, 7684, + 7696, 7708, 2817, 7686, 7698, 7710, 7750, 7786, 7797,15625, + 7874, 7951, 6948, 6941, 6957, 6949, 7400, 7505, 7048, 7122, + 7886, 7731, 6835, 6847, 2778, 6888, 2777, 6876, 6918, 6956, + 2767, 7028, 2766, 7022, 7103, 7097, 7115, 2760, 0, 2803, + 7721, 2793, 1369, 2789, 7741, 2781, 1444, 2758, 7842, 2751, + 901, 7136, 7138, 7809, 7926, 8043, 2736, 8129, 7914, 8106, + + 8117,15625, 7186, 7933, 8150, 8176, 2729, 7643, 7887, 7660, + 7286,15625, 2728, 7673, 8253, 8146, 8266, 8216, 7862, 7826, + 8141, 7848, 8245, 8248, 7851, 8275, 8283, 8294, 7910, 8290, + 7857, 8301, 8304, 8321, 8351, 8331, 8138, 8359, 8160, 8170, + 7195, 7213, 2651, 8376, 8335, 8379, 2712, 8387, 8386, 8367, + 8163, 8404, 7237, 2618, 8417, 8422, 8456, 8449, 8413, 8453, + 8480, 8506, 8486, 8489, 8495, 8499, 8516, 7471, 7321, 7356, + 7364, 7379, 2644, 7380, 2643, 7409, 7667, 7420, 7503, 7684, + 7517, 7571, 7595, 7601, 7590, 7667, 7693, 7696, 2608, 8523, + 8538, 8546, 8562, 8573, 8549, 8577, 8581, 8593, 8599, 8608, + + 2672, 8610, 8621, 8640, 8651, 8662, 7876, 8365, 7697, 7891, + 7793, 7884, 7794, 8377, 7875, 7892, 8727, 7951, 7955, 7950, + 0, 8398, 2600, 7971, 0, 8107, 0, 8114, 8195, 8248, + 8258, 2594, 8272, 8281, 8315, 8715, 8762, 8368, 2548, 8768, + 8820, 0, 0, 8826, 8383, 8903, 2543, 0, 8995, 0, + 8854, 8633, 8803, 8859, 8881,15625, 8977, 9004, 9026, 2607, + 8589, 8602, 8422, 8449, 2602, 8615, 8846, 8413, 2520, 8675, + 8834, 8684, 8776, 8840, 9021, 8757, 8788, 8898, 2570, 9112, + 9077, 8936, 8956, 9095, 9120, 9129, 9071, 9054, 2550, 9163, + 8490, 8493, 9123, 9136, 2475, 1255, 8972, 9024, 9139, 8517, + + 9142, 8535, 2474, 9145, 9165, 8549, 2459, 9153, 9188, 9195, + 9235, 2524, 9233, 8566, 8565, 8561, 8574, 8574, 8599, 8599, + 8600, 8600, 8608, 8613, 8618, 8631, 8714, 8738, 8735, 8786, + 8794, 8807, 8818, 8825, 8835, 8840, 8851, 8843, 8842, 9207, + 9227, 9263, 9251, 2513, 9281, 9257, 9292, 9305, 2483, 9307, + 9318, 9343, 9144, 8899, 9248, 9194, 9285, 9289, 9296, 9297, + 9309, 9364, 8889, 2427, 8993, 8994, 9022, 9146, 9175, 9218, + 9242, 9237, 9291, 9297, 9288, 9313, 9300, 9315, 9375, 9466, + 9472, 9481, 9318, 9487, 9321, 9569, 2390, 9502, 0, 9309, + 2389, 9508, 2377, 9515, 9526, 9551, 9589, 9626, 2433, 9479, + + 9503, 9332, 2422, 9485, 9565, 9345, 9642, 9662, 9665, 9549, + 2353, 1283, 9415, 9685, 9680, 9688, 9701, 2352, 1517, 9360, + 9393, 9693, 9725, 1674, 1531, 9733, 9738, 9394, 9488, 9756, + 2413, 9773, 9486, 9435, 9775, 9496, 9519, 9505, 2332, 1745, + 2358, 9506, 2340, 9549, 9696, 9551, 9577, 9671, 9676, 9695, + 9732, 9690, 9719, 9737, 9720, 9737, 9747, 9758, 9758, 9746, + 9756, 9775, 9776, 9767, 9766, 9768, 9807, 9838, 9841, 2299, + 1756, 9844, 9848, 2351, 9789, 9821, 9850, 9802, 9796, 9797, + 9805, 9806, 9830, 9859, 9831, 9832, 9861, 2311, 9835, 0, + 0, 9847, 9860, 0, 0, 0, 9855, 0, 2301, 9861, + + 9863, 9888, 9899, 9882, 9973, 9894, 9979, 9988,10005, 9919, + 10015,10032, 2270,10050,10065,10072,10079,10098,10107,10110, + 10129,10145,10179,10165, 2334, 9986,10108, 2324,10100,10256, + 9911,10021,10141,10202,10093, 1835, 1591,10275,10238,10278, + 10284,10287, 1838, 1619,10291, 9938, 9931,10294,10297,10300, + 10307, 9964, 2256,10321, 9950, 9989, 2252, 1882,10015,10328, + 10035,10076,10082, 2007, 1656,10344,10086,10087,10094,10101, + 10114,10118,10114,10338,10129,10116,10133,10138,10206,10247, + 10262,10288,10275,10292,10352,10302,10286,15625,10306,10317, + 10314,10319,10340,10336,10337,10382, 2124, 2080,10385,10393, + + 2307,10395,10370,10406,10349,10373,10382,10377,10350,10374, + 10380, 2260,10373,10383,10376,10391,10497, 2232,10432,10523, + 15625,10529,10538,10544,10559,10588,10607,10616, 0,10622, + 10637,10651,10666,10681,10699,10714,10701,10716,10736,10769, + 10747, 2230,10539,10632, 2229,10554,10846,10385,10469,10500, + 10505,10728,10574,10412, 2163,10673,10733,10810,10757,10841, + 10474, 2144,10477,10487,10863,10866,10763, 2123,10517,15625, + 10527, 2189, 2302,10873,10541,10534,10573,10560,10877,10880, + 10584, 2114,10602,10619,10639,10632,10651,10654,10664,10883, + 2105,10685,10672,10688,10671,10692,10690,10712,10724,10731, + + 10805,10887, 2079,10836,10860,10851,10853,10945,10869,10855, + 10862,10863,10948,10951,10970,10875, 2077, 2134,10957,10982, + 11008,10902,10876,10878,10916,10869, 0, 0,10891,10900, + 10934,10927, 0,10993,11034, 2057,10942,11036,11127,11133, + 11142,11148,11169,11175,11205,11211,11232,11213,11234,11263, + 2120,10976,11088, 2093,11140,11201,10957,11058, 2016,10947, + 11289,11084, 1976,10954,10957,10995,11111,11279,10981,10977, + 11184,11076,10994, 1973,10986,10987,11027,11054,11247, 1966, + 11102,11137,11124,11156,11174,11195,11276,11305, 1994,11197, + 1992,11308,11331,11188,11336,11195,11214,15625,11203,11210, + + 11219,11202,11203,11339,11271,11326,11292,11308,11328,11337, + 11338,11327,11337,11338,15625,11341,11343,11374,11381, 1960, + 11342, 2013,11362,11342,11392,11358,11379,11365,11380, 0, + 11361,11404,11456,11390, 1938,11404,11483,11489,11468,11491, + 1980,11479,11487, 1952,11484,11582,11425,11442,11445,11520, + 11446,11478,11467,11529,11523,11532,11560,11585, 1881,11477, + 15625,11479,11541, 1905,11527,11563,11554,11566, 1895,11553, + 11605, 1849,11614, 1833,11569,11625,11566,11628, 1831,11634, + 1809,15625,11642, 1723,11583, 1750,11594,11592,15625,11645, + 1714,11588,11589,11602,11611,11616,11610,11613,11614,11617, + + 15625,11636,11637,11628,11626,11624,15625,11630, 1756,11648, + 11667,11684,11745,11746,11631,11634, 0,11640, 1717,11647, + 11777,11754,11765, 1741,11767,11775, 1731,11804,11862,11658, + 11654,11677,11717,11742,11721,11723,11865,11803, 1647,11868, + 1623,11739,11743,11756,11757,11808, 1645,11871, 1639,11786, + 11812,11793,11879, 1598,11839,11839,11834,11856,11861,11846, + 11857,11858,11852,11853,11865,11856,11871,11864,11866,15625, + 11867,11863,11867,11868,11886,15625,15625,15625,11953, 1661, + 11895,11881,11907,11886,11956,11878,11929,11939,11959,11954, + 11976,11987, 1648,11988,11993, 1639,11992,12021,11983,11975, + + 12024, 1560,12038, 1557,11973,11990,12052,12012,12080,12009, + 12057,12058,12087, 1513,12061,12090,12093, 1497,12060,12061, + 12098, 1467,12066,12073,12080,12083,12071,12088,15625,12069, + 12088,12091,12078,12098,12081,12081,12093,12098,15625,12086, + 12084,12105,12105,15625,12110,12145, 1452, 1513,12114,12126, + 12187,12161,12118,12133, 0,12162,15625,12148,12179, 1505, + 12166,12225, 1503,12226,12270,12163,12183,12213,12208,12217, + 12176, 1432, 1458, 1292,12207,12213,12253,12227,12228, 1412, + 12244,12243,12261,12248,12244,12251,12257,12250,12262,12271, + 15625,12258,12269,12259,12260,12276,12277,12266,12261,12269, + + 15625,12273,15625, 1436,12287,12301,12281,12362, 0,12273, + 12291, 1392,12336,12380, 1381,12340,12398,12286,12276,12281, + 12314,12324,12340, 2261, 1294,12363,12369, 1321, 1307,12372, + 12366,12367,12379,12415,15625,12370,12387,12392,12380,15625, + 12384,12379,15625,12383,15625,12384,15625,12402,12392, 1317, + 12425,12379,12413, 0,12420, 1310,12459,12464, 1306,12467, + 12518,15625,12422,12435,15625,15625,12435,15625, 1200,12442, + 12451,12453,12455,12449,12471,12487,12458,12535, 1198,12459, + 12461,15625,12487,12498,12498,15625,12509,12514,15625, 1256, + 12465, 909, 942,12546,12551, 940,12560,12579,12530,15625, + + 12515,12523,12531,12537,12540,12541, 901,12582, 865,12537, + 15625,12600,12559,15625,15625,12560,15625,15625,12562, 924, + 12597,12612, 922,12598,12630,15625,12565,12575,12578,12597, + 12599,12611,12609,12657, 694,12603,12605,12607, 699,12660, + 12663, 689,12664,12625,12691,12626,12647,12650,12658,12653, + 12658,12660,15625,12663, 678,12686, 632,12722, 2380, 492, + 481,12671, 501, 492,12676,12680,12666,15625,12662,12687, + 15625, 440,12675,12689,12682,12690,12685,12745,15625,12708, + 12710,12701,12707,15625,12750,12753, 110,12723,12710,12722, + 12725,12769, 106,12733,12722,12775,12726,12721,12743,15625, + + 12750,12781,12762,12745,12751,12750,12752,12770,15625,12764, + 12777,12756,12806,15625,12889,12907,12925,12943,12961,12979, + 12997,13015,13033,13051,13069,13087,13105,13123,13141,13159, + 13174,13192,13206,13220,13234,13243,13257,13266,13282,13291, + 13303,13317,13331,13345,13354,13364,13369,13379,13397,13415, + 13433,13451,13469,13487,13505,13519,13528,13544,13562,13576, + 13585,13598,13607,13622,13636,13645,13663,13681,13696,13705, + 13720,13738,13756,13770,13779,13790,13799,13810,13819,13830, + 13839,13853,13862,13874,13883,13894,13903,13914,13923,13934, + 13943,13953,13958,13968,13986,14004,14022,14040,14058,14076, + + 14094,14112,14130,14144,14153,14168,14186,14204,14222,14236, + 14245,14256,14265,14280,14298,14316,14330,14339,14354,14372, + 14387,14405,14423,14437,14455,14469,14483,14497,14511,14526, + 14540,14554,14568,14581,14586,14596,14614,14632,14650,14668, + 14686,14700,14718,14736,14754,14772,14786,14800,14818,14836, + 14854,14868,14886,14904,14922,14940,14954,14968,14982,14996, + 15009,15014,15024,15042,15060,15078,15096,15110,15128,15146, + 15164,15178,15192,15210,15228,15242,15260,15278,15292,15306, + 15320,15334,15347,15352,15362,15380,15398,15412,15426,15444, + 15462,15480,15498,15516,15534,15552,15570,15588,15606 + + } ; + +static yyconst flex_int16_t yy_def[2700] = + { 0, + 2514, 1, 2514, 3, 2515, 2515, 2514, 7, 2514, 9, + 2514, 11, 2516, 2516, 2517, 2517, 2518, 2518, 2514, 19, + 2518, 2518, 2519, 2519, 2520, 2520, 2521, 2521, 2522, 2522, + 2523, 2523, 2524, 2524, 2525, 2525, 2514, 37, 2526, 2526, + 2527, 2527, 2514, 43, 2514, 45, 2528, 2528, 2514, 49, + 2529, 2529, 2518, 2518, 2530, 2530, 2518, 2518, 2514, 2514, + 2514, 2514, 2514, 2531, 2532, 2533, 2534, 2514, 2514, 2514, + 2514, 2514, 2514, 2533, 2514, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 2535, 2533, + + 2533, 2533, 2536, 2533, 2514, 2514, 2514, 2537, 2514, 2514, + 2514, 2537, 2537, 2537, 2537, 2537, 2537, 2537, 2537, 2537, + 2537, 2538, 2537, 2514, 2514, 2514, 2514, 2514, 2539, 2539, + 2539, 2514, 131, 131, 2514, 131, 131, 131, 131, 131, + 131, 131, 2539, 143, 143, 2540, 143, 2514, 2514, 2541, + 2542, 2543, 2514, 2542, 2542, 2544, 2542, 2542, 2542, 2545, + 2542, 2514, 2514, 2514, 2514, 2546, 2514, 2514, 2546, 2514, + 2546, 2514, 2514, 2546, 2546, 2546, 2546, 2546, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2547, 2514, + + 2514, 2514, 2547, 2514, 2547, 2547, 2547, 2547, 2547, 2547, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2548, 2514, 2549, 2550, 2514, 2551, 2514, 2514, + 2552, 2553, 2514, 2554, 2514, 2514, 2514, 2514, 2514, 2555, + 2556, 2514, 2514, 2514, 2514, 2514, 2556, 257, 257, 257, + 2514, 2556, 2556, 2556, 2557, 2556, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2558, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2559, 2560, 2514, 2514, 2514, + 2514, 2560, 2560, 2560, 2560, 2560, 2560, 2561, 2560, 2514, + + 2514, 2562, 2514, 2514, 2562, 2562, 2562, 2562, 2563, 2562, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2564, 2565, 2514, + 2514, 2514, 2514, 2514, 2565, 2514, 2514, 325, 325, 2514, + 2565, 2565, 2565, 2566, 2565, 2514, 2514, 2514, 2514, 2567, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2568, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2569, 2569, 2569, 2569, 2570, 2569, 2514, 2571, 2572, 2572, + 370, 370, 2573, 370, 2571, 2574, 2574, 2574, 2574, 2575, + 2574, 2514, 2576, 2514, 2576, 2576, 2576, 2577, 2576, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2574, 398, 398, + + 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, + 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, + 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, + 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, + 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, + 398, 398, 398, 398, 398, 2578, 2514, 2578, 2578, 2578, + 2579, 2578, 2514, 2514, 398, 2514, 2514, 2514, 2580, 2580, + 2580, 2580, 2581, 2580, 2514, 2514, 2514, 2514, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2514, 2580, 2514, 2514, 2514, + 2514, 2582, 2582, 493, 2514, 493, 493, 493, 493, 493, + + 493, 2582, 502, 502, 2583, 502, 2514, 502, 2514, 2514, + 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, + 493, 2514, 493, 2514, 2584, 2584, 2584, 2584, 2585, 2584, + 2514, 2586, 2586, 2586, 2586, 2587, 2586, 2514, 2588, 2514, + 2588, 2588, 2588, 2589, 2588, 2514, 2514, 2514, 2586, 2586, + 2590, 2514, 2590, 2590, 2590, 2591, 2590, 2514, 2514, 2586, + 2592, 2514, 2514, 2592, 2592, 2592, 2592, 2592, 2592, 2592, + 2592, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2593, 2593, 2593, 2514, 2514, 2593, 2593, 2593, 2593, 2593, + 2593, 2593, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + + 2514, 2514, 2514, 2514, 2514, 2594, 2514, 2595, 2514, 2514, + 2514, 2514, 2596, 2514, 2597, 2514, 2514, 2514, 2514, 2514, + 2514, 2598, 2514, 2514, 2514, 2599, 2514, 2600, 2514, 2514, + 2514, 2601, 2602, 2602, 634, 634, 2603, 634, 2601, 2604, + 2604, 2604, 2604, 2605, 2604, 2514, 2514, 2514, 2604, 2604, + 2604, 2604, 2604, 2514, 2604, 2514, 2514, 2514, 2514, 2606, + 2514, 2514, 2514, 2514, 2514, 2514, 2607, 2608, 2608, 669, + 669, 2609, 669, 2607, 2610, 2610, 2610, 2610, 2611, 2610, + 2514, 2514, 2610, 2610, 2610, 2514, 2610, 2514, 2514, 2612, + 2612, 2612, 2612, 2613, 2612, 2514, 2612, 2514, 2612, 2514, + + 2514, 2514, 2614, 2615, 2615, 705, 705, 2616, 705, 2614, + 2617, 2617, 2617, 2617, 2618, 2617, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2617, 724, 724, 724, 2514, 724, 2514, + 2514, 2514, 2619, 2514, 2514, 2514, 2514, 2514, 2620, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2621, 2622, 2623, 2514, + 2624, 2514, 2625, 2514, 2514, 2514, 2514, 2514, 2514, 2626, + 2514, 2626, 2626, 2626, 764, 764, 764, 764, 764, 764, + 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, + 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, + 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, + + 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, + 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, + 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, + 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, + 764, 2514, 2627, 2514, 2514, 2628, 2628, 2628, 2628, 2628, + 2628, 2628, 2514, 2629, 2629, 855, 855, 855, 855, 855, + 855, 855, 855, 855, 855, 2514, 2514, 2630, 2514, 2631, + 2632, 2632, 2514, 2633, 2514, 2634, 2634, 2634, 2634, 2634, + 2634, 2634, 2634, 2634, 2635, 2635, 2635, 2635, 2635, 2635, + 2635, 2635, 2635, 2514, 2636, 2636, 2514, 2514, 2637, 2637, + + 2514, 2514, 2638, 2638, 2514, 2639, 2640, 2641, 2514, 2514, + 2514, 2642, 2642, 2642, 2642, 2642, 2514, 2514, 2643, 2514, + 2514, 2644, 2645, 2646, 2514, 2647, 2647, 2647, 2514, 2648, + 2514, 2514, 2649, 2650, 2514, 2651, 2514, 2514, 2514, 2514, + 2514, 2514, 2652, 2514, 2652, 2652, 946, 2514, 2653, 2514, + 2514, 2514, 2654, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2655, 2514, 2514, 2656, 2656, 2656, 2514, 2514, 2514, 2514, + 2514, 2514, 2657, 2657, 974, 974, 974, 974, 974, 974, + 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, + 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, + + 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, + 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, + 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, + 974, 974, 974, 2514, 2657, 974, 974, 974, 974, 974, + 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, + 974, 974, 974, 974, 974, 2514, 2514, 2658, 2658, 2658, + 2658, 2658, 2658, 2658, 2659, 2659, 1066, 1066, 2514, 1066, + 1066, 1066, 1066, 1066, 1066, 1066, 2514, 2514, 2660, 2660, + 2514, 2661, 2661, 2661, 2661, 2661, 2661, 2661, 2661, 2661, + 2662, 2662, 2662, 2662, 2662, 2662, 2662, 2662, 2662, 2663, + + 2514, 2664, 2514, 2665, 2514, 2666, 2667, 2667, 2667, 2514, + 2514, 2668, 2668, 1113, 1113, 1113, 2514, 2669, 2669, 2669, + 2514, 2670, 2671, 2671, 2671, 2672, 2672, 2672, 2673, 2514, + 2674, 2514, 2675, 2675, 2675, 2514, 2514, 2514, 2514, 2514, + 2514, 2676, 2676, 1143, 2677, 2677, 2677, 2514, 2514, 2678, + 2678, 2678, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2679, + 2679, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, + 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, + 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 2514, + 2679, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, + + 2514, 2679, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, + 1161, 1161, 1161, 1161, 1161, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2679, 1161, 1161, 1161, 1161, 1161, + 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, + 1161, 1161, 2514, 2680, 2680, 2680, 2680, 2680, 2680, 2514, + 2681, 2681, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, + 2682, 2682, 2683, 2683, 2683, 2683, 2683, 2683, 2683, 2683, + 2683, 2684, 2684, 2684, 2684, 2684, 2684, 2684, 2684, 2685, + 2685, 2685, 2685, 2686, 2686, 2686, 2686, 2687, 2687, 2687, + 2687, 2514, 2514, 2688, 2514, 2514, 2514, 2688, 2688, 2688, + + 2688, 2514, 2514, 2689, 2689, 2689, 2514, 2514, 1143, 1143, + 1143, 2514, 2514, 2514, 1161, 2514, 2679, 1161, 1161, 1161, + 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, + 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, + 2514, 2514, 2514, 1161, 1161, 2514, 2514, 2679, 1161, 1161, + 1161, 1161, 2514, 2514, 1161, 2514, 2679, 1161, 1161, 1161, + 2514, 2679, 1161, 1161, 1161, 1161, 1161, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 1161, + 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, + + 2514, 2680, 2680, 2680, 2680, 2680, 1252, 1252, 1252, 1252, + 1252, 1252, 1252, 1252, 1252, 1252, 2682, 2683, 2683, 2683, + 2683, 2683, 2683, 2683, 2683, 2683, 2684, 2684, 2684, 2684, + 2684, 2684, 2684, 2514, 2514, 2688, 2690, 2514, 2514, 2690, + 2690, 1296, 1296, 2690, 1296, 1296, 1446, 1446, 2691, 1446, + 2690, 2514, 2688, 2688, 2688, 2514, 2689, 2689, 2689, 2514, + 2514, 1143, 1143, 1143, 2514, 2514, 1161, 2514, 2514, 1161, + 1161, 1161, 1161, 1161, 1161, 1161, 1161, 2514, 2514, 2679, + 1161, 1161, 1161, 1161, 1161, 1161, 1161, 2514, 2514, 2679, + 2514, 2514, 1161, 1161, 2514, 2692, 1161, 1161, 1161, 2514, + + 1161, 2514, 2514, 1161, 1161, 2514, 2514, 1161, 1161, 1161, + 2514, 2514, 2679, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 1161, + 1161, 1161, 2514, 2514, 2679, 1161, 1161, 1161, 2514, 2680, + 2680, 2680, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, + 1252, 2682, 2683, 2683, 2683, 2683, 2683, 2683, 2683, 2683, + 2684, 2684, 2684, 2684, 2684, 2684, 2514, 2514, 2688, 2690, + 2690, 2690, 2514, 2690, 1296, 2690, 1296, 2690, 1296, 1296, + 1296, 2693, 2514, 2688, 2688, 2689, 2689, 2689, 2514, 2514, + + 1143, 1143, 2514, 2514, 1161, 2514, 1161, 1161, 1161, 1161, + 2514, 2694, 1161, 1161, 1161, 1161, 1161, 2514, 2695, 2514, + 2514, 1161, 1161, 2692, 2692, 2514, 1161, 2514, 2514, 2514, + 2514, 2679, 2514, 1161, 1161, 2514, 2514, 2514, 2514, 2696, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 1161, 1161, 1161, 2514, + 2697, 1161, 1161, 2514, 2680, 2680, 2680, 1252, 1252, 1252, + 1252, 1252, 1252, 1252, 1252, 1252, 2682, 2683, 2683, 2683, + 2683, 2683, 2683, 2683, 2683, 2684, 2684, 2684, 2684, 2684, + + 2684, 2514, 2514, 2688, 2690, 2514, 2698, 2693, 2690, 1296, + 2690, 2690, 1446, 2693, 2693, 2698, 2693, 2693, 2693, 2688, + 2688, 2689, 2689, 2689, 2514, 2514, 1143, 2514, 2514, 1161, + 2514, 1161, 1161, 1161, 1161, 2694, 2694, 2514, 1161, 1161, + 1161, 1161, 2695, 2695, 2514, 2514, 2514, 1161, 1161, 2514, + 2514, 2514, 2514, 1161, 2514, 2514, 2514, 2699, 2514, 1161, + 2514, 2514, 2514, 2696, 2696, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 1161, 2697, 2697, 2514, 1161, + + 2514, 2680, 2680, 2680, 1252, 1252, 1252, 1252, 2683, 2683, + 2683, 2683, 2684, 2684, 2684, 2684, 2514, 2514, 2688, 2690, + 2514, 2698, 2698, 2698, 2698, 2698, 2698, 2698, 1296, 2693, + 2693, 2698, 2698, 2693, 2693, 2693, 2688, 2688, 2689, 2689, + 2689, 2514, 2514, 1143, 2514, 2514, 1161, 2514, 1161, 1161, + 1161, 2514, 2514, 2514, 2514, 1161, 1161, 1161, 2514, 2514, + 2514, 2514, 2514, 2514, 1161, 1161, 2514, 2514, 2514, 2514, + 2514, 2699, 2699, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 1161, 2514, 2514, 2514, 2514, 2514, 2680, 2680, + 2680, 1252, 1252, 1252, 1252, 2683, 2683, 2683, 2683, 2684, + 2684, 2684, 2684, 2514, 2514, 2514, 2514, 2688, 2690, 2698, + 2698, 2698, 2698, 2693, 2698, 2693, 2693, 2688, 2689, 2689, + 2514, 2514, 1143, 2514, 2514, 1161, 2514, 2514, 2514, 2514, + 1161, 2514, 2514, 2514, 2514, 2514, 1161, 1161, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 1161, 2514, 2514, + 2514, 2514, 2680, 2680, 2680, 1252, 1252, 2683, 2683, 2684, + 2684, 2684, 2514, 2514, 2514, 2514, 2698, 2693, 2688, 2689, + 2514, 2514, 1143, 2514, 2514, 1161, 2514, 2514, 2514, 1161, + 2514, 2514, 2514, 1161, 1161, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2680, + 2680, 2680, 1252, 1252, 2683, 2683, 2684, 2684, 2514, 2514, + 2698, 2688, 2689, 2514, 2514, 1143, 2514, 2514, 1161, 2514, + 2514, 2514, 1161, 2514, 2514, 2514, 1161, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2680, 2680, 2680, 1252, 1252, 2683, 2683, 2684, 2514, 2514, + 2688, 2689, 2514, 2514, 1143, 2514, 2514, 1161, 2514, 2514, + + 2514, 2514, 2514, 2514, 2514, 2514, 1161, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2680, 2680, + 1252, 1252, 2683, 2683, 2684, 2514, 2514, 2688, 2689, 2514, + 2514, 1143, 2514, 2514, 1161, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + + 2514, 2514, 2514, 2514, 2680, 2680, 1252, 1252, 2683, 2683, + 2514, 2514, 2514, 1143, 2514, 2514, 1161, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2680, 2680, 1252, 2683, 2514, 2514, 2514, 1143, 2514, 2514, + 1161, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2680, 2514, 2514, 2514, 1143, 2514, 2514, 1161, 2514, 2514, + + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 1143, 2514, 2514, 1161, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 1143, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 0, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514 + + } ; + +static yyconst flex_int16_t yy_nxt[15718] = + { 0, + 60, 61, 62, 61, 63, 64, 65, 66, 67, 68, + 68, 63, 69, 70, 71, 72, 73, 74, 63, 63, + 63, 75, 63, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 66, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 66, 66, 60, + 60, 63, 66, 99, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 66, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 66, 66, + 60, 100, 101, 102, 103, 104, 104, 104, 104, 104, + 104, 105, 106, 106, 107, 106, 106, 106, 108, 108, + + 106, 109, 109, 110, 111, 106, 111, 106, 106, 112, + 106, 106, 106, 106, 106, 108, 108, 108, 108, 108, + 113, 108, 108, 114, 108, 108, 108, 108, 108, 108, + 108, 115, 116, 117, 108, 108, 108, 118, 108, 108, + 108, 106, 106, 106, 108, 106, 108, 108, 108, 108, + 108, 113, 108, 108, 114, 108, 108, 108, 108, 108, + 108, 108, 115, 116, 117, 108, 108, 108, 118, 108, + 108, 108, 106, 119, 120, 121, 122, 123, 123, 123, + 123, 123, 123, 124, 126, 126, 392, 393, 2492, 394, + 604, 604, 2486, 127, 127, 128, 129, 130, 129, 128, + + 128, 131, 131, 128, 128, 128, 132, 133, 128, 134, + 135, 128, 131, 128, 128, 128, 128, 128, 131, 131, + 131, 136, 137, 131, 138, 131, 131, 131, 131, 131, + 131, 131, 139, 140, 131, 141, 131, 142, 131, 131, + 131, 131, 131, 131, 128, 128, 128, 131, 128, 131, + 131, 131, 136, 137, 131, 138, 131, 131, 131, 131, + 131, 131, 131, 139, 140, 131, 141, 131, 142, 131, + 131, 131, 131, 131, 131, 128, 143, 144, 145, 146, + 147, 147, 147, 147, 147, 147, 148, 149, 149, 107, + 149, 149, 150, 151, 151, 152, 149, 149, 153, 149, + + 149, 149, 149, 149, 151, 149, 149, 149, 149, 149, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 154, 151, 151, 151, 155, + 151, 151, 151, 151, 151, 151, 149, 149, 149, 151, + 156, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 154, 151, 151, 151, + 155, 151, 151, 151, 151, 151, 151, 149, 157, 158, + 159, 160, 161, 161, 161, 161, 161, 161, 162, 163, + 164, 165, 164, 163, 163, 163, 166, 167, 163, 163, + 168, 169, 170, 171, 172, 163, 166, 163, 163, 173, + + 163, 163, 166, 166, 166, 174, 175, 166, 176, 166, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 177, + 166, 178, 166, 166, 166, 166, 166, 166, 163, 163, + 163, 166, 163, 166, 166, 166, 174, 175, 166, 176, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 177, 166, 178, 166, 166, 166, 166, 166, 166, 163, + 163, 179, 163, 180, 163, 163, 163, 163, 163, 163, + 163, 182, 183, 182, 234, 182, 183, 182, 184, 234, + 237, 185, 184, 186, 237, 185, 240, 186, 190, 191, + 190, 240, 190, 191, 190, 192, 107, 107, 193, 192, + + 192, 107, 193, 107, 192, 476, 490, 355, 509, 511, + 477, 491, 355, 510, 512, 356, 235, 513, 269, 269, + 356, 235, 238, 2514, 357, 376, 238, 2471, 514, 357, + 313, 241, 313, 515, 516, 405, 241, 517, 355, 406, + 511, 564, 547, 355, 2475, 512, 356, 548, 513, 269, + 269, 356, 187, 2474, 188, 357, 187, 562, 188, 514, + 357, 313, 563, 313, 515, 516, 405, 2459, 517, 194, + 406, 195, 564, 194, 2458, 195, 196, 197, 198, 197, + 196, 196, 196, 199, 200, 201, 201, 202, 203, 204, + 205, 196, 196, 206, 196, 196, 201, 196, 196, 206, + + 206, 206, 206, 206, 206, 207, 206, 206, 206, 206, + 206, 206, 206, 206, 208, 206, 206, 209, 210, 206, + 206, 206, 206, 206, 206, 196, 196, 196, 206, 196, + 206, 206, 206, 206, 206, 206, 207, 206, 206, 206, + 206, 206, 206, 206, 206, 208, 206, 206, 209, 210, + 206, 206, 206, 206, 206, 206, 201, 196, 211, 196, + 212, 196, 196, 196, 196, 196, 196, 196, 213, 213, + 213, 213, 213, 213, 565, 486, 214, 566, 574, 214, + 218, 219, 218, 575, 2470, 220, 464, 221, 567, 222, + 223, 218, 219, 218, 578, 2455, 220, 728, 221, 579, + + 222, 223, 227, 228, 227, 565, 2442, 229, 566, 229, + 229, 229, 230, 227, 228, 227, 2455, 654, 229, 567, + 229, 229, 229, 230, 377, 378, 379, 380, 381, 381, + 381, 381, 381, 381, 382, 2514, 2514, 376, 376, 582, + 583, 2514, 586, 376, 488, 489, 587, 410, 428, 215, + 657, 216, 215, 376, 216, 466, 467, 424, 468, 584, + 411, 224, 599, 225, 585, 594, 595, 600, 596, 730, + 582, 583, 224, 586, 225, 603, 2434, 587, 410, 428, + 604, 657, 476, 231, 376, 232, 656, 477, 424, 663, + 664, 411, 719, 720, 231, 721, 232, 246, 247, 248, + + 247, 246, 249, 250, 251, 252, 253, 246, 246, 246, + 246, 254, 246, 246, 251, 246, 255, 246, 246, 256, + 251, 251, 251, 251, 251, 257, 258, 251, 251, 251, + 251, 259, 251, 251, 251, 251, 251, 260, 251, 251, + 251, 251, 251, 251, 251, 251, 246, 246, 246, 251, + 261, 251, 251, 251, 251, 251, 257, 258, 251, 251, + 251, 251, 259, 251, 251, 251, 251, 251, 260, 251, + 251, 251, 251, 251, 251, 251, 251, 246, 262, 263, + 264, 265, 266, 266, 266, 266, 266, 266, 267, 271, + 272, 271, 653, 273, 274, 640, 275, 276, 277, 358, + + 358, 358, 278, 271, 272, 271, 1290, 273, 274, 686, + 275, 276, 277, 2514, 490, 376, 278, 591, 662, 491, + 2514, 407, 376, 653, 700, 376, 640, 735, 2514, 279, + 376, 736, 376, 518, 592, 408, 418, 519, 409, 2442, + 419, 2439, 741, 279, 420, 412, 520, 2408, 591, 662, + 521, 413, 407, 2432, 742, 700, 376, 2423, 735, 2420, + 279, 2419, 736, 376, 518, 592, 408, 418, 519, 409, + 280, 419, 281, 741, 279, 420, 412, 520, 688, 689, + 359, 521, 413, 1289, 280, 742, 281, 282, 283, 284, + 283, 282, 285, 286, 287, 288, 289, 290, 282, 282, + + 282, 291, 282, 282, 287, 282, 282, 282, 282, 282, + 287, 287, 287, 287, 287, 292, 287, 287, 287, 287, + 287, 293, 287, 287, 287, 287, 287, 294, 287, 287, + 287, 287, 287, 287, 287, 287, 282, 282, 282, 287, + 282, 287, 287, 287, 287, 287, 292, 287, 287, 287, + 287, 287, 293, 287, 287, 287, 287, 287, 294, 287, + 287, 287, 287, 287, 287, 287, 287, 282, 295, 296, + 297, 298, 299, 299, 299, 299, 299, 299, 300, 107, + 107, 107, 107, 107, 301, 302, 302, 303, 107, 107, + 107, 107, 107, 107, 107, 107, 302, 107, 107, 107, + + 107, 304, 302, 302, 302, 302, 302, 305, 302, 302, + 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, + 302, 302, 302, 302, 302, 302, 302, 302, 107, 107, + 107, 302, 107, 302, 302, 302, 302, 302, 305, 302, + 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, + 302, 302, 302, 302, 302, 302, 302, 302, 302, 107, + 306, 307, 308, 309, 310, 310, 310, 310, 310, 310, + 311, 314, 315, 316, 315, 314, 317, 318, 319, 320, + 314, 314, 314, 321, 322, 323, 324, 314, 325, 314, + 326, 327, 314, 327, 319, 319, 319, 319, 319, 319, + + 328, 319, 319, 319, 319, 319, 319, 319, 319, 319, + 319, 319, 329, 319, 319, 319, 319, 319, 319, 319, + 314, 314, 314, 319, 330, 319, 319, 319, 319, 319, + 319, 328, 319, 319, 319, 319, 319, 319, 319, 319, + 319, 319, 319, 329, 319, 319, 319, 319, 319, 319, + 319, 314, 331, 332, 333, 334, 335, 335, 335, 335, + 335, 335, 336, 338, 339, 338, 1625, 1626, 340, 509, + 338, 339, 338, 2418, 510, 340, 341, 358, 358, 358, + 2378, 342, 743, 341, 630, 630, 630, 2368, 342, 744, + 343, 347, 348, 347, 1737, 1738, 349, 343, 347, 348, + + 347, 2324, 568, 349, 350, 360, 569, 344, 745, 351, + 2514, 350, 376, 743, 344, 570, 351, 512, 352, 571, + 744, 343, 376, 2396, 353, 352, 652, 2393, 343, 414, + 513, 353, 415, 568, 2390, 416, 547, 569, 344, 745, + 640, 548, 384, 640, 345, 344, 570, 514, 512, 352, + 571, 345, 2514, 376, 711, 353, 352, 652, 359, 2373, + 414, 513, 353, 415, 727, 631, 416, 630, 630, 630, + 562, 640, 354, 2372, 640, 563, 2325, 1282, 514, 354, + 2324, 362, 363, 364, 365, 366, 366, 366, 366, 366, + 366, 367, 368, 368, 574, 727, 368, 368, 2359, 575, + + 368, 368, 368, 368, 368, 368, 368, 368, 368, 2356, + 368, 368, 368, 368, 368, 385, 386, 387, 388, 389, + 389, 389, 389, 389, 389, 390, 578, 2514, 2514, 376, + 376, 579, 584, 599, 516, 451, 455, 585, 600, 376, + 376, 368, 368, 368, 2514, 368, 376, 2514, 631, 376, + 603, 1281, 1286, 2350, 651, 604, 376, 640, 421, 376, + 640, 422, 658, 658, 658, 516, 451, 455, 423, 417, + 376, 376, 368, 370, 371, 372, 373, 374, 374, 374, + 374, 374, 374, 375, 397, 651, 398, 376, 640, 421, + 376, 640, 422, 2514, 2277, 376, 399, 395, 758, 423, + + 417, 425, 658, 658, 658, 376, 517, 757, 759, 426, + 2323, 607, 607, 607, 2271, 427, 608, 854, 609, 2514, + 2315, 376, 2312, 2514, 610, 376, 1285, 399, 1744, 1745, + 2304, 376, 425, 855, 2246, 439, 376, 517, 757, 759, + 426, 429, 1625, 659, 856, 440, 427, 1750, 854, 2221, + 377, 378, 379, 380, 381, 381, 381, 381, 381, 381, + 382, 2514, 376, 376, 855, 2514, 439, 376, 857, 2514, + 858, 376, 429, 376, 430, 856, 440, 376, 431, 2216, + 400, 376, 401, 659, 859, 860, 432, 402, 403, 404, + 433, 397, 611, 755, 863, 2213, 864, 438, 2514, 857, + + 376, 858, 1737, 756, 376, 430, 434, 1852, 376, 431, + 376, 400, 376, 401, 435, 859, 860, 432, 402, 403, + 404, 433, 865, 436, 861, 863, 437, 864, 438, 876, + 1744, 2514, 877, 376, 756, 1859, 2514, 434, 376, 2203, + 862, 376, 2201, 441, 445, 435, 442, 2514, 376, 376, + 878, 446, 443, 865, 436, 861, 2263, 437, 444, 376, + 876, 447, 879, 877, 2514, 2260, 376, 1765, 448, 882, + 449, 862, 1879, 450, 441, 445, 376, 442, 2248, 376, + 2153, 878, 446, 443, 457, 1625, 2514, 2514, 2514, 444, + 376, 2219, 447, 879, 2514, 880, 376, 2215, 464, 448, + + 882, 449, 452, 376, 450, 2140, 376, 376, 883, 453, + 454, 881, 458, 459, 460, 461, 462, 462, 462, 462, + 462, 462, 463, 665, 665, 665, 880, 2514, 2514, 2138, + 376, 376, 376, 452, 376, 2514, 2514, 376, 464, 883, + 453, 454, 881, 376, 2514, 2514, 464, 761, 2196, 761, + 2514, 376, 762, 884, 885, 464, 1765, 1766, 2193, 588, + 376, 376, 376, 2514, 589, 376, 479, 1798, 1799, 2189, + 376, 376, 376, 2180, 376, 376, 590, 768, 376, 376, + 376, 761, 376, 761, 884, 885, 968, 376, 376, 376, + 588, 376, 969, 376, 969, 589, 2090, 970, 665, 665, + + 665, 376, 2161, 358, 666, 2083, 376, 590, 768, 376, + 480, 701, 701, 701, 701, 701, 701, 481, 376, 470, + 471, 472, 473, 474, 474, 474, 474, 474, 474, 475, + 470, 471, 472, 473, 474, 474, 474, 474, 474, 474, + 475, 480, 482, 483, 886, 887, 1737, 2514, 481, 1744, + 2514, 470, 471, 472, 473, 474, 474, 474, 474, 474, + 474, 475, 470, 471, 472, 473, 474, 474, 474, 474, + 474, 474, 475, 482, 483, 886, 887, 484, 485, 666, + 470, 471, 472, 473, 474, 474, 474, 474, 474, 474, + 475, 2080, 702, 1873, 1874, 702, 888, 470, 471, 472, + + 473, 474, 474, 474, 474, 474, 474, 475, 484, 485, + 731, 731, 731, 2078, 889, 2073, 470, 471, 472, 473, + 474, 474, 474, 474, 474, 474, 475, 888, 731, 731, + 731, 2071, 470, 471, 472, 473, 474, 474, 474, 474, + 474, 474, 475, 2514, 2514, 889, 2514, 2150, 376, 2514, + 2514, 737, 737, 737, 486, 2514, 2514, 2145, 774, 469, + 486, 2514, 2514, 2058, 890, 469, 486, 2514, 2514, 2127, + 891, 469, 486, 737, 737, 737, 892, 469, 559, 358, + 358, 358, 893, 532, 910, 911, 469, 469, 469, 774, + 469, 732, 469, 469, 469, 890, 469, 2124, 469, 469, + + 469, 891, 469, 524, 469, 469, 469, 892, 469, 732, + 532, 532, 532, 893, 532, 910, 911, 469, 1765, 2514, + 2033, 918, 2514, 469, 376, 2514, 614, 614, 614, 469, + 2109, 615, 738, 616, 376, 469, 492, 492, 492, 617, + 921, 532, 2019, 769, 2077, 932, 2075, 494, 1979, 494, + 495, 2514, 918, 376, 738, 1972, 2514, 2514, 1962, 765, + 359, 496, 497, 376, 498, 376, 951, 559, 753, 753, + 753, 921, 532, 499, 769, 500, 932, 501, 952, 526, + 527, 528, 529, 530, 530, 530, 530, 530, 530, 531, + 765, 1798, 496, 497, 376, 498, 1914, 951, 1958, 532, + + 532, 532, 955, 532, 499, 722, 500, 618, 501, 952, + 2044, 956, 630, 630, 630, 940, 502, 503, 504, 505, + 506, 506, 506, 506, 506, 506, 507, 492, 492, 492, + 532, 957, 2514, 955, 958, 1798, 2514, 2041, 494, 1934, + 494, 495, 956, 620, 620, 620, 940, 621, 622, 754, + 518, 2022, 496, 497, 519, 498, 623, 959, 376, 1915, + 540, 1902, 957, 520, 499, 958, 500, 521, 501, 533, + 534, 535, 536, 537, 537, 537, 537, 537, 537, 538, + 2514, 518, 376, 496, 497, 519, 498, 1890, 959, 376, + 549, 767, 376, 631, 520, 499, 1880, 500, 521, 501, + + 1873, 2514, 620, 620, 620, 1867, 902, 502, 503, 504, + 505, 506, 506, 506, 506, 506, 506, 507, 2514, 2514, + 2514, 549, 767, 376, 624, 971, 1860, 971, 550, 2514, + 972, 2514, 495, 541, 542, 543, 544, 545, 545, 545, + 545, 545, 545, 546, 552, 1853, 1954, 1951, 533, 534, + 535, 536, 537, 537, 537, 537, 537, 537, 538, 550, + 641, 642, 643, 644, 645, 645, 645, 645, 645, 645, + 646, 2368, 553, 554, 555, 556, 557, 557, 557, 557, + 557, 557, 558, 624, 1937, 376, 533, 534, 535, 536, + 537, 537, 537, 537, 537, 537, 538, 1004, 502, 508, + + 504, 505, 506, 506, 506, 506, 506, 506, 507, 2514, + 2514, 2514, 1929, 1873, 2514, 2514, 376, 2514, 1971, 711, + 2514, 941, 2514, 2514, 1918, 522, 2514, 2514, 1004, 711, + 493, 942, 2514, 2514, 1630, 376, 726, 559, 1751, 2514, + 2514, 1845, 532, 559, 2514, 2369, 376, 376, 532, 995, + 654, 1842, 1588, 1814, 975, 640, 376, 493, 493, 493, + 711, 493, 942, 1809, 771, 772, 376, 726, 1801, 532, + 532, 532, 773, 532, 1005, 532, 532, 532, 376, 532, + 995, 1543, 640, 640, 640, 975, 640, 376, 493, 2514, + 2471, 376, 1769, 2514, 2514, 771, 772, 908, 908, 908, + + 532, 376, 805, 773, 654, 1005, 532, 632, 632, 640, + 1767, 632, 632, 640, 1511, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 1758, 632, 632, 632, 632, 632, + 2514, 2514, 376, 805, 1488, 1478, 640, 640, 640, 1728, + 640, 654, 2514, 2514, 376, 376, 640, 658, 658, 658, + 1725, 990, 792, 376, 376, 376, 632, 632, 632, 1592, + 632, 607, 607, 607, 2472, 2514, 2514, 640, 894, 630, + 766, 1713, 1713, 640, 640, 640, 654, 640, 909, 1689, + 1009, 640, 990, 792, 376, 376, 376, 632, 634, 635, + 636, 637, 638, 638, 638, 638, 638, 638, 639, 649, + + 1674, 766, 650, 376, 640, 1017, 376, 977, 640, 640, + 640, 1009, 640, 676, 677, 678, 679, 680, 680, 680, + 680, 680, 680, 681, 1671, 614, 614, 614, 659, 1028, + 649, 1011, 898, 650, 376, 1640, 1017, 376, 977, 640, + 683, 1361, 611, 641, 642, 643, 644, 645, 645, 645, + 645, 645, 645, 646, 667, 667, 1356, 1346, 667, 667, + 1028, 1619, 667, 667, 667, 667, 667, 667, 667, 667, + 667, 683, 667, 667, 667, 667, 667, 944, 1138, 944, + 1138, 1612, 1137, 1139, 676, 677, 678, 679, 680, 680, + 680, 680, 680, 680, 681, 684, 919, 919, 919, 665, + + 665, 665, 1316, 667, 667, 667, 618, 667, 691, 692, + 693, 694, 695, 695, 695, 695, 695, 695, 696, 1603, + 685, 924, 924, 924, 1599, 1588, 684, 701, 701, 701, + 1295, 936, 936, 936, 667, 669, 670, 671, 672, 673, + 673, 673, 673, 673, 673, 674, 1575, 1033, 731, 731, + 731, 685, 1568, 676, 677, 678, 679, 680, 680, 680, + 680, 680, 680, 681, 676, 677, 678, 679, 680, 680, + 680, 680, 680, 680, 681, 2514, 2514, 920, 1033, 1041, + 666, 2514, 2514, 949, 949, 949, 686, 2514, 2514, 1549, + 1224, 675, 686, 2514, 2514, 1523, 1521, 675, 686, 2514, + + 1201, 376, 925, 675, 686, 2514, 758, 376, 702, 675, + 1041, 376, 937, 737, 737, 737, 759, 376, 675, 675, + 675, 779, 675, 1496, 675, 675, 675, 697, 675, 732, + 675, 675, 675, 1190, 675, 801, 675, 675, 675, 2514, + 675, 376, 376, 2514, 2514, 1465, 1460, 759, 376, 675, + 1452, 376, 779, 791, 698, 675, 1290, 665, 697, 690, + 1140, 675, 1140, 1290, 950, 1141, 801, 675, 691, 692, + 693, 694, 695, 695, 695, 695, 695, 695, 696, 376, + 2514, 2514, 376, 2514, 791, 376, 690, 690, 690, 1286, + 690, 698, 2514, 2514, 738, 376, 690, 1286, 2514, 2514, + + 376, 1282, 770, 698, 1032, 2514, 2514, 376, 690, 698, + 376, 1282, 1433, 976, 690, 981, 728, 690, 1428, 1426, + 2514, 711, 376, 690, 690, 690, 376, 690, 783, 1422, + 1420, 376, 376, 770, 1401, 690, 690, 690, 376, 690, + 376, 690, 690, 690, 976, 690, 981, 1034, 711, 711, + 711, 1313, 711, 1151, 690, 1146, 2514, 1141, 1141, 783, + 953, 953, 953, 376, 2514, 2514, 690, 965, 753, 753, + 1139, 376, 690, 703, 703, 728, 1139, 703, 703, 711, + 711, 703, 703, 703, 703, 703, 703, 703, 703, 703, + 493, 703, 703, 703, 703, 703, 712, 713, 714, 715, + + 716, 716, 716, 716, 716, 716, 717, 711, 711, 711, + 360, 711, 1137, 1134, 376, 1307, 1082, 704, 978, 1071, + 1124, 493, 703, 703, 703, 2514, 703, 376, 2514, 2514, + 668, 2514, 1119, 376, 1293, 2514, 2514, 376, 711, 728, + 701, 954, 1108, 376, 711, 376, 728, 1082, 966, 978, + 780, 711, 793, 703, 705, 706, 707, 708, 709, 709, + 709, 709, 709, 709, 710, 723, 979, 724, 376, 633, + 376, 711, 711, 711, 376, 711, 1083, 725, 711, 711, + 711, 780, 711, 793, 1104, 1102, 362, 363, 364, 365, + 366, 366, 366, 366, 366, 366, 367, 979, 2514, 2514, + + 2514, 376, 711, 1100, 2514, 2514, 2514, 1083, 725, 711, + 746, 2514, 2514, 2514, 376, 361, 746, 1275, 551, 539, + 376, 361, 997, 746, 525, 1243, 456, 980, 361, 972, + 972, 712, 713, 714, 715, 716, 716, 716, 716, 716, + 716, 717, 361, 361, 361, 376, 361, 970, 361, 361, + 361, 376, 361, 997, 970, 361, 361, 361, 980, 361, + 2514, 2514, 2514, 968, 2514, 965, 376, 1158, 383, 2514, + 2514, 376, 746, 361, 369, 361, 810, 361, 986, 361, + 464, 2514, 953, 949, 376, 376, 361, 377, 378, 379, + 380, 381, 381, 381, 381, 381, 381, 382, 384, 2514, + + 999, 376, 376, 711, 361, 361, 361, 810, 361, 986, + 1137, 781, 376, 376, 376, 376, 376, 2514, 2514, 936, + 1132, 690, 782, 2514, 2514, 675, 924, 919, 464, 640, + 908, 999, 904, 376, 464, 361, 368, 368, 1084, 376, + 368, 368, 781, 376, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 782, 368, 368, 368, 368, 368, 904, + 376, 376, 376, 993, 376, 376, 376, 376, 376, 1084, + 376, 385, 386, 387, 388, 389, 389, 389, 389, 389, + 389, 390, 376, 493, 1012, 368, 368, 368, 2514, 368, + 376, 376, 900, 2514, 993, 900, 376, 376, 896, 807, + + 376, 844, 844, 844, 844, 844, 844, 844, 844, 844, + 844, 844, 1075, 376, 493, 1012, 368, 370, 371, 372, + 373, 374, 374, 374, 374, 374, 374, 375, 368, 368, + 807, 376, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 748, 368, 368, 368, 368, + 368, 368, 896, 1089, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 368, 368, 748, 368, 368, + 368, 368, 2514, 2514, 376, 2514, 1019, 376, 2514, 2514, + 2514, 1085, 532, 464, 2514, 2514, 2514, 376, 376, 750, + 493, 469, 1057, 376, 383, 750, 968, 2514, 2514, 2514, + + 383, 753, 963, 737, 789, 376, 731, 1019, 750, 722, + 935, 728, 2514, 383, 376, 376, 376, 376, 376, 376, + 1086, 383, 383, 383, 376, 383, 728, 383, 383, 383, + 933, 383, 2514, 2514, 2514, 789, 368, 368, 798, 368, + 383, 383, 383, 750, 383, 2514, 376, 376, 383, 703, + 1087, 1086, 383, 701, 2514, 376, 376, 376, 383, 698, + 2514, 2514, 803, 376, 763, 698, 376, 376, 2514, 798, + 376, 383, 764, 376, 686, 383, 383, 383, 686, 383, + 840, 1087, 2514, 1013, 376, 922, 784, 667, 376, 785, + 775, 665, 776, 803, 376, 763, 376, 376, 376, 1088, + + 2514, 777, 376, 764, 376, 982, 383, 397, 778, 760, + 983, 840, 376, 658, 1013, 654, 2514, 784, 376, 399, + 785, 775, 786, 776, 787, 376, 654, 376, 376, 985, + 1088, 988, 777, 376, 906, 989, 982, 1090, 788, 778, + 632, 983, 2514, 376, 376, 2514, 2514, 376, 376, 630, + 399, 620, 905, 786, 376, 787, 794, 376, 376, 376, + 985, 790, 988, 376, 376, 797, 989, 904, 1090, 788, + 987, 795, 796, 377, 378, 379, 380, 381, 381, 381, + 381, 381, 381, 382, 614, 376, 901, 794, 376, 376, + 900, 607, 790, 2514, 376, 376, 797, 2514, 2514, 376, + + 376, 987, 795, 796, 2514, 376, 376, 897, 896, 376, + 376, 799, 2514, 800, 376, 804, 376, 2514, 2514, 376, + 376, 376, 802, 806, 376, 1024, 376, 376, 873, 376, + 376, 1000, 991, 2514, 873, 376, 376, 808, 809, 376, + 376, 376, 799, 811, 800, 812, 804, 376, 984, 813, + 869, 1091, 376, 802, 806, 376, 1024, 376, 376, 376, + 376, 376, 1000, 991, 869, 2514, 994, 376, 808, 809, + 376, 559, 559, 2514, 811, 376, 812, 376, 867, 984, + 813, 2514, 1091, 376, 376, 376, 2514, 825, 376, 814, + 376, 376, 820, 376, 815, 1001, 376, 994, 376, 1002, + + 996, 821, 816, 822, 817, 823, 867, 818, 376, 2514, + 819, 376, 376, 824, 2514, 376, 376, 826, 825, 1007, + 814, 376, 376, 820, 376, 815, 1001, 376, 522, 376, + 1002, 996, 821, 816, 822, 817, 823, 2514, 818, 376, + 522, 819, 492, 376, 824, 827, 376, 845, 826, 376, + 1007, 2514, 376, 376, 2514, 998, 376, 2514, 376, 376, + 828, 376, 2514, 376, 376, 830, 376, 1092, 992, 376, + 2514, 2514, 376, 376, 376, 1015, 827, 376, 832, 829, + 376, 833, 376, 835, 834, 831, 998, 836, 486, 376, + 486, 828, 376, 376, 376, 842, 830, 376, 1092, 992, + + 376, 842, 1069, 1003, 376, 376, 1015, 493, 1010, 832, + 829, 395, 833, 376, 835, 834, 831, 2514, 836, 376, + 2514, 2514, 376, 376, 376, 2514, 376, 376, 2514, 376, + 376, 376, 376, 376, 1003, 376, 837, 376, 493, 1010, + 376, 1006, 838, 752, 1093, 839, 1016, 750, 841, 750, + 2514, 2514, 457, 464, 2514, 2514, 464, 376, 2514, 2514, + 376, 842, 376, 376, 376, 842, 456, 837, 376, 842, + 456, 376, 1006, 838, 456, 1093, 839, 1016, 376, 841, + 458, 459, 460, 461, 462, 462, 462, 462, 462, 462, + 463, 748, 368, 456, 456, 456, 1036, 456, 456, 456, + + 746, 456, 456, 456, 2514, 2514, 746, 2514, 2514, 376, + 723, 358, 938, 737, 740, 842, 731, 734, 486, 2514, + 456, 711, 939, 469, 456, 728, 722, 1036, 456, 718, + 2514, 711, 456, 470, 471, 472, 473, 474, 474, 474, + 474, 474, 474, 475, 2514, 2514, 376, 456, 456, 456, + 469, 469, 469, 939, 469, 486, 2514, 2514, 698, 1022, + 469, 698, 711, 2514, 2514, 686, 682, 486, 944, 658, + 944, 2514, 469, 945, 486, 846, 661, 376, 456, 469, + 2514, 469, 711, 711, 376, 376, 376, 469, 469, 469, + 1022, 469, 711, 397, 1029, 967, 848, 1014, 1025, 469, + + 469, 469, 946, 469, 1094, 756, 469, 469, 469, 654, + 469, 648, 647, 629, 711, 376, 376, 376, 469, 847, + 2514, 627, 605, 711, 602, 1029, 601, 848, 1014, 1025, + 469, 849, 598, 946, 597, 1094, 756, 469, 593, 470, + 471, 472, 473, 474, 474, 474, 474, 474, 474, 475, + 847, 470, 471, 472, 473, 474, 474, 474, 474, 474, + 474, 475, 849, 470, 471, 472, 473, 474, 474, 474, + 474, 474, 474, 475, 850, 851, 376, 1023, 1021, 376, + 1026, 493, 376, 376, 376, 470, 471, 472, 473, 474, + 474, 474, 474, 474, 474, 475, 852, 1008, 1018, 1067, + + 1095, 1100, 1100, 1100, 579, 850, 851, 376, 1023, 1021, + 376, 1026, 493, 376, 376, 376, 470, 471, 472, 473, + 474, 474, 474, 474, 474, 474, 475, 852, 1008, 1018, + 1067, 1095, 470, 471, 472, 473, 474, 474, 474, 474, + 474, 474, 475, 853, 853, 853, 853, 853, 853, 853, + 853, 853, 853, 853, 470, 471, 472, 473, 474, 474, + 474, 474, 474, 474, 475, 470, 471, 472, 473, 474, + 474, 474, 474, 474, 474, 475, 492, 492, 492, 1096, + 580, 577, 1101, 576, 573, 572, 559, 494, 559, 494, + 495, 522, 522, 492, 486, 2514, 2514, 2514, 376, 376, + + 376, 496, 497, 376, 498, 1027, 524, 867, 478, 464, + 1096, 1020, 525, 499, 1031, 500, 1048, 501, 866, 866, + 866, 866, 866, 866, 866, 866, 866, 866, 866, 376, + 376, 376, 496, 497, 376, 498, 1027, 396, 395, 525, + 525, 525, 1020, 525, 499, 1031, 500, 1048, 501, 540, + 391, 2514, 245, 1102, 1102, 1102, 502, 503, 504, 505, + 506, 506, 506, 506, 506, 506, 507, 2514, 2514, 2514, + 525, 245, 1047, 376, 243, 1097, 376, 1051, 2514, 243, + 2514, 495, 526, 527, 528, 529, 530, 530, 530, 530, + 530, 530, 531, 2514, 2514, 2514, 2514, 2514, 2514, 1104, + + 1104, 1104, 376, 1047, 376, 867, 1097, 376, 1051, 1030, + 525, 533, 534, 535, 536, 537, 537, 537, 537, 537, + 537, 538, 541, 542, 543, 544, 545, 545, 545, 545, + 545, 545, 546, 376, 1103, 2514, 2514, 525, 525, 525, + 1030, 525, 1098, 2514, 2514, 2514, 2514, 502, 508, 504, + 505, 506, 506, 506, 506, 506, 506, 507, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 1034, 1034, 1034, 525, 2514, + 2514, 2514, 2514, 1098, 522, 2514, 2514, 2514, 493, 493, + 1105, 2514, 2514, 2514, 1073, 2514, 376, 867, 2514, 2514, + 2514, 376, 525, 867, 2514, 2514, 2514, 1037, 525, 559, + + 2514, 2514, 2514, 2514, 532, 1099, 493, 493, 493, 493, + 493, 559, 2514, 2514, 2514, 1073, 532, 376, 2514, 525, + 525, 525, 376, 525, 376, 525, 525, 525, 1037, 525, + 2514, 532, 532, 532, 376, 532, 1099, 493, 2514, 2514, + 1050, 1040, 1110, 532, 532, 532, 1035, 532, 2514, 559, + 525, 2514, 2514, 2514, 532, 376, 525, 2514, 376, 2514, + 2514, 2514, 532, 559, 2514, 376, 2514, 1044, 532, 1111, + 869, 1050, 1040, 1110, 532, 539, 2514, 2514, 2514, 2514, + 2514, 532, 532, 532, 2514, 532, 2514, 2514, 869, 376, + 2514, 2514, 493, 539, 2514, 532, 532, 532, 1044, 532, + + 1111, 2514, 539, 539, 539, 2514, 539, 711, 1042, 376, + 376, 1070, 532, 1117, 2514, 2514, 2514, 711, 1049, 1043, + 539, 539, 539, 493, 539, 869, 532, 2514, 2514, 2514, + 539, 947, 872, 539, 871, 493, 493, 1076, 869, 1042, + 376, 376, 1070, 539, 1117, 2514, 2514, 2514, 711, 1049, + 1043, 539, 2514, 2514, 2514, 2514, 1068, 539, 539, 539, + 2514, 539, 947, 872, 2514, 871, 493, 493, 1076, 1121, + 539, 539, 539, 2514, 539, 533, 534, 535, 536, 537, + 537, 537, 537, 537, 537, 538, 552, 1068, 539, 533, + 534, 535, 536, 537, 537, 537, 537, 537, 537, 538, + + 1121, 539, 875, 875, 875, 875, 875, 875, 875, 875, + 875, 875, 875, 2514, 553, 554, 555, 556, 557, 557, + 557, 557, 557, 557, 558, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 1130, 2514, 2514, 873, 2514, 2514, 873, + 2514, 551, 873, 2514, 551, 873, 2514, 551, 2514, 2514, + 551, 533, 534, 535, 536, 537, 537, 537, 537, 537, + 537, 538, 1148, 376, 1130, 2514, 1055, 1149, 551, 551, + 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, + 641, 642, 643, 644, 645, 645, 645, 645, 645, 645, + 646, 2514, 2514, 1148, 376, 2514, 2514, 1055, 1149, 551, + + 2514, 2514, 551, 913, 2514, 551, 654, 2514, 551, 632, + 632, 640, 1153, 632, 632, 2514, 2514, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 2514, 632, 632, 632, + 632, 632, 912, 1154, 913, 2514, 2514, 2514, 640, 640, + 640, 2514, 640, 1153, 1108, 908, 908, 641, 642, 643, + 644, 645, 645, 645, 645, 645, 645, 646, 632, 632, + 632, 2514, 632, 912, 1154, 2514, 1119, 919, 919, 640, + 641, 642, 643, 644, 645, 645, 645, 645, 645, 645, + 646, 2514, 1124, 924, 924, 2514, 2514, 2514, 2514, 632, + 634, 635, 636, 637, 638, 638, 638, 638, 638, 638, + + 639, 632, 632, 2514, 2514, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 906, 632, + 632, 632, 632, 632, 632, 1109, 2514, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 906, 632, 632, 632, 632, 2514, 2514, 1120, 1134, 936, + 936, 2514, 2514, 2514, 1155, 493, 654, 2514, 2514, 2514, + 2514, 640, 654, 1125, 2514, 2514, 1072, 640, 654, 2514, + 2514, 2514, 2514, 640, 917, 917, 917, 917, 917, 917, + 917, 917, 917, 917, 917, 1155, 493, 2514, 640, 640, + 640, 914, 640, 941, 640, 640, 640, 1072, 640, 1156, + + 640, 640, 640, 942, 640, 2514, 2514, 2514, 2514, 632, + 632, 2514, 632, 2514, 2514, 915, 2514, 1157, 686, 640, + 2514, 2514, 914, 675, 2514, 640, 2514, 2514, 2514, 1135, + 1156, 640, 2514, 2514, 942, 641, 642, 643, 644, 645, + 645, 645, 645, 645, 645, 646, 915, 916, 1157, 1166, + 675, 675, 675, 2514, 675, 641, 642, 643, 644, 645, + 645, 645, 645, 645, 645, 646, 641, 642, 643, 644, + 645, 645, 645, 645, 645, 645, 646, 2514, 916, 2514, + 1166, 675, 2514, 641, 642, 643, 644, 645, 645, 645, + 645, 645, 645, 646, 667, 667, 2514, 2514, 667, 667, + + 2514, 2514, 667, 667, 667, 667, 667, 667, 667, 667, + 667, 926, 667, 667, 667, 667, 667, 676, 677, 678, + 679, 680, 680, 680, 680, 680, 680, 681, 929, 929, + 929, 929, 929, 929, 929, 929, 929, 929, 929, 2514, + 376, 1177, 926, 667, 667, 667, 2514, 667, 2514, 676, + 677, 678, 679, 680, 680, 680, 680, 680, 680, 681, + 676, 677, 678, 679, 680, 680, 680, 680, 680, 680, + 681, 376, 1177, 2514, 667, 669, 670, 671, 672, 673, + 673, 673, 673, 673, 673, 674, 667, 667, 2514, 2514, + 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, + + 667, 667, 667, 922, 667, 667, 667, 667, 667, 667, + 2514, 2514, 667, 667, 667, 667, 667, 667, 667, 667, + 667, 667, 667, 667, 667, 922, 667, 667, 667, 667, + 2514, 2514, 2514, 723, 2514, 1136, 2514, 2514, 2514, 2514, + 2514, 686, 2514, 2514, 2514, 939, 675, 686, 2514, 2514, + 2514, 2514, 675, 686, 2514, 2514, 2514, 376, 675, 691, + 692, 693, 694, 695, 695, 695, 695, 695, 695, 696, + 1038, 1169, 1039, 675, 675, 675, 939, 675, 927, 675, + 675, 675, 711, 675, 376, 675, 675, 675, 376, 675, + 1146, 949, 949, 2514, 667, 667, 2514, 667, 928, 1144, + + 2514, 1038, 1169, 1039, 675, 2514, 2514, 2514, 2514, 927, + 675, 2514, 2514, 711, 2514, 376, 675, 2514, 676, 677, + 678, 679, 680, 680, 680, 680, 680, 680, 681, 928, + 1144, 1151, 953, 953, 676, 677, 678, 679, 680, 680, + 680, 680, 680, 680, 681, 2514, 2514, 2514, 965, 753, + 753, 2514, 2514, 2514, 1173, 376, 698, 2514, 2514, 2514, + 376, 690, 698, 2514, 2514, 2514, 2514, 690, 698, 2514, + 2514, 1147, 376, 690, 698, 2514, 2514, 2514, 376, 690, + 493, 397, 1045, 1159, 1046, 1173, 376, 1052, 690, 690, + 690, 376, 690, 756, 690, 690, 690, 930, 690, 1074, + + 690, 690, 690, 376, 690, 1178, 690, 690, 690, 376, + 690, 493, 1152, 1045, 2514, 1046, 2514, 2514, 1052, 690, + 2514, 2514, 2514, 2514, 756, 690, 2514, 2514, 930, 966, + 1074, 690, 2514, 2514, 2514, 2514, 1178, 690, 2514, 2514, + 2514, 691, 692, 693, 694, 695, 695, 695, 695, 695, + 695, 696, 931, 931, 931, 931, 931, 931, 931, 931, + 931, 931, 931, 691, 692, 693, 694, 695, 695, 695, + 695, 695, 695, 696, 703, 703, 2514, 2514, 703, 703, + 2514, 2514, 703, 703, 703, 703, 703, 703, 703, 703, + 703, 2514, 703, 703, 703, 703, 703, 712, 713, 714, + + 715, 716, 716, 716, 716, 716, 716, 717, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 376, + 376, 1164, 1171, 703, 703, 703, 2514, 703, 960, 960, + 960, 960, 960, 960, 960, 960, 960, 960, 960, 961, + 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, + 376, 376, 1164, 1171, 703, 705, 706, 707, 708, 709, + 709, 709, 709, 709, 709, 710, 703, 703, 2514, 2514, + 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, + 703, 703, 703, 933, 703, 703, 703, 703, 703, 703, + 2514, 2514, 703, 703, 703, 703, 703, 703, 703, 703, + + 703, 703, 703, 703, 703, 933, 703, 703, 703, 703, + 2514, 2514, 376, 376, 1165, 2514, 2514, 2514, 376, 1162, + 2514, 728, 2514, 2514, 2514, 1174, 711, 728, 2514, 2514, + 2514, 2514, 711, 728, 2514, 2514, 2514, 376, 711, 1172, + 376, 1187, 376, 376, 376, 1165, 728, 360, 2514, 376, + 1162, 711, 2514, 711, 711, 711, 1174, 711, 2514, 711, + 711, 711, 384, 711, 376, 711, 711, 711, 376, 711, + 1172, 376, 1187, 376, 703, 703, 1186, 703, 711, 711, + 711, 2514, 711, 376, 711, 1176, 2514, 1189, 2514, 2514, + 711, 762, 2514, 2514, 2514, 376, 711, 962, 962, 962, + + 962, 962, 962, 962, 962, 962, 962, 962, 2514, 711, + 723, 2514, 943, 2514, 376, 2514, 1176, 376, 1189, 376, + 1179, 1183, 725, 362, 363, 364, 365, 366, 366, 366, + 366, 366, 366, 367, 2514, 385, 386, 387, 388, 389, + 389, 389, 389, 389, 389, 390, 2514, 2514, 376, 2514, + 376, 1179, 1183, 725, 2514, 377, 378, 379, 380, 381, + 381, 381, 381, 381, 381, 382, 1281, 1100, 1100, 1108, + 908, 908, 2514, 1282, 2514, 2514, 712, 713, 714, 715, + 716, 716, 716, 716, 716, 716, 717, 368, 368, 2514, + 2514, 368, 368, 2514, 2514, 368, 368, 368, 368, 368, + + 368, 368, 368, 368, 376, 368, 368, 368, 368, 368, + 2514, 1175, 377, 378, 379, 380, 381, 381, 381, 381, + 381, 381, 382, 1056, 1056, 1056, 1056, 1056, 1056, 1056, + 1056, 1056, 1056, 1056, 1180, 376, 368, 368, 368, 2514, + 368, 1058, 1175, 2514, 2514, 2514, 2514, 1283, 2514, 376, + 1109, 376, 1163, 1184, 376, 376, 376, 376, 1053, 2514, + 2514, 376, 1054, 2514, 2514, 1180, 457, 368, 370, 371, + 372, 373, 374, 374, 374, 374, 374, 374, 375, 397, + 376, 973, 376, 1163, 1184, 376, 376, 376, 376, 1053, + 1059, 399, 376, 1054, 458, 459, 460, 461, 462, 462, + + 462, 462, 462, 462, 463, 470, 471, 472, 473, 474, + 474, 474, 474, 474, 474, 475, 2514, 2514, 2514, 2514, + 2514, 1059, 399, 470, 471, 472, 473, 474, 474, 474, + 474, 474, 474, 475, 1060, 1061, 1185, 2514, 376, 376, + 376, 1193, 1199, 376, 1188, 377, 378, 379, 380, 381, + 381, 381, 381, 381, 381, 382, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 1060, 1061, 1185, 974, 376, + 376, 376, 1193, 1199, 376, 1188, 470, 471, 472, 473, + 474, 474, 474, 474, 474, 474, 475, 1062, 470, 471, + 472, 473, 474, 474, 474, 474, 474, 474, 475, 974, + + 2514, 2514, 2514, 376, 1194, 1197, 376, 376, 376, 1063, + 1228, 2514, 2514, 2514, 2514, 1192, 2514, 524, 1062, 2514, + 2514, 2514, 377, 378, 379, 380, 381, 381, 381, 381, + 381, 381, 382, 1064, 376, 1194, 1197, 376, 376, 376, + 1063, 1228, 470, 471, 472, 473, 474, 474, 474, 474, + 474, 474, 475, 470, 471, 472, 473, 474, 474, 474, + 474, 474, 474, 475, 1064, 1077, 1077, 1077, 1077, 1077, + 1077, 1077, 1077, 1077, 1077, 1077, 2514, 2514, 2514, 2514, + 2514, 470, 471, 472, 473, 474, 474, 474, 474, 474, + 474, 475, 495, 526, 527, 528, 529, 530, 530, 530, + + 530, 530, 530, 531, 1078, 1078, 1078, 1078, 1078, 1078, + 1078, 1078, 1078, 1078, 1078, 1065, 540, 1081, 1081, 1081, + 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1079, + 2514, 376, 376, 1210, 376, 1226, 1065, 1122, 1122, 1122, + 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 502, 508, + 504, 505, 506, 506, 506, 506, 506, 506, 507, 495, + 1079, 1080, 376, 376, 1210, 376, 1226, 1066, 533, 534, + 535, 536, 537, 537, 537, 537, 537, 537, 538, 541, + 542, 543, 544, 545, 545, 545, 545, 545, 545, 546, + + 376, 1112, 1080, 1235, 2514, 2514, 2514, 2514, 1066, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 533, 534, + 535, 536, 537, 537, 537, 537, 537, 537, 538, 552, + 2514, 376, 1112, 2514, 1235, 502, 508, 504, 505, 506, + 506, 506, 506, 506, 506, 507, 641, 642, 643, 644, + 645, 645, 645, 645, 645, 645, 646, 553, 554, 555, + 556, 557, 557, 557, 557, 557, 557, 558, 632, 632, + 1116, 2514, 632, 632, 2514, 2514, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 1113, 632, 632, 632, 632, + 632, 376, 1208, 1227, 376, 1232, 1203, 376, 1182, 641, + + 642, 643, 644, 645, 645, 645, 645, 645, 645, 646, + 2514, 1114, 376, 376, 1212, 376, 1113, 632, 632, 632, + 2514, 632, 376, 1208, 1227, 376, 1232, 1203, 376, 1182, + 376, 641, 642, 643, 644, 645, 645, 645, 645, 645, + 645, 646, 1114, 376, 376, 1212, 376, 2514, 632, 634, + 635, 636, 637, 638, 638, 638, 638, 638, 638, 639, + 1115, 376, 1234, 493, 1252, 2514, 376, 1263, 641, 642, + 643, 644, 645, 645, 645, 645, 645, 645, 646, 1131, + 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, + 2514, 1115, 2514, 1234, 493, 1252, 1126, 376, 1263, 641, + + 642, 643, 644, 645, 645, 645, 645, 645, 645, 646, + 667, 667, 2514, 2514, 667, 667, 2514, 2514, 667, 667, + 667, 667, 667, 667, 667, 667, 667, 1126, 667, 667, + 667, 667, 667, 1127, 376, 1264, 1236, 2514, 1209, 2514, + 1195, 676, 677, 678, 679, 680, 680, 680, 680, 680, + 680, 681, 2514, 376, 1253, 376, 1265, 493, 1266, 667, + 667, 667, 2514, 667, 1127, 376, 1264, 1236, 2514, 1209, + 945, 1195, 676, 677, 678, 679, 680, 680, 680, 680, + 680, 680, 681, 1128, 376, 1253, 376, 1265, 493, 1266, + 667, 669, 670, 671, 672, 673, 673, 673, 673, 673, + + 673, 674, 1129, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 676, 677, 678, 679, 680, 680, 680, 680, + 680, 680, 681, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 1267, 1268, 2514, 1129, 712, 713, 714, 715, 716, 716, + 716, 716, 716, 716, 717, 2514, 2514, 2514, 691, 692, + 693, 694, 695, 695, 695, 695, 695, 695, 696, 703, + 703, 1267, 1268, 703, 703, 1269, 2514, 703, 703, 703, + 703, 703, 703, 703, 703, 703, 1170, 703, 703, 703, + 703, 703, 1167, 1181, 1196, 376, 1168, 1198, 1190, 1190, + 1190, 2514, 1200, 376, 1213, 376, 1269, 376, 376, 1206, + + 376, 376, 1270, 376, 1205, 1271, 376, 1170, 703, 703, + 703, 2514, 703, 1167, 1181, 1196, 376, 1168, 1198, 2514, + 1201, 1201, 1201, 1200, 376, 1213, 376, 376, 376, 376, + 1206, 376, 376, 1270, 376, 1205, 1271, 376, 2514, 703, + 705, 706, 707, 708, 709, 709, 709, 709, 709, 709, + 710, 723, 1204, 1142, 1207, 1211, 1214, 1215, 376, 376, + 1229, 1230, 376, 725, 1255, 376, 1233, 376, 2514, 1191, + 2514, 376, 376, 376, 493, 1224, 1224, 1224, 376, 2514, + 1272, 376, 1273, 1204, 2514, 1207, 1211, 1214, 1215, 2514, + 376, 1229, 1230, 376, 725, 1255, 376, 1233, 376, 2514, + + 2514, 1202, 376, 376, 376, 493, 2514, 2514, 2514, 376, + 464, 1272, 376, 1273, 376, 376, 1231, 712, 713, 714, + 715, 716, 716, 716, 716, 716, 716, 717, 2514, 376, + 1238, 1237, 2514, 1240, 1274, 1276, 1239, 1143, 1242, 1256, + 1257, 376, 376, 376, 376, 376, 376, 1231, 376, 376, + 376, 376, 493, 493, 493, 1244, 1225, 1277, 1278, 1279, + 376, 1238, 1237, 1254, 1240, 1274, 1276, 1239, 1143, 1242, + 1256, 1257, 376, 376, 2514, 1034, 2514, 1245, 1241, 376, + 376, 376, 376, 493, 493, 493, 2514, 376, 1277, 1278, + 1279, 2514, 2514, 2514, 712, 713, 714, 715, 716, 716, + + 716, 716, 716, 716, 717, 397, 2514, 1160, 1245, 1241, + 2514, 1289, 1104, 1104, 1246, 1290, 1260, 399, 376, 470, + 471, 472, 473, 474, 474, 474, 474, 474, 474, 475, + 493, 470, 471, 472, 473, 474, 474, 474, 474, 474, + 474, 475, 2514, 2514, 2514, 1246, 2514, 1260, 399, 470, + 471, 472, 473, 474, 474, 474, 474, 474, 474, 475, + 1247, 493, 1285, 1102, 1102, 1119, 919, 919, 2514, 1286, + 2514, 377, 378, 379, 380, 381, 381, 381, 381, 381, + 381, 382, 2514, 1248, 2514, 2514, 1124, 924, 924, 2514, + 2514, 1247, 1291, 2514, 470, 471, 472, 473, 474, 474, + + 474, 474, 474, 474, 475, 2514, 1292, 1161, 2514, 1302, + 2514, 1303, 470, 471, 472, 473, 474, 474, 474, 474, + 474, 474, 475, 470, 471, 472, 473, 474, 474, 474, + 474, 474, 474, 475, 1258, 1259, 495, 1292, 1161, 1250, + 1302, 493, 1303, 1287, 2514, 493, 1120, 2514, 377, 378, + 379, 380, 381, 381, 381, 381, 381, 381, 382, 1034, + 1034, 1034, 711, 2514, 2514, 1258, 1259, 1125, 1312, 2514, + 1311, 2514, 493, 2514, 2514, 2514, 493, 1368, 640, 2514, + 1216, 2514, 1370, 1217, 1218, 1371, 2514, 1372, 1373, 1134, + 936, 936, 1369, 711, 1219, 1220, 1221, 1249, 2514, 1312, + + 1222, 1311, 502, 508, 504, 505, 506, 506, 506, 506, + 506, 506, 507, 1370, 1217, 1218, 1371, 2514, 1372, 1373, + 2514, 2514, 2514, 1369, 1300, 1219, 1220, 1221, 1249, 1261, + 2514, 1222, 1146, 949, 949, 1151, 953, 953, 1262, 2514, + 1223, 1374, 470, 471, 472, 473, 474, 474, 474, 474, + 474, 474, 475, 495, 642, 2514, 2514, 2514, 533, 534, + 535, 536, 537, 537, 537, 537, 537, 537, 538, 1262, + 1135, 2514, 1374, 1375, 2514, 1294, 2514, 1418, 1419, 1251, + 691, 692, 693, 694, 695, 695, 695, 695, 695, 695, + 696, 2514, 533, 534, 535, 536, 537, 537, 537, 537, + + 537, 537, 538, 2514, 1375, 723, 1294, 1308, 1418, 1419, + 1251, 2514, 2514, 1147, 1421, 2514, 1152, 939, 1423, 502, + 508, 504, 505, 506, 506, 506, 506, 506, 506, 507, + 641, 642, 643, 644, 645, 645, 645, 645, 645, 645, + 646, 1295, 1295, 1295, 2514, 1421, 1296, 2514, 939, 1423, + 2514, 2514, 2514, 2514, 1297, 1424, 640, 2514, 2514, 2514, + 1305, 2514, 640, 397, 2514, 1314, 2514, 2514, 2514, 2514, + 2514, 2514, 493, 1299, 1410, 756, 2514, 2514, 2514, 493, + 493, 1301, 1425, 1411, 1304, 2514, 1424, 2514, 493, 676, + 677, 678, 679, 680, 680, 680, 680, 680, 680, 681, + + 1409, 1412, 1306, 493, 1299, 1410, 756, 2514, 2514, 2514, + 493, 493, 1301, 1425, 1411, 1304, 2514, 2514, 2514, 493, + 2514, 641, 1298, 643, 644, 645, 645, 645, 645, 645, + 645, 646, 642, 1306, 2514, 2514, 2514, 2514, 642, 676, + 677, 678, 679, 680, 680, 680, 680, 680, 680, 681, + 2514, 2514, 2514, 2514, 1318, 1427, 1429, 378, 676, 677, + 678, 679, 680, 680, 680, 680, 680, 680, 681, 723, + 2514, 1309, 2514, 1319, 1415, 2514, 2514, 2514, 2514, 493, + 1320, 725, 2514, 2514, 2514, 1318, 1427, 1429, 378, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 378, 2514, 2514, + + 2514, 2514, 2514, 2514, 1319, 1415, 2514, 2514, 2514, 2514, + 493, 1320, 725, 2514, 2514, 378, 1322, 1321, 1323, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 1430, 1325, 1431, 1324, + 2514, 378, 2514, 1328, 2514, 712, 713, 714, 715, 716, + 716, 716, 716, 716, 716, 717, 2514, 1322, 1321, 1323, + 2514, 2514, 2514, 493, 1310, 1326, 378, 1430, 1325, 1431, + 1324, 1327, 1432, 378, 1328, 2514, 2514, 2514, 2514, 2514, + 378, 2514, 2514, 2514, 1416, 378, 1329, 1434, 1435, 378, + 2514, 2514, 378, 2514, 493, 1310, 1326, 2514, 378, 2514, + 2514, 2514, 1327, 1432, 2514, 1330, 2514, 2514, 2514, 2514, + + 378, 2514, 2514, 378, 2514, 2514, 2514, 1329, 1434, 1435, + 2514, 1331, 712, 713, 714, 715, 716, 716, 716, 716, + 716, 716, 717, 397, 2514, 1315, 1330, 1333, 1456, 1491, + 1332, 378, 2514, 2514, 2514, 399, 2514, 2514, 2514, 2514, + 2514, 2514, 1331, 2514, 2514, 2514, 378, 2514, 2514, 2514, + 2514, 2514, 378, 1492, 2514, 1334, 2514, 2514, 1333, 1456, + 1491, 1332, 2514, 2514, 2514, 2514, 399, 2514, 2514, 2514, + 378, 2514, 2514, 2514, 2514, 1337, 1338, 1500, 378, 2514, + 2514, 2514, 2514, 2514, 1492, 378, 1334, 1335, 1339, 377, + 378, 379, 380, 381, 381, 381, 381, 381, 381, 382, + + 1316, 1316, 1316, 2514, 2514, 2514, 1337, 1338, 1500, 711, + 1190, 1190, 1190, 378, 2514, 2514, 2514, 378, 1336, 1339, + 378, 1340, 2514, 1464, 378, 2514, 2514, 2514, 378, 2514, + 2514, 2514, 2514, 2514, 2514, 1346, 1346, 1346, 1341, 2514, + 711, 464, 2514, 378, 2514, 1517, 376, 1342, 378, 2514, + 1347, 2514, 1340, 378, 1464, 2514, 2514, 2514, 2514, 2514, + 2514, 378, 1344, 2514, 2514, 2514, 2514, 2514, 2514, 1341, + 2514, 2514, 2514, 376, 376, 376, 1517, 376, 1342, 1518, + 377, 1317, 379, 380, 381, 381, 381, 381, 381, 381, + 382, 1343, 1519, 1344, 1345, 1349, 2514, 2514, 2514, 1351, + + 2514, 2514, 2514, 2514, 376, 2514, 1190, 1201, 1201, 1201, + 1518, 2514, 2514, 378, 1520, 2514, 1348, 1356, 1356, 1356, + 2514, 1522, 464, 1519, 2514, 1345, 1349, 376, 2514, 2514, + 1351, 493, 1350, 2514, 2514, 2514, 378, 2514, 2514, 378, + 1524, 1352, 1413, 1527, 1353, 1520, 378, 2514, 2514, 2514, + 2514, 378, 1522, 2514, 376, 376, 376, 2514, 376, 2514, + 2514, 2514, 493, 1350, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 1524, 1352, 1413, 1527, 1353, 2514, 378, 2514, 2514, + 2514, 378, 1361, 1361, 1361, 376, 1355, 1201, 1354, 2514, + 2514, 2514, 2514, 1359, 2514, 2514, 2514, 2514, 1357, 2514, + + 2514, 2514, 1360, 2514, 1358, 2514, 2514, 2514, 1514, 2514, + 2514, 2514, 1515, 1516, 378, 1363, 1364, 1355, 2514, 2514, + 2514, 2514, 2514, 2514, 1359, 2514, 2514, 2514, 378, 2514, + 2514, 2514, 2514, 1360, 1365, 1358, 493, 1528, 2514, 1514, + 378, 1366, 1414, 1515, 1516, 378, 1363, 1364, 378, 2514, + 1367, 1531, 2514, 2514, 2514, 2514, 2514, 2514, 1390, 378, + 2514, 2514, 2514, 1362, 464, 1365, 2514, 493, 1528, 376, + 378, 2514, 1366, 1414, 2514, 378, 2514, 2514, 2514, 2514, + 378, 1367, 1531, 2514, 2514, 2514, 378, 2514, 2514, 1390, + 378, 1224, 1224, 1224, 2514, 1391, 376, 376, 376, 378, + + 376, 2514, 378, 2514, 2514, 2514, 378, 1532, 1392, 2514, + 378, 2514, 2514, 2514, 1376, 1377, 1378, 1379, 1380, 1381, + 2514, 1382, 1533, 1383, 1534, 1384, 1391, 376, 1385, 1224, + 1535, 1386, 1387, 2514, 2514, 1388, 378, 2514, 1532, 1392, + 2514, 2514, 2514, 2514, 2514, 1376, 1377, 1378, 1379, 1380, + 1381, 1398, 1382, 1533, 1383, 1534, 1384, 378, 723, 1385, + 1461, 1535, 1386, 1387, 378, 1397, 1388, 2514, 2514, 2514, + 939, 2514, 1389, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 1398, 711, 378, 2514, 2514, 2514, 397, 1393, + 1466, 2514, 378, 2514, 1463, 1394, 1397, 2514, 2514, 2514, + + 756, 939, 1395, 1402, 1525, 1396, 1536, 1526, 1399, 2514, + 2514, 2514, 2514, 2514, 711, 1529, 1537, 2514, 2514, 1539, + 1393, 378, 1281, 1100, 1100, 1463, 1394, 1530, 1555, 1282, + 1538, 756, 1400, 1395, 1403, 1525, 1396, 1536, 1526, 1399, + 2514, 2514, 1285, 1102, 1102, 2514, 1529, 1537, 378, 1286, + 1539, 2514, 2514, 2514, 378, 2514, 2514, 378, 1530, 1555, + 378, 1538, 2514, 1400, 2514, 1403, 378, 470, 471, 472, + 473, 474, 474, 474, 474, 474, 474, 475, 378, 470, + 471, 472, 473, 474, 474, 474, 474, 474, 474, 475, + 378, 470, 471, 472, 473, 474, 474, 474, 474, 474, + + 474, 475, 1404, 1283, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 1405, 533, 534, 535, 536, 537, 537, 537, 537, + 537, 537, 538, 1287, 493, 493, 1406, 2514, 2514, 2514, + 2514, 470, 471, 472, 473, 474, 474, 474, 474, 474, + 474, 475, 1405, 1289, 1104, 1104, 1559, 1290, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 493, 493, 1406, 2514, 2514, + 2514, 1436, 2514, 2514, 2514, 2514, 2514, 470, 471, 472, + 473, 474, 474, 474, 474, 474, 474, 475, 470, 471, + 472, 473, 474, 474, 474, 474, 474, 474, 475, 495, + 641, 642, 643, 644, 645, 645, 645, 645, 645, 645, + + 646, 2514, 723, 1553, 1462, 1471, 493, 493, 378, 2514, + 711, 1478, 1478, 1478, 725, 1557, 1407, 2514, 1556, 1417, + 1558, 2514, 493, 1561, 1291, 2514, 1479, 1295, 1295, 1295, + 378, 2514, 1437, 378, 1553, 2514, 1471, 493, 493, 378, + 1297, 711, 2514, 2514, 378, 725, 1557, 1407, 1453, 1556, + 1417, 1558, 1438, 493, 1561, 502, 508, 504, 505, 506, + 506, 506, 506, 506, 506, 507, 495, 533, 534, 535, + 536, 537, 537, 537, 537, 537, 537, 538, 1563, 1453, + 1564, 1565, 1408, 1438, 2514, 1457, 2514, 2514, 2514, 2514, + 2514, 2514, 1480, 2514, 1569, 641, 642, 643, 644, 645, + + 645, 645, 645, 645, 645, 646, 2514, 2514, 1439, 1563, + 2514, 1564, 1565, 1408, 676, 677, 678, 679, 680, 680, + 680, 680, 680, 680, 681, 1569, 2514, 2514, 2514, 2514, + 2514, 2514, 502, 508, 504, 505, 506, 506, 506, 506, + 506, 506, 507, 1440, 1441, 1295, 1295, 1440, 1440, 1442, + 1443, 1440, 1440, 1440, 1440, 1440, 1440, 1444, 1440, 1440, + 1443, 1440, 1440, 1440, 1440, 1440, 1443, 1443, 1443, 1445, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1440, 1440, 1440, 1443, 1440, 1443, 1443, 1443, + + 1445, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1440, 1446, 1447, 1448, 1449, 1450, 1450, + 1450, 1450, 1450, 1450, 1451, 2514, 2514, 1454, 1570, 2514, + 2514, 2514, 2514, 2514, 2514, 1571, 654, 1316, 1316, 1316, + 2514, 640, 2514, 2514, 1455, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 1454, 1570, + 2514, 1488, 1488, 1488, 2514, 2514, 1571, 2514, 640, 640, + 640, 1458, 640, 1472, 1468, 1455, 1489, 641, 642, 643, + 644, 645, 645, 645, 645, 645, 645, 646, 641, 642, + + 643, 644, 645, 645, 645, 645, 645, 645, 646, 640, + 2514, 1295, 1458, 1459, 1472, 1468, 2514, 2514, 2514, 2514, + 378, 2514, 1572, 378, 2514, 2514, 2514, 2514, 1469, 2514, + 2514, 676, 677, 678, 679, 680, 680, 680, 680, 680, + 680, 681, 378, 1470, 1459, 378, 2514, 2514, 2514, 2514, + 2514, 2514, 1490, 1572, 2514, 2514, 2514, 676, 677, 678, + 679, 680, 680, 680, 680, 680, 680, 681, 397, 2514, + 1467, 2514, 2514, 2514, 1470, 2514, 2514, 2514, 2514, 2514, + 399, 2514, 1573, 464, 2514, 2514, 2514, 1473, 376, 2514, + 1474, 2514, 2514, 2514, 1574, 2514, 2514, 2514, 378, 2514, + + 1475, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 1576, 2514, + 1476, 399, 1577, 1573, 1481, 376, 376, 376, 1473, 376, + 1477, 1474, 2514, 2514, 2514, 1574, 2514, 378, 1482, 2514, + 378, 1475, 2514, 2514, 2514, 378, 2514, 2514, 2514, 1576, + 1483, 1476, 1578, 1577, 1484, 1481, 376, 2514, 1316, 2514, + 2514, 1477, 2514, 2514, 2514, 2514, 2514, 378, 2514, 1482, + 2514, 2514, 2514, 2514, 2514, 378, 1494, 1486, 2514, 2514, + 2514, 1483, 378, 1578, 2514, 1484, 378, 2514, 2514, 2514, + 1346, 1346, 1346, 378, 2514, 2514, 378, 2514, 2514, 2514, + 1554, 1485, 2514, 2514, 2514, 1347, 493, 1494, 1486, 1487, + + 1560, 1498, 2514, 378, 464, 2514, 2514, 2514, 493, 376, + 2514, 1583, 1493, 378, 2514, 2514, 2514, 378, 2514, 2514, + 2514, 1554, 1485, 1356, 1356, 1356, 1585, 493, 1497, 1566, + 1487, 1560, 1498, 378, 1567, 1499, 376, 376, 376, 493, + 376, 378, 1583, 1493, 1501, 711, 1502, 2514, 2514, 378, + 2514, 2514, 2514, 1606, 2514, 2514, 2514, 1585, 378, 1497, + 1566, 1495, 2514, 2514, 2514, 1567, 1499, 376, 378, 1346, + 2514, 2514, 711, 464, 2514, 1501, 711, 1502, 376, 1504, + 1505, 1361, 1361, 1361, 1606, 1602, 378, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 378, 2514, 2514, 2514, 378, + + 2514, 2514, 2514, 711, 1503, 376, 376, 376, 2514, 376, + 1504, 1505, 2514, 2514, 1508, 1506, 1602, 1511, 1511, 1511, + 2514, 2514, 1509, 464, 2514, 2514, 2514, 1620, 376, 2514, + 1621, 378, 1512, 2514, 2514, 378, 376, 2514, 1356, 2514, + 2514, 2514, 1510, 2514, 2514, 1508, 1506, 2514, 2514, 2514, + 2514, 2514, 2514, 1509, 1628, 376, 376, 376, 1620, 376, + 1540, 1621, 1507, 2514, 2514, 2514, 1629, 2514, 378, 2514, + 2514, 378, 1633, 1510, 2514, 2514, 2514, 378, 1543, 1543, + 1543, 378, 2514, 2514, 2514, 1628, 376, 1541, 1361, 2514, + 1641, 1540, 1642, 1544, 2514, 2514, 2514, 1629, 1513, 2514, + + 2514, 2514, 2514, 1633, 723, 378, 1600, 1643, 1546, 2514, + 2514, 2514, 1644, 2514, 1645, 1542, 939, 723, 1541, 1601, + 378, 1641, 1646, 1642, 2514, 711, 1647, 1550, 378, 725, + 397, 378, 1604, 1547, 1592, 1592, 1592, 1548, 1643, 1546, + 1648, 1649, 756, 1644, 378, 1645, 1542, 939, 1650, 1651, + 2514, 2514, 1652, 1646, 2514, 378, 711, 1647, 1653, 1545, + 725, 2514, 2514, 378, 1547, 2514, 2514, 2514, 1548, 2514, + 2514, 1648, 1649, 756, 2514, 378, 2514, 2514, 2514, 1650, + 1651, 378, 1551, 1652, 2514, 2514, 2514, 2514, 1552, 1653, + 378, 470, 471, 472, 473, 474, 474, 474, 474, 474, + + 474, 475, 470, 471, 472, 473, 474, 474, 474, 474, + 474, 474, 475, 1551, 2514, 1593, 2514, 2514, 2514, 1552, + 2514, 470, 471, 472, 473, 474, 474, 474, 474, 474, + 474, 475, 470, 471, 472, 473, 474, 474, 474, 474, + 474, 474, 475, 470, 471, 472, 473, 474, 474, 474, + 474, 474, 474, 475, 1562, 1579, 1654, 378, 2514, 2514, + 2514, 1655, 1656, 1441, 1295, 1295, 378, 2514, 1580, 1441, + 1295, 1295, 2514, 2514, 1580, 2514, 1444, 2514, 2514, 2514, + 2514, 2514, 1444, 2514, 2514, 1562, 1579, 1654, 1581, 2514, + 2514, 2514, 1655, 1656, 1581, 2514, 641, 642, 643, 644, + + 645, 645, 645, 645, 645, 645, 646, 1608, 533, 534, + 535, 536, 537, 537, 537, 537, 537, 537, 538, 1581, + 1657, 1441, 1295, 1295, 2514, 1581, 1580, 1441, 1295, 1295, + 2514, 1658, 1580, 1659, 1444, 2514, 2514, 2514, 1608, 378, + 1584, 2514, 2514, 2514, 1582, 2514, 1581, 2514, 2514, 2514, + 1582, 1657, 1581, 2514, 2514, 1441, 1295, 1295, 378, 2514, + 1580, 397, 1658, 1605, 1659, 1660, 1661, 1609, 1444, 2514, + 378, 1586, 1662, 399, 1663, 1664, 1607, 1581, 2514, 2514, + 1581, 1665, 1666, 1581, 641, 642, 643, 644, 645, 645, + 645, 645, 645, 645, 646, 1594, 1660, 1661, 1609, 1478, + + 1478, 1478, 1582, 1662, 399, 1663, 1664, 1607, 1582, 1580, + 1440, 1581, 1665, 1666, 1479, 2514, 378, 2514, 2514, 2514, + 1586, 2514, 378, 2514, 1595, 1443, 1594, 2514, 378, 1688, + 493, 2514, 2514, 2514, 2514, 2514, 1582, 2514, 2514, 2514, + 641, 642, 643, 644, 645, 645, 645, 645, 645, 645, + 646, 1679, 1443, 1443, 1443, 1595, 1443, 2514, 2514, 2514, + 1688, 493, 641, 642, 643, 644, 645, 645, 645, 645, + 645, 645, 646, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 1611, 2514, 2514, 1443, 1443, 1587, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1440, 1441, 1295, 1295, 1440, + + 1440, 1580, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1444, + 1440, 1440, 1586, 1440, 1440, 1440, 1440, 1596, 378, 1690, + 1691, 1590, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 378, 2514, + 1597, 2514, 2514, 2514, 1610, 1692, 2514, 2514, 1596, 2514, + 1690, 1691, 1590, 2514, 378, 1488, 1488, 1488, 676, 677, + 678, 679, 680, 680, 680, 680, 680, 680, 681, 1598, + 1489, 1597, 2514, 2514, 2514, 1610, 1692, 1591, 2514, 2514, + 2514, 1440, 1440, 2514, 1440, 676, 677, 678, 679, 680, + 680, 680, 680, 680, 680, 681, 2514, 2514, 2514, 2514, + + 1598, 2514, 1617, 378, 1613, 2514, 378, 676, 677, 678, + 679, 680, 680, 680, 680, 680, 680, 681, 2514, 2514, + 1614, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 464, + 2514, 2514, 2514, 1617, 376, 1613, 1618, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 1614, 1616, 378, 2514, 2514, 2514, 1615, 2514, 378, + 2514, 376, 376, 376, 1622, 376, 1630, 1630, 1630, 2514, + 2514, 2514, 1693, 1623, 2514, 493, 1627, 378, 2514, 2514, + 464, 1631, 2514, 1616, 1678, 376, 1634, 2514, 1615, 2514, + 2514, 2514, 376, 2514, 1478, 1622, 2514, 2514, 2514, 2514, + + 2514, 1694, 378, 1693, 1623, 378, 493, 1627, 2514, 2514, + 2514, 378, 376, 376, 376, 1678, 376, 1634, 378, 2514, + 2514, 378, 2514, 2514, 378, 493, 2514, 378, 2514, 2514, + 2514, 1635, 1694, 2514, 2514, 378, 1511, 1511, 1511, 2514, + 2514, 1681, 2514, 376, 1695, 1488, 2514, 1632, 2514, 1667, + 464, 1512, 1543, 1543, 1543, 376, 493, 1636, 2514, 2514, + 2514, 1637, 1635, 2514, 2514, 2514, 2514, 1544, 1696, 1668, + 378, 1697, 1681, 1638, 1680, 1695, 2514, 378, 2514, 493, + 1667, 2514, 376, 376, 376, 2514, 376, 2514, 2514, 378, + 1669, 2514, 1637, 2514, 2514, 2514, 2514, 2514, 464, 1696, + + 1668, 2514, 1697, 376, 1638, 1680, 2514, 2514, 2514, 378, + 493, 1682, 1683, 376, 2514, 1511, 493, 1639, 2514, 1672, + 493, 1669, 1684, 1685, 1675, 1698, 1699, 493, 493, 1700, + 376, 376, 376, 1670, 376, 1686, 1701, 1702, 1703, 378, + 493, 1706, 1682, 1683, 1710, 378, 1673, 493, 2514, 1676, + 1672, 493, 1585, 1684, 1685, 711, 1698, 1699, 493, 493, + 1700, 376, 2514, 1543, 2514, 2514, 1686, 1701, 1702, 1703, + 2514, 493, 1706, 2514, 378, 1710, 2514, 1673, 2514, 1677, + 1676, 2514, 1731, 1585, 1746, 2514, 711, 378, 470, 471, + 472, 473, 474, 474, 474, 474, 474, 474, 475, 470, + + 471, 472, 473, 474, 474, 474, 474, 474, 474, 475, + 1677, 1687, 1704, 1731, 2514, 1746, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 470, 471, 472, 473, 474, 474, + 474, 474, 474, 474, 475, 2514, 2514, 2514, 2514, 1747, + 1755, 2514, 1687, 1704, 2514, 533, 534, 535, 536, 537, + 537, 537, 537, 537, 537, 538, 641, 642, 643, 644, + 645, 645, 645, 645, 645, 645, 646, 1441, 1295, 1295, + 1747, 1755, 1580, 1441, 1295, 1295, 2514, 2514, 1580, 2514, + 1444, 2514, 1441, 1295, 1295, 2514, 1444, 1580, 1707, 1708, + 1708, 2514, 1581, 1580, 723, 1444, 1726, 378, 1581, 2514, + + 397, 1584, 1729, 1441, 1295, 1295, 939, 1581, 1580, 1715, + 1708, 1708, 756, 1581, 1716, 1705, 1444, 378, 723, 2514, + 1727, 2514, 1717, 1581, 1756, 2514, 711, 1759, 1581, 1581, + 725, 2514, 2514, 1761, 1718, 2514, 2514, 939, 1581, 2514, + 2514, 2514, 1762, 756, 1581, 1763, 1705, 1768, 1582, 2514, + 2514, 2514, 2514, 2514, 1582, 1756, 1720, 711, 1759, 1581, + 2514, 725, 1721, 1588, 1761, 1718, 2514, 2514, 2514, 1709, + 1441, 1295, 1295, 1762, 2514, 1580, 1763, 2514, 1768, 2514, + 397, 2514, 1730, 1444, 1588, 2514, 2514, 1720, 1722, 1770, + 1719, 1735, 399, 1721, 1773, 1581, 641, 642, 643, 644, + + 645, 645, 645, 645, 645, 645, 646, 641, 642, 643, + 644, 645, 645, 645, 645, 645, 645, 646, 1774, 1722, + 1770, 2514, 1735, 399, 2514, 1773, 1581, 2514, 2514, 2514, + 1723, 378, 676, 677, 678, 679, 680, 680, 680, 680, + 680, 680, 681, 2514, 2514, 2514, 2514, 378, 2514, 1774, + 1711, 1712, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, + 1711, 1723, 1724, 2514, 2514, 2514, 2514, 2514, 2514, 1732, + 676, 677, 678, 679, 680, 680, 680, 680, 680, 680, + 681, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 1724, 2514, 2514, 2514, 2514, 1775, 1733, + + 1732, 1734, 2514, 2514, 2514, 2514, 2514, 676, 677, 678, + 679, 680, 680, 680, 680, 680, 680, 681, 1739, 1771, + 1748, 1776, 1777, 1741, 378, 1740, 2514, 2514, 2514, 1775, + 1733, 2514, 1734, 1780, 1751, 1751, 1751, 1772, 1742, 2514, + 2514, 2514, 1781, 2514, 378, 2514, 2514, 378, 2514, 1739, + 1771, 1748, 1776, 1777, 1741, 1778, 1740, 1630, 1630, 1630, + 1782, 1783, 378, 1752, 1780, 1749, 1779, 378, 1772, 1742, + 378, 1784, 1631, 1781, 1754, 378, 2514, 2514, 2514, 2514, + 2514, 1785, 1786, 378, 2514, 1787, 1778, 1788, 2514, 2514, + 464, 1782, 1783, 2514, 1752, 376, 1749, 1779, 1789, 1792, + + 1790, 1793, 1784, 1794, 1795, 1754, 1802, 378, 2514, 2514, + 2514, 2514, 1785, 1786, 2514, 1753, 1787, 1760, 1788, 2514, + 378, 1791, 376, 376, 376, 2514, 376, 1806, 493, 1789, + 1792, 1790, 1793, 493, 1794, 1795, 493, 493, 1757, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 1760, 2514, + 2514, 2514, 1791, 376, 1805, 1630, 1803, 378, 1806, 493, + 2514, 493, 493, 493, 493, 1807, 1810, 493, 493, 1796, + 470, 471, 472, 473, 474, 474, 474, 474, 474, 474, + 475, 2514, 1811, 1808, 1812, 1800, 1813, 1803, 1815, 378, + 493, 1804, 493, 493, 493, 2514, 1807, 1810, 1816, 2514, + + 1796, 2514, 470, 471, 472, 473, 474, 474, 474, 474, + 474, 474, 475, 1811, 1808, 1812, 1800, 1813, 2514, 1815, + 378, 493, 1804, 378, 1817, 1818, 378, 1819, 1821, 1816, + 378, 470, 471, 472, 473, 474, 474, 474, 474, 474, + 474, 475, 533, 534, 535, 536, 537, 537, 537, 537, + 537, 537, 538, 1829, 2514, 1817, 1818, 1848, 1819, 1821, + 2514, 1863, 2514, 641, 642, 643, 644, 645, 645, 645, + 645, 645, 645, 646, 1441, 1295, 1295, 2514, 1864, 1580, + 1823, 1708, 1708, 2514, 1829, 1824, 2514, 1444, 1848, 1715, + 1708, 1708, 1863, 1825, 1716, 1869, 1820, 1870, 2514, 1581, + + 2514, 723, 1717, 1843, 2514, 1826, 1441, 1295, 1295, 1864, + 2514, 1580, 1871, 939, 1718, 2514, 1441, 1295, 1295, 1444, + 2514, 1580, 2514, 2514, 2514, 2514, 1869, 1820, 1870, 1444, + 1581, 1581, 1443, 1441, 1295, 1295, 1826, 2514, 1580, 2514, + 2514, 1581, 2514, 1871, 939, 1718, 1444, 2514, 2514, 1443, + 2514, 1830, 1295, 1295, 2514, 1582, 1716, 1875, 1581, 1876, + 2514, 1827, 1581, 2514, 1717, 2514, 1715, 1708, 1708, 2514, + 1719, 1716, 1581, 1832, 1295, 1295, 1718, 2514, 1824, 1717, + 1830, 1295, 1295, 2514, 2514, 1716, 1825, 1828, 1875, 1581, + 1876, 1718, 2514, 1834, 2514, 2514, 2514, 1582, 1826, 1830, + + 1295, 1295, 2514, 378, 1716, 1718, 2514, 1718, 1830, 1295, + 1295, 2514, 1717, 1716, 1588, 397, 2514, 1846, 1877, 1878, + 1851, 1717, 1718, 723, 1718, 1844, 1883, 756, 1884, 1826, + 2514, 711, 1831, 1718, 1885, 725, 1718, 1837, 1886, 1887, + 2514, 1835, 2514, 2514, 2514, 1888, 2514, 1719, 1889, 1877, + 1878, 1851, 1892, 1893, 1833, 1718, 1894, 1883, 756, 1884, + 2514, 1831, 711, 2514, 1718, 1885, 725, 2514, 1837, 1886, + 1887, 1838, 1835, 2514, 2514, 378, 1888, 1849, 1895, 1889, + 1831, 2514, 2514, 1892, 1893, 2514, 2514, 1894, 2514, 1836, + 1839, 641, 642, 643, 644, 645, 645, 645, 645, 645, + + 645, 646, 1838, 2514, 2514, 2514, 1840, 1841, 1849, 1895, + 641, 642, 643, 644, 645, 645, 645, 645, 645, 645, + 646, 1839, 2514, 378, 2514, 2514, 676, 677, 678, 679, + 680, 680, 680, 680, 680, 680, 681, 1840, 1841, 2514, + 2514, 2514, 2514, 1896, 1850, 2514, 676, 677, 678, 679, + 680, 680, 680, 680, 680, 680, 681, 2514, 2514, 2514, + 676, 677, 678, 679, 680, 680, 680, 680, 680, 680, + 681, 397, 2514, 1847, 1896, 1850, 1853, 1853, 1853, 2514, + 2514, 2514, 1897, 399, 378, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 1860, 1860, 1860, 2514, 2514, 2514, 2514, 2514, + + 2514, 1867, 1867, 1867, 1898, 1854, 2514, 2514, 1751, 1751, + 1751, 1857, 1899, 1897, 399, 2514, 1347, 1900, 1901, 1856, + 378, 1861, 2514, 2514, 2514, 1904, 2514, 1858, 1866, 2514, + 2514, 2514, 1905, 1906, 1865, 1898, 1854, 1752, 378, 1890, + 1890, 1890, 1857, 1899, 1907, 1880, 1880, 1880, 1900, 1901, + 1856, 2514, 1861, 1902, 1902, 1902, 1904, 1855, 1858, 1866, + 378, 1908, 1909, 1905, 1906, 1865, 378, 1910, 1752, 378, + 1911, 1912, 2514, 1862, 1881, 1907, 378, 2514, 2514, 378, + 493, 2514, 1868, 2514, 2514, 2514, 1915, 1915, 1915, 1753, + 1922, 1926, 1908, 1909, 2514, 2514, 2514, 1920, 1910, 1923, + + 1927, 1911, 1912, 378, 493, 1881, 2514, 1928, 493, 1924, + 378, 493, 1919, 493, 1930, 1916, 1931, 1932, 1933, 1913, + 1891, 1922, 1926, 2514, 2514, 2514, 1882, 2514, 1920, 1925, + 1923, 1927, 1957, 2514, 1903, 493, 2514, 1921, 1928, 493, + 1924, 2514, 2514, 1960, 493, 1930, 1916, 1931, 1932, 1933, + 1913, 470, 471, 472, 473, 474, 474, 474, 474, 474, + 474, 475, 2514, 1957, 378, 2514, 2514, 1917, 1921, 2514, + 2514, 2514, 2514, 1938, 1960, 378, 470, 471, 472, 473, + 474, 474, 474, 474, 474, 474, 475, 470, 471, 472, + 473, 474, 474, 474, 474, 474, 474, 475, 1934, 1934, + + 1934, 2514, 2514, 2514, 1938, 1964, 2514, 2514, 2514, 2514, + 2514, 1965, 1935, 641, 642, 643, 644, 645, 645, 645, + 645, 645, 645, 646, 1441, 1295, 1295, 2514, 1966, 1580, + 1832, 1295, 1295, 2514, 2514, 1824, 1964, 1444, 2514, 1823, + 1708, 1708, 1965, 1825, 1824, 1832, 1295, 1295, 2514, 1581, + 1824, 378, 1825, 1969, 723, 1826, 1952, 1939, 1825, 1966, + 1832, 1295, 1295, 2514, 1826, 1824, 939, 1970, 1975, 397, + 1826, 1955, 1976, 1940, 2514, 1853, 1853, 1853, 2514, 1936, + 1581, 756, 378, 2514, 1969, 1826, 1826, 378, 1939, 1832, + 1295, 1295, 2514, 2514, 1824, 1826, 1977, 939, 1970, 1975, + + 2514, 1826, 1825, 1976, 1854, 1582, 1978, 2514, 1832, 1295, + 1295, 1833, 756, 1824, 1826, 1981, 1826, 1823, 1708, 1708, + 1827, 1825, 1824, 1830, 1295, 1295, 1833, 1977, 1716, 1982, + 1825, 1941, 2514, 1826, 2514, 1854, 1717, 1978, 1830, 1295, + 1295, 1833, 1826, 1716, 2514, 1826, 1981, 723, 1718, 1953, + 1983, 1717, 1832, 1295, 1295, 711, 1855, 1824, 2514, 725, + 1982, 2514, 1941, 1718, 1826, 1825, 1984, 1832, 1295, 1295, + 1833, 2514, 1824, 1826, 2514, 2514, 2514, 1826, 1985, 1718, + 1825, 1983, 1715, 1708, 1708, 2514, 711, 1716, 2514, 1942, + 725, 2514, 1826, 1986, 1718, 1834, 1987, 1984, 1943, 2514, + + 1830, 1295, 1295, 2514, 1831, 1716, 1988, 1718, 1826, 1985, + 2514, 1989, 1990, 1717, 1991, 1715, 1708, 1708, 1992, 1944, + 1716, 1993, 1946, 1826, 1986, 1718, 1994, 1987, 1717, 1958, + 1958, 1958, 2514, 1833, 2514, 2514, 2514, 1988, 1718, 1995, + 1718, 1948, 1989, 1990, 1479, 1991, 2514, 1996, 1945, 1992, + 2514, 2514, 1993, 1946, 2514, 378, 1718, 1994, 1962, 1962, + 1962, 2514, 1997, 1719, 1867, 1867, 1867, 2514, 2514, 2514, + 1995, 1718, 1948, 1489, 2514, 2514, 2514, 1949, 1996, 1347, + 2514, 1831, 641, 642, 643, 644, 645, 645, 645, 645, + 645, 645, 646, 1997, 2514, 2514, 1947, 641, 642, 643, + + 644, 645, 645, 645, 645, 645, 645, 646, 1949, 1950, + 1959, 2514, 2514, 2514, 2514, 378, 2514, 676, 677, 678, + 679, 680, 680, 680, 680, 680, 680, 681, 676, 677, + 678, 679, 680, 680, 680, 680, 680, 680, 681, 1963, + 1950, 1961, 1860, 1860, 1860, 1868, 1998, 2514, 2514, 2514, + 676, 677, 678, 679, 680, 680, 680, 680, 680, 680, + 681, 397, 2514, 1956, 2514, 2514, 2514, 2514, 2514, 2514, + 2002, 1861, 1961, 399, 1972, 1972, 1972, 1998, 1979, 1979, + 1979, 1880, 1880, 1880, 1890, 1890, 1890, 2003, 1902, 1902, + 1902, 2004, 378, 1512, 2005, 2014, 2015, 2514, 2514, 2016, + + 2017, 2002, 1861, 1973, 399, 1967, 2021, 493, 1968, 493, + 1881, 2028, 1999, 2514, 2514, 2000, 2514, 2514, 2003, 2514, + 2514, 2514, 2004, 1862, 2514, 2005, 2014, 2015, 378, 2001, + 2016, 2017, 2029, 493, 1973, 2030, 1967, 2021, 493, 1968, + 493, 1881, 2028, 1999, 2026, 378, 2000, 493, 378, 2514, + 2514, 2514, 2019, 2019, 2019, 1974, 2514, 2027, 2514, 1980, + 2001, 2031, 1882, 2029, 493, 1891, 2030, 1544, 2032, 1903, + 2006, 1915, 1915, 1915, 2023, 2026, 2007, 2514, 493, 2036, + 2008, 2009, 2047, 2049, 2018, 2010, 2011, 2012, 2027, 2013, + 2051, 723, 2031, 2042, 1934, 1934, 1934, 2048, 2052, 2032, + + 1916, 2006, 2514, 939, 2514, 2514, 2514, 2007, 1935, 2514, + 2036, 2008, 2009, 2047, 2049, 2018, 2010, 2011, 2012, 2024, + 2013, 2051, 2053, 2056, 2057, 2060, 2061, 2062, 2048, 2052, + 378, 1916, 2514, 2020, 939, 2033, 2033, 2033, 470, 471, + 472, 473, 474, 474, 474, 474, 474, 474, 475, 2025, + 2024, 2063, 1917, 2053, 2056, 2057, 2060, 2061, 2062, 1958, + 1958, 1958, 2514, 470, 471, 472, 473, 474, 474, 474, + 474, 474, 474, 475, 1479, 1936, 2034, 1972, 1972, 1972, + 2025, 2514, 2063, 2514, 2514, 1962, 1962, 1962, 2514, 470, + 471, 472, 473, 474, 474, 474, 474, 474, 474, 475, + + 1489, 2064, 2514, 723, 2514, 2043, 1973, 2034, 2514, 2514, + 2514, 711, 2514, 2514, 2514, 725, 2035, 641, 642, 643, + 644, 645, 645, 645, 645, 645, 645, 646, 1441, 1295, + 1295, 2514, 2064, 1580, 1823, 1708, 1708, 1973, 2065, 1824, + 1959, 1444, 711, 1832, 1295, 1295, 725, 1940, 1824, 1823, + 1708, 1708, 2514, 1581, 1824, 397, 1825, 2045, 1974, 1826, + 2066, 2067, 1825, 2054, 2514, 2037, 1963, 756, 1826, 2065, + 1832, 1295, 1295, 2514, 1826, 1824, 1830, 1295, 1295, 2068, + 2514, 1716, 2514, 1825, 1581, 2058, 2058, 2058, 2514, 1717, + 1826, 2066, 2067, 378, 2514, 1826, 2037, 2514, 756, 1826, + + 1631, 1718, 2514, 2514, 2514, 1826, 1832, 1295, 1295, 1582, + 2068, 1824, 1830, 1295, 1295, 1827, 397, 1716, 2046, 1825, + 2514, 2069, 2070, 2076, 1833, 1717, 1826, 2514, 399, 2082, + 1943, 1826, 1718, 1830, 1295, 1295, 2085, 1718, 1716, 2086, + 1525, 1529, 2087, 2088, 2089, 2038, 1717, 2514, 1979, 1979, + 1979, 1942, 2069, 2070, 2076, 2039, 2514, 1944, 1718, 399, + 2082, 2514, 1826, 1512, 2514, 2514, 2059, 2085, 1718, 2514, + 2086, 1525, 1529, 2087, 2088, 2089, 2038, 2071, 2071, 2071, + 2514, 2514, 2514, 378, 2514, 2514, 2039, 1945, 2514, 1718, + 2514, 2514, 2514, 1831, 641, 642, 643, 644, 645, 645, + + 645, 645, 645, 645, 646, 2040, 2073, 2073, 2073, 2078, + 2078, 2078, 2092, 2514, 1836, 676, 677, 678, 679, 680, + 680, 680, 680, 680, 680, 681, 2055, 2514, 2095, 1980, + 2514, 2050, 2080, 2080, 2080, 2096, 2040, 2083, 2083, 2083, + 2090, 2090, 2090, 2092, 676, 677, 678, 679, 680, 680, + 680, 680, 680, 680, 681, 2097, 2514, 2055, 2072, 2095, + 2093, 378, 2050, 2094, 2098, 2100, 2096, 2103, 2104, 2105, + 2106, 378, 2107, 2101, 2099, 2514, 2514, 2514, 2108, 2110, + 2102, 2113, 2019, 2019, 2019, 2111, 2097, 2074, 2115, 493, + 2079, 2093, 2514, 2514, 2094, 2098, 2100, 1544, 2103, 2104, + + 2105, 2106, 2514, 2107, 2101, 2099, 2114, 2116, 2117, 2108, + 493, 2102, 2113, 2081, 2514, 2514, 2111, 2514, 2084, 2115, + 493, 2091, 2514, 470, 471, 472, 473, 474, 474, 474, + 474, 474, 474, 475, 2112, 2118, 2119, 2114, 2116, 2117, + 2120, 493, 2514, 470, 471, 472, 473, 474, 474, 474, + 474, 474, 474, 475, 2514, 2514, 378, 2033, 2033, 2033, + 2514, 2514, 2130, 2020, 2514, 2112, 2118, 2119, 2514, 2131, + 2514, 2120, 2514, 470, 471, 472, 473, 474, 474, 474, + 474, 474, 474, 475, 1832, 1295, 1295, 2132, 2134, 1824, + 1830, 1295, 1295, 2130, 723, 1716, 2125, 1825, 2034, 397, + + 2131, 2128, 723, 1717, 2126, 2135, 939, 2514, 2136, 1826, + 711, 756, 2514, 2142, 725, 1718, 2143, 2121, 2132, 2134, + 2122, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2034, + 2514, 2514, 2514, 2138, 2138, 2138, 2135, 939, 2035, 2136, + 1826, 711, 756, 2123, 2142, 725, 1718, 2143, 2121, 641, + 642, 643, 644, 645, 645, 645, 645, 645, 645, 646, + 2137, 2140, 2140, 2140, 2144, 1833, 2514, 2133, 2514, 2146, + 2514, 1831, 676, 677, 678, 679, 680, 680, 680, 680, + 680, 680, 681, 2514, 2514, 2514, 2058, 2058, 2058, 2147, + 2148, 2137, 2149, 2151, 2152, 2144, 2514, 397, 2133, 2129, + + 2146, 1631, 378, 2155, 2514, 378, 2071, 2071, 2071, 399, + 2160, 378, 2514, 2514, 2139, 2073, 2073, 2073, 2162, 2163, + 2147, 2148, 2165, 2149, 2151, 2152, 2153, 2153, 2153, 2078, + 2078, 2078, 2166, 2514, 2155, 2080, 2080, 2080, 2167, 2168, + 399, 2160, 2141, 2083, 2083, 2083, 2090, 2090, 2090, 2162, + 2163, 2169, 2170, 2165, 2171, 2514, 2514, 2172, 2173, 2174, + 2175, 2157, 2156, 2166, 378, 2181, 2176, 2059, 2177, 2167, + 2168, 2178, 2179, 2186, 2187, 2158, 2514, 2188, 2201, 2201, + 2201, 2190, 2169, 2170, 2159, 2171, 2164, 2072, 2172, 2173, + 2174, 2175, 2157, 2156, 2199, 2200, 2074, 2176, 2514, 2177, + + 2514, 2514, 2178, 2179, 2186, 2187, 2158, 2154, 2188, 2182, + 2079, 2183, 2190, 2514, 2514, 2159, 2081, 2164, 2514, 2514, + 2514, 2514, 2514, 2514, 2084, 2199, 2200, 2091, 2514, 470, + 471, 472, 473, 474, 474, 474, 474, 474, 474, 475, + 2182, 2514, 2183, 2203, 2203, 2203, 2514, 2514, 470, 471, + 472, 473, 474, 474, 474, 474, 474, 474, 475, 2202, + 2514, 2514, 2205, 2514, 2206, 470, 471, 472, 473, 474, + 474, 474, 474, 474, 474, 475, 493, 493, 1832, 1295, + 1295, 2209, 723, 1824, 2194, 2191, 2185, 2184, 2514, 2210, + 723, 1825, 2195, 2205, 939, 2206, 2192, 2211, 711, 378, + + 2514, 2212, 725, 1826, 2138, 2138, 2138, 493, 493, 2213, + 2213, 2213, 2209, 2221, 2221, 2221, 2191, 2185, 2184, 397, + 2210, 2197, 2514, 2514, 2204, 939, 2220, 2192, 2211, 711, + 2223, 756, 2212, 725, 1826, 641, 642, 643, 644, 645, + 645, 645, 645, 645, 645, 646, 676, 677, 678, 679, + 680, 680, 680, 680, 680, 680, 681, 2220, 2514, 1833, + 2514, 2223, 756, 2514, 2514, 2514, 2514, 2514, 2514, 2140, + 2140, 2140, 2216, 2216, 2216, 2224, 2225, 397, 2226, 2198, + 2153, 2153, 2153, 2227, 2228, 2139, 2217, 2229, 2231, 399, + 2214, 2207, 2232, 2233, 2222, 2234, 2235, 2236, 2230, 2237, + + 2238, 2239, 2208, 2240, 2241, 2242, 2224, 2225, 2243, 2226, + 2244, 2245, 2249, 2514, 2227, 2228, 2514, 493, 2229, 2231, + 399, 2253, 2207, 2232, 2233, 2514, 2234, 2235, 2236, 2251, + 2237, 2238, 2239, 2208, 2240, 2241, 2242, 2514, 2514, 2243, + 2514, 2244, 2245, 2250, 378, 2514, 2514, 378, 493, 2514, + 2141, 2514, 2253, 2218, 2246, 2246, 2246, 2514, 2514, 2514, + 2251, 2154, 470, 471, 472, 473, 474, 474, 474, 474, + 474, 474, 475, 2254, 2250, 2255, 470, 471, 472, 473, + 474, 474, 474, 474, 474, 474, 475, 493, 470, 471, + 472, 473, 474, 474, 474, 474, 474, 474, 475, 2256, + + 2252, 2257, 2258, 723, 2254, 2261, 2255, 397, 723, 2264, + 2262, 2266, 2267, 2259, 2268, 939, 711, 2514, 493, 756, + 725, 2269, 2514, 2514, 2514, 2201, 2201, 2201, 2514, 2514, + 2256, 2252, 2257, 2258, 2514, 2247, 397, 2514, 2265, 2203, + 2203, 2203, 2266, 2267, 2259, 2268, 939, 711, 399, 2270, + 756, 725, 2269, 2514, 2514, 2514, 2273, 641, 642, 643, + 644, 645, 645, 645, 645, 645, 645, 646, 676, 677, + 678, 679, 680, 680, 680, 680, 680, 680, 681, 399, + 2270, 2271, 2271, 2271, 2274, 2275, 2276, 2273, 2213, 2213, + 2213, 2216, 2216, 2216, 2277, 2277, 2277, 2281, 2282, 2221, + + 2221, 2221, 2284, 378, 2514, 2217, 2202, 2285, 2514, 2286, + 2287, 2288, 2289, 2290, 2291, 2274, 2275, 2276, 2292, 2293, + 2204, 2294, 2295, 2296, 2297, 2298, 2299, 2300, 2281, 2282, + 2278, 2305, 2301, 2284, 378, 2279, 2302, 2303, 2285, 2283, + 2286, 2287, 2288, 2289, 2290, 2291, 2246, 2246, 2246, 2292, + 2293, 2306, 2294, 2295, 2296, 2297, 2298, 2299, 2300, 2309, + 2310, 2278, 2272, 2301, 2514, 2514, 2279, 2302, 2303, 2214, + 2283, 2514, 2218, 2514, 2514, 2280, 2514, 2271, 2271, 2271, + 2222, 723, 2306, 2313, 2514, 2514, 2514, 2514, 2308, 2311, + 2309, 2310, 493, 939, 2318, 470, 471, 472, 473, 474, + + 474, 474, 474, 474, 474, 475, 2514, 470, 471, 472, + 473, 474, 474, 474, 474, 474, 474, 475, 493, 2308, + 2311, 2514, 2514, 493, 939, 2318, 2319, 2247, 2307, 641, + 642, 643, 644, 645, 645, 645, 645, 645, 645, 646, + 723, 397, 2314, 2316, 2320, 2321, 2322, 2326, 711, 493, + 2327, 2328, 725, 756, 2277, 2277, 2277, 2319, 2272, 2307, + 676, 677, 678, 679, 680, 680, 680, 680, 680, 680, + 681, 2514, 2514, 2514, 2329, 2320, 2321, 2322, 2326, 711, + 2330, 2327, 2328, 725, 756, 397, 2331, 2317, 2332, 2333, + 2278, 2334, 2335, 2336, 2337, 2279, 2338, 399, 2339, 2340, + + 2341, 2342, 2343, 2344, 2351, 2329, 2345, 2346, 2347, 2348, + 2349, 2330, 493, 2354, 2355, 2362, 2363, 2331, 2364, 2332, + 2333, 2278, 2334, 2335, 2336, 2337, 2279, 2338, 399, 2339, + 2340, 2341, 2342, 2343, 2344, 2280, 2514, 2345, 2346, 2347, + 2348, 2349, 2514, 493, 2354, 2355, 2362, 2363, 2352, 2364, + 2365, 723, 378, 2357, 2514, 397, 2514, 2360, 2514, 2514, + 2514, 2514, 2514, 939, 2514, 2366, 2514, 756, 470, 471, + 472, 473, 474, 474, 474, 474, 474, 474, 475, 2352, + 2367, 2365, 470, 471, 472, 473, 474, 474, 474, 474, + 474, 474, 475, 493, 939, 723, 2366, 2358, 756, 2514, + + 2514, 2514, 2353, 711, 2370, 2371, 2374, 725, 2375, 2376, + 2377, 2367, 2380, 397, 2381, 2361, 2378, 2378, 2378, 2382, + 2383, 2384, 2385, 2386, 493, 399, 2387, 2388, 2389, 2514, + 2514, 2514, 2514, 2353, 711, 2370, 2371, 2374, 725, 2375, + 2376, 2377, 2391, 2380, 493, 2381, 2392, 2399, 2514, 2514, + 2382, 2383, 2384, 2385, 2386, 2514, 399, 2387, 2388, 2389, + 470, 471, 472, 473, 474, 474, 474, 474, 474, 474, + 475, 2400, 2401, 2402, 723, 493, 2394, 2392, 2399, 723, + 378, 2395, 397, 2514, 2397, 2514, 939, 711, 2408, 2408, + 2408, 725, 2403, 2404, 756, 2405, 2406, 2379, 2407, 2410, + + 2411, 2412, 2400, 2401, 2402, 2514, 470, 471, 472, 473, + 474, 474, 474, 474, 474, 474, 475, 939, 711, 2514, + 2514, 2514, 725, 2403, 2404, 756, 2405, 2406, 2413, 2407, + 2410, 2411, 2412, 397, 2414, 2398, 2378, 2378, 2378, 2415, + 2416, 2417, 2378, 2378, 2378, 399, 470, 471, 472, 473, + 474, 474, 474, 474, 474, 474, 475, 2426, 2427, 2413, + 2428, 723, 2429, 2421, 2430, 2414, 723, 2431, 2422, 2409, + 2415, 2416, 2417, 939, 711, 397, 399, 2424, 725, 2433, + 2514, 2514, 2514, 2408, 2408, 2408, 2514, 756, 2426, 2427, + 2436, 2428, 2514, 2429, 397, 2430, 2425, 2437, 2431, 2438, + + 378, 2434, 2434, 2434, 939, 711, 399, 2444, 2514, 725, + 2433, 2445, 723, 397, 2440, 2443, 2514, 2379, 756, 2446, + 2447, 2436, 2448, 2379, 939, 756, 2514, 723, 2437, 2441, + 2438, 2514, 2514, 2514, 2449, 711, 2450, 399, 2444, 725, + 2452, 2453, 2445, 2454, 2514, 397, 2514, 2425, 2514, 2514, + 2446, 2447, 2457, 2448, 2514, 939, 756, 399, 2434, 2434, + 2434, 378, 2514, 2514, 2409, 2449, 711, 2450, 2462, 2514, + 725, 2452, 2453, 2463, 2454, 723, 2464, 2456, 723, 397, + 2441, 2443, 2435, 2457, 2465, 2451, 711, 939, 399, 2466, + 725, 756, 2458, 2458, 2458, 2467, 2468, 2469, 2473, 2462, + + 2459, 723, 2476, 2456, 2463, 2477, 2478, 2464, 2514, 2479, + 2480, 2481, 378, 939, 2482, 2465, 2451, 711, 939, 2483, + 2466, 725, 756, 2458, 2458, 2458, 2467, 2468, 2469, 2473, + 2484, 2459, 2485, 2476, 2488, 2489, 2477, 2478, 2490, 2435, + 2479, 2480, 2481, 2491, 939, 2482, 2486, 2486, 2486, 2495, + 2483, 2492, 2492, 2492, 2486, 2486, 2486, 2496, 2497, 2498, + 2499, 2484, 2500, 2485, 2514, 2488, 2489, 2501, 2502, 2490, + 2492, 2492, 2492, 2460, 2491, 2461, 2492, 2492, 2492, 2503, + 2495, 2504, 2378, 2378, 2378, 2505, 2506, 2507, 2496, 2497, + 2498, 2499, 2508, 2500, 2509, 2494, 2514, 2510, 2501, 2502, + + 2511, 2514, 2512, 2513, 2460, 2514, 2461, 2492, 2492, 2492, + 2503, 2514, 2504, 2514, 2514, 2514, 2505, 2506, 2507, 2514, + 2514, 2514, 2514, 2508, 2514, 2509, 2494, 2487, 2510, 2514, + 2514, 2511, 2493, 2512, 2513, 2487, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2493, 2514, 2514, 2514, 2514, 2514, 2493, 2514, 2514, + 2514, 2514, 2514, 2379, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2493, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + + 125, 125, 125, 125, 125, 125, 125, 181, 181, 181, + 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, + 181, 181, 181, 181, 181, 189, 189, 189, 189, 189, + 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, + 189, 189, 189, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 217, 217, 217, 217, 217, 217, 217, 217, 217, + 217, 217, 217, 217, 217, 217, 217, 217, 217, 226, + 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, + 226, 226, 226, 226, 226, 226, 226, 233, 233, 233, + + 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, + 233, 233, 233, 233, 233, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 239, 239, 239, 239, 239, 239, 239, + 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, + 239, 242, 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, 242, 244, + 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, + 244, 244, 244, 244, 244, 244, 244, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + + 268, 268, 268, 268, 268, 270, 270, 270, 270, 270, + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 270, 270, 270, 312, 312, 312, 312, 312, 312, 312, + 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, + 312, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 361, 361, 361, + 2514, 2514, 2514, 361, 2514, 2514, 2514, 2514, 361, 361, + 361, 361, 369, 369, 2514, 369, 369, 369, 369, 369, + + 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 376, 376, 2514, 2514, 2514, 376, 2514, 2514, 2514, 2514, + 376, 376, 376, 376, 383, 383, 383, 2514, 2514, 383, + 2514, 2514, 2514, 2514, 383, 383, 383, 383, 456, 456, + 2514, 2514, 2514, 456, 2514, 2514, 2514, 456, 456, 456, + 456, 456, 465, 2514, 465, 465, 465, 465, 465, 465, + 465, 469, 469, 2514, 2514, 2514, 469, 2514, 2514, 2514, + 2514, 469, 469, 469, 469, 487, 2514, 487, 487, 487, + 487, 487, 487, 493, 493, 2514, 493, 493, 2514, 493, + 493, 493, 2514, 2514, 2514, 2514, 493, 493, 493, 493, + + 523, 2514, 523, 523, 523, 523, 525, 525, 525, 2514, + 2514, 2514, 525, 2514, 2514, 2514, 2514, 525, 525, 525, + 525, 532, 532, 2514, 2514, 2514, 532, 2514, 2514, 2514, + 2514, 532, 532, 532, 532, 539, 539, 539, 2514, 2514, + 539, 2514, 2514, 2514, 2514, 539, 539, 539, 539, 551, + 551, 2514, 2514, 2514, 551, 2514, 2514, 2514, 551, 551, + 551, 551, 551, 560, 2514, 560, 560, 560, 560, 561, + 2514, 561, 2514, 561, 581, 2514, 581, 2514, 581, 606, + 606, 606, 606, 606, 606, 2514, 606, 606, 606, 606, + 606, 2514, 606, 606, 606, 606, 606, 612, 612, 612, + + 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, + 612, 612, 612, 612, 612, 613, 613, 613, 613, 613, + 613, 2514, 613, 613, 613, 613, 613, 2514, 613, 613, + 613, 613, 613, 619, 619, 619, 619, 619, 619, 619, + 619, 619, 619, 619, 619, 619, 619, 619, 619, 619, + 619, 625, 625, 625, 625, 625, 625, 625, 625, 625, + 625, 625, 625, 625, 625, 625, 625, 625, 625, 626, + 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, + 626, 626, 2514, 626, 626, 626, 626, 628, 628, 628, + 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, + + 2514, 628, 628, 628, 628, 633, 633, 2514, 633, 633, + 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, + 633, 633, 633, 640, 640, 2514, 2514, 2514, 640, 2514, + 2514, 2514, 2514, 640, 640, 640, 640, 655, 2514, 655, + 655, 655, 655, 655, 660, 660, 2514, 660, 660, 660, + 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, + 660, 660, 668, 668, 2514, 668, 668, 668, 668, 668, + 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, + 675, 675, 2514, 2514, 2514, 675, 2514, 2514, 2514, 2514, + 675, 675, 675, 675, 687, 2514, 687, 687, 687, 687, + + 687, 687, 690, 690, 2514, 2514, 2514, 690, 2514, 2514, + 2514, 2514, 690, 690, 690, 690, 699, 2514, 699, 699, + 699, 699, 704, 704, 2514, 704, 704, 704, 704, 704, + 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, + 711, 711, 2514, 2514, 2514, 711, 2514, 2514, 2514, 2514, + 711, 711, 711, 711, 729, 2514, 729, 729, 729, 729, + 2514, 2514, 729, 733, 733, 2514, 733, 733, 733, 733, + 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, + 733, 739, 739, 2514, 739, 739, 739, 739, 739, 739, + 739, 739, 739, 739, 739, 739, 739, 739, 739, 361, + + 361, 361, 2514, 2514, 2514, 361, 2514, 2514, 2514, 2514, + 361, 361, 361, 361, 747, 2514, 747, 747, 747, 747, + 368, 368, 2514, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 369, 369, + 2514, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 749, 749, 2514, 749, + 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, + 749, 749, 749, 749, 376, 376, 2514, 2514, 2514, 376, + 2514, 2514, 2514, 2514, 376, 376, 376, 376, 465, 2514, + 465, 465, 465, 465, 383, 383, 383, 2514, 2514, 383, + + 2514, 2514, 2514, 2514, 383, 383, 383, 383, 751, 2514, + 751, 751, 751, 751, 456, 456, 2514, 2514, 2514, 456, + 2514, 2514, 2514, 456, 456, 456, 456, 456, 843, 2514, + 843, 843, 843, 843, 469, 469, 2514, 2514, 2514, 469, + 2514, 2514, 2514, 2514, 469, 469, 469, 469, 487, 2514, + 487, 487, 487, 487, 493, 493, 2514, 493, 493, 2514, + 493, 493, 493, 2514, 2514, 2514, 2514, 493, 493, 493, + 493, 523, 2514, 523, 523, 523, 523, 525, 525, 525, + 2514, 2514, 2514, 525, 2514, 2514, 2514, 2514, 525, 525, + 525, 525, 868, 2514, 868, 868, 868, 868, 532, 532, + + 2514, 2514, 2514, 532, 2514, 2514, 2514, 2514, 532, 532, + 532, 532, 560, 2514, 560, 560, 560, 560, 539, 539, + 539, 2514, 2514, 539, 2514, 2514, 2514, 2514, 539, 539, + 539, 539, 870, 2514, 870, 870, 870, 870, 551, 551, + 2514, 2514, 2514, 551, 2514, 2514, 2514, 551, 551, 551, + 551, 551, 874, 2514, 874, 874, 874, 874, 561, 2514, + 561, 2514, 561, 581, 2514, 581, 2514, 581, 606, 606, + 606, 606, 606, 606, 2514, 606, 606, 606, 606, 606, + 2514, 606, 606, 606, 606, 606, 895, 895, 2514, 895, + 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, + + 895, 895, 895, 895, 613, 613, 613, 613, 613, 613, + 2514, 613, 613, 613, 613, 613, 2514, 613, 613, 613, + 613, 613, 899, 899, 2514, 899, 899, 899, 899, 899, + 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, + 903, 903, 2514, 903, 903, 903, 903, 903, 903, 903, + 903, 903, 903, 903, 903, 903, 903, 903, 626, 626, + 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, + 626, 2514, 626, 626, 626, 626, 628, 628, 628, 628, + 628, 628, 628, 628, 628, 628, 628, 628, 628, 2514, + 628, 628, 628, 628, 632, 632, 2514, 632, 632, 632, + + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 633, 633, 2514, 633, 633, 633, 633, 633, + 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, + 907, 907, 2514, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 640, 640, + 2514, 2514, 2514, 640, 2514, 2514, 2514, 2514, 640, 640, + 640, 640, 655, 2514, 655, 655, 655, 655, 660, 660, + 2514, 660, 660, 660, 660, 660, 660, 660, 660, 660, + 660, 660, 660, 660, 660, 660, 667, 667, 2514, 667, + 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, + + 667, 667, 667, 667, 668, 668, 2514, 668, 668, 668, + 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, + 668, 668, 923, 923, 2514, 923, 923, 923, 923, 923, + 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, + 675, 675, 2514, 2514, 2514, 675, 2514, 2514, 2514, 2514, + 675, 675, 675, 675, 687, 2514, 687, 687, 687, 687, + 690, 690, 2514, 2514, 2514, 690, 2514, 2514, 2514, 2514, + 690, 690, 690, 690, 699, 2514, 699, 699, 699, 699, + 703, 703, 2514, 703, 703, 703, 703, 703, 703, 703, + 703, 703, 703, 703, 703, 703, 703, 703, 704, 704, + + 2514, 704, 704, 704, 704, 704, 704, 704, 704, 704, + 704, 704, 704, 704, 704, 704, 934, 934, 2514, 934, + 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, + 934, 934, 934, 934, 711, 711, 2514, 2514, 2514, 711, + 2514, 2514, 2514, 2514, 711, 711, 711, 711, 729, 2514, + 729, 729, 729, 729, 733, 733, 2514, 733, 733, 733, + 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, + 733, 733, 739, 739, 2514, 739, 739, 739, 739, 739, + 739, 739, 739, 739, 739, 739, 739, 739, 739, 739, + 361, 361, 361, 2514, 2514, 2514, 361, 2514, 2514, 2514, + + 2514, 361, 361, 361, 361, 368, 368, 2514, 368, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 369, 369, 2514, 369, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 383, 383, 383, 2514, 2514, 383, 2514, 2514, 2514, + 2514, 383, 383, 383, 383, 964, 964, 964, 964, 964, + 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, + 964, 964, 964, 376, 376, 2514, 2514, 376, 376, 2514, + 2514, 2514, 2514, 376, 376, 376, 376, 456, 456, 2514, + 2514, 2514, 456, 2514, 2514, 2514, 456, 456, 456, 456, + + 456, 469, 469, 2514, 2514, 2514, 469, 2514, 2514, 2514, + 2514, 469, 469, 469, 469, 493, 493, 2514, 2514, 493, + 493, 2514, 2514, 2514, 2514, 493, 493, 493, 493, 525, + 525, 525, 2514, 2514, 2514, 525, 2514, 2514, 2514, 2514, + 525, 525, 525, 525, 539, 539, 539, 2514, 2514, 539, + 2514, 2514, 2514, 2514, 539, 539, 539, 539, 532, 532, + 2514, 2514, 2514, 532, 2514, 2514, 2514, 2514, 532, 532, + 532, 532, 551, 551, 2514, 2514, 2514, 551, 2514, 2514, + 2514, 551, 551, 551, 551, 551, 561, 2514, 561, 2514, + 561, 581, 2514, 581, 2514, 581, 895, 895, 2514, 895, + + 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 899, 899, 2514, 899, 899, 899, + 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, + 899, 899, 903, 903, 2514, 903, 903, 903, 903, 903, + 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, + 632, 632, 2514, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 633, 633, + 2514, 633, 633, 633, 633, 633, 633, 633, 633, 633, + 633, 633, 633, 633, 633, 633, 1107, 1107, 1107, 1107, + 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, + + 1107, 1107, 1107, 1107, 640, 640, 2514, 2514, 2514, 640, + 2514, 2514, 2514, 2514, 640, 640, 640, 640, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 667, 667, 2514, 667, + 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, + 667, 667, 667, 667, 668, 668, 2514, 668, 668, 668, + 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, + 668, 668, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, + 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, + 675, 675, 2514, 2514, 2514, 675, 2514, 2514, 2514, 2514, + + 675, 675, 675, 675, 690, 690, 2514, 2514, 2514, 690, + 2514, 2514, 2514, 2514, 690, 690, 690, 690, 703, 703, + 2514, 703, 703, 703, 703, 703, 703, 703, 703, 703, + 703, 703, 703, 703, 703, 703, 704, 704, 2514, 704, + 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, + 704, 704, 704, 704, 1133, 1133, 1133, 1133, 1133, 1133, + 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, + 1133, 1133, 711, 711, 2514, 2514, 711, 711, 2514, 2514, + 2514, 2514, 711, 711, 711, 711, 1145, 1145, 1145, 1145, + 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, + + 1145, 1145, 1145, 1145, 1150, 1150, 1150, 1150, 1150, 1150, + 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, + 1150, 1150, 368, 368, 2514, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 964, 964, 2514, 964, 964, 964, 964, 964, 964, 964, + 964, 964, 964, 964, 964, 964, 964, 964, 376, 376, + 2514, 2514, 376, 376, 2514, 2514, 2514, 2514, 376, 376, + 376, 376, 469, 469, 2514, 2514, 2514, 469, 2514, 2514, + 2514, 2514, 469, 469, 469, 469, 493, 493, 2514, 2514, + 493, 493, 493, 2514, 2514, 2514, 493, 493, 493, 493, + + 532, 532, 2514, 2514, 2514, 532, 2514, 2514, 2514, 2514, + 532, 532, 532, 532, 561, 2514, 561, 2514, 561, 581, + 2514, 581, 2514, 581, 1280, 1280, 1280, 1280, 1280, 1280, + 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, + 1280, 1280, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, + 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, + 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, + 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 632, 632, + 2514, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 1107, 1107, 2514, 1107, + + 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, + 1107, 1107, 1107, 1107, 640, 640, 2514, 2514, 2514, 640, + 2514, 2514, 2514, 2514, 640, 640, 640, 640, 1118, 1118, + 2514, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 667, 667, 2514, 667, + 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, + 667, 667, 667, 667, 1123, 1123, 2514, 1123, 1123, 1123, + 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, + 1123, 1123, 675, 675, 2514, 2514, 2514, 675, 2514, 2514, + 2514, 2514, 675, 675, 675, 675, 690, 690, 2514, 2514, + + 2514, 690, 2514, 2514, 2514, 2514, 690, 690, 690, 690, + 703, 703, 2514, 703, 703, 703, 703, 703, 703, 703, + 703, 703, 703, 703, 703, 703, 703, 703, 1133, 1133, + 2514, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, + 1133, 1133, 1133, 1133, 1133, 1133, 711, 711, 2514, 2514, + 711, 711, 2514, 2514, 2514, 2514, 711, 711, 711, 711, + 1145, 1145, 2514, 1145, 1145, 1145, 1145, 1145, 1145, 1145, + 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1150, 1150, + 2514, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, + 1150, 1150, 1150, 1150, 1150, 1150, 376, 376, 2514, 2514, + + 376, 376, 2514, 2514, 2514, 2514, 376, 376, 376, 376, + 469, 469, 2514, 2514, 2514, 469, 2514, 2514, 2514, 2514, + 469, 469, 469, 469, 493, 493, 2514, 2514, 493, 493, + 2514, 2514, 2514, 2514, 493, 493, 493, 493, 532, 532, + 2514, 2514, 2514, 532, 2514, 2514, 2514, 2514, 532, 532, + 532, 532, 561, 2514, 561, 2514, 561, 581, 2514, 581, + 2514, 581, 1280, 1280, 2514, 1280, 1280, 1280, 1280, 1280, + 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, + 1284, 1284, 2514, 1284, 1284, 1284, 1284, 1284, 1284, 1284, + 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1288, 1288, + + 2514, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, + 1288, 1288, 1288, 1288, 1288, 1288, 640, 640, 2514, 2514, + 2514, 640, 2514, 2514, 2514, 2514, 640, 640, 640, 640, + 675, 675, 2514, 2514, 2514, 675, 2514, 2514, 2514, 2514, + 675, 675, 675, 675, 1440, 1440, 1440, 1440, 1440, 1440, + 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, + 1440, 1440, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, + 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, + 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, + 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1714, 1714, + + 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, + 1714, 1714, 1714, 1714, 1714, 1714, 1736, 1736, 1736, 1736, + 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, + 1736, 1736, 1736, 1736, 1743, 1743, 1743, 1743, 1743, 1743, + 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, + 1743, 1743, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, + 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, + 1797, 1797, 1797, 1797, 1797, 1797, 1797, 1797, 1797, 1797, + 1797, 1797, 1797, 1797, 1797, 1797, 1797, 1797, 1822, 1822, + 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, + + 1822, 1822, 1822, 1822, 1822, 1822, 1872, 1872, 1872, 1872, + 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, + 1872, 1872, 1872, 1872, 59, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514 + } ; + +static yyconst flex_int16_t yy_chk[15718] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, + + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 5, 6, 71, 71, 2493, 71, + 232, 232, 2487, 5, 6, 7, 7, 7, 7, 7, + + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 13, 13, 13, 27, 14, 14, 14, 13, 28, + 29, 13, 14, 13, 30, 14, 31, 14, 15, 15, + 15, 32, 16, 16, 16, 15, 39, 40, 15, 16, + + 15, 47, 16, 48, 16, 110, 127, 57, 132, 133, + 110, 127, 58, 132, 136, 57, 27, 137, 39, 40, + 58, 28, 29, 77, 57, 77, 30, 2472, 138, 58, + 47, 31, 48, 139, 140, 77, 32, 141, 57, 77, + 133, 174, 153, 58, 2464, 136, 57, 153, 137, 39, + 40, 58, 13, 2463, 13, 57, 14, 168, 14, 138, + 58, 47, 168, 48, 139, 140, 77, 2461, 141, 15, + 77, 15, 174, 16, 2460, 16, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 21, 21, + 21, 22, 22, 22, 175, 122, 21, 176, 185, 22, + 23, 23, 23, 185, 2457, 23, 103, 23, 177, 23, + 23, 24, 24, 24, 193, 2455, 24, 334, 24, 193, + + 24, 24, 25, 25, 25, 175, 2442, 25, 176, 25, + 25, 25, 25, 26, 26, 26, 2439, 265, 26, 177, + 26, 26, 26, 26, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 79, 87, 79, 87, 199, + 199, 85, 207, 85, 122, 122, 208, 79, 87, 21, + 269, 21, 22, 85, 22, 103, 103, 85, 103, 202, + 79, 23, 223, 23, 202, 212, 212, 223, 212, 334, + 199, 199, 24, 207, 24, 230, 2435, 208, 79, 87, + 230, 269, 476, 25, 85, 25, 265, 476, 85, 281, + 281, 79, 323, 323, 26, 323, 26, 37, 37, 37, + + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 41, + 41, 41, 260, 41, 41, 260, 41, 41, 41, 61, + + 61, 61, 41, 42, 42, 42, 1291, 42, 42, 298, + 42, 42, 42, 78, 490, 78, 42, 210, 279, 490, + 80, 78, 80, 260, 313, 78, 260, 343, 83, 41, + 83, 344, 80, 142, 210, 78, 83, 142, 78, 2423, + 83, 2420, 352, 42, 83, 80, 142, 2409, 210, 279, + 142, 80, 78, 2407, 353, 313, 78, 2396, 343, 2393, + 41, 2392, 344, 80, 142, 210, 78, 83, 142, 78, + 41, 83, 41, 352, 42, 83, 80, 142, 298, 298, + 61, 142, 80, 1291, 42, 353, 42, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 51, 51, 51, 1496, 1496, 51, 509, + 52, 52, 52, 2390, 509, 52, 51, 62, 62, 62, + 2379, 51, 355, 52, 247, 247, 247, 2369, 52, 356, + 51, 55, 55, 55, 1612, 1612, 55, 52, 56, 56, + + 56, 2274, 178, 56, 55, 64, 178, 51, 357, 55, + 81, 56, 81, 355, 52, 178, 56, 496, 55, 178, + 356, 51, 81, 2359, 55, 56, 259, 2356, 52, 81, + 497, 56, 81, 178, 2350, 81, 547, 178, 51, 357, + 259, 547, 67, 259, 51, 52, 178, 498, 496, 55, + 178, 52, 329, 81, 329, 55, 56, 259, 62, 2329, + 81, 497, 56, 81, 329, 247, 81, 248, 248, 248, + 562, 259, 55, 2328, 259, 562, 2274, 1283, 498, 56, + 2325, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 65, 65, 574, 329, 65, 65, 2315, 574, + + 65, 65, 65, 65, 65, 65, 65, 65, 65, 2312, + 65, 65, 65, 65, 65, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 578, 96, 98, 96, + 98, 578, 584, 599, 499, 96, 98, 584, 599, 96, + 98, 65, 65, 65, 82, 65, 82, 84, 248, 84, + 603, 1283, 1287, 2304, 258, 603, 82, 258, 84, 84, + 258, 84, 271, 271, 271, 499, 96, 98, 84, 82, + 96, 98, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 74, 258, 74, 82, 258, 84, + 84, 258, 84, 86, 2280, 86, 74, 395, 397, 84, + + 82, 86, 272, 272, 272, 86, 500, 395, 397, 86, + 2273, 234, 234, 234, 2272, 86, 234, 511, 234, 88, + 2263, 88, 2260, 92, 234, 92, 1287, 74, 1619, 1619, + 2248, 88, 86, 512, 2247, 92, 86, 500, 395, 397, + 86, 88, 1625, 271, 513, 92, 86, 1625, 511, 2222, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 76, 88, 76, 512, 89, 92, 89, 514, 91, + 515, 91, 88, 76, 89, 513, 92, 89, 89, 2218, + 76, 91, 76, 272, 516, 517, 89, 76, 76, 76, + 89, 394, 234, 394, 519, 2214, 520, 91, 90, 514, + + 90, 515, 1737, 394, 76, 89, 90, 1737, 89, 89, + 90, 76, 91, 76, 90, 516, 517, 89, 76, 76, + 76, 89, 521, 90, 518, 519, 90, 520, 91, 564, + 1744, 93, 565, 93, 394, 1744, 94, 90, 94, 2204, + 518, 90, 2202, 93, 94, 90, 93, 95, 94, 95, + 566, 94, 93, 521, 90, 518, 2196, 90, 93, 95, + 564, 94, 567, 565, 402, 2193, 402, 1765, 95, 569, + 95, 518, 1765, 95, 93, 94, 402, 93, 2180, 94, + 2154, 566, 94, 93, 99, 1624, 1624, 100, 100, 93, + 95, 2149, 94, 567, 97, 568, 97, 2147, 100, 95, + + 569, 95, 97, 100, 95, 2141, 97, 402, 570, 97, + 97, 568, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 283, 283, 283, 568, 101, 101, 2139, + 100, 100, 100, 97, 100, 102, 102, 97, 101, 570, + 97, 97, 568, 101, 104, 104, 102, 399, 2127, 399, + 399, 102, 399, 571, 582, 104, 1640, 1640, 2124, 209, + 104, 100, 399, 405, 209, 405, 112, 1671, 1671, 2119, + 101, 101, 101, 2109, 101, 405, 209, 405, 102, 102, + 102, 756, 102, 756, 571, 582, 756, 104, 104, 104, + 209, 104, 757, 399, 757, 209, 2091, 757, 284, 284, + + 284, 101, 2086, 101, 283, 2084, 405, 209, 405, 102, + 113, 315, 315, 315, 316, 316, 316, 114, 104, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 113, 115, 116, 583, 586, 1736, 1736, 114, 1743, + 1743, 113, 113, 113, 113, 113, 113, 113, 113, 113, + 113, 113, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 115, 116, 583, 586, 117, 118, 284, + 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, + 115, 2081, 315, 1758, 1758, 316, 587, 116, 116, 116, + + 116, 116, 116, 116, 116, 116, 116, 116, 117, 118, + 338, 338, 338, 2079, 588, 2074, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 587, 339, 339, + 339, 2072, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 119, 119, 588, 409, 2069, 409, 120, + 120, 347, 347, 347, 119, 121, 121, 2064, 409, 119, + 120, 123, 123, 2059, 589, 120, 121, 157, 157, 2044, + 590, 121, 123, 348, 348, 348, 591, 123, 157, 358, + 358, 358, 592, 157, 648, 648, 119, 119, 119, 409, + 119, 338, 120, 120, 120, 589, 120, 2041, 121, 121, + + 121, 590, 121, 150, 123, 123, 123, 591, 123, 339, + 157, 157, 157, 592, 157, 648, 648, 119, 1764, 1764, + 2035, 657, 406, 120, 406, 120, 237, 237, 237, 121, + 2022, 237, 347, 237, 406, 123, 129, 129, 129, 237, + 662, 157, 2020, 406, 1991, 700, 1989, 129, 1980, 129, + 129, 401, 657, 401, 348, 1974, 158, 158, 1963, 401, + 358, 129, 129, 401, 129, 406, 735, 158, 392, 392, + 392, 662, 158, 129, 406, 129, 700, 129, 736, 150, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 401, 1798, 129, 129, 401, 129, 1798, 735, 1959, 158, + + 158, 158, 741, 158, 129, 722, 129, 237, 129, 736, + 1954, 742, 630, 630, 630, 722, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 129, 130, 130, 130, + 158, 743, 158, 741, 744, 1797, 1797, 1951, 130, 1936, + 130, 130, 742, 240, 240, 240, 722, 240, 240, 392, + 501, 1918, 130, 130, 501, 130, 240, 745, 784, 1917, + 152, 1903, 743, 501, 130, 744, 130, 501, 130, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 404, 501, 404, 130, 130, 501, 130, 1891, 745, 784, + 154, 404, 404, 630, 501, 130, 1882, 130, 501, 130, + + 1872, 1872, 620, 620, 620, 1868, 620, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 131, 131, + 131, 154, 404, 404, 240, 759, 1862, 759, 155, 131, + 759, 131, 131, 152, 152, 152, 152, 152, 152, 152, + 152, 152, 152, 152, 156, 1855, 1845, 1842, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 155, + 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, + 251, 2324, 156, 156, 156, 156, 156, 156, 156, 156, + 156, 156, 156, 620, 1818, 792, 155, 155, 155, 155, + 155, 155, 155, 155, 155, 155, 155, 794, 131, 131, + + 131, 131, 131, 131, 131, 131, 131, 131, 131, 143, + 143, 143, 1812, 1873, 143, 143, 792, 328, 1873, 328, + 143, 723, 143, 143, 1801, 143, 159, 159, 794, 328, + 143, 723, 161, 161, 1757, 783, 328, 159, 1753, 262, + 262, 1728, 159, 161, 408, 2324, 408, 765, 161, 783, + 262, 1725, 1713, 1699, 765, 262, 408, 143, 143, 143, + 328, 143, 723, 1688, 408, 408, 783, 328, 1674, 159, + 159, 159, 408, 159, 795, 161, 161, 161, 765, 161, + 783, 1670, 262, 262, 262, 765, 262, 408, 143, 431, + 2459, 431, 1643, 263, 263, 408, 408, 647, 647, 647, + + 159, 431, 431, 408, 263, 795, 161, 250, 250, 263, + 1641, 250, 250, 262, 1639, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 1631, 250, 250, 250, 250, 250, + 264, 264, 431, 431, 1618, 1611, 263, 263, 263, 1603, + 263, 264, 421, 403, 421, 403, 264, 658, 658, 658, + 1599, 778, 421, 778, 421, 403, 250, 250, 250, 1593, + 250, 607, 607, 607, 2459, 266, 266, 263, 607, 263, + 403, 1591, 1587, 264, 264, 264, 266, 264, 647, 1564, + 799, 266, 778, 421, 778, 421, 403, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 257, + + 1549, 403, 257, 767, 264, 807, 801, 767, 266, 266, + 266, 799, 266, 287, 287, 287, 287, 287, 287, 287, + 287, 287, 287, 287, 1544, 614, 614, 614, 658, 818, + 257, 801, 614, 257, 767, 1512, 807, 801, 767, 266, + 292, 1507, 607, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 286, 286, 1503, 1495, 286, 286, + 818, 1489, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 292, 286, 286, 286, 286, 286, 939, 940, 939, + 940, 1479, 939, 940, 292, 292, 292, 292, 292, 292, + 292, 292, 292, 292, 292, 293, 661, 661, 661, 665, + + 665, 665, 1469, 286, 286, 286, 614, 286, 302, 302, + 302, 302, 302, 302, 302, 302, 302, 302, 302, 1465, + 294, 682, 682, 682, 1460, 1447, 293, 701, 701, 701, + 1439, 719, 719, 719, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 1432, 823, 731, 731, + 731, 294, 1423, 293, 293, 293, 293, 293, 293, 293, + 293, 293, 293, 293, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 295, 295, 661, 823, 829, + 665, 296, 296, 734, 734, 734, 295, 297, 297, 1401, + 1389, 295, 296, 299, 299, 1375, 1373, 296, 297, 411, + + 1354, 411, 682, 297, 299, 427, 758, 427, 701, 299, + 829, 411, 719, 737, 737, 737, 758, 427, 295, 295, + 295, 411, 295, 1347, 296, 296, 296, 305, 296, 731, + 297, 297, 297, 1343, 297, 427, 299, 299, 299, 420, + 299, 420, 411, 306, 306, 1313, 1307, 758, 427, 295, + 1297, 420, 411, 420, 306, 296, 1290, 296, 305, 306, + 942, 297, 942, 1288, 734, 942, 427, 299, 305, 305, + 305, 305, 305, 305, 305, 305, 305, 305, 305, 822, + 307, 307, 420, 407, 420, 407, 306, 306, 306, 1286, + 306, 307, 308, 308, 737, 407, 307, 1284, 310, 310, + + 766, 1282, 407, 308, 822, 331, 331, 771, 308, 310, + 822, 1280, 1278, 766, 310, 771, 331, 306, 1273, 1271, + 414, 331, 414, 307, 307, 307, 407, 307, 414, 1267, + 1265, 766, 414, 407, 1243, 308, 308, 308, 771, 308, + 835, 310, 310, 310, 766, 310, 771, 1223, 331, 331, + 331, 1158, 331, 1152, 307, 1147, 307, 1141, 1140, 414, + 740, 740, 740, 414, 332, 332, 308, 753, 753, 753, + 1139, 835, 310, 318, 318, 332, 1138, 318, 318, 331, + 332, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 860, 318, 318, 318, 318, 318, 319, 319, 319, 319, + + 319, 319, 319, 319, 319, 319, 319, 332, 332, 332, + 361, 332, 1137, 1135, 768, 1132, 876, 1131, 768, 860, + 1125, 860, 318, 318, 318, 412, 318, 412, 333, 333, + 1122, 422, 1120, 422, 1111, 335, 335, 412, 332, 333, + 332, 740, 1109, 422, 333, 768, 335, 876, 753, 768, + 412, 335, 422, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 325, 769, 325, 412, 1106, + 769, 333, 333, 333, 422, 333, 877, 325, 335, 335, + 335, 412, 335, 422, 1105, 1103, 361, 361, 361, 361, + 361, 361, 361, 361, 361, 361, 361, 769, 362, 362, + + 362, 769, 333, 1101, 363, 363, 363, 877, 325, 335, + 362, 364, 364, 364, 786, 362, 363, 1095, 1081, 1078, + 770, 363, 786, 364, 1077, 1057, 1056, 770, 364, 972, + 971, 325, 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 362, 362, 362, 786, 362, 970, 363, 363, + 363, 770, 363, 786, 969, 364, 364, 364, 770, 364, + 366, 366, 366, 968, 436, 966, 436, 963, 962, 377, + 377, 775, 366, 362, 961, 960, 436, 366, 775, 363, + 377, 363, 954, 950, 788, 377, 364, 376, 376, 376, + 376, 376, 376, 376, 376, 376, 376, 376, 383, 413, + + 788, 413, 775, 948, 366, 366, 366, 436, 366, 775, + 944, 413, 377, 377, 377, 788, 377, 378, 378, 937, + 935, 931, 413, 379, 379, 929, 925, 920, 378, 917, + 909, 788, 904, 378, 379, 366, 369, 369, 878, 379, + 369, 369, 413, 377, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 413, 369, 369, 369, 369, 369, 903, + 378, 378, 378, 781, 378, 781, 379, 379, 379, 878, + 379, 383, 383, 383, 383, 383, 383, 383, 383, 383, + 383, 383, 802, 864, 802, 369, 369, 369, 433, 369, + 433, 378, 900, 378, 781, 899, 781, 379, 896, 433, + + 433, 464, 464, 464, 464, 464, 464, 464, 464, 464, + 464, 464, 864, 802, 864, 802, 369, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 369, 369, 370, 370, + 433, 433, 370, 370, 370, 370, 370, 370, 370, 370, + 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, + 373, 373, 895, 883, 373, 373, 373, 373, 373, 373, + 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, + 373, 373, 381, 381, 809, 418, 809, 418, 385, 385, + 385, 879, 875, 381, 386, 386, 386, 418, 381, 385, + 866, 853, 845, 844, 385, 386, 761, 387, 387, 387, + + 386, 754, 752, 738, 418, 809, 732, 809, 387, 720, + 718, 717, 425, 387, 425, 381, 381, 381, 418, 381, + 880, 385, 385, 385, 425, 385, 715, 386, 386, 386, + 710, 386, 389, 389, 389, 418, 373, 373, 425, 373, + 387, 387, 387, 389, 387, 400, 381, 400, 389, 706, + 881, 880, 385, 702, 429, 425, 429, 400, 386, 696, + 386, 415, 429, 415, 400, 694, 429, 803, 453, 425, + 453, 387, 400, 415, 681, 389, 389, 389, 679, 389, + 453, 881, 410, 803, 410, 674, 415, 670, 400, 415, + 410, 666, 410, 429, 410, 400, 772, 429, 803, 882, + + 416, 410, 416, 400, 415, 772, 389, 398, 410, 398, + 772, 453, 416, 659, 803, 646, 417, 415, 417, 398, + 415, 410, 416, 410, 417, 410, 644, 772, 417, 774, + 882, 777, 410, 774, 639, 777, 772, 884, 417, 410, + 635, 772, 419, 416, 419, 423, 424, 423, 424, 631, + 398, 624, 623, 416, 419, 417, 423, 423, 424, 417, + 774, 419, 777, 776, 774, 424, 777, 622, 884, 417, + 776, 423, 423, 398, 398, 398, 398, 398, 398, 398, + 398, 398, 398, 398, 618, 419, 617, 423, 423, 424, + 615, 611, 419, 426, 776, 426, 424, 428, 430, 428, + + 430, 776, 423, 423, 432, 426, 432, 610, 608, 428, + 430, 426, 434, 426, 434, 430, 432, 435, 437, 435, + 437, 779, 428, 432, 434, 814, 814, 789, 558, 435, + 437, 789, 779, 438, 556, 438, 426, 434, 435, 773, + 428, 430, 426, 437, 426, 438, 430, 432, 773, 438, + 546, 885, 779, 428, 432, 434, 814, 814, 789, 782, + 435, 437, 789, 779, 544, 442, 782, 442, 434, 435, + 773, 538, 536, 440, 437, 440, 438, 442, 531, 773, + 438, 439, 885, 439, 790, 440, 441, 442, 441, 439, + 782, 785, 440, 439, 439, 790, 791, 782, 441, 791, + + 785, 440, 439, 440, 439, 441, 529, 439, 442, 443, + 439, 443, 797, 441, 508, 790, 440, 443, 442, 797, + 439, 443, 785, 440, 439, 439, 790, 791, 507, 441, + 791, 785, 440, 439, 440, 439, 441, 444, 439, 444, + 505, 439, 503, 797, 441, 444, 787, 478, 443, 444, + 797, 445, 443, 445, 446, 787, 446, 447, 780, 447, + 445, 805, 448, 445, 448, 447, 446, 886, 780, 447, + 449, 450, 449, 450, 448, 805, 444, 787, 448, 446, + 444, 449, 449, 450, 449, 447, 787, 450, 475, 780, + 473, 445, 805, 793, 445, 463, 447, 446, 886, 780, + + 447, 461, 858, 793, 800, 448, 805, 858, 800, 448, + 446, 393, 449, 449, 450, 449, 447, 451, 450, 451, + 452, 454, 452, 454, 793, 455, 806, 455, 465, 451, + 465, 796, 452, 454, 793, 800, 451, 455, 858, 800, + 465, 796, 451, 391, 887, 452, 806, 390, 454, 388, + 458, 458, 456, 382, 459, 459, 380, 806, 460, 460, + 451, 458, 796, 452, 454, 459, 458, 451, 455, 460, + 459, 465, 796, 451, 460, 887, 452, 806, 825, 454, + 456, 456, 456, 456, 456, 456, 456, 456, 456, 456, + 456, 375, 371, 458, 458, 458, 825, 459, 459, 459, + + 367, 460, 460, 460, 462, 462, 365, 470, 470, 825, + 721, 359, 721, 354, 350, 462, 345, 341, 470, 729, + 462, 729, 721, 470, 458, 336, 324, 825, 459, 321, + 459, 729, 460, 469, 469, 469, 469, 469, 469, 469, + 469, 469, 469, 469, 471, 471, 812, 462, 462, 462, + 470, 470, 470, 721, 470, 471, 472, 472, 311, 812, + 471, 309, 729, 474, 474, 300, 291, 472, 725, 280, + 725, 725, 472, 725, 474, 479, 278, 812, 462, 474, + 726, 470, 726, 725, 819, 815, 804, 471, 471, 471, + 812, 471, 726, 755, 819, 755, 481, 804, 815, 472, + + 472, 472, 726, 472, 888, 755, 474, 474, 474, 267, + 474, 256, 254, 245, 725, 819, 815, 804, 471, 480, + 471, 243, 231, 726, 225, 819, 224, 481, 804, 815, + 472, 482, 216, 726, 215, 888, 755, 474, 211, 479, + 479, 479, 479, 479, 479, 479, 479, 479, 479, 479, + 480, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 482, 480, 480, 480, 480, 480, 480, 480, + 480, 480, 480, 480, 483, 484, 811, 813, 811, 813, + 816, 856, 798, 808, 816, 482, 482, 482, 482, 482, + 482, 482, 482, 482, 482, 482, 485, 798, 808, 856, + + 889, 897, 897, 897, 195, 483, 484, 811, 813, 811, + 813, 816, 856, 798, 808, 816, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 485, 798, 808, + 856, 889, 483, 483, 483, 483, 483, 483, 483, 483, + 483, 483, 483, 486, 486, 486, 486, 486, 486, 486, + 486, 486, 486, 486, 485, 485, 485, 485, 485, 485, + 485, 485, 485, 485, 485, 487, 487, 487, 487, 487, + 487, 487, 487, 487, 487, 487, 492, 492, 492, 890, + 194, 188, 897, 187, 180, 179, 162, 492, 160, 492, + 492, 148, 146, 144, 124, 526, 526, 526, 817, 821, + + 810, 492, 492, 834, 492, 817, 525, 526, 111, 105, + 890, 810, 526, 492, 821, 492, 834, 492, 522, 522, + 522, 522, 522, 522, 522, 522, 522, 522, 522, 817, + 821, 810, 492, 492, 834, 492, 817, 73, 72, 526, + 526, 526, 810, 526, 492, 821, 492, 834, 492, 539, + 69, 59, 36, 901, 901, 901, 492, 492, 492, 492, + 492, 492, 492, 492, 492, 492, 492, 493, 493, 493, + 526, 35, 833, 838, 34, 891, 833, 838, 493, 33, + 493, 493, 525, 525, 525, 525, 525, 525, 525, 525, + 525, 525, 525, 527, 527, 527, 0, 0, 0, 905, + + 905, 905, 820, 833, 838, 527, 891, 833, 838, 820, + 527, 532, 532, 532, 532, 532, 532, 532, 532, 532, + 532, 532, 539, 539, 539, 539, 539, 539, 539, 539, + 539, 539, 539, 820, 901, 0, 0, 527, 527, 527, + 820, 527, 892, 0, 0, 0, 0, 493, 493, 493, + 493, 493, 493, 493, 493, 493, 493, 493, 502, 502, + 502, 0, 0, 502, 502, 824, 824, 824, 527, 502, + 527, 502, 502, 892, 502, 528, 528, 528, 862, 502, + 905, 530, 530, 530, 862, 0, 826, 528, 533, 533, + 0, 824, 528, 530, 0, 0, 0, 826, 530, 533, + + 534, 534, 0, 0, 533, 893, 502, 502, 502, 862, + 502, 534, 0, 0, 0, 862, 534, 826, 0, 528, + 528, 528, 824, 528, 837, 530, 530, 530, 826, 530, + 0, 533, 533, 533, 828, 533, 893, 502, 535, 535, + 837, 828, 910, 534, 534, 534, 824, 534, 0, 535, + 528, 0, 537, 537, 535, 837, 530, 0, 831, 541, + 541, 541, 533, 537, 0, 828, 0, 831, 537, 911, + 541, 837, 828, 910, 534, 541, 534, 542, 542, 542, + 0, 535, 535, 535, 0, 535, 0, 0, 542, 831, + 0, 0, 859, 542, 0, 537, 537, 537, 831, 537, + + 911, 0, 541, 541, 541, 727, 541, 727, 830, 836, + 830, 859, 535, 918, 543, 543, 543, 727, 836, 830, + 542, 542, 542, 859, 542, 543, 537, 545, 545, 545, + 543, 727, 550, 541, 549, 865, 857, 865, 545, 830, + 836, 830, 859, 545, 918, 0, 0, 0, 727, 836, + 830, 542, 0, 542, 0, 0, 857, 543, 543, 543, + 0, 543, 727, 550, 0, 549, 865, 857, 865, 921, + 545, 545, 545, 0, 545, 549, 549, 549, 549, 549, + 549, 549, 549, 549, 549, 549, 551, 857, 543, 550, + 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, + + 921, 545, 559, 559, 559, 559, 559, 559, 559, 559, + 559, 559, 559, 0, 551, 551, 551, 551, 551, 551, + 551, 551, 551, 551, 551, 553, 553, 0, 554, 554, + 0, 555, 555, 932, 557, 557, 553, 0, 0, 554, + 0, 553, 555, 0, 554, 557, 0, 555, 0, 0, + 557, 560, 560, 560, 560, 560, 560, 560, 560, 560, + 560, 560, 951, 841, 932, 0, 841, 952, 553, 553, + 553, 554, 554, 554, 555, 555, 555, 557, 557, 557, + 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, + 640, 0, 0, 951, 841, 641, 641, 841, 952, 553, + + 0, 0, 554, 650, 554, 555, 641, 0, 557, 633, + 633, 641, 955, 633, 633, 0, 0, 633, 633, 633, + 633, 633, 633, 633, 633, 633, 0, 633, 633, 633, + 633, 633, 649, 956, 650, 0, 0, 0, 641, 641, + 641, 0, 641, 955, 908, 908, 908, 650, 650, 650, + 650, 650, 650, 650, 650, 650, 650, 650, 633, 633, + 633, 0, 633, 649, 956, 0, 919, 919, 919, 641, + 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, + 649, 0, 924, 924, 924, 0, 0, 0, 0, 633, + 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, + + 633, 634, 634, 0, 0, 634, 634, 634, 634, 634, + 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, + 634, 634, 634, 637, 637, 908, 0, 637, 637, 637, + 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, + 637, 637, 637, 637, 637, 642, 642, 919, 936, 936, + 936, 643, 643, 0, 957, 861, 642, 645, 645, 0, + 0, 642, 643, 924, 0, 0, 861, 643, 645, 0, + 0, 0, 0, 645, 654, 654, 654, 654, 654, 654, + 654, 654, 654, 654, 654, 957, 861, 0, 642, 642, + 642, 651, 642, 941, 643, 643, 643, 861, 643, 958, + + 645, 645, 645, 941, 645, 0, 0, 676, 676, 637, + 637, 0, 637, 0, 0, 652, 0, 959, 676, 642, + 0, 642, 651, 676, 0, 643, 0, 0, 0, 936, + 958, 645, 0, 0, 941, 651, 651, 651, 651, 651, + 651, 651, 651, 651, 651, 651, 652, 653, 959, 979, + 676, 676, 676, 0, 676, 652, 652, 652, 652, 652, + 652, 652, 652, 652, 652, 652, 655, 655, 655, 655, + 655, 655, 655, 655, 655, 655, 655, 0, 653, 0, + 979, 676, 0, 653, 653, 653, 653, 653, 653, 653, + 653, 653, 653, 653, 668, 668, 0, 0, 668, 668, + + 0, 0, 668, 668, 668, 668, 668, 668, 668, 668, + 668, 683, 668, 668, 668, 668, 668, 675, 675, 675, + 675, 675, 675, 675, 675, 675, 675, 675, 686, 686, + 686, 686, 686, 686, 686, 686, 686, 686, 686, 0, + 980, 990, 683, 668, 668, 668, 0, 668, 0, 683, + 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, + 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, + 687, 980, 990, 0, 668, 668, 668, 668, 668, 668, + 668, 668, 668, 668, 668, 668, 669, 669, 0, 0, + 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, + + 669, 669, 669, 669, 669, 669, 669, 669, 672, 672, + 0, 0, 672, 672, 672, 672, 672, 672, 672, 672, + 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, + 677, 677, 0, 938, 0, 938, 678, 678, 0, 0, + 0, 677, 680, 680, 0, 938, 677, 678, 0, 0, + 0, 0, 678, 680, 0, 0, 0, 827, 680, 690, + 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, + 827, 982, 827, 677, 677, 677, 938, 677, 684, 678, + 678, 678, 947, 678, 982, 680, 680, 680, 827, 680, + 949, 949, 949, 0, 672, 672, 0, 672, 685, 947, + + 0, 827, 982, 827, 677, 0, 677, 0, 0, 684, + 678, 0, 0, 947, 0, 982, 680, 0, 684, 684, + 684, 684, 684, 684, 684, 684, 684, 684, 684, 685, + 947, 953, 953, 953, 685, 685, 685, 685, 685, 685, + 685, 685, 685, 685, 685, 691, 691, 0, 965, 965, + 965, 692, 692, 0, 986, 991, 691, 693, 693, 0, + 986, 691, 692, 695, 695, 0, 0, 692, 693, 0, + 0, 949, 832, 693, 695, 0, 0, 0, 839, 695, + 863, 967, 832, 967, 832, 986, 991, 839, 691, 691, + 691, 986, 691, 967, 692, 692, 692, 697, 692, 863, + + 693, 693, 693, 832, 693, 992, 695, 695, 695, 839, + 695, 863, 953, 832, 0, 832, 0, 0, 839, 691, + 0, 0, 0, 0, 967, 692, 0, 692, 697, 965, + 863, 693, 0, 0, 0, 0, 992, 695, 0, 0, + 0, 697, 697, 697, 697, 697, 697, 697, 697, 697, + 697, 697, 698, 698, 698, 698, 698, 698, 698, 698, + 698, 698, 698, 699, 699, 699, 699, 699, 699, 699, + 699, 699, 699, 699, 704, 704, 0, 0, 704, 704, + 0, 0, 704, 704, 704, 704, 704, 704, 704, 704, + 704, 0, 704, 704, 704, 704, 704, 711, 711, 711, + + 711, 711, 711, 711, 711, 711, 711, 711, 728, 728, + 728, 728, 728, 728, 728, 728, 728, 728, 728, 977, + 984, 977, 984, 704, 704, 704, 0, 704, 746, 746, + 746, 746, 746, 746, 746, 746, 746, 746, 746, 748, + 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, + 977, 984, 977, 984, 704, 704, 704, 704, 704, 704, + 704, 704, 704, 704, 704, 704, 705, 705, 0, 0, + 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, + 705, 705, 705, 705, 705, 705, 705, 705, 708, 708, + 0, 0, 708, 708, 708, 708, 708, 708, 708, 708, + + 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, + 712, 712, 975, 997, 978, 0, 713, 713, 978, 975, + 0, 712, 714, 714, 0, 987, 712, 713, 0, 0, + 0, 0, 713, 714, 0, 716, 716, 985, 714, 985, + 1001, 1003, 987, 975, 997, 978, 716, 747, 0, 978, + 975, 716, 0, 712, 712, 712, 987, 712, 0, 713, + 713, 713, 751, 713, 1002, 714, 714, 714, 985, 714, + 985, 1001, 1003, 987, 708, 708, 1002, 708, 716, 716, + 716, 0, 716, 989, 712, 989, 0, 1005, 0, 762, + 713, 762, 713, 0, 0, 1002, 714, 750, 750, 750, + + 750, 750, 750, 750, 750, 750, 750, 750, 0, 716, + 724, 0, 724, 0, 989, 0, 989, 993, 1005, 998, + 993, 998, 724, 747, 747, 747, 747, 747, 747, 747, + 747, 747, 747, 747, 0, 751, 751, 751, 751, 751, + 751, 751, 751, 751, 751, 751, 763, 0, 993, 0, + 998, 993, 998, 724, 0, 762, 762, 762, 762, 762, + 762, 762, 762, 762, 762, 762, 1100, 1100, 1100, 1108, + 1108, 1108, 0, 1100, 0, 0, 724, 724, 724, 724, + 724, 724, 724, 724, 724, 724, 724, 749, 749, 0, + 0, 749, 749, 0, 0, 749, 749, 749, 749, 749, + + 749, 749, 749, 749, 988, 749, 749, 749, 749, 749, + 0, 988, 763, 763, 763, 763, 763, 763, 763, 763, + 763, 763, 763, 842, 842, 842, 842, 842, 842, 842, + 842, 842, 842, 842, 994, 988, 749, 749, 749, 0, + 749, 846, 988, 0, 0, 0, 0, 1100, 0, 840, + 1108, 994, 976, 999, 1006, 999, 1009, 1016, 840, 0, + 0, 976, 840, 0, 0, 994, 843, 749, 749, 749, + 749, 749, 749, 749, 749, 749, 749, 749, 749, 760, + 840, 760, 994, 976, 999, 1006, 999, 1009, 1016, 840, + 847, 760, 976, 840, 843, 843, 843, 843, 843, 843, + + 843, 843, 843, 843, 843, 846, 846, 846, 846, 846, + 846, 846, 846, 846, 846, 846, 0, 0, 0, 0, + 0, 847, 760, 847, 847, 847, 847, 847, 847, 847, + 847, 847, 847, 847, 848, 849, 1000, 0, 1004, 1010, + 1000, 1010, 1017, 1024, 1004, 760, 760, 760, 760, 760, + 760, 760, 760, 760, 760, 760, 764, 0, 0, 0, + 0, 0, 0, 0, 0, 848, 849, 1000, 764, 1004, + 1010, 1000, 1010, 1017, 1024, 1004, 849, 849, 849, 849, + 849, 849, 849, 849, 849, 849, 849, 850, 848, 848, + 848, 848, 848, 848, 848, 848, 848, 848, 848, 764, + + 0, 0, 0, 1008, 1011, 1014, 1011, 1039, 1014, 851, + 1039, 0, 0, 0, 0, 1008, 0, 868, 850, 0, + 0, 0, 764, 764, 764, 764, 764, 764, 764, 764, + 764, 764, 764, 852, 1008, 1011, 1014, 1011, 1039, 1014, + 851, 1039, 850, 850, 850, 850, 850, 850, 850, 850, + 850, 850, 850, 851, 851, 851, 851, 851, 851, 851, + 851, 851, 851, 851, 852, 867, 867, 867, 867, 867, + 867, 867, 867, 867, 867, 867, 0, 0, 0, 0, + 0, 852, 852, 852, 852, 852, 852, 852, 852, 852, + 852, 852, 854, 868, 868, 868, 868, 868, 868, 868, + + 868, 868, 868, 868, 869, 869, 869, 869, 869, 869, + 869, 869, 869, 869, 869, 854, 870, 873, 873, 873, + 873, 873, 873, 873, 873, 873, 873, 873, 906, 906, + 906, 906, 906, 906, 906, 906, 906, 906, 906, 871, + 0, 1028, 1053, 1028, 1037, 1037, 854, 922, 922, 922, + 922, 922, 922, 922, 922, 922, 922, 922, 854, 854, + 854, 854, 854, 854, 854, 854, 854, 854, 854, 855, + 871, 872, 1028, 1053, 1028, 1037, 1037, 855, 871, 871, + 871, 871, 871, 871, 871, 871, 871, 871, 871, 870, + 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, + + 1046, 912, 872, 1046, 0, 0, 0, 0, 855, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 872, 872, + 872, 872, 872, 872, 872, 872, 872, 872, 872, 874, + 0, 1046, 912, 0, 1046, 855, 855, 855, 855, 855, + 855, 855, 855, 855, 855, 855, 912, 912, 912, 912, + 912, 912, 912, 912, 912, 912, 912, 874, 874, 874, + 874, 874, 874, 874, 874, 874, 874, 874, 907, 907, + 916, 0, 907, 907, 0, 0, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 913, 907, 907, 907, 907, + 907, 1038, 1026, 1038, 1043, 1043, 1020, 1026, 996, 916, + + 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, + 0, 914, 996, 1020, 1030, 1055, 913, 907, 907, 907, + 0, 907, 1038, 1026, 1038, 1043, 1043, 1020, 1026, 996, + 1030, 913, 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 914, 996, 1020, 1030, 1055, 0, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 915, 1030, 1045, 1067, 1067, 0, 1045, 1082, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, 914, 933, + 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, + 0, 915, 0, 1045, 1067, 1067, 926, 1045, 1082, 915, + + 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, + 923, 923, 0, 0, 923, 923, 0, 0, 923, 923, + 923, 923, 923, 923, 923, 923, 923, 926, 923, 923, + 923, 923, 923, 927, 1047, 1083, 1047, 0, 1027, 0, + 1012, 926, 926, 926, 926, 926, 926, 926, 926, 926, + 926, 926, 0, 1012, 1068, 1027, 1084, 1068, 1085, 923, + 923, 923, 0, 923, 927, 1047, 1083, 1047, 945, 1027, + 945, 1012, 927, 927, 927, 927, 927, 927, 927, 927, + 927, 927, 927, 928, 1012, 1068, 1027, 1084, 1068, 1085, + 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, + + 923, 923, 930, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 928, 928, 928, 928, 928, 928, 928, 928, + 928, 928, 928, 0, 0, 0, 0, 0, 0, 0, + 1086, 1087, 0, 930, 945, 945, 945, 945, 945, 945, + 945, 945, 945, 945, 945, 0, 0, 0, 930, 930, + 930, 930, 930, 930, 930, 930, 930, 930, 930, 934, + 934, 1086, 1087, 934, 934, 1088, 0, 934, 934, 934, + 934, 934, 934, 934, 934, 934, 983, 934, 934, 934, + 934, 934, 981, 995, 1013, 983, 981, 1015, 1007, 1007, + 1007, 0, 1018, 995, 1031, 981, 1088, 1022, 1013, 1023, + + 1015, 1018, 1089, 1031, 1022, 1090, 1023, 983, 934, 934, + 934, 0, 934, 981, 995, 1013, 983, 981, 1015, 0, + 1019, 1019, 1019, 1018, 995, 1031, 981, 1007, 1022, 1013, + 1023, 1015, 1018, 1089, 1031, 1022, 1090, 1023, 0, 934, + 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, + 934, 943, 1021, 943, 1025, 1029, 1032, 1033, 1007, 1019, + 1040, 1041, 1029, 943, 1071, 1021, 1044, 1025, 0, 1007, + 0, 1032, 1033, 1040, 1071, 1036, 1036, 1036, 1041, 0, + 1091, 1044, 1093, 1021, 0, 1025, 1029, 1032, 1033, 0, + 1019, 1040, 1041, 1029, 943, 1071, 1021, 1044, 1025, 1035, + + 1035, 1019, 1032, 1033, 1040, 1071, 0, 0, 1035, 1041, + 1035, 1091, 1044, 1093, 1036, 1035, 1042, 943, 943, 943, + 943, 943, 943, 943, 943, 943, 943, 943, 946, 1042, + 1049, 1048, 0, 1051, 1094, 1096, 1050, 946, 1054, 1072, + 1073, 1049, 1035, 1035, 1035, 1036, 1035, 1042, 1048, 1050, + 1051, 1054, 1070, 1072, 1073, 1058, 1036, 1097, 1098, 1099, + 1042, 1049, 1048, 1070, 1051, 1094, 1096, 1050, 946, 1054, + 1072, 1073, 1049, 1035, 0, 1035, 0, 1059, 1052, 1048, + 1050, 1051, 1054, 1070, 1072, 1073, 0, 1052, 1097, 1098, + 1099, 0, 0, 0, 946, 946, 946, 946, 946, 946, + + 946, 946, 946, 946, 946, 973, 0, 973, 1059, 1052, + 0, 1104, 1104, 1104, 1060, 1104, 1076, 973, 1052, 1058, + 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, + 1076, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, + 1059, 1059, 0, 0, 0, 1060, 0, 1076, 973, 1060, + 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, + 1061, 1076, 1102, 1102, 1102, 1119, 1119, 1119, 0, 1102, + 0, 973, 973, 973, 973, 973, 973, 973, 973, 973, + 973, 973, 974, 1062, 0, 0, 1124, 1124, 1124, 0, + 0, 1061, 1104, 0, 1061, 1061, 1061, 1061, 1061, 1061, + + 1061, 1061, 1061, 1061, 1061, 0, 1110, 974, 0, 1117, + 0, 1121, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, + 1062, 1062, 1062, 1064, 1064, 1064, 1064, 1064, 1064, 1064, + 1064, 1064, 1064, 1064, 1074, 1075, 1065, 1110, 974, 1065, + 1117, 1074, 1121, 1102, 0, 1075, 1119, 0, 974, 974, + 974, 974, 974, 974, 974, 974, 974, 974, 974, 1034, + 1034, 1034, 1144, 0, 0, 1074, 1075, 1124, 1149, 0, + 1144, 0, 1074, 1115, 1115, 1115, 1075, 1216, 1115, 0, + 1034, 0, 1217, 1034, 1034, 1218, 1115, 1219, 1220, 1134, + 1134, 1134, 1216, 1144, 1034, 1034, 1034, 1063, 0, 1149, + + 1034, 1144, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, + 1065, 1065, 1065, 1217, 1034, 1034, 1218, 0, 1219, 1220, + 0, 0, 0, 1216, 1115, 1034, 1034, 1034, 1063, 1079, + 0, 1034, 1146, 1146, 1146, 1151, 1151, 1151, 1080, 0, + 1034, 1221, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, + 1063, 1063, 1063, 1066, 1115, 0, 1066, 0, 1079, 1079, + 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1080, + 1134, 0, 1221, 1222, 0, 1112, 0, 1263, 1264, 1066, + 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, + 1129, 0, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, + + 1080, 1080, 1080, 0, 1222, 1136, 1112, 1136, 1263, 1264, + 1066, 0, 0, 1146, 1266, 0, 1151, 1136, 1268, 1066, + 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, + 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, + 1112, 1113, 1113, 1113, 0, 1266, 1113, 0, 1136, 1268, + 0, 1114, 1114, 1114, 1113, 1269, 1114, 1116, 1116, 1116, + 1127, 0, 1116, 1159, 1114, 1159, 0, 0, 0, 0, + 1116, 0, 1254, 1114, 1254, 1159, 1164, 1164, 1164, 1253, + 1256, 1116, 1270, 1255, 1126, 0, 1269, 0, 1255, 1127, + 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, + + 1253, 1256, 1128, 1254, 1114, 1254, 1159, 1162, 1162, 1162, + 1253, 1256, 1116, 1270, 1255, 1126, 1165, 1165, 1165, 1255, + 0, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, + 1113, 1113, 1114, 1128, 1166, 1166, 1166, 0, 1116, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1163, 1163, 1163, 0, 1162, 1272, 1274, 1164, 1128, 1128, + 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1142, + 0, 1142, 0, 1163, 1259, 1168, 1168, 1168, 0, 1259, + 1166, 1142, 1167, 1167, 1167, 1162, 1272, 1274, 1162, 1170, + 1170, 1170, 0, 0, 1169, 1169, 1169, 1165, 1171, 1171, + + 1171, 1172, 1172, 1172, 1163, 1259, 0, 1175, 1175, 1175, + 1259, 1166, 1142, 0, 0, 1166, 1168, 1167, 1169, 1173, + 1173, 1173, 1174, 1174, 1174, 0, 1275, 1172, 1276, 1170, + 0, 1163, 0, 1175, 0, 1142, 1142, 1142, 1142, 1142, + 1142, 1142, 1142, 1142, 1142, 1142, 1143, 1168, 1167, 1169, + 1176, 1176, 1176, 1260, 1143, 1173, 1168, 1275, 1172, 1276, + 1170, 1174, 1277, 1167, 1175, 1177, 1177, 1177, 0, 0, + 1170, 1178, 1178, 1178, 1260, 1169, 1176, 1292, 1293, 1171, + 0, 0, 1172, 0, 1260, 1143, 1173, 0, 1175, 1179, + 1179, 1179, 1174, 1277, 0, 1177, 0, 1180, 1180, 1180, + + 1173, 0, 0, 1174, 1183, 1183, 1183, 1176, 1292, 1293, + 0, 1178, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, + 1143, 1143, 1143, 1160, 0, 1160, 1177, 1180, 1303, 1341, + 1179, 1176, 1181, 1181, 1181, 1160, 1182, 1182, 1182, 1186, + 1186, 1186, 1178, 1188, 1188, 1188, 1177, 1185, 1185, 1185, + 0, 0, 1178, 1342, 0, 1181, 0, 0, 1180, 1303, + 1341, 1179, 1187, 1187, 1187, 0, 1160, 1184, 1184, 1184, + 1179, 0, 1193, 1193, 1193, 1185, 1186, 1353, 1180, 0, + 1189, 1189, 1189, 0, 1342, 1183, 1181, 1182, 1187, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + + 1161, 1161, 1161, 0, 0, 0, 1185, 1186, 1353, 1311, + 1190, 1190, 1190, 1181, 1161, 0, 0, 1182, 1184, 1187, + 1186, 1189, 0, 1311, 1188, 0, 0, 0, 1185, 0, + 1191, 1191, 1192, 1192, 1192, 1195, 1195, 1195, 1190, 1191, + 1311, 1191, 0, 1187, 0, 1369, 1191, 1190, 1184, 0, + 1195, 0, 1189, 1193, 1311, 1194, 1194, 1194, 1198, 1198, + 1198, 1189, 1192, 0, 0, 1196, 1196, 1196, 0, 1190, + 1199, 1199, 1199, 1191, 1191, 1191, 1369, 1191, 1190, 1370, + 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, + 1161, 1190, 1371, 1192, 1194, 1196, 1197, 1197, 1197, 1198, + + 1200, 1200, 1200, 0, 1191, 0, 1191, 1201, 1201, 1201, + 1370, 1202, 1202, 1192, 1372, 0, 1195, 1204, 1204, 1204, + 1202, 1374, 1202, 1371, 0, 1194, 1196, 1202, 0, 0, + 1198, 1257, 1197, 1205, 1205, 1205, 1194, 0, 0, 1198, + 1376, 1200, 1257, 1378, 1201, 1372, 1196, 1203, 1203, 1203, + 0, 1199, 1374, 0, 1202, 1202, 1202, 0, 1202, 1206, + 1206, 1206, 1257, 1197, 1207, 1207, 1207, 1208, 1208, 1208, + 0, 1376, 1200, 1257, 1378, 1201, 0, 1197, 1209, 1209, + 1209, 1200, 1210, 1210, 1210, 1202, 1203, 1202, 1201, 1211, + 1211, 1211, 0, 1208, 1212, 1212, 1212, 0, 1204, 1213, + + 1213, 1213, 1209, 0, 1207, 1214, 1214, 1214, 1368, 1215, + 1215, 1215, 1368, 1368, 1205, 1211, 1212, 1203, 1227, 1227, + 1227, 1229, 1229, 1229, 1208, 1231, 1231, 1231, 1203, 1226, + 1226, 1226, 0, 1209, 1213, 1207, 1258, 1379, 0, 1368, + 1206, 1214, 1258, 1368, 1368, 1207, 1211, 1212, 1208, 0, + 1215, 1381, 0, 1225, 1225, 1228, 1228, 1228, 1226, 1209, + 0, 0, 1225, 1210, 1225, 1213, 0, 1258, 1379, 1225, + 1211, 0, 1214, 1258, 0, 1212, 1234, 1234, 1234, 0, + 1213, 1215, 1381, 1230, 1230, 1230, 1214, 0, 0, 1226, + 1215, 1224, 1224, 1224, 0, 1228, 1225, 1225, 1225, 1227, + + 1225, 0, 1229, 1238, 1238, 1238, 1231, 1382, 1230, 0, + 1226, 1239, 1239, 1239, 1224, 1224, 1224, 1224, 1224, 1224, + 0, 1224, 1383, 1224, 1384, 1224, 1228, 1225, 1224, 1225, + 1385, 1224, 1224, 0, 0, 1224, 1228, 0, 1382, 1230, + 1237, 1237, 1237, 0, 0, 1224, 1224, 1224, 1224, 1224, + 1224, 1239, 1224, 1383, 1224, 1384, 1224, 1234, 1308, 1224, + 1308, 1385, 1224, 1224, 1230, 1237, 1224, 1232, 1232, 1232, + 1308, 0, 1224, 1233, 1233, 1233, 1235, 1235, 1235, 1236, + 1236, 1236, 1239, 1310, 1238, 1240, 1240, 1240, 1314, 1232, + 1314, 0, 1239, 0, 1310, 1233, 1237, 1241, 1241, 1241, + + 1314, 1308, 1235, 1244, 1377, 1236, 1386, 1377, 1240, 1242, + 1242, 1242, 0, 0, 1310, 1380, 1387, 0, 0, 1388, + 1232, 1237, 1281, 1281, 1281, 1310, 1233, 1380, 1409, 1281, + 1387, 1314, 1241, 1235, 1245, 1377, 1236, 1386, 1377, 1240, + 0, 0, 1285, 1285, 1285, 0, 1380, 1387, 1232, 1285, + 1388, 0, 0, 0, 1233, 0, 0, 1235, 1380, 1409, + 1236, 1387, 0, 1241, 0, 1245, 1240, 1244, 1244, 1244, + 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1241, 1245, + 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, + 1242, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + + 1246, 1246, 1247, 1281, 0, 0, 0, 0, 0, 0, + 0, 1248, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, + 1262, 1262, 1262, 1285, 1411, 1413, 1249, 1320, 1320, 1320, + 0, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, + 1247, 1247, 1248, 1289, 1289, 1289, 1413, 1289, 0, 1322, + 1322, 1322, 1325, 1325, 1325, 1411, 1413, 1249, 1331, 1331, + 1331, 1294, 0, 1319, 1319, 1319, 0, 1248, 1248, 1248, + 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1249, 1249, + 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1251, + 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, + + 1294, 0, 1309, 1407, 1309, 1319, 1415, 1407, 1320, 0, + 1309, 1329, 1329, 1329, 1309, 1412, 1251, 0, 1410, 1261, + 1412, 0, 1410, 1416, 1289, 0, 1329, 1295, 1295, 1295, + 1322, 0, 1295, 1325, 1407, 0, 1319, 1415, 1407, 1331, + 1295, 1309, 0, 0, 1319, 1309, 1412, 1251, 1299, 1410, + 1261, 1412, 1295, 1410, 1416, 1251, 1251, 1251, 1251, 1251, + 1251, 1251, 1251, 1251, 1251, 1251, 1252, 1261, 1261, 1261, + 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1418, 1299, + 1419, 1420, 1252, 1295, 0, 1304, 0, 0, 0, 0, + 0, 0, 1329, 0, 1424, 1299, 1299, 1299, 1299, 1299, + + 1299, 1299, 1299, 1299, 1299, 1299, 0, 0, 1295, 1418, + 0, 1419, 1420, 1252, 1304, 1304, 1304, 1304, 1304, 1304, + 1304, 1304, 1304, 1304, 1304, 1424, 0, 0, 0, 0, + 0, 0, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, + 1252, 1252, 1252, 1296, 1296, 1296, 1296, 1296, 1296, 1296, + 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, + 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, + 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, + 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, + 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, + + 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, + 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, + 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, + 1296, 1296, 1296, 1296, 1296, 1298, 1298, 1300, 1426, 1337, + 1337, 1337, 1321, 1321, 1321, 1428, 1298, 1316, 1316, 1316, + 0, 1298, 0, 0, 1301, 0, 0, 0, 0, 0, + 0, 1339, 1339, 1339, 1351, 1351, 1351, 0, 1300, 1426, + 0, 1340, 1340, 1340, 0, 0, 1428, 0, 1298, 1298, + 1298, 1305, 1298, 1321, 1316, 1301, 1340, 1300, 1300, 1300, + 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1301, 1301, + + 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1298, + 0, 1298, 1305, 1306, 1321, 1316, 0, 1318, 1318, 1318, + 1337, 0, 1429, 1321, 0, 0, 0, 0, 1316, 0, + 0, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, + 1305, 1305, 1339, 1318, 1306, 1351, 1323, 1323, 1323, 1324, + 1324, 1324, 1340, 1429, 1315, 1315, 1315, 1306, 1306, 1306, + 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1315, 0, + 1315, 0, 1317, 1317, 1318, 0, 1326, 1326, 1326, 0, + 1315, 1317, 1430, 1317, 1327, 1327, 1327, 1323, 1317, 0, + 1324, 1330, 1330, 1330, 1431, 1328, 1328, 1328, 1318, 0, + + 1326, 0, 1332, 1332, 1332, 1333, 1333, 1333, 1433, 0, + 1327, 1315, 1434, 1430, 1330, 1317, 1317, 1317, 1323, 1317, + 1328, 1324, 1334, 1334, 1334, 1431, 0, 1323, 1332, 0, + 1324, 1326, 1336, 1336, 1336, 1315, 1345, 1345, 1345, 1433, + 1333, 1327, 1435, 1434, 1334, 1330, 1317, 0, 1317, 0, + 0, 1328, 1335, 1335, 1335, 0, 0, 1326, 0, 1332, + 1338, 1338, 1338, 0, 0, 1327, 1345, 1336, 1350, 1350, + 1350, 1333, 1330, 1435, 0, 1334, 1328, 1344, 1344, 1344, + 1346, 1346, 1346, 1332, 0, 0, 1333, 1349, 1349, 1349, + 1408, 1335, 0, 1348, 1348, 1346, 1408, 1345, 1336, 1338, + + 1414, 1350, 1348, 1334, 1348, 1352, 1352, 1352, 1414, 1348, + 0, 1438, 1344, 1336, 1359, 1359, 1359, 1345, 1355, 1355, + 1355, 1408, 1335, 1356, 1356, 1356, 1445, 1408, 1349, 1422, + 1338, 1414, 1350, 1335, 1422, 1352, 1348, 1348, 1348, 1414, + 1348, 1338, 1438, 1344, 1355, 1463, 1356, 0, 0, 1350, + 1358, 1358, 1358, 1468, 1360, 1360, 1360, 1445, 1344, 1349, + 1422, 1346, 1357, 1357, 0, 1422, 1352, 1348, 1349, 1348, + 0, 1357, 1464, 1357, 0, 1355, 1463, 1356, 1357, 1358, + 1360, 1361, 1361, 1361, 1468, 1464, 1352, 1363, 1363, 1363, + 1364, 1364, 1364, 0, 0, 1359, 1365, 1365, 1365, 1355, + + 1366, 1366, 1366, 1464, 1356, 1357, 1357, 1357, 0, 1357, + 1358, 1360, 1362, 1362, 1364, 1361, 1464, 1367, 1367, 1367, + 0, 1362, 1365, 1362, 1390, 1390, 1390, 1491, 1362, 0, + 1492, 1358, 1367, 0, 0, 1360, 1357, 0, 1357, 1391, + 1391, 1391, 1366, 0, 0, 1364, 1361, 1392, 1392, 1392, + 1395, 1395, 1395, 1365, 1500, 1362, 1362, 1362, 1491, 1362, + 1390, 1492, 1361, 1393, 1393, 1393, 1502, 0, 1363, 0, + 0, 1364, 1506, 1366, 1394, 1394, 1394, 1365, 1396, 1396, + 1396, 1366, 1397, 1397, 1397, 1500, 1362, 1393, 1362, 0, + 1514, 1390, 1515, 1396, 1398, 1398, 1398, 1502, 1367, 0, + + 1399, 1399, 1399, 1506, 1461, 1390, 1461, 1516, 1397, 1400, + 1400, 1400, 1517, 0, 1518, 1394, 1461, 1462, 1393, 1462, + 1391, 1514, 1519, 1515, 0, 1462, 1520, 1402, 1392, 1462, + 1466, 1395, 1466, 1399, 1452, 1452, 1452, 1400, 1516, 1397, + 1521, 1522, 1466, 1517, 1393, 1518, 1394, 1461, 1523, 1524, + 0, 0, 1525, 1519, 0, 1394, 1462, 1520, 1526, 1396, + 1462, 0, 0, 1397, 1399, 0, 0, 0, 1400, 0, + 0, 1521, 1522, 1466, 0, 1398, 1470, 1470, 1470, 1523, + 1524, 1399, 1404, 1525, 0, 1472, 1472, 1472, 1405, 1526, + 1400, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, + + 1402, 1402, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, + 1403, 1403, 1403, 1404, 0, 1452, 0, 0, 0, 1405, + 0, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, + 1404, 1404, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, + 1405, 1405, 1405, 1406, 1406, 1406, 1406, 1406, 1406, 1406, + 1406, 1406, 1406, 1406, 1417, 1436, 1527, 1470, 1476, 1476, + 1476, 1528, 1529, 1437, 1437, 1437, 1472, 0, 1437, 1440, + 1440, 1440, 0, 0, 1440, 0, 1437, 1473, 1473, 1473, + 0, 0, 1440, 0, 0, 1417, 1436, 1527, 1437, 1477, + 1477, 1477, 1528, 1529, 1440, 0, 1436, 1436, 1436, 1436, + + 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1473, 1417, 1417, + 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1437, + 1530, 1441, 1441, 1441, 0, 1440, 1441, 1444, 1444, 1444, + 0, 1531, 1444, 1532, 1441, 1471, 1471, 1471, 1473, 1476, + 1444, 1474, 1474, 1474, 1437, 0, 1441, 1467, 1467, 1467, + 1440, 1530, 1444, 0, 0, 1451, 1451, 1451, 1473, 0, + 1451, 1467, 1531, 1467, 1532, 1533, 1534, 1474, 1451, 0, + 1477, 1451, 1535, 1467, 1536, 1537, 1471, 1441, 0, 0, + 1451, 1538, 1539, 1444, 1453, 1453, 1453, 1453, 1453, 1453, + 1453, 1453, 1453, 1453, 1453, 1454, 1533, 1534, 1474, 1478, + + 1478, 1478, 1441, 1535, 1467, 1536, 1537, 1471, 1444, 1446, + 1446, 1451, 1538, 1539, 1478, 0, 1471, 0, 0, 0, + 1446, 0, 1474, 0, 1455, 1446, 1454, 0, 1467, 1563, + 1554, 0, 0, 0, 0, 0, 1451, 1482, 1482, 1482, + 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, + 1454, 1554, 1446, 1446, 1446, 1455, 1446, 1483, 1483, 1483, + 1563, 1554, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, + 1455, 1455, 1455, 1497, 1497, 1497, 0, 0, 0, 0, + 1478, 0, 0, 1446, 1446, 1446, 1446, 1446, 1446, 1446, + 1446, 1446, 1446, 1446, 1446, 1449, 1449, 1449, 1449, 1449, + + 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, + 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1457, 1482, 1565, + 1566, 1449, 1475, 1475, 1475, 1498, 1498, 1498, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1483, 0, + 1458, 0, 0, 0, 1475, 1567, 0, 0, 1457, 0, + 1565, 1566, 1449, 0, 1497, 1488, 1488, 1488, 1457, 1457, + 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1459, + 1488, 1458, 1487, 1487, 1487, 1475, 1567, 1449, 1481, 1481, + 1481, 1449, 1449, 0, 1449, 1458, 1458, 1458, 1458, 1458, + 1458, 1458, 1458, 1458, 1458, 1458, 1484, 1484, 1484, 0, + + 1459, 0, 1487, 1475, 1481, 0, 1498, 1459, 1459, 1459, + 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1480, 1480, + 1484, 1485, 1485, 1485, 1493, 1493, 1493, 1480, 0, 1480, + 1486, 1486, 1486, 1487, 1480, 1481, 1488, 1494, 1494, 1494, + 1499, 1499, 1499, 1501, 1501, 1501, 1504, 1504, 1504, 0, + 0, 1484, 1486, 1487, 1508, 1508, 1508, 1485, 0, 1481, + 0, 1480, 1480, 1480, 1493, 1480, 1505, 1505, 1505, 1490, + 1490, 0, 1568, 1494, 0, 1553, 1499, 1484, 1490, 0, + 1490, 1505, 0, 1486, 1553, 1490, 1508, 0, 1485, 1509, + 1509, 1509, 1480, 0, 1480, 1493, 1510, 1510, 1510, 0, + + 0, 1569, 1485, 1568, 1494, 1493, 1553, 1499, 1540, 1540, + 1540, 1486, 1490, 1490, 1490, 1553, 1490, 1508, 1494, 0, + 0, 1499, 0, 0, 1501, 1556, 0, 1504, 1541, 1541, + 1541, 1510, 1569, 0, 0, 1508, 1511, 1511, 1511, 1513, + 1513, 1556, 0, 1490, 1570, 1490, 0, 1505, 1513, 1540, + 1513, 1511, 1543, 1543, 1543, 1513, 1556, 1511, 1546, 1546, + 1546, 1511, 1510, 0, 1542, 1542, 1542, 1543, 1571, 1541, + 1509, 1572, 1556, 1511, 1555, 1570, 0, 1510, 0, 1555, + 1540, 0, 1513, 1513, 1513, 0, 1513, 1545, 1545, 1540, + 1542, 0, 1511, 1547, 1547, 1547, 1545, 0, 1545, 1571, + + 1541, 0, 1572, 1545, 1511, 1555, 1548, 1548, 1548, 1541, + 1555, 1557, 1558, 1513, 0, 1513, 1557, 1511, 0, 1547, + 1558, 1542, 1559, 1560, 1550, 1573, 1574, 1559, 1560, 1575, + 1545, 1545, 1545, 1543, 1545, 1561, 1576, 1577, 1578, 1546, + 1561, 1583, 1557, 1558, 1585, 1542, 1548, 1557, 0, 1551, + 1547, 1558, 1590, 1559, 1560, 1602, 1573, 1574, 1559, 1560, + 1575, 1545, 0, 1545, 0, 0, 1561, 1576, 1577, 1578, + 0, 1561, 1583, 0, 1547, 1585, 0, 1548, 0, 1552, + 1551, 0, 1606, 1590, 1620, 0, 1602, 1548, 1550, 1550, + 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1551, + + 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, + 1552, 1562, 1579, 1606, 0, 1620, 1613, 1613, 1613, 0, + 0, 0, 0, 0, 1552, 1552, 1552, 1552, 1552, 1552, + 1552, 1552, 1552, 1552, 1552, 0, 1634, 1634, 1634, 1621, + 1628, 0, 1562, 1579, 0, 1562, 1562, 1562, 1562, 1562, + 1562, 1562, 1562, 1562, 1562, 1562, 1579, 1579, 1579, 1579, + 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1580, 1580, 1580, + 1621, 1628, 1580, 1581, 1581, 1581, 0, 0, 1581, 0, + 1580, 0, 1582, 1582, 1582, 0, 1581, 1582, 1584, 1584, + 1584, 0, 1580, 1584, 1600, 1582, 1600, 1613, 1581, 0, + + 1604, 1584, 1604, 1588, 1588, 1588, 1600, 1582, 1588, 1592, + 1592, 1592, 1604, 1584, 1592, 1581, 1588, 1634, 1601, 0, + 1601, 0, 1592, 1580, 1629, 0, 1601, 1633, 1588, 1581, + 1601, 0, 0, 1636, 1592, 0, 0, 1600, 1582, 0, + 0, 0, 1637, 1604, 1584, 1638, 1581, 1642, 1580, 0, + 1610, 1610, 1610, 0, 1581, 1629, 1594, 1601, 1633, 1588, + 0, 1601, 1595, 1582, 1636, 1592, 1605, 1605, 1605, 1584, + 1586, 1586, 1586, 1637, 0, 1586, 1638, 0, 1642, 0, + 1605, 0, 1605, 1586, 1588, 0, 0, 1594, 1596, 1644, + 1592, 1610, 1605, 1595, 1646, 1586, 1594, 1594, 1594, 1594, + + 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1595, 1595, 1595, + 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1647, 1596, + 1644, 0, 1610, 1605, 0, 1646, 1586, 0, 0, 0, + 1597, 1610, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, + 1596, 1596, 1596, 1607, 1607, 1607, 0, 1605, 0, 1647, + 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, + 1586, 1597, 1598, 1608, 1608, 1608, 1609, 1609, 1609, 1607, + 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, + 1597, 1615, 1615, 1615, 0, 0, 1614, 1614, 1614, 1616, + 1616, 1616, 0, 1598, 1622, 1622, 1622, 0, 1648, 1608, + + 1607, 1609, 1617, 1617, 1617, 0, 0, 1598, 1598, 1598, + 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1614, 1645, + 1622, 1649, 1650, 1616, 1607, 1615, 1623, 1623, 1623, 1648, + 1608, 0, 1609, 1652, 1626, 1626, 1626, 1645, 1617, 1627, + 1627, 1627, 1653, 0, 1608, 0, 0, 1609, 0, 1614, + 1645, 1622, 1649, 1650, 1616, 1651, 1615, 1630, 1630, 1630, + 1654, 1655, 1615, 1626, 1652, 1623, 1651, 1614, 1645, 1617, + 1616, 1656, 1630, 1653, 1627, 1622, 1635, 1635, 1635, 1632, + 1632, 1657, 1658, 1617, 0, 1659, 1651, 1660, 1632, 0, + 1632, 1654, 1655, 0, 1626, 1632, 1623, 1651, 1661, 1663, + + 1662, 1664, 1656, 1665, 1666, 1627, 1675, 1623, 1667, 1667, + 1667, 0, 1657, 1658, 0, 1626, 1659, 1635, 1660, 0, + 1627, 1662, 1632, 1632, 1632, 0, 1632, 1679, 1680, 1661, + 1663, 1662, 1664, 1678, 1665, 1666, 1681, 1682, 1630, 1668, + 1668, 1668, 1669, 1669, 1669, 1672, 1672, 1672, 1635, 1673, + 1673, 1673, 1662, 1632, 1678, 1632, 1676, 1635, 1679, 1680, + 0, 1683, 1685, 1686, 1678, 1683, 1689, 1681, 1682, 1668, + 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, + 1675, 0, 1692, 1684, 1693, 1672, 1697, 1676, 1700, 1667, + 1684, 1677, 1683, 1685, 1686, 0, 1683, 1689, 1701, 0, + + 1668, 0, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, + 1676, 1676, 1676, 1692, 1684, 1693, 1672, 1697, 0, 1700, + 1668, 1684, 1677, 1669, 1702, 1703, 1672, 1704, 1706, 1701, + 1673, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, + 1677, 1677, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, + 1687, 1687, 1687, 1710, 0, 1702, 1703, 1731, 1704, 1706, + 0, 1746, 0, 1704, 1704, 1704, 1704, 1704, 1704, 1704, + 1704, 1704, 1704, 1704, 1705, 1705, 1705, 0, 1747, 1705, + 1707, 1707, 1707, 0, 1710, 1707, 0, 1705, 1731, 1708, + 1708, 1708, 1746, 1707, 1708, 1752, 1705, 1755, 0, 1705, + + 0, 1726, 1708, 1726, 0, 1707, 1709, 1709, 1709, 1747, + 0, 1709, 1756, 1726, 1708, 0, 1711, 1711, 1711, 1709, + 0, 1711, 1732, 1732, 1732, 0, 1752, 1705, 1755, 1711, + 1705, 1709, 1711, 1712, 1712, 1712, 1707, 0, 1712, 0, + 0, 1711, 0, 1756, 1726, 1708, 1712, 0, 0, 1712, + 0, 1714, 1714, 1714, 0, 1705, 1714, 1759, 1712, 1761, + 0, 1707, 1709, 0, 1714, 0, 1715, 1715, 1715, 0, + 1708, 1715, 1711, 1716, 1716, 1716, 1714, 0, 1716, 1715, + 1717, 1717, 1717, 0, 0, 1717, 1716, 1709, 1759, 1712, + 1761, 1715, 0, 1717, 1735, 1735, 1735, 1711, 1716, 1718, + + 1718, 1718, 0, 1732, 1718, 1717, 0, 1714, 1719, 1719, + 1719, 0, 1718, 1719, 1712, 1729, 0, 1729, 1762, 1763, + 1735, 1719, 1715, 1727, 1718, 1727, 1767, 1729, 1768, 1716, + 0, 1727, 1714, 1719, 1769, 1727, 1717, 1720, 1770, 1771, + 0, 1718, 1733, 1733, 1733, 1772, 0, 1715, 1773, 1762, + 1763, 1735, 1775, 1776, 1716, 1718, 1777, 1767, 1729, 1768, + 0, 1717, 1727, 0, 1719, 1769, 1727, 0, 1720, 1770, + 1771, 1721, 1718, 0, 0, 1735, 1772, 1733, 1778, 1773, + 1718, 0, 0, 1775, 1776, 0, 0, 1777, 0, 1719, + 1722, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, + + 1720, 1720, 1721, 1734, 1734, 1734, 1723, 1724, 1733, 1778, + 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, + 1721, 1722, 0, 1733, 0, 0, 1722, 1722, 1722, 1722, + 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1723, 1724, 1739, + 1739, 1739, 0, 1779, 1734, 0, 1724, 1724, 1724, 1724, + 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1730, 1730, 1730, + 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, + 1723, 1730, 0, 1730, 1779, 1734, 1738, 1738, 1738, 1740, + 1740, 1740, 1780, 1730, 1734, 1741, 1741, 1741, 1742, 1742, + 1742, 0, 1745, 1745, 1745, 1748, 1748, 1748, 1749, 1749, + + 1749, 1750, 1750, 1750, 1781, 1738, 0, 0, 1751, 1751, + 1751, 1741, 1782, 1780, 1730, 0, 1750, 1783, 1784, 1740, + 1739, 1745, 1754, 1754, 1754, 1786, 0, 1742, 1749, 1760, + 1760, 1760, 1787, 1789, 1748, 1781, 1738, 1751, 1730, 1774, + 1774, 1774, 1741, 1782, 1790, 1766, 1766, 1766, 1783, 1784, + 1740, 0, 1745, 1785, 1785, 1785, 1786, 1738, 1742, 1749, + 1740, 1791, 1792, 1787, 1789, 1748, 1741, 1793, 1751, 1742, + 1794, 1795, 0, 1745, 1766, 1790, 1748, 0, 0, 1749, + 1805, 0, 1750, 1796, 1796, 1796, 1799, 1799, 1799, 1751, + 1805, 1809, 1791, 1792, 1800, 1800, 1800, 1803, 1793, 1806, + + 1810, 1794, 1795, 1754, 1806, 1766, 0, 1811, 1808, 1807, + 1760, 1805, 1802, 1807, 1813, 1799, 1814, 1815, 1816, 1796, + 1774, 1805, 1809, 0, 0, 0, 1766, 0, 1803, 1808, + 1806, 1810, 1848, 0, 1785, 1806, 0, 1804, 1811, 1808, + 1807, 0, 0, 1854, 1807, 1813, 1799, 1814, 1815, 1816, + 1796, 1803, 1803, 1803, 1803, 1803, 1803, 1803, 1803, 1803, + 1803, 1803, 0, 1848, 1796, 0, 0, 1799, 1804, 0, + 1849, 1849, 1849, 1819, 1854, 1800, 1802, 1802, 1802, 1802, + 1802, 1802, 1802, 1802, 1802, 1802, 1802, 1804, 1804, 1804, + 1804, 1804, 1804, 1804, 1804, 1804, 1804, 1804, 1817, 1817, + + 1817, 1850, 1850, 1850, 1819, 1861, 1851, 1851, 1851, 0, + 0, 1863, 1817, 1819, 1819, 1819, 1819, 1819, 1819, 1819, + 1819, 1819, 1819, 1819, 1820, 1820, 1820, 0, 1864, 1820, + 1822, 1822, 1822, 0, 0, 1822, 1861, 1820, 0, 1823, + 1823, 1823, 1863, 1822, 1823, 1824, 1824, 1824, 0, 1820, + 1824, 1849, 1823, 1869, 1843, 1822, 1843, 1820, 1824, 1864, + 1825, 1825, 1825, 0, 1823, 1825, 1843, 1871, 1875, 1846, + 1824, 1846, 1876, 1825, 0, 1853, 1853, 1853, 0, 1817, + 1820, 1846, 1850, 0, 1869, 1825, 1822, 1851, 1820, 1826, + 1826, 1826, 0, 0, 1826, 1823, 1877, 1843, 1871, 1875, + + 0, 1824, 1826, 1876, 1853, 1820, 1878, 0, 1827, 1827, + 1827, 1822, 1846, 1827, 1826, 1881, 1825, 1828, 1828, 1828, + 1823, 1827, 1828, 1830, 1830, 1830, 1824, 1877, 1830, 1883, + 1828, 1826, 0, 1827, 0, 1853, 1830, 1878, 1831, 1831, + 1831, 1825, 1828, 1831, 0, 1826, 1881, 1844, 1830, 1844, + 1884, 1831, 1832, 1832, 1832, 1844, 1853, 1832, 0, 1844, + 1883, 0, 1826, 1831, 1827, 1832, 1885, 1833, 1833, 1833, + 1826, 0, 1833, 1828, 1856, 1856, 1856, 1832, 1886, 1830, + 1833, 1884, 1834, 1834, 1834, 0, 1844, 1834, 0, 1827, + 1844, 0, 1833, 1887, 1831, 1834, 1888, 1885, 1828, 0, + + 1835, 1835, 1835, 0, 1830, 1835, 1889, 1834, 1832, 1886, + 0, 1892, 1893, 1835, 1894, 1836, 1836, 1836, 1895, 1831, + 1836, 1896, 1835, 1833, 1887, 1835, 1897, 1888, 1836, 1852, + 1852, 1852, 0, 1832, 1857, 1857, 1857, 1889, 1834, 1898, + 1836, 1837, 1892, 1893, 1852, 1894, 0, 1899, 1833, 1895, + 0, 0, 1896, 1835, 0, 1856, 1835, 1897, 1859, 1859, + 1859, 0, 1900, 1834, 1867, 1867, 1867, 0, 0, 0, + 1898, 1836, 1837, 1859, 0, 0, 0, 1839, 1899, 1867, + 0, 1835, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, + 1837, 1837, 1837, 1900, 0, 0, 1836, 1838, 1838, 1838, + + 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1839, 1840, + 1852, 1858, 1858, 1858, 0, 1857, 0, 1839, 1839, 1839, + 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1841, 1841, + 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1859, + 1840, 1858, 1860, 1860, 1860, 1867, 1901, 1847, 1847, 1847, + 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, + 1840, 1847, 0, 1847, 1865, 1865, 1865, 1866, 1866, 1866, + 1904, 1860, 1858, 1847, 1874, 1874, 1874, 1901, 1879, 1879, + 1879, 1880, 1880, 1880, 1890, 1890, 1890, 1905, 1902, 1902, + 1902, 1906, 1858, 1879, 1907, 1909, 1910, 0, 0, 1911, + + 1912, 1904, 1860, 1874, 1847, 1865, 1916, 1923, 1866, 1924, + 1880, 1926, 1902, 0, 0, 1902, 0, 0, 1905, 0, + 0, 0, 1906, 1860, 0, 1907, 1909, 1910, 1847, 1902, + 1911, 1912, 1929, 1922, 1874, 1930, 1865, 1916, 1923, 1866, + 1924, 1880, 1926, 1902, 1922, 1865, 1902, 1925, 1866, 1913, + 1913, 1913, 1914, 1914, 1914, 1874, 0, 1925, 0, 1879, + 1902, 1931, 1880, 1929, 1922, 1890, 1930, 1914, 1932, 1902, + 1908, 1915, 1915, 1915, 1919, 1922, 1908, 0, 1925, 1937, + 1908, 1908, 1957, 1960, 1913, 1908, 1908, 1908, 1925, 1908, + 1964, 1952, 1931, 1952, 1934, 1934, 1934, 1957, 1965, 1932, + + 1915, 1908, 0, 1952, 0, 0, 0, 1908, 1934, 0, + 1937, 1908, 1908, 1957, 1960, 1913, 1908, 1908, 1908, 1920, + 1908, 1964, 1966, 1969, 1970, 1973, 1975, 1976, 1957, 1965, + 1913, 1915, 0, 1914, 1952, 1935, 1935, 1935, 1919, 1919, + 1919, 1919, 1919, 1919, 1919, 1919, 1919, 1919, 1919, 1921, + 1920, 1977, 1915, 1966, 1969, 1970, 1973, 1975, 1976, 1958, + 1958, 1958, 0, 1920, 1920, 1920, 1920, 1920, 1920, 1920, + 1920, 1920, 1920, 1920, 1958, 1934, 1935, 1972, 1972, 1972, + 1921, 0, 1977, 0, 0, 1962, 1962, 1962, 0, 1921, + 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, + + 1962, 1978, 0, 1953, 0, 1953, 1972, 1935, 0, 0, + 0, 1953, 1967, 1967, 1967, 1953, 1935, 1938, 1938, 1938, + 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1939, 1939, + 1939, 0, 1978, 1939, 1940, 1940, 1940, 1972, 1981, 1940, + 1958, 1939, 1953, 1941, 1941, 1941, 1953, 1940, 1941, 1942, + 1942, 1942, 0, 1939, 1942, 1955, 1941, 1955, 1972, 1940, + 1982, 1983, 1942, 1967, 0, 1941, 1962, 1955, 1941, 1981, + 1943, 1943, 1943, 0, 1942, 1943, 1944, 1944, 1944, 1984, + 0, 1944, 0, 1943, 1939, 1971, 1971, 1971, 0, 1944, + 1940, 1982, 1983, 1967, 0, 1943, 1941, 0, 1955, 1941, + + 1971, 1944, 1956, 1956, 1956, 1942, 1945, 1945, 1945, 1939, + 1984, 1945, 1946, 1946, 1946, 1940, 1956, 1946, 1956, 1945, + 0, 1985, 1986, 1990, 1941, 1946, 1943, 0, 1956, 1994, + 1942, 1945, 1944, 1947, 1947, 1947, 1996, 1946, 1947, 1997, + 1999, 2000, 2001, 2002, 2003, 1946, 1947, 0, 1979, 1979, + 1979, 1943, 1985, 1986, 1990, 1948, 0, 1944, 1947, 1956, + 1994, 0, 1945, 1979, 0, 0, 1971, 1996, 1946, 0, + 1997, 1999, 2000, 2001, 2002, 2003, 1946, 1987, 1987, 1987, + 1968, 1968, 1968, 1956, 0, 0, 1948, 1945, 0, 1947, + 1961, 1961, 1961, 1946, 1948, 1948, 1948, 1948, 1948, 1948, + + 1948, 1948, 1948, 1948, 1948, 1950, 1988, 1988, 1988, 1992, + 1992, 1992, 2005, 0, 1947, 1949, 1949, 1949, 1949, 1949, + 1949, 1949, 1949, 1949, 1949, 1949, 1968, 0, 2007, 1979, + 0, 1961, 1993, 1993, 1993, 2008, 1950, 1995, 1995, 1995, + 2004, 2004, 2004, 2005, 1950, 1950, 1950, 1950, 1950, 1950, + 1950, 1950, 1950, 1950, 1950, 2009, 0, 1968, 1987, 2007, + 2006, 1968, 1961, 2006, 2010, 2011, 2008, 2012, 2013, 2014, + 2016, 1961, 2017, 2011, 2010, 2018, 2018, 2018, 2021, 2023, + 2011, 2026, 2019, 2019, 2019, 2024, 2009, 1988, 2028, 2026, + 1992, 2006, 0, 0, 2006, 2010, 2011, 2019, 2012, 2013, + + 2014, 2016, 0, 2017, 2011, 2010, 2027, 2029, 2031, 2021, + 2027, 2011, 2026, 1993, 0, 0, 2024, 0, 1995, 2028, + 2026, 2004, 0, 2024, 2024, 2024, 2024, 2024, 2024, 2024, + 2024, 2024, 2024, 2024, 2025, 2032, 2034, 2027, 2029, 2031, + 2036, 2027, 0, 2023, 2023, 2023, 2023, 2023, 2023, 2023, + 2023, 2023, 2023, 2023, 0, 0, 2018, 2033, 2033, 2033, + 0, 0, 2047, 2019, 0, 2025, 2032, 2034, 0, 2048, + 0, 2036, 0, 2025, 2025, 2025, 2025, 2025, 2025, 2025, + 2025, 2025, 2025, 2025, 2037, 2037, 2037, 2049, 2051, 2037, + 2038, 2038, 2038, 2047, 2042, 2038, 2042, 2037, 2033, 2045, + + 2048, 2045, 2043, 2038, 2043, 2052, 2042, 0, 2053, 2037, + 2043, 2045, 0, 2060, 2043, 2038, 2062, 2037, 2049, 2051, + 2039, 2050, 2050, 2050, 2055, 2055, 2055, 0, 0, 2033, + 2054, 2054, 2054, 2056, 2056, 2056, 2052, 2042, 2033, 2053, + 2037, 2043, 2045, 2040, 2060, 2043, 2038, 2062, 2037, 2039, + 2039, 2039, 2039, 2039, 2039, 2039, 2039, 2039, 2039, 2039, + 2054, 2057, 2057, 2057, 2063, 2037, 0, 2050, 0, 2065, + 0, 2038, 2040, 2040, 2040, 2040, 2040, 2040, 2040, 2040, + 2040, 2040, 2040, 2046, 2046, 2046, 2058, 2058, 2058, 2066, + 2067, 2054, 2068, 2070, 2075, 2063, 0, 2046, 2050, 2046, + + 2065, 2058, 2050, 2077, 0, 2055, 2071, 2071, 2071, 2046, + 2085, 2054, 0, 0, 2056, 2073, 2073, 2073, 2087, 2088, + 2066, 2067, 2092, 2068, 2070, 2075, 2076, 2076, 2076, 2078, + 2078, 2078, 2093, 0, 2077, 2080, 2080, 2080, 2094, 2095, + 2046, 2085, 2057, 2083, 2083, 2083, 2090, 2090, 2090, 2087, + 2088, 2096, 2097, 2092, 2098, 0, 0, 2099, 2100, 2102, + 2103, 2080, 2078, 2093, 2046, 2110, 2104, 2058, 2105, 2094, + 2095, 2106, 2108, 2115, 2116, 2080, 0, 2118, 2132, 2132, + 2132, 2120, 2096, 2097, 2083, 2098, 2090, 2071, 2099, 2100, + 2102, 2103, 2080, 2078, 2130, 2131, 2073, 2104, 0, 2105, + + 0, 0, 2106, 2108, 2115, 2116, 2080, 2076, 2118, 2111, + 2078, 2112, 2120, 0, 0, 2083, 2080, 2090, 2133, 2133, + 2133, 0, 0, 0, 2083, 2130, 2131, 2090, 0, 2110, + 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, + 2111, 0, 2112, 2134, 2134, 2134, 0, 0, 2111, 2111, + 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2132, + 0, 0, 2135, 0, 2136, 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, 2112, 2113, 2114, 2121, 2121, + 2121, 2142, 2125, 2121, 2125, 2122, 2114, 2113, 0, 2143, + 2126, 2121, 2126, 2135, 2125, 2136, 2123, 2144, 2126, 2133, + + 0, 2145, 2126, 2121, 2138, 2138, 2138, 2113, 2114, 2146, + 2146, 2146, 2142, 2151, 2151, 2151, 2122, 2114, 2113, 2128, + 2143, 2128, 0, 0, 2134, 2125, 2150, 2123, 2144, 2126, + 2152, 2128, 2145, 2126, 2121, 2122, 2122, 2122, 2122, 2122, + 2122, 2122, 2122, 2122, 2122, 2122, 2123, 2123, 2123, 2123, + 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2150, 0, 2121, + 0, 2152, 2128, 2129, 2129, 2129, 2137, 2137, 2137, 2140, + 2140, 2140, 2148, 2148, 2148, 2155, 2156, 2129, 2157, 2129, + 2153, 2153, 2153, 2158, 2159, 2138, 2148, 2160, 2161, 2129, + 2146, 2137, 2162, 2163, 2151, 2164, 2165, 2166, 2160, 2167, + + 2167, 2168, 2140, 2169, 2171, 2172, 2155, 2156, 2173, 2157, + 2174, 2175, 2181, 0, 2158, 2159, 0, 2184, 2160, 2161, + 2129, 2186, 2137, 2162, 2163, 0, 2164, 2165, 2166, 2184, + 2167, 2167, 2168, 2140, 2169, 2171, 2172, 0, 0, 2173, + 0, 2174, 2175, 2183, 2129, 0, 0, 2137, 2184, 0, + 2140, 0, 2186, 2148, 2179, 2179, 2179, 0, 0, 0, + 2184, 2153, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, + 2182, 2182, 2182, 2187, 2183, 2188, 2181, 2181, 2181, 2181, + 2181, 2181, 2181, 2181, 2181, 2181, 2181, 2185, 2183, 2183, + 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2189, + + 2185, 2190, 2191, 2194, 2187, 2194, 2188, 2197, 2195, 2197, + 2195, 2199, 2200, 2192, 2205, 2194, 2195, 0, 2185, 2197, + 2195, 2206, 2198, 2198, 2198, 2201, 2201, 2201, 0, 0, + 2189, 2185, 2190, 2191, 0, 2179, 2198, 0, 2198, 2203, + 2203, 2203, 2199, 2200, 2192, 2205, 2194, 2195, 2198, 2208, + 2197, 2195, 2206, 2207, 2207, 2207, 2210, 2191, 2191, 2191, + 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2192, 2192, + 2192, 2192, 2192, 2192, 2192, 2192, 2192, 2192, 2192, 2198, + 2208, 2209, 2209, 2209, 2211, 2212, 2215, 2210, 2213, 2213, + 2213, 2216, 2216, 2216, 2217, 2217, 2217, 2219, 2220, 2221, + + 2221, 2221, 2223, 2198, 0, 2216, 2201, 2224, 0, 2225, + 2226, 2227, 2228, 2230, 2231, 2211, 2212, 2215, 2232, 2233, + 2203, 2234, 2235, 2236, 2237, 2238, 2240, 2241, 2219, 2220, + 2217, 2249, 2242, 2223, 2207, 2217, 2243, 2245, 2224, 2221, + 2225, 2226, 2227, 2228, 2230, 2231, 2246, 2246, 2246, 2232, + 2233, 2250, 2234, 2235, 2236, 2237, 2238, 2240, 2241, 2253, + 2254, 2217, 2209, 2242, 0, 0, 2217, 2243, 2245, 2213, + 2221, 0, 2216, 0, 0, 2217, 0, 2271, 2271, 2271, + 2221, 2261, 2250, 2261, 0, 0, 0, 0, 2252, 2256, + 2253, 2254, 2252, 2261, 2266, 2249, 2249, 2249, 2249, 2249, + + 2249, 2249, 2249, 2249, 2249, 2249, 0, 2250, 2250, 2250, + 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2251, 2252, + 2256, 0, 0, 2252, 2261, 2266, 2267, 2246, 2251, 2258, + 2258, 2258, 2258, 2258, 2258, 2258, 2258, 2258, 2258, 2258, + 2262, 2264, 2262, 2264, 2268, 2269, 2270, 2275, 2262, 2251, + 2276, 2278, 2262, 2264, 2277, 2277, 2277, 2267, 2271, 2251, + 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, + 2259, 2265, 2265, 2265, 2279, 2268, 2269, 2270, 2275, 2262, + 2281, 2276, 2278, 2262, 2264, 2265, 2282, 2265, 2283, 2284, + 2277, 2285, 2286, 2287, 2288, 2277, 2289, 2265, 2290, 2292, + + 2293, 2294, 2295, 2296, 2305, 2279, 2297, 2298, 2299, 2300, + 2302, 2281, 2307, 2310, 2311, 2318, 2319, 2282, 2320, 2283, + 2284, 2277, 2285, 2286, 2287, 2288, 2277, 2289, 2265, 2290, + 2292, 2293, 2294, 2295, 2296, 2277, 0, 2297, 2298, 2299, + 2300, 2302, 0, 2307, 2310, 2311, 2318, 2319, 2306, 2320, + 2321, 2313, 2265, 2313, 0, 2316, 0, 2316, 0, 0, + 0, 0, 0, 2313, 0, 2322, 0, 2316, 2305, 2305, + 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2306, + 2323, 2321, 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, + 2306, 2306, 2306, 2308, 2313, 2314, 2322, 2314, 2316, 2317, + + 2317, 2317, 2308, 2314, 2326, 2327, 2330, 2314, 2331, 2332, + 2333, 2323, 2336, 2317, 2337, 2317, 2334, 2334, 2334, 2338, + 2339, 2341, 2342, 2344, 2308, 2317, 2346, 2348, 2349, 0, + 0, 0, 0, 2308, 2314, 2326, 2327, 2330, 2314, 2331, + 2332, 2333, 2351, 2336, 2353, 2337, 2355, 2363, 0, 0, + 2338, 2339, 2341, 2342, 2344, 0, 2317, 2346, 2348, 2349, + 2352, 2352, 2352, 2352, 2352, 2352, 2352, 2352, 2352, 2352, + 2352, 2364, 2367, 2370, 2357, 2353, 2357, 2355, 2363, 2358, + 2317, 2358, 2360, 0, 2360, 0, 2357, 2358, 2376, 2376, + 2376, 2358, 2371, 2372, 2360, 2373, 2374, 2334, 2375, 2377, + + 2380, 2381, 2364, 2367, 2370, 0, 2351, 2351, 2351, 2351, + 2351, 2351, 2351, 2351, 2351, 2351, 2351, 2357, 2358, 2361, + 2361, 2361, 2358, 2371, 2372, 2360, 2373, 2374, 2383, 2375, + 2377, 2380, 2381, 2361, 2384, 2361, 2378, 2378, 2378, 2385, + 2387, 2388, 2406, 2406, 2406, 2361, 2391, 2391, 2391, 2391, + 2391, 2391, 2391, 2391, 2391, 2391, 2391, 2399, 2401, 2383, + 2402, 2394, 2403, 2394, 2404, 2384, 2395, 2405, 2395, 2376, + 2385, 2387, 2388, 2394, 2395, 2397, 2361, 2397, 2395, 2410, + 2398, 2398, 2398, 2408, 2408, 2408, 0, 2397, 2399, 2401, + 2413, 2402, 0, 2403, 2398, 2404, 2398, 2416, 2405, 2419, + + 2361, 2412, 2412, 2412, 2394, 2395, 2398, 2427, 0, 2395, + 2410, 2428, 2421, 2424, 2421, 2424, 0, 2378, 2397, 2429, + 2430, 2413, 2431, 2406, 2421, 2424, 0, 2422, 2416, 2422, + 2419, 2425, 2425, 2425, 2432, 2422, 2433, 2398, 2427, 2422, + 2436, 2437, 2428, 2438, 0, 2425, 0, 2425, 0, 0, + 2429, 2430, 2444, 2431, 0, 2421, 2424, 2425, 2434, 2434, + 2434, 2398, 0, 0, 2408, 2432, 2422, 2433, 2446, 0, + 2422, 2436, 2437, 2447, 2438, 2440, 2448, 2440, 2441, 2443, + 2441, 2443, 2412, 2444, 2449, 2434, 2441, 2440, 2425, 2450, + 2441, 2443, 2445, 2445, 2445, 2451, 2452, 2454, 2462, 2446, + + 2445, 2456, 2465, 2456, 2447, 2466, 2467, 2448, 0, 2469, + 2470, 2473, 2425, 2456, 2474, 2449, 2434, 2441, 2440, 2475, + 2450, 2441, 2443, 2458, 2458, 2458, 2451, 2452, 2454, 2462, + 2476, 2458, 2477, 2465, 2480, 2481, 2466, 2467, 2482, 2434, + 2469, 2470, 2473, 2483, 2456, 2474, 2478, 2478, 2478, 2488, + 2475, 2485, 2485, 2485, 2486, 2486, 2486, 2489, 2490, 2491, + 2494, 2476, 2495, 2477, 0, 2480, 2481, 2497, 2498, 2482, + 2492, 2492, 2492, 2445, 2483, 2445, 2496, 2496, 2496, 2499, + 2488, 2501, 2502, 2502, 2502, 2503, 2504, 2505, 2489, 2490, + 2491, 2494, 2506, 2495, 2507, 2486, 0, 2508, 2497, 2498, + + 2510, 0, 2511, 2512, 2458, 0, 2458, 2513, 2513, 2513, + 2499, 0, 2501, 0, 0, 0, 2503, 2504, 2505, 0, + 0, 0, 0, 2506, 0, 2507, 2486, 2478, 2508, 0, + 0, 2510, 2485, 2511, 2512, 2486, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2492, 0, 0, 0, 0, 0, 2496, 0, 0, + 0, 0, 0, 2502, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2513, 2515, + 2515, 2515, 2515, 2515, 2515, 2515, 2515, 2515, 2515, 2515, + + 2515, 2515, 2515, 2515, 2515, 2515, 2515, 2516, 2516, 2516, + 2516, 2516, 2516, 2516, 2516, 2516, 2516, 2516, 2516, 2516, + 2516, 2516, 2516, 2516, 2516, 2517, 2517, 2517, 2517, 2517, + 2517, 2517, 2517, 2517, 2517, 2517, 2517, 2517, 2517, 2517, + 2517, 2517, 2517, 2518, 2518, 2518, 2518, 2518, 2518, 2518, + 2518, 2518, 2518, 2518, 2518, 2518, 2518, 2518, 2518, 2518, + 2518, 2519, 2519, 2519, 2519, 2519, 2519, 2519, 2519, 2519, + 2519, 2519, 2519, 2519, 2519, 2519, 2519, 2519, 2519, 2520, + 2520, 2520, 2520, 2520, 2520, 2520, 2520, 2520, 2520, 2520, + 2520, 2520, 2520, 2520, 2520, 2520, 2520, 2521, 2521, 2521, + + 2521, 2521, 2521, 2521, 2521, 2521, 2521, 2521, 2521, 2521, + 2521, 2521, 2521, 2521, 2521, 2522, 2522, 2522, 2522, 2522, + 2522, 2522, 2522, 2522, 2522, 2522, 2522, 2522, 2522, 2522, + 2522, 2522, 2522, 2523, 2523, 2523, 2523, 2523, 2523, 2523, + 2523, 2523, 2523, 2523, 2523, 2523, 2523, 2523, 2523, 2523, + 2523, 2524, 2524, 2524, 2524, 2524, 2524, 2524, 2524, 2524, + 2524, 2524, 2524, 2524, 2524, 2524, 2524, 2524, 2524, 2525, + 2525, 2525, 2525, 2525, 2525, 2525, 2525, 2525, 2525, 2525, + 2525, 2525, 2525, 2525, 2525, 2525, 2525, 2526, 2526, 2526, + 2526, 2526, 2526, 2526, 2526, 2526, 2526, 2526, 2526, 2526, + + 2526, 2526, 2526, 2526, 2526, 2527, 2527, 2527, 2527, 2527, + 2527, 2527, 2527, 2527, 2527, 2527, 2527, 2527, 2527, 2527, + 2527, 2527, 2527, 2528, 2528, 2528, 2528, 2528, 2528, 2528, + 2528, 2528, 2528, 2528, 2528, 2528, 2528, 2528, 2528, 2528, + 2528, 2529, 2529, 2529, 2529, 2529, 2529, 2529, 2529, 2529, + 2529, 2529, 2529, 2529, 2529, 2529, 2529, 2529, 2529, 2530, + 2530, 2530, 2530, 2530, 2530, 2530, 2530, 2530, 2530, 2530, + 2530, 2530, 2530, 2530, 2530, 2530, 2530, 2531, 2531, 2531, + 0, 0, 0, 2531, 0, 0, 0, 0, 2531, 2531, + 2531, 2531, 2532, 2532, 0, 2532, 2532, 2532, 2532, 2532, + + 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532, + 2533, 2533, 0, 0, 0, 2533, 0, 0, 0, 0, + 2533, 2533, 2533, 2533, 2534, 2534, 2534, 0, 0, 2534, + 0, 0, 0, 0, 2534, 2534, 2534, 2534, 2535, 2535, + 0, 0, 0, 2535, 0, 0, 0, 2535, 2535, 2535, + 2535, 2535, 2536, 0, 2536, 2536, 2536, 2536, 2536, 2536, + 2536, 2537, 2537, 0, 0, 0, 2537, 0, 0, 0, + 0, 2537, 2537, 2537, 2537, 2538, 0, 2538, 2538, 2538, + 2538, 2538, 2538, 2539, 2539, 0, 2539, 2539, 0, 2539, + 2539, 2539, 0, 0, 0, 0, 2539, 2539, 2539, 2539, + + 2540, 0, 2540, 2540, 2540, 2540, 2541, 2541, 2541, 0, + 0, 0, 2541, 0, 0, 0, 0, 2541, 2541, 2541, + 2541, 2542, 2542, 0, 0, 0, 2542, 0, 0, 0, + 0, 2542, 2542, 2542, 2542, 2543, 2543, 2543, 0, 0, + 2543, 0, 0, 0, 0, 2543, 2543, 2543, 2543, 2544, + 2544, 0, 0, 0, 2544, 0, 0, 0, 2544, 2544, + 2544, 2544, 2544, 2545, 0, 2545, 2545, 2545, 2545, 2546, + 0, 2546, 0, 2546, 2547, 0, 2547, 0, 2547, 2548, + 2548, 2548, 2548, 2548, 2548, 0, 2548, 2548, 2548, 2548, + 2548, 0, 2548, 2548, 2548, 2548, 2548, 2549, 2549, 2549, + + 2549, 2549, 2549, 2549, 2549, 2549, 2549, 2549, 2549, 2549, + 2549, 2549, 2549, 2549, 2549, 2550, 2550, 2550, 2550, 2550, + 2550, 0, 2550, 2550, 2550, 2550, 2550, 0, 2550, 2550, + 2550, 2550, 2550, 2551, 2551, 2551, 2551, 2551, 2551, 2551, + 2551, 2551, 2551, 2551, 2551, 2551, 2551, 2551, 2551, 2551, + 2551, 2552, 2552, 2552, 2552, 2552, 2552, 2552, 2552, 2552, + 2552, 2552, 2552, 2552, 2552, 2552, 2552, 2552, 2552, 2553, + 2553, 2553, 2553, 2553, 2553, 2553, 2553, 2553, 2553, 2553, + 2553, 2553, 0, 2553, 2553, 2553, 2553, 2554, 2554, 2554, + 2554, 2554, 2554, 2554, 2554, 2554, 2554, 2554, 2554, 2554, + + 0, 2554, 2554, 2554, 2554, 2555, 2555, 0, 2555, 2555, + 2555, 2555, 2555, 2555, 2555, 2555, 2555, 2555, 2555, 2555, + 2555, 2555, 2555, 2556, 2556, 0, 0, 0, 2556, 0, + 0, 0, 0, 2556, 2556, 2556, 2556, 2557, 0, 2557, + 2557, 2557, 2557, 2557, 2558, 2558, 0, 2558, 2558, 2558, + 2558, 2558, 2558, 2558, 2558, 2558, 2558, 2558, 2558, 2558, + 2558, 2558, 2559, 2559, 0, 2559, 2559, 2559, 2559, 2559, + 2559, 2559, 2559, 2559, 2559, 2559, 2559, 2559, 2559, 2559, + 2560, 2560, 0, 0, 0, 2560, 0, 0, 0, 0, + 2560, 2560, 2560, 2560, 2561, 0, 2561, 2561, 2561, 2561, + + 2561, 2561, 2562, 2562, 0, 0, 0, 2562, 0, 0, + 0, 0, 2562, 2562, 2562, 2562, 2563, 0, 2563, 2563, + 2563, 2563, 2564, 2564, 0, 2564, 2564, 2564, 2564, 2564, + 2564, 2564, 2564, 2564, 2564, 2564, 2564, 2564, 2564, 2564, + 2565, 2565, 0, 0, 0, 2565, 0, 0, 0, 0, + 2565, 2565, 2565, 2565, 2566, 0, 2566, 2566, 2566, 2566, + 0, 0, 2566, 2567, 2567, 0, 2567, 2567, 2567, 2567, + 2567, 2567, 2567, 2567, 2567, 2567, 2567, 2567, 2567, 2567, + 2567, 2568, 2568, 0, 2568, 2568, 2568, 2568, 2568, 2568, + 2568, 2568, 2568, 2568, 2568, 2568, 2568, 2568, 2568, 2569, + + 2569, 2569, 0, 0, 0, 2569, 0, 0, 0, 0, + 2569, 2569, 2569, 2569, 2570, 0, 2570, 2570, 2570, 2570, + 2571, 2571, 0, 2571, 2571, 2571, 2571, 2571, 2571, 2571, + 2571, 2571, 2571, 2571, 2571, 2571, 2571, 2571, 2572, 2572, + 0, 2572, 2572, 2572, 2572, 2572, 2572, 2572, 2572, 2572, + 2572, 2572, 2572, 2572, 2572, 2572, 2573, 2573, 0, 2573, + 2573, 2573, 2573, 2573, 2573, 2573, 2573, 2573, 2573, 2573, + 2573, 2573, 2573, 2573, 2574, 2574, 0, 0, 0, 2574, + 0, 0, 0, 0, 2574, 2574, 2574, 2574, 2575, 0, + 2575, 2575, 2575, 2575, 2576, 2576, 2576, 0, 0, 2576, + + 0, 0, 0, 0, 2576, 2576, 2576, 2576, 2577, 0, + 2577, 2577, 2577, 2577, 2578, 2578, 0, 0, 0, 2578, + 0, 0, 0, 2578, 2578, 2578, 2578, 2578, 2579, 0, + 2579, 2579, 2579, 2579, 2580, 2580, 0, 0, 0, 2580, + 0, 0, 0, 0, 2580, 2580, 2580, 2580, 2581, 0, + 2581, 2581, 2581, 2581, 2582, 2582, 0, 2582, 2582, 0, + 2582, 2582, 2582, 0, 0, 0, 0, 2582, 2582, 2582, + 2582, 2583, 0, 2583, 2583, 2583, 2583, 2584, 2584, 2584, + 0, 0, 0, 2584, 0, 0, 0, 0, 2584, 2584, + 2584, 2584, 2585, 0, 2585, 2585, 2585, 2585, 2586, 2586, + + 0, 0, 0, 2586, 0, 0, 0, 0, 2586, 2586, + 2586, 2586, 2587, 0, 2587, 2587, 2587, 2587, 2588, 2588, + 2588, 0, 0, 2588, 0, 0, 0, 0, 2588, 2588, + 2588, 2588, 2589, 0, 2589, 2589, 2589, 2589, 2590, 2590, + 0, 0, 0, 2590, 0, 0, 0, 2590, 2590, 2590, + 2590, 2590, 2591, 0, 2591, 2591, 2591, 2591, 2592, 0, + 2592, 0, 2592, 2593, 0, 2593, 0, 2593, 2594, 2594, + 2594, 2594, 2594, 2594, 0, 2594, 2594, 2594, 2594, 2594, + 0, 2594, 2594, 2594, 2594, 2594, 2595, 2595, 0, 2595, + 2595, 2595, 2595, 2595, 2595, 2595, 2595, 2595, 2595, 2595, + + 2595, 2595, 2595, 2595, 2596, 2596, 2596, 2596, 2596, 2596, + 0, 2596, 2596, 2596, 2596, 2596, 0, 2596, 2596, 2596, + 2596, 2596, 2597, 2597, 0, 2597, 2597, 2597, 2597, 2597, + 2597, 2597, 2597, 2597, 2597, 2597, 2597, 2597, 2597, 2597, + 2598, 2598, 0, 2598, 2598, 2598, 2598, 2598, 2598, 2598, + 2598, 2598, 2598, 2598, 2598, 2598, 2598, 2598, 2599, 2599, + 2599, 2599, 2599, 2599, 2599, 2599, 2599, 2599, 2599, 2599, + 2599, 0, 2599, 2599, 2599, 2599, 2600, 2600, 2600, 2600, + 2600, 2600, 2600, 2600, 2600, 2600, 2600, 2600, 2600, 0, + 2600, 2600, 2600, 2600, 2601, 2601, 0, 2601, 2601, 2601, + + 2601, 2601, 2601, 2601, 2601, 2601, 2601, 2601, 2601, 2601, + 2601, 2601, 2602, 2602, 0, 2602, 2602, 2602, 2602, 2602, + 2602, 2602, 2602, 2602, 2602, 2602, 2602, 2602, 2602, 2602, + 2603, 2603, 0, 2603, 2603, 2603, 2603, 2603, 2603, 2603, + 2603, 2603, 2603, 2603, 2603, 2603, 2603, 2603, 2604, 2604, + 0, 0, 0, 2604, 0, 0, 0, 0, 2604, 2604, + 2604, 2604, 2605, 0, 2605, 2605, 2605, 2605, 2606, 2606, + 0, 2606, 2606, 2606, 2606, 2606, 2606, 2606, 2606, 2606, + 2606, 2606, 2606, 2606, 2606, 2606, 2607, 2607, 0, 2607, + 2607, 2607, 2607, 2607, 2607, 2607, 2607, 2607, 2607, 2607, + + 2607, 2607, 2607, 2607, 2608, 2608, 0, 2608, 2608, 2608, + 2608, 2608, 2608, 2608, 2608, 2608, 2608, 2608, 2608, 2608, + 2608, 2608, 2609, 2609, 0, 2609, 2609, 2609, 2609, 2609, + 2609, 2609, 2609, 2609, 2609, 2609, 2609, 2609, 2609, 2609, + 2610, 2610, 0, 0, 0, 2610, 0, 0, 0, 0, + 2610, 2610, 2610, 2610, 2611, 0, 2611, 2611, 2611, 2611, + 2612, 2612, 0, 0, 0, 2612, 0, 0, 0, 0, + 2612, 2612, 2612, 2612, 2613, 0, 2613, 2613, 2613, 2613, + 2614, 2614, 0, 2614, 2614, 2614, 2614, 2614, 2614, 2614, + 2614, 2614, 2614, 2614, 2614, 2614, 2614, 2614, 2615, 2615, + + 0, 2615, 2615, 2615, 2615, 2615, 2615, 2615, 2615, 2615, + 2615, 2615, 2615, 2615, 2615, 2615, 2616, 2616, 0, 2616, + 2616, 2616, 2616, 2616, 2616, 2616, 2616, 2616, 2616, 2616, + 2616, 2616, 2616, 2616, 2617, 2617, 0, 0, 0, 2617, + 0, 0, 0, 0, 2617, 2617, 2617, 2617, 2618, 0, + 2618, 2618, 2618, 2618, 2619, 2619, 0, 2619, 2619, 2619, + 2619, 2619, 2619, 2619, 2619, 2619, 2619, 2619, 2619, 2619, + 2619, 2619, 2620, 2620, 0, 2620, 2620, 2620, 2620, 2620, + 2620, 2620, 2620, 2620, 2620, 2620, 2620, 2620, 2620, 2620, + 2621, 2621, 2621, 0, 0, 0, 2621, 0, 0, 0, + + 0, 2621, 2621, 2621, 2621, 2622, 2622, 0, 2622, 2622, + 2622, 2622, 2622, 2622, 2622, 2622, 2622, 2622, 2622, 2622, + 2622, 2622, 2622, 2623, 2623, 0, 2623, 2623, 2623, 2623, + 2623, 2623, 2623, 2623, 2623, 2623, 2623, 2623, 2623, 2623, + 2623, 2624, 2624, 2624, 0, 0, 2624, 0, 0, 0, + 0, 2624, 2624, 2624, 2624, 2625, 2625, 2625, 2625, 2625, + 2625, 2625, 2625, 2625, 2625, 2625, 2625, 2625, 2625, 2625, + 2625, 2625, 2625, 2626, 2626, 0, 0, 2626, 2626, 0, + 0, 0, 0, 2626, 2626, 2626, 2626, 2627, 2627, 0, + 0, 0, 2627, 0, 0, 0, 2627, 2627, 2627, 2627, + + 2627, 2628, 2628, 0, 0, 0, 2628, 0, 0, 0, + 0, 2628, 2628, 2628, 2628, 2629, 2629, 0, 0, 2629, + 2629, 0, 0, 0, 0, 2629, 2629, 2629, 2629, 2630, + 2630, 2630, 0, 0, 0, 2630, 0, 0, 0, 0, + 2630, 2630, 2630, 2630, 2631, 2631, 2631, 0, 0, 2631, + 0, 0, 0, 0, 2631, 2631, 2631, 2631, 2632, 2632, + 0, 0, 0, 2632, 0, 0, 0, 0, 2632, 2632, + 2632, 2632, 2633, 2633, 0, 0, 0, 2633, 0, 0, + 0, 2633, 2633, 2633, 2633, 2633, 2634, 0, 2634, 0, + 2634, 2635, 0, 2635, 0, 2635, 2636, 2636, 0, 2636, + + 2636, 2636, 2636, 2636, 2636, 2636, 2636, 2636, 2636, 2636, + 2636, 2636, 2636, 2636, 2637, 2637, 0, 2637, 2637, 2637, + 2637, 2637, 2637, 2637, 2637, 2637, 2637, 2637, 2637, 2637, + 2637, 2637, 2638, 2638, 0, 2638, 2638, 2638, 2638, 2638, + 2638, 2638, 2638, 2638, 2638, 2638, 2638, 2638, 2638, 2638, + 2639, 2639, 0, 2639, 2639, 2639, 2639, 2639, 2639, 2639, + 2639, 2639, 2639, 2639, 2639, 2639, 2639, 2639, 2640, 2640, + 0, 2640, 2640, 2640, 2640, 2640, 2640, 2640, 2640, 2640, + 2640, 2640, 2640, 2640, 2640, 2640, 2641, 2641, 2641, 2641, + 2641, 2641, 2641, 2641, 2641, 2641, 2641, 2641, 2641, 2641, + + 2641, 2641, 2641, 2641, 2642, 2642, 0, 0, 0, 2642, + 0, 0, 0, 0, 2642, 2642, 2642, 2642, 2643, 2643, + 2643, 2643, 2643, 2643, 2643, 2643, 2643, 2643, 2643, 2643, + 2643, 2643, 2643, 2643, 2643, 2643, 2644, 2644, 0, 2644, + 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, + 2644, 2644, 2644, 2644, 2645, 2645, 0, 2645, 2645, 2645, + 2645, 2645, 2645, 2645, 2645, 2645, 2645, 2645, 2645, 2645, + 2645, 2645, 2646, 2646, 2646, 2646, 2646, 2646, 2646, 2646, + 2646, 2646, 2646, 2646, 2646, 2646, 2646, 2646, 2646, 2646, + 2647, 2647, 0, 0, 0, 2647, 0, 0, 0, 0, + + 2647, 2647, 2647, 2647, 2648, 2648, 0, 0, 0, 2648, + 0, 0, 0, 0, 2648, 2648, 2648, 2648, 2649, 2649, + 0, 2649, 2649, 2649, 2649, 2649, 2649, 2649, 2649, 2649, + 2649, 2649, 2649, 2649, 2649, 2649, 2650, 2650, 0, 2650, + 2650, 2650, 2650, 2650, 2650, 2650, 2650, 2650, 2650, 2650, + 2650, 2650, 2650, 2650, 2651, 2651, 2651, 2651, 2651, 2651, + 2651, 2651, 2651, 2651, 2651, 2651, 2651, 2651, 2651, 2651, + 2651, 2651, 2652, 2652, 0, 0, 2652, 2652, 0, 0, + 0, 0, 2652, 2652, 2652, 2652, 2653, 2653, 2653, 2653, + 2653, 2653, 2653, 2653, 2653, 2653, 2653, 2653, 2653, 2653, + + 2653, 2653, 2653, 2653, 2654, 2654, 2654, 2654, 2654, 2654, + 2654, 2654, 2654, 2654, 2654, 2654, 2654, 2654, 2654, 2654, + 2654, 2654, 2655, 2655, 0, 2655, 2655, 2655, 2655, 2655, + 2655, 2655, 2655, 2655, 2655, 2655, 2655, 2655, 2655, 2655, + 2656, 2656, 0, 2656, 2656, 2656, 2656, 2656, 2656, 2656, + 2656, 2656, 2656, 2656, 2656, 2656, 2656, 2656, 2657, 2657, + 0, 0, 2657, 2657, 0, 0, 0, 0, 2657, 2657, + 2657, 2657, 2658, 2658, 0, 0, 0, 2658, 0, 0, + 0, 0, 2658, 2658, 2658, 2658, 2659, 2659, 0, 0, + 2659, 2659, 2659, 0, 0, 0, 2659, 2659, 2659, 2659, + + 2660, 2660, 0, 0, 0, 2660, 0, 0, 0, 0, + 2660, 2660, 2660, 2660, 2661, 0, 2661, 0, 2661, 2662, + 0, 2662, 0, 2662, 2663, 2663, 2663, 2663, 2663, 2663, + 2663, 2663, 2663, 2663, 2663, 2663, 2663, 2663, 2663, 2663, + 2663, 2663, 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664, + 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664, + 2665, 2665, 2665, 2665, 2665, 2665, 2665, 2665, 2665, 2665, + 2665, 2665, 2665, 2665, 2665, 2665, 2665, 2665, 2666, 2666, + 0, 2666, 2666, 2666, 2666, 2666, 2666, 2666, 2666, 2666, + 2666, 2666, 2666, 2666, 2666, 2666, 2667, 2667, 0, 2667, + + 2667, 2667, 2667, 2667, 2667, 2667, 2667, 2667, 2667, 2667, + 2667, 2667, 2667, 2667, 2668, 2668, 0, 0, 0, 2668, + 0, 0, 0, 0, 2668, 2668, 2668, 2668, 2669, 2669, + 0, 2669, 2669, 2669, 2669, 2669, 2669, 2669, 2669, 2669, + 2669, 2669, 2669, 2669, 2669, 2669, 2670, 2670, 0, 2670, + 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670, + 2670, 2670, 2670, 2670, 2671, 2671, 0, 2671, 2671, 2671, + 2671, 2671, 2671, 2671, 2671, 2671, 2671, 2671, 2671, 2671, + 2671, 2671, 2672, 2672, 0, 0, 0, 2672, 0, 0, + 0, 0, 2672, 2672, 2672, 2672, 2673, 2673, 0, 0, + + 0, 2673, 0, 0, 0, 0, 2673, 2673, 2673, 2673, + 2674, 2674, 0, 2674, 2674, 2674, 2674, 2674, 2674, 2674, + 2674, 2674, 2674, 2674, 2674, 2674, 2674, 2674, 2675, 2675, + 0, 2675, 2675, 2675, 2675, 2675, 2675, 2675, 2675, 2675, + 2675, 2675, 2675, 2675, 2675, 2675, 2676, 2676, 0, 0, + 2676, 2676, 0, 0, 0, 0, 2676, 2676, 2676, 2676, + 2677, 2677, 0, 2677, 2677, 2677, 2677, 2677, 2677, 2677, + 2677, 2677, 2677, 2677, 2677, 2677, 2677, 2677, 2678, 2678, + 0, 2678, 2678, 2678, 2678, 2678, 2678, 2678, 2678, 2678, + 2678, 2678, 2678, 2678, 2678, 2678, 2679, 2679, 0, 0, + + 2679, 2679, 0, 0, 0, 0, 2679, 2679, 2679, 2679, + 2680, 2680, 0, 0, 0, 2680, 0, 0, 0, 0, + 2680, 2680, 2680, 2680, 2681, 2681, 0, 0, 2681, 2681, + 0, 0, 0, 0, 2681, 2681, 2681, 2681, 2682, 2682, + 0, 0, 0, 2682, 0, 0, 0, 0, 2682, 2682, + 2682, 2682, 2683, 0, 2683, 0, 2683, 2684, 0, 2684, + 0, 2684, 2685, 2685, 0, 2685, 2685, 2685, 2685, 2685, + 2685, 2685, 2685, 2685, 2685, 2685, 2685, 2685, 2685, 2685, + 2686, 2686, 0, 2686, 2686, 2686, 2686, 2686, 2686, 2686, + 2686, 2686, 2686, 2686, 2686, 2686, 2686, 2686, 2687, 2687, + + 0, 2687, 2687, 2687, 2687, 2687, 2687, 2687, 2687, 2687, + 2687, 2687, 2687, 2687, 2687, 2687, 2688, 2688, 0, 0, + 0, 2688, 0, 0, 0, 0, 2688, 2688, 2688, 2688, + 2689, 2689, 0, 0, 0, 2689, 0, 0, 0, 0, + 2689, 2689, 2689, 2689, 2690, 2690, 2690, 2690, 2690, 2690, + 2690, 2690, 2690, 2690, 2690, 2690, 2690, 2690, 2690, 2690, + 2690, 2690, 2691, 2691, 2691, 2691, 2691, 2691, 2691, 2691, + 2691, 2691, 2691, 2691, 2691, 2691, 2691, 2691, 2691, 2691, + 2692, 2692, 2692, 2692, 2692, 2692, 2692, 2692, 2692, 2692, + 2692, 2692, 2692, 2692, 2692, 2692, 2692, 2692, 2693, 2693, + + 2693, 2693, 2693, 2693, 2693, 2693, 2693, 2693, 2693, 2693, + 2693, 2693, 2693, 2693, 2693, 2693, 2694, 2694, 2694, 2694, + 2694, 2694, 2694, 2694, 2694, 2694, 2694, 2694, 2694, 2694, + 2694, 2694, 2694, 2694, 2695, 2695, 2695, 2695, 2695, 2695, + 2695, 2695, 2695, 2695, 2695, 2695, 2695, 2695, 2695, 2695, + 2695, 2695, 2696, 2696, 2696, 2696, 2696, 2696, 2696, 2696, + 2696, 2696, 2696, 2696, 2696, 2696, 2696, 2696, 2696, 2696, + 2697, 2697, 2697, 2697, 2697, 2697, 2697, 2697, 2697, 2697, + 2697, 2697, 2697, 2697, 2697, 2697, 2697, 2697, 2698, 2698, + 2698, 2698, 2698, 2698, 2698, 2698, 2698, 2698, 2698, 2698, + + 2698, 2698, 2698, 2698, 2698, 2698, 2699, 2699, 2699, 2699, + 2699, 2699, 2699, 2699, 2699, 2699, 2699, 2699, 2699, 2699, + 2699, 2699, 2699, 2699, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + + 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, 2514, + 2514, 2514, 2514, 2514, 2514, 2514, 2514 + } ; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +#line 1 "ob_proxy_parser_gbk.l" +#define YY_NO_INPUT 1 +#line 7 "ob_proxy_parser_gbk.l" +#define YYSTYPE OBPROXYSTYPE +#define YYLTYPE OBPROXYLTYPE +#include +#include "opsql/ob_proxy_parse_define.h" +#include "opsql/ob_proxy_parse_malloc.h" +#include "opsql/parser/ob_proxy_parse_result.h" +#include "opsql/parser/ob_proxy_parser_gbk_tab.h" +extern void ob_proxy_gbk_parser_fatal_error(yyconst char *msg, yyscan_t yyscanner); +void update_stmt_type(ObProxyBasicStmtType type, void *yyscanner); +void store_str(char* str, int64_t str_len, char* end_ptr, void *yyscanner); +void store_str_with_quote(ObProxyParseQuoteType type, char* str, int64_t str_len, char* end_ptr, void *yyscanner); + +#define YY_FATAL_ERROR(msg) ob_proxy_gbk_parser_fatal_error(msg, yyscanner) + +#define SET_DML_STMT(stmt_type) \ +do {\ + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner);\ + if (OB_NOTNULL(p)) {\ + if (OBPROXY_T_INVALID == p->cur_stmt_type_\ + || OBPROXY_T_BEGIN == p->cur_stmt_type_\ + || OBPROXY_T_SET == p->cur_stmt_type_) {\ + p->cur_stmt_type_ = stmt_type;\ + }\ + }\ +} while (0); + +#define SET_DDL_STMT(stmt_type) \ +do {\ + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner);\ + if (OB_NOTNULL(p)) {\ + if (OBPROXY_T_INVALID == p->cur_stmt_type_\ + || OBPROXY_T_BEGIN == p->cur_stmt_type_) {\ + p->cur_stmt_type_ = stmt_type;\ + }\ + }\ +} while (0); + +#define SET_BASIC_STMT(stmt_type) \ +do {\ + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner);\ + if (OB_NOTNULL(p)) {\ + if (OBPROXY_T_INVALID == p->cur_stmt_type_\ + || OBPROXY_T_BEGIN == p->cur_stmt_type_) {\ + p->cur_stmt_type_ = stmt_type;\ + }\ + }\ +} while (0); + +#define SET_ICMD_STMT(stmt_type) \ +do {\ + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner);\ + if (OB_NOTNULL(p) && (OBPROXY_T_INVALID == p->cur_stmt_type_ || OBPROXY_T_SHOW == p->cur_stmt_type_)) {\ + p->cur_stmt_type_ = stmt_type;\ + }\ + store_str(yytext, yyleng, yytext + yyleng, yyscanner);\ +} while (0); + +#define SET_GLOBAL_SET_STMT() \ +do {\ + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner);\ + if (OB_NOTNULL(p) && (OBPROXY_T_SET == p->cur_stmt_type_)) {\ + p->cur_stmt_type_ = OBPROXY_T_SET_GLOBAL;\ + }\ +} while (0); + +#define RETURN_NON_RESERVED_KEYWORD(word_type) \ + { store_str(yytext, yyleng, yytext + yyleng, yyscanner); return word_type; } + +#define RETURN_NON_RESERVED_KEYWORD_WITH_QUOTE(word_type, quote_type) \ + { store_str_with_quote(quote_type, yytext + 1, yyleng - 2, yytext + yyleng, yyscanner); return word_type; } + +#define RETURN_INT_NUM() \ +do {\ + errno = 0;\ + yylval->num = strtoll(yytext, NULL, 10);\ + if (0 != errno) {\ + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner);\ + if (OB_NOTNULL(p) && OBPROXY_T_INVALID < p->cur_stmt_type_ && p->cur_stmt_type_ < OBPROXY_T_ICMD_MAX) {\ + p->cmd_info_.err_type_ = OBPROXY_T_ERR_INVALID_NUM;\ + } else {\ + yylval->num = 0;\ + }\ + }\ + return INT_NUM;\ +} while (0); + +#define RETURN_COMMENT_INT_NUM() \ +do {\ + errno = 0;\ + yylval->num = strtoll(yytext, NULL, 10);\ + if (0 != errno) {\ + store_str(yytext, yyleng, yytext + yyleng, yyscanner);\ + return NAME_OB;\ + }\ + return INT_NUM;\ +} while (0); + +#define RETURN_NUMBER_VAL() \ + { store_str(yytext, yyleng, yytext + yyleng, yyscanner); return NUMBER_VAL; } + +#define RETURN_COL_NAME(word_type) \ +do { \ + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner);\ + if (OB_NOTNULL(p)) {\ + if (!p->has_ignored_word_) {\ + if (p->col_name_.str_len_ > 0) {\ + p->has_ignored_word_ = true;\ + } else {\ + p->col_name_.str_ = yytext;\ + p->col_name_.end_ptr_ = yytext + yyleng;\ + p->col_name_.str_len_ = yyleng;\ + return word_type;\ + }\ + }\ + }\ +} while (0); + +#define RETURN_IGNORED_WORD() \ +do { \ + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner);\ + if (OB_NOTNULL(p)) {\ + p->has_ignored_word_ = true;\ + if (IN_TRANS_PARSE_MODE == p->parse_mode_) {\ + return ERROR;\ + }\ + }\ +} while (0); + +#define RETURN_IGNORED_WORD_FOR_DUAL() \ +do { \ + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner);\ + if (OB_NOTNULL(p)) {\ + p->has_ignored_word_ = true;\ + p->is_dual_request_ = true; \ + if (IN_TRANS_PARSE_MODE == p->parse_mode_) {\ + return ERROR;\ + }\ + }\ +} while (0); + +#define SET_LAST_INSERT_ID() \ +do { \ + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner);\ + if (OB_NOTNULL(p)) {\ + p->has_last_insert_id_ = true;\ + }\ +} while (0); + +#define SET_FOUND_ROWS() \ +do { \ + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner);\ + if (OB_NOTNULL(p)) {\ + p->has_found_rows_ = true;\ + }\ +} while (0); + +#define SET_ROW_COUNT() \ +do { \ + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner);\ + if (OB_NOTNULL(p)) {\ + p->has_row_count_ = true;\ + }\ +} while (0); + +#define SET_HAS_EXPLAIN() \ +do { \ + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner);\ + if (OB_NOTNULL(p)) {\ + p->has_explain_ = true;\ + }\ +} while (0); + +#define RETURN_SHARD_COMMENT_NAME_OB_DOT(word_type) \ +do {\ + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner);\ + if (OB_NOTNULL(p) && !p->has_shard_comment_) {\ + p->has_shard_comment_ = true;\ + }\ + store_str(yytext, yyleng - 1, yytext + yyleng - 1, yyscanner);\ + return word_type;\ +} while (0); + +#define RETURN_SHARD_COMMENT(word_type) \ +do {\ + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner);\ + if (OB_NOTNULL(p) && !p->has_shard_comment_) {\ + p->has_shard_comment_ = true;\ + }\ + return word_type;\ +} while (0); + +#define SET_HAS_ANONYMOUS_BLOCK() \ +do { \ + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner);\ + if (OB_NOTNULL(p)) {\ + if (OBPROXY_T_INVALID == p->cur_stmt_type_) {\ + p->has_anonymous_block_ = true;\ + } \ + }\ +} while (0); + +#define PUSH_STATE(state) \ + { yy_push_state(state, yyscanner); } + +#define POP_STATE(state) \ + { yy_pop_state(yyscanner); } + +#define PUSH_STATE_IF_NOT_ICMD(state) \ +do {\ + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner);\ + if (OB_NOTNULL(p) && OBPROXY_T_INVALID < p->cur_stmt_type_ && p->cur_stmt_type_ < OBPROXY_T_ICMD_MAX) {\ + /*do nothing*/\ + } else {\ + yy_push_state(state, yyscanner);\ + }\ +} while (0); + +#define RETURN_WITH_CALL_CHECK(key) \ +do {\ + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner);\ + if (OB_NOTNULL(p) && (OBPROXY_T_CALL == p->cur_stmt_type_ || OBPROXY_T_INSERT == p->cur_stmt_type_)) {\ + return key;\ + } else {\ + PUSH_STATE(INITIAL); \ + RETURN_IGNORED_WORD();\ + }\ +} while (0); + +#define ENTER_QUOTE_STATE(state) \ +do {\ + PUSH_STATE(state); \ + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; \ + if (OB_NOTNULL(p)) { \ + p->tmp_buf_ = (yytext + 1); \ + p->tmp_start_ptr_ = yytext; \ + p->tmp_len_ = 0; \ + }\ +} while (0); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/* limit the length of int_num from 1 to 17 in case of int64_t out of bound, 17 -> [ ( length of 2^64 ) - 2 ]*/ +/* binlog relate SQL */ +#line 5037 "ob_proxy_parser_gbk_lex.c" + +#define INITIAL 0 +#define hint 1 +#define in_c_comment 2 +#define in_comment_expr 3 +#define in_old_comment_expr 4 +#define in_odp_comment_expr 5 +#define in_odp_comment_value_expr 6 +#define in_odp_comment_value_expr_calc 7 +#define in_ignored_comment_expr 8 +#define in_dbp_comment_expr 9 +#define in_dbp_comment_trace_expr 10 +#define in_dbp_comment_trace_value_expr 11 +#define in_dbp_comment_trace_value_expr_calc 12 +#define comment_sq 13 +#define sq 14 +#define dq 15 +#define bt 16 +#define bt_in_expr 17 +#define in_expr 18 +#define in_anonymous_block 19 +#define in_subquery 20 +#define in_no_select_query 21 +#define prepare 22 +#define insert_all_expr 23 +#define set_expr 24 +#define show_elastic_id 25 +#define show_topology 26 +#define show_tables 27 +#define proxy_icmd_state 28 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* Holds the entire state of the reentrant scanner. */ +struct yyguts_t + { + + /* User-defined. Not touched by flex. */ + YY_EXTRA_TYPE yyextra_r; + + /* The rest are the same as the globals declared in the non-reentrant scanner. */ + FILE *yyin_r, *yyout_r; + size_t yy_buffer_stack_top; /**< index of top of stack. */ + size_t yy_buffer_stack_max; /**< capacity of stack. */ + YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ + char yy_hold_char; + int yy_n_chars; + int yyleng_r; + char *yy_c_buf_p; + int yy_init; + int yy_start; + int yy_did_buffer_switch_on_eof; + int yy_start_stack_ptr; + int yy_start_stack_depth; + int *yy_start_stack; + yy_state_type yy_last_accepting_state; + char* yy_last_accepting_cpos; + + int yylineno_r; + int yy_flex_debug_r; + + char *yytext_r; + int yy_more_flag; + int yy_more_len; + + YYSTYPE * yylval_r; + + YYLTYPE * yylloc_r; + + }; /* end struct yyguts_t */ + +static int yy_init_globals (yyscan_t yyscanner ); + + /* This must go here because YYSTYPE and YYLTYPE are included + * from bison output in section 1.*/ + # define yylval yyg->yylval_r + + # define yylloc yyg->yylloc_r + +int ob_proxy_parser_gbk_yylex_init (yyscan_t* scanner); + +int ob_proxy_parser_gbk_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int ob_proxy_parser_gbk_yylex_destroy (yyscan_t yyscanner ); + +int ob_proxy_parser_gbk_yyget_debug (yyscan_t yyscanner ); + +void ob_proxy_parser_gbk_yyset_debug (int debug_flag ,yyscan_t yyscanner ); + +YY_EXTRA_TYPE ob_proxy_parser_gbk_yyget_extra (yyscan_t yyscanner ); + +void ob_proxy_parser_gbk_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); + +FILE *ob_proxy_parser_gbk_yyget_in (yyscan_t yyscanner ); + +void ob_proxy_parser_gbk_yyset_in (FILE * in_str ,yyscan_t yyscanner ); + +FILE *ob_proxy_parser_gbk_yyget_out (yyscan_t yyscanner ); + +void ob_proxy_parser_gbk_yyset_out (FILE * out_str ,yyscan_t yyscanner ); + +int ob_proxy_parser_gbk_yyget_leng (yyscan_t yyscanner ); + +char *ob_proxy_parser_gbk_yyget_text (yyscan_t yyscanner ); + +int ob_proxy_parser_gbk_yyget_lineno (yyscan_t yyscanner ); + +void ob_proxy_parser_gbk_yyset_lineno (int line_number ,yyscan_t yyscanner ); + +YYSTYPE * ob_proxy_parser_gbk_yyget_lval (yyscan_t yyscanner ); + +void ob_proxy_parser_gbk_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); + + YYLTYPE *ob_proxy_parser_gbk_yyget_lloc (yyscan_t yyscanner ); + + void ob_proxy_parser_gbk_yyset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int ob_proxy_parser_gbk_yywrap (yyscan_t yyscanner ); +#else +extern int ob_proxy_parser_gbk_yywrap (yyscan_t yyscanner ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (yyscan_t yyscanner ); +#else +static int input (yyscan_t yyscanner ); +#endif + +#endif + + static void yy_push_state (int new_state ,yyscan_t yyscanner); + + static void yy_pop_state (yyscan_t yyscanner ); + + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + int n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int ob_proxy_parser_gbk_yylex \ + (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner); + +#define YY_DECL int ob_proxy_parser_gbk_yylex \ + (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +#line 398 "ob_proxy_parser_gbk.l" + + + /* basic dml stmt: */ +#line 5314 "ob_proxy_parser_gbk_lex.c" + + yylval = yylval_param; + + yylloc = yylloc_param; + + if ( !yyg->yy_init ) + { + yyg->yy_init = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yyg->yy_start ) + yyg->yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + ob_proxy_parser_gbk_yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + ob_proxy_parser_gbk_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + } + + ob_proxy_parser_gbk_yy_load_buffer_state(yyscanner ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yyg->yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yyg->yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yyg->yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 2515 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 15625 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yyg->yy_hold_char; + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 401 "ob_proxy_parser_gbk.l" +{ SET_DML_STMT(OBPROXY_T_SELECT); PUSH_STATE(in_expr); return SELECT; } + YY_BREAK +case 2: +YY_RULE_SETUP +#line 402 "ob_proxy_parser_gbk.l" +{ SET_DML_STMT(OBPROXY_T_DELETE); PUSH_STATE_IF_NOT_ICMD(in_expr); return DELETE; } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 403 "ob_proxy_parser_gbk.l" +{ SET_DML_STMT(OBPROXY_T_INSERT); return INSERT; } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 404 "ob_proxy_parser_gbk.l" +{ SET_DML_STMT(OBPROXY_T_UPDATE); return UPDATE; } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 405 "ob_proxy_parser_gbk.l" +{ SET_DML_STMT(OBPROXY_T_REPLACE); return REPLACE; } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 406 "ob_proxy_parser_gbk.l" +{ SET_DML_STMT(OBPROXY_T_MERGE); return MERGE; } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 407 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW; } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 408 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(XA); } + YY_BREAK +/* if begin is for starting transaction, will set has_anonymous_block = false in yacc */ +case 9: +YY_RULE_SETUP +#line 410 "ob_proxy_parser_gbk.l" +{ SET_HAS_ANONYMOUS_BLOCK(); RETURN_NON_RESERVED_KEYWORD(BEGI); } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 411 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(START); } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 412 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_COMMIT); RETURN_IGNORED_WORD(); } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 413 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_ROLLBACK); RETURN_IGNORED_WORD(); } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 414 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SET); PUSH_STATE_IF_NOT_ICMD(set_expr); return SET; } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 415 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_CALL); return CALL; } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 416 "ob_proxy_parser_gbk.l" +{ SET_HAS_ANONYMOUS_BLOCK(); PUSH_STATE(in_anonymous_block); } + YY_BREAK +case 16: +YY_RULE_SETUP +#line 417 "ob_proxy_parser_gbk.l" +{ ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner); + if (OB_NOTNULL(p)) { + if (OBPROXY_T_INSERT == p->cur_stmt_type_) + PUSH_STATE(insert_all_expr); + } + return WHEN; } + YY_BREAK +/* basic ddl stmt */ +case 17: +YY_RULE_SETUP +#line 425 "ob_proxy_parser_gbk.l" +{ return CREATE; } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 426 "ob_proxy_parser_gbk.l" +{ return DROP; } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 427 "ob_proxy_parser_gbk.l" +{ return ALTER; } + YY_BREAK +case 20: +YY_RULE_SETUP +#line 428 "ob_proxy_parser_gbk.l" +{ return TRUNCATE; } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 429 "ob_proxy_parser_gbk.l" +{ return RENAME; } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 430 "ob_proxy_parser_gbk.l" +{ return INDEX; } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 431 "ob_proxy_parser_gbk.l" +{ return TABLE; } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 432 "ob_proxy_parser_gbk.l" +{ return STATUS; } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 433 "ob_proxy_parser_gbk.l" +{ return FROM; } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 434 "ob_proxy_parser_gbk.l" +{ return UNIQUE; } + YY_BREAK +/* ps stmt */ +case 27: +YY_RULE_SETUP +#line 437 "ob_proxy_parser_gbk.l" +{ return USING; } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 438 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(prepare); return PREPARE; } + YY_BREAK +case 29: +YY_RULE_SETUP +#line 439 "ob_proxy_parser_gbk.l" +{ return EXECUTE; } + YY_BREAK +case 30: +YY_RULE_SETUP +#line 440 "ob_proxy_parser_gbk.l" +{ return DEALLOCATE; } + YY_BREAK +/* oracle ddl stmt */ +case 31: +YY_RULE_SETUP +#line 444 "ob_proxy_parser_gbk.l" +{ return GRANT; } + YY_BREAK +case 32: +YY_RULE_SETUP +#line 445 "ob_proxy_parser_gbk.l" +{ return REVOKE; } + YY_BREAK +case 33: +YY_RULE_SETUP +#line 446 "ob_proxy_parser_gbk.l" +{ return ANALYZE; } + YY_BREAK +case 34: +YY_RULE_SETUP +#line 447 "ob_proxy_parser_gbk.l" +{ return PURGE; } + YY_BREAK +case 35: +YY_RULE_SETUP +#line 448 "ob_proxy_parser_gbk.l" +{ return COMMENT; } + YY_BREAK +case 36: +YY_RULE_SETUP +#line 449 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(FLASHBACK); } + YY_BREAK +case 37: +YY_RULE_SETUP +#line 450 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(AUDIT); } + YY_BREAK +case 38: +YY_RULE_SETUP +#line 451 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(NOAUDIT); } + YY_BREAK +case 39: +YY_RULE_SETUP +#line 453 "ob_proxy_parser_gbk.l" +{ return GROUP;} + YY_BREAK +case 40: +YY_RULE_SETUP +#line 454 "ob_proxy_parser_gbk.l" +{ return HAVING;} + YY_BREAK +case 41: +YY_RULE_SETUP +#line 455 "ob_proxy_parser_gbk.l" +{ return ORDER;} + YY_BREAK +case 42: +YY_RULE_SETUP +#line 456 "ob_proxy_parser_gbk.l" +{ return FOR;} + YY_BREAK +case 43: +YY_RULE_SETUP +#line 457 "ob_proxy_parser_gbk.l" +{ return UNION;} + YY_BREAK +case 44: +YY_RULE_SETUP +#line 458 "ob_proxy_parser_gbk.l" +{ return AS; } + YY_BREAK +case 45: +YY_RULE_SETUP +#line 459 "ob_proxy_parser_gbk.l" +{ return WHERE; } + YY_BREAK +case 46: +YY_RULE_SETUP +#line 460 "ob_proxy_parser_gbk.l" +{ return VALUES; } + YY_BREAK +case 47: +YY_RULE_SETUP +#line 461 "ob_proxy_parser_gbk.l" +{ return VALUES; } + YY_BREAK +case 48: +YY_RULE_SETUP +#line 462 "ob_proxy_parser_gbk.l" +{ SET_HAS_EXPLAIN(); return EXPLAIN; } + YY_BREAK +case 49: +YY_RULE_SETUP +#line 463 "ob_proxy_parser_gbk.l" +{ SET_HAS_EXPLAIN(); return DESC; } + YY_BREAK +case 50: +YY_RULE_SETUP +#line 464 "ob_proxy_parser_gbk.l" +{ SET_HAS_EXPLAIN(); return DESCRIBE; } + YY_BREAK +/*change from non_reserved to reserved according https://dev.mysql.com/doc/refman/5.6/en/keywords.html*/ +case 51: +YY_RULE_SETUP +#line 466 "ob_proxy_parser_gbk.l" +{ return READ; } + YY_BREAK +case 52: +YY_RULE_SETUP +#line 467 "ob_proxy_parser_gbk.l" +{ return WITH; } + YY_BREAK +case 53: +YY_RULE_SETUP +#line 468 "ob_proxy_parser_gbk.l" +{ return USE; } + YY_BREAK +case 54: +YY_RULE_SETUP +#line 469 "ob_proxy_parser_gbk.l" +{ return LIMIT; } + YY_BREAK +case 55: +YY_RULE_SETUP +#line 470 "ob_proxy_parser_gbk.l" +{ return ALL; } + YY_BREAK +case 56: +YY_RULE_SETUP +#line 471 "ob_proxy_parser_gbk.l" +{ return LIKE; } + YY_BREAK +case 57: +YY_RULE_SETUP +#line 472 "ob_proxy_parser_gbk.l" +{ return PARTITION; } + YY_BREAK +case 58: +YY_RULE_SETUP +#line 473 "ob_proxy_parser_gbk.l" +{ return BINARY; } + YY_BREAK +case 59: +YY_RULE_SETUP +#line 474 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(GROUP_NAME); } + YY_BREAK +/* to make bison easy, do not return these reserved keyword in non strict mode */ +case 60: +YY_RULE_SETUP +#line 477 "ob_proxy_parser_gbk.l" +{ RETURN_IGNORED_WORD(); } + YY_BREAK +case 61: +YY_RULE_SETUP +#line 478 "ob_proxy_parser_gbk.l" +{ RETURN_IGNORED_WORD(); } + YY_BREAK +case 62: +YY_RULE_SETUP +#line 479 "ob_proxy_parser_gbk.l" +{ RETURN_IGNORED_WORD(); } + YY_BREAK +case 63: +YY_RULE_SETUP +#line 480 "ob_proxy_parser_gbk.l" +{ RETURN_IGNORED_WORD(); } + YY_BREAK +case 64: +YY_RULE_SETUP +#line 481 "ob_proxy_parser_gbk.l" +{ RETURN_IGNORED_WORD(); } + YY_BREAK +/* no reserved keyword , don't forget to add these keyword in .y */ +/*refer: https://dev.mysql.com/doc/refman/5.6/en/keywords.html*/ +case 65: +YY_RULE_SETUP +#line 485 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(QUICK); } + YY_BREAK +case 66: +YY_RULE_SETUP +#line 486 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(COUNT); } + YY_BREAK +case 67: +YY_RULE_SETUP +#line 487 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(WARNINGS); } + YY_BREAK +case 68: +YY_RULE_SETUP +#line 488 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(ERRORS); } + YY_BREAK +case 69: +YY_RULE_SETUP +#line 489 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(TRACE); } + YY_BREAK +case 70: +YY_RULE_SETUP +#line 490 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(TRANSACTION); } + YY_BREAK +case 71: +YY_RULE_SETUP +#line 492 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(ONLY); } + YY_BREAK +case 72: +YY_RULE_SETUP +#line 494 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(CONSISTENT); } + YY_BREAK +case 73: +YY_RULE_SETUP +#line 495 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(SNAPSHOT); } + YY_BREAK +case 74: +YY_RULE_SETUP +#line 497 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(HELP); } + YY_BREAK +/*set names*/ +case 75: +/* rule 75 can match eol */ +YY_RULE_SETUP +#line 501 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SET_NAMES); return SET_NAMES; } + YY_BREAK +/*set charset*/ +case 76: +/* rule 76 can match eol */ +YY_RULE_SETUP +#line 503 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SET_CHARSET); return SET_CHARSET; } + YY_BREAK +/*set passwd*/ +case 77: +/* rule 77 can match eol */ +YY_RULE_SETUP +#line 505 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SET_PASSWORD); return SET_PASSWORD; } + YY_BREAK +/*set default*/ +case 78: +/* rule 78 can match eol */ +YY_RULE_SETUP +#line 507 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SET_DEFAULT); return SET_DEFAULT; } + YY_BREAK +case 79: +/* rule 79 can match eol */ +YY_RULE_SETUP +#line 509 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SET_OB_READ_CONSISTENCY); return SET_OB_READ_CONSISTENCY; } + YY_BREAK +case 80: +/* rule 80 can match eol */ +YY_RULE_SETUP +#line 510 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SET_TX_READ_ONLY); return SET_TX_READ_ONLY; } + YY_BREAK +/*internal cmd*/ +/*show net*/ +case 81: +/* rule 81 can match eol */ +YY_RULE_SETUP +#line 514 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_NET); return SHOW_PROXYNET; } + YY_BREAK +case 82: +YY_RULE_SETUP +#line 515 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(THREAD); } + YY_BREAK +case 83: +YY_RULE_SETUP +#line 516 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(CONNECTION); } + YY_BREAK +case 84: +YY_RULE_SETUP +#line 518 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(OFFSET); } + YY_BREAK +/*show session*/ +case 85: +/* rule 85 can match eol */ +YY_RULE_SETUP +#line 521 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_GLOBAL_SESSION); return SHOW_GLOBALSESSION; } + YY_BREAK +case 86: +/* rule 86 can match eol */ +YY_RULE_SETUP +#line 522 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_SESSION); return SHOW_PROXYSESSION; } + YY_BREAK +case 87: +/* rule 87 can match eol */ +YY_RULE_SETUP +#line 523 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_PROCESSLIST); return SHOW_PROCESSLIST; } + YY_BREAK +case 88: +YY_RULE_SETUP +#line 524 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(ATTRIBUTE); } + YY_BREAK +case 89: +YY_RULE_SETUP +#line 525 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(VARIABLES); } + YY_BREAK +case 90: +YY_RULE_SETUP +#line 527 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(STAT); } + YY_BREAK +/*show config*/ +case 91: +/* rule 91 can match eol */ +YY_RULE_SETUP +#line 530 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_CONFIG); PUSH_STATE(proxy_icmd_state); return SHOW_PROXYCONFIG; } + YY_BREAK +case 92: +YY_RULE_SETUP +#line 532 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(DIFF); } + YY_BREAK +case 93: +YY_RULE_SETUP +#line 533 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(USER); } + YY_BREAK +case 94: +YY_RULE_SETUP +#line 534 "ob_proxy_parser_gbk.l" +{ POP_STATE(); return LIKE; } + YY_BREAK +/*show sm*/ +case 95: +/* rule 95 can match eol */ +YY_RULE_SETUP +#line 537 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_SM); return SHOW_PROXYSM; } + YY_BREAK +/*show cluster*/ +case 96: +/* rule 96 can match eol */ +YY_RULE_SETUP +#line 540 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_CLUSTER); return SHOW_PROXYCLUSTER; } + YY_BREAK +/*show resource*/ +case 97: +/* rule 97 can match eol */ +YY_RULE_SETUP +#line 543 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_RESOURCE); return SHOW_PROXYRESOURCE; } + YY_BREAK +/*show congestion*/ +case 98: +/* rule 98 can match eol */ +YY_RULE_SETUP +#line 546 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_CONGESTION); return SHOW_PROXYCONGESTION; } + YY_BREAK +/*show route*/ +case 99: +/* rule 99 can match eol */ +YY_RULE_SETUP +#line 549 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_ROUTE); return SHOW_PROXYROUTE; } + YY_BREAK +case 100: +YY_RULE_SETUP +#line 551 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(ROUTINE); } + YY_BREAK +/*show vip*/ +case 101: +/* rule 101 can match eol */ +YY_RULE_SETUP +#line 554 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_VIP); return SHOW_PROXYVIP; } + YY_BREAK +/*show memory*/ +case 102: +/* rule 102 can match eol */ +YY_RULE_SETUP +#line 557 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_MEMORY); return SHOW_PROXYMEMORY; } + YY_BREAK +case 103: +YY_RULE_SETUP +#line 558 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(OBJPOOL); } + YY_BREAK +/*show sqlaudit*/ +case 104: +/* rule 104 can match eol */ +YY_RULE_SETUP +#line 561 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_SQLAUDIT); return SHOW_SQLAUDIT; } + YY_BREAK +/*show warnlog*/ +case 105: +/* rule 105 can match eol */ +YY_RULE_SETUP +#line 564 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_WARNLOG); return SHOW_WARNLOG; } + YY_BREAK +/*show stat*/ +case 106: +/* rule 106 can match eol */ +YY_RULE_SETUP +#line 567 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_STAT); return SHOW_PROXYSTAT; } + YY_BREAK +case 107: +YY_RULE_SETUP +#line 568 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(REFRESH); } + YY_BREAK +/*show trace*/ +case 108: +/* rule 108 can match eol */ +YY_RULE_SETUP +#line 571 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_TRACE); return SHOW_PROXYTRACE; } + YY_BREAK +/*show info*/ +case 109: +/* rule 109 can match eol */ +YY_RULE_SETUP +#line 574 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_INFO); return SHOW_PROXYINFO; } + YY_BREAK +case 110: +YY_RULE_SETUP +#line 575 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(UPGRADE); } + YY_BREAK +case 111: +YY_RULE_SETUP +#line 576 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(IDC); } + YY_BREAK +case 112: +/* rule 112 can match eol */ +YY_RULE_SETUP +#line 578 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW); PUSH_STATE(show_elastic_id ); return SHOW_ELASTIC_ID; } + YY_BREAK +case 113: +YY_RULE_SETUP +#line 579 "ob_proxy_parser_gbk.l" +{ POP_STATE(); PUSH_STATE(INITIAL); return FROM; } + YY_BREAK +case 114: +YY_RULE_SETUP +#line 580 "ob_proxy_parser_gbk.l" +{ POP_STATE(); PUSH_STATE(INITIAL); return WHERE; } + YY_BREAK +case YY_STATE_EOF(show_elastic_id): +#line 581 "ob_proxy_parser_gbk.l" +{ return END_P; } + YY_BREAK +case 115: +/* rule 115 can match eol */ +YY_RULE_SETUP +#line 582 "ob_proxy_parser_gbk.l" +{ } + YY_BREAK +case 116: +YY_RULE_SETUP +#line 583 "ob_proxy_parser_gbk.l" +{ POP_STATE(); PUSH_STATE(INITIAL); return yytext[0]; } + YY_BREAK +case 117: +YY_RULE_SETUP +#line 584 "ob_proxy_parser_gbk.l" +{ return ERROR; } + YY_BREAK +case 118: +/* rule 118 can match eol */ +YY_RULE_SETUP +#line 586 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_TOPOLOGY; } + YY_BREAK +case 119: +/* rule 119 can match eol */ +YY_RULE_SETUP +#line 588 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_DB_VERSION; } + YY_BREAK +case 120: +/* rule 120 can match eol */ +YY_RULE_SETUP +#line 589 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_DATABASES; } + YY_BREAK +case 121: +/* rule 121 can match eol */ +YY_RULE_SETUP +#line 591 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW); PUSH_STATE(show_tables); return SHOW_TABLES; } + YY_BREAK +case 122: +/* rule 122 can match eol */ +YY_RULE_SETUP +#line 592 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW); PUSH_STATE(show_tables); return SHOW_FULL_TABLES; } + YY_BREAK +case 123: +YY_RULE_SETUP +#line 594 "ob_proxy_parser_gbk.l" +{ POP_STATE(); PUSH_STATE(INITIAL); return FROM; } + YY_BREAK +case 124: +YY_RULE_SETUP +#line 595 "ob_proxy_parser_gbk.l" +{ POP_STATE(); PUSH_STATE(INITIAL); return LIKE; } + YY_BREAK +case YY_STATE_EOF(show_tables): +#line 596 "ob_proxy_parser_gbk.l" +{ return END_P; } + YY_BREAK +case 125: +/* rule 125 can match eol */ +YY_RULE_SETUP +#line 597 "ob_proxy_parser_gbk.l" +{ } + YY_BREAK +case 126: +YY_RULE_SETUP +#line 598 "ob_proxy_parser_gbk.l" +{ POP_STATE(); PUSH_STATE(INITIAL); return yytext[0]; } + YY_BREAK +case 127: +YY_RULE_SETUP +#line 599 "ob_proxy_parser_gbk.l" +{ return ERROR; } + YY_BREAK +case 128: +/* rule 128 can match eol */ +YY_RULE_SETUP +#line 600 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_COLUMNS; } + YY_BREAK +case 129: +/* rule 129 can match eol */ +YY_RULE_SETUP +#line 601 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_INDEX; } + YY_BREAK +case 130: +/* rule 130 can match eol */ +YY_RULE_SETUP +#line 603 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_CREATE_TABLE; } + YY_BREAK +case 131: +/* rule 131 can match eol */ +YY_RULE_SETUP +#line 604 "ob_proxy_parser_gbk.l" +{ SET_DML_STMT(OBPROXY_T_SELECT); return SELECT_DATABASE; } + YY_BREAK +case 132: +/* rule 132 can match eol */ +YY_RULE_SETUP +#line 605 "ob_proxy_parser_gbk.l" +{ SET_DML_STMT(OBPROXY_T_SELECT_PROXY_VERSION); return SELECT_PROXY_VERSION; } + YY_BREAK +/*alter config*/ +case 133: +/* rule 133 can match eol */ +YY_RULE_SETUP +#line 608 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_ALTER_CONFIG); return ALTER_PROXYCONFIG; } + YY_BREAK +/*alter resource*/ +case 134: +/* rule 134 can match eol */ +YY_RULE_SETUP +#line 611 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_ALTER_RESOURCE); return ALTER_PROXYRESOURCE; } + YY_BREAK +/*ping proxy*/ +case 135: +/* rule 135 can match eol */ +YY_RULE_SETUP +#line 614 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_PING_PROXY); return PING_PROXY; } + YY_BREAK +/*kill*/ +case 136: +/* rule 136 can match eol */ +YY_RULE_SETUP +#line 617 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_KILL_SESSION); return KILL_PROXYSESSION; } + YY_BREAK +case 137: +/* rule 137 can match eol */ +YY_RULE_SETUP +#line 618 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_KILL_GLOBAL_SESSION); return KILL_GLOBALSESSION; } + YY_BREAK +case 138: +YY_RULE_SETUP +#line 619 "ob_proxy_parser_gbk.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_KILL_MYSQL); return KILL; } + YY_BREAK +case 139: +YY_RULE_SETUP +#line 620 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(QUERY); } + YY_BREAK +/* obproxy_route_addr */ +case 140: +/* rule 140 can match eol */ +YY_RULE_SETUP +#line 623 "ob_proxy_parser_gbk.l" +{ return SELECT_OBPROXY_ROUTE_ADDR; } + YY_BREAK +case 141: +/* rule 141 can match eol */ +YY_RULE_SETUP +#line 624 "ob_proxy_parser_gbk.l" +{ return SET_OBPROXY_ROUTE_ADDR; } + YY_BREAK +/* identifer */ +case 142: +YY_RULE_SETUP +#line 627 "ob_proxy_parser_gbk.l" +{ SET_FOUND_ROWS(); RETURN_NON_RESERVED_KEYWORD(NAME_OB); } + YY_BREAK +case 143: +YY_RULE_SETUP +#line 628 "ob_proxy_parser_gbk.l" +{ SET_ROW_COUNT(); RETURN_NON_RESERVED_KEYWORD(NAME_OB); } + YY_BREAK +case 144: +YY_RULE_SETUP +#line 629 "ob_proxy_parser_gbk.l" +{ SET_LAST_INSERT_ID(); RETURN_NON_RESERVED_KEYWORD(NAME_OB); } + YY_BREAK +case 145: +YY_RULE_SETUP +#line 630 "ob_proxy_parser_gbk.l" +{ return ','; } + YY_BREAK +case 146: +YY_RULE_SETUP +#line 631 "ob_proxy_parser_gbk.l" +{ RETURN_INT_NUM(); } + YY_BREAK +case 147: +YY_RULE_SETUP +#line 632 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(NAME_OB); } + YY_BREAK +case 148: +YY_RULE_SETUP +#line 633 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD_WITH_QUOTE(NAME_OB, OBPROXY_QUOTE_T_SINGLE); } + YY_BREAK +case 149: +YY_RULE_SETUP +#line 634 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD_WITH_QUOTE(NAME_OB, OBPROXY_QUOTE_T_DOUBLE); } + YY_BREAK +case 150: +YY_RULE_SETUP +#line 635 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD_WITH_QUOTE(NAME_OB, OBPROXY_QUOTE_T_BACK); } + YY_BREAK +case 151: +YY_RULE_SETUP +#line 636 "ob_proxy_parser_gbk.l" +{ RETURN_NUMBER_VAL(); } + YY_BREAK +case 152: +YY_RULE_SETUP +#line 637 "ob_proxy_parser_gbk.l" +{ return PLACE_HOLDER; } + YY_BREAK +case 153: +YY_RULE_SETUP +#line 638 "ob_proxy_parser_gbk.l" +{ return yytext[0]; } + YY_BREAK +case 154: +YY_RULE_SETUP +#line 639 "ob_proxy_parser_gbk.l" +{ RETURN_WITH_CALL_CHECK(yytext[0]); } + YY_BREAK +case 155: +YY_RULE_SETUP +#line 640 "ob_proxy_parser_gbk.l" +{ RETURN_WITH_CALL_CHECK('('); } + YY_BREAK +case 156: +YY_RULE_SETUP +#line 641 "ob_proxy_parser_gbk.l" +{ RETURN_WITH_CALL_CHECK(')'); } + YY_BREAK +case 157: +/* rule 157 can match eol */ +YY_RULE_SETUP +#line 642 "ob_proxy_parser_gbk.l" +{ } + YY_BREAK +/* hint option */ +case 158: +/* rule 158 can match eol */ +YY_RULE_SETUP +#line 645 "ob_proxy_parser_gbk.l" +{ + PUSH_STATE(in_expr); + PUSH_STATE(hint); + SET_BASIC_STMT(OBPROXY_T_SELECT); + return SELECT_HINT_BEGIN; +} + YY_BREAK +case 159: +/* rule 159 can match eol */ +YY_RULE_SETUP +#line 651 "ob_proxy_parser_gbk.l" +{ + PUSH_STATE(hint); + SET_BASIC_STMT(OBPROXY_T_UPDATE); + return UPDATE_HINT_BEGIN; +} + YY_BREAK +case 160: +/* rule 160 can match eol */ +YY_RULE_SETUP +#line 656 "ob_proxy_parser_gbk.l" +{ + PUSH_STATE(in_expr); + PUSH_STATE(hint); + SET_BASIC_STMT(OBPROXY_T_DELETE); + return DELETE_HINT_BEGIN; +} + YY_BREAK +case 161: +/* rule 161 can match eol */ +YY_RULE_SETUP +#line 662 "ob_proxy_parser_gbk.l" +{ + PUSH_STATE(hint); + SET_BASIC_STMT(OBPROXY_T_INSERT); + return INSERT_HINT_BEGIN; +} + YY_BREAK +case 162: +/* rule 162 can match eol */ +YY_RULE_SETUP +#line 667 "ob_proxy_parser_gbk.l" +{ + PUSH_STATE(hint); + SET_BASIC_STMT(OBPROXY_T_REPLACE); + return REPLACE_HINT_BEGIN; +} + YY_BREAK +case 163: +/* rule 163 can match eol */ +YY_RULE_SETUP +#line 672 "ob_proxy_parser_gbk.l" +{ + PUSH_STATE(hint); + SET_BASIC_STMT(OBPROXY_T_MERGE); + return MERGE_HINT_BEGIN; +} + YY_BREAK +case 164: +/* rule 164 can match eol */ +YY_RULE_SETUP +#line 678 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW_MASTER_STATUS); return SHOW_MASTER_STATUS; } + YY_BREAK +case 165: +/* rule 165 can match eol */ +YY_RULE_SETUP +#line 679 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW_BINARY_LOGS); return SHOW_BINARY_LOGS; } + YY_BREAK +case 166: +/* rule 166 can match eol */ +YY_RULE_SETUP +#line 680 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW_BINLOG_EVENTS); return SHOW_BINLOG_EVENTS; } + YY_BREAK +case 167: +/* rule 167 can match eol */ +YY_RULE_SETUP +#line 681 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_PURGE_BINARY_LOGS); return PURGE_BINARY_LOGS; } + YY_BREAK +case 168: +/* rule 168 can match eol */ +YY_RULE_SETUP +#line 682 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_RESET_MASTER); return RESET_MASTER; } + YY_BREAK +case 169: +/* rule 169 can match eol */ +YY_RULE_SETUP +#line 683 "ob_proxy_parser_gbk.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW_BINLOG_SERVER_FOR_TENANT); return SHOW_BINLOG_SERVER_FOR_TENANT; } + YY_BREAK +case 170: +YY_RULE_SETUP +#line 685 "ob_proxy_parser_gbk.l" +{ return GLOBAL; } + YY_BREAK +case 171: +YY_RULE_SETUP +#line 686 "ob_proxy_parser_gbk.l" +{ return SESSION; } + YY_BREAK +case 172: +YY_RULE_SETUP +#line 687 "ob_proxy_parser_gbk.l" +{ RETURN_INT_NUM(); } + YY_BREAK +case 173: +YY_RULE_SETUP +#line 688 "ob_proxy_parser_gbk.l" +{ return ','; } + YY_BREAK +case 174: +YY_RULE_SETUP +#line 689 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(NAME_OB); } + YY_BREAK +case 175: +YY_RULE_SETUP +#line 690 "ob_proxy_parser_gbk.l" +{ RETURN_NUMBER_VAL(); } + YY_BREAK +case 176: +/* rule 176 can match eol */ +YY_RULE_SETUP +#line 691 "ob_proxy_parser_gbk.l" +{ } + YY_BREAK +case 177: +YY_RULE_SETUP +#line 692 "ob_proxy_parser_gbk.l" +{ return yytext[0]; } + YY_BREAK +case YY_STATE_EOF(set_expr): +#line 693 "ob_proxy_parser_gbk.l" +{ return END_P; } + YY_BREAK +case 178: +YY_RULE_SETUP +#line 694 "ob_proxy_parser_gbk.l" +{ POP_STATE(); PUSH_STATE(INITIAL); return yytext[0]; } + YY_BREAK +case 179: +YY_RULE_SETUP +#line 696 "ob_proxy_parser_gbk.l" +{ + PUSH_STATE(sq); + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->tmp_buf_ = (yytext + 1); + p->tmp_start_ptr_ = yytext; + p->tmp_len_ = 0; + } +} + YY_BREAK +case 180: +YY_RULE_SETUP +#line 706 "ob_proxy_parser_gbk.l" +{ + PUSH_STATE(dq); + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->tmp_buf_ = (yytext + 1); + p->tmp_start_ptr_ = yytext; + p->tmp_len_ = 0; + } +} + YY_BREAK +case 181: +YY_RULE_SETUP +#line 716 "ob_proxy_parser_gbk.l" +{ + PUSH_STATE(bt); + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (NULL != p) { + p->tmp_buf_ = (char *)obproxy_parse_malloc(OBPROXY_MAX_NAME_LENGTH, p->malloc_pool_); + p->tmp_start_ptr_ = yytext; + p->tmp_len_ = 0; + } +} + YY_BREAK +case 182: +YY_RULE_SETUP +#line 725 "ob_proxy_parser_gbk.l" +{ return ERROR; } + YY_BREAK +case 183: +YY_RULE_SETUP +#line 727 "ob_proxy_parser_gbk.l" +{ POP_STATE(); RETURN_IGNORED_WORD(); } + YY_BREAK +case 184: +YY_RULE_SETUP +#line 728 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case 185: +YY_RULE_SETUP +#line 730 "ob_proxy_parser_gbk.l" +{ return '('; } + YY_BREAK +case 186: +YY_RULE_SETUP +#line 731 "ob_proxy_parser_gbk.l" +{ return ')'; } + YY_BREAK +case 187: +YY_RULE_SETUP +#line 732 "ob_proxy_parser_gbk.l" +{ return QUERY_TIMEOUT; } + YY_BREAK +case 188: +YY_RULE_SETUP +#line 733 "ob_proxy_parser_gbk.l" +{ RETURN_INT_NUM(); } + YY_BREAK +case 189: +YY_RULE_SETUP +#line 734 "ob_proxy_parser_gbk.l" +{ return READ_CONSISTENCY; } + YY_BREAK +case 190: +YY_RULE_SETUP +#line 735 "ob_proxy_parser_gbk.l" +{ return WEAK; } + YY_BREAK +case 191: +YY_RULE_SETUP +#line 736 "ob_proxy_parser_gbk.l" +{ return STRONG; } + YY_BREAK +case 192: +YY_RULE_SETUP +#line 737 "ob_proxy_parser_gbk.l" +{ return FROZEN; } + YY_BREAK +case 193: +YY_RULE_SETUP +#line 738 "ob_proxy_parser_gbk.l" +{ return INDEX; } + YY_BREAK +case 194: +YY_RULE_SETUP +#line 739 "ob_proxy_parser_gbk.l" +{ return yytext[0]; } + YY_BREAK +case 195: +YY_RULE_SETUP +#line 740 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(NAME_OB); } + YY_BREAK +case 196: +YY_RULE_SETUP +#line 741 "ob_proxy_parser_gbk.l" +{ POP_STATE(); return HINT_END; } + YY_BREAK +case 197: +YY_RULE_SETUP +#line 742 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +/* comment */ +case 198: +YY_RULE_SETUP +#line 745 "ob_proxy_parser_gbk.l" +{ + PUSH_STATE(in_c_comment); + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + if (OBPROXY_T_INVALID == p->cur_stmt_type_) { + if (NULL == p->comment_begin_) { + p->comment_begin_ = yytext; + } + PUSH_STATE(in_comment_expr); + return COMMENT_BEGIN; + } + } +} + YY_BREAK +case 199: +YY_RULE_SETUP +#line 759 "ob_proxy_parser_gbk.l" +{ POP_STATE(); } + YY_BREAK +case 200: +/* rule 200 can match eol */ +YY_RULE_SETUP +#line 760 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case 201: +YY_RULE_SETUP +#line 761 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case 202: +YY_RULE_SETUP +#line 763 "ob_proxy_parser_gbk.l" +{ + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->comment_end_ = yytext + 2; + } + POP_STATE(); + POP_STATE(); + return COMMENT_END; +} + YY_BREAK +case 203: +YY_RULE_SETUP +#line 773 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_old_comment_expr); } + YY_BREAK +case 204: +/* rule 204 can match eol */ +YY_RULE_SETUP +#line 774 "ob_proxy_parser_gbk.l" +{ + PUSH_STATE(in_old_comment_expr); + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->simple_route_info_.table_start_ptr_ = yytext; + return ROUTE_TABLE; + } +} + YY_BREAK +case 205: +/* rule 205 can match eol */ +YY_RULE_SETUP +#line 783 "ob_proxy_parser_gbk.l" +{ + PUSH_STATE(in_old_comment_expr); + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + if (OBPROXY_T_INVALID == p->cur_stmt_type_) { + p->simple_route_info_.part_key_start_ptr_ = yytext; + return ROUTE_PART_KEY; + } + } +} + YY_BREAK +case 206: +YY_RULE_SETUP +#line 794 "ob_proxy_parser_gbk.l" +{ + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->simple_route_info_.table_start_ptr_ = yytext; + return ROUTE_TABLE; + } +} + YY_BREAK +case 207: +YY_RULE_SETUP +#line 802 "ob_proxy_parser_gbk.l" +{ + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + if (OBPROXY_T_INVALID == p->cur_stmt_type_) { + p->simple_route_info_.part_key_start_ptr_ = yytext; + return ROUTE_PART_KEY; + } + } +} + YY_BREAK +case 208: +YY_RULE_SETUP +#line 812 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(NAME_OB); } + YY_BREAK +case 209: +YY_RULE_SETUP +#line 813 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD_WITH_QUOTE(NAME_OB, OBPROXY_QUOTE_T_SINGLE); } + YY_BREAK +case 210: +YY_RULE_SETUP +#line 814 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD_WITH_QUOTE(NAME_OB, OBPROXY_QUOTE_T_DOUBLE); } + YY_BREAK +case 211: +YY_RULE_SETUP +#line 815 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD_WITH_QUOTE(NAME_OB, OBPROXY_QUOTE_T_BACK); } + YY_BREAK +case 212: +YY_RULE_SETUP +#line 816 "ob_proxy_parser_gbk.l" +{ + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->comment_end_ = yytext + 2; + } + POP_STATE(); + POP_STATE(); + POP_STATE(); + return COMMENT_END; +} + YY_BREAK +case 213: +YY_RULE_SETUP +#line 826 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case 214: +YY_RULE_SETUP +#line 828 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(ODP_COMMENT); } + YY_BREAK +case 215: +/* rule 215 can match eol */ +YY_RULE_SETUP +#line 829 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(GROUP_ID); } + YY_BREAK +case 216: +/* rule 216 can match eol */ +YY_RULE_SETUP +#line 830 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(TABLE_ID); } + YY_BREAK +case 217: +/* rule 217 can match eol */ +YY_RULE_SETUP +#line 831 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(TABLE_NAME); } + YY_BREAK +case 218: +/* rule 218 can match eol */ +YY_RULE_SETUP +#line 832 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(ELASTIC_ID); } + YY_BREAK +case 219: +/* rule 219 can match eol */ +YY_RULE_SETUP +#line 833 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(TESTLOAD); } + YY_BREAK +case 220: +/* rule 220 can match eol */ +YY_RULE_SETUP +#line 834 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(DISASTER_STATUS); } + YY_BREAK +case 221: +/* rule 221 can match eol */ +YY_RULE_SETUP +#line 835 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(TNT_ID); } + YY_BREAK +case 222: +/* rule 222 can match eol */ +YY_RULE_SETUP +#line 836 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(TRACE_ID); } + YY_BREAK +case 223: +/* rule 223 can match eol */ +YY_RULE_SETUP +#line 837 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT_NAME_OB_DOT(NAME_OB_DOT); } + YY_BREAK +case 224: +/* rule 224 can match eol */ +YY_RULE_SETUP +#line 838 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(RPC_ID); } + YY_BREAK +case 225: +/* rule 225 can match eol */ +YY_RULE_SETUP +#line 839 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_odp_comment_expr); return TARGET_DB_SERVER; } + YY_BREAK +case 226: +YY_RULE_SETUP +#line 841 "ob_proxy_parser_gbk.l" +{ return GROUP_ID; } + YY_BREAK +case 227: +YY_RULE_SETUP +#line 842 "ob_proxy_parser_gbk.l" +{ return TABLE_ID; } + YY_BREAK +case 228: +YY_RULE_SETUP +#line 843 "ob_proxy_parser_gbk.l" +{ return TABLE_NAME; } + YY_BREAK +case 229: +YY_RULE_SETUP +#line 844 "ob_proxy_parser_gbk.l" +{ return ELASTIC_ID; } + YY_BREAK +case 230: +YY_RULE_SETUP +#line 845 "ob_proxy_parser_gbk.l" +{ return TESTLOAD; } + YY_BREAK +case 231: +YY_RULE_SETUP +#line 846 "ob_proxy_parser_gbk.l" +{ return DISASTER_STATUS; } + YY_BREAK +case 232: +YY_RULE_SETUP +#line 847 "ob_proxy_parser_gbk.l" +{ return TNT_ID; } + YY_BREAK +case 233: +YY_RULE_SETUP +#line 848 "ob_proxy_parser_gbk.l" +{ return TRACE_ID; } + YY_BREAK +case 234: +YY_RULE_SETUP +#line 849 "ob_proxy_parser_gbk.l" +{ return RPC_ID; } + YY_BREAK +case 235: +YY_RULE_SETUP +#line 850 "ob_proxy_parser_gbk.l" +{ return TARGET_DB_SERVER; } + YY_BREAK +case 236: +YY_RULE_SETUP +#line 851 "ob_proxy_parser_gbk.l" +{ ENTER_QUOTE_STATE(comment_sq); } + YY_BREAK +case 237: +YY_RULE_SETUP +#line 852 "ob_proxy_parser_gbk.l" +{ return ','; } + YY_BREAK +case 238: +YY_RULE_SETUP +#line 853 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(NAME_OB); } + YY_BREAK +case 239: +YY_RULE_SETUP +#line 854 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_odp_comment_value_expr); return yytext[0]; } + YY_BREAK +case 240: +YY_RULE_SETUP +#line 855 "ob_proxy_parser_gbk.l" +{ return yytext[0]; } + YY_BREAK +case 241: +/* rule 241 can match eol */ +YY_RULE_SETUP +#line 856 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case 242: +YY_RULE_SETUP +#line 857 "ob_proxy_parser_gbk.l" +{ return ERROR; } + YY_BREAK +case 243: +YY_RULE_SETUP +#line 858 "ob_proxy_parser_gbk.l" +{ + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->comment_end_ = yytext + 2; + } + POP_STATE(); + POP_STATE(); + POP_STATE(); + return COMMENT_END; +} + YY_BREAK +case 244: +YY_RULE_SETUP +#line 869 "ob_proxy_parser_gbk.l" +{ ENTER_QUOTE_STATE(comment_sq); } + YY_BREAK +case 245: +YY_RULE_SETUP +#line 870 "ob_proxy_parser_gbk.l" +{ + POP_STATE(); + return ','; +} + YY_BREAK +case 246: +YY_RULE_SETUP +#line 874 "ob_proxy_parser_gbk.l" +{ + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->comment_end_ = yytext + 2; + } + POP_STATE(); + POP_STATE(); + POP_STATE(); + POP_STATE(); + return COMMENT_END; +} + YY_BREAK +case 247: +/* rule 247 can match eol */ +YY_RULE_SETUP +#line 885 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case 248: +YY_RULE_SETUP +#line 886 "ob_proxy_parser_gbk.l" +{ + do { + PUSH_STATE(in_odp_comment_value_expr_calc) + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->tmp_buf_ = yytext; + p->tmp_start_ptr_ = yytext; + p->tmp_len_ = 1; + } + } while (0); +} + YY_BREAK +case 249: +/* rule 249 can match eol */ +YY_RULE_SETUP +#line 898 "ob_proxy_parser_gbk.l" +{ + POP_STATE(); + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p) && OB_NOTNULL(p->tmp_buf_)) { + store_str(p->tmp_buf_, p->tmp_len_, p->tmp_start_ptr_ + p->tmp_len_, yyscanner); + yyless(0); + return NAME_STR; + } else { + RETURN_IGNORED_WORD(); + } +} + YY_BREAK +case 250: +YY_RULE_SETUP +#line 910 "ob_proxy_parser_gbk.l" +{ + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->tmp_len_ += yyleng; + } +} + YY_BREAK +case 251: +YY_RULE_SETUP +#line 917 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_dbp_comment_expr); RETURN_SHARD_COMMENT(DBP_COMMENT); } + YY_BREAK +case 252: +YY_RULE_SETUP +#line 918 "ob_proxy_parser_gbk.l" +{ return ROUTE_TAG; } + YY_BREAK +case 253: +YY_RULE_SETUP +#line 919 "ob_proxy_parser_gbk.l" +{ return SYS_TAG; } + YY_BREAK +case 254: +YY_RULE_SETUP +#line 920 "ob_proxy_parser_gbk.l" +{ return SCAN_ALL; } + YY_BREAK +case 255: +YY_RULE_SETUP +#line 921 "ob_proxy_parser_gbk.l" +{ return STICKY_SESSION; } + YY_BREAK +case 256: +YY_RULE_SETUP +#line 922 "ob_proxy_parser_gbk.l" +{ return SHARD_KEY; } + YY_BREAK +case 257: +YY_RULE_SETUP +#line 923 "ob_proxy_parser_gbk.l" +{ return TABLE_NAME;} + YY_BREAK +case 258: +YY_RULE_SETUP +#line 924 "ob_proxy_parser_gbk.l" +{ return PARALL; } + YY_BREAK +case 259: +YY_RULE_SETUP +#line 925 "ob_proxy_parser_gbk.l" +{ return GROUP_ID; } + YY_BREAK +case 260: +YY_RULE_SETUP +#line 926 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_dbp_comment_trace_expr); return TRACE; } + YY_BREAK +case 261: +YY_RULE_SETUP +#line 927 "ob_proxy_parser_gbk.l" +{ ENTER_QUOTE_STATE(comment_sq); } + YY_BREAK +case 262: +YY_RULE_SETUP +#line 928 "ob_proxy_parser_gbk.l" +{ return yytext[0]; } + YY_BREAK +case 263: +YY_RULE_SETUP +#line 929 "ob_proxy_parser_gbk.l" +{ return '('; } + YY_BREAK +case 264: +YY_RULE_SETUP +#line 930 "ob_proxy_parser_gbk.l" +{ return ')'; } + YY_BREAK +case 265: +YY_RULE_SETUP +#line 931 "ob_proxy_parser_gbk.l" +{ return ','; } + YY_BREAK +case 266: +/* rule 266 can match eol */ +YY_RULE_SETUP +#line 932 "ob_proxy_parser_gbk.l" +{ } + YY_BREAK +case 267: +YY_RULE_SETUP +#line 933 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(NAME_OB); } + YY_BREAK +case 268: +YY_RULE_SETUP +#line 935 "ob_proxy_parser_gbk.l" +{ + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->comment_end_ = yytext + 2; + } + POP_STATE(); + POP_STATE(); + POP_STATE(); + return COMMENT_END; +} + YY_BREAK +case 269: +YY_RULE_SETUP +#line 945 "ob_proxy_parser_gbk.l" +{return yytext[0];} + YY_BREAK +case 270: +YY_RULE_SETUP +#line 946 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_dbp_comment_trace_value_expr); return '('; } + YY_BREAK +case 271: +/* rule 271 can match eol */ +YY_RULE_SETUP +#line 947 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case 272: +YY_RULE_SETUP +#line 949 "ob_proxy_parser_gbk.l" +{ ENTER_QUOTE_STATE(comment_sq); } + YY_BREAK +case 273: +YY_RULE_SETUP +#line 950 "ob_proxy_parser_gbk.l" +{ + POP_STATE(); + POP_STATE(); + return ')'; +} + YY_BREAK +case 274: +YY_RULE_SETUP +#line 955 "ob_proxy_parser_gbk.l" +{ + do { + PUSH_STATE(in_dbp_comment_trace_value_expr_calc) + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->tmp_buf_ = yytext; + p->tmp_start_ptr_ = yytext; + p->tmp_len_ = 1; + } + return yytext[0]; + } while (0); +} + YY_BREAK +case 275: +YY_RULE_SETUP +#line 967 "ob_proxy_parser_gbk.l" +{ + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->comment_end_ = yytext + 2; + } + POP_STATE(); + POP_STATE(); + POP_STATE(); + POP_STATE(); + POP_STATE(); + return COMMENT_END; +} + YY_BREAK +case 276: +/* rule 276 can match eol */ +YY_RULE_SETUP +#line 979 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case 277: +YY_RULE_SETUP +#line 980 "ob_proxy_parser_gbk.l" +{ + do { + PUSH_STATE(in_dbp_comment_trace_value_expr_calc) + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->tmp_buf_ = yytext; + p->tmp_start_ptr_ = yytext; + p->tmp_len_ = 0; + } + } while (0); +} + YY_BREAK +case 278: +/* rule 278 can match eol */ +YY_RULE_SETUP +#line 992 "ob_proxy_parser_gbk.l" +{ + POP_STATE(); + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p) && OB_NOTNULL(p->tmp_buf_)) { + store_str(p->tmp_buf_, p->tmp_len_, p->tmp_start_ptr_ + p->tmp_len_, yyscanner); + yyless(0); + return NAME_STR; + } else { + RETURN_IGNORED_WORD(); + } +} + YY_BREAK +case 279: +YY_RULE_SETUP +#line 1004 "ob_proxy_parser_gbk.l" +{ + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->tmp_len_ += yyleng; + } +} + YY_BREAK +/* quote */ +case 280: +YY_RULE_SETUP +#line 1012 "ob_proxy_parser_gbk.l" +{ + PUSH_STATE(sq); + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->tmp_buf_ = (yytext + 1); + p->tmp_start_ptr_ = yytext; + p->tmp_len_ = 0; + } +} + YY_BREAK +case 281: +/* rule 281 can match eol */ +YY_RULE_SETUP +#line 1022 "ob_proxy_parser_gbk.l" +{ + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->tmp_len_ += yyleng; + } +} + YY_BREAK +case 282: +YY_RULE_SETUP +#line 1029 "ob_proxy_parser_gbk.l" +{ + POP_STATE(); + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p) + && OBPROXY_T_INVALID < p->cur_stmt_type_ + && (p->cur_stmt_type_ < OBPROXY_T_ICMD_MAX + || OBPROXY_T_CALL == p->cur_stmt_type_ + || OBPROXY_T_SET == p->cur_stmt_type_ + || OBPROXY_T_SHOW == p->cur_stmt_type_) + && OB_NOTNULL(p->tmp_buf_)) { + store_str_with_quote(OBPROXY_QUOTE_T_SINGLE, p->tmp_buf_, p->tmp_len_, p->tmp_start_ptr_ + p->tmp_len_ + 2, yyscanner); + return NAME_OB; + } else { + RETURN_IGNORED_WORD(); + } +} + YY_BREAK +case 283: +YY_RULE_SETUP +#line 1046 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case 284: +/* rule 284 can match eol */ +YY_RULE_SETUP +#line 1047 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case 285: +/* rule 285 can match eol */ +YY_RULE_SETUP +#line 1048 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case YY_STATE_EOF(sq): +#line 1049 "ob_proxy_parser_gbk.l" +{ return ERROR; } + YY_BREAK +/* comment sq return name_str */ +case 286: +/* rule 286 can match eol */ +YY_RULE_SETUP +#line 1052 "ob_proxy_parser_gbk.l" +{ + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->tmp_len_ += yyleng; + } +} + YY_BREAK +case 287: +YY_RULE_SETUP +#line 1059 "ob_proxy_parser_gbk.l" +{ + POP_STATE(); + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p) && OB_NOTNULL(p->tmp_buf_)) { + store_str(p->tmp_buf_, p->tmp_len_, p->tmp_start_ptr_ + p->tmp_len_ + 2, yyscanner); + return NAME_STR;; + } else { + RETURN_IGNORED_WORD(); + } +} + YY_BREAK +case 288: +YY_RULE_SETUP +#line 1070 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case 289: +/* rule 289 can match eol */ +YY_RULE_SETUP +#line 1071 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case 290: +/* rule 290 can match eol */ +YY_RULE_SETUP +#line 1072 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case YY_STATE_EOF(comment_sq): +#line 1073 "ob_proxy_parser_gbk.l" +{ return ERROR; } + YY_BREAK +/* dquote */ +case 291: +YY_RULE_SETUP +#line 1076 "ob_proxy_parser_gbk.l" +{ + PUSH_STATE(dq); + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->tmp_buf_ = (yytext + 1); + p->tmp_start_ptr_ = yytext; + p->tmp_len_ = 0; + } +} + YY_BREAK +case 292: +/* rule 292 can match eol */ +YY_RULE_SETUP +#line 1086 "ob_proxy_parser_gbk.l" +{ + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p)) { + p->tmp_len_ += yyleng; + } +} + YY_BREAK +case 293: +YY_RULE_SETUP +#line 1093 "ob_proxy_parser_gbk.l" +{ + POP_STATE(); + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (OB_NOTNULL(p) + && OBPROXY_T_INVALID < p->cur_stmt_type_ + && (p->cur_stmt_type_ < OBPROXY_T_ICMD_MAX + || OBPROXY_T_CALL == p->cur_stmt_type_ + || OBPROXY_T_SET == p->cur_stmt_type_ + || OBPROXY_T_SHOW == p->cur_stmt_type_) + && OB_NOTNULL(p->tmp_buf_)) { + store_str_with_quote(OBPROXY_QUOTE_T_DOUBLE, p->tmp_buf_, p->tmp_len_, p->tmp_start_ptr_ + p->tmp_len_ + 2, yyscanner); + return NAME_OB; + } else { + RETURN_IGNORED_WORD(); + } +} + YY_BREAK +case 294: +YY_RULE_SETUP +#line 1110 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case 295: +/* rule 295 can match eol */ +YY_RULE_SETUP +#line 1111 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case 296: +/* rule 296 can match eol */ +YY_RULE_SETUP +#line 1112 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case YY_STATE_EOF(dq): +#line 1113 "ob_proxy_parser_gbk.l" +{ return ERROR; } + YY_BREAK +/* backtick */ +case 297: +YY_RULE_SETUP +#line 1117 "ob_proxy_parser_gbk.l" +{ + PUSH_STATE(bt); + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (NULL != p) { + p->tmp_buf_ = (char *)obproxy_parse_malloc(OBPROXY_MAX_NAME_LENGTH, p->malloc_pool_); + p->tmp_start_ptr_ = yytext; + p->tmp_len_ = 0; + } +} + YY_BREAK +case 298: +YY_RULE_SETUP +#line 1127 "ob_proxy_parser_gbk.l" +{ + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (NULL != p && NULL != p->tmp_buf_ && p->tmp_len_ + 1 < OBPROXY_MAX_NAME_LENGTH) { + p->tmp_buf_[p->tmp_len_++] = '`'; + } +} + YY_BREAK +case 299: +/* rule 299 can match eol */ +YY_RULE_SETUP +#line 1134 "ob_proxy_parser_gbk.l" +{ + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (NULL != p && NULL != p->tmp_buf_ && p->tmp_len_ + yyleng < OBPROXY_MAX_NAME_LENGTH) { + memcpy(p->tmp_buf_ + p->tmp_len_, yytext, yyleng); + p->tmp_len_ += yyleng; + } +} + YY_BREAK +case 300: +YY_RULE_SETUP +#line 1142 "ob_proxy_parser_gbk.l" +{ + POP_STATE(); + ObProxyParseResult *p = (ObProxyParseResult *)yyextra; + if (NULL != p && NULL != p->tmp_buf_) { + yylval->str.str_ = obproxy_parse_strndup(p->tmp_buf_, p->tmp_len_, p->malloc_pool_); + yylval->str.str_len_ = p->tmp_len_; + yylval->str.end_ptr_ = p->tmp_start_ptr_ + p->tmp_len_ + 2; + yylval->str.quote_type_ = OBPROXY_QUOTE_T_BACK; + } + return NAME_OB; +} + YY_BREAK +case YY_STATE_EOF(bt): +#line 1154 "ob_proxy_parser_gbk.l" +{ + return ERROR; +} + YY_BREAK +case 301: +YY_RULE_SETUP +#line 1158 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case 302: +/* rule 302 can match eol */ +YY_RULE_SETUP +#line 1159 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case 303: +YY_RULE_SETUP +#line 1160 "ob_proxy_parser_gbk.l" +{ POP_STATE(); RETURN_IGNORED_WORD(); } + YY_BREAK +case YY_STATE_EOF(bt_in_expr): +#line 1161 "ob_proxy_parser_gbk.l" +{ return ERROR; } + YY_BREAK +/* some useful keyword */ +case 304: +/* rule 304 can match eol */ +YY_RULE_SETUP +#line 1164 "ob_proxy_parser_gbk.l" +{ RETURN_IGNORED_WORD_FOR_DUAL(); } + YY_BREAK +case 305: +YY_RULE_SETUP +#line 1165 "ob_proxy_parser_gbk.l" +{ POP_STATE(); PUSH_STATE(INITIAL); return FROM; } + YY_BREAK +case 306: +YY_RULE_SETUP +#line 1166 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_subquery); return '('; } + YY_BREAK +case 307: +YY_RULE_SETUP +#line 1167 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(dq); } + YY_BREAK +case 308: +YY_RULE_SETUP +#line 1168 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(sq); } + YY_BREAK +case 309: +YY_RULE_SETUP +#line 1169 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(bt_in_expr); } + YY_BREAK +case 310: +YY_RULE_SETUP +#line 1170 "ob_proxy_parser_gbk.l" +{ SET_FOUND_ROWS(); RETURN_IGNORED_WORD(); } + YY_BREAK +case 311: +YY_RULE_SETUP +#line 1171 "ob_proxy_parser_gbk.l" +{ SET_ROW_COUNT(); RETURN_IGNORED_WORD(); } + YY_BREAK +case 312: +YY_RULE_SETUP +#line 1172 "ob_proxy_parser_gbk.l" +{ SET_LAST_INSERT_ID(); RETURN_IGNORED_WORD(); } + YY_BREAK +case 313: +YY_RULE_SETUP +#line 1173 "ob_proxy_parser_gbk.l" +{ SET_GLOBAL_SET_STMT(); RETURN_IGNORED_WORD(); } + YY_BREAK +case 314: +/* rule 314 can match eol */ +YY_RULE_SETUP +#line 1174 "ob_proxy_parser_gbk.l" +{ RETURN_COL_NAME(TX_READ_ONLY); } + YY_BREAK +case 315: +YY_RULE_SETUP +#line 1175 "ob_proxy_parser_gbk.l" +{ RETURN_IGNORED_WORD(); } + YY_BREAK +case YY_STATE_EOF(in_expr): +#line 1176 "ob_proxy_parser_gbk.l" +{ return END_P; } + YY_BREAK +case 316: +/* rule 316 can match eol */ +YY_RULE_SETUP +#line 1177 "ob_proxy_parser_gbk.l" +{ } + YY_BREAK +case 317: +YY_RULE_SETUP +#line 1178 "ob_proxy_parser_gbk.l" +{ POP_STATE(); PUSH_STATE(INITIAL); return yytext[0]; } + YY_BREAK +case 318: +YY_RULE_SETUP +#line 1179 "ob_proxy_parser_gbk.l" +{ RETURN_IGNORED_WORD(); } + YY_BREAK +case 319: +YY_RULE_SETUP +#line 1181 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_expr); return SELECT; } + YY_BREAK +case 320: +YY_RULE_SETUP +#line 1182 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_subquery); return '('; } + YY_BREAK +case 321: +YY_RULE_SETUP +#line 1183 "ob_proxy_parser_gbk.l" +{ POP_STATE(); return ')'; } + YY_BREAK +case 322: +YY_RULE_SETUP +#line 1184 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(dq); } + YY_BREAK +case 323: +YY_RULE_SETUP +#line 1185 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(sq); } + YY_BREAK +case YY_STATE_EOF(in_subquery): +#line 1186 "ob_proxy_parser_gbk.l" +{ return END_P; } + YY_BREAK +case 324: +/* rule 324 can match eol */ +YY_RULE_SETUP +#line 1187 "ob_proxy_parser_gbk.l" +{ } + YY_BREAK +case 325: +YY_RULE_SETUP +#line 1188 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_no_select_query); RETURN_IGNORED_WORD(); } + YY_BREAK +case 326: +YY_RULE_SETUP +#line 1190 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(in_subquery); return '('; } + YY_BREAK +case 327: +YY_RULE_SETUP +#line 1191 "ob_proxy_parser_gbk.l" +{ POP_STATE(); POP_STATE(); return ')'; } + YY_BREAK +case 328: +YY_RULE_SETUP +#line 1192 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(dq); } + YY_BREAK +case 329: +YY_RULE_SETUP +#line 1193 "ob_proxy_parser_gbk.l" +{ PUSH_STATE(sq); } + YY_BREAK +case 330: +YY_RULE_SETUP +#line 1194 "ob_proxy_parser_gbk.l" +{ SET_FOUND_ROWS(); RETURN_IGNORED_WORD(); } + YY_BREAK +case 331: +YY_RULE_SETUP +#line 1195 "ob_proxy_parser_gbk.l" +{ SET_ROW_COUNT(); RETURN_IGNORED_WORD(); } + YY_BREAK +case 332: +YY_RULE_SETUP +#line 1196 "ob_proxy_parser_gbk.l" +{ SET_LAST_INSERT_ID(); RETURN_IGNORED_WORD(); } + YY_BREAK +case 333: +YY_RULE_SETUP +#line 1197 "ob_proxy_parser_gbk.l" +{ RETURN_IGNORED_WORD(); } + YY_BREAK +case YY_STATE_EOF(in_no_select_query): +#line 1198 "ob_proxy_parser_gbk.l" +{ return END_P; } + YY_BREAK +case 334: +/* rule 334 can match eol */ +YY_RULE_SETUP +#line 1199 "ob_proxy_parser_gbk.l" +{ } + YY_BREAK +case 335: +YY_RULE_SETUP +#line 1200 "ob_proxy_parser_gbk.l" +{ RETURN_IGNORED_WORD(); } + YY_BREAK +case 336: +YY_RULE_SETUP +#line 1202 "ob_proxy_parser_gbk.l" +{ return FROM; } + YY_BREAK +case 337: +YY_RULE_SETUP +#line 1203 "ob_proxy_parser_gbk.l" +{ return yytext[0]; } + YY_BREAK +case 338: +YY_RULE_SETUP +#line 1204 "ob_proxy_parser_gbk.l" +{ RETURN_NON_RESERVED_KEYWORD(NAME_OB); } + YY_BREAK +case 339: +YY_RULE_SETUP +#line 1205 "ob_proxy_parser_gbk.l" +{ POP_STATE(); } + YY_BREAK +case 340: +YY_RULE_SETUP +#line 1206 "ob_proxy_parser_gbk.l" +{ POP_STATE(); } + YY_BREAK +case 341: +YY_RULE_SETUP +#line 1208 "ob_proxy_parser_gbk.l" +{ POP_STATE(); RETURN_NON_RESERVED_KEYWORD(BEGI);} + YY_BREAK +case 342: +YY_RULE_SETUP +#line 1209 "ob_proxy_parser_gbk.l" +{} + YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(hint): +case YY_STATE_EOF(in_c_comment): +case YY_STATE_EOF(in_comment_expr): +case YY_STATE_EOF(in_old_comment_expr): +case YY_STATE_EOF(in_odp_comment_expr): +case YY_STATE_EOF(in_odp_comment_value_expr): +case YY_STATE_EOF(in_odp_comment_value_expr_calc): +case YY_STATE_EOF(in_ignored_comment_expr): +case YY_STATE_EOF(in_dbp_comment_expr): +case YY_STATE_EOF(in_dbp_comment_trace_expr): +case YY_STATE_EOF(in_dbp_comment_trace_value_expr): +case YY_STATE_EOF(in_dbp_comment_trace_value_expr_calc): +case YY_STATE_EOF(in_anonymous_block): +case YY_STATE_EOF(prepare): +case YY_STATE_EOF(insert_all_expr): +case YY_STATE_EOF(show_topology): +case YY_STATE_EOF(proxy_icmd_state): +#line 1211 "ob_proxy_parser_gbk.l" +{ return END_P; } + YY_BREAK +case 343: +YY_RULE_SETUP +#line 1212 "ob_proxy_parser_gbk.l" +{ RETURN_IGNORED_WORD(); } + YY_BREAK +case 344: +YY_RULE_SETUP +#line 1213 "ob_proxy_parser_gbk.l" +ECHO; + YY_BREAK +#line 7643 "ob_proxy_parser_gbk_lex.c" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yyg->yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * ob_proxy_parser_gbk_yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); + + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yyg->yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yyg->yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_END_OF_FILE: + { + yyg->yy_did_buffer_switch_on_eof = 0; + + if ( ob_proxy_parser_gbk_yywrap(yyscanner ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = + yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yyg->yy_c_buf_p = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of ob_proxy_parser_gbk_yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = yyg->yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) (yyg->yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + ob_proxy_parser_gbk_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + yyg->yy_n_chars, (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + if ( yyg->yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + ob_proxy_parser_gbk_yyrestart(yyin ,yyscanner); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) ob_proxy_parser_gbk_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + yyg->yy_n_chars += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (yyscan_t yyscanner) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_current_state = yyg->yy_start; + + for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 2515 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) +{ + register int yy_is_jam; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ + register char *yy_cp = yyg->yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 2515 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 2514); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (yyscan_t yyscanner) +#else + static int input (yyscan_t yyscanner) +#endif + +{ + int c; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + *yyg->yy_c_buf_p = yyg->yy_hold_char; + + if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + /* This was really a NUL. */ + *yyg->yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yyg->yy_c_buf_p - yyg->yytext_ptr; + ++yyg->yy_c_buf_p; + + switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + ob_proxy_parser_gbk_yyrestart(yyin ,yyscanner); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( ob_proxy_parser_gbk_yywrap(yyscanner ) ) + return EOF; + + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(yyscanner); +#else + return input(yyscanner); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = yyg->yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ + *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ + yyg->yy_hold_char = *++yyg->yy_c_buf_p; + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * @param yyscanner The scanner object. + * @note This function does not reset the start condition to @c INITIAL . + */ + void ob_proxy_parser_gbk_yyrestart (FILE * input_file , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! YY_CURRENT_BUFFER ){ + ob_proxy_parser_gbk_yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + ob_proxy_parser_gbk_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + } + + ob_proxy_parser_gbk_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); + ob_proxy_parser_gbk_yy_load_buffer_state(yyscanner ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * @param yyscanner The scanner object. + */ + void ob_proxy_parser_gbk_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* TODO. We should be able to replace this entire function body + * with + * ob_proxy_parser_gbk_yypop_buffer_state(); + * ob_proxy_parser_gbk_yypush_buffer_state(new_buffer); + */ + ob_proxy_parser_gbk_yyensure_buffer_stack (yyscanner); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + ob_proxy_parser_gbk_yy_load_buffer_state(yyscanner ); + + /* We don't actually know whether we did this switch during + * EOF (ob_proxy_parser_gbk_yywrap()) processing, but the only time this flag + * is looked at is after ob_proxy_parser_gbk_yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yyg->yy_did_buffer_switch_on_eof = 1; +} + +static void ob_proxy_parser_gbk_yy_load_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + yyg->yy_hold_char = *yyg->yy_c_buf_p; +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * @param yyscanner The scanner object. + * @return the allocated buffer state. + */ + YY_BUFFER_STATE ob_proxy_parser_gbk_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) ob_proxy_parser_gbk_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in ob_proxy_parser_gbk_yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) ob_proxy_parser_gbk_yyalloc(b->yy_buf_size + 2 ,yyscanner ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in ob_proxy_parser_gbk_yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + ob_proxy_parser_gbk_yy_init_buffer(b,file ,yyscanner); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with ob_proxy_parser_gbk_yy_create_buffer() + * @param yyscanner The scanner object. + */ + void ob_proxy_parser_gbk_yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + ob_proxy_parser_gbk_yyfree((void *) b->yy_ch_buf ,yyscanner ); + + ob_proxy_parser_gbk_yyfree((void *) b ,yyscanner ); +} + +#ifndef __cplusplus +extern int isatty (int ); +#endif /* __cplusplus */ + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a ob_proxy_parser_gbk_yyrestart() or at EOF. + */ + static void ob_proxy_parser_gbk_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) + +{ + int oerrno = errno; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + ob_proxy_parser_gbk_yy_flush_buffer(b ,yyscanner); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then ob_proxy_parser_gbk_yy_init_buffer was _probably_ + * called from ob_proxy_parser_gbk_yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * @param yyscanner The scanner object. + */ + void ob_proxy_parser_gbk_yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + ob_proxy_parser_gbk_yy_load_buffer_state(yyscanner ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * @param yyscanner The scanner object. + */ +void ob_proxy_parser_gbk_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (new_buffer == NULL) + return; + + ob_proxy_parser_gbk_yyensure_buffer_stack(yyscanner); + + /* This block is copied from ob_proxy_parser_gbk_yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + yyg->yy_buffer_stack_top++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from ob_proxy_parser_gbk_yy_switch_to_buffer. */ + ob_proxy_parser_gbk_yy_load_buffer_state(yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * @param yyscanner The scanner object. + */ +void ob_proxy_parser_gbk_yypop_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (!YY_CURRENT_BUFFER) + return; + + ob_proxy_parser_gbk_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner); + YY_CURRENT_BUFFER_LVALUE = NULL; + if (yyg->yy_buffer_stack_top > 0) + --yyg->yy_buffer_stack_top; + + if (YY_CURRENT_BUFFER) { + ob_proxy_parser_gbk_yy_load_buffer_state(yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void ob_proxy_parser_gbk_yyensure_buffer_stack (yyscan_t yyscanner) +{ + int num_to_alloc; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (!yyg->yy_buffer_stack) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + yyg->yy_buffer_stack = (struct yy_buffer_state**)ob_proxy_parser_gbk_yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in ob_proxy_parser_gbk_yyensure_buffer_stack()" ); + + memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + yyg->yy_buffer_stack_max = num_to_alloc; + yyg->yy_buffer_stack_top = 0; + return; + } + + if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = yyg->yy_buffer_stack_max + grow_size; + yyg->yy_buffer_stack = (struct yy_buffer_state**)ob_proxy_parser_gbk_yyrealloc + (yyg->yy_buffer_stack, + num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in ob_proxy_parser_gbk_yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); + yyg->yy_buffer_stack_max = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE ob_proxy_parser_gbk_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) ob_proxy_parser_gbk_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in ob_proxy_parser_gbk_yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + ob_proxy_parser_gbk_yy_switch_to_buffer(b ,yyscanner ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to ob_proxy_parser_gbk_yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * ob_proxy_parser_gbk_yy_scan_bytes() instead. + */ +YY_BUFFER_STATE ob_proxy_parser_gbk_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner) +{ + + return ob_proxy_parser_gbk_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner); +} + +/** Setup the input buffer state to scan the given bytes. The next call to ob_proxy_parser_gbk_yylex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE ob_proxy_parser_gbk_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) ob_proxy_parser_gbk_yyalloc(n ,yyscanner ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in ob_proxy_parser_gbk_yy_scan_bytes()" ); + + memcpy(buf, yybytes, _yybytes_len); + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = ob_proxy_parser_gbk_yy_scan_buffer(buf,n ,yyscanner); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in ob_proxy_parser_gbk_yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + + static void yy_push_state (int new_state , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( yyg->yy_start_stack_ptr >= yyg->yy_start_stack_depth ) + { + yy_size_t new_size; + + yyg->yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yyg->yy_start_stack_depth * sizeof( int ); + + if ( ! yyg->yy_start_stack ) + yyg->yy_start_stack = (int *) ob_proxy_parser_gbk_yyalloc(new_size ,yyscanner ); + + else + yyg->yy_start_stack = (int *) ob_proxy_parser_gbk_yyrealloc((void *) yyg->yy_start_stack,new_size ,yyscanner ); + + if ( ! yyg->yy_start_stack ) + YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); + } + + yyg->yy_start_stack[yyg->yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); +} + + static void yy_pop_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( --yyg->yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yyg->yy_start_stack[yyg->yy_start_stack_ptr]); +} + + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = yyg->yy_hold_char; \ + yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ + yyg->yy_hold_char = *yyg->yy_c_buf_p; \ + *yyg->yy_c_buf_p = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the user-defined data for this scanner. + * @param yyscanner The scanner object. + */ +YY_EXTRA_TYPE ob_proxy_parser_gbk_yyget_extra (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyextra; +} + +/** Get the current line number. + * @param yyscanner The scanner object. + */ +int ob_proxy_parser_gbk_yyget_lineno (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yylineno; +} + +/** Get the current column number. + * @param yyscanner The scanner object. + */ +int ob_proxy_parser_gbk_yyget_column (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yycolumn; +} + +/** Get the input stream. + * @param yyscanner The scanner object. + */ +FILE *ob_proxy_parser_gbk_yyget_in (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyin; +} + +/** Get the output stream. + * @param yyscanner The scanner object. + */ +FILE *ob_proxy_parser_gbk_yyget_out (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyout; +} + +/** Get the length of the current token. + * @param yyscanner The scanner object. + */ +int ob_proxy_parser_gbk_yyget_leng (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyleng; +} + +/** Get the current token. + * @param yyscanner The scanner object. + */ + +char *ob_proxy_parser_gbk_yyget_text (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yytext; +} + +/** Set the user-defined data. This data is never touched by the scanner. + * @param user_defined The data to be associated with this scanner. + * @param yyscanner The scanner object. + */ +void ob_proxy_parser_gbk_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyextra = user_defined ; +} + +/** Set the current line number. + * @param line_number + * @param yyscanner The scanner object. + */ +void ob_proxy_parser_gbk_yyset_lineno (int line_number , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* lineno is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + yy_fatal_error( "ob_proxy_parser_gbk_yyset_lineno called with no buffer" , yyscanner); + + yylineno = line_number; +} + +/** Set the current column. + * @param line_number + * @param yyscanner The scanner object. + */ +void ob_proxy_parser_gbk_yyset_column (int column_no , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* column is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + yy_fatal_error( "ob_proxy_parser_gbk_yyset_column called with no buffer" , yyscanner); + + yycolumn = column_no; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * @param yyscanner The scanner object. + * @see ob_proxy_parser_gbk_yy_switch_to_buffer + */ +void ob_proxy_parser_gbk_yyset_in (FILE * in_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyin = in_str ; +} + +void ob_proxy_parser_gbk_yyset_out (FILE * out_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyout = out_str ; +} + +int ob_proxy_parser_gbk_yyget_debug (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yy_flex_debug; +} + +void ob_proxy_parser_gbk_yyset_debug (int bdebug , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yy_flex_debug = bdebug ; +} + +/* Accessor methods for yylval and yylloc */ + +YYSTYPE * ob_proxy_parser_gbk_yyget_lval (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yylval; +} + +void ob_proxy_parser_gbk_yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yylval = yylval_param; +} + +YYLTYPE *ob_proxy_parser_gbk_yyget_lloc (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yylloc; +} + +void ob_proxy_parser_gbk_yyset_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yylloc = yylloc_param; +} + +/* User-visible API */ + +/* ob_proxy_parser_gbk_yylex_init is special because it creates the scanner itself, so it is + * the ONLY reentrant function that doesn't take the scanner as the last argument. + * That's why we explicitly handle the declaration, instead of using our macros. + */ + +int ob_proxy_parser_gbk_yylex_init(yyscan_t* ptr_yy_globals) + +{ + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) ob_proxy_parser_gbk_yyalloc ( sizeof( struct yyguts_t ), NULL ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + return yy_init_globals ( *ptr_yy_globals ); +} + +/* ob_proxy_parser_gbk_yylex_init_extra has the same functionality as ob_proxy_parser_gbk_yylex_init, but follows the + * convention of taking the scanner as the last argument. Note however, that + * this is a *pointer* to a scanner, as it will be allocated by this call (and + * is the reason, too, why this function also must handle its own declaration). + * The user defined value in the first argument will be available to ob_proxy_parser_gbk_yyalloc in + * the yyextra field. + */ + +int ob_proxy_parser_gbk_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) + +{ + struct yyguts_t dummy_yyguts; + + ob_proxy_parser_gbk_yyset_extra (yy_user_defined, &dummy_yyguts); + + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) ob_proxy_parser_gbk_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in + yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + ob_proxy_parser_gbk_yyset_extra (yy_user_defined, *ptr_yy_globals); + + return yy_init_globals ( *ptr_yy_globals ); +} + +static int yy_init_globals (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from ob_proxy_parser_gbk_yylex_destroy(), so don't allocate here. + */ + + yyg->yy_buffer_stack = 0; + yyg->yy_buffer_stack_top = 0; + yyg->yy_buffer_stack_max = 0; + yyg->yy_c_buf_p = (char *) 0; + yyg->yy_init = 0; + yyg->yy_start = 0; + + yyg->yy_start_stack_ptr = 0; + yyg->yy_start_stack_depth = 0; + yyg->yy_start_stack = NULL; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * ob_proxy_parser_gbk_yylex_init() + */ + return 0; +} + +/* ob_proxy_parser_gbk_yylex_destroy is for both reentrant and non-reentrant scanners. */ +int ob_proxy_parser_gbk_yylex_destroy (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + ob_proxy_parser_gbk_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); + YY_CURRENT_BUFFER_LVALUE = NULL; + ob_proxy_parser_gbk_yypop_buffer_state(yyscanner); + } + + /* Destroy the stack itself. */ + ob_proxy_parser_gbk_yyfree(yyg->yy_buffer_stack ,yyscanner); + yyg->yy_buffer_stack = NULL; + + /* Destroy the start condition stack. */ + ob_proxy_parser_gbk_yyfree(yyg->yy_start_stack ,yyscanner ); + yyg->yy_start_stack = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * ob_proxy_parser_gbk_yylex() is called, initialization will occur. */ + yy_init_globals( yyscanner); + + /* Destroy the main struct (reentrant only). */ + ob_proxy_parser_gbk_yyfree ( yyscanner , yyscanner ); + yyscanner = NULL; + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +#define YYTABLES_NAME "yytables" + +#line 1213 "ob_proxy_parser_gbk.l" + + +inline void *ob_proxy_parser_gbk_yyalloc(size_t bytes,void *yyscanner) +{ + void *ptr_ret = NULL; + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner); + if (OB_ISNULL(p)) { + // print err into msg buffer later + } else { + ptr_ret = obproxy_parse_malloc(bytes, p->malloc_pool_); + } + return ptr_ret; +} + +inline void *ob_proxy_parser_gbk_yyrealloc (void *ptr, size_t bytes, void *yyscanner) +{ + void *ptr_ret = NULL; + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner); + if (OB_ISNULL(p)) { + // print err into msg buffer later + } else { + ptr_ret = obproxy_parse_realloc(ptr, bytes, p->malloc_pool_); + } + return ptr_ret; + +} + +inline void ob_proxy_parser_gbk_yyfree(void *ptr,void *yyscanner) +{ + // Do nothing -- we leave it to the garbage collector. + obproxy_parse_free(ptr); +} + +inline void update_stmt_type(ObProxyBasicStmtType type, void *yyscanner) +{ + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner); + if (OB_ISNULL(p)) { + // print err into msg buffer later + } else { + // we only update the cur_stmt_type_ at the first time + if (OBPROXY_T_INVALID == p->cur_stmt_type_) { + p->cur_stmt_type_ = type; + } else { + // do nothing + } + } +} + +inline void store_str(char* str, int64_t str_len, char* end_ptr, void *yyscanner) +{ + YYSTYPE *lval = ob_proxy_parser_gbk_yyget_lval(yyscanner); + if (OB_ISNULL(lval)) { + // do nothing + } else { + lval->str.str_ = str; + lval->str.end_ptr_ = end_ptr; + lval->str.str_len_ = str_len; + lval->str.quote_type_ = OBPROXY_QUOTE_T_INVALID; + } +} + +inline void store_str_with_quote(ObProxyParseQuoteType type, char* str, int64_t str_len, char* end_ptr, void *yyscanner) +{ + YYSTYPE *lval = ob_proxy_parser_gbk_yyget_lval(yyscanner); + if (OB_ISNULL(lval)) { + // do nothing + } else { + lval->str.str_ = str; + lval->str.end_ptr_ = end_ptr; + lval->str.str_len_ = str_len; + lval->str.quote_type_ = type; + } +} + +/* A Bison parser, made by GNU Bison 2.4.1. */ + +/* Skeleton interface for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + + +#ifndef YY_OBPROXY_OB_PROXY_PARSER_TAB_H_INCLUDED +# define YY_OBPROXY_OB_PROXY_PARSER_TAB_H_INCLUDED +/* Debug traces. */ +#ifndef OBPROXY_GBK_DEBUG +# if defined YYDEBUG +#if YYDEBUG +# define OBPROXY_GBK_DEBUG 1 +# else +# define OBPROXY_GBK_DEBUG 0 +# endif +# else /* ! defined YYDEBUG */ +# define OBPROXY_GBK_DEBUG 0 +# endif /* ! defined YYDEBUG */ +#endif /* ! defined OBPROXY_GBK_DEBUG */ +#if OBPROXY_GBK_DEBUG +extern int ob_proxy_parser_gbk_yydebug; +#endif +/* Tokens. */ +#ifndef OBPROXYTOKENTYPE +# define OBPROXYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum obproxytokentype { + DUMMY_WHERE_CLAUSE = 258, + DUMMY_INSERT_CLAUSE = 259, + SELECT = 260, + DELETE = 261, + INSERT = 262, + UPDATE = 263, + REPLACE = 264, + MERGE = 265, + SHOW = 266, + SET = 267, + CALL = 268, + CREATE = 269, + DROP = 270, + ALTER = 271, + TRUNCATE = 272, + RENAME = 273, + TABLE = 274, + STATUS = 275, + UNIQUE = 276, + GRANT = 277, + REVOKE = 278, + ANALYZE = 279, + PURGE = 280, + COMMENT = 281, + FROM = 282, + DUAL = 283, + PREPARE = 284, + EXECUTE = 285, + USING = 286, + DEALLOCATE = 287, + SELECT_HINT_BEGIN = 288, + UPDATE_HINT_BEGIN = 289, + DELETE_HINT_BEGIN = 290, + INSERT_HINT_BEGIN = 291, + REPLACE_HINT_BEGIN = 292, + MERGE_HINT_BEGIN = 293, + HINT_END = 294, + COMMENT_BEGIN = 295, + COMMENT_END = 296, + ROUTE_TABLE = 297, + ROUTE_PART_KEY = 298, + QUERY_TIMEOUT = 299, + READ_CONSISTENCY = 300, + WEAK = 301, + STRONG = 302, + FROZEN = 303, + PLACE_HOLDER = 304, + END_P = 305, + ERROR = 306, + WHEN = 307, + FLASHBACK = 308, + AUDIT = 309, + NOAUDIT = 310, + BEGI = 311, + START = 312, + TRANSACTION = 313, + READ = 314, + ONLY = 315, + WITH = 316, + CONSISTENT = 317, + SNAPSHOT = 318, + INDEX = 319, + XA = 320, + WARNINGS = 321, + ERRORS = 322, + TRACE = 323, + QUICK = 324, + COUNT = 325, + AS = 326, + WHERE = 327, + VALUES = 328, + ORDER = 329, + GROUP = 330, + HAVING = 331, + INTO = 332, + UNION = 333, + FOR = 334, + TX_READ_ONLY = 335, + SELECT_OBPROXY_ROUTE_ADDR = 336, + SET_OBPROXY_ROUTE_ADDR = 337, + NAME_OB_DOT = 338, + NAME_OB = 339, + EXPLAIN = 340, + DESC = 341, + DESCRIBE = 342, + NAME_STR = 343, + USE = 344, + HELP = 345, + SET_NAMES = 346, + SET_CHARSET = 347, + SET_PASSWORD = 348, + SET_DEFAULT = 349, + SET_OB_READ_CONSISTENCY = 350, + SET_TX_READ_ONLY = 351, + GLOBAL = 352, + SESSION = 353, + NUMBER_VAL = 354, + GROUP_ID = 355, + TABLE_ID = 356, + ELASTIC_ID = 357, + TESTLOAD = 358, + ODP_COMMENT = 359, + TNT_ID = 360, + DISASTER_STATUS = 361, + TRACE_ID = 362, + RPC_ID = 363, + TARGET_DB_SERVER = 364, + DBP_COMMENT = 365, + ROUTE_TAG = 366, + SYS_TAG = 367, + TABLE_NAME = 368, + SCAN_ALL = 369, + STICKY_SESSION = 370, + PARALL = 371, + SHARD_KEY = 372, + INT_NUM = 373, + SHOW_PROXYNET = 374, + THREAD = 375, + CONNECTION = 376, + LIMIT = 377, + OFFSET = 378, + SHOW_PROCESSLIST = 379, + SHOW_PROXYSESSION = 380, + SHOW_GLOBALSESSION = 381, + ATTRIBUTE = 382, + VARIABLES = 383, + ALL = 384, + STAT = 385, + SHOW_PROXYCONFIG = 386, + DIFF = 387, + USER = 388, + LIKE = 389, + SHOW_PROXYSM = 390, + SHOW_PROXYCLUSTER = 391, + SHOW_PROXYRESOURCE = 392, + SHOW_PROXYCONGESTION = 393, + SHOW_PROXYROUTE = 394, + PARTITION = 395, + ROUTINE = 396, + SHOW_PROXYVIP = 397, + SHOW_PROXYMEMORY = 398, + OBJPOOL = 399, + SHOW_SQLAUDIT = 400, + SHOW_WARNLOG = 401, + SHOW_PROXYSTAT = 402, + REFRESH = 403, + SHOW_PROXYTRACE = 404, + SHOW_PROXYINFO = 405, + BINARY = 406, + UPGRADE = 407, + IDC = 408, + SHOW_ELASTIC_ID = 409, + SHOW_TOPOLOGY = 410, + GROUP_NAME = 411, + SHOW_DB_VERSION = 412, + SHOW_DATABASES = 413, + SHOW_TABLES = 414, + SHOW_FULL_TABLES = 415, + SELECT_DATABASE = 416, + SHOW_CREATE_TABLE = 417, + SELECT_PROXY_VERSION = 418, + SHOW_COLUMNS = 419, + SHOW_INDEX = 420, + ALTER_PROXYCONFIG = 421, + ALTER_PROXYRESOURCE = 422, + PING_PROXY = 423, + KILL_PROXYSESSION = 424, + KILL_GLOBALSESSION = 425, + KILL = 426, + QUERY = 427, + SHOW_MASTER_STATUS = 428, + SHOW_BINARY_LOGS = 429, + SHOW_BINLOG_EVENTS = 430, + PURGE_BINARY_LOGS = 431, + RESET_MASTER = 432, + SHOW_BINLOG_SERVER_FOR_TENANT = 433 + }; +#endif + + + +#if ! defined OBPROXYSTYPE && ! defined OBPROXYSTYPE_IS_DECLARED +typedef union OBPROXYSTYPE +{ + + + int64_t num; + ObProxyParseString str; + ObProxyCallParseNode *node; + ObShardColumnNode *shard_node; + ObProxySetVarNode *var_node; + + + +} OBPROXYSTYPE; +# define OBPROXYSTYPE_IS_TRIVIAL 1 +# define obproxystype OBPROXYSTYPE /* obsolescent; will be withdrawn */ +# define OBPROXYSTYPE_IS_DECLARED 1 +#endif + + + +#if ! defined OBPROXYLTYPE && ! defined OBPROXYLTYPE_IS_DECLARED +typedef struct OBPROXYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} OBPROXYLTYPE; +# define obproxyltype OBPROXYLTYPE /* obsolescent; will be withdrawn */ +# define OBPROXYLTYPE_IS_DECLARED 1 +# define OBPROXYLTYPE_IS_TRIVIAL 1 +#endif + + + +#endif + diff --git a/src/obproxy/opsql/parser/ob_proxy_parser_gbk_lex.h b/src/obproxy/opsql/parser/ob_proxy_parser_gbk_lex.h new file mode 100644 index 0000000000000000000000000000000000000000..2f58de10a2aafa49ddc468fe77da96a792a8d320 --- /dev/null +++ b/src/obproxy/opsql/parser/ob_proxy_parser_gbk_lex.h @@ -0,0 +1,373 @@ +#ifndef ob_proxy_parser_gbk_yyHEADER_H +#define ob_proxy_parser_gbk_yyHEADER_H 1 +#define ob_proxy_parser_gbk_yyIN_HEADER 1 + +#line 6 "ob_proxy_parser_gbk_lex.h" + +#line 8 "ob_proxy_parser_gbk_lex.h" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +void ob_proxy_parser_gbk_yyrestart (FILE *input_file ,yyscan_t yyscanner ); +void ob_proxy_parser_gbk_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +YY_BUFFER_STATE ob_proxy_parser_gbk_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); +void ob_proxy_parser_gbk_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void ob_proxy_parser_gbk_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void ob_proxy_parser_gbk_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +void ob_proxy_parser_gbk_yypop_buffer_state (yyscan_t yyscanner ); + +YY_BUFFER_STATE ob_proxy_parser_gbk_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); +YY_BUFFER_STATE ob_proxy_parser_gbk_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +YY_BUFFER_STATE ob_proxy_parser_gbk_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); + +void *ob_proxy_parser_gbk_yyalloc (yy_size_t ,yyscan_t yyscanner ); +void *ob_proxy_parser_gbk_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); +void ob_proxy_parser_gbk_yyfree (void * ,yyscan_t yyscanner ); + +/* Begin user sect3 */ + +#define ob_proxy_parser_gbk_yywrap(n) 1 +#define YY_SKIP_YYWRAP + +#define yytext_ptr yytext_r + +#ifdef YY_HEADER_EXPORT_START_CONDITIONS +#define INITIAL 0 +#define hint 1 +#define in_c_comment 2 +#define in_comment_expr 3 +#define in_old_comment_expr 4 +#define in_odp_comment_expr 5 +#define in_odp_comment_value_expr 6 +#define in_odp_comment_value_expr_calc 7 +#define in_ignored_comment_expr 8 +#define in_dbp_comment_expr 9 +#define in_dbp_comment_trace_expr 10 +#define in_dbp_comment_trace_value_expr 11 +#define in_dbp_comment_trace_value_expr_calc 12 +#define comment_sq 13 +#define sq 14 +#define dq 15 +#define bt 16 +#define bt_in_expr 17 +#define in_expr 18 +#define in_anonymous_block 19 +#define in_subquery 20 +#define in_no_select_query 21 +#define prepare 22 +#define insert_all_expr 23 +#define set_expr 24 +#define show_elastic_id 25 +#define show_topology 26 +#define show_tables 27 +#define proxy_icmd_state 28 + +#endif + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +int ob_proxy_parser_gbk_yylex_init (yyscan_t* scanner); + +int ob_proxy_parser_gbk_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int ob_proxy_parser_gbk_yylex_destroy (yyscan_t yyscanner ); + +int ob_proxy_parser_gbk_yyget_debug (yyscan_t yyscanner ); + +void ob_proxy_parser_gbk_yyset_debug (int debug_flag ,yyscan_t yyscanner ); + +YY_EXTRA_TYPE ob_proxy_parser_gbk_yyget_extra (yyscan_t yyscanner ); + +void ob_proxy_parser_gbk_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); + +FILE *ob_proxy_parser_gbk_yyget_in (yyscan_t yyscanner ); + +void ob_proxy_parser_gbk_yyset_in (FILE * in_str ,yyscan_t yyscanner ); + +FILE *ob_proxy_parser_gbk_yyget_out (yyscan_t yyscanner ); + +void ob_proxy_parser_gbk_yyset_out (FILE * out_str ,yyscan_t yyscanner ); + +int ob_proxy_parser_gbk_yyget_leng (yyscan_t yyscanner ); + +char *ob_proxy_parser_gbk_yyget_text (yyscan_t yyscanner ); + +int ob_proxy_parser_gbk_yyget_lineno (yyscan_t yyscanner ); + +void ob_proxy_parser_gbk_yyset_lineno (int line_number ,yyscan_t yyscanner ); + +OBPROXYSTYPE * ob_proxy_parser_gbk_yyget_lval (yyscan_t yyscanner ); + +void ob_proxy_parser_gbk_yyset_lval (OBPROXYSTYPE * yylval_param ,yyscan_t yyscanner ); + + OBPROXYLTYPE *ob_proxy_parser_gbk_yyget_lloc (yyscan_t yyscanner ); + + void ob_proxy_parser_gbk_yyset_lloc (OBPROXYLTYPE * yylloc_param ,yyscan_t yyscanner ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int ob_proxy_parser_gbk_yywrap (yyscan_t yyscanner ); +#else +extern int ob_proxy_parser_gbk_yywrap (yyscan_t yyscanner ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int ob_proxy_parser_gbk_yylex \ + (OBPROXYSTYPE * yylval_param,OBPROXYLTYPE * yylloc_param ,yyscan_t yyscanner); + +#define YY_DECL int ob_proxy_parser_gbk_yylex \ + (OBPROXYSTYPE * yylval_param, OBPROXYLTYPE * yylloc_param , yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +#undef YY_NEW_FILE +#undef YY_FLUSH_BUFFER +#undef yy_set_bol +#undef yy_new_buffer +#undef yy_set_interactive +#undef YY_DO_BEFORE_ACTION + +#ifdef YY_DECL_IS_OURS +#undef YY_DECL_IS_OURS +#undef YY_DECL +#endif + +#line 1213 "ob_proxy_parser_gbk.l" + + +#line 372 "ob_proxy_parser_gbk_lex.h" +#undef ob_proxy_parser_gbk_yyIN_HEADER +#endif /* ob_proxy_parser_gbk_yyHEADER_H */ diff --git a/src/obproxy/opsql/parser/ob_proxy_parser_gbk_tab.c b/src/obproxy/opsql/parser/ob_proxy_parser_gbk_tab.c new file mode 100644 index 0000000000000000000000000000000000000000..4dec0fda43c4b654581edad925172c2870022515 --- /dev/null +++ b/src/obproxy/opsql/parser/ob_proxy_parser_gbk_tab.c @@ -0,0 +1,4642 @@ + +/* A Bison parser, made by GNU Bison 2.4.1. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.4.1" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 1 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + +/* Using locations. */ +#define YYLSP_NEEDED 1 + +/* Substitute the variable and function names. */ +#define YYSTYPE OBPROXYSTYPE +#define YYLTYPE OBPROXYLTYPE +#define yyparse ob_proxy_parser_gbk_yyparse +#define yylex ob_proxy_parser_gbk_yylex +#define yyerror ob_proxy_parser_gbk_yyerror +#define yylval ob_proxy_parser_gbk_yylval +#define yychar ob_proxy_parser_gbk_yychar +#define yydebug ob_proxy_parser_gbk_yydebug +#define yynerrs ob_proxy_parser_gbk_yynerrs +#define yylloc ob_proxy_parser_gbk_yylloc + +/* Copy the first part of user declarations. */ + + +#include +#include "opsql/ob_proxy_parse_define.h" +#include "opsql/parser/ob_proxy_parse_result.h" + +#define HANDLE_ACCEPT() \ +do {\ + if (result->stmt_count_ > 1) {\ + result->stmt_type_ = OBPROXY_T_MULTI_STMT;\ + }\ + if (NULL != result->end_pos_) {\ + } else if (NULL != result->table_info_.table_name_.str_ && result->table_info_.table_name_.str_len_ > 0) {\ + if (NULL != result->part_name_.str_ && result->part_name_.str_len_ > 0) {\ + result->end_pos_ = result->part_name_.end_ptr_;\ + } else if (NULL != result->table_info_.alias_name_.str_ && result->table_info_.alias_name_.str_len_ > 0) {\ + result->end_pos_ = result->table_info_.alias_name_.end_ptr_;\ + } else {\ + result->end_pos_ = result->table_info_.table_name_.end_ptr_;\ + }\ + } else {\ + result->end_pos_ = ob_proxy_parser_gbk_yyget_text(result->yyscan_info_);\ + }\ + YYACCEPT;\ +} while (0); + +static inline void handle_stmt_end(ObProxyParseResult* result) +{ + // no need to judge NULL + if (result->has_ignored_word_) { + switch (result->cur_stmt_type_) { + // these stmt should match exactly, + // so if we have ignored word we should reset type + case OBPROXY_T_SELECT_TX_RO: + result->stmt_type_ = OBPROXY_T_SELECT; + break; + case OBPROXY_T_BEGIN: + result->stmt_type_ = OBPROXY_T_OTHERS; + break; + case OBPROXY_T_SHOW_TRACE: + result->stmt_type_ = OBPROXY_T_OTHERS; + break; + case OBPROXY_T_SELECT_ROUTE_ADDR: + result->stmt_type_ = OBPROXY_T_OTHERS; + break; + case OBPROXY_T_SET_ROUTE_ADDR: + result->stmt_type_ = OBPROXY_T_OTHERS; + break; + default: + result->stmt_type_ = result->cur_stmt_type_; + break; + } + } else { + result->stmt_type_ = result->cur_stmt_type_; + } + + if (OBPROXY_T_TEXT_PS_PREPARE == result->text_ps_inner_stmt_type_) { + ObProxyBasicStmtType tmp_type = result->cur_stmt_type_; + result->stmt_type_ = OBPROXY_T_TEXT_PS_PREPARE; + result->text_ps_inner_stmt_type_ = tmp_type; + } + + result->cur_stmt_type_ = OBPROXY_T_INVALID; + result->stmt_count_++; +} + +#define UPDATE_ALIAS_NAME(name) \ + /* only support select and update with alias name */ \ + /* insert into ... select also have alias name */ \ + if (NULL != result && (OBPROXY_T_SELECT == result->cur_stmt_type_ || OBPROXY_T_UPDATE == result->cur_stmt_type_ \ + || OBPROXY_T_INSERT == result->cur_stmt_type_ || OBPROXY_T_MERGE == result->cur_stmt_type_)) { \ + result->table_info_.alias_name_ = name; \ + } \ + +#define HANDLE_ERROR_ACCEPT() \ +do {\ + result->has_ignored_word_ = true;\ + if ((OBPROXY_T_INVALID < result->cur_stmt_type_ && result->cur_stmt_type_ < OBPROXY_T_ICMD_MAX) || (OBPROXY_T_PING_PROXY == result->cur_stmt_type_)) {\ + result->cmd_info_.err_type_ = OBPROXY_T_ERR_PARSE;\ + }\ + handle_stmt_end(result);\ + HANDLE_ACCEPT();\ +} while (0); + +#define SET_ICMD_SUB_TYPE(sub_type) \ +do {\ + result->cmd_info_.sub_type_ = sub_type;\ +} while (0); + +#define SET_ICMD_SUB_AND_ONE_ID(sub_type, id) \ +do {\ + result->cmd_info_.sub_type_ = sub_type;\ + result->cmd_info_.integer_[0] = id;\ +} while (0); + +#define SET_ICMD_SUB_AND_TWO_ID(sub_type, id, id_two) \ +do {\ + result->cmd_info_.sub_type_ = sub_type;\ + result->cmd_info_.integer_[0] = id;\ + result->cmd_info_.integer_[1] = id_two;\ +} while (0); + +#define SET_ICMD_SUB_AND_ONE_STRING(sub_type, string) \ +do {\ + result->cmd_info_.sub_type_ = sub_type;\ + result->cmd_info_.string_[0] = string;\ +} while (0); + +#define SET_ICMD_ONE_STRING(string) \ +do {\ + result->cmd_info_.string_[0] = string;\ +} while (0); + +#define SET_ICMD_TWO_STRING(string, string_two) \ +do {\ + result->cmd_info_.string_[0] = string;\ + result->cmd_info_.string_[1] = string_two;\ +} while (0); + +#define SET_ICMD_SECOND_STRING(string) \ +do {\ + result->cmd_info_.string_[1] = string;\ +} while (0); + +#define SET_ICMD_CONFIG_INT_VALUE(string, integer) \ +do {\ + result->cmd_info_.sub_type_ = OBPROXY_T_SUB_CONFIG_INT_VAULE;\ + result->cmd_info_.string_[0] = string;\ + result->cmd_info_.integer_[0] = integer;\ +} while (0); + +#define SET_ICMD_TYPE_STRING_INT_VALUE(sub_type, string, integer) \ +do {\ + result->cmd_info_.sub_type_ = sub_type;\ + result->cmd_info_.string_[0] = string;\ + result->cmd_info_.integer_[0] = integer;\ +} while (0); + +#define SET_ICMD_ONE_ID(id) \ +do {\ + result->cmd_info_.integer_[0] = id;\ +} while (0); + +#define SET_ICMD_TWO_ID(id, id_two) \ +do {\ + result->cmd_info_.integer_[0] = id;\ + result->cmd_info_.integer_[1] = id_two;\ +} while (0); + +#define SET_ICMD_SECOND_ID(id) \ +do {\ + result->cmd_info_.integer_[1] = id;\ +} while (0); + +#define SET_READ_CONSISTENCY(read_consistency_type) \ +do {\ + if (OBPROXY_READ_CONSISTENCY_INVALID == result->read_consistency_type_) {\ + result->read_consistency_type_ = read_consistency_type;\ + }\ +} while (0); + +#define add_call_node(call_parse_info, call_node) \ +do { \ + if (NULL != call_parse_info.tail_) {\ + call_parse_info.tail_->next_ = call_node;\ + call_parse_info.tail_ = call_node;\ + } else {\ + call_parse_info.head_ = call_node;\ + call_parse_info.tail_ = call_node;\ + }\ + ++call_parse_info.node_count_;\ +} while(0) + +#define malloc_call_node(call_node, type) \ +do { \ + if (OB_ISNULL(call_node = ((ObProxyCallParseNode *)obproxy_parse_malloc(sizeof(ObProxyCallParseNode), result->malloc_pool_)))) { \ + YYABORT; \ + } else { \ + call_node->type_ = type; \ + call_node->next_ = NULL; \ + } \ +} while(0) \ + +#define add_text_ps_node(text_ps_parse_info, parse_node) \ +do { \ + if (NULL != text_ps_parse_info.tail_) {\ + text_ps_parse_info.tail_->next_ = parse_node;\ + text_ps_parse_info.tail_ = parse_node;\ + } else {\ + text_ps_parse_info.head_ = parse_node;\ + text_ps_parse_info.tail_ = parse_node;\ + }\ + ++text_ps_parse_info.node_count_;\ +} while(0) + +#define malloc_parse_node(parse_node) \ +do { \ + if (OB_ISNULL(parse_node = ((ObProxyTextPsParseNode *)obproxy_parse_malloc(sizeof(ObProxyTextPsParseNode), result->malloc_pool_)))) { \ + YYABORT; \ + } else { \ + parse_node->next_ = NULL; \ + } \ +} while(0) \ + +#define malloc_shard_column_node(col_node, tb_name, col_name, col_type) \ +do { \ + if (OB_ISNULL(col_node = ((ObShardColumnNode *)obproxy_parse_malloc(sizeof(ObShardColumnNode), result->malloc_pool_)))) { \ + YYABORT; \ + } \ + col_node->tb_name_ = tb_name;\ + col_node->col_name_ = col_name;\ + col_node->type_ = col_type;\ +} while(0) + +#define add_shard_column_node(route_info, col_node) \ +do { \ + col_node->next_ = NULL;\ + if (NULL != route_info.tail_) {\ + route_info.tail_->next_ = col_node;\ + route_info.tail_ = col_node;\ + } else {\ + route_info.head_ = col_node;\ + route_info.tail_ = col_node;\ + }\ + ++route_info.node_count_;\ +} while(0) + +#define add_hint_index(route_info, index_tb_name) \ +do { \ + if (route_info.index_count_ >=0 && route_info.index_count_ < OBPROXY_MAX_HINT_INDEX_COUNT) {\ + route_info.index_tb_name_[route_info.index_count_] = index_tb_name; \ + }\ +} while(0) + +#define malloc_set_var_node(var_node, value_type) \ +do { \ + if (OB_ISNULL(var_node = ((ObProxySetVarNode *)obproxy_parse_malloc(sizeof(ObProxySetVarNode), result->malloc_pool_)))) { \ + YYABORT; \ + } \ + var_node->value_type_ = value_type;\ + var_node->next_ = NULL;\ +} while(0) + +#define add_set_var_node(set_info, var_node, name, type) \ +do { \ + var_node->name_ = name; \ + var_node->type_ = type; \ + if (NULL != set_info.tail_) {\ + set_info.tail_->next_ = var_node;\ + set_info.tail_ = var_node;\ + } else {\ + set_info.head_ = var_node;\ + set_info.tail_ = var_node;\ + }\ + ++set_info.node_count_;\ +} while(0) + + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + + +#ifndef YY_OBPROXY_OB_PROXY_PARSER_TAB_H_INCLUDED +# define YY_OBPROXY_OB_PROXY_PARSER_TAB_H_INCLUDED +/* Debug traces. */ +#ifndef OBPROXY_GBK_DEBUG +# if defined YYDEBUG +#if YYDEBUG +# define OBPROXY_GBK_DEBUG 1 +# else +# define OBPROXY_GBK_DEBUG 0 +# endif +# else /* ! defined YYDEBUG */ +# define OBPROXY_GBK_DEBUG 0 +# endif /* ! defined YYDEBUG */ +#endif /* ! defined OBPROXY_GBK_DEBUG */ +#if OBPROXY_GBK_DEBUG +extern int ob_proxy_parser_gbk_yydebug; +#endif +/* Tokens. */ +#ifndef OBPROXYTOKENTYPE +# define OBPROXYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum obproxytokentype { + DUMMY_WHERE_CLAUSE = 258, + DUMMY_INSERT_CLAUSE = 259, + SELECT = 260, + DELETE = 261, + INSERT = 262, + UPDATE = 263, + REPLACE = 264, + MERGE = 265, + SHOW = 266, + SET = 267, + CALL = 268, + CREATE = 269, + DROP = 270, + ALTER = 271, + TRUNCATE = 272, + RENAME = 273, + TABLE = 274, + STATUS = 275, + UNIQUE = 276, + GRANT = 277, + REVOKE = 278, + ANALYZE = 279, + PURGE = 280, + COMMENT = 281, + FROM = 282, + DUAL = 283, + PREPARE = 284, + EXECUTE = 285, + USING = 286, + DEALLOCATE = 287, + SELECT_HINT_BEGIN = 288, + UPDATE_HINT_BEGIN = 289, + DELETE_HINT_BEGIN = 290, + INSERT_HINT_BEGIN = 291, + REPLACE_HINT_BEGIN = 292, + MERGE_HINT_BEGIN = 293, + HINT_END = 294, + COMMENT_BEGIN = 295, + COMMENT_END = 296, + ROUTE_TABLE = 297, + ROUTE_PART_KEY = 298, + QUERY_TIMEOUT = 299, + READ_CONSISTENCY = 300, + WEAK = 301, + STRONG = 302, + FROZEN = 303, + PLACE_HOLDER = 304, + END_P = 305, + ERROR = 306, + WHEN = 307, + FLASHBACK = 308, + AUDIT = 309, + NOAUDIT = 310, + BEGI = 311, + START = 312, + TRANSACTION = 313, + READ = 314, + ONLY = 315, + WITH = 316, + CONSISTENT = 317, + SNAPSHOT = 318, + INDEX = 319, + XA = 320, + WARNINGS = 321, + ERRORS = 322, + TRACE = 323, + QUICK = 324, + COUNT = 325, + AS = 326, + WHERE = 327, + VALUES = 328, + ORDER = 329, + GROUP = 330, + HAVING = 331, + INTO = 332, + UNION = 333, + FOR = 334, + TX_READ_ONLY = 335, + SELECT_OBPROXY_ROUTE_ADDR = 336, + SET_OBPROXY_ROUTE_ADDR = 337, + NAME_OB_DOT = 338, + NAME_OB = 339, + EXPLAIN = 340, + DESC = 341, + DESCRIBE = 342, + NAME_STR = 343, + USE = 344, + HELP = 345, + SET_NAMES = 346, + SET_CHARSET = 347, + SET_PASSWORD = 348, + SET_DEFAULT = 349, + SET_OB_READ_CONSISTENCY = 350, + SET_TX_READ_ONLY = 351, + GLOBAL = 352, + SESSION = 353, + NUMBER_VAL = 354, + GROUP_ID = 355, + TABLE_ID = 356, + ELASTIC_ID = 357, + TESTLOAD = 358, + ODP_COMMENT = 359, + TNT_ID = 360, + DISASTER_STATUS = 361, + TRACE_ID = 362, + RPC_ID = 363, + TARGET_DB_SERVER = 364, + DBP_COMMENT = 365, + ROUTE_TAG = 366, + SYS_TAG = 367, + TABLE_NAME = 368, + SCAN_ALL = 369, + STICKY_SESSION = 370, + PARALL = 371, + SHARD_KEY = 372, + INT_NUM = 373, + SHOW_PROXYNET = 374, + THREAD = 375, + CONNECTION = 376, + LIMIT = 377, + OFFSET = 378, + SHOW_PROCESSLIST = 379, + SHOW_PROXYSESSION = 380, + SHOW_GLOBALSESSION = 381, + ATTRIBUTE = 382, + VARIABLES = 383, + ALL = 384, + STAT = 385, + SHOW_PROXYCONFIG = 386, + DIFF = 387, + USER = 388, + LIKE = 389, + SHOW_PROXYSM = 390, + SHOW_PROXYCLUSTER = 391, + SHOW_PROXYRESOURCE = 392, + SHOW_PROXYCONGESTION = 393, + SHOW_PROXYROUTE = 394, + PARTITION = 395, + ROUTINE = 396, + SHOW_PROXYVIP = 397, + SHOW_PROXYMEMORY = 398, + OBJPOOL = 399, + SHOW_SQLAUDIT = 400, + SHOW_WARNLOG = 401, + SHOW_PROXYSTAT = 402, + REFRESH = 403, + SHOW_PROXYTRACE = 404, + SHOW_PROXYINFO = 405, + BINARY = 406, + UPGRADE = 407, + IDC = 408, + SHOW_ELASTIC_ID = 409, + SHOW_TOPOLOGY = 410, + GROUP_NAME = 411, + SHOW_DB_VERSION = 412, + SHOW_DATABASES = 413, + SHOW_TABLES = 414, + SHOW_FULL_TABLES = 415, + SELECT_DATABASE = 416, + SHOW_CREATE_TABLE = 417, + SELECT_PROXY_VERSION = 418, + SHOW_COLUMNS = 419, + SHOW_INDEX = 420, + ALTER_PROXYCONFIG = 421, + ALTER_PROXYRESOURCE = 422, + PING_PROXY = 423, + KILL_PROXYSESSION = 424, + KILL_GLOBALSESSION = 425, + KILL = 426, + QUERY = 427, + SHOW_MASTER_STATUS = 428, + SHOW_BINARY_LOGS = 429, + SHOW_BINLOG_EVENTS = 430, + PURGE_BINARY_LOGS = 431, + RESET_MASTER = 432, + SHOW_BINLOG_SERVER_FOR_TENANT = 433 + }; +#endif + + + +#if ! defined OBPROXYSTYPE && ! defined OBPROXYSTYPE_IS_DECLARED +typedef union OBPROXYSTYPE +{ + + + int64_t num; + ObProxyParseString str; + ObProxyCallParseNode *node; + ObShardColumnNode *shard_node; + ObProxySetVarNode *var_node; + + + +} OBPROXYSTYPE; +# define OBPROXYSTYPE_IS_TRIVIAL 1 +# define obproxystype OBPROXYSTYPE /* obsolescent; will be withdrawn */ +# define OBPROXYSTYPE_IS_DECLARED 1 +#endif + +#if ! defined OBPROXYLTYPE && ! defined OBPROXYLTYPE_IS_DECLARED +typedef struct OBPROXYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} OBPROXYLTYPE; +# define obproxyltype OBPROXYLTYPE /* obsolescent; will be withdrawn */ +# define OBPROXYLTYPE_IS_DECLARED 1 +# define OBPROXYLTYPE_IS_TRIVIAL 1 +#endif + + +#endif +/* Copy the second part of user declarations. */ + + +#include "ob_proxy_parser_gbk_lex.h" +#define YYLEX_PARAM result->yyscan_info_ +extern void yyerror(YYLTYPE* yylloc, ObProxyParseResult* p, char* s,...); +extern void *obproxy_parse_malloc(const size_t nbyte, void *malloc_pool); + + + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int yyi) +#else +static int +YYID (yyi) + int yyi; +#endif +{ + return yyi; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \ + && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; + YYLTYPE yyls_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + + 2 * YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 314 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 1384 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 190 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 138 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 435 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 715 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 433 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 188, 2, 2, 2, 2, + 183, 184, 189, 2, 181, 2, 185, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 179, + 2, 182, 2, 2, 180, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 186, 2, 187, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, + 175, 176, 177, 178 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint16 yyprhs[] = +{ + 0, 0, 3, 5, 7, 9, 12, 15, 18, 22, + 24, 27, 31, 33, 36, 38, 40, 42, 44, 46, + 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, + 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, + 90, 93, 96, 99, 102, 105, 108, 110, 112, 115, + 117, 119, 121, 123, 124, 126, 128, 131, 133, 135, + 137, 139, 141, 143, 145, 147, 150, 155, 158, 160, + 162, 166, 169, 173, 176, 179, 183, 187, 189, 191, + 193, 195, 197, 199, 201, 203, 205, 208, 210, 212, + 214, 215, 218, 219, 221, 224, 230, 234, 236, 240, + 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, + 262, 264, 266, 268, 271, 274, 278, 284, 288, 294, + 295, 298, 299, 302, 306, 310, 316, 318, 320, 324, + 330, 338, 340, 344, 346, 350, 352, 354, 356, 358, + 360, 362, 368, 370, 374, 380, 381, 383, 387, 389, + 391, 393, 396, 400, 402, 404, 407, 409, 412, 416, + 420, 422, 424, 426, 427, 431, 433, 437, 441, 447, + 450, 453, 458, 461, 464, 468, 470, 475, 482, 487, + 493, 500, 505, 509, 511, 513, 515, 517, 520, 524, + 530, 537, 544, 551, 558, 565, 573, 580, 587, 594, + 601, 610, 619, 626, 627, 630, 633, 636, 638, 642, + 644, 649, 654, 658, 665, 669, 674, 679, 686, 690, + 692, 696, 697, 701, 705, 709, 713, 717, 721, 725, + 729, 733, 737, 741, 747, 751, 752, 754, 755, 757, + 759, 761, 763, 766, 768, 771, 773, 776, 779, 783, + 784, 786, 789, 791, 794, 796, 799, 802, 803, 806, + 811, 813, 818, 824, 826, 831, 836, 842, 843, 845, + 847, 849, 850, 852, 856, 860, 863, 865, 867, 869, + 871, 873, 875, 877, 879, 881, 883, 885, 887, 889, + 891, 893, 895, 897, 899, 901, 903, 905, 907, 909, + 911, 913, 915, 917, 919, 921, 922, 925, 930, 935, + 936, 939, 940, 943, 946, 948, 950, 954, 957, 961, + 966, 968, 971, 972, 975, 979, 982, 985, 988, 989, + 992, 996, 999, 1003, 1006, 1010, 1014, 1019, 1021, 1024, + 1027, 1031, 1034, 1037, 1038, 1040, 1042, 1045, 1048, 1052, + 1055, 1057, 1060, 1062, 1065, 1068, 1071, 1074, 1075, 1077, + 1081, 1087, 1090, 1094, 1097, 1098, 1100, 1103, 1106, 1109, + 1112, 1117, 1123, 1129, 1133, 1135, 1138, 1142, 1146, 1149, + 1152, 1156, 1160, 1161, 1164, 1166, 1170, 1174, 1178, 1179, + 1181, 1183, 1187, 1190, 1194, 1197, 1200, 1202, 1203, 1206, + 1211, 1214, 1216, 1220, 1223, 1228, 1232, 1238, 1240, 1242, + 1244, 1246, 1248, 1250, 1252, 1254, 1256, 1258, 1260, 1262, + 1264, 1266, 1268, 1270, 1272, 1274, 1276, 1278, 1280, 1282, + 1284, 1286, 1288, 1290, 1292, 1294 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int16 yyrhs[] = +{ + 191, 0, -1, 192, -1, 1, -1, 193, -1, 192, + 193, -1, 194, 50, -1, 194, 179, -1, 194, 179, + 50, -1, 179, -1, 179, 50, -1, 56, 194, 179, + -1, 195, -1, 254, 195, -1, 196, -1, 245, -1, + 250, -1, 246, -1, 247, -1, 248, -1, 197, -1, + 316, -1, 280, -1, 215, -1, 281, -1, 320, -1, + 321, -1, 228, -1, 229, -1, 230, -1, 231, -1, + 232, -1, 233, -1, 234, -1, 198, -1, 207, -1, + 249, -1, 282, -1, 322, -1, 268, 212, 211, -1, + 209, 196, -1, 209, 245, -1, 209, 247, -1, 209, + 248, -1, 209, 246, -1, 209, 249, -1, 199, -1, + 208, -1, 14, 200, -1, 15, -1, 16, -1, 17, + -1, 18, -1, -1, 19, -1, 64, -1, 21, 64, + -1, 196, -1, 245, -1, 246, -1, 248, -1, 247, + -1, 322, -1, 234, -1, 249, -1, 180, 84, -1, + 202, 181, 180, 84, -1, 180, 84, -1, 203, -1, + 201, -1, 29, 327, 27, -1, 30, 327, -1, 30, + 327, 31, -1, 205, 204, -1, 206, 202, -1, 15, + 29, 327, -1, 32, 29, 327, -1, 22, -1, 23, + -1, 24, -1, 25, -1, 53, -1, 26, -1, 54, + -1, 55, -1, 210, -1, 210, 84, -1, 85, -1, + 86, -1, 87, -1, -1, 27, 241, -1, -1, 238, + -1, 5, 80, -1, 5, 80, 212, 27, 241, -1, + 5, 80, 238, -1, 163, -1, 163, 71, 327, -1, + 213, -1, 214, -1, 226, -1, 227, -1, 216, -1, + 224, -1, 225, -1, 223, -1, 161, -1, 158, -1, + 221, -1, 222, -1, 217, -1, 218, -1, 162, 235, + -1, 210, 327, -1, 164, 27, 84, -1, 164, 27, + 84, 27, 84, -1, 165, 27, 84, -1, 165, 27, + 84, 27, 84, -1, -1, 134, 84, -1, -1, 27, + 84, -1, 159, 220, 219, -1, 160, 220, 219, -1, + 11, 19, 20, 220, 219, -1, 157, -1, 154, -1, + 154, 27, 84, -1, 154, 72, 156, 182, 84, -1, + 154, 27, 84, 72, 156, 182, 84, -1, 155, -1, + 155, 27, 84, -1, 81, -1, 82, 182, 118, -1, + 91, -1, 92, -1, 93, -1, 94, -1, 95, -1, + 96, -1, 13, 235, 183, 236, 184, -1, 327, -1, + 327, 185, 327, -1, 327, 185, 327, 185, 327, -1, + -1, 237, -1, 236, 181, 237, -1, 84, -1, 118, + -1, 99, -1, 180, 84, -1, 180, 180, 84, -1, + 49, -1, 239, -1, 238, 239, -1, 240, -1, 183, + 184, -1, 183, 196, 184, -1, 183, 238, 184, -1, + 324, -1, 242, -1, 196, -1, -1, 183, 244, 184, + -1, 84, -1, 244, 181, 84, -1, 271, 325, 323, + -1, 271, 325, 323, 243, 242, -1, 273, 241, -1, + 269, 241, -1, 270, 279, 27, 241, -1, 274, 325, + -1, 12, 251, -1, 252, 181, 251, -1, 252, -1, + 180, 84, 182, 253, -1, 180, 180, 97, 84, 182, + 253, -1, 97, 84, 182, 253, -1, 180, 180, 84, + 182, 253, -1, 180, 180, 98, 84, 182, 253, -1, + 98, 84, 182, 253, -1, 84, 182, 253, -1, 84, + -1, 118, -1, 99, -1, 255, -1, 255, 254, -1, + 40, 256, 41, -1, 40, 104, 264, 263, 41, -1, + 40, 101, 182, 267, 263, 41, -1, 40, 113, 182, + 267, 263, 41, -1, 40, 100, 182, 267, 263, 41, + -1, 40, 102, 182, 267, 263, 41, -1, 40, 103, + 182, 267, 263, 41, -1, 40, 83, 84, 182, 266, + 263, 41, -1, 40, 107, 182, 265, 263, 41, -1, + 40, 108, 182, 265, 263, 41, -1, 40, 105, 182, + 267, 263, 41, -1, 40, 106, 182, 267, 263, 41, + -1, 40, 110, 111, 182, 186, 258, 187, 41, -1, + 40, 110, 112, 182, 186, 260, 187, 41, -1, 40, + 109, 182, 267, 263, 41, -1, -1, 256, 257, -1, + 42, 84, -1, 43, 84, -1, 84, -1, 259, 181, + 258, -1, 259, -1, 100, 183, 267, 184, -1, 113, + 183, 267, 184, -1, 114, 183, 184, -1, 114, 183, + 116, 182, 267, 184, -1, 115, 183, 184, -1, 117, + 183, 261, 184, -1, 68, 183, 265, 184, -1, 68, + 183, 265, 188, 265, 184, -1, 262, 181, 261, -1, + 262, -1, 84, 182, 267, -1, -1, 263, 181, 264, + -1, 100, 182, 267, -1, 101, 182, 267, -1, 113, + 182, 267, -1, 102, 182, 267, -1, 103, 182, 267, + -1, 107, 182, 265, -1, 108, 182, 265, -1, 105, + 182, 267, -1, 106, 182, 267, -1, 109, 182, 267, + -1, 84, 185, 84, 182, 266, -1, 84, 182, 266, + -1, -1, 267, -1, -1, 267, -1, 84, -1, 88, + -1, 5, -1, 33, 275, -1, 8, -1, 34, 275, + -1, 6, -1, 35, 275, -1, 7, 272, -1, 36, + 275, 272, -1, -1, 129, -1, 129, 52, -1, 9, + -1, 37, 275, -1, 10, -1, 38, 275, -1, 276, + 39, -1, -1, 277, 276, -1, 44, 183, 118, 184, + -1, 118, -1, 45, 183, 278, 184, -1, 64, 183, + 84, 84, 184, -1, 84, -1, 84, 183, 118, 184, + -1, 84, 183, 84, 184, -1, 84, 183, 84, 84, + 184, -1, -1, 46, -1, 47, -1, 48, -1, -1, + 69, -1, 11, 315, 66, -1, 11, 315, 67, -1, + 11, 68, -1, 286, -1, 288, -1, 289, -1, 292, + -1, 290, -1, 294, -1, 295, -1, 296, -1, 297, + -1, 299, -1, 300, -1, 301, -1, 302, -1, 303, + -1, 305, -1, 306, -1, 308, -1, 309, -1, 310, + -1, 311, -1, 312, -1, 313, -1, 314, -1, 173, + -1, 174, -1, 175, -1, 176, -1, 177, -1, 178, + -1, -1, 122, 118, -1, 122, 118, 181, 118, -1, + 122, 118, 123, 118, -1, -1, 134, 84, -1, -1, + 134, 84, -1, 119, 287, -1, 120, -1, 121, -1, + 121, 118, 283, -1, 131, 284, -1, 131, 132, 284, + -1, 131, 132, 133, 284, -1, 124, -1, 126, 291, + -1, -1, 127, 84, -1, 127, 134, 84, -1, 127, + 129, -1, 134, 84, -1, 125, 293, -1, -1, 127, + 284, -1, 127, 118, 284, -1, 130, 284, -1, 130, + 118, 284, -1, 128, 284, -1, 128, 118, 284, -1, + 128, 129, 284, -1, 128, 129, 118, 284, -1, 135, + -1, 135, 118, -1, 136, 284, -1, 136, 153, 284, + -1, 137, 284, -1, 138, 298, -1, -1, 84, -1, + 129, -1, 129, 84, -1, 139, 285, -1, 139, 141, + 285, -1, 139, 140, -1, 142, -1, 142, 84, -1, + 143, -1, 143, 144, -1, 145, 283, -1, 145, 118, + -1, 146, 304, -1, -1, 118, -1, 118, 181, 118, + -1, 118, 181, 118, 181, 84, -1, 147, 284, -1, + 147, 148, 284, -1, 149, 307, -1, -1, 118, -1, + 118, 118, -1, 150, 151, -1, 150, 152, -1, 150, + 153, -1, 166, 12, 84, 182, -1, 166, 12, 84, + 182, 84, -1, 166, 12, 84, 182, 118, -1, 167, + 6, 84, -1, 168, -1, 169, 118, -1, 169, 118, + 118, -1, 170, 84, 118, -1, 170, 84, -1, 171, + 118, -1, 171, 121, 118, -1, 171, 172, 118, -1, + -1, 70, 189, -1, 56, -1, 57, 58, 317, -1, + 65, 56, 84, -1, 65, 57, 84, -1, -1, 318, + -1, 319, -1, 318, 181, 319, -1, 59, 60, -1, + 61, 62, 63, -1, 89, 84, -1, 90, 84, -1, + 84, -1, -1, 140, 84, -1, 140, 183, 84, 184, + -1, 325, 323, -1, 327, -1, 327, 185, 327, -1, + 327, 327, -1, 327, 185, 327, 327, -1, 327, 71, + 327, -1, 327, 185, 327, 71, 327, -1, 57, -1, + 65, -1, 56, -1, 58, -1, 62, -1, 67, -1, + 66, -1, 70, -1, 69, -1, 68, -1, 120, -1, + 121, -1, 123, -1, 127, -1, 128, -1, 130, -1, + 132, -1, 133, -1, 144, -1, 148, -1, 152, -1, + 153, -1, 172, -1, 156, -1, 53, -1, 54, -1, + 55, -1, 84, -1, 326, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 334, 334, 335, 337, 338, 340, 341, 342, 343, + 344, 345, 347, 348, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, 369, 370, 371, 372, 373, 374, 376, + 378, 379, 380, 381, 382, 383, 385, 386, 388, 389, + 390, 391, 392, 394, 395, 396, 397, 399, 400, 401, + 402, 403, 404, 405, 406, 408, 415, 423, 431, 432, + 435, 441, 446, 452, 455, 458, 463, 469, 470, 471, + 472, 473, 474, 475, 476, 478, 479, 481, 482, 483, + 485, 486, 488, 489, 491, 492, 493, 495, 496, 498, + 499, 500, 501, 502, 504, 505, 506, 507, 508, 509, + 510, 511, 512, 513, 514, 521, 526, 533, 538, 545, + 546, 548, 549, 551, 555, 560, 565, 567, 568, 573, + 578, 585, 586, 592, 595, 601, 602, 603, 604, 605, + 606, 609, 611, 615, 620, 628, 631, 636, 641, 646, + 651, 656, 661, 666, 674, 675, 677, 679, 680, 681, + 683, 684, 686, 688, 689, 691, 692, 694, 698, 699, + 700, 701, 702, 707, 709, 710, 712, 716, 720, 724, + 728, 732, 736, 740, 745, 750, 756, 757, 759, 760, + 761, 762, 763, 764, 765, 766, 772, 773, 774, 775, + 776, 777, 778, 779, 780, 782, 783, 784, 786, 787, + 789, 794, 799, 800, 801, 802, 804, 805, 807, 808, + 810, 818, 819, 821, 822, 823, 824, 825, 826, 827, + 828, 829, 830, 831, 837, 839, 840, 842, 843, 845, + 846, 848, 849, 850, 851, 852, 853, 854, 855, 857, + 858, 859, 861, 862, 863, 864, 865, 866, 867, 869, + 870, 871, 872, 877, 878, 879, 880, 882, 883, 884, + 885, 887, 888, 891, 892, 893, 896, 897, 898, 899, + 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, + 910, 911, 912, 913, 914, 915, 916, 917, 918, 920, + 921, 922, 923, 924, 925, 930, 932, 936, 941, 949, + 950, 954, 955, 958, 960, 961, 962, 966, 967, 968, + 972, 974, 976, 977, 978, 979, 980, 983, 985, 986, + 987, 988, 989, 990, 991, 992, 993, 997, 998, 1002, + 1003, 1008, 1011, 1013, 1014, 1015, 1016, 1020, 1021, 1022, + 1026, 1027, 1031, 1032, 1036, 1037, 1040, 1042, 1043, 1044, + 1045, 1049, 1050, 1053, 1055, 1056, 1057, 1061, 1062, 1063, + 1067, 1068, 1069, 1073, 1077, 1081, 1082, 1086, 1087, 1091, + 1092, 1093, 1096, 1097, 1100, 1104, 1105, 1106, 1108, 1109, + 1111, 1112, 1115, 1116, 1119, 1125, 1128, 1130, 1131, 1132, + 1134, 1139, 1142, 1146, 1150, 1155, 1159, 1165, 1166, 1167, + 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, + 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, + 1188, 1189, 1190, 1191, 1193, 1194 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "DUMMY_WHERE_CLAUSE", + "DUMMY_INSERT_CLAUSE", "SELECT", "DELETE", "INSERT", "UPDATE", "REPLACE", + "MERGE", "SHOW", "SET", "CALL", "CREATE", "DROP", "ALTER", "TRUNCATE", + "RENAME", "TABLE", "STATUS", "UNIQUE", "GRANT", "REVOKE", "ANALYZE", + "PURGE", "COMMENT", "FROM", "DUAL", "PREPARE", "EXECUTE", "USING", + "DEALLOCATE", "SELECT_HINT_BEGIN", "UPDATE_HINT_BEGIN", + "DELETE_HINT_BEGIN", "INSERT_HINT_BEGIN", "REPLACE_HINT_BEGIN", + "MERGE_HINT_BEGIN", "HINT_END", "COMMENT_BEGIN", "COMMENT_END", + "ROUTE_TABLE", "ROUTE_PART_KEY", "QUERY_TIMEOUT", "READ_CONSISTENCY", + "WEAK", "STRONG", "FROZEN", "PLACE_HOLDER", "END_P", "ERROR", "WHEN", + "FLASHBACK", "AUDIT", "NOAUDIT", "BEGI", "START", "TRANSACTION", "READ", + "ONLY", "WITH", "CONSISTENT", "SNAPSHOT", "INDEX", "XA", "WARNINGS", + "ERRORS", "TRACE", "QUICK", "COUNT", "AS", "WHERE", "VALUES", "ORDER", + "GROUP", "HAVING", "INTO", "UNION", "FOR", "TX_READ_ONLY", + "SELECT_OBPROXY_ROUTE_ADDR", "SET_OBPROXY_ROUTE_ADDR", "NAME_OB_DOT", + "NAME_OB", "EXPLAIN", "DESC", "DESCRIBE", "NAME_STR", "USE", "HELP", + "SET_NAMES", "SET_CHARSET", "SET_PASSWORD", "SET_DEFAULT", + "SET_OB_READ_CONSISTENCY", "SET_TX_READ_ONLY", "GLOBAL", "SESSION", + "NUMBER_VAL", "GROUP_ID", "TABLE_ID", "ELASTIC_ID", "TESTLOAD", + "ODP_COMMENT", "TNT_ID", "DISASTER_STATUS", "TRACE_ID", "RPC_ID", + "TARGET_DB_SERVER", "DBP_COMMENT", "ROUTE_TAG", "SYS_TAG", "TABLE_NAME", + "SCAN_ALL", "STICKY_SESSION", "PARALL", "SHARD_KEY", "INT_NUM", + "SHOW_PROXYNET", "THREAD", "CONNECTION", "LIMIT", "OFFSET", + "SHOW_PROCESSLIST", "SHOW_PROXYSESSION", "SHOW_GLOBALSESSION", + "ATTRIBUTE", "VARIABLES", "ALL", "STAT", "SHOW_PROXYCONFIG", "DIFF", + "USER", "LIKE", "SHOW_PROXYSM", "SHOW_PROXYCLUSTER", + "SHOW_PROXYRESOURCE", "SHOW_PROXYCONGESTION", "SHOW_PROXYROUTE", + "PARTITION", "ROUTINE", "SHOW_PROXYVIP", "SHOW_PROXYMEMORY", "OBJPOOL", + "SHOW_SQLAUDIT", "SHOW_WARNLOG", "SHOW_PROXYSTAT", "REFRESH", + "SHOW_PROXYTRACE", "SHOW_PROXYINFO", "BINARY", "UPGRADE", "IDC", + "SHOW_ELASTIC_ID", "SHOW_TOPOLOGY", "GROUP_NAME", "SHOW_DB_VERSION", + "SHOW_DATABASES", "SHOW_TABLES", "SHOW_FULL_TABLES", "SELECT_DATABASE", + "SHOW_CREATE_TABLE", "SELECT_PROXY_VERSION", "SHOW_COLUMNS", + "SHOW_INDEX", "ALTER_PROXYCONFIG", "ALTER_PROXYRESOURCE", "PING_PROXY", + "KILL_PROXYSESSION", "KILL_GLOBALSESSION", "KILL", "QUERY", + "SHOW_MASTER_STATUS", "SHOW_BINARY_LOGS", "SHOW_BINLOG_EVENTS", + "PURGE_BINARY_LOGS", "RESET_MASTER", "SHOW_BINLOG_SERVER_FOR_TENANT", + "';'", "'@'", "','", "'='", "'('", "')'", "'.'", "'{'", "'}'", "'#'", + "'*'", "$accept", "root", "sql_stmts", "sql_stmt", "comment_stmt", + "stmt", "select_stmt", "explain_stmt", "ddl_stmt", "mysql_ddl_stmt", + "create_dll_expr", "text_ps_from_stmt", "text_ps_execute_using_var_list", + "text_ps_prepare_var_list", "text_ps_prepare_args_stmt", + "text_ps_prepare_stmt", "text_ps_execute_stmt", "text_ps_stmt", + "oracle_ddl_stmt", "explain_or_desc_stmt", "explain_or_desc", "opt_from", + "select_expr_list", "select_tx_read_only_stmt", + "select_proxy_version_stmt", "hooked_stmt", "shard_special_stmt", + "show_columns_stmt", "show_index_stmt", "opt_show_like", "opt_show_from", + "show_tables_stmt", "show_table_status_stmt", "show_db_version_stmt", + "show_es_id_stmt", "show_topology_stmt", + "select_obproxy_route_addr_stmt", "set_obproxy_route_addr_stmt", + "set_names_stmt", "set_charset_stmt", "set_password_stmt", + "set_default_stmt", "set_ob_read_consistency_stmt", + "set_tx_read_only_stmt", "call_stmt", "routine_name_stmt", + "call_expr_list", "call_expr", "expr_list", "expr", "clause", "fromlist", + "sub_query", "opt_column_list", "column_list", "insert_stmt", + "replace_stmt", "update_stmt", "delete_stmt", "merge_stmt", "set_stmt", + "set_expr_list", "set_expr", "set_var_value", "comment_expr_list", + "comment_expr", "comment_list", "comment", "dbp_comment_list", + "dbp_comment", "dbp_sys_comment", "dbp_kv_comment_list", + "dbp_kv_comment", "odp_comment_list", "odp_comment", + "tracer_right_string_val", "name_right_string_val", "right_string_val", + "select_with_opt_hint", "update_with_opt_hint", "delete_with_opt_hint", + "insert_with_opt_hint", "insert_all_when", "replace_with_opt_hint", + "merge_with_opt_hint", "hint_list_with_end", "hint_list", "hint", + "opt_read_consistency", "opt_quick", "show_stmt", "icmd_stmt", + "binlog_stmt", "opt_limit", "opt_like", "opt_large_like", + "show_proxynet", "opt_show_net", "show_proxyconfig", "show_processlist", + "show_globalsession", "opt_show_global_session", "show_proxysession", + "opt_show_session", "show_proxysm", "show_proxycluster", + "show_proxyresource", "show_proxycongestion", "opt_show_congestion", + "show_proxyroute", "show_proxyvip", "show_proxymemory", "show_sqlaudit", + "show_warnlog", "opt_show_warnlog", "show_proxystat", "show_proxytrace", + "opt_show_trace", "show_proxyinfo", "alter_proxyconfig", + "alter_proxyresource", "ping_proxy", "kill_proxysession", + "kill_globalsession", "kill_mysql", "opt_count", "begin_stmt", + "opt_transaction_characteristics", "transaction_characteristics", + "transaction_characteristic", "use_db_stmt", "help_stmt", "other_stmt", + "partition_factor", "table_references", "table_factor", + "non_reserved_keyword", "var_name", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, + 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, + 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, + 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, + 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, + 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, + 425, 426, 427, 428, 429, 430, 431, 432, 433, 59, + 64, 44, 61, 40, 41, 46, 123, 125, 35, 42 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint16 yyr1[] = +{ + 0, 190, 191, 191, 192, 192, 193, 193, 193, 193, + 193, 193, 194, 194, 195, 195, 195, 195, 195, 195, + 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, + 195, 195, 195, 195, 195, 195, 195, 195, 195, 196, + 197, 197, 197, 197, 197, 197, 198, 198, 199, 199, + 199, 199, 199, 200, 200, 200, 200, 201, 201, 201, + 201, 201, 201, 201, 201, 202, 202, 203, 204, 204, + 205, 206, 206, 207, 207, 207, 207, 208, 208, 208, + 208, 208, 208, 208, 208, 209, 209, 210, 210, 210, + 211, 211, 212, 212, 213, 213, 213, 214, 214, 215, + 215, 215, 215, 215, 216, 216, 216, 216, 216, 216, + 216, 216, 216, 216, 216, 217, 217, 218, 218, 219, + 219, 220, 220, 221, 221, 222, 223, 224, 224, 224, + 224, 225, 225, 226, 227, 228, 229, 230, 231, 232, + 233, 234, 235, 235, 235, 236, 236, 236, 237, 237, + 237, 237, 237, 237, 238, 238, 239, 240, 240, 240, + 241, 241, 242, 243, 243, 244, 244, 245, 245, 246, + 247, 248, 249, 250, 251, 251, 252, 252, 252, 252, + 252, 252, 252, 253, 253, 253, 254, 254, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 256, 256, 257, 257, 257, 258, 258, + 259, 259, 259, 259, 259, 259, 260, 260, 261, 261, + 262, 263, 263, 264, 264, 264, 264, 264, 264, 264, + 264, 264, 264, 264, 264, 265, 265, 266, 266, 267, + 267, 268, 268, 269, 269, 270, 270, 271, 271, 272, + 272, 272, 273, 273, 274, 274, 275, 276, 276, 277, + 277, 277, 277, 277, 277, 277, 277, 278, 278, 278, + 278, 279, 279, 280, 280, 280, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 282, + 282, 282, 282, 282, 282, 283, 283, 283, 283, 284, + 284, 285, 285, 286, 287, 287, 287, 288, 288, 288, + 289, 290, 291, 291, 291, 291, 291, 292, 293, 293, + 293, 293, 293, 293, 293, 293, 293, 294, 294, 295, + 295, 296, 297, 298, 298, 298, 298, 299, 299, 299, + 300, 300, 301, 301, 302, 302, 303, 304, 304, 304, + 304, 305, 305, 306, 307, 307, 307, 308, 308, 308, + 309, 309, 309, 310, 311, 312, 312, 313, 313, 314, + 314, 314, 315, 315, 316, 316, 316, 316, 317, 317, + 318, 318, 319, 319, 320, 321, 322, 323, 323, 323, + 324, 325, 325, 325, 325, 325, 325, 326, 326, 326, + 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, + 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, + 326, 326, 326, 326, 327, 327 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 1, 1, 1, 2, 2, 2, 3, 1, + 2, 3, 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, + 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, + 1, 1, 1, 0, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 4, 2, 1, 1, + 3, 2, 3, 2, 2, 3, 3, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, + 0, 2, 0, 1, 2, 5, 3, 1, 3, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 3, 5, 3, 5, 0, + 2, 0, 2, 3, 3, 5, 1, 1, 3, 5, + 7, 1, 3, 1, 3, 1, 1, 1, 1, 1, + 1, 5, 1, 3, 5, 0, 1, 3, 1, 1, + 1, 2, 3, 1, 1, 2, 1, 2, 3, 3, + 1, 1, 1, 0, 3, 1, 3, 3, 5, 2, + 2, 4, 2, 2, 3, 1, 4, 6, 4, 5, + 6, 4, 3, 1, 1, 1, 1, 2, 3, 5, + 6, 6, 6, 6, 6, 7, 6, 6, 6, 6, + 8, 8, 6, 0, 2, 2, 2, 1, 3, 1, + 4, 4, 3, 6, 3, 4, 4, 6, 3, 1, + 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 5, 3, 0, 1, 0, 1, 1, + 1, 1, 2, 1, 2, 1, 2, 2, 3, 0, + 1, 2, 1, 2, 1, 2, 2, 0, 2, 4, + 1, 4, 5, 1, 4, 4, 5, 0, 1, 1, + 1, 0, 1, 3, 3, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 2, 4, 4, 0, + 2, 0, 2, 2, 1, 1, 3, 2, 3, 4, + 1, 2, 0, 2, 3, 2, 2, 2, 0, 2, + 3, 2, 3, 2, 3, 3, 4, 1, 2, 2, + 3, 2, 2, 0, 1, 1, 2, 2, 3, 2, + 1, 2, 1, 2, 2, 2, 2, 0, 1, 3, + 5, 2, 3, 2, 0, 1, 2, 2, 2, 2, + 4, 5, 5, 3, 1, 2, 3, 3, 2, 2, + 3, 3, 0, 2, 1, 3, 3, 3, 0, 1, + 1, 3, 2, 3, 2, 2, 1, 0, 2, 4, + 2, 1, 3, 2, 4, 3, 5, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint16 yydefact[] = +{ + 0, 3, 241, 245, 249, 243, 252, 254, 382, 0, + 0, 53, 49, 50, 51, 52, 77, 78, 79, 80, + 82, 0, 0, 0, 257, 257, 257, 257, 257, 257, + 203, 81, 83, 84, 384, 0, 0, 133, 0, 396, + 87, 88, 89, 0, 0, 135, 136, 137, 138, 139, + 140, 0, 320, 328, 322, 309, 337, 309, 309, 343, + 311, 350, 352, 305, 357, 309, 364, 0, 127, 131, + 126, 108, 121, 121, 107, 0, 97, 0, 0, 0, + 0, 374, 0, 0, 0, 299, 300, 301, 302, 303, + 304, 9, 0, 2, 4, 0, 12, 14, 20, 34, + 46, 0, 0, 35, 47, 0, 85, 99, 100, 23, + 103, 111, 112, 109, 110, 106, 104, 105, 101, 102, + 27, 28, 29, 30, 31, 32, 33, 15, 17, 18, + 19, 36, 16, 0, 186, 92, 0, 271, 0, 0, + 0, 22, 24, 37, 276, 277, 278, 280, 279, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 294, 295, 296, 297, 298, 21, 25, 26, + 38, 94, 250, 247, 0, 275, 0, 0, 0, 0, + 0, 0, 173, 175, 431, 432, 433, 409, 407, 410, + 411, 408, 413, 412, 416, 415, 414, 434, 417, 418, + 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, + 430, 429, 0, 435, 142, 54, 0, 55, 48, 0, + 0, 71, 0, 0, 0, 0, 263, 260, 242, 0, + 257, 244, 246, 249, 253, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 384, 0, 388, 0, 0, 0, 394, 395, 314, 315, + 313, 309, 309, 309, 327, 0, 0, 321, 309, 0, + 317, 338, 309, 339, 341, 344, 345, 342, 0, 349, + 311, 347, 351, 353, 355, 0, 354, 358, 356, 309, + 361, 365, 363, 367, 368, 369, 0, 0, 0, 0, + 119, 119, 113, 0, 0, 0, 0, 0, 375, 378, + 379, 0, 0, 10, 1, 5, 6, 7, 241, 0, + 57, 69, 68, 73, 63, 58, 59, 61, 60, 64, + 62, 0, 74, 40, 41, 44, 42, 43, 45, 86, + 114, 13, 187, 0, 90, 93, 154, 156, 162, 170, + 161, 160, 397, 401, 272, 0, 397, 169, 172, 0, + 96, 251, 121, 383, 273, 274, 0, 0, 0, 0, + 0, 0, 145, 0, 56, 75, 70, 72, 76, 0, + 267, 0, 0, 256, 258, 248, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 221, 0, 0, 235, 235, 0, 0, 0, + 0, 188, 0, 0, 207, 204, 11, 0, 0, 385, + 389, 390, 386, 387, 134, 305, 309, 329, 309, 309, + 333, 309, 331, 323, 325, 0, 326, 309, 318, 310, + 340, 346, 312, 348, 306, 0, 362, 366, 128, 0, + 132, 122, 0, 123, 124, 98, 115, 117, 0, 373, + 376, 377, 380, 381, 8, 67, 65, 0, 157, 0, + 0, 0, 39, 155, 0, 400, 0, 0, 403, 0, + 163, 0, 119, 183, 185, 184, 182, 0, 0, 0, + 0, 0, 0, 174, 153, 148, 150, 149, 0, 0, + 146, 143, 0, 268, 269, 270, 0, 0, 0, 0, + 237, 239, 240, 221, 221, 221, 221, 237, 0, 0, + 0, 0, 0, 0, 0, 235, 235, 0, 0, 0, + 221, 221, 221, 236, 221, 221, 0, 0, 221, 205, + 206, 392, 0, 0, 316, 330, 334, 309, 335, 332, + 324, 319, 0, 0, 359, 0, 0, 120, 0, 0, + 370, 0, 158, 159, 91, 398, 0, 405, 402, 171, + 0, 0, 95, 125, 178, 181, 176, 0, 0, 0, + 151, 0, 0, 141, 0, 259, 261, 0, 0, 265, + 264, 221, 238, 0, 0, 0, 0, 234, 0, 223, + 224, 226, 227, 230, 231, 228, 229, 232, 225, 189, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 393, + 391, 336, 308, 307, 0, 0, 129, 116, 118, 371, + 372, 66, 0, 0, 404, 165, 0, 168, 179, 0, + 0, 152, 147, 144, 262, 266, 0, 192, 190, 193, + 194, 237, 222, 198, 199, 196, 197, 202, 0, 0, + 0, 0, 0, 0, 209, 0, 0, 191, 360, 0, + 399, 406, 0, 164, 177, 180, 195, 233, 0, 0, + 0, 0, 0, 0, 0, 235, 0, 130, 166, 0, + 0, 0, 212, 214, 0, 0, 219, 200, 208, 0, + 201, 210, 211, 0, 0, 215, 0, 216, 235, 0, + 220, 218, 0, 213, 217 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 92, 93, 94, 95, 96, 348, 98, 99, 100, + 218, 321, 332, 322, 323, 101, 102, 103, 104, 105, + 106, 472, 344, 107, 108, 109, 110, 111, 112, 453, + 300, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 123, 124, 125, 126, 212, 499, 500, 345, 346, + 347, 349, 350, 571, 636, 127, 128, 129, 130, 131, + 132, 182, 183, 486, 133, 134, 249, 415, 663, 664, + 666, 695, 696, 529, 402, 532, 591, 533, 135, 136, + 137, 138, 173, 139, 140, 228, 229, 230, 506, 355, + 141, 142, 143, 286, 270, 281, 144, 260, 145, 146, + 147, 267, 148, 264, 149, 150, 151, 152, 277, 153, + 154, 155, 156, 157, 288, 158, 159, 292, 160, 161, + 162, 163, 164, 165, 166, 177, 167, 419, 420, 421, + 168, 169, 170, 475, 351, 352, 213, 353 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -479 +static const yytype_int16 yypact[] = +{ + 418, -479, 36, -479, -62, -479, -479, -479, 47, -14, + 1104, 50, 68, -479, -479, -479, -479, -479, -479, -479, + -479, 1104, 1104, 116, 8, 8, 8, 8, 8, 8, + 300, -479, -479, -479, 770, 109, 51, -479, 29, -479, + -479, -479, -479, 137, 157, -479, -479, -479, -479, -479, + -479, 129, -479, 221, 54, 71, 210, -54, 124, -2, + -36, 182, 172, 92, 217, -15, 224, 148, 49, 297, + -479, -479, 319, 319, -479, 1104, 285, 328, 330, 348, + 355, -479, 254, 291, -40, -479, -479, -479, -479, -479, + -479, 327, 379, 595, -479, -8, -479, -479, -479, -479, + -479, 11, 200, -479, -479, 360, 1212, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, -479, 944, 341, 201, 95, 316, 1104, 95, + 1104, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, 0, 334, -479, 367, -479, 199, 218, 208, 305, + 308, -11, -479, 230, -479, -479, -479, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, 216, -479, 227, -479, 350, -479, -479, 1104, + 388, 385, 1104, 234, 235, 237, 238, -479, -479, 383, + 8, -479, -479, -62, -479, -479, 353, 256, 257, 263, + 264, 212, 267, 275, 277, 278, 279, 198, 280, 46, + -479, 286, 76, 380, 384, 345, -479, -479, -479, 351, + -479, -25, -44, 38, -479, -16, 386, -479, 207, 392, + -479, -479, 124, -479, -479, -479, 393, -479, 394, -479, + 346, -479, -479, -479, -479, 361, -479, 301, -479, 124, + -479, 363, -479, -479, -479, -479, 400, 329, 402, 403, + 354, 354, -479, 1104, 405, 406, 407, 409, 376, 377, + -479, 378, 397, -479, -479, -479, -479, 447, -479, 414, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, 417, 325, -479, -479, -479, -479, -479, -479, 13, + -479, -479, -479, 10, 489, 201, -479, -479, -479, -479, + -479, -479, 381, 206, -479, 490, 381, -479, -479, 491, + 3, -479, 319, -479, -479, -479, 120, 337, 338, 340, + 147, -14, 2, 1104, -479, -479, -479, -479, -479, 408, + 284, 439, -7, -479, -479, -479, 342, 136, 136, 136, + 136, -27, 343, 347, 349, 352, 356, 357, 358, 359, + 364, 365, -479, 136, 136, 136, 136, 136, 366, 368, + 136, -479, 443, 444, -479, -479, -479, 470, 471, -479, + 370, -479, -479, -479, -479, 410, 124, -479, 124, 41, + -479, 124, -479, -479, -479, 451, -479, 124, -479, -479, + -479, -479, -479, -479, -69, 427, -479, -479, 464, 387, + -479, -479, 468, -479, -479, -479, 532, 535, 389, -479, + -479, -479, -479, -479, -479, -479, -479, 390, -479, 382, + 169, 95, -479, -479, -29, -479, 1104, 1104, -479, 95, + -9, 95, 354, -479, -479, -479, -479, 120, 120, 120, + 416, 506, 515, -479, -479, -479, -479, -479, 7, 110, + -479, 429, 431, -479, -479, -479, 432, 538, -53, 442, + 136, -479, -479, -479, -479, -479, -479, 136, 550, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, -13, + -479, -479, -479, -479, -479, -479, 450, 452, -479, -479, + -479, -479, 574, 76, -479, -479, -479, 124, -479, -479, + -479, -479, 521, 522, 460, 486, 559, -479, 560, 561, + 26, 562, -479, -479, -479, -479, 563, -479, 1070, -479, + 569, 70, -479, -479, -479, -479, -479, 120, 472, 473, + -479, 572, 2, -479, 1104, -479, -479, 474, 475, -479, + -479, -479, -479, -5, -4, -3, -1, -479, 479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + 212, 9, 15, 17, 18, 19, 140, 589, 20, -479, + -479, -479, -479, -479, 578, 481, -479, -479, -479, -479, + -479, -479, 480, 1104, -479, -479, 111, -479, -479, 120, + 120, -479, -479, -479, -479, -479, 21, -479, -479, -479, + -479, 136, -479, -479, -479, -479, -479, -479, 482, 483, + 484, 485, 487, 488, 492, 495, 496, -479, -479, 585, + -479, -479, 587, -479, -479, -479, -479, -479, 136, 136, + -59, 508, 588, 633, 140, 136, 652, -479, -479, 510, + 511, 514, -479, -479, 516, 513, 518, -479, -479, 42, + -479, -479, -479, 136, 136, -479, 588, -479, 136, 517, + -479, -479, 519, -479, -479 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = +{ + -479, -479, -479, 607, 668, 571, 1, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, 534, -479, -479, -479, -479, -479, -479, -287, + -60, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, -479, -479, 605, 632, -479, 126, -146, -281, + -479, -134, 138, -479, -479, 128, 131, 141, 151, 164, + -479, 339, -479, -455, 577, -479, -479, -479, 28, -479, + -479, 12, -479, -227, 103, -402, -478, -381, -479, -479, + -479, -479, 494, -479, -479, 253, 493, -479, -479, -479, + -479, -479, -479, 290, -55, 436, -479, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, 174, + -479, -479, 621, 369, -479, 97, -479, -10 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -435 +static const yytype_int16 yytable[] = +{ + 214, 97, 273, 274, 534, 357, 513, 514, 515, 516, + 290, 220, 221, 301, 454, 318, 318, 3, 4, 5, + 6, 7, 530, 531, 10, 360, 535, -92, 609, 538, + -93, 588, 574, 575, 576, 97, 647, 648, 649, 597, + 650, -167, 316, 24, 24, 25, 26, 27, 28, 29, + 653, 494, 223, 224, 552, 565, 654, 691, 655, 656, + 657, 667, 676, -434, 473, 214, 174, 172, 433, 215, + 178, 216, 225, 369, 428, 318, 296, 508, 310, 473, + 269, 311, 275, 179, 180, 429, 495, 411, 412, 413, + 269, 580, 226, 426, 97, 39, 340, 219, 278, 272, + 318, 496, 320, 24, 279, 280, 333, 253, 254, 269, + 629, 509, 553, 434, 217, 175, 171, 176, 435, 269, + 497, 297, 638, 605, 606, 692, 227, 276, 24, 592, + 414, 589, 312, 289, 97, 417, 592, 418, 599, 600, + 601, 602, 603, 604, 630, 222, 607, 608, 184, 185, + 186, 187, 188, 189, 566, 517, 431, 190, 518, 547, + 191, 192, 193, 194, 195, 196, 181, 252, 610, 370, + -167, 317, 269, 677, 570, 269, 610, 610, 610, 197, + 610, 265, 498, 343, 674, 675, 343, 581, 266, 473, + 610, 319, -434, 343, 468, 573, 610, 470, 610, 610, + 610, 610, 610, 268, 483, 269, 427, 430, 432, 375, + 284, 255, 378, 438, 285, 198, 199, 440, 200, 484, + 511, 256, 201, 202, 512, 203, 707, 204, 205, 325, + 708, 490, 326, 334, 446, 356, 335, 358, 485, 206, + 658, 257, 327, 207, 491, 492, 336, 208, 209, 258, + 259, 210, 328, 659, 660, 661, 337, 662, 269, 184, + 185, 186, 187, 188, 189, 329, 282, 211, 190, 338, + 592, 191, 192, 193, 194, 195, 196, 476, 231, 232, + 233, 234, 235, 699, 364, 365, 593, 594, 595, 596, + 197, 582, 672, 455, 583, 673, 391, 689, 690, 293, + 294, 295, 482, 611, 612, 613, 712, 614, 615, 408, + 409, 618, 392, 393, 394, 395, 283, 396, 397, 398, + 399, 400, 709, 710, 298, 401, 198, 199, 271, 200, + 503, 504, 505, 201, 202, 287, 203, 564, 204, 205, + 437, 269, 291, 478, 469, 569, 299, 572, 261, 262, + 206, 263, 343, 563, 207, 304, 303, 305, 208, 209, + 306, 307, 210, 501, 646, 318, 3, 4, 5, 6, + 7, 545, 308, 546, 548, 309, 549, 313, 211, 314, + 331, 30, 551, 236, 343, 354, 361, 362, 363, 367, + 366, 477, 368, 24, 25, 26, 27, 28, 29, 372, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 371, 373, 248, 374, 376, 377, 379, 380, 1, + 381, 382, 383, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 386, 387, 388, + 16, 17, 18, 19, 20, 389, 390, 21, 22, 403, + 23, 24, 25, 26, 27, 28, 29, 404, 30, 405, + 406, 407, 410, 424, 422, 416, 567, 568, 423, 425, + 436, 31, 32, 33, 34, 35, 439, 441, 442, 444, + 278, 447, 445, 36, 448, 449, 450, 451, 452, 456, + 457, 458, 621, 459, 460, 461, 462, 464, 465, 37, + 38, 466, 39, 40, 41, 42, 467, 43, 44, 45, + 46, 47, 48, 49, 50, 463, 471, 479, 481, 487, + 488, 474, 489, 507, 510, 519, 502, 539, 540, 520, + 541, 521, 285, 542, 522, 550, 555, 51, 523, 524, + 525, 526, 52, 53, 54, 554, 527, 528, 536, 55, + 537, 543, 557, 56, 57, 58, 59, 60, 634, 558, + 61, 62, 559, 63, 64, 65, 562, 66, 67, 556, + 561, 560, 68, 69, 643, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 578, 85, 86, 87, 88, 89, 90, 91, 577, 579, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 584, 585, 586, 16, 17, 18, + 19, 20, 587, 671, 21, 22, 590, 23, 24, 25, + 26, 27, 28, 29, 598, 30, 616, 619, 617, 622, + 623, 624, 625, 626, 627, 628, 631, 632, 31, 32, + 33, 34, 35, 635, 639, 640, 641, 665, 644, 645, + 36, 651, 668, 669, 670, 678, 679, 680, 681, 687, + 682, 688, 694, 684, 697, 683, 37, 38, 685, 39, + 40, 41, 42, 686, 43, 44, 45, 46, 47, 48, + 49, 50, 693, 700, 701, 702, 703, 705, 704, 706, + 315, 713, 251, 714, 341, 359, 324, 302, 642, 637, + 493, 342, 698, 652, 51, 544, 443, 620, 711, 52, + 53, 54, 330, 384, 0, 480, 55, 385, 0, 0, + 56, 57, 58, 59, 60, 0, 0, 61, 62, 0, + 63, 64, 65, 0, 66, 67, 0, 0, 0, 68, + 69, 0, 70, 71, 72, 73, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 0, 85, 86, + 87, 88, 89, 90, 91, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, + 0, 0, 16, 17, 18, 19, 20, 0, 0, 21, + 22, 0, 23, 24, 25, 26, 27, 28, 29, 0, + 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 31, 32, 33, 250, 35, 0, 0, + 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 37, 38, 0, 39, 40, 41, 42, 0, 43, + 44, 45, 46, 47, 48, 49, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, + 0, 0, 0, 0, 52, 53, 54, 0, 0, 0, + 0, 55, 0, 0, 0, 56, 57, 58, 59, 60, + 0, 0, 61, 62, 0, 63, 64, 65, 0, 66, + 67, 0, 0, 0, 68, 69, 0, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 0, 85, 86, 87, 88, 89, 90, 2, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 0, 0, 0, 16, 17, 18, 19, + 20, 0, 0, 21, 22, 0, 23, 24, 25, 26, + 27, 28, 29, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 31, 32, 33, + 250, 35, 0, 0, 0, 0, 0, 0, 0, 36, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 37, 38, 0, 39, 40, + 41, 42, 0, 43, 44, 45, 46, 47, 48, 49, + 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 51, 0, 0, 0, 0, 52, 53, + 54, 0, 0, 0, 0, 55, 0, 0, 0, 56, + 57, 58, 59, 60, 0, 0, 61, 62, 0, 63, + 64, 65, 0, 66, 67, 0, 0, 0, 68, 69, + 0, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 0, 85, 86, 87, + 88, 89, 90, 184, 185, 186, 187, 188, 189, 0, + 0, 0, 190, 0, 0, 191, 192, 193, 194, 195, + 196, 633, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 197, 0, 0, 184, 185, 186, + 187, 188, 189, 0, 0, 0, 190, 0, 0, 191, + 192, 193, 194, 195, 196, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 197, 0, + 198, 199, 0, 200, 0, 0, 0, 201, 202, 0, + 203, 0, 204, 205, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 206, 0, 0, 0, 207, 0, + 0, 0, 208, 209, 198, 199, 210, 200, 0, 0, + 0, 201, 202, 0, 203, 0, 204, 205, 0, 0, + 0, 0, 211, 0, 0, 0, 0, 0, 206, 0, + 0, 0, 207, 0, 0, 0, 208, 209, 0, 0, + 210, 0, 0, 0, 0, 184, 185, 186, 187, 188, + 189, 0, 0, 0, 190, 0, 211, 191, 192, 193, + 194, 195, 196, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 339, 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, 198, 199, 0, 200, 0, 0, 0, 201, + 202, 0, 203, 0, 204, 205, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 206, 0, 0, 0, + 207, 0, 0, 0, 208, 209, 0, 0, 210, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 211 +}; + +static const yytype_int16 yycheck[] = +{ + 10, 0, 57, 58, 406, 139, 387, 388, 389, 390, + 65, 21, 22, 73, 301, 5, 5, 6, 7, 8, + 9, 10, 403, 404, 13, 171, 407, 27, 41, 410, + 27, 84, 487, 488, 489, 34, 41, 41, 41, 517, + 41, 50, 50, 33, 33, 34, 35, 36, 37, 38, + 41, 49, 44, 45, 123, 84, 41, 116, 41, 41, + 41, 41, 41, 50, 345, 75, 19, 129, 84, 19, + 84, 21, 64, 84, 118, 5, 27, 84, 118, 360, + 134, 121, 84, 97, 98, 129, 84, 41, 42, 43, + 134, 84, 84, 118, 93, 84, 106, 29, 134, 153, + 5, 99, 101, 33, 140, 141, 105, 56, 57, 134, + 84, 118, 181, 129, 64, 68, 80, 70, 134, 134, + 118, 72, 577, 525, 526, 184, 118, 129, 33, 510, + 84, 184, 172, 148, 133, 59, 517, 61, 519, 520, + 521, 522, 523, 524, 118, 29, 527, 528, 53, 54, + 55, 56, 57, 58, 183, 182, 118, 62, 185, 118, + 65, 66, 67, 68, 69, 70, 180, 58, 181, 180, + 179, 179, 134, 651, 183, 134, 181, 181, 181, 84, + 181, 127, 180, 183, 639, 640, 183, 180, 134, 470, + 181, 180, 179, 183, 184, 482, 181, 343, 181, 181, + 181, 181, 181, 132, 84, 134, 261, 262, 263, 219, + 118, 182, 222, 268, 122, 120, 121, 272, 123, 99, + 84, 84, 127, 128, 88, 130, 184, 132, 133, 101, + 188, 84, 101, 105, 289, 138, 105, 140, 118, 144, + 100, 84, 101, 148, 97, 98, 105, 152, 153, 120, + 121, 156, 101, 113, 114, 115, 105, 117, 134, 53, + 54, 55, 56, 57, 58, 101, 84, 172, 62, 105, + 651, 65, 66, 67, 68, 69, 70, 71, 25, 26, + 27, 28, 29, 685, 66, 67, 513, 514, 515, 516, + 84, 181, 181, 303, 184, 184, 84, 678, 679, 151, + 152, 153, 362, 530, 531, 532, 708, 534, 535, 111, + 112, 538, 100, 101, 102, 103, 144, 105, 106, 107, + 108, 109, 703, 704, 27, 113, 120, 121, 118, 123, + 46, 47, 48, 127, 128, 118, 130, 471, 132, 133, + 133, 134, 118, 353, 343, 479, 27, 481, 127, 128, + 144, 130, 183, 184, 148, 27, 71, 27, 152, 153, + 12, 6, 156, 373, 591, 5, 6, 7, 8, 9, + 10, 426, 118, 428, 429, 84, 431, 50, 172, 0, + 180, 40, 437, 83, 183, 69, 52, 20, 189, 84, + 182, 185, 84, 33, 34, 35, 36, 37, 38, 183, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 181, 185, 113, 64, 27, 31, 183, 183, 1, + 183, 183, 39, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 84, 182, 182, + 22, 23, 24, 25, 26, 182, 182, 29, 30, 182, + 32, 33, 34, 35, 36, 37, 38, 182, 40, 182, + 182, 182, 182, 118, 84, 179, 476, 477, 84, 118, + 84, 53, 54, 55, 56, 57, 84, 84, 84, 118, + 134, 118, 181, 65, 84, 156, 84, 84, 134, 84, + 84, 84, 547, 84, 118, 118, 118, 50, 84, 81, + 82, 84, 84, 85, 86, 87, 181, 89, 90, 91, + 92, 93, 94, 95, 96, 118, 27, 27, 27, 182, + 182, 140, 182, 84, 182, 182, 118, 84, 84, 182, + 60, 182, 122, 62, 182, 84, 72, 119, 182, 182, + 182, 182, 124, 125, 126, 118, 182, 182, 182, 131, + 182, 181, 84, 135, 136, 137, 138, 139, 568, 27, + 142, 143, 27, 145, 146, 147, 184, 149, 150, 182, + 180, 182, 154, 155, 584, 157, 158, 159, 160, 161, + 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, + 84, 173, 174, 175, 176, 177, 178, 179, 182, 84, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 185, 184, 184, 22, 23, 24, + 25, 26, 84, 633, 29, 30, 184, 32, 33, 34, + 35, 36, 37, 38, 84, 40, 186, 63, 186, 118, + 118, 181, 156, 84, 84, 84, 84, 84, 53, 54, + 55, 56, 57, 84, 182, 182, 84, 68, 184, 184, + 65, 182, 84, 182, 184, 183, 183, 183, 183, 84, + 183, 84, 84, 181, 41, 187, 81, 82, 183, 84, + 85, 86, 87, 187, 89, 90, 91, 92, 93, 94, + 95, 96, 184, 41, 184, 184, 182, 184, 182, 181, + 93, 184, 34, 184, 133, 171, 101, 75, 582, 571, + 371, 134, 684, 610, 119, 425, 280, 543, 706, 124, + 125, 126, 101, 230, -1, 356, 131, 233, -1, -1, + 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, + 145, 146, 147, -1, 149, 150, -1, -1, -1, 154, + 155, -1, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, -1, 173, 174, + 175, 176, 177, 178, 179, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, + -1, -1, 22, 23, 24, 25, 26, -1, -1, 29, + 30, -1, 32, 33, 34, 35, 36, 37, 38, -1, + 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 53, 54, 55, 56, 57, -1, -1, + -1, -1, -1, -1, -1, 65, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 81, 82, -1, 84, 85, 86, 87, -1, 89, + 90, 91, 92, 93, 94, 95, 96, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 119, + -1, -1, -1, -1, 124, 125, 126, -1, -1, -1, + -1, 131, -1, -1, -1, 135, 136, 137, 138, 139, + -1, -1, 142, 143, -1, 145, 146, 147, -1, 149, + 150, -1, -1, -1, 154, 155, -1, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 171, -1, 173, 174, 175, 176, 177, 178, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, -1, -1, -1, 22, 23, 24, 25, + 26, -1, -1, 29, 30, -1, 32, 33, 34, 35, + 36, 37, 38, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 53, 54, 55, + 56, 57, -1, -1, -1, -1, -1, -1, -1, 65, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 81, 82, -1, 84, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, + 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 119, -1, -1, -1, -1, 124, 125, + 126, -1, -1, -1, -1, 131, -1, -1, -1, 135, + 136, 137, 138, 139, -1, -1, 142, 143, -1, 145, + 146, 147, -1, 149, 150, -1, -1, -1, 154, 155, + -1, 157, 158, 159, 160, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 170, 171, -1, 173, 174, 175, + 176, 177, 178, 53, 54, 55, 56, 57, 58, -1, + -1, -1, 62, -1, -1, 65, 66, 67, 68, 69, + 70, 71, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 84, -1, -1, 53, 54, 55, + 56, 57, 58, -1, -1, -1, 62, -1, -1, 65, + 66, 67, 68, 69, 70, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 84, -1, + 120, 121, -1, 123, -1, -1, -1, 127, 128, -1, + 130, -1, 132, 133, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 144, -1, -1, -1, 148, -1, + -1, -1, 152, 153, 120, 121, 156, 123, -1, -1, + -1, 127, 128, -1, 130, -1, 132, 133, -1, -1, + -1, -1, 172, -1, -1, -1, -1, -1, 144, -1, + -1, -1, 148, -1, -1, -1, 152, 153, -1, -1, + 156, -1, -1, -1, -1, 53, 54, 55, 56, 57, + 58, -1, -1, -1, 62, -1, 172, 65, 66, 67, + 68, 69, 70, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 84, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 120, 121, -1, 123, -1, -1, -1, 127, + 128, -1, 130, -1, 132, 133, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 144, -1, -1, -1, + 148, -1, -1, -1, 152, 153, -1, -1, 156, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 172 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint16 yystos[] = +{ + 0, 1, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 22, 23, 24, 25, + 26, 29, 30, 32, 33, 34, 35, 36, 37, 38, + 40, 53, 54, 55, 56, 57, 65, 81, 82, 84, + 85, 86, 87, 89, 90, 91, 92, 93, 94, 95, + 96, 119, 124, 125, 126, 131, 135, 136, 137, 138, + 139, 142, 143, 145, 146, 147, 149, 150, 154, 155, + 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, + 167, 168, 169, 170, 171, 173, 174, 175, 176, 177, + 178, 179, 191, 192, 193, 194, 195, 196, 197, 198, + 199, 205, 206, 207, 208, 209, 210, 213, 214, 215, + 216, 217, 218, 221, 222, 223, 224, 225, 226, 227, + 228, 229, 230, 231, 232, 233, 234, 245, 246, 247, + 248, 249, 250, 254, 255, 268, 269, 270, 271, 273, + 274, 280, 281, 282, 286, 288, 289, 290, 292, 294, + 295, 296, 297, 299, 300, 301, 302, 303, 305, 306, + 308, 309, 310, 311, 312, 313, 314, 316, 320, 321, + 322, 80, 129, 272, 19, 68, 70, 315, 84, 97, + 98, 180, 251, 252, 53, 54, 55, 56, 57, 58, + 62, 65, 66, 67, 68, 69, 70, 84, 120, 121, + 123, 127, 128, 130, 132, 133, 144, 148, 152, 153, + 156, 172, 235, 326, 327, 19, 21, 64, 200, 29, + 327, 327, 29, 44, 45, 64, 84, 118, 275, 276, + 277, 275, 275, 275, 275, 275, 83, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 113, 256, + 56, 194, 58, 56, 57, 182, 84, 84, 120, 121, + 287, 127, 128, 130, 293, 127, 134, 291, 132, 134, + 284, 118, 153, 284, 284, 84, 129, 298, 134, 140, + 141, 285, 84, 144, 118, 122, 283, 118, 304, 148, + 284, 118, 307, 151, 152, 153, 27, 72, 27, 27, + 220, 220, 235, 71, 27, 27, 12, 6, 118, 84, + 118, 121, 172, 50, 0, 193, 50, 179, 5, 180, + 196, 201, 203, 204, 234, 245, 246, 247, 248, 249, + 322, 180, 202, 196, 245, 246, 247, 248, 249, 84, + 327, 195, 254, 183, 212, 238, 239, 240, 196, 241, + 242, 324, 325, 327, 69, 279, 325, 241, 325, 212, + 238, 52, 20, 189, 66, 67, 182, 84, 84, 84, + 180, 181, 183, 185, 64, 327, 27, 31, 327, 183, + 183, 183, 183, 39, 276, 272, 84, 182, 182, 182, + 182, 84, 100, 101, 102, 103, 105, 106, 107, 108, + 109, 113, 264, 182, 182, 182, 182, 182, 111, 112, + 182, 41, 42, 43, 84, 257, 179, 59, 61, 317, + 318, 319, 84, 84, 118, 118, 118, 284, 118, 129, + 284, 118, 284, 84, 129, 134, 84, 133, 284, 84, + 284, 84, 84, 285, 118, 181, 284, 118, 84, 156, + 84, 84, 134, 219, 219, 327, 84, 84, 84, 84, + 118, 118, 118, 118, 50, 84, 84, 181, 184, 196, + 238, 27, 211, 239, 140, 323, 71, 185, 327, 27, + 323, 27, 220, 84, 99, 118, 253, 182, 182, 182, + 84, 97, 98, 251, 49, 84, 99, 118, 180, 236, + 237, 327, 118, 46, 47, 48, 278, 84, 84, 118, + 182, 84, 88, 267, 267, 267, 267, 182, 185, 182, + 182, 182, 182, 182, 182, 182, 182, 182, 182, 263, + 267, 267, 265, 267, 265, 267, 182, 182, 267, 84, + 84, 60, 62, 181, 283, 284, 284, 118, 284, 284, + 84, 284, 123, 181, 118, 72, 182, 84, 27, 27, + 182, 180, 184, 184, 241, 84, 183, 327, 327, 241, + 183, 243, 241, 219, 253, 253, 253, 182, 84, 84, + 84, 180, 181, 184, 185, 184, 184, 84, 84, 184, + 184, 266, 267, 263, 263, 263, 263, 266, 84, 267, + 267, 267, 267, 267, 267, 265, 265, 267, 267, 41, + 181, 263, 263, 263, 263, 263, 186, 186, 263, 63, + 319, 284, 118, 118, 181, 156, 84, 84, 84, 84, + 118, 84, 84, 71, 327, 84, 244, 242, 253, 182, + 182, 84, 237, 327, 184, 184, 263, 41, 41, 41, + 41, 182, 264, 41, 41, 41, 41, 41, 100, 113, + 114, 115, 117, 258, 259, 68, 260, 41, 84, 182, + 184, 327, 181, 184, 253, 253, 41, 266, 183, 183, + 183, 183, 183, 187, 181, 183, 187, 84, 84, 267, + 267, 116, 184, 184, 84, 261, 262, 41, 258, 265, + 41, 184, 184, 182, 182, 184, 181, 184, 188, 267, + 267, 261, 265, 184, 184 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (&yylloc, result, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) +#else +# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value, Location, result); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, ObProxyParseResult* result) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, result) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; + YYLTYPE const * const yylocationp; + ObProxyParseResult* result; +#endif +{ + if (!yyvaluep) + return; + YYUSE (yylocationp); + YYUSE (result); +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, ObProxyParseResult* result) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, result) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; + YYLTYPE const * const yylocationp; + ObProxyParseResult* result; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + YY_LOCATION_PRINT (yyoutput, *yylocationp); + YYFPRINTF (yyoutput, ": "); + yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, result); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +#else +static void +yy_stack_print (yybottom, yytop) + yytype_int16 *yybottom; + yytype_int16 *yytop; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, ObProxyParseResult* result) +#else +static void +yy_reduce_print (yyvsp, yylsp, yyrule, result) + YYSTYPE *yyvsp; + YYLTYPE *yylsp; + int yyrule; + ObProxyParseResult* result; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + , &(yylsp[(yyi + 1) - (yynrhs)]) , result); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, yylsp, Rule, result); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, ObProxyParseResult* result) +#else +static void +yydestruct (yymsg, yytype, yyvaluep, yylocationp, result) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; + YYLTYPE *yylocationp; + ObProxyParseResult* result; +#endif +{ + YYUSE (yyvaluep); + YYUSE (yylocationp); + YYUSE (result); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + +/* Prevent warnings from -Wmissing-prototypes. */ +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (ObProxyParseResult* result); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + + + +/*-------------------------. +| yyparse or yypush_parse. | +`-------------------------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (ObProxyParseResult* result) +#else +int +yyparse (result) + ObProxyParseResult* result; +#endif +#endif +{ +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Location data for the lookahead symbol. */ +YYLTYPE yylloc; + + /* Number of syntax errors so far. */ + int yynerrs; + + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + `yyss': related to states. + `yyvs': related to semantic values. + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + /* The location stack. */ + YYLTYPE yylsa[YYINITDEPTH]; + YYLTYPE *yyls; + YYLTYPE *yylsp; + + /* The locations where the error started and ended. */ + YYLTYPE yyerror_range[2]; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + YYLTYPE yyloc; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yytoken = 0; + yyss = yyssa; + yyvs = yyvsa; + yyls = yylsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + yyssp = yyss; + yyvsp = yyvs; + yylsp = yyls; + +#if YYLTYPE_IS_TRIVIAL + /* Initialize the default location before parsing starts. */ + yylloc.first_line = yylloc.last_line = 1; + yylloc.first_column = yylloc.last_column = 1; +#endif + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + YYLTYPE *yyls1 = yyls; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yyls1, yysize * sizeof (*yylsp), + &yystacksize); + + yyls = yyls1; + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); + YYSTACK_RELOCATE (yyls_alloc, yyls); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + yylsp = yyls + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + *++yylsp = yylloc; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + /* Default location. */ + YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: + + { HANDLE_ACCEPT(); ;} + break; + + case 3: + + { HANDLE_ERROR_ACCEPT(); ;} + break; + + case 6: + + { handle_stmt_end(result); HANDLE_ACCEPT(); ;} + break; + + case 7: + + { handle_stmt_end(result); ;} + break; + + case 8: + + { handle_stmt_end(result); HANDLE_ACCEPT(); ;} + break; + + case 9: + + { handle_stmt_end(result); ;} + break; + + case 10: + + { handle_stmt_end(result); HANDLE_ACCEPT(); ;} + break; + + case 11: + + { handle_stmt_end(result); ;} + break; + + case 14: + + {;} + break; + + case 15: + + {;} + break; + + case 16: + + {;} + break; + + case 17: + + {;} + break; + + case 18: + + {;} + break; + + case 19: + + {;} + break; + + case 20: + + {;} + break; + + case 21: + + {;} + break; + + case 22: + + {;} + break; + + case 23: + + {;} + break; + + case 24: + + {;} + break; + + case 25: + + {;} + break; + + case 26: + + {;} + break; + + case 27: + + {;} + break; + + case 28: + + {;} + break; + + case 29: + + {;} + break; + + case 30: + + {;} + break; + + case 31: + + {;} + break; + + case 32: + + {;} + break; + + case 33: + + {;} + break; + + case 34: + + {;} + break; + + case 35: + + {;} + break; + + case 36: + + {;} + break; + + case 37: + + {;} + break; + + case 38: + + { result->cur_stmt_type_ = OBPROXY_T_OTHERS; ;} + break; + + case 48: + + { result->cur_stmt_type_ = OBPROXY_T_CREATE; ;} + break; + + case 49: + + { result->cur_stmt_type_ = OBPROXY_T_DROP; ;} + break; + + case 50: + + { result->cur_stmt_type_ = OBPROXY_T_ALTER; ;} + break; + + case 51: + + { result->cur_stmt_type_ = OBPROXY_T_TRUNCATE; ;} + break; + + case 52: + + { result->cur_stmt_type_ = OBPROXY_T_RENAME; ;} + break; + + case 54: + + { result->sub_stmt_type_ = OBPROXY_T_SUB_CREATE_TABLE; ;} + break; + + case 55: + + { result->sub_stmt_type_ = OBPROXY_T_SUB_CREATE_INDEX; ;} + break; + + case 56: + + { result->sub_stmt_type_ = OBPROXY_T_SUB_CREATE_INDEX; ;} + break; + + case 57: + + {;} + break; + + case 58: + + {;} + break; + + case 59: + + {;} + break; + + case 60: + + {;} + break; + + case 61: + + {;} + break; + + case 62: + + {;} + break; + + case 63: + + {;} + break; + + case 64: + + {;} + break; + + case 65: + + { + ObProxyTextPsParseNode *node = NULL; + malloc_parse_node(node); + node->str_value_ = (yyvsp[(2) - (2)].str); + add_text_ps_node(result->text_ps_parse_info_, node); + ;} + break; + + case 66: + + { + ObProxyTextPsParseNode *node = NULL; + malloc_parse_node(node); + node->str_value_ = (yyvsp[(4) - (4)].str); + add_text_ps_node(result->text_ps_parse_info_, node); + ;} + break; + + case 67: + + { + ObProxyTextPsParseNode *node = NULL; + malloc_parse_node(node); + node->str_value_ = (yyvsp[(2) - (2)].str); + add_text_ps_node(result->text_ps_parse_info_, node); + ;} + break; + + case 70: + + { + result->text_ps_inner_stmt_type_ = OBPROXY_T_TEXT_PS_PREPARE; + result->text_ps_name_ = (yyvsp[(2) - (3)].str); + ;} + break; + + case 71: + + { + result->cur_stmt_type_ = OBPROXY_T_TEXT_PS_EXECUTE; + result->text_ps_name_ = (yyvsp[(2) - (2)].str); + ;} + break; + + case 72: + + { + result->cur_stmt_type_ = OBPROXY_T_TEXT_PS_EXECUTE; + result->text_ps_name_ = (yyvsp[(2) - (3)].str); + ;} + break; + + case 73: + + { + ;} + break; + + case 74: + + { + ;} + break; + + case 75: + + { + result->cur_stmt_type_ = OBPROXY_T_TEXT_PS_DROP; + result->text_ps_name_ = (yyvsp[(3) - (3)].str); + ;} + break; + + case 76: + + { + result->cur_stmt_type_ = OBPROXY_T_TEXT_PS_DROP; + result->text_ps_name_ = (yyvsp[(3) - (3)].str); + ;} + break; + + case 77: + + { result->cur_stmt_type_ = OBPROXY_T_GRANT; ;} + break; + + case 78: + + { result->cur_stmt_type_ = OBPROXY_T_REVOKE; ;} + break; + + case 79: + + { result->cur_stmt_type_ = OBPROXY_T_ANALYZE; ;} + break; + + case 80: + + { result->cur_stmt_type_ = OBPROXY_T_PURGE; ;} + break; + + case 81: + + { result->cur_stmt_type_ = OBPROXY_T_FLASHBACK; ;} + break; + + case 82: + + { result->cur_stmt_type_ = OBPROXY_T_COMMENT; ;} + break; + + case 83: + + { result->cur_stmt_type_ = OBPROXY_T_AUDIT; ;} + break; + + case 84: + + { result->cur_stmt_type_ = OBPROXY_T_NOAUDIT; ;} + break; + + case 87: + + {;} + break; + + case 88: + + {;} + break; + + case 89: + + {;} + break; + + case 94: + + { result->cur_stmt_type_ = OBPROXY_T_SELECT_TX_RO; ;} + break; + + case 98: + + { result->col_name_ = (yyvsp[(3) - (3)].str); ;} + break; + + case 99: + + {;} + break; + + case 100: + + {;} + break; + + case 101: + + {;} + break; + + case 102: + + {;} + break; + + case 103: + + {;} + break; + + case 104: + + {;} + break; + + case 105: + + {;} + break; + + case 106: + + {;} + break; + + case 107: + + { result->sub_stmt_type_ = OBPROXY_T_SUB_SELECT_DATABASE; ;} + break; + + case 108: + + { result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_DATABASES; ;} + break; + + case 109: + + {;} + break; + + case 110: + + {;} + break; + + case 111: + + {;} + break; + + case 112: + + {;} + break; + + case 113: + + { result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_CREATE_TABLE; ;} + break; + + case 114: + + { + result->table_info_.table_name_ = (yyvsp[(2) - (2)].str); + result->cur_stmt_type_ = OBPROXY_T_DESC; + result->sub_stmt_type_ = OBPROXY_T_SUB_DESC_TABLE; + ;} + break; + + case 115: + + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_COLUMNS; + result->table_info_.table_name_ = (yyvsp[(3) - (3)].str); + ;} + break; + + case 116: + + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_COLUMNS; + result->table_info_.table_name_ = (yyvsp[(3) - (5)].str); + result->table_info_.database_name_ = (yyvsp[(5) - (5)].str); + ;} + break; + + case 117: + + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_INDEX; + result->table_info_.table_name_ = (yyvsp[(3) - (3)].str); + ;} + break; + + case 118: + + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_INDEX; + result->table_info_.table_name_ = (yyvsp[(3) - (5)].str); + result->table_info_.database_name_ = (yyvsp[(5) - (5)].str); + ;} + break; + + case 119: + + {;} + break; + + case 120: + + { result->table_info_.table_name_ = (yyvsp[(2) - (2)].str); ;} + break; + + case 121: + + {;} + break; + + case 122: + + { result->table_info_.database_name_ = (yyvsp[(2) - (2)].str); ;} + break; + + case 123: + + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TABLES; + ;} + break; + + case 124: + + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_FULL_TABLES; + ;} + break; + + case 125: + + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TABLE_STATUS; + ;} + break; + + case 126: + + { result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_DB_VERSION; ;} + break; + + case 127: + + { result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_ELASTIC_ID; ;} + break; + + case 128: + + { + SET_ICMD_ONE_STRING((yyvsp[(3) - (3)].str)); + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_ELASTIC_ID; + ;} + break; + + case 129: + + { + SET_ICMD_SECOND_STRING((yyvsp[(5) - (5)].str)); + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_ELASTIC_ID; + ;} + break; + + case 130: + + { + SET_ICMD_ONE_STRING((yyvsp[(3) - (7)].str)); + SET_ICMD_SECOND_STRING((yyvsp[(7) - (7)].str)); + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_ELASTIC_ID; + ;} + break; + + case 131: + + { result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TOPOLOGY; ;} + break; + + case 132: + + { + result->table_info_.table_name_ = (yyvsp[(3) - (3)].str); + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TOPOLOGY; + ;} + break; + + case 133: + + { result->cur_stmt_type_ = OBPROXY_T_SELECT_ROUTE_ADDR; ;} + break; + + case 134: + + { + result->cur_stmt_type_ = OBPROXY_T_SET_ROUTE_ADDR; + result->cmd_info_.integer_[0] = (yyvsp[(3) - (3)].num); + ;} + break; + + case 135: + + {;} + break; + + case 136: + + {;} + break; + + case 137: + + {;} + break; + + case 138: + + {;} + break; + + case 139: + + {;} + break; + + case 140: + + {;} + break; + + case 142: + + { + result->table_info_.table_name_ = (yyvsp[(1) - (1)].str); + ;} + break; + + case 143: + + { + result->table_info_.package_name_ = (yyvsp[(1) - (3)].str); + result->table_info_.table_name_ = (yyvsp[(3) - (3)].str); + ;} + break; + + case 144: + + { + result->table_info_.database_name_ = (yyvsp[(1) - (5)].str); + result->table_info_.package_name_ = (yyvsp[(3) - (5)].str); + result->table_info_.table_name_ = (yyvsp[(5) - (5)].str); + ;} + break; + + case 145: + + { + result->call_parse_info_.node_count_ = 0; + ;} + break; + + case 146: + + { + result->call_parse_info_.node_count_ = 0; + add_call_node(result->call_parse_info_, (yyvsp[(1) - (1)].node)); + ;} + break; + + case 147: + + { + add_call_node(result->call_parse_info_, (yyvsp[(3) - (3)].node)); + ;} + break; + + case 148: + + { + malloc_call_node((yyval.node), CALL_TOKEN_STR_VAL); + (yyval.node)->str_value_ = (yyvsp[(1) - (1)].str); + ;} + break; + + case 149: + + { + malloc_call_node((yyval.node), CALL_TOKEN_INT_VAL); + (yyval.node)->int_value_ = (yyvsp[(1) - (1)].num); + ;} + break; + + case 150: + + { + malloc_call_node((yyval.node), CALL_TOKEN_NUMBER_VAL); + (yyval.node)->str_value_ = (yyvsp[(1) - (1)].str); + ;} + break; + + case 151: + + { + malloc_call_node((yyval.node), CALL_TOKEN_USER_VAR); + (yyval.node)->str_value_ = (yyvsp[(2) - (2)].str); + ;} + break; + + case 152: + + { + malloc_call_node((yyval.node), CALL_TOKEN_SYS_VAR); + (yyval.node)->str_value_ = (yyvsp[(3) - (3)].str); + ;} + break; + + case 153: + + { + result->placeholder_list_idx_++; + malloc_call_node((yyval.node), CALL_TOKEN_PLACE_HOLDER); + (yyval.node)->placeholder_idx_ = result->placeholder_list_idx_ - 1; + ;} + break; + + case 167: + + { + handle_stmt_end(result); + HANDLE_ACCEPT(); + ;} + break; + + case 172: + + { + handle_stmt_end(result); + HANDLE_ACCEPT(); + ;} + break; + + case 176: + + { + add_set_var_node(result->set_parse_info_, (yyvsp[(4) - (4)].var_node), (yyvsp[(2) - (4)].str), SET_VAR_USER); + ;} + break; + + case 177: + + { + add_set_var_node(result->set_parse_info_, (yyvsp[(6) - (6)].var_node), (yyvsp[(4) - (6)].str), SET_VAR_SYS); + ;} + break; + + case 178: + + { + add_set_var_node(result->set_parse_info_, (yyvsp[(4) - (4)].var_node), (yyvsp[(2) - (4)].str), SET_VAR_SYS); + ;} + break; + + case 179: + + { + add_set_var_node(result->set_parse_info_, (yyvsp[(5) - (5)].var_node), (yyvsp[(3) - (5)].str), SET_VAR_SYS); + ;} + break; + + case 180: + + { + add_set_var_node(result->set_parse_info_, (yyvsp[(6) - (6)].var_node), (yyvsp[(4) - (6)].str), SET_VAR_SYS); + ;} + break; + + case 181: + + { + add_set_var_node(result->set_parse_info_, (yyvsp[(4) - (4)].var_node), (yyvsp[(2) - (4)].str), SET_VAR_SYS); + ;} + break; + + case 182: + + { + add_set_var_node(result->set_parse_info_, (yyvsp[(3) - (3)].var_node), (yyvsp[(1) - (3)].str), SET_VAR_SYS); + ;} + break; + + case 183: + + { + malloc_set_var_node((yyval.var_node), SET_VALUE_TYPE_STR); + (yyval.var_node)->str_value_ = (yyvsp[(1) - (1)].str); + ;} + break; + + case 184: + + { + malloc_set_var_node((yyval.var_node), SET_VALUE_TYPE_INT); + (yyval.var_node)->int_value_ = (yyvsp[(1) - (1)].num); + ;} + break; + + case 185: + + { + malloc_set_var_node((yyval.var_node), SET_VALUE_TYPE_NUMBER); + (yyval.var_node)->str_value_ = (yyvsp[(1) - (1)].str); + ;} + break; + + case 188: + + {;} + break; + + case 189: + + {;} + break; + + case 190: + + { result->dbmesh_route_info_.tb_idx_str_ = (yyvsp[(4) - (6)].str); ;} + break; + + case 191: + + { result->dbmesh_route_info_.table_name_str_ = (yyvsp[(4) - (6)].str); ;} + break; + + case 192: + + { result->dbmesh_route_info_.group_idx_str_ = (yyvsp[(4) - (6)].str); ;} + break; + + case 193: + + { result->dbmesh_route_info_.es_idx_str_ = (yyvsp[(4) - (6)].str); ;} + break; + + case 194: + + { result->dbmesh_route_info_.testload_str_ = (yyvsp[(4) - (6)].str); ;} + break; + + case 195: + + { + malloc_shard_column_node((yyval.shard_node), (yyvsp[(2) - (7)].str), (yyvsp[(3) - (7)].str), DBMESH_TOKEN_STR_VAL); + (yyval.shard_node)->col_str_value_ = (yyvsp[(5) - (7)].str); + add_shard_column_node(result->dbmesh_route_info_, (yyval.shard_node)); + ;} + break; + + case 196: + + { result->trace_id_ = (yyvsp[(4) - (6)].str); ;} + break; + + case 197: + + { result->rpc_id_ = (yyvsp[(4) - (6)].str); ;} + break; + + case 198: + + { result->dbmesh_route_info_.tnt_id_str_ = (yyvsp[(4) - (6)].str); ;} + break; + + case 199: + + { result->dbmesh_route_info_.disaster_status_str_ = (yyvsp[(4) - (6)].str); ;} + break; + + case 200: + + {;} + break; + + case 201: + + {;} + break; + + case 202: + + { result->target_db_server_ = (yyvsp[(4) - (6)].str); ;} + break; + + case 203: + + {;} + break; + + case 205: + + { result->has_simple_route_info_ = true; result->simple_route_info_.table_name_ = (yyvsp[(2) - (2)].str); ;} + break; + + case 206: + + { result->simple_route_info_.part_key_ = (yyvsp[(2) - (2)].str); ;} + break; + + case 210: + + { + result->dbp_route_info_.has_group_info_ = true; + result->dbp_route_info_.group_idx_str_ = (yyvsp[(3) - (4)].str); + ;} + break; + + case 211: + + { + result->dbp_route_info_.has_group_info_ = true; + result->dbp_route_info_.table_name_ = (yyvsp[(3) - (4)].str); + ;} + break; + + case 212: + + { result->dbp_route_info_.scan_all_ = true; ;} + break; + + case 213: + + { result->dbp_route_info_.scan_all_ = true; ;} + break; + + case 214: + + { result->dbp_route_info_.sticky_session_ = true; ;} + break; + + case 215: + + {result->dbp_route_info_.has_shard_key_ = true;;} + break; + + case 216: + + { result->trace_id_ = (yyvsp[(3) - (4)].str); ;} + break; + + case 217: + + { result->trace_id_ = (yyvsp[(3) - (6)].str); result->rpc_id_ = (yyvsp[(5) - (6)].str); ;} + break; + + case 218: + + {;} + break; + + case 220: + + { + if (result->dbp_route_info_.shard_key_count_ < OBPROXY_MAX_DBP_SHARD_KEY_NUM) { + result->dbp_route_info_.shard_key_infos_[result->dbp_route_info_.shard_key_count_].left_str_ = (yyvsp[(1) - (3)].str); + result->dbp_route_info_.shard_key_infos_[result->dbp_route_info_.shard_key_count_].right_str_ = (yyvsp[(3) - (3)].str); + ++result->dbp_route_info_.shard_key_count_; + } + ;} + break; + + case 223: + + { result->dbmesh_route_info_.group_idx_str_ = (yyvsp[(3) - (3)].str); ;} + break; + + case 224: + + { result->dbmesh_route_info_.tb_idx_str_ = (yyvsp[(3) - (3)].str); ;} + break; + + case 225: + + { result->dbmesh_route_info_.table_name_str_ = (yyvsp[(3) - (3)].str); ;} + break; + + case 226: + + { result->dbmesh_route_info_.es_idx_str_ = (yyvsp[(3) - (3)].str); ;} + break; + + case 227: + + { result->dbmesh_route_info_.testload_str_ = (yyvsp[(3) - (3)].str); ;} + break; + + case 228: + + { result->trace_id_ = (yyvsp[(3) - (3)].str); ;} + break; + + case 229: + + { result->rpc_id_ = (yyvsp[(3) - (3)].str); ;} + break; + + case 230: + + { result->dbmesh_route_info_.tnt_id_str_ = (yyvsp[(3) - (3)].str); ;} + break; + + case 231: + + { result->dbmesh_route_info_.disaster_status_str_ = (yyvsp[(3) - (3)].str); ;} + break; + + case 232: + + { result->target_db_server_ = (yyvsp[(3) - (3)].str); ;} + break; + + case 233: + + { + malloc_shard_column_node((yyval.shard_node), (yyvsp[(1) - (5)].str), (yyvsp[(3) - (5)].str), DBMESH_TOKEN_STR_VAL); + (yyval.shard_node)->col_str_value_ = (yyvsp[(5) - (5)].str); + add_shard_column_node(result->dbmesh_route_info_, (yyval.shard_node)); + ;} + break; + + case 234: + + {;} + break; + + case 235: + + { (yyval.str).str_ = NULL; (yyval.str).str_len_ = 0; ;} + break; + + case 237: + + { (yyval.str).str_ = NULL; (yyval.str).str_len_ = 0; ;} + break; + + case 259: + + { result->query_timeout_ = (yyvsp[(3) - (4)].num); ;} + break; + + case 260: + + {;} + break; + + case 262: + + { + add_hint_index(result->dbmesh_route_info_, (yyvsp[(3) - (5)].str)); + result->dbmesh_route_info_.index_count_++; + ;} + break; + + case 263: + + {;} + break; + + case 264: + + {;} + break; + + case 265: + + {;} + break; + + case 266: + + {;} + break; + + case 267: + + {;} + break; + + case 268: + + { SET_READ_CONSISTENCY(OBPROXY_READ_CONSISTENCY_WEAK); ;} + break; + + case 269: + + { SET_READ_CONSISTENCY(OBPROXY_READ_CONSISTENCY_STRONG); ;} + break; + + case 270: + + { SET_READ_CONSISTENCY(OBPROXY_READ_CONSISTENCY_FROZEN); ;} + break; + + case 273: + + { result->cur_stmt_type_ = OBPROXY_T_SHOW_WARNINGS; ;} + break; + + case 274: + + { result->cur_stmt_type_ = OBPROXY_T_SHOW_ERRORS; ;} + break; + + case 275: + + { result->cur_stmt_type_ = OBPROXY_T_SHOW_TRACE; ;} + break; + + case 299: + + {;} + break; + + case 300: + + {;} + break; + + case 301: + + {;} + break; + + case 302: + + {;} + break; + + case 303: + + {;} + break; + + case 304: + + {;} + break; + + case 305: + + { +;} + break; + + case 306: + + { + result->cmd_info_.integer_[2] = (yyvsp[(2) - (2)].num);/*row*/ +;} + break; + + case 307: + + { + result->cmd_info_.integer_[1] = (yyvsp[(2) - (4)].num);/*offset*/ + result->cmd_info_.integer_[2] = (yyvsp[(4) - (4)].num);/*row*/ +;} + break; + + case 308: + + { + result->cmd_info_.integer_[1] = (yyvsp[(4) - (4)].num);/*offset*/ + result->cmd_info_.integer_[2] = (yyvsp[(2) - (4)].num);/*row*/ +;} + break; + + case 309: + + {;} + break; + + case 310: + + { result->cmd_info_.string_[0] = (yyvsp[(2) - (2)].str);;} + break; + + case 311: + + {;} + break; + + case 312: + + { result->cmd_info_.string_[1] = (yyvsp[(2) - (2)].str);;} + break; + + case 314: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_NET_THREAD); ;} + break; + + case 315: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_NET_CONNECTION); ;} + break; + + case 316: + + { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_NET_CONNECTION, (yyvsp[(2) - (3)].num)); ;} + break; + + case 317: + + {;} + break; + + case 318: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_CONFIG_DIFF); ;} + break; + + case 319: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_CONFIG_DIFF_USER); ;} + break; + + case 320: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_SESSION_LIST); ;} + break; + + case 322: + + {SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_GLOBAL_SESSION_LIST);;} + break; + + case 323: + + {SET_ICMD_SUB_AND_ONE_STRING(OBPROXY_T_SUB_GLOBAL_SESSION_LIST_INFO, (yyvsp[(2) - (2)].str));;} + break; + + case 324: + + {SET_ICMD_SUB_AND_ONE_STRING(OBPROXY_T_SUB_GLOBAL_SESSION_LIST_LIKE, (yyvsp[(3) - (3)].str));;} + break; + + case 325: + + {SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_GLOBAL_SESSION_LIST_INFO_ALL);;} + break; + + case 326: + + {result->cmd_info_.string_[0] = (yyvsp[(2) - (2)].str);;} + break; + + case 328: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_SESSION_LIST_INTERNAL); ;} + break; + + case 329: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_SESSION_ATTRIBUTE); ;} + break; + + case 330: + + { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_SESSION_ATTRIBUTE, (yyvsp[(2) - (3)].num)); ;} + break; + + case 331: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_SESSION_STAT); ;} + break; + + case 332: + + { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_SESSION_STAT, (yyvsp[(2) - (3)].num)); ;} + break; + + case 333: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_SESSION_VARIABLES_LOCAL); ;} + break; + + case 334: + + { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_SESSION_VARIABLES_LOCAL, (yyvsp[(2) - (3)].num)); ;} + break; + + case 335: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_SESSION_VARIABLES_ALL); ;} + break; + + case 336: + + { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_SESSION_VARIABLES_ALL, (yyvsp[(3) - (4)].num)); ;} + break; + + case 337: + + {;} + break; + + case 338: + + { SET_ICMD_ONE_ID((yyvsp[(2) - (2)].num)); ;} + break; + + case 339: + + {;} + break; + + case 340: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_INFO_IDC); ;} + break; + + case 341: + + {;} + break; + + case 343: + + {;} + break; + + case 344: + + { SET_ICMD_ONE_STRING((yyvsp[(1) - (1)].str)); ;} + break; + + case 345: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_CONGEST_ALL);;} + break; + + case 346: + + { SET_ICMD_SUB_AND_ONE_STRING(OBPROXY_T_SUB_CONGEST_ALL, (yyvsp[(2) - (2)].str));;} + break; + + case 347: + + {;} + break; + + case 348: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_ROUTE_ROUTINE); ;} + break; + + case 349: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_ROUTE_PARTITION); ;} + break; + + case 350: + + {;} + break; + + case 351: + + { SET_ICMD_ONE_STRING((yyvsp[(2) - (2)].str)); ;} + break; + + case 352: + + {;} + break; + + case 353: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_MEMORY_OBJPOOL); ;} + break; + + case 354: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_SQLAUDIT_AUDIT_ID); ;} + break; + + case 355: + + { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_SQLAUDIT_SM_ID, (yyvsp[(2) - (2)].num)); ;} + break; + + case 357: + + {;} + break; + + case 358: + + { SET_ICMD_SECOND_ID((yyvsp[(1) - (1)].num)); ;} + break; + + case 359: + + { SET_ICMD_TWO_ID((yyvsp[(3) - (3)].num), (yyvsp[(1) - (3)].num)); ;} + break; + + case 360: + + { SET_ICMD_TWO_ID((yyvsp[(3) - (5)].num), (yyvsp[(1) - (5)].num)); SET_ICMD_ONE_STRING((yyvsp[(5) - (5)].str)); ;} + break; + + case 361: + + {;} + break; + + case 362: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_STAT_REFRESH); ;} + break; + + case 364: + + {;} + break; + + case 365: + + { SET_ICMD_ONE_ID((yyvsp[(1) - (1)].num)); ;} + break; + + case 366: + + { SET_ICMD_SUB_AND_TWO_ID(OBPROXY_T_SUB_TRACE_LIMIT, (yyvsp[(1) - (2)].num),(yyvsp[(2) - (2)].num)); ;} + break; + + case 367: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_INFO_BINARY); ;} + break; + + case 368: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_INFO_UPGRADE); ;} + break; + + case 369: + + { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_INFO_IDC); ;} + break; + + case 370: + + { SET_ICMD_ONE_STRING((yyvsp[(3) - (4)].str)); ;} + break; + + case 371: + + { SET_ICMD_TWO_STRING((yyvsp[(3) - (5)].str), (yyvsp[(5) - (5)].str)); ;} + break; + + case 372: + + { SET_ICMD_CONFIG_INT_VALUE((yyvsp[(3) - (5)].str), (yyvsp[(5) - (5)].num)); ;} + break; + + case 373: + + { SET_ICMD_ONE_STRING((yyvsp[(3) - (3)].str)); ;} + break; + + case 374: + + {;} + break; + + case 375: + + { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_KILL_CS, (yyvsp[(2) - (2)].num)); ;} + break; + + case 376: + + { SET_ICMD_SUB_AND_TWO_ID(OBPROXY_T_SUB_KILL_SS, (yyvsp[(2) - (3)].num), (yyvsp[(3) - (3)].num)); ;} + break; + + case 377: + + {SET_ICMD_TYPE_STRING_INT_VALUE(OBPROXY_T_SUB_KILL_GLOBAL_SS_ID, (yyvsp[(2) - (3)].str),(yyvsp[(3) - (3)].num));;} + break; + + case 378: + + {SET_ICMD_SUB_AND_ONE_STRING(OBPROXY_T_SUB_KILL_GLOBAL_SS_DBKEY, (yyvsp[(2) - (2)].str));;} + break; + + case 379: + + { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_KILL_CONNECTION, (yyvsp[(2) - (2)].num)); ;} + break; + + case 380: + + { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_KILL_CONNECTION, (yyvsp[(3) - (3)].num)); ;} + break; + + case 381: + + { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_KILL_QUERY, (yyvsp[(3) - (3)].num)); ;} + break; + + case 384: + + { + result->has_anonymous_block_ = false ; + result->cur_stmt_type_ = OBPROXY_T_BEGIN; + ;} + break; + + case 385: + + { result->cur_stmt_type_ = OBPROXY_T_BEGIN; ;} + break; + + case 386: + + { result->cur_stmt_type_ = OBPROXY_T_BEGIN; ;} + break; + + case 387: + + { result->cur_stmt_type_ = OBPROXY_T_BEGIN; ;} + break; + + case 394: + + { + result->cur_stmt_type_ = OBPROXY_T_USE_DB; + result->table_info_.database_name_ = (yyvsp[(2) - (2)].str); + ;} + break; + + case 395: + + { result->cur_stmt_type_ = OBPROXY_T_HELP; ;} + break; + + case 397: + + {;} + break; + + case 398: + + { result->part_name_ = (yyvsp[(2) - (2)].str); ;} + break; + + case 399: + + { result->part_name_ = (yyvsp[(3) - (4)].str); ;} + break; + + case 400: + + { + handle_stmt_end(result); + HANDLE_ACCEPT(); + ;} + break; + + case 401: + + { + result->table_info_.table_name_ = (yyvsp[(1) - (1)].str); + ;} + break; + + case 402: + + { + result->table_info_.database_name_ = (yyvsp[(1) - (3)].str); + result->table_info_.table_name_ = (yyvsp[(3) - (3)].str); + ;} + break; + + case 403: + + { + UPDATE_ALIAS_NAME((yyvsp[(2) - (2)].str)); + result->table_info_.table_name_ = (yyvsp[(1) - (2)].str); + ;} + break; + + case 404: + + { + UPDATE_ALIAS_NAME((yyvsp[(4) - (4)].str)); + result->table_info_.database_name_ = (yyvsp[(1) - (4)].str); + result->table_info_.table_name_ = (yyvsp[(3) - (4)].str); + ;} + break; + + case 405: + + { + UPDATE_ALIAS_NAME((yyvsp[(3) - (3)].str)); + result->table_info_.table_name_ = (yyvsp[(1) - (3)].str); + ;} + break; + + case 406: + + { + UPDATE_ALIAS_NAME((yyvsp[(5) - (5)].str)); + result->table_info_.database_name_ = (yyvsp[(1) - (5)].str); + result->table_info_.table_name_ = (yyvsp[(3) - (5)].str); + ;} + break; + + + + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + *++yylsp = yyloc; + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (&yylloc, result, YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (&yylloc, result, yymsg); + } + else + { + yyerror (&yylloc, result, YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + yyerror_range[0] = yylloc; + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval, &yylloc, result); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + yyerror_range[0] = yylsp[1-yylen]; + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + yyerror_range[0] = *yylsp; + yydestruct ("Error: popping", + yystos[yystate], yyvsp, yylsp, result); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + *++yyvsp = yylval; + + yyerror_range[1] = yylloc; + /* Using YYLLOC is tempting, but would change the location of + the lookahead. YYLOC is available though. */ + YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2); + *++yylsp = yyloc; + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined(yyoverflow) || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (&yylloc, result, YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, &yylloc, result); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp, yylsp, result); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + + + + +void yyerror(YYLTYPE* yylloc, ObProxyParseResult* p, char* s, ...) +{ + // do nothing +} + +void ob_proxy_gbk_parser_fatal_error(yyconst char *msg, yyscan_t yyscanner) +{ + fprintf(stderr, "FATAL ERROR:%s\n", msg); + ObProxyParseResult *p = ob_proxy_parser_gbk_yyget_extra(yyscanner); + if (OB_ISNULL(p)) { + fprintf(stderr, "unexpected null parse result\n"); + } else { + longjmp(p->jmp_buf_, 1);//the secord param must be non-zero value + } +} + +int obproxy_parse_gbk_sql(ObProxyParseResult* p, const char* buf, size_t len) +{ + int ret = OB_SUCCESS; + //obproxydebug = 1; + if (OB_ISNULL(p) || OB_ISNULL(buf) || OB_UNLIKELY(len <= 0)) { + ret = OB_INVALID_ARGUMENT; + // print err msg later + } else if (OB_FAIL(ob_proxy_parser_gbk_yylex_init_extra(p, &(p->yyscan_info_)))) { + // print err msg later + } else { + int val = setjmp(p->jmp_buf_); + if (val) { + ret = OB_PARSER_ERR_PARSE_SQL; + } else { + ob_proxy_parser_gbk_yy_scan_buffer((char *)buf, len, p->yyscan_info_); + if (OB_FAIL(ob_proxy_parser_gbk_yyparse(p))) { + // print err msg later + } else { + // do nothing + } + } + } + + return ret; +} + diff --git a/src/obproxy/opsql/parser/ob_proxy_parser_gbk_tab.h b/src/obproxy/opsql/parser/ob_proxy_parser_gbk_tab.h new file mode 100644 index 0000000000000000000000000000000000000000..6ecd470afef3ddadd885578b5893d237bacad843 --- /dev/null +++ b/src/obproxy/opsql/parser/ob_proxy_parser_gbk_tab.h @@ -0,0 +1,276 @@ + +/* A Bison parser, made by GNU Bison 2.4.1. */ + +/* Skeleton interface for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + + +#ifndef YY_OBPROXY_OB_PROXY_PARSER_TAB_H_INCLUDED +# define YY_OBPROXY_OB_PROXY_PARSER_TAB_H_INCLUDED +/* Debug traces. */ +#ifndef OBPROXY_GBK_DEBUG +# if defined YYDEBUG +#if YYDEBUG +# define OBPROXY_GBK_DEBUG 1 +# else +# define OBPROXY_GBK_DEBUG 0 +# endif +# else /* ! defined YYDEBUG */ +# define OBPROXY_GBK_DEBUG 0 +# endif /* ! defined YYDEBUG */ +#endif /* ! defined OBPROXY_GBK_DEBUG */ +#if OBPROXY_GBK_DEBUG +extern int ob_proxy_parser_gbk_yydebug; +#endif +/* Tokens. */ +#ifndef OBPROXYTOKENTYPE +# define OBPROXYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum obproxytokentype { + DUMMY_WHERE_CLAUSE = 258, + DUMMY_INSERT_CLAUSE = 259, + SELECT = 260, + DELETE = 261, + INSERT = 262, + UPDATE = 263, + REPLACE = 264, + MERGE = 265, + SHOW = 266, + SET = 267, + CALL = 268, + CREATE = 269, + DROP = 270, + ALTER = 271, + TRUNCATE = 272, + RENAME = 273, + TABLE = 274, + STATUS = 275, + UNIQUE = 276, + GRANT = 277, + REVOKE = 278, + ANALYZE = 279, + PURGE = 280, + COMMENT = 281, + FROM = 282, + DUAL = 283, + PREPARE = 284, + EXECUTE = 285, + USING = 286, + DEALLOCATE = 287, + SELECT_HINT_BEGIN = 288, + UPDATE_HINT_BEGIN = 289, + DELETE_HINT_BEGIN = 290, + INSERT_HINT_BEGIN = 291, + REPLACE_HINT_BEGIN = 292, + MERGE_HINT_BEGIN = 293, + HINT_END = 294, + COMMENT_BEGIN = 295, + COMMENT_END = 296, + ROUTE_TABLE = 297, + ROUTE_PART_KEY = 298, + QUERY_TIMEOUT = 299, + READ_CONSISTENCY = 300, + WEAK = 301, + STRONG = 302, + FROZEN = 303, + PLACE_HOLDER = 304, + END_P = 305, + ERROR = 306, + WHEN = 307, + FLASHBACK = 308, + AUDIT = 309, + NOAUDIT = 310, + BEGI = 311, + START = 312, + TRANSACTION = 313, + READ = 314, + ONLY = 315, + WITH = 316, + CONSISTENT = 317, + SNAPSHOT = 318, + INDEX = 319, + XA = 320, + WARNINGS = 321, + ERRORS = 322, + TRACE = 323, + QUICK = 324, + COUNT = 325, + AS = 326, + WHERE = 327, + VALUES = 328, + ORDER = 329, + GROUP = 330, + HAVING = 331, + INTO = 332, + UNION = 333, + FOR = 334, + TX_READ_ONLY = 335, + SELECT_OBPROXY_ROUTE_ADDR = 336, + SET_OBPROXY_ROUTE_ADDR = 337, + NAME_OB_DOT = 338, + NAME_OB = 339, + EXPLAIN = 340, + DESC = 341, + DESCRIBE = 342, + NAME_STR = 343, + USE = 344, + HELP = 345, + SET_NAMES = 346, + SET_CHARSET = 347, + SET_PASSWORD = 348, + SET_DEFAULT = 349, + SET_OB_READ_CONSISTENCY = 350, + SET_TX_READ_ONLY = 351, + GLOBAL = 352, + SESSION = 353, + NUMBER_VAL = 354, + GROUP_ID = 355, + TABLE_ID = 356, + ELASTIC_ID = 357, + TESTLOAD = 358, + ODP_COMMENT = 359, + TNT_ID = 360, + DISASTER_STATUS = 361, + TRACE_ID = 362, + RPC_ID = 363, + TARGET_DB_SERVER = 364, + DBP_COMMENT = 365, + ROUTE_TAG = 366, + SYS_TAG = 367, + TABLE_NAME = 368, + SCAN_ALL = 369, + STICKY_SESSION = 370, + PARALL = 371, + SHARD_KEY = 372, + INT_NUM = 373, + SHOW_PROXYNET = 374, + THREAD = 375, + CONNECTION = 376, + LIMIT = 377, + OFFSET = 378, + SHOW_PROCESSLIST = 379, + SHOW_PROXYSESSION = 380, + SHOW_GLOBALSESSION = 381, + ATTRIBUTE = 382, + VARIABLES = 383, + ALL = 384, + STAT = 385, + SHOW_PROXYCONFIG = 386, + DIFF = 387, + USER = 388, + LIKE = 389, + SHOW_PROXYSM = 390, + SHOW_PROXYCLUSTER = 391, + SHOW_PROXYRESOURCE = 392, + SHOW_PROXYCONGESTION = 393, + SHOW_PROXYROUTE = 394, + PARTITION = 395, + ROUTINE = 396, + SHOW_PROXYVIP = 397, + SHOW_PROXYMEMORY = 398, + OBJPOOL = 399, + SHOW_SQLAUDIT = 400, + SHOW_WARNLOG = 401, + SHOW_PROXYSTAT = 402, + REFRESH = 403, + SHOW_PROXYTRACE = 404, + SHOW_PROXYINFO = 405, + BINARY = 406, + UPGRADE = 407, + IDC = 408, + SHOW_ELASTIC_ID = 409, + SHOW_TOPOLOGY = 410, + GROUP_NAME = 411, + SHOW_DB_VERSION = 412, + SHOW_DATABASES = 413, + SHOW_TABLES = 414, + SHOW_FULL_TABLES = 415, + SELECT_DATABASE = 416, + SHOW_CREATE_TABLE = 417, + SELECT_PROXY_VERSION = 418, + SHOW_COLUMNS = 419, + SHOW_INDEX = 420, + ALTER_PROXYCONFIG = 421, + ALTER_PROXYRESOURCE = 422, + PING_PROXY = 423, + KILL_PROXYSESSION = 424, + KILL_GLOBALSESSION = 425, + KILL = 426, + QUERY = 427, + SHOW_MASTER_STATUS = 428, + SHOW_BINARY_LOGS = 429, + SHOW_BINLOG_EVENTS = 430, + PURGE_BINARY_LOGS = 431, + RESET_MASTER = 432, + SHOW_BINLOG_SERVER_FOR_TENANT = 433 + }; +#endif + + + +#if ! defined OBPROXYSTYPE && ! defined OBPROXYSTYPE_IS_DECLARED +typedef union OBPROXYSTYPE +{ + + + int64_t num; + ObProxyParseString str; + ObProxyCallParseNode *node; + ObShardColumnNode *shard_node; + ObProxySetVarNode *var_node; + + + +} OBPROXYSTYPE; +# define OBPROXYSTYPE_IS_TRIVIAL 1 +# define obproxystype OBPROXYSTYPE /* obsolescent; will be withdrawn */ +# define OBPROXYSTYPE_IS_DECLARED 1 +#endif + + + +#if ! defined OBPROXYLTYPE && ! defined OBPROXYLTYPE_IS_DECLARED +typedef struct OBPROXYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} OBPROXYLTYPE; +# define obproxyltype OBPROXYLTYPE /* obsolescent; will be withdrawn */ +# define OBPROXYLTYPE_IS_DECLARED 1 +# define OBPROXYLTYPE_IS_TRIVIAL 1 +#endif + + + +#endif diff --git a/src/obproxy/opsql/parser/ob_proxy_parser_utf8_lex.c b/src/obproxy/opsql/parser/ob_proxy_parser_utf8_lex.c index d07893b86f32c4d6f1ce1c401f1f412479994276..b220208da9b8b531fc61d69b6b467a18b2e70e95 100644 --- a/src/obproxy/opsql/parser/ob_proxy_parser_utf8_lex.c +++ b/src/obproxy/opsql/parser/ob_proxy_parser_utf8_lex.c @@ -348,8 +348,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); yyg->yy_hold_char = *yy_cp; \ yyg->yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 323 -#define YY_END_OF_BUFFER 324 +#define YY_NUM_RULES 344 +#define YY_END_OF_BUFFER 345 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -357,240 +357,314 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[2102] = +static yyconst flex_int16_t yy_accept[2787] = { 0, - 134, 134, 177, 177, 0, 0, 0, 0, 190, 190, - 218, 218, 0, 0, 0, 0, 0, 0, 246, 246, + 147, 147, 195, 195, 0, 0, 0, 0, 208, 208, + 238, 238, 0, 0, 0, 0, 0, 0, 267, 267, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 295, 295, 0, 0, - 0, 0, 313, 313, 317, 317, 0, 0, 156, 156, - 0, 0, 324, 322, 144, 144, 140, 270, 144, 134, - 259, 141, 140, 132, 322, 140, 140, 133, 139, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 276, 322, 322, 179, 323, 177, 176, 179, - - 179, 170, 177, 177, 177, 177, 177, 177, 179, 183, - 182, 183, 185, 185, 323, 185, 185, 185, 185, 185, - 185, 185, 185, 185, 185, 185, 185, 185, 195, 195, - 190, 195, 195, 190, 190, 195, 222, 221, 221, 218, - 216, 222, 218, 217, 218, 220, 219, 218, 218, 218, - 218, 218, 222, 222, 228, 227, 227, 224, 228, 225, - 228, 228, 230, 229, 229, 229, 230, 230, 230, 248, - 245, 245, 246, 240, 241, 248, 246, 244, 246, 246, - 246, 246, 246, 248, 248, 250, 249, 323, 323, 256, - 255, 255, 253, 251, 252, 256, 256, 256, 258, 257, - - 257, 257, 258, 258, 258, 265, 266, 323, 260, 261, - 323, 271, 272, 323, 278, 279, 281, 282, 298, 296, - 296, 286, 296, 295, 287, 285, 298, 297, 298, 295, - 295, 295, 295, 295, 288, 298, 298, 321, 321, 305, - 304, 304, 302, 304, 303, 300, 301, 305, 305, 305, - 305, 315, 314, 314, 308, 314, 313, 309, 306, 307, - 315, 313, 313, 313, 315, 315, 318, 317, 319, 317, - 166, 166, 164, 158, 158, 162, 158, 156, 161, 164, - 155, 164, 164, 154, 160, 159, 159, 156, 156, 156, - 163, 164, 164, 113, 111, 111, 111, 113, 112, 113, - - 113, 113, 144, 0, 136, 0, 144, 134, 0, 135, - 133, 0, 138, 180, 138, 133, 134, 134, 134, 41, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 8, 0, 137, 0, 0, 177, 0, 178, - 170, 170, 177, 177, 177, 177, 177, 177, 0, 0, - 181, 0, 0, 0, 205, 0, 0, 0, 0, 0, - - 0, 0, 0, 184, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 192, 0, 190, 0, - 191, 0, 194, 190, 190, 0, 193, 218, 0, 223, - 218, 218, 218, 218, 218, 218, 218, 218, 0, 0, - 0, 226, 0, 0, 0, 229, 0, 0, 246, 246, - 246, 0, 247, 246, 246, 246, 246, 246, 246, 0, - 0, 0, 0, 0, 254, 0, 0, 0, 257, 0, - 0, 265, 0, 0, 267, 0, 0, 268, 260, 0, - 0, 262, 0, 0, 263, 0, 273, 0, 0, 0, - 274, 278, 277, 281, 280, 296, 0, 296, 295, 0, - - 0, 295, 295, 295, 295, 295, 295, 0, 0, 0, - 304, 0, 304, 0, 0, 0, 0, 314, 0, 314, - 313, 0, 313, 313, 313, 0, 0, 317, 317, 0, - 158, 0, 158, 156, 154, 0, 157, 157, 154, 156, - 0, 156, 156, 156, 0, 0, 111, 0, 111, 0, - 0, 0, 0, 144, 0, 0, 138, 0, 0, 134, - 52, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 39, 134, 134, 134, 134, 134, 134, 107, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 13, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 50, 134, 134, 134, 134, 134, 134, 142, 143, 132, - 177, 177, 177, 177, 177, 177, 167, 168, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, - 190, 218, 218, 218, 218, 218, 218, 218, 218, 221, - 217, 227, 225, 229, 246, 246, 246, 246, 246, 246, - 246, 246, 245, 242, 243, 244, 250, 249, 255, 252, - 257, 269, 0, 269, 0, 0, 264, 0, 264, 0, - - 0, 275, 0, 275, 0, 0, 296, 0, 0, 0, - 0, 295, 295, 295, 295, 295, 295, 285, 0, 304, - 0, 0, 300, 301, 314, 0, 313, 313, 313, 306, - 307, 317, 0, 158, 0, 0, 157, 0, 0, 156, - 0, 0, 156, 156, 156, 155, 111, 0, 0, 0, - 144, 144, 144, 0, 0, 138, 0, 138, 138, 134, - 134, 134, 134, 134, 134, 14, 134, 134, 134, 134, - 134, 134, 134, 134, 46, 89, 18, 134, 134, 134, - 134, 134, 134, 134, 134, 71, 134, 134, 134, 134, - 58, 125, 134, 53, 134, 134, 134, 134, 134, 134, - - 68, 134, 134, 134, 134, 134, 134, 134, 48, 134, - 134, 134, 134, 134, 134, 134, 134, 0, 0, 7, - 134, 134, 87, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 90, 134, 134, 134, 134, 16, 134, 49, - 177, 177, 177, 177, 177, 172, 0, 0, 0, 0, - 196, 0, 0, 0, 0, 0, 0, 190, 190, 218, - 218, 218, 218, 218, 218, 218, 218, 246, 233, 246, - 246, 246, 246, 246, 246, 0, 0, 0, 0, 0, - 0, 296, 296, 296, 0, 0, 0, 0, 295, 295, - 284, 295, 295, 295, 0, 304, 304, 304, 0, 0, - - 314, 314, 314, 0, 313, 313, 313, 316, 165, 158, - 158, 158, 0, 0, 157, 0, 157, 157, 0, 0, - 156, 156, 156, 111, 111, 111, 0, 109, 0, 144, - 19, 134, 134, 34, 9, 134, 134, 134, 134, 134, - 63, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 28, 36, 134, 134, 134, 22, 134, 0, 0, - 134, 51, 134, 6, 134, 134, 134, 38, 134, 0, - 0, 134, 31, 126, 62, 134, 134, 134, 134, 134, - 134, 134, 134, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 134, 10, 23, 134, 66, 134, 134, - - 40, 134, 134, 134, 25, 44, 134, 134, 42, 177, - 175, 177, 177, 177, 231, 0, 0, 0, 0, 0, - 186, 0, 0, 0, 190, 188, 218, 218, 218, 218, - 218, 218, 218, 218, 246, 246, 246, 246, 246, 246, - 239, 0, 0, 269, 0, 0, 0, 0, 264, 0, - 0, 0, 0, 275, 0, 0, 296, 0, 0, 0, - 295, 295, 0, 0, 0, 0, 295, 295, 295, 320, - 304, 0, 314, 313, 313, 313, 158, 0, 0, 156, - 156, 156, 111, 110, 0, 0, 134, 134, 55, 134, - 11, 134, 134, 17, 134, 134, 2, 134, 65, 134, - - 134, 134, 134, 134, 37, 134, 57, 3, 0, 0, - 0, 134, 134, 0, 0, 0, 134, 134, 81, 134, - 0, 0, 134, 134, 21, 134, 29, 134, 134, 134, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 134, 79, - 134, 134, 24, 4, 134, 43, 134, 134, 174, 177, - 177, 173, 0, 0, 0, 0, 206, 0, 0, 203, - 0, 190, 218, 218, 218, 215, 218, 218, 213, 218, - 232, 246, 246, 246, 246, 246, 0, 0, 0, 0, - 0, 0, 295, 295, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 292, 295, 295, 299, 313, 313, 313, - 0, 0, 156, 152, 156, 0, 0, 30, 134, 32, - 134, 134, 15, 60, 0, 0, 0, 134, 27, 45, - 134, 134, 134, 134, 0, 0, 0, 0, 0, 134, - 134, 0, 0, 35, 99, 134, 0, 26, 103, 5, - 134, 96, 134, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 315, 315, 0, 0, + 0, 0, 333, 333, 338, 338, 0, 0, 174, 174, + 0, 0, 0, 0, 0, 0, 0, 0, 345, 343, + 157, 157, 153, 291, 147, 147, 280, 154, 153, 145, + 343, 153, 153, 146, 152, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 297, 343, + + 343, 343, 343, 343, 343, 197, 344, 195, 194, 197, + 197, 188, 195, 195, 195, 195, 195, 195, 197, 197, + 197, 197, 197, 197, 201, 200, 201, 203, 203, 344, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 213, 213, + 208, 213, 213, 208, 208, 213, 213, 213, 213, 213, + 213, 213, 242, 241, 241, 238, 236, 242, 238, 237, + 238, 240, 239, 238, 238, 238, 238, 238, 242, 242, + 248, 247, 247, 244, 248, 245, 248, 248, 250, 249, + 249, 249, 250, 250, 250, 269, 266, 266, 267, 261, + + 262, 269, 267, 265, 267, 267, 267, 267, 267, 267, + 269, 269, 271, 270, 344, 344, 277, 276, 276, 274, + 272, 273, 277, 277, 277, 279, 278, 278, 278, 279, + 279, 279, 286, 287, 344, 281, 282, 344, 292, 293, + 344, 299, 300, 302, 303, 318, 316, 316, 307, 315, + 315, 308, 306, 318, 317, 318, 315, 315, 315, 315, + 309, 318, 318, 318, 318, 318, 318, 342, 342, 325, + 324, 324, 322, 324, 323, 320, 321, 325, 325, 325, + 325, 335, 334, 334, 328, 333, 333, 329, 326, 327, + 335, 333, 333, 333, 335, 335, 335, 335, 335, 335, + + 339, 338, 340, 337, 338, 344, 344, 344, 344, 344, + 344, 184, 184, 182, 176, 176, 180, 174, 174, 179, + 182, 173, 182, 182, 172, 178, 177, 174, 174, 181, + 182, 182, 182, 182, 182, 182, 117, 115, 115, 115, + 117, 116, 117, 117, 117, 127, 125, 125, 125, 127, + 126, 127, 127, 127, 344, 344, 344, 157, 0, 149, + 0, 0, 0, 0, 0, 0, 0, 157, 147, 157, + 157, 157, 157, 157, 157, 147, 0, 0, 0, 0, + 0, 0, 0, 148, 0, 0, 0, 0, 0, 0, + 146, 0, 0, 146, 151, 198, 151, 146, 147, 147, + + 147, 44, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 8, 0, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 134, 134, 134, 0, 0, 0, - 106, 134, 134, 177, 177, 0, 0, 0, 0, 0, - 0, 0, 0, 190, 218, 218, 218, 218, 218, 218, - - 218, 246, 246, 246, 246, 246, 0, 0, 0, 295, - 295, 0, 0, 0, 0, 0, 0, 295, 295, 313, - 313, 313, 0, 0, 156, 153, 0, 134, 134, 134, - 0, 0, 47, 134, 134, 134, 134, 0, 0, 0, - 0, 134, 134, 0, 0, 150, 134, 0, 0, 0, - 0, 12, 134, 0, 0, 0, 0, 0, 0, 0, + 0, 195, 0, 0, 0, 0, 0, 0, 0, 196, + 188, 188, 195, 195, 195, 195, 195, 195, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 199, 0, 0, + + 0, 223, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 70, 134, 20, 0, - 0, 134, 64, 177, 177, 0, 0, 197, 187, 198, - 0, 201, 204, 189, 218, 218, 207, 208, 218, 211, - - 214, 238, 246, 234, 246, 246, 0, 0, 0, 295, - 295, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 295, 295, 313, 313, 313, 0, 0, - 156, 0, 85, 134, 134, 0, 0, 147, 33, 134, - 134, 134, 0, 0, 148, 0, 0, 134, 134, 0, - 0, 0, 0, 54, 0, 0, 0, 130, 0, 0, - 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 210, 0, 0, 0, + 0, 0, 0, 0, 208, 0, 0, 0, 0, 0, + 0, 0, 209, 0, 0, 0, 0, 0, 0, 0, + 212, 208, 208, 0, 211, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, + 0, 243, 238, 238, 238, 238, 238, 238, 238, 238, + 0, 0, 0, 246, 0, 0, 0, 249, 0, 0, + + 267, 267, 267, 0, 268, 267, 267, 267, 267, 267, + 267, 267, 0, 0, 0, 0, 0, 275, 0, 0, + 0, 278, 0, 0, 286, 0, 0, 288, 0, 0, + 289, 281, 0, 0, 283, 0, 0, 284, 0, 294, + 0, 0, 0, 295, 299, 298, 302, 301, 316, 0, + 316, 315, 316, 316, 316, 316, 316, 316, 315, 0, + 0, 0, 0, 0, 0, 0, 0, 315, 315, 315, + 315, 315, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 324, 0, 324, 0, 0, 0, 0, 334, 0, + 334, 333, 334, 334, 334, 334, 334, 334, 333, 0, + + 0, 0, 0, 0, 0, 0, 333, 333, 333, 0, + 0, 0, 0, 0, 0, 0, 0, 338, 0, 0, + 0, 0, 0, 0, 338, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 176, 0, 176, 174, 176, 176, + 176, 176, 176, 176, 174, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 172, 175, 175, 172, 174, 174, + 174, 0, 0, 0, 0, 0, 0, 0, 0, 115, + 0, 115, 0, 0, 0, 0, 125, 0, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 134, 0, 0, 146, 86, 177, - 177, 0, 0, 0, 218, 218, 218, 246, 246, 246, - - 0, 0, 0, 295, 295, 283, 0, 0, 0, 0, - 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, - 0, 295, 290, 313, 313, 311, 0, 0, 156, 0, - 80, 69, 0, 0, 0, 0, 129, 56, 134, 0, - 0, 0, 0, 0, 0, 134, 134, 0, 0, 0, - 0, 122, 0, 0, 149, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, + 0, 0, 0, 0, 0, 157, 157, 157, 157, 157, + + 157, 157, 157, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 146, 157, 0, 146, 0, 0, 151, + 0, 146, 0, 147, 55, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 42, 147, 147, 147, 147, + 147, 147, 147, 111, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 13, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 53, 147, 147, 147, + + 147, 147, 147, 0, 0, 0, 0, 0, 0, 0, + 0, 147, 147, 155, 156, 145, 0, 0, 188, 188, + 195, 195, 195, 195, 195, 195, 195, 195, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 134, 0, 0, 0, 0, 177, 177, - 0, 200, 199, 218, 210, 209, 246, 246, 236, 0, - - 0, 0, 0, 0, 295, 289, 0, 0, 0, 0, - 0, 0, 295, 310, 313, 0, 0, 0, 0, 156, - 0, 0, 0, 0, 0, 134, 0, 0, 0, 0, - 0, 0, 134, 134, 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, 208, 208, 0, 0, 0, 0, 0, + 0, 0, 0, 208, 208, 0, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 241, 237, 247, 245, 249, + 267, 267, 267, 267, 267, 267, 267, 267, 267, 266, + + 263, 264, 265, 271, 270, 276, 273, 278, 290, 0, + 290, 0, 0, 285, 0, 285, 0, 0, 296, 0, + 296, 0, 0, 0, 316, 316, 316, 316, 316, 316, + 316, 316, 0, 0, 316, 0, 0, 0, 315, 315, + 315, 315, 315, 315, 315, 306, 0, 0, 324, 0, + 0, 320, 321, 0, 334, 334, 334, 334, 334, 334, + 334, 334, 0, 0, 334, 0, 333, 333, 333, 333, + 333, 326, 327, 0, 338, 338, 338, 0, 0, 0, + 176, 176, 176, 176, 176, 176, 176, 176, 0, 0, + 172, 176, 0, 172, 0, 0, 175, 0, 172, 0, + + 174, 174, 174, 174, 174, 173, 0, 115, 0, 0, + 0, 125, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 147, 147, 157, 0, 0, 0, 146, 157, 157, + 157, 0, 146, 151, 0, 151, 0, 151, 146, 147, + 147, 147, 147, 147, 147, 14, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 49, 18, 147, 147, 147, + 147, 147, 25, 147, 147, 147, 74, 147, 147, 147, + 147, 61, 138, 147, 56, 147, 147, 147, 147, 147, + 147, 71, 147, 147, 147, 147, 147, 147, 147, 51, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 0, + + 0, 7, 147, 147, 90, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 16, 147, + 52, 0, 0, 0, 188, 188, 195, 195, 195, 195, + 195, 190, 0, 0, 0, 0, 214, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 208, 208, 0, 0, 0, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 267, 253, 267, 267, 267, 267, + 267, 267, 267, 0, 0, 0, 0, 0, 0, 315, + 315, 316, 316, 316, 316, 0, 0, 0, 315, 305, + 315, 315, 315, 0, 324, 324, 324, 0, 0, 333, + + 333, 334, 334, 334, 334, 0, 333, 333, 333, 336, + 183, 174, 174, 176, 172, 176, 176, 176, 0, 172, + 175, 0, 175, 0, 175, 172, 174, 174, 115, 115, + 115, 0, 113, 0, 125, 125, 125, 0, 123, 124, + 92, 94, 93, 146, 157, 146, 146, 19, 147, 147, + 37, 9, 147, 147, 147, 147, 147, 66, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 31, + 39, 147, 147, 147, 22, 147, 0, 0, 147, 54, + 147, 6, 147, 147, 147, 41, 147, 0, 0, 147, + 34, 139, 65, 147, 147, 147, 147, 147, 147, 147, + + 147, 147, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 147, 10, 147, 23, 147, 69, 147, + 147, 43, 147, 147, 147, 27, 47, 147, 147, 45, + 188, 188, 195, 193, 195, 195, 195, 251, 0, 0, + 0, 0, 0, 204, 0, 0, 0, 0, 208, 206, + 238, 238, 238, 238, 238, 238, 238, 238, 238, 267, + 267, 267, 267, 267, 267, 267, 260, 0, 0, 290, + 0, 0, 0, 0, 285, 0, 0, 0, 0, 296, + 0, 0, 316, 0, 0, 315, 0, 315, 0, 0, + 315, 315, 315, 341, 324, 0, 334, 333, 333, 333, + + 172, 176, 172, 172, 174, 174, 115, 114, 125, 146, + 146, 146, 0, 0, 147, 147, 58, 147, 11, 147, + 147, 17, 147, 147, 147, 2, 147, 68, 147, 147, + 147, 147, 147, 40, 147, 60, 3, 0, 0, 0, + 0, 147, 147, 0, 0, 0, 147, 147, 84, 147, + 0, 0, 0, 147, 0, 0, 147, 21, 147, 0, + 0, 32, 147, 147, 147, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 116, 0, 67, 0, 0, 0, 0, 177, - 177, 0, 218, 237, 246, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 283, 295, 313, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 134, 0, 0, 0, 0, 134, 59, 0, 0, + 147, 24, 82, 147, 147, 26, 4, 147, 46, 147, + + 147, 188, 188, 192, 195, 195, 191, 0, 0, 0, + 0, 224, 0, 0, 0, 221, 0, 208, 238, 238, + 238, 234, 238, 238, 238, 232, 238, 252, 267, 267, + 267, 267, 267, 267, 0, 0, 0, 0, 0, 315, + 0, 0, 0, 0, 0, 315, 315, 0, 315, 0, + 0, 0, 0, 0, 0, 0, 0, 313, 315, 315, + 319, 333, 333, 333, 172, 172, 172, 170, 174, 146, + 146, 146, 0, 0, 0, 33, 147, 35, 147, 147, + 147, 15, 63, 0, 0, 0, 147, 29, 48, 147, + 147, 147, 147, 0, 0, 0, 0, 0, 0, 147, + + 147, 0, 0, 0, 38, 103, 147, 0, 0, 28, + 0, 0, 0, 107, 5, 0, 0, 0, 147, 100, + 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 73, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 91, 0, 0, 0, 0, 101, - 0, 0, 177, 177, 0, 218, 235, 0, 0, 0, - 0, 0, 0, 294, 0, 0, 283, 295, 313, 0, - 0, 0, 0, 151, 0, 0, 0, 0, 0, 61, - 0, 0, 0, 134, 150, 0, 0, 0, 0, 0, + 0, 147, 147, 147, 0, 0, 0, 110, 147, 147, + 188, 188, 195, 195, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 208, 238, 238, 238, 238, 238, 238, + 238, 238, 267, 267, 267, 267, 267, 267, 0, 0, + 315, 0, 0, 0, 0, 0, 0, 315, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 315, 315, + 333, 333, 333, 172, 172, 172, 171, 146, 146, 146, + 0, 0, 147, 147, 147, 147, 0, 0, 0, 50, + 147, 147, 147, 147, 0, 0, 0, 0, 0, 147, + 147, 0, 0, 0, 163, 147, 0, 0, 0, 0, + 0, 0, 0, 0, 12, 147, 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, 73, 147, + 20, 0, 0, 0, 147, 67, 188, 188, 195, 195, + + 0, 0, 215, 205, 216, 0, 0, 219, 222, 207, + 238, 238, 226, 227, 238, 238, 230, 233, 259, 267, + 254, 267, 267, 267, 0, 0, 315, 0, 0, 0, + 0, 0, 0, 315, 315, 315, 0, 0, 0, 0, + 0, 0, 0, 0, 315, 315, 333, 333, 333, 172, + 172, 172, 146, 146, 146, 0, 88, 147, 147, 147, + 0, 0, 0, 160, 36, 147, 147, 147, 0, 0, + 0, 161, 0, 0, 147, 147, 0, 0, 0, 0, + 57, 0, 0, 0, 0, 0, 0, 143, 0, 0, + 0, 0, 0, 0, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 78, 0, 0, 0, 0, 0, 97, - 100, 0, 169, 177, 0, 218, 0, 0, 0, 0, - 295, 313, 0, 0, 0, 0, 147, 0, 148, 0, - 0, 0, 131, 0, 0, 0, 0, 0, 145, 0, + 0, 0, 0, 0, 0, 0, 129, 0, 0, 0, + 0, 0, 0, 0, 147, 0, 0, 0, 159, 89, + 188, 188, 195, 195, 0, 0, 0, 0, 238, 238, + 238, 238, 267, 267, 267, 267, 0, 0, 315, 0, + 304, 0, 0, 0, 0, 0, 0, 0, 304, 0, + 0, 0, 0, 0, 0, 0, 315, 311, 333, 333, + 331, 172, 172, 172, 146, 146, 146, 0, 83, 72, + 30, 0, 0, 0, 0, 142, 59, 147, 0, 0, + 0, 0, 0, 0, 147, 147, 0, 0, 0, 0, + + 135, 0, 0, 0, 0, 162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 115, 0, 0, 0, 0, 0, 0, 0, - 105, 0, 0, 0, 0, 102, 0, 146, 0, 177, - 0, 218, 0, 0, 293, 291, 312, 0, 0, 0, + 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 129, 0, 0, 0, + 0, 0, 0, 0, 147, 0, 0, 0, 0, 188, + 188, 195, 195, 0, 218, 217, 0, 238, 229, 228, + 238, 267, 267, 267, 257, 0, 0, 0, 0, 310, + 304, 0, 0, 0, 0, 0, 0, 315, 330, 333, + 172, 172, 172, 146, 146, 146, 0, 0, 0, 0, + 0, 147, 0, 0, 0, 0, 0, 0, 147, 147, - 0, 0, 0, 0, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 108, 0, 0, 0, 0, 0, - 0, 0, 95, 0, 104, 0, 177, 202, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 121, 0, 0, 70, 0, 0, 0, 0, 188, 188, + 195, 195, 0, 0, 238, 238, 258, 267, 267, 0, + 0, 0, 0, 0, 0, 304, 315, 333, 172, 172, + 172, 146, 146, 146, 0, 0, 0, 0, 147, 0, + 0, 0, 0, 147, 62, 0, 0, 0, 0, 0, + + 0, 168, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 78, 0, 0, 0, 0, 0, + 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, + 129, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 95, 0, 0, 0, 0, 0, 105, 0, + 0, 188, 188, 195, 195, 0, 0, 238, 238, 256, + 267, 0, 0, 0, 304, 315, 333, 172, 172, 172, + 146, 146, 146, 0, 0, 0, 64, 0, 0, 0, + 147, 163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, - 0, 0, 0, 84, 0, 88, 0, 98, 0, 0, - 171, 0, 0, 0, 120, 0, 0, 123, 0, 118, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 81, 0, 0, 0, 0, 0, 101, 104, 118, 0, + 188, 188, 187, 195, 0, 0, 238, 238, 267, 0, + 0, 315, 333, 172, 172, 172, 146, 146, 146, 0, + 0, 160, 0, 161, 0, 0, 0, 144, 0, 0, + 0, 0, 0, 0, 0, 158, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 120, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 109, 0, 0, 0, 0, 106, 0, 159, + + 0, 188, 188, 195, 0, 0, 238, 238, 255, 0, + 314, 312, 332, 172, 172, 172, 146, 146, 146, 0, + 0, 0, 0, 0, 0, 0, 162, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, + 0, 108, 0, 188, 188, 195, 220, 0, 231, 238, + 0, 172, 172, 172, 146, 146, 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 77, 0, 117, 0, 0, 92, 0, 0, 83, 0, + 0, 0, 0, 0, 0, 80, 165, 0, 0, 0, - 0, 0, 0, 124, 0, 0, 0, 0, 0, 0, - 77, 0, 73, 0, 0, 0, 0, 82, 0, 93, - 0, 0, 0, 121, 0, 0, 0, 0, 0, 0, + 0, 122, 0, 0, 87, 0, 91, 0, 102, 0, + 0, 188, 188, 189, 225, 235, 0, 172, 172, 172, + 146, 146, 146, 133, 0, 0, 136, 167, 0, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 94, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, - 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, - 0, 293, 0, 0, 0, 0, 0, 128, 76, 0, - 0, 0, 0, 76, 0, 0, 76, 0, 0, 0, - 127, 0, 77, 0, 0, 0, 0, 0, 0, 76, - - 0 + 80, 0, 0, 0, 130, 0, 0, 0, 96, 0, + 0, 86, 188, 188, 0, 172, 172, 172, 146, 146, + 147, 0, 137, 0, 0, 0, 0, 0, 0, 80, + 0, 76, 0, 0, 0, 166, 0, 0, 85, 164, + 0, 97, 188, 0, 172, 172, 174, 151, 151, 147, + 134, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 175, 175, 174, 151, 151, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, + 0, 175, 175, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 119, 0, 0, 132, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 314, 0, 0, + 0, 0, 0, 141, 79, 0, 0, 0, 0, 0, + 0, 79, 0, 0, 0, 0, 79, 0, 0, 0, + 0, 140, 0, 80, 0, 0, 0, 0, 0, 0, + 169, 0, 0, 0, 79, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -599,1231 +673,2684 @@ static yyconst flex_int32_t yy_ec[256] = 1, 2, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 7, 8, 5, 5, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 20, 21, 1, - 22, 1, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 1, 51, 1, 5, 52, 53, 54, 55, 56, 57, - - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 78, 79, 80, 5, 80, 5, 1, 81, 1, 1, - 1, 1, 1, 1, 1, 82, 83, 1, 1, 84, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 85, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 86, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 87, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 11, 12, 13, 14, 15, 16, 17, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 19, 20, 1, + 21, 1, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 1, 50, 1, 5, 51, 52, 53, 54, 55, 56, + + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 5, 79, 5, 1, 80, 81, 81, + 81, 81, 81, 81, 81, 82, 83, 84, 84, 85, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 87, 88, 88, + 88, 1, 1, 89, 89, 89, 89, 89, 89, 89, + + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 90, 90, 90, 91, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 93, 94, + 94, 94, 94, 94, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; -static yyconst flex_int32_t yy_meta[88] = +static yyconst flex_int32_t yy_meta[95] = { 0, - 1, 2, 3, 3, 1, 4, 1, 5, 6, 1, - 1, 1, 2, 1, 7, 8, 1, 5, 5, 1, - 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 9, 5, 10, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, - 1, 1, 1, 1, 1, 2, 1 + 1, 2, 3, 3, 1, 4, 5, 6, 7, 1, + 1, 1, 2, 1, 8, 9, 1, 6, 10, 1, + 1, 1, 1, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 11, + 6, 12, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, + 5, 5, 5, 5 + } ; -static yyconst flex_int16_t yy_base[2200] = +static yyconst flex_int16_t yy_base[2949] = { 0, - 0, 0, 87, 0, 172, 173, 185, 0, 272, 0, - 359, 0, 445, 449, 462, 466, 0, 0, 553, 0, - 639, 642, 651, 662, 673, 684, 441, 446, 447, 451, - 456, 461, 5462, 5461, 5460, 5459, 771, 0, 469, 470, - 857, 867, 954, 0, 1041, 1128, 476, 478, 1215, 0, - 1301, 1308, 5511, 6183, 1070, 1073, 6183, 5504, 0, 0, - 5500, 6183, 159, 6183, 164, 162, 5496, 470, 6183, 472, - 461, 479, 472, 630, 653, 435, 673, 684, 451, 678, - 462, 454, 849, 691, 455, 684, 851, 860, 850, 625, - 873, 636, 5454, 5425, 5420, 6183, 6183, 0, 6183, 470, - - 508, 523, 626, 632, 636, 676, 670, 710, 5419, 6183, - 6183, 639, 6183, 1393, 1478, 1080, 692, 1317, 1086, 6183, - 1103, 1337, 1377, 1355, 1413, 1443, 1563, 5422, 6183, 5496, - 0, 5492, 738, 840, 859, 5447, 6183, 6183, 6183, 0, - 6183, 744, 0, 6183, 0, 6183, 6183, 853, 860, 855, - 859, 1132, 5418, 5413, 6183, 6183, 6183, 6183, 746, 6183, - 5416, 5411, 6183, 6183, 6183, 6183, 752, 5414, 5409, 6183, - 6183, 6183, 1026, 6183, 6183, 920, 0, 6183, 0, 859, - 882, 1053, 1121, 5412, 5406, 6183, 6183, 5409, 5404, 6183, - 6183, 6183, 6183, 6183, 6183, 921, 5406, 5401, 6183, 6183, - - 6183, 6183, 928, 5404, 5399, 0, 1469, 0, 0, 1483, - 0, 6183, 1498, 0, 0, 5430, 0, 5429, 6183, 1108, - 1324, 6183, 0, 0, 6183, 6183, 5466, 6183, 5456, 878, - 1125, 1013, 1054, 1047, 6183, 5398, 5393, 6183, 1062, 6183, - 1332, 1428, 6183, 0, 6183, 6183, 6183, 5462, 1118, 5395, - 5390, 6183, 1440, 1466, 6183, 0, 0, 6183, 6183, 6183, - 5459, 1114, 1129, 1116, 5392, 5387, 6183, 0, 6183, 1120, - 6183, 1130, 6183, 1513, 1521, 6183, 0, 0, 6183, 629, - 6183, 931, 701, 1346, 6183, 6183, 5447, 1124, 1135, 1144, - 6183, 5389, 5384, 6183, 1528, 1537, 0, 5453, 6183, 1135, - - 1146, 5386, 1540, 5385, 6183, 5459, 0, 0, 5455, 6183, - 748, 1554, 1288, 6183, 1382, 1492, 1442, 1509, 1288, 0, - 1270, 1290, 1294, 1299, 1313, 1523, 1327, 1544, 1339, 1337, - 1349, 1396, 1449, 1541, 1494, 1488, 1510, 1542, 1550, 1543, - 1575, 1555, 1550, 1561, 1548, 1562, 1583, 1579, 1598, 1593, - 1603, 1593, 1598, 1609, 1597, 1612, 1631, 1607, 1615, 1605, - 1621, 1625, 1627, 1613, 1641, 1629, 1661, 1664, 1660, 1634, - 1649, 1643, 0, 5410, 6183, 5381, 1413, 0, 930, 6183, - 1041, 1048, 1655, 1671, 1672, 1678, 1662, 1683, 1021, 1168, - 6183, 1736, 1732, 1740, 6183, 1755, 1759, 1787, 1795, 1831, - - 1916, 5380, 1422, 6183, 1812, 1849, 1830, 1874, 1912, 1841, - 1934, 1953, 1960, 1991, 1942, 5377, 6183, 5451, 0, 5445, - 6183, 1542, 6183, 1670, 1691, 5398, 6183, 0, 1697, 6183, - 1707, 1729, 1738, 1757, 1766, 1758, 1775, 1806, 5369, 5364, - 1707, 6183, 5366, 5361, 1769, 6183, 5363, 5359, 0, 1793, - 1791, 1770, 6183, 1817, 1815, 1849, 1850, 1854, 1857, 5361, - 1823, 5358, 5356, 1825, 6183, 5336, 5318, 1879, 6183, 5273, - 1122, 0, 2008, 5333, 6183, 5317, 5213, 6183, 0, 2012, - 5251, 6183, 5221, 5084, 6183, 2020, 6183, 5135, 5058, 4987, - 6183, 0, 6183, 0, 6183, 2025, 4926, 0, 0, 2034, - - 2000, 1849, 1849, 1871, 1885, 1887, 1896, 4924, 4903, 1917, - 2038, 4893, 0, 2045, 1953, 4886, 1306, 2048, 4879, 0, - 0, 2053, 1956, 1962, 1984, 4876, 1331, 0, 1994, 2001, - 2063, 4865, 0, 0, 1470, 2066, 2057, 2060, 2064, 1973, - 2038, 2014, 2020, 2018, 4801, 4789, 2093, 4781, 0, 2097, - 2045, 2056, 4780, 2100, 4771, 2108, 2090, 2117, 1509, 1692, - 0, 2083, 2080, 2075, 2092, 2095, 2104, 2097, 2100, 2100, - 2102, 2117, 2108, 2122, 2126, 2125, 2116, 2120, 2133, 2125, - 2120, 0, 2126, 2127, 2123, 2137, 2134, 2143, 0, 2138, - 2149, 2152, 2148, 2155, 2151, 2167, 2165, 4797, 2169, 2156, - - 2162, 2162, 2159, 2180, 2167, 2181, 2173, 2183, 2173, 2190, - 2190, 2177, 2196, 2186, 2184, 2190, 2184, 4785, 2203, 2256, - 2186, 2195, 2212, 2200, 2210, 2236, 2211, 2228, 2228, 2224, - 2228, 2233, 2227, 2240, 2237, 2238, 2245, 6183, 6183, 6183, - 2229, 2252, 2242, 2258, 2248, 2253, 6183, 6183, 2274, 2295, - 2275, 2277, 1097, 2281, 1347, 2291, 2296, 1930, 2303, 2250, - 2285, 2299, 2283, 2283, 4784, 2293, 2287, 4778, 2305, 6183, - 6183, 6183, 6183, 6183, 2288, 2291, 2290, 2311, 2299, 2296, - 2303, 2314, 6183, 6183, 6183, 6183, 6183, 6183, 6183, 6183, - 6183, 6183, 4820, 4817, 2342, 4698, 6183, 4768, 4758, 2369, - - 4655, 6183, 4724, 4685, 2372, 4606, 2375, 4541, 2307, 2351, - 2334, 2344, 2346, 2348, 2360, 2343, 4554, 6183, 2355, 2387, - 4517, 2363, 6183, 6183, 2391, 4497, 2358, 2353, 4480, 6183, - 6183, 2361, 2361, 2399, 4427, 2405, 2412, 2419, 1915, 2386, - 2361, 2378, 2371, 2393, 2379, 6183, 2440, 4416, 2396, 2398, - 2442, 2450, 2446, 4415, 2438, 2441, 2445, 2447, 2449, 2405, - 2422, 2439, 2430, 2437, 2436, 0, 2450, 2451, 2448, 2438, - 2440, 2461, 2438, 2444, 2447, 0, 0, 2448, 2446, 2467, - 2461, 2466, 2451, 2456, 2461, 0, 4440, 2460, 2457, 2464, - 0, 2535, 4438, 0, 2470, 2489, 2501, 2504, 2494, 2511, - - 0, 2499, 2509, 2542, 2522, 2519, 2500, 2515, 0, 2522, - 2515, 2528, 2519, 2529, 2523, 2530, 2533, 2627, 4396, 2561, - 2523, 2523, 0, 2539, 2547, 2544, 2531, 2548, 2549, 2543, - 2546, 2566, 0, 2562, 2565, 2573, 2572, 0, 2577, 0, - 2578, 2560, 2560, 4423, 2572, 0, 1366, 2597, 2599, 2584, - 6183, 2055, 2616, 2583, 2609, 2617, 2628, 4421, 2617, 2605, - 2608, 2616, 2625, 2630, 2624, 2628, 2633, 2619, 0, 2624, - 2632, 4420, 2642, 2644, 2647, 2705, 4385, 2708, 4381, 2716, - 4379, 2494, 2721, 2700, 4373, 2654, 2658, 4377, 2679, 2687, - 2730, 2696, 4376, 2699, 2690, 2735, 2738, 2744, 4341, 2702, - - 2748, 2757, 2750, 4316, 2708, 4344, 2716, 0, 6183, 2759, - 2764, 2766, 4309, 2755, 2757, 2759, 2761, 2764, 2712, 2721, - 2744, 2759, 2753, 2784, 2793, 2786, 4308, 6183, 2763, 2795, - 2801, 2751, 2780, 0, 0, 2759, 2771, 2766, 2784, 2769, - 0, 2788, 2777, 2791, 2793, 2790, 2783, 2783, 2795, 2803, - 4327, 0, 4321, 2801, 2793, 2805, 0, 2792, 2866, 4283, - 2809, 0, 2802, 2878, 2812, 2815, 2815, 0, 2816, 2882, - 4277, 2822, 0, 0, 0, 2829, 2846, 2851, 2861, 2866, - 2854, 2855, 2852, 2874, 2867, 2871, 2877, 2877, 2880, 2860, - 4275, 2967, 4274, 2877, 0, 0, 2882, 0, 2886, 2887, - - 0, 2885, 2886, 2888, 0, 2874, 2892, 2886, 0, 2889, - 0, 4302, 2903, 2902, 6183, 2932, 2939, 2664, 2938, 2933, - 2934, 2941, 2947, 2951, 2901, 0, 2914, 2927, 4288, 2949, - 4269, 2940, 2955, 4237, 2955, 4235, 2952, 2966, 2959, 4226, - 0, 3025, 3028, 3038, 3041, 4193, 3045, 3053, 3055, 3057, - 4181, 3012, 3065, 3069, 3073, 4176, 3048, 2954, 2954, 3021, - 3026, 4203, 3078, 3084, 4239, 4172, 3038, 3045, 3045, 6183, - 3086, 3051, 3093, 4194, 3065, 3062, 3101, 3063, 3065, 3072, - 3079, 3077, 3106, 6183, 3115, 4159, 3091, 3076, 0, 3079, - 0, 3084, 3088, 0, 3104, 3106, 3156, 3110, 0, 3113, - - 3105, 3121, 3105, 3110, 0, 3114, 0, 3176, 3130, 3126, - 4157, 3131, 3148, 3186, 4222, 4150, 3139, 3150, 0, 3158, - 3150, 4148, 3165, 3164, 0, 3170, 0, 3173, 3173, 3159, - 3205, 3175, 3179, 3181, 3181, 3179, 4154, 3174, 4147, 3182, - 3201, 3191, 3194, 3190, 3195, 3212, 3213, 4117, 3200, 0, - 3214, 3200, 0, 3247, 3223, 0, 3218, 3226, 0, 3214, - 3221, 0, 3247, 3253, 3255, 3261, 4171, 3259, 3268, 4152, - 3262, 3245, 3250, 3255, 3252, 0, 3261, 3271, 0, 3265, - 0, 3267, 3272, 3266, 3268, 3269, 3309, 3334, 3336, 3288, - 3283, 3291, 3295, 3292, 3296, 3344, 3350, 3364, 3378, 3384, - - 3416, 3371, 4076, 0, 3317, 3315, 6183, 3327, 3338, 3350, - 3369, 3364, 3366, 0, 3366, 3366, 4074, 0, 3365, 0, - 3377, 3382, 0, 0, 3443, 4142, 4071, 3384, 0, 0, - 3387, 3383, 3402, 3401, 3450, 4139, 4057, 3409, 3410, 3412, - 3420, 2969, 4051, 0, 0, 3422, 3423, 0, 0, 3472, - 3430, 0, 3428, 3483, 4119, 4043, 3443, 3443, 3431, 3440, - 3439, 3458, 3463, 3451, 3453, 3457, 3474, 3460, 3480, 3467, - 3474, 3478, 3489, 3474, 3473, 3474, 3490, 3547, 4107, 4024, - 0, 3495, 3483, 3494, 3492, 3515, 2983, 3538, 3521, 3544, - 3546, 3545, 3547, 3489, 3497, 4045, 3537, 3546, 3551, 3549, - - 3550, 3551, 3544, 3545, 3551, 3558, 3545, 3546, 3562, 3551, - 3550, 3565, 3619, 3625, 3634, 3641, 3996, 3548, 3558, 3591, - 3588, 3597, 3600, 3603, 3609, 0, 3612, 3623, 3615, 3617, - 3113, 3980, 0, 3622, 3611, 3624, 3624, 3580, 3927, 3639, - 3618, 3638, 3628, 3585, 3021, 3670, 3639, 3630, 3706, 3923, - 3852, 0, 3641, 3649, 3664, 3651, 3688, 3841, 3864, 3654, - 3847, 3661, 3687, 3659, 3670, 3687, 3672, 3692, 3699, 3700, - 3685, 3703, 3707, 3710, 3700, 3699, 0, 3705, 0, 3727, - 3816, 3700, 0, 3707, 3703, 3342, 3735, 3863, 3856, 3841, - 3733, 3835, 3828, 0, 3790, 3714, 0, 0, 3715, 0, - - 0, 0, 3727, 0, 3777, 3724, 3725, 3731, 3743, 3741, - 3730, 3742, 3806, 3812, 3821, 3828, 3843, 3858, 3873, 3880, - 3917, 3924, 3739, 3753, 3739, 3741, 3764, 3760, 3789, 3799, - 3805, 3791, 0, 3803, 3808, 3767, 3784, 3902, 0, 3831, - 3860, 3852, 3773, 3836, 3908, 3871, 3860, 3871, 3884, 3947, - 3951, 3903, 3737, 0, 3892, 3782, 3724, 0, 3917, 3903, - 3909, 3878, 3842, 3954, 3918, 3918, 3925, 3929, 3944, 3944, - 3939, 3976, 3957, 3945, 3960, 3943, 3966, 3949, 3970, 3969, - 3950, 3956, 3977, 3971, 3970, 4005, 4008, 4039, 0, 3990, - 3990, 4010, 4016, 4018, 3986, 4003, 4010, 4002, 4011, 4020, - - 4013, 4053, 3750, 4007, 4011, 6183, 4083, 4089, 4099, 4105, - 4119, 4146, 4156, 4179, 4193, 4207, 4213, 4241, 4256, 4279, - 4288, 4017, 0, 4022, 4024, 0, 4033, 4126, 4037, 4035, - 0, 0, 4163, 4186, 4056, 3706, 0, 0, 4082, 4175, - 4264, 4083, 3543, 4105, 4100, 4129, 4157, 4222, 3534, 4166, - 3460, 6183, 4051, 4055, 4273, 4183, 4226, 4225, 4307, 4315, - 4252, 3439, 4268, 4267, 4272, 4258, 4268, 4271, 4276, 4133, - 3401, 4295, 4286, 4303, 4303, 4312, 4305, 4303, 4300, 4375, - 4318, 4305, 4312, 4315, 4381, 4384, 4329, 3390, 4324, 4327, - 4362, 3452, 3412, 4327, 0, 0, 4344, 4365, 0, 4362, - - 4423, 4430, 3335, 4368, 4449, 0, 4454, 4461, 4476, 4491, - 4498, 4535, 4365, 0, 4367, 4381, 4518, 4521, 3321, 4527, - 4388, 4541, 3319, 4382, 3302, 4437, 4549, 3296, 4447, 3283, - 4445, 4470, 3310, 4458, 3275, 4468, 4557, 4565, 4494, 3269, - 4512, 4538, 4516, 4578, 3229, 4532, 3223, 4548, 4537, 4560, - 4537, 4558, 4401, 4586, 3132, 3101, 4563, 3048, 4606, 4553, - 4574, 4560, 4568, 4592, 4574, 4588, 4589, 4590, 4605, 4581, - 4591, 4600, 6183, 4605, 0, 4652, 3002, 4599, 2989, 4593, - 4595, 4634, 4619, 0, 4596, 4617, 4673, 4625, 4631, 2965, - 2938, 4642, 4679, 4682, 2919, 4709, 4700, 2933, 2926, 4645, - - 4717, 4648, 2893, 2885, 4692, 4729, 2796, 4658, 4676, 2785, - 4662, 4661, 2772, 4679, 4696, 4686, 4707, 0, 4746, 4758, - 2737, 4703, 2733, 4704, 4719, 2697, 2665, 4707, 4725, 4717, - 4728, 2679, 4721, 4785, 2601, 4794, 2561, 4737, 4797, 4737, - 4804, 2545, 4752, 2566, 4754, 4754, 4746, 4756, 4772, 4767, - 4765, 4768, 4768, 4771, 6183, 4791, 4792, 4778, 4777, 6183, - 2533, 4778, 4780, 4796, 4811, 4784, 0, 4856, 4790, 2559, - 2511, 4799, 4863, 6183, 2327, 2318, 4872, 4806, 4808, 4889, - 4812, 2267, 4892, 6183, 2208, 2164, 4831, 4829, 4900, 0, - 4903, 4843, 4845, 4861, 4910, 2069, 2024, 4853, 4851, 4865, - - 4863, 4917, 2039, 4920, 2001, 4874, 4928, 1938, 1918, 4886, - 4931, 1916, 4889, 4914, 1904, 4898, 4907, 4900, 4911, 4904, - 4921, 4909, 4914, 6183, 4916, 4915, 4918, 4918, 4936, 6183, - 6183, 4962, 0, 4933, 4963, 4938, 4948, 4951, 4945, 1897, - 4967, 4969, 4959, 1884, 4969, 4962, 5007, 1870, 5016, 1863, - 4959, 4971, 0, 1859, 5032, 4964, 4986, 4992, 5036, 1845, - 4998, 5043, 5053, 1821, 4990, 4993, 5060, 1782, 5003, 1773, - 5007, 5023, 6183, 5005, 5024, 5010, 5017, 5021, 5033, 5038, - 6183, 5027, 5026, 5046, 5043, 6183, 5048, 5081, 1769, 5052, - 5058, 5043, 5060, 5059, 6183, 0, 0, 5063, 5058, 5054, - - 1762, 1758, 5074, 5070, 5108, 1742, 1760, 1362, 5071, 1723, - 5075, 5131, 5097, 5076, 1704, 1692, 5087, 5082, 5102, 1688, - 5094, 5091, 5108, 5116, 6183, 5114, 5104, 5120, 5119, 5108, - 5106, 5115, 6183, 5119, 6183, 1685, 5110, 1713, 0, 5122, - 5137, 5124, 5133, 5126, 5132, 5134, 1646, 5139, 1340, 1635, - 5139, 5145, 1661, 1611, 1530, 5149, 5145, 5151, 5163, 5203, - 5169, 5160, 5164, 6183, 5166, 6183, 5165, 6183, 5186, 5177, - 0, 5179, 5191, 5183, 6183, 5194, 5184, 6183, 5184, 6183, - 1509, 1503, 5193, 5185, 5187, 5188, 5184, 5205, 5237, 5192, - 5263, 1491, 6183, 5200, 5208, 6183, 5214, 5224, 6183, 5217, - - 1518, 5219, 5232, 6183, 5223, 1454, 5230, 5237, 5242, 5244, - 5275, 1425, 5284, 1394, 5230, 1371, 5247, 6183, 5242, 6183, - 5251, 5252, 5259, 6183, 5249, 5257, 5253, 5276, 5279, 5280, - 1326, 5277, 5268, 5270, 5267, 5274, 5270, 5286, 5343, 5275, - 5298, 5299, 5300, 5291, 5293, 6183, 5360, 5302, 5369, 1309, - 5373, 1749, 1263, 1239, 5310, 1257, 1149, 5322, 5324, 6183, - 5303, 5334, 6183, 1110, 1107, 1078, 5327, 5339, 5330, 5332, - 5329, 6183, 5356, 1004, 5358, 5347, 5349, 6183, 5314, 5361, - 5341, 5354, 5357, 5402, 1000, 5354, 5406, 5354, 5350, 989, - 6183, 5369, 5430, 5368, 5368, 5391, 5385, 5397, 5378, 5433, - - 6183, 5519, 5529, 5539, 5549, 5559, 5569, 5579, 5589, 5599, - 5609, 5619, 5629, 5639, 5649, 5659, 5669, 5676, 5681, 946, - 5687, 5689, 943, 5698, 5703, 936, 5704, 5706, 5712, 906, - 5719, 5729, 5739, 5749, 5759, 5769, 5778, 5787, 898, 5797, - 5807, 876, 857, 5817, 752, 5827, 5834, 5839, 749, 5845, - 5847, 742, 5856, 5861, 725, 5862, 5864, 5870, 703, 5877, - 5887, 5897, 5907, 5917, 5927, 5936, 5945, 695, 5955, 5965, - 662, 654, 5975, 652, 5985, 5995, 546, 498, 6001, 480, - 6005, 478, 6012, 6022, 6032, 6042, 6052, 6062, 6072, 6082, - 6092, 6102, 6112, 6122, 6132, 6142, 6152, 6162, 6172 - + 0, 0, 94, 0, 186, 187, 199, 0, 293, 0, + 387, 0, 480, 484, 497, 501, 0, 0, 594, 0, + 687, 690, 699, 710, 721, 732, 476, 481, 482, 486, + 491, 496, 6207, 6185, 6184, 6183, 825, 0, 504, 505, + 918, 928, 1021, 0, 1115, 0, 511, 513, 1209, 0, + 1302, 1308, 0, 0, 1323, 1360, 493, 512, 6229,17872, + 1316, 1330,17872, 1336, 1451, 102, 695,17872, 6210,17872, + 503, 6208, 6212, 924,17872, 1511, 1312, 726, 1343, 679, + 912, 668, 1387, 1520, 490, 1527, 717, 1416, 1597, 1583, + 901, 1431, 1664, 927, 1591, 1422, 1672, 1315, 471, 1409, + + 1486, 1679, 1688, 1697, 1706,17872,17872, 872,17872, 500, + 6202, 1708, 1657, 1758, 1752, 1775, 1764, 1781, 1730, 1796, + 1805, 1814, 1823, 1832,17872,17872, 521,17872, 1919, 2012, + 1940, 523, 1967, 497,17872, 721, 919, 928, 498, 1297, + 917, 2059, 1915, 2050, 2059, 2068, 2077, 2086,17872, 1556, + 1737, 1928, 538, 1983, 2028, 1874, 2095, 2104, 2113, 2122, + 2131, 2140,17872,17872,17872, 0,17872, 574, 0,17872, + 0,17872,17872, 666, 683, 696, 707, 2205, 6133, 6107, + 17872,17872,17872,17872, 739,17872, 6113, 6102,17872,17872, + 17872,17872, 782, 6100, 6091,17872,17872,17872, 907,17872, + + 17872, 783, 0,17872, 0, 0, 735, 933, 1668, 1582, + 6096, 6088,17872,17872, 6088, 6080,17872,17872,17872,17872, + 17872,17872, 785, 6055, 6047,17872,17872,17872,17872, 924, + 6053, 6045, 0, 2228, 0, 0, 2245, 0,17872, 2261, + 0, 0, 6078, 0, 6075,17872, 1394, 1587,17872, 2352, + 1954,17872,17872, 6106,17872, 6097, 2000, 2205, 2217, 2223, + 17872, 2197, 2240, 2257, 2296, 2305, 2325,17872, 939,17872, + 1638, 1715,17872, 0,17872,17872,17872, 6074, 1279, 6008, + 5992,17872, 1857, 2327,17872, 2446, 2211,17872,17872,17872, + 6062, 2332, 2396, 2412, 2390, 2427, 2436, 2461, 2470, 2479, + + 17872, 2257,17872,17872, 2527, 2489, 2498, 2507, 2518, 2527, + 2542,17872, 1279,17872, 2392, 2629,17872, 2720, 2545,17872, + 6058,17872, 806, 6057, 2624,17872,17872, 2606, 2615,17872, + 2573, 2602, 2664, 2673, 2693, 2702,17872, 2647, 2671, 0, + 6059,17872, 1300, 1318, 5987,17872, 2674, 2764, 0, 6051, + 17872, 1316, 1329, 5955, 1333, 1347, 1349, 2789, 5951,17872, + 2757, 2735, 2744, 2753, 2776, 2785, 2801, 0, 2889, 2833, + 2842, 2862, 2871, 2904, 2913, 2573, 2922, 2931, 2940, 2949, + 2958, 2967, 2785,17872, 2976, 2985, 2994, 3003, 3012, 3021, + 6012, 2840, 6011, 1427, 1499,17872, 1501, 3094, 3100, 3076, + + 3106, 2843, 3082, 3122, 3147, 3164, 3170, 3206, 3176, 3249, + 3236, 3242, 3280, 3128, 3274, 3286, 3357, 3134, 3322, 3328, + 3336, 3365, 3396, 3371, 3402, 3409, 3429, 3435, 3417, 3450, + 3487, 3495, 3457, 3512, 3501, 3526, 3555, 3579, 3650, 3586, + 3651, 3562, 3573, 3607, 3155, 3637, 3666, 3651, 3690, 3704, + 3735, 3696, 3720, 3728, 2871, 3307,17872, 3051, 3750, 3759, + 3768, 3777, 3786, 3795, 3804, 3813, 3822, 3831, 3840, 3849, + 3858, 3052, 3867, 3876, 3885, 3894, 3903, 3912, 995,17872, + 6009, 3479, 3963, 3975, 3981, 3987, 3969, 3993, 3938, 4007, + 4016, 4025, 4034, 3206, 4043, 4052, 1296,17872, 4139, 4145, + + 4160,17872, 4184, 1377, 1661, 1605, 1593, 4153, 4175, 4184, + 4199, 4208, 4217, 4226, 4235, 1334,17872, 1680, 2053, 1607, + 1676, 1913, 1674, 3095, 4299, 3566, 1520, 3253, 4261, 4290, + 4299, 4308, 4317, 3476, 4326, 4335,17872, 3388, 4344, 4353, + 4362, 4371, 4380, 4389, 3442, 4398, 4407, 4416, 4425, 4434, + 4443, 4523,17872, 4453, 4462, 4471, 4480, 4489, 4498, 1405, + 17872, 4548, 4565, 4273,17872, 4511, 4520, 4540, 4563, 4580, + 4589, 4598, 4251, 4607, 4616, 4625, 3948, 4634, 4643, 0, + 1430,17872, 1368, 1434, 1461, 1523, 1936, 1522, 1628, 1685, + 5936, 5924, 1652,17872, 5927, 5911, 1653,17872, 5913, 5906, + + 0, 1672, 1756, 1822,17872, 1770, 1884, 1904, 1906, 1918, + 2010, 2013, 5909, 1513, 5902, 5899, 1823,17872, 5892, 5886, + 1912,17872, 5804, 487, 0, 3380, 5874,17872, 5844, 5776, + 17872, 0, 4238, 5816,17872, 5809, 5742,17872, 3678,17872, + 5815, 5804, 5738,17872, 0,17872, 0,17872, 3160, 5736, + 0, 4731, 4675, 4684, 4704, 4713, 4746, 4755, 3914, 4764, + 4773, 4782, 4791, 4800, 4809, 3620, 2007, 4854, 4861, 4867, + 4878, 4887, 4826, 4902, 4911, 4920, 4929, 3961, 4938, 4947, + 2067, 4961, 5735, 0, 4971, 2063, 5734, 613, 5034, 5733, + 0, 5125, 4959, 4973, 4983, 4992, 5001, 5010, 4265, 5019, + + 5028, 5069, 5078, 5098, 5107, 5165, 5152, 5158, 5178, 5150, + 5177, 5193, 5202, 5211, 4835, 5220, 5229, 4540, 5238, 5247, + 5256, 5265, 5274, 5283, 5334, 5293, 4692, 5302, 5311, 5322, + 4851, 5331, 5349, 2056, 5418, 5732, 0, 5509, 5358, 5367, + 5376, 5385, 5394, 5403, 4713, 5412, 5453, 5462, 5482, 5491, + 5524, 5763, 5549, 5761, 3098, 2216, 2436, 5597, 5542, 5576, + 5582, 5564, 5575, 5597, 5612, 5621, 5542, 5630, 5639, 5726, + 5698, 0, 5729, 2207, 2229, 5584, 5732, 5562, 0, 5735, + 2221, 2255, 5561, 2369, 2366, 2373, 5559, 5660, 5036, 5669, + 5678, 5687, 5696, 5705, 5714, 5723, 5420, 5747, 5756, 5765, + + 5774, 5783, 5792, 5499, 5801, 5810, 5818, 5827, 5836, 5845, + 5854, 5863, 5872, 5620, 5959, 5557, 3289, 1918, 2095, 3293, + 2238, 5948, 5540, 5921, 5954, 5962, 5968, 5979, 6002, 6048, + 6012, 6062, 6071, 6106, 6092, 6150, 6115, 6157, 6199, 6175, + 6186, 6215, 6206, 6222, 6239, 5992, 6257, 6301, 6287, 6310, + 6323, 6329, 6336, 6267, 6369, 6354, 6382, 6415, 6421, 6408, + 6436, 6462, 6452, 6501, 6474, 6480, 6508, 6533, 6559, 6541, + 6587, 6569, 6598, 6604, 6613, 6627, 6659, 6620, 6651, 6706, + 6692, 6712, 6719, 6738, 6730, 6753, 6761, 6798, 6824, 6833, + 6841, 6883, 6863, 6870, 6854, 6895, 6877, 6942, 6934, 6977, + + 6964, 7006, 6988, 6030, 6451, 6930, 7003, 7021, 5887, 7030, + 7039, 6905, 7043,17872,17872,17872, 7058, 5899, 5536, 6681, + 6971, 5908, 7087, 7102, 7093, 7125, 5527, 5932,17872,17872, + 7067, 7080, 7158, 7174, 7183, 7189, 7204, 7197, 7219, 7268, + 7226, 7283, 7255, 7276, 7244, 7289, 7304, 7313, 7321, 7330, + 7339, 7348, 6130, 7357, 7366, 7375, 7383, 7392, 7401, 7410, + 6254, 7419, 7428, 6791, 7482, 7438, 7446, 7455, 7467, 7476, + 6354, 7497, 7506, 6782, 6812, 7515, 2429, 2652, 2725, 5466, + 2903, 3094, 3085, 5465, 3103,17872,17872,17872,17872,17872, + 3158, 3161, 3208, 3256, 3279, 3281, 3297, 3321, 3335,17872, + + 17872,17872,17872,17872,17872,17872,17872,17872,17872, 5504, + 5391, 6096, 5186,17872, 5246, 5245, 6121, 5160,17872, 5233, + 5222, 6142, 5143, 5142, 7524, 7532, 7541, 7550, 7559, 6680, + 7568, 7577, 7585, 7120, 6167, 5141, 3375, 3357, 7637, 7643, + 7650, 7666, 7625, 7476, 7591,17872, 7606, 3373, 6317, 5140, + 3379,17872,17872, 5121, 7665, 7614, 7681, 7690, 7699, 7150, + 7708, 7717, 7725, 7241, 6485, 5096, 7777, 7783, 7767, 7631, + 7730,17872,17872, 7747, 7789, 7747, 7755, 7804, 3370, 5091, + 7813, 7821, 7830, 7839, 7848, 7857, 7866, 7875, 7883, 7892, + 5115, 6518, 5052, 3734, 2401, 2479, 3581, 3720, 7959, 5111, + + 7965, 7972, 7989, 7978, 7995,17872, 7937, 6734, 5048, 3404, + 3496, 6938, 4971, 3577, 3586, 3696, 3706, 3731, 8001, 8007, + 7952, 8101, 8195, 8045, 8065, 8130, 8060, 5032, 0, 7167, + 4969, 4968, 4156, 4948, 4924, 4923, 4922, 4918, 8145, 8162, + 8213, 8230, 8224, 8292, 8256, 8241, 8309, 8282, 8327, 8320, + 8335, 8344, 8353, 8374, 8380, 8389, 8364, 8434, 8416, 8424, + 8460, 8474, 8445, 8468, 8480, 8539, 8496, 8505, 8565, 8528, + 8575, 8584, 8599, 8591, 8607, 8636, 8647, 8678, 8686, 8693, + 8704, 8654, 8718, 8741, 8747, 8765, 8785, 8774, 8809, 8798, + 8853, 8844, 8829, 8868, 8878, 8899, 8916, 8923, 8939, 9032, + + 8084, 8948, 9002, 9035, 8910, 9044, 9050, 9061, 9074, 9093, + 9133, 9086, 9145, 9157, 9101, 9173, 9180, 9196, 9186, 9203, + 9213, 7952, 8557, 8939, 4908, 8956, 9224, 9021, 8263, 8992, + 8547, 7909, 9237, 9282, 9292, 9320,17872, 9303, 9326, 9332, + 9349, 9411, 9417, 9428, 9151, 9361, 9377, 9311, 9390, 9386, + 9397, 9466, 9440, 9446, 9461, 3731, 3731, 3736, 3746, 3987, + 4122, 4148, 4157, 4163, 4149, 0, 4154, 4180, 4874, 4190, + 4866, 4873, 5115, 7982, 4844, 8491, 4824, 8173, 4823, 9560, + 9654, 9504, 0, 7848, 4822, 4729, 5128, 4757, 9537, 9592, + 9544, 9512, 9606, 5136, 0, 8134, 4702, 4669, 5148, 9748, + + 9842, 9533, 0, 8543, 4659, 4658, 9631, 9621, 9700, 9599, + 17872, 9936,10030, 9692, 4717, 0, 8623, 4654, 4573, 5976, + 4634, 4618, 4617, 4593, 4592, 9788, 9796, 9879, 0, 8701, + 4529, 4508,17872, 5169, 0, 8708, 4507, 4288,17872,17872, + 17872,17872,17872, 4343, 4272, 6131, 9886, 9779, 9984,10038, + 9807, 9900,10048,10067, 9966,10079, 9995,10054,10134,10147, + 10085,10164,10172,10181,10188,10204,10228,10194,10216,10234, + 10252,10274,10313,10283,10296,10319,10390,10273,10363,10353, + 10380,10414,10403,10421,10444,10432,10459, 9915,10459,10513, + 10474,10466,10482,10545,10553,10562,10582,10573,10595,10604, + + 10611,10634, 5489, 5167, 5829, 5953, 5963, 6066, 6081, 4271, + 10627,10727,10652,10731,10501,10755,10652,10748,10742,10763, + 10777,10784,10801,10844,10869,10790,10881,10887,10902,10893, + 4332, 9873,10932, 9638, 9816,10962,10718,17872,10973,10981, + 10913,10994,11002,11017,11033,11023,11062,11053,10627,10532, + 6147, 6202, 4279, 6218, 4277, 6229, 6298, 6316, 4276, 6316, + 4275, 6415, 6430, 6423, 6409, 4197, 0, 4234, 8714, 4218, + 1422, 4146, 4216, 8817, 4215, 1517, 4128, 4199, 9999, 4198, + 1480, 4123, 4122, 6424, 6518,10853,11133,11224, 4186,11081, + 11085,11109,11091,17872, 4091, 6534, 4090,11008,11125,11281, + + 4150, 4085, 8242,11304,11312,11318, 4079,17872, 4077, 4138, + 8596,11324,10096,11124,11330,11383,11103,11409,11339,11418, + 11424,11352,11431,11437,11477,11446,11518,11455,11525,11536, + 11560,11590,11604,11466,11616,11503,11583, 6543, 6541, 4073, + 11581,11622,11639, 9784, 4139,11637,11683,11718,11669,11724, + 6542, 4066,11661,11711,10345,11706,11735,11741,11820,10335, + 11757,11762,11831,11842,11853,11859,10396, 6561, 6565, 6611, + 6605, 4094, 6600, 4093, 3971, 6623, 8225, 6632, 6637, 7180, + 6730, 6751, 6805, 6811, 6807, 6952, 8175, 7020, 3970,11807, + 11889,11790,11869,11882,11912,11899,11983,11938,11922,11961, + + 12003, 4019,11946,11273,11954,11996,11553,12041,12052,12067, + 12090,12033,12132,12098,12084,12113,12138,12144, 7017, 7020, + 7141, 0, 9137, 3982, 7179, 0, 7178, 0, 7196, 7273, + 7279, 7286, 3976, 7287, 1599, 1743, 1982, 7310, 7649,12124, + 12193, 7634, 3936,12237,12243, 0, 0,12252, 8003,12342, + 12432,12522,12612,12702,12792, 8813,12229,12182,12211,12246, + 17872,12281,12287,12274, 3996, 8746,12374,12314,12325, 3995, + 9305,12381, 8034, 3932,12368,12404,12461,12416,12467,12473, + 12558,12453,12495,10811, 3811,12510,12584,12532,12564,12646, + 12621,12655,12629,11375, 3804,12548, 8067, 8160, 3735,12686, + + 12734, 3728, 703,12679,12740,12752,12797, 8192, 3726,12765, + 8212, 3712,12812,12776,12834, 8241, 3688,12821,12847,12823, + 12895,12927, 3755,12887, 8246, 8281, 8315, 8325, 8324, 8344, + 8474, 8462, 8537, 8602, 8658, 8765, 8795, 8801, 8861, 8868, + 8892, 8928, 8955, 9028, 9037, 9133, 9197, 9229, 9216, 9268, + 3684,12919,12933,12949,11587, 3741,12916,12866,12962,12978, + 3733,12989,12293,12995,13005,13012,13018,13042,13097,13076, + 13121,13127,13136,12592, 9271, 3696, 9305, 9307, 9313, 9313, + 9322, 9323, 9381, 9460, 9461, 9467, 9457, 9654, 9641, 9656, + 13082,13178,13229,13235, 9732, 3633,13244, 9760,13334,13424, + + 13514,13604,13694,13272,13784,13874,13251, 3629,13108,13204, + 13219,13275,13240, 3684, 9789,13354,13285, 3673, 9793,13367, + 9758, 3608,13373,13433,13453,13459, 3578, 1437,13322,13465, + 13498,13487,13547,13555, 3555, 1807,13411, 9772, 9827,13614, + 13587, 3554, 1809, 2238,13192,13636, 9836, 9847, 3553,12062, + 3563,13581, 9873, 3494,13524,13667, 9943, 9960, 9944, 3485, + 1850,13631, 3510,10023, 3507,10027,10112,10035,10110,10125, + 10120,10139,10181,10142,10165,10169,10160,10171,10182,10276, + 10274,10309,10355,10454,10398,10397,10395,10452,13642,13731, + 13677, 3475, 1926,13720,13756,13724, 3534,13344,13793,13652, + + 13803,13819,13825,13843,13857,13887,13913,13904,13923,12351, + 3466,10459, 0, 0,10463,10545, 0, 0, 0,10547, + 0, 3464,10552,10564,10591,10604,13395,13984,14016,10605, + 14023,14032,14042,10687, 0, 0,14132,14049,14059,14114, + 14141,14151,14169, 3434,14001,13881,14100,14071,14109, 3448, + 10870,14193, 3435,10871,14210,10702,14163,14224,14235,14248, + 3362, 1928, 2275,13830,14242,14277,14263,14305, 3329, 1960, + 2343,14078,10736,10717,14331,14290,12663,14232,10735, 3313, + 14296,10726,10752, 3312, 1972,14322,10868,14342,10894,10877, + 10883, 3308, 1980, 2483,14409,10881,10882,10885,10952,10975, + + 10980,10974, 9118,10987,10974,10990,10974,10993,11012,11007, + 11078,11078,11103,10677,11167,11274,17872,11296,11297,11282, + 11287,11323,11322,11391,14362, 3280, 1992, 2707,14412,14401, + 3337,14270,14180,14386,14425,14432,14442,14450,11393,11412, + 11423, 3303,11412,11424,11417,11432,11688, 3298,14415,14543, + 17872,14549,14558,14564,14579,14585,14594,14615, 0,14621, + 14657,14676,14690,14707,14716,14723,14663,12479,14693,14701, + 13066, 3292,11546,14731, 3283,11850,14781,11484,14684,14742, + 14750,13027,14758,11518, 3202,14764,14788,14829,13113,14864, + 11519, 3198,11519,11563,14821,14844,13301, 3196,11621, 3155, + + 17872,11694, 3149, 2226, 2880,14894,11708,11699,11728,11707, + 13565,14897,11737, 3130,11742,11788,11793,11820,11828,11829, + 11830,11387, 3127,11847,11898,11913,11893,11935,12004,12014, + 12056,12049,12040,14901, 3102,12049,12063,12080,12096,14967, + 12112,12209,12215,12219,14924,13835,14945,12228, 3081, 3142, + 14873,14953,14889,14959,14968,14978,14984,12219, 0, 0, + 12221,12229,12238,12226, 0,13341,12730, 3067,12231,13445, + 15077,15083,15092,15098,15119,15125,15134,15128,13851,15137, + 3105,12332,15102, 3102,12464,15144,12700,13840, 3037,12241, + 2886,15160,14481, 2860,12286, 2827,12284,12299,15151,15191, + + 2816,12286,12284,14650,15244,12327, 2813,12416,12417,12436, + 12414,14798, 2774,12465, 2773,12479,12579,12636,12639,12696, + 12409,12573, 2772, 2794,12715, 2746,12640,12944,12727,13321, + 12732,12765,17872,12773,12786,12898, 2716,12892,12910,13474, + 12911,12998,12927,13009,13019,13356,15229,13007,13032,13090, + 17872,13148,13176,15169,14848, 2715,13206, 2691, 2746,15206, + 15220,15230,15250,15260,13236,13233, 0,13215,13287,15021, + 13274, 2648, 2647,13285,15330,15356,15236,15285, 2694,13736, + 15352, 2693,13737,15369,13333,13422, 2630,13410,15340, 2623, + 13411,13444,13533,15375,15382,13631,13980,15275, 2622,13584, + + 2621,17872,13586,13601, 2642, 2612,13583,13616,13633,13693, + 2640,13742,14458, 2600,14525, 2599,13771,14826,13793,15416, + 2591,15451, 2589,17872,15446, 2588,13834, 2597,13873,13871, + 17872,15435, 2567,13928,13997,14011,14025,14019,14017,14026, + 14029,14059,17872,14079,14084,14074,14077,14103,17872, 2566, + 14114, 2627,15392,15312,15442,15471,15478,14134,14163, 0, + 14172, 2593, 2516,14195,15488,15464,15484, 2481,14629,15493, + 2473,14671,15523,14209,14206,14881,15501,14904,14223,14224, + 15572,14939, 2404,15594, 2401, 2400,14225,14233,14239,14299, + 14949, 2377,15411, 2366,14304,15304, 2335, 2323,14401,15344, + + 2317,14405,14406, 2279,14400,14453, 2276,14458, 2255,14506, + 14498,14520,14532,14532, 2254,14570,14566,14686,14572,14577, + 17872,14589,14590,14604,14626,14647,17872,17872,17872,15421, + 2315,15511,15517,15552,15603,15609,14663,14694,14780,14778, + 14799,15597,15621, 2314,15621,15651, 2275,15652,15689,14830, + 14825,15628, 2211,15631, 2192,14887,14913,15634, 2186,14930, + 2156,15669,14921,14949,14999,15727, 2043,15008,15731,15734, + 2031,15016,15044,15746, 2029,15051, 2027,15071,15084,15087, + 15083,15125,17872,15110,15130,15130,15135,15158,15247,15295, + 15329,15336,17872,15341,15355,15470,15469,17872,15492,15749, + + 2008, 2047,15700,15706,15742,15757,15481,15594, 0,15595, + 17872,15673,15718, 2045,15758,15810, 2036,15811,15825,15594, + 15583, 1946, 1944,15643,15701,15745,15753, 1906, 1900, 1494, + 15746, 1847,15785,15817,15805,15795, 1725, 1640,15808,15810, + 15828, 1617,15815,15810,15819,15825,15818,15829,15837,17872, + 15824,15837,15833,15834,15850,15850,15839,15848,15856,17872, + 15873,17872, 1519, 1567,15852,15872,15863,15897, 0,15880, + 15898, 1500,15911,15919, 1482,15942,15957,15900,15907,15931, + 15934,15930, 1402,15933, 915, 1336,15936,15955, 1365, 1341, + 1302,15958,15951,15952,15964,15929,17872,15954,15974,15976, + + 15964,17872,15968,15971,17872,15975,17872,15984,17872,16002, + 15992, 1356,15999,15890,16014, 0,16005, 1354,16024,16025, + 1337,16044,16052,17872,16010,16000,17872,17872,16000,17872, + 1248, 1247,16022,16013,16028,16030,16025,16066,16072,16053, + 16075, 1234,16054,16056,17872,16057,16073,16069,17872,16088, + 16093,17872, 1002,16040, 959, 954,16119,16120, 905,16136, + 16137,16094,17872,16083, 730,16119,16126,16131,16132,16083, + 753,16165, 718,16118, 711,17872,16168,16130,17872,17872, + 16135,17872,17872,16137, 747,16164,16179, 745,16180,16187, + 17872,16163,16179,16175,16194,16195,16196, 674,16194,16236, + + 672,16185,16187,16188, 722,16239,16246, 711,16267,16204, + 16287,16191,16231,16248,16255,16247,16248, 627,16251,17872, + 16257, 687,16284, 648,16304, 1550, 513, 502,16265, 536, + 527,16272,16275,16264,17872,16268,16294,17872, 480, 472, + 466,16282,16294,16285,16284,16278,16329,17872,16302, 461, + 16316,16305,16307,17872,16357,16360, 462,16319,16302,16316, + 16321,16363, 454,16329, 447,16328,16385,16328,16328, 117, + 16340,17872,16349,16388,16359,16342,16356,16351,16353,16372, + 17872,16364,16376,16356,16405,17872,16496,16508,16520,16532, + 16544,16556,16568,16580,16592,16604,16616,16628,16640,16652, + + 16664,16676,16685,16691,16699,16701,16704,16712,16717,16723, + 16725,16727,16730,16737,16740,16748,16760,16772,16784,16796, + 16808,16819,16830,16838,16844,16856,16864,16866,16872,16880, + 16886,16898,16907,16913,16925,16933,16935,16938,16946,16951, + 16957,16959,16961,16964,16971,16974,16982,16994,17006,17018, + 17030,17042,17053,17064,17076,17084,17090,17102,17114,17122, + 17124,17130,17142,17150,17156,17168,17180,17192,17200,17205, + 17207,17212,17213,17216,17224,17236,17248,17260,17272,17280, + 17286,17298,17310,17318,17320,17326,17338,17346,17355,17367, + 17376,17382,17394,17402,17409,17417,17422,17430,17432,17439, + + 17441,17444,17446,17453,17456,17464,17476,17488,17500,17512, + 17524,17532,17538,17550,17562,17574,17582,17584,17590,17602, + 17614,17622,17631,17643,17655,17663,17668,17670,17675,17676, + 17679,17687,17699,17711,17723,17731,17737,17749,17757,17763, + 17775,17787,17799,17811,17823,17835,17847,17859 } ; -static yyconst flex_int16_t yy_def[2200] = +static yyconst flex_int16_t yy_def[2949] = { 0, - 2101, 1, 2101, 3, 2102, 2102, 2101, 7, 2101, 9, - 2101, 11, 2103, 2103, 2104, 2104, 2105, 2105, 2101, 19, - 2105, 2105, 2106, 2106, 2107, 2107, 2108, 2108, 2109, 2109, - 2110, 2110, 2111, 2111, 2112, 2112, 2101, 37, 2113, 2113, - 2114, 2114, 2101, 43, 2115, 2115, 2116, 2116, 2101, 49, - 2117, 2117, 2101, 2101, 2101, 2101, 2101, 2118, 2119, 2120, - 2121, 2101, 2101, 2101, 2101, 2101, 2101, 2120, 2101, 2120, - 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, - 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, - 2120, 2120, 2122, 2101, 2101, 2101, 2101, 2123, 2101, 2101, - - 2101, 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2101, 2101, - 2101, 2101, 2101, 2124, 2124, 2124, 2101, 2124, 2124, 2101, - 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2101, 2101, 2125, - 2126, 2127, 2101, 2126, 2126, 2128, 2101, 2101, 2101, 2129, - 2101, 2101, 2129, 2101, 2129, 2101, 2101, 2129, 2129, 2129, - 2129, 2129, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2130, 2101, 2101, 2101, 2130, 2101, 2130, 2130, - 2130, 2130, 2130, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - - 2101, 2101, 2101, 2101, 2101, 2131, 2101, 2132, 2133, 2101, - 2134, 2101, 2101, 2135, 2136, 2101, 2137, 2101, 2101, 2101, - 2101, 2101, 2138, 2139, 2101, 2101, 2101, 2101, 2101, 2139, - 2139, 2139, 2139, 2139, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2140, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2141, 2142, 2101, 2101, 2101, - 2101, 2142, 2142, 2142, 2101, 2101, 2101, 2143, 2101, 2143, - 2101, 2101, 2101, 2101, 2101, 2101, 2144, 2145, 2101, 2101, - 2101, 2101, 2101, 2145, 2101, 2101, 2101, 2145, 2145, 2145, - 2101, 2101, 2101, 2101, 2101, 2101, 2146, 2101, 2101, 2101, - - 2101, 2101, 2101, 2101, 2101, 2147, 2148, 2149, 2150, 2101, - 2101, 2101, 2101, 2101, 2101, 2149, 2149, 2149, 2149, 2149, - 2149, 2149, 2149, 2149, 2149, 2149, 2149, 2149, 2149, 2149, - 2149, 2149, 2149, 2149, 2149, 2149, 2149, 2149, 2149, 2149, - 2149, 2149, 2149, 2149, 2149, 2149, 2149, 2149, 2149, 2149, - 2149, 2149, 2149, 2149, 2149, 2149, 2149, 2149, 2149, 2149, - 2149, 2149, 2149, 2149, 2149, 2149, 2149, 2149, 2149, 2149, - 2149, 2149, 2149, 2151, 2101, 2101, 2101, 2152, 2101, 2101, - 2101, 2152, 2152, 2152, 2152, 2152, 2152, 2152, 2101, 2101, - 2101, 2153, 2153, 2153, 2101, 2153, 2153, 2153, 2153, 2153, - - 2153, 2101, 2101, 2101, 2153, 2153, 401, 2153, 2153, 401, - 2153, 2153, 2153, 2153, 401, 2101, 2101, 2154, 2155, 2156, - 2101, 2101, 2101, 2155, 2155, 2157, 2101, 2158, 2101, 2101, - 2158, 2158, 2158, 2158, 2158, 2158, 2158, 2158, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2159, 2159, - 2159, 2101, 2101, 2159, 2159, 2159, 2159, 2159, 2159, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2160, 2101, 2161, 2101, 2101, 2101, 2101, 2162, 2101, - 2163, 2101, 2101, 2101, 2101, 2101, 2101, 2164, 2101, 2101, - 2101, 2165, 2101, 2166, 2101, 2101, 2101, 2167, 2168, 2101, - - 2101, 2168, 2168, 2168, 2168, 2168, 2168, 2101, 2101, 2101, - 2101, 2101, 2169, 2101, 2101, 2101, 2101, 2101, 2101, 2170, - 2171, 2101, 2171, 2171, 2171, 2101, 2101, 2172, 2172, 2101, - 2101, 2101, 2173, 2174, 2101, 2101, 2101, 2101, 2174, 2174, - 2101, 2174, 2174, 2174, 2101, 2101, 2101, 2101, 2175, 2101, - 2101, 2101, 2101, 2176, 2101, 2101, 2101, 2101, 2101, 2177, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2101, 2101, 2101, - 2178, 2178, 2178, 2178, 2178, 2178, 2101, 2101, 2179, 2179, - 2179, 2179, 2179, 2179, 2179, 2179, 2179, 2179, 2179, 2180, - 2180, 2181, 2181, 2181, 2181, 2181, 2181, 2181, 2181, 2101, - 2101, 2101, 2101, 2101, 2182, 2182, 2182, 2182, 2182, 2182, - 2182, 2182, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2161, 2161, 2101, 2101, 2101, 2163, 2163, 2101, - - 2101, 2101, 2164, 2164, 2101, 2101, 2183, 2101, 2101, 2101, - 2101, 2168, 2168, 2168, 2168, 2168, 2168, 2101, 2101, 2184, - 2101, 2101, 2101, 2101, 2185, 2101, 2171, 2171, 2171, 2101, - 2101, 2172, 2101, 2186, 2101, 2101, 2101, 2101, 2101, 2174, - 2101, 2101, 2174, 2174, 2174, 2101, 2187, 2101, 2101, 2101, - 2176, 2176, 2176, 2101, 2101, 2101, 2101, 2101, 2101, 2177, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2101, 2101, 2177, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - 2178, 2178, 2178, 2178, 2178, 2178, 2179, 2179, 2179, 2179, - 2101, 2179, 2179, 2179, 2179, 2179, 2179, 2180, 2180, 2181, - 2181, 2181, 2181, 2181, 2181, 2181, 2181, 2182, 2182, 2182, - 2182, 2182, 2182, 2182, 2182, 2188, 2101, 2189, 2101, 2190, - 2101, 2183, 2183, 2183, 2101, 2101, 2101, 2101, 2168, 2168, - 2168, 2168, 2168, 2168, 2101, 2184, 2184, 2184, 2101, 2101, - - 2185, 2185, 2185, 2101, 2171, 2171, 2171, 2172, 2101, 2186, - 2186, 2186, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2174, 2174, 2174, 2187, 2187, 2187, 2101, 2101, 2101, 2176, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2101, 2101, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2101, - 2101, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - 2177, 2177, 2177, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2178, - 2178, 2178, 2178, 2178, 2101, 2179, 2179, 2179, 2179, 2179, - 2179, 2179, 2179, 2179, 2180, 2180, 2181, 2181, 2181, 2181, - 2181, 2181, 2181, 2181, 2182, 2182, 2182, 2182, 2182, 2182, - 2182, 2188, 2188, 2188, 2188, 2101, 2189, 2189, 2189, 2189, - 2101, 2190, 2190, 2190, 2190, 2101, 2183, 2101, 2101, 2101, - 2168, 2168, 2101, 2191, 2101, 2101, 2168, 2168, 2168, 2101, - 2184, 2101, 2185, 2171, 2171, 2171, 2186, 2101, 2101, 2174, - 2174, 2174, 2187, 2101, 2101, 2101, 2177, 2177, 2177, 2177, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2101, 2101, - 2101, 2177, 2177, 2101, 2101, 2101, 2177, 2177, 2177, 2177, - 2101, 2101, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, - 2177, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2177, 2177, - 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2178, 2178, - 2178, 2178, 2179, 2179, 2179, 2179, 2179, 2179, 2179, 2179, - 2179, 2180, 2181, 2181, 2181, 2181, 2181, 2181, 2181, 2181, - 2182, 2182, 2182, 2182, 2182, 2182, 2188, 2189, 2190, 2101, - 2101, 2101, 2168, 2168, 2101, 2191, 2191, 2191, 2191, 2191, - - 2191, 2101, 2101, 2168, 2168, 2168, 2101, 2171, 2171, 2171, - 2101, 2101, 2174, 2174, 2174, 2101, 2101, 2177, 2177, 2177, - 2177, 2177, 2177, 2177, 2101, 2101, 2101, 2177, 2177, 2177, - 2177, 2177, 2177, 2177, 2101, 2101, 2101, 2101, 2101, 2177, - 2177, 2192, 2101, 2177, 2177, 2177, 2101, 2177, 2177, 2177, - 2177, 2177, 2177, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2177, 2177, 2177, 2101, 2101, 2101, - 2177, 2177, 2177, 2178, 2178, 2179, 2179, 2179, 2179, 2179, - 2179, 2179, 2179, 2180, 2181, 2181, 2181, 2181, 2181, 2181, - - 2181, 2182, 2182, 2182, 2182, 2182, 2101, 2101, 2101, 2168, - 2168, 2101, 2191, 2191, 2191, 2193, 2101, 2168, 2168, 2171, - 2171, 2171, 2101, 2101, 2174, 2174, 2101, 2177, 2177, 2177, - 2194, 2101, 2177, 2177, 2177, 2177, 2177, 2195, 2101, 2101, - 2101, 2177, 2177, 2192, 2192, 2101, 2177, 2101, 2101, 2101, - 2101, 2177, 2177, 2101, 2101, 2101, 2196, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2177, 2177, 2177, 2197, - 2101, 2177, 2177, 2178, 2178, 2179, 2179, 2179, 2179, 2179, - 2179, 2179, 2179, 2180, 2181, 2181, 2181, 2181, 2181, 2181, - - 2181, 2182, 2182, 2182, 2182, 2182, 2101, 2101, 2101, 2168, - 2168, 2101, 2198, 2193, 2191, 2191, 2193, 2193, 2198, 2193, - 2193, 2193, 2101, 2168, 2168, 2171, 2171, 2171, 2101, 2101, - 2174, 2101, 2177, 2177, 2177, 2194, 2194, 2101, 2177, 2177, - 2177, 2177, 2195, 2195, 2101, 2101, 2101, 2177, 2177, 2101, - 2101, 2101, 2101, 2177, 2101, 2199, 2101, 2177, 2101, 2101, - 2101, 2196, 2196, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2177, 2197, 2197, 2101, 2177, 2178, - 2178, 2179, 2179, 2179, 2181, 2181, 2181, 2182, 2182, 2182, - - 2101, 2101, 2101, 2168, 2168, 2101, 2198, 2198, 2198, 2198, - 2198, 2198, 2191, 2191, 2193, 2193, 2198, 2198, 2193, 2193, - 2193, 2168, 2168, 2171, 2171, 2171, 2101, 2101, 2174, 2101, - 2177, 2177, 2101, 2101, 2101, 2101, 2177, 2177, 2177, 2101, - 2101, 2101, 2101, 2101, 2101, 2177, 2177, 2101, 2101, 2101, - 2101, 2101, 2199, 2199, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2177, 2101, 2101, 2101, 2101, 2178, 2178, - 2179, 2179, 2179, 2181, 2181, 2181, 2182, 2182, 2182, 2101, - - 2101, 2101, 2101, 2101, 2168, 2168, 2198, 2198, 2198, 2193, - 2198, 2193, 2168, 2171, 2171, 2101, 2101, 2101, 2101, 2174, - 2101, 2101, 2101, 2101, 2101, 2177, 2101, 2101, 2101, 2101, - 2101, 2101, 2177, 2177, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2177, 2101, 2101, 2101, 2101, 2178, - 2178, 2179, 2181, 2182, 2182, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2198, 2193, 2168, 2171, 2101, - - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2177, 2101, 2101, 2101, 2101, 2177, 2177, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2178, 2178, 2179, 2181, 2182, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2198, 2168, 2171, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2177, - 2101, 2101, 2101, 2177, 2101, 2101, 2101, 2101, 2101, 2101, - - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2178, 2178, 2179, 2181, 2101, 2101, 2101, 2101, - 2168, 2171, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2177, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2178, - 2179, 2181, 2101, 2101, 2101, 2168, 2171, 2101, 2101, 2101, - - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2178, 2179, 2181, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2178, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - - 0, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101 - + 2786, 1, 2786, 3, 2787, 2787, 2786, 7, 2786, 9, + 2786, 11, 2788, 2788, 2789, 2789, 2790, 2790, 2786, 19, + 2790, 2790, 2791, 2791, 2792, 2792, 2793, 2793, 2794, 2794, + 2795, 2795, 2796, 2796, 2797, 2797, 2786, 37, 2798, 2798, + 2799, 2799, 2786, 43, 2786, 45, 2800, 2800, 2786, 49, + 2801, 2801, 2790, 2790, 2802, 2802, 2790, 2790, 2786, 2786, + 2786, 2786, 2786, 2803, 2804, 2805, 2806, 2786, 2786, 2786, + 2786, 2786, 2786, 2805, 2786, 2805, 2805, 2805, 2805, 2805, + 2805, 2805, 2805, 2805, 2805, 2805, 2805, 2805, 2805, 2805, + 2805, 2805, 2805, 90, 2805, 2805, 90, 90, 2807, 2786, + + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2808, 2786, 2786, + 2786, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2809, 2809, + 2809, 2786, 2809, 133, 2786, 133, 133, 133, 133, 133, + 133, 133, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2810, + 2811, 2812, 2786, 2811, 2811, 2813, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2814, 2786, 2786, 2814, 2786, + 2814, 2786, 2786, 2814, 2814, 2814, 2814, 2814, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2815, 2786, + + 2786, 2786, 2815, 2786, 2815, 2815, 2815, 2815, 2815, 2815, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2816, 2786, 2817, 2818, 2786, 2819, 2786, 2786, + 2820, 2821, 2786, 2822, 2786, 2786, 2786, 2786, 2786, 2823, + 2824, 2786, 2786, 2786, 2786, 2786, 2824, 2824, 2824, 2824, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2825, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2826, 2827, 2786, 2786, 2786, + 2786, 2827, 2827, 2827, 2786, 2786, 2786, 2786, 2786, 2786, + + 2786, 2828, 2786, 2786, 2828, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2829, 2830, 2786, + 2786, 2786, 2786, 2786, 2830, 2786, 2786, 2830, 2830, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2831, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2832, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2833, 2786, 2786, 2786, 2786, 2786, 2786, 2834, 2835, 2834, + 2834, 2834, 2834, 2834, 2834, 2836, 2786, 2786, 2786, 2786, + 2786, 2786, 2837, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2836, 2836, 2836, + + 2836, 2836, 2836, 2836, 2836, 2836, 2836, 2836, 2836, 2836, + 2836, 2836, 2836, 2836, 2836, 2836, 2836, 2836, 2836, 2836, + 2836, 2836, 2836, 2836, 2836, 2836, 2836, 2836, 2836, 2836, + 2836, 2836, 2836, 2836, 2836, 2836, 2836, 2836, 410, 410, + 410, 2836, 2836, 2836, 2836, 2836, 2836, 2836, 2836, 2836, + 2836, 2836, 2836, 2836, 2836, 2838, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2839, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2839, 2839, 2839, 2839, 2839, 2839, 2839, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2840, 2840, + + 2840, 2786, 2840, 503, 503, 503, 503, 503, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 503, 503, 503, + 503, 503, 503, 503, 503, 503, 503, 503, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2841, 2786, 2786, + 2786, 2786, 2786, 2786, 2842, 2786, 2786, 2786, 2786, 2786, + 2786, 2843, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2842, 2842, 2844, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2845, + 2786, 2786, 2845, 2845, 2845, 2845, 2845, 2845, 2845, 2845, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + + 2846, 2846, 2846, 2786, 2786, 2846, 2846, 2846, 2846, 2846, + 2846, 2846, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2847, 2786, 2848, 2786, 2786, 2786, + 2786, 2849, 2786, 2850, 2786, 2786, 2786, 2786, 2786, 2786, + 2851, 2786, 2786, 2786, 2852, 2786, 2853, 2786, 2786, 2786, + 2854, 2855, 2854, 2854, 2854, 2854, 2854, 2854, 2856, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2856, 2856, 2856, + 2856, 2856, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2857, 2786, 2786, 2786, 2786, 2786, 2786, + 2858, 2859, 2858, 2858, 2858, 2858, 2858, 2858, 2860, 2786, + + 2786, 2786, 2786, 2786, 2786, 2786, 2860, 2860, 2860, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2861, 2786, 2786, + 2786, 2786, 2786, 2786, 2861, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2862, 2863, 2862, 2862, + 2862, 2862, 2862, 2862, 2864, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2864, 2864, 2864, + 2864, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2865, 2786, 2786, 2786, 2786, 2786, 2786, 2866, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2867, 2867, 2867, 2867, 2867, + + 2867, 2867, 2867, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2868, 2786, 2786, 2786, 2786, 2786, + 2786, 2869, 2786, 2869, 2869, 2869, 2869, 2869, 2869, 2869, + 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, + 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, + 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, + 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, + 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, + 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, + 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869, + + 2869, 2869, 2869, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2869, 2869, 2786, 2786, 2786, 2786, 2786, 2786, 2870, + 2870, 2870, 2870, 2870, 2870, 2870, 2870, 2870, 2786, 2786, + 2786, 2786, 2871, 2871, 2871, 2871, 2871, 2871, 2871, 2871, + 2871, 2871, 2871, 2871, 2871, 2871, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2872, 2872, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2872, 2872, 2786, 2873, 2873, 2873, 2873, + 2873, 2873, 2873, 2873, 2873, 2786, 2786, 2786, 2786, 2786, + 2874, 2874, 2874, 2874, 2874, 2874, 2874, 2874, 2874, 2786, + + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2875, + 2875, 2786, 2786, 2786, 2876, 2876, 2786, 2786, 2786, 2877, + 2877, 2786, 2786, 2786, 2878, 2878, 2878, 2878, 2878, 2878, + 2878, 2878, 2786, 2786, 2879, 2786, 2786, 2786, 2880, 2880, + 2880, 2880, 2880, 2880, 2880, 2786, 2786, 2786, 2881, 2786, + 2786, 2786, 2786, 2786, 2882, 2882, 2882, 2882, 2882, 2882, + 2882, 2882, 2786, 2786, 2883, 2786, 2884, 2884, 2884, 2884, + 2884, 2786, 2786, 2786, 2885, 2885, 2885, 2786, 2786, 2786, + 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2786, 2786, + 2786, 2887, 2786, 2786, 2786, 2786, 2786, 2786, 2888, 2786, + + 2888, 2888, 2888, 2888, 2888, 2786, 2786, 2889, 2786, 2786, + 2786, 2890, 2786, 2786, 2786, 2786, 2786, 2786, 2891, 2891, + 2786, 2892, 2892, 2893, 2894, 2894, 2786, 2786, 2895, 2895, + 2895, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2896, 2896, + 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, + 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, + 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, + 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, + 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, + 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2786, + + 2786, 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, + 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, 2896, + 2896, 2897, 2897, 2786, 2786, 2898, 2898, 2898, 2898, 2898, + 2898, 2898, 2899, 2899, 2899, 2899, 2786, 2899, 2899, 2899, + 2899, 2899, 2899, 2899, 2900, 2900, 2786, 2901, 2901, 2786, + 2902, 2902, 2903, 2903, 2786, 2904, 2904, 2904, 2904, 2904, + 2904, 2904, 2904, 2904, 2905, 2905, 2905, 2905, 2905, 2905, + 2905, 2905, 2905, 2906, 2786, 2907, 2786, 2908, 2786, 2909, + 2909, 2910, 2911, 2911, 2911, 2786, 2786, 2786, 2912, 2912, + 2912, 2912, 2912, 2786, 2913, 2913, 2913, 2786, 2786, 2914, + + 2914, 2915, 2916, 2916, 2916, 2786, 2917, 2917, 2917, 2918, + 2786, 2919, 2919, 2920, 2786, 2921, 2921, 2921, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2922, 2922, 2922, 2923, 2923, + 2923, 2786, 2786, 2786, 2924, 2924, 2924, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2925, 2786, 2926, 2926, 2926, 2926, + 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2926, + 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2926, + 2926, 2926, 2926, 2926, 2926, 2926, 2786, 2786, 2926, 2926, + 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2786, 2786, 2926, + 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2926, + + 2926, 2926, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2926, 2926, 2926, 2926, 2926, 2926, 2926, + 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2926, + 2786, 2927, 2927, 2927, 2927, 2927, 2927, 2786, 2928, 2928, + 2928, 2928, 2928, 2928, 2928, 2928, 2928, 2928, 2929, 2929, + 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2931, + 2931, 2931, 2931, 2931, 2931, 2931, 2931, 2932, 2932, 2932, + 2932, 2786, 2933, 2933, 2933, 2933, 2786, 2934, 2934, 2934, + 2934, 2786, 2935, 2786, 2786, 2936, 2786, 2786, 2786, 2786, + 2936, 2936, 2936, 2786, 2937, 2786, 2938, 2939, 2939, 2939, + + 2786, 2921, 2786, 2922, 2922, 2922, 2923, 2786, 2924, 2786, + 2786, 2926, 2786, 2786, 2926, 2926, 2926, 2926, 2926, 2926, + 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2926, + 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2786, 2786, 2786, + 2786, 2926, 2926, 2786, 2786, 2786, 2926, 2926, 2926, 2926, + 2786, 2786, 2786, 2926, 2786, 2786, 2926, 2926, 2926, 2786, + 2786, 2926, 2926, 2926, 2926, 2926, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2926, 2926, + + 2926, 2786, 2927, 2927, 2927, 2927, 2927, 2928, 2928, 2928, + 2928, 2928, 2928, 2928, 2928, 2928, 2928, 2929, 2930, 2930, + 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2931, 2931, 2931, + 2931, 2931, 2931, 2931, 2932, 2933, 2934, 2786, 2786, 2936, + 2940, 2786, 2786, 2940, 2940, 1488, 1488, 2940, 1488, 2940, + 2940, 2940, 2940, 2940, 2940, 2786, 2786, 2936, 2936, 2936, + 2786, 2939, 2939, 2939, 2786, 2786, 2922, 2922, 2922, 2786, + 2786, 2926, 2786, 2786, 2786, 2926, 2926, 2926, 2926, 2926, + 2926, 2926, 2926, 2786, 2786, 2786, 2926, 2926, 2926, 2926, + 2926, 2926, 2926, 2786, 2786, 2786, 2786, 2786, 2786, 2926, + + 2926, 2786, 2941, 2786, 2926, 2926, 2926, 2786, 2786, 2926, + 2786, 2786, 2786, 2926, 2926, 2786, 2786, 2786, 2926, 2926, + 2926, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2926, 2926, 2926, 2786, 2786, 2786, 2926, 2926, 2926, + 2786, 2927, 2927, 2927, 2928, 2928, 2928, 2928, 2928, 2928, + 2928, 2928, 2928, 2929, 2930, 2930, 2930, 2930, 2930, 2930, + 2930, 2930, 2931, 2931, 2931, 2931, 2931, 2931, 2786, 2786, + 2936, 2940, 2940, 2940, 2786, 2786, 2940, 1488, 2940, 2940, + + 2940, 2940, 2940, 2940, 2940, 2940, 2942, 2786, 2936, 2936, + 2939, 2939, 2939, 2786, 2786, 2922, 2922, 2786, 2786, 2926, + 2786, 2786, 2926, 2926, 2926, 2926, 2786, 2943, 2786, 2926, + 2926, 2926, 2926, 2926, 2786, 2944, 2786, 2786, 2786, 2926, + 2926, 2786, 2941, 2941, 2786, 2926, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2926, 2926, 2786, 2786, 2786, 2786, + 2945, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2926, 2926, + 2926, 2786, 2946, 2786, 2926, 2926, 2786, 2927, 2927, 2927, + + 2928, 2928, 2928, 2928, 2928, 2928, 2928, 2928, 2928, 2929, + 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2931, 2931, + 2931, 2931, 2931, 2931, 2786, 2786, 2936, 2940, 2940, 2786, + 2947, 2942, 2940, 1488, 1488, 1488, 2940, 2942, 2942, 2947, + 2942, 2942, 2942, 2786, 2936, 2936, 2939, 2939, 2939, 2786, + 2786, 2922, 2786, 2786, 2926, 2786, 2926, 2926, 2926, 2926, + 2786, 2943, 2943, 2786, 2926, 2926, 2926, 2926, 2786, 2944, + 2944, 2786, 2786, 2786, 2926, 2926, 2786, 2786, 2786, 2786, + 2926, 2786, 2786, 2786, 2948, 2786, 2786, 2926, 2786, 2786, + 2786, 2786, 2945, 2945, 2786, 2786, 2786, 2786, 2786, 2786, + + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2926, 2786, 2946, 2946, 2786, 2926, + 2786, 2927, 2927, 2927, 2928, 2928, 2928, 2928, 2930, 2930, + 2930, 2930, 2931, 2931, 2931, 2931, 2786, 2786, 2936, 2940, + 2786, 2947, 2947, 2947, 2947, 2947, 2947, 2940, 1488, 2942, + 2942, 2947, 2947, 2942, 2942, 2942, 2936, 2936, 2939, 2939, + 2939, 2786, 2786, 2922, 2786, 2786, 2926, 2786, 2926, 2926, + 2926, 2786, 2786, 2786, 2786, 2926, 2926, 2926, 2786, 2786, + 2786, 2786, 2786, 2786, 2926, 2926, 2786, 2786, 2786, 2786, + + 2786, 2786, 2786, 2948, 2948, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2926, 2786, 2786, 2786, 2786, 2786, + 2927, 2927, 2927, 2928, 2928, 2928, 2928, 2930, 2930, 2930, + 2930, 2931, 2931, 2931, 2931, 2786, 2786, 2786, 2786, 2936, + 2940, 2947, 2947, 2947, 2942, 2947, 2942, 2936, 2939, 2939, + 2786, 2786, 2922, 2786, 2786, 2926, 2786, 2786, 2786, 2786, + 2786, 2926, 2786, 2786, 2786, 2786, 2786, 2786, 2926, 2926, + + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2926, 2786, 2786, 2786, 2786, 2786, 2927, + 2927, 2927, 2928, 2928, 2930, 2930, 2931, 2931, 2931, 2786, + 2786, 2786, 2786, 2786, 2947, 2942, 2936, 2939, 2786, 2786, + 2922, 2786, 2786, 2926, 2786, 2786, 2786, 2786, 2926, 2786, + 2786, 2786, 2786, 2926, 2926, 2786, 2786, 2786, 2786, 2786, + + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2927, 2927, 2927, 2928, 2928, 2930, 2930, 2931, + 2931, 2786, 2786, 2786, 2947, 2936, 2939, 2786, 2786, 2922, + 2786, 2786, 2926, 2786, 2786, 2786, 2926, 2786, 2786, 2786, + 2926, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2927, 2927, 2927, 2928, 2928, 2930, 2930, 2931, 2786, + 2786, 2936, 2939, 2786, 2786, 2922, 2786, 2786, 2926, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2926, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + + 2786, 2786, 2927, 2927, 2928, 2928, 2930, 2930, 2931, 2786, + 2786, 2936, 2939, 2786, 2786, 2922, 2786, 2786, 2926, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2927, 2927, 2928, 2928, 2930, 2930, + 2786, 2786, 2786, 2922, 2786, 2786, 2926, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2927, 2927, 2928, 2930, 2786, 2786, 2786, 2922, + 2786, 2786, 2926, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2927, 2786, 2786, 2786, 2922, 2786, 2786, + 2926, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2922, 2786, 2786, 2926, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + + 2786, 2786, 2786, 2786, 2786, 2786, 2922, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 0, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786 } ; -static yyconst flex_int16_t yy_nxt[6271] = +static yyconst flex_int16_t yy_nxt[17967] = { 0, - 54, 55, 56, 55, 57, 58, 59, 60, 61, 62, - 62, 57, 63, 64, 65, 66, 67, 68, 68, 57, - 57, 57, 69, 57, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 60, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 60, 60, - 54, 60, 93, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 60, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 60, 60, 54, - 54, 54, 54, 54, 54, 94, 95, 96, 96, 97, - 96, 96, 96, 96, 98, 96, 99, 99, 100, 101, - - 96, 101, 96, 96, 102, 102, 96, 96, 96, 96, - 96, 98, 98, 98, 98, 98, 103, 98, 98, 104, - 98, 98, 98, 98, 98, 98, 98, 105, 106, 107, - 98, 98, 98, 108, 98, 98, 98, 96, 98, 96, - 98, 98, 98, 98, 98, 103, 98, 98, 104, 98, - 98, 98, 98, 98, 98, 98, 105, 106, 107, 98, - 98, 98, 108, 98, 98, 98, 96, 96, 96, 96, - 96, 96, 96, 109, 111, 111, 311, 311, 312, 313, - 313, 311, 311, 112, 112, 113, 114, 115, 114, 113, - 113, 113, 116, 113, 113, 113, 117, 118, 113, 119, - - 120, 113, 116, 116, 113, 113, 113, 113, 113, 116, - 116, 116, 121, 122, 116, 123, 116, 116, 116, 116, - 116, 116, 116, 124, 125, 116, 126, 116, 127, 116, - 116, 116, 116, 116, 116, 113, 116, 113, 116, 116, - 116, 121, 122, 116, 123, 116, 116, 116, 116, 116, - 116, 116, 124, 125, 116, 126, 116, 127, 116, 116, - 116, 116, 116, 116, 113, 113, 113, 113, 113, 113, - 128, 113, 129, 129, 97, 129, 129, 130, 129, 131, - 132, 129, 129, 133, 129, 129, 129, 129, 129, 131, - 131, 129, 129, 129, 129, 129, 131, 131, 131, 131, - - 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, - 131, 134, 131, 131, 131, 135, 131, 131, 131, 131, - 131, 131, 129, 131, 136, 131, 131, 131, 131, 131, - 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, - 134, 131, 131, 131, 135, 131, 131, 131, 131, 131, - 131, 129, 129, 129, 129, 129, 129, 129, 129, 137, - 138, 139, 138, 137, 137, 137, 140, 141, 137, 137, - 142, 143, 144, 145, 146, 137, 140, 140, 137, 137, - 147, 137, 137, 140, 140, 140, 148, 149, 140, 150, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - - 151, 140, 152, 140, 140, 140, 140, 140, 140, 137, - 140, 137, 140, 140, 140, 148, 149, 140, 150, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 151, - 140, 152, 140, 140, 140, 140, 140, 140, 137, 137, - 137, 137, 137, 137, 153, 154, 156, 157, 156, 207, - 156, 157, 156, 158, 207, 210, 159, 158, 160, 210, - 159, 213, 160, 164, 165, 164, 213, 164, 165, 164, - 166, 97, 97, 167, 166, 166, 335, 167, 97, 166, - 97, 379, 449, 342, 419, 315, 380, 316, 316, 323, - 346, 208, 347, 324, 239, 239, 208, 211, 317, 356, - - 328, 211, 378, 325, 329, 335, 214, 318, 272, 319, - 272, 214, 342, 330, 320, 321, 322, 326, 323, 346, - 327, 347, 324, 239, 239, 381, 381, 317, 356, 328, - 161, 162, 325, 329, 161, 162, 318, 272, 319, 272, - 382, 382, 330, 320, 321, 322, 326, 168, 169, 327, - 308, 168, 169, 170, 171, 172, 171, 170, 170, 170, - 173, 174, 175, 175, 176, 177, 178, 177, 170, 170, - 179, 179, 170, 170, 175, 170, 170, 179, 179, 179, - 179, 179, 179, 180, 179, 179, 179, 179, 179, 179, - 179, 179, 181, 179, 179, 182, 183, 179, 179, 179, - - 179, 179, 179, 170, 179, 170, 179, 179, 179, 179, - 179, 179, 180, 179, 179, 179, 179, 179, 179, 179, - 179, 181, 179, 179, 182, 183, 179, 179, 179, 179, - 179, 179, 175, 170, 170, 170, 170, 170, 184, 185, - 186, 186, 186, 186, 186, 186, 535, 535, 187, 369, - 390, 187, 191, 192, 191, 391, 534, 193, 528, 194, - 373, 195, 196, 191, 192, 191, 521, 383, 193, 384, - 194, 331, 195, 196, 200, 201, 200, 332, 369, 202, - 385, 202, 202, 202, 203, 200, 201, 200, 333, 373, - 202, 334, 202, 202, 202, 203, 383, 336, 384, 499, - - 331, 337, 343, 403, 386, 338, 332, 449, 404, 385, - 344, 339, 357, 387, 340, 352, 345, 333, 537, 537, - 334, 341, 358, 353, 188, 189, 336, 188, 189, 419, - 337, 343, 354, 386, 338, 355, 197, 198, 388, 344, - 339, 357, 387, 340, 352, 345, 378, 197, 198, 422, - 341, 358, 353, 308, 423, 429, 534, 441, 204, 205, - 430, 354, 442, 445, 355, 311, 311, 388, 446, 204, - 205, 219, 220, 221, 220, 219, 222, 223, 224, 225, - 226, 219, 219, 219, 219, 227, 219, 219, 224, 224, - 219, 228, 219, 219, 229, 230, 224, 224, 224, 224, - - 231, 232, 224, 224, 224, 224, 233, 224, 224, 224, - 224, 224, 234, 224, 224, 224, 224, 224, 224, 224, - 224, 219, 224, 235, 230, 224, 224, 224, 224, 231, - 232, 224, 224, 224, 224, 233, 224, 224, 224, 224, - 224, 234, 224, 224, 224, 224, 224, 224, 224, 224, - 219, 219, 219, 219, 219, 219, 236, 237, 241, 242, - 241, 528, 243, 244, 424, 245, 246, 247, 241, 242, - 241, 248, 243, 244, 348, 245, 246, 247, 349, 359, - 521, 248, 360, 425, 363, 431, 350, 366, 361, 367, - 351, 364, 368, 424, 362, 432, 433, 370, 434, 249, - - 454, 365, 499, 348, 371, 372, 455, 349, 359, 249, - 449, 360, 425, 363, 431, 350, 366, 361, 367, 351, - 364, 368, 502, 362, 432, 433, 370, 434, 249, 454, - 365, 452, 464, 371, 372, 455, 453, 465, 249, 468, - 419, 379, 250, 251, 469, 536, 380, 378, 535, 535, - 308, 502, 250, 251, 252, 253, 254, 253, 252, 255, - 256, 257, 258, 259, 260, 252, 252, 252, 261, 252, - 252, 257, 257, 252, 252, 252, 252, 252, 257, 257, - 257, 257, 257, 262, 257, 257, 257, 257, 257, 263, - 257, 257, 257, 257, 257, 264, 257, 257, 257, 257, - - 257, 257, 257, 257, 252, 257, 252, 257, 257, 257, - 257, 257, 262, 257, 257, 257, 257, 257, 263, 257, - 257, 257, 257, 257, 264, 257, 257, 257, 257, 257, - 257, 257, 257, 252, 252, 252, 252, 252, 252, 265, - 266, 97, 97, 97, 97, 97, 267, 97, 505, 269, - 97, 97, 97, 97, 97, 97, 97, 97, 381, 381, - 97, 97, 97, 97, 97, 382, 382, 450, 451, 2084, - 270, 303, 303, 303, 303, 303, 303, 505, 506, 456, - 2090, 2101, 2101, 2101, 457, 507, 2063, 2101, 2101, 2101, - 510, 97, 2101, 97, 2101, 395, 450, 451, 2101, 270, - - 2101, 395, 647, 648, 2101, 2101, 2101, 506, 456, 496, - 496, 496, 395, 457, 507, 2101, 851, 2101, 395, 510, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 267, 97, 406, 269, 97, 97, 97, - 97, 97, 97, 97, 97, 458, 515, 97, 97, 97, - 97, 97, 523, 524, 525, 304, 435, 270, 304, 2052, - 436, 529, 459, 503, 406, 2101, 504, 530, 542, 437, - 543, 2101, 544, 438, 458, 515, 551, 552, 97, 390, - 97, 523, 524, 525, 391, 435, 270, 2051, 2101, 436, - 529, 459, 503, 497, 2074, 504, 530, 542, 437, 543, - - 2069, 544, 438, 469, 469, 551, 552, 97, 97, 97, - 97, 97, 97, 97, 97, 273, 274, 275, 274, 273, - 276, 277, 278, 279, 273, 273, 273, 280, 281, 282, - 283, 273, 284, 284, 273, 285, 286, 273, 287, 288, - 278, 278, 278, 278, 278, 289, 278, 278, 278, 278, - 278, 278, 278, 278, 278, 278, 278, 290, 278, 278, - 278, 278, 278, 278, 278, 273, 278, 291, 288, 278, - 278, 278, 278, 278, 289, 278, 278, 278, 278, 278, - 278, 278, 278, 278, 278, 278, 290, 278, 278, 278, - 278, 278, 278, 278, 273, 273, 273, 273, 273, 273, - - 292, 293, 295, 296, 295, 313, 313, 297, 2068, 295, - 296, 295, 563, 564, 297, 298, 556, 565, 2101, 2101, - 2101, 299, 298, 2066, 566, 496, 496, 496, 299, 2101, - 300, 2101, 395, 511, 511, 511, 567, 300, 2101, 2101, - 2101, 563, 564, 2065, 405, 556, 565, 301, 568, 2101, - 1980, 2101, 395, 566, 301, 572, 2101, 2101, 2101, 300, - 2062, 538, 395, 539, 539, 567, 300, 2101, 576, 2101, - 395, 1949, 407, 405, 540, 577, 301, 568, 2101, 2101, - 2101, 395, 409, 301, 572, 1015, 302, 723, 724, 2101, - 578, 2101, 395, 302, 392, 392, 392, 576, 853, 557, - - 557, 407, 2101, 540, 577, 394, 2013, 394, 395, 497, - 558, 409, 730, 731, 2101, 2101, 2101, 512, 408, 578, - 396, 397, 2101, 398, 579, 2101, 1981, 2101, 395, 511, - 511, 511, 399, 403, 400, 580, 401, 410, 404, 558, - 2101, 518, 518, 518, 2101, 2101, 2101, 408, 1950, 396, - 397, 1991, 398, 579, 559, 2101, 559, 2101, 395, 560, - 560, 399, 2101, 400, 580, 401, 410, 518, 518, 518, - 473, 473, 473, 581, 2031, 474, 2030, 475, 402, 392, - 392, 392, 411, 476, 480, 480, 480, 535, 535, 481, - 394, 482, 394, 395, 638, 639, 640, 483, 2101, 486, - - 486, 486, 581, 487, 488, 396, 397, 315, 398, 316, - 316, 411, 489, 512, 531, 531, 531, 399, 584, 400, - 317, 401, 531, 531, 531, 519, 759, 759, 2101, 547, - 547, 547, 585, 586, 396, 397, 1980, 398, 547, 547, - 547, 303, 303, 303, 561, 587, 399, 584, 400, 317, - 401, 519, 562, 422, 477, 554, 554, 554, 423, 569, - 570, 585, 586, 402, 2101, 2101, 2101, 571, 484, 2022, - 573, 2016, 588, 561, 587, 2101, 589, 2101, 395, 574, - 590, 562, 582, 490, 1949, 583, 575, 412, 569, 570, - 594, 413, 595, 2006, 598, 596, 571, 597, 532, 573, - - 414, 588, 591, 599, 415, 589, 532, 600, 574, 590, - 1912, 582, 601, 548, 583, 575, 412, 592, 593, 594, - 413, 595, 548, 598, 596, 304, 597, 602, 603, 414, - 604, 591, 599, 415, 605, 606, 600, 607, 608, 555, - 609, 601, 616, 621, 610, 622, 592, 593, 2101, 623, - 619, 617, 624, 618, 625, 611, 602, 603, 620, 604, - 612, 628, 1986, 605, 606, 626, 607, 608, 613, 609, - 614, 616, 621, 610, 622, 635, 615, 636, 623, 619, - 617, 624, 618, 625, 611, 627, 637, 620, 629, 612, - 628, 630, 631, 641, 626, 633, 632, 613, 642, 614, - - 643, 634, 644, 645, 635, 615, 636, 646, 429, 560, - 560, 660, 1985, 430, 627, 637, 661, 629, 441, 1982, - 630, 631, 641, 442, 633, 632, 1905, 642, 395, 643, - 634, 644, 645, 2101, 2101, 2101, 646, 392, 392, 392, - 660, 2101, 2101, 2101, 2101, 661, 2101, 395, 394, 662, - 394, 395, 2101, 663, 2101, 395, 2101, 2101, 2101, 2063, - 2101, 2101, 2101, 396, 397, 1888, 398, 2101, 1867, 2101, - 395, 2101, 1862, 2101, 395, 399, 664, 400, 662, 401, - 445, 452, 663, 665, 1955, 446, 453, 406, 2101, 2101, - 2101, 666, 396, 397, 407, 398, 2101, 2101, 2101, 2101, - - 667, 2101, 395, 1859, 399, 664, 400, 2101, 401, 2101, - 395, 1948, 665, 2101, 2101, 2101, 406, 2101, 668, 410, - 666, 402, 1947, 407, 2101, 2101, 2101, 395, 408, 667, - 669, 675, 2101, 2101, 2101, 2064, 464, 649, 1849, 676, - 2101, 465, 1847, 2101, 2101, 2101, 395, 668, 410, 1936, - 2101, 2101, 2101, 1811, 651, 677, 678, 408, 393, 669, - 675, 2101, 1920, 2101, 395, 393, 649, 393, 676, 393, - 411, 393, 2101, 679, 680, 2101, 2101, 2101, 393, 681, - 2101, 682, 654, 651, 677, 678, 2101, 393, 2101, 395, - 468, 650, 712, 713, 393, 469, 393, 2101, 393, 411, - - 393, 1916, 679, 680, 684, 685, 686, 393, 681, 714, - 682, 654, 652, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 650, 712, 713, 715, 2101, 1910, 2101, 395, 2101, 716, - 2101, 395, 918, 918, 2101, 2101, 2101, 2101, 714, 1795, - 412, 652, 717, 1902, 413, 395, 2101, 719, 2101, 395, - 1901, 653, 715, 414, 2101, 2101, 2101, 415, 716, 2101, - 655, 2101, 2101, 2101, 1783, 2101, 659, 2101, 395, 412, - 393, 717, 2101, 413, 2101, 395, 719, 1773, 656, 393, - 653, 856, 414, 393, 1741, 739, 415, 739, 722, 655, - 740, 740, 2101, 2101, 2101, 659, 1870, 2101, 1736, 393, - - 727, 2101, 657, 2101, 728, 2101, 395, 656, 393, 473, - 473, 473, 393, 480, 480, 480, 692, 722, 1734, 2101, - 697, 486, 486, 486, 709, 702, 496, 496, 496, 727, - 729, 657, 732, 728, 658, 707, 707, 707, 2101, 511, - 511, 511, 710, 711, 733, 2101, 720, 720, 720, 518, - 518, 518, 1865, 709, 725, 725, 725, 743, 744, 729, - 745, 732, 741, 658, 531, 531, 531, 734, 734, 734, - 395, 710, 711, 733, 537, 537, 2101, 737, 737, 538, - 742, 539, 539, 749, 750, 736, 743, 744, 738, 745, - 1861, 741, 540, 477, 547, 547, 547, 484, 747, 747, - - 747, 752, 554, 554, 1720, 490, 1019, 557, 557, 742, - 497, 760, 749, 750, 736, 761, 762, 738, 558, 708, - 755, 540, 755, 512, 763, 756, 756, 764, 765, 757, - 721, 757, 766, 519, 758, 758, 767, 768, 726, 770, - 760, 771, 769, 772, 761, 762, 773, 558, 532, 1854, - 774, 735, 775, 763, 776, 777, 764, 765, 778, 779, - 780, 766, 781, 782, 783, 767, 768, 784, 770, 785, - 771, 769, 772, 786, 787, 773, 788, 789, 548, 774, - 790, 775, 748, 776, 777, 753, 791, 778, 779, 780, - 792, 781, 782, 783, 793, 794, 784, 795, 785, 797, - - 798, 799, 786, 787, 800, 788, 789, 801, 802, 790, - 803, 804, 805, 806, 807, 791, 808, 809, 810, 792, - 811, 812, 813, 793, 794, 814, 795, 815, 797, 798, - 799, 817, 820, 800, 821, 824, 801, 802, 825, 803, - 804, 805, 806, 807, 1705, 808, 809, 810, 828, 811, - 812, 813, 831, 822, 814, 823, 815, 818, 818, 818, - 817, 820, 826, 821, 824, 832, 829, 825, 830, 833, - 834, 835, 836, 827, 837, 838, 840, 828, 841, 839, - 842, 831, 822, 843, 823, 844, 845, 846, 1844, 395, - 395, 826, 395, 858, 832, 829, 395, 830, 833, 834, - - 835, 836, 827, 837, 838, 840, 395, 841, 839, 842, - 395, 395, 843, 847, 844, 845, 846, 849, 395, 848, - 859, 850, 858, 860, 852, 861, 854, 862, 864, 857, - 865, 867, 868, 869, 870, 871, 872, 873, 874, 855, - 875, 819, 847, 876, 876, 876, 849, 1701, 848, 859, - 850, 886, 860, 852, 861, 854, 862, 864, 857, 865, - 867, 868, 869, 870, 871, 872, 873, 874, 855, 875, - 878, 878, 878, 880, 880, 880, 883, 707, 707, 887, - 886, 888, 889, 890, 891, 892, 893, 895, 897, 720, - 720, 900, 902, 725, 725, 905, 906, 908, 1693, 909, - - 911, 734, 734, 740, 740, 919, 920, 1840, 887, 921, - 888, 889, 890, 891, 892, 893, 895, 914, 922, 914, - 900, 923, 915, 915, 905, 906, 908, 877, 909, 737, - 737, 916, 928, 916, 919, 920, 917, 917, 921, 929, - 738, 925, 747, 747, 2101, 2101, 931, 922, 2101, 2101, - 923, 752, 554, 554, 879, 756, 756, 881, 756, 756, - 884, 928, 758, 758, 758, 758, 759, 759, 929, 738, - 932, 933, 898, 934, 935, 931, 903, 936, 937, 939, - 940, 941, 938, 942, 912, 943, 944, 945, 946, 947, - 948, 949, 950, 951, 952, 953, 2101, 2101, 954, 932, - - 933, 956, 934, 935, 957, 958, 936, 937, 939, 940, - 941, 938, 942, 962, 943, 944, 945, 946, 947, 948, - 949, 950, 951, 952, 953, 926, 930, 954, 963, 964, - 956, 965, 966, 957, 958, 753, 959, 959, 959, 967, - 968, 969, 962, 970, 970, 970, 972, 973, 974, 975, - 976, 977, 978, 979, 980, 981, 982, 963, 964, 983, - 965, 966, 992, 992, 992, 994, 995, 996, 967, 968, - 969, 997, 998, 999, 1000, 972, 973, 974, 975, 976, - 977, 978, 979, 980, 981, 982, 1001, 1002, 983, 1003, - 1004, 1687, 1005, 1006, 994, 995, 996, 1007, 395, 395, - - 997, 998, 999, 1000, 1008, 1009, 1010, 1011, 1012, 1014, - 1838, 1021, 395, 1676, 395, 1001, 1002, 1817, 1003, 1004, - 960, 1005, 1006, 1018, 395, 1815, 1007, 971, 818, 818, - 818, 395, 395, 1008, 1009, 1010, 1011, 1012, 1014, 1016, - 1021, 1809, 1017, 395, 1022, 1026, 993, 1027, 1020, 1023, - 984, 1028, 1018, 985, 986, 1029, 1024, 1030, 1031, 1032, - 1033, 1034, 1035, 1036, 987, 988, 989, 1037, 1016, 1039, - 990, 1017, 1040, 1022, 1026, 1041, 1027, 1020, 1023, 395, - 1028, 1808, 985, 986, 1029, 1024, 1030, 1031, 1032, 1033, - 1034, 1035, 1036, 987, 988, 989, 1037, 1058, 1039, 990, - - 1059, 1040, 2101, 2101, 1041, 1061, 1043, 876, 876, 1048, - 878, 878, 819, 1044, 1062, 1165, 1049, 1053, 880, 880, - 1067, 1054, 883, 707, 707, 1069, 1058, 1070, 1072, 1059, - 1806, 1063, 1063, 1063, 1061, 1074, 1064, 2101, 2101, 897, - 720, 720, 1076, 1062, 1065, 1644, 2101, 2101, 1801, 1067, - 2101, 2101, 2101, 2101, 1069, 1078, 1070, 1072, 902, 725, - 725, 2101, 2101, 1079, 1074, 911, 734, 734, 2101, 2101, - 1080, 1076, 915, 915, 915, 915, 917, 917, 917, 917, - 1057, 918, 918, 1081, 1078, 1082, 2101, 2101, 2101, 2101, - 1045, 1084, 1079, 1050, 925, 747, 747, 2101, 2101, 1080, - - 1087, 1055, 1085, 1085, 1085, 1088, 884, 1089, 1090, 1091, - 1092, 1093, 1081, 1638, 1082, 1066, 1094, 1797, 1095, 1096, - 1084, 1097, 1098, 898, 1071, 1099, 1100, 1101, 1102, 1087, - 1073, 1105, 1106, 1107, 1088, 1108, 1089, 1090, 1091, 1092, - 1093, 1112, 903, 1113, 1117, 1094, 1077, 1095, 1096, 912, - 1097, 1098, 1627, 1118, 1099, 1100, 1101, 1102, 1119, 1120, - 1105, 1106, 1107, 1123, 1108, 1622, 1083, 959, 959, 959, - 1112, 1124, 1113, 1117, 1125, 752, 1786, 1126, 926, 1114, - 1114, 1114, 1118, 970, 970, 970, 1086, 1119, 1120, 1127, - 1128, 1129, 1123, 1130, 1115, 1131, 1109, 1132, 1134, 1135, - - 1124, 1136, 1137, 1125, 1138, 1110, 1126, 1139, 1149, 1150, - 1151, 1152, 1133, 1153, 1154, 1155, 1156, 1157, 1127, 1128, - 1129, 1121, 1130, 1158, 1131, 1109, 1159, 1134, 1135, 1161, - 1136, 1137, 1162, 1138, 1110, 1172, 1139, 1149, 1150, 1151, - 1152, 1133, 1153, 1154, 1155, 1156, 1157, 395, 395, 395, - 1121, 960, 1158, 395, 395, 1159, 395, 1173, 1161, 1174, - 1167, 1162, 395, 1116, 1172, 1617, 395, 971, 992, 992, - 992, 1164, 1166, 1782, 1170, 1163, 1176, 1779, 1178, 1169, - 1345, 1346, 1179, 1181, 1778, 1168, 1173, 1183, 1174, 1167, - 1184, 1185, 1190, 1140, 1141, 1142, 1191, 1143, 395, 1776, - - 1164, 1166, 1171, 1170, 1163, 1176, 1144, 1178, 1169, 1145, - 1146, 1179, 1181, 1147, 2101, 2101, 1183, 1054, 1601, 1184, - 1185, 1190, 1140, 1141, 1142, 1191, 1143, 2101, 2101, 1043, - 876, 876, 1345, 1044, 1387, 1144, 1044, 1450, 1145, 1146, - 2101, 2101, 1147, 2101, 2101, 1771, 1044, 2101, 2101, 1044, - 2101, 2101, 993, 1049, 1048, 878, 878, 2101, 2101, 2101, - 2101, 1049, 1192, 1049, 1193, 1049, 1053, 880, 880, 1586, - 1054, 2101, 2101, 1204, 1054, 2101, 2101, 1205, 1054, 1063, - 1063, 1063, 1761, 1206, 1064, 1197, 1063, 1063, 2101, 2101, - 1198, 1192, 1065, 1193, 1207, 2101, 2101, 1209, 1199, 1740, - - 1210, 1211, 1204, 2101, 2101, 1195, 1205, 1212, 2101, 2101, - 1213, 1200, 1206, 1045, 1214, 1215, 1085, 1085, 1085, 1218, - 1219, 1187, 1220, 1207, 1437, 1438, 1209, 1221, 883, 1210, - 1211, 1222, 1223, 1224, 1195, 1228, 1212, 1188, 1050, 1213, - 1200, 1229, 1230, 1214, 1215, 1231, 1232, 1233, 1218, 1219, - 1055, 1220, 1738, 1189, 1216, 1234, 1221, 1225, 1225, 1225, - 1222, 1223, 1224, 1066, 1228, 1238, 897, 1239, 1240, 1201, - 1229, 1230, 1226, 902, 1231, 1232, 1233, 1235, 1235, 1235, - 1241, 911, 1244, 1216, 1234, 1245, 925, 1114, 1114, 1114, - 1246, 1247, 1236, 1248, 1238, 1249, 1239, 1240, 1250, 1251, - - 1086, 1252, 1115, 1253, 1260, 1261, 1254, 1254, 1254, 1241, - 1262, 1244, 1570, 1257, 1245, 1263, 1265, 1258, 1259, 1246, - 1247, 1255, 1248, 1267, 1249, 1268, 1269, 1250, 1251, 1270, - 1252, 1271, 1253, 1260, 1261, 1272, 1273, 1274, 1275, 1262, - 1276, 1227, 1257, 1277, 1263, 1265, 1258, 1259, 1278, 1278, - 1278, 1281, 1267, 1282, 1268, 1269, 1283, 1284, 1270, 1285, - 1271, 1237, 395, 1279, 1272, 1273, 1274, 1275, 395, 1276, - 395, 1116, 1277, 1294, 395, 1286, 395, 395, 1295, 1287, - 1281, 1296, 1282, 395, 1297, 1283, 1284, 1288, 1285, 1289, - 1256, 1290, 1292, 1298, 1293, 1300, 1291, 1301, 1299, 1302, - - 1303, 1304, 1294, 1560, 1286, 1305, 1306, 1295, 1287, 1727, - 1296, 2101, 2101, 1297, 1307, 1308, 1288, 1044, 1289, 1309, - 1290, 1292, 1298, 1293, 1300, 1291, 1301, 1299, 1302, 1303, - 1304, 1310, 1280, 1311, 1305, 1306, 2101, 2101, 2101, 2101, - 1312, 1054, 1049, 1307, 1308, 1197, 1063, 1063, 1309, 1723, - 1198, 1197, 1063, 1063, 1318, 1548, 1198, 395, 1199, 1319, - 1310, 1717, 1311, 1541, 1199, 1197, 1063, 1063, 1320, 1312, - 1198, 1200, 1316, 1316, 1316, 1321, 1713, 1200, 1199, 1197, - 1063, 1063, 1534, 1318, 1198, 1197, 1063, 1063, 1319, 1043, - 1198, 1200, 1313, 1492, 1322, 1323, 1324, 1320, 1199, 1710, - - 1200, 1704, 1325, 1326, 1321, 1200, 1200, 1327, 1328, 1329, - 1330, 1200, 1333, 1334, 1048, 1691, 1053, 1197, 1063, 1063, - 1200, 1335, 1198, 1322, 1323, 1324, 1336, 395, 1314, 1201, - 1199, 1325, 1326, 1337, 1200, 1201, 1327, 1328, 1329, 1330, - 1200, 1333, 1334, 1200, 1225, 1225, 1225, 1340, 1341, 1201, - 1335, 1235, 1235, 1235, 1342, 1336, 1317, 1314, 1343, 1226, - 1347, 1348, 1337, 1201, 1352, 1353, 1236, 395, 1359, 1201, - 1679, 1360, 1200, 1349, 1349, 1349, 1340, 1341, 1361, 1362, - 1363, 1655, 1364, 1342, 1254, 1254, 1254, 1343, 1350, 1347, - 1348, 1365, 1366, 1352, 1353, 1367, 1315, 1359, 1368, 1255, - - 1360, 1201, 1369, 1370, 1371, 1372, 1354, 1361, 1362, 1363, - 1355, 1364, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1647, - 1365, 1366, 1356, 1382, 1367, 1383, 1384, 1368, 1227, 1385, - 395, 1369, 1370, 1371, 1372, 1237, 395, 1394, 1395, 1355, - 1451, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1278, 1278, - 1278, 1356, 1382, 395, 1383, 1384, 1386, 1351, 1385, 395, - 395, 395, 395, 1279, 1397, 1388, 1394, 1395, 1256, 1389, - 1391, 1390, 1392, 1398, 1393, 1399, 1400, 1401, 1402, 1403, - 1404, 1405, 1406, 1407, 1408, 1386, 1409, 1410, 1411, 1412, - 1424, 1444, 1445, 1397, 1388, 1425, 1345, 2101, 1389, 1391, - - 1390, 1392, 1398, 1393, 1399, 1400, 1401, 1402, 1403, 1404, - 1405, 1406, 1407, 1408, 1635, 1409, 1410, 1411, 1412, 1424, - 1413, 1414, 1414, 1630, 1425, 1198, 1197, 1063, 1063, 1426, - 1427, 1198, 1280, 1313, 1428, 1197, 1063, 1063, 1429, 1199, - 1198, 1430, 1418, 1414, 1414, 1431, 1200, 1419, 1199, 1416, - 1432, 1433, 1200, 1434, 1435, 1420, 1439, 1440, 1426, 1427, - 1441, 1200, 1442, 1428, 1446, 1447, 1448, 1429, 1421, 1449, - 1430, 1451, 1451, 1451, 1431, 1200, 1454, 1455, 1416, 1432, - 1433, 1200, 1434, 1435, 1458, 1439, 1440, 1459, 1460, 1441, - 1200, 1442, 1461, 1446, 1447, 1448, 1466, 1421, 1449, 1463, - - 1464, 1452, 1468, 1471, 1415, 1454, 1455, 1349, 1349, 1349, - 1201, 1469, 1472, 1458, 1197, 1473, 1459, 1460, 1474, 1201, - 1475, 1461, 1350, 1476, 1477, 1466, 1422, 1478, 1479, 1470, - 1452, 1468, 1471, 1480, 1482, 1483, 1484, 1485, 1487, 1488, - 1469, 1472, 1489, 1490, 1473, 1491, 1496, 1474, 395, 1475, - 395, 1497, 1476, 1477, 1481, 1453, 1478, 1479, 1470, 1498, - 1500, 1501, 1480, 1482, 1483, 1484, 1485, 1493, 1502, 1494, - 1503, 1489, 1490, 1504, 1491, 1496, 1505, 1506, 1437, 2101, - 1497, 1522, 1523, 1481, 1444, 2101, 1625, 1524, 1498, 1500, - 1501, 1351, 1525, 1554, 1555, 1437, 1493, 1502, 1494, 1503, - - 1533, 1604, 1504, 1526, 1349, 1505, 1506, 1508, 1414, 1414, - 1522, 1523, 1509, 1418, 1414, 1414, 1524, 1551, 1419, 1316, - 1510, 1525, 1197, 1063, 1063, 1527, 1420, 1198, 1499, 1197, - 1063, 1063, 1526, 1511, 1198, 1199, 1528, 1529, 1530, 1421, - 1531, 1495, 1199, 395, 1515, 1063, 1063, 1444, 1200, 1419, - 395, 1532, 1540, 1463, 1527, 1200, 395, 1420, 1559, 1418, - 1414, 1414, 1511, 1514, 1419, 1528, 1529, 1530, 1421, 1531, - 1421, 395, 1420, 1537, 1517, 1063, 1063, 1200, 395, 1509, - 1532, 1515, 1063, 1063, 1200, 1421, 1419, 1510, 1538, 1463, - 2101, 1512, 1514, 1539, 1519, 1544, 1278, 1422, 1467, 1421, - - 1511, 1513, 1537, 1534, 1534, 1534, 1201, 1421, 1545, 1541, - 1541, 1541, 1546, 1201, 1421, 1465, 1547, 1538, 1515, 1063, - 1063, 1254, 1539, 1419, 1544, 1515, 1063, 1063, 1516, 1511, - 1419, 1420, 1457, 1535, 1456, 1550, 1421, 1545, 1420, 1542, - 1552, 1546, 1556, 1422, 1421, 1547, 1557, 1558, 1548, 1548, - 1548, 1421, 1451, 1451, 1451, 1560, 1560, 1560, 1518, 1563, - 1564, 1520, 1535, 1115, 1550, 1516, 1565, 1566, 1542, 1552, - 1567, 1556, 1568, 1421, 1569, 1557, 1558, 1570, 1570, 1570, - 1421, 1572, 1452, 1573, 1574, 1561, 1575, 1536, 1563, 1564, - 1520, 1576, 1577, 1543, 1578, 1565, 1566, 1579, 1580, 1567, - - 1581, 1568, 1516, 1569, 1521, 1582, 1583, 1235, 1584, 1516, - 1572, 1452, 1573, 1574, 1561, 1575, 1487, 2101, 1589, 1487, - 1576, 1577, 1590, 1578, 1585, 395, 1579, 1580, 1594, 1581, - 1595, 395, 1549, 395, 1582, 1583, 1453, 1584, 1596, 1562, - 1586, 1586, 1586, 1592, 1597, 1598, 1593, 1589, 1599, 1600, - 1605, 1590, 1591, 1606, 1601, 1601, 1601, 1594, 1613, 1595, - 1225, 1571, 1554, 2101, 1614, 1615, 1554, 1596, 1602, 1616, - 1587, 1637, 1592, 1597, 1598, 1593, 1423, 1599, 1600, 1605, - 1620, 1591, 1606, 1621, 1517, 1063, 1063, 1613, 1624, 1509, - 1508, 1414, 1414, 1614, 1615, 1509, 1396, 1510, 1616, 1587, - - 1517, 1063, 1063, 1510, 1381, 1509, 1517, 1063, 1063, 1620, - 1511, 1509, 1621, 1510, 1626, 1629, 1511, 1624, 1380, 1607, - 1517, 1063, 1063, 1358, 1588, 1509, 1511, 1617, 1617, 1617, - 1357, 1114, 1511, 1510, 1570, 1570, 1570, 1339, 1603, 1511, - 1631, 1618, 1632, 1626, 1629, 1511, 1511, 1517, 1063, 1063, - 1338, 1332, 1509, 1331, 1085, 1511, 1063, 1197, 1063, 1063, - 1510, 1511, 1198, 1608, 1622, 1622, 1622, 395, 1518, 1631, - 1199, 1632, 1633, 1511, 1512, 1511, 1627, 1627, 1627, 1226, - 1197, 1063, 1063, 1200, 1518, 1198, 395, 1534, 1534, 1534, - 1518, 1236, 1608, 1199, 1515, 1063, 1063, 992, 1266, 1419, - - 1634, 1633, 1511, 1636, 1518, 1264, 1200, 1420, 1515, 1063, - 1063, 1619, 1200, 1419, 1517, 1063, 1063, 1535, 1571, 1509, - 1421, 1420, 1641, 1548, 1548, 1548, 1609, 1510, 970, 1634, - 1243, 1518, 1636, 1242, 1421, 1200, 1413, 959, 1115, 1217, - 1511, 1201, 1517, 1063, 1063, 1208, 1535, 1509, 1623, 1421, - 1642, 1641, 1203, 1202, 1194, 1510, 880, 1418, 1414, 1414, - 1628, 878, 1419, 1421, 1201, 1541, 1541, 1541, 1511, 1511, - 1519, 1536, 1643, 876, 1638, 1638, 1638, 1186, 1516, 1642, - 1515, 1063, 1063, 1421, 1646, 1419, 1182, 1610, 1180, 1515, - 1063, 1063, 1516, 1420, 1419, 1542, 1648, 1511, 1518, 1649, - - 1650, 1643, 1420, 1612, 1639, 1651, 1421, 1549, 1644, 1644, - 1644, 1652, 1421, 1646, 1653, 1421, 1560, 1560, 1560, 1654, - 1177, 1611, 1656, 1255, 1542, 1648, 1518, 1657, 1649, 1650, - 1658, 1659, 1612, 1639, 1651, 1421, 1660, 1661, 1662, 1175, - 1652, 1422, 1663, 1653, 1421, 1672, 1561, 1673, 1654, 1543, - 1674, 1656, 1675, 1160, 1148, 818, 1657, 1122, 1640, 1658, - 1659, 1678, 1680, 1111, 1516, 1660, 1661, 1662, 1418, 1681, - 1683, 1663, 1104, 1516, 1672, 1561, 1673, 395, 1103, 1674, - 1684, 1675, 1676, 1676, 1676, 1586, 1586, 1586, 747, 734, - 1678, 1680, 1645, 1685, 1686, 1075, 725, 1279, 1681, 1683, - - 1562, 1664, 1734, 1734, 1734, 1682, 1692, 1665, 1698, 1684, - 1699, 1666, 1667, 1700, 1708, 1587, 1668, 1669, 1670, 1711, - 1671, 720, 1685, 1686, 1601, 1601, 1601, 1068, 1060, 1709, - 1664, 1687, 1687, 1687, 1682, 1692, 1665, 1698, 1602, 1699, - 1666, 1667, 1700, 1708, 1587, 1668, 1669, 1670, 1711, 1671, - 1693, 1693, 1693, 707, 1688, 1508, 1414, 1414, 1709, 1056, - 1509, 1051, 1517, 1063, 1063, 1046, 1677, 1509, 1607, 1588, - 1694, 1038, 1025, 1689, 1013, 1510, 991, 1517, 1063, 1063, - 1712, 1511, 1509, 1688, 1714, 1696, 1735, 1715, 1511, 961, - 1510, 955, 1515, 1063, 1063, 554, 927, 1419, 1716, 1517, - - 1063, 1063, 1689, 1511, 1509, 1420, 1718, 913, 1603, 1712, - 1511, 1719, 1510, 1714, 1696, 1690, 1715, 1511, 1421, 1617, - 1617, 1617, 1701, 1701, 1701, 1511, 1722, 1716, 1705, 1705, - 1705, 907, 1511, 1618, 1695, 1718, 1515, 1063, 1063, 1512, - 1719, 1419, 1622, 1622, 1622, 1702, 1518, 1421, 1706, 1420, - 1627, 1627, 1627, 1724, 1511, 1722, 1508, 1226, 1720, 1720, - 1720, 1518, 1421, 1725, 1726, 1236, 1638, 1638, 1638, 1728, - 1697, 1515, 1729, 1350, 1702, 1730, 1516, 904, 1517, 1644, - 1644, 1644, 1724, 1518, 1731, 1732, 1733, 1736, 1736, 1736, - 1739, 1421, 1725, 1726, 1255, 1743, 1639, 899, 1728, 1697, - - 1744, 1729, 1745, 1619, 1730, 894, 1703, 1741, 1741, 1741, - 1746, 1749, 1707, 1731, 1732, 1733, 1750, 1751, 1752, 1739, - 1516, 885, 1757, 1758, 1743, 1639, 1623, 1747, 1753, 1744, - 1748, 1745, 1759, 1754, 1628, 1760, 1762, 1763, 1764, 1746, - 1749, 1755, 1721, 1766, 1767, 1750, 1751, 1752, 1756, 395, - 1640, 1757, 1758, 1676, 1676, 1676, 1747, 1753, 1765, 1748, - 1768, 1759, 1754, 1645, 1760, 1762, 1763, 1764, 1279, 1769, - 1755, 1737, 1766, 1767, 1687, 1687, 1687, 1756, 1770, 1772, - 1693, 1693, 1693, 1773, 1773, 1773, 486, 1765, 1780, 1768, - 704, 1742, 1781, 1705, 1705, 1705, 1787, 1688, 1769, 1774, - - 1694, 1515, 1063, 1063, 1788, 1789, 1419, 1770, 1772, 1790, - 1517, 1063, 1063, 1706, 1420, 1509, 1689, 1780, 1701, 1701, - 1701, 1781, 1791, 1510, 1792, 1787, 1688, 1421, 1793, 704, - 1783, 1783, 1783, 1788, 1789, 480, 1511, 1677, 1790, 1794, - 1798, 1702, 1799, 1800, 1777, 1689, 1784, 1795, 1795, 1795, - 1802, 1791, 1803, 1792, 1804, 1805, 1421, 1793, 1690, 1720, - 1720, 1720, 1807, 1810, 1695, 1511, 699, 1775, 1794, 1798, - 1702, 1799, 1800, 1777, 1350, 1813, 699, 1707, 473, 1802, - 1816, 1803, 1818, 1804, 1805, 1516, 1734, 1734, 1734, 1819, - 1820, 1807, 1810, 1821, 1518, 1736, 1736, 1736, 1811, 1811, - - 1811, 1822, 1703, 1823, 1813, 1741, 1741, 1741, 1824, 1816, - 1825, 1818, 1826, 1827, 1785, 1828, 1829, 1830, 1819, 1820, - 1831, 1832, 1821, 1833, 1834, 694, 395, 1836, 694, 866, - 1822, 1796, 1823, 1837, 1839, 863, 816, 1824, 1841, 1825, - 1842, 1826, 1827, 1721, 1828, 1829, 1830, 1814, 796, 1831, - 1832, 754, 1833, 1834, 1835, 1843, 1836, 1693, 1693, 1693, - 547, 553, 1837, 1839, 1773, 1773, 1773, 1841, 1845, 1842, - 1735, 1846, 746, 1517, 1063, 1063, 1814, 1694, 1509, 1737, - 1774, 531, 1812, 1835, 1843, 1851, 1510, 1852, 1853, 1742, - 1705, 1705, 1705, 1783, 1783, 1783, 1855, 1845, 1856, 1511, - - 1846, 1847, 1847, 1847, 1849, 1849, 1849, 1857, 1858, 1784, - 1706, 1795, 1795, 1795, 1851, 1866, 1852, 1853, 1859, 1859, - 1859, 1862, 1862, 1862, 1869, 1855, 1871, 1856, 1511, 1867, - 1867, 1867, 1811, 1811, 1811, 1863, 1857, 1858, 1872, 1875, - 1873, 1695, 1876, 1877, 1866, 545, 1878, 1881, 1775, 1874, - 1879, 1880, 1882, 1869, 1883, 1871, 518, 1518, 1884, 526, - 1885, 1886, 1887, 1888, 1888, 1888, 511, 1872, 1875, 1873, - 1890, 1876, 1877, 516, 1707, 1878, 1881, 1785, 395, 1879, - 1880, 1882, 1892, 1883, 718, 1848, 1893, 1884, 1850, 1885, - 1886, 1887, 1894, 1895, 1896, 1796, 1897, 1898, 1899, 1890, - - 1900, 1903, 1860, 1904, 496, 1864, 508, 1891, 1847, 1847, - 1847, 1892, 1907, 1868, 1908, 1893, 1812, 1849, 1849, 1849, - 1909, 1894, 1895, 1896, 1911, 1897, 1898, 1899, 1917, 1900, - 1903, 1918, 1904, 1905, 1905, 1905, 1891, 1859, 1859, 1859, - 1921, 1907, 1922, 1908, 1862, 1862, 1862, 1889, 1923, 1909, - 1924, 1925, 1926, 1911, 1912, 1912, 1912, 1917, 1863, 1927, - 1918, 1867, 1867, 1867, 1928, 1929, 1930, 706, 1931, 1921, - 1932, 1922, 705, 395, 1933, 1934, 1935, 1923, 1937, 1924, - 1925, 1926, 1888, 1888, 1888, 1939, 1940, 1941, 1927, 1942, - 1943, 1913, 1848, 1928, 1929, 1930, 1914, 1931, 1944, 1932, - - 1938, 1850, 1919, 1933, 1934, 1935, 1945, 1937, 1946, 1905, - 1905, 1905, 1951, 1952, 1939, 1940, 1941, 1906, 1942, 1943, - 1913, 1860, 1953, 1954, 1956, 1914, 1957, 1944, 1864, 1938, - 1958, 1919, 1912, 1912, 1912, 1945, 1959, 1946, 1915, 1960, - 704, 1951, 1952, 1961, 1962, 1868, 1963, 1964, 1965, 1966, - 1967, 1953, 1954, 1956, 1968, 1957, 1969, 1970, 1971, 1958, - 1972, 1973, 1974, 1975, 701, 1959, 1889, 1976, 1960, 1913, - 1977, 1978, 1961, 1962, 1914, 1963, 1964, 1965, 1966, 1967, - 1979, 1983, 1984, 1968, 1987, 1969, 1970, 1971, 1988, 1972, - 1973, 1974, 1975, 1906, 1989, 1990, 1976, 1993, 1913, 1977, - - 1978, 1994, 1995, 1914, 1991, 1991, 1991, 1996, 1997, 1979, - 1983, 1984, 1998, 1987, 1999, 2000, 1915, 1988, 2001, 2002, - 2003, 2004, 2005, 1989, 1990, 2007, 1993, 2008, 2009, 2010, - 1994, 1995, 2011, 2012, 2015, 700, 1996, 1997, 2013, 2013, - 2013, 1998, 2017, 1999, 2000, 2018, 2019, 2001, 2002, 2003, - 2004, 2005, 2020, 2021, 2007, 2023, 2008, 2009, 2010, 699, - 2024, 2011, 2012, 2015, 1991, 1991, 1991, 2025, 2026, 2027, - 2028, 2017, 2029, 2032, 2018, 2019, 1991, 1991, 1991, 2033, - 2034, 2020, 2021, 2035, 2023, 2013, 2013, 2013, 1992, 2024, - 2036, 2037, 2038, 696, 2039, 2040, 2025, 2026, 2027, 2028, - - 2041, 2029, 2032, 2042, 2043, 2044, 2045, 2046, 2033, 2034, - 2047, 2048, 2035, 2049, 2050, 2084, 2084, 2084, 2055, 2036, - 2037, 2038, 2014, 2039, 2040, 2056, 2057, 2058, 2059, 2041, - 2060, 695, 2042, 2043, 2044, 2045, 2046, 2061, 2067, 2047, - 2048, 694, 2049, 2050, 2051, 2051, 2051, 2055, 1992, 2070, - 2071, 2072, 2052, 691, 2056, 2057, 2058, 2059, 2073, 2060, - 1992, 1693, 1693, 1693, 2075, 2076, 2061, 2067, 2077, 2014, - 1705, 1705, 1705, 2078, 2051, 2051, 2051, 2079, 2070, 2071, - 2072, 1694, 2052, 2080, 2081, 2082, 2083, 2073, 2086, 2087, - 1706, 2088, 2089, 2075, 2076, 2091, 2092, 2077, 2093, 2085, - - 690, 2094, 2078, 2084, 2084, 2084, 2079, 2084, 2084, 2084, - 2095, 2096, 2080, 2081, 2082, 2083, 689, 2086, 2087, 2097, - 2088, 2089, 2098, 2099, 2091, 2092, 2100, 2093, 2053, 2054, - 2094, 1991, 1991, 1991, 2084, 2084, 2084, 688, 687, 2095, - 2096, 683, 446, 674, 673, 1695, 672, 671, 2097, 670, - 427, 2098, 2099, 421, 1707, 2100, 417, 392, 2053, 2054, - 416, 303, 375, 310, 305, 376, 553, 550, 546, 545, - 541, 527, 526, 522, 517, 516, 514, 509, 508, 501, - 500, 495, 493, 471, 470, 467, 466, 2085, 463, 462, - 461, 2085, 460, 448, 447, 444, 443, 440, 439, 427, - - 421, 417, 416, 389, 377, 376, 375, 314, 310, 305, - 2101, 218, 218, 216, 216, 1992, 2101, 2101, 2085, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 155, - 155, 155, 155, 155, 155, 155, 155, 155, 155, 163, - 163, 163, 163, 163, 163, 163, 163, 163, 163, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 190, - 190, 190, 190, 190, 190, 190, 190, 190, 190, 199, - 199, 199, 199, 199, 199, 199, 199, 199, 199, 206, - 206, 206, 206, 206, 206, 206, 206, 206, 206, 209, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 212, - - 212, 212, 212, 212, 212, 212, 212, 212, 212, 215, - 215, 215, 215, 215, 215, 215, 215, 215, 215, 217, - 217, 217, 217, 217, 217, 217, 217, 217, 217, 238, - 238, 238, 238, 238, 238, 238, 238, 238, 238, 240, - 240, 240, 240, 240, 240, 240, 240, 240, 240, 268, - 268, 268, 268, 268, 268, 268, 268, 268, 268, 271, - 271, 271, 271, 271, 271, 271, 271, 271, 271, 294, - 294, 294, 294, 294, 294, 294, 294, 294, 294, 306, - 306, 307, 307, 2101, 307, 307, 307, 307, 307, 307, - 307, 309, 309, 374, 2101, 2101, 2101, 2101, 374, 393, - - 393, 2101, 393, 2101, 393, 393, 418, 418, 420, 420, - 426, 2101, 2101, 2101, 2101, 426, 428, 2101, 428, 472, - 472, 472, 472, 472, 2101, 472, 472, 2101, 472, 478, - 478, 478, 478, 478, 478, 478, 478, 478, 478, 479, - 479, 479, 479, 479, 2101, 479, 479, 2101, 479, 485, - 485, 485, 485, 485, 485, 485, 485, 485, 485, 491, - 491, 491, 491, 491, 491, 491, 491, 491, 491, 492, - 492, 492, 492, 492, 492, 492, 492, 492, 494, 494, - 494, 494, 494, 494, 494, 494, 494, 498, 498, 2101, - 498, 498, 498, 498, 498, 498, 498, 513, 513, 2101, - - 513, 513, 513, 513, 513, 513, 513, 520, 520, 2101, - 520, 520, 520, 520, 520, 520, 520, 533, 533, 2101, - 533, 533, 533, 533, 533, 533, 533, 549, 549, 2101, - 549, 549, 549, 549, 549, 549, 549, 306, 306, 307, - 307, 2101, 307, 307, 307, 307, 307, 307, 307, 309, - 309, 374, 2101, 2101, 2101, 2101, 374, 393, 393, 2101, - 393, 2101, 393, 393, 418, 418, 420, 420, 426, 2101, - 2101, 2101, 2101, 426, 428, 2101, 428, 472, 472, 472, - 472, 472, 2101, 472, 472, 2101, 472, 693, 693, 2101, - 693, 693, 693, 693, 693, 693, 693, 479, 479, 479, - - 479, 479, 2101, 479, 479, 2101, 479, 698, 698, 2101, - 698, 698, 698, 698, 698, 698, 698, 703, 703, 2101, - 703, 703, 703, 703, 703, 703, 703, 492, 492, 492, - 492, 492, 492, 492, 492, 492, 494, 494, 494, 494, - 494, 494, 494, 494, 494, 498, 498, 2101, 498, 498, - 498, 498, 498, 498, 498, 513, 513, 2101, 513, 513, - 513, 513, 513, 513, 513, 520, 520, 2101, 520, 520, - 520, 520, 520, 520, 520, 533, 533, 2101, 533, 533, - 533, 533, 533, 533, 533, 549, 549, 2101, 549, 549, - 549, 549, 549, 549, 549, 751, 751, 751, 751, 751, - - 751, 751, 751, 751, 751, 393, 2101, 2101, 393, 428, - 2101, 428, 882, 882, 882, 882, 882, 882, 882, 882, - 882, 882, 896, 896, 896, 896, 896, 896, 896, 896, - 896, 896, 901, 901, 901, 901, 901, 901, 901, 901, - 901, 901, 910, 910, 910, 910, 910, 910, 910, 910, - 910, 910, 924, 924, 924, 924, 924, 924, 924, 924, - 924, 924, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, - 1042, 1042, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, - 1047, 1047, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, - 1052, 1052, 1196, 1196, 1196, 1196, 1196, 1196, 1196, 1196, - - 1196, 1196, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, - 1417, 1417, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, - 1436, 1436, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, - 1443, 1443, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, - 1462, 1462, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, - 1486, 1486, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, - 1507, 1507, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, - 1553, 1553, 53, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101 + 60, 61, 62, 61, 63, 64, 65, 66, 67, 68, + 68, 63, 69, 70, 71, 72, 73, 74, 63, 63, + 63, 75, 63, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 66, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 66, 66, 60, + 66, 99, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 66, 85, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 66, 66, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 100, 101, + 102, 103, 104, 105, 106, 106, 107, 106, 106, 106, + + 108, 108, 106, 109, 109, 110, 111, 106, 111, 106, + 106, 112, 106, 106, 106, 106, 106, 108, 108, 108, + 108, 108, 113, 108, 108, 114, 108, 108, 108, 108, + 108, 108, 108, 115, 116, 117, 108, 108, 108, 118, + 108, 108, 108, 106, 108, 106, 108, 108, 108, 108, + 108, 113, 108, 108, 114, 108, 108, 108, 108, 108, + 108, 108, 115, 116, 117, 108, 108, 108, 118, 108, + 108, 108, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 119, 120, 121, 122, 123, 124, 126, 126, + 377, 378, 379, 380, 381, 382, 2762, 127, 127, 128, + + 129, 130, 129, 128, 128, 131, 131, 128, 128, 128, + 132, 133, 128, 134, 135, 128, 131, 128, 128, 128, + 128, 128, 131, 131, 131, 136, 137, 131, 138, 131, + 131, 131, 131, 131, 131, 131, 139, 140, 131, 141, + 131, 142, 131, 131, 131, 131, 131, 131, 128, 131, + 128, 131, 131, 131, 136, 137, 131, 138, 131, 131, + 131, 131, 131, 131, 131, 139, 140, 131, 141, 131, + 142, 131, 131, 131, 131, 131, 131, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 143, 144, 145, + 146, 147, 148, 149, 149, 107, 149, 149, 150, 151, + + 151, 152, 149, 149, 153, 149, 149, 149, 149, 149, + 151, 149, 149, 149, 149, 149, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 154, 151, 151, 151, 155, 151, 151, 151, 151, + 151, 151, 149, 151, 156, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 154, 151, 151, 151, 155, 151, 151, 151, 151, 151, + 151, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 157, 158, 159, 160, 161, 162, 163, 164, 165, + 164, 163, 163, 163, 166, 167, 163, 163, 168, 169, + + 170, 171, 172, 163, 166, 163, 163, 173, 163, 163, + 166, 166, 166, 174, 175, 166, 176, 166, 166, 166, + 166, 166, 166, 166, 166, 166, 166, 177, 166, 178, + 166, 166, 166, 166, 166, 166, 163, 166, 163, 166, + 166, 166, 174, 175, 166, 176, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 166, 177, 166, 178, 166, + 166, 166, 166, 166, 166, 163, 163, 163, 163, 163, + 163, 163, 163, 163, 163, 163, 163, 179, 163, 180, + 163, 182, 183, 182, 234, 182, 183, 182, 184, 234, + 237, 185, 184, 186, 237, 185, 240, 186, 190, 191, + + 190, 240, 190, 191, 190, 192, 107, 107, 193, 192, + 192, 479, 193, 107, 192, 107, 480, 392, 393, 355, + 394, 424, 457, 500, 522, 235, 2756, 356, 269, 269, + 235, 238, 497, 2770, 516, 238, 357, 498, 355, 517, + 241, 2765, 313, 2738, 313, 241, 356, 2726, 355, 560, + 424, 2725, 500, 522, 561, 357, 356, 269, 269, 458, + 459, 460, 461, 462, 463, 357, 2750, 355, 622, 622, + 187, 313, 188, 313, 187, 356, 188, 2744, 377, 378, + 379, 380, 381, 382, 357, 581, 2743, 194, 2741, 195, + 582, 194, 2740, 195, 196, 197, 198, 197, 196, 196, + + 196, 199, 200, 201, 201, 202, 203, 204, 205, 196, + 196, 206, 196, 196, 201, 196, 196, 206, 206, 206, + 206, 206, 206, 207, 206, 206, 206, 206, 206, 206, + 206, 206, 208, 206, 206, 209, 210, 206, 206, 206, + 206, 206, 206, 196, 206, 196, 206, 206, 206, 206, + 206, 206, 207, 206, 206, 206, 206, 206, 206, 206, + 206, 208, 206, 206, 209, 210, 206, 206, 206, 206, + 206, 206, 201, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 196, 211, 196, 212, 196, 213, 213, + 213, 213, 213, 213, 1052, 1053, 214, 583, 2737, 214, + + 218, 219, 218, 384, 2722, 220, 2700, 221, 417, 222, + 223, 218, 219, 218, 1844, 1845, 220, 584, 221, 412, + 222, 223, 227, 228, 227, 413, 583, 229, 2708, 229, + 229, 229, 230, 227, 228, 227, 585, 417, 229, 2722, + 229, 229, 229, 230, 428, 586, 584, 500, 412, 407, + 593, 2718, 519, 2672, 413, 594, 377, 378, 379, 380, + 381, 382, 2708, 408, 2705, 585, 409, 377, 378, 379, + 380, 381, 382, 428, 586, 606, 500, 215, 407, 216, + 215, 519, 216, 385, 386, 387, 388, 389, 390, 224, + 2641, 225, 408, 597, 604, 409, 617, 2698, 598, 605, + + 224, 618, 225, 2697, 606, 377, 378, 379, 380, 381, + 382, 231, 2630, 232, 377, 378, 379, 380, 381, 382, + 753, 754, 231, 755, 232, 246, 247, 248, 247, 246, + 249, 250, 251, 252, 253, 246, 246, 246, 246, 254, + 246, 246, 251, 246, 255, 246, 246, 256, 251, 251, + 251, 251, 251, 257, 258, 251, 251, 251, 251, 259, + 251, 251, 251, 251, 251, 260, 251, 251, 251, 251, + 251, 251, 251, 251, 246, 251, 261, 251, 251, 251, + 251, 251, 257, 258, 251, 251, 251, 251, 259, 251, + 251, 251, 251, 251, 260, 251, 251, 251, 251, 251, + + 251, 251, 251, 246, 246, 246, 246, 246, 246, 246, + 246, 246, 246, 262, 263, 264, 265, 266, 267, 271, + 272, 271, 2688, 273, 274, 2630, 275, 276, 277, 271, + 272, 271, 278, 273, 274, 621, 275, 276, 277, 397, + 622, 398, 278, 500, 438, 500, 414, 602, 603, 415, + 445, 399, 416, 520, 500, 524, 607, 446, 376, 279, + 473, 474, 475, 476, 477, 478, 681, 447, 521, 279, + 376, 2685, 500, 438, 500, 414, 602, 603, 415, 445, + 399, 416, 520, 500, 524, 607, 446, 376, 279, 377, + 378, 379, 380, 381, 382, 681, 447, 521, 279, 376, + + 377, 378, 379, 380, 381, 382, 479, 2631, 280, 2684, + 281, 480, 377, 378, 379, 380, 381, 382, 280, 2683, + 281, 282, 283, 284, 283, 282, 285, 286, 287, 288, + 289, 290, 282, 282, 282, 291, 282, 282, 287, 282, + 282, 282, 282, 282, 287, 287, 287, 287, 287, 292, + 287, 287, 287, 287, 287, 293, 287, 287, 287, 287, + 287, 294, 287, 287, 287, 287, 287, 287, 287, 287, + 282, 287, 282, 287, 287, 287, 287, 287, 292, 287, + 287, 287, 287, 287, 293, 287, 287, 287, 287, 287, + 294, 287, 287, 287, 287, 287, 287, 287, 287, 282, + + 282, 282, 282, 282, 282, 282, 282, 282, 282, 295, + 296, 297, 298, 299, 300, 107, 107, 107, 107, 107, + 301, 302, 302, 303, 107, 107, 107, 107, 107, 107, + 107, 107, 302, 107, 107, 107, 107, 304, 302, 302, + 302, 302, 302, 305, 302, 302, 302, 302, 302, 302, + 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, + 302, 302, 302, 302, 107, 302, 107, 302, 302, 302, + 302, 302, 305, 302, 302, 302, 302, 302, 302, 302, + 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, + 302, 302, 302, 107, 107, 107, 107, 107, 107, 107, + + 107, 107, 107, 306, 307, 308, 309, 310, 311, 314, + 315, 316, 315, 314, 317, 318, 319, 320, 314, 314, + 314, 321, 322, 323, 324, 314, 325, 314, 326, 327, + 314, 327, 319, 319, 319, 319, 319, 319, 328, 319, + 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + 329, 319, 319, 319, 319, 319, 319, 319, 314, 319, + 330, 319, 319, 319, 319, 319, 319, 328, 319, 319, + 319, 319, 319, 319, 319, 319, 319, 319, 319, 329, + 319, 319, 319, 319, 319, 319, 319, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 331, 332, 333, + + 334, 335, 336, 338, 339, 338, 686, 497, 340, 338, + 339, 338, 498, 2675, 340, 734, 341, 358, 358, 358, + 523, 342, 341, 500, 347, 348, 347, 342, 2585, 349, + 343, 358, 358, 358, 2665, 686, 343, 350, 455, 405, + 774, 360, 351, 406, 734, 516, 376, 344, 775, 523, + 517, 352, 500, 344, 2659, 376, 781, 353, 376, 343, + 782, 347, 348, 347, 784, 343, 349, 455, 405, 774, + 410, 2656, 406, 2653, 350, 376, 344, 775, 785, 351, + 352, 2534, 344, 411, 376, 781, 353, 376, 352, 782, + 786, 2636, 345, 784, 353, 649, 649, 649, 345, 410, + + 377, 378, 379, 380, 381, 382, 359, 785, 500, 977, + 418, 520, 411, 354, 419, 2635, 560, 352, 420, 786, + 359, 561, 2632, 353, 362, 363, 364, 365, 366, 367, + 1470, 377, 378, 379, 380, 381, 382, 500, 977, 418, + 520, 581, 397, 419, 817, 451, 582, 420, 1963, 1964, + 354, 368, 368, 429, 818, 368, 368, 978, 439, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 440, 368, + 368, 368, 368, 368, 451, 377, 378, 379, 380, 381, + 382, 2527, 429, 818, 650, 1480, 978, 439, 376, 376, + 376, 376, 376, 376, 376, 376, 376, 440, 979, 2621, + + 368, 1635, 368, 2585, 377, 378, 379, 380, 381, 382, + 377, 378, 379, 380, 381, 382, 395, 2618, 820, 377, + 378, 379, 380, 381, 382, 1475, 819, 979, 821, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 368, 370, + 371, 372, 373, 374, 375, 400, 421, 401, 980, 422, + 425, 500, 402, 403, 404, 819, 423, 821, 426, 1637, + 2738, 537, 943, 983, 427, 464, 464, 464, 464, 464, + 464, 464, 464, 464, 400, 421, 401, 980, 422, 425, + 500, 402, 403, 404, 2612, 423, 2586, 426, 649, 649, + 649, 943, 983, 427, 1001, 1002, 1636, 1003, 2500, 377, + + 378, 379, 380, 381, 382, 611, 434, 1470, 377, 378, + 379, 380, 381, 382, 435, 377, 378, 379, 380, 381, + 382, 430, 612, 436, 500, 431, 437, 448, 523, 449, + 935, 524, 450, 432, 611, 434, 500, 433, 500, 682, + 682, 682, 2739, 435, 539, 540, 541, 542, 543, 544, + 430, 612, 436, 500, 431, 437, 448, 523, 449, 935, + 524, 450, 432, 593, 597, 500, 433, 500, 594, 598, + 984, 377, 378, 379, 380, 381, 382, 650, 1469, 377, + 378, 379, 380, 381, 382, 377, 378, 379, 380, 381, + 382, 441, 500, 608, 442, 452, 2474, 483, 609, 984, + + 443, 521, 453, 454, 933, 500, 444, 500, 985, 991, + 610, 500, 376, 936, 938, 376, 682, 682, 682, 2469, + 441, 500, 608, 442, 452, 482, 483, 609, 683, 443, + 521, 453, 454, 933, 500, 444, 500, 985, 991, 610, + 500, 376, 936, 938, 376, 473, 474, 475, 476, 477, + 478, 1475, 377, 378, 379, 380, 381, 382, 465, 466, + 466, 466, 466, 466, 466, 466, 466, 467, 467, 467, + 467, 467, 467, 467, 467, 467, 468, 468, 468, 468, + 468, 468, 468, 469, 470, 471, 471, 471, 471, 471, + 471, 471, 471, 471, 484, 485, 473, 474, 475, 476, + + 477, 478, 486, 992, 2591, 683, 487, 993, 488, 472, + 472, 472, 472, 472, 472, 472, 472, 472, 1971, 1972, + 1844, 2786, 1474, 484, 485, 546, 547, 548, 549, 550, + 551, 486, 992, 604, 617, 487, 993, 488, 605, 618, + 473, 474, 475, 476, 477, 478, 473, 474, 475, 476, + 477, 478, 473, 474, 475, 476, 477, 478, 689, 689, + 689, 1994, 1995, 473, 474, 475, 476, 477, 478, 473, + 474, 475, 476, 477, 478, 489, 489, 489, 489, 489, + 489, 489, 489, 489, 490, 491, 491, 491, 491, 491, + 491, 491, 491, 492, 492, 492, 492, 492, 492, 492, + + 492, 492, 493, 493, 493, 493, 493, 493, 493, 494, + 495, 496, 496, 496, 496, 496, 496, 496, 496, 496, + 499, 499, 499, 621, 994, 565, 2466, 995, 622, 996, + 823, 501, 823, 501, 502, 1134, 553, 2028, 2029, 1963, + 2786, 2786, 2786, 2786, 500, 503, 504, 690, 505, 997, + 2584, 937, 2786, 994, 2786, 502, 995, 506, 996, 507, + 981, 508, 566, 567, 568, 569, 570, 571, 2786, 2786, + 2786, 1971, 2786, 500, 503, 504, 982, 505, 997, 2786, + 937, 2786, 502, 2105, 2106, 2583, 506, 1480, 507, 981, + 508, 1994, 2786, 518, 500, 500, 500, 500, 500, 500, + + 500, 500, 500, 2028, 2786, 982, 562, 509, 510, 511, + 512, 513, 514, 499, 499, 499, 554, 555, 556, 557, + 558, 559, 518, 2454, 501, 2452, 501, 502, 509, 510, + 515, 512, 513, 514, 998, 562, 999, 668, 503, 504, + 669, 505, 660, 661, 662, 663, 664, 665, 1037, 1038, + 506, 563, 507, 2575, 508, 509, 510, 515, 512, 513, + 514, 1479, 2572, 998, 2564, 999, 668, 503, 504, 669, + 505, 546, 547, 548, 549, 550, 551, 1037, 1038, 506, + 563, 507, 525, 508, 500, 500, 526, 2563, 660, 661, + 662, 663, 664, 665, 934, 527, 1048, 1051, 1079, 528, + + 509, 510, 511, 512, 513, 514, 2400, 1135, 2542, 1135, + 2538, 525, 1136, 500, 500, 526, 546, 547, 548, 549, + 550, 551, 2532, 934, 527, 1048, 1051, 1079, 528, 529, + 529, 529, 529, 529, 529, 529, 529, 529, 530, 531, + 531, 531, 531, 531, 531, 531, 531, 532, 532, 532, + 532, 532, 532, 532, 532, 532, 533, 533, 533, 533, + 533, 533, 533, 534, 535, 536, 536, 536, 536, 536, + 536, 536, 536, 536, 545, 545, 545, 545, 545, 545, + 545, 545, 545, 572, 572, 572, 572, 572, 572, 572, + 572, 572, 573, 574, 574, 574, 574, 574, 574, 574, + + 574, 575, 575, 575, 575, 575, 575, 575, 575, 575, + 576, 576, 576, 576, 576, 576, 576, 577, 578, 579, + 579, 579, 579, 579, 579, 579, 579, 579, 587, 626, + 626, 626, 588, 756, 627, 2384, 628, 2105, 2786, 670, + 671, 589, 629, 1096, 1110, 590, 633, 633, 633, 1844, + 1137, 634, 1137, 635, 1977, 1138, 1111, 587, 1114, 636, + 672, 588, 639, 639, 639, 2382, 640, 641, 670, 671, + 589, 2523, 1096, 1110, 590, 642, 659, 659, 659, 659, + 659, 659, 659, 659, 659, 1111, 1963, 1114, 1115, 672, + 2522, 2082, 2517, 660, 661, 662, 663, 664, 665, 700, + + 701, 702, 703, 704, 705, 660, 661, 662, 663, 664, + 665, 660, 661, 662, 663, 664, 665, 1115, 630, 673, + 673, 673, 673, 673, 673, 673, 673, 673, 689, 689, + 689, 2514, 2502, 2332, 2325, 637, 674, 675, 675, 675, + 675, 675, 675, 675, 675, 719, 720, 721, 722, 723, + 724, 643, 651, 651, 1971, 2322, 651, 651, 2320, 2089, + 651, 651, 651, 651, 651, 651, 651, 651, 651, 707, + 651, 651, 651, 651, 651, 676, 676, 676, 676, 676, + 676, 676, 676, 676, 677, 677, 677, 677, 677, 677, + 677, 678, 679, 735, 735, 735, 2477, 1116, 707, 1117, + + 1118, 651, 2315, 651, 680, 680, 680, 680, 680, 680, + 680, 680, 680, 1100, 2313, 1100, 2472, 690, 1321, 708, + 700, 701, 702, 703, 704, 705, 1116, 2468, 1117, 1118, + 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, + 653, 654, 655, 656, 657, 658, 691, 691, 708, 709, + 691, 691, 1256, 1097, 691, 691, 691, 691, 691, 691, + 691, 691, 691, 1098, 691, 691, 691, 691, 691, 699, + 699, 699, 699, 699, 699, 699, 699, 699, 709, 2298, + 2461, 1256, 736, 2459, 700, 701, 702, 703, 704, 705, + 2447, 1322, 1098, 1322, 1994, 691, 1323, 691, 2444, 2111, + + 700, 701, 702, 703, 704, 705, 710, 710, 710, 710, + 710, 710, 710, 710, 710, 711, 712, 712, 712, 712, + 712, 712, 712, 712, 691, 691, 691, 691, 691, 691, + 691, 691, 691, 691, 693, 694, 695, 696, 697, 698, + 713, 713, 713, 713, 713, 713, 713, 713, 713, 714, + 714, 714, 714, 714, 714, 714, 715, 716, 717, 717, + 717, 717, 717, 717, 717, 717, 717, 725, 718, 718, + 718, 718, 718, 718, 718, 718, 718, 726, 726, 726, + 726, 726, 726, 726, 726, 726, 727, 728, 728, 728, + 728, 728, 728, 728, 728, 2270, 725, 729, 729, 729, + + 729, 729, 729, 729, 729, 729, 730, 730, 730, 730, + 730, 730, 730, 731, 732, 719, 720, 721, 722, 723, + 724, 733, 733, 733, 733, 733, 733, 733, 733, 733, + 735, 735, 735, 746, 747, 748, 749, 750, 751, 757, + 760, 758, 761, 2440, 2431, 2255, 2415, 2411, 770, 770, + 770, 759, 745, 745, 745, 745, 745, 745, 745, 745, + 745, 377, 378, 379, 380, 381, 382, 2409, 2407, 760, + 2404, 761, 770, 770, 770, 777, 777, 777, 2398, 2397, + 759, 762, 762, 762, 762, 762, 762, 762, 762, 762, + 2395, 2212, 2390, 1257, 746, 747, 748, 749, 750, 751, + + 2205, 2386, 2193, 746, 747, 748, 749, 750, 751, 2188, + 2371, 2368, 746, 747, 748, 749, 750, 751, 2028, 736, + 737, 737, 1257, 2146, 737, 737, 2166, 2363, 737, 737, + 737, 737, 737, 737, 737, 737, 737, 771, 737, 737, + 737, 737, 737, 763, 764, 764, 764, 764, 764, 764, + 764, 764, 765, 765, 765, 765, 765, 765, 765, 765, + 765, 771, 360, 2352, 778, 777, 777, 777, 1258, 737, + 2147, 737, 766, 766, 766, 766, 766, 766, 766, 767, + 768, 769, 769, 769, 769, 769, 769, 769, 769, 769, + 358, 358, 358, 384, 2350, 2134, 2319, 1258, 737, 737, + + 737, 737, 737, 737, 737, 737, 737, 737, 739, 740, + 741, 742, 743, 744, 361, 361, 361, 361, 361, 361, + 361, 361, 361, 788, 788, 788, 788, 788, 788, 788, + 788, 788, 789, 790, 790, 790, 790, 790, 790, 790, + 790, 815, 815, 815, 2317, 362, 363, 364, 365, 366, + 367, 2122, 2112, 2306, 778, 791, 791, 791, 791, 791, + 791, 791, 791, 791, 792, 792, 792, 792, 792, 792, + 792, 793, 794, 385, 386, 387, 388, 389, 390, 359, + 795, 795, 795, 795, 795, 795, 795, 795, 795, 368, + 368, 2105, 2301, 368, 368, 2097, 2204, 368, 368, 368, + + 368, 368, 368, 368, 368, 368, 2090, 368, 368, 368, + 368, 368, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 796, 796, 796, 796, 796, 796, 796, 796, 796, + 816, 377, 378, 379, 380, 381, 382, 1260, 368, 2290, + 368, 797, 798, 798, 798, 798, 798, 798, 798, 798, + 799, 799, 799, 799, 799, 799, 799, 799, 799, 377, + 378, 379, 380, 381, 382, 2083, 1260, 368, 368, 368, + 368, 368, 368, 368, 368, 368, 368, 370, 371, 372, + 373, 374, 375, 800, 800, 800, 800, 800, 800, 800, + 801, 802, 803, 803, 803, 803, 803, 803, 803, 803, + + 803, 376, 376, 376, 376, 376, 376, 376, 376, 376, + 464, 464, 464, 464, 464, 464, 464, 464, 464, 804, + 466, 466, 466, 466, 466, 466, 466, 466, 467, 467, + 467, 467, 467, 467, 467, 467, 467, 468, 468, 468, + 468, 468, 468, 468, 805, 470, 471, 471, 471, 471, + 471, 471, 471, 471, 471, 383, 383, 383, 383, 383, + 383, 383, 383, 383, 806, 806, 806, 806, 806, 806, + 806, 806, 806, 807, 808, 808, 808, 808, 808, 808, + 808, 808, 809, 809, 809, 809, 809, 809, 809, 809, + 809, 810, 810, 810, 810, 810, 810, 810, 811, 812, + + 813, 813, 813, 813, 813, 813, 813, 813, 813, 397, + 825, 822, 823, 757, 823, 1094, 2287, 824, 826, 2282, + 939, 399, 2279, 1261, 828, 1095, 500, 1262, 1264, 827, + 456, 456, 456, 456, 456, 456, 456, 456, 456, 825, + 473, 474, 475, 476, 477, 478, 2273, 826, 829, 939, + 399, 845, 1261, 828, 1095, 500, 1262, 1264, 827, 2259, + 2258, 649, 649, 649, 377, 378, 379, 380, 381, 382, + 377, 378, 379, 380, 381, 382, 830, 829, 851, 890, + 845, 2237, 377, 378, 379, 380, 381, 382, 377, 378, + 379, 380, 381, 382, 377, 378, 379, 380, 381, 382, + + 831, 1265, 1266, 836, 832, 830, 2223, 851, 890, 2215, + 377, 378, 379, 380, 381, 382, 377, 378, 379, 380, + 381, 382, 377, 378, 379, 380, 381, 382, 1850, 831, + 1265, 1266, 836, 832, 1978, 377, 378, 379, 380, 381, + 382, 833, 834, 377, 378, 379, 380, 381, 382, 835, + 650, 1267, 377, 378, 379, 380, 381, 382, 377, 378, + 379, 380, 381, 382, 377, 378, 379, 380, 381, 382, + 833, 834, 837, 841, 838, 2201, 944, 2196, 835, 1268, + 1267, 2191, 842, 839, 500, 928, 928, 929, 930, 928, + 840, 928, 928, 928, 377, 378, 379, 380, 381, 382, + + 2184, 837, 841, 838, 397, 944, 1133, 843, 1268, 2181, + 820, 842, 839, 500, 846, 1269, 818, 847, 844, 840, + 821, 1270, 1271, 848, 377, 378, 379, 380, 381, 382, + 377, 378, 379, 380, 381, 382, 843, 377, 378, 379, + 380, 381, 382, 846, 1269, 818, 847, 844, 2169, 821, + 1270, 1271, 848, 2161, 2150, 1272, 852, 853, 457, 1755, + 1273, 854, 377, 378, 379, 380, 381, 382, 377, 378, + 379, 380, 381, 382, 377, 378, 379, 380, 381, 382, + 849, 626, 626, 626, 1272, 852, 853, 1722, 1009, 1273, + 854, 2103, 2100, 537, 850, 458, 459, 460, 461, 462, + + 463, 855, 1287, 1288, 1294, 859, 1299, 1311, 1694, 849, + 377, 378, 379, 380, 381, 382, 377, 378, 379, 380, + 381, 382, 856, 850, 377, 378, 379, 380, 381, 382, + 855, 1287, 1288, 1294, 859, 1299, 1311, 857, 858, 1333, + 865, 1684, 861, 860, 862, 377, 378, 379, 380, 381, + 382, 856, 2075, 377, 378, 379, 380, 381, 382, 377, + 378, 379, 380, 381, 382, 2072, 857, 858, 1333, 865, + 630, 861, 860, 862, 863, 864, 539, 540, 541, 542, + 543, 544, 866, 869, 377, 378, 379, 380, 381, 382, + 377, 378, 379, 380, 381, 382, 920, 377, 378, 379, + + 380, 381, 382, 863, 864, 377, 378, 379, 380, 381, + 382, 866, 869, 1807, 2044, 867, 2039, 377, 378, 379, + 380, 381, 382, 377, 378, 379, 380, 381, 382, 868, + 546, 547, 548, 549, 550, 551, 1334, 871, 377, 378, + 379, 380, 381, 382, 867, 377, 378, 379, 380, 381, + 382, 2031, 870, 872, 2026, 946, 946, 1998, 868, 946, + 1996, 946, 946, 946, 1992, 1334, 871, 473, 474, 475, + 476, 477, 478, 1560, 1985, 377, 378, 379, 380, 381, + 382, 870, 872, 377, 378, 379, 380, 381, 382, 377, + 378, 379, 380, 381, 382, 873, 888, 500, 1097, 887, + + 377, 378, 379, 380, 381, 382, 874, 942, 1098, 376, + 875, 376, 1339, 1340, 377, 378, 379, 380, 381, 382, + 882, 1035, 1035, 1035, 873, 888, 500, 376, 887, 883, + 889, 884, 1555, 1544, 1969, 874, 942, 1098, 376, 875, + 376, 1339, 1340, 377, 378, 379, 380, 381, 382, 882, + 377, 378, 379, 380, 381, 382, 376, 1961, 883, 889, + 884, 377, 378, 379, 380, 381, 382, 377, 378, 379, + 380, 381, 382, 876, 376, 376, 376, 891, 877, 639, + 639, 639, 894, 1019, 376, 885, 878, 1513, 879, 892, + 1953, 880, 376, 886, 881, 377, 378, 379, 380, 381, + + 382, 1950, 876, 376, 376, 376, 891, 877, 1944, 893, + 1036, 894, 1487, 376, 885, 878, 895, 879, 892, 896, + 880, 376, 886, 881, 1341, 377, 378, 379, 380, 381, + 382, 897, 1324, 1342, 1324, 898, 901, 1325, 893, 377, + 378, 379, 380, 381, 382, 895, 1912, 902, 896, 757, + 1897, 1320, 1893, 1341, 377, 378, 379, 380, 381, 382, + 897, 1095, 1342, 1412, 898, 901, 1861, 1854, 643, 899, + 903, 1343, 1451, 1452, 1453, 900, 902, 1454, 377, 378, + 379, 380, 381, 382, 377, 378, 379, 380, 381, 382, + 1095, 1849, 377, 378, 379, 380, 381, 382, 899, 903, + + 1343, 1451, 1452, 1453, 900, 1388, 1454, 1842, 377, 378, + 379, 380, 381, 382, 1377, 1836, 377, 378, 379, 380, + 381, 382, 1828, 377, 378, 379, 380, 381, 382, 904, + 904, 904, 904, 904, 904, 904, 904, 904, 905, 906, + 906, 906, 906, 906, 906, 906, 906, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 908, 908, 908, 908, + 908, 908, 908, 909, 910, 911, 911, 911, 911, 911, + 911, 911, 911, 911, 376, 376, 376, 376, 376, 376, + 376, 376, 376, 358, 912, 912, 912, 912, 912, 912, + 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, + + 912, 376, 376, 376, 376, 376, 376, 376, 376, 376, + 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, + 913, 914, 915, 913, 916, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 917, 917, 917, + 917, 917, 917, 917, 917, 917, 472, 472, 472, 472, + 472, 472, 472, 472, 472, 489, 489, 489, 489, 489, + 489, 489, 489, 489, 490, 491, 491, 491, 491, 491, + 491, 491, 491, 492, 492, 492, 492, 492, 492, 492, + 492, 492, 493, 493, 493, 493, 493, 493, 493, 918, + 495, 496, 496, 496, 496, 496, 496, 496, 496, 496, + + 921, 922, 660, 661, 662, 663, 664, 665, 923, 925, + 924, 1822, 1818, 1814, 1455, 1796, 926, 472, 472, 472, + 472, 472, 472, 472, 472, 472, 1787, 975, 975, 921, + 922, 975, 1780, 975, 975, 975, 1761, 923, 925, 924, + 1045, 1045, 1046, 1455, 1045, 926, 1045, 1045, 1045, 1751, + 1200, 473, 474, 475, 476, 477, 478, 473, 474, 475, + 476, 477, 478, 473, 474, 475, 476, 477, 478, 473, + 474, 475, 476, 477, 478, 473, 474, 475, 476, 477, + 478, 473, 474, 475, 476, 477, 478, 927, 927, 927, + 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, + + 927, 927, 927, 927, 472, 472, 472, 472, 472, 472, + 472, 472, 472, 928, 928, 928, 928, 928, 928, 928, + 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, + 928, 931, 931, 931, 931, 931, 931, 931, 931, 931, + 499, 499, 499, 1734, 1732, 1709, 2786, 2786, 2786, 1456, + 1703, 501, 1699, 501, 502, 1670, 1336, 2786, 1330, 2786, + 502, 2786, 2786, 2786, 1317, 503, 504, 1665, 505, 1304, + 1296, 397, 2786, 1346, 2786, 502, 525, 506, 1456, 507, + 526, 508, 1457, 818, 500, 2786, 2786, 2786, 1458, 527, + 1459, 1460, 1461, 528, 503, 504, 2786, 505, 2786, 502, + + 1656, 1284, 1278, 1480, 1480, 525, 506, 1276, 507, 526, + 508, 1457, 818, 500, 1462, 519, 1464, 1458, 527, 1459, + 1460, 1461, 528, 1475, 1475, 1274, 1470, 509, 510, 511, + 512, 513, 514, 509, 510, 515, 512, 513, 514, 633, + 633, 633, 1470, 1462, 519, 1464, 1014, 1634, 509, 510, + 515, 512, 513, 514, 500, 500, 500, 500, 500, 500, + 500, 500, 500, 529, 529, 529, 529, 529, 529, 529, + 529, 529, 509, 510, 515, 512, 513, 514, 530, 531, + 531, 531, 531, 531, 531, 531, 531, 532, 532, 532, + 532, 532, 532, 532, 532, 532, 533, 533, 533, 533, + + 533, 533, 533, 534, 535, 536, 536, 536, 536, 536, + 536, 536, 536, 536, 932, 531, 531, 531, 531, 531, + 531, 531, 531, 940, 565, 1629, 1627, 1623, 637, 1621, + 500, 974, 974, 974, 974, 974, 974, 974, 974, 941, + 500, 500, 500, 500, 500, 500, 500, 500, 500, 1602, + 1575, 1130, 940, 700, 701, 702, 703, 704, 705, 500, + 1510, 566, 567, 568, 569, 570, 571, 1112, 941, 499, + 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, + 945, 945, 945, 945, 945, 945, 945, 500, 500, 500, + 500, 500, 500, 500, 500, 500, 946, 946, 946, 946, + + 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, + 946, 946, 946, 946, 947, 947, 947, 947, 947, 947, + 947, 947, 947, 538, 538, 538, 538, 538, 538, 538, + 538, 538, 948, 948, 948, 948, 948, 948, 948, 948, + 948, 949, 950, 950, 950, 950, 950, 950, 950, 950, + 951, 951, 951, 951, 951, 951, 951, 951, 951, 952, + 952, 952, 952, 952, 952, 952, 953, 954, 955, 955, + 955, 955, 955, 955, 955, 955, 955, 545, 545, 545, + 545, 545, 545, 545, 545, 545, 572, 572, 572, 572, + 572, 572, 572, 572, 572, 573, 574, 574, 574, 574, + + 574, 574, 574, 574, 575, 575, 575, 575, 575, 575, + 575, 575, 575, 576, 576, 576, 576, 576, 576, 576, + 577, 578, 579, 579, 579, 579, 579, 579, 579, 579, + 579, 553, 552, 552, 552, 552, 552, 552, 552, 552, + 552, 956, 956, 956, 956, 956, 956, 956, 956, 956, + 957, 958, 958, 958, 958, 958, 958, 958, 958, 959, + 959, 959, 959, 959, 959, 959, 959, 959, 960, 960, + 960, 960, 960, 960, 960, 961, 962, 963, 963, 963, + 963, 963, 963, 963, 963, 963, 1509, 1108, 964, 965, + 564, 564, 564, 564, 564, 564, 564, 564, 564, 966, + + 966, 966, 966, 966, 966, 966, 966, 966, 1507, 1325, + 1325, 554, 555, 556, 557, 558, 559, 964, 965, 967, + 968, 968, 968, 968, 968, 968, 968, 968, 719, 720, + 721, 722, 723, 724, 1323, 1323, 546, 547, 548, 549, + 550, 551, 969, 969, 969, 969, 969, 969, 969, 969, + 969, 1321, 1092, 546, 547, 548, 549, 550, 551, 970, + 970, 970, 970, 970, 970, 970, 971, 972, 973, 973, + 973, 973, 973, 973, 973, 973, 973, 545, 545, 545, + 545, 545, 545, 545, 545, 545, 974, 974, 974, 974, + 974, 974, 974, 974, 974, 545, 545, 545, 545, 545, + + 545, 545, 545, 545, 975, 975, 975, 975, 975, 975, + 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, + 975, 975, 976, 976, 976, 976, 976, 976, 976, 976, + 976, 651, 651, 1502, 1501, 651, 651, 1065, 1497, 651, + 651, 651, 651, 651, 651, 651, 651, 651, 1049, 651, + 651, 651, 651, 651, 652, 652, 652, 652, 652, 652, + 652, 652, 652, 1025, 1025, 1025, 1025, 1025, 1025, 1025, + 1025, 1025, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, + 651, 1495, 651, 1026, 1027, 1027, 1027, 1027, 1027, 1027, + 1027, 1027, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, + + 1028, 746, 747, 748, 749, 750, 751, 1485, 1035, 651, + 651, 651, 651, 651, 651, 651, 651, 651, 651, 653, + 654, 655, 656, 657, 658, 1029, 1029, 1029, 1029, 1029, + 1029, 1029, 1030, 1031, 1032, 1032, 1032, 1032, 1032, 1032, + 1032, 1032, 1032, 659, 659, 659, 659, 659, 659, 659, + 659, 659, 673, 673, 673, 673, 673, 673, 673, 673, + 673, 1033, 675, 675, 675, 675, 675, 675, 675, 675, + 676, 676, 676, 676, 676, 676, 676, 676, 676, 677, + 677, 677, 677, 677, 677, 677, 1034, 679, 680, 680, + 680, 680, 680, 680, 680, 680, 680, 1039, 1040, 1465, + + 1466, 1483, 1482, 1477, 1041, 659, 659, 659, 659, 659, + 659, 659, 659, 659, 1071, 1071, 1072, 1073, 1071, 1042, + 1071, 1071, 1071, 1472, 1463, 1431, 1039, 1040, 1465, 1466, + 1077, 1077, 1043, 1041, 1077, 1138, 1077, 1077, 1077, 1138, + 1136, 1136, 660, 661, 662, 663, 664, 665, 1042, 660, + 661, 662, 663, 664, 665, 660, 661, 662, 663, 664, + 665, 1043, 682, 682, 682, 1134, 660, 661, 662, 663, + 664, 665, 1049, 1049, 1049, 660, 661, 662, 663, 664, + 665, 649, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, + 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 659, + + 659, 659, 659, 659, 659, 659, 659, 659, 1045, 1045, + 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, + 1045, 1045, 1045, 1045, 1045, 1045, 1047, 1047, 1047, 1047, + 1047, 1047, 1047, 1047, 1047, 689, 689, 689, 692, 692, + 692, 692, 692, 692, 692, 692, 692, 815, 1345, 1344, + 1338, 683, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, + 1055, 1050, 1056, 1057, 1057, 1057, 1057, 1057, 1057, 1057, + 1057, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, + 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1060, 1061, 1062, + 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 699, 699, + + 699, 699, 699, 699, 699, 699, 699, 710, 710, 710, + 710, 710, 710, 710, 710, 710, 1119, 1119, 1119, 1119, + 1119, 1119, 1119, 1119, 690, 691, 691, 1332, 1321, 691, + 691, 1319, 1315, 691, 691, 691, 691, 691, 691, 691, + 691, 691, 1467, 691, 691, 691, 691, 691, 1063, 712, + 712, 712, 712, 712, 712, 712, 712, 713, 713, 713, + 713, 713, 713, 713, 713, 713, 1065, 1065, 1065, 1484, + 735, 1467, 1494, 1496, 691, 1306, 691, 714, 714, 714, + 714, 714, 714, 714, 1064, 716, 717, 717, 717, 717, + 717, 717, 717, 717, 717, 1067, 1508, 1569, 1484, 1068, + + 689, 1494, 1496, 691, 691, 691, 691, 691, 691, 691, + 691, 691, 691, 693, 694, 695, 696, 697, 698, 1298, + 1286, 649, 639, 1069, 1067, 1508, 1569, 1021, 1068, 699, + 699, 699, 699, 699, 699, 699, 699, 699, 1021, 633, + 700, 701, 702, 703, 704, 705, 700, 701, 702, 703, + 704, 705, 1069, 1016, 1016, 1066, 689, 1070, 1070, 1070, + 1070, 1070, 1070, 1070, 1070, 626, 700, 701, 702, 703, + 704, 705, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, + 1070, 699, 699, 699, 699, 699, 699, 699, 699, 699, + 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, + + 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1074, 1074, + 1074, 1074, 1074, 1074, 1074, 1074, 1074, 718, 718, 718, + 718, 718, 718, 718, 718, 718, 726, 726, 726, 726, + 726, 726, 726, 726, 726, 727, 728, 728, 728, 728, + 728, 728, 728, 728, 729, 729, 729, 729, 729, 729, + 729, 729, 729, 730, 730, 730, 730, 730, 730, 730, + 731, 732, 733, 733, 733, 733, 733, 733, 733, 733, + 733, 1075, 718, 718, 718, 718, 718, 718, 718, 718, + 718, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, + 718, 718, 718, 718, 718, 718, 718, 718, 718, 1011, + + 1075, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, + 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 735, + 735, 735, 719, 720, 721, 722, 723, 724, 1078, 1078, + 1078, 1078, 1078, 1078, 1078, 1078, 1078, 738, 738, 738, + 738, 738, 738, 738, 738, 738, 1081, 1081, 1081, 1081, + 1081, 1081, 1081, 1081, 1081, 1082, 1083, 1083, 1083, 1083, + 1083, 1083, 1083, 1083, 1084, 1084, 1084, 1084, 1084, 1084, + 1084, 1084, 1084, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1086, 1087, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, + 1088, 745, 745, 745, 745, 745, 745, 745, 745, 745, + + 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 736, 737, + 737, 1567, 1011, 737, 737, 1263, 1259, 737, 737, 737, + 737, 737, 737, 737, 737, 737, 1568, 737, 737, 737, + 737, 737, 762, 762, 762, 762, 762, 762, 762, 762, + 762, 1089, 764, 764, 764, 764, 764, 764, 764, 764, + 1092, 1092, 1092, 1225, 1100, 1568, 1100, 1134, 737, 1101, + 737, 765, 765, 765, 765, 765, 765, 765, 765, 765, + 766, 766, 766, 766, 766, 766, 766, 1090, 768, 912, + 912, 912, 912, 912, 912, 912, 912, 737, 737, 737, + 737, 737, 737, 737, 737, 737, 737, 739, 740, 741, + + 742, 743, 744, 769, 769, 769, 769, 769, 769, 769, + 769, 769, 757, 1102, 1099, 473, 474, 475, 476, 477, + 478, 1105, 1105, 1103, 759, 1105, 1106, 1105, 1105, 1105, + 746, 747, 748, 749, 750, 751, 1132, 1128, 358, 1093, + 777, 783, 1102, 745, 745, 745, 745, 745, 745, 745, + 745, 745, 1103, 759, 735, 1104, 1104, 1104, 1104, 1104, + 1104, 1104, 1104, 770, 746, 747, 748, 749, 750, 751, + 746, 747, 748, 749, 750, 751, 1104, 1104, 1104, 1104, + 1104, 1104, 1104, 1104, 1104, 746, 747, 748, 749, 750, + 751, 745, 745, 745, 745, 745, 745, 745, 745, 745, + + 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, + 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1107, 1107, + 1107, 1107, 1107, 1107, 1107, 1107, 1107, 770, 770, 770, + 1108, 1108, 1108, 777, 777, 777, 1112, 1112, 1112, 361, + 361, 361, 361, 361, 361, 361, 361, 361, 1119, 1119, + 1119, 1119, 1119, 1119, 1119, 1119, 1119, 361, 361, 361, + 361, 361, 361, 361, 361, 361, 1120, 1120, 1120, 1120, + 1120, 1120, 1120, 1120, 1120, 1120, 1120, 776, 756, 1120, + 1091, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, + 1120, 1120, 1120, 1121, 1121, 1121, 1121, 1121, 1121, 1121, + + 1121, 1121, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 1080, 1054, 682, 687, 1024, 771, 1023, 1022, 1109, + 1021, 1018, 778, 1017, 1016, 1113, 1122, 1122, 1122, 1122, + 1122, 1122, 1122, 1122, 1122, 369, 369, 369, 369, 369, + 369, 369, 369, 369, 1123, 1123, 1123, 1123, 1123, 1123, + 1123, 1123, 1123, 1123, 1123, 1013, 1570, 1123, 1012, 1123, + 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, + 1123, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, + 913, 913, 1011, 1008, 913, 1570, 913, 913, 913, 383, + 383, 383, 383, 383, 383, 383, 383, 383, 1125, 1125, + + 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, + 1125, 1125, 1125, 1125, 1125, 383, 383, 383, 383, 383, + 383, 383, 383, 383, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1228, 2786, 1126, 824, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, + 1130, 815, 815, 397, 1228, 1139, 1223, 1223, 1007, 2786, + 1223, 1006, 1223, 1223, 1223, 399, 1571, 2786, 928, 928, + 1005, 1004, 928, 2786, 928, 928, 928, 1572, 1000, 1140, + 598, 757, 990, 1503, 2786, 989, 473, 474, 475, 476, + + 477, 478, 1141, 1095, 399, 1571, 988, 2786, 987, 377, + 378, 379, 380, 381, 382, 986, 1572, 2786, 1140, 1142, + 473, 474, 475, 476, 477, 478, 919, 2786, 395, 814, + 787, 1141, 1095, 1143, 783, 1145, 377, 378, 379, 380, + 381, 382, 377, 378, 379, 380, 381, 382, 1142, 1131, + 377, 378, 379, 380, 381, 382, 377, 378, 379, 380, + 381, 382, 1143, 2786, 1145, 780, 776, 377, 378, 379, + 380, 381, 382, 773, 756, 752, 706, 2786, 688, 1144, + 377, 378, 379, 380, 381, 382, 2786, 687, 685, 1573, + 377, 378, 379, 380, 381, 382, 1146, 1274, 1274, 1274, + + 377, 378, 379, 380, 381, 382, 1147, 2786, 1144, 456, + 456, 456, 456, 456, 456, 456, 456, 456, 1573, 667, + 666, 2786, 1276, 1276, 1276, 1146, 648, 1574, 1150, 646, + 2786, 624, 623, 620, 619, 1147, 377, 378, 379, 380, + 381, 382, 1148, 1278, 1278, 1278, 397, 1149, 1511, 1152, + 377, 378, 379, 380, 381, 382, 1574, 1150, 818, 377, + 378, 379, 380, 381, 382, 2786, 616, 615, 1284, 1035, + 1035, 1148, 2786, 1151, 614, 613, 1149, 600, 1152, 599, + 377, 378, 379, 380, 381, 382, 1275, 818, 596, 1619, + 2786, 1153, 595, 592, 377, 378, 379, 380, 381, 382, + + 1156, 2786, 1151, 377, 378, 379, 380, 381, 382, 1246, + 1246, 1277, 591, 1246, 2786, 1246, 1246, 1246, 1619, 481, + 1153, 2786, 1154, 396, 1157, 395, 1155, 391, 2786, 1156, + 2786, 1159, 1279, 1620, 245, 245, 243, 2786, 377, 378, + 379, 380, 381, 382, 1622, 377, 378, 379, 380, 381, + 382, 1154, 1158, 1157, 2786, 1155, 1160, 1285, 243, 2786, + 1159, 2786, 1620, 377, 378, 379, 380, 381, 382, 2786, + 2786, 1624, 2786, 1622, 377, 378, 379, 380, 381, 382, + 1161, 1158, 2786, 2786, 2786, 1160, 2786, 377, 378, 379, + 380, 381, 382, 1162, 377, 378, 379, 380, 381, 382, + + 1624, 2786, 2786, 377, 378, 379, 380, 381, 382, 1161, + 377, 378, 379, 380, 381, 382, 2786, 2786, 1296, 1049, + 1049, 2786, 1162, 1164, 2786, 2786, 2786, 377, 378, 379, + 380, 381, 382, 1249, 1249, 1625, 1163, 1249, 2786, 1249, + 1249, 1249, 1626, 1628, 2786, 377, 378, 379, 380, 381, + 382, 2786, 1164, 1165, 1166, 377, 378, 379, 380, 381, + 382, 2786, 2786, 2786, 1625, 1163, 1168, 1167, 2786, 2786, + 2786, 1626, 1628, 2786, 2786, 377, 378, 379, 380, 381, + 382, 1170, 1165, 1166, 2786, 2786, 2786, 2786, 2786, 377, + 378, 379, 380, 381, 382, 1168, 1167, 2786, 377, 378, + + 379, 380, 381, 382, 2786, 2786, 1169, 1297, 2786, 1171, + 1170, 377, 378, 379, 380, 381, 382, 377, 378, 379, + 380, 381, 382, 2786, 377, 378, 379, 380, 381, 382, + 2786, 2786, 2786, 1254, 1254, 1169, 2786, 1254, 1171, 1254, + 1254, 1254, 377, 378, 379, 380, 381, 382, 2786, 1630, + 1174, 2786, 1172, 1631, 1632, 1173, 1633, 377, 378, 379, + 380, 381, 382, 1175, 2786, 1638, 2786, 2786, 2786, 2786, + 377, 378, 379, 380, 381, 382, 2786, 2786, 1630, 1174, + 2786, 1172, 1631, 1632, 1173, 1633, 1304, 1065, 1065, 2786, + 2786, 2786, 1175, 1176, 1638, 2786, 377, 378, 379, 380, + + 381, 382, 1177, 377, 378, 379, 380, 381, 382, 377, + 378, 379, 380, 381, 382, 2786, 2786, 1179, 1180, 1317, + 1092, 1092, 1176, 2786, 377, 378, 379, 380, 381, 382, + 1178, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 2786, + 377, 378, 379, 380, 381, 382, 1179, 1180, 2786, 1181, + 377, 378, 379, 380, 381, 382, 2786, 2786, 1639, 1178, + 2786, 2786, 377, 378, 379, 380, 381, 382, 377, 378, + 379, 380, 381, 382, 2786, 1305, 1661, 1697, 1181, 2786, + 1182, 1698, 1708, 1184, 2786, 1728, 1183, 1639, 1729, 377, + 378, 379, 380, 381, 382, 2786, 377, 378, 379, 380, + + 381, 382, 2786, 2786, 2786, 1661, 1697, 1186, 1318, 1182, + 1698, 1708, 1184, 2786, 1728, 1183, 1185, 1729, 2786, 2786, + 2786, 377, 378, 379, 380, 381, 382, 1187, 2786, 377, + 378, 379, 380, 381, 382, 2786, 1186, 2786, 1189, 1730, + 1731, 1733, 2786, 1192, 1188, 1185, 2786, 377, 378, 379, + 380, 381, 382, 1190, 1735, 1738, 1187, 377, 378, 379, + 380, 381, 382, 2786, 2786, 2786, 2786, 1189, 1730, 1731, + 1733, 1739, 1192, 1188, 2786, 377, 378, 379, 380, 381, + 382, 2786, 1190, 1735, 1738, 1193, 377, 378, 379, 380, + 381, 382, 377, 378, 379, 380, 381, 382, 1226, 1191, + + 1739, 377, 378, 379, 380, 381, 382, 2786, 377, 378, + 379, 380, 381, 382, 1193, 377, 378, 379, 380, 381, + 382, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 1191, 1195, + 2786, 2786, 2786, 1194, 2786, 1330, 1108, 1108, 2786, 377, + 378, 379, 380, 381, 382, 2786, 1196, 377, 378, 379, + 380, 381, 382, 2786, 1200, 1200, 1200, 1199, 1195, 1281, + 1281, 1197, 1194, 1281, 1742, 1281, 1281, 1281, 2786, 473, + 474, 475, 476, 477, 478, 1196, 2786, 2786, 2786, 2786, + 377, 378, 379, 380, 381, 382, 1199, 1743, 1198, 2786, + 1197, 2786, 2786, 1742, 377, 378, 379, 380, 381, 382, + + 377, 378, 379, 380, 381, 382, 1202, 377, 378, 379, + 380, 381, 382, 2786, 2786, 2786, 1743, 2786, 377, 378, + 379, 380, 381, 382, 1331, 2786, 377, 378, 379, 380, + 381, 382, 1744, 1251, 1745, 1202, 1203, 2786, 2786, 2786, + 2786, 377, 378, 1201, 380, 381, 382, 1746, 2786, 377, + 378, 379, 380, 381, 382, 2786, 2786, 2786, 2786, 2786, + 2786, 1744, 1251, 1745, 1204, 1203, 1205, 1206, 1207, 2786, + 546, 547, 548, 549, 550, 551, 1746, 1213, 2786, 546, + 547, 548, 549, 550, 551, 2786, 377, 378, 379, 380, + 381, 382, 2786, 1204, 2786, 1205, 1206, 1207, 2786, 1210, + + 546, 547, 548, 549, 550, 551, 1213, 1211, 1208, 1212, + 2786, 2786, 377, 378, 379, 380, 381, 382, 2786, 1209, + 2786, 377, 378, 379, 380, 381, 382, 2786, 1210, 377, + 378, 379, 380, 381, 382, 1214, 1211, 1208, 1212, 1336, + 1112, 1112, 377, 378, 379, 380, 381, 382, 1209, 2786, + 2786, 377, 378, 379, 380, 381, 382, 2786, 377, 378, + 379, 380, 381, 382, 1214, 377, 378, 379, 380, 381, + 382, 377, 378, 379, 380, 381, 382, 1216, 1215, 2786, + 2786, 2786, 2786, 377, 378, 379, 380, 381, 382, 2786, + 2786, 1747, 2786, 377, 378, 379, 380, 381, 382, 2786, + + 1218, 2786, 2786, 2786, 2786, 2786, 1216, 1215, 1217, 1222, + 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1221, 1227, + 1747, 2786, 377, 378, 379, 380, 381, 382, 1337, 1218, + 377, 378, 379, 380, 381, 382, 2786, 1217, 2786, 2786, + 2786, 2786, 1219, 1750, 1775, 1776, 1220, 1221, 1227, 2786, + 2786, 2786, 377, 378, 379, 380, 381, 382, 2786, 473, + 474, 475, 476, 477, 478, 377, 378, 379, 380, 381, + 382, 1219, 1750, 1775, 1776, 1220, 377, 378, 379, 380, + 381, 382, 456, 456, 456, 456, 456, 456, 456, 456, + 456, 2786, 2786, 2786, 377, 378, 379, 380, 381, 382, + + 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, + 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1224, 1224, + 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1229, 1230, 2786, + 1231, 377, 378, 379, 380, 381, 382, 376, 376, 376, + 376, 376, 376, 376, 376, 376, 472, 472, 472, 472, + 472, 472, 472, 472, 472, 2786, 1229, 1230, 1232, 1231, + 945, 945, 945, 945, 945, 945, 945, 945, 1130, 815, + 815, 2786, 1777, 502, 2786, 473, 474, 475, 476, 477, + 478, 473, 474, 475, 476, 477, 478, 1232, 2786, 502, + 473, 474, 475, 476, 477, 478, 1233, 1234, 502, 1045, + + 1045, 1777, 1781, 1045, 502, 1045, 1045, 1045, 2786, 1782, + 2786, 1740, 502, 473, 474, 475, 476, 477, 478, 502, + 2786, 2786, 1237, 1741, 1235, 1233, 1234, 1783, 2786, 1301, + 1301, 1781, 1236, 1301, 502, 1301, 1301, 1301, 1782, 1238, + 1740, 502, 2786, 2786, 2786, 2786, 509, 510, 515, 512, + 513, 514, 1741, 1235, 2786, 1241, 1783, 1131, 2786, 502, + 2786, 1236, 509, 510, 515, 512, 513, 514, 1238, 1239, + 502, 509, 510, 515, 512, 513, 514, 509, 510, 515, + 512, 513, 514, 502, 1241, 509, 510, 515, 512, 513, + 514, 502, 509, 510, 515, 512, 513, 514, 502, 2786, + + 1784, 1244, 1240, 2786, 502, 1243, 2786, 509, 510, 515, + 512, 513, 514, 1785, 509, 510, 515, 512, 513, 514, + 1071, 1071, 1786, 1788, 1071, 1242, 1071, 1071, 1071, 1784, + 1244, 1240, 509, 510, 515, 512, 513, 514, 2786, 2786, + 2786, 1789, 1785, 509, 510, 515, 512, 513, 514, 2786, + 2786, 1786, 1788, 2786, 1242, 2786, 509, 510, 515, 512, + 513, 514, 2786, 2786, 509, 510, 515, 512, 513, 514, + 1789, 509, 510, 515, 512, 513, 514, 509, 510, 515, + 512, 513, 514, 500, 500, 500, 500, 500, 500, 500, + 500, 500, 538, 538, 538, 538, 538, 538, 538, 538, + + 538, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, + 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 538, 538, + 538, 538, 538, 538, 538, 538, 538, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1247, 1247, 1247, 1247, 1247, + 1247, 1247, 1247, 1247, 552, 552, 552, 552, 552, 552, + 552, 552, 552, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 552, 552, 552, 552, 552, 552, 552, 552, 552, 1249, + 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + + 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1250, 1250, 1250, + 1250, 1250, 1250, 1250, 1250, 1250, 1252, 564, 564, 564, + 564, 564, 564, 564, 564, 564, 1253, 1253, 1253, 1253, + 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, + 1253, 1253, 1253, 2786, 2786, 1252, 564, 564, 564, 564, + 564, 564, 564, 564, 564, 1254, 1254, 1254, 1254, 1254, + 1254, 1254, 1254, 1254, 660, 661, 662, 663, 664, 665, + 546, 547, 548, 549, 550, 551, 1254, 1254, 1254, 1254, + 1254, 1254, 1254, 1254, 1254, 1255, 1255, 1255, 1255, 1255, + 1255, 1255, 1255, 1255, 545, 545, 545, 545, 545, 545, + + 545, 545, 545, 652, 652, 652, 652, 652, 652, 652, + 652, 652, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, + 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 652, + 652, 652, 652, 652, 652, 652, 652, 652, 1281, 1281, + 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, + 1281, 1281, 1281, 1281, 1281, 1281, 1282, 1282, 1282, 1282, + 1282, 1282, 1282, 1282, 1282, 1044, 1044, 1044, 1044, 1044, + 1044, 1044, 1044, 1289, 1291, 1293, 1790, 1795, 1290, 660, + 661, 662, 663, 664, 665, 659, 659, 659, 659, 659, + 659, 659, 659, 659, 1300, 1300, 1300, 1300, 1300, 1300, + + 1300, 1300, 1289, 1291, 2786, 1790, 1795, 1290, 1292, 2786, + 2786, 2786, 2786, 660, 661, 662, 663, 664, 665, 700, + 701, 702, 703, 704, 705, 660, 661, 662, 663, 664, + 665, 660, 661, 662, 663, 664, 665, 1292, 660, 661, + 662, 663, 664, 665, 692, 692, 692, 692, 692, 692, + 692, 692, 692, 2786, 660, 661, 662, 663, 664, 665, + 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 692, + 692, 692, 692, 692, 692, 692, 692, 692, 1301, 1301, + 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, + 1301, 1301, 1301, 1301, 1301, 1301, 1302, 1302, 1302, 1302, + + 1302, 1302, 1302, 1302, 1302, 1070, 1070, 1070, 1070, 1070, + 1070, 1070, 1070, 1307, 2786, 2786, 2786, 1309, 700, 701, + 702, 703, 704, 705, 1310, 1308, 699, 699, 699, 699, + 699, 699, 699, 699, 699, 719, 720, 721, 722, 723, + 724, 2786, 1307, 719, 720, 721, 722, 723, 724, 1284, + 1035, 1035, 2786, 1310, 1308, 700, 701, 702, 703, 704, + 705, 2786, 2786, 2786, 2786, 700, 701, 702, 703, 704, + 705, 700, 701, 702, 703, 704, 705, 719, 720, 721, + 722, 723, 724, 718, 718, 718, 718, 718, 718, 718, + 718, 718, 738, 738, 738, 738, 738, 738, 738, 738, + + 738, 1312, 1312, 1312, 1312, 1312, 1312, 1312, 1312, 1312, + 1312, 1312, 1312, 1312, 1312, 1312, 1312, 1312, 738, 738, + 738, 738, 738, 738, 738, 738, 738, 1313, 1313, 1313, + 1313, 1313, 1313, 1313, 1313, 1313, 1313, 1313, 1285, 2786, + 1313, 2786, 1313, 1313, 1313, 1313, 1313, 1313, 1313, 1313, + 1313, 1313, 1313, 1313, 1314, 1314, 1314, 1314, 1314, 1314, + 1314, 1314, 1314, 1104, 1104, 1104, 1104, 1104, 1104, 1104, + 1104, 1105, 1105, 2786, 757, 1105, 1326, 1105, 1105, 1105, + 2786, 2786, 1101, 1469, 1274, 1274, 759, 2786, 2786, 2786, + 1470, 2786, 2786, 2786, 2786, 2786, 1327, 473, 474, 475, + + 476, 477, 478, 457, 2786, 2786, 360, 2786, 2786, 2786, + 2786, 2786, 360, 2786, 2786, 759, 745, 745, 745, 745, + 745, 745, 745, 745, 745, 1327, 2786, 2786, 2786, 2786, + 1328, 361, 361, 361, 361, 361, 361, 361, 361, 361, + 458, 459, 460, 461, 462, 463, 1798, 746, 747, 748, + 749, 750, 751, 746, 747, 748, 749, 750, 751, 1328, + 746, 747, 748, 749, 750, 751, 746, 747, 748, 749, + 750, 751, 1471, 384, 1821, 1798, 2786, 746, 747, 748, + 749, 750, 751, 746, 747, 748, 749, 750, 751, 362, + 363, 364, 365, 366, 367, 362, 363, 364, 365, 366, + + 367, 368, 368, 1821, 1838, 368, 368, 2786, 2786, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 2786, 368, + 368, 368, 368, 368, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 1838, 2786, 1296, 1049, 1049, 384, 383, + 383, 383, 383, 383, 383, 383, 383, 383, 2786, 2786, + 368, 2786, 368, 385, 386, 387, 388, 389, 390, 2786, + 397, 2786, 1347, 1411, 466, 466, 466, 466, 466, 466, + 466, 466, 399, 2786, 1479, 1278, 1278, 2786, 1480, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 368, 370, + 371, 372, 373, 374, 375, 368, 368, 1839, 1748, 368, + + 368, 399, 1348, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 1749, 368, 368, 368, 368, 368, 385, 386, + 387, 388, 389, 390, 1297, 2786, 1839, 1748, 2786, 1847, + 2786, 1348, 2786, 377, 378, 379, 380, 381, 382, 2786, + 2786, 1749, 2786, 1848, 368, 2786, 368, 2786, 2786, 2786, + 377, 378, 379, 380, 381, 382, 2786, 757, 1847, 1666, + 1349, 1350, 1736, 1481, 1853, 1737, 1351, 2786, 2786, 1095, + 1863, 2786, 1848, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 370, 371, 372, 373, 374, 375, 1349, + 1350, 1736, 2786, 1853, 1737, 1351, 1353, 2786, 1095, 1863, + + 2786, 377, 378, 379, 380, 381, 382, 2786, 1864, 1356, + 1435, 2786, 377, 378, 379, 380, 381, 382, 377, 378, + 379, 380, 381, 382, 2786, 1353, 2786, 2786, 1352, 377, + 378, 379, 380, 381, 382, 2786, 1354, 1864, 1356, 1435, + 1355, 2786, 2786, 2786, 377, 378, 379, 380, 381, 382, + 2786, 473, 474, 475, 476, 477, 478, 1352, 1357, 2786, + 2786, 1865, 1358, 1866, 1867, 1354, 2786, 1868, 2786, 1355, + 377, 378, 379, 380, 381, 382, 1361, 1359, 1360, 2786, + 377, 378, 379, 380, 381, 382, 2786, 1357, 2786, 2786, + 1865, 1358, 1866, 1867, 2786, 2786, 1868, 377, 378, 379, + + 380, 381, 382, 2786, 2786, 1361, 1359, 1360, 377, 378, + 379, 380, 381, 382, 2786, 377, 378, 379, 380, 381, + 382, 1362, 1363, 377, 378, 379, 380, 381, 382, 1364, + 2786, 2786, 377, 378, 379, 380, 381, 382, 2786, 2786, + 2786, 377, 378, 379, 380, 381, 382, 1367, 2786, 2786, + 1362, 1363, 377, 378, 379, 380, 381, 382, 1364, 1366, + 2786, 2786, 377, 378, 379, 380, 381, 382, 377, 378, + 379, 380, 381, 382, 1365, 2786, 1367, 377, 378, 379, + 380, 381, 382, 2786, 2786, 2786, 2786, 2786, 1366, 2786, + 1368, 2786, 1474, 1276, 1276, 2786, 2786, 2786, 2786, 1475, + + 1369, 1869, 1870, 1365, 377, 378, 379, 380, 381, 382, + 1370, 2786, 377, 378, 379, 380, 381, 382, 1371, 1368, + 2786, 2786, 377, 378, 379, 380, 381, 382, 2786, 1369, + 1869, 1870, 2786, 377, 378, 379, 380, 381, 382, 1370, + 2786, 2786, 2786, 2786, 1304, 1065, 1065, 1371, 377, 378, + 379, 380, 381, 382, 2786, 1373, 377, 378, 379, 380, + 381, 382, 377, 378, 379, 380, 381, 382, 377, 378, + 379, 380, 381, 382, 1375, 1372, 2786, 2786, 1871, 2786, + 2786, 1476, 2786, 1437, 377, 378, 379, 380, 381, 382, + 2786, 2786, 2786, 377, 378, 379, 380, 381, 382, 2786, + + 1377, 1377, 1377, 1375, 1372, 1374, 2786, 1871, 457, 2786, + 2786, 397, 1437, 1671, 2786, 1376, 377, 378, 379, 380, + 381, 382, 2786, 818, 1317, 1092, 1092, 377, 378, 379, + 380, 381, 382, 1305, 1374, 473, 474, 475, 476, 477, + 478, 1379, 1872, 2786, 1376, 458, 459, 460, 461, 462, + 463, 2786, 818, 377, 378, 379, 380, 381, 382, 2786, + 2786, 2786, 2786, 377, 378, 379, 380, 381, 382, 2786, + 2786, 1872, 377, 378, 379, 380, 381, 382, 1380, 377, + 378, 379, 380, 381, 382, 1381, 2786, 377, 378, 1378, + 380, 381, 382, 2786, 1873, 377, 378, 379, 380, 381, + + 382, 2786, 1330, 1108, 1108, 1382, 2786, 1380, 2786, 1336, + 1112, 1112, 1383, 1318, 1381, 1469, 1274, 1274, 2786, 2786, + 2786, 2786, 1470, 1873, 377, 378, 379, 380, 381, 382, + 1384, 1385, 2786, 2786, 1382, 377, 378, 379, 380, 381, + 382, 1383, 377, 378, 379, 380, 381, 382, 1388, 1388, + 1388, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 1386, 1384, + 1385, 757, 2786, 1815, 2786, 2786, 377, 378, 379, 380, + 381, 382, 1387, 1095, 377, 378, 379, 380, 381, 382, + 2786, 377, 378, 379, 380, 381, 382, 1386, 1390, 2786, + 2786, 1331, 377, 378, 379, 380, 381, 382, 1337, 1874, + + 2786, 1387, 1095, 2786, 1471, 2786, 377, 378, 379, 380, + 381, 382, 1391, 2786, 1807, 1807, 1807, 1390, 1474, 1276, + 1276, 1392, 1875, 2786, 2786, 1475, 2786, 2786, 1874, 377, + 378, 379, 380, 381, 382, 377, 378, 1389, 380, 381, + 382, 1391, 1393, 1876, 2786, 2786, 2786, 2786, 2786, 2786, + 1392, 1875, 1396, 377, 378, 379, 380, 381, 382, 2786, + 2786, 2786, 377, 378, 379, 380, 381, 382, 2786, 2786, + 2786, 1393, 1876, 377, 378, 379, 380, 381, 382, 1395, + 1394, 1396, 2786, 2786, 1877, 2786, 377, 378, 379, 380, + 381, 382, 2786, 2786, 2786, 1878, 2786, 377, 378, 379, + + 380, 381, 382, 1808, 2786, 2786, 2786, 1476, 1395, 1394, + 1397, 1398, 2786, 1877, 2786, 2786, 2786, 377, 378, 379, + 380, 381, 382, 1399, 1878, 2786, 1879, 2786, 2786, 2786, + 2786, 2786, 377, 378, 379, 380, 381, 382, 2786, 1397, + 1398, 377, 378, 379, 380, 381, 382, 1400, 1401, 1412, + 1412, 1412, 1399, 1416, 2786, 1879, 377, 378, 379, 380, + 381, 382, 2786, 2786, 1402, 1880, 377, 378, 379, 380, + 381, 382, 2786, 1432, 2786, 2786, 1400, 1401, 2786, 2786, + 2786, 1881, 1416, 2786, 2786, 2786, 2786, 377, 378, 379, + 380, 381, 382, 1402, 1880, 2786, 2786, 2786, 377, 378, + + 379, 380, 381, 382, 377, 378, 379, 380, 381, 382, + 1881, 377, 378, 379, 380, 381, 382, 2786, 456, 456, + 456, 456, 456, 456, 456, 456, 456, 377, 378, 379, + 380, 381, 382, 1200, 1200, 1200, 377, 378, 1413, 380, + 381, 382, 1436, 1414, 473, 474, 475, 476, 477, 478, + 2786, 2786, 2786, 2786, 1403, 2786, 2786, 1404, 1405, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 1434, 1406, 1407, + 1408, 1417, 1414, 1418, 1409, 1882, 2786, 1415, 1883, 2786, + 473, 474, 475, 476, 477, 478, 1404, 1405, 1419, 2786, + 377, 378, 379, 380, 381, 382, 1434, 1406, 1407, 1408, + + 1417, 2786, 1418, 1409, 1882, 2786, 1415, 1883, 2786, 473, + 474, 475, 476, 477, 478, 1420, 2786, 1419, 1421, 2122, + 2122, 2122, 1410, 377, 378, 379, 380, 381, 382, 1423, + 1426, 2786, 377, 378, 379, 380, 381, 382, 377, 378, + 379, 380, 381, 382, 1420, 2786, 2786, 1421, 2786, 377, + 378, 379, 380, 381, 382, 2786, 537, 2786, 1423, 1426, + 2786, 2786, 377, 378, 379, 380, 381, 382, 1778, 1422, + 1884, 2786, 2786, 1779, 377, 378, 379, 380, 381, 382, + 1425, 377, 378, 379, 380, 381, 382, 1424, 2786, 377, + 378, 379, 380, 381, 382, 2786, 2786, 1778, 1422, 1884, + + 1427, 2786, 1779, 1428, 2786, 2786, 2786, 2786, 2123, 1425, + 2786, 2786, 2786, 2786, 2786, 2786, 1424, 2786, 2786, 2786, + 2786, 377, 378, 379, 380, 381, 382, 1429, 2786, 1427, + 1430, 1885, 1428, 377, 378, 379, 380, 381, 382, 539, + 540, 541, 542, 543, 544, 377, 378, 379, 380, 381, + 382, 1433, 502, 1886, 1887, 1438, 1429, 2786, 2786, 1430, + 1885, 377, 378, 379, 380, 381, 382, 2786, 377, 378, + 379, 380, 381, 382, 377, 378, 379, 380, 381, 382, + 1433, 2786, 1886, 1887, 377, 378, 379, 380, 381, 382, + 2786, 377, 378, 379, 380, 381, 382, 502, 2786, 2786, + + 2786, 377, 378, 379, 380, 381, 382, 502, 1888, 2786, + 2786, 1911, 473, 474, 475, 476, 477, 478, 502, 553, + 397, 2786, 1819, 1439, 2786, 509, 510, 515, 512, 513, + 514, 1913, 818, 1914, 1440, 502, 1915, 1888, 2786, 1916, + 1911, 502, 2786, 2786, 2786, 2786, 2786, 502, 1917, 1918, + 2786, 2786, 1439, 1442, 2786, 2786, 2786, 1443, 1441, 1444, + 1913, 818, 1914, 1440, 502, 1915, 537, 2786, 1916, 2786, + 509, 510, 515, 512, 513, 514, 1445, 1917, 1918, 2786, + 509, 510, 515, 512, 513, 514, 1443, 1441, 1444, 2786, + 2786, 509, 510, 515, 512, 513, 514, 2786, 553, 554, + + 555, 556, 557, 558, 559, 1445, 2786, 1919, 509, 510, + 515, 512, 513, 514, 509, 510, 515, 512, 513, 514, + 509, 510, 515, 512, 513, 514, 502, 2786, 2786, 2786, + 2786, 2786, 502, 2786, 2786, 2786, 1919, 509, 510, 515, + 512, 513, 514, 502, 2786, 1446, 2786, 1449, 1447, 539, + 540, 541, 542, 543, 544, 1448, 538, 538, 538, 538, + 538, 538, 538, 538, 538, 552, 552, 552, 552, 552, + 552, 552, 552, 552, 1446, 2786, 2786, 1447, 554, 555, + 556, 557, 558, 559, 1448, 546, 547, 548, 549, 550, + 551, 565, 2786, 1450, 1920, 1921, 1922, 565, 1923, 509, + + 510, 515, 512, 513, 514, 509, 510, 515, 512, 513, + 514, 2786, 2786, 2786, 2786, 2786, 509, 510, 515, 512, + 513, 514, 1450, 1920, 1921, 1922, 2786, 1923, 566, 567, + 568, 569, 570, 571, 566, 567, 568, 569, 570, 571, + 564, 564, 564, 564, 564, 564, 564, 564, 564, 2786, + 2786, 2786, 2786, 2786, 546, 547, 548, 549, 550, 551, + 651, 651, 1492, 1486, 651, 651, 2786, 1491, 651, 651, + 651, 651, 651, 651, 651, 651, 651, 2786, 651, 651, + 651, 651, 651, 652, 652, 652, 652, 652, 652, 652, + 652, 652, 1486, 1487, 1487, 1487, 1491, 2786, 1488, 2786, + + 660, 661, 662, 663, 664, 665, 1489, 2786, 2786, 651, + 2786, 651, 692, 692, 692, 692, 692, 692, 692, 692, + 692, 2786, 2786, 2786, 2786, 660, 661, 662, 663, 664, + 665, 1493, 660, 661, 662, 663, 664, 665, 651, 651, + 651, 651, 651, 651, 651, 651, 651, 651, 653, 654, + 655, 656, 657, 658, 651, 651, 2786, 1498, 651, 651, + 1493, 2786, 651, 651, 651, 651, 651, 651, 651, 651, + 651, 1499, 651, 651, 651, 651, 651, 1924, 1925, 1926, + 660, 661, 1490, 663, 664, 665, 1498, 719, 720, 721, + 722, 723, 724, 2786, 660, 661, 662, 663, 664, 665, + + 2786, 2786, 2786, 651, 2786, 651, 1924, 1925, 1926, 700, + 701, 702, 703, 704, 705, 2786, 2786, 2786, 2786, 700, + 701, 702, 703, 704, 705, 1500, 473, 474, 475, 476, + 477, 478, 651, 651, 651, 651, 651, 651, 651, 651, + 651, 651, 653, 654, 655, 656, 657, 658, 691, 691, + 2786, 2786, 691, 691, 1500, 1930, 691, 691, 691, 691, + 691, 691, 691, 691, 691, 2786, 691, 691, 691, 691, + 691, 738, 738, 738, 738, 738, 738, 738, 738, 738, + 1513, 1513, 1513, 1934, 1930, 1544, 1544, 1544, 700, 701, + 702, 703, 704, 705, 2786, 1956, 1973, 691, 2786, 691, + + 1545, 2786, 2786, 757, 757, 1504, 1951, 2786, 397, 2786, + 1954, 2786, 1934, 2786, 2786, 759, 1095, 2786, 2786, 1505, + 818, 2786, 2786, 2786, 1956, 1973, 691, 691, 691, 691, + 691, 691, 691, 691, 691, 691, 693, 694, 695, 696, + 697, 698, 691, 691, 759, 1095, 691, 691, 1505, 818, + 691, 691, 691, 691, 691, 691, 691, 691, 691, 2786, + 691, 691, 691, 691, 691, 2786, 1605, 377, 378, 1514, + 380, 381, 382, 1974, 1702, 2786, 746, 747, 748, 749, + 750, 751, 1982, 1983, 746, 747, 748, 749, 750, 751, + 1603, 691, 2786, 691, 2786, 377, 378, 379, 380, 381, + + 382, 397, 1974, 1512, 473, 474, 475, 476, 477, 478, + 1506, 1982, 1983, 399, 1987, 2786, 1388, 1388, 1388, 2786, + 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, + 693, 694, 695, 696, 697, 698, 737, 737, 2786, 1506, + 737, 737, 399, 1987, 737, 737, 737, 737, 737, 737, + 737, 737, 737, 1551, 737, 737, 737, 737, 737, 2786, + 2786, 473, 474, 475, 476, 477, 478, 746, 747, 748, + 749, 750, 751, 2786, 377, 378, 379, 380, 381, 382, + 1989, 2786, 1551, 1990, 1991, 737, 2786, 737, 377, 378, + 379, 380, 381, 382, 2786, 2786, 2786, 2786, 2786, 2786, + + 1479, 1278, 1278, 2786, 1480, 1552, 2786, 2786, 1519, 1989, + 2786, 2786, 1990, 1991, 737, 737, 737, 737, 737, 737, + 737, 737, 737, 737, 739, 740, 741, 742, 743, 744, + 737, 737, 1515, 2786, 737, 737, 1521, 1519, 737, 737, + 737, 737, 737, 737, 737, 737, 737, 2786, 737, 737, + 737, 737, 737, 2786, 377, 378, 379, 380, 381, 382, + 2786, 1515, 1516, 2786, 1997, 1521, 2786, 1999, 2786, 2786, + 2786, 2786, 377, 378, 379, 380, 381, 382, 2002, 737, + 2786, 737, 2786, 377, 378, 379, 380, 381, 382, 1481, + 2786, 1516, 2786, 1997, 2786, 1517, 1999, 1513, 1513, 1513, + + 2786, 2786, 2786, 1518, 1520, 2786, 2786, 2002, 737, 737, + 737, 737, 737, 737, 737, 737, 737, 737, 739, 740, + 741, 742, 743, 744, 1517, 1524, 377, 378, 379, 380, + 381, 382, 1518, 1520, 1673, 2000, 377, 378, 379, 380, + 381, 382, 377, 378, 379, 380, 381, 382, 2786, 2786, + 2786, 2003, 2004, 2001, 1524, 377, 378, 379, 380, 381, + 382, 1522, 2786, 1673, 2000, 2005, 2006, 377, 378, 379, + 380, 381, 382, 377, 378, 379, 380, 381, 382, 2786, + 2003, 2004, 2001, 2786, 1523, 2009, 1674, 2786, 2010, 2786, + 1522, 1525, 2011, 2786, 2005, 2006, 2786, 2786, 2786, 1526, + + 2786, 2012, 2786, 2786, 2007, 2013, 2786, 2786, 2786, 2786, + 2786, 2786, 1527, 1523, 2009, 2008, 2014, 2010, 1531, 2786, + 1525, 2011, 377, 378, 379, 380, 381, 382, 1526, 1528, + 2012, 2786, 2786, 2007, 2013, 377, 378, 379, 380, 381, + 382, 1527, 2786, 2786, 2008, 2014, 1529, 1531, 2786, 2786, + 2786, 2786, 377, 378, 379, 380, 381, 382, 1528, 1530, + 377, 378, 379, 380, 381, 382, 1532, 2786, 2786, 377, + 378, 379, 380, 381, 382, 1529, 377, 378, 379, 380, + 381, 382, 377, 378, 379, 380, 381, 382, 1530, 2786, + 2786, 2786, 377, 378, 379, 380, 381, 382, 2786, 2786, + + 2015, 2016, 1533, 1534, 377, 378, 379, 380, 381, 382, + 1536, 2786, 2786, 2786, 2786, 2786, 377, 378, 379, 380, + 381, 382, 377, 378, 379, 380, 381, 382, 2786, 2015, + 2016, 2786, 1534, 2786, 2786, 2786, 1560, 1560, 1560, 1536, + 377, 378, 379, 380, 381, 382, 1555, 1555, 1555, 2786, + 2017, 1535, 1541, 466, 466, 466, 466, 466, 466, 466, + 466, 1537, 377, 378, 379, 380, 381, 382, 2786, 1711, + 1716, 377, 378, 379, 380, 381, 382, 2786, 2786, 2017, + 1535, 2786, 2786, 2786, 377, 378, 379, 380, 381, 382, + 1537, 1377, 1377, 1377, 1542, 2786, 2786, 2018, 1711, 1716, + + 2786, 377, 378, 379, 380, 381, 382, 377, 378, 379, + 380, 381, 382, 2786, 2786, 1544, 1544, 1544, 2786, 1538, + 1543, 2021, 2786, 1542, 2786, 1717, 2018, 2786, 1539, 2786, + 1545, 2022, 2023, 1725, 1547, 1712, 2786, 1726, 1727, 2786, + 2786, 377, 378, 379, 380, 381, 382, 2786, 1538, 1543, + 2021, 377, 378, 379, 380, 381, 382, 1539, 1548, 2786, + 2022, 2023, 1725, 1547, 2786, 2786, 1726, 1727, 377, 378, + 379, 380, 381, 382, 2786, 1555, 1555, 1555, 2786, 2019, + 1540, 2786, 2786, 2786, 2786, 2786, 1549, 1548, 2024, 2786, + 2040, 377, 378, 379, 380, 381, 382, 2786, 2041, 2786, + + 2020, 1550, 377, 378, 1546, 380, 381, 382, 2019, 377, + 378, 379, 380, 381, 382, 1549, 2786, 2024, 2786, 2040, + 377, 378, 379, 380, 381, 382, 2786, 2041, 2786, 2020, + 1550, 2786, 377, 378, 379, 380, 381, 382, 1553, 466, + 466, 466, 466, 466, 466, 466, 466, 377, 378, 379, + 380, 381, 382, 1554, 377, 378, 379, 380, 381, 382, + 2786, 2786, 377, 378, 1556, 380, 381, 382, 2786, 2042, + 377, 378, 379, 380, 381, 382, 2786, 2786, 2043, 2045, + 1558, 2786, 1554, 1560, 1560, 1560, 1557, 1559, 2786, 377, + 378, 379, 380, 381, 382, 2786, 2786, 2786, 2042, 2046, + + 1562, 377, 378, 379, 380, 381, 382, 2043, 2045, 1558, + 2786, 2786, 2786, 2786, 2786, 1557, 1559, 2786, 1563, 2786, + 546, 547, 548, 549, 550, 551, 2786, 2047, 2046, 1562, + 2048, 2786, 2786, 377, 378, 379, 380, 381, 382, 2051, + 1564, 377, 378, 379, 380, 381, 382, 1563, 1565, 2786, + 377, 378, 379, 380, 381, 382, 2047, 2786, 2786, 2048, + 1618, 377, 378, 379, 380, 381, 382, 2786, 2051, 1564, + 377, 378, 1561, 380, 381, 382, 1566, 1565, 2134, 2134, + 2134, 2786, 2786, 377, 378, 379, 380, 381, 382, 1618, + 2786, 2786, 377, 378, 379, 380, 381, 382, 2786, 377, + + 378, 379, 380, 381, 382, 1566, 1200, 912, 912, 912, + 912, 912, 912, 912, 912, 546, 547, 548, 549, 550, + 551, 2059, 377, 378, 379, 380, 381, 382, 1412, 1412, + 1412, 1590, 466, 466, 466, 466, 466, 466, 466, 466, + 377, 378, 379, 380, 381, 382, 2786, 1607, 2078, 2786, + 2059, 1576, 1577, 1578, 1579, 1580, 1581, 2786, 1582, 2093, + 1583, 1591, 1584, 2786, 2094, 1585, 2099, 2135, 1586, 1587, + 2786, 2786, 1588, 2101, 1593, 2102, 1607, 2078, 2786, 2786, + 1576, 1577, 1578, 1579, 1580, 1581, 1594, 1582, 2093, 1583, + 1591, 1584, 2786, 2094, 1585, 2099, 1592, 1586, 1587, 2786, + + 1595, 1588, 2101, 1593, 2102, 2786, 473, 474, 475, 476, + 477, 478, 1684, 1684, 1684, 1594, 2786, 1589, 2786, 377, + 378, 379, 380, 381, 382, 1592, 2786, 1685, 1596, 1595, + 377, 378, 379, 380, 381, 382, 377, 378, 379, 380, + 381, 382, 2786, 377, 378, 379, 380, 381, 382, 2786, + 2786, 377, 378, 379, 380, 381, 382, 1596, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 377, 378, 379, 380, 381, + 382, 1597, 377, 378, 379, 380, 381, 382, 377, 378, + 379, 380, 381, 382, 2786, 757, 397, 2073, 2076, 377, + 378, 379, 380, 381, 382, 1598, 2786, 1095, 818, 2786, + + 1597, 1827, 2786, 1640, 2786, 2786, 2786, 2786, 2786, 2786, + 2107, 1600, 2786, 2786, 2786, 2786, 2786, 2786, 2108, 2109, + 2110, 2115, 1599, 2116, 1598, 2117, 1095, 818, 502, 2786, + 2786, 2786, 377, 378, 379, 380, 381, 382, 1601, 2107, + 1600, 660, 661, 662, 663, 664, 665, 2108, 2109, 2110, + 2115, 1599, 2116, 2786, 2117, 2786, 2786, 377, 378, 379, + 380, 381, 382, 1610, 2786, 2786, 2786, 1601, 1604, 377, + 378, 379, 380, 381, 382, 377, 378, 379, 380, 381, + 382, 377, 378, 379, 380, 381, 382, 1606, 502, 2118, + 377, 378, 379, 380, 381, 382, 502, 1604, 2786, 2786, + + 2119, 509, 510, 515, 512, 513, 514, 2120, 2121, 502, + 2124, 2125, 1609, 2126, 2127, 1608, 1606, 502, 2118, 2786, + 473, 474, 475, 476, 477, 478, 2786, 1611, 1612, 2119, + 2128, 2786, 502, 2786, 2786, 2786, 2120, 2121, 502, 2124, + 2125, 1609, 2126, 2127, 1608, 2786, 2786, 2129, 502, 2130, + 473, 474, 475, 476, 477, 478, 1611, 1612, 1662, 2128, + 1615, 509, 510, 515, 512, 513, 514, 1613, 502, 509, + 510, 515, 512, 513, 514, 1614, 2129, 502, 2130, 2786, + 2786, 2786, 509, 510, 515, 512, 513, 514, 1616, 1615, + 509, 510, 515, 512, 513, 514, 700, 701, 702, 703, + + 704, 705, 2131, 1617, 1614, 509, 510, 515, 512, 513, + 514, 509, 510, 515, 512, 513, 514, 1616, 2786, 1658, + 2132, 509, 510, 515, 512, 513, 514, 2786, 1660, 2133, + 2786, 2131, 2786, 2786, 1487, 1487, 1487, 2786, 2786, 1641, + 1659, 509, 510, 515, 512, 513, 514, 1489, 1658, 2132, + 509, 510, 515, 512, 513, 514, 1663, 1660, 2133, 1642, + 1657, 675, 675, 675, 675, 675, 675, 675, 675, 1659, + 2786, 2786, 2786, 660, 661, 662, 663, 664, 665, 660, + 661, 662, 663, 664, 665, 1663, 2786, 2786, 1642, 2786, + 2136, 377, 378, 379, 380, 381, 382, 660, 661, 662, + + 663, 664, 665, 1675, 466, 466, 466, 466, 466, 466, + 466, 466, 2786, 700, 701, 702, 703, 704, 705, 2136, + 2786, 2786, 2786, 1643, 1644, 1645, 1487, 1487, 1644, 1644, + 1646, 1647, 1644, 1644, 1644, 1644, 1644, 1644, 1648, 1644, + 1644, 1647, 1644, 1644, 1644, 1644, 1644, 1647, 1647, 1647, + 1649, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, + 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, + 1647, 1647, 1647, 1644, 1647, 1644, 1647, 1647, 1647, 1649, + 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, + 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, + + 1647, 1647, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, + 1644, 1644, 1650, 1651, 1652, 1653, 1654, 1655, 1664, 757, + 2137, 1667, 2786, 2138, 2139, 2786, 2786, 2786, 2786, 2140, + 2141, 759, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 397, + 2786, 1672, 2786, 2786, 2786, 2786, 1668, 1664, 2786, 2137, + 2142, 399, 2138, 2139, 2786, 1669, 2143, 1676, 2140, 2141, + 759, 473, 474, 475, 476, 477, 478, 2786, 2786, 700, + 701, 702, 703, 704, 705, 1668, 1694, 1694, 1694, 2142, + 399, 2786, 2786, 2786, 1669, 2143, 1676, 2786, 2122, 2122, + 2122, 1695, 746, 747, 748, 749, 750, 751, 2786, 2786, + + 746, 747, 748, 749, 750, 751, 746, 747, 748, 749, + 750, 751, 377, 378, 379, 380, 381, 382, 377, 378, + 379, 380, 381, 382, 2786, 2144, 1677, 377, 378, 379, + 380, 381, 382, 2786, 2158, 2786, 2786, 2786, 2159, 2786, + 377, 378, 379, 380, 381, 382, 2786, 1684, 1684, 1684, + 2160, 1678, 2786, 2162, 2144, 1677, 1681, 2163, 2164, 2165, + 1679, 2786, 1685, 2158, 1682, 1835, 1680, 2159, 2786, 2786, + 2786, 377, 378, 379, 380, 381, 382, 2123, 2786, 2160, + 1678, 2786, 2162, 2786, 2786, 1681, 2163, 2164, 2165, 1679, + 2786, 2786, 2786, 1682, 2786, 1680, 2786, 377, 378, 379, + + 380, 381, 382, 1683, 2786, 2786, 377, 378, 379, 380, + 381, 382, 377, 378, 379, 380, 381, 382, 2786, 377, + 378, 379, 380, 381, 382, 377, 378, 379, 380, 381, + 382, 2187, 1683, 2786, 377, 378, 1686, 380, 381, 382, + 2786, 2786, 1687, 377, 378, 379, 380, 381, 382, 2190, + 2195, 2786, 1688, 2197, 377, 378, 379, 380, 381, 382, + 2187, 757, 2786, 2182, 2786, 377, 378, 379, 380, 381, + 382, 1687, 1689, 1095, 2786, 2786, 2786, 2786, 2190, 2195, + 2786, 1688, 2197, 1690, 1694, 1694, 1694, 2786, 1755, 1755, + 1755, 377, 378, 379, 380, 381, 382, 2786, 2786, 1695, + + 2786, 1689, 1095, 1756, 2198, 2786, 377, 378, 379, 380, + 381, 382, 1690, 377, 378, 379, 380, 381, 382, 2786, + 2786, 2786, 2786, 2786, 377, 378, 379, 380, 381, 382, + 1691, 2786, 2786, 2198, 2786, 2786, 2786, 2786, 2786, 2786, + 1692, 473, 474, 475, 476, 477, 478, 2786, 377, 378, + 379, 380, 381, 382, 2786, 2786, 1693, 2202, 1700, 1691, + 1377, 912, 912, 912, 912, 912, 912, 912, 912, 1692, + 1701, 377, 378, 1696, 380, 381, 382, 1892, 377, 378, + 379, 380, 381, 382, 2786, 1693, 2202, 1700, 2786, 2166, + 2166, 2166, 377, 378, 379, 380, 381, 382, 2786, 1701, + + 2786, 2786, 2786, 2167, 377, 378, 379, 380, 381, 382, + 377, 378, 379, 380, 381, 382, 1704, 466, 466, 466, + 466, 466, 466, 466, 466, 1705, 2786, 377, 378, 379, + 380, 381, 382, 2786, 2203, 2208, 2786, 2209, 1710, 2786, + 1388, 912, 912, 912, 912, 912, 912, 912, 912, 2786, + 2786, 2210, 1706, 2211, 1705, 1707, 2786, 377, 378, 379, + 380, 381, 382, 2203, 2208, 1714, 2209, 1710, 2214, 2216, + 2786, 377, 378, 379, 380, 381, 382, 2786, 2168, 2786, + 2210, 1706, 2211, 2786, 1707, 1713, 466, 466, 466, 466, + 466, 466, 466, 466, 1714, 2786, 2786, 2214, 2216, 377, + + 378, 379, 380, 381, 382, 2786, 377, 378, 379, 380, + 381, 382, 377, 378, 379, 380, 381, 382, 2786, 2217, + 2218, 2786, 2786, 377, 378, 379, 380, 381, 382, 377, + 378, 379, 380, 381, 382, 2786, 1718, 466, 466, 466, + 466, 466, 466, 466, 466, 2786, 2786, 1715, 2217, 2218, + 377, 378, 379, 380, 381, 382, 1719, 2786, 2786, 2786, + 1722, 1722, 1722, 2786, 2786, 397, 2219, 2185, 2786, 1720, + 2220, 2221, 2222, 2224, 2786, 1723, 1715, 818, 377, 378, + 379, 380, 381, 382, 2786, 1719, 1412, 912, 912, 912, + 912, 912, 912, 912, 912, 2219, 1721, 2786, 1720, 2220, + + 2221, 2222, 2224, 2786, 2786, 2786, 818, 1753, 377, 378, + 379, 380, 381, 382, 2786, 2786, 2786, 2786, 2786, 377, + 378, 379, 380, 381, 382, 1721, 1752, 2786, 2786, 2786, + 377, 378, 379, 380, 381, 382, 1753, 2786, 2225, 2226, + 2227, 377, 378, 379, 380, 381, 382, 377, 378, 1724, + 380, 381, 382, 2786, 1754, 1752, 2786, 377, 378, 379, + 380, 381, 382, 1762, 2228, 1758, 2786, 2225, 2226, 2227, + 377, 378, 379, 380, 381, 382, 2786, 377, 378, 379, + 380, 381, 382, 1754, 1755, 1755, 1755, 377, 378, 379, + 380, 381, 382, 2228, 1758, 1759, 1763, 2786, 2786, 1756, + + 377, 378, 379, 380, 381, 382, 2786, 2786, 2786, 2786, + 377, 378, 379, 380, 381, 382, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 1759, 1763, 377, 378, 379, 380, + 381, 382, 1760, 1764, 473, 474, 475, 476, 477, 478, + 2229, 2230, 473, 474, 475, 476, 477, 478, 502, 377, + 378, 379, 380, 381, 382, 2786, 502, 2786, 2786, 2786, + 2786, 1760, 1764, 1850, 1850, 1850, 2786, 502, 1765, 2229, + 2230, 377, 378, 1757, 380, 381, 382, 1766, 1851, 2231, + 2232, 2233, 502, 2238, 473, 474, 475, 476, 477, 478, + 2239, 377, 378, 379, 380, 381, 382, 1765, 1767, 502, + + 2786, 2786, 2786, 2786, 2786, 502, 1766, 1772, 2231, 2232, + 2233, 2786, 2238, 502, 2786, 2786, 2786, 1768, 2786, 2239, + 2240, 509, 510, 515, 512, 513, 514, 1767, 502, 509, + 510, 515, 512, 513, 514, 2786, 1772, 2241, 2250, 2786, + 509, 510, 515, 512, 513, 514, 1768, 502, 1771, 2240, + 2786, 2786, 1984, 502, 2786, 509, 510, 515, 512, 513, + 514, 2786, 2786, 1769, 1791, 2786, 2241, 2250, 1770, 1773, + 2786, 1774, 509, 510, 515, 512, 513, 514, 509, 510, + 515, 512, 513, 514, 2786, 2786, 509, 510, 515, 512, + 513, 514, 1769, 1791, 1645, 1487, 1487, 1770, 1773, 1792, + + 1774, 509, 510, 515, 512, 513, 514, 1648, 2786, 2786, + 2786, 2786, 660, 661, 662, 663, 664, 665, 2786, 1793, + 509, 510, 515, 512, 513, 514, 509, 510, 515, 512, + 513, 514, 546, 547, 548, 549, 550, 551, 1645, 1487, + 1487, 2786, 2786, 1792, 1645, 1487, 1487, 1809, 1793, 1792, + 2251, 1648, 2252, 1645, 1487, 1487, 2253, 1648, 1792, 2257, + 2786, 2265, 2266, 1793, 2267, 2268, 1797, 2269, 2274, 1793, + 660, 661, 662, 663, 664, 665, 1809, 2288, 1793, 2251, + 2786, 2252, 2786, 1794, 2786, 2253, 2786, 2786, 2257, 1810, + 2265, 2266, 1793, 2267, 2268, 2786, 2269, 2274, 1793, 660, + + 661, 662, 663, 664, 665, 2786, 2288, 1793, 1487, 1044, + 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1813, 1810, 2786, + 2786, 1811, 2291, 1812, 1899, 2292, 2293, 1794, 2296, 2786, + 2786, 2297, 2786, 1794, 660, 661, 662, 663, 664, 665, + 2786, 2786, 1794, 1645, 1487, 1487, 1813, 757, 1792, 2280, + 1811, 2291, 1812, 1899, 2292, 2293, 1648, 2296, 2300, 1095, + 2297, 1817, 700, 701, 702, 703, 704, 705, 1793, 700, + 701, 702, 703, 704, 705, 700, 701, 702, 703, 704, + 705, 473, 474, 475, 476, 477, 478, 2300, 1095, 757, + 1817, 1816, 2786, 2786, 2786, 2786, 397, 1793, 1820, 2786, + + 2786, 759, 746, 747, 748, 749, 750, 751, 399, 2786, + 2313, 2313, 2313, 746, 747, 748, 749, 750, 751, 2786, + 2786, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, + 759, 2786, 1794, 1645, 1487, 1487, 2786, 399, 1792, 546, + 547, 548, 549, 550, 551, 2786, 1648, 1513, 912, 912, + 912, 912, 912, 912, 912, 912, 2302, 2303, 1793, 2786, + 2304, 2305, 746, 747, 748, 749, 750, 751, 2786, 377, + 378, 379, 380, 381, 382, 2786, 2786, 2786, 2786, 397, + 2786, 2283, 2786, 2786, 2786, 2302, 2303, 1793, 2786, 2304, + 2305, 818, 377, 378, 379, 380, 381, 382, 1824, 2314, + + 1825, 2307, 2308, 1823, 377, 378, 379, 380, 381, 382, + 2786, 1799, 1799, 1799, 1799, 1799, 1799, 1799, 1799, 1799, + 818, 2786, 1794, 1645, 1487, 1487, 2786, 1824, 1792, 1825, + 2307, 2308, 1823, 2786, 2786, 2786, 1648, 2786, 2786, 2786, + 2786, 377, 378, 379, 380, 381, 382, 2786, 1793, 377, + 378, 379, 380, 381, 382, 377, 378, 379, 380, 381, + 382, 377, 378, 379, 380, 381, 382, 660, 661, 662, + 663, 664, 665, 2786, 2315, 2315, 2315, 1793, 2786, 2786, + 2786, 1826, 2786, 377, 378, 379, 380, 381, 382, 1829, + 466, 466, 466, 466, 466, 466, 466, 466, 2786, 2786, + + 2786, 1800, 1801, 1801, 1801, 1801, 1801, 1801, 1801, 1801, + 1826, 1830, 1794, 1645, 1487, 1487, 2309, 2786, 1792, 2786, + 377, 378, 379, 380, 381, 382, 1648, 1837, 466, 466, + 466, 466, 466, 466, 466, 466, 2786, 2786, 1793, 1910, + 1830, 2320, 2320, 2320, 2786, 2309, 377, 378, 379, 380, + 381, 382, 377, 378, 379, 380, 381, 382, 1832, 2310, + 1834, 2786, 2786, 2316, 2097, 2097, 2097, 1793, 1910, 2786, + 2786, 1831, 377, 378, 379, 380, 381, 382, 1833, 1545, + 546, 547, 548, 549, 550, 551, 2311, 1832, 2310, 1834, + 2786, 1802, 1802, 1802, 1802, 1802, 1802, 1802, 1802, 1802, + + 1831, 2786, 1794, 1645, 1487, 1487, 2786, 1833, 1792, 377, + 378, 379, 380, 381, 382, 2311, 1648, 377, 378, 379, + 380, 381, 382, 2312, 2786, 2285, 2786, 1840, 1793, 2786, + 2321, 2270, 2270, 2270, 377, 378, 379, 380, 381, 382, + 2286, 2318, 2786, 377, 378, 379, 380, 381, 382, 2786, + 2786, 2786, 2312, 2098, 2285, 2786, 1840, 1793, 1544, 912, + 912, 912, 912, 912, 912, 912, 912, 2786, 2324, 2286, + 2318, 1841, 2271, 2327, 377, 378, 379, 380, 381, 382, + 2786, 1803, 1803, 1803, 1803, 1803, 1803, 1803, 1804, 1805, + 2328, 2786, 1794, 1645, 1487, 1487, 2786, 2324, 1792, 2786, + + 1841, 2271, 2327, 2786, 2786, 2786, 1648, 2786, 2786, 2786, + 1736, 2786, 2786, 2786, 2786, 2786, 2786, 1740, 1793, 2328, + 2272, 2786, 377, 378, 379, 380, 381, 382, 377, 378, + 379, 380, 381, 382, 1846, 1850, 1850, 1850, 2786, 1736, + 377, 378, 379, 380, 381, 382, 1740, 1793, 2786, 2786, + 1851, 2786, 2786, 377, 378, 379, 380, 381, 382, 2786, + 2786, 2786, 2786, 1846, 377, 378, 379, 380, 381, 382, + 2786, 1806, 1806, 1806, 1806, 1806, 1806, 1806, 1806, 1806, + 1855, 2786, 1794, 2786, 2786, 377, 378, 379, 380, 381, + 382, 1555, 912, 912, 912, 912, 912, 912, 912, 912, + + 1560, 912, 912, 912, 912, 912, 912, 912, 912, 1855, + 2786, 377, 378, 379, 380, 381, 382, 2786, 2786, 2786, + 2786, 2329, 377, 378, 1852, 380, 381, 382, 1722, 1722, + 1722, 1856, 2786, 2330, 2786, 377, 378, 379, 380, 381, + 382, 2786, 2786, 1723, 2786, 2322, 2322, 2322, 2786, 1857, + 2329, 2331, 2334, 1858, 377, 378, 379, 380, 381, 382, + 1856, 1889, 2330, 2337, 2786, 1859, 1862, 466, 466, 466, + 466, 466, 466, 466, 466, 1890, 1891, 2786, 2786, 2786, + 2331, 2334, 1858, 377, 378, 379, 380, 381, 382, 1895, + 1889, 2786, 2337, 2786, 1859, 1894, 466, 466, 466, 466, + + 466, 466, 466, 466, 1890, 1891, 1898, 377, 378, 379, + 380, 381, 382, 2786, 2786, 2786, 2786, 1860, 1895, 1896, + 502, 377, 378, 379, 380, 381, 382, 502, 2188, 2188, + 2188, 1900, 2335, 502, 2323, 2336, 2338, 377, 378, 379, + 380, 381, 382, 1685, 1903, 1901, 2339, 2345, 1896, 2786, + 377, 378, 379, 380, 381, 382, 2786, 502, 2786, 2786, + 1900, 2335, 1902, 2346, 2336, 2338, 377, 378, 379, 380, + 381, 382, 2786, 1903, 1901, 2339, 2345, 473, 474, 475, + 476, 477, 478, 473, 474, 475, 476, 477, 478, 1904, + 2786, 502, 2346, 509, 510, 515, 512, 513, 514, 1906, + + 509, 510, 515, 512, 513, 514, 509, 510, 515, 512, + 513, 514, 502, 2786, 2193, 2193, 2193, 2189, 1904, 1927, + 2786, 2347, 2786, 1905, 2786, 2786, 2786, 2786, 1906, 1695, + 509, 510, 515, 512, 513, 514, 502, 2786, 2786, 2786, + 2786, 2786, 502, 2786, 2786, 2786, 2786, 1907, 1927, 1945, + 2347, 502, 1905, 1908, 700, 701, 702, 703, 704, 705, + 2786, 2786, 1909, 2786, 509, 510, 515, 512, 513, 514, + 660, 661, 662, 663, 664, 665, 1907, 2348, 1945, 1645, + 1487, 1487, 1908, 2786, 1792, 509, 510, 515, 512, 513, + 514, 1909, 1648, 1978, 1978, 1978, 660, 661, 662, 663, + + 664, 665, 2786, 2194, 1793, 2349, 2348, 2786, 2786, 509, + 510, 515, 512, 513, 514, 509, 510, 515, 512, 513, + 514, 2786, 1979, 2786, 509, 510, 515, 512, 513, 514, + 1645, 1487, 1487, 1793, 2349, 1792, 1645, 1487, 1487, 2786, + 1946, 1792, 2351, 1648, 2786, 1931, 1932, 1932, 2786, 1648, + 1792, 1979, 1939, 1932, 1932, 1793, 1947, 1940, 1797, 2358, + 2359, 1793, 2360, 2786, 2786, 1941, 2786, 2786, 1794, 1946, + 1793, 2351, 1928, 1645, 1487, 1487, 1949, 1942, 1792, 2786, + 2786, 2786, 1980, 2786, 1793, 1947, 1648, 2786, 2358, 2359, + 1793, 2360, 660, 661, 662, 663, 664, 665, 1793, 1793, + + 2786, 1928, 2097, 2097, 2097, 1949, 1942, 700, 701, 702, + 703, 704, 705, 2786, 1929, 2786, 1948, 1545, 2361, 1794, + 2362, 2364, 2325, 2325, 2325, 1794, 2786, 1793, 700, 701, + 702, 703, 704, 705, 1933, 1645, 1487, 1487, 2786, 2786, + 1792, 1943, 2166, 2166, 2166, 1948, 2786, 2361, 1648, 2362, + 2364, 1936, 1936, 2786, 2786, 1936, 2167, 1936, 1936, 1936, + 1793, 2032, 1794, 700, 701, 702, 703, 704, 705, 757, + 2374, 1952, 2786, 746, 747, 748, 749, 750, 751, 2786, + 2786, 759, 397, 2340, 1955, 2786, 2786, 2786, 2786, 1793, + 2786, 2098, 2786, 2341, 399, 2786, 2786, 2786, 2786, 2374, + + 1957, 1684, 912, 912, 912, 912, 912, 912, 912, 912, + 759, 2326, 2340, 1647, 1647, 1647, 1647, 1647, 1647, 1647, + 1647, 1647, 2341, 399, 1794, 1645, 1487, 1487, 2786, 1957, + 1792, 2168, 473, 474, 475, 476, 477, 478, 1648, 2786, + 2049, 2786, 746, 747, 748, 749, 750, 751, 2786, 2375, + 1793, 2786, 2376, 2378, 2786, 377, 378, 379, 380, 381, + 382, 377, 378, 379, 380, 381, 382, 2786, 2786, 2049, + 1958, 2379, 2786, 2786, 2786, 2332, 2332, 2332, 2375, 1793, + 2786, 2376, 2378, 660, 661, 662, 663, 664, 665, 1959, + 1694, 912, 912, 912, 912, 912, 912, 912, 912, 1958, + + 2379, 1960, 2786, 1645, 1935, 1935, 1935, 1935, 1935, 1935, + 1935, 1935, 2786, 2786, 1794, 1645, 1487, 1487, 1959, 2786, + 1792, 377, 378, 379, 380, 381, 382, 2786, 1648, 2786, + 1960, 1965, 1966, 660, 661, 662, 663, 664, 665, 2786, + 1793, 377, 378, 379, 380, 381, 382, 377, 378, 379, + 380, 381, 382, 377, 378, 379, 380, 381, 382, 2786, + 1965, 1966, 2786, 2786, 2333, 2786, 2212, 2212, 2212, 1793, + 2786, 2786, 2786, 2786, 2380, 377, 378, 379, 380, 381, + 382, 1723, 1967, 2786, 2786, 2786, 377, 378, 379, 380, + 381, 382, 1968, 1935, 1935, 1935, 1935, 1935, 1935, 1935, + + 1935, 1935, 2786, 2380, 1794, 1645, 1487, 1487, 2786, 2786, + 1792, 1967, 377, 378, 379, 380, 381, 382, 1648, 2786, + 2387, 1968, 2786, 2388, 2389, 2391, 2786, 1976, 2786, 2786, + 1793, 2786, 2382, 2382, 2382, 377, 378, 379, 380, 381, + 382, 1975, 2392, 377, 378, 379, 380, 381, 382, 2387, + 2786, 2786, 2388, 2389, 2391, 2213, 1976, 2786, 2786, 1793, + 1986, 466, 466, 466, 466, 466, 466, 466, 466, 2393, + 1975, 2392, 1981, 2786, 2786, 377, 378, 379, 380, 381, + 382, 2786, 2786, 1647, 1647, 1647, 1647, 1647, 1647, 1647, + 1647, 1647, 2786, 2034, 1794, 1645, 1487, 1487, 2393, 2786, + + 1792, 1981, 377, 378, 379, 380, 381, 382, 1648, 1988, + 1722, 912, 912, 912, 912, 912, 912, 912, 912, 2394, + 1793, 2383, 2034, 2786, 377, 378, 379, 380, 381, 382, + 377, 378, 379, 380, 381, 382, 2786, 2786, 1988, 2786, + 473, 474, 475, 476, 477, 478, 2786, 2786, 2394, 1793, + 2786, 757, 397, 2369, 2372, 377, 378, 379, 380, 381, + 382, 2786, 2025, 1095, 818, 377, 378, 379, 380, 381, + 382, 2786, 2786, 1936, 1936, 1936, 1936, 1936, 1936, 1936, + 1936, 1936, 2396, 2786, 1794, 1645, 1487, 1487, 2786, 2786, + 1792, 2025, 1095, 818, 2786, 2786, 2399, 2030, 1648, 1755, + + 912, 912, 912, 912, 912, 912, 912, 912, 2786, 2786, + 1793, 2396, 377, 378, 379, 380, 381, 382, 502, 377, + 378, 379, 380, 381, 382, 2399, 2030, 2786, 2033, 2786, + 2402, 2083, 2083, 2083, 502, 2786, 2255, 2255, 2255, 1793, + 502, 2188, 2188, 2188, 377, 378, 379, 380, 381, 382, + 2036, 1756, 2786, 2035, 2786, 2786, 1685, 2033, 502, 2402, + 2084, 2410, 2786, 1936, 1936, 1936, 1936, 1936, 1936, 1936, + 1936, 1936, 502, 2786, 1794, 1645, 1487, 1487, 2786, 2036, + 1792, 473, 474, 475, 476, 477, 478, 2786, 1648, 2084, + 2410, 509, 510, 515, 512, 513, 514, 2412, 2413, 2786, + + 1793, 2786, 502, 2786, 2786, 2786, 2786, 509, 510, 515, + 512, 513, 514, 509, 510, 515, 512, 513, 514, 502, + 2085, 2786, 2037, 2068, 2786, 2256, 2412, 2413, 502, 1793, + 2189, 509, 510, 515, 512, 513, 514, 2038, 502, 700, + 701, 702, 703, 704, 705, 509, 510, 515, 512, 513, + 514, 2037, 2068, 1937, 1937, 1937, 1937, 1937, 1937, 1937, + 1937, 1937, 2416, 2786, 1794, 2786, 2038, 2786, 2786, 660, + 661, 662, 663, 664, 665, 509, 510, 515, 512, 513, + 514, 2384, 2384, 2384, 2786, 1645, 1487, 1487, 2786, 2786, + 1792, 2416, 509, 510, 515, 512, 513, 514, 1648, 2786, + + 2786, 509, 510, 515, 512, 513, 514, 2050, 2786, 2786, + 1793, 509, 510, 515, 512, 513, 514, 1645, 1487, 1487, + 2786, 2786, 1792, 2786, 2053, 1932, 1932, 2786, 2067, 2054, + 1648, 2786, 2786, 1939, 1932, 1932, 2050, 2055, 1940, 1793, + 2417, 2786, 1793, 1645, 1487, 1487, 1941, 2418, 1792, 2056, + 2060, 1487, 1487, 2419, 2420, 1940, 1648, 2067, 1942, 2421, + 1939, 1932, 1932, 1941, 2786, 1940, 2786, 2422, 1793, 2417, + 2385, 1793, 2423, 1941, 1794, 1942, 2418, 2786, 2056, 2090, + 2090, 2090, 2419, 2420, 2786, 1942, 2786, 1942, 2421, 660, + 661, 662, 663, 664, 665, 1645, 2422, 1793, 2070, 2786, + + 2424, 2423, 2425, 2786, 1942, 2786, 1794, 2426, 2091, 2786, + 2786, 2786, 2427, 2057, 1942, 2062, 1487, 1487, 2786, 2428, + 2054, 2058, 1943, 2786, 2786, 2786, 2786, 2070, 2055, 2424, + 2786, 2425, 1794, 1645, 1487, 1487, 2426, 2091, 1792, 2061, + 2056, 2427, 2060, 1487, 1487, 2069, 1648, 1940, 2428, 1943, + 2429, 2071, 2060, 1487, 1487, 2064, 2430, 1940, 1793, 700, + 701, 702, 703, 704, 705, 1941, 2786, 1942, 2092, 2056, + 2060, 1487, 1487, 2786, 2069, 1940, 2437, 1942, 2786, 2429, + 2071, 2786, 2786, 1941, 2786, 2430, 2786, 1793, 700, 701, + 702, 703, 704, 705, 2065, 1942, 1942, 700, 701, 702, + + 703, 704, 705, 2438, 2063, 2437, 1942, 2152, 757, 2439, + 2074, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, + 759, 2786, 1794, 2065, 1942, 397, 2786, 2077, 2786, 2441, + 2786, 2061, 2438, 1978, 1978, 1978, 2152, 399, 2439, 2786, + 2786, 2061, 2786, 2786, 2786, 2450, 2786, 2451, 2066, 759, + 2786, 377, 378, 379, 380, 381, 382, 2786, 2441, 2061, + 2079, 2786, 1979, 2786, 2456, 2457, 399, 2462, 473, 474, + 475, 476, 477, 478, 2450, 2081, 2451, 2080, 2786, 2463, + 2464, 746, 747, 748, 749, 750, 751, 2151, 2786, 2079, + 2087, 1979, 2786, 2456, 2457, 2786, 2462, 2786, 377, 378, + + 379, 380, 381, 382, 2081, 2786, 2080, 2786, 2463, 2464, + 2786, 2786, 377, 378, 379, 380, 381, 382, 2086, 2087, + 2786, 2096, 1980, 377, 378, 379, 380, 381, 382, 2786, + 377, 378, 379, 380, 381, 382, 377, 378, 379, 380, + 381, 382, 2786, 2465, 2473, 2088, 2786, 2086, 2786, 2786, + 2096, 377, 378, 379, 380, 381, 382, 2786, 473, 474, + 475, 476, 477, 478, 2786, 377, 378, 379, 380, 381, + 382, 2095, 2465, 2473, 2088, 2786, 2786, 2786, 377, 378, + 379, 380, 381, 382, 377, 378, 379, 380, 381, 382, + 2786, 2786, 2786, 377, 378, 379, 380, 381, 382, 2145, + + 2095, 1850, 912, 912, 912, 912, 912, 912, 912, 912, + 2112, 2112, 2112, 2147, 2147, 2147, 2786, 2153, 2786, 377, + 378, 379, 380, 381, 382, 2786, 2786, 2786, 2145, 2786, + 377, 378, 379, 380, 381, 382, 2786, 2786, 2476, 2113, + 502, 2478, 2148, 2479, 2480, 2786, 2153, 502, 2786, 2786, + 377, 378, 379, 380, 381, 382, 2170, 502, 2155, 2313, + 2313, 2313, 2786, 2786, 2786, 502, 2154, 2476, 2113, 2156, + 2478, 2148, 2479, 2480, 473, 474, 475, 476, 477, 478, + 2481, 2482, 2193, 2193, 2193, 2170, 2786, 2155, 2786, 377, + 378, 379, 380, 381, 382, 2154, 2786, 1695, 2156, 2114, + + 2157, 2786, 2149, 660, 661, 662, 663, 664, 665, 2481, + 2482, 2786, 2786, 509, 510, 515, 512, 513, 514, 2786, + 509, 510, 515, 512, 513, 514, 2315, 2315, 2315, 2485, + 509, 510, 515, 512, 513, 514, 2786, 2786, 509, 510, + 515, 512, 513, 514, 1645, 1487, 1487, 2483, 2314, 1792, + 2062, 1487, 1487, 2786, 2486, 2054, 2484, 1648, 2485, 2053, + 1932, 1932, 2786, 2055, 2054, 2062, 1487, 1487, 2786, 1793, + 2054, 2194, 2055, 2487, 2488, 2056, 2483, 2171, 2055, 2786, + 2062, 1487, 1487, 2486, 2056, 2054, 2062, 1487, 1487, 2786, + 2056, 2054, 2786, 2172, 2786, 2062, 1487, 1487, 1793, 2055, + + 2054, 2489, 2487, 2488, 2056, 2056, 2171, 2490, 2055, 2493, + 2786, 2056, 2786, 2056, 2494, 2316, 1645, 1487, 1487, 2056, + 2056, 1792, 2060, 1487, 1487, 2786, 2495, 1940, 2173, 1648, + 2489, 2786, 2496, 1794, 2056, 1941, 2490, 2786, 2493, 2063, + 2056, 1793, 2786, 2494, 757, 2497, 2445, 1942, 2057, 2056, + 2786, 2298, 2298, 2298, 2063, 2495, 1095, 2173, 2060, 1487, + 1487, 2496, 2786, 1940, 2786, 2786, 1851, 2786, 2498, 2063, + 1793, 1941, 2499, 2174, 2497, 2063, 1942, 2062, 1487, 1487, + 2786, 2786, 2054, 1942, 2063, 1095, 397, 2786, 2448, 2786, + 2055, 2062, 1487, 1487, 1931, 2786, 2054, 2498, 818, 2786, + + 2786, 2499, 2056, 2178, 2055, 1794, 2507, 2786, 1939, 1932, + 1932, 2061, 1942, 1940, 2491, 2492, 2056, 2060, 1487, 1487, + 2786, 2064, 1940, 2786, 2060, 1487, 1487, 818, 2786, 1940, + 1941, 2056, 2178, 1942, 2179, 2507, 2175, 1941, 2508, 2177, + 2299, 2180, 1942, 2491, 2492, 2056, 757, 2061, 2183, 1942, + 2786, 660, 661, 662, 663, 664, 665, 2786, 759, 2083, + 2083, 2083, 1942, 2179, 2786, 2786, 2063, 2508, 2177, 2176, + 2180, 1942, 377, 378, 379, 380, 381, 382, 1942, 2786, + 2063, 700, 701, 702, 703, 704, 705, 759, 2084, 700, + 701, 702, 703, 704, 705, 2786, 397, 1943, 2186, 2212, + + 2212, 2212, 1939, 2786, 2786, 2786, 2061, 2786, 399, 2786, + 2786, 2786, 2786, 2061, 1723, 2786, 2509, 2084, 2510, 746, + 747, 748, 749, 750, 751, 2786, 2786, 2400, 2400, 2400, + 377, 378, 379, 380, 381, 382, 2786, 399, 377, 378, + 379, 380, 381, 382, 2786, 2509, 2511, 2510, 2085, 2255, + 2255, 2255, 377, 378, 379, 380, 381, 382, 2520, 2786, + 2192, 2786, 2521, 2199, 1756, 2090, 2090, 2090, 2786, 377, + 378, 379, 380, 381, 382, 2511, 377, 378, 379, 380, + 381, 382, 2452, 2452, 2452, 2786, 2200, 2520, 2213, 2192, + 2260, 2521, 2199, 2786, 2091, 2205, 2205, 2205, 2112, 2112, + + 2112, 2786, 2134, 2134, 2134, 2454, 2454, 2454, 2786, 377, + 378, 379, 380, 381, 382, 2200, 2401, 377, 378, 379, + 380, 381, 382, 2091, 2206, 2786, 2234, 2113, 2524, 2235, + 2262, 2786, 377, 378, 379, 380, 381, 382, 2256, 2786, + 2382, 2382, 2382, 2236, 2525, 2786, 2147, 2147, 2147, 2786, + 2466, 2466, 2466, 2206, 2092, 2234, 2113, 2524, 2235, 2262, + 2254, 473, 474, 475, 476, 477, 478, 2526, 2529, 2786, + 2786, 2453, 2236, 2525, 502, 2148, 2530, 473, 474, 475, + 476, 477, 478, 502, 2207, 2786, 2786, 2114, 2786, 2254, + 2261, 2135, 2242, 502, 2455, 2786, 2526, 2529, 2243, 502, + + 2786, 2263, 2244, 2245, 2148, 2530, 2786, 2246, 2247, 2248, + 2786, 2249, 377, 378, 379, 380, 381, 382, 2786, 2261, + 2786, 2242, 2270, 2270, 2270, 2264, 2531, 2243, 2786, 2383, + 2263, 2244, 2245, 2533, 2786, 2149, 2246, 2247, 2248, 2467, + 2249, 473, 474, 475, 476, 477, 478, 509, 510, 515, + 512, 513, 514, 2539, 2264, 2531, 509, 510, 515, 512, + 513, 514, 2533, 2271, 2786, 2786, 509, 510, 515, 512, + 513, 514, 509, 510, 515, 512, 513, 514, 1645, 1487, + 1487, 2540, 2539, 1792, 2053, 1932, 1932, 2543, 2786, 2054, + 2786, 1648, 2271, 2062, 1487, 1487, 2786, 2172, 2054, 2062, + + 1487, 1487, 2786, 1793, 2054, 2544, 2055, 2786, 2786, 2056, + 2540, 2272, 2055, 2545, 2546, 2275, 2543, 757, 2056, 2281, + 2060, 1487, 1487, 2547, 2056, 1940, 2062, 1487, 1487, 759, + 2786, 2054, 1793, 1941, 2544, 2060, 1487, 1487, 2056, 2055, + 1940, 2786, 2545, 2546, 2275, 1942, 2786, 2056, 1941, 2548, + 2786, 2056, 2547, 2056, 2549, 2786, 2550, 2551, 759, 397, + 1942, 2284, 2786, 2786, 2786, 2786, 2786, 1794, 2276, 2786, + 2277, 399, 2786, 2057, 1942, 2786, 2552, 2053, 2548, 2278, + 2056, 2553, 2063, 2549, 2786, 2550, 2551, 2786, 2063, 1942, + 746, 747, 748, 749, 750, 751, 2786, 2276, 2060, 2277, + + 399, 2294, 2289, 2786, 2062, 2552, 2786, 2786, 2278, 2061, + 2553, 2786, 2786, 2786, 2786, 2063, 660, 661, 662, 663, + 664, 665, 2786, 2353, 2061, 700, 701, 702, 703, 704, + 705, 2289, 377, 378, 379, 380, 381, 382, 2295, 377, + 378, 379, 380, 381, 382, 2205, 2205, 2205, 377, 378, + 379, 380, 381, 382, 2786, 2786, 2342, 377, 378, 379, + 380, 381, 382, 2354, 2343, 502, 2786, 2295, 2786, 2786, + 2786, 2344, 2355, 2356, 2206, 502, 2298, 2298, 2298, 377, + 378, 379, 380, 381, 382, 2342, 2366, 2357, 2554, 2786, + 2786, 1851, 2354, 2343, 473, 474, 475, 476, 477, 478, + + 2344, 2355, 2356, 2206, 2786, 2474, 2474, 2474, 473, 474, + 475, 476, 477, 478, 2786, 2786, 2357, 2554, 473, 474, + 475, 476, 477, 478, 660, 661, 662, 663, 664, 665, + 2786, 2062, 1487, 1487, 2207, 2367, 2054, 2555, 509, 510, + 515, 512, 513, 514, 2055, 2400, 2400, 2400, 509, 510, + 515, 512, 513, 514, 2433, 2786, 2056, 2060, 1487, 1487, + 2556, 2786, 1940, 2557, 2365, 2299, 2555, 757, 2786, 2370, + 1941, 2786, 2786, 700, 701, 702, 703, 704, 705, 759, + 2786, 2558, 1942, 2433, 397, 2056, 2373, 2377, 2786, 2556, + 2786, 2786, 2557, 2365, 2475, 2786, 399, 2786, 2559, 2786, + + 473, 474, 475, 476, 477, 478, 2381, 2786, 759, 2432, + 2558, 1942, 2469, 2469, 2469, 2786, 2377, 2320, 2320, 2320, + 2063, 2786, 2500, 2500, 2500, 399, 2470, 2559, 377, 378, + 379, 380, 381, 382, 2401, 2381, 2332, 2332, 2332, 2786, + 746, 747, 748, 749, 750, 751, 2061, 2325, 2325, 2325, + 2403, 2786, 2322, 2322, 2322, 2786, 2786, 377, 378, 379, + 380, 381, 382, 377, 378, 379, 380, 381, 382, 2434, + 377, 378, 379, 380, 381, 382, 2414, 2786, 2405, 2403, + 473, 474, 475, 476, 477, 478, 502, 2786, 2408, 2062, + 1487, 1487, 2406, 502, 2054, 2442, 2786, 2560, 2434, 2786, + + 2561, 2471, 2055, 2786, 2786, 2414, 2321, 2405, 757, 2786, + 2446, 2501, 2786, 2435, 2056, 2443, 2786, 2408, 2436, 2562, + 759, 2406, 2569, 2786, 2442, 2333, 2560, 2786, 2503, 2561, + 473, 474, 475, 476, 477, 478, 2326, 2786, 397, 2786, + 2449, 2323, 2435, 2056, 2443, 2786, 2786, 2436, 2562, 759, + 399, 2569, 660, 661, 662, 663, 664, 665, 2786, 509, + 510, 515, 512, 513, 514, 2786, 509, 510, 515, 512, + 513, 514, 700, 701, 702, 703, 704, 705, 2063, 399, + 2786, 746, 747, 748, 749, 750, 751, 2786, 2504, 377, + 378, 379, 380, 381, 382, 2384, 2384, 2384, 2458, 473, + + 474, 475, 476, 477, 478, 473, 474, 475, 476, 477, + 478, 377, 378, 379, 380, 381, 382, 2504, 502, 2786, + 2786, 2570, 2571, 2512, 502, 2578, 2579, 2458, 2460, 2452, + 2452, 2452, 2454, 2454, 2454, 2786, 757, 2786, 2515, 2786, + 473, 474, 475, 476, 477, 478, 2505, 2513, 1095, 2786, + 2570, 2571, 2512, 2506, 2578, 2579, 2786, 2460, 2786, 2786, + 377, 378, 379, 380, 381, 382, 757, 397, 2516, 2518, + 2527, 2527, 2527, 2786, 2580, 2505, 2513, 1095, 759, 818, + 2786, 2786, 2506, 2786, 2385, 660, 661, 662, 663, 664, + 665, 509, 510, 515, 512, 513, 514, 509, 510, 515, + + 512, 513, 514, 2580, 397, 2786, 2519, 759, 818, 700, + 701, 702, 703, 704, 705, 2786, 399, 2565, 2453, 2786, + 2786, 2455, 377, 378, 379, 380, 381, 382, 2466, 2466, + 2466, 2566, 2469, 2469, 2469, 2534, 2534, 2534, 2581, 746, + 747, 748, 749, 750, 751, 399, 2470, 2474, 2474, 2474, + 2500, 2500, 2500, 2786, 2527, 2527, 2527, 502, 2786, 2528, + 2566, 660, 661, 662, 663, 664, 665, 2581, 2786, 2786, + 2786, 2535, 502, 757, 2582, 2573, 2536, 377, 378, 379, + 380, 381, 382, 2567, 2568, 1095, 2587, 2541, 473, 474, + 475, 476, 477, 478, 473, 474, 475, 476, 477, 478, + + 2535, 2786, 2786, 2582, 2786, 2536, 700, 701, 702, 703, + 704, 705, 2567, 2568, 1095, 2587, 2541, 2467, 2534, 2534, + 2534, 2471, 2588, 2786, 2537, 757, 397, 2574, 2576, 2589, + 509, 510, 515, 512, 513, 514, 2475, 759, 818, 2501, + 397, 2590, 2577, 2528, 2592, 509, 510, 515, 512, 513, + 514, 2588, 399, 2593, 2535, 2594, 2595, 2596, 2589, 2536, + 2597, 2598, 2599, 2600, 2601, 2602, 759, 818, 2603, 2613, + 2590, 2786, 2786, 2592, 2786, 2604, 2605, 2606, 502, 2607, + 2608, 399, 2593, 2535, 2594, 2595, 2596, 2786, 2536, 2597, + 2598, 2599, 2600, 2601, 2602, 2609, 2610, 2603, 746, 747, + + 748, 749, 750, 751, 2604, 2605, 2606, 2537, 2607, 2608, + 2611, 2786, 502, 377, 378, 379, 380, 381, 382, 2614, + 2616, 2617, 2786, 2786, 2609, 2610, 757, 2786, 2619, 2624, + 2641, 2641, 2641, 2786, 757, 2786, 2620, 2615, 1095, 2611, + 473, 474, 475, 476, 477, 478, 759, 2625, 2614, 2616, + 2617, 509, 510, 515, 512, 513, 514, 397, 2624, 2622, + 473, 474, 475, 476, 477, 478, 2615, 1095, 2626, 818, + 2627, 2628, 397, 2629, 2623, 759, 2625, 2633, 473, 474, + 475, 476, 477, 478, 399, 509, 510, 515, 512, 513, + 514, 2634, 2637, 2638, 2639, 2640, 2643, 2626, 818, 2627, + + 2628, 2644, 2629, 2645, 2646, 2647, 2633, 746, 747, 748, + 749, 750, 751, 399, 2648, 2649, 2654, 2786, 2786, 2642, + 2634, 2637, 2638, 2639, 2640, 2643, 2650, 2651, 2652, 502, + 2644, 2655, 2645, 2646, 2647, 2662, 2663, 2664, 2786, 757, + 757, 2657, 2658, 2648, 2649, 377, 378, 379, 380, 381, + 382, 1095, 759, 2666, 2667, 2650, 2651, 2652, 2786, 397, + 2655, 2660, 2786, 2786, 2662, 2663, 2664, 397, 2668, 2661, + 2669, 818, 2670, 2672, 2672, 2672, 2641, 2641, 2641, 399, + 1095, 759, 2666, 2667, 2641, 2641, 2641, 473, 474, 475, + 476, 477, 478, 2671, 2674, 2676, 2677, 2668, 2678, 2669, + + 818, 2670, 509, 510, 515, 512, 513, 514, 399, 2679, + 2680, 2786, 2786, 746, 747, 748, 749, 750, 751, 2681, + 2682, 2691, 2671, 2674, 2676, 2677, 2692, 2678, 473, 474, + 475, 476, 477, 478, 757, 757, 2686, 2687, 2679, 2680, + 377, 378, 379, 380, 381, 382, 1095, 759, 2681, 2682, + 2691, 397, 397, 2689, 2690, 2692, 2693, 2694, 2695, 2696, + 2699, 2702, 2673, 818, 399, 2642, 2672, 2672, 2672, 2700, + 2700, 2700, 2703, 2642, 2704, 1095, 759, 2786, 2786, 757, + 2786, 2706, 2786, 2786, 2786, 2693, 2694, 2695, 2696, 2699, + 2702, 1095, 818, 399, 757, 397, 2707, 2709, 2786, 2786, + + 2786, 2703, 397, 2704, 2690, 2710, 759, 818, 746, 747, + 748, 749, 750, 751, 399, 2711, 2712, 2713, 2714, 2715, + 1095, 2716, 2719, 2720, 2721, 377, 378, 379, 380, 381, + 382, 2724, 2786, 2729, 2710, 759, 818, 2700, 2700, 2700, + 2786, 2786, 2786, 399, 2711, 2712, 2713, 2714, 2715, 2786, + 2716, 2719, 2720, 2721, 757, 2673, 2723, 2730, 2701, 2786, + 2724, 757, 2729, 2707, 2717, 2786, 1095, 746, 747, 748, + 749, 750, 751, 759, 2731, 377, 378, 379, 380, 381, + 382, 2732, 397, 2733, 2709, 2734, 2730, 2735, 2725, 2725, + 2725, 2736, 2742, 2717, 818, 1095, 2726, 2786, 2745, 757, + + 2746, 2723, 759, 2731, 2747, 2725, 2725, 2725, 2786, 2786, + 2732, 1095, 2733, 2726, 2734, 2748, 2735, 2749, 2751, 2752, + 2736, 2742, 2753, 818, 2754, 2755, 2701, 2745, 2758, 2746, + 2756, 2756, 2756, 2747, 746, 747, 748, 749, 750, 751, + 1095, 2759, 2760, 2761, 2748, 2766, 2749, 2751, 2752, 2767, + 2786, 2753, 2768, 2754, 2755, 2769, 2771, 2758, 2762, 2762, + 2762, 2756, 2756, 2756, 2762, 2762, 2762, 2786, 2772, 2773, + 2759, 2760, 2761, 2786, 2766, 2774, 2775, 2727, 2767, 2728, + 2776, 2768, 2777, 2778, 2769, 2771, 2762, 2762, 2762, 2641, + 2641, 2641, 2779, 2780, 2727, 2781, 2728, 2772, 2773, 2782, + + 2783, 2784, 2764, 2785, 2774, 2775, 2762, 2762, 2762, 2776, + 2786, 2777, 2778, 2786, 2786, 2786, 2786, 2786, 2786, 2757, + 2786, 2779, 2780, 2786, 2781, 2786, 2786, 2786, 2782, 2783, + 2784, 2764, 2785, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2763, 2786, 2786, + 2757, 2786, 2786, 2763, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2763, 2786, 2786, 2642, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2763, 125, 125, 125, 125, + + 125, 125, 125, 125, 125, 125, 125, 125, 181, 181, + 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, + 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, + 189, 189, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 217, 217, 217, 217, 217, 217, + 217, 217, 217, 217, 217, 217, 226, 226, 226, 226, + 226, 226, 226, 226, 226, 226, 226, 226, 233, 233, + 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 239, 239, 239, 239, 239, 239, 239, 239, + + 239, 239, 239, 239, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 244, 244, 244, 244, + 244, 244, 244, 244, 244, 244, 244, 244, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 270, 270, 312, 312, 312, 312, 312, 312, 312, 312, + 312, 312, 312, 312, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 361, 361, + 361, 369, 369, 2786, 369, 369, 369, 369, 369, 369, + + 369, 369, 369, 376, 376, 383, 383, 383, 456, 456, + 2786, 2786, 2786, 2786, 2786, 456, 472, 472, 500, 500, + 2786, 500, 500, 2786, 500, 500, 538, 538, 538, 545, + 545, 552, 552, 552, 564, 564, 2786, 2786, 2786, 2786, + 2786, 564, 580, 2786, 580, 601, 2786, 601, 625, 625, + 625, 625, 625, 625, 2786, 625, 625, 625, 2786, 625, + 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, + 631, 631, 632, 632, 632, 632, 632, 632, 2786, 632, + 632, 632, 2786, 632, 638, 638, 638, 638, 638, 638, + 638, 638, 638, 638, 638, 638, 644, 644, 644, 644, + + 644, 644, 644, 644, 644, 644, 644, 644, 645, 645, + 645, 645, 645, 645, 645, 645, 645, 645, 645, 647, + 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, + 652, 652, 2786, 652, 652, 652, 652, 652, 652, 652, + 652, 652, 659, 659, 684, 684, 2786, 684, 684, 684, + 684, 684, 684, 684, 684, 684, 692, 692, 2786, 692, + 692, 692, 692, 692, 692, 692, 692, 692, 699, 699, + 718, 718, 738, 738, 2786, 738, 738, 738, 738, 738, + 738, 738, 738, 738, 745, 745, 772, 772, 2786, 772, + 772, 772, 772, 772, 772, 772, 772, 772, 779, 779, + + 2786, 779, 779, 779, 779, 779, 779, 779, 779, 779, + 361, 361, 361, 368, 368, 2786, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 369, 369, 2786, 369, 369, + 369, 369, 369, 369, 369, 369, 369, 376, 376, 383, + 383, 383, 456, 456, 2786, 2786, 2786, 2786, 2786, 456, + 472, 472, 500, 500, 2786, 500, 500, 2786, 500, 500, + 538, 538, 538, 545, 545, 552, 552, 552, 564, 564, + 2786, 2786, 2786, 2786, 2786, 564, 580, 2786, 580, 601, + 2786, 601, 625, 625, 625, 625, 625, 625, 2786, 625, + 625, 625, 2786, 625, 1010, 1010, 2786, 1010, 1010, 1010, + + 1010, 1010, 1010, 1010, 1010, 1010, 632, 632, 632, 632, + 632, 632, 2786, 632, 632, 632, 2786, 632, 1015, 1015, + 2786, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1020, 1020, 2786, 1020, 1020, 1020, 1020, 1020, 1020, 1020, + 1020, 1020, 645, 645, 645, 645, 645, 645, 645, 645, + 645, 645, 645, 647, 647, 647, 647, 647, 647, 647, + 647, 647, 647, 647, 651, 651, 2786, 651, 651, 651, + 651, 651, 651, 651, 651, 651, 652, 652, 2786, 652, + 652, 652, 652, 652, 652, 652, 652, 652, 659, 659, + 684, 684, 2786, 684, 684, 684, 684, 684, 684, 684, + + 684, 684, 691, 691, 2786, 691, 691, 691, 691, 691, + 691, 691, 691, 691, 692, 692, 2786, 692, 692, 692, + 692, 692, 692, 692, 692, 692, 699, 699, 718, 718, + 737, 737, 2786, 737, 737, 737, 737, 737, 737, 737, + 737, 737, 738, 738, 2786, 738, 738, 738, 738, 738, + 738, 738, 738, 738, 745, 745, 772, 772, 2786, 772, + 772, 772, 772, 772, 772, 772, 772, 772, 779, 779, + 2786, 779, 779, 779, 779, 779, 779, 779, 779, 779, + 368, 368, 2786, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, + + 1129, 1129, 1129, 1129, 376, 376, 2786, 2786, 376, 472, + 472, 500, 500, 2786, 2786, 500, 545, 545, 580, 2786, + 580, 601, 2786, 601, 1010, 1010, 2786, 1010, 1010, 1010, + 1010, 1010, 1010, 1010, 1010, 1010, 1015, 1015, 2786, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1020, 1020, + 2786, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, + 651, 651, 2786, 651, 651, 651, 651, 651, 651, 651, + 651, 651, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, + 1283, 1283, 1283, 1283, 659, 659, 1295, 1295, 1295, 1295, + 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 691, 691, + + 2786, 691, 691, 691, 691, 691, 691, 691, 691, 691, + 1303, 1303, 1303, 1303, 1303, 1303, 1303, 1303, 1303, 1303, + 1303, 1303, 699, 699, 718, 718, 737, 737, 2786, 737, + 737, 737, 737, 737, 737, 737, 737, 737, 1316, 1316, + 1316, 1316, 1316, 1316, 1316, 1316, 1316, 1316, 1316, 1316, + 745, 745, 2786, 2786, 745, 1329, 1329, 1329, 1329, 1329, + 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1335, 1335, 1335, + 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 361, + 361, 361, 369, 369, 2786, 369, 369, 369, 369, 369, + 369, 369, 369, 369, 368, 368, 2786, 368, 368, 368, + + 368, 368, 368, 368, 368, 368, 383, 383, 383, 1129, + 1129, 2786, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, + 1129, 376, 376, 2786, 2786, 376, 456, 456, 2786, 2786, + 2786, 2786, 2786, 456, 472, 472, 500, 500, 2786, 2786, + 500, 500, 538, 538, 538, 552, 552, 552, 545, 545, + 564, 564, 2786, 2786, 2786, 2786, 2786, 564, 580, 2786, + 580, 601, 2786, 601, 1468, 1468, 1468, 1468, 1468, 1468, + 1468, 1468, 1468, 1468, 1468, 1468, 1473, 1473, 1473, 1473, + 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1478, 1478, + 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, + + 652, 652, 2786, 652, 652, 652, 652, 652, 652, 652, + 652, 652, 651, 651, 2786, 651, 651, 651, 651, 651, + 651, 651, 651, 651, 1283, 1283, 2786, 1283, 1283, 1283, + 1283, 1283, 1283, 1283, 1283, 1283, 659, 659, 1295, 1295, + 2786, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, + 692, 692, 2786, 692, 692, 692, 692, 692, 692, 692, + 692, 692, 691, 691, 2786, 691, 691, 691, 691, 691, + 691, 691, 691, 691, 1303, 1303, 2786, 1303, 1303, 1303, + 1303, 1303, 1303, 1303, 1303, 1303, 699, 699, 718, 718, + 738, 738, 2786, 738, 738, 738, 738, 738, 738, 738, + + 738, 738, 737, 737, 2786, 737, 737, 737, 737, 737, + 737, 737, 737, 737, 1316, 1316, 2786, 1316, 1316, 1316, + 1316, 1316, 1316, 1316, 1316, 1316, 745, 745, 2786, 2786, + 745, 1329, 1329, 2786, 1329, 1329, 1329, 1329, 1329, 1329, + 1329, 1329, 1329, 1335, 1335, 2786, 1335, 1335, 1335, 1335, + 1335, 1335, 1335, 1335, 1335, 1129, 1129, 2786, 1129, 1129, + 1129, 1129, 1129, 1129, 1129, 1129, 1129, 376, 376, 2786, + 2786, 376, 472, 472, 500, 500, 2786, 2786, 500, 545, + 545, 580, 2786, 580, 601, 2786, 601, 1468, 1468, 2786, + 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1473, + + 1473, 2786, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, + 1473, 1478, 1478, 2786, 1478, 1478, 1478, 1478, 1478, 1478, + 1478, 1478, 1478, 1283, 1283, 2786, 1283, 1283, 1283, 1283, + 1283, 1283, 1283, 1283, 1283, 659, 659, 1295, 1295, 2786, + 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1303, + 1303, 2786, 1303, 1303, 1303, 1303, 1303, 1303, 1303, 1303, + 1303, 699, 699, 1644, 1644, 1644, 1644, 1644, 1644, 1644, + 1644, 1644, 1644, 1644, 1644, 1843, 1843, 1843, 1843, 1843, + 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1938, 1938, 1938, + 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1962, + + 1962, 1962, 1962, 1962, 1962, 1962, 1962, 1962, 1962, 1962, + 1962, 1970, 1970, 1970, 1970, 1970, 1970, 1970, 1970, 1970, + 1970, 1970, 1970, 1993, 1993, 1993, 1993, 1993, 1993, 1993, + 1993, 1993, 1993, 1993, 1993, 2027, 2027, 2027, 2027, 2027, + 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2052, 2052, 2052, + 2052, 2052, 2052, 2052, 2052, 2052, 2052, 2052, 2052, 2104, + 2104, 2104, 2104, 2104, 2104, 2104, 2104, 2104, 2104, 2104, + 2104, 59, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786 } ; -static yyconst flex_int16_t yy_chk[6271] = +static yyconst flex_int16_t yy_chk[17967] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -1833,8 +3360,8 @@ static yyconst flex_int16_t yy_chk[6271] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, @@ -1843,9 +3370,9 @@ static yyconst flex_int16_t yy_chk[6271] = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 5, 6, 63, 63, 65, 66, - 66, 65, 65, 5, 6, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 5, 6, + 66, 66, 66, 66, 66, 66, 2770, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, @@ -1854,111 +3381,111 @@ static yyconst flex_int16_t yy_chk[6271] = 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 11, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 13, 13, 13, 27, - 14, 14, 14, 13, 28, 29, 13, 14, 13, 30, - 14, 31, 14, 15, 15, 15, 32, 16, 16, 16, - 15, 39, 40, 15, 16, 15, 76, 16, 47, 16, - 48, 100, 2182, 79, 2180, 68, 100, 68, 68, 71, - 81, 27, 82, 71, 39, 40, 28, 29, 68, 85, - - 73, 30, 2178, 72, 73, 76, 31, 70, 47, 70, - 48, 32, 79, 73, 70, 70, 70, 72, 71, 81, - 72, 82, 71, 39, 40, 101, 101, 68, 85, 73, - 13, 13, 72, 73, 14, 14, 70, 47, 70, 48, - 102, 102, 73, 70, 70, 70, 72, 15, 15, 72, - 2177, 16, 16, 19, 19, 19, 19, 19, 19, 19, + 11, 13, 13, 13, 27, 14, 14, 14, 13, 28, + 29, 13, 14, 13, 30, 14, 31, 14, 15, 15, + + 15, 32, 16, 16, 16, 15, 39, 40, 15, 16, + 15, 110, 16, 47, 16, 48, 110, 71, 71, 57, + 71, 85, 99, 134, 139, 27, 2765, 57, 39, 40, + 28, 29, 127, 2763, 132, 30, 57, 127, 58, 132, + 31, 2757, 47, 2750, 48, 32, 58, 2741, 57, 153, + 85, 2740, 134, 139, 153, 58, 57, 39, 40, 99, + 99, 99, 99, 99, 99, 57, 2739, 58, 624, 624, + 13, 47, 13, 48, 14, 58, 14, 2731, 85, 85, + 85, 85, 85, 85, 58, 168, 2730, 15, 2728, 15, + 168, 16, 2727, 16, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 21, 21, 21, 22, 22, 22, 280, 280, 21, 90, - 112, 22, 23, 23, 23, 112, 2174, 23, 2172, 23, - 92, 23, 23, 24, 24, 24, 2171, 103, 24, 104, - 24, 74, 24, 24, 25, 25, 25, 74, 90, 25, - 105, 25, 25, 25, 25, 26, 26, 26, 75, 92, - 26, 75, 26, 26, 26, 26, 103, 77, 104, 2168, - - 74, 77, 80, 117, 106, 77, 74, 2159, 117, 105, - 80, 78, 86, 107, 78, 84, 80, 75, 283, 283, - 75, 78, 86, 84, 21, 21, 77, 22, 22, 2155, - 77, 80, 84, 106, 77, 84, 23, 23, 108, 80, - 78, 86, 107, 78, 84, 80, 2152, 24, 24, 133, - 78, 86, 84, 2149, 133, 142, 2145, 159, 25, 25, - 142, 84, 159, 167, 84, 311, 311, 108, 167, 26, - 26, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 19, 19, 19, 19, 19, 19, 19, 19, 21, 21, + 21, 22, 22, 22, 688, 688, 21, 174, 2724, 22, + + 23, 23, 23, 67, 2722, 23, 2718, 23, 82, 23, + 23, 24, 24, 24, 1703, 1703, 24, 175, 24, 80, + 24, 24, 25, 25, 25, 80, 174, 25, 2708, 25, + 25, 25, 25, 26, 26, 26, 176, 82, 26, 2705, + 26, 26, 26, 26, 87, 177, 175, 136, 80, 78, + 185, 2701, 136, 2698, 80, 185, 82, 82, 82, 82, + 82, 82, 2688, 78, 2685, 176, 78, 80, 80, 80, + 80, 80, 80, 87, 177, 207, 136, 21, 78, 21, + 22, 136, 22, 67, 67, 67, 67, 67, 67, 23, + 2675, 23, 78, 193, 202, 78, 223, 2673, 193, 202, + + 24, 223, 24, 2671, 207, 87, 87, 87, 87, 87, + 87, 25, 2665, 25, 78, 78, 78, 78, 78, 78, + 323, 323, 26, 323, 26, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, 41, 41, - 41, 2143, 41, 41, 134, 41, 41, 41, 42, 42, - 42, 41, 42, 42, 83, 42, 42, 42, 83, 87, - 2142, 42, 87, 135, 88, 148, 83, 89, 87, 89, - 83, 88, 89, 134, 87, 149, 150, 91, 151, 41, - - 180, 88, 2139, 83, 91, 91, 181, 83, 87, 42, - 2130, 87, 135, 88, 148, 83, 89, 87, 89, 83, - 88, 89, 230, 87, 149, 150, 91, 151, 41, 180, - 88, 176, 196, 91, 91, 181, 176, 196, 42, 203, - 2126, 379, 41, 41, 203, 282, 379, 2123, 282, 282, - 2120, 230, 42, 42, 43, 43, 43, 43, 43, 43, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 41, + 41, 41, 2659, 41, 41, 2585, 41, 41, 41, 42, + 42, 42, 41, 42, 42, 230, 42, 42, 42, 74, + 230, 74, 42, 141, 91, 137, 81, 199, 199, 81, + 94, 74, 81, 137, 138, 141, 208, 94, 94, 41, + 108, 108, 108, 108, 108, 108, 269, 94, 138, 42, + 94, 2656, 141, 91, 137, 81, 199, 199, 81, 94, + 74, 81, 137, 138, 141, 208, 94, 94, 41, 91, + 91, 91, 91, 91, 91, 269, 94, 138, 42, 94, + + 81, 81, 81, 81, 81, 81, 479, 2585, 41, 2655, + 41, 479, 74, 74, 74, 74, 74, 74, 42, 2653, + 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 45, 45, 45, 45, 45, 45, 45, 232, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 381, 381, - 45, 45, 45, 45, 45, 382, 382, 173, 173, 2090, - 45, 55, 55, 55, 56, 56, 56, 232, 233, 182, - 2085, 116, 116, 116, 182, 234, 2074, 119, 119, 119, - 239, 45, 116, 45, 116, 116, 173, 173, 119, 45, - - 119, 119, 389, 389, 121, 121, 121, 233, 182, 220, - 220, 220, 653, 182, 234, 121, 653, 121, 121, 239, - 45, 45, 45, 45, 45, 45, 45, 45, 46, 46, - 46, 46, 46, 46, 46, 121, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 183, 249, 46, 46, 46, - 46, 46, 262, 263, 264, 55, 152, 46, 56, 2066, - 152, 270, 183, 231, 121, 116, 231, 272, 288, 152, - 289, 119, 290, 152, 183, 249, 300, 301, 46, 390, - 46, 262, 263, 264, 390, 152, 46, 2065, 121, 152, - 270, 183, 231, 220, 2064, 231, 272, 288, 152, 289, - - 2057, 290, 152, 471, 471, 300, 301, 46, 46, 46, - 46, 46, 46, 46, 46, 49, 49, 49, 49, 49, + 43, 43, 43, 43, 43, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + + 45, 45, 45, 45, 45, 45, 45, 45, 45, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, @@ -1968,552 +3495,1839 @@ static yyconst flex_int16_t yy_chk[6271] = 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 51, 51, 51, 313, 313, 51, 2056, 52, - 52, 52, 319, 321, 52, 51, 313, 322, 118, 118, - 118, 51, 52, 2054, 323, 221, 221, 221, 52, 118, - 51, 118, 118, 241, 241, 241, 324, 52, 122, 122, - 122, 319, 321, 2053, 118, 313, 322, 51, 325, 122, - 1949, 122, 122, 323, 52, 327, 124, 124, 124, 51, - 2050, 284, 655, 284, 284, 324, 52, 124, 329, 124, - 124, 1908, 122, 118, 284, 330, 51, 325, 123, 123, - 123, 847, 124, 52, 327, 847, 51, 517, 517, 123, - 331, 123, 123, 52, 114, 114, 114, 329, 655, 315, - - 315, 122, 118, 284, 330, 114, 2031, 114, 114, 221, - 315, 124, 527, 527, 125, 125, 125, 241, 123, 331, - 114, 114, 122, 114, 332, 125, 1949, 125, 125, 242, - 242, 242, 114, 403, 114, 332, 114, 125, 403, 315, - 124, 253, 253, 253, 126, 126, 126, 123, 1908, 114, - 114, 2016, 114, 332, 317, 126, 317, 126, 126, 317, - 317, 114, 123, 114, 332, 114, 125, 254, 254, 254, - 207, 207, 207, 333, 2014, 207, 2012, 207, 114, 115, - 115, 115, 126, 207, 210, 210, 210, 535, 535, 210, - 115, 210, 115, 115, 377, 377, 377, 210, 125, 213, - - 213, 213, 333, 213, 213, 115, 115, 316, 115, 316, - 316, 126, 213, 242, 274, 274, 274, 115, 335, 115, - 316, 115, 275, 275, 275, 253, 559, 559, 126, 295, - 295, 295, 335, 336, 115, 115, 2006, 115, 296, 296, - 296, 303, 303, 303, 318, 337, 115, 335, 115, 316, - 115, 254, 318, 422, 207, 312, 312, 312, 422, 326, - 326, 335, 336, 115, 127, 127, 127, 326, 210, 2001, - 328, 1992, 338, 318, 337, 127, 339, 127, 127, 328, - 340, 318, 334, 213, 1982, 334, 328, 127, 326, 326, - 342, 127, 343, 1981, 345, 344, 326, 344, 274, 328, - - 127, 338, 341, 346, 127, 339, 275, 347, 328, 340, - 1955, 334, 348, 295, 334, 328, 127, 341, 341, 342, - 127, 343, 296, 345, 344, 303, 344, 349, 350, 127, - 351, 341, 346, 127, 352, 353, 347, 354, 355, 312, - 356, 348, 358, 360, 356, 361, 341, 341, 127, 362, - 359, 358, 363, 358, 364, 357, 349, 350, 359, 351, - 357, 366, 1954, 352, 353, 365, 354, 355, 357, 356, - 357, 358, 360, 356, 361, 370, 357, 371, 362, 359, - 358, 363, 358, 364, 357, 365, 372, 359, 367, 357, - 366, 367, 368, 383, 365, 369, 368, 357, 384, 357, - - 385, 369, 386, 387, 370, 357, 371, 388, 429, 560, - 560, 424, 1953, 429, 365, 372, 425, 367, 441, 1950, - 367, 368, 383, 441, 369, 368, 1947, 384, 1938, 385, - 369, 386, 387, 393, 393, 393, 388, 392, 392, 392, - 424, 394, 394, 394, 393, 425, 393, 393, 392, 431, - 392, 392, 394, 432, 394, 394, 396, 396, 396, 2052, - 397, 397, 397, 392, 392, 1936, 392, 396, 1920, 396, - 396, 397, 1916, 397, 397, 392, 433, 392, 431, 392, - 445, 452, 432, 434, 1915, 445, 452, 396, 398, 398, - 398, 435, 392, 392, 397, 392, 399, 399, 399, 398, - - 436, 398, 398, 1910, 392, 433, 392, 399, 392, 399, - 399, 1907, 434, 405, 405, 405, 396, 393, 437, 399, - 435, 392, 1906, 397, 405, 394, 405, 405, 398, 436, - 438, 450, 400, 400, 400, 2052, 464, 405, 1902, 451, - 396, 464, 1901, 400, 397, 400, 400, 437, 399, 1889, - 406, 406, 406, 1870, 407, 454, 455, 398, 407, 438, - 450, 406, 1868, 406, 406, 410, 405, 407, 451, 410, - 400, 407, 398, 456, 457, 408, 408, 408, 410, 458, - 399, 459, 410, 407, 454, 455, 408, 407, 408, 408, - 468, 406, 502, 503, 410, 468, 407, 405, 410, 400, - - 407, 1864, 456, 457, 461, 461, 461, 410, 458, 504, - 459, 410, 408, 409, 409, 409, 400, 401, 401, 401, - 406, 502, 503, 505, 409, 1860, 409, 409, 401, 506, - 401, 401, 739, 739, 406, 411, 411, 411, 504, 1854, - 401, 408, 507, 1850, 401, 658, 411, 510, 411, 411, - 1848, 409, 505, 401, 412, 412, 412, 401, 506, 408, - 411, 413, 413, 413, 1844, 412, 415, 412, 412, 401, - 415, 507, 413, 401, 413, 413, 510, 1840, 412, 415, - 409, 658, 401, 415, 1815, 540, 401, 540, 515, 411, - 540, 540, 414, 414, 414, 415, 1812, 409, 1809, 415, - - 523, 401, 413, 414, 524, 414, 414, 412, 415, 473, - 473, 473, 415, 480, 480, 480, 473, 515, 1808, 411, - 480, 486, 486, 486, 501, 486, 496, 496, 496, 523, - 525, 413, 529, 524, 414, 500, 500, 500, 412, 511, - 511, 511, 501, 501, 530, 413, 514, 514, 514, 518, - 518, 518, 1805, 501, 522, 522, 522, 542, 543, 525, - 544, 529, 541, 414, 531, 531, 531, 536, 536, 536, - 852, 501, 501, 530, 537, 537, 414, 538, 538, 539, - 541, 539, 539, 551, 552, 537, 542, 543, 538, 544, - 1803, 541, 539, 473, 547, 547, 547, 480, 550, 550, - - 550, 554, 554, 554, 1797, 486, 852, 557, 557, 541, - 496, 562, 551, 552, 537, 563, 564, 538, 557, 500, - 556, 539, 556, 511, 565, 556, 556, 566, 567, 558, - 514, 558, 568, 518, 558, 558, 569, 570, 522, 571, - 562, 572, 570, 573, 563, 564, 574, 557, 531, 1796, - 574, 536, 575, 565, 576, 577, 566, 567, 578, 579, - 580, 568, 581, 583, 584, 569, 570, 585, 571, 586, - 572, 570, 573, 587, 588, 574, 590, 591, 547, 574, - 592, 575, 550, 576, 577, 554, 593, 578, 579, 580, - 594, 581, 583, 584, 595, 596, 585, 597, 586, 599, - - 600, 601, 587, 588, 602, 590, 591, 603, 604, 592, - 605, 606, 607, 608, 609, 593, 610, 611, 612, 594, - 613, 614, 615, 595, 596, 616, 597, 617, 599, 600, - 601, 619, 621, 602, 622, 624, 603, 604, 625, 605, - 606, 607, 608, 609, 1786, 610, 611, 612, 627, 613, - 614, 615, 629, 623, 616, 623, 617, 620, 620, 620, - 619, 621, 626, 622, 624, 630, 628, 625, 628, 631, - 632, 633, 634, 626, 635, 636, 637, 627, 641, 636, - 642, 629, 623, 643, 623, 644, 645, 646, 1785, 649, - 651, 626, 652, 660, 630, 628, 654, 628, 631, 632, - - 633, 634, 626, 635, 636, 637, 656, 641, 636, 642, - 650, 657, 643, 649, 644, 645, 646, 651, 659, 650, - 661, 652, 660, 662, 654, 663, 656, 664, 666, 659, - 667, 669, 675, 676, 677, 678, 679, 680, 681, 657, - 682, 620, 649, 695, 695, 695, 651, 1782, 650, 661, - 652, 709, 662, 654, 663, 656, 664, 666, 659, 667, - 669, 675, 676, 677, 678, 679, 680, 681, 657, 682, - 700, 700, 700, 705, 705, 705, 707, 707, 707, 710, - 709, 711, 712, 713, 714, 715, 716, 719, 720, 720, - 720, 722, 725, 725, 725, 727, 728, 732, 1776, 733, - - 734, 734, 734, 740, 740, 741, 742, 1775, 710, 743, - 711, 712, 713, 714, 715, 716, 719, 736, 744, 736, - 722, 745, 736, 736, 727, 728, 732, 695, 733, 737, - 737, 738, 749, 738, 741, 742, 738, 738, 743, 750, - 737, 747, 747, 747, 751, 751, 760, 744, 753, 753, - 745, 752, 752, 752, 700, 755, 755, 705, 756, 756, - 707, 749, 757, 757, 758, 758, 759, 759, 750, 737, - 761, 762, 720, 763, 764, 760, 725, 765, 767, 768, - 769, 770, 767, 771, 734, 772, 773, 774, 775, 778, - 779, 780, 781, 782, 783, 784, 882, 882, 785, 761, - - 762, 788, 763, 764, 789, 790, 765, 767, 768, 769, - 770, 767, 771, 795, 772, 773, 774, 775, 778, 779, - 780, 781, 782, 783, 784, 747, 753, 785, 796, 797, - 788, 798, 799, 789, 790, 752, 792, 792, 792, 800, - 802, 803, 795, 804, 804, 804, 805, 806, 807, 808, - 810, 811, 812, 813, 814, 815, 816, 796, 797, 817, - 798, 799, 820, 820, 820, 821, 822, 824, 800, 802, - 803, 825, 826, 827, 828, 805, 806, 807, 808, 810, - 811, 812, 813, 814, 815, 816, 829, 830, 817, 831, - 832, 1771, 834, 835, 821, 822, 824, 836, 854, 850, - - 825, 826, 827, 828, 837, 839, 841, 842, 843, 845, - 1770, 854, 848, 1761, 849, 829, 830, 1744, 831, 832, - 792, 834, 835, 850, 855, 1742, 836, 804, 818, 818, - 818, 853, 856, 837, 839, 841, 842, 843, 845, 848, - 854, 1737, 849, 857, 855, 859, 820, 860, 853, 856, - 818, 861, 850, 818, 818, 862, 857, 863, 864, 865, - 866, 867, 868, 870, 818, 818, 818, 871, 848, 873, - 818, 849, 874, 855, 859, 875, 860, 853, 856, 1018, - 861, 1735, 818, 818, 862, 857, 863, 864, 865, 866, - 867, 868, 870, 818, 818, 818, 871, 886, 873, 818, - - 887, 874, 884, 884, 875, 889, 876, 876, 876, 878, - 878, 878, 818, 876, 890, 1018, 878, 880, 880, 880, - 892, 880, 883, 883, 883, 894, 886, 895, 900, 887, - 1732, 891, 891, 891, 889, 905, 891, 896, 896, 897, - 897, 897, 907, 890, 891, 1727, 898, 898, 1726, 892, - 901, 901, 903, 903, 894, 919, 895, 900, 902, 902, - 902, 910, 910, 920, 905, 911, 911, 911, 912, 912, - 921, 907, 914, 914, 915, 915, 916, 916, 917, 917, - 884, 918, 918, 922, 919, 923, 924, 924, 926, 926, - 876, 929, 920, 878, 925, 925, 925, 930, 930, 921, - - 932, 880, 931, 931, 931, 933, 883, 936, 937, 938, - 939, 940, 922, 1723, 923, 891, 942, 1721, 943, 944, - 929, 945, 946, 897, 898, 947, 948, 949, 950, 932, - 903, 954, 955, 956, 933, 958, 936, 937, 938, 939, - 940, 961, 902, 963, 965, 942, 912, 943, 944, 911, - 945, 946, 1713, 966, 947, 948, 949, 950, 967, 969, - 954, 955, 956, 972, 958, 1710, 926, 959, 959, 959, - 961, 976, 963, 965, 977, 930, 1707, 978, 925, 964, - 964, 964, 966, 970, 970, 970, 931, 967, 969, 979, - 980, 981, 972, 982, 964, 983, 959, 984, 985, 986, - - 976, 987, 988, 977, 989, 959, 978, 990, 994, 997, - 999, 1000, 984, 1002, 1003, 1004, 1006, 1007, 979, 980, - 981, 970, 982, 1008, 983, 959, 1010, 985, 986, 1013, - 987, 988, 1014, 989, 959, 1025, 990, 994, 997, 999, - 1000, 984, 1002, 1003, 1004, 1006, 1007, 1016, 1020, 1021, - 970, 959, 1008, 1019, 1017, 1010, 1022, 1027, 1013, 1028, - 1020, 1014, 1023, 964, 1025, 1704, 1024, 970, 992, 992, - 992, 1017, 1019, 1703, 1023, 1016, 1030, 1699, 1032, 1022, - 1242, 1242, 1033, 1035, 1698, 1021, 1027, 1037, 1028, 1020, - 1038, 1039, 1058, 992, 992, 992, 1059, 992, 1287, 1695, - - 1017, 1019, 1024, 1023, 1016, 1030, 992, 1032, 1022, 992, - 992, 1033, 1035, 992, 1052, 1052, 1037, 1052, 1691, 1038, - 1039, 1058, 992, 992, 992, 1059, 992, 1042, 1042, 1043, - 1043, 1043, 1345, 1042, 1287, 992, 1043, 1345, 992, 992, - 1044, 1044, 992, 1045, 1045, 1690, 1044, 1047, 1047, 1045, - 1057, 1057, 992, 1047, 1048, 1048, 1048, 1049, 1049, 1050, - 1050, 1048, 1060, 1049, 1061, 1050, 1053, 1053, 1053, 1679, - 1053, 1054, 1054, 1067, 1054, 1055, 1055, 1068, 1055, 1063, - 1063, 1063, 1677, 1069, 1063, 1064, 1064, 1064, 1071, 1071, - 1064, 1060, 1063, 1061, 1072, 1073, 1073, 1075, 1064, 1658, - - 1076, 1078, 1067, 1077, 1077, 1063, 1068, 1079, 1083, 1083, - 1080, 1064, 1069, 1043, 1081, 1082, 1085, 1085, 1085, 1087, - 1088, 1045, 1090, 1072, 1331, 1331, 1075, 1092, 1057, 1076, - 1078, 1093, 1095, 1096, 1063, 1098, 1079, 1050, 1048, 1080, - 1064, 1100, 1101, 1081, 1082, 1102, 1103, 1104, 1087, 1088, - 1053, 1090, 1656, 1055, 1085, 1106, 1092, 1097, 1097, 1097, - 1093, 1095, 1096, 1063, 1098, 1109, 1071, 1110, 1112, 1064, - 1100, 1101, 1097, 1073, 1102, 1103, 1104, 1108, 1108, 1108, - 1113, 1077, 1117, 1085, 1106, 1118, 1083, 1114, 1114, 1114, - 1120, 1121, 1108, 1123, 1109, 1124, 1110, 1112, 1126, 1128, - - 1085, 1129, 1114, 1130, 1133, 1134, 1131, 1131, 1131, 1113, - 1135, 1117, 1655, 1132, 1118, 1136, 1138, 1132, 1132, 1120, - 1121, 1131, 1123, 1140, 1124, 1141, 1142, 1126, 1128, 1143, - 1129, 1144, 1130, 1133, 1134, 1145, 1146, 1147, 1149, 1135, - 1151, 1097, 1132, 1152, 1136, 1138, 1132, 1132, 1154, 1154, - 1154, 1155, 1140, 1157, 1141, 1142, 1158, 1160, 1143, 1161, - 1144, 1108, 1163, 1154, 1145, 1146, 1147, 1149, 1164, 1151, - 1165, 1114, 1152, 1172, 1168, 1163, 1166, 1171, 1173, 1164, - 1155, 1174, 1157, 1169, 1175, 1158, 1160, 1165, 1161, 1166, - 1131, 1168, 1169, 1177, 1171, 1178, 1168, 1180, 1177, 1182, - - 1183, 1184, 1172, 1647, 1163, 1185, 1186, 1173, 1164, 1645, - 1174, 1187, 1187, 1175, 1190, 1191, 1165, 1187, 1166, 1192, - 1168, 1169, 1177, 1171, 1178, 1168, 1180, 1177, 1182, 1183, - 1184, 1193, 1154, 1194, 1185, 1186, 1188, 1188, 1189, 1189, - 1195, 1189, 1188, 1190, 1191, 1196, 1196, 1196, 1192, 1640, - 1196, 1197, 1197, 1197, 1205, 1635, 1197, 1386, 1196, 1206, - 1193, 1633, 1194, 1630, 1197, 1198, 1198, 1198, 1208, 1195, - 1198, 1196, 1202, 1202, 1202, 1209, 1628, 1197, 1198, 1199, - 1199, 1199, 1625, 1205, 1199, 1200, 1200, 1200, 1206, 1187, - 1200, 1198, 1199, 1386, 1210, 1211, 1212, 1208, 1200, 1623, - - 1196, 1619, 1213, 1215, 1209, 1199, 1197, 1216, 1219, 1221, - 1222, 1200, 1228, 1231, 1188, 1603, 1189, 1201, 1201, 1201, - 1198, 1232, 1201, 1210, 1211, 1212, 1233, 1593, 1200, 1196, - 1201, 1213, 1215, 1234, 1199, 1197, 1216, 1219, 1221, 1222, - 1200, 1228, 1231, 1201, 1225, 1225, 1225, 1238, 1239, 1198, - 1232, 1235, 1235, 1235, 1240, 1233, 1202, 1200, 1241, 1225, - 1246, 1247, 1234, 1199, 1251, 1253, 1235, 1592, 1257, 1200, - 1588, 1258, 1201, 1250, 1250, 1250, 1238, 1239, 1259, 1260, - 1261, 1571, 1262, 1240, 1254, 1254, 1254, 1241, 1250, 1246, - 1247, 1263, 1264, 1251, 1253, 1265, 1201, 1257, 1266, 1254, - - 1258, 1201, 1267, 1268, 1269, 1270, 1254, 1259, 1260, 1261, - 1254, 1262, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1562, - 1263, 1264, 1254, 1282, 1265, 1283, 1284, 1266, 1225, 1285, - 1286, 1267, 1268, 1269, 1270, 1235, 1289, 1294, 1295, 1254, - 1551, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1278, - 1278, 1254, 1282, 1288, 1283, 1284, 1286, 1250, 1285, 1290, - 1292, 1291, 1293, 1278, 1297, 1288, 1294, 1295, 1254, 1289, - 1291, 1290, 1292, 1298, 1293, 1299, 1300, 1301, 1302, 1303, - 1304, 1305, 1306, 1307, 1308, 1286, 1309, 1310, 1311, 1312, - 1318, 1338, 1338, 1297, 1288, 1319, 1344, 1344, 1289, 1291, - - 1290, 1292, 1298, 1293, 1299, 1300, 1301, 1302, 1303, 1304, - 1305, 1306, 1307, 1308, 1549, 1309, 1310, 1311, 1312, 1318, - 1313, 1313, 1313, 1543, 1319, 1313, 1314, 1314, 1314, 1320, - 1321, 1314, 1278, 1313, 1322, 1315, 1315, 1315, 1323, 1314, - 1315, 1324, 1316, 1316, 1316, 1325, 1313, 1316, 1315, 1314, - 1327, 1328, 1314, 1329, 1330, 1316, 1334, 1335, 1320, 1321, - 1336, 1315, 1337, 1322, 1340, 1341, 1342, 1323, 1316, 1343, - 1324, 1346, 1346, 1346, 1325, 1313, 1347, 1348, 1314, 1327, - 1328, 1314, 1329, 1330, 1353, 1334, 1335, 1354, 1355, 1336, - 1315, 1337, 1356, 1340, 1341, 1342, 1360, 1316, 1343, 1357, - - 1357, 1346, 1362, 1364, 1313, 1347, 1348, 1349, 1349, 1349, - 1314, 1363, 1365, 1353, 1315, 1366, 1354, 1355, 1367, 1315, - 1368, 1356, 1349, 1369, 1370, 1360, 1316, 1371, 1372, 1363, - 1346, 1362, 1364, 1373, 1374, 1375, 1376, 1378, 1380, 1380, - 1363, 1365, 1382, 1384, 1366, 1385, 1396, 1367, 1391, 1368, - 1387, 1399, 1369, 1370, 1373, 1346, 1371, 1372, 1363, 1403, - 1406, 1407, 1373, 1374, 1375, 1376, 1378, 1387, 1408, 1391, - 1409, 1382, 1384, 1410, 1385, 1396, 1411, 1412, 1436, 1436, - 1399, 1424, 1425, 1373, 1443, 1443, 1536, 1426, 1403, 1406, - 1407, 1349, 1427, 1456, 1456, 1437, 1387, 1408, 1391, 1409, - - 1437, 1503, 1410, 1428, 1457, 1411, 1412, 1413, 1413, 1413, - 1424, 1425, 1413, 1414, 1414, 1414, 1426, 1453, 1414, 1423, - 1413, 1427, 1415, 1415, 1415, 1429, 1414, 1415, 1405, 1416, - 1416, 1416, 1428, 1413, 1416, 1415, 1430, 1431, 1432, 1414, - 1434, 1395, 1416, 1393, 1417, 1417, 1417, 1444, 1415, 1417, - 1392, 1435, 1444, 1463, 1429, 1416, 1390, 1417, 1463, 1418, - 1418, 1418, 1413, 1416, 1418, 1430, 1431, 1432, 1414, 1434, - 1417, 1389, 1418, 1440, 1419, 1419, 1419, 1415, 1388, 1419, - 1435, 1420, 1420, 1420, 1416, 1418, 1420, 1419, 1441, 1462, - 1462, 1413, 1416, 1442, 1420, 1446, 1381, 1414, 1361, 1417, - - 1419, 1415, 1440, 1438, 1438, 1438, 1415, 1420, 1447, 1445, - 1445, 1445, 1448, 1416, 1418, 1359, 1449, 1441, 1421, 1421, - 1421, 1358, 1442, 1421, 1446, 1422, 1422, 1422, 1417, 1419, - 1422, 1421, 1351, 1438, 1350, 1452, 1420, 1447, 1422, 1445, - 1455, 1448, 1459, 1418, 1421, 1449, 1460, 1461, 1450, 1450, - 1450, 1422, 1451, 1451, 1451, 1464, 1464, 1464, 1419, 1465, - 1466, 1421, 1438, 1450, 1452, 1420, 1467, 1468, 1445, 1455, - 1469, 1459, 1470, 1421, 1471, 1460, 1461, 1472, 1472, 1472, - 1422, 1473, 1451, 1474, 1475, 1464, 1476, 1438, 1465, 1466, - 1421, 1477, 1478, 1445, 1479, 1467, 1468, 1480, 1481, 1469, - - 1482, 1470, 1421, 1471, 1422, 1483, 1484, 1339, 1485, 1422, - 1473, 1451, 1474, 1475, 1464, 1476, 1486, 1486, 1490, 1487, - 1477, 1478, 1491, 1479, 1487, 1492, 1480, 1481, 1495, 1482, - 1496, 1493, 1450, 1494, 1483, 1484, 1451, 1485, 1497, 1464, - 1488, 1488, 1488, 1493, 1498, 1499, 1494, 1490, 1500, 1501, - 1504, 1491, 1492, 1505, 1502, 1502, 1502, 1495, 1522, 1496, - 1332, 1472, 1553, 1553, 1524, 1525, 1554, 1497, 1502, 1527, - 1488, 1554, 1493, 1498, 1499, 1494, 1317, 1500, 1501, 1504, - 1529, 1492, 1505, 1530, 1507, 1507, 1507, 1522, 1535, 1507, - 1508, 1508, 1508, 1524, 1525, 1508, 1296, 1507, 1527, 1488, - - 1509, 1509, 1509, 1508, 1280, 1509, 1510, 1510, 1510, 1529, - 1507, 1510, 1530, 1509, 1539, 1542, 1508, 1535, 1279, 1510, - 1511, 1511, 1511, 1256, 1488, 1511, 1509, 1528, 1528, 1528, - 1255, 1243, 1510, 1511, 1570, 1570, 1570, 1237, 1502, 1507, - 1544, 1528, 1545, 1539, 1542, 1508, 1511, 1512, 1512, 1512, - 1236, 1227, 1512, 1226, 1217, 1509, 1203, 1513, 1513, 1513, - 1512, 1510, 1513, 1511, 1533, 1533, 1533, 1170, 1507, 1544, - 1513, 1545, 1546, 1512, 1508, 1511, 1540, 1540, 1540, 1533, - 1514, 1514, 1514, 1513, 1509, 1514, 1167, 1534, 1534, 1534, - 1510, 1540, 1511, 1514, 1515, 1515, 1515, 1148, 1139, 1515, - - 1547, 1546, 1512, 1550, 1511, 1137, 1514, 1515, 1516, 1516, - 1516, 1528, 1513, 1516, 1517, 1517, 1517, 1534, 1570, 1517, - 1515, 1516, 1556, 1548, 1548, 1548, 1512, 1517, 1122, 1547, - 1116, 1512, 1550, 1115, 1516, 1514, 1513, 1111, 1548, 1086, - 1517, 1513, 1518, 1518, 1518, 1074, 1534, 1518, 1533, 1515, - 1557, 1556, 1066, 1065, 1062, 1518, 1056, 1519, 1519, 1519, - 1540, 1051, 1519, 1516, 1514, 1541, 1541, 1541, 1518, 1517, - 1519, 1534, 1558, 1046, 1555, 1555, 1555, 1040, 1515, 1557, - 1520, 1520, 1520, 1519, 1561, 1520, 1036, 1516, 1034, 1521, - 1521, 1521, 1516, 1520, 1521, 1541, 1563, 1518, 1517, 1564, - - 1565, 1558, 1521, 1520, 1555, 1566, 1520, 1548, 1559, 1559, - 1559, 1567, 1519, 1561, 1568, 1521, 1560, 1560, 1560, 1569, - 1031, 1518, 1572, 1559, 1541, 1563, 1518, 1573, 1564, 1565, - 1574, 1575, 1520, 1555, 1566, 1520, 1576, 1577, 1578, 1029, - 1567, 1519, 1579, 1568, 1521, 1581, 1560, 1582, 1569, 1541, - 1583, 1572, 1584, 1012, 993, 991, 1573, 971, 1555, 1574, - 1575, 1587, 1589, 960, 1520, 1576, 1577, 1578, 1521, 1590, - 1594, 1579, 953, 1521, 1581, 1560, 1582, 1591, 951, 1583, - 1597, 1584, 1585, 1585, 1585, 1586, 1586, 1586, 927, 913, - 1587, 1589, 1559, 1598, 1600, 906, 904, 1585, 1590, 1594, - - 1560, 1580, 1653, 1653, 1653, 1591, 1604, 1580, 1613, 1597, - 1615, 1580, 1580, 1616, 1621, 1586, 1580, 1580, 1580, 1624, - 1580, 899, 1598, 1600, 1601, 1601, 1601, 893, 888, 1621, - 1580, 1602, 1602, 1602, 1591, 1604, 1580, 1613, 1601, 1615, - 1580, 1580, 1616, 1621, 1586, 1580, 1580, 1580, 1624, 1580, - 1605, 1605, 1605, 885, 1602, 1607, 1607, 1607, 1621, 881, - 1607, 879, 1608, 1608, 1608, 877, 1585, 1608, 1607, 1586, - 1605, 872, 858, 1602, 844, 1608, 819, 1609, 1609, 1609, - 1626, 1607, 1609, 1602, 1629, 1608, 1653, 1631, 1608, 793, - 1609, 787, 1610, 1610, 1610, 754, 748, 1610, 1632, 1611, - - 1611, 1611, 1602, 1609, 1611, 1610, 1634, 735, 1601, 1626, - 1607, 1636, 1611, 1629, 1608, 1602, 1631, 1608, 1610, 1617, - 1617, 1617, 1618, 1618, 1618, 1611, 1639, 1632, 1620, 1620, - 1620, 729, 1609, 1617, 1605, 1634, 1612, 1612, 1612, 1607, - 1636, 1612, 1622, 1622, 1622, 1618, 1608, 1610, 1620, 1612, - 1627, 1627, 1627, 1641, 1611, 1639, 1609, 1622, 1637, 1637, - 1637, 1609, 1612, 1642, 1643, 1627, 1638, 1638, 1638, 1646, - 1612, 1610, 1648, 1637, 1618, 1649, 1610, 726, 1611, 1644, - 1644, 1644, 1641, 1611, 1650, 1651, 1652, 1654, 1654, 1654, - 1657, 1612, 1642, 1643, 1644, 1660, 1638, 721, 1646, 1612, - - 1661, 1648, 1662, 1617, 1649, 717, 1618, 1659, 1659, 1659, - 1663, 1665, 1620, 1650, 1651, 1652, 1666, 1667, 1668, 1657, - 1612, 708, 1670, 1671, 1660, 1638, 1622, 1664, 1668, 1661, - 1664, 1662, 1672, 1669, 1627, 1674, 1678, 1680, 1681, 1663, - 1665, 1669, 1637, 1683, 1685, 1666, 1667, 1668, 1669, 1682, - 1638, 1670, 1671, 1676, 1676, 1676, 1664, 1668, 1682, 1664, - 1686, 1672, 1669, 1644, 1674, 1678, 1680, 1681, 1676, 1688, - 1669, 1654, 1683, 1685, 1687, 1687, 1687, 1669, 1689, 1692, - 1693, 1693, 1693, 1694, 1694, 1694, 706, 1682, 1700, 1686, - 704, 1659, 1702, 1705, 1705, 1705, 1708, 1687, 1688, 1694, - - 1693, 1697, 1697, 1697, 1709, 1711, 1697, 1689, 1692, 1712, - 1696, 1696, 1696, 1705, 1697, 1696, 1687, 1700, 1701, 1701, - 1701, 1702, 1714, 1696, 1715, 1708, 1687, 1697, 1716, 703, - 1706, 1706, 1706, 1709, 1711, 701, 1696, 1676, 1712, 1717, - 1722, 1701, 1724, 1725, 1696, 1687, 1706, 1719, 1719, 1719, - 1728, 1714, 1729, 1715, 1730, 1731, 1697, 1716, 1687, 1720, - 1720, 1720, 1733, 1738, 1693, 1696, 699, 1694, 1717, 1722, - 1701, 1724, 1725, 1696, 1720, 1740, 698, 1705, 696, 1728, - 1743, 1729, 1745, 1730, 1731, 1697, 1734, 1734, 1734, 1746, - 1747, 1733, 1738, 1748, 1696, 1736, 1736, 1736, 1739, 1739, - - 1739, 1749, 1701, 1750, 1740, 1741, 1741, 1741, 1751, 1743, - 1752, 1745, 1753, 1754, 1706, 1756, 1757, 1758, 1746, 1747, - 1759, 1762, 1748, 1763, 1764, 694, 1765, 1766, 693, 668, - 1749, 1719, 1750, 1769, 1772, 665, 618, 1751, 1778, 1752, - 1779, 1753, 1754, 1720, 1756, 1757, 1758, 1741, 598, 1759, - 1762, 555, 1763, 1764, 1765, 1781, 1766, 1768, 1768, 1768, - 553, 548, 1769, 1772, 1773, 1773, 1773, 1778, 1787, 1779, - 1734, 1788, 546, 1777, 1777, 1777, 1741, 1768, 1777, 1736, - 1773, 545, 1739, 1765, 1781, 1792, 1777, 1793, 1794, 1741, - 1780, 1780, 1780, 1783, 1783, 1783, 1798, 1787, 1799, 1777, - - 1788, 1789, 1789, 1789, 1791, 1791, 1791, 1800, 1801, 1783, - 1780, 1795, 1795, 1795, 1792, 1806, 1793, 1794, 1802, 1802, - 1802, 1804, 1804, 1804, 1810, 1798, 1813, 1799, 1777, 1807, - 1807, 1807, 1811, 1811, 1811, 1804, 1800, 1801, 1814, 1817, - 1816, 1768, 1818, 1819, 1806, 532, 1820, 1822, 1773, 1816, - 1821, 1821, 1823, 1810, 1825, 1813, 526, 1777, 1826, 519, - 1827, 1828, 1829, 1832, 1832, 1832, 516, 1814, 1817, 1816, - 1834, 1818, 1819, 512, 1780, 1820, 1822, 1783, 1835, 1821, - 1821, 1823, 1836, 1825, 509, 1789, 1837, 1826, 1791, 1827, - 1828, 1829, 1838, 1839, 1841, 1795, 1842, 1843, 1845, 1834, - - 1846, 1851, 1802, 1852, 508, 1804, 497, 1835, 1847, 1847, - 1847, 1836, 1856, 1807, 1857, 1837, 1811, 1849, 1849, 1849, - 1858, 1838, 1839, 1841, 1861, 1842, 1843, 1845, 1865, 1846, - 1851, 1866, 1852, 1855, 1855, 1855, 1835, 1859, 1859, 1859, - 1869, 1856, 1871, 1857, 1862, 1862, 1862, 1832, 1872, 1858, - 1874, 1875, 1876, 1861, 1863, 1863, 1863, 1865, 1862, 1877, - 1866, 1867, 1867, 1867, 1878, 1879, 1880, 490, 1882, 1869, - 1883, 1871, 489, 1891, 1884, 1885, 1887, 1872, 1890, 1874, - 1875, 1876, 1888, 1888, 1888, 1892, 1893, 1894, 1877, 1898, - 1899, 1863, 1847, 1878, 1879, 1880, 1863, 1882, 1900, 1883, - - 1891, 1849, 1867, 1884, 1885, 1887, 1903, 1890, 1904, 1905, - 1905, 1905, 1909, 1911, 1892, 1893, 1894, 1855, 1898, 1899, - 1863, 1859, 1913, 1914, 1917, 1863, 1918, 1900, 1862, 1891, - 1919, 1867, 1912, 1912, 1912, 1903, 1921, 1904, 1863, 1922, - 488, 1909, 1911, 1923, 1924, 1867, 1926, 1927, 1928, 1929, - 1930, 1913, 1914, 1917, 1931, 1918, 1932, 1934, 1937, 1919, - 1940, 1941, 1942, 1943, 484, 1921, 1888, 1944, 1922, 1912, - 1945, 1946, 1923, 1924, 1912, 1926, 1927, 1928, 1929, 1930, - 1948, 1951, 1952, 1931, 1956, 1932, 1934, 1937, 1957, 1940, - 1941, 1942, 1943, 1905, 1958, 1959, 1944, 1961, 1912, 1945, - - 1946, 1962, 1963, 1912, 1960, 1960, 1960, 1965, 1967, 1948, - 1951, 1952, 1969, 1956, 1970, 1972, 1912, 1957, 1973, 1974, - 1976, 1977, 1979, 1958, 1959, 1983, 1961, 1984, 1985, 1986, - 1962, 1963, 1987, 1988, 1990, 483, 1965, 1967, 1989, 1989, - 1989, 1969, 1994, 1970, 1972, 1995, 1997, 1973, 1974, 1976, - 1977, 1979, 1998, 2000, 1983, 2002, 1984, 1985, 1986, 481, - 2003, 1987, 1988, 1990, 1991, 1991, 1991, 2005, 2007, 2008, - 2009, 1994, 2010, 2015, 1995, 1997, 2011, 2011, 2011, 2017, - 2019, 1998, 2000, 2021, 2002, 2013, 2013, 2013, 1960, 2003, - 2022, 2023, 2025, 477, 2026, 2027, 2005, 2007, 2008, 2009, - - 2028, 2010, 2015, 2029, 2030, 2032, 2033, 2034, 2017, 2019, - 2035, 2036, 2021, 2037, 2038, 2079, 2079, 2079, 2040, 2022, - 2023, 2025, 1989, 2026, 2027, 2041, 2042, 2043, 2044, 2028, - 2045, 476, 2029, 2030, 2032, 2033, 2034, 2048, 2055, 2035, - 2036, 474, 2037, 2038, 2039, 2039, 2039, 2040, 1991, 2058, - 2059, 2061, 2039, 470, 2041, 2042, 2043, 2044, 2062, 2045, - 2011, 2047, 2047, 2047, 2067, 2068, 2048, 2055, 2069, 2013, - 2049, 2049, 2049, 2070, 2051, 2051, 2051, 2071, 2058, 2059, - 2061, 2047, 2051, 2073, 2075, 2076, 2077, 2062, 2080, 2081, - 2049, 2082, 2083, 2067, 2068, 2086, 2088, 2069, 2089, 2079, - - 467, 2092, 2070, 2084, 2084, 2084, 2071, 2087, 2087, 2087, - 2094, 2095, 2073, 2075, 2076, 2077, 466, 2080, 2081, 2096, - 2082, 2083, 2097, 2098, 2086, 2088, 2099, 2089, 2039, 2039, - 2092, 2093, 2093, 2093, 2100, 2100, 2100, 463, 462, 2094, - 2095, 460, 448, 447, 444, 2047, 443, 440, 2096, 439, - 426, 2097, 2098, 420, 2049, 2099, 418, 416, 2051, 2051, - 402, 376, 374, 309, 306, 304, 302, 298, 293, 292, - 287, 266, 265, 261, 251, 250, 248, 237, 236, 229, - 227, 218, 216, 205, 204, 198, 197, 2084, 189, 188, - 185, 2087, 184, 169, 168, 162, 161, 154, 153, 136, - - 132, 130, 128, 109, 95, 94, 93, 67, 61, 58, - 53, 36, 35, 34, 33, 2093, 0, 0, 2100, 2102, - 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2103, - 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2104, - 2104, 2104, 2104, 2104, 2104, 2104, 2104, 2104, 2104, 2105, - 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2106, - 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2107, - 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2108, - 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2109, - 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2110, - - 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2111, - 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2112, - 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2113, - 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2114, - 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2115, - 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2116, - 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2117, - 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2118, - 2118, 2119, 2119, 0, 2119, 2119, 2119, 2119, 2119, 2119, - 2119, 2121, 2121, 2122, 0, 0, 0, 0, 2122, 2124, - - 2124, 0, 2124, 0, 2124, 2124, 2125, 2125, 2127, 2127, - 2128, 0, 0, 0, 0, 2128, 2129, 0, 2129, 2131, - 2131, 2131, 2131, 2131, 0, 2131, 2131, 0, 2131, 2132, - 2132, 2132, 2132, 2132, 2132, 2132, 2132, 2132, 2132, 2133, - 2133, 2133, 2133, 2133, 0, 2133, 2133, 0, 2133, 2134, - 2134, 2134, 2134, 2134, 2134, 2134, 2134, 2134, 2134, 2135, - 2135, 2135, 2135, 2135, 2135, 2135, 2135, 2135, 2135, 2136, - 2136, 2136, 2136, 2136, 2136, 2136, 2136, 2136, 2137, 2137, - 2137, 2137, 2137, 2137, 2137, 2137, 2137, 2138, 2138, 0, - 2138, 2138, 2138, 2138, 2138, 2138, 2138, 2140, 2140, 0, - - 2140, 2140, 2140, 2140, 2140, 2140, 2140, 2141, 2141, 0, - 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2144, 2144, 0, - 2144, 2144, 2144, 2144, 2144, 2144, 2144, 2146, 2146, 0, - 2146, 2146, 2146, 2146, 2146, 2146, 2146, 2147, 2147, 2148, - 2148, 0, 2148, 2148, 2148, 2148, 2148, 2148, 2148, 2150, - 2150, 2151, 0, 0, 0, 0, 2151, 2153, 2153, 0, - 2153, 0, 2153, 2153, 2154, 2154, 2156, 2156, 2157, 0, - 0, 0, 0, 2157, 2158, 0, 2158, 2160, 2160, 2160, - 2160, 2160, 0, 2160, 2160, 0, 2160, 2161, 2161, 0, - 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2162, 2162, 2162, - - 2162, 2162, 0, 2162, 2162, 0, 2162, 2163, 2163, 0, - 2163, 2163, 2163, 2163, 2163, 2163, 2163, 2164, 2164, 0, - 2164, 2164, 2164, 2164, 2164, 2164, 2164, 2165, 2165, 2165, - 2165, 2165, 2165, 2165, 2165, 2165, 2166, 2166, 2166, 2166, - 2166, 2166, 2166, 2166, 2166, 2167, 2167, 0, 2167, 2167, - 2167, 2167, 2167, 2167, 2167, 2169, 2169, 0, 2169, 2169, - 2169, 2169, 2169, 2169, 2169, 2170, 2170, 0, 2170, 2170, - 2170, 2170, 2170, 2170, 2170, 2173, 2173, 0, 2173, 2173, - 2173, 2173, 2173, 2173, 2173, 2175, 2175, 0, 2175, 2175, - 2175, 2175, 2175, 2175, 2175, 2176, 2176, 2176, 2176, 2176, - - 2176, 2176, 2176, 2176, 2176, 2179, 0, 0, 2179, 2181, - 0, 2181, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, - 2183, 2183, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2185, 2185, 2185, 2185, 2185, 2185, 2185, 2185, - 2185, 2185, 2186, 2186, 2186, 2186, 2186, 2186, 2186, 2186, - 2186, 2186, 2187, 2187, 2187, 2187, 2187, 2187, 2187, 2187, - 2187, 2187, 2188, 2188, 2188, 2188, 2188, 2188, 2188, 2188, - 2188, 2188, 2189, 2189, 2189, 2189, 2189, 2189, 2189, 2189, - 2189, 2189, 2190, 2190, 2190, 2190, 2190, 2190, 2190, 2190, - 2190, 2190, 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191, - - 2191, 2191, 2192, 2192, 2192, 2192, 2192, 2192, 2192, 2192, - 2192, 2192, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, - 2193, 2193, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, - 2194, 2194, 2195, 2195, 2195, 2195, 2195, 2195, 2195, 2195, - 2195, 2195, 2196, 2196, 2196, 2196, 2196, 2196, 2196, 2196, - 2196, 2196, 2197, 2197, 2197, 2197, 2197, 2197, 2197, 2197, - 2197, 2197, 2198, 2198, 2198, 2198, 2198, 2198, 2198, 2198, - 2198, 2198, 2199, 2199, 2199, 2199, 2199, 2199, 2199, 2199, - 2199, 2199, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, - 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101 + 49, 49, 49, 51, 51, 51, 279, 497, 51, 52, + 52, 52, 497, 2642, 52, 313, 51, 61, 61, 61, + 140, 51, 52, 140, 55, 55, 55, 52, 2632, 55, + 51, 62, 62, 62, 2631, 279, 52, 55, 98, 77, + 343, 64, 55, 77, 313, 516, 98, 51, 344, 140, + 516, 55, 140, 52, 2621, 98, 352, 55, 98, 51, + 353, 56, 56, 56, 355, 52, 56, 98, 77, 343, + 79, 2618, 77, 2612, 56, 98, 51, 344, 356, 56, + 55, 2591, 52, 79, 98, 352, 55, 98, 56, 353, + 357, 2590, 51, 355, 56, 247, 247, 247, 52, 79, + + 77, 77, 77, 77, 77, 77, 61, 356, 504, 583, + 83, 504, 79, 55, 83, 2589, 560, 56, 83, 357, + 62, 560, 2586, 56, 64, 64, 64, 64, 64, 64, + 1471, 79, 79, 79, 79, 79, 79, 504, 583, 83, + 504, 581, 394, 83, 394, 96, 581, 83, 1828, 1828, + 56, 65, 65, 88, 394, 65, 65, 584, 92, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 92, 65, + 65, 65, 65, 65, 96, 83, 83, 83, 83, 83, + 83, 2583, 88, 394, 247, 1481, 584, 92, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 92, 585, 2575, + + 65, 1471, 65, 2530, 88, 88, 88, 88, 88, 88, + 96, 96, 96, 96, 96, 96, 395, 2572, 397, 92, + 92, 92, 92, 92, 92, 1476, 395, 585, 397, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 76, 84, 76, 586, 84, + 86, 527, 76, 76, 76, 395, 84, 397, 86, 1481, + 2726, 150, 527, 588, 86, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 76, 84, 76, 586, 84, 86, + 527, 76, 76, 76, 2564, 84, 2530, 86, 248, 248, + 248, 527, 588, 86, 614, 614, 1476, 614, 2563, 76, + + 76, 76, 76, 76, 76, 210, 90, 1635, 84, 84, + 84, 84, 84, 84, 90, 86, 86, 86, 86, 86, + 86, 89, 210, 90, 507, 89, 90, 95, 506, 95, + 520, 507, 95, 89, 210, 90, 506, 89, 520, 271, + 271, 271, 2726, 90, 150, 150, 150, 150, 150, 150, + 89, 210, 90, 507, 89, 90, 95, 506, 95, 520, + 507, 95, 89, 593, 597, 506, 89, 520, 593, 597, + 589, 90, 90, 90, 90, 90, 90, 248, 1635, 95, + 95, 95, 95, 95, 95, 89, 89, 89, 89, 89, + 89, 93, 505, 209, 93, 97, 2542, 113, 209, 589, + + 93, 505, 97, 97, 518, 523, 93, 521, 590, 602, + 209, 518, 97, 521, 523, 97, 272, 272, 272, 2538, + 93, 505, 209, 93, 97, 112, 113, 209, 271, 93, + 505, 97, 97, 518, 523, 93, 521, 590, 602, 209, + 518, 97, 521, 523, 97, 113, 113, 113, 113, 113, + 113, 1636, 93, 93, 93, 93, 93, 93, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, + 103, 103, 103, 103, 103, 103, 104, 104, 104, 104, + 104, 104, 104, 104, 104, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 114, 115, 112, 112, 112, 112, + + 112, 112, 116, 603, 2537, 272, 117, 606, 118, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 1836, 1836, + 1843, 1843, 1636, 114, 115, 151, 151, 151, 151, 151, + 151, 116, 603, 604, 617, 117, 606, 118, 604, 617, + 115, 115, 115, 115, 115, 115, 114, 114, 114, 114, + 114, 114, 117, 117, 117, 117, 117, 117, 283, 283, + 283, 1861, 1861, 116, 116, 116, 116, 116, 116, 118, + 118, 118, 118, 118, 118, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 121, 121, 121, 121, 121, 121, + 121, 121, 121, 122, 122, 122, 122, 122, 122, 122, + + 122, 122, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 129, 129, 129, 621, 607, 156, 2532, 608, 621, 609, + 818, 129, 818, 129, 129, 818, 152, 1893, 1893, 1962, + 1962, 131, 131, 131, 522, 129, 129, 283, 129, 610, + 2529, 522, 131, 607, 131, 131, 608, 129, 609, 129, + 587, 129, 156, 156, 156, 156, 156, 156, 133, 133, + 133, 1970, 1970, 522, 129, 129, 587, 129, 610, 133, + 522, 133, 133, 1985, 1985, 2528, 129, 1637, 129, 587, + 129, 1993, 1993, 133, 143, 143, 143, 143, 143, 143, + + 143, 143, 143, 2027, 2027, 587, 154, 129, 129, 129, + 129, 129, 129, 130, 130, 130, 152, 152, 152, 152, + 152, 152, 133, 2523, 130, 2522, 130, 130, 131, 131, + 131, 131, 131, 131, 611, 154, 612, 257, 130, 130, + 257, 130, 251, 251, 251, 251, 251, 251, 667, 667, + 130, 155, 130, 2517, 130, 133, 133, 133, 133, 133, + 133, 1637, 2514, 611, 2502, 612, 257, 130, 130, 257, + 130, 154, 154, 154, 154, 154, 154, 667, 667, 130, + 155, 130, 142, 130, 519, 142, 142, 2501, 257, 257, + 257, 257, 257, 257, 519, 142, 681, 686, 734, 142, + + 130, 130, 130, 130, 130, 130, 2477, 819, 2475, 819, + 2471, 142, 819, 519, 142, 142, 155, 155, 155, 155, + 155, 155, 2467, 519, 142, 681, 686, 734, 142, 144, + 144, 144, 144, 144, 144, 144, 144, 144, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 159, 159, 159, 159, 159, 159, 159, 159, + + 159, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 162, + 162, 162, 162, 162, 162, 162, 162, 162, 178, 234, + 234, 234, 178, 756, 234, 2461, 234, 2104, 2104, 258, + 259, 178, 234, 756, 774, 178, 237, 237, 237, 1844, + 821, 237, 821, 237, 1844, 821, 775, 178, 781, 237, + 260, 178, 240, 240, 240, 2459, 240, 240, 258, 259, + 178, 2455, 756, 774, 178, 240, 262, 262, 262, 262, + 262, 262, 262, 262, 262, 775, 1963, 781, 782, 260, + 2453, 1963, 2447, 258, 258, 258, 258, 258, 258, 287, + + 287, 287, 287, 287, 287, 259, 259, 259, 259, 259, + 259, 260, 260, 260, 260, 260, 260, 782, 234, 263, + 263, 263, 263, 263, 263, 263, 263, 263, 284, 284, + 284, 2444, 2431, 2415, 2409, 237, 264, 264, 264, 264, + 264, 264, 264, 264, 264, 302, 302, 302, 302, 302, + 302, 240, 250, 250, 1971, 2407, 250, 250, 2404, 1971, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 292, + 250, 250, 250, 250, 250, 265, 265, 265, 265, 265, + 265, 265, 265, 265, 266, 266, 266, 266, 266, 266, + 266, 266, 266, 315, 315, 315, 2401, 784, 292, 785, + + 786, 250, 2398, 250, 267, 267, 267, 267, 267, 267, + 267, 267, 267, 1095, 2397, 1095, 2394, 284, 1095, 293, + 292, 292, 292, 292, 292, 292, 784, 2392, 785, 786, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 286, 286, 293, 294, + 286, 286, 977, 757, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 757, 286, 286, 286, 286, 286, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 294, 2386, + 2385, 977, 315, 2383, 293, 293, 293, 293, 293, 293, + 2371, 1096, 757, 1096, 1994, 286, 1096, 286, 2368, 1994, + + 294, 294, 294, 294, 294, 294, 296, 296, 296, 296, + 296, 296, 296, 296, 296, 297, 297, 297, 297, 297, + 297, 297, 297, 297, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 298, 298, 298, 298, 298, 298, 298, 298, 298, 299, + 299, 299, 299, 299, 299, 299, 299, 299, 300, 300, + 300, 300, 300, 300, 300, 300, 300, 305, 306, 306, + 306, 306, 306, 306, 306, 306, 306, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 2363, 305, 309, 309, 309, + + 309, 309, 309, 309, 309, 309, 310, 310, 310, 310, + 310, 310, 310, 310, 310, 305, 305, 305, 305, 305, + 305, 311, 311, 311, 311, 311, 311, 311, 311, 311, + 316, 316, 316, 319, 319, 319, 319, 319, 319, 325, + 328, 325, 329, 2362, 2352, 2350, 2333, 2328, 338, 338, + 338, 325, 331, 331, 331, 331, 331, 331, 331, 331, + 331, 376, 376, 376, 376, 376, 376, 2326, 2323, 328, + 2321, 329, 339, 339, 339, 347, 347, 347, 2316, 2314, + 325, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 2311, 2306, 2305, 978, 328, 328, 328, 328, 328, 328, + + 2301, 2299, 2290, 329, 329, 329, 329, 329, 329, 2287, + 2282, 2279, 325, 325, 325, 325, 325, 325, 2028, 316, + 318, 318, 978, 2028, 318, 318, 2273, 2272, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 338, 318, 318, + 318, 318, 318, 333, 333, 333, 333, 333, 333, 333, + 333, 333, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 339, 361, 2259, 347, 348, 348, 348, 979, 318, + 2258, 318, 335, 335, 335, 335, 335, 335, 335, 335, + 335, 336, 336, 336, 336, 336, 336, 336, 336, 336, + 358, 358, 358, 383, 2256, 2237, 2226, 979, 318, 318, + + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 362, 362, 362, 362, 362, 362, + 362, 362, 362, 363, 363, 363, 363, 363, 363, 363, + 363, 363, 364, 364, 364, 364, 364, 364, 364, 364, + 364, 392, 392, 392, 2224, 361, 361, 361, 361, 361, + 361, 2223, 2215, 2213, 348, 365, 365, 365, 365, 365, + 365, 365, 365, 365, 366, 366, 366, 366, 366, 366, + 366, 366, 366, 383, 383, 383, 383, 383, 383, 358, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 369, + 369, 2105, 2207, 369, 369, 2201, 2105, 369, 369, 369, + + 369, 369, 369, 369, 369, 369, 2196, 369, 369, 369, + 369, 369, 370, 370, 370, 370, 370, 370, 370, 370, + 370, 371, 371, 371, 371, 371, 371, 371, 371, 371, + 392, 402, 402, 402, 402, 402, 402, 981, 369, 2194, + 369, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 373, 373, 373, 373, 373, 373, 373, 373, 373, 455, + 455, 455, 455, 455, 455, 2191, 981, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 374, 374, 374, 374, 374, 374, 374, + 374, 374, 375, 375, 375, 375, 375, 375, 375, 375, + + 375, 377, 377, 377, 377, 377, 377, 377, 377, 377, + 378, 378, 378, 378, 378, 378, 378, 378, 378, 379, + 379, 379, 379, 379, 379, 379, 379, 379, 380, 380, + 380, 380, 380, 380, 380, 380, 380, 381, 381, 381, + 381, 381, 381, 381, 381, 381, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 385, 385, 385, 385, 385, + 385, 385, 385, 385, 386, 386, 386, 386, 386, 386, + 386, 386, 386, 387, 387, 387, 387, 387, 387, 387, + 387, 387, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 389, 389, 389, 389, 389, 389, 389, 389, 389, + + 390, 390, 390, 390, 390, 390, 390, 390, 390, 398, + 400, 398, 399, 755, 399, 755, 2189, 399, 400, 2184, + 524, 398, 2181, 982, 403, 755, 524, 983, 985, 401, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 400, + 472, 472, 472, 472, 472, 472, 2168, 400, 404, 524, + 398, 414, 982, 403, 755, 524, 983, 985, 401, 2150, + 2149, 649, 649, 649, 400, 400, 400, 400, 400, 400, + 403, 403, 403, 403, 403, 403, 405, 404, 418, 445, + 414, 2135, 398, 398, 398, 398, 398, 398, 399, 399, + 399, 399, 399, 399, 401, 401, 401, 401, 401, 401, + + 406, 991, 992, 409, 407, 405, 2123, 418, 445, 2114, + 404, 404, 404, 404, 404, 404, 414, 414, 414, 414, + 414, 414, 418, 418, 418, 418, 418, 418, 2103, 406, + 991, 992, 409, 407, 2100, 405, 405, 405, 405, 405, + 405, 408, 408, 445, 445, 445, 445, 445, 445, 408, + 649, 993, 406, 406, 406, 406, 406, 406, 407, 407, + 407, 407, 407, 407, 409, 409, 409, 409, 409, 409, + 408, 408, 410, 411, 410, 2098, 528, 2092, 408, 994, + 993, 2085, 412, 410, 528, 494, 494, 494, 494, 494, + 410, 494, 494, 494, 408, 408, 408, 408, 408, 408, + + 2075, 410, 411, 410, 817, 528, 817, 413, 994, 2072, + 820, 412, 410, 528, 415, 995, 817, 415, 413, 410, + 820, 996, 997, 416, 411, 411, 411, 411, 411, 411, + 412, 412, 412, 412, 412, 412, 413, 410, 410, 410, + 410, 410, 410, 415, 995, 817, 415, 413, 2048, 820, + 996, 997, 416, 2042, 2031, 998, 419, 420, 456, 2026, + 999, 421, 415, 415, 415, 415, 415, 415, 413, 413, + 413, 413, 413, 413, 416, 416, 416, 416, 416, 416, + 417, 626, 626, 626, 998, 419, 420, 1992, 626, 999, + 421, 1984, 1980, 538, 417, 456, 456, 456, 456, 456, + + 456, 422, 1037, 1038, 1048, 424, 1051, 1079, 1969, 417, + 419, 419, 419, 419, 419, 419, 420, 420, 420, 420, + 420, 420, 423, 417, 421, 421, 421, 421, 421, 421, + 422, 1037, 1038, 1048, 424, 1051, 1079, 423, 423, 1110, + 429, 1961, 426, 425, 426, 417, 417, 417, 417, 417, + 417, 423, 1953, 422, 422, 422, 422, 422, 422, 424, + 424, 424, 424, 424, 424, 1950, 423, 423, 1110, 429, + 626, 426, 425, 426, 427, 428, 538, 538, 538, 538, + 538, 538, 430, 433, 423, 423, 423, 423, 423, 423, + 425, 425, 425, 425, 425, 425, 482, 426, 426, 426, + + 426, 426, 426, 427, 428, 429, 429, 429, 429, 429, + 429, 430, 433, 1944, 1922, 431, 1911, 427, 427, 427, + 427, 427, 427, 428, 428, 428, 428, 428, 428, 432, + 545, 545, 545, 545, 545, 545, 1111, 435, 430, 430, + 430, 430, 430, 430, 431, 433, 433, 433, 433, 433, + 433, 1897, 434, 436, 1892, 534, 534, 1865, 432, 534, + 1863, 534, 534, 534, 1860, 1111, 435, 482, 482, 482, + 482, 482, 482, 1854, 1851, 431, 431, 431, 431, 431, + 431, 434, 436, 432, 432, 432, 432, 432, 432, 435, + 435, 435, 435, 435, 435, 437, 443, 526, 1097, 442, + + 434, 434, 434, 434, 434, 434, 438, 526, 1097, 440, + 438, 440, 1114, 1115, 436, 436, 436, 436, 436, 436, + 440, 666, 666, 666, 437, 443, 526, 440, 442, 440, + 444, 440, 1849, 1842, 1835, 438, 526, 1097, 440, 438, + 440, 1114, 1115, 437, 437, 437, 437, 437, 437, 440, + 442, 442, 442, 442, 442, 442, 440, 1827, 440, 444, + 440, 443, 443, 443, 443, 443, 443, 438, 438, 438, + 438, 438, 438, 439, 441, 439, 441, 446, 439, 639, + 639, 639, 448, 639, 439, 441, 439, 1822, 439, 447, + 1818, 439, 441, 441, 439, 444, 444, 444, 444, 444, + + 444, 1814, 439, 441, 439, 441, 446, 439, 1808, 447, + 666, 448, 1796, 439, 441, 439, 449, 439, 447, 449, + 439, 441, 441, 439, 1116, 446, 446, 446, 446, 446, + 446, 450, 1098, 1117, 1098, 450, 452, 1098, 447, 448, + 448, 448, 448, 448, 448, 449, 1776, 453, 449, 1094, + 1761, 1094, 1756, 1116, 447, 447, 447, 447, 447, 447, + 450, 1094, 1117, 1751, 450, 452, 1723, 1717, 639, 451, + 454, 1118, 1256, 1257, 1258, 451, 453, 1259, 449, 449, + 449, 449, 449, 449, 452, 452, 452, 452, 452, 452, + 1094, 1712, 450, 450, 450, 450, 450, 450, 451, 454, + + 1118, 1256, 1257, 1258, 451, 1709, 1259, 1702, 453, 453, + 453, 453, 453, 453, 1699, 1695, 454, 454, 454, 454, + 454, 454, 1685, 451, 451, 451, 451, 451, 451, 459, + 459, 459, 459, 459, 459, 459, 459, 459, 460, 460, + 460, 460, 460, 460, 460, 460, 460, 461, 461, 461, + 461, 461, 461, 461, 461, 461, 462, 462, 462, 462, + 462, 462, 462, 462, 462, 463, 463, 463, 463, 463, + 463, 463, 463, 463, 464, 464, 464, 464, 464, 464, + 464, 464, 464, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 466, 466, 466, 466, 466, 466, 466, 466, + + 466, 467, 467, 467, 467, 467, 467, 467, 467, 467, + 468, 468, 468, 468, 468, 468, 468, 468, 468, 469, + 469, 469, 469, 469, 469, 469, 469, 469, 470, 470, + 470, 470, 470, 470, 470, 470, 470, 471, 471, 471, + 471, 471, 471, 471, 471, 471, 473, 473, 473, 473, + 473, 473, 473, 473, 473, 474, 474, 474, 474, 474, + 474, 474, 474, 474, 475, 475, 475, 475, 475, 475, + 475, 475, 475, 476, 476, 476, 476, 476, 476, 476, + 476, 476, 477, 477, 477, 477, 477, 477, 477, 477, + 477, 478, 478, 478, 478, 478, 478, 478, 478, 478, + + 483, 484, 659, 659, 659, 659, 659, 659, 485, 487, + 486, 1674, 1670, 1665, 1260, 1643, 488, 489, 489, 489, + 489, 489, 489, 489, 489, 489, 1633, 577, 577, 483, + 484, 577, 1624, 577, 577, 577, 1602, 485, 487, 486, + 678, 678, 678, 1260, 678, 488, 678, 678, 678, 1589, + 1575, 483, 483, 483, 483, 483, 483, 487, 487, 487, + 487, 487, 487, 484, 484, 484, 484, 484, 484, 485, + 485, 485, 485, 485, 485, 486, 486, 486, 486, 486, + 486, 488, 488, 488, 488, 488, 488, 490, 490, 490, + 490, 490, 490, 490, 490, 491, 491, 491, 491, 491, + + 491, 491, 491, 491, 492, 492, 492, 492, 492, 492, + 492, 492, 492, 493, 493, 493, 493, 493, 493, 493, + 493, 493, 495, 495, 495, 495, 495, 495, 495, 495, + 495, 496, 496, 496, 496, 496, 496, 496, 496, 496, + 499, 499, 499, 1574, 1572, 1552, 500, 500, 500, 1261, + 1545, 499, 1540, 499, 499, 1510, 1509, 500, 1507, 500, + 500, 501, 501, 501, 1502, 499, 499, 1501, 499, 1497, + 1495, 1133, 501, 1133, 501, 501, 508, 499, 1261, 499, + 508, 499, 1262, 1133, 508, 503, 503, 503, 1263, 508, + 1264, 1265, 1267, 508, 499, 499, 503, 499, 503, 503, + + 1489, 1483, 1482, 1480, 1478, 508, 499, 1477, 499, 508, + 499, 1262, 1133, 508, 1268, 503, 1270, 1263, 508, 1264, + 1265, 1267, 508, 1475, 1473, 1472, 1470, 499, 499, 499, + 499, 499, 499, 500, 500, 500, 500, 500, 500, 633, + 633, 633, 1468, 1268, 503, 1270, 633, 1466, 501, 501, + 501, 501, 501, 501, 509, 509, 509, 509, 509, 509, + 509, 509, 509, 510, 510, 510, 510, 510, 510, 510, + 510, 510, 503, 503, 503, 503, 503, 503, 511, 511, + 511, 511, 511, 511, 511, 511, 511, 512, 512, 512, + 512, 512, 512, 512, 512, 512, 513, 513, 513, 513, + + 513, 513, 513, 513, 513, 514, 514, 514, 514, 514, + 514, 514, 514, 514, 515, 515, 515, 515, 515, 515, + 515, 515, 515, 525, 564, 1461, 1459, 1455, 633, 1453, + 525, 573, 573, 573, 573, 573, 573, 573, 573, 525, + 529, 529, 529, 529, 529, 529, 529, 529, 529, 1431, + 1410, 1345, 525, 699, 699, 699, 699, 699, 699, 525, + 1344, 564, 564, 564, 564, 564, 564, 1338, 525, 530, + 530, 530, 530, 530, 530, 530, 530, 530, 531, 531, + 531, 531, 531, 531, 531, 531, 531, 532, 532, 532, + 532, 532, 532, 532, 532, 532, 533, 533, 533, 533, + + 533, 533, 533, 533, 533, 535, 535, 535, 535, 535, + 535, 535, 535, 535, 536, 536, 536, 536, 536, 536, + 536, 536, 536, 539, 539, 539, 539, 539, 539, 539, + 539, 539, 540, 540, 540, 540, 540, 540, 540, 540, + 540, 541, 541, 541, 541, 541, 541, 541, 541, 541, + 542, 542, 542, 542, 542, 542, 542, 542, 542, 543, + 543, 543, 543, 543, 543, 543, 543, 543, 544, 544, + 544, 544, 544, 544, 544, 544, 544, 546, 546, 546, + 546, 546, 546, 546, 546, 546, 547, 547, 547, 547, + 547, 547, 547, 547, 547, 548, 548, 548, 548, 548, + + 548, 548, 548, 548, 549, 549, 549, 549, 549, 549, + 549, 549, 549, 550, 550, 550, 550, 550, 550, 550, + 550, 550, 551, 551, 551, 551, 551, 551, 551, 551, + 551, 552, 554, 554, 554, 554, 554, 554, 554, 554, + 554, 555, 555, 555, 555, 555, 555, 555, 555, 555, + 556, 556, 556, 556, 556, 556, 556, 556, 556, 557, + 557, 557, 557, 557, 557, 557, 557, 557, 558, 558, + 558, 558, 558, 558, 558, 558, 558, 559, 559, 559, + 559, 559, 559, 559, 559, 559, 1337, 1332, 562, 563, + 566, 566, 566, 566, 566, 566, 566, 566, 566, 567, + + 567, 567, 567, 567, 567, 567, 567, 567, 1331, 1325, + 1324, 552, 552, 552, 552, 552, 552, 562, 563, 568, + 568, 568, 568, 568, 568, 568, 568, 568, 718, 718, + 718, 718, 718, 718, 1323, 1322, 562, 562, 562, 562, + 562, 562, 569, 569, 569, 569, 569, 569, 569, 569, + 569, 1321, 1319, 563, 563, 563, 563, 563, 563, 570, + 570, 570, 570, 570, 570, 570, 570, 570, 571, 571, + 571, 571, 571, 571, 571, 571, 571, 572, 572, 572, + 572, 572, 572, 572, 572, 572, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 575, 575, 575, 575, 575, + + 575, 575, 575, 575, 576, 576, 576, 576, 576, 576, + 576, 576, 576, 578, 578, 578, 578, 578, 578, 578, + 578, 578, 579, 579, 579, 579, 579, 579, 579, 579, + 579, 652, 652, 1318, 1315, 652, 652, 1306, 1305, 652, + 652, 652, 652, 652, 652, 652, 652, 652, 1298, 652, + 652, 652, 652, 652, 653, 653, 653, 653, 653, 653, + 653, 653, 653, 654, 654, 654, 654, 654, 654, 654, + 654, 654, 727, 727, 727, 727, 727, 727, 727, 727, + 652, 1297, 652, 655, 655, 655, 655, 655, 655, 655, + 655, 655, 656, 656, 656, 656, 656, 656, 656, 656, + + 656, 745, 745, 745, 745, 745, 745, 1288, 1286, 652, + 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, + 652, 652, 652, 652, 652, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 658, 658, 658, 658, 658, 658, + 658, 658, 658, 660, 660, 660, 660, 660, 660, 660, + 660, 660, 661, 661, 661, 661, 661, 661, 661, 661, + 661, 662, 662, 662, 662, 662, 662, 662, 662, 662, + 663, 663, 663, 663, 663, 663, 663, 663, 663, 664, + 664, 664, 664, 664, 664, 664, 664, 664, 665, 665, + 665, 665, 665, 665, 665, 665, 665, 668, 669, 1271, + + 1272, 1285, 1279, 1277, 670, 673, 673, 673, 673, 673, + 673, 673, 673, 673, 715, 715, 715, 715, 715, 671, + 715, 715, 715, 1275, 1269, 1225, 668, 669, 1271, 1272, + 731, 731, 672, 670, 731, 1138, 731, 731, 731, 1137, + 1136, 1135, 668, 668, 668, 668, 668, 668, 671, 669, + 669, 669, 669, 669, 669, 670, 670, 670, 670, 670, + 670, 672, 682, 682, 682, 1134, 671, 671, 671, 671, + 671, 671, 685, 685, 685, 672, 672, 672, 672, 672, + 672, 674, 674, 674, 674, 674, 674, 674, 674, 674, + 675, 675, 675, 675, 675, 675, 675, 675, 675, 676, + + 676, 676, 676, 676, 676, 676, 676, 676, 677, 677, + 677, 677, 677, 677, 677, 677, 677, 679, 679, 679, + 679, 679, 679, 679, 679, 679, 680, 680, 680, 680, + 680, 680, 680, 680, 680, 689, 689, 689, 693, 693, + 693, 693, 693, 693, 693, 693, 693, 1132, 1131, 1128, + 1113, 682, 694, 694, 694, 694, 694, 694, 694, 694, + 694, 685, 695, 695, 695, 695, 695, 695, 695, 695, + 695, 696, 696, 696, 696, 696, 696, 696, 696, 696, + 697, 697, 697, 697, 697, 697, 697, 697, 697, 698, + 698, 698, 698, 698, 698, 698, 698, 698, 700, 700, + + 700, 700, 700, 700, 700, 700, 700, 701, 701, 701, + 701, 701, 701, 701, 701, 701, 789, 789, 789, 789, + 789, 789, 789, 789, 689, 692, 692, 1109, 1100, 692, + 692, 1093, 1091, 692, 692, 692, 692, 692, 692, 692, + 692, 692, 1273, 692, 692, 692, 692, 692, 702, 702, + 702, 702, 702, 702, 702, 702, 702, 703, 703, 703, + 703, 703, 703, 703, 703, 703, 706, 706, 706, 1287, + 1080, 1273, 1294, 1299, 692, 1066, 692, 704, 704, 704, + 704, 704, 704, 704, 704, 704, 705, 705, 705, 705, + 705, 705, 705, 705, 705, 707, 1334, 1404, 1287, 708, + + 1054, 1294, 1299, 692, 692, 692, 692, 692, 692, 692, + 692, 692, 692, 692, 692, 692, 692, 692, 692, 1050, + 1036, 1024, 1023, 709, 707, 1334, 1404, 1021, 708, 710, + 710, 710, 710, 710, 710, 710, 710, 710, 1020, 1018, + 707, 707, 707, 707, 707, 707, 708, 708, 708, 708, + 708, 708, 709, 1016, 1015, 706, 711, 711, 711, 711, + 711, 711, 711, 711, 711, 1013, 709, 709, 709, 709, + 709, 709, 712, 712, 712, 712, 712, 712, 712, 712, + 712, 713, 713, 713, 713, 713, 713, 713, 713, 713, + 714, 714, 714, 714, 714, 714, 714, 714, 714, 716, + + 716, 716, 716, 716, 716, 716, 716, 716, 717, 717, + 717, 717, 717, 717, 717, 717, 717, 719, 719, 719, + 719, 719, 719, 719, 719, 719, 720, 720, 720, 720, + 720, 720, 720, 720, 720, 721, 721, 721, 721, 721, + 721, 721, 721, 721, 722, 722, 722, 722, 722, 722, + 722, 722, 722, 723, 723, 723, 723, 723, 723, 723, + 723, 723, 724, 724, 724, 724, 724, 724, 724, 724, + 724, 725, 726, 726, 726, 726, 726, 726, 726, 726, + 726, 728, 728, 728, 728, 728, 728, 728, 728, 728, + 729, 729, 729, 729, 729, 729, 729, 729, 729, 1011, + + 725, 730, 730, 730, 730, 730, 730, 730, 730, 730, + 732, 732, 732, 732, 732, 732, 732, 732, 732, 735, + 735, 735, 725, 725, 725, 725, 725, 725, 733, 733, + 733, 733, 733, 733, 733, 733, 733, 739, 739, 739, + 739, 739, 739, 739, 739, 739, 740, 740, 740, 740, + 740, 740, 740, 740, 740, 741, 741, 741, 741, 741, + 741, 741, 741, 741, 742, 742, 742, 742, 742, 742, + 742, 742, 742, 743, 743, 743, 743, 743, 743, 743, + 743, 743, 744, 744, 744, 744, 744, 744, 744, 744, + 744, 746, 746, 746, 746, 746, 746, 746, 746, 746, + + 797, 797, 797, 797, 797, 797, 797, 797, 735, 738, + 738, 1403, 1010, 738, 738, 984, 980, 738, 738, 738, + 738, 738, 738, 738, 738, 738, 1403, 738, 738, 738, + 738, 738, 747, 747, 747, 747, 747, 747, 747, 747, + 747, 748, 748, 748, 748, 748, 748, 748, 748, 748, + 753, 753, 753, 919, 759, 1403, 759, 823, 738, 759, + 738, 749, 749, 749, 749, 749, 749, 749, 749, 749, + 750, 750, 750, 750, 750, 750, 750, 750, 750, 804, + 804, 804, 804, 804, 804, 804, 804, 738, 738, 738, + 738, 738, 738, 738, 738, 738, 738, 738, 738, 738, + + 738, 738, 738, 751, 751, 751, 751, 751, 751, 751, + 751, 751, 758, 760, 758, 927, 927, 927, 927, 927, + 927, 767, 767, 761, 758, 767, 767, 767, 767, 767, + 759, 759, 759, 759, 759, 759, 816, 814, 787, 753, + 783, 778, 760, 762, 762, 762, 762, 762, 762, 762, + 762, 762, 761, 758, 763, 763, 763, 763, 763, 763, + 763, 763, 763, 776, 760, 760, 760, 760, 760, 760, + 761, 761, 761, 761, 761, 761, 764, 764, 764, 764, + 764, 764, 764, 764, 764, 758, 758, 758, 758, 758, + 758, 765, 765, 765, 765, 765, 765, 765, 765, 765, + + 766, 766, 766, 766, 766, 766, 766, 766, 766, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 769, 769, + 769, 769, 769, 769, 769, 769, 769, 770, 770, 770, + 773, 773, 773, 777, 777, 777, 780, 780, 780, 788, + 788, 788, 788, 788, 788, 788, 788, 788, 790, 790, + 790, 790, 790, 790, 790, 790, 790, 791, 791, 791, + 791, 791, 791, 791, 791, 791, 792, 792, 792, 792, + 792, 792, 792, 792, 792, 793, 793, 771, 754, 793, + 752, 793, 793, 793, 794, 794, 794, 794, 794, 794, + 794, 794, 794, 795, 795, 795, 795, 795, 795, 795, + + 795, 795, 796, 796, 796, 796, 796, 796, 796, 796, + 796, 736, 690, 687, 683, 650, 770, 643, 642, 773, + 641, 637, 777, 636, 634, 780, 798, 798, 798, 798, + 798, 798, 798, 798, 798, 799, 799, 799, 799, 799, + 799, 799, 799, 799, 800, 800, 800, 800, 800, 800, + 800, 800, 800, 801, 801, 630, 1405, 801, 629, 801, + 801, 801, 802, 802, 802, 802, 802, 802, 802, 802, + 802, 803, 803, 803, 803, 803, 803, 803, 803, 803, + 805, 805, 627, 623, 805, 1405, 805, 805, 805, 806, + 806, 806, 806, 806, 806, 806, 806, 806, 807, 807, + + 807, 807, 807, 807, 807, 807, 808, 808, 808, 808, + 808, 808, 808, 808, 808, 809, 809, 809, 809, 809, + 809, 809, 809, 809, 810, 810, 810, 810, 810, 810, + 810, 810, 810, 811, 811, 922, 824, 811, 824, 811, + 811, 811, 812, 812, 812, 812, 812, 812, 812, 812, + 812, 813, 813, 813, 813, 813, 813, 813, 813, 813, + 815, 815, 815, 822, 922, 822, 909, 909, 620, 825, + 909, 619, 909, 909, 909, 822, 1406, 826, 918, 918, + 616, 615, 918, 827, 918, 918, 918, 1407, 613, 826, + 600, 1320, 599, 1320, 828, 596, 922, 922, 922, 922, + + 922, 922, 827, 1320, 822, 1406, 595, 846, 592, 824, + 824, 824, 824, 824, 824, 591, 1407, 829, 826, 828, + 928, 928, 928, 928, 928, 928, 481, 831, 393, 391, + 359, 827, 1320, 829, 354, 831, 822, 822, 822, 822, + 822, 822, 825, 825, 825, 825, 825, 825, 828, 815, + 826, 826, 826, 826, 826, 826, 827, 827, 827, 827, + 827, 827, 829, 830, 831, 350, 345, 828, 828, 828, + 828, 828, 828, 341, 324, 321, 291, 832, 281, 830, + 846, 846, 846, 846, 846, 846, 833, 280, 278, 1408, + 829, 829, 829, 829, 829, 829, 832, 1012, 1012, 1012, + + 831, 831, 831, 831, 831, 831, 833, 835, 830, 904, + 904, 904, 904, 904, 904, 904, 904, 904, 1408, 256, + 254, 834, 1017, 1017, 1017, 832, 245, 1409, 835, 243, + 837, 232, 231, 225, 224, 833, 830, 830, 830, 830, + 830, 830, 834, 1022, 1022, 1022, 1346, 834, 1346, 837, + 832, 832, 832, 832, 832, 832, 1409, 835, 1346, 833, + 833, 833, 833, 833, 833, 836, 216, 215, 1035, 1035, + 1035, 834, 838, 836, 212, 211, 834, 195, 837, 194, + 835, 835, 835, 835, 835, 835, 1012, 1346, 188, 1451, + 840, 838, 187, 180, 834, 834, 834, 834, 834, 834, + + 840, 841, 836, 837, 837, 837, 837, 837, 837, 953, + 953, 1017, 179, 953, 839, 953, 953, 953, 1451, 111, + 838, 843, 839, 73, 841, 72, 839, 69, 59, 840, + 842, 843, 1022, 1452, 36, 35, 34, 844, 836, 836, + 836, 836, 836, 836, 1454, 838, 838, 838, 838, 838, + 838, 839, 842, 841, 845, 839, 844, 1035, 33, 0, + 843, 0, 1452, 840, 840, 840, 840, 840, 840, 0, + 0, 1456, 847, 1454, 841, 841, 841, 841, 841, 841, + 845, 842, 854, 0, 0, 844, 0, 839, 839, 839, + 839, 839, 839, 847, 843, 843, 843, 843, 843, 843, + + 1456, 0, 849, 842, 842, 842, 842, 842, 842, 845, + 844, 844, 844, 844, 844, 844, 848, 0, 1049, 1049, + 1049, 0, 847, 849, 0, 850, 0, 845, 845, 845, + 845, 845, 845, 961, 961, 1457, 848, 961, 851, 961, + 961, 961, 1458, 1460, 852, 847, 847, 847, 847, 847, + 847, 853, 849, 850, 851, 854, 854, 854, 854, 854, + 854, 0, 0, 0, 1457, 848, 853, 852, 0, 856, + 0, 1458, 1460, 0, 0, 849, 849, 849, 849, 849, + 849, 856, 850, 851, 855, 0, 0, 0, 0, 848, + 848, 848, 848, 848, 848, 853, 852, 857, 850, 850, + + 850, 850, 850, 850, 0, 0, 855, 1049, 0, 857, + 856, 851, 851, 851, 851, 851, 851, 852, 852, 852, + 852, 852, 852, 860, 853, 853, 853, 853, 853, 853, + 858, 0, 0, 971, 971, 855, 859, 971, 857, 971, + 971, 971, 856, 856, 856, 856, 856, 856, 0, 1462, + 860, 861, 858, 1463, 1464, 859, 1465, 855, 855, 855, + 855, 855, 855, 861, 0, 1484, 0, 863, 0, 0, + 857, 857, 857, 857, 857, 857, 0, 862, 1462, 860, + 0, 858, 1463, 1464, 859, 1465, 1065, 1065, 1065, 865, + 0, 0, 861, 862, 1484, 866, 860, 860, 860, 860, + + 860, 860, 863, 858, 858, 858, 858, 858, 858, 859, + 859, 859, 859, 859, 859, 0, 864, 865, 866, 1092, + 1092, 1092, 862, 867, 861, 861, 861, 861, 861, 861, + 864, 905, 905, 905, 905, 905, 905, 905, 905, 0, + 863, 863, 863, 863, 863, 863, 865, 866, 868, 867, + 862, 862, 862, 862, 862, 862, 870, 0, 1485, 864, + 0, 0, 865, 865, 865, 865, 865, 865, 866, 866, + 866, 866, 866, 866, 869, 1065, 1496, 1538, 867, 0, + 868, 1539, 1551, 870, 872, 1568, 869, 1485, 1569, 864, + 864, 864, 864, 864, 864, 0, 867, 867, 867, 867, + + 867, 867, 871, 0, 0, 1496, 1538, 872, 1092, 868, + 1539, 1551, 870, 873, 1568, 869, 871, 1569, 0, 874, + 0, 868, 868, 868, 868, 868, 868, 873, 875, 870, + 870, 870, 870, 870, 870, 878, 872, 0, 875, 1570, + 1571, 1573, 876, 878, 874, 871, 0, 869, 869, 869, + 869, 869, 869, 876, 1576, 1578, 873, 872, 872, 872, + 872, 872, 872, 0, 0, 0, 879, 875, 1570, 1571, + 1573, 1579, 878, 874, 877, 871, 871, 871, 871, 871, + 871, 0, 876, 1576, 1578, 879, 873, 873, 873, 873, + 873, 873, 874, 874, 874, 874, 874, 874, 920, 877, + + 1579, 875, 875, 875, 875, 875, 875, 881, 878, 878, + 878, 878, 878, 878, 879, 876, 876, 876, 876, 876, + 876, 880, 0, 0, 0, 0, 0, 882, 877, 881, + 0, 0, 0, 880, 883, 1108, 1108, 1108, 0, 879, + 879, 879, 879, 879, 879, 885, 882, 877, 877, 877, + 877, 877, 877, 884, 886, 886, 886, 885, 881, 1030, + 1030, 883, 880, 1030, 1581, 1030, 1030, 1030, 886, 920, + 920, 920, 920, 920, 920, 882, 887, 0, 0, 0, + 881, 881, 881, 881, 881, 881, 885, 1582, 884, 0, + 883, 0, 0, 1581, 880, 880, 880, 880, 880, 880, + + 882, 882, 882, 882, 882, 882, 887, 883, 883, 883, + 883, 883, 883, 888, 0, 0, 1582, 0, 885, 885, + 885, 885, 885, 885, 1108, 0, 884, 884, 884, 884, + 884, 884, 1583, 964, 1584, 887, 888, 0, 0, 889, + 0, 886, 886, 886, 886, 886, 886, 1585, 890, 887, + 887, 887, 887, 887, 887, 0, 891, 0, 0, 0, + 0, 1583, 964, 1584, 889, 888, 889, 890, 891, 895, + 974, 974, 974, 974, 974, 974, 1585, 895, 893, 964, + 964, 964, 964, 964, 964, 894, 888, 888, 888, 888, + 888, 888, 897, 889, 0, 889, 890, 891, 892, 893, + + 975, 975, 975, 975, 975, 975, 895, 894, 892, 894, + 896, 0, 889, 889, 889, 889, 889, 889, 0, 892, + 912, 890, 890, 890, 890, 890, 890, 0, 893, 891, + 891, 891, 891, 891, 891, 896, 894, 892, 894, 1112, + 1112, 1112, 895, 895, 895, 895, 895, 895, 892, 899, + 0, 893, 893, 893, 893, 893, 893, 898, 894, 894, + 894, 894, 894, 894, 896, 897, 897, 897, 897, 897, + 897, 892, 892, 892, 892, 892, 892, 899, 898, 901, + 0, 0, 0, 896, 896, 896, 896, 896, 896, 0, + 0, 1586, 900, 912, 912, 912, 912, 912, 912, 0, + + 901, 0, 0, 903, 0, 0, 899, 898, 900, 906, + 906, 906, 906, 906, 906, 906, 906, 906, 903, 921, + 1586, 902, 899, 899, 899, 899, 899, 899, 1112, 901, + 898, 898, 898, 898, 898, 898, 0, 900, 0, 0, + 0, 0, 902, 1588, 1619, 1620, 902, 903, 921, 0, + 0, 0, 901, 901, 901, 901, 901, 901, 913, 921, + 921, 921, 921, 921, 921, 900, 900, 900, 900, 900, + 900, 902, 1588, 1619, 1620, 902, 903, 903, 903, 903, + 903, 903, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 0, 0, 0, 902, 902, 902, 902, 902, 902, + + 908, 908, 908, 908, 908, 908, 908, 908, 908, 910, + 910, 910, 910, 910, 910, 910, 910, 910, 911, 911, + 911, 911, 911, 911, 911, 911, 911, 923, 924, 0, + 925, 913, 913, 913, 913, 913, 913, 917, 917, 917, + 917, 917, 917, 917, 917, 917, 931, 931, 931, 931, + 931, 931, 931, 931, 931, 0, 923, 924, 926, 925, + 932, 932, 932, 932, 932, 932, 932, 932, 1130, 1130, + 1130, 0, 1621, 933, 0, 923, 923, 923, 923, 923, + 923, 925, 925, 925, 925, 925, 925, 926, 0, 934, + 924, 924, 924, 924, 924, 924, 933, 934, 935, 1034, + + 1034, 1621, 1625, 1034, 936, 1034, 1034, 1034, 0, 1627, + 0, 1580, 938, 926, 926, 926, 926, 926, 926, 937, + 0, 0, 937, 1580, 935, 933, 934, 1629, 0, 1060, + 1060, 1625, 936, 1060, 939, 1060, 1060, 1060, 1627, 938, + 1580, 941, 0, 0, 0, 0, 933, 933, 933, 933, + 933, 933, 1580, 935, 0, 941, 1629, 1130, 0, 945, + 0, 936, 934, 934, 934, 934, 934, 934, 938, 939, + 943, 935, 935, 935, 935, 935, 935, 936, 936, 936, + 936, 936, 936, 940, 941, 938, 938, 938, 938, 938, + 938, 944, 937, 937, 937, 937, 937, 937, 942, 0, + + 1630, 944, 940, 0, 946, 943, 0, 939, 939, 939, + 939, 939, 939, 1631, 941, 941, 941, 941, 941, 941, + 1064, 1064, 1632, 1634, 1064, 942, 1064, 1064, 1064, 1630, + 944, 940, 945, 945, 945, 945, 945, 945, 0, 0, + 0, 1638, 1631, 943, 943, 943, 943, 943, 943, 0, + 0, 1632, 1634, 0, 942, 0, 940, 940, 940, 940, + 940, 940, 0, 0, 944, 944, 944, 944, 944, 944, + 1638, 942, 942, 942, 942, 942, 942, 946, 946, 946, + 946, 946, 946, 947, 947, 947, 947, 947, 947, 947, + 947, 947, 948, 948, 948, 948, 948, 948, 948, 948, + + 948, 949, 949, 949, 949, 949, 949, 949, 949, 950, + 950, 950, 950, 950, 950, 950, 950, 950, 951, 951, + 951, 951, 951, 951, 951, 951, 951, 952, 952, 952, + 952, 952, 952, 952, 952, 952, 954, 954, 954, 954, + 954, 954, 954, 954, 954, 955, 955, 955, 955, 955, + 955, 955, 955, 955, 956, 956, 956, 956, 956, 956, + 956, 956, 956, 957, 957, 957, 957, 957, 957, 957, + 957, 958, 958, 958, 958, 958, 958, 958, 958, 958, + 959, 959, 959, 959, 959, 959, 959, 959, 959, 960, + 960, 960, 960, 960, 960, 960, 960, 960, 962, 962, + + 962, 962, 962, 962, 962, 962, 962, 963, 963, 963, + 963, 963, 963, 963, 963, 963, 965, 966, 966, 966, + 966, 966, 966, 966, 966, 966, 967, 967, 967, 967, + 967, 967, 967, 967, 968, 968, 968, 968, 968, 968, + 968, 968, 968, 0, 0, 965, 969, 969, 969, 969, + 969, 969, 969, 969, 969, 970, 970, 970, 970, 970, + 970, 970, 970, 970, 1044, 1044, 1044, 1044, 1044, 1044, + 965, 965, 965, 965, 965, 965, 972, 972, 972, 972, + 972, 972, 972, 972, 972, 973, 973, 973, 973, 973, + 973, 973, 973, 973, 976, 976, 976, 976, 976, 976, + + 976, 976, 976, 1025, 1025, 1025, 1025, 1025, 1025, 1025, + 1025, 1025, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, + 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1028, + 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1029, 1029, + 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1031, 1031, 1031, + 1031, 1031, 1031, 1031, 1031, 1031, 1032, 1032, 1032, 1032, + 1032, 1032, 1032, 1032, 1032, 1033, 1033, 1033, 1033, 1033, + 1033, 1033, 1033, 1039, 1041, 1043, 1639, 1642, 1040, 1045, + 1045, 1045, 1045, 1045, 1045, 1047, 1047, 1047, 1047, 1047, + 1047, 1047, 1047, 1047, 1056, 1056, 1056, 1056, 1056, 1056, + + 1056, 1056, 1039, 1041, 0, 1639, 1642, 1040, 1042, 0, + 0, 0, 0, 1043, 1043, 1043, 1043, 1043, 1043, 1070, + 1070, 1070, 1070, 1070, 1070, 1039, 1039, 1039, 1039, 1039, + 1039, 1040, 1040, 1040, 1040, 1040, 1040, 1042, 1041, 1041, + 1041, 1041, 1041, 1041, 1055, 1055, 1055, 1055, 1055, 1055, + 1055, 1055, 1055, 0, 1042, 1042, 1042, 1042, 1042, 1042, + 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1058, + 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1059, 1059, + 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1061, 1061, 1061, + 1061, 1061, 1061, 1061, 1061, 1061, 1062, 1062, 1062, 1062, + + 1062, 1062, 1062, 1062, 1062, 1063, 1063, 1063, 1063, 1063, + 1063, 1063, 1063, 1067, 0, 0, 0, 1069, 1071, 1071, + 1071, 1071, 1071, 1071, 1075, 1068, 1074, 1074, 1074, 1074, + 1074, 1074, 1074, 1074, 1074, 1076, 1076, 1076, 1076, 1076, + 1076, 0, 1067, 1077, 1077, 1077, 1077, 1077, 1077, 1284, + 1284, 1284, 0, 1075, 1068, 1069, 1069, 1069, 1069, 1069, + 1069, 0, 0, 0, 0, 1067, 1067, 1067, 1067, 1067, + 1067, 1068, 1068, 1068, 1068, 1068, 1068, 1075, 1075, 1075, + 1075, 1075, 1075, 1078, 1078, 1078, 1078, 1078, 1078, 1078, + 1078, 1078, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, + + 1081, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1083, + 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1084, 1084, + 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1086, 1086, 1284, 0, + 1086, 0, 1086, 1086, 1086, 1087, 1087, 1087, 1087, 1087, + 1087, 1087, 1087, 1087, 1088, 1088, 1088, 1088, 1088, 1088, + 1088, 1088, 1088, 1089, 1089, 1089, 1089, 1089, 1089, 1089, + 1089, 1090, 1090, 0, 1099, 1090, 1099, 1090, 1090, 1090, + 1101, 0, 1101, 1274, 1274, 1274, 1099, 1102, 0, 0, + 1274, 0, 0, 1104, 0, 0, 1102, 1232, 1232, 1232, + + 1232, 1232, 1232, 1222, 1103, 0, 1119, 0, 0, 0, + 1105, 0, 1120, 0, 0, 1099, 1107, 1107, 1107, 1107, + 1107, 1107, 1107, 1107, 1107, 1102, 0, 0, 0, 0, + 1103, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, + 1222, 1222, 1222, 1222, 1222, 1222, 1649, 1099, 1099, 1099, + 1099, 1099, 1099, 1101, 1101, 1101, 1101, 1101, 1101, 1103, + 1102, 1102, 1102, 1102, 1102, 1102, 1104, 1104, 1104, 1104, + 1104, 1104, 1274, 1125, 1673, 1649, 0, 1103, 1103, 1103, + 1103, 1103, 1103, 1105, 1105, 1105, 1105, 1105, 1105, 1119, + 1119, 1119, 1119, 1119, 1119, 1120, 1120, 1120, 1120, 1120, + + 1120, 1122, 1122, 1673, 1697, 1122, 1122, 0, 0, 1122, + 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 0, 1122, + 1122, 1122, 1122, 1122, 1124, 1124, 1124, 1124, 1124, 1124, + 1124, 1124, 1124, 1697, 0, 1296, 1296, 1296, 1126, 1127, + 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 0, 0, + 1122, 0, 1122, 1125, 1125, 1125, 1125, 1125, 1125, 0, + 1139, 0, 1139, 1201, 1201, 1201, 1201, 1201, 1201, 1201, + 1201, 1201, 1139, 0, 1278, 1278, 1278, 1140, 1278, 1122, + 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, + 1122, 1122, 1122, 1122, 1122, 1123, 1123, 1698, 1587, 1123, + + 1123, 1139, 1140, 1123, 1123, 1123, 1123, 1123, 1123, 1123, + 1123, 1123, 1587, 1123, 1123, 1123, 1123, 1123, 1126, 1126, + 1126, 1126, 1126, 1126, 1296, 0, 1698, 1587, 1141, 1708, + 0, 1140, 0, 1139, 1139, 1139, 1139, 1139, 1139, 1143, + 0, 1587, 0, 1711, 1123, 1142, 1123, 0, 0, 0, + 1140, 1140, 1140, 1140, 1140, 1140, 1146, 1503, 1708, 1503, + 1141, 1142, 1577, 1278, 1716, 1577, 1143, 0, 0, 1503, + 1725, 1145, 1711, 1123, 1123, 1123, 1123, 1123, 1123, 1123, + 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1141, + 1142, 1577, 0, 1716, 1577, 1143, 1145, 1148, 1503, 1725, + + 0, 1141, 1141, 1141, 1141, 1141, 1141, 1144, 1726, 1148, + 1229, 0, 1143, 1143, 1143, 1143, 1143, 1143, 1142, 1142, + 1142, 1142, 1142, 1142, 1147, 1145, 0, 0, 1144, 1146, + 1146, 1146, 1146, 1146, 1146, 1150, 1147, 1726, 1148, 1229, + 1147, 0, 1149, 0, 1145, 1145, 1145, 1145, 1145, 1145, + 1151, 1229, 1229, 1229, 1229, 1229, 1229, 1144, 1149, 1152, + 0, 1727, 1150, 1728, 1729, 1147, 0, 1730, 1153, 1147, + 1148, 1148, 1148, 1148, 1148, 1148, 1153, 1151, 1152, 1157, + 1144, 1144, 1144, 1144, 1144, 1144, 0, 1149, 0, 1154, + 1727, 1150, 1728, 1729, 0, 1155, 1730, 1147, 1147, 1147, + + 1147, 1147, 1147, 0, 1156, 1153, 1151, 1152, 1150, 1150, + 1150, 1150, 1150, 1150, 0, 1149, 1149, 1149, 1149, 1149, + 1149, 1154, 1155, 1151, 1151, 1151, 1151, 1151, 1151, 1156, + 0, 1159, 1152, 1152, 1152, 1152, 1152, 1152, 0, 1160, + 0, 1153, 1153, 1153, 1153, 1153, 1153, 1160, 0, 1158, + 1154, 1155, 1157, 1157, 1157, 1157, 1157, 1157, 1156, 1159, + 1163, 0, 1154, 1154, 1154, 1154, 1154, 1154, 1155, 1155, + 1155, 1155, 1155, 1155, 1158, 1161, 1160, 1156, 1156, 1156, + 1156, 1156, 1156, 1164, 0, 0, 0, 0, 1159, 1162, + 1161, 0, 1276, 1276, 1276, 1165, 0, 0, 0, 1276, + + 1162, 1731, 1732, 1158, 1159, 1159, 1159, 1159, 1159, 1159, + 1164, 1167, 1160, 1160, 1160, 1160, 1160, 1160, 1165, 1161, + 1168, 0, 1158, 1158, 1158, 1158, 1158, 1158, 0, 1162, + 1731, 1732, 0, 1163, 1163, 1163, 1163, 1163, 1163, 1164, + 0, 0, 0, 1170, 1304, 1304, 1304, 1165, 1161, 1161, + 1161, 1161, 1161, 1161, 1166, 1168, 1164, 1164, 1164, 1164, + 1164, 1164, 1162, 1162, 1162, 1162, 1162, 1162, 1165, 1165, + 1165, 1165, 1165, 1165, 1170, 1166, 0, 0, 1733, 0, + 1169, 1276, 0, 1231, 1167, 1167, 1167, 1167, 1167, 1167, + 1171, 0, 0, 1168, 1168, 1168, 1168, 1168, 1168, 1172, + + 1173, 1173, 1173, 1170, 1166, 1169, 1174, 1733, 1223, 0, + 0, 1511, 1231, 1511, 1173, 1171, 1170, 1170, 1170, 1170, + 1170, 1170, 1175, 1511, 1317, 1317, 1317, 1166, 1166, 1166, + 1166, 1166, 1166, 1304, 1169, 1231, 1231, 1231, 1231, 1231, + 1231, 1174, 1734, 0, 1171, 1223, 1223, 1223, 1223, 1223, + 1223, 1176, 1511, 1169, 1169, 1169, 1169, 1169, 1169, 0, + 0, 0, 1177, 1171, 1171, 1171, 1171, 1171, 1171, 1182, + 0, 1734, 1172, 1172, 1172, 1172, 1172, 1172, 1176, 1174, + 1174, 1174, 1174, 1174, 1174, 1177, 0, 1173, 1173, 1173, + 1173, 1173, 1173, 1178, 1735, 1175, 1175, 1175, 1175, 1175, + + 1175, 1179, 1330, 1330, 1330, 1178, 0, 1176, 1180, 1336, + 1336, 1336, 1179, 1317, 1177, 1469, 1469, 1469, 0, 1181, + 0, 0, 1469, 1735, 1176, 1176, 1176, 1176, 1176, 1176, + 1180, 1181, 0, 1183, 1178, 1177, 1177, 1177, 1177, 1177, + 1177, 1179, 1182, 1182, 1182, 1182, 1182, 1182, 1185, 1185, + 1185, 0, 0, 0, 0, 0, 1184, 0, 1183, 1180, + 1181, 1666, 1185, 1666, 0, 0, 1178, 1178, 1178, 1178, + 1178, 1178, 1184, 1666, 1179, 1179, 1179, 1179, 1179, 1179, + 1186, 1180, 1180, 1180, 1180, 1180, 1180, 1183, 1186, 1188, + 0, 1330, 1181, 1181, 1181, 1181, 1181, 1181, 1336, 1736, + + 1187, 1184, 1666, 0, 1469, 0, 1183, 1183, 1183, 1183, + 1183, 1183, 1187, 1190, 1656, 1656, 1656, 1186, 1474, 1474, + 1474, 1188, 1737, 0, 1189, 1474, 0, 0, 1736, 1184, + 1184, 1184, 1184, 1184, 1184, 1185, 1185, 1185, 1185, 1185, + 1185, 1187, 1189, 1738, 1193, 0, 0, 0, 0, 0, + 1188, 1737, 1193, 1186, 1186, 1186, 1186, 1186, 1186, 1192, + 0, 0, 1188, 1188, 1188, 1188, 1188, 1188, 1191, 0, + 0, 1189, 1738, 1187, 1187, 1187, 1187, 1187, 1187, 1192, + 1191, 1193, 0, 1194, 1739, 0, 1190, 1190, 1190, 1190, + 1190, 1190, 0, 1195, 0, 1740, 0, 1189, 1189, 1189, + + 1189, 1189, 1189, 1656, 0, 0, 0, 1474, 1192, 1191, + 1194, 1195, 0, 1739, 1196, 0, 0, 1193, 1193, 1193, + 1193, 1193, 1193, 1196, 1740, 1205, 1741, 0, 0, 0, + 0, 1197, 1192, 1192, 1192, 1192, 1192, 1192, 1198, 1194, + 1195, 1191, 1191, 1191, 1191, 1191, 1191, 1197, 1198, 1202, + 1202, 1202, 1196, 1205, 1199, 1741, 1194, 1194, 1194, 1194, + 1194, 1194, 0, 1202, 1199, 1742, 1195, 1195, 1195, 1195, + 1195, 1195, 0, 1226, 0, 0, 1197, 1198, 0, 0, + 0, 1743, 1205, 0, 0, 0, 0, 1196, 1196, 1196, + 1196, 1196, 1196, 1199, 1742, 0, 0, 0, 1205, 1205, + + 1205, 1205, 1205, 1205, 1197, 1197, 1197, 1197, 1197, 1197, + 1743, 1198, 1198, 1198, 1198, 1198, 1198, 1203, 1224, 1224, + 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1199, 1199, 1199, + 1199, 1199, 1199, 1200, 1200, 1200, 1202, 1202, 1202, 1202, + 1202, 1202, 1230, 1203, 1226, 1226, 1226, 1226, 1226, 1226, + 1204, 0, 0, 0, 1200, 0, 0, 1200, 1200, 1206, + 0, 0, 0, 0, 0, 1207, 0, 1228, 1200, 1200, + 1200, 1206, 1203, 1207, 1200, 1744, 1208, 1204, 1745, 0, + 1230, 1230, 1230, 1230, 1230, 1230, 1200, 1200, 1208, 1209, + 1203, 1203, 1203, 1203, 1203, 1203, 1228, 1200, 1200, 1200, + + 1206, 1212, 1207, 1200, 1744, 0, 1204, 1745, 1210, 1228, + 1228, 1228, 1228, 1228, 1228, 1209, 1215, 1208, 1210, 2003, + 2003, 2003, 1200, 1204, 1204, 1204, 1204, 1204, 1204, 1212, + 1215, 0, 1206, 1206, 1206, 1206, 1206, 1206, 1207, 1207, + 1207, 1207, 1207, 1207, 1209, 0, 0, 1210, 1211, 1208, + 1208, 1208, 1208, 1208, 1208, 0, 1245, 0, 1212, 1215, + 1213, 0, 1209, 1209, 1209, 1209, 1209, 1209, 1623, 1211, + 1746, 0, 1214, 1623, 1212, 1212, 1212, 1212, 1212, 1212, + 1214, 1210, 1210, 1210, 1210, 1210, 1210, 1213, 1216, 1215, + 1215, 1215, 1215, 1215, 1215, 1217, 0, 1623, 1211, 1746, + + 1216, 1219, 1623, 1217, 0, 0, 0, 0, 2003, 1214, + 0, 1218, 0, 0, 0, 0, 1213, 0, 1220, 0, + 0, 1211, 1211, 1211, 1211, 1211, 1211, 1218, 1221, 1216, + 1220, 1747, 1217, 1213, 1213, 1213, 1213, 1213, 1213, 1245, + 1245, 1245, 1245, 1245, 1245, 1214, 1214, 1214, 1214, 1214, + 1214, 1227, 1233, 1748, 1749, 1233, 1218, 0, 0, 1220, + 1747, 1216, 1216, 1216, 1216, 1216, 1216, 0, 1217, 1217, + 1217, 1217, 1217, 1217, 1219, 1219, 1219, 1219, 1219, 1219, + 1227, 0, 1748, 1749, 1218, 1218, 1218, 1218, 1218, 1218, + 0, 1220, 1220, 1220, 1220, 1220, 1220, 1234, 0, 0, + + 1234, 1221, 1221, 1221, 1221, 1221, 1221, 1235, 1750, 0, + 1235, 1775, 1227, 1227, 1227, 1227, 1227, 1227, 1238, 1248, + 1671, 1238, 1671, 1234, 0, 1233, 1233, 1233, 1233, 1233, + 1233, 1777, 1671, 1778, 1235, 1236, 1779, 1750, 1236, 1780, + 1775, 1239, 0, 0, 1239, 0, 0, 1240, 1781, 1782, + 1240, 0, 1234, 1238, 0, 0, 0, 1239, 1236, 1240, + 1777, 1671, 1778, 1235, 1241, 1779, 1246, 1241, 1780, 0, + 1234, 1234, 1234, 1234, 1234, 1234, 1241, 1781, 1782, 0, + 1235, 1235, 1235, 1235, 1235, 1235, 1239, 1236, 1240, 0, + 0, 1238, 1238, 1238, 1238, 1238, 1238, 0, 1249, 1248, + + 1248, 1248, 1248, 1248, 1248, 1241, 0, 1783, 1236, 1236, + 1236, 1236, 1236, 1236, 1239, 1239, 1239, 1239, 1239, 1239, + 1240, 1240, 1240, 1240, 1240, 1240, 1242, 0, 0, 1242, + 0, 0, 1243, 0, 0, 1243, 1783, 1241, 1241, 1241, + 1241, 1241, 1241, 1244, 0, 1242, 1244, 1251, 1243, 1246, + 1246, 1246, 1246, 1246, 1246, 1244, 1247, 1247, 1247, 1247, + 1247, 1247, 1247, 1247, 1247, 1250, 1250, 1250, 1250, 1250, + 1250, 1250, 1250, 1250, 1242, 0, 0, 1243, 1249, 1249, + 1249, 1249, 1249, 1249, 1244, 1251, 1251, 1251, 1251, 1251, + 1251, 1253, 0, 1252, 1784, 1785, 1786, 1254, 1787, 1242, + + 1242, 1242, 1242, 1242, 1242, 1243, 1243, 1243, 1243, 1243, + 1243, 0, 0, 0, 0, 0, 1244, 1244, 1244, 1244, + 1244, 1244, 1252, 1784, 1785, 1786, 0, 1787, 1253, 1253, + 1253, 1253, 1253, 1253, 1254, 1254, 1254, 1254, 1254, 1254, + 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 0, + 0, 0, 0, 0, 1252, 1252, 1252, 1252, 1252, 1252, + 1280, 1280, 1292, 1289, 1280, 1280, 0, 1291, 1280, 1280, + 1280, 1280, 1280, 1280, 1280, 1280, 1280, 0, 1280, 1280, + 1280, 1280, 1280, 1282, 1282, 1282, 1282, 1282, 1282, 1282, + 1282, 1282, 1289, 1290, 1290, 1290, 1291, 0, 1290, 0, + + 1292, 1292, 1292, 1292, 1292, 1292, 1290, 0, 0, 1280, + 0, 1280, 1302, 1302, 1302, 1302, 1302, 1302, 1302, 1302, + 1302, 0, 0, 0, 0, 1289, 1289, 1289, 1289, 1289, + 1289, 1293, 1291, 1291, 1291, 1291, 1291, 1291, 1280, 1280, + 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, + 1280, 1280, 1280, 1280, 1281, 1281, 0, 1307, 1281, 1281, + 1293, 0, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, + 1281, 1308, 1281, 1281, 1281, 1281, 1281, 1788, 1789, 1790, + 1290, 1290, 1290, 1290, 1290, 1290, 1307, 1310, 1310, 1310, + 1310, 1310, 1310, 0, 1293, 1293, 1293, 1293, 1293, 1293, + + 0, 0, 0, 1281, 0, 1281, 1788, 1789, 1790, 1308, + 1308, 1308, 1308, 1308, 1308, 0, 0, 0, 0, 1307, + 1307, 1307, 1307, 1307, 1307, 1309, 1434, 1434, 1434, 1434, + 1434, 1434, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, + 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1300, 1300, + 0, 0, 1300, 1300, 1309, 1795, 1300, 1300, 1300, 1300, + 1300, 1300, 1300, 1300, 1300, 0, 1300, 1300, 1300, 1300, + 1300, 1314, 1314, 1314, 1314, 1314, 1314, 1314, 1314, 1314, + 1348, 1348, 1348, 1798, 1795, 1544, 1544, 1544, 1309, 1309, + 1309, 1309, 1309, 1309, 1348, 1821, 1838, 1300, 0, 1300, + + 1544, 0, 0, 1326, 1815, 1326, 1815, 0, 1819, 0, + 1819, 1327, 1798, 0, 0, 1326, 1815, 0, 0, 1327, + 1819, 0, 1351, 0, 1821, 1838, 1300, 1300, 1300, 1300, + 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, + 1300, 1300, 1301, 1301, 1326, 1815, 1301, 1301, 1327, 1819, + 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 0, + 1301, 1301, 1301, 1301, 1301, 0, 1435, 1348, 1348, 1348, + 1348, 1348, 1348, 1839, 1544, 0, 1326, 1326, 1326, 1326, + 1326, 1326, 1847, 1848, 1327, 1327, 1327, 1327, 1327, 1327, + 1432, 1301, 0, 1301, 1328, 1351, 1351, 1351, 1351, 1351, + + 1351, 1347, 1839, 1347, 1435, 1435, 1435, 1435, 1435, 1435, + 1328, 1847, 1848, 1347, 1853, 1352, 1388, 1388, 1388, 0, + 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, + 1301, 1301, 1301, 1301, 1301, 1301, 1312, 1312, 0, 1328, + 1312, 1312, 1347, 1853, 1312, 1312, 1312, 1312, 1312, 1312, + 1312, 1312, 1312, 1388, 1312, 1312, 1312, 1312, 1312, 0, + 0, 1432, 1432, 1432, 1432, 1432, 1432, 1328, 1328, 1328, + 1328, 1328, 1328, 0, 1347, 1347, 1347, 1347, 1347, 1347, + 1857, 1355, 1388, 1858, 1859, 1312, 0, 1312, 1352, 1352, + 1352, 1352, 1352, 1352, 0, 0, 0, 0, 0, 1349, + + 1479, 1479, 1479, 0, 1479, 1388, 0, 0, 1355, 1857, + 1357, 0, 1858, 1859, 1312, 1312, 1312, 1312, 1312, 1312, + 1312, 1312, 1312, 1312, 1312, 1312, 1312, 1312, 1312, 1312, + 1313, 1313, 1349, 0, 1313, 1313, 1357, 1355, 1313, 1313, + 1313, 1313, 1313, 1313, 1313, 1313, 1313, 0, 1313, 1313, + 1313, 1313, 1313, 1350, 1355, 1355, 1355, 1355, 1355, 1355, + 0, 1349, 1350, 1353, 1864, 1357, 0, 1866, 0, 1358, + 0, 0, 1349, 1349, 1349, 1349, 1349, 1349, 1868, 1313, + 0, 1313, 1354, 1357, 1357, 1357, 1357, 1357, 1357, 1479, + 0, 1350, 0, 1864, 1356, 1353, 1866, 1513, 1513, 1513, + + 1361, 0, 0, 1354, 1356, 0, 0, 1868, 1313, 1313, + 1313, 1313, 1313, 1313, 1313, 1313, 1313, 1313, 1313, 1313, + 1313, 1313, 1313, 1313, 1353, 1361, 1350, 1350, 1350, 1350, + 1350, 1350, 1354, 1356, 1513, 1867, 1353, 1353, 1353, 1353, + 1353, 1353, 1358, 1358, 1358, 1358, 1358, 1358, 0, 1359, + 0, 1869, 1870, 1867, 1361, 1354, 1354, 1354, 1354, 1354, + 1354, 1359, 1360, 1513, 1867, 1871, 1872, 1356, 1356, 1356, + 1356, 1356, 1356, 1361, 1361, 1361, 1361, 1361, 1361, 1362, + 1869, 1870, 1867, 0, 1360, 1874, 1513, 1363, 1875, 0, + 1359, 1362, 1876, 0, 1871, 1872, 1364, 0, 0, 1363, + + 0, 1877, 0, 1365, 1873, 1878, 0, 0, 0, 1368, + 0, 0, 1364, 1360, 1874, 1873, 1879, 1875, 1368, 1366, + 1362, 1876, 1359, 1359, 1359, 1359, 1359, 1359, 1363, 1365, + 1877, 1369, 0, 1873, 1878, 1360, 1360, 1360, 1360, 1360, + 1360, 1364, 0, 1367, 1873, 1879, 1366, 1368, 0, 1370, + 0, 0, 1362, 1362, 1362, 1362, 1362, 1362, 1365, 1367, + 1363, 1363, 1363, 1363, 1363, 1363, 1369, 1371, 0, 1364, + 1364, 1364, 1364, 1364, 1364, 1366, 1365, 1365, 1365, 1365, + 1365, 1365, 1368, 1368, 1368, 1368, 1368, 1368, 1367, 1372, + 0, 0, 1366, 1366, 1366, 1366, 1366, 1366, 1374, 0, + + 1880, 1881, 1371, 1372, 1369, 1369, 1369, 1369, 1369, 1369, + 1374, 1375, 0, 0, 0, 0, 1367, 1367, 1367, 1367, + 1367, 1367, 1370, 1370, 1370, 1370, 1370, 1370, 1373, 1880, + 1881, 0, 1372, 0, 1376, 0, 1560, 1560, 1560, 1374, + 1371, 1371, 1371, 1371, 1371, 1371, 1555, 1555, 1555, 0, + 1882, 1373, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, + 1378, 1376, 1372, 1372, 1372, 1372, 1372, 1372, 1380, 1555, + 1560, 1374, 1374, 1374, 1374, 1374, 1374, 0, 1379, 1882, + 1373, 0, 0, 0, 1375, 1375, 1375, 1375, 1375, 1375, + 1376, 1377, 1377, 1377, 1379, 1381, 0, 1883, 1555, 1560, + + 0, 1373, 1373, 1373, 1373, 1373, 1373, 1376, 1376, 1376, + 1376, 1376, 1376, 0, 0, 1382, 1382, 1382, 1383, 1377, + 1381, 1885, 0, 1379, 0, 1560, 1883, 0, 1377, 1382, + 1382, 1886, 1887, 1567, 1383, 1555, 1384, 1567, 1567, 0, + 0, 1380, 1380, 1380, 1380, 1380, 1380, 1386, 1377, 1381, + 1885, 1379, 1379, 1379, 1379, 1379, 1379, 1377, 1384, 1385, + 1886, 1887, 1567, 1383, 0, 0, 1567, 1567, 1381, 1381, + 1381, 1381, 1381, 1381, 1387, 1391, 1391, 1391, 0, 1884, + 1377, 1392, 0, 0, 0, 0, 1385, 1384, 1888, 1391, + 1912, 1383, 1383, 1383, 1383, 1383, 1383, 1393, 1915, 0, + + 1884, 1387, 1382, 1382, 1382, 1382, 1382, 1382, 1884, 1384, + 1384, 1384, 1384, 1384, 1384, 1385, 1415, 1888, 0, 1912, + 1386, 1386, 1386, 1386, 1386, 1386, 0, 1915, 1390, 1884, + 1387, 0, 1385, 1385, 1385, 1385, 1385, 1385, 1389, 1389, + 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1387, 1387, 1387, + 1387, 1387, 1387, 1390, 1392, 1392, 1392, 1392, 1392, 1392, + 1394, 0, 1391, 1391, 1391, 1391, 1391, 1391, 1395, 1916, + 1393, 1393, 1393, 1393, 1393, 1393, 0, 1396, 1920, 1923, + 1395, 0, 1390, 1397, 1397, 1397, 1394, 1396, 1398, 1415, + 1415, 1415, 1415, 1415, 1415, 0, 0, 1397, 1916, 1924, + + 1398, 1390, 1390, 1390, 1390, 1390, 1390, 1920, 1923, 1395, + 1399, 0, 0, 0, 0, 1394, 1396, 0, 1399, 1400, + 1450, 1450, 1450, 1450, 1450, 1450, 1401, 1925, 1924, 1398, + 1926, 0, 0, 1394, 1394, 1394, 1394, 1394, 1394, 1930, + 1400, 1395, 1395, 1395, 1395, 1395, 1395, 1399, 1401, 1402, + 1396, 1396, 1396, 1396, 1396, 1396, 1925, 0, 0, 1926, + 1449, 1398, 1398, 1398, 1398, 1398, 1398, 1417, 1930, 1400, + 1397, 1397, 1397, 1397, 1397, 1397, 1402, 1401, 2014, 2014, + 2014, 0, 0, 1399, 1399, 1399, 1399, 1399, 1399, 1449, + 0, 0, 1400, 1400, 1400, 1400, 1400, 1400, 0, 1401, + + 1401, 1401, 1401, 1401, 1401, 1402, 1411, 1411, 1411, 1411, + 1411, 1411, 1411, 1411, 1411, 1449, 1449, 1449, 1449, 1449, + 1449, 1934, 1402, 1402, 1402, 1402, 1402, 1402, 1412, 1412, + 1412, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, + 1417, 1417, 1417, 1417, 1417, 1417, 1414, 1437, 1956, 0, + 1934, 1412, 1412, 1412, 1412, 1412, 1412, 1419, 1412, 1973, + 1412, 1414, 1412, 1418, 1974, 1412, 1979, 2014, 1412, 1412, + 1416, 0, 1412, 1982, 1418, 1983, 1437, 1956, 1420, 0, + 1412, 1412, 1412, 1412, 1412, 1412, 1420, 1412, 1973, 1412, + 1414, 1412, 1421, 1974, 1412, 1979, 1416, 1412, 1412, 1422, + + 1421, 1412, 1982, 1418, 1983, 1426, 1437, 1437, 1437, 1437, + 1437, 1437, 1684, 1684, 1684, 1420, 1423, 1412, 0, 1414, + 1414, 1414, 1414, 1414, 1414, 1416, 0, 1684, 1423, 1421, + 1419, 1419, 1419, 1419, 1419, 1419, 1418, 1418, 1418, 1418, + 1418, 1418, 0, 1416, 1416, 1416, 1416, 1416, 1416, 0, + 0, 1420, 1420, 1420, 1420, 1420, 1420, 1423, 0, 1424, + 0, 0, 0, 0, 0, 1421, 1421, 1421, 1421, 1421, + 1421, 1424, 1422, 1422, 1422, 1422, 1422, 1422, 1426, 1426, + 1426, 1426, 1426, 1426, 1425, 1951, 1954, 1951, 1954, 1423, + 1423, 1423, 1423, 1423, 1423, 1425, 1427, 1951, 1954, 0, + + 1424, 1684, 1428, 1486, 0, 0, 0, 0, 1430, 0, + 1987, 1428, 0, 0, 0, 0, 0, 1429, 1989, 1990, + 1991, 1996, 1427, 1997, 1425, 1998, 1951, 1954, 1441, 0, + 0, 0, 1424, 1424, 1424, 1424, 1424, 1424, 1429, 1987, + 1428, 1486, 1486, 1486, 1486, 1486, 1486, 1989, 1990, 1991, + 1996, 1427, 1997, 0, 1998, 0, 0, 1425, 1425, 1425, + 1425, 1425, 1425, 1441, 0, 0, 0, 1429, 1433, 1427, + 1427, 1427, 1427, 1427, 1427, 1428, 1428, 1428, 1428, 1428, + 1428, 1430, 1430, 1430, 1430, 1430, 1430, 1436, 1439, 1999, + 1429, 1429, 1429, 1429, 1429, 1429, 1440, 1433, 0, 0, + + 2000, 1441, 1441, 1441, 1441, 1441, 1441, 2001, 2002, 1442, + 2004, 2005, 1440, 2006, 2007, 1439, 1436, 1443, 1999, 0, + 1433, 1433, 1433, 1433, 1433, 1433, 0, 1442, 1443, 2000, + 2008, 0, 1444, 0, 0, 0, 2001, 2002, 1446, 2004, + 2005, 1440, 2006, 2007, 1439, 0, 0, 2009, 1445, 2010, + 1436, 1436, 1436, 1436, 1436, 1436, 1442, 1443, 1498, 2008, + 1446, 1439, 1439, 1439, 1439, 1439, 1439, 1444, 1448, 1440, + 1440, 1440, 1440, 1440, 1440, 1445, 2009, 1447, 2010, 0, + 0, 0, 1442, 1442, 1442, 1442, 1442, 1442, 1447, 1446, + 1443, 1443, 1443, 1443, 1443, 1443, 1498, 1498, 1498, 1498, + + 1498, 1498, 2011, 1448, 1445, 1444, 1444, 1444, 1444, 1444, + 1444, 1446, 1446, 1446, 1446, 1446, 1446, 1447, 1517, 1491, + 2012, 1445, 1445, 1445, 1445, 1445, 1445, 0, 1493, 2013, + 0, 2011, 0, 0, 1487, 1487, 1487, 0, 0, 1487, + 1492, 1448, 1448, 1448, 1448, 1448, 1448, 1487, 1491, 2012, + 1447, 1447, 1447, 1447, 1447, 1447, 1499, 1493, 2013, 1487, + 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1492, + 0, 0, 0, 1491, 1491, 1491, 1491, 1491, 1491, 1493, + 1493, 1493, 1493, 1493, 1493, 1499, 0, 0, 1487, 0, + 2015, 1517, 1517, 1517, 1517, 1517, 1517, 1492, 1492, 1492, + + 1492, 1492, 1492, 1514, 1514, 1514, 1514, 1514, 1514, 1514, + 1514, 1514, 0, 1499, 1499, 1499, 1499, 1499, 1499, 2015, + 0, 0, 0, 1487, 1488, 1488, 1488, 1488, 1488, 1488, + 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, + 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, + 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, + 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, + 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, + 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, + 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, + + 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, + 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1500, 1504, + 2016, 1504, 0, 2018, 2019, 0, 0, 1505, 0, 2020, + 2021, 1504, 0, 1506, 0, 0, 0, 0, 0, 1512, + 0, 1512, 0, 0, 0, 1515, 1505, 1500, 0, 2016, + 2022, 1512, 2018, 2019, 1519, 1506, 2023, 1515, 2020, 2021, + 1504, 1604, 1604, 1604, 1604, 1604, 1604, 1522, 0, 1500, + 1500, 1500, 1500, 1500, 1500, 1505, 1694, 1694, 1694, 2022, + 1512, 0, 0, 0, 1506, 2023, 1515, 0, 2122, 2122, + 2122, 1694, 1504, 1504, 1504, 1504, 1504, 1504, 1516, 0, + + 1505, 1505, 1505, 1505, 1505, 1505, 1506, 1506, 1506, 1506, + 1506, 1506, 1512, 1512, 1512, 1512, 1512, 1512, 1515, 1515, + 1515, 1515, 1515, 1515, 1518, 2024, 1516, 1519, 1519, 1519, + 1519, 1519, 1519, 1520, 2039, 0, 0, 0, 2040, 1521, + 1522, 1522, 1522, 1522, 1522, 1522, 1523, 1526, 1526, 1526, + 2041, 1518, 1524, 2043, 2024, 1516, 1523, 2044, 2045, 2046, + 1520, 1526, 1526, 2039, 1524, 1694, 1521, 2040, 0, 0, + 1528, 1516, 1516, 1516, 1516, 1516, 1516, 2122, 0, 2041, + 1518, 1534, 2043, 0, 0, 1523, 2044, 2045, 2046, 1520, + 0, 0, 1525, 1524, 0, 1521, 0, 1518, 1518, 1518, + + 1518, 1518, 1518, 1525, 0, 0, 1520, 1520, 1520, 1520, + 1520, 1520, 1521, 1521, 1521, 1521, 1521, 1521, 1536, 1523, + 1523, 1523, 1523, 1523, 1523, 1524, 1524, 1524, 1524, 1524, + 1524, 2078, 1525, 1527, 1526, 1526, 1526, 1526, 1526, 1526, + 1529, 0, 1527, 1528, 1528, 1528, 1528, 1528, 1528, 2084, + 2091, 1530, 1529, 2093, 1534, 1534, 1534, 1534, 1534, 1534, + 2078, 2073, 0, 2073, 0, 1525, 1525, 1525, 1525, 1525, + 1525, 1527, 1530, 2073, 0, 1531, 0, 0, 2084, 2091, + 0, 1529, 2093, 1531, 1537, 1537, 1537, 0, 1755, 1755, + 1755, 1536, 1536, 1536, 1536, 1536, 1536, 0, 1537, 1537, + + 0, 1530, 2073, 1755, 2094, 1532, 1527, 1527, 1527, 1527, + 1527, 1527, 1531, 1529, 1529, 1529, 1529, 1529, 1529, 1533, + 0, 0, 0, 0, 1530, 1530, 1530, 1530, 1530, 1530, + 1532, 1535, 0, 2094, 0, 0, 0, 1542, 0, 0, + 1533, 1607, 1607, 1607, 1607, 1607, 1607, 0, 1531, 1531, + 1531, 1531, 1531, 1531, 1543, 0, 1535, 2099, 1542, 1532, + 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1533, + 1543, 1537, 1537, 1537, 1537, 1537, 1537, 1755, 1532, 1532, + 1532, 1532, 1532, 1532, 1549, 1535, 2099, 1542, 0, 2047, + 2047, 2047, 1533, 1533, 1533, 1533, 1533, 1533, 1547, 1543, + + 0, 0, 0, 2047, 1535, 1535, 1535, 1535, 1535, 1535, + 1542, 1542, 1542, 1542, 1542, 1542, 1546, 1546, 1546, 1546, + 1546, 1546, 1546, 1546, 1546, 1547, 1554, 1543, 1543, 1543, + 1543, 1543, 1543, 1548, 2102, 2107, 0, 2108, 1554, 1550, + 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 0, + 1557, 2109, 1548, 2110, 1547, 1550, 1558, 1549, 1549, 1549, + 1549, 1549, 1549, 2102, 2107, 1557, 2108, 1554, 2113, 2115, + 0, 1547, 1547, 1547, 1547, 1547, 1547, 1562, 2047, 0, + 2109, 1548, 2110, 0, 1550, 1556, 1556, 1556, 1556, 1556, + 1556, 1556, 1556, 1556, 1557, 0, 0, 2113, 2115, 1554, + + 1554, 1554, 1554, 1554, 1554, 1592, 1548, 1548, 1548, 1548, + 1548, 1548, 1550, 1550, 1550, 1550, 1550, 1550, 0, 2116, + 2117, 0, 0, 1557, 1557, 1557, 1557, 1557, 1557, 1558, + 1558, 1558, 1558, 1558, 1558, 1559, 1561, 1561, 1561, 1561, + 1561, 1561, 1561, 1561, 1561, 0, 1563, 1559, 2116, 2117, + 1562, 1562, 1562, 1562, 1562, 1562, 1563, 1564, 0, 0, + 1566, 1566, 1566, 0, 0, 2076, 2118, 2076, 1565, 1564, + 2119, 2120, 2121, 2124, 1566, 1566, 1559, 2076, 1592, 1592, + 1592, 1592, 1592, 1592, 1593, 1563, 1590, 1590, 1590, 1590, + 1590, 1590, 1590, 1590, 1590, 2118, 1565, 1594, 1564, 2119, + + 2120, 2121, 2124, 0, 1591, 0, 2076, 1594, 1559, 1559, + 1559, 1559, 1559, 1559, 1596, 0, 0, 0, 0, 1563, + 1563, 1563, 1563, 1563, 1563, 1565, 1591, 1595, 0, 0, + 1564, 1564, 1564, 1564, 1564, 1564, 1594, 1599, 2125, 2126, + 2127, 1565, 1565, 1565, 1565, 1565, 1565, 1566, 1566, 1566, + 1566, 1566, 1566, 1598, 1595, 1591, 0, 1593, 1593, 1593, + 1593, 1593, 1593, 1603, 2128, 1598, 0, 2125, 2126, 2127, + 1594, 1594, 1594, 1594, 1594, 1594, 1600, 1591, 1591, 1591, + 1591, 1591, 1591, 1595, 1597, 1597, 1597, 1596, 1596, 1596, + 1596, 1596, 1596, 2128, 1598, 1600, 1605, 0, 1597, 1597, + + 1595, 1595, 1595, 1595, 1595, 1595, 0, 0, 0, 0, + 1599, 1599, 1599, 1599, 1599, 1599, 0, 0, 1601, 0, + 0, 0, 0, 0, 1600, 1605, 1598, 1598, 1598, 1598, + 1598, 1598, 1601, 1606, 1603, 1603, 1603, 1603, 1603, 1603, + 2129, 2130, 1605, 1605, 1605, 1605, 1605, 1605, 1612, 1600, + 1600, 1600, 1600, 1600, 1600, 0, 1608, 0, 0, 0, + 0, 1601, 1606, 1850, 1850, 1850, 0, 1609, 1608, 2129, + 2130, 1597, 1597, 1597, 1597, 1597, 1597, 1609, 1850, 2131, + 2132, 2133, 1610, 2136, 1606, 1606, 1606, 1606, 1606, 1606, + 2137, 1601, 1601, 1601, 1601, 1601, 1601, 1608, 1610, 1615, + + 0, 0, 0, 0, 0, 1611, 1609, 1615, 2131, 2132, + 2133, 0, 2136, 1614, 0, 0, 0, 1611, 0, 2137, + 2138, 1612, 1612, 1612, 1612, 1612, 1612, 1610, 1616, 1608, + 1608, 1608, 1608, 1608, 1608, 0, 1615, 2139, 2141, 0, + 1609, 1609, 1609, 1609, 1609, 1609, 1611, 1613, 1614, 2138, + 0, 0, 1850, 1617, 0, 1610, 1610, 1610, 1610, 1610, + 1610, 0, 0, 1613, 1640, 0, 2139, 2141, 1613, 1617, + 0, 1618, 1615, 1615, 1615, 1615, 1615, 1615, 1611, 1611, + 1611, 1611, 1611, 1611, 0, 0, 1614, 1614, 1614, 1614, + 1614, 1614, 1613, 1640, 1641, 1641, 1641, 1613, 1617, 1641, + + 1618, 1616, 1616, 1616, 1616, 1616, 1616, 1641, 0, 0, + 0, 0, 1640, 1640, 1640, 1640, 1640, 1640, 0, 1641, + 1613, 1613, 1613, 1613, 1613, 1613, 1617, 1617, 1617, 1617, + 1617, 1617, 1618, 1618, 1618, 1618, 1618, 1618, 1644, 1644, + 1644, 0, 0, 1644, 1645, 1645, 1645, 1659, 1641, 1645, + 2142, 1644, 2143, 1648, 1648, 1648, 2144, 1645, 1648, 2148, + 0, 2158, 2161, 1644, 2162, 2163, 1648, 2164, 2169, 1645, + 1658, 1658, 1658, 1658, 1658, 1658, 1659, 2190, 1648, 2142, + 0, 2143, 0, 1641, 0, 2144, 0, 0, 2148, 1660, + 2158, 2161, 1644, 2162, 2163, 0, 2164, 2169, 1645, 1659, + + 1659, 1659, 1659, 1659, 1659, 0, 2190, 1648, 1657, 1657, + 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1664, 1660, 0, + 0, 1662, 2195, 1663, 1763, 2197, 2198, 1644, 2202, 1668, + 0, 2203, 0, 1645, 1660, 1660, 1660, 1660, 1660, 1660, + 1669, 0, 1648, 1650, 1650, 1650, 1664, 2182, 1650, 2182, + 1662, 2195, 1663, 1763, 2197, 2198, 1650, 2202, 2206, 2182, + 2203, 1669, 1664, 1664, 1664, 1664, 1664, 1664, 1650, 1662, + 1662, 1662, 1662, 1662, 1662, 1663, 1663, 1663, 1663, 1663, + 1663, 1763, 1763, 1763, 1763, 1763, 1763, 2206, 2182, 1667, + 1669, 1667, 0, 0, 0, 0, 1672, 1650, 1672, 0, + + 0, 1667, 1668, 1668, 1668, 1668, 1668, 1668, 1672, 0, + 2221, 2221, 2221, 1669, 1669, 1669, 1669, 1669, 1669, 1676, + 0, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, + 1667, 1678, 1650, 1651, 1651, 1651, 0, 1672, 1651, 1910, + 1910, 1910, 1910, 1910, 1910, 0, 1651, 1675, 1675, 1675, + 1675, 1675, 1675, 1675, 1675, 1675, 2208, 2209, 1651, 0, + 2210, 2211, 1667, 1667, 1667, 1667, 1667, 1667, 1682, 1672, + 1672, 1672, 1672, 1672, 1672, 0, 1677, 0, 0, 2185, + 0, 2185, 1679, 0, 0, 2208, 2209, 1651, 1680, 2210, + 2211, 2185, 1676, 1676, 1676, 1676, 1676, 1676, 1679, 2221, + + 1680, 2214, 2216, 1677, 1678, 1678, 1678, 1678, 1678, 1678, + 1683, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, + 2185, 0, 1651, 1652, 1652, 1652, 0, 1679, 1652, 1680, + 2214, 2216, 1677, 0, 0, 0, 1652, 0, 0, 0, + 0, 1682, 1682, 1682, 1682, 1682, 1682, 1688, 1652, 1677, + 1677, 1677, 1677, 1677, 1677, 1679, 1679, 1679, 1679, 1679, + 1679, 1680, 1680, 1680, 1680, 1680, 1680, 2068, 2068, 2068, + 2068, 2068, 2068, 1681, 2222, 2222, 2222, 1652, 0, 1689, + 0, 1681, 0, 1683, 1683, 1683, 1683, 1683, 1683, 1686, + 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 0, 1687, + + 0, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, + 1681, 1687, 1652, 1653, 1653, 1653, 2217, 0, 1653, 0, + 1688, 1688, 1688, 1688, 1688, 1688, 1653, 1696, 1696, 1696, + 1696, 1696, 1696, 1696, 1696, 1696, 1691, 0, 1653, 1774, + 1687, 2227, 2227, 2227, 1693, 2217, 1681, 1681, 1681, 1681, + 1681, 1681, 1689, 1689, 1689, 1689, 1689, 1689, 1691, 2218, + 1693, 1690, 0, 2222, 1977, 1977, 1977, 1653, 1774, 0, + 1692, 1690, 1687, 1687, 1687, 1687, 1687, 1687, 1692, 1977, + 1774, 1774, 1774, 1774, 1774, 1774, 2219, 1691, 2218, 1693, + 0, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, + + 1690, 1700, 1653, 1654, 1654, 1654, 0, 1692, 1654, 1691, + 1691, 1691, 1691, 1691, 1691, 2219, 1654, 1693, 1693, 1693, + 1693, 1693, 1693, 2220, 0, 2187, 0, 1700, 1654, 0, + 2227, 2167, 2167, 2167, 1690, 1690, 1690, 1690, 1690, 1690, + 2187, 2225, 0, 1692, 1692, 1692, 1692, 1692, 1692, 1701, + 0, 0, 2220, 1977, 2187, 1705, 1700, 1654, 1704, 1704, + 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1706, 2229, 2187, + 2225, 1701, 2167, 2231, 1700, 1700, 1700, 1700, 1700, 1700, + 1710, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, + 2232, 1714, 1654, 1655, 1655, 1655, 0, 2229, 1655, 0, + + 1701, 2167, 2231, 0, 0, 0, 1655, 0, 0, 0, + 2234, 0, 1707, 0, 0, 0, 0, 2235, 1655, 2232, + 2167, 0, 1701, 1701, 1701, 1701, 1701, 1701, 1705, 1705, + 1705, 1705, 1705, 1705, 1707, 1715, 1715, 1715, 1720, 2234, + 1706, 1706, 1706, 1706, 1706, 1706, 2235, 1655, 0, 1715, + 1715, 0, 0, 1710, 1710, 1710, 1710, 1710, 1710, 0, + 0, 0, 1719, 1707, 1714, 1714, 1714, 1714, 1714, 1714, + 0, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, + 1719, 1758, 1655, 0, 0, 1707, 1707, 1707, 1707, 1707, + 1707, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, + + 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1719, + 1721, 1720, 1720, 1720, 1720, 1720, 1720, 0, 0, 0, + 0, 2236, 1715, 1715, 1715, 1715, 1715, 1715, 1722, 1722, + 1722, 1721, 0, 2238, 1752, 1719, 1719, 1719, 1719, 1719, + 1719, 0, 0, 1722, 0, 2228, 2228, 2228, 1753, 1722, + 2236, 2239, 2241, 1722, 1758, 1758, 1758, 1758, 1758, 1758, + 1721, 1752, 2238, 2243, 1754, 1722, 1724, 1724, 1724, 1724, + 1724, 1724, 1724, 1724, 1724, 1753, 1754, 1759, 0, 0, + 2239, 2241, 1722, 1721, 1721, 1721, 1721, 1721, 1721, 1759, + 1752, 0, 2243, 1760, 1722, 1757, 1757, 1757, 1757, 1757, + + 1757, 1757, 1757, 1757, 1753, 1754, 1762, 1752, 1752, 1752, + 1752, 1752, 1752, 0, 0, 0, 0, 1722, 1759, 1760, + 1765, 1753, 1753, 1753, 1753, 1753, 1753, 1766, 2082, 2082, + 2082, 1764, 2242, 1767, 2228, 2242, 2244, 1754, 1754, 1754, + 1754, 1754, 1754, 2082, 1767, 1765, 2245, 2248, 1760, 0, + 1759, 1759, 1759, 1759, 1759, 1759, 0, 1768, 0, 0, + 1764, 2242, 1766, 2249, 2242, 2244, 1760, 1760, 1760, 1760, + 1760, 1760, 0, 1767, 1765, 2245, 2248, 1762, 1762, 1762, + 1762, 1762, 1762, 1764, 1764, 1764, 1764, 1764, 1764, 1768, + 0, 1770, 2249, 1765, 1765, 1765, 1765, 1765, 1765, 1770, + + 1766, 1766, 1766, 1766, 1766, 1766, 1767, 1767, 1767, 1767, + 1767, 1767, 1769, 0, 2089, 2089, 2089, 2082, 1768, 1791, + 0, 2250, 0, 1769, 0, 0, 0, 0, 1770, 2089, + 1768, 1768, 1768, 1768, 1768, 1768, 1771, 0, 0, 0, + 0, 0, 1772, 0, 0, 0, 0, 1771, 1791, 1809, + 2250, 1773, 1769, 1772, 2071, 2071, 2071, 2071, 2071, 2071, + 0, 0, 1773, 0, 1770, 1770, 1770, 1770, 1770, 1770, + 1791, 1791, 1791, 1791, 1791, 1791, 1771, 2252, 1809, 1792, + 1792, 1792, 1772, 0, 1792, 1769, 1769, 1769, 1769, 1769, + 1769, 1773, 1792, 1845, 1845, 1845, 1809, 1809, 1809, 1809, + + 1809, 1809, 0, 2089, 1792, 2253, 2252, 0, 0, 1771, + 1771, 1771, 1771, 1771, 1771, 1772, 1772, 1772, 1772, 1772, + 1772, 0, 1845, 0, 1773, 1773, 1773, 1773, 1773, 1773, + 1793, 1793, 1793, 1792, 2253, 1793, 1794, 1794, 1794, 0, + 1810, 1794, 2257, 1793, 0, 1797, 1797, 1797, 0, 1794, + 1797, 1845, 1807, 1807, 1807, 1793, 1811, 1807, 1797, 2265, + 2266, 1794, 2268, 0, 0, 1807, 0, 0, 1792, 1810, + 1797, 2257, 1793, 1804, 1804, 1804, 1813, 1807, 1804, 0, + 0, 0, 1845, 0, 1793, 1811, 1804, 0, 2265, 2266, + 1794, 2268, 1810, 1810, 1810, 1810, 1810, 1810, 1804, 1797, + + 1817, 1793, 2097, 2097, 2097, 1813, 1807, 1811, 1811, 1811, + 1811, 1811, 1811, 0, 1794, 0, 1812, 2097, 2269, 1793, + 2271, 2274, 2230, 2230, 2230, 1794, 0, 1804, 1813, 1813, + 1813, 1813, 1813, 1813, 1797, 1799, 1799, 1799, 0, 0, + 1799, 1807, 2166, 2166, 2166, 1812, 0, 2269, 1799, 2271, + 2274, 1804, 1804, 0, 0, 1804, 2166, 1804, 1804, 1804, + 1799, 1898, 1804, 1812, 1812, 1812, 1812, 1812, 1812, 1816, + 2285, 1816, 0, 1817, 1817, 1817, 1817, 1817, 1817, 0, + 0, 1816, 1820, 2246, 1820, 0, 0, 0, 1823, 1799, + 0, 2097, 0, 2246, 1820, 0, 0, 0, 0, 2285, + + 1823, 1829, 1829, 1829, 1829, 1829, 1829, 1829, 1829, 1829, + 1816, 2230, 2246, 1799, 1799, 1799, 1799, 1799, 1799, 1799, + 1799, 1799, 2246, 1820, 1799, 1800, 1800, 1800, 0, 1823, + 1800, 2166, 1898, 1898, 1898, 1898, 1898, 1898, 1800, 0, + 1927, 0, 1816, 1816, 1816, 1816, 1816, 1816, 1824, 2286, + 1800, 0, 2288, 2291, 0, 1820, 1820, 1820, 1820, 1820, + 1820, 1823, 1823, 1823, 1823, 1823, 1823, 0, 1825, 1927, + 1824, 2292, 0, 0, 1826, 2240, 2240, 2240, 2286, 1800, + 1830, 2288, 2291, 1927, 1927, 1927, 1927, 1927, 1927, 1825, + 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1824, + + 2292, 1826, 1832, 1800, 1800, 1800, 1800, 1800, 1800, 1800, + 1800, 1800, 0, 1831, 1800, 1801, 1801, 1801, 1825, 0, + 1801, 1824, 1824, 1824, 1824, 1824, 1824, 0, 1801, 0, + 1826, 1831, 1832, 2170, 2170, 2170, 2170, 2170, 2170, 1855, + 1801, 1825, 1825, 1825, 1825, 1825, 1825, 1826, 1826, 1826, + 1826, 1826, 1826, 1830, 1830, 1830, 1830, 1830, 1830, 0, + 1831, 1832, 1833, 0, 2240, 0, 2111, 2111, 2111, 1801, + 1834, 0, 0, 0, 2293, 1832, 1832, 1832, 1832, 1832, + 1832, 2111, 1833, 0, 0, 0, 1831, 1831, 1831, 1831, + 1831, 1831, 1834, 1801, 1801, 1801, 1801, 1801, 1801, 1801, + + 1801, 1801, 1841, 2293, 1801, 1802, 1802, 1802, 0, 0, + 1802, 1833, 1855, 1855, 1855, 1855, 1855, 1855, 1802, 0, + 2300, 1834, 0, 2303, 2304, 2307, 0, 1841, 0, 1840, + 1802, 0, 2296, 2296, 2296, 1833, 1833, 1833, 1833, 1833, + 1833, 1840, 2308, 1834, 1834, 1834, 1834, 1834, 1834, 2300, + 0, 1846, 2303, 2304, 2307, 2111, 1841, 1889, 0, 1802, + 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 2309, + 1840, 2308, 1846, 0, 0, 1841, 1841, 1841, 1841, 1841, + 1841, 0, 1856, 1802, 1802, 1802, 1802, 1802, 1802, 1802, + 1802, 1802, 1891, 1900, 1802, 1803, 1803, 1803, 2309, 0, + + 1803, 1846, 1840, 1840, 1840, 1840, 1840, 1840, 1803, 1856, + 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 2310, + 1803, 2296, 1900, 0, 1846, 1846, 1846, 1846, 1846, 1846, + 1889, 1889, 1889, 1889, 1889, 1889, 0, 0, 1856, 1896, + 1900, 1900, 1900, 1900, 1900, 1900, 1890, 0, 2310, 1803, + 0, 2280, 2283, 2280, 2283, 1856, 1856, 1856, 1856, 1856, + 1856, 0, 1890, 2280, 2283, 1891, 1891, 1891, 1891, 1891, + 1891, 1895, 0, 1803, 1803, 1803, 1803, 1803, 1803, 1803, + 1803, 1803, 2312, 0, 1803, 1805, 1805, 1805, 0, 0, + 1805, 1890, 2280, 2283, 0, 0, 2317, 1895, 1805, 1894, + + 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 0, 0, + 1805, 2312, 1896, 1896, 1896, 1896, 1896, 1896, 1901, 1890, + 1890, 1890, 1890, 1890, 1890, 2317, 1895, 0, 1899, 0, + 2319, 1964, 1964, 1964, 1902, 0, 2146, 2146, 2146, 1805, + 1903, 2188, 2188, 2188, 1895, 1895, 1895, 1895, 1895, 1895, + 1902, 2146, 0, 1901, 0, 0, 2188, 1899, 1904, 2319, + 1964, 2327, 0, 1805, 1805, 1805, 1805, 1805, 1805, 1805, + 1805, 1805, 1905, 0, 1805, 1806, 1806, 1806, 0, 1902, + 1806, 1899, 1899, 1899, 1899, 1899, 1899, 0, 1806, 1964, + 2327, 1901, 1901, 1901, 1901, 1901, 1901, 2329, 2330, 0, + + 1806, 0, 1906, 0, 0, 0, 0, 1902, 1902, 1902, + 1902, 1902, 1902, 1903, 1903, 1903, 1903, 1903, 1903, 1908, + 1964, 0, 1906, 1946, 0, 2146, 2329, 2330, 1907, 1806, + 2188, 1904, 1904, 1904, 1904, 1904, 1904, 1907, 1909, 2179, + 2179, 2179, 2179, 2179, 2179, 1905, 1905, 1905, 1905, 1905, + 1905, 1906, 1946, 1806, 1806, 1806, 1806, 1806, 1806, 1806, + 1806, 1806, 2334, 0, 1806, 0, 1907, 0, 0, 1946, + 1946, 1946, 1946, 1946, 1946, 1906, 1906, 1906, 1906, 1906, + 1906, 2297, 2297, 2297, 0, 1928, 1928, 1928, 0, 0, + 1928, 2334, 1908, 1908, 1908, 1908, 1908, 1908, 1928, 0, + + 0, 1907, 1907, 1907, 1907, 1907, 1907, 1928, 0, 0, + 1928, 1909, 1909, 1909, 1909, 1909, 1909, 1929, 1929, 1929, + 0, 0, 1929, 0, 1931, 1931, 1931, 0, 1945, 1931, + 1929, 0, 0, 1932, 1932, 1932, 1928, 1931, 1932, 1928, + 2335, 0, 1929, 1933, 1933, 1933, 1932, 2336, 1933, 1931, + 1938, 1938, 1938, 2337, 2338, 1938, 1933, 1945, 1932, 2339, + 1939, 1939, 1939, 1938, 0, 1939, 0, 2340, 1933, 2335, + 2297, 1929, 2341, 1939, 1928, 1938, 2336, 0, 1931, 1972, + 1972, 1972, 2337, 2338, 0, 1939, 0, 1932, 2339, 1945, + 1945, 1945, 1945, 1945, 1945, 1929, 2340, 1933, 1948, 0, + + 2342, 2341, 2344, 0, 1938, 0, 1929, 2345, 1972, 0, + 0, 0, 2346, 1931, 1939, 1940, 1940, 1940, 0, 2347, + 1940, 1933, 1932, 0, 0, 0, 0, 1948, 1940, 2342, + 0, 2344, 1933, 1937, 1937, 1937, 2345, 1972, 1937, 1938, + 1940, 2346, 1941, 1941, 1941, 1947, 1937, 1941, 2347, 1939, + 2348, 1949, 1942, 1942, 1942, 1941, 2351, 1942, 1937, 1948, + 1948, 1948, 1948, 1948, 1948, 1942, 0, 1941, 1972, 1940, + 1943, 1943, 1943, 0, 1947, 1943, 2358, 1942, 1957, 2348, + 1949, 0, 0, 1943, 0, 2351, 0, 1937, 1947, 1947, + 1947, 1947, 1947, 1947, 1942, 1943, 1941, 1949, 1949, 1949, + + 1949, 1949, 1949, 2359, 1940, 2358, 1942, 2033, 1952, 2361, + 1952, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, + 1952, 0, 1937, 1942, 1943, 1955, 0, 1955, 0, 2364, + 0, 1941, 2359, 1978, 1978, 1978, 2033, 1955, 2361, 1958, + 0, 1942, 0, 0, 0, 2374, 0, 2375, 1943, 1952, + 1959, 1957, 1957, 1957, 1957, 1957, 1957, 1965, 2364, 1943, + 1958, 0, 1978, 1960, 2379, 2380, 1955, 2387, 2033, 2033, + 2033, 2033, 2033, 2033, 2374, 1960, 2375, 1959, 1967, 2388, + 2389, 1952, 1952, 1952, 1952, 1952, 1952, 2032, 0, 1958, + 1967, 1978, 1966, 2379, 2380, 0, 2387, 0, 1955, 1955, + + 1955, 1955, 1955, 1955, 1960, 1976, 1959, 0, 2388, 2389, + 0, 1981, 1958, 1958, 1958, 1958, 1958, 1958, 1966, 1967, + 1968, 1976, 1978, 1959, 1959, 1959, 1959, 1959, 1959, 0, + 1965, 1965, 1965, 1965, 1965, 1965, 1960, 1960, 1960, 1960, + 1960, 1960, 0, 2390, 2395, 1968, 1975, 1966, 0, 0, + 1976, 1967, 1967, 1967, 1967, 1967, 1967, 1988, 2032, 2032, + 2032, 2032, 2032, 2032, 0, 1966, 1966, 1966, 1966, 1966, + 1966, 1975, 2390, 2395, 1968, 0, 0, 2025, 1976, 1976, + 1976, 1976, 1976, 1976, 1981, 1981, 1981, 1981, 1981, 1981, + 0, 0, 0, 1968, 1968, 1968, 1968, 1968, 1968, 2025, + + 1975, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, + 1995, 1995, 1995, 2029, 2029, 2029, 2030, 2034, 0, 1975, + 1975, 1975, 1975, 1975, 1975, 0, 0, 0, 2025, 0, + 1988, 1988, 1988, 1988, 1988, 1988, 0, 0, 2399, 1995, + 2035, 2402, 2029, 2403, 2405, 0, 2034, 2036, 0, 0, + 2025, 2025, 2025, 2025, 2025, 2025, 2049, 2037, 2036, 2313, + 2313, 2313, 0, 0, 0, 2038, 2035, 2399, 1995, 2037, + 2402, 2029, 2403, 2405, 2034, 2034, 2034, 2034, 2034, 2034, + 2406, 2408, 2193, 2193, 2193, 2049, 0, 2036, 0, 2030, + 2030, 2030, 2030, 2030, 2030, 2035, 0, 2193, 2037, 1995, + + 2038, 0, 2029, 2049, 2049, 2049, 2049, 2049, 2049, 2406, + 2408, 0, 0, 2035, 2035, 2035, 2035, 2035, 2035, 0, + 2036, 2036, 2036, 2036, 2036, 2036, 2315, 2315, 2315, 2411, + 2037, 2037, 2037, 2037, 2037, 2037, 0, 0, 2038, 2038, + 2038, 2038, 2038, 2038, 2050, 2050, 2050, 2410, 2313, 2050, + 2052, 2052, 2052, 0, 2412, 2052, 2410, 2050, 2411, 2053, + 2053, 2053, 0, 2052, 2053, 2054, 2054, 2054, 0, 2050, + 2054, 2193, 2053, 2413, 2414, 2052, 2410, 2050, 2054, 0, + 2055, 2055, 2055, 2412, 2053, 2055, 2056, 2056, 2056, 0, + 2054, 2056, 0, 2055, 0, 2057, 2057, 2057, 2050, 2056, + + 2057, 2416, 2413, 2414, 2052, 2055, 2050, 2417, 2057, 2419, + 0, 2056, 0, 2053, 2420, 2315, 2058, 2058, 2058, 2054, + 2057, 2058, 2060, 2060, 2060, 0, 2422, 2060, 2056, 2058, + 2416, 0, 2423, 2050, 2055, 2060, 2417, 0, 2419, 2052, + 2056, 2058, 0, 2420, 2369, 2424, 2369, 2060, 2053, 2057, + 0, 2204, 2204, 2204, 2054, 2422, 2369, 2056, 2061, 2061, + 2061, 2423, 0, 2061, 0, 0, 2204, 0, 2425, 2055, + 2058, 2061, 2426, 2057, 2424, 2056, 2060, 2062, 2062, 2062, + 0, 0, 2062, 2061, 2057, 2369, 2372, 0, 2372, 0, + 2062, 2063, 2063, 2063, 2058, 0, 2063, 2425, 2372, 2079, + + 0, 2426, 2062, 2067, 2063, 2058, 2437, 0, 2064, 2064, + 2064, 2060, 2061, 2064, 2418, 2418, 2063, 2065, 2065, 2065, + 0, 2064, 2065, 0, 2066, 2066, 2066, 2372, 0, 2066, + 2065, 2062, 2067, 2064, 2069, 2437, 2061, 2066, 2438, 2065, + 2204, 2070, 2065, 2418, 2418, 2063, 2074, 2061, 2074, 2066, + 0, 2067, 2067, 2067, 2067, 2067, 2067, 2080, 2074, 2083, + 2083, 2083, 2064, 2069, 0, 2081, 2062, 2438, 2065, 2063, + 2070, 2065, 2079, 2079, 2079, 2079, 2079, 2079, 2066, 2086, + 2063, 2069, 2069, 2069, 2069, 2069, 2069, 2074, 2083, 2070, + 2070, 2070, 2070, 2070, 2070, 0, 2077, 2064, 2077, 2212, + + 2212, 2212, 2066, 2087, 0, 0, 2065, 0, 2077, 0, + 0, 0, 0, 2066, 2212, 0, 2439, 2083, 2440, 2074, + 2074, 2074, 2074, 2074, 2074, 0, 0, 2318, 2318, 2318, + 2080, 2080, 2080, 2080, 2080, 2080, 2095, 2077, 2081, 2081, + 2081, 2081, 2081, 2081, 2088, 2439, 2441, 2440, 2083, 2255, + 2255, 2255, 2086, 2086, 2086, 2086, 2086, 2086, 2450, 2096, + 2088, 0, 2451, 2095, 2255, 2090, 2090, 2090, 0, 2077, + 2077, 2077, 2077, 2077, 2077, 2441, 2087, 2087, 2087, 2087, + 2087, 2087, 2376, 2376, 2376, 0, 2096, 2450, 2212, 2088, + 2151, 2451, 2095, 0, 2090, 2106, 2106, 2106, 2112, 2112, + + 2112, 0, 2134, 2134, 2134, 2378, 2378, 2378, 0, 2095, + 2095, 2095, 2095, 2095, 2095, 2096, 2318, 2088, 2088, 2088, + 2088, 2088, 2088, 2090, 2106, 0, 2134, 2112, 2456, 2134, + 2153, 0, 2096, 2096, 2096, 2096, 2096, 2096, 2255, 2145, + 2382, 2382, 2382, 2134, 2457, 0, 2147, 2147, 2147, 0, + 2391, 2391, 2391, 2106, 2090, 2134, 2112, 2456, 2134, 2153, + 2145, 2151, 2151, 2151, 2151, 2151, 2151, 2460, 2463, 0, + 0, 2376, 2134, 2457, 2154, 2147, 2464, 2153, 2153, 2153, + 2153, 2153, 2153, 2155, 2106, 0, 0, 2112, 0, 2145, + 2152, 2134, 2140, 2156, 2378, 0, 2460, 2463, 2140, 2157, + + 0, 2154, 2140, 2140, 2147, 2464, 0, 2140, 2140, 2140, + 0, 2140, 2145, 2145, 2145, 2145, 2145, 2145, 0, 2152, + 0, 2140, 2270, 2270, 2270, 2157, 2465, 2140, 0, 2382, + 2154, 2140, 2140, 2468, 0, 2147, 2140, 2140, 2140, 2391, + 2140, 2152, 2152, 2152, 2152, 2152, 2152, 2154, 2154, 2154, + 2154, 2154, 2154, 2472, 2157, 2465, 2155, 2155, 2155, 2155, + 2155, 2155, 2468, 2270, 0, 0, 2156, 2156, 2156, 2156, + 2156, 2156, 2157, 2157, 2157, 2157, 2157, 2157, 2171, 2171, + 2171, 2473, 2472, 2171, 2172, 2172, 2172, 2476, 0, 2172, + 0, 2171, 2270, 2173, 2173, 2173, 0, 2172, 2173, 2174, + + 2174, 2174, 0, 2171, 2174, 2478, 2173, 0, 0, 2172, + 2473, 2270, 2174, 2479, 2480, 2173, 2476, 2183, 2173, 2183, + 2175, 2175, 2175, 2481, 2174, 2175, 2176, 2176, 2176, 2183, + 0, 2176, 2171, 2175, 2478, 2177, 2177, 2177, 2172, 2176, + 2177, 0, 2479, 2480, 2173, 2175, 0, 2173, 2177, 2482, + 0, 2176, 2481, 2174, 2484, 0, 2485, 2486, 2183, 2186, + 2177, 2186, 0, 0, 0, 0, 2199, 2171, 2177, 0, + 2178, 2186, 0, 2172, 2175, 2192, 2487, 2174, 2482, 2180, + 2176, 2488, 2173, 2484, 2254, 2485, 2486, 0, 2174, 2177, + 2183, 2183, 2183, 2183, 2183, 2183, 0, 2177, 2175, 2178, + + 2186, 2199, 2192, 0, 2176, 2487, 2200, 0, 2180, 2175, + 2488, 0, 0, 0, 0, 2176, 2178, 2178, 2178, 2178, + 2178, 2178, 0, 2260, 2177, 2180, 2180, 2180, 2180, 2180, + 2180, 2192, 2186, 2186, 2186, 2186, 2186, 2186, 2200, 2199, + 2199, 2199, 2199, 2199, 2199, 2205, 2205, 2205, 2192, 2192, + 2192, 2192, 2192, 2192, 0, 0, 2247, 2254, 2254, 2254, + 2254, 2254, 2254, 2261, 2247, 2263, 0, 2200, 0, 0, + 0, 2247, 2262, 2263, 2205, 2264, 2298, 2298, 2298, 2200, + 2200, 2200, 2200, 2200, 2200, 2247, 2277, 2264, 2489, 0, + 0, 2298, 2261, 2247, 2260, 2260, 2260, 2260, 2260, 2260, + + 2247, 2262, 2263, 2205, 0, 2396, 2396, 2396, 2261, 2261, + 2261, 2261, 2261, 2261, 0, 0, 2264, 2489, 2262, 2262, + 2262, 2262, 2262, 2262, 2277, 2277, 2277, 2277, 2277, 2277, + 0, 2275, 2275, 2275, 2205, 2278, 2275, 2490, 2263, 2263, + 2263, 2263, 2263, 2263, 2275, 2400, 2400, 2400, 2264, 2264, + 2264, 2264, 2264, 2264, 2354, 2289, 2275, 2276, 2276, 2276, + 2491, 0, 2276, 2492, 2275, 2298, 2490, 2281, 0, 2281, + 2276, 0, 0, 2278, 2278, 2278, 2278, 2278, 2278, 2281, + 0, 2494, 2276, 2354, 2284, 2275, 2284, 2289, 0, 2491, + 2294, 0, 2492, 2275, 2396, 0, 2284, 2295, 2495, 0, + + 2354, 2354, 2354, 2354, 2354, 2354, 2294, 0, 2281, 2353, + 2494, 2276, 2393, 2393, 2393, 0, 2289, 2320, 2320, 2320, + 2275, 0, 2430, 2430, 2430, 2284, 2393, 2495, 2289, 2289, + 2289, 2289, 2289, 2289, 2400, 2294, 2332, 2332, 2332, 0, + 2281, 2281, 2281, 2281, 2281, 2281, 2276, 2325, 2325, 2325, + 2320, 0, 2322, 2322, 2322, 0, 0, 2284, 2284, 2284, + 2284, 2284, 2284, 2294, 2294, 2294, 2294, 2294, 2294, 2355, + 2295, 2295, 2295, 2295, 2295, 2295, 2332, 0, 2322, 2320, + 2353, 2353, 2353, 2353, 2353, 2353, 2356, 0, 2325, 2365, + 2365, 2365, 2322, 2357, 2365, 2366, 0, 2496, 2355, 0, + + 2497, 2393, 2365, 0, 0, 2332, 2320, 2322, 2370, 0, + 2370, 2430, 0, 2356, 2365, 2367, 2377, 2325, 2357, 2499, + 2370, 2322, 2507, 0, 2366, 2332, 2496, 0, 2432, 2497, + 2355, 2355, 2355, 2355, 2355, 2355, 2325, 0, 2373, 0, + 2373, 2322, 2356, 2365, 2367, 0, 0, 2357, 2499, 2370, + 2373, 2507, 2366, 2366, 2366, 2366, 2366, 2366, 0, 2356, + 2356, 2356, 2356, 2356, 2356, 0, 2357, 2357, 2357, 2357, + 2357, 2357, 2367, 2367, 2367, 2367, 2367, 2367, 2365, 2373, + 0, 2370, 2370, 2370, 2370, 2370, 2370, 2381, 2434, 2377, + 2377, 2377, 2377, 2377, 2377, 2384, 2384, 2384, 2381, 2432, + + 2432, 2432, 2432, 2432, 2432, 2433, 2433, 2433, 2433, 2433, + 2433, 2373, 2373, 2373, 2373, 2373, 2373, 2434, 2435, 0, + 0, 2508, 2510, 2442, 2436, 2520, 2521, 2381, 2384, 2452, + 2452, 2452, 2454, 2454, 2454, 0, 2445, 0, 2445, 0, + 2434, 2434, 2434, 2434, 2434, 2434, 2435, 2443, 2445, 2458, + 2508, 2510, 2442, 2436, 2520, 2521, 0, 2384, 0, 0, + 2381, 2381, 2381, 2381, 2381, 2381, 2446, 2448, 2446, 2448, + 2462, 2462, 2462, 0, 2524, 2435, 2443, 2445, 2446, 2448, + 0, 0, 2436, 0, 2384, 2442, 2442, 2442, 2442, 2442, + 2442, 2435, 2435, 2435, 2435, 2435, 2435, 2436, 2436, 2436, + + 2436, 2436, 2436, 2524, 2449, 0, 2449, 2446, 2448, 2443, + 2443, 2443, 2443, 2443, 2443, 0, 2449, 2503, 2452, 0, + 0, 2454, 2458, 2458, 2458, 2458, 2458, 2458, 2466, 2466, + 2466, 2504, 2469, 2469, 2469, 2470, 2470, 2470, 2525, 2446, + 2446, 2446, 2446, 2446, 2446, 2449, 2469, 2474, 2474, 2474, + 2500, 2500, 2500, 0, 2527, 2527, 2527, 2505, 0, 2462, + 2504, 2512, 2512, 2512, 2512, 2512, 2512, 2525, 0, 0, + 0, 2470, 2506, 2515, 2526, 2515, 2470, 2449, 2449, 2449, + 2449, 2449, 2449, 2505, 2506, 2515, 2531, 2474, 2503, 2503, + 2503, 2503, 2503, 2503, 2504, 2504, 2504, 2504, 2504, 2504, + + 2470, 0, 0, 2526, 0, 2470, 2513, 2513, 2513, 2513, + 2513, 2513, 2505, 2506, 2515, 2531, 2474, 2466, 2534, 2534, + 2534, 2469, 2533, 0, 2470, 2516, 2518, 2516, 2518, 2535, + 2505, 2505, 2505, 2505, 2505, 2505, 2474, 2516, 2518, 2500, + 2519, 2536, 2519, 2527, 2539, 2506, 2506, 2506, 2506, 2506, + 2506, 2533, 2519, 2540, 2534, 2541, 2543, 2544, 2535, 2534, + 2545, 2546, 2547, 2548, 2549, 2551, 2516, 2518, 2552, 2565, + 2536, 0, 0, 2539, 0, 2553, 2554, 2555, 2567, 2556, + 2557, 2519, 2540, 2534, 2541, 2543, 2544, 0, 2534, 2545, + 2546, 2547, 2548, 2549, 2551, 2558, 2559, 2552, 2516, 2516, + + 2516, 2516, 2516, 2516, 2553, 2554, 2555, 2534, 2556, 2557, + 2561, 0, 2568, 2519, 2519, 2519, 2519, 2519, 2519, 2566, + 2570, 2571, 0, 0, 2558, 2559, 2573, 0, 2573, 2578, + 2596, 2596, 2596, 0, 2574, 0, 2574, 2568, 2573, 2561, + 2565, 2565, 2565, 2565, 2565, 2565, 2574, 2579, 2566, 2570, + 2571, 2567, 2567, 2567, 2567, 2567, 2567, 2576, 2578, 2576, + 2566, 2566, 2566, 2566, 2566, 2566, 2568, 2573, 2580, 2576, + 2581, 2582, 2577, 2584, 2577, 2574, 2579, 2587, 2614, 2614, + 2614, 2614, 2614, 2614, 2577, 2568, 2568, 2568, 2568, 2568, + 2568, 2588, 2592, 2593, 2594, 2595, 2598, 2580, 2576, 2581, + + 2582, 2599, 2584, 2600, 2601, 2603, 2587, 2574, 2574, 2574, + 2574, 2574, 2574, 2577, 2604, 2606, 2613, 0, 0, 2596, + 2588, 2592, 2593, 2594, 2595, 2598, 2608, 2610, 2611, 2615, + 2599, 2617, 2600, 2601, 2603, 2625, 2626, 2629, 0, 2619, + 2620, 2619, 2620, 2604, 2606, 2577, 2577, 2577, 2577, 2577, + 2577, 2619, 2620, 2633, 2634, 2608, 2610, 2611, 0, 2622, + 2617, 2622, 0, 0, 2625, 2626, 2629, 2623, 2635, 2623, + 2636, 2622, 2637, 2639, 2639, 2639, 2641, 2641, 2641, 2623, + 2619, 2620, 2633, 2634, 2670, 2670, 2670, 2613, 2613, 2613, + 2613, 2613, 2613, 2638, 2640, 2643, 2644, 2635, 2646, 2636, + + 2622, 2637, 2615, 2615, 2615, 2615, 2615, 2615, 2623, 2647, + 2648, 0, 0, 2620, 2620, 2620, 2620, 2620, 2620, 2650, + 2651, 2662, 2638, 2640, 2643, 2644, 2664, 2646, 2654, 2654, + 2654, 2654, 2654, 2654, 2657, 2658, 2657, 2658, 2647, 2648, + 2623, 2623, 2623, 2623, 2623, 2623, 2657, 2658, 2650, 2651, + 2662, 2660, 2661, 2660, 2661, 2664, 2666, 2667, 2668, 2669, + 2674, 2678, 2639, 2660, 2661, 2641, 2672, 2672, 2672, 2677, + 2677, 2677, 2681, 2670, 2684, 2657, 2658, 0, 0, 2686, + 0, 2686, 0, 0, 0, 2666, 2667, 2668, 2669, 2674, + 2678, 2686, 2660, 2661, 2687, 2689, 2687, 2689, 0, 0, + + 0, 2681, 2690, 2684, 2690, 2692, 2687, 2689, 2658, 2658, + 2658, 2658, 2658, 2658, 2690, 2693, 2694, 2695, 2696, 2697, + 2686, 2699, 2702, 2703, 2704, 2661, 2661, 2661, 2661, 2661, + 2661, 2710, 0, 2712, 2692, 2687, 2689, 2700, 2700, 2700, + 0, 0, 0, 2690, 2693, 2694, 2695, 2696, 2697, 0, + 2699, 2702, 2703, 2704, 2706, 2672, 2706, 2713, 2677, 0, + 2710, 2707, 2712, 2707, 2700, 0, 2706, 2687, 2687, 2687, + 2687, 2687, 2687, 2707, 2714, 2690, 2690, 2690, 2690, 2690, + 2690, 2715, 2709, 2716, 2709, 2717, 2713, 2719, 2711, 2711, + 2711, 2721, 2729, 2700, 2709, 2706, 2711, 0, 2732, 2723, + + 2733, 2723, 2707, 2714, 2734, 2725, 2725, 2725, 0, 0, + 2715, 2723, 2716, 2725, 2717, 2736, 2719, 2737, 2742, 2743, + 2721, 2729, 2744, 2709, 2745, 2746, 2700, 2732, 2749, 2733, + 2747, 2747, 2747, 2734, 2707, 2707, 2707, 2707, 2707, 2707, + 2723, 2751, 2752, 2753, 2736, 2758, 2737, 2742, 2743, 2759, + 0, 2744, 2760, 2745, 2746, 2761, 2764, 2749, 2755, 2755, + 2755, 2756, 2756, 2756, 2762, 2762, 2762, 0, 2766, 2768, + 2751, 2752, 2753, 0, 2758, 2769, 2771, 2711, 2759, 2711, + 2773, 2760, 2775, 2776, 2761, 2764, 2767, 2767, 2767, 2774, + 2774, 2774, 2777, 2778, 2725, 2779, 2725, 2766, 2768, 2780, + + 2782, 2783, 2756, 2784, 2769, 2771, 2785, 2785, 2785, 2773, + 0, 2775, 2776, 0, 0, 0, 0, 0, 0, 2747, + 0, 2777, 2778, 0, 2779, 0, 0, 0, 2780, 2782, + 2783, 2756, 2784, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2755, 0, 0, + 2756, 0, 0, 2762, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2767, 0, 0, 2774, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2785, 2787, 2787, 2787, 2787, + + 2787, 2787, 2787, 2787, 2787, 2787, 2787, 2787, 2788, 2788, + 2788, 2788, 2788, 2788, 2788, 2788, 2788, 2788, 2788, 2788, + 2789, 2789, 2789, 2789, 2789, 2789, 2789, 2789, 2789, 2789, + 2789, 2789, 2790, 2790, 2790, 2790, 2790, 2790, 2790, 2790, + 2790, 2790, 2790, 2790, 2791, 2791, 2791, 2791, 2791, 2791, + 2791, 2791, 2791, 2791, 2791, 2791, 2792, 2792, 2792, 2792, + 2792, 2792, 2792, 2792, 2792, 2792, 2792, 2792, 2793, 2793, + 2793, 2793, 2793, 2793, 2793, 2793, 2793, 2793, 2793, 2793, + 2794, 2794, 2794, 2794, 2794, 2794, 2794, 2794, 2794, 2794, + 2794, 2794, 2795, 2795, 2795, 2795, 2795, 2795, 2795, 2795, + + 2795, 2795, 2795, 2795, 2796, 2796, 2796, 2796, 2796, 2796, + 2796, 2796, 2796, 2796, 2796, 2796, 2797, 2797, 2797, 2797, + 2797, 2797, 2797, 2797, 2797, 2797, 2797, 2797, 2798, 2798, + 2798, 2798, 2798, 2798, 2798, 2798, 2798, 2798, 2798, 2798, + 2799, 2799, 2799, 2799, 2799, 2799, 2799, 2799, 2799, 2799, + 2799, 2799, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800, + 2800, 2800, 2800, 2800, 2801, 2801, 2801, 2801, 2801, 2801, + 2801, 2801, 2801, 2801, 2801, 2801, 2802, 2802, 2802, 2802, + 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2803, 2803, + 2803, 2804, 2804, 0, 2804, 2804, 2804, 2804, 2804, 2804, + + 2804, 2804, 2804, 2805, 2805, 2806, 2806, 2806, 2807, 2807, + 0, 0, 0, 0, 0, 2807, 2808, 2808, 2809, 2809, + 0, 2809, 2809, 0, 2809, 2809, 2810, 2810, 2810, 2811, + 2811, 2812, 2812, 2812, 2813, 2813, 0, 0, 0, 0, + 0, 2813, 2814, 0, 2814, 2815, 0, 2815, 2816, 2816, + 2816, 2816, 2816, 2816, 0, 2816, 2816, 2816, 0, 2816, + 2817, 2817, 2817, 2817, 2817, 2817, 2817, 2817, 2817, 2817, + 2817, 2817, 2818, 2818, 2818, 2818, 2818, 2818, 0, 2818, + 2818, 2818, 0, 2818, 2819, 2819, 2819, 2819, 2819, 2819, + 2819, 2819, 2819, 2819, 2819, 2819, 2820, 2820, 2820, 2820, + + 2820, 2820, 2820, 2820, 2820, 2820, 2820, 2820, 2821, 2821, + 2821, 2821, 2821, 2821, 2821, 2821, 2821, 2821, 2821, 2822, + 2822, 2822, 2822, 2822, 2822, 2822, 2822, 2822, 2822, 2822, + 2823, 2823, 0, 2823, 2823, 2823, 2823, 2823, 2823, 2823, + 2823, 2823, 2824, 2824, 2825, 2825, 0, 2825, 2825, 2825, + 2825, 2825, 2825, 2825, 2825, 2825, 2826, 2826, 0, 2826, + 2826, 2826, 2826, 2826, 2826, 2826, 2826, 2826, 2827, 2827, + 2828, 2828, 2829, 2829, 0, 2829, 2829, 2829, 2829, 2829, + 2829, 2829, 2829, 2829, 2830, 2830, 2831, 2831, 0, 2831, + 2831, 2831, 2831, 2831, 2831, 2831, 2831, 2831, 2832, 2832, + + 0, 2832, 2832, 2832, 2832, 2832, 2832, 2832, 2832, 2832, + 2833, 2833, 2833, 2834, 2834, 0, 2834, 2834, 2834, 2834, + 2834, 2834, 2834, 2834, 2834, 2835, 2835, 0, 2835, 2835, + 2835, 2835, 2835, 2835, 2835, 2835, 2835, 2836, 2836, 2837, + 2837, 2837, 2838, 2838, 0, 0, 0, 0, 0, 2838, + 2839, 2839, 2840, 2840, 0, 2840, 2840, 0, 2840, 2840, + 2841, 2841, 2841, 2842, 2842, 2843, 2843, 2843, 2844, 2844, + 0, 0, 0, 0, 0, 2844, 2845, 0, 2845, 2846, + 0, 2846, 2847, 2847, 2847, 2847, 2847, 2847, 0, 2847, + 2847, 2847, 0, 2847, 2848, 2848, 0, 2848, 2848, 2848, + + 2848, 2848, 2848, 2848, 2848, 2848, 2849, 2849, 2849, 2849, + 2849, 2849, 0, 2849, 2849, 2849, 0, 2849, 2850, 2850, + 0, 2850, 2850, 2850, 2850, 2850, 2850, 2850, 2850, 2850, + 2851, 2851, 0, 2851, 2851, 2851, 2851, 2851, 2851, 2851, + 2851, 2851, 2852, 2852, 2852, 2852, 2852, 2852, 2852, 2852, + 2852, 2852, 2852, 2853, 2853, 2853, 2853, 2853, 2853, 2853, + 2853, 2853, 2853, 2853, 2854, 2854, 0, 2854, 2854, 2854, + 2854, 2854, 2854, 2854, 2854, 2854, 2855, 2855, 0, 2855, + 2855, 2855, 2855, 2855, 2855, 2855, 2855, 2855, 2856, 2856, + 2857, 2857, 0, 2857, 2857, 2857, 2857, 2857, 2857, 2857, + + 2857, 2857, 2858, 2858, 0, 2858, 2858, 2858, 2858, 2858, + 2858, 2858, 2858, 2858, 2859, 2859, 0, 2859, 2859, 2859, + 2859, 2859, 2859, 2859, 2859, 2859, 2860, 2860, 2861, 2861, + 2862, 2862, 0, 2862, 2862, 2862, 2862, 2862, 2862, 2862, + 2862, 2862, 2863, 2863, 0, 2863, 2863, 2863, 2863, 2863, + 2863, 2863, 2863, 2863, 2864, 2864, 2865, 2865, 0, 2865, + 2865, 2865, 2865, 2865, 2865, 2865, 2865, 2865, 2866, 2866, + 0, 2866, 2866, 2866, 2866, 2866, 2866, 2866, 2866, 2866, + 2867, 2867, 0, 2867, 2867, 2867, 2867, 2867, 2867, 2867, + 2867, 2867, 2868, 2868, 2868, 2868, 2868, 2868, 2868, 2868, + + 2868, 2868, 2868, 2868, 2869, 2869, 0, 0, 2869, 2870, + 2870, 2871, 2871, 0, 0, 2871, 2872, 2872, 2873, 0, + 2873, 2874, 0, 2874, 2875, 2875, 0, 2875, 2875, 2875, + 2875, 2875, 2875, 2875, 2875, 2875, 2876, 2876, 0, 2876, + 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2877, 2877, + 0, 2877, 2877, 2877, 2877, 2877, 2877, 2877, 2877, 2877, + 2878, 2878, 0, 2878, 2878, 2878, 2878, 2878, 2878, 2878, + 2878, 2878, 2879, 2879, 2879, 2879, 2879, 2879, 2879, 2879, + 2879, 2879, 2879, 2879, 2880, 2880, 2881, 2881, 2881, 2881, + 2881, 2881, 2881, 2881, 2881, 2881, 2881, 2881, 2882, 2882, + + 0, 2882, 2882, 2882, 2882, 2882, 2882, 2882, 2882, 2882, + 2883, 2883, 2883, 2883, 2883, 2883, 2883, 2883, 2883, 2883, + 2883, 2883, 2884, 2884, 2885, 2885, 2886, 2886, 0, 2886, + 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2887, 2887, + 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887, + 2888, 2888, 0, 0, 2888, 2889, 2889, 2889, 2889, 2889, + 2889, 2889, 2889, 2889, 2889, 2889, 2889, 2890, 2890, 2890, + 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2891, + 2891, 2891, 2892, 2892, 0, 2892, 2892, 2892, 2892, 2892, + 2892, 2892, 2892, 2892, 2893, 2893, 0, 2893, 2893, 2893, + + 2893, 2893, 2893, 2893, 2893, 2893, 2894, 2894, 2894, 2895, + 2895, 0, 2895, 2895, 2895, 2895, 2895, 2895, 2895, 2895, + 2895, 2896, 2896, 0, 0, 2896, 2897, 2897, 0, 0, + 0, 0, 0, 2897, 2898, 2898, 2899, 2899, 0, 0, + 2899, 2899, 2900, 2900, 2900, 2901, 2901, 2901, 2902, 2902, + 2903, 2903, 0, 0, 0, 0, 0, 2903, 2904, 0, + 2904, 2905, 0, 2905, 2906, 2906, 2906, 2906, 2906, 2906, + 2906, 2906, 2906, 2906, 2906, 2906, 2907, 2907, 2907, 2907, + 2907, 2907, 2907, 2907, 2907, 2907, 2907, 2907, 2908, 2908, + 2908, 2908, 2908, 2908, 2908, 2908, 2908, 2908, 2908, 2908, + + 2909, 2909, 0, 2909, 2909, 2909, 2909, 2909, 2909, 2909, + 2909, 2909, 2910, 2910, 0, 2910, 2910, 2910, 2910, 2910, + 2910, 2910, 2910, 2910, 2911, 2911, 0, 2911, 2911, 2911, + 2911, 2911, 2911, 2911, 2911, 2911, 2912, 2912, 2913, 2913, + 0, 2913, 2913, 2913, 2913, 2913, 2913, 2913, 2913, 2913, + 2914, 2914, 0, 2914, 2914, 2914, 2914, 2914, 2914, 2914, + 2914, 2914, 2915, 2915, 0, 2915, 2915, 2915, 2915, 2915, + 2915, 2915, 2915, 2915, 2916, 2916, 0, 2916, 2916, 2916, + 2916, 2916, 2916, 2916, 2916, 2916, 2917, 2917, 2918, 2918, + 2919, 2919, 0, 2919, 2919, 2919, 2919, 2919, 2919, 2919, + + 2919, 2919, 2920, 2920, 0, 2920, 2920, 2920, 2920, 2920, + 2920, 2920, 2920, 2920, 2921, 2921, 0, 2921, 2921, 2921, + 2921, 2921, 2921, 2921, 2921, 2921, 2922, 2922, 0, 0, + 2922, 2923, 2923, 0, 2923, 2923, 2923, 2923, 2923, 2923, + 2923, 2923, 2923, 2924, 2924, 0, 2924, 2924, 2924, 2924, + 2924, 2924, 2924, 2924, 2924, 2925, 2925, 0, 2925, 2925, + 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2926, 2926, 0, + 0, 2926, 2927, 2927, 2928, 2928, 0, 0, 2928, 2929, + 2929, 2930, 0, 2930, 2931, 0, 2931, 2932, 2932, 0, + 2932, 2932, 2932, 2932, 2932, 2932, 2932, 2932, 2932, 2933, + + 2933, 0, 2933, 2933, 2933, 2933, 2933, 2933, 2933, 2933, + 2933, 2934, 2934, 0, 2934, 2934, 2934, 2934, 2934, 2934, + 2934, 2934, 2934, 2935, 2935, 0, 2935, 2935, 2935, 2935, + 2935, 2935, 2935, 2935, 2935, 2936, 2936, 2937, 2937, 0, + 2937, 2937, 2937, 2937, 2937, 2937, 2937, 2937, 2937, 2938, + 2938, 0, 2938, 2938, 2938, 2938, 2938, 2938, 2938, 2938, + 2938, 2939, 2939, 2940, 2940, 2940, 2940, 2940, 2940, 2940, + 2940, 2940, 2940, 2940, 2940, 2941, 2941, 2941, 2941, 2941, + 2941, 2941, 2941, 2941, 2941, 2941, 2941, 2942, 2942, 2942, + 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2943, + + 2943, 2943, 2943, 2943, 2943, 2943, 2943, 2943, 2943, 2943, + 2943, 2944, 2944, 2944, 2944, 2944, 2944, 2944, 2944, 2944, + 2944, 2944, 2944, 2945, 2945, 2945, 2945, 2945, 2945, 2945, + 2945, 2945, 2945, 2945, 2945, 2946, 2946, 2946, 2946, 2946, + 2946, 2946, 2946, 2946, 2946, 2946, 2946, 2947, 2947, 2947, + 2947, 2947, 2947, 2947, 2947, 2947, 2947, 2947, 2947, 2948, + 2948, 2948, 2948, 2948, 2948, 2948, 2948, 2948, 2948, 2948, + 2948, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, 2786, + 2786, 2786, 2786, 2786, 2786, 2786 } ; /* The intent behind this definition is that it'll catch @@ -2789,9 +5603,13 @@ do {\ + -/*following character status will be rewrite by gen_parse.sh according to connection character*/ -#line 2796 "ob_proxy_parser_utf8_lex.c" + + +/* limit the length of int_num from 1 to 17 in case of int64_t out of bound, 17 -> [ ( length of 2^64 ) - 2 ]*/ +/* binlog relate SQL */ +#line 5614 "ob_proxy_parser_utf8_lex.c" #define INITIAL 0 #define hint 1 @@ -2818,7 +5636,10 @@ do {\ #define prepare 22 #define insert_all_expr 23 #define set_expr 24 -#define show_topology 25 +#define show_elastic_id 25 +#define show_topology 26 +#define show_tables 27 +#define proxy_icmd_state 28 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way @@ -3060,11 +5881,11 @@ YY_DECL register int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; -#line 366 "ob_proxy_parser_utf8.l" +#line 400 "ob_proxy_parser_utf8.l" /* basic dml stmt: */ -#line 3070 "ob_proxy_parser_utf8_lex.c" +#line 5891 "ob_proxy_parser_utf8_lex.c" yylval = yylval_param; @@ -3121,13 +5942,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 2102 ) + if ( yy_current_state >= 2787 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 6183 ); + while ( yy_base[yy_current_state] != 17872 ); yy_find_action: yy_act = yy_accept[yy_current_state]; @@ -3153,86 +5974,86 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 369 "ob_proxy_parser_utf8.l" +#line 403 "ob_proxy_parser_utf8.l" { SET_DML_STMT(OBPROXY_T_SELECT); PUSH_STATE(in_expr); return SELECT; } YY_BREAK case 2: YY_RULE_SETUP -#line 370 "ob_proxy_parser_utf8.l" +#line 404 "ob_proxy_parser_utf8.l" { SET_DML_STMT(OBPROXY_T_DELETE); PUSH_STATE_IF_NOT_ICMD(in_expr); return DELETE; } YY_BREAK case 3: YY_RULE_SETUP -#line 371 "ob_proxy_parser_utf8.l" +#line 405 "ob_proxy_parser_utf8.l" { SET_DML_STMT(OBPROXY_T_INSERT); return INSERT; } YY_BREAK case 4: YY_RULE_SETUP -#line 372 "ob_proxy_parser_utf8.l" +#line 406 "ob_proxy_parser_utf8.l" { SET_DML_STMT(OBPROXY_T_UPDATE); return UPDATE; } YY_BREAK case 5: YY_RULE_SETUP -#line 373 "ob_proxy_parser_utf8.l" +#line 407 "ob_proxy_parser_utf8.l" { SET_DML_STMT(OBPROXY_T_REPLACE); return REPLACE; } YY_BREAK case 6: YY_RULE_SETUP -#line 374 "ob_proxy_parser_utf8.l" +#line 408 "ob_proxy_parser_utf8.l" { SET_DML_STMT(OBPROXY_T_MERGE); return MERGE; } YY_BREAK case 7: YY_RULE_SETUP -#line 375 "ob_proxy_parser_utf8.l" +#line 409 "ob_proxy_parser_utf8.l" { SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW; } YY_BREAK case 8: YY_RULE_SETUP -#line 376 "ob_proxy_parser_utf8.l" +#line 410 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(XA); } YY_BREAK /* if begin is for starting transaction, will set has_anonymous_block = false in yacc */ case 9: YY_RULE_SETUP -#line 378 "ob_proxy_parser_utf8.l" +#line 412 "ob_proxy_parser_utf8.l" { SET_HAS_ANONYMOUS_BLOCK(); RETURN_NON_RESERVED_KEYWORD(BEGI); } YY_BREAK case 10: YY_RULE_SETUP -#line 379 "ob_proxy_parser_utf8.l" +#line 413 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(START); } YY_BREAK case 11: YY_RULE_SETUP -#line 380 "ob_proxy_parser_utf8.l" +#line 414 "ob_proxy_parser_utf8.l" { SET_BASIC_STMT(OBPROXY_T_COMMIT); RETURN_IGNORED_WORD(); } YY_BREAK case 12: YY_RULE_SETUP -#line 381 "ob_proxy_parser_utf8.l" +#line 415 "ob_proxy_parser_utf8.l" { SET_BASIC_STMT(OBPROXY_T_ROLLBACK); RETURN_IGNORED_WORD(); } YY_BREAK case 13: YY_RULE_SETUP -#line 382 "ob_proxy_parser_utf8.l" +#line 416 "ob_proxy_parser_utf8.l" { SET_BASIC_STMT(OBPROXY_T_SET); PUSH_STATE_IF_NOT_ICMD(set_expr); return SET; } YY_BREAK case 14: YY_RULE_SETUP -#line 383 "ob_proxy_parser_utf8.l" +#line 417 "ob_proxy_parser_utf8.l" { SET_BASIC_STMT(OBPROXY_T_CALL); return CALL; } YY_BREAK case 15: YY_RULE_SETUP -#line 384 "ob_proxy_parser_utf8.l" +#line 418 "ob_proxy_parser_utf8.l" { SET_HAS_ANONYMOUS_BLOCK(); PUSH_STATE(in_anonymous_block); } YY_BREAK case 16: YY_RULE_SETUP -#line 385 "ob_proxy_parser_utf8.l" +#line 419 "ob_proxy_parser_utf8.l" { ObProxyParseResult *p = ob_proxy_parser_utf8_yyget_extra(yyscanner); if (OB_NOTNULL(p)) { - if (OBPROXY_T_INSERT == p->cur_stmt_type_) + if (OBPROXY_T_INSERT == p->cur_stmt_type_) PUSH_STATE(insert_all_expr); } return WHEN; } @@ -3240,724 +6061,798 @@ YY_RULE_SETUP /* basic ddl stmt */ case 17: YY_RULE_SETUP -#line 393 "ob_proxy_parser_utf8.l" +#line 427 "ob_proxy_parser_utf8.l" { return CREATE; } YY_BREAK case 18: YY_RULE_SETUP -#line 394 "ob_proxy_parser_utf8.l" +#line 428 "ob_proxy_parser_utf8.l" { return DROP; } YY_BREAK case 19: YY_RULE_SETUP -#line 395 "ob_proxy_parser_utf8.l" +#line 429 "ob_proxy_parser_utf8.l" { return ALTER; } YY_BREAK case 20: YY_RULE_SETUP -#line 396 "ob_proxy_parser_utf8.l" +#line 430 "ob_proxy_parser_utf8.l" { return TRUNCATE; } YY_BREAK case 21: YY_RULE_SETUP -#line 397 "ob_proxy_parser_utf8.l" +#line 431 "ob_proxy_parser_utf8.l" { return RENAME; } YY_BREAK case 22: YY_RULE_SETUP -#line 398 "ob_proxy_parser_utf8.l" +#line 432 "ob_proxy_parser_utf8.l" { return INDEX; } YY_BREAK case 23: YY_RULE_SETUP -#line 399 "ob_proxy_parser_utf8.l" +#line 433 "ob_proxy_parser_utf8.l" { return TABLE; } YY_BREAK case 24: YY_RULE_SETUP -#line 400 "ob_proxy_parser_utf8.l" -{ return UNIQUE; } +#line 434 "ob_proxy_parser_utf8.l" +{ return STATUS; } YY_BREAK -/* ps stmt */ case 25: YY_RULE_SETUP -#line 403 "ob_proxy_parser_utf8.l" -{ return USING; } +#line 435 "ob_proxy_parser_utf8.l" +{ return FROM; } YY_BREAK case 26: YY_RULE_SETUP -#line 404 "ob_proxy_parser_utf8.l" -{ PUSH_STATE(prepare); return PREPARE; } +#line 436 "ob_proxy_parser_utf8.l" +{ return UNIQUE; } YY_BREAK +/* ps stmt */ case 27: YY_RULE_SETUP -#line 405 "ob_proxy_parser_utf8.l" -{ return EXECUTE; } +#line 439 "ob_proxy_parser_utf8.l" +{ return USING; } YY_BREAK -/* oracle ddl stmt */ case 28: YY_RULE_SETUP -#line 408 "ob_proxy_parser_utf8.l" -{ return GRANT; } +#line 440 "ob_proxy_parser_utf8.l" +{ PUSH_STATE(prepare); return PREPARE; } YY_BREAK case 29: YY_RULE_SETUP -#line 409 "ob_proxy_parser_utf8.l" -{ return REVOKE; } +#line 441 "ob_proxy_parser_utf8.l" +{ return EXECUTE; } YY_BREAK case 30: YY_RULE_SETUP -#line 410 "ob_proxy_parser_utf8.l" -{ return ANALYZE; } +#line 442 "ob_proxy_parser_utf8.l" +{ return DEALLOCATE; } YY_BREAK +/* oracle ddl stmt */ case 31: YY_RULE_SETUP -#line 411 "ob_proxy_parser_utf8.l" -{ return PURGE; } +#line 446 "ob_proxy_parser_utf8.l" +{ return GRANT; } YY_BREAK case 32: YY_RULE_SETUP -#line 412 "ob_proxy_parser_utf8.l" -{ return COMMENT; } +#line 447 "ob_proxy_parser_utf8.l" +{ return REVOKE; } YY_BREAK case 33: YY_RULE_SETUP -#line 413 "ob_proxy_parser_utf8.l" -{ RETURN_NON_RESERVED_KEYWORD(FLASHBACK); } +#line 448 "ob_proxy_parser_utf8.l" +{ return ANALYZE; } YY_BREAK case 34: YY_RULE_SETUP -#line 414 "ob_proxy_parser_utf8.l" -{ RETURN_NON_RESERVED_KEYWORD(AUDIT); } +#line 449 "ob_proxy_parser_utf8.l" +{ return PURGE; } YY_BREAK case 35: YY_RULE_SETUP -#line 415 "ob_proxy_parser_utf8.l" -{ RETURN_NON_RESERVED_KEYWORD(NOAUDIT); } +#line 450 "ob_proxy_parser_utf8.l" +{ return COMMENT; } YY_BREAK case 36: YY_RULE_SETUP -#line 417 "ob_proxy_parser_utf8.l" -{ return GROUP;} +#line 451 "ob_proxy_parser_utf8.l" +{ RETURN_NON_RESERVED_KEYWORD(FLASHBACK); } YY_BREAK case 37: YY_RULE_SETUP -#line 418 "ob_proxy_parser_utf8.l" -{ return HAVING;} +#line 452 "ob_proxy_parser_utf8.l" +{ RETURN_NON_RESERVED_KEYWORD(AUDIT); } YY_BREAK case 38: YY_RULE_SETUP -#line 419 "ob_proxy_parser_utf8.l" -{ return ORDER;} +#line 453 "ob_proxy_parser_utf8.l" +{ RETURN_NON_RESERVED_KEYWORD(NOAUDIT); } YY_BREAK case 39: YY_RULE_SETUP -#line 420 "ob_proxy_parser_utf8.l" -{ return FOR;} +#line 455 "ob_proxy_parser_utf8.l" +{ return GROUP;} YY_BREAK case 40: YY_RULE_SETUP -#line 421 "ob_proxy_parser_utf8.l" -{ return UNION;} +#line 456 "ob_proxy_parser_utf8.l" +{ return HAVING;} YY_BREAK case 41: YY_RULE_SETUP -#line 422 "ob_proxy_parser_utf8.l" -{ return AS; } +#line 457 "ob_proxy_parser_utf8.l" +{ return ORDER;} YY_BREAK case 42: YY_RULE_SETUP -#line 423 "ob_proxy_parser_utf8.l" -{ return WHERE; } +#line 458 "ob_proxy_parser_utf8.l" +{ return FOR;} YY_BREAK case 43: YY_RULE_SETUP -#line 424 "ob_proxy_parser_utf8.l" -{ return VALUES; } +#line 459 "ob_proxy_parser_utf8.l" +{ return UNION;} YY_BREAK case 44: YY_RULE_SETUP -#line 425 "ob_proxy_parser_utf8.l" -{ return VALUES; } +#line 460 "ob_proxy_parser_utf8.l" +{ return AS; } YY_BREAK case 45: YY_RULE_SETUP -#line 426 "ob_proxy_parser_utf8.l" -{ SET_HAS_EXPLAIN(); return EXPLAIN; } +#line 461 "ob_proxy_parser_utf8.l" +{ return WHERE; } YY_BREAK case 46: YY_RULE_SETUP -#line 427 "ob_proxy_parser_utf8.l" -{ SET_HAS_EXPLAIN(); return DESC; } +#line 462 "ob_proxy_parser_utf8.l" +{ return VALUES; } YY_BREAK case 47: YY_RULE_SETUP -#line 428 "ob_proxy_parser_utf8.l" -{ SET_HAS_EXPLAIN(); return DESCRIBE; } +#line 463 "ob_proxy_parser_utf8.l" +{ return VALUES; } YY_BREAK -/*change from non_reserved to reserved according https://dev.mysql.com/doc/refman/5.6/en/keywords.html*/ case 48: YY_RULE_SETUP -#line 430 "ob_proxy_parser_utf8.l" -{ return READ; } +#line 464 "ob_proxy_parser_utf8.l" +{ SET_HAS_EXPLAIN(); return EXPLAIN; } YY_BREAK case 49: YY_RULE_SETUP -#line 431 "ob_proxy_parser_utf8.l" -{ return WITH; } +#line 465 "ob_proxy_parser_utf8.l" +{ SET_HAS_EXPLAIN(); return DESC; } YY_BREAK case 50: YY_RULE_SETUP -#line 432 "ob_proxy_parser_utf8.l" -{ return USE; } +#line 466 "ob_proxy_parser_utf8.l" +{ SET_HAS_EXPLAIN(); return DESCRIBE; } YY_BREAK +/*change from non_reserved to reserved according https://dev.mysql.com/doc/refman/5.6/en/keywords.html*/ case 51: YY_RULE_SETUP -#line 433 "ob_proxy_parser_utf8.l" -{ return LIMIT; } +#line 468 "ob_proxy_parser_utf8.l" +{ return READ; } YY_BREAK case 52: YY_RULE_SETUP -#line 434 "ob_proxy_parser_utf8.l" -{ return ALL; } +#line 469 "ob_proxy_parser_utf8.l" +{ return WITH; } YY_BREAK case 53: YY_RULE_SETUP -#line 435 "ob_proxy_parser_utf8.l" -{ return LIKE; } +#line 470 "ob_proxy_parser_utf8.l" +{ return USE; } YY_BREAK case 54: YY_RULE_SETUP -#line 436 "ob_proxy_parser_utf8.l" -{ return PARTITION; } +#line 471 "ob_proxy_parser_utf8.l" +{ return LIMIT; } YY_BREAK case 55: YY_RULE_SETUP -#line 437 "ob_proxy_parser_utf8.l" -{ return BINARY; } +#line 472 "ob_proxy_parser_utf8.l" +{ return ALL; } YY_BREAK case 56: YY_RULE_SETUP -#line 438 "ob_proxy_parser_utf8.l" -{ return GROUP_NAME; } +#line 473 "ob_proxy_parser_utf8.l" +{ return LIKE; } YY_BREAK -/* to make bison easy, do not return these reserved keyword in non strict mode */ case 57: YY_RULE_SETUP -#line 441 "ob_proxy_parser_utf8.l" -{ RETURN_IGNORED_WORD(); } +#line 474 "ob_proxy_parser_utf8.l" +{ return PARTITION; } YY_BREAK case 58: YY_RULE_SETUP -#line 442 "ob_proxy_parser_utf8.l" -{ RETURN_IGNORED_WORD(); } +#line 475 "ob_proxy_parser_utf8.l" +{ return BINARY; } YY_BREAK case 59: YY_RULE_SETUP -#line 443 "ob_proxy_parser_utf8.l" -{ RETURN_IGNORED_WORD(); } +#line 476 "ob_proxy_parser_utf8.l" +{ RETURN_NON_RESERVED_KEYWORD(GROUP_NAME); } YY_BREAK +/* to make bison easy, do not return these reserved keyword in non strict mode */ case 60: YY_RULE_SETUP -#line 444 "ob_proxy_parser_utf8.l" +#line 479 "ob_proxy_parser_utf8.l" { RETURN_IGNORED_WORD(); } YY_BREAK case 61: YY_RULE_SETUP -#line 445 "ob_proxy_parser_utf8.l" +#line 480 "ob_proxy_parser_utf8.l" { RETURN_IGNORED_WORD(); } YY_BREAK -/* no reserved keyword , don't forget to add these keyword in .y */ -/*refer: https://dev.mysql.com/doc/refman/5.6/en/keywords.html*/ case 62: YY_RULE_SETUP -#line 449 "ob_proxy_parser_utf8.l" -{ RETURN_NON_RESERVED_KEYWORD(QUICK); } +#line 481 "ob_proxy_parser_utf8.l" +{ RETURN_IGNORED_WORD(); } YY_BREAK case 63: YY_RULE_SETUP -#line 450 "ob_proxy_parser_utf8.l" -{ RETURN_NON_RESERVED_KEYWORD(COUNT); } +#line 482 "ob_proxy_parser_utf8.l" +{ RETURN_IGNORED_WORD(); } YY_BREAK case 64: YY_RULE_SETUP -#line 451 "ob_proxy_parser_utf8.l" -{ RETURN_NON_RESERVED_KEYWORD(WARNINGS); } +#line 483 "ob_proxy_parser_utf8.l" +{ RETURN_IGNORED_WORD(); } YY_BREAK +/* no reserved keyword , don't forget to add these keyword in .y */ +/*refer: https://dev.mysql.com/doc/refman/5.6/en/keywords.html*/ case 65: YY_RULE_SETUP -#line 452 "ob_proxy_parser_utf8.l" -{ RETURN_NON_RESERVED_KEYWORD(ERRORS); } +#line 487 "ob_proxy_parser_utf8.l" +{ RETURN_NON_RESERVED_KEYWORD(QUICK); } YY_BREAK case 66: YY_RULE_SETUP -#line 453 "ob_proxy_parser_utf8.l" -{ RETURN_NON_RESERVED_KEYWORD(TRACE); } +#line 488 "ob_proxy_parser_utf8.l" +{ RETURN_NON_RESERVED_KEYWORD(COUNT); } YY_BREAK case 67: YY_RULE_SETUP -#line 454 "ob_proxy_parser_utf8.l" -{ RETURN_NON_RESERVED_KEYWORD(TRANSACTION); } +#line 489 "ob_proxy_parser_utf8.l" +{ RETURN_NON_RESERVED_KEYWORD(WARNINGS); } YY_BREAK case 68: YY_RULE_SETUP -#line 456 "ob_proxy_parser_utf8.l" -{ RETURN_NON_RESERVED_KEYWORD(ONLY); } +#line 490 "ob_proxy_parser_utf8.l" +{ RETURN_NON_RESERVED_KEYWORD(ERRORS); } YY_BREAK case 69: YY_RULE_SETUP -#line 458 "ob_proxy_parser_utf8.l" -{ RETURN_NON_RESERVED_KEYWORD(CONSISTENT); } +#line 491 "ob_proxy_parser_utf8.l" +{ RETURN_NON_RESERVED_KEYWORD(TRACE); } YY_BREAK case 70: YY_RULE_SETUP -#line 459 "ob_proxy_parser_utf8.l" -{ RETURN_NON_RESERVED_KEYWORD(SNAPSHOT); } +#line 492 "ob_proxy_parser_utf8.l" +{ RETURN_NON_RESERVED_KEYWORD(TRANSACTION); } YY_BREAK case 71: YY_RULE_SETUP -#line 461 "ob_proxy_parser_utf8.l" -{ RETURN_NON_RESERVED_KEYWORD(HELP); } +#line 494 "ob_proxy_parser_utf8.l" +{ RETURN_NON_RESERVED_KEYWORD(ONLY); } YY_BREAK -/*set names*/ case 72: -/* rule 72 can match eol */ YY_RULE_SETUP -#line 465 "ob_proxy_parser_utf8.l" -{ SET_BASIC_STMT(OBPROXY_T_SET_NAMES); return SET_NAMES; } +#line 496 "ob_proxy_parser_utf8.l" +{ RETURN_NON_RESERVED_KEYWORD(CONSISTENT); } YY_BREAK -/*set charset*/ case 73: -/* rule 73 can match eol */ YY_RULE_SETUP -#line 467 "ob_proxy_parser_utf8.l" -{ SET_BASIC_STMT(OBPROXY_T_SET_CHARSET); return SET_CHARSET; } +#line 497 "ob_proxy_parser_utf8.l" +{ RETURN_NON_RESERVED_KEYWORD(SNAPSHOT); } YY_BREAK -/*set passwd*/ case 74: -/* rule 74 can match eol */ YY_RULE_SETUP -#line 469 "ob_proxy_parser_utf8.l" -{ SET_BASIC_STMT(OBPROXY_T_SET_PASSWORD); return SET_PASSWORD; } +#line 499 "ob_proxy_parser_utf8.l" +{ RETURN_NON_RESERVED_KEYWORD(HELP); } YY_BREAK -/*set default*/ +/*set names*/ case 75: /* rule 75 can match eol */ YY_RULE_SETUP -#line 471 "ob_proxy_parser_utf8.l" -{ SET_BASIC_STMT(OBPROXY_T_SET_DEFAULT); return SET_DEFAULT; } +#line 503 "ob_proxy_parser_utf8.l" +{ SET_BASIC_STMT(OBPROXY_T_SET_NAMES); return SET_NAMES; } YY_BREAK +/*set charset*/ case 76: /* rule 76 can match eol */ YY_RULE_SETUP -#line 473 "ob_proxy_parser_utf8.l" -{ SET_BASIC_STMT(OBPROXY_T_SET_OB_READ_CONSISTENCY); return SET_OB_READ_CONSISTENCY; } +#line 505 "ob_proxy_parser_utf8.l" +{ SET_BASIC_STMT(OBPROXY_T_SET_CHARSET); return SET_CHARSET; } YY_BREAK +/*set passwd*/ case 77: /* rule 77 can match eol */ YY_RULE_SETUP -#line 474 "ob_proxy_parser_utf8.l" +#line 507 "ob_proxy_parser_utf8.l" +{ SET_BASIC_STMT(OBPROXY_T_SET_PASSWORD); return SET_PASSWORD; } + YY_BREAK +/*set default*/ +case 78: +/* rule 78 can match eol */ +YY_RULE_SETUP +#line 509 "ob_proxy_parser_utf8.l" +{ SET_BASIC_STMT(OBPROXY_T_SET_DEFAULT); return SET_DEFAULT; } + YY_BREAK +case 79: +/* rule 79 can match eol */ +YY_RULE_SETUP +#line 511 "ob_proxy_parser_utf8.l" +{ SET_BASIC_STMT(OBPROXY_T_SET_OB_READ_CONSISTENCY); return SET_OB_READ_CONSISTENCY; } + YY_BREAK +case 80: +/* rule 80 can match eol */ +YY_RULE_SETUP +#line 512 "ob_proxy_parser_utf8.l" { SET_BASIC_STMT(OBPROXY_T_SET_TX_READ_ONLY); return SET_TX_READ_ONLY; } YY_BREAK /*internal cmd*/ /*show net*/ -case 78: -/* rule 78 can match eol */ +case 81: +/* rule 81 can match eol */ YY_RULE_SETUP -#line 478 "ob_proxy_parser_utf8.l" +#line 516 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_NET); return SHOW_PROXYNET; } YY_BREAK -case 79: +case 82: YY_RULE_SETUP -#line 479 "ob_proxy_parser_utf8.l" +#line 517 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(THREAD); } YY_BREAK -case 80: +case 83: YY_RULE_SETUP -#line 480 "ob_proxy_parser_utf8.l" +#line 518 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(CONNECTION); } YY_BREAK -case 81: +case 84: YY_RULE_SETUP -#line 482 "ob_proxy_parser_utf8.l" +#line 520 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(OFFSET); } YY_BREAK /*show session*/ -case 82: -/* rule 82 can match eol */ +case 85: +/* rule 85 can match eol */ YY_RULE_SETUP -#line 485 "ob_proxy_parser_utf8.l" +#line 523 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_GLOBAL_SESSION); return SHOW_GLOBALSESSION; } YY_BREAK -case 83: -/* rule 83 can match eol */ +case 86: +/* rule 86 can match eol */ YY_RULE_SETUP -#line 486 "ob_proxy_parser_utf8.l" +#line 524 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_SESSION); return SHOW_PROXYSESSION; } YY_BREAK -case 84: -/* rule 84 can match eol */ +case 87: +/* rule 87 can match eol */ YY_RULE_SETUP -#line 487 "ob_proxy_parser_utf8.l" +#line 525 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_PROCESSLIST); return SHOW_PROCESSLIST; } YY_BREAK -case 85: +case 88: YY_RULE_SETUP -#line 488 "ob_proxy_parser_utf8.l" +#line 526 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(ATTRIBUTE); } YY_BREAK -case 86: +case 89: YY_RULE_SETUP -#line 489 "ob_proxy_parser_utf8.l" +#line 527 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(VARIABLES); } YY_BREAK -case 87: +case 90: YY_RULE_SETUP -#line 491 "ob_proxy_parser_utf8.l" +#line 529 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(STAT); } YY_BREAK /*show config*/ -case 88: -/* rule 88 can match eol */ +case 91: +/* rule 91 can match eol */ YY_RULE_SETUP -#line 494 "ob_proxy_parser_utf8.l" -{ SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_CONFIG); return SHOW_PROXYCONFIG; } +#line 532 "ob_proxy_parser_utf8.l" +{ SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_CONFIG); PUSH_STATE(proxy_icmd_state); return SHOW_PROXYCONFIG; } YY_BREAK -case 89: +case 92: YY_RULE_SETUP -#line 496 "ob_proxy_parser_utf8.l" +#line 534 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(DIFF); } YY_BREAK -case 90: +case 93: YY_RULE_SETUP -#line 497 "ob_proxy_parser_utf8.l" +#line 535 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(USER); } YY_BREAK +case 94: +YY_RULE_SETUP +#line 536 "ob_proxy_parser_utf8.l" +{ POP_STATE(); return LIKE; } + YY_BREAK /*show sm*/ -case 91: -/* rule 91 can match eol */ +case 95: +/* rule 95 can match eol */ YY_RULE_SETUP -#line 500 "ob_proxy_parser_utf8.l" +#line 539 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_SM); return SHOW_PROXYSM; } YY_BREAK /*show cluster*/ -case 92: -/* rule 92 can match eol */ +case 96: +/* rule 96 can match eol */ YY_RULE_SETUP -#line 503 "ob_proxy_parser_utf8.l" +#line 542 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_CLUSTER); return SHOW_PROXYCLUSTER; } YY_BREAK /*show resource*/ -case 93: -/* rule 93 can match eol */ +case 97: +/* rule 97 can match eol */ YY_RULE_SETUP -#line 506 "ob_proxy_parser_utf8.l" +#line 545 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_RESOURCE); return SHOW_PROXYRESOURCE; } YY_BREAK /*show congestion*/ -case 94: -/* rule 94 can match eol */ +case 98: +/* rule 98 can match eol */ YY_RULE_SETUP -#line 509 "ob_proxy_parser_utf8.l" +#line 548 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_CONGESTION); return SHOW_PROXYCONGESTION; } YY_BREAK /*show route*/ -case 95: -/* rule 95 can match eol */ +case 99: +/* rule 99 can match eol */ YY_RULE_SETUP -#line 512 "ob_proxy_parser_utf8.l" +#line 551 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_ROUTE); return SHOW_PROXYROUTE; } YY_BREAK -case 96: +case 100: YY_RULE_SETUP -#line 514 "ob_proxy_parser_utf8.l" +#line 553 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(ROUTINE); } YY_BREAK /*show vip*/ -case 97: -/* rule 97 can match eol */ +case 101: +/* rule 101 can match eol */ YY_RULE_SETUP -#line 517 "ob_proxy_parser_utf8.l" +#line 556 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_VIP); return SHOW_PROXYVIP; } YY_BREAK /*show memory*/ -case 98: -/* rule 98 can match eol */ +case 102: +/* rule 102 can match eol */ YY_RULE_SETUP -#line 520 "ob_proxy_parser_utf8.l" +#line 559 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_MEMORY); return SHOW_PROXYMEMORY; } YY_BREAK -case 99: +case 103: YY_RULE_SETUP -#line 521 "ob_proxy_parser_utf8.l" +#line 560 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(OBJPOOL); } YY_BREAK /*show sqlaudit*/ -case 100: -/* rule 100 can match eol */ +case 104: +/* rule 104 can match eol */ YY_RULE_SETUP -#line 524 "ob_proxy_parser_utf8.l" +#line 563 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_SQLAUDIT); return SHOW_SQLAUDIT; } YY_BREAK /*show warnlog*/ -case 101: -/* rule 101 can match eol */ +case 105: +/* rule 105 can match eol */ YY_RULE_SETUP -#line 527 "ob_proxy_parser_utf8.l" +#line 566 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_WARNLOG); return SHOW_WARNLOG; } YY_BREAK /*show stat*/ -case 102: -/* rule 102 can match eol */ +case 106: +/* rule 106 can match eol */ YY_RULE_SETUP -#line 530 "ob_proxy_parser_utf8.l" +#line 569 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_STAT); return SHOW_PROXYSTAT; } YY_BREAK -case 103: +case 107: YY_RULE_SETUP -#line 531 "ob_proxy_parser_utf8.l" +#line 570 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(REFRESH); } YY_BREAK /*show trace*/ -case 104: -/* rule 104 can match eol */ +case 108: +/* rule 108 can match eol */ YY_RULE_SETUP -#line 534 "ob_proxy_parser_utf8.l" +#line 573 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_TRACE); return SHOW_PROXYTRACE; } YY_BREAK /*show info*/ -case 105: -/* rule 105 can match eol */ +case 109: +/* rule 109 can match eol */ YY_RULE_SETUP -#line 537 "ob_proxy_parser_utf8.l" +#line 576 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_SHOW_INFO); return SHOW_PROXYINFO; } YY_BREAK -case 106: +case 110: YY_RULE_SETUP -#line 538 "ob_proxy_parser_utf8.l" +#line 577 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(UPGRADE); } YY_BREAK -case 107: +case 111: YY_RULE_SETUP -#line 539 "ob_proxy_parser_utf8.l" +#line 578 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(IDC); } YY_BREAK -case 108: -/* rule 108 can match eol */ +case 112: +/* rule 112 can match eol */ YY_RULE_SETUP -#line 541 "ob_proxy_parser_utf8.l" -{ SET_BASIC_STMT(OBPROXY_T_SHOW); PUSH_STATE(show_topology); return SHOW_TOPOLOGY; } +#line 580 "ob_proxy_parser_utf8.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW); PUSH_STATE(show_elastic_id ); return SHOW_ELASTIC_ID; } YY_BREAK -case 109: +case 113: YY_RULE_SETUP -#line 542 "ob_proxy_parser_utf8.l" +#line 581 "ob_proxy_parser_utf8.l" { POP_STATE(); PUSH_STATE(INITIAL); return FROM; } YY_BREAK -case 110: +case 114: YY_RULE_SETUP -#line 543 "ob_proxy_parser_utf8.l" +#line 582 "ob_proxy_parser_utf8.l" { POP_STATE(); PUSH_STATE(INITIAL); return WHERE; } YY_BREAK -case YY_STATE_EOF(show_topology): -#line 544 "ob_proxy_parser_utf8.l" +case YY_STATE_EOF(show_elastic_id): +#line 583 "ob_proxy_parser_utf8.l" { return END_P; } YY_BREAK -case 111: -/* rule 111 can match eol */ +case 115: +/* rule 115 can match eol */ YY_RULE_SETUP -#line 545 "ob_proxy_parser_utf8.l" +#line 584 "ob_proxy_parser_utf8.l" { } YY_BREAK -case 112: +case 116: YY_RULE_SETUP -#line 546 "ob_proxy_parser_utf8.l" +#line 585 "ob_proxy_parser_utf8.l" { POP_STATE(); PUSH_STATE(INITIAL); return yytext[0]; } YY_BREAK -case 113: +case 117: YY_RULE_SETUP -#line 547 "ob_proxy_parser_utf8.l" +#line 586 "ob_proxy_parser_utf8.l" { return ERROR; } YY_BREAK -case 114: -/* rule 114 can match eol */ +case 118: +/* rule 118 can match eol */ YY_RULE_SETUP -#line 549 "ob_proxy_parser_utf8.l" +#line 588 "ob_proxy_parser_utf8.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_TOPOLOGY; } + YY_BREAK +case 119: +/* rule 119 can match eol */ +YY_RULE_SETUP +#line 590 "ob_proxy_parser_utf8.l" { SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_DB_VERSION; } YY_BREAK -case 115: -/* rule 115 can match eol */ +case 120: +/* rule 120 can match eol */ YY_RULE_SETUP -#line 550 "ob_proxy_parser_utf8.l" +#line 591 "ob_proxy_parser_utf8.l" { SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_DATABASES; } YY_BREAK -case 116: -/* rule 116 can match eol */ +case 121: +/* rule 121 can match eol */ YY_RULE_SETUP -#line 551 "ob_proxy_parser_utf8.l" -{ SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_TABLES; } +#line 593 "ob_proxy_parser_utf8.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW); PUSH_STATE(show_tables); return SHOW_TABLES; } YY_BREAK -case 117: -/* rule 117 can match eol */ +case 122: +/* rule 122 can match eol */ +YY_RULE_SETUP +#line 594 "ob_proxy_parser_utf8.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW); PUSH_STATE(show_tables); return SHOW_FULL_TABLES; } + YY_BREAK +case 123: +YY_RULE_SETUP +#line 596 "ob_proxy_parser_utf8.l" +{ POP_STATE(); PUSH_STATE(INITIAL); return FROM; } + YY_BREAK +case 124: +YY_RULE_SETUP +#line 597 "ob_proxy_parser_utf8.l" +{ POP_STATE(); PUSH_STATE(INITIAL); return LIKE; } + YY_BREAK +case YY_STATE_EOF(show_tables): +#line 598 "ob_proxy_parser_utf8.l" +{ return END_P; } + YY_BREAK +case 125: +/* rule 125 can match eol */ +YY_RULE_SETUP +#line 599 "ob_proxy_parser_utf8.l" +{ } + YY_BREAK +case 126: +YY_RULE_SETUP +#line 600 "ob_proxy_parser_utf8.l" +{ POP_STATE(); PUSH_STATE(INITIAL); return yytext[0]; } + YY_BREAK +case 127: +YY_RULE_SETUP +#line 601 "ob_proxy_parser_utf8.l" +{ return ERROR; } + YY_BREAK +case 128: +/* rule 128 can match eol */ YY_RULE_SETUP -#line 552 "ob_proxy_parser_utf8.l" +#line 602 "ob_proxy_parser_utf8.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_COLUMNS; } + YY_BREAK +case 129: +/* rule 129 can match eol */ +YY_RULE_SETUP +#line 603 "ob_proxy_parser_utf8.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_INDEX; } + YY_BREAK +case 130: +/* rule 130 can match eol */ +YY_RULE_SETUP +#line 605 "ob_proxy_parser_utf8.l" { SET_BASIC_STMT(OBPROXY_T_SHOW); return SHOW_CREATE_TABLE; } YY_BREAK -case 118: -/* rule 118 can match eol */ +case 131: +/* rule 131 can match eol */ YY_RULE_SETUP -#line 553 "ob_proxy_parser_utf8.l" +#line 606 "ob_proxy_parser_utf8.l" { SET_DML_STMT(OBPROXY_T_SELECT); return SELECT_DATABASE; } YY_BREAK -case 119: -/* rule 119 can match eol */ +case 132: +/* rule 132 can match eol */ YY_RULE_SETUP -#line 554 "ob_proxy_parser_utf8.l" +#line 607 "ob_proxy_parser_utf8.l" { SET_DML_STMT(OBPROXY_T_SELECT_PROXY_VERSION); return SELECT_PROXY_VERSION; } YY_BREAK /*alter config*/ -case 120: -/* rule 120 can match eol */ +case 133: +/* rule 133 can match eol */ YY_RULE_SETUP -#line 557 "ob_proxy_parser_utf8.l" +#line 610 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_ALTER_CONFIG); return ALTER_PROXYCONFIG; } YY_BREAK /*alter resource*/ -case 121: -/* rule 121 can match eol */ +case 134: +/* rule 134 can match eol */ YY_RULE_SETUP -#line 560 "ob_proxy_parser_utf8.l" +#line 613 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_ALTER_RESOURCE); return ALTER_PROXYRESOURCE; } YY_BREAK /*ping proxy*/ -case 122: -/* rule 122 can match eol */ +case 135: +/* rule 135 can match eol */ YY_RULE_SETUP -#line 563 "ob_proxy_parser_utf8.l" +#line 616 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_PING_PROXY); return PING_PROXY; } YY_BREAK /*kill*/ -case 123: -/* rule 123 can match eol */ +case 136: +/* rule 136 can match eol */ YY_RULE_SETUP -#line 566 "ob_proxy_parser_utf8.l" +#line 619 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_KILL_SESSION); return KILL_PROXYSESSION; } YY_BREAK -case 124: -/* rule 124 can match eol */ +case 137: +/* rule 137 can match eol */ YY_RULE_SETUP -#line 567 "ob_proxy_parser_utf8.l" +#line 620 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_KILL_GLOBAL_SESSION); return KILL_GLOBALSESSION; } YY_BREAK -case 125: +case 138: YY_RULE_SETUP -#line 568 "ob_proxy_parser_utf8.l" +#line 621 "ob_proxy_parser_utf8.l" { SET_ICMD_STMT(OBPROXY_T_ICMD_KILL_MYSQL); return KILL; } YY_BREAK -case 126: +case 139: YY_RULE_SETUP -#line 569 "ob_proxy_parser_utf8.l" +#line 622 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(QUERY); } YY_BREAK /* obproxy_route_addr */ -case 127: -/* rule 127 can match eol */ +case 140: +/* rule 140 can match eol */ YY_RULE_SETUP -#line 572 "ob_proxy_parser_utf8.l" +#line 625 "ob_proxy_parser_utf8.l" { return SELECT_OBPROXY_ROUTE_ADDR; } YY_BREAK -case 128: -/* rule 128 can match eol */ +case 141: +/* rule 141 can match eol */ YY_RULE_SETUP -#line 573 "ob_proxy_parser_utf8.l" +#line 626 "ob_proxy_parser_utf8.l" { return SET_OBPROXY_ROUTE_ADDR; } YY_BREAK /* identifer */ -case 129: +case 142: YY_RULE_SETUP -#line 576 "ob_proxy_parser_utf8.l" +#line 629 "ob_proxy_parser_utf8.l" { SET_FOUND_ROWS(); RETURN_NON_RESERVED_KEYWORD(NAME_OB); } YY_BREAK -case 130: +case 143: YY_RULE_SETUP -#line 577 "ob_proxy_parser_utf8.l" +#line 630 "ob_proxy_parser_utf8.l" { SET_ROW_COUNT(); RETURN_NON_RESERVED_KEYWORD(NAME_OB); } YY_BREAK -case 131: +case 144: YY_RULE_SETUP -#line 578 "ob_proxy_parser_utf8.l" +#line 631 "ob_proxy_parser_utf8.l" { SET_LAST_INSERT_ID(); RETURN_NON_RESERVED_KEYWORD(NAME_OB); } YY_BREAK -case 132: +case 145: YY_RULE_SETUP -#line 579 "ob_proxy_parser_utf8.l" +#line 632 "ob_proxy_parser_utf8.l" { return ','; } YY_BREAK -case 133: +case 146: YY_RULE_SETUP -#line 580 "ob_proxy_parser_utf8.l" +#line 633 "ob_proxy_parser_utf8.l" { RETURN_INT_NUM(); } YY_BREAK -case 134: +case 147: YY_RULE_SETUP -#line 581 "ob_proxy_parser_utf8.l" +#line 634 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(NAME_OB); } YY_BREAK -case 135: +case 148: YY_RULE_SETUP -#line 582 "ob_proxy_parser_utf8.l" +#line 635 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD_WITH_QUOTE(NAME_OB, OBPROXY_QUOTE_T_SINGLE); } YY_BREAK -case 136: +case 149: YY_RULE_SETUP -#line 583 "ob_proxy_parser_utf8.l" +#line 636 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD_WITH_QUOTE(NAME_OB, OBPROXY_QUOTE_T_DOUBLE); } YY_BREAK -case 137: +case 150: YY_RULE_SETUP -#line 584 "ob_proxy_parser_utf8.l" +#line 637 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD_WITH_QUOTE(NAME_OB, OBPROXY_QUOTE_T_BACK); } YY_BREAK -case 138: +case 151: YY_RULE_SETUP -#line 585 "ob_proxy_parser_utf8.l" +#line 638 "ob_proxy_parser_utf8.l" { RETURN_NUMBER_VAL(); } YY_BREAK -case 139: +case 152: YY_RULE_SETUP -#line 586 "ob_proxy_parser_utf8.l" +#line 639 "ob_proxy_parser_utf8.l" { return PLACE_HOLDER; } YY_BREAK -case 140: +case 153: YY_RULE_SETUP -#line 587 "ob_proxy_parser_utf8.l" +#line 640 "ob_proxy_parser_utf8.l" { return yytext[0]; } YY_BREAK -case 141: +case 154: YY_RULE_SETUP -#line 588 "ob_proxy_parser_utf8.l" +#line 641 "ob_proxy_parser_utf8.l" { RETURN_WITH_CALL_CHECK(yytext[0]); } YY_BREAK -case 142: +case 155: YY_RULE_SETUP -#line 589 "ob_proxy_parser_utf8.l" +#line 642 "ob_proxy_parser_utf8.l" { RETURN_WITH_CALL_CHECK('('); } YY_BREAK -case 143: +case 156: YY_RULE_SETUP -#line 590 "ob_proxy_parser_utf8.l" +#line 643 "ob_proxy_parser_utf8.l" { RETURN_WITH_CALL_CHECK(')'); } YY_BREAK -case 144: -/* rule 144 can match eol */ +case 157: +/* rule 157 can match eol */ YY_RULE_SETUP -#line 591 "ob_proxy_parser_utf8.l" +#line 644 "ob_proxy_parser_utf8.l" { } YY_BREAK /* hint option */ -case 145: -/* rule 145 can match eol */ +case 158: +/* rule 158 can match eol */ YY_RULE_SETUP -#line 594 "ob_proxy_parser_utf8.l" +#line 647 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_expr); PUSH_STATE(hint); @@ -3965,20 +6860,20 @@ YY_RULE_SETUP return SELECT_HINT_BEGIN; } YY_BREAK -case 146: -/* rule 146 can match eol */ +case 159: +/* rule 159 can match eol */ YY_RULE_SETUP -#line 600 "ob_proxy_parser_utf8.l" +#line 653 "ob_proxy_parser_utf8.l" { PUSH_STATE(hint); SET_BASIC_STMT(OBPROXY_T_UPDATE); return UPDATE_HINT_BEGIN; } YY_BREAK -case 147: -/* rule 147 can match eol */ +case 160: +/* rule 160 can match eol */ YY_RULE_SETUP -#line 605 "ob_proxy_parser_utf8.l" +#line 658 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_expr); PUSH_STATE(hint); @@ -3986,95 +6881,125 @@ YY_RULE_SETUP return DELETE_HINT_BEGIN; } YY_BREAK -case 148: -/* rule 148 can match eol */ +case 161: +/* rule 161 can match eol */ YY_RULE_SETUP -#line 611 "ob_proxy_parser_utf8.l" +#line 664 "ob_proxy_parser_utf8.l" { PUSH_STATE(hint); SET_BASIC_STMT(OBPROXY_T_INSERT); return INSERT_HINT_BEGIN; } YY_BREAK -case 149: -/* rule 149 can match eol */ +case 162: +/* rule 162 can match eol */ YY_RULE_SETUP -#line 616 "ob_proxy_parser_utf8.l" +#line 669 "ob_proxy_parser_utf8.l" { PUSH_STATE(hint); SET_BASIC_STMT(OBPROXY_T_REPLACE); return REPLACE_HINT_BEGIN; } YY_BREAK -case 150: -/* rule 150 can match eol */ +case 163: +/* rule 163 can match eol */ YY_RULE_SETUP -#line 621 "ob_proxy_parser_utf8.l" +#line 674 "ob_proxy_parser_utf8.l" { PUSH_STATE(hint); SET_BASIC_STMT(OBPROXY_T_MERGE); return MERGE_HINT_BEGIN; } YY_BREAK -case 151: -/* rule 151 can match eol */ +case 164: +/* rule 164 can match eol */ YY_RULE_SETUP -#line 627 "ob_proxy_parser_utf8.l" -{ return AUTOCOMMIT_0; } +#line 680 "ob_proxy_parser_utf8.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW_MASTER_STATUS); return SHOW_MASTER_STATUS; } YY_BREAK -case 152: +case 165: +/* rule 165 can match eol */ +YY_RULE_SETUP +#line 681 "ob_proxy_parser_utf8.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW_BINARY_LOGS); return SHOW_BINARY_LOGS; } + YY_BREAK +case 166: +/* rule 166 can match eol */ +YY_RULE_SETUP +#line 682 "ob_proxy_parser_utf8.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW_BINLOG_EVENTS); return SHOW_BINLOG_EVENTS; } + YY_BREAK +case 167: +/* rule 167 can match eol */ +YY_RULE_SETUP +#line 683 "ob_proxy_parser_utf8.l" +{ SET_BASIC_STMT(OBPROXY_T_PURGE_BINARY_LOGS); return PURGE_BINARY_LOGS; } + YY_BREAK +case 168: +/* rule 168 can match eol */ +YY_RULE_SETUP +#line 684 "ob_proxy_parser_utf8.l" +{ SET_BASIC_STMT(OBPROXY_T_RESET_MASTER); return RESET_MASTER; } + YY_BREAK +case 169: +/* rule 169 can match eol */ +YY_RULE_SETUP +#line 685 "ob_proxy_parser_utf8.l" +{ SET_BASIC_STMT(OBPROXY_T_SHOW_BINLOG_SERVER_FOR_TENANT); return SHOW_BINLOG_SERVER_FOR_TENANT; } + YY_BREAK +case 170: YY_RULE_SETUP -#line 628 "ob_proxy_parser_utf8.l" +#line 687 "ob_proxy_parser_utf8.l" { return GLOBAL; } YY_BREAK -case 153: +case 171: YY_RULE_SETUP -#line 629 "ob_proxy_parser_utf8.l" +#line 688 "ob_proxy_parser_utf8.l" { return SESSION; } YY_BREAK -case 154: +case 172: YY_RULE_SETUP -#line 630 "ob_proxy_parser_utf8.l" +#line 689 "ob_proxy_parser_utf8.l" { RETURN_INT_NUM(); } YY_BREAK -case 155: +case 173: YY_RULE_SETUP -#line 631 "ob_proxy_parser_utf8.l" +#line 690 "ob_proxy_parser_utf8.l" { return ','; } YY_BREAK -case 156: +case 174: YY_RULE_SETUP -#line 632 "ob_proxy_parser_utf8.l" +#line 691 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(NAME_OB); } YY_BREAK -case 157: +case 175: YY_RULE_SETUP -#line 633 "ob_proxy_parser_utf8.l" +#line 692 "ob_proxy_parser_utf8.l" { RETURN_NUMBER_VAL(); } YY_BREAK -case 158: -/* rule 158 can match eol */ +case 176: +/* rule 176 can match eol */ YY_RULE_SETUP -#line 634 "ob_proxy_parser_utf8.l" +#line 693 "ob_proxy_parser_utf8.l" { } YY_BREAK -case 159: +case 177: YY_RULE_SETUP -#line 635 "ob_proxy_parser_utf8.l" +#line 694 "ob_proxy_parser_utf8.l" { return yytext[0]; } YY_BREAK case YY_STATE_EOF(set_expr): -#line 636 "ob_proxy_parser_utf8.l" +#line 695 "ob_proxy_parser_utf8.l" { return END_P; } YY_BREAK -case 160: +case 178: YY_RULE_SETUP -#line 637 "ob_proxy_parser_utf8.l" +#line 696 "ob_proxy_parser_utf8.l" { POP_STATE(); PUSH_STATE(INITIAL); return yytext[0]; } YY_BREAK -case 161: +case 179: YY_RULE_SETUP -#line 639 "ob_proxy_parser_utf8.l" +#line 698 "ob_proxy_parser_utf8.l" { PUSH_STATE(sq); ObProxyParseResult *p = (ObProxyParseResult *)yyextra; @@ -4085,9 +7010,9 @@ YY_RULE_SETUP } } YY_BREAK -case 162: +case 180: YY_RULE_SETUP -#line 649 "ob_proxy_parser_utf8.l" +#line 708 "ob_proxy_parser_utf8.l" { PUSH_STATE(dq); ObProxyParseResult *p = (ObProxyParseResult *)yyextra; @@ -4098,9 +7023,9 @@ YY_RULE_SETUP } } YY_BREAK -case 163: +case 181: YY_RULE_SETUP -#line 659 "ob_proxy_parser_utf8.l" +#line 718 "ob_proxy_parser_utf8.l" { PUSH_STATE(bt); ObProxyParseResult *p = (ObProxyParseResult *)yyextra; @@ -4111,90 +7036,90 @@ YY_RULE_SETUP } } YY_BREAK -case 164: +case 182: YY_RULE_SETUP -#line 668 "ob_proxy_parser_utf8.l" +#line 727 "ob_proxy_parser_utf8.l" { return ERROR; } YY_BREAK -case 165: +case 183: YY_RULE_SETUP -#line 670 "ob_proxy_parser_utf8.l" +#line 729 "ob_proxy_parser_utf8.l" { POP_STATE(); RETURN_IGNORED_WORD(); } YY_BREAK -case 166: +case 184: YY_RULE_SETUP -#line 671 "ob_proxy_parser_utf8.l" +#line 730 "ob_proxy_parser_utf8.l" {} YY_BREAK -case 167: +case 185: YY_RULE_SETUP -#line 673 "ob_proxy_parser_utf8.l" +#line 732 "ob_proxy_parser_utf8.l" { return '('; } YY_BREAK -case 168: +case 186: YY_RULE_SETUP -#line 674 "ob_proxy_parser_utf8.l" +#line 733 "ob_proxy_parser_utf8.l" { return ')'; } YY_BREAK -case 169: +case 187: YY_RULE_SETUP -#line 675 "ob_proxy_parser_utf8.l" +#line 734 "ob_proxy_parser_utf8.l" { return QUERY_TIMEOUT; } YY_BREAK -case 170: +case 188: YY_RULE_SETUP -#line 676 "ob_proxy_parser_utf8.l" +#line 735 "ob_proxy_parser_utf8.l" { RETURN_INT_NUM(); } YY_BREAK -case 171: +case 189: YY_RULE_SETUP -#line 677 "ob_proxy_parser_utf8.l" +#line 736 "ob_proxy_parser_utf8.l" { return READ_CONSISTENCY; } YY_BREAK -case 172: +case 190: YY_RULE_SETUP -#line 678 "ob_proxy_parser_utf8.l" +#line 737 "ob_proxy_parser_utf8.l" { return WEAK; } YY_BREAK -case 173: +case 191: YY_RULE_SETUP -#line 679 "ob_proxy_parser_utf8.l" +#line 738 "ob_proxy_parser_utf8.l" { return STRONG; } YY_BREAK -case 174: +case 192: YY_RULE_SETUP -#line 680 "ob_proxy_parser_utf8.l" +#line 739 "ob_proxy_parser_utf8.l" { return FROZEN; } YY_BREAK -case 175: +case 193: YY_RULE_SETUP -#line 681 "ob_proxy_parser_utf8.l" +#line 740 "ob_proxy_parser_utf8.l" { return INDEX; } YY_BREAK -case 176: +case 194: YY_RULE_SETUP -#line 682 "ob_proxy_parser_utf8.l" +#line 741 "ob_proxy_parser_utf8.l" { return yytext[0]; } YY_BREAK -case 177: +case 195: YY_RULE_SETUP -#line 683 "ob_proxy_parser_utf8.l" +#line 742 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(NAME_OB); } YY_BREAK -case 178: +case 196: YY_RULE_SETUP -#line 684 "ob_proxy_parser_utf8.l" +#line 743 "ob_proxy_parser_utf8.l" { POP_STATE(); return HINT_END; } YY_BREAK -case 179: +case 197: YY_RULE_SETUP -#line 685 "ob_proxy_parser_utf8.l" +#line 744 "ob_proxy_parser_utf8.l" {} YY_BREAK /* comment */ -case 180: +case 198: YY_RULE_SETUP -#line 688 "ob_proxy_parser_utf8.l" +#line 747 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_c_comment); ObProxyParseResult *p = (ObProxyParseResult *)yyextra; @@ -4209,25 +7134,25 @@ YY_RULE_SETUP } } YY_BREAK -case 181: +case 199: YY_RULE_SETUP -#line 702 "ob_proxy_parser_utf8.l" +#line 761 "ob_proxy_parser_utf8.l" { POP_STATE(); } YY_BREAK -case 182: -/* rule 182 can match eol */ +case 200: +/* rule 200 can match eol */ YY_RULE_SETUP -#line 703 "ob_proxy_parser_utf8.l" +#line 762 "ob_proxy_parser_utf8.l" {} YY_BREAK -case 183: +case 201: YY_RULE_SETUP -#line 704 "ob_proxy_parser_utf8.l" +#line 763 "ob_proxy_parser_utf8.l" {} YY_BREAK -case 184: +case 202: YY_RULE_SETUP -#line 706 "ob_proxy_parser_utf8.l" +#line 765 "ob_proxy_parser_utf8.l" { ObProxyParseResult *p = (ObProxyParseResult *)yyextra; if (OB_NOTNULL(p)) { @@ -4238,15 +7163,15 @@ YY_RULE_SETUP return COMMENT_END; } YY_BREAK -case 185: +case 203: YY_RULE_SETUP -#line 716 "ob_proxy_parser_utf8.l" +#line 775 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_old_comment_expr); } YY_BREAK -case 186: -/* rule 186 can match eol */ +case 204: +/* rule 204 can match eol */ YY_RULE_SETUP -#line 717 "ob_proxy_parser_utf8.l" +#line 776 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_old_comment_expr); ObProxyParseResult *p = (ObProxyParseResult *)yyextra; @@ -4256,10 +7181,10 @@ YY_RULE_SETUP } } YY_BREAK -case 187: -/* rule 187 can match eol */ +case 205: +/* rule 205 can match eol */ YY_RULE_SETUP -#line 726 "ob_proxy_parser_utf8.l" +#line 785 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_old_comment_expr); ObProxyParseResult *p = (ObProxyParseResult *)yyextra; @@ -4271,9 +7196,9 @@ YY_RULE_SETUP } } YY_BREAK -case 188: +case 206: YY_RULE_SETUP -#line 737 "ob_proxy_parser_utf8.l" +#line 796 "ob_proxy_parser_utf8.l" { ObProxyParseResult *p = (ObProxyParseResult *)yyextra; if (OB_NOTNULL(p)) { @@ -4282,9 +7207,9 @@ YY_RULE_SETUP } } YY_BREAK -case 189: +case 207: YY_RULE_SETUP -#line 745 "ob_proxy_parser_utf8.l" +#line 804 "ob_proxy_parser_utf8.l" { ObProxyParseResult *p = (ObProxyParseResult *)yyextra; if (OB_NOTNULL(p)) { @@ -4295,29 +7220,29 @@ YY_RULE_SETUP } } YY_BREAK -case 190: +case 208: YY_RULE_SETUP -#line 755 "ob_proxy_parser_utf8.l" +#line 814 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(NAME_OB); } YY_BREAK -case 191: +case 209: YY_RULE_SETUP -#line 756 "ob_proxy_parser_utf8.l" +#line 815 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD_WITH_QUOTE(NAME_OB, OBPROXY_QUOTE_T_SINGLE); } YY_BREAK -case 192: +case 210: YY_RULE_SETUP -#line 757 "ob_proxy_parser_utf8.l" +#line 816 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD_WITH_QUOTE(NAME_OB, OBPROXY_QUOTE_T_DOUBLE); } YY_BREAK -case 193: +case 211: YY_RULE_SETUP -#line 758 "ob_proxy_parser_utf8.l" +#line 817 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD_WITH_QUOTE(NAME_OB, OBPROXY_QUOTE_T_BACK); } YY_BREAK -case 194: +case 212: YY_RULE_SETUP -#line 759 "ob_proxy_parser_utf8.l" +#line 818 "ob_proxy_parser_utf8.l" { ObProxyParseResult *p = (ObProxyParseResult *)yyextra; if (OB_NOTNULL(p)) { @@ -4329,160 +7254,171 @@ YY_RULE_SETUP return COMMENT_END; } YY_BREAK -case 195: +case 213: YY_RULE_SETUP -#line 769 "ob_proxy_parser_utf8.l" +#line 828 "ob_proxy_parser_utf8.l" {} YY_BREAK -case 196: +case 214: YY_RULE_SETUP -#line 771 "ob_proxy_parser_utf8.l" +#line 830 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(ODP_COMMENT); } YY_BREAK -case 197: -/* rule 197 can match eol */ +case 215: +/* rule 215 can match eol */ YY_RULE_SETUP -#line 772 "ob_proxy_parser_utf8.l" +#line 831 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(GROUP_ID); } YY_BREAK -case 198: -/* rule 198 can match eol */ +case 216: +/* rule 216 can match eol */ YY_RULE_SETUP -#line 773 "ob_proxy_parser_utf8.l" +#line 832 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(TABLE_ID); } YY_BREAK -case 199: -/* rule 199 can match eol */ +case 217: +/* rule 217 can match eol */ YY_RULE_SETUP -#line 774 "ob_proxy_parser_utf8.l" +#line 833 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(TABLE_NAME); } YY_BREAK -case 200: -/* rule 200 can match eol */ +case 218: +/* rule 218 can match eol */ YY_RULE_SETUP -#line 775 "ob_proxy_parser_utf8.l" +#line 834 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(ELASTIC_ID); } YY_BREAK -case 201: -/* rule 201 can match eol */ +case 219: +/* rule 219 can match eol */ YY_RULE_SETUP -#line 776 "ob_proxy_parser_utf8.l" +#line 835 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(TESTLOAD); } YY_BREAK -case 202: -/* rule 202 can match eol */ +case 220: +/* rule 220 can match eol */ YY_RULE_SETUP -#line 777 "ob_proxy_parser_utf8.l" +#line 836 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(DISASTER_STATUS); } YY_BREAK -case 203: -/* rule 203 can match eol */ +case 221: +/* rule 221 can match eol */ YY_RULE_SETUP -#line 778 "ob_proxy_parser_utf8.l" +#line 837 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(TNT_ID); } YY_BREAK -case 204: -/* rule 204 can match eol */ +case 222: +/* rule 222 can match eol */ YY_RULE_SETUP -#line 779 "ob_proxy_parser_utf8.l" +#line 838 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(TRACE_ID); } YY_BREAK -case 205: -/* rule 205 can match eol */ +case 223: +/* rule 223 can match eol */ YY_RULE_SETUP -#line 780 "ob_proxy_parser_utf8.l" +#line 839 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT_NAME_OB_DOT(NAME_OB_DOT); } YY_BREAK -case 206: -/* rule 206 can match eol */ +case 224: +/* rule 224 can match eol */ YY_RULE_SETUP -#line 781 "ob_proxy_parser_utf8.l" +#line 840 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_odp_comment_expr); RETURN_SHARD_COMMENT(RPC_ID); } YY_BREAK -case 207: +case 225: +/* rule 225 can match eol */ +YY_RULE_SETUP +#line 841 "ob_proxy_parser_utf8.l" +{ PUSH_STATE(in_odp_comment_expr); return TARGET_DB_SERVER; } + YY_BREAK +case 226: YY_RULE_SETUP -#line 783 "ob_proxy_parser_utf8.l" +#line 843 "ob_proxy_parser_utf8.l" { return GROUP_ID; } YY_BREAK -case 208: +case 227: YY_RULE_SETUP -#line 784 "ob_proxy_parser_utf8.l" +#line 844 "ob_proxy_parser_utf8.l" { return TABLE_ID; } YY_BREAK -case 209: +case 228: YY_RULE_SETUP -#line 785 "ob_proxy_parser_utf8.l" +#line 845 "ob_proxy_parser_utf8.l" { return TABLE_NAME; } YY_BREAK -case 210: +case 229: YY_RULE_SETUP -#line 786 "ob_proxy_parser_utf8.l" +#line 846 "ob_proxy_parser_utf8.l" { return ELASTIC_ID; } YY_BREAK -case 211: +case 230: YY_RULE_SETUP -#line 787 "ob_proxy_parser_utf8.l" +#line 847 "ob_proxy_parser_utf8.l" { return TESTLOAD; } YY_BREAK -case 212: +case 231: YY_RULE_SETUP -#line 788 "ob_proxy_parser_utf8.l" +#line 848 "ob_proxy_parser_utf8.l" { return DISASTER_STATUS; } YY_BREAK -case 213: +case 232: YY_RULE_SETUP -#line 789 "ob_proxy_parser_utf8.l" +#line 849 "ob_proxy_parser_utf8.l" { return TNT_ID; } YY_BREAK -case 214: +case 233: YY_RULE_SETUP -#line 790 "ob_proxy_parser_utf8.l" +#line 850 "ob_proxy_parser_utf8.l" { return TRACE_ID; } YY_BREAK -case 215: +case 234: YY_RULE_SETUP -#line 791 "ob_proxy_parser_utf8.l" +#line 851 "ob_proxy_parser_utf8.l" { return RPC_ID; } YY_BREAK -case 216: +case 235: YY_RULE_SETUP -#line 792 "ob_proxy_parser_utf8.l" +#line 852 "ob_proxy_parser_utf8.l" +{ return TARGET_DB_SERVER; } + YY_BREAK +case 236: +YY_RULE_SETUP +#line 853 "ob_proxy_parser_utf8.l" { ENTER_QUOTE_STATE(comment_sq); } YY_BREAK -case 217: +case 237: YY_RULE_SETUP -#line 793 "ob_proxy_parser_utf8.l" +#line 854 "ob_proxy_parser_utf8.l" { return ','; } YY_BREAK -case 218: +case 238: YY_RULE_SETUP -#line 794 "ob_proxy_parser_utf8.l" +#line 855 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(NAME_OB); } YY_BREAK -case 219: +case 239: YY_RULE_SETUP -#line 795 "ob_proxy_parser_utf8.l" +#line 856 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_odp_comment_value_expr); return yytext[0]; } YY_BREAK -case 220: +case 240: YY_RULE_SETUP -#line 796 "ob_proxy_parser_utf8.l" +#line 857 "ob_proxy_parser_utf8.l" { return yytext[0]; } YY_BREAK -case 221: -/* rule 221 can match eol */ +case 241: +/* rule 241 can match eol */ YY_RULE_SETUP -#line 797 "ob_proxy_parser_utf8.l" +#line 858 "ob_proxy_parser_utf8.l" {} YY_BREAK -case 222: +case 242: YY_RULE_SETUP -#line 798 "ob_proxy_parser_utf8.l" +#line 859 "ob_proxy_parser_utf8.l" { return ERROR; } YY_BREAK -case 223: +case 243: YY_RULE_SETUP -#line 799 "ob_proxy_parser_utf8.l" +#line 860 "ob_proxy_parser_utf8.l" { ObProxyParseResult *p = (ObProxyParseResult *)yyextra; if (OB_NOTNULL(p)) { @@ -4494,22 +7430,22 @@ YY_RULE_SETUP return COMMENT_END; } YY_BREAK -case 224: +case 244: YY_RULE_SETUP -#line 810 "ob_proxy_parser_utf8.l" +#line 871 "ob_proxy_parser_utf8.l" { ENTER_QUOTE_STATE(comment_sq); } YY_BREAK -case 225: +case 245: YY_RULE_SETUP -#line 811 "ob_proxy_parser_utf8.l" +#line 872 "ob_proxy_parser_utf8.l" { POP_STATE(); return ','; } YY_BREAK -case 226: +case 246: YY_RULE_SETUP -#line 815 "ob_proxy_parser_utf8.l" +#line 876 "ob_proxy_parser_utf8.l" { ObProxyParseResult *p = (ObProxyParseResult *)yyextra; if (OB_NOTNULL(p)) { @@ -4522,15 +7458,15 @@ YY_RULE_SETUP return COMMENT_END; } YY_BREAK -case 227: -/* rule 227 can match eol */ +case 247: +/* rule 247 can match eol */ YY_RULE_SETUP -#line 826 "ob_proxy_parser_utf8.l" +#line 887 "ob_proxy_parser_utf8.l" {} YY_BREAK -case 228: +case 248: YY_RULE_SETUP -#line 827 "ob_proxy_parser_utf8.l" +#line 888 "ob_proxy_parser_utf8.l" { do { PUSH_STATE(in_odp_comment_value_expr_calc) @@ -4543,10 +7479,10 @@ YY_RULE_SETUP } while (0); } YY_BREAK -case 229: -/* rule 229 can match eol */ +case 249: +/* rule 249 can match eol */ YY_RULE_SETUP -#line 839 "ob_proxy_parser_utf8.l" +#line 900 "ob_proxy_parser_utf8.l" { POP_STATE(); ObProxyParseResult *p = (ObProxyParseResult *)yyextra; @@ -4559,9 +7495,9 @@ YY_RULE_SETUP } } YY_BREAK -case 230: +case 250: YY_RULE_SETUP -#line 851 "ob_proxy_parser_utf8.l" +#line 912 "ob_proxy_parser_utf8.l" { ObProxyParseResult *p = (ObProxyParseResult *)yyextra; if (OB_NOTNULL(p)) { @@ -4569,90 +7505,95 @@ YY_RULE_SETUP } } YY_BREAK -case 231: +case 251: YY_RULE_SETUP -#line 858 "ob_proxy_parser_utf8.l" +#line 919 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_dbp_comment_expr); RETURN_SHARD_COMMENT(DBP_COMMENT); } YY_BREAK -case 232: +case 252: YY_RULE_SETUP -#line 859 "ob_proxy_parser_utf8.l" +#line 920 "ob_proxy_parser_utf8.l" { return ROUTE_TAG; } YY_BREAK -case 233: +case 253: YY_RULE_SETUP -#line 860 "ob_proxy_parser_utf8.l" +#line 921 "ob_proxy_parser_utf8.l" { return SYS_TAG; } YY_BREAK -case 234: +case 254: YY_RULE_SETUP -#line 861 "ob_proxy_parser_utf8.l" +#line 922 "ob_proxy_parser_utf8.l" { return SCAN_ALL; } YY_BREAK -case 235: +case 255: +YY_RULE_SETUP +#line 923 "ob_proxy_parser_utf8.l" +{ return STICKY_SESSION; } + YY_BREAK +case 256: YY_RULE_SETUP -#line 862 "ob_proxy_parser_utf8.l" +#line 924 "ob_proxy_parser_utf8.l" { return SHARD_KEY; } YY_BREAK -case 236: +case 257: YY_RULE_SETUP -#line 863 "ob_proxy_parser_utf8.l" +#line 925 "ob_proxy_parser_utf8.l" { return TABLE_NAME;} YY_BREAK -case 237: +case 258: YY_RULE_SETUP -#line 864 "ob_proxy_parser_utf8.l" +#line 926 "ob_proxy_parser_utf8.l" { return PARALL; } YY_BREAK -case 238: +case 259: YY_RULE_SETUP -#line 865 "ob_proxy_parser_utf8.l" +#line 927 "ob_proxy_parser_utf8.l" { return GROUP_ID; } YY_BREAK -case 239: +case 260: YY_RULE_SETUP -#line 866 "ob_proxy_parser_utf8.l" +#line 928 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_dbp_comment_trace_expr); return TRACE; } YY_BREAK -case 240: +case 261: YY_RULE_SETUP -#line 867 "ob_proxy_parser_utf8.l" +#line 929 "ob_proxy_parser_utf8.l" { ENTER_QUOTE_STATE(comment_sq); } YY_BREAK -case 241: +case 262: YY_RULE_SETUP -#line 868 "ob_proxy_parser_utf8.l" +#line 930 "ob_proxy_parser_utf8.l" { return yytext[0]; } YY_BREAK -case 242: +case 263: YY_RULE_SETUP -#line 869 "ob_proxy_parser_utf8.l" +#line 931 "ob_proxy_parser_utf8.l" { return '('; } YY_BREAK -case 243: +case 264: YY_RULE_SETUP -#line 870 "ob_proxy_parser_utf8.l" +#line 932 "ob_proxy_parser_utf8.l" { return ')'; } YY_BREAK -case 244: +case 265: YY_RULE_SETUP -#line 871 "ob_proxy_parser_utf8.l" +#line 933 "ob_proxy_parser_utf8.l" { return ','; } YY_BREAK -case 245: -/* rule 245 can match eol */ +case 266: +/* rule 266 can match eol */ YY_RULE_SETUP -#line 872 "ob_proxy_parser_utf8.l" +#line 934 "ob_proxy_parser_utf8.l" { } YY_BREAK -case 246: +case 267: YY_RULE_SETUP -#line 873 "ob_proxy_parser_utf8.l" +#line 935 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(NAME_OB); } YY_BREAK -case 247: +case 268: YY_RULE_SETUP -#line 875 "ob_proxy_parser_utf8.l" +#line 937 "ob_proxy_parser_utf8.l" { ObProxyParseResult *p = (ObProxyParseResult *)yyextra; if (OB_NOTNULL(p)) { @@ -4664,39 +7605,39 @@ YY_RULE_SETUP return COMMENT_END; } YY_BREAK -case 248: +case 269: YY_RULE_SETUP -#line 885 "ob_proxy_parser_utf8.l" +#line 947 "ob_proxy_parser_utf8.l" {return yytext[0];} YY_BREAK -case 249: +case 270: YY_RULE_SETUP -#line 886 "ob_proxy_parser_utf8.l" +#line 948 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_dbp_comment_trace_value_expr); return '('; } YY_BREAK -case 250: -/* rule 250 can match eol */ +case 271: +/* rule 271 can match eol */ YY_RULE_SETUP -#line 887 "ob_proxy_parser_utf8.l" +#line 949 "ob_proxy_parser_utf8.l" {} YY_BREAK -case 251: +case 272: YY_RULE_SETUP -#line 889 "ob_proxy_parser_utf8.l" +#line 951 "ob_proxy_parser_utf8.l" { ENTER_QUOTE_STATE(comment_sq); } YY_BREAK -case 252: +case 273: YY_RULE_SETUP -#line 890 "ob_proxy_parser_utf8.l" +#line 952 "ob_proxy_parser_utf8.l" { POP_STATE(); POP_STATE(); return ')'; } YY_BREAK -case 253: +case 274: YY_RULE_SETUP -#line 895 "ob_proxy_parser_utf8.l" +#line 957 "ob_proxy_parser_utf8.l" { do { PUSH_STATE(in_dbp_comment_trace_value_expr_calc) @@ -4710,9 +7651,9 @@ YY_RULE_SETUP } while (0); } YY_BREAK -case 254: +case 275: YY_RULE_SETUP -#line 907 "ob_proxy_parser_utf8.l" +#line 969 "ob_proxy_parser_utf8.l" { ObProxyParseResult *p = (ObProxyParseResult *)yyextra; if (OB_NOTNULL(p)) { @@ -4726,15 +7667,15 @@ YY_RULE_SETUP return COMMENT_END; } YY_BREAK -case 255: -/* rule 255 can match eol */ +case 276: +/* rule 276 can match eol */ YY_RULE_SETUP -#line 919 "ob_proxy_parser_utf8.l" +#line 981 "ob_proxy_parser_utf8.l" {} YY_BREAK -case 256: +case 277: YY_RULE_SETUP -#line 920 "ob_proxy_parser_utf8.l" +#line 982 "ob_proxy_parser_utf8.l" { do { PUSH_STATE(in_dbp_comment_trace_value_expr_calc) @@ -4747,10 +7688,10 @@ YY_RULE_SETUP } while (0); } YY_BREAK -case 257: -/* rule 257 can match eol */ +case 278: +/* rule 278 can match eol */ YY_RULE_SETUP -#line 932 "ob_proxy_parser_utf8.l" +#line 994 "ob_proxy_parser_utf8.l" { POP_STATE(); ObProxyParseResult *p = (ObProxyParseResult *)yyextra; @@ -4763,9 +7704,9 @@ YY_RULE_SETUP } } YY_BREAK -case 258: +case 279: YY_RULE_SETUP -#line 944 "ob_proxy_parser_utf8.l" +#line 1006 "ob_proxy_parser_utf8.l" { ObProxyParseResult *p = (ObProxyParseResult *)yyextra; if (OB_NOTNULL(p)) { @@ -4774,9 +7715,9 @@ YY_RULE_SETUP } YY_BREAK /* quote */ -case 259: +case 280: YY_RULE_SETUP -#line 952 "ob_proxy_parser_utf8.l" +#line 1014 "ob_proxy_parser_utf8.l" { PUSH_STATE(sq); ObProxyParseResult *p = (ObProxyParseResult *)yyextra; @@ -4787,10 +7728,10 @@ YY_RULE_SETUP } } YY_BREAK -case 260: -/* rule 260 can match eol */ +case 281: +/* rule 281 can match eol */ YY_RULE_SETUP -#line 962 "ob_proxy_parser_utf8.l" +#line 1024 "ob_proxy_parser_utf8.l" { ObProxyParseResult *p = (ObProxyParseResult *)yyextra; if (OB_NOTNULL(p)) { @@ -4798,9 +7739,9 @@ YY_RULE_SETUP } } YY_BREAK -case 261: +case 282: YY_RULE_SETUP -#line 969 "ob_proxy_parser_utf8.l" +#line 1031 "ob_proxy_parser_utf8.l" { POP_STATE(); ObProxyParseResult *p = (ObProxyParseResult *)yyextra; @@ -4808,7 +7749,8 @@ YY_RULE_SETUP && OBPROXY_T_INVALID < p->cur_stmt_type_ && (p->cur_stmt_type_ < OBPROXY_T_ICMD_MAX || OBPROXY_T_CALL == p->cur_stmt_type_ - || OBPROXY_T_SET == p->cur_stmt_type_) + || OBPROXY_T_SET == p->cur_stmt_type_ + || OBPROXY_T_SHOW == p->cur_stmt_type_) && OB_NOTNULL(p->tmp_buf_)) { store_str_with_quote(OBPROXY_QUOTE_T_SINGLE, p->tmp_buf_, p->tmp_len_, p->tmp_start_ptr_ + p->tmp_len_ + 2, yyscanner); return NAME_OB; @@ -4817,32 +7759,32 @@ YY_RULE_SETUP } } YY_BREAK -case 262: +case 283: YY_RULE_SETUP -#line 985 "ob_proxy_parser_utf8.l" +#line 1048 "ob_proxy_parser_utf8.l" {} YY_BREAK -case 263: -/* rule 263 can match eol */ +case 284: +/* rule 284 can match eol */ YY_RULE_SETUP -#line 986 "ob_proxy_parser_utf8.l" +#line 1049 "ob_proxy_parser_utf8.l" {} YY_BREAK -case 264: -/* rule 264 can match eol */ +case 285: +/* rule 285 can match eol */ YY_RULE_SETUP -#line 987 "ob_proxy_parser_utf8.l" +#line 1050 "ob_proxy_parser_utf8.l" {} YY_BREAK case YY_STATE_EOF(sq): -#line 988 "ob_proxy_parser_utf8.l" +#line 1051 "ob_proxy_parser_utf8.l" { return ERROR; } YY_BREAK /* comment sq return name_str */ -case 265: -/* rule 265 can match eol */ +case 286: +/* rule 286 can match eol */ YY_RULE_SETUP -#line 991 "ob_proxy_parser_utf8.l" +#line 1054 "ob_proxy_parser_utf8.l" { ObProxyParseResult *p = (ObProxyParseResult *)yyextra; if (OB_NOTNULL(p)) { @@ -4850,9 +7792,9 @@ YY_RULE_SETUP } } YY_BREAK -case 266: +case 287: YY_RULE_SETUP -#line 998 "ob_proxy_parser_utf8.l" +#line 1061 "ob_proxy_parser_utf8.l" { POP_STATE(); ObProxyParseResult *p = (ObProxyParseResult *)yyextra; @@ -4864,31 +7806,31 @@ YY_RULE_SETUP } } YY_BREAK -case 267: +case 288: YY_RULE_SETUP -#line 1009 "ob_proxy_parser_utf8.l" +#line 1072 "ob_proxy_parser_utf8.l" {} YY_BREAK -case 268: -/* rule 268 can match eol */ +case 289: +/* rule 289 can match eol */ YY_RULE_SETUP -#line 1010 "ob_proxy_parser_utf8.l" +#line 1073 "ob_proxy_parser_utf8.l" {} YY_BREAK -case 269: -/* rule 269 can match eol */ +case 290: +/* rule 290 can match eol */ YY_RULE_SETUP -#line 1011 "ob_proxy_parser_utf8.l" +#line 1074 "ob_proxy_parser_utf8.l" {} YY_BREAK case YY_STATE_EOF(comment_sq): -#line 1012 "ob_proxy_parser_utf8.l" +#line 1075 "ob_proxy_parser_utf8.l" { return ERROR; } YY_BREAK /* dquote */ -case 270: +case 291: YY_RULE_SETUP -#line 1015 "ob_proxy_parser_utf8.l" +#line 1078 "ob_proxy_parser_utf8.l" { PUSH_STATE(dq); ObProxyParseResult *p = (ObProxyParseResult *)yyextra; @@ -4899,10 +7841,10 @@ YY_RULE_SETUP } } YY_BREAK -case 271: -/* rule 271 can match eol */ +case 292: +/* rule 292 can match eol */ YY_RULE_SETUP -#line 1025 "ob_proxy_parser_utf8.l" +#line 1088 "ob_proxy_parser_utf8.l" { ObProxyParseResult *p = (ObProxyParseResult *)yyextra; if (OB_NOTNULL(p)) { @@ -4910,9 +7852,9 @@ YY_RULE_SETUP } } YY_BREAK -case 272: +case 293: YY_RULE_SETUP -#line 1032 "ob_proxy_parser_utf8.l" +#line 1095 "ob_proxy_parser_utf8.l" { POP_STATE(); ObProxyParseResult *p = (ObProxyParseResult *)yyextra; @@ -4920,7 +7862,8 @@ YY_RULE_SETUP && OBPROXY_T_INVALID < p->cur_stmt_type_ && (p->cur_stmt_type_ < OBPROXY_T_ICMD_MAX || OBPROXY_T_CALL == p->cur_stmt_type_ - || OBPROXY_T_SET == p->cur_stmt_type_) + || OBPROXY_T_SET == p->cur_stmt_type_ + || OBPROXY_T_SHOW == p->cur_stmt_type_) && OB_NOTNULL(p->tmp_buf_)) { store_str_with_quote(OBPROXY_QUOTE_T_DOUBLE, p->tmp_buf_, p->tmp_len_, p->tmp_start_ptr_ + p->tmp_len_ + 2, yyscanner); return NAME_OB; @@ -4929,31 +7872,31 @@ YY_RULE_SETUP } } YY_BREAK -case 273: +case 294: YY_RULE_SETUP -#line 1048 "ob_proxy_parser_utf8.l" +#line 1112 "ob_proxy_parser_utf8.l" {} YY_BREAK -case 274: -/* rule 274 can match eol */ +case 295: +/* rule 295 can match eol */ YY_RULE_SETUP -#line 1049 "ob_proxy_parser_utf8.l" +#line 1113 "ob_proxy_parser_utf8.l" {} YY_BREAK -case 275: -/* rule 275 can match eol */ +case 296: +/* rule 296 can match eol */ YY_RULE_SETUP -#line 1050 "ob_proxy_parser_utf8.l" +#line 1114 "ob_proxy_parser_utf8.l" {} YY_BREAK case YY_STATE_EOF(dq): -#line 1051 "ob_proxy_parser_utf8.l" +#line 1115 "ob_proxy_parser_utf8.l" { return ERROR; } YY_BREAK /* backtick */ -case 276: +case 297: YY_RULE_SETUP -#line 1055 "ob_proxy_parser_utf8.l" +#line 1119 "ob_proxy_parser_utf8.l" { PUSH_STATE(bt); ObProxyParseResult *p = (ObProxyParseResult *)yyextra; @@ -4964,9 +7907,9 @@ YY_RULE_SETUP } } YY_BREAK -case 277: +case 298: YY_RULE_SETUP -#line 1065 "ob_proxy_parser_utf8.l" +#line 1129 "ob_proxy_parser_utf8.l" { ObProxyParseResult *p = (ObProxyParseResult *)yyextra; if (NULL != p && NULL != p->tmp_buf_ && p->tmp_len_ + 1 < OBPROXY_MAX_NAME_LENGTH) { @@ -4974,10 +7917,10 @@ YY_RULE_SETUP } } YY_BREAK -case 278: -/* rule 278 can match eol */ +case 299: +/* rule 299 can match eol */ YY_RULE_SETUP -#line 1072 "ob_proxy_parser_utf8.l" +#line 1136 "ob_proxy_parser_utf8.l" { ObProxyParseResult *p = (ObProxyParseResult *)yyextra; if (NULL != p && NULL != p->tmp_buf_ && p->tmp_len_ + yyleng < OBPROXY_MAX_NAME_LENGTH) { @@ -4986,9 +7929,9 @@ YY_RULE_SETUP } } YY_BREAK -case 279: +case 300: YY_RULE_SETUP -#line 1080 "ob_proxy_parser_utf8.l" +#line 1144 "ob_proxy_parser_utf8.l" { POP_STATE(); ObProxyParseResult *p = (ObProxyParseResult *)yyextra; @@ -5002,243 +7945,242 @@ YY_RULE_SETUP } YY_BREAK case YY_STATE_EOF(bt): -#line 1092 "ob_proxy_parser_utf8.l" +#line 1156 "ob_proxy_parser_utf8.l" { return ERROR; } YY_BREAK -case 280: +case 301: YY_RULE_SETUP -#line 1096 "ob_proxy_parser_utf8.l" +#line 1160 "ob_proxy_parser_utf8.l" {} YY_BREAK -case 281: -/* rule 281 can match eol */ +case 302: +/* rule 302 can match eol */ YY_RULE_SETUP -#line 1097 "ob_proxy_parser_utf8.l" +#line 1161 "ob_proxy_parser_utf8.l" {} YY_BREAK -case 282: +case 303: YY_RULE_SETUP -#line 1098 "ob_proxy_parser_utf8.l" +#line 1162 "ob_proxy_parser_utf8.l" { POP_STATE(); RETURN_IGNORED_WORD(); } YY_BREAK case YY_STATE_EOF(bt_in_expr): -#line 1099 "ob_proxy_parser_utf8.l" +#line 1163 "ob_proxy_parser_utf8.l" { return ERROR; } YY_BREAK /* some useful keyword */ -case 283: -/* rule 283 can match eol */ +case 304: +/* rule 304 can match eol */ YY_RULE_SETUP -#line 1102 "ob_proxy_parser_utf8.l" +#line 1166 "ob_proxy_parser_utf8.l" { RETURN_IGNORED_WORD_FOR_DUAL(); } YY_BREAK -case 284: +case 305: YY_RULE_SETUP -#line 1103 "ob_proxy_parser_utf8.l" +#line 1167 "ob_proxy_parser_utf8.l" { POP_STATE(); PUSH_STATE(INITIAL); return FROM; } YY_BREAK -case 285: +case 306: YY_RULE_SETUP -#line 1104 "ob_proxy_parser_utf8.l" +#line 1168 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_subquery); return '('; } YY_BREAK -case 286: +case 307: YY_RULE_SETUP -#line 1105 "ob_proxy_parser_utf8.l" +#line 1169 "ob_proxy_parser_utf8.l" { PUSH_STATE(dq); } YY_BREAK -case 287: +case 308: YY_RULE_SETUP -#line 1106 "ob_proxy_parser_utf8.l" +#line 1170 "ob_proxy_parser_utf8.l" { PUSH_STATE(sq); } YY_BREAK -case 288: +case 309: YY_RULE_SETUP -#line 1107 "ob_proxy_parser_utf8.l" +#line 1171 "ob_proxy_parser_utf8.l" { PUSH_STATE(bt_in_expr); } YY_BREAK -case 289: +case 310: YY_RULE_SETUP -#line 1108 "ob_proxy_parser_utf8.l" +#line 1172 "ob_proxy_parser_utf8.l" { SET_FOUND_ROWS(); RETURN_IGNORED_WORD(); } YY_BREAK -case 290: +case 311: YY_RULE_SETUP -#line 1109 "ob_proxy_parser_utf8.l" +#line 1173 "ob_proxy_parser_utf8.l" { SET_ROW_COUNT(); RETURN_IGNORED_WORD(); } YY_BREAK -case 291: +case 312: YY_RULE_SETUP -#line 1110 "ob_proxy_parser_utf8.l" +#line 1174 "ob_proxy_parser_utf8.l" { SET_LAST_INSERT_ID(); RETURN_IGNORED_WORD(); } YY_BREAK -case 292: +case 313: YY_RULE_SETUP -#line 1111 "ob_proxy_parser_utf8.l" +#line 1175 "ob_proxy_parser_utf8.l" { SET_GLOBAL_SET_STMT(); RETURN_IGNORED_WORD(); } YY_BREAK -case 293: -/* rule 293 can match eol */ +case 314: +/* rule 314 can match eol */ YY_RULE_SETUP -#line 1112 "ob_proxy_parser_utf8.l" +#line 1176 "ob_proxy_parser_utf8.l" { RETURN_COL_NAME(TX_READ_ONLY); } YY_BREAK -case 294: -/* rule 294 can match eol */ -YY_RULE_SETUP -#line 1113 "ob_proxy_parser_utf8.l" -{ return AUTOCOMMIT_0; } - YY_BREAK -case 295: +case 315: YY_RULE_SETUP -#line 1114 "ob_proxy_parser_utf8.l" +#line 1177 "ob_proxy_parser_utf8.l" { RETURN_IGNORED_WORD(); } YY_BREAK case YY_STATE_EOF(in_expr): -#line 1115 "ob_proxy_parser_utf8.l" +#line 1178 "ob_proxy_parser_utf8.l" { return END_P; } YY_BREAK -case 296: -/* rule 296 can match eol */ +case 316: +/* rule 316 can match eol */ YY_RULE_SETUP -#line 1116 "ob_proxy_parser_utf8.l" +#line 1179 "ob_proxy_parser_utf8.l" { } YY_BREAK -case 297: +case 317: YY_RULE_SETUP -#line 1117 "ob_proxy_parser_utf8.l" +#line 1180 "ob_proxy_parser_utf8.l" { POP_STATE(); PUSH_STATE(INITIAL); return yytext[0]; } YY_BREAK -case 298: +case 318: YY_RULE_SETUP -#line 1118 "ob_proxy_parser_utf8.l" +#line 1181 "ob_proxy_parser_utf8.l" { RETURN_IGNORED_WORD(); } YY_BREAK -case 299: +case 319: YY_RULE_SETUP -#line 1120 "ob_proxy_parser_utf8.l" +#line 1183 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_expr); return SELECT; } YY_BREAK -case 300: +case 320: YY_RULE_SETUP -#line 1121 "ob_proxy_parser_utf8.l" +#line 1184 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_subquery); return '('; } YY_BREAK -case 301: +case 321: YY_RULE_SETUP -#line 1122 "ob_proxy_parser_utf8.l" +#line 1185 "ob_proxy_parser_utf8.l" { POP_STATE(); return ')'; } YY_BREAK -case 302: +case 322: YY_RULE_SETUP -#line 1123 "ob_proxy_parser_utf8.l" +#line 1186 "ob_proxy_parser_utf8.l" { PUSH_STATE(dq); } YY_BREAK -case 303: +case 323: YY_RULE_SETUP -#line 1124 "ob_proxy_parser_utf8.l" +#line 1187 "ob_proxy_parser_utf8.l" { PUSH_STATE(sq); } YY_BREAK case YY_STATE_EOF(in_subquery): -#line 1125 "ob_proxy_parser_utf8.l" +#line 1188 "ob_proxy_parser_utf8.l" { return END_P; } YY_BREAK -case 304: -/* rule 304 can match eol */ +case 324: +/* rule 324 can match eol */ YY_RULE_SETUP -#line 1126 "ob_proxy_parser_utf8.l" +#line 1189 "ob_proxy_parser_utf8.l" { } YY_BREAK -case 305: +case 325: YY_RULE_SETUP -#line 1127 "ob_proxy_parser_utf8.l" +#line 1190 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_no_select_query); RETURN_IGNORED_WORD(); } YY_BREAK -case 306: +case 326: YY_RULE_SETUP -#line 1129 "ob_proxy_parser_utf8.l" +#line 1192 "ob_proxy_parser_utf8.l" { PUSH_STATE(in_subquery); return '('; } YY_BREAK -case 307: +case 327: YY_RULE_SETUP -#line 1130 "ob_proxy_parser_utf8.l" +#line 1193 "ob_proxy_parser_utf8.l" { POP_STATE(); POP_STATE(); return ')'; } YY_BREAK -case 308: +case 328: YY_RULE_SETUP -#line 1131 "ob_proxy_parser_utf8.l" +#line 1194 "ob_proxy_parser_utf8.l" { PUSH_STATE(dq); } YY_BREAK -case 309: +case 329: YY_RULE_SETUP -#line 1132 "ob_proxy_parser_utf8.l" +#line 1195 "ob_proxy_parser_utf8.l" { PUSH_STATE(sq); } YY_BREAK -case 310: +case 330: YY_RULE_SETUP -#line 1133 "ob_proxy_parser_utf8.l" +#line 1196 "ob_proxy_parser_utf8.l" { SET_FOUND_ROWS(); RETURN_IGNORED_WORD(); } YY_BREAK -case 311: +case 331: YY_RULE_SETUP -#line 1134 "ob_proxy_parser_utf8.l" +#line 1197 "ob_proxy_parser_utf8.l" { SET_ROW_COUNT(); RETURN_IGNORED_WORD(); } YY_BREAK -case 312: +case 332: YY_RULE_SETUP -#line 1135 "ob_proxy_parser_utf8.l" +#line 1198 "ob_proxy_parser_utf8.l" { SET_LAST_INSERT_ID(); RETURN_IGNORED_WORD(); } YY_BREAK -case 313: +case 333: YY_RULE_SETUP -#line 1136 "ob_proxy_parser_utf8.l" +#line 1199 "ob_proxy_parser_utf8.l" { RETURN_IGNORED_WORD(); } YY_BREAK case YY_STATE_EOF(in_no_select_query): -#line 1137 "ob_proxy_parser_utf8.l" +#line 1200 "ob_proxy_parser_utf8.l" { return END_P; } YY_BREAK -case 314: -/* rule 314 can match eol */ +case 334: +/* rule 334 can match eol */ YY_RULE_SETUP -#line 1138 "ob_proxy_parser_utf8.l" +#line 1201 "ob_proxy_parser_utf8.l" { } YY_BREAK -case 315: +case 335: YY_RULE_SETUP -#line 1139 "ob_proxy_parser_utf8.l" +#line 1202 "ob_proxy_parser_utf8.l" { RETURN_IGNORED_WORD(); } YY_BREAK -case 316: +case 336: YY_RULE_SETUP -#line 1141 "ob_proxy_parser_utf8.l" +#line 1204 "ob_proxy_parser_utf8.l" { return FROM; } YY_BREAK -case 317: +case 337: +YY_RULE_SETUP +#line 1205 "ob_proxy_parser_utf8.l" +{ return yytext[0]; } + YY_BREAK +case 338: YY_RULE_SETUP -#line 1142 "ob_proxy_parser_utf8.l" +#line 1206 "ob_proxy_parser_utf8.l" { RETURN_NON_RESERVED_KEYWORD(NAME_OB); } YY_BREAK -case 318: +case 339: YY_RULE_SETUP -#line 1143 "ob_proxy_parser_utf8.l" +#line 1207 "ob_proxy_parser_utf8.l" { POP_STATE(); } YY_BREAK -case 319: +case 340: YY_RULE_SETUP -#line 1144 "ob_proxy_parser_utf8.l" +#line 1208 "ob_proxy_parser_utf8.l" { POP_STATE(); } YY_BREAK -case 320: +case 341: YY_RULE_SETUP -#line 1146 "ob_proxy_parser_utf8.l" -{ POP_STATE(); return BEGI;} +#line 1210 "ob_proxy_parser_utf8.l" +{ POP_STATE(); RETURN_NON_RESERVED_KEYWORD(BEGI);} YY_BREAK -case 321: +case 342: YY_RULE_SETUP -#line 1147 "ob_proxy_parser_utf8.l" +#line 1211 "ob_proxy_parser_utf8.l" {} YY_BREAK case YY_STATE_EOF(INITIAL): @@ -5257,20 +8199,22 @@ case YY_STATE_EOF(in_dbp_comment_trace_value_expr_calc): case YY_STATE_EOF(in_anonymous_block): case YY_STATE_EOF(prepare): case YY_STATE_EOF(insert_all_expr): -#line 1149 "ob_proxy_parser_utf8.l" +case YY_STATE_EOF(show_topology): +case YY_STATE_EOF(proxy_icmd_state): +#line 1213 "ob_proxy_parser_utf8.l" { return END_P; } YY_BREAK -case 322: +case 343: YY_RULE_SETUP -#line 1150 "ob_proxy_parser_utf8.l" +#line 1214 "ob_proxy_parser_utf8.l" { RETURN_IGNORED_WORD(); } YY_BREAK -case 323: +case 344: YY_RULE_SETUP -#line 1151 "ob_proxy_parser_utf8.l" +#line 1215 "ob_proxy_parser_utf8.l" ECHO; YY_BREAK -#line 5276 "ob_proxy_parser_utf8_lex.c" +#line 8220 "ob_proxy_parser_utf8_lex.c" case YY_END_OF_BUFFER: { @@ -5562,7 +8506,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 2102 ) + if ( yy_current_state >= 2787 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -5591,11 +8535,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 2102 ) + if ( yy_current_state >= 2787 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 2101); + yy_is_jam = (yy_current_state == 2786); return yy_is_jam ? 0 : yy_current_state; } @@ -6420,7 +9364,7 @@ static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) #define YYTABLES_NAME "yytables" -#line 1151 "ob_proxy_parser_utf8.l" +#line 1215 "ob_proxy_parser_utf8.l" inline void *ob_proxy_parser_utf8_yyalloc(size_t bytes,void *yyscanner) @@ -6569,152 +9513,165 @@ extern int ob_proxy_parser_utf8_yydebug; TRUNCATE = 272, RENAME = 273, TABLE = 274, - UNIQUE = 275, - GRANT = 276, - REVOKE = 277, - ANALYZE = 278, - PURGE = 279, - COMMENT = 280, - FROM = 281, - DUAL = 282, - PREPARE = 283, - EXECUTE = 284, - USING = 285, - SELECT_HINT_BEGIN = 286, - UPDATE_HINT_BEGIN = 287, - DELETE_HINT_BEGIN = 288, - INSERT_HINT_BEGIN = 289, - REPLACE_HINT_BEGIN = 290, - MERGE_HINT_BEGIN = 291, - HINT_END = 292, - COMMENT_BEGIN = 293, - COMMENT_END = 294, - ROUTE_TABLE = 295, - ROUTE_PART_KEY = 296, - QUERY_TIMEOUT = 297, - READ_CONSISTENCY = 298, - WEAK = 299, - STRONG = 300, - FROZEN = 301, - PLACE_HOLDER = 302, - END_P = 303, - ERROR = 304, - WHEN = 305, - FLASHBACK = 306, - AUDIT = 307, - NOAUDIT = 308, - BEGI = 309, - START = 310, - TRANSACTION = 311, - READ = 312, - ONLY = 313, - WITH = 314, - CONSISTENT = 315, - SNAPSHOT = 316, - INDEX = 317, - XA = 318, - WARNINGS = 319, - ERRORS = 320, - TRACE = 321, - QUICK = 322, - COUNT = 323, - AS = 324, - WHERE = 325, - VALUES = 326, - ORDER = 327, - GROUP = 328, - HAVING = 329, - INTO = 330, - UNION = 331, - FOR = 332, - TX_READ_ONLY = 333, - AUTOCOMMIT_0 = 334, - SELECT_OBPROXY_ROUTE_ADDR = 335, - SET_OBPROXY_ROUTE_ADDR = 336, - NAME_OB_DOT = 337, - NAME_OB = 338, - EXPLAIN = 339, - DESC = 340, - DESCRIBE = 341, - NAME_STR = 342, - USE = 343, - HELP = 344, - SET_NAMES = 345, - SET_CHARSET = 346, - SET_PASSWORD = 347, - SET_DEFAULT = 348, - SET_OB_READ_CONSISTENCY = 349, - SET_TX_READ_ONLY = 350, - GLOBAL = 351, - SESSION = 352, - NUMBER_VAL = 353, - GROUP_ID = 354, - TABLE_ID = 355, - ELASTIC_ID = 356, - TESTLOAD = 357, - ODP_COMMENT = 358, - TNT_ID = 359, - DISASTER_STATUS = 360, - TRACE_ID = 361, - RPC_ID = 362, - DBP_COMMENT = 363, - ROUTE_TAG = 364, - SYS_TAG = 365, - TABLE_NAME = 366, - SCAN_ALL = 367, - PARALL = 368, - SHARD_KEY = 369, - INT_NUM = 370, - SHOW_PROXYNET = 371, - THREAD = 372, - CONNECTION = 373, - LIMIT = 374, - OFFSET = 375, - SHOW_PROCESSLIST = 376, - SHOW_PROXYSESSION = 377, - SHOW_GLOBALSESSION = 378, - ATTRIBUTE = 379, - VARIABLES = 380, - ALL = 381, - STAT = 382, - SHOW_PROXYCONFIG = 383, - DIFF = 384, - USER = 385, - LIKE = 386, - SHOW_PROXYSM = 387, - SHOW_PROXYCLUSTER = 388, - SHOW_PROXYRESOURCE = 389, - SHOW_PROXYCONGESTION = 390, - SHOW_PROXYROUTE = 391, - PARTITION = 392, - ROUTINE = 393, - SHOW_PROXYVIP = 394, - SHOW_PROXYMEMORY = 395, - OBJPOOL = 396, - SHOW_SQLAUDIT = 397, - SHOW_WARNLOG = 398, - SHOW_PROXYSTAT = 399, - REFRESH = 400, - SHOW_PROXYTRACE = 401, - SHOW_PROXYINFO = 402, - BINARY = 403, - UPGRADE = 404, - IDC = 405, - SHOW_TOPOLOGY = 406, - GROUP_NAME = 407, - SHOW_DB_VERSION = 408, - SHOW_DATABASES = 409, - SHOW_TABLES = 410, - SELECT_DATABASE = 411, - SHOW_CREATE_TABLE = 412, - SELECT_PROXY_VERSION = 413, - ALTER_PROXYCONFIG = 414, - ALTER_PROXYRESOURCE = 415, - PING_PROXY = 416, - KILL_PROXYSESSION = 417, - KILL_GLOBALSESSION = 418, - KILL = 419, - QUERY = 420 + STATUS = 275, + UNIQUE = 276, + GRANT = 277, + REVOKE = 278, + ANALYZE = 279, + PURGE = 280, + COMMENT = 281, + FROM = 282, + DUAL = 283, + PREPARE = 284, + EXECUTE = 285, + USING = 286, + DEALLOCATE = 287, + SELECT_HINT_BEGIN = 288, + UPDATE_HINT_BEGIN = 289, + DELETE_HINT_BEGIN = 290, + INSERT_HINT_BEGIN = 291, + REPLACE_HINT_BEGIN = 292, + MERGE_HINT_BEGIN = 293, + HINT_END = 294, + COMMENT_BEGIN = 295, + COMMENT_END = 296, + ROUTE_TABLE = 297, + ROUTE_PART_KEY = 298, + QUERY_TIMEOUT = 299, + READ_CONSISTENCY = 300, + WEAK = 301, + STRONG = 302, + FROZEN = 303, + PLACE_HOLDER = 304, + END_P = 305, + ERROR = 306, + WHEN = 307, + FLASHBACK = 308, + AUDIT = 309, + NOAUDIT = 310, + BEGI = 311, + START = 312, + TRANSACTION = 313, + READ = 314, + ONLY = 315, + WITH = 316, + CONSISTENT = 317, + SNAPSHOT = 318, + INDEX = 319, + XA = 320, + WARNINGS = 321, + ERRORS = 322, + TRACE = 323, + QUICK = 324, + COUNT = 325, + AS = 326, + WHERE = 327, + VALUES = 328, + ORDER = 329, + GROUP = 330, + HAVING = 331, + INTO = 332, + UNION = 333, + FOR = 334, + TX_READ_ONLY = 335, + SELECT_OBPROXY_ROUTE_ADDR = 336, + SET_OBPROXY_ROUTE_ADDR = 337, + NAME_OB_DOT = 338, + NAME_OB = 339, + EXPLAIN = 340, + DESC = 341, + DESCRIBE = 342, + NAME_STR = 343, + USE = 344, + HELP = 345, + SET_NAMES = 346, + SET_CHARSET = 347, + SET_PASSWORD = 348, + SET_DEFAULT = 349, + SET_OB_READ_CONSISTENCY = 350, + SET_TX_READ_ONLY = 351, + GLOBAL = 352, + SESSION = 353, + NUMBER_VAL = 354, + GROUP_ID = 355, + TABLE_ID = 356, + ELASTIC_ID = 357, + TESTLOAD = 358, + ODP_COMMENT = 359, + TNT_ID = 360, + DISASTER_STATUS = 361, + TRACE_ID = 362, + RPC_ID = 363, + TARGET_DB_SERVER = 364, + DBP_COMMENT = 365, + ROUTE_TAG = 366, + SYS_TAG = 367, + TABLE_NAME = 368, + SCAN_ALL = 369, + STICKY_SESSION = 370, + PARALL = 371, + SHARD_KEY = 372, + INT_NUM = 373, + SHOW_PROXYNET = 374, + THREAD = 375, + CONNECTION = 376, + LIMIT = 377, + OFFSET = 378, + SHOW_PROCESSLIST = 379, + SHOW_PROXYSESSION = 380, + SHOW_GLOBALSESSION = 381, + ATTRIBUTE = 382, + VARIABLES = 383, + ALL = 384, + STAT = 385, + SHOW_PROXYCONFIG = 386, + DIFF = 387, + USER = 388, + LIKE = 389, + SHOW_PROXYSM = 390, + SHOW_PROXYCLUSTER = 391, + SHOW_PROXYRESOURCE = 392, + SHOW_PROXYCONGESTION = 393, + SHOW_PROXYROUTE = 394, + PARTITION = 395, + ROUTINE = 396, + SHOW_PROXYVIP = 397, + SHOW_PROXYMEMORY = 398, + OBJPOOL = 399, + SHOW_SQLAUDIT = 400, + SHOW_WARNLOG = 401, + SHOW_PROXYSTAT = 402, + REFRESH = 403, + SHOW_PROXYTRACE = 404, + SHOW_PROXYINFO = 405, + BINARY = 406, + UPGRADE = 407, + IDC = 408, + SHOW_ELASTIC_ID = 409, + SHOW_TOPOLOGY = 410, + GROUP_NAME = 411, + SHOW_DB_VERSION = 412, + SHOW_DATABASES = 413, + SHOW_TABLES = 414, + SHOW_FULL_TABLES = 415, + SELECT_DATABASE = 416, + SHOW_CREATE_TABLE = 417, + SELECT_PROXY_VERSION = 418, + SHOW_COLUMNS = 419, + SHOW_INDEX = 420, + ALTER_PROXYCONFIG = 421, + ALTER_PROXYRESOURCE = 422, + PING_PROXY = 423, + KILL_PROXYSESSION = 424, + KILL_GLOBALSESSION = 425, + KILL = 426, + QUERY = 427, + SHOW_MASTER_STATUS = 428, + SHOW_BINARY_LOGS = 429, + SHOW_BINLOG_EVENTS = 430, + PURGE_BINARY_LOGS = 431, + RESET_MASTER = 432, + SHOW_BINLOG_SERVER_FOR_TENANT = 433 }; #endif diff --git a/src/obproxy/opsql/parser/ob_proxy_parser_utf8_lex.h b/src/obproxy/opsql/parser/ob_proxy_parser_utf8_lex.h index 17fecf15347cdf695f73fca4ca2d361c96a2ad82..4cb2afb957c2ecb080ed0f7e9d479076e371b696 100644 --- a/src/obproxy/opsql/parser/ob_proxy_parser_utf8_lex.h +++ b/src/obproxy/opsql/parser/ob_proxy_parser_utf8_lex.h @@ -244,7 +244,10 @@ void ob_proxy_parser_utf8_yyfree (void * ,yyscan_t yyscanner ); #define prepare 22 #define insert_all_expr 23 #define set_expr 24 -#define show_topology 25 +#define show_elastic_id 25 +#define show_topology 26 +#define show_tables 27 +#define proxy_icmd_state 28 #endif @@ -362,9 +365,9 @@ extern int ob_proxy_parser_utf8_yylex \ #undef YY_DECL #endif -#line 1151 "ob_proxy_parser_utf8.l" +#line 1215 "ob_proxy_parser_utf8.l" -#line 369 "ob_proxy_parser_utf8_lex.h" +#line 372 "ob_proxy_parser_utf8_lex.h" #undef ob_proxy_parser_utf8_yyIN_HEADER #endif /* ob_proxy_parser_utf8_yyHEADER_H */ diff --git a/src/obproxy/opsql/parser/ob_proxy_parser_utf8_tab.c b/src/obproxy/opsql/parser/ob_proxy_parser_utf8_tab.c index 0c60398f75312da01031df667017ae27d3a481a2..0ae9f5266328cec8b4212ac29d1a95eacc6aa9ce 100644 --- a/src/obproxy/opsql/parser/ob_proxy_parser_utf8_tab.c +++ b/src/obproxy/opsql/parser/ob_proxy_parser_utf8_tab.c @@ -112,9 +112,6 @@ static inline void handle_stmt_end(ObProxyParseResult* result) case OBPROXY_T_SELECT_TX_RO: result->stmt_type_ = OBPROXY_T_SELECT; break; - case OBPROXY_T_SET_AC_0: - result->stmt_type_ = OBPROXY_T_OTHERS; - break; case OBPROXY_T_BEGIN: result->stmt_type_ = OBPROXY_T_OTHERS; break; @@ -133,7 +130,7 @@ static inline void handle_stmt_end(ObProxyParseResult* result) } } else { result->stmt_type_ = result->cur_stmt_type_; - } + } if (OBPROXY_T_TEXT_PS_PREPARE == result->text_ps_inner_stmt_type_) { ObProxyBasicStmtType tmp_type = result->cur_stmt_type_; @@ -262,24 +259,24 @@ do { } \ } while(0) \ -#define add_text_ps_execute_node(text_ps_execute_parse_info, execute_parse_node) \ +#define add_text_ps_node(text_ps_parse_info, parse_node) \ do { \ - if (NULL != text_ps_execute_parse_info.tail_) {\ - text_ps_execute_parse_info.tail_->next_ = execute_parse_node;\ - text_ps_execute_parse_info.tail_ = execute_parse_node;\ + if (NULL != text_ps_parse_info.tail_) {\ + text_ps_parse_info.tail_->next_ = parse_node;\ + text_ps_parse_info.tail_ = parse_node;\ } else {\ - text_ps_execute_parse_info.head_ = execute_parse_node;\ - text_ps_execute_parse_info.tail_ = execute_parse_node;\ + text_ps_parse_info.head_ = parse_node;\ + text_ps_parse_info.tail_ = parse_node;\ }\ - ++text_ps_execute_parse_info.node_count_;\ + ++text_ps_parse_info.node_count_;\ } while(0) -#define malloc_execute_parse_node(execute_parse_node) \ +#define malloc_parse_node(parse_node) \ do { \ - if (OB_ISNULL(execute_parse_node = ((ObProxyTextPsExecuteParseNode *)obproxy_parse_malloc(sizeof(ObProxyTextPsExecuteParseNode), result->malloc_pool_)))) { \ + if (OB_ISNULL(parse_node = ((ObProxyTextPsParseNode *)obproxy_parse_malloc(sizeof(ObProxyTextPsParseNode), result->malloc_pool_)))) { \ YYABORT; \ } else { \ - execute_parse_node->next_ = NULL; \ + parse_node->next_ = NULL; \ } \ } while(0) \ @@ -398,152 +395,165 @@ extern int ob_proxy_parser_utf8_yydebug; TRUNCATE = 272, RENAME = 273, TABLE = 274, - UNIQUE = 275, - GRANT = 276, - REVOKE = 277, - ANALYZE = 278, - PURGE = 279, - COMMENT = 280, - FROM = 281, - DUAL = 282, - PREPARE = 283, - EXECUTE = 284, - USING = 285, - SELECT_HINT_BEGIN = 286, - UPDATE_HINT_BEGIN = 287, - DELETE_HINT_BEGIN = 288, - INSERT_HINT_BEGIN = 289, - REPLACE_HINT_BEGIN = 290, - MERGE_HINT_BEGIN = 291, - HINT_END = 292, - COMMENT_BEGIN = 293, - COMMENT_END = 294, - ROUTE_TABLE = 295, - ROUTE_PART_KEY = 296, - QUERY_TIMEOUT = 297, - READ_CONSISTENCY = 298, - WEAK = 299, - STRONG = 300, - FROZEN = 301, - PLACE_HOLDER = 302, - END_P = 303, - ERROR = 304, - WHEN = 305, - FLASHBACK = 306, - AUDIT = 307, - NOAUDIT = 308, - BEGI = 309, - START = 310, - TRANSACTION = 311, - READ = 312, - ONLY = 313, - WITH = 314, - CONSISTENT = 315, - SNAPSHOT = 316, - INDEX = 317, - XA = 318, - WARNINGS = 319, - ERRORS = 320, - TRACE = 321, - QUICK = 322, - COUNT = 323, - AS = 324, - WHERE = 325, - VALUES = 326, - ORDER = 327, - GROUP = 328, - HAVING = 329, - INTO = 330, - UNION = 331, - FOR = 332, - TX_READ_ONLY = 333, - AUTOCOMMIT_0 = 334, - SELECT_OBPROXY_ROUTE_ADDR = 335, - SET_OBPROXY_ROUTE_ADDR = 336, - NAME_OB_DOT = 337, - NAME_OB = 338, - EXPLAIN = 339, - DESC = 340, - DESCRIBE = 341, - NAME_STR = 342, - USE = 343, - HELP = 344, - SET_NAMES = 345, - SET_CHARSET = 346, - SET_PASSWORD = 347, - SET_DEFAULT = 348, - SET_OB_READ_CONSISTENCY = 349, - SET_TX_READ_ONLY = 350, - GLOBAL = 351, - SESSION = 352, - NUMBER_VAL = 353, - GROUP_ID = 354, - TABLE_ID = 355, - ELASTIC_ID = 356, - TESTLOAD = 357, - ODP_COMMENT = 358, - TNT_ID = 359, - DISASTER_STATUS = 360, - TRACE_ID = 361, - RPC_ID = 362, - DBP_COMMENT = 363, - ROUTE_TAG = 364, - SYS_TAG = 365, - TABLE_NAME = 366, - SCAN_ALL = 367, - PARALL = 368, - SHARD_KEY = 369, - INT_NUM = 370, - SHOW_PROXYNET = 371, - THREAD = 372, - CONNECTION = 373, - LIMIT = 374, - OFFSET = 375, - SHOW_PROCESSLIST = 376, - SHOW_PROXYSESSION = 377, - SHOW_GLOBALSESSION = 378, - ATTRIBUTE = 379, - VARIABLES = 380, - ALL = 381, - STAT = 382, - SHOW_PROXYCONFIG = 383, - DIFF = 384, - USER = 385, - LIKE = 386, - SHOW_PROXYSM = 387, - SHOW_PROXYCLUSTER = 388, - SHOW_PROXYRESOURCE = 389, - SHOW_PROXYCONGESTION = 390, - SHOW_PROXYROUTE = 391, - PARTITION = 392, - ROUTINE = 393, - SHOW_PROXYVIP = 394, - SHOW_PROXYMEMORY = 395, - OBJPOOL = 396, - SHOW_SQLAUDIT = 397, - SHOW_WARNLOG = 398, - SHOW_PROXYSTAT = 399, - REFRESH = 400, - SHOW_PROXYTRACE = 401, - SHOW_PROXYINFO = 402, - BINARY = 403, - UPGRADE = 404, - IDC = 405, - SHOW_TOPOLOGY = 406, - GROUP_NAME = 407, - SHOW_DB_VERSION = 408, - SHOW_DATABASES = 409, - SHOW_TABLES = 410, - SELECT_DATABASE = 411, - SHOW_CREATE_TABLE = 412, - SELECT_PROXY_VERSION = 413, - ALTER_PROXYCONFIG = 414, - ALTER_PROXYRESOURCE = 415, - PING_PROXY = 416, - KILL_PROXYSESSION = 417, - KILL_GLOBALSESSION = 418, - KILL = 419, - QUERY = 420 + STATUS = 275, + UNIQUE = 276, + GRANT = 277, + REVOKE = 278, + ANALYZE = 279, + PURGE = 280, + COMMENT = 281, + FROM = 282, + DUAL = 283, + PREPARE = 284, + EXECUTE = 285, + USING = 286, + DEALLOCATE = 287, + SELECT_HINT_BEGIN = 288, + UPDATE_HINT_BEGIN = 289, + DELETE_HINT_BEGIN = 290, + INSERT_HINT_BEGIN = 291, + REPLACE_HINT_BEGIN = 292, + MERGE_HINT_BEGIN = 293, + HINT_END = 294, + COMMENT_BEGIN = 295, + COMMENT_END = 296, + ROUTE_TABLE = 297, + ROUTE_PART_KEY = 298, + QUERY_TIMEOUT = 299, + READ_CONSISTENCY = 300, + WEAK = 301, + STRONG = 302, + FROZEN = 303, + PLACE_HOLDER = 304, + END_P = 305, + ERROR = 306, + WHEN = 307, + FLASHBACK = 308, + AUDIT = 309, + NOAUDIT = 310, + BEGI = 311, + START = 312, + TRANSACTION = 313, + READ = 314, + ONLY = 315, + WITH = 316, + CONSISTENT = 317, + SNAPSHOT = 318, + INDEX = 319, + XA = 320, + WARNINGS = 321, + ERRORS = 322, + TRACE = 323, + QUICK = 324, + COUNT = 325, + AS = 326, + WHERE = 327, + VALUES = 328, + ORDER = 329, + GROUP = 330, + HAVING = 331, + INTO = 332, + UNION = 333, + FOR = 334, + TX_READ_ONLY = 335, + SELECT_OBPROXY_ROUTE_ADDR = 336, + SET_OBPROXY_ROUTE_ADDR = 337, + NAME_OB_DOT = 338, + NAME_OB = 339, + EXPLAIN = 340, + DESC = 341, + DESCRIBE = 342, + NAME_STR = 343, + USE = 344, + HELP = 345, + SET_NAMES = 346, + SET_CHARSET = 347, + SET_PASSWORD = 348, + SET_DEFAULT = 349, + SET_OB_READ_CONSISTENCY = 350, + SET_TX_READ_ONLY = 351, + GLOBAL = 352, + SESSION = 353, + NUMBER_VAL = 354, + GROUP_ID = 355, + TABLE_ID = 356, + ELASTIC_ID = 357, + TESTLOAD = 358, + ODP_COMMENT = 359, + TNT_ID = 360, + DISASTER_STATUS = 361, + TRACE_ID = 362, + RPC_ID = 363, + TARGET_DB_SERVER = 364, + DBP_COMMENT = 365, + ROUTE_TAG = 366, + SYS_TAG = 367, + TABLE_NAME = 368, + SCAN_ALL = 369, + STICKY_SESSION = 370, + PARALL = 371, + SHARD_KEY = 372, + INT_NUM = 373, + SHOW_PROXYNET = 374, + THREAD = 375, + CONNECTION = 376, + LIMIT = 377, + OFFSET = 378, + SHOW_PROCESSLIST = 379, + SHOW_PROXYSESSION = 380, + SHOW_GLOBALSESSION = 381, + ATTRIBUTE = 382, + VARIABLES = 383, + ALL = 384, + STAT = 385, + SHOW_PROXYCONFIG = 386, + DIFF = 387, + USER = 388, + LIKE = 389, + SHOW_PROXYSM = 390, + SHOW_PROXYCLUSTER = 391, + SHOW_PROXYRESOURCE = 392, + SHOW_PROXYCONGESTION = 393, + SHOW_PROXYROUTE = 394, + PARTITION = 395, + ROUTINE = 396, + SHOW_PROXYVIP = 397, + SHOW_PROXYMEMORY = 398, + OBJPOOL = 399, + SHOW_SQLAUDIT = 400, + SHOW_WARNLOG = 401, + SHOW_PROXYSTAT = 402, + REFRESH = 403, + SHOW_PROXYTRACE = 404, + SHOW_PROXYINFO = 405, + BINARY = 406, + UPGRADE = 407, + IDC = 408, + SHOW_ELASTIC_ID = 409, + SHOW_TOPOLOGY = 410, + GROUP_NAME = 411, + SHOW_DB_VERSION = 412, + SHOW_DATABASES = 413, + SHOW_TABLES = 414, + SHOW_FULL_TABLES = 415, + SELECT_DATABASE = 416, + SHOW_CREATE_TABLE = 417, + SELECT_PROXY_VERSION = 418, + SHOW_COLUMNS = 419, + SHOW_INDEX = 420, + ALTER_PROXYCONFIG = 421, + ALTER_PROXYRESOURCE = 422, + PING_PROXY = 423, + KILL_PROXYSESSION = 424, + KILL_GLOBALSESSION = 425, + KILL = 426, + QUERY = 427, + SHOW_MASTER_STATUS = 428, + SHOW_BINARY_LOGS = 429, + SHOW_BINLOG_EVENTS = 430, + PURGE_BINARY_LOGS = 431, + RESET_MASTER = 432, + SHOW_BINLOG_SERVER_FOR_TENANT = 433 }; #endif @@ -806,22 +816,22 @@ union yyalloc #endif /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 305 +#define YYFINAL 314 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 1423 +#define YYLAST 1384 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 177 +#define YYNTOKENS 190 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 128 +#define YYNNTS 138 /* YYNRULES -- Number of rules. */ -#define YYNRULES 427 +#define YYNRULES 435 /* YYNRULES -- Number of states. */ -#define YYNSTATES 681 +#define YYNSTATES 715 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 420 +#define YYMAXUTOK 433 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -832,16 +842,16 @@ static const yytype_uint8 yytranslate[] = 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 175, 2, 2, 2, 2, - 170, 171, 176, 2, 168, 2, 172, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 166, - 2, 169, 2, 2, 167, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 188, 2, 2, 2, 2, + 183, 184, 189, 2, 181, 2, 185, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 179, + 2, 182, 2, 2, 180, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 173, 2, 174, 2, 2, 2, 2, + 2, 2, 2, 186, 2, 187, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -871,7 +881,8 @@ static const yytype_uint8 yytranslate[] = 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165 + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, + 175, 176, 177, 178 }; #if YYDEBUG @@ -880,227 +891,233 @@ static const yytype_uint8 yytranslate[] = static const yytype_uint16 yyprhs[] = { 0, 0, 3, 5, 7, 9, 12, 15, 18, 22, - 24, 27, 31, 33, 35, 37, 39, 41, 43, 45, - 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, - 67, 69, 71, 73, 75, 77, 79, 81, 85, 88, - 91, 94, 97, 100, 103, 106, 109, 112, 115, 118, - 121, 123, 125, 128, 130, 132, 134, 136, 137, 139, - 141, 144, 146, 148, 150, 152, 154, 156, 158, 160, - 163, 168, 172, 175, 178, 183, 185, 187, 189, 191, - 193, 195, 197, 199, 201, 204, 206, 208, 210, 211, - 214, 215, 217, 220, 226, 230, 232, 236, 239, 243, - 245, 247, 249, 251, 253, 255, 257, 259, 261, 263, - 265, 268, 271, 273, 275, 279, 285, 293, 295, 299, - 301, 303, 305, 307, 309, 311, 317, 319, 323, 329, - 330, 332, 336, 338, 340, 342, 345, 349, 351, 353, - 356, 358, 361, 365, 369, 371, 373, 375, 376, 380, - 382, 386, 390, 396, 399, 402, 407, 410, 413, 417, - 419, 424, 431, 436, 442, 449, 454, 458, 460, 462, - 464, 466, 469, 473, 479, 486, 493, 500, 507, 514, - 522, 529, 536, 543, 550, 559, 568, 569, 572, 575, - 578, 580, 584, 586, 591, 596, 600, 607, 612, 617, - 624, 628, 630, 634, 635, 639, 643, 647, 651, 655, - 659, 663, 667, 671, 675, 681, 685, 686, 688, 689, - 691, 693, 695, 697, 700, 702, 705, 707, 710, 713, - 717, 718, 720, 723, 725, 728, 730, 733, 736, 737, - 740, 745, 747, 752, 758, 760, 765, 770, 776, 777, - 779, 781, 783, 784, 786, 790, 794, 797, 799, 801, - 803, 805, 807, 809, 811, 813, 815, 817, 819, 821, - 823, 825, 827, 829, 831, 833, 835, 837, 839, 841, - 843, 844, 847, 852, 857, 858, 861, 862, 865, 868, - 870, 872, 876, 879, 883, 888, 890, 893, 894, 897, - 901, 904, 907, 910, 911, 914, 918, 921, 925, 928, - 932, 936, 941, 943, 946, 949, 953, 956, 959, 960, - 962, 964, 967, 970, 974, 977, 979, 982, 984, 987, - 990, 993, 996, 997, 999, 1003, 1009, 1012, 1016, 1019, - 1020, 1022, 1025, 1028, 1031, 1034, 1039, 1045, 1051, 1055, - 1057, 1060, 1064, 1068, 1071, 1074, 1078, 1082, 1083, 1086, - 1088, 1092, 1096, 1100, 1101, 1103, 1105, 1109, 1112, 1116, - 1119, 1122, 1124, 1125, 1128, 1133, 1136, 1138, 1142, 1145, - 1150, 1154, 1160, 1162, 1164, 1166, 1168, 1170, 1172, 1174, - 1176, 1178, 1180, 1182, 1184, 1186, 1188, 1190, 1192, 1194, - 1196, 1198, 1200, 1202, 1204, 1206, 1208, 1210, 1212, 1214, - 1216, 1218, 1220, 1222, 1224, 1226, 1228, 1230, 1232, 1234, - 1236, 1238, 1240, 1242, 1244, 1246, 1248, 1250 + 24, 27, 31, 33, 36, 38, 40, 42, 44, 46, + 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, + 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, + 90, 93, 96, 99, 102, 105, 108, 110, 112, 115, + 117, 119, 121, 123, 124, 126, 128, 131, 133, 135, + 137, 139, 141, 143, 145, 147, 150, 155, 158, 160, + 162, 166, 169, 173, 176, 179, 183, 187, 189, 191, + 193, 195, 197, 199, 201, 203, 205, 208, 210, 212, + 214, 215, 218, 219, 221, 224, 230, 234, 236, 240, + 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, + 262, 264, 266, 268, 271, 274, 278, 284, 288, 294, + 295, 298, 299, 302, 306, 310, 316, 318, 320, 324, + 330, 338, 340, 344, 346, 350, 352, 354, 356, 358, + 360, 362, 368, 370, 374, 380, 381, 383, 387, 389, + 391, 393, 396, 400, 402, 404, 407, 409, 412, 416, + 420, 422, 424, 426, 427, 431, 433, 437, 441, 447, + 450, 453, 458, 461, 464, 468, 470, 475, 482, 487, + 493, 500, 505, 509, 511, 513, 515, 517, 520, 524, + 530, 537, 544, 551, 558, 565, 573, 580, 587, 594, + 601, 610, 619, 626, 627, 630, 633, 636, 638, 642, + 644, 649, 654, 658, 665, 669, 674, 679, 686, 690, + 692, 696, 697, 701, 705, 709, 713, 717, 721, 725, + 729, 733, 737, 741, 747, 751, 752, 754, 755, 757, + 759, 761, 763, 766, 768, 771, 773, 776, 779, 783, + 784, 786, 789, 791, 794, 796, 799, 802, 803, 806, + 811, 813, 818, 824, 826, 831, 836, 842, 843, 845, + 847, 849, 850, 852, 856, 860, 863, 865, 867, 869, + 871, 873, 875, 877, 879, 881, 883, 885, 887, 889, + 891, 893, 895, 897, 899, 901, 903, 905, 907, 909, + 911, 913, 915, 917, 919, 921, 922, 925, 930, 935, + 936, 939, 940, 943, 946, 948, 950, 954, 957, 961, + 966, 968, 971, 972, 975, 979, 982, 985, 988, 989, + 992, 996, 999, 1003, 1006, 1010, 1014, 1019, 1021, 1024, + 1027, 1031, 1034, 1037, 1038, 1040, 1042, 1045, 1048, 1052, + 1055, 1057, 1060, 1062, 1065, 1068, 1071, 1074, 1075, 1077, + 1081, 1087, 1090, 1094, 1097, 1098, 1100, 1103, 1106, 1109, + 1112, 1117, 1123, 1129, 1133, 1135, 1138, 1142, 1146, 1149, + 1152, 1156, 1160, 1161, 1164, 1166, 1170, 1174, 1178, 1179, + 1181, 1183, 1187, 1190, 1194, 1197, 1200, 1202, 1203, 1206, + 1211, 1214, 1216, 1220, 1223, 1228, 1232, 1238, 1240, 1242, + 1244, 1246, 1248, 1250, 1252, 1254, 1256, 1258, 1260, 1262, + 1264, 1266, 1268, 1270, 1272, 1274, 1276, 1278, 1280, 1282, + 1284, 1286, 1288, 1290, 1292, 1294 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int16 yyrhs[] = { - 178, 0, -1, 179, -1, 1, -1, 180, -1, 179, - 180, -1, 181, 48, -1, 181, 166, -1, 181, 166, - 48, -1, 166, -1, 166, 48, -1, 54, 181, 166, - -1, 182, -1, 223, -1, 228, -1, 224, -1, 225, - -1, 226, -1, 183, -1, 184, -1, 293, -1, 258, - -1, 200, -1, 259, -1, 297, -1, 298, -1, 206, - -1, 207, -1, 208, -1, 209, -1, 210, -1, 211, - -1, 212, -1, 185, -1, 191, -1, 227, -1, 299, - -1, 246, 196, 195, -1, 193, 182, -1, 193, 223, - -1, 193, 225, -1, 193, 226, -1, 193, 224, -1, - 193, 227, -1, 232, 182, -1, 232, 223, -1, 232, - 225, -1, 232, 226, -1, 232, 224, -1, 232, 227, - -1, 186, -1, 192, -1, 14, 187, -1, 15, -1, - 16, -1, 17, -1, 18, -1, -1, 19, -1, 62, - -1, 20, 62, -1, 182, -1, 223, -1, 224, -1, - 226, -1, 225, -1, 299, -1, 212, -1, 227, -1, - 167, 83, -1, 189, 168, 167, 83, -1, 28, 304, - 26, -1, 190, 188, -1, 29, 304, -1, 29, 304, - 30, 189, -1, 21, -1, 22, -1, 23, -1, 24, - -1, 51, -1, 25, -1, 52, -1, 53, -1, 194, - -1, 194, 83, -1, 84, -1, 85, -1, 86, -1, - -1, 26, 219, -1, -1, 216, -1, 5, 78, -1, - 5, 78, 196, 26, 219, -1, 5, 78, 216, -1, - 158, -1, 158, 69, 304, -1, 12, 79, -1, 12, - 79, 216, -1, 197, -1, 198, -1, 199, -1, 204, - -1, 205, -1, 201, -1, 203, -1, 202, -1, 156, - -1, 154, -1, 155, -1, 157, 213, -1, 194, 213, - -1, 153, -1, 151, -1, 151, 26, 83, -1, 151, - 70, 152, 169, 83, -1, 151, 26, 83, 70, 152, - 169, 83, -1, 80, -1, 81, 169, 115, -1, 90, - -1, 91, -1, 92, -1, 93, -1, 94, -1, 95, - -1, 13, 213, 170, 214, 171, -1, 304, -1, 304, - 172, 304, -1, 304, 172, 304, 172, 304, -1, -1, - 215, -1, 214, 168, 215, -1, 83, -1, 115, -1, - 98, -1, 167, 83, -1, 167, 167, 83, -1, 47, - -1, 217, -1, 216, 217, -1, 218, -1, 170, 171, - -1, 170, 182, 171, -1, 170, 216, 171, -1, 301, - -1, 220, -1, 182, -1, -1, 170, 222, 171, -1, - 83, -1, 222, 168, 83, -1, 249, 302, 300, -1, - 249, 302, 300, 221, 220, -1, 251, 219, -1, 247, - 219, -1, 248, 257, 26, 219, -1, 252, 302, -1, - 12, 229, -1, 230, 168, 229, -1, 230, -1, 167, - 83, 169, 231, -1, 167, 167, 96, 83, 169, 231, - -1, 96, 83, 169, 231, -1, 167, 167, 83, 169, - 231, -1, 167, 167, 97, 83, 169, 231, -1, 97, - 83, 169, 231, -1, 83, 169, 231, -1, 83, -1, - 115, -1, 98, -1, 233, -1, 233, 232, -1, 38, - 234, 39, -1, 38, 103, 242, 241, 39, -1, 38, - 100, 169, 245, 241, 39, -1, 38, 111, 169, 245, - 241, 39, -1, 38, 99, 169, 245, 241, 39, -1, - 38, 101, 169, 245, 241, 39, -1, 38, 102, 169, - 245, 241, 39, -1, 38, 82, 83, 169, 244, 241, - 39, -1, 38, 106, 169, 243, 241, 39, -1, 38, - 107, 169, 243, 241, 39, -1, 38, 104, 169, 245, - 241, 39, -1, 38, 105, 169, 245, 241, 39, -1, - 38, 108, 109, 169, 173, 236, 174, 39, -1, 38, - 108, 110, 169, 173, 238, 174, 39, -1, -1, 234, - 235, -1, 40, 83, -1, 41, 83, -1, 83, -1, - 237, 168, 236, -1, 237, -1, 99, 170, 245, 171, - -1, 111, 170, 245, 171, -1, 112, 170, 171, -1, - 112, 170, 113, 169, 245, 171, -1, 114, 170, 239, - 171, -1, 66, 170, 243, 171, -1, 66, 170, 243, - 175, 243, 171, -1, 240, 168, 239, -1, 240, -1, - 83, 169, 245, -1, -1, 241, 168, 242, -1, 99, - 169, 245, -1, 100, 169, 245, -1, 111, 169, 245, - -1, 101, 169, 245, -1, 102, 169, 245, -1, 106, - 169, 243, -1, 107, 169, 243, -1, 104, 169, 245, - -1, 105, 169, 245, -1, 83, 172, 83, 169, 244, - -1, 83, 169, 244, -1, -1, 245, -1, -1, 245, - -1, 83, -1, 87, -1, 5, -1, 31, 253, -1, - 8, -1, 32, 253, -1, 6, -1, 33, 253, -1, - 7, 250, -1, 34, 253, 250, -1, -1, 126, -1, - 126, 50, -1, 9, -1, 35, 253, -1, 10, -1, - 36, 253, -1, 254, 37, -1, -1, 255, 254, -1, - 42, 170, 115, 171, -1, 115, -1, 43, 170, 256, - 171, -1, 62, 170, 83, 83, 171, -1, 83, -1, - 83, 170, 115, 171, -1, 83, 170, 83, 171, -1, - 83, 170, 83, 83, 171, -1, -1, 44, -1, 45, - -1, 46, -1, -1, 67, -1, 11, 292, 64, -1, - 11, 292, 65, -1, 11, 66, -1, 263, -1, 265, - -1, 266, -1, 269, -1, 267, -1, 271, -1, 272, - -1, 273, -1, 274, -1, 276, -1, 277, -1, 278, - -1, 279, -1, 280, -1, 282, -1, 283, -1, 285, - -1, 286, -1, 287, -1, 288, -1, 289, -1, 290, - -1, 291, -1, -1, 119, 115, -1, 119, 115, 168, - 115, -1, 119, 115, 120, 115, -1, -1, 131, 83, - -1, -1, 131, 83, -1, 116, 264, -1, 117, -1, - 118, -1, 118, 115, 260, -1, 128, 261, -1, 128, - 129, 261, -1, 128, 129, 130, 261, -1, 121, -1, - 123, 268, -1, -1, 124, 83, -1, 124, 131, 83, - -1, 124, 126, -1, 131, 83, -1, 122, 270, -1, - -1, 124, 261, -1, 124, 115, 261, -1, 127, 261, - -1, 127, 115, 261, -1, 125, 261, -1, 125, 115, - 261, -1, 125, 126, 261, -1, 125, 126, 115, 261, - -1, 132, -1, 132, 115, -1, 133, 261, -1, 133, - 150, 261, -1, 134, 261, -1, 135, 275, -1, -1, - 83, -1, 126, -1, 126, 83, -1, 136, 262, -1, - 136, 138, 262, -1, 136, 137, -1, 139, -1, 139, - 83, -1, 140, -1, 140, 141, -1, 142, 260, -1, - 142, 115, -1, 143, 281, -1, -1, 115, -1, 115, - 168, 115, -1, 115, 168, 115, 168, 83, -1, 144, - 261, -1, 144, 145, 261, -1, 146, 284, -1, -1, - 115, -1, 115, 115, -1, 147, 148, -1, 147, 149, - -1, 147, 150, -1, 159, 12, 83, 169, -1, 159, - 12, 83, 169, 83, -1, 159, 12, 83, 169, 115, - -1, 160, 6, 83, -1, 161, -1, 162, 115, -1, - 162, 115, 115, -1, 163, 83, 115, -1, 163, 83, - -1, 164, 115, -1, 164, 118, 115, -1, 164, 165, - 115, -1, -1, 68, 176, -1, 54, -1, 55, 56, - 294, -1, 63, 54, 83, -1, 63, 55, 83, -1, - -1, 295, -1, 296, -1, 295, 168, 296, -1, 57, - 58, -1, 59, 60, 61, -1, 88, 83, -1, 89, - 83, -1, 83, -1, -1, 137, 83, -1, 137, 170, - 83, 171, -1, 302, 300, -1, 304, -1, 304, 172, - 304, -1, 304, 304, -1, 304, 172, 304, 304, -1, - 304, 69, 304, -1, 304, 172, 304, 69, 304, -1, - 55, -1, 63, -1, 54, -1, 56, -1, 60, -1, - 65, -1, 64, -1, 68, -1, 67, -1, 66, -1, - 117, -1, 118, -1, 120, -1, 124, -1, 125, -1, - 127, -1, 129, -1, 130, -1, 141, -1, 145, -1, - 149, -1, 150, -1, 165, -1, 99, -1, 100, -1, - 101, -1, 102, -1, 152, -1, 103, -1, 104, -1, - 105, -1, 106, -1, 107, -1, 108, -1, 109, -1, - 110, -1, 111, -1, 113, -1, 112, -1, 114, -1, - 62, -1, 51, -1, 52, -1, 53, -1, 83, -1, - 303, -1 + 191, 0, -1, 192, -1, 1, -1, 193, -1, 192, + 193, -1, 194, 50, -1, 194, 179, -1, 194, 179, + 50, -1, 179, -1, 179, 50, -1, 56, 194, 179, + -1, 195, -1, 254, 195, -1, 196, -1, 245, -1, + 250, -1, 246, -1, 247, -1, 248, -1, 197, -1, + 316, -1, 280, -1, 215, -1, 281, -1, 320, -1, + 321, -1, 228, -1, 229, -1, 230, -1, 231, -1, + 232, -1, 233, -1, 234, -1, 198, -1, 207, -1, + 249, -1, 282, -1, 322, -1, 268, 212, 211, -1, + 209, 196, -1, 209, 245, -1, 209, 247, -1, 209, + 248, -1, 209, 246, -1, 209, 249, -1, 199, -1, + 208, -1, 14, 200, -1, 15, -1, 16, -1, 17, + -1, 18, -1, -1, 19, -1, 64, -1, 21, 64, + -1, 196, -1, 245, -1, 246, -1, 248, -1, 247, + -1, 322, -1, 234, -1, 249, -1, 180, 84, -1, + 202, 181, 180, 84, -1, 180, 84, -1, 203, -1, + 201, -1, 29, 327, 27, -1, 30, 327, -1, 30, + 327, 31, -1, 205, 204, -1, 206, 202, -1, 15, + 29, 327, -1, 32, 29, 327, -1, 22, -1, 23, + -1, 24, -1, 25, -1, 53, -1, 26, -1, 54, + -1, 55, -1, 210, -1, 210, 84, -1, 85, -1, + 86, -1, 87, -1, -1, 27, 241, -1, -1, 238, + -1, 5, 80, -1, 5, 80, 212, 27, 241, -1, + 5, 80, 238, -1, 163, -1, 163, 71, 327, -1, + 213, -1, 214, -1, 226, -1, 227, -1, 216, -1, + 224, -1, 225, -1, 223, -1, 161, -1, 158, -1, + 221, -1, 222, -1, 217, -1, 218, -1, 162, 235, + -1, 210, 327, -1, 164, 27, 84, -1, 164, 27, + 84, 27, 84, -1, 165, 27, 84, -1, 165, 27, + 84, 27, 84, -1, -1, 134, 84, -1, -1, 27, + 84, -1, 159, 220, 219, -1, 160, 220, 219, -1, + 11, 19, 20, 220, 219, -1, 157, -1, 154, -1, + 154, 27, 84, -1, 154, 72, 156, 182, 84, -1, + 154, 27, 84, 72, 156, 182, 84, -1, 155, -1, + 155, 27, 84, -1, 81, -1, 82, 182, 118, -1, + 91, -1, 92, -1, 93, -1, 94, -1, 95, -1, + 96, -1, 13, 235, 183, 236, 184, -1, 327, -1, + 327, 185, 327, -1, 327, 185, 327, 185, 327, -1, + -1, 237, -1, 236, 181, 237, -1, 84, -1, 118, + -1, 99, -1, 180, 84, -1, 180, 180, 84, -1, + 49, -1, 239, -1, 238, 239, -1, 240, -1, 183, + 184, -1, 183, 196, 184, -1, 183, 238, 184, -1, + 324, -1, 242, -1, 196, -1, -1, 183, 244, 184, + -1, 84, -1, 244, 181, 84, -1, 271, 325, 323, + -1, 271, 325, 323, 243, 242, -1, 273, 241, -1, + 269, 241, -1, 270, 279, 27, 241, -1, 274, 325, + -1, 12, 251, -1, 252, 181, 251, -1, 252, -1, + 180, 84, 182, 253, -1, 180, 180, 97, 84, 182, + 253, -1, 97, 84, 182, 253, -1, 180, 180, 84, + 182, 253, -1, 180, 180, 98, 84, 182, 253, -1, + 98, 84, 182, 253, -1, 84, 182, 253, -1, 84, + -1, 118, -1, 99, -1, 255, -1, 255, 254, -1, + 40, 256, 41, -1, 40, 104, 264, 263, 41, -1, + 40, 101, 182, 267, 263, 41, -1, 40, 113, 182, + 267, 263, 41, -1, 40, 100, 182, 267, 263, 41, + -1, 40, 102, 182, 267, 263, 41, -1, 40, 103, + 182, 267, 263, 41, -1, 40, 83, 84, 182, 266, + 263, 41, -1, 40, 107, 182, 265, 263, 41, -1, + 40, 108, 182, 265, 263, 41, -1, 40, 105, 182, + 267, 263, 41, -1, 40, 106, 182, 267, 263, 41, + -1, 40, 110, 111, 182, 186, 258, 187, 41, -1, + 40, 110, 112, 182, 186, 260, 187, 41, -1, 40, + 109, 182, 267, 263, 41, -1, -1, 256, 257, -1, + 42, 84, -1, 43, 84, -1, 84, -1, 259, 181, + 258, -1, 259, -1, 100, 183, 267, 184, -1, 113, + 183, 267, 184, -1, 114, 183, 184, -1, 114, 183, + 116, 182, 267, 184, -1, 115, 183, 184, -1, 117, + 183, 261, 184, -1, 68, 183, 265, 184, -1, 68, + 183, 265, 188, 265, 184, -1, 262, 181, 261, -1, + 262, -1, 84, 182, 267, -1, -1, 263, 181, 264, + -1, 100, 182, 267, -1, 101, 182, 267, -1, 113, + 182, 267, -1, 102, 182, 267, -1, 103, 182, 267, + -1, 107, 182, 265, -1, 108, 182, 265, -1, 105, + 182, 267, -1, 106, 182, 267, -1, 109, 182, 267, + -1, 84, 185, 84, 182, 266, -1, 84, 182, 266, + -1, -1, 267, -1, -1, 267, -1, 84, -1, 88, + -1, 5, -1, 33, 275, -1, 8, -1, 34, 275, + -1, 6, -1, 35, 275, -1, 7, 272, -1, 36, + 275, 272, -1, -1, 129, -1, 129, 52, -1, 9, + -1, 37, 275, -1, 10, -1, 38, 275, -1, 276, + 39, -1, -1, 277, 276, -1, 44, 183, 118, 184, + -1, 118, -1, 45, 183, 278, 184, -1, 64, 183, + 84, 84, 184, -1, 84, -1, 84, 183, 118, 184, + -1, 84, 183, 84, 184, -1, 84, 183, 84, 84, + 184, -1, -1, 46, -1, 47, -1, 48, -1, -1, + 69, -1, 11, 315, 66, -1, 11, 315, 67, -1, + 11, 68, -1, 286, -1, 288, -1, 289, -1, 292, + -1, 290, -1, 294, -1, 295, -1, 296, -1, 297, + -1, 299, -1, 300, -1, 301, -1, 302, -1, 303, + -1, 305, -1, 306, -1, 308, -1, 309, -1, 310, + -1, 311, -1, 312, -1, 313, -1, 314, -1, 173, + -1, 174, -1, 175, -1, 176, -1, 177, -1, 178, + -1, -1, 122, 118, -1, 122, 118, 181, 118, -1, + 122, 118, 123, 118, -1, -1, 134, 84, -1, -1, + 134, 84, -1, 119, 287, -1, 120, -1, 121, -1, + 121, 118, 283, -1, 131, 284, -1, 131, 132, 284, + -1, 131, 132, 133, 284, -1, 124, -1, 126, 291, + -1, -1, 127, 84, -1, 127, 134, 84, -1, 127, + 129, -1, 134, 84, -1, 125, 293, -1, -1, 127, + 284, -1, 127, 118, 284, -1, 130, 284, -1, 130, + 118, 284, -1, 128, 284, -1, 128, 118, 284, -1, + 128, 129, 284, -1, 128, 129, 118, 284, -1, 135, + -1, 135, 118, -1, 136, 284, -1, 136, 153, 284, + -1, 137, 284, -1, 138, 298, -1, -1, 84, -1, + 129, -1, 129, 84, -1, 139, 285, -1, 139, 141, + 285, -1, 139, 140, -1, 142, -1, 142, 84, -1, + 143, -1, 143, 144, -1, 145, 283, -1, 145, 118, + -1, 146, 304, -1, -1, 118, -1, 118, 181, 118, + -1, 118, 181, 118, 181, 84, -1, 147, 284, -1, + 147, 148, 284, -1, 149, 307, -1, -1, 118, -1, + 118, 118, -1, 150, 151, -1, 150, 152, -1, 150, + 153, -1, 166, 12, 84, 182, -1, 166, 12, 84, + 182, 84, -1, 166, 12, 84, 182, 118, -1, 167, + 6, 84, -1, 168, -1, 169, 118, -1, 169, 118, + 118, -1, 170, 84, 118, -1, 170, 84, -1, 171, + 118, -1, 171, 121, 118, -1, 171, 172, 118, -1, + -1, 70, 189, -1, 56, -1, 57, 58, 317, -1, + 65, 56, 84, -1, 65, 57, 84, -1, -1, 318, + -1, 319, -1, 318, 181, 319, -1, 59, 60, -1, + 61, 62, 63, -1, 89, 84, -1, 90, 84, -1, + 84, -1, -1, 140, 84, -1, 140, 183, 84, 184, + -1, 325, 323, -1, 327, -1, 327, 185, 327, -1, + 327, 327, -1, 327, 185, 327, 327, -1, 327, 71, + 327, -1, 327, 185, 327, 71, 327, -1, 57, -1, + 65, -1, 56, -1, 58, -1, 62, -1, 67, -1, + 66, -1, 70, -1, 69, -1, 68, -1, 120, -1, + 121, -1, 123, -1, 127, -1, 128, -1, 130, -1, + 132, -1, 133, -1, 144, -1, 148, -1, 152, -1, + 153, -1, 172, -1, 156, -1, 53, -1, 54, -1, + 55, -1, 84, -1, 326, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 336, 336, 337, 339, 340, 342, 343, 344, 345, - 346, 347, 349, 350, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, - 367, 368, 369, 370, 371, 372, 373, 375, 377, 378, - 379, 380, 381, 382, 384, 385, 386, 387, 388, 389, - 391, 392, 394, 395, 396, 397, 398, 400, 401, 402, - 403, 405, 406, 407, 408, 409, 410, 411, 412, 414, - 421, 429, 435, 438, 443, 449, 450, 451, 452, 453, - 454, 455, 456, 458, 459, 461, 462, 463, 465, 466, - 468, 469, 471, 472, 473, 475, 476, 478, 479, 481, - 482, 483, 484, 485, 486, 488, 489, 490, 491, 492, - 493, 494, 500, 502, 503, 508, 513, 520, 523, 529, - 530, 531, 532, 533, 534, 537, 539, 543, 548, 556, - 559, 564, 569, 574, 579, 584, 589, 594, 602, 603, - 605, 607, 608, 609, 611, 612, 614, 616, 617, 619, - 620, 622, 626, 627, 628, 629, 630, 635, 637, 638, - 640, 644, 648, 652, 656, 660, 664, 668, 673, 678, - 684, 685, 687, 688, 689, 690, 691, 692, 693, 694, - 700, 701, 702, 703, 704, 705, 707, 708, 710, 711, - 712, 714, 715, 717, 722, 727, 728, 729, 731, 732, - 734, 735, 737, 745, 746, 748, 749, 750, 751, 752, - 753, 754, 755, 756, 757, 763, 765, 766, 768, 769, - 771, 772, 774, 775, 776, 777, 778, 779, 780, 781, - 783, 784, 785, 787, 788, 789, 790, 791, 792, 793, - 795, 796, 797, 798, 803, 804, 805, 806, 808, 809, - 810, 811, 813, 814, 817, 818, 819, 822, 823, 824, - 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, - 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, - 849, 851, 855, 860, 868, 869, 873, 874, 877, 879, - 880, 881, 885, 886, 887, 891, 893, 895, 896, 897, - 898, 899, 902, 904, 905, 906, 907, 908, 909, 910, - 911, 912, 916, 917, 921, 922, 927, 930, 932, 933, - 934, 935, 939, 940, 941, 945, 946, 950, 951, 955, - 956, 959, 961, 962, 963, 964, 968, 969, 972, 974, - 975, 976, 980, 981, 982, 986, 987, 988, 992, 996, - 1000, 1001, 1005, 1006, 1010, 1011, 1012, 1015, 1016, 1019, - 1023, 1024, 1025, 1027, 1028, 1030, 1031, 1034, 1035, 1038, - 1044, 1047, 1049, 1050, 1051, 1053, 1058, 1061, 1065, 1069, - 1074, 1078, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, - 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, - 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, - 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, - 1122, 1123, 1124, 1125, 1126, 1127, 1129, 1130 + 0, 334, 334, 335, 337, 338, 340, 341, 342, 343, + 344, 345, 347, 348, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, 369, 370, 371, 372, 373, 374, 376, + 378, 379, 380, 381, 382, 383, 385, 386, 388, 389, + 390, 391, 392, 394, 395, 396, 397, 399, 400, 401, + 402, 403, 404, 405, 406, 408, 415, 423, 431, 432, + 435, 441, 446, 452, 455, 458, 463, 469, 470, 471, + 472, 473, 474, 475, 476, 478, 479, 481, 482, 483, + 485, 486, 488, 489, 491, 492, 493, 495, 496, 498, + 499, 500, 501, 502, 504, 505, 506, 507, 508, 509, + 510, 511, 512, 513, 514, 521, 526, 533, 538, 545, + 546, 548, 549, 551, 555, 560, 565, 567, 568, 573, + 578, 585, 586, 592, 595, 601, 602, 603, 604, 605, + 606, 609, 611, 615, 620, 628, 631, 636, 641, 646, + 651, 656, 661, 666, 674, 675, 677, 679, 680, 681, + 683, 684, 686, 688, 689, 691, 692, 694, 698, 699, + 700, 701, 702, 707, 709, 710, 712, 716, 720, 724, + 728, 732, 736, 740, 745, 750, 756, 757, 759, 760, + 761, 762, 763, 764, 765, 766, 772, 773, 774, 775, + 776, 777, 778, 779, 780, 782, 783, 784, 786, 787, + 789, 794, 799, 800, 801, 802, 804, 805, 807, 808, + 810, 818, 819, 821, 822, 823, 824, 825, 826, 827, + 828, 829, 830, 831, 837, 839, 840, 842, 843, 845, + 846, 848, 849, 850, 851, 852, 853, 854, 855, 857, + 858, 859, 861, 862, 863, 864, 865, 866, 867, 869, + 870, 871, 872, 877, 878, 879, 880, 882, 883, 884, + 885, 887, 888, 891, 892, 893, 896, 897, 898, 899, + 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, + 910, 911, 912, 913, 914, 915, 916, 917, 918, 920, + 921, 922, 923, 924, 925, 930, 932, 936, 941, 949, + 950, 954, 955, 958, 960, 961, 962, 966, 967, 968, + 972, 974, 976, 977, 978, 979, 980, 983, 985, 986, + 987, 988, 989, 990, 991, 992, 993, 997, 998, 1002, + 1003, 1008, 1011, 1013, 1014, 1015, 1016, 1020, 1021, 1022, + 1026, 1027, 1031, 1032, 1036, 1037, 1040, 1042, 1043, 1044, + 1045, 1049, 1050, 1053, 1055, 1056, 1057, 1061, 1062, 1063, + 1067, 1068, 1069, 1073, 1077, 1081, 1082, 1086, 1087, 1091, + 1092, 1093, 1096, 1097, 1100, 1104, 1105, 1106, 1108, 1109, + 1111, 1112, 1115, 1116, 1119, 1125, 1128, 1130, 1131, 1132, + 1134, 1139, 1142, 1146, 1150, 1155, 1159, 1165, 1166, 1167, + 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, + 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, + 1188, 1189, 1190, 1191, 1193, 1194 }; #endif @@ -1112,45 +1129,52 @@ static const char *const yytname[] = "$end", "error", "$undefined", "DUMMY_WHERE_CLAUSE", "DUMMY_INSERT_CLAUSE", "SELECT", "DELETE", "INSERT", "UPDATE", "REPLACE", "MERGE", "SHOW", "SET", "CALL", "CREATE", "DROP", "ALTER", "TRUNCATE", - "RENAME", "TABLE", "UNIQUE", "GRANT", "REVOKE", "ANALYZE", "PURGE", - "COMMENT", "FROM", "DUAL", "PREPARE", "EXECUTE", "USING", - "SELECT_HINT_BEGIN", "UPDATE_HINT_BEGIN", "DELETE_HINT_BEGIN", - "INSERT_HINT_BEGIN", "REPLACE_HINT_BEGIN", "MERGE_HINT_BEGIN", - "HINT_END", "COMMENT_BEGIN", "COMMENT_END", "ROUTE_TABLE", - "ROUTE_PART_KEY", "QUERY_TIMEOUT", "READ_CONSISTENCY", "WEAK", "STRONG", - "FROZEN", "PLACE_HOLDER", "END_P", "ERROR", "WHEN", "FLASHBACK", "AUDIT", - "NOAUDIT", "BEGI", "START", "TRANSACTION", "READ", "ONLY", "WITH", - "CONSISTENT", "SNAPSHOT", "INDEX", "XA", "WARNINGS", "ERRORS", "TRACE", - "QUICK", "COUNT", "AS", "WHERE", "VALUES", "ORDER", "GROUP", "HAVING", - "INTO", "UNION", "FOR", "TX_READ_ONLY", "AUTOCOMMIT_0", + "RENAME", "TABLE", "STATUS", "UNIQUE", "GRANT", "REVOKE", "ANALYZE", + "PURGE", "COMMENT", "FROM", "DUAL", "PREPARE", "EXECUTE", "USING", + "DEALLOCATE", "SELECT_HINT_BEGIN", "UPDATE_HINT_BEGIN", + "DELETE_HINT_BEGIN", "INSERT_HINT_BEGIN", "REPLACE_HINT_BEGIN", + "MERGE_HINT_BEGIN", "HINT_END", "COMMENT_BEGIN", "COMMENT_END", + "ROUTE_TABLE", "ROUTE_PART_KEY", "QUERY_TIMEOUT", "READ_CONSISTENCY", + "WEAK", "STRONG", "FROZEN", "PLACE_HOLDER", "END_P", "ERROR", "WHEN", + "FLASHBACK", "AUDIT", "NOAUDIT", "BEGI", "START", "TRANSACTION", "READ", + "ONLY", "WITH", "CONSISTENT", "SNAPSHOT", "INDEX", "XA", "WARNINGS", + "ERRORS", "TRACE", "QUICK", "COUNT", "AS", "WHERE", "VALUES", "ORDER", + "GROUP", "HAVING", "INTO", "UNION", "FOR", "TX_READ_ONLY", "SELECT_OBPROXY_ROUTE_ADDR", "SET_OBPROXY_ROUTE_ADDR", "NAME_OB_DOT", "NAME_OB", "EXPLAIN", "DESC", "DESCRIBE", "NAME_STR", "USE", "HELP", "SET_NAMES", "SET_CHARSET", "SET_PASSWORD", "SET_DEFAULT", "SET_OB_READ_CONSISTENCY", "SET_TX_READ_ONLY", "GLOBAL", "SESSION", "NUMBER_VAL", "GROUP_ID", "TABLE_ID", "ELASTIC_ID", "TESTLOAD", "ODP_COMMENT", "TNT_ID", "DISASTER_STATUS", "TRACE_ID", "RPC_ID", - "DBP_COMMENT", "ROUTE_TAG", "SYS_TAG", "TABLE_NAME", "SCAN_ALL", - "PARALL", "SHARD_KEY", "INT_NUM", "SHOW_PROXYNET", "THREAD", - "CONNECTION", "LIMIT", "OFFSET", "SHOW_PROCESSLIST", "SHOW_PROXYSESSION", - "SHOW_GLOBALSESSION", "ATTRIBUTE", "VARIABLES", "ALL", "STAT", - "SHOW_PROXYCONFIG", "DIFF", "USER", "LIKE", "SHOW_PROXYSM", - "SHOW_PROXYCLUSTER", "SHOW_PROXYRESOURCE", "SHOW_PROXYCONGESTION", - "SHOW_PROXYROUTE", "PARTITION", "ROUTINE", "SHOW_PROXYVIP", - "SHOW_PROXYMEMORY", "OBJPOOL", "SHOW_SQLAUDIT", "SHOW_WARNLOG", - "SHOW_PROXYSTAT", "REFRESH", "SHOW_PROXYTRACE", "SHOW_PROXYINFO", - "BINARY", "UPGRADE", "IDC", "SHOW_TOPOLOGY", "GROUP_NAME", - "SHOW_DB_VERSION", "SHOW_DATABASES", "SHOW_TABLES", "SELECT_DATABASE", - "SHOW_CREATE_TABLE", "SELECT_PROXY_VERSION", "ALTER_PROXYCONFIG", - "ALTER_PROXYRESOURCE", "PING_PROXY", "KILL_PROXYSESSION", - "KILL_GLOBALSESSION", "KILL", "QUERY", "';'", "'@'", "','", "'='", "'('", - "')'", "'.'", "'{'", "'}'", "'#'", "'*'", "$accept", "root", "sql_stmts", - "sql_stmt", "stmt", "select_stmt", "explain_stmt", "comment_stmt", - "ddl_stmt", "mysql_ddl_stmt", "create_dll_expr", "text_ps_from_stmt", - "text_ps_using_var_list", "text_ps_prepare_stmt", "text_ps_stmt", + "TARGET_DB_SERVER", "DBP_COMMENT", "ROUTE_TAG", "SYS_TAG", "TABLE_NAME", + "SCAN_ALL", "STICKY_SESSION", "PARALL", "SHARD_KEY", "INT_NUM", + "SHOW_PROXYNET", "THREAD", "CONNECTION", "LIMIT", "OFFSET", + "SHOW_PROCESSLIST", "SHOW_PROXYSESSION", "SHOW_GLOBALSESSION", + "ATTRIBUTE", "VARIABLES", "ALL", "STAT", "SHOW_PROXYCONFIG", "DIFF", + "USER", "LIKE", "SHOW_PROXYSM", "SHOW_PROXYCLUSTER", + "SHOW_PROXYRESOURCE", "SHOW_PROXYCONGESTION", "SHOW_PROXYROUTE", + "PARTITION", "ROUTINE", "SHOW_PROXYVIP", "SHOW_PROXYMEMORY", "OBJPOOL", + "SHOW_SQLAUDIT", "SHOW_WARNLOG", "SHOW_PROXYSTAT", "REFRESH", + "SHOW_PROXYTRACE", "SHOW_PROXYINFO", "BINARY", "UPGRADE", "IDC", + "SHOW_ELASTIC_ID", "SHOW_TOPOLOGY", "GROUP_NAME", "SHOW_DB_VERSION", + "SHOW_DATABASES", "SHOW_TABLES", "SHOW_FULL_TABLES", "SELECT_DATABASE", + "SHOW_CREATE_TABLE", "SELECT_PROXY_VERSION", "SHOW_COLUMNS", + "SHOW_INDEX", "ALTER_PROXYCONFIG", "ALTER_PROXYRESOURCE", "PING_PROXY", + "KILL_PROXYSESSION", "KILL_GLOBALSESSION", "KILL", "QUERY", + "SHOW_MASTER_STATUS", "SHOW_BINARY_LOGS", "SHOW_BINLOG_EVENTS", + "PURGE_BINARY_LOGS", "RESET_MASTER", "SHOW_BINLOG_SERVER_FOR_TENANT", + "';'", "'@'", "','", "'='", "'('", "')'", "'.'", "'{'", "'}'", "'#'", + "'*'", "$accept", "root", "sql_stmts", "sql_stmt", "comment_stmt", + "stmt", "select_stmt", "explain_stmt", "ddl_stmt", "mysql_ddl_stmt", + "create_dll_expr", "text_ps_from_stmt", "text_ps_execute_using_var_list", + "text_ps_prepare_var_list", "text_ps_prepare_args_stmt", + "text_ps_prepare_stmt", "text_ps_execute_stmt", "text_ps_stmt", "oracle_ddl_stmt", "explain_or_desc_stmt", "explain_or_desc", "opt_from", "select_expr_list", "select_tx_read_only_stmt", - "select_proxy_version_stmt", "set_autocommit_0_stmt", "hooked_stmt", - "shard_special_stmt", "show_db_version_stmt", "show_es_id_stmt", + "select_proxy_version_stmt", "hooked_stmt", "shard_special_stmt", + "show_columns_stmt", "show_index_stmt", "opt_show_like", "opt_show_from", + "show_tables_stmt", "show_table_status_stmt", "show_db_version_stmt", + "show_es_id_stmt", "show_topology_stmt", "select_obproxy_route_addr_stmt", "set_obproxy_route_addr_stmt", "set_names_stmt", "set_charset_stmt", "set_password_stmt", "set_default_stmt", "set_ob_read_consistency_stmt", @@ -1167,8 +1191,8 @@ static const char *const yytname[] = "insert_with_opt_hint", "insert_all_when", "replace_with_opt_hint", "merge_with_opt_hint", "hint_list_with_end", "hint_list", "hint", "opt_read_consistency", "opt_quick", "show_stmt", "icmd_stmt", - "opt_limit", "opt_like", "opt_large_like", "show_proxynet", - "opt_show_net", "show_proxyconfig", "show_processlist", + "binlog_stmt", "opt_limit", "opt_like", "opt_large_like", + "show_proxynet", "opt_show_net", "show_proxyconfig", "show_processlist", "show_globalsession", "opt_show_global_session", "show_proxysession", "opt_show_session", "show_proxysm", "show_proxycluster", "show_proxyresource", "show_proxycongestion", "opt_show_congestion", @@ -1205,105 +1229,108 @@ static const yytype_uint16 yytoknum[] = 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, - 415, 416, 417, 418, 419, 420, 59, 64, 44, 61, - 40, 41, 46, 123, 125, 35, 42 + 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, + 425, 426, 427, 428, 429, 430, 431, 432, 433, 59, + 64, 44, 61, 40, 41, 46, 123, 125, 35, 42 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint16 yyr1[] = { - 0, 177, 178, 178, 179, 179, 180, 180, 180, 180, - 180, 180, 181, 181, 181, 181, 181, 181, 181, 181, - 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, - 181, 181, 181, 181, 181, 181, 181, 182, 183, 183, - 183, 183, 183, 183, 184, 184, 184, 184, 184, 184, - 185, 185, 186, 186, 186, 186, 186, 187, 187, 187, - 187, 188, 188, 188, 188, 188, 188, 188, 188, 189, - 189, 190, 191, 191, 191, 192, 192, 192, 192, 192, - 192, 192, 192, 193, 193, 194, 194, 194, 195, 195, - 196, 196, 197, 197, 197, 198, 198, 199, 199, 200, - 200, 200, 200, 200, 200, 201, 201, 201, 201, 201, - 201, 201, 202, 203, 203, 203, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 213, 213, 214, - 214, 214, 215, 215, 215, 215, 215, 215, 216, 216, - 217, 218, 218, 218, 219, 219, 220, 221, 221, 222, - 222, 223, 223, 224, 225, 226, 227, 228, 229, 229, - 230, 230, 230, 230, 230, 230, 230, 231, 231, 231, - 232, 232, 233, 233, 233, 233, 233, 233, 233, 233, - 233, 233, 233, 233, 233, 233, 234, 234, 235, 235, - 235, 236, 236, 237, 237, 237, 237, 237, 238, 238, - 239, 239, 240, 241, 241, 242, 242, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 243, 243, 244, 244, - 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, - 250, 250, 250, 251, 251, 252, 252, 253, 254, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 256, 256, - 256, 256, 257, 257, 258, 258, 258, 259, 259, 259, - 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, - 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, - 260, 260, 260, 260, 261, 261, 262, 262, 263, 264, - 264, 264, 265, 265, 265, 266, 267, 268, 268, 268, - 268, 268, 269, 270, 270, 270, 270, 270, 270, 270, - 270, 270, 271, 271, 272, 272, 273, 274, 275, 275, - 275, 275, 276, 276, 276, 277, 277, 278, 278, 279, - 279, 280, 281, 281, 281, 281, 282, 282, 283, 284, - 284, 284, 285, 285, 285, 286, 286, 286, 287, 288, - 289, 289, 290, 290, 291, 291, 291, 292, 292, 293, - 293, 293, 293, 294, 294, 295, 295, 296, 296, 297, - 298, 299, 300, 300, 300, 301, 302, 302, 302, 302, - 302, 302, 303, 303, 303, 303, 303, 303, 303, 303, - 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, - 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, - 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, - 303, 303, 303, 303, 303, 303, 304, 304 + 0, 190, 191, 191, 192, 192, 193, 193, 193, 193, + 193, 193, 194, 194, 195, 195, 195, 195, 195, 195, + 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, + 195, 195, 195, 195, 195, 195, 195, 195, 195, 196, + 197, 197, 197, 197, 197, 197, 198, 198, 199, 199, + 199, 199, 199, 200, 200, 200, 200, 201, 201, 201, + 201, 201, 201, 201, 201, 202, 202, 203, 204, 204, + 205, 206, 206, 207, 207, 207, 207, 208, 208, 208, + 208, 208, 208, 208, 208, 209, 209, 210, 210, 210, + 211, 211, 212, 212, 213, 213, 213, 214, 214, 215, + 215, 215, 215, 215, 216, 216, 216, 216, 216, 216, + 216, 216, 216, 216, 216, 217, 217, 218, 218, 219, + 219, 220, 220, 221, 221, 222, 223, 224, 224, 224, + 224, 225, 225, 226, 227, 228, 229, 230, 231, 232, + 233, 234, 235, 235, 235, 236, 236, 236, 237, 237, + 237, 237, 237, 237, 238, 238, 239, 240, 240, 240, + 241, 241, 242, 243, 243, 244, 244, 245, 245, 246, + 247, 248, 249, 250, 251, 251, 252, 252, 252, 252, + 252, 252, 252, 253, 253, 253, 254, 254, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 256, 256, 257, 257, 257, 258, 258, + 259, 259, 259, 259, 259, 259, 260, 260, 261, 261, + 262, 263, 263, 264, 264, 264, 264, 264, 264, 264, + 264, 264, 264, 264, 264, 265, 265, 266, 266, 267, + 267, 268, 268, 269, 269, 270, 270, 271, 271, 272, + 272, 272, 273, 273, 274, 274, 275, 276, 276, 277, + 277, 277, 277, 277, 277, 277, 277, 278, 278, 278, + 278, 279, 279, 280, 280, 280, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 282, + 282, 282, 282, 282, 282, 283, 283, 283, 283, 284, + 284, 285, 285, 286, 287, 287, 287, 288, 288, 288, + 289, 290, 291, 291, 291, 291, 291, 292, 293, 293, + 293, 293, 293, 293, 293, 293, 293, 294, 294, 295, + 295, 296, 297, 298, 298, 298, 298, 299, 299, 299, + 300, 300, 301, 301, 302, 302, 303, 304, 304, 304, + 304, 305, 305, 306, 307, 307, 307, 308, 308, 308, + 309, 309, 309, 310, 311, 312, 312, 313, 313, 314, + 314, 314, 315, 315, 316, 316, 316, 316, 317, 317, + 318, 318, 319, 319, 320, 321, 322, 323, 323, 323, + 324, 325, 325, 325, 325, 325, 325, 326, 326, 326, + 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, + 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, + 326, 326, 326, 326, 327, 327 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 1, 1, 1, 2, 2, 2, 3, 1, - 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 3, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 2, 1, 1, 1, 1, 0, 1, 1, - 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, - 4, 3, 2, 2, 4, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 1, 1, 1, 0, 2, - 0, 1, 2, 5, 3, 1, 3, 2, 3, 1, + 2, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 1, 1, 3, 5, 7, 1, 3, 1, - 1, 1, 1, 1, 1, 5, 1, 3, 5, 0, - 1, 3, 1, 1, 1, 2, 3, 1, 1, 2, - 1, 2, 3, 3, 1, 1, 1, 0, 3, 1, - 3, 3, 5, 2, 2, 4, 2, 2, 3, 1, - 4, 6, 4, 5, 6, 4, 3, 1, 1, 1, - 1, 2, 3, 5, 6, 6, 6, 6, 6, 7, - 6, 6, 6, 6, 8, 8, 0, 2, 2, 2, - 1, 3, 1, 4, 4, 3, 6, 4, 4, 6, - 3, 1, 3, 0, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 5, 3, 0, 1, 0, 1, - 1, 1, 1, 2, 1, 2, 1, 2, 2, 3, - 0, 1, 2, 1, 2, 1, 2, 2, 0, 2, - 4, 1, 4, 5, 1, 4, 4, 5, 0, 1, - 1, 1, 0, 1, 3, 3, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, + 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, + 1, 1, 1, 0, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 4, 2, 1, 1, + 3, 2, 3, 2, 2, 3, 3, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, + 0, 2, 0, 1, 2, 5, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 3, 5, 3, 5, 0, + 2, 0, 2, 3, 3, 5, 1, 1, 3, 5, + 7, 1, 3, 1, 3, 1, 1, 1, 1, 1, + 1, 5, 1, 3, 5, 0, 1, 3, 1, 1, + 1, 2, 3, 1, 1, 2, 1, 2, 3, 3, + 1, 1, 1, 0, 3, 1, 3, 3, 5, 2, + 2, 4, 2, 2, 3, 1, 4, 6, 4, 5, + 6, 4, 3, 1, 1, 1, 1, 2, 3, 5, + 6, 6, 6, 6, 6, 7, 6, 6, 6, 6, + 8, 8, 6, 0, 2, 2, 2, 1, 3, 1, + 4, 4, 3, 6, 3, 4, 4, 6, 3, 1, + 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 5, 3, 0, 1, 0, 1, 1, + 1, 1, 2, 1, 2, 1, 2, 2, 3, 0, + 1, 2, 1, 2, 1, 2, 2, 0, 2, 4, + 1, 4, 5, 1, 4, 4, 5, 0, 1, 1, + 1, 0, 1, 3, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 2, 4, 4, 0, 2, 0, 2, 2, 1, - 1, 3, 2, 3, 4, 1, 2, 0, 2, 3, - 2, 2, 2, 0, 2, 3, 2, 3, 2, 3, - 3, 4, 1, 2, 2, 3, 2, 2, 0, 1, - 1, 2, 2, 3, 2, 1, 2, 1, 2, 2, - 2, 2, 0, 1, 3, 5, 2, 3, 2, 0, - 1, 2, 2, 2, 2, 4, 5, 5, 3, 1, - 2, 3, 3, 2, 2, 3, 3, 0, 2, 1, - 3, 3, 3, 0, 1, 1, 3, 2, 3, 2, - 2, 1, 0, 2, 4, 2, 1, 3, 2, 4, - 3, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 2, 4, 4, 0, + 2, 0, 2, 2, 1, 1, 3, 2, 3, 4, + 1, 2, 0, 2, 3, 2, 2, 2, 0, 2, + 3, 2, 3, 2, 3, 3, 4, 1, 2, 2, + 3, 2, 2, 0, 1, 1, 2, 2, 3, 2, + 1, 2, 1, 2, 2, 2, 2, 0, 1, 3, + 5, 2, 3, 2, 0, 1, 2, 2, 2, 2, + 4, 5, 5, 3, 1, 2, 3, 3, 2, 2, + 3, 3, 0, 2, 1, 3, 3, 3, 0, 1, + 1, 3, 2, 3, 2, 2, 1, 0, 2, 4, + 2, 1, 3, 2, 4, 3, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1 + 1, 1, 1, 1, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -1311,486 +1338,486 @@ static const yytype_uint8 yyr2[] = means the default is an error. */ static const yytype_uint16 yydefact[] = { - 0, 3, 222, 226, 230, 224, 233, 235, 357, 0, - 0, 57, 53, 54, 55, 56, 75, 76, 77, 78, - 80, 0, 0, 238, 238, 238, 238, 238, 238, 186, - 79, 81, 82, 359, 0, 0, 117, 0, 371, 85, - 86, 87, 0, 0, 119, 120, 121, 122, 123, 124, - 0, 295, 303, 297, 284, 312, 284, 284, 318, 286, - 325, 327, 280, 332, 284, 339, 0, 113, 112, 108, - 109, 107, 0, 95, 0, 0, 349, 0, 0, 0, - 9, 0, 2, 4, 0, 12, 18, 19, 33, 50, - 0, 34, 51, 0, 83, 99, 100, 101, 22, 104, - 106, 105, 102, 103, 26, 27, 28, 29, 30, 31, - 32, 13, 15, 16, 17, 35, 14, 0, 170, 90, - 0, 252, 0, 0, 0, 21, 23, 257, 258, 259, - 261, 260, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 20, 24, 25, 36, 92, 231, 228, 256, 0, 0, - 97, 0, 0, 0, 0, 157, 159, 423, 424, 425, - 384, 382, 385, 386, 422, 383, 388, 387, 391, 390, - 389, 426, 405, 406, 407, 408, 410, 411, 412, 413, - 414, 415, 416, 417, 418, 420, 419, 421, 392, 393, - 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, - 409, 404, 0, 427, 126, 58, 0, 59, 52, 0, - 73, 0, 0, 0, 244, 241, 223, 0, 238, 225, - 227, 230, 234, 236, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 359, 0, 363, - 0, 0, 0, 369, 370, 289, 290, 288, 284, 284, - 284, 302, 0, 0, 296, 284, 0, 292, 313, 284, - 314, 316, 319, 320, 317, 0, 324, 286, 322, 326, - 328, 330, 0, 329, 333, 331, 284, 336, 340, 338, - 342, 343, 344, 0, 0, 110, 0, 0, 0, 350, - 353, 354, 0, 0, 10, 1, 5, 6, 7, 222, - 61, 72, 67, 62, 63, 65, 64, 68, 66, 38, - 39, 42, 40, 41, 43, 84, 111, 44, 45, 48, - 46, 47, 49, 171, 0, 88, 91, 138, 140, 146, - 154, 145, 144, 372, 376, 253, 0, 372, 153, 156, - 0, 94, 232, 358, 254, 255, 98, 0, 0, 0, - 0, 0, 0, 129, 0, 60, 71, 0, 0, 248, - 0, 0, 237, 239, 229, 0, 0, 0, 0, 0, + 0, 3, 241, 245, 249, 243, 252, 254, 382, 0, + 0, 53, 49, 50, 51, 52, 77, 78, 79, 80, + 82, 0, 0, 0, 257, 257, 257, 257, 257, 257, + 203, 81, 83, 84, 384, 0, 0, 133, 0, 396, + 87, 88, 89, 0, 0, 135, 136, 137, 138, 139, + 140, 0, 320, 328, 322, 309, 337, 309, 309, 343, + 311, 350, 352, 305, 357, 309, 364, 0, 127, 131, + 126, 108, 121, 121, 107, 0, 97, 0, 0, 0, + 0, 374, 0, 0, 0, 299, 300, 301, 302, 303, + 304, 9, 0, 2, 4, 0, 12, 14, 20, 34, + 46, 0, 0, 35, 47, 0, 85, 99, 100, 23, + 103, 111, 112, 109, 110, 106, 104, 105, 101, 102, + 27, 28, 29, 30, 31, 32, 33, 15, 17, 18, + 19, 36, 16, 0, 186, 92, 0, 271, 0, 0, + 0, 22, 24, 37, 276, 277, 278, 280, 279, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 294, 295, 296, 297, 298, 21, 25, 26, + 38, 94, 250, 247, 0, 275, 0, 0, 0, 0, + 0, 0, 173, 175, 431, 432, 433, 409, 407, 410, + 411, 408, 413, 412, 416, 415, 414, 434, 417, 418, + 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, + 430, 429, 0, 435, 142, 54, 0, 55, 48, 0, + 0, 71, 0, 0, 0, 0, 263, 260, 242, 0, + 257, 244, 246, 249, 253, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 384, 0, 388, 0, 0, 0, 394, 395, 314, 315, + 313, 309, 309, 309, 327, 0, 0, 321, 309, 0, + 317, 338, 309, 339, 341, 344, 345, 342, 0, 349, + 311, 347, 351, 353, 355, 0, 354, 358, 356, 309, + 361, 365, 363, 367, 368, 369, 0, 0, 0, 0, + 119, 119, 113, 0, 0, 0, 0, 0, 375, 378, + 379, 0, 0, 10, 1, 5, 6, 7, 241, 0, + 57, 69, 68, 73, 63, 58, 59, 61, 60, 64, + 62, 0, 74, 40, 41, 44, 42, 43, 45, 86, + 114, 13, 187, 0, 90, 93, 154, 156, 162, 170, + 161, 160, 397, 401, 272, 0, 397, 169, 172, 0, + 96, 251, 121, 383, 273, 274, 0, 0, 0, 0, + 0, 0, 145, 0, 56, 75, 70, 72, 76, 0, + 267, 0, 0, 256, 258, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 203, 0, 0, 216, 216, 0, 0, 0, 172, 0, - 0, 190, 187, 11, 0, 0, 360, 364, 365, 361, - 362, 118, 280, 284, 304, 284, 284, 308, 284, 306, - 298, 300, 0, 301, 284, 293, 285, 315, 321, 287, - 323, 281, 0, 337, 341, 114, 0, 96, 0, 348, - 351, 352, 355, 356, 8, 141, 0, 0, 0, 37, - 139, 0, 375, 0, 0, 378, 0, 147, 0, 167, - 169, 168, 166, 0, 0, 0, 0, 0, 0, 158, - 137, 132, 134, 133, 0, 0, 130, 127, 0, 74, - 0, 249, 250, 251, 0, 0, 0, 0, 218, 220, - 221, 203, 203, 203, 203, 218, 0, 0, 0, 0, - 0, 0, 0, 216, 216, 0, 0, 203, 203, 203, - 217, 203, 0, 0, 203, 188, 189, 367, 0, 0, - 291, 305, 309, 284, 310, 307, 299, 294, 0, 0, - 334, 0, 0, 345, 142, 143, 89, 373, 0, 380, - 377, 155, 0, 0, 93, 162, 165, 160, 0, 0, - 0, 135, 0, 0, 125, 0, 69, 0, 240, 242, - 0, 0, 246, 245, 203, 219, 0, 0, 0, 0, - 215, 0, 205, 206, 208, 209, 212, 213, 210, 211, - 207, 173, 0, 0, 0, 0, 0, 0, 0, 0, - 368, 366, 311, 283, 282, 0, 0, 115, 346, 347, - 0, 0, 379, 149, 0, 152, 163, 0, 0, 136, - 131, 128, 0, 243, 247, 0, 176, 174, 177, 178, - 218, 204, 182, 183, 180, 181, 0, 0, 0, 0, - 0, 192, 0, 0, 175, 335, 0, 374, 381, 0, - 148, 161, 164, 70, 179, 214, 0, 0, 0, 0, - 0, 0, 216, 0, 116, 150, 0, 0, 0, 195, - 0, 0, 201, 184, 191, 0, 185, 193, 194, 0, - 0, 197, 0, 198, 216, 0, 202, 200, 0, 196, - 199 + 0, 0, 221, 0, 0, 235, 235, 0, 0, 0, + 0, 188, 0, 0, 207, 204, 11, 0, 0, 385, + 389, 390, 386, 387, 134, 305, 309, 329, 309, 309, + 333, 309, 331, 323, 325, 0, 326, 309, 318, 310, + 340, 346, 312, 348, 306, 0, 362, 366, 128, 0, + 132, 122, 0, 123, 124, 98, 115, 117, 0, 373, + 376, 377, 380, 381, 8, 67, 65, 0, 157, 0, + 0, 0, 39, 155, 0, 400, 0, 0, 403, 0, + 163, 0, 119, 183, 185, 184, 182, 0, 0, 0, + 0, 0, 0, 174, 153, 148, 150, 149, 0, 0, + 146, 143, 0, 268, 269, 270, 0, 0, 0, 0, + 237, 239, 240, 221, 221, 221, 221, 237, 0, 0, + 0, 0, 0, 0, 0, 235, 235, 0, 0, 0, + 221, 221, 221, 236, 221, 221, 0, 0, 221, 205, + 206, 392, 0, 0, 316, 330, 334, 309, 335, 332, + 324, 319, 0, 0, 359, 0, 0, 120, 0, 0, + 370, 0, 158, 159, 91, 398, 0, 405, 402, 171, + 0, 0, 95, 125, 178, 181, 176, 0, 0, 0, + 151, 0, 0, 141, 0, 259, 261, 0, 0, 265, + 264, 221, 238, 0, 0, 0, 0, 234, 0, 223, + 224, 226, 227, 230, 231, 228, 229, 232, 225, 189, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 393, + 391, 336, 308, 307, 0, 0, 129, 116, 118, 371, + 372, 66, 0, 0, 404, 165, 0, 168, 179, 0, + 0, 152, 147, 144, 262, 266, 0, 192, 190, 193, + 194, 237, 222, 198, 199, 196, 197, 202, 0, 0, + 0, 0, 0, 0, 209, 0, 0, 191, 360, 0, + 399, 406, 0, 164, 177, 180, 195, 233, 0, 0, + 0, 0, 0, 0, 0, 235, 0, 130, 166, 0, + 0, 0, 212, 214, 0, 0, 219, 200, 208, 0, + 201, 210, 211, 0, 0, 215, 0, 216, 235, 0, + 220, 218, 0, 213, 217 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 81, 82, 83, 84, 339, 86, 87, 88, 89, - 218, 311, 479, 90, 91, 92, 93, 94, 449, 335, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 212, 475, 476, 336, - 337, 338, 340, 341, 543, 604, 111, 112, 113, 114, - 115, 116, 165, 166, 462, 117, 118, 246, 402, 630, - 631, 633, 661, 662, 506, 390, 509, 564, 510, 119, - 120, 121, 122, 156, 123, 124, 226, 227, 228, 484, - 346, 125, 126, 283, 267, 278, 127, 257, 128, 129, - 130, 264, 131, 261, 132, 133, 134, 135, 274, 136, - 137, 138, 139, 140, 285, 141, 142, 289, 143, 144, - 145, 146, 147, 148, 149, 159, 150, 406, 407, 408, - 151, 152, 153, 452, 342, 343, 213, 344 + -1, 92, 93, 94, 95, 96, 348, 98, 99, 100, + 218, 321, 332, 322, 323, 101, 102, 103, 104, 105, + 106, 472, 344, 107, 108, 109, 110, 111, 112, 453, + 300, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 123, 124, 125, 126, 212, 499, 500, 345, 346, + 347, 349, 350, 571, 636, 127, 128, 129, 130, 131, + 132, 182, 183, 486, 133, 134, 249, 415, 663, 664, + 666, 695, 696, 529, 402, 532, 591, 533, 135, 136, + 137, 138, 173, 139, 140, 228, 229, 230, 506, 355, + 141, 142, 143, 286, 270, 281, 144, 260, 145, 146, + 147, 267, 148, 264, 149, 150, 151, 152, 277, 153, + 154, 155, 156, 157, 288, 158, 159, 292, 160, 161, + 162, 163, 164, 165, 166, 177, 167, 419, 420, 421, + 168, 169, 170, 475, 351, 352, 213, 353 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -475 +#define YYPACT_NINF -479 static const yytype_int16 yypact[] = { - 365, -475, 28, -475, -61, -475, -475, -475, 145, -39, - 1154, 35, -475, -475, -475, -475, -475, -475, -475, -475, - -475, 1154, 1154, 30, 30, 30, 30, 30, 30, 139, - -475, -475, -475, 821, 15, 201, -475, -83, -475, -475, - -475, -475, 41, 57, -475, -475, -475, -475, -475, -475, - 191, -475, 170, 55, 135, 42, -62, 46, -33, -11, - 98, 87, -7, 157, -63, 162, 150, 26, -475, -475, - -475, -475, 1154, 241, 303, 312, -475, 204, 237, -51, - 273, 322, 541, -475, 8, -475, -475, -475, -475, -475, - 184, -475, -475, 227, 1258, -475, -475, -475, -475, -475, - -475, -475, -475, -475, -475, -475, -475, -475, -475, -475, - -475, -475, -475, -475, -475, -475, -475, 227, 285, 154, - 660, 258, 1154, 660, 1154, -475, -475, -475, -475, -475, - -475, -475, -475, -475, -475, -475, -475, -475, -475, -475, - -475, -475, -475, -475, -475, -475, -475, -475, -475, -475, - -475, -475, -475, -475, -18, 276, -475, -475, 151, 16, - 154, 160, 247, 248, -36, -475, 164, -475, -475, -475, - -475, -475, -475, -475, -475, -475, -475, -475, -475, -475, - -475, -475, -475, -475, -475, -475, -475, -475, -475, -475, - -475, -475, -475, -475, -475, -475, -475, -475, -475, -475, - -475, -475, -475, -475, -475, -475, -475, -475, -475, -475, - -475, -475, 163, -475, 165, -475, 278, -475, -475, 309, - 311, 172, 173, 174, 175, -475, -475, 310, 30, -475, - -475, -61, -475, -475, 263, 179, 181, 182, 186, 169, - 187, 190, 193, 195, 202, 196, 36, -475, 218, 244, - 266, 269, 238, -475, -475, -475, 242, -475, -30, 52, - -24, -475, -22, 284, -475, 183, 302, -475, -475, 46, - -475, -475, -475, 308, -475, 319, -475, 261, -475, -475, - -475, -475, 253, -475, 236, -475, 46, -475, 280, -475, - -475, -475, -475, 323, 255, -475, 1154, 325, 326, 290, - 295, -475, 296, 297, -475, -475, -475, -475, 366, -475, - -475, -475, -475, -475, -475, -475, -475, -475, -475, -475, - -475, -475, -475, -475, -475, -25, -475, -475, -475, -475, - -475, -475, -475, -475, 1, 387, 154, -475, -475, -475, - -475, -475, -475, 286, 935, -475, 389, 286, -475, -475, - 395, -6, -475, -475, -475, -475, 154, 60, 256, 257, - 260, 99, -37, -4, 1154, -475, -475, 265, 307, 104, - 341, -5, -475, -475, -475, 262, 93, 93, 93, 93, - 79, 267, 268, 270, 271, 272, 283, 292, 293, 294, - -475, 93, 93, 93, 93, 298, 300, 93, -475, 344, - 347, -475, -475, -475, 375, 374, -475, 274, -475, -475, - -475, -475, 316, 46, -475, 46, -16, -475, 46, -475, - -475, -475, 355, -475, 46, -475, -475, -475, -475, -475, - -475, -50, 332, -475, -475, 394, 301, -475, 304, -475, - -475, -475, -475, -475, -475, -475, 305, 146, 660, -475, - -475, -41, -475, 1154, 1154, -475, 660, 3, 660, -475, - -475, -475, -475, 60, 60, 60, 306, 382, 383, -475, - -475, -475, -475, -475, -34, 114, -475, 299, 391, 314, - 313, -475, -475, -475, 318, 396, -48, 320, 93, -475, - -475, -475, -475, -475, -475, 93, 397, 93, 93, 93, - 93, 93, 93, 93, 93, 93, -17, -475, -475, -475, - -475, -475, 317, 321, -475, -475, -475, -475, 411, 244, - -475, -475, -475, 46, -475, -475, -475, -475, 362, 363, - 315, 333, 409, 6, -475, -475, -475, -475, 412, -475, - 1050, -475, 413, 69, -475, -475, -475, -475, 60, 334, - 337, -475, 419, -4, -475, 1154, -475, 343, -475, -475, - 342, 346, -475, -475, -475, -475, -15, -14, -13, -12, - -475, 345, -475, -475, -475, -475, -475, -475, -475, -475, - -475, -475, 169, -9, -8, -3, -2, 88, 449, 0, - -475, -475, -475, -475, -475, 450, 367, -475, -475, -475, - 361, 1154, -475, -475, 125, -475, -475, 60, 60, -475, - -475, -475, 451, -475, -475, 2, -475, -475, -475, -475, - 93, -475, -475, -475, -475, -475, 368, 369, 370, 371, - 386, 376, 372, 393, -475, -475, 452, -475, -475, 454, - -475, -475, -475, -475, -475, -475, 93, 93, -68, 460, - 522, 88, 93, 529, -475, -475, 400, 407, 414, -475, - 415, 410, 417, -475, -475, 78, -475, -475, -475, 93, - 93, -475, 460, -475, 93, 416, -475, -475, 418, -475, - -475 + 418, -479, 36, -479, -62, -479, -479, -479, 47, -14, + 1104, 50, 68, -479, -479, -479, -479, -479, -479, -479, + -479, 1104, 1104, 116, 8, 8, 8, 8, 8, 8, + 300, -479, -479, -479, 770, 109, 51, -479, 29, -479, + -479, -479, -479, 137, 157, -479, -479, -479, -479, -479, + -479, 129, -479, 221, 54, 71, 210, -54, 124, -2, + -36, 182, 172, 92, 217, -15, 224, 148, 49, 297, + -479, -479, 319, 319, -479, 1104, 285, 328, 330, 348, + 355, -479, 254, 291, -40, -479, -479, -479, -479, -479, + -479, 327, 379, 595, -479, -8, -479, -479, -479, -479, + -479, 11, 200, -479, -479, 360, 1212, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, -479, 944, 341, 201, 95, 316, 1104, 95, + 1104, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, 0, 334, -479, 367, -479, 199, 218, 208, 305, + 308, -11, -479, 230, -479, -479, -479, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, 216, -479, 227, -479, 350, -479, -479, 1104, + 388, 385, 1104, 234, 235, 237, 238, -479, -479, 383, + 8, -479, -479, -62, -479, -479, 353, 256, 257, 263, + 264, 212, 267, 275, 277, 278, 279, 198, 280, 46, + -479, 286, 76, 380, 384, 345, -479, -479, -479, 351, + -479, -25, -44, 38, -479, -16, 386, -479, 207, 392, + -479, -479, 124, -479, -479, -479, 393, -479, 394, -479, + 346, -479, -479, -479, -479, 361, -479, 301, -479, 124, + -479, 363, -479, -479, -479, -479, 400, 329, 402, 403, + 354, 354, -479, 1104, 405, 406, 407, 409, 376, 377, + -479, 378, 397, -479, -479, -479, -479, 447, -479, 414, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, 417, 325, -479, -479, -479, -479, -479, -479, 13, + -479, -479, -479, 10, 489, 201, -479, -479, -479, -479, + -479, -479, 381, 206, -479, 490, 381, -479, -479, 491, + 3, -479, 319, -479, -479, -479, 120, 337, 338, 340, + 147, -14, 2, 1104, -479, -479, -479, -479, -479, 408, + 284, 439, -7, -479, -479, -479, 342, 136, 136, 136, + 136, -27, 343, 347, 349, 352, 356, 357, 358, 359, + 364, 365, -479, 136, 136, 136, 136, 136, 366, 368, + 136, -479, 443, 444, -479, -479, -479, 470, 471, -479, + 370, -479, -479, -479, -479, 410, 124, -479, 124, 41, + -479, 124, -479, -479, -479, 451, -479, 124, -479, -479, + -479, -479, -479, -479, -69, 427, -479, -479, 464, 387, + -479, -479, 468, -479, -479, -479, 532, 535, 389, -479, + -479, -479, -479, -479, -479, -479, -479, 390, -479, 382, + 169, 95, -479, -479, -29, -479, 1104, 1104, -479, 95, + -9, 95, 354, -479, -479, -479, -479, 120, 120, 120, + 416, 506, 515, -479, -479, -479, -479, -479, 7, 110, + -479, 429, 431, -479, -479, -479, 432, 538, -53, 442, + 136, -479, -479, -479, -479, -479, -479, 136, 550, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, -13, + -479, -479, -479, -479, -479, -479, 450, 452, -479, -479, + -479, -479, 574, 76, -479, -479, -479, 124, -479, -479, + -479, -479, 521, 522, 460, 486, 559, -479, 560, 561, + 26, 562, -479, -479, -479, -479, 563, -479, 1070, -479, + 569, 70, -479, -479, -479, -479, -479, 120, 472, 473, + -479, 572, 2, -479, 1104, -479, -479, 474, 475, -479, + -479, -479, -479, -5, -4, -3, -1, -479, 479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + 212, 9, 15, 17, 18, 19, 140, 589, 20, -479, + -479, -479, -479, -479, 578, 481, -479, -479, -479, -479, + -479, -479, 480, 1104, -479, -479, 111, -479, -479, 120, + 120, -479, -479, -479, -479, -479, 21, -479, -479, -479, + -479, 136, -479, -479, -479, -479, -479, -479, 482, 483, + 484, 485, 487, 488, 492, 495, 496, -479, -479, 585, + -479, -479, 587, -479, -479, -479, -479, -479, 136, 136, + -59, 508, 588, 633, 140, 136, 652, -479, -479, 510, + 511, 514, -479, -479, 516, 513, 518, -479, -479, 42, + -479, -479, -479, 136, 136, -479, 588, -479, 136, 517, + -479, -479, 519, -479, -479 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -475, -475, -475, 498, 549, 5, -475, -475, -475, -475, - -475, -475, -475, -475, -475, -475, -475, -475, -475, 432, - -475, -475, -475, -475, -475, -475, -475, -475, -475, -475, - -475, -475, -475, -475, -475, 500, 11, -475, 44, -150, - -303, -475, -120, 45, -475, -475, -27, 95, 108, 137, - 188, -475, 239, -475, -446, 480, -475, -475, -475, -52, - -475, -475, -72, -475, -285, 20, -387, -474, -363, -475, - -475, -475, -475, 377, -475, -475, 264, 378, -475, -475, - -475, -475, -475, 197, -55, 328, -475, -475, -475, -475, - -475, -475, -475, -475, -475, -475, -475, -475, -475, -475, - -475, -475, -475, -475, -475, -475, -475, -475, -475, -475, - -475, -475, -475, -475, -475, -475, -475, -475, -475, 84, - -475, -475, 517, 281, -475, 180, -475, -10 + -479, -479, -479, 607, 668, 571, 1, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, 534, -479, -479, -479, -479, -479, -479, -287, + -60, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, -479, -479, 605, 632, -479, 126, -146, -281, + -479, -134, 138, -479, -479, 128, 131, 141, 151, 164, + -479, 339, -479, -455, 577, -479, -479, -479, 28, -479, + -479, 12, -479, -227, 103, -402, -478, -381, -479, -479, + -479, -479, 494, -479, -479, 253, 493, -479, -479, -479, + -479, -479, -479, 290, -55, 436, -479, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, -479, + -479, -479, -479, -479, -479, -479, -479, -479, -479, 174, + -479, -479, 621, 369, -479, 97, -479, -10 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -427 +#define YYTABLE_NINF -435 static const yytype_int16 yytable[] = { - 214, 270, 271, 348, 351, 85, 309, 511, -90, 287, - 356, 219, 220, 491, 492, 493, 494, 545, 546, 547, - -91, 570, 581, -426, 616, 617, 618, 619, 507, 508, - 622, 623, 23, 450, 514, 561, 624, 625, 85, 634, - 160, 644, 537, 470, 161, 658, 161, 360, 450, 551, - 272, -151, 293, 450, 215, 216, 307, 162, 163, 162, - 163, 420, 214, 313, 301, 155, 320, 302, 266, 266, - 528, 249, 221, 222, 309, 398, 399, 400, 486, 471, - 354, 355, 286, 295, 214, 413, 252, 85, 269, 598, - 328, 418, 223, 273, 472, 310, 294, 217, 319, 523, - 23, 266, 606, 659, 421, 326, 154, 266, 281, 422, - 487, 473, 282, 224, 303, 266, 578, 579, 529, 401, - 275, 599, 327, 562, 253, 565, 276, 277, 164, 538, - 164, 361, 565, 552, 572, 573, 574, 575, 576, 577, - 254, -426, 580, 459, 450, 225, 645, -426, 481, 482, - 483, 582, 334, 582, 582, 582, 582, 268, 460, 582, - 582, 641, 642, 474, 334, 582, 582, 415, 582, -151, - 582, 334, 445, 542, 308, 461, 489, 266, 416, 262, - 490, 279, 466, 266, 447, 314, 263, 626, 321, 309, - 3, 4, 5, 6, 7, 467, 468, 10, 315, 627, - 628, 322, 629, 414, 417, 419, 566, 567, 568, 569, - 425, 157, 329, 158, 427, 23, 24, 25, 26, 27, - 28, 234, 583, 584, 585, 330, 586, 316, 280, 589, - 323, 433, 309, 3, 4, 5, 6, 7, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 495, 673, - 245, 496, 380, 674, 331, 250, 251, 565, 23, 24, - 25, 26, 27, 28, 265, 665, 266, 38, 381, 382, - 383, 384, 284, 385, 386, 387, 388, 288, 317, 615, - 389, 324, 553, 656, 657, 554, 437, 678, 229, 230, - 231, 232, 233, 639, 258, 259, 640, 260, 290, 291, - 292, 404, 347, 405, 349, 332, 675, 676, 255, 256, - 296, 395, 396, 424, 266, 297, 334, 535, 298, 299, - 300, 304, 305, 29, 334, 345, 352, 353, 536, 357, - 358, 359, 362, 363, 455, 366, 541, 364, 544, 446, - 365, 367, 368, 369, 370, 371, 375, 372, 376, 409, - 377, 378, 410, 411, 477, 379, 391, 412, 521, 392, - 522, 524, 393, 525, 394, 397, 1, 423, 431, 527, + 214, 97, 273, 274, 534, 357, 513, 514, 515, 516, + 290, 220, 221, 301, 454, 318, 318, 3, 4, 5, + 6, 7, 530, 531, 10, 360, 535, -92, 609, 538, + -93, 588, 574, 575, 576, 97, 647, 648, 649, 597, + 650, -167, 316, 24, 24, 25, 26, 27, 28, 29, + 653, 494, 223, 224, 552, 565, 654, 691, 655, 656, + 657, 667, 676, -434, 473, 214, 174, 172, 433, 215, + 178, 216, 225, 369, 428, 318, 296, 508, 310, 473, + 269, 311, 275, 179, 180, 429, 495, 411, 412, 413, + 269, 580, 226, 426, 97, 39, 340, 219, 278, 272, + 318, 496, 320, 24, 279, 280, 333, 253, 254, 269, + 629, 509, 553, 434, 217, 175, 171, 176, 435, 269, + 497, 297, 638, 605, 606, 692, 227, 276, 24, 592, + 414, 589, 312, 289, 97, 417, 592, 418, 599, 600, + 601, 602, 603, 604, 630, 222, 607, 608, 184, 185, + 186, 187, 188, 189, 566, 517, 431, 190, 518, 547, + 191, 192, 193, 194, 195, 196, 181, 252, 610, 370, + -167, 317, 269, 677, 570, 269, 610, 610, 610, 197, + 610, 265, 498, 343, 674, 675, 343, 581, 266, 473, + 610, 319, -434, 343, 468, 573, 610, 470, 610, 610, + 610, 610, 610, 268, 483, 269, 427, 430, 432, 375, + 284, 255, 378, 438, 285, 198, 199, 440, 200, 484, + 511, 256, 201, 202, 512, 203, 707, 204, 205, 325, + 708, 490, 326, 334, 446, 356, 335, 358, 485, 206, + 658, 257, 327, 207, 491, 492, 336, 208, 209, 258, + 259, 210, 328, 659, 660, 661, 337, 662, 269, 184, + 185, 186, 187, 188, 189, 329, 282, 211, 190, 338, + 592, 191, 192, 193, 194, 195, 196, 476, 231, 232, + 233, 234, 235, 699, 364, 365, 593, 594, 595, 596, + 197, 582, 672, 455, 583, 673, 391, 689, 690, 293, + 294, 295, 482, 611, 612, 613, 712, 614, 615, 408, + 409, 618, 392, 393, 394, 395, 283, 396, 397, 398, + 399, 400, 709, 710, 298, 401, 198, 199, 271, 200, + 503, 504, 505, 201, 202, 287, 203, 564, 204, 205, + 437, 269, 291, 478, 469, 569, 299, 572, 261, 262, + 206, 263, 343, 563, 207, 304, 303, 305, 208, 209, + 306, 307, 210, 501, 646, 318, 3, 4, 5, 6, + 7, 545, 308, 546, 548, 309, 549, 313, 211, 314, + 331, 30, 551, 236, 343, 354, 361, 362, 363, 367, + 366, 477, 368, 24, 25, 26, 27, 28, 29, 372, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 371, 373, 248, 374, 376, 377, 379, 380, 1, + 381, 382, 383, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 386, 387, 388, + 16, 17, 18, 19, 20, 389, 390, 21, 22, 403, + 23, 24, 25, 26, 27, 28, 29, 404, 30, 405, + 406, 407, 410, 424, 422, 416, 567, 568, 423, 425, + 436, 31, 32, 33, 34, 35, 439, 441, 442, 444, + 278, 447, 445, 36, 448, 449, 450, 451, 452, 456, + 457, 458, 621, 459, 460, 461, 462, 464, 465, 37, + 38, 466, 39, 40, 41, 42, 467, 43, 44, 45, + 46, 47, 48, 49, 50, 463, 471, 479, 481, 487, + 488, 474, 489, 507, 510, 519, 502, 539, 540, 520, + 541, 521, 285, 542, 522, 550, 555, 51, 523, 524, + 525, 526, 52, 53, 54, 554, 527, 528, 536, 55, + 537, 543, 557, 56, 57, 58, 59, 60, 634, 558, + 61, 62, 559, 63, 64, 65, 562, 66, 67, 556, + 561, 560, 68, 69, 643, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 578, 85, 86, 87, 88, 89, 90, 91, 577, 579, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 403, 426, 16, 17, 18, 19, - 20, 428, 275, 21, 22, 434, 23, 24, 25, 26, - 27, 28, 429, 29, 432, 440, 435, 436, 438, 439, - 441, 442, 443, 448, 444, 456, 30, 31, 32, 33, - 34, 458, 480, 451, 485, 463, 464, 515, 35, 465, - 516, 488, 478, 517, 518, 282, 497, 498, 526, 499, - 500, 501, 519, 539, 540, 36, 37, 530, 38, 39, - 40, 41, 502, 42, 43, 44, 45, 46, 47, 48, - 49, 503, 504, 505, 531, 549, 550, 512, 592, 513, - 532, 555, 590, 533, 556, 548, 534, 593, 594, 560, - 571, 50, 557, 595, 558, 596, 51, 52, 53, 559, - 587, 563, 597, 54, 588, 600, 603, 55, 56, 57, - 58, 59, 609, 607, 60, 61, 608, 62, 63, 64, - 612, 65, 66, 613, 620, 632, 67, 614, 68, 69, - 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 602, 80, 637, 635, 643, 654, 636, 655, 646, 647, - 648, 649, 652, 660, 651, 611, 2, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 650, 663, 16, 17, 18, 19, 20, 653, 666, 21, - 22, 667, 23, 24, 25, 26, 27, 28, 668, 29, - 306, 671, 248, 669, 670, 672, 350, 679, 605, 680, - 312, 638, 30, 31, 32, 33, 34, 610, 333, 664, - 677, 469, 621, 591, 35, 430, 373, 318, 374, 520, + 12, 13, 14, 15, 584, 585, 586, 16, 17, 18, + 19, 20, 587, 671, 21, 22, 590, 23, 24, 25, + 26, 27, 28, 29, 598, 30, 616, 619, 617, 622, + 623, 624, 625, 626, 627, 628, 631, 632, 31, 32, + 33, 34, 35, 635, 639, 640, 641, 665, 644, 645, + 36, 651, 668, 669, 670, 678, 679, 680, 681, 687, + 682, 688, 694, 684, 697, 683, 37, 38, 685, 39, + 40, 41, 42, 686, 43, 44, 45, 46, 47, 48, + 49, 50, 693, 700, 701, 702, 703, 705, 704, 706, + 315, 713, 251, 714, 341, 359, 324, 302, 642, 637, + 493, 342, 698, 652, 51, 544, 443, 620, 711, 52, + 53, 54, 330, 384, 0, 480, 55, 385, 0, 0, + 56, 57, 58, 59, 60, 0, 0, 61, 62, 0, + 63, 64, 65, 0, 66, 67, 0, 0, 0, 68, + 69, 0, 70, 71, 72, 73, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 0, 85, 86, + 87, 88, 89, 90, 91, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, + 0, 0, 16, 17, 18, 19, 20, 0, 0, 21, + 22, 0, 23, 24, 25, 26, 27, 28, 29, 0, + 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 31, 32, 33, 250, 35, 0, 0, + 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 36, 37, 0, 38, 39, 40, 41, 457, 42, - 43, 44, 45, 46, 47, 48, 49, 0, 0, 0, + 0, 37, 38, 0, 39, 40, 41, 42, 0, 43, + 44, 45, 46, 47, 48, 49, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, - 0, 0, 51, 52, 53, 309, 0, 0, 0, 54, - 0, 0, 0, 55, 56, 57, 58, 59, 0, 0, - 60, 61, 0, 62, 63, 64, 0, 65, 66, 0, - 0, 23, 67, 0, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 0, 80, 0, 0, - 0, 167, 168, 169, 170, 171, 172, 0, 0, 0, - 173, 0, 174, 175, 176, 177, 178, 179, 180, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, + 0, 0, 0, 0, 52, 53, 54, 0, 0, 0, + 0, 55, 0, 0, 0, 56, 57, 58, 59, 60, + 0, 0, 61, 62, 0, 63, 64, 65, 0, 66, + 67, 0, 0, 0, 68, 69, 0, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 0, 85, 86, 87, 88, 89, 90, 2, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 0, 0, 0, 16, 17, 18, 19, + 20, 0, 0, 21, 22, 0, 23, 24, 25, 26, + 27, 28, 29, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 31, 32, 33, + 250, 35, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 181, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, - 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, - 193, 194, 195, 196, 197, 0, 0, 198, 199, 0, - 200, 0, 0, 0, 201, 202, 0, 203, 0, 204, - 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 206, 0, 0, 0, 207, 0, 0, 0, 208, - 209, 0, 210, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 211, 2, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 0, 16, 17, 18, 19, 20, 0, 0, 21, - 22, 0, 23, 24, 25, 26, 27, 28, 0, 29, + 0, 0, 0, 0, 0, 37, 38, 0, 39, 40, + 41, 42, 0, 43, 44, 45, 46, 47, 48, 49, + 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 30, 31, 32, 247, 34, 0, 0, 0, - 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, + 0, 0, 0, 51, 0, 0, 0, 0, 52, 53, + 54, 0, 0, 0, 0, 55, 0, 0, 0, 56, + 57, 58, 59, 60, 0, 0, 61, 62, 0, 63, + 64, 65, 0, 66, 67, 0, 0, 0, 68, 69, + 0, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 0, 85, 86, 87, + 88, 89, 90, 184, 185, 186, 187, 188, 189, 0, + 0, 0, 190, 0, 0, 191, 192, 193, 194, 195, + 196, 633, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 197, 0, 0, 184, 185, 186, + 187, 188, 189, 0, 0, 0, 190, 0, 0, 191, + 192, 193, 194, 195, 196, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 197, 0, + 198, 199, 0, 200, 0, 0, 0, 201, 202, 0, + 203, 0, 204, 205, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 206, 0, 0, 0, 207, 0, + 0, 0, 208, 209, 198, 199, 210, 200, 0, 0, + 0, 201, 202, 0, 203, 0, 204, 205, 0, 0, + 0, 0, 211, 0, 0, 0, 0, 0, 206, 0, + 0, 0, 207, 0, 0, 0, 208, 209, 0, 0, + 210, 0, 0, 0, 0, 184, 185, 186, 187, 188, + 189, 0, 0, 0, 190, 0, 211, 191, 192, 193, + 194, 195, 196, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 36, 37, 0, 38, 39, 40, 41, 0, 42, - 43, 44, 45, 46, 47, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, - 0, 0, 51, 52, 53, 0, 0, 0, 0, 54, - 0, 0, 0, 55, 56, 57, 58, 59, 0, 0, - 60, 61, 0, 62, 63, 64, 0, 65, 66, 0, - 0, 0, 67, 0, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 167, 168, 169, 170, - 171, 172, 0, 0, 0, 173, 0, 174, 175, 176, - 177, 178, 179, 180, 453, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 0, 0, 198, 199, 0, 200, 0, 0, 0, 201, 202, 0, 203, 0, 204, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 0, 0, 0, - 207, 0, 0, 0, 208, 209, 0, 210, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 211, 167, 168, 169, 170, 171, 172, 454, 0, 0, - 173, 0, 174, 175, 176, 177, 178, 179, 180, 601, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 181, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, - 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, - 193, 194, 195, 196, 197, 0, 0, 198, 199, 0, - 200, 0, 0, 0, 201, 202, 0, 203, 0, 204, - 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 206, 0, 0, 0, 207, 0, 0, 0, 208, - 209, 0, 210, 0, 0, 167, 168, 169, 170, 171, - 172, 0, 0, 0, 173, 211, 174, 175, 176, 177, - 178, 179, 180, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 181, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 0, - 0, 198, 199, 0, 200, 0, 0, 0, 201, 202, - 0, 203, 0, 204, 205, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 206, 0, 0, 0, 207, - 0, 0, 0, 208, 209, 0, 210, 0, 0, 167, - 168, 169, 170, 171, 172, 0, 0, 0, 173, 211, - 174, 175, 176, 177, 178, 179, 180, 0, 0, 0, + 207, 0, 0, 0, 208, 209, 0, 0, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 0, 0, 198, 199, 0, 200, 0, - 0, 0, 201, 202, 0, 203, 0, 204, 205, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, - 0, 0, 0, 207, 0, 0, 0, 208, 209, 0, - 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 211 + 0, 0, 0, 0, 211 }; static const yytype_int16 yycheck[] = { - 10, 56, 57, 123, 154, 0, 5, 394, 26, 64, - 160, 21, 22, 376, 377, 378, 379, 463, 464, 465, - 26, 495, 39, 48, 39, 39, 39, 39, 391, 392, - 39, 39, 31, 336, 397, 83, 39, 39, 33, 39, - 79, 39, 83, 47, 83, 113, 83, 83, 351, 83, - 83, 48, 26, 356, 19, 20, 48, 96, 97, 96, - 97, 83, 72, 90, 115, 126, 93, 118, 131, 131, - 120, 56, 42, 43, 5, 39, 40, 41, 83, 83, - 64, 65, 145, 72, 94, 115, 169, 82, 150, 83, - 117, 115, 62, 126, 98, 90, 70, 62, 93, 115, - 31, 131, 548, 171, 126, 94, 78, 131, 115, 131, - 115, 115, 119, 83, 165, 131, 503, 504, 168, 83, - 131, 115, 117, 171, 83, 488, 137, 138, 167, 170, - 167, 167, 495, 167, 497, 498, 499, 500, 501, 502, - 83, 166, 505, 83, 447, 115, 620, 172, 44, 45, - 46, 168, 170, 168, 168, 168, 168, 115, 98, 168, - 168, 607, 608, 167, 170, 168, 168, 115, 168, 166, - 168, 170, 171, 170, 166, 115, 83, 131, 126, 124, - 87, 83, 83, 131, 334, 90, 131, 99, 93, 5, - 6, 7, 8, 9, 10, 96, 97, 13, 90, 111, - 112, 93, 114, 258, 259, 260, 491, 492, 493, 494, - 265, 66, 117, 68, 269, 31, 32, 33, 34, 35, - 36, 82, 507, 508, 509, 117, 511, 90, 141, 514, - 93, 286, 5, 6, 7, 8, 9, 10, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 169, 171, - 111, 172, 83, 175, 117, 54, 55, 620, 31, 32, - 33, 34, 35, 36, 129, 652, 131, 83, 99, 100, - 101, 102, 115, 104, 105, 106, 107, 115, 90, 564, - 111, 93, 168, 646, 647, 171, 296, 674, 24, 25, - 26, 27, 28, 168, 124, 125, 171, 127, 148, 149, - 150, 57, 122, 59, 124, 117, 669, 670, 117, 118, - 69, 109, 110, 130, 131, 12, 170, 171, 6, 115, - 83, 48, 0, 38, 170, 67, 50, 176, 448, 169, - 83, 83, 168, 170, 344, 26, 456, 172, 458, 334, - 62, 30, 170, 170, 170, 170, 83, 37, 169, 83, - 169, 169, 83, 115, 364, 169, 169, 115, 413, 169, - 415, 416, 169, 418, 169, 169, 1, 83, 115, 424, + 10, 0, 57, 58, 406, 139, 387, 388, 389, 390, + 65, 21, 22, 73, 301, 5, 5, 6, 7, 8, + 9, 10, 403, 404, 13, 171, 407, 27, 41, 410, + 27, 84, 487, 488, 489, 34, 41, 41, 41, 517, + 41, 50, 50, 33, 33, 34, 35, 36, 37, 38, + 41, 49, 44, 45, 123, 84, 41, 116, 41, 41, + 41, 41, 41, 50, 345, 75, 19, 129, 84, 19, + 84, 21, 64, 84, 118, 5, 27, 84, 118, 360, + 134, 121, 84, 97, 98, 129, 84, 41, 42, 43, + 134, 84, 84, 118, 93, 84, 106, 29, 134, 153, + 5, 99, 101, 33, 140, 141, 105, 56, 57, 134, + 84, 118, 181, 129, 64, 68, 80, 70, 134, 134, + 118, 72, 577, 525, 526, 184, 118, 129, 33, 510, + 84, 184, 172, 148, 133, 59, 517, 61, 519, 520, + 521, 522, 523, 524, 118, 29, 527, 528, 53, 54, + 55, 56, 57, 58, 183, 182, 118, 62, 185, 118, + 65, 66, 67, 68, 69, 70, 180, 58, 181, 180, + 179, 179, 134, 651, 183, 134, 181, 181, 181, 84, + 181, 127, 180, 183, 639, 640, 183, 180, 134, 470, + 181, 180, 179, 183, 184, 482, 181, 343, 181, 181, + 181, 181, 181, 132, 84, 134, 261, 262, 263, 219, + 118, 182, 222, 268, 122, 120, 121, 272, 123, 99, + 84, 84, 127, 128, 88, 130, 184, 132, 133, 101, + 188, 84, 101, 105, 289, 138, 105, 140, 118, 144, + 100, 84, 101, 148, 97, 98, 105, 152, 153, 120, + 121, 156, 101, 113, 114, 115, 105, 117, 134, 53, + 54, 55, 56, 57, 58, 101, 84, 172, 62, 105, + 651, 65, 66, 67, 68, 69, 70, 71, 25, 26, + 27, 28, 29, 685, 66, 67, 513, 514, 515, 516, + 84, 181, 181, 303, 184, 184, 84, 678, 679, 151, + 152, 153, 362, 530, 531, 532, 708, 534, 535, 111, + 112, 538, 100, 101, 102, 103, 144, 105, 106, 107, + 108, 109, 703, 704, 27, 113, 120, 121, 118, 123, + 46, 47, 48, 127, 128, 118, 130, 471, 132, 133, + 133, 134, 118, 353, 343, 479, 27, 481, 127, 128, + 144, 130, 183, 184, 148, 27, 71, 27, 152, 153, + 12, 6, 156, 373, 591, 5, 6, 7, 8, 9, + 10, 426, 118, 428, 429, 84, 431, 50, 172, 0, + 180, 40, 437, 83, 183, 69, 52, 20, 189, 84, + 182, 185, 84, 33, 34, 35, 36, 37, 38, 183, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 181, 185, 113, 64, 27, 31, 183, 183, 1, + 183, 183, 39, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 84, 182, 182, + 22, 23, 24, 25, 26, 182, 182, 29, 30, 182, + 32, 33, 34, 35, 36, 37, 38, 182, 40, 182, + 182, 182, 182, 118, 84, 179, 476, 477, 84, 118, + 84, 53, 54, 55, 56, 57, 84, 84, 84, 118, + 134, 118, 181, 65, 84, 156, 84, 84, 134, 84, + 84, 84, 547, 84, 118, 118, 118, 50, 84, 81, + 82, 84, 84, 85, 86, 87, 181, 89, 90, 91, + 92, 93, 94, 95, 96, 118, 27, 27, 27, 182, + 182, 140, 182, 84, 182, 182, 118, 84, 84, 182, + 60, 182, 122, 62, 182, 84, 72, 119, 182, 182, + 182, 182, 124, 125, 126, 118, 182, 182, 182, 131, + 182, 181, 84, 135, 136, 137, 138, 139, 568, 27, + 142, 143, 27, 145, 146, 147, 184, 149, 150, 182, + 180, 182, 154, 155, 584, 157, 158, 159, 160, 161, + 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, + 84, 173, 174, 175, 176, 177, 178, 179, 182, 84, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 166, 83, 21, 22, 23, 24, - 25, 83, 131, 28, 29, 115, 31, 32, 33, 34, - 35, 36, 83, 38, 168, 115, 83, 152, 83, 83, - 115, 115, 115, 26, 48, 26, 51, 52, 53, 54, - 55, 26, 115, 137, 83, 169, 169, 83, 63, 169, - 83, 169, 167, 58, 60, 119, 169, 169, 83, 169, - 169, 169, 168, 453, 454, 80, 81, 115, 83, 84, - 85, 86, 169, 88, 89, 90, 91, 92, 93, 94, - 95, 169, 169, 169, 70, 83, 83, 169, 523, 169, - 169, 172, 61, 169, 83, 169, 171, 115, 115, 83, - 83, 116, 168, 168, 171, 152, 121, 122, 123, 171, - 173, 171, 83, 128, 173, 83, 83, 132, 133, 134, - 135, 136, 83, 169, 139, 140, 169, 142, 143, 144, - 167, 146, 147, 171, 169, 66, 151, 171, 153, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 540, 166, 171, 83, 83, 83, 169, 83, 170, 170, - 170, 170, 170, 83, 168, 555, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 174, 39, 21, 22, 23, 24, 25, 174, 39, 28, - 29, 171, 31, 32, 33, 34, 35, 36, 171, 38, - 82, 171, 33, 169, 169, 168, 154, 171, 543, 171, - 90, 601, 51, 52, 53, 54, 55, 553, 118, 651, - 672, 362, 582, 519, 63, 277, 228, 90, 231, 412, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 80, 81, -1, 83, 84, 85, 86, 347, 88, - 89, 90, 91, 92, 93, 94, 95, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 116, -1, -1, - -1, -1, 121, 122, 123, 5, -1, -1, -1, 128, - -1, -1, -1, 132, 133, 134, 135, 136, -1, -1, - 139, 140, -1, 142, 143, 144, -1, 146, 147, -1, - -1, 31, 151, -1, 153, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, 164, -1, 166, -1, -1, - -1, 51, 52, 53, 54, 55, 56, -1, -1, -1, - 60, -1, 62, 63, 64, 65, 66, 67, 68, -1, + 15, 16, 17, 18, 185, 184, 184, 22, 23, 24, + 25, 26, 84, 633, 29, 30, 184, 32, 33, 34, + 35, 36, 37, 38, 84, 40, 186, 63, 186, 118, + 118, 181, 156, 84, 84, 84, 84, 84, 53, 54, + 55, 56, 57, 84, 182, 182, 84, 68, 184, 184, + 65, 182, 84, 182, 184, 183, 183, 183, 183, 84, + 183, 84, 84, 181, 41, 187, 81, 82, 183, 84, + 85, 86, 87, 187, 89, 90, 91, 92, 93, 94, + 95, 96, 184, 41, 184, 184, 182, 184, 182, 181, + 93, 184, 34, 184, 133, 171, 101, 75, 582, 571, + 371, 134, 684, 610, 119, 425, 280, 543, 706, 124, + 125, 126, 101, 230, -1, 356, 131, 233, -1, -1, + 135, 136, 137, 138, 139, -1, -1, 142, 143, -1, + 145, 146, 147, -1, 149, 150, -1, -1, -1, 154, + 155, -1, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, -1, 173, 174, + 175, 176, 177, 178, 179, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, + -1, -1, 22, 23, 24, 25, 26, -1, -1, 29, + 30, -1, 32, 33, 34, 35, 36, 37, 38, -1, + 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 53, 54, 55, 56, 57, -1, -1, + -1, -1, -1, -1, -1, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 83, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, -1, -1, 117, 118, -1, - 120, -1, -1, -1, 124, 125, -1, 127, -1, 129, - 130, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 141, -1, -1, -1, 145, -1, -1, -1, 149, - 150, -1, 152, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 165, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - -1, -1, 21, 22, 23, 24, 25, -1, -1, 28, - 29, -1, 31, 32, 33, 34, 35, 36, -1, 38, + -1, 81, 82, -1, 84, 85, 86, 87, -1, 89, + 90, 91, 92, 93, 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 51, 52, 53, 54, 55, -1, -1, -1, - -1, -1, -1, -1, 63, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 119, + -1, -1, -1, -1, 124, 125, 126, -1, -1, -1, + -1, 131, -1, -1, -1, 135, 136, 137, 138, 139, + -1, -1, 142, 143, -1, 145, 146, 147, -1, 149, + 150, -1, -1, -1, 154, 155, -1, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 171, -1, 173, 174, 175, 176, 177, 178, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, -1, -1, -1, 22, 23, 24, 25, + 26, -1, -1, 29, 30, -1, 32, 33, 34, 35, + 36, 37, 38, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 53, 54, 55, + 56, 57, -1, -1, -1, -1, -1, -1, -1, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 80, 81, -1, 83, 84, 85, 86, -1, 88, - 89, 90, 91, 92, 93, 94, 95, -1, -1, -1, + -1, -1, -1, -1, -1, 81, 82, -1, 84, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, 95, + 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 116, -1, -1, - -1, -1, 121, 122, 123, -1, -1, -1, -1, 128, - -1, -1, -1, 132, 133, 134, 135, 136, -1, -1, - 139, 140, -1, 142, 143, 144, -1, 146, 147, -1, - -1, -1, 151, -1, 153, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, 164, 51, 52, 53, 54, - 55, 56, -1, -1, -1, 60, -1, 62, 63, 64, - 65, 66, 67, 68, 69, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 83, -1, + -1, -1, -1, 119, -1, -1, -1, -1, 124, 125, + 126, -1, -1, -1, -1, 131, -1, -1, -1, 135, + 136, 137, 138, 139, -1, -1, 142, 143, -1, 145, + 146, 147, -1, 149, 150, -1, -1, -1, 154, 155, + -1, 157, 158, 159, 160, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 170, 171, -1, 173, 174, 175, + 176, 177, 178, 53, 54, 55, 56, 57, 58, -1, + -1, -1, 62, -1, -1, 65, 66, 67, 68, 69, + 70, 71, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 84, -1, -1, 53, 54, 55, + 56, 57, 58, -1, -1, -1, 62, -1, -1, 65, + 66, 67, 68, 69, 70, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 84, -1, + 120, 121, -1, 123, -1, -1, -1, 127, 128, -1, + 130, -1, 132, 133, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 144, -1, -1, -1, 148, -1, + -1, -1, 152, 153, 120, 121, 156, 123, -1, -1, + -1, 127, 128, -1, 130, -1, 132, 133, -1, -1, + -1, -1, 172, -1, -1, -1, -1, -1, 144, -1, + -1, -1, 148, -1, -1, -1, 152, 153, -1, -1, + 156, -1, -1, -1, -1, 53, 54, 55, 56, 57, + 58, -1, -1, -1, 62, -1, 172, 65, 66, 67, + 68, 69, 70, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 84, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - -1, -1, 117, 118, -1, 120, -1, -1, -1, 124, - 125, -1, 127, -1, 129, 130, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 141, -1, -1, -1, - 145, -1, -1, -1, 149, 150, -1, 152, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 165, 51, 52, 53, 54, 55, 56, 172, -1, -1, - 60, -1, 62, 63, 64, 65, 66, 67, 68, 69, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 83, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, -1, -1, 117, 118, -1, - 120, -1, -1, -1, 124, 125, -1, 127, -1, 129, - 130, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 141, -1, -1, -1, 145, -1, -1, -1, 149, - 150, -1, 152, -1, -1, 51, 52, 53, 54, 55, - 56, -1, -1, -1, 60, 165, 62, 63, 64, 65, - 66, 67, 68, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 83, -1, -1, + -1, -1, 120, 121, -1, 123, -1, -1, -1, 127, + 128, -1, 130, -1, 132, 133, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 144, -1, -1, -1, + 148, -1, -1, -1, 152, 153, -1, -1, 156, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, -1, - -1, 117, 118, -1, 120, -1, -1, -1, 124, 125, - -1, 127, -1, 129, 130, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 141, -1, -1, -1, 145, - -1, -1, -1, 149, 150, -1, 152, -1, -1, 51, - 52, 53, 54, 55, 56, -1, -1, -1, 60, 165, - 62, 63, 64, 65, 66, 67, 68, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 83, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, -1, -1, 117, 118, -1, 120, -1, - -1, -1, 124, 125, -1, 127, -1, 129, 130, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 141, - -1, -1, -1, 145, -1, -1, -1, 149, 150, -1, - 152, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 165 + -1, -1, -1, -1, 172 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -1798,74 +1825,77 @@ static const yytype_int16 yycheck[] = static const yytype_uint16 yystos[] = { 0, 1, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 21, 22, 23, 24, - 25, 28, 29, 31, 32, 33, 34, 35, 36, 38, - 51, 52, 53, 54, 55, 63, 80, 81, 83, 84, - 85, 86, 88, 89, 90, 91, 92, 93, 94, 95, - 116, 121, 122, 123, 128, 132, 133, 134, 135, 136, - 139, 140, 142, 143, 144, 146, 147, 151, 153, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 166, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 190, 191, 192, 193, 194, 197, 198, 199, 200, 201, - 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 223, 224, 225, 226, 227, 228, 232, 233, 246, - 247, 248, 249, 251, 252, 258, 259, 263, 265, 266, - 267, 269, 271, 272, 273, 274, 276, 277, 278, 279, - 280, 282, 283, 285, 286, 287, 288, 289, 290, 291, - 293, 297, 298, 299, 78, 126, 250, 66, 68, 292, - 79, 83, 96, 97, 167, 229, 230, 51, 52, 53, - 54, 55, 56, 60, 62, 63, 64, 65, 66, 67, - 68, 83, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 117, 118, - 120, 124, 125, 127, 129, 130, 141, 145, 149, 150, - 152, 165, 213, 303, 304, 19, 20, 62, 187, 304, - 304, 42, 43, 62, 83, 115, 253, 254, 255, 253, - 253, 253, 253, 253, 82, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 111, 234, 54, 181, 56, - 54, 55, 169, 83, 83, 117, 118, 264, 124, 125, - 127, 270, 124, 131, 268, 129, 131, 261, 115, 150, - 261, 261, 83, 126, 275, 131, 137, 138, 262, 83, - 141, 115, 119, 260, 115, 281, 145, 261, 115, 284, - 148, 149, 150, 26, 70, 213, 69, 12, 6, 115, - 83, 115, 118, 165, 48, 0, 180, 48, 166, 5, - 182, 188, 212, 223, 224, 225, 226, 227, 299, 182, - 223, 224, 225, 226, 227, 83, 213, 182, 223, 224, - 225, 226, 227, 232, 170, 196, 216, 217, 218, 182, - 219, 220, 301, 302, 304, 67, 257, 302, 219, 302, - 196, 216, 50, 176, 64, 65, 216, 169, 83, 83, - 83, 167, 168, 170, 172, 62, 26, 30, 170, 170, - 170, 170, 37, 254, 250, 83, 169, 169, 169, 169, - 83, 99, 100, 101, 102, 104, 105, 106, 107, 111, - 242, 169, 169, 169, 169, 109, 110, 169, 39, 40, - 41, 83, 235, 166, 57, 59, 294, 295, 296, 83, - 83, 115, 115, 115, 261, 115, 126, 261, 115, 261, - 83, 126, 131, 83, 130, 261, 83, 261, 83, 83, - 262, 115, 168, 261, 115, 83, 152, 304, 83, 83, - 115, 115, 115, 115, 48, 171, 182, 216, 26, 195, - 217, 137, 300, 69, 172, 304, 26, 300, 26, 83, - 98, 115, 231, 169, 169, 169, 83, 96, 97, 229, - 47, 83, 98, 115, 167, 214, 215, 304, 167, 189, - 115, 44, 45, 46, 256, 83, 83, 115, 169, 83, - 87, 245, 245, 245, 245, 169, 172, 169, 169, 169, - 169, 169, 169, 169, 169, 169, 241, 245, 245, 243, - 245, 243, 169, 169, 245, 83, 83, 58, 60, 168, - 260, 261, 261, 115, 261, 261, 83, 261, 120, 168, - 115, 70, 169, 169, 171, 171, 219, 83, 170, 304, - 304, 219, 170, 221, 219, 231, 231, 231, 169, 83, - 83, 83, 167, 168, 171, 172, 83, 168, 171, 171, - 83, 83, 171, 171, 244, 245, 241, 241, 241, 241, - 244, 83, 245, 245, 245, 245, 245, 245, 243, 243, - 245, 39, 168, 241, 241, 241, 241, 173, 173, 241, - 61, 296, 261, 115, 115, 168, 152, 83, 83, 115, - 83, 69, 304, 83, 222, 220, 231, 169, 169, 83, - 215, 304, 167, 171, 171, 241, 39, 39, 39, 39, - 169, 242, 39, 39, 39, 39, 99, 111, 112, 114, - 236, 237, 66, 238, 39, 83, 169, 171, 304, 168, - 171, 231, 231, 83, 39, 244, 170, 170, 170, 170, - 174, 168, 170, 174, 83, 83, 245, 245, 113, 171, - 83, 239, 240, 39, 236, 243, 39, 171, 171, 169, - 169, 171, 168, 171, 175, 245, 245, 239, 243, 171, - 171 + 13, 14, 15, 16, 17, 18, 22, 23, 24, 25, + 26, 29, 30, 32, 33, 34, 35, 36, 37, 38, + 40, 53, 54, 55, 56, 57, 65, 81, 82, 84, + 85, 86, 87, 89, 90, 91, 92, 93, 94, 95, + 96, 119, 124, 125, 126, 131, 135, 136, 137, 138, + 139, 142, 143, 145, 146, 147, 149, 150, 154, 155, + 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, + 167, 168, 169, 170, 171, 173, 174, 175, 176, 177, + 178, 179, 191, 192, 193, 194, 195, 196, 197, 198, + 199, 205, 206, 207, 208, 209, 210, 213, 214, 215, + 216, 217, 218, 221, 222, 223, 224, 225, 226, 227, + 228, 229, 230, 231, 232, 233, 234, 245, 246, 247, + 248, 249, 250, 254, 255, 268, 269, 270, 271, 273, + 274, 280, 281, 282, 286, 288, 289, 290, 292, 294, + 295, 296, 297, 299, 300, 301, 302, 303, 305, 306, + 308, 309, 310, 311, 312, 313, 314, 316, 320, 321, + 322, 80, 129, 272, 19, 68, 70, 315, 84, 97, + 98, 180, 251, 252, 53, 54, 55, 56, 57, 58, + 62, 65, 66, 67, 68, 69, 70, 84, 120, 121, + 123, 127, 128, 130, 132, 133, 144, 148, 152, 153, + 156, 172, 235, 326, 327, 19, 21, 64, 200, 29, + 327, 327, 29, 44, 45, 64, 84, 118, 275, 276, + 277, 275, 275, 275, 275, 275, 83, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 113, 256, + 56, 194, 58, 56, 57, 182, 84, 84, 120, 121, + 287, 127, 128, 130, 293, 127, 134, 291, 132, 134, + 284, 118, 153, 284, 284, 84, 129, 298, 134, 140, + 141, 285, 84, 144, 118, 122, 283, 118, 304, 148, + 284, 118, 307, 151, 152, 153, 27, 72, 27, 27, + 220, 220, 235, 71, 27, 27, 12, 6, 118, 84, + 118, 121, 172, 50, 0, 193, 50, 179, 5, 180, + 196, 201, 203, 204, 234, 245, 246, 247, 248, 249, + 322, 180, 202, 196, 245, 246, 247, 248, 249, 84, + 327, 195, 254, 183, 212, 238, 239, 240, 196, 241, + 242, 324, 325, 327, 69, 279, 325, 241, 325, 212, + 238, 52, 20, 189, 66, 67, 182, 84, 84, 84, + 180, 181, 183, 185, 64, 327, 27, 31, 327, 183, + 183, 183, 183, 39, 276, 272, 84, 182, 182, 182, + 182, 84, 100, 101, 102, 103, 105, 106, 107, 108, + 109, 113, 264, 182, 182, 182, 182, 182, 111, 112, + 182, 41, 42, 43, 84, 257, 179, 59, 61, 317, + 318, 319, 84, 84, 118, 118, 118, 284, 118, 129, + 284, 118, 284, 84, 129, 134, 84, 133, 284, 84, + 284, 84, 84, 285, 118, 181, 284, 118, 84, 156, + 84, 84, 134, 219, 219, 327, 84, 84, 84, 84, + 118, 118, 118, 118, 50, 84, 84, 181, 184, 196, + 238, 27, 211, 239, 140, 323, 71, 185, 327, 27, + 323, 27, 220, 84, 99, 118, 253, 182, 182, 182, + 84, 97, 98, 251, 49, 84, 99, 118, 180, 236, + 237, 327, 118, 46, 47, 48, 278, 84, 84, 118, + 182, 84, 88, 267, 267, 267, 267, 182, 185, 182, + 182, 182, 182, 182, 182, 182, 182, 182, 182, 263, + 267, 267, 265, 267, 265, 267, 182, 182, 267, 84, + 84, 60, 62, 181, 283, 284, 284, 118, 284, 284, + 84, 284, 123, 181, 118, 72, 182, 84, 27, 27, + 182, 180, 184, 184, 241, 84, 183, 327, 327, 241, + 183, 243, 241, 219, 253, 253, 253, 182, 84, 84, + 84, 180, 181, 184, 185, 184, 184, 84, 84, 184, + 184, 266, 267, 263, 263, 263, 263, 266, 84, 267, + 267, 267, 267, 267, 267, 265, 265, 267, 267, 41, + 181, 263, 263, 263, 263, 263, 186, 186, 263, 63, + 319, 284, 118, 118, 181, 156, 84, 84, 84, 84, + 118, 84, 84, 71, 327, 84, 244, 242, 253, 182, + 182, 84, 237, 327, 184, 184, 263, 41, 41, 41, + 41, 182, 264, 41, 41, 41, 41, 41, 100, 113, + 114, 115, 117, 258, 259, 68, 260, 41, 84, 182, + 184, 327, 181, 184, 253, 253, 41, 266, 183, 183, + 183, 183, 183, 187, 181, 183, 187, 84, 84, 267, + 267, 116, 184, 184, 84, 261, 262, 41, 258, 265, + 41, 184, 184, 182, 182, 184, 181, 184, 188, 267, + 267, 261, 265, 184, 184 }; #define yyerrok (yyerrstatus = 0) @@ -2756,16 +2786,6 @@ yyreduce: { handle_stmt_end(result); ;} break; - case 12: - - {;} - break; - - case 13: - - {;} - break; - case 14: {;} @@ -2878,110 +2898,130 @@ yyreduce: case 36: + {;} + break; + + case 37: + + {;} + break; + + case 38: + { result->cur_stmt_type_ = OBPROXY_T_OTHERS; ;} break; - case 52: + case 48: { result->cur_stmt_type_ = OBPROXY_T_CREATE; ;} break; - case 53: + case 49: { result->cur_stmt_type_ = OBPROXY_T_DROP; ;} break; - case 54: + case 50: { result->cur_stmt_type_ = OBPROXY_T_ALTER; ;} break; - case 55: + case 51: { result->cur_stmt_type_ = OBPROXY_T_TRUNCATE; ;} break; - case 56: + case 52: { result->cur_stmt_type_ = OBPROXY_T_RENAME; ;} break; - case 58: + case 54: { result->sub_stmt_type_ = OBPROXY_T_SUB_CREATE_TABLE; ;} break; - case 59: + case 55: { result->sub_stmt_type_ = OBPROXY_T_SUB_CREATE_INDEX; ;} break; - case 60: + case 56: { result->sub_stmt_type_ = OBPROXY_T_SUB_CREATE_INDEX; ;} break; - case 61: + case 57: {;} break; - case 62: + case 58: {;} break; - case 63: + case 59: {;} break; - case 64: + case 60: {;} break; - case 65: + case 61: {;} break; - case 66: + case 62: {;} break; - case 67: + case 63: {;} break; - case 68: + case 64: {;} break; - case 69: + case 65: { - ObProxyTextPsExecuteParseNode *node = NULL; - malloc_execute_parse_node(node); - node->str_value_ = (yyvsp[(2) - (2)].str); - add_text_ps_execute_node(result->text_ps_execute_parse_info_, node); - ;} + ObProxyTextPsParseNode *node = NULL; + malloc_parse_node(node); + node->str_value_ = (yyvsp[(2) - (2)].str); + add_text_ps_node(result->text_ps_parse_info_, node); + ;} break; - case 70: + case 66: { - ObProxyTextPsExecuteParseNode *node = NULL; - malloc_execute_parse_node(node); - node->str_value_ = (yyvsp[(4) - (4)].str); - add_text_ps_execute_node(result->text_ps_execute_parse_info_, node); - ;} + ObProxyTextPsParseNode *node = NULL; + malloc_parse_node(node); + node->str_value_ = (yyvsp[(4) - (4)].str); + add_text_ps_node(result->text_ps_parse_info_, node); + ;} break; - case 71: + case 67: + + { + ObProxyTextPsParseNode *node = NULL; + malloc_parse_node(node); + node->str_value_ = (yyvsp[(2) - (2)].str); + add_text_ps_node(result->text_ps_parse_info_, node); + ;} + break; + + case 70: { result->text_ps_inner_stmt_type_ = OBPROXY_T_TEXT_PS_PREPARE; @@ -2989,98 +3029,115 @@ yyreduce: ;} break; + case 71: + + { + result->cur_stmt_type_ = OBPROXY_T_TEXT_PS_EXECUTE; + result->text_ps_name_ = (yyvsp[(2) - (2)].str); + ;} + break; + case 72: { - ;} + result->cur_stmt_type_ = OBPROXY_T_TEXT_PS_EXECUTE; + result->text_ps_name_ = (yyvsp[(2) - (3)].str); + ;} break; case 73: { - result->cur_stmt_type_ = OBPROXY_T_TEXT_PS_EXECUTE; - result->text_ps_name_ = (yyvsp[(2) - (2)].str); ;} break; case 74: { - result->cur_stmt_type_ = OBPROXY_T_TEXT_PS_EXECUTE; - result->text_ps_name_ = (yyvsp[(2) - (4)].str); ;} break; case 75: - { result->cur_stmt_type_ = OBPROXY_T_GRANT; ;} + { + result->cur_stmt_type_ = OBPROXY_T_TEXT_PS_DROP; + result->text_ps_name_ = (yyvsp[(3) - (3)].str); + ;} break; case 76: - { result->cur_stmt_type_ = OBPROXY_T_REVOKE; ;} + { + result->cur_stmt_type_ = OBPROXY_T_TEXT_PS_DROP; + result->text_ps_name_ = (yyvsp[(3) - (3)].str); + ;} break; case 77: - { result->cur_stmt_type_ = OBPROXY_T_ANALYZE; ;} + { result->cur_stmt_type_ = OBPROXY_T_GRANT; ;} break; case 78: - { result->cur_stmt_type_ = OBPROXY_T_PURGE; ;} + { result->cur_stmt_type_ = OBPROXY_T_REVOKE; ;} break; case 79: - { result->cur_stmt_type_ = OBPROXY_T_FLASHBACK; ;} + { result->cur_stmt_type_ = OBPROXY_T_ANALYZE; ;} break; case 80: - { result->cur_stmt_type_ = OBPROXY_T_COMMENT; ;} + { result->cur_stmt_type_ = OBPROXY_T_PURGE; ;} break; case 81: - { result->cur_stmt_type_ = OBPROXY_T_AUDIT; ;} + { result->cur_stmt_type_ = OBPROXY_T_FLASHBACK; ;} break; case 82: + { result->cur_stmt_type_ = OBPROXY_T_COMMENT; ;} + break; + + case 83: + + { result->cur_stmt_type_ = OBPROXY_T_AUDIT; ;} + break; + + case 84: + { result->cur_stmt_type_ = OBPROXY_T_NOAUDIT; ;} break; - case 85: + case 87: {;} break; - case 86: + case 88: {;} break; - case 87: + case 89: {;} break; - case 92: + case 94: { result->cur_stmt_type_ = OBPROXY_T_SELECT_TX_RO; ;} break; - case 96: + case 98: { result->col_name_ = (yyvsp[(3) - (3)].str); ;} break; - case 97: - - { result->cur_stmt_type_ = OBPROXY_T_SET_AC_0; ;} - break; - case 99: {;} @@ -3133,63 +3190,167 @@ yyreduce: case 109: - { result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TABLES; ;} + {;} break; case 110: - { result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_CREATE_TABLE; ;} + {;} break; case 111: + {;} + break; + + case 112: + + {;} + break; + + case 113: + + { result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_CREATE_TABLE; ;} + break; + + case 114: + { + result->table_info_.table_name_ = (yyvsp[(2) - (2)].str); result->cur_stmt_type_ = OBPROXY_T_DESC; result->sub_stmt_type_ = OBPROXY_T_SUB_DESC_TABLE; ;} break; - case 112: + case 115: + + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_COLUMNS; + result->table_info_.table_name_ = (yyvsp[(3) - (3)].str); + ;} + break; + + case 116: + + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_COLUMNS; + result->table_info_.table_name_ = (yyvsp[(3) - (5)].str); + result->table_info_.database_name_ = (yyvsp[(5) - (5)].str); + ;} + break; + + case 117: + + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_INDEX; + result->table_info_.table_name_ = (yyvsp[(3) - (3)].str); + ;} + break; + + case 118: + + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_INDEX; + result->table_info_.table_name_ = (yyvsp[(3) - (5)].str); + result->table_info_.database_name_ = (yyvsp[(5) - (5)].str); + ;} + break; + + case 119: + + {;} + break; + + case 120: + + { result->table_info_.table_name_ = (yyvsp[(2) - (2)].str); ;} + break; + + case 121: + + {;} + break; + + case 122: + + { result->table_info_.database_name_ = (yyvsp[(2) - (2)].str); ;} + break; + + case 123: + + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TABLES; + ;} + break; + + case 124: + + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_FULL_TABLES; + ;} + break; + + case 125: + + { + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TABLE_STATUS; + ;} + break; + + case 126: { result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_DB_VERSION; ;} break; - case 113: + case 127: - { result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TOPOLOGY; ;} + { result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_ELASTIC_ID; ;} break; - case 114: + case 128: { SET_ICMD_ONE_STRING((yyvsp[(3) - (3)].str)); - result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TOPOLOGY; + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_ELASTIC_ID; ;} break; - case 115: + case 129: { SET_ICMD_SECOND_STRING((yyvsp[(5) - (5)].str)); - result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TOPOLOGY; + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_ELASTIC_ID; ;} break; - case 116: + case 130: { SET_ICMD_ONE_STRING((yyvsp[(3) - (7)].str)); SET_ICMD_SECOND_STRING((yyvsp[(7) - (7)].str)); + result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_ELASTIC_ID; + ;} + break; + + case 131: + + { result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TOPOLOGY; ;} + break; + + case 132: + + { + result->table_info_.table_name_ = (yyvsp[(3) - (3)].str); result->sub_stmt_type_ = OBPROXY_T_SUB_SHOW_TOPOLOGY; ;} break; - case 117: + case 133: { result->cur_stmt_type_ = OBPROXY_T_SELECT_ROUTE_ADDR; ;} break; - case 118: + case 134: { result->cur_stmt_type_ = OBPROXY_T_SET_ROUTE_ADDR; @@ -3197,44 +3358,44 @@ yyreduce: ;} break; - case 119: + case 135: {;} break; - case 120: + case 136: {;} break; - case 121: + case 137: {;} break; - case 122: + case 138: {;} break; - case 123: + case 139: {;} break; - case 124: + case 140: {;} break; - case 126: + case 142: { result->table_info_.table_name_ = (yyvsp[(1) - (1)].str); ;} break; - case 127: + case 143: { result->table_info_.package_name_ = (yyvsp[(1) - (3)].str); @@ -3242,7 +3403,7 @@ yyreduce: ;} break; - case 128: + case 144: { result->table_info_.database_name_ = (yyvsp[(1) - (5)].str); @@ -3251,14 +3412,14 @@ yyreduce: ;} break; - case 129: + case 145: { result->call_parse_info_.node_count_ = 0; ;} break; - case 130: + case 146: { result->call_parse_info_.node_count_ = 0; @@ -3266,14 +3427,14 @@ yyreduce: ;} break; - case 131: + case 147: { add_call_node(result->call_parse_info_, (yyvsp[(3) - (3)].node)); ;} break; - case 132: + case 148: { malloc_call_node((yyval.node), CALL_TOKEN_STR_VAL); @@ -3281,7 +3442,7 @@ yyreduce: ;} break; - case 133: + case 149: { malloc_call_node((yyval.node), CALL_TOKEN_INT_VAL); @@ -3289,7 +3450,7 @@ yyreduce: ;} break; - case 134: + case 150: { malloc_call_node((yyval.node), CALL_TOKEN_NUMBER_VAL); @@ -3297,7 +3458,7 @@ yyreduce: ;} break; - case 135: + case 151: { malloc_call_node((yyval.node), CALL_TOKEN_USER_VAR); @@ -3305,7 +3466,7 @@ yyreduce: ;} break; - case 136: + case 152: { malloc_call_node((yyval.node), CALL_TOKEN_SYS_VAR); @@ -3313,7 +3474,7 @@ yyreduce: ;} break; - case 137: + case 153: { result->placeholder_list_idx_++; @@ -3322,7 +3483,7 @@ yyreduce: ;} break; - case 151: + case 167: { handle_stmt_end(result); @@ -3330,7 +3491,7 @@ yyreduce: ;} break; - case 156: + case 172: { handle_stmt_end(result); @@ -3338,56 +3499,56 @@ yyreduce: ;} break; - case 160: + case 176: { add_set_var_node(result->set_parse_info_, (yyvsp[(4) - (4)].var_node), (yyvsp[(2) - (4)].str), SET_VAR_USER); ;} break; - case 161: + case 177: { add_set_var_node(result->set_parse_info_, (yyvsp[(6) - (6)].var_node), (yyvsp[(4) - (6)].str), SET_VAR_SYS); ;} break; - case 162: + case 178: { add_set_var_node(result->set_parse_info_, (yyvsp[(4) - (4)].var_node), (yyvsp[(2) - (4)].str), SET_VAR_SYS); ;} break; - case 163: + case 179: { add_set_var_node(result->set_parse_info_, (yyvsp[(5) - (5)].var_node), (yyvsp[(3) - (5)].str), SET_VAR_SYS); ;} break; - case 164: + case 180: { add_set_var_node(result->set_parse_info_, (yyvsp[(6) - (6)].var_node), (yyvsp[(4) - (6)].str), SET_VAR_SYS); ;} break; - case 165: + case 181: { add_set_var_node(result->set_parse_info_, (yyvsp[(4) - (4)].var_node), (yyvsp[(2) - (4)].str), SET_VAR_SYS); ;} break; - case 166: + case 182: { add_set_var_node(result->set_parse_info_, (yyvsp[(3) - (3)].var_node), (yyvsp[(1) - (3)].str), SET_VAR_SYS); ;} break; - case 167: + case 183: { malloc_set_var_node((yyval.var_node), SET_VALUE_TYPE_STR); @@ -3395,7 +3556,7 @@ yyreduce: ;} break; - case 168: + case 184: { malloc_set_var_node((yyval.var_node), SET_VALUE_TYPE_INT); @@ -3403,7 +3564,7 @@ yyreduce: ;} break; - case 169: + case 185: { malloc_set_var_node((yyval.var_node), SET_VALUE_TYPE_NUMBER); @@ -3411,42 +3572,42 @@ yyreduce: ;} break; - case 172: + case 188: {;} break; - case 173: + case 189: {;} break; - case 174: + case 190: { result->dbmesh_route_info_.tb_idx_str_ = (yyvsp[(4) - (6)].str); ;} break; - case 175: + case 191: { result->dbmesh_route_info_.table_name_str_ = (yyvsp[(4) - (6)].str); ;} break; - case 176: + case 192: { result->dbmesh_route_info_.group_idx_str_ = (yyvsp[(4) - (6)].str); ;} break; - case 177: + case 193: { result->dbmesh_route_info_.es_idx_str_ = (yyvsp[(4) - (6)].str); ;} break; - case 178: + case 194: { result->dbmesh_route_info_.testload_str_ = (yyvsp[(4) - (6)].str); ;} break; - case 179: + case 195: { malloc_shard_column_node((yyval.shard_node), (yyvsp[(2) - (7)].str), (yyvsp[(3) - (7)].str), DBMESH_TOKEN_STR_VAL); @@ -3455,52 +3616,57 @@ yyreduce: ;} break; - case 180: + case 196: { result->trace_id_ = (yyvsp[(4) - (6)].str); ;} break; - case 181: + case 197: { result->rpc_id_ = (yyvsp[(4) - (6)].str); ;} break; - case 182: + case 198: { result->dbmesh_route_info_.tnt_id_str_ = (yyvsp[(4) - (6)].str); ;} break; - case 183: + case 199: { result->dbmesh_route_info_.disaster_status_str_ = (yyvsp[(4) - (6)].str); ;} break; - case 184: + case 200: {;} break; - case 185: + case 201: {;} break; - case 186: + case 202: + + { result->target_db_server_ = (yyvsp[(4) - (6)].str); ;} + break; + + case 203: {;} break; - case 188: + case 205: { result->has_simple_route_info_ = true; result->simple_route_info_.table_name_ = (yyvsp[(2) - (2)].str); ;} break; - case 189: + case 206: { result->simple_route_info_.part_key_ = (yyvsp[(2) - (2)].str); ;} break; - case 193: + case 210: { result->dbp_route_info_.has_group_info_ = true; @@ -3508,7 +3674,7 @@ yyreduce: ;} break; - case 194: + case 211: { result->dbp_route_info_.has_group_info_ = true; @@ -3516,37 +3682,42 @@ yyreduce: ;} break; - case 195: + case 212: { result->dbp_route_info_.scan_all_ = true; ;} break; - case 196: + case 213: { result->dbp_route_info_.scan_all_ = true; ;} break; - case 197: + case 214: + + { result->dbp_route_info_.sticky_session_ = true; ;} + break; + + case 215: {result->dbp_route_info_.has_shard_key_ = true;;} break; - case 198: + case 216: { result->trace_id_ = (yyvsp[(3) - (4)].str); ;} break; - case 199: + case 217: { result->trace_id_ = (yyvsp[(3) - (6)].str); result->rpc_id_ = (yyvsp[(5) - (6)].str); ;} break; - case 200: + case 218: {;} break; - case 202: + case 220: { if (result->dbp_route_info_.shard_key_count_ < OBPROXY_MAX_DBP_SHARD_KEY_NUM) { @@ -3557,52 +3728,57 @@ yyreduce: ;} break; - case 205: + case 223: { result->dbmesh_route_info_.group_idx_str_ = (yyvsp[(3) - (3)].str); ;} break; - case 206: + case 224: { result->dbmesh_route_info_.tb_idx_str_ = (yyvsp[(3) - (3)].str); ;} break; - case 207: + case 225: { result->dbmesh_route_info_.table_name_str_ = (yyvsp[(3) - (3)].str); ;} break; - case 208: + case 226: { result->dbmesh_route_info_.es_idx_str_ = (yyvsp[(3) - (3)].str); ;} break; - case 209: + case 227: { result->dbmesh_route_info_.testload_str_ = (yyvsp[(3) - (3)].str); ;} break; - case 210: + case 228: { result->trace_id_ = (yyvsp[(3) - (3)].str); ;} break; - case 211: + case 229: { result->rpc_id_ = (yyvsp[(3) - (3)].str); ;} break; - case 212: + case 230: { result->dbmesh_route_info_.tnt_id_str_ = (yyvsp[(3) - (3)].str); ;} break; - case 213: + case 231: { result->dbmesh_route_info_.disaster_status_str_ = (yyvsp[(3) - (3)].str); ;} break; - case 214: + case 232: + + { result->target_db_server_ = (yyvsp[(3) - (3)].str); ;} + break; + + case 233: { malloc_shard_column_node((yyval.shard_node), (yyvsp[(1) - (5)].str), (yyvsp[(3) - (5)].str), DBMESH_TOKEN_STR_VAL); @@ -3611,32 +3787,32 @@ yyreduce: ;} break; - case 215: + case 234: {;} break; - case 216: + case 235: { (yyval.str).str_ = NULL; (yyval.str).str_len_ = 0; ;} break; - case 218: + case 237: { (yyval.str).str_ = NULL; (yyval.str).str_len_ = 0; ;} break; - case 240: + case 259: { result->query_timeout_ = (yyvsp[(3) - (4)].num); ;} break; - case 241: + case 260: {;} break; - case 243: + case 262: { add_hint_index(result->dbmesh_route_info_, (yyvsp[(3) - (5)].str)); @@ -3644,75 +3820,105 @@ yyreduce: ;} break; - case 244: + case 263: {;} break; - case 245: + case 264: {;} break; - case 246: + case 265: {;} break; - case 247: + case 266: {;} break; - case 248: + case 267: {;} break; - case 249: + case 268: { SET_READ_CONSISTENCY(OBPROXY_READ_CONSISTENCY_WEAK); ;} break; - case 250: + case 269: { SET_READ_CONSISTENCY(OBPROXY_READ_CONSISTENCY_STRONG); ;} break; - case 251: + case 270: { SET_READ_CONSISTENCY(OBPROXY_READ_CONSISTENCY_FROZEN); ;} break; - case 254: + case 273: { result->cur_stmt_type_ = OBPROXY_T_SHOW_WARNINGS; ;} break; - case 255: + case 274: { result->cur_stmt_type_ = OBPROXY_T_SHOW_ERRORS; ;} break; - case 256: + case 275: { result->cur_stmt_type_ = OBPROXY_T_SHOW_TRACE; ;} break; - case 280: + case 299: + + {;} + break; + + case 300: + + {;} + break; + + case 301: + + {;} + break; + + case 302: + + {;} + break; + + case 303: + + {;} + break; + + case 304: + + {;} + break; + + case 305: { ;} break; - case 281: + case 306: { result->cmd_info_.integer_[2] = (yyvsp[(2) - (2)].num);/*row*/ ;} break; - case 282: + case 307: { result->cmd_info_.integer_[1] = (yyvsp[(2) - (4)].num);/*offset*/ @@ -3720,7 +3926,7 @@ yyreduce: ;} break; - case 283: + case 308: { result->cmd_info_.integer_[1] = (yyvsp[(4) - (4)].num);/*offset*/ @@ -3728,342 +3934,342 @@ yyreduce: ;} break; - case 284: + case 309: {;} break; - case 285: + case 310: { result->cmd_info_.string_[0] = (yyvsp[(2) - (2)].str);;} break; - case 286: + case 311: {;} break; - case 287: + case 312: { result->cmd_info_.string_[1] = (yyvsp[(2) - (2)].str);;} break; - case 289: + case 314: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_NET_THREAD); ;} break; - case 290: + case 315: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_NET_CONNECTION); ;} break; - case 291: + case 316: { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_NET_CONNECTION, (yyvsp[(2) - (3)].num)); ;} break; - case 292: + case 317: {;} break; - case 293: + case 318: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_CONFIG_DIFF); ;} break; - case 294: + case 319: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_CONFIG_DIFF_USER); ;} break; - case 295: + case 320: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_SESSION_LIST); ;} break; - case 297: + case 322: {SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_GLOBAL_SESSION_LIST);;} break; - case 298: + case 323: {SET_ICMD_SUB_AND_ONE_STRING(OBPROXY_T_SUB_GLOBAL_SESSION_LIST_INFO, (yyvsp[(2) - (2)].str));;} break; - case 299: + case 324: {SET_ICMD_SUB_AND_ONE_STRING(OBPROXY_T_SUB_GLOBAL_SESSION_LIST_LIKE, (yyvsp[(3) - (3)].str));;} break; - case 300: + case 325: {SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_GLOBAL_SESSION_LIST_INFO_ALL);;} break; - case 301: + case 326: {result->cmd_info_.string_[0] = (yyvsp[(2) - (2)].str);;} break; - case 303: + case 328: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_SESSION_LIST_INTERNAL); ;} break; - case 304: + case 329: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_SESSION_ATTRIBUTE); ;} break; - case 305: + case 330: { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_SESSION_ATTRIBUTE, (yyvsp[(2) - (3)].num)); ;} break; - case 306: + case 331: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_SESSION_STAT); ;} break; - case 307: + case 332: { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_SESSION_STAT, (yyvsp[(2) - (3)].num)); ;} break; - case 308: + case 333: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_SESSION_VARIABLES_LOCAL); ;} break; - case 309: + case 334: { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_SESSION_VARIABLES_LOCAL, (yyvsp[(2) - (3)].num)); ;} break; - case 310: + case 335: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_SESSION_VARIABLES_ALL); ;} break; - case 311: + case 336: { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_SESSION_VARIABLES_ALL, (yyvsp[(3) - (4)].num)); ;} break; - case 312: + case 337: {;} break; - case 313: + case 338: { SET_ICMD_ONE_ID((yyvsp[(2) - (2)].num)); ;} break; - case 314: + case 339: {;} break; - case 315: + case 340: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_INFO_IDC); ;} break; - case 316: + case 341: {;} break; - case 318: + case 343: {;} break; - case 319: + case 344: { SET_ICMD_ONE_STRING((yyvsp[(1) - (1)].str)); ;} break; - case 320: + case 345: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_CONGEST_ALL);;} break; - case 321: + case 346: { SET_ICMD_SUB_AND_ONE_STRING(OBPROXY_T_SUB_CONGEST_ALL, (yyvsp[(2) - (2)].str));;} break; - case 322: + case 347: {;} break; - case 323: + case 348: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_ROUTE_ROUTINE); ;} break; - case 324: + case 349: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_ROUTE_PARTITION); ;} break; - case 325: + case 350: {;} break; - case 326: + case 351: { SET_ICMD_ONE_STRING((yyvsp[(2) - (2)].str)); ;} break; - case 327: + case 352: {;} break; - case 328: + case 353: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_MEMORY_OBJPOOL); ;} break; - case 329: + case 354: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_SQLAUDIT_AUDIT_ID); ;} break; - case 330: + case 355: { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_SQLAUDIT_SM_ID, (yyvsp[(2) - (2)].num)); ;} break; - case 332: + case 357: {;} break; - case 333: + case 358: { SET_ICMD_SECOND_ID((yyvsp[(1) - (1)].num)); ;} break; - case 334: + case 359: { SET_ICMD_TWO_ID((yyvsp[(3) - (3)].num), (yyvsp[(1) - (3)].num)); ;} break; - case 335: + case 360: { SET_ICMD_TWO_ID((yyvsp[(3) - (5)].num), (yyvsp[(1) - (5)].num)); SET_ICMD_ONE_STRING((yyvsp[(5) - (5)].str)); ;} break; - case 336: + case 361: {;} break; - case 337: + case 362: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_STAT_REFRESH); ;} break; - case 339: + case 364: {;} break; - case 340: + case 365: { SET_ICMD_ONE_ID((yyvsp[(1) - (1)].num)); ;} break; - case 341: + case 366: { SET_ICMD_SUB_AND_TWO_ID(OBPROXY_T_SUB_TRACE_LIMIT, (yyvsp[(1) - (2)].num),(yyvsp[(2) - (2)].num)); ;} break; - case 342: + case 367: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_INFO_BINARY); ;} break; - case 343: + case 368: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_INFO_UPGRADE); ;} break; - case 344: + case 369: { SET_ICMD_SUB_TYPE(OBPROXY_T_SUB_INFO_IDC); ;} break; - case 345: + case 370: { SET_ICMD_ONE_STRING((yyvsp[(3) - (4)].str)); ;} break; - case 346: + case 371: { SET_ICMD_TWO_STRING((yyvsp[(3) - (5)].str), (yyvsp[(5) - (5)].str)); ;} break; - case 347: + case 372: { SET_ICMD_CONFIG_INT_VALUE((yyvsp[(3) - (5)].str), (yyvsp[(5) - (5)].num)); ;} break; - case 348: + case 373: { SET_ICMD_ONE_STRING((yyvsp[(3) - (3)].str)); ;} break; - case 349: + case 374: {;} break; - case 350: + case 375: { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_KILL_CS, (yyvsp[(2) - (2)].num)); ;} break; - case 351: + case 376: { SET_ICMD_SUB_AND_TWO_ID(OBPROXY_T_SUB_KILL_SS, (yyvsp[(2) - (3)].num), (yyvsp[(3) - (3)].num)); ;} break; - case 352: + case 377: {SET_ICMD_TYPE_STRING_INT_VALUE(OBPROXY_T_SUB_KILL_GLOBAL_SS_ID, (yyvsp[(2) - (3)].str),(yyvsp[(3) - (3)].num));;} break; - case 353: + case 378: {SET_ICMD_SUB_AND_ONE_STRING(OBPROXY_T_SUB_KILL_GLOBAL_SS_DBKEY, (yyvsp[(2) - (2)].str));;} break; - case 354: + case 379: { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_KILL_CONNECTION, (yyvsp[(2) - (2)].num)); ;} break; - case 355: + case 380: { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_KILL_CONNECTION, (yyvsp[(3) - (3)].num)); ;} break; - case 356: + case 381: { SET_ICMD_SUB_AND_ONE_ID(OBPROXY_T_SUB_KILL_QUERY, (yyvsp[(3) - (3)].num)); ;} break; - case 359: + case 384: { result->has_anonymous_block_ = false ; @@ -4071,22 +4277,22 @@ yyreduce: ;} break; - case 360: + case 385: { result->cur_stmt_type_ = OBPROXY_T_BEGIN; ;} break; - case 361: + case 386: { result->cur_stmt_type_ = OBPROXY_T_BEGIN; ;} break; - case 362: + case 387: { result->cur_stmt_type_ = OBPROXY_T_BEGIN; ;} break; - case 369: + case 394: { result->cur_stmt_type_ = OBPROXY_T_USE_DB; @@ -4094,27 +4300,27 @@ yyreduce: ;} break; - case 370: + case 395: { result->cur_stmt_type_ = OBPROXY_T_HELP; ;} break; - case 372: + case 397: {;} break; - case 373: + case 398: { result->part_name_ = (yyvsp[(2) - (2)].str); ;} break; - case 374: + case 399: { result->part_name_ = (yyvsp[(3) - (4)].str); ;} break; - case 375: + case 400: { handle_stmt_end(result); @@ -4122,14 +4328,14 @@ yyreduce: ;} break; - case 376: + case 401: { result->table_info_.table_name_ = (yyvsp[(1) - (1)].str); ;} break; - case 377: + case 402: { result->table_info_.database_name_ = (yyvsp[(1) - (3)].str); @@ -4137,7 +4343,7 @@ yyreduce: ;} break; - case 378: + case 403: { UPDATE_ALIAS_NAME((yyvsp[(2) - (2)].str)); @@ -4145,7 +4351,7 @@ yyreduce: ;} break; - case 379: + case 404: { UPDATE_ALIAS_NAME((yyvsp[(4) - (4)].str)); @@ -4154,7 +4360,7 @@ yyreduce: ;} break; - case 380: + case 405: { UPDATE_ALIAS_NAME((yyvsp[(3) - (3)].str)); @@ -4162,7 +4368,7 @@ yyreduce: ;} break; - case 381: + case 406: { UPDATE_ALIAS_NAME((yyvsp[(5) - (5)].str)); diff --git a/src/obproxy/opsql/parser/ob_proxy_parser_utf8_tab.h b/src/obproxy/opsql/parser/ob_proxy_parser_utf8_tab.h index 6740aaa8a50ee6e4ac795e51bf5d70cffd39e6c0..16705243e814c9556ba0fc11af0ab0cbc3d98dfa 100644 --- a/src/obproxy/opsql/parser/ob_proxy_parser_utf8_tab.h +++ b/src/obproxy/opsql/parser/ob_proxy_parser_utf8_tab.h @@ -73,152 +73,165 @@ extern int ob_proxy_parser_utf8_yydebug; TRUNCATE = 272, RENAME = 273, TABLE = 274, - UNIQUE = 275, - GRANT = 276, - REVOKE = 277, - ANALYZE = 278, - PURGE = 279, - COMMENT = 280, - FROM = 281, - DUAL = 282, - PREPARE = 283, - EXECUTE = 284, - USING = 285, - SELECT_HINT_BEGIN = 286, - UPDATE_HINT_BEGIN = 287, - DELETE_HINT_BEGIN = 288, - INSERT_HINT_BEGIN = 289, - REPLACE_HINT_BEGIN = 290, - MERGE_HINT_BEGIN = 291, - HINT_END = 292, - COMMENT_BEGIN = 293, - COMMENT_END = 294, - ROUTE_TABLE = 295, - ROUTE_PART_KEY = 296, - QUERY_TIMEOUT = 297, - READ_CONSISTENCY = 298, - WEAK = 299, - STRONG = 300, - FROZEN = 301, - PLACE_HOLDER = 302, - END_P = 303, - ERROR = 304, - WHEN = 305, - FLASHBACK = 306, - AUDIT = 307, - NOAUDIT = 308, - BEGI = 309, - START = 310, - TRANSACTION = 311, - READ = 312, - ONLY = 313, - WITH = 314, - CONSISTENT = 315, - SNAPSHOT = 316, - INDEX = 317, - XA = 318, - WARNINGS = 319, - ERRORS = 320, - TRACE = 321, - QUICK = 322, - COUNT = 323, - AS = 324, - WHERE = 325, - VALUES = 326, - ORDER = 327, - GROUP = 328, - HAVING = 329, - INTO = 330, - UNION = 331, - FOR = 332, - TX_READ_ONLY = 333, - AUTOCOMMIT_0 = 334, - SELECT_OBPROXY_ROUTE_ADDR = 335, - SET_OBPROXY_ROUTE_ADDR = 336, - NAME_OB_DOT = 337, - NAME_OB = 338, - EXPLAIN = 339, - DESC = 340, - DESCRIBE = 341, - NAME_STR = 342, - USE = 343, - HELP = 344, - SET_NAMES = 345, - SET_CHARSET = 346, - SET_PASSWORD = 347, - SET_DEFAULT = 348, - SET_OB_READ_CONSISTENCY = 349, - SET_TX_READ_ONLY = 350, - GLOBAL = 351, - SESSION = 352, - NUMBER_VAL = 353, - GROUP_ID = 354, - TABLE_ID = 355, - ELASTIC_ID = 356, - TESTLOAD = 357, - ODP_COMMENT = 358, - TNT_ID = 359, - DISASTER_STATUS = 360, - TRACE_ID = 361, - RPC_ID = 362, - DBP_COMMENT = 363, - ROUTE_TAG = 364, - SYS_TAG = 365, - TABLE_NAME = 366, - SCAN_ALL = 367, - PARALL = 368, - SHARD_KEY = 369, - INT_NUM = 370, - SHOW_PROXYNET = 371, - THREAD = 372, - CONNECTION = 373, - LIMIT = 374, - OFFSET = 375, - SHOW_PROCESSLIST = 376, - SHOW_PROXYSESSION = 377, - SHOW_GLOBALSESSION = 378, - ATTRIBUTE = 379, - VARIABLES = 380, - ALL = 381, - STAT = 382, - SHOW_PROXYCONFIG = 383, - DIFF = 384, - USER = 385, - LIKE = 386, - SHOW_PROXYSM = 387, - SHOW_PROXYCLUSTER = 388, - SHOW_PROXYRESOURCE = 389, - SHOW_PROXYCONGESTION = 390, - SHOW_PROXYROUTE = 391, - PARTITION = 392, - ROUTINE = 393, - SHOW_PROXYVIP = 394, - SHOW_PROXYMEMORY = 395, - OBJPOOL = 396, - SHOW_SQLAUDIT = 397, - SHOW_WARNLOG = 398, - SHOW_PROXYSTAT = 399, - REFRESH = 400, - SHOW_PROXYTRACE = 401, - SHOW_PROXYINFO = 402, - BINARY = 403, - UPGRADE = 404, - IDC = 405, - SHOW_TOPOLOGY = 406, - GROUP_NAME = 407, - SHOW_DB_VERSION = 408, - SHOW_DATABASES = 409, - SHOW_TABLES = 410, - SELECT_DATABASE = 411, - SHOW_CREATE_TABLE = 412, - SELECT_PROXY_VERSION = 413, - ALTER_PROXYCONFIG = 414, - ALTER_PROXYRESOURCE = 415, - PING_PROXY = 416, - KILL_PROXYSESSION = 417, - KILL_GLOBALSESSION = 418, - KILL = 419, - QUERY = 420 + STATUS = 275, + UNIQUE = 276, + GRANT = 277, + REVOKE = 278, + ANALYZE = 279, + PURGE = 280, + COMMENT = 281, + FROM = 282, + DUAL = 283, + PREPARE = 284, + EXECUTE = 285, + USING = 286, + DEALLOCATE = 287, + SELECT_HINT_BEGIN = 288, + UPDATE_HINT_BEGIN = 289, + DELETE_HINT_BEGIN = 290, + INSERT_HINT_BEGIN = 291, + REPLACE_HINT_BEGIN = 292, + MERGE_HINT_BEGIN = 293, + HINT_END = 294, + COMMENT_BEGIN = 295, + COMMENT_END = 296, + ROUTE_TABLE = 297, + ROUTE_PART_KEY = 298, + QUERY_TIMEOUT = 299, + READ_CONSISTENCY = 300, + WEAK = 301, + STRONG = 302, + FROZEN = 303, + PLACE_HOLDER = 304, + END_P = 305, + ERROR = 306, + WHEN = 307, + FLASHBACK = 308, + AUDIT = 309, + NOAUDIT = 310, + BEGI = 311, + START = 312, + TRANSACTION = 313, + READ = 314, + ONLY = 315, + WITH = 316, + CONSISTENT = 317, + SNAPSHOT = 318, + INDEX = 319, + XA = 320, + WARNINGS = 321, + ERRORS = 322, + TRACE = 323, + QUICK = 324, + COUNT = 325, + AS = 326, + WHERE = 327, + VALUES = 328, + ORDER = 329, + GROUP = 330, + HAVING = 331, + INTO = 332, + UNION = 333, + FOR = 334, + TX_READ_ONLY = 335, + SELECT_OBPROXY_ROUTE_ADDR = 336, + SET_OBPROXY_ROUTE_ADDR = 337, + NAME_OB_DOT = 338, + NAME_OB = 339, + EXPLAIN = 340, + DESC = 341, + DESCRIBE = 342, + NAME_STR = 343, + USE = 344, + HELP = 345, + SET_NAMES = 346, + SET_CHARSET = 347, + SET_PASSWORD = 348, + SET_DEFAULT = 349, + SET_OB_READ_CONSISTENCY = 350, + SET_TX_READ_ONLY = 351, + GLOBAL = 352, + SESSION = 353, + NUMBER_VAL = 354, + GROUP_ID = 355, + TABLE_ID = 356, + ELASTIC_ID = 357, + TESTLOAD = 358, + ODP_COMMENT = 359, + TNT_ID = 360, + DISASTER_STATUS = 361, + TRACE_ID = 362, + RPC_ID = 363, + TARGET_DB_SERVER = 364, + DBP_COMMENT = 365, + ROUTE_TAG = 366, + SYS_TAG = 367, + TABLE_NAME = 368, + SCAN_ALL = 369, + STICKY_SESSION = 370, + PARALL = 371, + SHARD_KEY = 372, + INT_NUM = 373, + SHOW_PROXYNET = 374, + THREAD = 375, + CONNECTION = 376, + LIMIT = 377, + OFFSET = 378, + SHOW_PROCESSLIST = 379, + SHOW_PROXYSESSION = 380, + SHOW_GLOBALSESSION = 381, + ATTRIBUTE = 382, + VARIABLES = 383, + ALL = 384, + STAT = 385, + SHOW_PROXYCONFIG = 386, + DIFF = 387, + USER = 388, + LIKE = 389, + SHOW_PROXYSM = 390, + SHOW_PROXYCLUSTER = 391, + SHOW_PROXYRESOURCE = 392, + SHOW_PROXYCONGESTION = 393, + SHOW_PROXYROUTE = 394, + PARTITION = 395, + ROUTINE = 396, + SHOW_PROXYVIP = 397, + SHOW_PROXYMEMORY = 398, + OBJPOOL = 399, + SHOW_SQLAUDIT = 400, + SHOW_WARNLOG = 401, + SHOW_PROXYSTAT = 402, + REFRESH = 403, + SHOW_PROXYTRACE = 404, + SHOW_PROXYINFO = 405, + BINARY = 406, + UPGRADE = 407, + IDC = 408, + SHOW_ELASTIC_ID = 409, + SHOW_TOPOLOGY = 410, + GROUP_NAME = 411, + SHOW_DB_VERSION = 412, + SHOW_DATABASES = 413, + SHOW_TABLES = 414, + SHOW_FULL_TABLES = 415, + SELECT_DATABASE = 416, + SHOW_CREATE_TABLE = 417, + SELECT_PROXY_VERSION = 418, + SHOW_COLUMNS = 419, + SHOW_INDEX = 420, + ALTER_PROXYCONFIG = 421, + ALTER_PROXYRESOURCE = 422, + PING_PROXY = 423, + KILL_PROXYSESSION = 424, + KILL_GLOBALSESSION = 425, + KILL = 426, + QUERY = 427, + SHOW_MASTER_STATUS = 428, + SHOW_BINARY_LOGS = 429, + SHOW_BINLOG_EVENTS = 430, + PURGE_BINARY_LOGS = 431, + RESET_MASTER = 432, + SHOW_BINLOG_SERVER_FOR_TENANT = 433 }; #endif diff --git a/src/obproxy/optimizer/ob_sharding_select_log_plan.cpp b/src/obproxy/optimizer/ob_sharding_select_log_plan.cpp index a4e80fa871d5514329d8804fcb9417de388f68d2..3c3a654be00bc5da3d1637a076eb2800fbd1321f 100644 --- a/src/obproxy/optimizer/ob_sharding_select_log_plan.cpp +++ b/src/obproxy/optimizer/ob_sharding_select_log_plan.cpp @@ -18,6 +18,7 @@ #include "engine/ob_proxy_operator_table_scan.h" #include "engine/ob_proxy_operator_projection.h" #include "obutils/ob_proxy_stmt.h" +#include "obproxy/proxy/mysqllib/ob_proxy_mysql_request.h" using namespace oceanbase::obproxy::engine; using namespace oceanbase::common; @@ -154,7 +155,7 @@ int ObShardingSelectLogPlan::do_handle_avg_expr(ObProxyExprAvg *agg_expr, T *&ex MEMCPY(buf, sql_string.ptr(), sql_string.length()); expr->set_expr_name(buf, sql_string.length()); if (OB_FAIL(handle_derived(expr))) { - LOG_WARN("fail to handle derived", K(ret)); + LOG_WARN("fail to handle derived", K(ret)); } } } @@ -489,8 +490,8 @@ int ObShardingSelectLogPlan::handle_derived(ObProxyExpr *expr, bool column_first ObProxyExprType expr_type = expr->get_expr_type(); if (OB_PROXY_EXPR_TYPE_COLUMN == expr_type || OB_PROXY_EXPR_TYPE_SHARDING_CONST == expr_type || expr->is_func_expr()) { - ObProxySelectStmt *select_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); - ObIArray &select_expr_array = select_stmt->select_exprs_; + ObProxyDMLStmt *dml_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); + ObIArray &select_expr_array = dml_stmt->select_exprs_; // Priority is given to finding derived columns, all derived columns have aliases and can be uniquely located if (bret && do_need_derived(derived_exprs_, expr, column_first, bret)) { @@ -571,8 +572,8 @@ int ObShardingSelectLogPlan::analyze_group_by_clause() { int ret = OB_SUCCESS; - ObProxySelectStmt *select_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); - ObIArray &group_by_exprs = select_stmt->group_by_exprs_; + ObProxyDMLStmt *dml_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); + ObIArray &group_by_exprs = dml_stmt->group_by_exprs_; for (int64_t i = 0; OB_SUCC(ret) && i < group_by_exprs.count(); i++) { ObProxyGroupItem *group_item = dynamic_cast(group_by_exprs.at(i)); @@ -595,8 +596,8 @@ int ObShardingSelectLogPlan::analyze_order_by_clause() { int ret = OB_SUCCESS; - ObProxySelectStmt *select_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); - ObIArray &order_by_exprs = select_stmt->order_by_exprs_; + ObProxyDMLStmt *dml_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); + ObIArray &order_by_exprs = dml_stmt->order_by_exprs_; for (int64_t i = 0; OB_SUCC(ret) && i < order_by_exprs.count(); i++) { ObProxyOrderItem *order_item = dynamic_cast(order_by_exprs.at(i)); @@ -618,8 +619,8 @@ int ObShardingSelectLogPlan::analyze_order_by_clause() int ObShardingSelectLogPlan::analyze_select_clause() { int ret = OB_SUCCESS; - ObProxySelectStmt *select_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); - ObIArray &select_expr_array = select_stmt->select_exprs_; + ObProxyDMLStmt *dml_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); + ObIArray &select_expr_array = dml_stmt->select_exprs_; for (int64_t i = 0; OB_SUCC(ret) && i < select_expr_array.count(); i++) { ObProxyExpr *select_expr = select_expr_array.at(i); @@ -635,9 +636,9 @@ int ObShardingSelectLogPlan::append_derived_order_by(bool &is_same_group_and_ord { int ret = OB_SUCCESS; - ObProxySelectStmt *select_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); - ObIArray &group_by_exprs = select_stmt->group_by_exprs_; - ObIArray &order_by_exprs = select_stmt->order_by_exprs_; + ObProxyDMLStmt *dml_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); + ObIArray &group_by_exprs = dml_stmt->group_by_exprs_; + ObIArray &order_by_exprs = dml_stmt->order_by_exprs_; if (!group_by_exprs.empty() && order_by_exprs.empty()) { is_same_group_and_order = true; @@ -679,28 +680,28 @@ int ObShardingSelectLogPlan::append_derived_order_by(bool &is_same_group_and_ord int ObShardingSelectLogPlan::rewrite_sql(ObSqlString &new_sql) { int ret = OB_SUCCESS; - ObProxySelectStmt *select_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); + ObProxyDMLStmt *dml_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); ObString sql = client_request_.get_sql(); if (derived_columns_.empty() && derived_orders_.empty() - && (select_stmt->limit_size_ == -1 || select_stmt->limit_size_ == 0)) { + && (dml_stmt->limit_size_ == -1 || dml_stmt->limit_size_ == 0)) { new_sql.append(sql); } else { const char *sql_ptr = sql.ptr(); int64_t sql_len = sql.length(); if (derived_columns_.empty() && derived_orders_.empty()) { - int64_t limit_position = select_stmt->limit_token_off_; + int64_t limit_position = dml_stmt->limit_token_off_; new_sql.append(sql_ptr, limit_position); new_sql.append("LIMIT "); - if (select_stmt->limit_size_ == 0) { - new_sql.append_fmt("%d", select_stmt->limit_size_); + if (dml_stmt->limit_size_ == 0) { + new_sql.append_fmt("%d", dml_stmt->limit_size_); } else { - new_sql.append_fmt("%d", select_stmt->limit_offset_ + select_stmt->limit_size_); + new_sql.append_fmt("%d", dml_stmt->limit_offset_ + dml_stmt->limit_size_); } } else { - int64_t from_position = select_stmt->get_from_token_off(); - int64_t limit_position = select_stmt->limit_token_off_; + int64_t from_position = dml_stmt->get_from_token_off(); + int64_t limit_position = dml_stmt->limit_token_off_; new_sql.append(sql_ptr, from_position); if (!derived_columns_.empty()) { @@ -746,10 +747,10 @@ int ObShardingSelectLogPlan::rewrite_sql(ObSqlString &new_sql) if (limit_position > 0) { new_sql.append("LIMIT "); - if (select_stmt->limit_size_ == 0) { - new_sql.append_fmt("%d", select_stmt->limit_size_); + if (dml_stmt->limit_size_ == 0) { + new_sql.append_fmt("%d", dml_stmt->limit_size_); } else { - new_sql.append_fmt("%d", select_stmt->limit_offset_ + select_stmt->limit_size_); + new_sql.append_fmt("%d", dml_stmt->limit_offset_ + dml_stmt->limit_size_); } } } @@ -763,8 +764,8 @@ int ObShardingSelectLogPlan::add_agg_operator(bool need_set_limit) { int ret = OB_SUCCESS; - ObProxySelectStmt *select_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); - ObIArray &group_by_exprs = select_stmt->group_by_exprs_; + ObProxyDMLStmt *dml_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); + ObIArray &group_by_exprs = dml_stmt->group_by_exprs_; T *agg_operator = NULL; ObProxyAggInput *agg_input = NULL; @@ -778,8 +779,8 @@ int ObShardingSelectLogPlan::add_agg_operator(bool need_set_limit) LOG_WARN("set child failed", K(ret)); } else { if (need_set_limit) { - agg_input->set_limit_offset(select_stmt->limit_offset_); - agg_input->set_limit_size(select_stmt->limit_size_); + agg_input->set_limit_offset(dml_stmt->limit_offset_); + agg_input->set_limit_size(dml_stmt->limit_size_); is_set_limit_ = true; } plan_root_ = agg_operator; @@ -815,8 +816,8 @@ int ObShardingSelectLogPlan::add_sort_operator(bool need_set_limit) { int ret = OB_SUCCESS; - ObProxySelectStmt *select_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); - ObIArray &order_by_exprs = select_stmt->order_by_exprs_; + ObProxyDMLStmt *dml_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); + ObIArray &order_by_exprs = dml_stmt->order_by_exprs_; T *sort_operator = NULL; ObProxySortInput *sort_input = NULL; @@ -828,8 +829,8 @@ int ObShardingSelectLogPlan::add_sort_operator(bool need_set_limit) LOG_WARN("set child failed", K(ret)); } else { if (need_set_limit) { - sort_input->set_limit_offset(select_stmt->limit_offset_); - sort_input->set_limit_size(select_stmt->limit_size_); + sort_input->set_limit_offset(dml_stmt->limit_offset_); + sort_input->set_limit_size(dml_stmt->limit_size_); is_set_limit_ = true; } plan_root_ = sort_operator; @@ -864,9 +865,9 @@ int ObShardingSelectLogPlan::add_agg_and_sort_operator(bool is_same_group_and_or { int ret = OB_SUCCESS; - ObProxySelectStmt *select_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); - ObIArray &group_by_exprs = select_stmt->group_by_exprs_; - ObIArray &order_by_exprs = select_stmt->order_by_exprs_; + ObProxyDMLStmt *dml_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); + ObIArray &group_by_exprs = dml_stmt->group_by_exprs_; + ObIArray &order_by_exprs = dml_stmt->order_by_exprs_; if (!group_by_exprs.empty() || !agg_exprs_.empty()) { if (!is_same_group_and_order) { @@ -907,7 +908,7 @@ int ObShardingSelectLogPlan::add_table_scan_operator(ObIArray(client_request_.get_parse_result().get_proxy_stmt()); + ObProxyDMLStmt *dml_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); ObProxyTableScanOp *table_scan_op = NULL; ObProxyTableScanInput *table_scan_input = NULL; char *buf = NULL; @@ -919,7 +920,7 @@ int ObShardingSelectLogPlan::add_table_scan_operator(ObIArrayset_db_key_names(shard_connector_array))) { LOG_WARN("fail to set db key name", K(ret)); } else if (OB_FAIL(table_scan_input->set_shard_props(shard_prop_array))) { @@ -930,9 +931,9 @@ int ObShardingSelectLogPlan::add_table_scan_operator(ObIArrayset_agg_exprs(agg_exprs_))) { LOG_WARN("fail to set agg expr", K(ret)); - } else if (OB_FAIL(table_scan_input->set_group_exprs(select_stmt->group_by_exprs_))) { + } else if (OB_FAIL(table_scan_input->set_group_exprs(dml_stmt->group_by_exprs_))) { LOG_WARN("fail to set group exprs", K(ret)); - } else if (OB_FAIL(table_scan_input->set_order_exprs(select_stmt->order_by_exprs_))) { + } else if (OB_FAIL(table_scan_input->set_order_exprs(dml_stmt->order_by_exprs_))) { LOG_WARN("fail to set order exprs", K(ret)); } else { table_scan_input->set_request_sql(request_sql); @@ -947,7 +948,7 @@ int ObShardingSelectLogPlan::add_table_scan_operator(ObIArray(client_request_.get_parse_result().get_proxy_stmt()); + ObProxyDMLStmt *dml_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); ObProxyProOp *op = NULL; ObProxyProInput *input = NULL; @@ -958,8 +959,8 @@ int ObShardingSelectLogPlan::add_projection_operator() input->set_calc_exprs(calc_exprs_); input->set_derived_column_count(derived_column_count_); if (!is_set_limit_) { - input->set_limit_offset(select_stmt->limit_offset_); - input->set_limit_size(select_stmt->limit_size_); + input->set_limit_offset(dml_stmt->limit_offset_); + input->set_limit_size(dml_stmt->limit_size_); is_set_limit_ = true; } if (OB_FAIL(op->set_child(0, plan_root_))) { @@ -976,9 +977,9 @@ int ObShardingSelectLogPlan::compare_group_and_order(bool &is_same_group_and_ord { int ret = OB_SUCCESS; - ObProxySelectStmt *select_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); - ObIArray &group_by_exprs = select_stmt->group_by_exprs_; - ObIArray &order_by_exprs = select_stmt->order_by_exprs_; + ObProxyDMLStmt *dml_stmt = static_cast(client_request_.get_parse_result().get_proxy_stmt()); + ObIArray &group_by_exprs = dml_stmt->group_by_exprs_; + ObIArray &order_by_exprs = dml_stmt->order_by_exprs_; if (!group_by_exprs.empty() && !order_by_exprs.empty() && group_by_exprs.count() == order_by_exprs.count()) { diff --git a/src/obproxy/packet/Makemodule.am b/src/obproxy/packet/Makemodule.am index e50623194a5c897105b2a849c3e57951b8058d15..7cc929e1076f4e0547f174c5c513410f821ea961 100644 --- a/src/obproxy/packet/Makemodule.am +++ b/src/obproxy/packet/Makemodule.am @@ -8,4 +8,6 @@ obproxy/packet/ob_mysql_packet_writer.cpp\ obproxy/packet/ob_mysql_packet_reader.h\ obproxy/packet/ob_mysql_packet_reader.cpp\ obproxy/packet/ob_mysql_packet_util.cpp\ -obproxy/packet/ob_mysql_packet_util.h +obproxy/packet/ob_mysql_packet_util.h\ +obproxy/packet/ob_proxy_packet_writer.h\ +obproxy/packet/ob_proxy_packet_writer.cpp diff --git a/src/obproxy/packet/ob_mysql_packet_reader.cpp b/src/obproxy/packet/ob_mysql_packet_reader.cpp index f5c95effe244f91f2df646e4d8e5d63f26305741..d28ba1ba93e0e95e88ef552b6530f912fd35f55e 100644 --- a/src/obproxy/packet/ob_mysql_packet_reader.cpp +++ b/src/obproxy/packet/ob_mysql_packet_reader.cpp @@ -12,7 +12,6 @@ #define USING_LOG_PREFIX PROXY #include "packet/ob_mysql_packet_reader.h" -#include "rpc/obmysql/ob_mysql_util.h" #include "rpc/obmysql/packet/ompk_ok.h" using namespace oceanbase::common; @@ -111,20 +110,20 @@ inline int ObMysqlPacketReader::get_buf(ObIOBufferReader &buf_reader, const int6 return ret; } -inline int ObMysqlPacketReader::get_content_len_and_seq(ObIOBufferReader &buf_reader, - const int64_t offset, int64_t &content_len, uint8_t &seq) +int ObMysqlPacketReader::is_eof_packet(ObIOBufferReader &buf_reader, const int64_t offset, bool &is_eof) { int ret = OB_SUCCESS; char *pbuf = NULL; - if (OB_FAIL(get_buf(buf_reader, OB_MYSQL_NET_HEADER_LENGTH, offset, pbuf))) { + is_eof = false; + if (OB_FAIL(get_buf(buf_reader, proxy::MYSQL_NET_META_LENGTH, offset, pbuf))) { LOG_WARN("fail to get header buf", K(ret)); } else if (OB_ISNULL(pbuf)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("pbuf is null, which is unexpected", K(pbuf), K(ret)); } else { - content_len = static_cast(ob_uint3korr(pbuf)); - seq = static_cast(ob_uint1korr(pbuf + 3)); - } + int64_t eof = static_cast(uint1korr(pbuf + 4)); + is_eof = (proxy::MYSQL_EOF_PACKET_TYPE == eof); + } return ret; } @@ -191,12 +190,18 @@ int ObMysqlPacketReader::get_ok_packet_server_status(ObIOBufferReader &buf_reade int ObMysqlPacketReader::get_packet(ObIOBufferReader &buf_reader, ObMySQLPacket &packet) +{ + return get_packet(buf_reader, 0, packet); +} + +int ObMysqlPacketReader::get_packet(ObIOBufferReader &buf_reader, + const int64_t offset, + ObMySQLPacket &packet) { int ret = OB_SUCCESS; char *content_buf = NULL; int64_t content_len = 0; uint8_t seq = 0; - int64_t offset = 0; if (OB_FAIL(get_content_len_and_seq(buf_reader, offset, content_len, seq))) { LOG_WARN("fail to get content length and seq", K(content_len), K(seq), K(offset), K(ret)); } else if (OB_FAIL(get_buf(buf_reader, content_len, offset + OB_MYSQL_NET_HEADER_LENGTH, content_buf))) { diff --git a/src/obproxy/packet/ob_mysql_packet_reader.h b/src/obproxy/packet/ob_mysql_packet_reader.h index 75dadab073f330365a94266a1d1a235c0df695ec..a95758e3489153ca20a84f89e071d2a40e774abd 100644 --- a/src/obproxy/packet/ob_mysql_packet_reader.h +++ b/src/obproxy/packet/ob_mysql_packet_reader.h @@ -15,6 +15,8 @@ #include "utils/ob_proxy_lib.h" #include "iocore/eventsystem/ob_io_buffer.h" +#include "proxy/mysqllib/ob_mysql_common_define.h" +#include "rpc/obmysql/ob_mysql_util.h" namespace oceanbase { @@ -44,6 +46,8 @@ public: // === GET function will not comsume the packet int get_content_len_and_seq(event::ObIOBufferReader &buf_reader, const int64_t offset, int64_t &content_len, uint8_t &seq); + int is_eof_packet(event::ObIOBufferReader &buf_reader, const int64_t offset, bool &is_eof); + // DESC: get the next ok packet from MIOBuffer // NOTE: 1. get function will NOT consume buffer as packet may hold some string int mio_buf // 2. if mio_buf.consume or reader.reset is called, do NOT use the packet any more @@ -71,6 +75,9 @@ public: obmysql::OMPKOK &ok_pkt); int get_packet(event::ObIOBufferReader &buf_reader, obmysql::ObMySQLPacket &packet); + int get_packet(event::ObIOBufferReader &buf_reader, + const int64_t offset, + obmysql::ObMySQLPacket &packet); int get_ok_packet_server_status(event::ObIOBufferReader &buf_reader, obmysql::ObServerStatusFlags &server_status); // === READ function will comsume the packet @@ -134,6 +141,26 @@ inline int ObMysqlPacketReader::read_packet_str(event::ObIOBufferReader &buf_rea return ret; } +inline int ObMysqlPacketReader::get_content_len_and_seq(event::ObIOBufferReader &buf_reader, + const int64_t offset, + int64_t &content_len, + uint8_t &seq) +{ + int ret = OB_SUCCESS; + char *pbuf = NULL; + if (OB_FAIL(get_buf(buf_reader, OB_MYSQL_NET_HEADER_LENGTH, offset, pbuf))) { + PROXY_LOG(WARN, "fail to get header buf", K(ret)); + } else if (OB_ISNULL(pbuf)) { + ret = OB_ERR_UNEXPECTED; + PROXY_LOG(WARN, "pbuf is null, which is unexpected", K(pbuf), K(ret)); + } else { + content_len = static_cast(uint3korr(pbuf)); + seq = static_cast(uint1korr(pbuf + 3)); + } + + return ret; +} + } // end of namespace packet } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/packet/ob_mysql_packet_util.cpp b/src/obproxy/packet/ob_mysql_packet_util.cpp index e8086c9f35daf55b1bbda6bfcb5bb017a9b9e598..74eb479c45c2a313c5150f586373b898d099d5ac 100644 --- a/src/obproxy/packet/ob_mysql_packet_util.cpp +++ b/src/obproxy/packet/ob_mysql_packet_util.cpp @@ -14,11 +14,14 @@ #include "ob_mysql_packet_util.h" #include "common/obsm_row.h" +#include "common/obsm_utils.h" #include "rpc/obmysql/packet/ompk_eof.h" #include "rpc/obmysql/packet/ompk_ok.h" #include "rpc/obmysql/packet/ompk_error.h" #include "rpc/obmysql/packet/ompk_resheader.h" #include "packet/ob_mysql_packet_writer.h" +#include "obproxy/engine/ob_proxy_operator_result.h" +#include "obproxy/iocore/eventsystem/ob_buf_allocator.h" using namespace oceanbase::common; using namespace oceanbase::obmysql; @@ -69,14 +72,37 @@ int ObMysqlPacketUtil::encode_header(ObMIOBuffer &write_buf, return ret; } +int ObMysqlPacketUtil::encode_field_packet(ObMIOBuffer &write_buf, + uint8_t &seq, + ObMySQLField &field) { + int ret = OB_SUCCESS; + OMPKField field_packet(field); + field_packet.set_seq(seq++); + if (OB_FAIL(ObMysqlPacketWriter::write_field_packet(write_buf, field_packet))) { + LOG_WARN("fail to write field", K(field_packet), K(field), K(ret)); + --seq; + } + return ret; +} + +int ObMysqlPacketUtil::encode_row_packet(ObMIOBuffer &write_buf, + uint8_t &seq, + const ObNewRow &row, + ObIArray *fields) +{ + return encode_row_packet(write_buf, TEXT, seq, row, fields); +} + int ObMysqlPacketUtil::encode_row_packet(ObMIOBuffer &write_buf, + MYSQL_PROTOCOL_TYPE protocol_type, uint8_t &seq, const ObNewRow &row, ObIArray *fields) { int ret = OB_SUCCESS; - OMPKRow row_packet(ObSMRow(TEXT, row, NULL, fields)); + ObSMRow sm_row(protocol_type, row, NULL, fields); + OMPKRow row_packet(sm_row); row_packet.set_seq(seq++); if (OB_FAIL(ObMysqlPacketWriter::write_row_packet(write_buf, row_packet))) { @@ -104,14 +130,13 @@ int ObMysqlPacketUtil::encode_eof_packet(ObMIOBuffer &write_buf, return ret; } -int ObMysqlPacketUtil::encode_err_packet_buf(ObMIOBuffer &write_buf, uint8_t &seq, - const int errcode, const char *msg_buf) +int ObMysqlPacketUtil::encode_err_packet(ObMIOBuffer &write_buf, uint8_t &seq, const int errcode, const char *msg_buf) { - return encode_err_packet_buf(write_buf, seq, errcode, ObString::make_string(msg_buf)); + return encode_err_packet(write_buf, seq, errcode, ObString::make_string(msg_buf)); } -int ObMysqlPacketUtil::encode_err_packet_buf(ObMIOBuffer &write_buf, uint8_t &seq, - const int errcode, ObString msg_buf) +int ObMysqlPacketUtil::encode_err_packet(ObMIOBuffer &write_buf, uint8_t &seq, const int errcode, + const ObString &msg_buf) { int ret = OB_SUCCESS; @@ -129,36 +154,10 @@ int ObMysqlPacketUtil::encode_err_packet_buf(ObMIOBuffer &write_buf, uint8_t &se return ret; } -int ObMysqlPacketUtil::encode_err_packet(ObMIOBuffer &write_buf, uint8_t &seq, - int errcode) -{ - int ret = OB_SUCCESS; - const int32_t MAX_MSG_BUF_SIZE = 256; - if (OB_SUCCESS == errcode) { - BACKTRACE(ERROR, (OB_SUCCESS == errcode), "BUG send error packet but err code is 0"); - errcode = OB_ERR_UNEXPECTED; - } - char msg_buf[MAX_MSG_BUF_SIZE]; - const char *errmsg = ob_strerror(errcode); - int32_t length = 0; - if (OB_ISNULL(errmsg)) { - length = snprintf(msg_buf, sizeof(msg_buf), "Unknown user error"); - } else { - length = snprintf(msg_buf, sizeof(msg_buf), errmsg); - } - if (length < 0 || length >= MAX_MSG_BUF_SIZE) { - ret = OB_BUF_NOT_ENOUGH; - PROXY_LOG(WARN, "msg_buf is not enough", K(length), K(errmsg), K(ret)); - } else { - ret = encode_err_packet_buf(write_buf, seq, errcode, msg_buf); - } - return ret; -} - int ObMysqlPacketUtil::encode_ok_packet(ObMIOBuffer &write_buf, uint8_t &seq, const int64_t affected_rows, const ObMySQLCapabilityFlags &capability, - uint16_t status_flag /* 0 */) + const uint16_t status_flag /* 0 */) { int ret = OB_SUCCESS; diff --git a/src/obproxy/packet/ob_mysql_packet_util.h b/src/obproxy/packet/ob_mysql_packet_util.h index 6ad9b1cf571589b6e9dd8ae97382a2d18f12df00..2073997e1002d00617d90b83709153935fb21161 100644 --- a/src/obproxy/packet/ob_mysql_packet_util.h +++ b/src/obproxy/packet/ob_mysql_packet_util.h @@ -35,6 +35,10 @@ namespace event { class ObMIOBuffer; } +namespace engine +{ +class ObProxyResultResp; +} class ObMysqlPacketUtil { @@ -43,54 +47,31 @@ public: static int encode_header(event::ObMIOBuffer &write_buf, uint8_t &seq, common::ObIArray &fields, uint16_t status_flag = 0); - static int encode_row_packet(event::ObMIOBuffer &write_buf, uint8_t &seq, + static int encode_field_packet(event::ObMIOBuffer &write_buf, + uint8_t &seq, + obmysql::ObMySQLField &field); + static int encode_row_packet(event::ObMIOBuffer &write_buf, + uint8_t &seq, + const common::ObNewRow &row, + common::ObIArray *fields = NULL); + static int encode_row_packet(event::ObMIOBuffer &write_buf, + obmysql::MYSQL_PROTOCOL_TYPE protocol_type, + uint8_t &seq, const common::ObNewRow &row, common::ObIArray *fields = NULL); static int encode_eof_packet(event::ObMIOBuffer &write_buf, uint8_t &seq, uint16_t status_flag = 0); - static int encode_err_packet(event::ObMIOBuffer &write_buf, uint8_t &seq, int errcode); - - template - static int encode_err_packet(event::ObMIOBuffer &write_buf, uint8_t &seq, int errcode, T ¶m) - { - int ret = common::OB_SUCCESS; - const int32_t MAX_MSG_BUF_SIZE = 256; - if (OB_UNLIKELY(common::OB_SUCCESS == errcode)) { - PROXY_LOG(WARN, "BUG send error packet but err code is 0", "Backtrace", common::lbt()); - errcode = common::OB_ERR_UNEXPECTED; - } - char msg_buf[MAX_MSG_BUF_SIZE]; - const char *errmsg = ob_str_user_error(errcode); - int32_t length = 0; - if (OB_ISNULL(errmsg)) { - length = snprintf(msg_buf, sizeof(msg_buf), "Unknown user error, err=%d", errcode); - } else { - length = snprintf(msg_buf, sizeof(msg_buf), errmsg, param); - } - if (OB_UNLIKELY(length < 0) || OB_UNLIKELY(length > MAX_MSG_BUF_SIZE)) { - ret = common::OB_BUF_NOT_ENOUGH; - PROXY_LOG(WARN, "msg_buf is not enough", K(length), K(errmsg), K(ret)); - } else { - ret = encode_err_packet_buf(write_buf, seq, errcode, msg_buf); - } - return ret; - } - static int encode_err_packet_buf(event::ObMIOBuffer &write_buf, - uint8_t &seq, - const int errcode, - const char *msg_buf); + static int encode_err_packet(event::ObMIOBuffer &write_buf, uint8_t &seq, const int errcode, const char *msg_buf); - static int encode_err_packet_buf(event::ObMIOBuffer &write_buf, - uint8_t &seq, - const int errcode, - common::ObString msg); + static int encode_err_packet(event::ObMIOBuffer &write_buf, uint8_t &seq, const int errcode, + const common::ObString &msg); static int encode_ok_packet(event::ObMIOBuffer &write_buf, uint8_t &seq, const int64_t affected_rows, const obmysql::ObMySQLCapabilityFlags &capability, - uint16_t status_flag = 0); + const uint16_t status_flag = 0); static int encode_kv_resultset(event::ObMIOBuffer &write_buf, uint8_t &seq, const obmysql::ObMySQLField &field, diff --git a/src/obproxy/packet/ob_mysql_packet_writer.cpp b/src/obproxy/packet/ob_mysql_packet_writer.cpp index b6166416876e1bf57e96821736ddcb65fdf4b189..475b2df415810e6a64487704c3cecb687d7e4124 100644 --- a/src/obproxy/packet/ob_mysql_packet_writer.cpp +++ b/src/obproxy/packet/ob_mysql_packet_writer.cpp @@ -78,60 +78,90 @@ int ObMysqlPacketWriter::write_packet(ObMIOBuffer &mio_buf, } -// only compress ObMysqlRawPacket, -int ObMysqlPacketWriter::write_compressed_packet(ObMIOBuffer &mio_buf, - const ObMySQLRawPacket &packet, - uint8_t &compressed_seq, - const bool is_checksum_on) +int ObMysqlPacketWriter::write_raw_packet(ObMIOBuffer &mio_buf, const ObString &packet_str) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(packet_str.empty())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(packet_str), K(ret)); + } else { + int64_t written_len = 0; + if (OB_FAIL(mio_buf.write(packet_str.ptr(), packet_str.length(), written_len))) { + LOG_WARN("not all data write to miobuffer", K(written_len), K(packet_str.length()), K(ret)); + } else if (OB_UNLIKELY(packet_str.length() != written_len)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("packet is not written completely", K(written_len), K(packet_str.length()), K(ret)); + } else {} // do nothing + } + return ret; +} + +int ObMysqlPacketWriter::write_raw_packet(ObMIOBuffer &write_buf, const ObMySQLRawPacket &packet) { int ret = OB_SUCCESS; + char meta_buf[MYSQL_NET_META_LENGTH]; int64_t pos = 0; int64_t meta_buf_len = MYSQL_NET_META_LENGTH; - // 1. encode mysql packet meta(header + cmd) + const char *buf = packet.get_cdata(); + int64_t buf_len = packet.get_clen(); + int64_t written_len = 0; + + // first write mysql packet meta(header + cmd) if (OB_FAIL(packet.encode_packet_meta(meta_buf, meta_buf_len, pos))) { LOG_WARN("fail to encode packet meta", K(pos), K(packet), K(meta_buf_len), K(ret)); + } else if (OB_FAIL(write_buf.write(meta_buf, meta_buf_len, written_len))) { + LOG_WARN("fail to write meta buf to dst buf", K(ret)); + } else if (OB_UNLIKELY(written_len != MYSQL_NET_META_LENGTH)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("written len dismatch", K(ret), K(written_len), K(MYSQL_NET_META_LENGTH)); + } else if (OB_FAIL(write_buf.write(buf, buf_len, written_len))) { // then write packet body + LOG_WARN("fail to write packet buf to dst buf", K(ret)); + } else if (OB_UNLIKELY(written_len != buf_len)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("written len dismatch", K(ret), K(buf_len), K(written_len)); } else { - ObIOBufferReader *tmp_reader = NULL; - ObMIOBuffer *tmp_mio_buf = NULL; - const char *buf = packet.get_cdata(); - int64_t buf_len = packet.get_clen(); - int64_t written_len = 0; - const bool use_fast_compress = true; - if (OB_ISNULL(tmp_mio_buf = new_empty_miobuffer())) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to new miobuffer", K(ret)); - } else if (OB_ISNULL(tmp_reader = tmp_mio_buf->alloc_reader())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("fail to alloc reader", K(ret)); - // 2. write the meta buf, the first part of mysql packet - } else if (OB_FAIL(tmp_mio_buf->write(meta_buf, meta_buf_len, written_len))) { - LOG_WARN("fail to write", K(meta_buf_len), K(ret)); - } else if (OB_UNLIKELY(written_len != MYSQL_NET_META_LENGTH)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("written_len dismatch", K(written_len), K(MYSQL_NET_META_LENGTH), K(ret)); - // 3. write the request buf, the second part of mysql packet - } else if (OB_FAIL(tmp_mio_buf->write(buf, buf_len, written_len))) { - LOG_WARN("fail to write", K(buf_len), K(ret)); - } else if (OB_UNLIKELY(written_len != buf_len)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("written_len dismatch", K(written_len), K(buf_len), K(ret)); - // 4. make up compress packet - } else if (OB_FAIL(ObMysqlAnalyzerUtils::consume_and_compress_data(tmp_reader, - &mio_buf, tmp_reader->read_avail(), use_fast_compress, compressed_seq, is_checksum_on))) { - LOG_WARN("fail to consume and compress data", K(use_fast_compress), - K(tmp_reader->read_avail()), K(ret)); - } - if (NULL != tmp_mio_buf) { - free_miobuffer(tmp_mio_buf); - tmp_mio_buf = NULL; - tmp_reader = NULL; - } + // nothing } return ret; } +// only compress ObMysqlRawPacket +int ObMysqlPacketWriter::write_compressed_packet(ObMIOBuffer &mio_buf, + const ObMySQLRawPacket &packet, + uint8_t &compressed_seq, + const bool is_checksum_on) +{ + int ret = OB_SUCCESS; + + const bool use_fast_compress = true; + ObIOBufferReader *tmp_mio_reader = NULL; + ObMIOBuffer *tmp_mio_buf = NULL; + + if (OB_ISNULL(tmp_mio_buf = new_empty_miobuffer())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to new miobuffer", K(ret)); + } else if (OB_ISNULL(tmp_mio_reader = tmp_mio_buf->alloc_reader())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to alloc reader", K(ret)); + } else if (OB_FAIL(ObMysqlPacketWriter::write_raw_packet(*tmp_mio_buf, packet))) { + LOG_WARN("fail to write raw packet", K(ret)); + } else if (OB_FAIL(ObMysqlAnalyzerUtils::consume_and_compress_data(tmp_mio_reader, &mio_buf, + tmp_mio_reader->read_avail(), use_fast_compress, compressed_seq, is_checksum_on))) { + LOG_WARN("fail to consume and compress data", K(ret)); + } else { + // nothing + } + + if (NULL != tmp_mio_buf) { + free_miobuffer(tmp_mio_buf); + tmp_mio_buf = NULL; + tmp_mio_reader = NULL; + } + + return ret; +} int ObMysqlPacketWriter::write_compressed_packet( ObMIOBuffer &mio_buf, @@ -200,24 +230,6 @@ int ObMysqlPacketWriter::write_compressed_packet( return ret; } -int ObMysqlPacketWriter::write_raw_packet(ObMIOBuffer &mio_buf, const ObString &packet_str) -{ - int ret = OB_SUCCESS; - if (OB_UNLIKELY(packet_str.empty())) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid argument", K(packet_str), K(ret)); - } else { - int64_t written_len = 0; - if (OB_FAIL(mio_buf.write(packet_str.ptr(), packet_str.length(), written_len))) { - LOG_WARN("not all data write to miobuffer", K(written_len), K(packet_str.length()), K(ret)); - } else if (OB_UNLIKELY(packet_str.length() != written_len)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("packet is not written completely", K(written_len), K(packet_str.length()), K(ret)); - } else {} // do nothing - } - return ret; -} - int ObMysqlPacketWriter::write_request_packet(ObMIOBuffer &mio_buf, const ObMySQLCmd cmd, const common::ObString &sql_str, uint8_t &compressed_seq, diff --git a/src/obproxy/packet/ob_mysql_packet_writer.h b/src/obproxy/packet/ob_mysql_packet_writer.h index 71eb10cf67b2a23b2a6c83db1fceb06165a34869..b5170418b98d523c80bcd87b14224b27d6dfea25 100644 --- a/src/obproxy/packet/ob_mysql_packet_writer.h +++ b/src/obproxy/packet/ob_mysql_packet_writer.h @@ -39,15 +39,19 @@ public: ~ObMysqlPacketWriter() {} // write mysql packet to mio buffer + static int write_packet(event::ObMIOBuffer &mio_buf, const obmysql::ObMySQLPacket &packet); static int write_packet(event::ObMIOBuffer &mio_buf, - const obmysql::ObMySQLPacket &packet); + const obmysql::ObMySQLPacket &packet, + const int64_t packet_len); + static int write_field_packet(event::ObMIOBuffer &mio_buf, const obmysql::OMPKField &field_packet); static int write_row_packet(event::ObMIOBuffer &mio_buf, const obmysql::OMPKRow &row_packet); // write raw packet string to mio buffer - static int write_raw_packet(event::ObMIOBuffer &mio_buf, - const common::ObString &raw_packet); + static int write_raw_packet(event::ObMIOBuffer &mio_buf, const common::ObString &raw_packet); + static int write_raw_packet(event::ObMIOBuffer &write_buf, const obmysql::ObMySQLRawPacket &packet); + // write request packet to mio buffer static int write_request_packet(event::ObMIOBuffer &mio_buf, const obmysql::ObMySQLCmd cmd, @@ -56,9 +60,6 @@ public: const bool need_compress, const bool is_checksum_on); private: - static int write_packet(event::ObMIOBuffer &mio_buf, - const obmysql::ObMySQLPacket &packet, - const int64_t packet_len); // @packet, normal mysql packet // compress the packet and write compressed packet to mio_buf static int write_compressed_packet(event::ObMIOBuffer &mio_buf, @@ -72,6 +73,8 @@ private: const obmysql::ObMySQLRawPacket &packet, uint8_t &compressed_seq, const bool is_checksum_on); + + DISALLOW_COPY_AND_ASSIGN(ObMysqlPacketWriter); }; inline int ObMysqlPacketWriter::write_packet(event::ObMIOBuffer &mio_buf, diff --git a/src/obproxy/packet/ob_proxy_ok_packet.h b/src/obproxy/packet/ob_proxy_ok_packet.h index cfb41aec5f8ba76249e0a258f4a4f7d8e1263623..bae6b87a2800ac778110165f63e4d70cad28f058 100644 --- a/src/obproxy/packet/ob_proxy_ok_packet.h +++ b/src/obproxy/packet/ob_proxy_ok_packet.h @@ -74,7 +74,7 @@ inline void ObProxyOKPacket::set_seq(const uint8_t seq) // if buffer is valid, set to buffer directly if (is_buffer_valid_) { if (OB_LIKELY(OB_SEQ_POS < OB_MAX_OK_PACKET_LENGTH)) { - ob_int1store(pkt_buf_ + OB_SEQ_POS, seq); + int1store(pkt_buf_ + OB_SEQ_POS, seq); } else { is_buffer_valid_ = false; } @@ -92,7 +92,7 @@ inline void ObProxyOKPacket::set_status_flags(const uint16_t status_flags) // if buffer is valid, set to buffer directly if (is_buffer_valid_) { if (OB_LIKELY(status_flags_pos_ + 1 < OB_MAX_OK_PACKET_LENGTH)) { - ob_int2store(pkt_buf_ + status_flags_pos_, status_flags); + int2store(pkt_buf_ + status_flags_pos_, status_flags); } else { is_buffer_valid_ = false; } @@ -110,7 +110,7 @@ inline void ObProxyOKPacket::set_warnings_count(const uint16_t warnings_count) // if buffer is valid, set to buffer directly if (is_buffer_valid_) { if (OB_LIKELY(warnings_count_pos_ + 1 < OB_MAX_OK_PACKET_LENGTH)) { - ob_int2store(pkt_buf_ + warnings_count_pos_, warnings_count); + int2store(pkt_buf_ + warnings_count_pos_, warnings_count); } else { is_buffer_valid_ = false; } diff --git a/src/obproxy/packet/ob_proxy_packet_writer.cpp b/src/obproxy/packet/ob_proxy_packet_writer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d5d1a1089a7a323dbc2347ee4927e6fd3c626f65 --- /dev/null +++ b/src/obproxy/packet/ob_proxy_packet_writer.cpp @@ -0,0 +1,233 @@ +/** + * Copyright (c) 2022 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ +#define USING_LOG_PREFIX PROXY + +#include "lib/oblog/ob_log.h" +#include "obproxy/packet/ob_proxy_packet_writer.h" +#include "obproxy/packet/ob_mysql_packet_writer.h" +#include "obproxy/proxy/mysqllib/ob_proxy_session_info.h" +#include "obproxy/proxy/mysqllib/ob_2_0_protocol_struct.h" +#include "obproxy/proxy/mysqllib/ob_mysql_ob20_packet_write.h" +#include "rpc/obmysql/ob_mysql_field.h" +#include "obproxy/iocore/eventsystem/ob_io_buffer.h" +#include "lib/utility/ob_macro_utils.h" +#include "obproxy/proxy/mysqllib/ob_2_0_protocol_utils.h" +#include "obproxy/proxy/mysql/ob_mysql_client_session.h" + + +using namespace oceanbase::obproxy::proxy; +using namespace oceanbase::obproxy::event; +using namespace oceanbase::common; + +namespace oceanbase +{ +namespace obproxy +{ +namespace packet +{ + +int ObProxyPacketWriter::write_packet(event::ObMIOBuffer &write_buf, + ObMysqlClientSession &client_session, + const ObProxyProtocol protocol, + obmysql::ObMySQLPacket &packet) +{ + int ret = OB_SUCCESS; + + if (protocol == ObProxyProtocol::PROTOCOL_OB20) { + Ob20ProtocolHeader &ob20_head = client_session.get_session_info().ob20_request_.ob20_header_; + uint8_t compressed_seq = static_cast(client_session.get_compressed_seq() + 1); + Ob20ProtocolHeaderParam ob20_head_param(client_session.get_cs_id(), ob20_head.request_id_, compressed_seq, + compressed_seq, true, false, false, + client_session.is_client_support_new_extra_info(), + client_session.is_trans_internal_routing()); + if (OB_FAIL(ObMysqlOB20PacketWriter::write_packet(write_buf, packet, ob20_head_param))) { + LOG_WARN("fail to write ob20 packet", K(ret)); + } else { + client_session.set_compressed_seq(compressed_seq); + } + } else { + if (OB_FAIL(ObMysqlPacketWriter::write_packet(write_buf, packet))) { + LOG_WARN("fail to write mysql packet", K(ret)); + } + } + + return ret; +} + +int ObProxyPacketWriter::write_raw_packet(event::ObMIOBuffer &write_buf, + ObMysqlClientSession &client_session, + const ObProxyProtocol protocol, + ObString &pkt_str) +{ + int ret = OB_SUCCESS; + + if (protocol == ObProxyProtocol::PROTOCOL_OB20) { + Ob20ProtocolHeader &ob20_head = client_session.get_session_info().ob20_request_.ob20_header_; + uint8_t compressed_seq = static_cast(client_session.get_compressed_seq() + 1); + Ob20ProtocolHeaderParam ob20_head_param(client_session.get_cs_id(), ob20_head.request_id_, + compressed_seq, compressed_seq, true, false, false, + client_session.is_client_support_new_extra_info(), + client_session.is_trans_internal_routing()); + if (OB_FAIL(ObMysqlOB20PacketWriter::write_raw_packet(write_buf, pkt_str, ob20_head_param))) { + LOG_WARN("fail to write raw packet in ob20 format", K(ret)); + } else { + client_session.set_compressed_seq(compressed_seq); + } + } else { + if (OB_FAIL(ObMysqlPacketWriter::write_raw_packet(write_buf, pkt_str))) { + LOG_WARN("fail to write raw ok packet", K(ret)); + } + } + + return ret; +} + +int ObProxyPacketWriter::write_kv_resultset(event::ObMIOBuffer &write_buf, + ObMysqlClientSession &client_session, + const ObProxyProtocol protocol, + uint8_t &seq, + const obmysql::ObMySQLField &field, + ObObj &field_value, + const uint16_t status_flag) +{ + int ret = OB_SUCCESS; + + if (protocol == ObProxyProtocol::PROTOCOL_OB20) { + Ob20ProtocolHeader &ob20_head = client_session.get_session_info().ob20_request_.ob20_header_; + uint8_t compressed_seq = static_cast(client_session.get_compressed_seq() + 1); + Ob20ProtocolHeaderParam ob20_head_param(client_session.get_cs_id(), ob20_head.request_id_, compressed_seq, + compressed_seq, true, false, false, + client_session.is_client_support_new_extra_info(), + client_session.is_trans_internal_routing()); + if (OB_FAIL(ObProto20Utils::encode_kv_resultset(write_buf, ob20_head_param, seq, field, + field_value, status_flag))) { + LOG_WARN("fail to encode kv resultset", K(ret)); + } + } else { + // mysql + if (OB_FAIL(ObMysqlPacketUtil::encode_kv_resultset(write_buf, seq, field, field_value, status_flag))) { + LOG_WARN("fail to encode kv resultset", K(seq), K(ret)); + } + } + + return ret; +} + +int ObProxyPacketWriter::write_ok_packet(event::ObMIOBuffer &write_buf, + ObMysqlClientSession &client_session, + const ObProxyProtocol protocol, + uint8_t &seq, + const int64_t affected_rows, + const obmysql::ObMySQLCapabilityFlags &capability) +{ + int ret = OB_SUCCESS; + + if (protocol == ObProxyProtocol::PROTOCOL_OB20) { + Ob20ProtocolHeader &ob20_head = client_session.get_session_info().ob20_request_.ob20_header_; + uint8_t compressed_seq = static_cast(client_session.get_compressed_seq() + 1); + Ob20ProtocolHeaderParam ob20_head_param(client_session.get_cs_id(), ob20_head.request_id_, compressed_seq, + compressed_seq, true, false, false, + client_session.is_client_support_new_extra_info(), + client_session.is_trans_internal_routing()); + if (OB_FAIL(ObProto20Utils::encode_ok_packet(write_buf, ob20_head_param, seq, affected_rows, capability))) { + LOG_WARN("fail to encode ok packet in ob20 format", K(ret)); + } else { + client_session.set_compressed_seq(compressed_seq); + } + } else { + if (OB_FAIL(ObMysqlPacketUtil::encode_ok_packet(write_buf, seq, affected_rows, capability))) { + LOG_WARN("[ObMysqlSM::do_internal_request] fail to encode OB_MYSQL_COM_PING response ok packet", K(ret)); + } + } + + return ret; +} + +int ObProxyPacketWriter::get_err_buf(int err_code, char *&buf) +{ + int ret = OB_SUCCESS; + + if (OB_UNLIKELY(err_code == OB_SUCCESS)) { + BACKTRACE(ERROR, (OB_SUCCESS == err_code), "BUG send error packet but err code is 0"); + err_code = OB_ERR_UNEXPECTED; + } + + static __thread char msg_buffer_[MAX_MSG_BUFFER_SIZE]; + MEMSET(msg_buffer_, 0x0, sizeof(msg_buffer_)); + const char *err_msg = ob_strerror(err_code); + int32_t length = 0; + if (OB_ISNULL(err_msg)) { + length = snprintf(msg_buffer_, sizeof(msg_buffer_), "Unknown user error"); + } else { + length = snprintf(msg_buffer_, sizeof(msg_buffer_), err_msg); + } + + if (OB_UNLIKELY(length < 0) || OB_UNLIKELY(length >= MAX_MSG_BUFFER_SIZE)) { + ret = OB_BUF_NOT_ENOUGH; + LOG_WARN("err msg buffer not enough", K(ret), K(length), K(err_msg)); + } else { + buf = msg_buffer_; + } + + return ret; +} + +// build error packet back to client +int ObProxyPacketWriter::write_error_packet(event::ObMIOBuffer &write_buf, + proxy::ObMysqlClientSession *client_session, + const ObProxyProtocol protocol, + uint8_t &seq, + const int err_code, + const char *msg_buf) +{ + return write_error_packet(write_buf, client_session, protocol, seq, err_code, common::ObString::make_string(msg_buf)); +} + +int ObProxyPacketWriter::write_error_packet(event::ObMIOBuffer &write_buf, + proxy::ObMysqlClientSession *client_session, + const ObProxyProtocol protocol, + uint8_t &seq, + const int err_code, + const ObString &msg_buf) +{ + int ret = OB_SUCCESS; + + if (protocol == ObProxyProtocol::PROTOCOL_OB20) { + if (OB_ISNULL(client_session)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid client session ptr in ob20 mode", K(ret)); + } else { + Ob20ProtocolHeader &ob20_head = client_session->get_session_info().ob20_request_.ob20_header_; + uint8_t compressed_seq = static_cast(client_session->get_compressed_seq() + 1); + Ob20ProtocolHeaderParam ob20_head_param(client_session->get_cs_id(), ob20_head.request_id_, + compressed_seq, compressed_seq, true, false, false, + client_session->is_client_support_new_extra_info(), + client_session->is_trans_internal_routing()); + if (OB_FAIL(ObProto20Utils::encode_err_packet(write_buf, ob20_head_param, seq, err_code, msg_buf))) { + LOG_WARN("fail to encode err packet in ob20 format", K(ret)); + } + } + } else { + // mysql + if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet(write_buf, seq, err_code, msg_buf))) { + LOG_WARN("fail to encode err packet buf in mysql format", K(ret)); + } + } + + return ret; +} + + +} // end of packet +} // end of obproxy +} // end of oceanbase + diff --git a/src/obproxy/packet/ob_proxy_packet_writer.h b/src/obproxy/packet/ob_proxy_packet_writer.h new file mode 100644 index 0000000000000000000000000000000000000000..4b58c4db61ca969fccab45ecbe5416086e4a7b97 --- /dev/null +++ b/src/obproxy/packet/ob_proxy_packet_writer.h @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2022 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ +#ifndef OB_PROXY_PACKET_WRITER_H +#define OB_PROXY_PACKET_WRITER_H + +#include "obproxy/proxy/mysqllib/ob_proxy_session_info.h" +#include "lib/ob_errno.h" + +namespace oceanbase +{ +namespace obproxy +{ +namespace proxy +{ +class ObMysqlClientSession; +} // end of proxy + +namespace packet +{ +#define MAX_MSG_BUFFER_SIZE (256) + +class ObProxyPacketWriter { +public: + // packet + static int write_packet(event::ObMIOBuffer &write_buf, + proxy::ObMysqlClientSession &client_session, + const proxy::ObProxyProtocol protocol, + obmysql::ObMySQLPacket &packet); + static int write_raw_packet(event::ObMIOBuffer &write_buf, + proxy::ObMysqlClientSession &client_session, + const proxy::ObProxyProtocol protocol, + ObString &pkt_str); + static int write_kv_resultset(event::ObMIOBuffer &write_buf, proxy::ObMysqlClientSession &client_session, + const proxy::ObProxyProtocol protocol, uint8_t &seq, + const obmysql::ObMySQLField &field, ObObj &field_value, const uint16_t status_flag); + static int write_ok_packet(event::ObMIOBuffer &write_buf, proxy::ObMysqlClientSession &client_session, + const proxy::ObProxyProtocol protocol, uint8_t &seq, const int64_t affected_rows, + const obmysql::ObMySQLCapabilityFlags &capability); + + // get thread err buffer + static int get_err_buf(int err_code, char *&buf); + + template + static int get_user_err_buf(int err_code, char *&buf, T ¶m) + { + int ret = common::OB_SUCCESS; + if (OB_UNLIKELY(err_code == common::OB_SUCCESS)) { + err_code = common::OB_ERR_UNEXPECTED; + } + + static __thread char msg_buffer_[MAX_MSG_BUFFER_SIZE]; + MEMSET(msg_buffer_, 0x0, sizeof(msg_buffer_)); + const char *err_msg = common::ob_str_user_error(err_code); + int32_t length = 0; + if (OB_ISNULL(err_msg)) { + length = snprintf(msg_buffer_, sizeof(msg_buffer_), "Unknown user error, err=%d", err_code); + } else { + length = snprintf(msg_buffer_, sizeof(msg_buffer_), err_msg, param); + } + + if (OB_UNLIKELY(length < 0) || OB_UNLIKELY(length > MAX_MSG_BUFFER_SIZE)) { + ret = common::OB_BUF_NOT_ENOUGH; + } else { + buf = msg_buffer_; + } + return ret; + } + + static int write_error_packet(event::ObMIOBuffer &write_buf, proxy::ObMysqlClientSession *client_session, + const proxy::ObProxyProtocol protocol, uint8_t &seq, + const int err_code, const char *msg_buf); + static int write_error_packet(event::ObMIOBuffer &write_buf, proxy::ObMysqlClientSession *client_session, + const proxy::ObProxyProtocol protocol, uint8_t &seq, const int err_code, + const ObString &msg_buf); + +}; + + +} // end of packet +} // end of obproxy +} // end of oceanbase + +#endif // end OB_PROXY_PACKET_WRITER_H diff --git a/src/obproxy/prometheus/ob_prometheus_processor.cpp b/src/obproxy/prometheus/ob_prometheus_processor.cpp index a3e3b82aa23e28e3b24ef3ae9edfd048a80523ca..63bb4c9037f767c00287d0687307a0c543092438 100644 --- a/src/obproxy/prometheus/ob_prometheus_processor.cpp +++ b/src/obproxy/prometheus/ob_prometheus_processor.cpp @@ -61,6 +61,19 @@ int ObPrometheusProcessor::start_prometheus() return ret; } +int ObPrometheusProcessor::start_one_prometheus(int64_t index) +{ + int ret = OB_SUCCESS; + ObEThread **ethreads = g_event_processor.event_thread_[ET_NET]; + if (OB_ISNULL(ethreads[index]->thread_prometheus_ = new(std::nothrow) ObThreadPrometheus())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to new ObThreadPrometheus", K(index), K(ret)); + } else if (OB_FAIL(ethreads[index]->thread_prometheus_->init(ethreads[index]))) { + LOG_WARN("fail to init thread prometheus", K(index), K(ret)); + } + return ret; +} + int ObPrometheusProcessor::start_prometheus_task() { int ret = OB_SUCCESS; diff --git a/src/obproxy/prometheus/ob_prometheus_processor.h b/src/obproxy/prometheus/ob_prometheus_processor.h index c41e33d9a219d5a781434cee6bb90cba6e198b97..44525392f27beb7391fcfd0b770a807c3822fe33 100644 --- a/src/obproxy/prometheus/ob_prometheus_processor.h +++ b/src/obproxy/prometheus/ob_prometheus_processor.h @@ -40,6 +40,7 @@ public: int start_prometheus(); int start_prometheus_task(); + int start_one_prometheus(int64_t index); int handle_counter(const char *name_ptr, const char *help_ptr, common::ObVector &label_array, @@ -87,7 +88,7 @@ private: obutils::ObAsyncCommonTask *prometheus_sync_cont_; char version_[100]; - char proxy_ip_[common::OB_IP_STR_BUFF]; // ip primary key + char proxy_ip_[common::MAX_IP_ADDR_LENGTH]; // ip primary key common::ObVector default_constant_labels_; ObPrometheusFamilyHashTable family_hash_; diff --git a/src/obproxy/prometheus/ob_sql_prometheus.cpp b/src/obproxy/prometheus/ob_sql_prometheus.cpp index 922fda3d87231f1470f14418210e46371cc5f985..8f0f9f62cff59332a030738928066b0e285a9e07 100644 --- a/src/obproxy/prometheus/ob_sql_prometheus.cpp +++ b/src/obproxy/prometheus/ob_sql_prometheus.cpp @@ -178,7 +178,7 @@ int ObSQLPrometheus::handle_prometheus(const ObString &logic_tenant_name, { int32_t value = va_arg(args, int32_t); - ObProxyPrometheusUtils::build_label(label_vector, LABEL_VIP, vip_addr_name, false); + ObProxyPrometheusUtils::build_label(label_vector, LABEL_VIP, vip_addr_name, true); if (OB_FAIL(g_ob_prometheus_processor.handle_gauge(USED_CONNECTIONS, USED_CONNECTIONS_HELP, label_vector, value, false))) { diff --git a/src/obproxy/prometheus/ob_thread_prometheus.cpp b/src/obproxy/prometheus/ob_thread_prometheus.cpp index 687942be6ef8c1aa4322f65a008f18dd21e49570..69944adee9bb1ebd208c29660e6730819793c6e3 100644 --- a/src/obproxy/prometheus/ob_thread_prometheus.cpp +++ b/src/obproxy/prometheus/ob_thread_prometheus.cpp @@ -98,7 +98,7 @@ int ObSQLMonitorInfoCont::schedule_report_prometheus_info() LOG_WARN("not inited", K_(is_inited), K(ret)); } else if (get_global_hot_upgrade_info().is_graceful_exit_timeout(get_hrtime())) { LOG_WARN("proxy need exit now"); - } else if (OB_UNLIKELY(!self_ethread().is_event_thread_type(ET_NET))) { + } else if (OB_UNLIKELY(!thread_->is_event_thread_type(ET_NET))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("sql monitor info cont must be scheduled in net thread", K(ret)); } else if (OB_ISNULL(thread_->schedule_in(this, HRTIME_USECONDS(report_interval_us_), EVENT_NONE))) { diff --git a/src/obproxy/proxy/api/ob_api.cpp b/src/obproxy/proxy/api/ob_api.cpp index d1aee20f62c8c13ce33de541659409b7595f9329..2f98f5bb6acea80002bb8fd5087e85f1d46fffad 100644 --- a/src/obproxy/proxy/api/ob_api.cpp +++ b/src/obproxy/proxy/api/ob_api.cpp @@ -23,6 +23,7 @@ #include "proxy/plugins/ob_mysql_response_cursor_transform_plugin.h" #include "proxy/plugins/ob_mysql_response_new_ps_transform_plugin.h" #include "proxy/plugins/ob_mysql_request_execute_transform_plugin.h" +#include "proxy/plugins/ob_mysql_response_ob20_transform_plugin.h" /**************************************************************** * IMPORTANT - READ ME @@ -458,6 +459,7 @@ int api_init() init_mysql_response_prepare_transform(); init_mysql_response_cursor_transform(); init_mysql_response_prepare_execute_transform(); + init_mysql_response_ob20_protocol_transform(); // } } } diff --git a/src/obproxy/proxy/api/ob_api_internal.h b/src/obproxy/proxy/api/ob_api_internal.h index d309439f60dbd95f4dd8563a31f0247b2be435c5..a956efb1204f1689b50bb2419ed79e04613349c0 100644 --- a/src/obproxy/proxy/api/ob_api_internal.h +++ b/src/obproxy/proxy/api/ob_api_internal.h @@ -93,6 +93,9 @@ public: // Remove all hooks. void destroy(); + // Remove hooks indicated by id + void destroy(ID id); + // Add the hook cont to the front of the hooks for id. int prepend(ID id, ObContInternal *cont); @@ -120,7 +123,7 @@ public: private: bool hooks_p_; // Flag for (not) empty container. - + // The array of hooks lists. ObAPIHooks hooks_[N]; }; @@ -203,6 +206,23 @@ inline void ObFeatureAPIHooks::destroy() hooks_p_ = false; } +template +inline void ObFeatureAPIHooks::destroy(ID id) +{ + if (is_valid(id)) { + hooks_[id].destroy(); + + bool has_hooks_or_not = false; + for (int i = 0; i < N; ++i) { + if (!hooks_[i].is_empty()) { + has_hooks_or_not = true; + break; + } + } + hooks_p_ = has_hooks_or_not; + } +} + template inline int ObFeatureAPIHooks::prepend(ID id, ObContInternal *cont) { diff --git a/src/obproxy/proxy/api/ob_mysql_sm_api.cpp b/src/obproxy/proxy/api/ob_mysql_sm_api.cpp index 92feba16f34bbb0107fcace911561c1326a84716..6c94d244188ab021a9c8dc1e8f37848c1f76708d 100644 --- a/src/obproxy/proxy/api/ob_mysql_sm_api.cpp +++ b/src/obproxy/proxy/api/ob_mysql_sm_api.cpp @@ -937,8 +937,9 @@ int ObMysqlSMApi::setup_server_transfer_to_transform() ObMysqlResp *server_response = &sm_->trans_state_.trans_info_.server_response_; ObIMysqlRespAnalyzer *analyzer = NULL; - ObProxyProtocol ob_proxy_protocol = sm_->use_compression_protocol(); - if (PROTOCOL_CHECKSUM == ob_proxy_protocol || PROTOCOL_OB20 == ob_proxy_protocol) { + ObProxyProtocol ob_proxy_protocol = sm_->get_server_session_protocol(); + if (ObProxyProtocol::PROTOCOL_CHECKSUM == ob_proxy_protocol + || ObProxyProtocol::PROTOCOL_OB20 == ob_proxy_protocol) { const uint8_t req_seq = sm_->get_request_seq(); const obmysql::ObMySQLCmd cmd = sm_->get_request_cmd(); ObMysqlCompressAnalyzer *compress_analyzer = &sm_->get_compress_analyzer(); @@ -1021,11 +1022,20 @@ int ObMysqlSMApi::setup_transfer_from_transform() ret = OB_ERR_UNEXPECTED; LOG_WARN("failed to add consumer", K(c), K_(sm_->sm_id), K(ret)); } else { + ObIMysqlRespAnalyzer *analyzer = NULL; + if (ObProxyProtocol::PROTOCOL_OB20 == sm_->get_client_session_protocol()) { + analyzer = &sm_->compress_ob20_analyzer_; + LOG_DEBUG("set res packet analyzer is ob20"); + } else { + analyzer = &sm_->analyzer_; + LOG_DEBUG("set res packet analyzer is normal"); + } + response_transform_info_.entry_->in_tunnel_ = true; sm_->client_entry_->in_tunnel_ = true; if (OB_FAIL(setup_plugin_clients(*p))) { LOG_WARN("failed to setup_plugin_clients", K(p), K_(sm_->sm_id), K(ret)); - } else if (OB_FAIL(p->set_response_packet_analyzer(0, MYSQL_RESPONSE, &sm_->analyzer_, NULL))) { + } else if (OB_FAIL(p->set_response_packet_analyzer(0, MYSQL_RESPONSE, analyzer, NULL))) { LOG_WARN("failed to set_producer_packet_analyzer", K(p), K_(sm_->sm_id), K(ret)); } else if (OB_FAIL(sm_->tunnel_.tunnel_run(p))) { LOG_WARN("failed to run tunnel", K(p), K_(sm_->sm_id), K(ret)); diff --git a/src/obproxy/proxy/api/ob_mysql_sm_api.h b/src/obproxy/proxy/api/ob_mysql_sm_api.h index 8d70ed8e3c16672fa8e8136eace53f321cf3efb9..4099ffeacdb396c6ac819793c29778c9d5bba5c5 100644 --- a/src/obproxy/proxy/api/ob_mysql_sm_api.h +++ b/src/obproxy/proxy/api/ob_mysql_sm_api.h @@ -116,6 +116,7 @@ public: void txn_hook_append(const ObMysqlHookID id, ObContInternal *cont); void txn_hook_prepend(const ObMysqlHookID id, ObContInternal *cont); ObAPIHook *txn_hook_get(const ObMysqlHookID id); + void txn_destroy_hook(const ObMysqlHookID id); public: // Tunneling request to plugin @@ -180,6 +181,11 @@ inline ObAPIHook *ObMysqlSMApi::txn_hook_get(const ObMysqlHookID id) return api_hooks_.get(id); } +inline void ObMysqlSMApi::txn_destroy_hook(const ObMysqlHookID id) +{ + api_hooks_.destroy(id); +} + } // end of namespace proxy } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/proxy/client/Makemodule.am b/src/obproxy/proxy/client/Makemodule.am index 33b73fdd46dfa848b4f27ee7b8230a82f161160c..d62193b0040199704727fd9cc2a8c7f1e0624c02 100644 --- a/src/obproxy/proxy/client/Makemodule.am +++ b/src/obproxy/proxy/client/Makemodule.am @@ -8,4 +8,6 @@ obproxy/proxy/client/ob_mysql_client_pool.cpp\ obproxy/proxy/client/ob_raw_mysql_client.h\ obproxy/proxy/client/ob_raw_mysql_client.cpp\ obproxy/proxy/client/ob_mysql_proxy.h\ -obproxy/proxy/client/ob_mysql_proxy.cpp +obproxy/proxy/client/ob_mysql_proxy.cpp\ +obproxy/proxy/client/ob_driver_client.h\ +obproxy/proxy/client/ob_driver_client.cpp diff --git a/src/obproxy/proxy/client/ob_client_utils.cpp b/src/obproxy/proxy/client/ob_client_utils.cpp index 98529095c4c478caa500a4189b33830f95b47059..cfc78c7bf69244ad7a01955ac6b113fb6525e18b 100644 --- a/src/obproxy/proxy/client/ob_client_utils.cpp +++ b/src/obproxy/proxy/client/ob_client_utils.cpp @@ -17,7 +17,7 @@ #include "rpc/obmysql/packet/ompk_handshake_response.h" #include "packet/ob_mysql_packet_reader.h" #include "packet/ob_mysql_packet_writer.h" - +#include "omt/ob_proxy_config_table_processor.h" using namespace oceanbase::common; using namespace oceanbase::obmysql; @@ -25,6 +25,8 @@ using namespace oceanbase::obproxy; using namespace oceanbase::obproxy::proxy; using namespace oceanbase::obproxy::event; using namespace oceanbase::obproxy::packet; +using namespace oceanbase::obproxy::omt; +using namespace oceanbase::obproxy::obutils; namespace oceanbase { @@ -41,7 +43,10 @@ void ObMysqlRequestParam::reset() current_idc_name_.reset(); is_user_idc_name_set_ = false; need_print_trace_stat_ = false; - + target_addr_.reset(); + ob_client_flags_.flags_ = 0; + mysql_client_ = NULL; + is_detect_client_ = false; } void ObMysqlRequestParam::reset_sql() @@ -80,6 +85,10 @@ int ObMysqlRequestParam::deep_copy(const ObMysqlRequestParam &other) } else { is_user_idc_name_set_ = other.is_user_idc_name_set_; need_print_trace_stat_ = other.need_print_trace_stat_; + target_addr_ = other.target_addr_; + ob_client_flags_.flags_ = other.ob_client_flags_.flags_; + mysql_client_ = other.mysql_client_; + is_detect_client_ = other.is_detect_client_; if (other.is_user_idc_name_set_ && !other.current_idc_name_.empty()) { MEMCPY(current_idc_name_buf_, other.current_idc_name_.ptr(), other.current_idc_name_.length()); current_idc_name_.assign_ptr(current_idc_name_buf_, other.current_idc_name_.length()); @@ -264,15 +273,15 @@ int64_t ObMysqlResultHandler::to_string(char *buf, const int64_t buf_len) const return pos; } -//------------------------- ObClientReuqestInfo--------------------------------// -void ObClientReuqestInfo::reset() +//------------------------- ObClientRequestInfo --------------------------------// +void ObClientRequestInfo::reset() { reset_names(); need_skip_stage2_ = false; request_param_.reset(); } -void ObClientReuqestInfo::reset_names() +void ObClientRequestInfo::reset_names() { if ((NULL != name_) && (name_len_ > 0)) { op_fixed_mem_free(name_, name_len_); @@ -281,31 +290,35 @@ void ObClientReuqestInfo::reset_names() name_len_ = 0; user_name_.reset(); database_name_.reset(); + cluster_name_.reset(); password_.reset(); password0_.reset(); password1_.reset(); using_password_num_ = -1; + password_version_ = 0; } -void ObClientReuqestInfo::reset_sql() +void ObClientRequestInfo::reset_sql() { request_param_.reset(); } -int64_t ObClientReuqestInfo::to_string(char *buf, const int64_t buf_len) const +int64_t ObClientRequestInfo::to_string(char *buf, const int64_t buf_len) const { int64_t pos = 0; J_OBJ_START(); J_KV(K_(user_name), K_(database_name), + K_(cluster_name), K_(request_param)); J_OBJ_END(); return pos; } -int ObClientReuqestInfo::set_names(const ObString &user_name, +int ObClientRequestInfo::set_names(const ObString &user_name, const ObString &password, const ObString &database_name, + const ObString &cluster_name, const ObString &password1) { int ret = OB_SUCCESS; @@ -314,13 +327,24 @@ int ObClientReuqestInfo::set_names(const ObString &user_name, LOG_WARN("user_name can not be NULL", K(user_name), K(ret)); } else { reset_names(); - int64_t total_len = user_name.length() + password.length() + password1.length() + database_name.length(); + int64_t total_len = user_name.length() + password.length() + password1.length() + + database_name.length() + cluster_name.length(); + if (user_name.prefix_case_match(ObProxyTableInfo::READ_ONLY_USERNAME)) { + if (password.empty()) { + total_len += ENC_STRING_BUF_LEN - 2; + } + if (password1.empty()) { + total_len += ENC_STRING_BUF_LEN - 2; + } + } + if (OB_ISNULL(name_ = static_cast(op_fixed_mem_alloc(total_len)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to allocate mem", "alloc size", total_len, K(ret)); } else { int64_t pos = 0; name_len_ = total_len; + memset(name_, 0, total_len); MEMCPY(name_, user_name.ptr(), user_name.length()); user_name_.assign_ptr(name_, user_name.length()); pos += user_name.length(); @@ -328,25 +352,41 @@ int ObClientReuqestInfo::set_names(const ObString &user_name, if (!password.empty()) { MEMCPY(name_ + pos, password.ptr(), password.length()); password_.assign_ptr(name_ + pos, password.length()); + using_password_num_ = 0; password0_ = password_; pos += password.length(); + } else if (user_name.prefix_case_match(ObProxyTableInfo::READ_ONLY_USERNAME)) { + password0_.assign_ptr(name_ + pos, ENC_STRING_BUF_LEN - 2); + pos += ENC_STRING_BUF_LEN - 2; } - + if (!password1.empty()) { MEMCPY(name_ + pos, password1.ptr(), password1.length()); password1_.assign_ptr(name_ + pos, password1.length()); pos += password1.length(); + if (password_.empty()) { + password_ = password1_; + using_password_num_ = 1; + } + } else if (user_name.prefix_case_match(ObProxyTableInfo::READ_ONLY_USERNAME)) { + password1_.assign_ptr(name_ + pos, ENC_STRING_BUF_LEN - 2); + pos+= ENC_STRING_BUF_LEN - 2; } - if (!password.empty() && !password1.empty()) { + if (user_name.prefix_case_match(ObProxyTableInfo::READ_ONLY_USERNAME) && password0_.empty() && password1_.empty()) { using_password_num_ = 0; } - if (!database_name.empty()) { MEMCPY(name_ + pos, database_name.ptr(), database_name.length()); database_name_.assign_ptr(name_ + pos, database_name.length()); pos += database_name.length(); } + + if (!cluster_name.empty()) { + MEMCPY(name_ + pos, cluster_name.ptr(), cluster_name.length()); + cluster_name_.assign_ptr(name_ + pos, cluster_name.length()); + pos += cluster_name.length(); + } if (pos != total_len) { ret = OB_ERR_UNEXPECTED; LOG_WARN("pos must be equal to total len", K(pos), K(total_len), K(ret)); @@ -357,7 +397,7 @@ int ObClientReuqestInfo::set_names(const ObString &user_name, return ret; } -int ObClientReuqestInfo::set_request_param(const ObMysqlRequestParam &request_param) +int ObClientRequestInfo::set_request_param(const ObMysqlRequestParam &request_param) { int ret = OB_SUCCESS; if (OB_UNLIKELY(!request_param.is_valid())) { @@ -417,7 +457,7 @@ int ObClientUtils::get_scramble(ObIOBufferReader *response_reader, char *buf, int ObClientUtils::build_handshake_response_packet( ObClientMysqlResp *handshake, - ObClientReuqestInfo *info, + ObClientRequestInfo *info, ObMIOBuffer *handshake_resp_buf) { int ret = OB_SUCCESS; @@ -485,6 +525,45 @@ int ObClientUtils::build_handshake_response_packet( return ret; } +const ObString& ObClientRequestInfo::get_password() +{ + int ret = OB_SUCCESS; + uint64_t global_version = get_global_proxy_config_table_processor().get_config_version(); + if (!cluster_name_.empty() && password_version_ != global_version && user_name_.prefix_case_match(ObProxyTableInfo::READ_ONLY_USERNAME)) { + ObConfigItem item; + ObVipAddr addr; + password_.reset(); + if (OB_FAIL(get_global_config_processor().get_proxy_config( + addr, cluster_name_, "", ObProxyTableInfo::OBSERVER_SYS_PASSWORD, item))) { + LOG_WARN("get observer_sys_password config failed", K_(cluster_name), K(ret)); + } else if (40 == strlen(item.str())) { + MEMCPY(password0_.ptr(), item.str(), strlen(item.str())); + password_ = password0_; + } else { + memset(password0_.ptr(), 0, password0_.length()); + } + + using_password_num_ = 0; + + if (OB_SUCC(ret)) { + if (OB_FAIL(get_global_config_processor().get_proxy_config( + addr, cluster_name_, "", ObProxyTableInfo::OBSERVER_SYS_PASSWORD1, item))) { + LOG_WARN("get observer_sys_password1 config failed", K_(cluster_name), K(ret)); + } else if (40 == strlen(item.str())) { + MEMCPY(password1_.ptr(), item.str(), strlen(item.str())); + } else { + memset(password1_.ptr(), 0, sizeof(password1_.length())); + } + } + if (OB_SUCC(ret)) { + password_version_ = global_version; + } + LOG_DEBUG("get new password success", K(password0_), K(password1_)); + } + + return password_; +} + } // end of namespace proxy } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/proxy/client/ob_client_utils.h b/src/obproxy/proxy/client/ob_client_utils.h index a8aa347a21bc6e66699df46a1b497efbd2a37bab..bd281ddbfed3ef4c6cdb5e1da540f1ee6e98015b 100644 --- a/src/obproxy/proxy/client/ob_client_utils.h +++ b/src/obproxy/proxy/client/ob_client_utils.h @@ -16,6 +16,7 @@ #include "iocore/net/ob_net.h" #include "proxy/mysqllib/ob_mysql_transaction_analyzer.h" #include "proxy/mysqllib/ob_resultset_fetcher.h" +#include "utils/ob_proxy_table_define.h" namespace oceanbase { @@ -23,23 +24,50 @@ namespace obproxy { namespace proxy { +class ObMysqlClient; + +union ObClientFlags +{ + ObClientFlags() : flags_(0) {} + explicit ObClientFlags(uint32_t flag) : flags_(flag) {} + + bool is_skip_autocommit() const { return 1 == client_flags_.OB_CLIENT_SKIP_AUTOCOMMIT; } + bool is_send_request_direct() const { return 1 == client_flags_.OB_CLIENT_SEND_REQUEST_DIRECT; } + + uint32_t flags_; + struct ClinetFlags + { + uint32_t OB_CLIENT_SKIP_AUTOCOMMIT: 1; + uint32_t OB_CLIENT_SEND_REQUEST_DIRECT: 1; + uint32_t OB_CLIENT_FLAG_RESERVED_NOT_USE: 30; + } client_flags_; +}; + class ObMysqlRequestParam { public: ObMysqlRequestParam() : sql_(), is_deep_copy_(false), is_user_idc_name_set_(false), - need_print_trace_stat_(false), current_idc_name_() {}; + need_print_trace_stat_(false), current_idc_name_(), + target_addr_(), ob_client_flags_(0), mysql_client_(NULL), + is_detect_client_(false) {}; explicit ObMysqlRequestParam(const char *sql) : sql_(sql), is_deep_copy_(false), is_user_idc_name_set_(false), - need_print_trace_stat_(false), current_idc_name_() {}; + need_print_trace_stat_(false), current_idc_name_(), target_addr_(), + ob_client_flags_(0), mysql_client_(NULL), is_detect_client_(false) {}; ObMysqlRequestParam(const char *sql, const ObString &idc_name) : sql_(sql), is_deep_copy_(false), is_user_idc_name_set_(true), - need_print_trace_stat_(true), current_idc_name_(idc_name) {}; + need_print_trace_stat_(true), current_idc_name_(idc_name), target_addr_(), + ob_client_flags_(0), mysql_client_(NULL), is_detect_client_(false) {}; void reset(); void reset_sql(); + void set_target_addr(const common::ObAddr addr) { target_addr_ = addr; } + void set_mysql_client(ObMysqlClient *mysql_client) { mysql_client_ = mysql_client; } + void set_is_detect_client(const bool is_detect_client) { is_detect_client_ = is_detect_client; } bool is_valid() const { return !sql_.empty(); } int deep_copy(const ObMysqlRequestParam &other); int deep_copy_sql(const common::ObString &sql); - TO_STRING_KV(K_(sql), K_(is_deep_copy), K_(current_idc_name), K_(is_user_idc_name_set), K_(need_print_trace_stat)); + TO_STRING_KV(K_(sql), K_(is_deep_copy), K_(current_idc_name), K_(is_user_idc_name_set), + K_(need_print_trace_stat), K_(target_addr), K(ob_client_flags_.flags_), K_(is_detect_client)); common::ObString sql_; bool is_deep_copy_; @@ -47,6 +75,12 @@ public: bool need_print_trace_stat_; common::ObString current_idc_name_; char current_idc_name_buf_[OB_PROXY_MAX_IDC_NAME_LENGTH]; + common::ObAddr target_addr_; + // using flags to affect client_vc acition + // bit 1: whether set autocommit + ObClientFlags ob_client_flags_; + ObMysqlClient* mysql_client_; + bool is_detect_client_; }; class ObClientMysqlResp @@ -150,15 +184,15 @@ inline int ObMysqlResultHandler::get_double(const char *col_name, double &double return (NULL == rs_fetcher_) ? (common::OB_INNER_STAT_ERROR) : (rs_fetcher_->get_double(col_name, double_val)); } -class ObClientReuqestInfo +class ObClientRequestInfo { public: - ObClientReuqestInfo() - : user_name_(), database_name_(), password_(), + ObClientRequestInfo() + : user_name_(), database_name_(), cluster_name_(), password_(), password0_(), password1_(), using_password_num_(-1), request_param_(), name_(NULL), name_len_(0), - need_skip_stage2_(false) {} - ~ObClientReuqestInfo() { reset(); } + need_skip_stage2_(false), password_version_(0) {} + ~ObClientRequestInfo() { reset(); } void reset(); void reset_names(); @@ -170,21 +204,28 @@ public: int set_names(const common::ObString &user_name, const common::ObString &password, const common::ObString &database_name, + const common::ObString &cluster_name, const common::ObString &password1 = ""); int set_request_param(const ObMysqlRequestParam &request_param); const common::ObString &get_user_name() const { return user_name_; } const common::ObString &get_database_name() const { return database_name_; } - const common::ObString &get_password() const { return password_; } + const common::ObString &get_password(); bool change_password() { bool bret = false; - if (using_password_num_ != -1) { + if (using_password_num_ != -1 && user_name_.prefix_case_match(ObProxyTableInfo::READ_ONLY_USERNAME)) { using_password_num_ = (using_password_num_ + 1) % 2; if (using_password_num_ == 0) { password_ = password0_; + if ('\0' == *password0_.ptr()) { + password_.reset(); + } } else { password_ = password1_; + if ('\0' == *password1_.ptr()) { + password_.reset(); + } } bret = true; } @@ -199,6 +240,7 @@ public: private: common::ObString user_name_; common::ObString database_name_; + common::ObString cluster_name_; common::ObString password_; common::ObString password0_; common::ObString password1_; @@ -207,8 +249,9 @@ private: char *name_; int64_t name_len_; bool need_skip_stage2_; + int64_t password_version_; - DISALLOW_COPY_AND_ASSIGN(ObClientReuqestInfo); + DISALLOW_COPY_AND_ASSIGN(ObClientRequestInfo); }; class ObClientUtils @@ -224,7 +267,7 @@ public: const int64_t buf_len, int64_t ©_len); static int build_handshake_response_packet(ObClientMysqlResp *handshake, - ObClientReuqestInfo *info, + ObClientRequestInfo *info, event::ObMIOBuffer *handshake_resp_buf); }; diff --git a/src/obproxy/proxy/client/ob_client_vc.cpp b/src/obproxy/proxy/client/ob_client_vc.cpp index 69c1f205f76b6c147bd4265ad29284656b712339..8c80d7c31512b4ee922a283da9ac195ba35001ec 100644 --- a/src/obproxy/proxy/client/ob_client_vc.cpp +++ b/src/obproxy/proxy/client/ob_client_vc.cpp @@ -17,12 +17,16 @@ #include "proxy/mysqllib/ob_mysql_request_builder.h" #include "proxy/mysql/ob_mysql_client_session.h" #include "obutils/ob_resource_pool_processor.h" +#include "proxy/mysql/ob_mysql_sm.h" +#include "utils/ob_proxy_table_define.h" using namespace oceanbase::common; using namespace oceanbase::obmysql; +using namespace oceanbase::obproxy; using namespace oceanbase::obproxy::event; using namespace oceanbase::obproxy::packet; using namespace oceanbase::obproxy::obutils; +using namespace oceanbase::obproxy::proxy; namespace oceanbase { @@ -37,13 +41,12 @@ enum CLIENT_MAGIC_DEAD = 0xDDCCBBAA }; -static int64_t const MYSQL_BUFFER_SIZE = BUFFER_SIZE_FOR_INDEX(BUFFER_SIZE_INDEX_8K); static int64_t const RESCHEDULE_GET_NETHANDLER_LOCK_INTERVAL = HRTIME_MSECONDS(1); // 1ms ObClientVC::ObClientVC(ObMysqlClient &client_core) : ObNetVConnection(), magic_(CLIENT_MAGIC_ALIVE), disconnect_by_client_(false), - is_request_sent_(false), is_resp_received_(false), core_client_(&client_core), - pending_action_(NULL), read_state_(), write_state_() + is_request_sent_(false), core_client_(&client_core), + pending_action_(NULL), read_state_(), write_state_(), addr_() { SET_HANDLER(&ObClientVC::main_handler); } @@ -81,9 +84,8 @@ int ObClientVC::main_handler(int event, void *data) } case CLIENT_INFORM_MYSQL_CLIENT_TRANSFER_RESP_EVENT: { pending_action_ = NULL; - // notify ObMysqlClient to read mysql response - if (NULL != core_client_) { - core_client_->handle_event(VC_EVENT_READ_READY, &write_state_.vio_); + if (OB_FAIL(transfer_bytes())) { + LOG_ERROR("fail to transfer bytes", K(ret)); } break; } @@ -176,7 +178,6 @@ void ObClientVC::do_io_close(const int lerrno) } is_request_sent_ = false; - is_resp_received_ = false; if (NULL != core_client_ && !disconnect_by_client_) { core_client_->handle_event(CLIENT_VC_DISCONNECT_EVENT, NULL); @@ -194,26 +195,28 @@ void ObClientVC::reenable_re(ObVIO *vio) read_avail = reader->read_avail(); } _LOG_DEBUG("client_vc reenable_re %s, read_avail=%ld, reader=%p, thread=%p, " - "is_request_sent=%d, is_resp_received=%d", + "is_request_sent=%d", (ObVIO::WRITE == vio->op_) ? "Write" : "Read", read_avail, - reader, this_ethread(), is_request_sent_, is_resp_received_); + reader, this_ethread(), is_request_sent_); if (ObVIO::WRITE == vio->op_) { // write_vio - if (NULL != core_client_) { - if (read_avail > 0 && !is_resp_received_) { - int ret = OB_SUCCESS; - if (OB_ISNULL(pending_action_ = mutex_->thread_holding_->schedule_imm( - this, CLIENT_INFORM_MYSQL_CLIENT_TRANSFER_RESP_EVENT))) { - ret = OB_ERR_UNEXPECTED; - LOG_ERROR("fail to schedule imm", K(ret)); - } else { - is_resp_received_ = true; - } + if (NULL != core_client_ && NULL == pending_action_ && read_avail > 0) { + int ret = OB_SUCCESS; + if (OB_ISNULL(pending_action_ = mutex_->thread_holding_->schedule_imm( + this, CLIENT_INFORM_MYSQL_CLIENT_TRANSFER_RESP_EVENT))) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("fail to schedule imm", K(ret)); } } } else if (ObVIO::READ == vio->op_) { // read_vio if (NULL != read_state_.vio_.cont_) { if (!is_request_sent_) { + if (addr_.is_valid()) { + ObMysqlSM *sm = reinterpret_cast(read_state_.vio_.cont_); + sm->trans_state_.server_info_.set_addr(net::ops_ip_sa_cast(addr_.get_sockaddr())); + sm->trans_state_.force_retry_congested_ = true; + sm->trans_state_.need_retry_ = false; + } // notify client session to read mysql request read_state_.vio_.cont_->handle_event(VC_EVENT_READ_READY, &read_state_.vio_); is_request_sent_ = true; @@ -223,10 +226,59 @@ void ObClientVC::reenable_re(ObVIO *vio) } } +int ObClientVC::transfer_bytes() +{ + int ret = OB_SUCCESS; + + // Check the state of our write buffer as well as ntodo + ObVIO &vio = write_state_.vio_; + int64_t ntodo = vio.ntodo(); + ObIOBufferReader *reader = vio.get_reader(); + if (OB_ISNULL(reader)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to get reader", K(ret)); + } else { + int64_t bytes_avail = reader->read_avail(); + int64_t act_on = MIN(bytes_avail, ntodo); + int64_t total_added = 0; + ObMIOBuffer *transfer_to = core_client_->get_client_buf(); + + if (act_on <= 0) { + ret = OB_INVALID_ARGUMENT; + _LOG_WARN("act on data can not <= 0, avail=%ld, ntodo=%ld, " + "act_on=%ld, ret=%d", bytes_avail, ntodo, act_on, ret); + } else if (OB_ISNULL(transfer_to)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("resp buffer can not be NULL", K(transfer_to), K(ret)); + } else if (OB_FAIL(transfer_to->write(reader, act_on, total_added, 0)) + || act_on != total_added) { + LOG_WARN("failed to transfer data from iobuffer reader to iobfer", + K(act_on), K(total_added), K(ret)); + } else if (OB_FAIL(reader->consume(total_added))) { + LOG_WARN("fail to consume", K(total_added), K(ret)); + } else { + vio.ndone_ += total_added; + LOG_DEBUG("transfer_bytes succ", "ndone", vio.ndone_, "nbytes", vio.nbytes_); + if (write_state_.vio_.ntodo() > 0) { + if (NULL != write_state_.vio_.cont_) { + write_state_.vio_.cont_->handle_event(VC_EVENT_WRITE_READY, &write_state_.vio_); + } + } else { + // notify ObMysqlClient to read mysql response + if (NULL != core_client_) { + core_client_->handle_event(VC_EVENT_READ_READY, &write_state_.vio_); + } + } + } + } + + return ret; +} + ObMysqlClient::ObMysqlClient() : ObContinuation(), magic_(CLIENT_MAGIC_ALIVE), reentrancy_count_(0), terminate_(false), is_inited_(false), in_use_(false), is_request_complete_(false), use_short_connection_(false), - client_vc_(NULL), pool_(NULL), + client_vc_(NULL), pool_(NULL), cr_(NULL), active_timeout_action_(NULL), common_mutex_(), action_(), active_timeout_ms_(0), next_action_(CLIENT_ACTION_UNDEFINED), request_buf_(NULL), request_reader_(NULL), mysql_resp_(NULL), info_(), is_session_pool_client_(false), @@ -240,6 +292,7 @@ int ObMysqlClient::init(ObMysqlClientPool *pool, const ObString &password, const ObString &database, const bool is_meta_mysql_client, + const ObString &cluster_name, const ObString &password1, ClientPoolOption* client_pool_option) { @@ -254,8 +307,8 @@ int ObMysqlClient::init(ObMysqlClientPool *pool, } else if (OB_ISNULL(mutex = new_proxy_mutex(CLIENT_VC_LOCK))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to allocate mutex", K(ret)); - } else if (OB_FAIL(info_.set_names(user_name, password, database, password1))) { - LOG_WARN("fail to set names", K(user_name), K(password), K(database), K(ret)); + } else if (OB_FAIL(info_.set_names(user_name, password, database, cluster_name, password1))) { + LOG_WARN("fail to set names", K(user_name), K(password), K(database), K(cluster_name), K(ret)); } else { if (client_pool_option != NULL) { info_.set_need_skip_stage2(client_pool_option->need_skip_stage2_); @@ -274,6 +327,31 @@ int ObMysqlClient::init(ObMysqlClientPool *pool, return ret; } +int ObMysqlClient::init_detect_client(ObClusterResource *cr) +{ + int ret = OB_SUCCESS; + ObProxyMutex *mutex = NULL; + ObString password(get_global_proxy_config().observer_sys_password.str()); + if (OB_UNLIKELY(is_inited_ ||NULL == cr)) { + ret = OB_INIT_TWICE; + LOG_WARN("init twice", K_(is_inited), K(ret)); + } else if (OB_ISNULL(mutex = new_proxy_mutex(CLIENT_VC_LOCK))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to allocate mutex", K(ret)); + } else if (OB_FAIL(info_.set_names(ObProxyTableInfo::DETECT_USERNAME_USER, password, "obproxy", "obproxy"))) { + LOG_WARN("fail to set names", K(ret)); + } else { + common_mutex_ = mutex; + mutex_ = common_mutex_; + next_action_ = CLIENT_ACTION_CONNECT; + cr->inc_ref(); + cr_ = cr; + is_inited_ = true; + use_short_connection_ = true; + } + return ret; +} + int ObMysqlClient::post_request( ObContinuation *cont, const ObMysqlRequestParam &request_param, @@ -370,7 +448,7 @@ int ObMysqlClient::post_request( mysql_resp_ = NULL; } action = NULL; - release(); + release(false); } return ret; @@ -431,12 +509,7 @@ int ObMysqlClient::main_handler(int event, void *data) } } - --reentrancy_count_; - if (OB_UNLIKELY(reentrancy_count_ < 0)) { - LOG_ERROR("invalid reentrancy_count", K_(reentrancy_count), K(this)); - } - - if (0 == reentrancy_count_) { + if (1 == reentrancy_count_) { // here common_mutex_ is free or held by this thread, so we can ensure lock it MUTEX_LOCK(lock, common_mutex_, this_ethread()); if (OB_SUCCESS == ret && need_connect_retry_ && CLIENT_ACTION_CONNECT == next_action_) { @@ -457,19 +530,35 @@ int ObMysqlClient::main_handler(int event, void *data) if (OB_SUCC(ret)) { do_post_request(); } + + --reentrancy_count_; + if (OB_UNLIKELY(reentrancy_count_ < 0)) { + LOG_ERROR("invalid reentrancy_count", K_(reentrancy_count), K(this)); + } } else { if (is_request_complete_) { if (OB_FAIL(handle_request_complete())) { LOG_WARN("fail to handle request complete", K(ret)); } - } + } if (terminate_) { kill_this(); he_ret = EVENT_DONE; + } else { + --reentrancy_count_; + if (OB_UNLIKELY(reentrancy_count_ < 0)) { + LOG_ERROR("invalid reentrancy_count", K_(reentrancy_count), K(this)); + } } } + } else { + --reentrancy_count_; + if (OB_UNLIKELY(reentrancy_count_ < 0)) { + LOG_ERROR("invalid reentrancy_count", K_(reentrancy_count), K(this)); + } } + return he_ret; } @@ -529,7 +618,7 @@ int ObMysqlClient::handle_request_complete() } } - release(); + release(true); if (need_callback) { cont->handle_event(CLIENT_TRANSPORT_MYSQL_RESP_EVENT, mysql_resp); } @@ -657,7 +746,7 @@ int ObMysqlClient::do_post_request() } case CLIENT_ACTION_READ_NORMAL_RESP: { if (OB_FAIL(setup_read_normal_resp())) { - LOG_WARN("fail to setup read handshake", K(ret)); + LOG_WARN("fail to setup read normal resp", K(ret)); } else if (OB_FAIL(schedule_active_timeout())) { LOG_WARN("fail to schedule_active_timeout", K(ret)); } else if (OB_FAIL(forward_mysql_request())) { @@ -715,7 +804,9 @@ int ObMysqlClient::do_next_action(void *data) break; } case CLIENT_ACTION_READ_LOGIN_RESP: { - if (OB_FAIL(transfer_and_analyze_response(vio, OB_MYSQL_COM_LOGIN))) { + if (info_.get_request_param().is_detect_client_) { + is_request_complete_ = true; + } else if (OB_FAIL(transfer_and_analyze_response(vio, OB_MYSQL_COM_LOGIN))) { LOG_WARN("fail to transfer and analyze resposne", K(ret)); } else if (!mysql_resp_->is_resp_completed()) { ret = OB_ERR_UNEXPECTED; @@ -727,6 +818,12 @@ int ObMysqlClient::do_next_action(void *data) if (OB_FAIL(transport_mysql_resp())) { LOG_WARN("fail to transfrom mysql resp", K(ret)); } + } else if (info_.get_request_param().ob_client_flags_.is_skip_autocommit()) { + if (OB_FAIL(setup_read_normal_resp())) { + LOG_WARN("fail to setup read normal resp", K(ret)); + } else if (OB_FAIL(forward_mysql_request())) { + LOG_WARN("fail to schedule post request", K(ret)); + } } else { retry_times_ = 0; if (OB_FAIL(setup_read_autocommit_resp())) { @@ -789,61 +886,19 @@ int ObMysqlClient::do_next_action(void *data) int ObMysqlClient::transfer_and_analyze_response(ObVIO &vio, const obmysql::ObMySQLCmd cmd) { int ret = OB_SUCCESS; - // Check the state of our write buffer as well as ntodo - int64_t ntodo = vio.ntodo(); - ObIOBufferReader *reader = vio.get_reader(); - if (OB_ISNULL(reader)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("fail to get reader", K(ret)); - } else { - int64_t bytes_avail = reader->read_avail(); - int64_t act_on = MIN(bytes_avail, ntodo); - int64_t added = 0; - ObMIOBuffer *transfer_to = mysql_resp_->get_resp_miobuf(); - if (act_on <= 0) { - ret = OB_INVALID_ARGUMENT; - _LOG_WARN("act on data can not <= 0, avail=%ld, ntodo=%ld, " - "act_on=%ld, ret=%d", bytes_avail, ntodo, act_on, ret); - } else if (OB_ISNULL(transfer_to)) { + if (vio.ndone_ == vio.nbytes_) { + LOG_DEBUG("transfer_and_analyze_response"); + if (OB_FAIL(mysql_resp_->analyze_resp(cmd))) { + LOG_WARN("fail to analyze_trans_response", K(ret)); + } else if (!mysql_resp_->is_resp_completed()) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("resp buffer can not be NULL", K(transfer_to), K(ret)); - } else if (OB_FAIL(transfer_bytes(*transfer_to, *reader, act_on, added))) { - LOG_WARN("fail to transfer_bytes", K(ret)); - } else { - vio.ndone_ += added; - LOG_DEBUG("transfer_bytes succ", "ndone", vio.ndone_, "nbytes", vio.nbytes_); - if (vio.ndone_ == vio.nbytes_) { - LOG_DEBUG("transder_and_analyze_response", K(added)); - if (OB_FAIL(mysql_resp_->analyze_resp(cmd))) { - LOG_WARN("fail to analyze_trans_response", K(ret)); - } else if (!mysql_resp_->is_resp_completed()) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("mysql response must be received completed here", K(ret)); - } - } else { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("ndone should be equal to nbytes", - K_(vio.ndone), K_(vio.nbytes), K(ret)); - } + LOG_WARN("mysql response must be received completed here", K(ret)); } - } - - return ret; -} - -int ObMysqlClient::transfer_bytes(ObMIOBuffer &transfer_to, - ObIOBufferReader &transfer_from, - const int64_t act_on, int64_t &total_added) -{ - int ret = OB_SUCCESS; - - if (OB_FAIL(transfer_to.write(&transfer_from, act_on, total_added, 0)) - || act_on != total_added) { - LOG_WARN("failed to transfer data from iobuffer reader to iobfer", - K(act_on), K(total_added), K(ret)); - } else if (OB_FAIL(transfer_from.consume(total_added))) { - LOG_WARN("fail to consume", K(total_added), K(ret)); + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("ndone should be equal to nbytes", + K_(vio.ndone), K_(vio.nbytes), K(ret)); } return ret; @@ -852,10 +907,10 @@ int ObMysqlClient::transfer_bytes(ObMIOBuffer &transfer_to, int ObMysqlClient::forward_mysql_request() { int ret = OB_SUCCESS; + client_vc_->set_addr(info_.get_request_param().target_addr_); if (request_reader_->read_avail() > 0) { client_vc_->clear_request_sent(); - client_vc_->clear_resp_received(); client_vc_->reenable_read(); } @@ -1001,7 +1056,13 @@ int ObMysqlClient::do_new_connection_with_cr(ObMysqlClientSession *client_sessio { int ret = OB_SUCCESS; - ObClusterResource *cr = pool_->acquire_cluster_resource(); // inc ref + ObClusterResource *cr = NULL; + if (NULL != cr_) { + cr_->inc_ref(); + cr = cr_; + } else { + cr = pool_->acquire_cluster_resource(); // inc ref + } LOG_DEBUG("new connection", K(cr), KPC(cr)); if (OB_ISNULL(cr)) { ret = OB_ERR_UNEXPECTED; @@ -1030,6 +1091,10 @@ int ObMysqlClient::setup_read_handshake() } else { client_vc_->mutex_ = mutex_; client_session->set_proxy_mysql_client(); + if (info_.get_request_param().ob_client_flags_.is_send_request_direct()) { + client_session->set_can_send_request(); + client_session->is_need_update_dummy_entry_ = true; + } client_session->set_session_pool_client(is_session_pool_client_); if (is_session_pool_client_) { // client_session->set_is_dbmesh_user(false); @@ -1039,10 +1104,9 @@ int ObMysqlClient::setup_read_handshake() client_session->set_server_addr(server_addr_); client_session->set_first_dml_sql_got(); client_session->inner_request_param_ = &info_.get_request_param(); - client_vc_->clear_resp_received(); next_action_ = CLIENT_ACTION_READ_HANDSHAKE; - if (pool_->is_cluster_param()) { + if ((NULL != pool_ && pool_->is_cluster_param()) || NULL != cr_) { if (OB_FAIL(do_new_connection_with_cr(client_session))) { LOG_WARN("fail to new connection with cr", K(ret)); } @@ -1070,9 +1134,9 @@ int ObMysqlClient::setup_read_handshake() return ret; } -void ObMysqlClient::release() +void ObMysqlClient::release(bool is_need_check_reentry) { - if (OB_LIKELY(0 == reentrancy_count_) && OB_LIKELY(!terminate_)) { + if (OB_LIKELY(!is_need_check_reentry || 1 == reentrancy_count_) && OB_LIKELY(!terminate_)) { int ret = OB_SUCCESS; if (OB_FAIL(cancel_active_timeout())) { LOG_ERROR("fail to cancel timeout action," @@ -1080,9 +1144,11 @@ void ObMysqlClient::release() } else { // for defense, make sure client vc's mutex is common mutex when release to client pool; // Never free client vc in mysql client, it will be free by mysql_sm - if (NULL != client_vc_ && client_vc_->mutex_ != common_mutex_) { + if (!info_.get_request_param().is_detect_client_ && NULL != client_vc_ && client_vc_->mutex_ != common_mutex_) { client_vc_->handle_event(CLIENT_VC_SWAP_MUTEX_EVENT, common_mutex_.ptr_); - client_vc_->mutex_ = common_mutex_; + if (NULL != client_vc_) { + client_vc_->mutex_ = common_mutex_; + } } action_.set_continuation(NULL); action_.cancelled_ = false; @@ -1092,7 +1158,9 @@ void ObMysqlClient::release() in_use_ = false; is_request_complete_ = false; mutex_ = common_mutex_; // when idle, keep common_mutex_ - pool_->release_mysql_client(this); + if (NULL != pool_) { + pool_->release_mysql_client(this); + } } } } @@ -1121,6 +1189,11 @@ void ObMysqlClient::kill_this() pool_ = NULL; } + if (NULL != cr_) { + cr_->dec_ref(); + cr_ = NULL; + } + is_inited_ = false; in_use_ = false; use_short_connection_ = false; @@ -1147,7 +1220,7 @@ void ObMysqlClient::kill_this() int ObMysqlClient::alloc(ObMysqlClientPool *pool, ObMysqlClient *&client, const ObString &user_name, const ObString &password, - const ObString &database, const bool is_meta_mysql_client, + const ObString &database, const bool is_meta_mysql_client, const ObString &cluster_name, const ObString &password1, ClientPoolOption* client_pool_option) { int ret = OB_SUCCESS; @@ -1155,7 +1228,7 @@ int ObMysqlClient::alloc(ObMysqlClientPool *pool, ObMysqlClient *&client, if (OB_ISNULL(client = op_alloc(ObMysqlClient))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to allocate ObMysqlClient", K(ret)); - } else if (OB_FAIL(client->init(pool, user_name, password, database, is_meta_mysql_client, password1, client_pool_option))) { + } else if (OB_FAIL(client->init(pool, user_name, password, database, is_meta_mysql_client, cluster_name, password1, client_pool_option))) { LOG_WARN("fail to init client", K(ret)); } if (OB_FAIL(ret) && (NULL != client)) { diff --git a/src/obproxy/proxy/client/ob_client_vc.h b/src/obproxy/proxy/client/ob_client_vc.h index 4e0d981c308f387d7d528f01a618567c6f138d73..1956032317c75628ae23bc18d8b2460ad865cdde 100644 --- a/src/obproxy/proxy/client/ob_client_vc.h +++ b/src/obproxy/proxy/client/ob_client_vc.h @@ -80,6 +80,7 @@ public: virtual void reenable(event::ObVIO *vio) { reenable_re(vio); } virtual void reenable_re(event::ObVIO *vio); void reenable_read() { reenable_re(&read_state_.vio_); } + int transfer_bytes(); // Timeouts virtual int set_active_timeout(ObHRTime timeout_in) { UNUSED(timeout_in); return 0; } @@ -101,18 +102,18 @@ public: virtual int apply_options() { return 0; } void clear_request_sent() { is_request_sent_ = false; } - void clear_resp_received() { is_resp_received_ = false; } + void set_addr(const common::ObAddr &addr) { addr_ = addr; } private: uint32_t magic_; bool disconnect_by_client_; // dissconnect by received VC_EVENT_EOS, sent by ObMysqlClient bool is_request_sent_; // used to inform client session read request only once - bool is_resp_received_; // used to inform mysql client read resp onely once ObMysqlClient *core_client_; event::ObAction *pending_action_; ObClientVCState read_state_; ObClientVCState write_state_; + common::ObAddr addr_; DISALLOW_COPY_AND_ASSIGN(ObClientVC); }; @@ -140,6 +141,7 @@ public: const common::ObString &password, const common::ObString &database, const bool is_meta_mysql_client, + const common::ObString &cluster_name = "", const common::ObString &password1 = "", ClientPoolOption* client_pool_option = NULL); @@ -148,9 +150,12 @@ public: const common::ObString &password, const common::ObString &database, const bool is_meta_mysql_client, + const common::ObString &cluster_name = "", const common::ObString &password1 = "", ClientPoolOption* client_pool_option = NULL); + int init_detect_client(obutils::ObClusterResource *cr); + // must be used under the mutex_'s lock bool is_avail() const { return !in_use_; } @@ -165,6 +170,8 @@ public: static const char *get_client_event_name(const int64_t event); event::ObProxyMutex *get_common_mutex() { return common_mutex_.ptr_; } + void kill_this(); + event::ObMIOBuffer *get_client_buf() { return mysql_resp_->get_resp_miobuf(); } private: static const char *get_client_action_name(const ObClientActionType type); @@ -172,8 +179,6 @@ private: int do_post_request(); int do_next_action(void *data); int transfer_and_analyze_response(event::ObVIO &vio, const obmysql::ObMySQLCmd cmd); - int transfer_bytes(event::ObMIOBuffer &transfer_to, event::ObIOBufferReader &transfer_from, - const int64_t act_on, int64_t &added); int notify_transfer_completed(); @@ -185,7 +190,6 @@ private: int setup_read_normal_resp(); bool is_in_auth() const; int transport_mysql_resp(); - void kill_this(); int handle_client_vc_disconnect(); int forward_mysql_request(); @@ -194,7 +198,7 @@ private: int handle_active_timeout(); int handle_request_complete(); - void release(); + void release(bool is_need_check_reentry); public: SLINK(ObMysqlClient, link_); @@ -213,6 +217,8 @@ private: bool use_short_connection_; ObClientVC *client_vc_; ObMysqlClientPool *pool_; + // in some situtaion, we can create obmysql client without ClientPool + obutils::ObClusterResource *cr_; event::ObAction *active_timeout_action_; common::ObPtr common_mutex_; @@ -225,7 +231,7 @@ private: event::ObIOBufferReader *request_reader_; ObClientMysqlResp *mysql_resp_; - ObClientReuqestInfo info_; + ObClientRequestInfo info_; bool is_session_pool_client_; ObProxySchemaKey schema_key_; diff --git a/src/obproxy/proxy/client/ob_driver_client.cpp b/src/obproxy/proxy/client/ob_driver_client.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29d1711fda6317d9a0cc9d6be41627614f7bad28 --- /dev/null +++ b/src/obproxy/proxy/client/ob_driver_client.cpp @@ -0,0 +1,375 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * + * ************************************************************* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "proxy/client/ob_driver_client.h" +#include "proxy/mysql/ob_mysql_client_session.h" +#include "iocore/eventsystem/ob_action.h" +#include "iocore/net/ob_socket_manager.h" + +using namespace oceanbase::common; +using namespace oceanbase::obproxy::event; +using namespace oceanbase::obproxy::net; + +#define SET_NONBLOCKING(fd) { \ + int tmp_ret = OB_SUCCESS; \ + int flags = fcntl(fd, F_GETFL); \ + int res = -1; \ + flags |= O_NONBLOCK; \ + if (OB_SUCCESS != (tmp_ret = ObSocketManager::fcntl(fd, F_SETFL, flags, res))) { \ + OBPROXY_DRIVER_CLIENT_LOG(WARN, "fail to set nonblocking", K(tmp_ret), K(errno), K(strerror(errno))); \ + if (OB_SUCCESS == ret) { \ + ret = tmp_ret; \ + } \ + } \ +} + +#define SET_BLOCKING(fd) { \ + int tmp_ret = OB_SUCCESS; \ + int flags = fcntl(fd, F_GETFL); \ + int res = -1; \ + flags &= ~O_NONBLOCK; \ + if (OB_SUCCESS != (tmp_ret = ObSocketManager::fcntl(fd, F_SETFL, flags, res))) { \ + OBPROXY_DRIVER_CLIENT_LOG(WARN, "fail to set blocking", K(ret), K(errno), K(strerror(errno))); \ + if (OB_SUCCESS == ret) { \ + ret = tmp_ret; \ + } \ + } \ +} + +namespace oceanbase +{ +namespace obproxy +{ +namespace proxy +{ + +ObDriverClient::ObDriverClient() : is_inited_(false), unix_fd_(-1), connect_timeout_(0), recv_timeout_(0), send_timeout_(0), cs_id_(-1) +{ +} + +ObDriverClient::~ObDriverClient() +{ + destroy(); +} + +void ObDriverClient::destroy() +{ + is_inited_ = false; + if (unix_fd_ != -1) { + close(unix_fd_); + unix_fd_ = -1; + } + connect_timeout_ = 0; + send_timeout_ = 0; + recv_timeout_ = 0; + cs_id_ = -1; +} + +int ObDriverClient::init() +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(is_inited_)) { + ret = OB_INIT_TWICE; + OBPROXY_DRIVER_CLIENT_LOG(WARN, "driver client init twice", K(this), K(ret)); + } else if (OB_FAIL(ObSocketManager::socket(AF_UNIX, SOCK_STREAM, 0, unix_fd_))) { + OBPROXY_DRIVER_CLIENT_LOG(ERROR, "dirver client create socket failed", K(this), K(ret)); + } else { + OBPROXY_DRIVER_CLIENT_LOG(DEBUG, "init driver client", K(this), K_(cs_id)); + is_inited_ = true; + } + return ret; +} + +int ObDriverClient::sync_connect() +{ + int ret = OB_SUCCESS; + struct sockaddr_un addr; + addr.sun_family = AF_UNIX; + memset(addr.sun_path, 0, sizeof(addr.sun_path)); + strncpy(addr.sun_path, get_global_layout().get_unix_domain_path(), sizeof(addr.sun_path) - 1); + if (OB_FAIL(ObSocketManager::connect(unix_fd_, (struct sockaddr*)&addr, sizeof(addr)))) { + OBPROXY_DRIVER_CLIENT_LOG(WARN, "driver client connect unix domain failed", K(this), K(errno), K(ret)); + } else { + OBPROXY_DRIVER_CLIENT_LOG(DEBUG, "driver client connect success" , K(this)); + } + return ret; +} + +int ObDriverClient::sync_connect_with_timeout() +{ + int ret = OB_SUCCESS; + if (connect_timeout_ < 0) { + ret = OB_ERR_UNEXPECTED; + OBPROXY_DRIVER_CLIENT_LOG(WARN, "connect timeout value unexpected", K(connect_timeout_), K(ret)); + } else if (connect_timeout_ == 0) { + ret = sync_connect(); + } else { + int64_t timeout = connect_timeout_; + struct sockaddr_un addr; + addr.sun_family = AF_UNIX; + memset(addr.sun_path, 0, sizeof(addr.sun_path)); + strncpy(addr.sun_path, get_global_layout().get_unix_domain_path(), sizeof(addr.sun_path) - 1); + SET_NONBLOCKING(unix_fd_); + + int connect_rv = 0; + while (OB_SUCC(ret)) { + connect_rv = connect(unix_fd_, (struct sockaddr*)&addr, sizeof(addr)); + if (connect_rv < 0) { + int64_t prev_time = get_current_time(); + if (errno != EINPROGRESS && errno != EWOULDBLOCK && errno != EAGAIN) { + ret = ob_get_sys_errno(); + OBPROXY_DRIVER_CLIENT_LOG(WARN, "connect failed", K(ret)); + } else if (errno == EWOULDBLOCK || errno == EAGAIN) { + // The unix socket encounters the above socket sleep 1ms to prevent it from being called all the time. + // Refer to https://stackoverflow.com/questions/48222690/set-connect-timeout-on-unix-domain-socket + usleep(1000); + int64_t new_time = get_current_time(); + timeout -= (new_time - prev_time); + prev_time = new_time; + if (timeout <= 0) { + ret = OB_TIMEOUT; + OBPROXY_DRIVER_CLIENT_LOG(WARN ,"connect timeout", K_(connect_timeout), K(ret)); + } + } else if (errno == EINPROGRESS) { + while (OB_SUCC(ret)) { + struct pollfd pfd; + pfd.fd = unix_fd_; + pfd.events = POLLOUT; + connect_rv = poll(&pfd, 1, static_cast(timeout)); + if (connect_rv > 0) { + break; + } else if (connect_rv == 0) { + ret = OB_TIMEOUT; + OBPROXY_DRIVER_CLIENT_LOG(WARN ,"connect timeout", K_(connect_timeout), K(ret)); + } else { + if (errno != EINTR) { + ret = ob_get_sys_errno(); + OBPROXY_DRIVER_CLIENT_LOG(WARN, "poll failed", K(ret)); + } else { + int64_t new_time = get_current_time(); + timeout -= (new_time - prev_time); + prev_time = new_time; + if (timeout <= 0) { + ret = OB_TIMEOUT; + OBPROXY_DRIVER_CLIENT_LOG(WARN ,"connect timeout", K_(connect_timeout), K(ret)); + } + } + } + } + if (OB_SUCC(ret) && connect_rv > 0) { + OBPROXY_DRIVER_CLIENT_LOG(DEBUG, "connect with timeout success", K_(connect_timeout), K(ret)); + break; + } + } + } else { + OBPROXY_DRIVER_CLIENT_LOG(DEBUG, "connect with timeout success", K_(connect_timeout), K(ret)); + break; + } + } + SET_BLOCKING(unix_fd_); + } + + return ret; +} + +int ObDriverClient::sync_recv_internal(char *buf, int64_t buf_len, int64_t &recv_len, int recv_flags) +{ + int ret = OB_SUCCESS; + + if (OB_UNLIKELY(NULL == buf || 0 >= buf_len)) { + ret = OB_ERR_UNEXPECTED; + OBPROXY_DRIVER_CLIENT_LOG(WARN, "buf is null or len is invalid", K(buf_len), K(this), K_(cs_id), K(ret)); + } else { + + do { + recv_len = recv(unix_fd_, buf, buf_len, recv_flags); + } while (recv_len == -1 && EINTR == errno); + + OBPROXY_DRIVER_CLIENT_LOG(DEBUG, "sync_recv_internal recv finish", K(recv_len), K(errno)); + + if (EAGAIN == errno || EWOULDBLOCK == errno) { + // will call this func again, do nothing + } else if (-1 == recv_len) { + ret = ob_get_sys_errno(); + OBPROXY_DRIVER_CLIENT_LOG(WARN, "recv failed", K(ret), KP(buf), K(buf_len), K(recv_len), K(recv_flags)); + } else { + // success, do nothing + } + } + + return ret; +} + +int ObDriverClient::sync_wait_io_or_timeout(bool is_recv) +{ + int ret = OB_SUCCESS; + struct pollfd pfd; + int rv = 0; + int64_t timeout = 0; + int64_t prev_time = get_current_time(); + int64_t new_time = 0; + + memset(&pfd, 0, sizeof(pfd)); + pfd.fd = unix_fd_; + if (is_recv) { + timeout = recv_timeout_ <= 0 ? -1 : recv_timeout_; + pfd.events = POLLIN | POLLERR; + } else { + timeout = send_timeout_ <= 0 ? -1 : send_timeout_; + pfd.events = POLLOUT; + } + + OBPROXY_DRIVER_CLIENT_LOG(DEBUG, "sync_wait_io_or_timeout call poll", K(is_recv), K(timeout)); + + do { + // Prevent continuous interruptions, resulting in waiting + if (timeout > 0) { + new_time = get_current_time(); + timeout -= new_time - prev_time; + if (timeout < 0) { + timeout = 0; + } + prev_time = new_time; + } + rv = poll(&pfd, 1, static_cast(timeout)); + } while (rv == -1 && errno == EINTR); + + if (rv < 0) { + ret = ob_get_sys_errno(); + OBPROXY_DRIVER_CLIENT_LOG(WARN, "poll error", K(ret)); + } else if (rv == 0) { + ret = OB_TIMEOUT; + OBPROXY_DRIVER_CLIENT_LOG(WARN, "poll timeout", K(timeout), K(ret)); + } else { + // recv >= 0 , do nothing + } + + return ret; +} + +int ObDriverClient::sync_recv_with_timeout(char *buf, int64_t buf_len, int64_t &recv_len) +{ + int ret = OB_SUCCESS; + + if (OB_UNLIKELY(NULL == buf || 0 >= buf_len)) { + ret = OB_ERR_UNEXPECTED; + OBPROXY_DRIVER_CLIENT_LOG(WARN, "buf is null or len is invalid", K(buf_len), K(this), K_(cs_id), K(ret)); + } else { + int recv_flags= MSG_DONTWAIT; + recv_len = -1; + + while (OB_SUCC(ret) && -1 == recv_len) { + if (OB_FAIL(sync_recv_internal(buf, buf_len, recv_len, recv_flags))) { + OBPROXY_DRIVER_CLIENT_LOG(WARN, "fail to call sync_recv_internal", K(buf_len), K(recv_len), K(ret)); + } else if (-1 == recv_len && OB_FAIL(sync_wait_io_or_timeout(true))) { + OBPROXY_DRIVER_CLIENT_LOG(WARN, "fail to call sync_wait_io_or_timeout", K(ret)); + } else { + // do nothing + } + } + + if (OB_FAIL(ret)) { + OBPROXY_DRIVER_CLIENT_LOG(WARN, "driver client recv failed", K(this), K(recv_len), K(recv_flags), K_(cs_id), K_(unix_fd), K(ret)); + } + + } + + return ret; +} + +int ObDriverClient::sync_send_internal(const char *buf, int64_t buf_len, int64_t &send_len, int send_flags) +{ + int ret = OB_SUCCESS; + + if (OB_UNLIKELY(NULL == buf || 0 >= buf_len)) { + ret = OB_ERR_UNEXPECTED; + OBPROXY_DRIVER_CLIENT_LOG(WARN, "buf is null or len is invalid", K(buf_len), K(this), K_(cs_id), K(ret)); + } else { + + do { + send_len = send(unix_fd_, buf, buf_len, send_flags); + } while (send_len == -1 && EINTR == errno); + + OBPROXY_DRIVER_CLIENT_LOG(DEBUG, "sync_send_internal send finish", K(send_len), K(errno)); + + if (EAGAIN == errno || EWOULDBLOCK == errno) { + // will call this func again, do nothing + } else if (-1 == send_len) { + ret = ob_get_sys_errno(); + OBPROXY_DRIVER_CLIENT_LOG(WARN, "send failed", K(ret), KP(buf), K(buf_len), K(send_len), K(send_flags)); + } else { + // success, do nothing + } + } + + return ret; +} + +int ObDriverClient::sync_send_with_timeout(const char *buf, int64_t buf_len, int64_t &send_len) +{ + int ret = OB_SUCCESS; + + if (OB_UNLIKELY(NULL == buf || 0 >= buf_len)) { + ret = OB_ERR_UNEXPECTED; + OBPROXY_DRIVER_CLIENT_LOG(WARN, "buf is null or len is invalid", K(buf_len), K(this), K_(cs_id), K(ret)); + } else { + int send_flags = MSG_DONTWAIT | MSG_NOSIGNAL; + send_len = -1; + + while (OB_SUCC(ret) && -1 == send_len) { + if (OB_FAIL(sync_send_internal(buf, buf_len, send_len, send_flags))) { + OBPROXY_DRIVER_CLIENT_LOG(WARN, "fail to call sync_send_internal", K(buf_len), K(send_len), K(ret)); + } else if (-1 == send_len && OB_FAIL(sync_wait_io_or_timeout(false))) { + OBPROXY_DRIVER_CLIENT_LOG(WARN, "fail to call sync_wait_io_or_timeout", K(ret)); + } else { + // do nothing + } + } + + if (OB_FAIL(ret)) { + OBPROXY_DRIVER_CLIENT_LOG(WARN, "driver client send failed", K(this), K(send_len), K(send_flags), K_(cs_id), K_(unix_fd), K(ret)); + } + + } + + return ret; +} + +int64_t ObDriverClient::get_current_time() +{ + timeval tv; + gettimeofday(&tv, NULL); + int64_t current_time = tv.tv_sec * 1000 + tv.tv_usec / 1000; + return current_time; +} + +} // end of proxy +} // end of obproxy +} // end of oceanbase diff --git a/src/obproxy/proxy/client/ob_driver_client.h b/src/obproxy/proxy/client/ob_driver_client.h new file mode 100644 index 0000000000000000000000000000000000000000..0e345c4639bdf8ce157f2015ed7f632f22fb587d --- /dev/null +++ b/src/obproxy/proxy/client/ob_driver_client.h @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * + * ************************************************************* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OB_DRIVER_CLIENT_H_ +#define OB_DRIVER_CLIENT_H_ + +#include "proxy/client/ob_client_utils.h" +#include "iocore/net/ob_net_vconnection.h" +#include "iocore/eventsystem/ob_ethread.h" + +namespace oceanbase +{ +namespace obproxy +{ +namespace proxy +{ + +class ObDriverClient +{ +public: + ObDriverClient(); + virtual ~ObDriverClient(); + int init(); + int sync_connect(); + int sync_connect_with_timeout(); + int sync_recv_with_timeout(char *buf, int64_t buf_len, int64_t &recv_len); + int sync_send_with_timeout(const char *buf, int64_t buf_len, int64_t &send_len); + inline void set_connect_timeout(const int64_t timeout) { connect_timeout_ = timeout; } + inline void set_cs_id(const int64_t cs_id) { cs_id_ = cs_id; } + void destroy(); + + int64_t get_connect_timeout() const { return connect_timeout_; } + int64_t get_recv_timeout() const { return recv_timeout_; } + void set_recv_timeout(const int64_t timeout) { recv_timeout_ = timeout; } + int64_t get_send_timeout() const { return send_timeout_; } + void set_send_timeout(const int64_t timeout) { send_timeout_ = timeout; } + +private: + inline int64_t get_current_time(); + int sync_recv_internal(char *buf, int64_t buf_len, int64_t &recv_len, int recv_flags); + int sync_send_internal(const char *buf, int64_t buf_len, int64_t &send_len, int send_flags); + int sync_wait_io_or_timeout(bool is_recv); + +private: + bool is_inited_; + int unix_fd_; + int64_t connect_timeout_; + int64_t recv_timeout_; + int64_t send_timeout_; + int64_t cs_id_; +private: +DISALLOW_COPY_AND_ASSIGN(ObDriverClient); +}; + +} // end of namespace proxy +} // end of namespace obproxy +} // end of namespace oceanbase + +#endif diff --git a/src/obproxy/proxy/client/ob_mysql_client_pool.cpp b/src/obproxy/proxy/client/ob_mysql_client_pool.cpp index 99ba5d7bff84ea414171426a29251af8ff80fc21..423b2904f48eba2976b4a627c73f30014db84496 100644 --- a/src/obproxy/proxy/client/ob_mysql_client_pool.cpp +++ b/src/obproxy/proxy/client/ob_mysql_client_pool.cpp @@ -158,6 +158,7 @@ int ObMysqlClientPool::init( const ObString &user_name, const ObString &password, const ObString &database, + const ObString &cluster_name, const ObString &password1, ClientPoolOption* client_pool_option) { @@ -175,7 +176,8 @@ int ObMysqlClientPool::init( ObMysqlClient *mysql_client = NULL; const int64_t mc_count = get_mysql_client_pool_count(is_meta_mysql_client); for (int64_t i = 0; (i < mc_count && OB_SUCC(ret)); ++i) { - if (OB_FAIL(ObMysqlClient::alloc(this, mysql_client, user_name, password, database, is_meta_mysql_client, password1, client_pool_option))) { + if (OB_FAIL(ObMysqlClient::alloc(this, mysql_client, user_name, password, database, is_meta_mysql_client, + cluster_name, password1, client_pool_option))) { LOG_WARN("fail to alloc mysql client", K(user_name), K(password), K(database), "idx", i, K(is_meta_mysql_client), K(ret)); } else if (OB_ISNULL(mysql_client)) { diff --git a/src/obproxy/proxy/client/ob_mysql_client_pool.h b/src/obproxy/proxy/client/ob_mysql_client_pool.h index 3e5e9b3366506610bdc7d69d8a7fb7f8b532c890..e02f2719267a840329fd3860b5e861dda2188618 100644 --- a/src/obproxy/proxy/client/ob_mysql_client_pool.h +++ b/src/obproxy/proxy/client/ob_mysql_client_pool.h @@ -52,6 +52,7 @@ public: const common::ObString &user_name, const common::ObString &password, const common::ObString &database, + const common::ObString &cluster_name = "", const common::ObString &password1 = "", ClientPoolOption* client_pool_option = NULL); void destroy(); diff --git a/src/obproxy/proxy/client/ob_mysql_proxy.cpp b/src/obproxy/proxy/client/ob_mysql_proxy.cpp index a3a40e97ea7315b7f98969c8de47b94569dd396c..97b40250d45dd3b6ad5ef62b245c9b69513d0533 100644 --- a/src/obproxy/proxy/client/ob_mysql_proxy.cpp +++ b/src/obproxy/proxy/client/ob_mysql_proxy.cpp @@ -173,7 +173,7 @@ int ObMysqlProxyCont::async_post_request(const ObMysqlRequestParam &request_para action = NULL; if (OB_UNLIKELY(!request_param.is_valid()) || OB_UNLIKELY(timeout_ms <= 0) - || OB_ISNULL(client_pool)) { + || (!request_param.is_detect_client_ && OB_ISNULL(client_pool))) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid input value", K(request_param), K(timeout_ms), K(ret)); } else if (OB_FAIL(request_param_.deep_copy(request_param))) { @@ -181,8 +181,10 @@ int ObMysqlProxyCont::async_post_request(const ObMysqlRequestParam &request_para } else { is_nonblock_ = true; timeout_ms_ = timeout_ms; - client_pool->inc_ref(); - client_pool_ = client_pool; + if (NULL != client_pool) { + client_pool->inc_ref(); + client_pool_ = client_pool; + } } if (OB_SUCC(ret)) { @@ -322,7 +324,13 @@ int ObMysqlProxyCont::do_post_request() if (OB_SUCC(ret)) { ret = OB_EAGAIN; if (NULL == mysql_client_) { - mysql_client_ = client_pool_->acquire_mysql_client(); + // For probing requests, in order to prevent competition for connection pool connections, + // use a separate mysql_client + if (NULL != request_param_.mysql_client_) { + mysql_client_ = request_param_.mysql_client_; + } else { + mysql_client_ = client_pool_->acquire_mysql_client(); + } } if (NULL != mysql_client_) { ObAction *action = NULL; @@ -463,6 +471,7 @@ int ObMysqlProxy::init(const int64_t timeout_ms, const ObString &user_name, const ObString &password, const ObString &database, + const ObString &cluster_name, const ObString &password1) { int ret = OB_SUCCESS; @@ -472,7 +481,7 @@ int ObMysqlProxy::init(const int64_t timeout_ms, } else if (OB_UNLIKELY(timeout_ms <= 0)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid input value", K(timeout_ms), K(ret)); - } else if (OB_FAIL(raw_mysql_client_.init(user_name, password, database, password1))) { + } else if (OB_FAIL(raw_mysql_client_.init(user_name, password, database, cluster_name, password1))) { LOG_WARN("fail to init raw mysql client", K(ret)); } else { timeout_ms_ = timeout_ms; @@ -500,7 +509,7 @@ int ObMysqlProxy::rebuild_client_pool(ObShardConnector *shard_conn, ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid input value", K(user_name)); } else { - if (OB_FAIL(alloc_client_pool(is_meta_mysql_client, user_name, password, database, password1, client_pool_option))) { + if (OB_FAIL(alloc_client_pool(is_meta_mysql_client, user_name, password, database, "", password1, client_pool_option))) { LOG_WARN("fail to alloc client pool", K(is_meta_mysql_client), K(user_name), K(database), K(ret)); } else { client_pool_->set_shard_conn(shard_conn); @@ -539,7 +548,7 @@ int ObMysqlProxy::rebuild_client_pool(ObClusterResource *cluster_resource, } else { ObString full_username(full_user_name); if (OB_FAIL(alloc_client_pool(is_meta_mysql_client, full_username, - password, database, password1, client_pool_option))) { + password, database, cluster_name, password1, client_pool_option))) { LOG_WARN("fail to alloc client pool", K(user_name), K(database), K(ret)); } else { client_pool_->set_cluster_resource(cluster_resource); @@ -584,6 +593,12 @@ int ObMysqlProxy::async_write(ObContinuation *cont, const char *sql, ObAction *& return async_execute(cont, request_param, timeout_ms_, action); } +int ObMysqlProxy::async_read(event::ObContinuation *cont, const ObMysqlRequestParam &request_param, + event::ObAction *&action, const int64_t timeout_ms) +{ + return async_execute(cont, request_param, timeout_ms, action); +} + int ObMysqlProxy::async_read(event::ObContinuation *cont, const ObMysqlRequestParam &request_param, event::ObAction *&action) { return async_execute(cont, request_param, timeout_ms_, action); @@ -607,7 +622,7 @@ int ObMysqlProxy::async_execute(ObContinuation *cont, LOG_DEBUG("ObMysqlProxy::async_execute", K(cont), K(request_param), K(timeout_ms), K(ret)); ObMysqlProxyCont *mp_cont = NULL; ObMysqlClientPool *pool = NULL; - if (OB_ISNULL(pool = acquire_client_pool())) { + if (!request_param.is_detect_client_ && OB_ISNULL(pool = acquire_client_pool())) { ret = OB_ENTRY_NOT_EXIST; LOG_WARN("client pool is null", K(ret)); } else { @@ -819,6 +834,7 @@ int ObMysqlProxy::alloc_client_pool(const bool is_meta_mysql_client, const ObString &user_name, const ObString &password, const ObString &database, + const ObString &cluster_name, const ObString &password1, ClientPoolOption* client_pool_option) { @@ -833,7 +849,7 @@ int ObMysqlProxy::alloc_client_pool(const bool is_meta_mysql_client, } else if (FALSE_IT(client_pool->inc_ref())) { // will dec_ref in destroy() } else if (OB_FAIL(client_pool->init(is_meta_mysql_client, user_name, - password, database, password1, client_pool_option))) { + password, database, cluster_name, password1, client_pool_option))) { LOG_WARN("fail to init client pool", K(user_name), K(password), K(database), K(is_meta_mysql_client), K(ret)); } else { @@ -845,14 +861,14 @@ int ObMysqlProxy::alloc_client_pool(const bool is_meta_mysql_client, client_pool_ = client_pool; // update raw mysql client info - ObClientReuqestInfo &info = raw_mysql_client_.get_request_info(); + ObClientRequestInfo &info = raw_mysql_client_.get_request_info(); info.reset_names(); bool need_skip_stage2 = false; if (client_pool_option) { need_skip_stage2 = client_pool_option->need_skip_stage2_; } info.set_need_skip_stage2(need_skip_stage2); - if (OB_FAIL(info.set_names(user_name, password, database))) { + if (OB_FAIL(info.set_names(user_name, password, database, cluster_name))) { LOG_WARN("fail to set raw mysql client request info", K(ret)); } } diff --git a/src/obproxy/proxy/client/ob_mysql_proxy.h b/src/obproxy/proxy/client/ob_mysql_proxy.h index 811fcab89ab1431d8ace545915e03b5c48ec56d3..f671d55facc3e2ec4c4cdf91492acc395c6f7421 100644 --- a/src/obproxy/proxy/client/ob_mysql_proxy.h +++ b/src/obproxy/proxy/client/ob_mysql_proxy.h @@ -57,6 +57,7 @@ public: const common::ObString &user_name, const common::ObString &password, const common::ObString &database, + const common::ObString &cluster_name = "", const common::ObString &password1 = ""); bool is_inited() const { return is_inited_; } void destroy(); @@ -93,6 +94,8 @@ public: // Attention!! async_read or async_write must be called by ObEThread int async_read(event::ObContinuation *cont, const char *sql, event::ObAction *&action); int async_read(event::ObContinuation *cont, const ObMysqlRequestParam &request_param, event::ObAction *&action); + int async_read(event::ObContinuation *cont, const ObMysqlRequestParam &request_param, + event::ObAction *&action, const int64_t timeout_ms); int async_write(event::ObContinuation *cont, const char *sql, event::ObAction *&action); // raw execute related @@ -114,6 +117,7 @@ private: const common::ObString &user_name, const common::ObString &password, const common::ObString &database, + const common::ObString &cluster_name = "", const common::ObString &password1 = "", ClientPoolOption* client_pool_option = NULL); public: diff --git a/src/obproxy/proxy/client/ob_raw_mysql_client.cpp b/src/obproxy/proxy/client/ob_raw_mysql_client.cpp index 8bdbb5896d45814b1d81a762e5163d2f2e47e9a9..08614b884e7e0ffb41f2d855fbbecc59fe1ea4bd 100644 --- a/src/obproxy/proxy/client/ob_raw_mysql_client.cpp +++ b/src/obproxy/proxy/client/ob_raw_mysql_client.cpp @@ -39,7 +39,7 @@ ObRawMysqlClientActor::ObRawMysqlClientActor() addr_(), request_buf_(NULL), request_reader_(NULL) {} -int ObRawMysqlClientActor::init(ObClientReuqestInfo &info) +int ObRawMysqlClientActor::init(ObClientRequestInfo &info) { int ret = OB_SUCCESS; if (OB_UNLIKELY(is_inited_)) { @@ -149,7 +149,7 @@ int ObRawMysqlClientActor::connect(const ObAddr &addr, const int64_t timeout_ms) options.f_blocking_ = true; // blocking read or send ObIpEndpoint ip; - ops_ip_copy(ip.sa_, addr.get_ipv4(), static_cast(addr.get_port())); + ip.assign(addr.get_sockaddr()); if (OB_FAIL(con_.open(options))) { LOG_WARN("fail to open connection", K(ret)); } else if (OB_FAIL(con_.connect(ip.sa_, options))) { @@ -401,6 +401,7 @@ int ObRawMysqlClientActor::read_response(const ObMySQLCmd cmd) int ObRawMysqlClient::init(const ObString &user_name, const ObString &password, const ObString &database, + const ObString &cluster_name, const ObString &password1) { int ret = OB_SUCCESS; @@ -412,7 +413,7 @@ int ObRawMysqlClient::init(const ObString &user_name, LOG_WARN("init twice", K_(is_inited), K(ret)); } else if (OB_FAIL(mutex_init(&mutex_))) { LOG_WARN("fail to init mutex", K(ret)); - } else if (OB_FAIL(info_.set_names(user_name, password, database, password1))) { + } else if (OB_FAIL(info_.set_names(user_name, password, database, cluster_name, password1))) { LOG_WARN("fail to set names", K(user_name), K(password), K(password1), K(database), K(ret)); int tmp_ret = OB_SUCCESS; if (OB_SUCCESS != (tmp_ret = mutex_destroy(&mutex_))) { diff --git a/src/obproxy/proxy/client/ob_raw_mysql_client.h b/src/obproxy/proxy/client/ob_raw_mysql_client.h index 37ff9a54bc27b85da4912023822f2bd8474e42c5..f489aa1070549676b37815b83c2e71998fcdb32c 100644 --- a/src/obproxy/proxy/client/ob_raw_mysql_client.h +++ b/src/obproxy/proxy/client/ob_raw_mysql_client.h @@ -33,7 +33,7 @@ public: ObRawMysqlClientActor(); ~ObRawMysqlClientActor() { destroy(); } - int init(ObClientReuqestInfo &info); + int init(ObClientRequestInfo &info); int sync_raw_execute(const char *sql, const int64_t timeout_ms, ObClientMysqlResp *&resp); void reset() { destroy(); } bool is_avail() { return is_avail_; } @@ -51,7 +51,7 @@ private: private: bool is_inited_; bool is_avail_; - ObClientReuqestInfo *info_; + ObClientRequestInfo *info_; ObClientMysqlResp *resp_; net::ObConnection con_; common::ObAddr addr_; @@ -82,13 +82,14 @@ public: int init(const common::ObString &user_name, const common::ObString &password, const common::ObString &database, + const common::ObString &cluster_name, const common::ObString &password1 = ""); int sync_raw_execute(const char *sql, const int64_t timeout_ms, ObClientMysqlResp *&resp); int set_server_addr(const common::ObIArray &addrs); int set_target_server(const common::ObIArray &replicas); - ObClientReuqestInfo &get_request_info() { return info_; } + ObClientRequestInfo &get_request_info() { return info_; } int disconnect(); void destroy(); @@ -98,7 +99,7 @@ public: private: static const int64_t DEFAULT_SERVER_ADDRS_COUNT = 3; bool is_inited_; - ObClientReuqestInfo info_; + ObClientRequestInfo info_; ObProxyReplicaLocation target_server_[DEFAULT_SERVER_ADDRS_COUNT]; ObRawMysqlClientActor actor_; ObMutex mutex_; diff --git a/src/obproxy/proxy/mysql/ob_mysql_client_session.cpp b/src/obproxy/proxy/mysql/ob_mysql_client_session.cpp index fcea98f760c270c3572abd4aa7942e69f4bb0e93..aae717e13d162fc7bc1c6124559a6ecda484d247 100644 --- a/src/obproxy/proxy/mysql/ob_mysql_client_session.cpp +++ b/src/obproxy/proxy/mysql/ob_mysql_client_session.cpp @@ -21,7 +21,8 @@ #include "prometheus/ob_sql_prometheus.h" #include "dbconfig/ob_proxy_pb_utils.h" #include "proxy/mysql/ob_mysql_global_session_manager.h" -#include "omt/ob_resource_unit_table_processor.h" +#include "omt/ob_conn_table_processor.h" +#include "omt/ob_white_list_table_processor.h" using namespace oceanbase::common; using namespace oceanbase::common::hash; @@ -62,22 +63,24 @@ ObMutex g_debug_cs_list_mutex; #endif ObMysqlClientSession::ObMysqlClientSession() - : can_direct_ok_(false), is_proxy_mysql_client_(false), active_(false), test_server_addr_(), + : can_direct_ok_(false), is_proxy_mysql_client_(false), can_direct_send_request_(false), + active_(false), test_server_addr_(), vc_ready_killed_(false), is_waiting_trans_first_request_(false), is_need_send_trace_info_(true), is_already_send_trace_info_(false), - is_first_handle_close_request_(true), is_in_trans_for_close_request_(false), - is_need_return_last_bound_ss_(false), - need_delete_cluster_(false), is_first_dml_sql_got_(false), + is_first_handle_request_(true), is_in_trans_for_close_request_(false), is_last_request_in_trans_(false), + is_trans_internal_routing_(false), is_need_return_last_bound_ss_(false), need_delete_cluster_(false), + is_first_dml_sql_got_(false), is_proxy_enable_trans_internal_routing_(false), compressed_seq_(0), cluster_resource_(NULL), dummy_entry_(NULL), is_need_update_dummy_entry_(false), - dummy_ldc_(), dummy_entry_valid_time_ns_(0), server_state_version_(0), + dummy_ldc_(), dummy_entry_valid_time_ns_(0), server_state_version_(0), inner_request_param_(NULL), tcp_init_cwnd_set_(false), half_close_(false), conn_decrease_(false), conn_prometheus_decrease_(false), vip_connection_decrease_(false), magic_(MYSQL_CS_MAGIC_DEAD), create_thread_(NULL), is_local_connection_(false), client_vc_(NULL), in_list_stat_(LIST_INIT), current_tid_(-1), - cs_id_(0), proxy_sessid_(0), bound_ss_(NULL), cur_ss_(NULL), lii_ss_(NULL), last_bound_ss_(NULL), read_buffer_(NULL), + cs_id_(0), proxy_sessid_(0), bound_ss_(NULL), cur_ss_(NULL), lii_ss_(NULL), last_bound_ss_(NULL), + trans_coordinator_ss_addr_(), read_buffer_(NULL), buffer_reader_(NULL), mysql_sm_(NULL), read_state_(MCS_INIT), ka_vio_(NULL), server_ka_vio_(NULL), trace_stats_(NULL), select_plan_(NULL), - ps_id_(0), cursor_id_(CURSOR_ID_START), text_ps_cache_(), using_ldg_(false) + ps_id_(0), cursor_id_(CURSOR_ID_START), using_ldg_(false) { SET_HANDLER(&ObMysqlClientSession::main_handler); bool enable_session_pool = get_global_proxy_config().is_pool_mode @@ -130,7 +133,7 @@ void ObMysqlClientSession::destroy() // here need place before session_info_.destroy, because use some session_info's data if (conn_prometheus_decrease_) { - SESSION_PROMETHEUS_STAT(session_info_, PROMETHEUS_CURRENT_SESSION, true, -1); + SESSION_PROMETHEUS_STAT(session_info_, PROMETHEUS_CURRENT_SESSION, true, -1); SESSION_PROMETHEUS_STAT(session_info_, PROMETHEUS_USED_CONNECTIONS, -1); conn_prometheus_decrease_ = false; } @@ -142,7 +145,6 @@ void ObMysqlClientSession::destroy() test_server_addr_.reset(); session_info_.destroy(); // destroy ps_cache after destroy session, because client session info hold ps entry pointer - text_ps_cache_.destroy(); if (NULL != trace_stats_) { trace_stats_->destory(); trace_stats_ = NULL; @@ -155,14 +157,19 @@ void ObMysqlClientSession::destroy() is_need_send_trace_info_ = true; is_already_send_trace_info_ = false; - is_first_handle_close_request_ = true; + is_first_handle_request_ = true; is_in_trans_for_close_request_ = false; + is_last_request_in_trans_ = false; + is_trans_internal_routing_ = false; is_need_return_last_bound_ss_ = false; is_first_dml_sql_got_ = false; - + is_proxy_enable_trans_internal_routing_ = false; + compressed_seq_ = 0; + trans_coordinator_ss_addr_.reset(); schema_key_.reset(); ObProxyClientSession::cleanup(); create_thread_ = NULL; + using_ldg_ = false; op_reclaim_free(this); } @@ -181,7 +188,7 @@ inline void ObMysqlClientSession::decrease_used_connections() session_info_.get_tenant_name(tenant_name); } - get_global_resource_unit_table_processor().dec_conn( + get_global_conn_table_processor().dec_conn( cluster_name, tenant_name, ip_name); } @@ -368,15 +375,22 @@ int ObMysqlClientSession::new_connection( if (OB_FAIL(fetch_tenant_by_vip())) { PROXY_CS_LOG(WARN, "fail to fetch tenant by vip", K(ret)); ret = OB_SUCCESS; - } else { - session_info_.set_is_read_only_user(ct_info_.vip_tenant_.is_read_only()); - session_info_.set_is_request_follower_user(ct_info_.vip_tenant_.is_request_follower()); - session_info_.set_vip_addr_name(ct_info_.vip_tenant_.vip_addr_.addr_); + } else if (is_vip_lookup_success()) { + ObString user_name; + if (!get_global_white_list_table_processor().can_ip_pass( + ct_info_.vip_tenant_.cluster_name_, ct_info_.vip_tenant_.tenant_name_, + user_name, client_vc_->get_real_client_addr())) { + ret = OB_ERR_CAN_NOT_PASS_WHITELIST; + PROXY_CS_LOG(DEBUG, "can not pass white_list", K(ct_info_.vip_tenant_.cluster_name_), + K(ct_info_.vip_tenant_.tenant_name_), K(client_addr), K(ret)); + } } } // 2. handle_new_connection no matter convert vip to tenant result. - handle_new_connection(); + if (OB_SUCC(ret)) { + handle_new_connection(); + } } } // end if (OB_SUCC(ret)) } else { @@ -395,15 +409,30 @@ int ObMysqlClientSession::new_connection( int ObMysqlClientSession::fetch_tenant_by_vip() { int ret = OB_SUCCESS; - if (OB_FAIL(get_global_vip_tenant_processor().get_vip_tenant(ct_info_.vip_tenant_))) { - //if login succ latter, we will desc cache miss stat. - MYSQL_SSN_INCREMENT_DYN_STAT(VIP_TO_TENANT_CACHE_MISS); - ct_info_.lookup_success_ = false; - PROXY_CS_LOG(INFO, "fail to get_vip_tenant", "vip_tenant", ct_info_.vip_tenant_, K(ret)); - } else { - MYSQL_SSN_INCREMENT_DYN_STAT(VIP_TO_TENANT_CACHE_HIT); - ct_info_.lookup_success_ = true; - PROXY_CS_LOG(DEBUG, "succ to get_vip_tenant name", "vip_tenant", ct_info_.vip_tenant_); + ct_info_.lookup_success_ = false; + ObVipAddr addr = ct_info_.vip_tenant_.vip_addr_; + ObConfigItem tenant_item, cluster_item; + bool found = false; + if (OB_FAIL(get_global_config_processor().get_proxy_config_with_level( + addr, "", "", "proxy_tenant_name", tenant_item, "LEVEL_VIP", found))) { + PROXY_CS_LOG(WARN, "get proxy tenant name config failed", K(addr), K(ret)); + } + + if (OB_SUCC(ret) && found) { + if (OB_FAIL(get_global_config_processor().get_proxy_config_with_level( + addr, "", "", "rootservice_cluster_name", cluster_item, "LEVEL_VIP", found))) { + PROXY_CS_LOG(WARN, "get cluster name config failed", K(addr), K(ret)); + } + } + + if (OB_SUCC(ret) && found) { + if (OB_FAIL(ct_info_.vip_tenant_.set_tenant_cluster(tenant_item.str(), cluster_item.str()))) { + PROXY_CS_LOG(WARN, "set tenant and cluster name failed", K(tenant_item), K(cluster_item), K(ret)); + } else { + session_info_.set_vip_addr_name(addr.addr_); + ct_info_.lookup_success_ = true; + PROXY_CS_LOG(DEBUG, "succ to get conn info", "vip_tenant", ct_info_.vip_tenant_); + } } return ret; } @@ -411,24 +440,9 @@ int ObMysqlClientSession::fetch_tenant_by_vip() int ObMysqlClientSession::get_vip_addr() { int ret = OB_SUCCESS; - int32_t ip; - int32_t port; int64_t vid; - if (OB_UNLIKELY(obutils::get_global_proxy_config().enable_qa_mode)) { - // simulate pulic cloud SLB IP addr - ObAddr addr; - if (OB_FAIL(addr.parse_from_cstring(get_global_proxy_config().qa_mode_mock_public_cloud_slb_addr))) { - PROXY_CS_LOG(WARN, "parse from string failed", K(ret)); - } else { - ct_info_.vip_tenant_.vip_addr_.set(addr.get_ipv4(), addr.get_port(), - get_global_proxy_config().qa_mode_mock_public_cloud_vid); - } - } else { - ip = ntohl(client_vc_->get_virtual_ip()); - port = static_cast(client_vc_->get_virtual_port()); - vid = static_cast(client_vc_->get_virtual_vid()); - ct_info_.vip_tenant_.vip_addr_.set(ip, port, vid); - } + vid = static_cast(client_vc_->get_virtual_vid()); + ct_info_.vip_tenant_.vip_addr_.set(client_vc_->get_virtual_addr(), vid); // TODO, get client ip, slb ip from kernal @@ -580,6 +594,7 @@ int ObMysqlClientSession::create_scramble() uint64_t ObMysqlClientSession::get_next_proxy_sessid() { + // TODO: Consider IPv6 support static uint64_t next_proxy_sessid = 1; const ObAddr &addr = get_global_hot_upgrade_info().local_addr_; int64_t ipv4 = static_cast(addr.get_ipv4()); @@ -634,9 +649,13 @@ void ObMysqlClientSession::do_io_shutdown(const ShutdownHowToType howto) void ObMysqlClientSession::do_io_close(const int alerrno) { + PROXY_SS_LOG(INFO, "client session do_io_close", K(*this), KP(client_vc_), KP(this)); int ret = OB_SUCCESS; // Prevent double closing if (MCS_CLOSED != read_state_) { + if (NULL != mysql_sm_) { + mysql_sm_->set_detect_server_info(mysql_sm_->trans_state_.server_info_.addr_, -1, 0); + } if (MCS_ACTIVE_READER == read_state_) { if (LIST_ADDED == in_list_stat_ || is_proxy_mysql_client_) { MYSQL_DECREMENT_DYN_STAT(CURRENT_CLIENT_TRANSACTIONS); @@ -796,6 +815,8 @@ int ObMysqlClientSession::state_server_keep_alive(int event, void *data) case VC_EVENT_READ_READY: case VC_EVENT_EOS: // The server session closed or something is amiss + case VC_EVENT_DETECT_SERVER_DEAD: + // find server dead case VC_EVENT_ACTIVE_TIMEOUT: case VC_EVENT_INACTIVITY_TIMEOUT: @@ -860,7 +881,8 @@ int ObMysqlClientSession::state_keep_alive(int event, void *data) // fallthrough case VC_EVENT_ERROR: case VC_EVENT_ACTIVE_TIMEOUT: - case VC_EVENT_INACTIVITY_TIMEOUT: { + case VC_EVENT_INACTIVITY_TIMEOUT: + case VC_EVENT_DETECT_SERVER_DEAD: { if (MCS_HALF_CLOSED == read_state_) { half_close_ = false; } @@ -960,7 +982,8 @@ int ObMysqlClientSession::attach_server_session(ObMysqlServerSession *session) || OB_UNLIKELY(0 != session->get_reader()->read_avail()) || OB_UNLIKELY(session->get_netvc() == client_vc_)) { ret = OB_INVALID_ARGUMENT; - PROXY_CS_LOG(WARN, "invalid server session", K(session), K(client_vc_), K(bound_ss_), K(ret)); + PROXY_CS_LOG(WARN, "invalid server session", K(bound_ss_), K(session), K(cur_ss_), + K(session->get_reader()->read_avail()), K(session->get_netvc()), K(client_vc_)); } else { session->state_ = MSS_KA_CLIENT_SLAVE; bound_ss_ = session; @@ -1406,7 +1429,8 @@ bool ObMysqlClientSession::is_authorised_proxysys(const ObProxyLoginUserType typ int ret = OB_SUCCESS; //1.check ip - if (!get_global_proxy_config().skip_proxy_sys_private_check + if (RUN_MODE_PROXY == g_run_mode + && !get_global_proxy_config().skip_proxy_sys_private_check && !ops_is_ip_private(client_vc_->get_remote_addr()) && !ops_is_ip_loopback(client_vc_->get_remote_addr())) { char src_ip[INET6_ADDRSTRLEN]; @@ -1458,7 +1482,9 @@ bool ObMysqlClientSession::is_authorised_proxysys(const ObProxyLoginUserType typ bool ObMysqlClientSession::is_need_convert_vip_to_tname() { - return (get_global_proxy_config().need_convert_vip_to_tname && !this->is_proxy_mysql_client_ ); + return (get_global_proxy_config().need_convert_vip_to_tname + && !this->is_proxy_mysql_client_ + && RUN_MODE_PROXY == g_run_mode); } inline bool ObMysqlClientSession::need_close() const @@ -1531,9 +1557,8 @@ ObString ObMysqlClientSession::get_current_idc_name() const //if empty, return default empty ret_idc = session_info_.get_idc_name(); } - } else if (OB_LIKELY(NULL != mysql_sm_) - && OB_LIKELY(NULL != mysql_sm_->trans_state_.mysql_config_params_)) { - ObString tmp_idc(mysql_sm_->trans_state_.mysql_config_params_->proxy_idc_name_); + } else if (OB_LIKELY(NULL != mysql_sm_)) { + ObString tmp_idc(mysql_sm_->proxy_idc_name_); if (!tmp_idc.empty()) { //if empty, return default empty ret_idc = tmp_idc; @@ -1610,7 +1635,7 @@ int ObMysqlClientSession::check_update_ldc() } else { need_ignore = true; } - PROXY_CS_LOG(ERROR, "fail to tryrdlock server_state_lock, ignore this update", + PROXY_CS_LOG(WARN, "fail to tryrdlock server_state_lock, ignore this update", K(err_no), "old_idc_name", dummy_ldc_.get_idc_name(), K(new_idc_name), @@ -1716,14 +1741,23 @@ int init_cs_map_for_thread() int ret = OB_SUCCESS; const int64_t event_thread_count = g_event_processor.thread_count_for_type_[ET_CALL]; for (int64_t i = 0; i < event_thread_count && OB_SUCC(ret); ++i) { - if (OB_ISNULL(g_event_processor.event_thread_[ET_CALL][i]->cs_map_ = new (std::nothrow) ObMysqlClientSessionMap())) { - ret = OB_ALLOCATE_MEMORY_FAILED; + if (OB_FAIL(init_cs_map_for_one_thread(i))) { PROXY_NET_LOG(WARN, "fail to new ObInactivityCop", K(i), K(ret)); } } return ret; } +int init_cs_map_for_one_thread(int64_t index) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(g_event_processor.event_thread_[ET_CALL][index]->cs_map_ = new (std::nothrow) ObMysqlClientSessionMap())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + PROXY_NET_LOG(WARN, "fail to new ObInactivityCop", K(index), K(ret)); + } + return ret; +} + int init_random_seed_for_thread() { int ret = OB_SUCCESS; @@ -1760,6 +1794,39 @@ int init_random_seed_for_thread() return ret; } +int init_random_seed_for_one_thread(int64_t index) +{ + int ret = OB_SUCCESS; + //1. create init random seed + ObMysqlRandom *init_seed = new (std::nothrow) ObMysqlRandom(); + if (OB_ISNULL(init_seed)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + PROXY_NET_LOG(WARN, "fail to new ObMysqlRandom", K(ret)); + } else { + const uint64_t current_time = static_cast(get_hrtime_internal()); + init_seed->init(current_time, current_time / 2); + } + + //2. create random seed of each ethread + if (OB_SUCC(ret)) { + ObMysqlRandom *tmp_random = NULL; + if (OB_ISNULL(tmp_random = new (std::nothrow) ObMysqlRandom())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + PROXY_NET_LOG(WARN, "fail to new ObMysqlRandom", K(index), K(ret)); + } else { + const uint64_t tmp = init_seed->get_uint64(); + tmp_random->init(tmp + reinterpret_cast(tmp_random), + tmp + static_cast(g_event_processor.event_thread_[ET_CALL][index]->tid_)); + g_event_processor.event_thread_[ET_CALL][index]->random_seed_ = tmp_random; + } + } + + if (OB_LIKELY(NULL != init_seed)) { + delete init_seed; + } + return ret; +} + inline bool is_proxy_conn_id_avail(const uint64_t conn_id) { bool bret = true; diff --git a/src/obproxy/proxy/mysql/ob_mysql_client_session.h b/src/obproxy/proxy/mysql/ob_mysql_client_session.h index 06013b423634ac2bef08f9c079362619c089bccf..d991d91fde8feb1d0499fb04107aac139a5c2c91 100644 --- a/src/obproxy/proxy/mysql/ob_mysql_client_session.h +++ b/src/obproxy/proxy/mysql/ob_mysql_client_session.h @@ -27,6 +27,7 @@ #include "optimizer/ob_sharding_select_log_plan.h" #include "optimizer/ob_proxy_optimizer_processor.h" #include "iocore/net/ob_unix_net_vconnection.h" +#include "ob_proxy_init.h" namespace oceanbase { @@ -107,10 +108,12 @@ public: inline ObMysqlServerSession *get_cur_server_session() const { return cur_ss_; } inline ObMysqlServerSession *get_lii_server_session() const { return lii_ss_; } inline ObMysqlServerSession *get_last_bound_server_session() const { return last_bound_ss_; } + inline net::ObIpEndpoint &get_trans_coordinator_ss_addr() { return trans_coordinator_ss_addr_; } inline void set_server_session(ObMysqlServerSession *ssession) { bound_ss_ = ssession; } inline void set_cur_server_session(ObMysqlServerSession *ssession) { cur_ss_ = ssession; } inline void set_lii_server_session(ObMysqlServerSession *ssession) { lii_ss_ = ssession; } inline void set_last_bound_server_session(ObMysqlServerSession *ssession) { last_bound_ss_ = ssession; } + inline void set_trans_coordinator_ss_addr(const sockaddr &addr) { trans_coordinator_ss_addr_.assign(addr); } bool is_hold_conn_id(const uint32_t conn_id); // Functions for manipulating api hooks @@ -133,6 +136,10 @@ public: //proxy inner mysql_client do need convert vip to tenant bool is_need_convert_vip_to_tname(); + // client cap judgement + bool is_client_support_full_link_trace() const { return session_info_.is_client_support_full_link_trace(); } + bool is_client_support_new_extra_info() const { return session_info_.is_client_support_new_extra_info(); } + int64_t get_current_tid() const { return current_tid_; } uint32_t &get_cs_id_ref() { return cs_id_; } @@ -225,6 +232,7 @@ public: void set_need_delete_cluster() { need_delete_cluster_ = true; } void set_proxy_mysql_client() { is_proxy_mysql_client_ = true; } + void set_can_send_request() { can_direct_send_request_ = true; } void set_session_pool_client(bool is_session_pool_client) { session_info_.is_session_pool_client_ = is_session_pool_client; } @@ -233,18 +241,26 @@ public: void set_first_dml_sql_got() { is_first_dml_sql_got_ = true; } bool is_first_dml_sql_got() const { return is_first_dml_sql_got_; } + uint8_t get_compressed_seq() const { return compressed_seq_; } + void set_compressed_seq(const uint8_t seq) { compressed_seq_ = seq; } + void set_need_send_trace_info(bool is_need_send_trace_info) { is_need_send_trace_info_ = is_need_send_trace_info; } bool is_need_send_trace_info() const { return is_need_send_trace_info_; } void set_already_send_trace_info(bool is_already_send_trace_info) { is_already_send_trace_info_ = is_already_send_trace_info; } bool is_already_send_trace_info() const { return is_already_send_trace_info_; } - void set_first_handle_close_request(bool is_first_handle_close_request) { is_first_handle_close_request_ = is_first_handle_close_request; } - bool is_first_handle_close_request() const { return is_first_handle_close_request_; } + void set_first_handle_request(bool is_first_handle_request) { is_first_handle_request_ = is_first_handle_request; } + bool is_first_handle_request() const { return is_first_handle_request_; } void set_in_trans_for_close_request(bool is_in_trans_for_close_request) { is_in_trans_for_close_request_ = is_in_trans_for_close_request; } bool is_in_trans_for_close_request() const { return is_in_trans_for_close_request_; } + void set_last_request_in_trans(bool is_in_trans) { is_last_request_in_trans_ = is_in_trans; } + bool is_last_request_in_trans() { return is_last_request_in_trans_; } + void set_trans_internal_routing(bool is_internal_routing) { is_trans_internal_routing_ = is_internal_routing; } + bool is_trans_internal_routing() const { return is_trans_internal_routing_; } void set_need_return_last_bound_ss(bool is_need_return_last_bound_ss) { is_need_return_last_bound_ss_ = is_need_return_last_bound_ss; } bool is_need_return_last_bound_ss() const { return is_need_return_last_bound_ss_; } - + void set_proxy_enable_trans_internal_routing(bool is_enable_internal_route) { is_proxy_enable_trans_internal_routing_ = is_enable_internal_route; } + bool is_proxy_enable_trans_internal_routing() const { return is_proxy_enable_trans_internal_routing_; } bool enable_analyze_internal_cmd() const { return session_info_.enable_analyze_internal_cmd(); } bool is_metadb_user() const { return session_info_.is_metadb_user(); } bool is_proxysys_user() const { return session_info_.is_proxysys_user(); } @@ -274,9 +290,6 @@ public: void set_can_direct_ok(bool val) { can_direct_ok_ = val; } // ps cache - ObTextPsEntry *get_text_ps_entry(const common::ObString &sql); - int add_text_ps_entry(ObTextPsEntry *entry) { return text_ps_cache_.set_text_ps_entry(entry); } - int delete_text_ps_entry(ObTextPsEntry *entry) { return text_ps_cache_.delete_text_ps_entry(entry); } uint32_t inc_and_get_ps_id() { uint32_t ps_id = ++ps_id_; if (ps_id >= (CURSOR_ID_START)) { @@ -321,6 +334,7 @@ public: bool can_direct_ok_; bool is_proxy_mysql_client_; // used for ObMysqlClient + bool can_direct_send_request_; // used for ObMysqlClient bool can_server_session_release_; //used for session release proxy::ObCommonAddr common_addr_; // session pool server_addr @@ -337,12 +351,16 @@ public: bool is_waiting_trans_first_request_; bool is_need_send_trace_info_; bool is_already_send_trace_info_; - bool is_first_handle_close_request_; + bool is_first_handle_request_; bool is_in_trans_for_close_request_; + bool is_last_request_in_trans_; + bool is_trans_internal_routing_; bool is_need_return_last_bound_ss_; bool need_delete_cluster_; bool is_first_dml_sql_got_;//default false, will route with merge status careless //it is true after user first dml sql arrived. + bool is_proxy_enable_trans_internal_routing_; // from config, update each tranasction start + uint8_t compressed_seq_; // seq management between client & proxy obutils::ObClusterResource *cluster_resource_; ObTableEntry *dummy_entry_; // __all_dummy's table location entry @@ -366,8 +384,6 @@ public: #endif private: - static const uint32_t LOCAL_IPV4_ADDR = 0x100007F; - enum ObClientReadState { MCS_INIT = 0, @@ -418,9 +434,14 @@ private: ObMysqlServerSession *lii_ss_; ObMysqlServerSession *last_bound_ss_; + // coordinator session address in transaction + net::ObIpEndpoint trans_coordinator_ss_addr_; + event::ObMIOBuffer *read_buffer_; event::ObIOBufferReader *buffer_reader_; + ObMysqlSM *mysql_sm_; + ObClientReadState read_state_; event::ObVIO *ka_vio_; @@ -437,7 +458,6 @@ private: optimizer::ObShardingSelectLogPlan *select_plan_; uint32_t ps_id_; uint32_t cursor_id_; - ObBasePsEntryCache text_ps_cache_; bool using_ldg_; private: DISALLOW_COPY_AND_ASSIGN(ObMysqlClientSession); @@ -445,11 +465,11 @@ private: inline void ObMysqlClientSession::set_local_connection() { - if (is_proxy_mysql_client_) { + if (is_proxy_mysql_client_ || RUN_MODE_CLIENT == g_run_mode) { is_local_connection_ = true; } else { if (OB_NOT_NULL(client_vc_)) { - is_local_connection_ = LOCAL_IPV4_ADDR == client_vc_->get_local_ip(); + is_local_connection_ = net::ops_is_ip_loopback(client_vc_->get_local_addr()); } } } @@ -464,30 +484,16 @@ inline uint32_t ObMysqlClientSession::get_next_ps_stmt_id() return ret; } -ObTextPsEntry *ObMysqlClientSession::get_text_ps_entry(const common::ObString &sql) -{ - int ret = OB_SUCCESS; - ObTextPsEntry *entry = NULL; - if (OB_FAIL(text_ps_cache_.get_text_ps_entry(sql, entry))) { - if (OB_HASH_NOT_EXIST != ret) { - _PROXY_LOG(WARN, "fail to get text ps entry with sql, ret =%d", ret); - } else { - _PROXY_LOG(WARN, "text ps entry not exist, ret=%d", ret); - } - } - return entry; -} - inline common::ObAddr ObMysqlClientSession::get_real_client_addr(net::ObNetVConnection *server_vc) { common::ObAddr ret_addr; - if (is_proxy_mysql_client_) { + if (is_proxy_mysql_client_ || RUN_MODE_CLIENT == g_run_mode) { if (OB_NOT_NULL(server_vc)) { - ret_addr.set_ipv4_addr(ntohl(server_vc->get_local_ip()), server_vc->get_local_port()); + ret_addr.set_sockaddr(server_vc->get_local_addr()); } } else { if (OB_NOT_NULL(client_vc_)) { - ret_addr.set_ipv4_addr(ntohl(client_vc_->get_real_client_ip()), client_vc_->get_real_client_port()); + ret_addr.set_sockaddr(client_vc_->get_real_client_addr()); } } PROXY_CS_LOG(DEBUG, "succ to get real client addr", K(ret_addr)); @@ -568,12 +574,15 @@ inline common::ObMysqlRandom &get_random_seed(const event::ObEThread &t) int init_cs_map_for_thread(); int init_random_seed_for_thread(); +int init_random_seed_for_one_thread(int64_t index); bool is_proxy_conn_id_avail(const uint64_t conn_id); bool is_server_conn_id_avail(const uint64_t conn_id); bool is_conn_id_avail(const int64_t conn_id, bool &is_proxy_generated); int extract_thread_id(const uint32_t cs_id, int64_t &thread_id); +int init_cs_map_for_one_thread(int64_t index); + } // end of namespace proxy } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/proxy/mysql/ob_mysql_debug_names.cpp b/src/obproxy/proxy/mysql/ob_mysql_debug_names.cpp index 67c56fc66e9edb57303f7a17839b5ee117a54d10..2489e507aaa7d44cf91d8a51971234afea02be1a 100644 --- a/src/obproxy/proxy/mysql/ob_mysql_debug_names.cpp +++ b/src/obproxy/proxy/mysql/ob_mysql_debug_names.cpp @@ -68,6 +68,10 @@ const char *ObMysqlDebugNames::get_event_name(const int event) ret = "VC_EVENT_ACTIVE_TIMEOUT"; break; + case VC_EVENT_DETECT_SERVER_DEAD: + ret = "VC_EVENT_DETECT_SERVER_DEAD"; + break; + case EVENT_INTERVAL: ret = "VC_EVENT_INTERVAL"; break; diff --git a/src/obproxy/proxy/mysql/ob_mysql_global_session_manager.cpp b/src/obproxy/proxy/mysql/ob_mysql_global_session_manager.cpp index cc70732bd402266e14eb94119ee86279e127b0b0..8216b465132f17a2451c11c8eefd82561513d532 100644 --- a/src/obproxy/proxy/mysql/ob_mysql_global_session_manager.cpp +++ b/src/obproxy/proxy/mysql/ob_mysql_global_session_manager.cpp @@ -81,6 +81,7 @@ int ObMysqlServerSessionList::main_handler(int event, void *data) case VC_EVENT_ERROR: case VC_EVENT_INACTIVITY_TIMEOUT: case VC_EVENT_ACTIVE_TIMEOUT: + case VC_EVENT_DETECT_SERVER_DEAD: net_vc = static_cast((static_cast(data))->vc_server_); break; @@ -1042,4 +1043,4 @@ ObMysqlContJobList& get_global_server_conn_job_list() } // end of namespace proxy } // end of namespace obproxy -} // end of namespace oceanbase \ No newline at end of file +} // end of namespace oceanbase diff --git a/src/obproxy/proxy/mysql/ob_mysql_proxy_port.cpp b/src/obproxy/proxy/mysql/ob_mysql_proxy_port.cpp index 3d602d9424d47704c8643f1c6dca78193b7c2aba..24a794a005b951bf58f6d6ed420f394dd1580dad 100644 --- a/src/obproxy/proxy/mysql/ob_mysql_proxy_port.cpp +++ b/src/obproxy/proxy/mysql/ob_mysql_proxy_port.cpp @@ -23,10 +23,16 @@ namespace obproxy { namespace proxy { -ObMysqlProxyPort &get_global_proxy_port() +ObMysqlProxyPort &get_global_proxy_ipv4_port() { - static ObMysqlProxyPort g_proxy_port; - return g_proxy_port; + static ObMysqlProxyPort g_proxy_ipv4_port; + return g_proxy_ipv4_port; +} + +ObMysqlProxyPort &get_global_proxy_ipv6_port() +{ + static ObMysqlProxyPort g_proxy_ipv6_port; + return g_proxy_ipv6_port; } void ObMysqlProxyPort::reset() diff --git a/src/obproxy/proxy/mysql/ob_mysql_proxy_port.h b/src/obproxy/proxy/mysql/ob_mysql_proxy_port.h index 45fb1afb434e92a614a88afc0d58924692c4e7e0..f94c93b9710ed26b7ecfa184334c1fa79433b9b0 100644 --- a/src/obproxy/proxy/mysql/ob_mysql_proxy_port.h +++ b/src/obproxy/proxy/mysql/ob_mysql_proxy_port.h @@ -55,7 +55,8 @@ public: net::ObIpAddr inbound_ip_; }; -ObMysqlProxyPort &get_global_proxy_port(); +ObMysqlProxyPort &get_global_proxy_ipv4_port(); +ObMysqlProxyPort &get_global_proxy_ipv6_port(); } // end of namespace proxy } // end of namespace obproxy diff --git a/src/obproxy/proxy/mysql/ob_mysql_proxy_server_main.cpp b/src/obproxy/proxy/mysql/ob_mysql_proxy_server_main.cpp index 43fb615da3a3f696923947b629115650c057c84c..59ab305f137e5434ce4ad039cd4e30abaebd90ea 100644 --- a/src/obproxy/proxy/mysql/ob_mysql_proxy_server_main.cpp +++ b/src/obproxy/proxy/mysql/ob_mysql_proxy_server_main.cpp @@ -22,9 +22,11 @@ #include "iocore/eventsystem/ob_blocking_task.h" #include "iocore/eventsystem/ob_grpc_task.h" #include "iocore/eventsystem/ob_shard_watch_task.h" +#include "iocore/eventsystem/ob_shard_scan_all_task.h" #include "obutils/ob_congestion_manager.h" #include "obutils/ob_proxy_config.h" #include "dbconfig/ob_proxy_db_config_processor.h" +#include "ob_proxy_init.h" using namespace oceanbase::common; using namespace oceanbase::obproxy::event; @@ -41,7 +43,8 @@ namespace proxy { // global acceptor, ObMysqlProxyAccept -ObMysqlProxyAcceptor g_mysql_proxy_acceptor; +ObMysqlProxyAcceptor g_mysql_proxy_ipv4_acceptor; +ObMysqlProxyAcceptor g_mysql_proxy_ipv6_acceptor; // called from ob_api.cpp int ObMysqlProxyServerMain::make_net_accept_options( @@ -105,7 +108,7 @@ int ObMysqlProxyServerMain::init_mysql_proxy_server(const ObMysqlConfigParams &c // enable reclaim mysql sm op_reclaim_sparse_opt(ObMysqlSM, ObMysqlSM::instantiate_func, ENABLE_RECLAIM, 1); - if (OB_FAIL(init_mysql_proxy_port(config_params))) { + if (RUN_MODE_PROXY == g_run_mode && OB_FAIL(init_mysql_proxy_port(config_params))) { LOG_ERROR("fail to init mysql proxy port", K(ret)); } else if (OB_FAIL(init_mysql_stats())) { LOG_ERROR("fail to init_mysql_stats", K(ret)); @@ -119,38 +122,59 @@ int ObMysqlProxyServerMain::init_mysql_proxy_server(const ObMysqlConfigParams &c } #endif - if (OB_SUCC(ret)) { + int64_t ip_mode = config_params.ip_listen_mode_; + bool enable_ipv4 = (ip_mode == 1 || ip_mode == 3); + bool enable_ipv6 = (ip_mode == 2 || ip_mode == 3); + + if (OB_SUCC(ret) && enable_ipv4) { // do the configuration defined ports if (OB_FAIL(make_mysql_proxy_acceptor(config_params, - get_global_proxy_port(), - g_mysql_proxy_acceptor))) { + get_global_proxy_ipv4_port(), + g_mysql_proxy_ipv4_acceptor))) { + LOG_ERROR("fail to make mysql proxy acceptor", K(ret)); + } + } + + if (OB_SUCC(ret) && enable_ipv6) { + if (OB_FAIL(make_mysql_proxy_acceptor(config_params, + get_global_proxy_ipv6_port(), + g_mysql_proxy_ipv6_acceptor))) { LOG_ERROR("fail to make mysql proxy acceptor", K(ret)); } } return ret; } +int ObMysqlProxyServerMain::start_mysql_proxy_acceptor() +{ + int ret = OB_SUCCESS; + int64_t ip_mode = get_global_proxy_config().ip_listen_mode; + bool enable_ipv4 = (ip_mode == 1 || ip_mode == 3); + bool enable_ipv6 = (ip_mode == 2 || ip_mode == 3); + // start accepting connections + // although we make a good pretence here, I don't believe that ObNetProcessor::main_accept() + // ever actually returns NULL. It would be useful to be able to detect errors + // and spew them here though. + if (enable_ipv4 && OB_ISNULL(g_net_processor.main_accept(*(g_mysql_proxy_ipv4_acceptor.accept_), + get_global_proxy_ipv4_port().fd_, + g_mysql_proxy_ipv4_acceptor.net_opt_))) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("fail to execute ipv4 main accept", K(ret)); + } else if (enable_ipv6 && OB_ISNULL(g_net_processor.main_accept(*(g_mysql_proxy_ipv6_acceptor.accept_), + get_global_proxy_ipv6_port().fd_, + g_mysql_proxy_ipv6_acceptor.net_opt_))) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("fail to execute ipv6 main accept", K(ret)); + } + + return ret; +} + int ObMysqlProxyServerMain::start_mysql_proxy_server(const ObMysqlConfigParams &config_params) { int ret = OB_SUCCESS; if (OB_FAIL(start_processor_threads(config_params))) { LOG_ERROR("fail to start processor threads", K(ret)); - } else if (get_global_proxy_config().enable_sharding - && !get_global_proxy_config().use_local_dbconfig - && !get_global_db_config_processor().is_config_inited() - && OB_FAIL(get_global_db_config_processor().init_sharding_config())) { - LOG_ERROR("fail to init sharding config", K(ret)); - } else { - ObMysqlProxyPort &proxy_port = get_global_proxy_port(); - // start accepting connections - // although we make a good pretence here, I don't believe that ObNetProcessor::main_accept() - // ever actually returns NULL. It would be useful to be able to detect errors - // and spew them here though. - if (OB_ISNULL(g_net_processor.main_accept(*(g_mysql_proxy_acceptor.accept_), proxy_port.fd_, - g_mysql_proxy_acceptor.net_opt_))) { - ret = OB_ERR_UNEXPECTED; - LOG_ERROR("fail to execute main accept", K(ret)); - } } return ret; } @@ -160,18 +184,20 @@ int ObMysqlProxyServerMain::start_processor_threads(const ObMysqlConfigParams &c int ret = OB_SUCCESS; int64_t stack_size = config_params.stack_size_; int64_t event_threads = config_params.work_thread_num_; + int64_t shard_scan_threads = config_params.shard_scan_thread_num_; int64_t task_threads = config_params.task_thread_num_; bool enable_cpu_topology = config_params.enable_cpu_topology_; bool automatic_match_work_thread = config_params.automatic_match_work_thread_; int64_t blocking_threads = config_params.block_thread_num_; //thread for blocking task int64_t grpc_threads = config_params.grpc_thread_num_; int64_t grpc_watch_threads = 1; + bool enable_cpu_isolate = config_params.enable_cpu_isolate_; if (OB_UNLIKELY(stack_size <= 0) || OB_UNLIKELY(event_threads <= 0) || OB_UNLIKELY(task_threads <= 0)) { ret = OB_INVALID_CONFIG; LOG_WARN("invalid variable", K(stack_size), K(event_threads), K(task_threads), K(ret)); } else if (OB_FAIL(g_event_processor.start(static_cast(event_threads), stack_size, - enable_cpu_topology, automatic_match_work_thread))) { + enable_cpu_topology, automatic_match_work_thread, enable_cpu_isolate))) { LOG_ERROR("fail to start event processor", K(stack_size), K(event_threads), K(ret)); } else if (OB_FAIL(g_net_processor.start())) { LOG_ERROR("fail to start net processor", K(ret)); @@ -186,6 +212,11 @@ int ObMysqlProxyServerMain::start_processor_threads(const ObMysqlConfigParams &c } else if (get_global_proxy_config().enable_sharding && OB_FAIL(g_shard_watch_task_processor.start(grpc_watch_threads, stack_size))) { LOG_ERROR("fail to start grpc parent task processor", K(stack_size), K(ret)); + } else if (get_global_proxy_config().enable_sharding + && OB_FAIL(g_shard_scan_all_task_processor.start(shard_scan_threads > 0 ? shard_scan_threads + : g_event_processor.thread_count_for_type_[ET_CALL] / 2, + stack_size))) { + LOG_ERROR("fail to start grpc parent task processor", K(stack_size), K(ret)); } else if (OB_FAIL(init_cs_map_for_thread())) { LOG_ERROR("fail to init cs_map for thread", K(ret)); } else if (OB_FAIL(init_table_map_for_thread())) { @@ -200,36 +231,68 @@ int ObMysqlProxyServerMain::start_processor_threads(const ObMysqlConfigParams &c LOG_ERROR("fail to init sql_table_map for thread", K(ret)); } else if (OB_FAIL(init_ps_entry_cache_for_thread())) { LOG_ERROR("fail to init ps entry cache for thread", K(ret)); + } else if (OB_FAIL(init_text_ps_entry_cache_for_thread())) { + LOG_ERROR("fail to init text ps entry cache for thread", K(ret)); } else if (OB_FAIL(init_random_seed_for_thread())) { LOG_ERROR("fail to init random seed for thread", K(ret)); } else {} return ret; } +int ObMysqlProxyServerMain::init_inherited_info(ObMysqlProxyPort &proxy_port, const int fd) +{ + int ret = OB_SUCCESS; + proxy_port.fd_ = fd; + struct sockaddr_storage sock_addr; + int64_t namelen = sizeof(sock_addr); + memset(&sock_addr, 0, namelen); + if (OB_FAIL(ObSocketManager::getsockname(proxy_port.fd_, (struct sockaddr*)(&sock_addr), &namelen))) { + LOG_ERROR("fail to get sock name", K(ret)); + } else { + // This step of conversion is mainly to obtain the port number, sockaddr_in and sockaddr_in6 port number positions are compatible + struct sockaddr_in *ain = (sockaddr_in *)&sock_addr; + proxy_port.inbound_ip_.assign(*(struct sockaddr*)(&sock_addr)); + proxy_port.port_ = static_cast((ntohs)(ain->sin_port)); + LOG_INFO("succ init mysql proxy port by inherited fd", K(proxy_port)); + } + return ret; +} + int ObMysqlProxyServerMain::init_mysql_proxy_port(const ObMysqlConfigParams &config_params) { int ret = OB_SUCCESS; - ObMysqlProxyPort &proxy_port = get_global_proxy_port(); + ObMysqlProxyPort &proxy_ipv4_port = get_global_proxy_ipv4_port(); + ObMysqlProxyPort &proxy_ipv6_port = get_global_proxy_ipv6_port(); const ObHotUpgraderInfo &info = get_global_hot_upgrade_info(); + int64_t ip_mode = config_params.ip_listen_mode_; + bool enable_ipv4 = (ip_mode == 1 || ip_mode == 3); + bool enable_ipv6 = (ip_mode == 2 || ip_mode == 3); // init from inherited fd if (info.is_inherited_) { - proxy_port.fd_ = info.fd_; - struct sockaddr sock_addr; - int64_t namelen = sizeof(sock_addr); - memset(&sock_addr, 0, namelen); - if (OB_FAIL(ObSocketManager::getsockname(proxy_port.fd_, &sock_addr , &namelen))) { - LOG_ERROR("fail to get sock name", K(ret), K(ret)); - } else { - struct sockaddr_in *ain = (sockaddr_in *)&sock_addr; - proxy_port.inbound_ip_.assign(sock_addr); - proxy_port.port_ = static_cast((ntohs)(ain->sin_port)); - LOG_INFO("succ init mysql proxy port by inherited fd", K(proxy_port)); + if (enable_ipv4) { + if (OB_FAIL(init_inherited_info(proxy_ipv4_port, info.ipv4_fd_))) { + LOG_WARN("fail to init inherited info", K(ret)); + } + } + + if (OB_SUCC(ret) && enable_ipv6) { + if (OB_FAIL(init_inherited_info(proxy_ipv6_port, info.ipv6_fd_))) { + LOG_WARN("fail to init inherited info", K(ret)); + } } } else { // init from config - proxy_port.port_ = static_cast(config_params.listen_port_); - proxy_port.inbound_ip_ = config_params.local_bound_ip_; - LOG_INFO("succ init mysql proxy port by config", K(proxy_port)); + if (enable_ipv4) { + proxy_ipv4_port.port_ = static_cast(config_params.listen_port_); + proxy_ipv4_port.inbound_ip_ = config_params.local_bound_ip_; + LOG_INFO("succ init mysql proxy ipv4 port by config", K(proxy_ipv4_port)); + } + + if (enable_ipv6) { + proxy_ipv6_port.port_ = static_cast(config_params.listen_port_); + proxy_ipv6_port.inbound_ip_ = config_params.local_bound_ipv6_ip_; + LOG_INFO("succ init mysql proxy ipv6 port by config", K(proxy_ipv6_port)); + } } return ret; } diff --git a/src/obproxy/proxy/mysql/ob_mysql_proxy_server_main.h b/src/obproxy/proxy/mysql/ob_mysql_proxy_server_main.h index f860182b6ff2465b23db5e54bf4c01bae0397807..01195d510a9cc57a859d19d42941223681f773e4 100644 --- a/src/obproxy/proxy/mysql/ob_mysql_proxy_server_main.h +++ b/src/obproxy/proxy/mysql/ob_mysql_proxy_server_main.h @@ -57,6 +57,7 @@ public: // the port data should have been created by // init_mysql_proxy_server() static int start_mysql_proxy_server(const ObMysqlConfigParams &config_params); + static int start_mysql_proxy_acceptor(); private: static int make_net_accept_options( @@ -69,6 +70,7 @@ private: static int start_processor_threads(const ObMysqlConfigParams &config_params); static int init_mysql_proxy_port(const ObMysqlConfigParams &config_params); + static int init_inherited_info(ObMysqlProxyPort &proxy_port, const int fd); }; } // end of namespace proxy diff --git a/src/obproxy/proxy/mysql/ob_mysql_server_session.cpp b/src/obproxy/proxy/mysql/ob_mysql_server_session.cpp index 051d571b107591e10a8ddac8747ade61c54cc9b1..7409bb54c02786a7cc9a9e553128a05cf2d42086 100644 --- a/src/obproxy/proxy/mysql/ob_mysql_server_session.cpp +++ b/src/obproxy/proxy/mysql/ob_mysql_server_session.cpp @@ -15,6 +15,7 @@ #include "prometheus/ob_sql_prometheus.h" #include "proxy/mysql/ob_mysql_global_session_manager.h" #include "obutils/ob_proxy_config.h" +#include "utils/ob_proxy_table_define.h" using namespace oceanbase::common; using namespace oceanbase::obproxy::event; @@ -142,7 +143,15 @@ void ObMysqlServerSession::do_io_shutdown(const ShutdownHowToType howto) void ObMysqlServerSession::do_io_close(const int alerrno) { - PROXY_SS_LOG(INFO, "server session do_io_close", K(*this), KP(server_vc_), KP(this)); + bool need_print = true; + if(NULL != client_session_ && + client_session_->get_session_info().get_priv_info().user_name_ == ObProxyTableInfo::DETECT_USERNAME_USER) { + need_print = false; + } + + if (need_print) { + PROXY_SS_LOG(INFO, "server session do_io_close", K(*this), KP(server_vc_), KP(this)); + } if (MSS_ACTIVE == state_) { MYSQL_DECREMENT_DYN_STAT(CURRENT_SERVER_TRANSACTIONS); --server_trans_stat_; @@ -174,9 +183,14 @@ void ObMysqlServerSession::do_io_close(const int alerrno) if (this == client_session_->get_last_bound_server_session()) { client_session_->set_last_bound_server_session(NULL); } - PROXY_SS_LOG(INFO, "server session is closing", K_(ss_id), K_(server_sessid), K_(server_ip), - "cs_id", client_session_->get_cs_id(), - "proxy_sessid", client_session_->get_proxy_sessid()); + if (server_ip_ == client_session_->get_trans_coordinator_ss_addr()) { + client_session_->get_trans_coordinator_ss_addr().reset(); + } + if (need_print) { + PROXY_SS_LOG(INFO, "server session is closing", K_(ss_id), K_(server_sessid), K_(server_ip), + "cs_id", client_session_->get_cs_id(), + "proxy_sessid", client_session_->get_proxy_sessid()); + } } else { PROXY_SS_LOG(INFO, "server session has not bound to client session", K(*this)); } diff --git a/src/obproxy/proxy/mysql/ob_mysql_server_session.h b/src/obproxy/proxy/mysql/ob_mysql_server_session.h index ad97ccb3ffa28308b25dbacade43df234541d98d..c3751b1f91d60cb3fb5602e74ce76d8bd5a4d46a 100644 --- a/src/obproxy/proxy/mysql/ob_mysql_server_session.h +++ b/src/obproxy/proxy/mysql/ob_mysql_server_session.h @@ -14,7 +14,6 @@ #define OBPROXY_SERVER_SESSION_H #include "iocore/net/ob_net.h" -#include "proxy/mysqllib/ob_proxy_session_info.h" #include "cmd/ob_internal_cmd_handler.h" #include "obutils/ob_proxy_json_config_info.h" #include "proxy/mysql/ob_mysql_global_session_utils.h" @@ -28,7 +27,6 @@ namespace proxy #define SERVER_ADDR_LOOKUP_EVENT_DONE INTERNAL_CMD_EVENTS_START + 3 #define UINT24_MAX (16777215U) -class ObMysqlSM; class ObMysqlClientSession; enum ObMSSState @@ -143,10 +141,12 @@ public: // cancel the inactivity timeout void cancel_inactivity_timeout(); + // server cap judgement bool is_ob_protocol_v2_supported() const { return session_info_.is_ob_protocol_v2_supported(); } bool is_checksum_supported() const { return session_info_.is_checksum_supported(); } bool is_checksum_on() const { return session_info_.is_checksum_on(); } bool is_extra_ok_packet_for_stats_enabled() const { return session_info_.is_extra_ok_packet_for_stats_enabled(); } + bool is_full_link_trace_supported() const { return session_info_.is_full_link_trace_supported(); } uint32_t get_server_sessid() const { return server_sessid_; } void set_server_sessid(const uint32_t server_sessid) { server_sessid_ = server_sessid; } diff --git a/src/obproxy/proxy/mysql/ob_mysql_session_manager.cpp b/src/obproxy/proxy/mysql/ob_mysql_session_manager.cpp index 44f4bb276014a776edf52ea57a949aff1b0c4d49..01741a120fcb2fe7164f7394ca2d6834573db391 100644 --- a/src/obproxy/proxy/mysql/ob_mysql_session_manager.cpp +++ b/src/obproxy/proxy/mysql/ob_mysql_session_manager.cpp @@ -187,6 +187,7 @@ int ObServerSessionPool::event_handler(int event, void *data) case VC_EVENT_ERROR: case VC_EVENT_INACTIVITY_TIMEOUT: case VC_EVENT_ACTIVE_TIMEOUT: + case VC_EVENT_DETECT_SERVER_DEAD: net_vc = static_cast((static_cast(data))->vc_server_); break; diff --git a/src/obproxy/proxy/mysql/ob_mysql_sm.cpp b/src/obproxy/proxy/mysql/ob_mysql_sm.cpp index 11da28076201de616d25859737bd66ce85e5825b..3297af194562afc273b8a7fe2a0cf61dde5f7b13 100644 --- a/src/obproxy/proxy/mysql/ob_mysql_sm.cpp +++ b/src/obproxy/proxy/mysql/ob_mysql_sm.cpp @@ -50,6 +50,7 @@ #include "cmd/ob_select_database_handler.h" #include "cmd/ob_show_topology_handler.h" #include "cmd/ob_show_db_version_handler.h" +#include "cmd/ob_show_table_status_handler.h" #include "obutils/ob_tenant_stat_manager.h" #include "prometheus/ob_net_prometheus.h" #include "prometheus/ob_sql_prometheus.h" @@ -64,11 +65,18 @@ #include "dbconfig/ob_proxy_pb_utils.h" #include "proxy/mysql/ob_mysql_global_session_manager.h" #include "omt/ob_white_list_table_processor.h" -#include "omt/ob_resource_unit_table_processor.h" +#include "omt/ob_conn_table_processor.h" #include "omt/ob_ssl_config_table_processor.h" #include "iocore/net/ob_inet.h" +#include "iocore/eventsystem/ob_shard_scan_all_task.h" #include "prometheus/ob_thread_prometheus.h" +#include "ob_proxy_init.h" #include "common/obsm_utils.h" +#include "proxy/mysqllib/ob_proxy_ob20_request.h" +#include "proxy/mysqllib/ob_mysql_resp_analyzer.h" +#include "obproxy/packet/ob_proxy_packet_writer.h" +#include "obproxy/cmd/ob_internal_cmd_processor.h" +#include "engine/ob_proxy_operator_cont.h" using namespace oceanbase::share; using namespace oceanbase::common; @@ -192,13 +200,18 @@ ObMysqlSM::ObMysqlSM() terminate_sm_(false), kill_this_async_done_(false), handling_ssl_request_(false), need_renew_cluster_resource_(false), is_in_trans_(true), retry_acquire_server_session_count_(0), start_acquire_server_session_time_(0), - skip_plugin_(false) + skip_plugin_(false), add_detect_server_cnt_(false), enable_cloud_full_username_(false), + enable_client_ssl_(false), enable_server_ssl_(false), enable_read_write_split_(false), + enable_transaction_split_(false), enable_ob_protocol_v2_(false), config_version_(0), target_db_server_(NULL) { static bool scatter_inited = false; memset(&history_, 0, sizeof(history_)); memset(&vc_table_, 0, sizeof(vc_table_)); + memset(proxy_route_policy_, 0, sizeof(proxy_route_policy_)); + memset(flt_trace_buffer_, 0, sizeof(flt_trace_buffer_)); + if (!scatter_inited) { make_scatter_list(*this); scatter_inited = true; @@ -221,6 +234,10 @@ inline void ObMysqlSM::cleanup() sm_cluster_resource_->dec_ref(); sm_cluster_resource_ = NULL; } + if (OB_NOT_NULL(target_db_server_)) { + op_free(target_db_server_); + target_db_server_ = NULL; + } } inline void ObMysqlSM::destroy() @@ -259,7 +276,7 @@ int ObMysqlSM::state_add_to_list(int event, void *data) // The list if for general debugging The config // variable exists mostly to allow us to // measure an performance drop during benchmark runs - if (trans_state_.mysql_config_params_->enable_mysqlsm_info_) { + if (get_global_proxy_config().enable_mysqlsm_info) { if (is_in_list_) { terminate_sm_ = true; LOG_ERROR("state_add_to_list, it should not arrive here again", K_(is_in_list), K_(sm_id)); @@ -381,7 +398,7 @@ int ObMysqlSM::attach_client_session( // assign dummy entry valid time client_session_->dummy_entry_valid_time_ns_ = ObRandomNumUtils::get_random_half_to_full( - trans_state_.mysql_config_params_->tenant_location_valid_time_); + get_global_proxy_config().tenant_location_valid_time * 1000); // Allocate a client entry in the state machine's vc table client_entry_ = vc_table_.new_entry(); @@ -469,12 +486,14 @@ inline int ObMysqlSM::setup_client_request_read() ret = OB_ERR_UNEXPECTED; LOG_WARN("client session failed to do_io_read", K_(sm_id), K(ret)); } else { - if (client_buffer_reader_->read_avail() > 0 - || (trans_state_.is_auth_request_ && trans_state_.is_trans_first_request_)) { - LOG_INFO("the request already in buffer, continue to handle it", - "buffer len", client_buffer_reader_->read_avail(), - "is_auth_rquest", trans_state_.is_auth_request_); - handle_event(VC_EVENT_READ_READY, client_entry_->read_vio_); + if (OB_SUCC(ret)) { + int64_t read_avail = client_buffer_reader_->read_avail(); + if (read_avail > 0 + || (trans_state_.is_auth_request_ && trans_state_.is_trans_first_request_)) { + LOG_INFO("the request already in buffer, continue to handle it", + "buffer len", read_avail, "is_auth_rquest", trans_state_.is_auth_request_); + handle_event(VC_EVENT_READ_READY, client_entry_->read_vio_); + } } } return ret; @@ -509,6 +528,9 @@ int ObMysqlSM::state_client_request_read(int event, void *data) milestones_.trans_start_ = get_based_hrtime(); } } + + // record the config of enable_transaction_internal_routing + client_session_->set_proxy_enable_trans_internal_routing(trans_state_.mysql_config_params_->enable_transaction_internal_routing_ && is_enable_ob_protocol_v2()); } if (OB_UNLIKELY(get_global_performance_params().enable_trace_)) { @@ -563,7 +585,8 @@ int ObMysqlSM::state_client_request_read(int event, void *data) } case VC_EVENT_ERROR: - case VC_EVENT_ACTIVE_TIMEOUT: { + case VC_EVENT_ACTIVE_TIMEOUT: + case VC_EVENT_DETECT_SERVER_DEAD: { LOG_WARN("ObMysqlSM::state_client_request_read", "event", ObMysqlDebugNames::get_event_name(event), K_(sm_id), "client_vc", client_session_ == NULL ? "NULL" : P(client_session_->get_netvc())); @@ -581,7 +604,8 @@ int ObMysqlSM::state_client_request_read(int event, void *data) } - if (OB_SUCC(ret) && !client_session_->is_proxy_mysql_client_) { + if (OB_SUCC(ret) && !client_session_->is_proxy_mysql_client_ + && RUN_MODE_PROXY == g_run_mode) { ObNetVConnection *vc = client_session_->get_netvc(); if (OB_UNLIKELY(NULL != vc && vc->options_.sockopt_flags_ != trans_state_.mysql_config_params_->client_sock_option_flag_out_)) { @@ -600,7 +624,10 @@ int ObMysqlSM::state_client_request_read(int event, void *data) if (OB_SUCC(ret)) { ObMysqlAnalyzeStatus status = ANALYZE_CONT; - analyze_mysql_request(status); + int64_t first_packet_len = 0; // the mysql packet total len or mysql compress packet total len + if (OB_FAIL(handle_first_request_packet(status, first_packet_len))) { + LOG_WARN("fail to handle first request packet", K(ret), K(status)); + } cmd_size_stats_.client_request_bytes_ = client_buffer_reader_->read_avail(); @@ -619,7 +646,19 @@ int ObMysqlSM::state_client_request_read(int event, void *data) //must read all data of the request, otherwise will read the remain request data when recv next request trans_state_.mysql_errcode_ = OB_ERR_PARSE_SQL; trans_state_.mysql_errmsg_ = ob_strerror(OB_ERR_PARSER_SYNTAX); - if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_))) { + if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_, client_session_))) { + LOG_WARN("fail to build err resp", K(ret)); + } else if (OB_FAIL(client_buffer_reader_->consume_all())) { + LOG_WARN("fail to consume all", K_(sm_id), K(ret)); + } else { + trans_state_.next_action_ = ObMysqlTransact::SM_ACTION_INTERNAL_NOOP; + callout_api_and_start_next_action(ObMysqlTransact::SM_ACTION_API_SEND_RESPONSE); + } + break; + case ANALYZE_NOT_SUPPORT: + trans_state_.mysql_errcode_ = OB_NOT_SUPPORTED; + trans_state_.mysql_errmsg_ = ob_strerror(OB_NOT_SUPPORTED); + if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_, client_session_))) { LOG_WARN("fail to build err resp", K(ret)); } else if (OB_FAIL(client_buffer_reader_->consume_all())) { LOG_WARN("fail to consume all", K_(sm_id), K(ret)); @@ -665,21 +704,24 @@ int ObMysqlSM::state_client_request_read(int event, void *data) } } else { MYSQL_INCREMENT_DYN_STAT(TOTAL_CLIENT_REQUEST_REREAD_COUNT); - int64_t request_len = trans_state_.trans_info_.client_request_.get_packet_len(); - if (request_len > 0 && request_len > client_buffer_reader_->mbuf_->water_mark_) { + int64_t mysql_req_len = trans_state_.trans_info_.client_request_.get_packet_len(); + int64_t request_max = MAX(first_packet_len, mysql_req_len); + request_max = MAX(request_max, MYSQL_COMPRESSED_OB20_HEALDER_LENGTH); + if (request_max > 0 && request_max > client_buffer_reader_->mbuf_->water_mark_) { // ensure the read buffer can cache the whole reqeust - client_buffer_reader_->mbuf_->water_mark_ = request_len; + client_buffer_reader_->mbuf_->water_mark_ = request_max; + LOG_DEBUG("modify client buffer reader water mark", K(request_max)); } if (trans_state_.trans_info_.client_request_.is_large_request()) { // Disable further I/O on the client since there could // be rest request body that we are tunneling, and we can't issue // another IO later for the rest request body with a different buffer client_entry_->read_vio_->nbytes_ = client_entry_->read_vio_->ndone_; - trans_state_.trans_info_.request_content_length_ = request_len; + trans_state_.trans_info_.request_content_length_ = mysql_req_len; MYSQL_INCREMENT_TRANS_STAT(CLIENT_LARGE_REQUESTS); LOG_DEBUG("large request", - K_(sm_id), K(request_len), + K_(sm_id), K(mysql_req_len), "saved_request_len", client_buffer_reader_->read_avail()); client_entry_->vc_handler_ = &ObMysqlSM::state_watch_for_client_abort; @@ -720,8 +762,8 @@ int ObMysqlSM::state_client_request_read(int event, void *data) set_client_wait_timeout(); // no request data to read, reset read trigger and avoid unnecessary reading - ObUnixNetVConnection* vc = static_cast(client_session_->get_netvc()); if (!client_session_->is_proxy_mysql_client_) { + ObUnixNetVConnection* vc = static_cast(client_session_->get_netvc()); if (!handling_ssl_request_) { vc->reset_read_trigger(); } @@ -856,6 +898,7 @@ int ObMysqlSM::state_handle_shard_ddl(int event, void *data) case VC_EVENT_EOS: case VC_EVENT_ACTIVE_TIMEOUT: case VC_EVENT_INACTIVITY_TIMEOUT: + case VC_EVENT_DETECT_SERVER_DEAD: LOG_WARN("handle shard ddl meet error, will disconnect", K_(sm_id), "event", ObMysqlDebugNames::get_event_name(event), K(ret)); ret = OB_CONNECT_ERROR; @@ -901,19 +944,26 @@ int ObMysqlSM::process_shard_ddl_result(ObShardDDLStatus *ddl_status) } if (OB_SUCC(ret)) { + ObProxyProtocol client_protocol = get_client_session_protocol(); + ObMysqlClientSession *client_session = get_client_session(); + if (ddl_status->is_success()) { - const ObMySQLCapabilityFlags &capability = client_session_->get_session_info().get_orig_capability_flags(); - if (OB_FAIL(ObMysqlPacketUtil::encode_ok_packet(*buf, seq, 0, capability))) { - LOG_WARN("[ObMysqlSM::do_internal_request] fail to encode login response ok packet", + const ObMySQLCapabilityFlags &capability = client_session->get_session_info().get_orig_capability_flags(); + if (OB_FAIL(ObProxyPacketWriter::write_ok_packet(*buf, *client_session_, client_protocol, seq, 0, capability))) { + LOG_WARN("[ObMysqlSM::do_internal_request] fail to encode shard ddl ok packet", K_(sm_id), K(ret)); } } else { int64_t error_code = 0; if (OB_FAIL(get_int_value(ddl_status->get_error_code(), error_code))) { LOG_WARN("fail to get int error code", "errcode", ddl_status->get_error_code(), K(ret)); - } else if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet_buf(*buf, seq, static_cast(-error_code), ddl_status->get_error_message()))) { + } else if (OB_FAIL(ObProxyPacketWriter::write_error_packet(*buf, client_session, client_protocol, + seq, static_cast(-error_code), + ddl_status->get_error_message()))) { LOG_WARN("fail to encode err pacekt buf", K(seq), "errmsg", ddl_status->get_error_message(), "errcode", error_code, K(ret)); + } else { + // nothing } } } @@ -930,19 +980,17 @@ int ObMysqlSM::setup_handle_execute_plan() ObShardingSelectLogPlan* plan = NULL; ObProxyOperator* operator_root = NULL; + ObProxyOperatorCont *operator_cont = NULL; + ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; int64_t total_len = client_buffer_reader_->read_avail(); - if (total_len > trans_state_.trans_info_.client_request_.get_packet_meta().pkt_len_) { - total_len = trans_state_.trans_info_.client_request_.get_packet_meta().pkt_len_; + if (total_len > client_request.get_packet_meta().pkt_len_) { + total_len = client_request.get_packet_meta().pkt_len_; } - ObShardProp *shard_prop = client_session_->get_session_info().get_shard_prop(); - ObHRTime execute_timeout = 0; - if (OB_NOT_NULL(shard_prop)) { - execute_timeout = HRTIME_MSECONDS(shard_prop->get_socket_timeout()); - } else { - execute_timeout = client_session_->get_session_info().get_query_timeout(); - } + uint8_t seq = static_cast(client_request.get_packet_meta().pkt_seq_ + 1); + + ObHRTime execute_timeout = get_query_timeout(); // consume data in client buffer reader if (OB_FAIL(client_buffer_reader_->consume(total_len))) { @@ -956,16 +1004,23 @@ int ObMysqlSM::setup_handle_execute_plan() } else if (OB_NOT_NULL(pending_action_)){ ret = OB_ERR_UNEXPECTED; LOG_WARN("pending_action must be NULL here", K_(pending_action), K_(sm_id), K(ret)); - } else if (OB_FAIL(operator_root->open(this, pending_action_, hrtime_to_msec(execute_timeout)))) { - LOG_WARN("fail to open operator", K_(sm_id), K(execute_timeout), K(ret)); - } else if (OB_FAIL(operator_root->get_next_row())) { - LOG_WARN("fail to get next row", K_(sm_id), K(ret)); - } else if (OB_ISNULL(pending_action_)) { - LOG_WARN("pending action should not be null", K_(sm_id), K(ret)); + } else if (OB_ISNULL(operator_cont = new(std::nothrow) ObProxyOperatorCont(this, &self_ethread()))) { + LOG_WARN("fail to alloc parallel execute cont", K(ret)); + } else if (OB_FAIL(operator_cont->init(operator_root, seq, hrtime_to_msec(execute_timeout)))) { + LOG_WARN("fail to init execute cont", K(ret)); + } else if (OB_ISNULL(g_shard_scan_all_task_processor.schedule_imm(operator_cont, ET_SHARD_SCAN_ALL))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to schedule parallel execute cont", K(ret)); } else { + pending_action_ = &operator_cont->get_action(); client_session_->set_inactivity_timeout(execute_timeout); } + if (OB_FAIL(ret) && OB_LIKELY(NULL != operator_cont)) { + operator_cont->destroy(); + operator_cont = NULL; + } + return ret; } @@ -977,14 +1032,14 @@ int ObMysqlSM::state_handle_execute_plan(int event, void *data) ObShardingSelectLogPlan* plan = NULL; ObProxyOperator* operator_root = NULL; - pending_action_ = NULL; switch (event) { - case VC_EVENT_READ_COMPLETE: + case ASYNC_PROCESS_DONE_EVENT: + pending_action_ = NULL; if (OB_ISNULL(data)) { ret = OB_ERR_NULL_VALUE; LOG_WARN("data is NULL", K_(sm_id), K(ret)); - } else if (OB_FAIL(process_executor_result(reinterpret_cast(data)))) { + } else if (OB_FAIL(process_executor_result(reinterpret_cast(data)))) { LOG_WARN("fail to process executor result, will disconnect", K_(sm_id), K(ret)); } else { trans_state_.next_action_ = ObMysqlTransact::SM_ACTION_INTERNAL_NOOP; @@ -994,6 +1049,7 @@ int ObMysqlSM::state_handle_execute_plan(int event, void *data) case VC_EVENT_EOS: case VC_EVENT_ACTIVE_TIMEOUT: case VC_EVENT_INACTIVITY_TIMEOUT: + case VC_EVENT_DETECT_SERVER_DEAD: LOG_WARN("handle execute plan meet error, will disconnect", K_(sm_id), "event", ObMysqlDebugNames::get_event_name(event), K(ret)); ret = OB_CONNECT_ERROR; @@ -1010,9 +1066,23 @@ int ObMysqlSM::state_handle_execute_plan(int event, void *data) } } + if (OB_NOT_NULL(pending_action_)) { + int tmp_ret = OB_SUCCESS; + if (OB_SUCCESS != (tmp_ret = pending_action_->cancel())) { + LOG_WARN("failed to cancel pending action", K_(pending_action), K_(sm_id), K(tmp_ret)); + } + + if (OB_SUCC(ret)) { + ret = tmp_ret; + } + pending_action_ = NULL; + } + if (OB_ISNULL(plan = client_session_->get_sharding_select_log_plan())) { + ret = OB_ERR_UNEXPECTED; LOG_WARN("select log plan should not be null", K_(sm_id), K(ret)); } else if (OB_ISNULL(operator_root = plan->get_plan_root())) { + ret = OB_ERR_UNEXPECTED; LOG_WARN("operator should not be null", K_(sm_id), K(ret)); } else { operator_root->close(); @@ -1027,12 +1097,10 @@ int ObMysqlSM::state_handle_execute_plan(int event, void *data) return VC_EVENT_NONE; } -int ObMysqlSM::process_executor_result(ObProxyResultResp *result_resp) +int ObMysqlSM::process_executor_result(ObIOBufferReader *resp_reader) { int ret = OB_SUCCESS; - ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; - uint8_t seq = static_cast(client_request.get_packet_meta().pkt_seq_ + 1); ObMIOBuffer *buf = NULL; if (NULL != trans_state_.internal_buffer_) { @@ -1046,106 +1114,36 @@ int ObMysqlSM::process_executor_result(ObProxyResultResp *result_resp) } if (OB_SUCC(ret)) { - if (result_resp->is_resultset_resp()) { - if (OB_FAIL(build_executor_resp(buf, seq, result_resp))) { - LOG_WARN("fail to build shard scan resp", K(ret)); - } - } else { - if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet_buf(*buf, seq, result_resp->get_err_code(), result_resp->get_err_msg()))) { - LOG_WARN("fail to encode err pacekt buf", K(seq), "errmsg", result_resp->get_err_msg(), - "errcode", result_resp->get_err_code(), K(ret)); - } - } - } - - return ret; -} - -int ObMysqlSM::build_executor_resp(ObMIOBuffer *write_buf, uint8_t &seq, ObProxyResultResp *result_resp) -{ - int ret = OB_SUCCESS; - int64_t column_count = result_resp->get_column_count(); - ObSEArray *fields = NULL; - ObSEArray ob_fields; - - // header , cols , first eof - if (OB_SUCC(ret)) { - if (OB_FAIL(result_resp->get_fields(fields))) { - LOG_WARN("faild to push field", K(fields), K(ret)); - } else if (OB_ISNULL(fields)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("fields should not be null", K(ret)); - } else if (OB_UNLIKELY(fields->count() != column_count)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("fields count should equal column_count", K(column_count), "fileds count", fields->count(), K(ret)); - } else if (OB_FAIL(ObMysqlPacketUtil::encode_header(*write_buf, seq, *fields))) { - LOG_WARN("faild to encode header", K(fields), K(seq), K(ret)); - } else { - for (int64_t i = 0; OB_SUCC(ret) && i < column_count; i++) { - ObMySQLField &mysql_field = fields->at(i); - ObField ob_field; - if (OB_FAIL(ObSMUtils::to_ob_field(mysql_field, ob_field))) { - LOG_WARN("faild to ob field", K(mysql_field), K(ret)); - } else if (OB_FAIL(ob_fields.push_back(ob_field))) { - LOG_WARN("faild to push ob field", K(ob_field), K(ret)); - } + ObMysqlClientSession *client_session = get_client_session(); + ObProxyProtocol client_protocol = get_client_session_protocol(); + + if (client_protocol == ObProxyProtocol::PROTOCOL_OB20) { + Ob20ProtocolHeader &ob20_head = client_session->get_session_info().ob20_request_.ob20_header_; + uint8_t compressed_seq = static_cast(client_session->get_compressed_seq() + 1); + Ob20ProtocolHeaderParam ob20_head_param(client_session->get_cs_id(), ob20_head.request_id_, compressed_seq, + compressed_seq, true, false, false, + client_session->is_client_support_new_extra_info(), + client_session->is_trans_internal_routing()); + if (OB_FAIL(ObProto20Utils::consume_and_compress_data(resp_reader, buf, + resp_reader->read_avail(), ob20_head_param))) { + LOG_WARN("fail to consume and compress data for executor response packet in ob20", K(ret)); + } else { + LOG_DEBUG("succ to executor response in ob20 packet"); } - } - } - - // rows - if (OB_SUCC(ret)) { - ObObj *objs = NULL; - int64_t buf_len = sizeof(ObObj) * column_count; - - if (OB_ISNULL(objs = static_cast(op_fixed_mem_alloc(buf_len)))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("faild to alloc obj array", K(column_count), K(ret)); } else { - ObNewRow row; - //ObSEArray *row_array; - ObSEArray *row_array; - while ((OB_SUCC(ret)) && (OB_SUCC(result_resp->next(row_array)))) { - if (OB_ISNULL(row_array)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("row_array should not be null", K(ret)); - } else if (OB_UNLIKELY(row_array->count() != column_count)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("row_array count should equal column_count", K(column_count), "row_array count", row_array->count(), K(ret)); - } - - for (int64_t i = 0; OB_SUCC(ret) && i < column_count; i++) { - objs[i] = *(row_array->at(i)); - } - - if (OB_SUCC(ret)) { - row.cells_ = objs; - row.count_ = column_count; - if (OB_FAIL(ObMysqlPacketUtil::encode_row_packet(*write_buf, seq, row, &ob_fields))) { - LOG_WARN("faild to encode row", K(seq), K(row), K(ret)); - } else { - row.reset(); - row_array = NULL; - } - } - } - - if (OB_ITER_END == ret) { - ret = OB_SUCCESS; + int64_t data_size = resp_reader->read_avail(); + int64_t bytes_written = 0; + if (OB_FAIL(buf->remove_append(resp_reader, bytes_written))) { + LOG_ERROR("Error while remove_append to buf", "Attempted size", data_size, + "wrote size", bytes_written, K(ret)); + } else if (OB_UNLIKELY(bytes_written != data_size)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected result", "Attempted size", data_size, + "wrote size", bytes_written, K(ret)); + } else { + LOG_DEBUG("succ to write to client", "Attempted size", bytes_written); } } - - if (OB_NOT_NULL(objs)) { - op_fixed_mem_free(objs, buf_len); - objs = NULL; - } - } - - // second eof - if (OB_SUCC(ret)) { - if (OB_FAIL(ObMysqlPacketUtil::encode_eof_packet(*write_buf, seq))) { - LOG_WARN("faild to encode row", K(seq), K(ret)); - } } return ret; @@ -1168,8 +1166,7 @@ int ObMysqlSM::handle_shard_request(bool &need_response_for_stmt, bool &need_wai ObDbConfigLogicDb *db_info = NULL; if (!session_info.is_sharding_user() - || parse_result.is_shard_special_cmd() - || ObProxyShardUtils::is_special_db(trans_state_)) { + || parse_result.is_shard_special_cmd()) { // do nothing } else { if (obmysql::OB_MYSQL_COM_FIELD_LIST == req_cmd) { @@ -1177,10 +1174,12 @@ int ObMysqlSM::handle_shard_request(bool &need_response_for_stmt, bool &need_wai LOG_WARN("com_field_list cmd is unsupported for sharding table", K(ret)); } else if (obmysql::OB_MYSQL_COM_QUERY != req_cmd) { //do nothing - } else if (parse_result.is_invalid_stmt() && parse_result.has_shard_comment()) { - ret = OB_ERR_PARSER_SYNTAX; - LOG_WARN("fail to parse shard sql with shard comment", - "sql", client_request.get_sql(), K(ret)); + } else if (ObProxyShardUtils::is_special_db(parse_result)) { + if (OB_FAIL(ObProxyShardUtils::handle_information_schema_request(*client_session_, + trans_state_, + *client_buffer_reader_))) { + LOG_WARN("fail to handle information schema request", K(ret)); + } } else { // get logic db and check auth if (OB_FAIL(ObProxyShardUtils::get_logic_db_info(trans_state_, @@ -1195,20 +1194,30 @@ int ObMysqlSM::handle_shard_request(bool &need_response_for_stmt, bool &need_wai LOG_WARN("fail to check shard request", K(ret)); } else if (parse_result.is_dual_request()) { //do nothing + } else if (parse_result.is_ddl_stmt()) { + const ObString runtime_env = get_global_proxy_config().runtime_env.str(); + if (0 == runtime_env.case_compare(OB_PROXY_DBP_RUNTIME_ENV)) { + if (OB_FAIL(ObProxyShardUtils::handle_ddl_request(this, *client_session_, trans_state_, *db_info, need_wait_callback))) { + LOG_WARN("fail to handle ddl request", K(ret)); + } + } else { + ret = OB_NOT_SUPPORTED; + LOG_WARN("ddl stmt is unsupported for sharding table", K(ret)); + } } else if (db_info->is_single_shard_db_table()) { // sindle db table - if (OB_FAIL(ObProxyShardUtils::handle_single_shard_request(this, *client_session_, - trans_state_, *client_buffer_reader_, *db_info, need_wait_callback))) { + if (OB_FAIL(ObProxyShardUtils::handle_single_shard_request(*client_session_, + trans_state_, *client_buffer_reader_, *db_info))) { LOG_WARN("fail to handle single shard request", K(ret)); } - } else if (OB_FAIL(ObProxyShardUtils::handle_shard_request(this, *client_session_, - trans_state_, *client_buffer_reader_, *db_info, need_wait_callback))) { + } else if (OB_FAIL(ObProxyShardUtils::handle_shard_request(*client_session_, + trans_state_, *client_buffer_reader_, *db_info))) { LOG_WARN("fail to handle shard request", K(ret)); } } if (OB_FAIL(ret)) { - int tmp_ret = ObProxyShardUtils::build_error_packet(ret, need_response_for_stmt, trans_state_); + int tmp_ret = ObProxyShardUtils::build_error_packet(ret, need_response_for_stmt, trans_state_, client_session_); ret = OB_SUCC(tmp_ret) ? tmp_ret : ret; } if (OB_SUCC(ret) && !need_response_for_stmt && !need_wait_callback) { @@ -1281,9 +1290,10 @@ int ObMysqlSM::handle_limit(bool &need_response_for_client) if (OB_FAIL(databuff_printf(err_msg_buf, OB_MAX_ERROR_MSG_LEN, pos, ob_str_user_error(OB_ERR_LIMIT), limit_name.length(), limit_name.ptr()))) { } else { + ObMysqlClientSession *client_session = get_client_session(); trans_state_.mysql_errcode_ = OB_ERR_LIMIT; trans_state_.mysql_errmsg_ = err_msg_buf; - if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_))) { + if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_, client_session))) { LOG_WARN("fail to build err resp", K(ret)); } else { need_response_for_client = true; @@ -1469,7 +1479,8 @@ void ObMysqlSM::setup_get_cluster_resource() // return err packet to client "Access denied for ..." trans_state_.mysql_errcode_ = OB_CLUSTER_NOT_EXIST; int tmp_ret = OB_SUCCESS; - if (OB_UNLIKELY(OB_SUCCESS != (tmp_ret = ObMysqlTransact::build_error_packet(trans_state_)))) { + if (OB_UNLIKELY(OB_SUCCESS != + (tmp_ret = ObMysqlTransact::build_error_packet(trans_state_, client_session_)))) { LOG_WARN("fail to build err packet", K(tmp_ret)); } else { trans_state_.current_.state_ = ObMysqlTransact::INTERNAL_ERROR; @@ -1489,6 +1500,15 @@ void ObMysqlSM::setup_get_cluster_resource() MYSQL_SM_SET_DEFAULT_HANDLER(&ObMysqlSM::state_get_cluster_resource); milestones_.cluster_resource_create_begin_ = get_based_hrtime(); + if (enable_record_full_link_trace_info()) { + SET_TRACE_BUFFER(flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + trace::ObSpanCtx *ctx = FLT_BEGIN_SPAN(ob_proxy_cluster_resource_create); + if (OB_NOT_NULL(ctx)) { + flt_.trace_log_info_.cluster_resource_create_ctx_ = ctx; + LOG_DEBUG("begin span ob_proxy_cluster_resource_create", K(ctx->span_id_)); + } + } + ret = get_global_resource_pool_processor().get_cluster_resource(*this, (process_async_task_pfn)&ObMysqlSM::process_cluster_resource, client_session_->is_proxy_mysql_client_, cluster_name, cluster_id, cr_handler); @@ -1639,6 +1659,17 @@ int ObMysqlSM::state_get_cluster_resource(int event, void *data) milestones_.cluster_resource_create_end_ = get_based_hrtime(); cmd_time_stats_.cluster_resource_create_time_ = milestone_diff(milestones_.cluster_resource_create_begin_, milestones_.cluster_resource_create_end_); + + if (enable_record_full_link_trace_info()) { + trace::ObSpanCtx *ctx = flt_.trace_log_info_.cluster_resource_create_ctx_; + if (OB_NOT_NULL(ctx)) { + LOG_DEBUG("end span ob_proxy_cluster_resource_create", K(ctx->span_id_)); + SET_TRACE_BUFFER(flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + FLT_END_SPAN(ctx); + flt_.trace_log_info_.cluster_resource_create_ctx_ = NULL; // logically free, mem still in OBTRACE + } + } + switch (event) { case CLUSTER_RESOURCE_CREATE_COMPLETE_EVENT: pending_action_ = NULL; @@ -1667,7 +1698,7 @@ int ObMysqlSM::state_get_cluster_resource(int event, void *data) return VC_EVENT_NONE; } -inline int ObMysqlSM::init_request_content(ObRequestAnalyzeCtx &ctx) +inline int ObMysqlSM::init_request_content(ObRequestAnalyzeCtx &ctx, const bool is_mysql_req_in_ob20) { int ret = OB_SUCCESS; @@ -1685,10 +1716,12 @@ inline int ObMysqlSM::init_request_content(ObRequestAnalyzeCtx &ctx) } } } else { - trans_state_.trans_info_.client_request_.reuse(); + ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; + client_request.reuse(); const bool eaic = client_session_->enable_analyze_internal_cmd(); - trans_state_.trans_info_.client_request_.set_enable_analyze_internal_cmd(eaic); - trans_state_.trans_info_.client_request_.set_user_identity(client_session_->get_user_identity()); + client_request.set_enable_analyze_internal_cmd(eaic); + client_request.set_user_identity(client_session_->get_user_identity()); + client_request.set_mysql_req_in_ob20_payload(is_mysql_req_in_ob20); ctx.is_sharding_mode_ = client_session_->get_session_info().is_sharding_user(); ctx.connection_collation_ = static_cast(client_session_->get_session_info().get_collation_connection()); @@ -1733,36 +1766,85 @@ inline bool ObMysqlSM::check_connection_throttle() bool ObMysqlSM::can_pass_white_list() { bool can_pass = false; - bool need_check_white_list = true; - ObStringKV string_kv; + if (RUN_MODE_CLIENT == g_run_mode) { + can_pass = true; + } else { + ObStringKV string_kv; + ObClientSessionInfo &session_info = client_session_->get_session_info(); + ObHSRResult &hsr = session_info.get_login_req().get_hsr_result(); + ObUnixNetVConnection* unix_vc = static_cast(client_session_->get_netvc()); + if (OB_UNLIKELY(NULL == unix_vc)) { + LOG_WARN("invalid unix_vc"); + } else if (get_global_white_list_table_processor().can_ip_pass(hsr.cluster_name_, hsr.tenant_name_, hsr.user_name_, unix_vc->get_real_client_addr())) { + can_pass = true; + } + } + + return can_pass; +} + +/* + * support ob2.0 protocol between client and proxy + * client will send cap through CLIENT_CONNECT_ATTRS in mysql handshake response packet. + * key: "__proxy_capability_flag" + * + * client supported ob2.0 protocol or not + * while negotiate with client, not only the cap shift OB_CAP_OB_PROTOCOL_V2 should be set, + but also the CONN_ATTR kv of key:"__mysql_client_type" and value "__ob_libobclient"/"__ob_jdbc_client" + should be set, to indicate that client support ob2.0 protocol transfer. + */ +int ObMysqlSM::analyze_capacity_flag_from_client() +{ + int ret = OB_SUCCESS; + ObClientSessionInfo &session_info = client_session_->get_session_info(); ObHSRResult &hsr = session_info.get_login_req().get_hsr_result(); - ObUnixNetVConnection* unix_vc = static_cast(client_session_->get_netvc()); - if (OB_UNLIKELY(NULL == unix_vc)) { - LOG_WARN("invalid unix_vc"); - } else { - for (int64_t i = 0; need_check_white_list && i < hsr.response_.get_connect_attrs().count(); ++i) { - string_kv = hsr.response_.get_connect_attrs().at(i); - if (0 == string_kv.key_.case_compare(OB_MYSQL_CLIENT_IP)) { - if (!string_kv.value_.empty()) { - char client_ip_buf[256]; - snprintf(client_ip_buf, ObHandshakeResponseParam::OB_MAX_IP_BUF_LEN, "%.*s", string_kv.value_.length(), string_kv.value_.ptr()); - need_check_white_list = false; - if (get_global_white_list_table_processor().can_ip_pass(hsr.cluster_name_, hsr.tenant_name_, hsr.user_name_, client_ip_buf)) { - can_pass = true; - } - } - break; + int64_t total_conn_attrs = hsr.response_.get_connect_attrs().count(); + ObStringKV string_kv; + bool is_client_send_client_mode = false; + + for (int64_t i = 0; OB_SUCC(ret) && i < total_conn_attrs; ++i) { + string_kv = hsr.response_.get_connect_attrs().at(i); + if (0 == string_kv.key_.case_compare(OB_MYSQL_CAPABILITY_FLAG)) { + int64_t orig_client_cap = 0; + if (OB_FAIL(get_int_value(string_kv.value_, orig_client_cap))) { + LOG_WARN("fail to get int value from cap flag", K(ret), K(string_kv.key_), K(string_kv.value_)); + } else { + uint64_t set_client_cap = orig_client_cap & OBPROXY_DEFAULT_CAPABILITY_FLAG; + session_info.set_client_ob_capability(set_client_cap); + LOG_DEBUG("succ to analyze origin capability flag from client", K(orig_client_cap), K(set_client_cap)); } - } - if (need_check_white_list) { - if (get_global_white_list_table_processor().can_ip_pass(hsr.cluster_name_, hsr.tenant_name_, hsr.user_name_, unix_vc->get_remote_ip(), true)) { - can_pass = true; + } else if (0 == string_kv.key_.case_compare(OB_MYSQL_CLIENT_MODE)) { + // another tag for client to judge the support of ob2.0 + if (0 == string_kv.value_.compare(OB_MYSQL_CLIENT_LIBOBCLIENT_MODE) + || 0 == string_kv.value_.compare(OB_MYSQL_CLIENT_JDBC_CLIENT_MODE)) { + is_client_send_client_mode = true; + LOG_DEBUG("client transfered mysql client mode", K(string_kv.value_)); } + } else { + continue; } } - return can_pass; + // whether client truely support ob2.0 or not + // whether proxy config flag set or not + if (OB_SUCC(ret)) { + uint64_t origin_client_cap = session_info.get_client_ob_capability(); + if (!session_info.is_client_support_ob20_protocol() + || !is_client_send_client_mode + || !get_global_proxy_config().enable_ob_protocol_v2_with_client) { + origin_client_cap &= ~(OB_CAP_OB_PROTOCOL_V2); + session_info.set_client_ob_capability(origin_client_cap); + } + } + + if (OB_SUCC(ret)) { + const uint64_t last_client_cap = session_info.get_client_ob_capability(); + const bool is_client_support_ob20 = session_info.is_client_support_ob20_protocol(); + LOG_INFO("final client capability flag in negotiation", K(last_client_cap), K(is_client_support_ob20)); + } + + return ret; } // chect weahter connections reach throttle @@ -1784,7 +1866,7 @@ inline bool ObMysqlSM::check_vt_connection_throttle() cs_info.get_tenant_name(tenant_name); } - return get_global_resource_unit_table_processor().check_and_inc_conn( + return get_global_conn_table_processor().check_and_inc_conn( cluster_name, tenant_name, ip_name); } @@ -1795,8 +1877,9 @@ int ObMysqlSM::encode_error_message(int err_code) if (OB_FAIL(client_buffer_reader_->consume_all())) { LOG_WARN("client buffer reader fail to consume all", K(ret)); } else { + ObMysqlClientSession *client_session = get_client_session(); trans_state_.mysql_errcode_ = err_code; - if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_))) { + if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_, client_session))) { LOG_WARN("[ObMysqlSM::encode_error_message] fail to encode error response", K_(sm_id), K(ret), "errcode", trans_state_.mysql_errcode_); } @@ -1805,12 +1888,15 @@ int ObMysqlSM::encode_error_message(int err_code) return ret; } +/* + * proxy will do parition route with observer, the cap is determined by proxy config + */ inline bool ObMysqlSM::is_partition_table_route_supported() { bool bret = false; if (trans_state_.mysql_config_params_->enable_partition_table_route_) { if (NULL != client_session_ - && client_session_->get_session_info().is_partition_table_supported()) { + && client_session_->get_session_info().is_server_support_partition_table()) { bret = true; } } @@ -1822,7 +1908,7 @@ inline bool ObMysqlSM::is_pl_route_supported() bool bret = false; if (trans_state_.mysql_config_params_->enable_pl_route_) { if (NULL != client_session_ - && client_session_->get_session_info().is_pl_route_supported()) { + && client_session_->get_session_info().is_server_support_pl_route()) { bret = true; } } @@ -1925,11 +2011,12 @@ inline int ObMysqlSM::save_user_login_info(ObClientSessionInfo &session_info, Ob // no need add database name to client session info here, // because if login request has -D database option, obproxy // will get changed database name from response ok packet; + trans_state_.refresh_mysql_config(); } return ret; } -void ObMysqlSM::analyze_mysql_request(ObMysqlAnalyzeStatus &status) +void ObMysqlSM::analyze_mysql_request(ObMysqlAnalyzeStatus &status, const bool is_mysql_req_in_ob20) { int ret = OB_SUCCESS; if (OB_UNLIKELY(get_global_performance_params().enable_trace_)) { @@ -1948,36 +2035,46 @@ void ObMysqlSM::analyze_mysql_request(ObMysqlAnalyzeStatus &status) LOG_WARN("client session is NULL in init_request_content", K_(sm_id), K(ret)); // 1. init request content at first - } else if (OB_FAIL(init_request_content(ctx))) { + } else if (OB_FAIL(init_request_content(ctx, is_mysql_req_in_ob20))) { LOG_WARN("fail to init requtest content", K_(sm_id), K(ret)); } else { // 2. analyze mysql request(auth request or common mysql request) ObClientSessionInfo &session_info = client_session_->get_session_info(); - session_info.reset_text_ps_state(); ObMysqlAuthRequest &orig_auth_req = session_info.get_login_req(); ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; ObMySQLCmd &req_cmd = trans_state_.trans_info_.sql_cmd_; - ObMysqlRequestAnalyzer::analyze_request(ctx, orig_auth_req, client_request, req_cmd, status, session_info.is_oracle_mode()); + ObMysqlRequestAnalyzer::analyze_request(ctx, orig_auth_req, client_request, req_cmd, status, + session_info.is_oracle_mode(), + session_info.is_client_support_ob20_protocol()); if (OB_LIKELY(ANALYZE_DONE == status)) { // 3. if BEGIN or START TRANSACTION, try to hold it if (OB_LIKELY(OB_MYSQL_COM_QUERY == req_cmd)) { MYSQL_INCREMENT_DYN_STAT(TOTAL_QUERY_COUNT); - if (OB_UNLIKELY(client_request.get_parse_result().need_hold_start_trans())) { + // Not set start trans sql + // 1. already in transaction + // 2. already hold xa start + if (OB_UNLIKELY(client_request.get_parse_result().need_hold_start_trans() + && trans_state_.is_trans_first_request_ + && !trans_state_.is_hold_xa_start_)) { if (OB_FAIL(session_info.set_start_trans_sql(client_request.get_sql()))) { LOG_WARN("fail to set start transaction sqld", K_(sm_id), K(ret)); } } if (OB_SUCC(ret)) { if (OB_UNLIKELY(client_request.get_parse_result().is_text_ps_prepare_stmt())) { - if (OB_FAIL(analyze_text_ps_prepare_request())) { + if (OB_FAIL(analyze_text_ps_prepare_request(ctx))) { LOG_WARN("analyze text ps prepare request failed", K(ret)); } } else if (OB_UNLIKELY(client_request.get_parse_result().is_text_ps_execute_stmt())) { if (OB_FAIL(analyze_text_ps_execute_request())) { LOG_WARN("analyze text ps execute request failed", K(ret)); } + } else if (OB_UNLIKELY(client_request.get_parse_result().is_text_ps_drop_stmt())) { + if (OB_FAIL(analyze_text_ps_drop_request())) { + LOG_WARN("analyze text ps drop request failed", K(ret)); + } } } // 4. if OB_MYSQL_COM_LOGIN, do some check @@ -1985,7 +2082,7 @@ void ObMysqlSM::analyze_mysql_request(ObMysqlAnalyzeStatus &status) if (OB_FAIL(analyze_login_request(ctx, status))) { LOG_WARN("fail to analyze login request", K(ret)); } - } else if (OB_MYSQL_COM_CHANGE_USER == req_cmd) { + } else if (OB_MYSQL_COM_RESET_CONNECTION == req_cmd) { if (session_info.is_sharding_user() || session_info.is_session_pool_client_) { if (OB_FAIL(encode_error_message(OB_NOT_SUPPORTED))) { LOG_WARN("fail to encode unsupport change user error message", K(ret)); @@ -2018,13 +2115,38 @@ void ObMysqlSM::analyze_mysql_request(ObMysqlAnalyzeStatus &status) if (OB_FAIL(analyze_fetch_request())) { LOG_WARN("fail to analyze fetch request", K(ret)); } - } else if (OB_MYSQL_COM_STMT_CLOSE == req_cmd) { - if (OB_FAIL(analyze_close_request())) { + } else if (OB_MYSQL_COM_STMT_CLOSE == req_cmd || OB_MYSQL_COM_STMT_RESET == req_cmd) { + if (OB_FAIL(analyze_close_reset_request())) { LOG_WARN("fail to analyze fetch request", K(ret)); } } else if (OB_MYSQL_COM_STMT_PREPARE_EXECUTE == req_cmd) { if (OB_FAIL(analyze_ps_prepare_execute_request())) { LOG_WARN("fail to analyze ps prepare execute request", K(ret)); + // Not set start trans sql + // 1. already in transaction + // 2. already hold xa start + // 3. already hold begin + } else if (get_global_proxy_config().enable_xa_route + && client_request.get_parse_result().need_hold_xa_start() + && trans_state_.is_trans_first_request_ + && !trans_state_.is_hold_start_trans_ + && !trans_state_.is_hold_xa_start_) { + LOG_DEBUG("[ObMysqlSM::analyze_mysql_request] save xa start request packet"); + session_info.set_start_trans_sql(client_request.get_req_pkt()); + // save the xa start ps id, session_info.ps_id_ will be reset at ObMysqlSM::setup_cmd_complete() + session_info.set_xa_start_ps_id(session_info.get_client_ps_id()); + } + } else if (OB_MYSQL_COM_CHANGE_USER == req_cmd) { + if (OB_UNLIKELY(session_info.is_sharding_user() || client_session_->using_ldg())) { + if (OB_FAIL(encode_error_message(OB_NOT_SUPPORTED))) { + LOG_WARN("fail to encode unsupport change user error message", K(ret)); + } else { + LOG_WARN("sharding or ldg not support change user", K(session_info.is_sharding_user()), + KPC_(client_session), K(ret)); + } + status = ANALYZE_ERROR; + } else if (OB_FAIL(analyze_change_user_request())) { + LOG_WARN("fail to analyze change user request", K(ret)); } } else { // do nothing @@ -2042,6 +2164,11 @@ void ObMysqlSM::analyze_mysql_request(ObMysqlAnalyzeStatus &status) if (OB_FAIL(analyze_ps_prepare_execute_request())) { LOG_WARN("fail to analyze ps prepare execute request", K(ret)); } + } else if (client_request.get_parse_result().is_text_ps_execute_stmt() && + client_request.is_large_request()) { + if (OB_FAIL(analyze_text_ps_execute_request())) { + LOG_WARN("fail to analyze text ps execute request", K(ret)); + } } } else { // is not ANALYZE_DONE, do nothing @@ -2059,6 +2186,129 @@ void ObMysqlSM::analyze_mysql_request(ObMysqlAnalyzeStatus &status) milestone_diff(milestones_.client_.analyze_request_begin_, milestones_.client_.analyze_request_end_); } +int ObMysqlSM::analyze_change_user_request() +{ + int ret = OB_SUCCESS; + ObClientSessionInfo& client_info = client_session_->get_session_info(); + // len represents the size of the entire OB_MYSQL_COM_CHANGE_USER message + int64_t len = trans_state_.trans_info_.client_request_.get_packet_meta().pkt_len_; + if (OB_UNLIKELY(len <= 0)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid len", K(len), K(ret)); + } else { + ObVariableLenBuffer<128> user_buffer; + if (OB_FAIL(user_buffer.init(len))) { + LOG_WARN("fail to init user buffer", K(ret)); + } else { + char *start = const_cast(user_buffer.ptr()); + char *written_pos = client_buffer_reader_->copy(start, len, 0); + if (OB_UNLIKELY(written_pos != start + len)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("write pos not expected", K(written_pos), K(start), K(len), K(ret)); + } else if (OB_FAIL(client_buffer_reader_->consume_all())) { + LOG_WARN("client_buffer_reader consume_all failed", K(ret)); + } else { + ObMIOBuffer *write_buffer = client_buffer_reader_->writer(); + // buf points to the username part of OB_MYSQL_COM_CHANGE_USER + char *buf = start + MYSQL_NET_META_LENGTH; + ObString username = ObString::make_string(buf); + int64_t name_len = strlen(buf); + ObHSRResult result; + int64_t written_len = 0; + ObString& tenant_name = client_info.get_login_req().get_hsr_result().tenant_name_; + ObString& cluster_name = client_info.get_login_req().get_hsr_result().cluster_name_; + if (OB_FAIL(ObProxyAuthParser::parse_full_user_name(username, tenant_name, cluster_name, result))) { + LOG_WARN("parse full user name failed", K(ret)); + } else if (OB_FAIL(write_buffer->write(start, MYSQL_NET_META_LENGTH, written_len))) { + LOG_WARN("fail to write header", K(ret)); + } else if (OB_UNLIKELY(MYSQL_NET_META_LENGTH != written_len)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("not write completely", K(written_len), K(ret)); + } + // write username + if (OB_SUCC(ret)) { + if (OB_FAIL(write_buffer->write(result.user_name_.ptr(), result.user_name_.length(), written_len))) { + LOG_WARN("fail to write username", K(ret)); + } else if (OB_UNLIKELY(result.user_name_.length() != written_len)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("not write completely", K(written_len), K(ret)); + } + } + // write tenant name + int64_t new_name_len = 0; + if (OB_SUCC(ret)) { + if (result.has_tenant_username_ && result.has_cluster_username_) { + if (OB_UNLIKELY(tenant_name != result.tenant_name_ || cluster_name != result.cluster_name_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("name not match", K(result), K(tenant_name), K(cluster_name), K(ret)); + } + } else if (result.has_tenant_username_ && !result.has_cluster_username_) { + if (OB_UNLIKELY(tenant_name != result.tenant_name_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("name not match", K(result), K(tenant_name), K(ret)); + } + } else if (!result.has_tenant_username_ && !result.has_cluster_username_) { + // do nothing + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("should not come here", K(result), K(ret)); + } + if (OB_SUCC(ret)) { + if (OB_FAIL(write_buffer->write("@", 1, written_len))) { + LOG_WARN("fail to write @", K(ret)); + } else if (1 != written_len) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("not write completely", K(written_len), K(ret)); + } else if (OB_FAIL(write_buffer->write(tenant_name.ptr(), tenant_name.length(), written_len))) { + LOG_WARN("fail to write tenant_name", K(ret)); + } else if (tenant_name.length() != written_len) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("not write completely", K(written_len), K(ret)); + } else { + new_name_len = tenant_name.length() + result.user_name_.length() + 1; + } + } + LOG_DEBUG("change user name", K(result), K(tenant_name)); + } + // Write the rest of the message + if (OB_SUCC(ret)) { + if (OB_FAIL(write_buffer->write("\0", 1, written_len))) { + LOG_WARN("fail to write string null", K(ret)); + } else if (1 != written_len) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("not write completely", K(written_len), K(ret)); + } else if (OB_FAIL(write_buffer->write(buf + name_len + 1, len - MYSQL_NET_META_LENGTH - name_len - 1, written_len))) { + LOG_WARN("fail to write left buffer", K(ret)); + } else if (written_len != len - MYSQL_NET_META_LENGTH - name_len - 1) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("not write completely", K(written_len), K(ret)); + } else if (get_client_session_protocol() == ObProxyProtocol::PROTOCOL_OB20) { + char crc_buf[4]; + memset(crc_buf, 0, sizeof(crc_buf)); + if (OB_FAIL(write_buffer->write(crc_buf, 4, written_len))) { + LOG_WARN("fail to write crc_buf", K(ret)); + } else if (4 != written_len) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("not write completely", K(written_len), K(ret)); + } + } + } + // Re-modify the message length + if (OB_SUCC(ret)) { + uint32_t new_len = static_cast(len - MYSQL_NET_HEADER_LENGTH + new_name_len - name_len); + client_buffer_reader_->replace(reinterpret_cast(&new_len), 3, 0); + ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; + client_request.get_packet_meta().pkt_len_ = new_len + MYSQL_NET_HEADER_LENGTH; + if (OB_FAIL(client_request.add_request(client_buffer_reader_, trans_state_.mysql_config_params_->request_buffer_length_))) { + LOG_WARN("fail to add com request", K(ret)); + } + } + } + } + } + return ret; +} + int ObMysqlSM::analyze_login_request(ObRequestAnalyzeCtx &ctx, ObMysqlAnalyzeStatus &status) { int ret = OB_SUCCESS; @@ -2070,7 +2320,7 @@ int ObMysqlSM::analyze_login_request(ObRequestAnalyzeCtx &ctx, ObMysqlAnalyzeSta if (NULL == unix_vc) { ret = OB_ERR_UNEXPECTED; LOG_WARN("client entry vc is null", K(ret)); - } else if (hsr.response_.is_ssl_request() && !unix_vc->ssl_connected()) { + } else if (!client_session_->is_proxy_mysql_client_ && hsr.response_.is_ssl_request() && !unix_vc->ssl_connected()) { if (OB_FAIL(unix_vc->ssl_init(ObUnixNetVConnection::SSL_SERVER, client_session_->get_vip_cluster_name(), client_session_->get_vip_tenant_name()))) { @@ -2098,7 +2348,7 @@ int ObMysqlSM::analyze_login_request(ObRequestAnalyzeCtx &ctx, ObMysqlAnalyzeSta LOG_WARN("fail to check user sharding", K_(sm_id), K(ret)); // add some message for login error bool need_response_for_stmt = false; - ObProxyShardUtils::build_error_packet(ret, need_response_for_stmt, trans_state_); + ObProxyShardUtils::build_error_packet(ret, need_response_for_stmt, trans_state_, client_session_); // As long as the check user fails, the link will be broken trans_state_.current_.state_ = ObMysqlTransact::INTERNAL_ERROR; //save user name, tenant name, cluster name @@ -2121,7 +2371,9 @@ int ObMysqlSM::analyze_login_request(ObRequestAnalyzeCtx &ctx, ObMysqlAnalyzeSta SESSION_PROMETHEUS_STAT(client_session_->get_session_info(), PROMETHEUS_CURRENT_SESSION, true, 1); SESSION_PROMETHEUS_STAT(client_session_->get_session_info(), PROMETHEUS_USED_CONNECTIONS, 1); client_session_->set_conn_prometheus_decrease(true); - if (!can_pass_white_list()) { + // Private cloud scenario is_vip_lookup_success is flase + // When the public cloud is_vip_lookup_success is false, you also need to go through the whitelist process + if (!client_session_->is_vip_lookup_success() && !can_pass_white_list()) { status = ANALYZE_CAN_NOT_PASS_WHITE_LIST_ERROR; } else if (check_connection_throttle()) { // check client connection throttle count @@ -2129,18 +2381,22 @@ int ObMysqlSM::analyze_login_request(ObRequestAnalyzeCtx &ctx, ObMysqlAnalyzeSta LOG_WARN("fail to encode throttle message", K_(sm_id), K(ret)); } status = ANALYZE_ERROR; // disconnect - } else if (check_vt_connection_throttle()) { - // check cloud vip connection throttle count - if (OB_FAIL(encode_error_message(OB_ERR_CON_COUNT_ERROR))) { - LOG_WARN("fail to encode vip throttle message", K_(sm_id), K(ret)); - } - status = ANALYZE_ERROR; // disconnect + } else if (OB_FAIL(analyze_capacity_flag_from_client())) { + LOG_WARN("fail to analyze capacity flag from client", K(ret)); + status = ANALYZE_ERROR; } else { - client_session_->set_vip_connection_decrease(true); + if (check_vt_connection_throttle()) { + // check cloud vip connection throttle count + if (OB_FAIL(encode_error_message(OB_ERR_CON_COUNT_ERROR))) { + LOG_WARN("fail to encode vip throttle message", K_(sm_id), K(ret)); + } + status = ANALYZE_ERROR; // disconnect + } else { + client_session_->set_vip_connection_decrease(true); + } } } - // the data which remains in client_buffer_reader_ is orig auth request, // and will not send to observer; // later we will rewrite_first_login_req, send first_auth_req to observer @@ -2151,11 +2407,7 @@ int ObMysqlSM::analyze_login_request(ObRequestAnalyzeCtx &ctx, ObMysqlAnalyzeSta if (!client_session_->is_proxy_mysql_client_) { net::ObIpEndpoint client_addr; - if (client_session_->is_need_convert_vip_to_tname()) { - net::ops_ip_copy(client_addr, client_session_->get_netvc()->get_real_client_addr()); - } else { - net::ops_ip_copy(client_addr, client_session_->get_netvc()->get_remote_addr()); - } + net::ops_ip_copy(client_addr, ops_ip_sa_cast(client_session_->get_real_client_addr().get_sockaddr())); LOG_INFO("client login audit", K(client_addr), K(hsr.cluster_name_), K(hsr.tenant_name_), K(hsr.user_name_), "status", ret == OB_SUCCESS && status != ANALYZE_ERROR ? "success" : "failed"); } @@ -2174,24 +2426,19 @@ int ObMysqlSM::do_analyze_ps_prepare_request(const ObString &ps_sql) ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; ObPsEntry *ps_entry = NULL; + ObGlobalPsEntry *global_ps_entry = NULL; ObPsIdEntry *ps_id_entry = NULL; - bool is_new_ps_entry = false; - - ObBasePsEntryCache &ps_entry_cache = self_ethread().get_ps_entry_cache(); - ps_entry_cache.get_ps_entry(ps_sql, ps_entry); - - if (NULL == ps_entry) { - if (OB_FAIL(ObPsEntry::alloc_and_init_ps_entry(ps_sql, client_request.get_parse_result(), ps_entry))) { - LOG_WARN("fail to alloc and init ps entry", K(ret)); - } else if (OB_FAIL(ps_entry_cache.set_ps_entry(ps_entry))) { - LOG_WARN("fail to add ps entry to cache", K(ret)); - if (OB_LIKELY(NULL != ps_entry)) { - ps_entry->destroy(); - ps_entry = NULL; - } + if (get_global_proxy_config().enable_global_ps_cache) { + ObBasePsEntryGlobalCache& ps_entry_global_cache = get_global_ps_entry_cache(); + if (OB_FAIL(ps_entry_global_cache.acquire_or_create_ps_entry(ps_sql, client_request.get_parse_result(), global_ps_entry))) { + LOG_WARN("create ps entry failed", K(ps_sql), K(ret)); } else { - ps_entry->inc_ref(); - is_new_ps_entry = true; + ps_entry = global_ps_entry; + } + } else { + ObBasePsEntryThreadCache &ps_entry_thread_cache = self_ethread().get_ps_entry_cache(); + if (OB_FAIL(ps_entry_thread_cache.acquire_or_create_ps_entry(ps_sql, client_request.get_parse_result(), ps_entry))) { + LOG_WARN("create ps entry failed", K(ps_sql), K(ret)); } } @@ -2201,21 +2448,20 @@ int ObMysqlSM::do_analyze_ps_prepare_request(const ObString &ps_sql) LOG_WARN("fail to alloc ps id entry", K(ret)); } else if (OB_FAIL(session_info.add_ps_id_entry(ps_id_entry))) { LOG_WARN("fail to add ps id entry", KPC(ps_entry), K(ret)); - if (OB_LIKELY(NULL != ps_id_entry)) { - ps_id_entry->destroy(); - ps_id_entry = NULL; - } } else { // set current ps info session_info.set_ps_entry(ps_id_entry->ps_entry_); session_info.set_client_ps_id(ps_id_entry->ps_id_); session_info.set_ps_id_entry(ps_id_entry); } - } - - if (is_new_ps_entry) { - ps_entry->dec_ref(); - ps_entry = NULL; + if (OB_FAIL(ret)) { + if (OB_LIKELY(NULL != ps_id_entry)) { + ps_id_entry->destroy(); + ps_id_entry = NULL; + } else if (OB_LIKELY(NULL == ps_id_entry && NULL != ps_entry)) { + ps_entry->dec_ref(); + } + } } return ret; } @@ -2228,6 +2474,8 @@ int ObMysqlSM::analyze_ps_prepare_request() ObString ps_sql = client_request.get_sql(); char *ps_sql_buf = NULL; int64_t complete_sql_len = client_request.get_packet_len() - MYSQL_NET_META_LENGTH; + LOG_DEBUG("analyze ps prepare req", K(complete_sql_len), K(ps_sql.length()), K(ps_sql)); + if (complete_sql_len > ps_sql.length()) { if (OB_ISNULL(ps_sql_buf = static_cast(op_fixed_mem_alloc(complete_sql_len)))) { ret = OB_ALLOCATE_MEMORY_FAILED; @@ -2235,6 +2483,7 @@ int ObMysqlSM::analyze_ps_prepare_request() } else { client_buffer_reader_->copy(ps_sql_buf, complete_sql_len, MYSQL_NET_META_LENGTH); ps_sql.assign_ptr(ps_sql_buf, static_cast(complete_sql_len)); + LOG_DEBUG("after ps sql", K(ps_sql), K(complete_sql_len)); } } @@ -2473,15 +2722,16 @@ int ObMysqlSM::analyze_ps_execute_request(bool is_large_request) return ret; } -int ObMysqlSM::analyze_text_ps_prepare_request() +int ObMysqlSM::analyze_text_ps_prepare_request(const ObRequestAnalyzeCtx &ctx) { int ret = OB_SUCCESS; - ObClientSessionInfo &session_info = client_session_->get_session_info(); ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; ObString text_ps_sql = client_request.get_sql(); char *text_ps_sql_buf = NULL; - int64_t complete_sql_len = client_request.get_packet_len() - MYSQL_NET_META_LENGTH; + char *text_ps_prepare_buf = NULL; + int64_t text_ps_prepare_buf_len = 0; + int64_t complete_sql_len = client_request.get_packet_len() - MYSQL_NET_META_LENGTH; if (complete_sql_len > text_ps_sql.length()) { if (OB_ISNULL(text_ps_sql_buf = static_cast(op_fixed_mem_alloc(complete_sql_len)))) { ret = OB_ALLOCATE_MEMORY_FAILED; @@ -2492,76 +2742,206 @@ int ObMysqlSM::analyze_text_ps_prepare_request() } } - ObTextPsNameEntry *text_ps_name_entry = session_info.get_text_ps_name_entry(client_request.get_parse_result().get_text_ps_name()); + if (OB_SUCC(ret)) { + if (OB_FAIL(do_parse_text_ps_prepare_sql(text_ps_prepare_buf, text_ps_prepare_buf_len, text_ps_sql, ctx))) { + LOG_WARN("fail to do_parse_text_ps_prepare_sql", K(ret)); + } else if (OB_FAIL(do_analyze_text_ps_prepare_request(text_ps_sql))) { + LOG_WARN("fail to do_analyze_text_ps_prepare_request", K(text_ps_sql), K(ret)); + } + } + + if (NULL != text_ps_sql_buf) { + op_fixed_mem_free(text_ps_sql_buf, complete_sql_len); + } + if (NULL != text_ps_prepare_buf) { + op_fixed_mem_free(text_ps_prepare_buf, text_ps_prepare_buf_len); + } + return ret; +} + +int ObMysqlSM::do_parse_text_ps_prepare_sql(char*& text_ps_prepare_buf, + int64_t& text_ps_prepare_buf_len, + ObString& text_ps_sql, const ObRequestAnalyzeCtx& ctx) +{ + int ret = OB_SUCCESS; + + ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; + ObClientSessionInfo &cs_info = client_session_->get_session_info(); + + // If it is SET @s = CONCAT('SELECT * FROM ', 't1'); PREPARE stmt3 FROM @s; + // This prepare statement needs to be parsed once + ObProxyTextPsInfo prepare_info = client_request.get_parse_result().text_ps_info_; + if (1 == prepare_info.param_count_) { + ObProxyTextPsParam* param = prepare_info.params_.at(0); + ObString user_name = param->str_value_.config_string_; + ObObj user_value; + if (OB_FAIL(cs_info.get_user_variable_value(user_name, user_value))) { + LOG_WARN("get user variable failed", K(ret), K(user_name)); + } else if (!user_value.is_varchar()) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid extra info value type", K(ret), K(user_value)); + } else { + const char* prepare_pos = text_ps_sql.find('@'); + ObString prepare = text_ps_sql.split_on(prepare_pos); + text_ps_prepare_buf_len = prepare.length() + user_value.get_string().length() + 2; + text_ps_prepare_buf = reinterpret_cast(op_fixed_mem_alloc(text_ps_prepare_buf_len)); + if (OB_UNLIKELY(NULL == text_ps_prepare_buf)) { + ret = common::OB_ALLOCATE_MEMORY_FAILED; + PROXY_LOG(ERROR, "fail to alloc mem", K(text_ps_prepare_buf_len), K(ret)); + } else { + MEMCPY(text_ps_prepare_buf, prepare.ptr(), prepare.length()); + MEMCPY(text_ps_prepare_buf + prepare.length(), user_value.get_string().ptr(), user_value.get_string().length()); + text_ps_sql.reset(); + text_ps_sql.assign_ptr(text_ps_prepare_buf, static_cast(text_ps_prepare_buf_len)); + int64_t pos = prepare.length() + user_value.get_string().length(); + MEMSET(text_ps_prepare_buf + pos, 0, 2); + ObProxySqlParser sql_parser; + ObSqlParseResult &sql_parse_result = client_request.get_parse_result(); + sql_parse_result.reset(); + bool use_lower_case_name = false; + if (!ctx.is_sharding_mode_ && !cs_info.is_oracle_mode()) { + use_lower_case_name = ctx.cached_variables_->need_use_lower_case_names(); + } + if (OB_FAIL(sql_parser.parse_sql(text_ps_sql, ctx.parse_mode_, sql_parse_result, + use_lower_case_name, + ctx.connection_collation_, + ctx.drop_origin_db_table_name_, + client_request.is_sharding_user()))) { + LOG_WARN("fail to parse sql", K(text_ps_sql), K(ret)); + } else { + LOG_DEBUG("succ to parse sql", K(text_ps_sql)); + } + } + } + } + return ret; +} + +int ObMysqlSM::do_analyze_text_ps_prepare_request(const ObString& text_ps_sql) +{ + int ret = OB_SUCCESS; + + // here we have the complete request in miobuffer, but client request buffer with + // configured request_buffer_length may be not enough to copy all data, + // we need copy complete ps sql + ObClientSessionInfo &session_info = client_session_->get_session_info(); + ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; + ObTextPsEntry *text_ps_entry = NULL; + ObGlobalTextPsEntry *global_text_ps_entry = NULL; + ObString text_ps_name = client_request.get_parse_result().get_text_ps_name(); + ObTextPsNameEntry *text_ps_name_entry = session_info.get_text_ps_name_entry(text_ps_name); + LOG_DEBUG("prepare text ps name", K(client_request.get_parse_result().get_text_ps_name())); if (OB_SUCC(ret) && NULL != text_ps_name_entry) { - if (OB_FAIL(session_info.delete_text_ps_name_entry(text_ps_name_entry))) { + uint32_t client_ps_id = text_ps_name_entry->version_; + if (OB_FAIL(session_info.delete_text_ps_name_entry(text_ps_name))) { LOG_WARN("delete text ps name entry failed", K(ret), KPC(text_ps_name_entry)); } else { - LOG_DEBUG("delete from text ps name entry", KPC(text_ps_name_entry)); + session_info.remove_ps_id_addrs(client_ps_id); + ObMysqlServerSession* server_session = NULL; + server_session = client_session_->get_server_session(); + if (OB_NOT_NULL(server_session)) { + server_session->get_session_info().remove_text_ps_version(client_ps_id); + } + int64_t svr_session_count = client_session_->get_session_manager().get_svr_session_count(); + for (int64_t i = 0; i < svr_session_count; ++i) { + server_session = client_session_->get_session_manager().get_server_session(i); + if (OB_NOT_NULL(server_session)) { + server_session->get_session_info().remove_text_ps_version(client_ps_id); + } + } + LOG_DEBUG("delete text ps name entry succed", K(client_ps_id), KPC(text_ps_name_entry)); + } + } + + if (get_global_proxy_config().enable_global_ps_cache) { + ObBasePsEntryGlobalCache& text_ps_entry_global_cache = get_global_text_ps_entry_cache(); + if (OB_FAIL(text_ps_entry_global_cache.acquire_or_create_ps_entry(text_ps_sql, client_request.get_parse_result(), global_text_ps_entry))) { + LOG_WARN("create text ps entry failed", K(text_ps_sql), K(ret)); + } else { + text_ps_entry = global_text_ps_entry; + } + } else { + ObBasePsEntryThreadCache &text_ps_entry_thread_cache = self_ethread().get_text_ps_entry_cache(); + if (OB_FAIL(text_ps_entry_thread_cache.acquire_or_create_ps_entry(text_ps_sql, client_request.get_parse_result(), text_ps_entry))) { + LOG_WARN("create text ps entry failed", K(text_ps_sql), K(ret)); } } if (OB_SUCC(ret)) { - ObTextPsEntry *text_ps_entry = NULL; - if (OB_FAIL(ObTextPsEntry::alloc_and_init_text_ps_entry( - text_ps_sql, client_request.get_parse_result(), text_ps_entry))) { - LOG_WARN("fail to alloc and init text ps entry", K(ret)); - } else if (OB_FAIL(client_session_->add_text_ps_entry(text_ps_entry))) { - LOG_WARN("fail to add text ps entry to cache", K(ret)); - if (OB_LIKELY(NULL != text_ps_entry)) { - text_ps_entry->destroy(); - text_ps_entry = NULL; - } - } else if (OB_FAIL(ObTextPsNameEntry::alloc_text_ps_name_entry( - client_request.get_parse_result().get_text_ps_name(), - text_ps_entry, text_ps_name_entry))) { + if (OB_FAIL(ObTextPsNameEntry::alloc_text_ps_name_entry( + client_request.get_parse_result().get_text_ps_name(), text_ps_entry, text_ps_name_entry))) { LOG_WARN("fail to alloc text ps name entry", K(ret)); } else if (OB_FAIL(session_info.add_text_ps_name_entry(text_ps_name_entry))) { LOG_WARN("fail to add text ps name entry", KPC(text_ps_name_entry), K(ret)); + } else { + text_ps_name_entry->version_ = client_session_->inc_and_get_ps_id(); + session_info.set_client_ps_id(text_ps_name_entry->version_); + session_info.set_text_ps_name_entry(text_ps_name_entry); + LOG_DEBUG("session info add text ps name", K(client_request.get_parse_result().get_text_ps_name())); + } + if (OB_FAIL(ret)) { if (OB_LIKELY(NULL != text_ps_name_entry)) { text_ps_name_entry->destroy(); text_ps_name_entry = NULL; + } else if (OB_LIKELY(NULL == text_ps_name_entry && NULL != text_ps_entry)) { + text_ps_entry->destroy(); } - } else { - text_ps_entry->set_version(client_session_->inc_and_get_ps_id()); } } + return ret; +} - if (OB_SUCC(ret)) { - session_info.set_text_ps_entry(text_ps_name_entry->text_ps_entry_); - session_info.set_client_text_ps_name(client_request.get_parse_result().get_text_ps_name()); - LOG_DEBUG("session info add text ps name", K(client_request.get_parse_result().get_text_ps_name())); +int ObMysqlSM::analyze_text_ps_execute_request() +{ + int ret = OB_SUCCESS; - if (NULL != text_ps_sql_buf) { - op_fixed_mem_free(text_ps_sql_buf, complete_sql_len); - text_ps_sql_buf = NULL; - } + ObClientSessionInfo &session_info = client_session_->get_session_info(); + ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; + const ObString &text_ps_name = client_request.get_parse_result().get_text_ps_name(); + ObTextPsEntry* text_ps_entry = NULL; + ObTextPsNameEntry* text_ps_name_entry = NULL; + LOG_DEBUG("execute text ps name", K(text_ps_name)); + if (OB_ISNULL(text_ps_name_entry = session_info.get_text_ps_name_entry(text_ps_name))) { + LOG_WARN("text ps name entry does not exist", K(text_ps_name), KPC(text_ps_entry)); + // if not execute 'prepare stmt1', send 'execute stmt1' to server. server will return error msg + client_request.get_parse_result().set_stmt_type(OBPROXY_T_OTHERS); + } else if (OB_ISNULL(text_ps_entry = text_ps_name_entry->text_ps_entry_) || !text_ps_entry->is_valid()) { + LOG_WARN("text ps entry does not exist", K(text_ps_name), KPC(text_ps_entry)); + // if not execute 'prepare stmt1', send 'execute stmt1' to server. server will return error msg + client_request.get_parse_result().set_stmt_type(OBPROXY_T_OTHERS); + } else { + session_info.set_client_ps_id(text_ps_name_entry->version_); + session_info.set_text_ps_name_entry(text_ps_name_entry); + client_request.set_text_ps_parse_result(&text_ps_entry->get_base_ps_parse_result()); } return ret; } -int ObMysqlSM::analyze_text_ps_execute_request() +int ObMysqlSM::analyze_text_ps_drop_request() { int ret = OB_SUCCESS; ObClientSessionInfo &session_info = client_session_->get_session_info(); ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; const ObString &text_ps_name = client_request.get_parse_result().get_text_ps_name(); - ObTextPsEntry *entry = NULL; - - if (OB_ISNULL(entry = session_info.get_text_ps_entry(text_ps_name)) || !entry->is_valid()) { - LOG_WARN("text ps entry does not exist", K(text_ps_name), KPC(entry)); - // if not execute 'prepare stmt1', send 'execute stmt1' to server. server will return error msg + ObTextPsEntry* text_ps_entry = NULL; + ObTextPsNameEntry* text_ps_name_entry = NULL; + LOG_DEBUG("drop text ps name", K(text_ps_name)); + if (OB_ISNULL(text_ps_name_entry = session_info.get_text_ps_name_entry(text_ps_name))) { + ret = OB_ERR_PREPARE_STMT_NOT_FOUND; + LOG_WARN("text ps name entry does not exist", K(text_ps_name), KPC(text_ps_entry)); + if (OB_SUCCESS != encode_error_message(OB_ERR_PREPARE_STMT_NOT_FOUND)) { + LOG_WARN("fail to encode error message", K(ret)); + } + } else if (OB_ISNULL(text_ps_entry = text_ps_name_entry->text_ps_entry_) || !text_ps_entry->is_valid()) { + LOG_WARN("text ps entry does not exist", K(text_ps_name), KPC(text_ps_entry)); + // If drop stmt1, stmt1 does not have prepare and execute, send it directly to the server, and let the server return an error message client_request.get_parse_result().set_stmt_type(OBPROXY_T_OTHERS); } else { - session_info.set_text_ps_entry(entry); - session_info.set_client_text_ps_name(text_ps_name); - session_info.set_text_ps_execute(true); - client_request.set_text_ps_parse_result(&entry->get_base_ps_parse_result()); + session_info.set_client_ps_id(text_ps_name_entry->version_); } - return ret; } @@ -2586,7 +2966,7 @@ int ObMysqlSM::analyze_fetch_request() return ret; } -int ObMysqlSM::analyze_close_request() +int ObMysqlSM::analyze_close_reset_request() { int ret = OB_SUCCESS; @@ -2659,6 +3039,7 @@ int ObMysqlSM::state_watch_for_client_abort(int event, void *data) case VC_EVENT_ERROR: case VC_EVENT_ACTIVE_TIMEOUT: case VC_EVENT_INACTIVITY_TIMEOUT: + case VC_EVENT_DETECT_SERVER_DEAD: if (tunnel_.is_tunnel_active()) { // Check to see if the client is part of the tunnel. // If so forward the event to the tunnel. Otherwise, @@ -2688,6 +3069,16 @@ int ObMysqlSM::state_watch_for_client_abort(int event, void *data) milestones_.client_.client_end_ = get_based_hrtime(); set_client_abort(ObMysqlTransact::ABORTED, event); update_congestion_entry(event); + if (OB_MYSQL_COM_QUIT != trans_state_.trans_info_.client_request_.get_packet_meta().cmd_) { + if (NULL != trans_state_.congestion_entry_) { + trans_state_.congestion_entry_->set_client_feedback_failed_at(event::get_hrtime()); + if (trans_state_.congestion_entry_->client_feedback_congested_) { + if (NULL != sm_cluster_resource_) { + sm_cluster_resource_->alive_addr_set_.set_refactored(trans_state_.congestion_entry_->server_ip_); + } + } + } + } terminate_sm_ = true; break; @@ -2948,7 +3339,6 @@ int ObMysqlSM::state_observer_open(int event, void *data) trans_state_.current_.send_action_ = ObMysqlTransact::SERVER_SEND_HANDSHAKE; } LOG_DEBUG("succ to establish server sesssion", K_(sm_id)); - handle_observer_open(); } } @@ -3033,6 +3423,7 @@ int ObMysqlSM::state_server_response_read(int event, void *data) // fall through case VC_EVENT_ERROR: case VC_EVENT_ACTIVE_TIMEOUT: + case VC_EVENT_DETECT_SERVER_DEAD: LOG_WARN("ObMysqlSM::state_server_response_read", "event", ObMysqlDebugNames::get_event_name(event), K_(sm_id)); // Error handling function @@ -3050,6 +3441,28 @@ int ObMysqlSM::state_server_response_read(int event, void *data) } } + if (enable_record_full_link_trace_info()) { + SET_TRACE_BUFFER(flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + LOG_DEBUG("state server response read begin."); + + // server process req end + trace::ObSpanCtx *server_process_req_ctx = flt_.trace_log_info_.server_process_req_ctx_; + if (OB_NOT_NULL(server_process_req_ctx)) { + LOG_DEBUG("end span ob_proxy_server_process_req", K(server_process_req_ctx->span_id_)); + FLT_END_SPAN(server_process_req_ctx); + flt_.trace_log_info_.server_process_req_ctx_ = NULL; + } + + // client response write begin, check inited or not, only init it once + if (flt_.trace_log_info_.client_response_write_ctx_ == NULL) { + trace::ObSpanCtx *ctx = FLT_BEGIN_SPAN(ob_proxy_client_response_write); + if (OB_NOT_NULL(ctx)) { + flt_.trace_log_info_.client_response_write_ctx_ = ctx; + LOG_DEBUG("begin span ob_proxy_client_response_write", K(ctx->span_id_)); + } + } + } + if (OB_SUCC(ret)) { // Reset the inactivity timeout if this is the first // time we've been called. The timeout had been set to @@ -3062,8 +3475,7 @@ int ObMysqlSM::state_server_response_read(int event, void *data) } bool need_receive_completed = false; - if (OB_UNLIKELY((NULL != client_session_ && client_session_->is_proxy_mysql_client_) - || ObMysqlTransact::SERVER_SEND_REQUEST != trans_state_.current_.send_action_)) { + if (ObMysqlTransact::SERVER_SEND_REQUEST != trans_state_.current_.send_action_) { need_receive_completed = true; } @@ -3090,6 +3502,19 @@ int ObMysqlSM::state_server_response_read(int event, void *data) - cmd_time_stats_.server_response_analyze_time_); } } + + ObMysqlResp &server_response = trans_state_.trans_info_.server_response_; + if (enable_record_full_link_trace_info() + && (server_response.get_analyze_result().is_resp_completed() + || server_response.get_analyze_result().is_trans_completed())) { + trace::ObSpanCtx *ctx = flt_.trace_log_info_.server_response_read_ctx_; + if (OB_NOT_NULL(ctx)) { + LOG_DEBUG("end span ob_proxy_server_response_read", K(ctx->span_id_)); + SET_TRACE_BUFFER(flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + FLT_END_SPAN(ctx); + flt_.trace_log_info_.server_response_read_ctx_ = NULL; + } + } } switch (state) { @@ -3134,12 +3559,15 @@ int ObMysqlSM::state_server_response_read(int event, void *data) if (ObMysqlTransact::SERVER_SEND_REQUEST == trans_state_.current_.send_action_) { set_client_wait_timeout(); } - + + // skip the response handling plugins or not trans_state_.current_.state_ = ObMysqlTransact::CONNECTION_ALIVE; trans_state_.transact_return_point = ObMysqlTransact::handle_response; if (OB_MYSQL_COM_QUERY == trans_state_.trans_info_.sql_cmd_ + && (ObProxyProtocol::PROTOCOL_OB20 != get_client_session_protocol() + || ObMysqlTransact::SERVER_SEND_REQUEST != trans_state_.current_.send_action_) && (trans_state_.trans_info_.server_response_.get_analyze_result().is_decompressed() - || PROTOCOL_NORMAL == use_compression_protocol())) { + || ObProxyProtocol::PROTOCOL_NORMAL == get_server_session_protocol())) { skip_plugin_ = true; } callout_api_and_start_next_action(ObMysqlTransact::SM_ACTION_API_READ_RESPONSE); @@ -3195,25 +3623,37 @@ int ObMysqlSM::state_server_response_read(int event, void *data) ObMysqlCompressAnalyzer& ObMysqlSM::get_compress_analyzer() { - if (PROTOCOL_OB20 == use_compression_protocol()) { + if (ObProxyProtocol::PROTOCOL_OB20 == get_server_session_protocol()) { return compress_ob20_analyzer_; } else { return compress_analyzer_; } } -ObProxyProtocol ObMysqlSM::use_compression_protocol() const +ObProxyProtocol ObMysqlSM::get_server_session_protocol() const { // in auth, do not use compress prototcol if (NULL == server_session_ || (!server_session_->is_checksum_supported() && !server_session_->is_ob_protocol_v2_supported()) || ObMysqlTransact::SERVER_SEND_SAVED_LOGIN == trans_state_.current_.send_action_ || ObMysqlTransact::SERVER_SEND_LOGIN == trans_state_.current_.send_action_ - || ObMysqlTransact::SERVER_SEND_HANDSHAKE == trans_state_.current_.send_action_) { - return PROTOCOL_NORMAL; + || ObMysqlTransact::SERVER_SEND_HANDSHAKE == trans_state_.current_.send_action_ + || ObMysqlTransact::is_binlog_request(trans_state_)) { + return ObProxyProtocol::PROTOCOL_NORMAL; } else if (server_session_->is_ob_protocol_v2_supported()) { - return PROTOCOL_OB20; + return ObProxyProtocol::PROTOCOL_OB20; + } else { + return ObProxyProtocol::PROTOCOL_CHECKSUM; // current checksum is supported by zlib + } +} + +ObProxyProtocol ObMysqlSM::get_client_session_protocol() const +{ + if (client_session_ == NULL + || !client_session_->get_session_info().is_client_support_ob20_protocol() + || trans_state_.is_auth_request_) { + return ObProxyProtocol::PROTOCOL_NORMAL; } else { - return PROTOCOL_CHECKSUM; // current checksum is supported by zlib + return ObProxyProtocol::PROTOCOL_OB20; } } @@ -3252,7 +3692,7 @@ bool ObMysqlSM::need_reject_user_login(const ObString &user, const ObString &ten bret = (!get_global_proxy_config().skip_proxyro_check && tenant.case_compare(OB_SYS_TENANT_NAME) == 0 && user.case_compare(ObProxyTableInfo::READ_ONLY_USERNAME_USER) == 0) - || (is_cloud_user && !get_global_proxy_config().enable_cloud_full_username + || (is_cloud_user && !enable_cloud_full_username_ && (has_tenant_username || has_cluster_username)) || (!is_cloud_user && get_global_proxy_config().enable_full_username && (!has_cluster_username || !has_tenant_username)); @@ -3265,7 +3705,7 @@ uint8_t ObMysqlSM::get_request_seq() { uint8_t seq = 0; - if (use_compression_protocol() == PROTOCOL_CHECKSUM) { + if (get_server_session_protocol() == ObProxyProtocol::PROTOCOL_CHECKSUM) { if (ObMysqlTransact::SERVER_SEND_REQUEST == trans_state_.current_.send_action_) { seq = trans_state_.trans_info_.client_request_.get_packet_meta().pkt_seq_; } else { @@ -3337,9 +3777,10 @@ inline int ObMysqlSM::handle_oceanbase_first_response_packet(ObMysqlAnalyzeStatu { int ret = OB_SUCCESS; - ObProxyProtocol ob_proxy_protocol = use_compression_protocol(); + ObProxyProtocol ob_proxy_protocol = get_server_session_protocol(); - if (OB_UNLIKELY(PROTOCOL_CHECKSUM == ob_proxy_protocol || PROTOCOL_OB20 == ob_proxy_protocol)) { // compressed protocol + if (OB_UNLIKELY(ObProxyProtocol::PROTOCOL_CHECKSUM == ob_proxy_protocol + || ObProxyProtocol::PROTOCOL_OB20 == ob_proxy_protocol)) { // compressed protocol if (OB_FAIL(handle_first_compress_response_packet(state, need_receive_completed, first_pkt_len))) { LOG_WARN("fail to handle_first_compress_response_packet", K(need_receive_completed), K(ret)); } @@ -3368,12 +3809,17 @@ inline int ObMysqlSM::handle_first_compress_response_packet(ObMysqlAnalyzeStatus if (server_buffer_reader_->is_read_avail_more_than(MYSQL_COMPRESSED_HEALDER_LENGTH)) { ObMysqlCompressAnalyzer::AnalyzeMode mode; - if (!need_receive_completed || ObMysqlTransact::SERVER_SEND_REQUEST != trans_state_.current_.send_action_) { + if (ObMysqlTransact::SERVER_SEND_XA_START == trans_state_.current_.send_action_) { + mode = ObMysqlCompressAnalyzer::DECOMPRESS_MODE; + } else if (!need_receive_completed || ObMysqlTransact::SERVER_SEND_REQUEST != trans_state_.current_.send_action_) { mode = ObMysqlCompressAnalyzer::SIMPLE_MODE; } else { mode = ObMysqlCompressAnalyzer::DECOMPRESS_MODE; } + LOG_DEBUG("handle first compress resp, print tag", + K(mode), K(need_receive_completed), K(trans_state_.current_.send_action_)); + if (OB_FAIL(compress_analyzer->init(req_seq, mode, cmd, mysql_mode, enable_extra_ok_packet_for_stats, req_seq, server_session_->get_server_request_id(), server_session_->get_server_sessid()))) { @@ -3383,16 +3829,21 @@ inline int ObMysqlSM::handle_first_compress_response_packet(ObMysqlAnalyzeStatus LOG_WARN("fail to analyze first response", K(server_buffer_reader_), K(need_receive_completed), K(server_response), K_(sm_id), K(ret)); } else { - LOG_DEBUG("after first response", K(req_seq), K(result), "is_resp_finished", - server_response.get_analyze_result().is_resp_completed(), - "is_trans_finished", server_response.get_analyze_result().is_trans_completed()); - if (ANALYZE_DONE == result.status_ && PROTOCOL_CHECKSUM == use_compression_protocol()) { + ObRespAnalyzeResult &analyze_result = server_response.get_analyze_result(); + LOG_DEBUG("after first response", K(req_seq), + "is_resp_finished", analyze_result.is_resp_completed(), + "is_trans_finished", analyze_result.is_trans_completed(), + K(result), K(server_response)); + if (ANALYZE_DONE == result.status_ && ObProxyProtocol::PROTOCOL_CHECKSUM == get_server_session_protocol()) { check_update_checksum_switch(result.is_checksum_on_); } state = result.status_; first_pkt_len = result.header_.compressed_len_ + MYSQL_COMPRESSED_HEALDER_LENGTH; cmd_size_stats_.server_response_bytes_ = server_buffer_reader_->read_avail(); + + // save flt from response analyze result to sm + save_response_flt_result_to_sm(analyze_result.flt_); } } else { state = ANALYZE_CONT; @@ -3400,6 +3851,179 @@ inline int ObMysqlSM::handle_first_compress_response_packet(ObMysqlAnalyzeStatus return ret; } +void ObMysqlSM::save_response_flt_result_to_sm(common::FLTObjManage &flt) +{ + // control info + if (flt.control_info_.is_valid() || flt.control_info_.is_need_send()) { + flt_.control_info_ = flt.control_info_; + flt.control_info_.reset(); + LOG_DEBUG("update control info from server response", K(flt_.control_info_)); + } + + // query info + if (flt.query_info_.is_valid()) { + flt_.query_info_ = flt.query_info_; + flt.query_info_.reset(); + LOG_DEBUG("update query info from server response", K(flt_.query_info_)); + } + + if (flt.span_info_.is_valid()) { + LOG_WARN("attention: span info in rsp valid!"); + } + if (flt.app_info_.is_valid()) { + LOG_WARN("attention: app info in rsp valid!"); + } + if (flt.driver_span_info_.is_valid()) { + LOG_WARN("attention: driver span info in rsp valid!"); + } + +} + +bool ObMysqlSM::enable_record_full_link_trace_info() +{ + return flt_.span_info_.trace_enable_ && flt_.span_info_.is_valid(); +} + +bool ObMysqlSM::is_proxy_init_trace_log_info() +{ + return flt_.trace_log_info_.is_inited_; +} + +int ObMysqlSM::handle_resp_for_end_proxy_root_span(trace::UUID &trace_id, bool is_in_trans) +{ + int ret = OB_SUCCESS; + + LOG_DEBUG("end proxy root span begin", K(flt_.span_info_), K(is_in_trans)); + + if (enable_record_full_link_trace_info()) { + SET_TRACE_BUFFER(flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + trace_id = flt_.span_info_.trace_id_; + + if (flt_.query_info_.is_valid()) { + // set tag to proxy root span and print with it + FLT_SET_TAG(query_start_ts, flt_.query_info_.query_start_ts_, query_end_ts, flt_.query_info_.query_end_ts_); + LOG_DEBUG("set observer query info tag to proxy root span", K(flt_.query_info_)); + flt_.query_info_.reset(); + } + + ObMysqlClientSession *client_session = get_client_session(); + if (!client_session->is_client_support_full_link_trace()) { + // add client ip and port to tag, inorder to classify the different io from client + net::ObIpEndpoint client_ip_point; + net::ops_ip_copy(client_ip_point, client_session->get_netvc()->get_real_client_addr()); + char client_addr_buf[INET6_ADDRSTRLEN] = {0}; + if (OB_FAIL(ops_ip_nptop(client_ip_point, client_addr_buf, INET6_ADDRSTRLEN))) { + LOG_WARN("fail to ops ip nptop", K(ret)); + } else { + const char *client_addr_ptr = client_addr_buf; + FLT_SET_TAG(client_host, client_addr_ptr); + LOG_DEBUG("set client host tag to proxy root span", K(client_addr_ptr)); + } + } + + // accord to record policy and slow query, print the log + trace::ObSpanCtx *ctx = flt_.trace_log_info_.proxy_root_span_ctx_; + if (OB_NOT_NULL(ctx)) { + LOG_DEBUG("end span ob proxy root", K(trace_id), K(ctx->span_id_), K(OBTRACE->is_auto_flush())); + FLT_END_SPAN(ctx); + flt_.trace_log_info_.proxy_root_span_ctx_ = NULL; + } + + // slow query check + int64_t slow_query_thres_in_control_info = flt_.control_info_.slow_query_threshold_; + if (!flt_.span_info_.force_print_ // do not print repeatly + && flt_.trace_log_info_.proxy_root_span_begin_time_ > 0 + && slow_query_thres_in_control_info > 0 + && (flt_.control_info_.record_policy_ == RP_ONLY_SLOW_QUERY + || flt_.control_info_.record_policy_ == RP_SAMPLE_AND_SLOW_QUERY)) { + int64_t proxy_root_span_end_time = ObTimeUtility::current_time(); + if (milestone_diff(flt_.trace_log_info_.proxy_root_span_begin_time_, proxy_root_span_end_time) + > slow_query_thres_in_control_info) { + // slow query need to print + LOG_DEBUG("succ to print slow query trace log", K(slow_query_thres_in_control_info), + K(proxy_root_span_end_time), K(flt_.trace_log_info_.proxy_root_span_begin_time_)); + FLUSH_TRACE(); + flt_.trace_log_info_.proxy_root_span_begin_time_ = -1; + } + } + + /* + * clear obtrace instance, and re-init + * if it is not force print policy, only record the current SQL span in obtrace memory + * do not print other sql span info in obtrace + * for only slow query policy, only print slow query, do not print other sql in obtrace instance + * for sample and slow query policy, force print will print all sqls, while others only print slow query + */ + if (flt_.span_info_.force_print_ == false) { + trace::UUID trace_id = OBTRACE->get_trace_id(); + trace::UUID root_span_id = OBTRACE->get_root_span_id(); + uint8_t policy = OBTRACE->get_policy(); + OBTRACE->init(trace_id, root_span_id, policy); + } + + // reset app info, after succeed to send request to observer + if (flt_.app_info_.is_valid()) { + flt_.app_info_.reset(); + } + + // reset span info, root obproxy span end, clear span info + bool trace_enable = flt_.span_info_.trace_enable_; + bool force_print = flt_.span_info_.force_print_; + flt_.span_info_.reset(); + if (is_in_trans) { + flt_.span_info_.trace_id_ = trace_id; // in trans, keep the trace id as the same before + if (is_proxy_init_trace_log_info()) { + // proxy generate trace, still in trans, save bool, save trace id, regenerate span id. + flt_.span_info_.trace_enable_ = trace_enable; + flt_.span_info_.force_print_ = force_print; + } + } + } + + return ret; +} + +int ObMysqlSM::handle_for_end_proxy_trace(trace::UUID &trace_id) +{ + int ret = OB_SUCCESS; + + if (is_proxy_init_trace_log_info()) { + LOG_DEBUG("end trace generated by proxy", K(trace_id)); + + SET_TRACE_BUFFER(flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + FLT_END_TRACE(); + + flt_.trace_log_info_.reset(); + } + + return ret; +} + +int ObMysqlSM::handle_resp_for_end_flt_trace(bool is_trans_completed) +{ + int ret = OB_SUCCESS; + trace::UUID trace_id; + + if (is_trans_completed) { + if (OB_FAIL(handle_resp_for_end_proxy_root_span(trace_id, false))) { + LOG_WARN("fail to handle resp for end span", K(ret)); + } else if (OB_FAIL(handle_for_end_proxy_trace(trace_id))) { + LOG_WARN("fail to handle resp for end trace", K(ret)); + } else { + // nothing + } + } else { + if (OB_FAIL(handle_resp_for_end_proxy_root_span(trace_id, true))) { + LOG_WARN("fail to handle resp for end span in plugin", K(ret)); + } else { + // nothing + // proxy generate trace & still in trans, do not clear the OBTRACE memory + } + } + + return ret; +} + inline int ObMysqlSM::handle_first_normal_response_packet(ObMysqlAnalyzeStatus &state, const bool need_receive_completed, int64_t &first_pkt_len) { @@ -3412,6 +4036,7 @@ inline int ObMysqlSM::handle_first_normal_response_packet(ObMysqlAnalyzeStatus & bool is_autocommit_0 = false; if (OB_FAIL(client_session_->get_session_info().field_mgr_.get_common_sys_variable_value("autocommit", obj))) { LOG_DEBUG("fail to get autocommit val", K(ret)); + ret = OB_SUCCESS; } else if (obj.get_int() == 0) { LOG_DEBUG("autocommit is 0"); is_autocommit_0 = true; @@ -3419,7 +4044,8 @@ inline int ObMysqlSM::handle_first_normal_response_packet(ObMysqlAnalyzeStatus & if (OB_LIKELY(server_buffer_reader_->is_read_avail_more_than(MYSQL_NET_META_LENGTH))) { if (OB_UNLIKELY(!client_session_->get_session_info().is_oceanbase_server() - || trans_state_.mysql_config_params_->is_mysql_routing_mode())) { + || trans_state_.mysql_config_params_->is_mysql_routing_mode() + || ObMysqlTransact::is_binlog_request(trans_state_))) { LOG_DEBUG("handle_first_normal_response_packet", K(trans_state_.current_.state_), K(is_in_trans_), K(is_autocommit_0)); analyzer_.set_server_cmd(trans_state_.trans_info_.sql_cmd_, STANDARD_MYSQL_PROTOCOL_MODE, @@ -3448,6 +4074,355 @@ inline int ObMysqlSM::handle_first_normal_response_packet(ObMysqlAnalyzeStatus & return ret; } +int ObMysqlSM::handle_first_request_packet(ObMysqlAnalyzeStatus &status, int64_t &first_packet_len) +{ + int ret = OB_SUCCESS; + LOG_DEBUG("handle first request packet begin"); + + if (get_client_session_protocol() != ObProxyProtocol::PROTOCOL_OB20) { + analyze_mysql_request(status); + } else { + ObClientSessionInfo &client_session_info = get_client_session()->get_session_info(); + if (client_session_info.ob20_request_.remain_payload_len_ == 0) { + LOG_DEBUG("handle ob20 req begin", K(client_buffer_reader_->read_avail())); + // analyze ob20 request here, do not copy mysql packet + // ensure the whole ob20 request received complete is enough + if (OB_FAIL(handle_first_compress_request_packet(status, first_packet_len))) { + LOG_WARN("fail to handle first compress request from client", K(ret), K(status), K(first_packet_len)); + } else if (status == ANALYZE_DONE) { + analyze_mysql_request(status, true); + analyze_status_after_analyze_mysql_in_ob20_payload(status, client_session_info); + } else if (status == ANALYZE_CONT) { + LOG_DEBUG("handle first compress request continue.", K(first_packet_len)); + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected ret status, handle ob20 first compress req", K(ret), K(status), K(first_packet_len)); + } + } else { + // more than one mysql packet in ob20 payload, handle it one by one + // at last, consume the tail crc of ob20 in client_buffer_reader_ + LOG_DEBUG("handle other mysql req in ob20 payload begin"); + analyze_mysql_request(status, true); + analyze_status_after_analyze_mysql_in_ob20_payload(status, client_session_info); + } + } + + LOG_DEBUG("after handle first request packet", K(status)); + + return ret; +} + +/* + * analyze ob20 request from client + * all the reqs are saved in src: client_buffer_reader_, there could be more than one mysql packet in ob20 payload data + * the strategy to avoid copy buffer is: + * 1: resolve the necessary compressed head and ob20 head info from the begging of src buffer (7 + 24) + * 2: get extra len if extra info flag is set in ob20 head flag + * 3: remain payload len = ob20.head.payload_len - extra len - 4(extra len) + * 4: consume src buffer, len = compressed head + ob20 head (7 + 24) + 4(extra len) + extra len, make sure the ptr + point to basic info in ob20 payload data(several mysql packets) + * 5: analyze mysql packet + * + * the procedure of this is compatible with the current mysql buffer consume + * take care of the end crc judgement, by remain payload len + */ +int ObMysqlSM::handle_first_compress_request_packet(ObMysqlAnalyzeStatus &status, int64_t &first_packet_len) +{ + int ret = OB_SUCCESS; + + if (client_buffer_reader_->is_read_avail_more_than(MYSQL_COMPRESSED_HEALDER_LENGTH)) { + ObMysqlCompressedOB20AnalyzeResult ob20_result; + ObMysqlCompressAnalyzer *compress_analyzer = &compress_ob20_analyzer_; // to support more compress protocol here + compress_analyzer->reset(); + + if (OB_FAIL(compress_analyzer->init(0, ObMysqlCompressAnalyzer::DECOMPRESS_MODE, OB_MYSQL_COM_MAX_NUM, + UNDEFINED_MYSQL_PROTOCOL_MODE, false, 0, 0, 0))) { + LOG_WARN("fail to init compress analyzer", K(ret)); + status = ANALYZE_ERROR; + } else if (OB_FAIL(compress_analyzer->analyze_first_request(*client_buffer_reader_, + ob20_result, + trans_state_.trans_info_.client_request_, + status))) { + LOG_WARN("fail to analyze first compress request", K(ret)); + } else if (status == ANALYZE_DONE) { + if (OB_FAIL(handle_compress_request_analyze_done(ob20_result, first_packet_len, status))) { + LOG_WARN("fail to handle compress request analyze done", K(ret)); + } + } else if (status == ANALYZE_CONT) { + first_packet_len = ob20_result.header_.compressed_len_ > 0 + ? ob20_result.header_.compressed_len_ + MYSQL_COMPRESSED_HEALDER_LENGTH + : 0; + LOG_DEBUG("analyze first compress request continue.", K(status), K(first_packet_len)); + } + } else { + status = ANALYZE_CONT; + } + + return ret; +} + +int ObMysqlSM::handle_compress_request_analyze_done(ObMysqlCompressedOB20AnalyzeResult &ob20_result, + int64_t &first_packet_len, + ObMysqlAnalyzeStatus &status) +{ + int ret = OB_SUCCESS; + + // total mysql packet len in ob20 payload = payload_len - extra_len(4) - extra_info_len (if extra exist) + int64_t remain_mysql_packets_len = 0; + if (ob20_result.ob20_header_.flag_.is_extra_info_exist()) { + remain_mysql_packets_len = static_cast(ob20_result.ob20_header_.payload_len_ + - ob20_result.extra_info_.extra_len_ + - OB20_PROTOCOL_EXTRA_INFO_LENGTH); + } else { + remain_mysql_packets_len = static_cast(ob20_result.ob20_header_.payload_len_); + } + + if (remain_mysql_packets_len <= 0) { + ret = OB_INVALID_ARGUMENT; + status = ANALYZE_ERROR; + LOG_WARN("receive err mysql packet len in ob20 payload", K(ret), K(remain_mysql_packets_len), K(ob20_result)); + } else { + first_packet_len = ob20_result.header_.compressed_len_ + MYSQL_COMPRESSED_HEALDER_LENGTH; + ObClientSessionInfo &client_session_info = get_client_session()->get_session_info(); + client_session_info.ob20_request_.remain_payload_len_ = remain_mysql_packets_len; + client_session_info.ob20_request_.ob20_request_received_done_ = true; + client_session_info.ob20_request_.ob20_header_ = ob20_result.ob20_header_; + get_client_session()->set_compressed_seq(ob20_result.ob20_header_.cp_hdr_.seq_); + LOG_DEBUG("analyze first ob20 packet finish", K(status), K(ob20_result), K(remain_mysql_packets_len), + "req compressed seq", get_client_session()->get_compressed_seq()); + + // save FLT to sm after analyze ob20 req done + save_request_flt_result_to_sm(ob20_result.flt_); + + // consume, make sure the beginning in reader_ is mysql packet + int64_t offset = MYSQL_COMPRESSED_OB20_HEALDER_LENGTH; + if (ob20_result.ob20_header_.flag_.is_extra_info_exist()) { + offset += OB20_PROTOCOL_EXTRA_INFO_LENGTH + ob20_result.extra_info_.extra_len_; + } + + if (OB_FAIL(client_buffer_reader_->consume(offset))) { + status = ANALYZE_ERROR; + LOG_WARN("fail to consume buffer", K(ret)); + } else { + LOG_DEBUG("consume the compress head and ob20 head in client buffer", + K(offset), K(client_buffer_reader_->read_avail())); + } + } + + return ret; +} + +void ObMysqlSM::analyze_status_after_analyze_mysql_in_ob20_payload(ObMysqlAnalyzeStatus &status, + ObClientSessionInfo &client_session_info) +{ + int64_t mysql_packet_len = trans_state_.trans_info_.client_request_.get_packet_len(); + int ret = OB_SUCCESS; + if (OB_LIKELY(status == ANALYZE_DONE)) { + if (OB_UNLIKELY(mysql_packet_len == MYSQL_PACKET_MAX_LENGTH)) { + status = ANALYZE_NOT_SUPPORT; + LOG_WARN("do not support full mysql packet in ob2.0 payload now", K(status)); + } + } else if (OB_UNLIKELY(status == ANALYZE_CONT)) { + status = ANALYZE_NOT_SUPPORT; + int64_t total_avail = client_buffer_reader_->read_avail(); + LOG_WARN("compress packet received done, mysql packet not received done yet, or unexpected analyze status", + K(status), K(total_avail), K(mysql_packet_len)); + } else { + LOG_WARN("unexpected status after analyze mysql in ob20 payload", K(status)); + } + + if (OB_FAIL(analyze_ob20_remain_after_analyze_mysql_request_done(client_session_info))) { + if (OB_LIKELY(status == ANALYZE_DONE)) { + if (ret == OB_NOT_SUPPORTED) { + status = ANALYZE_NOT_SUPPORT; + } else { + status = ANALYZE_ERROR; + LOG_WARN("fail to analyze ob20 remain after mysql req done", K(ret), K(status)); + } + } + } +} + +int ObMysqlSM::analyze_ob20_remain_after_analyze_mysql_request_done(ObClientSessionInfo &client_session_info) +{ + int ret = OB_SUCCESS; + + int64_t mysql_packet_len = trans_state_.trans_info_.client_request_.get_packet_len(); + int64_t remain_payload_len = client_session_info.ob20_request_.remain_payload_len_; + if (remain_payload_len < mysql_packet_len) { + ret = OB_NOT_SUPPORTED; + client_session_info.ob20_request_.remain_payload_len_ = 0; + LOG_WARN("unexpected situation after received total compress packet and total mysql packet", + K(ret), K(remain_payload_len), K(mysql_packet_len)); + } else { + client_session_info.ob20_request_.remain_payload_len_ -= mysql_packet_len; + LOG_DEBUG("analyze other mysql reqs in compress payload", K(remain_payload_len), K(mysql_packet_len)); + } + + return ret; +} + +int ObMysqlSM::handle_req_for_begin_proxy_root_span() +{ + int ret = OB_SUCCESS; + + // according to client capability + if (get_client_session()->is_client_support_full_link_trace()) { + handle_req_to_generate_root_span_from_client(); + } else { + // client do not support flt, proxy generate obtrace + if (OB_FAIL(handle_req_to_generate_root_span_by_proxy())) { + LOG_WARN("fail to do proxy generate proxy root span", K(ret)); + } + } + + return ret; +} + +void ObMysqlSM::handle_req_to_generate_root_span_from_client() +{ + // client pass span info to proxy, proxy use it directly + if (flt_.span_info_.is_valid() && flt_.control_info_.is_valid()) { + SET_TRACE_BUFFER(flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + if (enable_record_full_link_trace_info()) { + OBTRACE->init(flt_.span_info_.trace_id_, flt_.span_info_.span_id_, flt_.control_info_.level_); + if (flt_.span_info_.force_print_) { + FLT_SET_AUTO_FLUSH(true); + } else { + FLT_SET_AUTO_FLUSH(false); + } + + trace::ObSpanCtx *ctx = FLT_BEGIN_SPAN(ob_proxy); + if (OB_NOT_NULL(ctx)) { + flt_.trace_log_info_.proxy_root_span_ctx_ = ctx; + flt_.span_info_.span_id_ = ctx->span_id_; + flt_.span_info_.ref_type_ = common::SYNC; + flt_.trace_log_info_.proxy_root_span_begin_time_ = ObTimeUtility::current_time(); + LOG_DEBUG("client gen, proxy use, begin span ob proxy root based on client trace", + K(ctx->span_id_), K(flt_.span_info_), K(OBTRACE->is_auto_flush())); + } + } else { + FLT_SET_AUTO_FLUSH(false); + LOG_DEBUG("req flt trace not enable in this req, auto flush false.", K(flt_.span_info_)); + } + } +} + +/* + * global.enable_trace_ as the total switch to decide whether proxy will monitor or not + * including xflush, full link trace + */ +int ObMysqlSM::handle_req_to_generate_root_span_by_proxy() +{ + int ret = OB_SUCCESS; + + if (flt_.control_info_.is_valid() + && get_global_performance_params().enable_trace_ + && !client_session_->is_proxy_mysql_client_ + && client_session_->get_session_info().is_server_support_full_link_trace()) { + if (!is_proxy_init_trace_log_info()) { + double pct = trace::get_random_percentage(); + if (pct < flt_.control_info_.sample_percentage_) { + flt_.span_info_.trace_enable_ = true; + } else { + flt_.span_info_.trace_enable_ = false; + } + + SET_TRACE_BUFFER(flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + if (flt_.span_info_.trace_enable_) { + flt_.span_info_.trace_id_ = FLT_BEGIN_TRACE(); + FLT_SET_TRACE_LEVEL(flt_.control_info_.level_); // need set trace level after BEGIN TRACE + LOG_DEBUG("begin trace generated by proxy", K(flt_.span_info_.trace_id_), K(flt_.control_info_.level_)); + + if (flt_.control_info_.record_policy_ == RP_ALL) { + flt_.span_info_.force_print_ = true; + } else if (flt_.control_info_.record_policy_ == RP_SAMPLE_AND_SLOW_QUERY) { + double print_pct = trace::get_random_percentage(); + if (print_pct < flt_.control_info_.print_sample_percentage_) { + flt_.span_info_.force_print_ = true; + } else { + flt_.span_info_.force_print_ = false; + } + } else if (flt_.control_info_.record_policy_ == RP_ONLY_SLOW_QUERY) { + flt_.span_info_.force_print_ = false; + } else { + flt_.span_info_.force_print_ = false; + } + + // generate ob proxy root span + trace::ObSpanCtx *ctx = FLT_BEGIN_SPAN(ob_proxy); + if (OB_NOT_NULL(ctx)) { + flt_.trace_log_info_.proxy_root_span_ctx_ = ctx; + flt_.span_info_.span_id_ = ctx->span_id_; + flt_.span_info_.ref_type_ = common::SYNC; + flt_.trace_log_info_.proxy_root_span_begin_time_ = ObTimeUtility::current_time(); + LOG_DEBUG("proxy gen, begin trace, begin span ob proxy root.", + K(flt_.span_info_), K(flt_.trace_log_info_), K(flt_.control_info_)); + } else { + LOG_DEBUG("proxy gen, begin, empty span ctx!"); + } + } else { + flt_.span_info_.force_print_ = false; + } + + if (flt_.span_info_.force_print_) { + FLT_SET_AUTO_FLUSH(true); + } else { + FLT_SET_AUTO_FLUSH(false); + } + + flt_.trace_log_info_.is_inited_ = true; + LOG_DEBUG("proxy init trace log info done", K(flt_.span_info_), K(flt_.trace_log_info_)); + } else if (is_in_trans_) { + // still in trans, proxy has initede trace log info before. + // nothing, use the span generated before, regenerate root span id + if (flt_.span_info_.trace_enable_) { + SET_TRACE_BUFFER(flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + + trace::ObSpanCtx *ctx = FLT_BEGIN_SPAN(ob_proxy); + if (OB_NOT_NULL(ctx)) { + flt_.trace_log_info_.proxy_root_span_ctx_ = ctx; + flt_.span_info_.span_id_ = ctx->span_id_; + flt_.span_info_.ref_type_ = common::SYNC; + flt_.trace_log_info_.proxy_root_span_begin_time_ = ObTimeUtility::current_time(); + LOG_DEBUG("proxy gen trace before, still in trans, begin span ob proxy root", + K(flt_.span_info_), K(flt_.trace_log_info_)); + } else { + LOG_DEBUG("proxy gen, in trans, empty span ctx!"); + } + } + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected error, proxy has generate trace&span id at req, but not in trans", + K(ret), K(flt_.trace_log_info_)); + } + } + + return ret; +} + +void ObMysqlSM::save_request_flt_result_to_sm(common::FLTObjManage &flt) +{ + // span info from client + if (flt.span_info_.is_valid()) { + flt_.span_info_ = flt.span_info_; + LOG_DEBUG("succ to save req span info to sm", K(flt_.span_info_)); + } + + // app info + if (flt.app_info_.is_valid()) { + flt_.app_info_ = flt.app_info_; + LOG_DEBUG("succ to save req app info to sm", K(flt_.app_info_)); + } + + // driver span info, print right now + if (flt.driver_span_info_.is_valid()) { + SET_TRACE_BUFFER(flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + _OBPROXY_TRACE_LOG(INFO, "%s", flt.driver_span_info_.curr_driver_span_.ptr()); + LOG_DEBUG("succ get driver span info from req", K(flt.driver_span_info_.curr_driver_span_)); + } +} + int ObMysqlSM::state_server_request_send(int event, void *data) { int ret = OB_SUCCESS; @@ -3475,6 +4450,17 @@ int ObMysqlSM::state_server_request_send(int event, void *data) milestones_.server_.server_write_end_ = get_based_hrtime(); cmd_time_stats_.server_request_write_time_ += (milestones_.server_.server_write_end_ - milestones_.server_.server_write_begin_); } + + if (enable_record_full_link_trace_info()) { + trace::ObSpanCtx *ctx = flt_.trace_log_info_.server_request_write_ctx_; + if (OB_NOT_NULL(ctx)) { + LOG_DEBUG("end span ob_proxy_server_request_write", K(ctx->span_id_)); + SET_TRACE_BUFFER(flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + FLT_END_SPAN(ctx); + flt_.trace_log_info_.server_request_write_ctx_ = NULL; + } + } + // We are done sending the request, deallocate our // buffer and then decide what to do next if (OB_UNLIKELY(NULL != server_entry_->write_buffer_)) { @@ -3496,17 +4482,16 @@ int ObMysqlSM::state_server_request_send(int event, void *data) ObClientSessionInfo &cs_info = client_session_->get_session_info(); ObServerSessionInfo &ss_info = server_session_->get_session_info(); uint32_t client_ps_id = cs_info.get_client_ps_id(); - ObPsIdAddrs *ps_id_addrs = cs_info.get_ps_id_addrs(client_ps_id); // remove directly ss_info.remove_ps_id_pair(client_ps_id); ss_info.remove_cursor_id_pair(client_ps_id); cs_info.remove_cursor_id_addr(client_ps_id); cs_info.remove_piece_info(client_ps_id); - if (NULL != ps_id_addrs) { - ps_id_addrs->remove_addr(server_session_->get_netvc()->get_remote_addr()); + if (OB_FAIL(cs_info.remove_request_send_addr(server_session_->get_netvc()->get_remote_addr()))) { + LOG_WARN("fail to erase server addr", K(ret)); + } else { + call_transact_and_set_next_state(ObMysqlTransact::handle_request); } - - call_transact_and_set_next_state(ObMysqlTransact::handle_request); } else if (OB_UNLIKELY(ObMysqlTransact::SERVER_SEND_SSL_REQUEST == trans_state_.current_.send_action_)) { ObUnixNetVConnection *vc = static_cast(server_session_->get_netvc()); if (OB_FAIL(vc->ssl_init(ObUnixNetVConnection::SSL_CLIENT, @@ -3560,6 +4545,7 @@ int ObMysqlSM::state_server_request_send(int event, void *data) case VC_EVENT_ERROR: case VC_EVENT_ACTIVE_TIMEOUT: case VC_EVENT_INACTIVITY_TIMEOUT: + case VC_EVENT_DETECT_SERVER_DEAD: LOG_WARN("ObMysqlSM::state_server_request_send", "event", ObMysqlDebugNames::get_event_name(event), K_(sm_id)); // if something unusual happened in sending request, also need to get request write time @@ -3620,7 +4606,7 @@ int ObMysqlSM::handle_server_request_send_long_data() } else { trans_state_.current_.state_ = ObMysqlTransact::TRANSACTION_COMPLETE; } - + LOG_DEBUG("send_long_data send finish, trans to handle request"); release_server_session(); callout_api_and_start_next_action(ObMysqlTransact::SM_ACTION_API_CMD_COMPLETE); @@ -3652,9 +4638,11 @@ int ObMysqlSM::process_partition_location(ObMysqlRouteResult &result) LOG_WARN("can not get table entry, and dummy entry does not exist, will disconnect", K_(sm_id), K(type), K(ret)); // if failed, encode err packet and send to client, then disconnect + ObMysqlClientSession *client_session = get_client_session(); int ret_tmp = OB_SUCCESS; trans_state_.mysql_errcode_ = OB_GET_LOCATION_TIME_OUT; - if (OB_UNLIKELY(OB_SUCCESS != (ret_tmp = ObMysqlTransact::build_error_packet(trans_state_)))) { + if (OB_UNLIKELY(OB_SUCCESS != + (ret_tmp = ObMysqlTransact::build_error_packet(trans_state_, client_session)))) { LOG_WARN("fail to build err packet", K(ret_tmp)); } } @@ -3727,17 +4715,32 @@ bool ObMysqlSM::is_cached_dummy_entry_expired() } else if (cached_dummy_entry->is_need_update()) { // dirty, but not in punish time need_update = true; } else if (cached_dummy_entry->is_avail_state()) { + bool expired = false; if (valid_ns > 0) { - bool expired = ((get_hrtime_internal() - hrtime_from_usec(cached_dummy_entry->get_create_time_us())) > valid_ns); - if (expired - && !cached_dummy_entry->is_sys_dummy_entry() - && cached_dummy_entry->cas_set_dirty_state()) { - LOG_INFO("this cached dummy entry is expired, set to dirty", KPC(cached_dummy_entry), - K(valid_ns)); - MYSQL_INCREMENT_TRANS_STAT(DUMMY_ENTRY_EXPIRED_COUNT); - need_update = true; + expired = ((get_hrtime_internal() - hrtime_from_usec(cached_dummy_entry->get_create_time_us()))> valid_ns); + } + + if (!expired) { + int64_t tenant_version = 0; + if (OB_UNLIKELY(get_global_proxy_config().check_tenant_locality_change)) { + tenant_version = sm_cluster_resource_->get_location_tenant_version( + client_session_->get_session_info().get_priv_info().tenant_name_); + } + + if (!(expired = get_global_table_cache().is_table_entry_expired(*cached_dummy_entry))) { + cached_dummy_entry->check_and_set_expire_time(tenant_version, cached_dummy_entry->is_sys_dummy_entry()); + LOG_DEBUG("dummy entry expired", KPC(cached_dummy_entry)); } } + + if (expired + && !cached_dummy_entry->is_sys_dummy_entry() + && cached_dummy_entry->cas_set_dirty_state()) { + LOG_INFO("this cached dummy entry is expired, set to dirty", KPC(cached_dummy_entry), + K(valid_ns)); + MYSQL_INCREMENT_TRANS_STAT(DUMMY_ENTRY_EXPIRED_COUNT); + need_update = true; + } } } @@ -4079,20 +5082,24 @@ int ObMysqlSM::tunnel_handler_request_transfered(int event, void *data) int ObMysqlSM::tunnel_handler_response_transfered(int event, void *data) { STATE_ENTER(ObMysqlSM::tunnel_handler_response_transfered, event); + int ret = OB_SUCCESS; if (OB_UNLIKELY(MYSQL_TUNNEL_EVENT_DONE != event) || OB_UNLIKELY(data != &tunnel_)) { terminate_sm_ = true; LOG_ERROR("unexpected event type", K(event), K_(sm_id)); + } else if (OB_ISNULL(client_entry_)) { + ret = OB_INNER_STAT_ERROR; + LOG_WARN("client_entry or server entry is null, disconnect", K_(client_entry), K(ret)); } else { - // only the first request in one transaction will need to update pl, + // only the first request in one transaction or internal routing transaction will need to update pl, // begin(start transaction), or set autocommit = 0 is not the first request; - if (trans_state_.is_trans_first_request_) { + if ((trans_state_.is_trans_first_request_ || client_session_->is_trans_internal_routing()) + && !ObMysqlTransact::is_binlog_request(trans_state_)) { ObMysqlTransact::handle_pl_update(trans_state_); } if (obmysql::OB_MYSQL_COM_STMT_FETCH == trans_state_.trans_info_.sql_cmd_ && client_session_->is_need_return_last_bound_ss()) { - int ret = OB_SUCCESS; ObMysqlServerSession *last_bound_session = client_session_->get_last_bound_server_session(); if (NULL != last_bound_session) { // Since the tunnel_handler_server only releases server_session in a transaction, @@ -4128,6 +5135,12 @@ int ObMysqlSM::tunnel_handler_response_transfered(int event, void *data) } } + if (OB_FAIL(ret)) { + trans_state_.inner_errcode_ = ret; + trans_state_.current_.state_ = ObMysqlTransact::INTERNAL_ERROR; + call_transact_and_set_next_state(ObMysqlTransact::handle_response); + } + return EVENT_DONE; } @@ -4161,6 +5174,7 @@ int ObMysqlSM::tunnel_handler_server(int event, ObMysqlTunnelProducer &p) switch (event) { case VC_EVENT_INACTIVITY_TIMEOUT: case VC_EVENT_ACTIVE_TIMEOUT: + case VC_EVENT_DETECT_SERVER_DEAD: case VC_EVENT_ERROR: // fall through case VC_EVENT_EOS: @@ -4172,6 +5186,7 @@ int ObMysqlSM::tunnel_handler_server(int event, ObMysqlTunnelProducer &p) trans_state_.current_.state_ = ObMysqlTransact::ACTIVE_TIMEOUT; break; case VC_EVENT_ERROR: + case VC_EVENT_DETECT_SERVER_DEAD: trans_state_.current_.state_ = ObMysqlTransact::CONNECTION_ERROR; break; case VC_EVENT_EOS: @@ -4359,53 +5374,21 @@ void ObMysqlSM::print_mysql_complete_log(ObMysqlTunnelProducer *p) bool print_warn_log = false; bool print_info_log = false; if (OB_LIKELY(NULL != client_session_)) { - if (OB_UNLIKELY(result.is_error_resp())) { - // filtering some error code later + if (OB_UNLIKELY(result.is_error_resp() && client_session_->is_proxy_mysql_client_ + && client_session_->get_session_info().get_priv_info().user_name_ != ObProxyTableInfo::DETECT_USERNAME_USER)) { if (result.is_not_supported_error()) { print_info_log = true; - OBPROXY_XF_LOG(INFO, XFH_SQL_NOT_SUPPORT, - "client_ip", trans_state_.client_info_.addr_, - "server_ip", trans_state_.server_info_.addr_, - "proxy_user_name", client_session_->get_session_info().get_priv_info().get_proxy_user_name(), - "database_name", client_session_->get_session_info().get_database_name(), - "sql", trans_state_.trans_info_.client_request_.get_print_sql(), - "sql_cmd", get_mysql_cmd_str(trans_state_.trans_info_.sql_cmd_)); } else { print_warn_log = true; - OBPROXY_XF_LOG(WARN, XFH_SQL_ERROR_RESP, - "client_ip", trans_state_.client_info_.addr_, - "server_ip", trans_state_.server_info_.addr_, - "proxy_user_name", client_session_->get_session_info().get_priv_info().get_proxy_user_name(), - "database_name", client_session_->get_session_info().get_database_name(), - "sql", trans_state_.trans_info_.client_request_.get_print_sql(), - "sql_cmd", get_mysql_cmd_str(trans_state_.trans_info_.sql_cmd_), - "sql_error", get_xflush_error_name(result.get_error_code()), - "msg", result); } } else if (!result.is_partition_hit() && trans_state_.is_trans_first_request_ && !client_session_->is_proxyro_user()) {//proxyro user no need print partition miss xflush_log print_info_log = true; - OBPROXY_XF_LOG(INFO, XFH_SQL_PARTITION_MISS, - "client_ip", trans_state_.client_info_.addr_, - "server_ip", trans_state_.server_info_.addr_, - "proxy_user_name", client_session_->get_session_info().get_priv_info().get_proxy_user_name(), - "database_name", client_session_->get_session_info().get_database_name(), - "sql", trans_state_.trans_info_.client_request_.get_print_sql(), - "sql_cmd", get_mysql_cmd_str(trans_state_.trans_info_.sql_cmd_)); } if(NULL != p && p->is_flow_controlled()) { print_info_log = true; - OBPROXY_XF_LOG(INFO, XFH_SQL_FLOW_CTL, - "client_ip", trans_state_.client_info_.addr_, - "server_ip", trans_state_.server_info_.addr_, - "proxy_user_name", client_session_->get_session_info().get_priv_info().get_proxy_user_name(), - "database_name", client_session_->get_session_info().get_database_name(), - "sql", trans_state_.trans_info_.client_request_.get_print_sql(), - "sql_cmd", get_mysql_cmd_str(trans_state_.trans_info_.sql_cmd_), - "cpu_ctl_count", p->cpu_flow_control_count_, - "mem_ctl_count", p->memory_flow_control_count_); } } @@ -4496,8 +5479,7 @@ void ObMysqlSM::update_safe_read_snapshot() ObSafeSnapshotEntry *entry = NULL; bool is_need_force_sync = true; ObAddr last_addr; - last_addr.set_ipv4_addr(trans_state_.server_info_.addr_.get_ip4_host_order(), - static_cast(trans_state_.server_info_.addr_.get_port_host_order())); + last_addr.set_sockaddr(trans_state_.server_info_.addr_.sa_); if (result.is_partition_hit()) { entry = sm_cluster_resource_->safe_snapshot_mgr_.get(last_addr); @@ -4611,7 +5593,7 @@ int ObMysqlSM::trim_ok_packet(ObIOBufferReader &reader) if (OK_PACKET_ACTION_CONSUME == analyze_result.get_ok_packet_action_type()) { if (OB_FAIL(ObProxySessionInfoHandler::analyze_extra_ok_packet( reader, client_session->get_session_info(), - server_session->get_session_info(), need_handle_sysvar, analyze_result))) { + server_session->get_session_info(), need_handle_sysvar, analyze_result, trans_state_.trace_log_))) { LOG_WARN("fail to analyze extra ok packet", K_(sm_id), K(ret)); } } else if (OK_PACKET_ACTION_REWRITE == analyze_result.get_ok_packet_action_type()) { @@ -4620,10 +5602,14 @@ int ObMysqlSM::trim_ok_packet(ObIOBufferReader &reader) const ObProxyBasicStmtType type = trans_state_.trans_info_.client_request_.get_parse_result().get_stmt_type(); bool is_save_to_common_sys = client_info.is_sharding_user() && (OBPROXY_T_SET == type || OBPROXY_T_SET_NAMES == type || OBPROXY_T_SET_CHARSET == type); - if (OB_FAIL(ObProxySessionInfoHandler::rebuild_ok_packet( - reader, client_session->get_session_info(), - server_session->get_session_info(), trans_state_.is_auth_request_, - need_handle_sysvar, analyze_result, is_save_to_common_sys))) { + if (OB_FAIL(ObProxySessionInfoHandler::rebuild_ok_packet(reader, + client_session->get_session_info(), + server_session->get_session_info(), + trans_state_.is_auth_request_, + need_handle_sysvar, + analyze_result, + trans_state_.trace_log_, + is_save_to_common_sys))) { LOG_WARN("fail to analyze rewrite ok packet", K_(sm_id), K(ret)); } } @@ -4631,18 +5617,25 @@ int ObMysqlSM::trim_ok_packet(ObIOBufferReader &reader) // reset route_addr client_session->get_session_info().set_obproxy_route_addr(0); - if (OB_UNLIKELY(is_causal_order_read_enabled())) { - // handle safe snapshot version - if (WEAK == trans_state_.get_trans_consistency_level(client_session->get_session_info()) - && trans_state_.trans_info_.client_request_.get_parse_result().is_select_stmt()) { - update_safe_read_snapshot(); - } + if (OB_UNLIKELY(is_causal_order_read_enabled())) { + // handle safe snapshot version + if (WEAK == trans_state_.get_trans_consistency_level(client_session->get_session_info()) + && trans_state_.trans_info_.client_request_.get_parse_result().is_select_stmt()) { + update_safe_read_snapshot(); + } } // handle other variables if (OB_SUCC(ret)) { + bool is_only_sync_trans_sess = trans_state_.trans_info_.server_response_.get_analyze_result().is_error_resp(); if (OB_FAIL(handle_saved_session_variables())) { LOG_WARN("fail to handle saved session varialbes", K(ret)); + } else if (OB_FAIL(ObProxySessionInfoHandler::save_changed_sess_info(client_session->get_session_info(), + server_session->get_session_info(), + analyze_result.get_extra_info(), + trans_state_.trace_log_, + is_only_sync_trans_sess))) { + LOG_WARN("fail to save changed session info", K(ret)); } } } @@ -4680,8 +5673,17 @@ int ObMysqlSM::tunnel_handler_client(int event, ObMysqlTunnelConsumer &c) case VC_EVENT_INACTIVITY_TIMEOUT: case VC_EVENT_ACTIVE_TIMEOUT: case VC_EVENT_ERROR: - LOG_WARN("ObMysqlSM::tunnel_handler_client", "event", - ObMysqlDebugNames::get_event_name(event), K_(sm_id)); + case VC_EVENT_DETECT_SERVER_DEAD: { + // Probe user does not print disconnection log + bool is_detect_user = false; + if (NULL != client_session_ && client_session_->get_session_info().get_priv_info().user_name_ == ObProxyTableInfo::DETECT_USERNAME_USER) { + is_detect_user = true; + } + + if (!is_detect_user) { + LOG_WARN("ObMysqlSM::tunnel_handler_client", "event", + ObMysqlDebugNames::get_event_name(event), K_(sm_id)); + } // The client died or aborted. Check to see // if we should setup a background fill set_client_abort(ObMysqlTransact::ABORTED, event); @@ -4703,7 +5705,7 @@ int ObMysqlSM::tunnel_handler_client(int event, ObMysqlTunnelConsumer &c) // session and client session close_connection = true; break; - + } case VC_EVENT_WRITE_COMPLETE: { c.write_success_ = true; trans_state_.client_info_.abort_ = ObMysqlTransact::DIDNOT_ABORT; @@ -4778,6 +5780,7 @@ int ObMysqlSM::tunnel_handler_request_transfer_client(int event, ObMysqlTunnelPr case VC_EVENT_ERROR: case VC_EVENT_INACTIVITY_TIMEOUT: case VC_EVENT_ACTIVE_TIMEOUT: + case VC_EVENT_DETECT_SERVER_DEAD: LOG_WARN("ObMysqlSM::tunnel_handler_request_transfer_client", "event", ObMysqlDebugNames::get_event_name(event), K_(sm_id)); // Did not complete request transfer tunneling. Abort the @@ -4865,6 +5868,7 @@ int ObMysqlSM::tunnel_handler_request_transfer_server(int event, ObMysqlTunnelCo case VC_EVENT_ERROR: case VC_EVENT_INACTIVITY_TIMEOUT: case VC_EVENT_ACTIVE_TIMEOUT: + case VC_EVENT_DETECT_SERVER_DEAD: { LOG_WARN("ObMysqlSM::tunnel_handler_request_transfer_server", "event", ObMysqlDebugNames::get_event_name(event), K_(sm_id)); @@ -5002,16 +6006,21 @@ void ObMysqlSM::do_congestion_control_lookup() // 2. cur congestion is avail(base servers has been added) // 3. need pl lookup // 4. not mysql route mode - // + // 5. need use coordinator session in transaction (included in 'need pl lookup') // Attention! when force_retry_congested_, also need do congestion lookup if (OB_UNLIKELY(enable_congestion && sm_cluster_resource_->is_congestion_avail() - && trans_state_.need_pl_lookup_ - && !trans_state_.mysql_config_params_->is_mysql_routing_mode())) { + && trans_state_.is_need_pl_lookup() + && !trans_state_.mysql_config_params_->is_mysql_routing_mode() + && !trans_state_.mysql_config_params_->is_mock_routing_mode())) { trans_state_.need_congestion_lookup_ = true; + LOG_DEBUG("need to do congestion lookup", + K(trans_state_.is_need_pl_lookup()), + K(trans_state_.pl_lookup_state_)); } else { LOG_DEBUG("no need do congestion lookup", K_(sm_id), K(enable_congestion), - K(sm_cluster_resource_->is_congestion_avail()), "need_pl_lookup", trans_state_.need_pl_lookup_, + K(sm_cluster_resource_->is_congestion_avail()), + "pl_lookup_state", ObMysqlTransact::get_pl_lookup_state_string(trans_state_.pl_lookup_state_), "force_retry_congestion", trans_state_.force_retry_congested_, "route_mode", trans_state_.mysql_config_params_->server_routing_mode_); trans_state_.need_congestion_lookup_ = false; @@ -5070,6 +6079,15 @@ void ObMysqlSM::do_partition_location_lookup() milestones_.pl_lookup_end_ = 0; } + if (enable_record_full_link_trace_info()) { + SET_TRACE_BUFFER(flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + trace::ObSpanCtx *ctx = FLT_BEGIN_SPAN(ob_proxy_partition_location_lookup); + if (OB_NOT_NULL(ctx)) { + flt_.trace_log_info_.partition_location_lookup_ctx_ = ctx; + LOG_DEBUG("begin span ob_proxy_partition_location_lookup", K(ctx->span_id_)); + } + } + if (OB_UNLIKELY(trans_state_.api_server_addr_set_)) { // If the API has set the server address before the partition // location lookup then we can skip the lookup @@ -5102,12 +6120,20 @@ void ObMysqlSM::do_partition_location_lookup() ObAction *pl_lookup_action_handle = NULL; bool find_entry = false; int64_t tenant_version = 0; + bool is_random_routing_mode = trans_state_.mysql_config_params_->is_random_routing_mode(); bool need_pl_route = (is_pl_route_supported() && (trans_state_.trans_info_.client_request_.get_parse_result().is_call_stmt() || trans_state_.trans_info_.client_request_.get_parse_result().is_text_ps_call_stmt())); + + if (OB_UNLIKELY(get_global_proxy_config().check_tenant_locality_change)) { + tenant_version = sm_cluster_resource_->get_location_tenant_version( + client_session_->get_session_info().get_priv_info().tenant_name_); + } + // Get it from table_map first if (OB_LIKELY(!trans_state_.pll_info_.is_force_renew() && !name.is_all_dummy_table() && !trans_state_.pll_info_.is_cached_dummy_force_renew()) - && !need_pl_route) { + && !need_pl_route + && !is_random_routing_mode) { ObTableRefHashMap &table_map = self_ethread().get_table_map(); ObTableEntry *tmp_entry = NULL; int64_t cr_id = 0; @@ -5118,15 +6144,11 @@ void ObMysqlSM::do_partition_location_lookup() cr_id = sm_cluster_resource_->get_cluster_id(); } ObTableEntryKey key(name, sm_cluster_resource_->version_, cr_id); - if (OB_UNLIKELY(get_global_proxy_config().check_tenant_locality_change)) { - tenant_version = sm_cluster_resource_->get_location_tenant_version( - client_session_->get_session_info().get_priv_info().tenant_name_); - } tmp_entry = table_map.get(key); if (NULL != tmp_entry && !tmp_entry->is_partition_table() && (tmp_entry->is_avail_state() || tmp_entry->is_updating_state()) && !(get_global_table_cache().is_table_entry_expired(*tmp_entry))) { - tmp_entry->check_and_set_expire_time(tenant_version, tmp_entry->is_dummy_entry()); + tmp_entry->check_and_set_expire_time(tenant_version, tmp_entry->is_sys_dummy_entry()); tmp_entry->renew_last_access_time(); ObMysqlRouteResult result; @@ -5151,6 +6173,7 @@ void ObMysqlSM::do_partition_location_lookup() param.use_lower_case_name_ = client_session_->get_session_info().need_use_lower_case_names(); param.mysql_proxy_ = &sm_cluster_resource_->mysql_proxy_; param.cr_version_ = sm_cluster_resource_->version_; + param.cluster_version_ = sm_cluster_resource_->cluster_version_; if (get_global_resource_pool_processor().get_default_cluster_resource() == sm_cluster_resource_) { // default cluster resource cluster id is always 0, and it is used only for building cluster resource param.cr_id_ = client_session_->get_session_info().get_cluster_id(); @@ -5166,7 +6189,7 @@ void ObMysqlSM::do_partition_location_lookup() param.route_ = &trans_state_.pll_info_.route_; param.need_pl_route_ = need_pl_route; param.current_idc_name_ = client_session_->get_current_idc_name();//shallow copy - if (trans_state_.pll_info_.is_cached_dummy_force_renew()) { + if (trans_state_.pll_info_.is_cached_dummy_force_renew() || is_random_routing_mode) { param.need_pl_route_ = false; param.name_.shallow_copy(name.cluster_name_, name.tenant_name_, ObString::make_string(OB_SYS_DATABASE_NAME), @@ -5196,6 +6219,75 @@ void ObMysqlSM::do_partition_location_lookup() } } +void ObMysqlSM::do_binlog_location_lookup() +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(get_global_performance_params().enable_trace_)) { + milestones_.bl_lookup_begin_ = get_based_hrtime(); + milestones_.bl_lookup_end_ = 0; + } + + LOG_DEBUG("do binlog location lookup"); + MYSQL_SM_SET_DEFAULT_HANDLER(&ObMysqlSM::state_binlog_location_lookup); + if (OB_UNLIKELY(NULL != pending_action_)) { + trans_state_.pll_info_.lookup_success_ = false; + LOG_ERROR("do_binlog_location_lookup, pending_action_ should be NULL", + K_(pending_action), K_(sm_id)); + call_transact_and_set_next_state(NULL); + } else if (trans_state_.server_info_.addr_.is_valid()) { + trans_state_.pll_info_.lookup_success_ = true; + call_transact_and_set_next_state(NULL); + } else { + const ObTableEntryName &name = trans_state_.pll_info_.te_name_; + ObAction *bl_lookup_action_handle = NULL; + bool find_entry = false; + // Obtained from the cache, no longer retrieved from the remote end + ObTableRefHashMap &table_map = self_ethread().get_table_map(); + ObTableEntry *tmp_entry = NULL; + ObTableEntryKey key(name, 0, 0); + tmp_entry = table_map.get(key); + if (OB_LIKELY(NULL != tmp_entry)) { + tmp_entry->renew_last_access_time(); + ObMysqlRouteResult result; + result.table_entry_ = tmp_entry; + result.is_table_entry_from_remote_ = false; + tmp_entry->set_need_force_flush(false); + find_entry = true; + LOG_DEBUG("ObMysqlRoute get table entry succ", KPC(tmp_entry)); + state_binlog_location_lookup(TABLE_ENTRY_EVENT_LOOKUP_DONE, &result); + } + + if (OB_UNLIKELY(!find_entry)) { + ObRouteParam param; + param.cont_ = this; + param.need_pl_route_ = false; + param.force_renew_ = trans_state_.pll_info_.is_force_renew(); + param.is_need_force_flush_ = trans_state_.pll_info_.is_need_force_flush(); + param.mysql_proxy_ = &sm_cluster_resource_->mysql_proxy_; + param.timeout_us_ = hrtime_to_usec(trans_state_.mysql_config_params_->short_async_task_timeout_); + param.name_.shallow_copy(name); + param.cr_version_ = 0; + param.cr_id_ = 0; + + LOG_DEBUG("Doing binlog location lookup", K_(sm_id), K(param)); + bl_lookup_action_handle = NULL; + ret = ObMysqlRoute::get_route_entry(param, sm_cluster_resource_, bl_lookup_action_handle); + } + + if (OB_SUCC(ret)) { + if (NULL == bl_lookup_action_handle) { + // do nothing + } else { + pending_action_ = bl_lookup_action_handle; + } + } else { + trans_state_.pll_info_.lookup_success_ = false; + LOG_WARN("fail to get binlog table entry", K_(sm_id), K(name), K(ret)); + call_transact_and_set_next_state(NULL); + } + } +} + void ObMysqlSM::do_server_addr_lookup() { ObProxyKillQueryInfo *query_info = trans_state_.trans_info_.client_request_.query_info_; @@ -5204,7 +6296,7 @@ void ObMysqlSM::do_server_addr_lookup() // call ObMysqlTransact::handle_server_addr_lookup() to handle fail / success call_transact_and_set_next_state(NULL); - } else if (!trans_state_.need_pl_lookup_) { + } else if (!trans_state_.is_need_pl_lookup()) { // need use last server session query_info->errcode_ = OB_NOT_SUPPORTED; LOG_WARN("[ObMysqlSM::do_server_addr_lookup] As we need use last server session, " @@ -5234,7 +6326,7 @@ void ObMysqlSM::do_server_addr_lookup() // call ObMysqlTransact::handle_server_addr_lookup() to handle fail / success call_transact_and_set_next_state(NULL); } - }//end of trans_state_.need_pl_lookup_ + }//end of is_need_pl_lookup } int ObMysqlSM::state_congestion_control_lookup(int event, void *data) @@ -5260,6 +6352,52 @@ int ObMysqlSM::state_congestion_control_lookup(int event, void *data) return EVENT_DONE; } +void ObMysqlSM::set_detect_server_info(net::ObIpEndpoint target_addr, int cnt, int64_t time) +{ + if (OB_LIKELY(target_addr.is_valid() + && NULL != sm_cluster_resource_ + && NULL != client_session_ + && !client_session_->is_proxy_mysql_client_ + //Optimize the performance in closed scenes, 1 means accurate detection + && (1 == get_global_proxy_config().server_detect_mode || add_detect_server_cnt_))) { + bool found = false; + common::DRWLock &server_state_lock1 = sm_cluster_resource_->get_server_state_lock(0); + common::DRWLock &server_state_lock2 = sm_cluster_resource_->get_server_state_lock(1); + server_state_lock1.rdlock(); + server_state_lock2.rdlock(); + common::ObIArray &server_state_info = + sm_cluster_resource_->get_server_state_info(sm_cluster_resource_->server_state_version_); + for (int i = 0; !found && i < server_state_info.count(); i++) { + ObServerStateSimpleInfo &info = server_state_info.at(i); + ObIpEndpoint addr(info.addr_.get_sockaddr()); + if (addr == target_addr) { + // add_detect_server_cnt_ prevents do_observer_open from failing before, and subtracts 1 from cnt + if (cnt > 0 && 1 == get_global_proxy_config().server_detect_mode) { + add_detect_server_cnt_ = true; + (void)ATOMIC_AAF(&info.request_sql_cnt_, cnt); + } else if (cnt < 0) { + if (add_detect_server_cnt_) { + add_detect_server_cnt_ = false; + (void)ATOMIC_AAF(&info.request_sql_cnt_, cnt); + } + } + if (0 != time) { + (void)ATOMIC_SET(&info.last_response_time_, time); + (void)ATOMIC_SET(&info.detect_fail_cnt_, 0); + } + LOG_DEBUG("set detect server info", K(addr), K(cnt), K(time), K(info), K(sm_cluster_resource_->server_state_version_)); + found = true; + } + } + server_state_lock2.rdunlock(); + server_state_lock1.rdunlock(); + + if (!found) { + LOG_WARN("not found server", K(target_addr), K(cnt), KPC(sm_cluster_resource_)); + } + } +} + int ObMysqlSM::do_observer_open() { int ret = OB_SUCCESS; @@ -5270,6 +6408,15 @@ int ObMysqlSM::do_observer_open() milestones_.do_observer_open_end_ = 0; } + if (enable_record_full_link_trace_info()) { + SET_TRACE_BUFFER(flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + trace::ObSpanCtx *ctx = FLT_BEGIN_SPAN(ob_proxy_do_observer_open); + if (OB_NOT_NULL(ctx)) { + flt_.trace_log_info_.do_observer_open_ctx_ = ctx; + LOG_DEBUG("begin span ob_proxy_do_observer_open", K(ctx->span_id_)); + } + } + // if sync all variables completed, send request directly through handle_observer_open if (OB_UNLIKELY(trans_state_.send_reqeust_direct_)) { if (OB_ISNULL(server_session_) || ObMysqlTransact::SERVER_SEND_REQUEST != trans_state_.current_.send_action_) { @@ -5284,6 +6431,13 @@ int ObMysqlSM::do_observer_open() release_server_session(); } + if (add_detect_server_cnt_) { + set_detect_server_info(trans_state_.pre_server_info_.addr_, -1, 0); + } + // Large requests will enter do_observer_open twice, and the second time will set send_request_direct to true + set_detect_server_info(trans_state_.server_info_.addr_, 1, 0); + trans_state_.pre_server_info_.addr_ = trans_state_.server_info_.addr_; + if (OB_UNLIKELY(NULL != server_entry_)) { if (MYSQL_SERVER_VC != server_entry_->vc_type_) { ret = OB_ERR_UNEXPECTED; @@ -5418,10 +6572,11 @@ inline int ObMysqlSM::handle_retry_acquire_svr_session() { LOG_DEBUG("succ to retry acquire svr session", K(diff_time), K(interval)); } } else { + ObMysqlClientSession *client_session = get_client_session(); ret = OB_SESSION_POOL_FULL_ERROR; trans_state_.mysql_errcode_ = OB_SESSION_POOL_FULL_ERROR; trans_state_.mysql_errmsg_ = "No empty server session, acquire session failed"; - if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_))) { + if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_, client_session))) { LOG_WARN("fail to encode err pacekt buf", K_(sm_id), "errcode", trans_state_.mysql_errcode_, "user_err_msg", trans_state_.mysql_errmsg_, K(ret)); @@ -5466,40 +6621,47 @@ inline int ObMysqlSM::do_oceanbase_internal_observer_open(ObMysqlServerSession * last_session = client_session_->get_server_session(); // if need_pl_lookup is false, we must use last server session - // allow no last server session when OB_MYSQL_COM_STMT_CLOSE/OB_MYSQL_COM_STMT_FETCH and need_pl_lookup_ = false - if (!trans_state_.need_pl_lookup_ - && ((OB_MYSQL_COM_STMT_CLOSE != trans_state_.trans_info_.sql_cmd_ && OB_MYSQL_COM_STMT_FETCH != trans_state_.trans_info_.sql_cmd_) - || !client_session_->is_need_return_last_bound_ss())) { - if (OB_ISNULL(last_session)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("last server session is NULL, disconnect", K_(sm_id), K(ret)); - } else if (OB_UNLIKELY(last_session->server_ip_ != trans_state_.server_info_.addr_)) { - ret = OB_ERR_UNEXPECTED; - LOG_ERROR("last server session ip is unexpected", - K_(last_session->server_ip), K_(trans_state_.server_info_.addr), K_(sm_id), K(ret)); - } else { + // allow no last server session when OB_MYSQL_COM_STMT_CLOSE/OB_MYSQL_COM_STMT_FETCH and NEED_PL_LOOKUP + obmysql::ObMySQLCmd cmd = trans_state_.trans_info_.sql_cmd_; + bool is_text_ps_close = trans_state_.trans_info_.client_request_.get_parse_result().is_text_ps_drop_stmt(); + if (!trans_state_.is_need_pl_lookup() + && ((OB_MYSQL_COM_STMT_CLOSE != cmd + && OB_MYSQL_COM_STMT_FETCH != cmd + && OB_MYSQL_COM_STMT_RESET != cmd + && OB_MYSQL_COM_STMT_GET_PIECE_DATA != cmd + && !is_text_ps_close) + || !client_session_->is_need_return_last_bound_ss())) { + ObMysqlServerSession *target_session = NULL; + if (trans_state_.pl_lookup_state_ == ObMysqlTransact::USE_COORDINATOR_SESSION) { + if (OB_FAIL(client_session_->acquire_svr_session(trans_state_.server_info_.addr_.sa_, false, target_session))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("acquire coordinator session fail, disconnect", K_(sm_id), K(ret)); + } + LOG_DEBUG("use coordinator server session", K_(sm_id)); + } else if (trans_state_.pl_lookup_state_ == ObMysqlTransact::USE_LAST_SERVER_SESSION){ + target_session = last_session; LOG_DEBUG("use last server session", K_(sm_id)); - selected_session = last_session; + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected pl lookup state", K(trans_state_.pl_lookup_state_)); } - } else { - /* - if ((trans_state_.mysql_config_params_->is_mock_routing_mode() && !client_session_->is_proxy_mysql_client_) - || trans_state_.mysql_config_params_->is_mysql_routing_mode()) { - if (client_session_->test_server_addr_.is_valid()) { - trans_state_.server_info_.addr_ = client_session_->test_server_addr_; - LOG_DEBUG("use hacked server addr", K_(sm_id), "server addr", trans_state_.server_info_.addr_); - } else if (OB_FAIL(trans_state_.mysql_config_params_->get_one_test_server_addr( - client_session_->test_server_addr_))) { - LOG_INFO("mysql mode, but test server addr in not set, open conn to observer", K(ret)); - ret = OB_SUCCESS; + if (OB_SUCC(ret)) { + if (OB_ISNULL(target_session)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("target server session is NULL, disconnect", K_(sm_id), K(ret)); + } else if (OB_UNLIKELY(target_session->server_ip_ != trans_state_.server_info_.addr_)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("target session ip is unexpected", + K_(target_session->server_ip), K_(trans_state_.server_info_.addr), K_(sm_id), K(ret)); } else { - trans_state_.server_info_.addr_ = client_session_->test_server_addr_; - LOG_DEBUG("use hacked server addr", K_(sm_id), "server addr", trans_state_.server_info_.addr_); + selected_session = target_session; } } - */ - LOG_DEBUG("sql cmd", K(trans_state_.trans_info_.sql_cmd_), K(client_session_->is_session_pool_client())); - if (OB_UNLIKELY(trans_state_.trans_info_.sql_cmd_ == OB_MYSQL_COM_LOGIN && client_session_->is_session_pool_client() && !client_session_->can_direct_ok())) { + } else { + LOG_DEBUG("sql cmd", K(cmd), K(client_session_->is_session_pool_client())); + if (OB_UNLIKELY(OB_MYSQL_COM_LOGIN == cmd + && client_session_->is_session_pool_client() + && !client_session_->can_direct_ok())) { LOG_DEBUG("OB_MYSQL_COM_LOGIN here not use pool"); // only proxy_mysql_client for session pool use pool_sever_addr // this logic is for pre connection create @@ -5580,6 +6742,8 @@ inline int ObMysqlSM::do_internal_observer_open() { int ret = OB_SUCCESS; ObMysqlServerSession *selected_session = NULL; + ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; + bool is_in_trans = ObMysqlTransact::is_in_trans(trans_state_); if (OB_LIKELY(client_session_->get_session_info().is_oceanbase_server())) { if (OB_FAIL(do_oceanbase_internal_observer_open(selected_session))) { @@ -5625,30 +6789,50 @@ inline int ObMysqlSM::do_internal_observer_open() // (6) send text ps prepare for text ps execute // (7) send request(including normal request, ps execute, first prepare); + obmysql::ObMySQLCmd cmd = trans_state_.trans_info_.client_request_.get_packet_meta().cmd_; LOG_DEBUG("get server session from connection pool", K_(sm_id), "server addr", server_session_->server_ip_, K(server_session_->ss_id_), "client_session version", client_info.get_session_version(), - "server version", server_info.get_session_var_version()); - if (OB_UNLIKELY(OB_MYSQL_COM_STMT_CLOSE == trans_state_.trans_info_.client_request_.get_packet_meta().cmd_)) { + "server version", server_info.get_session_var_version(), + "cmd", cmd); + + trans_state_.trace_log_.log_it("[get_conn]", + "time", get_based_hrtime(), + "lookup", trans_state_.pl_lookup_state_, + "sql_cmd", trans_state_.trans_info_.sql_cmd_, + "stmt_type", trans_state_.trans_info_.client_request_.get_parse_result().get_stmt_type(), + "in_trans", is_in_trans, + "internal_route", get_client_session()->is_trans_internal_routing() && is_in_trans, + "svr", server_session_->server_ip_, + "sessid", server_session_->get_server_sessid()); + + if (OB_UNLIKELY(OB_MYSQL_COM_STMT_CLOSE == cmd + || OB_MYSQL_COM_STMT_RESET == cmd + || ObMysqlTransact::is_binlog_request(trans_state_) + || client_session_->can_direct_send_request_)) { // no need sync var on OB_MYSQL_COM_STMT_CLOSE trans_state_.current_.send_action_ = ObMysqlTransact::SERVER_SEND_REQUEST; } else if (OB_UNLIKELY(client_info.need_reset_database(server_info))) { trans_state_.current_.send_action_ = ObMysqlTransact::SERVER_SEND_USE_DATABASE; - } else if (OB_UNLIKELY(client_info.need_reset_session_vars(server_info))) { + } else if (OB_UNLIKELY(client_info.is_server_support_session_var_sync() && + client_info.need_reset_user_session_vars(server_info))) { + trans_state_.current_.send_action_ = ObMysqlTransact::SERVER_SEND_SESSION_USER_VARS; + } else if (OB_UNLIKELY(!(client_info.is_server_support_session_var_sync()) && + client_info.need_reset_session_vars(server_info))) { trans_state_.current_.send_action_ = ObMysqlTransact::SERVER_SEND_SESSION_VARS; - } else if (OB_UNLIKELY(client_info.need_reset_last_insert_id(server_info))) { - // TODO: current version proxy parse can't judge last_insert_id exactly, - // so we do not judge, whether sql_reuslt has_last_insert_id here - trans_state_.current_.send_action_ = ObMysqlTransact::SERVER_SEND_LAST_INSERT_ID; } else if (OB_UNLIKELY(trans_state_.is_hold_start_trans_)) { trans_state_.current_.send_action_ = ObMysqlTransact::SERVER_SEND_START_TRANS; - } else if (OB_UNLIKELY(((OB_MYSQL_COM_STMT_EXECUTE == trans_state_.trans_info_.client_request_.get_packet_meta().cmd_) - || (OB_MYSQL_COM_STMT_SEND_PIECE_DATA == trans_state_.trans_info_.client_request_.get_packet_meta().cmd_) - || (OB_MYSQL_COM_STMT_SEND_LONG_DATA == trans_state_.trans_info_.client_request_.get_packet_meta().cmd_)) - && client_info.need_do_prepare(server_info))) { + } else if (OB_UNLIKELY(trans_state_.is_hold_xa_start_)) { + trans_state_.current_.send_action_ = ObMysqlTransact::SERVER_SEND_XA_START; + LOG_DEBUG("[ObMysqlSM::do_internal_observer_open] set send action SERVER_SEND_XA_START to sync xa start"); + } else if (OB_UNLIKELY(((OB_MYSQL_COM_STMT_EXECUTE == cmd) + || (OB_MYSQL_COM_STMT_SEND_PIECE_DATA == cmd) + || (OB_MYSQL_COM_STMT_SEND_LONG_DATA == cmd)) + && client_info.need_do_prepare(server_info))) { trans_state_.current_.send_action_ = ObMysqlTransact::SERVER_SEND_PREPARE; - } else if (OB_UNLIKELY(client_info.is_text_ps_execute() && client_info.need_do_text_ps_prepare(server_info))) { + } else if (OB_UNLIKELY(client_request.get_parse_result().is_text_ps_execute_stmt() && + client_info.need_do_text_ps_prepare(server_info))) { trans_state_.current_.send_action_ = ObMysqlTransact::SERVER_SEND_TEXT_PS_PREPARE; } else { trans_state_.current_.send_action_ = ObMysqlTransact::SERVER_SEND_REQUEST; @@ -5657,6 +6841,16 @@ inline int ObMysqlSM::do_internal_observer_open() } else { if (OB_FAIL(connect_observer())) { LOG_WARN("failed to connection observer", K_(sm_id), K(ret)); + } else { + + trans_state_.trace_log_.log_it("[create_conn]", + "time", get_based_hrtime(), + "lookup", trans_state_.pl_lookup_state_, + "sql_cmd", trans_state_.trans_info_.sql_cmd_, + "stmt_type", trans_state_.trans_info_.client_request_.get_parse_result().get_stmt_type(), + "in_trans", is_in_trans, + "internal_route", get_client_session()->is_trans_internal_routing() && is_in_trans, + "svr", trans_state_.server_info_.addr_); } } } @@ -5720,12 +6914,15 @@ inline int ObMysqlSM::connect_observer() return ret; } -int ObMysqlSM::do_internal_request_for_sharding_init_db(ObMIOBuffer *buf, - ObProxyMysqlRequest &client_request, - ObClientSessionInfo &client_info) +int ObMysqlSM::do_internal_request_for_sharding_init_db(ObMIOBuffer *buf) { int ret = OB_SUCCESS; - + + ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; + ObMysqlClientSession *client_session = get_client_session(); + ObClientSessionInfo &client_info = client_session->get_session_info(); + ObProxyProtocol client_procotol = get_client_session_protocol(); + // handle use db stmt or OB_MYSQL_COM_INIT_DB cmd when sharding LOG_DEBUG("sharding init db"); ObHSRResult &hsr = client_info.get_login_req().get_hsr_result(); @@ -5735,16 +6932,16 @@ int ObMysqlSM::do_internal_request_for_sharding_init_db(ObMIOBuffer *buf, } else { db_name = client_request.get_sql(); } - if (OB_FAIL(ObProxyShardUtils::handle_shard_use_db(trans_state_, *client_session_, db_name))) { + if (OB_FAIL(ObProxyShardUtils::handle_shard_use_db(trans_state_, *client_session, db_name))) { if (OB_ENTRY_NOT_EXIST == ret) { // response unknown db trans_state_.mysql_errcode_ = OB_ERR_BAD_DATABASE; trans_state_.mysql_errmsg_ = ob_strerror(OB_ERR_BAD_DATABASE); - if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_))) { + if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_, client_session))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to build err resp", K_(sm_id), K(ret)); } } else if (OB_ERR_NO_DB_PRIVILEGE == ret) { - if (OB_FAIL(ObMysqlTransact::build_no_privilege_message(trans_state_, *client_session_, db_name))) { + if (OB_FAIL(ObMysqlTransact::build_no_privilege_message(trans_state_, *client_session, db_name))) { LOG_WARN("fail to build_no_privilege_message", K(db_name), K(ret)); } } else { @@ -5754,9 +6951,11 @@ int ObMysqlSM::do_internal_request_for_sharding_init_db(ObMIOBuffer *buf, LOG_WARN("fail to save user login info", K_(sm_id), K(ret)); } else { // if start trans is hold, we treat this resp is in trans - bool is_in_trans = (trans_state_.is_hold_start_trans_ || ObMysqlTransact::is_in_trans(trans_state_)); - if (OB_FAIL(ObMysqlResponseBuilder::build_ok_resq_with_state_changed( - *buf, client_request, client_info, is_in_trans))) { + bool is_in_trans = (trans_state_.is_hold_xa_start_ + || trans_state_.is_hold_start_trans_ + || ObMysqlTransact::is_in_trans(trans_state_)); + if (OB_FAIL(ObMysqlResponseBuilder::build_ok_resq_with_state_changed(*buf, client_request, *client_session, + client_procotol, is_in_trans))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to build ok res", K_(sm_id), K(ret)); } } @@ -5764,12 +6963,23 @@ int ObMysqlSM::do_internal_request_for_sharding_init_db(ObMIOBuffer *buf, return ret; } -int ObMysqlSM::do_internal_request_for_sharding_show_db_version(ObMIOBuffer *buf, - ObProxyMysqlRequest &client_request, - ObClientSessionInfo &client_info) +int ObMysqlSM::do_internal_request_for_sharding_show_db_version(ObMIOBuffer *buf) { int ret = OB_SUCCESS; + ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; + ObMysqlClientSession *client_session = get_client_session(); + ObClientSessionInfo &client_info = client_session->get_session_info(); + ObProxyProtocol client_protocol = get_client_session_protocol(); + Ob20ProtocolHeader &ob20_head = client_session->get_session_info().ob20_request_.ob20_header_; + uint8_t compressed_seq = static_cast(client_session->get_compressed_seq() + 1); + Ob20ProtocolHeaderParam ob20_head_param(client_session->get_cs_id(), ob20_head.request_id_, compressed_seq, + compressed_seq, true, false, false, + client_session->is_client_support_new_extra_info(), + client_session->is_trans_internal_routing()); + ObCmdInfo info(static_cast(client_request.get_packet_meta().pkt_seq_ + 1), + trans_state_.mysql_config_params_->internal_cmd_mem_limited_, client_protocol, ob20_head_param); + // handle show db version when sharding LOG_DEBUG("sharding show db_version"); ObString logic_tenant_name; @@ -5780,80 +6990,151 @@ int ObMysqlSM::do_internal_request_for_sharding_show_db_version(ObMIOBuffer *buf LOG_WARN("fail to get_logic_database_name", K(ret)); trans_state_.mysql_errcode_ = OB_ERR_NO_DB_SELECTED; trans_state_.mysql_errmsg_ = ob_strerror(OB_ERR_NO_DB_SELECTED); - if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_))) { + if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_, client_session))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to build not err resp", K_(sm_id), K(ret)); } - } else if (OB_FAIL(ObShowDBVersionHandler::show_db_version_cmd_callback(buf, - static_cast(client_request.get_packet_meta().pkt_seq_ + 1), - trans_state_.mysql_config_params_->internal_cmd_mem_limited_, - logic_tenant_name, logic_database_name))) { + } else if (OB_FAIL(ObShowDBVersionHandler::show_db_version_cmd_callback(buf, info, logic_tenant_name, + logic_database_name))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to handle show db version", K_(sm_id), K(ret)); } return ret; } -int ObMysqlSM::do_internal_request_for_sharding_show_db(ObMIOBuffer *buf, - ObProxyMysqlRequest &client_request, - ObClientSessionInfo &client_info) +int ObMysqlSM::do_internal_request_for_sharding_show_db(ObMIOBuffer *buf) { int ret = OB_SUCCESS; + ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; + ObMysqlClientSession *client_session = get_client_session(); + ObClientSessionInfo &client_info = client_session->get_session_info(); + ObProxyProtocol client_protocol = get_client_session_protocol(); + Ob20ProtocolHeader &ob20_head = client_session->get_session_info().ob20_request_.ob20_header_; + uint8_t compressed_seq = static_cast(client_session->get_compressed_seq() + 1); + Ob20ProtocolHeaderParam ob20_head_param(client_session->get_cs_id(), ob20_head.request_id_, compressed_seq, + compressed_seq, true, false, false, + client_session->is_client_support_new_extra_info(), + client_session->is_trans_internal_routing()); + ObCmdInfo info(static_cast(client_request.get_packet_meta().pkt_seq_ + 1), + trans_state_.mysql_config_params_->internal_cmd_mem_limited_, client_protocol, ob20_head_param); + // handle show databases when sharding LOG_DEBUG("sharding show databases"); ObString logic_tenant_name; if (OB_FAIL(client_info.get_logic_tenant_name(logic_tenant_name))) { LOG_WARN("fail to get_logic_tenant_name", K(ret)); - } else if (OB_FAIL(ObShowDatabasesHandler::show_databases_cmd_callback(buf, - static_cast(client_request.get_packet_meta().pkt_seq_ + 1), - trans_state_.mysql_config_params_->internal_cmd_mem_limited_, logic_tenant_name))) { + } else if (OB_FAIL(ObShowDatabasesHandler::show_databases_cmd_callback(buf, info, logic_tenant_name))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to handle show databases", K_(sm_id), K(ret)); } return ret; } -int ObMysqlSM::do_internal_request_for_sharding_show_table(ObMIOBuffer *buf, - ObProxyMysqlRequest &client_request, - ObClientSessionInfo &client_info) +int ObMysqlSM::do_internal_request_for_sharding_show_table(ObMIOBuffer *buf) { int ret = OB_SUCCESS; + ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; + ObMysqlClientSession *client_session = get_client_session(); + ObClientSessionInfo &client_info = client_session->get_session_info(); + ObProxyProtocol client_protocol = get_client_session_protocol(); + Ob20ProtocolHeader &ob20_head = client_session->get_session_info().ob20_request_.ob20_header_; + uint8_t compressed_seq = static_cast(client_session->get_compressed_seq() + 1); + Ob20ProtocolHeaderParam ob20_head_param(client_session->get_cs_id(), ob20_head.request_id_, compressed_seq, + compressed_seq, true, false, false, + client_session->is_client_support_new_extra_info(), + client_session->is_trans_internal_routing()); + ObCmdInfo info(static_cast(client_request.get_packet_meta().pkt_seq_ + 1), + trans_state_.mysql_config_params_->internal_cmd_mem_limited_, client_protocol, ob20_head_param); + // handle show tables when sharding LOG_DEBUG("sharding show tables"); ObString logic_tenant_name; - ObString logic_database_name; + ObString logic_database_name = client_request.get_parse_result().get_database_name(); + ObString logic_table_name = client_request.get_parse_result().get_table_name(); + if (OB_FAIL(client_info.get_logic_tenant_name(logic_tenant_name))) { LOG_WARN("fail to get_logic_tenant_name", K(ret)); - } else if (OB_FAIL(client_info.get_logic_database_name(logic_database_name))) { + } else if (logic_database_name.empty() && + OB_FAIL(client_info.get_logic_database_name(logic_database_name))) { LOG_WARN("fail to get_logic_database_name", K(ret)); trans_state_.mysql_errcode_ = OB_ERR_NO_DB_SELECTED; trans_state_.mysql_errmsg_ = ob_strerror(OB_ERR_NO_DB_SELECTED); - if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_))) { + if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_, client_session))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to build not err resp", K_(sm_id), K(ret)); } - } else if (OB_FAIL(ObShowTablesHandler::show_tables_cmd_callback(buf, - static_cast(client_request.get_packet_meta().pkt_seq_ + 1), - trans_state_.mysql_config_params_->internal_cmd_mem_limited_, - logic_tenant_name, logic_database_name))) { + } else if (OB_FAIL(ObShowTablesHandler::show_tables_cmd_callback(buf, info, client_request.get_parse_result().get_cmd_sub_type(), + logic_tenant_name, logic_database_name, logic_table_name))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to handle show databases", K_(sm_id), K(ret)); } return ret; } -int ObMysqlSM::do_internal_request_for_sharding_show_topology(ObMIOBuffer *buf, - ObProxyMysqlRequest &client_request, - ObClientSessionInfo &client_info) +int ObMysqlSM::do_internal_request_for_sharding_show_table_status(ObMIOBuffer *buf) { int ret = OB_SUCCESS; + ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; + ObMysqlClientSession *client_session = get_client_session(); + ObClientSessionInfo &client_info = client_session->get_session_info(); + ObProxyProtocol client_protocol = get_client_session_protocol(); + Ob20ProtocolHeader &ob20_head = client_session->get_session_info().ob20_request_.ob20_header_; + uint8_t compressed_seq = static_cast(client_session->get_compressed_seq() + 1); + + // handle show table status when sharding + LOG_DEBUG("sharding show table status"); + ObString logic_database_name = client_request.get_parse_result().get_database_name(); + ObString logic_table_name = client_request.get_parse_result().get_table_name(); + ObString logic_tenant_name; - // handle show topology when sharding + Ob20ProtocolHeaderParam ob20_head_param(client_session->get_cs_id(), ob20_head.request_id_, compressed_seq, + compressed_seq, true, false, false, + client_session->is_client_support_new_extra_info(), + client_session->is_trans_internal_routing()); + ObCmdInfo info(static_cast(client_request.get_packet_meta().pkt_seq_ + 1), + trans_state_.mysql_config_params_->internal_cmd_mem_limited_, client_protocol, ob20_head_param); + + if (OB_FAIL(client_info.get_logic_tenant_name(logic_tenant_name))) { + LOG_WARN("fail to get_logic_tenant_name", K(ret)); + } else if (logic_database_name.empty() && + OB_FAIL(client_info.get_logic_database_name(logic_database_name))) { + LOG_WARN("fail to get_logic_database_name", K(ret)); + trans_state_.mysql_errcode_ = OB_ERR_NO_DB_SELECTED; + trans_state_.mysql_errmsg_ = ob_strerror(OB_ERR_NO_DB_SELECTED); + if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_, client_session))) { + LOG_WARN("[ObMysqlSM::do_internal_request] fail to build not err resp", K_(sm_id), K(ret)); + } + } else if (OB_FAIL(ObShowTableStatusHandler::show_table_status_cmd_callback(buf, info, + logic_tenant_name, logic_database_name, logic_table_name))) { + LOG_WARN("[ObMysqlSM::do_internal_request] fail to handle show table status", K_(sm_id), K(ret)); + } + + return ret; +} + +int ObMysqlSM::do_internal_request_for_sharding_show_elastic_id(ObMIOBuffer *buf) +{ + int ret = OB_SUCCESS; + + ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; + ObMysqlClientSession *client_session = get_client_session(); + ObClientSessionInfo &client_info = client_session->get_session_info(); + ObProxyProtocol client_protocol = get_client_session_protocol(); + Ob20ProtocolHeader &ob20_head = client_session->get_session_info().ob20_request_.ob20_header_; + uint8_t compressed_seq = static_cast(client_session->get_compressed_seq() + 1); + Ob20ProtocolHeaderParam ob20_head_param(client_session->get_cs_id(), ob20_head.request_id_, compressed_seq, + compressed_seq, true, false, false, + client_session->is_client_support_new_extra_info(), + client_session->is_trans_internal_routing()); + ObCmdInfo info(static_cast(client_request.get_packet_meta().pkt_seq_ + 1), + trans_state_.mysql_config_params_->internal_cmd_mem_limited_, client_protocol, ob20_head_param); + + // handle show elastic id when sharding ObInternalCmdInfo &cmd_info = *client_request.cmd_info_; ObString logic_db_name = cmd_info.get_like_string(); ObString logic_tenant_name; ObString group_name = cmd_info.get_value_string(); - LOG_DEBUG("sharding show topology", K(logic_db_name), K(group_name)); + LOG_DEBUG("sharding show elastic id", K(logic_db_name), K(group_name)); if (logic_db_name.empty()) { if (OB_FAIL(client_info.get_logic_database_name(logic_db_name))) { LOG_WARN("fail to get_logic_db_name", K(ret)); @@ -5861,30 +7142,75 @@ int ObMysqlSM::do_internal_request_for_sharding_show_topology(ObMIOBuffer *buf, } if (OB_FAIL(ret)) { // do nothing - } if (OB_FAIL(client_info.get_logic_tenant_name(logic_tenant_name))) { + } else if (OB_FAIL(client_info.get_logic_tenant_name(logic_tenant_name))) { LOG_WARN("fail to get_logic_tenant_name", K(ret)); - } else if (OB_FAIL(ObShowTopologyHandler::show_topology_cmd_callback(buf, - static_cast(client_request.get_packet_meta().pkt_seq_ + 1), - trans_state_.mysql_config_params_->internal_cmd_mem_limited_, - logic_tenant_name, logic_db_name, group_name))) { - LOG_WARN("[ObMysqlSM::do_internal_request] fail to handle show topology", K_(sm_id), K(ret)); + } else if (OB_FAIL(ObShowTopologyHandler::show_elastic_id_cmd_callback(buf, info, + logic_tenant_name, logic_db_name, group_name))) { + LOG_WARN("[ObMysqlSM::do_internal_request] fail to handle show elastic id", K_(sm_id), K(ret)); } + return ret; +} + + +int ObMysqlSM::do_internal_request_for_sharding_show_topology(ObMIOBuffer *buf) +{ + int ret = OB_SUCCESS; + ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; + ObMysqlClientSession *client_session = get_client_session(); + ObClientSessionInfo &client_info = client_session->get_session_info(); + ObProxyProtocol client_protocol = get_client_session_protocol(); + Ob20ProtocolHeader &ob20_head = client_session->get_session_info().ob20_request_.ob20_header_; + uint8_t compressed_seq = static_cast(client_session->get_compressed_seq() + 1); + Ob20ProtocolHeaderParam ob20_head_param(client_session->get_cs_id(), ob20_head.request_id_, compressed_seq, + compressed_seq, true, false, false, + client_session->is_client_support_new_extra_info(), + client_session->is_proxy_enable_trans_internal_routing()); + ObCmdInfo info(static_cast(client_request.get_packet_meta().pkt_seq_ + 1), + trans_state_.mysql_config_params_->internal_cmd_mem_limited_, client_protocol, ob20_head_param); + + // handle show topology when sharding + ObString logic_db_name; + ObString logic_tenant_name; + ObString logic_table_name = client_request.get_parse_result().get_table_name(); + LOG_DEBUG("sharding show topology", K(logic_db_name)); + if (logic_db_name.empty()) { + if (OB_FAIL(client_info.get_logic_database_name(logic_db_name))) { + LOG_WARN("fail to get_logic_db_name", K(ret)); + } + } + if (OB_FAIL(ret)) { + // do nothing + } else if (OB_FAIL(client_info.get_logic_tenant_name(logic_tenant_name))) { + LOG_WARN("fail to get_logic_tenant_name", K(ret)); + } else if (OB_FAIL(client_info.get_logic_database_name(logic_db_name))) { + } else if (OB_FAIL(ObShowTopologyHandler::show_topology_cmd_callback(buf, info, + logic_tenant_name, logic_db_name, logic_table_name))) { + LOG_WARN("[ObMysqlSM::do_internal_request] fail to handle show topology", K_(sm_id), K(ret)); + } return ret; } -int ObMysqlSM::do_internal_request_for_sharding_select_db(ObMIOBuffer *buf, - ObProxyMysqlRequest &client_request, - ObClientSessionInfo &client_info) +int ObMysqlSM::do_internal_request_for_sharding_select_db(ObMIOBuffer *buf) { int ret = OB_SUCCESS; + ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; + ObMysqlClientSession *client_session = get_client_session(); + ObClientSessionInfo &client_info = client_session->get_session_info(); + ObProxyProtocol client_protocol = get_client_session_protocol(); + Ob20ProtocolHeader &ob20_head = client_session->get_session_info().ob20_request_.ob20_header_; + uint8_t compressed_seq = static_cast(client_session->get_compressed_seq() + 1); + Ob20ProtocolHeaderParam ob20_head_param(client_session->get_cs_id(), ob20_head.request_id_, compressed_seq, + compressed_seq, true, false, false, + client_session->is_client_support_new_extra_info(), + client_session->is_trans_internal_routing()); + ObCmdInfo info(static_cast(client_request.get_packet_meta().pkt_seq_ + 1), + trans_state_.mysql_config_params_->internal_cmd_mem_limited_, client_protocol, ob20_head_param); + ObString logic_database_name; client_info.get_logic_database_name(logic_database_name); - if (OB_FAIL(ObSelectDatabaseHandler::select_database_cmd_callback(buf, - static_cast(client_request.get_packet_meta().pkt_seq_ + 1), - trans_state_.mysql_config_params_->internal_cmd_mem_limited_, - logic_database_name))) { + if (OB_FAIL(ObSelectDatabaseHandler::select_database_cmd_callback(buf, info, logic_database_name))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to handle select database()", K_(sm_id), K(ret)); } @@ -5916,14 +7242,16 @@ void ObMysqlSM::do_internal_request() K_(sm_id), K(ret)); } else { buf = trans_state_.internal_buffer_; + ObProxyProtocol client_protocol = get_client_session_protocol(); + switch (trans_state_.trans_info_.sql_cmd_) { case OB_MYSQL_COM_HANDSHAKE: { OMPKHandshake handshake; - if (!client_session_->is_proxy_mysql_client_ && - get_global_ssl_config_table_processor().is_ssl_supported( + if (enable_client_ssl_ + && !client_session_->is_proxy_mysql_client_ && + get_global_ssl_config_table_processor().is_ssl_key_info_valid( client_session_->get_vip_cluster_name(), - client_session_->get_vip_tenant_name(), - true)) { + client_session_->get_vip_tenant_name())) { handshake.enable_ssl(); } // current not support compress to client @@ -5951,8 +7279,8 @@ void ObMysqlSM::do_internal_request() } } - if (FAILEDx(ObMysqlPacketWriter::write_packet(*buf, handshake))) { - LOG_WARN("fail to serialize handshake packet", K_(sm_id), K(ret)); + if (FAILEDx(ObProxyPacketWriter::write_packet(*buf, *client_session_, client_protocol, handshake))) { + LOG_WARN("fail to build handshake packet", K_(sm_id), K(ret)); } else { ObMySQLCapabilityFlags capability(handshake.get_server_capability()); client_session_->get_session_info().save_orig_capability_flags(capability); @@ -5971,27 +7299,20 @@ void ObMysqlSM::do_internal_request() ObMysqlAuthRequest &orig_auth_req = client_session_->get_session_info().get_login_req(); const ObMySQLCapabilityFlags &capability = client_session_->get_session_info().get_orig_capability_flags(); uint8_t pkt_seq = static_cast(orig_auth_req.get_packet_meta().pkt_seq_ + 1); - - if (OB_FAIL(ObMysqlPacketUtil::encode_ok_packet(*buf, pkt_seq, 0, capability))) { - LOG_WARN("[ObMysqlSM::do_internal_request] fail to encode login response ok packet", - K_(sm_id), K(ret)); + if (OB_FAIL(ObProxyPacketWriter::write_ok_packet(*buf, *client_session_, client_protocol, + pkt_seq, 0, capability))) { + LOG_WARN("fail to write ok packet", K(ret)); } } break; } case OB_MYSQL_COM_PING: { LOG_DEBUG("proxy response OB_MYSQL_COM_PING ok packet", K_(sm_id), "cs_id", client_session_->get_cs_id()); - if (OB_LIKELY(get_global_hot_upgrade_info().need_conn_accept_)) { - uint8_t pkt_seq = static_cast(trans_state_.trans_info_.client_request_.get_packet_meta().pkt_seq_ + 1); - const ObMySQLCapabilityFlags &capability = client_session_->get_session_info().get_orig_capability_flags(); - if (OB_FAIL(ObMysqlPacketUtil::encode_ok_packet(*buf, pkt_seq, 0, capability))) { - LOG_WARN("[ObMysqlSM::do_internal_request] fail to encode OB_MYSQL_COM_PING response ok packet", - K_(sm_id), K(ret)); - } - } else { - ret = OB_SERVER_IS_STOPPING; - LOG_INFO("proxy had been stop accepting new connection, " - "disconnect here for OB_MYSQL_COM_PING", K_(sm_id), "cs_id", client_session_->get_cs_id(), K(ret)); + uint8_t pkt_seq = static_cast(trans_state_.trans_info_.client_request_.get_packet_meta().pkt_seq_ + 1); + const ObMySQLCapabilityFlags &capability = client_session_->get_session_info().get_orig_capability_flags(); + if (OB_FAIL(ObProxyPacketWriter::write_ok_packet(*buf, *client_session_, client_protocol, + pkt_seq, 0, capability))) { + LOG_WARN("fail to encode OB_MYSQL_COM_PING response ok packet", K(ret)); } break; } @@ -6015,6 +7336,21 @@ void ObMysqlSM::do_internal_request() break; } + case OB_MYSQL_COM_STMT_RESET: { + ObClientSessionInfo &client_info = client_session_->get_session_info(); + uint32_t client_ps_id = client_info.get_client_ps_id(); + + uint8_t pkt_seq = static_cast(trans_state_.trans_info_.client_request_.get_packet_meta().pkt_seq_ + 1); + const ObMySQLCapabilityFlags &capability = client_info.get_orig_capability_flags(); + if (OB_FAIL(ObProxyPacketWriter::write_ok_packet(*buf, *client_session_, client_protocol, + pkt_seq, 0, capability))) { + LOG_WARN("[ObMysqlSM::do_internal_request] fail to build OB_MYSQL_COM_STMT_RESET response ok packet", + K_(sm_id), K(client_ps_id), K(ret)); + } + LOG_DEBUG("proxy no response OB_MYSQL_COM_STMT_RESET", K_(sm_id), "cs_id", client_session_->get_cs_id()); + break; + } + case OB_MYSQL_COM_QUERY: case OB_MYSQL_COM_SLEEP: case OB_MYSQL_COM_INIT_DB: @@ -6031,68 +7367,68 @@ void ObMysqlSM::do_internal_request() case OB_MYSQL_COM_DELAYED_INSERT: case OB_MYSQL_COM_CHANGE_USER: case OB_MYSQL_COM_SHUTDOWN: + case OB_MYSQL_COM_STMT_PREPARE_EXECUTE: case OB_MYSQL_COM_DAEMON: { ObProxyMysqlRequest &client_request = trans_state_.trans_info_.client_request_; ObClientSessionInfo &client_info = client_session_->get_session_info(); uint8_t next_seq = static_cast(client_request.get_packet_meta().pkt_seq_ + 1); // 1. hold_start_trans if (client_request.get_parse_result().need_hold_start_trans()) { + // hold begin reset hold xa start trans_state_.is_hold_start_trans_ = true; - if (OB_FAIL(ObMysqlResponseBuilder::build_start_trans_resp(*buf, client_request, client_info))) { + if (OB_FAIL(ObMysqlResponseBuilder::build_start_trans_resp(*buf, client_request, + *client_session_, client_protocol))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to build start trans resp", K_(sm_id), K(ret)); } - + // hold_xa_start + } else if (client_request.get_parse_result().need_hold_xa_start()) { + LOG_DEBUG("[ObMysqlSM::do_internal_request] to build xa start resp"); + // hold xa start reset hold begin + trans_state_.is_hold_xa_start_ = true; + if (OB_FAIL(ObMysqlResponseBuilder::build_prepare_execute_xa_start_resp(*buf, client_request, + *client_session_, client_protocol))) { + LOG_WARN("[ObMysqlSM::do_internal_request] fail to build xa start resp", K_(sm_id), K(ret)); + } // 2. bad_route_request } else if (ObMysqlTransact::is_bad_route_request(trans_state_)) { trans_state_.mysql_errcode_ = OB_NOT_SUPPORTED; trans_state_.mysql_errmsg_ = "Not supported, bad route request"; - if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_))) { + if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_, client_session_))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to encode err pacekt buf", K_(sm_id), K(next_seq), "errcode", trans_state_.mysql_errcode_, "user_err_msg", trans_state_.mysql_errmsg_, K(ret)); } else { // throw away the former 'begin' or 'start transaction' trans_state_.is_hold_start_trans_ = false; + trans_state_.is_hold_xa_start_ = false; } // 3. not_supported } else if (client_request.get_parse_result().is_not_supported()) { trans_state_.mysql_errcode_ = OB_NOT_SUPPORTED; - if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_))) { + if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_, client_session_))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to build not supported err resp", K_(sm_id), K(ret)); } // 4. select_tx_ro } else if (client_request.get_parse_result().is_select_tx_ro()) { // if start trans is hold, we treat this resp is in trans - bool is_in_trans = (trans_state_.is_hold_start_trans_ || ObMysqlTransact::is_in_trans(trans_state_)); - if (OB_FAIL(ObMysqlResponseBuilder::build_select_tx_ro_resp( - *buf, client_request, client_info, is_in_trans))) { + bool is_in_trans = (trans_state_.is_hold_xa_start_ + || trans_state_.is_hold_start_trans_ + || ObMysqlTransact::is_in_trans(trans_state_)); + if (OB_FAIL(ObMysqlResponseBuilder::build_select_tx_ro_resp(*buf, client_request, *client_session_, + client_protocol, is_in_trans))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to build select @@tx_read_only", K_(sm_id), K(ret)); } - - // 5. set_autocommit_0 - } else if (client_request.get_parse_result().is_set_autocommit_0()) { - // if start trans is hold, we treat this resp is in trans - bool is_in_trans = (trans_state_.is_hold_start_trans_ || ObMysqlTransact::is_in_trans(trans_state_)); - ObObj value; - value.set_int(0); - if (client_info.update_common_sys_variable("autocommit", value, true, false)) { - LOG_WARN("fail to update sys variable", K_(sm_id), K(ret)); - } else if (OB_FAIL(ObMysqlResponseBuilder::build_ok_resq_with_state_changed( - *buf, client_request, client_info, is_in_trans))) { - LOG_WARN("[ObMysqlSM::do_internal_request] fail to build set autocommit = 0", K_(sm_id), K(ret)); - } - // 6. ping_proxy } else if (client_request.get_parse_result().is_ping_proxy_cmd() && !client_request.get_parse_result().is_internal_error_cmd()) { if (OB_LIKELY(get_global_hot_upgrade_info().need_conn_accept_)) { uint8_t pkt_seq = static_cast(trans_state_.trans_info_.client_request_.get_packet_meta().pkt_seq_ + 1); const ObMySQLCapabilityFlags &capability = client_session_->get_session_info().get_orig_capability_flags(); - if (OB_FAIL(ObMysqlPacketUtil::encode_ok_packet(*buf, pkt_seq, 0, capability))) { - LOG_WARN("[ObMysqlSM::do_internal_request] fail to encode 'ping proxy' response ok packet", - K_(sm_id), K(ret)); + if (OB_FAIL(ObProxyPacketWriter::write_ok_packet(*buf, *client_session_, client_protocol, + pkt_seq, 0, capability))) { + LOG_WARN("fail to write ok packet", K(ret)); } } else { ret = OB_SERVER_IS_STOPPING; @@ -6106,14 +7442,14 @@ void ObMysqlSM::do_internal_request() // python mysql will send 'SET autocommit=0' after connected, proxysys need resp ok packet uint8_t pkt_seq = static_cast(trans_state_.trans_info_.client_request_.get_packet_meta().pkt_seq_ + 1); const ObMySQLCapabilityFlags &capability = client_session_->get_session_info().get_orig_capability_flags(); - if (OB_FAIL(ObMysqlPacketUtil::encode_ok_packet(*buf, pkt_seq, 0, capability))) { - LOG_WARN("[ObMysqlSM::do_internal_request] fail to encode ok packet for internal cmd", - K_(sm_id), K(ret)); + if (OB_FAIL(ObProxyPacketWriter::write_ok_packet(*buf, *client_session_, client_protocol, + pkt_seq, 0, capability))) { + LOG_WARN("fail to build ok packet", K(ret)); } } else { trans_state_.mysql_errcode_ = OB_ERR_OPERATOR_UNKNOWN; trans_state_.mysql_errmsg_ = "Unknown operator, bad internal cmd"; - if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_))) { + if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_, client_session_))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to build not err resp", K_(sm_id), K(ret)); } } @@ -6121,21 +7457,20 @@ void ObMysqlSM::do_internal_request() // 8. select route_addr } else if (client_request.get_parse_result().is_select_route_addr()) { ObMysqlServerSession *last_session = client_session_->get_server_session(); - int64_t addr = 0; if (NULL != last_session && NULL != last_session->get_netvc()) { - addr = ObMysqlTransact::build_addr_from_ip_port( - ntohl(last_session->get_netvc()->get_remote_ip()), - last_session->get_netvc()->get_remote_port()); // if start trans is hold, we treat this resp is in trans - bool is_in_trans = (trans_state_.is_hold_start_trans_ || ObMysqlTransact::is_in_trans(trans_state_)); - if (OB_FAIL(ObMysqlResponseBuilder::build_select_route_addr_resp( - *buf, client_request, client_info, is_in_trans, addr))) { + bool is_in_trans = (trans_state_.is_hold_xa_start_ + || trans_state_.is_hold_start_trans_ + || ObMysqlTransact::is_in_trans(trans_state_)); + if (OB_FAIL(ObMysqlResponseBuilder::build_select_route_addr_resp(*buf, client_request, + *client_session_, client_protocol, is_in_trans, + last_session->get_netvc()->get_remote_addr()))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to build select @obproxy_route_addr", K_(sm_id), K(ret)); } } else { trans_state_.mysql_errcode_ = OB_SERVER_NOT_ACTIVE; trans_state_.mysql_errmsg_ = "last session is invalid"; - if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_))) { + if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_, client_session_))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to build not err resp", K_(sm_id), K(ret)); } } @@ -6144,9 +7479,11 @@ void ObMysqlSM::do_internal_request() } else if (client_request.get_parse_result().is_set_route_addr()) { client_info.set_obproxy_route_addr(client_request.get_parse_result().cmd_info_.integer_[0]); // if start trans is hold, we treat this resp is in trans - bool is_in_trans = (trans_state_.is_hold_start_trans_ || ObMysqlTransact::is_in_trans(trans_state_)); - if (OB_FAIL(ObMysqlResponseBuilder::build_set_route_addr_resp( - *buf, client_request, client_info, is_in_trans))) { + bool is_in_trans = (trans_state_.is_hold_xa_start_ + || trans_state_.is_hold_start_trans_ + || ObMysqlTransact::is_in_trans(trans_state_)); + if (OB_FAIL(ObMysqlResponseBuilder::build_set_route_addr_resp(*buf, client_request, *client_session_, + client_protocol, is_in_trans))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to build set @obproxy_route_addr", K_(sm_id), K(ret)); } else { LOG_DEBUG("@obproxy_route_addr is set", K(client_info.get_obproxy_route_addr())); @@ -6156,7 +7493,7 @@ void ObMysqlSM::do_internal_request() if (client_session_->get_session_info().is_request_follower_user()) { trans_state_.mysql_errcode_ = OB_OP_NOT_ALLOW; trans_state_.mysql_errmsg_ = "set ob_read_consitency is not allowed"; - if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_))) { + if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_, client_session_))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to encode err pacekt buf", K_(sm_id), K(next_seq), "errcode", trans_state_.mysql_errcode_, "user_err_msg", trans_state_.mysql_errmsg_, K(ret)); @@ -6170,7 +7507,7 @@ void ObMysqlSM::do_internal_request() if (client_session_->get_session_info().is_read_only_user()) { trans_state_.mysql_errcode_ = OB_OP_NOT_ALLOW; trans_state_.mysql_errmsg_ = "set ob_read_consitency is not allowed"; - if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_))) { + if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_, client_session_))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to encode err pacekt buf", K_(sm_id), K(next_seq), "errcode", trans_state_.mysql_errcode_, "user_err_msg", trans_state_.mysql_errmsg_, K(ret)); @@ -6184,44 +7521,70 @@ void ObMysqlSM::do_internal_request() } else if (client_session_->get_session_info().is_sharding_user() && (OB_MYSQL_COM_INIT_DB == trans_state_.trans_info_.sql_cmd_ || client_request.get_parse_result().is_use_db_stmt())) { - if (OB_FAIL(do_internal_request_for_sharding_init_db(buf, client_request, client_info))) { + if (OB_FAIL(do_internal_request_for_sharding_init_db(buf))) { LOG_WARN("fail to do internal request for sharding init db", K_(sm_id), K(ret)); } } else if (client_session_->get_session_info().is_sharding_user() && client_request.get_parse_result().is_show_db_version_stmt()) { - if (OB_FAIL(do_internal_request_for_sharding_show_db_version(buf, client_request, client_info))) { + if (OB_FAIL(do_internal_request_for_sharding_show_db_version(buf))) { LOG_WARN("fail to do internal request for sharding show db version", K_(sm_id), K(ret)); } } else if (client_session_->get_session_info().is_sharding_user() && client_request.get_parse_result().is_show_databases_stmt()) { - if (OB_FAIL(do_internal_request_for_sharding_show_db(buf, client_request, client_info))) { + if (OB_FAIL(do_internal_request_for_sharding_show_db(buf))) { + LOG_WARN("fail to do internal request for sharding show db", K_(sm_id), K(ret)); + } + } else if (client_session_->get_session_info().is_sharding_user() + && (client_request.get_parse_result().is_show_tables_stmt() + || client_request.get_parse_result().is_show_full_tables_stmt())) { + if (OB_FAIL(do_internal_request_for_sharding_show_table(buf))) { LOG_WARN("fail to do internal request for sharding show db", K_(sm_id), K(ret)); } } else if (client_session_->get_session_info().is_sharding_user() - && client_request.get_parse_result().is_show_tables_stmt()) { - if (OB_FAIL(do_internal_request_for_sharding_show_table(buf, client_request, client_info))) { + && (client_request.get_parse_result().is_show_table_status_stmt())) { + if (OB_FAIL(do_internal_request_for_sharding_show_table_status(buf))) { + LOG_WARN("fail to do internal request for sharding show db", K_(sm_id), K(ret)); + } + } else if (client_session_->get_session_info().is_sharding_user() + && client_request.get_parse_result().is_show_elastic_id_stmt()) { + if (OB_FAIL(do_internal_request_for_sharding_show_elastic_id(buf))) { LOG_WARN("fail to do internal request for sharding show db", K_(sm_id), K(ret)); } } else if (client_session_->get_session_info().is_sharding_user() && client_request.get_parse_result().is_show_topology_stmt()) { - if (OB_FAIL(do_internal_request_for_sharding_show_topology(buf, client_request, client_info))) { + if (OB_FAIL(do_internal_request_for_sharding_show_topology(buf))) { LOG_WARN("fail to do internal request for sharding show db", K_(sm_id), K(ret)); } } else if (client_session_->get_session_info().is_sharding_user() && client_request.get_parse_result().is_select_database_stmt()) { - if (OB_FAIL(do_internal_request_for_sharding_select_db(buf, client_request, client_info))) { + if (OB_FAIL(do_internal_request_for_sharding_select_db(buf))) { LOG_WARN("fail to do internal request for sharding show db", K_(sm_id), K(ret)); } // 13. select_proxy_version } else if (client_request.get_parse_result().is_select_proxy_version()) { // if start trans is hold, we treat this resp is in trans - bool is_in_trans = (trans_state_.is_hold_start_trans_ || ObMysqlTransact::is_in_trans(trans_state_)); - if (OB_FAIL(ObMysqlResponseBuilder::build_select_proxy_version_resp( - *buf, client_request, client_info, is_in_trans))) { + bool is_in_trans = (trans_state_.is_hold_xa_start_ + || trans_state_.is_hold_start_trans_ + || ObMysqlTransact::is_in_trans(trans_state_)); + if (OB_FAIL(ObMysqlResponseBuilder::build_select_proxy_version_resp(*buf, client_request, *client_session_, + client_protocol, is_in_trans))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to build select proxy_version", K_(sm_id), K(ret)); } - - // 14. internal cmd + // 14. drop prepare stmt + } else if (client_request.get_parse_result().is_text_ps_drop_stmt()) { + ObString text_ps_name = client_request.get_parse_result().get_text_ps_name(); + uint32_t client_ps_id = client_info.get_client_ps_id(); + uint8_t pkt_seq = static_cast(trans_state_.trans_info_.client_request_.get_packet_meta().pkt_seq_ + 1); + const ObMySQLCapabilityFlags &capability = client_info.get_orig_capability_flags(); + if (OB_FAIL(ObProxyPacketWriter::write_ok_packet(*buf, *client_session_, client_protocol, + pkt_seq, 0, capability))) { + LOG_WARN("fail to write ok packet", K(ret)); + } else { + client_info.delete_text_ps_name_entry(text_ps_name); + client_info.remove_ps_id_addrs(client_ps_id); + LOG_DEBUG("proxy no response text ps drop", K_(sm_id), "cs_id", client_session_->get_cs_id()); + } + // 15. internal cmd } else { send_response_direct = false; if (OB_ISNULL(client_request.cmd_info_)) { @@ -6235,6 +7598,16 @@ void ObMysqlSM::do_internal_request() cmd_info.session_priv_ = &client_session_->get_session_info().get_priv_info(); cmd_info.set_memory_limit(trans_state_.mysql_config_params_->internal_cmd_mem_limited_); cmd_info.set_internal_user(client_request.is_proxysys_user()); + + Ob20ProtocolHeader &ob20_head = client_session_->get_session_info().ob20_request_.ob20_header_; + uint8_t compressed_seq = static_cast(client_session_->get_compressed_seq() + 1); + Ob20ProtocolHeaderParam ob20_head_param(client_session_->get_cs_id(), ob20_head.request_id_, compressed_seq, + compressed_seq, true, false, false, + client_session_->is_client_support_new_extra_info(), + client_session_->is_trans_internal_routing()); + cmd_info.set_protocol(get_client_session_protocol()); + cmd_info.set_ob20_head_param(ob20_head_param); + ObAction *cmd_handler = NULL; if (OB_FAIL(get_global_internal_cmd_processor().execute_cmd(this, cmd_info, buf, cmd_handler))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to execute_cmd", K_(sm_id), K(ret)); @@ -6260,7 +7633,7 @@ void ObMysqlSM::do_internal_request() if (!is_supported_mysql_cmd(trans_state_.trans_info_.sql_cmd_)) { LOG_WARN("not supported mysql cmd", K_(sm_id), "cmd", get_mysql_cmd_str(trans_state_.trans_info_.sql_cmd_)); trans_state_.mysql_errcode_ = OB_NOT_SUPPORTED; - if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_))) { + if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state_, client_session_))) { LOG_WARN("[ObMysqlSM::do_internal_request] fail to build not supported err resp", K_(sm_id), K(ret)); } } else { @@ -6305,6 +7678,7 @@ inline void ObMysqlSM::set_client_abort(const ObMysqlTransact::ObAbortStateType break; case VC_EVENT_ERROR: + case VC_EVENT_DETECT_SERVER_DEAD: trans_state_.client_info_.state_ = ObMysqlTransact::CONNECTION_ERROR; xflush_head = XFH_CONNECTION_ERROR; break; @@ -6345,7 +7719,7 @@ inline void ObMysqlSM::set_client_abort(const ObMysqlTransact::ObAbortStateType "request_cmd", get_mysql_cmd_str(trans_state_.trans_info_.client_request_.get_packet_meta().cmd_), "sql_cmd", get_mysql_cmd_str(trans_state_.trans_info_.sql_cmd_), "sql", trans_state_.trans_info_.get_print_sql()); - } else { + } else if (client_session_->get_session_info().get_priv_info().user_name_ != ObProxyTableInfo::DETECT_USERNAME_USER) { LOG_WARN("client will abort soon", K_(sm_id), K(cs_id), @@ -6480,6 +7854,16 @@ void ObMysqlSM::handle_observer_open() milestones_.do_observer_open_end_); } + if (enable_record_full_link_trace_info()) { + trace::ObSpanCtx *ctx = flt_.trace_log_info_.do_observer_open_ctx_; + if (OB_NOT_NULL(ctx)) { + LOG_DEBUG("end span ob_proxy_do_observer_open", K(ctx->span_id_)); + SET_TRACE_BUFFER(flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + FLT_END_SPAN(ctx); + flt_.trace_log_info_.do_observer_open_ctx_ = NULL; + } + } + // applying per-transaction observer netVC options // here IFF they differ from the netVC's current // options. This should keep this from being @@ -6540,9 +7924,10 @@ void ObMysqlSM::handle_observer_open() //fall through case ObMysqlTransact::SERVER_SEND_SESSION_VARS: //fall through - case ObMysqlTransact::SERVER_SEND_LAST_INSERT_ID: + case ObMysqlTransact::SERVER_SEND_SESSION_USER_VARS: //fall through case ObMysqlTransact::SERVER_SEND_START_TRANS: + case ObMysqlTransact::SERVER_SEND_XA_START: //fall through case ObMysqlTransact::SERVER_SEND_PREPARE: case ObMysqlTransact::SERVER_SEND_TEXT_PS_PREPARE: @@ -6573,13 +7958,16 @@ void ObMysqlSM::handle_observer_open() inline bool ObMysqlSM::need_setup_client_transfer() { bool need = false; + ObProxyProtocol server_protocol = get_server_session_protocol(); + if (OB_LIKELY(client_session_->get_session_info().is_oceanbase_server())) { need = (!trans_state_.is_auth_request_ && trans_state_.trans_info_.request_content_length_ > 0 - && (PROTOCOL_CHECKSUM == use_compression_protocol() - || PROTOCOL_OB20 == use_compression_protocol() + && (ObProxyProtocol::PROTOCOL_CHECKSUM == server_protocol + || ObProxyProtocol::PROTOCOL_OB20 == server_protocol || obmysql::OB_MYSQL_COM_STMT_PREPARE == trans_state_.trans_info_.client_request_.get_packet_meta().cmd_ - || obmysql::OB_MYSQL_COM_STMT_EXECUTE == trans_state_.trans_info_.client_request_.get_packet_meta().cmd_) + || obmysql::OB_MYSQL_COM_STMT_EXECUTE == trans_state_.trans_info_.client_request_.get_packet_meta().cmd_ + || trans_state_.trans_info_.client_request_.get_parse_result().is_text_ps_prepare_stmt()) && NULL != api_.do_request_transform_open()); if (need) { LOG_DEBUG("[need_setup_client_transfer] will setup client transfer", K_(sm_id)); @@ -6676,7 +8064,8 @@ void ObMysqlSM::handle_server_setup_error(int event, void *data) : ObMysqlTransact::CONNECTION_CLOSED); break; } - case VC_EVENT_ERROR: { + case VC_EVENT_ERROR: + case VC_EVENT_DETECT_SERVER_DEAD: { trans_state_.current_.state_ = ObMysqlTransact::CONNECTION_ERROR; break; } @@ -6808,13 +8197,15 @@ int ObMysqlSM::setup_client_transfer(ObMysqlVCType to_vc_type) switch (to_vc_type) { case MYSQL_TRANSFORM_VC: MYSQL_SM_SET_DEFAULT_HANDLER(&ObMysqlSM::state_request_wait_for_transform_read); - if (OB_ISNULL(api_.request_transform_info_.entry_) - || api_.request_transform_info_.entry_->vc_ != api_.request_transform_info_.vc_) { + if (OB_ISNULL(api_.request_transform_info_.entry_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid internal state", KP_(api_.request_transform_info_.vc), K_(sm_id), K(ret)); + } else if (api_.request_transform_info_.entry_->vc_ != api_.request_transform_info_.vc_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid internal state", - K_(api_.request_transform_info_.entry), - K_(api_.request_transform_info_.entry_->vc), - K_(api_.request_transform_info_.vc), K_(sm_id), K(ret)); + KP_(api_.request_transform_info_.entry), + KP_(api_.request_transform_info_.entry_->vc), + KP_(api_.request_transform_info_.vc), K_(sm_id), K(ret)); } else if (OB_ISNULL(c = tunnel_.add_consumer(api_.request_transform_info_.entry_->vc_, client_entry_->vc_, &ObMysqlSM::tunnel_handler_transform_write, @@ -6907,9 +8298,10 @@ int ObMysqlSM::attach_server_session(ObMysqlServerSession &s) server_entry_->vc_handler_ = &ObMysqlSM::state_server_request_send; if (OB_UNLIKELY(client_session_->is_session_pool_client() && client_session_->is_proxy_mysql_client_)) { - if (server_session_->get_session_info().get_ob_capability() == 0) { - server_session_->get_session_info().set_ob_capability(client_session_->get_session_info().get_ob_capability()); - LOG_DEBUG("set_ob_capability", K(client_session_->get_session_info().get_ob_capability())); + if (server_session_->get_session_info().get_server_ob_capability() == 0) { + uint64_t ob_server_cap = client_session_->get_session_info().get_server_ob_capability(); + server_session_->get_session_info().set_server_ob_capability(ob_server_cap); + LOG_DEBUG("set server session capability", K(ob_server_cap)); } } @@ -6976,7 +8368,8 @@ int ObMysqlSM::setup_server_request_send() LOG_ERROR("invalid send_action", "send_action", trans_state_.current_.send_action_, K_(sm_id), K(ret)); dump_history_state(); } else { - LOG_DEBUG("[ObMysqlSM::setup_server_request_send] send request to observer", K_(sm_id)); + LOG_DEBUG("[ObMysqlSM::setup_server_request_send] send request to observer", K_(sm_id), + K(trans_state_.current_.send_action_)); // Send the request header server_entry_->vc_handler_ = &ObMysqlSM::state_server_request_send; @@ -7020,12 +8413,23 @@ int ObMysqlSM::setup_server_request_send() } } + if (enable_record_full_link_trace_info()) { + SET_TRACE_BUFFER(flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + trace::ObSpanCtx *ctx = FLT_BEGIN_SPAN(ob_proxy_server_request_write); + if (OB_NOT_NULL(ctx)) { + flt_.trace_log_info_.server_request_write_ctx_ = ctx; + LOG_DEBUG("begin span ob_proxy_server_request_write", K(ctx->span_id_)); + } + } + LOG_DEBUG("build server request finish", K(flt_.span_info_)); + // if write_buffer_ is not NULL, when clean server entry, will free the write_buffer_. // so the mio_buffer we alloc in build_server_request will free evently. server_entry_->write_buffer_ = (buf_start != client_buffer_reader_) ? buf_start->writer() : NULL; // set query_timeout to each request, ddl stmt will never timeout - if (OB_UNLIKELY(trans_state_.trans_info_.client_request_.get_parse_result().is_ddl_stmt())) { + if (OB_UNLIKELY(trans_state_.trans_info_.client_request_.get_parse_result().is_ddl_stmt() + || ObMysqlTransact::is_binlog_request(trans_state_))) { cancel_server_query_timeout(); // if PL/SQL: // 1. if in trans, use trx timeout @@ -7034,8 +8438,11 @@ int ObMysqlSM::setup_server_request_send() // 1. if send begin or start, think as in trans // 2. if autocommit = 0, first SQL think as not in trans } else if (OB_UNLIKELY(trans_state_.trans_info_.client_request_.get_parse_result().is_call_stmt() + || trans_state_.trans_info_.client_request_.get_parse_result().is_text_ps_call_stmt() || trans_state_.trans_info_.client_request_.get_parse_result().has_anonymous_block())) { - if (trans_state_.is_hold_start_trans_ || ObMysqlTransact::is_in_trans(trans_state_)) { + if (trans_state_.is_hold_xa_start_ + || trans_state_.is_hold_start_trans_ + || ObMysqlTransact::is_in_trans(trans_state_)) { set_server_trx_timeout(); } else { cancel_server_query_timeout(); @@ -7100,6 +8507,25 @@ int ObMysqlSM::setup_server_response_read() cmd_size_stats_.server_response_bytes_ = 0; milestones_.server_.server_read_end_ = 0; + LOG_DEBUG("setup server response read begin."); + + // full link trace + if (enable_record_full_link_trace_info()) { + SET_TRACE_BUFFER(flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + + trace::ObSpanCtx *server_response_read_ctx = FLT_BEGIN_SPAN(ob_proxy_server_response_read); + if (OB_NOT_NULL(server_response_read_ctx)) { + flt_.trace_log_info_.server_response_read_ctx_ = server_response_read_ctx; + LOG_DEBUG("begin span ob_proxy_server_response_read", K(server_response_read_ctx->span_id_)); + } + + trace::ObSpanCtx *server_process_req_ctx = FLT_BEGIN_SPAN(ob_proxy_server_process_req); + if (OB_NOT_NULL(server_process_req_ctx)) { + flt_.trace_log_info_.server_process_req_ctx_ = server_process_req_ctx; + LOG_DEBUG("begin span ob_proxy_server_process_req", K(server_process_req_ctx->span_id_)); + } + } + // The tunnel from observer to client is now setup. Ready to read the response if (OB_UNLIKELY(NULL != trans_state_.cache_block_)) { // use the cached block to read server response @@ -7155,13 +8581,9 @@ void ObMysqlSM::setup_error_transfer() "sql_cmd", get_mysql_cmd_str(trans_state_.trans_info_.sql_cmd_), "sql", trans_state_.trans_info_.get_print_sql()); } else { - if (OB_MYSQL_COM_LOGIN == trans_state_.trans_info_.sql_cmd_) { - if (OB_ISNULL(client_session_)) { - LOG_DEBUG("OB_MYSQL_COM_LOGIN close, should close"); - client_session_->can_server_session_release_ = false; - } + if (OB_NOT_NULL(client_session_)) { + client_session_->can_server_session_release_ = false; } - client_session_->can_server_session_release_ = false; LOG_WARN("[setup_error_transfer] Now closing connection", K_(sm_id), "request_cmd", get_mysql_cmd_str(request_cmd), "sql_cmd", get_mysql_cmd_str(trans_state_.trans_info_.sql_cmd_), @@ -7231,7 +8653,9 @@ int ObMysqlSM::setup_internal_transfer(MysqlSMHandler handler_arg) // if the internal request is not the first request and not proxysys, // it means that it is in trans (or hold trans), in this case we do NOT change the trans_state_ if (trans_state_.is_trans_first_request_) { - if (trans_state_.is_auth_request_ || trans_state_.is_hold_start_trans_) { + if (trans_state_.is_auth_request_ + || trans_state_.is_hold_start_trans_ + || trans_state_.is_hold_xa_start_) { trans_state_.current_.state_ = ObMysqlTransact::CMD_COMPLETE; } else { // proxysys && !OB_MYSQL_COM_LOGIN &&!OB_MYSQL_COM_HANDSHAKE will also enter here @@ -7336,13 +8760,18 @@ int ObMysqlSM::setup_server_transfer() ObMysqlResp &server_response = trans_state_.trans_info_.server_response_; ObIMysqlRespAnalyzer *analyzer = NULL; bool is_resultset = server_response.get_analyze_result().is_resultset_resp(); - if (OB_UNLIKELY((PROTOCOL_CHECKSUM == use_compression_protocol()) + if (OB_UNLIKELY((ObProxyProtocol::PROTOCOL_CHECKSUM == get_server_session_protocol()) && (NULL != client_session_) // inner sql's compressed response has tranfer to normal mysql packet && (!client_session_->is_proxy_mysql_client_))) { if (is_resultset) { LOG_ERROR("compress protocol's never reach here", K(is_resultset)); } + } else if (get_global_proxy_config().enable_binlog_service + && (OB_MYSQL_COM_REGISTER_SLAVE == trans_state_.trans_info_.sql_cmd_ + || OB_MYSQL_COM_BINLOG_DUMP == trans_state_.trans_info_.sql_cmd_ + || OB_MYSQL_COM_BINLOG_DUMP_GTID == trans_state_.trans_info_.sql_cmd_)) { + analyzer = &analyzer_; } else { analyzer = is_resultset ? &analyzer_ : NULL; } @@ -7378,6 +8807,13 @@ int ObMysqlSM::setup_cmd_complete() reinterpret_cast(client_session_->get_last_bound_server_session()), K_(sm_id), K(ret)); } else { + ObMysqlTransact::record_trans_state(trans_state_, ObMysqlTransact::is_in_trans(trans_state_)); + set_detect_server_info(trans_state_.server_info_.addr_, -1, ObTimeUtility::current_time()); + if (OB_UNLIKELY(add_detect_server_cnt_)) { + LOG_ERROR("setup_cmd_complete, add_detect_server_cnt_ should be false"); + add_detect_server_cnt_ = false; + // abort(); + } tunnel_.reset(); client_entry_->in_tunnel_ = false; api_.reset(); @@ -7387,7 +8823,7 @@ int ObMysqlSM::setup_cmd_complete() if (client_session_->is_already_send_trace_info()) { client_session_->set_need_send_trace_info(false); } - client_session_->set_first_handle_close_request(true); + client_session_->set_first_handle_request(true); client_session_->set_in_trans_for_close_request(false); client_session_->set_sharding_select_log_plan(NULL); client_session_->set_need_return_last_bound_ss(false); @@ -7431,30 +8867,78 @@ int ObMysqlSM::setup_cmd_complete() if (OB_UNLIKELY(get_global_performance_params().enable_trace_)) { update_cmd_stats(); milestones_.cmd_reset(); - } + } LOG_DEBUG("still in transaction, wait next request", K_(sm_id)); } - cmd_size_stats_.reset(); - if (OB_UNLIKELY(get_global_performance_params().enable_trace_)) { - cmd_time_stats_.reset(); - } - trans_state_.reset(); - // reset ps info - if (NULL != server_session_) { - server_session_->get_session_info().reset_server_ps_id(); - } - if (NULL != client_session_) { - client_session_->get_session_info().reset_recv_client_ps_id(); - client_session_->get_session_info().reset_client_ps_id(); - client_session_->get_session_info().reset_ps_entry(); - client_session_->get_session_info().reset_client_cursor_id(); + + // end client response write span after cmd complete + if (enable_record_full_link_trace_info()) { + trace::ObSpanCtx *ctx = flt_.trace_log_info_.client_response_write_ctx_; + if (OB_NOT_NULL(ctx)) { + LOG_DEBUG("end span ob_proxy_client_response_write", K(ctx->span_id_)); + SET_TRACE_BUFFER(flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + FLT_END_SPAN(ctx); + flt_.trace_log_info_.client_response_write_ctx_ = NULL; + } + } + + // consume the ob20 tail crc(4) in client buf reader while analyzed all the mysql packet in ob20 payload + ObClientSessionInfo &client_session_info = get_client_session()->get_session_info(); + ObProxyProtocol client_proto = get_client_session_protocol(); + bool ob20_req_received_done = client_session_info.ob20_request_.ob20_request_received_done_; + int64_t ob20_req_remain_payload_len = client_session_info.ob20_request_.remain_payload_len_; + if (client_proto == ObProxyProtocol::PROTOCOL_OB20 + && ob20_req_received_done + && ob20_req_remain_payload_len == 0) { + client_session_info.ob20_request_.reset(); + int64_t read_avail = client_buffer_reader_->read_avail(); + LOG_DEBUG("before handle tail crc in setup cmd complete", K(read_avail)); + if (OB_LIKELY(read_avail >= OB20_PROTOCOL_TAILER_LENGTH)) { + if (OB_FAIL(client_buffer_reader_->consume(OB20_PROTOCOL_TAILER_LENGTH))) { + LOG_WARN("fail to consume the last crc buffer in client request buffer", K(ret)); + } + } else { + // nothing + // cause buffer could be consumed all before, eg: handle internal request + } } - // wait new client request - if (OB_FAIL(setup_client_request_read())) { - LOG_WARN("failed to setup_client_request_read", K_(sm_id), K(ret)); + // it's necessary to end full link trace resource after trans/resp finished + if (OB_SUCC(ret)) { + if (OB_FAIL(handle_resp_for_end_flt_trace(ObMysqlTransact::TRANSACTION_COMPLETE + == trans_state_.current_.state_))) { + LOG_WARN("fail to handle resp for end flt trace", K(ret)); + } else { + cmd_size_stats_.reset(); + if (OB_UNLIKELY(get_global_performance_params().enable_trace_)) { + cmd_time_stats_.reset(); + } + if (ObMysqlTransact::is_in_trans(trans_state_) && client_session_->is_trans_internal_routing()) { + trans_state_.server_info_.reset(); + trans_state_.pll_info_.reset(); + trans_state_.current_.attempts_ = 1; + trans_state_.reset_congestion_entry(); + } + trans_state_.reset(); + // reset ps info + if (NULL != server_session_) { + server_session_->get_session_info().reset_server_ps_id(); + } + if (NULL != client_session_) { + client_session_->get_session_info().reset_recv_client_ps_id(); + client_session_->get_session_info().reset_client_ps_id(); + client_session_->get_session_info().reset_ps_entry(); + client_session_->get_session_info().reset_client_cursor_id(); + } + + // wait new client request + if (OB_FAIL(setup_client_request_read())) { + LOG_WARN("failed to setup_client_request_read", K_(sm_id), K(ret)); + } + } } } + return ret; } @@ -7471,14 +8955,14 @@ bool ObMysqlSM::need_close_last_used_ss() if (OB_LIKELY(NULL != client_session_) && NULL != (last_ss = client_session_->get_server_session()) && client_session_->get_session_info().is_read_consistency_set() - && client_session_->dummy_ldc_.is_readonly_zone_exist()) { + && client_session_->dummy_ldc_.is_readonly_zone_exist() + && !ObMysqlTransact::is_in_trans(trans_state_)) { common::ObAddr tmp_addr; - (void)tmp_addr.set_ipv4_addr(last_ss->server_ip_.get_ip4_host_order(), static_cast(last_ss->server_ip_.get_port_host_order())); + (void)tmp_addr.set_sockaddr(last_ss->server_ip_.sa_); const bool is_last_route_readonly_zone = client_session_->dummy_ldc_.is_readonly_zone(tmp_addr); const bool is_weak_read = (common::WEAK == static_cast(client_session_->get_session_info().get_read_consistency())); common::ObAddr current_addr; - (void)current_addr.set_ipv4_addr(trans_state_.server_info_.addr_.get_ip4_host_order(), - static_cast(trans_state_.server_info_.addr_.get_port_host_order())); + (void)current_addr.set_sockaddr(trans_state_.server_info_.addr_.sa_); const bool is_current_route_readonly_zone = client_session_->dummy_ldc_.is_readonly_zone(current_addr); // if readonly zone exist, should choose readonly zone when weak read and close connection which connect to readwrite zone if (is_last_route_readonly_zone != is_current_route_readonly_zone) { @@ -7494,7 +8978,9 @@ bool ObMysqlSM::need_close_last_used_ss() bool ObMysqlSM::can_server_session_release() { bool result = false; - bool is_in_trans = (trans_state_.is_hold_start_trans_ || ObMysqlTransact::is_in_trans(trans_state_)); + bool is_in_trans = (trans_state_.is_hold_start_trans_ + || trans_state_.is_hold_xa_start_ + || ObMysqlTransact::is_in_trans(trans_state_)); bool is_allowed_state_ = (ObMysqlTransact::STATE_UNDEFINED == trans_state_.current_.state_ || ObMysqlTransact::TRANSACTION_COMPLETE == trans_state_.current_.state_); // here should handle some case before release @@ -7715,7 +9201,8 @@ inline void ObMysqlSM::update_congestion_entry(const int event) int64_t client_connect_timeout = 0; if ((VC_EVENT_EOS == event || VC_EVENT_INACTIVITY_TIMEOUT == event - || VC_EVENT_ACTIVE_TIMEOUT == event) + || VC_EVENT_ACTIVE_TIMEOUT == event + || VC_EVENT_DETECT_SERVER_DEAD) && ObMysqlTransact::SM_ACTION_OBSERVER_OPEN == trans_state_.next_action_ && 0 == milestones_.server_connect_end_ && OB_LIKELY(NULL != pending_action_) @@ -7868,10 +9355,10 @@ inline void ObMysqlSM::get_monitor_error_info(int32_t &error_code, ObString &err "%.*s,%.*s:%.*s:%.*s,%s," \ "%.*s,%.*s,%s,%s,%s,%s,%.*s," \ "%ldus,%ldus,%dus,%ldus," \ - TRACE_ID_FORMAT ",%s,%s," \ + TRACE_ID_FORMAT ",%.*s,%s," \ "%.*s,%s,%s" -#define MONITOR_ERROR_LOG_FORMAT MONITOR_LOG_FORMAT ",%.*s" +#define MONITOR_ERROR_LOG_FORMAT MONITOR_LOG_FORMAT ",%.*s,%.*s" #define MONITOR_LOG_PARAM \ logic_tenant_name.length(), logic_tenant_name.ptr(), \ @@ -7897,12 +9384,13 @@ inline void ObMysqlSM::get_monitor_error_info(int32_t &error_code, ObString &err 0, \ hrtime_to_usec(cmd_time_stats_.server_process_request_time_), \ \ - trace_id_0, trace_id_1, "", "", \ - shard_name.length(), shard_name.ptr(), \ + trace_id_0, trace_id_1, server_trace_id.length(), server_trace_id.ptr(), \ + "", shard_name.length(), shard_name.ptr(), \ is_enc_beyond_trust ? "1" : "0", \ ip_port_buff -#define MONITOR_ERROR_LOG_PARAM MONITOR_LOG_PARAM, error_msg.length(), error_msg.ptr() +#define MONITOR_ERROR_LOG_PARAM MONITOR_LOG_PARAM, error_msg.length(), error_msg.ptr(),\ + server_trace_id.length(), server_trace_id.ptr() inline void ObMysqlSM::update_monitor_log() @@ -8029,6 +9517,7 @@ inline void ObMysqlSM::update_monitor_log() char ip_buff_temp[INET6_ADDRSTRLEN] = "\0"; snprintf(ip_port_buff, INET6_ADDRPORTSTRLEN, "%s:%u", ops_ip_ntop(server_addr, ip_buff_temp, INET6_ADDRSTRLEN), ops_ip_port_host_order(server_addr)); } + const ObString &server_trace_id = get_server_trace_id(); if ((slow_time_threshold > 0 && slow_time_threshold < cmd_time_stats_.request_total_time_) || is_error_resp) { @@ -8043,6 +9532,7 @@ inline void ObMysqlSM::update_monitor_log() } if (is_error_resp) { + const ObString &server_trace_id = get_server_trace_id(); _OBPROXY_ERROR_LOG(WARN, MONITOR_ERROR_LOG_FORMAT, MONITOR_ERROR_LOG_PARAM); } } @@ -8088,7 +9578,7 @@ inline void ObMysqlSM::update_monitor_log() monitor_info.request_total_time_ = cmd_time_stats_.request_total_time_; monitor_info.server_process_request_time_ = cmd_time_stats_.server_process_request_time_; monitor_info.prepare_send_request_to_server_time_ = cmd_time_stats_.prepare_send_request_to_server_time_; - self_ethread().thread_prometheus_->set_sql_monitor_info(tenant_name, cluster_name, monitor_info); + self_ethread().thread_prometheus_->set_sql_monitor_info(tenant_name, cluster_name, monitor_info); } else { if (!client_session_->is_need_convert_vip_to_tname()) { NET_PROMETHEUS_STAT(logic_tenant_name, logic_database_name, @@ -8193,23 +9683,21 @@ inline void ObMysqlSM::update_cmd_stats() trans_stats_.send_all_session_vars_time_ += cmd_time_stats_.server_send_all_session_variable_time_; trans_stats_.send_use_database_time_ += cmd_time_stats_.server_send_use_database_time_; trans_stats_.send_session_vars_time_ += cmd_time_stats_.server_send_session_variable_time_; - trans_stats_.send_last_insert_id_time_ += cmd_time_stats_.server_send_last_insert_id_time_; + trans_stats_.send_session_user_vars_time_ += cmd_time_stats_.server_send_session_user_variable_time_; trans_stats_.send_start_trans_time_ += cmd_time_stats_.server_send_start_trans_time_; + trans_stats_.send_xa_start_time_ += cmd_time_stats_.server_send_xa_start_time_; trans_stats_.build_server_request_time_ += cmd_time_stats_.build_server_request_time_; int64_t slow_time_threshold = trans_state_.mysql_config_params_->slow_query_time_threshold_; int64_t proxy_process_time_threshold = trans_state_.mysql_config_params_->slow_proxy_process_time_threshold_; const char *SLOW_QUERY = "Slow Query: "; const char *TRACE_STAT = "Trace Stat: "; - const char *xf_head = NULL; const char *log_head = NULL; bool print_info_log = false; if (slow_time_threshold > 0 && slow_time_threshold < cmd_time_stats_.request_total_time_) { - xf_head = XFH_SQL_SLOW_QUERY; log_head = SLOW_QUERY; } else if (proxy_process_time_threshold > 0 && proxy_process_time_threshold < cmd_time_stats_.prepare_send_request_to_server_time_) { - xf_head = XFH_SQL_SLOW_QUERY; log_head = SLOW_QUERY; print_info_log = true; } else if (need_print_trace_stat()) { @@ -8223,15 +9711,19 @@ inline void ObMysqlSM::update_cmd_stats() uint32_t cs_id = 0; uint32_t server_sessid = 0; int64_t ss_id = 0; - ObProxyProtocol ob_proxy_protocol = use_compression_protocol(); + ObProxyProtocol ob_proxy_protocol = get_server_session_protocol(); ObString user_name; ObString tenant_name; ObString cluster_name; ObString logic_tenant_name; ObString logic_database_name; + ObString trans_internal_routing_state; + bool is_in_trans = ObMysqlTransact::is_in_trans(trans_state_); + bool is_trans_internal_routing = false; if (NULL != client_session_) { proxy_sessid = client_session_->get_proxy_sessid(); cs_id = client_session_->get_cs_id(); + is_trans_internal_routing = client_session_->is_trans_internal_routing(); const ObClientSessionInfo &cs_info = client_session_->get_session_info(); cs_info.get_user_name(user_name); cs_info.get_tenant_name(tenant_name); @@ -8239,6 +9731,7 @@ inline void ObMysqlSM::update_cmd_stats() cs_info.get_logic_database_name(logic_database_name); cs_info.get_logic_tenant_name(logic_tenant_name); } + trans_internal_routing_state = is_in_trans ? (is_trans_internal_routing ? "trans internal routing" : "trans not internal routing") : "not in trans"; get_server_session_ids(server_sessid, ss_id); if (print_info_log) { @@ -8262,7 +9755,8 @@ inline void ObMysqlSM::update_cmd_stats() K_(sm_id), K_(cmd_size_stats), K_(cmd_time_stats), - "sql", trans_state_.trans_info_.get_print_sql()); + "sql", trans_state_.trans_info_.get_print_sql(), + K(trans_internal_routing_state)); } else { LOG_WARN(log_head, "client_ip", trans_state_.client_info_.addr_, @@ -8283,24 +9777,8 @@ inline void ObMysqlSM::update_cmd_stats() K_(sm_id), K_(cmd_size_stats), K_(cmd_time_stats), - "sql", trans_state_.trans_info_.get_print_sql()); - } - - if (NULL != xf_head) { - OBPROXY_XF_LOG(INFO, xf_head, - "client_ip", trans_state_.client_info_.addr_, - "server_ip", trans_state_.server_info_.addr_, - "obproxy_client_port", trans_state_.server_info_.obproxy_addr_, - "route_type", get_route_type_string(trans_state_.pll_info_.route_.cur_chosen_route_type_), - K(user_name), - K(tenant_name), - K(cluster_name), - K(logic_database_name), - K(logic_tenant_name), - K(ob_proxy_protocol), - "sql", trans_state_.trans_info_.get_print_sql(), - K_(cmd_size_stats), - K_(cmd_time_stats)); + "sql", trans_state_.trans_info_.get_print_sql(), + K(trans_internal_routing_state)); } } @@ -8401,7 +9879,7 @@ inline void ObMysqlSM::update_stats() && trans_state_.mysql_config_params_->slow_transaction_time_threshold_ < trans_stats_.trans_time_) { uint32_t cs_id = (OB_ISNULL(client_session_) ? 0 : client_session_->get_cs_id()); uint64_t proxy_sessid = (OB_ISNULL(client_session_) ? 0 : client_session_->get_proxy_sessid()); - ObProxyProtocol ob_proxy_protocol = use_compression_protocol(); + ObProxyProtocol ob_proxy_protocol = get_server_session_protocol(); int64_t ss_id = 0; uint32_t server_sessid = 0; @@ -8551,6 +10029,10 @@ inline void ObMysqlSM::set_next_state() do_partition_location_lookup(); break; + case ObMysqlTransact::SM_ACTION_BINLOG_LOCATION_LOOKUP: + do_binlog_location_lookup(); + break; + case ObMysqlTransact::SM_ACTION_CONGESTION_CONTROL_LOOKUP: do_congestion_control_lookup(); break; @@ -8609,6 +10091,44 @@ inline void ObMysqlSM::set_next_state() } } +int ObMysqlSM::state_binlog_location_lookup(int event, void *data) +{ + int ret = OB_SUCCESS; + STATE_ENTER(ObMysqlSM::state_binlog_location_lookup, event); + pending_action_ = NULL; + if (OB_UNLIKELY(get_global_performance_params().enable_trace_)) { + milestones_.bl_lookup_end_ = get_based_hrtime(); + cmd_time_stats_.bl_lookup_time_ += milestone_diff(milestones_.bl_lookup_begin_, milestones_.bl_lookup_end_); + milestones_.bl_process_begin_ = milestones_.bl_lookup_end_; + } + + if (OB_UNLIKELY(TABLE_ENTRY_EVENT_LOOKUP_DONE != event) || OB_ISNULL(data)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("unexpected event type, it should not happen", K(event), K(data), K(ret)); + } else { + ObMysqlRouteResult *result = reinterpret_cast(data); + if (OB_UNLIKELY(NULL == result || NULL == result->table_entry_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get binlog entry failed", K(result), K(ret)); + } else { + trans_state_.pll_info_.set_route_info(*result); + trans_state_.pll_info_.lookup_success_ = true; + call_transact_and_set_next_state(NULL); + } + } + + if (OB_FAIL(ret)) { + trans_state_.inner_errcode_ = ret; + // failed, disconnect + trans_state_.pll_info_.lookup_success_ = false; + trans_state_.current_.state_ = ObMysqlTransact::INTERNAL_ERROR; + // call ObMysqlTransact::handle_bl_lookup() to handle fail / success + call_transact_and_set_next_state(NULL); + } + + return EVENT_DONE; +} + } // end of namespace proxy } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/proxy/mysql/ob_mysql_sm.h b/src/obproxy/proxy/mysql/ob_mysql_sm.h index e30031e67c7edfc04952f7003469a973f22a7721..ec159024a91f7373d9b37265fd7a1479c8c1edc2 100644 --- a/src/obproxy/proxy/mysql/ob_mysql_sm.h +++ b/src/obproxy/proxy/mysql/ob_mysql_sm.h @@ -33,6 +33,7 @@ #include "utils/ob_proxy_lib.h" #include "utils/ob_proxy_monitor_utils.h" +#include "utils/ob_target_db_server.h" #include "iocore/eventsystem/ob_event_system.h" #include "proxy/mysqllib/ob_mysql_request_analyzer.h" #include "proxy/mysqllib/ob_mysql_compress_analyzer.h" @@ -47,6 +48,7 @@ #include "proxy/shard/obproxy_shard_ddl_cont.h" #include "obutils/ob_tenant_stat_struct.h" #include "engine/ob_proxy_operator_result.h" +#include "lib/utility/ob_2_0_full_link_trace_info.h" namespace oceanbase { @@ -156,29 +158,34 @@ public: int process_shard_ddl_result(ObShardDDLStatus *ddl_status); int setup_handle_execute_plan(); int state_handle_execute_plan(int event, void *data); - int process_executor_result(engine::ObProxyResultResp *result_resp); - int build_executor_resp(event::ObMIOBuffer *write_buf, uint8_t &seq, engine::ObProxyResultResp *result_resp); + int process_executor_result(event::ObIOBufferReader *resp_reader); int handle_shard_request(bool &need_response_for_stmt, bool &need_wait_callback); int check_user_identity(const ObString &user_name, const ObString &tenant_name, const ObString &cluster_name); int save_user_login_info(ObClientSessionInfo &session_info, ObHSRResult &hsr_result); - void analyze_mysql_request(ObMysqlAnalyzeStatus &status); + void analyze_mysql_request(ObMysqlAnalyzeStatus &status, const bool is_mysql_req_in_ob20 = false); int analyze_login_request(ObRequestAnalyzeCtx &ctx, ObMysqlAnalyzeStatus &status); + int analyze_change_user_request(); int analyze_ps_prepare_request(); int do_analyze_ps_prepare_request(const ObString &ps_sql); int analyze_ps_execute_request(bool is_large_request = false); int do_analyze_ps_execute_request(ObPsIdEntry *entry, bool is_large_request); int do_analyze_ps_execute_request_with_flag(ObPsIdEntry *entry); int do_analyze_ps_execute_request_without_flag(ObPsIdEntry *entry); - int analyze_text_ps_prepare_request(); + int analyze_text_ps_prepare_request(const ObRequestAnalyzeCtx &ctx); + int do_parse_text_ps_prepare_sql(char*& text_ps_prepare_buf, int64_t& text_ps_prepare_buf_len, + ObString& text_ps_sql, const ObRequestAnalyzeCtx& ctx); + int do_analyze_text_ps_prepare_request(const ObString& text_ps_sql); int analyze_text_ps_execute_request(); + int analyze_text_ps_drop_request(); int analyze_fetch_request(); - int analyze_close_request(); + int analyze_close_reset_request(); int analyze_ps_prepare_execute_request(); bool need_setup_client_transfer(); bool check_connection_throttle(); bool can_pass_white_list(); + int analyze_capacity_flag_from_client(); bool check_vt_connection_throttle(); bool is_partition_table_route_supported(); bool is_pl_route_supported(); @@ -223,7 +230,8 @@ public: void release_server_session(); bool need_close_last_used_ss(); - ObProxyProtocol use_compression_protocol() const; + ObProxyProtocol get_server_session_protocol() const; + ObProxyProtocol get_client_session_protocol() const; bool is_checksum_on() const; bool is_extra_ok_packet_for_stats_enabled() const; uint8_t get_request_seq(); @@ -243,6 +251,7 @@ public: const bool has_cluster_username, const bool is_cloud_user) const; inline void set_skip_plugin(const bool bvalue) { skip_plugin_ = bvalue; } + void set_detect_server_info(net::ObIpEndpoint target_addr, int cnt, int64_t time); public: static const int64_t OP_LOCAL_NUM = 32; static const int64_t MAX_SCATTER_LEN; @@ -279,6 +288,10 @@ public: ObMysqlCompressOB20Analyzer compress_ob20_analyzer_; ObMysqlRequestAnalyzer request_analyzer_; +public: + common::FLTObjManage flt_; // ob20 full link trace obj + char flt_trace_buffer_[MAX_TRACE_LOG_SIZE]; // buffer for full link trace with each sm + public: static uint32_t get_next_sm_id(); void remove_client_entry(); @@ -295,6 +308,7 @@ public: int state_watch_for_client_abort(int event, void *data); int state_server_addr_lookup(int event, void *data); int state_partition_location_lookup(int event, void *data); + int state_binlog_location_lookup(int event, void *data); int state_add_to_list(int event, void *data); int state_remove_from_list(int event, void *data); @@ -325,6 +339,7 @@ public: int tunnel_handler_plugin_client(int event, ObMysqlTunnelConsumer &c); void do_partition_location_lookup(); + void do_binlog_location_lookup(); void do_congestion_control_lookup(); void do_server_addr_lookup(); int do_observer_open(); @@ -332,24 +347,14 @@ public: int do_normal_internal_observer_open(ObMysqlServerSession *&selected_session); int do_internal_observer_open(); void do_internal_request(); - int do_internal_request_for_sharding_init_db(event::ObMIOBuffer *buf, - ObProxyMysqlRequest &client_request, - ObClientSessionInfo &client_info); - int do_internal_request_for_sharding_show_db_version(event::ObMIOBuffer *buf, - ObProxyMysqlRequest &client_request, - ObClientSessionInfo &client_info); - int do_internal_request_for_sharding_show_db(event::ObMIOBuffer *buf, - ObProxyMysqlRequest &client_request, - ObClientSessionInfo &client_info); - int do_internal_request_for_sharding_show_table(event::ObMIOBuffer *buf, - ObProxyMysqlRequest &client_request, - ObClientSessionInfo &client_info); - int do_internal_request_for_sharding_show_topology(event::ObMIOBuffer *buf, - ObProxyMysqlRequest &client_request, - ObClientSessionInfo &client_info); - int do_internal_request_for_sharding_select_db(event::ObMIOBuffer *buf, - ObProxyMysqlRequest &client_request, - ObClientSessionInfo &client_info); + int do_internal_request_for_sharding_init_db(event::ObMIOBuffer *buf); + int do_internal_request_for_sharding_show_db_version(event::ObMIOBuffer *buf); + int do_internal_request_for_sharding_show_db(event::ObMIOBuffer *buf); + int do_internal_request_for_sharding_show_table(event::ObMIOBuffer *buf); + int do_internal_request_for_sharding_show_table_status(event::ObMIOBuffer *buf); + int do_internal_request_for_sharding_show_elastic_id(event::ObMIOBuffer *buf); + int do_internal_request_for_sharding_show_topology(event::ObMIOBuffer *buf); + int do_internal_request_for_sharding_select_db(event::ObMIOBuffer *buf); int connect_observer(); int setup_client_transfer(ObMysqlVCType to_vc_type); void handle_api_return(); @@ -370,7 +375,7 @@ public: void set_next_state(); void call_transact_and_set_next_state(TransactEntryFunc f); - int init_request_content(ObRequestAnalyzeCtx &ctx); + int init_request_content(ObRequestAnalyzeCtx &ctx, const bool is_mysql_req_in_ob20); int server_transfer_init(event::ObMIOBuffer *buf, int64_t &nbytes); void setup_set_cached_variables(); @@ -390,6 +395,9 @@ public: const bool need_receive_completed, int64_t &first_pkt_len); + int handle_first_request_packet(ObMysqlAnalyzeStatus &status, int64_t &first_packet_len); + int handle_first_compress_request_packet(ObMysqlAnalyzeStatus &state, int64_t &first_packet_len); + void check_update_checksum_switch(const bool is_compressed_payload); void clear_entries(); @@ -425,6 +433,18 @@ public: int handle_limit(bool &need_direct_response_for_client); int handle_ldg(bool &need_direct_response_for_client); + void save_response_flt_result_to_sm(common::FLTObjManage &flt); + void save_request_flt_result_to_sm(common::FLTObjManage &flt); + bool enable_record_full_link_trace_info(); + bool is_proxy_init_trace_log_info(); + int handle_resp_for_end_proxy_root_span(trace::UUID &trace_id, bool is_in_trans); + int handle_req_for_begin_proxy_root_span(); + void handle_req_to_generate_root_span_from_client(); + int handle_req_to_generate_root_span_by_proxy(); + int handle_for_end_proxy_trace(trace::UUID &trace_id); + int handle_resp_for_end_flt_trace(bool is_trans_completed); + void set_enable_ob_protocol_v2(const bool enable_ob_protocol_v2) { enable_ob_protocol_v2_ = enable_ob_protocol_v2; } + bool is_enable_ob_protocol_v2() const { return enable_ob_protocol_v2_; } private: static const int64_t HISTORY_SIZE = 32; @@ -463,11 +483,31 @@ private: int32_t retry_acquire_server_session_count_; int64_t start_acquire_server_session_time_; bool skip_plugin_; + bool add_detect_server_cnt_; +public: + // Multi-level configuration items: Because the most fine-grained configuration items + // can take effect at the VIP level, each SM may need to be different + char proxy_route_policy_[OB_MAX_CONFIG_VALUE_LEN]; + char proxy_idc_name_[OB_MAX_CONFIG_VALUE_LEN]; + bool enable_cloud_full_username_; + bool enable_client_ssl_; + bool enable_server_ssl_; + bool enable_read_write_split_; + bool enable_transaction_split_; + bool enable_ob_protocol_v2_; // limit the scope of changing enable_protocol_v2_ to client session level + uint64_t config_version_; + ObTargetDbServer *target_db_server_; +private: // private functions int handle_server_request_send_long_data(); int do_analyze_ps_execute_request_with_remain_value(event::ObMIOBuffer *writer, int64_t read_avail, int64_t param_type_pos); + int handle_compress_request_analyze_done(ObMysqlCompressedOB20AnalyzeResult &ob20_result, int64_t &first_packet_len, + ObMysqlAnalyzeStatus &status); + void analyze_status_after_analyze_mysql_in_ob20_payload(ObMysqlAnalyzeStatus &status, + ObClientSessionInfo &client_session_info); + int analyze_ob20_remain_after_analyze_mysql_request_done(ObClientSessionInfo &client_session_info); }; inline ObMysqlSM *ObMysqlSM::allocate() @@ -559,16 +599,16 @@ inline void ObMysqlSM::set_internal_cmd_timeout(const ObHRTime timeout) inline int64_t ObMysqlSM::get_query_timeout() { int64_t timeout = HRTIME_NSECONDS(trans_state_.mysql_config_params_->observer_query_timeout_delta_); - if (OB_LIKELY(NULL != client_session_) && OB_LIKELY(NULL != server_session_)) { - dbconfig::ObShardProp *shard_prop = client_session_->get_session_info().get_shard_prop(); - if (OB_NOT_NULL(shard_prop)) { - timeout = HRTIME_MSECONDS(shard_prop->get_socket_timeout()); + if (OB_LIKELY(NULL != client_session_)) { + int64_t hint_query_timeout = trans_state_.trans_info_.client_request_.get_parse_result().get_hint_query_timeout(); + // if the request contains query_timeout in hint, we use it + if (hint_query_timeout > 0) { + // the query timeout in hint is in microseconds(us), so convert it into nanoseconds + timeout += HRTIME_USECONDS(hint_query_timeout); } else { - int64_t hint_query_timeout = trans_state_.trans_info_.client_request_.get_parse_result().get_hint_query_timeout(); - // if the request contains query_timeout in hint, we use it - if (hint_query_timeout > 0) { - // the query timeout in hint is in microseconds(us), so convert it into nanoseconds - timeout += HRTIME_USECONDS(hint_query_timeout); + dbconfig::ObShardProp *shard_prop = client_session_->get_session_info().get_shard_prop(); + if (OB_NOT_NULL(shard_prop)) { + timeout = HRTIME_MSECONDS(shard_prop->get_socket_timeout()); } else { // we do parse in trans now, so we can use query_timeout in anycase timeout += client_session_->get_session_info().get_query_timeout(); @@ -633,6 +673,9 @@ inline void ObMysqlSM::clear_entries() if (OB_SUCCESS != vc_table_.cleanup_entry(client_entry_)) { PROXY_LOG(WARN, "vc_table failed to cleanup client entry", K_(client_entry), K_(sm_id)); } + if (OB_LIKELY(client_entry_->vc_ == NULL)) { + client_session_ = NULL; // vc is equivalent to session + } client_entry_ = NULL; } @@ -640,6 +683,9 @@ inline void ObMysqlSM::clear_entries() if (OB_SUCCESS != vc_table_.cleanup_entry(server_entry_)) { PROXY_LOG(WARN, "vc_table failed to cleanup client entry", K_(server_entry), K_(sm_id)); } + if (OB_LIKELY(server_entry_->vc_ == NULL)) { + server_session_ = NULL; // vc is equivalent to session + } server_entry_ = NULL; } } @@ -678,11 +724,11 @@ inline ObHRTime ObMysqlSM::get_based_hrtime() return time; } -inline bool ObMysqlSM::is_causal_order_read_enabled() -{ - return trans_state_.mysql_config_params_->enable_causal_order_read_ - && NULL != client_session_ - && client_session_->get_session_info().is_safe_read_weak_supported(); +inline bool ObMysqlSM::is_causal_order_read_enabled() +{ + return trans_state_.mysql_config_params_->enable_causal_order_read_ + && NULL != client_session_ + && client_session_->get_session_info().is_server_support_safe_read_weak(); } inline bool ObMysqlSM::need_print_trace_stat() const diff --git a/src/obproxy/proxy/mysql/ob_mysql_sm_time_stat.cpp b/src/obproxy/proxy/mysql/ob_mysql_sm_time_stat.cpp index f8bd548077839740f33e636878ba45a5a59cdd67..6efcbb0b6e853ca068284c261b634696cff438d7 100644 --- a/src/obproxy/proxy/mysql/ob_mysql_sm_time_stat.cpp +++ b/src/obproxy/proxy/mysql/ob_mysql_sm_time_stat.cpp @@ -37,6 +37,9 @@ int64_t ObCmdTimeStat::to_string(char *buf, const int64_t buf_len) const TO_STRING_TIME_US(pl_lookup_time_); TO_STRING_TIME_US(pl_process_time_); + TO_STRING_TIME_US(bl_lookup_time_); + TO_STRING_TIME_US(bl_process_time_); + #if OB_DETAILED_SLOW_QUERY TO_STRING_TIME_US(debug_assign_time_); TO_STRING_TIME_US(debug_consistency_time_); @@ -58,9 +61,10 @@ int64_t ObCmdTimeStat::to_string(char *buf, const int64_t buf_len) const TO_STRING_TIME_US(server_send_saved_login_time_); TO_STRING_TIME_US(server_send_use_database_time_); TO_STRING_TIME_US(server_send_session_variable_time_); + TO_STRING_TIME_US(server_send_session_user_variable_time_); TO_STRING_TIME_US(server_send_all_session_variable_time_); - TO_STRING_TIME_US(server_send_last_insert_id_time_); TO_STRING_TIME_US(server_send_start_trans_time_); + TO_STRING_TIME_US(server_send_xa_start_time_); TO_STRING_TIME_US(build_server_request_time_); TO_STRING_TIME_US(plugin_compress_request_time_); TO_STRING_TIME_US(prepare_send_request_to_server_time_); @@ -100,9 +104,10 @@ int64_t ObTransactionStat::to_string(char *buf, const int64_t buf_len) const TO_STRING_TIME_US(send_saved_login_time_); TO_STRING_TIME_US(send_use_database_time_); TO_STRING_TIME_US(send_session_vars_time_); + TO_STRING_TIME_US(send_session_user_vars_time_); TO_STRING_TIME_US(send_all_session_vars_time_); - TO_STRING_TIME_US(send_last_insert_id_time_); TO_STRING_TIME_US(send_start_trans_time_); + TO_STRING_TIME_US(send_xa_start_time_); TO_STRING_TIME_US(build_server_request_time_); TO_STRING_TIME_US(plugin_compress_request_time_); TO_STRING_TIME_US(prepare_send_request_to_server_time_); diff --git a/src/obproxy/proxy/mysql/ob_mysql_sm_time_stat.h b/src/obproxy/proxy/mysql/ob_mysql_sm_time_stat.h index 04b11120e6ea50220a9d821e7fc34a438a5ef751..45d19c9dda6902c1006c3a26c7188548e8759130 100644 --- a/src/obproxy/proxy/mysql/ob_mysql_sm_time_stat.h +++ b/src/obproxy/proxy/mysql/ob_mysql_sm_time_stat.h @@ -69,7 +69,8 @@ struct ObTransactionMilestones ObTransactionMilestones() : last_client_cmd_end_(0), server_connect_begin_(0), server_connect_end_(0), server_first_write_begin_(0), pl_lookup_begin_(0), pl_lookup_end_(0), - pl_process_begin_(0), pl_process_end_(0), congestion_control_begin_(0), + pl_process_begin_(0), pl_process_end_(0), bl_lookup_begin_(0), bl_lookup_end_(0), + bl_process_begin_(0), bl_process_end_(0), congestion_control_begin_(0), congestion_control_end_(0), congestion_process_begin_(0), congestion_process_end_(0), cluster_resource_create_begin_(0), cluster_resource_create_end_(0), trans_start_(0), trans_finish_(0), do_observer_open_begin_(0), do_observer_open_end_(0) @@ -111,6 +112,14 @@ struct ObTransactionMilestones ObHRTime pl_process_begin_; ObHRTime pl_process_end_; + // binlog location lookup + ObHRTime bl_lookup_begin_; + ObHRTime bl_lookup_end_; + + // binlog location process + ObHRTime bl_process_begin_; + ObHRTime bl_process_end_; + // congestion_control_lookup ObHRTime congestion_control_begin_; ObHRTime congestion_control_end_; @@ -154,6 +163,8 @@ struct ObCmdTimeStat ObHRTime cluster_resource_create_time_; ObHRTime pl_lookup_time_; ObHRTime pl_process_time_; + ObHRTime bl_lookup_time_; + ObHRTime bl_process_time_; #if OB_DETAILED_SLOW_QUERY ObHRTime debug_assign_time_; @@ -177,9 +188,10 @@ struct ObCmdTimeStat ObHRTime server_send_saved_login_time_; ObHRTime server_send_use_database_time_; ObHRTime server_send_session_variable_time_; + ObHRTime server_send_session_user_variable_time_; ObHRTime server_send_all_session_variable_time_; - ObHRTime server_send_last_insert_id_time_; ObHRTime server_send_start_trans_time_; + ObHRTime server_send_xa_start_time_; ObHRTime build_server_request_time_; ObHRTime plugin_compress_request_time_; @@ -241,9 +253,10 @@ struct ObTransactionStat ObHRTime send_saved_login_time_; ObHRTime send_use_database_time_; ObHRTime send_session_vars_time_; + ObHRTime send_session_user_vars_time_; ObHRTime send_all_session_vars_time_; - ObHRTime send_last_insert_id_time_; ObHRTime send_start_trans_time_; + ObHRTime send_xa_start_time_; ObHRTime build_server_request_time_; ObHRTime plugin_compress_request_time_; diff --git a/src/obproxy/proxy/mysql/ob_mysql_transact.cpp b/src/obproxy/proxy/mysql/ob_mysql_transact.cpp index 4a196d827e9e41538868883859203b25c8dbb416..c4d134bdd2de0d61849e2f1dd511a3091ffb096d 100644 --- a/src/obproxy/proxy/mysql/ob_mysql_transact.cpp +++ b/src/obproxy/proxy/mysql/ob_mysql_transact.cpp @@ -38,6 +38,8 @@ #include "lib/encrypt/ob_encrypted_helper.h" #include "proxy/shard/obproxy_shard_utils.h" #include "rpc/obmysql/packet/ompk_change_user.h" +#include "rpc/obmysql/packet/ompk_prepare_execute.h" +#include "omt/ob_proxy_config_table_processor.h" using namespace oceanbase::share; using namespace oceanbase::common; @@ -60,6 +62,62 @@ namespace proxy #define MYSQL_INCREMENT_TRANS_STAT(X) update_stat(s, X, 1); #define MYSQL_SUM_TIME_STAT(X, cost) update_stat(s, X, cost); +bool ObMysqlTransact::is_in_trans(ObTransState &s) +{ + // if a trans is commit, the state will be set to TRANSACTION_COMPLETE, + // so if current state is CMD_COMPLETE, it means that we have send a sql successfully and + // the trans has not commit, that is to say "in trans" + // so far, there are three cases NOT in trans: + // 1. handshake response (login packet) need pl lookup + // 2. the first sql of one transaction + // 3. the second sql of one transaction, if the first sql is 'begin' or 'start transaction' + + // s.current_.state_ may changed to CONNECTION_ALIVE on state_server_response_read, + // here add last_request_in_trans to correct transaction state + + bool is_in_trans = false; + if (!s.is_auth_request_ && !s.is_hold_start_trans_ && !s.is_hold_xa_start_) { + if (ObMysqlTransact::CMD_COMPLETE == s.current_.state_) { + is_in_trans = true; + } else if (ObMysqlTransact::TRANSACTION_COMPLETE != s.current_.state_ + && s.sm_->client_session_ != NULL + && s.sm_->client_session_->is_last_request_in_trans()) { + is_in_trans = true; + } + } + return is_in_trans; +} + +void ObMysqlTransact::record_trans_state(ObTransState &s, bool is_in_trans) +{ + ObMysqlClientSession *client_session = s.sm_->get_client_session(); + bool last_request_in_trans = client_session->is_last_request_in_trans(); + if (client_session->is_proxy_enable_trans_internal_routing()) { + // set distributed transaction route flag + bool server_trans_internal_routing = s.trans_info_.server_response_.get_analyze_result().is_server_trans_internal_routing(); + bool is_trans_internal_routing = ObMysqlTransact::handle_set_trans_internal_routing(s, server_trans_internal_routing); + + if (!last_request_in_trans && is_in_trans) { + client_session->set_trans_coordinator_ss_addr(s.server_info_.addr_.sa_); + LOG_DEBUG("start internal routing transaction", "coordinator addr", client_session->get_trans_coordinator_ss_addr()); + s.trace_log_.set_need_print(is_trans_internal_routing); + s.trace_log_.log_it("[trans_start]", + "proxy_sessid", client_session->get_proxy_sessid(), + "coordinator", s.server_info_.addr_, + "sql_cmd", s.trans_info_.sql_cmd_, + "stmt_type", s.trans_info_.client_request_.get_parse_result().get_stmt_type()); + } else if (last_request_in_trans && !is_in_trans) { + // close txn, refresh enable_transaction_internal_routing_ + LOG_DEBUG("internal routing transaction close", "coordinator addr", client_session->get_trans_coordinator_ss_addr()); + client_session->get_trans_coordinator_ss_addr().reset(); + } + + client_session->set_trans_internal_routing(is_trans_internal_routing); + LOG_DEBUG("set transaction internal routing flag", "internal routing state", is_trans_internal_routing); + } + client_session->set_last_request_in_trans(is_in_trans); +} + void ObMysqlTransact::handle_error_jump(ObTransState &s) { LOG_WARN("[ObMysqlTransact::handle_error_jump]"); @@ -126,6 +184,31 @@ bool ObMysqlTransact::ObTransState::is_for_update_sql(common::ObString src_sql) return bret; } +ObConsistencyLevel ObMysqlTransact::ObTransState::get_read_write_consistency_level(ObClientSessionInfo &session_info) +{ + ObConsistencyLevel ret_level = common::STRONG; + bool enable_weak_read = false; + if (ObMysqlTransact::is_in_trans(sm_->trans_state_) + || 0 == session_info.get_cached_variables().get_autocommit() + || is_hold_start_trans_ + || is_hold_xa_start_) { + if (ObMysqlTransact::is_in_trans(sm_->trans_state_) + || is_hold_start_trans_ + || is_hold_xa_start_) { + enable_weak_read = false; + } else { + enable_weak_read = sm_->enable_read_write_split_ && sm_->enable_transaction_split_; + } + } else { + enable_weak_read = sm_->enable_read_write_split_; + } + + if (enable_weak_read) { + ret_level = common::WEAK; + } + return ret_level; +} + ObConsistencyLevel ObMysqlTransact::ObTransState::get_trans_consistency_level( ObClientSessionInfo &cs_info) { @@ -147,17 +230,24 @@ ObConsistencyLevel ObMysqlTransact::ObTransState::get_trans_consistency_level( if (INVALID_CONSISTENCY != pll_info_.route_.consistency_level_) { ret_level = pll_info_.route_.consistency_level_; } else { - if (trans_info_.client_request_.get_parse_result().is_select_stmt()) { + if (trans_info_.client_request_.get_parse_result().is_select_stmt() || + trans_info_.client_request_.get_parse_result().is_text_ps_select_stmt()) { const ObConsistencyLevel sql_hint = trans_info_.client_request_.get_parse_result().get_hint_consistency_level(); const ObConsistencyLevel sys_var = static_cast(cs_info.get_read_consistency()); + const ObConsistencyLevel read_write_consistence_level = get_read_write_consistency_level(cs_info); if (common::STRONG == sql_hint || common::WEAK == sql_hint) { ret_level = sql_hint; } else { - if (common::STRONG == sys_var || common::WEAK == sys_var) { + if (common::WEAK == sys_var) { ret_level = sys_var; } else { - PROXY_LOG(DEBUG, "unsupport ob_read_consistency vars, maybe proxy is old, use strong read " + if (common::STRONG == read_write_consistence_level || common::WEAK == read_write_consistence_level) { + ret_level = read_write_consistence_level; + } + if (common::STRONG != sys_var) { + PROXY_LOG(DEBUG, "unsupport ob_read_consistency vars, maybe proxy is old, use strong read " "instead", "sys_var", get_consistency_level_str(sys_var)); + } } } if (common::WEAK == ret_level) { @@ -167,7 +257,7 @@ ObConsistencyLevel ObMysqlTransact::ObTransState::get_trans_consistency_level( } else { sql = trans_info_.client_request_.get_sql(); } - if (OB_UNLIKELY(!cs_info.is_read_weak_supported())) { + if (OB_UNLIKELY(!cs_info.is_server_support_read_weak())) { ret_level = common::STRONG; PROXY_LOG(DEBUG, "ObServer do not support read weak, treat it as strong read", "sql_hint", get_consistency_level_str(sql_hint), @@ -294,10 +384,8 @@ void ObMysqlTransact::acquire_cached_server_session(ObTransState &s) } else if (get_global_proxy_config().enable_cached_server && !s.sm_->client_session_->is_proxy_mysql_client_ && NULL != last_session && OB_LIKELY(!s.mysql_config_params_->is_random_routing_mode())) { - const int32_t ip = ops_ip4_addr_host_order(last_session->get_netvc()->get_remote_addr()); - const int32_t port = static_cast(ops_ip_port_host_order(last_session->get_netvc()->get_remote_addr())); ObAddr last_addr; - last_addr.set_ipv4_addr(ip, port); + last_addr.set_sockaddr(last_session->get_netvc()->get_remote_addr()); #if OB_DETAILED_SLOW_QUERY ObHRTime t1 = common::get_hrtime_internal(); #endif @@ -365,8 +453,13 @@ bool ObMysqlTransact::can_direct_ok_for_login(ObTransState &s) { bool bret = false; ObClientSessionInfo &cs_info = s.sm_->client_session_->get_session_info(); - if (!(obmysql::OB_MYSQL_COM_LOGIN == s.trans_info_.sql_cmd_ && s.is_auth_request_ && s.sm_->client_session_->is_session_pool_client())) { - // should only session_pool_client and LOGIN for auth + if (!(obmysql::OB_MYSQL_COM_LOGIN == s.trans_info_.sql_cmd_ && s.is_auth_request_)) { + // should only LOGIN for auth + } else if (s.sm_->client_session_->can_direct_send_request_) { + //scan all return ok + bret = true; + } else if (!s.sm_->client_session_->is_session_pool_client()) { + // should only session_pool_client } else if (cs_info.is_sharding_user()) { bret = true; } else if (!s.sm_->client_session_->is_proxy_mysql_client_ && get_global_proxy_config().enable_no_sharding_skip_real_conn) { @@ -495,7 +588,7 @@ void ObMysqlTransact::handle_mysql_request(ObTransState &s) int ret = OB_SUCCESS; sockaddr sa; memset(&sa, 0, sizeof(sa)); - bool need_pl_lookup = ObMysqlTransact::need_pl_lookup(s); + bool need_pl_lookup = (ObMysqlTransact::need_pl_lookup(s) == NEED_PL_LOOKUP); ObMysqlServerSession *last_session = s.sm_->client_session_->get_server_session(); if (need_pl_lookup) { ObMysqlServerSession *svr_session = NULL; @@ -560,20 +653,67 @@ void ObMysqlTransact::handle_mysql_request(ObTransState &s) } } -void ObMysqlTransact::handle_ps_close(ObTransState &s) +void ObMysqlTransact::handle_ps_close_reset(ObTransState &s) { int ret = OB_SUCCESS; ObMysqlClientSession *client_session = s.sm_->get_client_session(); + ObIArray &remove_addrs = client_session->get_session_info().get_request_send_addrs(); // At the end of each request, server_entry_ and server_session_ will be placed, // including the internal jump of the close command multiple times. - if (!client_session->is_first_handle_close_request()) { + if (!client_session->is_first_handle_request()) { s.sm_->release_server_session(); // If it is not the first time to come in, it will also be judged according to the transaction status of the first time. - s.need_pl_lookup_ = s.need_pl_lookup_ && !client_session->is_in_trans_for_close_request(); + bool need_pl_lookup = s.is_need_pl_lookup() && !client_session->is_in_trans_for_close_request(); + // sync pl_lookup_state_ + if (!need_pl_lookup) { + if (client_session->is_proxy_enable_trans_internal_routing()) { + s.pl_lookup_state_ = USE_COORDINATOR_SESSION; + } else { + s.pl_lookup_state_ = USE_LAST_SERVER_SESSION; + } + } } else { // The first time you come in, record the previous transaction status client_session->set_in_trans_for_close_request(is_in_trans(s)); + + remove_addrs.reuse(); + bool found = false; + uint32_t client_ps_id = client_session->get_session_info().get_client_ps_id(); + // If greater than 1 << 31L, it means cursor_id; otherwise, it is ps_id + if (client_ps_id >= (CURSOR_ID_START)) { + ObCursorIdAddr *cursor_id_addr = client_session->get_session_info().get_cursor_id_addr(client_ps_id); + if (NULL != cursor_id_addr) { + for (int64_t i = 0; !found && i< remove_addrs.count(); i++) { + if (remove_addrs.at(i) == cursor_id_addr->get_addr()) { + found = true; + } + } + if (!found) { + if (OB_FAIL(remove_addrs.push_back(cursor_id_addr->get_addr()))) { + LOG_WARN("fail to push back addr", K(ret)); + } + } + } + } else { + ObPsIdAddrs *ps_id_addrs = client_session->get_session_info().get_ps_id_addrs(client_ps_id); + if (NULL != ps_id_addrs && 0 != ps_id_addrs->get_addrs().count()) { + ObIArray &array = ps_id_addrs->get_addrs(); + for (int64_t i = 0; i < array.count(); i++) { + found = false; + for (int64_t j = 0; !found && j < remove_addrs.count(); j++) { + if (remove_addrs.at(j) == array.at(i)) { + found = true; + } + } + if (!found) { + if (OB_FAIL(remove_addrs.push_back(array.at(i)))) { + LOG_WARN("fail to push back addr", K(ret)); + } + } + } + } + } } ObMysqlServerSession *last_session = client_session->get_server_session(); @@ -583,64 +723,43 @@ void ObMysqlTransact::handle_ps_close(ObTransState &s) * 1. last_session does not exist. * 2. last_bound_session is not null. */ - if (!s.need_pl_lookup_ && client_session->is_first_handle_close_request() + if (!s.is_need_pl_lookup() && client_session->is_first_handle_request() && (NULL == last_session || NULL != last_bound_session)) { LOG_ERROR("[ObMysqlTransact::handle request] something is wrong, we have to disconnect", - "is_first_handle_close_request_", client_session->is_first_handle_close_request(), + "is_first_handle_close_request_", client_session->is_first_handle_request(), KP(last_session), KP(last_bound_session)); TRANSACT_RETURN(SM_ACTION_SEND_ERROR_NOOP, NULL); } else { - uint32_t client_ps_id = client_session->get_session_info().get_client_ps_id(); - bool is_need_send_close_cmd = false; + bool is_need_send_cmd = false; bool is_need_send_to_bound_ss = false; ObIpEndpoint addr; - // If greater than 1 << 31L, it means cursor_id; otherwise, it is ps_id - if (client_ps_id >= (CURSOR_ID_START)) { - ObCursorIdAddr *cursor_id_addr = client_session->get_session_info().get_cursor_id_addr(client_ps_id); - if (NULL != cursor_id_addr) { - is_need_send_close_cmd = true; - addr = cursor_id_addr->get_addr(); - // If no routing is required, and it is the first time, the bound_ss is sent first. - // If the server to be sent is bound_ss, the flag is set, and no migration is required later. - if (!s.need_pl_lookup_ - && client_session->is_first_handle_close_request() - && addr == ObIpEndpoint(last_session->get_netvc()->get_remote_addr())) { - is_need_send_to_bound_ss = true; - } - } - } else { - ObPsIdAddrs *ps_id_addrs = client_session->get_session_info().get_ps_id_addrs(client_ps_id); - if (NULL != ps_id_addrs && 0 != ps_id_addrs->get_addrs().size()) { - is_need_send_close_cmd = true; - /* If no routing is required, and it is the first time to come in - * Then check if there is any need to send to bound_ss, if so, send it first, - * otherwise migrate the connection, and then migrate back - */ - if (!s.need_pl_lookup_ - && client_session->is_first_handle_close_request()) { - ObPsIdAddrs::ADDR_HASH_SET::iterator iter = ps_id_addrs->get_addrs().begin(); - ObPsIdAddrs::ADDR_HASH_SET::iterator iter_end = ps_id_addrs->get_addrs().end(); - - for (; iter != iter_end; iter++) { - if (iter->first == ObIpEndpoint(last_session->get_netvc()->get_remote_addr())) { - is_need_send_to_bound_ss = true; - addr = iter->first; - break; - } + if (0 != remove_addrs.count()) { + is_need_send_cmd = true; + /* If no routing is required, and it is the first time to come in + * Then check if there is any need to send to bound_ss, if so, send it first, + * otherwise migrate the connection, and then migrate back + */ + if (!s.is_need_pl_lookup() + && client_session->is_first_handle_request()) { + for (int64_t i = 0; i < remove_addrs.count(); i++) { + if (remove_addrs.at(i) == ObIpEndpoint(last_session->get_netvc()->get_remote_addr())) { + is_need_send_to_bound_ss = true; + addr = remove_addrs.at(i); + break; } } + } - if (!is_need_send_to_bound_ss) { - addr = ps_id_addrs->get_addrs().begin()->first; - } + if (!is_need_send_to_bound_ss) { + addr = remove_addrs.at(0); } } - if (is_need_send_close_cmd) { + if (is_need_send_cmd) { // If no routing is required, and there is no last server session in the server to be sent, migrate ObMysqlServerSession *last_bound_session = client_session->get_last_bound_server_session(); - if (!s.need_pl_lookup_ + if (!s.is_need_pl_lookup() && !is_need_send_to_bound_ss && NULL == last_bound_session) { client_session->attach_server_session(NULL); @@ -650,12 +769,13 @@ void ObMysqlTransact::handle_ps_close(ObTransState &s) } if (OB_SUCC(ret)) { - client_session->set_first_handle_close_request(false); + client_session->set_first_handle_request(false); s.server_info_.set_addr(addr); s.pll_info_.lookup_success_ = true; start_access_control(s); } } else { + LOG_DEBUG("handle_ps_close_reset don't need send cmd"); // This indicates that session migration has occurred and needs to be migrated back if (client_session->is_need_return_last_bound_ss()) { if (NULL != last_bound_session) { @@ -688,23 +808,44 @@ void ObMysqlTransact::handle_oceanbase_request(ObTransState &s) { int ret = OB_SUCCESS; ObClientSessionInfo &cs_info = get_client_session_info(s); - if (OB_LIKELY(cs_info.is_allow_use_last_session())) { - s.need_pl_lookup_ = need_pl_lookup(s); - } else { - s.need_pl_lookup_ = true; + ObProxyMysqlRequest &client_request = s.trans_info_.client_request_; + ObPLLookupState state = need_pl_lookup(s); + // if target db server set + bool hint_target_db = OB_NOT_NULL(client_request.get_parse_result().get_target_db_server()) + && !client_request.get_parse_result().get_target_db_server()->is_empty(); + bool conf_target_db = OB_NOT_NULL(s.sm_->target_db_server_) + && !s.sm_->target_db_server_->is_empty(); + s.pl_lookup_state_ = state; + if (OB_UNLIKELY(!cs_info.is_allow_use_last_session())) { + s.pl_lookup_state_ = NEED_PL_LOOKUP; + } + // generate span before each request + if (s.sm_->get_client_session()->is_first_handle_request()) { + if (OB_FAIL(s.sm_->handle_req_for_begin_proxy_root_span())) { + LOG_WARN("fail to handle req for begin proxy root span", K(ret)); + } } - + obmysql::ObMySQLCmd cmd = s.trans_info_.sql_cmd_; - - if (OB_UNLIKELY(cs_info.is_sharding_user()) - && OB_FAIL(ObProxyShardUtils::update_sys_read_consistency_if_need(cs_info))) { + if (is_in_trans(s) + && s.sm_->get_client_session()->is_proxy_enable_trans_internal_routing() + && OB_UNLIKELY(!s.sm_->get_client_session()->get_trans_coordinator_ss_addr().is_valid())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("coordinator session addr is invalid, we have to disconnect", K(ret)); + TRANSACT_RETURN(SM_ACTION_SEND_ERROR_NOOP, NULL); // disconnect + } else if (OB_UNLIKELY(cs_info.is_sharding_user()) + && OB_FAIL(ObProxyShardUtils::update_sys_read_consistency_if_need(cs_info))) { LOG_WARN("fail to update_sys_read_consistency_if_need", K(ret)); TRANSACT_RETURN(SM_ACTION_SEND_ERROR_NOOP, NULL); // disconnect + } else if (s.sm_->get_client_session()->get_session_info().get_priv_info().user_name_ == ObProxyTableInfo::DETECT_USERNAME_USER && s.server_info_.addr_.is_valid()) { + lookup_skip_open_server(s); } else if (OB_UNLIKELY(need_server_session_lookup(s))) { TRANSACT_RETURN(SM_ACTION_SERVER_ADDR_LOOKUP, handle_server_addr_lookup); - } else if (OB_UNLIKELY(obmysql::OB_MYSQL_COM_STMT_CLOSE == cmd)) { - handle_ps_close(s); - } else if (OB_LIKELY(s.need_pl_lookup_)) { + } else if (OB_UNLIKELY(obmysql::OB_MYSQL_COM_STMT_CLOSE == cmd || obmysql::OB_MYSQL_COM_STMT_RESET == cmd)) { + handle_ps_close_reset(s); + } else if (client_request.get_parse_result().is_text_ps_drop_stmt()) { + handle_ps_close_reset(s); + } else if (OB_LIKELY(s.is_need_pl_lookup())) { // if need pl lookup, we should extract pl info first if (OB_FAIL(extract_partition_info(s))) { LOG_WARN("fail to extract partition info", K(ret)); @@ -717,6 +858,7 @@ void ObMysqlTransact::handle_oceanbase_request(ObTransState &s) uint16_t port = 0; get_ip_port_from_addr(addr, ip, port); s.server_info_.set_addr(ip, port); + LOG_DEBUG("set addr here", K(s.server_info_.addr_)); s.pll_info_.lookup_success_ = true; LOG_DEBUG("@obproxy_route_addr is set", "address", s.server_info_.addr_, K(addr)); } else if (obmysql::OB_MYSQL_COM_STMT_FETCH == cmd @@ -765,23 +907,80 @@ void ObMysqlTransact::handle_oceanbase_request(ObTransState &s) LOG_DEBUG("succ to set target addr for send piece/prepare execute/send long data", "address", s.server_info_.addr_, KPC(info)); } - } else if ((s.mysql_config_params_->is_mock_routing_mode() && !s.sm_->client_session_->is_proxy_mysql_client_) - || s.mysql_config_params_->is_mysql_routing_mode()) { - if (OB_FAIL(s.mysql_config_params_->get_one_test_server_addr(s.server_info_.addr_))) { - LOG_INFO("mysql or mock mode, but test server addr in not set, do normal pl lookup", K(ret)); - ret = OB_SUCCESS; - } else { - s.sm_->client_session_->test_server_addr_ = s.server_info_.addr_; - s.pll_info_.lookup_success_ = true; - LOG_DEBUG("mysql mode, test server is valid, just use it and skip pl lookup", + } else { /* do nothing */} + + // Specified server addr + // 1. target_db_server (comment & multi levle config) + // 2. test_server_addr & server_routing_mode (deprecated global config) + + // target db server (sql comment & multi level config) + if (OB_SUCC(ret) && !s.pll_info_.lookup_success_) { + // Use target_db_server + // exsit in sql comment parsed result + if (hint_target_db) { + if (OB_FAIL(client_request.get_parse_result().get_target_db_server()->get(s.server_info_.addr_))) { + LOG_WARN("fail to get target db server from sql comment", K(ret)); + TRANSACT_RETURN(SM_ACTION_SEND_ERROR_NOOP, NULL); + } else { + // in case of dummy entry is NULL + if (NULL == s.sm_->client_session_->dummy_entry_) { + s.sm_->client_session_->is_need_update_dummy_entry_ = true; + } + s.pll_info_.lookup_success_ = true; + LOG_DEBUG("succ to get target db server from sql comment", "address", s.server_info_.addr_); + } + // exist in multi level config target_db_server + } else if (conf_target_db) { + s.sm_->target_db_server_->reuse(); + if (OB_FAIL(s.sm_->target_db_server_->get(s.server_info_.addr_))) { + LOG_WARN("fail to get target db server from multi level config", K(ret)); + TRANSACT_RETURN(SM_ACTION_SEND_ERROR_NOOP, NULL); + } else { + // in case of dummy entry is NULL + if (NULL == s.sm_->client_session_->dummy_entry_) { + s.sm_->client_session_->is_need_update_dummy_entry_ = true; + } + s.pll_info_.lookup_success_ = true; + LOG_DEBUG("succ to get target db server from multi level config", + "address", s.server_info_.addr_); + } + } else { /* do nothing */} + } else if (OB_SUCC(ret)) { + if ((hint_target_db && !client_request.get_parse_result().get_target_db_server()->contains(s.server_info_.addr_)) || + (!hint_target_db && conf_target_db && !s.sm_->target_db_server_->contains(s.server_info_.addr_))) { + ret = OB_OP_NOT_ALLOW; + LOG_WARN("Not allow to route to", "choosen server", s.server_info_.addr_, K(ret)); + TRANSACT_RETURN(SM_ACTION_SEND_ERROR_NOOP, NULL); } - } else if (OB_UNLIKELY(!s.mysql_config_params_->is_random_routing_mode() + } + // deprecated global config + if (OB_SUCC(ret) && !s.pll_info_.lookup_success_) { + if ((s.mysql_config_params_->is_mock_routing_mode() && !s.sm_->client_session_->is_proxy_mysql_client_) + || s.mysql_config_params_->is_mysql_routing_mode()) { + if (OB_FAIL(s.mysql_config_params_->get_one_test_server_addr(s.server_info_.addr_))) { + LOG_INFO("mysql or mock mode, but test server addr in not set, do normal pl lookup", K(ret)); + if (NULL == s.sm_->client_session_->dummy_entry_) { + s.sm_->client_session_->is_need_update_dummy_entry_ = true; + } + ret = OB_SUCCESS; + } else { + s.sm_->client_session_->test_server_addr_ = s.server_info_.addr_; + s.pll_info_.lookup_success_ = true; + LOG_DEBUG("mysql mode, test server is valid, just use it and skip pl lookup", + "address", s.server_info_.addr_); + } + } else { /* do nothing */} + } + + if (OB_SUCC(ret) && !s.pll_info_.lookup_success_) { + if (OB_UNLIKELY(!s.mysql_config_params_->is_random_routing_mode() && !s.api_server_addr_set_ - && s.pll_info_.te_name_.is_all_dummy_table() + && s.pll_info_.te_name_.is_all_dummy_table() && cs_info.is_allow_use_last_session())) { - acquire_cached_server_session(s); - } // end of !is_in_test_mode + acquire_cached_server_session(s); + } + } if (OB_SUCC(ret)) { TRANSACT_RETURN(SM_ACTION_PARTITION_LOCATION_LOOKUP, handle_pl_lookup); @@ -789,10 +988,30 @@ void ObMysqlTransact::handle_oceanbase_request(ObTransState &s) } } else { // !need_pl_lookup - LOG_DEBUG("[ObMysqlTransact::handle request] force to use last server session"); - ObMysqlServerSession *last_session = s.sm_->client_session_->get_server_session(); + LOG_DEBUG("[ObMysqlTransact::handle request] force to use last server session/coordinator server session", K(get_pl_lookup_state_string(s.pl_lookup_state_))); + ObMysqlClientSession *client_session = s.sm_->get_client_session(); + ObMysqlServerSession *last_session = client_session->get_server_session(); + sockaddr target_addr; + + if (s.pl_lookup_state_ == USE_COORDINATOR_SESSION) { + LOG_DEBUG("use coordinator session"); + target_addr = client_session->get_trans_coordinator_ss_addr().sa_; + } else if (s.pl_lookup_state_ == USE_LAST_SERVER_SESSION) { + LOG_DEBUG("use last server session"); + if (OB_UNLIKELY(NULL == last_session )) { + TRANSACT_RETURN(SM_ACTION_SEND_ERROR_NOOP, NULL); + ret = OB_ERR_UNEXPECTED; + LOG_WARN("[ObMysqlTransact::handle request] last server session is invalid, we have to disconnect", K(ret)); + } else { + target_addr = last_session->get_netvc()->get_remote_addr(); + } + } else { + TRANSACT_RETURN(SM_ACTION_SEND_ERROR_NOOP, NULL); + ret = OB_ERR_UNEXPECTED; + LOG_WARN("[ObMysqlTransact::handle request] unexpected pl lookup state, we have to disconnect", K(s.pl_lookup_state_), K(ret)); + } - if (OB_LIKELY(NULL != last_session)) { + if (OB_SUCC(ret)) { if (obmysql::OB_MYSQL_COM_STMT_FETCH == cmd) { ObCursorIdAddr *cursor_id_addr = NULL; if (OB_FAIL(cs_info.get_cursor_id_addr(cursor_id_addr))) { @@ -803,12 +1022,16 @@ void ObMysqlTransact::handle_oceanbase_request(ObTransState &s) TRANSACT_RETURN(SM_ACTION_SEND_ERROR_NOOP, NULL); } } else { - if (OB_UNLIKELY(cursor_id_addr->get_addr() != last_session->get_netvc()->get_remote_addr())) { - ObMysqlClientSession *client_session = s.sm_->get_client_session(); - client_session->attach_server_session(NULL); - last_session->do_io_read(client_session, 0, NULL); - client_session->set_last_bound_server_session(last_session); - client_session->set_need_return_last_bound_ss(true); + if (OB_SUCC(ret) && OB_UNLIKELY(!ops_ip_addr_port_eq(cursor_id_addr->get_addr(), target_addr))) { + if (USE_COORDINATOR_SESSION == s.pl_lookup_state_) { + // under internal routing transaction, OB_MYSQL_COM_STMT_FETCH may be routed to participant + // don't need compare target server + } else { + client_session->attach_server_session(NULL); + last_session->do_io_read(client_session, 0, NULL); + client_session->set_last_bound_server_session(last_session); + client_session->set_need_return_last_bound_ss(true); + } } s.server_info_.set_addr(cursor_id_addr->get_addr()); @@ -823,26 +1046,31 @@ void ObMysqlTransact::handle_oceanbase_request(ObTransState &s) } else { TRANSACT_RETURN(SM_ACTION_SEND_ERROR_NOOP, NULL); } - } else if (OB_UNLIKELY(cursor_id_addr->get_addr() != last_session->get_netvc()->get_remote_addr())) { - s.mysql_errcode_ = OB_ERR_DISTRIBUTED_NOT_SUPPORTED; - s.mysql_errmsg_ = "fetch cursor target server is not the trans server"; - int tmp_ret = OB_SUCCESS; - if (OB_UNLIKELY(OB_SUCCESS != (tmp_ret = build_error_packet(s)))) { - LOG_WARN("fail to build err packet", K(tmp_ret)); + } else if (OB_UNLIKELY(!ops_ip_addr_port_eq(cursor_id_addr->get_addr(), target_addr))) { + if (USE_COORDINATOR_SESSION == s.pl_lookup_state_) { + // under internal routing transaction, OB_MYSQL_COM_STMT_GET_PIECE_DATA may be routed to participant + // don't need compare target server + target_addr = cursor_id_addr->get_addr().sa_; } else { - LOG_WARN("fetch cursor target server is not the trans server", - "fetch cursor target server", cursor_id_addr->get_addr(), - "trans server", ObIpEndpoint(last_session->get_netvc()->get_remote_addr())); - } + s.mysql_errcode_ = OB_ERR_DISTRIBUTED_NOT_SUPPORTED; + s.mysql_errmsg_ = "fetch cursor target server is not the trans server"; + int tmp_ret = OB_SUCCESS; + if (OB_UNLIKELY(OB_SUCCESS != (tmp_ret = build_error_packet(s, client_session)))) { + LOG_WARN("fail to build err packet", K(tmp_ret)); + } else { + LOG_WARN("fetch cursor target server is not the trans server", + "fetch cursor target server", cursor_id_addr->get_addr(), + "trans server", ObIpEndpoint(target_addr)); + } - ret = OB_ERR_DISTRIBUTED_NOT_SUPPORTED; - s.inner_errcode_ = ret; - s.current_.state_ = ObMysqlTransact::INTERNAL_ERROR; - TRANSACT_RETURN(SM_ACTION_INTERNAL_NOOP, NULL); + ret = OB_ERR_DISTRIBUTED_NOT_SUPPORTED; + s.inner_errcode_ = ret; + s.current_.state_ = ObMysqlTransact::INTERNAL_ERROR; + TRANSACT_RETURN(SM_ACTION_INTERNAL_NOOP, NULL); + } } - if (OB_SUCC(ret)) { - s.server_info_.set_addr(last_session->get_netvc()->get_remote_addr()); + s.server_info_.set_addr(target_addr); s.pll_info_.lookup_success_ = true; } } else if (obmysql::OB_MYSQL_COM_STMT_SEND_PIECE_DATA == cmd @@ -863,16 +1091,16 @@ void ObMysqlTransact::handle_oceanbase_request(ObTransState &s) ret = OB_ERR_UNEXPECTED; LOG_WARN("info is invalid", K(ret)); TRANSACT_RETURN(SM_ACTION_SEND_ERROR_NOOP, NULL); - } else if (OB_UNLIKELY(info->get_addr() != last_session->get_netvc()->get_remote_addr())) { + } else if (OB_UNLIKELY(!ops_ip_addr_port_eq(info->get_addr(), target_addr))) { s.mysql_errcode_ = OB_ERR_DISTRIBUTED_NOT_SUPPORTED; s.mysql_errmsg_ = "send piece info target server is not the trans server"; int tmp_ret = OB_SUCCESS; - if (OB_UNLIKELY(OB_SUCCESS != (tmp_ret = build_error_packet(s)))) { + if (OB_UNLIKELY(OB_SUCCESS != (tmp_ret = build_error_packet(s, client_session)))) { LOG_WARN("fail to build err packet", K(tmp_ret)); } else { LOG_WARN("send piece/long data target server is not the trans server", "target server", info->get_addr(), - "trans server", ObIpEndpoint(last_session->get_netvc()->get_remote_addr())); + "trans server", ObIpEndpoint(target_addr)); } ret = OB_ERR_DISTRIBUTED_NOT_SUPPORTED; @@ -882,22 +1110,29 @@ void ObMysqlTransact::handle_oceanbase_request(ObTransState &s) } if (OB_SUCC(ret)) { - s.server_info_.set_addr(last_session->get_netvc()->get_remote_addr()); + s.server_info_.set_addr(target_addr); s.pll_info_.lookup_success_ = true; } } else { - s.server_info_.set_addr(last_session->get_netvc()->get_remote_addr()); + s.server_info_.set_addr(target_addr); s.pll_info_.lookup_success_ = true; } if (OB_SUCC(ret)) { - start_access_control(s); + // if target db server set, then make sure target db server is the choosen server + if ((hint_target_db && !client_request.get_parse_result().get_target_db_server()->contains(s.server_info_.addr_)) || + (!hint_target_db && conf_target_db && !s.sm_->target_db_server_->contains(s.server_info_.addr_))) { + ret = OB_OP_NOT_ALLOW; + LOG_WARN("Not allow to route to", "choosen server", s.server_info_.addr_, K(ret)); + TRANSACT_RETURN(SM_ACTION_SEND_ERROR_NOOP, NULL); + } else { + start_access_control(s); + } } - } else { - LOG_WARN("[ObMysqlTransact::handle request] last session is NULL, we have to disconnect"); - TRANSACT_RETURN(SM_ACTION_SEND_ERROR_NOOP, NULL); } } // end of !s.need_pl_lookup + + LOG_DEBUG("handle oceanbase request, is addr valid:", K(s.server_info_.addr_.is_valid())); } void ObMysqlTransact::handle_fetch_request(ObTransState &s) @@ -913,9 +1148,10 @@ void ObMysqlTransact::handle_fetch_request(ObTransState &s) tmp_ret = OB_CURSOR_NOT_EXIST; } + ObMysqlClientSession *client_session = s.sm_->get_client_session(); if (OB_FAIL(s.sm_->get_client_buffer_reader()->consume_all())) { LOG_WARN("client buffer reader fail to consume all", K(ret)); - } else if (OB_FAIL(build_error_packet(s))) { + } else if (OB_FAIL(ObMysqlTransact::build_error_packet(s, client_session))) { LOG_WARN("fail to build err packet", K(ret)); } @@ -979,6 +1215,8 @@ void ObMysqlTransact::handle_request(ObTransState &s) } // so it's an internal request TRANSACT_RETURN(SM_ACTION_INTERNAL_REQUEST, handle_internal_request); + } else if (OB_UNLIKELY(is_binlog_request(s))) { + handle_binlog_request(s); } else { if (OB_UNLIKELY(get_global_performance_params().enable_stat_)) { if (obmysql::OB_MYSQL_COM_QUERY == s.trans_info_.sql_cmd_) { @@ -1006,22 +1244,23 @@ void ObMysqlTransact::handle_request(ObTransState &s) } } - if (OB_ISNULL(s.sm_->client_session_)) { + ObMysqlClientSession *client_session = s.sm_->get_client_session(); + if (OB_ISNULL(client_session)) { LOG_WARN("[ObMysqlTransact::handle request] client session is NULL, we have to disconnect"); TRANSACT_RETURN(SM_ACTION_SEND_ERROR_NOOP, NULL); } else if (OB_UNLIKELY(is_session_memory_overflow(s))) { s.mysql_errcode_ = OB_EXCEED_MEM_LIMIT; int tmp_ret = OB_SUCCESS; - if (OB_UNLIKELY(OB_SUCCESS != (tmp_ret = build_error_packet(s)))) { + if (OB_UNLIKELY(OB_SUCCESS != (tmp_ret = build_error_packet(s, client_session)))) { LOG_WARN("fail to build err packet", K(tmp_ret)); } else { LOG_WARN("client memory exceed memory limit", - "client mem size", s.sm_->client_session_->get_session_info().get_memory_size(), + "client mem size", client_session->get_session_info().get_memory_size(), "config mem size", s.mysql_config_params_->client_max_memory_size_); } s.current_.state_ = ObMysqlTransact::INTERNAL_ERROR; TRANSACT_RETURN(SM_ACTION_INTERNAL_NOOP, NULL); - } else if (OB_LIKELY(s.sm_->client_session_->get_session_info().is_oceanbase_server())) { + } else if (OB_LIKELY(client_session->get_session_info().is_oceanbase_server())) { handle_oceanbase_request(s); } else { handle_mysql_request(s); @@ -1029,31 +1268,131 @@ void ObMysqlTransact::handle_request(ObTransState &s) } } -inline bool ObMysqlTransact::need_use_last_server_session(ObTransState &s) +inline bool ObMysqlTransact::need_use_coordinator_session(ObTransState &s) { + // session in trans internal routing state + bool use_coordinator = false; + int ret = OB_SUCCESS; + ObSqlParseResult &parser_result = s.trans_info_.client_request_.get_parse_result(); + ObClientSessionInfo &session_info = s.sm_->get_client_session()->get_session_info(); + if (ObMysqlTransact::is_trans_specified(s)) { + if (s.sm_->get_client_session() != NULL + && s.sm_->get_client_session()->get_server_session() != NULL + && ops_ip_addr_port_eq (s.sm_->get_client_session()->get_trans_coordinator_ss_addr(), + s.sm_->get_client_session()->get_server_session()->get_netvc()->get_remote_addr())) { + LOG_WARN("internal routing transaction specified, coordinator session not equal with last session", K(ret)); + } + use_coordinator = true; + } else if (s.trans_info_.request_content_length_ > 0) { + // large request, route to coordinator session + use_coordinator = true; + } else if (s.sm_->get_client_session()->is_trans_internal_routing() + && is_sql_able_to_route_participant_in_trans(parser_result, s.trans_info_.sql_cmd_)) { + use_coordinator = false; + } else if (s.sm_->get_client_session()->is_trans_internal_routing() && parser_result.is_text_ps_execute_stmt()) { + ObTextPsEntry* text_ps_entry = NULL; + ObTextPsNameEntry* text_ps_name_entry = session_info.get_text_ps_name_entry(); + if (OB_ISNULL(text_ps_name_entry)) { + use_coordinator = true; + ret = OB_ERR_PREPARE_STMT_NOT_FOUND; + LOG_WARN("need use coordinator on text ps execute stmt, get text ps name entry failed", K(ret)); + } else if (OB_ISNULL(text_ps_entry = text_ps_name_entry->text_ps_entry_) || !text_ps_entry->is_valid()) { + use_coordinator = true; + ret = OB_INVALID_ERROR; + LOG_WARN("need use coordinator on text ps execute stmt, get text ps entry failed", K(ret)); + } else { + use_coordinator = !is_sql_able_to_route_participant_in_trans(text_ps_entry->get_base_ps_parse_result(), s.trans_info_.sql_cmd_); + } + } else { + // the rest of sql, use coordinator session + use_coordinator = true; + } + return use_coordinator; +} + +bool ObMysqlTransact::is_sql_able_to_route_participant_in_trans(obutils::ObSqlParseResult& base_sql_parse_result, obmysql::ObMySQLCmd sql_cmd) { + // transaction internal routing rule + // (1) route dml with table name to participant + // (2) route OB_MYSQL_COM_STMT_EXECUTE or text ps execute with inner sql like (1) to participant + // (3) route sql command except OB_MYSQL_COM_QUERY/OB_MYSQL_COM_STMT_PREPARE/OB_MYSQL_COM_STMT_EXECUTE to coordinator + // (4) route dual request to coordinator, in case of sql like `select DBMS_XA.XA_START(DBMS_XA_XID(?,?,?), 65536) from dual;` start xa transaction + // (5) route multi-stmt to coordinator + + bool able_to_route = false; + switch (sql_cmd) { + case obmysql::OB_MYSQL_COM_QUERY: + case obmysql::OB_MYSQL_COM_STMT_PREPARE: + case obmysql::OB_MYSQL_COM_STMT_EXECUTE: + able_to_route = true; + break; + + default: + able_to_route = false; + break; + } + if (able_to_route) { + if (base_sql_parse_result.is_dual_request()) { + able_to_route = false; + } else { + able_to_route = (base_sql_parse_result.is_text_ps_prepare_stmt() + && base_sql_parse_result.is_text_ps_inner_dml_stmt() + && !base_sql_parse_result.is_text_ps_call_stmt() + && !base_sql_parse_result.is_multi_semicolon_in_stmt() + && base_sql_parse_result.get_table_name_length() > 0) + || (base_sql_parse_result.is_dml_stmt() + && !base_sql_parse_result.is_multi_stmt() + && !base_sql_parse_result.is_multi_semicolon_in_stmt() + && base_sql_parse_result.get_table_name_length() > 0); + } + } + return able_to_route; +} + +inline ObMysqlTransact::ObPLLookupState ObMysqlTransact::need_pl_lookup(ObTransState &s) { - // there are three cases we must force to use last server session - // 1. trans has begin, other sql must send to the same server session - // 2. a func depend on last execute sql - // 3. has already specified transaction characteristics (set transaction xxx), not commit yet, - return (is_in_trans(s) - || OB_UNLIKELY(NULL != s.sm_->client_session_ - && !s.sm_->client_session_->is_session_pool_client() - && (s.trans_info_.client_request_.get_parse_result().has_dependent_func() - || s.sm_->client_session_->get_session_info().is_trans_specified()))); + ObPLLookupState state = NEED_PL_LOOKUP; + bool trans_specified = is_trans_specified(s); + bool is_dep_func = has_dependent_func(s); + bool in_trans = is_in_trans(s); + if (in_trans && s.sm_->get_client_session()->is_proxy_enable_trans_internal_routing()) { + if (is_dep_func) { + state = USE_LAST_SERVER_SESSION; + } else { + state = need_use_coordinator_session(s) ? USE_COORDINATOR_SESSION : NEED_PL_LOOKUP; + } + } else { + state =(in_trans || trans_specified || is_dep_func) ? USE_LAST_SERVER_SESSION : NEED_PL_LOOKUP; + } + // if we don't use last server session/coordinator session, we must do pl lookup + LOG_DEBUG("need pl lookup", "state", get_pl_lookup_state_string(state), + "sql_cmd", ObProxyParserUtils::get_sql_cmd_name(s.trans_info_.sql_cmd_), + "is trans specified", trans_specified, + "has dependent func", is_dep_func, + "is in trans", in_trans); + + return state; +} + +inline bool ObMysqlTransact::is_trans_specified(ObTransState &s) +{ + return OB_UNLIKELY(NULL != s.sm_->client_session_ + && !s.sm_->client_session_->is_session_pool_client() + && s.sm_->client_session_->get_session_info().is_trans_specified()); } -inline bool ObMysqlTransact::need_pl_lookup(ObTransState &s) +inline bool ObMysqlTransact::has_dependent_func(ObTransState &s) { - // if we don't use last server session, we must do pl lookup - return !need_use_last_server_session(s); + return OB_UNLIKELY(NULL != s.sm_->client_session_ + && !s.sm_->client_session_->is_session_pool_client() + && (s.trans_info_.client_request_.get_parse_result().has_dependent_func())); } //reroute conditions: -// 1. Transaction first SQL +// 1. Transaction first SQL/FREE TRANSACTION ROUTE // 2. No reroute has occurred // 3. It is not a large request, and the request is less than 4K // (because the data in the read_buffer will be consumed again here, and the second routing will be copied from the 4K Buffer) // 4. In case of EXECUTE or PREPARE_EXECUTE request, no pieceInfo structure exists +// 5.Non-designated primary zone/IP routing inline bool ObMysqlTransact::is_need_reroute(ObMysqlTransact::ObTransState &s) { int ret = OB_SUCCESS; @@ -1062,10 +1401,17 @@ inline bool ObMysqlTransact::is_need_reroute(ObMysqlTransact::ObTransState &s) bool is_need_reroute = false; is_need_reroute = s.mysql_config_params_->enable_reroute_ - && !s.is_rerouted_ && s.need_pl_lookup_ - && s.is_trans_first_request_ + && '\0' == s.mysql_config_params_->proxy_primary_zone_name_[0] + && !s.is_rerouted_ && s.is_need_pl_lookup() + && (s.is_trans_first_request_ + || (ObMysqlTransact::is_in_trans(s) + && s.sm_->client_session_->is_trans_internal_routing())) && !s.trans_info_.client_request_.is_large_request() - && total_request_packet_len == cached_request_packet_len; + && total_request_packet_len == cached_request_packet_len + && (OB_ISNULL(s.trans_info_.client_request_.get_parse_result().get_target_db_server()) + || s.trans_info_.client_request_.get_parse_result().get_target_db_server()->is_empty()) + && (OB_ISNULL(s.sm_->target_db_server_) || s.sm_->target_db_server_->is_empty()); + if (is_need_reroute && (obmysql::OB_MYSQL_COM_STMT_PREPARE_EXECUTE == s.trans_info_.client_request_.get_packet_meta().cmd_ @@ -1118,7 +1464,7 @@ int ObMysqlTransact::extract_partition_info(ObTransState &s) // real cluster resource, can not used by other tenant ret = OB_ERR_UNEXPECTED; LOG_WARN("default cluster resource can only used by sys tenant", - K(tenant_name), KPC(s.sm_->sm_cluster_resource_)); + K(tenant_name), KPC(s.sm_->sm_cluster_resource_)); } } } @@ -1139,40 +1485,77 @@ int ObMysqlTransact::extract_partition_info(ObTransState &s) } else { is_table_name_from_parser = true; - database_name = parse_result.get_database_name(); - if (OB_LIKELY(database_name.empty())) { + if (OB_LIKELY(parse_result.get_database_name().empty())) { if (OB_SUCCESS != cs_info.get_database_name(database_name)) { database_name = OB_SYS_DATABASE_NAME; } + ObProxyParseString tmp_database_name; + tmp_database_name.str_ = database_name.ptr(); + tmp_database_name.end_ptr_ = database_name.ptr() + database_name.length() - 1; + tmp_database_name.str_len_ = database_name.length(); + tmp_database_name.quote_type_ = OBPROXY_QUOTE_T_INVALID; + if (OB_FAIL(parse_result.set_db_name(tmp_database_name))) { + LOG_WARN("parse result set db name failed", K(ret)); + } } else { is_database_name_from_parser = true; } - package_name = parse_result.get_package_name(); - if (OB_UNLIKELY(!package_name.empty())) { - is_package_name_from_parser = true; - } - - // if run here, means table name and db name all come from parse result - if (OB_UNLIKELY(s.sm_->client_session_->get_session_info().is_oracle_mode())) { - if (is_table_name_from_parser && OBPROXY_QUOTE_T_INVALID == parse_result.get_table_name_quote()) { - string_to_upper_case(table_name.ptr(), table_name.length()); - } - if (is_database_name_from_parser && OBPROXY_QUOTE_T_INVALID == parse_result.get_database_name_quote()) { - string_to_upper_case(database_name.ptr(), database_name.length()); + if (OB_SUCC(ret)) { + database_name = parse_result.get_database_name(); + package_name = parse_result.get_package_name(); + if (OB_UNLIKELY(!package_name.empty())) { + is_package_name_from_parser = true; } - if (is_package_name_from_parser && OBPROXY_QUOTE_T_INVALID == parse_result.get_package_name_quote()) { - string_to_upper_case(package_name.ptr(), package_name.length()); + + // if run here, means table name and db name all come from parse result + if (OB_UNLIKELY(s.sm_->client_session_->get_session_info().is_oracle_mode())) { + if (is_table_name_from_parser && OBPROXY_QUOTE_T_INVALID == parse_result.get_table_name_quote()) { + string_to_upper_case(table_name.ptr(), table_name.length()); + } + if (is_database_name_from_parser && OBPROXY_QUOTE_T_INVALID == parse_result.get_database_name_quote()) { + string_to_upper_case(database_name.ptr(), database_name.length()); + } + if (is_package_name_from_parser && OBPROXY_QUOTE_T_INVALID == parse_result.get_package_name_quote()) { + string_to_upper_case(package_name.ptr(), package_name.length()); + } } } } + if (OB_SUCC(ret)) { + if (IS_CLUSTER_VERSION_LESS_THAN_V4(s.sm_->sm_cluster_resource_->cluster_version_) + && tenant_name == OB_SYS_TENANT_NAME && database_name == OB_SYS_DATABASE_NAME + && !get_global_proxy_config().enable_qa_mode) { + table_name = OB_ALL_DUMMY_TNAME; + } + } + if (OB_UNLIKELY(s.mysql_config_params_->enable_index_route_ && is_need_use_sql_table_cache(s) && table_name != OB_ALL_DUMMY_TNAME)) { ObString sql_id; + ObString user_sql; + + ObProxyMysqlRequest &client_request = s.trans_info_.client_request_; + ObClientSessionInfo &client_info = s.sm_->client_session_->get_session_info(); + if (obmysql::OB_MYSQL_COM_STMT_EXECUTE == client_request.get_packet_meta().cmd_ + || obmysql::OB_MYSQL_COM_STMT_SEND_LONG_DATA == client_request.get_packet_meta().cmd_) { + if (OB_FAIL(client_info.get_ps_sql(user_sql))) { + LOG_WARN("fail to get ps sql", K(ret)); + ret = OB_SUCCESS; + } + } else if (parse_result.is_text_ps_execute_stmt()) { + if (OB_FAIL(client_info.get_text_ps_sql(user_sql))) { + LOG_WARN("fail to get text ps sql", K(ret)); + ret = OB_SUCCESS; + } + } else { + user_sql = client_request.get_sql(); + } + // parse sql id - if (OB_FAIL(ObMysqlRequestAnalyzer::analyze_sql_id(s.trans_info_.client_request_, sql_id))) { + if (OB_FAIL(ObMysqlRequestAnalyzer::analyze_sql_id(user_sql, s.trans_info_.client_request_, sql_id))) { LOG_WARN("fail to analyze sql id", K(ret)); } else if (!sql_id.empty()) { ObSqlTableCache &sql_table_cache = get_global_sql_table_cache(); @@ -1361,7 +1744,7 @@ inline void ObMysqlTransact::ObPartitionLookupInfo::pl_update_if_necessary(const // if client session disconnect, can not access te_name_ te_name_.reset(); } else { - is_read_weak_supported = s.sm_->client_session_->get_session_info().is_read_weak_supported(); + is_read_weak_supported = s.sm_->client_session_->get_session_info().is_server_support_read_weak(); } // print log @@ -1381,12 +1764,13 @@ inline void ObMysqlTransact::ObPartitionLookupInfo::pl_update_if_necessary(const // 2. strong read, but leader do not exist //or // 3. weak read, but calculate server return miss or tenant server return hit + // besides, if we go with route optimize procedure, do not need pl update here if (route_.is_strong_read()) { const bool is_leader = is_leader_server(); const bool has_table_but_no_leader = (!route_.is_no_route_info_found() && !is_leader_existent()); if (is_leader != is_partition_hit || has_table_but_no_leader) { LOG_INFO("will set strong read route dirty", K(is_leader), K(is_partition_hit), K(has_table_but_no_leader), - "origin_name", te_name_, "route_info", route_); + "origin_name", te_name_, "route_info", route_); //NOTE:: if leader was congested from server, it will set_dirty in ObMysqlTransact::handle_congestion_control_lookup // here we only care response if (route_.set_target_dirty()) { @@ -1453,6 +1837,7 @@ void ObMysqlTransact::handle_congestion_control_lookup(ObTransState &s) } else { bool is_in_alive_congested = false; bool is_in_dead_congested = false; + bool is_in_detect_congested = false; ObCongestionEntry *cgt_entry= s.congestion_entry_; if (NULL == cgt_entry) { ObProxyMutex *mutex_ = s.sm_->mutex_; @@ -1463,6 +1848,7 @@ void ObMysqlTransact::handle_congestion_control_lookup(ObTransState &s) } else { is_in_dead_congested = cgt_entry->is_dead_congested(); + is_in_detect_congested = cgt_entry->is_detect_congested(); if (!s.force_retry_congested_ && is_in_dead_congested && s.pll_info_.is_strong_read() @@ -1501,16 +1887,23 @@ void ObMysqlTransact::handle_congestion_control_lookup(ObTransState &s) "and will expand its retry interval to avoid other connections use this server", KPC(cgt_entry)); cgt_entry->set_alive_failed_at(get_hrtime()); + if (get_global_proxy_config().server_detect_mode != 0) { + if (OB_LIKELY(NULL != s.sm_->sm_cluster_resource_)) { + s.sm_->sm_cluster_resource_->alive_addr_set_.set_refactored(cgt_entry->server_ip_); + } + is_in_alive_congested = true; + } } else { is_in_alive_congested = true; } } - if (is_in_alive_congested || is_in_dead_congested) { + if (is_in_alive_congested || is_in_dead_congested || is_in_detect_congested) { LOG_DEBUG("target server is in congested", "addr", s.server_info_.addr_, K(is_in_dead_congested), K(is_in_alive_congested), + K(is_in_detect_congested), "force_retry_congested", s.force_retry_congested_, KPC(cgt_entry), "pll info", s.pll_info_); @@ -1528,6 +1921,9 @@ void ObMysqlTransact::handle_congestion_control_lookup(ObTransState &s) CONGEST_INCREMENT_DYN_STAT(alive_congested_stat); s.current_.state_ = ObMysqlTransact::ALIVE_CONGESTED; handle_response(s); + } else if (!s.force_retry_congested_ && is_in_detect_congested) { + s.current_.state_ = ObMysqlTransact::DETECT_CONGESTED; + handle_response(s); } else { start_access_control(s); // continue } @@ -1603,8 +1999,7 @@ void ObMysqlTransact::check_safe_read_snapshot(ObTransState &s) ObSafeSnapshotEntry *entry = NULL; const ObProxyPartitionLocation *pl = s.pll_info_.route_.cur_chosen_pl_; ObAddr addr; - addr.set_ipv4_addr(s.server_info_.addr_.get_ip4_host_order(), - static_cast(s.server_info_.addr_.get_port_host_order())); + addr.set_sockaddr(s.server_info_.addr_.sa_); if (OB_ISNULL(pl) || pl->is_server_changed()) { // get the max snapshot server of all server int64_t count = s.sm_->client_session_->dummy_ldc_.count(); @@ -1718,6 +2113,17 @@ void ObMysqlTransact::handle_pl_lookup(ObTransState &s) { int ret = OB_SUCCESS; ++s.pll_info_.pl_attempts_; + + if (s.sm_->enable_record_full_link_trace_info()) { + trace::ObSpanCtx *ctx = s.sm_->flt_.trace_log_info_.partition_location_lookup_ctx_; + if (OB_NOT_NULL(ctx)) { + LOG_DEBUG("end span ob_proxy_partition_location_lookup", K(ctx->span_id_)); + SET_TRACE_BUFFER(s.sm_->flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + FLT_END_SPAN(ctx); + s.sm_->flt_.trace_log_info_.partition_location_lookup_ctx_ = NULL; + } + } + if (OB_UNLIKELY(!s.pll_info_.lookup_success_)) { // partition location lookup failed ret = OB_ERR_UNEXPECTED; LOG_WARN("[ObMysqlTransact::handle_pl_lookup] " @@ -1736,8 +2142,27 @@ void ObMysqlTransact::handle_pl_lookup(ObTransState &s) ret = OB_ERR_UNEXPECTED; LOG_WARN("[ObMysqlTransact::handle_pl_lookup] " "it should not arrive here, will disconnect", K(ret)); - } else if (OB_UNLIKELY(is_server_addr_set && s.mysql_config_params_->is_mysql_routing_mode())) { - LOG_DEBUG("[ObMysqlTransact::handle_pl_lookup] use mysql route mode and server addr is set, " + } else if (OB_UNLIKELY(is_server_addr_set + && (s.mysql_config_params_->is_mysql_routing_mode() + || (s.mysql_config_params_->is_mock_routing_mode() + && !s.sm_->client_session_->is_proxy_mysql_client_)))) { + LOG_DEBUG("[ObMysqlTransact::handle_pl_lookup] use mysql route mode or mock mode and server addr is set, " + "use cached session", + "addr", s.server_info_.addr_, + "attempts", s.current_.attempts_, + "sm_id", s.sm_->sm_id_); + } else if (OB_UNLIKELY(is_server_addr_set + && ((OB_NOT_NULL(s.sm_->target_db_server_) && !s.sm_->target_db_server_->is_empty()) + || (OB_NOT_NULL(s.trans_info_.client_request_.get_parse_result().get_target_db_server()) + && !s.trans_info_.client_request_.get_parse_result().get_target_db_server()->is_empty())))) { + if (OB_NOT_NULL(s.sm_->client_session_->dummy_entry_) + && s.sm_->client_session_->dummy_entry_->is_avail_state() + && s.sm_->client_session_->dummy_entry_->is_valid() + && is_addr_logonly(s.server_info_.addr_, s.sm_->client_session_->dummy_entry_->get_tenant_servers())) { + ret = OB_OP_NOT_ALLOW; + LOG_WARN("Not allow to route to logonly replica", "choosen server", s.server_info_.addr_, K(ret)); + } + LOG_DEBUG("[ObMysqlTransact::handle_pl_lookup] use target db server and server addr is set, " "use cached session", "addr", s.server_info_.addr_, "attempts", s.current_.attempts_, @@ -1762,7 +2187,7 @@ void ObMysqlTransact::handle_pl_lookup(ObTransState &s) "proxy_enable_causal_order_read", s.sm_->trans_state_.mysql_config_params_->enable_causal_order_read_, "server_enable_causal_order_read", - s.sm_->client_session_->get_session_info().is_safe_read_weak_supported()); + s.sm_->client_session_->get_session_info().is_server_support_safe_read_weak()); s.sm_->client_session_->dummy_ldc_.set_safe_snapshot_manager(NULL); } else { LOG_DEBUG("safe weak read is enabled"); @@ -1778,10 +2203,12 @@ void ObMysqlTransact::handle_pl_lookup(ObTransState &s) const ObProxyReplicaLocation *replica = pl->get_replica(i); if (NULL != replica && replica->is_leader()) { fill_addr = true; - s.server_info_.set_addr(replica->server_.get_ipv4(), static_cast(replica->server_.get_port())); + s.server_info_.set_addr(ops_ip_sa_cast(replica->server_.get_sockaddr())); + LOG_DEBUG("set addr here", K(s.server_info_.addr_)); s.pll_info_.route_.cur_chosen_server_.replica_ = replica; s.pll_info_.route_.leader_item_.is_used_ = true; s.pll_info_.route_.skip_leader_item_ = true; + s.pll_info_.route_.cur_chosen_route_type_ = ROUTE_TYPE_LEADER; break; } } @@ -1792,6 +2219,7 @@ void ObMysqlTransact::handle_pl_lookup(ObTransState &s) s.pll_info_.route_.need_use_dup_replica_ = use_dup_replica; const bool disable_merge_status_check = need_disable_merge_status_check(s); const ObRoutePolicyEnum route_policy = s.get_route_policy(*s.sm_->client_session_, use_dup_replica); + bool is_random_routing_mode = s.mysql_config_params_->is_random_routing_mode(); ModulePageAllocator *allocator = NULL; ObLDCLocation::get_thread_allocator(allocator); @@ -1805,9 +2233,10 @@ void ObMysqlTransact::handle_pl_lookup(ObTransState &s) if (OB_FAIL(s.pll_info_.route_.fill_replicas( consistency_level, route_policy, + is_random_routing_mode, disable_merge_status_check, - s.sm_->client_session_->dummy_entry_, - s.sm_->client_session_->dummy_ldc_, + s.sm_->client_session_, + s.sm_->sm_cluster_resource_, simple_servers_info, region_names, proxy_primary_zone_name @@ -1832,29 +2261,18 @@ void ObMysqlTransact::handle_pl_lookup(ObTransState &s) int32_t attempt_count = 0; bool found_leader_force_congested = false; - if (OB_UNLIKELY(s.mysql_config_params_->is_random_routing_mode()) && (!s.sm_->client_session_->is_proxy_mysql_client_)) { - uint32_t last_ip = 0; - uint16_t last_port = 0; - ObNetVConnection *netvc = NULL; - if (NULL != s.sm_->client_session_->get_server_session() && NULL != (netvc = s.sm_->client_session_->get_server_session()->get_netvc()) && s.pll_info_.replica_size() > 1) { - last_ip = ntohl(netvc->get_remote_ip()); - last_port = netvc->get_remote_port(); - } - replica = s.pll_info_.get_next_replica(last_ip, last_port, s.force_retry_congested_); - } else { - replica = s.pll_info_.get_next_avail_replica(s.force_retry_congested_, attempt_count, - found_leader_force_congested); - s.current_.attempts_ += attempt_count; - if ((NULL == replica) && s.pll_info_.is_all_iterate_once()) { // next round - // if we has tried all servers, do force retry in next round - LOG_INFO("all replica is force_congested, force retry congested now", - "route", s.pll_info_.route_); - s.pll_info_.reset_cursor(); - s.force_retry_congested_ = true; + replica = s.pll_info_.get_next_avail_replica(s.force_retry_congested_, attempt_count, + found_leader_force_congested); + s.current_.attempts_ += attempt_count; + if ((NULL == replica) && s.pll_info_.is_all_iterate_once()) { // next round + // if we has tried all servers, do force retry in next round + LOG_INFO("all replica is force_congested, force retry congested now", + "route", s.pll_info_.route_); + s.pll_info_.reset_cursor(); + s.force_retry_congested_ = true; - // get replica again - replica = s.pll_info_.get_next_avail_replica(); - } + // get replica again + replica = s.pll_info_.get_next_avail_replica(); } #if OB_DETAILED_SLOW_QUERY @@ -1867,8 +2285,8 @@ void ObMysqlTransact::handle_pl_lookup(ObTransState &s) ret = OB_ERR_UNEXPECTED; LOG_WARN("no replica avail", K(replica), K(ret)); } else { - s.server_info_.set_addr(replica->server_.get_ipv4(), - static_cast(replica->server_.get_port())); + s.server_info_.set_addr(ops_ip_sa_cast(replica->server_.get_sockaddr())); + LOG_DEBUG("get replica by pl lookup, set addr", K(s.server_info_.addr_)); } if (found_leader_force_congested) { @@ -1920,24 +2338,32 @@ void ObMysqlTransact::handle_server_addr_lookup(ObTransState &s) // server session lookup failed, response err/ok packet LOG_DEBUG("[ObMysqlTransact::handle_server_addr_lookup] server addr lookup " "failed, response err/ok packet", "errcode", query_info->errcode_); + ObMIOBuffer *buf = NULL; + ObMysqlSM *sm = s.sm_; + // consume data in client buffer reader - if (OB_FAIL(s.sm_->get_client_buffer_reader()->consume_all())) { + if (OB_ISNULL(sm)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect empty sm", K(ret)); + } else if (OB_FAIL(sm->get_client_buffer_reader()->consume_all())) { LOG_WARN("[ObMysqlTransact::handle_server_addr_lookup] fail to consume client_buffer_reader_", K(ret)); } else if (OB_FAIL(s.alloc_internal_buffer(MYSQL_BUFFER_SIZE))) { LOG_WARN("[ObMysqlTransact::handle_server_addr_lookup] fail to allocate internal miobuffer", K(ret)); } else { buf = s.internal_buffer_; uint8_t seq = static_cast(s.trans_info_.client_request_.get_packet_meta().pkt_seq_ + 1); + ObMysqlClientSession *client_session = sm->get_client_session(); + ObProxyProtocol client_protocol = sm->get_client_session_protocol(); switch (query_info->errcode_) { case OB_SUCCESS: { - if (OB_ISNULL(s.sm_->client_session_)) { + if (OB_ISNULL(client_session)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("[ObMysqlTransact::handle_server_addr_lookup] client session is NULL, will disconnect", K(ret)); } else { const ObMySQLCapabilityFlags &capability = get_client_session_info(s).get_orig_capability_flags(); - if (OB_FAIL(ObMysqlPacketUtil::encode_ok_packet(*buf, seq, 0, capability))) { + if (ObProxyPacketWriter::write_ok_packet(*buf, *client_session, client_protocol, seq, 0, capability)) { LOG_WARN("[ObMysqlTransact::handle_server_addr_lookup] fail to build ok resp " "packet", K(ret)); } @@ -1946,24 +2372,33 @@ void ObMysqlTransact::handle_server_addr_lookup(ObTransState &s) } case OB_UNKNOWN_CONNECTION: case OB_ERR_KILL_DENIED: { - if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet(*buf, seq, query_info->errcode_, query_info->cs_id_))) { - LOG_WARN("[ObMysqlTransact::handle_server_addr_lookup] fail to build err resp packet", - K(ret), "cs_id", query_info->cs_id_); + char *err_msg = NULL; + if (OB_FAIL(ObProxyPacketWriter::get_user_err_buf(query_info->errcode_, err_msg, query_info->cs_id_))) { + LOG_WARN("fail to get user err buf", K(ret)); + } else if (OB_FAIL(ObProxyPacketWriter::write_error_packet(*buf, client_session, client_protocol, + seq, query_info->errcode_, err_msg))) { + LOG_WARN("[ObMysqlTransact::build_error_packet] fail to build not supported err resp", K(ret)); } break; } case OB_ERR_NO_PRIVILEGE: { - if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet(*buf, seq, query_info->errcode_, - query_info->priv_name_))) { - LOG_WARN("[ObMysqlTransact::handle_server_addr_lookup] fail to build err resp packet", + char *err_msg = NULL; + if (OB_FAIL(ObProxyPacketWriter::get_user_err_buf(query_info->errcode_, err_msg, query_info->priv_name_))) { + LOG_WARN("fail to get user err buf", K(ret)); + } else if (OB_FAIL(ObProxyPacketWriter::write_error_packet(*buf, client_session, client_protocol, + seq, query_info->errcode_, err_msg))) { + LOG_WARN("[ObMysqlTransact::handle_server_addr_lookup] fail to build no privilege err resp packet", K(ret), "priv_name", query_info->priv_name_); } break; } default: { - if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet(*buf, seq, query_info->errcode_))) { - LOG_WARN("[ObMysqlTransact::handle_server_addr_lookup] fail to build err resp " - "packet", K(ret)); + char *err_msg = NULL; + if (OB_FAIL(ObProxyPacketWriter::get_err_buf(query_info->errcode_, err_msg))) { + LOG_WARN("fail to get err buf", K(ret)); + } else if (OB_FAIL(ObProxyPacketWriter::write_error_packet(*buf, client_session, client_protocol, + seq, query_info->errcode_, err_msg))) { + LOG_WARN("[ObMysqlTransact::build_error_packet] fail to build err resp packet", K(ret)); } break; } @@ -2003,7 +2438,7 @@ void ObMysqlTransact::handle_server_addr_lookup(ObTransState &s) inline void ObMysqlTransact::start_access_control(ObTransState &s) { - if (s.need_pl_lookup_) { + if (s.is_need_pl_lookup()) { TRANSACT_RETURN(SM_ACTION_API_OBSERVER_PL, ObMysqlTransact::lookup_skip_open_server); s.sm_->set_skip_plugin(true); } else { @@ -2016,26 +2451,6 @@ inline void ObMysqlTransact::lookup_skip_open_server(ObTransState &s) TRANSACT_RETURN(SM_ACTION_OBSERVER_OPEN, ObMysqlTransact::handle_response); } -inline int ObMysqlTransact::build_user_request( - ObTransState &s, ObIOBufferReader *client_buffer_reader, - ObIOBufferReader *&reader, int64_t &request_len) -{ - int ret = OB_SUCCESS; - - if (s.sm_->client_session_->get_session_info().is_oceanbase_server()) { - if (OB_FAIL(build_oceanbase_user_request(s, client_buffer_reader, reader, request_len))) { - LOG_WARN("fail to build oceanbase user request", K(ret)); - } - } else { - // no need compress, send directly - int64_t client_request_len = s.trans_info_.client_request_.get_packet_len(); - request_len = client_request_len; - reader = client_buffer_reader; - } - - return ret; -} - int ObMysqlTransact::rewrite_stmt_id(ObTransState &s, ObIOBufferReader *client_buffer_reader) { int ret = OB_SUCCESS; @@ -2064,7 +2479,7 @@ int ObMysqlTransact::rewrite_stmt_id(ObTransState &s, ObIOBufferReader *client_b } else { client_buffer_reader->replace(reinterpret_cast(&server_cursor_id), sizeof(server_cursor_id), MYSQL_NET_META_LENGTH); } - } else if (obmysql::OB_MYSQL_COM_STMT_CLOSE == cmd) { + } else if (obmysql::OB_MYSQL_COM_STMT_CLOSE == cmd || obmysql::OB_MYSQL_COM_STMT_RESET == cmd) { ObServerSessionInfo &ss_info = get_server_session_info(s); ObClientSessionInfo &cs_info = get_client_session_info(s); uint32_t client_ps_id = cs_info.get_client_ps_id(); @@ -2101,12 +2516,32 @@ int ObMysqlTransact::rewrite_stmt_id(ObTransState &s, ObIOBufferReader *client_b return ret; } +inline int ObMysqlTransact::build_user_request( + ObTransState &s, ObIOBufferReader *client_buffer_reader, + ObIOBufferReader *&reader, int64_t &request_len) +{ + int ret = OB_SUCCESS; + + if (s.sm_->client_session_->get_session_info().is_oceanbase_server()) { + if (OB_FAIL(build_oceanbase_user_request(s, client_buffer_reader, reader, request_len))) { + LOG_WARN("fail to build oceanbase user request", K(ret)); + } + } else { + // no need compress, send directly + int64_t client_request_len = s.trans_info_.client_request_.get_packet_len(); + request_len = client_request_len; + reader = client_buffer_reader; + } + + return ret; +} + inline int ObMysqlTransact::build_oceanbase_user_request( ObTransState &s, ObIOBufferReader *client_buffer_reader, ObIOBufferReader *&reader, int64_t &request_len) { int ret = OB_SUCCESS; - ObProxyProtocol ob_proxy_protocol = s.sm_->use_compression_protocol(); + ObProxyProtocol server_protocol = s.sm_->get_server_session_protocol(); int64_t client_request_len = s.trans_info_.client_request_.get_packet_len(); // obproxy only send one mysql request packet at once; // if received multi request packets, we will send it one by one; @@ -2126,9 +2561,11 @@ inline int ObMysqlTransact::build_oceanbase_user_request( } else if (OB_FAIL(rewrite_stmt_id(s, client_buffer_reader))) { LOG_WARN("rewrite stmt id failed", K(ret)); } else { + obmysql::ObMySQLCmd req_cmd_type = s.trans_info_.client_request_.get_packet_meta().cmd_; ObIOBufferReader *request_buffer_reader = client_buffer_reader; - if (PROTOCOL_OB20 == ob_proxy_protocol || PROTOCOL_CHECKSUM == ob_proxy_protocol) { // convert standard mysql protocol to compression protocol - ObMIOBuffer *write_buffer = NULL; + ObMIOBuffer *write_buffer = NULL; + if (ObProxyProtocol::PROTOCOL_OB20 == server_protocol + || ObProxyProtocol::PROTOCOL_CHECKSUM == server_protocol) { // convert standard mysql protocol to compression protocol uint8_t compress_seq = 0; if (OB_ISNULL(write_buffer = new_miobuffer(MYSQL_BUFFER_SIZE))) { ret = OB_ALLOCATE_MEMORY_FAILED; @@ -2136,49 +2573,60 @@ inline int ObMysqlTransact::build_oceanbase_user_request( } else if (OB_ISNULL(reader = write_buffer->alloc_reader())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("[ObMysqlTransact::build_user_request] failed to allocate iobuffer reader", K(ret)); - } else if (obmysql::OB_MYSQL_COM_STMT_CLOSE == s.trans_info_.client_request_.get_packet_meta().cmd_ - && OB_ISNULL(request_buffer_reader = client_buffer_reader->clone())) { + } else if ((obmysql::OB_MYSQL_COM_STMT_CLOSE == req_cmd_type + || obmysql::OB_MYSQL_COM_STMT_RESET == req_cmd_type + || s.trans_info_.client_request_.get_parse_result().is_text_ps_drop_stmt()) + && OB_ISNULL(request_buffer_reader = client_buffer_reader->clone())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("[ObMysqlTransact::build_user_request] failed to clone client buffer reader", K(ret)); } else { - if (PROTOCOL_OB20 == ob_proxy_protocol) { - const bool is_last_packet = true; - // here and handle_error_resp need have same reroute conditions - const bool need_reroute = is_need_reroute(s); - ObSEArray extro_info; - char client_ip_buf[MAX_IP_BUFFER_LEN] = "\0"; - ObMysqlClientSession *client_session = s.sm_->get_client_session(); - if (!client_session->is_proxy_mysql_client_ - && client_session->is_need_send_trace_info() - && is_last_packet) { - ObAddr client_ip = client_session->get_real_client_addr(); - if (OB_FAIL(ObProxyTraceUtils::build_client_ip(extro_info, client_ip_buf, client_ip))) { - LOG_ERROR("fail to build client ip", K(client_ip), K(ret)); - } else { - client_session->set_already_send_trace_info(true); - } - } - - if (OB_SUCC(ret)) { - if (OB_FAIL(ObProto20Utils::consume_and_compress_data( - request_buffer_reader, write_buffer, client_request_len, compress_seq, compress_seq, - s.sm_->get_server_session()->get_next_server_request_id(), - s.sm_->get_server_session()->get_server_sessid(), - is_last_packet, need_reroute, &extro_info))) { - LOG_ERROR("fail to consume_and_compress_data", K(ret)); + if (ObProxyProtocol::PROTOCOL_OB20 == server_protocol) { + if (OB_FAIL(build_oceanbase_ob20_user_request(s, *write_buffer, *request_buffer_reader, + client_request_len, compress_seq))) { + LOG_WARN("fail to build oceanbase ob20 user request", K(ret), K(client_request_len), K(compress_seq)); + } else { + // handle tail crc for other cmd type, close will send to every server, do not clear buf here + if (obmysql::OB_MYSQL_COM_STMT_CLOSE != req_cmd_type + && obmysql::OB_MYSQL_COM_STMT_RESET != req_cmd_type + && !s.trans_info_.client_request_.get_parse_result().is_text_ps_drop_stmt()) { + ObProxyProtocol client_protocol = s.sm_->get_client_session_protocol(); + if (client_protocol == ObProxyProtocol::PROTOCOL_OB20) { + ObClientSessionInfo &cs_info = s.sm_->get_client_session()->get_session_info(); + const bool ob20_req_received_done = cs_info.ob20_request_.ob20_request_received_done_; + const int64_t ob20_req_remain_payload_len = cs_info.ob20_request_.remain_payload_len_; + if (ob20_req_received_done + && ob20_req_remain_payload_len == 0) { + cs_info.ob20_request_.ob20_request_received_done_ = false; + int64_t read_avail = client_buffer_reader->read_avail(); + LOG_DEBUG("after build user ob req, handle ob20 tail crc in buffer", + K(ob20_req_received_done), K(ob20_req_remain_payload_len), K(read_avail)); + if (read_avail >= OB20_PROTOCOL_TAILER_LENGTH) { + if (OB_FAIL(client_buffer_reader->consume(OB20_PROTOCOL_TAILER_LENGTH))) { + LOG_WARN("fail to consume the last crc buffer in client request buffer", K(ret)); + } + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected enter here, client-proxy use ob2.0, handled mysql packet in payload done," + " unexpected remain buffer len, expect tail crc 4", K(ret), K(read_avail)); + } + } + } } - } + } // else } else { + // compress protocol const bool use_fast_compress = true; const bool is_checksum_on = s.sm_->is_checksum_on(); - if (OB_FAIL(ObMysqlAnalyzerUtils::consume_and_compress_data( - request_buffer_reader, write_buffer, client_request_len, use_fast_compress, - compress_seq, is_checksum_on))) { - LOG_WARN("fail to consume_and_compress_data", K(ret)); + if (OB_FAIL(ObMysqlAnalyzerUtils::consume_and_compress_data(request_buffer_reader, write_buffer, + client_request_len, use_fast_compress, + compress_seq, is_checksum_on))) { + LOG_WARN("fail to consume and compress mysql compress data", K(ret)); } } - if (obmysql::OB_MYSQL_COM_STMT_CLOSE == s.trans_info_.client_request_.get_packet_meta().cmd_) { + if (obmysql::OB_MYSQL_COM_STMT_CLOSE == req_cmd_type + || obmysql::OB_MYSQL_COM_STMT_RESET == req_cmd_type + || s.trans_info_.client_request_.get_parse_result().is_text_ps_drop_stmt()) { request_buffer_reader->dealloc(); request_buffer_reader = NULL; } @@ -2186,16 +2634,16 @@ inline int ObMysqlTransact::build_oceanbase_user_request( if (OB_SUCC(ret)) { s.sm_->get_server_session()->set_compressed_seq(compress_seq); request_len = reader->read_avail(); - LOG_DEBUG("build user compressed request succ", K(ob_proxy_protocol), - "origin len", client_request_len, "compress len", request_len); + LOG_DEBUG("build user compressed request succ", K(server_protocol), + "origin len", client_request_len, "compress len", request_len, "compress seq", compress_seq); } } } else { // no need compress, send directly request_len = client_request_len; - - ObMIOBuffer *write_buffer = NULL; - if (obmysql::OB_MYSQL_COM_STMT_CLOSE == s.trans_info_.client_request_.get_packet_meta().cmd_) { + if (obmysql::OB_MYSQL_COM_STMT_CLOSE == req_cmd_type + || obmysql::OB_MYSQL_COM_STMT_RESET == req_cmd_type + || s.trans_info_.client_request_.get_parse_result().is_text_ps_drop_stmt()) { int64_t written_len = 0; if (OB_ISNULL(write_buffer = new_miobuffer(MYSQL_BUFFER_SIZE))) { ret = OB_ALLOCATE_MEMORY_FAILED; @@ -2213,12 +2661,20 @@ inline int ObMysqlTransact::build_oceanbase_user_request( } reader = request_buffer_reader; } + + if (OB_FAIL(ret)) { + reader = NULL; + if (NULL != write_buffer) { + free_miobuffer(write_buffer); + write_buffer = NULL; + } + } } } LOG_DEBUG("[ObMysqlTransact::build_user_request] send request to observer", - "sm_id", s.sm_->sm_id_, K(ob_proxy_protocol), K(client_request_len), - "total_client_request_len", reader->read_avail(), + "sm_id", s.sm_->sm_id_, K(server_protocol), K(client_request_len), + "total_client_request_len", (reader != NULL) ? reader->read_avail() : 0, "request len send to server", request_len, K(s.trans_info_.request_content_length_), K(s.trans_info_.sql_cmd_), @@ -2226,7 +2682,92 @@ inline int ObMysqlTransact::build_oceanbase_user_request( return ret; } -inline int ObMysqlTransact::build_normal_login_request( +int ObMysqlTransact::build_oceanbase_ob20_user_request(ObTransState &s, ObMIOBuffer &write_buffer, + ObIOBufferReader &request_buffer_reader, + int64_t client_request_len, + uint8_t &compress_seq) +{ + int ret = OB_SUCCESS; + int64_t req_buf_avail = request_buffer_reader.read_avail(); + if (OB_UNLIKELY(req_buf_avail < client_request_len)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected buffer len check", K(ret), K(req_buf_avail), K(client_request_len)); + } else { + const int64_t split_request_len = 1 << 23L; // 8MB split each mysql packet + int64_t remain_req_len = client_request_len; + int64_t curr_req_len = 0; + bool generated_extra_info = false; + bool is_last_packet = false; + const bool need_reroute = is_need_reroute(s); + const bool is_weak_read = (WEAK == s.sm_->trans_state_.get_trans_consistency_level(s.sm_->get_client_session()->get_session_info())); + ObSEArray extra_info; + ObSqlString sess_info_value; + char client_ip_buf[MAX_IP_BUFFER_LEN] = "\0"; + char server_extra_info_buf[SERVER_EXTRA_INFO_BUF_MAX_LEN] = "\0"; + ObMysqlServerSession *server_session = s.sm_->get_server_session(); + ObMysqlClientSession *client_session = s.sm_->get_client_session(); + uint32_t req_id = server_session->get_next_server_request_id(); + + while (OB_SUCC(ret) && remain_req_len > 0) { + curr_req_len = remain_req_len > split_request_len ? split_request_len : remain_req_len; + remain_req_len -= curr_req_len; + if (remain_req_len == 0) { + is_last_packet = true; + } + + if (!generated_extra_info) { + // cause observer could only resolve extra info in the first ob20 packet + if (OB_FAIL(ObProxyTraceUtils::build_related_extra_info_all(extra_info, s.sm_, + client_ip_buf, MAX_IP_BUFFER_LEN, server_extra_info_buf, SERVER_EXTRA_INFO_BUF_MAX_LEN, + sess_info_value, true))) { + LOG_WARN("fail to build related extra info", K(ret)); + } else { + generated_extra_info = true; + } + } else { + extra_info.reset(); + } + + if (OB_SUCC(ret)) { + Ob20ProtocolHeaderParam ob20_head_param(server_session->get_server_sessid(), + req_id, compress_seq, compress_seq, is_last_packet, is_weak_read, need_reroute, + server_session->get_session_info().is_new_extra_info_supported(), + client_session->is_trans_internal_routing()); + if (OB_FAIL(ObProto20Utils::consume_and_compress_data(&request_buffer_reader, &write_buffer, + curr_req_len, ob20_head_param, &extra_info))) { + LOG_WARN("fail to consume and compress ob20 data", K(ret)); + } else { + LOG_DEBUG("succ to consume and compress in ob20", K(curr_req_len), K(compress_seq), K(is_last_packet), + K(req_id)); + compress_seq++; + } + } + } // while + compress_seq--; + } // else + + return ret; +} + +bool ObMysqlTransact::handle_set_trans_internal_routing(ObMysqlTransact::ObTransState &s, bool server_transaction_routing_flag) +{ + // used to set the header flag + // if session in a transaction, return the config of enable_internal_transaction_routing in server + // else return the config enable_internal_transaction_routing + bool internal_routing_flag = false; + if (is_trans_specified(s)) { + // trans_spcified, disable trans internal routing + internal_routing_flag = false; + } else if (!is_in_trans(s)) { + // do nothing, return config of enable_internal_transaction + internal_routing_flag = s.sm_->get_client_session()->is_proxy_enable_trans_internal_routing(); + } else { + internal_routing_flag = s.sm_->get_client_session()->is_proxy_enable_trans_internal_routing() && server_transaction_routing_flag; + } + return internal_routing_flag; +} + +inline int ObMysqlTransact::build_normal_login_request( ObTransState &s, ObIOBufferReader *&reader, int64_t &request_len) { int ret = OB_SUCCESS; @@ -2302,6 +2843,9 @@ inline int ObMysqlTransact::build_normal_login_request( int ObMysqlTransact::build_server_request(ObTransState &s, ObIOBufferReader *&reader, int64_t &request_len) { int ret = OB_SUCCESS; + LOG_DEBUG("[ObMysqlTransact::build_server_request] checking sending sql", + "cur_send_action", ObMysqlTransact::get_send_action_name(s.current_.send_action_), K(s.trans_info_.get_print_sql()), K(is_in_trans(s)), + K(s.sm_->get_client_session()->get_cs_id())); ObIOBufferReader *client_buffer_reader = NULL; BuildFunc build_func = NULL; reader = NULL; @@ -2349,7 +2893,9 @@ int ObMysqlTransact::build_server_request(ObTransState &s, ObIOBufferReader *&re } case SERVER_SEND_SAVED_LOGIN: - if (s.sm_->client_session_->get_session_info().is_oceanbase_server()) { + if (is_binlog_request(s)) { + build_func = ObMysqlRequestBuilder::build_binlog_login_packet; + } else if (s.sm_->client_session_->get_session_info().is_oceanbase_server()) { // write the buffor using saved login packet directly build_func = ObMysqlRequestBuilder::build_saved_login_packet; } else { @@ -2370,14 +2916,18 @@ int ObMysqlTransact::build_server_request(ObTransState &s, ObIOBufferReader *&re case SERVER_SEND_SESSION_VARS: build_func = ObMysqlRequestBuilder::build_session_vars_sync_packet; break; - - case SERVER_SEND_LAST_INSERT_ID: - build_func = ObMysqlRequestBuilder::build_last_insert_id_sync_packet; + + case SERVER_SEND_SESSION_USER_VARS: + build_func = ObMysqlRequestBuilder::build_session_user_vars_sync_packet; break; case SERVER_SEND_START_TRANS: build_func = ObMysqlRequestBuilder::build_start_trans_request; break; + + case SERVER_SEND_XA_START: + build_func = ObMysqlRequestBuilder::build_xa_start_request; + break; case SERVER_SEND_PREPARE: build_func = ObMysqlRequestBuilder::build_prepare_request; @@ -2409,15 +2959,13 @@ int ObMysqlTransact::build_server_request(ObTransState &s, ObIOBufferReader *&re } else { ObMysqlClientSession *client_session = s.sm_->get_client_session(); ObMysqlServerSession *server_session = s.sm_->get_server_session(); - ObProxyProtocol ob_proxy_protocol = s.sm_->use_compression_protocol(); + ObProxyProtocol ob_proxy_protocol = s.sm_->get_server_session_protocol(); if (OB_ISNULL(client_session) || OB_ISNULL(server_session)) { ret = OB_ERR_SYS; LOG_WARN("[ObMysqlTransact::build_server_request] invalid internal variables", K(client_session), K(server_session)); - } else if (OB_FAIL(build_func(*write_buffer, - client_session->get_session_info(), - server_session, - ob_proxy_protocol))) { + } else if (OB_FAIL(build_func(s.sm_, *write_buffer, client_session->get_session_info(), + server_session, ob_proxy_protocol))) { LOG_WARN("[ObMysqlTransact::build_server_request] fail to build packet," " will disconnect", "sm_id", s.sm_->sm_id_, "action_name", get_send_action_name(s.current_.send_action_), K(ret)); @@ -2483,10 +3031,11 @@ inline int ObMysqlTransact::do_handle_prepare_response(ObTransState &s, ObIOBuff int ret = OB_SUCCESS; //into here, the first packet must received completely - ObProxyProtocol ob_proxy_protocol = s.sm_->use_compression_protocol(); + ObProxyProtocol ob_proxy_protocol = s.sm_->get_server_session_protocol(); ObMysqlResp &server_response = s.trans_info_.server_response_; - if (!server_response.get_analyze_result().is_decompressed() && - (PROTOCOL_CHECKSUM == ob_proxy_protocol || PROTOCOL_OB20 == ob_proxy_protocol)) { + if (!server_response.get_analyze_result().is_decompressed() + && (ObProxyProtocol::PROTOCOL_CHECKSUM == ob_proxy_protocol + || ObProxyProtocol::PROTOCOL_OB20 == ob_proxy_protocol)) { ObMysqlCompressedOB20AnalyzeResult result; ObMysqlCompressAnalyzer *compress_analyzer = &s.sm_->get_compress_analyzer(); compress_analyzer->reset(); @@ -2532,7 +3081,7 @@ inline int ObMysqlTransact::do_handle_prepare_succ(ObTransState &s, uint32_t ser ObClientSessionInfo &cs_info = get_client_session_info(s); ObServerSessionInfo &ss_info = get_server_session_info(s); - uint32_t client_ps_id = cs_info.get_client_ps_id(); + uint32_t client_ps_id = s.is_hold_xa_start_? cs_info.get_xa_start_ps_id() : cs_info.get_client_ps_id(); ObPsIdPair *ps_id_pair = ss_info.get_ps_id_pair(client_ps_id); /* here two case: * if first in: @@ -2621,7 +3170,7 @@ inline int ObMysqlTransact::do_handle_execute_succ(ObTransState &s) ObClientSessionInfo &cs_info = get_client_session_info(s); ObServerSessionInfo &ss_info = get_server_session_info(s); - uint32_t client_ps_id = cs_info.get_client_ps_id(); + uint32_t client_ps_id = s.is_hold_xa_start_? cs_info.get_xa_start_ps_id() : cs_info.get_client_ps_id(); ObPsIdPair *ps_id_pair = ss_info.get_ps_id_pair(client_ps_id); ObCursorIdPair *cursor_id_pair = ss_info.get_curosr_id_pair(client_ps_id); if (OB_ISNULL(ps_id_pair)) { @@ -2671,6 +3220,79 @@ inline int ObMysqlTransact::do_handle_execute_succ(ObTransState &s) return ret; } +inline int ObMysqlTransact::do_handle_prepare_execute_xa_succ(ObIOBufferReader &buf_reader) { + int ret = OB_SUCCESS; + int64_t offset = 0; + int64_t content_len = 0; + uint8_t seq = 0; + ObMysqlPacketReader pkt_reader; + ObNewRow row; + ObSMRow sm_row(BINARY, row); + OMPKRow row_pkt(sm_row); + OMPKPrepareExecute prepare_execute_pkt; + int32_t eof_count_before_result_set = 0; + // read prepare execute resp + if (OB_FAIL(pkt_reader.get_packet(buf_reader, prepare_execute_pkt))) { + LOG_WARN("fail to get prepare execute resp of xa start", K(ret)); + } else if (prepare_execute_pkt.get_column_num() > 0 && FALSE_IT(++eof_count_before_result_set)) { + } else if (prepare_execute_pkt.get_param_num() > 0 && FALSE_IT(++eof_count_before_result_set)) { + } else { + LOG_DEBUG("succ to get eof count of resp of xa start sync", K(eof_count_before_result_set)); + } + + int32_t eof_count = 0; + // num-param * coldef & eof & one row coldef & eof + while (OB_SUCC(ret) && eof_count < eof_count_before_result_set) { + bool is_eof = false; + if (OB_FAIL(pkt_reader.is_eof_packet(buf_reader, offset, is_eof))) { + LOG_WARN("fail test eof of resp of xa start sync", K(ret)); + } else if (OB_FAIL(pkt_reader.get_content_len_and_seq(buf_reader, offset, content_len, seq))) { + LOG_WARN("fail to read packet len and seq of resp of xa start sync", K(ret)); + } else { + offset += content_len + MYSQL_NET_HEADER_LENGTH; + } + if (is_eof) { + ++eof_count; + LOG_DEBUG("succ to read eof of resp of xa start sync", K(eof_count)); + } + } + + // read ProtocolBinary::ResultsetRow + if (OB_SUCC(ret)) { + if (OB_FAIL(pkt_reader.get_packet(buf_reader, offset, row_pkt))) { + LOG_WARN("fail to get result set row packet of resp of xa start sync", K(ret)); + } else { + // 0a 00 00 08 00 00 00 00 00 00 00 00 00 00 + // ^^^^^^^^^^^ header + // ^^ packet header + // ^^ bitmap + // ^^^^^^^^^^^^^^^^^^^^^^^ long/int(8/4bytes) + const char *content_buf = row_pkt.get_cdata(); + int64_t content_len = row_pkt.get_clen(); + int8_t pkt_hdr = -1; + int8_t bitmap = -1; + int32_t xa_result = -1; + if (OB_FAIL(ObMysqlPacketUtil::get_int1(content_buf, content_len, pkt_hdr))) { + LOG_WARN("fail to get pkt hdr from row packet of resp of xa start sync", K(ret)); + } else if (OB_FAIL(ObMysqlPacketUtil::get_int1(content_buf, content_len, bitmap))) { + LOG_WARN("fail to get bitmap from row packet of resp of xa start sync", K(ret)); + } else if (OB_UNLIKELY(pkt_hdr != 0x00)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("wrong result set row pkt hdr of resp of xa start sync", K(ret), K(pkt_hdr)); + } else if (OB_FAIL(ObMysqlPacketUtil::get_int4(content_buf, content_len, xa_result))) { + LOG_WARN("fail to get xa result of resp of xa start sync", K(ret)); + } else if (OB_UNLIKELY(xa_result != 0)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to sync xa start", K(xa_result), K(ret)); + } else { + LOG_DEBUG("succ to sync xa start"); + } + } + } + + return ret; +} + inline void ObMysqlTransact::handle_execute_succ(ObTransState &s) { int ret = OB_SUCCESS; @@ -2716,11 +3338,12 @@ inline void ObMysqlTransact::handle_prepare_execute_succ(ObTransState &s) } else if (OB_FAIL(do_handle_prepare_succ(s, server_ps_id))) { LOG_WARN("fail to do handle prepare succ", K(ret)); } - if (OB_SUCC(ret) && s.trans_info_.server_response_.get_analyze_result().is_resultset_resp()) { if (OB_FAIL(do_handle_execute_succ(s))) { LOG_WARN("fail to do handle execute succ", K(ret)); - } + } else if (s.is_hold_xa_start_ && OB_FAIL(do_handle_prepare_execute_xa_succ(*buf_reader))) { + LOG_WARN("fail to do handle prepare execute xa succ", K(ret)); + } else {} } } @@ -2732,11 +3355,29 @@ inline void ObMysqlTransact::handle_prepare_execute_succ(ObTransState &s) void ObMysqlTransact::handle_text_ps_prepare_succ(ObTransState &s) { int ret = OB_SUCCESS; - if (NULL != s.sm_->client_session_) { - ObClientSessionInfo &cs_info = get_client_session_info(s); - ObServerSessionInfo &ss_info = get_server_session_info(s); - if (OB_FAIL(ss_info.add_text_ps_name(cs_info.get_text_ps_entry()->get_version()))) { - LOG_WARN("add text ps name failed", K(ret)); + ObMysqlServerSession *ss = s.sm_->get_server_session(); + ObClientSessionInfo &cs_info = get_client_session_info(s); + ObServerSessionInfo &ss_info = get_server_session_info(s); + uint32_t ps_id = cs_info.get_client_ps_id(); + if (OB_FAIL(ss_info.set_text_ps_version(ps_id))) { + LOG_WARN("add text ps name failed", K(ret)); + } else { + const sockaddr &addr = ss->get_netvc()->get_remote_addr(); + ObPsIdAddrs *ps_id_addrs = cs_info.get_ps_id_addrs(ps_id); + if (NULL == ps_id_addrs) { + if (OB_FAIL(ObPsIdAddrs::alloc_ps_id_addrs(ps_id, addr, ps_id_addrs))) { + LOG_WARN("fail to alloc ps id addrs", K(ps_id), K(ret)); + } else if (OB_ISNULL(ps_id_addrs)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("ps_id_addrs is null", K(ps_id_addrs), K(ret)); + } else if (OB_FAIL(cs_info.add_ps_id_addrs(ps_id_addrs))) { + LOG_WARN("fail to add ps_id_addrs", KPC(ps_id_addrs), K(ret)); + ps_id_addrs->destroy(); + } + } else { + if (OB_FAIL(ps_id_addrs->add_addr(addr))) { + LOG_WARN("fail to add addr into ps_id_addrs", "addr", ObIpEndpoint(addr), K(ret)); + } } } @@ -2745,6 +3386,52 @@ void ObMysqlTransact::handle_text_ps_prepare_succ(ObTransState &s) } } +int ObMysqlTransact::handle_ps_reset_succ(ObTransState &s, bool &is_user_request) +{ + int ret = OB_SUCCESS; + is_user_request = false; + + // clear cursor_id_pair + ObClientSessionInfo &cs_info = get_client_session_info(s); + ObMysqlServerSession *ss = s.sm_->get_server_session(); + ObServerSessionInfo &ss_info = get_server_session_info(s); + uint32_t client_ps_id = cs_info.get_client_ps_id(); + // delete it directly + ss_info.remove_cursor_id_pair(client_ps_id); + cs_info.remove_cursor_id_addr(client_ps_id); + cs_info.remove_piece_info(client_ps_id); + if (OB_FAIL(cs_info.remove_request_send_addr(ss->get_netvc()->get_remote_addr()))) { + LOG_WARN("fail to erase server addr", K(ret)); + } + + return ret; +} + +int ObMysqlTransact::handle_text_ps_drop_succ(ObTransState &s, bool &is_user_request) +{ + int ret = OB_SUCCESS; + is_user_request = false; + + // text_ps_drop can not handle session info in trim_ok_packet, handle here + ObClientSessionInfo &cs_info = get_client_session_info(s); + ObServerSessionInfo &ss_info = get_server_session_info(s); + uint32_t ps_id = cs_info.get_client_ps_id(); + ObMysqlServerSession *ss = s.sm_->get_server_session(); + if (OB_FAIL(cs_info.remove_request_send_addr(ss->get_netvc()->get_remote_addr()))) { + LOG_WARN("fail to erase server addr", K(ret)); + } else if (OB_FAIL(ss_info.remove_text_ps_version(ps_id))) { + LOG_WARN("fail to remove text ps id", K(ret)); + } else if (OB_FAIL(ObProxySessionInfoHandler::save_changed_sess_info(s.sm_->get_client_session()->get_session_info(), + s.sm_->get_server_session()->get_session_info(), + s.trans_info_.server_response_.get_analyze_result().get_extra_info(), + s.trace_log_, + false))) { + LOG_WARN("fail to save changed session info", K(get_send_action_name(s.current_.send_action_))); + s.current_.state_ = INTERNAL_ERROR; + } + return ret; +} + /* Oceanbase: * user var: no need handle here. handle it in save_changed_session_info * sys var: if exist in comomn_sys, update it; otherwise, update sys @@ -2752,15 +3439,16 @@ void ObMysqlTransact::handle_text_ps_prepare_succ(ObTransState &s) * use var: save it when get OK Response * sys var: if exist in comomn_sys, update it; otherwise, update sys */ -inline void ObMysqlTransact::handle_user_request_succ(ObTransState &s) +inline void ObMysqlTransact::handle_user_request_succ(ObTransState &s, bool &is_user_request) { int ret = OB_SUCCESS; + is_user_request = true; - ObClientSessionInfo &client_info = get_client_session_info(s); + ObClientSessionInfo& client_info = get_client_session_info(s); + ObProxyMysqlRequest& client_request = s.trans_info_.client_request_; if (client_info.is_sharding_user() && !client_info.is_oceanbase_server()) { - ObSqlParseResult &sql_result = s.trans_info_.client_request_.get_parse_result(); - const ObProxyBasicStmtType type = sql_result.get_stmt_type(); + const ObProxyBasicStmtType type = client_request.get_parse_result().get_stmt_type(); if (OBPROXY_T_SET == type && OB_FAIL(handle_user_set_request_succ(s))) { LOG_WARN("fail to handle user set request", K(ret)); @@ -2769,9 +3457,25 @@ inline void ObMysqlTransact::handle_user_request_succ(ObTransState &s) } } - if (OB_SUCC(ret) && obmysql::OB_MYSQL_COM_CHANGE_USER == s.trans_info_.sql_cmd_) { - if (OB_FAIL(handle_change_user_request_succ(s))) { - LOG_WARN("fail to handle change user request", K(ret)); + if (OB_SUCC(ret)) { + if (obmysql::OB_MYSQL_COM_CHANGE_USER == s.trans_info_.sql_cmd_) { + if (OB_FAIL(handle_change_user_request_succ(s))) { + LOG_WARN("fail to handle change user request", K(ret)); + } + } else if (obmysql::OB_MYSQL_COM_RESET_CONNECTION == s.trans_info_.sql_cmd_) { + if (OB_FAIL(handle_reset_connection_request_succ(s))) { + LOG_WARN("fail to handle reset connection request on success", K(ret)); + } + } else if (obmysql::OB_MYSQL_COM_STMT_RESET == s.trans_info_.sql_cmd_) { + if (OB_FAIL(handle_ps_reset_succ(s, is_user_request))) { + LOG_WARN("fail to handle ps reset request", K(ret)); + } + } else if (client_request.get_parse_result().is_text_ps_drop_stmt()) { + if (OB_FAIL(handle_text_ps_drop_succ(s, is_user_request))) { + LOG_WARN("fail to handle text ps drop request", K(ret)); + } + } else if (client_request.get_parse_result().is_text_ps_prepare_stmt()) { + handle_text_ps_prepare_succ(s); } } @@ -2815,12 +3519,7 @@ inline int ObMysqlTransact::handle_change_user_request_succ(ObTransState &s) * The above three version number synchronization has been processed in save_changed_session_info, no need to process it anymore */ - // 2. Clean up user variables - if (OB_FAIL(client_info.remove_all_user_variable())) { - LOG_WARN("remove all user variable failed", K(ret)); - } - - // 3. Update auth_str + // 2. update auth_str if (OB_SUCC(ret)) { const ObString full_username = client_info.get_full_username(); ObMysqlServerSession* server_session = s.sm_->get_server_session(); @@ -2834,10 +3533,11 @@ inline int ObMysqlTransact::handle_change_user_request_succ(ObTransState &s) } } - // 4. Clear all server sessions - if (OB_SUCC(ret)) { - ObMysqlClientSession* client_session = s.sm_->get_client_session(); - client_session->get_session_manager().purge_keepalives(); + // 3. clear session related source + // 4. clear all server session, reconnect if needed + if (OB_SUCC(ret) + && OB_FAIL(clear_session_related_source(s))) { + LOG_WARN("fail to clear session related source", K(ret)); } } } @@ -2847,6 +3547,56 @@ inline int ObMysqlTransact::handle_change_user_request_succ(ObTransState &s) return ret; } +int ObMysqlTransact::handle_reset_connection_request_succ(ObTransState &s) +{ + int ret = OB_SUCCESS; + + // clear session related source + // clear all server session, reconnect if needed + if (OB_FAIL(clear_session_related_source(s))) { + LOG_WARN("fail to clear session related source", K(ret)); + } + + return ret; +} + +// clear after OB_MYSQL_COM_RESET_CONNECTION / OB_MYSQL_COM_CHANGE_USR +int ObMysqlTransact::clear_session_related_source(ObTransState &s) +{ + int ret = OB_SUCCESS; + + ObClientSessionInfo &client_info = get_client_session_info(s); + ObServerSessionInfo &server_info = get_server_session_info(s); + + // reset user variable + if (OB_FAIL(client_info.remove_all_user_variable())) { + LOG_WARN("fail to remove all user variables", K(ret)); + } else { + // reset session state, including rollback any open transaction, reset transaction isolation level + // reset session variables, delete user variables, remove prepare statement + client_info.destroy_ps_id_entry_map(); + client_info.destroy_ps_id_addrs_map(); + client_info.destroy_cursor_id_addr_map(); + client_info.destroy_piece_info_map(); + client_info.destroy_text_ps_name_entry_map(); + + // server session + server_info.destroy_ps_id_pair_map(); + server_info.destroy_cursor_id_pair_map(); + server_info.reuse_text_ps_version_set(); + + // close other server sessions, avoid to send every server session, reconnect if needed + ObMysqlClientSession *client_session = s.sm_->get_client_session(); + if (OB_NOT_NULL(client_session)) { + client_session->get_session_manager().purge_keepalives(); + } + + LOG_DEBUG("succ to clear session related source"); + } + + return ret; +} + inline int ObMysqlTransact::handle_user_set_request_succ(ObTransState &s) { int ret = OB_SUCCESS; @@ -2857,46 +3607,45 @@ inline int ObMysqlTransact::handle_user_set_request_succ(ObTransState &s) ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid session, client session is NULL"); } else if (OB_LIKELY(set_info.node_count_ > 0)) { - ObClientSessionInfo &client_info = get_client_session_info(s); for (int i = 0; OB_SUCC(ret) && i < set_info.node_count_; i++) { - SetVarNode &var_node = set_info.var_nodes_.at(i); + SetVarNode* var_node = set_info.var_nodes_.at(i); ObObj value; - if (SET_VALUE_TYPE_INT == var_node.value_type_) { - value.set_int(var_node.int_value_); - } else if (SET_VALUE_TYPE_NUMBER == var_node.value_type_) { - const char *nptr = var_node.str_value_.buf_; + if (SET_VALUE_TYPE_INT == var_node->value_type_) { + value.set_int(var_node->int_value_); + } else if (SET_VALUE_TYPE_NUMBER == var_node->value_type_) { + const char *nptr = var_node->str_value_.ptr(); char *end_ptr = NULL; double double_val = strtod(nptr, &end_ptr); if (*nptr != '\0' && *end_ptr == '\0') { value.set_double(double_val); } else { - OBLOG_LOG(WARN, "invalid double value", "str", var_node.str_value_.string_); - value.set_varchar(var_node.str_value_.string_); + OBLOG_LOG(WARN, "invalid double value", "str", var_node->str_value_); + value.set_varchar(var_node->str_value_.config_string_); } } else { - if (0 == var_node.var_name_.string_.case_compare("character_set_results") - && 0 == var_node.str_value_.string_.case_compare("NULL")) { + if (0 == var_node->var_name_.config_string_.case_compare("character_set_results") + && 0 == var_node->str_value_.config_string_.case_compare("NULL")) { value.set_varchar(ObString::make_empty_string()); } else { - value.set_varchar(var_node.str_value_.string_); + value.set_varchar(var_node->str_value_.config_string_); } } // TODO: if not exist, insert; otherwise, cmp and update - if (SET_VAR_USER == var_node.var_type_) { - if (OB_FAIL(client_info.replace_user_variable(var_node.var_name_.string_, + if (SET_VAR_USER == var_node->var_type_) { + if (OB_FAIL(client_info.replace_user_variable(var_node->var_name_.config_string_, value))) { - LOG_WARN("fail to replace user variable", K(var_node), K(ret)); + LOG_WARN("fail to replace user variable", KPC(var_node), K(ret)); } else { - LOG_DEBUG("succ to update user variables", "key", var_node.var_name_.string_, K(value)); + LOG_DEBUG("succ to update user variables", "key", var_node->var_name_, K(value)); } - } else if (SET_VAR_SYS == var_node.var_type_) { - if (OB_FAIL(client_info.update_common_sys_variable(var_node.var_name_.string_, + } else if (SET_VAR_SYS == var_node->var_type_) { + if (OB_FAIL(client_info.update_common_sys_variable(var_node->var_name_.config_string_, value, true, false))) { - LOG_WARN("fail to update common sys variable", K(var_node), K(ret)); + LOG_WARN("fail to update common sys variable", KPC(var_node), K(ret)); } else { - LOG_DEBUG("succ to update common sys variables", "key", var_node.var_name_.string_, K(value)); + LOG_DEBUG("succ to update common sys variables", "key", var_node->var_name_.config_string_, K(value)); } } } @@ -3052,14 +3801,21 @@ inline void ObMysqlTransact::handle_use_db_succ(ObTransState &s) } } -void ObMysqlTransact::handle_error_resp(ObTransState &s) +void ObMysqlTransact::handle_error_resp(ObTransState &s, bool &is_user_request) { ObRespAnalyzeResult &resp = s.trans_info_.server_response_.get_analyze_result(); - bool is_user_request = false; + ObProxyMysqlRequest& client_request = s.trans_info_.client_request_; + is_user_request = false; int64_t max_connect_attempts = get_max_connect_attempts(s); ObServerStateType pre_state = s.current_.state_; s.current_.state_ = RESPONSE_ERROR; + s.trace_log_.log_it("[get_error]", "code", resp.error_pkt_.get_err_code(), "trace_id", resp.server_trace_id_); + if (resp.is_mysql_wrong_arguments_error() + || resp.is_trans_free_route_not_supported_error() + || resp.is_internal_error()) { + LOG_WARN("trace_log", K(s.trace_log_)); + } switch(s.current_.send_action_) { case SERVER_SEND_HANDSHAKE: if (!s.sm_->client_session_->get_session_info().is_oceanbase_server()) { @@ -3187,16 +3943,30 @@ void ObMysqlTransact::handle_error_resp(ObTransState &s) K(cached_request_packet_len), K(total_request_packet_len), "sql", s.trans_info_.client_request_.get_print_sql(), K(resp)); } - if (resp.is_ora_fatal_error()) { + + // Because the RESET request is to be sent to the specified Server, + // if an error occurs in the execution of the Server, an error packet is returned directly + if (obmysql::OB_MYSQL_COM_STMT_RESET == s.trans_info_.sql_cmd_ || + s.trans_info_.client_request_.get_parse_result().is_text_ps_drop_stmt()) { + if (OB_SUCCESS != s.sm_->get_client_buffer_reader()->consume_all()) { + s.current_.state_ = INTERNAL_ERROR; + LOG_WARN("fail to consume client buffer reader", "state", s.current_.state_); + } else { + is_user_request = true; + } + } else if (resp.is_trans_free_route_not_supported_error()) { + s.current_.error_type_ = TRANS_FREE_ROUTE_NOT_SUPPORTED_ERROR; + } else if (resp.is_ora_fatal_error()) { s.current_.error_type_ = ORA_FATAL_ERROR; } else if (resp.is_standby_weak_readonly_error() && s.sm_->sm_cluster_resource_->is_deleting() && OB_DEFAULT_CLUSTER_ID == s.sm_->sm_cluster_resource_->get_cluster_id()) { // if primary switchover, need disconnection when get STANDBY_WEAK_READONLY_ERROR error s.current_.error_type_ = STANDBY_WEAK_READONLY_ERROR; - } else if (s.is_trans_first_request_ - && !s.trans_info_.client_request_.is_large_request() - && (total_request_packet_len == cached_request_packet_len)) { + } else if ((s.is_trans_first_request_ + || (ObMysqlTransact::is_in_trans(s) && s.sm_->get_client_session()->is_trans_internal_routing())) + && !s.trans_info_.client_request_.is_large_request() + && (total_request_packet_len == cached_request_packet_len)) { if (resp.is_reroute_error()) { s.current_.error_type_ = REQUEST_REROUTE_ERROR; // if all attempts were failed, we should transfer the error pkt to client finally @@ -3230,11 +4000,16 @@ void ObMysqlTransact::handle_error_resp(ObTransState &s) uint32_t client_ps_id = cs_info.get_client_ps_id(); cs_info.remove_ps_id_entry(client_ps_id); } + if (is_user_request && client_request.get_parse_result().is_text_ps_prepare_stmt()) { + ObClientSessionInfo &cs_info = get_client_session_info(s); + ObString text_ps_name = client_request.get_parse_result().get_text_ps_name(); + cs_info.delete_text_ps_name_entry(text_ps_name); + } break; } case SERVER_SEND_ALL_SESSION_VARS: case SERVER_SEND_SESSION_VARS: - case SERVER_SEND_LAST_INSERT_ID: + case SERVER_SEND_SESSION_USER_VARS: s.current_.error_type_ = RESET_SESSION_VARS_COMMON_ERROR; break; @@ -3245,6 +4020,11 @@ void ObMysqlTransact::handle_error_resp(ObTransState &s) case SERVER_SEND_START_TRANS: s.current_.error_type_ = START_TRANS_COMMON_ERROR; break; + + case SERVER_SEND_XA_START: + LOG_DEBUG("[ObMysqlTransact::handle_error_resp] xa start resp error"); + s.current_.error_type_ = START_XA_START_ERROR; + break; case SERVER_SEND_PREPARE: s.current_.error_type_ = SYNC_PREPARE_COMMON_ERROR; @@ -3332,6 +4112,8 @@ void ObMysqlTransact::handle_error_resp(ObTransState &s) } s.is_rerouted_ = true; } + } else if (TRANS_FREE_ROUTE_NOT_SUPPORTED_ERROR == s.current_.error_type_) { + s.is_rerouted_ = true; } @@ -3372,7 +4154,7 @@ void ObMysqlTransact::handle_error_resp(ObTransState &s) } } -inline void ObMysqlTransact::handle_resultset_resp(ObTransState &s) +inline void ObMysqlTransact::handle_resultset_resp(ObTransState &s, bool &is_user_request) { if (OB_UNLIKELY(obmysql::OB_MYSQL_COM_STMT_PREPARE == s.trans_info_.sql_cmd_ || SERVER_SEND_PREPARE == s.current_.send_action_)) { @@ -3384,17 +4166,27 @@ inline void ObMysqlTransact::handle_resultset_resp(ObTransState &s) } // consume response of non-user request + if (OB_UNLIKELY(SERVER_SEND_XA_START == s.current_.send_action_)) { + if (s.sm_->get_client_session()->is_proxy_enable_trans_internal_routing()) { + record_trans_state(s, true); + } + LOG_DEBUG("[ObMysqlTransact::handle_resultset_resp] reset xa start flag s.is_hold_xa_start_"); + s.is_hold_xa_start_ = false; + } if (OB_UNLIKELY(SERVER_SEND_REQUEST != s.current_.send_action_)) { //LOG_WARN("handle_resultset_resp, not expected"); consume_response_packet(s); + is_user_request = false; + } else { + is_user_request = true; } } -inline void ObMysqlTransact::handle_ok_resp(ObTransState &s) +inline void ObMysqlTransact::handle_ok_resp(ObTransState &s, bool &is_user_request) { int ret = OB_SUCCESS; // in fact, we handle ok, eof, resultset and other responses in this function - bool is_user_request = false; + is_user_request = false; if (NULL != s.sm_->client_session_ && NULL != s.sm_->get_server_session()) { ObClientSessionInfo &client_info = get_client_session_info(s); @@ -3405,8 +4197,7 @@ inline void ObMysqlTransact::handle_ok_resp(ObTransState &s) is_user_request = true; break; case SERVER_SEND_REQUEST: - handle_user_request_succ(s); - is_user_request = true; + handle_user_request_succ(s, is_user_request); break; case SERVER_SEND_SAVED_LOGIN: @@ -3415,6 +4206,7 @@ inline void ObMysqlTransact::handle_ok_resp(ObTransState &s) case SERVER_SEND_ALL_SESSION_VARS: case SERVER_SEND_SESSION_VARS: + case SERVER_SEND_SESSION_USER_VARS: ObProxySessionInfoHandler::assign_session_vars_version(client_info, server_info); // send session var function will send last_insert_id in passing ObProxySessionInfoHandler::assign_last_insert_id_version(client_info, server_info); @@ -3426,12 +4218,9 @@ inline void ObMysqlTransact::handle_ok_resp(ObTransState &s) handle_use_db_succ(s); break; - case SERVER_SEND_LAST_INSERT_ID: - ObProxySessionInfoHandler::assign_last_insert_id_version(client_info, server_info); - break; - case SERVER_SEND_START_TRANS: // reset hold start trans flag if receive ok packet + LOG_DEBUG("sync session info from the ok packet of the sql `begin`"); s.is_hold_start_trans_ = false; break; @@ -3449,28 +4238,35 @@ inline void ObMysqlTransact::handle_ok_resp(ObTransState &s) K(client_info), K(server_info)); break; } + + // due to server may retrun reroute error in internal routing trans + // internal routing trans allow to record transaction state after begin statement + if (s.current_.send_action_ == SERVER_SEND_START_TRANS && s.sm_->get_client_session()->is_proxy_enable_trans_internal_routing()) { + record_trans_state(s, true); + } } - if (obmysql::OB_MYSQL_COM_STMT_SEND_PIECE_DATA == s.trans_info_.sql_cmd_) { - ObPieceInfo *info = NULL; - ObClientSessionInfo &cs_info = get_client_session_info(s); - if (OB_FAIL(cs_info.get_piece_info(info))) { - if (OB_HASH_NOT_EXIST == ret) { - if (OB_ISNULL(info = op_alloc(ObPieceInfo))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - PROXY_API_LOG(ERROR, "fail to allocate memory for piece info", K(ret)); - } else { - info->set_ps_id(cs_info.get_client_ps_id()); - info->set_addr(s.sm_->get_server_session()->get_netvc()->get_remote_addr()); - if (OB_FAIL(cs_info.add_piece_info(info))) { - PROXY_API_LOG(WARN, "fail to add piece info", K(ret)); - op_free(info); - info = NULL; + if (OB_SUCC(ret)) { + if (obmysql::OB_MYSQL_COM_STMT_SEND_PIECE_DATA == s.trans_info_.sql_cmd_) { + ObPieceInfo *info = NULL; + ObClientSessionInfo &cs_info = get_client_session_info(s); + if (OB_FAIL(cs_info.get_piece_info(info))) { + if (OB_HASH_NOT_EXIST == ret) { + if (OB_ISNULL(info = op_alloc(ObPieceInfo))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + PROXY_API_LOG(ERROR, "fail to allocate memory for piece info", K(ret)); + } else { + info->set_ps_id(cs_info.get_client_ps_id()); + info->set_addr(s.sm_->get_server_session()->get_netvc()->get_remote_addr()); + if (OB_FAIL(cs_info.add_piece_info(info))) { + PROXY_API_LOG(WARN, "fail to add piece info", K(ret)); + op_free(info); + info = NULL; + } } } } } - if (OB_FAIL(ret)) { s.current_.state_ = INTERNAL_ERROR; LOG_WARN("add piece info failed", K(ret)); @@ -3493,57 +4289,70 @@ inline void ObMysqlTransact::handle_handshake_pkt(ObTransState &s) if (OB_LIKELY(NULL != client_session) && OB_LIKELY(SERVER_SEND_HANDSHAKE == s.current_.send_action_) && OB_LIKELY(NULL != server_session)) { - ObRespAnalyzeResult &result = s.trans_info_.server_response_.get_analyze_result(); - - uint32_t conn_id = 0; - //use connection id from OMPKHandshakeResponse Packet when the follow happened - //1. proxy_mysql_client - //2. client service mode - //3. mysql routing mode - if (client_session->is_proxy_mysql_client_ - || OB_CLIENT_SERVICE_MODE == s.mysql_config_params_->proxy_service_mode_ - || s.mysql_config_params_->is_mysql_routing_mode()) { - conn_id = result.get_connection_id(); - } else { - //if use server service mode, connection id is equal to cs_id - conn_id = client_session->get_cs_id(); - } - server_session->set_server_sessid(conn_id); - ObMySQLCapabilityFlags capability(result.get_server_capability()); - server_session->get_session_info().save_compatible_capability_flags(capability); - ObAddr client_addr = client_session->get_real_client_addr(const_cast(server_session->get_netvc())); - - //we need update proxy_sessid when first connect server - if (0 == client_session->get_proxy_sessid()) { - client_session->set_proxy_sessid(ObMysqlClientSession::get_next_proxy_sessid()); - LOG_INFO("succ to set proxy_sessid", "cs_id", client_session->get_cs_id(), - "proxy_sessid", client_session->get_proxy_sessid(), - "server_ip", server_session->server_ip_, - "ss_id", server_session->ss_id_, - "server_sessid", conn_id, - "is_proxy_mysql_client", client_session->is_proxy_mysql_client_, - "ss_fd", server_session->get_netvc()->get_conn_fd(), - K(client_addr)); - } - LOG_DEBUG("succ to fill conn id for server session", K(conn_id), - "ss_id", server_session->ss_id_, - "cs_id", client_session->get_cs_id(), - "proxy_sessid", client_session->get_proxy_sessid(), - "is_proxy_mysql_client", client_session->is_proxy_mysql_client_, - K(client_addr)); - - if (s.mysql_config_params_->enable_client_ip_checkout_) { - if (OB_UNLIKELY(!client_addr.is_valid())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("real client add is invalid, it should not happened", K(client_addr), K(ret)); + // for probing SQL + if (client_session->get_session_info().get_priv_info().user_name_ == ObProxyTableInfo::DETECT_USERNAME_USER) { + // Simulate the return of ERROR messages + LOG_DEBUG("get handshake from detect server success"); + s.mysql_errcode_ = OB_NOT_SUPPORTED; + s.mysql_errmsg_ = "not supported, bad route request"; + if (OB_FAIL(ObMysqlTransact::build_error_packet(s, client_session))) { + LOG_WARN("fail to encode err packet buf", K(ret)); } + ret = OB_NOT_SUPPORTED; } else { - client_addr.reset(); - } - if (OB_SUCC(ret)) { - if (s.sm_->client_session_->get_session_info().is_oceanbase_server()) { - if (OB_FAIL(handle_oceanbase_handshake_pkt(s, conn_id, client_addr))) { - LOG_WARN("fail to handle oceanbase handshke pkt", K(conn_id), K(client_addr), K(ret)); + ObRespAnalyzeResult &result = s.trans_info_.server_response_.get_analyze_result(); + + uint32_t conn_id = 0; + //use connection id from OMPKHandshakeResponse Packet when the follow happened + //1. proxy_mysql_client + //2. client service mode + //3. mysql routing mode + if (client_session->is_proxy_mysql_client_ + || OB_CLIENT_SERVICE_MODE == s.mysql_config_params_->proxy_service_mode_ + || s.mysql_config_params_->is_mysql_routing_mode()) { + conn_id = result.get_connection_id(); + } else { + //if use server service mode, connection id is equal to cs_id + conn_id = client_session->get_cs_id(); + } + server_session->set_server_sessid(conn_id); + ObMySQLCapabilityFlags capability(result.get_server_capability()); + server_session->get_session_info().save_compatible_capability_flags(capability); + ObAddr client_addr = client_session->get_real_client_addr(const_cast(server_session->get_netvc())); + + //we need update proxy_sessid when first connect server + if (0 == client_session->get_proxy_sessid()) { + client_session->set_proxy_sessid(ObMysqlClientSession::get_next_proxy_sessid()); + LOG_INFO("succ to set proxy_sessid", "cs_id", client_session->get_cs_id(), + "proxy_sessid", client_session->get_proxy_sessid(), + "server_ip", server_session->server_ip_, + "ss_id", server_session->ss_id_, + "server_sessid", conn_id, + "is_proxy_mysql_client", client_session->is_proxy_mysql_client_, + "ss_fd", server_session->get_netvc()->get_conn_fd(), + K(client_addr)); + } + LOG_DEBUG("succ to fill conn id for server session", K(conn_id), + "ss_id", server_session->ss_id_, + "cs_id", client_session->get_cs_id(), + "proxy_sessid", client_session->get_proxy_sessid(), + "is_proxy_mysql_client", client_session->is_proxy_mysql_client_, + K(client_addr)); + s.trace_log_.log_it("[handshake]", "svr", s.server_info_.addr_, "svr_sessid", server_session->get_server_sessid()); + + if (s.mysql_config_params_->enable_client_ip_checkout_) { + if (OB_UNLIKELY(!client_addr.is_valid())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("real client add is invalid, it should not happened", K(client_addr), K(ret)); + } + } else { + client_addr.reset(); + } + if (OB_SUCC(ret)) { + if (s.sm_->client_session_->get_session_info().is_oceanbase_server()) { + if (OB_FAIL(handle_oceanbase_handshake_pkt(s, conn_id, client_addr))) { + LOG_WARN("fail to handle oceanbase handshke pkt", K(conn_id), K(client_addr), K(ret)); + } } } } @@ -3563,13 +4372,14 @@ inline int ObMysqlTransact::handle_oceanbase_handshake_pkt(ObTransState &s, uint // current proxy support use compress, and inner request also use compress bool use_compress = s.mysql_config_params_->enable_compression_protocol_; - bool use_ob_protocol_v2 = s.mysql_config_params_->enable_ob_protocol_v2_; - bool use_ssl = !s.sm_->client_session_->is_proxy_mysql_client_ + bool use_ob_protocol_v2 = s.sm_->is_enable_ob_protocol_v2(); + bool use_ssl = s.sm_->enable_server_ssl_ + && !s.sm_->client_session_->is_proxy_mysql_client_ && s.trans_info_.server_response_.get_analyze_result().support_ssl() - && get_global_ssl_config_table_processor().is_ssl_supported( - s.sm_->client_session_->get_vip_cluster_name(), + && get_global_ssl_config_table_processor().is_ssl_key_info_valid( s.sm_->client_session_->get_vip_cluster_name(), - false); + s.sm_->client_session_->get_vip_tenant_name()); + bool enable_client_ip_checkout = s.mysql_config_params_->enable_client_ip_checkout_; ObRespAnalyzeResult &result = s.trans_info_.server_response_.get_analyze_result(); const ObString &server_scramble = result.get_scramble_string(); const ObString &proxy_scramble = client_session->get_scramble_string(); @@ -3598,7 +4408,8 @@ inline int ObMysqlTransact::handle_oceanbase_handshake_pkt(ObTransState &s, uint client_addr, use_compress, use_ob_protocol_v2, - use_ssl))) { + use_ssl, + enable_client_ip_checkout))) { LOG_WARN("fail to handle rewrite saved hrs pkt, INTERNAL_ERROR", K(ret)); } else { LOG_DEBUG("succ to rewrite saved hrs pkt"); @@ -3615,7 +4426,8 @@ inline int ObMysqlTransact::handle_oceanbase_handshake_pkt(ObTransState &s, uint client_addr, use_compress, use_ob_protocol_v2, - use_ssl))) { + use_ssl, + enable_client_ip_checkout))) { LOG_WARN("fail to handle rewrite first hrs pkt, INTERNAL_ERROR", K(ret)); } else { LOG_DEBUG("succ to rewrite first hrs pkt"); @@ -3685,24 +4497,39 @@ void ObMysqlTransact::handle_db_reset(ObTransState &s) inline void ObMysqlTransact::handle_first_response_packet(ObTransState &s) { ObRespAnalyzeResult &resp = s.trans_info_.server_response_.get_analyze_result(); - + bool is_user_request = false; // handle resp if (resp.is_resultset_resp()) { MYSQL_INCREMENT_TRANS_STAT(SERVER_RESULTSET_RESPONSES); - handle_resultset_resp(s); + handle_resultset_resp(s, is_user_request); } else if (resp.is_ok_resp()) { MYSQL_INCREMENT_TRANS_STAT(SERVER_OK_RESPONSES); - handle_ok_resp(s); + handle_ok_resp(s, is_user_request); } else if (resp.is_error_resp()) { MYSQL_INCREMENT_TRANS_STAT(SERVER_ERROR_RESPONSES); - handle_error_resp(s); + handle_error_resp(s, is_user_request); } else if (resp.is_handshake_pkt()) { MYSQL_INCREMENT_TRANS_STAT(SERVER_OTHER_RESPONSES); handle_handshake_pkt(s); } else { MYSQL_INCREMENT_TRANS_STAT(SERVER_OTHER_RESPONSES); - handle_ok_resp(s); + handle_ok_resp(s, is_user_request); + } + + if (s.current_.send_action_ != SERVER_SEND_SAVED_LOGIN + && s.current_.send_action_ != SERVER_SEND_HANDSHAKE + && !is_user_request) { + bool is_only_sync_trans_sess = resp.is_error_resp(); + if (OB_SUCCESS != ObProxySessionInfoHandler::save_changed_sess_info(s.sm_->get_client_session()->get_session_info(), + s.sm_->get_server_session()->get_session_info(), + resp.get_extra_info(), + s.trace_log_, + is_only_sync_trans_sess)) { + s.current_.state_ = INTERNAL_ERROR; + LOG_WARN("fail to save changed session info", K(get_send_action_name(s.current_.send_action_))); + } } + } inline ObServerSessionInfo &ObMysqlTransact::get_server_session_info(ObTransState &s) @@ -3751,7 +4578,7 @@ int ObMysqlTransact::build_no_privilege_message(ObTransState &trans_state, static_cast(user.length()), user.ptr(), client_ip); } trans_state.mysql_errmsg_ = err_msg; - if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state))) { + if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state, &client_session))) { LOG_WARN("fail to build err packet", K(ret)); } return ret; @@ -3807,7 +4634,7 @@ inline void ObMysqlTransact::update_trace_stat(ObTransState &s) trace_record->server_state_ = static_cast(s.current_.state_); trace_record->send_action_ = static_cast(s.current_.send_action_); trace_record->resp_error_ = static_cast(s.current_.error_type_); - trace_record->addr_.set_ipv4_addr(s.server_info_.get_ipv4(), s.server_info_.get_port()); + trace_record->addr_.set_sockaddr(s.server_info_.addr_.sa_); if (0 == trace_stats->last_trace_end_time_) { trace_record->cost_time_us_ = static_cast(hrtime_to_usec( milestone_diff(s.sm_->milestones_.pl_lookup_begin_, get_based_hrtime(s)))); @@ -3833,16 +4660,18 @@ void ObMysqlTransact::handle_oceanbase_server_resp_error(ObTransState &s, ObMySQ case REQUEST_CONNECT_ERROR: case REQUEST_SERVER_INIT_ERROR: case REQUEST_REROUTE_ERROR: - case REQUEST_SERVER_STOPPING_ERROR: { - // before retry send request, write the saved packet to client buffer - ObString req_pkt = s.trans_info_.client_request_.get_req_pkt(); - int64_t pkt_len = req_pkt.length(); + case REQUEST_SERVER_STOPPING_ERROR: + case TRANS_FREE_ROUTE_NOT_SUPPORTED_ERROR: { + // before retry send request, write the req packet back to client buffer ObIOBufferReader *client_reader = s.sm_->get_client_buffer_reader(); - int64_t written_len = 0; if (OB_ISNULL(client_reader)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("[ObMysqlTransact::handle_server_resp_error] client reader is NULL"); } else { + // rewrite request to client buffer in order to retry + ObString req_pkt = s.trans_info_.client_request_.get_req_pkt(); + int64_t pkt_len = req_pkt.length(); + int64_t written_len = 0; if (0 != client_reader->read_avail() || req_pkt.empty()) { ret = OB_INNER_STAT_ERROR; LOG_ERROR("[ObMysqlTransact::handle_server_resp_error] invalid internal state", @@ -3887,6 +4716,7 @@ void ObMysqlTransact::handle_oceanbase_server_resp_error(ObTransState &s, ObMySQ case SAVED_LOGIN_COMMON_ERROR: case RESET_SESSION_VARS_COMMON_ERROR: case START_TRANS_COMMON_ERROR: + case START_XA_START_ERROR: case SYNC_DATABASE_COMMON_ERROR: { //current server session is still ok s.sm_->clear_server_entry(); @@ -3894,6 +4724,7 @@ void ObMysqlTransact::handle_oceanbase_server_resp_error(ObTransState &s, ObMySQ break; } case SYNC_PREPARE_COMMON_ERROR: + case SYNC_TEXT_PS_PREPARE_COMMON_ERROR: // no need retry, just disconnect connection for sync_prepare_error handle_server_connection_break(s); break; @@ -3986,6 +4817,8 @@ inline void ObMysqlTransact::handle_response_from_server(ObTransState &s) // fall through case DEAD_CONGESTED: // fall through + case DETECT_CONGESTED: + // fall through case CONNECT_ERROR: { handle_retry_server_connection(s); break; @@ -4017,7 +4850,7 @@ inline void ObMysqlTransact::handle_response_from_server(ObTransState &s) "request_cmd", get_mysql_cmd_str(s.trans_info_.client_request_.get_packet_meta().cmd_), "sql_cmd", get_mysql_cmd_str(s.trans_info_.sql_cmd_), "sql", s.trans_info_.get_print_sql()); - } else { + } else if (s.need_retry_) { LOG_WARN("connection error", "server_state", ObMysqlTransact::get_server_state_name(s.current_.state_), "request_cmd", get_mysql_cmd_str(s.trans_info_.client_request_.get_packet_meta().cmd_), @@ -4046,13 +4879,16 @@ void ObMysqlTransact::handle_oceanbase_retry_server_connection(ObTransState &s) ObPieceInfo *info = NULL; ObSSRetryStatus retry_status = NO_NEED_RETRY; const int64_t max_connect_attempts = get_max_connect_attempts(s); + bool is_reroute_to_coordinator = false; ObIpEndpoint old_target_server; net::ops_ip_copy(old_target_server, s.server_info_.addr_.sa_); int64_t obproxy_route_addr = 0; + bool is_internal_routing = false; if (NULL != s.sm_ && NULL != s.sm_->client_session_) { obproxy_route_addr = s.sm_->client_session_->get_session_info().get_obproxy_route_addr(); + is_internal_routing = s.sm_->client_session_->is_trans_internal_routing(); } if (OB_FAIL(s.sm_->get_client_session()->get_session_info().get_piece_info(info))) { @@ -4064,13 +4900,20 @@ void ObMysqlTransact::handle_oceanbase_retry_server_connection(ObTransState &s) if (OB_UNLIKELY(s.mysql_config_params_->is_mysql_routing_mode())) { LOG_DEBUG("in mysql mode, no need retry, will disconnect"); retry_status = NO_NEED_RETRY; + } else if (OB_UNLIKELY(is_in_trans(s) + && s.sm_->get_client_session()->is_proxy_enable_trans_internal_routing() + && !s.sm_->get_client_session()->get_trans_coordinator_ss_addr().is_valid())) { + // check coordinator addr in transaction + LOG_WARN("coordinator add is invalid in transaction, no need retry"); + retry_status = NO_NEED_RETRY; + // we will update retry_status only the follow all happened - // 1. not in transaction + // 1. not in transaction / in internal routing tranaction // 2. attempts_ is less then max_connect_attempts // 3. is not kill query // 4. is not piece info - } else if (!is_in_trans(s) + } else if (s.need_retry_ && s.current_.attempts_ < max_connect_attempts && 0 == obproxy_route_addr && !s.trans_info_.client_request_.is_kill_query() @@ -4078,17 +4921,30 @@ void ObMysqlTransact::handle_oceanbase_retry_server_connection(ObTransState &s) && obmysql::OB_MYSQL_COM_STMT_GET_PIECE_DATA != s.trans_info_.sql_cmd_ && !second_in) { ++s.current_.attempts_; - LOG_DEBUG("start next retry"); - - if (s.pll_info_.is_force_renew()) { // force pl lookup - retry_status = NOT_FOUND_EXISTING_ADDR; - } else if (REQUEST_REROUTE_ERROR == s.current_.error_type_) { - retry_status = FOUND_EXISTING_ADDR; - net::ops_ip_copy(s.server_info_.addr_, s.reroute_info_.replica_.server_.get_ipv4(), - static_cast(s.reroute_info_.replica_.server_.get_port())); - } else { - retry_status = retry_server_connection_not_open(s); + LOG_DEBUG("start next retry", "is in trans:", is_in_trans(s)); + // if use target db server then no need renew, will retry server from target db server + if ((OB_NOT_NULL(s.trans_info_.client_request_.get_parse_result().get_target_db_server()) + && !s.trans_info_.client_request_.get_parse_result().get_target_db_server()->is_empty()) + || (OB_NOT_NULL(s.sm_->target_db_server_) && !s.sm_->target_db_server_->is_empty())) { + s.pll_info_.force_renew_state_ = ObPartitionLookupInfo::ObForceRenewState::NO_NEED_RENEW; + s.pll_info_.is_need_force_flush_ = false; } + if (s.current_.error_type_ == TRANS_FREE_ROUTE_NOT_SUPPORTED_ERROR) { + // downgrade transaction internal routing, route the rest of request to coordinator session + LOG_DEBUG("transaction internal routing retry", K(s.trans_info_.sql_cmd_)); + retry_status = FOUND_EXISTING_ADDR; + s.server_info_.set_addr(s.sm_->get_client_session()->get_trans_coordinator_ss_addr()); + is_reroute_to_coordinator = true; + } else if (!is_in_trans(s) || is_internal_routing) { + if (s.pll_info_.is_force_renew()) { // force pl lookup + retry_status = NOT_FOUND_EXISTING_ADDR; + } else if (REQUEST_REROUTE_ERROR == s.current_.error_type_) { + retry_status = FOUND_EXISTING_ADDR; + s.server_info_.set_addr(ops_ip_sa_cast(s.reroute_info_.replica_.server_.get_sockaddr())); + } else { + retry_status = retry_server_connection_not_open(s); + } + } } if (NULL == s.congestion_entry_ || !s.congestion_entry_->is_congested()) { @@ -4134,14 +4990,21 @@ void ObMysqlTransact::handle_oceanbase_retry_server_connection(ObTransState &s) s.congestion_entry_->dec_ref(); s.congestion_entry_ = NULL; } - s.congestion_lookup_success_ = false; - s.need_congestion_lookup_ = true; + if (is_reroute_to_coordinator) { + s.congestion_lookup_success_ = true; + s.need_congestion_lookup_ = false; + s.pl_lookup_state_ = USE_COORDINATOR_SESSION; + } else { + s.congestion_lookup_success_ = false; + s.need_congestion_lookup_ = true; + } LOG_DEBUG("FOUND_EXISTING_ADDR, Retrying...", "attempts now", s.current_.attempts_, K(max_connect_attempts), "retry observer", s.server_info_.addr_, - "force_retry_congested", s.force_retry_congested_); + "force_retry_congested", s.force_retry_congested_, + "is reroute to coordinaotr", is_reroute_to_coordinator); TRANSACT_RETURN(SM_ACTION_CONGESTION_CONTROL_LOOKUP, handle_congestion_control_lookup); } else if (NOT_FOUND_EXISTING_ADDR == retry_status) { // before retry another server, reset analyze result @@ -4180,7 +5043,15 @@ void ObMysqlTransact::handle_oceanbase_retry_server_connection(ObTransState &s) void ObMysqlTransact::handle_retry_server_connection(ObTransState &s) { - if (s.sm_->client_session_->get_session_info().is_oceanbase_server()) { + /* + * reset response transform hook to keep the plugin created as the correct order + * otherwise, the packet handled by plugin will be err, eg, reroute err packet + */ + s.sm_->api_.txn_destroy_hook(OB_MYSQL_RESPONSE_TRANSFORM_HOOK); + + // Binlog requests also do not support retries + if (s.sm_->client_session_->get_session_info().is_oceanbase_server() + && !is_binlog_request(s)) { handle_oceanbase_retry_server_connection(s); } else { handle_server_connection_break(s); @@ -4248,8 +5119,35 @@ ObMysqlTransact::ObSSRetryStatus ObMysqlTransact::retry_server_connection_not_op if (s.current_.attempts_ == get_max_connect_attempts(s)) { handle_retry_last_time(s); } - - if (s.pll_info_.replica_size() > 0) { + // target db server (sql comment & multi level config) + if (OB_NOT_NULL(s.trans_info_.client_request_.get_parse_result().get_target_db_server()) + && !s.trans_info_.client_request_.get_parse_result().get_target_db_server()->is_empty()) { + if (OB_FAIL(s.trans_info_.client_request_.get_parse_result().get_target_db_server()->get_next(s.server_info_.addr_))) { + LOG_WARN("fail to get target db server from sql comment, will disconnect", K(ret)); + } else { + ret_status = FOUND_EXISTING_ADDR; + LOG_DEBUG("succ to get target db server from sql comment, will retry", + "address", s.server_info_.addr_); + } + } else if (OB_NOT_NULL(s.sm_->target_db_server_) && !s.sm_->target_db_server_->is_empty()) { + if (OB_FAIL(s.sm_->target_db_server_->get_next(s.server_info_.addr_))) { + LOG_WARN("fail to get target db server from multi level config, will disconnect", K(ret)); + } else { + ret_status = FOUND_EXISTING_ADDR; + LOG_DEBUG("succ to get target db server from multi level config, will retry", + "address", s.server_info_.addr_); + } + // config: server_routing_mode & test_server_addr + } else if ((s.mysql_config_params_->is_mock_routing_mode() && !s.sm_->client_session_->is_proxy_mysql_client_) + || s.mysql_config_params_->is_mysql_routing_mode()) { + if (OB_FAIL(s.mysql_config_params_->get_one_test_server_addr(s.server_info_.addr_))) { + LOG_WARN("mysql or mock mode, but test server addr in not set, disconnect", K(ret)); + } else { + s.sm_->client_session_->test_server_addr_ = s.server_info_.addr_; + LOG_DEBUG("mysql mode, test server is valid, just use it to retry", + "address", s.server_info_.addr_); + } + } else if (s.pll_info_.replica_size() > 0) { int32_t attempt_count = 0; //as leader must first used, here found_leader_force_congested is usefull bool found_leader_force_congested = false; @@ -4271,7 +5169,9 @@ ObMysqlTransact::ObSSRetryStatus ObMysqlTransact::retry_server_connection_not_op } if ((NULL != replica) && replica->is_valid()) { - s.server_info_.set_addr(replica->server_.get_ipv4(), static_cast(replica->server_.get_port())); + struct sockaddr_storage sockaddr = replica->server_.get_sockaddr(); + s.server_info_.set_addr(*(struct sockaddr*)(&(sockaddr))); + LOG_DEBUG("set addr here", K(s.server_info_.addr_)); ret_status = FOUND_EXISTING_ADDR; } else { // unavailalbe replica, just defense @@ -4311,35 +5211,51 @@ ObMysqlTransact::ObSSRetryStatus ObMysqlTransact::retry_server_connection_not_op inline void ObMysqlTransact::handle_server_connection_break(ObTransState &s) { if (NULL != s.sm_->client_session_) { - int64_t ss_id = (OB_ISNULL(s.sm_->get_server_session()) ? 0 : s.sm_->get_server_session()->ss_id_); - uint32_t server_sessid = (OB_ISNULL(s.sm_->get_server_session()) ? 0 : s.sm_->get_server_session()->get_server_sessid()); - - LOG_INFO("[ObMysqlTransact::handle_server_connection_break]", - "client_ip", s.client_info_.addr_, - "server_ip", s.server_info_.addr_, - "cs_id", s.sm_->client_session_->get_cs_id(), - "proxy_sessid", s.sm_->client_session_->get_proxy_sessid(), - K(ss_id), - K(server_sessid), - "sm_id", s.sm_->sm_id_, - "proxy_user_name", s.sm_->client_session_->get_session_info().get_priv_info().get_proxy_user_name(), - "database_name", s.sm_->client_session_->get_session_info().get_database_name(), - "server_state", ObMysqlTransact::get_server_state_name(s.current_.state_), - "request_cmd", get_mysql_cmd_str(s.trans_info_.client_request_.get_packet_meta().cmd_), - "sql_cmd", get_mysql_cmd_str(s.trans_info_.sql_cmd_), - "sql", s.trans_info_.get_print_sql()); - - if (obmysql::OB_MYSQL_COM_QUIT != s.trans_info_.sql_cmd_) { - OBPROXY_XF_LOG(INFO, XFH_CONNECTION_SERVER_ABORT, - "client_ip", s.client_info_.addr_, - "server_ip", s.server_info_.addr_, - "cluster_name", s.sm_->client_session_->get_session_info().get_priv_info().cluster_name_, - "tenant_name", s.sm_->client_session_->get_session_info().get_priv_info().tenant_name_, - "user_name", s.sm_->client_session_->get_session_info().get_priv_info().user_name_, - "db", s.sm_->client_session_->get_session_info().get_database_name(), - "server_state", ObMysqlTransact::get_server_state_name(s.current_.state_), - "sql", s.trans_info_.client_request_.get_print_sql(), - "request_cmd", get_mysql_cmd_str(s.trans_info_.sql_cmd_)); + if (s.sm_->client_session_->get_session_info().get_priv_info().user_name_ == ObProxyTableInfo::DETECT_USERNAME_USER) { + // do nothing + } else { + int64_t ss_id = (OB_ISNULL(s.sm_->get_server_session()) ? 0 : s.sm_->get_server_session()->ss_id_); + uint32_t server_sessid = (OB_ISNULL(s.sm_->get_server_session()) ? 0 : s.sm_->get_server_session()->get_server_sessid()); + + LOG_INFO("[ObMysqlTransact::handle_server_connection_break]", + "client_ip", s.client_info_.addr_, + "server_ip", s.server_info_.addr_, + "cs_id", s.sm_->client_session_->get_cs_id(), + "proxy_sessid", s.sm_->client_session_->get_proxy_sessid(), + K(ss_id), + K(server_sessid), + "sm_id", s.sm_->sm_id_, + "proxy_user_name", s.sm_->client_session_->get_session_info().get_priv_info().get_proxy_user_name(), + "database_name", s.sm_->client_session_->get_session_info().get_database_name(), + "server_state", ObMysqlTransact::get_server_state_name(s.current_.state_), + "request_cmd", get_mysql_cmd_str(s.trans_info_.client_request_.get_packet_meta().cmd_), + "sql_cmd", get_mysql_cmd_str(s.trans_info_.sql_cmd_), + "sql", s.trans_info_.get_print_sql()); + + if (obmysql::OB_MYSQL_COM_QUIT != s.trans_info_.sql_cmd_) { + OBPROXY_XF_LOG(INFO, XFH_CONNECTION_SERVER_ABORT, + "client_ip", s.client_info_.addr_, + "server_ip", s.server_info_.addr_, + "cluster_name", s.sm_->client_session_->get_session_info().get_priv_info().cluster_name_, + "tenant_name", s.sm_->client_session_->get_session_info().get_priv_info().tenant_name_, + "user_name", s.sm_->client_session_->get_session_info().get_priv_info().user_name_, + "db", s.sm_->client_session_->get_session_info().get_database_name(), + "server_state", ObMysqlTransact::get_server_state_name(s.current_.state_), + "sql", s.trans_info_.client_request_.get_print_sql(), + "request_cmd", get_mysql_cmd_str(s.trans_info_.sql_cmd_)); + + s.trace_log_.log_it("[svr_connection_break]", + "cli", s.client_info_.addr_, + "svr", s.server_info_.addr_, + "cluster", s.sm_->client_session_->get_session_info().get_priv_info().cluster_name_, + "tenant", s.sm_->client_session_->get_session_info().get_priv_info().tenant_name_, + "user", s.sm_->client_session_->get_session_info().get_priv_info().user_name_, + "db", s.sm_->client_session_->get_session_info().get_database_name(), + "svr_state", ObMysqlTransact::get_server_state_name(s.current_.state_), + "sql", s.trans_info_.client_request_.get_print_sql(), + "sql_cmd", get_mysql_cmd_str(s.trans_info_.sql_cmd_)); + LOG_WARN("trace_log", K(s.trace_log_)); + } } } else { LOG_INFO("[ObMysqlTransact::handle_server_connection_break]", @@ -4357,6 +5273,14 @@ inline void ObMysqlTransact::handle_server_connection_break(ObTransState &s) "server_state", ObMysqlTransact::get_server_state_name(s.current_.state_), "sql", s.trans_info_.client_request_.get_print_sql(), "request_cmd", get_mysql_cmd_str(s.trans_info_.sql_cmd_)); + + s.trace_log_.log_it("[svr_connection_break]", + "cli", s.client_info_.addr_, + "svr", s.server_info_.addr_, + "svr_state", ObMysqlTransact::get_server_state_name(s.current_.state_), + "sql", s.trans_info_.client_request_.get_print_sql(), + "sql_cmd", get_mysql_cmd_str(s.trans_info_.sql_cmd_)); + LOG_WARN("trace_log", K(s.trace_log_)); } } @@ -4373,7 +5297,7 @@ inline void ObMysqlTransact::handle_server_connection_break(ObTransState &s) void ObMysqlTransact::handle_on_forward_server_response(ObTransState &s) { LOG_DEBUG("[ObMysqlTransact::handle_on_forward_server_response]", - "cur_send_action", ObMysqlTransact::get_send_action_name(s.current_.send_action_)); + "cur_send_action", ObMysqlTransact::get_send_action_name(s.current_.send_action_),"startm trans", s.is_hold_start_trans_); switch (s.current_.send_action_) { case SERVER_SEND_HANDSHAKE: { @@ -4385,8 +5309,10 @@ void ObMysqlTransact::handle_on_forward_server_response(ObTransState &s) } } else { bool server_support_ssl = resp.support_ssl(); - bool is_server_ssl_supported = get_global_ssl_config_table_processor().is_ssl_supported( - s.sm_->client_session_->get_vip_cluster_name(), s.sm_->client_session_->get_vip_tenant_name(), false); + bool is_server_ssl_supported = s.sm_->enable_server_ssl_ && + get_global_ssl_config_table_processor().is_ssl_key_info_valid( + s.sm_->client_session_->get_vip_cluster_name(), + s.sm_->client_session_->get_vip_tenant_name()); LOG_DEBUG("ssl support", K(is_server_ssl_supported), K(server_support_ssl)); if (is_server_ssl_supported && server_support_ssl && !s.sm_->client_session_->is_proxy_mysql_client_) { @@ -4424,7 +5350,7 @@ void ObMysqlTransact::handle_on_forward_server_response(ObTransState &s) break; } else if (client_info.is_oceanbase_server()) { bool is_proxy_mysql_client_ = s.sm_->client_session_->is_proxy_mysql_client_; - if (client_info.need_reset_all_session_vars() && !is_proxy_mysql_client_) { + if (client_info.need_reset_all_session_vars() && !is_binlog_request(s) && !is_proxy_mysql_client_) { // 1.if global vars changed, we need to sync all session vars to keep // server session vars is equal to the snapshot of client session // 2.proxy mysql client no need sync all session vars @@ -4447,7 +5373,11 @@ void ObMysqlTransact::handle_on_forward_server_response(ObTransState &s) ObClientSessionInfo &client_info = get_client_session_info(s); ObServerSessionInfo &server_info = get_server_session_info(s); //obutils::ObSqlParseResult &sql_result = s.trans_info_.client_request_.get_parse_result(); - if (obmysql::OB_MYSQL_COM_STMT_CLOSE == s.trans_info_.client_request_.get_packet_meta().cmd_) { + obmysql::ObMySQLCmd cmd = s.trans_info_.client_request_.get_packet_meta().cmd_; + if (obmysql::OB_MYSQL_COM_STMT_CLOSE == cmd + || obmysql::OB_MYSQL_COM_STMT_RESET == cmd + || is_binlog_request(s) + || s.sm_->client_session_->can_direct_send_request_) { // no need sync var, send to server directly s.current_.send_action_ = SERVER_SEND_REQUEST; s.next_action_ = SM_ACTION_API_SEND_REQUEST; @@ -4474,13 +5404,17 @@ void ObMysqlTransact::handle_on_forward_server_response(ObTransState &s) ObClientSessionInfo &client_info = get_client_session_info(s); ObServerSessionInfo &server_info = get_server_session_info(s); //obutils::ObSqlParseResult &sql_result = s.trans_info_.client_request_.get_parse_result(); - if (client_info.need_reset_session_vars(server_info)) { + if (client_info.is_server_support_session_var_sync() && + client_info.need_reset_user_session_vars(server_info)) { + s.current_.send_action_ = SERVER_SEND_SESSION_USER_VARS; + s.next_action_ = SM_ACTION_API_SEND_REQUEST; + break; + } else if (!client_info.is_server_support_session_var_sync() && + client_info.need_reset_session_vars(server_info)) { s.current_.send_action_ = SERVER_SEND_SESSION_VARS; s.next_action_ = SM_ACTION_API_SEND_REQUEST; break; - } else { - // fall through: - } + } else { /* fall through */ } } else { s.current_.state_ = INTERNAL_ERROR; handle_server_connection_break(s); @@ -4492,29 +5426,28 @@ void ObMysqlTransact::handle_on_forward_server_response(ObTransState &s) } __attribute__ ((fallthrough)); case SERVER_SEND_SESSION_VARS: - case SERVER_SEND_LAST_INSERT_ID: + case SERVER_SEND_SESSION_USER_VARS: case SERVER_SEND_PREPARE: case SERVER_SEND_TEXT_PS_PREPARE: + case SERVER_SEND_XA_START: case SERVER_SEND_START_TRANS: { if (OB_LIKELY(NULL != s.sm_->client_session_) && OB_LIKELY(NULL != s.sm_->get_server_session())) { ObClientSessionInfo &client_info = get_client_session_info(s); ObServerSessionInfo &server_info = get_server_session_info(s); obmysql::ObMySQLCmd cmd = s.trans_info_.client_request_.get_packet_meta().cmd_; - //obutils::ObSqlParseResult &sql_result = s.trans_info_.client_request_.get_parse_result(); - if (client_info.need_reset_last_insert_id(server_info)) { - // TODO: current version proxy parse can't judge last_insert_id exactly, - // so we do not judge, whether sql_reuslt has_last_insert_id here - // if it is large request, we do not parse the sql, we don't know whether the sql contains - // last_insert_id, in this case we will sync last_insert_id if need - s.current_.send_action_ = SERVER_SEND_LAST_INSERT_ID; - } else if (s.is_hold_start_trans_) { + ObProxyMysqlRequest &client_request = s.trans_info_.client_request_; + if (s.is_hold_start_trans_) { s.current_.send_action_ = SERVER_SEND_START_TRANS; + } else if (s.is_hold_xa_start_) { + LOG_DEBUG("[ObMysqlTransact::handle_on_forward_server_response] set send action SERVER_SEND_XA_START for sync xa start"); + s.current_.send_action_ = SERVER_SEND_XA_START; } else if ((obmysql::OB_MYSQL_COM_STMT_EXECUTE == cmd - || obmysql::OB_MYSQL_COM_STMT_SEND_PIECE_DATA == cmd - || obmysql::OB_MYSQL_COM_STMT_SEND_LONG_DATA == cmd) + || obmysql::OB_MYSQL_COM_STMT_SEND_PIECE_DATA == cmd + || obmysql::OB_MYSQL_COM_STMT_SEND_LONG_DATA == cmd) && client_info.need_do_prepare(server_info)) { s.current_.send_action_ = SERVER_SEND_PREPARE; - } else if (client_info.is_text_ps_execute() && client_info.need_do_text_ps_prepare(server_info)) { + } else if (client_request.get_parse_result().is_text_ps_execute_stmt() && + client_info.need_do_text_ps_prepare(server_info)) { s.current_.send_action_ = SERVER_SEND_TEXT_PS_PREPARE; } else { s.current_.send_action_ = SERVER_SEND_REQUEST; @@ -4548,9 +5481,18 @@ void ObMysqlTransact::handle_on_forward_server_response(ObTransState &s) break; } case SERVER_SEND_REQUEST: { - s.next_action_ = SM_ACTION_SERVER_READ; - if (get_client_session_info(s).is_oceanbase_server()) { - s.sm_->api_.do_response_transform_open(); + ObRespAnalyzeResult &resp = s.trans_info_.server_response_.get_analyze_result(); + obmysql::ObMySQLCmd cmd = s.trans_info_.client_request_.get_packet_meta().cmd_; + ObProxyMysqlRequest &client_request = s.trans_info_.client_request_; + // OB_MYSQL_COM_STMT_RESET request, if executed correctly, jump; otherwise return errro packet to client + if ((obmysql::OB_MYSQL_COM_STMT_RESET == cmd || client_request.get_parse_result().is_text_ps_drop_stmt()) + && resp.is_ok_resp()) { + TRANSACT_RETURN(SM_ACTION_API_READ_REQUEST, ObMysqlTransact::handle_request); + } else { + s.next_action_ = SM_ACTION_SERVER_READ; + if (get_client_session_info(s).is_oceanbase_server()) { + s.sm_->api_.do_response_transform_open(); + } } break; } @@ -4615,11 +5557,11 @@ inline void ObMysqlTransact::update_sync_session_stat(ObTransState &s) MYSQL_INCREMENT_TRANS_STAT(SEND_CHANGED_SESSION_VARS_REQUESTS); break; - case SERVER_SEND_LAST_INSERT_ID: - s.sm_->cmd_time_stats_.server_send_last_insert_id_time_ += cost; + case SERVER_SEND_SESSION_USER_VARS: + s.sm_->cmd_time_stats_.server_send_session_user_variable_time_ += cost; s.sm_->cmd_time_stats_.server_sync_session_variable_time_ += cost; - MYSQL_SUM_TIME_STAT(TOTAL_SEND_LAST_INSERT_ID_TIME, cost); - MYSQL_INCREMENT_TRANS_STAT(SEND_LAST_INSERT_ID_REQUESTS); + MYSQL_SUM_TIME_STAT(TOTAL_SEND_CHANGED_SESSION_USER_VARS_TIME, cost); + MYSQL_INCREMENT_TRANS_STAT(SEND_CHANGED_SESSION_USER_VARS_REQUESTS); break; case SERVER_SEND_START_TRANS: @@ -4628,6 +5570,13 @@ inline void ObMysqlTransact::update_sync_session_stat(ObTransState &s) MYSQL_SUM_TIME_STAT(TOTAL_SEND_START_TRANS_TIME, cost); MYSQL_INCREMENT_TRANS_STAT(SEND_START_TRANS_REQUESTS); break; + + case SERVER_SEND_XA_START: + s.sm_->cmd_time_stats_.server_send_xa_start_time_ += cost; + s.sm_->cmd_time_stats_.server_sync_session_variable_time_ += cost; + MYSQL_SUM_TIME_STAT(TOTAL_SEND_XA_START_TIME, cost); + MYSQL_INCREMENT_TRANS_STAT(SEND_XA_START_REQUESTS); + break; case SERVER_SEND_HANDSHAKE: case SERVER_SEND_LOGIN: @@ -4656,6 +5605,7 @@ inline void ObMysqlTransact::handle_server_failed(ObTransState &s) switch (s.current_.state_) { case ALIVE_CONGESTED: case DEAD_CONGESTED: + case DETECT_CONGESTED: case INTERNAL_ERROR: break; @@ -4860,7 +5810,7 @@ int ObMysqlTransact::add_new_stat_block(ObTransState &s) return ret; } -int ObMysqlTransact::build_error_packet(ObTransState &s) +int ObMysqlTransact::build_error_packet(ObTransState &s, ObMysqlClientSession *client_session) { int ret = OB_SUCCESS; if (0 == s.mysql_errcode_) { @@ -4882,12 +5832,18 @@ int ObMysqlTransact::build_error_packet(ObTransState &s) } if (OB_SUCC(ret)) { + ObMysqlSM *sm = s.sm_; + ObProxyProtocol client_protocol = ObProxyProtocol::PROTOCOL_NORMAL; + if (sm != NULL) { + client_protocol = sm->get_client_session_protocol(); + } + int errcode = s.mysql_errcode_; s.inner_errcode_ = s.mysql_errcode_; uint8_t next_seq = 0; if (s.is_auth_request_) { - if ((NULL != s.sm_) && (NULL != s.sm_->client_session_)) { - ObMysqlAuthRequest &auth_req = s.sm_->client_session_->get_session_info().get_login_req(); + if (client_session != NULL) { + ObMysqlAuthRequest &auth_req = client_session->get_session_info().get_login_req(); next_seq = static_cast(auth_req.get_packet_meta().pkt_seq_ + 1); } } else { @@ -4897,7 +5853,8 @@ int ObMysqlTransact::build_error_packet(ObTransState &s) if (NULL != s.mysql_errmsg_) { const char *errmsg = s.mysql_errmsg_; - if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet_buf(*buf, next_seq, errcode, errmsg))) { + if (OB_FAIL(ObProxyPacketWriter::write_error_packet(*buf, client_session, client_protocol, + next_seq, errcode, errmsg))) { LOG_WARN("[ObMysqlTransact::build_error_packet] fail to encode err pacekt buf", K(next_seq), K(errmsg), K(errcode), K(ret)); } @@ -4912,8 +5869,8 @@ int ObMysqlTransact::build_error_packet(ObTransState &s) int64_t name_len = 0; const char *name_str = NULL; bool has_auth_resp = false; - if ((NULL != s.sm_) && (NULL != s.sm_->client_session_)) { - ObClientSessionInfo &client_info = s.sm_->client_session_->get_session_info(); + if (client_session != NULL) { + ObClientSessionInfo &client_info = client_session->get_session_info(); ObMysqlAuthRequest &auth_req = client_info.get_login_req(); ObHSRResult &result = auth_req.get_hsr_result(); if (!result.is_clustername_from_default_) { @@ -4931,9 +5888,12 @@ int ObMysqlTransact::build_error_packet(ObTransState &s) if (OB_FAIL(databuff_printf(errmsg, BUF_LEN, pos, ob_str_user_error(errcode), name_len, name_str, strlen(ip_buff), ip_buff, (has_auth_resp ? "YES" : "NO")))) { LOG_WARN("fail to fill err_msg", K(ret)); - } else if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet_buf(*buf, next_seq, errcode, errmsg))) { + } else if (OB_FAIL(ObProxyPacketWriter::write_error_packet(*buf, client_session, client_protocol, + next_seq, errcode, errmsg))) { LOG_WARN("[ObMysqlTransact::build_error_packet] fail to encode err pacekt buf", K(next_seq), K(errcode), K(ret)); + } else { + // nothing } break; } @@ -4946,9 +5906,16 @@ int ObMysqlTransact::build_error_packet(ObTransState &s) case OB_ERR_FETCH_OUT_SEQUENCE: case OB_CURSOR_NOT_EXIST: case OB_ERR_CON_COUNT_ERROR: - case OB_NOT_SUPPORTED: { - if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet(*buf, next_seq, errcode))) { + case OB_NOT_SUPPORTED: + case OB_ERR_PREPARE_STMT_NOT_FOUND: { + char *err_msg = NULL; + if (OB_FAIL(ObProxyPacketWriter::get_err_buf(errcode, err_msg))) { + LOG_WARN("fail to get err buf", K(ret)); + } else if (OB_FAIL(ObProxyPacketWriter::write_error_packet(*buf, client_session, client_protocol, + next_seq, errcode, err_msg))) { LOG_WARN("[ObMysqlTransact::build_error_packet] fail to build not supported err resp", K(ret)); + } else { + // nothing } break; } @@ -4980,6 +5947,242 @@ void ObMysqlTransact::handle_new_config_acquired(ObTransState &s) } } +void ObMysqlTransact::ObTransState::refresh_mysql_config() +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(mysql_config_params_ != get_global_mysql_config_processor().get_config())) { + ObMysqlConfigParams *config = NULL; + if (OB_ISNULL(config = get_global_mysql_config_processor().acquire())) { + PROXY_TXN_LOG(WARN, "fail to acquire mysql config"); + } else { + if (OB_LIKELY(NULL != mysql_config_params_)) { + mysql_config_params_->dec_ref(); + mysql_config_params_ = NULL; + } + mysql_config_params_ = config; + } + ObMysqlTransact::handle_new_config_acquired(*this); + } + + if (OB_UNLIKELY(get_global_performance_params().enable_trace_)) { + if (NULL != sqlaudit_record_queue_) { + sqlaudit_record_queue_->refcount_dec(); + sqlaudit_record_queue_ = NULL; + } + + if (mysql_config_params_->sqlaudit_mem_limited_ > 0) { + sqlaudit_record_queue_ = get_global_sqlaudit_processor().acquire(); + } + } + + // record v2 config + if (is_auth_request_) { + bool enable_v2 = mysql_config_params_->enable_ob_protocol_v2_; + sm_->set_enable_ob_protocol_v2(enable_v2); + PROXY_CS_LOG(DEBUG, "client session start with ", "enable_ob_protocol_v2:", enable_v2, "cs_id", sm_->get_client_session()->get_cs_id()); + } + + // Start to get the version number. If there are concurrent modifications, the version will be pushed up. + // The next time it is executed, it will continue to be updated. + ObNetVConnection *client_vc = static_cast(sm_->get_client_session()->get_netvc()); + ObMysqlClientSession *client_session = sm_->get_client_session(); + ObClientSessionInfo &session_info = sm_->get_client_session()->get_session_info(); + uint64_t global_version = get_global_proxy_config_table_processor().get_config_version(); + if (sm_->config_version_ != global_version && NULL != client_vc) { + int64_t vid = static_cast(client_vc->get_virtual_vid()); + ObVipAddr addr; + addr.set(client_vc->get_virtual_addr(), vid); + ObString tenant_name; + ObString cluster_name; + if (client_session->is_need_convert_vip_to_tname() && client_session->is_vip_lookup_success()) { + cluster_name = sm_->get_client_session()->get_vip_cluster_name(); + tenant_name = sm_->get_client_session()->get_vip_tenant_name(); + if (OB_FAIL(get_config_item(cluster_name, tenant_name, addr, global_version))) { + LOG_WARN("get config item failed", K(cluster_name), K(tenant_name), K(addr), K(ret)); + } + } else { + if (OB_FAIL(session_info.get_cluster_name(cluster_name))) { + LOG_DEBUG("get tenant name failed", K(ret)); + } + if (OB_SUCC(ret) && OB_FAIL(session_info.get_tenant_name(tenant_name))) { + LOG_DEBUG("get tenant name failed", K(ret)); + } + + if (trans_info_.sql_cmd_ == obmysql::OB_MYSQL_COM_END) { + get_config_item(cluster_name, tenant_name, addr, 0); + } else { + if (OB_SUCC(ret) && OB_FAIL(get_config_item(cluster_name, tenant_name, addr, global_version))) { + LOG_WARN("get config item failed", K(cluster_name), K(tenant_name), K(addr), K(ret)); + } + } + } + + LOG_DEBUG("get config succ", K(addr), K(cluster_name), K(tenant_name), + K_(sm_->proxy_route_policy), K_(sm_->proxy_idc_name), + K_(sm_->enable_cloud_full_username), K_(sm_->enable_client_ssl), + K_(sm_->enable_server_ssl), K_(sm_->enable_transaction_split), K_(sm_->enable_transaction_split), + K(session_info.is_request_follower_user()), K(session_info.is_read_only_user()), + K_(sm_->target_db_server), K(ret)); + } +} + +int ObMysqlTransact::ObTransState::get_config_item(const ObString& cluster_name, + const ObString &tenant_name, + const ObVipAddr &addr, + const int64_t global_version) +{ + int ret = OB_SUCCESS; + ObClientSessionInfo &session_info = sm_->get_client_session()->get_session_info(); + if (OB_SUCC(ret)) { + ObConfigItem item; + if (OB_FAIL(get_global_config_processor().get_proxy_config( + addr, cluster_name, tenant_name, "proxy_route_policy", item))) { + LOG_WARN("get proxy route policy config failed", K(addr), K(cluster_name), K(tenant_name), K(ret)); + } else { + MEMCPY(sm_->proxy_route_policy_, item.str(), strlen(item.str())); + } + } + + if (OB_SUCC(ret)) { + ObConfigItem item; + if (OB_FAIL(get_global_config_processor().get_proxy_config( + addr, cluster_name, tenant_name, "proxy_idc_name", item))) { + LOG_WARN("get proxy idc name config failed", K(addr), K(cluster_name), K(tenant_name), K(ret)); + } else { + MEMCPY(sm_->proxy_idc_name_, item.str(), strlen(item.str())); + } + } + + if (OB_SUCC(ret)) { + ObConfigBoolItem bool_item; + if (OB_FAIL(get_global_config_processor().get_proxy_config_bool_item( + addr, cluster_name, tenant_name, "enable_cloud_full_username", bool_item))) { + LOG_WARN("get enable_cloud_full_username failed", K(addr), K(cluster_name), K(tenant_name), K(ret)); + } else { + sm_->enable_cloud_full_username_ = bool_item.get_value(); + } + } + + if (OB_SUCC(ret)) { + ObConfigBoolItem bool_item; + if (OB_FAIL(get_global_config_processor().get_proxy_config_bool_item( + addr, cluster_name, tenant_name, "enable_client_ssl", bool_item))) { + LOG_WARN("get enable_client_ssl failed", K(addr), K(cluster_name), K(tenant_name), K(ret)); + } else { + sm_->enable_client_ssl_ = bool_item.get_value(); + } + } + + if (OB_SUCC(ret)) { + ObConfigBoolItem bool_item; + if (OB_FAIL(get_global_config_processor().get_proxy_config_bool_item( + addr, cluster_name, tenant_name, "enable_server_ssl", bool_item))) { + LOG_WARN("get enable_server_ssl failed", K(addr), K(cluster_name), K(tenant_name), K(ret)); + } else { + sm_->enable_server_ssl_ = bool_item.get_value(); + } + } + + if (OB_SUCC(ret)) { + ObConfigItem item; + if (OB_FAIL(get_global_config_processor().get_proxy_config( + addr, cluster_name, tenant_name, "target_db_server", item))) { + LOG_WARN("fail to get target_db_server", K(addr), K(cluster_name), K(tenant_name), K(ret)); + // if config empty + } else if (OB_ISNULL(item.str()) || strlen(item.str()) == 0 ) { + // target db server not null, reset it + if (OB_NOT_NULL(sm_->target_db_server_)) { + op_free(sm_->target_db_server_); + sm_->target_db_server_ = NULL; + // target db server is null, do nothing + } else { /* do nothing */} + // if config not empty + // target db server is null, allocate and init one + } else if (OB_ISNULL(sm_->target_db_server_) && OB_ISNULL(sm_->target_db_server_ = op_alloc(ObTargetDbServer))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc memory to for target db server", K(ret)); + } else if (OB_FAIL(sm_->target_db_server_->init(item.str(), strlen(item.str())))) { + LOG_WARN("fail to load target db server from multi level config", K(ret)); + } + } + + if (OB_SUCC(ret)) { + ObConfigIntItem int_item; + if (OB_FAIL(get_global_config_processor().get_proxy_config_int_item( + addr, cluster_name, tenant_name, "obproxy_read_only", int_item))) { + LOG_WARN("get vip obproxy_read_only failed", K(addr), K(cluster_name), K(tenant_name), K(ret)); + } else { + bool is_read_only = (ReadOnly == int_item.get_value()); + bool is_sys_var_update = (session_info.is_read_only_user() != is_read_only); + session_info.set_is_read_only_user(is_read_only); + if (is_sys_var_update) { + ObString tx_read_only("tx_read_only"); + ObString tx_read_only_true; + if (session_info.is_read_only_user()) { + tx_read_only_true = "1"; + } else { + tx_read_only_true = "0"; + } + if (OB_FAIL(session_info.update_sys_variable(tx_read_only, tx_read_only_true))) { + LOG_WARN("replace user variables failed", K(tx_read_only_true), K(ret)); + } + } + } + } + + if (OB_SUCC(ret)) { + ObConfigIntItem int_item; + if (OB_FAIL(get_global_config_processor().get_proxy_config_int_item( + addr, cluster_name, tenant_name, "obproxy_read_consistency", int_item))) { + LOG_WARN("get vip obproxy_read_consistency failed", K(addr), K(cluster_name), K(tenant_name), K(ret)); + } else { + bool is_request_follower = (RequestFollower == int_item.get_value()); + bool is_sys_var_update = (session_info.is_request_follower_user() != is_request_follower); + session_info.set_is_request_follower_user(is_request_follower); + if (is_sys_var_update) { + ObString ob_read_consistency("ob_read_consistency"); + ObString weak; + if (session_info.is_request_follower_user()) { + weak = "2"; + } else { + weak = "3"; + } + if (OB_FAIL(session_info.update_sys_variable(ob_read_consistency, weak))) { + LOG_WARN("replace user variables failed", K(weak), K(ret)); + } else { + session_info.set_read_consistency_set_flag(true); + } + } + } + } + + if (OB_SUCC(ret)) { + ObConfigBoolItem bool_item; + if (OB_FAIL(get_global_config_processor().get_proxy_config_bool_item( + addr, cluster_name, tenant_name, "enable_read_write_split", bool_item))) { + LOG_WARN("get enable_read_write_split failed", K(addr), K(cluster_name), K(tenant_name), K(ret)); + } else { + sm_->enable_read_write_split_ = bool_item.get_value(); + } + } + + if (OB_SUCC(ret)) { + ObConfigBoolItem bool_item; + if (OB_FAIL(get_global_config_processor().get_proxy_config_bool_item( + addr, cluster_name, tenant_name, "enable_transaction_split", bool_item))) { + LOG_WARN("get enable_transaction_split failed", K(addr), K(cluster_name), K(tenant_name), K(ret)); + } else { + sm_->enable_transaction_split_ = bool_item.get_value(); + } + } + + if (OB_SUCC(ret) && global_version > 0) { + sm_->config_version_ = global_version; + } + + return ret; +} + inline void ObMysqlTransact::ObTransState::get_route_policy(ObProxyRoutePolicyEnum policy, ObRoutePolicyEnum& ret_policy) { @@ -5039,12 +6242,11 @@ inline ObRoutePolicyEnum ObMysqlTransact::ObTransState::get_route_policy(ObMysql //if no readonly zone exist, use orig policy ret_policy = MERGE_IDC_ORDER; if (common::WEAK == get_trans_consistency_level(cs.get_session_info())) { - if (is_valid_proxy_route_policy(cs.get_session_info().get_proxy_route_policy()) + if (is_valid_proxy_route_policy(cs.get_session_info().get_proxy_route_policy()) && cs.get_session_info().is_proxy_route_policy_set()) { get_route_policy(cs.get_session_info().get_proxy_route_policy(), ret_policy); } else { - const ObString value = get_global_proxy_config().proxy_route_policy.str(); - ObProxyRoutePolicyEnum policy = get_proxy_route_policy(value); + ObProxyRoutePolicyEnum policy = get_proxy_route_policy(sm_->proxy_route_policy_); PROXY_CS_LOG(DEBUG, "succ to global variable proxy_route_policy", "policy", get_proxy_route_policy_enum_string(policy)); get_route_policy(policy, ret_policy); @@ -5190,6 +6392,10 @@ const char *ObMysqlTransact::get_server_resp_error_name(ObMysqlTransact::ObServe ret = "START_TRANS_COMMON_ERROR"; break; + case ObMysqlTransact::START_XA_START_ERROR: + ret = "START_XA_START_ERROR"; + break; + case ObMysqlTransact::SYNC_DATABASE_COMMON_ERROR: ret = "SYNC_DATABASE_COMMON_ERROR"; break; @@ -5198,6 +6404,10 @@ const char *ObMysqlTransact::get_server_resp_error_name(ObMysqlTransact::ObServe ret = "SYNC_PREPARE_COMMON_ERROR"; break; + case ObMysqlTransact::SYNC_TEXT_PS_PREPARE_COMMON_ERROR: + ret = "SYNC_TEXT_PS_PREPARE_COMMON_ERROR"; + break; + case ObMysqlTransact::ORA_FATAL_ERROR: ret = "ORA_FATAL_ERROR"; break; @@ -5230,6 +6440,9 @@ const char *ObMysqlTransact::get_server_resp_error_name(ObMysqlTransact::ObServe ret = "SYANDBY_WEAK_READONLY_ERROR"; break; + case ObMysqlTransact::TRANS_FREE_ROUTE_NOT_SUPPORTED_ERROR: + ret = "TRANS_FREE_ROUTE_NOT_SUPPORTED_ERROR"; + break; case ObMysqlTransact::MAX_RESP_ERROR: ret = "MAX_RESP_ERR"; break; @@ -5297,6 +6510,10 @@ const char *ObMysqlTransact::get_server_state_name(ObMysqlTransact::ObServerStat ret = "ALIVE_CONGESTED"; break; + case ObMysqlTransact::DETECT_CONGESTED: + ret = "DETECT_CONGESTED"; + break; + case ObMysqlTransact::INTERNAL_ERROR: ret = "INTERNAL_ERROR"; break; @@ -5341,13 +6558,17 @@ const char *ObMysqlTransact::get_send_action_name( case ObMysqlTransact::SERVER_SEND_SESSION_VARS: ret = "SERVER_SEND_SESSION_VARS"; break; + + case ObMysqlTransact::SERVER_SEND_SESSION_USER_VARS: + ret = "SERVER_SEND_SESSION_USER_VARS"; + break; case ObMysqlTransact::SERVER_SEND_START_TRANS: ret = "SERVER_SEND_START_TRANS"; break; - case ObMysqlTransact::SERVER_SEND_LAST_INSERT_ID: - ret = "SERVER_SEND_LAST_INSERT_ID"; + case ObMysqlTransact::SERVER_SEND_XA_START: + ret = "SERVER_SEND_XA_START"; break; case ObMysqlTransact::SERVER_SEND_REQUEST: @@ -5400,10 +6621,18 @@ bool ObMysqlTransact::is_internal_request(ObTransState &s) || (s.trans_info_.client_request_.is_sharding_user() && (s.trans_info_.client_request_.get_parse_result().is_shard_special_cmd() || obmysql::OB_MYSQL_COM_INIT_DB == s.trans_info_.sql_cmd_ - || (s.trans_info_.client_request_.get_parse_result().is_show_tables_stmt() + || ((s.trans_info_.client_request_.get_parse_result().is_show_tables_stmt() + || s.trans_info_.client_request_.get_parse_result().is_show_full_tables_stmt() + || s.trans_info_.client_request_.get_parse_result().is_show_table_status_stmt()) && !is_single_shard_db_table(s)))) || (s.is_trans_first_request_ + && !s.is_hold_xa_start_ && s.trans_info_.client_request_.get_parse_result().need_hold_start_trans()) + || (s.is_trans_first_request_ + && !s.is_hold_start_trans_ + && !s.is_hold_xa_start_ + && s.trans_info_.client_request_.get_parse_result().need_hold_xa_start() + && get_global_proxy_config().enable_xa_route) || s.trans_info_.client_request_.get_parse_result().is_internal_request() || is_bad_route_request(s)) || !is_supported_mysql_cmd(s.trans_info_.sql_cmd_) @@ -5413,6 +6642,95 @@ bool ObMysqlTransact::is_internal_request(ObTransState &s) &&s.trans_info_.client_request_.get_parse_result().is_set_ob_read_consistency()); } +int64_t ObMysqlTransact::get_max_connect_attempts(ObTransState &s) +{ + int64_t target_db_server_num = 0; + if (NULL != s.trans_info_.client_request_.get_parse_result().get_target_db_server() + && 0 < s.trans_info_.client_request_.get_parse_result().get_target_db_server()->num()) { + target_db_server_num = s.trans_info_.client_request_.get_parse_result().get_target_db_server()->num(); + } else if (NULL != s.sm_->target_db_server_ && 0 < s.sm_->target_db_server_->num()) { + target_db_server_num = s.sm_->target_db_server_->num(); + } + return std::max(target_db_server_num, std::max(s.mysql_config_params_->connect_observer_max_retries_, + get_max_connect_attempts_from_replica(s.pll_info_.replica_size()))); +} + +bool ObMysqlTransact::is_binlog_request(const ObTransState &s) +{ + bool bret = false; + if (get_global_proxy_config().enable_binlog_service + && (obmysql::OB_MYSQL_COM_REGISTER_SLAVE == s.trans_info_.client_request_.get_packet_meta().cmd_ + || obmysql::OB_MYSQL_COM_BINLOG_DUMP == s.trans_info_.client_request_.get_packet_meta().cmd_ + || obmysql::OB_MYSQL_COM_BINLOG_DUMP_GTID == s.trans_info_.client_request_.get_packet_meta().cmd_ + || s.trans_info_.client_request_.get_parse_result().is_binlog_stmt())) { + bret = true; + } + + return bret; +} + +void ObMysqlTransact::handle_binlog_request(ObTransState &s) +{ + ObClientSessionInfo &cs_info = get_client_session_info(s); + ObString cluster_name = cs_info.get_priv_info().cluster_name_; + ObString tenant_name = cs_info.get_priv_info().tenant_name_; + + ObTableEntryName &te_name = s.pll_info_.te_name_; + te_name.cluster_name_ = cluster_name; + te_name.tenant_name_ = tenant_name; + // mock database name + te_name.database_name_ = OB_SYS_DATABASE_NAME; + te_name.table_name_ = OB_ALL_BINLOG_DUMMY_TNAME; + LOG_DEBUG("handle binlog request", K(te_name)); + TRANSACT_RETURN(SM_ACTION_BINLOG_LOCATION_LOOKUP, handle_bl_lookup); +} + +void ObMysqlTransact::handle_bl_lookup(ObTransState &s) +{ + int ret = OB_SUCCESS; + ++s.pll_info_.pl_attempts_; + + if (OB_UNLIKELY(!s.pll_info_.lookup_success_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("[ObMysqlTransact::handle_bl_lookup] " + "fail to lookup binlog location, will disconnect", K(ret)); + } else if (s.server_info_.addr_.is_valid()) { + // do nothing + } else { + LOG_DEBUG("ObMysqlTransact::handle_bl_lookup] binlog location lookup successful", + "pl_attempts", s.pll_info_.pl_attempts_); + const ObProxyPartitionLocation *pl = s.pll_info_.route_.table_entry_->get_first_pl(); + if (NULL != pl && pl->replica_count() > 0) { + s.server_info_.set_addr(ops_ip_sa_cast(pl->get_replica(0)->server_.get_sockaddr())); + s.pll_info_.route_.cur_chosen_server_.replica_ = pl->get_replica(0); + } else { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("not found binlog server replica", K(ret)); + } + } + + if (OB_SUCC(ret)) { + LOG_DEBUG("[ObMysqlTransact::handle_bl_lookup] chosen server, and begin to congestion lookup", + "addr", s.server_info_.addr_, + "attempts", s.current_.attempts_, + "sm_id", s.sm_->sm_id_); + if (OB_UNLIKELY(get_global_performance_params().enable_trace_)) { + s.sm_->milestones_.bl_process_end_ = get_based_hrtime(s); + s.sm_->cmd_time_stats_.bl_process_time_ += + milestone_diff(s.sm_->milestones_.bl_process_begin_, s.sm_->milestones_.bl_process_end_); + } + // At present, binlog does not have high-availability features. + // After routing, it directly forwards and does not follow the disaster recovery management process. + TRANSACT_RETURN(SM_ACTION_OBSERVER_OPEN, ObMysqlTransact::handle_response); + } + + if (OB_FAIL(ret)) { + s.inner_errcode_ = ret; + // disconnect + TRANSACT_RETURN(SM_ACTION_SEND_ERROR_NOOP, NULL); + } +} + } // end of namespace proxy } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/proxy/mysql/ob_mysql_transact.h b/src/obproxy/proxy/mysql/ob_mysql_transact.h index 76b827926ff2055cfb476459fc557caa500c3069..6a5242956ac93a6b03f72f9af6247c4e71c62c1d 100644 --- a/src/obproxy/proxy/mysql/ob_mysql_transact.h +++ b/src/obproxy/proxy/mysql/ob_mysql_transact.h @@ -24,10 +24,12 @@ #include "proxy/mysqllib/ob_mysql_config_processor.h" #include "proxy/route/ob_table_cache.h" #include "proxy/route/ob_server_route.h" +#include "proxy/route/ob_tenant_server.h" #include "proxy/mysql/ob_mysql_proxy_port.h" #include "cmd/ob_show_sqlaudit_handler.h" #include "proxy/api/ob_transform.h" -#include "proxy/mysqllib/ob_proxy_session_info.h" +#include "proxy/mysqllib/ob_proxy_ob20_request.h" +#include "lib/oblog/ob_simple_trace.h" namespace oceanbase { @@ -51,7 +53,6 @@ class ObMysqlSM; class ObMysqlClientSession; class ObClientSessionInfo; class ObServerSessionInfo; -struct ObTransactionStat; class ObSqlauditRecordQueue; enum @@ -69,6 +70,12 @@ public: MAYBE_ABORTED, ABORTED }; + enum ObPLLookupState + { + NEED_PL_LOOKUP = 0, + USE_LAST_SERVER_SESSION, + USE_COORDINATOR_SESSION + }; enum ObMysqlTransactMagic { @@ -85,6 +92,8 @@ public: }; static common::ObString get_retry_status_string(const ObSSRetryStatus status); + static common::ObString get_pl_lookup_state_string(const ObPLLookupState state); + // Please do not forget to fix ObServerState // (ob_api.h) in case of any modifications in @@ -104,6 +113,7 @@ public: TRANSACTION_COMPLETE, DEAD_CONGESTED, ALIVE_CONGESTED, + DETECT_CONGESTED, INTERNAL_ERROR }; @@ -127,6 +137,8 @@ public: RESET_SESSION_VARS_COMMON_ERROR, // sync start trans related START_TRANS_COMMON_ERROR, + // sync xa start related + START_XA_START_ERROR, // sync database related SYNC_DATABASE_COMMON_ERROR, // sync com_stmt_prepare @@ -143,7 +155,7 @@ public: REQUEST_READ_ONLY_ERROR, REQUEST_REROUTE_ERROR, STANDBY_WEAK_READONLY_ERROR, - + TRANS_FREE_ROUTE_NOT_SUPPORTED_ERROR, // attention!! add error type between MIN_RESP_ERROR and MAX_RESP_ERROR MAX_RESP_ERROR }; @@ -183,6 +195,8 @@ public: SM_ACTION_API_SEND_RESPONSE, SM_ACTION_API_CMD_COMPLETE, SM_ACTION_API_SM_SHUTDOWN, + + SM_ACTION_BINLOG_LOCATION_LOOKUP, }; enum ObAttachDummyEntryType @@ -267,12 +281,13 @@ public: SERVER_SEND_ALL_SESSION_VARS, SERVER_SEND_USE_DATABASE, SERVER_SEND_SESSION_VARS, - SERVER_SEND_LAST_INSERT_ID, + SERVER_SEND_SESSION_USER_VARS, SERVER_SEND_START_TRANS, + SERVER_SEND_XA_START, SERVER_SEND_REQUEST, SERVER_SEND_PREPARE, SERVER_SEND_SSL_REQUEST, - SERVER_SEND_TEXT_PS_PREPARE, + SERVER_SEND_TEXT_PS_PREPARE }; struct ObCurrentInfo @@ -381,15 +396,11 @@ public: { return route_.get_next_avail_replica(); } - const ObProxyReplicaLocation *get_next_replica(const uint32_t cur_ip, const uint16_t cur_port, - const bool is_force_retry) - { - return route_.get_next_replica(cur_ip, cur_port, is_force_retry); - } const ObProxyReplicaLocation *get_leader_replica_from_remote() { return route_.get_leader_replica_from_remote(); } + void reset_consistency(); void reset_pl(); void reset(); @@ -481,11 +492,12 @@ public: sm_(NULL), mysql_config_params_(NULL), is_rerouted_(false), - need_pl_lookup_(false), + pl_lookup_state_ (NEED_PL_LOOKUP), is_auth_request_(false), is_trans_first_request_(false), is_proxysys_tenant_(false), is_hold_start_trans_(false), + is_hold_xa_start_(false), send_reqeust_direct_(false), source_(SOURCE_NONE), pre_transform_source_(SOURCE_NONE), @@ -513,7 +525,9 @@ public: is_congestion_entry_updated_(false), api_mysql_sm_shutdown_(false), api_server_addr_set_(false), - sqlaudit_record_queue_(NULL) + need_retry_(true), + sqlaudit_record_queue_(NULL), + trace_log_() { memset(user_args_, 0, sizeof(user_args_)); } @@ -529,9 +543,8 @@ public: PROXY_TXN_LOG(WARN, "invalid argument", K(sm), K(ret)); } else { sm_ = sm; - need_pl_lookup_ = true; + pl_lookup_state_ = NEED_PL_LOOKUP; current_stats_ = &first_stats_; - refresh_mysql_config(); trans_info_.reset(); } return ret; @@ -542,34 +555,11 @@ public: return ((mysql_config_params_->sqlaudit_mem_limited_ > 0) && (NULL != sqlaudit_record_queue_)); } - void refresh_mysql_config() - { - if (OB_UNLIKELY(mysql_config_params_ != get_global_mysql_config_processor().get_config())) { - ObMysqlConfigParams *config = NULL; - if (OB_ISNULL(config = get_global_mysql_config_processor().acquire())) { - PROXY_TXN_LOG(WARN, "failed to acquire mysql config"); - } else { - if (OB_LIKELY(NULL != mysql_config_params_)) { - mysql_config_params_->dec_ref(); - mysql_config_params_ = NULL; - } - mysql_config_params_ = config; - } - ObMysqlTransact::handle_new_config_acquired(*this); - } - - if (OB_UNLIKELY(get_global_performance_params().enable_trace_)) { - if (NULL != sqlaudit_record_queue_) { - sqlaudit_record_queue_->refcount_dec(); - sqlaudit_record_queue_ = NULL; - } - - if (mysql_config_params_->sqlaudit_mem_limited_ > 0) { - sqlaudit_record_queue_ = get_global_sqlaudit_processor().acquire(); - } - } - } - + void refresh_mysql_config(); + int get_config_item(const common::ObString& cluster_name, + const common::ObString &tenant_name, + const obutils::ObVipAddr &addr, + const int64_t global_version = 0); void record_transaction_stats() { // Loop over our transaction stat blocks and record the stats @@ -688,30 +678,19 @@ public: reroute_info_.reset(); if (CMD_COMPLETE == current_.state_) { - if (!is_hold_start_trans_) { + if (!is_hold_start_trans_ && !is_hold_xa_start_) { is_trans_first_request_ = false; } if (obmysql::OB_MYSQL_COM_LOGIN == trans_info_.sql_cmd_) { is_auth_request_ = false; } + pll_info_.reset_consistency(); } else if (TRANSACTION_COMPLETE == current_.state_) { + trace_log_.reset(); is_trans_first_request_ = true; is_auth_request_ = false; - - if (NULL != congestion_entry_) { - // if this trans succ, just set avlie this server; - if (!is_congestion_entry_updated_) { - congestion_entry_->set_alive_congested_free(); - } - congestion_entry_->dec_ref(); - congestion_entry_ = NULL; - } - is_congestion_entry_updated_ = false; - congestion_entry_not_exist_count_ = 0; - need_congestion_lookup_ = true; - congestion_lookup_success_ = false; - force_retry_congested_ = false; + reset_congestion_entry(); mysql_errmsg_ = NULL; inner_errcode_ = 0; inner_errmsg_ = NULL; @@ -722,6 +701,7 @@ public: } server_info_.reset(); + pre_server_info_.reset(); current_.reset(); trans_info_.reset(); pll_info_.reset(); @@ -730,6 +710,23 @@ public: } else { /* do nothing */ } } + void reset_congestion_entry() + { + if (NULL != congestion_entry_) { + // if this trans succ, just set alive this server; + if (!is_congestion_entry_updated_) { + congestion_entry_->set_alive_congested_free(); + } + congestion_entry_->dec_ref(); + congestion_entry_ = NULL; + } + is_congestion_entry_updated_ = false; + congestion_entry_not_exist_count_ = 0; + need_congestion_lookup_ = true; + congestion_lookup_success_ = false; + force_retry_congested_ = false; + } + void destroy() { record_transaction_stats(); @@ -757,9 +754,11 @@ public: static bool is_for_update_sql(common::ObString src_sql); common::ObConsistencyLevel get_trans_consistency_level(ObClientSessionInfo &cs_info); + common::ObConsistencyLevel get_read_write_consistency_level(ObClientSessionInfo &session_info); bool is_request_readonly_zone_support(ObClientSessionInfo &cs_info); ObRoutePolicyEnum get_route_policy(ObMysqlClientSession &cs, const bool need_use_dup_replica); void get_route_policy(ObProxyRoutePolicyEnum policy, ObRoutePolicyEnum& ret_policy); + bool is_need_pl_lookup() { return pl_lookup_state_ == NEED_PL_LOOKUP; } event::ObFixedArenaAllocator<1024> arena_; @@ -769,16 +768,20 @@ public: ObMysqlConfigParams *mysql_config_params_; ObConnectionAttributes client_info_; ObConnectionAttributes server_info_; + // fail-fast probe use + ObConnectionAttributes pre_server_info_; ObCurrentInfo current_; ObTransactInfo trans_info_; bool is_rerouted_; - bool need_pl_lookup_; + // determin if do pl lookup + ObPLLookupState pl_lookup_state_; bool is_auth_request_; bool is_trans_first_request_; bool is_proxysys_tenant_; bool is_hold_start_trans_; // indicate whether hold begin(start transaction) + bool is_hold_xa_start_; bool send_reqeust_direct_; // when send sync all session variables, we can send user request directly ObSourceType source_; @@ -820,8 +823,10 @@ public: bool is_congestion_entry_updated_; bool api_mysql_sm_shutdown_; bool api_server_addr_set_; + bool need_retry_; ObSqlauditRecordQueue *sqlaudit_record_queue_; + common::ObSimpleTrace<4096> trace_log_; private: DISALLOW_COPY_AND_ASSIGN(ObTransState); @@ -833,7 +838,7 @@ public: static void handle_mysql_request(ObTransState &s); static int set_server_ip_by_shard_conn(ObTransState &s, dbconfig::ObShardConnector* shard_conn); static void handle_oceanbase_request(ObTransState &s); - static void handle_ps_close(ObTransState &s); + static void handle_ps_close_reset(ObTransState &s); static void handle_fetch_request(ObTransState &s); static void handle_request(ObTransState &s); static int build_normal_login_request(ObTransState &s, event::ObIOBufferReader *&reader, @@ -843,6 +848,10 @@ public: static int build_oceanbase_user_request(ObTransState &s, event::ObIOBufferReader *client_buffer_reader, event::ObIOBufferReader *&reader, int64_t &request_len); + static int build_oceanbase_ob20_user_request(ObTransState &s, event::ObMIOBuffer &write_buffer, + event::ObIOBufferReader &request_buffer_reader, + int64_t client_request_len, + uint8_t &compress_seq); static int build_user_request(ObTransState &s, event::ObIOBufferReader *client_buffer_reader, event::ObIOBufferReader *&reader, int64_t &request_len); static int rewrite_stmt_id(ObTransState &s, event::ObIOBufferReader *client_buffer_reader); @@ -856,11 +865,13 @@ public: static void handle_error_jump(ObTransState &s); static void handle_internal_request(ObTransState &s); + static void handle_binlog_request(ObTransState &s); static void handle_server_addr_lookup(ObTransState &s); static void get_region_name_and_server_info(ObTransState &s, common::ObIArray &simple_servers_info, common::ObIArray ®ion_names); static void handle_pl_lookup(ObTransState &s); + static void handle_bl_lookup(ObTransState &s); static void modify_pl_lookup(ObTransState &s); static void handle_congestion_control_lookup(ObTransState &s); static void handle_congestion_entry_not_exist(ObTransState &s); @@ -883,6 +894,7 @@ public: static bool is_dbmesh_pool_user(ObTransState &s); static bool is_internal_request(ObTransState &s); + static bool is_binlog_request(const ObTransState &s); static bool is_single_shard_db_table(ObTransState &s); static bool can_direct_ok_for_login(ObTransState &s); static bool is_in_trans(ObTransState &s); @@ -891,29 +903,28 @@ public: static bool is_bad_route_request(ObTransState &s); static bool is_session_memory_overflow(ObTransState &s); static bool need_use_dup_replica(const common::ObConsistencyLevel level, ObTransState &s); - static bool need_pl_lookup(ObTransState &s); - static bool need_use_last_server_session(ObTransState &s); + static ObPLLookupState need_pl_lookup(ObTransState &s); + static bool need_use_coordinator_session(ObTransState &s); static bool is_db_reset(ObTransState &s); static bool need_server_session_lookup(ObTransState &s); static int64_t get_max_connect_attempts_from_replica(const int64_t replica_size); static int64_t get_max_connect_attempts(ObTransState &s); static int build_table_entry_request_packet(ObTransState &s, event::ObIOBufferReader *&reader); - static void handle_resultset_resp(ObTransState &s); + static void handle_resultset_resp(ObTransState &s, bool &is_user_request); static int fetch_table_entry_info(ObTransState &s); static ObClientSessionInfo &get_client_session_info(ObTransState &s); static ObServerSessionInfo &get_server_session_info(ObTransState &s); static void consume_response_packet(ObTransState &s); - static int build_no_privilege_message(ObTransState &trans_state, - ObMysqlClientSession &client_session, + static int build_no_privilege_message(ObTransState &trans_state, ObMysqlClientSession &client_session, const common::ObString &database); static void handle_handshake_pkt(ObTransState &s); static int handle_oceanbase_handshake_pkt(ObTransState &s, uint32_t conn_id, ObAddr &client_addr); - static void handle_error_resp(ObTransState &s); - static void handle_ok_resp(ObTransState &s); + static void handle_error_resp(ObTransState &s, bool &is_user_request); + static void handle_ok_resp(ObTransState &s, bool &is_user_request); static void handle_db_reset(ObTransState &s); static void handle_first_response_packet(ObTransState &s); @@ -924,7 +935,7 @@ public: static void update_sql_cmd(ObTransState &s); // check if the global_vars_version is changed, called when receive saved login responce static int check_global_vars_version(ObTransState &s, const obmysql::ObStringKV &str_kv); - static void handle_user_request_succ(ObTransState &s); + static void handle_user_request_succ(ObTransState &s, bool &is_user_request); static int handle_user_set_request_succ(ObTransState &s); static int handle_normal_user_request_succ(ObTransState &s); static void handle_saved_login_succ(ObTransState &s); @@ -936,10 +947,15 @@ public: static void handle_execute_succ(ObTransState &s); static int do_handle_execute_succ(ObTransState &s); static void handle_prepare_execute_succ(ObTransState &s); + static int do_handle_prepare_execute_xa_succ(event::ObIOBufferReader &buf_reader); static void handle_text_ps_prepare_succ(ObTransState &s); + static int handle_text_ps_drop_succ(ObTransState &s, bool &is_user_request); static int handle_change_user_request_succ(ObTransState &s); + static int handle_reset_connection_request_succ(ObTransState &s); + static int clear_session_related_source(ObTransState &s); + static int handle_ps_reset_succ(ObTransState &s, bool &is_user_request); - static int build_error_packet(ObTransState &s); + static int build_error_packet(ObTransState &s, ObMysqlClientSession *client_session); static void handle_new_config_acquired(ObTransState &s); @@ -967,12 +983,17 @@ public: static const char *get_send_action_name(ObMysqlTransact::ObServerSendActionType type); static const char *get_server_resp_error_name(ObMysqlTransact::ObServerRespErrorType type); - static int64_t build_addr_from_ip_port(const uint32_t ip, const uint16_t port); static void get_ip_port_from_addr(const int64_t addr, uint32_t &ip, uint16_t &port); static void check_safe_read_snapshot(ObTransState &s); static bool is_need_reroute(ObMysqlTransact::ObTransState &s); static bool is_need_use_sql_table_cache(ObMysqlTransact::ObTransState &s); + static bool handle_set_trans_internal_routing(ObMysqlTransact::ObTransState &s, bool server_transaction_routing_flag); + static bool is_sql_able_to_route_participant_in_trans(obutils::ObSqlParseResult& base_sql_parse_result, obmysql::ObMySQLCmd sql_cmd); + static bool is_trans_specified(ObTransState &s); + static bool has_dependent_func(ObTransState &s); + static void record_trans_state(ObTransState &s, bool is_in_trans); + static bool is_addr_logonly(const net::ObIpEndpoint &addr, const ObTenantServer *ts); }; inline bool ObMysqlTransact::is_need_use_sql_table_cache(ObMysqlTransact::ObTransState &s) @@ -986,20 +1007,6 @@ inline bool ObMysqlTransact::is_need_use_sql_table_cache(ObMysqlTransact::ObTran typedef void (*TransactEntryFunc)(ObMysqlTransact::ObTransState &s); -inline bool ObMysqlTransact::is_in_trans(ObTransState &s) -{ - // if a trans is commit, the state will be set to TRANSACTION_COMPLETE, - // so if current state is CMD_COMPLETE, it means that we have send a sql successfully and - // the trans has not commit, that is to say "in trans" - // so far, there are three cases NOT in trans: - // 1. handshake response (login packet) need pl lookup - // 2. the first sql of one transaction - // 3. the second sql of one transaction, if the first sql is 'begin' or 'start transaction' - return (!s.is_auth_request_ - && ObMysqlTransact::CMD_COMPLETE == s.current_.state_ - && !s.is_hold_start_trans_); -} - inline bool ObMysqlTransact::is_user_trans_complete(ObTransState &s) { return (!s.is_trans_first_request_ @@ -1010,7 +1017,7 @@ inline bool ObMysqlTransact::is_user_trans_complete(ObTransState &s) inline bool ObMysqlTransact::is_bad_route_request(ObTransState &s) { bool bret = false; - if (s.mysql_config_params_->enable_bad_route_reject_ && s.is_hold_start_trans_) { + if (s.mysql_config_params_->enable_bad_route_reject_ && (s.is_hold_start_trans_ || s.is_hold_xa_start_)) { obutils::ObSqlParseResult &parse_result = s.trans_info_.client_request_.get_parse_result(); const ObString &table_name = parse_result.get_table_name(); bret = table_name.empty(); @@ -1048,11 +1055,6 @@ inline int64_t ObMysqlTransact::get_max_connect_attempts_from_replica(const int6 return (replica_size * 2 + 1); } -inline int64_t ObMysqlTransact::get_max_connect_attempts(ObTransState &s) -{ - return std::max(s.mysql_config_params_->connect_observer_max_retries_, - get_max_connect_attempts_from_replica(s.pll_info_.replica_size())); -} inline bool ObMysqlTransact::is_in_auth_process(ObTransState &s) { @@ -1099,6 +1101,11 @@ inline int64_t milestone_diff(const ObHRTime start, const ObHRTime end) return (start > 0 && end > start) ? (end - start) : 0; } +inline void ObMysqlTransact::ObPartitionLookupInfo::reset_consistency() +{ + route_.set_consistency_level(common::INVALID_CONSISTENCY); +} + inline void ObMysqlTransact::ObPartitionLookupInfo::reset_pl() { route_.reset(); @@ -1141,11 +1148,16 @@ inline void ObMysqlTransact::update_sql_cmd(ObTransState &s) case SERVER_SEND_ALL_SESSION_VARS: case SERVER_SEND_SESSION_VARS: - case SERVER_SEND_LAST_INSERT_ID: + case SERVER_SEND_SESSION_USER_VARS: case SERVER_SEND_START_TRANS: case SERVER_SEND_TEXT_PS_PREPARE: s.trans_info_.sql_cmd_ = obmysql::OB_MYSQL_COM_QUERY; break; + + case SERVER_SEND_XA_START: + PROXY_TXN_LOG(DEBUG, "[ObMysqlTransact::update_sql_cmd] set s.trans_info_.sql_cmd OB_MYSQL_COM_STMT_PREPARE_EXECUTE for sync xa start"); + s.trans_info_.sql_cmd_ = obmysql::OB_MYSQL_COM_STMT_PREPARE_EXECUTE; + break; case SERVER_SEND_PREPARE: s.trans_info_.sql_cmd_ = obmysql::OB_MYSQL_COM_STMT_PREPARE; @@ -1189,9 +1201,23 @@ inline common::ObString ObMysqlTransact::get_retry_status_string(const ObSSRetry return common::ObString::make_string(str); } -inline int64_t ObMysqlTransact::build_addr_from_ip_port(const uint32_t ip, const uint16_t port) +inline common::ObString ObMysqlTransact::get_pl_lookup_state_string(const ObPLLookupState state) { - return (static_cast(port) << 32) | ip; + const char *str = ""; + switch (state) { + case NEED_PL_LOOKUP: + str = "NEED_PL_LOOKUP"; + break; + case USE_LAST_SERVER_SESSION: + str = "USE_LAST_SERVER_SESSION"; + break; + case USE_COORDINATOR_SESSION: + str = "USE_COORDINATOR_SESSION"; + break; + default: + str = "UNKNOWN"; + } + return common::ObString::make_string(str); } inline void ObMysqlTransact::get_ip_port_from_addr(const int64_t addr, uint32_t &ip, uint16_t &port) @@ -1202,6 +1228,28 @@ inline void ObMysqlTransact::get_ip_port_from_addr(const int64_t addr, uint32_t port = static_cast((addr & PORT_MASK) >> 32); } +inline bool ObMysqlTransact::is_addr_logonly(const net::ObIpEndpoint &addr, const ObTenantServer *ts) +{ + bool ret = false; + if (OB_ISNULL(ts)) { + ret = false; + } else { + int64_t cnt = ts->server_count_; + ObAddr tmp_addr; + tmp_addr.reset(); + tmp_addr.set_sockaddr(addr.sa_); + for (int64_t i = 0; i < cnt; ++i) { + if (tmp_addr == ts->get_replica_location(i)->server_ + && (common::REPLICA_TYPE_LOGONLY == ts->get_replica_location(i)->get_replica_type() + || common::REPLICA_TYPE_ENCRYPTION_LOGONLY == ts->get_replica_location(i)->get_replica_type())) { + ret = true; + break; + } + } + } + return ret; +} + } // end of namespace proxy } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/proxy/mysql/ob_mysql_tunnel.cpp b/src/obproxy/proxy/mysql/ob_mysql_tunnel.cpp index 7cdcf90b40b5a2373db58cfba2863dc2f3b34b5e..fa39e1571be9cd7f1eb8f7b92c93a7f7d7ed8393 100644 --- a/src/obproxy/proxy/mysql/ob_mysql_tunnel.cpp +++ b/src/obproxy/proxy/mysql/ob_mysql_tunnel.cpp @@ -588,7 +588,8 @@ inline int ObMysqlTunnel::producer_handler_packet(int event, ObMysqlTunnelProduc case VC_EVENT_READ_COMPLETE: case MYSQL_TUNNEL_EVENT_PRECOMPLETE: case VC_EVENT_INACTIVITY_TIMEOUT: - case VC_EVENT_EOS: { + case VC_EVENT_EOS: + case VC_EVENT_DETECT_SERVER_DEAD: { p.packet_analyzer_.last_server_event_ = event; // If we couldn't understand the encoding, return an error @@ -765,6 +766,7 @@ bool ObMysqlTunnel::producer_handler(int event, ObMysqlTunnelProducer &p) case VC_EVENT_ERROR: case VC_EVENT_ACTIVE_TIMEOUT: case VC_EVENT_INACTIVITY_TIMEOUT: + case VC_EVENT_DETECT_SERVER_DEAD: case MYSQL_TUNNEL_EVENT_CONSUMER_DETACH: p.alive_ = false; p.bytes_read_ = p.read_vio_->ndone_; @@ -915,7 +917,8 @@ bool ObMysqlTunnel::consumer_handler(int event, ObMysqlTunnelConsumer &c) case VC_EVENT_EOS: case VC_EVENT_ERROR: case VC_EVENT_ACTIVE_TIMEOUT: - case VC_EVENT_INACTIVITY_TIMEOUT: { + case VC_EVENT_INACTIVITY_TIMEOUT: + case VC_EVENT_DETECT_SERVER_DEAD: { c.alive_ = false; c.bytes_written_ = c.write_vio_ ? c.write_vio_->ndone_ : 0; diff --git a/src/obproxy/proxy/mysql/ob_prepare_statement_struct.cpp b/src/obproxy/proxy/mysql/ob_prepare_statement_struct.cpp index 3453ee2c5057d1936c262b5d3602772df880ecef..e60c7380a177204a5fb1efd0957632a2cb164279 100644 --- a/src/obproxy/proxy/mysql/ob_prepare_statement_struct.cpp +++ b/src/obproxy/proxy/mysql/ob_prepare_statement_struct.cpp @@ -91,15 +91,13 @@ DEF_TO_STRING(ObTextPsNameEntry) { int64_t pos = 0; J_OBJ_START(); - J_KV(KP(this), K_(text_ps_name), KPC_(text_ps_entry)); + J_KV(KP(this), K_(text_ps_name), KPC_(text_ps_entry), K_(version)); J_OBJ_END(); return pos; } -void ObBasePsEntry::destroy() { - if (NULL != ps_entry_cache_) { - ps_entry_cache_->delete_base_ps_entry(this); - } +void ObBasePsEntry::destroy() +{ base_ps_parse_result_.reset(); } @@ -125,16 +123,22 @@ int ObPsIdAddrs::alloc_ps_id_addrs(uint32_t ps_id, const struct sockaddr &addr, int ObPsIdAddrs::add_addr(const struct sockaddr &socket_addr) { int ret = OB_SUCCESS; net::ObIpEndpoint addr(socket_addr); - if (OB_FAIL(addrs_.set_refactored(addr))) { + if (OB_FAIL(addrs_.push_back(addr))) { LOG_WARN("set refactored failed", K(addr), K(ret)); } return ret; } + int ObPsIdAddrs::remove_addr(const struct sockaddr &socket_addr) { int ret = OB_SUCCESS; net::ObIpEndpoint addr(socket_addr); - if (OB_FAIL(addrs_.erase_refactored(addr))) { - LOG_WARN("set refactored failed", K(addr), K(ret)); + for(int64_t i = 0; OB_SUCC(ret) && i < addrs_.count(); i++) { + if (addr == addrs_.at(i)) { + if (OB_FAIL(addrs_.remove(i))) { + LOG_WARN("fail to remove", K(i), K(ret)); + } + break; + } } return ret; } @@ -217,40 +221,6 @@ int ObPsSqlMeta::set_param_type(const char *param_type, int64_t param_type_len) return ret; } -int ObPsEntry::alloc_and_init_ps_entry(const ObString &ps_sql, - const ObSqlParseResult &parse_result, - ObPsEntry *&entry) -{ - int ret = OB_SUCCESS; - int64_t alloc_size = 0; - char *buf = NULL; - - int64_t obj_size = sizeof(ObPsEntry); - int64_t sql_len = ps_sql.length() + PARSE_EXTRA_CHAR_NUM; - - alloc_size += sizeof(ObPsEntry) + sql_len; - if (OB_ISNULL(buf = static_cast(op_fixed_mem_alloc(alloc_size)))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to alloc mem for ps entry", K(alloc_size), K(ret)); - } else { - entry = new (buf) ObPsEntry(); - if (OB_FAIL(entry->init(buf + obj_size, alloc_size - obj_size))) { - LOG_WARN("fail to init ps entry", K(ret)); - } else if (OB_FAIL(entry->set_sql(ps_sql))) { - LOG_WARN("fail to set ps sql", K(ret)); - } else { - entry->set_base_ps_parse_result(parse_result); - } - } - - if (OB_FAIL(ret) && NULL != buf) { - op_fixed_mem_free(buf, alloc_size); - entry = NULL; - alloc_size = 0; - } - return ret; -} - int ObPsEntry::init(char *buf_start, int64_t buf_len) { int ret = OB_SUCCESS; @@ -287,9 +257,17 @@ int ObPsEntry::set_sql(const ObString &ps_sql) return ret; } +void ObPsEntry::free() +{ + if (NULL != ps_entry_cache_) { + ps_entry_cache_->delete_base_ps_entry(this); + } + destroy(); +} + void ObPsEntry::destroy() { - LOG_INFO("ps entry will be destroyed", KPC(this)); + LOG_DEBUG("ps entry will be destroyed", KPC(this)); if (OB_LIKELY(is_inited_)) { ObBasePsEntry::destroy(); is_inited_ = false; @@ -300,64 +278,12 @@ void ObPsEntry::destroy() } } -void ObBasePsEntryCache::destroy() -{ - ObBasePsEntryMap::iterator last = base_ps_map_.end(); - ObBasePsEntryMap::iterator tmp_iter; - for (ObBasePsEntryMap::iterator base_ps_iter = base_ps_map_.begin(); base_ps_iter != last;) { - tmp_iter = base_ps_iter; - ++base_ps_iter; - tmp_iter->destroy(); - } - base_ps_map_.reset(); -} - -int init_ps_entry_cache_for_thread() -{ - int ret = OB_SUCCESS; - const int64_t event_thread_count = g_event_processor.thread_count_for_type_[ET_CALL]; - for (int64_t i = 0; i < event_thread_count && OB_SUCC(ret); ++i) { - if (OB_ISNULL(g_event_processor.event_thread_[ET_CALL][i]->ps_entry_cache_ - = new (std::nothrow) ObBasePsEntryCache())) { - ret = OB_ALLOCATE_MEMORY_FAILED; - PROXY_NET_LOG(WARN, "fail to new ObBasePsEntryCache", K(i), K(ret)); - } - } - return ret; -} - -int ObTextPsEntry::alloc_and_init_text_ps_entry(const ObString &text_ps_sql, - const ObSqlParseResult &parse_result, - ObTextPsEntry *&entry) +void ObGlobalPsEntry::free() { - int ret = OB_SUCCESS; - int64_t alloc_size = 0; - char *buf = NULL; - - int64_t obj_size = sizeof(ObTextPsEntry); - int64_t sql_len = text_ps_sql.length() + PARSE_EXTRA_CHAR_NUM; - - alloc_size = obj_size + sql_len; - if (OB_ISNULL(buf = static_cast(op_fixed_mem_alloc(alloc_size)))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to alloc mem for text ps entry", K(alloc_size), K(ret)); - } else { - entry = new (buf) ObTextPsEntry(); - if (OB_FAIL(entry->init(buf + obj_size, alloc_size - obj_size, text_ps_sql))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to alloc mem for text ps entry", K(alloc_size), K(ret)); - } else { - entry->set_base_ps_parse_result(parse_result); - } - } - - if (OB_FAIL(ret) && NULL != buf) { - op_fixed_mem_free(buf, alloc_size); - entry = NULL; - alloc_size = 0; + LOG_DEBUG("global ps entry will be destroyed", KPC(this)); + if (NULL != ps_entry_cache_) { + ps_entry_cache_->delete_base_ps_entry(this); } - - return ret; } int ObTextPsEntry::init(char *buf_start, int64_t buf_len, const ObString &text_ps_sql) @@ -387,16 +313,35 @@ int ObTextPsEntry::init(char *buf_start, int64_t buf_len, const ObString &text_p return ret; } +void ObTextPsEntry::free() +{ + if (NULL != ps_entry_cache_) { + ps_entry_cache_->delete_base_ps_entry(this); + } + destroy(); +} + void ObTextPsEntry::destroy() { LOG_INFO("text ps entry will be destroyed", KPC(this)); if (OB_LIKELY(is_inited_)) { + ObBasePsEntry::destroy(); is_inited_ = false; - int64_t total_len = sizeof(ObTextPsEntry) + base_ps_sql_.length() + PARSE_EXTRA_CHAR_NUM; + int64_t total_len = sizeof(ObTextPsEntry) + buf_len_; + buf_start_ = NULL; + buf_len_ = 0; op_fixed_mem_free(this, total_len); } } +void ObGlobalTextPsEntry::free() +{ + LOG_INFO("global text ps entry will be destroyed", KPC(this)); + if (NULL != ps_entry_cache_) { + ps_entry_cache_->delete_base_ps_entry(this); + } +} + int ObTextPsNameEntry::alloc_text_ps_name_entry(const ObString &text_ps_name, ObTextPsEntry *text_ps_entry, ObTextPsNameEntry *&text_ps_name_entry) @@ -408,7 +353,7 @@ int ObTextPsNameEntry::alloc_text_ps_name_entry(const ObString &text_ps_name, LOG_WARN("stmt name is empty", K(ret)); } else { char *buf = NULL; - int64_t alloc_size = sizeof(ObTextPsNameEntry) + text_ps_name.size(); + int64_t alloc_size = sizeof(ObTextPsNameEntry) + text_ps_name.length(); if (OB_ISNULL(buf = static_cast(op_fixed_mem_alloc(alloc_size)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to alloc mem for text ps name entry", K(alloc_size), K(ret)); @@ -424,11 +369,106 @@ int ObTextPsNameEntry::alloc_text_ps_name_entry(const ObString &text_ps_name, void ObTextPsNameEntry::destroy() { - LOG_INFO("text ps entry will be destroyed", KPC(this)); + LOG_INFO("text ps name entry will be destroyed", KPC(this)); int64_t total_len = sizeof(ObTextPsNameEntry) + text_ps_name_.length(); + text_ps_entry_->dec_ref(); + text_ps_entry_ = NULL; op_fixed_mem_free(this, total_len); } +void ObBasePsEntryThreadCache::delete_base_ps_entry(ObBasePsEntry *base_ps_entry) +{ + ps_entry_thread_map_.remove(base_ps_entry); +} + +void ObBasePsEntryThreadCache::destroy() +{ + ObBasePsEntryMap::iterator last = ps_entry_thread_map_.end(); + ObBasePsEntryMap::iterator tmp_iter; + for (ObBasePsEntryMap::iterator base_ps_iter = ps_entry_thread_map_.begin(); base_ps_iter != last;) { + tmp_iter = base_ps_iter; + ++base_ps_iter; + tmp_iter->destroy(); + } + ps_entry_thread_map_.reset(); +} + +void ObBasePsEntryGlobalCache::delete_base_ps_entry(ObBasePsEntry *base_ps_entry) +{ + common::DRWLock::WRLockGuard guard(lock_); + ps_entry_global_map_.remove(base_ps_entry); +} + +void ObBasePsEntryGlobalCache::destroy() +{ + ObBasePsEntryGlobalMap::iterator last = ps_entry_global_map_.end(); + ObBasePsEntryGlobalMap::iterator tmp_iter; + for (ObBasePsEntryGlobalMap::iterator base_ps_iter = ps_entry_global_map_.begin(); base_ps_iter != last;) { + tmp_iter = base_ps_iter; + ++base_ps_iter; + tmp_iter->destroy(); + } + ps_entry_global_map_.reset(); +} + +int init_ps_entry_cache_for_thread() +{ + int ret = OB_SUCCESS; + const int64_t event_thread_count = g_event_processor.thread_count_for_type_[ET_CALL]; + for (int64_t i = 0; i < event_thread_count && OB_SUCC(ret); ++i) { + if (OB_FAIL(init_ps_entry_cache_for_one_thread(i))) { + PROXY_NET_LOG(WARN, "fail to new ObBasePsEntryThreadCache", K(i), K(ret)); + } + } + return ret; +} + +int init_text_ps_entry_cache_for_thread() +{ + int ret = OB_SUCCESS; + const int64_t event_thread_count = g_event_processor.thread_count_for_type_[ET_CALL]; + for (int64_t i = 0; i < event_thread_count && OB_SUCC(ret); ++i) { + if (OB_FAIL(init_text_ps_entry_cache_for_one_thread(i))) { + PROXY_NET_LOG(WARN, "fail to new ObBasePsEntryThreadCache", K(i), K(ret)); + } + } + return ret; +} + +int init_ps_entry_cache_for_one_thread(int64_t index) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(g_event_processor.event_thread_[ET_CALL][index]->ps_entry_cache_ + = new (std::nothrow) ObBasePsEntryThreadCache())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + PROXY_NET_LOG(WARN, "fail to new ObBasePsEntryThreadCache", K(index), K(ret)); + } + return ret; +} + +int init_text_ps_entry_cache_for_one_thread(int64_t index) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(g_event_processor.event_thread_[ET_CALL][index]->text_ps_entry_cache_ + = new (std::nothrow) ObBasePsEntryThreadCache())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + PROXY_NET_LOG(WARN, "fail to new ObBasePsEntryThreadCache", K(index), K(ret)); + } + return ret; +} + +ObBasePsEntryGlobalCache &get_global_ps_entry_cache() +{ + static ObBasePsEntryGlobalCache ps_entry_cache; + return ps_entry_cache; +} + +ObBasePsEntryGlobalCache &get_global_text_ps_entry_cache() +{ + static ObBasePsEntryGlobalCache text_ps_entry_cache; + return text_ps_entry_cache; +} + } // end of namespace proxy } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/proxy/mysql/ob_prepare_statement_struct.h b/src/obproxy/proxy/mysql/ob_prepare_statement_struct.h index 5d43ce47490a18d2f025008617a3685d2cf1a79f..83fa44aa01f76bfbe4b48ce29779a4e671f0bb91 100644 --- a/src/obproxy/proxy/mysql/ob_prepare_statement_struct.h +++ b/src/obproxy/proxy/mysql/ob_prepare_statement_struct.h @@ -45,19 +45,9 @@ public: static const int BUCKET_SIZE = 8; static const int NODE_NUM = 8; - // use SimpleAllocer to save mem - typedef common::hash::ObHashSet, - common::hash::equal_to, - common::hash::SimpleAllocer::AllocType, NODE_NUM> - > ADDR_HASH_SET; - ObPsIdAddrs() : ps_id_(0), addrs_() { - addrs_.create(BUCKET_SIZE); } ObPsIdAddrs(uint32_t ps_id) : ps_id_(ps_id), addrs_() { - addrs_.create(BUCKET_SIZE); } ~ObPsIdAddrs() {}; @@ -65,13 +55,12 @@ public: void destroy(); int add_addr(const struct sockaddr &socket_addr); int remove_addr(const struct sockaddr &socket_addr); - ADDR_HASH_SET &get_addrs() { return addrs_; } + ObIArray &get_addrs() { return addrs_; } int64_t to_string(char *buf, const int64_t buf_len) const; public: uint32_t ps_id_; // client ps id - ADDR_HASH_SET addrs_; - + ObSEArray addrs_; LINK(ObPsIdAddrs, ps_id_addrs_link_); }; @@ -115,8 +104,7 @@ public: const common::ObString &get_base_ps_sql() { return base_ps_sql_; } - virtual void free() { destroy(); } - + virtual void free() {} virtual void destroy(); public: @@ -189,13 +177,14 @@ public: ObPsEntry() : ObBasePsEntry() {} ~ObPsEntry() {} + template static int alloc_and_init_ps_entry(const common::ObString &ps_sql, const obutils::ObSqlParseResult &parse_result, - ObPsEntry *&entry); + T *&entry); int init(char *buf_start, int64_t buf_len); - void destroy(); + virtual void free(); + virtual void destroy(); int set_sql(const common::ObString &ps_sql); - int64_t to_string(char *buf, const int64_t buf_len) const; private: @@ -205,6 +194,61 @@ public: DISALLOW_COPY_AND_ASSIGN(ObPsEntry); }; +class ObGlobalPsEntry : public ObPsEntry +{ +public: + ObGlobalPsEntry() : ObPsEntry() {} + ~ObGlobalPsEntry() {} + virtual void free(); + template + static int alloc_and_init_ps_entry(const common::ObString &ps_sql, + const obutils::ObSqlParseResult &parse_result, + T *&entry); +}; + +template +int ObGlobalPsEntry::alloc_and_init_ps_entry(const ObString &ps_sql, + const obutils::ObSqlParseResult &parse_result, + T *&entry) +{ + return ObPsEntry::alloc_and_init_ps_entry(ps_sql, parse_result, entry); +} + +template +int ObPsEntry::alloc_and_init_ps_entry(const ObString &ps_sql, + const obutils::ObSqlParseResult &parse_result, + T *&entry) +{ + int ret = OB_SUCCESS; + int64_t alloc_size = 0; + char *buf = NULL; + + int64_t obj_size = sizeof(T); + int64_t sql_len = ps_sql.length() + PARSE_EXTRA_CHAR_NUM; + + alloc_size += sizeof(T) + sql_len; + if (OB_ISNULL(buf = static_cast(op_fixed_mem_alloc(alloc_size)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + PROXY_SM_LOG(WARN, "fail to alloc mem for ps entry", K(alloc_size), K(ret)); + } else { + entry = new (buf) T(); + if (OB_FAIL(entry->init(buf + obj_size, alloc_size - obj_size))) { + PROXY_SM_LOG(WARN, "fail to init ps entry", K(ret)); + } else if (OB_FAIL(entry->set_sql(ps_sql))) { + PROXY_SM_LOG(WARN, "fail to set ps sql", K(ret)); + } else { + entry->set_base_ps_parse_result(parse_result); + } + } + + if (OB_FAIL(ret) && NULL != buf) { + op_fixed_mem_free(buf, alloc_size); + entry = NULL; + alloc_size = 0; + } + return ret; +} + // stored in client session info class ObPsIdEntry { @@ -212,7 +256,6 @@ public: ObPsIdEntry() : ps_id_(0), ps_entry_(NULL), ps_meta_() {} ObPsIdEntry(uint32_t client_id, ObPsEntry *entry) : ps_id_(client_id), ps_entry_(entry) { - ps_entry_->inc_ref(); } ~ObPsIdEntry() {} @@ -268,33 +311,85 @@ public: class ObTextPsEntry : public ObBasePsEntry { public: - ObTextPsEntry() : ObBasePsEntry(), version_(0) {} - ~ObTextPsEntry() { destroy(); } + ObTextPsEntry() : ObBasePsEntry() {} + ~ObTextPsEntry() { } - static int alloc_and_init_text_ps_entry(const common::ObString &sql, - const obutils::ObSqlParseResult &parse_result, - ObTextPsEntry *&entry); + template + static int alloc_and_init_ps_entry(const common::ObString &sql, + const obutils::ObSqlParseResult &parse_result, + T *&entry); int init(char *buf_start, int64_t buf_len, const common::ObString &text_ps_sql); - void destroy(); - - void set_version(uint32_t version) { version_ = version; } - uint32_t get_version() const { return version_; } - + virtual void free(); + virtual void destroy(); int64_t to_string(char *buf, const int64_t buf_len) const; -private: - uint32_t version_; +private: DISALLOW_COPY_AND_ASSIGN(ObTextPsEntry); }; +template +int ObTextPsEntry::alloc_and_init_ps_entry(const ObString &text_ps_sql, + const obutils::ObSqlParseResult &parse_result, + T *&entry) +{ + int ret = OB_SUCCESS; + int64_t alloc_size = 0; + char *buf = NULL; + + int64_t obj_size = sizeof(T); + int64_t sql_len = text_ps_sql.length() + PARSE_EXTRA_CHAR_NUM; + + alloc_size = obj_size + sql_len; + if (OB_ISNULL(buf = static_cast(op_fixed_mem_alloc(alloc_size)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + PROXY_SM_LOG(WARN, "fail to alloc mem for text ps entry", K(alloc_size), K(ret)); + } else { + entry = new (buf) T(); + if (OB_FAIL(entry->init(buf + obj_size, alloc_size - obj_size, text_ps_sql))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + PROXY_SM_LOG(WARN, "fail to alloc mem for text ps entry", K(alloc_size), K(ret)); + } else { + entry->set_base_ps_parse_result(parse_result); + } + } + + if (OB_FAIL(ret) && NULL != buf) { + op_fixed_mem_free(buf, alloc_size); + entry = NULL; + alloc_size = 0; + } + + return ret; +} + +class ObGlobalTextPsEntry : public ObTextPsEntry +{ +public: + ObGlobalTextPsEntry() : ObTextPsEntry() {} + ~ObGlobalTextPsEntry() {} + virtual void free(); + template + static int alloc_and_init_ps_entry(const common::ObString &sql, + const obutils::ObSqlParseResult &parse_result, + T *&entry); +}; + +template +int ObGlobalTextPsEntry::alloc_and_init_ps_entry(const ObString &sql, + const obutils::ObSqlParseResult &parse_result, + T *&entry) +{ + return ObTextPsEntry::alloc_and_init_ps_entry(sql, parse_result, entry); +} + class ObTextPsNameEntry { public: - ObTextPsNameEntry() : text_ps_name_(), text_ps_entry_(NULL) {} + ObTextPsNameEntry() : text_ps_name_(), text_ps_entry_(NULL), version_(0) {} ~ObTextPsNameEntry() { destroy(); } ObTextPsNameEntry(char *buf, const int64_t buf_len, ObTextPsEntry *entry) { - text_ps_name_.assign(buf, static_cast(buf_len)); + text_ps_name_.assign_ptr(buf, static_cast(buf_len)); text_ps_entry_ = entry; } @@ -304,31 +399,43 @@ public: void destroy(); bool is_valid() const { - return !text_ps_name_.empty() - && NULL != text_ps_entry_ - && text_ps_entry_->is_valid(); + return !text_ps_name_.empty() && NULL != text_ps_entry_ && text_ps_entry_->is_valid(); } - const ObString& get_text_ps_name() { return text_ps_name_; } - ObTextPsEntry *get_text_ps_entry() { return text_ps_entry_; } int64_t to_string(char *buf, const int64_t buf_len) const; public: // text_ps_name and text_ps_entry alloced in alloc_text_ps_name_entry ObString text_ps_name_; ObTextPsEntry *text_ps_entry_; + uint32_t version_; LINK(ObTextPsNameEntry, text_ps_name_link_); }; class ObBasePsEntryCache { public: - ObBasePsEntryCache() : base_ps_map_() {} - ~ObBasePsEntryCache() { destroy(); } + ObBasePsEntryCache() {} + virtual ~ObBasePsEntryCache() { destroy(); } + virtual void destroy() {} + +public: + virtual void delete_base_ps_entry(ObBasePsEntry *base_ps_entry) { + UNUSED(base_ps_entry); + } + +private: + DISALLOW_COPY_AND_ASSIGN(ObBasePsEntryCache); +}; + +class ObBasePsEntryThreadCache : public ObBasePsEntryCache +{ +public: + ObBasePsEntryThreadCache() : ObBasePsEntryCache(), ps_entry_thread_map_() {} + ~ObBasePsEntryThreadCache() { destroy(); } void destroy(); public: static const int64_t HASH_BUCKET_SIZE = 64; - struct ObBasePsEntryHashing { typedef const common::ObString &Key; @@ -339,67 +446,210 @@ public: static Key key(Value const *value) { return value->base_ps_sql_; } static bool equal(Key lhs, Key rhs) { return lhs == rhs; } }; - typedef common::hash::ObBuildInHashMap ObBasePsEntryMap; public: - int get_ps_entry(const common::ObString &sql, ObPsEntry *&ps_entry) - { - int ret = common::OB_SUCCESS; - ObBasePsEntry *tmp_entry = NULL; - if (OB_FAIL(base_ps_map_.get_refactored(sql, tmp_entry))) { - //do nothing - } else { - ps_entry = static_cast(tmp_entry); - } - return ret; + template + int acquire_ps_entry(const common::ObString &sql, T *&ps_entry); + + template + int create_ps_entry(const common::ObString &sql, + const obutils::ObSqlParseResult &parse_result, + T *&ps_entry); + + template + int acquire_or_create_ps_entry(const common::ObString &sql, + const obutils::ObSqlParseResult &parse_result, + T *&ps_entry); + + void delete_base_ps_entry(ObBasePsEntry *base_ps_entry); + +private: + ObBasePsEntryMap ps_entry_thread_map_; + DISALLOW_COPY_AND_ASSIGN(ObBasePsEntryThreadCache); +}; + +template +int ObBasePsEntryThreadCache::acquire_ps_entry(const ObString &sql, T *&ps_entry) +{ + int ret = OB_SUCCESS; + ObBasePsEntry *tmp_entry = NULL; + if (OB_FAIL(ps_entry_thread_map_.get_refactored(sql, tmp_entry))) { + //do nothing + } else { + ps_entry = static_cast(tmp_entry); + ps_entry->inc_ref(); } + return ret; +} - int set_ps_entry(ObPsEntry *ps_entry) - { - ObBasePsEntry *tmp_entry = static_cast(ps_entry); - tmp_entry->set_ps_entry_cache(this); - return base_ps_map_.unique_set(tmp_entry); +template +int ObBasePsEntryThreadCache::create_ps_entry(const common::ObString &sql, + const obutils::ObSqlParseResult &parse_result, + T *&ps_entry) +{ + int ret = OB_SUCCESS; + ObBasePsEntry* tmp_ps_entry = NULL; + if (OB_FAIL(ps_entry_thread_map_.get_refactored(sql, tmp_ps_entry))) { + if (OB_HASH_NOT_EXIST == ret) { + if (OB_FAIL(T::alloc_and_init_ps_entry(sql, parse_result, ps_entry))) { + PROXY_SM_LOG(WARN, "fail to alloc and init ps entry", K(ret)); + } else if (OB_FAIL(ps_entry_thread_map_.unique_set(ps_entry))) { + PROXY_SM_LOG(WARN, "fail to add ps entry to cache", K(ret)); + if (OB_LIKELY(NULL != ps_entry)) { + ps_entry->destroy(); + ps_entry = NULL; + } + } else { + ObBasePsEntry *tmp_entry = static_cast(ps_entry); + tmp_entry->set_ps_entry_cache(this); + } + } + } else { + ps_entry = static_cast(tmp_ps_entry); } + if (OB_SUCC(ret)) { + ps_entry->inc_ref(); + } + return ret; +} - int get_text_ps_entry(const common::ObString &sql, ObTextPsEntry *&text_ps_entry) - { - int ret = common::OB_SUCCESS; - ObBasePsEntry *tmp_entry = NULL; - if (OB_FAIL(base_ps_map_.get_refactored(sql, tmp_entry))) { - //do nothing +template +int ObBasePsEntryThreadCache::acquire_or_create_ps_entry(const ObString &sql, + const obutils::ObSqlParseResult &parse_result, + T *&ps_entry) +{ + int ret = OB_SUCCESS; + if (OB_FAIL(acquire_ps_entry(sql, ps_entry))) { + if (OB_HASH_NOT_EXIST == ret) { + if (OB_FAIL(create_ps_entry(sql, parse_result, ps_entry))) { + PROXY_SM_LOG(WARN, "fail to create ps entry", K(sql), K(ret)); + } else { + PROXY_SM_LOG(DEBUG, "succ to create ps entry", K(sql), KPC(ps_entry)); + } } else { - text_ps_entry = static_cast(tmp_entry); + PROXY_SM_LOG(WARN, "fail to get ps entry", K(sql), K(ret)); } - return ret; } + return ret; +} - int set_text_ps_entry(ObTextPsEntry *text_ps_entry) +class ObBasePsEntryGlobalCache : public ObBasePsEntryCache +{ +public: + ObBasePsEntryGlobalCache() : ObBasePsEntryCache(), lock_(), ps_entry_global_map_() {} + ~ObBasePsEntryGlobalCache() { destroy(); } + void destroy(); + +public: + static const int64_t HASH_BUCKET_SIZE = 64; + struct ObBasePsEntryHashing { - ObBasePsEntry *tmp_entry = text_ps_entry; - return base_ps_map_.unique_set(tmp_entry); + typedef const common::ObString &Key; + typedef ObBasePsEntry Value; + typedef ObDLList(ObBasePsEntry, base_ps_entry_link_) ListHead; + + static uint64_t hash(Key key) { return key.hash(); } + static Key key(Value const *value) { return value->base_ps_sql_; } + static bool equal(Key lhs, Key rhs) { return lhs == rhs; } + static int64_t inc_ref(Value* value) { return ATOMIC_AAF(&value->ref_count_, 1); } + static bool bcas_ref(Value* value, int64_t cmpv, int64_t newv) { return ATOMIC_BCAS(&value->ref_count_, cmpv, newv); } + static int64_t get_ref(Value* value) { return ATOMIC_LOAD(&value->ref_count_); } + static void destroy(Value* value) { value->destroy(); } + }; + typedef common::hash::ObBuildInHashMapForRefCount ObBasePsEntryGlobalMap; + +public: + template + int acquire_ps_entry(const common::ObString &sql, T *&ps_entry); + + template + int create_ps_entry(const common::ObString &sql, + const obutils::ObSqlParseResult &parse_result, + T *&ps_entry); + + template + int acquire_or_create_ps_entry(const common::ObString &sql, + const obutils::ObSqlParseResult &parse_result, + T *&ps_entry); + + void delete_base_ps_entry(ObBasePsEntry *base_ps_entry); + +private: + common::DRWLock lock_; + ObBasePsEntryGlobalMap ps_entry_global_map_; + DISALLOW_COPY_AND_ASSIGN(ObBasePsEntryGlobalCache); +}; + +template +int ObBasePsEntryGlobalCache::acquire_ps_entry(const ObString &sql, T *&ps_entry) +{ + int ret = OB_SUCCESS; + common::DRWLock::RDLockGuard guard(lock_); + ObBasePsEntry *tmp_entry = NULL; + if (OB_FAIL(ps_entry_global_map_.get_refactored(sql, tmp_entry))) { + //do nothing + } else { + ps_entry = static_cast(tmp_entry); } + return ret; +} - int delete_text_ps_entry(ObTextPsEntry *text_ps_entry) - { - if (NULL != text_ps_entry) { - base_ps_map_.remove(text_ps_entry->base_ps_sql_); - text_ps_entry->destroy(); +template +int ObBasePsEntryGlobalCache::create_ps_entry(const common::ObString &sql, + const obutils::ObSqlParseResult &parse_result, + T *&ps_entry) +{ + int ret = OB_SUCCESS; + DRWLock::WRLockGuard guard(lock_); + ObBasePsEntry* tmp_ps_entry = NULL; + if (OB_FAIL(ps_entry_global_map_.get_refactored(sql, tmp_ps_entry))) { + if (OB_HASH_NOT_EXIST == ret) { + if (OB_FAIL(T::alloc_and_init_ps_entry(sql, parse_result, ps_entry))) { + PROXY_SM_LOG(WARN, "fail to alloc and init ps entry", K(ret)); + } else if (OB_FAIL(ps_entry_global_map_.unique_set(ps_entry))) { + PROXY_SM_LOG(WARN, "fail to add ps entry to cache", K(ret)); + if (OB_LIKELY(NULL != ps_entry)) { + ps_entry->destroy(); + ps_entry = NULL; + } + } else { + ObBasePsEntry *tmp_entry = static_cast(ps_entry); + tmp_entry->set_ps_entry_cache(this); + } } - return common::OB_SUCCESS; + } else { + ps_entry = static_cast(tmp_ps_entry); } + return ret; +} - void delete_base_ps_entry(ObBasePsEntry *base_ps_entry) - { - base_ps_map_.remove(base_ps_entry); +template +int ObBasePsEntryGlobalCache::acquire_or_create_ps_entry(const ObString &sql, + const obutils::ObSqlParseResult &parse_result, + T *&ps_entry) +{ + int ret = OB_SUCCESS; + if (OB_FAIL(acquire_ps_entry(sql, ps_entry))) { + if (OB_HASH_NOT_EXIST == ret) { + if (OB_FAIL(create_ps_entry(sql, parse_result, ps_entry))) { + PROXY_SM_LOG(WARN, "fail to create ps entry", K(sql), K(ret)); + } else { + PROXY_SM_LOG(DEBUG, "succ to create ps entry", K(sql), KPC(ps_entry)); + } + } else { + PROXY_SM_LOG(WARN, "fail to get ps entry", K(sql), K(ret)); + } } - -private: - ObBasePsEntryMap base_ps_map_; - DISALLOW_COPY_AND_ASSIGN(ObBasePsEntryCache); -}; + return ret; +} int init_ps_entry_cache_for_thread(); +int init_ps_entry_cache_for_one_thread(int64_t index); +int init_text_ps_entry_cache_for_thread(); +int init_text_ps_entry_cache_for_one_thread(int64_t index); +ObBasePsEntryGlobalCache &get_global_ps_entry_cache(); +ObBasePsEntryGlobalCache &get_global_text_ps_entry_cache(); } // end of namespace proxy } // end of namespace obproxy diff --git a/src/obproxy/proxy/mysqllib/Makemodule.am b/src/obproxy/proxy/mysqllib/Makemodule.am index c44f07be68c50638ba63b8620ac1592e47408105..73fc607df1e82e08619eb4d8b470fa2f5876021e 100644 --- a/src/obproxy/proxy/mysqllib/Makemodule.am +++ b/src/obproxy/proxy/mysqllib/Makemodule.am @@ -10,6 +10,7 @@ obproxy/proxy/mysqllib/ob_mysql_response.cpp\ obproxy/proxy/mysqllib/ob_mysql_common_define.h\ obproxy/proxy/mysqllib/ob_proxy_mysql_request.h\ obproxy/proxy/mysqllib/ob_proxy_mysql_request.cpp\ +obproxy/proxy/mysqllib/ob_proxy_ob20_request.h\ obproxy/proxy/mysqllib/ob_mysql_request_analyzer.h\ obproxy/proxy/mysqllib/ob_mysql_request_analyzer.cpp\ obproxy/proxy/mysqllib/ob_proxy_auth_parser.h\ diff --git a/src/obproxy/proxy/mysqllib/ob_2_0_protocol_struct.h b/src/obproxy/proxy/mysqllib/ob_2_0_protocol_struct.h index 64aa6221df7f642062451e3a8a0cbf4107174b8e..c0904b9715400b74d10966dfe76b3b80e86eba4e 100644 --- a/src/obproxy/proxy/mysqllib/ob_2_0_protocol_struct.h +++ b/src/obproxy/proxy/mysqllib/ob_2_0_protocol_struct.h @@ -14,6 +14,9 @@ #define OBPROXY_OB20_PROTOCOL_STRUCT_H #include "proxy/mysqllib/ob_mysql_common_define.h" +#include "obutils/ob_proxy_buf.h" +#include "lib/container/ob_se_array.h" +#include "lib/string/ob_sql_string.h" namespace oceanbase { @@ -22,6 +25,28 @@ namespace obproxy namespace proxy { +const char * const OB_V20_PRO_EXTRA_KV_NAME_SYNC_SESSION_INFO = "sess_inf"; +const char * const OB_V20_PRO_EXTRA_KV_NAME_FULL_LINK_TRACE = "full_trc"; +const char * const OB_TRACE_INFO_VAR_NAME = "ob_trace_info"; +const char * const OB_TRACE_INFO_CLIENT_IP = "client_ip"; + + +/* + * oceanbase 2.0 protocol new extra info key type + * + * [0, 999] only for ob driver + * [1001, 1999] only for obproxy + * [2001, 65535] common for observer + obclient + obproxy + */ +enum Ob20NewExtraInfoProtocolKeyType { + OB20_DRIVER_END = 1000, + OB20_PROXY_END = 2000, + TRACE_INFO = 2001, + SESS_INFO = 2002, + FULL_TRC = 2003, + OB20_SVR_END, +}; + // used for proxy and observer to negotiate new features union Ob20ProtocolFlags { @@ -30,6 +55,8 @@ union Ob20ProtocolFlags bool is_extra_info_exist() const { return 1 == st_flags_.OB_EXTRA_INFO_EXIST; } bool is_last_packet() const { return 1 == st_flags_.OB_IS_LAST_PACKET; } + bool is_new_extra_info() const { return 1 == st_flags_.OB_IS_NEW_EXTRA_INFO; } + bool is_trans_internal_routing() const { return 1 == st_flags_.OB_IS_TRANS_INTERNAL_ROUTING; } uint32_t flags_; struct Protocol20Flags @@ -37,10 +64,104 @@ union Ob20ProtocolFlags uint32_t OB_EXTRA_INFO_EXIST: 1; uint32_t OB_IS_LAST_PACKET: 1; uint32_t OB_IS_PROXY_REROUTE: 1; - uint64_t OB_FLAG_RESERVED_NOT_USE: 30; + uint32_t OB_IS_NEW_EXTRA_INFO: 1; + uint32_t OB_IS_WEAK_READ: 1; + uint32_t OB_IS_TRANS_INTERNAL_ROUTING: 1; + uint32_t OB_FLAG_RESERVED_NOT_USE: 26; } st_flags_; }; +enum SessionSyncInfoType { + //SESSION_SYNC_USER_VAR, // for user variables + SESSION_SYNC_APPLICATION_INFO = 0, // for application info + SESSION_SYNC_APPLICATION_CONTEXT = 1, // for app ctx + SESSION_SYNC_CLIENT_ID = 2, // for client identifier + SESSION_SYNC_CONTROL_INFO = 3, // for full trace link control info + SESSION_SYNC_SYS_VAR = 4, // for system variables + SESSION_SYNC_TXN_STATIC_INFO = 5, // 5: basic txn info + SESSION_SYNC_TXN_DYNAMIC_INFO = 6, // 6: txn dynamic info + SESSION_SYNC_TXN_PARTICIPANTS_INFO = 7, // 7: txn dynamic info + SESSION_SYNC_TXN_EXTRA_INFO = 8, // 8: txn dynamic info + SESSION_SYNC_MAX_TYPE, +}; + +struct Ob20ExtraInfo +{ +public: + Ob20ExtraInfo() : is_exist_sess_info_(false), extra_info_buf_(), sess_info_buf_(), + sess_info_count_(0), extra_len_(0), sess_info_length_(), + sess_info_cur_idx_(0), sess_info_offset_(0) {} + ~Ob20ExtraInfo() {} + + void reset() { + is_exist_sess_info_ = false; + extra_info_buf_.reset(); + sess_info_buf_.reset(); + sess_info_count_ = 0; + extra_len_ = 0; + + sess_info_length_.reset(); + sess_info_cur_idx_ = 0; + sess_info_offset_ = 0; + } + inline bool exist_sess_info() const { return is_exist_sess_info_; } + inline uint32_t get_sess_info_count() { return sess_info_count_; } + inline int get_next_sess_info(common::ObString &sess_info); + void reset_sess_info_iterate_idx() { + sess_info_cur_idx_ = 0; + sess_info_offset_ = 0; + } + int add_sess_info_buf(const char *str, const int64_t len); + TO_STRING_KV(K_(is_exist_sess_info), K_(sess_info_count), K_(extra_len)); +public: + // for session info sync mechanism + bool is_exist_sess_info_; + obutils::ObVariableLenBuffer<32> extra_info_buf_; // save last packet extra info kv + common::ObSqlString sess_info_buf_; // save all sess info + uint32_t sess_info_count_; + uint32_t extra_len_; // extra len in ob20 payload, if the flag.exist_extra_info + +private: + // sess info iterator info + common::ObSEArray sess_info_length_; + uint32_t sess_info_cur_idx_; + uint64_t sess_info_offset_; +}; + +int Ob20ExtraInfo::get_next_sess_info(common::ObString &sess_info) +{ + sess_info.reset(); + int ret = common::OB_SUCCESS; + uint64_t length = sess_info_length_.at(sess_info_cur_idx_); + uint64_t buf_length = sess_info_buf_.length(); + if (sess_info_offset_ + length > buf_length) { + ret = common::OB_ERR_UNEXPECTED; + PROXY_LOG(WARN, "unexpected length of sess info buffer", K(ret), K(sess_info_offset_), K(length)); + } else { + sess_info.assign_ptr(sess_info_buf_.ptr() + sess_info_offset_, static_cast(length)); + sess_info_offset_ += length; + sess_info_cur_idx_ ++; + } + return ret; +} + +int Ob20ExtraInfo::add_sess_info_buf(const char *value, const int64_t len) +{ + int ret = common::OB_SUCCESS; + if (OB_UNLIKELY(NULL == value || 0 >= len)) { + ret = common::OB_INVALID_ARGUMENT; + PROXY_LOG(WARN, "invalid argument", K(value), K(len), K(ret)); + } else if (OB_FAIL(sess_info_buf_.append(value, len))) { + PROXY_LOG(WARN, "fail to append sess info buf", K(value), K(len), K(ret)); + } else if (OB_FAIL(sess_info_length_.push_back(len))) { + PROXY_LOG(WARN, "fail to record sess info buf length", K(ret)); + } else { + is_exist_sess_info_ = true; + sess_info_count_++; + } + return ret; +} + class Ob20ProtocolHeader { public: @@ -81,6 +202,80 @@ public: K_(reserved)); }; +// used for transfer function argument +class Ob20ProtocolHeaderParam { +public: + Ob20ProtocolHeaderParam() : connection_id_(0), + request_id_(0), + compressed_seq_(0), + pkt_seq_(0), + is_last_packet_(false), + is_weak_read_(false), + is_need_reroute_(false), + is_new_extra_info_(false), + is_trans_internal_routing_(false) {} + Ob20ProtocolHeaderParam(uint32_t conn_id, uint32_t req_id, uint8_t compressed_seq, uint8_t pkt_seq, + bool is_last_packet, bool is_weak_read, bool is_need_reroute, + bool is_new_extra_info, bool is_trans_internal_routing) + : connection_id_(conn_id), request_id_(req_id), compressed_seq_(compressed_seq), + pkt_seq_(pkt_seq), is_last_packet_(is_last_packet), + is_weak_read_(is_weak_read), is_need_reroute_(is_need_reroute), + is_new_extra_info_(is_new_extra_info), is_trans_internal_routing_(is_trans_internal_routing) {} + ~Ob20ProtocolHeaderParam() {} + + Ob20ProtocolHeaderParam(const Ob20ProtocolHeaderParam ¶m) { + *this = param; + } + + Ob20ProtocolHeaderParam &operator=(const Ob20ProtocolHeaderParam ¶m) { + if (this != ¶m) { + connection_id_ = param.connection_id_; + request_id_ = param.request_id_; + compressed_seq_ = param.compressed_seq_; + pkt_seq_ = param.pkt_seq_; + is_last_packet_ = param.is_last_packet_; + is_weak_read_ = param.is_weak_read_; + is_need_reroute_ = param.is_need_reroute_; + is_new_extra_info_ = param.is_new_extra_info_; + is_trans_internal_routing_ = param.is_trans_internal_routing_; + } + return *this; + } + + uint32_t get_connection_id() const { return connection_id_; } + uint32_t get_request_id() const { return request_id_; } + uint8_t get_compressed_seq() const { return compressed_seq_; } + uint8_t get_pkt_seq() const { return pkt_seq_; } + bool is_last_packet() const { return is_last_packet_; } + bool is_weak_read() const { return is_weak_read_; } + bool is_need_reroute() const { return is_need_reroute_; } + bool is_new_extra_info() const { return is_new_extra_info_; } + bool is_trans_internal_routing() const { return is_trans_internal_routing_; } + void reset() + { + MEMSET(this, 0x0, sizeof(Ob20ProtocolHeaderParam)); + is_last_packet_ = false; + is_weak_read_ = false; + is_need_reroute_ = false; + is_new_extra_info_ = false; + is_trans_internal_routing_ = false; + } + + TO_STRING_KV(K_(connection_id), K_(request_id), K_(compressed_seq), K_(pkt_seq), + K_(is_last_packet), K_(is_need_reroute), K_(is_new_extra_info), K_(is_trans_internal_routing)); +private: + uint32_t connection_id_; + uint32_t request_id_; + uint8_t compressed_seq_; + uint8_t pkt_seq_; + bool is_last_packet_; + bool is_weak_read_; + bool is_need_reroute_; + bool is_new_extra_info_; + bool is_trans_internal_routing_; +}; + + } // end of namespace proxy } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/proxy/mysqllib/ob_2_0_protocol_utils.cpp b/src/obproxy/proxy/mysqllib/ob_2_0_protocol_utils.cpp index 64be6deab5771e8fd969f251409cc8aea44f505e..183a18a5133cb8c136dd96313ac5256f7d3d59e0 100644 --- a/src/obproxy/proxy/mysqllib/ob_2_0_protocol_utils.cpp +++ b/src/obproxy/proxy/mysqllib/ob_2_0_protocol_utils.cpp @@ -19,6 +19,8 @@ #include "lib/checksum/ob_crc16.h" #include "rpc/obmysql/ob_mysql_util.h" #include "proxy/mysqllib/ob_session_field_mgr.h" +#include "obproxy/proxy/mysql/ob_mysql_sm.h" + using namespace oceanbase::obproxy::event; using namespace oceanbase::obproxy::packet; @@ -32,6 +34,103 @@ namespace obproxy namespace proxy { +int ObProto20Utils::encode_ok_packet(event::ObMIOBuffer &write_buf, const Ob20ProtocolHeaderParam &ob20_head_param, + uint8_t &seq, const int64_t affected_rows, + const obmysql::ObMySQLCapabilityFlags &capability, + const uint16_t status_flag /* 0 */) +{ + int ret = OB_SUCCESS; + + ObMIOBuffer *tmp_mio_buf = NULL; + ObIOBufferReader *tmp_mio_reader = NULL; + if (OB_ISNULL(tmp_mio_buf = new_miobuffer(MYSQL_BUFFER_SIZE))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to new miobuffer", K(ret), K(MYSQL_BUFFER_SIZE)); + } else if (OB_ISNULL(tmp_mio_reader = tmp_mio_buf->alloc_reader())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to alloc reader", K(ret)); + } else if (OB_FAIL(ObMysqlPacketUtil::encode_ok_packet(*tmp_mio_buf, seq, affected_rows, capability, status_flag))) { + LOG_WARN("fail to encode ok packet", K(ret)); + } else if (OB_FAIL(ObProto20Utils::consume_and_compress_data(tmp_mio_reader, &write_buf, + tmp_mio_reader->read_avail(), ob20_head_param))) { + LOG_WARN("fail to consume and compress ok packet in ob20", K(ret)); + } else { + // nothing + } + + if (OB_LIKELY(tmp_mio_buf != NULL)) { + free_miobuffer(tmp_mio_buf); + tmp_mio_buf = NULL; + tmp_mio_reader = NULL; + } + + return ret; +} + +int ObProto20Utils::encode_kv_resultset(ObMIOBuffer &write_buf, const Ob20ProtocolHeaderParam &ob20_head_param, + uint8_t &seq, const ObMySQLField &field, ObObj &field_value, + const uint16_t status_flag) +{ + int ret = OB_SUCCESS; + + event::ObIOBufferReader *tmp_mio_reader = NULL; + event::ObMIOBuffer *tmp_mio_buf = NULL; + if (OB_ISNULL(tmp_mio_buf = new_empty_miobuffer(MYSQL_BUFFER_SIZE))) { + ret = common::OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc miobuffer", K(ret)); + } else if (OB_ISNULL(tmp_mio_reader = tmp_mio_buf->alloc_reader())) { + ret = common::OB_ERR_UNEXPECTED; + LOG_WARN("fail to alloc reader", K(ret)); + } else if (OB_FAIL(ObMysqlPacketUtil::encode_kv_resultset(*tmp_mio_buf, seq, field, field_value, status_flag))) { + LOG_WARN("fail to encode kv resultset", K(ret)); + } else if (OB_FAIL(ObProto20Utils::consume_and_compress_data(tmp_mio_reader, &write_buf, + tmp_mio_reader->read_avail(), ob20_head_param))) { + LOG_WARN("fail to consume and compress kv resultset in ob20 packet", K(ret)); + } else { + LOG_DEBUG("succ to encode kv resultset in ob20 packet"); + } + + if (OB_LIKELY(tmp_mio_buf != NULL)) { + free_miobuffer(tmp_mio_buf); + tmp_mio_buf = NULL; + tmp_mio_reader = NULL; + } + + return ret; +} + +int ObProto20Utils::encode_err_packet(event::ObMIOBuffer &write_buf, const Ob20ProtocolHeaderParam &ob20_head_param, + uint8_t &seq, const int err_code, const ObString &msg_buf) +{ + int ret = OB_SUCCESS; + + event::ObIOBufferReader *tmp_mio_reader = NULL; + event::ObMIOBuffer *tmp_mio_buf = NULL; + + if (OB_ISNULL(tmp_mio_buf = new_empty_miobuffer(MYSQL_BUFFER_SIZE))) { + ret = common::OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc miobuffer", K(ret)); + } else if (OB_ISNULL(tmp_mio_reader = tmp_mio_buf->alloc_reader())) { + ret = common::OB_ERR_UNEXPECTED; + LOG_WARN("fail to alloc reader", K(ret)); + } else if (OB_FAIL(ObMysqlPacketUtil::encode_err_packet(*tmp_mio_buf, seq, err_code, msg_buf))) { + LOG_WARN("fail to encode err packet buf", K(ret)); + } else if (OB_FAIL(ObProto20Utils::consume_and_compress_data(tmp_mio_reader, &write_buf, + tmp_mio_reader->read_avail(), ob20_head_param))) { + LOG_WARN("fail to consume and compress data for err packet in ob20", K(ret)); + } else { + LOG_DEBUG("succ to encode err packet in ob20 packet"); + } + + if (OB_LIKELY(tmp_mio_buf != NULL)) { + free_miobuffer(tmp_mio_buf); + tmp_mio_buf = NULL; + tmp_mio_reader = NULL; + } + + return ret; +} + int ObProto20Utils::analyze_ok_packet_and_get_reroute_info(ObIOBufferReader *reader, const int64_t pkt_len, const ObMySQLCapabilityFlags &cap, @@ -64,7 +163,7 @@ int ObProto20Utils::analyze_ok_packet_and_get_reroute_info(ObIOBufferReader *rea return ret; } -int ObProto20Utils::analyze_fisrt_mysql_packet( +int ObProto20Utils::analyze_first_mysql_packet( ObIOBufferReader &reader, ObMysqlCompressedOB20AnalyzeResult &result, ObMysqlAnalyzeResult &mysql_result) @@ -75,16 +174,16 @@ int ObProto20Utils::analyze_fisrt_mysql_packet( if (result.ob20_header_.flag_.is_extra_info_exist()) { uint32_t extra_len; - char extro_info[OB20_PROTOCOL_EXTRA_INFO_LENGTH]; - char *written_pos = reader.copy(extro_info, OB20_PROTOCOL_EXTRA_INFO_LENGTH, MYSQL_COMPRESSED_OB20_HEALDER_LENGTH); + char extra_info[OB20_PROTOCOL_EXTRA_INFO_LENGTH]; + char *written_pos = reader.copy(extra_info, OB20_PROTOCOL_EXTRA_INFO_LENGTH, MYSQL_COMPRESSED_OB20_HEALDER_LENGTH); - if (OB_UNLIKELY(written_pos != extro_info + OB20_PROTOCOL_EXTRA_INFO_LENGTH)) { + if (OB_UNLIKELY(written_pos != extra_info + OB20_PROTOCOL_EXTRA_INFO_LENGTH)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("not copy completely", KP(written_pos), K(extro_info), + LOG_WARN("not copy completely", KP(written_pos), K(extra_info), "header_length", OB20_PROTOCOL_EXTRA_INFO_LENGTH, K(ret)); } else { - char *extro_info_ptr = extro_info; - ObMySQLUtil::get_uint4(extro_info_ptr, extra_len); + char *extra_info_ptr = extra_info; + ObMySQLUtil::get_uint4(extra_info_ptr, extra_len); extra_len += OB20_PROTOCOL_EXTRA_INFO_LENGTH; } } @@ -218,11 +317,11 @@ inline int ObProto20Utils::reserve_proto20_hdr(ObMIOBuffer *write_buf, char *&hd inline int ObProto20Utils::fill_proto20_header(char *hdr_start, const int64_t payload_len, const uint8_t compressed_seq, const uint8_t packet_seq, const uint32_t request_id, const uint32_t connid, - const bool is_last_packet, const bool is_need_reroute, - const bool is_extro_info_exist) + const bool is_last_packet, const bool is_weak_read, + const bool is_need_reroute, const bool is_extra_info_exist, + const bool is_new_extra_info, const bool is_trans_internal_routing) { int ret = OB_SUCCESS; - //include compress header and ob20 header int64_t header_len = MYSQL_COMPRESSED_HEALDER_LENGTH + OB20_PROTOCOL_HEADER_LENGTH; //compress payload @@ -231,9 +330,12 @@ inline int ObProto20Utils::fill_proto20_header(char *hdr_start, const int64_t pa int16_t magic_num = OB20_PROTOCOL_MAGIC_NUM; uint16_t version = OB20_PROTOCOL_VERSION_VALUE; Ob20ProtocolFlags flag; - flag.st_flags_.OB_EXTRA_INFO_EXIST = is_extro_info_exist ? 1 : 0; + flag.st_flags_.OB_EXTRA_INFO_EXIST = is_extra_info_exist ? 1 : 0; flag.st_flags_.OB_IS_LAST_PACKET = is_last_packet ? 1 : 0; flag.st_flags_.OB_IS_PROXY_REROUTE = is_need_reroute ? 1 : 0; + flag.st_flags_.OB_IS_WEAK_READ = is_weak_read ? 1 : 0; + flag.st_flags_.OB_IS_NEW_EXTRA_INFO = is_new_extra_info ? 1 : 0; + flag.st_flags_.OB_IS_TRANS_INTERNAL_ROUTING = is_trans_internal_routing ? 1 : 0; uint16_t reserved = 0; uint16_t header_checksum = 0; int64_t pos = 0; @@ -273,56 +375,76 @@ inline int ObProto20Utils::fill_proto20_header(char *hdr_start, const int64_t pa } else { LOG_DEBUG("fill proto20 header succ", K(compress_len), K(compressed_seq), K(uncompress_len), K(magic_num), K(version), K(connid), K(request_id), K(packet_seq), K(payload_len), - K(flag.flags_), K(reserved), K(header_checksum)); + K(flag.flags_), K(reserved), K(header_checksum), K(is_last_packet), K(is_extra_info_exist), + K(is_new_extra_info), K(lbt())); } } } return ret; } -inline int ObProto20Utils::fill_proto20_extro_info(ObMIOBuffer *write_buf, const ObIArray *extro_info, - int64_t &payload_len, uint64_t &crc64, bool &is_extro_info_exist) +int ObProto20Utils::fill_proto20_extra_info(ObMIOBuffer *write_buf, const ObIArray *extra_info, + const bool is_new_extra_info, int64_t &payload_len, + uint64_t &crc64, bool &is_extra_info_exist) +{ + int ret = OB_SUCCESS; + + if (is_new_extra_info) { + if (OB_FAIL(fill_proto20_new_extra_info(write_buf, extra_info, payload_len, crc64, is_extra_info_exist))) { + LOG_WARN("fail to fill new extra info"); + } + } else { + if (OB_FAIL(fill_proto20_obobj_extra_info(write_buf, extra_info, payload_len, crc64, is_extra_info_exist))) { + LOG_WARN("fail to fill obobj extra info"); + } + } + + return ret; +} + +int ObProto20Utils::fill_proto20_obobj_extra_info(ObMIOBuffer *write_buf, const ObIArray *extra_info, + int64_t &payload_len, uint64_t &crc64, bool &is_extra_info_exist) { int ret = OB_SUCCESS; int64_t max_kv_size = 0; - int64_t extro_info_len = 0; - for (int64_t i = 0; OB_SUCC(ret) && i < extro_info->count(); i++) { - const ObObJKV &ob_obj_kv = extro_info->at(i); + int64_t extra_info_len = 0; + for (int64_t i = 0; OB_SUCC(ret) && i < extra_info->count(); i++) { + const ObObJKV &ob_obj_kv = extra_info->at(i); const int64_t key_size = ob_obj_kv.key_.get_serialize_size(); const int64_t value_size = ob_obj_kv.value_.get_serialize_size(); - extro_info_len += (key_size + value_size); + extra_info_len += (key_size + value_size); if (key_size + value_size > max_kv_size) { max_kv_size = key_size + value_size; } } - - if (OB_LIKELY(extro_info_len > 0)) { + + if (OB_LIKELY(extra_info_len > 0)) { int64_t pos = 0; int64_t written_len = 0; - char extro_info_len_store[OB20_PROTOCOL_EXTRA_INFO_LENGTH]; - if (OB_FAIL(ObMySQLUtil::store_int4(extro_info_len_store, + char extra_info_len_store[OB20_PROTOCOL_EXTRA_INFO_LENGTH]; + if (OB_FAIL(ObMySQLUtil::store_int4(extra_info_len_store, OB20_PROTOCOL_EXTRA_INFO_LENGTH, - static_cast(extro_info_len), pos))) { - LOG_ERROR("fail to store extro_info_len", K(extro_info_len), K(ret)); - } else if (OB_FAIL(write_buf->write(extro_info_len_store, pos, written_len))) { - LOG_WARN("fail to write extro info len", K(extro_info_len_store), K(ret)); + static_cast(extra_info_len), pos))) { + LOG_ERROR("fail to store extra_info_len", K(extra_info_len), K(ret)); + } else if (OB_FAIL(write_buf->write(extra_info_len_store, pos, written_len))) { + LOG_WARN("fail to write extra info len", K(extra_info_len_store), K(ret)); } else if (OB_UNLIKELY(written_len != pos)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("fail to write extro info len", K(written_len), K(pos), K(ret)); + LOG_WARN("fail to write extra info len", K(written_len), K(pos), K(ret)); } else { payload_len += written_len; - crc64 = ob_crc64(crc64, extro_info_len_store, written_len); - is_extro_info_exist = true; + crc64 = ob_crc64(crc64, extra_info_len_store, written_len); + is_extra_info_exist = true; char *obj_buf = NULL; if (OB_ISNULL(obj_buf = static_cast(op_fixed_mem_alloc(max_kv_size)))) { LOG_WARN("fail to alloc memory", K(max_kv_size), K(ret)); } else { - for (int64_t i = 0; OB_SUCC(ret) && i < extro_info->count(); i++) { + for (int64_t i = 0; OB_SUCC(ret) && i < extra_info->count(); i++) { pos = 0; - const ObObJKV &ob_obj_kv = extro_info->at(i); + const ObObJKV &ob_obj_kv = extra_info->at(i); if (OB_FAIL(ob_obj_kv.key_.serialize(obj_buf, max_kv_size, pos))) { LOG_WARN("ail to serialize key", K(i), "key", ob_obj_kv.key_, K(ret)); } else if (OB_FAIL(ob_obj_kv.value_.serialize(obj_buf, max_kv_size, pos))) { @@ -330,13 +452,14 @@ inline int ObProto20Utils::fill_proto20_extro_info(ObMIOBuffer *write_buf, const } else { written_len = 0; if (OB_FAIL(write_buf->write(obj_buf, pos, written_len))) { - LOG_WARN("fail to write extro info", K(pos), K(ret)); + LOG_WARN("fail to write extra info", K(pos), K(ret)); } else if (OB_UNLIKELY(written_len != pos)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("fail to write extro info", K(written_len), K(pos), K(ret)); + LOG_WARN("fail to write extra info", K(written_len), K(pos), K(ret)); } else { payload_len += written_len; crc64 = ob_crc64(crc64, obj_buf, written_len); + LOG_DEBUG("succ to fill obobj extra info item", K(ob_obj_kv.key_), K(written_len)); } } } @@ -348,14 +471,100 @@ inline int ObProto20Utils::fill_proto20_extro_info(ObMIOBuffer *write_buf, const } } - LOG_DEBUG("fill proto20 extro succ", KPC(extro_info), K(payload_len), K(crc64), - K(is_extro_info_exist)); + LOG_DEBUG("fill proto20 obobj extra info end", K(ret), KPC(extra_info), + K(extra_info_len), K(payload_len), K(crc64), K(is_extra_info_exist)); + + return ret; +} + +int ObProto20Utils::fill_proto20_new_extra_info(ObMIOBuffer *write_buf, const ObIArray *extra_info, + int64_t &payload_len, uint64_t &crc64, bool &is_extra_info_exist) +{ + int ret = OB_SUCCESS; + + int64_t extra_info_len = 0; + for (int64_t i = 0; OB_SUCC(ret) && i < extra_info->count(); i++) { + const ObObJKV &obobj_kv = extra_info->at(i); + ObString obj_value = obobj_kv.value_.get_varchar(); + extra_info_len += FLT_TYPE_AND_LEN + obj_value.length(); + } + + if (extra_info_len > 0) { + LOG_DEBUG("will fill new extra info", K(extra_info_len)); + int64_t pos = 0; + int64_t written_len = 0; + char extra_info_len_store[OB20_PROTOCOL_EXTRA_INFO_LENGTH]; + if (OB_FAIL(ObMySQLUtil::store_int4(extra_info_len_store, + OB20_PROTOCOL_EXTRA_INFO_LENGTH, + static_cast(extra_info_len), pos))) { + LOG_ERROR("fail to store extra_info_len", K(extra_info_len), K(ret)); + } else if (OB_FAIL(write_buf->write(extra_info_len_store, pos, written_len))) { + LOG_WARN("fail to write extra info len", K(extra_info_len_store), K(ret)); + } else if (OB_UNLIKELY(written_len != pos)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to write extra info len", K(written_len), K(pos), K(ret)); + } else { + payload_len += written_len; + crc64 = ob_crc64(crc64, extra_info_len_store, written_len); + is_extra_info_exist = true; + + for (int64_t i = 0; OB_SUCC(ret) && i < extra_info->count(); ++i) { + Ob20NewExtraInfoProtocolKeyType key_type = OB20_SVR_END; + const ObObJKV &obobj_kv = extra_info->at(i); + ObString obj_key = obobj_kv.key_.get_varchar(); + ObString obj_value = obobj_kv.value_.get_varchar(); + if (obj_key.case_compare(OB_V20_PRO_EXTRA_KV_NAME_FULL_LINK_TRACE) == 0) { + key_type = FULL_TRC; + } else if (obj_key.case_compare(OB_V20_PRO_EXTRA_KV_NAME_SYNC_SESSION_INFO) == 0) { + key_type = SESS_INFO; + } else if (obj_key.case_compare(OB_TRACE_INFO_VAR_NAME) == 0) { + key_type = TRACE_INFO; + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected extra key error", K(ret), K(obj_key), K(obj_value)); + } + + if (OB_SUCC(ret)) { + // fill type and value + char new_extra_info_key_len_buf[FLT_TYPE_AND_LEN]; + int64_t t_pos = 0; + int64_t type_written_len = 0; + int64_t value_written_len = 0; + const char *ptr = obj_value.ptr(); + const int32_t len = obj_value.length(); + if (OB_FAIL(Ob20FullLinkTraceTransUtil::store_type_and_len( + new_extra_info_key_len_buf, FLT_TYPE_AND_LEN, t_pos, key_type, len))) { + LOG_WARN("fail to store type and len for new extra info", K(ret), K(key_type), K(obj_value)); + } else if (OB_FAIL(write_buf->write(new_extra_info_key_len_buf, FLT_TYPE_AND_LEN, type_written_len))) { + LOG_WARN("fail to write type and len to buf", K(ret)); + } else if (OB_UNLIKELY(FLT_TYPE_AND_LEN != type_written_len)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected check written len", K(ret), K(type_written_len)); + } else if (OB_NOT_NULL(ptr) && len > 0 + && OB_FAIL(write_buf->write(ptr, len, value_written_len))) { + LOG_WARN("fail to write obj value to buf", K(ret), K(obj_value), K(len), K(NULL == ptr), K(obj_key)); + } else if (OB_UNLIKELY(len != value_written_len)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected check written len", K(ret), K(len), K(value_written_len)); + } else { + payload_len += (type_written_len + value_written_len); + crc64 = ob_crc64(crc64, new_extra_info_key_len_buf, type_written_len); + crc64 = ob_crc64(crc64, ptr, len); + LOG_DEBUG("succ to fill new extra info item", K(key_type), K(value_written_len)); + } + } + } // for + } // else + } + + LOG_DEBUG("fill proto20 new extra info end", K(ret), KPC(extra_info), + K(extra_info_len), K(payload_len), K(crc64), K(is_extra_info_exist)); return ret; } -inline int ObProto20Utils::fill_proto20_payload(ObIOBufferReader *reader, ObMIOBuffer *write_buf, - const int64_t data_len, int64_t &payload_len, uint64_t &crc64) +int ObProto20Utils::fill_proto20_payload(ObIOBufferReader *reader, ObMIOBuffer *write_buf, + const int64_t data_len, int64_t &payload_len, uint64_t &crc64) { int ret = OB_SUCCESS; @@ -388,7 +597,7 @@ inline int ObProto20Utils::fill_proto20_payload(ObIOBufferReader *reader, ObMIOB return ret; } -inline int ObProto20Utils::fill_proto20_tailer(ObMIOBuffer *write_buf, const uint64_t crc64) +int ObProto20Utils::fill_proto20_tailer(ObMIOBuffer *write_buf, const uint64_t crc64) { int ret = OB_SUCCESS; @@ -411,47 +620,313 @@ inline int ObProto20Utils::fill_proto20_tailer(ObMIOBuffer *write_buf, const uin return ret; } -int ObProto20Utils::consume_and_compress_data(ObIOBufferReader *reader, ObMIOBuffer *write_buf, - const int64_t data_len, const uint8_t compressed_seq, - const uint8_t packet_seq, const uint32_t request_id, - const uint32_t connid, const bool is_last_packet, - const bool is_need_reroute, - const ObIArray *extro_info) +int ObProto20Utils::consume_and_compress_data(ObIOBufferReader *reader, + ObMIOBuffer *write_buf, + const int64_t data_len, + const Ob20ProtocolHeaderParam &ob20_head_param, + const ObIArray *extra_info) { int ret = OB_SUCCESS; uint64_t crc64 = 0; char *hdr_start = NULL; int64_t payload_len = 0; - bool is_extro_info_exist = false; + bool is_extra_info_exist = false; + + const uint8_t compressed_seq = ob20_head_param.get_compressed_seq(); + const uint8_t packet_seq = ob20_head_param.get_pkt_seq(); + const uint32_t request_id = ob20_head_param.get_request_id(); + const uint32_t conn_id = ob20_head_param.get_connection_id(); + const bool is_last_packet = ob20_head_param.is_last_packet(); + const bool is_weak_read = ob20_head_param.is_weak_read(); + const bool is_need_reroute = ob20_head_param.is_need_reroute(); + const bool is_new_extra_info = ob20_head_param.is_new_extra_info(); + const bool is_trans_internal_routing = ob20_head_param.is_trans_internal_routing(); if (OB_ISNULL(reader) || OB_ISNULL(write_buf) || data_len > reader->read_avail()) { ret = OB_INVALID_ARGUMENT; int64_t tmp_read_avail = ((NULL == reader) ? 0 : reader->read_avail()); LOG_ERROR("invalid input value", K(reader), K(write_buf), K(data_len), K(compressed_seq), - K(packet_seq), K(request_id), K(connid), K(is_last_packet), K(is_need_reroute), - "read_avail", tmp_read_avail, K(ret)); + K(packet_seq), K(request_id), K(conn_id), K(is_last_packet), K(is_weak_read), + K(is_need_reroute), "read_avail", tmp_read_avail, K(ret)); } else if (OB_FAIL(reserve_proto20_hdr(write_buf, hdr_start))) { LOG_ERROR("fail to reserve proto20 hdr", K(ret)); - } else if (OB_NOT_NULL(extro_info) - && OB_FAIL(fill_proto20_extro_info(write_buf, extro_info, payload_len, crc64, is_extro_info_exist))) { - LOG_ERROR("fail to fill proto20 extro info", KPC(extro_info), K(ret)); + } else if (OB_NOT_NULL(extra_info) + && OB_FAIL(fill_proto20_extra_info(write_buf, extra_info, is_new_extra_info, + payload_len, crc64, is_extra_info_exist))) { + LOG_ERROR("fail to fill proto20 extra info", KPC(extra_info), K(ret)); } else if (OB_FAIL(fill_proto20_payload(reader, write_buf, data_len, payload_len, crc64))) { LOG_ERROR("fail to fill proto20 payload", K(data_len), K(crc64), K(ret)); } else if (OB_FAIL(fill_proto20_tailer(write_buf, crc64))) { LOG_ERROR("fail to fill proto20 tailer", K(crc64), K(ret)); } else if (OB_FAIL(fill_proto20_header(hdr_start, payload_len, compressed_seq, - packet_seq, request_id, connid, - is_last_packet, is_need_reroute, - is_extro_info_exist))) { + packet_seq, request_id, conn_id, + is_last_packet, is_weak_read, is_need_reroute, + is_extra_info_exist, is_new_extra_info, is_trans_internal_routing))) { LOG_ERROR("fail to fill_proto20_header", K(payload_len), K(compressed_seq), - K(packet_seq), K(request_id), K(connid), K(is_last_packet), - K(is_need_reroute), K(ret)); + K(packet_seq), K(request_id), K(conn_id), K(is_last_packet), + K(is_weak_read), K(is_need_reroute), K(ret)); } else { LOG_DEBUG("build mysql compress packet with ob20 succ", "origin len", data_len, K(compressed_seq), K(crc64)); } return ret; } +bool ObProto20Utils::is_trans_related_sess_info(int16_t type) +{ + return SESSION_SYNC_TXN_STATIC_INFO <= type && type <= SESSION_SYNC_TXN_EXTRA_INFO; +} + +int ObProxyTraceUtils::build_client_ip(ObIArray &extra_info, + char *buf, + int64_t buf_len, + ObMysqlSM *sm, + const bool is_last_packet_or_segment) +{ + int ret = OB_SUCCESS; + + ObMysqlClientSession *client_session = sm->get_client_session(); + if (!client_session->is_proxy_mysql_client_ + && client_session->is_need_send_trace_info() + && is_last_packet_or_segment) { + int64_t pos = 0; + ObAddr client_ip = client_session->get_real_client_addr(); + + if (OB_FAIL(ObMySQLUtil::store_str_nzt(buf, buf_len, OB_TRACE_INFO_CLIENT_IP, pos))) { + LOG_WARN("fail to store client addr", K(ret)); + } else if (OB_FAIL(ObMySQLUtil::store_str_nzt(buf, buf_len, "=", pos))) { + LOG_WARN("fail to store equals sign", K(ret)); + } else if (OB_UNLIKELY(!client_ip.ip_to_string(buf + STRLEN(buf), + static_cast(buf_len - pos)))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to ip_to_string", K(client_ip), K(ret)); + } else { + ObObJKV kv; + kv.key_.set_varchar(OB_TRACE_INFO_VAR_NAME, static_cast(STRLEN(OB_TRACE_INFO_VAR_NAME))); + kv.key_.set_default_collation_type(); + kv.value_.set_varchar(buf, static_cast(STRLEN(buf))); + kv.value_.set_default_collation_type(); + + if (OB_FAIL(extra_info.push_back(kv))) { + LOG_WARN("fail to push back", K(ret)); + } else { + LOG_DEBUG("succ to generate client ip info"); + client_session->set_already_send_trace_info(true); + } + } + } + + return ret; +} + +int ObProxyTraceUtils::build_sync_sess_info(common::ObIArray &extra_info, + common::ObSqlString &info_value, + common::hash::ObHashMap &sess_info_hash_map, + common::hash::ObHashMap &client_sess_field_version, + common::hash::ObHashMap &server_sess_field_version, + ObMysqlSM *sm) +{ + int ret = OB_SUCCESS; + ObObJKV ob_sess_info; + ob_sess_info.key_.set_varchar(OB_V20_PRO_EXTRA_KV_NAME_SYNC_SESSION_INFO, + static_cast(STRLEN(OB_V20_PRO_EXTRA_KV_NAME_SYNC_SESSION_INFO))); + ob_sess_info.key_.set_default_collation_type(); + + const int MAX_TYPE_RECORD = 32; + char type_record[MAX_TYPE_RECORD]; + memset(type_record, '0', MAX_TYPE_RECORD); + bool is_sess_exist = false; + + SessFieldHashMap::iterator last = sess_info_hash_map.end(); + SessFieldHashMap::iterator it = sess_info_hash_map.begin(); + for (; it != last && OB_SUCC(ret); ++it) { + int16_t sess_info_type = it->first; + int64_t client_version = 0; + int64_t server_version = 0; + if (OB_FAIL(ObProxyTraceUtils::get_sess_field_version(client_version , sess_info_type, client_sess_field_version))) { + LOG_WARN("fail to get client session field version", K(ret), K(sess_info_type)); + } else if (OB_FAIL(ObProxyTraceUtils::get_sess_field_version(server_version , sess_info_type, server_sess_field_version))) { + LOG_WARN("fail to get server session field version", K(ret), K(sess_info_type)); + } else if (client_version > server_version) { + is_sess_exist = true; + if (sess_info_type < MAX_TYPE_RECORD) { + type_record[sess_info_type] = '1'; + } + info_value.append(it->second); + } + } + if (is_sess_exist) { + type_record[MAX_TYPE_RECORD - 1] = '\0'; + sm->trans_state_.trace_log_.log_it("[send_sess]", "type", type_record); + } + if (OB_SUCC(ret)) { + ob_sess_info.value_.set_varchar(info_value.string()); + ob_sess_info.value_.set_default_collation_type(); + if (OB_FAIL(extra_info.push_back(ob_sess_info))) { + LOG_WARN("fail to push back", K(ret)); + } + } + return ret; +} + +int ObProxyTraceUtils::build_extra_info_for_server(ObMysqlSM *sm, + char *buf, + int64_t buf_len, + common::ObIArray &extra_info, + const bool is_last_packet_or_segment) +{ + int ret = OB_SUCCESS; + int64_t pos = 0; + FLTSpanInfo &span_info = sm->flt_.span_info_; + FLTAppInfo &app_info = sm->flt_.app_info_; + + LOG_DEBUG("before build extra for server", K(is_last_packet_or_segment), K(span_info), K(app_info)); + + // proxy could send span_info and app_info to server + if (sm->get_server_session()->is_full_link_trace_supported() + && is_last_packet_or_segment + && sm->enable_record_full_link_trace_info()) { + // set current child span id from OBTRACE to server + SET_TRACE_BUFFER(sm->flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + trace::ObSpanCtx *curr_span_ctx = OBTRACE->last_active_span_; + if (curr_span_ctx != NULL) { + INIT_SPAN(curr_span_ctx); // before send to observer, init span first + trace::UUID &curr_span_id = curr_span_ctx->span_id_; + span_info.span_id_ = curr_span_id; + LOG_DEBUG("set the latest span id as current span id", K(curr_span_id)); + } else { + // unexpected here + ret = OB_ERR_UNEXPECTED; + FLTTraceLogInfo &trace_log_info = sm->flt_.trace_log_info_; + LOG_WARN("unexpected empty current span ctx, plz check!", K(ret), K(span_info), K(trace_log_info)); + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(span_info.serialize(buf, buf_len, pos))) { + LOG_WARN("fail to serialize span info for server", K(ret)); + } + } + } + + if (OB_SUCC(ret) + && sm->get_server_session()->is_ob_protocol_v2_supported() + && app_info.is_valid()) { + if (OB_FAIL(app_info.serialize(buf, buf_len, pos))) { + LOG_WARN("fail to serialize app info for server", K(ret)); + } + } + + int32_t total_seri = static_cast(pos); + if (OB_SUCC(ret) && total_seri > 0) { + ObObJKV kv; + kv.key_.set_varchar(OB_V20_PRO_EXTRA_KV_NAME_FULL_LINK_TRACE, + static_cast(STRLEN(OB_V20_PRO_EXTRA_KV_NAME_FULL_LINK_TRACE))); + kv.key_.set_default_collation_type(); + kv.value_.set_varchar(buf, total_seri); + kv.value_.set_default_collation_type(); + + if (OB_FAIL(extra_info.push_back(kv))) { + LOG_WARN("fail to push back to extra info", K(ret)); + } else { + if (app_info.is_valid()) { + app_info.reset(); // only send once if exist + } + LOG_DEBUG("succ to serialize extra info for server", K(kv.key_), K(pos), K(total_seri)); + } + } + + return ret; +} + +int ObProxyTraceUtils::build_extra_info_for_client(ObMysqlSM *sm, + char *buf, + const int64_t len, + common::ObIArray &extra_info) +{ + int ret = OB_SUCCESS; + + int64_t pos = 0; + FLTControlInfo &control_info = sm->flt_.control_info_; + if (control_info.is_need_send()) { + if (sm->get_client_session()->is_client_support_full_link_trace()) { + if (OB_FAIL(control_info.serialize(buf, len, pos))) { + LOG_WARN("fail to serialize control info", K(ret)); + } + } + // do not send control info to client again, keep it + // the client could support flt or not, so reset here + control_info.set_need_send(false); + } + + if (OB_SUCC(ret) && pos > 0) { + ObObJKV kv; + kv.key_.set_varchar(OB_V20_PRO_EXTRA_KV_NAME_FULL_LINK_TRACE, + static_cast(STRLEN(OB_V20_PRO_EXTRA_KV_NAME_FULL_LINK_TRACE))); + kv.key_.set_default_collation_type(); + kv.value_.set_varchar(buf, static_cast(pos)); + kv.value_.set_default_collation_type(); + + if (OB_FAIL(extra_info.push_back(kv))) { + LOG_WARN("fail to push back", K(ret)); + } else { + LOG_DEBUG("succ to generate extra info back to client", K(pos), K(extra_info)); + } + } + + return ret; +} + +int ObProxyTraceUtils::build_related_extra_info_all(ObIArray &extra_info, ObMysqlSM *sm, + char *ip_buf, const int64_t ip_buf_len, + char *extra_info_buf, const int64_t extra_info_buf_len, + ObSqlString &sess_info_value, const bool is_last_packet) +{ + int ret = OB_SUCCESS; + + if (OB_FAIL(ObProxyTraceUtils::build_client_ip(extra_info, ip_buf, ip_buf_len, sm, is_last_packet))) { + LOG_WARN("fail to build client ip", K(ret)); + } else if (OB_FAIL(ObProxyTraceUtils::build_extra_info_for_server(sm, extra_info_buf, extra_info_buf_len, + extra_info, is_last_packet))) { + LOG_WARN("fail to build extra info for server"); + } else { + ObMysqlServerSession *server_session = sm->get_server_session(); + ObMysqlClientSession *client_session = sm->get_client_session(); + if (OB_SUCC(ret) && OB_NOT_NULL(client_session) && OB_NOT_NULL(server_session)) { + ObClientSessionInfo &client_info = client_session->get_session_info(); + ObServerSessionInfo &server_info = server_session->get_session_info(); + if (!client_session->is_proxy_mysql_client_ + && client_info.need_reset_sess_info_vars(server_info) + && is_last_packet) { + SessFieldHashMap &sess_info_hash_map = client_info.get_sess_info_map(); + LOG_DEBUG("send session info to server", "server addr", sm->trans_state_.server_info_.addr_); + if (OB_FAIL(ObProxyTraceUtils::build_sync_sess_info(extra_info, sess_info_value, + sess_info_hash_map, + client_info.get_sess_field_version(), + server_info.get_sess_field_version(), + sm))) { + LOG_WARN("fail to build sync sess info", K(ret)); + } + } + } + } + + return ret; +} + +int ObProxyTraceUtils::get_sess_field_version(int64_t &version, int16_t type, common::hash::ObHashMap &map) +{ + int ret = OB_SUCCESS; + version = 0; + if (OB_FAIL(map.get_refactored(type, version))) { + if (OB_HASH_NOT_EXIST == ret) { + version = 0; + ret = OB_SUCCESS; + } else { + LOG_WARN("query session field version failed", K(type), K(ret)); + } + } + return ret; +} + } // end of namespace proxy } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/proxy/mysqllib/ob_2_0_protocol_utils.h b/src/obproxy/proxy/mysqllib/ob_2_0_protocol_utils.h index 4e7c7891c215278ce58cd81206469c09f01907fe..883917d73d18b8d38f9d8ce70ee9d7a3ef9a03f3 100644 --- a/src/obproxy/proxy/mysqllib/ob_2_0_protocol_utils.h +++ b/src/obproxy/proxy/mysqllib/ob_2_0_protocol_utils.h @@ -18,14 +18,25 @@ #include "rpc/obmysql/ob_mysql_packet.h" #include "proxy/mysqllib/ob_mysql_response.h" #include "proxy/route/ob_route_struct.h" +#include "obproxy/engine/ob_proxy_operator_result.h" namespace oceanbase { +namespace obmysql +{ +class ObMySQLField; +} + namespace obproxy { namespace proxy { + +#define SERVER_EXTRA_INFO_BUF_MAX_LEN (335) // FLTSpanInfo: 75 + FLTAppInfo: 260 +#define CLIENT_EXTRA_INFO_BUF_MAX_LEN (100) // FLTControlInfo:62 + FLTQueryInfo: 34 + typedef obmysql::ObCommonKV ObObJKV; +class ObMysqlSM; class ObProto20Utils { @@ -34,40 +45,52 @@ public: ObProto20Utils(); virtual ~ObProto20Utils(); + // encode packet utils + static int encode_ok_packet(event::ObMIOBuffer &write_buf, const Ob20ProtocolHeaderParam &ob20_head_param, + uint8_t &seq, const int64_t affected_rows, + const obmysql::ObMySQLCapabilityFlags &capability, const uint16_t status_flag = 0); + static int encode_kv_resultset(event::ObMIOBuffer &write_buf, const Ob20ProtocolHeaderParam &ob20_head_param, + uint8_t &seq, const obmysql::ObMySQLField &field, ObObj &field_value, + const uint16_t status_flag = 0); + static int encode_err_packet(event::ObMIOBuffer &write_buf, const Ob20ProtocolHeaderParam &ob20_head_param, + uint8_t &seq, const int err_code, const ObString &msg_buf); + // analyze utils static int analyze_ok_packet_and_get_reroute_info(event::ObIOBufferReader *reader, const int64_t pkt_len, const obmysql::ObMySQLCapabilityFlags &cap, ObProxyRerouteInfo &reroute_info); - - static int analyze_fisrt_mysql_packet(event::ObIOBufferReader &reader, + static int analyze_first_mysql_packet(event::ObIOBufferReader &reader, ObMysqlCompressedOB20AnalyzeResult &result, ObMysqlAnalyzeResult &mysql_result); static int analyze_one_compressed_packet(event::ObIOBufferReader &reader, ObMysqlCompressedOB20AnalyzeResult &result); - static int consume_and_compress_data(event::ObIOBufferReader *reader, event::ObMIOBuffer *write_buf, - const int64_t data_len, const uint8_t compressed_seq, const uint8_t packet_seq, - const uint32_t request_id, const uint32_t connid, const bool is_last_packet, - const bool is_need_reroute, const common::ObIArray *extro_info = NULL); + const int64_t data_len, const Ob20ProtocolHeaderParam &ob20_head_param, + const common::ObIArray *extra_info = NULL); + // fill utils + static int fill_proto20_extra_info(event::ObMIOBuffer *write_buf, const common::ObIArray *extra_info, + const bool is_new_extra_info, int64_t &payload_len, uint64_t &crc64, + bool &is_extra_info_exist); + static int fill_proto20_payload(event::ObIOBufferReader *reader, event::ObMIOBuffer *write_buf, + const int64_t data_len, int64_t &payload_len, uint64_t &crc64); + static int fill_proto20_tailer(event::ObMIOBuffer *write_buf, const uint64_t crc64); + static int fill_proto20_header(char *hdr_start, const int64_t payload_len, + const uint8_t compressed_seq, const uint8_t packet_seq, + const uint32_t request_id, const uint32_t connid, + const bool is_last_packet, const bool is_weak_read, + const bool is_need_reroute, const bool is_extra_info_exist, + const bool is_new_extra_info, const bool is_trans_internal_routing); + static int reserve_proto20_hdr(event::ObMIOBuffer *write_buf, char *&hdr_start); + static bool is_trans_related_sess_info(int16_t type); + private: inline static int analyze_compressed_packet_header(const char *start, const int64_t len, ObMysqlCompressedOB20AnalyzeResult &result); - - inline static int reserve_proto20_hdr(event::ObMIOBuffer *write_buf, char *&hdr_start); - inline static int fill_proto20_header(char *hdr_start, const int64_t payload_len, - const uint8_t compressed_seq, const uint8_t packet_seq, - const uint32_t request_id, const uint32_t connid, - const bool is_last_packet, const bool is_need_reroute, - const bool is_extro_info_exist); - - inline static int fill_proto20_extro_info(event::ObMIOBuffer *write_buf, const common::ObIArray *extro_info, - int64_t &payload_len, uint64_t &crc64, bool &is_extro_info_exist); - - inline static int fill_proto20_payload(event::ObIOBufferReader *reader, event::ObMIOBuffer *write_buf, - const int64_t data_len, int64_t &payload_len, uint64_t &crc64); - - inline static int fill_proto20_tailer(event::ObMIOBuffer *write_buf, const uint64_t crc64); + static int fill_proto20_obobj_extra_info(event::ObMIOBuffer *write_buf, const common::ObIArray *extra_info, + int64_t &payload_len, uint64_t &crc64, bool &is_extra_info_exist); + static int fill_proto20_new_extra_info(event::ObMIOBuffer *write_buf, const common::ObIArray *extra_info, + int64_t &payload_len, uint64_t &crc64, bool &is_extra_info_exist); private: DISALLOW_COPY_AND_ASSIGN(ObProto20Utils); @@ -76,7 +99,26 @@ private: class ObProxyTraceUtils { public: - static int build_client_ip(common::ObIArray &extro_info, char *client_ip_buf, common::ObAddr &client_ip); + static int build_client_ip(common::ObIArray &extra_info, char *buf, int64_t buf_len, ObMysqlSM *sm, + const bool is_last_packet_or_segment); + static int build_extra_info_for_server(ObMysqlSM *sm, char *buf, int64_t buf_len, + common::ObIArray &extra_info, const bool is_last_packet_or_segment); + static int build_extra_info_for_client(ObMysqlSM *sm, char *buf, const int64_t len, + common::ObIArray &extra_info); + static int build_sync_sess_info(common::ObIArray &extra_info, + common::ObSqlString &info_value, + common::hash::ObHashMap &sess_info_hash_map, + common::hash::ObHashMap &client_sess_field_version, + common::hash::ObHashMap &server_sess_field_version, + ObMysqlSM *sm); + static int build_related_extra_info_all(common::ObIArray &extra_info, ObMysqlSM *sm, + char *ip_buf, const int64_t ip_buf_len, + char *extra_info_buf, const int64_t extra_info_buf_len, + common::ObSqlString &info_value, const bool is_last_packet); + static int get_sess_field_version(int64_t &version, int16_t type, common::hash::ObHashMap &map); + +private: + DISALLOW_COPY_AND_ASSIGN(ObProxyTraceUtils); }; } // end of namespace proxy diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_analyzer_utils.cpp b/src/obproxy/proxy/mysqllib/ob_mysql_analyzer_utils.cpp index 8653f70ef03966d07ac5934cd0ca6d4799caee70..95b9d99d8b427990cc7821dcd2581e781b94b57d 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_analyzer_utils.cpp +++ b/src/obproxy/proxy/mysqllib/ob_mysql_analyzer_utils.cpp @@ -77,9 +77,9 @@ int ObMysqlAnalyzerUtils::analyze_compressed_packet_header( ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid input value", KP(start), K(len), K(ret)); } else { - header.compressed_len_ = ob_uint3korr(start); + header.compressed_len_ = uint3korr(start); header.seq_ = static_cast(start[3]); - header.non_compressed_len_ = ob_uint3korr(start + 4); + header.non_compressed_len_ = uint3korr(start + 4); } return ret; } @@ -138,7 +138,7 @@ int ObMysqlAnalyzerUtils::consume_and_normal_compress_data( } else { //checksum off, just copy int64_t written_len = 0; - // because OB_MYSQL_COM_STMT_CLOSE, can not move block, need copy data + // because OB_MYSQL_COM_STMT_CLOSE/OB_MYSQL_COM_STMT_RESET, can not move block, need copy data if (OB_FAIL(write_buf->write(reader, data_len, written_len))) { LOG_WARN("fail to write uncompress data", K(write_buf), K(data_len), K(ret)); } else if (OB_UNLIKELY(written_len != data_len)) { diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_analyzer_utils.h b/src/obproxy/proxy/mysqllib/ob_mysql_analyzer_utils.h index 3a9b166277014156c513e615b425e6c4dde35c55..7f4a8303f649a01f9f0d7101bd95facea535dbfc 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_analyzer_utils.h +++ b/src/obproxy/proxy/mysqllib/ob_mysql_analyzer_utils.h @@ -29,6 +29,7 @@ class ObMIOBuffer; namespace proxy { class ObMysqlCompressedAnalyzeResult; + class ObMysqlAnalyzerUtils { public: diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_common_define.h b/src/obproxy/proxy/mysqllib/ob_mysql_common_define.h index a87bce46d854f9f913546df60c77aa9fa0c9a0e0..76806ac162a5fb2aaa20431868cc99afd2a78412 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_common_define.h +++ b/src/obproxy/proxy/mysqllib/ob_mysql_common_define.h @@ -64,6 +64,13 @@ static const int32_t OB20_PROTOCOL_EXTRA_INFO_LENGTH = 4; // for the lengt static const int16_t OB20_PROTOCOL_VERSION_VALUE = 20; static const int64_t MYSQL_COMPRESSED_OB20_HEALDER_LENGTH = MYSQL_COMPRESSED_HEALDER_LENGTH + OB20_PROTOCOL_HEADER_LENGTH; +enum class ObProxyProtocol +{ + PROTOCOL_NORMAL = 0, + PROTOCOL_CHECKSUM, + PROTOCOL_OB20, +}; + // one of those types indicates that one mysql cmd response is finished enum ObMysqlRespEndingType { @@ -158,30 +165,31 @@ bool is_supported_mysql_cmd(const obmysql::ObMySQLCmd mysql_cmd) case obmysql::OB_MYSQL_COM_TIME: case obmysql::OB_MYSQL_COM_DELAYED_INSERT: case obmysql::OB_MYSQL_COM_DAEMON: + case obmysql::OB_MYSQL_COM_RESET_CONNECTION: // Prepared Statements(Binary Protocol) case obmysql::OB_MYSQL_COM_STMT_PREPARE: case obmysql::OB_MYSQL_COM_STMT_EXECUTE: case obmysql::OB_MYSQL_COM_STMT_PREPARE_EXECUTE: case obmysql::OB_MYSQL_COM_STMT_SEND_LONG_DATA: case obmysql::OB_MYSQL_COM_STMT_CLOSE: + case obmysql::OB_MYSQL_COM_STMT_RESET: // Stored Procedures case obmysql::OB_MYSQL_COM_STMT_FETCH: case obmysql::OB_MYSQL_COM_CHANGE_USER: + // binlog related + case obmysql::OB_MYSQL_COM_REGISTER_SLAVE: + case obmysql::OB_MYSQL_COM_BINLOG_DUMP: + case obmysql::OB_MYSQL_COM_BINLOG_DUMP_GTID: // pieceinfo case obmysql::OB_MYSQL_COM_STMT_SEND_PIECE_DATA: case obmysql::OB_MYSQL_COM_STMT_GET_PIECE_DATA: ret = true; break; // Replication Protocol - case obmysql::OB_MYSQL_COM_BINLOG_DUMP: case obmysql::OB_MYSQL_COM_TABLE_DUMP: case obmysql::OB_MYSQL_COM_CONNECT_OUT: - case obmysql::OB_MYSQL_COM_REGISTER_SLAVE: - case obmysql::OB_MYSQL_COM_BINLOG_DUMP_GTID: // Stored Procedures case obmysql::OB_MYSQL_COM_SET_OPTION: - // mysql prepare statement - case obmysql::OB_MYSQL_COM_STMT_RESET: ret = false; break; default: diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_compress_analyzer.cpp b/src/obproxy/proxy/mysqllib/ob_mysql_compress_analyzer.cpp index 6b412927575fbcd2f1a964fb4303271e3b21ed6f..fc8920f560784e79f43cc687855322d6dd8220ae 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_compress_analyzer.cpp +++ b/src/obproxy/proxy/mysqllib/ob_mysql_compress_analyzer.cpp @@ -63,6 +63,8 @@ int ObMysqlCompressAnalyzer::init( } } is_inited_ = true; + + LOG_DEBUG("compress analyzer init", K(last_seq), K(mode), K(mysql_cmd), K(enable_extra_ok_packet_for_stats), K(lbt())); } return ret; } @@ -190,7 +192,7 @@ int ObMysqlCompressAnalyzer::analyze_compressed_response(event::ObIOBufferReader } } } - LOG_DEBUG("analyze compressed response finished", "data_size", reader.read_avail(), K(resp)); + LOG_DEBUG("analyze compressed response finished", "data_size", reader.read_avail(), K(mode_), K(resp)); return ret; } @@ -238,6 +240,7 @@ int ObMysqlCompressAnalyzer::analyze_compressed_response(const ObString &compres is_stream_finished_ = true; LOG_DEBUG("simple mode, compressed stream complete", K(mode_)); } + LOG_DEBUG("print analyzer in simple mode", K(is_last_packet_), K(is_last_data), K(resp)); } else if (DECOMPRESS_MODE == mode_) { if (is_last_packet_) { if (OB_FAIL(analyze_last_compress_packet(buf_start, buf_len, is_last_data, resp))) { @@ -262,9 +265,8 @@ int ObMysqlCompressAnalyzer::analyze_compressed_response(const ObString &compres return ret; } -int ObMysqlCompressAnalyzer::decode_compressed_header( - const ObString &compressed_data, - int64_t &avail_len) +int ObMysqlCompressAnalyzer::decode_compressed_header(const ObString &compressed_data, + int64_t &avail_len) { int ret = OB_SUCCESS; int64_t origin_len = compressed_data.length(); @@ -787,6 +789,46 @@ int ObMysqlCompressAnalyzer::analyze_response(event::ObIOBufferReader &reader, O return ret; } +int ObMysqlCompressAnalyzer::analyze_first_request(ObIOBufferReader &reader, + ObMysqlCompressedAnalyzeResult &result, + ObProxyMysqlRequest &req, + ObMysqlAnalyzeStatus &status) +{ + UNUSED(req); + + int ret = OB_SUCCESS; + result.reset(); + + if (!is_inited_) { + ret = OB_NOT_INIT; + LOG_WARN("analyzer not init", K(ret)); + } else if (OB_FAIL(analyze_one_compressed_packet(reader, result))) { // 7 + 24 header decode finish + LOG_WARN("fail to analyze one compressed packet", K(ret)); + } else if (ANALYZE_DONE == result.status_) { + status = result.status_; + + // total ob20 request received complete here, total_len = ob20.head.compressed_len + mysql compress head(3+1+3) + // get extra info from ob20 payload + if (OB_FAIL(analyze_compress_packet_payload(reader, result))) { + LOG_WARN("fail to analyze compress packet payload", K(ret)); + status = ANALYZE_ERROR; + } + } + + return ret; +} + +int ObMysqlCompressAnalyzer::analyze_compress_packet_payload(event::ObIOBufferReader &reader, + ObMysqlCompressedAnalyzeResult &result) +{ + UNUSED(reader); + UNUSED(result); + + int ret = OB_INVALID_ARGUMENT; + LOG_WARN("unexpected protocol type handle."); + return ret; +} + } // end of namespace proxy } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_compress_analyzer.h b/src/obproxy/proxy/mysqllib/ob_mysql_compress_analyzer.h index 8c988c506a0e1548c6834322d0edd54e6125a053..b0c1875a642d157aff5480cee97eb3d52adf8828 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_compress_analyzer.h +++ b/src/obproxy/proxy/mysqllib/ob_mysql_compress_analyzer.h @@ -17,6 +17,7 @@ #include "proxy/mysqllib/ob_i_mysql_respone_analyzer.h" #include "proxy/mysqllib/ob_proxy_parser_utils.h" #include "utils/ob_zlib_stream_compressor.h" +#include "obproxy/iocore/eventsystem/ob_io_buffer.h" namespace oceanbase { @@ -28,6 +29,7 @@ class ObMIOBuffer; } namespace proxy { +class ObProxyMysqlRequest; class ObMysqlCompressAnalyzer : public ObIMysqlRespAnalyzer { @@ -76,6 +78,13 @@ public: ObMysqlResp &resp); int analyze_first_response(event::ObIOBufferReader &reader, ObMysqlCompressedAnalyzeResult &result); + + int analyze_first_request(event::ObIOBufferReader &reader, + ObMysqlCompressedAnalyzeResult &result, + ObProxyMysqlRequest &req, + ObMysqlAnalyzeStatus &status); + virtual int analyze_compress_packet_payload(event::ObIOBufferReader &reader, + ObMysqlCompressedAnalyzeResult &result); common::ObString get_last_packet_string(); diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_compress_ob20_analyzer.cpp b/src/obproxy/proxy/mysqllib/ob_mysql_compress_ob20_analyzer.cpp index 366c8193fd70730e1f7d7972fa525df47e9a3240..b0e6fbc2e56381a9a3b396f975fc8c34583a59da 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_compress_ob20_analyzer.cpp +++ b/src/obproxy/proxy/mysqllib/ob_mysql_compress_ob20_analyzer.cpp @@ -17,6 +17,7 @@ #include "lib/checksum/ob_crc64.h" #include "lib/checksum/ob_crc16.h" #include "rpc/obmysql/ob_mysql_util.h" +#include "lib/utility/ob_2_0_full_link_trace_info.h" using namespace oceanbase::obmysql; using namespace oceanbase::obproxy::event; @@ -62,6 +63,8 @@ void ObMysqlCompressOB20Analyzer::reset() last_ob20_seq_ = 0; request_id_ = 0; sessid_ = 0; + remain_head_checked_len_ = 0; + extra_header_len_ = 0; extra_len_ = 0; extra_checked_len_ = 0; payload_checked_len_ = 0; @@ -82,6 +85,8 @@ int64_t ObMysqlCompressOB20Analyzer::to_string(char *buf, const int64_t buf_len) J_KV(K_(last_ob20_seq), K_(request_id), K_(sessid), + K_(remain_head_checked_len), + K_(extra_header_len), K_(extra_len), K_(extra_checked_len), K_(payload_checked_len), @@ -135,7 +140,7 @@ int ObMysqlCompressOB20Analyzer::do_analyzer_end(ObMysqlResp &resp) return ret; } -inline int ObMysqlCompressOB20Analyzer::do_body_checksum(const char *&payload_start, uint64_t &payload_len) +inline int ObMysqlCompressOB20Analyzer::do_body_checksum(const char *&payload_start, int64_t &payload_len) { int ret = OB_SUCCESS; uint32_t tail_remain_len = static_cast(OB20_PROTOCOL_TAILER_LENGTH - tail_checked_len_); @@ -153,6 +158,7 @@ inline int ObMysqlCompressOB20Analyzer::do_body_checksum(const char *&payload_st ObMySQLUtil::get_uint4(temp_buf, payload_checksum); ob20_analyzer_state_ = OB20_ANALYZER_END; + if (payload_checksum != 0) { if (OB_UNLIKELY(crc64_ != payload_checksum)) { ret = OB_CHECKSUM_ERROR; @@ -162,22 +168,29 @@ inline int ObMysqlCompressOB20Analyzer::do_body_checksum(const char *&payload_st // 0 means skip checksum LOG_DEBUG("body checksum is 0", K_(crc64)); } + } } return ret; } -inline int ObMysqlCompressOB20Analyzer::do_body_decode(const char *&payload_start, uint64_t &payload_len, ObMysqlResp &resp) +inline int ObMysqlCompressOB20Analyzer::do_body_decode(const char *&payload_start, + int64_t &payload_len, + ObMysqlResp &resp) { int ret = OB_SUCCESS; - uint32_t payload_remain_len = static_cast(curr_compressed_ob20_header_.payload_len_ - payload_checked_len_); + uint32_t payload_remain_len = static_cast(curr_compressed_ob20_header_.payload_len_ + - extra_header_len_ - extra_len_ - payload_checked_len_); if (payload_remain_len > 0 && payload_len > 0) { int64_t filled_len = 0; uint32_t body_len = static_cast(payload_len <= payload_remain_len ? payload_len : payload_remain_len); + crc64_ = ob_crc64(crc64_, payload_start, body_len); // actual is crc32 + LOG_DEBUG("print body decode", K(payload_len), K(payload_remain_len), K(payload_checked_len_), K(body_len)); + ObString buf; buf.assign_ptr(payload_start, body_len); ObBufferReader buf_reader(buf); @@ -195,7 +208,7 @@ inline int ObMysqlCompressOB20Analyzer::do_body_decode(const char *&payload_star resp.get_analyze_result().reserved_len_for_ob20_ok_ = result_.get_reserved_len(); LOG_DEBUG("do payload decode succ", K_(payload_checked_len), K(payload_len)); - if (payload_checked_len_ == curr_compressed_ob20_header_.payload_len_) { + if (payload_checked_len_ == curr_compressed_ob20_header_.payload_len_ - extra_header_len_ - extra_len_) { ob20_analyzer_state_ = OB20_ANALYZER_TAIL; LOG_DEBUG("do payload decode end", K_(crc64), K_(payload_checked_len), K(payload_len)); } @@ -205,42 +218,83 @@ inline int ObMysqlCompressOB20Analyzer::do_body_decode(const char *&payload_star return ret; } -inline int ObMysqlCompressOB20Analyzer::do_extra_info_decode(const char* &payload_start, uint64_t &payload_len) +inline int ObMysqlCompressOB20Analyzer::do_extra_info_decode(const char* &payload_start, + int64_t &payload_len, + ObMysqlResp &resp) { int ret = OB_SUCCESS; + Ob20ExtraInfo &extra_info = resp.get_analyze_result().get_extra_info(); if (curr_compressed_ob20_header_.flag_.is_extra_info_exist()) { //get extra info length if (extra_len_ == 0) { uint32_t extra_remain_len = static_cast(OB20_PROTOCOL_EXTRA_INFO_LENGTH - extra_checked_len_); - uint32_t extra_len = static_cast(payload_len <= extra_remain_len ? payload_len : extra_remain_len); - MEMCPY(temp_buf_ + extra_checked_len_, payload_start, extra_len); - extra_checked_len_ += extra_len; - payload_start += extra_len; - payload_len -= extra_len; + uint32_t extra_header_len = static_cast(payload_len <= extra_remain_len ? payload_len : extra_remain_len); + + crc64_ = ob_crc64(crc64_, payload_start, extra_header_len); // actual is crc32 + + MEMCPY(temp_buf_ + extra_checked_len_, payload_start, extra_header_len); + extra_checked_len_ += extra_header_len; + payload_start += extra_header_len; + payload_len -= extra_header_len; LOG_DEBUG("do extra info lenth succ", K_(extra_checked_len), K(payload_len)); if (extra_checked_len_ == OB20_PROTOCOL_EXTRA_INFO_LENGTH) { char *temp_buf = temp_buf_; ObMySQLUtil::get_uint4(temp_buf, extra_len_); + extra_header_len_ = OB20_PROTOCOL_EXTRA_INFO_LENGTH; extra_checked_len_ = 0; - LOG_DEBUG("do extra info lenth end", K_(extra_len), K(payload_len)); + LOG_DEBUG("do extra info length end", K_(extra_len), K_(extra_header_len), K(payload_len)); + + extra_info.extra_info_buf_.reset(); } } //get extra info - uint32_t extra_remain_len = extra_len_ - extra_checked_len_; - if (extra_len_ > 0 && extra_remain_len > 0 && payload_len > 0) { - uint32_t extra_remain_len = static_cast(extra_len_ - extra_checked_len_); + int64_t extra_remain_len = extra_len_ - extra_checked_len_; + if (OB_SUCC(ret) && extra_len_ > 0 && extra_remain_len > 0 && payload_len > 0) { uint32_t extra_len = static_cast(payload_len <= extra_remain_len ? payload_len : extra_remain_len); - extra_checked_len_ += extra_len; - payload_start += extra_len; - payload_len -= extra_len; - - LOG_DEBUG("do extra info succ", K_(extra_checked_len), K(payload_len)); - if (extra_checked_len_ == extra_len_) { - ob20_analyzer_state_ = OB20_ANALYZER_PAYLOAD; - LOG_DEBUG("do extra info end", K_(extra_len), K(payload_len)); + if (!extra_info.extra_info_buf_.is_inited()) { + if (OB_FAIL(extra_info.extra_info_buf_.init(extra_len_))) { + LOG_WARN("fail int alloc mem", K(extra_len_), K(ret)); + } + } + if (OB_SUCC(ret)) { + if (OB_FAIL(extra_info.extra_info_buf_.write(payload_start, extra_len))) { + LOG_WARN("fail to write", K(extra_len), K(ret)); + } + } + + if (OB_SUCC(ret)) { + crc64_ = ob_crc64(crc64_, payload_start, extra_len); // actual is crc32 + + extra_checked_len_ += extra_len; + payload_start += extra_len; + payload_len -= extra_len; + + LOG_DEBUG("do extra info succ", K_(extra_checked_len), K(payload_len)); + if (extra_checked_len_ == extra_len_) { + if (curr_compressed_ob20_header_.flag_.is_new_extra_info()) { + if (OB_FAIL(do_new_extra_info_decode(extra_info.extra_info_buf_.ptr(), + extra_info.extra_info_buf_.len(), + extra_info, + resp.get_analyze_result().flt_))) { + LOG_WARN("fail to do resp new extra info decode", K(ret)); + } + } else { + if (OB_FAIL(do_obobj_extra_info_decode(extra_info.extra_info_buf_.ptr(), + extra_info.extra_info_buf_.len(), + extra_info, + resp.get_analyze_result().flt_))) { + LOG_WARN("fail to do resp obobj extra info decode", K(ret)); + } + } + + if (OB_SUCC(ret)) { + ob20_analyzer_state_ = OB20_ANALYZER_PAYLOAD; + LOG_DEBUG("do extra info end", K_(extra_len), K(payload_len)); + } + } // if extra info received done } } } else { @@ -251,6 +305,97 @@ inline int ObMysqlCompressOB20Analyzer::do_extra_info_decode(const char* &payloa return ret; } +int ObMysqlCompressOB20Analyzer::do_obobj_extra_info_decode(const char *buf, + const int64_t len, + Ob20ExtraInfo &extra_info, + common::FLTObjManage &flt_manage) +{ + int ret = OB_SUCCESS; + + int64_t pos = 0; + while (OB_SUCC(ret) && pos < len) { + common::ObObj key; + common::ObObj value; + if (OB_FAIL(key.deserialize(buf, len, pos))) { + LOG_WARN("fail to deserialize extra info", K(ret)); + } else if (!key.is_varchar()) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid extra info key type", K(ret), K(key)); + } else if (OB_FAIL(value.deserialize(buf, len, pos))) { + LOG_WARN("fail to deserialize extra info", K(ret)); + } else if (!value.is_varchar()) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid extra info value type", K(ret), K(key), K(value)); + } else { + LOG_DEBUG("deserialize extra info", K(key), K(value)); + + if (0 == key.get_string().case_compare(OB_V20_PRO_EXTRA_KV_NAME_SYNC_SESSION_INFO)) { + const char *value_ptr = value.get_string().ptr(); + const int64_t value_len = value.get_string().length(); + if (OB_FAIL(extra_info.add_sess_info_buf(value_ptr, value_len))) { + LOG_WARN("fail to write sess info to buf", K(ret), K(value)); + } + } else if (0 == key.get_string().case_compare(OB_V20_PRO_EXTRA_KV_NAME_FULL_LINK_TRACE)) { + int64_t full_pos = 0; + ObString full_trc = value.get_string(); + const char *full_trc_buf = full_trc.ptr(); + const int64_t full_trc_len = full_trc.length(); + if (OB_FAIL(flt_manage.deserialize(full_trc_buf, full_trc_len, full_pos))) { + LOG_WARN("fail to deserialize FLT", K(ret)); + } else if (full_pos != full_trc_len) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected pos and length check", K(ret), K(full_pos), K(full_trc)); + } else { + LOG_DEBUG("succ to deserialize obobj extra info", K(flt_manage)); + } + } else { + LOG_DEBUG("attention: do no recognize such an extra info key", K(ret), K(key)); + } + } + } // while + + return ret; +} + +int ObMysqlCompressOB20Analyzer::do_new_extra_info_decode(const char *buf, + const int64_t len, + Ob20ExtraInfo &extra_info, + common::FLTObjManage &flt_manage) +{ + int ret = OB_SUCCESS; + + int64_t pos = 0; + while (OB_SUCC(ret) && pos < len) { + int16_t key_type = OB20_SVR_END; + int32_t key_len = 0; + if (OB_FAIL(common::Ob20FullLinkTraceTransUtil::resolve_type_and_len(buf, len, pos, key_type, key_len))) { + LOG_WARN("fail to resolve type and len for new extra info", K(ret)); + } else { + Ob20NewExtraInfoProtocolKeyType type = static_cast(key_type); + if (type == SESS_INFO) { + if (OB_FAIL(extra_info.add_sess_info_buf(buf+pos, key_len))) { + LOG_WARN("fail to write sess info buf", K(ret), K(key_len)); + } + } else if (type == FULL_TRC) { + int64_t full_pos = 0; + if (OB_FAIL(flt_manage.deserialize(buf + pos, key_len, full_pos))) { + LOG_WARN("fail to deserialize FLT", K(ret)); + } else if (full_pos != key_len) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected pos and length check", K(ret), K(full_pos)); + } else { + LOG_DEBUG("succ to deserialize new extra info", K(flt_manage)); + } + } else { + LOG_WARN("unexpected new extra info type", K(type), K(key_len)); + } + pos += key_len; // pos offset at last + } + } // while + + return ret; +} + inline int ObMysqlCompressOB20Analyzer::do_header_checksum(const char *header_start) { int ret = OB_SUCCESS; @@ -309,9 +454,8 @@ inline int ObMysqlCompressOB20Analyzer::do_header_decode(const char *start) return ret; } -int ObMysqlCompressOB20Analyzer::decode_compressed_header( - const ObString &compressed_data, - int64_t &avail_len) +int ObMysqlCompressOB20Analyzer::decode_compressed_header(const ObString &compressed_data, + int64_t &avail_len) { int ret = OB_SUCCESS; int64_t origin_len = compressed_data.length(); @@ -383,6 +527,7 @@ int ObMysqlCompressOB20Analyzer::decode_compressed_header( is_last_packet_ = true; } + extra_header_len_ = 0; extra_len_ = 0; extra_checked_len_ = 0; payload_checked_len_ = 0; @@ -392,6 +537,7 @@ int ObMysqlCompressOB20Analyzer::decode_compressed_header( last_ob20_seq_++; last_seq_ = curr_compressed_ob20_header_.cp_hdr_.seq_; remain_len_ = curr_compressed_ob20_header_.payload_len_ + OB20_PROTOCOL_TAILER_LENGTH; + LOG_DEBUG("decode compressed header succ", K_(curr_compressed_ob20_header)); } } @@ -411,7 +557,7 @@ int ObMysqlCompressOB20Analyzer::analyze_last_compress_packet( } else if (OB_FAIL(decompress_data(start, len, resp))) { LOG_WARN("fail to decompress last mysql packet", K(ret)); } - + resp.get_analyze_result().is_server_trans_internal_routing_ = curr_compressed_ob20_header_.flag_.is_trans_internal_routing(); return ret; } @@ -419,11 +565,14 @@ int ObMysqlCompressOB20Analyzer::decompress_data(const char *compressed_data, co { int ret = OB_SUCCESS; const char *payload_start = compressed_data; - uint64_t payload_len = len; + int64_t payload_len = len; + + LOG_DEBUG("ob20 analyzer state", K(ob20_analyzer_state_), K(len)); + while (OB_SUCC(ret) && payload_len > 0) { switch (ob20_analyzer_state_) { case OB20_ANALYZER_EXTRA: { - if (OB_FAIL(do_extra_info_decode(payload_start, payload_len))) { + if (OB_FAIL(do_extra_info_decode(payload_start, payload_len, resp))) { LOG_ERROR("do extra info decode failed", K(payload_len), K(len), KPC(this), K(ret)); } break; @@ -485,7 +634,7 @@ int ObMysqlCompressOB20Analyzer::analyze_first_response( } } else { ObMysqlAnalyzeResult mysql_result; - if (OB_FAIL(ObProto20Utils::analyze_fisrt_mysql_packet(reader, dynamic_cast(result), mysql_result))) { + if (OB_FAIL(ObProto20Utils::analyze_first_mysql_packet(reader, dynamic_cast(result), mysql_result))) { LOG_WARN("fail to analyze packet", K(&reader), K(ret)); } else { // if it is result + eof + error + ok, it may be not.... @@ -511,33 +660,202 @@ int ObMysqlCompressOB20Analyzer::analyze_first_response( return ret; } -int ObProxyTraceUtils::build_client_ip(ObIArray &extro_info, char *client_ip_buf, ObAddr &client_ip) +int ObMysqlCompressOB20Analyzer::analyze_compress_packet_payload(ObIOBufferReader &reader, + ObMysqlCompressedAnalyzeResult &result) { int ret = OB_SUCCESS; - int64_t pos = 0; - if (OB_FAIL(ObMySQLUtil::store_str_nzt(client_ip_buf, MAX_IP_BUFFER_LEN, OB_TRACE_INFO_CLIENT_IP, pos))) { - LOG_WARN("fail to store client addr", K(ret)); - } else if (OB_FAIL(ObMySQLUtil::store_str_nzt(client_ip_buf, MAX_IP_BUFFER_LEN, "=", pos))) { - LOG_WARN("fail to store equals sign", K(ret)); - } else if (OB_UNLIKELY(!client_ip.ip_to_string(client_ip_buf + STRLEN(client_ip_buf), - static_cast(MAX_IP_BUFFER_LEN - pos)))) { + + ObMysqlCompressedOB20AnalyzeResult &ob20_result = dynamic_cast(result); + if (!ob20_result.ob20_header_.flag_.is_extra_info_exist()) { + LOG_DEBUG("no extra info flag in ob20 head"); + } else { + ObIOBufferBlock *block = NULL; + int64_t offset = 0; + char *data = NULL; + int64_t data_size = 0; + if (NULL != reader.block_) { + reader.skip_empty_blocks(); + block = reader.block_; + offset = reader.start_offset_; + data = block->start() + offset; + data_size = block->read_avail() - offset; + } + + if (data_size <= 0) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("the first block data_size in reader is less than 0", K(offset), K(block->read_avail()), K(ret)); + } + + ob20_req_analyze_state_ = OB20_REQ_ANALYZE_HEAD; // begin + ObString req_buf; + + while (OB_SUCC(ret) && block != NULL && data_size > 0 && ob20_req_analyze_state_ != OB20_REQ_ANALYZE_END) { + req_buf.assign_ptr(data, static_cast(data_size)); + if (OB_FAIL(decompress_request_packet(req_buf, ob20_result))) { //only extra info now + LOG_WARN("fail to decompress request packet", K(ret)); + } else { + offset = 0; + block = block->next_; + if (NULL != block) { + data = block->start(); + data_size = block->read_avail(); + } + } + } + } + + LOG_DEBUG("analyze ob20 request payload finished", K(ret), K(reader.read_avail()), K(ob20_result)); + + return ret; +} + +// check the buffer cross different blocks +int ObMysqlCompressOB20Analyzer::decompress_request_packet(ObString &req_buf, + ObMysqlCompressedOB20AnalyzeResult &ob20_result) +{ + int ret = OB_SUCCESS; + + if (!is_inited_ || req_buf.length() <= 0) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected argument check", K(ret), K(req_buf)); + } else { + const char *buf_start = req_buf.ptr(); + int64_t buf_len = req_buf.length(); + + while (OB_SUCC(ret) && buf_len > 0 && ob20_req_analyze_state_ != OB20_REQ_ANALYZE_END) { + switch (ob20_req_analyze_state_) { + case OB20_REQ_ANALYZE_HEAD: { + if (OB_FAIL(do_req_head_decode(buf_start, buf_len))) { + LOG_WARN("fail to to req head decode", K(ret)); + } + break; + } + case OB20_REQ_ANALYZE_EXTRA: { + if (OB_FAIL(do_req_extra_decode(buf_start, buf_len, ob20_result))) { + LOG_WARN("fail to do req extra decode", K(ret)); + } + break; + } + case OB20_REQ_ANALYZE_END: { + break; + } + default: { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("ob20 analyze decompress req unknown status", K(ret), K(ob20_req_analyze_state_)); + } + } + } + } + + return ret; +} + +int ObMysqlCompressOB20Analyzer::do_req_head_decode(const char* &buf_start, int64_t &buf_len) +{ + int ret = OB_SUCCESS; + + if (remain_head_checked_len_ == 0) { + remain_head_checked_len_ = MYSQL_COMPRESSED_OB20_HEALDER_LENGTH; + } else if (remain_head_checked_len_ < 0) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("fail to ip_to_string", K(client_ip), K(ret)); + LOG_WARN("unexpected remain head checked len", K(ret), K(remain_head_checked_len_)); } else { - ObObJKV ob_trace_info; + // remain_head_checked_len_ > 0, nothing + } - ob_trace_info.key_.set_varchar(OB_TRACE_INFO_VAR_NAME, static_cast(STRLEN(OB_TRACE_INFO_VAR_NAME))); - ob_trace_info.key_.set_default_collation_type(); + if (OB_SUCC(ret)) { + if (remain_head_checked_len_ > buf_len) { + remain_head_checked_len_ -= buf_len; + buf_start += buf_len; + buf_len = 0; + } else { + buf_start += remain_head_checked_len_; + buf_len -= remain_head_checked_len_; + remain_head_checked_len_ = 0; + ob20_req_analyze_state_ = OB20_REQ_ANALYZE_EXTRA; + } + } + + LOG_DEBUG("ob20 do req head decode", K(remain_head_checked_len_), K(buf_len), K(ob20_req_analyze_state_)); + + return ret; +} + +int ObMysqlCompressOB20Analyzer::do_req_extra_decode(const char *&buf_start, + int64_t &buf_len, + ObMysqlCompressedOB20AnalyzeResult &ob20_result) +{ + int ret = OB_SUCCESS; + + if (ob20_result.ob20_header_.flag_.is_extra_info_exist()) { + // extra len + if (extra_len_ == 0) { + uint32_t extra_remain_len = static_cast(OB20_PROTOCOL_EXTRA_INFO_LENGTH - extra_checked_len_); + uint32_t extra_header_len = static_cast(MIN(buf_len, extra_remain_len)); - ob_trace_info.value_.set_varchar(client_ip_buf, static_cast(STRLEN(client_ip_buf))); - ob_trace_info.value_.set_default_collation_type(); + MEMCPY(temp_buf_ + extra_checked_len_, buf_start, extra_header_len); + extra_checked_len_ += extra_header_len; + buf_start += extra_header_len; + buf_len -= extra_header_len; - extro_info.push_back(ob_trace_info); + if (extra_checked_len_ == OB20_PROTOCOL_EXTRA_INFO_LENGTH) { + char *temp_buf = temp_buf_; + ObMySQLUtil::get_uint4(temp_buf, extra_len_); + ob20_result.extra_info_.extra_len_ = extra_len_; + extra_checked_len_ = 0; + LOG_DEBUG("ob20 do req extra len decode success", K(extra_len_), K(buf_len)); + ob20_result.extra_info_.extra_info_buf_.reset(); + } + } + + // extra info + int64_t extra_remain_len = extra_len_ - extra_checked_len_; + if (extra_len_ > 0 && buf_len > 0 && extra_remain_len > 0) { + Ob20ExtraInfo &extra_info = ob20_result.extra_info_; + if (!extra_info.extra_info_buf_.is_inited() + && OB_FAIL(extra_info.extra_info_buf_.init(extra_len_))) { + LOG_WARN("fail to init buf", K(ret)); + } + if (OB_SUCC(ret)) { + uint32_t curr_extra_len = static_cast(MIN(buf_len, extra_remain_len)); + if (OB_FAIL(extra_info.extra_info_buf_.write(buf_start, curr_extra_len))) { + LOG_WARN("fail to write to buf", K(ret), K(buf_len)); + } else { + extra_checked_len_ += curr_extra_len; + buf_start += curr_extra_len; + buf_len -= curr_extra_len; + + // decode total extra info + if (extra_checked_len_ == extra_len_) { + const char *buf = extra_info.extra_info_buf_.ptr(); + const int64_t len = extra_info.extra_info_buf_.len(); + if (ob20_result.ob20_header_.flag_.is_new_extra_info()) { + if (OB_FAIL(do_new_extra_info_decode(buf, len, extra_info, ob20_result.flt_))) { + LOG_WARN("fail to do new extra info decode", K(ret)); + } + } else { + if (OB_FAIL(do_obobj_extra_info_decode(buf, len, extra_info, ob20_result.flt_))) { + LOG_WARN("fail to do req obobj extra info decode", K(ret)); + } + } + + if (OB_SUCC(ret)) { + ob20_req_analyze_state_ = OB20_REQ_ANALYZE_END; + LOG_DEBUG("ob20 req analyzer analyzed finished"); + } + } // decode total extra info + } + } + } + } else { + ob20_req_analyze_state_ = OB20_REQ_ANALYZE_END; + LOG_DEBUG("no extra info flag, set to analyze end"); } return ret; } + } // end of namespace proxy } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_compress_ob20_analyzer.h b/src/obproxy/proxy/mysqllib/ob_mysql_compress_ob20_analyzer.h index c520fbe96698afad40a92b14fefb46d1e4a3537c..7fd1bdb76d4d91fc1b6f028c9140aa705179c1dd 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_compress_ob20_analyzer.h +++ b/src/obproxy/proxy/mysqllib/ob_mysql_compress_ob20_analyzer.h @@ -19,6 +19,13 @@ namespace oceanbase { + +namespace common +{ +class ObObj; +class FLTObjManage; +} + namespace obproxy { namespace proxy @@ -33,13 +40,21 @@ enum OB20AnalyzerState OB20_ANALYZER_MAX }; +enum OB20ReqAnalyzeState +{ + OB20_REQ_ANALYZE_HEAD, + OB20_REQ_ANALYZE_EXTRA, + OB20_REQ_ANALYZE_END, + OB20_REQ_ANALYZE_MAX +}; + class ObMysqlCompressOB20Analyzer : public ObMysqlCompressAnalyzer { public: ObMysqlCompressOB20Analyzer() - : ObMysqlCompressAnalyzer(), last_ob20_seq_(0), request_id_(0), sessid_(0), - extra_len_(0), extra_checked_len_(0), payload_checked_len_(0), tail_checked_len_(0), - ob20_analyzer_state_(OB20_ANALYZER_MAX), crc64_(0), curr_compressed_ob20_header_() + : ObMysqlCompressAnalyzer(), last_ob20_seq_(0), request_id_(0), sessid_(0), remain_head_checked_len_(0), + extra_header_len_(0), extra_len_(0), extra_checked_len_(0), payload_checked_len_(0), tail_checked_len_(0), + ob20_analyzer_state_(OB20_ANALYZER_MAX), crc64_(0), result_(), curr_compressed_ob20_header_() {} virtual ~ObMysqlCompressOB20Analyzer() { reset(); } @@ -58,6 +73,13 @@ public: const bool need_receive_completed, ObMysqlCompressedAnalyzeResult &result, ObMysqlResp &resp); + virtual int analyze_compress_packet_payload(event::ObIOBufferReader &reader, + ObMysqlCompressedAnalyzeResult &result); + int decompress_request_packet(common::ObString &req_buf, + ObMysqlCompressedOB20AnalyzeResult &ob20_result); + int do_req_head_decode(const char* &buf_start, int64_t &buf_len); + int do_req_extra_decode(const char* &buf_start, int64_t &buf_len, ObMysqlCompressedOB20AnalyzeResult &ob20_result); + int64_t to_string(char *buf, const int64_t buf_len) const; protected: @@ -72,22 +94,29 @@ protected: private: int do_header_decode(const char *start); int do_header_checksum(const char *header_start); - int do_extra_info_decode(const char *&payload_start, uint64_t &payload_len); - int do_body_checksum(const char *&payload_start, uint64_t &payload_len); - int do_body_decode(const char *&payload_start, uint64_t &payload_len, ObMysqlResp &resp); + int do_extra_info_decode(const char *&payload_start, int64_t &payload_len, ObMysqlResp &resp); + int do_body_checksum(const char *&payload_start, int64_t &payload_len); + int do_body_decode(const char *&payload_start, int64_t &payload_len, ObMysqlResp &resp); int do_analyzer_end(ObMysqlResp &resp); + int do_obobj_extra_info_decode(const char *buf, const int64_t len, Ob20ExtraInfo &extra_info, + common::FLTObjManage &flt_manage); + int do_new_extra_info_decode(const char *buf, const int64_t len, Ob20ExtraInfo &extra_info, + common::FLTObjManage &flt_manage); private: uint8_t last_ob20_seq_; uint32_t request_id_; uint32_t sessid_; + int64_t remain_head_checked_len_; + uint32_t extra_header_len_; uint32_t extra_len_; uint32_t extra_checked_len_; uint32_t payload_checked_len_; uint32_t tail_checked_len_; + enum OB20ReqAnalyzeState ob20_req_analyze_state_; enum OB20AnalyzerState ob20_analyzer_state_; - char temp_buf_[4]; - char header_buf_[MYSQL_COMPRESSED_OB20_HEALDER_LENGTH]; + char temp_buf_[OB20_PROTOCOL_EXTRA_INFO_LENGTH]; // temp 4 extra len buffer + char header_buf_[MYSQL_COMPRESSED_OB20_HEALDER_LENGTH]; // temp 7+24 head buffer uint64_t crc64_; ObRespResult result_; ObMysqlRespAnalyzer analyzer_; diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_config_processor.cpp b/src/obproxy/proxy/mysqllib/ob_mysql_config_processor.cpp index 4ad44b3c5c7046f3a0559df3de6713d5d69c6cc4..b693c59583ce2f40e3308cad1ff4935f31e09215 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_config_processor.cpp +++ b/src/obproxy/proxy/mysqllib/ob_mysql_config_processor.cpp @@ -74,6 +74,7 @@ ObMysqlConfigParams::ObMysqlConfigParams() task_thread_num_(0), block_thread_num_(0), grpc_thread_num_(0), + shard_scan_thread_num_(0), automatic_match_work_thread_(true), enable_congestion_(false), @@ -86,6 +87,7 @@ ObMysqlConfigParams::ObMysqlConfigParams() enable_reroute_(false), enable_index_route_(false), enable_causal_order_read_(true), + enable_transaction_internal_routing_(true), sqlaudit_mem_limited_(0), internal_cmd_mem_limited_(0), @@ -114,7 +116,11 @@ ObMysqlConfigParams::ObMysqlConfigParams() proxy_service_mode_(OB_MAX_SERVICE_MODE), server_routing_mode_(OB_MAX_ROUTING_MODE), proxy_id_(0), - client_max_memory_size_(0) + client_max_memory_size_(0), + enable_cpu_isolate_(false), + enable_primary_zone_(true), + ip_listen_mode_(0), + local_bound_ipv6_ip_() { proxy_idc_name_[0] = '\0'; } @@ -167,6 +173,7 @@ int ObMysqlConfigParams::assign_config(const ObProxyConfig &proxy_config) CONFIG_ITEM_ASSIGN(task_thread_num); CONFIG_ITEM_ASSIGN(block_thread_num); CONFIG_ITEM_ASSIGN(grpc_thread_num); + CONFIG_ITEM_ASSIGN(shard_scan_thread_num); CONFIG_ITEM_ASSIGN(automatic_match_work_thread); CONFIG_ITEM_ASSIGN(enable_congestion); @@ -176,6 +183,7 @@ int ObMysqlConfigParams::assign_config(const ObProxyConfig &proxy_config) CONFIG_ITEM_ASSIGN(enable_proxy_scramble); CONFIG_ITEM_ASSIGN(enable_compression_protocol); CONFIG_ITEM_ASSIGN(enable_ob_protocol_v2); + CONFIG_ITEM_ASSIGN(enable_transaction_internal_routing); CONFIG_ITEM_ASSIGN(enable_reroute); CONFIG_ITEM_ASSIGN(enable_index_route); CONFIG_ITEM_ASSIGN(enable_causal_order_read); @@ -206,6 +214,9 @@ int ObMysqlConfigParams::assign_config(const ObProxyConfig &proxy_config) CONFIG_TIME_ASSIGN(slow_query_time_threshold); CONFIG_ITEM_ASSIGN(proxy_id); CONFIG_ITEM_ASSIGN(client_max_memory_size); + CONFIG_ITEM_ASSIGN(enable_cpu_isolate); + CONFIG_ITEM_ASSIGN(enable_primary_zone); + CONFIG_ITEM_ASSIGN(ip_listen_mode); if (OB_SUCC(ret)) { obsys::CRLockGuard guard(proxy_config.rwlock_); @@ -251,6 +262,9 @@ int ObMysqlConfigParams::assign_config(const ObProxyConfig &proxy_config) if(OB_UNLIKELY(0 != local_bound_ip_.load(proxy_config.local_bound_ip))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to assign ip value", K(proxy_config.local_bound_ip.str()), K(ret)); + } else if (OB_UNLIKELY(0 != local_bound_ipv6_ip_.load(proxy_config.local_bound_ipv6_ip))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to assign ipv6 value", K(proxy_config.local_bound_ipv6_ip.str()), K(ret)); } } @@ -304,7 +318,7 @@ DEF_TO_STRING(ObMysqlConfigParams) J_COMMA(); J_KV(K_(short_async_task_timeout), K_(short_async_task_timeout), K_(min_congested_connect_timeout), K_(tenant_location_valid_time), K_(local_bound_ip), K_(listen_port), K_(stack_size), K_(work_thread_num), - K_(task_thread_num), K_(block_thread_num), K_(grpc_thread_num), K_(automatic_match_work_thread), + K_(task_thread_num), K_(block_thread_num), K_(grpc_thread_num), K_(shard_scan_thread_num), K_(automatic_match_work_thread), K_(enable_congestion), K_(enable_bad_route_reject), K_(test_server_addr), K_(sqlaudit_mem_limited), K_(max_connections), K_(client_max_connections), K_(enable_client_connection_lru_disconnect), K_(connect_observer_max_retries), @@ -316,11 +330,12 @@ DEF_TO_STRING(ObMysqlConfigParams) K_(slow_transaction_time_threshold), K_(slow_proxy_process_time_threshold), K_(query_digest_time_threshold), K_(slow_query_time_threshold), K_(proxy_service_mode), K_(server_routing_mode), K_(proxy_id), K_(proxy_idc_name), - K_(client_max_memory_size), + K_(client_max_memory_size), K_(enable_cpu_isolate), K_(default_inactivity_timeout), K_(enable_partition_table_route), K_(enable_pl_route), K_(enable_cluster_checkout), K_(enable_client_ip_checkout), K_(enable_proxy_scramble), - K_(enable_compression_protocol), K_(enable_ob_protocol_v2), K_(enable_reroute), K_(enable_index_route), - K_(enable_causal_order_read)); + K_(enable_compression_protocol), K_(enable_ob_protocol_v2), + K_(enable_reroute), K_(enable_index_route), K_(enable_causal_order_read), + K_(ip_listen_mode), K_(local_bound_ipv6_ip)); J_OBJ_END(); return pos; } diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_config_processor.h b/src/obproxy/proxy/mysqllib/ob_mysql_config_processor.h index 2b4cb07156317a8dda37b7aee2689f66fb630c50..86020f9b87189eb2503f0ca52971288f3c592cab 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_config_processor.h +++ b/src/obproxy/proxy/mysqllib/ob_mysql_config_processor.h @@ -102,6 +102,7 @@ public: CfgInt task_thread_num_; CfgInt block_thread_num_; CfgInt grpc_thread_num_; + CfgInt shard_scan_thread_num_; CfgBool automatic_match_work_thread_; CfgBool enable_congestion_; CfgBool enable_bad_route_reject_; @@ -113,6 +114,7 @@ public: CfgBool enable_reroute_; CfgBool enable_index_route_; CfgBool enable_causal_order_read_; + CfgBool enable_transaction_internal_routing_; CfgIpPortList test_server_addr_; CfgInt sqlaudit_mem_limited_; @@ -143,6 +145,10 @@ public: obutils::ObServerRoutingMode server_routing_mode_; CfgInt proxy_id_; CfgInt client_max_memory_size_; + CfgBool enable_cpu_isolate_; + CfgBool enable_primary_zone_; + CfgInt ip_listen_mode_; + CfgIp local_bound_ipv6_ip_; char proxy_idc_name_[OB_PROXY_MAX_IDC_NAME_LENGTH + 1]; char proxy_primary_zone_name_[common::MAX_ZONE_LENGTH + 1]; }; diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_ob20_packet_write.cpp b/src/obproxy/proxy/mysqllib/ob_mysql_ob20_packet_write.cpp index fcc02b5d35df14c3f3e9d999e16a6a2d4313369f..ad197d8b4130123b53049acf548255598c28a32d 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_ob20_packet_write.cpp +++ b/src/obproxy/proxy/mysqllib/ob_mysql_ob20_packet_write.cpp @@ -15,6 +15,8 @@ #include "proxy/mysqllib/ob_mysql_common_define.h" #include "proxy/mysqllib/ob_mysql_ob20_packet_write.h" #include "proxy/mysqllib/ob_2_0_protocol_utils.h" +#include "obproxy/packet/ob_mysql_packet_writer.h" +#include "obproxy/proxy/mysqllib/ob_mysql_analyzer_utils.h" using namespace oceanbase::obproxy::event; using namespace oceanbase::common; @@ -26,68 +28,138 @@ namespace obproxy { namespace proxy { -// only compress ObMysqlRawPacket, + int ObMysqlOB20PacketWriter::write_compressed_packet(ObMIOBuffer &mio_buf, const ObMySQLRawPacket &packet, - uint8_t &compressed_seq, - const uint32_t request_id, - const uint32_t sessid) + const Ob20ProtocolHeaderParam &ob20_head_param, + const common::ObIArray *extra_info) { int ret = OB_SUCCESS; - char meta_buf[MYSQL_NET_META_LENGTH]; + + ObIOBufferReader *tmp_mio_reader = NULL; + ObMIOBuffer *tmp_mio_buf = NULL; + const int64_t packet_len = packet.get_clen() + MYSQL_NET_META_LENGTH; + if (OB_ISNULL(tmp_mio_buf = new_miobuffer(packet_len))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to new miobuffer", K(ret)); + } else if (OB_ISNULL(tmp_mio_reader = tmp_mio_buf->alloc_reader())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to alloc reader", K(ret)); + } else if (OB_FAIL(packet::ObMysqlPacketWriter::write_raw_packet(*tmp_mio_buf, packet))) { + LOG_WARN("fail to write raw packet", K(ret)); + } else if (OB_FAIL(ObProto20Utils::consume_and_compress_data(tmp_mio_reader, &mio_buf, + tmp_mio_reader->read_avail(), ob20_head_param, extra_info))) { + LOG_WARN("fail to consume and compress data", K(ret)); + } else { + // nothing + } + + if (OB_LIKELY(NULL != tmp_mio_buf)) { + free_miobuffer(tmp_mio_buf); + tmp_mio_buf = NULL; + tmp_mio_reader = NULL; + } + + return ret; +} + +int ObMysqlOB20PacketWriter::write_compressed_packet(ObMIOBuffer &mio_buf, + const obmysql::ObMySQLPacket &packet, + const Ob20ProtocolHeaderParam &ob20_head_param) +{ + int ret = OB_SUCCESS; + + const int64_t serialize_size = packet.get_serialize_size(); + const int64_t packet_len = serialize_size + MYSQL_NET_HEADER_LENGTH; + int64_t tmp_len = packet_len; int64_t pos = 0; - int64_t meta_buf_len = MYSQL_NET_META_LENGTH; - // 1. encode mysql packet meta(header + cmd) - if (OB_FAIL(packet.encode_packet_meta(meta_buf, meta_buf_len, pos))) { - LOG_WARN("fail to encode packet meta", K(pos), K(packet), K(meta_buf_len), K(ret)); + ObMIOBuffer *tmp_mio_buf = NULL; + ObIOBufferReader *tmp_mio_reader = NULL; + + if (OB_ISNULL(tmp_mio_buf = new_miobuffer(packet_len))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to new miobuffer", K(ret), K(packet_len)); + } else if (OB_ISNULL(tmp_mio_reader = tmp_mio_buf->alloc_reader())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to alloc reader", K(ret)); + } else if (ObMySQLPacket::encode_packet(tmp_mio_buf->end(), tmp_len, pos, packet)) { + LOG_WARN("fail to encode packet", K(ret), K(tmp_len), K(pos), K(pos), K(packet_len), K(packet)); + } else if (OB_FAIL(tmp_mio_buf->fill(pos))) { + // move start pointer + LOG_WARN("fail to fill iobuffer", K(ret), K(pos)); + } else if (ObProto20Utils::consume_and_compress_data(tmp_mio_reader, &mio_buf, + tmp_mio_reader->read_avail(), ob20_head_param)) { + LOG_WARN("fail to consume and compress data", K(ret)); + } else { + // nothing + } + + // free mio buf + if (OB_LIKELY(tmp_mio_buf != NULL)) { + free_miobuffer(tmp_mio_buf); + tmp_mio_buf = NULL; + tmp_mio_reader = NULL; + } + + return ret; +} + +int ObMysqlOB20PacketWriter::write_raw_packet(event::ObMIOBuffer &mio_buf, const common::ObString &packet_str, + const Ob20ProtocolHeaderParam &ob20_head_param) +{ + int ret = OB_SUCCESS; + + // write to buffer directly + const char *buf = packet_str.ptr(); + const int64_t buf_len = packet_str.length(); + if (OB_UNLIKELY(buf == NULL) || OB_UNLIKELY(buf_len <= 0)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument before write raw packet", K(ret), K(buf), K(buf_len)); } else { - ObIOBufferReader *tmp_reader = NULL; ObMIOBuffer *tmp_mio_buf = NULL; - const char *buf = packet.get_cdata(); - int64_t buf_len = packet.get_clen(); + ObIOBufferReader *tmp_mio_reader = NULL; int64_t written_len = 0; - const bool is_last_packet = true; - const bool is_need_reroute = false; - if (OB_ISNULL(tmp_mio_buf = new_empty_miobuffer())) { + if (OB_ISNULL(tmp_mio_buf = new_miobuffer(buf_len))) { ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to new miobuffer", K(ret)); - } else if (OB_ISNULL(tmp_reader = tmp_mio_buf->alloc_reader())) { + LOG_WARN("fail to new miobuffer", K(ret), K(buf_len)); + } else if (OB_ISNULL(tmp_mio_reader = tmp_mio_buf->alloc_reader())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to alloc reader", K(ret)); - // 2. write the meta buf, the first part of mysql packet - } else if (OB_FAIL(tmp_mio_buf->write(meta_buf, meta_buf_len, written_len))) { - LOG_WARN("fail to write", K(meta_buf_len), K(ret)); - } else if (OB_UNLIKELY(written_len != MYSQL_NET_META_LENGTH)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("written_len dismatch", K(written_len), K(MYSQL_NET_META_LENGTH), K(ret)); - // 3. write the request buf, the second part of mysql packet } else if (OB_FAIL(tmp_mio_buf->write(buf, buf_len, written_len))) { LOG_WARN("fail to write", K(buf_len), K(ret)); } else if (OB_UNLIKELY(written_len != buf_len)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("written_len dismatch", K(written_len), K(buf_len), K(ret)); - // 4. make up compress packet - } else if (OB_FAIL(ObProto20Utils::consume_and_compress_data(tmp_reader, - &mio_buf, tmp_reader->read_avail(), compressed_seq, compressed_seq, - request_id, sessid, is_last_packet, is_need_reroute))) { - LOG_WARN("fail to consume_and_compress_data", K(ret)); + } else if (OB_FAIL(ObProto20Utils::consume_and_compress_data(tmp_mio_reader, &mio_buf, + tmp_mio_reader->read_avail(), ob20_head_param))) { + LOG_WARN("fail to consume and compress data", K(ret)); + } else { + LOG_DEBUG("succ to write raw packet in ob20 format"); } - if (NULL != tmp_mio_buf) { + if (OB_LIKELY(NULL != tmp_mio_buf)) { free_miobuffer(tmp_mio_buf); tmp_mio_buf = NULL; - tmp_reader = NULL; + tmp_mio_reader = NULL; } } - + return ret; } -int ObMysqlOB20PacketWriter::write_request_packet(ObMIOBuffer &mio_buf, const ObMySQLCmd cmd, +int ObMysqlOB20PacketWriter::write_request_packet(ObMIOBuffer &mio_buf, + const ObMySQLCmd cmd, const common::ObString &sql_str, - uint8_t &compressed_seq, - const uint32_t request_id, - const uint32_t sessid) + const uint32_t conn_id, + const uint32_t req_id, + const uint8_t compressed_seq, + const uint8_t pkt_seq, + bool is_last_packet, + bool is_weak_read, + bool is_need_reroute, + bool is_new_extra_info, + bool is_trans_internal_routing, + const common::ObIArray *extra_info) { int ret = OB_SUCCESS; if (OB_UNLIKELY(sql_str.empty())) { @@ -98,15 +170,51 @@ int ObMysqlOB20PacketWriter::write_request_packet(ObMIOBuffer &mio_buf, const Ob LOG_WARN("we cannot support packet which is larger than 16MB", K(sql_str), K(MYSQL_PACKET_MAX_LENGTH), K(ret)); } else { + Ob20ProtocolHeaderParam ob20_head_param(conn_id, req_id, compressed_seq, pkt_seq, is_last_packet, + is_weak_read, is_need_reroute, + is_new_extra_info, is_trans_internal_routing); ObMySQLRawPacket com_pkt(cmd); com_pkt.set_content(sql_str.ptr(), static_cast(sql_str.length())); - if (OB_FAIL(ObMysqlOB20PacketWriter::write_compressed_packet(mio_buf, com_pkt, compressed_seq, request_id, sessid))) { + if (OB_FAIL(ObMysqlOB20PacketWriter::write_compressed_packet(mio_buf, com_pkt, ob20_head_param, extra_info))) { LOG_WARN("write packet failed", K(sql_str), K(ret)); } } return ret; } +int ObMysqlOB20PacketWriter::write_packet(ObMIOBuffer &mio_buf, + const char *buf, + const int64_t buf_len, + const Ob20ProtocolHeaderParam &ob20_head_param) +{ + int ret = OB_SUCCESS; + + obmysql::ObMySQLPacket packet; + packet.set_content(buf, static_cast(buf_len)); + ret = write_packet(mio_buf, packet, ob20_head_param); + + return ret; +} + +int ObMysqlOB20PacketWriter::write_packet(ObMIOBuffer &mio_buf, + const obmysql::ObMySQLPacket &packet, + const Ob20ProtocolHeaderParam &ob20_head_param) +{ + int ret = OB_SUCCESS; + + int64_t serialize_size = packet.get_serialize_size(); + if (OB_UNLIKELY(serialize_size < 0)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid serialize size", K(ret), K(serialize_size)); + } else if (OB_FAIL(write_compressed_packet(mio_buf, packet, ob20_head_param))) { + LOG_WARN("fail to write compressed packet", K(ret), K(serialize_size)); + } else { + // nothing + } + + return ret; +} + } // end of namespace proxy } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_ob20_packet_write.h b/src/obproxy/proxy/mysqllib/ob_mysql_ob20_packet_write.h index 9034ffa43cceca46f55eef27010459305dee582e..f9ab966880084a563f8d22b72585b45687c26f55 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_ob20_packet_write.h +++ b/src/obproxy/proxy/mysqllib/ob_mysql_ob20_packet_write.h @@ -16,6 +16,7 @@ #include "lib/string/ob_sql_string.h" #include "iocore/eventsystem/ob_io_buffer.h" #include "rpc/obmysql/ob_mysql_packet.h" +#include "obproxy/proxy/mysqllib/ob_2_0_protocol_utils.h" namespace oceanbase { @@ -23,6 +24,7 @@ namespace obproxy { namespace proxy { +class Ob20ProtocolHeaderParam; class ObMysqlOB20PacketWriter { @@ -31,18 +33,26 @@ public: ~ObMysqlOB20PacketWriter() {} // write request packet to mio buffer - static int write_request_packet(event::ObMIOBuffer &mio_buf, - const obmysql::ObMySQLCmd cmd, - const common::ObString &sql_str, - uint8_t &compressed_seq, - const uint32_t request_id, - const uint32_t sessid); + static int write_raw_packet(event::ObMIOBuffer &mio_buf, const common::ObString &packet_str, + const Ob20ProtocolHeaderParam &ob20_head_param); + static int write_request_packet(event::ObMIOBuffer &mio_buf, const obmysql::ObMySQLCmd cmd, + const common::ObString &sql_str, const uint32_t conn_id, + const uint32_t req_id, const uint8_t compressed_seq, + const uint8_t pkt_seq, bool is_last_packet, bool is_weak_read, + bool is_need_reroute, bool is_new_extra_info, bool is_trans_internal_routing, + const common::ObIArray *extra_info = NULL); + static int write_packet(event::ObMIOBuffer &mio_buf, const char *buf, const int64_t buf_len, + const Ob20ProtocolHeaderParam &ob20_head_param); + static int write_packet(event::ObMIOBuffer &mio_buf, const obmysql::ObMySQLPacket &packet, + const Ob20ProtocolHeaderParam &ob20_head_param); + private: - static int write_compressed_packet(event::ObMIOBuffer &mio_buf, - const obmysql::ObMySQLRawPacket &packet, - uint8_t &compressed_seq, - const uint32_t request_id, - const uint32_t sessid); + static int write_compressed_packet(event::ObMIOBuffer &mio_buf, const obmysql::ObMySQLRawPacket &packet, + const Ob20ProtocolHeaderParam &ob20_head_param, + const common::ObIArray *extra_info = NULL); + static int write_compressed_packet(event::ObMIOBuffer &mio_buf, const obmysql::ObMySQLPacket &packet, + const Ob20ProtocolHeaderParam &ob20_head_param); + DISALLOW_COPY_AND_ASSIGN(ObMysqlOB20PacketWriter); }; } // end of namespace proxy diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_packet_rewriter.cpp b/src/obproxy/proxy/mysqllib/ob_mysql_packet_rewriter.cpp index afaa78c345b7fe7c276b1783a7c4b7f8383c16af..97233be2345eef42ac79d089ff1dcf785be2cdda 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_packet_rewriter.cpp +++ b/src/obproxy/proxy/mysqllib/ob_mysql_packet_rewriter.cpp @@ -15,6 +15,7 @@ #include "proxy/mysqllib/ob_mysql_response.h" #include "proxy/mysqllib/ob_proxy_auth_parser.h" #include "proxy/mysqllib/ob_session_field_mgr.h" +#include "proxy/mysqllib/ob_proxy_session_info.h" #include "lib/encrypt/ob_encrypted_helper.h" using namespace oceanbase::common; @@ -131,7 +132,7 @@ int ObHandshakeResponseParam::write_client_addr_buf(const common::ObAddr &addr) int ret = OB_SUCCESS; if (OB_UNLIKELY(!addr.is_valid())) { //do not write - } else if (OB_UNLIKELY(!addr.ip_to_string(client_ip_buf_, OB_MAX_IP_BUF_LEN))) { + } else if (OB_UNLIKELY(!addr.ip_to_string(client_ip_buf_, MAX_IP_ADDR_LENGTH))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to ip_to_string", K(addr), K(ret)); } @@ -141,9 +142,13 @@ int ObHandshakeResponseParam::write_client_addr_buf(const common::ObAddr &addr) int ObMysqlPacketRewriter::rewrite_ok_packet(const OMPKOK &src_ok, const ObMySQLCapabilityFlags &des_cap, OMPKOK &des_ok, - const bool need_save_sys_var) + ObClientSessionInfo &client_info, + char *cap_buf, + const int64_t cap_buf_len, + const bool is_auth_request) { int ret = OB_SUCCESS; + des_ok.set_affected_rows(src_ok.get_affected_rows()); des_ok.set_last_insert_id(src_ok.get_last_insert_id()); des_ok.set_server_status(src_ok.get_server_status()); @@ -154,21 +159,43 @@ int ObMysqlPacketRewriter::rewrite_ok_packet(const OMPKOK &src_ok, // tmp_flags.cap_flags_.OB_CLIENT_SESSION_TRACK = 0; // tmp_flags.cap_flags_.OB_CLIENT_DEPRECATE_EOF = 0; - if (need_save_sys_var) { + if (client_info.is_oracle_mode()) { des_ok.set_state_changed(true); // tmp_flags.cap_flags_.OB_CLIENT_SESSION_TRACK = 1; const common::ObIArray &system_vars = src_ok.get_system_vars(); - for (int64_t i = 0; i < system_vars.count(); ++i) { + for (int64_t i = 0; i < system_vars.count() && OB_SUCC(ret); ++i) { if (ObSessionFieldMgr::is_nls_date_timestamp_format_variable(system_vars.at(i).key_)) { - des_ok.add_system_var(system_vars.at(i)); + if (OB_FAIL(des_ok.add_system_var(system_vars.at(i)))) { + LOG_WARN("fail to add system var", K(ret), "key:", system_vars.at(i).key_); + } } } } + des_ok.set_capability(tmp_flags); + // cap.OB_CLIENT_SESSION_TRACK is already set in orig_cap + if (OB_SUCC(ret) && client_info.is_client_support_ob20_protocol() && is_auth_request) { + des_ok.set_state_changed(true); + uint64_t cap = client_info.get_client_ob_capability(); + int64_t pos = 0; + + if (OB_FAIL(databuff_printf(cap_buf, cap_buf_len, pos, "%lu", cap))) { + LOG_WARN("fail to databuff printf", K(ret), K(pos)); + } else { + ObStringKV str_kv; + str_kv.key_.assign_ptr(sql::OB_SV_CAPABILITY_FLAG, static_cast(STRLEN(sql::OB_SV_CAPABILITY_FLAG))); + str_kv.value_.assign_ptr(cap_buf, static_cast(STRLEN(cap_buf))); + if (OB_FAIL(des_ok.add_system_var(str_kv))) { + LOG_WARN("fail to add system var while rewrite ok packet", K(ret)); + } else { + LOG_DEBUG("succ to add system var in ok packet back to client", K(str_kv), K(cap)); + } + } + } + return ret; }; - int ObMysqlPacketRewriter::add_connect_attr(const char *key, const char *value, OMPKHandshakeResponse &tg_hsr) { @@ -212,19 +239,41 @@ int ObMysqlPacketRewriter::rewrite_handshake_response_packet( } // find client_ip - ObStringKV string_kv; - for (int64_t i = 0; OB_SUCC(ret) && i < tg_hsr.get_connect_attrs().count(); ++i) { - string_kv = tg_hsr.get_connect_attrs().at(i); - if (0 == string_kv.key_.case_compare(OB_MYSQL_CLIENT_IP)) { - if (!string_kv.value_.empty()) { - snprintf(param.client_ip_buf_, ObHandshakeResponseParam::OB_MAX_IP_BUF_LEN, "%.*s", string_kv.value_.length(), string_kv.value_.ptr()); + if (RUN_MODE_PROXY == g_run_mode && param.enable_client_ip_checkout_) { + ObStringKV string_kv; + for (int64_t i = 0; OB_SUCC(ret) && i < tg_hsr.get_connect_attrs().count(); ++i) { + string_kv = tg_hsr.get_connect_attrs().at(i); + if (0 == string_kv.key_.case_compare(OB_MYSQL_CLIENT_IP)) { + if (!string_kv.value_.empty()) { + snprintf(param.client_ip_buf_, MAX_IP_ADDR_LENGTH, "%.*s", string_kv.value_.length(), string_kv.value_.ptr()); + } + break; } - break; } } // reset before add tg_hsr.reset_connect_attr(); + // add transparent transit conn attrs & find client_ip + OMPKHandshakeResponse &orig_hsr = orig_auth_req.get_hsr_result().response_; + bool find_client_ip = false; + for (int64_t i = 0; OB_SUCC(ret) && i < orig_hsr.get_connect_attrs().count(); ++i) { + ObStringKV kv; + // transit conn attrs OB_MYSQL_OB_CLIENT + if (OB_FAIL(orig_hsr.get_connect_attrs().at(i, kv))) { + LOG_WARN("fail access handshake response connect attrs", K(i), K(ret)); + } else if (kv.key_.prefix_match(OB_MYSQL_OB_CLIENT)) { + if (OB_FAIL(tg_hsr.get_connect_attrs().push_back(kv))) { + LOG_WARN("fail push back transparent transmit connect attrs", K(kv), K(ret)); + } else { /* succ */ } + } else if (!find_client_ip + && param.enable_client_ip_checkout_ + && 0 == kv.key_.case_compare(OB_MYSQL_CLIENT_IP) + && !kv.value_.empty()){ + snprintf(param.client_ip_buf_, MAX_IP_ADDR_LENGTH, "%.*s", kv.value_.length(), kv.value_.ptr()); + find_client_ip = true; + } else { /* do nothing */ } + } // 4. add obproxy specified connect attrs: // a. proxy_mode // b. connection id @@ -252,9 +301,7 @@ int ObMysqlPacketRewriter::rewrite_handshake_response_packet( LOG_WARN("fail to add client ip", K(param.client_ip_buf_), K(ret)); } else if (OB_FAIL(add_connect_attr(OB_MYSQL_PROXY_VERSION, param.proxy_version_buf_, tg_hsr))) { LOG_WARN("fail to add proxy version", K(param.proxy_version_buf_), K(ret)); - } else { - //do nothing - } + } else { /* succ */ } return ret; diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_packet_rewriter.h b/src/obproxy/proxy/mysqllib/ob_mysql_packet_rewriter.h index 8bce5d4635bbd891d4ae65a02461a929c2514f02..238ecbcf942225bfb0ea2e4b307a340a7796139f 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_packet_rewriter.h +++ b/src/obproxy/proxy/mysqllib/ob_mysql_packet_rewriter.h @@ -38,6 +38,9 @@ class ObIOBufferReader; namespace proxy { class ObMysqlAuthRequest; +class ObClientSessionInfo; + +static const int64_t OB_MAX_UINT64_BUF_LEN = 22; // string length of max uint64_t(2**64 - 1) struct ObHandshakeResponseParam { @@ -60,15 +63,14 @@ public: int write_cluster_id_buf(const int64_t cluster_id); static const int64_t OB_MAX_UINT32_BUF_LEN = 11; // string length of max uint32_t(2**32 - 1) - static const int64_t OB_MAX_UINT64_BUF_LEN = 22; // string length of max uint64_t(2**64 - 1) static const int64_t OB_MAX_VERSION_BUF_LEN = 22; // string length of (xxx.xxx.xxx.xxx.xxx) - static const int64_t OB_MAX_IP_BUF_LEN = 20; // string length of (xxx.xxx.xxx.xxx.xxx) bool is_saved_login_; bool use_compress_; bool use_ob_protocol_v2_; int64_t cluster_id_; bool use_ssl_; + bool enable_client_ip_checkout_; common::ObString cluster_name_; common::ObString proxy_scramble_; @@ -78,7 +80,7 @@ public: char global_vars_version_buf_[OB_MAX_UINT64_BUF_LEN]; char cap_buf_[OB_MAX_UINT64_BUF_LEN]; char proxy_scramble_buf_[obmysql::OMPKHandshake::SCRAMBLE_TOTAL_SIZE]; - char client_ip_buf_[OB_MAX_IP_BUF_LEN]; + char client_ip_buf_[MAX_IP_ADDR_LENGTH]; char cluster_id_buf_[OB_MAX_UINT64_BUF_LEN]; private: @@ -91,7 +93,10 @@ public: static int rewrite_ok_packet(const obmysql::OMPKOK &src_ok, const obmysql::ObMySQLCapabilityFlags &des_cap, obmysql::OMPKOK &des_ok, - const bool need_save_sys_var); + ObClientSessionInfo &client_info, + char *cap_buf, + const int64_t cap_buf_max_len, + const bool is_auth_request); static int rewrite_handshake_response_packet(ObMysqlAuthRequest &orig_auth_req, ObHandshakeResponseParam ¶m, diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_request_analyzer.cpp b/src/obproxy/proxy/mysqllib/ob_mysql_request_analyzer.cpp index 8c4fbf79d11da751c4bd11a7349ce572c6d1790a..b95aa448edd8ef4e207463ac2f7970f3eca41aed 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_request_analyzer.cpp +++ b/src/obproxy/proxy/mysqllib/ob_mysql_request_analyzer.cpp @@ -79,7 +79,8 @@ void ObMysqlRequestAnalyzer::analyze_request(const ObRequestAnalyzeCtx &ctx, ObProxyMysqlRequest &client_request, ObMySQLCmd &sql_cmd, ObMysqlAnalyzeStatus &status, - const bool is_oracle_mode /* false*/) + const bool is_oracle_mode /* false */, + const bool is_client_support_ob20_protocol /* false */) { int ret = OB_SUCCESS; if (OB_ISNULL(ctx.reader_)) { @@ -102,6 +103,9 @@ void ObMysqlRequestAnalyzer::analyze_request(const ObRequestAnalyzeCtx &ctx, // 2. verify request's legality, just print WARN int64_t avail_bytes = ctx.reader_->read_avail(); if (avail_bytes >= MYSQL_NET_META_LENGTH) { + if (is_client_support_ob20_protocol) { + avail_bytes -= OB20_PROTOCOL_TAILER_LENGTH; // avoid to print too much log in ob2.0 protocol with client + } if (avail_bytes > result.meta_.pkt_len_) { LOG_WARN("recevied more than one mysql packet at once, it is unexpected so far", "first packet len(include packet header)", result.meta_.pkt_len_, @@ -159,7 +163,8 @@ void ObMysqlRequestAnalyzer::analyze_request(const ObRequestAnalyzeCtx &ctx, && !client_request.is_sharding_user() && !client_request.is_proxysys_user() && !ctx.using_ldg_ - && OB_MYSQL_COM_STMT_SEND_LONG_DATA != sql_cmd) { + && OB_MYSQL_COM_STMT_SEND_LONG_DATA != sql_cmd + && OB_MYSQL_COM_CHANGE_USER != sql_cmd) { if (OB_FAIL(do_analyze_request(ctx, sql_cmd, auth_request, client_request, is_oracle_mode))) { status = ANALYZE_ERROR; LOG_WARN("fail to dispatch mysql cmd", "analyze status", @@ -184,8 +189,8 @@ int ObMysqlRequestAnalyzer::get_payload_length(const char *buffer) ret = OB_INVALID_ARGUMENT; LOG_WARN("buffer is NULL", K(ret)); } else { - payload_length = ob_uint3korr(buffer); - packet_seq_ = ob_uint1korr(buffer + MYSQL_PAYLOAD_LENGTH_LENGTH); + payload_length = uint3korr(buffer); + packet_seq_ = uint1korr(buffer + MYSQL_PAYLOAD_LENGTH_LENGTH); if (MYSQL_PACKET_MAX_LENGTH == payload_length) { is_last_request_packet_ = false; } else { @@ -367,6 +372,7 @@ void ObMysqlRequestAnalyzer::extract_fileds(const ObExprParseResult& result, ObP void ObMysqlRequestAnalyzer::extract_fileds(const ObExprParseResult& result, SqlFieldResult &sql_result) { + int ret = OB_SUCCESS; int64_t total_num = result.all_relation_info_.relation_num_; ObProxyRelationExpr* relation_expr = NULL; ObString name_str; @@ -394,34 +400,43 @@ void ObMysqlRequestAnalyzer::extract_fileds(const ObExprParseResult& result, Sql } if (relation_expr->right_value_ != NULL) { ObProxyTokenNode *token = relation_expr->right_value_->head_; - SqlField field; - field.reset(); - field.column_name_.set(name_str); - SqlColumnValue column_value; - while (NULL != token) { - switch(token->type_) { - case TOKEN_INT_VAL: - column_value.value_type_ = TOKEN_INT_VAL; - column_value.column_int_value_ = token->int_value_; - column_value.column_value_.set_integer(token->int_value_); - field.column_values_.push_back(column_value); - break; - case TOKEN_STR_VAL: - column_value.value_type_ = TOKEN_STR_VAL; - value_str.assign_ptr(token->str_value_.str_, - token->str_value_.str_len_); - column_value.column_value_.set(value_str); - field.column_values_.push_back(column_value); - break; - default: - LOG_DEBUG("invalid token type", "token type", get_obproxy_token_type(token->type_)); - break; + SqlField* field = NULL; + if (OB_FAIL(SqlField::alloc_sql_field(field))) { + LOG_WARN("fail to alloc sql field", K(ret)); + } else { + field->column_name_.set_value(name_str.length(), name_str.ptr()); + SqlColumnValue column_value; + while (OB_SUCC(ret) && NULL != token) { + switch(token->type_) { + case TOKEN_INT_VAL: + column_value.value_type_ = TOKEN_INT_VAL; + column_value.column_int_value_ = token->int_value_; + column_value.column_value_.set_integer(token->int_value_); + if (OB_FAIL(field->column_values_.push_back(column_value))) { + LOG_WARN("fail to push column_value", K(ret)); + } + break; + case TOKEN_STR_VAL: + column_value.value_type_ = TOKEN_STR_VAL; + value_str.assign_ptr(token->str_value_.str_, + token->str_value_.str_len_); + column_value.column_value_.set_value(value_str); + if (OB_FAIL(field->column_values_.push_back(column_value))) { + LOG_WARN("fail to push back column_value", K(ret)); + } + break; + default: + LOG_DEBUG("invalid token type", "token type", get_obproxy_token_type(token->type_)); + break; + } + token = token->next_; + } + if (OB_SUCC(ret) && field->is_valid() && OB_SUCCESS == sql_result.fields_.push_back(field)) { + ++sql_result.field_num_; + } else { + field->reset(); + field = NULL; } - token = token->next_; - } - if (field.is_valid()) { - sql_result.fields_.push_back(field); - ++sql_result.field_num_; } } else { LOG_WARN("right value is null"); @@ -463,7 +478,6 @@ int ObMysqlRequestAnalyzer::parse_sql_fileds(ObProxyMysqlRequest &client_request ObExprParser expr_parser(*allocator, parse_mode); ObString sql = client_request.get_sql(); expr_result.part_key_info_.key_num_ = 0; - expr_result.target_mask_ = 0; ObString expr_sql = ObProxyMysqlRequest::get_expr_sql(sql, sql_parse_result.get_parsed_length()); if (SELECT_STMT_PARSE_MODE == parse_mode) { const char *expr_sql_str = expr_sql.ptr(); @@ -538,6 +552,18 @@ inline int ObMysqlRequestAnalyzer::do_analyze_request( LOG_WARN("fail to parse sql", K(sql), K(ret)); } else if (OB_FAIL(handle_internal_cmd(client_request))) { LOG_WARN("fail to handle internal cmd", K(sql), K(ret)); + } else if (sql_parse_result.is_dual_request() + && OB_MYSQL_COM_STMT_PREPARE_EXECUTE == sql_cmd + && get_global_proxy_config().enable_xa_route) { + // specically check if sql is xa start + // from obci only one format: select DBMS_XA.XA_START(?, ?) from dual + ObString tmp = sql; + tmp.split_on(' '); + ObString dbms_xa_start = tmp.split_on(' ').split_on('(').trim(); + if (0 == dbms_xa_start.case_compare("DBMS_XA.XA_START")) { + sql_parse_result.set_xa_start_stmt(true); + LOG_DEBUG("[ObMysqlRequestAnalyzer::do_analyze_request] receive xa start req in prepare execute packet"); + } } } } else { @@ -559,6 +585,7 @@ inline int ObMysqlRequestAnalyzer::do_analyze_request( } case OB_MYSQL_COM_STMT_FETCH: case OB_MYSQL_COM_STMT_CLOSE: + case OB_MYSQL_COM_STMT_RESET: case OB_MYSQL_COM_STMT_EXECUTE: case OB_MYSQL_COM_STMT_SEND_LONG_DATA: case OB_MYSQL_COM_STMT_SEND_PIECE_DATA: @@ -569,21 +596,8 @@ inline int ObMysqlRequestAnalyzer::do_analyze_request( } break; } - case OB_MYSQL_COM_PING: { - // proxy handle mysql_ping() by itself - int64_t len = 0; - if (NULL == ctx.reader_) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid buffer reader", K_(ctx.reader), K(ret)); - } else if (MYSQL_NET_META_LENGTH != (len = ctx.reader_->read_avail())) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("buffer reader length is not equal to MYSQL_NET_META_LENGTH", K(len)); - ObMysqlPacketReader reader; - reader.print_reader(*ctx.reader_); - } - break; - } case OB_MYSQL_COM_CHANGE_USER: + case OB_MYSQL_COM_RESET_CONNECTION: case OB_MYSQL_COM_INIT_DB: { if (OB_FAIL(client_request.add_request(ctx.reader_, ctx.request_buffer_length_))) { LOG_WARN("fail to add com request", K(ret)); @@ -615,6 +629,7 @@ inline int ObMysqlRequestAnalyzer::do_analyze_request( break; } } + case OB_MYSQL_COM_PING: case OB_MYSQL_COM_HANDSHAKE: case OB_MYSQL_COM_QUIT: { break; @@ -727,7 +742,8 @@ int ObMysqlRequestAnalyzer::handle_internal_cmd(ObProxyMysqlRequest &client_requ parse_result.set_err_stmt_type(OBPROXY_T_ERR_NOT_SUPPORTED); } is_internal_cmd = true; - } else if (client_request.is_sharding_user() && parse_result.is_show_topology_stmt()) { + } else if (client_request.is_sharding_user() && (parse_result.is_show_topology_stmt() + || parse_result.is_show_elastic_id_stmt())) { is_internal_cmd = true; } @@ -794,6 +810,16 @@ int ObMysqlRequestAnalyzer::analyze_execute_header(const int64_t param_num, int ObMysqlRequestAnalyzer::parse_param_type(const int64_t param_num, ObIArray ¶m_types, const char *&buf, int64_t &data_len) +{ + ObSEArray type_infos; + return parse_param_type(param_num, param_types, type_infos, buf, data_len); +} + +// The default data of this method is complete and can only come in once +int ObMysqlRequestAnalyzer::parse_param_type(const int64_t param_num, + ObIArray ¶m_types, + ObIArray &type_infos, + const char *&buf, int64_t &data_len) { int ret = OB_SUCCESS; @@ -807,10 +833,11 @@ int ObMysqlRequestAnalyzer::parse_param_type(const int64_t param_num, LOG_WARN("fail to get int1", K(data_len), K(ret)); } else if (OB_FAIL(param_types.push_back(static_cast(type)))) { LOG_WARN("fail to push back param type", K(type), K(ret)); + } else if (OB_FAIL(type_infos.push_back(TypeInfo()))) { + LOG_WARN("fail to push back empty type info", K(ret)); } else if (OB_MYSQL_TYPE_COMPLEX == type) { - TypeInfo type_name_info; + TypeInfo &type_name_info = type_infos.at(i); uint8_t elem_type = 0; - // skip all complex type bytes if (OB_FAIL(decode_type_info(buf, data_len, type_name_info))) { LOG_WARN("failed to decode type info", K(ret)); } else if (type_name_info.type_name_.empty()) { @@ -941,7 +968,7 @@ int ObMysqlRequestAnalyzer::do_analyze_execute_param(const char *buf, } else if (OB_FAIL(parse_param_value(allocator, param_buf, data_len, type, charset, target_obj))) { LOG_DEBUG("fail to parse param value", K(i), K(ret)); } else { - LOG_DEBUG("succ to parse execute param", K(ob_type), K(i)); + LOG_DEBUG("succ to parse execute param", K(ob_type), K(type), K(i)); } } } // end for @@ -1041,9 +1068,8 @@ int ObMysqlRequestAnalyzer::analyze_send_long_data_param(ObProxyMysqlRequest &cl ret = OB_INVALID_ARGUMENT; LOG_WARN("fail to get param name from prepare result", K(ret), K(param_id), K(sql_result.field_num_)); } else { - obutils::SqlField &field = sql_result.fields_.at(param_id); - param_name = field.column_name_.string_; - + obutils::SqlField* field = sql_result.fields_.at(param_id); + param_name = field->column_name_.config_string_; ObProxyPartKeyInfo &key_info = part_info->get_part_key_info(); for (uint64_t i = 0; i < key_info.key_num_; ++i) { ObProxyPartKey &part_key = key_info.part_keys_[i]; @@ -1128,7 +1154,6 @@ int ObMysqlRequestAnalyzer::parse_param_value(ObIAllocator &allocator, ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid input value", K(data), K(ret)); } else { - ObCollationType cs_type = ObCharset::get_default_collation(charset); switch (type) { case OB_MYSQL_TYPE_TINY: { int8_t value; @@ -1204,10 +1229,14 @@ int ObMysqlRequestAnalyzer::parse_param_value(ObIAllocator &allocator, case OB_MYSQL_TYPE_STRING: case OB_MYSQL_TYPE_VARCHAR: case OB_MYSQL_TYPE_VAR_STRING: - case OB_MYSQL_TYPE_NEWDECIMAL: { + case OB_MYSQL_TYPE_NEWDECIMAL: + case OB_MYSQL_TYPE_OB_UROWID: + case OB_MYSQL_TYPE_JSON: + case OB_MYSQL_TYPE_GEOMETRY: { ObString str; ObString dst; uint64_t length = 0; + common::ObCollationType cs_type = common::ObCharset::get_default_collation(charset); if (OB_FAIL(ObMysqlPacketUtil::get_length(data, buf_len, length))) { LOG_ERROR("decode varchar param value failed", K(buf_len), K(ret)); } else if (buf_len < length) { @@ -1216,7 +1245,7 @@ int ObMysqlRequestAnalyzer::parse_param_value(ObIAllocator &allocator, } else { str.assign_ptr(data, static_cast(length)); if (OB_FAIL(ob_write_string(allocator, str, dst))) { - LOG_WARN("Failed to write str", K(ret)); + LOG_WARN("failed to ob write string", K(ret)); } else { if (OB_MYSQL_TYPE_NEWDECIMAL == type) { number::ObNumber nb; @@ -1452,8 +1481,7 @@ int ObMysqlRequestAnalyzer::decode_type_info(const char*& buf, int64_t &buf_len, } } if (OB_SUCC(ret)) { - uint64_t version = 0; - if (OB_FAIL(ObMysqlPacketUtil::get_length(buf, buf_len, version))) { + if (OB_FAIL(ObMysqlPacketUtil::get_length(buf, buf_len, type_info.version_))) { LOG_WARN("failed to get version", K(ret)); } } @@ -1624,7 +1652,7 @@ int ObMysqlRequestAnalyzer::get_int1_from_reader(event::ObIOBufferReader* reader return ret; } -int ObMysqlRequestAnalyzer::analyze_sql_id(ObProxyMysqlRequest &client_request, ObString &sql_id) +int ObMysqlRequestAnalyzer::analyze_sql_id(const ObString &sql, ObProxyMysqlRequest &client_request, ObString &sql_id) { int ret = OB_SUCCESS; ObArenaAllocator *allocator = NULL; @@ -1649,7 +1677,6 @@ int ObMysqlRequestAnalyzer::analyze_sql_id(ObProxyMysqlRequest &client_request, parse_result.is_dynamic_sql_ = false; parse_result.is_batched_multi_enabled_split_ = false; - const ObString sql = client_request.get_sql(); int64_t new_length = sql.length() + 1; // needed by sql parser, terminated with '\0' char *buf = (char *)parse_malloc(new_length, parse_result.malloc_pool_); diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_request_analyzer.h b/src/obproxy/proxy/mysqllib/ob_mysql_request_analyzer.h index a34e22039748e94e7e4423f89aa920b7e4c8fd67..58c88db544bfcdf61320fa7c555f91cdba87a0b9 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_request_analyzer.h +++ b/src/obproxy/proxy/mysqllib/ob_mysql_request_analyzer.h @@ -87,7 +87,8 @@ public: ObProxyMysqlRequest &client_request, obmysql::ObMySQLCmd &sql_cmd, ObMysqlAnalyzeStatus &status, - const bool is_oracle_mode = false); + const bool is_oracle_mode = false, + const bool is_client_support_ob20_protocol = false); static void extract_fileds(const ObExprParseResult& result, obutils::SqlFieldResult &sql_result); static int parse_sql_fileds(ObProxyMysqlRequest &client_request, common::ObCollationType connection_collation); @@ -102,6 +103,11 @@ public: common::ObIArray ¶m_types, const char *&buf, int64_t &data_len); + static int parse_param_type(const int64_t param_num, + common::ObIArray ¶m_types, + common::ObIArray &type_infos, + const char *&buf, int64_t &data_len); + static int parse_param_type_from_reader(int64_t& param_offset, const int64_t param_num, common::ObIArray ¶m_types, @@ -133,17 +139,7 @@ public: const char *&data, int64_t &buf_len, const uint8_t type, const ObCharsetType charset, ObObj ¶m); - static int analyze_sql_id(ObProxyMysqlRequest &client_request, common::ObString &sql_id); - -private: - struct TypeInfo { - TypeInfo() : relation_name_(), type_name_(), is_elem_type_(false) {} ; - common::ObString relation_name_; - common::ObString type_name_; - ObObjType elem_type_; - bool is_elem_type_; - TO_STRING_KV(K_(relation_name), K_(type_name), K_(elem_type), K_(is_elem_type)); - }; + static int analyze_sql_id(const ObString &sql, ObProxyMysqlRequest &client_request, common::ObString &sql_id); private: int get_payload_length(const char *buffer); @@ -171,11 +167,11 @@ private: const char *&data, int64_t &buf_len, ObObj ¶m); static int parse_mysql_time_value(const char *&data, int64_t &buf_len, ObObj ¶m); - static int decode_type_info(const char*& buf, int64_t &buf_len, TypeInfo &type_info); + static int decode_type_info(const char*& buf, int64_t &buf_len, obmysql::TypeInfo &type_info); static int decode_type_info_from_reader(event::ObIOBufferReader* reader, int64_t &decoded_offset, - TypeInfo &type_info); + obmysql::TypeInfo &type_info); static int get_uint1_from_reader(event::ObIOBufferReader* reader, int64_t &decoded_offset, diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_request_builder.cpp b/src/obproxy/proxy/mysqllib/ob_mysql_request_builder.cpp index c4adf34ccc3d48555a2a6deaeb0f72f4d822d132..4d28b0d4f3bb22463390861c8cffd3b8a328c36d 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_request_builder.cpp +++ b/src/obproxy/proxy/mysqllib/ob_mysql_request_builder.cpp @@ -12,6 +12,7 @@ #define USING_LOG_PREFIX PROXY #include "proxy/mysqllib/ob_mysql_request_builder.h" +#include "proxy/mysql/ob_mysql_sm.h" using namespace oceanbase::common; using namespace oceanbase::obmysql; @@ -25,7 +26,8 @@ namespace obproxy namespace proxy { -int ObMysqlRequestBuilder::build_database_sync_packet(ObMIOBuffer &mio_buf, +int ObMysqlRequestBuilder::build_database_sync_packet(ObMysqlSM *sm, + ObMIOBuffer &mio_buf, ObClientSessionInfo &client_info, ObMysqlServerSession *server_session, const ObProxyProtocol ob_proxy_protocol) @@ -54,12 +56,26 @@ int ObMysqlRequestBuilder::build_database_sync_packet(ObMIOBuffer &mio_buf, if (OB_SUCC(ret)) { uint8_t compressed_seq = 0; - if (PROTOCOL_OB20 == ob_proxy_protocol) { - ret = ObMysqlOB20PacketWriter::write_request_packet(mio_buf, cmd, db_name, compressed_seq, - server_session->get_next_server_request_id(), - server_session->get_server_sessid()); + if (ObProxyProtocol::PROTOCOL_OB20 == ob_proxy_protocol) { + ObSEArray extra_info; + ObSqlString sess_info_value; + char client_ip_buf[MAX_IP_BUFFER_LEN] = "\0"; + char server_extra_info_buf[SERVER_EXTRA_INFO_BUF_MAX_LEN] = "\0"; + if (OB_FAIL(ObProxyTraceUtils::build_related_extra_info_all(extra_info, sm, + client_ip_buf, MAX_IP_BUFFER_LEN, server_extra_info_buf, SERVER_EXTRA_INFO_BUF_MAX_LEN, + sess_info_value, true))) { + LOG_WARN("fail to build related extra info", K(ret)); + } else if (OB_FAIL(ObMysqlOB20PacketWriter::write_request_packet(mio_buf, cmd, db_name, + server_session->get_server_sessid(), + server_session->get_next_server_request_id(), + compressed_seq, compressed_seq, true, false, false, + server_info.is_new_extra_info_supported(), + sm->get_client_session()->is_trans_internal_routing(), + &extra_info))) { + LOG_WARN("fail to write request packet in ob20", K(ret)); + } else { /* nothing */ } } else { - const bool need_compress = ob_proxy_protocol == PROTOCOL_CHECKSUM ? true : false; + const bool need_compress = ob_proxy_protocol == ObProxyProtocol::PROTOCOL_CHECKSUM ? true : false; ret = ObMysqlPacketWriter::write_request_packet(mio_buf, cmd, db_name, compressed_seq, need_compress, server_info.is_checksum_on()); } @@ -68,14 +84,15 @@ int ObMysqlRequestBuilder::build_database_sync_packet(ObMIOBuffer &mio_buf, server_session->set_compressed_seq(compressed_seq); LOG_DEBUG("will sync schema", K(db_name)); } else { - LOG_WARN("fail to write buffer", K(cmd), K(db_name), K(ob_proxy_protocol), K(ret)); + LOG_WARN("fail to write packet", K(cmd), K(db_name), K(ob_proxy_protocol), K(ret)); } } } return ret; } -int ObMysqlRequestBuilder::build_all_session_vars_sync_packet(ObMIOBuffer &mio_buf, +int ObMysqlRequestBuilder::build_all_session_vars_sync_packet(ObMysqlSM *sm, + ObMIOBuffer &mio_buf, ObClientSessionInfo &client_info, ObMysqlServerSession *server_session, const ObProxyProtocol ob_proxy_protocol) @@ -88,12 +105,26 @@ int ObMysqlRequestBuilder::build_all_session_vars_sync_packet(ObMIOBuffer &mio_b LOG_WARN("fail to extract all variable reset sql", K(ret)); } else { uint8_t compressed_seq = 0; - if (PROTOCOL_OB20 == ob_proxy_protocol) { - ret = ObMysqlOB20PacketWriter::write_request_packet(mio_buf, cmd, reset_sql.string(), compressed_seq, - server_session->get_next_server_request_id(), - server_session->get_server_sessid()); + if (ObProxyProtocol::PROTOCOL_OB20 == ob_proxy_protocol) { + ObSEArray extra_info; + ObSqlString sess_info_value; + char client_ip_buf[MAX_IP_BUFFER_LEN] = "\0"; + char server_extra_info_buf[SERVER_EXTRA_INFO_BUF_MAX_LEN] = "\0"; + if (OB_FAIL(ObProxyTraceUtils::build_related_extra_info_all(extra_info, sm, + client_ip_buf, MAX_IP_BUFFER_LEN, server_extra_info_buf, SERVER_EXTRA_INFO_BUF_MAX_LEN, + sess_info_value, true))) { + LOG_WARN("fail to build related extra info", K(ret)); + } else if (OB_FAIL(ObMysqlOB20PacketWriter::write_request_packet(mio_buf, cmd, reset_sql.string(), + server_session->get_server_sessid(), + server_session->get_next_server_request_id(), + compressed_seq, compressed_seq, true, false, false, + server_info.is_new_extra_info_supported(), + sm->get_client_session()->is_trans_internal_routing(), + &extra_info))) { + LOG_WARN("fail to write request packet in ob20", K(ret)); + } else { /* nothing */ } } else { - const bool need_compress = ob_proxy_protocol == PROTOCOL_CHECKSUM ? true : false; + const bool need_compress = ob_proxy_protocol == ObProxyProtocol::PROTOCOL_CHECKSUM ? true : false; ret = ObMysqlPacketWriter::write_request_packet(mio_buf, cmd, reset_sql.string(), compressed_seq, need_compress, server_info.is_checksum_on()); } @@ -102,7 +133,7 @@ int ObMysqlRequestBuilder::build_all_session_vars_sync_packet(ObMIOBuffer &mio_b server_session->set_compressed_seq(compressed_seq); LOG_DEBUG("will sync all session variables", K(reset_sql)); } else { - LOG_WARN("fail to write buffer", K(cmd), K(reset_sql), K(ob_proxy_protocol), K(ret)); + LOG_WARN("fail to write packet", K(cmd), K(reset_sql), K(ob_proxy_protocol), K(ret)); } } @@ -110,7 +141,8 @@ int ObMysqlRequestBuilder::build_all_session_vars_sync_packet(ObMIOBuffer &mio_b } -int ObMysqlRequestBuilder::build_session_vars_sync_packet(ObMIOBuffer &mio_buf, +int ObMysqlRequestBuilder::build_session_vars_sync_packet(ObMysqlSM *sm, + ObMIOBuffer &mio_buf, ObClientSessionInfo &client_info, ObMysqlServerSession *server_session, const ObProxyProtocol ob_proxy_protocol) @@ -123,12 +155,26 @@ int ObMysqlRequestBuilder::build_session_vars_sync_packet(ObMIOBuffer &mio_buf, LOG_WARN("fail to extract variable reset sql", K(ret)); } else { uint8_t compressed_seq = 0; - if (PROTOCOL_OB20 == ob_proxy_protocol) { - ret = ObMysqlOB20PacketWriter::write_request_packet(mio_buf, cmd, reset_sql.string(), compressed_seq, - server_session->get_next_server_request_id(), - server_session->get_server_sessid()); + if (ObProxyProtocol::PROTOCOL_OB20 == ob_proxy_protocol) { + ObSEArray extra_info; + ObSqlString sess_info_value; + char client_ip_buf[MAX_IP_BUFFER_LEN] = "\0"; + char server_extra_info_buf[SERVER_EXTRA_INFO_BUF_MAX_LEN] = "\0"; + if (OB_FAIL(ObProxyTraceUtils::build_related_extra_info_all(extra_info, sm, + client_ip_buf, MAX_IP_BUFFER_LEN, server_extra_info_buf, SERVER_EXTRA_INFO_BUF_MAX_LEN, + sess_info_value, true))) { + LOG_WARN("fail to build related extra info", K(ret)); + } else if (OB_FAIL(ObMysqlOB20PacketWriter::write_request_packet(mio_buf, cmd, reset_sql.string(), + server_session->get_server_sessid(), + server_session->get_next_server_request_id(), + compressed_seq, compressed_seq, true, false, false, + server_info.is_new_extra_info_supported(), + sm->get_client_session()->is_trans_internal_routing(), + &extra_info))) { + LOG_WARN("fail to write request packet in ob20", K(ret)); + } else { /* nothing */ } } else { - const bool need_compress = ob_proxy_protocol == PROTOCOL_CHECKSUM ? true : false; + const bool need_compress = ob_proxy_protocol == ObProxyProtocol::PROTOCOL_CHECKSUM ? true : false; ret = ObMysqlPacketWriter::write_request_packet(mio_buf, cmd, reset_sql.string(), compressed_seq, need_compress, server_info.is_checksum_on()); } @@ -137,47 +183,62 @@ int ObMysqlRequestBuilder::build_session_vars_sync_packet(ObMIOBuffer &mio_buf, server_session->set_compressed_seq(compressed_seq); LOG_DEBUG("will sync session variables", K(reset_sql)); } else { - LOG_WARN("fail to write buffer", K(cmd), K(reset_sql), K(ob_proxy_protocol), K(ret)); + LOG_WARN("fail to write packet", K(cmd), K(reset_sql), K(ob_proxy_protocol), K(ret)); } } return ret; } -int ObMysqlRequestBuilder::build_last_insert_id_sync_packet(ObMIOBuffer &mio_buf, - ObClientSessionInfo &client_info, - ObMysqlServerSession *server_session, - const ObProxyProtocol ob_proxy_protocol) +int ObMysqlRequestBuilder::build_session_user_vars_sync_packet(ObMysqlSM *sm, + ObMIOBuffer &mio_buf, + ObClientSessionInfo &client_info, + ObMysqlServerSession *server_session, + const ObProxyProtocol ob_proxy_protocol) { int ret = OB_SUCCESS; ObMySQLCmd cmd = OB_MYSQL_COM_QUERY; ObSqlString reset_sql; ObServerSessionInfo &server_info = server_session->get_session_info(); - if (OB_FAIL(client_info.extract_last_insert_id_reset_sql(server_info, reset_sql))) { - LOG_WARN("fail to extract last_insert_id variable reset sql", K(ret)); + if (OB_FAIL(client_info.extract_user_variable_reset_sql(server_info, reset_sql))) { + LOG_WARN("fail to extract variable reset sql", K(ret)); } else { uint8_t compressed_seq = 0; - if (PROTOCOL_OB20 == ob_proxy_protocol) { - ret = ObMysqlOB20PacketWriter::write_request_packet(mio_buf, cmd, reset_sql.string(), compressed_seq, - server_session->get_next_server_request_id(), - server_session->get_server_sessid()); + if (ObProxyProtocol::PROTOCOL_OB20 == ob_proxy_protocol) { + ObSEArray extra_info; + ObSqlString sess_info_value; + char client_ip_buf[MAX_IP_BUFFER_LEN] = "\0"; + char server_extra_info_buf[SERVER_EXTRA_INFO_BUF_MAX_LEN] = "\0"; + if (OB_FAIL(ObProxyTraceUtils::build_related_extra_info_all(extra_info, sm, + client_ip_buf, MAX_IP_BUFFER_LEN, server_extra_info_buf, SERVER_EXTRA_INFO_BUF_MAX_LEN, + sess_info_value, true))) { + LOG_WARN("fail to build extra info for server", K(ret)); + } else if (OB_FAIL(ObMysqlOB20PacketWriter::write_request_packet(mio_buf, cmd, reset_sql.string(), + server_session->get_server_sessid(), + server_session->get_next_server_request_id(), + compressed_seq, compressed_seq, true, false, false, + server_info.is_new_extra_info_supported(), + sm->get_client_session()->is_trans_internal_routing(), + &extra_info))) { + LOG_WARN("fail to write request packet in ob20", K(ret)); + } else { /* nothing */ } } else { - const bool need_compress = ob_proxy_protocol == PROTOCOL_CHECKSUM ? true : false; + const bool need_compress = ob_proxy_protocol == ObProxyProtocol::PROTOCOL_CHECKSUM ? true : false; ret = ObMysqlPacketWriter::write_request_packet(mio_buf, cmd, reset_sql.string(), compressed_seq, need_compress, server_info.is_checksum_on()); } if (OB_SUCC(ret)) { server_session->set_compressed_seq(compressed_seq); - LOG_DEBUG("will sync last_insert_id variable", K(reset_sql)); + LOG_DEBUG("will sync session user variables", K(reset_sql)); } else { - LOG_WARN("fail to write buffer", K(cmd), K(reset_sql), K(ob_proxy_protocol), K(ret)); + LOG_WARN("fail to write packet", K(cmd), K(reset_sql), K(ob_proxy_protocol), K(ret)); } } - return ret; } -int ObMysqlRequestBuilder::build_start_trans_request(ObMIOBuffer &mio_buf, +int ObMysqlRequestBuilder::build_start_trans_request(ObMysqlSM *sm, + ObMIOBuffer &mio_buf, ObClientSessionInfo &client_info, ObMysqlServerSession *server_session, const ObProxyProtocol ob_proxy_protocol) @@ -188,12 +249,26 @@ int ObMysqlRequestBuilder::build_start_trans_request(ObMIOBuffer &mio_buf, ObServerSessionInfo &server_info = server_session->get_session_info(); uint8_t compressed_seq = 0; - if (PROTOCOL_OB20 == ob_proxy_protocol) { - ret = ObMysqlOB20PacketWriter::write_request_packet(mio_buf, cmd, sql, compressed_seq, - server_session->get_next_server_request_id(), - server_session->get_server_sessid()); + if (ObProxyProtocol::PROTOCOL_OB20 == ob_proxy_protocol) { + ObSEArray extra_info; + ObSqlString sess_info_value; + char client_ip_buf[MAX_IP_BUFFER_LEN] = "\0"; + char server_extra_info_buf[SERVER_EXTRA_INFO_BUF_MAX_LEN] = "\0"; + if (OB_FAIL(ObProxyTraceUtils::build_related_extra_info_all(extra_info, sm, + client_ip_buf, MAX_IP_BUFFER_LEN, server_extra_info_buf, SERVER_EXTRA_INFO_BUF_MAX_LEN, + sess_info_value, true))) { + LOG_WARN("fail to build related extra info", K(ret)); + } else if (OB_FAIL(ObMysqlOB20PacketWriter::write_request_packet(mio_buf, cmd, sql, + server_session->get_server_sessid(), + server_session->get_next_server_request_id(), + compressed_seq, compressed_seq, true, false, false, + server_info.is_new_extra_info_supported(), + sm->get_client_session()->is_trans_internal_routing(), + &extra_info))) { + LOG_WARN("fail to write request packet in ob20", K(ret)); + } else { /* nothing */ } } else { - const bool need_compress = ob_proxy_protocol == PROTOCOL_CHECKSUM ? true : false; + const bool need_compress = ob_proxy_protocol == ObProxyProtocol::PROTOCOL_CHECKSUM ? true : false; ret = ObMysqlPacketWriter::write_request_packet(mio_buf, cmd, sql, compressed_seq, need_compress, server_info.is_checksum_on()); } @@ -202,13 +277,62 @@ int ObMysqlRequestBuilder::build_start_trans_request(ObMIOBuffer &mio_buf, server_session->set_compressed_seq(compressed_seq); LOG_DEBUG("will send start trans sql", K(sql)); } else { - LOG_WARN("fail to write buffer", K(cmd), K(sql), K(ob_proxy_protocol), K(ret)); + LOG_WARN("fail to write packet", K(cmd), K(sql), K(ob_proxy_protocol), K(ret)); } return ret; } -int ObMysqlRequestBuilder::build_prepare_request(ObMIOBuffer &mio_buf, +int ObMysqlRequestBuilder::build_xa_start_request(ObMysqlSM *sm, + ObMIOBuffer &mio_buf, + ObClientSessionInfo &client_info, + ObMysqlServerSession *server_session, + const ObProxyProtocol ob_proxy_protocol) +{ + LOG_DEBUG("start to build xa start request"); + int ret = OB_SUCCESS; + ObString &xa_start_req_pkt = client_info.get_start_trans_sql(); + ObString xa_pkt_payload(xa_start_req_pkt.length() - MYSQL_NET_META_LENGTH, + xa_start_req_pkt.ptr() + MYSQL_NET_META_LENGTH); + ObServerSessionInfo &server_info = server_session->get_session_info(); + ObMySQLCmd cmd = OB_MYSQL_COM_STMT_PREPARE_EXECUTE; + uint8_t compressed_seq = 0; + if (ObProxyProtocol::PROTOCOL_OB20 == ob_proxy_protocol) { + ObSEArray extra_info; + ObSqlString sess_info_value; + char client_ip_buf[MAX_IP_BUFFER_LEN] = "\0"; + char server_extra_info_buf[SERVER_EXTRA_INFO_BUF_MAX_LEN] = "\0"; + if (OB_FAIL(ObProxyTraceUtils::build_related_extra_info_all(extra_info, sm, + client_ip_buf, MAX_IP_BUFFER_LEN, server_extra_info_buf, SERVER_EXTRA_INFO_BUF_MAX_LEN, + sess_info_value, true))) { + LOG_WARN("fail to build related extra info", K(ret)); + } else if (OB_FAIL(ObMysqlOB20PacketWriter::write_request_packet(mio_buf, cmd, xa_pkt_payload, + server_session->get_server_sessid(), + server_session->get_next_server_request_id(), + compressed_seq, compressed_seq, true, false, false, + server_info.is_new_extra_info_supported(), + sm->get_client_session()->is_trans_internal_routing(), + &extra_info))) { + LOG_WARN("fail to write request packet in ob20", K(ret)); + } else { /* nothing */ } + } else { + const bool need_compress = ob_proxy_protocol == ObProxyProtocol::PROTOCOL_CHECKSUM ? true : false; + ret = ObMysqlPacketWriter::write_request_packet(mio_buf, cmd, xa_pkt_payload, compressed_seq, + need_compress, server_info.is_checksum_on()); + } + + if (OB_SUCC(ret)) { + server_session->set_compressed_seq(compressed_seq); + LOG_DEBUG("will send to sync xa start", K(xa_pkt_payload)); + } else { + LOG_WARN("fail to write xa start request to buffer", K(cmd), K(xa_pkt_payload), K(ob_proxy_protocol), K(ret)); + } + + return OB_SUCCESS; +} + +int ObMysqlRequestBuilder::build_prepare_request(ObMysqlSM *sm, + ObMIOBuffer &mio_buf, ObClientSessionInfo &client_info, ObMysqlServerSession *server_session, const ObProxyProtocol ob_proxy_protocol) @@ -221,12 +345,26 @@ int ObMysqlRequestBuilder::build_prepare_request(ObMIOBuffer &mio_buf, LOG_WARN("fail to get ps sql", K(ret)); } else { uint8_t compressed_seq = 0; - if (PROTOCOL_OB20 == ob_proxy_protocol) { - ret = ObMysqlOB20PacketWriter::write_request_packet(mio_buf, cmd, ps_sql, compressed_seq, - server_session->get_next_server_request_id(), - server_session->get_server_sessid()); + if (ObProxyProtocol::PROTOCOL_OB20 == ob_proxy_protocol) { + ObSEArray extra_info; + ObSqlString sess_info_value; + char client_ip_buf[MAX_IP_BUFFER_LEN] = "\0"; + char server_extra_info_buf[SERVER_EXTRA_INFO_BUF_MAX_LEN] = "\0"; + if (OB_FAIL(ObProxyTraceUtils::build_related_extra_info_all(extra_info, sm, + client_ip_buf, MAX_IP_BUFFER_LEN, server_extra_info_buf, SERVER_EXTRA_INFO_BUF_MAX_LEN, + sess_info_value, true))) { + LOG_WARN("fail to build related extra info", K(ret)); + } else if (OB_FAIL(ObMysqlOB20PacketWriter::write_request_packet(mio_buf, cmd, ps_sql, + server_session->get_server_sessid(), + server_session->get_next_server_request_id(), + compressed_seq, compressed_seq, true, false, false, + server_info.is_new_extra_info_supported(), + sm->get_client_session()->is_trans_internal_routing(), + &extra_info))) { + LOG_WARN("fail to write request packet in ob20", K(ret)); + } else { /* nothing */ } } else { - const bool need_compress = ob_proxy_protocol == PROTOCOL_CHECKSUM ? true : false; + const bool need_compress = ob_proxy_protocol == ObProxyProtocol::PROTOCOL_CHECKSUM ? true : false; ret = ObMysqlPacketWriter::write_request_packet(mio_buf, cmd, ps_sql, compressed_seq, need_compress, server_info.is_checksum_on()); } @@ -235,18 +373,20 @@ int ObMysqlRequestBuilder::build_prepare_request(ObMIOBuffer &mio_buf, server_session->set_compressed_seq(compressed_seq); LOG_DEBUG("will prepare sql", K(ps_sql)); } else { - LOG_WARN("fail to write buffer", K(cmd), K(ps_sql), K(ob_proxy_protocol), K(ret)); + LOG_WARN("fail to write packet", K(cmd), K(ps_sql), K(ob_proxy_protocol), K(ret)); } } return ret; } -int ObMysqlRequestBuilder::build_ssl_request_packet(event::ObMIOBuffer &mio_buf, - ObClientSessionInfo &client_info, - ObMysqlServerSession *server_session, - const ObProxyProtocol ob_proxy_protocol) +int ObMysqlRequestBuilder::build_ssl_request_packet(ObMysqlSM *sm, + event::ObMIOBuffer &mio_buf, + ObClientSessionInfo &client_info, + ObMysqlServerSession *server_session, + const ObProxyProtocol ob_proxy_protocol) { + UNUSED(sm); UNUSED(server_session); UNUSED(ob_proxy_protocol); // auth request no need compress obmysql::OMPKSSLRequest ssl_req = client_info.get_ssl_req(); @@ -254,7 +394,8 @@ int ObMysqlRequestBuilder::build_ssl_request_packet(event::ObMIOBuffer &mio_buf, return packet::ObMysqlPacketWriter::write_packet(mio_buf, ssl_req); } -int ObMysqlRequestBuilder::build_text_ps_prepare_request(ObMIOBuffer &mio_buf, +int ObMysqlRequestBuilder::build_text_ps_prepare_request(ObMysqlSM *sm, + ObMIOBuffer &mio_buf, ObClientSessionInfo &client_info, ObMysqlServerSession *server_session, const ObProxyProtocol ob_proxy_protocol) @@ -267,27 +408,59 @@ int ObMysqlRequestBuilder::build_text_ps_prepare_request(ObMIOBuffer &mio_buf, LOG_WARN("fail to get ps sql", K(ret)); } else { uint8_t compressed_seq = 0; - if (PROTOCOL_OB20 == ob_proxy_protocol) { - ret = ObMysqlOB20PacketWriter::write_request_packet(mio_buf, cmd, sql, compressed_seq, - server_session->get_next_server_request_id(), - server_session->get_server_sessid()); + if (ObProxyProtocol::PROTOCOL_OB20 == ob_proxy_protocol) { + ObSEArray extra_info; + ObSqlString sess_info_value; + char client_ip_buf[MAX_IP_BUFFER_LEN] = "\0"; + char server_extra_info_buf[SERVER_EXTRA_INFO_BUF_MAX_LEN] = "\0"; + if (OB_FAIL(ObProxyTraceUtils::build_related_extra_info_all(extra_info, sm, + client_ip_buf, MAX_IP_BUFFER_LEN, server_extra_info_buf, SERVER_EXTRA_INFO_BUF_MAX_LEN, + sess_info_value, true))) { + LOG_WARN("fail to build related extra info", K(ret)); + } else if (OB_FAIL(ObMysqlOB20PacketWriter::write_request_packet(mio_buf, cmd, sql, + server_session->get_server_sessid(), + server_session->get_next_server_request_id(), + compressed_seq, compressed_seq, true, false, false, + server_info.is_new_extra_info_supported(), + sm->get_client_session()->is_trans_internal_routing(), + &extra_info))) { + LOG_WARN("fail to write request packet in ob20", K(ret)); + } else { /* nothing */ } } else { - const bool need_compress = ob_proxy_protocol == PROTOCOL_CHECKSUM ? true : false; + const bool need_compress = ob_proxy_protocol == ObProxyProtocol::PROTOCOL_CHECKSUM ? true : false; ret = ObMysqlPacketWriter::write_request_packet(mio_buf, cmd, sql, compressed_seq, - need_compress, server_info.is_checksum_on()); + need_compress, server_info.is_checksum_on()); } if (OB_SUCC(ret)) { server_session->set_compressed_seq(compressed_seq); LOG_DEBUG("text ps sql will prepare", K(sql)); } else { - LOG_WARN("fal to write buffer", K(cmd), K(sql), K(ob_proxy_protocol), K(ret)); + LOG_WARN("fal to write packet", K(cmd), K(sql), K(ob_proxy_protocol), K(ret)); } } return ret; } +int ObMysqlRequestBuilder::build_binlog_login_packet(ObMysqlSM *sm, + ObMIOBuffer &mio_buf, + ObClientSessionInfo &client_info, + ObMysqlServerSession *server_session, + const ObProxyProtocol ob_proxy_protocol) +{ + UNUSED(sm); + UNUSED(server_session); + UNUSED(ob_proxy_protocol); + + OMPKHandshakeResponse tg_hsr = client_info.get_login_req().get_hsr_result().response_; + tg_hsr.set_username(client_info.get_login_req().get_hsr_result().full_name_); + tg_hsr.set_seq(1); + tg_hsr.reset_connect_attr(); + + return packet::ObMysqlPacketWriter::write_packet(mio_buf, tg_hsr); +} + } // end of namespace proxy } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_request_builder.h b/src/obproxy/proxy/mysqllib/ob_mysql_request_builder.h index b3317e24dac608ce58f6d325f011ce4dbeaa2aa9..137b409748e4fcd936cf7b4ad5aa9900b3418590 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_request_builder.h +++ b/src/obproxy/proxy/mysqllib/ob_mysql_request_builder.h @@ -32,64 +32,88 @@ class ObMIOBuffer; } namespace proxy { +class ObMysqlSM; -typedef int (*BuildFunc)(event::ObMIOBuffer &, ObClientSessionInfo &, ObMysqlServerSession *, const ObProxyProtocol ob_proxy_protocol); +typedef int (*BuildFunc)(ObMysqlSM *sm, event::ObMIOBuffer &, ObClientSessionInfo &, ObMysqlServerSession *, + const ObProxyProtocol ob_proxy_protocol); class ObMysqlRequestBuilder { public: // build login packet to send first login request - static int build_first_login_packet(event::ObMIOBuffer &mio_buf, + static int build_first_login_packet(ObMysqlSM *sm, + event::ObMIOBuffer &mio_buf, ObClientSessionInfo &client_info, ObMysqlServerSession *server_session, const ObProxyProtocol ob_proxy_protocol); // build login packet to send orig login request - static int build_orig_login_packet(event::ObMIOBuffer &mio_buf, + static int build_orig_login_packet(ObMysqlSM *sm, + event::ObMIOBuffer &mio_buf, ObClientSessionInfo &client_info, ObMysqlServerSession *server_session, const ObProxyProtocol ob_proxy_protocol); + + // build binlog login request + static int build_binlog_login_packet(ObMysqlSM *sm, + event::ObMIOBuffer &mio_buf, + ObClientSessionInfo &client_info, + ObMysqlServerSession *server_session, + const ObProxyProtocol ob_proxy_protocol); // build saved login packet to send saved login request - static int build_saved_login_packet(event::ObMIOBuffer &mio_buf, + static int build_saved_login_packet(ObMysqlSM *sm, + event::ObMIOBuffer &mio_buf, ObClientSessionInfo &client_info, ObMysqlServerSession *server_session, const ObProxyProtocol ob_proxy_protocol); - static int build_ssl_request_packet(event::ObMIOBuffer &mio_buf, + static int build_ssl_request_packet(ObMysqlSM *sm, + event::ObMIOBuffer &mio_buf, ObClientSessionInfo &client_info, ObMysqlServerSession *server_session, const ObProxyProtocol ob_proxy_protocol); // build packet to sync all session vars - static int build_all_session_vars_sync_packet(event::ObMIOBuffer &mio_buf, + static int build_all_session_vars_sync_packet(ObMysqlSM *sm, + event::ObMIOBuffer &mio_buf, ObClientSessionInfo &client_info, ObMysqlServerSession *server_session, const ObProxyProtocol ob_proxy_protocol); // build OB_MYSQL_COM_INIT_DB packet to sync database name - static int build_database_sync_packet(event::ObMIOBuffer &mio_buf, + static int build_database_sync_packet(ObMysqlSM *sm, + event::ObMIOBuffer &mio_buf, ObClientSessionInfo &client_info, ObMysqlServerSession *server_session, const ObProxyProtocol ob_proxy_protocol); // build OB_MYSQL_COM_QUERY packet to sync session vars - static int build_session_vars_sync_packet(event::ObMIOBuffer &mio_buf, + static int build_session_vars_sync_packet(ObMysqlSM *sm, + event::ObMIOBuffer &mio_buf, ObClientSessionInfo &client_info, ObMysqlServerSession *server_session, const ObProxyProtocol ob_proxy_protocol); - // build OB_MYSQL_COM_QUERY packet to sync last_insert_id var - static int build_last_insert_id_sync_packet(event::ObMIOBuffer &mio_buf, - ObClientSessionInfo &client_info, - ObMysqlServerSession *server_session, - const ObProxyProtocol ob_proxy_protocol); + // build OB_MYSQL_COM_QUERY packet to sync session user vars + static int build_session_user_vars_sync_packet(ObMysqlSM *sm, + event::ObMIOBuffer &mio_buf, + ObClientSessionInfo &client_info, + ObMysqlServerSession *server_session, + const ObProxyProtocol ob_proxy_protocol); // build start transaction request packet - static int build_start_trans_request(event::ObMIOBuffer &mio_buf, + static int build_start_trans_request(ObMysqlSM *sm, + event::ObMIOBuffer &mio_buf, ObClientSessionInfo &client_info, ObMysqlServerSession *server_session, const ObProxyProtocol ob_proxy_protocol); + + static int build_xa_start_request(ObMysqlSM *sm, + event::ObMIOBuffer &mio_buf, + ObClientSessionInfo &client_info, + ObMysqlServerSession *server_session, + const ObProxyProtocol ob_proxy_protocol); // build mysql request packet static int build_mysql_request(event::ObMIOBuffer &mio_buf, @@ -99,23 +123,27 @@ public: const bool is_checksum_on); // build mysql prepare request packet - static int build_prepare_request(event::ObMIOBuffer &mio_buf, + static int build_prepare_request(ObMysqlSM *sm, + event::ObMIOBuffer &mio_buf, ObClientSessionInfo &client_info, ObMysqlServerSession *server_session, const ObProxyProtocol ob_proxy_protocol); - static int build_text_ps_prepare_request(event::ObMIOBuffer &mio_buf, + static int build_text_ps_prepare_request(ObMysqlSM *sm, + event::ObMIOBuffer &mio_buf, ObClientSessionInfo &client_info, ObMysqlServerSession *server_session, const ObProxyProtocol ob_proxy_protocol); }; -inline int ObMysqlRequestBuilder::build_first_login_packet(event::ObMIOBuffer &mio_buf, +inline int ObMysqlRequestBuilder::build_first_login_packet(ObMysqlSM *sm, + event::ObMIOBuffer &mio_buf, ObClientSessionInfo &client_info, ObMysqlServerSession *server_session, const ObProxyProtocol ob_proxy_protocol) { + UNUSED(sm); UNUSED(server_session); UNUSED(ob_proxy_protocol); // auth request no need compress ObMysqlAuthRequest &auth_req = client_info.get_login_req(); @@ -127,12 +155,14 @@ inline int ObMysqlRequestBuilder::build_first_login_packet(event::ObMIOBuffer &m return packet::ObMysqlPacketWriter::write_raw_packet(mio_buf, packet_str); } -inline int ObMysqlRequestBuilder::build_orig_login_packet(event::ObMIOBuffer &mio_buf, +inline int ObMysqlRequestBuilder::build_orig_login_packet(ObMysqlSM *sm, + event::ObMIOBuffer &mio_buf, ObClientSessionInfo &client_info, ObMysqlServerSession *server_session, const ObProxyProtocol ob_proxy_protocol) { + UNUSED(sm); UNUSED(server_session); UNUSED(ob_proxy_protocol); // auth request no need compress ObMysqlAuthRequest &auth_req = client_info.get_login_req(); @@ -144,11 +174,13 @@ inline int ObMysqlRequestBuilder::build_orig_login_packet(event::ObMIOBuffer &mi return packet::ObMysqlPacketWriter::write_raw_packet(mio_buf, packet_str); } -inline int ObMysqlRequestBuilder::build_saved_login_packet(event::ObMIOBuffer &mio_buf, +inline int ObMysqlRequestBuilder::build_saved_login_packet(ObMysqlSM *sm, + event::ObMIOBuffer &mio_buf, ObClientSessionInfo &client_info, ObMysqlServerSession *server_session, const ObProxyProtocol ob_proxy_protocol) { + UNUSED(sm); UNUSED(ob_proxy_protocol); // auth request no need compress ObMysqlAuthRequest &auth_req = client_info.get_login_req(); ObHSRResult &hsr = auth_req.get_hsr_result(); diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_resp_analyzer.cpp b/src/obproxy/proxy/mysqllib/ob_mysql_resp_analyzer.cpp index 7eaae250ad070c2da7aae539edec44870eb69c25..b8b752c589eb176a0233a5f7661240d71b635829 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_resp_analyzer.cpp +++ b/src/obproxy/proxy/mysqllib/ob_mysql_resp_analyzer.cpp @@ -75,7 +75,10 @@ inline int ObMysqlPacketMetaAnalyzer::update_cur_type(ObRespResult &result, cons // paket will treat as ok packet. // so in ResultSet Protocol, a packet can be detemined as ok packet by // both 0x00 === pkt_type and 1 != has_already_recived_eof_pkt_cnt - if (OB_MYSQL_COM_STMT_PREPARE == result.get_cmd()) { + if (OB_MYSQL_COM_BINLOG_DUMP == result.get_cmd() + || OB_MYSQL_COM_BINLOG_DUMP_GTID == result.get_cmd()) { + break; + } else if (OB_MYSQL_COM_STMT_PREPARE == result.get_cmd()) { /* Preapre Request, in OCEANBASE, maybe error + ok. in this case, should set OK_PACKET_ENDING_TYPE */ if (0 == prepare_ok_pkt_cnt && 0 == err_pkt_cnt) { cur_type_ = PREPARE_OK_PACKET_ENDING_TYPE; @@ -176,7 +179,10 @@ ObRespResult::ObRespResult() mysql_mode_(UNDEFINED_MYSQL_PROTOCOL_MODE), resp_type_(MAX_RESP_TYPE), trans_state_(IN_TRANS_STATE_BY_DEFAULT), - reserved_len_(0) + reserved_len_(0), + all_pkt_cnt_(0), + expect_pkt_cnt_(0), + is_recv_resultset_(false) { MEMSET(pkt_cnt_, 0, sizeof(pkt_cnt_)); } @@ -194,7 +200,10 @@ int ObRespResult::is_resp_finished(bool &finished, ObMysqlRespEndingType &ending || OB_UNLIKELY(OB_MYSQL_COM_END == cmd_) || OB_UNLIKELY(UNDEFINED_MYSQL_PROTOCOL_MODE == mysql_mode_)) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid argument", K(pkt_cnt_), K(cmd_), K(mysql_mode_), K(ret)); + LOG_WARN("invalid argument", "ok pkt count", pkt_cnt_[OK_PACKET_ENDING_TYPE], + "eof pkt count", pkt_cnt_[EOF_PACKET_ENDING_TYPE], + "err pkt count", pkt_cnt_[ERROR_PACKET_ENDING_TYPE], + K(cmd_), K(mysql_mode_), K(ret)); } else { LOG_DEBUG("pkt count", "ok pkt count", pkt_cnt_[OK_PACKET_ENDING_TYPE], "error pkt count", pkt_cnt_[ERROR_PACKET_ENDING_TYPE], @@ -234,8 +243,10 @@ int ObRespResult::is_resp_finished(bool &finished, ObMysqlRespEndingType &ending case OB_MYSQL_COM_REFRESH : case OB_MYSQL_COM_PROCESS_KILL : case OB_MYSQL_COM_LOGIN: + case OB_MYSQL_COM_STMT_RESET: case OB_MYSQL_COM_INIT_DB : - case OB_MYSQL_COM_CHANGE_USER: { + case OB_MYSQL_COM_CHANGE_USER: + case OB_MYSQL_COM_RESET_CONNECTION: { if (OB_UNLIKELY(is_mysql_mode())) { if (1 == pkt_cnt_[OK_PACKET_ENDING_TYPE]) { finished = true; @@ -254,6 +265,9 @@ int ObRespResult::is_resp_finished(bool &finished, ObMysqlRespEndingType &ending finished = true; ending_type = ERROR_PACKET_ENDING_TYPE; } + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected mode error", K(ret), K(get_mysql_mode())); } break; } @@ -472,6 +486,27 @@ int ObRespResult::is_resp_finished(bool &finished, ObMysqlRespEndingType &ending } break; } + case OB_MYSQL_COM_BINLOG_DUMP: + case OB_MYSQL_COM_BINLOG_DUMP_GTID : { + if (1 == pkt_cnt_[EOF_PACKET_ENDING_TYPE]) { + finished = true; + ending_type = EOF_PACKET_ENDING_TYPE; + } else if (1 == pkt_cnt_[ERROR_PACKET_ENDING_TYPE]) { + finished = true; + ending_type = ERROR_PACKET_ENDING_TYPE; + } + break; + } + case OB_MYSQL_COM_REGISTER_SLAVE: { + if (1 == pkt_cnt_[ERROR_PACKET_ENDING_TYPE]) { + finished = true; + ending_type = ERROR_PACKET_ENDING_TYPE; + } else if (1 == pkt_cnt_[OK_PACKET_ENDING_TYPE]) { + finished = true; + ending_type = OK_PACKET_ENDING_TYPE; + } + break; + } default : { if (!is_supported_mysql_cmd(cmd_)) { ret = OB_NOT_SUPPORTED; @@ -527,8 +562,8 @@ inline int ObMysqlRespAnalyzer::read_pkt_hdr(ObBufferReader &buf_reader) } if (OB_LIKELY(NULL != buf_start)) { - meta_analyzer_.get_meta().pkt_len_ = ob_uint3korr(buf_start); - meta_analyzer_.get_meta().pkt_seq_ = ob_uint1korr(buf_start + 3); + meta_analyzer_.get_meta().pkt_len_ = uint3korr(buf_start); + meta_analyzer_.get_meta().pkt_seq_ = uint1korr(buf_start + 3); state_ = READ_TYPE; next_read_len_ = meta_analyzer_.get_meta().pkt_len_; } @@ -1099,7 +1134,7 @@ inline int ObMysqlRespAnalyzer::analyze_eof_pkt(obmysql::ObMySQLCmd cmd, bool &i LOG_WARN("fail to build packet content", K(ret)); } else { // skip 2 bytes of warning_count, we don't care it - server_status.flags_ = ob_uint2korr(body_buf_.ptr() + 2); + server_status.flags_ = uint2korr(body_buf_.ptr() + 2); if (server_status.status_flags_.OB_SERVER_STATUS_IN_TRANS) { is_in_trans = true; diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_response.cpp b/src/obproxy/proxy/mysqllib/ob_mysql_response.cpp index 454642c4c998b10a62bb429c356b8765b586e1a6..9a6c751889a8e82f98c56d13b2e28b5973170575 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_response.cpp +++ b/src/obproxy/proxy/mysqllib/ob_mysql_response.cpp @@ -42,7 +42,8 @@ int64_t ObRespAnalyzeResult::to_string(char *buf, const int64_t buf_len) const K_(server_capabilities_lower_.capability), K_(ok_packet_action_type), K_(last_ok_pkt_len), - K_(rewritten_last_ok_pkt_len)); + K_(rewritten_last_ok_pkt_len), + K_(extra_info)); if (is_error_resp()) { J_COMMA(); diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_response.h b/src/obproxy/proxy/mysqllib/ob_mysql_response.h index b2d915652a92a8d8119e83c1ac8173e35b451fdf..de5431d00ff44720115c6a03e08379eb55942ef2 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_response.h +++ b/src/obproxy/proxy/mysqllib/ob_mysql_response.h @@ -23,6 +23,8 @@ #include "rpc/obmysql/packet/ompk_handshake.h" #include "proxy/mysqllib/ob_mysql_common_define.h" #include "proxy/mysqllib/ob_mysql_resp_analyzer.h" +#include "proxy/mysqllib/ob_2_0_protocol_struct.h" +#include "lib/utility/ob_2_0_full_link_trace_info.h" namespace oceanbase { @@ -41,7 +43,8 @@ enum ObOKPacketActionType { struct ObRespAnalyzeResult { ObRespAnalyzeResult() { reset(); } - ~ObRespAnalyzeResult() { } + ~ObRespAnalyzeResult() { destroy(); } + void reset(); void destroy() { reset(); } @@ -75,7 +78,7 @@ struct ObRespAnalyzeResult bool is_server_can_use_compress() const { return (1 == server_capabilities_lower_.capability_flag_.OB_SERVER_CAN_USE_COMPRESS); } void set_server_trace_id(const common::ObString &trace_id); bool support_ssl() const { return 1 == server_capabilities_lower_.capability_flag_.OB_SERVER_SSL; } - + bool is_server_trans_internal_routing() const { return is_server_trans_internal_routing_; } bool is_not_supported_error() const { return (is_error_resp() && ER_NOT_SUPPORTED_YET == error_pkt_.get_err_code()); @@ -132,14 +135,30 @@ struct ObRespAnalyzeResult { return (is_error_resp() && -common::OB_STANDBY_WEAK_READ_ONLY == error_pkt_.get_err_code()); } + bool is_trans_free_route_not_supported_error() const + { + return (is_error_resp() && -common::OB_TRANS_FREE_ROUTE_NOT_SUPPORTED == error_pkt_.get_err_code()); + } + bool is_mysql_wrong_arguments_error() const + { + return (is_error_resp() && ER_WRONG_ARGUMENTS == error_pkt_.get_err_code()); + } + bool is_internal_error() const + { + return (is_error_resp() && -common::OB_INTERNAL_ERROR == error_pkt_.get_err_code()); + } inline uint32_t get_server_capability() const { return ((server_capabilities_upper_.capability_ << 16) | server_capabilities_lower_.capability_); } - int64_t to_string(char *buf, const int64_t buf_len) const; + Ob20ExtraInfo &get_extra_info() { return extra_info_; } + const Ob20ExtraInfo &get_extra_info() const { return extra_info_; } + int64_t to_string(char *buf, const int64_t buf_len) const; + + /* define elements */ bool has_more_compress_packet_; bool is_decompressed_; bool is_trans_completed_; @@ -165,9 +184,7 @@ struct ObRespAnalyzeResult obmysql::OMPKHandshake::ServerCapabilitiesUpper server_capabilities_upper_; bool is_resultset_resp_; char scramble_buf_[obmysql::OMPKHandshake::SCRAMBLE_TOTAL_SIZE + 1]; - ObOKPacketActionType ok_packet_action_type_; - int64_t reserved_len_; int64_t reserved_len_for_ob20_ok_; int64_t last_ok_pkt_len_; @@ -176,10 +193,12 @@ struct ObRespAnalyzeResult // only one of structs below is valid, according to ending_type_ obmysql::OMPKError error_pkt_; obutils::ObVariableLenBuffer error_pkt_buf_; // only store error pkt - common::ObString server_trace_id_; char server_trace_id_buf_[common::OB_MAX_TRACE_ID_LENGTH]; + Ob20ExtraInfo extra_info_; + common::FLTObjManage flt_; + bool is_server_trans_internal_routing_; DISALLOW_COPY_AND_ASSIGN(ObRespAnalyzeResult); }; @@ -190,6 +209,7 @@ public: ~ObMysqlResp() { destroy(); } void reset() { analyze_result_.reset(); } void destroy() { analyze_result_.destroy(); } + ObRespAnalyzeResult &get_analyze_result() { return analyze_result_; } const ObRespAnalyzeResult &get_analyze_result() const { return analyze_result_; } @@ -225,6 +245,9 @@ inline void ObRespAnalyzeResult::reset() server_capabilities_upper_.capability_ = 0; is_resultset_resp_ = false; server_trace_id_.reset(); + extra_info_.reset(); + flt_.reset(); + is_server_trans_internal_routing_ = false; } inline void ObRespAnalyzeResult::set_server_trace_id(const common::ObString &trace_id) @@ -241,6 +264,7 @@ inline void ObRespAnalyzeResult::set_server_trace_id(const common::ObString &tra } } + } // end of namespace proxy } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_response_builder.cpp b/src/obproxy/proxy/mysqllib/ob_mysql_response_builder.cpp index fd7eb6ca95f0555f9b403aae617a094ba8afa62d..596b68c057580b7a7799eb2326ff7e7b3b470454 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_response_builder.cpp +++ b/src/obproxy/proxy/mysqllib/ob_mysql_response_builder.cpp @@ -13,10 +13,15 @@ #define USING_LOG_PREFIX PROXY #include "proxy/mysqllib/ob_mysql_response_builder.h" #include "rpc/obmysql/packet/ompk_ok.h" +#include "rpc/obmysql/packet/ompk_prepare_execute.h" +#include "rpc/obmysql/packet/ompk_prepare_execute_req.h" +#include "rpc/obmysql/packet/ompk_eof.h" #include "packet/ob_proxy_cached_packets.h" #include "packet/ob_mysql_packet_writer.h" #include "packet/ob_mysql_packet_util.h" #include "proxy/mysqllib/ob_proxy_session_info.h" +#include "obproxy/packet/ob_proxy_packet_writer.h" +#include "obproxy/proxy/mysql/ob_mysql_client_session.h" using namespace oceanbase::common; using namespace oceanbase::obmysql; @@ -24,7 +29,6 @@ using namespace oceanbase::sql; using namespace oceanbase::obproxy::event; using namespace oceanbase::obproxy::packet; - namespace oceanbase { namespace obproxy @@ -36,7 +40,8 @@ const ObString ObMysqlResponseBuilder::OBPROXY_PROXY_VERSION_NAME = "proxy_versi int ObMysqlResponseBuilder::build_ok_resp(ObMIOBuffer &mio_buf, ObProxyMysqlRequest &client_request, - ObClientSessionInfo &info, + ObMysqlClientSession &client_session, + const ObProxyProtocol protocol, const bool is_in_trans, const bool is_state_changed) { @@ -51,7 +56,7 @@ int ObMysqlResponseBuilder::build_ok_resp(ObMIOBuffer &mio_buf, // default set of ok packet // 0x22 means OB_SERVER_STATUS_AUTOCOMMIT, OB_SERVER_STATUS_NO_INDEX_USED is set - int64_t autocommit = info.get_cached_variables().get_autocommit(); + int64_t autocommit = client_session.get_session_info().get_cached_variables().get_autocommit(); ObServerStatusFlags ssf(0x22); if (is_in_trans) { ssf.status_flags_.OB_SERVER_STATUS_IN_TRANS = 1; @@ -59,8 +64,8 @@ int ObMysqlResponseBuilder::build_ok_resp(ObMIOBuffer &mio_buf, if (is_state_changed) { ssf.status_flags_.OB_SERVER_SESSION_STATE_CHANGED = 1; } - if (0 != autocommit) { - ssf.status_flags_.OB_SERVER_STATUS_AUTOCOMMIT = 1; + if (0 == autocommit) { + ssf.status_flags_.OB_SERVER_STATUS_AUTOCOMMIT = 0; } //ok_packet.set_server_status(ssf.status_flags_); ok_packet->set_status_flags(ssf.flags_); @@ -68,21 +73,200 @@ int ObMysqlResponseBuilder::build_ok_resp(ObMIOBuffer &mio_buf, ObString pkt_str; if (OB_FAIL(ok_packet->get_packet_str(pkt_str))) { LOG_WARN("fail to get ok packet str", K(ret)); - } else if (OB_FAIL(ObMysqlPacketWriter::write_raw_packet(mio_buf, pkt_str))) { - LOG_WARN("fail to write ok packet", K(ret)); + } else if (OB_FAIL(ObProxyPacketWriter::write_raw_packet(mio_buf, client_session, protocol, pkt_str))) { + LOG_WARN("fail to write packet", K(ret)); } } return ret; } +/** + * @brief build OB_MYSQL_COM_STMT_PREPARE_EXECUTE response of XA_START request + * OB_MYSQL_COM_STMT_PREPARE_EXECUTE + * struct of OB_MYSQL_COM_STMT_PREPARE_EXECUTE RESPONSE: + * Prepare + * param_num > 0 ? ColDef * param_num + * Eof + * col_num > 0 ? ColDef * col_num + * Eof + * Row + * Eof + * Ok + * + * @param mio_buf + * @param client_request + * @param info + * @return int + */ +int ObMysqlResponseBuilder::build_prepare_execute_xa_start_resp(ObMIOBuffer &mio_buf, + ObProxyMysqlRequest &client_request, + ObMysqlClientSession &client_session, + const ObProxyProtocol protocol) +{ + int ret = OB_SUCCESS; + ObClientSessionInfo &info = client_session.get_session_info(); + OMPKPrepareExecuteReq prepare_req_pkt; + ObIOBufferReader *tmp_mio_reader = NULL; + ObMIOBuffer *tmp_mio_buf = &mio_buf; + + if (protocol == ObProxyProtocol::PROTOCOL_OB20) { + if (OB_ISNULL(tmp_mio_buf = new_empty_miobuffer())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to new miobuffer", K(ret)); + } else if (OB_ISNULL(tmp_mio_reader = tmp_mio_buf->alloc_reader())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to alloc reader", K(ret)); + } + } + + if (OB_SUCC(ret)) { + // decode the prepare execute request + prepare_req_pkt.set_content(client_request.get_req_pkt().ptr() + MYSQL_NET_HEADER_LENGTH, + static_cast(client_request.get_packet_len())); + if (OB_FAIL(prepare_req_pkt.decode())) { + LOG_WARN("fail to decode the xa start prepare execute", K(ret)); + } + } + + if (OB_SUCC(ret)) { + // get seq + uint8_t seq = static_cast(client_request.get_packet_meta().pkt_seq_ + 1); + uint32_t sid = info.get_client_ps_id(); + int64_t autocommit = info.get_cached_variables().get_autocommit(); + // write prepare execute resp + OMPKPrepareExecute prepare_pkt; + prepare_pkt.set_seq(seq++); + prepare_pkt.set_status(0); + prepare_pkt.set_statement_id(sid); + prepare_pkt.set_column_num(1); + prepare_pkt.set_param_num(static_cast(prepare_req_pkt.get_param_num())); + prepare_pkt.set_warning_count(0); + prepare_pkt.set_extend_flag(0); + prepare_pkt.set_has_result_set(1); + if (OB_FAIL(ObMysqlPacketWriter::write_packet(*tmp_mio_buf, prepare_pkt))) { + seq--; + LOG_WARN("fail to write prepare pkt of resp of xa start hold", K(ret)); + } + // write params Coldef + for (int32_t i = 0; OB_SUCC(ret) && i < prepare_req_pkt.get_param_num(); i++) { + ObMySQLField param_field; + param_field.cname_ = "?"; + param_field.type_ = prepare_req_pkt.get_param_types().at(i); + param_field.type_info_ = prepare_req_pkt.get_type_infos().at(i); + param_field.flags_ = 0; + param_field.charsetnr_ = static_cast(info.get_collation_connection()); + param_field.length_ = 0; + if (OB_FAIL(ObMysqlPacketUtil::encode_field_packet(*tmp_mio_buf, seq, param_field))) { + LOG_WARN("fail to write field pkt of resp of xa start hold", K(ret), K(param_field)); + } + } + // write Eof + if (prepare_req_pkt.get_param_num() > 0 && OB_SUCC(ret)) { + uint16_t status_flag_0 = 0; + status_flag_0 |= (1 << OB_SERVER_STATUS_IN_TRANS_POS); + if (0 != autocommit) { + status_flag_0 |= (1 << OB_SERVER_STATUS_AUTOCOMMIT_POS); + } + if (OB_FAIL(ObMysqlPacketUtil::encode_eof_packet(*tmp_mio_buf, seq, status_flag_0))){ + LOG_WARN("fail to write eof pkt of resp of xa start hold", K(ret)); + } + } + // ColDef: row field + if (OB_SUCC(ret)) { + ObMySQLField row_col_field; + row_col_field.cname_ = client_request.get_parse_sql(); + row_col_field.org_cname_ = client_request.get_parse_sql(); + row_col_field.type_ = OB_MYSQL_TYPE_LONG; + row_col_field.flags_ = OB_MYSQL_BINARY_FLAG; + row_col_field.charsetnr_ = CS_TYPE_BINARY; + row_col_field.length_ = 0; + if (OB_FAIL(ObMysqlPacketUtil::encode_field_packet(*tmp_mio_buf, seq, row_col_field))) { + LOG_WARN("fail to write field pkt of resp of xa start hold", K(ret)); + } + } + // Eof + if (OB_SUCC(ret)) { + uint16_t status_flag_1 = 0; + if (0 != autocommit) { + status_flag_1 |= (1 << OB_SERVER_STATUS_AUTOCOMMIT_POS); + } + status_flag_1 |= (1 << OB_SERVER_STATUS_IN_TRANS_POS); + status_flag_1 |= (1 << OB_SERVER_STATUS_CURSOR_EXISTS_POS); + if (OB_FAIL(ObMysqlPacketUtil::encode_eof_packet(*tmp_mio_buf, seq, status_flag_1))) { + LOG_WARN("fail to write eof pkt of resp of xa start hold", K(ret)); + } + } + // Row + if (OB_SUCC(ret)) { + ObObj field_value; + field_value.set_int32(0); + ObNewRow row; + row.cells_ = &field_value; + row.count_ = 1; + if (ObMysqlPacketUtil::encode_row_packet(*tmp_mio_buf, BINARY, seq, row)) { + LOG_WARN("fail to write row pkt", K(ret)); + } + } + // write Eof + if (OB_SUCC(ret)) { + uint16_t status_flag_2 = 0; + if (0 != autocommit) { + status_flag_2 |= (1 << OB_SERVER_STATUS_AUTOCOMMIT_POS); + } + status_flag_2 |= (1 << OB_SERVER_STATUS_IN_TRANS_POS); + status_flag_2 |= (1 << OB_SERVER_STATUS_LAST_ROW_SENT_POS); + if (OB_FAIL(ObMysqlPacketUtil::encode_eof_packet(*tmp_mio_buf, seq, status_flag_2))) { + LOG_WARN("fail to write eof pkt of resp of xa start hold", K(ret)); + } + } + // Ok + if (OB_SUCC(ret)) { + uint16_t status_flag_3 = 0; + if (0 != autocommit) { + status_flag_3 |= (1 << OB_SERVER_STATUS_AUTOCOMMIT_POS); + } + status_flag_3 |= (1 << OB_SERVER_STATUS_IN_TRANS_POS); + status_flag_3 |= (1 << OB_SERVER_STATUS_NO_INDEX_USED_POS); + status_flag_3 |= (1 << OB_SERVER_STATUS_CURSOR_EXISTS_POS); + status_flag_3 |= (1 << OB_SERVER_STATUS_LAST_ROW_SENT_POS); + status_flag_3 |= (1 << OB_SERVER_SESSION_STATE_CHANGED_POS); + if (OB_FAIL(ObMysqlPacketUtil::encode_ok_packet(*tmp_mio_buf, seq, 0, info.get_orig_capability_flags(), status_flag_3))) { + LOG_WARN("fail to write last ok pkt of resp of xa start hold", K(ret)); + } else { + LOG_DEBUG("succ to write prepare execute packets of resp of xa start hold"); + } + } else { + LOG_WARN("fail to write prepare execute packets of resp of xa start hold", K(ret)); + } + + if (OB_SUCC(ret) && protocol == ObProxyProtocol::PROTOCOL_OB20) { + Ob20ProtocolHeader &ob20_head = client_session.get_session_info().ob20_request_.ob20_header_; + uint8_t compressed_seq = static_cast(client_session.get_compressed_seq() + 1); + Ob20ProtocolHeaderParam ob20_head_param(client_session.get_cs_id(), ob20_head.request_id_, compressed_seq, + compressed_seq, true, false, false, + client_session.is_client_support_new_extra_info(), + client_session.is_trans_internal_routing()); + if (OB_FAIL(ObProto20Utils::consume_and_compress_data(tmp_mio_reader, &mio_buf, + tmp_mio_reader->read_avail(), ob20_head_param))) { + LOG_WARN("fail to consume and compress data for executor response packet in ob20", K(ret)); + } else { + LOG_DEBUG("succ to executor response in ob20 packet"); + } + } + } + return ret; +} + int ObMysqlResponseBuilder::build_select_tx_ro_resp(ObMIOBuffer &mio_buf, ObProxyMysqlRequest &client_request, - ObClientSessionInfo &info, + ObMysqlClientSession &client_session, + const ObProxyProtocol protocol, const bool is_in_trans) { int ret = OB_SUCCESS; - + ObClientSessionInfo &info = client_session.get_session_info(); + // get seq uint8_t seq = static_cast(client_request.get_packet_meta().pkt_seq_ + 1); @@ -109,20 +293,23 @@ int ObMysqlResponseBuilder::build_select_tx_ro_resp(ObMIOBuffer &mio_buf, } // encode to mio_buf - if (OB_FAIL(ObMysqlPacketUtil::encode_kv_resultset(mio_buf, seq, - field, field_value, status_flag))) { - LOG_WARN("fail to encode kv resultset", K(seq), K(ret)); + if (OB_FAIL(ObProxyPacketWriter::write_kv_resultset(mio_buf, client_session, protocol, seq, + field, field_value, status_flag))) { + LOG_WARN("fail to write kv resultset", K(ret)); } + return ret; } int ObMysqlResponseBuilder::build_select_route_addr_resp(ObMIOBuffer &mio_buf, ObProxyMysqlRequest &client_request, - ObClientSessionInfo &info, + ObMysqlClientSession &client_session, + const ObProxyProtocol protocol, const bool is_in_trans, - int64_t addr) + const struct sockaddr &addr) { int ret = OB_SUCCESS; + ObClientSessionInfo &info = client_session.get_session_info(); // get seq uint8_t seq = static_cast(client_request.get_packet_meta().pkt_seq_ + 1); @@ -131,13 +318,16 @@ int ObMysqlResponseBuilder::build_select_route_addr_resp(ObMIOBuffer &mio_buf, ObMySQLField field; field.cname_ = OBPROXY_ROUTE_ADDR_NAME; field.org_cname_ = OBPROXY_ROUTE_ADDR_NAME; - field.type_ = OB_MYSQL_TYPE_LONGLONG; + field.type_ = OB_MYSQL_TYPE_VARCHAR; field.charsetnr_ = CS_TYPE_BINARY; field.flags_ = OB_MYSQL_BINARY_FLAG; // get filed value ObObj field_value; - field_value.set_int(addr); + char buf[MAX_IP_ADDR_LENGTH]; + memset(buf, 0, sizeof(buf)); + net::ops_ip_ntop(addr, buf, MAX_IP_ADDR_LENGTH); + field_value.set_varchar(buf); // get status flag uint16_t status_flag = 0; @@ -150,19 +340,22 @@ int ObMysqlResponseBuilder::build_select_route_addr_resp(ObMIOBuffer &mio_buf, } // encode to mio_buf - if (OB_FAIL(ObMysqlPacketUtil::encode_kv_resultset(mio_buf, seq, - field, field_value, status_flag))) { - LOG_WARN("fail to encode kv resultset", K(seq), K(ret)); + if (OB_FAIL(ObProxyPacketWriter::write_kv_resultset(mio_buf, client_session, protocol, seq, + field, field_value, status_flag))) { + LOG_WARN("fail to write kv resultset", K(ret)); } + return ret; } int ObMysqlResponseBuilder::build_select_proxy_version_resp(ObMIOBuffer &mio_buf, ObProxyMysqlRequest &client_request, - ObClientSessionInfo &info, + ObMysqlClientSession &client_session, + const ObProxyProtocol protocol, const bool is_in_trans) { int ret = OB_SUCCESS; + ObClientSessionInfo &info = client_session.get_session_info(); // get seq uint8_t seq = static_cast(client_request.get_packet_meta().pkt_seq_ + 1); @@ -195,10 +388,11 @@ int ObMysqlResponseBuilder::build_select_proxy_version_resp(ObMIOBuffer &mio_buf } // encode to mio_buf - if (OB_FAIL(ObMysqlPacketUtil::encode_kv_resultset(mio_buf, seq, - field, field_value, status_flag))) { - LOG_WARN("fail to encode kv resultset", K(seq), K(ret)); + if (OB_FAIL(ObProxyPacketWriter::write_kv_resultset(mio_buf, client_session, protocol, + seq, field, field_value, status_flag))) { + LOG_WARN("fail to write kv resultset", K(ret)); } + return ret; } diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_response_builder.h b/src/obproxy/proxy/mysqllib/ob_mysql_response_builder.h index 73a9fd12e663b2885493bc2ca0b65c1511afe569..e021a0ce5ccbc51fbcf468588657a6915cd230e0 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_response_builder.h +++ b/src/obproxy/proxy/mysqllib/ob_mysql_response_builder.h @@ -13,6 +13,8 @@ #ifndef OBPROXY_MYSQL_RESPONSE_BUILDER_H #define OBPROXY_MYSQL_RESPONSE_BUILDER_H #include "utils/ob_proxy_lib.h" +#include "common/obsm_row.h" +#include "proxy/mysqllib/ob_mysql_common_define.h" namespace oceanbase { @@ -24,6 +26,7 @@ class ObMIOBuffer; } namespace proxy { +class ObMysqlClientSession; class ObClientSessionInfo; class ObProxyMysqlRequest; class ObMysqlResponseBuilder @@ -32,68 +35,78 @@ public: static const common::ObString OBPROXY_ROUTE_ADDR_NAME; static const common::ObString OBPROXY_PROXY_VERSION_NAME; - static int build_ok_resp(event::ObMIOBuffer &mio_buf, - ObProxyMysqlRequest &client_request, - ObClientSessionInfo &info, - const bool is_in_trans, - const bool is_state_changed); + static int build_ok_resp(event::ObMIOBuffer &mio_buf, ObProxyMysqlRequest &client_request, + ObMysqlClientSession &client_session, const ObProxyProtocol protocol, + const bool is_in_trans, const bool is_state_changed); - static int build_start_trans_resp(event::ObMIOBuffer &mio_buf, - ObProxyMysqlRequest &client_request, - ObClientSessionInfo &info); + static int build_start_trans_resp(event::ObMIOBuffer &mio_buf, ObProxyMysqlRequest &client_request, + ObMysqlClientSession &client_session, const ObProxyProtocol protocol); + + static int build_prepare_execute_xa_start_resp(event::ObMIOBuffer &mio_buf, + ObProxyMysqlRequest &client_request, + ObMysqlClientSession &client_session, + const ObProxyProtocol protocol); static int build_select_tx_ro_resp(event::ObMIOBuffer &mio_buf, ObProxyMysqlRequest &client_request, - ObClientSessionInfo &info, + ObMysqlClientSession &client_session, + const ObProxyProtocol protocol, const bool is_in_trans); static int build_ok_resq_with_state_changed(event::ObMIOBuffer &mio_buf, ObProxyMysqlRequest &client_request, - ObClientSessionInfo &info, + ObMysqlClientSession &client_session, + const ObProxyProtocol protocol, const bool is_in_trans); static int build_select_route_addr_resp(event::ObMIOBuffer &mio_buf, ObProxyMysqlRequest &client_request, - ObClientSessionInfo &info, + ObMysqlClientSession &client_session, + const ObProxyProtocol protocol, const bool is_in_trans, - int64_t addr); + const struct sockaddr &addr); static int build_set_route_addr_resp(event::ObMIOBuffer &mio_buf, ObProxyMysqlRequest &client_request, - ObClientSessionInfo &info, + ObMysqlClientSession &client_session, + const ObProxyProtocol protocol, const bool is_in_trans); static int build_select_proxy_version_resp(event::ObMIOBuffer &mio_buf, ObProxyMysqlRequest &client_request, - ObClientSessionInfo &info, + ObMysqlClientSession &client_session, + const ObProxyProtocol protocol, const bool is_in_trans); }; inline int ObMysqlResponseBuilder::build_start_trans_resp(event::ObMIOBuffer &mio_buf, ObProxyMysqlRequest &client_request, - ObClientSessionInfo &info) + ObMysqlClientSession &client_session, + const ObProxyProtocol protocol) { static const bool is_in_trans = true; static const bool is_state_changed = false; - return build_ok_resp(mio_buf, client_request, info, is_in_trans, is_state_changed); + return build_ok_resp(mio_buf, client_request, client_session, protocol, is_in_trans, is_state_changed); } inline int ObMysqlResponseBuilder::build_ok_resq_with_state_changed(event::ObMIOBuffer &mio_buf, ObProxyMysqlRequest &client_request, - ObClientSessionInfo &info, + ObMysqlClientSession &client_session, + const ObProxyProtocol protocol, const bool is_in_trans) { static const bool is_state_changed = true; - return build_ok_resp(mio_buf, client_request, info, is_in_trans, is_state_changed); + return build_ok_resp(mio_buf, client_request, client_session, protocol, is_in_trans, is_state_changed); } inline int ObMysqlResponseBuilder::build_set_route_addr_resp(event::ObMIOBuffer &mio_buf, ObProxyMysqlRequest &client_request, - ObClientSessionInfo &info, + ObMysqlClientSession &client_session, + const ObProxyProtocol protocol, const bool is_in_trans) { static const bool is_state_changed = false; - return build_ok_resp(mio_buf, client_request, info, is_in_trans, is_state_changed); + return build_ok_resp(mio_buf, client_request, client_session, protocol, is_in_trans, is_state_changed); } } // end of namespace proxy diff --git a/src/obproxy/proxy/mysqllib/ob_proxy_auth_parser.cpp b/src/obproxy/proxy/mysqllib/ob_proxy_auth_parser.cpp index 3212eceb945c2eb24fdf5d0bcc67e64578c3eb82..c605991197c039330e3c37778a89c1ab1ae3e198 100644 --- a/src/obproxy/proxy/mysqllib/ob_proxy_auth_parser.cpp +++ b/src/obproxy/proxy/mysqllib/ob_proxy_auth_parser.cpp @@ -261,43 +261,17 @@ bool ObProxyAuthParser::is_nonstandard_username(const ObString &full_name, const return bret; } -int ObProxyAuthParser::parse_full_user_name(const ObString &full_name, - const ObString &default_tenant_name, - const ObString &default_cluster_name, - ObHSRResult &hsr) +int ObProxyAuthParser::handle_full_user_name(ObString &full_user_name, const char separator, + ObString &user, ObString &tenant, + ObString &cluster, ObString &cluster_id_str) { int ret = OB_SUCCESS; - bool is_standard_username = false; - char separator = '\0'; - - analyze_user_name_attr(full_name, is_standard_username, separator); - if (OB_FAIL(do_parse_full_user_name(full_name, separator, default_tenant_name, - default_cluster_name, hsr))) { - LOG_WARN("fail to parse standard full username", K(full_name), K(ret)); - } - return ret; -} - -int ObProxyAuthParser::do_parse_full_user_name(const ObString &full_name, - const char separator, - const ObString &default_tenant_name, - const ObString &default_cluster_name, - ObHSRResult &hsr) -{ - int ret = OB_SUCCESS; const char *tenant_pos = NULL; const char *user_cluster_pos = NULL; const char *cluster_id_pos = NULL; - ObString full_user_name = full_name; - ObString user; - ObString tenant; - ObString cluster; ObString name_id_str; - ObString cluster_id_str; - char tenant_str[OB_MAX_TENANT_NAME_LENGTH]; - char cluster_str[OB_PROXY_MAX_CLUSTER_NAME_LENGTH]; if ('\0' == separator) { //standard full username: user@tenant#cluster:cluster_id @@ -330,14 +304,54 @@ int ObProxyAuthParser::do_parse_full_user_name(const ObString &full_name, user_cluster_pos = full_user_name.find(separator); tenant = full_user_name.split_on(separator); user = full_user_name; - if (NULL != (cluster_id_pos = user.find(CLUSTER_ID_SEPARATOR))) { + if (NULL != (cluster_id_pos = user.find(separator)) + || NULL != (cluster_id_pos = user.find(CLUSTER_ID_SEPARATOR))) { name_id_str = user; user = name_id_str.split_on(cluster_id_pos); cluster_id_str = name_id_str; } } + return ret; +} - if (OB_SUCC(ret)) { +int ObProxyAuthParser::parse_full_user_name(const ObString &full_name, + const ObString &default_tenant_name, + const ObString &default_cluster_name, + ObHSRResult &hsr) +{ + int ret = OB_SUCCESS; + bool is_standard_username = false; + char separator = '\0'; + + analyze_user_name_attr(full_name, is_standard_username, separator); + + if (OB_FAIL(do_parse_full_user_name(full_name, separator, default_tenant_name, + default_cluster_name, hsr))) { + LOG_WARN("fail to parse standard full username", K(full_name), K(ret)); + } + return ret; +} + +int ObProxyAuthParser::do_parse_full_user_name(const ObString &full_name, + const char separator, + const ObString &default_tenant_name, + const ObString &default_cluster_name, + ObHSRResult &hsr) +{ + int ret = OB_SUCCESS; + + ObString full_user_name = full_name; + ObString user; + ObString tenant; + ObString cluster; + ObString cluster_id_str; + char tenant_str[OB_MAX_TENANT_NAME_LENGTH]; + char cluster_str[OB_PROXY_MAX_CLUSTER_NAME_LENGTH]; + + if (OB_FAIL(handle_full_user_name(full_user_name, separator, user, tenant, + cluster, cluster_id_str))) { + LOG_WARN("fail to handle full user name", K(full_user_name), K(separator), K(ret)); + } else { if (tenant.empty() && cluster.empty()) { // if proxy start with specified tenant and cluster, just use them ObProxyConfig &proxy_config = get_global_proxy_config(); @@ -406,7 +420,6 @@ int ObProxyAuthParser::parse_handshake_response(ObMysqlAuthRequest &request, const char *start = auth.ptr() + MYSQL_NET_HEADER_LENGTH; uint32_t len = static_cast(auth.length() - MYSQL_NET_HEADER_LENGTH); OMPKHandshakeResponse &hsr = result.response_; - OMPKHandshake handshake; hsr.set_content(start, len); if (OB_FAIL(hsr.decode())) { diff --git a/src/obproxy/proxy/mysqllib/ob_proxy_auth_parser.h b/src/obproxy/proxy/mysqllib/ob_proxy_auth_parser.h index 67b0809ac70367d16843b0db2597ca8c7a77223b..47912b39d00c7d17d75ef5accaaaffc5717cdc3e 100644 --- a/src/obproxy/proxy/mysqllib/ob_proxy_auth_parser.h +++ b/src/obproxy/proxy/mysqllib/ob_proxy_auth_parser.h @@ -123,6 +123,13 @@ public: const common::ObString &default_cluster_name, ObHSRResult &hsr); + static void analyze_user_name_attr(const common::ObString &full_name, + bool &is_standard_username, + char &separator); + static int handle_full_user_name(common::ObString &full_name, const char separator, + common::ObString &user, common::ObString &tenant, + common::ObString &cluster, common::ObString &cluster_id_str); + static int covert_hex_to_string(const common::ObString &hex, char *str, const int64_t str_len); static int covert_string_to_hex(const common::ObString &string, char *hex, const int64_t hex_len); @@ -139,10 +146,6 @@ public: const common::ObString &default_tenant_name, const common::ObString &defualt_cluster_name); - static void analyze_user_name_attr(const common::ObString &full_name, - bool &is_standard_username, - char &separator); - static int do_parse_full_user_name(const common::ObString &full_name, const char separator, const common::ObString &default_tenant_name, diff --git a/src/obproxy/proxy/mysqllib/ob_proxy_mysql_request.cpp b/src/obproxy/proxy/mysqllib/ob_proxy_mysql_request.cpp index 4af8393b210496156efcf3762c29234164ceaf46..6c0907ec34b0a7ac0fb6955857980fdbab9b099c 100644 --- a/src/obproxy/proxy/mysqllib/ob_proxy_mysql_request.cpp +++ b/src/obproxy/proxy/mysqllib/ob_proxy_mysql_request.cpp @@ -14,6 +14,8 @@ #include "utils/ob_proxy_utils.h" #include "proxy/mysqllib/ob_proxy_mysql_request.h" +#include "obproxy/cmd/ob_internal_cmd_processor.h" +#include "obproxy/utils/ob_proxy_privilege_check.h" using namespace oceanbase::common; using namespace oceanbase::sql; @@ -67,7 +69,7 @@ ObProxyMysqlRequest::ObProxyMysqlRequest() req_pkt_len_(0), req_buf_for_prepare_execute_(NULL), req_buf_for_prepare_execute_len_(0), result_(), ps_result_(NULL), user_identity_(USER_TYPE_NONE), is_internal_cmd_(false), is_kill_query_(false), - is_large_request_(false), enable_analyze_internal_cmd_(false) + is_large_request_(false), enable_analyze_internal_cmd_(false), is_mysql_req_in_ob20_payload_(false) { sql_id_buf_[0] = '\0'; } @@ -87,9 +89,12 @@ int ObProxyMysqlRequest::add_request(event::ObIOBufferReader *reader, const int6 ret = OB_INVALID_ARGUMENT; LOG_WARN("buffer reader is empty", K(ret)); } else { - //OB_MYSQL_COM_STMT_CLOSE always followed other request - if (OB_UNLIKELY(OB_MYSQL_COM_STMT_CLOSE == meta_.cmd_ || OB_MYSQL_COM_STMT_SEND_LONG_DATA == meta_.cmd_) - && OB_LIKELY(total_len > meta_.pkt_len_)) { + // OB_MYSQL_COM_STMT_CLOSE/OB_MYSQL_COM_STMT_SEND_LONG_DATA always followed other request + // mysql req in ob20 payload, always followed by crc or other mysql req + LOG_DEBUG("add request before", K(total_len), K(meta_), K(is_mysql_req_in_ob20_payload())); + if (total_len > meta_.pkt_len_ + && (is_mysql_req_in_ob20_payload() + || OB_UNLIKELY(OB_MYSQL_COM_STMT_CLOSE == meta_.cmd_ || OB_MYSQL_COM_STMT_SEND_LONG_DATA == meta_.cmd_))) { total_len = meta_.pkt_len_; } @@ -159,6 +164,33 @@ int ObProxyMysqlRequest::fill_query_info(const int64_t cs_id) return ret; } +void ObProxyMysqlRequest::reuse(bool is_reset_origin_db_table /* true */) +{ + if (OB_UNLIKELY(NULL != cmd_info_)) { + op_fixed_mem_free(cmd_info_, static_cast(sizeof(ObInternalCmdInfo))); + cmd_info_ = NULL; + } + if (OB_UNLIKELY(NULL != query_info_)) { + op_fixed_mem_free(query_info_, static_cast(sizeof(ObProxyKillQueryInfo))); + query_info_ = NULL; + } + if (NULL != ps_result_) { + ps_result_ = NULL; + } + meta_.reset(); + result_.reset(is_reset_origin_db_table); + is_internal_cmd_ = false; + is_kill_query_ = false; + is_large_request_ = false; + enable_analyze_internal_cmd_ = false; + is_mysql_req_in_ob20_payload_ = false; + user_identity_ = USER_TYPE_NONE; + req_pkt_len_ = 0; + allocator_.reuse(); + sql_id_buf_[0] = '\0'; +} + + } // end of namespace proxy } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/proxy/mysqllib/ob_proxy_mysql_request.h b/src/obproxy/proxy/mysqllib/ob_proxy_mysql_request.h index 9f8a606f8273f35cfea1fc88d0d2fac11636ce16..39e9a86a4da8b2e2da7994e4d3c62219eb549dfa 100644 --- a/src/obproxy/proxy/mysqllib/ob_proxy_mysql_request.h +++ b/src/obproxy/proxy/mysqllib/ob_proxy_mysql_request.h @@ -36,6 +36,7 @@ class ObIOBufferReader; } namespace proxy { + struct ObProxyKillQueryInfo { ObProxyKillQueryInfo() { reset(); } @@ -77,6 +78,7 @@ public: static common::ObString get_print_sql(const common::ObString &req_sql, const int64_t sql_len = PRINT_SQL_LEN); common::ObString get_req_pkt(); obutils::ObSqlParseResult &get_parse_result(); + const obutils::ObSqlParseResult &get_parse_result() const; obutils::ObSqlParseResult *get_ps_parse_result() { return ps_result_; } void set_ps_parse_result(obutils::ObSqlParseResult *ps_result) { ps_result_ = ps_result; } void set_text_ps_parse_result(obutils::ObSqlParseResult *text_ps_result) @@ -90,6 +92,8 @@ public: bool is_kill_query() const { return is_kill_query_; } bool is_large_request() const { return is_large_request_; } bool enable_analyze_internal_cmd() const { return enable_analyze_internal_cmd_; } + bool is_mysql_req_in_ob20_payload() const { return is_mysql_req_in_ob20_payload_; } + bool is_sharding_user() const { return USER_TYPE_SHARDING == user_identity_; } bool is_proxysys_user() const { return USER_TYPE_PROXYSYS == user_identity_; } bool is_inspector_user() const { return USER_TYPE_INSPECTOR == user_identity_; } @@ -100,12 +104,15 @@ public: void set_is_kill_query(const bool flag) { is_kill_query_ = flag; } void set_large_request(const bool flag) { is_large_request_ = flag; } void set_enable_analyze_internal_cmd(const bool internal) { enable_analyze_internal_cmd_ = internal; } + void set_mysql_req_in_ob20_payload(const bool flag) { is_mysql_req_in_ob20_payload_ = flag; } + void set_user_identity(const ObProxyLoginUserType type) { user_identity_ = type; } inline ObProxyLoginUserType get_user_identity() const { return user_identity_; } int64_t get_packet_len() { return meta_.pkt_len_; } ObMysqlPacketMeta &get_packet_meta() { return meta_; } + const ObMysqlPacketMeta &get_packet_meta() const { return meta_; } void set_packet_meta(const ObMysqlPacketMeta &meta) { meta_ = meta; } // add received request @@ -123,6 +130,8 @@ public: ObInternalCmdInfo *cmd_info_; ObProxyKillQueryInfo *query_info_; + TO_STRING_KV(K_(meta), K_(req_buf_len), K_(req_pkt_len), K_(is_internal_cmd), K_(is_kill_query), + K_(is_large_request), K_(enable_analyze_internal_cmd), K_(is_mysql_req_in_ob20_payload)); private: ObMysqlPacketMeta meta_; // request packet meta char *req_buf_; // request buf @@ -140,36 +149,12 @@ private: bool is_kill_query_; bool is_large_request_; bool enable_analyze_internal_cmd_;//indicate whether need analyze internal cmd + bool is_mysql_req_in_ob20_payload_; // whether the mysql req is in ob20 protocol req payload common::ObArenaAllocator allocator_; char sql_id_buf_[common::OB_MAX_SQL_ID_LENGTH + 1]; }; -inline void ObProxyMysqlRequest::reuse(bool is_reset_origin_db_table /* true */) -{ - if (OB_UNLIKELY(NULL != cmd_info_)) { - op_fixed_mem_free(cmd_info_, static_cast(sizeof(ObInternalCmdInfo))); - cmd_info_ = NULL; - } - if (OB_UNLIKELY(NULL != query_info_)) { - op_fixed_mem_free(query_info_, static_cast(sizeof(ObProxyKillQueryInfo))); - query_info_ = NULL; - } - if (NULL != ps_result_) { - ps_result_ = NULL; - } - meta_.reset(); - result_.reset(is_reset_origin_db_table); - is_internal_cmd_ = false; - is_kill_query_ = false; - is_large_request_ = false; - enable_analyze_internal_cmd_ = false; - user_identity_ = USER_TYPE_NONE; - req_pkt_len_ = 0; - allocator_.reuse(); - sql_id_buf_[0] = '\0'; -} - bool ObProxyMysqlRequest::is_real_dml_sql() const { bool bret = false; @@ -213,7 +198,17 @@ inline void ObProxyMysqlRequest::reset(bool is_reset_origin_db_table /* true */) inline obutils::ObSqlParseResult &ObProxyMysqlRequest::get_parse_result() { obutils::ObSqlParseResult *result = &result_; - if ((obmysql::OB_MYSQL_COM_STMT_EXECUTE == meta_.cmd_ || obmysql::OB_MYSQL_COM_STMT_SEND_LONG_DATA == meta_.cmd_) + if ((obmysql::OB_MYSQL_COM_STMT_EXECUTE == meta_.cmd_ || obmysql::OB_MYSQL_COM_STMT_SEND_LONG_DATA == meta_.cmd_) + && NULL != ps_result_) { + result = ps_result_; + } + return *result; +} + +const obutils::ObSqlParseResult &ObProxyMysqlRequest::get_parse_result() const +{ + const obutils::ObSqlParseResult *result = &result_; + if ((obmysql::OB_MYSQL_COM_STMT_EXECUTE == meta_.cmd_ || obmysql::OB_MYSQL_COM_STMT_SEND_LONG_DATA == meta_.cmd_) && NULL != ps_result_) { result = ps_result_; } diff --git a/src/obproxy/proxy/mysqllib/ob_proxy_ob20_request.h b/src/obproxy/proxy/mysqllib/ob_proxy_ob20_request.h new file mode 100644 index 0000000000000000000000000000000000000000..befc96198abcf478a6d2fa50d52589985a5d1d7d --- /dev/null +++ b/src/obproxy/proxy/mysqllib/ob_proxy_ob20_request.h @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef OBPROXY_MYSQL_OB20_REQUEST_H +#define OBPROXY_MYSQL_OB20_REQUEST_H + +#include "proxy/mysqllib/ob_mysql_common_define.h" +#include "proxy/mysqllib/ob_2_0_protocol_struct.h" + +namespace oceanbase +{ +namespace obproxy +{ +namespace proxy +{ + +struct ObProxyObProto20Request { +public: + ObProxyObProto20Request() + : remain_payload_len_(0), ob20_request_received_done_(false) + { + ob20_header_.reset(); + } + ~ObProxyObProto20Request() {} + void reset() + { + remain_payload_len_ = 0; + ob20_request_received_done_ = false; + ob20_header_.reset(); + } + + // ob20 payload could contain more than one mysql packet, the total mysql packet len stored here + int64_t remain_payload_len_; + bool ob20_request_received_done_; // ob2.0 request from client received done, and tail crc not handled yet + Ob20ProtocolHeader ob20_header_; + + TO_STRING_KV(K_(remain_payload_len), K_(ob20_request_received_done), K_(ob20_header)); +}; + +} // proxy +} // obproxy +} // oceanbase + +#endif diff --git a/src/obproxy/proxy/mysqllib/ob_proxy_parser_utils.cpp b/src/obproxy/proxy/mysqllib/ob_proxy_parser_utils.cpp index 23e1d7c45fbc09f352467cb2d57a18efc2edad63..7c944a7c56762a95ecffa82bcea55580c11f4f68 100644 --- a/src/obproxy/proxy/mysqllib/ob_proxy_parser_utils.cpp +++ b/src/obproxy/proxy/mysqllib/ob_proxy_parser_utils.cpp @@ -13,6 +13,7 @@ #define USING_LOG_PREFIX PROXY #include "proxy/mysqllib/ob_proxy_parser_utils.h" #include "rpc/obmysql/ob_mysql_util.h" +#include "iocore/eventsystem/ob_io_buffer.h" using namespace oceanbase::obproxy::event; using namespace oceanbase::obmysql; @@ -27,18 +28,18 @@ uint64_t ObProxyParserUtils::get_lenenc_int(const char *&buf) { uint64_t ret_value = 0; uint64_t int_len = 0; - int_len = ob_uint1korr(buf); + int_len = uint1korr(buf); buf += 1; if (int_len < 0xfb) { ret_value = int_len; } else if (0xfc == int_len){ - ret_value = ob_uint2korr(buf); + ret_value = uint2korr(buf); buf += 2; } else if (0xfd == int_len){ - ret_value = ob_uint3korr(buf); + ret_value = uint3korr(buf); buf += 3; } else if(0xfe == int_len){ - ret_value = ob_uint8korr(buf); + ret_value = uint8korr(buf); buf += 8; } return ret_value; @@ -136,6 +137,10 @@ const char *ObProxyParserUtils::get_sql_cmd_name(const ObMySQLCmd cmd) name = "OB_MYSQL_COM_BINLOG_DUMP"; break; + case OB_MYSQL_COM_RESET_CONNECTION: + name = "OB_MYSQL_COM_RESET_CONNECTION"; + break; + case OB_MYSQL_COM_TABLE_DUMP: name = "OB_MYSQL_COM_TABLE_DUMP"; break; @@ -266,8 +271,8 @@ int ObProxyParserUtils::analyze_one_packet(ObIOBufferReader &reader, ObMysqlAnal } if (OB_SUCC(ret)) { - result.meta_.pkt_len_ = ob_uint3korr(buf_start) + MYSQL_NET_HEADER_LENGTH; - result.meta_.pkt_seq_ = ob_uint1korr(buf_start + 3); + result.meta_.pkt_len_ = uint3korr(buf_start) + MYSQL_NET_HEADER_LENGTH; + result.meta_.pkt_seq_ = uint1korr(buf_start + 3); result.meta_.data_ = static_cast(buf_start[4]); if (OB_LIKELY(len >= result.meta_.pkt_len_)) { result.status_ = ANALYZE_DONE; @@ -301,8 +306,8 @@ int ObProxyParserUtils::analyze_one_packet_only_header(ObIOBufferReader &reader, } if (OB_SUCC(ret)) { - result.meta_.pkt_len_ = ob_uint3korr(buf_start) + MYSQL_NET_HEADER_LENGTH; // include header - result.meta_.pkt_seq_ = ob_uint1korr(buf_start + 3); + result.meta_.pkt_len_ = uint3korr(buf_start) + MYSQL_NET_HEADER_LENGTH; // include header + result.meta_.pkt_seq_ = uint1korr(buf_start + 3); result.meta_.cmd_ = OB_MYSQL_COM_MAX_NUM; // only analyze header if (len >= result.meta_.pkt_len_) { result.status_ = ANALYZE_DONE; @@ -319,8 +324,8 @@ int ObProxyParserUtils::analyze_mysql_packet_meta(const char *ptr, const int64_t ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid input value", KP(ptr), K(len), K(ret)); } else { - meta.pkt_len_ = ob_uint3korr(ptr) + MYSQL_NET_HEADER_LENGTH; - meta.pkt_seq_ = ob_uint1korr(ptr + 3); + meta.pkt_len_ = uint3korr(ptr) + MYSQL_NET_HEADER_LENGTH; + meta.pkt_seq_ = uint1korr(ptr + 3); meta.data_ = static_cast(ptr[4]); } @@ -334,8 +339,8 @@ int ObProxyParserUtils::analyze_mysql_packet_header(const char *ptr, const int64 ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid input value", KP(ptr), K(len), K(ret)); } else { - header.len_ = ob_uint3korr(ptr); - header.seq_ = ob_uint1korr(ptr + 3); + header.len_ = uint3korr(ptr); + header.seq_ = uint1korr(ptr + 3); } return ret; diff --git a/src/obproxy/proxy/mysqllib/ob_proxy_parser_utils.h b/src/obproxy/proxy/mysqllib/ob_proxy_parser_utils.h index c9ece90512b610e82b2cfdaf42118bcdd0a2e7c4..f464cef439be286b893f8394fb69e7b20ac77351 100644 --- a/src/obproxy/proxy/mysqllib/ob_proxy_parser_utils.h +++ b/src/obproxy/proxy/mysqllib/ob_proxy_parser_utils.h @@ -16,8 +16,9 @@ #include "lib/ob_define.h" #include "rpc/obmysql/ob_mysql_packet.h" #include "proxy/mysqllib/ob_mysql_common_define.h" -#include "proxy/mysqllib/ob_proxy_mysql_request.h" #include "proxy/mysqllib/ob_2_0_protocol_struct.h" +#include "lib/utility/ob_2_0_full_link_trace_info.h" + namespace oceanbase { @@ -32,6 +33,7 @@ namespace proxy enum ObMysqlAnalyzeStatus { + ANALYZE_NOT_SUPPORT = -4, ANALYZE_CAN_NOT_PASS_WHITE_LIST_ERROR = -3, ANALYZE_OBPARSE_ERROR = -2, ANALYZE_ERROR = -1, @@ -79,16 +81,22 @@ public: class ObMysqlCompressedOB20AnalyzeResult : public ObMysqlCompressedAnalyzeResult { public: - ObMysqlCompressedOB20AnalyzeResult() : ObMysqlCompressedAnalyzeResult(), ob20_header_() {} - ~ObMysqlCompressedOB20AnalyzeResult() {} + ObMysqlCompressedOB20AnalyzeResult() + : ObMysqlCompressedAnalyzeResult(), ob20_header_(), extra_info_(), flt_() {} + ~ObMysqlCompressedOB20AnalyzeResult() { reset(); } virtual void reset() { ObMysqlCompressedAnalyzeResult::reset(); ob20_header_.reset(); + extra_info_.reset(); + flt_.reset(); } Ob20ProtocolHeader ob20_header_; - TO_STRING_KV(K_(status), K_(header), K_(is_checksum_on), K_(ob20_header)); + Ob20ExtraInfo extra_info_; + common::FLTObjManage flt_; + + TO_STRING_KV(K_(status), K_(header), K_(is_checksum_on), K_(ob20_header), K_(extra_info)); }; class ObProxyParserUtils diff --git a/src/obproxy/proxy/mysqllib/ob_proxy_session_info.cpp b/src/obproxy/proxy/mysqllib/ob_proxy_session_info.cpp index bfe77e3e5eed5246b836bda24030a734af424c6f..6268bd3b44b12e65efe2035184207bfd1d5d1b59 100644 --- a/src/obproxy/proxy/mysqllib/ob_proxy_session_info.cpp +++ b/src/obproxy/proxy/mysqllib/ob_proxy_session_info.cpp @@ -20,12 +20,14 @@ #include "proxy/mysqllib/ob_sys_var_set_processor.h" #include "obutils/ob_proxy_json_config_info.h" #include "obutils/ob_resource_pool_processor.h" +#include "rpc/obmysql/ob_mysql_util.h" using namespace oceanbase::sql; using namespace oceanbase::common; using namespace oceanbase::common::hash; using namespace oceanbase::obproxy::obutils; using namespace oceanbase::obproxy::dbconfig; +using namespace oceanbase::obmysql; namespace oceanbase { @@ -37,16 +39,16 @@ const int64_t SESSION_ITEM_NUM = 256; ObServerSessionInfo::ObServerSessionInfo() : cap_(0), compatible_capability_(0), checksum_switch_(CHECKSUM_ON), is_inited_(false), server_type_(DB_OB_MYSQL), shard_conn_(NULL), - ps_id_(0), ps_id_pair_map_(), cursor_id_pair_map_(), allocator_(), text_ps_name_set_() + ps_id_(0), ps_id_pair_map_(), cursor_id_pair_map_(), allocator_(), text_ps_version_set_() { const int BUCKET_SIZE = 8; - text_ps_name_set_.create(BUCKET_SIZE); + text_ps_version_set_.create(BUCKET_SIZE); } ObServerSessionInfo::~ObServerSessionInfo() { reset(); - text_ps_name_set_.destroy(); + text_ps_version_set_.destroy(); if (NULL != shard_conn_) { shard_conn_->dec_ref(); shard_conn_ = NULL; @@ -120,7 +122,7 @@ void ObServerSessionInfo::reset() cap_ = 0; compatible_capability_.capability_ = 0; checksum_switch_ = CHECKSUM_ON; - text_ps_name_set_.reuse(); + reuse_text_ps_version_set(); } void ObServerSessionInfo::destroy_ps_id_pair_map() @@ -147,34 +149,55 @@ void ObServerSessionInfo::destroy_cursor_id_pair_map() cursor_id_pair_map_.reset(); } -int ObServerSessionInfo::add_text_ps_name(const uint32_t text_ps_name_id) +int ObServerSessionInfo::set_text_ps_version(const int64_t text_ps_version) { int ret = OB_SUCCESS; - if (OB_FAIL(text_ps_name_set_.set_refactored(text_ps_name_id))) { - LOG_WARN("set refactored failed", K(ret), K(text_ps_name_id)); + if (OB_FAIL(text_ps_version_set_.set_refactored(text_ps_version))) { + LOG_WARN("set refactored failed", K(ret), K(text_ps_version)); + } else { + LOG_DEBUG("set refactored succed", K(text_ps_version)); + } + + return ret; +} + +int ObServerSessionInfo::remove_text_ps_version(const int64_t text_ps_version) +{ + int ret = OB_SUCCESS; + + if (OB_FAIL(text_ps_version_set_.erase_refactored(text_ps_version))) { + LOG_WARN("remove refactored failed", K(ret), K(text_ps_version)); + } else { + LOG_DEBUG("remove refactored succed", K(text_ps_version)); } - + return ret; } +void ObServerSessionInfo::reuse_text_ps_version_set() +{ + text_ps_version_set_.reuse(); +} + ObClientSessionInfo::ObClientSessionInfo() : is_inited_(false), is_trans_specified_(false), is_global_vars_changed_(false), - is_user_idc_name_set_(false), is_read_consistency_set_(false), is_oracle_mode_(false), + is_user_idc_name_set_(false), is_read_consistency_set_(false), is_oracle_mode_(false), is_proxy_route_policy_set_(false), - enable_shard_authority_(false), enable_reset_db_(true), cap_(0), safe_read_snapshot_(0), + enable_shard_authority_(false), enable_reset_db_(true), client_cap_(0), server_cap_(0), + safe_read_snapshot_(0), syncing_safe_read_snapshot_(0), route_policy_(1), proxy_route_policy_(MAX_PROXY_ROUTE_POLICY), user_identity_(USER_TYPE_NONE), cached_variables_(), global_vars_version_(OB_INVALID_VERSION), obproxy_route_addr_(0), var_set_processor_(NULL), cluster_id_(OB_INVALID_CLUSTER_ID), real_meta_cluster_name_(), real_meta_cluster_name_str_(NULL), server_type_(DB_OB_MYSQL), shard_conn_(NULL), shard_prop_(NULL), - group_id_(OBPROXY_MAX_DBMESH_ID), is_allow_use_last_session_(true), + group_id_(OBPROXY_MAX_DBMESH_ID), table_id_(OBPROXY_MAX_DBMESH_ID), es_id_(OBPROXY_MAX_DBMESH_ID), + is_allow_use_last_session_(true), consistency_level_prop_(INVALID_CONSISTENCY), - recv_client_ps_id_(0), ps_id_(0), ps_entry_(NULL), ps_id_entry_map_(), - text_ps_name_entry_map_(), is_text_ps_execute_(false), - cursor_id_(0), cursor_id_addr_map_(), - ps_id_addrs_map_(), + recv_client_ps_id_(0), ps_id_(0), ps_entry_(NULL), ps_id_entry_(NULL), ps_id_entry_map_(), + text_ps_name_entry_(NULL), text_ps_name_entry_map_(), cursor_id_(0), cursor_id_addr_map_(), + ps_id_addrs_map_(), request_send_addrs_(), is_read_only_user_(false), is_request_follower_user_(false) { @@ -183,6 +206,8 @@ ObClientSessionInfo::ObClientSessionInfo() MEMSET(idc_name_buf_, 0, sizeof(idc_name_buf_)); MEMSET(client_host_buf_, 0, sizeof(client_host_buf_)); MEMSET(username_buf_, 0, sizeof(username_buf_)); + + ob20_request_.reset(); } ObClientSessionInfo::~ObClientSessionInfo() @@ -199,7 +224,7 @@ int64_t ObClientSessionInfo::to_string(char *buf, const int64_t buf_len) const K_(is_read_consistency_set), K_(idc_name), K_(cluster_id), K_(real_meta_cluster_name), K_(safe_read_snapshot), K_(syncing_safe_read_snapshot), K_(route_policy), K_(proxy_route_policy), K_(user_identity), K_(global_vars_version), - K_(is_read_only_user), K_(is_request_follower_user)); + K_(is_read_only_user), K_(is_request_follower_user), K_(ob20_request), K_(client_cap), K_(server_cap)); J_OBJ_END(); return pos; } @@ -212,6 +237,8 @@ int ObClientSessionInfo::init() LOG_WARN("client session is inited", K(ret)); } else if (OB_FAIL(field_mgr_.init())) { LOG_WARN("fail to init field_mgr", K(ret)); + } else if (OB_FAIL(sess_info_hash_map_.create(32, ObModIds::OB_PROXY_SESS_SYNC))) { + LOG_WARN("create hash map failed", K(ret)); } else { LOG_DEBUG("init session info success", K(cached_variables_)); is_inited_ = true; @@ -292,7 +319,7 @@ int ObClientSessionInfo::set_tenant_name(const ObString &tenant_name) int ObClientSessionInfo::set_vip_addr_name(const common::ObAddr &vip_addr) { int ret = OB_SUCCESS; - char vip_name[OB_IP_STR_BUFF]; + char vip_name[MAX_IP_ADDR_LENGTH]; if (OB_UNLIKELY(!vip_addr.ip_to_string(vip_name, static_cast(sizeof(vip_name))))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to covert ip to string", K(vip_name), K(ret)); @@ -350,6 +377,71 @@ int ObClientSessionInfo::set_ldg_logical_tenant_name(const ObString &tenant_name return field_mgr_.set_ldg_logical_tenant_name(tenant_name); } +int ObClientSessionInfo::update_sess_sync_info(const ObString& sess_info, common::ObSimpleTrace<4096> &trace_log) +{ + int ret = OB_SUCCESS; + const char *buf = sess_info.ptr(); + const int64_t len = sess_info.length(); + const char *end = buf + len; + // decode sess_info + const int MAX_TYPE_RECORD = 32; + char type_record[MAX_TYPE_RECORD]; + memset(type_record, '0', MAX_TYPE_RECORD); + if (NULL != sess_info.ptr()) { + while (OB_SUCC(ret) && buf < end) { + int16_t info_type = 0; + int32_t info_len = 0; + ObMySQLUtil::get_int2(buf, info_type); + ObMySQLUtil::get_int4(buf, info_len); + if(info_type < MAX_TYPE_RECORD) { + type_record[info_type] = '1'; + } + if (buf + info_len > end) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("data is error", K(info_type), K(info_len), K(len), K(ret)); + } else { + LOG_DEBUG("extra info", K(info_type), K(info_len), K(len)); + char* info_value = NULL; + ObString info_value_string; + if (OB_FAIL(inc_sess_field_version(info_type))) { + LOG_WARN("fail to update sess field versoin", K(info_type), K(ret)); + } + if (OB_SUCC(sess_info_hash_map_.get_refactored(info_type, info_value_string))) { + sess_info_hash_map_.erase_refactored(info_type); + int64_t total_len = info_value_string.length(); + op_fixed_mem_free(info_value_string.ptr(), total_len); + } + int64_t client_version = 0; + if (OB_FAIL(ObProxyTraceUtils::get_sess_field_version(client_version , info_type, version_.sess_field_version_))) { + LOG_WARN("fail to set client session field version", K(info_type), K(ret)); + } else { + } + info_value_string.reset(); + if (OB_ISNULL(info_value = static_cast(op_fixed_mem_alloc(info_len + 6)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc memory", K(info_len), K(ret)); + } else if (FALSE_IT(MEMCPY(info_value, buf - 6, info_len + 6))) { + } else if (FALSE_IT(info_value_string.assign_ptr(info_value, info_len + 6))) { + } else if (OB_FAIL(sess_info_hash_map_.set_refactored(info_type, info_value_string))) { + LOG_WARN("fail to set to hash map", K(info_type), K(ret)); + op_fixed_mem_free(info_value, info_len + 6); + info_value = NULL; + } else { + buf += info_len; + } + } + } + type_record[MAX_TYPE_RECORD - 1] = '\0'; + trace_log.log_it("[get_sess]", "type", type_record); + if (OB_SUCC(ret)) { + version_.inc_sess_info_version(); + LOG_DEBUG("update sess info succ", K(sess_info)); + } + } + + return ret; +} + int ObClientSessionInfo::get_cluster_name(ObString &cluster_name) const { return field_mgr_.get_cluster_name(cluster_name); @@ -803,6 +895,46 @@ int ObClientSessionInfo::extract_all_variable_reset_sql(ObSqlString &sql) return ret; } +int ObClientSessionInfo::extract_user_variable_reset_sql(ObServerSessionInfo &server_info, + ObSqlString &sql) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(!is_inited_)) { + ret = OB_NOT_INIT; + LOG_WARN("client session is not inited", K(ret)); + } else { + bool need_reset = false; + if (OB_FAIL(sql.append_fmt("SET"))) { + LOG_WARN("fail to append_fmt 'SET'", K(ret)); + } else if (!is_oceanbase_server()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("extract user variable reset sql only for oceanbase server"); + } else { /* do nothing */ } + + //reset user variable + if (OB_SUCC(ret)) { + if (need_reset_user_session_vars(server_info)) { + need_reset = true; + if (OB_FAIL(field_mgr_.format_user_var(sql))) { + LOG_WARN("fail to format_user_var.", K(sql), K(*this), + K(server_info), K(ret)); + } + } + } + + if (OB_SUCC(ret)) { + if (need_reset) { + *(sql.ptr() + sql.length() - 1) = ';'; //replace ',' with ';' + } else { + sql.reset(); + } + } else { + sql.reset(); + } + } + return ret; +} + int ObClientSessionInfo::extract_variable_reset_sql(ObServerSessionInfo &server_info, ObSqlString &sql) { @@ -1138,6 +1270,7 @@ void ObClientSessionInfo::destroy() if (is_inited_) { field_mgr_.destroy(); login_req_.destroy(); + destroy_sess_info_map(); is_inited_ = false; } if (NULL != var_set_processor_) { @@ -1155,6 +1288,7 @@ void ObClientSessionInfo::destroy() destroy_cursor_id_addr_map(); destroy_ps_id_addrs_map(); destroy_piece_info_map(); + destroy_text_ps_name_entry_map(); is_trans_specified_ = false; is_global_vars_changed_ = false; is_user_idc_name_set_ = false; @@ -1174,7 +1308,8 @@ void ObClientSessionInfo::destroy() syncing_safe_read_snapshot_ = 0; route_policy_ = 1; proxy_route_policy_ = MAX_PROXY_ROUTE_POLICY; - cap_ = 0; + client_cap_ = 0; + server_cap_ = 0; cluster_id_ = OB_INVALID_CLUSTER_ID; free_real_meta_cluster_name(); @@ -1188,6 +1323,8 @@ void ObClientSessionInfo::destroy() shard_prop_ = NULL; } group_id_ = OBPROXY_MAX_DBMESH_ID; + table_id_ = OBPROXY_MAX_DBMESH_ID; + es_id_ = OBPROXY_MAX_DBMESH_ID; is_allow_use_last_session_ = true; up_info_.reset(); } @@ -1240,25 +1377,34 @@ void ObClientSessionInfo::destroy_ps_id_addrs_map() ps_id_addrs_map_.reset(); } -ObTextPsNameEntry *ObClientSessionInfo::get_text_ps_name_entry(const common::ObString &text_ps_name) const +void ObClientSessionInfo::destroy_text_ps_name_entry_map() { - int ret = OB_SUCCESS; - ObTextPsNameEntry *text_ps_name_entry = NULL; - if (OB_FAIL(text_ps_name_entry_map_.get_refactored(text_ps_name, text_ps_name_entry))) { - if (OB_HASH_NOT_EXIST != ret) { - LOG_WARN("fail to get text ps name enrtry with client stmt name", K(ret), K(text_ps_name)); - } - } else if (OB_ISNULL(text_ps_name_entry)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("text ps name entry is null", K(ret), K(text_ps_name)); + ObTextPsNameEntryMap::iterator last = text_ps_name_entry_map_.end(); + ObTextPsNameEntryMap::iterator tmp_iter; + for (ObTextPsNameEntryMap::iterator ps_iter = text_ps_name_entry_map_.begin(); ps_iter != last;) { + tmp_iter = ps_iter; + ++ps_iter; + tmp_iter->destroy(); } - return text_ps_name_entry; + text_ps_name_entry_map_.reset(); } -ObTextPsEntry *ObClientSessionInfo::get_text_ps_entry(const common::ObString &text_ps_name) +void ObClientSessionInfo::destroy_sess_info_map() +{ + SessFieldHashMap::iterator last = sess_info_hash_map_.end(); + SessFieldHashMap::iterator tmp_iter; + for (SessFieldHashMap::iterator iter = sess_info_hash_map_.begin(); iter != last;) { + tmp_iter = iter; + ++iter; + int64_t total_len = tmp_iter->second.length(); + op_fixed_mem_free(tmp_iter->second.ptr(), total_len); + } + sess_info_hash_map_.destroy(); +} + +ObTextPsNameEntry *ObClientSessionInfo::get_text_ps_name_entry(const common::ObString &text_ps_name) const { int ret = OB_SUCCESS; - ObTextPsEntry *text_ps_entry = NULL; ObTextPsNameEntry *text_ps_name_entry = NULL; if (OB_FAIL(text_ps_name_entry_map_.get_refactored(text_ps_name, text_ps_name_entry))) { if (OB_HASH_NOT_EXIST != ret) { @@ -1267,26 +1413,23 @@ ObTextPsEntry *ObClientSessionInfo::get_text_ps_entry(const common::ObString &te } else if (OB_ISNULL(text_ps_name_entry)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("text ps name entry is null", K(ret), K(text_ps_name)); - } else { - text_ps_entry = text_ps_name_entry->text_ps_entry_; } - - return text_ps_entry; + return text_ps_name_entry; } int ObClientSessionInfo::add_text_ps_name_entry(ObTextPsNameEntry *text_ps_name_entry) { LOG_DEBUG("add text ps name entry", K(text_ps_name_entry->text_ps_name_)); - set_text_ps_entry(text_ps_name_entry->text_ps_entry_); - set_client_text_ps_name(text_ps_name_entry->text_ps_name_); return text_ps_name_entry_map_.unique_set(text_ps_name_entry); } -int ObClientSessionInfo::delete_text_ps_name_entry(ObTextPsNameEntry *text_ps_name_entry) +int ObClientSessionInfo::delete_text_ps_name_entry(ObString& text_ps_name) { - ObTextPsNameEntry *tmp = text_ps_name_entry_map_.remove(text_ps_name_entry->text_ps_name_); + ObTextPsNameEntry *tmp = text_ps_name_entry_map_.remove(text_ps_name); if (NULL == tmp) { - LOG_WARN("unexpected", KPC(text_ps_name_entry)); + LOG_WARN("unexpected", K(text_ps_name)); + } else { + tmp->destroy(); } return OB_SUCCESS; } diff --git a/src/obproxy/proxy/mysqllib/ob_proxy_session_info.h b/src/obproxy/proxy/mysqllib/ob_proxy_session_info.h index 9bbad103ecfc4294c62b98cbbc5752d316da813b..ec50f4f629d32fe100b91809acb6d73d621039f0 100644 --- a/src/obproxy/proxy/mysqllib/ob_proxy_session_info.h +++ b/src/obproxy/proxy/mysqllib/ob_proxy_session_info.h @@ -19,10 +19,12 @@ #include "lib/hash_func/murmur_hash.h" #include "lib/hash/ob_build_in_hashmap.h" #include "lib/hash/ob_hashset.h" +#include "lib/oblog/ob_simple_trace.h" #include "utils/ob_proxy_utils.h" #include "obutils/ob_cached_variables.h" #include "proxy/mysqllib/ob_session_field_mgr.h" #include "proxy/mysqllib/ob_proxy_auth_parser.h" +#include "proxy/mysqllib/ob_2_0_protocol_utils.h" #include "proxy/route/ob_ldc_struct.h" #include "proxy/mysql/ob_prepare_statement_struct.h" #include "proxy/mysql/ob_cursor_struct.h" @@ -33,6 +35,8 @@ #include "dbconfig/ob_proxy_db_config_info.h" #include "obutils/ob_proxy_sql_parser.h" #include "obutils/ob_proxy_json_config_info.h" +#include "proxy/mysqllib/ob_proxy_ob20_request.h" +#include "utils/ob_proxy_privilege_check.h" namespace oceanbase { @@ -45,6 +49,9 @@ class ObProxyConfigString; class ObDefaultSysVarSet; namespace proxy { +typedef common::hash::ObHashMap SessFieldHashMap; +typedef common::hash::ObHashMap SessFieldVersionHashMap; + enum ObProxyChecksumSwitch { CHECKSUM_UNUSED = -1, @@ -52,19 +59,12 @@ enum ObProxyChecksumSwitch CHECKSUM_ON, }; -enum ObProxyProtocol -{ - PROTOCOL_NORMAL = 0, - PROTOCOL_CHECKSUM, - PROTOCOL_OB20, -}; - class ObSessionVarVersion { public: - ObSessionVarVersion() { reset(); } + ObSessionVarVersion() { reset(); sess_field_version_.create(32, ObModIds::OB_PROXY_SESS_SYNC); } ~ObSessionVarVersion() { reset(); } - void reset() { memset(this, 0, sizeof(ObSessionVarVersion)); } + void reset(); void inc_common_hot_sys_var_version() { common_hot_sys_var_version_++; } void inc_common_sys_var_version() { common_sys_var_version_++; } @@ -75,10 +75,15 @@ public: void inc_user_var_version() { user_var_version_++; } void inc_db_name_version() { db_name_version_++; } void inc_last_insert_id_version() { last_insert_id_version_++; } + void inc_sess_info_version() { sess_info_version_++; } + int inc_sess_field_version(int16_t type); + SessFieldVersionHashMap& get_sess_field_version() { return sess_field_version_; } + + TO_STRING_KV(K_(common_hot_sys_var_version), K_(common_sys_var_version), K_(mysql_hot_sys_var_version), K_(mysql_sys_var_version), K_(hot_sys_var_version), K_(sys_var_version), K_(user_var_version), - K_(db_name_version), K_(last_insert_id_version)); + K_(db_name_version), K_(last_insert_id_version), K_(sess_info_version)); public: int64_t common_hot_sys_var_version_; int64_t common_sys_var_version_; @@ -89,11 +94,45 @@ public: int64_t user_var_version_; int64_t db_name_version_; int64_t last_insert_id_version_; + int64_t sess_info_version_; + SessFieldVersionHashMap sess_field_version_; private: DISALLOW_COPY_AND_ASSIGN(ObSessionVarVersion); }; + +inline int ObSessionVarVersion::inc_sess_field_version(int16_t type) +{ + int ret = OB_SUCCESS; + int64_t new_version = 0; + if (OB_FAIL(ObProxyTraceUtils::get_sess_field_version(new_version, type, sess_field_version_))) { + _PROXY_LOG(WARN, "fail to update session field versoin, query version failed, field type:%d, ret:%d",type, ret); + } + + if (OB_SUCC(ret)) { + new_version++; + if (OB_FAIL(sess_field_version_.set_refactored(type, new_version, 1))) { + _PROXY_LOG(WARN, "update session field versoin failed, field type:%d, ret:%d", type, ret); + } + } + return ret; +} + +inline void ObSessionVarVersion::reset() { + common_hot_sys_var_version_ = 0; + common_sys_var_version_ = 0; + mysql_hot_sys_var_version_ = 0; + mysql_sys_var_version_ = 0; + hot_sys_var_version_ = 0; + sys_var_version_ = 0; + user_var_version_ = 0; + db_name_version_ = 0; + last_insert_id_version_ = 0; + sess_info_version_ = 0; + sess_field_version_.clear(); +} + class ObSessionVarValHash { public: @@ -142,8 +181,24 @@ public: int update_common_sys_variable(const ObString &var_name, const ObObj &value, const bool is_need_insert, const bool is_oceanbase); void set_ob_server(const common::ObAddr &ob_server) { ob_server_ = ob_server; } - uint64_t get_ob_capability() const { return cap_; } - void set_ob_capability(const uint64_t cap) { cap_ = cap; } + + /* server session capability */ + uint64_t get_server_ob_capability() const { return cap_; } + void set_server_ob_capability(const uint64_t cap) { cap_ = cap; } + bool is_checksum_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_CHECKSUM); } + bool is_safe_read_weak_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_SAFE_WEAK_READ); } + bool is_new_partition_hit_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_PRIORITY_HIT); } + bool is_checksum_switch_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_CHECKSUM_SWITCH); } + bool is_ob_protocol_v2_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_OB_PROTOCOL_V2); } + bool is_extra_ok_packet_for_stats_enabled() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_EXTRA_OK_PACKET_FOR_STATISTICS); } + bool is_pl_route_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_PL_ROUTE); } + bool is_full_link_trace_supported() const { + return is_ob_protocol_v2_supported() && OB_TEST_CAPABILITY(cap_, OB_CAP_PROXY_FULL_LINK_TRACING); + } + bool is_new_extra_info_supported() const { + return is_ob_protocol_v2_supported() && OB_TEST_CAPABILITY(cap_, OB_CAP_PROXY_NEW_EXTRA_INFO); + } + const obmysql::ObMySQLCapabilityFlags get_compatible_capability_flags() const { // for compatible, OBServer 1479 handshake return SESSION_TRACK = 0, but still return session state info in ok packet if (is_oceanbase_server()) { @@ -155,15 +210,6 @@ public: } }; void save_compatible_capability_flags(const obmysql::ObMySQLCapabilityFlags &capability) { compatible_capability_ = capability; }; - bool is_partition_table_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_PARTITION_TABLE); } - bool is_change_user_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_CHANGE_USER); } - bool is_checksum_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_CHECKSUM); } - bool is_safe_read_weak_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_SAFE_WEAK_READ); } - bool is_new_partition_hit_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_PRIORITY_HIT); } - bool is_checksum_switch_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_CHECKSUM_SWITCH); } - bool is_ob_protocol_v2_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_OB_PROTOCOL_V2); } - bool is_extra_ok_packet_for_stats_enabled() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_EXTRA_OK_PACKET_FOR_STATISTICS); } - bool is_pl_route_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_PL_ROUTE); } const common::ObAddr &get_ob_server() const { return ob_server_;} const ObSessionVarVersion &get_session_var_version() const { return version_; } @@ -177,7 +223,8 @@ public: int64_t get_user_var_version() const { return version_.user_var_version_; } int64_t get_db_name_version() const { return version_.db_name_version_; } int64_t get_last_insert_id_version() const { return version_.last_insert_id_version_; } - + int64_t get_sess_info_version() const { return version_.sess_info_version_; } + SessFieldVersionHashMap& get_sess_field_version() { return version_.sess_field_version_; } void set_common_hot_sys_var_version(const int64_t version) { version_.common_hot_sys_var_version_ = version; } void set_common_sys_var_version(const int64_t version) { version_.common_sys_var_version_ = version; } void set_mysql_hot_sys_var_version(const int64_t version) { version_.mysql_hot_sys_var_version_ = version; } @@ -187,6 +234,7 @@ public: void set_user_var_version(const int64_t version) { version_.user_var_version_ = version; } void set_db_name_version(const int64_t version) { version_.db_name_version_ = version; } void set_last_insert_id_version(const int64_t version) { version_.last_insert_id_version_ = version; } + void set_sess_info_version(const int64_t version) { version_.sess_info_version_ = version; } ObProxyChecksumSwitch get_checksum_switch() const { return checksum_switch_; } void set_checksum_switch(const ObProxyChecksumSwitch checksum_switch) { checksum_switch_ = checksum_switch; } @@ -217,7 +265,7 @@ public: } void destroy_ps_id_pair_map(); - bool is_server_text_ps_name_exist(const uint32_t text_ps_name_id); + bool is_server_text_ps_version_exist(const uint32_t text_ps_version); int get_server_cursor_id(uint32_t client_cursor_id, uint32_t &server_cursor_id); int add_cursor_id_pair(ObCursorIdPair *cursor_id_pair) @@ -234,7 +282,9 @@ public: } } void destroy_cursor_id_pair_map(); - int add_text_ps_name(const uint32_t text_ps_name_id); + int set_text_ps_version(const int64_t text_ps_version); + int remove_text_ps_version(const int64_t text_ps_version); + void reuse_text_ps_version_set(); int get_database_name(ObString &database_name) const; int set_database_name(const common::ObString &database_name, const bool is_string_to_lower_case); @@ -261,7 +311,9 @@ public: ObSessionFieldMgr field_mgr_; ObSessionVarValHash val_hash_; private: + /* server session capability, filled in negotiation */ uint64_t cap_; + obmysql::ObMySQLCapabilityFlags compatible_capability_; common::ObAddr ob_server_; @@ -276,7 +328,7 @@ private: ObCursorIdPairMap cursor_id_pair_map_; common::ObArenaAllocator allocator_; - common::hash::ObHashSet text_ps_name_set_; + common::hash::ObHashSet text_ps_version_set_; DISALLOW_COPY_AND_ASSIGN(ObServerSessionInfo); }; @@ -304,10 +356,10 @@ inline uint32_t ObServerSessionInfo::get_server_ps_id(uint32_t client_ps_id) return server_ps_id; } -bool ObServerSessionInfo::is_server_text_ps_name_exist(const uint32_t text_ps_name_id) +bool ObServerSessionInfo::is_server_text_ps_version_exist(const uint32_t text_ps_version) { bool bret = false; - if (OB_HASH_EXIST == text_ps_name_set_.exist_refactored(text_ps_name_id)) { + if (OB_HASH_EXIST == text_ps_version_set_.exist_refactored(text_ps_version)) { bret = true; } @@ -412,15 +464,43 @@ public: bool &need_delete_cluster); void free_real_meta_cluster_name(); - uint64_t get_ob_capability() const { return cap_; } - void set_ob_capability(const uint64_t cap) { cap_ = cap; } - bool is_partition_table_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_PARTITION_TABLE); } - bool is_change_user_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_CHANGE_USER); } - bool is_checksum_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_CHECKSUM); } - bool is_read_weak_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_READ_WEAK); } - bool is_safe_read_weak_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_SAFE_WEAK_READ); } - bool is_ob_protocol_v2_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_OB_PROTOCOL_V2); } - bool is_pl_route_supported() const { return OB_TEST_CAPABILITY(cap_, OB_CAP_PL_ROUTE); } + /* client session capability */ + uint64_t get_client_ob_capability() const { return client_cap_; } + void set_client_ob_capability(const uint64_t cap) { client_cap_ = cap; } + bool is_client_support_ob20_protocol() const { return OB_TEST_CAPABILITY(client_cap_, OB_CAP_OB_PROTOCOL_V2); } + bool is_client_support_full_link_trace() const { + return is_client_support_ob20_protocol() && OB_TEST_CAPABILITY(client_cap_, OB_CAP_PROXY_FULL_LINK_TRACING); + } + bool is_client_support_new_extra_info() const { + return is_client_support_ob20_protocol() && OB_TEST_CAPABILITY(client_cap_, OB_CAP_PROXY_NEW_EXTRA_INFO); + } + + /* server session capability, filled in negotiation */ + void set_server_ob_capability(const uint64_t cap) { server_cap_ = cap; } + uint64_t get_server_ob_capability() const { return server_cap_; } + bool is_server_support_full_link_trace() const { + return OB_TEST_CAPABILITY(server_cap_, OB_CAP_OB_PROTOCOL_V2) + && OB_TEST_CAPABILITY(server_cap_, OB_CAP_PROXY_FULL_LINK_TRACING); + } + bool is_server_support_partition_table() const { + return OB_TEST_CAPABILITY(server_cap_, OB_CAP_PARTITION_TABLE); + } + bool is_server_support_read_weak() const { + return OB_TEST_CAPABILITY(server_cap_, OB_CAP_READ_WEAK); + } + bool is_server_support_safe_read_weak() const { + return OB_TEST_CAPABILITY(server_cap_, OB_CAP_SAFE_WEAK_READ); + } + bool is_server_support_pl_route() const { + return OB_TEST_CAPABILITY(server_cap_, OB_CAP_PL_ROUTE); + } + + bool is_server_support_session_var_sync() const { + return OB_TEST_CAPABILITY(server_cap_, OB_CAP_OB_PROTOCOL_V2) + && OB_TEST_CAPABILITY(server_cap_, OB_CAP_PROXY_SESSION_SYNC) + && OB_TEST_CAPABILITY(server_cap_, OB_CAP_PROXY_SESSION_VAR_SYNC); + } + bool is_oracle_mode() const { bool is_oracle_mode = false; if (is_sharding_user()) { @@ -451,6 +531,10 @@ public: int64_t get_user_var_version() const { return version_.user_var_version_; } int64_t get_db_name_version() const { return version_.db_name_version_; } int64_t get_last_insert_id_version() const { return version_.last_insert_id_version_; } + int64_t get_sess_info_version() const { return version_.sess_info_version_; } + SessFieldVersionHashMap& get_sess_field_version() { return version_.sess_field_version_; } + int inc_sess_field_version(int16_t type) { return version_.inc_sess_field_version(type); } + void set_db_name_version(const int64_t version) { version_.db_name_version_ = version; } @@ -464,6 +548,7 @@ public: int set_ldg_logical_tenant_name(const common::ObString &tenant_name); int set_logic_tenant_name(const common::ObString &logic_tenant_name); int set_logic_database_name(const common::ObString &logic_database_name); + int update_sess_sync_info(const common::ObString& sess_info, common::ObSimpleTrace<4096> &trace_log); int get_cluster_name(common::ObString &cluster_name) const; int get_tenant_name(common::ObString &tenant_name) const; int get_vip_addr_name(common::ObString &vip_addr_name) const; @@ -475,8 +560,8 @@ public: int get_ldg_logical_tenant_name(common::ObString &tenant_name) const; int get_logic_tenant_name(common::ObString &logic_tenant_name) const; int get_logic_database_name(common::ObString &logic_database_name) const; - int remove_database_name() { return field_mgr_.remove_database_name(); } + SessFieldHashMap& get_sess_info_map() { return sess_info_hash_map_; } // judge whether need reset session variables bool need_reset_database(const ObServerSessionInfo &server_info) const; @@ -491,6 +576,7 @@ public: bool need_reset_user_session_vars(const ObServerSessionInfo &server_info) const; // not include last_insert_id system variable bool need_reset_session_vars(const ObServerSessionInfo &server_info) const; + bool need_reset_sess_info_vars(const ObServerSessionInfo &server_info) const; // include all bool need_reset_all_session_vars() const { return is_global_vars_changed_; } bool is_user_idc_name_set() const { return is_user_idc_name_set_; } @@ -534,6 +620,7 @@ public: int extract_all_variable_reset_sql(common::ObSqlString &sql); int extract_variable_reset_sql(ObServerSessionInfo &server_info, common::ObSqlString &sql); + int extract_user_variable_reset_sql(ObServerSessionInfo &server_info, ObSqlString &sql); int extract_oceanbase_variable_reset_sql(ObServerSessionInfo &server_info, common::ObSqlString &sql, bool &need_reset); int extract_mysql_variable_reset_sql(ObServerSessionInfo &server_info, @@ -570,7 +657,7 @@ public: //proxy route policy ObProxyRoutePolicyEnum get_proxy_route_policy() const { return proxy_route_policy_; } - void set_proxy_route_policy(ObProxyRoutePolicyEnum policy) { + void set_proxy_route_policy(ObProxyRoutePolicyEnum policy) { proxy_route_policy_ = policy; is_proxy_route_policy_set_ = true; } @@ -581,7 +668,6 @@ public: void set_trans_specified_flag() { is_trans_specified_ = true; } void clear_trans_specified_flag() { is_trans_specified_ = false; } bool is_trans_specified() const { return is_trans_specified_; } - void set_user_identity(const ObProxyLoginUserType identity) { user_identity_ = identity; } ObProxyLoginUserType get_user_identity() const { return user_identity_; } bool enable_analyze_internal_cmd() const; @@ -629,10 +715,12 @@ public: // deep copy, this function will alloc buf int set_start_trans_sql(const common::ObString &sql); + void set_xa_start_ps_id(const int32_t ps_id) { xa_start_ps_id_ = ps_id; } // reset start trans sql, free buf void reset_start_trans_sql(); - // get start trans sql + // get start trans sql / xa start req pkt common::ObString &get_start_trans_sql() { return saved_start_trans_sql_; } + int32_t get_xa_start_ps_id() const { return xa_start_ps_id_; }; obproxy::ObDefaultSysVarSet *get_sys_var_set() { return field_mgr_.get_sys_var_set(); } void set_sysvar_set_processor(ObSysVarSetProcessor &var_set_processor) { var_set_processor_ = &var_set_processor; } @@ -694,6 +782,12 @@ public: void set_group_id(const int64_t group_id) { group_id_ = group_id; } int64_t get_group_id() { return group_id_; } + void set_table_id(const int64_t table_id) { table_id_ = table_id; } + int64_t get_table_id() { return table_id_; } + + void set_es_id(const int64_t es_id) { es_id_ = es_id; } + int64_t get_es_id() { return es_id_; } + bool is_sys_hot_version_changed() const { return hash_version_.hot_sys_var_version_ != version_.hot_sys_var_version_; } @@ -755,25 +849,15 @@ public: int get_ps_sql(common::ObString &ps_sql); bool need_do_prepare(ObServerSessionInfo &server_info) const; + // text prepare statement int add_text_ps_name_entry(ObTextPsNameEntry *text_ps_name_entry); - int delete_text_ps_name_entry(ObTextPsNameEntry *text_ps_name_entry); - - void set_text_ps_entry(ObTextPsEntry *entry) { text_ps_entry_ = entry; } - void set_client_text_ps_name(const common::ObString &text_ps_name) - { - MEMCPY(text_ps_name_buf_, text_ps_name.ptr(), text_ps_name.length()); - text_ps_name_.assign(text_ps_name_buf_, text_ps_name.length()); - } - ObTextPsEntry *get_text_ps_entry() { return text_ps_entry_; } - ObTextPsEntry *get_text_ps_entry(const common::ObString &text_ps_name); + int delete_text_ps_name_entry(common::ObString& text_ps_name); + void set_text_ps_name_entry(ObTextPsNameEntry *entry) { text_ps_name_entry_ = entry; } int get_text_ps_sql(common::ObString &sql); - const common::ObString& get_text_ps_name() const { return text_ps_name_; } bool need_do_text_ps_prepare(ObServerSessionInfo &server_info) const; - ObTextPsNameEntry *get_text_ps_name_entry(const common::ObString &text_ps_name) const; - void reset_text_ps_state() { is_text_ps_execute_ = false; } - void set_text_ps_execute(const bool is_execute) { is_text_ps_execute_ = is_execute; } - bool is_text_ps_execute() const { return is_text_ps_execute_; } + ObTextPsNameEntry *get_text_ps_name_entry() { return text_ps_name_entry_; } + void destroy_text_ps_name_entry_map(); uint32_t get_client_cursor_id() { return cursor_id_; } void set_client_cursor_id(uint32_t cursor_id) { cursor_id_ = cursor_id; } @@ -832,6 +916,22 @@ public: } } void destroy_ps_id_addrs_map(); + void destroy_sess_info_map(); + + common::ObIArray &get_request_send_addrs() { return request_send_addrs_; } + int remove_request_send_addr(const struct sockaddr &socket_addr) { + int ret = OB_SUCCESS; + net::ObIpEndpoint addr(socket_addr); + for (int64_t i = 0; OB_SUCC(ret) && i < request_send_addrs_.count(); i++) { + if (addr == request_send_addrs_.at(i)) { + if (OB_FAIL(request_send_addrs_.remove(i))) { + PROXY_LOG(WARN, "fail to remove item", K(i), K(ret)); + } + break; + } + } + return ret; + } void set_is_read_only_user(bool is_read_only_user) { @@ -850,6 +950,7 @@ public: bool is_session_pool_client_; // used for ObMysqlClient ObSessionVarVersion hash_version_; ObSessionVarValHash val_hash_; + ObProxyObProto20Request ob20_request_; // handle ob v2.0 protocol request info from client private: int load_all_cached_variable(); @@ -874,9 +975,12 @@ private: // original login capability obmysql::ObMySQLCapabilityFlags orig_capability_; - // proxy capability - uint64_t cap_; + // client session capability + uint64_t client_cap_; + // server session capability, filled in negotiation + uint64_t server_cap_; + // safe snapshot version int64_t safe_read_snapshot_; // sync safe snapshot version @@ -899,8 +1003,12 @@ private: dbconfig::ObShardUserPrivInfo up_info_; // saved start transaction sql + // saved xa start request packet (prepare execute) common::ObString saved_start_trans_sql_; + // saved xa start request's ps id + uint32_t xa_start_ps_id_; + ObProxyLoginUserType user_identity_; ObSessionVarVersion version_; // cached variables @@ -908,6 +1016,7 @@ private: // global variables version, will be set at the first time get login responce(OK packet) int64_t global_vars_version_; // obproxy_route_addr + // TODO: only support IPv4, IPv6 unsupported int64_t obproxy_route_addr_; ObSysVarSetProcessor *var_set_processor_; @@ -925,6 +1034,8 @@ private: dbconfig::ObShardConnector *shard_conn_; dbconfig::ObShardProp *shard_prop_; int64_t group_id_; + int64_t table_id_; + int64_t es_id_; bool is_allow_use_last_session_; common::ObString client_host_; @@ -941,22 +1052,23 @@ private: ObPsEntry *ps_entry_; ObPsIdEntry *ps_id_entry_; ObPsIdEntryMap ps_id_entry_map_; - common::ObString text_ps_name_; - ObTextPsEntry *text_ps_entry_; + ObTextPsNameEntry* text_ps_name_entry_; ObTextPsNameEntryMap text_ps_name_entry_map_; - bool is_text_ps_execute_; uint32_t cursor_id_; ObCursorIdAddrMap cursor_id_addr_map_; ObPsIdAddrsMap ps_id_addrs_map_; ObPieceInfoMap piece_info_map_; + common::ObSEArray request_send_addrs_; bool is_read_only_user_; bool is_request_follower_user_; char text_ps_name_buf_[common::OB_MAX_TEXT_PS_NAME_LENGTH]; + SessFieldHashMap sess_info_hash_map_; + DISALLOW_COPY_AND_ASSIGN(ObClientSessionInfo); }; @@ -1188,7 +1300,8 @@ inline bool ObClientSessionInfo::need_reset_session_vars(const ObServerSessionIn || need_reset_hot_session_vars(server_info) || need_reset_cold_session_vars(server_info) || need_reset_user_session_vars(server_info) - || need_reset_safe_read_snapshot(server_info); + || need_reset_safe_read_snapshot(server_info) + || need_reset_last_insert_id(server_info); } else { bret = need_reset_common_hot_session_vars(server_info) || need_reset_common_cold_session_vars(server_info) @@ -1199,6 +1312,16 @@ inline bool ObClientSessionInfo::need_reset_session_vars(const ObServerSessionIn return bret; } +inline bool ObClientSessionInfo::need_reset_sess_info_vars(const ObServerSessionInfo &server_info) const +{ + bool bret = false; + // TODO: Processing for sharding connection pools + bret = get_sess_info_version() > server_info.get_sess_info_version(); + PROXY_LOG(DEBUG, "need_reset_sess_info_vars", K(bret), + K(get_sess_info_version()), K(server_info.get_sess_info_version())); + return bret; +} + inline int ObClientSessionInfo::create_scramble(common::ObMysqlRandom &random) { int ret = common::OB_SUCCESS; @@ -1222,7 +1345,7 @@ inline bool ObClientSessionInfo::need_do_prepare(ObServerSessionInfo &server_inf inline bool ObClientSessionInfo::need_do_text_ps_prepare(ObServerSessionInfo &server_info) const { - return NULL != text_ps_entry_ && !server_info.is_server_text_ps_name_exist(text_ps_entry_->get_version()); + return NULL != text_ps_name_entry_ && !server_info.is_server_text_ps_version_exist(text_ps_name_entry_->version_); } int ObClientSessionInfo::get_ps_sql(common::ObString &ps_sql) @@ -1241,12 +1364,12 @@ int ObClientSessionInfo::get_ps_sql(common::ObString &ps_sql) int ObClientSessionInfo::get_text_ps_sql(common::ObString &sql) { int ret = OB_SUCCESS; - if (OB_ISNULL(text_ps_entry_)) { + if (OB_ISNULL(text_ps_name_entry_) || OB_ISNULL(text_ps_name_entry_->text_ps_entry_)) { ret = OB_ERR_UNEXPECTED; _PROXY_LOG(WARN, "text ps entry is null, ret = %d", ret); } else { - const common::ObString &tmp_sql = text_ps_entry_->get_base_ps_sql(); - sql.assign(const_cast(tmp_sql.ptr()), tmp_sql.length()); + const common::ObString &tmp_sql = text_ps_name_entry_->text_ps_entry_->get_base_ps_sql(); + sql.assign_ptr(const_cast(tmp_sql.ptr()), tmp_sql.length()); } return ret; } diff --git a/src/obproxy/proxy/mysqllib/ob_proxy_session_info_handler.cpp b/src/obproxy/proxy/mysqllib/ob_proxy_session_info_handler.cpp index b458af2b5e2dd4b94f07c3a9be2891e35e26cc00..2ffd5e9976d346dcc4da6c1383e313504de79b52 100644 --- a/src/obproxy/proxy/mysqllib/ob_proxy_session_info_handler.cpp +++ b/src/obproxy/proxy/mysqllib/ob_proxy_session_info_handler.cpp @@ -22,6 +22,11 @@ #include "obutils/ob_proxy_config.h" #include "proxy/client/ob_client_utils.h" #include "lib/encrypt/ob_encrypted_helper.h" +#include "proxy/mysql/ob_mysql_transact.h" +#include "proxy/mysqllib/ob_2_0_protocol_struct.h" +#include "proxy/mysqllib/ob_2_0_protocol_utils.h" +#include "proxy/mysql/ob_mysql_client_session.h" +#include "lib/container/ob_se_array.h" using namespace oceanbase::common; using namespace oceanbase::obmysql; @@ -44,7 +49,8 @@ int ObProxySessionInfoHandler::analyze_extra_ok_packet(ObIOBufferReader &reader, ObClientSessionInfo &client_info, ObServerSessionInfo &server_info, const bool need_handle_sysvar, - ObRespAnalyzeResult &resp_result) + ObRespAnalyzeResult &resp_result, + common::ObSimpleTrace<4096> &trace_log) { int ret = OB_SUCCESS; @@ -60,7 +66,7 @@ int ObProxySessionInfoHandler::analyze_extra_ok_packet(ObIOBufferReader &reader, LOG_WARN("fail to get ok packet", K(ret)); // save changed info } else if (OB_FAIL(save_changed_session_info(client_info, server_info, false, - need_handle_sysvar, src_ok, resp_result, false))) { + need_handle_sysvar, src_ok, resp_result, trace_log, false))) { LOG_WARN("fail to save changed session info", K(ret)); } else { LOG_DEBUG("analyze_extra_ok_packet", K(src_ok)); @@ -90,6 +96,7 @@ int ObProxySessionInfoHandler::rebuild_ok_packet(ObIOBufferReader &reader, const bool is_auth_request, const bool need_handle_sysvar, ObRespAnalyzeResult &resp_result, + common::ObSimpleTrace<4096> &trace_log, const bool is_save_to_common_sys) { int ret = OB_SUCCESS; @@ -98,31 +105,39 @@ int ObProxySessionInfoHandler::rebuild_ok_packet(ObIOBufferReader &reader, if (pkt_len > OB_SIMPLE_OK_PKT_LEN) { ObMysqlPacketReader pkt_reader; const ObMySQLCapabilityFlags cap = server_info.get_compatible_capability_flags(); + OMPKOK src_ok; int64_t offset = reader.read_avail() - pkt_len; LOG_DEBUG("rebuild_ok_packet", K(reader.read_avail()), K(pkt_len), K(offset)); // 1. get ok packet from buffer - pkt_reader.get_ok_packet(reader, offset, cap, src_ok); - // 2. save seesion info - if (OB_FAIL(save_changed_session_info(client_info, server_info, is_auth_request, - need_handle_sysvar, src_ok, resp_result, + if (OB_FAIL(pkt_reader.get_ok_packet(reader, offset, cap, src_ok))) { + LOG_WARN("fail to get ok packet", K(offset), K(ret)); + // 2. save seesion info + } else if (OB_FAIL(save_changed_session_info(client_info, + server_info, + is_auth_request, + need_handle_sysvar, + src_ok, + resp_result, + trace_log, is_save_to_common_sys))) { LOG_WARN("fail to save changed session info", K(is_auth_request), K(ret)); } else { // 3. rewrite ok packet OMPKOK des_ok; + char cap_buf[OB_MAX_UINT64_BUF_LEN]; const ObMySQLCapabilityFlags &orig_cap = client_info.get_orig_capability_flags(); - if (OB_FAIL(ObMysqlPacketRewriter::rewrite_ok_packet(src_ok, orig_cap, des_ok, - client_info.is_oracle_mode()))) { + + if (OB_FAIL(ObMysqlPacketRewriter::rewrite_ok_packet(src_ok, orig_cap, des_ok, client_info, + cap_buf, OB_MAX_UINT64_BUF_LEN, is_auth_request))) { LOG_WARN("fail to rewrite ok packet", K(src_ok), K(ret)); } else { LOG_DEBUG("rebuild_ok_packet succ", K(src_ok), "src_size", src_ok.get_serialize_size(), K(des_ok), "dst_size", des_ok.get_serialize_size()); - + // 4. trim the orig ok packet - resp_result.rewritten_last_ok_pkt_len_ = des_ok.get_serialize_size() - + MYSQL_NET_HEADER_LENGTH; + resp_result.rewritten_last_ok_pkt_len_ = des_ok.get_serialize_size() + MYSQL_NET_HEADER_LENGTH; ObMIOBuffer *writer = reader.writer(); if (OB_ISNULL(writer)) { ret = OB_ERR_UNEXPECTED; @@ -161,6 +176,7 @@ int ObProxySessionInfoHandler::rewrite_query_req_by_sharding(ObClientSessionInfo obmysql::ObMySQLCmd tmp_req_cmd = obmysql::OB_MYSQL_COM_MAX_NUM; client_request.reset(false); + client_request.set_user_identity(USER_TYPE_SHARDING); ObMysqlRequestAnalyzer::analyze_request(target_ctx, tmp_auth_req, client_request, tmp_req_cmd, status); @@ -515,8 +531,8 @@ int ObProxySessionInfoHandler::rewrite_first_login_req(ObClientSessionInfo &clie const ObAddr &client_addr, const bool use_compress, const bool use_ob_protocol_v2, - const bool use_ssl) -{ + const bool use_ssl, + const bool enable_client_ip_checkout){ int ret = OB_SUCCESS; // first login packet, which will be sent to observer at first auth // (include modified packet data and analyzed result, with -D database) @@ -525,6 +541,7 @@ int ObProxySessionInfoHandler::rewrite_first_login_req(ObClientSessionInfo &clie param.use_compress_ = use_compress; param.use_ob_protocol_v2_ = use_ob_protocol_v2; param.use_ssl_ = use_ssl; + param.enable_client_ip_checkout_ = enable_client_ip_checkout; // in the first login packet the version is set to 0, // in the saved login packet the version is set to the global vars version // observer used this value to judge whether the connection is first server session @@ -548,8 +565,8 @@ int ObProxySessionInfoHandler::rewrite_saved_login_req(ObClientSessionInfo &clie const ObAddr &client_addr, const bool use_compress, const bool use_ob_protocol_v2, - const bool use_ssl) -{ + const bool use_ssl, + const bool enable_client_ip_checkout){ int ret = OB_SUCCESS; // saved login packet, which will be sent to observer later // (include modified packet data and analyzed result, without -D database) @@ -558,6 +575,7 @@ int ObProxySessionInfoHandler::rewrite_saved_login_req(ObClientSessionInfo &clie param.use_compress_ = use_compress; param.use_ob_protocol_v2_ = use_ob_protocol_v2; param.use_ssl_ = use_ssl; + param.enable_client_ip_checkout_ = enable_client_ip_checkout; // in the first login packet the version is set to 0, // in the saved login packet the version is set to the global vars version // observer used this value to judge whether the connection is first server session @@ -591,9 +609,9 @@ inline int ObProxySessionInfoHandler::rewrite_common_login_req(ObClientSessionIn } if (param.use_ob_protocol_v2_) { - cap |= (OB_CAP_OB_PROTOCOL_V2 | OB_CAP_PROXY_REROUTE); + cap |= (OB_CAP_OB_PROTOCOL_V2 | OB_CAP_PROXY_NEW_EXTRA_INFO | OB_CAP_PROXY_REROUTE | OB_CAP_PROXY_SESSION_SYNC | OB_CAP_PROXY_SESSION_VAR_SYNC); } else { - cap &= ~(OB_CAP_OB_PROTOCOL_V2 | OB_CAP_PROXY_REROUTE); + cap &= ~(OB_CAP_OB_PROTOCOL_V2 | OB_CAP_PROXY_NEW_EXTRA_INFO | OB_CAP_PROXY_REROUTE | OB_CAP_PROXY_SESSION_SYNC | OB_CAP_PROXY_SESSION_VAR_SYNC); } param.cluster_name_ = cluster_name; @@ -620,7 +638,10 @@ inline int ObProxySessionInfoHandler::rewrite_common_login_req(ObClientSessionIn LOG_WARN("fail to rewrite_login_req", K(param), K(ret)); } else if (OB_FAIL(ObProxySessionInfoHandler::rewrite_ssl_req(client_info))) { LOG_WARN("fail to rewrite_login_req", K(ret)); + } else { + LOG_DEBUG("proxy rewrite common login req, key:__proxy_capability_flag", K(cap)); } + return ret; } @@ -689,30 +710,33 @@ inline int ObProxySessionInfoHandler::handle_global_variables_version_var( return ret; } -int ObProxySessionInfoHandler::handle_capability_flag_var( - ObClientSessionInfo &client_info, - ObServerSessionInfo &server_info, - const ObString &value, - const bool is_auth_request, - bool &need_save) +int ObProxySessionInfoHandler::handle_capability_flag_var(ObClientSessionInfo &client_info, + ObServerSessionInfo &server_info, + const ObString &value, + const bool is_auth_request, + bool &need_save) { int ret = OB_SUCCESS; - need_save = true; - int64_t cap = 0; - if (OB_FAIL(get_int_value(value, cap))) { + int64_t orig_server_cap = 0; + + if (OB_FAIL(get_int_value(value, orig_server_cap))) { LOG_WARN("fail to get int from obstring", K(value), K(ret)); } else { - uint64_t local_cap = (0 == client_info.get_ob_capability()) - ? OBPROXY_DEFAULT_CAPABILITY_FLAG - : client_info.get_ob_capability(); - uint64_t client_cap = (cap & local_cap); - uint64_t server_cap = (cap & OBPROXY_DEFAULT_CAPABILITY_FLAG); - - client_info.set_ob_capability(client_cap); - server_info.set_ob_capability(server_cap); - LOG_INFO("succ to set ob_capability_flag", K(client_cap), K(server_cap), "orgin_cap", cap, - "support_checksum", server_info.is_checksum_supported(), K(is_auth_request)); + uint64_t orig_client_cap = client_info.get_client_ob_capability(); + uint64_t client_cap = orig_client_cap & OBPROXY_DEFAULT_CAPABILITY_FLAG; + uint64_t server_cap = orig_server_cap & OBPROXY_DEFAULT_CAPABILITY_FLAG; + + server_info.set_server_ob_capability(server_cap); + client_info.set_client_ob_capability(client_cap); + client_info.set_server_ob_capability(server_cap); + + LOG_INFO("succ to set ob_capability_flag in negotiation", + K(client_cap), K(server_cap), K(orig_client_cap), K(orig_server_cap), + "client_support_ob_v2", client_info.is_client_support_ob20_protocol(), + "server_support_checksum", server_info.is_checksum_supported(), + "server_support_ob_v2", server_info.is_ob_protocol_v2_supported(), + K(is_auth_request)); } return ret; } @@ -1095,10 +1119,13 @@ int ObProxySessionInfoHandler::save_changed_session_info(ObClientSessionInfo &cl const bool need_handle_sysvar, OMPKOK &ok_pkt, ObRespAnalyzeResult &resp_result, + common::ObSimpleTrace<4096> &trace_log, const bool is_save_to_common_sys) { int ret = OB_SUCCESS; // 1. save server status + trace_log.log_it("[svr_status]", "in_trans", ok_pkt.get_server_status().status_flags_.OB_SERVER_STATUS_IN_TRANS, + "ac", ok_pkt.get_server_status().status_flags_.OB_SERVER_STATUS_AUTOCOMMIT); if (is_auth_request) { bool is_oracle_mode = 1 == ok_pkt.get_server_status().status_flags_.OB_SERVER_STATUS_RESERVED; LOG_DEBUG("will set oracle mode ", K(is_oracle_mode)); @@ -1365,6 +1392,52 @@ int ObProxySessionInfoHandler::assign_session_vars_version( return ret; } +int ObProxySessionInfoHandler::save_changed_sess_info(ObClientSessionInfo& client_info, + ObServerSessionInfo& server_info, Ob20ExtraInfo& extra_info, common::ObSimpleTrace<4096> &trace_log, bool is_only_sync_trans_sess) +{ + int ret = OB_SUCCESS; + if (extra_info.exist_sess_info()) { + ObString sess_info; + extra_info.reset_sess_info_iterate_idx(); + for (uint32_t i = 0; OB_SUCC(ret) && i < extra_info.get_sess_info_count(); i++) { + if (OB_FAIL(extra_info.get_next_sess_info(sess_info))) { + LOG_WARN("fail to update sess sync info", K(ret)); + } else if (OB_FAIL(client_info.update_sess_sync_info(sess_info, trace_log))) { + LOG_WARN("fail to update sess sync info", K(ret), K(extra_info)); + } + } + } + bool need_update_version = true; + if (OB_SUCC(ret)) { + SessFieldVersionHashMap::iterator last = client_info.get_sess_field_version().end(); + SessFieldVersionHashMap::iterator it = client_info.get_sess_field_version().begin(); + for (; it != last && OB_SUCC(ret); ++it) { + int16_t sess_info_type = it->first; + int64_t client_version = 0; + + if (OB_FAIL(ObProxyTraceUtils::get_sess_field_version(client_version , sess_info_type, client_info.get_sess_field_version()))) { + LOG_WARN("fail to set client session field version", K(ret), K(sess_info_type)); + } else if (is_only_sync_trans_sess && !ObProto20Utils::is_trans_related_sess_info(sess_info_type)) { + // internal routing trans not support sync session info idempotent + // here keep session info syncing in some case for only internal routing trans as temporary processing + int64_t server_version = 0; + if (OB_FAIL(ObProxyTraceUtils::get_sess_field_version(server_version, sess_info_type, server_info.get_sess_field_version()))) { + LOG_WARN("fail to get server session field version", K(ret), K(sess_info_type)); + } else if (client_version > server_version) { + need_update_version = false; + } + } else if (OB_FAIL(server_info.get_sess_field_version().set_refactored(sess_info_type, client_version, 1))) { + LOG_WARN("fail to set sess field versoin", K(sess_info_type), K(ret)); + } + } + } + + if (OB_SUCC(ret) && need_update_version) { + server_info.set_sess_info_version(client_info.get_sess_info_version()); + } + return ret; +} + } // end of namespace proxy } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/proxy/mysqllib/ob_proxy_session_info_handler.h b/src/obproxy/proxy/mysqllib/ob_proxy_session_info_handler.h index 0e75c058fa9bbb4082e0971452008935f0c1a819..aac0cc178096c59b4af86b45d3d807607b62a0ad 100644 --- a/src/obproxy/proxy/mysqllib/ob_proxy_session_info_handler.h +++ b/src/obproxy/proxy/mysqllib/ob_proxy_session_info_handler.h @@ -14,6 +14,8 @@ #define OBPROXY_SESSION_INFO_HANDLER_H #include "rpc/obmysql/ob_mysql_packet.h" #include "utils/ob_proxy_lib.h" +#include "proxy/mysqllib/ob_2_0_protocol_struct.h" +#include "lib/oblog/ob_simple_trace.h" namespace oceanbase { @@ -72,6 +74,7 @@ public: const bool need_handle_sysvar, obmysql::OMPKOK &ok_pkt, ObRespAnalyzeResult &resp_result, + common::ObSimpleTrace<4096> &trace_log, const bool is_save_to_common_sys = false); // The @reader must has only one receive completed ok packet, @@ -84,13 +87,15 @@ public: const bool is_auth_request, const bool need_handle_sysvar, ObRespAnalyzeResult &resp_result, - const bool is_save_to_common_sys = false); + common::ObSimpleTrace<4096> &trace_log, + const bool is_save_to_common_sys); static int analyze_extra_ok_packet(event::ObIOBufferReader &reader, ObClientSessionInfo &client_info, ObServerSessionInfo &server_info, const bool need_handle_sysvar, - ObRespAnalyzeResult &resp_result); + ObRespAnalyzeResult &resp_result, + common::ObSimpleTrace<4096> &trace_log); static int rewrite_query_req_by_sharding(ObClientSessionInfo &client_info, ObProxyMysqlRequest &client_request, @@ -122,8 +127,8 @@ public: const common::ObAddr &client_addr, const bool use_compress, const bool use_ob_protocol_v2, - const bool use_ssl); - + const bool use_ssl, + const bool enable_client_ip_checkout); static int rewrite_saved_login_req(ObClientSessionInfo &client_info, const common::ObString &cluster_name, const int64_t cluster_id, @@ -134,8 +139,8 @@ public: const common::ObAddr &client_addr, const bool use_compress, const bool use_ob_protocol_v2, - const bool use_ssl); - + const bool use_ssl, + const bool enable_client_ip_checkout); static int rewrite_common_login_req(ObClientSessionInfo &client_info, ObHandshakeResponseParam ¶m, const int64_t global_vars_version, @@ -168,6 +173,11 @@ public: const common::ObString &value, const bool is_auth_request, bool &need_save); + static int save_changed_sess_info(ObClientSessionInfo& client_info, + ObServerSessionInfo& server_info, + Ob20ExtraInfo& extra_info, + common::ObSimpleTrace<4096> &trace_log, + bool is_only_sync_trans_sess); private: static ObProxySysVarType get_sys_var_type(const common::ObString &var_name); @@ -235,7 +245,6 @@ private: const obmysql::ObStringKV &str_kv, const bool is_auth_request, ObRespAnalyzeResult &resp_result); - }; } // end of namespace proxy diff --git a/src/obproxy/proxy/mysqllib/ob_resultset_fetcher.h b/src/obproxy/proxy/mysqllib/ob_resultset_fetcher.h index 465b246a2127ffde97e7e85d7e983e600bed3f87..a188b38a5e61270776212dbf937ff3f18a3cc277 100644 --- a/src/obproxy/proxy/mysqllib/ob_resultset_fetcher.h +++ b/src/obproxy/proxy/mysqllib/ob_resultset_fetcher.h @@ -45,6 +45,7 @@ } \ } +// limit max length #define PROXY_EXTRACT_STRBUF_FIELD_MYSQL(result, column_name, field, max_length, real_length) \ if (OB_SUCCESS == ret) { \ ObString str_value; \ @@ -66,6 +67,27 @@ } \ } +// unlimit max length +#define PROXY_EXTRACT_STRBUF_FIELD_MYSQL_UNLIMIT_LENGTH(result, column_name, field, real_length, allocator) \ +if (OB_SUCCESS == ret) { \ + ObString str_value; \ + if (OB_SUCCESS == (ret = (result).get_varchar(column_name, str_value))) { \ + if (str_value.empty()) { \ + real_length = 0; \ + field = NULL; \ + } else if (OB_ISNULL(field = static_cast(allocator.alloc(str_value.length() + 1)))) { \ + ret = OB_ALLOCATE_MEMORY_FAILED; \ + LOG_WARN("fail to allc part key name", K(field), K(str_value.length()), K(ret)); \ + } else { \ + MEMCPY(field, str_value.ptr(), str_value.length()); \ + real_length = str_value.length(); \ + field[str_value.length()] = '\0'; \ + } \ + } else { \ + PROXY_LOG(WARN, "fail to extract strbuf field mysql", K(column_name), K(real_length), K(ret)); \ + } \ +} + namespace oceanbase { namespace common diff --git a/src/obproxy/proxy/mysqllib/ob_session_field_mgr.h b/src/obproxy/proxy/mysqllib/ob_session_field_mgr.h index cbe099568314168c677661efa394a8a277b5b5a7..7d21e0cfb24dc3a19b0b98e0433ef1a6d58d7b8c 100644 --- a/src/obproxy/proxy/mysqllib/ob_session_field_mgr.h +++ b/src/obproxy/proxy/mysqllib/ob_session_field_mgr.h @@ -108,10 +108,10 @@ enum ObSessionFieldStat enum ObSessionVarType { - OB_SESSION_USER_VAR = 0, - OB_SESSION_SYS_VAR, - OB_SESSION_COMMON_SYS_VAR, - OB_SESSION_MYSQL_SYS_VAR, + OB_SESSION_USER_VAR = 0, // user variable + OB_SESSION_SYS_VAR, // system variable only oceanbase supported + OB_SESSION_COMMON_SYS_VAR, // system variable oceanbase and mysql both supported + OB_SESSION_MYSQL_SYS_VAR, // system variable only mysql supported OB_SESSION_VAR_MAX, }; diff --git a/src/obproxy/proxy/plugins/Makemodule.am b/src/obproxy/proxy/plugins/Makemodule.am index ee07f45cc543ad43394097236fca72e7cdf080fe..cec8138feaf85ff78fff2826d5de5407ff04ee53 100644 --- a/src/obproxy/proxy/plugins/Makemodule.am +++ b/src/obproxy/proxy/plugins/Makemodule.am @@ -12,4 +12,6 @@ obproxy/proxy/plugins/ob_mysql_request_execute_transform_plugin.h\ obproxy/proxy/plugins/ob_mysql_response_cursor_transform_plugin.cpp\ obproxy/proxy/plugins/ob_mysql_response_cursor_transform_plugin.h\ obproxy/proxy/plugins/ob_mysql_response_new_ps_transform_plugin.cpp\ -obproxy/proxy/plugins/ob_mysql_response_new_ps_transform_plugin.h +obproxy/proxy/plugins/ob_mysql_response_new_ps_transform_plugin.h\ +obproxy/proxy/plugins/ob_mysql_response_ob20_transform_plugin.h\ +obproxy/proxy/plugins/ob_mysql_response_ob20_transform_plugin.cpp diff --git a/src/obproxy/proxy/plugins/ob_mysql_request_compress_transform_plugin.cpp b/src/obproxy/proxy/plugins/ob_mysql_request_compress_transform_plugin.cpp index 2e4fb4464c943899b3bbbc7f1b528d5c75c8b767..d886b6129ecdd7b78aaa0ac108b863cbc3f08de2 100644 --- a/src/obproxy/proxy/plugins/ob_mysql_request_compress_transform_plugin.cpp +++ b/src/obproxy/proxy/plugins/ob_mysql_request_compress_transform_plugin.cpp @@ -131,31 +131,32 @@ int ObMysqlRequestCompressTransformPlugin::build_compressed_packet(bool is_last_ const bool is_need_reroute = false; //large request don't save, so can't reroute; // local_reader_ will consume in consume_and_compress_data(), // compressed_seq_ will inc in consume_and_compress_data - ObProxyProtocol ob_proxy_protocol = sm_->use_compression_protocol(); - if (PROTOCOL_OB20 == ob_proxy_protocol) { + ObProxyProtocol ob_proxy_protocol = sm_->get_server_session_protocol(); + if (ObProxyProtocol::PROTOCOL_OB20 == ob_proxy_protocol) { if (request_id_ > UINT24_MAX) { request_id_ = sm_->get_server_session()->get_next_server_request_id(); } - ObSEArray extro_info; + ObSEArray extra_info; + ObSqlString sess_info_value; char client_ip_buf[MAX_IP_BUFFER_LEN] = "\0"; - ObMysqlClientSession *client_session = sm_->get_client_session(); - if (!client_session->is_proxy_mysql_client_ - && client_session->is_need_send_trace_info() - && is_last_segment) { - ObAddr client_ip = client_session->get_real_client_addr(); - if (OB_FAIL(ObProxyTraceUtils::build_client_ip(extro_info, client_ip_buf, client_ip))) { - PROXY_API_LOG(WARN, "fail to build client ip", K(client_ip), K(ret)); - } else { - client_session->set_already_send_trace_info(true); - } - } - - if (OB_SUCC(ret)) { - if (OB_FAIL(ObProto20Utils::consume_and_compress_data(local_reader_, - mio_buffer_, local_reader_->read_avail(), compressed_seq_, - compressed_seq_, request_id_, sm_->get_server_session()->get_server_sessid(), - is_last_segment, is_need_reroute, &extro_info))) { + char server_extra_info_buf[SERVER_EXTRA_INFO_BUF_MAX_LEN] = "\0"; + + if (OB_FAIL(ObProxyTraceUtils::build_related_extra_info_all(extra_info, sm_, + client_ip_buf, MAX_IP_BUFFER_LEN, + server_extra_info_buf, SERVER_EXTRA_INFO_BUF_MAX_LEN, + sess_info_value, is_last_segment))) { + PROXY_API_LOG(WARN, "fail to build related extra info all", K(ret)); + } else { + ObMysqlServerSession *server_session = sm_->get_server_session(); + ObMysqlClientSession *client_session = sm_->get_client_session(); + const bool is_weak_read = (WEAK == sm_->trans_state_.get_trans_consistency_level(client_session->get_session_info())); + Ob20ProtocolHeaderParam ob20_head_param(server_session->get_server_sessid(), request_id_, compressed_seq_, + compressed_seq_, is_last_segment, is_weak_read, is_need_reroute, + server_session->get_session_info().is_new_extra_info_supported(), + client_session->is_trans_internal_routing()); + if (OB_FAIL(ObProto20Utils::consume_and_compress_data(local_reader_, mio_buffer_, local_reader_->read_avail(), + ob20_head_param, &extra_info))) { PROXY_API_LOG(WARN, "fail to consume and compress data with OB20", K(ret)); } } @@ -209,8 +210,8 @@ int ObMysqlRequestCompressTransformPlugin::check_last_data_segment( if (read_avail >= (ntodo + MYSQL_NET_META_LENGTH)) { char tmp_buff[MYSQL_NET_META_LENGTH]; // print the next packet's meta reader.copy(tmp_buff, MYSQL_NET_META_LENGTH, ntodo); - int64_t payload_len = ob_uint3korr(tmp_buff); - int64_t seq = ob_uint1korr(tmp_buff + 3); + int64_t payload_len = uint3korr(tmp_buff); + int64_t seq = uint1korr(tmp_buff + 3); int64_t cmd = static_cast(tmp_buff[4]); PROXY_API_LOG(ERROR, "next packet meta is", K(payload_len), K(seq), K(cmd)); } diff --git a/src/obproxy/proxy/plugins/ob_mysql_request_compress_transform_plugin.h b/src/obproxy/proxy/plugins/ob_mysql_request_compress_transform_plugin.h index f586fffd0db6fb45ddeef5056f1cee5552b1255e..6a463892aec77fe2b883226ee879b0ef8c03e19d 100644 --- a/src/obproxy/proxy/plugins/ob_mysql_request_compress_transform_plugin.h +++ b/src/obproxy/proxy/plugins/ob_mysql_request_compress_transform_plugin.h @@ -101,10 +101,10 @@ public: PROXY_API_LOG(DEBUG, "need_enable_plugin", "request_content_length", sm->trans_state_.trans_info_.request_content_length_, "enable_compression_protocol", sm->trans_state_.mysql_config_params_->enable_compression_protocol_, - "enable_ob_protocol_v2", sm->trans_state_.mysql_config_params_->enable_ob_protocol_v2_); + "enable_ob_protocol_v2", sm->is_enable_ob_protocol_v2()); return (sm->trans_state_.trans_info_.request_content_length_ > 0 && (sm->trans_state_.mysql_config_params_->enable_compression_protocol_ - || sm->trans_state_.mysql_config_params_->enable_ob_protocol_v2_)); + || sm->is_enable_ob_protocol_v2())); } private: diff --git a/src/obproxy/proxy/plugins/ob_mysql_request_prepare_transform_plugin.cpp b/src/obproxy/proxy/plugins/ob_mysql_request_prepare_transform_plugin.cpp index 0ae0bb47f69a334fcfd422355c0a5dfc89615044..e5465daa658ddd0a5087d5ba16670b574ee547d4 100644 --- a/src/obproxy/proxy/plugins/ob_mysql_request_prepare_transform_plugin.cpp +++ b/src/obproxy/proxy/plugins/ob_mysql_request_prepare_transform_plugin.cpp @@ -89,7 +89,7 @@ int ObMysqlRequestPrepareTransformPlugin::consume(event::ObIOBufferReader *reade OB_FAIL(handle_ps_prepare())) { PROXY_API_LOG(WARN, "fail to handle ps prepare", K(ret)); } else if (sm_->trans_state_.trans_info_.client_request_.get_parse_result().is_text_ps_prepare_stmt() - && handle_text_ps_prepare()) { + && OB_FAIL(handle_text_ps_prepare())) { PROXY_API_LOG(WARN, "fail to handle text ps prepare", K(ret)); } } @@ -143,52 +143,12 @@ int ObMysqlRequestPrepareTransformPlugin::handle_ps_prepare() int ObMysqlRequestPrepareTransformPlugin::handle_text_ps_prepare() { int ret = OB_SUCCESS; - ObClientSessionInfo &session_info = sm_->get_client_session()->get_session_info(); - ObProxyMysqlRequest &client_request = sm_->trans_state_.trans_info_.client_request_; ObString text_ps_sql; text_ps_sql.assign_ptr(ps_or_text_ps_sql_buf_ + MYSQL_NET_META_LENGTH, static_cast(ps_pkt_len_ - MYSQL_NET_META_LENGTH)); - ObTextPsEntry *text_ps_entry = sm_->get_client_session()->get_text_ps_entry(text_ps_sql); - ObTextPsNameEntry *text_ps_name_entry = session_info.get_text_ps_name_entry(text_ps_sql); - - if (NULL == text_ps_entry) { - if (OB_FAIL(ObTextPsEntry::alloc_and_init_text_ps_entry( - text_ps_sql, client_request.get_parse_result(), text_ps_entry))) { - PROXY_API_LOG(WARN, "fail to alloc and init text ps entry", K(ret)); - } else if (OB_FAIL(sm_->get_client_session()->add_text_ps_entry(text_ps_entry))) { - PROXY_API_LOG(WARN, "fail to add text ps entry to cache", K(ret)); - if (OB_LIKELY(NULL != text_ps_entry)) { - text_ps_entry->destroy(); - text_ps_entry = NULL; - } - } else if (OB_FAIL(ObTextPsNameEntry::alloc_text_ps_name_entry( - client_request.get_parse_result().get_text_ps_name(), - text_ps_entry, text_ps_name_entry))) { - PROXY_API_LOG(WARN, "fail to alloc text ps name entry", K(ret)); - } else if (OB_FAIL(session_info.add_text_ps_name_entry(text_ps_name_entry))) { - PROXY_API_LOG(WARN, "fail to add text ps name entry", KPC(text_ps_entry), K(ret)); - if (OB_LIKELY(NULL != text_ps_name_entry)) { - text_ps_name_entry->destroy(); - text_ps_name_entry = NULL; - } - } - } else if (NULL == text_ps_name_entry) { - if (OB_FAIL(ObTextPsNameEntry::alloc_text_ps_name_entry( - client_request.get_parse_result().get_text_ps_name(), - text_ps_entry, text_ps_name_entry))) { - PROXY_API_LOG(WARN, "fail to alloc text ps name entry", K(ret)); - } else if (OB_FAIL(session_info.add_text_ps_name_entry(text_ps_name_entry))) { - PROXY_API_LOG(WARN, "fail to add text ps name entry", KPC(text_ps_name_entry), K(ret)); - if (OB_LIKELY(NULL != text_ps_name_entry)) { - text_ps_name_entry->destroy(); - text_ps_name_entry = NULL; - } - } - } - - if (OB_SUCC(ret)) { - session_info.set_text_ps_entry(text_ps_name_entry->text_ps_entry_); - session_info.set_client_text_ps_name(client_request.get_parse_result().get_text_ps_name()); + if (OB_FAIL(sm_->do_analyze_text_ps_prepare_request(text_ps_sql))) { + PROXY_API_LOG(WARN, "fail to do_analyze_text_ps_prepare_request", K(text_ps_sql), K(ret)); } + return ret; } @@ -219,8 +179,8 @@ int ObMysqlRequestPrepareTransformPlugin::check_last_data_segment( if (read_avail >= (ntodo + MYSQL_NET_META_LENGTH)) { char tmp_buff[MYSQL_NET_META_LENGTH]; // print the next packet's meta reader.copy(tmp_buff, MYSQL_NET_META_LENGTH, ntodo); - int64_t payload_len = ob_uint3korr(tmp_buff); - int64_t seq = ob_uint1korr(tmp_buff + 3); + int64_t payload_len = uint3korr(tmp_buff); + int64_t seq = uint1korr(tmp_buff + 3); int64_t cmd = static_cast(tmp_buff[4]); PROXY_API_LOG(ERROR, "next packet meta is", K(payload_len), K(seq), K(cmd)); } diff --git a/src/obproxy/proxy/plugins/ob_mysql_response_compress_transform_plugin.cpp b/src/obproxy/proxy/plugins/ob_mysql_response_compress_transform_plugin.cpp index 397ccbbe05b0719479872d462d44423bab69618c..ea4105a56c4e78f9d7088026452c80f0ec46d773 100644 --- a/src/obproxy/proxy/plugins/ob_mysql_response_compress_transform_plugin.cpp +++ b/src/obproxy/proxy/plugins/ob_mysql_response_compress_transform_plugin.cpp @@ -34,10 +34,10 @@ ObMysqlResponseCompressTransformPlugin::ObMysqlResponseCompressTransformPlugin(O local_reader_(NULL), local_transfer_reader_(NULL), compress_analyzer_(), compress_ob20_analyzer_(), analyzer_(NULL) { - ObProxyProtocol ob_proxy_protocol = sm_->use_compression_protocol(); - if (ob_proxy_protocol == PROTOCOL_CHECKSUM) { + ObProxyProtocol ob_proxy_protocol = sm_->get_server_session_protocol(); + if (ob_proxy_protocol == ObProxyProtocol::PROTOCOL_CHECKSUM) { analyzer_ = &compress_analyzer_; - } else if (ob_proxy_protocol == PROTOCOL_OB20) { + } else if (ob_proxy_protocol == ObProxyProtocol::PROTOCOL_OB20) { analyzer_ = &compress_ob20_analyzer_; } @@ -108,6 +108,9 @@ int ObMysqlResponseCompressTransformPlugin::consume(event::ObIOBufferReader *rea int64_t plugin_decompress_response_end = sm_->get_based_hrtime(); sm_->cmd_time_stats_.plugin_decompress_response_time_ += milestone_diff(plugin_decompress_response_begin, plugin_decompress_response_end); + + // save flt from response analyze result to sm + sm_->save_response_flt_result_to_sm(server_response.get_analyze_result().flt_); } } @@ -134,16 +137,46 @@ int ObMysqlResponseCompressTransformPlugin::consume(event::ObIOBufferReader *rea sm_->trans_state_.current_.state_ = ObMysqlTransact::CMD_COMPLETE; } + if (analyze_result.is_trans_completed() || analyze_result.is_resp_completed()) { + if (sm_->enable_record_full_link_trace_info()) { + trace::ObSpanCtx *ctx = sm_->flt_.trace_log_info_.server_response_read_ctx_; + if (OB_NOT_NULL(ctx)) { + PROXY_API_LOG(DEBUG, "end span ob_proxy_server_response_read", K(ctx->span_id_)); + SET_TRACE_BUFFER(sm_->flt_trace_buffer_, MAX_TRACE_LOG_SIZE); + FLT_END_SPAN(ctx); + sm_->flt_.trace_log_info_.server_response_read_ctx_ = NULL; + } + } + } + // get consume size again, for trim the last packet consume_size = local_transfer_reader_->read_avail() - analyze_result.get_reserved_len_for_ob20_ok(); - // just send all data in local_transfer_reader_ - if (consume_size != (produce_size = produce(local_transfer_reader_, consume_size))) { - ret = OB_ERR_UNEXPECTED; - PROXY_API_LOG(WARN, "fail to produce", "expected size", consume_size, - "actual size", produce_size, K(ret)); - } else if (OB_FAIL(local_transfer_reader_->consume(consume_size))) { - PROXY_API_LOG(WARN, "fail to consume local transfer reader", K(consume_size), K(ret)); + // Here is a situation: + // under the 2.0 protocol, the last 4 tail checksum bytes were not read, + // but the Tunnel sent all the MySQL content. + // For ClientVC, after receiving all MySQL content, + // it does not judge the end of the response based on the content, + // but judges based on write_state_.vio_.ntodo(), + // but because Tunnel has not read the last 4 tail checksum bytes, + // Tunnel will not modify nbytes in ntodo, + // causing ClientVC to think Have not finished receiving, continue to wait, do not continue to process. + // After the Tunnel receives the last 4 tail checksum bytes, + // since these 4 bytes are not sent to the Client, + // the Client VC will not be triggered again. + // As a result, the Tunnel ends directly, and the ClientVC How Hung lives + // + // Therefore, it is modified here that if the entire Tunnel is not over, + // the last bit of MySQL packet content will not be sent, and will not be sent until the entire Tunnel is over + if (!analyze_result.is_last_ok_handled() || analyzer_->is_stream_finished()) { + // just send all data in local_transfer_reader_ + if (consume_size != (produce_size = produce(local_transfer_reader_, consume_size))) { + ret = OB_ERR_UNEXPECTED; + PROXY_API_LOG(WARN, "fail to produce", "expected size", consume_size, + "actual size", produce_size, K(ret)); + } else if (OB_FAIL(local_transfer_reader_->consume(consume_size))) { + PROXY_API_LOG(WARN, "fail to consume local transfer reader", K(consume_size), K(ret)); + } } } } diff --git a/src/obproxy/proxy/plugins/ob_mysql_response_compress_transform_plugin.h b/src/obproxy/proxy/plugins/ob_mysql_response_compress_transform_plugin.h index 3e2d001a665fe37beb3972abeaf29ca2cf6cc317..d2c24835305412d8c2cd63dd4b384e17b0387c9d 100644 --- a/src/obproxy/proxy/plugins/ob_mysql_response_compress_transform_plugin.h +++ b/src/obproxy/proxy/plugins/ob_mysql_response_compress_transform_plugin.h @@ -95,12 +95,10 @@ public: { return (!sm->trans_state_.trans_info_.client_request_.is_internal_cmd() && NULL != sm->client_session_ - // inner sql will received compeleted, no need plugin - && !sm->client_session_->is_proxy_mysql_client_ && ObMysqlTransact::SERVER_SEND_REQUEST == sm->trans_state_.current_.send_action_ && !sm->trans_state_.trans_info_.server_response_.get_analyze_result().is_decompressed() - && (PROTOCOL_CHECKSUM == sm->use_compression_protocol() - || PROTOCOL_OB20 == sm->use_compression_protocol())); + && (ObProxyProtocol::PROTOCOL_CHECKSUM == sm->get_server_session_protocol() + || ObProxyProtocol::PROTOCOL_OB20 == sm->get_server_session_protocol())); } private: diff --git a/src/obproxy/proxy/plugins/ob_mysql_response_cursor_transform_plugin.cpp b/src/obproxy/proxy/plugins/ob_mysql_response_cursor_transform_plugin.cpp index c0efbe4a3bb2d2f331ca1d1d18037973efd3d562..5850cb3841e32ae5b4bec28a804e0393f0db0a8b 100644 --- a/src/obproxy/proxy/plugins/ob_mysql_response_cursor_transform_plugin.cpp +++ b/src/obproxy/proxy/plugins/ob_mysql_response_cursor_transform_plugin.cpp @@ -202,7 +202,8 @@ int ObMysqlResponseCursorTransformPlugin::handle_resultset_row(event::ObIOBuffer if (hava_cursor) { ObNewRow row; - OMPKRow row_packet(ObSMRow(BINARY, row)); + ObSMRow sm_row(BINARY, row); + OMPKRow row_packet(sm_row); packet::ObMysqlPacketReader pkt_reader; if (OB_FAIL(pkt_reader.get_packet(*reader, row_packet))) { PROXY_API_LOG(ERROR, "fail to get filed packet from reader", K(ret)); @@ -342,6 +343,7 @@ int ObMysqlResponseCursorTransformPlugin::skip_field_value(const char *&data, in break; } case OB_MYSQL_TYPE_GEOMETRY: + case OB_MYSQL_TYPE_JSON: case OB_MYSQL_TYPE_BLOB: case OB_MYSQL_TYPE_LONG_BLOB: case OB_MYSQL_TYPE_MEDIUM_BLOB: @@ -361,6 +363,7 @@ int ObMysqlResponseCursorTransformPlugin::skip_field_value(const char *&data, in case OB_MYSQL_TYPE_STRING: case OB_MYSQL_TYPE_VARCHAR: case OB_MYSQL_TYPE_VAR_STRING: + case OB_MYSQL_TYPE_OB_UROWID: case OB_MYSQL_TYPE_DECIMAL: case OB_MYSQL_TYPE_NEWDECIMAL: { uint64_t length = 0; diff --git a/src/obproxy/proxy/plugins/ob_mysql_response_cursor_transform_plugin.h b/src/obproxy/proxy/plugins/ob_mysql_response_cursor_transform_plugin.h index 581b2a5c71e223bb91cc27c0f816015c0c81ccf4..464c0a2f8983ddaac53ab1ca4538af5e3d0c6843 100644 --- a/src/obproxy/proxy/plugins/ob_mysql_response_cursor_transform_plugin.h +++ b/src/obproxy/proxy/plugins/ob_mysql_response_cursor_transform_plugin.h @@ -115,9 +115,9 @@ public: { return (!sm->trans_state_.trans_info_.client_request_.is_internal_cmd() && ObMysqlTransact::SERVER_SEND_REQUEST == sm->trans_state_.current_.send_action_ - && (obmysql::OB_MYSQL_COM_STMT_EXECUTE == sm->trans_state_.trans_info_.sql_cmd_ - && sm->trans_state_.trans_info_.client_request_.get_parse_result().is_call_stmt() - && sm->trans_state_.trans_info_.server_response_.get_analyze_result().is_resultset_resp())); + && obmysql::OB_MYSQL_COM_STMT_EXECUTE == sm->trans_state_.trans_info_.sql_cmd_ + && !sm->trans_state_.trans_info_.client_request_.get_parse_result().is_dml_stmt() + && sm->trans_state_.trans_info_.server_response_.get_analyze_result().is_resultset_resp()); } private: diff --git a/src/obproxy/proxy/plugins/ob_mysql_response_ob20_transform_plugin.cpp b/src/obproxy/proxy/plugins/ob_mysql_response_ob20_transform_plugin.cpp new file mode 100644 index 0000000000000000000000000000000000000000..613690e2e6dfe98fb36d5e9b222d2163b25c05c2 --- /dev/null +++ b/src/obproxy/proxy/plugins/ob_mysql_response_ob20_transform_plugin.cpp @@ -0,0 +1,260 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ +#define USING_LOG_PREFIX PROXY + +#include "lib/oblog/ob_log.h" +#include "ob_mysql_response_ob20_transform_plugin.h" +#include "obutils/ob_resource_pool_processor.h" +#include "proxy/mysqllib/ob_2_0_protocol_utils.h" +#include "proxy/mysqllib/ob_2_0_protocol_struct.h" + +using namespace oceanbase::common; +using namespace oceanbase::obproxy::event; + + +namespace oceanbase +{ +namespace obproxy +{ +namespace proxy +{ + +ObMysqlResponseOb20ProtocolTransformPlugin *ObMysqlResponseOb20ProtocolTransformPlugin::alloc(ObApiTransaction &transaction) +{ + return op_reclaim_alloc_args(ObMysqlResponseOb20ProtocolTransformPlugin, transaction); +} + +ObMysqlResponseOb20ProtocolTransformPlugin::ObMysqlResponseOb20ProtocolTransformPlugin(ObApiTransaction &transaction) + : ObTransformationPlugin(transaction, ObTransformationPlugin::RESPONSE_TRANSFORMATION), + tail_crc_(0), target_payload_len_(0), handled_payload_len_(0), state_(OB20_PLUGIN_INIT_STATE), + local_reader_(NULL), out_buffer_(NULL), out_buffer_reader_(NULL) +{ + PROXY_API_LOG(DEBUG, "ObMysqlResponseOb20ProtocolTransformPlugin born", K(this)); +} + +void ObMysqlResponseOb20ProtocolTransformPlugin::destroy() +{ + PROXY_API_LOG(DEBUG, "ObMysqlResponseOb20ProtocolTransformPlugin destroy"); + ObTransformationPlugin::destroy(); + op_reclaim_free(this); +} + +// process the packet while handling the io buffer reader +int ObMysqlResponseOb20ProtocolTransformPlugin::consume(event::ObIOBufferReader *reader) +{ + int ret = OB_SUCCESS; + bool is_resp_finished = sm_->trans_state_.trans_info_.server_response_.get_analyze_result().is_resp_completed(); + + PROXY_API_LOG(DEBUG, "ObMysqlResponseOb20ProtocolTransformPlugin::consume begin", K(is_resp_finished), K(state_)); + + if (state_ == OB20_PLUGIN_INIT_STATE) { + if (OB_FAIL(alloc_iobuffer_inner(reader))) { + LOG_WARN("fail to alloc iobuffer inner", K(ret)); + } else { + int64_t total_avail = local_reader_->read_avail(); + target_payload_len_ = total_avail; + LOG_DEBUG("set total payload len in ob20 resp", K(target_payload_len_)); + } + } + + if (OB_SUCC(ret) && state_ == OB20_PLUGIN_INIT_STATE && target_payload_len_ > 0) { + ObSEArray extra_info; + char client_extra_info_buf[CLIENT_EXTRA_INFO_BUF_MAX_LEN] = "\0"; + if (OB_FAIL(ObProxyTraceUtils::build_extra_info_for_client(sm_, client_extra_info_buf, + CLIENT_EXTRA_INFO_BUF_MAX_LEN, extra_info))) { + LOG_WARN("fail to build extra info for client", K(ret)); + } else if (OB_FAIL(build_ob20_head_and_extra(out_buffer_, extra_info, is_resp_finished))) { + LOG_WARN("fail to build ob20 head and extra", K(ret)); + } else { + int64_t local_reader_avail = local_reader_->read_avail(); + int64_t could_write_max = MIN(local_reader_avail, target_payload_len_); // more than MYSQL_NET_HEADER_LENGTH + if (OB_FAIL(build_ob20_body(local_reader_, local_reader_avail, out_buffer_, could_write_max, tail_crc_))) { + LOG_WARN("fail to build ob20 body", K(ret)); + } else if (OB_UNLIKELY(handled_payload_len_ > target_payload_len_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected err, handled len > target len", K(ret), K(handled_payload_len_), K(target_payload_len_)); + } else if (handled_payload_len_ == target_payload_len_) { + state_ = OB20_PLUGIN_FIN_STATE; + } else { + state_ = OB20_PLUGIN_CONT_STATE; // handled mysql len < target mysql len, continue + } + } + } + + if (OB_SUCC(ret) && state_ == OB20_PLUGIN_CONT_STATE) { + // build body as much as possible + int64_t local_reader_avail = local_reader_->read_avail(); + int64_t could_write_max = MIN(local_reader_avail, target_payload_len_ - handled_payload_len_); + if (OB_FAIL(build_ob20_body(local_reader_, local_reader_avail, out_buffer_, could_write_max, tail_crc_))) { + LOG_WARN("fail to build ob20 body", K(ret)); + } else if (OB_UNLIKELY(handled_payload_len_ > target_payload_len_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected handle > target len", K(ret), K(handled_payload_len_), K(target_payload_len_)); + } else if (handled_payload_len_ == target_payload_len_) { + state_ = OB20_PLUGIN_FIN_STATE; + } else { + // handled len < target len, continue + } + } + + if (OB_SUCC(ret) && state_ == OB20_PLUGIN_FIN_STATE) { + if (OB_FAIL(ObProto20Utils::fill_proto20_tailer(out_buffer_, tail_crc_))) { + LOG_WARN("fail to build ob20 tail crc", K(ret)); + } + } + + if (OB_SUCC(ret) && state_ != OB20_PLUGIN_INIT_STATE) { + int64_t avail_size = out_buffer_reader_->read_avail(); + int64_t produce_size = 0; + if (avail_size != (produce_size = produce(out_buffer_reader_, avail_size))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to produce to VIO", K(ret), K(avail_size), K(produce_size)); + } else if (OB_FAIL(out_buffer_reader_->consume(avail_size))) { + LOG_WARN("fail to consume out buffer reader", K(ret), K(avail_size)); + } else if (state_ == OB20_PLUGIN_FIN_STATE) { + state_ = OB20_PLUGIN_INIT_STATE; + reset(); + LOG_DEBUG("finish this ob20 response back to client"); + } + } + + if (OB_FAIL(ret)) { + reset(); + sm_->trans_state_.inner_errcode_ = ret; + sm_->trans_state_.current_.state_ = ObMysqlTransact::INTERNAL_ERROR; + LOG_WARN("fail to consume in ob20 response transform plugin", K(ret)); + } + + return ret; +} + +int ObMysqlResponseOb20ProtocolTransformPlugin::build_ob20_head_and_extra(ObMIOBuffer *write_buf, + ObIArray &extra_info, + bool is_last_packet) +{ + int ret = OB_SUCCESS; + + // total mysql len in ob20 response payload + int64_t payload_len = target_payload_len_; // msyql + (4 + extra_info_len() if exist) + char *head_start = NULL; + if (OB_FAIL(ObProto20Utils::reserve_proto20_hdr(write_buf, head_start))) { + LOG_WARN("fail to reserve ob20 head", K(ret)); + } else { + ObMysqlClientSession *client_session = sm_->get_client_session(); + Ob20ProtocolHeader &ob20_head = client_session->get_session_info().ob20_request_.ob20_header_; + uint8_t last_compressed_seq = static_cast(client_session->get_compressed_seq() + 1); + const bool is_new_extra_info = client_session->get_session_info().is_client_support_new_extra_info(); + bool is_extra_info_exist = false; + bool is_trans_internal_routing = false; + + if (OB_FAIL(ObProto20Utils::fill_proto20_extra_info(write_buf, &extra_info, is_new_extra_info, + payload_len, tail_crc_, is_extra_info_exist))) { + LOG_WARN("fail to fill ob20 extra info", K(ret)); + } else if (OB_FAIL(ObProto20Utils::fill_proto20_header(head_start, + payload_len, + last_compressed_seq, + last_compressed_seq, + ob20_head.request_id_, + client_session->get_cs_id(), + is_last_packet, + false, false, + is_extra_info_exist, + is_new_extra_info, + is_trans_internal_routing))) { + LOG_WARN("fail to fill ob20 head", K(ret)); + } else { + client_session->set_compressed_seq(last_compressed_seq); + } + } + + return ret; +} + +int ObMysqlResponseOb20ProtocolTransformPlugin::build_ob20_body(ObIOBufferReader *reader, + int64_t reader_avail, + ObMIOBuffer *write_buf, + int64_t write_len, + uint64_t &crc) +{ + int ret = OB_SUCCESS; + + if (reader_avail == 0 || write_len == 0) { + LOG_DEBUG("arg is 0, continue...", K(reader_avail), K(write_len)); + } else if (reader_avail < 0 || write_len < 0 || reader_avail < write_len) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected argument check, plz check", K(ret), K(reader_avail), K(write_len)); + } else { + int64_t payload_len = 0; + if (OB_FAIL(ObProto20Utils::fill_proto20_payload(reader, write_buf, write_len, payload_len, crc))) { + LOG_WARN("fail to fill ob20 body in ob20 plugin", K(ret), K(write_len), K(reader_avail)); + } else { + handled_payload_len_ += write_len; + } + } + + return ret; +} + +void ObMysqlResponseOb20ProtocolTransformPlugin::handle_input_complete() +{ + PROXY_API_LOG(DEBUG, "ObMysqlResponseOb20ProtocolTransformPlugin::handle_input_complete happen", K(lbt())); + + if (NULL != local_reader_) { + LOG_DEBUG("free local reader in handle input complete"); + local_reader_->dealloc(); + local_reader_ = NULL; + } + + if (NULL != out_buffer_) { + free_miobuffer(out_buffer_); + out_buffer_ = NULL; + out_buffer_reader_ = NULL; + } + + set_output_complete(); +} + +int ObMysqlResponseOb20ProtocolTransformPlugin::alloc_iobuffer_inner(event::ObIOBufferReader *reader) +{ + int ret = OB_SUCCESS; + + if (NULL == local_reader_ && OB_ISNULL(local_reader_ = reader->clone())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to clone reader to local", K(ret)); + } + + if (OB_SUCC(ret) && NULL == out_buffer_) { + if (OB_ISNULL(out_buffer_ = new_miobuffer(MYSQL_BUFFER_SIZE))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to new miobuffer", K(ret)); + } else if (NULL == (out_buffer_reader_ = out_buffer_->alloc_reader())) { + LOG_WARN("fail to alloc local reader", K(ret)); + } else { + LOG_DEBUG("alloc iobuffer inner finish"); + } + } + + return ret; +} + +void ObMysqlResponseOb20ProtocolTransformPlugin::reset() +{ + tail_crc_ = 0; + handled_payload_len_ = 0; + target_payload_len_= 0; + state_ = OB20_PLUGIN_INIT_STATE; +} + +} // proxy +} // obproxy +} // oceanbase + diff --git a/src/obproxy/proxy/plugins/ob_mysql_response_ob20_transform_plugin.h b/src/obproxy/proxy/plugins/ob_mysql_response_ob20_transform_plugin.h new file mode 100644 index 0000000000000000000000000000000000000000..6c2ce70a197d9dc1cb8b847ba19b290bde55778c --- /dev/null +++ b/src/obproxy/proxy/plugins/ob_mysql_response_ob20_transform_plugin.h @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef OBPROXY_MYSQL_RESPONSE_OB20_PROTOCOL_TRANSFORM_PLUGIN_H +#define OBPROXY_MYSQL_RESPONSE_OB20_PROTOCOL_TRANSFORM_PLUGIN_H + +#include "proxy/api/ob_global_plugin.h" +#include "proxy/api/ob_transformation_plugin.h" +#include "proxy/mysql/ob_mysql_sm.h" + +namespace oceanbase +{ +namespace obproxy +{ +namespace proxy +{ + +enum Ob20ProtolTransPluginState { + OB20_PLUGIN_INIT_STATE, // init, at least need mysql head(4) + OB20_PLUGIN_CONT_STATE, // recevied mysql head done, total mysql packet has not received done yet + OB20_PLUGIN_FIN_STATE // mysql packet handled done, need handle tail crc, then reset to init state +}; + +class ObMysqlResponseOb20ProtocolTransformPlugin : public ObTransformationPlugin +{ +public: + static ObMysqlResponseOb20ProtocolTransformPlugin *alloc(ObApiTransaction &transaction); + + explicit ObMysqlResponseOb20ProtocolTransformPlugin(ObApiTransaction &transaction); + + virtual void destroy(); + + virtual int consume(event::ObIOBufferReader *reader); + + virtual void handle_input_complete(); + +private: + int alloc_iobuffer_inner(event::ObIOBufferReader *reader); + void reset(); + + int build_ob20_head_and_extra(event::ObMIOBuffer *write_buf, common::ObIArray &extra_info, + bool is_last_packet); + int build_ob20_body(event::ObIOBufferReader *reader, int64_t reader_avail, event::ObMIOBuffer *write_buf, + int64_t write_len, uint64_t &crc); + +private: + uint64_t tail_crc_; + int64_t target_payload_len_; + int64_t handled_payload_len_; + Ob20ProtolTransPluginState state_; + + event::ObIOBufferReader *local_reader_; + event::ObMIOBuffer *out_buffer_; // save temp result, after produce, consume all + event::ObIOBufferReader *out_buffer_reader_; // reader of out_buffer_ + + DISALLOW_COPY_AND_ASSIGN(ObMysqlResponseOb20ProtocolTransformPlugin); +}; + + +class ObMysqlResponseOb20ProtocolGlobalPlugin : public ObGlobalPlugin +{ +public: + static ObMysqlResponseOb20ProtocolGlobalPlugin *alloc() + { + return op_reclaim_alloc(ObMysqlResponseOb20ProtocolGlobalPlugin); + } + + ObMysqlResponseOb20ProtocolGlobalPlugin() + { + register_hook(HOOK_READ_RESPONSE); + } + + virtual void destroy() + { + ObGlobalPlugin::destroy(); + op_reclaim_free(this); + } + + virtual void handle_read_response(ObApiTransaction &transaction) + { + ObTransactionPlugin *plugin = NULL; + + if (need_enable_plugin(transaction.get_sm())) { + plugin = ObMysqlResponseOb20ProtocolTransformPlugin::alloc(transaction); + if (NULL != plugin) { + transaction.add_plugin(plugin); + PROXY_API_LOG(DEBUG, "add ObMysqlResponseOb20ProtocolTransformPlugin", K(plugin)); + } else { + PROXY_API_LOG(ERROR, "fail to alloc mem for ObMysqlResponseOb20ProtocolTransformPlugin"); + } + } else { + PROXY_API_LOG(DEBUG, "no need setup ObMysqlResponseOb20ProtocolTransformPlugin"); + } + + transaction.resume(); + } + + inline bool need_enable_plugin(ObMysqlSM *sm) const + { + return (!sm->trans_state_.trans_info_.client_request_.is_internal_cmd() + && NULL != sm->client_session_ + // inner sql will received compeleted, no need plugin + && !sm->client_session_->is_proxy_mysql_client_ + && ObMysqlTransact::SERVER_SEND_REQUEST == sm->trans_state_.current_.send_action_ + && ObProxyProtocol::PROTOCOL_OB20 == sm->get_client_session_protocol()); + } + +private: + DISALLOW_COPY_AND_ASSIGN(ObMysqlResponseOb20ProtocolGlobalPlugin); +}; + + +void init_mysql_response_ob20_protocol_transform() +{ + PROXY_API_LOG(INFO, "init mysql response ob20 protocol transform plugin"); + ObMysqlResponseOb20ProtocolGlobalPlugin *ob20_prot_trans = ObMysqlResponseOb20ProtocolGlobalPlugin::alloc(); + UNUSED(ob20_prot_trans); +} + +} // proxy +} // obproxy +} // oceanbase + +#endif + diff --git a/src/obproxy/proxy/plugins/ob_trim_okpacket_transform_plugin.h b/src/obproxy/proxy/plugins/ob_trim_okpacket_transform_plugin.h index f92e46622d2b4e8cbcda47ec0e5a5cb30a506589..d95dc327b5d1fa81d60cebbbe3e034b359f9c60d 100644 --- a/src/obproxy/proxy/plugins/ob_trim_okpacket_transform_plugin.h +++ b/src/obproxy/proxy/plugins/ob_trim_okpacket_transform_plugin.h @@ -181,7 +181,7 @@ public: if (OB_SUCCESS != (ret = src_ok.decode())) { PROXY_API_LOG(WARN, "fail to decode ok packet", K(src_ok), K(ret)); } else if (OB_SUCCESS != (ret = ObProxySessionInfoHandler::save_changed_session_info( - client_info, server_info, sm_->trans_state_.is_auth_request_, NULL, src_ok, analyze_result))) { + client_info, server_info, sm_->trans_state_.is_auth_request_, NULL, src_ok, analyze_result, sm_->trans_state_.trace_log_))) { _PROXY_API_LOG(WARN, "fail to save changed session info, is_auth_request=%d, ret=%d", sm_->trans_state_.is_auth_request_, ret); } diff --git a/src/obproxy/proxy/route/ob_cache_cleaner.cpp b/src/obproxy/proxy/route/ob_cache_cleaner.cpp index 68ed0f5de61107e08d8c754ed8a79e5b1f5a46ee..f81a0e0c6addc907f76f241ea98dd7acf6a90b0e 100644 --- a/src/obproxy/proxy/route/ob_cache_cleaner.cpp +++ b/src/obproxy/proxy/route/ob_cache_cleaner.cpp @@ -816,6 +816,29 @@ int ObCacheCleaner::schedule_cache_cleaner() { int ret = OB_SUCCESS; + ObEventThreadType etype = ET_NET; + int64_t net_thread_count = g_event_processor.thread_count_for_type_[etype]; + + const int64_t mt_part_num = MT_HASHTABLE_PARTITIONS; + if (net_thread_count > 0 && mt_part_num > 0) { + for (int64_t i = 0; i < net_thread_count; ++i) { + // calc range + if (OB_FAIL(schedule_one_cache_cleaner(i))) { + LOG_WARN("fail to init cleaner", K(i), K(ret)); + } + } + } else { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("thread_num or mt_part_num can not be NULL", K(mt_part_num), K(net_thread_count), K(ret)); + } + + return ret; +} + +int ObCacheCleaner::schedule_one_cache_cleaner(int64_t index) +{ + int ret = OB_SUCCESS; + ObEventThreadType etype = ET_NET; int64_t net_thread_count = g_event_processor.thread_count_for_type_[etype]; ObEThread **netthreads = g_event_processor.event_thread_[etype]; @@ -833,23 +856,23 @@ int ObCacheCleaner::schedule_cache_cleaner() if (net_thread_count > 0 && mt_part_num > 0) { int64_t part_num_per_thread = mt_part_num / net_thread_count; int64_t remain_num = mt_part_num % net_thread_count; - for (int64_t i = 0; i < net_thread_count; ++i) { + //for (int64_t i = 0; i < net_thread_count; ++i) { // calc range range.reset(); if (part_num_per_thread > 0) { // thread_num <= mt_part_num - if (i < remain_num) { - range.start_idx_ = (part_num_per_thread + 1) * i; - range.end_idx_ = ((part_num_per_thread + 1) * (i + 1) - 1); + if (index < remain_num) { + range.start_idx_ = (part_num_per_thread + 1) * index; + range.end_idx_ = ((part_num_per_thread + 1) * (index + 1) - 1); } else { int64_t base = (part_num_per_thread + 1) * remain_num; - range.start_idx_ = base + (part_num_per_thread) * (i - remain_num); - range.end_idx_ = base + ((part_num_per_thread) * (i - remain_num + 1) - 1); + range.start_idx_ = base + (part_num_per_thread) * (index - remain_num); + range.end_idx_ = base + ((part_num_per_thread) * (index - remain_num + 1) - 1); } } else if (0 == part_num_per_thread) { // thread_num > mt_part_num - if (i < mt_part_num) { - range.start_idx_ = i; - range.end_idx_ = i; + if (index < mt_part_num) { + range.start_idx_ = index; + range.end_idx_ = index; } } @@ -858,19 +881,19 @@ int ObCacheCleaner::schedule_cache_cleaner() ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to alloc cleaner", K(ret)); } else if (OB_FAIL(cleaner->init(table_cache, partition_cache, routine_cache, sql_table_cache, range, - net_thread_count, i, clean_interval))) { + net_thread_count, index, clean_interval))) { LOG_WARN("fail to init cleaner", K(range), K(ret)); - } else if (OB_ISNULL(target_ethread = netthreads[i])) { + } else if (OB_ISNULL(target_ethread = netthreads[index])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("ethread can not be NULL", K(target_ethread), K(ret)); } else if (OB_FAIL(cleaner->start_clean_cache(*target_ethread))) { LOG_WARN("fail to start clean cache", K(ret)); } else { target_ethread->cache_cleaner_ = cleaner; - LOG_INFO("succ schedule cache cleaners", K(target_ethread), K(range), K(i), + LOG_INFO("succ schedule cache cleaners", K(target_ethread), K(range), K(index), K(part_num_per_thread), K(remain_num), K(net_thread_count), K(ret)); } - } + //} } else { ret = OB_ERR_UNEXPECTED; LOG_ERROR("thread_num or mt_part_num can not be NULL", K(mt_part_num), K(net_thread_count), K(ret)); @@ -879,6 +902,7 @@ int ObCacheCleaner::schedule_cache_cleaner() return ret; } + struct ObClientSessionCloseHandler { ObClientSessionCloseHandler() : cs_(NULL), force_close_(false) {} @@ -1213,7 +1237,7 @@ int ObCacheCleaner::update_clean_interval() for (int64_t i = 0; (i < thread_count) && OB_SUCC(ret); ++i) { if (OB_ISNULL(ethread = threads[i]) || OB_ISNULL(cleaner = threads[i]->cache_cleaner_)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("ethread and cache cleaner can not be NULL", K(ethread), K(cleaner), K(ret)); + LOG_WARN("ethread and cache cleaner can not be NULL", K(i), K(thread_count), K(ethread), K(cleaner), K(ret)); } else if (OB_FAIL(cleaner->set_clean_interval(interval_us))) { LOG_WARN("fail to set clean interval", K(interval_us), K(ret)); } else if (OB_ISNULL(ethread->schedule_imm(cleaner))) { diff --git a/src/obproxy/proxy/route/ob_cache_cleaner.h b/src/obproxy/proxy/route/ob_cache_cleaner.h index 16b9e40bb6a96365f80d4964a9c9d199a9b4c5a3..f8871fd65a1773717b7c8422e10e66d9e727c446 100644 --- a/src/obproxy/proxy/route/ob_cache_cleaner.h +++ b/src/obproxy/proxy/route/ob_cache_cleaner.h @@ -93,6 +93,7 @@ public: int main_handler(int event, void *data); static int schedule_cache_cleaner(); static int update_clean_interval(); + static int schedule_one_cache_cleaner(int64_t index); int64_t to_string(char *buf, const int64_t buf_len) const; int push_deleting_cr(obutils::ObResourceDeleteActor *actor); diff --git a/src/obproxy/proxy/route/ob_ldc_location.cpp b/src/obproxy/proxy/route/ob_ldc_location.cpp index b75e06e2d8f71cf0170d2a3db559538c0ca37ead..1a35852f17a3260ace1f443a3829c8558b0afbc0 100644 --- a/src/obproxy/proxy/route/ob_ldc_location.cpp +++ b/src/obproxy/proxy/route/ob_ldc_location.cpp @@ -20,6 +20,8 @@ #include "obutils/ob_safe_snapshot_manager.h" #include "obutils/ob_config_server_processor.h" #include "iocore/eventsystem/ob_buf_allocator.h" +#include "obproxy/obutils/ob_resource_pool_processor.h" + using namespace oceanbase::common; using namespace oceanbase::share; @@ -36,8 +38,16 @@ void ObLDCLocation::reset_item_array() if (NULL != item_array_ && item_count_ > 0) { op_fixed_mem_free(item_array_, static_cast(sizeof(ObLDCItem)) * item_count_); } + + if (NULL != primary_zone_item_array_ && primary_zone_item_count_ > 0) { + op_fixed_mem_free(primary_zone_item_array_, static_cast(sizeof(ObLDCItem)) * primary_zone_item_count_); + } + item_array_ = NULL; item_count_ = 0; + primary_zone_item_array_ = NULL; + primary_zone_item_count_ = 0; + site_start_index_array_[SAME_IDC] = 0; site_start_index_array_[SAME_REGION] = 0; site_start_index_array_[OTHER_REGION] = 0; @@ -355,10 +365,12 @@ bool ObLDCLocation::is_in_primary_zone(const ObProxyReplicaLocation &replica, int ObLDCLocation::fill_strong_read_location(const ObProxyPartitionLocation *pl, ObLDCLocation &dummy_ldc, ObLDCItem &leader_item, ObLDCLocation &ldc_location, bool &entry_need_update, const bool is_only_readwrite_zone, const bool need_use_dup_replica, - const bool need_skip_leader_item, + const bool need_skip_leader_item, const bool is_random_routing_mode, const ObIArray &ss_info, const ObIArray ®ion_names, - const ObString &proxy_primary_zone_name) + const ObString &proxy_primary_zone_name, + const ObString &tenant_name, + obutils::ObClusterResource *cluster_resource) { int ret = OB_SUCCESS; entry_need_update = false; @@ -369,102 +381,35 @@ int ObLDCLocation::fill_strong_read_location(const ObProxyPartitionLocation *pl, } else if (OB_FAIL(get_thread_allocator(allocator))) { LOG_WARN("fail to get_thread_allocator", K(ret)); } else { - ObSEArray tmp_item_array(OB_MAX_LDC_ITEM_COUNT, *allocator); - const bool is_ldc_used = dummy_ldc.is_ldc_used(); + LdcItemArrayType tmp_item_array(OB_MAX_LDC_ITEM_COUNT, *allocator); + LdcItemArrayType tmp_pz_item_array(OB_MAX_LDC_ITEM_COUNT, *allocator); + + // reset status and item dummy_ldc.reset_item_status(); leader_item.reset(); //1. fill tmp_item_array from pl if (NULL != pl && pl->is_valid()) { - const bool default_merging_status = false; - const bool default_congested_status = false; - const ObIDCType default_idc_type = SAME_IDC; - const ObZoneType default_zone_type = ZONE_TYPE_READWRITE; - ObLDCItem tmp_item; - bool need_use_it = true; - - for (int64_t i = 0; OB_SUCC(ret) && i < pl->replica_count(); ++i) { - const ObProxyReplicaLocation &replica = *(pl->get_replica(i)); - tmp_item.reset(); - need_use_it = true; - for (int64_t j = 0; NULL == tmp_item.replica_ && need_use_it && OB_SUCC(ret) && j < dummy_ldc.item_count_; ++j) { - ObLDCItem &dummy_item = dummy_ldc.item_array_[j]; - if (dummy_item.is_used_) { - //continue - } else if (OB_ISNULL(dummy_item.replica_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("dummy_item is invalid", K(dummy_item), K(j), K(dummy_ldc), K(ret)); - } else if (replica.server_ == dummy_item.replica_->server_) { - if (is_only_readwrite_zone - && common::ZONE_TYPE_READWRITE != dummy_item.zone_type_ - && !replica.is_leader()) { - //do not use it - need_use_it = false; - } else if (REPLICA_TYPE_LOGONLY == replica.get_replica_type() - || REPLICA_TYPE_ENCRYPTION_LOGONLY == replica.get_replica_type()) { - // log relica, skip - need_use_it = false; - } else { - tmp_item.set_partition_item(replica, dummy_item); - } - dummy_item.is_used_ = true; - } - }//end of for - - if (OB_SUCC(ret) && need_use_it) { - need_use_it = is_in_primary_zone(replica, ss_info, proxy_primary_zone_name); - } - - if (OB_SUCC(ret) && need_use_it) { - //not found it - if (NULL == tmp_item.replica_) { - // if relica not in dummy entry, need check whether relica is same IDC or Region - entry_need_update = check_need_update_entry(replica, dummy_ldc, ss_info, region_names); - - if (replica.is_leader()) { - LOG_WARN("fail to find leader in dummy ldc with ldc, maybe someone old, continue use it", - K(replica)); - if (!need_skip_leader_item) { - leader_item.set(replica, default_merging_status, default_idc_type, default_zone_type, - true, default_congested_status); - if (need_use_dup_replica) { - if (OB_FAIL(tmp_item_array.push_back(leader_item))) { - LOG_WARN("fail to push_back leader_item", K(leader_item), K(tmp_item_array), K(ret)); - } - } - } - } else if (is_ldc_used) { - LOG_WARN("fail to find replica in dummy ldc with ldc, maybe someone old, " - "do not use it", K(replica)); - } else { - LOG_WARN("fail to find replica in dummy ldc without ldc, maybe someone old, " - "continue use it", K(replica)); - tmp_item.set(replica, default_merging_status, default_idc_type, default_zone_type, - true, default_congested_status);//without ldc, location will put into same_idc - if (OB_FAIL(tmp_item_array.push_back(tmp_item))) { - LOG_WARN("fail to push_back target_item", K(tmp_item), K(tmp_item_array), K(ret)); - } - } - } else { - //found it - if (replica.is_leader()) { - if (!need_skip_leader_item) { - leader_item = tmp_item; - if (need_use_dup_replica) { - if (OB_FAIL(tmp_item_array.push_back(leader_item))) { - LOG_WARN("fail to push_back leader_item", K(leader_item), K(tmp_item_array), K(ret)); - } - } - } - } else if (OB_FAIL(tmp_item_array.push_back(tmp_item))) { - LOG_WARN("fail to push_back target_item", K(tmp_item), K(tmp_item_array), K(ret)); - } - } - }//OB_SUCC - }//end of for pl - }//end of pl - - //3. fill tmp_item_array from dummy entry + if (OB_FAIL(fill_item_array_from_pl(pl, ss_info, region_names, proxy_primary_zone_name, need_skip_leader_item, + is_only_readwrite_zone, need_use_dup_replica, dummy_ldc, entry_need_update, + leader_item, tmp_item_array))) { + LOG_WARN("fail to fill item array from pl", K(ret)); + } + } else if (cluster_resource != NULL + && proxy_primary_zone_name.empty() + && !tenant_name.empty() + && !is_random_routing_mode + && get_global_proxy_config().enable_primary_zone) { + //2. pl = NULL, no table entry, no partition entry, enable flag, choose from primary zone list + // if proxy_primary_zone_name is set, use proxy_primary_zone_name as the proxy route dest addr + // random route mode, do not go through primary zone policy + if (OB_FAIL(fill_primary_zone_item_array(allocator, cluster_resource, ss_info, tenant_name, + dummy_ldc, tmp_pz_item_array))) { + LOG_WARN("fail to fill primary zone item array", K(ret)); + } + } + + //4. fill tmp_item_array from dummy entry if (OB_SUCC(ret)) { if (tmp_item_array.count() > 1) { //shuffle the partition server @@ -489,12 +434,13 @@ int ObLDCLocation::fill_strong_read_location(const ObProxyPartitionLocation *pl, //3. fill tenant_ldc without leader if (OB_SUCC(ret)) { - if (OB_FAIL(ldc_location.set_ldc_location(pl, dummy_ldc, tmp_item_array))) { + if (OB_FAIL(ldc_location.set_ldc_location(pl, dummy_ldc, tmp_item_array, tmp_pz_item_array))) { LOG_WARN("fail to set_ldc_location", K(ret)); } } allocator = NULL; } + return ret; } @@ -515,6 +461,7 @@ int ObLDCLocation::fill_weak_read_location(const ObProxyPartitionLocation *pl, LOG_WARN("fail to get_thread_allocator", K(ret)); } else { ObSEArray tmp_item_array(OB_MAX_LDC_ITEM_COUNT, *allocator); + ObSEArray tmp_pz_item_array(OB_MAX_LDC_ITEM_COUNT, *allocator); //mainly used for no-ldc, get random start idx const bool is_ldc_used = dummy_ldc.is_ldc_used(); dummy_ldc.reset_item_status(); @@ -612,7 +559,7 @@ int ObLDCLocation::fill_weak_read_location(const ObProxyPartitionLocation *pl, //3. fill ldc_location from tmp_item_array if (OB_SUCC(ret)) { - if (OB_FAIL(ldc_location.set_ldc_location(pl, dummy_ldc, tmp_item_array))) { + if (OB_FAIL(ldc_location.set_ldc_location(pl, dummy_ldc, tmp_item_array, tmp_pz_item_array))) { LOG_WARN("fail to set_ldc_location", K(ret)); } else { // target_ldc we should use priority @@ -625,8 +572,207 @@ int ObLDCLocation::fill_weak_read_location(const ObProxyPartitionLocation *pl, return ret; } +int ObLDCLocation::fill_item_array_from_pl(const ObProxyPartitionLocation *pl, + const ObIArray &ss_info, + const ObIArray ®ion_names, + const ObString &proxy_primary_zone_name, + const bool need_skip_leader_item, + const bool is_only_readwrite_zone, + const bool need_use_dup_replica, + ObLDCLocation &dummy_ldc, + bool &entry_need_update, + ObLDCItem &leader_item, + LdcItemArrayType &tmp_item_array) +{ + int ret = OB_SUCCESS; + + const bool default_merging_status = false; + const bool default_congested_status = false; + const ObIDCType default_idc_type = SAME_IDC; + const ObZoneType default_zone_type = ZONE_TYPE_READWRITE; + const bool is_ldc_used = dummy_ldc.is_ldc_used(); + ObLDCItem tmp_item; + bool need_use_it = true; + + for (int64_t i = 0; OB_SUCC(ret) && i < pl->replica_count(); ++i) { + const ObProxyReplicaLocation &replica = *(pl->get_replica(i)); + tmp_item.reset(); // reset each for + need_use_it = true; + for (int64_t j = 0; NULL == tmp_item.replica_ && need_use_it && OB_SUCC(ret) && j < dummy_ldc.item_count_; ++j) { + ObLDCItem &dummy_item = dummy_ldc.item_array_[j]; + if (dummy_item.is_used_) { + //continue + } else if (OB_ISNULL(dummy_item.replica_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("dummy_item is invalid", K(dummy_item), K(j), K(dummy_ldc), K(ret)); + } else if (replica.server_ == dummy_item.replica_->server_) { + if (is_only_readwrite_zone + && common::ZONE_TYPE_READWRITE != dummy_item.zone_type_ + && !replica.is_leader()) { + //do not use it + need_use_it = false; + } else if (REPLICA_TYPE_LOGONLY == replica.get_replica_type() + || REPLICA_TYPE_ENCRYPTION_LOGONLY == replica.get_replica_type()) { + // replica type logonly, pass it + need_use_it = false; + } else { + tmp_item.set_partition_item(replica, dummy_item); + } + dummy_item.is_used_ = true; + } + } // for + + if (OB_SUCC(ret) && need_use_it) { + need_use_it = is_in_primary_zone(replica, ss_info, proxy_primary_zone_name); + } + + if (OB_SUCC(ret) && need_use_it) { + // not found it + if (NULL == tmp_item.replica_) { + // if table location is not in dummy entry, need judge whether it is in the same IDC/REGION + entry_need_update = check_need_update_entry(replica, dummy_ldc, ss_info, region_names); + if (replica.is_leader()) { + LOG_WARN("fail to find leader in dummy ldc with ldc, maybe someone old, continue use it", + K(replica)); + if (!need_skip_leader_item) { + leader_item.set(replica, default_merging_status, default_idc_type, default_zone_type, + true, default_congested_status); + if (need_use_dup_replica) { + if (OB_FAIL(tmp_item_array.push_back(leader_item))) { + LOG_WARN("fail to push_back leader_item", K(leader_item), K(tmp_item_array), K(ret)); + } + } + } + } else if (is_ldc_used) { + LOG_WARN("fail to find replica in dummy ldc with ldc, maybe someone old, " + "do not use it", K(replica)); + } else { + LOG_WARN("fail to find replica in dummy ldc without ldc, maybe someone old, " + "continue use it", K(replica)); + tmp_item.set(replica, default_merging_status, default_idc_type, default_zone_type, + true, default_congested_status); //without ldc, location will put into same_idc + if (OB_FAIL(tmp_item_array.push_back(tmp_item))) { + LOG_WARN("fail to push_back target_item", K(tmp_item), K(tmp_item_array), K(ret)); + } + } + } else { + //found it + if (replica.is_leader()) { + if (!need_skip_leader_item) { + leader_item = tmp_item; + if (need_use_dup_replica) { + if (OB_FAIL(tmp_item_array.push_back(leader_item))) { + LOG_WARN("fail to push_back leader_item", K(leader_item), K(tmp_item_array), K(ret)); + } + } + } + } else if (OB_FAIL(tmp_item_array.push_back(tmp_item))) { + LOG_WARN("fail to push_back target_item", K(tmp_item), K(tmp_item_array), K(ret)); + } + } + } // if + } // for + + return ret; +} + +int ObLDCLocation::fill_primary_zone_item_array(common::ModulePageAllocator *allocator, + obutils::ObClusterResource *cluster_resource, + const ObIArray &ss_info, + const ObString &tenant_name, + ObLDCLocation &dummy_ldc, + LdcItemArrayType &tmp_pz_item_array) +{ + int ret = OB_SUCCESS; + LOG_DEBUG("fill strong read location, primary zone route optimize begin."); + + // get location info from map + ObLDCItem tmp_pz_item; + ObLocationTenantInfo *info = NULL; + if (OB_FAIL(cluster_resource->get_location_tenant_info(tenant_name, info))) { + if (ret == OB_HASH_NOT_EXIST) { + ret = OB_SUCCESS; + LOG_INFO("no location tenant info, do not update, or no right to visit all_tenant table", K(tenant_name)); + } else { + LOG_WARN("fail to get location tenant info", K(ret)); + } + } else if (info != NULL) { + // pz zone name list & weight list + PrimaryZonePrioArrayType &pz_prio_array = info->primary_zone_prio_array_; + PrimaryZonePrioWeightArrayType &pz_prio_weight_array = info->primary_zone_prio_weight_array_; + + // zone name match + if (!pz_prio_array.empty() + && !pz_prio_weight_array.empty() + && pz_prio_array.count() == pz_prio_weight_array.count()) { + // same weight choose + int64_t i = 0; + int64_t j = 0; + int64_t pz_prio_weight_count = pz_prio_weight_array.count(); + while (i < pz_prio_weight_count) { + j = i; + do { + j++; + } while (j < pz_prio_weight_count && pz_prio_weight_array.at(i) == pz_prio_weight_array.at(j)); + LOG_DEBUG("search in range", K(i), K(j), "weight", pz_prio_weight_array.at(i)); + + // find all dummy ldc replica, compared with primary zone name and search in ss info + ObSEArray tmp_pz_tmp_item_array(OB_MAX_LDC_ITEM_COUNT, *allocator); + for (int64_t k = i; k < j && k < pz_prio_weight_count; ++k) { + ObString &each_zone = pz_prio_array.at(k); + for (int64_t p = 0; p < dummy_ldc.item_count_; ++p) { + ObLDCItem &dummy_item = dummy_ldc.item_array_[p]; + if (dummy_item.is_used_ + || REPLICA_TYPE_LOGONLY == dummy_item.replica_->get_replica_type() + || REPLICA_TYPE_ENCRYPTION_LOGONLY == dummy_item.replica_->get_replica_type() + || dummy_item.replica_ == NULL) { // rep != null ? + LOG_DEBUG("continue this replica", K(dummy_item)); + continue; + } else { + if (is_in_primary_zone(*dummy_item.replica_, ss_info, each_zone)) { + tmp_pz_item.reset(); + tmp_pz_item.set(*dummy_item.replica_, dummy_item.is_merging_, dummy_item.idc_type_, + dummy_item.zone_type_, dummy_item.is_partition_server_, dummy_item.is_force_congested_); + tmp_pz_tmp_item_array.push_back(tmp_pz_item); + dummy_item.is_used_ = true; + } + } + } // for + } // for + + // put tmp_pz to pz + if (!tmp_pz_tmp_item_array.empty()) { + std::random_shuffle(tmp_pz_tmp_item_array.begin(), tmp_pz_tmp_item_array.end(), dummy_ldc.random_); + for (int64_t q = 0; q < tmp_pz_tmp_item_array.count(); ++q) { + ObLDCItem &tmp_item = tmp_pz_tmp_item_array.at(q); + tmp_pz_item_array.push_back(tmp_item); + } + LOG_DEBUG("random shuffle tmp pz tmp item array, and push to tmp pz item array", + K(tmp_pz_tmp_item_array), K(tmp_pz_item_array)); + } + + // at last + i = j; + } // while + } else if (pz_prio_array.empty() + && pz_prio_weight_array.empty()) { + LOG_DEBUG("no primary zone for this tenant, route with tenant location cache", K(tenant_name)); + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected error while check the location tenant info", K(ret), KPC(info)); + } + + // dec ref after use + info->dec_ref(); + } + + return ret; +} + int ObLDCLocation::set_ldc_location(const ObProxyPartitionLocation *pl, - const ObLDCLocation &dummy_ldc, const ObIArray &tmp_item_array) + const ObLDCLocation &dummy_ldc, + const ObIArray &tmp_item_array, + const ObIArray &tmp_pz_item_array) { int ret = OB_SUCCESS; reset(); @@ -666,6 +812,23 @@ int ObLDCLocation::set_ldc_location(const ObProxyPartitionLocation *pl, } } } + + if (!tmp_pz_item_array.empty()) { + const int64_t alloc_size = static_cast(sizeof(ObLDCItem)) * tmp_pz_item_array.count(); + char *pz_item_array_buf = NULL; + if (OB_ISNULL(pz_item_array_buf = static_cast(op_fixed_mem_alloc(alloc_size)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc mem", K(ret), K(alloc_size)); + } else { + primary_zone_item_count_ = tmp_pz_item_array.count(); + primary_zone_item_array_ = new (pz_item_array_buf) ObLDCItem[primary_zone_item_count_]; + for (int64_t i = 0; i < primary_zone_item_count_; ++i) { + primary_zone_item_array_[i] = tmp_pz_item_array.at(i); + LOG_DEBUG("push to pz item", K(i), K(primary_zone_item_array_[i])); + } + } + } + return ret; } diff --git a/src/obproxy/proxy/route/ob_ldc_location.h b/src/obproxy/proxy/route/ob_ldc_location.h index 27d06b621bcdb59d8c0d128a13c6b7a3732c1232..49ba6a001f484c4ce3a04aa700c6b0ff54b862cf 100644 --- a/src/obproxy/proxy/route/ob_ldc_location.h +++ b/src/obproxy/proxy/route/ob_ldc_location.h @@ -21,6 +21,8 @@ #include "lib/allocator/page_arena.h" #include "lib/random/ob_random.h" + + namespace oceanbase { namespace obproxy @@ -30,6 +32,7 @@ namespace obutils class ObServerStateSimpleInfo; class ObSafeSnapshotManager; class ObProxyNameString; +class ObClusterResource; } namespace proxy { @@ -130,8 +133,8 @@ class ObLDCLocation { public: ObLDCLocation() - : item_array_(NULL), item_count_(0), site_start_index_array_(), - pl_(NULL), ts_(NULL), safe_snapshot_mananger_(NULL), + : item_array_(NULL), item_count_(0), primary_zone_item_array_(NULL), primary_zone_item_count_(0), + site_start_index_array_(), pl_(NULL), ts_(NULL), safe_snapshot_mananger_(NULL), readonly_exist_status_(READONLY_ZONE_UNKNOWN), use_ldc_(false), idc_name_(), idc_name_buf_(), random_() {} @@ -161,12 +164,20 @@ public: static common::ObString get_zone_exist_status_string(const ObReadOnlyZoneExistStatus status); bool is_empty() const; - int64_t count() const { return (is_empty() ? 0 : item_count_); } + int64_t count() const { return (is_empty() ? 0 : item_count_) + + (is_primary_zone_empty() ? 0 : primary_zone_item_count_); } void reset_item_status(); void reset_item_array(); void reset(); const ObLDCItem *get_item_array() const { return item_array_; } ObLDCItem *get_item_array() { return item_array_; } + + bool is_primary_zone_empty() const { return (NULL == primary_zone_item_array_ || primary_zone_item_count_ <= 0); } + int64_t primary_zone_count() const { return ((is_primary_zone_empty()) ? 0 : primary_zone_item_count_); } + + const ObLDCItem *get_primary_zone_item_array() const { return primary_zone_item_array_; } + ObLDCItem *get_primary_zone_item_array() { return primary_zone_item_array_; } + const int64_t *get_site_start_index_array() const { return site_start_index_array_; } int64_t get_other_region_site_start_index() const { return site_start_index_array_[OTHER_REGION]; } bool is_ldc_used() const { return use_ldc_ && !idc_name_.empty(); } @@ -208,9 +219,12 @@ public: const bool is_only_readwrite_zone, const bool need_use_dup_replica, const bool need_skip_leader_item, + const bool is_random_routing_mode, const common::ObIArray &ss_info, const common::ObIArray ®ion_names, - const common::ObString &proxy_primary_zone_name); + const common::ObString &proxy_primary_zone_name, + const common::ObString &tenant_name, + obutils::ObClusterResource *cluster_resource); static int fill_weak_read_location(const ObProxyPartitionLocation *pl, ObLDCLocation &dummy_ldc, ObLDCLocation &ldc_location, @@ -228,7 +242,8 @@ public: const common::ObString &proxy_primary_zone_name); int set_ldc_location(const ObProxyPartitionLocation *pl, const ObLDCLocation &dummy_ldc, - const common::ObIArray &tmp_item_array); + const common::ObIArray &tmp_item_array, + const common::ObIArray &tmp_pz_item_array); void set_safe_snapshot_manager(const obutils::ObSafeSnapshotManager *safe_snapshot_mananger) { @@ -263,10 +278,31 @@ private: static int add_unique_region_name(const common::ObString ®ion_name, common::ObIArray ®ion_names); + typedef common::ObSEArray LdcItemArrayType; + static int fill_primary_zone_item_array(common::ModulePageAllocator *allocator, + obutils::ObClusterResource *cluster_resource, + const common::ObIArray &ss_info, + const ObString &tenant_name, + ObLDCLocation &dummy_ldc, + LdcItemArrayType &tmp_pz_item_array); + static int fill_item_array_from_pl(const ObProxyPartitionLocation *pl, + const common::ObIArray &ss_info, + const common::ObIArray ®ion_names, + const ObString &proxy_primary_zone_name, + const bool need_skip_leader_item, + const bool is_only_readwrite_zone, + const bool need_use_dup_replica, + ObLDCLocation &dummy_ldc, + bool &entry_need_update, + ObLDCItem &leader_item, + LdcItemArrayType &tmp_item_array); private: ObLDCItem *item_array_; int64_t item_count_; + ObLDCItem *primary_zone_item_array_; + int64_t primary_zone_item_count_; + //store start index of each site, //array[MAX_IDC_TYPE] store the end index, just for traverse efficiently int64_t site_start_index_array_[MAX_IDC_TYPE + 1]; diff --git a/src/obproxy/proxy/route/ob_ldc_route.cpp b/src/obproxy/proxy/route/ob_ldc_route.cpp index 89290f037dbb952aeb719db8ae5a83e87186034f..aa4e73d679fe7ab49646c773832ac68a47c20652 100644 --- a/src/obproxy/proxy/route/ob_ldc_route.cpp +++ b/src/obproxy/proxy/route/ob_ldc_route.cpp @@ -625,6 +625,28 @@ const ObLDCItem *ObLDCRoute::get_next_item() } return ret_item; } + +const ObLDCItem *ObLDCRoute::get_next_primary_zone_item() +{ + ObLDCItem *ret_item = NULL; + + if (!location_.is_primary_zone_empty()) { + ObLDCItem *pz_item_array = location_.get_primary_zone_item_array(); + int64_t pz_array_count = location_.primary_zone_count(); + for (int64_t i = 0; i < pz_array_count; ++i) { + ret_item = &pz_item_array[i]; + if (!ret_item->is_used_) { + ret_item->is_used_ = true; + break; + } else { + ret_item = NULL; + } + } + } + + return ret_item; +} + } // end of namespace proxy } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/proxy/route/ob_ldc_route.h b/src/obproxy/proxy/route/ob_ldc_route.h index 80d81ba87a8c04cea5ee31510b1bc97cd7bea735..0aa8df069aab367c1d2e47b729b69769e94d1713 100644 --- a/src/obproxy/proxy/route/ob_ldc_route.h +++ b/src/obproxy/proxy/route/ob_ldc_route.h @@ -29,7 +29,10 @@ public: ~ObLDCRoute() {} void reset_cursor(); void reset(); + const ObLDCItem *get_next_item(); + const ObLDCItem *get_next_primary_zone_item(); + bool is_reach_end() const; bool is_follower_first_policy() const { return (policy_ >= FOLLOWER_FIRST && policy_ <= UNMERGE_FOLLOWER_FIRST_OPTIMIZED); } ObRouteType get_curr_route_type() const; diff --git a/src/obproxy/proxy/route/ob_mysql_route.cpp b/src/obproxy/proxy/route/ob_mysql_route.cpp index a457bda7916f1a5cf7f157615b4f5f66d9e905b5..008ba529c57abd89127957d64176500198fff6e4 100644 --- a/src/obproxy/proxy/route/ob_mysql_route.cpp +++ b/src/obproxy/proxy/route/ob_mysql_route.cpp @@ -59,7 +59,8 @@ int64_t ObRouteParam::to_string(char *buf, const int64_t buf_len) const K_(is_need_force_flush), K_(tenant_version), K_(timeout_us), - K_(current_idc_name)); + K_(current_idc_name), + K_(cluster_version)); J_OBJ_END(); return pos; } @@ -435,7 +436,7 @@ int ObMysqlRoute::state_table_entry_lookup(int event, void *data) param_.is_need_force_flush_ = result->is_need_force_flush_; } if (NULL != table_entry_) { - table_entry_->check_and_set_expire_time(param_.tenant_version_, table_entry_->is_dummy_entry()); + table_entry_->check_and_set_expire_time(param_.tenant_version_, table_entry_->is_sys_dummy_entry()); } result->target_entry_ = NULL; @@ -492,35 +493,33 @@ inline int ObMysqlRoute::check_and_rebuild_call_params() ObSessionSysField *sys_filed = NULL; ObSessionUserField *user_filed = NULL; for (int32_t i = 0; OB_SUCC(ret) && i < call_info.param_count_; ++i) { - ObProxyCallParam &call_param = call_info.params_.at(i); - if (CALL_TOKEN_SYS_VAR == call_param.type_) { + ObProxyCallParam* call_param = call_info.params_.at(i); + if (CALL_TOKEN_SYS_VAR == call_param->type_) { sys_filed = NULL; - if (OB_FAIL(client_info.get_sys_variable(call_param.str_value_.string_, sys_filed))) { - LOG_INFO("fail to find sys variables", "name", call_param.str_value_.string_, K(ret)); + if (OB_FAIL(client_info.get_sys_variable(call_param->str_value_.config_string_, sys_filed))) { + LOG_INFO("fail to find sys variables", "name", call_param->str_value_.config_string_, K(ret)); } else if (NULL != sys_filed) { - char *buf = call_param.str_value_.buf_; - const int64_t max_size = call_param.str_value_.get_max_size(); + char buf[OBPROXY_MAX_STRING_VALUE_LENGTH]; int64_t pos = 0; - if (OB_FAIL(sys_filed->value_.print_sql_literal(buf, max_size, pos))) { + if (OB_FAIL(sys_filed->value_.print_sql_literal(buf, OBPROXY_MAX_STRING_VALUE_LENGTH, pos))) { LOG_INFO("fail to print sql literal", K(pos), K(i), KPC(sys_filed), K(ret)); } else { ObString new_value(pos, buf); - call_param.str_value_.set(new_value); + call_param->str_value_.set_value(new_value); } } - } else if (CALL_TOKEN_USER_VAR == call_param.type_) { + } else if (CALL_TOKEN_USER_VAR == call_param->type_) { user_filed = NULL; - if (OB_FAIL(client_info.get_user_variable(call_param.str_value_.string_, user_filed))) { - LOG_INFO("fail to find sys variables, ignore", "name", call_param.str_value_.string_, K(ret)); + if (OB_FAIL(client_info.get_user_variable(call_param->str_value_.config_string_, user_filed))) { + LOG_INFO("fail to find sys variables", K_(call_param->str_value_.config_string), K(ret)); } else if (NULL != user_filed) { - char *buf = call_param.str_value_.buf_; - const int64_t max_size = call_param.str_value_.get_max_size(); + char buf[OBPROXY_MAX_STRING_VALUE_LENGTH]; int64_t pos = 0; - if (OB_FAIL(user_filed->value_.print_plain_str_literal(buf, max_size, pos))) { + if (OB_FAIL(user_filed->value_.print_plain_str_literal(buf, OBPROXY_MAX_STRING_VALUE_LENGTH, pos))) { LOG_INFO("fail to print sql literal, ignore", K(pos), K(i), KPC(user_filed), K(ret)); } else { ObString new_value(pos, buf); - call_param.str_value_.set(new_value); + call_param->str_value_.set_value(new_value); } } } @@ -664,6 +663,7 @@ inline void ObMysqlRoute::setup_partition_entry_lookup() part_param.set_table_entry(table_entry_); part_param.mysql_proxy_ = param_.mysql_proxy_; part_param.tenant_version_ = param_.tenant_version_; + part_param.cluster_version_ = param_.cluster_version_; if (!param_.current_idc_name_.empty()) { MEMCPY(part_param.current_idc_name_buf_, param_.current_idc_name_.ptr(), param_.current_idc_name_.length()); part_param.current_idc_name_.assign_ptr(part_param.current_idc_name_buf_, param_.current_idc_name_.length()); @@ -929,6 +929,7 @@ inline int ObMysqlRoute::deep_copy_route_param(ObRouteParam ¶m) param_.need_pl_route_ = param.need_pl_route_; param_.is_oracle_mode_ = param.is_oracle_mode_; param_.is_need_force_flush_ = param.is_need_force_flush_; + param_.cluster_version_ = param.cluster_version_; if (!param.current_idc_name_.empty()) { MEMCPY(param_.current_idc_name_buf_, param.current_idc_name_.ptr(), param.current_idc_name_.length()); param_.current_idc_name_.assign_ptr(param_.current_idc_name_buf_, param.current_idc_name_.length()); diff --git a/src/obproxy/proxy/route/ob_mysql_route.h b/src/obproxy/proxy/route/ob_mysql_route.h index 36e1f9b511431052ab3c71544bda7f2fb41ce3da..cfa676cc9c16d2c1af75cfff387f36820d7ce90a 100644 --- a/src/obproxy/proxy/route/ob_mysql_route.h +++ b/src/obproxy/proxy/route/ob_mysql_route.h @@ -89,9 +89,9 @@ public: ObRouteParam() : cont_(NULL), name_(), force_renew_(false), use_lower_case_name_(false), is_partition_table_route_supported_(false), need_pl_route_(false), is_oracle_mode_(false), - is_need_force_flush_(false), result_(), mysql_proxy_(NULL), client_request_(NULL), client_info_(), + is_need_force_flush_(false), result_(), mysql_proxy_(NULL), client_request_(NULL), client_info_(NULL), route_(NULL), cr_version_(-1), cr_id_(-1), tenant_version_(0), timeout_us_(-1), current_idc_name_(), - cr_(NULL) {} + cluster_version_(0), cr_(NULL) {} ~ObRouteParam() { reset(); } void reset(); @@ -121,6 +121,7 @@ public: int64_t timeout_us_; common::ObString current_idc_name_; char current_idc_name_buf_[OB_PROXY_MAX_IDC_NAME_LENGTH]; + int64_t cluster_version_; private: // for defense, ensure mysql_proxy_ is safely used @@ -150,6 +151,7 @@ inline void ObRouteParam::reset() is_oracle_mode_ = false; is_need_force_flush_ = false; mysql_proxy_ = NULL; + client_request_ = NULL; route_ = NULL; cr_version_ = -1; cr_id_ = -1; @@ -157,6 +159,7 @@ inline void ObRouteParam::reset() timeout_us_ = -1; set_cluster_resource(NULL); current_idc_name_.reset(); + cluster_version_ = 0; } // all route related work, include table entry lookup, sql fast parse, diff --git a/src/obproxy/proxy/route/ob_partition_cache.cpp b/src/obproxy/proxy/route/ob_partition_cache.cpp index 1470bec898dcd603b7d2ee376c5737ca6bd2922a..e465de57c992cf76706da7de1953430703443a8a 100644 --- a/src/obproxy/proxy/route/ob_partition_cache.cpp +++ b/src/obproxy/proxy/route/ob_partition_cache.cpp @@ -562,22 +562,33 @@ int init_partition_map_for_thread() { int ret = OB_SUCCESS; const int64_t event_thread_count = g_event_processor.thread_count_for_type_[ET_CALL]; + for (int64_t i = 0; (i < event_thread_count) && OB_SUCC(ret); ++i) { + if (OB_FAIL(init_partition_map_for_one_thread(i))) { + LOG_WARN("fail to init partition_map", K(i), K(ret)); + } + } + return ret; +} + +int init_partition_map_for_one_thread(int64_t index) +{ + int ret = OB_SUCCESS; ObEThread **ethreads = NULL; if (OB_ISNULL(ethreads = g_event_processor.event_thread_[ET_CALL])) { ret = OB_ERR_UNEXPECTED; PROXY_NET_LOG(ERROR, "fail to get ET_NET thread", K(ret)); + } else if (OB_ISNULL(ethreads[index])) { + ret = OB_ERR_UNEXPECTED; + PROXY_NET_LOG(ERROR, "fail to get ET_NET thread", K(ret)); } else { - for (int64_t i = 0; (i < event_thread_count) && OB_SUCC(ret); ++i) { - if (OB_ISNULL(ethreads[i]->partition_map_ = new (std::nothrow) ObPartitionRefHashMap(ObModIds::OB_PROXY_PARTITION_ENTRY_MAP))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to new ObPartitionRefHashMap", K(i), K(ethreads[i]), K(ret)); - } else if (OB_FAIL(ethreads[i]->partition_map_->init())) { - LOG_WARN("fail to init partition_map", K(ret)); - } + if (OB_ISNULL(ethreads[index]->partition_map_ = new (std::nothrow) ObPartitionRefHashMap(ObModIds::OB_PROXY_PARTITION_ENTRY_MAP))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to new ObPartitionRefHashMap", K(index), K(ethreads[index]), K(ret)); + } else if (OB_FAIL(ethreads[index]->partition_map_->init())) { + LOG_WARN("fail to init partition_map", K(ret)); } } return ret; - } int ObPartitionRefHashMap::clean_hash_map() diff --git a/src/obproxy/proxy/route/ob_partition_cache.h b/src/obproxy/proxy/route/ob_partition_cache.h index b8f442efbcc95e16d5f6bd55c9ca62312ee5c880..ec3043f48edf0acc7b448dbecd4f6bffe5591aa3 100644 --- a/src/obproxy/proxy/route/ob_partition_cache.h +++ b/src/obproxy/proxy/route/ob_partition_cache.h @@ -157,6 +157,7 @@ private: }; int init_partition_map_for_thread(); +int init_partition_map_for_one_thread(int64_t index); } // end of namespace proxy } // end of namespace obproxy diff --git a/src/obproxy/proxy/route/ob_partition_processor.cpp b/src/obproxy/proxy/route/ob_partition_processor.cpp index e2ac35571ce6234353c4095b58fd1f4e1d67669f..87b8d0a1f100b35dc99e031792d86d22b7ba4b5c 100644 --- a/src/obproxy/proxy/route/ob_partition_processor.cpp +++ b/src/obproxy/proxy/route/ob_partition_processor.cpp @@ -275,7 +275,7 @@ int ObPartitionEntryCont::handle_client_resp(void *data) ret = OB_ERR_UNEXPECTED; LOG_WARN("rs_fetcher and entry can not be NULL", K(rs_fetcher), K(entry), K(ret)); } else if (OB_FAIL(ObRouteUtils::fetch_one_partition_entry_info( - *rs_fetcher, *param_.get_table_entry(), entry))) { + *rs_fetcher, *param_.get_table_entry(), entry, param_.cluster_version_))) { LOG_WARN("fail to fetch one partition entry info", K(ret)); } else if (NULL == entry) { PROCESSOR_INCREMENT_DYN_STAT(GET_PARTITION_ENTRY_FROM_REMOTE_FAIL); @@ -485,7 +485,8 @@ int ObPartitionEntryCont::lookup_entry_remote() char sql[OB_SHORT_SQL_LENGTH]; sql[0] = '\0'; if (OB_FAIL(ObRouteUtils::get_partition_entry_sql(sql, OB_SHORT_SQL_LENGTH, - param_.get_table_entry()->get_names(), param_.partition_id_, param_.is_need_force_flush_))) { + param_.get_table_entry()->get_names(), param_.partition_id_, + param_.is_need_force_flush_, param_.cluster_version_))) { LOG_WARN("fail to get table entry sql", K(sql), K(ret)); } else { const ObMysqlRequestParam request_param(sql, param_.current_idc_name_); @@ -596,6 +597,7 @@ inline void ObPartitionParam::deep_copy(ObPartitionParam &other) // no need assign result_ mysql_proxy_ = other.mysql_proxy_; tenant_version_ = other.tenant_version_; + cluster_version_ = other.cluster_version_; set_table_entry(other.get_table_entry()); if (!other.current_idc_name_.empty()) { MEMCPY(current_idc_name_buf_, other.current_idc_name_.ptr(), other.current_idc_name_.length()); diff --git a/src/obproxy/proxy/route/ob_partition_processor.h b/src/obproxy/proxy/route/ob_partition_processor.h index e000ddad138de593825925e4d3775cbdae54022c..fcbb88a58195468234ef38ceebe8d5b299df8985 100644 --- a/src/obproxy/proxy/route/ob_partition_processor.h +++ b/src/obproxy/proxy/route/ob_partition_processor.h @@ -50,7 +50,8 @@ public: : cont_(NULL), partition_id_(common::OB_INVALID_ID), force_renew_(false), is_need_force_flush_(false), result_(), mysql_proxy_(NULL), - current_idc_name_(), tenant_version_(0), table_entry_(NULL) {} + current_idc_name_(), tenant_version_(0), + cluster_version_(0), table_entry_(NULL) {} ~ObPartitionParam() { reset(); } void reset(); @@ -70,6 +71,7 @@ public: common::ObString current_idc_name_; char current_idc_name_buf_[OB_PROXY_MAX_IDC_NAME_LENGTH]; uint64_t tenant_version_; + int64_t cluster_version_; private: ObTableEntry *table_entry_; @@ -95,6 +97,7 @@ inline void ObPartitionParam::reset() set_table_entry(NULL); current_idc_name_.reset(); tenant_version_ = 0; + cluster_version_ = 0; } inline void ObPartitionParam::set_table_entry(ObTableEntry *entry) diff --git a/src/obproxy/proxy/route/ob_route_struct.cpp b/src/obproxy/proxy/route/ob_route_struct.cpp index ef69a2dc8e663344edd5337546cbca3c8d772df9..d3ed65f72a35f6c0a3f9a40cf79a145c94cd7324 100644 --- a/src/obproxy/proxy/route/ob_route_struct.cpp +++ b/src/obproxy/proxy/route/ob_route_struct.cpp @@ -315,12 +315,12 @@ int64_t ObTableEntryKey::to_string(char *buf, const int64_t buf_len) const return pos; } -void ObRouteEntry::check_and_set_expire_time(const uint64_t tenant_version, const bool is_dummy_entry) +void ObRouteEntry::check_and_set_expire_time(const uint64_t tenant_version, const bool is_sys_dummy_entry) { int64_t period_us = obutils::get_global_proxy_config().location_expire_period_time; const int64_t TENANT_LOCALITY_CHANGE_TIME = 60 * 1000 * 1000; const int64_t TENANT_LOCALITY_CHANGE_TIME_CONFIG = -1; - if (AVAIL == state_ && !is_dummy_entry) { + if (AVAIL == state_ && !is_sys_dummy_entry) { if (tenant_version != tenant_version_) { tenant_version_ = tenant_version; // -1 means the change comes from a locality change diff --git a/src/obproxy/proxy/route/ob_route_struct.h b/src/obproxy/proxy/route/ob_route_struct.h index 0a0e5bb722ba8875c796676ea1996a54506c3d53..d6bfbdba9172b093870ae8c7650b17db018d8717 100644 --- a/src/obproxy/proxy/route/ob_route_struct.h +++ b/src/obproxy/proxy/route/ob_route_struct.h @@ -203,9 +203,7 @@ int ObProxyRerouteInfo::deserialize_struct_content(const char *buf, const int64_ if (ObAddr::IPV4 == version) { replica_.server_.set_ipv4_addr(ipv4, port); } else { - // must IPV6, not support yet, TODO open below later - //server_.set_ipv6_addr(ipv6_high, ipv6_low, port); - replica_.server_.reset(); + replica_.server_.set_ipv6_addr(ipv6_high, ipv6_low, port); } } int64_t table_name_len = 0; @@ -233,7 +231,7 @@ inline int ObProxyReplicaLocation::add_addr(const char *ip, const int64_t port) int ret = common::OB_SUCCESS; if (OB_UNLIKELY(NULL == ip || port <= 0)) { ret = common::OB_INVALID_ARGUMENT; - } else if (OB_UNLIKELY(!server_.set_ipv4_addr(ip, static_cast(port)))) { + } else if (OB_UNLIKELY(!server_.set_ip_addr(ip, static_cast(port)))) { ret = common::OB_INVALID_ARGUMENT; } return ret; @@ -430,7 +428,7 @@ public: uint64_t get_tenant_version() const { return tenant_version_; } int64_t get_time_for_expired() const { return time_for_expired_; } void set_time_for_expired(int64_t expire_time) { time_for_expired_ = expire_time; } - void check_and_set_expire_time(const uint64_t tenant_version, const bool is_dummy_entry); + void check_and_set_expire_time(const uint64_t tenant_version, const bool is_sys_dummy_entry); protected: int64_t cr_version_; // one entry must belong to one cluster with the specfied version @@ -517,6 +515,7 @@ public: bool is_sys_tenant() const; bool is_oceanbase_db() const; bool is_all_dummy_table() const; + bool is_binlog_table() const; int deep_copy(const ObTableEntryName &name, char *buf, const int64_t buf_len); void shallow_copy(const ObTableEntryName &name); void shallow_copy(const common::ObString &cluster_name, const common::ObString &tenant_name, @@ -525,7 +524,6 @@ public: const common::ObString &database_name, const common::ObString &package_name, const common::ObString &table_name); - common::ObString cluster_name_; common::ObString tenant_name_; common::ObString database_name_; @@ -585,6 +583,12 @@ inline bool ObTableEntryName::is_all_dummy_table() const return is_valid() && table_name_[0] == '_' && all_dummy_tname_str == table_name_; } +inline bool ObTableEntryName::is_binlog_table() const +{ + static const common::ObString binlog_tname_str(share::OB_ALL_BINLOG_DUMMY_TNAME); + return is_valid() && binlog_tname_str == table_name_; +} + inline bool ObTableEntryName::is_ob_dummy() const { return is_oceanbase_db() && is_all_dummy_table(); diff --git a/src/obproxy/proxy/route/ob_route_utils.cpp b/src/obproxy/proxy/route/ob_route_utils.cpp index f627d48fdf6093541048e40a47ac8bbdee4008b0..0b702046a4ff418c8662f0ca65d6a16300625f5d 100644 --- a/src/obproxy/proxy/route/ob_route_utils.cpp +++ b/src/obproxy/proxy/route/ob_route_utils.cpp @@ -54,24 +54,25 @@ static const char *PROXY_PLAIN_SCHEMA_SQL = "SELECT /*+READ_CONSISTENCY(WEAK)%s*/ * " "FROM oceanbase.%s " "WHERE tenant_name = '%.*s' AND database_name = '%.*s' AND table_name = '%.*s' " - "AND partition_id = %ld " + "AND %s = %ld " "ORDER BY role ASC LIMIT %ld"; static const char *PROXY_TENANT_SCHEMA_SQL = //svr_ip, sql_port, table_id, role, part_num, replica_num "SELECT /*+READ_CONSISTENCY(WEAK)*/ * " "FROM oceanbase.%s " "WHERE tenant_name = '%.*s' AND database_name = '%.*s' AND table_name = '%.*s' AND sql_port > 0 " - "ORDER BY partition_id ASC, role ASC LIMIT %ld"; + "ORDER BY %s ASC, role ASC LIMIT %ld"; static const char *PROXY_PART_INFO_SQL = - "SELECT /*+READ_CONSISTENCY(WEAK)*/ template_num, part_level, part_num, part_type, part_space, part_expr, " - "part_interval_bin, interval_start_bin, sub_part_num, sub_part_type, sub_part_space, " - "sub_part_expr, def_sub_part_interval_bin, def_sub_interval_start_bin, " - "part_key_num, part_key_name, part_key_type, part_key_idx, part_key_level, part_key_extra, " - "spare1, spare2, spare4, spare5 " + "SELECT /*+READ_CONSISTENCY(WEAK)*/ * " "FROM oceanbase.%s " "WHERE table_id = %lu order by part_key_idx LIMIT %d;"; +static const char *PROXY_PART_INFO_SQL_V4 = + "SELECT /*+READ_CONSISTENCY(WEAK)*/ * " + "FROM oceanbase.%s " + "WHERE table_id = %lu and tenant_name = '%.*s' order by part_key_idx LIMIT %d;"; + static const char *PROXY_FIRST_PART_SQL = "SELECT /*+READ_CONSISTENCY(WEAK)*/ part_id, part_name, high_bound_val_bin, sub_part_num " "FROM oceanbase.%s " @@ -83,16 +84,26 @@ static const char *PROXY_HASH_FIRST_PART_SQL = "FROM oceanbase.%s " "WHERE table_id = %lu LIMIT %ld;"; +static const char *PROXY_FIRST_PART_SQL_V4 = + "SELECT /*+READ_CONSISTENCY(WEAK)*/ tablet_id, part_id, part_name, high_bound_val_bin, sub_part_num " + "FROM oceanbase.%s " + "WHERE table_id = %lu and tenant_name = '%.*s' LIMIT %ld;"; + static const char *PROXY_SUB_PART_SQL = - "SELECT /*+READ_CONSISTENCY(WEAK)*/ part_id, sub_part_id, high_bound_val_bin " + "SELECT /*+READ_CONSISTENCY(WEAK)*/ part_id, sub_part_id, part_name, high_bound_val_bin " "FROM oceanbase.%s " "WHERE table_id = %lu and part_id = %ld LIMIT %ld;"; static const char *PROXY_NON_TEMPLATE_SUB_PART_SQL = - "SELECT /*+READ_CONSISTENCY(WEAK)*/ part_id, sub_part_id, high_bound_val_bin " + "SELECT /*+READ_CONSISTENCY(WEAK)*/ part_id, sub_part_id, part_name, high_bound_val_bin " "FROM oceanbase.%s " "WHERE table_id = %lu LIMIT %ld;"; +static const char *PROXY_SUB_PART_SQL_V4 = + "SELECT /*+READ_CONSISTENCY(WEAK)*/ tablet_id, part_id, sub_part_id, part_name, high_bound_val_bin " + "FROM oceanbase.%s " + "WHERE table_id = %lu and tenant_name = '%.*s' LIMIT %ld;"; + static const char *PROXY_ROUTINE_SCHEMA_SQL = "SELECT /*+READ_CONSISTENCY(WEAK)*/ * " "FROM oceanbase.%s " @@ -107,6 +118,15 @@ static const char *PROXY_ROUTINE_SCHEMA_SQL_WITH_PACKAGE = "AND partition_id = 0 AND svr_ip = '' AND sql_port = 0 " "ORDER BY table_id ASC LIMIT 1;"; +static const char *PROXY_ROUTINE_SCHEMA_SQL_V4 = + "SELECT /*+READ_CONSISTENCY(WEAK)*/ * " + "FROM %s " + "WHERE tenant_name = '%.*s' and database_name = '%.*s' and package_name = '%.*s' " + "and routine_name = '%.*s';"; + +static const char *PROXY_BINLOG_ADDR_SQL = + "show binlog server for tenant `%.*s`.`%.*s`"; + static void get_tenant_name(const ObString &origin_tenant_name, char *new_tenant_name_buf, ObString &new_tenant_name) { new_tenant_name = origin_tenant_name; int32_t pos = 0; @@ -129,7 +149,8 @@ static void get_tenant_name(const ObString &origin_tenant_name, char *new_tenant int ObRouteUtils::get_table_entry_sql(char *sql_buf, const int64_t buf_len, ObTableEntryName &name, - bool is_need_force_flush /*false*/) + bool is_need_force_flush, /*false*/ + const int64_t cluster_version) { int ret = OB_SUCCESS; if (OB_ISNULL(sql_buf) || OB_UNLIKELY(buf_len <= 0) || OB_UNLIKELY(!name.is_valid())) { @@ -146,6 +167,7 @@ int ObRouteUtils::get_table_entry_sql(char *sql_buf, const int64_t buf_len, new_tenant_name.length(), new_tenant_name.ptr(), name.database_name_.length(), name.database_name_.ptr(), name.table_name_.length(), name.table_name_.ptr(), + IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version) ? "partition_id" : "tablet_id", INT64_MAX)); } else { const int64_t FIRST_PARTITION_ID = 0; @@ -155,6 +177,7 @@ int ObRouteUtils::get_table_entry_sql(char *sql_buf, const int64_t buf_len, new_tenant_name.length(), new_tenant_name.ptr(), name.database_name_.length(), name.database_name_.ptr(), name.table_name_.length(), name.table_name_.ptr(), + IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version) ? "partition_id" : "tablet_id", FIRST_PARTITION_ID, INT64_MAX)); } @@ -169,17 +192,31 @@ int ObRouteUtils::get_table_entry_sql(char *sql_buf, const int64_t buf_len, int ObRouteUtils::get_part_info_sql(char *sql_buf, const int64_t buf_len, - const uint64_t table_id) + const uint64_t table_id, + ObTableEntryName &name, + const int64_t cluster_version) { int ret = OB_SUCCESS; - if (OB_ISNULL(sql_buf) || OB_UNLIKELY(buf_len <= 0)) { + if (OB_ISNULL(sql_buf) || OB_UNLIKELY(buf_len <= 0) || OB_UNLIKELY(!name.is_valid())) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid input value", LITERAL_K(sql_buf), K(buf_len), K(ret)); + LOG_WARN("invalid input value", LITERAL_K(sql_buf), K(buf_len), K(name), K(ret)); } else { - int64_t len = snprintf(sql_buf, buf_len, PROXY_PART_INFO_SQL, - OB_ALL_VIRTUAL_PROXY_PARTITION_INFO_TNAME, - table_id, - OB_MAX_PARTITION_KEY_COLUMN_NUMBER); + int64_t len = 0; + if (IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + len = snprintf(sql_buf, buf_len, PROXY_PART_INFO_SQL, + OB_ALL_VIRTUAL_PROXY_PARTITION_INFO_TNAME, + table_id, + OB_MAX_PARTITION_KEY_COLUMN_NUMBER); + } else { + char new_tenant_name_buf[OB_MAX_TENANT_NAME_LENGTH * 2 + 1]; + ObString new_tenant_name; + get_tenant_name(name.tenant_name_, new_tenant_name_buf, new_tenant_name); + len = snprintf(sql_buf, buf_len, PROXY_PART_INFO_SQL_V4, + OB_ALL_VIRTUAL_PROXY_PARTITION_INFO_TNAME, + table_id, + new_tenant_name.length(), new_tenant_name.ptr(), + OB_MAX_PARTITION_KEY_COLUMN_NUMBER); + } if (OB_UNLIKELY(len <= 0) || OB_UNLIKELY(len >= buf_len)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to fill sql", K(sql_buf), K(len), K(buf_len), K(ret)); @@ -192,23 +229,34 @@ int ObRouteUtils::get_part_info_sql(char *sql_buf, int ObRouteUtils::get_first_part_sql(char *sql_buf, const int64_t buf_len, const uint64_t table_id, - const bool is_hash_part) + const bool is_hash_part, + ObTableEntryName &name, + const int64_t cluster_version) { int ret = OB_SUCCESS; int64_t len = 0; - if (OB_ISNULL(sql_buf) || OB_UNLIKELY(buf_len <= 0)) { + if (OB_ISNULL(sql_buf) || OB_UNLIKELY(buf_len <= 0) || OB_UNLIKELY(!name.is_valid())) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid input value", LITERAL_K(sql_buf), K(buf_len), K(ret)); - } else { + LOG_WARN("invalid input value", LITERAL_K(sql_buf), K(buf_len), K(name), K(ret)); + } else if (IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { len = snprintf(sql_buf, buf_len, is_hash_part ? PROXY_HASH_FIRST_PART_SQL : PROXY_FIRST_PART_SQL, + OB_ALL_VIRTUAL_PROXY_PARTITION_TNAME, + table_id, + INT64_MAX); + } else { + char new_tenant_name_buf[OB_MAX_TENANT_NAME_LENGTH * 2 + 1]; + ObString new_tenant_name; + get_tenant_name(name.tenant_name_, new_tenant_name_buf, new_tenant_name); + len = snprintf(sql_buf, buf_len, PROXY_FIRST_PART_SQL_V4, OB_ALL_VIRTUAL_PROXY_PARTITION_TNAME, table_id, + new_tenant_name.length(), new_tenant_name.ptr(), INT64_MAX); - if (OB_UNLIKELY(len <= 0) || OB_UNLIKELY(len >= buf_len)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("fail to fill sql", K(sql_buf), K(len), K(buf_len), K(ret)); - } + } + if (OB_UNLIKELY(len <= 0) || OB_UNLIKELY(len >= buf_len)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to fill sql", K(sql_buf), K(len), K(buf_len), K(ret)); } return ret; @@ -217,18 +265,29 @@ int ObRouteUtils::get_first_part_sql(char *sql_buf, int ObRouteUtils::get_sub_part_sql(char *sql_buf, const int64_t buf_len, const uint64_t table_id, - const bool is_template_table) + const bool is_template_table, + ObTableEntryName &name, + const int64_t cluster_version) { int ret = OB_SUCCESS; int64_t len = 0; - if (OB_ISNULL(sql_buf) || OB_UNLIKELY(buf_len <= 0)) { + if (OB_ISNULL(sql_buf) || OB_UNLIKELY(buf_len <= 0) || OB_UNLIKELY(!name.is_valid())) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid input value", LITERAL_K(sql_buf), K(buf_len), K(ret)); + LOG_WARN("invalid input value", LITERAL_K(sql_buf), K(buf_len), K(name), K(ret)); } else { // assume all sub_part are same for each fisrt part // templete part id is -1 - if (is_template_table) { + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + char new_tenant_name_buf[OB_MAX_TENANT_NAME_LENGTH * 2 + 1]; + ObString new_tenant_name; + get_tenant_name(name.tenant_name_, new_tenant_name_buf, new_tenant_name); + len = snprintf(sql_buf, buf_len, PROXY_SUB_PART_SQL_V4, + OB_ALL_VIRTUAL_PROXY_SUB_PARTITION_TNAME, + table_id, + new_tenant_name.length(), new_tenant_name.ptr(), + INT64_MAX); + } else if (is_template_table) { const int64_t TEMPLATE_PART_ID = -1; len = snprintf(sql_buf, buf_len, PROXY_SUB_PART_SQL, OB_ALL_VIRTUAL_PROXY_SUB_PARTITION_TNAME, @@ -251,6 +310,32 @@ int ObRouteUtils::get_sub_part_sql(char *sql_buf, return ret; } +int ObRouteUtils::get_binlog_entry_sql(char *sql_buf, + const int64_t buf_len, + const ObString &cluster_name, + const ObString &tenant_name) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(sql_buf) || OB_UNLIKELY(buf_len <= 0) + || OB_UNLIKELY(cluster_name.empty()) + || OB_UNLIKELY(tenant_name.empty())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid input value", LITERAL_K(sql_buf), K(buf_len), K(cluster_name), K(tenant_name), K(ret)); + } else { + int64_t len = 0; + len = static_cast(snprintf(sql_buf, buf_len, PROXY_BINLOG_ADDR_SQL, + cluster_name.length(), cluster_name.ptr(), + tenant_name.length(), tenant_name.ptr())); + + if (OB_UNLIKELY(len <= 0) || OB_UNLIKELY(len >= buf_len)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to fill binlog sql", K(sql_buf), K(len), K(buf_len), K(ret)); + } + } + + return ret; +} + bool is_fake_ip_port(const char *ip_str, const int64_t port) { const ObString fake_ip("0.0.0.0"); @@ -259,11 +344,12 @@ bool is_fake_ip_port(const char *ip_str, const int64_t port) } int ObRouteUtils::fetch_table_entry(ObResultSetFetcher &rs_fetcher, - ObTableEntry &entry) + ObTableEntry &entry, + const int64_t cluster_version) { int ret = OB_SUCCESS; int64_t tmp_real_str_len = 0; - char ip_str[OB_IP_STR_BUFF]; + char ip_str[MAX_IP_ADDR_LENGTH]; ip_str[0] = '\0'; int64_t port = 0; uint64_t table_id = OB_INVALID_ID; @@ -290,7 +376,7 @@ int ObRouteUtils::fetch_table_entry(ObResultSetFetcher &rs_fetcher, replica_type = -1; table_type = -1; - PROXY_EXTRACT_STRBUF_FIELD_MYSQL(rs_fetcher, "svr_ip", ip_str, OB_IP_STR_BUFF, tmp_real_str_len); + PROXY_EXTRACT_STRBUF_FIELD_MYSQL(rs_fetcher, "svr_ip", ip_str, MAX_IP_ADDR_LENGTH, tmp_real_str_len); PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "sql_port", port, int64_t); PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "table_id", table_id, uint64_t); PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "role", role, int64_t); @@ -307,7 +393,11 @@ int ObRouteUtils::fetch_table_entry(ObResultSetFetcher &rs_fetcher, } if (OB_SUCC(ret)) { - PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "spare1", replica_type, int32_t); + if (IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "spare1", replica_type, int32_t); + } else { + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "replica_type", replica_type, int32_t); + } if (OB_ERR_COLUMN_NOT_FOUND == ret) { LOG_DEBUG("can not find spare1, maybe is old server, ignore", K(replica_type), K(ret)); ret = OB_SUCCESS; @@ -316,7 +406,11 @@ int ObRouteUtils::fetch_table_entry(ObResultSetFetcher &rs_fetcher, } if (OB_SUCC(ret)) { - PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "spare2", dup_replica_type, int32_t); + if (IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "spare2", dup_replica_type, int32_t); + } else { + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "dup_replica_type", dup_replica_type, int32_t); + } if (OB_ERR_COLUMN_NOT_FOUND == ret) { LOG_DEBUG("can not find spare2, maybe is old server, ignore", K(dup_replica_type), K(ret)); ret = OB_SUCCESS; @@ -442,16 +536,45 @@ int ObRouteUtils::fetch_table_entry(ObResultSetFetcher &rs_fetcher, return ret; } -int ObRouteUtils::fetch_part_info(ObResultSetFetcher &rs_fetcher, ObProxyPartInfo &part_info) +int ObRouteUtils::split_part_expr(ObString expr, ObIArray &arr) +{ + int ret = OB_SUCCESS; + ObString tmp; + while (OB_SUCC(ret) && !expr.empty()) { + tmp = expr.split_on(',').trim(); + if (tmp.empty()) { + tmp = expr.trim(); + expr.reset(); + } + if (tmp[0] == '`') { + tmp.assign_ptr(tmp.ptr() + 1, tmp.length() - 1); + } + if (tmp[tmp.length() - 1] == '`') { + tmp.assign_ptr(tmp.ptr(), tmp.length() - 1); + } + if (OB_FAIL(arr.push_back(tmp))) { + LOG_WARN("fail to push back", K(tmp), K(ret)); + } else { + LOG_DEBUG("succ to push back", K(tmp)); + } + } + return ret; +} + + +int ObRouteUtils::fetch_part_info(ObResultSetFetcher &rs_fetcher, ObProxyPartInfo &part_info, const int64_t cluster_version) { int ret = OB_SUCCESS; ObPartitionLevel part_level = PARTITION_LEVEL_ONE; int64_t part_key_num = 1; int64_t template_num = 1; + ObString part_expr; + ObString sub_part_expr; // init part key info part_info.get_part_key_info().key_num_ = 0; + part_info.set_cluster_version(cluster_version); for (int64_t i = 0; i < part_key_num && OB_SUCC(ret); ++i) { // get first row if (OB_FAIL(rs_fetcher.next())) { @@ -483,6 +606,39 @@ int ObRouteUtils::fetch_part_info(ObResultSetFetcher &rs_fetcher, ObProxyPartInf part_key_num = OBPROXY_MAX_PART_KEY_NUM; } + // get part expr + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "part_expr", part_expr); + char *buf = NULL; + if (part_expr.empty()) { + LOG_DEBUG("part expression is empty"); + } else if (OB_ISNULL(buf = static_cast(part_info.get_allocator().alloc(part_expr.length())))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to allc part key name", K(buf), K(part_expr.length()), K(ret)); + } else { + memcpy(buf, part_expr.ptr(), part_expr.length()); + part_expr.assign_ptr(buf, part_expr.length()); + } + + // get sub part expr + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "sub_part_expr", sub_part_expr); + if (sub_part_expr.empty()) { + LOG_DEBUG("sub part expression is empty"); + } else if (OB_ISNULL(buf = static_cast(part_info.get_allocator().alloc(sub_part_expr.length())))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to allc part key name", K(buf), K(sub_part_expr.length()), K(ret)); + } else { + memcpy(buf, sub_part_expr.ptr(), sub_part_expr.length()); + sub_part_expr.assign_ptr(buf, sub_part_expr.length()); + } + // split part expression + if (part_info.get_part_level() >= PARTITION_LEVEL_ONE + && OB_FAIL(split_part_expr(part_expr, part_info.get_part_columns()))) { + LOG_WARN("fail to split part expr", K(ret)); + } else if (part_info.get_part_level() == PARTITION_LEVEL_TWO + && OB_FAIL(split_part_expr(sub_part_expr, part_info.get_sub_part_columns())) ) { + LOG_WARN("fail to split sub part expr", K(ret)); + } + if (OB_FAIL(fetch_part_option(rs_fetcher, part_info))) { LOG_WARN("fail to get part option", K(ret)); } @@ -492,73 +648,60 @@ int ObRouteUtils::fetch_part_info(ObResultSetFetcher &rs_fetcher, ObProxyPartInf // get part key info for EACH line if (OB_SUCC(ret)) { - if (OB_FAIL(fetch_part_key(rs_fetcher, part_info))) { + if (OB_FAIL(fetch_part_key(rs_fetcher, part_info, cluster_version))) { LOG_WARN("fail to get part key", K(ret)); - } // end of if + } } // end of if (OB_SUCC(ret)) } // end of else } // end of for - if (OB_SUCC(ret)) { - if (OB_FAIL(build_part_desc(part_info))) { - LOG_WARN("fail to build part desc ", K(part_info), K(ret)); + // handle generated key, map the key for generated key calculation to real key + for (int64_t i = 0; i < part_info.get_part_key_info().key_num_; ++i) { + if (part_info.get_part_key_info().part_keys_[i].generated_col_idx_ >= 0) { + for (int64_t j = 0; j < part_info.get_part_key_info().key_num_; ++j) { + ObProxyParseString *l = &part_info.get_part_key_info().part_keys_[i].name_; + ObProxyParseString *r = &part_info.get_part_key_info().part_keys_[j].name_; + if (i != j && l->str_ != NULL + && r->str_ != NULL + && l->str_len_ == r->str_len_ + && 0 == strncasecmp(l->str_, r->str_, l->str_len_)) { + part_info.get_part_key_info().part_keys_[i].real_source_idx_ = j; + } + } + } } } return ret; } -int ObRouteUtils::build_part_desc(ObProxyPartInfo &part_info) { - int ret = OB_SUCCESS; - ObProxyPartOption &sub_part_opt = part_info.get_sub_part_option(); - - // for first part, we will build part desc in fetch_first_part - if (part_info.has_unknown_part_key()) { - LOG_INFO("part key type is unsopported, no need build part_desc", K(part_info)); - } else if (!part_info.is_template_table()) { - LOG_INFO("part table is non-template table, build hash and key part_desc later", K(part_info)); - } else if (OB_FAIL(build_part_desc(part_info, PARTITION_LEVEL_TWO, sub_part_opt))) { - LOG_WARN("fail to build sub part", K(sub_part_opt), K(ret)); - } else { - // do nothing - } - - return ret; -} - -int ObRouteUtils::build_part_desc(ObProxyPartInfo &part_info, - const ObPartitionLevel part_level, - ObProxyPartOption &part_opt) { - int ret = OB_SUCCESS; - ObProxyPartMgr &part_mgr = part_info.get_part_mgr(); - - if (part_level != PARTITION_LEVEL_TWO) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid argument", K(part_level), K(ret)); - } else { - if (part_opt.is_hash_part()) { - if (OB_FAIL(part_mgr.build_hash_part(part_info.is_oracle_mode(), - part_level, - part_opt.part_func_type_, - part_opt.part_num_, - part_opt.part_space_, - part_info.is_template_table(), - part_info.get_part_key_info()))) { - LOG_WARN("fail to build hash part", K(part_opt), K(ret)); - } - } else if (part_opt.is_key_part()) { - if (OB_FAIL(part_mgr.build_key_part(part_level, - part_opt.part_func_type_, - part_opt.part_num_, - part_opt.part_space_, - part_info.is_template_table(), - part_info.get_part_key_info()))) { - LOG_WARN("fail to build key part", K(part_opt), K(ret)); - } +void ObRouteUtils::set_part_key_accuracy(ObProxyPartKey *part_key, ObObjType part_key_type, + const int32_t length, const int16_t precision, const int16_t scale) +{ + part_key->accuracy_.length_ = -1; // init -1 means not used + part_key->accuracy_.precision_ = -1; + part_key->accuracy_.scale_ = -1; + + // use accord to obj_type + if (ob_is_otimestamp_type(part_key_type)) { + if (scale < MIN_SCALE_FOR_TEMPORAL || scale > MAX_SCALE_FOR_ORACLE_TEMPORAL) { + part_key->accuracy_.scale_ = DEFAULT_SCALE_FOR_ORACLE_TIMESTAMP; + LOG_WARN("invalid scale for timestamp in oracle, set to default:6", K(scale)); } else { - // we will build range part desc when fetch the range column + part_key->accuracy_.scale_ = static_cast(scale); // timestamp only need scale + LOG_DEBUG("succ to set timestamp scale of accuracy", K(scale)); } + } else if (ob_is_number_tc(part_key_type) + || ob_is_datetime_tc(part_key_type) + || ob_is_time_tc(part_key_type)) { + part_key->accuracy_.precision_ = precision; + part_key->accuracy_.scale_ = scale; + part_key->accuracy_.valid_ = 1; + } else if (ob_is_string_tc(part_key_type)) { + part_key->accuracy_.length_ = length; + part_key->accuracy_.precision_ = precision; + part_key->accuracy_.valid_ = 1; } - return ret; + // more obj type could be supported here. } /* @@ -616,32 +759,7 @@ void ObRouteUtils::parse_part_key_accuracy(ObProxyPartKey *part_key, int32_t length = static_cast(nums[0]); int16_t precision = static_cast(nums[1]); int16_t scale = static_cast(nums[2]); - - part_key->accuracy_.length_ = -1; // init -1 means not used - part_key->accuracy_.precision_ = -1; - part_key->accuracy_.scale_ = -1; - - // use accord to obj_type - if (ob_is_otimestamp_type(part_key_type)) { - if (scale < MIN_SCALE_FOR_TEMPORAL || scale > MAX_SCALE_FOR_ORACLE_TEMPORAL) { - part_key->accuracy_.scale_ = DEFAULT_SCALE_FOR_ORACLE_TIMESTAMP; - LOG_WARN("invalid scale for timestamp in oracle, set to default:6", K(scale)); - } else { - part_key->accuracy_.scale_ = static_cast(scale); // timestamp only need scale - LOG_DEBUG("succ to set timestamp scale of accuracy", K(scale)); - } - } else if (ob_is_number_tc(part_key_type) - || ob_is_datetime_tc(part_key_type) - || ob_is_time_tc(part_key_type)) { - part_key->accuracy_.precision_ = precision; - part_key->accuracy_.scale_ = scale; - part_key->accuracy_.valid_ = 1; - } else if (ob_is_string_tc(part_key_type)) { - part_key->accuracy_.length_ = length; - part_key->accuracy_.precision_ = precision; - part_key->accuracy_.valid_ = 1; - } - // more obj type could be supported here. + set_part_key_accuracy(part_key, part_key_type, length, precision, scale); } } @@ -655,104 +773,158 @@ void ObRouteUtils::parse_part_key_accuracy(ObProxyPartKey *part_key, } inline int ObRouteUtils::fetch_part_key(ObResultSetFetcher &rs_fetcher, - ObProxyPartInfo &part_info) + ObProxyPartInfo &part_info, + const int64_t cluster_version) { int ret = OB_SUCCESS; - ObProxyPartKeyInfo &part_key_info = part_info.get_part_key_info(); - ObIAllocator &allocator = part_info.get_allocator(); - ObPartitionLevel part_key_level = PARTITION_LEVEL_ONE; - int64_t part_key_idx = -1; - ObObjType part_key_type = ObMaxType; - ObCollationType part_key_cs_type = CS_TYPE_INVALID; - ObString part_key_name; - ObString part_key_extra; - ObString constraint_part_key; - int64_t idx_in_rowid = -1; - ObString part_key_accuracy; - - PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_key_level", part_key_level, ObPartitionLevel); - // part key idx is the order of part key in all columns - PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_key_idx", part_key_idx, int64_t); - PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_key_type", part_key_type, ObObjType); - PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "part_key_name", part_key_name); - // use part_key_extra as generated key expr - PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "part_key_extra", part_key_extra); - PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "spare4", constraint_part_key); - // use spare1 as table collation type - PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "spare1", part_key_cs_type, ObCollationType); - // use spare2 as rowid index - PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "spare2", idx_in_rowid, int64_t); - // use spare5 as the accuracy of the part key - PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "spare5", part_key_accuracy); - - LOG_DEBUG("fetch part key", K(part_key_level), K(part_key_idx), K(part_key_type), K(part_key_name), - K(part_key_extra), K(constraint_part_key), K(part_key_cs_type), K(idx_in_rowid), K(part_key_accuracy)); - - if (!is_obj_type_supported(part_key_type)) { - part_info.set_unknown_part_key(true); - } - - ObProxyPartKey *part_key = &part_key_info.part_keys_[part_key_info.key_num_]; - - if (PARTITION_LEVEL_ONE == part_key_level) { - part_key->level_ = PART_KEY_LEVEL_ONE; - } else if (PARTITION_LEVEL_TWO == part_key_level) { - part_key->level_ = PART_KEY_LEVEL_TWO; + // only process OBPROXY_MAX_PART_KEY_NUM part key + if (OBPROXY_MAX_PART_KEY_NUM <= part_info.get_part_key_info().key_num_) { + LOG_WARN("proxy does not support to fetch more part key", K(OBPROXY_MAX_PART_KEY_NUM)); } else { - ret = OB_INVALID_ARGUMENT_FOR_EXTRACT; - LOG_WARN("part key level is invalid", K(part_key_level), K(ret)); - } + ObProxyPartKeyInfo &part_key_info = part_info.get_part_key_info(); + ObIAllocator &allocator = part_info.get_allocator(); + ObPartitionLevel part_key_level = PARTITION_LEVEL_ONE; + int64_t part_key_idx = -1; + ObObjType part_key_type = ObMaxType; + ObCollationType part_key_cs_type = CS_TYPE_INVALID; + ObString part_key_name; + ObString part_key_extra; + + // here store serialized default value + // mysql mode return serialized ObObj with relevant column's type + // oracle mode return serialized ObObj with varchar type + char *part_key_default_value = NULL; + int default_val_len = 0; + + ObString constraint_part_key; + int64_t idx_in_rowid = -1; + ObString part_key_accuracy; + int64_t part_key_length = -1; + int64_t part_key_precision = -1; + int64_t part_key_scale = -1; + + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_key_level", part_key_level, ObPartitionLevel); + // part key idx is the order of part key in all columns + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_key_idx", part_key_idx, int64_t); + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_key_type", part_key_type, ObObjType); + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "part_key_name", part_key_name); + // use part_key_extra as generated key expr + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "part_key_extra", part_key_extra); + if (IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "spare4", constraint_part_key); + // use spare1 as table collation type + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "spare1", part_key_cs_type, ObCollationType); + // use spare2 as rowid index + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "spare2", idx_in_rowid, int64_t); + // use spare5 as the accuracy of the part key + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "spare5", part_key_accuracy); + } else { + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "part_key_expr", constraint_part_key); + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_key_collation_type", part_key_cs_type, ObCollationType); + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_key_rowkey_idx", idx_in_rowid, int64_t); + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_key_length", part_key_length, int64_t); + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_key_precision", part_key_precision, int64_t); + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_key_scale", part_key_scale, int64_t); + } - char *buf = NULL; - if (OB_ISNULL(buf = static_cast(allocator.alloc(part_key_name.length())))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to allc part key name", K(buf), K(part_key_name.length()), K(ret)); - } else { - memcpy(buf, part_key_name.ptr(), part_key_name.length()); - } + if (OB_SUCC(ret)){ + PROXY_EXTRACT_STRBUF_FIELD_MYSQL_UNLIMIT_LENGTH(rs_fetcher, "part_key_default_value", part_key_default_value, default_val_len, allocator); + if (OB_ERR_COLUMN_NOT_FOUND == ret) { + LOG_DEBUG("part key default value not exist, continue", K(ret)); + ret = OB_SUCCESS; + } + } - if (OB_SUCC(ret)) { - part_key->idx_ = part_key_idx; - part_key->name_.str_len_ = part_key_name.length(); - part_key->name_.str_ = buf; - part_key->obj_type_ = part_key_type; - part_key->idx_in_rowid_ = idx_in_rowid; - part_key->accuracy_.valid_ = 0; // not valid accuracy - - parse_part_key_accuracy(part_key, part_key_type, &allocator, part_key_accuracy); - - if (CS_TYPE_INVALID == part_key_cs_type) { - part_key->cs_type_ = ObCharset::get_default_collation(ObCharset::get_default_charset()); + LOG_DEBUG("fetch part key", K(part_key_level), K(part_key_idx), K(part_key_type), K(part_key_name), + K(part_key_extra), K(constraint_part_key), K(part_key_cs_type), + K(idx_in_rowid), K(part_key_accuracy), K(part_key_default_value), + K(part_key_length), K(part_key_precision), K(part_key_scale)); + + if (!is_obj_type_supported(part_key_type)) { + part_info.set_unknown_part_key(true); + } + + ObProxyPartKey *part_key = &part_key_info.part_keys_[part_key_info.key_num_]; + + if (PARTITION_LEVEL_ONE == part_key_level) { + part_key->level_ = PART_KEY_LEVEL_ONE; + } else if (PARTITION_LEVEL_TWO == part_key_level) { + part_key->level_ = PART_KEY_LEVEL_TWO; } else { - part_key->cs_type_ = part_key_cs_type; + ret = OB_INVALID_ARGUMENT_FOR_EXTRACT; + LOG_WARN("part key level is invalid", K(part_key_level), K(ret)); } - if (!part_key_extra.empty() || !constraint_part_key.empty()) { - part_key->is_generated_ = true; - part_info.set_has_generated_key(true); - int64_t generated_key_idx = part_key_info.key_num_; - ++part_key_info.key_num_; - if (OB_FAIL(add_generated_part_key(part_key_extra, generated_key_idx, part_info))) { - LOG_WARN("fail to add generated key", K(part_key_extra), K(ret)); - } - const char *sep_pos = NULL; - ObString tmp_str; - while (NULL != (sep_pos = (constraint_part_key.find(PART_KEY_EXTRA_SEPARATOR)))) { - tmp_str = constraint_part_key.split_on(sep_pos); - if (OB_FAIL(add_generated_part_key(tmp_str, generated_key_idx, part_info))) { - LOG_WARN("fail to add generated key", K(tmp_str), K(ret)); + char *buf = NULL; + if (OB_ISNULL(buf = static_cast(allocator.alloc(part_key_name.length())))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to allc part key name", K(buf), K(part_key_name.length()), K(ret)); + } else { + memcpy(buf, part_key_name.ptr(), part_key_name.length()); + } + + if (OB_SUCC(ret)) { + part_key->idx_ = part_key_idx; + part_key->name_.str_len_ = part_key_name.length(); + part_key->name_.str_ = buf; + part_key->obj_type_ = part_key_type; + part_key->idx_in_rowid_ = idx_in_rowid; + part_key->accuracy_.valid_ = 0; // not valid accuracy + ObIArray &columns = (part_key->level_ == PART_KEY_LEVEL_ONE ? + part_info.get_part_columns() : part_info.get_sub_part_columns()); + for (int i = 0; i < columns.count(); i++) { + ObString col(part_key->name_.str_len_, part_key->name_.str_); + if (columns.at(i).case_compare(col) == 0) { + part_key->idx_in_part_columns_ = i; + break; } } - if (OB_FAIL(add_generated_part_key(constraint_part_key, generated_key_idx, part_info))) { - LOG_WARN("fail to add generated key", K(constraint_part_key), K(ret)); + part_key->default_value_.str_len_ = default_val_len; + part_key->default_value_.str_ = part_key_default_value; + part_key->generated_col_idx_ = -1; + part_key->real_source_idx_ = -1; + + if (IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + parse_part_key_accuracy(part_key, part_key_type, &allocator, part_key_accuracy); + } else { + set_part_key_accuracy(part_key, part_key_type, + static_cast(part_key_length), + static_cast(part_key_precision), + static_cast(part_key_scale)); + } + + if (CS_TYPE_INVALID == part_key_cs_type) { + part_key->cs_type_ = ObCharset::get_default_collation(ObCharset::get_default_charset()); + } else { + part_key->cs_type_ = part_key_cs_type; + } + + if (!part_key_extra.empty() || !constraint_part_key.empty()) { + part_key->is_generated_ = true; + part_info.set_has_generated_key(true); + int64_t generated_key_idx = part_key_info.key_num_; + ++part_key_info.key_num_; + if (OB_FAIL(add_generated_part_key(part_key_extra, generated_key_idx, part_info))) { + LOG_WARN("fail to add generated key", K(part_key_extra), K(ret)); + } + const char *sep_pos = NULL; + ObString tmp_str; + while (NULL != (sep_pos = (constraint_part_key.find(PART_KEY_EXTRA_SEPARATOR)))) { + tmp_str = constraint_part_key.split_on(sep_pos); + if (OB_FAIL(add_generated_part_key(tmp_str, generated_key_idx, part_info))) { + LOG_WARN("fail to add generated key", K(tmp_str), K(ret)); + } + } + if (OB_FAIL(add_generated_part_key(constraint_part_key, generated_key_idx, part_info))) { + LOG_WARN("fail to add generated key", K(constraint_part_key), K(ret)); + } + } else { + part_key->is_generated_ = false; + ++part_key_info.key_num_; } - } else { - part_key->is_generated_ = false; - ++part_key_info.key_num_; } } - return ret; } @@ -787,7 +959,6 @@ int ObRouteUtils::add_generated_part_key(const ObString &part_key_extra, LOG_WARN("generated function param num is unexpectedlly larger than 3", "child num", child->child_num_, K(OBPROXY_MAX_PARAM_NUM), K(ret)); } else { - LOG_DEBUG("succ to parse generated function expr", "func_expr_result:", ObFuncExprParseResultPrintWrapper(result)); part_key_info.part_keys_[part_key_info.key_num_].func_type_ = func_expr_node->func_type_; part_key_info.part_keys_[part_key_info.key_num_].param_num_ = child->child_num_; part_key_info.part_keys_[part_key_info.key_num_].generated_col_idx_ = generated_key_idx; @@ -805,6 +976,7 @@ int ObRouteUtils::add_generated_part_key(const ObString &part_key_extra, part_key_info.part_keys_[part_key_info.key_num_].level_ = part_key.level_; part_key_info.part_keys_[part_key_info.key_num_].obj_type_ = part_key.obj_type_; part_key_info.part_keys_[part_key_info.key_num_].cs_type_ = part_key.cs_type_; + part_key_info.part_keys_[part_key_info.key_num_].idx_in_part_columns_ = part_key.idx_in_part_columns_; part_key_info.part_keys_[part_key_info.key_num_].is_generated_ = false; } child_param_node = child_param_node->next_; @@ -823,6 +995,12 @@ inline int ObRouteUtils::fetch_part_option(ObResultSetFetcher &rs_fetcher, ObProxyPartOption &first_part_opt = part_info.get_first_part_option(); ObProxyPartOption &sub_part_opt = part_info.get_sub_part_option(); + //get all sub part num + int64_t all_sub_part_num=0; + //"all_part_num" in __all_virtual_proxy_partition_info + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "all_part_num", all_sub_part_num, int64_t); + part_info.get_part_mgr().set_all_sub_part_num(all_sub_part_num); + // get first part PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_num", first_part_opt.part_num_, int64_t); PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_type", first_part_opt.part_func_type_, @@ -838,46 +1016,55 @@ inline int ObRouteUtils::fetch_part_option(ObResultSetFetcher &rs_fetcher, return ret; } -int ObRouteUtils::fetch_first_part(ObResultSetFetcher &rs_fetcher, ObProxyPartInfo &part_info) +int ObRouteUtils::fetch_first_part(ObResultSetFetcher &rs_fetcher, ObProxyPartInfo &part_info, const int64_t cluster_version) { int ret = OB_SUCCESS; - if (part_info.get_first_part_option().is_range_part()) { + part_info.get_part_mgr().set_cluster_version(cluster_version); + if (part_info.get_first_part_option().is_range_part(cluster_version)) { if (OB_FAIL(part_info.get_part_mgr().build_range_part(share::schema::PARTITION_LEVEL_ONE, part_info.get_first_part_option().part_func_type_, part_info.get_first_part_option().part_num_, + part_info.get_part_columns().count(), part_info.is_template_table(), part_info.get_part_key_info(), - rs_fetcher))) { + rs_fetcher, + cluster_version))) { LOG_WARN("fail to build range part", K(ret)); } - } else if (part_info.get_first_part_option().is_list_part()) { + } else if (part_info.get_first_part_option().is_list_part(cluster_version)) { if (OB_FAIL(part_info.get_part_mgr().build_list_part(share::schema::PARTITION_LEVEL_ONE, part_info.get_first_part_option().part_func_type_, part_info.get_first_part_option().part_num_, + part_info.get_part_columns().count(), part_info.is_template_table(), part_info.get_part_key_info(), - rs_fetcher))) { + rs_fetcher, + cluster_version))) { LOG_WARN("fail to build list part", K(ret)); } - } else if (part_info.get_first_part_option().is_hash_part()) { + } else if (part_info.get_first_part_option().is_hash_part(cluster_version)) { if (OB_FAIL(part_info.get_part_mgr().build_hash_part(part_info.is_oracle_mode(), share::schema::PARTITION_LEVEL_ONE, part_info.get_first_part_option().part_func_type_, part_info.get_first_part_option().part_num_, part_info.get_first_part_option().part_space_, + part_info.get_part_columns().count(), part_info.is_template_table(), part_info.get_part_key_info(), - &rs_fetcher))) { + &rs_fetcher, + cluster_version))) { LOG_WARN("fail to build hash part", K(ret)); } - } else if (part_info.get_first_part_option().is_key_part()) { + } else if (part_info.get_first_part_option().is_key_part(cluster_version)) { if (OB_FAIL(part_info.get_part_mgr().build_key_part(share::schema::PARTITION_LEVEL_ONE, part_info.get_first_part_option().part_func_type_, part_info.get_first_part_option().part_num_, part_info.get_first_part_option().part_space_, + part_info.get_part_columns().count(), part_info.is_template_table(), part_info.get_part_key_info(), - &rs_fetcher))) { + &rs_fetcher, + cluster_version))) { LOG_WARN("fail to build key part", K(ret)); } } else { @@ -888,80 +1075,96 @@ int ObRouteUtils::fetch_first_part(ObResultSetFetcher &rs_fetcher, ObProxyPartIn return ret; } -int ObRouteUtils::fetch_sub_part(ObResultSetFetcher &rs_fetcher, ObProxyPartInfo &part_info) +int ObRouteUtils::fetch_sub_part(ObResultSetFetcher &rs_fetcher, ObProxyPartInfo &part_info, const int64_t cluster_version) { int ret = OB_SUCCESS; - if (part_info.get_sub_part_option().is_range_part()) { + if (part_info.get_sub_part_option().is_range_part(cluster_version)) { if (part_info.is_template_table()) { if (OB_FAIL(part_info.get_part_mgr().build_range_part(share::schema::PARTITION_LEVEL_TWO, part_info.get_sub_part_option().part_func_type_, part_info.get_sub_part_option().part_num_, + part_info.get_sub_part_columns().count(), part_info.is_template_table(), part_info.get_part_key_info(), - rs_fetcher))) { + rs_fetcher, + cluster_version))) { LOG_WARN("fail to build range part", K(ret)); } } else { if (OB_FAIL(part_info.get_part_mgr().build_sub_range_part_with_non_template(part_info.get_sub_part_option().part_func_type_, + part_info.get_sub_part_columns().count(), part_info.get_part_key_info(), - rs_fetcher))) { + rs_fetcher, + cluster_version))) { LOG_WARN("fail to build range part", K(ret)); } } - } else if (part_info.get_sub_part_option().is_list_part()) { + } else if (part_info.get_sub_part_option().is_list_part(cluster_version)) { if (part_info.is_template_table()) { if (OB_FAIL(part_info.get_part_mgr().build_list_part(share::schema::PARTITION_LEVEL_TWO, part_info.get_sub_part_option().part_func_type_, part_info.get_sub_part_option().part_num_, + part_info.get_sub_part_columns().count(), part_info.is_template_table(), part_info.get_part_key_info(), - rs_fetcher))) { + rs_fetcher, + cluster_version))) { LOG_WARN("fail to build list part", K(ret)); } } else { if (OB_FAIL(part_info.get_part_mgr().build_sub_list_part_with_non_template(part_info.get_sub_part_option().part_func_type_, + part_info.get_sub_part_columns().count(), part_info.get_part_key_info(), - rs_fetcher))) { + rs_fetcher, + cluster_version))) { LOG_WARN("fail to build range part", K(ret)); } } - } else if (part_info.get_sub_part_option().is_hash_part()) { + } else if (part_info.get_sub_part_option().is_hash_part(cluster_version)) { if (part_info.is_template_table()) { if (OB_FAIL(part_info.get_part_mgr().build_hash_part(part_info.is_oracle_mode(), share::schema::PARTITION_LEVEL_TWO, part_info.get_sub_part_option().part_func_type_, part_info.get_sub_part_option().part_num_, part_info.get_sub_part_option().part_space_, + part_info.get_sub_part_columns().count(), part_info.is_template_table(), part_info.get_part_key_info(), - &rs_fetcher))) { + &rs_fetcher, + cluster_version))) { LOG_WARN("fail to build hash part", K(ret)); } } else { if (OB_FAIL(part_info.get_part_mgr().build_sub_hash_part_with_non_template(part_info.is_oracle_mode(), part_info.get_sub_part_option().part_func_type_, part_info.get_sub_part_option().part_space_, + part_info.get_sub_part_columns().count(), part_info.get_part_key_info(), - rs_fetcher))) { + rs_fetcher, + cluster_version))) { LOG_WARN("fail to build range part", K(ret)); } } - } else if (part_info.get_sub_part_option().is_key_part()) { + } else if (part_info.get_sub_part_option().is_key_part(cluster_version)) { if (part_info.is_template_table()) { if (OB_FAIL(part_info.get_part_mgr().build_key_part(share::schema::PARTITION_LEVEL_TWO, part_info.get_sub_part_option().part_func_type_, part_info.get_sub_part_option().part_num_, part_info.get_sub_part_option().part_space_, + part_info.get_sub_part_columns().count(), part_info.is_template_table(), part_info.get_part_key_info(), - &rs_fetcher))) { + &rs_fetcher, + cluster_version))) { LOG_WARN("fail to build key part", K(ret)); } } else { if (OB_FAIL(part_info.get_part_mgr().build_sub_key_part_with_non_template(part_info.get_sub_part_option().part_func_type_, part_info.get_sub_part_option().part_space_, + part_info.get_sub_part_columns().count(), part_info.get_part_key_info(), - rs_fetcher))) { + rs_fetcher, + cluster_version))) { LOG_WARN("fail to build range part", K(ret)); } } @@ -1130,6 +1333,7 @@ int ObRouteUtils::convert_route_param_to_table_param( table_param.mysql_proxy_ = route_param.mysql_proxy_; table_param.cr_version_ = route_param.cr_version_; table_param.cr_id_ = route_param.cr_id_; + table_param.cluster_version_ = route_param.cluster_version_; table_param.tenant_version_ = route_param.tenant_version_; table_param.is_partition_table_route_supported_ = route_param.is_partition_table_route_supported_; table_param.is_oracle_mode_ = route_param.is_oracle_mode_; @@ -1154,6 +1358,7 @@ int ObRouteUtils::convert_route_param_to_routine_param( routine_param.mysql_proxy_ = route_param.mysql_proxy_; routine_param.cr_version_ = route_param.cr_version_; routine_param.cr_id_ = route_param.cr_id_; + routine_param.cluster_version_ = route_param.cluster_version_; } return ret; } @@ -1161,7 +1366,8 @@ int ObRouteUtils::convert_route_param_to_routine_param( int ObRouteUtils::get_partition_entry_sql(char *sql_buf, const int64_t buf_len, const ObTableEntryName &name, const uint64_t partition_id, - bool is_need_force_flush) + bool is_need_force_flush, + const int64_t cluster_version) { int ret = OB_SUCCESS; if (OB_ISNULL(sql_buf) || OB_UNLIKELY(buf_len <= 0) @@ -1180,6 +1386,7 @@ int ObRouteUtils::get_partition_entry_sql(char *sql_buf, const int64_t buf_len, new_tenant_name.length(), new_tenant_name.ptr(), name.database_name_.length(), name.database_name_.ptr(), name.table_name_.length(), name.table_name_.ptr(), + cluster_version < 4 ? "partition_id" : "tablet_id", partition_id, INT64_MAX)); if (OB_UNLIKELY(len <= 0) || OB_UNLIKELY(len >= buf_len)) { @@ -1194,11 +1401,12 @@ int ObRouteUtils::get_partition_entry_sql(char *sql_buf, const int64_t buf_len, int ObRouteUtils::fetch_one_partition_entry_info( ObResultSetFetcher &rs_fetcher, ObTableEntry &table_entry, - ObPartitionEntry *&entry) + ObPartitionEntry *&entry, + const int64_t cluster_version) { int ret = OB_SUCCESS; int64_t tmp_real_str_len = 0; - char ip_str[OB_IP_STR_BUFF]; + char ip_str[MAX_IP_ADDR_LENGTH]; ip_str[0] = '\0'; int64_t port = 0; uint64_t table_id = OB_INVALID_ID; @@ -1218,12 +1426,16 @@ int ObRouteUtils::fetch_one_partition_entry_info( ip_str[0] = '\0'; port = 0; - PROXY_EXTRACT_STRBUF_FIELD_MYSQL(rs_fetcher, "svr_ip", ip_str, OB_IP_STR_BUFF, tmp_real_str_len); + PROXY_EXTRACT_STRBUF_FIELD_MYSQL(rs_fetcher, "svr_ip", ip_str, MAX_IP_ADDR_LENGTH, tmp_real_str_len); PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "sql_port", port, int64_t); PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "table_id", table_id, uint64_t); - PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "partition_id", partition_id, uint64_t); PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "role", role, int64_t); PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_num", part_num, int64_t); + if (IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "partition_id", partition_id, uint64_t); + } else { + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "tablet_id", partition_id, uint64_t); + } if (OB_SUCC(ret)) { PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "schema_version", schema_version, int64_t); @@ -1235,20 +1447,28 @@ int ObRouteUtils::fetch_one_partition_entry_info( } if (OB_SUCC(ret)) { - PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "spare1", replica_type, int32_t); - if (OB_ERR_COLUMN_NOT_FOUND == ret) { - LOG_DEBUG("can not find spare1, maybe is old server, ignore", K(replica_type), K(ret)); - ret = OB_SUCCESS; - replica_type = 0; + if (IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "spare1", replica_type, int32_t); + if (OB_ERR_COLUMN_NOT_FOUND == ret) { + LOG_DEBUG("can not find spare1, maybe is old server, ignore", K(replica_type), K(ret)); + ret = OB_SUCCESS; + replica_type = 0; + } + } else { + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "replica_type", replica_type, int32_t); } } if (OB_SUCC(ret)) { - PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "spare2", dup_replica_type, int32_t); - if (OB_ERR_COLUMN_NOT_FOUND == ret) { - LOG_DEBUG("can not find spare2, maybe is old server, ignore", K(dup_replica_type), K(ret)); - ret = OB_SUCCESS; - dup_replica_type = 0; + if (IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "spare2", dup_replica_type, int32_t); + if (OB_ERR_COLUMN_NOT_FOUND == ret) { + LOG_DEBUG("can not find spare2, maybe is old server, ignore", K(dup_replica_type), K(ret)); + ret = OB_SUCCESS; + dup_replica_type = 0; + } + } else { + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "dup_replica_type", dup_replica_type, int32_t); } } @@ -1319,7 +1539,8 @@ int ObRouteUtils::fetch_one_partition_entry_info( } int ObRouteUtils::get_routine_entry_sql(char *sql_buf, const int64_t buf_len, - const ObTableEntryName &name) + const ObTableEntryName &name, + const int64_t cluster_version) { int ret = OB_SUCCESS; if (OB_ISNULL(sql_buf) @@ -1334,19 +1555,28 @@ int ObRouteUtils::get_routine_entry_sql(char *sql_buf, const int64_t buf_len, ObString new_tenant_name; get_tenant_name(name.tenant_name_, new_tenant_name_buf, new_tenant_name); // call A.B or call A.B.C - if (OB_UNLIKELY(!name.package_name_.empty())) { - len = static_cast(snprintf(sql_buf, OB_SHORT_SQL_LENGTH, PROXY_ROUTINE_SCHEMA_SQL_WITH_PACKAGE, - OB_ALL_VIRTUAL_PROXY_SCHEMA_TNAME, - new_tenant_name.length(), new_tenant_name.ptr(), - name.database_name_.length(), name.database_name_.ptr(), - name.package_name_.length(), name.package_name_.ptr(), - name.package_name_.length(), name.package_name_.ptr(), - name.table_name_.length(), name.table_name_.ptr())); + if (IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + if (OB_UNLIKELY(!name.package_name_.empty())) { + len = static_cast(snprintf(sql_buf, OB_SHORT_SQL_LENGTH, PROXY_ROUTINE_SCHEMA_SQL_WITH_PACKAGE, + OB_ALL_VIRTUAL_PROXY_SCHEMA_TNAME, + new_tenant_name.length(), new_tenant_name.ptr(), + name.database_name_.length(), name.database_name_.ptr(), + name.package_name_.length(), name.package_name_.ptr(), + name.package_name_.length(), name.package_name_.ptr(), + name.table_name_.length(), name.table_name_.ptr())); + } else { + len = static_cast(snprintf(sql_buf, OB_SHORT_SQL_LENGTH, PROXY_ROUTINE_SCHEMA_SQL, + OB_ALL_VIRTUAL_PROXY_SCHEMA_TNAME, + new_tenant_name.length(), new_tenant_name.ptr(), + name.database_name_.length(), name.database_name_.ptr(), + name.table_name_.length(), name.table_name_.ptr())); + } } else { - len = static_cast(snprintf(sql_buf, OB_SHORT_SQL_LENGTH, PROXY_ROUTINE_SCHEMA_SQL, - OB_ALL_VIRTUAL_PROXY_SCHEMA_TNAME, + len = static_cast(snprintf(sql_buf, OB_SHORT_SQL_LENGTH, PROXY_ROUTINE_SCHEMA_SQL_V4, + OB_ALL_VIRTUAL_PROXY_ROUTINE_TNAME, new_tenant_name.length(), new_tenant_name.ptr(), name.database_name_.length(), name.database_name_.ptr(), + name.package_name_.length(), name.package_name_.ptr(), name.table_name_.length(), name.table_name_.ptr())); } @@ -1364,7 +1594,8 @@ int ObRouteUtils::fetch_one_routine_entry_info( const ObTableEntryName &name, const int64_t cr_version, const int64_t cr_id, - ObRoutineEntry *&entry) + ObRoutineEntry *&entry, + const int64_t cluster_version) { int ret = OB_SUCCESS; int64_t routine_type = 0; @@ -1376,10 +1607,16 @@ int ObRouteUtils::fetch_one_routine_entry_info( if (OB_SUCC(rs_fetcher.next())) { PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "database_name", database_name); - PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "table_type", routine_type, int64_t); - PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "table_id", routine_id, uint64_t); PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "schema_version", schema_version, int64_t); - PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "spare4", route_sql);//used for route_sql + if (IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "table_type", routine_type, int64_t); + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "table_id", routine_id, uint64_t); + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "spare4", route_sql);//used for route_sql + } else { + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "routine_type", routine_type, int64_t); + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "routine_id", routine_id, uint64_t); + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "routine_sql", route_sql);//used for route_sql + } } if (OB_ITER_END == ret) { @@ -1402,6 +1639,73 @@ int ObRouteUtils::fetch_one_routine_entry_info( return ret; } +int ObRouteUtils::fetch_binlog_entry(ObResultSetFetcher &rs_fetcher, + ObTableEntry &entry) +{ + int ret = OB_SUCCESS; + int64_t tmp_real_str_len = 0; + char ip[OB_IP_PORT_STR_BUFF]; + char status[32]; + int64_t port = 0; + ObProxyReplicaLocation prl; + ObProxyPartitionLocation *ppl = NULL; + ObSEArray server_list; + + while (OB_SUCC(ret) && OB_SUCC(rs_fetcher.next())) { + ip[0] = '\0'; + status[0] = '\0'; + prl.reset(); + bool binlog_service_ok = false; + + PROXY_EXTRACT_STRBUF_FIELD_MYSQL(rs_fetcher, "ip", ip, OB_IP_PORT_STR_BUFF, tmp_real_str_len); + PROXY_EXTRACT_STRBUF_FIELD_MYSQL(rs_fetcher, "status", status, sizeof(status), tmp_real_str_len); + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "port", port, int64_t); + + if (0 == strcasecmp("OK", status)) { + binlog_service_ok = true; + } + + if (OB_SUCC(ret) && binlog_service_ok) { + if (OB_FAIL(prl.add_addr(ip, port))) { + LOG_WARN("invalid ip or port in fetching binlog entry", K(ret)); + } else if (server_list.push_back(prl)) { + LOG_WARN("fail to add server", K(prl), K(ret)); + } + } + } + + if (OB_ITER_END == ret) { + ret = OB_SUCCESS; + } + + if (OB_SUCC(ret) && !server_list.empty()) { + if (OB_ISNULL(ppl = op_alloc(ObProxyPartitionLocation))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to allocate memory for ObProxyPartitionLocation", K(ret)); + } else if (OB_FAIL(ppl->set_replicas(server_list))) { + LOG_WARN("fail to set replicas", K(server_list), K(ret)); + } else if (!server_list.empty() && OB_UNLIKELY(!ppl->is_valid())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("ppl should not unavailabe", KPC(ppl), K(ret)); + } else { + if (ppl->is_valid()) { + if (OB_FAIL(entry.set_first_partition_location(ppl))) { + LOG_WARN("fail to set first partition location", K(ret)); + } else { + ppl = NULL; + } + } + } + } + + if (NULL != ppl) { + op_free(ppl); + ppl = NULL; + } + + return ret; +} + } // end of namespace proxy } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/proxy/route/ob_route_utils.h b/src/obproxy/proxy/route/ob_route_utils.h index 3aef1be171be674c224a10d7a8b0646324cde11d..c908b22d51b2bacbda9bda43f814319654476656 100644 --- a/src/obproxy/proxy/route/ob_route_utils.h +++ b/src/obproxy/proxy/route/ob_route_utils.h @@ -42,16 +42,30 @@ class ObRouteUtils { public: static int get_table_entry_sql(char *sql_buf, const int64_t buf_len, ObTableEntryName &name, - bool is_need_force_flush = false); - static int get_part_info_sql(char *sql_buf, const int64_t buf_len, const uint64_t table_id); - static int get_first_part_sql(char *sql_buf, const int64_t buf_len, const uint64_t table_id, const bool is_hash_part); + bool is_need_force_flush, const int64_t cluster_version); + static int get_part_info_sql(char *sql_buf, const int64_t buf_len, const uint64_t table_id, + ObTableEntryName &name, const int64_t cluster_version); + static int get_first_part_sql(char *sql_buf, const int64_t buf_len, const uint64_t table_id, + const bool is_hash_part, ObTableEntryName &name, const int64_t cluster_version); static int get_sub_part_sql(char *sql_buf, const int64_t buf_len, const uint64_t table_id, - const bool is_template_table); + const bool is_template_table, ObTableEntryName &name, const int64_t cluster_version); - static int fetch_table_entry(obproxy::ObResultSetFetcher &rs_fetcher, ObTableEntry &entry); - static int fetch_part_info(obproxy::ObResultSetFetcher &rs_fetcher, ObProxyPartInfo &part_info); - static int fetch_first_part(obproxy::ObResultSetFetcher &rs_fetcher, ObProxyPartInfo &part_info); - static int fetch_sub_part(obproxy::ObResultSetFetcher &rs_fetcher, ObProxyPartInfo &part_info); + static int fetch_table_entry(obproxy::ObResultSetFetcher &rs_fetcher, ObTableEntry &entry, + const int64_t cluster_version); + static int fetch_part_info(obproxy::ObResultSetFetcher &rs_fetcher, ObProxyPartInfo &part_info, + const int64_t cluster_version); + static int fetch_first_part(obproxy::ObResultSetFetcher &rs_fetcher, ObProxyPartInfo &part_info, + const int64_t cluster_version); + static int fetch_sub_part(obproxy::ObResultSetFetcher &rs_fetcher, ObProxyPartInfo &part_info, + const int64_t cluster_version); + + static int get_binlog_entry_sql(char *sql_buf, + const int64_t buf_len, + const ObString &cluster_name, + const ObString &tenant_name); + + static int fetch_binlog_entry(obproxy::ObResultSetFetcher &rs_fetcher, ObTableEntry &entry); + static int split_part_expr(common::ObString expr, common::ObIArray &arr); static int build_sys_dummy_entry(const common::ObString &cluster_name, const int64_t cluster_id, @@ -77,33 +91,35 @@ public: static int get_partition_entry_sql(char *sql_buf, const int64_t buf_len, const ObTableEntryName &name, uint64_t partition_id, - bool is_need_force_flush); + bool is_need_force_flush, + const int64_t cluster_version); static int fetch_one_partition_entry_info(obproxy::ObResultSetFetcher &rs_fetcher, ObTableEntry &table_entry, - ObPartitionEntry *&entry); + ObPartitionEntry *&entry, + const int64_t cluster_version); static int get_routine_entry_sql(char *sql_buf, const int64_t buf_len, - const ObTableEntryName &name); + const ObTableEntryName &name, + const int64_t cluster_version); static int fetch_one_routine_entry_info(obproxy::ObResultSetFetcher &rs_fetcher, const ObTableEntryName &name, const int64_t cr_version, const int64_t cr_id, - ObRoutineEntry *&entry); + ObRoutineEntry *&entry, + const int64_t cluster_version); private: - static int fetch_part_key(obproxy::ObResultSetFetcher &rs_fetcher, ObProxyPartInfo &part_info); + static int fetch_part_key(obproxy::ObResultSetFetcher &rs_fetcher, ObProxyPartInfo &part_info, + const int64_t cluster_version); + static void set_part_key_accuracy(ObProxyPartKey *part_key, common::ObObjType part_key_type, + const int32_t length, const int16_t precision, const int16_t scale); static void parse_part_key_accuracy(ObProxyPartKey *part_key, common::ObObjType part_key_type, common::ObIAllocator *allocator, ObString &part_key_accuracy); static int add_generated_part_key(const common::ObString &func_expr, const int64_t generated_key_idx, ObProxyPartInfo &part_info); static int fetch_part_option(obproxy::ObResultSetFetcher &rs_fetcher, ObProxyPartInfo &part_info); - static int build_part_desc(ObProxyPartInfo &part_info); - static int build_part_desc(ObProxyPartInfo &part_info, - const share::schema::ObPartitionLevel part_level, - ObProxyPartOption &part_opt); - }; bool is_fake_ip_port(const char *ip_str, const int64_t port); diff --git a/src/obproxy/proxy/route/ob_routine_cache.cpp b/src/obproxy/proxy/route/ob_routine_cache.cpp index 4fc2d821dcf3264900889fb81e8a63ef4e64e492..86c0e4a728fb9acba8f3933d3d7c6d26d69acb41 100644 --- a/src/obproxy/proxy/route/ob_routine_cache.cpp +++ b/src/obproxy/proxy/route/ob_routine_cache.cpp @@ -634,22 +634,33 @@ int init_routine_map_for_thread() { int ret = OB_SUCCESS; const int64_t event_thread_count = g_event_processor.thread_count_for_type_[ET_CALL]; + for (int64_t i = 0; (i < event_thread_count) && OB_SUCC(ret); ++i) { + if (OB_FAIL(init_routine_map_for_one_thread(i))) { + LOG_WARN("fail to init routine_map", K(i), K(ret)); + } + } + return ret; +} + +int init_routine_map_for_one_thread(int64_t index) +{ + int ret = OB_SUCCESS; ObEThread **ethreads = NULL; if (OB_ISNULL(ethreads = g_event_processor.event_thread_[ET_CALL])) { ret = OB_ERR_UNEXPECTED; PROXY_NET_LOG(ERROR, "fail to get ET_NET thread", K(ret)); + } else if (OB_ISNULL(ethreads[index])) { + ret = OB_ERR_UNEXPECTED; + PROXY_NET_LOG(ERROR, "fail to get ET_NET thread", K(ret)); } else { - for (int64_t i = 0; (i < event_thread_count) && OB_SUCC(ret); ++i) { - if (OB_ISNULL(ethreads[i]->routine_map_ = new (std::nothrow) ObRoutineRefHashMap(ObModIds::OB_PROXY_ROUTINE_ENTRY_MAP))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to new ObRoutineRefHashMap", K(i), K(ethreads[i]), K(ret)); - } else if (OB_FAIL(ethreads[i]->routine_map_->init())) { - LOG_WARN("fail to init routine_map", K(ret)); - } + if (OB_ISNULL(ethreads[index]->routine_map_ = new (std::nothrow) ObRoutineRefHashMap(ObModIds::OB_PROXY_ROUTINE_ENTRY_MAP))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to new ObRoutineRefHashMap", K(index), K(ethreads[index]), K(ret)); + } else if (OB_FAIL(ethreads[index]->routine_map_->init())) { + LOG_WARN("fail to init routine_map", K(ret)); } } return ret; - } int ObRoutineRefHashMap::clean_hash_map() diff --git a/src/obproxy/proxy/route/ob_routine_cache.h b/src/obproxy/proxy/route/ob_routine_cache.h index 1e15471a4be668c38ed4b55fbc85660f2158cd6a..59ec9b076d2dc68f045d19af06e8958dcb04a7b1 100644 --- a/src/obproxy/proxy/route/ob_routine_cache.h +++ b/src/obproxy/proxy/route/ob_routine_cache.h @@ -150,6 +150,7 @@ private: }; int init_routine_map_for_thread(); +int init_routine_map_for_one_thread(int64_t index); } // end of namespace proxy } // end of namespace obproxy diff --git a/src/obproxy/proxy/route/ob_routine_processor.cpp b/src/obproxy/proxy/route/ob_routine_processor.cpp index 6fd4deaad3328ba8666f43eaedf601cd04012ef2..601f56796f92460260194b3183e95ffaaf6e8f73 100644 --- a/src/obproxy/proxy/route/ob_routine_processor.cpp +++ b/src/obproxy/proxy/route/ob_routine_processor.cpp @@ -271,7 +271,7 @@ int ObRoutineEntryCont::handle_client_resp(void *data) ret = OB_ERR_UNEXPECTED; LOG_WARN("rs_fetcher and entry can not be NULL", K(rs_fetcher), K(entry), K(ret)); } else if (OB_FAIL(ObRouteUtils::fetch_one_routine_entry_info( - *rs_fetcher, param_.name_, param_.cr_version_, param_.cr_id_, entry))) { + *rs_fetcher, param_.name_, param_.cr_version_, param_.cr_id_, entry, param_.cluster_version_))) { LOG_WARN("fail to fetch one routine entry info", K(ret)); } else if (NULL == entry) { PROCESSOR_INCREMENT_DYN_STAT(GET_ROUTINE_ENTRY_FROM_REMOTE_FAIL); @@ -438,7 +438,7 @@ int ObRoutineEntryCont::lookup_entry_remote() ObMysqlProxy *mysql_proxy = param_.mysql_proxy_; char sql[OB_SHORT_SQL_LENGTH]; sql[0] = '\0'; - if (OB_FAIL(ObRouteUtils::get_routine_entry_sql(sql, OB_SHORT_SQL_LENGTH, param_.name_))) { + if (OB_FAIL(ObRouteUtils::get_routine_entry_sql(sql, OB_SHORT_SQL_LENGTH, param_.name_, param_.cluster_version_))) { LOG_WARN("fail to get table entry sql", K(sql), K(ret)); } else { const ObMysqlRequestParam request_param(sql, param_.current_idc_name_); @@ -540,6 +540,7 @@ inline int ObRoutineParam::deep_copy(ObRoutineParam &other) force_renew_ = other.force_renew_; cr_version_ = other.cr_version_; cr_id_ = other.cr_id_; + cluster_version_ = other.cluster_version_; // no need assign result_ mysql_proxy_ = other.mysql_proxy_; if (!other.current_idc_name_.empty()) { diff --git a/src/obproxy/proxy/route/ob_routine_processor.h b/src/obproxy/proxy/route/ob_routine_processor.h index 4a41b5733f260dac3f2c68eb7d4a002f98f1fbad..bf2b15e1b0386dd97cfe594f8863f7d083509525 100644 --- a/src/obproxy/proxy/route/ob_routine_processor.h +++ b/src/obproxy/proxy/route/ob_routine_processor.h @@ -64,6 +64,7 @@ public: ObRoutineResult result_; int64_t cr_version_; int64_t cr_id_; + int64_t cluster_version_; common::ObString current_idc_name_; char current_idc_name_buf_[OB_PROXY_MAX_IDC_NAME_LENGTH]; @@ -89,6 +90,7 @@ inline void ObRoutineParam::reset() force_renew_ = false; cr_version_ = 0; cr_id_ = common::OB_INVALID_CLUSTER_ID; + cluster_version_ = 0; current_idc_name_.reset(); if (NULL != name_buf_ && name_buf_len_ > 0) { diff --git a/src/obproxy/proxy/route/ob_server_route.h b/src/obproxy/proxy/route/ob_server_route.h index 413b504a170cd70f5f24868840e4038f7d9784cc..64b9afbed60361c38e8f944c04cd931374429611 100644 --- a/src/obproxy/proxy/route/ob_server_route.h +++ b/src/obproxy/proxy/route/ob_server_route.h @@ -19,11 +19,19 @@ #include "proxy/route/ob_table_entry.h" #include "proxy/route/ob_partition_entry.h" #include "proxy/route/ob_mysql_route.h" +#include "obproxy/obutils/ob_proxy_config.h" +#include "obproxy/proxy/mysql/ob_mysql_client_session.h" + namespace oceanbase { namespace obproxy { +namespace obutils +{ +class ObClusterResource; +} + namespace proxy { class ObMysqlRouteResult; @@ -45,17 +53,16 @@ public: // | | // +<---------------------------------------+ const ObProxyReplicaLocation *get_next_avail_replica(); - const ObProxyReplicaLocation *get_next_replica(const uint32_t cur_ip, const uint16_t cur_port, - const bool is_force_retry); const ObProxyReplicaLocation *get_leader_replica_from_remote() const; ObTableEntry *get_dummy_entry(); ObTableEntry *get_table_entry() { return table_entry_; } int fill_replicas(const common::ObConsistencyLevel level, const ObRoutePolicyEnum route_policy, + const bool is_random_routing_mode, const bool disable_merge_status_check, - ObTableEntry *dummy_entry, - ObLDCLocation &dummy_ldc, + ObMysqlClientSession *client_session, + obutils::ObClusterResource *cluster_resource, const common::ObIArray &ss_info, const common::ObIArray ®ion_names, const common::ObString &proxy_primary_zone_name @@ -67,7 +74,10 @@ public: int fill_strong_read_replica(const ObProxyPartitionLocation *pl, ObLDCLocation &dummy_ldc, const common::ObIArray &ss_info, const common::ObIArray ®ion_names, - const common::ObString &proxy_primary_zone_name); + const common::ObString &proxy_primary_zone_name, + const common::ObString &tenant_name, + obutils::ObClusterResource *cluster_resource, + const bool is_random_routing_mode); int fill_weak_read_replica(const ObProxyPartitionLocation *pl, ObLDCLocation &dummy_ldc, const common::ObIArray &ss_info, const common::ObIArray ®ion_names, @@ -187,7 +197,8 @@ inline int ObServerRoute::fill_weak_read_replica( inline int ObServerRoute::fill_strong_read_replica(const ObProxyPartitionLocation *pl, ObLDCLocation &dummy_ldc, const common::ObIArray &ss_info, const common::ObIArray ®ion_names, - const ObString &proxy_primary_zone_name) + const ObString &proxy_primary_zone_name, const ObString &tenant_name, + obutils::ObClusterResource *cluster_resource, const bool is_random_routing_mode) { int ret = common::OB_SUCCESS; const bool is_only_readwrite_zone = (ONLY_READWRITE_ZONE == ldc_route_.policy_); @@ -197,12 +208,15 @@ inline int ObServerRoute::fill_strong_read_replica(const ObProxyPartitionLocatio is_only_readwrite_zone, need_use_dup_replica_, skip_leader_item_, + is_random_routing_mode, ss_info, region_names, - proxy_primary_zone_name))) { + proxy_primary_zone_name, + tenant_name, + cluster_resource))) { PROXY_LOG(WARN, "fail to divide_leader_replica", K(ret)); } else { valid_count_ = ldc_route_.location_.count() + ((!need_use_dup_replica_ && leader_item_.is_valid()) ? 1 : 0); - PROXY_LOG(DEBUG, "succ to fill_strong_read_replica", KPC(this), KPC(pl), K(dummy_ldc)); + PROXY_LOG(DEBUG, "succ to fill_strong_read_replica", KPC(this), KPC(pl), K(dummy_ldc), K(valid_count_)); } if (entry_need_update) { //if dummy entry has expand, we can update it here @@ -214,9 +228,10 @@ inline int ObServerRoute::fill_strong_read_replica(const ObProxyPartitionLocatio inline int ObServerRoute::fill_replicas( const common::ObConsistencyLevel level, const ObRoutePolicyEnum route_policy, + const bool is_random_routing_mode, const bool disable_merge_status_check, - ObTableEntry *dummy_entry, - ObLDCLocation &dummy_ldc, + ObMysqlClientSession *client_session, + obutils::ObClusterResource *cluster_resource, const common::ObIArray &ss_info, const common::ObIArray ®ion_names, const ObString &proxy_primary_zone_name @@ -227,6 +242,10 @@ inline int ObServerRoute::fill_replicas( ) { int ret = common::OB_SUCCESS; + + ObTableEntry *dummy_entry = client_session->dummy_entry_; + ObLDCLocation &dummy_ldc = client_session->dummy_ldc_; + if (OB_UNLIKELY(common::STRONG != level && common::WEAK != level)) { ret = common::OB_ERR_UNEXPECTED; PROXY_LOG(WARN, "unsupport ObConsistencyLevel", K(level), K(ret)); @@ -273,7 +292,9 @@ inline int ObServerRoute::fill_replicas( #endif if (is_strong_read()) { - ret = fill_strong_read_replica(cur_chosen_pl_, dummy_ldc, ss_info, region_names, proxy_primary_zone_name); + ObString &tenant_name = client_session->get_session_info().get_priv_info().tenant_name_; + ret = fill_strong_read_replica(cur_chosen_pl_, dummy_ldc, ss_info, region_names, + proxy_primary_zone_name, tenant_name, cluster_resource, is_random_routing_mode); } else { ret = fill_weak_read_replica(cur_chosen_pl_, dummy_ldc, ss_info, region_names, proxy_primary_zone_name); } @@ -366,11 +387,20 @@ inline const ObProxyReplicaLocation *ObServerRoute::get_next_avail_replica() cur_chosen_route_type_ = ROUTE_TYPE_LEADER; leader_item_.is_used_ = true; } else { - leader_item_.is_used_ = true; - //2. get follower - item = ldc_route_.get_next_item(); - cur_chosen_route_type_ = ldc_route_.get_curr_route_type(); + leader_item_.is_used_ = true; + item = ldc_route_.get_next_primary_zone_item(); + if (item == NULL) { + item = ldc_route_.get_next_item(); // primary zone no replica, choose from others. + if (NULL != item) { + cur_chosen_route_type_ = ldc_route_.get_curr_route_type(); + PROXY_LOG(DEBUG, "enable pz, no pz item, choose from origin item", K(item->replica_->server_)); + } + } else { + // succ to get item from primary zone route optimize, no need update pl + no_need_pl_update_ = true; + PROXY_LOG(DEBUG, "enable pz, choose pz item", K(item->replica_->server_)); + } } } @@ -405,27 +435,6 @@ inline const ObProxyReplicaLocation *ObServerRoute::get_next_avail_replica() return cur_chosen_server_.replica_; } -inline const ObProxyReplicaLocation *ObServerRoute::get_next_replica( - const uint32_t cur_ip, - const uint16_t cur_port, - const bool is_force_retry) -{ - UNUSED(is_force_retry); - const ObProxyReplicaLocation *replica = NULL; - bool found = false; - leader_item_.is_used_ = true; - while (!found) { - replica = get_next_avail_replica(); - if (NULL == replica) { - found = true; - } else if ((cur_ip != replica->server_.get_ipv4()) - || (cur_port != static_cast(replica->server_.get_port()))) { - found = true; - } - } - return replica; -} - inline bool ObServerRoute::is_partition_table() const { return ((NULL != table_entry_) && table_entry_->is_partition_table()); diff --git a/src/obproxy/proxy/route/ob_sql_table_cache.cpp b/src/obproxy/proxy/route/ob_sql_table_cache.cpp index 9963b035d88ef8855fb772a829aadf520ee21afb..7e693ac91aae41d06b0a12d13dfdabe188f542da 100644 --- a/src/obproxy/proxy/route/ob_sql_table_cache.cpp +++ b/src/obproxy/proxy/route/ob_sql_table_cache.cpp @@ -258,22 +258,33 @@ int init_sql_table_map_for_thread() { int ret = OB_SUCCESS; const int64_t event_thread_count = g_event_processor.thread_count_for_type_[ET_CALL]; + for (int64_t i = 0; (i < event_thread_count) && OB_SUCC(ret); ++i) { + if (OB_FAIL(init_sql_table_map_for_one_thread(i))) { + LOG_WARN("fail to init sql_table_map", K(i), K(ret)); + } + } + return ret; +} + +int init_sql_table_map_for_one_thread(int64_t index) +{ + int ret = OB_SUCCESS; ObEThread **ethreads = NULL; if (OB_ISNULL(ethreads = g_event_processor.event_thread_[ET_CALL])) { ret = OB_ERR_UNEXPECTED; PROXY_NET_LOG(ERROR, "fail to get ET_NET thread", K(ret)); + } else if (OB_ISNULL(ethreads[index])) { + ret = OB_ERR_UNEXPECTED; + PROXY_NET_LOG(ERROR, "fail to get ET_NET thread", K(ret)); } else { - for (int64_t i = 0; (i < event_thread_count) && OB_SUCC(ret); ++i) { - if (OB_ISNULL(ethreads[i]->sql_table_map_ = new (std::nothrow) ObSqlTableRefHashMap(ObModIds::OB_PROXY_SQL_TABLE_ENTRY_MAP))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to new ObSqlTableRefHashMap", K(i), K(ethreads[i]), K(ret)); - } else if (OB_FAIL(ethreads[i]->sql_table_map_->init())) { - LOG_WARN("fail to init sql_table_map", K(ret)); - } + if (OB_ISNULL(ethreads[index]->sql_table_map_ = new (std::nothrow) ObSqlTableRefHashMap(ObModIds::OB_PROXY_SQL_TABLE_ENTRY_MAP))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to new ObSqlTableRefHashMap", K(index), K(ethreads[index]), K(ret)); + } else if (OB_FAIL(ethreads[index]->sql_table_map_->init())) { + LOG_WARN("fail to init sql_table_map", K(ret)); } } return ret; - } int ObSqlTableRefHashMap::clean_hash_map() diff --git a/src/obproxy/proxy/route/ob_sql_table_cache.h b/src/obproxy/proxy/route/ob_sql_table_cache.h index 4b78addaff4cd70090827951aceaa8318cf2bd57..9e2c4ebe5b473ff62906c7bf9dd4d845e20f4d52 100644 --- a/src/obproxy/proxy/route/ob_sql_table_cache.h +++ b/src/obproxy/proxy/route/ob_sql_table_cache.h @@ -109,6 +109,7 @@ private: }; int init_sql_table_map_for_thread(); +int init_sql_table_map_for_one_thread(int64_t index); } // end of namespace proxy } // end of namespace obproxy diff --git a/src/obproxy/proxy/route/ob_table_cache.cpp b/src/obproxy/proxy/route/ob_table_cache.cpp index 9d4532694500e586fd20a2caee10deb414680a6d..0213dd48d6112f5b3c8e10730e6eed9607d78347 100644 --- a/src/obproxy/proxy/route/ob_table_cache.cpp +++ b/src/obproxy/proxy/route/ob_table_cache.cpp @@ -663,25 +663,36 @@ int init_table_map_for_thread() { int ret = OB_SUCCESS; const int64_t event_thread_count = g_event_processor.thread_count_for_type_[ET_CALL]; + for (int64_t i = 0; (i < event_thread_count) && OB_SUCC(ret); ++i) { + if (OB_FAIL(init_table_map_for_one_thread(i))) { + LOG_WARN("fail to init table_map", K(i), K(ret)); + } + } + return ret; +} + +int init_table_map_for_one_thread(int64_t index) +{ + int ret = OB_SUCCESS; ObEThread **ethreads = NULL; if (OB_ISNULL(ethreads = g_event_processor.event_thread_[ET_CALL])) { ret = OB_ERR_UNEXPECTED; PROXY_NET_LOG(ERROR, "fail to get ET_NET thread", K(ret)); + } else if (OB_ISNULL(ethreads[index])) { + ret = OB_ERR_UNEXPECTED; + PROXY_NET_LOG(ERROR, "fail to get ET_NET thread", K(ret)); } else { - for (int64_t i = 0; (i < event_thread_count) && OB_SUCC(ret); ++i) { - if (OB_ISNULL(ethreads[i]->table_map_ = new (std::nothrow) ObTableRefHashMap(ObModIds::OB_PROXY_TABLE_ENTRY_MAP))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to new ObTableRefHashMap", K(i), K(ethreads[i]), K(ret)); - } else if (OB_FAIL(ethreads[i]->table_map_->init())) { - LOG_WARN("fail to init table_map", K(ret)); - } else { - LOG_DEBUG("succ to init table_map", K(ET_CALL), "ethread", reinterpret_cast(ethreads[i]), - "table_map", reinterpret_cast(ethreads[i]->table_map_), K(ret)); - } + if (OB_ISNULL(ethreads[index]->table_map_ = new (std::nothrow) ObTableRefHashMap(ObModIds::OB_PROXY_TABLE_ENTRY_MAP))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to new ObTableRefHashMap", K(index), K(ethreads[index]), K(ret)); + } else if (OB_FAIL(ethreads[index]->table_map_->init())) { + LOG_WARN("fail to init table_map", K(ret)); + } else { + LOG_DEBUG("succ to init table_map", K(ET_CALL), "ethread", reinterpret_cast(ethreads[index]), + "table_map", reinterpret_cast(ethreads[index]->table_map_), K(ret)); } } return ret; - } int ObTableRefHashMap::clean_hash_map() diff --git a/src/obproxy/proxy/route/ob_table_cache.h b/src/obproxy/proxy/route/ob_table_cache.h index d5556fe4d11d5bd192a4811ba08fc58876b50579..0d8fd0d6ee218577571a3d87de286615e55f411f 100644 --- a/src/obproxy/proxy/route/ob_table_cache.h +++ b/src/obproxy/proxy/route/ob_table_cache.h @@ -122,7 +122,7 @@ bool ObTableCache::is_table_entry_expired_in_time_mode(const ObTableEntry &entry { bool is_expire = (!entry.is_sys_dummy_entry() && (entry.get_create_time_us() <= expire_time_us_)); if (!is_expire) { - is_expire = (!entry.is_dummy_entry()) && entry.get_time_for_expired() > 0 + is_expire = (!entry.is_sys_dummy_entry()) && entry.get_time_for_expired() > 0 && entry.get_time_for_expired() <= common::ObTimeUtility::current_time(); } @@ -161,6 +161,7 @@ private: }; int init_table_map_for_thread(); +int init_table_map_for_one_thread(int64_t index); } // end of namespace proxy } // end of namespace obproxy diff --git a/src/obproxy/proxy/route/ob_table_entry.cpp b/src/obproxy/proxy/route/ob_table_entry.cpp index 42155b32499658feb860e0202d044eeb76a1c9ee..409e07c891d0a31063627fc018d564c42d6af782 100644 --- a/src/obproxy/proxy/route/ob_table_entry.cpp +++ b/src/obproxy/proxy/route/ob_table_entry.cpp @@ -118,6 +118,7 @@ int ObTableEntry::set_names(const ObTableEntryName &name) LOG_WARN("fail to deep copy table entry names", K(ret)); } else { is_dummy_entry_ = name_.is_all_dummy_table(); + is_binlog_entry_ = name_.is_binlog_table(); } return ret; } diff --git a/src/obproxy/proxy/route/ob_table_entry.h b/src/obproxy/proxy/route/ob_table_entry.h index b04cd276086d805cd66eda65841493eeb6413363..34edf1856f7eeedb47a0c56c0630be10c9d8f283 100644 --- a/src/obproxy/proxy/route/ob_table_entry.h +++ b/src/obproxy/proxy/route/ob_table_entry.h @@ -40,7 +40,7 @@ class ObTableEntry : public ObRouteEntry { public: ObTableEntry() - : ObRouteEntry(), is_inited_(false), is_dummy_entry_(false), is_entry_from_rslist_(false), + : ObRouteEntry(), is_inited_(false), is_dummy_entry_(false), is_binlog_entry_(NULL), is_entry_from_rslist_(false), is_empty_entry_allowed_(false), is_need_force_flush_(false), has_dup_replica_(false), table_id_(common::OB_INVALID_ID), table_type_(share::schema::MAX_TABLE_TYPE), part_num_(0), replica_num_(0), name_(), buf_len_(0), buf_start_(NULL), first_pl_(NULL) @@ -70,7 +70,7 @@ public: bool is_dummy_entry() const { return is_dummy_entry_; } bool is_sys_dummy_entry() const { return is_dummy_entry_ && name_.is_sys_tenant(); } bool is_common_dummy_entry() const { return is_dummy_entry_ && !name_.is_sys_tenant(); } - bool is_location_entry() const { return !is_dummy_entry_ && 1 == part_num_; } + bool is_location_entry() const { return (!is_dummy_entry_ && 1 == part_num_) || is_binlog_entry_; } bool is_part_info_entry() const { return !is_dummy_entry_ && part_num_ > 1; } bool is_non_partition_table() const { return (1 == get_part_num()); } bool is_partition_table() const { return (get_part_num() > 1); } @@ -125,6 +125,7 @@ public: private: bool is_inited_; bool is_dummy_entry_; + bool is_binlog_entry_; bool is_entry_from_rslist_; bool is_empty_entry_allowed_; bool is_need_force_flush_; @@ -164,7 +165,7 @@ inline bool ObTableEntry::is_valid() const || (is_location_entry() && NULL != first_pl_ && OB_LIKELY(first_pl_->is_valid())) || (is_part_info_entry() && NULL != part_info_ && OB_LIKELY(part_info_->is_valid())))) ) - ); + ) || is_binlog_entry_; } inline int64_t ObTableEntry::get_server_count() const diff --git a/src/obproxy/proxy/route/ob_table_entry_cont.cpp b/src/obproxy/proxy/route/ob_table_entry_cont.cpp index 4fafaf1c5b2cfe030a91a7017064f5ec76dbc89e..a5a4950bdc837bcdaeccc618a51d2bf41dad878d 100644 --- a/src/obproxy/proxy/route/ob_table_entry_cont.cpp +++ b/src/obproxy/proxy/route/ob_table_entry_cont.cpp @@ -83,6 +83,7 @@ void ObTableRouteParam::reset() mysql_proxy_ = NULL; cr_version_ = 0; cr_id_ = OB_INVALID_CLUSTER_ID; + cluster_version_ = 0; tenant_version_ = 0; current_idc_name_.reset(); is_need_force_flush_ = false; @@ -239,6 +240,9 @@ const char *ObTableEntryCont::get_state_name(const ObTableEntryLookupState state case LOOKUP_DONE_STATE: name = "LOOKUP_DONE_STATE"; break; + case LOOKUP_BINLOG_ENTRY_STATE: + name = "LOOKUP_BINLOG_ENTRY_STATE"; + break; default: name = "Unknown State"; LOG_WARN("Unknown State", K(state)); @@ -346,6 +350,7 @@ inline int ObTableEntryCont::deep_copy_table_param(ObTableRouteParam ¶m) table_param_.cr_version_ = param.cr_version_; table_param_.cr_id_ = param.cr_id_; table_param_.tenant_version_ = param.tenant_version_; + table_param_.cluster_version_ = param.cluster_version_; table_param_.is_partition_table_route_supported_ = param.is_partition_table_route_supported_; table_param_.is_oracle_mode_ = param.is_oracle_mode_; table_param_.is_need_force_flush_ = param.is_need_force_flush_; @@ -390,6 +395,7 @@ inline int ObTableEntryCont::set_next_state() bool is_part_table_route_supported = table_param_.is_partition_table_route_supported_; switch (state_) { case LOOKUP_TABLE_ENTRY_STATE: + case LOOKUP_BINLOG_ENTRY_STATE: if (OB_ISNULL(newest_table_entry_)) { next_state = LOOKUP_DONE_STATE; } else if (newest_table_entry_->is_partition_table() && is_part_table_route_supported) { @@ -426,9 +432,7 @@ inline int ObTableEntryCont::set_next_state() next_state = LOOKUP_DONE_STATE; ret = OB_ERR_UNEXPECTED; LOG_WARN("part info should not be null here", K(ret)); - } else if (!newest_table_entry_->get_part_info()->is_template_table() - || newest_table_entry_->get_part_info()->get_sub_part_option().is_range_part() - || newest_table_entry_->get_part_info()->get_sub_part_option().is_list_part()) { + } else if (newest_table_entry_->get_part_info()->has_sub_part()) { next_state = LOOKUP_SUB_PART_STATE; } else { next_state = LOOKUP_DONE_STATE; @@ -478,6 +482,9 @@ inline int ObTableEntryCont::handle_client_resp(void *data) case LOOKUP_SUB_PART_STATE: ret = handle_sub_part_resp(*rs_fetcher); break; + case LOOKUP_BINLOG_ENTRY_STATE: + ret = handle_binlog_entry_resp(*rs_fetcher); + break; case LOOKUP_DONE_STATE: default: ret = OB_ERR_UNEXPECTED; @@ -527,7 +534,8 @@ inline int ObTableEntryCont::handle_table_entry_resp(ObResultSetFetcher &rs_fetc ret = OB_ERR_UNEXPECTED; LOG_WARN("table entry should not be NULL", K_(newest_table_entry), K(ret)); } else if (OB_FAIL(ObRouteUtils::fetch_table_entry(rs_fetcher, - *newest_table_entry_))) { + *newest_table_entry_, + table_param_.cluster_version_))) { LOG_WARN("fail to fetch one table entry info", K(ret)); } else { newest_table_entry_->set_tenant_version(table_param_.tenant_version_); @@ -535,6 +543,22 @@ inline int ObTableEntryCont::handle_table_entry_resp(ObResultSetFetcher &rs_fetc return ret; } +int ObTableEntryCont::handle_binlog_entry_resp(ObResultSetFetcher &rs_fetcher) +{ + int ret = OB_SUCCESS; + if (OB_FAIL(ObTableEntry::alloc_and_init_table_entry(table_param_.name_, 0, 0, newest_table_entry_))) { + LOG_WARN("fail to alloc and init table entry", "name", table_param_.name_, K(ret)); + } else if (OB_ISNULL(newest_table_entry_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("table entry should not be NULL", K_(newest_table_entry), K(ret)); + } else if (OB_FAIL(ObRouteUtils::fetch_binlog_entry(rs_fetcher, + *newest_table_entry_))) { + LOG_WARN("fail to fetch binlog entry info", K(ret)); + } + + return ret; +} + inline int ObTableEntryCont::handle_part_info_resp(ObResultSetFetcher &rs_fetcher) { int ret = OB_SUCCESS; @@ -549,7 +573,7 @@ inline int ObTableEntryCont::handle_part_info_resp(ObResultSetFetcher &rs_fetche LOG_WARN("part info should not be null here", K(ret)); } else if (FALSE_IT(part_info->set_oracle_mode(table_param_.is_oracle_mode_))) { // do nothing - } else if (OB_FAIL(ObRouteUtils::fetch_part_info(rs_fetcher, *part_info))) { + } else if (OB_FAIL(ObRouteUtils::fetch_part_info(rs_fetcher, *part_info, table_param_.cluster_version_))) { PROCESSOR_INCREMENT_DYN_STAT(GET_PART_INFO_FROM_REMOTE_FAIL); ROUTE_PROMETHEUS_STAT(table_param_.name_, PROMETHEUS_ENTRY_LOOKUP_COUNT, PARTITION_INFO, false, false); LOG_WARN("fail to fetch part info", K(ret)); @@ -570,7 +594,7 @@ inline int ObTableEntryCont::handle_first_part_resp(ObResultSetFetcher &rs_fetch } else if (OB_ISNULL(part_info = newest_table_entry_->get_part_info())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("part info should not be null here", K(ret)); - } else if (OB_FAIL(ObRouteUtils::fetch_first_part(rs_fetcher, *part_info))) { + } else if (OB_FAIL(ObRouteUtils::fetch_first_part(rs_fetcher, *part_info, table_param_.cluster_version_))) { PROCESSOR_INCREMENT_DYN_STAT(GET_FIRST_PART_FROM_REMOTE_FAIL); ROUTE_PROMETHEUS_STAT(table_param_.name_, PROMETHEUS_ENTRY_LOOKUP_COUNT, PARTITION_INFO, false, false); LOG_WARN("fail to fetch part info", K(ret)); @@ -591,7 +615,7 @@ inline int ObTableEntryCont::handle_sub_part_resp(ObResultSetFetcher &rs_fetcher } else if (OB_ISNULL(part_info = newest_table_entry_->get_part_info())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("part info should not be null here", K(ret)); - } else if (OB_FAIL(ObRouteUtils::fetch_sub_part(rs_fetcher, *part_info))) { + } else if (OB_FAIL(ObRouteUtils::fetch_sub_part(rs_fetcher, *part_info, table_param_.cluster_version_))) { PROCESSOR_INCREMENT_DYN_STAT(GET_SUB_PART_FROM_REMOTE_FAIL); ROUTE_PROMETHEUS_STAT(table_param_.name_, PROMETHEUS_ENTRY_LOOKUP_COUNT, PARTITION_INFO, false, false); LOG_WARN("fail to fetch part info", K(ret)); @@ -881,13 +905,33 @@ inline int ObTableEntryCont::lookup_entry_remote() ObMysqlProxy *mysql_proxy = table_param_.mysql_proxy_; char sql[OB_SHORT_SQL_LENGTH]; sql[0] = '\0'; - if (OB_FAIL(ObRouteUtils::get_table_entry_sql(sql, OB_SHORT_SQL_LENGTH, table_param_.name_, - table_param_.is_need_force_flush_))) { - LOG_WARN("fail to get table entry sql", K(sql), K(ret)); + if (table_param_.name_.table_name_ == OB_ALL_BINLOG_DUMMY_TNAME) { + if (OB_FAIL(ObRouteUtils::get_binlog_entry_sql(sql, OB_SHORT_SQL_LENGTH, + table_param_.name_.cluster_name_, table_param_.name_.tenant_name_))) { + LOG_WARN("fail to get binlog entry sql", K(ret)); + } else { + state_ = LOOKUP_BINLOG_ENTRY_STATE; + ObMysqlRequestParam request_param(sql); + ObAddr addr; + if (OB_FAIL(addr.parse_from_cstring(get_global_proxy_config().binlog_service_ip.str()))) { + LOG_WARN("parse from cstring failed", K(ret)); + } else { + request_param.set_target_addr(addr); + request_param.ob_client_flags_.client_flags_.OB_CLIENT_SKIP_AUTOCOMMIT = 1; + if (OB_FAIL(mysql_proxy->async_read(this, request_param, pending_action_))) { + LOG_WARN("fail to aysnc read", K(sql), K(addr), K(ret)); + } + } + } } else { - const ObMysqlRequestParam request_param(sql, table_param_.current_idc_name_); - if (OB_FAIL(mysql_proxy->async_read(this, request_param, pending_action_))) { - LOG_WARN("fail to nonblock read", K(sql), K_(table_param), K(ret)); + if (OB_FAIL(ObRouteUtils::get_table_entry_sql(sql, OB_SHORT_SQL_LENGTH, table_param_.name_, + table_param_.is_need_force_flush_, table_param_.cluster_version_))) { + LOG_WARN("fail to get table entry sql", K(sql), K(ret)); + } else { + const ObMysqlRequestParam request_param(sql, table_param_.current_idc_name_); + if (OB_FAIL(mysql_proxy->async_read(this, request_param, pending_action_))) { + LOG_WARN("fail to nonblock read", K(sql), K_(table_param), K(ret)); + } } } @@ -911,7 +955,9 @@ inline int ObTableEntryCont::lookup_part_info_remote() ret = OB_ERR_UNEXPECTED; LOG_WARN("table entry should not be null", K(ret)); } else if (OB_FAIL(ObRouteUtils::get_part_info_sql(sql, OB_SHORT_SQL_LENGTH, - newest_table_entry_->get_table_id()))) { + newest_table_entry_->get_table_id(), + table_param_.name_, + table_param_.cluster_version_))) { LOG_WARN("fail to get table entry sql", K(sql), K(ret)); } else { const ObMysqlRequestParam request_param(sql, table_param_.current_idc_name_); @@ -934,8 +980,10 @@ inline int ObTableEntryCont::lookup_first_part_remote() LOG_WARN("table entry should not be null", K(ret)); } else if (OB_FAIL(ObRouteUtils::get_first_part_sql(sql, OB_SHORT_SQL_LENGTH, newest_table_entry_->get_table_id(), - (newest_table_entry_->get_part_info()->get_first_part_option().is_hash_part() - || newest_table_entry_->get_part_info()->get_first_part_option().is_key_part())))) { + (newest_table_entry_->get_part_info()->get_first_part_option().is_hash_part(table_param_.cluster_version_) + || newest_table_entry_->get_part_info()->get_first_part_option().is_key_part(table_param_.cluster_version_)), + table_param_.name_, + table_param_.cluster_version_))) { LOG_WARN("fail to get table entry sql", K(sql), K(ret)); } else { const ObMysqlRequestParam request_param(sql, table_param_.current_idc_name_); @@ -958,7 +1006,9 @@ inline int ObTableEntryCont::lookup_sub_part_remote() LOG_WARN("table entry should not be null", K(ret)); } else if (OB_FAIL(ObRouteUtils::get_sub_part_sql(sql, OB_SHORT_SQL_LENGTH, newest_table_entry_->get_table_id(), - newest_table_entry_->get_part_info()->is_template_table()))) { + newest_table_entry_->get_part_info()->is_template_table(), + table_param_.name_, + table_param_.cluster_version_))) { LOG_WARN("fail to get table entry sql", K(sql), K(ret)); } else { const ObMysqlRequestParam request_param(sql, table_param_.current_idc_name_); diff --git a/src/obproxy/proxy/route/ob_table_entry_cont.h b/src/obproxy/proxy/route/ob_table_entry_cont.h index 744e36f2e3073947b930bee03414eaa9c914bb0c..189bae912a51d6541f2eaada7181d9b4c38cbc76 100644 --- a/src/obproxy/proxy/route/ob_table_entry_cont.h +++ b/src/obproxy/proxy/route/ob_table_entry_cont.h @@ -50,6 +50,7 @@ enum ObTableEntryLookupState LOOKUP_PART_INFO_STATE, LOOKUP_FIRST_PART_STATE, LOOKUP_SUB_PART_STATE, + LOOKUP_BINLOG_ENTRY_STATE, LOOKUP_DONE_STATE, }; @@ -89,6 +90,7 @@ public: ObTableEntryName name_; int64_t cr_version_; int64_t cr_id_; + int64_t cluster_version_; uint64_t tenant_version_; bool is_partition_table_route_supported_; bool force_renew_; @@ -141,6 +143,7 @@ private: int handle_sub_part_resp(ObResultSetFetcher &rs_fetcher); int handle_lookup_remote(); int handle_lookup_remote_done(); + int handle_binlog_entry_resp(ObResultSetFetcher &rs_fetcher); int handle_lookup_remote_for_update(); int add_to_global_cache(bool &add_succ); diff --git a/src/obproxy/proxy/route/ob_tenant_server.cpp b/src/obproxy/proxy/route/ob_tenant_server.cpp index 6eb8ddfcda16773bddc98bc3a0b7ef31820cf92d..fcf5186a5cea91223aeeb22d3de4151fffeb36f7 100644 --- a/src/obproxy/proxy/route/ob_tenant_server.cpp +++ b/src/obproxy/proxy/route/ob_tenant_server.cpp @@ -43,7 +43,7 @@ int ObTenantServer::init(const ObIArray &locations) LOG_WARN("invalid replica location", K(locations), K(ret)); } else if (OB_UNLIKELY(NULL != server_array_)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("server_list_ should be null here", K(server_array_), K(ret)); + LOG_WARN("server_array_ should be null here", K(server_array_), K(ret)); } else { const int64_t alloc_size = static_cast(sizeof(ObProxyReplicaLocation)) * locations.count(); char *server_list_buf = NULL; diff --git a/src/obproxy/proxy/route/obproxy_expr_calculator.cpp b/src/obproxy/proxy/route/obproxy_expr_calculator.cpp index 0031c6d1ebbdb03e144698248cb05cc5269849be..c22bc8004a0780e89f8f75f55325b0fb6bdee897 100644 --- a/src/obproxy/proxy/route/obproxy_expr_calculator.cpp +++ b/src/obproxy/proxy/route/obproxy_expr_calculator.cpp @@ -47,8 +47,10 @@ int ObProxyExprCalculator::calculate_partition_id(common::ObArenaAllocator &allo { int ret = OB_SUCCESS; ObString part_name = parse_result.get_part_name(); + bool old_is_oracle_mode = lib::is_oracle_mode(); + lib::set_oracle_mode(client_info.is_oracle_mode()); if (!part_name.empty()) { - if (OB_FAIL(part_info.get_part_mgr().get_part_with_part_name(part_name, partition_id))) { + if (OB_FAIL(part_info.get_part_mgr().get_part_with_part_name(part_name, partition_id, part_info, route, *this))) { LOG_WARN("fail to get part id with part name", K(part_name), K(ret)); } } @@ -65,6 +67,7 @@ int ObProxyExprCalculator::calculate_partition_id(common::ObArenaAllocator &allo const common::ObString &print_sql = ObProxyMysqlRequest::get_print_sql(req_sql); ObPsIdEntry *ps_id_entry = NULL; ObTextPsEntry *text_ps_entry = NULL; + ObTextPsNameEntry* text_ps_name_entry = NULL; ObMySQLCmd cmd = client_request.get_packet_meta().cmd_; if (OB_MYSQL_COM_STMT_EXECUTE == cmd || OB_MYSQL_COM_STMT_SEND_LONG_DATA == cmd) { @@ -76,7 +79,10 @@ int ObProxyExprCalculator::calculate_partition_id(common::ObArenaAllocator &allo LOG_WARN("client ps id entry is null", K(ret)); } } else if (parse_result.is_text_ps_execute_stmt()) { - if (OB_ISNULL(text_ps_entry = client_info.get_text_ps_entry())) { + if (OB_ISNULL(text_ps_name_entry = client_info.get_text_ps_name_entry())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("client text ps name entry is null", K(ret)); + } else if (OB_ISNULL(text_ps_entry = text_ps_name_entry->text_ps_entry_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("client text ps entry is null", K(ret)); } @@ -88,22 +94,27 @@ int ObProxyExprCalculator::calculate_partition_id(common::ObArenaAllocator &allo LOG_INFO("fail to do expr parse", K(print_sql), K(part_info), "expr_parse_result", ObExprParseResultPrintWrapper(expr_parse_result)); } else if (OB_FAIL(do_expr_resolve(expr_parse_result, client_request, &client_info, ps_id_entry, - text_ps_entry, part_info, allocator, resolve_result))) { + text_ps_entry, part_info, allocator, resolve_result, + parse_result, partition_id))) { LOG_INFO("fail to do expr resolve", K(print_sql), "expr_parse_result", ObExprParseResultPrintWrapper(expr_parse_result), K(part_info), KPC(ps_id_entry), KPC(text_ps_entry), K(resolve_result)); - } else if (OB_FAIL(do_partition_id_calc(resolve_result, client_info, route, part_info, parse_result, - allocator, partition_id))) { - if (OB_MYSQL_COM_STMT_PREPARE != cmd) { - LOG_INFO("fail to do expr resolve", K(print_sql), K(resolve_result), K(part_info)); + } else if (partition_id == OB_INVALID_INDEX) { + if (OB_FAIL(do_partition_id_calc(resolve_result, client_info, route, part_info, + parse_result, allocator, partition_id))) { + if (OB_MYSQL_COM_STMT_PREPARE != cmd) { + LOG_INFO("fail to do expr resolve", K(print_sql), K(resolve_result), K(part_info)); + } } } else { - /* do nothing */ + LOG_DEBUG("succ to get partition id(tabletid) from rowid", K(partition_id)); } } - if (OB_FAIL(ret) + if ((OB_FAIL(ret) || partition_id == OB_INVALID_INDEX) + && !get_global_proxy_config().enable_primary_zone && !get_global_proxy_config().enable_cached_server) { + // if proxy primary zone route optimization disabled, use random part id optimization int64_t tmp_first_part_id = OB_INVALID_INDEX; int64_t tmp_sub_part_id = OB_INVALID_INDEX; if (OB_FAIL(calc_part_id_by_random_choose_from_exist(part_info, @@ -118,6 +129,7 @@ int ObProxyExprCalculator::calculate_partition_id(common::ObArenaAllocator &allo } } + lib::set_oracle_mode(old_is_oracle_mode); return ret; } @@ -189,14 +201,6 @@ int ObProxyExprCalculator::do_expr_parse(const common::ObString &req_sql, expr_result.part_key_info_.part_keys_[i] = key_info.part_keys_[i]; } - expr_result.target_mask_ = 0; - if (PARTITION_LEVEL_ONE == part_info.get_part_level()) { - expr_result.target_mask_ = FIRST_PART_MASK; - } else if (PARTITION_LEVEL_TWO == part_info.get_part_level()) { - expr_result.target_mask_ = BOTH_PART_MASK; - } else { - // do nothing - } if (OB_FAIL(expr_parser.parse_reqsql(req_sql, parse_result.get_parsed_length(), expr_result, parse_result.get_stmt_type(), connection_collation))) { LOG_DEBUG("fail to do expr parse_reqsql", K(req_sql), K(ret)); @@ -238,7 +242,9 @@ int ObProxyExprCalculator::do_expr_resolve(ObExprParseResult &parse_result, ObTextPsEntry *text_ps_entry, ObProxyPartInfo &part_info, ObIAllocator &allocator, - ObExprResolverResult &resolve_result) + ObExprResolverResult &resolve_result, + const ObSqlParseResult &sql_parse_result, + int64_t &partition_id) { int ret = OB_SUCCESS; ObExprResolverContext ctx; @@ -248,12 +254,15 @@ int ObProxyExprCalculator::do_expr_resolve(ObExprParseResult &parse_result, ctx.ps_id_entry_ = ps_id_entry; ctx.text_ps_entry_ = text_ps_entry; ctx.client_info_ = client_info; - + ctx.parse_result_ = &parse_result; + ctx.is_insert_stm_ = sql_parse_result.is_insert_stmt(); + ObSqlParseResult &result = const_cast(sql_parse_result); + ctx.sql_field_result_ = &result.get_sql_filed_result(); ObExprResolver expr_resolver(allocator); if (parse_result.has_rowid_) { - if (OB_FAIL(calc_partition_id_using_rowid(parse_result, part_info, resolve_result, allocator))) { - LOG_WARN("calc partition id using rowid failed", K(ret)); + if (OB_FAIL(calc_partition_id_using_rowid(ctx, resolve_result, allocator, partition_id))) { + LOG_DEBUG("calc partition id using rowid failed", K(ret)); } } else if (OB_FAIL(expr_resolver.resolve(ctx, resolve_result))) { LOG_DEBUG("fail to do expr resolve", K(ret)); @@ -276,44 +285,64 @@ int ObProxyExprCalculator::do_partition_id_calc(ObExprResolverResult &resolve_re ObProxyPartMgr &part_mgr = part_info.get_part_mgr(); int64_t first_part_id = OB_INVALID_INDEX; int64_t sub_part_id = OB_INVALID_INDEX; + int64_t tablet_id = -1; if (part_info.has_first_part()) { - ObPartDescCtx ctx(&session_info, parse_result.is_insert_stmt()); + ObPartDescCtx ctx(&session_info, parse_result.is_insert_stmt(), part_info.get_cluster_version()); ObSEArray part_ids; + ObSEArray tablet_ids; if (OB_FAIL(part_mgr.get_first_part(resolve_result.ranges_[PARTITION_LEVEL_ONE - 1], allocator, part_ids, - ctx))) { + ctx, + tablet_ids))) { LOG_DEBUG("fail to get first part", K(ret)); } else if (part_ids.count() >= 1) { first_part_id = part_ids[0]; - } else { - // do nothing } + if (OB_SUCC(ret) && tablet_ids.count() >= 1) { + tablet_id = tablet_ids.at(0); + } + + LOG_DEBUG("do partition id calc", K(first_part_id), K(tablet_id), K(part_info.has_sub_part())); - ObSEArray sub_part_ids; if (OB_INVALID_INDEX != first_part_id && part_info.has_sub_part()) { ObPartDesc *sub_part_desc_ptr = NULL; + ObSEArray sub_part_ids; + ObSEArray tablet_ids; if (OB_FAIL(part_mgr.get_sub_part_desc_by_first_part_id(part_info.is_template_table(), first_part_id, - sub_part_desc_ptr))) { + sub_part_desc_ptr, + part_info.get_cluster_version()))) { LOG_WARN("fail to get sub part desc by first", K(ret)); } else if (OB_FAIL(part_mgr.get_sub_part(resolve_result.ranges_[PARTITION_LEVEL_TWO - 1], allocator, sub_part_desc_ptr, sub_part_ids, - ctx))) { + ctx, + tablet_ids))) { LOG_WARN("fail to get sub part", K(ret)); } else if (sub_part_ids.count() >= 1) { sub_part_id = sub_part_ids[0]; - } else { - // nothing. + } + + if (OB_SUCC(ret) && tablet_ids.count() >= 1) { + tablet_id = tablet_ids[0]; } } - if (OB_SUCC(ret)) { - partition_id = generate_phy_part_id(first_part_id, sub_part_id, part_info.get_part_level()); + LOG_DEBUG("do partition id calc", K(sub_part_id), K(tablet_id), K(part_info.has_sub_part())); + + if (OB_SUCC(ret) + && (tablet_id != -1 || (first_part_id != OB_INVALID_INDEX && (!part_info.has_sub_part() || sub_part_id != OB_INVALID_INDEX)))) { + if (tablet_id == -1) { + partition_id = generate_phy_part_id(first_part_id, sub_part_id, part_info.get_part_level()); + } else { + partition_id = tablet_id; + } LOG_DEBUG("succ to get part id", K(first_part_id), K(sub_part_id), K(partition_id)); - } else if (!get_global_proxy_config().enable_cached_server) { + } else if (!get_global_proxy_config().enable_primary_zone + && !get_global_proxy_config().enable_cached_server) { + // if proxy primary zone route optimization disabled, use random part id optimization if (OB_FAIL(calc_part_id_by_random_choose_from_exist(part_info, first_part_id, sub_part_id, partition_id))) { LOG_WARN("fail to get part id at last", K(first_part_id), K(sub_part_id), K(ret)); } else { @@ -321,6 +350,8 @@ int ObProxyExprCalculator::do_partition_id_calc(ObExprResolverResult &resolve_re route.no_need_pl_update_ = true; LOG_DEBUG("succ to get part id by random", K(first_part_id), K(sub_part_id), K(partition_id)); } + } else { + // nothing } } else { ret = OB_INVALID_ARGUMENT; @@ -336,7 +367,8 @@ int ObProxyExprCalculator::calc_part_id_by_random_choose_from_exist(ObProxyPartI int64_t &phy_part_id) { int ret = OB_SUCCESS; - + int64_t tablet_id; + ObProxyPartMgr &part_mgr = part_info.get_part_mgr(); if (part_info.has_first_part() && OB_INVALID_INDEX == first_part_id) { int64_t first_part_num = 0; @@ -347,12 +379,15 @@ int ObProxyExprCalculator::calc_part_id_by_random_choose_from_exist(ObProxyPartI if (OB_FAIL(ObRandomNumUtils::get_random_num(0, first_part_num - 1, rand_num))) { LOG_WARN("fail to get random num in first part", K(first_part_num), K(ret)); } else { - if (OB_FAIL(part_mgr.get_first_part_id_by_idx(rand_num, first_part_id))) { - LOG_WARN("failed to random get first part id by idx", K(rand_num), K(ret)); + if (OB_FAIL(part_mgr.get_first_part_id_by_random(rand_num, first_part_id, tablet_id))) { + LOG_WARN("failed to get first part id by random", K(rand_num), K(ret)); + } else { + //nothing; } } } } + LOG_DEBUG("choose partition id from exist", K(first_part_id), K(sub_part_id)); if (OB_SUCC(ret) && part_info.has_sub_part() && OB_INVALID_INDEX == sub_part_id) { int64_t sub_part_num = 0; @@ -364,24 +399,30 @@ int ObProxyExprCalculator::calc_part_id_by_random_choose_from_exist(ObProxyPartI LOG_WARN("fail to get random num in sub part", K(sub_part_num), K(ret)); } else { ObSEArray part_ids; + ObSEArray tablet_ids; ObPartDesc *sub_part_desc_ptr = NULL; if (OB_FAIL(part_mgr.get_sub_part_desc_by_first_part_id(part_info.is_template_table(), first_part_id, - sub_part_desc_ptr))) { + sub_part_desc_ptr, + part_info.get_cluster_version()))) { LOG_WARN("fail to get sub part desc by first part id", K(first_part_id), K(ret)); - } else if (OB_FAIL(part_mgr.get_sub_part_by_random(sub_rand_num, sub_part_desc_ptr, part_ids))) { + } else if (OB_FAIL(part_mgr.get_sub_part_by_random(sub_rand_num, sub_part_desc_ptr, part_ids, tablet_ids))) { LOG_WARN("fail to get sub part id by random", K(ret)); } else if (part_ids.count() >= 1) { sub_part_id = part_ids[0]; - } else { - // nothing. + } else if (tablet_ids.count() >= 1) { + tablet_id = tablet_ids[0]; } } } } - + if (OB_SUCC(ret)) { - phy_part_id = generate_phy_part_id(first_part_id, sub_part_id, part_info.get_part_level()); + if (tablet_id != -1) { + phy_part_id = tablet_id; + } else { + phy_part_id = generate_phy_part_id(first_part_id, sub_part_id, part_info.get_part_level()); + } } else { LOG_WARN("fail to cal part id by random choose from exist", K(ret)); } @@ -389,56 +430,73 @@ int ObProxyExprCalculator::calc_part_id_by_random_choose_from_exist(ObProxyPartI return ret; } -int ObProxyExprCalculator::calc_partition_id_using_rowid(const ObExprParseResult &parse_result, - ObProxyPartInfo &part_info, +int ObProxyExprCalculator::calc_partition_id_using_rowid(ObExprResolverContext &ctx, ObExprResolverResult &resolve_result, - common::ObIAllocator &allocator) + common::ObIAllocator &allocator, + int64_t &partition_id) { int ret = OB_SUCCESS; - const ObProxyParseString &rowid_str = parse_result.rowid_str_; - ObURowIDData rowid_data; - ObArray pk_vals; - if (OB_FAIL(ObURowIDData::decode2urowid(rowid_str.str_, rowid_str.str_len_, allocator, rowid_data))) { - LOG_WARN("decode2urowid failed", K(ret)); - } else if (OB_FAIL(rowid_data.get_pk_vals(pk_vals))) { - LOG_WARN("get pk vals failed", K(ret)); + const ObProxyRelationInfo *relation_info = ctx.relation_info_; + + if (OB_ISNULL(relation_info)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid ctx relation info", K(ret)); } else { - ObProxyPartKeyInfo &key_info = part_info.get_part_key_info(); - bool set_level_one_obj = false; - bool set_level_two_obj = false; - for (int64_t i = 0; OB_SUCC(ret) && i < key_info.key_num_; i++) { - ObProxyPartKey &part_key = key_info.part_keys_[i]; - if ((PART_KEY_LEVEL_ONE == part_key.level_ - || PART_KEY_LEVEL_BOTH == part_key.level_) - && !set_level_one_obj) { - if (part_key.idx_in_rowid_ < pk_vals.count()) { - ObObj &obj = pk_vals.at(part_key.idx_in_rowid_); - // handle rowid = xxx - resolve_result.ranges_[0].start_key_.assign(&obj, 1); - resolve_result.ranges_[0].end_key_.assign(&obj, 1); - resolve_result.ranges_[0].border_flag_.set_inclusive_start(); - resolve_result.ranges_[0].border_flag_.set_inclusive_end(); - set_level_one_obj = true; - LOG_DEBUG("get level one partition val from rowid", K(obj)); - } else { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("calc partition id using rowid failed", K(part_key.idx_in_rowid_), K(pk_vals.count())); + for (int64_t i = 0; OB_SUCC(ret) && i < relation_info->relation_num_; ++i) { + if (OB_ISNULL(relation_info->relations_[i])) { + LOG_INFO("invalid relation, continue.", K(i)); + } else { + ObProxyRelationExpr *relation = relation_info->relations_[i]; + if (relation->type_ == F_COMP_EQ + && relation->left_value_ != NULL + && relation->left_value_->column_node_ != NULL + && relation->right_value_ != NULL + && relation->right_value_->head_ != NULL + && is_equal_to_rowid(&relation->left_value_->column_node_->column_name_)) { + if (OB_FAIL(calc_partition_id_with_rowid(relation, ctx, allocator, resolve_result, partition_id) )) { + LOG_INFO("fail to calc partition id with rowid", K(ret)); + } else { + LOG_DEBUG("succ to calc partition id with rowid", K(partition_id)); + } } } - if (PART_KEY_LEVEL_TWO == part_key.level_ - && !set_level_two_obj) { - if (part_key.idx_in_rowid_ < pk_vals.count()) { - ObObj &obj = pk_vals.at(part_key.idx_in_rowid_); - // handle rowid = xxx - resolve_result.ranges_[1].start_key_.assign(&obj, 1); - resolve_result.ranges_[1].end_key_.assign(&obj, 1); - resolve_result.ranges_[1].border_flag_.set_inclusive_start(); - resolve_result.ranges_[1].border_flag_.set_inclusive_end(); - set_level_two_obj = true; - LOG_DEBUG("get level two partition val from rowid", K(obj)); - } else { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("calc partition id using rowid failed", K(part_key.idx_in_rowid_), K(pk_vals.count())); + } // for + } + + return ret; +} + +int ObProxyExprCalculator::calc_partition_id_with_rowid(ObProxyRelationExpr *relation, + ObExprResolverContext &ctx, + common::ObIAllocator &allocator, + ObExprResolverResult &resolve_result, + int64_t &partition_id) +{ + int ret = OB_SUCCESS; + + ObObj *target_obj = NULL; + void *buf = NULL; + if (OB_ISNULL(buf = allocator.alloc(sizeof(ObObj)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc mem", K(ret)); + } else if (OB_ISNULL(target_obj = new (buf) ObObj())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to new mem", K(ret)); + } else { + ObExprResolver expr_resolver(allocator); + if (OB_FAIL(expr_resolver.resolve_token_list(relation, ctx.part_info_, ctx.client_request_, ctx.client_info_, + ctx.ps_id_entry_, ctx.text_ps_entry_, + target_obj, ctx.sql_field_result_, true))) { + LOG_INFO("fail to resolve token list with rowid", K(ret)); + } else { + if (!target_obj->is_varchar()) { + ret = OB_ERR_UNEXPECTED; + LOG_INFO("expected obj type after resolved from execute", K(ret), K(target_obj->get_type())); + } else { + ObString obj_str = target_obj->get_varchar(); + if (OB_FAIL(calc_partition_id_with_rowid_str(obj_str.ptr(), obj_str.length(), allocator, + resolve_result, *ctx.part_info_, partition_id))) { + LOG_INFO("fail to calc partition id with rowid str within execute", K(ret)); } } } @@ -447,13 +505,34 @@ int ObProxyExprCalculator::calc_partition_id_using_rowid(const ObExprParseResult return ret; } +int ObProxyExprCalculator::calc_partition_id_with_rowid_str(const char *str, + const int64_t str_len, + common::ObIAllocator &allocator, + ObExprResolverResult &resolve_result, + ObProxyPartInfo &part_info, + int64_t &partition_id) +{ + int ret = OB_SUCCESS; + + ObURowIDData rowid_data; + if (OB_FAIL(ObURowIDData::decode2urowid(str, str_len, allocator, rowid_data))) { + LOG_WARN("decode2urowid failed", K(ret)); + } else if (OB_FAIL(rowid_data.get_obobj_or_partition_id_from_decoded(part_info, resolve_result, partition_id, allocator))) { + LOG_WARN("fail to get obobj or partition id by rowid data", K(ret)); + } else { + // nothing + } + + return ret; +} + int ObExprCalcTool::build_dtc_params_with_tz_info(ObClientSessionInfo *session_info, ObObjType obj_type, ObTimeZoneInfo &tz_info, ObDataTypeCastParams &dtc_params) { int ret = OB_SUCCESS; - + if (OB_FAIL(build_tz_info(session_info, obj_type, tz_info))) { LOG_WARN("fail to build tz info", K(ret)); } else if (OB_FAIL(build_dtc_params(session_info, obj_type, dtc_params))) { @@ -466,7 +545,7 @@ int ObExprCalcTool::build_dtc_params_with_tz_info(ObClientSessionInfo *session_i } /* - * for ObTimestampLTZType, input timestamp string, and we also need time_zone from session + * for ObTimestampLTZType, ObTimestampTZType input timestamp string, and we also need time_zone from session * in order to decide the absolutely time */ int ObExprCalcTool::build_tz_info(ObClientSessionInfo *session_info, @@ -474,22 +553,31 @@ int ObExprCalcTool::build_tz_info(ObClientSessionInfo *session_info, ObTimeZoneInfo &tz_info) { int ret = OB_SUCCESS; + if (ObTimestampLTZType == obj_type || ObTimestampTZType == obj_type) { + if (OB_FAIL(build_tz_info_for_all_type(session_info, tz_info))) { + LOG_WARN("fail to build time zone info with session", K(ret)); + } + } + return ret; +} + +int ObExprCalcTool::build_tz_info_for_all_type(ObClientSessionInfo *session_info, + ObTimeZoneInfo &tz_info) +{ + int ret = OB_SUCCESS; + ObObj value_obj; + ObString sys_key_name = ObString::make_string(oceanbase::sql::OB_SV_TIME_ZONE); - if (ObTimestampLTZType == obj_type) { - ObObj value_obj; - ObString sys_key_name = ObString::make_string(oceanbase::sql::OB_SV_TIME_ZONE); - if (OB_FAIL(session_info->get_sys_variable_value(sys_key_name, value_obj))) { - LOG_WARN("fail to get sys var from session", K(ret), K(sys_key_name)); + if (OB_FAIL(session_info->get_sys_variable_value(sys_key_name, value_obj))) { + LOG_WARN("fail to get sys var from session", K(ret), K(sys_key_name)); + } else { + ObString value_str = value_obj.get_string(); + if (OB_FAIL(tz_info.set_timezone(value_str))) { + LOG_WARN("fail to set time zone for tz_info", K(ret), K(value_str)); } else { - ObString value_str = value_obj.get_string(); - if (OB_FAIL(tz_info.set_timezone(value_str))) { - LOG_WARN("fail to set time zone for tz_info", K(ret), K(value_str)); - } else { - LOG_DEBUG("succ to set time zone for tz_info", K(value_str)); - } + LOG_DEBUG("succ to set time zone for tz_info", K(value_str)); } } - return ret; } @@ -540,4 +628,4 @@ int ObExprCalcTool::build_dtc_params(ObClientSessionInfo *session_info, return ret; } - + diff --git a/src/obproxy/proxy/route/obproxy_expr_calculator.h b/src/obproxy/proxy/route/obproxy_expr_calculator.h index dece8ca04da81a13896b79f1d15dedd7d3ae4864..a657c074ba8824643832e3d41705fe0257435b1c 100644 --- a/src/obproxy/proxy/route/obproxy_expr_calculator.h +++ b/src/obproxy/proxy/route/obproxy_expr_calculator.h @@ -31,6 +31,7 @@ namespace obproxy namespace opsql { class ObExprResolverResult; +struct ObExprResolverContext; } namespace obutils { @@ -58,6 +59,10 @@ public: ObServerRoute &route, ObProxyPartInfo &part_info, int64_t &partition_id); + int calc_part_id_by_random_choose_from_exist(ObProxyPartInfo &part_info, + int64_t &first_part_id, + int64_t &sub_part_id, + int64_t &phy_part_id); private: // do parse -> do resolve -> do partition id calc int do_expr_parse(const common::ObString &req_sql, @@ -73,7 +78,9 @@ private: ObTextPsEntry *text_ps_entry, ObProxyPartInfo &part_info, common::ObIAllocator &allocator, - opsql::ObExprResolverResult &resolve_result); + opsql::ObExprResolverResult &resolve_result, + const obutils::ObSqlParseResult &sql_parse_result, + int64_t &partition_id); int do_partition_id_calc(opsql::ObExprResolverResult &resolve_result, ObClientSessionInfo &client_info, ObServerRoute &route, @@ -90,14 +97,21 @@ private: int do_resolve_with_part_key(const obutils::ObSqlParseResult &parse_result, common::ObIAllocator &allocator, opsql::ObExprResolverResult &resolve_result); - int calc_partition_id_using_rowid(const ObExprParseResult &parse_result, - ObProxyPartInfo &part_info, + int calc_partition_id_using_rowid(opsql::ObExprResolverContext &ctx, opsql::ObExprResolverResult &resolve_result, - common::ObIAllocator &allocator); - int calc_part_id_by_random_choose_from_exist(ObProxyPartInfo &part_info, - int64_t &first_part_id, - int64_t &sub_part_id, - int64_t &phy_part_id); + common::ObIAllocator &allocator, + int64_t &partition_id); + int calc_partition_id_with_rowid(ObProxyRelationExpr *relation, + opsql::ObExprResolverContext &ctx, + common::ObIAllocator &allocator, + opsql::ObExprResolverResult &resolve_result, + int64_t &partition_id); + int calc_partition_id_with_rowid_str(const char *str, + const int64_t str_len, + common::ObIAllocator &allocator, + opsql::ObExprResolverResult &resolve_result, + ObProxyPartInfo &part_info, + int64_t &partition_id); }; class ObExprCalcTool { @@ -109,6 +123,9 @@ public: static int build_tz_info(ObClientSessionInfo *session_info, common::ObObjType obj_type, common::ObTimeZoneInfo &tz_info); + + static int build_tz_info_for_all_type(ObClientSessionInfo *session_info, + common::ObTimeZoneInfo &tz_info); static int build_dtc_params(ObClientSessionInfo *session_info, common::ObObjType obj_type, common::ObDataTypeCastParams &dtc_params); diff --git a/src/obproxy/proxy/route/obproxy_part_info.cpp b/src/obproxy/proxy/route/obproxy_part_info.cpp index 3f2686f7551ff6d716e0d6ec6ffb53b05bcb9826..d5621c04e0a6aa1f70f8af933c2caabfb0a02f01 100644 --- a/src/obproxy/proxy/route/obproxy_part_info.cpp +++ b/src/obproxy/proxy/route/obproxy_part_info.cpp @@ -41,6 +41,7 @@ ObProxyPartInfo::ObProxyPartInfo() : is_oracle_mode_(false) , sub_part_option_() , part_key_info_() , part_mgr_(allocator_) + , cluster_version_() { } @@ -93,6 +94,7 @@ int ObProxyPartInfo::alloc(ObProxyPartInfo *&part_info) void ObProxyPartInfo::free() { + part_mgr_.destroy(); allocator_.reset(); op_fixed_mem_free(this, sizeof(ObProxyPartInfo)); } diff --git a/src/obproxy/proxy/route/obproxy_part_info.h b/src/obproxy/proxy/route/obproxy_part_info.h index 44b8b3f2c1ddfd8b5510017cb562eea2bbd5f90b..2f2a0bbee0511cd323e3712622a9b531ba24c9bd 100644 --- a/src/obproxy/proxy/route/obproxy_part_info.h +++ b/src/obproxy/proxy/route/obproxy_part_info.h @@ -30,10 +30,10 @@ class ObProxyPartOption public: ObProxyPartOption(); ~ObProxyPartOption() {} - bool is_range_part() const; - bool is_hash_part() const; - bool is_key_part() const; - bool is_list_part() const; + bool is_range_part(const int64_t cluster_version) const; + bool is_hash_part(const int64_t cluster_version) const; + bool is_key_part(const int64_t cluster_version) const; + bool is_list_part(const int64_t cluster_version) const; int64_t to_string(char *buf, const int64_t buf_len) const; @@ -68,6 +68,8 @@ public: share::schema::ObPartitionLevel get_part_level() const { return part_level_; } common::ObCollationType get_table_cs_type() const { return table_cs_type_; } + common::ObIArray &get_part_columns() { return part_columns_; } + common::ObIArray &get_sub_part_columns() { return sub_part_columns_; } ObProxyPartOption &get_first_part_option() { return first_part_option_; } ObProxyPartOption &get_sub_part_option() { return sub_part_option_; } ObProxyPartMgr &get_part_mgr() { return part_mgr_; } @@ -76,6 +78,8 @@ public: void set_part_level(const share::schema::ObPartitionLevel level) { part_level_ = level; } void set_table_cs_type(const common::ObCollationType cs_type) { table_cs_type_ = cs_type; } + int64_t get_cluster_version() const { return cluster_version_; } + void set_cluster_version(const int64_t cluster_version) { cluster_version_ = cluster_version; } int64_t to_string(char *buf, const int64_t buf_len) const; @@ -89,31 +93,35 @@ private: share::schema::ObPartitionLevel part_level_; common::ObCollationType table_cs_type_; + common::ObSEArray part_columns_; + common::ObSEArray sub_part_columns_; + common::ObArenaAllocator allocator_; ObProxyPartOption first_part_option_; ObProxyPartOption sub_part_option_; ObProxyPartKeyInfo part_key_info_; ObProxyPartMgr part_mgr_; + int64_t cluster_version_; }; -inline bool ObProxyPartOption::is_range_part() const +inline bool ObProxyPartOption::is_range_part(const int64_t cluster_version) const { - return share::schema::is_range_part(part_func_type_); + return share::schema::is_range_part(part_func_type_, cluster_version); } -inline bool ObProxyPartOption::is_hash_part() const +inline bool ObProxyPartOption::is_hash_part(const int64_t cluster_version) const { - return share::schema::is_hash_part(part_func_type_); + return share::schema::is_hash_part(part_func_type_, cluster_version); } -inline bool ObProxyPartOption::is_key_part() const +inline bool ObProxyPartOption::is_key_part(const int64_t cluster_version) const { - return share::schema::is_key_part(part_func_type_); + return share::schema::is_key_part(part_func_type_, cluster_version); } -inline bool ObProxyPartOption::is_list_part() const +inline bool ObProxyPartOption::is_list_part(const int64_t cluster_version) const { - return share::schema::is_list_part(part_func_type_); + return share::schema::is_list_part(part_func_type_, cluster_version); } } // namespace proxy diff --git a/src/obproxy/proxy/route/obproxy_part_mgr.cpp b/src/obproxy/proxy/route/obproxy_part_mgr.cpp index 8365c653bfae2de59df0a567c5edb54028f6b7b6..a61883049eed40febb6aa92f666518dd4b67f364 100644 --- a/src/obproxy/proxy/route/obproxy_part_mgr.cpp +++ b/src/obproxy/proxy/route/obproxy_part_mgr.cpp @@ -17,7 +17,11 @@ #include "share/part/ob_part_desc_key.h" #include "share/part/ob_part_desc_range.h" #include "share/part/ob_part_desc_list.h" +#include "share/part/ob_part_mgr_util.h" #include "proxy/mysqllib/ob_resultset_fetcher.h" +#include "utils/ob_proxy_utils.h" +#include "proxy/route/obproxy_expr_calculator.h" +#include "proxy/route/ob_server_route.h" using namespace oceanbase::common; using namespace oceanbase::share::schema; @@ -27,64 +31,114 @@ namespace obproxy { namespace proxy { -int64_t ObPartNameIdPair::to_string(char *buf, const int64_t buf_len) const -{ - int64_t pos = 0; - J_OBJ_START(); - J_KV(K_(part_name), K_(part_id)); - J_OBJ_END(); - return pos; -} ObProxyPartMgr::ObProxyPartMgr(ObIAllocator &allocator) : first_part_desc_(NULL) , sub_part_desc_(NULL) , first_part_num_(0) , sub_part_num_(NULL) - , part_pair_array_(NULL) + , all_first_part_name_buf_(NULL) + , all_sub_part_name_buf_(NULL) + , all_first_part_name_length_(0) + , all_sub_part_name_length_(0) + , first_part_name_id_map_() + , sub_part_name_id_map_() , allocator_(allocator) + , cluster_version_(0) { } +void ObProxyPartMgr::destroy() +{ + if(first_part_name_id_map_.created()) { + first_part_name_id_map_.destroy(); + } + if(sub_part_name_id_map_.created()) { + sub_part_name_id_map_.destroy(); + } +} int ObProxyPartMgr::get_part_with_part_name(const ObString &part_name, - int64_t &part_id) + int64_t &part_id, + ObProxyPartInfo &part_info, + ObServerRoute &route, + ObProxyExprCalculator &expr_calculator) { int ret = OB_SUCCESS; - if (NULL != part_pair_array_&& first_part_num_ > 0) { - bool found = false; - for (int64_t i = 0; !found && i < first_part_num_; ++i) { - if (part_pair_array_[i].get_part_name().case_compare(part_name) == 0) { - part_id = part_pair_array_[i].get_part_id(); - found = true; + if ( part_name.length() <= 0 || part_name.length() > MAX_PART_NAME_LENGTH) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("error part name", K(part_name)); + } else { + ObPartitionLevel part_level = part_info.get_part_level(); + ObString store_part_name; + int64_t * part_id_ptr = NULL; + PART_NAME_BUF tmp_buf;//64 byte stack buf + store_part_name.assign_ptr((char *)&tmp_buf, part_name.length()); + MEMCPY(store_part_name.ptr(), part_name.ptr(), store_part_name.length()); + string_to_upper_case(store_part_name.ptr(), store_part_name.length()); + if ((sub_part_name_id_map_.created()) && OB_NOT_NULL(part_id_ptr = (int64_t *)sub_part_name_id_map_.get(store_part_name))) { + //find sub part name, get ptr->(physical part id) + part_id = *part_id_ptr; + LOG_DEBUG("succ to get part id by sub part name", K(part_id), K(part_name)); + } else if ((first_part_name_id_map_.created()) && OB_NOT_NULL(part_id_ptr = (int64_t *)first_part_name_id_map_.get(store_part_name))) { + //find first part name, get ptr->(first part id) + LOG_DEBUG("succ to get part id by first part name", K(*part_id_ptr), K(part_name)); + if(OB_LIKELY(PARTITION_LEVEL_ONE == part_level)) { + part_id = *part_id_ptr; + } else if((PARTITION_LEVEL_TWO == part_level) + && !obutils::get_global_proxy_config().enable_primary_zone + && !obutils::get_global_proxy_config().enable_cached_server) { + int64_t first_part_id = *part_id_ptr; + int64_t sub_part_id = OB_INVALID_INDEX; + if(OB_FAIL(expr_calculator.calc_part_id_by_random_choose_from_exist(part_info, first_part_id, sub_part_id, part_id))) { + LOG_DEBUG("fail to get random part id by first part name", K(first_part_id), K(part_id), K(part_name)); + } else { + // get part id by random, no need update pl + route.no_need_pl_update_ = true; + LOG_DEBUG("succ to get random part id by first part name", K(first_part_id), K(sub_part_id), K(part_id)); + } + } else { + //do nothing } } - if (found) { - LOG_DEBUG("succ to get part id with part name", K(part_id), K(part_name)); - } } return ret; } -int ObProxyPartMgr::get_first_part_id_by_idx(const int64_t idx, int64_t &part_id) +int ObProxyPartMgr::get_first_part_id_by_random(const int64_t rand_num, + int64_t &first_part_id, + int64_t &tablet_id) { int ret = OB_SUCCESS; - if (idx < 0 || idx >= first_part_num_ || OB_ISNULL(part_pair_array_)) { + ObSEArray part_ids; + ObSEArray tablet_ids; + if (OB_ISNULL(first_part_desc_)) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("fail to get part id by idx", K(ret), K(idx), K(first_part_num_), K(part_pair_array_)); + LOG_WARN("fail to get first part, null ptr", K(ret)); } else { - part_id = part_pair_array_[idx].get_part_id(); + if (OB_FAIL(first_part_desc_->get_part_by_num(rand_num, part_ids, tablet_ids))) { + LOG_WARN("fail to get first part by random", K(first_part_desc_), K(ret)); + } else { + if (part_ids.count() >= 1) { + first_part_id = part_ids[0]; + } + if (tablet_ids.count() >= 1) { + tablet_id = tablet_ids[0]; + } + } } + return ret; } int ObProxyPartMgr::get_first_part(ObNewRange &range, ObIAllocator &allocator, ObIArray &part_ids, - ObPartDescCtx &ctx) + ObPartDescCtx &ctx, + ObIArray &tablet_ids) { int ret = OB_SUCCESS; if (OB_NOT_NULL(first_part_desc_)) { - ret = first_part_desc_->get_part(range, allocator, part_ids, ctx); + ret = first_part_desc_->get_part(range, allocator, part_ids, ctx, tablet_ids); } else { ret = OB_INVALID_ARGUMENT; } @@ -97,19 +151,20 @@ int ObProxyPartMgr::get_first_part(ObNewRange &range, int ObProxyPartMgr::get_sub_part_desc_by_first_part_id(const bool is_template_table, const int64_t first_part_id, - ObPartDesc *&sub_part_desc_ptr) + ObPartDesc *&sub_part_desc_ptr, + const int64_t cluster_version) { int ret = OB_SUCCESS; if (OB_LIKELY(is_sub_part_valid())) { ObPartDesc *sub_part_desc_tmp = NULL; - - if (is_template_table) { + + if (is_template_table && IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { sub_part_desc_tmp = sub_part_desc_; } else { const ObPartitionFuncType sub_part_func_type = sub_part_desc_->get_part_func_type(); for (int64_t i = 0; i < first_part_num_; ++i) { - if (is_range_part(sub_part_func_type)) { + if (is_range_part(sub_part_func_type, cluster_version)) { ObPartDescRange *desc_range = (((ObPartDescRange*)sub_part_desc_) + i); RangePartition *part_array = desc_range->get_part_array(); // use first sub partition of everty first partition to get firt partition id @@ -117,7 +172,7 @@ int ObProxyPartMgr::get_sub_part_desc_by_first_part_id(const bool is_template_ta sub_part_desc_tmp = desc_range; break; } - } else if (is_list_part(sub_part_func_type)) { + } else if (is_list_part(sub_part_func_type, cluster_version)) { ObPartDescList *desc_list = (((ObPartDescList*)sub_part_desc_) + i); ListPartition *part_array = desc_list->get_part_array(); // use first sub partition of everty first partition to get firt partition id @@ -125,13 +180,13 @@ int ObProxyPartMgr::get_sub_part_desc_by_first_part_id(const bool is_template_ta sub_part_desc_tmp = desc_list; break; } - } else if (is_hash_part(sub_part_func_type)) { + } else if (is_hash_part(sub_part_func_type, cluster_version)) { ObPartDescHash *desc_hash = (((ObPartDescHash*)sub_part_desc_) + i); if (first_part_id == desc_hash->get_first_part_id()) { sub_part_desc_tmp = desc_hash; break; } - } else if (is_key_part(sub_part_func_type)) { + } else if (is_key_part(sub_part_func_type, cluster_version)) { ObPartDescKey *desc_key = (((ObPartDescKey*)sub_part_desc_) + i); if (first_part_id == desc_key->get_first_part_id()) { sub_part_desc_tmp = desc_key; @@ -153,45 +208,47 @@ int ObProxyPartMgr::get_sub_part_desc_by_first_part_id(const bool is_template_ta ret = OB_INVALID_ARGUMENT; LOG_WARN("fail to get sub part desc by first part id", K(ret)); } - + return ret; -} +} int ObProxyPartMgr::get_sub_part(ObNewRange &range, ObIAllocator &allocator, ObPartDesc *sub_part_desc_ptr, ObIArray &part_ids, - ObPartDescCtx &ctx) + ObPartDescCtx &ctx, + ObIArray &tablet_ids) { int ret = OB_SUCCESS; - + if (OB_ISNULL(sub_part_desc_ptr)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("fail to get sub part, null ptr", K(ret)); } else { - if (OB_FAIL(sub_part_desc_ptr->get_part(range, allocator, part_ids, ctx))) { + if (OB_FAIL(sub_part_desc_ptr->get_part(range, allocator, part_ids, ctx, tablet_ids))) { LOG_WARN("fail to get sub part", K(sub_part_desc_ptr), K(ret)); } } - + return ret; } -int ObProxyPartMgr::get_sub_part_by_random(const int64_t rand_num, +int ObProxyPartMgr::get_sub_part_by_random(const int64_t rand_num, ObPartDesc *sub_part_desc_ptr, - ObIArray &part_ids) + ObIArray &part_ids, + ObIArray &tablet_ids) { int ret = OB_SUCCESS; - + if (OB_ISNULL(sub_part_desc_ptr)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("fail to get sub part, null ptr", K(ret)); } else { - if (OB_FAIL(sub_part_desc_ptr->get_part_by_num(rand_num, part_ids))) { + if (OB_FAIL(sub_part_desc_ptr->get_part_by_num(rand_num, part_ids, tablet_ids))) { LOG_WARN("fail to get sub part by random", K(sub_part_desc_ptr), K(ret)); } } - + return ret; } @@ -200,96 +257,174 @@ int ObProxyPartMgr::build_hash_part(const bool is_oracle_mode, const ObPartitionFuncType part_func_type, const int64_t part_num, const int64_t part_space, + const int64_t part_col_num, const bool is_template_table, const ObProxyPartKeyInfo &key_info, - ObResultSetFetcher *rs_fetcher /*NULL*/) + ObResultSetFetcher *rs_fetcher /*NULL*/, + const int64_t cluster_version) { int ret = OB_SUCCESS; void *tmp_buf = NULL; ObPartDescHash *desc_hash = NULL; - int64_t part_id = -1; - ObString part_name; + PART_NAME_BUF *name_buf = NULL; + int64_t *name_len_buf = NULL; + int64_t *part_id_buf = NULL; int64_t sub_part_num = 0; + ObString part_name; + int64_t *part_array = NULL; - if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObPartDescHash)))) { + // After observer v4.0, there is no concept of template partition + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version) && PARTITION_LEVEL_TWO == part_level) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("cluster version bigger than 4 and level is two", K(ret), K(cluster_version)); + } else if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObPartDescHash)))) { ret = OB_REACH_MEMORY_LIMIT; LOG_WARN("part mgr reach memory limit", K(ret)); } else if (OB_ISNULL(desc_hash = new (tmp_buf) ObPartDescHash())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("part mgr reach memory limit", K(ret)); + } else if (OB_FAIL(alloc_name_buf(name_buf, name_len_buf, part_id_buf, part_num))) { + LOG_WARN("fail to alloc name buf", K(ret)); + } else if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version) && OB_ISNULL(desc_hash->tablet_id_array_ = (int64_t*)allocator_.alloc(sizeof(int64_t) * part_num))) { + ret = OB_REACH_MEMORY_LIMIT; + LOG_WARN("part mgr reach memory limit, alloc tablet id array failed", K(ret), K(part_num)); + } else if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version) && OB_ISNULL(part_array = (int64_t*)allocator_.alloc(sizeof(int64_t) * part_num))) { + ret = OB_REACH_MEMORY_LIMIT; + LOG_WARN("part mgr reach memory limit, alloc part array failed", K(ret), K(part_num)); } else { - if (NULL != rs_fetcher && PARTITION_LEVEL_ONE == part_level) { - first_part_num_ = part_num; - if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObPartNameIdPair) * part_num))) { - ret = OB_REACH_MEMORY_LIMIT; - LOG_WARN("part mgr reach memory limit", K(ret)); - } else if (OB_ISNULL(part_pair_array_ = new (tmp_buf) ObPartNameIdPair[part_num])) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("failed to do placement new", K(tmp_buf), K(part_num), K(ret)); - } else if (!is_template_table && OB_ISNULL(sub_part_num_ = (int64_t *)allocator_.alloc(sizeof(int64_t) * part_num))) { - ret = OB_REACH_MEMORY_LIMIT; - LOG_WARN("part mgr reach memory limit", K(ret)); - } - for (int64_t i = 0; i < part_num && OB_SUCC(ret); ++i) { - if (OB_FAIL(rs_fetcher->next())) { - LOG_DEBUG("failed to get next rs_fetcher", K(ret)); - } else { - PROXY_EXTRACT_INT_FIELD_MYSQL(*rs_fetcher, "part_id", part_id, int64_t); - PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(*rs_fetcher, "part_name", part_name); - part_pair_array_[i].set_part_id(part_id); - if (OB_FAIL(part_pair_array_[i].set_part_name(part_name))) { - LOG_WARN("fail to set part name", K(part_name), K(ret)); - } else if (!is_template_table) { - PROXY_EXTRACT_INT_FIELD_MYSQL(*rs_fetcher, "sub_part_num", sub_part_num, int64_t); - sub_part_num_[i] = sub_part_num; + if (NULL != rs_fetcher) { + if (PARTITION_LEVEL_ONE == part_level) { + first_part_num_ = part_num; + if (!is_template_table && OB_ISNULL(sub_part_num_ = (int64_t *)allocator_.alloc(sizeof(int64_t) * part_num))) { + ret = OB_REACH_MEMORY_LIMIT; + LOG_WARN("part mgr reach memory limit", K(ret)); + } + for (int64_t i = 0; i < part_num && OB_SUCC(ret); ++i) { + if (OB_FAIL(rs_fetcher->next())) { + LOG_DEBUG("fail to get next rs_fetcher", K(ret)); + } else { + PROXY_EXTRACT_INT_FIELD_MYSQL(*rs_fetcher, "part_id", part_id_buf[i], int64_t); + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(*rs_fetcher, "part_name", part_name); + + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + int64_t tablet_id = -1; + part_array[i] = part_id_buf[i]; + PROXY_EXTRACT_INT_FIELD_MYSQL(*rs_fetcher, "tablet_id", tablet_id, int64_t); + desc_hash->tablet_id_array_[i] = tablet_id; + if ((tablet_id != -1) && (tablet_id != 0)) { + part_id_buf[i] = tablet_id; + } + } + + if (part_name.length() <= MAX_PART_NAME_LENGTH) { + MEMCPY(name_buf[i], part_name.ptr(), part_name.length()); + name_len_buf[i] = part_name.length(); + all_first_part_name_length_ += part_name.length(); + } else {//treat too long name string as empty string + name_len_buf[i] = 0; + } + + if (!is_template_table) { + PROXY_EXTRACT_INT_FIELD_MYSQL(*rs_fetcher, "sub_part_num", sub_part_num, int64_t); + sub_part_num_[i] = sub_part_num; + } } + } // end for + if (OB_ITER_END == ret) { + LOG_DEBUG("empty first hash part info, maybe ob version < 2.1", K(ret)); + ret = OB_SUCCESS; } - } // end for - if (OB_ITER_END == ret) { - LOG_DEBUG("empty first hash part info, maybe ob version < 2.1", K(ret)); - ret = OB_SUCCESS; + } else if (PARTITION_LEVEL_TWO == part_level) { + for (int64_t i = 0; i < part_num && OB_SUCC(ret); ++i) {//part_num=sub part num + if (OB_FAIL(rs_fetcher->next())) { + LOG_DEBUG("fail to get next rs_fetcher", K(ret)); + } else { + PROXY_EXTRACT_INT_FIELD_MYSQL(*rs_fetcher, "sub_part_id", part_id_buf[i], int64_t); + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(*rs_fetcher, "part_name", part_name); + if (part_name.length() <= MAX_PART_NAME_LENGTH) { + MEMCPY(name_buf[i], part_name.ptr(), part_name.length()); + name_len_buf[i] = part_name.length(); + all_sub_part_name_length_ += part_name.length(); + } else {//treat too long name string as empty string + name_len_buf[i] = 0; + } + } + } // end for + } else { + //nothing } - } // end NULL != rs_fetcher && PARTITION_LEVEL_ONE == part_level + } // end NULL != rs_fetcher } if (OB_SUCC(ret)) { + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + desc_hash->set_part_array(part_array); + } desc_hash->set_oracle_mode(is_oracle_mode); desc_hash->set_part_space(part_space); desc_hash->set_part_num(part_num); desc_hash->set_part_level(part_level); desc_hash->set_part_func_type(part_func_type); - // find the first match key, should consider whether the key is both part one and part two? + for (int i = 0; i < part_col_num; i++) { + desc_hash->get_accuracies().push_back(ObAccuracy()); + desc_hash->get_obj_types().push_back(ObObjType()); + desc_hash->get_cs_types().push_back(ObCollationType()); + } + // find all keys in this level for (int i = 0; i < key_info.key_num_; ++i) { if (static_cast(key_info.part_keys_[i].level_) == part_level) { - desc_hash->set_part_key_type(static_cast(key_info.part_keys_[i].obj_type_)); - desc_hash->set_part_key_cs_type(static_cast(key_info.part_keys_[i].cs_type_)); - desc_hash->set_accuracy(key_info.part_keys_[i].accuracy_); - break; + ObAccuracy accuracy(key_info.part_keys_[i].accuracy_.valid_, + key_info.part_keys_[i].accuracy_.length_, + key_info.part_keys_[i].accuracy_.precision_, + key_info.part_keys_[i].accuracy_.scale_); + desc_hash->get_accuracies().at(key_info.part_keys_[i].idx_in_part_columns_) = accuracy; + desc_hash->get_obj_types().at(key_info.part_keys_[i].idx_in_part_columns_) = static_cast(key_info.part_keys_[i].obj_type_); + desc_hash->get_cs_types().at(key_info.part_keys_[i].idx_in_part_columns_) = static_cast(key_info.part_keys_[i].cs_type_); } } + if (PARTITION_LEVEL_ONE == part_level) { first_part_desc_ = desc_hash; + if (OB_FAIL(init_first_part_map())) { + LOG_DEBUG("fail to create first part name id map", K(ret)); + } else if (OB_FAIL(build_part_name_id_map(name_buf, name_len_buf, part_id_buf, all_first_part_name_buf_, all_first_part_name_length_, part_num, first_part_name_id_map_))) { + LOG_DEBUG("fail to build first part name id map", K(ret)); + } } else if (PARTITION_LEVEL_TWO == part_level) { sub_part_desc_ = desc_hash; + if (OB_FAIL(init_sub_part_map())) { + LOG_DEBUG("fail to create temp sub part name id map", K(ret)); + } else if (OB_FAIL(build_temp_sub_part_name_id_map(name_buf, name_len_buf, part_id_buf, part_num))) { + LOG_DEBUG("fail to build temp sub part name id map", K(ret)); + } } else { ret = OB_INVALID_ARGUMENT; LOG_WARN("part level invalid", K(part_level), K(ret)); } } + + free_name_buf(name_buf, name_len_buf, part_id_buf); return ret; } int ObProxyPartMgr::build_sub_hash_part_with_non_template(const bool is_oracle_mode, const ObPartitionFuncType part_func_type, const int64_t part_space, + const int64_t part_col_num, const ObProxyPartKeyInfo &key_info, - ObResultSetFetcher &rs_fetcher) + ObResultSetFetcher &rs_fetcher, + const int64_t cluster_version) { int ret = OB_SUCCESS; void *tmp_buf = NULL; ObPartDescHash *desc_hash = NULL; common::ObPartDesc *sub_part_desc = NULL; - int64_t part_id = -1; + PART_NAME_BUF *name_buf = NULL; + int64_t *name_len_buf = NULL; + int64_t *part_id_buf = NULL; + int64_t first_part_id = -1; + int64_t sub_part_id = -1; + ObString sub_part_name; // alloc desc_range if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObPartDescHash) * first_part_num_))) { @@ -297,34 +432,66 @@ int ObProxyPartMgr::build_sub_hash_part_with_non_template(const bool is_oracle_m LOG_WARN("part mgr reach memory limit", K(ret)); } else if (OB_ISNULL(sub_part_desc = new (tmp_buf) ObPartDescHash[first_part_num_])) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("failed to do placement new", K(tmp_buf), K(ret)); + LOG_WARN("fail to do placement new", K(tmp_buf), K(ret)); + } else if (OB_FAIL(alloc_name_buf(name_buf, name_len_buf, part_id_buf, all_sub_part_num_))) { + LOG_WARN("fail to alloc name buf", K(ret)); } + int64_t index=0; for (int64_t i = 0; i < first_part_num_ && OB_SUCC(ret); ++i) { desc_hash = (((ObPartDescHash *)sub_part_desc) + i); + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version) && OB_ISNULL(desc_hash->tablet_id_array_ = (int64_t*)allocator_.alloc(sizeof(int64_t) * sub_part_num_[i]))) { + ret = OB_REACH_MEMORY_LIMIT; + LOG_WARN("allocator alloc tablet id array failed", K(ret), K(sub_part_num_[i])); + } for (int64_t j = 0; j < sub_part_num_[i] && OB_SUCC(ret); ++j) { - if (OB_FAIL(rs_fetcher.next())) { - LOG_WARN("failed to get next rs_fetcher", K(ret)); + if (OB_FAIL(rs_fetcher.next()) || index >= all_sub_part_num_) { + LOG_WARN("fail to get next rs_fetcher", K(ret)); } else { - PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_id", part_id, int64_t); + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_id", first_part_id, int64_t); + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "sub_part_id", sub_part_id, int64_t); + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "part_name", sub_part_name); + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "tablet_id", desc_hash->tablet_id_array_[j], int64_t); + } + if (sub_part_name.length() <= MAX_PART_NAME_LENGTH) { + MEMCPY(name_buf[index], sub_part_name.ptr(), sub_part_name.length()); + name_len_buf[index] = sub_part_name.length(); + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + part_id_buf[index] = desc_hash->tablet_id_array_[j]; + } else { + part_id_buf[index] = generate_phy_part_id(first_part_id, sub_part_id); + } + all_sub_part_name_length_ += sub_part_name.length(); + } else {//treat too long name string as empty string + name_len_buf[index] = 0; + } + ++index; } } - if (OB_SUCC(ret)) { desc_hash->set_oracle_mode(is_oracle_mode); - desc_hash->set_first_part_id(part_id); + desc_hash->set_first_part_id(first_part_id); desc_hash->set_part_space(part_space); desc_hash->set_part_num(sub_part_num_[i]); desc_hash->set_part_level(PARTITION_LEVEL_TWO); desc_hash->set_part_func_type(part_func_type); - // find the first match key, should consider whether the key is both part one and part two? + for (int i = 0; i < part_col_num; i++) { + desc_hash->get_accuracies().push_back(ObAccuracy()); + desc_hash->get_obj_types().push_back(ObObjType()); + desc_hash->get_cs_types().push_back(ObCollationType()); + } + // find all keys in this level for (int i = 0; i < key_info.key_num_; ++i) { if (static_cast(key_info.part_keys_[i].level_) == PARTITION_LEVEL_TWO) { - desc_hash->set_part_key_type(static_cast(key_info.part_keys_[i].obj_type_)); - desc_hash->set_part_key_cs_type(static_cast(key_info.part_keys_[i].cs_type_)); - desc_hash->set_accuracy(key_info.part_keys_[i].accuracy_); - break; + ObAccuracy accuracy(key_info.part_keys_[i].accuracy_.valid_, + key_info.part_keys_[i].accuracy_.length_, + key_info.part_keys_[i].accuracy_.precision_, + key_info.part_keys_[i].accuracy_.scale_); + desc_hash->get_accuracies().at(key_info.part_keys_[i].idx_in_part_columns_) = accuracy; + desc_hash->get_obj_types().at(key_info.part_keys_[i].idx_in_part_columns_) = static_cast(key_info.part_keys_[i].obj_type_); + desc_hash->get_cs_types().at(key_info.part_keys_[i].idx_in_part_columns_) = static_cast(key_info.part_keys_[i].cs_type_); } } } @@ -332,8 +499,14 @@ int ObProxyPartMgr::build_sub_hash_part_with_non_template(const bool is_oracle_m if (OB_SUCC(ret)) { sub_part_desc_ = sub_part_desc; + if (OB_FAIL(init_sub_part_map())) { + LOG_DEBUG("fail to create non temp sub part name id map", K(ret)); + } else if (OB_FAIL(build_part_name_id_map(name_buf, name_len_buf, part_id_buf, all_sub_part_name_buf_, all_sub_part_name_length_, all_sub_part_num_, sub_part_name_id_map_))) { + LOG_DEBUG("fail to build non temp sub part name id map", K(ret)); + } } + free_name_buf(name_buf, name_len_buf, part_id_buf); return ret; } @@ -341,93 +514,170 @@ int ObProxyPartMgr::build_key_part(const ObPartitionLevel part_level, const ObPartitionFuncType part_func_type, const int64_t part_num, const int64_t part_space, + const int64_t part_col_num, const bool is_template_table, const ObProxyPartKeyInfo &key_info, - ObResultSetFetcher *rs_fetcher /*NULL*/) + ObResultSetFetcher *rs_fetcher /*NULL*/, + const int64_t cluster_version) { int ret = OB_SUCCESS; void *tmp_buf = NULL; ObPartDescKey *desc_key = NULL; - int64_t part_id = -1; - ObString part_name; + PART_NAME_BUF *name_buf = NULL; + int64_t *name_len_buf = NULL; + int64_t *part_id_buf = NULL; int64_t sub_part_num = 0; + ObString part_name; + int64_t *part_array = NULL; - if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObPartDescKey)))) { + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version) && PARTITION_LEVEL_TWO == part_level) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("cluster version is bigger than 4 and level is two", K(ret), K(cluster_version)); + } else if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObPartDescKey)))) { ret = OB_REACH_MEMORY_LIMIT; LOG_WARN("part mgr reach memory limit", K(ret)); } else if (OB_ISNULL(desc_key = new (tmp_buf) ObPartDescKey())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("part mgr reach memory limit", K(ret)); + } else if (OB_FAIL(alloc_name_buf(name_buf, name_len_buf, part_id_buf, part_num))) { + LOG_WARN("fail to alloc name buf", K(ret)); + } else if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version) && OB_ISNULL(desc_key->tablet_id_array_ = (int64_t*)allocator_.alloc(sizeof(int64_t) * part_num))) { + ret = OB_REACH_MEMORY_LIMIT; + LOG_WARN("part mgr reach memory limit", K(ret), K(part_num)); + } else if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version) && OB_ISNULL(part_array = (int64_t*)allocator_.alloc(sizeof(int64_t) * part_num))) { + ret = OB_REACH_MEMORY_LIMIT; + LOG_WARN("fail to alloc part array", K(ret), K(part_num)); } else { - if (NULL != rs_fetcher && PARTITION_LEVEL_ONE == part_level) { - first_part_num_ = part_num; - if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObPartNameIdPair) * part_num))) { - ret = OB_REACH_MEMORY_LIMIT; - LOG_WARN("part mgr reach memory limit", K(ret)); - } else if (OB_ISNULL(part_pair_array_ = new (tmp_buf) ObPartNameIdPair[part_num])) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("failed to do placement new", K(tmp_buf), K(part_num), K(ret)); - } else if (!is_template_table && OB_ISNULL(sub_part_num_ = (int64_t *)allocator_.alloc(sizeof(int64_t) * part_num))) { - ret = OB_REACH_MEMORY_LIMIT; - LOG_WARN("part mgr reach memory limit", K(ret)); - } - for (int64_t i = 0; i < part_num && OB_SUCC(ret); ++i) { - if (OB_FAIL(rs_fetcher->next())) { - LOG_DEBUG("failed to get next rs_fetcher", K(ret)); - } else { - PROXY_EXTRACT_INT_FIELD_MYSQL(*rs_fetcher, "part_id", part_id, int64_t); - PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(*rs_fetcher, "part_name", part_name); - part_pair_array_[i].set_part_id(part_id); - if (OB_FAIL(part_pair_array_[i].set_part_name(part_name))) { - LOG_WARN("fail to set part name", K(part_name), K(ret)); - } else if (!is_template_table) { - PROXY_EXTRACT_INT_FIELD_MYSQL(*rs_fetcher, "sub_part_num", sub_part_num, int64_t); - sub_part_num_[i] = sub_part_num; + if (NULL != rs_fetcher) { + if (PARTITION_LEVEL_ONE == part_level) { + first_part_num_ = part_num; + if (!is_template_table && OB_ISNULL(sub_part_num_ = (int64_t *)allocator_.alloc(sizeof(int64_t) * part_num))) { + ret = OB_REACH_MEMORY_LIMIT; + LOG_WARN("part mgr reach memory limit", K(ret)); + } + for (int64_t i = 0; i < part_num && OB_SUCC(ret); ++i) { + if (OB_FAIL(rs_fetcher->next())) { + LOG_DEBUG("fail to get next rs_fetcher", K(ret)); + } else { + PROXY_EXTRACT_INT_FIELD_MYSQL(*rs_fetcher, "part_id", part_id_buf[i], int64_t); + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(*rs_fetcher, "part_name", part_name); + + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + int64_t tablet_id = -1; + part_array[i] = part_id_buf[i]; + PROXY_EXTRACT_INT_FIELD_MYSQL(*rs_fetcher, "tablet_id", tablet_id, int64_t); + desc_key->tablet_id_array_[i] = tablet_id; + if ((tablet_id != -1) && (tablet_id != 0)) { + part_id_buf[i] = tablet_id; + } + } + + if (part_name.length() <= MAX_PART_NAME_LENGTH) { + MEMCPY(name_buf[i], part_name.ptr(), part_name.length()); + name_len_buf[i] = part_name.length(); + all_first_part_name_length_ += part_name.length(); + } else {//treat too long name string as empty string + name_len_buf[i] = 0; + } + + if (!is_template_table) { + PROXY_EXTRACT_INT_FIELD_MYSQL(*rs_fetcher, "sub_part_num", sub_part_num, int64_t); + sub_part_num_[i] = sub_part_num; + } } + } // end for + if (OB_ITER_END == ret) { + LOG_DEBUG("empty first key part info, maybe ob version < 2.1", K(ret)); + ret = OB_SUCCESS; } - } // end for - if (OB_ITER_END == ret) { - LOG_DEBUG("empty first key part info, maybe ob version < 2.1", K(ret)); - ret = OB_SUCCESS; + } else if (PARTITION_LEVEL_TWO == part_level) { + for (int64_t i = 0; i < part_num && OB_SUCC(ret); ++i) {//part_num=sub part num + if (OB_FAIL(rs_fetcher->next())) { + LOG_DEBUG("fail to get next rs_fetcher", K(ret)); + } else { + PROXY_EXTRACT_INT_FIELD_MYSQL(*rs_fetcher, "sub_part_id", part_id_buf[i], int64_t); + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(*rs_fetcher, "part_name", part_name); + if (part_name.length() <= MAX_PART_NAME_LENGTH) { + MEMCPY(name_buf[i], part_name.ptr(), part_name.length()); + name_len_buf[i] = part_name.length(); + all_sub_part_name_length_ += part_name.length(); + } else {//treat too long name string as empty string + name_len_buf[i] = 0; + } + } + } // end for + } else { + //nothing } - } // end NULL != rs_fetcher && PARTITION_LEVEL_ONE == part_level + } // end NULL != rs_fetcher } + if (OB_SUCC(ret)) { + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + desc_key->set_part_array(part_array); + } desc_key->set_part_space(part_space); desc_key->set_part_num(part_num); desc_key->set_part_level(part_level); desc_key->set_part_func_type(part_func_type); - // find the first match key, should consider whether the key is both part one and part two? + for (int i = 0; i < part_col_num; i++) { + desc_key->get_accuracies().push_back(ObAccuracy()); + desc_key->get_obj_types().push_back(ObObjType()); + desc_key->get_cs_types().push_back(ObCollationType()); + } + // find all keys in this level for (int i = 0; i < key_info.key_num_; ++i) { if (static_cast(key_info.part_keys_[i].level_) == part_level) { - desc_key->set_part_key_type(static_cast(key_info.part_keys_[i].obj_type_)); - desc_key->set_part_key_cs_type(static_cast(key_info.part_keys_[i].cs_type_)); - desc_key->set_accuracy(key_info.part_keys_[i].accuracy_); - break; + ObAccuracy accuracy(key_info.part_keys_[i].accuracy_.valid_, + key_info.part_keys_[i].accuracy_.length_, + key_info.part_keys_[i].accuracy_.precision_, + key_info.part_keys_[i].accuracy_.scale_); + desc_key->get_accuracies().at(key_info.part_keys_[i].idx_in_part_columns_) = accuracy; + desc_key->get_obj_types().at(key_info.part_keys_[i].idx_in_part_columns_) = static_cast(key_info.part_keys_[i].obj_type_); + desc_key->get_cs_types().at(key_info.part_keys_[i].idx_in_part_columns_) = static_cast(key_info.part_keys_[i].cs_type_); } } if (PARTITION_LEVEL_ONE == part_level) { first_part_desc_ = desc_key; + if (OB_FAIL(init_first_part_map())) { + LOG_DEBUG("fail to create first part name id map", K(ret)); + } else if (OB_FAIL(build_part_name_id_map(name_buf, name_len_buf, part_id_buf, all_first_part_name_buf_, all_first_part_name_length_, part_num, first_part_name_id_map_))) { + LOG_DEBUG("fail to build first part name id map", K(ret)); + } } else if (PARTITION_LEVEL_TWO == part_level) { sub_part_desc_ = desc_key; + if (OB_FAIL(init_sub_part_map())) { + LOG_DEBUG("fail to create temp sub part name id map", K(ret)); + } else if (OB_FAIL(build_temp_sub_part_name_id_map(name_buf, name_len_buf, part_id_buf, part_num))) { + LOG_DEBUG("fail to build temp sub part name id map", K(ret)); + } } else { ret = OB_INVALID_ARGUMENT; LOG_WARN("part level invalid", K(part_level), K(ret)); } } + + free_name_buf(name_buf, name_len_buf, part_id_buf); return ret; } int ObProxyPartMgr::build_sub_key_part_with_non_template(const ObPartitionFuncType part_func_type, const int64_t part_space, + const int64_t part_col_num, const ObProxyPartKeyInfo &key_info, - ObResultSetFetcher &rs_fetcher) + ObResultSetFetcher &rs_fetcher, + const int64_t cluster_version) { int ret = OB_SUCCESS; void *tmp_buf = NULL; ObPartDescKey *desc_key = NULL; common::ObPartDesc *sub_part_desc = NULL; - int64_t part_id = -1; + PART_NAME_BUF *name_buf = NULL; + int64_t *name_len_buf = NULL; + int64_t *part_id_buf = NULL; + int64_t first_part_id = -1; + int64_t sub_part_id = -1; + ObString sub_part_name; // alloc desc_range if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObPartDescKey) * first_part_num_))) { @@ -435,33 +685,66 @@ int ObProxyPartMgr::build_sub_key_part_with_non_template(const ObPartitionFuncTy LOG_WARN("part mgr reach memory limit", K(ret)); } else if (OB_ISNULL(sub_part_desc = new (tmp_buf) ObPartDescKey[first_part_num_])) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("failed to do placement new", K(tmp_buf), K(ret)); + LOG_WARN("fail to do placement new", K(tmp_buf), K(ret)); + } else if (OB_FAIL(alloc_name_buf(name_buf, name_len_buf, part_id_buf, all_sub_part_num_))) { + LOG_WARN("fail to alloc name buf", K(ret)); } + int64_t index=0; for (int64_t i = 0; i < first_part_num_ && OB_SUCC(ret); ++i) { desc_key = (((ObPartDescKey *)sub_part_desc) + i); + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version) && OB_ISNULL(desc_key->tablet_id_array_ = (int64_t*)allocator_.alloc(sizeof(int64_t) * sub_part_num_[i]))) { + ret = OB_REACH_MEMORY_LIMIT; + LOG_WARN("allocate tablet id array failed", K(ret), K(sub_part_num_[i])); + } for (int64_t j = 0; j < sub_part_num_[i] && OB_SUCC(ret); ++j) { - if (OB_FAIL(rs_fetcher.next())) { - LOG_WARN("failed to get next rs_fetcher", K(ret)); + if (OB_FAIL(rs_fetcher.next()) || index >= all_sub_part_num_) { + LOG_WARN("fail to get next rs_fetcher", K(ret)); } else { - PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_id", part_id, int64_t); + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_id", first_part_id, int64_t); + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "sub_part_id", sub_part_id, int64_t); + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "part_name", sub_part_name); + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "tablet_id", desc_key->tablet_id_array_[j], int64_t); + } + if (sub_part_name.length() <= MAX_PART_NAME_LENGTH) { + MEMCPY(name_buf[index], sub_part_name.ptr(), sub_part_name.length()); + name_len_buf[index] = sub_part_name.length(); + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + part_id_buf[index] = desc_key->tablet_id_array_[j]; + } else { + part_id_buf[index] = generate_phy_part_id(first_part_id, sub_part_id); + } + all_sub_part_name_length_ += sub_part_name.length(); + } else {//treat too long name string as empty string + name_len_buf[index] = 0; + } + ++index; } } if (OB_SUCC(ret)) { - desc_key->set_first_part_id(part_id); + desc_key->set_first_part_id(first_part_id); desc_key->set_part_space(part_space); desc_key->set_part_num(sub_part_num_[i]); desc_key->set_part_level(PARTITION_LEVEL_TWO); desc_key->set_part_func_type(part_func_type); - // find the first match key, should consider whether the key is both part one and part two? + for (int i = 0; i < part_col_num; i++) { + desc_key->get_accuracies().push_back(ObAccuracy()); + desc_key->get_obj_types().push_back(ObObjType()); + desc_key->get_cs_types().push_back(ObCollationType()); + } + // find all keys in this level for (int i = 0; i < key_info.key_num_; ++i) { if (static_cast(key_info.part_keys_[i].level_) == PARTITION_LEVEL_TWO) { - desc_key->set_part_key_type(static_cast(key_info.part_keys_[i].obj_type_)); - desc_key->set_part_key_cs_type(static_cast(key_info.part_keys_[i].cs_type_)); - desc_key->set_accuracy(key_info.part_keys_[i].accuracy_); - break; + ObAccuracy accuracy(key_info.part_keys_[i].accuracy_.valid_, + key_info.part_keys_[i].accuracy_.length_, + key_info.part_keys_[i].accuracy_.precision_, + key_info.part_keys_[i].accuracy_.scale_); + desc_key->get_accuracies().at(key_info.part_keys_[i].idx_in_part_columns_) = accuracy; + desc_key->get_obj_types().at(key_info.part_keys_[i].idx_in_part_columns_) = static_cast(key_info.part_keys_[i].obj_type_); + desc_key->get_cs_types().at(key_info.part_keys_[i].idx_in_part_columns_) = static_cast(key_info.part_keys_[i].cs_type_); } } } @@ -469,48 +752,61 @@ int ObProxyPartMgr::build_sub_key_part_with_non_template(const ObPartitionFuncTy if (OB_SUCC(ret)) { sub_part_desc_ = sub_part_desc; + if (OB_FAIL(init_sub_part_map())) { + LOG_DEBUG("fail to create non temp sub part name id map", K(ret)); + } else if (OB_FAIL(build_part_name_id_map(name_buf, name_len_buf, part_id_buf, all_sub_part_name_buf_, all_sub_part_name_length_, all_sub_part_num_, sub_part_name_id_map_))) { + LOG_DEBUG("fail to build non temp sub part name id map", K(ret)); + } } + free_name_buf(name_buf, name_len_buf, part_id_buf); return ret; } int ObProxyPartMgr::build_range_part(const ObPartitionLevel part_level, const ObPartitionFuncType part_func_type, const int64_t part_num, + const int64_t part_col_num, const bool is_template_table, const ObProxyPartKeyInfo &key_info, - ObResultSetFetcher &rs_fetcher) + ObResultSetFetcher &rs_fetcher, + const int64_t cluster_version) { int ret = OB_SUCCESS; void *tmp_buf = NULL; ObPartDescRange *desc_range = NULL; RangePartition *part_array = NULL; - ObString part_name; + PART_NAME_BUF *name_buf = NULL; + int64_t *name_len_buf = NULL; + int64_t *part_id_buf = NULL; int64_t sub_part_num = 0; + ObString part_name; + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version) && PARTITION_LEVEL_TWO == part_level) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("cluster version bigger than 4, level two has no tempalte", K(ret)); // alloc desc_range and part_array - if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObPartDescRange)))) { + } else if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObPartDescRange)))) { ret = OB_REACH_MEMORY_LIMIT; LOG_WARN("part mgr reach memory limit", K(ret)); } else if (OB_ISNULL(desc_range = new (tmp_buf) ObPartDescRange())) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("failed to do placement new", K(tmp_buf), K(ret)); + LOG_WARN("fail to do placement new", K(tmp_buf), K(ret)); + } else if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version) && OB_ISNULL(desc_range->tablet_id_array_ = (int64_t*)allocator_.alloc(sizeof(int64_t) * part_num))) { + ret = OB_REACH_MEMORY_LIMIT; + LOG_WARN("part mgr reach memory limit", K(ret)); } else if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(RangePartition) * part_num))) { ret = OB_REACH_MEMORY_LIMIT; LOG_WARN("part mgr reach memory limit", K(ret)); } else if (OB_ISNULL(part_array = new (tmp_buf) RangePartition[part_num])) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("failed to do placement new", K(tmp_buf), K(part_num), K(ret)); + LOG_WARN("fail to do placement new", K(tmp_buf), K(part_num), K(ret)); + } else if (OB_FAIL(alloc_name_buf(name_buf, name_len_buf, part_id_buf, part_num))) { + LOG_WARN("fail to alloc name buf", K(ret)); } else { if (PARTITION_LEVEL_ONE == part_level) { first_part_num_ = part_num; - if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObPartNameIdPair) * part_num))) { - ret = OB_REACH_MEMORY_LIMIT; - LOG_WARN("part mgr reach memory limit", K(ret)); - } else if (OB_ISNULL(part_pair_array_ = new (tmp_buf) ObPartNameIdPair[part_num])) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("failed to do placement new", K(tmp_buf), K(part_num), K(ret)); - } else if (!is_template_table && OB_ISNULL(sub_part_num_ = (int64_t *)allocator_.alloc(sizeof(int64_t) * part_num))) { + if (!is_template_table && OB_ISNULL(sub_part_num_ = (int64_t *)allocator_.alloc(sizeof(int64_t) * part_num))) { ret = OB_REACH_MEMORY_LIMIT; LOG_WARN("part mgr reach memory limit", K(ret)); } @@ -522,21 +818,42 @@ int ObProxyPartMgr::build_range_part(const ObPartitionLevel part_level, int64_t pos = 0; for (int64_t i = 0; i < part_num && OB_SUCC(ret); ++i) { if (OB_FAIL(rs_fetcher.next())) { - LOG_WARN("failed to get next rs_fetcher", K(ret)); + LOG_WARN("fail to get next rs_fetcher", K(ret)); } else { if (PARTITION_LEVEL_ONE == part_level) { PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_id", part_array[i].part_id_, int64_t); + part_id_buf[i] = part_array[i].part_id_; + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + int64_t tablet_id = -1; + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "tablet_id", tablet_id, int64_t); + desc_range->tablet_id_array_[i] = tablet_id; + if ((tablet_id != -1) && (tablet_id != 0)) { + part_id_buf[i] = tablet_id; + } + } PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "part_name", part_name); - - part_pair_array_[i].set_part_id(part_array[i].part_id_); - if (OB_FAIL(part_pair_array_[i].set_part_name(part_name))) { - LOG_WARN("fail to set part name", K(part_name), K(ret)); - } else if (!is_template_table) { + if (part_name.length() <= MAX_PART_NAME_LENGTH) { + MEMCPY(name_buf[i], part_name.ptr(), part_name.length()); + name_len_buf[i] = part_name.length(); + all_first_part_name_length_ += part_name.length(); + } else {//treat too long name string as empty string + name_len_buf[i] = 0; + } + if (!is_template_table) { PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "sub_part_num", sub_part_num, int64_t); sub_part_num_[i] = sub_part_num; } } else if (PARTITION_LEVEL_TWO == part_level) { - PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "sub_part_id", part_array[i].part_id_, int64_t); + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "sub_part_id", part_array[i].part_id_, int64_t);//sub_part_id + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "part_name", part_name); + part_id_buf[i] = part_array[i].part_id_; + if (part_name.length() <= MAX_PART_NAME_LENGTH) { + MEMCPY(name_buf[i], part_name.ptr(), part_name.length()); + name_len_buf[i] = part_name.length(); + all_sub_part_name_length_ += part_name.length(); + } else {//treat too long name string as empty string + name_len_buf[i] = 0; + } } else { ret = OB_INVALID_ARGUMENT; } @@ -544,10 +861,10 @@ int ObProxyPartMgr::build_range_part(const ObPartitionLevel part_level, pos = 0; if (OB_FAIL(ret)) { - LOG_WARN("failed to fetch result", K(ret)); + LOG_WARN("fail to fetch result", K(ret)); } else if (OB_FAIL(part_array[i].high_bound_val_.deserialize(allocator_, tmp_str.ptr(), tmp_str.length(), pos))) { - LOG_WARN("failed to deserialize", K(tmp_str), K(ret)); + LOG_WARN("fail to deserialize", K(tmp_str), K(ret)); } else { // do nothing } @@ -558,7 +875,7 @@ int ObProxyPartMgr::build_range_part(const ObPartitionLevel part_level, if (OB_SUCC(ret)) { if (OB_FAIL(desc_range->set_part_array(part_array, part_num))) { - LOG_WARN("failed to set_part_array, unexpected ", K(ret)); + LOG_WARN("fail to set_part_array, unexpected ", K(ret)); } } @@ -566,32 +883,57 @@ int ObProxyPartMgr::build_range_part(const ObPartitionLevel part_level, if (OB_SUCC(ret)) { desc_range->set_part_level(part_level); desc_range->set_part_func_type(part_func_type); - for (int k = 0; k < key_info.key_num_; ++k) { - if (static_cast(key_info.part_keys_[k].level_) == part_level) { - desc_range->set_accuracy(key_info.part_keys_[k].accuracy_); - break; + for (int i = 0; i < part_col_num; i++) { + desc_range->get_accuracies().push_back(ObAccuracy()); + } + // find all keys in this level + for (int i = 0; i < key_info.key_num_; ++i) { + if (static_cast(key_info.part_keys_[i].level_) == part_level) { + ObAccuracy accuracy(key_info.part_keys_[i].accuracy_.valid_, + key_info.part_keys_[i].accuracy_.length_, + key_info.part_keys_[i].accuracy_.precision_, + key_info.part_keys_[i].accuracy_.scale_); + desc_range->get_accuracies().at(key_info.part_keys_[i].idx_in_part_columns_) = accuracy; } } if (PARTITION_LEVEL_ONE == part_level) { first_part_desc_ = desc_range; + if (OB_FAIL(init_first_part_map())) { + LOG_DEBUG("fail to create first part name id map", K(ret)); + } else if (OB_FAIL(build_part_name_id_map(name_buf, name_len_buf, part_id_buf, all_first_part_name_buf_, all_first_part_name_length_, part_num, first_part_name_id_map_))) { + LOG_DEBUG("fail to build first part name id map", K(ret)); + } } else if (PARTITION_LEVEL_TWO == part_level) { sub_part_desc_ = desc_range; + if (OB_FAIL(init_sub_part_map())) { + LOG_DEBUG("fail to create temp sub part name id map", K(ret)); + } else if (OB_FAIL(build_temp_sub_part_name_id_map(name_buf, name_len_buf, part_id_buf, part_num))) { + LOG_DEBUG("fail to build temp sub part name id map", K(ret)); + } } else { ret = OB_INVALID_ARGUMENT; LOG_WARN("part level invalid", K(part_level), K(ret)); } } + + free_name_buf(name_buf, name_len_buf, part_id_buf); return ret; } int ObProxyPartMgr::build_sub_range_part_with_non_template(const ObPartitionFuncType part_func_type, + const int64_t part_col_num, const ObProxyPartKeyInfo &key_info, - ObResultSetFetcher &rs_fetcher) + ObResultSetFetcher &rs_fetcher, + const int64_t cluster_version) { int ret = OB_SUCCESS; void *tmp_buf = NULL; RangePartition *part_array = NULL; common::ObPartDesc *sub_part_desc = NULL; + PART_NAME_BUF *name_buf = NULL; + int64_t *name_len_buf = NULL; + int64_t *part_id_buf = NULL; + ObString sub_part_name; // alloc desc_range if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObPartDescRange) * first_part_num_))) { @@ -599,40 +941,62 @@ int ObProxyPartMgr::build_sub_range_part_with_non_template(const ObPartitionFunc LOG_WARN("part mgr reach memory limit", K(ret)); } else if (OB_ISNULL(sub_part_desc = new (tmp_buf) ObPartDescRange[first_part_num_])) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("failed to do placement new", K(tmp_buf), K(ret)); + LOG_WARN("fail to do placement new", K(tmp_buf), K(ret)); + } else if (OB_FAIL(alloc_name_buf(name_buf, name_len_buf, part_id_buf, all_sub_part_num_))) { + LOG_WARN("fail to alloc name buf", K(ret)); } - // build desc_range ObString tmp_str; + int64_t index = 0; int64_t pos = 0; ObPartDescRange *desc_range = NULL; for (int64_t i = 0; i < first_part_num_ && OB_SUCC(ret); ++i) { + desc_range = (((ObPartDescRange *)sub_part_desc) + i); tmp_buf = NULL; if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(RangePartition) * sub_part_num_[i]))) { ret = OB_REACH_MEMORY_LIMIT; LOG_WARN("part mgr reach memory limit", K(ret)); } else if (OB_ISNULL(part_array = new (tmp_buf) RangePartition[sub_part_num_[i]])) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("failed to do placement new", K(tmp_buf), "sub_part_index", i, + LOG_WARN("fail to do placement new", K(tmp_buf), "sub_part_index", i, "sub_part_num", sub_part_num_[i], K(ret)); - } else { - desc_range = (((ObPartDescRange *)sub_part_desc) + i); + } else if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version) && OB_ISNULL(desc_range->tablet_id_array_ = (int64_t*)allocator_.alloc(sizeof(int64_t) * sub_part_num_[i]))) { + ret = OB_REACH_MEMORY_LIMIT; + LOG_WARN("alloc tablet id array failed", K(ret), K(sub_part_num_[i])); } for (int64_t j = 0; j < sub_part_num_[i] && OB_SUCC(ret); ++j) { - if (OB_FAIL(rs_fetcher.next())) { - LOG_WARN("failed to get next rs_fetcher", K(ret)); + if (OB_FAIL(rs_fetcher.next()) || index >= all_sub_part_num_) { + LOG_WARN("fail to get next rs_fetcher", K(ret)); } else { PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_id", part_array[j].first_part_id_, int64_t); PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "sub_part_id", part_array[j].part_id_, int64_t); PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "high_bound_val_bin", tmp_str); + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "tablet_id", desc_range->tablet_id_array_[j], int64_t); + } + + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "part_name", sub_part_name); + if (sub_part_name.length() <= MAX_PART_NAME_LENGTH) { + MEMCPY(name_buf[index], sub_part_name.ptr(), sub_part_name.length()); + name_len_buf[index] = sub_part_name.length(); + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + part_id_buf[index] = desc_range->tablet_id_array_[j]; + } else { + part_id_buf[index] = generate_phy_part_id(part_array[j].first_part_id_, part_array[j].part_id_); + } + all_sub_part_name_length_ += sub_part_name.length(); + } else {//treat too long name string as empty string + name_len_buf[index] = 0; + } + ++index; pos = 0; if (OB_FAIL(ret)) { - LOG_WARN("failed to fetch result", K(ret)); + LOG_WARN("fail to fetch result", K(ret)); } else if (OB_FAIL(part_array[j].high_bound_val_.deserialize(allocator_, tmp_str.ptr(), tmp_str.length(), pos))) { - LOG_WARN("failed to deserialize", K(tmp_str), K(ret)); + LOG_WARN("fail to deserialize", K(tmp_str), K(ret)); } else { // do nothing } @@ -642,62 +1006,82 @@ int ObProxyPartMgr::build_sub_range_part_with_non_template(const ObPartitionFunc if (OB_SUCC(ret)) { desc_range->set_part_level(PARTITION_LEVEL_TWO); desc_range->set_part_func_type(part_func_type); - for (int k = 0; k < key_info.key_num_; ++k) { - if (static_cast(key_info.part_keys_[k].level_) == PARTITION_LEVEL_TWO) { - desc_range->set_accuracy(key_info.part_keys_[k].accuracy_); - break; + for (int i = 0; i < part_col_num; i++) { + desc_range->get_accuracies().push_back(ObAccuracy()); + } + // find all keys in this level + for (int i = 0; i < key_info.key_num_; ++i) { + if (static_cast(key_info.part_keys_[i].level_) == PARTITION_LEVEL_TWO) { + ObAccuracy accuracy(key_info.part_keys_[i].accuracy_.valid_, + key_info.part_keys_[i].accuracy_.length_, + key_info.part_keys_[i].accuracy_.precision_, + key_info.part_keys_[i].accuracy_.scale_); + desc_range->get_accuracies().at(key_info.part_keys_[i].idx_in_part_columns_) = accuracy; } } if (OB_FAIL(desc_range->set_part_array(part_array, sub_part_num_[i]))) { - LOG_WARN("failed to set_part_array, unexpected ", K(ret)); + LOG_WARN("fail to set_part_array, unexpected ", K(ret)); } } } // end of for if (OB_SUCC(ret)) { sub_part_desc_ = sub_part_desc; + if (OB_FAIL(init_sub_part_map())) { + LOG_DEBUG("fail to create non temp sub part name id map", K(ret)); + } else if (OB_FAIL(build_part_name_id_map(name_buf, name_len_buf, part_id_buf, all_sub_part_name_buf_, all_sub_part_name_length_, all_sub_part_num_, sub_part_name_id_map_))) { + LOG_DEBUG("fail to build non temp sub part name id map", K(ret)); + } } + free_name_buf(name_buf, name_len_buf, part_id_buf); return ret; } int ObProxyPartMgr::build_list_part(const ObPartitionLevel part_level, const ObPartitionFuncType part_func_type, const int64_t part_num, + const int64_t part_col_num, const bool is_template_table, const ObProxyPartKeyInfo &key_info, - ObResultSetFetcher &rs_fetcher) + ObResultSetFetcher &rs_fetcher, + const int64_t cluster_version) { int ret = OB_SUCCESS; void *tmp_buf = NULL; ObPartDescList *desc_list = NULL; ListPartition *part_array = NULL; - ObString part_name; + PART_NAME_BUF *name_buf = NULL; + int64_t *name_len_buf = NULL; + int64_t *part_id_buf = NULL; int64_t sub_part_num = 0; + ObString part_name; + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version) && PARTITION_LEVEL_TWO == part_level) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("cluster version bigger than 4, part level is two", K(ret), K(cluster_version)); // alloc desc_range and part_array - if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObPartDescList)))) { + } else if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObPartDescList)))) { ret = OB_REACH_MEMORY_LIMIT; LOG_WARN("part mgr reach memory limit", K(ret)); } else if (OB_ISNULL(desc_list = new (tmp_buf) ObPartDescList())) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("failed to do placement new", K(tmp_buf), K(ret)); + LOG_WARN("fail to do placement new", K(tmp_buf), K(ret)); + } else if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version) && OB_ISNULL(desc_list->tablet_id_array_ = (int64_t*)allocator_.alloc(sizeof(int64_t) * part_num))) { + ret = OB_REACH_MEMORY_LIMIT; + LOG_WARN("part mgr reach memory limit, alloc tablet id array failed", K(ret)); } else if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ListPartition) * part_num))) { ret = OB_REACH_MEMORY_LIMIT; LOG_WARN("part mgr reach memory limit", K(ret)); } else if (OB_ISNULL(part_array = new (tmp_buf) ListPartition[part_num])) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("failed to do placement new", K(tmp_buf), K(part_num), K(ret)); + LOG_WARN("fail to do placement new", K(tmp_buf), K(part_num), K(ret)); + } else if (OB_FAIL(alloc_name_buf(name_buf, name_len_buf, part_id_buf, part_num))) { + LOG_WARN("fail to alloc name buf", K(ret)); } else { if (PARTITION_LEVEL_ONE == part_level) { first_part_num_ = part_num; - if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObPartNameIdPair) * part_num))) { - ret = OB_REACH_MEMORY_LIMIT; - LOG_WARN("part mgr reach memory limit", K(ret)); - } else if (OB_ISNULL(part_pair_array_ = new (tmp_buf) ObPartNameIdPair[part_num])) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("failed to do placement new", K(tmp_buf), K(part_num), K(ret)); - } else if (!is_template_table && OB_ISNULL(sub_part_num_ = (int64_t *)allocator_.alloc(sizeof(int64_t) * part_num))) { + if (!is_template_table && OB_ISNULL(sub_part_num_ = (int64_t *)allocator_.alloc(sizeof(int64_t) * part_num))) { ret = OB_REACH_MEMORY_LIMIT; LOG_WARN("part mgr reach memory limit", K(ret)); } @@ -710,23 +1094,44 @@ int ObProxyPartMgr::build_list_part(const ObPartitionLevel part_level, ObNewRow row; ObNewRow tmp_row; ObObj obj_array[OB_USER_ROW_MAX_COLUMNS_COUNT]; - row.assign(obj_array, OB_USER_ROW_MAX_COLUMNS_COUNT); for (int64_t i = 0; i < part_num && OB_SUCC(ret); ++i) { if (OB_FAIL(rs_fetcher.next())) { - LOG_WARN("failed to get next rs_fetcher", K(ret)); + LOG_WARN("fail to get next rs_fetcher", K(ret)); } else { if (PARTITION_LEVEL_ONE == part_level) { PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_id", part_array[i].part_id_, int64_t); + part_id_buf[i] = part_array[i].part_id_; + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + int64_t tablet_id = -1; + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "tablet_id", tablet_id, int64_t); + desc_list->tablet_id_array_[i] = tablet_id; + if ((tablet_id != -1) && (tablet_id != 0)) { + part_id_buf[i] = tablet_id; + } + } PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "part_name", part_name); - part_pair_array_[i].set_part_id(part_array[i].part_id_); - if (OB_FAIL(part_pair_array_[i].set_part_name(part_name))) { - LOG_WARN("fail to set part name", K(part_name), K(ret)); - } else if (!is_template_table) { + if (part_name.length() <= MAX_PART_NAME_LENGTH) { + MEMCPY(name_buf[i], part_name.ptr(), part_name.length()); + name_len_buf[i] = part_name.length(); + all_first_part_name_length_ += part_name.length(); + } else {//treat too long name string as empty string + name_len_buf[i] = 0; + } + if (!is_template_table) { PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "sub_part_num", sub_part_num, int64_t); sub_part_num_[i] = sub_part_num; } } else if (PARTITION_LEVEL_TWO == part_level) { - PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "sub_part_id", part_array[i].part_id_, int64_t); + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "sub_part_id", part_array[i].part_id_, int64_t);//sub_part_id + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "part_name", part_name); + part_id_buf[i] = part_array[i].part_id_; + if (part_name.length() <= MAX_PART_NAME_LENGTH) { + MEMCPY(name_buf[i], part_name.ptr(), part_name.length()); + name_len_buf[i] = part_name.length(); + all_sub_part_name_length_ += part_name.length(); + } else {//treat too long name string as empty string + name_len_buf[i] = 0; + } } else { ret = OB_INVALID_ARGUMENT; } @@ -737,6 +1142,7 @@ int ObProxyPartMgr::build_list_part(const ObPartitionLevel part_level, } else { // deserialize ob rows array while (OB_SUCC(ret) && pos < tmp_str.length()) { + row.assign(obj_array, OB_USER_ROW_MAX_COLUMNS_COUNT); if (OB_FAIL(row.deserialize(tmp_str.ptr(), tmp_str.length(), pos))) { LOG_WARN("fail to deserialize ob row", K(tmp_str), K(ret)); } else if (OB_FAIL(ob_write_row(allocator_, row, tmp_row))) { @@ -756,7 +1162,7 @@ int ObProxyPartMgr::build_list_part(const ObPartitionLevel part_level, if (OB_SUCC(ret)) { if (OB_FAIL(desc_list->set_part_array(part_array, part_num))) { - LOG_WARN("failed to set_part_array, unexpected ", K(ret)); + LOG_WARN("fail to set_part_array, unexpected ", K(ret)); } } @@ -764,77 +1170,124 @@ int ObProxyPartMgr::build_list_part(const ObPartitionLevel part_level, if (OB_SUCC(ret)) { desc_list->set_part_level(part_level); desc_list->set_part_func_type(part_func_type); - for (int k = 0; k < key_info.key_num_; ++k) { - if (static_cast(key_info.part_keys_[k].level_) == part_level) { - desc_list->set_accuracy(key_info.part_keys_[k].accuracy_); - break; + for (int i = 0; i < part_col_num; i++) { + desc_list->get_accuracies().push_back(ObAccuracy()); + } + // find all keys in this level + for (int i = 0; i < key_info.key_num_; ++i) { + if (static_cast(key_info.part_keys_[i].level_) == part_level) { + ObAccuracy accuracy(key_info.part_keys_[i].accuracy_.valid_, + key_info.part_keys_[i].accuracy_.length_, + key_info.part_keys_[i].accuracy_.precision_, + key_info.part_keys_[i].accuracy_.scale_); + desc_list->get_accuracies().at(key_info.part_keys_[i].idx_in_part_columns_) = accuracy; } } if (PARTITION_LEVEL_ONE == part_level) { first_part_desc_ = desc_list; + if (OB_FAIL(init_first_part_map())) { + LOG_DEBUG("fail to create first part name id map", K(ret)); + } else if (OB_FAIL(build_part_name_id_map(name_buf, name_len_buf, part_id_buf, all_first_part_name_buf_, all_first_part_name_length_, part_num, first_part_name_id_map_))) { + LOG_DEBUG("fail to build first part name id map", K(ret)); + } } else if (PARTITION_LEVEL_TWO == part_level) { sub_part_desc_ = desc_list; + if (OB_FAIL(init_sub_part_map())) { + LOG_DEBUG("fail to create temp sub part name id map", K(ret)); + } else if (OB_FAIL(build_temp_sub_part_name_id_map(name_buf, name_len_buf, part_id_buf, part_num))) { + LOG_DEBUG("fail to build temp sub part name id map", K(ret)); + } } else { ret = OB_INVALID_ARGUMENT; LOG_WARN("part level invalid", K(part_level), K(ret)); } } + + free_name_buf(name_buf, name_len_buf, part_id_buf); return ret; } int ObProxyPartMgr::build_sub_list_part_with_non_template(const ObPartitionFuncType part_func_type, + const int64_t part_col_num, const ObProxyPartKeyInfo &key_info, - ObResultSetFetcher &rs_fetcher) + ObResultSetFetcher &rs_fetcher, + const int64_t cluster_version) { int ret = OB_SUCCESS; void *tmp_buf = NULL; ListPartition *part_array = NULL; common::ObPartDesc *sub_part_desc = NULL; - + PART_NAME_BUF *name_buf = NULL; + int64_t *name_len_buf = NULL; + int64_t *part_id_buf = NULL; + ObString sub_part_name; + // alloc desc_range if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ObPartDescList) * first_part_num_))) { ret = OB_REACH_MEMORY_LIMIT; LOG_WARN("part mgr reach memory limit", K(ret)); } else if (OB_ISNULL(sub_part_desc = new (tmp_buf) ObPartDescList[first_part_num_])) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("failed to do placement new", K(tmp_buf), K(ret)); + LOG_WARN("fail to do placement new", K(tmp_buf), K(ret)); + } else if (OB_FAIL(alloc_name_buf(name_buf, name_len_buf, part_id_buf, all_sub_part_num_))) { + LOG_WARN("fail to alloc name buf", K(ret)); } - // build desc_list ObString tmp_str; + int64_t index = 0; int64_t pos = 0; ObNewRow row; ObNewRow tmp_row; ObObj obj_array[OB_USER_ROW_MAX_COLUMNS_COUNT]; - row.assign(obj_array, OB_USER_ROW_MAX_COLUMNS_COUNT); ObPartDescList *desc_list = NULL; for (int64_t i = 0; i < first_part_num_ && OB_SUCC(ret); ++i) { tmp_buf = NULL; + desc_list = (((ObPartDescList *)sub_part_desc) + i); if (OB_ISNULL(tmp_buf = allocator_.alloc(sizeof(ListPartition) * sub_part_num_[i]))) { ret = OB_REACH_MEMORY_LIMIT; LOG_WARN("part mgr reach memory limit", K(ret)); } else if (OB_ISNULL(part_array = new (tmp_buf) ListPartition[sub_part_num_[i]])) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("failed to do placement new", K(tmp_buf), "sub_part_index", i, + LOG_WARN("fail to do placement new", K(tmp_buf), "sub_part_index", i, "sub_part_num", sub_part_num_[i], K(ret)); - } else { - desc_list = (((ObPartDescList *)sub_part_desc) + i); + } else if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version) && OB_ISNULL(desc_list->tablet_id_array_ = (int64_t*)allocator_.alloc(sizeof(int64_t) * sub_part_num_[i]))) { + ret = OB_REACH_MEMORY_LIMIT; + LOG_WARN("alloc tablet id array failed", K(ret), K(sub_part_num_[i])); } for (int64_t j = 0; j < sub_part_num_[i] && OB_SUCC(ret); ++j) { - if (OB_FAIL(rs_fetcher.next())) { - LOG_WARN("failed to get next rs_fetcher", K(ret)); + if (OB_FAIL(rs_fetcher.next()) || index >= all_sub_part_num_) { + LOG_WARN("fail to get next rs_fetcher", K(ret)); } else { PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "part_id", part_array[j].first_part_id_, int64_t); PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "sub_part_id", part_array[j].part_id_, int64_t); PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "high_bound_val_bin", tmp_str); + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + PROXY_EXTRACT_INT_FIELD_MYSQL(rs_fetcher, "tablet_id", desc_list->tablet_id_array_[j], int64_t); + } + + PROXY_EXTRACT_VARCHAR_FIELD_MYSQL(rs_fetcher, "part_name", sub_part_name); + if (sub_part_name.length() <= MAX_PART_NAME_LENGTH) { + MEMCPY(name_buf[index], sub_part_name.ptr(), sub_part_name.length()); + name_len_buf[index] = sub_part_name.length(); + if (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + part_id_buf[index] = desc_list->tablet_id_array_[j]; + } else { + part_id_buf[index] = generate_phy_part_id(part_array[j].first_part_id_, part_array[j].part_id_); + } + all_sub_part_name_length_ += sub_part_name.length(); + } else {//treat too long name string as empty string + name_len_buf[index] = 0; + } + ++index; pos = 0; if (OB_FAIL(ret)) { LOG_WARN("fail to fetch result", K(ret)); } else { // deserialize ob rows array while (OB_SUCC(ret) && pos < tmp_str.length()) { + row.assign(obj_array, OB_USER_ROW_MAX_COLUMNS_COUNT); if (OB_FAIL(row.deserialize(tmp_str.ptr(), tmp_str.length(), pos))) { LOG_WARN("fail to deserialize ob row", K(tmp_str), K(ret)); } else if (OB_FAIL(ob_write_row(allocator_, row, tmp_row))) { @@ -855,22 +1308,35 @@ int ObProxyPartMgr::build_sub_list_part_with_non_template(const ObPartitionFuncT if (OB_SUCC(ret)) { desc_list->set_part_level(PARTITION_LEVEL_TWO); desc_list->set_part_func_type(part_func_type); - for (int k = 0; k < key_info.key_num_; ++k) { - if (static_cast(key_info.part_keys_[k].level_) == PARTITION_LEVEL_TWO) { - desc_list->set_accuracy(key_info.part_keys_[k].accuracy_); - break; + for (int i = 0; i < part_col_num; i++) { + desc_list->get_accuracies().push_back(ObAccuracy()); + } + // find all keys in this level + for (int i = 0; i < key_info.key_num_; ++i) { + if (static_cast(key_info.part_keys_[i].level_) == PARTITION_LEVEL_TWO) { + ObAccuracy accuracy(key_info.part_keys_[i].accuracy_.valid_, + key_info.part_keys_[i].accuracy_.length_, + key_info.part_keys_[i].accuracy_.precision_, + key_info.part_keys_[i].accuracy_.scale_); + desc_list->get_accuracies().at(key_info.part_keys_[i].idx_in_part_columns_) = accuracy; } } if (OB_FAIL(desc_list->set_part_array(part_array, sub_part_num_[i]))) { - LOG_WARN("failed to set_part_array, unexpected ", K(ret)); + LOG_WARN("fail to set_part_array, unexpected ", K(ret)); } } } // end of for if (OB_SUCC(ret)) { sub_part_desc_ = sub_part_desc; + if (OB_FAIL(init_sub_part_map())) { + LOG_DEBUG("fail to create non temp sub part name id map", K(ret)); + } else if (OB_FAIL(build_part_name_id_map(name_buf, name_len_buf, part_id_buf, all_sub_part_name_buf_, all_sub_part_name_length_, all_sub_part_num_, sub_part_name_id_map_))) { + LOG_DEBUG("fail to build non temp sub part name id map", K(ret)); + } } + free_name_buf(name_buf, name_len_buf, part_id_buf); return ret; } @@ -891,8 +1357,8 @@ int ObProxyPartMgr::get_sub_part_num_by_first_part_id(ObProxyPartInfo &part_info int64_t &num) { int ret = OB_SUCCESS; - - if (part_info.is_template_table()) { + const int64_t cluster_version = part_info.get_cluster_version(); + if (part_info.is_template_table() && IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { num = part_info.get_sub_part_option().part_num_; } else { if (OB_UNLIKELY(!is_sub_part_valid())) { @@ -901,9 +1367,9 @@ int ObProxyPartMgr::get_sub_part_num_by_first_part_id(ObProxyPartInfo &part_info } else { int sub_ret = OB_INVALID_ARGUMENT; const ObPartitionFuncType sub_part_func_type = sub_part_desc_->get_part_func_type(); - + for (int64_t i = 0; i < first_part_num_; ++i) { - if (is_range_part(sub_part_func_type)) { + if (is_range_part(sub_part_func_type, cluster_version)) { ObPartDescRange *desc_range = (((ObPartDescRange*)sub_part_desc_) + i); RangePartition *part_array = desc_range->get_part_array(); if (first_part_id == part_array[0].first_part_id_) { @@ -911,7 +1377,7 @@ int ObProxyPartMgr::get_sub_part_num_by_first_part_id(ObProxyPartInfo &part_info sub_ret = OB_SUCCESS; break; } - } else if (is_list_part(sub_part_func_type)) { + } else if (is_list_part(sub_part_func_type, cluster_version)) { ObPartDescList *desc_list = (((ObPartDescList*)sub_part_desc_) + i); ListPartition *part_array = desc_list->get_part_array(); if (first_part_id == part_array[0].first_part_id_) { @@ -919,14 +1385,14 @@ int ObProxyPartMgr::get_sub_part_num_by_first_part_id(ObProxyPartInfo &part_info sub_ret = OB_SUCCESS; break; } - } else if (is_hash_part(sub_part_func_type)) { + } else if (is_hash_part(sub_part_func_type, cluster_version)) { ObPartDescHash *desc_hash = (((ObPartDescHash*)sub_part_desc_) + i); if (first_part_id == desc_hash->get_first_part_id()) { num = sub_part_num_[i]; sub_ret = OB_SUCCESS; break; } - } else if (is_key_part(sub_part_func_type)) { + } else if (is_key_part(sub_part_func_type, cluster_version)) { ObPartDescKey *desc_key = (((ObPartDescKey*)sub_part_desc_) + i); if (first_part_id == desc_key->get_first_part_id()) { num = sub_part_num_[i]; @@ -945,10 +1411,116 @@ int ObProxyPartMgr::get_sub_part_num_by_first_part_id(ObProxyPartInfo &part_info } } } - + + return ret; +} + +int ObProxyPartMgr::build_part_name_id_map(const PART_NAME_BUF * const name_buf, + const int64_t * const name_len_buf, + const int64_t * const part_id_buf, + char * target_part_name_buf, + const int64_t total_part_name_len, + const int64_t part_num, + PartNameIdMap& part_name_id_map) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(name_buf) || OB_ISNULL(name_len_buf) || OB_ISNULL(part_id_buf)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("fail to get part name buf", K(ret)); + } else if (OB_NOT_NULL(target_part_name_buf)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("part name buf is alloc twice", K(ret)); + } else if (OB_ISNULL(target_part_name_buf = (char *)allocator_.alloc(total_part_name_len))) { + ret = OB_REACH_MEMORY_LIMIT; + LOG_WARN("part mgr reach memory limit when alloc all first part name buf", K(ret)); + } else { + ObString part_name; + int64_t pos = 0; + for (int64_t i = 0; OB_SUCC(ret) && i < part_num; ++i) { + if (OB_LIKELY( 0 != name_len_buf[i])) { + part_name.assign_ptr(target_part_name_buf + pos, static_cast(name_len_buf[i])); + MEMCPY(target_part_name_buf + pos, name_buf[i], name_len_buf[i]); + string_to_upper_case(part_name.ptr(), part_name.length()); + part_name_id_map.set_refactored(part_name, part_id_buf[i]); + pos += name_len_buf[i]; + } + } + } + return ret; +} + +int ObProxyPartMgr::build_temp_sub_part_name_id_map(const PART_NAME_BUF * const name_buf, + const int64_t * const name_len_buf, + const int64_t * const part_id_buf, + const int64_t part_num) +{ + int ret = OB_SUCCESS; + all_sub_part_name_length_ = (all_first_part_name_length_ * part_num) //total length of first-part-name + + (all_sub_part_name_length_ * first_part_num_) //total length of sub-part-name + + (part_num * first_part_num_); //total length of 's' + if (OB_ISNULL(name_buf) || OB_ISNULL(name_len_buf) || OB_ISNULL(part_id_buf)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("fail to get part name buf", K(ret)); + } else if (OB_ISNULL(all_sub_part_name_buf_ = (char *)allocator_.alloc(sizeof(char) * all_sub_part_name_length_))) { + ret = OB_REACH_MEMORY_LIMIT; + LOG_WARN("part mgr reach memory limit when alloc all first part name buf", K(ret)); + } else { + ObString part_name; + int64_t pos = 0; + int64_t tmp_len = 0; + PartNameIdMap::const_iterator iter = first_part_name_id_map_.begin(); + PartNameIdMap::const_iterator end = first_part_name_id_map_.end(); + for (; OB_SUCC(ret) && iter !=end; iter++) { + for (int64_t i = 0; OB_SUCC(ret) && i < part_num; ++i) { + if (OB_LIKELY(0 != name_len_buf[i])) { + tmp_len = iter->first.length() + 1 + name_len_buf[i];//first part name + 's' + sub part name + if (OB_LIKELY(tmp_len <= MAX_PART_NAME_LENGTH)) { + part_name.assign_ptr(all_sub_part_name_buf_ + pos, static_cast(tmp_len)); + MEMCPY(all_sub_part_name_buf_ + pos, iter->first.ptr(), iter->first.length()); + pos += iter->first.length(); + all_sub_part_name_buf_[pos++] = 'S'; + MEMCPY(all_sub_part_name_buf_ + pos, name_buf[i], name_len_buf[i]); + pos += name_len_buf[i]; + string_to_upper_case(part_name.ptr(), part_name.length()); + sub_part_name_id_map_.set_refactored(part_name, generate_phy_part_id(iter->second, part_id_buf[i])); + } + } + } + } + } return ret; } +int ObProxyPartMgr::alloc_name_buf(PART_NAME_BUF *&name_buf, int64_t *&name_len_buf, int64_t *&part_id_buf, const int64_t part_num) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(name_buf = (PART_NAME_BUF *)allocator_.alloc(sizeof(PART_NAME_BUF) * part_num))) { + ret = OB_REACH_MEMORY_LIMIT; + LOG_WARN("part mgr reach memory limit when alloc name buf", K(ret)); + } else if (OB_ISNULL(name_len_buf = (int64_t *)allocator_.alloc(sizeof(int64_t) * part_num))) { + ret = OB_REACH_MEMORY_LIMIT; + LOG_WARN("part mgr reach memory limit when alloc name len buf", K(ret)); + } else if (OB_ISNULL(part_id_buf = (int64_t *)allocator_.alloc(sizeof(int64_t) * part_num))) { + ret = OB_REACH_MEMORY_LIMIT; + LOG_WARN("part mgr reach memory limit when alloc part id buf", K(ret)); + } + + return ret; +} + +void ObProxyPartMgr::free_name_buf(PART_NAME_BUF *name_buf, int64_t *name_len_buf, int64_t *part_id_buf) +{ + if (OB_NOT_NULL(part_id_buf)) { + allocator_.free(part_id_buf); + } + if (OB_NOT_NULL(name_len_buf)) { + allocator_.free(name_len_buf); + } + if (OB_NOT_NULL(name_buf)) { + allocator_.free(name_buf); + } +} + int64_t ObProxyPartMgr::to_string(char *buf, const int64_t buf_len) const { int64_t pos = 0; @@ -963,13 +1535,13 @@ int64_t ObProxyPartMgr::to_string(char *buf, const int64_t buf_len) const ObPartDesc *sub_part_desc = NULL; int i = 0; // If it is a non-template partition, only print the first secondary partition to avoid too many logs - if (is_range_part(sub_part_func_type)) { + if (is_range_part(sub_part_func_type, cluster_version_)) { sub_part_desc = (((ObPartDescRange*)sub_part_desc_) + i); - } else if (is_list_part(sub_part_func_type)) { + } else if (is_list_part(sub_part_func_type, cluster_version_)) { sub_part_desc = (((ObPartDescList*)sub_part_desc_) + i); - } else if (is_hash_part(sub_part_func_type)) { + } else if (is_hash_part(sub_part_func_type, cluster_version_)) { sub_part_desc = (((ObPartDescHash*)sub_part_desc_) + i); - } else if (is_key_part(sub_part_func_type)) { + } else if (is_key_part(sub_part_func_type, cluster_version_)) { sub_part_desc = (((ObPartDescKey*)sub_part_desc_) + i); } J_KV("first_part_id", i, KPC(sub_part_desc)); diff --git a/src/obproxy/proxy/route/obproxy_part_mgr.h b/src/obproxy/proxy/route/obproxy_part_mgr.h index 98798152125c297dad347533cd5363b6a4cdab0e..f1c8e341e45a8240201483c29ab63072f3c7bf37 100644 --- a/src/obproxy/proxy/route/obproxy_part_mgr.h +++ b/src/obproxy/proxy/route/obproxy_part_mgr.h @@ -29,119 +29,103 @@ namespace obproxy class ObResultSetFetcher; namespace proxy { - -class ObPartNameIdPair -{ -public: - ObPartNameIdPair() : part_id_(-1) - { - part_name_buf_[0] = '\0'; - } - ~ObPartNameIdPair() {} - - int set_part_name(const common::ObString &part_name); - void set_part_id(int64_t part_id) { part_id_ = part_id; } - - const common::ObString get_part_name() const { return part_name_; } - int64_t get_part_id() const { return part_id_; } - - int assign(const ObPartNameIdPair &other); - int64_t to_string(char *buf, const int64_t buf_len) const; -public: - common::ObString part_name_; - -private: - int64_t part_id_; - char part_name_buf_[common::OB_MAX_PARTITION_NAME_LENGTH]; - DISALLOW_COPY_AND_ASSIGN(ObPartNameIdPair); -}; - -inline int ObPartNameIdPair::set_part_name(const common::ObString &part_name) -{ - int ret = common::OB_SUCCESS; - if (part_name.length() > common::OB_MAX_PARTITION_NAME_LENGTH) { - ret = common::OB_INVALID_ARGUMENT; - PROXY_LOG(WARN, "invalid part name", K(part_name), K(ret)); - } else { - MEMCPY(part_name_buf_, part_name.ptr(), part_name.length()); - part_name_.assign_ptr(part_name_buf_, part_name.length()); - } - return ret; -} - -inline int ObPartNameIdPair::assign(const ObPartNameIdPair &other) -{ - int ret = common::OB_SUCCESS; - set_part_id(other.get_part_id()); - ret = set_part_name(other.get_part_name()); - return ret; -} +class ObProxyExprCalculator; +class ObServerRoute; class ObProxyPartMgr { +private: + const static int64_t MAX_PART_NAME_LENGTH = common::OB_MAX_PARTITION_NAME_LENGTH;//64 + typedef char PART_NAME_BUF[MAX_PART_NAME_LENGTH]; + typedef hash::ObHashMap PartNameIdMap; public: explicit ObProxyPartMgr(common::ObIAllocator &allocator); ~ObProxyPartMgr() { } - + void destroy(); + int get_part_with_part_name(const common::ObString &part_name, - int64_t &part_id_); - int get_first_part_id_by_idx(const int64_t idx, int64_t &part_id); + int64_t &part_id, + ObProxyPartInfo &part_info, + ObServerRoute &route, + ObProxyExprCalculator &expr_calculator); + int get_first_part_id_by_random(const int64_t rand_num, + int64_t &first_part_id, + int64_t &tablet_id); int get_first_part(common::ObNewRange &range, common::ObIAllocator &allocator, common::ObIArray &part_ids, - common::ObPartDescCtx &ctx); + common::ObPartDescCtx &ctx, + common::ObIArray &tablet_ids); int get_sub_part(common::ObNewRange &range, common::ObIAllocator &allocator, common::ObPartDesc *sub_part_desc_ptr, common::ObIArray &part_ids, - common::ObPartDescCtx &ctx); + common::ObPartDescCtx &ctx, + common::ObIArray &tablet_ids); - int get_sub_part_by_random(const int64_t rand_num, + int get_sub_part_by_random(const int64_t rand_num, common::ObPartDesc *sub_part_desc_ptr, - common::ObIArray &part_ids); + common::ObIArray &part_ids, + common::ObIArray &tablet_ids); int build_hash_part(const bool is_oracle_mode, const share::schema::ObPartitionLevel part_level, const share::schema::ObPartitionFuncType part_func_type, const int64_t part_num, const int64_t part_space, + const int64_t part_col_num, const bool is_template_table, const ObProxyPartKeyInfo &key_info, - ObResultSetFetcher *rs_fetcher = NULL); + ObResultSetFetcher *rs_fetcher, + const int64_t cluster_version); int build_sub_hash_part_with_non_template(const bool is_oracle_mode, const share::schema::ObPartitionFuncType part_func_type, const int64_t part_space, + const int64_t part_col_num, const ObProxyPartKeyInfo &key_info, - ObResultSetFetcher &rs_fetcher); + ObResultSetFetcher &rs_fetcher, + const int64_t cluster_version); int build_key_part(const share::schema::ObPartitionLevel part_level, const share::schema::ObPartitionFuncType part_func_type, const int64_t part_num, const int64_t part_space, + const int64_t part_col_num, const bool is_template_table, const ObProxyPartKeyInfo &key_info, - ObResultSetFetcher *rs_fetcher = NULL); + ObResultSetFetcher *rs_fetcher, + const int64_t cluster_version); int build_sub_key_part_with_non_template(const share::schema::ObPartitionFuncType part_func_type, const int64_t part_space, + const int64_t part_col_num, const ObProxyPartKeyInfo &key_info, - ObResultSetFetcher &rs_fetcher); + ObResultSetFetcher &rs_fetcher, + const int64_t cluster_version); int build_range_part(const share::schema::ObPartitionLevel part_level, const share::schema::ObPartitionFuncType part_func_type, const int64_t part_num, + const int64_t part_col_num, const bool is_template_table, const ObProxyPartKeyInfo &key_info, - ObResultSetFetcher &rs_fetcher); + ObResultSetFetcher &rs_fetcher, + const int64_t cluster_version); int build_sub_range_part_with_non_template(const share::schema::ObPartitionFuncType part_func_type, + const int64_t part_col_num, const ObProxyPartKeyInfo &key_info, - ObResultSetFetcher &rs_fetcher); + ObResultSetFetcher &rs_fetcher, + const int64_t cluster_verison); int build_list_part(const share::schema::ObPartitionLevel part_level, const share::schema::ObPartitionFuncType part_func_type, const int64_t part_num, + const int64_t part_col_num, const bool is_template_table, const ObProxyPartKeyInfo &key_info, - ObResultSetFetcher &rs_fetcher); + ObResultSetFetcher &rs_fetcher, + const int64_t cluster_version); int build_sub_list_part_with_non_template(const share::schema::ObPartitionFuncType part_func_type, + const int64_t part_col_num, const ObProxyPartKeyInfo &key_info, - ObResultSetFetcher &rs_fetcher); + ObResultSetFetcher &rs_fetcher, + const int64_t cluster_version); bool is_first_part_valid() const { return NULL != first_part_desc_; } bool is_sub_part_valid() const { return NULL != sub_part_desc_; } @@ -151,21 +135,60 @@ public: int64_t &num); int get_sub_part_desc_by_first_part_id(const bool is_template_table, const int64_t first_part_id, - ObPartDesc *&sub_part_desc_ptr); + ObPartDesc *&sub_part_desc_ptr, + const int64_t cluster_version); + void set_all_sub_part_num(int64_t all_sub_part_num); common::ObObjType get_first_part_type() const; common::ObObjType get_sub_part_type() const; + void set_cluster_version(const int64_t cluster_version) { cluster_version_ = cluster_version; } int64_t to_string(char *buf, const int64_t buf_len) const; +private: + int init_first_part_map(); + int init_sub_part_map(); + int alloc_name_buf(PART_NAME_BUF *&name_buf, int64_t *&name_len_buf, int64_t *&part_id_buf, const int64_t part_num); + void free_name_buf(PART_NAME_BUF *name_buf, int64_t *name_len_buf, int64_t *part_id_buf); + int build_part_name_id_map(const PART_NAME_BUF * const name_buf, + const int64_t * const name_len_buf, + const int64_t * const part_id_buf, + char * target_part_name_buf, + const int64_t total_part_name_len, + const int64_t part_num, + PartNameIdMap& part_name_id_map); + int build_temp_sub_part_name_id_map(const PART_NAME_BUF * const name_buf, + const int64_t * const name_len_buf, + const int64_t * const part_id_buf, + const int64_t part_num); private: common::ObPartDesc *first_part_desc_; common::ObPartDesc *sub_part_desc_; // may be we need a array here int64_t first_part_num_; int64_t *sub_part_num_; - ObPartNameIdPair* part_pair_array_; // first part name id pair array + int64_t all_sub_part_num_; + char * all_first_part_name_buf_; // first part name cancatenation string: "p1|p2|···|pn" + char * all_sub_part_name_buf_;// sub part name cancatenation string: "p1sp1|p1sp2|···|pnspn" + int64_t all_first_part_name_length_; + int64_t all_sub_part_name_length_; + PartNameIdMap first_part_name_id_map_; // map K(first part name) to V(first part id) + PartNameIdMap sub_part_name_id_map_; // map K(sub part name) to V(physical part id) common::ObIAllocator &allocator_; + int64_t cluster_version_; }; +inline void ObProxyPartMgr::set_all_sub_part_num(int64_t all_sub_part_num) +{ + all_sub_part_num_ = all_sub_part_num; +} +inline int ObProxyPartMgr::init_first_part_map() +{ + return first_part_name_id_map_.create(first_part_num_ * 1, ObModIds::OB_HASH_BUCKET, ObModIds::OB_HASH_NODE);//default load factor = 1.0 +} +inline int ObProxyPartMgr::init_sub_part_map() +{ + return sub_part_name_id_map_.create(all_sub_part_num_ * 1, ObModIds::OB_HASH_BUCKET, ObModIds::OB_HASH_NODE);//default load factor = 1.0 +} + } // namespace proxy } // namespace obproxy } // namespace oceanbase diff --git a/src/obproxy/proxy/shard/obproxy_shard_ddl_cont.cpp b/src/obproxy/proxy/shard/obproxy_shard_ddl_cont.cpp index d22f2567efaa5f5f1595badfdca5d9f3f1e924c6..8c26537c3daee0005a492c154ffe4cd58ed8571e 100644 --- a/src/obproxy/proxy/shard/obproxy_shard_ddl_cont.cpp +++ b/src/obproxy/proxy/shard/obproxy_shard_ddl_cont.cpp @@ -245,6 +245,8 @@ int ObShardDDLCont::covert_stmt_type_to_operation(const ObProxyBasicStmtType stm operation = SHARD_DDL_OPERATION_DROP; } else if (stmt_type == OBPROXY_T_RENAME) { operation = SHARD_DDL_OPERATION_RENAME; + } else if (stmt_type == OBPROXY_T_TRUNCATE) { + operation = SHARD_DDL_OPERATION_TRUNCATE; } else { ret = OB_NOT_SUPPORTED; } diff --git a/src/obproxy/proxy/shard/obproxy_shard_ddl_cont.h b/src/obproxy/proxy/shard/obproxy_shard_ddl_cont.h index 6a4a1261b0a493e5ceb612f0457fb604ac7ddcfc..f17845276cd261d690631ebeb1bbc8ebc0b114a7 100644 --- a/src/obproxy/proxy/shard/obproxy_shard_ddl_cont.h +++ b/src/obproxy/proxy/shard/obproxy_shard_ddl_cont.h @@ -32,6 +32,7 @@ enum ObShardDDLOperation { SHARD_DDL_OPERATION_ALTER, SHARD_DDL_OPERATION_DROP, SHARD_DDL_OPERATION_RENAME, + SHARD_DDL_OPERATION_TRUNCATE, SHARD_DDL_OPERATION_MAX }; diff --git a/src/obproxy/proxy/shard/obproxy_shard_utils.cpp b/src/obproxy/proxy/shard/obproxy_shard_utils.cpp index 877e9b2b8e0c5ddb6a5e370d6f8c1b3acaf5f2f1..a6d983cf7e7651e9dbb1335d4111b70e04d7e165 100644 --- a/src/obproxy/proxy/shard/obproxy_shard_utils.cpp +++ b/src/obproxy/proxy/shard/obproxy_shard_utils.cpp @@ -94,6 +94,8 @@ int ObProxyShardUtils::check_logic_database(ObMysqlTransact::ObTransState &trans if (OB_SUCC(ret)) { session_info.set_group_id(OBPROXY_MAX_DBMESH_ID); + session_info.set_table_id(OBPROXY_MAX_DBMESH_ID); + session_info.set_es_id(OBPROXY_MAX_DBMESH_ID); session_info.set_logic_database_name(db_name); LOG_DEBUG("check logic database success", K(db_name)); } @@ -128,6 +130,7 @@ int ObProxyShardUtils::change_connector(ObDbConfigLogicDb &logic_db_info, LOG_WARN("not support distributed transaction", K(trans_state.current_.state_), K(trans_state.is_auth_request_), K(trans_state.is_hold_start_trans_), + K(trans_state.is_hold_xa_start_), KPC(prev_shard_conn), KPC(shard_conn), K(ret)); } else { @@ -231,27 +234,26 @@ void ObProxyShardUtils::replace_oracle_table(ObSqlString &new_sql, const ObStrin hava_quoto = false; } -int ObProxyShardUtils::do_rewrite_shard_select_request(const ObString &sql, - ObSqlParseResult &parse_result, - bool is_oracle_mode, - const ObHashMap &table_name_map, - const ObString &real_database_name, - bool is_single_shard_db_table, - ObSqlString &new_sql) +int ObProxyShardUtils::rewrite_shard_dml_request(const ObString &sql, + ObSqlString &new_sql, + ObSqlParseResult &parse_result, + bool is_oracle_mode, + const ObHashMap &table_name_map, + const ObString &real_database_name, + bool is_single_shard_db_table) { int ret = OB_SUCCESS; - const uint32_t PARSE_EXTRA_CHAR_NUM = 2; const char *sql_ptr = sql.ptr(); int64_t sql_len = sql.length(); int64_t copy_pos = 0; - ObProxySelectStmt *select_stmt = static_cast(parse_result.get_proxy_stmt()); - if (OB_ISNULL(select_stmt)) { + ObProxyDMLStmt *dml_stmt = static_cast(parse_result.get_proxy_stmt()); + if (OB_ISNULL(dml_stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null select stmt", K(ret)); } else { - ObProxySelectStmt::TablePosArray &table_pos_array = select_stmt->get_table_pos_array(); + ObProxyDMLStmt::TablePosArray &table_pos_array = dml_stmt->get_table_pos_array(); std::sort(table_pos_array.begin(), table_pos_array.end()); for (int64_t i = 0; OB_SUCC(ret) && i < table_pos_array.count(); i++) { @@ -262,8 +264,6 @@ int ObProxyShardUtils::do_rewrite_shard_select_request(const ObString &sql, ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null expr table", K(ret)); } else { - bool database_hava_quoto = false; - bool table_hava_quoto = false; int64_t table_pos = expr_table_pos.get_table_pos(); int64_t database_pos = expr_table_pos.get_database_pos(); @@ -275,52 +275,10 @@ int ObProxyShardUtils::do_rewrite_shard_select_request(const ObString &sql, ObString real_table_name; if (OB_FAIL(table_name_map.get_refactored(table_name, real_table_name))) { LOG_WARN("fail to get real table name", K(table_name), K(ret)); - } else { - if (*(sql_ptr + table_pos - 1) == '`' || *(sql_ptr + table_pos - 1) == '"') { - table_hava_quoto = true; - table_pos -= 1; - table_len += 2; - } - - // replace database - if (database_pos > 0) { - // If there is database in SQL - if (*(sql_ptr + database_pos - 1) == '`' || *(sql_ptr + database_pos - 1) == '"') { - database_hava_quoto = true; - database_pos -= 1; - database_len += 2; - } - new_sql.append(sql_ptr + copy_pos, database_pos - copy_pos); - - if (is_oracle_mode) { - replace_oracle_table(new_sql, real_database_name, database_hava_quoto, is_single_shard_db_table, true); - } else { - new_sql.append(real_database_name); - } - - copy_pos = database_pos + database_len; - new_sql.append(sql_ptr + copy_pos, table_pos - copy_pos); - } else { - // If there is no database in SQL, single database and single table will not be added. - // add real database name before logic table name - new_sql.append(sql_ptr + copy_pos, table_pos - copy_pos); - if (!is_single_shard_db_table && !real_database_name.empty()) { - if (is_oracle_mode) { - replace_oracle_table(new_sql, real_database_name, database_hava_quoto, is_single_shard_db_table, true); - } else { - new_sql.append(real_database_name); - } - new_sql.append(".", 1); - } - } - - // replace table name - if (is_oracle_mode) { - replace_oracle_table(new_sql, real_table_name, table_hava_quoto, is_single_shard_db_table, false); - } else { - new_sql.append(real_table_name); - } - copy_pos = table_pos + table_len; + } else if (OB_FAIL(rewrite_shard_request_table(sql_ptr, database_pos, database_len, + table_pos, table_len, real_table_name, real_database_name, + is_oracle_mode, is_single_shard_db_table, new_sql, copy_pos))) { + LOG_WARN("fail to rewrite table", K(ret)); } } } @@ -328,81 +286,130 @@ int ObProxyShardUtils::do_rewrite_shard_select_request(const ObString &sql, if (OB_SUCC(ret)) { - new_sql.append(sql_ptr + copy_pos, sql_len - copy_pos - PARSE_EXTRA_CHAR_NUM); + new_sql.append(sql_ptr + copy_pos, sql_len - copy_pos); } return ret; } -int ObProxyShardUtils::rewrite_shard_select_request(ObClientSessionInfo &session_info, - ObProxyMysqlRequest &client_request, - ObIOBufferReader &client_buffer_reader, - const ObHashMap &table_name_map, - const ObString &real_database_name, - bool is_single_shard_db_table) + +int ObProxyShardUtils::rewrite_shard_request_db(const char *sql_ptr, int64_t database_pos, + int64_t table_pos, uint64_t database_len, + const ObString &real_database_name, bool is_oracle_mode, + bool is_single_shard_db_table, ObSqlString &new_sql, int64_t ©_pos) { int ret = OB_SUCCESS; - ObSqlParseResult &parse_result = client_request.get_parse_result(); - ObSqlString new_sql; + bool database_hava_quoto = false; - if (OB_FAIL(do_rewrite_shard_select_request(client_request.get_parse_sql(), parse_result, - session_info.is_oracle_mode(), table_name_map, - real_database_name, is_single_shard_db_table, - new_sql))) { - } else { - // 4. push reader forward by consuming old buffer and write new sql into buffer - if (OB_FAIL(client_buffer_reader.consume_all())) { - LOG_WARN("fail to consume all", K(ret)); + // replace database + if (database_pos > 0) { + // If there is database in SQL + if (*(sql_ptr + database_pos - 1) == '`' || *(sql_ptr + database_pos - 1) == '"') { + database_hava_quoto = true; + database_pos -= 1; + database_len += 2; + } + new_sql.append(sql_ptr + copy_pos, database_pos - copy_pos); + + if (is_oracle_mode) { + replace_oracle_table(new_sql, real_database_name, database_hava_quoto, is_single_shard_db_table, true); } else { - ObMIOBuffer *writer = client_buffer_reader.mbuf_; - if (OB_ISNULL(writer)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null values ", K(writer), K(ret)); - // no need compress here, if server session support compress, it will compress later - } else if (OB_FAIL(ObMysqlRequestBuilder::build_mysql_request(*writer, obmysql::OB_MYSQL_COM_QUERY, new_sql.string(), false, false))) { - LOG_WARN("fail to build_mysql_request", K(new_sql), K(ret)); - } else if (OB_FAIL(ObProxySessionInfoHandler::rewrite_query_req_by_sharding(session_info, client_request, client_buffer_reader))) { - LOG_WARN("fail to rewrite_query_req_by_sharding", K(ret)); + new_sql.append(real_database_name); + } + + copy_pos = database_pos + database_len; + if (database_pos < table_pos) { + new_sql.append(sql_ptr + copy_pos, table_pos - copy_pos); + } + } else { + // If there is no database in SQL, single database and single table will not be added. + // add real database name before logic table name + new_sql.append(sql_ptr + copy_pos, table_pos - copy_pos); + if (!is_single_shard_db_table && !real_database_name.empty()) { + if (is_oracle_mode) { + replace_oracle_table(new_sql, real_database_name, database_hava_quoto, is_single_shard_db_table, true); + } else { + new_sql.append(real_database_name); } + new_sql.append(".", 1); } } return ret; } -// MySQL use single quoto to table, case-insensitive -// Oracle use double quoto, case-sensitive, The default is uppercase -// if single schema table mode, table from SQL: -// if have quoto, add quoto -// if no quoto, not add quoto -// if sharding mode, table from config, both add quoto -int ObProxyShardUtils::rewrite_shard_request(ObClientSessionInfo &session_info, - ObProxyMysqlRequest &client_request, - ObIOBufferReader &client_buffer_reader, - const ObString &table_name, const ObString &database_name, - const ObString &real_table_name, const ObString &real_database_name, - bool is_single_shard_db_table) +int ObProxyShardUtils::rewrite_shard_request_table_no_db(const char *sql_ptr, + int64_t table_pos, uint64_t table_len, + const ObString &real_table_name, + bool is_oracle_mode, bool is_single_shard_db_table, + ObSqlString &new_sql, int64_t ©_pos) { int ret = OB_SUCCESS; - const uint32_t PARSE_EXTRA_CHAR_NUM = 2; - uint64_t table_len = table_name.length(); - int64_t dml_tb_pos = client_request.get_parse_result().get_dbmesh_route_info().tb_pos_; - uint64_t index_table_len = table_name.length(); - int64_t index_table_pos = client_request.get_parse_result().get_dbmesh_route_info().index_tb_pos_; + bool table_have_quoto = false; - ObString sql = client_request.get_parse_sql(); - common::ObSqlString new_sql; - const char *sql_ptr = sql.ptr(); - int64_t sql_len = sql.length(); + if (*(sql_ptr + table_pos - 1) == '`' || *(sql_ptr + table_pos - 1) == '"') { + table_have_quoto = true; + table_pos -= 1; + table_len += 2; + } + + new_sql.append(sql_ptr + copy_pos, table_pos - copy_pos); + if (is_oracle_mode) { + replace_oracle_table(new_sql, real_table_name, table_have_quoto, is_single_shard_db_table, false); + } else { + new_sql.append(real_table_name); + } + + copy_pos = table_pos + table_len; + + return ret; +} + + +int ObProxyShardUtils::rewrite_shard_request_table(const char *sql_ptr, + int64_t database_pos, uint64_t database_len, + int64_t table_pos, uint64_t table_len, + const ObString &real_table_name, const ObString &real_database_name, + bool is_oracle_mode, bool is_single_shard_db_table, + ObSqlString &new_sql, int64_t ©_pos) +{ + int ret = OB_SUCCESS; + + bool table_hava_quoto = false; + + if (*(sql_ptr + table_pos - 1) == '`' || *(sql_ptr + table_pos - 1) == '"') { + table_hava_quoto = true; + table_pos -= 1; + table_len += 2; + } + + if (OB_FAIL(rewrite_shard_request_db(sql_ptr, database_pos, table_pos, database_len, + real_database_name, is_oracle_mode, + is_single_shard_db_table, new_sql, copy_pos))) { + LOG_WARN("fail to rewrite db", K(ret)); + } else { + // replace table name + if (is_oracle_mode) { + replace_oracle_table(new_sql, real_table_name, table_hava_quoto, is_single_shard_db_table, false); + } else { + new_sql.append(real_table_name); + } + + copy_pos = table_pos + table_len; + } + + return ret; +} + +int ObProxyShardUtils::rewrite_shard_request_hint_table(const char *sql_ptr, int64_t index_table_pos, uint64_t index_table_len, + const ObString &real_table_name, bool is_oracle_mode, + bool is_single_shard_db_table, ObSqlString &new_sql, int64_t ©_pos) +{ + int ret = OB_SUCCESS; - bool database_hava_quoto = false; bool table_hava_quoto = false; - int64_t table_pos = dml_tb_pos; - int64_t database_pos = -1; - int64_t copy_pos = 0; - ObString tmp_str; // replace index table name in hint if (index_table_pos > 0) { @@ -413,7 +420,7 @@ int ObProxyShardUtils::rewrite_shard_request(ObClientSessionInfo &session_info, } new_sql.append(sql_ptr + copy_pos, index_table_pos); - if (session_info.is_oracle_mode()) { + if (is_oracle_mode) { replace_oracle_table(new_sql, real_table_name, table_hava_quoto, is_single_shard_db_table, false); } else { new_sql.append(real_table_name); @@ -422,81 +429,65 @@ int ObProxyShardUtils::rewrite_shard_request(ObClientSessionInfo &session_info, copy_pos = index_table_pos + index_table_len; } - if (*(sql_ptr + table_pos - 1) == '`' || *(sql_ptr + table_pos - 1) == '"') { - table_hava_quoto = true; - table_pos -= 1; - table_len = table_name.length() + 2; - } + return ret; +} - // get database pos, check whether have database or not - // TODO: get database pos by parser - bool sql_has_database = !client_request.get_parse_result().get_origin_database_name().empty(); - if (sql_has_database && *(sql_ptr + table_pos - 1) == '.') { - database_pos = table_pos - 1 - database_name.length(); - if (*(sql_ptr + table_pos - 2) == '`' || *(sql_ptr + table_pos - 2) == '"') { - database_hava_quoto = true; - database_pos -= 2; - tmp_str.assign_ptr(sql_ptr + database_pos + 1, static_cast(database_name.length())); - } else { - tmp_str.assign_ptr(sql_ptr + database_pos, static_cast(database_name.length())); - } - if (database_name == tmp_str) { - // do nothing - } else { - database_pos = -1; - } - } +// MySQL use single quoto to table, case-insensitive +// Oracle use double quoto, case-sensitive, The default is uppercase +// if single schema table mode, table from SQL: +// if have quoto, add quoto +// if no quoto, not add quoto +// if sharding mode, table from config, both add quoto +int ObProxyShardUtils::rewrite_shard_request(ObClientSessionInfo &session_info, + ObSqlParseResult &parse_result, + const ObString &table_name, const ObString &database_name, + const ObString &real_table_name, const ObString &real_database_name, + bool is_single_shard_db_table, + const ObString& sql, + ObSqlString& new_sql) +{ + int ret = OB_SUCCESS; - // replace database - if (database_pos > 0) { - new_sql.append(sql_ptr + copy_pos, database_pos - copy_pos); + uint64_t table_len = table_name.length(); + uint64_t database_len = database_name.length(); + uint64_t index_table_len = table_name.length(); + int64_t table_pos = parse_result.get_dbmesh_route_info().tb_pos_; + int64_t database_pos = parse_result.get_dbmesh_route_info().db_pos_; + int64_t index_table_pos = parse_result.get_dbmesh_route_info().index_tb_pos_; - if (session_info.is_oracle_mode()) { - replace_oracle_table(new_sql, real_database_name, database_hava_quoto, is_single_shard_db_table, true); - } else { - new_sql.append(real_database_name); - } + const char *sql_ptr = sql.ptr(); + int64_t sql_len = sql.length(); - new_sql.append(".", 1); - } else { - // if SQL not have database, no need add database in single mode - // add real database name before logic table name - new_sql.append(sql_ptr + copy_pos, table_pos - copy_pos); - if (!is_single_shard_db_table && !database_name.empty()) { + bool is_oracle_mode = session_info.is_oracle_mode(); + int64_t copy_pos = 0; - if (session_info.is_oracle_mode()) { - replace_oracle_table(new_sql, real_database_name, database_hava_quoto, is_single_shard_db_table, true); - } else { - new_sql.append(real_database_name); + if (OB_FAIL(rewrite_shard_request_hint_table(sql_ptr, index_table_pos, index_table_len, + real_table_name, is_oracle_mode, + is_single_shard_db_table,new_sql, copy_pos))) { + LOG_WARN("fail to rewrite hint table", K(ret)); + } else { + if (OB_INVALID_INDEX == database_pos || database_pos < table_pos) { + if (OB_FAIL(rewrite_shard_request_table(sql_ptr, database_pos, database_len, + table_pos, table_len, real_table_name, real_database_name, + is_oracle_mode, is_single_shard_db_table, new_sql, copy_pos))) { + LOG_WARN("fail to rewrite table", K(ret)); + } + } else { + if (OB_FAIL(rewrite_shard_request_table(sql_ptr, 0, database_len, + table_pos, table_len, real_table_name, real_database_name, + is_oracle_mode, is_single_shard_db_table, new_sql, copy_pos))) { + LOG_WARN("fail to rewrite table", K(ret)); + } else if (OB_FAIL(rewrite_shard_request_db(sql_ptr, database_pos, table_pos, database_len, + real_database_name, is_oracle_mode, + is_single_shard_db_table, new_sql, copy_pos))) { + LOG_WARN("fail to rewrite db", K(ret)); } - new_sql.append(".", 1); } } - // replace table name - if (session_info.is_oracle_mode()) { - replace_oracle_table(new_sql, real_table_name, table_hava_quoto, is_single_shard_db_table, false); - } else { - new_sql.append(real_table_name); - } - - copy_pos = table_pos + table_len; - new_sql.append(sql_ptr + copy_pos, sql_len - copy_pos - PARSE_EXTRA_CHAR_NUM); - - // 4. push reader forward by consuming old buffer and write new sql into buffer - if (OB_FAIL(client_buffer_reader.consume_all())) { - LOG_WARN("fail to consume all", K(ret)); - } else { - ObMIOBuffer *writer = client_buffer_reader.mbuf_; - if (OB_ISNULL(writer)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null values ", K(writer), K(ret)); - // no need compress here, if server session support comrpess, it will compress later - } else if (OB_FAIL(ObMysqlRequestBuilder::build_mysql_request(*writer, obmysql::OB_MYSQL_COM_QUERY, new_sql.string(), false, false))) { - LOG_WARN("fail to build_mysql_request", K(new_sql), K(ret)); - } else if (OB_FAIL(ObProxySessionInfoHandler::rewrite_query_req_by_sharding(session_info, client_request, client_buffer_reader))) { - LOG_WARN("fail to rewrite_query_req_by_sharding", K(ret)); - } + if (OB_SUCC(ret)) { + new_sql.append(sql_ptr + copy_pos, sql_len - copy_pos); + LOG_DEBUG("succ to rewrite sql", K(sql), K(new_sql)); } return ret; @@ -716,25 +707,21 @@ int ObProxyShardUtils::testload_check_and_rewrite_testload_hint_index(common::Ob * Args: * @param session_info : client session info * @param client_request : client request - * @param client_buffer_reader : buffer to rewrite request * @param is_single_shard_db_table: * @param real_database_name : real database name in Server * @param logic_db_info : config info for database * */ -int ObProxyShardUtils::testload_check_and_rewrite_testload_request(ObClientSessionInfo &session_info, - ObProxyMysqlRequest &client_request, - ObIOBufferReader &client_buffer_reader, +int ObProxyShardUtils::testload_check_and_rewrite_testload_request(ObSqlParseResult &parse_result, bool is_single_shard_db_table, const ObString &hint_table, const ObString &real_database_name, - ObDbConfigLogicDb &logic_db_info) + ObDbConfigLogicDb &logic_db_info, + const ObString& sql, + common::ObSqlString& new_sql) { int ret = OB_SUCCESS; UNUSED(is_single_shard_db_table); - ObSqlParseResult &parse_result = client_request.get_parse_result(); - ObString sql = client_request.get_sql(); - common::ObSqlString new_sql; //init by default const char *sql_ptr = sql.ptr(); int64_t sql_len = sql.length(); ObArenaAllocator allocator; @@ -865,30 +852,13 @@ int ObProxyShardUtils::testload_check_and_rewrite_testload_request(ObClientSessi } } LOG_DEBUG("ObProxyShardUtils::check_and_rewrite_testload_request all", K(ret), K(new_sql)); - //rewrite sql base on new_sql - if (OB_SUCC(ret)) { - if (OB_FAIL(client_buffer_reader.consume_all())) { - LOG_WARN("fail to consume all", K(ret)); - } else { - ObMIOBuffer *writer = client_buffer_reader.mbuf_; - if (OB_ISNULL(writer)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null values ", K(writer), K(ret)); - // no need compress here, if server session support compress, it will compress later - } else if (OB_FAIL(ObMysqlRequestBuilder::build_mysql_request(*writer, obmysql::OB_MYSQL_COM_QUERY, new_sql.string(), false, false))) { - LOG_WARN("fail to build_mysql_request", K(new_sql), K(ret)); - } else if (OB_FAIL(ObProxySessionInfoHandler::rewrite_query_req_by_sharding(session_info, client_request, client_buffer_reader))) { - LOG_WARN("fail to rewrite_query_req_by_sharding", K(ret)); - } - } - } -//*/ + return ret; } -bool ObProxyShardUtils::is_special_db(ObMysqlTransact::ObTransState &s) +bool ObProxyShardUtils::is_special_db(obutils::ObSqlParseResult& parse_result) { - const ObString &database_name = s.trans_info_.client_request_.get_parse_result().get_origin_database_name(); + const ObString &database_name = parse_result.get_origin_database_name(); if (!database_name.empty() && 0 == database_name.case_compare("information_schema")) { return true; } @@ -971,19 +941,73 @@ int ObProxyShardUtils::check_shard_request(ObMysqlClientSession &client_session, return ret; } -int ObProxyShardUtils::get_shard_hint(ObDbConfigLogicDb &logic_db_info, +int ObProxyShardUtils::get_shard_hint(const ObString &table_name, + ObClientSessionInfo &session_info, + ObDbConfigLogicDb &logic_db_info, ObSqlParseResult &parse_result, int64_t &group_index, int64_t &tb_index, - int64_t &es_index, ObString &table_name, + int64_t &es_index, ObString &hint_table_name, ObTestLoadType &testload_type) { int ret = OB_SUCCESS; + + bool is_sticky_session = false; + + if (OB_FAIL(get_shard_hint(logic_db_info, parse_result, + group_index, tb_index, es_index, + hint_table_name, testload_type, + is_sticky_session))) { + LOG_WARN("fail to get shard hint", K(ret)); + } else if (is_sticky_session) { + group_index = session_info.get_group_id(); + tb_index = session_info.get_table_id(); + es_index = session_info.get_es_id(); + + if (group_index == OBPROXY_MAX_DBMESH_ID) { + group_index = 0; + } + + if (tb_index == OBPROXY_MAX_DBMESH_ID) { + tb_index = 0; + } + + if (es_index == OBPROXY_MAX_DBMESH_ID) { + es_index = 0; + } + + if (tb_index == 0 && group_index > 0) { + tb_index = group_index; + } + } + + if (OB_SUCC(ret) && !logic_db_info.is_single_shard_db_table()) { + ObShardRule *logic_tb_info = NULL; + if (OB_FAIL(logic_db_info.get_shard_rule(logic_tb_info, table_name))) { + LOG_WARN("fail to get shard rule", K(table_name), K(ret)); + } else if (group_index != OBPROXY_MAX_DBMESH_ID && group_index >= logic_tb_info->db_size_) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("sql with group hint and greater than db size", + "db_size", logic_tb_info->db_size_, K(group_index), K(ret)); + } + } + + return ret; +} + +int ObProxyShardUtils::get_shard_hint(ObDbConfigLogicDb &logic_db_info, + ObSqlParseResult &parse_result, + int64_t &group_index, int64_t &tb_index, + int64_t &es_index, ObString &hint_table_name, + ObTestLoadType &testload_type, + bool &is_sticky_session) +{ + int ret = OB_SUCCESS; DbMeshRouteInfo &odp_route_info = parse_result.get_dbmesh_route_info(); DbpRouteInfo &dbp_route_info = parse_result.get_dbp_route_info(); if (odp_route_info.is_valid()) { group_index = parse_result.get_dbmesh_route_info().group_idx_; - table_name = parse_result.get_dbmesh_route_info().table_name_; - if (table_name.empty()) { + hint_table_name = parse_result.get_dbmesh_route_info().table_name_; + if (hint_table_name.empty()) { tb_index = parse_result.get_dbmesh_route_info().tb_idx_; } es_index = parse_result.get_dbmesh_route_info().es_idx_; @@ -998,7 +1022,9 @@ int ObProxyShardUtils::get_shard_hint(ObDbConfigLogicDb &logic_db_info, } else if (dbp_route_info.is_valid()) { if (parse_result.get_dbp_route_info().is_group_info_valid()) { group_index = dbp_route_info.group_idx_; - table_name = dbp_route_info.table_name_; + hint_table_name = dbp_route_info.table_name_; + } else if (parse_result.get_dbp_route_info().sticky_session_) { + is_sticky_session = true; } } return ret; @@ -1018,6 +1044,172 @@ bool ObProxyShardUtils::is_read_stmt(ObClientSessionInfo &session_info, ObMysqlT || parse_result.has_explain())); } +bool ObProxyShardUtils::is_unsupport_type_in_multi_stmt(ObSqlParseResult& parse_result) +{ + return parse_result.is_shard_special_cmd() + || ObProxyShardUtils::is_special_db(parse_result) + || parse_result.is_ddl_stmt() + || parse_result.is_multi_stmt() + || parse_result.is_show_tables_stmt() + || parse_result.is_show_full_tables_stmt() + || parse_result.is_show_table_status_stmt(); +} + +int ObProxyShardUtils::handle_information_schema_request(ObMysqlClientSession &client_session, + ObMysqlTransact::ObTransState &trans_state, + ObIOBufferReader &client_buffer_reader) +{ + int ret = OB_SUCCESS; + + ObProxyMysqlRequest &client_request = trans_state.trans_info_.client_request_; + ObSqlParseResult &parse_result = client_request.get_parse_result(); + SqlFieldResult& sql_result = parse_result.get_sql_filed_result(); + ObProxySqlParser sql_parser; + ObString sql = client_request.get_parse_sql(); + ObProxyDMLStmt *dml_stmt = NULL; + if (OB_FAIL(sql_parser.parse_sql_by_obparser(sql, NORMAL_PARSE_MODE, parse_result, true))) { + LOG_WARN("parse_sql_by_obparser failed", K(ret), K(sql)); + } else if (OB_ISNULL(dml_stmt = dynamic_cast(parse_result.get_proxy_stmt()))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("dml stmt is null, unexpected", K(ret)); + } else { + ObClientSessionInfo &cs_info = client_session.get_session_info(); + ObDbConfigLogicDb *logic_db_info = NULL; + ObShardConnector *shard_conn = NULL; + bool is_rewrite_sql = false; + bool is_single_shard_db_table = false; + + common::ObSqlString new_sql; + const char *sql_ptr = sql.ptr(); + int64_t sql_len = sql.length(); + int64_t copy_pos = 0; + + ObString last_database_name; + char real_database_name[OB_MAX_DATABASE_NAME_LENGTH]; + char real_table_name[OB_MAX_TABLE_NAME_LENGTH]; + + ObProxyDMLStmt::DbTablePosArray &db_table_pos_array = dml_stmt->get_db_table_pos_array(); + std::sort(db_table_pos_array.begin(), db_table_pos_array.end()); + + for (int64_t i = 0; OB_SUCC(ret) && i < db_table_pos_array.count(); i++) { + ObProxyDbTablePos &db_table_pos = db_table_pos_array.at(i); + if (SHARDING_POS_DB == db_table_pos.get_type()) { + const ObString &database_name = db_table_pos.get_name(); + + if (last_database_name.empty()) { + last_database_name = database_name; + } else if (0 != last_database_name.case_compare(database_name)) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("do not support two schema", K(database_name), K(last_database_name), K(ret)); + } + + if (OB_SUCC(ret) && NULL == shard_conn) { + ObShardConnector *prev_shard_conn = cs_info.get_shard_connector(); + ObString logic_tenant_name; + ObDbConfigCache &dbconfig_cache = get_global_dbconfig_cache(); + if (OB_ISNULL(prev_shard_conn)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("prev shard connector info is null", K(ret)); + } else if (OB_FAIL(cs_info.get_logic_tenant_name(logic_tenant_name))) { + ret = OB_ERR_UNEXPECTED; // no need response, just return ret and disconnect + LOG_ERROR("fail to get logic tenant name", K(ret)); + } else if (OB_ISNULL(logic_db_info = dbconfig_cache.get_exist_db_info(logic_tenant_name, database_name))) { + ret = OB_ERR_BAD_DATABASE; + LOG_WARN("database not exist", K(logic_tenant_name), K(database_name)); + } else if (OB_FAIL(logic_db_info->get_first_group_shard_connector(shard_conn, OBPROXY_MAX_DBMESH_ID, false, TESTLOAD_NON))) { + LOG_WARN("fail to get random shard connector", K(ret), KPC(logic_db_info)); + } else if (*prev_shard_conn != *shard_conn) { + if (OB_FAIL(change_connector(*logic_db_info, client_session, trans_state, prev_shard_conn, shard_conn))) { + LOG_WARN("fail to change connector", KPC(prev_shard_conn), KPC(shard_conn), K(ret)); + } + } + + if (OB_SUCC(ret)) { + snprintf(real_database_name, OB_MAX_DATABASE_NAME_LENGTH, "%.*s", + shard_conn->database_name_.length(), shard_conn->database_name_.ptr()); + is_single_shard_db_table = logic_db_info->is_single_shard_db_table(); + } + } + } + } + + if (OB_SUCC(ret) && last_database_name.empty()) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("do not support zero schema", K(ret)); + } + + for (int64_t i = 0; OB_SUCC(ret) && i < db_table_pos_array.count(); i++) { + ObProxyDbTablePos &db_table_pos = db_table_pos_array.at(i); + if (SHARDING_POS_DB == db_table_pos.get_type()) { + const ObString &database_name = db_table_pos.get_name(); + int32_t database_pos = db_table_pos.get_pos(); + if (OB_FAIL(rewrite_shard_request_db(sql_ptr, database_pos, 0, database_name.length(), + real_database_name, cs_info.is_oracle_mode(), + is_single_shard_db_table, new_sql, copy_pos))) { + LOG_WARN("fail to rewrite db", K(ret)); + } else { + is_rewrite_sql = true; + } + } else if (!is_single_shard_db_table && SHARDING_POS_TABLE == db_table_pos.get_type()) { + int32_t table_pos = db_table_pos.get_pos(); + const ObString &table_name = db_table_pos.get_name(); + int64_t tb_index = 0; + ObTestLoadType testload_type = TESTLOAD_NON; + ObString hint_table; + if (OB_FAIL(logic_db_info->get_real_table_name(table_name, sql_result, + real_table_name, OB_MAX_TABLE_NAME_LENGTH, + tb_index, hint_table, testload_type))) { + if (OB_ENTRY_NOT_EXIST == ret) { + // If the table does not exist, ignore the table name + ret = OB_SUCCESS; + } else { + LOG_WARN("fail to get real table name", K(table_name), K(tb_index), K(testload_type), K(ret)); + } + } else if (OB_FAIL(rewrite_shard_request_table_no_db(sql_ptr, table_pos, table_name.length(), real_table_name, + cs_info.is_oracle_mode(), is_single_shard_db_table, + new_sql, copy_pos))) { + LOG_WARN("fail to rewrite table", K(ret)); + } else { + is_rewrite_sql = true; + } + } + } + + if (OB_SUCC(ret) && is_rewrite_sql) { + const uint32_t PARSE_EXTRA_CHAR_NUM = 2; + new_sql.append(sql_ptr + copy_pos, sql_len - copy_pos - PARSE_EXTRA_CHAR_NUM); + + // 4. push reader forward by consuming old buffer and write new sql into buffer + if (OB_FAIL(client_buffer_reader.consume_all())) { + LOG_WARN("fail to consume all", K(ret)); + } else { + ObMIOBuffer *writer = client_buffer_reader.mbuf_; + if (OB_ISNULL(writer)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null values ", K(writer), K(ret)); + // no need compress here, if server session support compress, it will compress later + } else if (OB_FAIL(ObMysqlRequestBuilder::build_mysql_request(*writer, obmysql::OB_MYSQL_COM_QUERY, new_sql.string(), false, false))) { + LOG_WARN("fail to build_mysql_request", K(new_sql), K(ret)); + } else if (OB_FAIL(ObProxySessionInfoHandler::rewrite_query_req_by_sharding(cs_info, client_request, client_buffer_reader))) { + LOG_WARN("fail to rewrite_query_req_by_sharding", K(ret)); + } + } + } + + if (NULL != shard_conn) { + shard_conn->dec_ref(); + shard_conn = NULL; + } + + if (NULL != logic_db_info) { + logic_db_info->dec_ref(); + logic_db_info = NULL; + } + } + + return ret; +} + /* * if no table name * use last shard connector @@ -1036,8 +1228,13 @@ bool ObProxyShardUtils::is_read_stmt(ObClientSessionInfo &session_info, ObMysqlT */ int ObProxyShardUtils::do_handle_single_shard_request(ObMysqlClientSession &client_session, ObMysqlTransact::ObTransState &trans_state, - ObIOBufferReader &client_buffer_reader, - ObDbConfigLogicDb &logic_db_info) + ObDbConfigLogicDb &logic_db_info, + const ObString& sql, + ObSqlString& new_sql, + ObSqlParseResult &parse_result, + int64_t& es_index, + int64_t& group_index, + const int64_t last_es_index) { int ret = OB_SUCCESS; @@ -1047,30 +1244,19 @@ int ObProxyShardUtils::do_handle_single_shard_request(ObMysqlClientSession &clie ObShardConnector *shard_conn = NULL; ObShardConnector *prev_shard_conn = session_info.get_shard_connector(); - ObProxyMysqlRequest &client_request = trans_state.trans_info_.client_request_; - ObSqlParseResult &parse_result = client_request.get_parse_result(); - ObString table_name = client_request.get_parse_result().get_origin_table_name(); - int64_t group_index = OBPROXY_MAX_DBMESH_ID; + ObString table_name = parse_result.get_origin_table_name(); + es_index = OBPROXY_MAX_DBMESH_ID; + group_index = OBPROXY_MAX_DBMESH_ID; int64_t tb_index = OBPROXY_MAX_DBMESH_ID; - int64_t es_index = OBPROXY_MAX_DBMESH_ID; ObTestLoadType testload_type = TESTLOAD_NON; ObString hint_table; bool is_need_rewrite_sql = false; bool is_skip_rewrite_check = false; - bool is_need_skip_router = false; + bool is_sticky_session = false; if (OB_FAIL(get_shard_hint(logic_db_info, parse_result, - group_index, tb_index, es_index, hint_table, testload_type))) { + group_index, tb_index, es_index, hint_table, testload_type, is_sticky_session))) { LOG_WARN("fail to get shard hint", K(ret)); } else { - // some case can skip route: - // 1. if specify group_index, tb_index, es_index - // 2. if in trans, use last shard connector - // 3. special sql, use last shard connector - is_need_skip_router = (!(OBPROXY_MAX_DBMESH_ID != es_index && 0 != es_index) - && ((is_sharding_in_trans(session_info, trans_state)) - || parse_result.is_show_tables_stmt() - || (parse_result.is_select_stmt() && parse_result.has_last_insert_id()))); - // some case can skip rewrite check: // 1. if sql have table name, can not skip // 2. if sql have no table name @@ -1079,6 +1265,8 @@ int ObProxyShardUtils::do_handle_single_shard_request(ObMysqlClientSession &clie // 2.3 COMMIT // 2.4 ROLLBACK is_skip_rewrite_check = table_name.empty() && (parse_result.is_show_tables_stmt() + || parse_result.is_show_full_tables_stmt() + || parse_result.is_show_table_status_stmt() || (parse_result.is_select_stmt() && parse_result.has_last_insert_id()) || parse_result.is_commit_stmt() || parse_result.is_rollback_stmt()); @@ -1086,7 +1274,7 @@ int ObProxyShardUtils::do_handle_single_shard_request(ObMysqlClientSession &clie // 1. sql have db // 2. have testload flag // 3. specify table in hint - is_need_rewrite_sql = (!is_skip_rewrite_check) && (!client_request.get_parse_result().get_origin_database_name().empty() + is_need_rewrite_sql = (!is_skip_rewrite_check) && (!parse_result.get_origin_database_name().empty() || TESTLOAD_NON != testload_type || !hint_table.empty()); @@ -1096,156 +1284,328 @@ int ObProxyShardUtils::do_handle_single_shard_request(ObMysqlClientSession &clie || (is_need_rewrite_sql && table_name.empty())) { ret = OB_NOT_SUPPORTED; LOG_WARN("sql with dbmesh route hint and no table name is unsupported", K(tb_index), K(group_index), K(is_need_rewrite_sql), K(ret)); - } + } } if (OB_SUCC(ret)) { char real_table_name[OB_MAX_TABLE_NAME_LENGTH]; char real_database_name[OB_MAX_DATABASE_NAME_LENGTH]; - if (!is_need_skip_router) { - bool is_read_stmt = ObProxyShardUtils::is_read_stmt(session_info, trans_state, parse_result); + // The write request takes the write weight, and the request in the transaction is considered to be write + // Read Request Walk Weight + bool is_read_stmt = ObProxyShardUtils::is_read_stmt(session_info, trans_state, parse_result); - if (OB_FAIL(logic_db_info.get_single_table_info(table_name, shard_conn, - real_database_name, OB_MAX_DATABASE_NAME_LENGTH, - real_table_name, OB_MAX_TABLE_NAME_LENGTH, - group_index, tb_index, es_index, - hint_table, testload_type, is_read_stmt))) { - LOG_WARN("shard tpo info is null", K(ret)); - } else if (OB_ISNULL(shard_conn) || OB_ISNULL(prev_shard_conn)) { - ret = OB_EXPR_CALC_ERROR; - LOG_WARN("shard connector info or prev shard connector info is null", KP(shard_conn), - KP(prev_shard_conn), K(ret)); - } else if (*prev_shard_conn != *shard_conn) { - if (OB_FAIL(change_connector(logic_db_info, client_session, trans_state, prev_shard_conn, shard_conn))) { - LOG_WARN("fail to change connector", KPC(prev_shard_conn), KPC(shard_conn), K(ret)); - } - } - if (OB_NOT_NULL(shard_conn)) { - shard_conn->dec_ref(); - shard_conn = NULL; - } - } else { // is_need_skip_router == true, write new table_name and database_name - if (OB_NOT_NULL(prev_shard_conn) && OB_FAIL(logic_db_info.get_single_real_table_info(table_name, *prev_shard_conn, - real_database_name, OB_MAX_DATABASE_NAME_LENGTH, - real_table_name, OB_MAX_TABLE_NAME_LENGTH, - hint_table))) { - LOG_WARN("fail to get real table info", K(table_name), K(ret)); - } else if (OB_ISNULL(prev_shard_conn)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("shard previous connection info is null to use", K(is_need_skip_router), K(ret)); + if (OB_FAIL(logic_db_info.get_single_table_info(table_name, shard_conn, + real_database_name, OB_MAX_DATABASE_NAME_LENGTH, + real_table_name, OB_MAX_TABLE_NAME_LENGTH, + group_index, tb_index, es_index, + hint_table, testload_type, is_read_stmt, last_es_index))) { + LOG_WARN("shard tpo info is null", K(ret)); + } else if (OB_ISNULL(shard_conn) || OB_ISNULL(prev_shard_conn)) { + ret = OB_EXPR_CALC_ERROR; + LOG_WARN("shard connector info or prev shard connector info is null", KP(shard_conn), + KP(prev_shard_conn), K(ret)); + } else if (*prev_shard_conn != *shard_conn) { + if (OB_FAIL(change_connector(logic_db_info, client_session, trans_state, prev_shard_conn, shard_conn))) { + LOG_WARN("fail to change connector", KPC(prev_shard_conn), KPC(shard_conn), K(ret)); } } + if (OB_NOT_NULL(shard_conn)) { + shard_conn->dec_ref(); + shard_conn = NULL; + } - if (!is_skip_rewrite_check) { - LOG_DEBUG("check_and_rewrite_testload_request", K(testload_type), K(ret)); - if (OB_SUCC(ret) && TESTLOAD_ALIPAY_COMPATIBLE == testload_type && hint_table.empty()) { /* testload = 8 */ - ret = OB_ERR_TESTLOAD_ALIPAY_COMPATIBLE; - LOG_WARN("not have table_name's hint for 'testload=8' (TESTLOAD_ALIPAY_COMPATIBLE)", K(ret)); - } else if (OB_SUCC(ret) && TESTLOAD_NON != testload_type) { //rewrite table name for testload - ObProxySqlParser sql_parser; - ObSqlParseResult &sql_parse_result = client_request.get_parse_result(); - ObString sql = client_request.get_parse_sql(); - if (OB_FAIL(sql_parser.parse_sql_by_obparser(sql, NORMAL_PARSE_MODE, sql_parse_result, false))) { - LOG_WARN("parse_sql_by_obparser failed", K(ret), K(sql)); - } else if (OB_FAIL(testload_check_and_rewrite_testload_request(session_info, client_request, client_buffer_reader, - false, hint_table, ObString::make_string(real_database_name), logic_db_info))) { - LOG_WARN("fail to check and rewrite testload request"); + if (OB_SUCC(ret)) { + if (!is_skip_rewrite_check) { + if (TESTLOAD_ALIPAY_COMPATIBLE == testload_type && hint_table.empty()) { /* testload = 8 */ + ret = OB_ERR_TESTLOAD_ALIPAY_COMPATIBLE; + LOG_WARN("not have table_name's hint for 'testload=8' (TESTLOAD_ALIPAY_COMPATIBLE)", K(ret)); + } else if (TESTLOAD_NON != testload_type) { //rewrite table name for testload + LOG_DEBUG("check_and_rewrite_testload_request", K(testload_type), K(ret)); + ObProxySqlParser sql_parser; + if (OB_FAIL(sql_parser.parse_sql_by_obparser(ObProxyMysqlRequest::get_parse_sql(sql), + NORMAL_PARSE_MODE, parse_result, false))) { + LOG_WARN("parse_sql_by_obparser failed", K(ret), K(sql)); + } else if (OB_FAIL(testload_check_and_rewrite_testload_request(parse_result, false, hint_table, + ObString::make_string(real_database_name), + logic_db_info, sql, new_sql))) { + LOG_WARN("fail to check and rewrite testload request"); + } + } else if (is_need_rewrite_sql) { + if (OB_FAIL(rewrite_shard_request(session_info, parse_result, table_name, + logic_db_info.db_name_.config_string_, ObString::make_string(real_table_name), + ObString::make_string(real_database_name), true, sql, new_sql))) { + LOG_WARN("fail to rewrite shard request", K(ret), K(table_name), + K(logic_db_info.db_name_), K(real_table_name), K(real_database_name)); + } } else { - is_need_rewrite_sql = false; - LOG_DEBUG("check and rewrite testload data"); - } - } - - if (OB_SUCC(ret) && is_need_rewrite_sql) { - if (OB_FAIL(rewrite_shard_request(session_info, client_request, client_buffer_reader, - table_name, logic_db_info.db_name_.config_string_, ObString::make_string(real_table_name), - ObString::make_string(real_database_name), true))) { - LOG_WARN("fail to rewrite shard request", K(ret), K(table_name), - K(logic_db_info.db_name_), K(real_table_name), K(real_database_name)); + //no need to rewrite sql, just append to new sql; + ret = new_sql.append(sql); + LOG_DEBUG("not need to rewrite sql by rules", K(real_database_name), K(real_table_name)); } + } else { + //no need to rewrite sql, just append to new sql; + ret = new_sql.append(sql); + LOG_DEBUG("not need to rewrite sql by rules", K(real_database_name), K(real_table_name)); } - } else { - LOG_DEBUG("not need to rewrite sql by rules", K(real_database_name), K(real_table_name)); - } + } } - return ret; } -int ObProxyShardUtils::handle_single_shard_request(ObMysqlSM *sm, - ObMysqlClientSession &client_session, +int ObProxyShardUtils::handle_single_shard_request(ObMysqlClientSession &client_session, ObMysqlTransact::ObTransState &trans_state, ObIOBufferReader &client_buffer_reader, - ObDbConfigLogicDb &logic_db_info, - bool &need_wait_callback) + ObDbConfigLogicDb &logic_db_info) { int ret = OB_SUCCESS; + ObClientSessionInfo &session_info = client_session.get_session_info(); ObProxyMysqlRequest &client_request = trans_state.trans_info_.client_request_; - ObSqlParseResult &parse_result = client_request.get_parse_result(); - const ObString runtime_env = get_global_proxy_config().runtime_env.str(); - if (parse_result.is_ddl_stmt() && 0 == runtime_env.case_compare(OB_PROXY_DBP_RUNTIME_ENV)) { - if (OB_FAIL(handle_ddl_request(sm, client_session, trans_state, logic_db_info, need_wait_callback))) { - LOG_WARN("fail to handle ddl request", K(ret)); + ObSqlParseResult &origin_parse_result = client_request.get_parse_result(); + ObString origin_sql = client_request.get_sql();//should not use get_parse_sql() + ObSqlString new_sql; + ObSEArray sql_array; + ObArenaAllocator &allocator = origin_parse_result.allocator_; + char * multi_sql_buf = NULL; + int64_t es_index = OBPROXY_MAX_DBMESH_ID; + int64_t group_index = OBPROXY_MAX_DBMESH_ID; + int64_t last_es_index = OBPROXY_MAX_DBMESH_ID; + int64_t last_group_index = OBPROXY_MAX_DBMESH_ID; + if (OB_FAIL(ObProxySqlParser::split_multiple_stmt(origin_sql, sql_array))) { + LOG_WARN("fail to split sql", K(ret)); + } else if (OB_UNLIKELY(sql_array.count() <= 0)){ + ret = OB_ERR_PARSER_SYNTAX; + LOG_WARN("fail to split sql and the sql num is wrong", K(ret)); + } else if (OB_UNLIKELY((sql_array.count() > 1) + && OB_FAIL(ObProxySqlParser::preprocess_multi_stmt(allocator, + multi_sql_buf, + origin_sql.length(), + sql_array)))) { + LOG_WARN("fail to preprocess multi stmt", K(ret)); + } else { + bool is_multi_stmt = sql_array.count() > 1; + ObSqlParseResult parse_result; + ObSqlParseResult* real_parse_result = NULL; + ObProxySqlParser sql_parser; + for (int64_t i = 0; OB_SUCC(ret) && i < sql_array.count(); ++i) { + const ObString& sql = sql_array.at(i); + if (0 == i) { + real_parse_result = &origin_parse_result; + } else if (OB_FAIL(sql_parser.parse_sql(ObProxyMysqlRequest::get_parse_sql(sql), + NORMAL_PARSE_MODE/*parse_mode*/, parse_result, + false/*use_lower_case_name*/, + static_cast(client_session.get_session_info().get_collation_connection()), + false/*drop_origin_db_table_name*/, + true /*is sharding user*/))) { + LOG_WARN("fail to handle single shard request for single sql", K(ret), K(sql)); + } else { + real_parse_result = &parse_result; + } + + if (OB_SUCC(ret)) { + if (OB_UNLIKELY(real_parse_result->is_invalid_stmt() && real_parse_result->has_shard_comment())) { + ret = OB_ERR_PARSER_SYNTAX; + LOG_WARN("fail to parse shard sql with shard comment","sql", client_request.get_sql(), K(ret)); + } else if (OB_UNLIKELY(is_multi_stmt && ObProxyShardUtils::is_unsupport_type_in_multi_stmt(*real_parse_result))) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("unsupport type in multi stmt", K(ret), K(sql)); + } else if (OB_FAIL(do_handle_single_shard_request(client_session, trans_state, logic_db_info, sql, new_sql, + *real_parse_result, es_index, group_index, last_es_index))) { + LOG_WARN("fail to handle single shard request for single sql", K(ret), K(sql), K(new_sql)); + } else if (OB_UNLIKELY((i > 0) && ((es_index != last_es_index) || (group_index != last_group_index)))) { + ret = OB_ERR_DISTRIBUTED_NOT_SUPPORTED; + LOG_WARN("different elastic index or group index for multi stmt is not supported", K(es_index), K(last_es_index), K(group_index), + K(last_group_index), K(sql), K(new_sql), K(ret)); + } else { + last_es_index = es_index; + last_group_index = group_index; + if (i > 0) { + real_parse_result->reset(); + } + } + } + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(build_shard_request_packet(session_info, client_request, client_buffer_reader, new_sql.string()))) { + LOG_WARN("fail to build sharding request packet", K(ret)); } - } else if (OB_FAIL(do_handle_single_shard_request(client_session, trans_state, - client_buffer_reader, logic_db_info))) { - LOG_WARN("fail to handle single shard request", K(ret)); + } + + if(NULL != multi_sql_buf) { + allocator.free(multi_sql_buf); } return ret; } -int ObProxyShardUtils::handle_shard_request(ObMysqlSM *sm, - ObMysqlClientSession &client_session, - ObMysqlTransact::ObTransState &trans_state, - ObIOBufferReader &client_buffer_reader, - ObDbConfigLogicDb &db_info, - bool &need_wait_callback) +int ObProxyShardUtils::handle_shard_request(ObMysqlClientSession &client_session, + ObMysqlTransact::ObTransState &trans_state, + ObIOBufferReader &client_buffer_reader, + ObDbConfigLogicDb &logic_db_info) { int ret = OB_SUCCESS; + ObClientSessionInfo &session_info = client_session.get_session_info(); session_info.set_enable_reset_db(false); ObProxyMysqlRequest &client_request = trans_state.trans_info_.client_request_; - ObSqlParseResult &parse_result = client_request.get_parse_result(); - ObString table_name = client_request.get_parse_result().get_origin_table_name(); - if (parse_result.is_ddl_stmt()) { - const ObString runtime_env = get_global_proxy_config().runtime_env.str(); - if (0 == runtime_env.case_compare(OB_PROXY_DBP_RUNTIME_ENV)) { - if (OB_FAIL(handle_ddl_request(sm, client_session, trans_state, db_info, need_wait_callback))) { - LOG_WARN("fail to handle ddl request", K(ret)); + ObSqlParseResult &origin_parse_result = client_request.get_parse_result(); + ObString first_table_name = origin_parse_result.get_origin_table_name(); + ObString origin_sql = client_request.get_sql();//should not use get_parse_sql() + ObSqlString new_sql; + ObSEArray sql_array; + ObArenaAllocator &allocator = origin_parse_result.allocator_; + char * multi_sql_buf = NULL; + int64_t es_index = OBPROXY_MAX_DBMESH_ID; + int64_t group_index = OBPROXY_MAX_DBMESH_ID; + int64_t last_es_index = OBPROXY_MAX_DBMESH_ID; + int64_t last_group_index = OBPROXY_MAX_DBMESH_ID; + bool is_scan_all = false; + + if (OB_FAIL(ObProxySqlParser::split_multiple_stmt(origin_sql, sql_array))) { + LOG_WARN("fail to split sql", K(ret)); + } else if (OB_UNLIKELY(sql_array.count() <= 0)){ + ret = OB_ERR_PARSER_SYNTAX; + LOG_WARN("fail to split sql and the sql num is wrong", K(ret)); + } else if (OB_UNLIKELY((sql_array.count() > 1) + && OB_FAIL(ObProxySqlParser::preprocess_multi_stmt(allocator, + multi_sql_buf, + origin_sql.length(), + sql_array)))) { + LOG_WARN("fail to preprocess multi stmt", K(ret)); + } else { + bool is_multi_stmt = sql_array.count() > 1; + ObSqlParseResult parse_result; + ObSqlParseResult* real_parse_result = NULL; + ObProxySqlParser sql_parser; + for (int64_t i = 0; OB_SUCC(ret) && i < sql_array.count(); ++i) { + const ObString& sql = sql_array.at(i); + if (0 == i) { + real_parse_result = &origin_parse_result; + } else if (OB_FAIL(sql_parser.parse_sql(ObProxyMysqlRequest::get_parse_sql(sql), + NORMAL_PARSE_MODE/*parse_mode*/, parse_result, + false/*use_lower_case_name*/, + static_cast(client_session.get_session_info().get_collation_connection()), + false/*drop_origin_db_table_name*/, + true /*is sharding user*/))) { + LOG_WARN("fail to handle single shard request for single sql", K(ret), K(sql)); + } else { + real_parse_result = &parse_result; + } + + if (OB_SUCC(ret)) { + if (OB_UNLIKELY(real_parse_result->is_invalid_stmt() && real_parse_result->has_shard_comment())) { + ret = OB_ERR_PARSER_SYNTAX; + LOG_WARN("fail to parse shard sql with shard comment","sql", client_request.get_sql(), K(ret)); + } else if (OB_UNLIKELY(is_multi_stmt && ObProxyShardUtils::is_unsupport_type_in_multi_stmt(*real_parse_result))) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("unsupport type in multi stmt", K(ret), K(sql)); + } else if (OB_FAIL(do_handle_shard_request(client_session, trans_state, logic_db_info, sql, new_sql, *real_parse_result, + es_index, group_index, last_es_index, is_scan_all))) { + LOG_WARN("fail to handle single shard request for single sql", K(ret), K(sql), K(new_sql)); + } else if (OB_UNLIKELY((i > 0) && ((es_index != last_es_index) || (group_index != last_group_index)))) { + ret = OB_ERR_DISTRIBUTED_NOT_SUPPORTED; + LOG_WARN("different elastic index or group index for multi stmt is not supported", K(es_index), K(last_es_index), K(group_index), + K(last_group_index), K(sql), K(new_sql), K(ret)); + } else if (OB_UNLIKELY(is_multi_stmt && is_scan_all)) { + ret = OB_ERR_DISTRIBUTED_NOT_SUPPORTED; + LOG_WARN("scan all sql in multi stmt is not supported", K(sql), K(new_sql), K(ret)); + } else { + last_es_index = es_index; + last_group_index = group_index; + if (i > 0) { + real_parse_result->reset(); + } + } } - } else { - ret = OB_NOT_SUPPORTED; - LOG_WARN("ddl stmt is unsupported for sharding table", K(ret)); } - } else if (parse_result.is_show_tables_stmt() || (table_name.empty() && !parse_result.is_dml_stmt())) { - //do nothing - } else if (table_name.empty()) { - // keep compatible, skip - } else if (parse_result.is_multi_stmt()) { - ret = OB_NOT_SUPPORTED; - LOG_WARN("multi stmt is unsupported for sharding table", "stmt type", parse_result.get_stmt_type(), K(ret)); - } else if (parse_result.is_show_create_table_stmt() || parse_result.is_desc_table_stmt()) { - if (OB_FAIL(handle_other_request(client_session, trans_state, - client_buffer_reader, table_name, db_info))) { - LOG_WARN("fail to handle other request", K(ret), K(session_info), K(table_name)); + + if (OB_SUCC(ret)) { + if (is_scan_all) { + if (OB_FAIL(handle_scan_all_real_info(logic_db_info, client_session, trans_state, first_table_name))) { + LOG_WARN("fail to handle scan all real info", K(first_table_name), K(ret)); + } + } else { + if (OB_FAIL(build_shard_request_packet(session_info, client_request, client_buffer_reader, new_sql.string()))) { + LOG_WARN("fail to build sharding request packet", K(new_sql), K(ret)); + } + } + } + } + + if(NULL != multi_sql_buf) { + allocator.free(multi_sql_buf); + } + + return ret; +} + +int ObProxyShardUtils::do_handle_shard_request(ObMysqlClientSession &client_session, + ObMysqlTransact::ObTransState &trans_state, + ObDbConfigLogicDb &db_info, + const ObString& sql, + ObSqlString& new_sql, + ObSqlParseResult &parse_result, + int64_t& es_index, + int64_t& group_index, + const int64_t last_es_index, + bool& is_scan_all) +{ + int ret = OB_SUCCESS; + + ObString table_name = parse_result.get_origin_table_name(); + if (OB_UNLIKELY(is_unsupport_type_in_multi_stmt(parse_result) + || table_name.empty())) { + // Let it go for now, keep compatible + new_sql.append(sql); + } else if (parse_result.is_show_stmt() || parse_result.is_desc_table_stmt()) { + if (OB_FAIL(handle_other_request(client_session, trans_state, table_name, db_info, + sql, new_sql, parse_result, es_index, group_index))) { + LOG_WARN("fail to handle other request", K(ret), K(sql), K(new_sql), K(table_name)); } } else if (parse_result.is_select_stmt()) { - if (OB_FAIL(handle_select_request(client_session, trans_state, - client_buffer_reader, table_name, db_info))) { - LOG_WARN("fail to handle select request", K(ret), K(session_info), K(table_name)); + if (OB_FAIL(handle_select_request(client_session, trans_state, table_name, db_info, + sql, new_sql, parse_result, es_index, group_index, last_es_index, is_scan_all))) { + LOG_WARN("fail to handle select request", K(ret), K(sql), K(new_sql), K(table_name)); } } else if (parse_result.is_dml_stmt()) { - if (OB_FAIL(handle_dml_request(client_session, trans_state, - client_buffer_reader, table_name, db_info))) { - LOG_WARN("fail to handle dml request", K(table_name), K(ret)); + if (OB_FAIL(handle_dml_request(client_session, trans_state, table_name, db_info, + sql, new_sql, parse_result, es_index, group_index, last_es_index))) { + LOG_WARN("fail to handle dml request", K(table_name), K(sql), K(new_sql), K(ret)); } } else { ret = OB_NOT_SUPPORTED; LOG_WARN("stmt is unsupported for sharding table", "stmt type", parse_result.get_stmt_type(), K(ret)); + } + + return ret; } + +int ObProxyShardUtils::build_shard_request_packet(ObClientSessionInfo &session_info, + ObProxyMysqlRequest &client_request, + ObIOBufferReader &client_buffer_reader, + const ObString& sql) +{ + int ret = OB_SUCCESS; + + // 4. push reader forward by consuming old buffer and write new sql into buffer + if (OB_FAIL(client_buffer_reader.consume_all())) { + LOG_WARN("fail to consume all", K(ret)); + } else { + ObMIOBuffer *writer = client_buffer_reader.mbuf_; + if (OB_ISNULL(writer)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null values ", K(writer), K(ret)); + // no need compress here, if server session support compress, it will compress later + } else if (OB_FAIL(ObMysqlRequestBuilder::build_mysql_request(*writer, obmysql::OB_MYSQL_COM_QUERY, sql, false, false))) { + LOG_WARN("fail to build_mysql_request", K(sql), K(ret)); + } else if (OB_FAIL(ObProxySessionInfoHandler::rewrite_query_req_by_sharding(session_info, client_request, client_buffer_reader))) { + LOG_WARN("fail to rewrite_query_req_by_sharding", K(ret)); + } + } + return ret; } @@ -1296,25 +1656,29 @@ int ObProxyShardUtils::handle_ddl_request(ObMysqlSM *sm, int ObProxyShardUtils::handle_other_request(ObMysqlClientSession &client_session, ObMysqlTransact::ObTransState &trans_state, - ObIOBufferReader &client_buffer_reader, const ObString &table_name, - ObDbConfigLogicDb &db_info) + ObDbConfigLogicDb &db_info, + const ObString& sql, + ObSqlString& new_sql, + ObSqlParseResult &parse_result, + int64_t& es_index, + int64_t& group_index) { int ret = OB_SUCCESS; ObClientSessionInfo &session_info = client_session.get_session_info(); - ObProxyMysqlRequest &client_request = trans_state.trans_info_.client_request_; char real_table_name[OB_MAX_TABLE_NAME_LENGTH]; char real_database_name[OB_MAX_DATABASE_NAME_LENGTH]; if (OB_FAIL(handle_other_real_info(db_info, client_session, trans_state, table_name, real_database_name, OB_MAX_DATABASE_NAME_LENGTH, - real_table_name, OB_MAX_TABLE_NAME_LENGTH))) { + real_table_name, OB_MAX_TABLE_NAME_LENGTH, + parse_result, es_index, group_index))) { LOG_WARN("fail to handle other real info", K(ret), K(session_info), K(table_name)); - } else if (OB_FAIL(rewrite_shard_request(session_info, client_request, client_buffer_reader, + } else if (OB_FAIL(rewrite_shard_request(session_info, parse_result, table_name, db_info.db_name_.config_string_, ObString::make_string(real_table_name), - ObString::make_string(real_database_name), false))) { + ObString::make_string(real_database_name), false, sql, new_sql))) { LOG_WARN("fail to rewrite shard request", K(ret), K(table_name), K(db_info.db_name_), K(real_table_name), K(real_database_name)); } @@ -1324,19 +1688,20 @@ int ObProxyShardUtils::handle_other_request(ObMysqlClientSession &client_session int ObProxyShardUtils::handle_select_request(ObMysqlClientSession &client_session, ObMysqlTransact::ObTransState &trans_state, - ObIOBufferReader &client_buffer_reader, const ObString &table_name, - ObDbConfigLogicDb &db_info) + ObDbConfigLogicDb &db_info, + const ObString& sql, + ObSqlString& new_sql, + ObSqlParseResult &parse_result, + int64_t& es_index, + int64_t& group_index, + const int64_t last_es_index, + bool& is_scan_all) { int ret = OB_SUCCESS; - ObProxyMysqlRequest &client_request = trans_state.trans_info_.client_request_; - ObSqlParseResult &parse_result = client_request.get_parse_result(); SqlFieldResult& sql_result = parse_result.get_sql_filed_result(); - - bool is_scan_all = false; ObProxySqlParser sql_parser; - ObString sql = client_request.get_parse_sql(); - if (OB_FAIL(sql_parser.parse_sql_by_obparser(sql, NORMAL_PARSE_MODE, parse_result, true))) { + if (OB_FAIL(sql_parser.parse_sql_by_obparser(ObProxyMysqlRequest::get_parse_sql(sql), NORMAL_PARSE_MODE, parse_result, true))) { LOG_WARN("parse_sql_by_obparser failed", K(ret), K(sql)); } else if (FALSE_IT(is_scan_all = need_scan_all(parse_result))) { // impossible @@ -1348,12 +1713,10 @@ int ObProxyShardUtils::handle_select_request(ObMysqlClientSession &client_sessio if (OB_SUCC(ret)) { if (is_scan_all) { - if (OB_FAIL(handle_scan_all_real_info(db_info, client_session, trans_state, table_name))) { - LOG_WARN("fail to handle scan all real info", K(table_name), K(ret)); - } + //handle scan all later } else { - if (OB_FAIL(handle_select_real_info(db_info, client_session, trans_state, - table_name, client_buffer_reader))) { + if (OB_FAIL(handle_dml_real_info(db_info, client_session, trans_state, table_name, + sql, new_sql, parse_result, es_index, group_index, last_es_index))) { LOG_WARN("fail to handle dml real info", K(table_name), K(ret)); } } @@ -1364,33 +1727,22 @@ int ObProxyShardUtils::handle_select_request(ObMysqlClientSession &client_sessio int ObProxyShardUtils::handle_dml_request(ObMysqlClientSession &client_session, ObMysqlTransact::ObTransState &trans_state, - ObIOBufferReader &client_buffer_reader, const ObString &table_name, - ObDbConfigLogicDb &db_info) + ObDbConfigLogicDb &db_info, + const ObString& sql, + ObSqlString& new_sql, + ObSqlParseResult &parse_result, + int64_t& es_index, + int64_t& group_index, + const int64_t last_es_index) { int ret = OB_SUCCESS; - ObClientSessionInfo &session_info = client_session.get_session_info(); - ObProxyMysqlRequest &client_request = trans_state.trans_info_.client_request_; - ObSqlParseResult &parse_result = client_request.get_parse_result(); - char real_table_name[OB_MAX_TABLE_NAME_LENGTH]; - char real_database_name[OB_MAX_DATABASE_NAME_LENGTH]; - - ObCollationType connection_collation = static_cast(client_session.get_session_info().get_collation_connection()); - if (OB_FAIL(ObMysqlRequestAnalyzer::parse_sql_fileds(client_request, connection_collation))) { - LOG_WARN("fail to extract_fileds", K(connection_collation), K(ret)); - } else if ((parse_result.is_insert_stmt() || parse_result.is_replace_stmt() - || parse_result.is_update_stmt()) && parse_result.get_batch_insert_values_count() > 1) { - ret = OB_ERR_BATCH_INSERT_FOUND; - LOG_WARN("batch insert not supported in sharding sql", K(ret), K(parse_result.get_batch_insert_values_count())); - } else if (OB_FAIL(handle_dml_real_info(db_info, client_session, trans_state, table_name, - real_database_name, OB_MAX_DATABASE_NAME_LENGTH, - real_table_name, OB_MAX_TABLE_NAME_LENGTH))) { - LOG_WARN("fail to handle dml real info", K(ret), K(session_info), K(table_name)); - } else if (OB_FAIL(rewrite_shard_request(session_info, client_request, client_buffer_reader, - table_name, db_info.db_name_.config_string_, ObString::make_string(real_table_name), - ObString::make_string(real_database_name), false))) { - LOG_WARN("fail to rewrite shard request", K(ret), K(table_name), - K(db_info.db_name_), K(real_table_name), K(real_database_name)); + ObProxySqlParser sql_parser; + if (OB_FAIL(sql_parser.parse_sql_by_obparser(ObProxyMysqlRequest::get_parse_sql(sql), NORMAL_PARSE_MODE, parse_result, true))) { + LOG_WARN("parse_sql_by_obparser failed", K(ret), K(sql)); + } else if (OB_FAIL(handle_dml_real_info(db_info, client_session, trans_state, table_name, + sql, new_sql, parse_result, es_index, group_index, last_es_index))) { + LOG_WARN("fail to handle dml real info", K(table_name), K(ret)); } return ret; @@ -1401,16 +1753,16 @@ int ObProxyShardUtils::check_topology(ObSqlParseResult &parse_result, { int ret = OB_SUCCESS; - ObProxySelectStmt *select_stmt = static_cast(parse_result.get_proxy_stmt()); - if (OB_ISNULL(select_stmt)) { + ObProxyDMLStmt *dml_stmt = static_cast(parse_result.get_proxy_stmt()); + if (OB_ISNULL(dml_stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("select stmt is null, unexpected", K(ret)); } else { int64_t last_db_size = -1; int64_t last_tb_size = -1; - ObProxySelectStmt::ExprMap &table_exprs_map = select_stmt->get_table_exprs_map(); - ObProxySelectStmt::ExprMap::iterator iter = table_exprs_map.begin(); - ObProxySelectStmt::ExprMap::iterator end = table_exprs_map.end(); + ObProxyDMLStmt::ExprMap &table_exprs_map = dml_stmt->get_table_exprs_map(); + ObProxyDMLStmt::ExprMap::iterator iter = table_exprs_map.begin(); + ObProxyDMLStmt::ExprMap::iterator end = table_exprs_map.end(); for (; OB_SUCC(ret) && iter != end; iter++) { ObProxyExpr *expr = iter->second; @@ -1780,6 +2132,10 @@ int ObProxyShardUtils::get_db_version(const ObString &logic_tenant_name, } else { db_version = logic_db_info->get_version(); } + if (NULL != logic_db_info) { + logic_db_info->dec_ref(); + logic_db_info = NULL; + } return ret; } @@ -1847,26 +2203,27 @@ int ObProxyShardUtils::handle_other_real_info(ObDbConfigLogicDb &logic_db_info, ObMysqlTransact::ObTransState &trans_state, const ObString &table_name, char *real_database_name, int64_t db_name_len, - char *real_table_name, int64_t tb_name_len) + char *real_table_name, int64_t tb_name_len, + ObSqlParseResult &parse_result, + int64_t& es_id, int64_t& group_id) { int ret = OB_SUCCESS; ObShardConnector *shard_conn = NULL; ObClientSessionInfo &cs_info = client_session.get_session_info(); ObShardConnector *prev_shard_conn = cs_info.get_shard_connector(); - ObSqlParseResult &parse_result = trans_state.trans_info_.client_request_.get_parse_result(); ObShardRule *logic_tb_info = NULL; - int64_t group_id = OBPROXY_MAX_DBMESH_ID; + group_id = OBPROXY_MAX_DBMESH_ID; int64_t table_id = OBPROXY_MAX_DBMESH_ID; - int64_t es_id = OBPROXY_MAX_DBMESH_ID; + es_id = OBPROXY_MAX_DBMESH_ID; ObTestLoadType testload_type = TESTLOAD_NON; ObString hint_table; if (OB_ISNULL(prev_shard_conn)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("shard connector info is null", K(ret)); - } else if (OB_FAIL(get_shard_hint(logic_db_info, parse_result, + } else if (OB_FAIL(get_shard_hint(table_name, cs_info, logic_db_info, parse_result, group_id, table_id, es_id, hint_table, testload_type))) { LOG_WARN("fail to get shard hint", K(ret)); // get group_id @@ -1874,21 +2231,24 @@ int ObProxyShardUtils::handle_other_real_info(ObDbConfigLogicDb &logic_db_info, LOG_WARN("fail to get shard rule", K(table_name), K(ret)); } else { int64_t last_group_id = cs_info.get_group_id(); - ObString saved_database_name; cs_info.get_logic_database_name(saved_database_name); bool is_not_saved_database = saved_database_name != logic_db_info.db_name_.config_string_; - // need to re-select a shard_conn condition, and any one of the conditions can be satisfied - // 1. SQL comes with database, and it is different from the current logic library - // 2. The group id is specified in the hint, and it is different from the last time - // 3. No group_id is specified, nor did the last one (for example, switch the library) - // 4. If the last group_id is greater than the db_size of the table of this SQL - // (for example, the table of the previous SQL is group_{00-99}, the table of this SQL is group_00) - if (is_not_saved_database - || (group_id != OBPROXY_MAX_DBMESH_ID && group_id != last_group_id) - || last_group_id == OBPROXY_MAX_DBMESH_ID - || last_group_id >= logic_tb_info->db_size_) { + // If group_id is specified, check if it exceeds db_size and use it + if (group_id != OBPROXY_MAX_DBMESH_ID) { + if (group_id >= logic_tb_info->db_size_) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("sql with group hint and greater than db size", + "db_size", logic_tb_info->db_size_, K(group_id), K(ret)); + } + // If no group_id is specified, and the database accessed by the current SQL is the session database, the last_group_id is used + } else if (!is_not_saved_database && last_group_id < logic_tb_info->db_size_) { + group_id = last_group_id; + es_id = cs_info.get_es_id(); + } + + if (OB_SUCC(ret)) { ObShardTpo *shard_tpo = NULL; ObGroupCluster *gc_info = NULL; if (OB_FAIL(logic_db_info.get_shard_tpo(shard_tpo))) { @@ -1941,15 +2301,6 @@ int ObProxyShardUtils::handle_other_real_info(ObDbConfigLogicDb &logic_db_info, } } } - - //If it is the logic library on the current session, you can reuse this group_id next time - if (OB_SUCC(ret) && !is_not_saved_database) { - cs_info.set_group_id(group_id); - } - } else { - prev_shard_conn->inc_ref(); - shard_conn = prev_shard_conn; - group_id = last_group_id; } if (OB_SUCC(ret)) { @@ -1974,6 +2325,13 @@ int ObProxyShardUtils::handle_other_real_info(ObDbConfigLogicDb &logic_db_info, } } } + + //If it is a logic library on the current session, this group_id can be reused next time + if (OB_SUCC(ret) && !is_not_saved_database) { + cs_info.set_group_id(group_id); + cs_info.set_table_id(table_id); + cs_info.set_es_id(es_id); + } } if (NULL != shard_conn) { @@ -1998,11 +2356,11 @@ int ObProxyShardUtils::handle_scan_all_real_info(ObDbConfigLogicDb &logic_db_inf ObSEArray, 4> table_name_map_array; ObIAllocator *allocator = NULL; - ObProxySelectStmt *select_stmt = static_cast(parse_result.get_proxy_stmt()); - if (OB_ISNULL(select_stmt)) { + ObProxyDMLStmt *dml_stmt = static_cast(parse_result.get_proxy_stmt()); + if (OB_ISNULL(dml_stmt)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("select stmt is null, unexpected", K(ret)); - } else if (select_stmt->has_unsupport_expr_type()) { + LOG_WARN("dml stmt is null, unexpected", K(ret)); + } else if (dml_stmt->has_unsupport_expr_type()) { ret = OB_ERROR_UNSUPPORT_EXPR_TYPE; LOG_WARN("unsupport sql", K(ret)); } else if (OB_FAIL(check_topology(parse_result, logic_db_info))) { @@ -2018,17 +2376,17 @@ int ObProxyShardUtils::handle_scan_all_real_info(ObDbConfigLogicDb &logic_db_inf table_name_map_array))) { LOG_WARN("fail to handle sharding select real info", K(ret), K(table_name)); } else { - LOG_DEBUG("proxy stmt", K(select_stmt->get_stmt_type()), K(select_stmt->limit_offset_), K(select_stmt->limit_size_)); + LOG_DEBUG("proxy stmt", K(dml_stmt->get_stmt_type()), K(dml_stmt->limit_offset_), K(dml_stmt->limit_size_)); LOG_DEBUG("select expr"); - for (int64_t i = 0; i < select_stmt->select_exprs_.count(); i++) { - ObProxyExpr::print_proxy_expr(select_stmt->select_exprs_.at(i)); + for (int64_t i = 0; i < dml_stmt->select_exprs_.count(); i++) { + ObProxyExpr::print_proxy_expr(dml_stmt->select_exprs_.at(i)); } LOG_DEBUG("group by expr"); - for (int64_t i = 0; i < select_stmt->group_by_exprs_.count(); i++) { - ObProxyExpr::print_proxy_expr(select_stmt->group_by_exprs_.at(i)); + for (int64_t i = 0; i < dml_stmt->group_by_exprs_.count(); i++) { + ObProxyExpr::print_proxy_expr(dml_stmt->group_by_exprs_.at(i)); } - for (int64_t i = 0; i < select_stmt->order_by_exprs_.count(); i++) { - ObProxyOrderItem *order_expr = select_stmt->order_by_exprs_.at(i); + for (int64_t i = 0; i < dml_stmt->order_by_exprs_.count(); i++) { + ObProxyOrderItem *order_expr = dml_stmt->order_by_exprs_.at(i); LOG_DEBUG("order by expr", K(order_expr->order_direction_)); ObProxyExpr::print_proxy_expr(order_expr); } @@ -2049,11 +2407,16 @@ int ObProxyShardUtils::handle_scan_all_real_info(ObDbConfigLogicDb &logic_db_inf return ret; } -int ObProxyShardUtils::handle_select_real_info(ObDbConfigLogicDb &logic_db_info, - ObMysqlClientSession &client_session, - ObMysqlTransact::ObTransState &trans_state, - const ObString &table_name, - ObIOBufferReader &client_buffer_reader) +int ObProxyShardUtils::handle_dml_real_info(ObDbConfigLogicDb &logic_db_info, + ObMysqlClientSession &client_session, + ObMysqlTransact::ObTransState &trans_state, + const ObString &table_name, + const ObString& sql, + ObSqlString& new_sql, + ObSqlParseResult &parse_result, + int64_t& es_index, + int64_t& group_index, + const int64_t last_es_index) { int ret = OB_SUCCESS; @@ -2061,14 +2424,12 @@ int ObProxyShardUtils::handle_select_real_info(ObDbConfigLogicDb &logic_db_info, ObClientSessionInfo &session_info = client_session.get_session_info(); ObShardConnector *prev_shard_conn = session_info.get_shard_connector(); - ObProxyMysqlRequest &client_request = trans_state.trans_info_.client_request_; - ObSqlParseResult &parse_result = client_request.get_parse_result(); SqlFieldResult &sql_result = parse_result.get_sql_filed_result(); - ObProxySelectStmt *select_stmt = dynamic_cast(parse_result.get_proxy_stmt()); + ObProxyDMLStmt *dml_stmt = dynamic_cast(parse_result.get_proxy_stmt()); - int64_t group_index = OBPROXY_MAX_DBMESH_ID; + group_index = OBPROXY_MAX_DBMESH_ID; int64_t tb_index = OBPROXY_MAX_DBMESH_ID; - int64_t es_index = OBPROXY_MAX_DBMESH_ID; + es_index = OBPROXY_MAX_DBMESH_ID; ObTestLoadType testload_type = TESTLOAD_NON; ObString hint_table; ObArenaAllocator allocator; @@ -2081,22 +2442,22 @@ int ObProxyShardUtils::handle_select_real_info(ObDbConfigLogicDb &logic_db_info, // read request weight bool is_read_stmt = ObProxyShardUtils::is_read_stmt(session_info, trans_state, parse_result); - if (OB_ISNULL(select_stmt)) { + if (OB_ISNULL(dml_stmt)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("select stmt is null, unexpected", K(ret)); + LOG_WARN("dml stmt is null, unexpected", K(ret)); } else if (OB_FAIL(table_name_map.create(OB_ALIAS_TABLE_MAP_MAX_BUCKET_NUM, ObModIds::OB_HASH_ALIAS_TABLE_MAP))) { LOG_WARN("fail to create table name map", K(ret)); - } else if (OB_FAIL(get_shard_hint(logic_db_info, parse_result, + } else if (OB_FAIL(get_shard_hint(table_name, session_info, logic_db_info, parse_result, group_index, tb_index, es_index, hint_table, testload_type))) { LOG_WARN("fail to get shard hint", K(ret)); } if (OB_SUCC(ret)) { - ObProxySelectStmt::ExprMap &table_exprs_map = select_stmt->get_table_exprs_map(); - ObProxySelectStmt::ExprMap::iterator iter = table_exprs_map.begin(); - ObProxySelectStmt::ExprMap::iterator end = table_exprs_map.end(); + ObProxyDMLStmt::ExprMap &table_exprs_map = dml_stmt->get_table_exprs_map(); + ObProxyDMLStmt::ExprMap::iterator iter = table_exprs_map.begin(); + ObProxyDMLStmt::ExprMap::iterator end = table_exprs_map.end(); if (!hint_table.empty() && table_exprs_map.size() > 1) { ret = OB_ERR_MORE_TABLES_WITH_TABLE_HINT; @@ -2105,7 +2466,7 @@ int ObProxyShardUtils::handle_select_real_info(ObDbConfigLogicDb &logic_db_info, real_database_name, OB_MAX_DATABASE_NAME_LENGTH, real_table_name, OB_MAX_TABLE_NAME_LENGTH, group_index, tb_index, es_index, - hint_table, testload_type, is_read_stmt))) { + hint_table, testload_type, is_read_stmt, last_es_index))) { LOG_WARN("fail to get real info", K(table_name), K(group_index), K(tb_index), K(es_index), K(hint_table), K(testload_type), K(is_read_stmt), K(ret)); } else if (OB_ISNULL(shard_conn) || OB_ISNULL(prev_shard_conn)) { @@ -2138,8 +2499,9 @@ int ObProxyShardUtils::handle_select_real_info(ObDbConfigLogicDb &logic_db_info, } if (OB_SUCC(ret)) { - if (OB_FAIL(rewrite_shard_select_request(session_info, client_request, client_buffer_reader, - table_name_map, ObString::make_string(real_database_name), false))) { + if (OB_FAIL(rewrite_shard_dml_request(sql, new_sql, parse_result, + session_info.is_oracle_mode(), table_name_map, + ObString::make_string(real_database_name), false))) { LOG_WARN("fail to rewrite shard request", K(real_database_name), K(ret)); } } @@ -2157,6 +2519,8 @@ int ObProxyShardUtils::handle_select_real_info(ObDbConfigLogicDb &logic_db_info, bool is_not_saved_database = saved_database_name != logic_db_info.db_name_.config_string_; if (!is_not_saved_database) { session_info.set_group_id(group_index); + session_info.set_table_id(tb_index); + session_info.set_es_id(es_index); } } @@ -2167,58 +2531,8 @@ int ObProxyShardUtils::handle_select_real_info(ObDbConfigLogicDb &logic_db_info, return ret; } -int ObProxyShardUtils::handle_dml_real_info(ObDbConfigLogicDb &logic_db_info, - ObMysqlClientSession &client_session, - ObMysqlTransact::ObTransState &trans_state, - const ObString &table_name, - char *real_database_name, int64_t db_name_len, - char *real_table_name, int64_t tb_name_len) -{ - int ret = OB_SUCCESS; - - ObShardConnector *shard_conn = NULL; - ObClientSessionInfo &session_info = client_session.get_session_info(); - ObShardConnector *prev_shard_conn = session_info.get_shard_connector(); - ObSqlParseResult &parse_result = trans_state.trans_info_.client_request_.get_parse_result(); - int64_t group_id = OBPROXY_MAX_DBMESH_ID; - - bool is_read_stmt = ObProxyShardUtils::is_read_stmt(session_info, trans_state, parse_result); - - if (OB_FAIL(get_real_info(logic_db_info, table_name, parse_result, shard_conn, - real_database_name, db_name_len, - real_table_name, tb_name_len, - &group_id, NULL, NULL, is_read_stmt))) { - LOG_WARN("fail to get real db and tb", K(table_name), K(ret)); - } else if (OB_ISNULL(shard_conn) || OB_ISNULL(prev_shard_conn)) { - ret = OB_EXPR_CALC_ERROR; - LOG_WARN("shard connector info or prev shard connector info is null", KP(shard_conn), - KP(prev_shard_conn), K(ret)); - } - - if (OB_SUCC(ret) && *prev_shard_conn != *shard_conn) { - if (OB_FAIL(change_connector(logic_db_info, client_session, trans_state, prev_shard_conn, shard_conn))) { - LOG_WARN("fail to change connector", KPC(prev_shard_conn), KPC(shard_conn), K(ret)); - } - } - - //There may be a database in SQL, only the logical library saved on the session can save the group_id, and it can be reused next time - if (OB_SUCC(ret)) { - ObString saved_database_name; - session_info.get_logic_database_name(saved_database_name); - bool is_not_saved_database = saved_database_name != logic_db_info.db_name_.config_string_; - if (!is_not_saved_database) { - session_info.set_group_id(group_id); - } - } - - if (NULL != shard_conn) { - shard_conn->dec_ref(); - shard_conn = NULL; - } - return ret; -} - -int ObProxyShardUtils::get_real_info(ObDbConfigLogicDb &logic_db_info, +int ObProxyShardUtils::get_real_info(ObClientSessionInfo &session_info, + ObDbConfigLogicDb &logic_db_info, const ObString &table_name, ObSqlParseResult &parse_result, ObShardConnector *&shard_conn, @@ -2233,7 +2547,7 @@ int ObProxyShardUtils::get_real_info(ObDbConfigLogicDb &logic_db_info, int64_t es_index = OBPROXY_MAX_DBMESH_ID; ObTestLoadType testload_type = TESTLOAD_NON; ObString hint_table; - if (OB_FAIL(get_shard_hint(logic_db_info, parse_result, + if (OB_FAIL(get_shard_hint(table_name, session_info, logic_db_info, parse_result, group_index, tb_index, es_index, hint_table, testload_type))) { LOG_WARN("fail to get shard hint", K(ret)); } else if (OB_FAIL(logic_db_info.get_real_info(table_name, parse_result, shard_conn, @@ -2264,6 +2578,7 @@ int ObProxyShardUtils::is_sharding_in_trans(ObClientSessionInfo &session_info, O { return 0 == session_info.get_cached_variables().get_autocommit() || trans_state.is_hold_start_trans_ + || trans_state.is_hold_xa_start_ || ObMysqlTransact::is_in_trans(trans_state); } @@ -2295,7 +2610,7 @@ bool ObProxyShardUtils::check_shard_authority(const ObShardUserPrivInfo &up_info bret = up_info.priv_set_ & (OB_PRIV_DELETE | OB_PRIV_INSERT); } else if (parse_result.is_delete_stmt()) { bret = up_info.priv_set_ & OB_PRIV_DELETE; - } else if (parse_result.is_create_stmt()) { + } else if (parse_result.is_create_stmt() || parse_result.is_rename_stmt()) { bret = up_info.priv_set_ & OB_PRIV_CREATE; } else if (parse_result.is_alter_stmt()) { bret = up_info.priv_set_ & OB_PRIV_ALTER; @@ -2309,8 +2624,10 @@ bool ObProxyShardUtils::check_shard_authority(const ObShardUserPrivInfo &up_info return bret; } -int ObProxyShardUtils::build_error_packet(int err_code, bool &need_response_for_dml, - ObMysqlTransact::ObTransState &trans_state) +int ObProxyShardUtils::build_error_packet(int err_code, + bool &need_response_for_dml, + ObMysqlTransact::ObTransState &trans_state, + ObMysqlClientSession *client_session) { int ret = OB_SUCCESS; switch (err_code) { @@ -2357,7 +2674,7 @@ int ObProxyShardUtils::build_error_packet(int err_code, bool &need_response_for_ if (need_response_for_dml) { trans_state.mysql_errcode_ = err_code; trans_state.mysql_errmsg_ = ob_strerror(err_code); - if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state))) { + if (OB_FAIL(ObMysqlTransact::build_error_packet(trans_state, client_session))) { LOG_WARN("fail to build err resp", K(ret)); } } @@ -2385,7 +2702,7 @@ int ObProxyShardUtils::handle_sharding_select_real_info(ObDbConfigLogicDb &logic bool is_read_stmt = ObProxyShardUtils::is_read_stmt(session_info, trans_state, parse_result); - if (OB_FAIL(get_shard_hint(logic_db_info, parse_result, + if (OB_FAIL(get_shard_hint(table_name, session_info, logic_db_info, parse_result, group_index, tb_index, es_index, hint_table, testload_type))) { LOG_WARN("fail to get shard hint", K(ret)); diff --git a/src/obproxy/proxy/shard/obproxy_shard_utils.h b/src/obproxy/proxy/shard/obproxy_shard_utils.h index 3d9ca5494faf571096498629d550eecbb32bbc82..78518138bd1946526ad8575e2f32c9f3133c3304 100644 --- a/src/obproxy/proxy/shard/obproxy_shard_utils.h +++ b/src/obproxy/proxy/shard/obproxy_shard_utils.h @@ -46,12 +46,13 @@ public: static int get_db_version(const ObString &logic_tenant_name, const ObString &logic_database_name, ObString &db_version); - static bool is_special_db(ObMysqlTransact::ObTransState &s); + static bool is_special_db(obutils::ObSqlParseResult& parse_result); static int get_logic_db_info(ObMysqlTransact::ObTransState &s, ObClientSessionInfo &session_info, dbconfig::ObDbConfigLogicDb *&logic_db_info); - static int get_real_info(dbconfig::ObDbConfigLogicDb &logic_db_info, + static int get_real_info(ObClientSessionInfo &session_info, + dbconfig::ObDbConfigLogicDb &logic_db_info, const common::ObString &table_name, obutils::ObSqlParseResult &parse_result, dbconfig::ObShardConnector *&shard_conn, @@ -64,33 +65,62 @@ public: static bool check_shard_authority(const dbconfig::ObShardUserPrivInfo &up_info, const obutils::ObSqlParseResult &parse_result); - static int get_shard_hint(dbconfig::ObDbConfigLogicDb &logic_db_info, + static int get_shard_hint(const ObString &table_name, + ObClientSessionInfo &session_info, + dbconfig::ObDbConfigLogicDb &logic_db_info, obutils::ObSqlParseResult &parse_result, int64_t &group_index, int64_t &tb_index, - int64_t &es_index, ObString &table_name, + int64_t &es_index, ObString &hint_table_name, dbconfig::ObTestLoadType &testload_type); + static int get_shard_hint(dbconfig::ObDbConfigLogicDb &logic_db_info, + obutils::ObSqlParseResult &parse_result, + int64_t &group_index, int64_t &tb_index, + int64_t &es_index, ObString &hint_table_name, + dbconfig::ObTestLoadType &testload_type, + bool &is_sticky_session); + static int check_shard_request(ObMysqlClientSession &client_session, obutils::ObSqlParseResult &parse_result, dbconfig::ObDbConfigLogicDb &logic_db_info); - static int handle_shard_request(ObMysqlSM *sm, - ObMysqlClientSession &client_session, - ObMysqlTransact::ObTransState &trans_state, - ObIOBufferReader &client_buffer_reader, - dbconfig::ObDbConfigLogicDb &db_info, - bool &need_wait_callback); + static int do_handle_shard_request(ObMysqlClientSession &client_session, + ObMysqlTransact::ObTransState &trans_state, + dbconfig::ObDbConfigLogicDb &db_info, + const ObString& sql, + ObSqlString& new_sql, + obutils::ObSqlParseResult &parse_result, + int64_t& es_index, + int64_t& group_index, + const int64_t last_es_index, + bool& is_scan_all); + static int handle_shard_request(ObMysqlClientSession &client_session, + ObMysqlTransact::ObTransState &trans_state, + ObIOBufferReader &client_buffer_reader, + dbconfig::ObDbConfigLogicDb &db_info); + static int handle_ddl_request(ObMysqlSM *sm, + ObMysqlClientSession &client_session, + ObMysqlTransact::ObTransState &trans_state, + dbconfig::ObDbConfigLogicDb &db_info, + bool &need_wait_callback); static int do_handle_single_shard_request(ObMysqlClientSession &client_session, ObMysqlTransact::ObTransState &trans_state, - ObIOBufferReader &client_buffer_reader, - dbconfig::ObDbConfigLogicDb &logic_db_info); - static int handle_single_shard_request(ObMysqlSM *sm, - ObMysqlClientSession &client_session, + dbconfig::ObDbConfigLogicDb &logic_db_info, + const ObString& sql, + ObSqlString& new_sql, + obutils::ObSqlParseResult &parse_result, + int64_t& es_index, + int64_t& group_index, + const int64_t last_es_index); + static int handle_single_shard_request(ObMysqlClientSession &client_session, ObMysqlTransact::ObTransState &trans_state, ObIOBufferReader &client_buffer_reader, - dbconfig::ObDbConfigLogicDb &logic_db_info, - bool &need_wait_callback); + dbconfig::ObDbConfigLogicDb &logic_db_info); static int build_error_packet(int err_code, bool &need_response_for_dml, - ObMysqlTransact::ObTransState &trans_state); + ObMysqlTransact::ObTransState &trans_state, + ObMysqlClientSession *client_session); + static int handle_information_schema_request(ObMysqlClientSession &client_session, + ObMysqlTransact::ObTransState &trans_state, + ObIOBufferReader &client_buffer_reader); static int handle_sharding_select_real_info(dbconfig::ObDbConfigLogicDb &logic_db_info, ObMysqlClientSession &client_session, @@ -108,13 +138,13 @@ public: static int check_topology(obutils::ObSqlParseResult &parse_result, dbconfig::ObDbConfigLogicDb &db_info); - static int do_rewrite_shard_select_request(const ObString &sql, - obutils::ObSqlParseResult &parse_result, - bool is_oracle_mode, - const common::hash::ObHashMap &table_name_map, - const ObString &real_database_name, - bool is_single_shard_db_table, - common::ObSqlString &new_sql); + static int rewrite_shard_dml_request(const ObString &sql, + ObSqlString &new_sql, + obutils::ObSqlParseResult &parse_result, + bool is_oracle_mode, + const common::hash::ObHashMap &table_name_map, + const ObString &real_database_name, + bool is_single_shard_db_table); static int add_table_name_to_map(ObIAllocator &allocator, hash::ObHashMap &table_name_map, const ObString &table_name, const ObString &real_table_name); @@ -123,49 +153,72 @@ private: static bool is_read_stmt(ObClientSessionInfo &session_info, ObMysqlTransact::ObTransState &trans_state, obutils::ObSqlParseResult &parse_result); + static bool is_unsupport_type_in_multi_stmt(obutils::ObSqlParseResult& parse_result); static int change_connector(dbconfig::ObDbConfigLogicDb &logic_db_info, ObMysqlClientSession &client_session, ObMysqlTransact::ObTransState &trans_state, const dbconfig::ObShardConnector *prev_shard_conn, dbconfig::ObShardConnector *shard_conn); - - static int handle_ddl_request(ObMysqlSM *sm, - ObMysqlClientSession &client_session, - ObMysqlTransact::ObTransState &trans_state, - dbconfig::ObDbConfigLogicDb &db_info, - bool &need_wait_callback); static int handle_dml_request(ObMysqlClientSession &client_session, ObMysqlTransact::ObTransState &trans_state, - ObIOBufferReader &client_buffer_reader, - const common::ObString &table_name, - dbconfig::ObDbConfigLogicDb &db_info); + const ObString &table_name, + dbconfig::ObDbConfigLogicDb &db_info, + const ObString& sql, + ObSqlString& new_sql, + obutils::ObSqlParseResult &parse_result, + int64_t& es_index, + int64_t& group_index, + const int64_t last_es_index); static int handle_other_request(ObMysqlClientSession &client_session, ObMysqlTransact::ObTransState &trans_state, - ObIOBufferReader &client_buffer_reader, - const common::ObString &table_name, - dbconfig::ObDbConfigLogicDb &db_info); + const ObString &table_name, + dbconfig::ObDbConfigLogicDb &db_info, + const ObString& sql, + ObSqlString& new_sql, + obutils::ObSqlParseResult &parse_result, + int64_t& es_index, + int64_t& group_index); static int handle_select_request(ObMysqlClientSession &client_session, ObMysqlTransact::ObTransState &trans_state, - ObIOBufferReader &client_buffer_reader, - const common::ObString &table_name, - dbconfig::ObDbConfigLogicDb &db_info); + const ObString &table_name, + dbconfig::ObDbConfigLogicDb &db_info, + const ObString& sql, + ObSqlString& new_sql, + obutils::ObSqlParseResult &parse_result, + int64_t& es_index, + int64_t& group_index, + const int64_t last_es_index, + bool& is_scan_all); static int check_logic_database(ObMysqlTransact::ObTransState &trans_state, ObMysqlClientSession &client_session, const ObString &db_name); static void replace_oracle_table(ObSqlString &new_sql, const ObString &real_name, bool &hava_quoto, bool is_single_shard_db_table, bool is_database); + static int rewrite_shard_request_db(const char *sql_ptr, int64_t database_pos, + int64_t table_pos, uint64_t database_len, + const ObString &real_database_name, bool is_oracle_mode, + bool is_single_shard_db_table, ObSqlString &new_sql, int64_t ©_pos); + static int rewrite_shard_request_table(const char *sql_ptr, + int64_t database_pos, uint64_t database_len, + int64_t table_pos, uint64_t table_len, + const ObString &real_table_name, const ObString &real_database_name, + bool is_oracle_mode, bool is_single_shard_db_table, + ObSqlString &new_sql, int64_t ©_pos); + static int rewrite_shard_request_table_no_db(const char *sql_ptr, + int64_t table_pos, uint64_t table_len, + const ObString &real_table_name, + bool is_oracle_mode, bool is_single_shard_db_table, + ObSqlString &new_sql, int64_t ©_pos); + static int rewrite_shard_request_hint_table(const char *sql_ptr, int64_t index_table_pos, uint64_t index_table_len, + const ObString &real_table_name, bool is_oracle_mode, + bool is_single_shard_db_table, ObSqlString &new_sql, int64_t ©_pos); static int rewrite_shard_request(ObClientSessionInfo &session_info, - ObProxyMysqlRequest &client_request, - ObIOBufferReader &client_buffer_reader, + obutils::ObSqlParseResult &parse_result, const ObString &table_name, const ObString &database_name, const ObString &real_table_name, const ObString &real_database_name, - bool is_single_shard_db_table); - static int rewrite_shard_select_request(ObClientSessionInfo &session_info, - ObProxyMysqlRequest &client_request, - ObIOBufferReader &client_buffer_reader, - const common::hash::ObHashMap &table_name_map, - const ObString &real_database_name, - bool is_single_shard_db_table); + bool is_single_shard_db_table, + const ObString& sql, + common::ObSqlString& new_sql); static int testload_check_obparser_node_is_valid(const ParseNode *root, const ObItemType &type); static int testload_rewrite_name_base_on_parser_node(common::ObSqlString &new_sql, const char *new_name, @@ -176,13 +229,13 @@ private: static int testload_get_obparser_db_and_table_node(const ParseNode *root, ParseNode *&db_node, ParseNode *&table_node); - static int testload_check_and_rewrite_testload_request(ObClientSessionInfo &session_info, - ObProxyMysqlRequest &client_request, - ObIOBufferReader &client_buffer_reader, + static int testload_check_and_rewrite_testload_request(obutils::ObSqlParseResult &parse_result, bool is_single_shard_db_table, const ObString &hint_table, const ObString &real_database_name, - dbconfig::ObDbConfigLogicDb &logic_db_info); + dbconfig::ObDbConfigLogicDb &logic_db_info, + const ObString& sql, + common::ObSqlString& new_sql); static int testload_check_and_rewrite_testload_hint_index(common::ObSqlString &new_sql, const char *sql_ptr, int64_t sql_len, @@ -202,27 +255,33 @@ private: ObMysqlTransact::ObTransState &trans_state, const ObString &table_name, char *real_database_name, int64_t db_name_len, - char *real_table_name, int64_t tb_name_len); - static int handle_dml_real_info(dbconfig::ObDbConfigLogicDb &logic_db_info, - ObMysqlClientSession &client_session, - ObMysqlTransact::ObTransState &trans_state, - const ObString &table_name, - char *real_database_name, int64_t db_name_len, - char *real_table_name, int64_t tb_name_len); + char *real_table_name, int64_t tb_name_len, + obutils::ObSqlParseResult &parse_result, + int64_t& es_index, + int64_t& group_index); static int handle_scan_all_real_info(dbconfig::ObDbConfigLogicDb &logic_db_info, ObMysqlClientSession &client_session, ObMysqlTransact::ObTransState &trans_state, const ObString &table_name); - static int handle_select_real_info(dbconfig::ObDbConfigLogicDb &logic_db_info, - ObMysqlClientSession &client_session, - ObMysqlTransact::ObTransState &trans_state, - const ObString &table_name, - ObIOBufferReader &client_buffer_reader); + static int handle_dml_real_info(dbconfig::ObDbConfigLogicDb &logic_db_info, + ObMysqlClientSession &client_session, + ObMysqlTransact::ObTransState &trans_state, + const ObString &table_name, + const ObString& sql, + ObSqlString& new_sql, + obutils::ObSqlParseResult &parse_result, + int64_t& es_index, + int64_t& group_index, + const int64_t last_es_index); static int handle_sys_read_consitency_prop(dbconfig::ObDbConfigLogicDb &logic_db_info, dbconfig::ObShardConnector& shard_conn, ObClientSessionInfo &session_info); static int is_sharding_in_trans(ObClientSessionInfo &session_info, ObMysqlTransact::ObTransState &trans_state); + static int build_shard_request_packet(ObClientSessionInfo &session_info, + ObProxyMysqlRequest &client_request, + ObIOBufferReader &client_buffer_reader, + const ObString& sql); }; diff --git a/src/obproxy/stat/ob_mysql_stats.cpp b/src/obproxy/stat/ob_mysql_stats.cpp index 0b096d7a7c3d9d53cd7e80b1563e513f4f70342c..eb8161e634aa0482050d6492327cabc651be41df 100644 --- a/src/obproxy/stat/ob_mysql_stats.cpp +++ b/src/obproxy/stat/ob_mysql_stats.cpp @@ -272,6 +272,9 @@ int init_mysql_stats() MYSQL_REGISTER_RAW_STAT(mysql_rsb, RECT_PROCESS, "send_changed_session_vars_requests", RECD_INT, SEND_CHANGED_SESSION_VARS_REQUESTS, SYNC_SUM, RECP_NULL); + MYSQL_REGISTER_RAW_STAT(mysql_rsb, RECT_PROCESS, "send_changed_session_user_vars_requests", + RECD_INT, SEND_CHANGED_SESSION_USER_VARS_REQUESTS, SYNC_SUM, RECP_NULL); + MYSQL_REGISTER_RAW_STAT(mysql_rsb, RECT_PROCESS, "send_last_insert_id_requests", RECD_INT, SEND_LAST_INSERT_ID_REQUESTS, SYNC_SUM, RECP_PERSISTENT); @@ -334,6 +337,9 @@ int init_mysql_stats() MYSQL_REGISTER_RAW_STAT(mysql_rsb, RECT_PROCESS, "total_send_changed_session_vars_time", RECD_INT, TOTAL_SEND_CHANGED_SESSION_VARS_TIME, SYNC_SUM, RECP_NULL); + MYSQL_REGISTER_RAW_STAT(mysql_rsb, RECT_PROCESS, "total_send_changed_session_user_vars_time", + RECD_INT, TOTAL_SEND_CHANGED_SESSION_USER_VARS_TIME, SYNC_SUM, RECP_NULL); + MYSQL_REGISTER_RAW_STAT(mysql_rsb, RECT_PROCESS, "total_send_last_insert_id_time", RECD_INT, TOTAL_SEND_LAST_INSERT_ID_TIME, SYNC_SUM, RECP_NULL); diff --git a/src/obproxy/stat/ob_mysql_stats.h b/src/obproxy/stat/ob_mysql_stats.h index 99c6b17a53ac0e66ff88c8c2859b3ad10fd7cf8a..6dd8679667c16e77e6982b875ef530a2f5c69766 100644 --- a/src/obproxy/stat/ob_mysql_stats.h +++ b/src/obproxy/stat/ob_mysql_stats.h @@ -60,8 +60,10 @@ enum ObMysqlStats TOTAL_SEND_ALL_SESSION_VARS_TIME, TOTAL_SEND_USE_DATABASE_TIME, TOTAL_SEND_CHANGED_SESSION_VARS_TIME, + TOTAL_SEND_CHANGED_SESSION_USER_VARS_TIME, TOTAL_SEND_LAST_INSERT_ID_TIME, TOTAL_SEND_START_TRANS_TIME, + TOTAL_SEND_XA_START_TIME, TOTAL_PL_LOOKUP_TIME, TOTAL_CONGESTION_CONTROL_LOOKUP_TIME, @@ -132,8 +134,10 @@ enum ObMysqlStats SEND_ALL_SESSION_VARS_REQUESTS, SEND_USE_DATABASE_REQUESTS, SEND_CHANGED_SESSION_VARS_REQUESTS, + SEND_CHANGED_SESSION_USER_VARS_REQUESTS, SEND_LAST_INSERT_ID_REQUESTS, SEND_START_TRANS_REQUESTS, + SEND_XA_START_REQUESTS, VIP_TO_TENANT_CACHE_HIT, VIP_TO_TENANT_CACHE_MISS, diff --git a/src/obproxy/stat/ob_stat_processor.cpp b/src/obproxy/stat/ob_stat_processor.cpp index da5da868334eeb58193dcc29a7b29c1efd55952e..f1341f36ef20f250f638d53c7cd2fc4f2bbf7eff 100644 --- a/src/obproxy/stat/ob_stat_processor.cpp +++ b/src/obproxy/stat/ob_stat_processor.cpp @@ -92,7 +92,7 @@ int ObSessionStatTableSync::init(ObMysqlProxy &mysql_proxy, const char *cluster_ { int ret = OB_SUCCESS; ObAddr addr; - char ip_str[OB_IP_STR_BUFF]; + char ip_str[MAX_IP_ADDR_LENGTH]; ip_str[0] = '\0'; if (OB_ISNULL(cluster_name) @@ -101,7 +101,7 @@ int ObSessionStatTableSync::init(ObMysqlProxy &mysql_proxy, const char *cluster_ LOG_WARN("invalid parameter", K(cluster_name), K(stats), K(stat_names), K(ret)); } else if (OB_FAIL(ObProxyTableProcessorUtils::get_proxy_local_addr(addr))) { LOG_WARN("fail to get proxy local addr", K(addr), K(ret)); - } else if (!addr.ip_to_string(ip_str, OB_IP_STR_BUFF)) { + } else if (!addr.ip_to_string(ip_str, MAX_IP_ADDR_LENGTH)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to covert ip to string", K(addr), K(ret)); } else if (OB_FAIL(sql_.append_fmt(ObStatProcessor::INSERT_PROXY_STAT_SQL_HEAD, diff --git a/src/obproxy/stat/ob_stat_processor.h b/src/obproxy/stat/ob_stat_processor.h index 7d90c9ad443dfdbad50fed00b0a14db9a039833b..c5d39815d97d5ffc36745936ececc5e5bba5b2d1 100644 --- a/src/obproxy/stat/ob_stat_processor.h +++ b/src/obproxy/stat/ob_stat_processor.h @@ -586,7 +586,7 @@ private: ASLL(ObRecRawStatBlock, link_) all_blocks_; - char proxy_ip_[common::OB_IP_STR_BUFF]; // ip primary key + char proxy_ip_[common::MAX_IP_ADDR_LENGTH]; // ip primary key int32_t proxy_port_; // port primary key DISALLOW_COPY_AND_ASSIGN(ObStatProcessor); }; diff --git a/src/obproxy/utils/Makemodule.am b/src/obproxy/utils/Makemodule.am index 747c60513b95638463ea00bfda2627edc0725f4c..72841d3f7abbf229bfc4167294bec3e5dbec28af 100644 --- a/src/obproxy/utils/Makemodule.am +++ b/src/obproxy/utils/Makemodule.am @@ -23,6 +23,8 @@ obproxy/utils/ob_cpu_affinity.cpp\ obproxy/utils/ob_proxy_blowfish.h\ obproxy/utils/ob_proxy_blowfish.cpp\ obproxy/utils/ob_proxy_monitor_utils.h\ -obproxy/utils/ob_proxy_monitor_utils.cpp +obproxy/utils/ob_proxy_monitor_utils.cpp\ +obproxy/utils/ob_target_db_server.h\ +obproxy/utils/ob_target_db_server.cpp utils_sources:= ${utils_common_sources} diff --git a/src/obproxy/utils/ob_layout.cpp b/src/obproxy/utils/ob_layout.cpp index 466b12b2f1b7900ff74a5cc8f279f12ad0bb6d9a..a54ad36da58ff38d151adc53772b8f23b606fb21 100644 --- a/src/obproxy/utils/ob_layout.cpp +++ b/src/obproxy/utils/ob_layout.cpp @@ -11,8 +11,11 @@ */ #define USING_LOG_PREFIX PROXY -#include "utils/ob_layout.h" #include +#include "utils/ob_layout.h" +#include "ob_proxy_init.h" + +#define UNIX_PATH_LENGTH_MAX (sizeof(struct sockaddr_un) - sizeof(sa_family_t)) using namespace oceanbase::common; using namespace oceanbase::obproxy::event; @@ -22,6 +25,9 @@ namespace oceanbase namespace obproxy { +static const char* obproxy_domain = "obproxy.domain"; +static const char* obproxy_dir = "./.obproxy"; + ObLayout &get_global_layout() { static ObLayout g_layout; @@ -30,7 +36,8 @@ ObLayout &get_global_layout() ObLayout::ObLayout() : is_inited_(false), prefix_(NULL), bin_dir_(NULL), etc_dir_(NULL), - log_dir_(NULL), conf_dir_(NULL), control_config_dir_(NULL), dbconfig_dir_(NULL) + log_dir_(NULL), conf_dir_(NULL), control_config_dir_(NULL), + dbconfig_dir_(NULL), unix_domain_path_(NULL) { } @@ -49,7 +56,7 @@ int ObLayout::init(const char *start_cmd) MPRINT("layout has already been inited, ret=%d", ret); } else if (OB_ISNULL(start_cmd)) { ret = OB_ERR_UNEXPECTED; - MPRINT("start comd is NULL, ret=%d", ret); + MPRINT("start cmd is NULL, ret=%d", ret); } else if (OB_ISNULL(cwd = arena.alloc(MAX_PATH_LENGTH))) { ret = OB_ALLOCATE_MEMORY_FAILED; MPRINT("fail to alloc memeory,alloc_size=%ld, ret=%d", MAX_PATH_LENGTH, ret); @@ -60,6 +67,8 @@ int ObLayout::init(const char *start_cmd) MPRINT("fail to init proxy bin dir, ret=%d", ret); } else if (OB_FAIL(init_dir_prefix(cwd))) { MPRINT("fail to init proxy dir prefix, ret=%d", ret); + } else if (RUN_MODE_CLIENT == g_run_mode && OB_FAIL(handle_client_dirs())) { + MPRINT("fail to construct client dirs, ret=%d", ret); } else if (OB_FAIL(construct_dirs())) { MPRINT("fail to construct dirs, ret=%d", ret); } else { @@ -168,6 +177,42 @@ int ObLayout::init_bin_dir(const char *cwd, const char *start_cmd) } int ObLayout::init_dir_prefix(const char *cwd) +{ + int ret = OB_SUCCESS; + if (RUN_MODE_PROXY == g_run_mode) { + if (OB_FAIL(init_dir_prefix_proxy_mode(cwd))) { + LOG_WARN("init dir prefix proxy mode failed", K(ret)); + } + } else if (RUN_MODE_CLIENT == g_run_mode) { + if (OB_FAIL(init_dir_prefix_client_mode())) { + LOG_WARN("init_dir_prefix_client_mode", K(ret)); + } + } + + return ret; +} + +int ObLayout::init_dir_prefix_client_mode() +{ + int ret = OB_SUCCESS; + int64_t prefix_len = 0; + + prefix_len = strlen(obproxy_dir); + + if (OB_SUCC(ret)) { + if (OB_ISNULL(prefix_ = static_cast(allocator_.alloc(prefix_len + 1)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + MPRINT("fail to alloc memeory, prefix_len=%ld, ret=%d", prefix_len, ret); + } else { + MEMCPY(prefix_, obproxy_dir, prefix_len); + prefix_[prefix_len] = '\0'; + } + } + + return ret; +} + +int ObLayout::init_dir_prefix_proxy_mode(const char *cwd) { int ret = OB_SUCCESS; char *env_path = NULL; @@ -291,5 +336,56 @@ int ObLayout::construct_single_dir(const char *sub_dir, char *&full_path) return ret; } +int ObLayout::handle_client_dirs() +{ + int ret = OB_SUCCESS; + if (OB_FAIL(construct_client_obproxy_dirs())) { + LOG_WARN("construct_client_obproxy_dirs failed", K(ret)); + } else if (OB_FAIL(remove_unix_domain())) { + LOG_WARN("remove unix domain failed", K(ret)); + } + + return ret; +} + +int ObLayout::construct_client_obproxy_dirs() +{ + int ret = OB_SUCCESS; + char *actual_path = NULL; + // Create the .obproxy directory + if (OB_FAIL(extract_actual_path(prefix_, actual_path))) { + MPRINT("fail to extract_actual_path, prefix_path=%s, ret=%d", prefix_, ret); + } else if (OB_FAIL(FileDirectoryUtils::create_full_path(actual_path))) { + MPRINT("fail to create_full_path, actual_path=%s, ret=%d", actual_path, ret); + } + + if (NULL != actual_path && prefix_ != actual_path) { + allocator_.free(actual_path); + } + actual_path = NULL; + + + return ret; +} + +int ObLayout::remove_unix_domain() +{ + int ret = OB_SUCCESS; + char *actual_path = NULL; + + if (OB_FAIL(merge_file_path(prefix_, obproxy_domain, allocator_, unix_domain_path_))) { + MPRINT("fail to merge file path, sub_dir=%s, ret=%d", obproxy_domain, ret); + } else if (OB_FAIL(extract_actual_path(unix_domain_path_, actual_path))) { + MPRINT("fail to extract_actual_path, full_path=%s, ret=%d", unix_domain_path_, ret); + } else { + remove(actual_path); + if (NULL != actual_path && unix_domain_path_ != actual_path) { + allocator_.free(actual_path); + } + actual_path = NULL; + } + return ret; +} + }//end of namespace obproxy }//end of namespace oceanbase diff --git a/src/obproxy/utils/ob_layout.h b/src/obproxy/utils/ob_layout.h index beb15a3c563c56673abc0896dc74070e482c4d91..527a97f96901ee7e5653120cf57a73debec3cbdf 100644 --- a/src/obproxy/utils/ob_layout.h +++ b/src/obproxy/utils/ob_layout.h @@ -36,14 +36,20 @@ public: const char *get_control_config_dir() const { return control_config_dir_; } const char *get_dbconfig_dir() const { return dbconfig_dir_; } const char *get_proxy_root_dir() const { return prefix_; } + const char *get_unix_domain_path() const { return unix_domain_path_; } static int merge_file_path(const char *root, const char *file, common::ObIAllocator &allocator, char *&buf); private: int init_bin_dir(const char *cwd, const char *start_cmd); int init_dir_prefix(const char *cwd); + int init_dir_prefix_proxy_mode(const char *cwd); + int init_dir_prefix_client_mode(); int construct_dirs(); int construct_single_dir(const char *sub_dir, char *&full_path); int extract_actual_path(const char * const full_path, char *&actual_path); + int handle_client_dirs(); + int construct_client_obproxy_dirs(); + int remove_unix_domain(); private: bool is_inited_; @@ -54,6 +60,7 @@ private: char *conf_dir_; char *control_config_dir_; char *dbconfig_dir_; + char *unix_domain_path_; event::ObFixedArenaAllocator allocator_; }; diff --git a/src/obproxy/utils/ob_proxy_hot_upgrader.cpp b/src/obproxy/utils/ob_proxy_hot_upgrader.cpp index 98fb1e9443df6d2c1e83bc4bc3f106de6ee5472b..600e97515f56abfa8554a1db6dda45aff2225b1d 100644 --- a/src/obproxy/utils/ob_proxy_hot_upgrader.cpp +++ b/src/obproxy/utils/ob_proxy_hot_upgrader.cpp @@ -14,6 +14,7 @@ #include "utils/ob_proxy_hot_upgrader.h" #include "iocore/eventsystem/ob_event_processor.h" +#include "ob_proxy_init.h" using namespace oceanbase::common; using namespace oceanbase::obproxy::event; @@ -28,7 +29,8 @@ ObHotUpgraderInfo g_hot_upgrade_info; void ObHotUpgraderInfo::reset() { - fd_ = OB_INVALID_INDEX; + ipv4_fd_ = OB_INVALID_INDEX; + ipv6_fd_ = OB_INVALID_INDEX; received_sig_ = OB_INVALID_INDEX; sub_pid_ = OB_INVALID_INDEX; rc_status_ = RCS_NONE; @@ -67,9 +69,9 @@ DEF_TO_STRING(ObHotUpgraderInfo) { int64_t pos = 0; J_OBJ_START(); - J_KV(K_(is_inherited), K_(upgrade_version), K_(need_conn_accept), K_(user_rejected), K_(fd), - K_(received_sig), K_(sub_pid), K_(graceful_exit_end_time), K_(graceful_exit_start_time), - K_(active_client_vc_count), K_(local_addr), + J_KV(K_(is_inherited), K_(upgrade_version), K_(need_conn_accept), K_(user_rejected), K_(ipv4_fd), + K_(ipv6_fd), K_(received_sig), K_(sub_pid), K_(graceful_exit_end_time), + K_(graceful_exit_start_time), K_(active_client_vc_count), K_(local_addr), "rc_status", get_rc_status_string(rc_status_), "hu_cmd", get_cmd_string(cmd_), "state", get_state_string(state_), diff --git a/src/obproxy/utils/ob_proxy_hot_upgrader.h b/src/obproxy/utils/ob_proxy_hot_upgrader.h index 95398a390bb1e9003d10e29967cc96255f88f925..cbc14887703d4d8e9e7cdb0d3ff7f23e5eb22f1d 100644 --- a/src/obproxy/utils/ob_proxy_hot_upgrader.h +++ b/src/obproxy/utils/ob_proxy_hot_upgrader.h @@ -20,7 +20,8 @@ namespace oceanbase { namespace obproxy { -#define OBPROXY_INHERITED_FD "OBPROXY_INHERITED_FD" +#define OBPROXY_INHERITED_IPV4_FD "OBPROXY_INHERITED_FD" +#define OBPROXY_INHERITED_IPV6_FD "OBPROXY_INHERITED_IPV6_FD" extern volatile int g_proxy_fatal_errcode; enum ObReloadConfigStatus @@ -196,7 +197,8 @@ public: static const int64_t MAX_RESTART_BUF_SIZE = 64; static const int64_t OB_MAX_INHERITED_ARGC = 4; - int fd_; // listen fd, which to be passed to sub process + int ipv4_fd_; // listen fd, which to be passed to sub process + int ipv6_fd_; int received_sig_; ObReloadConfigStatus rc_status_; // identify the current status for reload config volatile pid_t sub_pid_; // sub process pid if fork succeed diff --git a/src/obproxy/utils/ob_proxy_lib.h b/src/obproxy/utils/ob_proxy_lib.h index 61931fd55d837195b2f64543b0ce55643233a474..98768673516d2cc585a9021b3c533287a2c0c10d 100644 --- a/src/obproxy/utils/ob_proxy_lib.h +++ b/src/obproxy/utils/ob_proxy_lib.h @@ -160,7 +160,7 @@ const static int64_t PRINT_JSON_LEN = 16 * 1024; // Attention!! must confirm OB_NORMAL_MYSQL_CLIENT_COUNT >= OB_META_MYSQL_CLIENT_COUNT // or will dead lock static const int64_t OB_META_MYSQL_CLIENT_COUNT = 2; -static const int64_t OB_NORMAL_MYSQL_CLIENT_COUNT = 4; +static const int64_t OB_NORMAL_MYSQL_CLIENT_COUNT = 64; static const int64_t OB_PROXY_WARN_LOG_BUF_LENGTH = (1 << 20) * 1; static const int64_t OB_PROXY_WARN_LOG_AVG_LENGTH = 512; @@ -196,7 +196,12 @@ static const uint64_t OBPROXY_DEFAULT_CAPABILITY_FLAG = | OB_CAP_OB_PROTOCOL_V2 | OB_CAP_EXTRA_OK_PACKET_FOR_STATISTICS | OB_CAP_PL_ROUTE - | OB_CAP_PROXY_REROUTE); + | OB_CAP_PROXY_REROUTE + | OB_CAP_PROXY_SESSION_SYNC + | OB_CAP_PROXY_FULL_LINK_TRACING + | OB_CAP_PROXY_NEW_EXTRA_INFO + | OB_CAP_PROXY_SESSION_VAR_SYNC + ); #define OBPROXY_SYS_ERRNO_START -10000 /* diff --git a/src/obproxy/utils/ob_proxy_table_define.cpp b/src/obproxy/utils/ob_proxy_table_define.cpp index e98d559c0726234248150f5d6eed9f5c9ecab23f..4cd0107f10641c002da9d59b39e518310e5466ee 100644 --- a/src/obproxy/utils/ob_proxy_table_define.cpp +++ b/src/obproxy/utils/ob_proxy_table_define.cpp @@ -98,11 +98,15 @@ const char *ObProxyTableInfo::PROXY_VIP_TENANT_VERSION_NAME = "o const char *ObProxyTableInfo::READ_ONLY_USERNAME_USER = "proxyro"; const char *ObProxyTableInfo::READ_ONLY_USERNAME = "proxyro@sys"; const char *ObProxyTableInfo::READ_ONLY_DATABASE = "oceanbase"; +const char *ObProxyTableInfo::OBSERVER_SYS_PASSWORD = "observer_sys_password"; +const char *ObProxyTableInfo::OBSERVER_SYS_PASSWORD1 = "observer_sys_password1"; const char *ObProxyTableInfo::TEST_MODE_USERNAME = "root@sys"; const char *ObProxyTableInfo::TEST_MODE_PASSWORD = ""; const char *ObProxyTableInfo::TEST_MODE_DATABASE = "oceanbase"; +const char *ObProxyTableInfo::DETECT_USERNAME_USER = "detect_user"; + const ObString ObProxyTableInfo::PROXY_ALL_PROXY_HEADER = ObString::make_string("all_proxy"); const ObString ObProxyTableInfo::PROXY_CONFIG_VERSION_NAME = ObString::make_string(".config_version"); const ObString ObProxyTableInfo::PROXY_UPGRADE_SWITCH_NAME = ObString::make_string(".upgrade_switch"); @@ -132,7 +136,7 @@ int ObProxyTableInfo::get_create_proxy_table_sql(char *buf, const int64_t len) } else { int64_t w_len = snprintf(buf, len, CREATE_PROXY_TABLE_SQL, PROXY_INFO_TABLE_NAME, - OB_IP_STR_BUFF, // ip + MAX_IP_ADDR_LENGTH, // ip OB_MAX_APP_NAME_LENGTH, // app_name OB_MAX_PROXY_BINARY_VERSION_LEN, // binary_version OB_MAX_UNAME_INFO_LEN, // system_info @@ -239,7 +243,7 @@ int ObProxyTableInfo::get_create_proxy_vip_tenant_table_sql(char *buf, const int } else { int64_t w_len = snprintf(buf, len, CREATE_PROXY_VIP_TENANT_TABLE_SQL, PROXY_VIP_TENANT_TABLE_NAME, // table name - OB_IP_STR_BUFF, // vip + MAX_IP_ADDR_LENGTH, // vip OB_MAX_TENANT_NAME_LENGTH, // tenant_name length OB_PROXY_MAX_CLUSTER_NAME_LENGTH, // cluster_name length OB_MAX_CONFIG_INFO_LEN // info length diff --git a/src/obproxy/utils/ob_proxy_table_define.h b/src/obproxy/utils/ob_proxy_table_define.h index f769156056fe86c2513481442d1072fcbe268d85..b0cfab63be257816d285210095c5dae3ae6af9a8 100644 --- a/src/obproxy/utils/ob_proxy_table_define.h +++ b/src/obproxy/utils/ob_proxy_table_define.h @@ -67,10 +67,16 @@ public: static const char *READ_ONLY_USERNAME_USER; static const char *READ_ONLY_USERNAME; static const char *READ_ONLY_DATABASE; + static const char *READ_ONLY_PASSWD_STAGED1; + + static const char *OBSERVER_SYS_PASSWORD; + static const char *OBSERVER_SYS_PASSWORD1; static const char *TEST_MODE_USERNAME; static const char *TEST_MODE_PASSWORD; static const char *TEST_MODE_DATABASE; + + static const char *DETECT_USERNAME_USER; }; } // end of namespace obproxy diff --git a/src/obproxy/utils/ob_proxy_utils.cpp b/src/obproxy/utils/ob_proxy_utils.cpp index b4e624e1da9128f2b16b46d1de2fa73116fc6f98..615bac67a310a757b687a37292bb00dcfad31455 100644 --- a/src/obproxy/utils/ob_proxy_utils.cpp +++ b/src/obproxy/utils/ob_proxy_utils.cpp @@ -344,5 +344,39 @@ int paste_tenant_and_cluster_name(const ObString &tenant_name, const ObString &c return ret; } +// split str like 'val0,val1;val2;val3' to +// item: val0 val1 val2 val3 +// weight: 0 0 1 2 +int split_weight_group(ObString weight_group_str, + ObIArray &items, + ObIArray &weights) { + int ret = OB_SUCCESS; + int8_t weight = 0; + bool finish = false; + while (OB_SUCC(ret) && !weight_group_str.empty() && !finish) { + ObString group = weight_group_str.split_on(';'); + if (group.empty()) { + group = weight_group_str; + finish = true; + } + // split by ',' + bool group_finish = false; + while (OB_SUCC(ret) && !group.empty() && !group_finish) { + ObString item = group.split_on(','); + if (item.empty()) { + item = group; + group_finish = true; + } + if (OB_FAIL(items.push_back(item))) { + LOG_WARN("fail to push back item", K(item), K(ret)); + } else if (OB_FAIL(weights.push_back(weight))) { + LOG_WARN("fail to push back weight", K(weight), K(ret)); + } else { /* succ */} + } + weight++; + } + return ret; +} + } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/utils/ob_proxy_utils.h b/src/obproxy/utils/ob_proxy_utils.h index 300d7c9c327e33e30e4b646b0457459025a2972c..62976d39861b443b5dfa0e1565e4b15664e26380 100644 --- a/src/obproxy/utils/ob_proxy_utils.h +++ b/src/obproxy/utils/ob_proxy_utils.h @@ -16,6 +16,7 @@ #include "common/ob_object.h" #include "lib/string/ob_fixed_length_string.h" #include "utils/ob_proxy_lib.h" +#include "iocore/net/ob_inet.h" namespace oceanbase { @@ -79,6 +80,12 @@ int convert_timestamp_to_version(int64_t time_us, char *buf, int64_t len); int paste_tenant_and_cluster_name(const common::ObString &tenant_name, const common::ObString &cluster_name, common::ObFixedLengthString &key_string); +// split str like val0,val1;val2;val3 into +// item: val0 val1 val2 val3 +// weight: 0 0 1 2 +int split_weight_group(common::ObString weight_group_str, + common::ObIArray &item, + common::ObIArray &weights); } // end of namespace obproxy } // end of namespace oceanbase diff --git a/src/obproxy/utils/ob_target_db_server.cpp b/src/obproxy/utils/ob_target_db_server.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8a0384d009ab5b8bff21292b00f297bedfe402cf --- /dev/null +++ b/src/obproxy/utils/ob_target_db_server.cpp @@ -0,0 +1,147 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ +#define USING_LOG_PREFIX PROXY +#include "utils/ob_target_db_server.h" + + +namespace oceanbase +{ +namespace obproxy +{ +using namespace oceanbase::common; + +int ObTargetDbServer::init(const char* target_db_server_str, uint64_t target_db_server_str_len) +{ + int ret = OB_SUCCESS; + reset(); + if (OB_ISNULL(target_db_server_str)) { + ret = OB_INIT_FAIL; + LOG_WARN("fail to init target db server for NULL str", K(ret)); + } else if (target_db_server_str_len == 0) { + LOG_DEBUG("succ to init target db server with empty str"); + } else if (OB_ISNULL(target_db_server_buf_ = static_cast(op_fixed_mem_alloc(target_db_server_str_len + 1)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to allocate mem for target db server", K(ret), K(target_db_server_str_len)); + } else { + target_db_server_buf_len_ = target_db_server_str_len + 1; + MEMSET(target_db_server_buf_, '\0', target_db_server_buf_len_); + MEMCPY(target_db_server_buf_, target_db_server_str, target_db_server_str_len); + + ObString target_db_server_str(target_db_server_str_len, target_db_server_buf_); + if (OB_FAIL(split_weight_group(target_db_server_str, target_db_server_, target_db_server_weight_))) { + LOG_WARN("fail to split target db server str", K(ret)); + } else { /* succ */ } + } + + if (OB_SUCC(ret)) { + is_init_ = true; + LOG_DEBUG("succ to init all target db server", K_(target_db_server), K_(target_db_server_weight)); + } else { + reset(); + } + return ret; +} + +int ObTargetDbServer::get(net::ObIpEndpoint &dest) +{ + int ret = OB_SUCCESS; + + // [weight_start, weight_end) + if (!is_init_) { + ret = OB_INIT_FAIL; + LOG_WARN("fail to get next, target db server not init", K(ret)); + } else if (last_failed_idx_ == target_db_server_.count() - 1) { + ret = OB_DATA_OUT_OF_RANGE; + LOG_WARN("fail to get next, all target db server has failed", K(ret)); + } else if (!is_rand_) { + ObTargetDbServerArray::iterator weight_begin = target_db_server_.begin(); + for (int64_t i = 0; i < target_db_server_.count(); i++) { + if (i == target_db_server_.count() - 1) { + std::random_shuffle(weight_begin, target_db_server_.end()); + } else if (target_db_server_weight_.at(i) != target_db_server_weight_.at(i + 1)) { + ObTargetDbServerArray::iterator weight_end = target_db_server_.begin() + (i + 1); + std::random_shuffle(weight_begin, weight_end); + weight_begin = weight_end; + } + } + is_rand_ = true; + } + if (OB_SUCC(ret)) { + ObString addr; + uint64_t idx = last_failed_idx_ + 1; + if (OB_FAIL(target_db_server_.at(idx, addr))) { + LOG_WARN("fail to access target db server array", K(ret), K(idx)); + } else if (OB_FAIL(ops_ip_pton(addr, dest))) { + LOG_WARN("fail to do ops_ip_pton on target db server", K(ret), K(addr)); + } else { + LOG_DEBUG("succ to get target db server", K(dest)); + } + } + return ret; +} + +int ObTargetDbServer::get_next(net::ObIpEndpoint &dest_addr) +{ + // mark previous one as failed + last_failed_idx_++; + return get(dest_addr); +} + +void ObTargetDbServer::reset() +{ + is_init_ = false; + is_rand_ = false; + last_failed_idx_ = -1; + if (OB_NOT_NULL(target_db_server_buf_)) { + op_fixed_mem_free(target_db_server_buf_, target_db_server_buf_len_); + target_db_server_buf_len_ = 0; + target_db_server_buf_ = NULL; + } + target_db_server_.reset(); + target_db_server_weight_.reset(); +} + +bool ObTargetDbServer::contains(net::ObIpEndpoint &addr) +{ + bool ret = false; + if (is_init_) { + char addr_buf[MAX_IP_ADDR_LENGTH]; + MEMSET(addr_buf, '\0', MAX_IP_ADDR_LENGTH); + // get like '{xxx.xxxx.xxx.xxx:xxxx}' + addr.to_string(addr_buf, sizeof(addr_buf)); + // remove the last '}' + addr_buf[strlen(addr_buf) - 1] = '\0'; + ObTargetDbServerArray::iterator it = target_db_server_.begin(); + while (it != target_db_server_.end()) { + // skip the first '{' + if (it->case_compare(addr_buf + 1) == 0) { + ret = true; + break; + } + it++; + } + } else { + LOG_DEBUG("target db server not init!"); + } + return ret; +} + +int64_t ObTargetDbServer::to_string(char *buf, const int64_t buf_len) const +{ + int64_t pos = 0; + J_OBJ_START(); + J_KV(K_(is_init), K_(is_rand), K_(last_failed_idx), K_(target_db_server)); + J_OBJ_END(); + return pos; +} +} // namespace obproxy +} // namespace oceanbase \ No newline at end of file diff --git a/src/obproxy/utils/ob_target_db_server.h b/src/obproxy/utils/ob_target_db_server.h new file mode 100644 index 0000000000000000000000000000000000000000..54a3ef88f74118c54e20d50b1d4e9b0697ffe78e --- /dev/null +++ b/src/obproxy/utils/ob_target_db_server.h @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ +#ifndef OB_TARGET_DB_SERVER_H +#define OB_TARGET_DB_SERVER_H + +#include "lib/ob_define.h" +#include "lib/container/ob_se_array.h" +#include "lib/container/ob_se_array_iterator.h" +#include "lib/utility/ob_print_utils.h" +#include "iocore/net/ob_inet.h" +#include "lib/string/ob_string.h" +#include "utils/ob_proxy_utils.h" +#include "iocore/eventsystem/ob_buf_allocator.h" + +namespace oceanbase +{ +namespace obproxy +{ +typedef common::ObSEArray ObTargetDbServerArray; +class ObTargetDbServer +{ +public: + ObTargetDbServer() : + is_init_(false), is_rand_(false), last_failed_idx_(-1), + target_db_server_buf_(NULL), target_db_server_buf_len_(0) {} + + ObTargetDbServer& operator=(const ObTargetDbServer &other) { + if (this != &other) { + reset(); + // other.target_db_server_buf_len_ - 1 to minus last '\0' + init(other.target_db_server_buf_, other.target_db_server_buf_len_ - 1); + } + return *this; + } + + ~ObTargetDbServer() { + reset(); + } + + int init(const char* target_db_server_buf, uint64_t target_db_server_buf_len); + // get the server with the highest priority execpt failed servers + int get(net::ObIpEndpoint &dest_addr); + // mark the previous visit server as failed then call get() + int get_next(net::ObIpEndpoint &dest_addr); + // num of target db server + inline int64_t num() const { return is_init_? target_db_server_.count() : 0; } + void reset(); + int64_t to_string(char *buf, const int64_t buf_len) const; + bool contains(net::ObIpEndpoint &addr); + + inline bool is_init() const { return is_init_; } + inline bool is_empty() const { return is_init_? target_db_server_.empty() : true; } + inline void reuse() { is_rand_ = false; last_failed_idx_ = -1; } + +private: + bool is_init_; + bool is_rand_; + int64_t last_failed_idx_; + char* target_db_server_buf_; + uint64_t target_db_server_buf_len_; + + ObTargetDbServerArray target_db_server_; + common::ObSEArray target_db_server_weight_; +}; + +} // end of namespace obproxy +} // end of namespace oceanbase +#endif \ No newline at end of file diff --git a/src/rpc/Makemodule.am b/src/rpc/Makemodule.am index 50120c2976e165e2e520f28c266849dfb0e75007..3b318e9fbf9df18811eadb0384def371460baede 100644 --- a/src/rpc/Makemodule.am +++ b/src/rpc/Makemodule.am @@ -20,6 +20,10 @@ rpc/obmysql/packet/ompk_handshake_response.h\ rpc/obmysql/packet/ompk_handshake_response.cpp\ rpc/obmysql/packet/ompk_prepare.h\ rpc/obmysql/packet/ompk_prepare.cpp\ +rpc/obmysql/packet/ompk_prepare_execute.h\ +rpc/obmysql/packet/ompk_prepare_execute.cpp\ +rpc/obmysql/packet/ompk_prepare_execute_req.h\ +rpc/obmysql/packet/ompk_prepare_execute_req.cpp\ rpc/obmysql/packet/ompk_ping.h\ rpc/obmysql/packet/ompk_ssl_request.h\ rpc/obmysql/packet/ompk_ssl_request.cpp diff --git a/src/rpc/ob_request.cpp b/src/rpc/ob_request.cpp index f2e4c658ea69d0ac87764cf285af43c6d7fc962f..4b692185a5a21fc1c3a1ad7b540ce80977507f72 100644 --- a/src/rpc/ob_request.cpp +++ b/src/rpc/ob_request.cpp @@ -24,8 +24,11 @@ char *ObRequest::easy_alloc(int64_t size) const if (NULL == ez_req_ || NULL == ez_req_->ms) { RPC_LOG(ERROR, "ez_req_ is not corret"); } else { - buf = easy_pool_alloc( - ez_req_->ms->pool, static_cast(size)); + /* this function is defined for c driver client compile */ + UNUSED(size); + buf = NULL; + // buf = easy_pool_alloc( + // ez_req_->ms->pool, static_cast(size)); } return static_cast(buf); } diff --git a/src/rpc/obmysql/ob_mysql_field.cpp b/src/rpc/obmysql/ob_mysql_field.cpp index dfd6198be09fcd9eb1400eb136497c44a1e64eaf..21d30995ee63bc907d1701a24a88f38aa2026148 100644 --- a/src/rpc/obmysql/ob_mysql_field.cpp +++ b/src/rpc/obmysql/ob_mysql_field.cpp @@ -94,6 +94,15 @@ int ObMySQLField::serialize_pro41(char *buf, const int64_t len, int64_t &pos) co LOG_WARN("serialize 0 failed", K(ret)); } } + if (OB_SUCC(ret) && OB_MYSQL_TYPE_COMPLEX == type_) { + if (OB_FAIL(ObMySQLUtil::store_str_v(buf, len, type_info_.relation_name_.ptr(), type_info_.relation_name_.length(), pos))) { + LOG_WARN("serialize relation_name_ failed", K(ret)); + } else if (OB_FAIL(ObMySQLUtil::store_str_v(buf, len, type_info_.type_name_.ptr(), type_info_.type_name_.length(),pos))) { + LOG_WARN("serialize type_name_ failed", K(ret)); + } else if (OB_FAIL(ObMySQLUtil::store_length(buf, len, type_info_.version_, pos))) { + LOG_WARN("serialize type_name_ failed", K(ret)); + } else { /* succ to write complex type */ } + } return ret; } diff --git a/src/rpc/obmysql/ob_mysql_field.h b/src/rpc/obmysql/ob_mysql_field.h index 32cfc7ab77d5749e3684f9a64ffbd4c430749cbb..e8001a6a95d60f956b9e0379149701b09b4491cf 100644 --- a/src/rpc/obmysql/ob_mysql_field.h +++ b/src/rpc/obmysql/ob_mysql_field.h @@ -22,6 +22,17 @@ namespace oceanbase { namespace obmysql { + +struct TypeInfo { + TypeInfo() : relation_name_(), type_name_(), version_(0), is_elem_type_(false) {} ; + common::ObString relation_name_; + common::ObString type_name_; + uint64_t version_; + ObObjType elem_type_; + bool is_elem_type_; + TO_STRING_KV(K_(relation_name), K_(type_name), K_(version), K_(elem_type), K_(is_elem_type)); +}; + class ObMySQLField { public: @@ -90,6 +101,7 @@ public: common::ObString org_cname_; // original column name common::ObAccuracy accuracy_; EMySQLFieldType type_; // value type + TypeInfo type_info_; // for complex type uint16_t flags_; // unsigned and so on... EMySQLFieldType default_value_; //default value, only effective when command was OB_MYSQL_COM_FIELD_LIST uint16_t charsetnr_; //character set of table diff --git a/src/rpc/obmysql/ob_mysql_global.h b/src/rpc/obmysql/ob_mysql_global.h index 0c6c1c36e2dba9d3cc2fb67e56cb4b6b7180223b..1acf42dca36be3f7ba0d1781996666bb540fd23a 100644 --- a/src/rpc/obmysql/ob_mysql_global.h +++ b/src/rpc/obmysql/ob_mysql_global.h @@ -99,6 +99,8 @@ enum EMySQLFieldType OB_MYSQL_TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE = 201, OB_MYSQL_TYPE_OB_TIMESTAMP_NANO = 202, OB_MYSQL_TYPE_OB_RAW = 203, + OB_MYSQL_TYPE_OB_UROWID = 209, + OB_MYSQL_TYPE_JSON = 245, OB_MYSQL_TYPE_NEWDECIMAL = 246, OB_MYSQL_TYPE_ENUM = 247, OB_MYSQL_TYPE_SET = 248, @@ -218,6 +220,9 @@ inline const char *get_emysql_field_type_str(const obmysql::EMySQLFieldType &typ case obmysql::OB_MYSQL_TYPE_STRING: str = "OB_MYSQL_TYPE_STRING"; break; + case obmysql::OB_MYSQL_TYPE_JSON: + str = "OB_MYSQL_TYPE_JSON"; + break; case obmysql::OB_MYSQL_TYPE_GEOMETRY: str = "OB_MYSQL_TYPE_GEOMETRY"; break; diff --git a/src/rpc/obmysql/ob_mysql_packet.cpp b/src/rpc/obmysql/ob_mysql_packet.cpp index 05fb8a8c654748ac7577e7a00bcc8b0224dbb269..ba3362a733659cfed396ca6b90e357eda4dec9c3 100644 --- a/src/rpc/obmysql/ob_mysql_packet.cpp +++ b/src/rpc/obmysql/ob_mysql_packet.cpp @@ -223,7 +223,8 @@ char const *get_mysql_cmd_str(ObMySQLCmd mysql_cmd) "Daemno", // OB_MYSQL_COM_DAEMON, "Binlog dump gtid", // OB_MYSQL_COM_BINLOG_DUMP_GTID, - // "Reset connection", // OB_MYSQL_COM_RESET_CONNECTION, + "Reset connection", // OB_MYSQL_COM_RESET_CONNECTION, + "Prepare Execute", // OB_MYSQL_COM_STMT_PREPARE_EXECUTE, "SEND PIECE DATA", "GET PIECE DATA", diff --git a/src/rpc/obmysql/ob_mysql_packet.h b/src/rpc/obmysql/ob_mysql_packet.h index f7a1df19ea515a550b7b282ba606dea0404e3498..fe3b9dd577a3661053a78a1494749ba9a78c00a4 100644 --- a/src/rpc/obmysql/ob_mysql_packet.h +++ b/src/rpc/obmysql/ob_mysql_packet.h @@ -64,7 +64,7 @@ enum ObMySQLCmd OB_MYSQL_COM_BINLOG_DUMP_GTID, - // OB_MYSQL_COM_RESET_CONNECTION, + OB_MYSQL_COM_RESET_CONNECTION, // 0x1f, 31 OB_MYSQL_COM_STMT_PREPARE_EXECUTE = OBPROXY_NEW_MYSQL_CMD_START, OB_MYSQL_COM_STMT_SEND_PIECE_DATA, OB_MYSQL_COM_STMT_GET_PIECE_DATA, diff --git a/src/rpc/obmysql/ob_mysql_util.h b/src/rpc/obmysql/ob_mysql_util.h index 13dce9db873b45369aeb0822617bbfadb0eff80c..8c9b9f367ba346d8bf1e2cdf770ef7ba6772c15e 100644 --- a/src/rpc/obmysql/ob_mysql_util.h +++ b/src/rpc/obmysql/ob_mysql_util.h @@ -236,7 +236,7 @@ int ObMySQLUtil::store_int1(char *buf, int64_t len, int8_t v, int64_t &pos) OB_LOG(WARN, "invalid argument", K(buf)); } else { if (len >= pos + 1) { - ob_int1store(buf + pos, v); + int1store(buf + pos, v); pos++; } else { ret = OB_SIZE_OVERFLOW; @@ -253,7 +253,7 @@ int ObMySQLUtil::store_int2(char *buf, int64_t len, int16_t v, int64_t &pos) OB_LOG(WARN, "invalid argument", K(buf)); } else { if (len >= pos + 2) { - ob_int2store(buf + pos, v); + int2store(buf + pos, v); pos += 2; } else { ret = OB_SIZE_OVERFLOW; @@ -270,7 +270,7 @@ int ObMySQLUtil::store_int3(char *buf, int64_t len, int32_t v, int64_t &pos) OB_LOG(WARN, "invalid argument", K(buf)); } else { if (len >= pos + 3) { - ob_int3store(buf + pos, v); + int3store(buf + pos, v); pos += 3; } else { ret = OB_SIZE_OVERFLOW; @@ -287,7 +287,7 @@ int ObMySQLUtil::store_int4(char *buf, int64_t len, int32_t v, int64_t &pos) OB_LOG(WARN, "invalid argument", K(buf)); } else { if (len >= pos + 4) { - ob_int4store(buf + pos, v); + int4store(buf + pos, v); pos += 4; } else { ret = OB_SIZE_OVERFLOW; @@ -304,7 +304,7 @@ int ObMySQLUtil::store_int5(char *buf, int64_t len, int64_t v, int64_t &pos) OB_LOG(WARN, "invalid argument", K(buf)); } else { if (len >= pos + 5) { - ob_int5store(buf + pos, v); + int5store(buf + pos, v); pos += 5; } else { ret = OB_SIZE_OVERFLOW; @@ -321,7 +321,7 @@ int ObMySQLUtil::store_int6(char *buf, int64_t len, int64_t v, int64_t &pos) OB_LOG(WARN, "invalid argument", K(buf)); } else { if (len >= pos + 6) { - ob_int6store(buf + pos, v); + int6store(buf + pos, v); pos += 6; } else { ret = OB_SIZE_OVERFLOW; @@ -338,7 +338,7 @@ int ObMySQLUtil::store_int8(char *buf, int64_t len, int64_t v, int64_t &pos) OB_LOG(WARN, "invalid argument", K(buf)); } else { if (len >= pos + 8) { - ob_int8store(buf + pos, v); + int8store(buf + pos, v); pos += 8; } else { ret = OB_SIZE_OVERFLOW; @@ -352,7 +352,7 @@ void ObMySQLUtil::get_int1(char *&pos, int8_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_sint1korr(pos); + v = sint1korr(pos); pos++; } } @@ -361,7 +361,7 @@ void ObMySQLUtil::get_int2(char *&pos, int16_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_sint2korr(pos); + v = sint2korr(pos); pos += 2; } } @@ -370,7 +370,7 @@ void ObMySQLUtil::get_int3(char *&pos, int32_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_sint3korr(pos); + v = sint3korr(pos); pos += 3; } } @@ -379,7 +379,7 @@ void ObMySQLUtil::get_int4(char *&pos, int32_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_sint4korr(pos); + v = sint4korr(pos); pos += 4; } } @@ -388,7 +388,7 @@ void ObMySQLUtil::get_int8(char *&pos, int64_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_sint8korr(pos); + v = sint8korr(pos); pos += 8; } } @@ -398,7 +398,7 @@ void ObMySQLUtil::get_int1(const char *&pos, int8_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_sint1korr(pos); + v = sint1korr(pos); pos++; } } @@ -407,7 +407,7 @@ void ObMySQLUtil::get_int2(const char *&pos, int16_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_sint2korr(pos); + v = sint2korr(pos); pos += 2; } } @@ -416,7 +416,7 @@ void ObMySQLUtil::get_int3(const char *&pos, int32_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_sint3korr(pos); + v = sint3korr(pos); pos += 3; } } @@ -425,7 +425,7 @@ void ObMySQLUtil::get_int4(const char *&pos, int32_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_sint4korr(pos); + v = sint4korr(pos); pos += 4; } } @@ -434,7 +434,7 @@ void ObMySQLUtil::get_int8(const char *&pos, int64_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_sint8korr(pos); + v = sint8korr(pos); pos += 8; } } @@ -444,7 +444,7 @@ void ObMySQLUtil::get_uint1(const char *&pos, uint8_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_uint1korr(pos); + v = uint1korr(pos); pos ++; } } @@ -453,7 +453,7 @@ void ObMySQLUtil::get_uint2(const char *&pos, uint16_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_uint2korr(pos); + v = uint2korr(pos); pos += 2; } } @@ -462,7 +462,7 @@ void ObMySQLUtil::get_uint3(const char *&pos, uint32_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_uint3korr(pos); + v = uint3korr(pos); pos += 3; } } @@ -471,7 +471,7 @@ void ObMySQLUtil::get_uint4(const char *&pos, uint32_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_uint4korr(pos); + v = uint4korr(pos); pos += 4; } } @@ -480,7 +480,7 @@ void ObMySQLUtil::get_uint5(const char *&pos, uint64_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_uint5korr(pos); + v = uint5korr(pos); pos += 5; } } @@ -489,7 +489,7 @@ void ObMySQLUtil::get_uint6(const char *&pos, uint64_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_uint6korr(pos); + v = uint6korr(pos); pos += 6; } } @@ -498,7 +498,7 @@ void ObMySQLUtil::get_uint8(const char *&pos, uint64_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_uint8korr(pos); + v = uint8korr(pos); pos += 8; } } @@ -508,7 +508,7 @@ void ObMySQLUtil::get_uint1(char *&pos, uint8_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_uint1korr(pos); + v = uint1korr(pos); pos ++; } } @@ -517,7 +517,7 @@ void ObMySQLUtil::get_uint2(char *&pos, uint16_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_uint2korr(pos); + v = uint2korr(pos); pos += 2; } } @@ -526,7 +526,7 @@ void ObMySQLUtil::get_uint3(char *&pos, uint32_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_uint3korr(pos); + v = uint3korr(pos); pos += 3; } } @@ -535,7 +535,7 @@ void ObMySQLUtil::get_uint4(char *&pos, uint32_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_uint4korr(pos); + v = uint4korr(pos); pos += 4; } } @@ -544,7 +544,7 @@ void ObMySQLUtil::get_uint5(char *&pos, uint64_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_uint5korr(pos); + v = uint5korr(pos); pos += 5; } } @@ -553,7 +553,7 @@ void ObMySQLUtil::get_uint6(char *&pos, uint64_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_uint6korr(pos); + v = uint6korr(pos); pos += 6; } } @@ -562,7 +562,7 @@ void ObMySQLUtil::get_uint8(char *&pos, uint64_t &v) if (OB_ISNULL(pos)) { OB_LOG(WARN, "invalid argument", K(pos)); } else { - v = ob_uint8korr(pos); + v = uint8korr(pos); pos += 8; } } diff --git a/src/rpc/obmysql/packet/ompk_handshake.cpp b/src/rpc/obmysql/packet/ompk_handshake.cpp index ec2d13db8d1a9a4dd75fc5004c379a7c2527d500..e7aa4381f718b3621d86291fc04153beeb05fb2f 100644 --- a/src/rpc/obmysql/packet/ompk_handshake.cpp +++ b/src/rpc/obmysql/packet/ompk_handshake.cpp @@ -55,6 +55,9 @@ OMPKHandshake::OMPKHandshake() server_capabilities_lower_.capability_flag_.OB_SERVER_SECURE_CONNECTION = 1; server_capabilities_upper_.capability_ = 0; + server_capabilities_upper_.capability_flag_.OB_SERVER_MULTIPLE_STATEMENTS = 1; + server_capabilities_upper_.capability_flag_.OB_SERVER_MULTIPLE_RESULTS = 1; + server_capabilities_upper_.capability_flag_.OB_SERVER_PS_MULTIPLE_RESULTS = 1; server_capabilities_upper_.capability_flag_.OB_SERVER_PLUGIN_AUTH = 1; //server_capabilities_upper_.capability_flag_.OB_SERVER_CONNECT_ATTRS = 1; @@ -66,11 +69,11 @@ OMPKHandshake::OMPKHandshake() auth_plugin_data_len_ = 0; } - server_language_ = 83;//utf8_bin - server_status_ = 0;// no this value in mysql protocol document + server_language_ = 46; // utf8mb4_bin + server_status_ = 0; // no this value in mysql protocol document //auth_plugin_data_len_ = 0; - memset(reserved_, 0, sizeof (reserved_)); - memset(auth_plugin_data2_, 'b', sizeof (auth_plugin_data2_) - 1); + memset(reserved_, 0, sizeof(reserved_)); + memset(auth_plugin_data2_, 'b', sizeof(auth_plugin_data2_) - 1); } OMPKHandshake::~OMPKHandshake() diff --git a/src/rpc/obmysql/packet/ompk_handshake_response.cpp b/src/rpc/obmysql/packet/ompk_handshake_response.cpp index 583cc5d306082356a33e1fc1293980635f8b3d51..1913071309feaad21f23ce772f766339cbf1cba7 100644 --- a/src/rpc/obmysql/packet/ompk_handshake_response.cpp +++ b/src/rpc/obmysql/packet/ompk_handshake_response.cpp @@ -48,7 +48,7 @@ int OMPKHandshakeResponse::decode() } if (OB_SUCC(ret) && pos < end) { - capability_.capability_ = ob_uint2korr(pos); + capability_.capability_ = uint2korr(pos); if (4 == len && !capability_.cap_flags_.OB_CLIENT_PROTOCOL_41) { ret = OB_NOT_SUPPORTED; LOG_ERROR("ob only support mysql client protocol 4.1", K(ret)); diff --git a/src/rpc/obmysql/packet/ompk_handshake_response.h b/src/rpc/obmysql/packet/ompk_handshake_response.h index ffbeb1cc010bf5baec261f01fb12bb1dd6afaff5..ecb0a0c6ca306b6376581720fee2a982c7693e7e 100644 --- a/src/rpc/obmysql/packet/ompk_handshake_response.h +++ b/src/rpc/obmysql/packet/ompk_handshake_response.h @@ -49,7 +49,7 @@ public: inline const ObString &get_auth_response() const { return auth_response_; } inline const ObString &get_database() const { return database_; } inline const ObString &get_auth_plugin_name() const { return auth_plugin_name_; } - inline const common::ObIArray &get_connect_attrs() const { return connect_attrs_; } + inline common::ObIArray &get_connect_attrs() { return connect_attrs_; } bool is_obproxy_client_mod() const; inline void set_capability_flags(const ObMySQLCapabilityFlags &cap) { capability_ = cap; } diff --git a/src/rpc/obmysql/packet/ompk_ok.h b/src/rpc/obmysql/packet/ompk_ok.h index 106b092d0c0a386da1af0b4652377cbc10496947..06ca3c18da513d31c17f4ee8d121afee832692c2 100644 --- a/src/rpc/obmysql/packet/ompk_ok.h +++ b/src/rpc/obmysql/packet/ompk_ok.h @@ -43,6 +43,7 @@ public: int set_message(const common::ObString &message); void set_changed_schema(const common::ObString &schema); void set_state_changed(const bool state_changed); + int add_system_var(const ObStringKV &system_var); int add_user_var(const ObStringKV &user_var); inline void set_capability(const ObMySQLCapabilityFlags &cap) { capability_ = cap; } diff --git a/src/rpc/obmysql/packet/ompk_prepare_execute.cpp b/src/rpc/obmysql/packet/ompk_prepare_execute.cpp new file mode 100644 index 0000000000000000000000000000000000000000..23bdf666f3c845d8458ecf8060b18ab795069f2c --- /dev/null +++ b/src/rpc/obmysql/packet/ompk_prepare_execute.cpp @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#define USING_LOG_PREFIX RPC_OBMYSQL +#include "ompk_prepare_execute.h" +#include "lib/oblog/ob_log_module.h" +#include "rpc/obmysql/ob_mysql_util.h" + +using namespace oceanbase::common; +using namespace oceanbase::obmysql; + +namespace oceanbase +{ +using namespace common; +namespace obmysql +{ + +int OMPKPrepareExecute::decode() +{ + int ret = OB_SUCCESS; + const char *pos = cdata_; + if (NULL != cdata_) { + ObMySQLUtil::get_uint1(pos, status_); + ObMySQLUtil::get_uint4(pos, statement_id_); + ObMySQLUtil::get_uint2(pos, column_num_); + ObMySQLUtil::get_uint2(pos, param_num_); + ObMySQLUtil::get_uint1(pos, reserved_); + ObMySQLUtil::get_uint2(pos, warning_count_); + ObMySQLUtil::get_uint4(pos, extend_flag_); + ObMySQLUtil::get_uint1(pos, has_result_set_); + } else { + ret = OB_INVALID_ARGUMENT; + LOG_ERROR("null input", K(ret), K(cdata_)); + } + return ret; +} + +int OMPKPrepareExecute::serialize(char* buffer, int64_t length, int64_t& pos) const +{ + int ret = OB_SUCCESS; + if (NULL == buffer || 0 >= length || pos < 0 || length - pos < get_serialize_size()) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(buffer), K(length), K(pos), "need_size", get_serialize_size()); + } else { + if (OB_SUCCESS != (ret = ObMySQLUtil::store_int1(buffer, length, status_, pos))) { + LOG_WARN("store failed", K(buffer), K(length), K_(status), K(pos)); + } else if (OB_FAIL(ObMySQLUtil::store_int4(buffer, length, statement_id_, pos))) { + LOG_WARN("store failed", K(buffer), K(length), K_(statement_id), K(pos)); + } else if (OB_FAIL(ObMySQLUtil::store_int2(buffer, length, column_num_, pos))) { + LOG_WARN("store failed", K(buffer), K(length), K_(column_num), K(pos)); + } else if (OB_FAIL(ObMySQLUtil::store_int2(buffer, length, param_num_, pos))) { + LOG_WARN("store failed", K(buffer), K(length), K_(param_num), K(pos)); + } else if (OB_FAIL(ObMySQLUtil::store_int1(buffer, length, reserved_, pos))) { + LOG_WARN("store failed", K(buffer), K(length), K_(reserved), K(pos)); + } else if (OB_FAIL(ObMySQLUtil::store_int2(buffer, length, warning_count_, pos))) { + LOG_WARN("store failed", K(buffer), K(length), K_(warning_count), K(pos)); + } else if (OB_FAIL(ObMySQLUtil::store_int4(buffer, length, extend_flag_, pos))) { + LOG_WARN("store failed", K(buffer), K(length), K_(extend_flag), K(pos)); + } else if (OB_FAIL(ObMySQLUtil::store_int1(buffer, length, has_result_set_, pos))) { + LOG_WARN("store failed", K(buffer), K(length), K_(has_result_set), K(pos)); + } + } + return ret; +} + +int64_t OMPKPrepareExecute::get_serialize_size() const +{ + int64_t len = 0; + len += 1; // status + len += 4; // statement id + len += 2; // column num + len += 2; // param num + len += 1; // reserved + len += 2; // warning count + len += 4; // extend flags + len += 1; // has result set + return len; +} + + + + +} //end of obmysql +} //end of oceanbase diff --git a/src/rpc/obmysql/packet/ompk_prepare_execute.h b/src/rpc/obmysql/packet/ompk_prepare_execute.h new file mode 100644 index 0000000000000000000000000000000000000000..f33c6ce18107698181ce08cdbc5d24d1cab0733e --- /dev/null +++ b/src/rpc/obmysql/packet/ompk_prepare_execute.h @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + + +#ifndef OCEANBASE_RPC_OBMYSQL_OMPK_PREPARE_EXECUTE_H_ +#define OCEANBASE_RPC_OBMYSQL_OMPK_PREPARE_EXECUTE_H_ + +#include "ompk_prepare_execute.h" +#include "rpc/obmysql/ob_mysql_packet.h" +#include "lib/utility/ob_macro_utils.h" + +namespace oceanbase +{ +namespace obmysql +{ + +/** + * This packet is response to OB_MYSQL_COM_STMT_PREPARE + * following with param desc && column desc packets + * + * status (1) -- [00] OK + * statement_id (4) -- statement-id + * num_columns (2) -- number of columns + * num_params (2) -- number of params + * reserved_ (1) -- [00] filler + * warning_count (2) -- number of warnings + */ + +class OMPKPrepareExecute: public ObMySQLPacket +{ +public: + OMPKPrepareExecute() : + status_(0), + statement_id_(0), + column_num_(0), + param_num_(0), + reserved_(0), + warning_count_(0), + extend_flag_(0), + has_result_set_(0) + {} + virtual ~OMPKPrepareExecute() {} + + int decode(); + virtual int serialize(char* buffer, int64_t length, int64_t& pos) const; + virtual int64_t get_serialize_size() const; + + inline void set_status(const uint8_t status) { status_ = status; } + inline void set_statement_id(const uint32_t id) { statement_id_ = id; } + inline void set_column_num(const uint16_t num) { column_num_ = num;} + inline void set_param_num(const uint16_t num) { param_num_ = num; } + inline void set_warning_count(const uint16_t count) { warning_count_ = count; } + inline void set_extend_flag(const uint32_t extend_flag) { extend_flag_ = extend_flag; } + inline void set_has_result_set(const uint8_t has_result_set) { has_result_set_ = has_result_set; } + + inline uint32_t get_statement_id() const { return statement_id_; } + inline uint16_t get_column_num() const { return column_num_;} + inline uint16_t get_param_num() const { return param_num_; } + inline uint16_t get_warning_count() const { return warning_count_; } + inline uint32_t get_extend_flag() const { return extend_flag_; } + inline uint8_t has_result_set() const { return has_result_set_; } + +private: + uint8_t status_; + uint32_t statement_id_; + uint16_t column_num_; + uint16_t param_num_; + uint8_t reserved_; + uint16_t warning_count_; + uint32_t extend_flag_; + uint8_t has_result_set_; + DISALLOW_COPY_AND_ASSIGN(OMPKPrepareExecute); +}; + +} //end of obmysql +} //end of oceanbase + + +#endif //OCEANBASE_RPC_OBMYSQL_OMPK_PREPARE_EXECUTE_H_ diff --git a/src/rpc/obmysql/packet/ompk_prepare_execute_req.cpp b/src/rpc/obmysql/packet/ompk_prepare_execute_req.cpp new file mode 100644 index 0000000000000000000000000000000000000000..533ec01e5d6c96e168ed86276f25e8e21e7e453c --- /dev/null +++ b/src/rpc/obmysql/packet/ompk_prepare_execute_req.cpp @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#define USING_LOG_PREFIX RPC_OBMYSQL +#include "ompk_prepare_execute_req.h" + +using namespace oceanbase::common; +using namespace oceanbase::obmysql; +namespace oceanbase +{ +using namespace common; +using namespace obproxy; +using namespace proxy; + +namespace obmysql +{ + +int OMPKPrepareExecuteReq::decode() +{ + int ret = OB_SUCCESS; + const char *pos = cdata_; + int64_t data_len = hdr_.len_; + if (NULL != cdata_) { + uint64_t query_len = 0; + // skip cmd + if (OB_FAIL(ObMysqlPacketUtil::get_uint1(pos, data_len, cmd_))) { + LOG_WARN("fail to get uint1", K(data_len), K(ret)); + } else if (OB_FAIL(ObMysqlPacketUtil::get_uint4(pos, data_len, statement_id_))) { + LOG_WARN("fail to get uint4", K(data_len), K(ret)); + } else if (OB_FAIL(ObMysqlPacketUtil::get_uint1(pos, data_len, flags_))) { + LOG_WARN("fail to get uint1", K(data_len), K(ret)); + } else if (OB_FAIL(ObMysqlPacketUtil::get_uint4(pos, data_len, iteration_count_))) { + LOG_WARN("fail to get uint4", K(data_len), K(ret)); + } else if (OB_FAIL(ObMysqlPacketUtil::get_length(pos, data_len, query_len))) { + LOG_WARN("fail to get length", K(data_len), K(ret)); + // skip query + } else if (FALSE_IT(pos += query_len)) { + } else if (OB_FAIL(ObMysqlPacketUtil::get_uint4(pos, data_len, param_num_))) { + LOG_WARN("fail to get uint4", K(data_len), K(ret)); + // skip null bitmap + } else if (param_num_ <= 0) { + LOG_DEBUG("skip read param related", K(param_num_)); + } else if (FALSE_IT(pos += (param_num_ + 7)/8)) { + } else if (OB_FAIL(ObMysqlPacketUtil::get_uint1(pos, data_len, new_params_bound_flag_))) { + LOG_WARN("fail to get uint1", K(data_len), K(ret)); + } else if (new_params_bound_flag_ == 1 + && OB_FAIL(ObMysqlRequestAnalyzer::parse_param_type(param_num_, param_types_, type_infos_, pos, data_len))) { + LOG_WARN("fail to parse param type", K_(param_num), K(pos), K(data_len), K(ret)); + } else { /* do nothing */ } + // skip the rest of data + } else { + ret = OB_INVALID_ARGUMENT; + LOG_ERROR("null input", K(ret), K(cdata_)); + } + return ret; +} + +} //end of obmysql +} //end of oceanbase diff --git a/src/rpc/obmysql/packet/ompk_prepare_execute_req.h b/src/rpc/obmysql/packet/ompk_prepare_execute_req.h new file mode 100644 index 0000000000000000000000000000000000000000..c1d148f83494ef92a57c50659687ae1c405a4173 --- /dev/null +++ b/src/rpc/obmysql/packet/ompk_prepare_execute_req.h @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + + +#ifndef OCEANBASE_RPC_OBMYSQL_OMPK_PREPARE_EXECUTE_REQ_H_ +#define OCEANBASE_RPC_OBMYSQL_OMPK_PREPARE_EXECUTE_REQ_H_ + +#include "rpc/obmysql/ob_mysql_util.h" +#include "lib/container/ob_se_array.h" +#include "lib/utility/ob_macro_utils.h" +#include "lib/oblog/ob_log_module.h" +#include "obproxy/proxy/mysqllib/ob_mysql_request_analyzer.h" +#include "obproxy/packet/ob_mysql_packet_util.h" +namespace oceanbase +{ + +namespace obmysql +{ + +/** + * This packet is request to OB_MYSQL_COM_STMT_PREPARE_EXECUTE + * following with param desc && column desc packets + * + */ + +class OMPKPrepareExecuteReq: public ObMySQLPacket +{ +public: + OMPKPrepareExecuteReq() : + cmd_(OB_MYSQL_COM_STMT_PREPARE_EXECUTE), + statement_id_(0), + flags_(0), + iteration_count_(0), + query_(NULL), + param_num_(0), + null_bitmap_(NULL), + new_params_bound_flag_(0) + {} + virtual ~OMPKPrepareExecuteReq() {} + + virtual int decode(); + + inline uint32_t get_statement_id() const { return statement_id_; } + inline uint32_t get_param_num() const { return param_num_; } + inline common::ObIArray& get_param_types() { return param_types_; } + inline common::ObIArray& get_type_infos() { return type_infos_; } + +private: + uint8_t cmd_; + uint32_t statement_id_; + uint8_t flags_; + uint32_t iteration_count_; + common::ObString query_; + uint32_t param_num_; + char* null_bitmap_; + uint8_t new_params_bound_flag_; + common::ObSEArray param_types_; + common::ObSEArray type_infos_; + // ingore value of eache parameter + uint32_t execute_mode_; + uint32_t num_close_stmt_count_; + uint32_t check_sum_; + uint32_t extend_flag_; + + DISALLOW_COPY_AND_ASSIGN(OMPKPrepareExecuteReq); +}; + +} //end of obmysql +} //end of oceanbase + + +#endif //OCEANBASE_RPC_OBMYSQL_OMPK_PREPARE_EXECUTE_REQ_H_ diff --git a/src/rpc/obmysql/packet/ompk_ssl_request.cpp b/src/rpc/obmysql/packet/ompk_ssl_request.cpp index 7576c75ce11a46fe3ae7798bbd16797bf98ca109..3c68242234361993b255f08b3481d8dc43ad542a 100644 --- a/src/rpc/obmysql/packet/ompk_ssl_request.cpp +++ b/src/rpc/obmysql/packet/ompk_ssl_request.cpp @@ -39,7 +39,7 @@ int OMPKSSLRequest::decode() ret = OB_ERR_UNEXPECTED; LOG_WARN("error ssl request packet", K(len), K(pos), K(end), K(ret)); } else { - capability_.capability_ = ob_uint2korr(pos); + capability_.capability_ = uint2korr(pos); if (OB_UNLIKELY(!capability_.cap_flags_.OB_CLIENT_SSL)) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("error capability from ssl request packet", K(ret)); diff --git a/src/share/config/ob_common_config.cpp b/src/share/config/ob_common_config.cpp index f02b5d6d8e066e65778cfaf150bb9c77c2fd02d0..7f15540a4c3e578aec6b0f5b587ca4bdf4a6a6d2 100644 --- a/src/share/config/ob_common_config.cpp +++ b/src/share/config/ob_common_config.cpp @@ -15,6 +15,7 @@ #include "share/config/ob_server_config.h" #include "common/ob_record_header.h" +static const char *ignore_config_opt_str[] = {"target_db_server"}; namespace oceanbase { namespace common @@ -44,9 +45,26 @@ ObCommonConfig::~ObCommonConfig() { } +// tmp use for opt str +int ObCommonConfig::add_extra_config_from_opt(const char *config_str, + int64_t version /* = 0 */ , + bool check_name /* = false */) +{ + return add_config(config_str, version, check_name, ",\n", ignore_config_opt_str); +} + int ObCommonConfig::add_extra_config(const char *config_str, int64_t version /* = 0 */ , bool check_name /* = false */) +{ + return add_config(config_str, version, check_name, "\n", NULL); +} + +int ObCommonConfig::add_config(const char *config_str, + int64_t version /* = 0 */ , + bool check_name /* = false */, + const char* delim, + const char* ignore_conf[]) { int ret = OB_SUCCESS; const int64_t MAX_OPTS_LENGTH = sysconf(_SC_ARG_MAX); @@ -67,7 +85,7 @@ int ObCommonConfig::add_extra_config(const char *config_str, } else { MEMCPY(buf, config_str, config_str_length); buf[config_str_length] = '\0'; - token = STRTOK_R(buf, ",\n", &saveptr); + token = STRTOK_R(buf, delim, &saveptr); } while (OB_SUCC(ret) && OB_LIKELY(NULL != token)) { @@ -86,7 +104,21 @@ int ObCommonConfig::add_extra_config(const char *config_str, value = saveptr_one; } + bool ignore = false; + if (OB_SUCC(ret) && OB_NOT_NULL(ignore_conf)) { + int64_t ignore_conf_num = sizeof(ignore_config_opt_str)/sizeof(char*); + for (int64_t i = 0; i < ignore_conf_num; i++) { + ObString conf(ignore_conf[i]); + if (OB_NOT_NULL(ignore_conf[i]) && conf.case_compare(name) == 0) { + ignore = true; + break; + } + } + } + if (OB_FAIL(ret)) { + } else if (ignore) { + LOG_INFO("Ignore config", K(name), K(value)); } else if (OB_ISNULL(pp_item = container_.get(ObConfigStringKey(name)))) { /* make compatible with previous configuration */ ret = check_name ? OB_INVALID_CONFIG : OB_SUCCESS; @@ -101,7 +133,7 @@ int ObCommonConfig::add_extra_config(const char *config_str, (*pp_item)->set_version(version); LOG_INFO("Load config succ", K(name), K(value)); } - token = STRTOK_R(NULL, ",\n", &saveptr); + token = STRTOK_R(NULL, delim, &saveptr); } if (NULL != buf) { diff --git a/src/share/config/ob_common_config.h b/src/share/config/ob_common_config.h index d1a51b6cdfc0dec450a50ec81ae06cbfc6386cb7..a34c9df029f669dc3071030d1e14b23dda4d9267 100644 --- a/src/share/config/ob_common_config.h +++ b/src/share/config/ob_common_config.h @@ -77,6 +77,15 @@ public: virtual int add_extra_config(const char *config_str, const int64_t version = 0, const bool check_name = false); + int add_extra_config_from_opt(const char *config_str, + const int64_t version = 0, + const bool check_name = false); + int add_config(const char *config_str, + int64_t version, + bool check_name, + const char* delim, + const char* ignore_conf[]); + virtual bool is_debug_sync_enabled() const { return false; } NEED_SERIALIZE_AND_DESERIALIZE; diff --git a/src/share/config/ob_config.cpp b/src/share/config/ob_config.cpp index 86e91e76e9497af695ddfc518d4498fd64c5b3c6..e62c40fdee4a2910164cb58c31cd29ea77c38d0d 100644 --- a/src/share/config/ob_config.cpp +++ b/src/share/config/ob_config.cpp @@ -110,6 +110,36 @@ void ObConfigItem::init(const char *name, } } +ObConfigItem::ObConfigItem(const ObConfigItem& item) +{ + set_name(item.name()); + set_value(item.str()); + set_info(item.info()); + set_section(item.section()); + set_visible_level(item.visible_level()); + set_range_str(item.range_str()); + set_version(item.version()); + need_reboot_ = item.need_reboot(); + is_initial_value_set_ = item.is_initial_value_set(); +} + +ObConfigItem& ObConfigItem::operator =(const ObConfigItem& item) +{ + if (this != &item) { + set_name(item.name()); + set_value(item.str()); + set_info(item.info()); + set_section(item.section()); + set_visible_level(item.visible_level()); + set_range_str(item.range_str()); + set_version(item.version()); + need_reboot_ = item.need_reboot(); + is_initial_value_set_ = item.is_initial_value_set(); + } + + return *this; +} + // ObConfigIntListItem ObConfigItem *ObConfigIntListItem::clone() { diff --git a/src/share/config/ob_config.h b/src/share/config/ob_config.h index 84929b1ae3c557a444780b51101975ec4e7f704d..bfe2042fd1c126da36ccba75301ab3613685959e 100644 --- a/src/share/config/ob_config.h +++ b/src/share/config/ob_config.h @@ -63,11 +63,13 @@ class ObConfigItem public: ObConfigItem(); virtual ~ObConfigItem(); + ObConfigItem(const ObConfigItem& item); + ObConfigItem& operator =(const ObConfigItem& item); void init(const char *name, const char *def, const char *info, CFG_EXTRA_INFO_DECLARE); void init(const char *name, const char *def, const char *range, const char *info, CFG_EXTRA_INFO_DECLARE); virtual bool parse_range(const char *range) { UNUSED(range); return true; } - virtual ObConfigItem *clone() = 0; + virtual ObConfigItem *clone() { return NULL; } int64_t to_string(char *buf, const int64_t buf_len) const; void add_checker(const ObConfigChecker *new_ck) @@ -156,11 +158,15 @@ public: virtual bool operator >=(const char *) const { return false; } virtual bool operator <(const char *) const { return false; } virtual bool operator <=(const char *) const { return false; } - virtual void set_initial_value() = 0; + virtual void set_initial_value() {} protected: //use current value to do input operation - virtual bool set(const char *str) = 0; + virtual bool set(const char *str) + { + UNUSED(str); + return true; + } const ObConfigChecker *ck_; int64_t version_; @@ -172,9 +178,6 @@ protected: char section_str_[OB_MAX_CONFIG_SECTION_LEN]; char visible_level_str_[OB_MAX_CONFIG_VISIBLE_LEVEL_LEN]; char range_str_[OB_RANGE_STR_BUFSIZ]; - -private: - DISALLOW_COPY_AND_ASSIGN(ObConfigItem); }; class ObConfigIntListItem @@ -346,7 +349,7 @@ public: virtual bool parse_range(const char *range); virtual void set_initial_value() { initial_value_ = value_; is_initial_value_set_ = true; } -protected: +public: //use current value to do input operation bool set(const char *str); virtual int64_t parse(const char *str, bool &valid) const = 0; @@ -604,10 +607,11 @@ public: operator const bool &() const { return ((need_reboot_ && is_initial_value_set_) ? initial_value_ : value_); } ObConfigBoolItem &operator = (const bool value) { set_value(value ? "True" : "False"); return *this; } virtual void set_initial_value() { initial_value_ = value_; is_initial_value_set_ = true; } + const bool get_value() { return value_; } + bool set(const char *str); protected: //use current value to do input operation - bool set(const char *str); bool parse(const char *str, bool &valid) const; private: diff --git a/src/share/config/ob_config_helper.cpp b/src/share/config/ob_config_helper.cpp index cc4a43d5ac25f10725cdbfc2ccac3b4db42138f5..5e9bca71fdf3dca57193e5a051ae597faa3de0a9 100644 --- a/src/share/config/ob_config_helper.cpp +++ b/src/share/config/ob_config_helper.cpp @@ -17,11 +17,16 @@ namespace oceanbase { namespace common { + bool ObConfigIpChecker::check(const ObConfigItem &t) const { - struct sockaddr_in sa; - int result = inet_pton(AF_INET, t.str(), &(sa.sin_addr)); - return result != 0; + struct in_addr in; + int result = inet_pton(AF_INET, t.str(), &in); + if (result != 1) { + struct in6_addr in6; + result = inet_pton(AF_INET6, t.str(), &in6); + } + return result == 1; } ObConfigConsChecker:: ~ObConfigConsChecker() diff --git a/src/share/inner_table/ob_inner_table_schema_constants.h b/src/share/inner_table/ob_inner_table_schema_constants.h index 6dfa83734ecec4eccf7a4d19a8108d11f0aad996..dbad5b7aebae40fa70c38f2b2f52ef4cc8c8652c 100644 --- a/src/share/inner_table/ob_inner_table_schema_constants.h +++ b/src/share/inner_table/ob_inner_table_schema_constants.h @@ -298,6 +298,7 @@ const char *const OB_HELP_KEYWORD_TNAME = "help_keyw const char *const OB_HELP_RELATION_TNAME = "help_relation"; const char *const OB_ALL_LOCAL_INDEX_STATUS_TNAME = "__all_local_index_status"; const char *const OB_ALL_DUMMY_TNAME = "__all_dummy"; +const char *const OB_ALL_BINLOG_DUMMY_TNAME = "__all_binlog_dummy"; const char *const OB_ALL_FROZEN_MAP_TNAME = "__all_frozen_map"; const char *const OB_ALL_CLOG_HISTORY_INFO_TNAME = "__all_clog_history_info"; const char *const OB_ALL_CLOG_HISTORY_INFO_V2_TNAME = "__all_clog_history_info_v2"; @@ -486,6 +487,12 @@ const char *const OB_ALL_VIRTUAL_SESSTAT_I1_TNAME = "__idx_109 const char *const OB_ALL_VIRTUAL_SYSSTAT_I1_TNAME = "__idx_1099511638797_i1"; const char *const OB_ALL_VIRTUAL_SQL_AUDIT_I1_TNAME = "__idx_1099511638807_i1"; +// 4.0 schema +const char* const OB_ALL_VIRTUAL_PROXY_ROUTINE_TNAME = "__all_virtual_proxy_routine"; +const char* const DBA_OB_ZONES_VNAME = "DBA_OB_ZONES"; +const char* const DBA_OB_SERVERS_VNAME = "DBA_OB_SERVERS"; +const char* const DBA_OB_TENANTS_VNAME = "DBA_OB_TENANTS"; + // initial data for __all_privilege struct PrivilegeRow { const char *privilege_; diff --git a/src/share/part/ob_part_desc.cpp b/src/share/part/ob_part_desc.cpp index f59bd5e7eaba42d136c4745513d17f07d1760d0c..58fdc09f67ce6497767c93f297cb27de460a7134 100644 --- a/src/share/part/ob_part_desc.cpp +++ b/src/share/part/ob_part_desc.cpp @@ -13,6 +13,7 @@ #include "share/part/ob_part_desc.h" #include "common/ob_obj_cast.h" #include "obproxy/proxy/mysqllib/ob_proxy_session_info.h" +#include "obproxy/proxy/route/obproxy_expr_calculator.h" namespace oceanbase @@ -23,19 +24,24 @@ namespace common int ObPartDesc::get_part(common::ObNewRange &range, common::ObIAllocator &allocator, common::ObIArray &part_ids, - ObPartDescCtx &ctx) + ObPartDescCtx &ctx, + common::ObIArray &tablet_ids) { UNUSED(range); UNUSED(allocator); UNUSED(part_ids); UNUSED(ctx); + UNUSED(tablet_ids); return OB_NOT_IMPLEMENT; } -int ObPartDesc::get_part_by_num(const int64_t num, common::ObIArray &part_ids) +int ObPartDesc::get_part_by_num(const int64_t num, + common::ObIArray &part_ids, + common::ObIArray &tablet_ids) { UNUSED(num); UNUSED(part_ids); + UNUSED(tablet_ids); return OB_NOT_IMPLEMENT; } @@ -87,9 +93,47 @@ int ObPartDesc::build_dtc_params(obproxy::proxy::ObClientSessionInfo *session_in return ret; } -void ObPartDesc::set_accuracy(const ObProxyPartKeyAccuracy &accuracy) +int ObPartDesc::cast_obj(ObObj &src_obj, + ObObj &target_obj, + ObIAllocator &allocator, + ObPartDescCtx &ctx, + ObAccuracy &accuracy) { - accuracy_ = accuracy; + return cast_obj(src_obj, target_obj.get_type(), target_obj.get_collation_type(), allocator, ctx, accuracy); +} + +int ObPartDesc::cast_obj(ObObj &src_obj, + ObObjType obj_type, + ObCollationType cs_type, + ObIAllocator &allocator, + ObPartDescCtx &ctx, + ObAccuracy &accuracy) +{ + int ret = OB_SUCCESS; + COMMON_LOG(DEBUG, "begin to cast obj", K(src_obj), K(obj_type), K(cs_type)); + + ObTimeZoneInfo tz_info; + ObDataTypeCastParams dtc_params; + + if (OB_FAIL(obproxy::proxy::ObExprCalcTool::build_dtc_params_with_tz_info(ctx.get_session_info(), + obj_type, tz_info, dtc_params))) { + COMMON_LOG(WARN, "fail to build dtc params with ctx session", K(ret), K(obj_type)); + } else { + ObCastCtx cast_ctx(&allocator, &dtc_params, CM_NULL_ON_WARN, cs_type); + const ObObj *res_obj = &src_obj; + + // use src_obj as buf_obj + if (OB_FAIL(ObObjCasterV2::to_type(obj_type, cs_type, cast_ctx, src_obj, src_obj))) { + COMMON_LOG(WARN, "failed to cast obj", K(ret), K(src_obj), K(obj_type), K(cs_type)); + } else if (ctx.need_accurate() + && OB_FAIL(obj_accuracy_check(cast_ctx, accuracy, cs_type, *res_obj, src_obj, res_obj))) { + COMMON_LOG(WARN, "fail to obj accuracy check", K(ret), K(src_obj)); + } else { + COMMON_LOG(DEBUG, "end to cast obj for range", K(src_obj), K(obj_type), K(cs_type)); + } + } + + return ret; } } // end of common diff --git a/src/share/part/ob_part_desc.h b/src/share/part/ob_part_desc.h index fac0180a134437b6609f473cc0407ebdc4c4d0ee..77e271e762e33c86219445ec812983624e1d0f86 100644 --- a/src/share/part/ob_part_desc.h +++ b/src/share/part/ob_part_desc.h @@ -18,6 +18,7 @@ #include "lib/timezone/ob_time_convert.h" #include "share/part/ob_part_mgr_util.h" #include "obproxy/opsql/expr_parser/ob_expr_parse_result.h" +#include "common/ob_row.h" namespace oceanbase { @@ -35,26 +36,31 @@ namespace common class ObPartDescCtx { public: - ObPartDescCtx() : session_info_(NULL), need_accurate_(false) {} + ObPartDescCtx() : session_info_(NULL), need_accurate_(false), cluster_version_(0) {} ObPartDescCtx(obproxy::proxy::ObClientSessionInfo *session_info) - : session_info_(session_info), need_accurate_(false) {} - ObPartDescCtx(obproxy::proxy::ObClientSessionInfo *session_info, bool need_accurate) - : session_info_(session_info), need_accurate_(need_accurate) {} + : session_info_(session_info), need_accurate_(false), cluster_version_(0) {} + ObPartDescCtx(obproxy::proxy::ObClientSessionInfo *session_info, bool need_accurate, const int64_t cluster_version) + : session_info_(session_info), need_accurate_(need_accurate), cluster_version_(cluster_version) {} ~ObPartDescCtx() {} - + obproxy::proxy::ObClientSessionInfo *get_session_info() { return session_info_; } bool need_accurate() { return need_accurate_; } + int64_t get_cluster_version() const { return cluster_version_; } private: obproxy::proxy::ObClientSessionInfo *session_info_; /* need accurate the part key result or not, currently only support insert stmt, need to support update set=x stmt */ - bool need_accurate_; + bool need_accurate_; + int64_t cluster_version_; }; class ObPartDesc { public: + ObPartDesc() : part_level_(share::schema::PARTITION_LEVEL_ZERO), tablet_id_array_(NULL) {} + virtual ~ObPartDesc() {} + /* * get partition id according to range * @in param range @@ -66,8 +72,10 @@ public: virtual int get_part(common::ObNewRange &range, common::ObIAllocator &allocator, common::ObIArray &part_ids, - ObPartDescCtx &ctx); - virtual int get_part_by_num(const int64_t num, common::ObIArray &part_ids); + ObPartDescCtx &ctx, + common::ObIArray &tablet_ids); + virtual int get_part_by_num(const int64_t num, common::ObIArray &part_ids, + common::ObIArray &tablet_ids); void set_part_level(share::schema::ObPartitionLevel part_level) { part_level_ = part_level; } share::schema::ObPartitionLevel get_part_level() { return part_level_; } void set_part_func_type(share::schema::ObPartitionFuncType part_func_type) { part_func_type_ = part_func_type; } @@ -75,15 +83,26 @@ public: int build_dtc_params(obproxy::proxy::ObClientSessionInfo *session_info, ObObjType obj_type, ObDataTypeCastParams &dtc_params); - void set_accuracy(const ObProxyPartKeyAccuracy &accuracy); + ObIArray &get_accuracies() { return accuracies_; } - ObPartDesc() : part_level_(share::schema::PARTITION_LEVEL_ZERO) {}; - virtual ~ObPartDesc() {}; + int cast_obj(ObObj &src_obj, + ObObj &target_obj, + ObIAllocator &allocator, + ObPartDescCtx &ctx, + ObAccuracy &accuracy); + int cast_obj(ObObj &src_obj, + ObObjType obj_type, + ObCollationType cs_type, + ObIAllocator &allocator, + ObPartDescCtx &ctx, + ObAccuracy &accuracy); + DECLARE_VIRTUAL_TO_STRING = 0; share::schema::ObPartitionLevel part_level_; share::schema::ObPartitionFuncType part_func_type_; - ObProxyPartKeyAccuracy accuracy_; + ObSEArray accuracies_; + int64_t *tablet_id_array_; }; } diff --git a/src/share/part/ob_part_desc_hash.cpp b/src/share/part/ob_part_desc_hash.cpp index e0d994c4c4e438b8a5a35bdb2216cbede23508a2..e90b14212f699bcd63dc901cc88aa87b54152885 100644 --- a/src/share/part/ob_part_desc_hash.cpp +++ b/src/share/part/ob_part_desc_hash.cpp @@ -27,44 +27,94 @@ ObPartDescHash::ObPartDescHash() : is_oracle_mode_(false) { } -/* +/** GET PARTITION ID - - If input is not single int value, get all partition ids; otherwise, get the particular one. + Hash partition only route like 'by hash(c1,c2) ... where c1=xx and c2=xx', + only use range.start_key_ to calc, because when condition is like 'c1=xx', + start_key_[i] == end_key_[i] + @param range (xxx,yyy,min,min ; xxx,yyy,max,max) + @param allocator + @param part_ids[out] + @param ctx */ int ObPartDescHash::get_part(ObNewRange &range, ObIAllocator &allocator, ObIArray &part_ids, - ObPartDescCtx &ctx) + ObPartDescCtx &ctx, + ObIArray &tablet_ids) { - int ret = OB_SUCCESS; - if (1 != range.get_start_key().get_obj_cnt()) { // single value - ret = OB_INVALID_ARGUMENT; - COMMON_LOG(DEBUG, "hash part should be single key", - "obj_cnt", range.get_start_key().get_obj_cnt(), K(ret)); - } else { - int64_t part_idx = -1; - ObObj &src_obj = const_cast(range.get_start_key().get_obj_ptr()[0]); - if (is_oracle_mode_) { - ret = calc_value_for_oracle(src_obj, allocator, part_idx, ctx); + int ret = OB_SUCCESS; + // 1. Cast obj + // provide all objs are valid. + // "valid" means the obj not min or max + int64_t valid_obj_cnt = range.start_key_.get_obj_cnt(); + for (int64_t i = 0; OB_SUCC(ret) && i < range.start_key_.get_obj_cnt(); i++) { + // if obj is min or max, means all valid obj has been casted + if (range.start_key_.get_obj_ptr()[i].is_max_value() || + range.start_key_.get_obj_ptr()[i].is_min_value()) { + // minus the number of invalid obj + valid_obj_cnt = valid_obj_cnt - (range.start_key_.get_obj_cnt() - i); + // not need to cast any more and break loop + if (valid_obj_cnt == 0) { + ret = OB_INVALID_ARGUMENT; + COMMON_LOG(WARN, "not support hash partition calc with range", K(range)); + } + break; } else { - ret = calc_value_for_mysql(src_obj, allocator, part_idx); + ObObj *src_obj = const_cast(&range.start_key_.get_obj_ptr()[i]); + if (OB_ISNULL(src_obj)) { + // here src_obj shouldn't be null + ret = OB_ERR_NULL_VALUE; + COMMON_LOG(ERROR, "unexpected null pointer src_obj"); + } else if (src_obj->is_null()) { + // here src_obj shouldn't be null type + ret = OB_OBJ_TYPE_ERROR; + COMMON_LOG(ERROR, "unexpected null type", K(src_obj)); + // oracle mode cast all valid objs to target type + } else if (is_oracle_mode_) { + if(OB_FAIL(cast_obj(*src_obj, obj_types_[i], cs_types_[i], allocator, ctx, accuracies_.at(i)))) { + COMMON_LOG(WARN, "cast obj failed", K(src_obj), "obj_type", obj_types_[i], "cs_type", cs_types_[i]); + // TODO: handle failure + } + // mysql mode only cast first valid obj to int type then break loop + } else /*if (is_mysql_mode_) */ { + ObCastCtx cast_ctx(&allocator, NULL, CM_NULL_ON_WARN, CS_TYPE_INVALID); + if (OB_FAIL(ObObjCasterV2::to_type(ObIntType, cs_types_[i], cast_ctx, *src_obj, *src_obj))) { + COMMON_LOG(WARN, "failed to cast to ObIntType", K(src_obj), K(ret)); + } + break; + } } + } - if (OB_SUCC(ret)) { - int64_t part_id = -1; - if (OB_FAIL(get_part_hash_idx(part_idx, part_id))) { - COMMON_LOG(WARN, "fail to get part hash id", K(ret)); - } else if (OB_FAIL(part_ids.push_back(part_id))) { - COMMON_LOG(WARN, "fail to push part_id", K(ret)); - } + // 2. Calc partition id + int64_t part_idx = -1; + if (OB_SUCC(ret)) { + // hash val + int64_t result = 0; + if (is_oracle_mode_) { + // oracle mode: use obj to calc hash val + ret = calc_value_for_oracle(range.start_key_.get_obj_ptr(), valid_obj_cnt, result, ctx); + } else { + // mysql mode: use single obj to calc hash val + ret = calc_value_for_mysql(range.start_key_.get_obj_ptr(), result); } + int64_t part_id = -1; + if (OB_SUCC(ret) && OB_FAIL(calc_hash_part_idx(result, part_num_, part_idx))) { + COMMON_LOG(WARN, "fail to cal hash part idx", K(ret), K(result), K(part_num_)); + } else if (OB_FAIL(get_part_hash_idx(part_idx, part_id))) { + COMMON_LOG(WARN, "fail to get part hash id", K(part_idx), K(ret)); + } else if (OB_FAIL(part_ids.push_back(part_id))) { + COMMON_LOG(WARN, "fail to push part_id", K(ret)); + } else if (NULL != tablet_id_array_ && OB_FAIL(tablet_ids.push_back(tablet_id_array_[part_idx]))) { + COMMON_LOG(WARN, "fail to push tablet_id", K(ret)); + } else {} } return ret; } -int ObPartDescHash::get_part_by_num(const int64_t num, common::ObIArray &part_ids) +int ObPartDescHash::get_part_by_num(const int64_t num, common::ObIArray &part_ids, common::ObIArray &tablet_ids) { int ret = OB_SUCCESS; int64_t part_id = -1; @@ -73,6 +123,8 @@ int ObPartDescHash::get_part_by_num(const int64_t num, common::ObIArray COMMON_LOG(WARN, "fail to get part hash id", K(num), K(ret)); } else if (OB_FAIL(part_ids.push_back(part_id))) { COMMON_LOG(WARN, "fail to push part_id", K(ret)); + } else if (NULL != tablet_id_array_ && OB_FAIL(tablet_ids.push_back(tablet_id_array_[part_idx]))) { + COMMON_LOG(WARN, "fail to push tablet_id", K(ret)); } return ret; } @@ -92,7 +144,7 @@ bool ObPartDescHash::is_oracle_supported_type(const ObObjType type) case ObTimestampLTZType: case ObTimestampNanoType: case ObRawType: - /* + /* case ObIntervalYMType: case ObIntervalDSType: */ @@ -110,7 +162,7 @@ bool ObPartDescHash::is_oracle_supported_type(const ObObjType type) return supported; } -uint64_t ObPartDescHash::calc_hash_value_with_seed(const ObObj &obj, int64_t seed) +uint64_t ObPartDescHash::calc_hash_value_with_seed(const ObObj &obj, const int64_t cluster_version, int64_t seed) { uint64 hval = 0; ObObjType type = obj.get_type(); @@ -128,13 +180,17 @@ uint64_t ObPartDescHash::calc_hash_value_with_seed(const ObObj &obj, int64_t see } obj_trimmed.set_collation_type(obj.get_collation_type()); obj_trimmed.set_string(type, obj.get_string_ptr(), val_len); - if (share::schema::PARTITION_FUNC_TYPE_HASH_V2 == part_func_type_) { + if ((IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version) + && share::schema::PARTITION_FUNC_TYPE_HASH_V2 == part_func_type_) + || (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version))) { hval = obj_trimmed.hash_murmur(seed); } else { hval = obj_trimmed.hash(seed); } } else { - if (share::schema::PARTITION_FUNC_TYPE_HASH_V2 == part_func_type_) { + if ((IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version) + && share::schema::PARTITION_FUNC_TYPE_HASH_V2 == part_func_type_) + || (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version))) { hval = obj.hash_murmur(seed); } else { hval = obj.hash(seed); @@ -143,103 +199,91 @@ uint64_t ObPartDescHash::calc_hash_value_with_seed(const ObObj &obj, int64_t see return hval; } - -int ObPartDescHash::calc_value_for_oracle(ObObj &src_obj, - ObIAllocator &allocator, - int64_t &part_idx, +int ObPartDescHash::calc_value_for_oracle(const ObObj *objs, + int64_t objs_cnt, + int64_t &result, ObPartDescCtx &ctx) { int ret = OB_SUCCESS; - - ObTimeZoneInfo tz_info; - ObDataTypeCastParams dtc_params; - - if (OB_FAIL(obproxy::proxy::ObExprCalcTool::build_dtc_params_with_tz_info(ctx.get_session_info(), - obj_type_, tz_info, dtc_params))) { - COMMON_LOG(WARN, "fail to build dtc params with tz info", K(ret)); - } else { - lib::set_oracle_mode(true); - - uint64_t hash_val = 0; - ObCastCtx cast_ctx(&allocator, &dtc_params, CM_NULL_ON_WARN, cs_type_); - const ObObj *res_obj = &src_obj; - - ObAccuracy accuracy(accuracy_.valid_, accuracy_.length_, accuracy_.precision_, accuracy_.scale_); - - // use src_obj as buf_obj - COMMON_LOG(DEBUG, "begin to cast value for hash oracle", K(src_obj), K(cs_type_)); - if (OB_FAIL(ObObjCasterV2::to_type(obj_type_, cs_type_, cast_ctx, src_obj, src_obj))) { - COMMON_LOG(WARN, "failed to cast obj", K(ret), K(src_obj), K(obj_type_), K(cs_type_)); - } else if (ctx.need_accurate() - && OB_FAIL(obj_accuracy_check(cast_ctx, accuracy, cs_type_, *res_obj, src_obj, res_obj))) { - COMMON_LOG(WARN, "fail to obj accuracy check", K(ret), K(src_obj), K(obj_type_)); + uint64_t hash_code = 0; + if (OB_ISNULL(objs) || 0 == objs_cnt) { + ret = OB_ERR_UNEXPECTED; + COMMON_LOG(WARN, "objs_stack is null or number incorrect", K(objs), K(objs_cnt), K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < objs_cnt; ++i) { + const ObObj &obj = objs[i]; + const ObObjType type = obj.get_type(); + if (ObNullType == type) { + //do nothing, hash_code not changed + } else if (!is_oracle_supported_type(type)) { + ret = OB_INVALID_ARGUMENT; + COMMON_LOG(WARN, "type is wrong", K(ret), K(obj), K(type)); } else { - COMMON_LOG(DEBUG, "finish to cast and accuracy values for hash oracle", K(src_obj), K(obj_type_), K(cs_type_)); - // calculate hash value - const ObObjType type = src_obj.get_type(); - if (ObNullType == type) { - //do nothing, hash_code not changed - } else if (!is_oracle_supported_type(type)) { - ret = OB_INVALID_ARGUMENT; - COMMON_LOG(WARN, "type is wrong", K(ret), K(src_obj), K(type)); - } else { - hash_val = calc_hash_value_with_seed(src_obj, hash_val); - } + hash_code = calc_hash_value_with_seed(obj, ctx.get_cluster_version(), hash_code); } + } + result = static_cast(hash_code); + result = result < 0 ? -result : result; + if (OB_SUCC(ret)) { + COMMON_LOG(TRACE, "succ to calc hash value with oracle mode", KP(objs), K(objs[0]), K(objs_cnt), K(result), K(ret)); + } else { + COMMON_LOG(WARN, "fail to calc hash value with oracle mode", KP(objs), K(objs_cnt), K(result), K(ret)); + } + return ret; +} - lib::set_oracle_mode(false); - - // calculate logic partition - if (OB_SUCC(ret)) { - int64_t N = 0; - int64_t powN = 0; - const static int64_t max_part_num_log2 = 64; - - int64_t result_num = static_cast(hash_val); - result_num = result_num < 0 ? -result_num : result_num; - - N = static_cast(std::log(part_num_) / std::log(2)); - if (N >= max_part_num_log2) { - ret = OB_ERR_UNEXPECTED; - COMMON_LOG(WARN, "result is too big", K(N), K(part_num_), K(result_num)); +int ObPartDescHash::calc_value_for_mysql(const ObObj *obj, int64_t &result) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(obj)) { + ret = OB_ERR_UNEXPECTED; + COMMON_LOG(WARN, "unexpected null ptr", K(ret)); + } else if (OB_UNLIKELY(obj->is_null())) { + result = 0; + } else { + int64_t num = 0; + if (OB_FAIL(obj->get_int(num))) { + COMMON_LOG(WARN, "fail to get int", K(obj), K(ret)); + } else { + if (OB_UNLIKELY(INT64_MIN == num)) { + num = INT64_MAX; } else { - powN = (1ULL << N); - part_idx = result_num % powN; - if (part_idx + powN < part_num_ && (result_num & powN) == powN) { - part_idx += powN; - } + num = num < 0 ? -num : num; } - COMMON_LOG(DEBUG, "get hash part idx for oracle mode", - K(ret), K(result_num), K(part_num_), K(N), K(powN), K(part_idx)); + result = num; } } - + COMMON_LOG(TRACE, "calc hash value with mysql mode", K(ret)); return ret; } -int ObPartDescHash::calc_value_for_mysql(ObObj &src_obj, ObIAllocator &allocator, int64_t &part_idx) +int ObPartDescHash::calc_hash_part_idx(const uint64_t val, + const int64_t part_num, + int64_t &partition_idx) { int ret = OB_SUCCESS; - - ObCastCtx cast_ctx(&allocator, NULL, CM_NULL_ON_WARN, CS_TYPE_INVALID); - ObObjType target_type = ObIntType; - if (OB_FAIL(ObObjCasterV2::to_type(target_type, cs_type_, cast_ctx, src_obj, src_obj))) { - COMMON_LOG(INFO, "failed to cast to target type", K(target_type), K(src_obj), K(ret)); - } else { - int64_t val = 0; - if (OB_FAIL(src_obj.get_int(val))) { - COMMON_LOG(WARN, "fail to get int", K(src_obj), K(ret)); + int64_t N = 0; + int64_t powN = 0; + const static int64_t max_part_num_log2 = 64; + // This function is used by SQL. Should ensure SQL runs in MySQL mode when query sys table. + if (is_oracle_mode_) { + // It will not be a negative number, so use forced conversion instead of floor + N = static_cast(std::log(part_num) / std::log(2)); + if (N >= max_part_num_log2) { + ret = OB_ERR_UNEXPECTED; + COMMON_LOG(WARN, "result is too big", K(N), K(part_num), K(val)); } else { - if (OB_UNLIKELY(INT64_MIN == val)) { - val = INT64_MAX; - } else { - val = val < 0 ? -val : val; + powN = (1ULL << N); + partition_idx = val & (powN - 1); //pow(2, N)); + if (partition_idx + powN < part_num && (val & powN) == powN) { + partition_idx += powN; } - part_idx = val % part_num_; - COMMON_LOG(DEBUG, "get hash part idx for mysql mode", K(ret), K(val), K(part_num_), K(part_idx)); } + COMMON_LOG(DEBUG, "get hash part idx", K(lbt()), K(ret), K(val), K(part_num), K(N), K(powN), K(partition_idx)); + } else { + partition_idx = val % part_num; + COMMON_LOG(DEBUG, "get hash part idx", K(lbt()), K(ret), K(val), K(part_num), K(partition_idx)); } - return ret; } diff --git a/src/share/part/ob_part_desc_hash.h b/src/share/part/ob_part_desc_hash.h index 67f9b025eb09360fd38ea7bb6527ea65020fb4a8..2d5b10eefcbecbf0dbfe815adb1be59aa81c057b 100644 --- a/src/share/part/ob_part_desc_hash.h +++ b/src/share/part/ob_part_desc_hash.h @@ -16,6 +16,7 @@ //#include "common/ob_object.h" #include "share/part/ob_part_desc.h" #include "share/part/ob_part_mgr_util.h" +#include "proxy/route/obproxy_part_mgr.h" namespace oceanbase { @@ -31,17 +32,19 @@ public: virtual int get_part(ObNewRange &range, ObIAllocator &allocator, ObIArray &part_ids, - ObPartDescCtx &ctx); - virtual int get_part_by_num(const int64_t num, ObIArray &part_ids); + ObPartDescCtx &ctx, + ObIArray &tablet_ids); + virtual int get_part_by_num(const int64_t num, ObIArray &part_ids, ObIArray &tablet_ids); void set_part_num(int64_t part_num) { part_num_ = part_num; } void set_part_space(int64_t part_space) { part_space_ = part_space; } void set_first_part_id(int64_t first_part_id) { first_part_id_ = first_part_id; } int64_t get_first_part_id() { return first_part_id_; } - void set_part_key_type(const ObObjType obj_type) { obj_type_ = obj_type; } - void set_part_key_cs_type(const ObCollationType cs_type) { cs_type_ = cs_type; } void set_part_array(int64_t *part_array) { part_array_ = part_array; } void set_oracle_mode(bool is_oracle_mode) { is_oracle_mode_ = is_oracle_mode; } + ObIArray &get_obj_types() { return obj_types_; } + ObIArray &get_cs_types() { return cs_types_; } + VIRTUAL_TO_STRING_KV("part_type", "hash", K_(is_oracle_mode), K_(part_num), @@ -49,20 +52,21 @@ public: K_(part_level), K_(part_func_type)); private: - uint64_t calc_hash_value_with_seed(const ObObj &obj, int64_t seed); + uint64_t calc_hash_value_with_seed(const ObObj &obj, const int64_t cluster_version, int64_t seed); bool is_oracle_supported_type(const ObObjType type); - int calc_value_for_oracle(ObObj &src_obj, ObIAllocator &allocator, int64_t &part_idx, ObPartDescCtx &ctx); - int calc_value_for_mysql(ObObj &src_obj, ObIAllocator &allocator, int64_t &part_idx); + int calc_value_for_oracle(const ObObj *objs, int64_t objs_cnt, int64_t &result, ObPartDescCtx &ctx); + int calc_value_for_mysql(const ObObj *obj, int64_t &result); int get_part_hash_idx(const int64_t part_idx, int64_t &part_id); + int calc_hash_part_idx(const uint64_t val, const int64_t part_num, int64_t &partition_idx); private: bool is_oracle_mode_; int64_t part_num_; int64_t part_space_; int64_t first_part_id_; - // TODO: add multiple key - ObObjType obj_type_; - ObCollationType cs_type_; + // multiple key + ObSEArray obj_types_; + ObSEArray cs_types_; int64_t *part_array_; }; } diff --git a/src/share/part/ob_part_desc_key.cpp b/src/share/part/ob_part_desc_key.cpp index 934cb2308c695c3c20bd35d0b35fe65ba1529da8..86127731a2e4cf408c73502f4d3d14b72e778483 100644 --- a/src/share/part/ob_part_desc_key.cpp +++ b/src/share/part/ob_part_desc_key.cpp @@ -22,87 +22,169 @@ namespace common ObPartDescKey::ObPartDescKey() : part_num_(0) , part_space_(0) , first_part_id_(0) - , obj_type_(ObMaxType) - , cs_type_(CS_TYPE_INVALID) , part_array_(NULL) { } - -/* +/** GET PARTITION ID - - If input is not single int value, return invalid argument; otherwise, get the particular one. + Hash partition only route like 'by key(c1,c2) ... where c1=xx and c2=xx', + only use range.start_key_ to calc, because when condition is like 'c1=xx', + start_key_[i] == end_key_[i] + @param range (xxx,yyy,min,min ; xxx,yyy,max,max) + @param allocator + @param part_ids[out] + @param ctx */ int ObPartDescKey::get_part(ObNewRange &range, ObIAllocator &allocator, ObIArray &part_ids, - ObPartDescCtx &ctx) + ObPartDescCtx &ctx, + ObIArray &tablet_ids) { int ret = OB_SUCCESS; + // provide all objs are valid. + // "valid" means the obj not min or max + int64_t valid_obj_cnt = range.start_key_.get_obj_cnt(); + // cast objs store in range.start_key_ + for (int64_t i = 0; OB_SUCC(ret) && i < range.start_key_.get_obj_cnt(); i++) { + // if obj is min or max, means all valid obj has been casted + if (range.start_key_.get_obj_ptr()[i].is_max_value() || + range.start_key_.get_obj_ptr()[i].is_min_value()) { + // minus the number of invalid obj + valid_obj_cnt = valid_obj_cnt - (range.start_key_.get_obj_cnt() - i); + // not need to cast any more and break loop + if (valid_obj_cnt == 0) { + ret = OB_INVALID_ARGUMENT; + COMMON_LOG(WARN, "not support key partition calc with range", K(range)); + } + break; + } else { + ObObj *src_obj = const_cast(&range.start_key_.get_obj_ptr()[i]); + // here src_obj shouldn't be null + if (OB_ISNULL(src_obj)) { + ret = OB_ERR_NULL_VALUE; + COMMON_LOG(ERROR, "unexpected null pointer src_obj"); + break; + } else if (src_obj->is_null()) { + // here src_obj shouldn't be null type + ret = OB_OBJ_TYPE_ERROR; + COMMON_LOG(ERROR, "unexpected null type", K(src_obj)); + } else if(OB_FAIL(cast_obj(*src_obj, obj_types_[i], cs_types_[i], allocator, ctx, accuracies_.at(i)))) { + COMMON_LOG(WARN, "cast obj failed", K(src_obj), "obj_type", obj_types_[i], "cs_type", cs_types_[i]); + // TODO: handle failure + } + } - if (1 != range.get_start_key().get_obj_cnt()) { // single value - ret = OB_INVALID_ARGUMENT; - COMMON_LOG(WARN, "key part should be single key", - "obj_cnt", range.get_start_key().get_obj_cnt(), K(ret)); - } else { - ObTimeZoneInfo tz_info; - ObDataTypeCastParams dtc_params; - if (OB_FAIL(obproxy::proxy::ObExprCalcTool::build_dtc_params_with_tz_info(ctx.get_session_info(), - obj_type_, tz_info, dtc_params))) { - COMMON_LOG(WARN, "fail to build dtc params with ctx session", K(ret), K(obj_type_)); + } + + int64_t part_idx = -1; + if (OB_SUCC(ret)) { + // hash val + int64_t result = 0; + int64_t part_id = -1; + if (OB_FAIL(calc_value_for_mysql(range.start_key_.get_obj_ptr(), valid_obj_cnt, result, ctx))) { + COMMON_LOG(WARN, "fail to cal key val", K(ret), K(valid_obj_cnt)); + } else if (OB_FAIL(calc_key_part_idx(result, part_num_, part_idx))) { + COMMON_LOG(WARN, "fail to cal key part idx", K(ret), K(result), K(part_num_)); + } else if (OB_FAIL(get_part_hash_idx(part_idx, part_id))) { + COMMON_LOG(WARN, "fail to get part key id", K(part_idx), K(ret)); + } else if (OB_FAIL(part_ids.push_back(part_id))) { + COMMON_LOG(WARN, "fail to push part_id", K(ret)); + } else if (NULL != tablet_id_array_ && OB_FAIL(tablet_ids.push_back(tablet_id_array_[part_idx]))) { + COMMON_LOG(WARN, "fail to push tablet id", K(ret)); + } else {} + } + + return ret; +} + + +int ObPartDescKey::calc_value_for_mysql(const ObObj *objs, + int64_t objs_cnt, + int64_t &result, + ObPartDescCtx &ctx) +{ + int ret = OB_SUCCESS; + uint64_t hash_code = 0; + if (OB_ISNULL(objs) || 0 == objs_cnt) { + ret = OB_ERR_UNEXPECTED; + COMMON_LOG(WARN, "objs_stack is null or number incorrect", K(objs), K(objs_cnt), K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < objs_cnt; ++i) { + const ObObj &obj = objs[i]; + if (ObNullType == obj.get_type()) { + //do nothing, hash_code not changed } else { - ObCastCtx cast_ctx(&allocator, &dtc_params, CM_NULL_ON_WARN, cs_type_); - ObObj &src_obj = const_cast(range.get_start_key().get_obj_ptr()[0]); - const ObObj *res_obj = &src_obj; - ObAccuracy accuracy(accuracy_.valid_, accuracy_.length_, accuracy_.precision_, accuracy_.scale_); - - // use src_obj as buf_obj - if (OB_FAIL(ObObjCasterV2::to_type(obj_type_, cs_type_, cast_ctx, src_obj, src_obj))) { - COMMON_LOG(WARN, "fail to cast obj", K(ret), K(src_obj), K(obj_type_), K(cs_type_)); - } else if (ctx.need_accurate() - && OB_FAIL(obj_accuracy_check(cast_ctx, accuracy, cs_type_, *res_obj, src_obj, res_obj))) { - COMMON_LOG(WARN, "fail to obj accuracy check", K(ret), K(src_obj), K(obj_type_)); - } else { - int64_t result_num = 0; - if (share::schema::PARTITION_FUNC_TYPE_KEY_V3 == part_func_type_ - || share::schema::PARTITION_FUNC_TYPE_KEY_IMPLICIT_V2 == part_func_type_) { - result_num = static_cast(src_obj.hash_murmur()); - } else { - result_num = static_cast(src_obj.hash()); - } - result_num = result_num < 0 ? -result_num : result_num; - int64_t part_idx = result_num % part_num_; - int64_t part_id = part_idx; - if (share::schema::PARTITION_LEVEL_ONE == part_level_ && NULL != part_array_) { - part_id = part_array_[part_idx]; - } - part_id = part_space_ << OB_PART_IDS_BITNUM | part_id; - if (OB_FAIL(part_ids.push_back(part_id))) { - COMMON_LOG(WARN, "fail to push part_id", K(ret)); - } - } + hash_code = calc_hash_value_with_seed(obj, ctx.get_cluster_version(), hash_code); } } + result = static_cast(hash_code); + result = result < 0 ? -result : result; + if (OB_SUCC(ret)) { + COMMON_LOG(TRACE, "succ to calc hash value with oracle mode", KP(objs), K(objs[0]), K(objs_cnt), K(result), K(ret)); + } else { + COMMON_LOG(WARN, "fail to calc hash value with oracle mode", KP(objs), K(objs_cnt), K(result), K(ret)); + } + return ret; +} +uint64_t ObPartDescKey::calc_hash_value_with_seed(const ObObj &obj, const int64_t cluster_version, int64_t seed) +{ + int64_t hval = 0; + if ((IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version) + && (share::schema::PARTITION_FUNC_TYPE_KEY_V3 == part_func_type_ + || share::schema::PARTITION_FUNC_TYPE_KEY_IMPLICIT_V2 == part_func_type_)) + || (!IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version))) { + hval = static_cast(obj.hash_murmur(seed)); + } else { + hval = static_cast(obj.hash(seed)); + } + + return hval; +} + +int ObPartDescKey::calc_key_part_idx(const uint64_t val, + const int64_t part_num, + int64_t &partition_idx) +{ + int ret = OB_SUCCESS; + partition_idx = val % part_num; + COMMON_LOG(DEBUG, "get hash part idx", K(lbt()), K(ret), K(val), K(part_num), K(partition_idx)); return ret; } -int ObPartDescKey::get_part_by_num(const int64_t num, common::ObIArray &part_ids) +int ObPartDescKey::get_part_by_num(const int64_t num, common::ObIArray &part_ids, common::ObIArray &tablet_ids) { int ret = OB_SUCCESS; + int64_t part_id = -1; int64_t part_idx = num % part_num_; - int64_t part_id = part_idx; - if (share::schema::PARTITION_LEVEL_ONE == part_level_ && part_array_ != NULL) { - part_id = part_array_[part_idx]; - } - part_id = part_space_ << OB_PART_IDS_BITNUM | part_id; - if (OB_FAIL(part_ids.push_back(part_id))) { + if (OB_FAIL(get_part_hash_idx(part_idx, part_id))) { + COMMON_LOG(WARN, "fail to get part hash id", K(num), K(ret)); + } else if (OB_FAIL(part_ids.push_back(part_id))) { COMMON_LOG(WARN, "fail to push part_id", K(ret)); + } else if (NULL != tablet_id_array_ && OB_FAIL(tablet_ids.push_back(tablet_id_array_[part_idx]))) { + COMMON_LOG(WARN, "fail to push tablet id", K(ret)); + } + return ret; +} + +int ObPartDescKey::get_part_hash_idx(const int64_t part_idx, int64_t &part_id) +{ + int ret =OB_SUCCESS; + + part_id = part_idx; + if (share::schema::PARTITION_LEVEL_ONE == part_level_) { + if (part_idx >= 0 && NULL != part_array_) { + part_id = part_array_[part_idx]; + } + } + if (OB_SUCC(ret)) { + part_id = part_space_ << OB_PART_IDS_BITNUM | part_id; + COMMON_LOG(DEBUG, "get hash part id", K(ret), K(part_num_), K(part_id)); } return ret; } - } // end of common -} // end of oceanbase +} diff --git a/src/share/part/ob_part_desc_key.h b/src/share/part/ob_part_desc_key.h index 7ddd342fcc61938d09a353e68ae1b1e279478d52..f1b66763c88210c83a2e5969759626c634fdaf39 100644 --- a/src/share/part/ob_part_desc_key.h +++ b/src/share/part/ob_part_desc_key.h @@ -15,7 +15,7 @@ #include "share/part/ob_part_desc.h" #include "share/part/ob_part_mgr_util.h" - +#include "proxy/route/obproxy_part_mgr.h" namespace oceanbase { namespace common @@ -29,29 +29,37 @@ public: virtual int get_part(ObNewRange &range, ObIAllocator &allocator, ObIArray &part_ids, - ObPartDescCtx &ctx); - virtual int get_part_by_num(const int64_t num, common::ObIArray &part_ids); + ObPartDescCtx &ctx, + ObIArray &tablet_ids); + virtual int get_part_by_num(const int64_t num, common::ObIArray &part_ids, common::ObIArray &tablet_ids); void set_part_num(int64_t part_num) { part_num_ = part_num; } void set_part_space(int64_t part_space) { part_space_ = part_space; } void set_first_part_id(int64_t first_part_id) { first_part_id_ = first_part_id; } int64_t get_first_part_id() { return first_part_id_; } - void set_part_key_type(const ObObjType obj_type) { obj_type_ = obj_type; } - void set_part_key_cs_type(const ObCollationType cs_type) { cs_type_ = cs_type; } void set_part_array(int64_t *part_array) { part_array_ = part_array; } + ObIArray &get_obj_types() { return obj_types_; } + ObIArray &get_cs_types() { return cs_types_; } + VIRTUAL_TO_STRING_KV("part_type", "key", K_(part_num), K_(part_space), K_(first_part_id), K_(part_level), K_(part_func_type)); +private: + int calc_value_for_mysql(const ObObj *objs, int64_t objs_cnt, int64_t &result, ObPartDescCtx &ctx); + uint64_t calc_hash_value_with_seed(const ObObj &obj, const int64_t cluster_version, int64_t seed); + int calc_key_part_idx(const uint64_t val, const int64_t part_num, int64_t &partition_idx); + int get_part_hash_idx(const int64_t part_idx, int64_t &part_id); + private: int64_t part_num_; int64_t part_space_; int64_t first_part_id_; - // TODO: add multiple key - ObObjType obj_type_; - ObCollationType cs_type_; + // multiple key + ObSEArray obj_types_; + ObSEArray cs_types_; int64_t *part_array_; }; diff --git a/src/share/part/ob_part_desc_list.cpp b/src/share/part/ob_part_desc_list.cpp index 3d7016362a10143263398d957523a703ab86da14..1f23817f1c72f2f6f089267f59b461e69459e40c 100644 --- a/src/share/part/ob_part_desc_list.cpp +++ b/src/share/part/ob_part_desc_list.cpp @@ -49,96 +49,100 @@ ListPartition::ListPartition() : part_id_(0), rows_() int ObPartDescList::get_part(ObNewRange &range, ObIAllocator &allocator, ObIArray &part_ids, - ObPartDescCtx &ctx) + ObPartDescCtx &ctx, + ObIArray &tablet_ids) { int ret = OB_SUCCESS; - + ObNewRow src_row; + // for list partition, row in start_key_ + src_row.assign(const_cast(range.start_key_.get_obj_ptr()), range.start_key_.get_obj_cnt()); if (OB_ISNULL(part_array_) || OB_UNLIKELY(part_array_size_ <= 0)) { ret = OB_INVALID_ARGUMENT; COMMON_LOG(WARN, "invalid argument, ", K_(part_array), K_(part_array_size), K(ret)); // use the fisrt range as the type to cast - } else if (1 != range.get_start_key().get_obj_cnt()) { // single value - ret = OB_INVALID_ARGUMENT; - COMMON_LOG(DEBUG, "list part should be single key", - "obj_cnt", range.get_start_key().get_obj_cnt(), K(ret)); } else { - ObObj &src_obj = const_cast(range.get_start_key().get_obj_ptr()[0]); - // use the first row cell as target obj - ObObj &target_obj = const_cast(part_array_[0].rows_[0].get_cell(0)); - if (OB_FAIL(cast_obj(src_obj, target_obj, allocator, ctx))) { - COMMON_LOG(INFO, "fail to cast obj", K(src_obj), K(target_obj), K(ret)); - } else { - bool found = false; - for (int64_t i = 0; OB_SUCC(ret) && i < part_array_size_ && !found; ++i) { - if (i == default_part_array_idx_) { - continue; - } - for (int64_t j= 0; OB_SUCC(ret) && j < part_array_[i].rows_.count() && !found; ++j) { - if (part_array_[i].rows_[j].get_count() == 0) { - ret = OB_ERR_UNEXPECTED; - COMMON_LOG(WARN, "no cells in the row", K(part_array_[i].rows_[j]), K(ret)); - } else if (src_obj == part_array_[i].rows_[j].get_cell(0)) { + bool found = false; + bool casted = false; + // cast src_row and compare with part array + for (int64_t i = 0; i < part_array_size_ && !found; i++) { + if (i == default_part_array_idx_) { + continue; + } + for (int64_t j = 0; j < part_array_[i].rows_.count() && !found; j++) { + if (part_array_[i].rows_[j].get_count() == 0) { + ret = OB_ERR_UNEXPECTED; + COMMON_LOG(WARN, "no cells in the row", K(part_array_[i].rows_[j]), K(ret)); + } else { + // if not cast, cast first + if (!casted && OB_FAIL(cast_row(src_row, part_array_[i].rows_.at(j), allocator, ctx))) { + COMMON_LOG(WARN, "fail to cast row"); + continue; + } else { + casted = true; + } + // if casted, then compare + if (casted && src_row == part_array_[i].rows_.at(j)) { found = true; if (OB_FAIL(part_ids.push_back(part_array_[i].part_id_))) { COMMON_LOG(WARN, "fail to push part id", K(ret)); + } else if (NULL != tablet_id_array_ && OB_FAIL(tablet_ids.push_back(tablet_id_array_[i]))) { + COMMON_LOG(WARN, "fail to push tablet id", K(ret)); } - } // end found - } // end for rows - } // end for part_array - if (!found && OB_INVALID_INDEX != default_part_array_idx_) { - // if no row cell matches, use default partition - COMMON_LOG(DEBUG, "will use default partition id", K(src_obj), K(ret)); - if (OB_FAIL(part_ids.push_back(part_array_[default_part_array_idx_].part_id_))) { - COMMON_LOG(WARN, "fail to push part id", K(ret)); + } else {} } + } // end for rows + } // end for part_array + + if (!found && OB_INVALID_INDEX != default_part_array_idx_) { + // if no row matches, use default partition + COMMON_LOG(DEBUG, "will use default partition id", K(src_row), K(ret)); + if (OB_FAIL(part_ids.push_back(part_array_[default_part_array_idx_].part_id_))) { + COMMON_LOG(WARN, "fail to push part id", K(ret)); + } else if (NULL != tablet_id_array_ && OB_FAIL(tablet_ids.push_back(tablet_id_array_[default_part_array_idx_]))) { + COMMON_LOG(WARN, "fail to push tablet id", K(ret)); } } } return ret; } -int ObPartDescList::get_part_by_num(const int64_t num, common::ObIArray &part_ids) +int ObPartDescList::get_part_by_num(const int64_t num, common::ObIArray &part_ids, common::ObIArray &tablet_ids) { int ret = OB_SUCCESS; int64_t part_idx = num % part_array_size_; if (OB_FAIL(part_ids.push_back(part_array_[part_idx].part_id_))) { COMMON_LOG(WARN, "fail to push part_id", K(ret)); + } else if (NULL != tablet_id_array_ && OB_FAIL(tablet_ids.push_back(tablet_id_array_[part_idx]))) { + COMMON_LOG(WARN, "fal to push tablet id", K(ret)); } return ret; } -inline int ObPartDescList::cast_obj(ObObj &src_obj, - ObObj &target_obj, - ObIAllocator &allocator, - ObPartDescCtx &ctx) +int ObPartDescList::cast_row(ObNewRow &src_row, + ObNewRow &target_row, + ObIAllocator &allocator, + ObPartDescCtx &ctx) { int ret = OB_SUCCESS; - COMMON_LOG(DEBUG, "begin to cast obj for list", K(src_obj), K(target_obj)); - - ObTimeZoneInfo tz_info; - ObDataTypeCastParams dtc_params; - ObObjType obj_type = target_obj.get_type(); - - if (OB_FAIL(obproxy::proxy::ObExprCalcTool::build_dtc_params_with_tz_info(ctx.get_session_info(), - obj_type, tz_info, dtc_params))) { - COMMON_LOG(WARN, "fail to build dtc params with ctx session", K(ret), K(obj_type)); - } else { - ObCastCtx cast_ctx(&allocator, &dtc_params, CM_NULL_ON_WARN, target_obj.get_collation_type()); - const ObObj *res_obj = &src_obj; - ObAccuracy accuracy(accuracy_.valid_, accuracy_.length_, accuracy_.precision_, accuracy_.scale_); - - // use src_obj as buf_obj - if (OB_FAIL(ObObjCasterV2::to_type(obj_type, target_obj.get_collation_type(), cast_ctx, src_obj, src_obj))) { - COMMON_LOG(WARN, "failed to cast obj", K(ret), K(src_obj), K(target_obj)); - } else if (ctx.need_accurate() - && OB_FAIL(obj_accuracy_check(cast_ctx, accuracy, target_obj.get_collation_type(), *res_obj, src_obj, res_obj))) { - COMMON_LOG(WARN, "fail to obj accuracy check", K(ret), K(src_obj), K(obj_type)); + int64_t min_col_cnt = std::min(src_row.count_, target_row.count_); + for (int64_t i = 0; i < min_col_cnt && OB_SUCC(ret); ++i) { + if (src_row.get_cell(i).is_max_value() || + src_row.get_cell(i).is_min_value()) { + COMMON_LOG(DEBUG, "skip min/max obj"); + continue; + } + if (OB_FAIL(cast_obj(src_row.get_cell(i), + target_row.get_cell(i), + allocator, + ctx, + accuracies_.at(i)))) { + COMMON_LOG(INFO, "fail to cast obj", K(i), K(ret)); } else { - COMMON_LOG(DEBUG, "succ to cast obj for list", K(src_obj), K(target_obj)); + // do nothing } } - + return ret; } diff --git a/src/share/part/ob_part_desc_list.h b/src/share/part/ob_part_desc_list.h index 6d58340e0bd027b967eab303874561321ad026a3..f324a5369699aca3e776d2ebb7d1a8e3d30ae897 100644 --- a/src/share/part/ob_part_desc_list.h +++ b/src/share/part/ob_part_desc_list.h @@ -16,6 +16,7 @@ #include "share/part/ob_part_desc.h" #include "common/ob_row.h" #include "lib/container/ob_se_array.h" +#include "proxy/route/obproxy_part_mgr.h" namespace oceanbase { @@ -29,6 +30,7 @@ struct ListPartition ListPartition(); TO_STRING_KV(K_(part_id), + K_(first_part_id), K_(rows)); }; @@ -41,8 +43,9 @@ public: virtual int get_part(ObNewRange &range, ObIAllocator &allocator, ObIArray &part_ids, - ObPartDescCtx &ctx); - virtual int get_part_by_num(const int64_t num, common::ObIArray &part_ids); + ObPartDescCtx &ctx, + ObIArray &tablet_ids); + virtual int get_part_by_num(const int64_t num, common::ObIArray &part_ids, common::ObIArray &tablet_ids); void set_default_part_array_idx(int64_t idx) { default_part_array_idx_ = idx; } int64_t get_default_part_array_idx() const { return default_part_array_idx_; } ListPartition *get_part_array() { return part_array_; } @@ -52,12 +55,13 @@ public: return OB_SUCCESS; } - DECLARE_VIRTUAL_TO_STRING; -private: - int cast_obj(ObObj &src_obj, - ObObj &target_obj, + int cast_row(ObNewRow &src_row, + ObNewRow &target_row, ObIAllocator &allocator, ObPartDescCtx &ctx); + + DECLARE_VIRTUAL_TO_STRING; + private: ListPartition *part_array_; int64_t part_array_size_; diff --git a/src/share/part/ob_part_desc_range.cpp b/src/share/part/ob_part_desc_range.cpp index 750f6d7dec0ec80c63ff7232eec2b043cea0c4e7..120049b04baccc1fb9e9e6d4efbb9c00cb0b43e9 100644 --- a/src/share/part/ob_part_desc_range.cpp +++ b/src/share/part/ob_part_desc_range.cpp @@ -126,7 +126,8 @@ RangePartition::RangePartition() : is_max_value_(false) int ObPartDescRange::get_part(ObNewRange &range, ObIAllocator &allocator, ObIArray &part_ids, - ObPartDescCtx &ctx) + ObPartDescCtx &ctx, + ObIArray &tablet_ids) { int ret = OB_SUCCESS; part_ids.reset(); @@ -151,34 +152,44 @@ int ObPartDescRange::get_part(ObNewRange &range, for (int64_t i = start; OB_SUCC(ret) && i <= end; i ++) { if (OB_FAIL(part_ids.push_back(part_array_[i].part_id_))) { COMMON_LOG(WARN, "fail to push part id", K(ret)); + } else if (NULL != tablet_id_array_ && OB_FAIL(tablet_ids.push_back(tablet_id_array_[i]))) { + COMMON_LOG(WARN, "fail to push tablet id", K(ret)); } } } return ret; } -int ObPartDescRange::get_part_by_num(const int64_t num, common::ObIArray &part_ids) +int ObPartDescRange::get_part_by_num(const int64_t num, common::ObIArray &part_ids, common::ObIArray &tablet_ids) { int ret = OB_SUCCESS; int64_t part_idx = num % part_array_size_; if (OB_FAIL(part_ids.push_back(part_array_[part_idx].part_id_))) { COMMON_LOG(WARN, "fail to push part id", K(ret)); + } else if (NULL != tablet_id_array_ && OB_FAIL(tablet_ids.push_back(tablet_id_array_[part_idx]))) { + COMMON_LOG(WARN, "fail to push tablet id", K(ret)); } return ret; } int ObPartDescRange::cast_key(ObRowkey &src_key, - ObRowkey &target_key, - ObIAllocator &allocator, - ObPartDescCtx &ctx) + ObRowkey &target_key, + ObIAllocator &allocator, + ObPartDescCtx &ctx) { int ret = OB_SUCCESS; int64_t min_col_cnt = std::min(src_key.get_obj_cnt(), target_key.get_obj_cnt()); for (int64_t i = 0; i < min_col_cnt && OB_SUCC(ret); ++i) { + if (src_key.get_obj_ptr()[i].is_max_value() || + src_key.get_obj_ptr()[i].is_min_value()) { + COMMON_LOG(DEBUG, "skip min/max obj"); + continue; + } if (OB_FAIL(cast_obj(const_cast(src_key.get_obj_ptr()[i]), const_cast(target_key.get_obj_ptr()[i]), allocator, - ctx))) { + ctx, + accuracies_.at(i)))) { COMMON_LOG(INFO, "fail to cast obj", K(i), K(ret)); } else { // do nothing @@ -187,39 +198,5 @@ int ObPartDescRange::cast_key(ObRowkey &src_key, return ret; } -inline int ObPartDescRange::cast_obj(ObObj &src_obj, - ObObj &target_obj, - ObIAllocator &allocator, - ObPartDescCtx &ctx) -{ - int ret = OB_SUCCESS; - COMMON_LOG(DEBUG, "begin to cast obj for range", K(src_obj), K(target_obj)); - - ObTimeZoneInfo tz_info; - ObDataTypeCastParams dtc_params; - ObObjType obj_type = target_obj.get_type(); - - if (OB_FAIL(obproxy::proxy::ObExprCalcTool::build_dtc_params_with_tz_info(ctx.get_session_info(), - obj_type, tz_info, dtc_params))) { - COMMON_LOG(WARN, "fail to build dtc params with ctx session", K(ret), K(obj_type)); - } else { - ObCastCtx cast_ctx(&allocator, &dtc_params, CM_NULL_ON_WARN, target_obj.get_collation_type()); - const ObObj *res_obj = &src_obj; - ObAccuracy accuracy(accuracy_.valid_, accuracy_.length_, accuracy_.precision_, accuracy_.scale_); - - // use src_obj as buf_obj - if (OB_FAIL(ObObjCasterV2::to_type(obj_type, target_obj.get_collation_type(), cast_ctx, src_obj, src_obj))) { - COMMON_LOG(WARN, "failed to cast obj", K(ret), K(src_obj), K(target_obj)); - } else if (ctx.need_accurate() - && OB_FAIL(obj_accuracy_check(cast_ctx, accuracy, target_obj.get_collation_type(), *res_obj, src_obj, res_obj))) { - COMMON_LOG(WARN, "fail to obj accuracy check", K(ret), K(src_obj)); - } else { - COMMON_LOG(DEBUG, "end to cast obj for range", K(src_obj), K(target_obj)); - } - } - - return ret; -} - } // end of common } // end of oceanbase diff --git a/src/share/part/ob_part_desc_range.h b/src/share/part/ob_part_desc_range.h index e7465b02e9ab94bf0951ea07ff3667c8b28b466c..6baabf8a8743334b476c2bd9379ece57ddb0eb6c 100644 --- a/src/share/part/ob_part_desc_range.h +++ b/src/share/part/ob_part_desc_range.h @@ -15,6 +15,7 @@ #include "share/part/ob_part_desc.h" #include "lib/container/ob_se_array.h" +#include "proxy/route/obproxy_part_mgr.h" namespace oceanbase { @@ -44,8 +45,9 @@ public: virtual int get_part(common::ObNewRange &range, common::ObIAllocator &allocator, ObIArray &part_ids, - ObPartDescCtx &ctx); - virtual int get_part_by_num(const int64_t num, common::ObIArray &part_ids); + ObPartDescCtx &ctx, + ObIArray &tablet_ids); + virtual int get_part_by_num(const int64_t num, common::ObIArray &part_ids, common::ObIArray &tablet_ids); RangePartition* get_part_array() { return part_array_; } int set_part_array(RangePartition *part_array, int64_t size) { part_array_ = part_array; @@ -53,6 +55,11 @@ public: return common::OB_SUCCESS; } + int cast_key(ObRowkey &src_key, + ObRowkey &target_key, + ObIAllocator &allocator, + ObPartDescCtx &ctx); + DECLARE_VIRTUAL_TO_STRING; private: int64_t get_start(const RangePartition *part_array, @@ -63,15 +70,6 @@ private: const int64_t size, const ObNewRange &range); - int cast_key(ObRowkey &src_key, - ObRowkey &target_key, - ObIAllocator &allocator, - ObPartDescCtx &ctx); - - int cast_obj(ObObj &src_obj, - ObObj &target_obj, - ObIAllocator &allocator, - ObPartDescCtx &ctx); private: RangePartition *part_array_; int64_t part_array_size_; diff --git a/src/share/part/ob_part_mgr_util.h b/src/share/part/ob_part_mgr_util.h index 2cf675dae758007dc8d40e677c14786edb6c6449..4b6ebf683a251d679d65d9b5271a3e26443eef0e 100644 --- a/src/share/part/ob_part_mgr_util.h +++ b/src/share/part/ob_part_mgr_util.h @@ -44,6 +44,20 @@ enum ObPartitionFuncType PARTITION_FUNC_TYPE_MAX, }; +enum ObPartitionFuncTypeV4 +{ + //TODO add other type + PARTITION_FUNC_TYPE_V4_HASH = 0, + PARTITION_FUNC_TYPE_V4_KEY, + PARTITION_FUNC_TYPE_V4_KEY_IMPLICIT, + PARTITION_FUNC_TYPE_V4_RANGE, + PARTITION_FUNC_TYPE_V4_RANGE_COLUMNS, + PARTITION_FUNC_TYPE_V4_LIST, + PARTITION_FUNC_TYPE_V4_LIST_COLUMNS, + PARTITION_FUNC_TYPE_V4_INTERVAL, + PARTITION_FUNC_TYPE_V4_MAX, +}; + const char *get_partition_func_type_str(const ObPartitionFuncType type) { static const char *type_str_array[PARTITION_FUNC_TYPE_MAX] = @@ -67,18 +81,55 @@ const char *get_partition_func_type_str(const ObPartitionFuncType type) return str; } -inline bool is_hash_part(const ObPartitionFuncType part_type) -{ return PARTITION_FUNC_TYPE_HASH == part_type || PARTITION_FUNC_TYPE_HASH_V2 == part_type; } +inline bool is_hash_part(const ObPartitionFuncType part_type, const int64_t cluster_version) +{ + bool bret = false; + if (IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + bret = PARTITION_FUNC_TYPE_HASH == part_type || PARTITION_FUNC_TYPE_HASH_V2 == part_type; + } else { + bret = PARTITION_FUNC_TYPE_V4_HASH == static_cast(part_type); + } + return bret; +} + +inline bool is_range_part(const ObPartitionFuncType part_type, const int64_t cluster_version) +{ + bool bret = false; + if (IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + bret = PARTITION_FUNC_TYPE_RANGE == part_type || PARTITION_FUNC_TYPE_RANGE_COLUMNS == part_type; + } else { + ObPartitionFuncTypeV4 v4_type = static_cast(part_type); + bret = PARTITION_FUNC_TYPE_V4_RANGE == v4_type || PARTITION_FUNC_TYPE_V4_RANGE_COLUMNS == v4_type; + } + + return bret; +} -inline bool is_range_part(const ObPartitionFuncType part_type) -{ return PARTITION_FUNC_TYPE_RANGE == part_type || PARTITION_FUNC_TYPE_RANGE_COLUMNS == part_type; } +inline bool is_key_part(const ObPartitionFuncType part_type, const int64_t cluster_version) +{ + bool bret = false; + if (IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + bret = PARTITION_FUNC_TYPE_KEY_IMPLICIT == part_type || PARTITION_FUNC_TYPE_KEY_V2 == part_type + || PARTITION_FUNC_TYPE_KEY_V3 == part_type || PARTITION_FUNC_TYPE_KEY_IMPLICIT_V2 == part_type; + } else { + ObPartitionFuncTypeV4 v4_type = static_cast(part_type); + bret = PARTITION_FUNC_TYPE_V4_KEY_IMPLICIT == v4_type || PARTITION_FUNC_TYPE_V4_KEY == v4_type; + } + return bret; +} -inline bool is_key_part(const ObPartitionFuncType part_type) -{ return PARTITION_FUNC_TYPE_KEY_IMPLICIT == part_type || PARTITION_FUNC_TYPE_KEY_V2 == part_type - || PARTITION_FUNC_TYPE_KEY_V3 == part_type || PARTITION_FUNC_TYPE_KEY_IMPLICIT_V2 == part_type; } +inline bool is_list_part(const ObPartitionFuncType part_type, const int64_t cluster_version) +{ + bool bret = false; + if (IS_CLUSTER_VERSION_LESS_THAN_V4(cluster_version)) { + bret = PARTITION_FUNC_TYPE_LIST == part_type || PARTITION_FUNC_TYPE_LIST_COLUMNS == part_type; + } else { + ObPartitionFuncTypeV4 v4_type = static_cast(part_type); + bret = PARTITION_FUNC_TYPE_V4_LIST == v4_type || PARTITION_FUNC_TYPE_V4_LIST_COLUMNS == v4_type; + } -inline bool is_list_part(const ObPartitionFuncType part_type) -{ return PARTITION_FUNC_TYPE_LIST == part_type || PARTITION_FUNC_TYPE_LIST_COLUMNS == part_type; } + return bret; +} OB_INLINE int64_t generate_phy_part_id(int64_t part_idx, int64_t sub_part_idx) { diff --git a/unittest/obproxy/ob_expr_parser_checker.cpp b/unittest/obproxy/ob_expr_parser_checker.cpp index da4fcf7e12d0b1d39cc0e71d2478673687d612ef..c6d61cc46b7adebf120f46d6c1a885a405b8fb7a 100644 --- a/unittest/obproxy/ob_expr_parser_checker.cpp +++ b/unittest/obproxy/ob_expr_parser_checker.cpp @@ -124,7 +124,6 @@ void ObExprParserChecker::build_schema(std::string &extra_str, ObExprParseResult } result.part_key_info_.key_num_ = 0; - result.target_mask_ = 0; while (true) { ObProxyParseString part_key_name = get_value(extra_str, "part_key", pos); ObProxyParseString part_key_level = get_value(extra_str, "part_level", pos); @@ -143,11 +142,6 @@ void ObExprParserChecker::build_schema(std::string &extra_str, ObExprParseResult result.part_key_info_.part_keys_[result.part_key_info_.key_num_].idx_ = part_key_idx.str_[0] - '0'; } ++result.part_key_info_.key_num_; - if (PART_KEY_LEVEL_ONE == level) { - result.target_mask_ |= BOTH_BOUND_FLAG; - } else { - result.target_mask_ |= (BOTH_BOUND_FLAG << 2); - } } } } @@ -340,6 +334,8 @@ int main(int argc, char **argv) case 'c': if (strcmp(optarg, "utb8") == 0) { connection_collation = CS_TYPE_UTF8MB4_GENERAL_CI; + } else if (strcmp(optarg, "gb18030") == 0) { + connection_collation = CS_TYPE_GB18030_CHINESE_CI; } break; case 't': diff --git a/unittest/obproxy/obproxy_parser_checker.cpp b/unittest/obproxy/obproxy_parser_checker.cpp index f6446e9e1d310d7f6345fab0c5f656f714abea62..6aac10ebf011588733dd0bb67cb9ae9ed512fef3 100644 --- a/unittest/obproxy/obproxy_parser_checker.cpp +++ b/unittest/obproxy/obproxy_parser_checker.cpp @@ -12,6 +12,7 @@ #include "obproxy_parser_checker.h" #include "lib/utility/ob_print_utils.h" +#include "obproxy/obutils/ob_proxy_sql_parser.h" #include #include #include @@ -196,6 +197,8 @@ int main(int argc, char **argv) case 'c': if (strcmp(optarg, "utb8") == 0) { connection_collation = CS_TYPE_UTF8MB4_GENERAL_CI; + } else if (strcmp(optarg, "gb18030") == 0) { + connection_collation = CS_TYPE_GB18030_CHINESE_CI; } break; case 'r': diff --git a/unittest/obproxy/obproxy_parser_test.cpp b/unittest/obproxy/obproxy_parser_test.cpp index f091eebcd2881cd0ce23aa6084538d1690995ed2..0a8ab8d0213c17a6eaccf39f27ec42f5b23851d0 100755 --- a/unittest/obproxy/obproxy_parser_test.cpp +++ b/unittest/obproxy/obproxy_parser_test.cpp @@ -23,6 +23,7 @@ #include "proxy/mysqllib/ob_proxy_mysql_request.h" #include "opsql/expr_parser/ob_expr_parser.h" #include "opsql/expr_parser/ob_expr_parser_utils.h" +#include "obproxy/obutils/ob_proxy_sql_parser.h" #include "lib/allocator/page_arena.h" #include "obutils/ob_proxy_stmt.h" @@ -50,19 +51,19 @@ void show_sql_result(SqlFieldResult& sql_result) { fprintf(stdout, "========== sql_result is ===========\n"); for(int i = 0; i < sql_result.field_num_; i++) { char buf[256]; - printf("column_name:length:%d\t", sql_result.fields_[i].column_name_.string_.length()); + printf("column_name:length:%d\t", sql_result.fields_[i]->column_name_.config_string_.length()); snprintf(buf, 256, "column_name:%.*s", - sql_result.fields_[i].column_name_.string_.length(), - sql_result.fields_[i].column_name_.string_.ptr()); + sql_result.fields_[i]->column_name_.config_string_.length(), + sql_result.fields_[i]->column_name_.config_string_.ptr()); printf("%s\t", buf); //printf(" %s ", function_type_to_string(sql_result.fields_[i].type_).c_str()); - printf(" (%s) ", token_type_to_string(sql_result.fields_[i].value_type_).c_str()); - if(sql_result.fields_[i].value_type_ == TOKEN_INT_VAL) { - snprintf(buf, 256, "column_value:%ld", sql_result.fields_[i].column_int_value_); - } else if (sql_result.fields_[i].value_type_ == TOKEN_STR_VAL){ - snprintf(buf, sql_result.fields_[i].column_value_.config_string_.length()+1, "column_value:%.*s", - sql_result.fields_[i].column_value_.config_string_.length(), - sql_result.fields_[i].column_value_.config_string_.ptr()); + printf(" (%s) ", token_type_to_string(sql_result.fields_[i]->value_type_).c_str()); + if(sql_result.fields_[i]->value_type_ == TOKEN_INT_VAL) { + snprintf(buf, 256, "column_value:%ld", sql_result.fields_[i]->column_int_value_); + } else if (sql_result.fields_[i]->value_type_ == TOKEN_STR_VAL){ + snprintf(buf, sql_result.fields_[i]->column_value_.config_string_.length()+1, "column_value:%.*s", + sql_result.fields_[i]->column_value_.config_string_.length(), + sql_result.fields_[i]->column_value_.config_string_.ptr()); } printf("%s\n", buf); // fprintf(stdout, "%s %s %s\n", sql_result.fields_[i].column_name_, @@ -136,7 +137,6 @@ void build_schema(std::string &extra_str, ObExprParseResult &result) pos = 0; result.part_key_info_.key_num_ = 0; - result.target_mask_ = 0; while (true) { ObProxyParseString part_key_name = get_value(extra_str, "part_key", pos); ObProxyParseString part_key_level = get_value(extra_str, "part_level", pos); @@ -161,11 +161,6 @@ void build_schema(std::string &extra_str, ObExprParseResult &result) result.part_key_info_.part_keys_[result.part_key_info_.key_num_].idx_ = part_key_idx.str_[0] - '0'; } ++result.part_key_info_.key_num_; - if (PART_KEY_LEVEL_ONE == level) { - result.target_mask_ |= BOTH_BOUND_FLAG; - } else { - result.target_mask_ |= (BOTH_BOUND_FLAG << 2); - } } } } @@ -206,8 +201,8 @@ void extract_local_fileds(const ObExprParseResult& result, ObProxyMysqlRequest & printf("Got an empty relation_expr"); continue; } - SqlField field; - field.reset(); + SqlField *field = NULL; + SqlField::alloc_sql_field(field); //sql_result.fields_[sql_result.field_num_].type_ = relation_expr->type_; if(relation_expr->left_value_ != NULL && relation_expr->left_value_->head_ != NULL @@ -216,9 +211,9 @@ void extract_local_fileds(const ObExprParseResult& result, ObProxyMysqlRequest & ObString tmp_column(relation_expr->left_value_->head_->column_name_.str_len_, relation_expr->left_value_->head_->column_name_.str_); LOG_DEBUG("column_name is ", K(tmp_column)); - field.column_name_.set(tmp_column); + field->column_name_.set_value(tmp_column); - LOG_DEBUG("field.column", K(field.column_name_)); + LOG_DEBUG("field->column", K(field->column_name_)); // strncpy(sql_result.fields_[sql_result.field_num_].column_name_, // relation_expr->left_value_->head_->column_name_.str_, // relation_expr->left_value_->head_->column_name_.str_len_); @@ -233,19 +228,19 @@ void extract_local_fileds(const ObExprParseResult& result, ObProxyMysqlRequest & if(relation_expr->right_value_ != NULL && relation_expr->right_value_->head_ != NULL) { if(relation_expr->right_value_->head_->type_ == TOKEN_INT_VAL) { - field.value_type_ = TOKEN_INT_VAL; - field.column_int_value_ = relation_expr->right_value_->head_->int_value_; - LOG_DEBUG("field.value", K(field.column_int_value_)); + field->value_type_ = TOKEN_INT_VAL; + field->column_int_value_ = relation_expr->right_value_->head_->int_value_; + LOG_DEBUG("field->value", K(field->column_int_value_)); // snprintf(sql_result.fields_[sql_result.field_num_].column_value_, // 32, "%ld", relation_expr->right_value_->head_->int_value_); // sql_result.fields_[sql_result.field_num_].column_value_ = ""; // sql_result.fields_[sql_result.field_num_].column_value_ = std::string(buf); } else if(relation_expr->right_value_->head_->type_ == TOKEN_STR_VAL) { - field.value_type_ = TOKEN_STR_VAL; - field.column_value_.config_string_.assign_ptr( + field->value_type_ = TOKEN_STR_VAL; + field->column_value_.config_string_.assign_ptr( relation_expr->right_value_->head_->str_value_.str_, relation_expr->right_value_->head_->str_value_.str_len_); - LOG_DEBUG("field.column_value", K(field.column_value_)); + LOG_DEBUG("field->column_value", K(field->column_value_)); // strncpy(sql_result.fields_[sql_result.field_num_].column_value_, // relation_expr->right_value_->head_->str_value_.str_, diff --git a/unittest/obproxy/test_cgroup_ctrl.cpp b/unittest/obproxy/test_cgroup_ctrl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..553361e53ec0f5110c7b07dd8b67b08d6f03d007 --- /dev/null +++ b/unittest/obproxy/test_cgroup_ctrl.cpp @@ -0,0 +1,126 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * + * ************************************************************* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "all_mock.h" +#include "observer/omt/ob_cgroup_ctrl.h" +#include "lib/atomic/ob_atomic.h" + +using namespace oceanbase::common; +using namespace oceanbase::omt; +using namespace oceanbase::observer; + +void *thread_func(void *args) +{ + int *tid = static_cast(args); + *tid = static_cast(syscall(SYS_gettid)); + sleep(3); +} + +// Create a soft chain from the current directory to the cgroup directory in advance. +// The cgroup directory needs to mount three modules: cpu, cpuset, and cpuacct +TEST(TestCgroupCtrl, AddDelete) +{ + ObCgroupCtrl cg_ctrl; + ASSERT_EQ(OB_SUCCESS, cg_ctrl.init()); + ASSERT_TRUE(cg_ctrl.is_valid()); + + int tids[4]; + pthread_t ts[4]; + for (int i = 0; i < 4; i++) { + pthread_create(&ts[i], nullptr, thread_func, &tids[i]); + } + sleep(1); + + const uint64_t tenant_id1 = 1001; + ASSERT_EQ(OB_SUCCESS, cg_ctrl.create_tenant_cgroup(tenant_id1)); + ASSERT_EQ(OB_SUCCESS, cg_ctrl.add_thread_to_cgroup(tenant_id1, tids[0])); + ASSERT_EQ(OB_SUCCESS, cg_ctrl.add_thread_to_cgroup(tenant_id1, tids[1])); + + const uint64_t tenant_id2 = 1002; + ASSERT_EQ(OB_SUCCESS, cg_ctrl.create_tenant_cgroup(tenant_id2)); + ASSERT_EQ(OB_SUCCESS, cg_ctrl.add_thread_to_cgroup(tenant_id2, tids[2])); + ASSERT_EQ(OB_SUCCESS, cg_ctrl.add_thread_to_cgroup(tenant_id2, tids[3])); + + ASSERT_EQ(OB_SUCCESS, cg_ctrl.remove_thread_from_cgroup(tenant_id2, tids[2])); + ASSERT_EQ(OB_SUCCESS, cg_ctrl.remove_thread_from_cgroup(tenant_id2, tids[3])); + + ASSERT_EQ(OB_SUCCESS, cg_ctrl.remove_tenant_cgroup(tenant_id1)); + + for (int i = 0; i < 4; i++) { + pthread_join(ts[i], nullptr); + } +} + +TEST(TestCgroupCtrl, SetGetValue) +{ + ObCgroupCtrl cg_ctrl; + ASSERT_EQ(OB_SUCCESS, cg_ctrl.init()); + ASSERT_TRUE(cg_ctrl.is_valid()); + + int tids[4]; + pthread_t ts[4]; + for (int i = 0; i < 4; i++) { + pthread_create(&ts[i], nullptr, thread_func, &tids[i]); + } + sleep(1); + + const uint64_t tenant_id1 = 1001; + ASSERT_EQ(OB_SUCCESS, cg_ctrl.create_tenant_cgroup(tenant_id1)); + ASSERT_EQ(OB_SUCCESS, cg_ctrl.add_thread_to_cgroup(tenant_id1, tids[0])); + ASSERT_EQ(OB_SUCCESS, cg_ctrl.add_thread_to_cgroup(tenant_id1, tids[1])); + + const int32_t cpu_shares = 2048; + int32_t cpu_shares_v = 0; + ASSERT_EQ(OB_SUCCESS, cg_ctrl.set_cpu_shares(tenant_id1, cpu_shares)); + ASSERT_EQ(OB_SUCCESS, cg_ctrl.get_cpu_shares(tenant_id1, cpu_shares_v)); + ASSERT_EQ(cpu_shares, cpu_shares_v); + + const int32_t cpu_cfs_quota = 80000; + int32_t cpu_cfs_quota_v = 0; + ASSERT_EQ(OB_SUCCESS, cg_ctrl.set_cpu_cfs_quota(tenant_id1, cpu_cfs_quota)); + ASSERT_EQ(OB_SUCCESS, cg_ctrl.get_cpu_cfs_quota(tenant_id1, cpu_cfs_quota_v)); + ASSERT_EQ(cpu_cfs_quota, cpu_cfs_quota_v); + + for (int i = 0; i < 4; i++) { + pthread_join(ts[i], nullptr); + } +} +int main(int argc, char *argv[]) +{ + OB_LOGGER.set_file_name("test_cgroup_ctrl.log", true); + OB_LOGGER.set_log_level("INFO"); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + diff --git a/unittest/obproxy/test_ldc_location.cpp b/unittest/obproxy/test_ldc_location.cpp index 80f9bbe9ce8ebaee658b12b517c135fbd9a60a4c..cc2c69fd26f35e8bf42760d65179dcaed43b58be 100644 --- a/unittest/obproxy/test_ldc_location.cpp +++ b/unittest/obproxy/test_ldc_location.cpp @@ -27,7 +27,7 @@ EXPECT_TRUE(is_partition_server == item->is_partition_server_);\ EXPECT_TRUE(item->is_used_);\ EXPECT_FALSE(item->is_force_congested_);\ - EXPECT_EQ(ObAddr::convert_ipv4_addr(addr), item->replica_->server_.get_ipv4());\ + EXPECT_EQ(convert_ipv4_addr_utils(addr), item->replica_->server_.get_ipv4());\ EXPECT_EQ(port, item->replica_->server_.get_port());\ EXPECT_EQ(type1, test_ldc_route.get_curr_route_type());\ EXPECT_TRUE(!test_ldc_route.is_reach_end()); @@ -41,6 +41,25 @@ namespace obproxy namespace proxy { +static uint32_t convert_ipv4_addr_utils(const char *ip) +{ + in_addr binary; + int iret = 0; + uint32_t result = 0; + + if (!OB_ISNULL(ip)) { + memset(&binary, 0, sizeof (binary)); + iret = inet_pton(AF_INET, ip, &binary); + if (iret == -1) { // no support family + binary.s_addr = 0; + } else if (iret == 0) { // invalid ip string + binary.s_addr = 0; + } + result = ntohl(binary.s_addr); + } + return result; +} + class TesLDCLocation : public ::testing::Test { @@ -182,7 +201,7 @@ void TesLDCLocation::test_get_next_item(ObLDCRoute &test_ldc_route, ASSERT_TRUE(test_ldc_route.disable_merge_status_check_ || is_merge == item->is_merging_); ASSERT_TRUE(zone_type == item->zone_type_); ASSERT_TRUE(is_partition == item->is_partition_server_); - ASSERT_EQ(ObAddr::convert_ipv4_addr(ip_str), item->replica_->server_.get_ipv4()); + ASSERT_EQ(convert_ipv4_addr_utils(ip_str), item->replica_->server_.get_ipv4()); ASSERT_EQ(port, item->replica_->server_.get_port()); ASSERT_EQ(route_type, test_ldc_route.get_curr_route_type()); ASSERT_TRUE(!test_ldc_route.is_reach_end()); @@ -206,7 +225,7 @@ void TesLDCLocation::test_get_next_item(ObLDCRoute &test_ldc_route, ASSERT_TRUE(role == item->replica_->role_); } ASSERT_TRUE(is_partition == item->is_partition_server_); - ASSERT_EQ(ObAddr::convert_ipv4_addr(ip_str), item->replica_->server_.get_ipv4()); + ASSERT_EQ(convert_ipv4_addr_utils(ip_str), item->replica_->server_.get_ipv4()); ASSERT_EQ(port, item->replica_->server_.get_port()); ASSERT_EQ(route_type, test_ldc_route.get_curr_route_type()); ASSERT_TRUE(!test_ldc_route.is_reach_end()); @@ -429,15 +448,15 @@ TEST_F(TesLDCLocation, assign) ObLDCItem *item_array = const_cast(test_ldc.get_item_array()); for (int64_t i = 0; i < 10; i++) { EXPECT_EQ(SAME_IDC, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("1.1.1.1"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("1.1.1.1"), item_array[i].replica_->server_.get_ipv4()); } for (int64_t i = 10; i < 25; i++) { EXPECT_EQ(SAME_IDC, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("2.2.2.2"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("2.2.2.2"), item_array[i].replica_->server_.get_ipv4()); } for (int64_t i = 25; i < 40; i++) { EXPECT_EQ(SAME_IDC, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("3.3.3.3"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("3.3.3.3"), item_array[i].replica_->server_.get_ipv4()); } //empty name treat as do not use @@ -459,15 +478,15 @@ TEST_F(TesLDCLocation, assign) item_array = const_cast(test_ldc.get_item_array()); for (int64_t i = 0; i < 10; i++) { EXPECT_EQ(SAME_IDC, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("1.1.1.1"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("1.1.1.1"), item_array[i].replica_->server_.get_ipv4()); } for (int64_t i = 10; i < 25; i++) { EXPECT_EQ(SAME_IDC, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("2.2.2.2"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("2.2.2.2"), item_array[i].replica_->server_.get_ipv4()); } for (int64_t i = 25; i < 40; i++) { EXPECT_EQ(SAME_IDC, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("3.3.3.3"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("3.3.3.3"), item_array[i].replica_->server_.get_ipv4()); } //right name, but congestion is not available @@ -489,19 +508,19 @@ TEST_F(TesLDCLocation, assign) item_array = const_cast(test_ldc.get_item_array()); for (int64_t i = 0; i < 15; i++) { EXPECT_EQ(SAME_IDC, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("1.1.1.1"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("1.1.1.1"), item_array[i].replica_->server_.get_ipv4()); } for (int64_t i = 15; i < 30; i++) { EXPECT_EQ(SAME_IDC, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("2.2.2.2"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("2.2.2.2"), item_array[i].replica_->server_.get_ipv4()); } for (int64_t i = 30; i < 45; i++) { EXPECT_EQ(SAME_IDC, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("3.3.3.3"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("3.3.3.3"), item_array[i].replica_->server_.get_ipv4()); } for (int64_t i = 45; i < 60; i++) { EXPECT_EQ(SAME_IDC, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("4.4.4.4"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("4.4.4.4"), item_array[i].replica_->server_.get_ipv4()); } //right name @@ -522,15 +541,15 @@ TEST_F(TesLDCLocation, assign) item_array = const_cast(test_ldc.get_item_array()); for (int64_t i = site_start_index_array[SAME_IDC]; i < site_start_index_array[SAME_REGION]; i++) { EXPECT_EQ(SAME_IDC, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("1.1.1.1"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("1.1.1.1"), item_array[i].replica_->server_.get_ipv4()); } for (int64_t i = site_start_index_array[SAME_REGION]; i < site_start_index_array[OTHER_REGION]; i++) { EXPECT_EQ(SAME_REGION, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("2.2.2.2"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("2.2.2.2"), item_array[i].replica_->server_.get_ipv4()); } for (int64_t i = site_start_index_array[OTHER_REGION]; i < site_start_index_array[MAX_IDC_TYPE]; i++) { EXPECT_EQ(OTHER_REGION, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("3.3.3.3"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("3.3.3.3"), item_array[i].replica_->server_.get_ipv4()); } for (int64_t i = site_start_index_array[SAME_IDC]; i < site_start_index_array[SAME_IDC] + 5; i++) { @@ -646,11 +665,11 @@ TEST_F(TesLDCLocation, assign_other_region) ObLDCItem *item_array = const_cast(test_ldc.get_item_array()); for (int64_t i = site_start_index_array[SAME_IDC]; i < site_start_index_array[SAME_REGION]; i++) { EXPECT_EQ(SAME_IDC, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("3.3.3.3"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("3.3.3.3"), item_array[i].replica_->server_.get_ipv4()); } for (int64_t i = site_start_index_array[OTHER_REGION]; i < site_start_index_array[MAX_IDC_TYPE]; i++) { EXPECT_EQ(OTHER_REGION, item_array[i].idc_type_); - EXPECT_NE(ObAddr::convert_ipv4_addr("3.3.3.3"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_NE(convert_ipv4_addr_utils("3.3.3.3"), item_array[i].replica_->server_.get_ipv4()); } for (int64_t i = site_start_index_array[SAME_IDC]; i < site_start_index_array[SAME_IDC] + 5; i++) { @@ -747,15 +766,15 @@ TEST_F(TesLDCLocation, assign_non_ldc) ObLDCItem *item_array = const_cast(test_ldc.get_item_array()); for (int64_t i = 0; i < 10; i++) { EXPECT_EQ(SAME_IDC, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("1.1.1.1"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("1.1.1.1"), item_array[i].replica_->server_.get_ipv4()); } for (int64_t i = 10; i < 25; i++) { EXPECT_EQ(SAME_IDC, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("2.2.2.2"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("2.2.2.2"), item_array[i].replica_->server_.get_ipv4()); } for (int64_t i = 25; i < 40; i++) { EXPECT_EQ(SAME_IDC, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("3.3.3.3"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("3.3.3.3"), item_array[i].replica_->server_.get_ipv4()); } for (int64_t i = 0; i < 10; i++) { @@ -835,8 +854,10 @@ TEST_F(TesLDCLocation, fill_strong_read_location) ObSEArray servers_info; ObString proxy_primary_zone_name; bool need_skip_leader = false; - ASSERT_EQ(OB_ERR_UNEXPECTED, ObLDCLocation::fill_strong_read_location(&pl, dummy_ldc, leader_item, target_ldc, entry_need_update, is_only_readwrite_zone, - need_use_dup_replica, need_skip_leader, servers_info, region_names, proxy_primary_zone_name)); + bool is_random_route_mode = false; + ASSERT_EQ(OB_ERR_UNEXPECTED, ObLDCLocation::fill_strong_read_location(&pl, dummy_ldc, leader_item, target_ldc, + entry_need_update, is_only_readwrite_zone, need_use_dup_replica, need_skip_leader, is_random_route_mode, + servers_info, region_names, proxy_primary_zone_name, ObString(), NULL)); ASSERT_EQ(OB_SUCCESS, dummy_ldc.assign(&ts, ss_info_, idc_name, true, cluster_name, OB_DEFAULT_CLUSTER_ID)); ASSERT_TRUE(dummy_ldc.is_ldc_used()); @@ -876,7 +897,8 @@ TEST_F(TesLDCLocation, fill_strong_read_location) ASSERT_TRUE(!dummy_ldc.is_empty()); ASSERT_EQ(OB_SUCCESS, ObLDCLocation::fill_strong_read_location(&pl, dummy_ldc, leader_item, - target_ldc, entry_need_update, is_only_readwrite_zone, need_use_dup_replica, need_skip_leader, servers_info, region_names, proxy_primary_zone_name)); + target_ldc, entry_need_update, is_only_readwrite_zone, need_use_dup_replica, need_skip_leader, + is_random_route_mode, servers_info, region_names, proxy_primary_zone_name, ObString(), NULL)); ASSERT_TRUE(target_ldc.is_ldc_used()); ASSERT_TRUE(!entry_need_update); ASSERT_TRUE(!leader_item.is_valid()); @@ -896,7 +918,8 @@ TEST_F(TesLDCLocation, fill_strong_read_location) is_only_readwrite_zone = true; ASSERT_EQ(OB_SUCCESS, ObLDCLocation::fill_strong_read_location(&pl, dummy_ldc, leader_item, - target_ldc, entry_need_update, is_only_readwrite_zone, need_use_dup_replica, need_skip_leader, servers_info, region_names, proxy_primary_zone_name)); + target_ldc, entry_need_update, is_only_readwrite_zone, need_use_dup_replica, need_skip_leader, + is_random_route_mode, servers_info, region_names, proxy_primary_zone_name, ObString(), NULL)); ASSERT_TRUE(target_ldc.is_ldc_used()); ASSERT_TRUE(entry_need_update); ASSERT_TRUE(leader_item.is_valid()); @@ -912,7 +935,8 @@ TEST_F(TesLDCLocation, fill_strong_read_location) is_only_readwrite_zone = false; ASSERT_EQ(OB_SUCCESS, ObLDCLocation::fill_strong_read_location(&pl, dummy_ldc, leader_item, - target_ldc, entry_need_update, is_only_readwrite_zone, need_use_dup_replica, need_skip_leader, servers_info, region_names, proxy_primary_zone_name)); + target_ldc, entry_need_update, is_only_readwrite_zone, need_use_dup_replica, need_skip_leader, + is_random_route_mode, servers_info, region_names, proxy_primary_zone_name, ObString(), NULL)); ASSERT_TRUE(target_ldc.is_ldc_used()); ASSERT_TRUE(entry_need_update); ASSERT_TRUE(leader_item.is_valid()); @@ -932,7 +956,8 @@ TEST_F(TesLDCLocation, set_ldc_location) ObLDCLocation dummy_ldc; ObProxyPartitionLocation pl; ObSEArray tmp_item_array; - ASSERT_EQ(OB_SUCCESS, target_ldc.set_ldc_location(&pl, dummy_ldc, tmp_item_array)); + ObSEArray tmp_pz_item_array; + ASSERT_EQ(OB_SUCCESS, target_ldc.set_ldc_location(&pl, dummy_ldc, tmp_item_array, tmp_pz_item_array)); ASSERT_TRUE(!target_ldc.is_ldc_used()); ASSERT_TRUE(target_ldc.is_empty()); @@ -954,7 +979,7 @@ TEST_F(TesLDCLocation, set_ldc_location) tmp_item_array.push_back(same_idc_item); tmp_item_array.push_back(same_region_item); - ASSERT_EQ(OB_SUCCESS, target_ldc.set_ldc_location(&pl, dummy_ldc, tmp_item_array)); + ASSERT_EQ(OB_SUCCESS, target_ldc.set_ldc_location(&pl, dummy_ldc, tmp_item_array, tmp_pz_item_array)); ASSERT_TRUE(!target_ldc.is_ldc_used()); ASSERT_TRUE(!target_ldc.is_empty()); ASSERT_EQ(12, target_ldc.count()); @@ -1337,19 +1362,19 @@ TEST_F(TesLDCLocation, get_next_item) item_array = const_cast(test_ldc.get_item_array()); for (int64_t i = site_start_index_array[SAME_IDC]; i < site_start_index_array[SAME_REGION]; i++) { EXPECT_EQ(SAME_IDC, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("1.1.1.1"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("1.1.1.1"), item_array[i].replica_->server_.get_ipv4()); EXPECT_EQ((i < 10 ? ZONE_TYPE_READWRITE : ZONE_TYPE_READONLY), item_array[i].zone_type_); EXPECT_TRUE((i % 10 < 5) == item_array[i].is_merging_); } for (int64_t i = site_start_index_array[SAME_REGION]; i < site_start_index_array[OTHER_REGION]; i++) { EXPECT_EQ(SAME_REGION, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("2.2.2.2"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("2.2.2.2"), item_array[i].replica_->server_.get_ipv4()); EXPECT_EQ((i < (10 + site_start_index_array[SAME_REGION])? ZONE_TYPE_READWRITE : ZONE_TYPE_READONLY), item_array[i].zone_type_); EXPECT_TRUE((i % 10 < 5) == item_array[i].is_merging_); } for (int64_t i = site_start_index_array[OTHER_REGION]; i < site_start_index_array[MAX_IDC_TYPE]; i++) { EXPECT_EQ(OTHER_REGION, item_array[i].idc_type_); - EXPECT_EQ(ObAddr::convert_ipv4_addr("3.3.3.3"), item_array[i].replica_->server_.get_ipv4()); + EXPECT_EQ(convert_ipv4_addr_utils("3.3.3.3"), item_array[i].replica_->server_.get_ipv4()); EXPECT_EQ((i < (10 + site_start_index_array[OTHER_REGION]) ? ZONE_TYPE_READWRITE : ZONE_TYPE_READONLY), item_array[i].zone_type_); EXPECT_TRUE((i % 10 < 5) == item_array[i].is_merging_); } diff --git a/unittest/obproxy/test_mysql_request_analyzer.cpp b/unittest/obproxy/test_mysql_request_analyzer.cpp index e12eeb1d79221b1d0a054aa4d9cdbdee44e9e489..77b48f6683d9fae14fd3db6c8a41d66ba870c4be 100644 --- a/unittest/obproxy/test_mysql_request_analyzer.cpp +++ b/unittest/obproxy/test_mysql_request_analyzer.cpp @@ -52,9 +52,9 @@ void TestEvent::TearDown() void TestEvent::gen_mysql_packet(char *&data, const int64_t packet_size) { data = (char *) malloc(packet_size + MYSQL_NET_HEADER_LENGTH); - ob_int3store(data, packet_size); + int3store(data, packet_size); int64_t size = 0; - size = ob_uint3korr(data); + size = uint3korr(data); LOG_INFO("gen mysql packet", K(size)); } @@ -731,12 +731,12 @@ TEST_F(TestEvent, test_analyze_16m_0b_in_one_buffer) ObRequestBuffer buffer; tmp_buf = (char *) malloc(MYSQL_NET_HEADER_LENGTH + packet_len_16m + MYSQL_NET_HEADER_LENGTH + packet_len_0b); - ob_int3store(tmp_buf, packet_len_16m); - size = ob_uint3korr(tmp_buf); + int3store(tmp_buf, packet_len_16m); + size = uint3korr(tmp_buf); LOG_INFO("gen mysql packet", K(size)); - ob_int3store(tmp_buf + (MYSQL_NET_HEADER_LENGTH + packet_len_16m), packet_len_0b); - size = ob_uint3korr(tmp_buf + (MYSQL_NET_HEADER_LENGTH + packet_len_16m)); + int3store(tmp_buf + (MYSQL_NET_HEADER_LENGTH + packet_len_16m), packet_len_0b); + size = uint3korr(tmp_buf + (MYSQL_NET_HEADER_LENGTH + packet_len_16m)); LOG_INFO("gen mysql packet", K(size)); buffer.assign_ptr(tmp_buf, MYSQL_NET_HEADER_LENGTH + packet_len_16m + MYSQL_NET_HEADER_LENGTH + packet_len_0b); diff --git a/unittest/obproxy/test_proxy_table_processor_utils.cpp b/unittest/obproxy/test_proxy_table_processor_utils.cpp index 02953428d52b75726e3438e28ebe929811b86ba1..4b5e07870928c491541336c43b0f8a6172420c78 100644 --- a/unittest/obproxy/test_proxy_table_processor_utils.cpp +++ b/unittest/obproxy/test_proxy_table_processor_utils.cpp @@ -42,8 +42,8 @@ TEST_F(TestProxyTableProcessorUtils, test_get_proxy_local_addr) ASSERT_EQ(addr, addr_org); ObAddr my_addr; - char ip_str[OB_IP_STR_BUFF] = {'\0'}; - int ret = ObProxyTableProcessorUtils::get_one_local_addr(ip_str, OB_IP_STR_BUFF); + char ip_str[MAX_IP_ADDR_LENGTH] = {'\0'}; + int ret = ObProxyTableProcessorUtils::get_one_local_addr(ip_str, MAX_IP_ADDR_LENGTH); ASSERT_EQ(OB_SUCCESS, ret); my_addr.set_ipv4_addr(ip_str, static_cast(config.listen_port)); @@ -63,15 +63,15 @@ TEST_F(TestProxyTableProcessorUtils, test_get_proxy_local_addr_inherited) int ret = OB_SUCCESS; ObHotUpgraderInfo &info = get_global_hot_upgrade_info(); info.is_inherited_ = true; - info.fd_ = NO_FD; + info.ipv4_fd_ = NO_FD; ObAddr addr; ret = ObProxyTableProcessorUtils::get_proxy_local_addr(addr); ASSERT_EQ(OB_ERR_UNEXPECTED, ret); - char ip_str[OB_IP_STR_BUFF] = {'\0'}; - ret = ObProxyTableProcessorUtils::get_one_local_addr(ip_str, OB_IP_STR_BUFF); + char ip_str[MAX_IP_ADDR_LENGTH] = {'\0'}; + ret = ObProxyTableProcessorUtils::get_one_local_addr(ip_str, MAX_IP_ADDR_LENGTH); ASSERT_EQ(OB_SUCCESS, ret); struct sockaddr_in s_add; @@ -87,7 +87,7 @@ TEST_F(TestProxyTableProcessorUtils, test_get_proxy_local_addr_inherited) close(test_fd); } ASSERT_TRUE(-1 != bind_ret); - info.fd_ = test_fd; + info.ipv4_fd_ = test_fd; ret = ObProxyTableProcessorUtils::get_proxy_local_addr(addr); ASSERT_EQ(OB_SUCCESS, ret); ObAddr addr2(ObAddr::IPV4, ip_str, port); @@ -107,7 +107,7 @@ TEST_F(TestProxyTableProcessorUtils, test_get_proxy_local_addr_inherited) close(test_fd); } ASSERT_TRUE(-1 != bind_ret); - info.fd_ = test_fd; + info.ipv4_fd_ = test_fd; ret = ObProxyTableProcessorUtils::get_proxy_local_addr(addr); ASSERT_EQ(OB_SUCCESS, ret); addr2.reset(); diff --git a/unittest/obproxy/test_tenant_processor.cpp b/unittest/obproxy/test_tenant_processor.cpp index 78b1f7db825f6a233cdc0db9133d257371c9e3a5..70c4868599a21339f767b94dd2d7bc07875b9040 100644 --- a/unittest/obproxy/test_tenant_processor.cpp +++ b/unittest/obproxy/test_tenant_processor.cpp @@ -28,11 +28,11 @@ * limitations under the License. */ -//#define private public #define USING_LOG_PREFIX PROXY #include #include #include "lib/objectpool/ob_concurrency_objpool.h" +#include "obproxy/omt/ob_conn_table_processor.h" #include "obproxy/omt/ob_resource_unit_table_processor.h" #include "obproxy/obutils/ob_config_processor.h" #include "lib/oblog/ob_log.h" @@ -53,7 +53,7 @@ struct conn_map_def { class TestTenantProcessor : public ::testing::Test { public: - TestTenantProcessor(): t_processor_(get_global_resource_unit_table_processor()) {} + TestTenantProcessor(): t_processor_(get_global_conn_table_processor()) {} int init_env(); int check_map_value(conn_map_def* conn_map, uint32_t size); @@ -64,7 +64,7 @@ public: //t_processor_.destroy(); } - ObResourceUnitTableProcessor& t_processor_; + ObConnTableProcessor& t_processor_; }; static int callback(void *NotUsed, int argc, char **argv, char **azColName) @@ -184,7 +184,7 @@ TEST_F(TestTenantProcessor, test_multi_vt_conn) char *zErrMsg = 0; ASSERT_EQ(0, init_env()); - + /* replace SQL statement */ sql = (char*)"replace into resource_unit(name, value, cluster_name, tenant_name)" \ "values('resource_max_connections', '[{\"vip\": \"127.0.0.1\", \"value\": 2000}, {\"vip\": \"127.0.0.2\", \"value\": 3000}]', 'ob_cluster', 'ob_tenant');"; @@ -213,7 +213,7 @@ TEST_F(TestTenantProcessor, test_multi_row_vt_conn) char *zErrMsg = 0; ASSERT_EQ(0, init_env()); - + /* replace SQL statement */ sql = (char*)"replace into resource_unit(name, value, cluster_name, tenant_name)" \ "values('resource_max_connections', '[{\"vip\": \"127.0.0.1\", \"value\": 2000}, {\"vip\": \"127.0.0.2\", \"value\": 3000}]', 'ob_cluster', 'ob_tenant');"; @@ -254,7 +254,7 @@ TEST_F(TestTenantProcessor, test_repeat_key) char *zErrMsg = 0; ASSERT_EQ(0, init_env()); - + /* replace SQL statement */ sql = (char*)"replace into resource_unit(name, value, cluster_name, tenant_name)" \ "values('resource_max_connections', '[{\"vip\": \"127.0.0.1\", \"value\": 2000}," \ @@ -284,8 +284,9 @@ TEST_F(TestTenantProcessor, test_diff_key) char *zErrMsg = 0; ASSERT_EQ(0, init_env()); - + // Insert connection related information + sql = (char*)"replace into resource_unit(name, value, cluster_name, tenant_name)" \ "values('resource_max_connections', '[{\"vip\": \"127.0.0.1\", \"value\": 2000}," \ "{\"vip\": \"127.0.0.2\", \"value\": 4450}]', 'ob_cluster', 'ob_tenant');"; @@ -352,28 +353,31 @@ TEST_F(TestTenantProcessor, test_no_conn_key) TEST_F(TestTenantProcessor, test_execute) { ASSERT_EQ(0, init_env()); - + SqlFieldResult sql_result; sql_result.field_num_ = 4; - SqlField sql_field; - sql_field.column_name_.set("cluster"); - sql_field.column_value_.set_value("ob_cluster"); + SqlField *sql_field = NULL; + SqlField::alloc_sql_field(sql_field); + sql_field->column_name_.set_value("cluster"); + sql_field->column_value_.set_value("ob_cluster"); sql_result.fields_.push_back(sql_field); - - sql_field.column_name_.set("tenant"); - sql_field.column_value_.set_value("ob_tenant"); + + SqlField::alloc_sql_field(sql_field); + sql_field->column_name_.set_value("tenant"); + sql_field->column_value_.set_value("ob_tenant"); sql_result.fields_.push_back(sql_field); - sql_field.column_name_.set("name"); - sql_field.column_value_.set_value("resource_max_connections"); + SqlField::alloc_sql_field(sql_field); + sql_field->column_name_.set_value("name"); + sql_field->column_value_.set_value("resource_max_connections"); sql_result.fields_.push_back(sql_field); - sql_field.column_name_.set("value"); - sql_field.column_value_.set_value("[{\"vip\": \"127.0.0.1\", \"value\": 5000}]"); + SqlField::alloc_sql_field(sql_field); + sql_field->column_name_.set_value("value"); + sql_field->column_value_.set_value("[{\"vip\": \"127.0.0.1\", \"value\": 5000}]"); sql_result.fields_.push_back(sql_field); - + ObCloudFnParams cloud_params; - cloud_params.config_type_ = OBPROXY_CONFIG_CLOUD; cloud_params.stmt_type_ = OBPROXY_T_REPLACE; cloud_params.fields_ = &sql_result; cloud_params.cluster_name_ = "ob_cluster"; @@ -399,28 +403,31 @@ TEST_F(TestTenantProcessor, test_execute) TEST_F(TestTenantProcessor, test_rollback) { ASSERT_EQ(0, init_env()); - + SqlFieldResult sql_result; sql_result.field_num_ = 4; - SqlField sql_field; - sql_field.column_name_.set("cluster"); - sql_field.column_value_.set_value("ob_cluster"); + SqlField *sql_field = NULL; + SqlField::alloc_sql_field(sql_field); + sql_field->column_name_.set_value("cluster"); + sql_field->column_value_.set_value("ob_cluster"); sql_result.fields_.push_back(sql_field); - - sql_field.column_name_.set("tenant"); - sql_field.column_value_.set_value("ob_tenant"); + + SqlField::alloc_sql_field(sql_field); + sql_field->column_name_.set_value("tenant"); + sql_field->column_value_.set_value("ob_tenant"); sql_result.fields_.push_back(sql_field); - sql_field.column_name_.set("name"); - sql_field.column_value_.set_value("resource_max_connections"); + SqlField::alloc_sql_field(sql_field); + sql_field->column_name_.set_value("name"); + sql_field->column_value_.set_value("resource_max_connections"); sql_result.fields_.push_back(sql_field); - sql_field.column_name_.set("value"); - sql_field.column_value_.set_value("[{\"vip\": \"127.0.0.1\", \"value\": 5000}]"); + SqlField::alloc_sql_field(sql_field); + sql_field->column_name_.set_value("value"); + sql_field->column_value_.set_value("[{\"vip\": \"127.0.0.1\", \"value\": 5000}]"); sql_result.fields_.push_back(sql_field); - + ObCloudFnParams cloud_params; - cloud_params.config_type_ = OBPROXY_CONFIG_CLOUD; cloud_params.stmt_type_ = OBPROXY_T_REPLACE; cloud_params.fields_ = &sql_result; cloud_params.cluster_name_ = "ob_cluster"; @@ -439,7 +446,7 @@ TEST_F(TestTenantProcessor, test_rollback) ASSERT_EQ(0, check_map_value(conn_map, 1)); // vt_conn_map is empty after rollback - ObResourceUnitTableProcessor::commit(false); + ObResourceUnitTableProcessor::commit(&cloud_params, false); ObVipTenantConnCache::dump_conn_map(*vt_conn_map); LOG_DEBUG("conn map", "count", t_processor_.get_conn_map_count()); ASSERT_EQ(0, t_processor_.get_conn_map_count()); @@ -448,28 +455,27 @@ TEST_F(TestTenantProcessor, test_rollback) TEST_F(TestTenantProcessor, test_execute_update_value) { ASSERT_EQ(0, init_env()); - + SqlFieldResult sql_result; sql_result.field_num_ = 4; SqlField sql_field[4]; - sql_field[0].column_name_.set("cluster"); + sql_field[0].column_name_.set_value("cluster"); sql_field[0].column_value_.set_value("ob_cluster"); - sql_result.fields_.push_back(sql_field[0]); - - sql_field[1].column_name_.set("tenant"); + sql_result.fields_.push_back(&sql_field[0]); + + sql_field[1].column_name_.set_value("tenant"); sql_field[1].column_value_.set_value("ob_tenant"); - sql_result.fields_.push_back(sql_field[1]); + sql_result.fields_.push_back(&sql_field[1]); - sql_field[2].column_name_.set("name"); + sql_field[2].column_name_.set_value("name"); sql_field[2].column_value_.set_value("resource_max_connections"); - sql_result.fields_.push_back(sql_field[2]); + sql_result.fields_.push_back(&sql_field[2]); + + sql_field[3].column_name_.set_value("value"); + sql_field[3].column_value_.set_value("[{\"vip\": \"127.0.0.1\", \"value\": 5000}, {\"vip\": \"10.8.17.120\", \"value\": 6000}]"); + sql_result.fields_.push_back(&sql_field[3]); - sql_field[3].column_name_.set("value"); - sql_field[3].column_value_.set_value("[{\"vip\": \"127.0.0.1\", \"value\": 5000}, {\"vip\": \"127.0.0.2\", \"value\": 6000}]"); - sql_result.fields_.push_back(sql_field[3]); - ObCloudFnParams cloud_params; - cloud_params.config_type_ = OBPROXY_CONFIG_CLOUD; cloud_params.stmt_type_ = OBPROXY_T_REPLACE; cloud_params.fields_ = &sql_result; cloud_params.cluster_name_ = "ob_cluster"; @@ -485,20 +491,25 @@ TEST_F(TestTenantProcessor, test_execute_update_value) {"ob_tenant#ob_cluster|127.0.0.1", 5000} }; ASSERT_EQ(0, check_map_value(conn_map, 2)); - ObResourceUnitTableProcessor::commit(true); + ObResourceUnitTableProcessor::commit(&cloud_params, true); LOG_DEBUG("success1"); - + + SqlField tmp_field[4]; + tmp_field[0] = sql_field[0]; + tmp_field[1] = sql_field[1]; + tmp_field[2] = sql_field[2]; + tmp_field[3] = sql_field[3]; sql_result.reset(); sql_result.field_num_ = 4; - sql_result.fields_.push_back(sql_field[0]); - sql_result.fields_.push_back(sql_field[1]); - sql_result.fields_.push_back(sql_field[2]); - sql_field[3].column_name_.set("value"); - sql_field[3].column_value_.set_value("[{\"vip\": \"127.0.0.3\", \"value\": 4000}, {\"vip\": \"127.0.0.2\", \"value\": 7777}]"); - sql_result.fields_.push_back(sql_field[3]); + sql_result.fields_.push_back(&tmp_field[0]); + sql_result.fields_.push_back(&tmp_field[1]); + sql_result.fields_.push_back(&tmp_field[2]); + sql_field[3].column_name_.set_value("value"); + sql_field[3].column_value_.set_value("[{\"vip\": \"127.0.0.3\", \"value\": 4000}, {\"vip\": \"10.8.17.120\", \"value\": 7777}]"); + sql_result.fields_.push_back(&tmp_field[3]); cloud_params.fields_ = &sql_result; - ASSERT_EQ(0, ObResourceUnitTableProcessor::execute(&cloud_params)); + ASSERT_EQ(0, ObResourceUnitTableProcessor::execute(&cloud_params)); LOG_DEBUG("conn map", "count", t_processor_.get_conn_map_count()); ASSERT_EQ(3, t_processor_.get_conn_map_count()); conn_map_def conn_map_1[3] = { @@ -509,7 +520,7 @@ TEST_F(TestTenantProcessor, test_execute_update_value) ASSERT_EQ(0, check_map_value(conn_map_1, 3)); LOG_DEBUG("success2"); - ObResourceUnitTableProcessor::commit(false); + ObResourceUnitTableProcessor::commit(&cloud_params, false); ObVipTenantConnCache::VTHashMap* vt_conn_map = t_processor_.get_conn_map(); ObVipTenantConnCache::dump_conn_map(*vt_conn_map); conn_map_def conn_map_2[2] = { @@ -524,28 +535,27 @@ TEST_F(TestTenantProcessor, test_execute_update_value) TEST_F(TestTenantProcessor, test_delete_tenant) { ASSERT_EQ(0, init_env()); - + SqlFieldResult sql_result; sql_result.field_num_ = 4; SqlField sql_field[4]; - sql_field[0].column_name_.set("cluster"); + sql_field[0].column_name_.set_value("cluster"); sql_field[0].column_value_.set_value("ob_cluster"); - sql_result.fields_.push_back(sql_field[0]); - - sql_field[1].column_name_.set("tenant"); + sql_result.fields_.push_back(&sql_field[0]); + + sql_field[1].column_name_.set_value("tenant"); sql_field[1].column_value_.set_value("ob_tenant"); - sql_result.fields_.push_back(sql_field[1]); + sql_result.fields_.push_back(&sql_field[1]); - sql_field[2].column_name_.set("name"); + sql_field[2].column_name_.set_value("name"); sql_field[2].column_value_.set_value("resource_max_connections"); - sql_result.fields_.push_back(sql_field[2]); + sql_result.fields_.push_back(&sql_field[2]); + + sql_field[3].column_name_.set_value("value"); + sql_field[3].column_value_.set_value("[{\"vip\": \"127.0.0.1\", \"value\": 5000}, {\"vip\": \"10.8.17.120\", \"value\": 6000}]"); + sql_result.fields_.push_back(&sql_field[3]); - sql_field[3].column_name_.set("value"); - sql_field[3].column_value_.set_value("[{\"vip\": \"127.0.0.1\", \"value\": 5000}, {\"vip\": \"127.0.0.2\", \"value\": 6000}]"); - sql_result.fields_.push_back(sql_field[3]); - ObCloudFnParams cloud_params; - cloud_params.config_type_ = OBPROXY_CONFIG_CLOUD; cloud_params.stmt_type_ = OBPROXY_T_REPLACE; cloud_params.fields_ = &sql_result; cloud_params.cluster_name_ = "ob_cluster"; @@ -563,19 +573,24 @@ TEST_F(TestTenantProcessor, test_delete_tenant) ASSERT_EQ(0, check_map_value(conn_map, 2)); LOG_DEBUG("success1"); + SqlField tmp_field[4]; + tmp_field[0] = sql_field[0]; + tmp_field[1] = sql_field[1]; + tmp_field[2] = sql_field[2]; + tmp_field[3] = sql_field[3]; sql_result.reset(); sql_result.field_num_ = 4; - sql_result.fields_.push_back(sql_field[0]); - sql_field[1].column_name_.set("tenant"); + sql_result.fields_.push_back(&tmp_field[0]); + sql_field[1].column_name_.set_value("tenant"); sql_field[1].column_value_.set_value("ob_tenant_1"); - sql_result.fields_.push_back(sql_field[1]); - sql_result.fields_.push_back(sql_field[2]); - sql_field[3].column_name_.set("value"); - sql_field[3].column_value_.set_value("[{\"vip\": \"127.0.0.3\", \"value\": 4000}, {\"vip\": \"127.0.0.2\", \"value\": 7777}]"); - sql_result.fields_.push_back(sql_field[3]); + sql_result.fields_.push_back(&tmp_field[1]); + sql_result.fields_.push_back(&tmp_field[2]); + sql_field[3].column_name_.set_value("value"); + sql_field[3].column_value_.set_value("[{\"vip\": \"127.0.0.1\", \"value\": 4000}, {\"vip\": \"10.8.17.120\", \"value\": 7777}]"); + sql_result.fields_.push_back(&tmp_field[3]); cloud_params.fields_ = &sql_result; cloud_params.tenant_name_ = "ob_tenant_1"; - + ASSERT_EQ(0, ObResourceUnitTableProcessor::execute(&cloud_params)); ObVipTenantConnCache::VTHashMap* vt_conn_map = t_processor_.get_conn_map(); ObVipTenantConnCache::dump_conn_map(*vt_conn_map); diff --git a/unittest/obproxy/test_white_list_processor.cpp b/unittest/obproxy/test_white_list_processor.cpp index aec7a728153798e47342fbf7816d0a66ee90bc4f..564247a3bb89755fd70b510b91bdcc71c80aba3b 100644 --- a/unittest/obproxy/test_white_list_processor.cpp +++ b/unittest/obproxy/test_white_list_processor.cpp @@ -53,19 +53,33 @@ TEST_F(TestWhiteListProcessor, test_ip_net) char ip2[32] = "127.0.0.3"; char ip3[32] = "127.0.0.4"; char ip4[32] = "127.0.0.5"; - ASSERT_EQ(true, white_list_processor_.can_ip_pass(cluster_name, tenant_name, user_name, ip1)); - ASSERT_EQ(true, white_list_processor_.can_ip_pass(cluster_name, tenant_name, user_name, ip2)); - ASSERT_EQ(false, white_list_processor_.can_ip_pass(cluster_name, tenant_name, user_name, ip3)); - ASSERT_EQ(false, white_list_processor_.can_ip_pass(cluster_name, tenant_name, user_name, ip4)); + ObAddr addr1(ObAddr::VER::IPV4, ip1, 0); + ObAddr addr2(ObAddr::VER::IPV4, ip2, 0); + ObAddr addr3(ObAddr::VER::IPV4, ip3, 0); + ObAddr addr4(ObAddr::VER::IPV4, ip4, 0); + struct sockaddr_storage ss = addr1.get_sockaddr(); + ASSERT_EQ(true, white_list_processor_.can_ip_pass(cluster_name, tenant_name, user_name, *reinterpret_cast(&ss))); + ss = addr2.get_sockaddr(); + ASSERT_EQ(true, white_list_processor_.can_ip_pass(cluster_name, tenant_name, user_name, *reinterpret_cast(&ss))); + ss = addr3.get_sockaddr(); + ASSERT_EQ(false, white_list_processor_.can_ip_pass(cluster_name, tenant_name, user_name, *reinterpret_cast(&ss))); + ss = addr4.get_sockaddr(); + ASSERT_EQ(false, white_list_processor_.can_ip_pass(cluster_name, tenant_name, user_name, *reinterpret_cast(&ss))); ObString cluster_name2 = "cluster2"; ObString tenant_name2 = "tenant2"; ObString user_name2 = "user2"; char ip5[32] = "127.0.0.1"; char ip6[32] = "127.0.0.2"; char ip7[32] = "127.0.0.3"; - ASSERT_EQ(true, white_list_processor_.can_ip_pass(cluster_name2, tenant_name2, user_name2, ip5)); - ASSERT_EQ(false, white_list_processor_.can_ip_pass(cluster_name2, tenant_name2, user_name2, ip6)); - ASSERT_EQ(true, white_list_processor_.can_ip_pass(cluster_name2, tenant_name2, user_name2, ip7)); + ObAddr addr5(ObAddr::VER::IPV4, ip5, 0); + ObAddr addr6(ObAddr::VER::IPV4, ip6, 0); + ObAddr addr7(ObAddr::VER::IPV4, ip7, 0); + ss = addr5.get_sockaddr(); + ASSERT_EQ(true, white_list_processor_.can_ip_pass(cluster_name2, tenant_name2, user_name2, *reinterpret_cast(&ss))); + ss = addr6.get_sockaddr(); + ASSERT_EQ(false, white_list_processor_.can_ip_pass(cluster_name2, tenant_name2, user_name2, *reinterpret_cast(&ss))); + ss = addr7.get_sockaddr(); + ASSERT_EQ(true, white_list_processor_.can_ip_pass(cluster_name2, tenant_name2, user_name2, *reinterpret_cast(&ss))); } int main(int argc, char **argv)